Snap for 6445658 from fff55c6819a56966d6e1463baabe2512ee71553f to rvc-d1-release

Change-Id: I1218e1c1265c7056ae3170ad2f4ba182918bc11d
diff --git a/.gitignore b/.gitignore
index 3255d0e..bd7c8f5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -49,6 +49,7 @@
 /third_party/spirv-headers/src
 /third_party/spirv-tools/src
 /third_party/SwiftShader
+/third_party/VulkanMemoryAllocator
 /third_party/VK-GL-CTS/src
 /third_party/vulkan-headers/src
 /third_party/vulkan-loader/src
diff --git a/Android.bp b/Android.bp
index 5435d31..5178980 100644
--- a/Android.bp
+++ b/Android.bp
@@ -425,41 +425,17 @@
     },
 }
 cc_defaults {
-    name: "angle_vulkan_headers",
+    name: "angle_vulkan_entry_points",
     stl: "libc++_static",
-    local_include_dirs: [
-        "",
-        "third_party/vulkan-headers/src/include/",
+    shared_libs: [
+        "libvulkan",
     ],
     sdk_version: "28",
     cflags: [
-        "-DANDROID",
-        "-DANDROID_NDK_VERSION_ROLL=r20_1",
-        "-DCR_CLANG_REVISION=\"n344329-9284abd0-6\"",
-        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
-        "-DHAVE_SYS_UIO_H",
-        "-DNDEBUG",
-        "-DNVALGRIND",
-        "-DVK_USE_PLATFORM_ANDROID_KHR",
-        "-D_FORTIFY_SOURCE=2",
-        "-D_GNU_SOURCE",
-        "-D__STDC_CONSTANT_MACROS",
-        "-D__STDC_FORMAT_MACROS",
-        "-Wno-bitwise-conditional-parentheses",
-        "-Wno-builtin-assume-aligned-alignment",
-        "-Wno-builtin-macro-redefined",
-        "-Wno-c++11-narrowing",
-        "-Wno-deprecated-copy",
-        "-Wno-final-dtor-non-final-class",
-        "-Wno-ignored-pragma-optimize",
-        "-Wno-implicit-fallthrough",
-        "-Wno-implicit-int-float-conversion",
-        "-Wno-missing-field-initializers",
-        "-Wno-non-c-typedef-for-linkage",
-        "-Wno-undefined-var-template",
         "-Wno-unknown-warning-option",
-        "-Wno-unneeded-internal-declaration",
-        "-Wno-unused-parameter",
+    ],
+    defaults: [
+        "angle_volk",
     ],
 }
 cc_defaults {
@@ -508,20 +484,122 @@
     ],
 }
 cc_defaults {
-    name: "angle_vulkan_entry_points",
+    name: "angle_vulkan_memory_allocator",
     stl: "libc++_static",
-    shared_libs: [
-        "libvulkan",
+    local_include_dirs: [
+        "",
+        "src/third_party/volk/",
+        "third_party/VulkanMemoryAllocator/src/",
+        "third_party/vulkan-headers/src/include/",
     ],
     sdk_version: "28",
     cflags: [
+        "-DANDROID",
+        "-DANDROID_NDK_VERSION_ROLL=r20_1",
+        "-DCR_CLANG_REVISION=\"n344329-9284abd0-6\"",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DHAVE_SYS_UIO_H",
+        "-DNDEBUG",
+        "-DNVALGRIND",
+        "-DVK_USE_PLATFORM_ANDROID_KHR",
+        "-DVMA_IMPLEMENTATION",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-Wno-bitwise-conditional-parentheses",
+        "-Wno-builtin-assume-aligned-alignment",
+        "-Wno-builtin-macro-redefined",
+        "-Wno-c++11-narrowing",
+        "-Wno-deprecated-copy",
+        "-Wno-final-dtor-non-final-class",
+        "-Wno-ignored-pragma-optimize",
+        "-Wno-implicit-fallthrough",
+        "-Wno-implicit-int-float-conversion",
+        "-Wno-missing-field-initializers",
+        "-Wno-non-c-typedef-for-linkage",
+        "-Wno-undefined-var-template",
         "-Wno-unknown-warning-option",
+        "-Wno-unneeded-internal-declaration",
+        "-Wno-unused-parameter",
+        "-Wno-unused-variable",
     ],
     defaults: [
         "angle_volk",
-        "angle_vulkan_headers",
     ],
 }
+cc_defaults {
+    name: "angle_vk_mem_alloc_wrapper",
+    stl: "libc++_static",
+    local_include_dirs: [
+        "include/",
+        "src/",
+        "src/third_party/volk/",
+        "third_party/VulkanMemoryAllocator/src/",
+        "third_party/vulkan-headers/src/include/",
+    ],
+    srcs: [
+        "src/libANGLE/renderer/vulkan/vk_mem_alloc_wrapper.cpp",
+    ],
+    sdk_version: "28",
+    cflags: [
+        "-DANDROID",
+        "-DANDROID_NDK_VERSION_ROLL=r20_1",
+        "-DCR_CLANG_REVISION=\"n344329-9284abd0-6\"",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DHAVE_SYS_UIO_H",
+        "-DNDEBUG",
+        "-DNVALGRIND",
+        "-DVK_USE_PLATFORM_ANDROID_KHR",
+        "-DVMA_IMPLEMENTATION",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-Wno-bitwise-conditional-parentheses",
+        "-Wno-builtin-assume-aligned-alignment",
+        "-Wno-builtin-macro-redefined",
+        "-Wno-c++11-narrowing",
+        "-Wno-deprecated-copy",
+        "-Wno-extra-semi-stmt",
+        "-Wno-final-dtor-non-final-class",
+        "-Wno-ignored-pragma-optimize",
+        "-Wno-implicit-fallthrough",
+        "-Wno-implicit-int-float-conversion",
+        "-Wno-missing-field-initializers",
+        "-Wno-non-c-typedef-for-linkage",
+        "-Wno-undefined-var-template",
+        "-Wno-unknown-warning-option",
+        "-Wno-unneeded-internal-declaration",
+        "-Wno-unused-parameter",
+        "-Wno-unused-variable",
+    ],
+    defaults: [
+        "angle_vulkan_memory_allocator",
+    ],
+    arch: {
+        arm64: {
+            cflags: [
+                "-DANGLE_IS_64_BIT_CPU",
+            ],
+        },
+        x86_64: {
+            cflags: [
+                "-DANGLE_IS_64_BIT_CPU",
+            ],
+        },
+        x86: {
+            cflags: [
+                "-DANGLE_IS_32_BIT_CPU",
+            ],
+        },
+        arm: {
+            cflags: [
+                "-DANGLE_IS_32_BIT_CPU",
+            ],
+        },
+    },
+}
 cc_library_static {
     generated_headers: [
         "angle_spvtools_core_enums_unified1",
@@ -626,121 +704,130 @@
     ],
 }
 cc_genrule {
+    name: "angle_spvtools_vendor_tables_spv-amd-shader-trinary-minmax",
     tool_files: [
         "third_party/spirv-tools/src/utils/generate_grammar_tables.py",
     ],
+    cmd: "$(location) --extinst-vendor-grammar $(location third_party/spirv-tools/src/source/extinst.spv-amd-shader-trinary-minmax.grammar.json) --vendor-insts-output $(location spv-amd-shader-trinary-minmax.insts.inc) --vendor-operand-kind-prefix ...nil...",
     srcs: [
         "third_party/spirv-tools/src/source/extinst.spv-amd-shader-trinary-minmax.grammar.json",
     ],
-    cmd: "$(location) --extinst-vendor-grammar $(location third_party/spirv-tools/src/source/extinst.spv-amd-shader-trinary-minmax.grammar.json) --vendor-insts-output $(location spv-amd-shader-trinary-minmax.insts.inc) --vendor-operand-kind-prefix ...nil...",
-    name: "angle_spvtools_vendor_tables_spv-amd-shader-trinary-minmax",
+    sdk_version: "28",
     out: [
         "spv-amd-shader-trinary-minmax.insts.inc",
     ],
 }
 cc_genrule {
+    name: "angle_spvtools_vendor_tables_spv-amd-shader-explicit-vertex-parameter",
     tool_files: [
         "third_party/spirv-tools/src/utils/generate_grammar_tables.py",
     ],
+    cmd: "$(location) --extinst-vendor-grammar $(location third_party/spirv-tools/src/source/extinst.spv-amd-shader-explicit-vertex-parameter.grammar.json) --vendor-insts-output $(location spv-amd-shader-explicit-vertex-parameter.insts.inc) --vendor-operand-kind-prefix ...nil...",
     srcs: [
         "third_party/spirv-tools/src/source/extinst.spv-amd-shader-explicit-vertex-parameter.grammar.json",
     ],
-    cmd: "$(location) --extinst-vendor-grammar $(location third_party/spirv-tools/src/source/extinst.spv-amd-shader-explicit-vertex-parameter.grammar.json) --vendor-insts-output $(location spv-amd-shader-explicit-vertex-parameter.insts.inc) --vendor-operand-kind-prefix ...nil...",
-    name: "angle_spvtools_vendor_tables_spv-amd-shader-explicit-vertex-parameter",
+    sdk_version: "28",
     out: [
         "spv-amd-shader-explicit-vertex-parameter.insts.inc",
     ],
 }
 cc_genrule {
+    name: "angle_spvtools_vendor_tables_spv-amd-shader-ballot",
     tool_files: [
         "third_party/spirv-tools/src/utils/generate_grammar_tables.py",
     ],
+    cmd: "$(location) --extinst-vendor-grammar $(location third_party/spirv-tools/src/source/extinst.spv-amd-shader-ballot.grammar.json) --vendor-insts-output $(location spv-amd-shader-ballot.insts.inc) --vendor-operand-kind-prefix ...nil...",
     srcs: [
         "third_party/spirv-tools/src/source/extinst.spv-amd-shader-ballot.grammar.json",
     ],
-    cmd: "$(location) --extinst-vendor-grammar $(location third_party/spirv-tools/src/source/extinst.spv-amd-shader-ballot.grammar.json) --vendor-insts-output $(location spv-amd-shader-ballot.insts.inc) --vendor-operand-kind-prefix ...nil...",
-    name: "angle_spvtools_vendor_tables_spv-amd-shader-ballot",
+    sdk_version: "28",
     out: [
         "spv-amd-shader-ballot.insts.inc",
     ],
 }
 cc_genrule {
+    name: "angle_spvtools_vendor_tables_spv-amd-gcn-shader",
     tool_files: [
         "third_party/spirv-tools/src/utils/generate_grammar_tables.py",
     ],
+    cmd: "$(location) --extinst-vendor-grammar $(location third_party/spirv-tools/src/source/extinst.spv-amd-gcn-shader.grammar.json) --vendor-insts-output $(location spv-amd-gcn-shader.insts.inc) --vendor-operand-kind-prefix ...nil...",
     srcs: [
         "third_party/spirv-tools/src/source/extinst.spv-amd-gcn-shader.grammar.json",
     ],
-    cmd: "$(location) --extinst-vendor-grammar $(location third_party/spirv-tools/src/source/extinst.spv-amd-gcn-shader.grammar.json) --vendor-insts-output $(location spv-amd-gcn-shader.insts.inc) --vendor-operand-kind-prefix ...nil...",
-    name: "angle_spvtools_vendor_tables_spv-amd-gcn-shader",
+    sdk_version: "28",
     out: [
         "spv-amd-gcn-shader.insts.inc",
     ],
 }
 cc_genrule {
+    name: "angle_spvtools_vendor_tables_opencl.debuginfo.100",
     tool_files: [
         "third_party/spirv-tools/src/utils/generate_grammar_tables.py",
     ],
+    cmd: "$(location) --extinst-vendor-grammar $(location third_party/spirv-tools/src/source/extinst.opencl.debuginfo.100.grammar.json) --vendor-insts-output $(location opencl.debuginfo.100.insts.inc) --vendor-operand-kind-prefix CLDEBUG100_",
     srcs: [
         "third_party/spirv-tools/src/source/extinst.opencl.debuginfo.100.grammar.json",
     ],
-    cmd: "$(location) --extinst-vendor-grammar $(location third_party/spirv-tools/src/source/extinst.opencl.debuginfo.100.grammar.json) --vendor-insts-output $(location opencl.debuginfo.100.insts.inc) --vendor-operand-kind-prefix CLDEBUG100_",
-    name: "angle_spvtools_vendor_tables_opencl.debuginfo.100",
+    sdk_version: "28",
     out: [
         "opencl.debuginfo.100.insts.inc",
     ],
 }
 cc_genrule {
+    name: "angle_spvtools_vendor_tables_debuginfo",
     tool_files: [
         "third_party/spirv-tools/src/utils/generate_grammar_tables.py",
     ],
+    cmd: "$(location) --extinst-vendor-grammar $(location third_party/spirv-tools/src/source/extinst.debuginfo.grammar.json) --vendor-insts-output $(location debuginfo.insts.inc) --vendor-operand-kind-prefix ...nil...",
     srcs: [
         "third_party/spirv-tools/src/source/extinst.debuginfo.grammar.json",
     ],
-    cmd: "$(location) --extinst-vendor-grammar $(location third_party/spirv-tools/src/source/extinst.debuginfo.grammar.json) --vendor-insts-output $(location debuginfo.insts.inc) --vendor-operand-kind-prefix ...nil...",
-    name: "angle_spvtools_vendor_tables_debuginfo",
+    sdk_version: "28",
     out: [
         "debuginfo.insts.inc",
     ],
 }
 cc_genrule {
+    name: "angle_spvtools_opencl_tables_opencl1-0",
     tool_files: [
         "third_party/spirv-tools/src/utils/generate_grammar_tables.py",
     ],
+    cmd: "$(location) --spirv-core-grammar $(location third_party/spirv-headers/src/include/spirv/1.0/spirv.core.grammar.json) --extinst-debuginfo-grammar $(location third_party/spirv-tools/src/source/extinst.debuginfo.grammar.json) --extinst-cldebuginfo100-grammar $(location third_party/spirv-tools/src/source/extinst.opencl.debuginfo.100.grammar.json) --extinst-opencl-grammar $(location third_party/spirv-headers/src/include/spirv/1.0/extinst.opencl.std.100.grammar.json) --opencl-insts-output $(location opencl.std.insts.inc)",
     srcs: [
         "third_party/spirv-headers/src/include/spirv/1.0/extinst.opencl.std.100.grammar.json",
         "third_party/spirv-headers/src/include/spirv/1.0/spirv.core.grammar.json",
         "third_party/spirv-tools/src/source/extinst.debuginfo.grammar.json",
         "third_party/spirv-tools/src/source/extinst.opencl.debuginfo.100.grammar.json",
     ],
-    cmd: "$(location) --spirv-core-grammar $(location third_party/spirv-headers/src/include/spirv/1.0/spirv.core.grammar.json) --extinst-debuginfo-grammar $(location third_party/spirv-tools/src/source/extinst.debuginfo.grammar.json) --extinst-cldebuginfo100-grammar $(location third_party/spirv-tools/src/source/extinst.opencl.debuginfo.100.grammar.json) --extinst-opencl-grammar $(location third_party/spirv-headers/src/include/spirv/1.0/extinst.opencl.std.100.grammar.json) --opencl-insts-output $(location opencl.std.insts.inc)",
-    name: "angle_spvtools_opencl_tables_opencl1-0",
+    sdk_version: "28",
     out: [
         "opencl.std.insts.inc",
     ],
 }
 cc_genrule {
+    name: "angle_spvtools_language_header_debuginfo",
     tool_files: [
         "third_party/spirv-tools/src/utils/generate_language_headers.py",
     ],
+    cmd: "$(location) --extinst-grammar $(location third_party/spirv-tools/src/source/extinst.debuginfo.grammar.json) --extinst-output-path $(location DebugInfo.h)",
     srcs: [
         "third_party/spirv-tools/src/source/extinst.debuginfo.grammar.json",
     ],
-    cmd: "$(location) --extinst-grammar $(location third_party/spirv-tools/src/source/extinst.debuginfo.grammar.json) --extinst-output-path $(location DebugInfo.h)",
-    name: "angle_spvtools_language_header_debuginfo",
+    sdk_version: "28",
     out: [
         "DebugInfo.h",
     ],
 }
 cc_genrule {
+    name: "angle_spvtools_language_header_cldebuginfo100",
     tool_files: [
         "third_party/spirv-tools/src/utils/generate_language_headers.py",
     ],
+    cmd: "$(location) --extinst-grammar $(location third_party/spirv-tools/src/source/extinst.opencl.debuginfo.100.grammar.json) --extinst-output-path $(location OpenCLDebugInfo100.h)",
     srcs: [
         "third_party/spirv-tools/src/source/extinst.opencl.debuginfo.100.grammar.json",
     ],
-    cmd: "$(location) --extinst-grammar $(location third_party/spirv-tools/src/source/extinst.opencl.debuginfo.100.grammar.json) --extinst-output-path $(location OpenCLDebugInfo100.h)",
-    name: "angle_spvtools_language_header_cldebuginfo100",
+    sdk_version: "28",
     out: [
         "OpenCLDebugInfo100.h",
     ],
@@ -783,61 +870,65 @@
     ],
 }
 cc_genrule {
+    name: "angle_spvtools_glsl_tables_glsl1-0",
     tool_files: [
         "third_party/spirv-tools/src/utils/generate_grammar_tables.py",
     ],
+    cmd: "$(location) --spirv-core-grammar $(location third_party/spirv-headers/src/include/spirv/1.0/spirv.core.grammar.json) --extinst-debuginfo-grammar $(location third_party/spirv-tools/src/source/extinst.debuginfo.grammar.json) --extinst-cldebuginfo100-grammar $(location third_party/spirv-tools/src/source/extinst.opencl.debuginfo.100.grammar.json) --extinst-glsl-grammar $(location third_party/spirv-headers/src/include/spirv/1.0/extinst.glsl.std.450.grammar.json) --glsl-insts-output $(location glsl.std.450.insts.inc)",
     srcs: [
         "third_party/spirv-headers/src/include/spirv/1.0/extinst.glsl.std.450.grammar.json",
         "third_party/spirv-headers/src/include/spirv/1.0/spirv.core.grammar.json",
         "third_party/spirv-tools/src/source/extinst.debuginfo.grammar.json",
         "third_party/spirv-tools/src/source/extinst.opencl.debuginfo.100.grammar.json",
     ],
-    cmd: "$(location) --spirv-core-grammar $(location third_party/spirv-headers/src/include/spirv/1.0/spirv.core.grammar.json) --extinst-debuginfo-grammar $(location third_party/spirv-tools/src/source/extinst.debuginfo.grammar.json) --extinst-cldebuginfo100-grammar $(location third_party/spirv-tools/src/source/extinst.opencl.debuginfo.100.grammar.json) --extinst-glsl-grammar $(location third_party/spirv-headers/src/include/spirv/1.0/extinst.glsl.std.450.grammar.json) --glsl-insts-output $(location glsl.std.450.insts.inc)",
-    name: "angle_spvtools_glsl_tables_glsl1-0",
+    sdk_version: "28",
     out: [
         "glsl.std.450.insts.inc",
     ],
 }
 cc_genrule {
+    name: "angle_spvtools_generators_inc",
     tool_files: [
         "third_party/spirv-tools/src/utils/generate_registry_tables.py",
     ],
+    cmd: "$(location) --xml $(location third_party/spirv-headers/src/include/spirv/spir-v.xml) --generator $(location generators.inc)",
     srcs: [
         "third_party/spirv-headers/src/include/spirv/spir-v.xml",
     ],
-    cmd: "$(location) --xml $(location third_party/spirv-headers/src/include/spirv/spir-v.xml) --generator $(location generators.inc)",
-    name: "angle_spvtools_generators_inc",
+    sdk_version: "28",
     out: [
         "generators.inc",
     ],
 }
 cc_genrule {
+    name: "angle_spvtools_core_tables_unified1",
     tool_files: [
         "third_party/spirv-tools/src/utils/generate_grammar_tables.py",
     ],
+    cmd: "$(location) --spirv-core-grammar $(location third_party/spirv-headers/src/include/spirv/unified1/spirv.core.grammar.json) --core-insts-output $(location core.insts-unified1.inc) --extinst-debuginfo-grammar $(location third_party/spirv-tools/src/source/extinst.debuginfo.grammar.json) --extinst-cldebuginfo100-grammar $(location third_party/spirv-tools/src/source/extinst.opencl.debuginfo.100.grammar.json) --operand-kinds-output $(location operand.kinds-unified1.inc)",
     srcs: [
         "third_party/spirv-headers/src/include/spirv/unified1/spirv.core.grammar.json",
         "third_party/spirv-tools/src/source/extinst.debuginfo.grammar.json",
         "third_party/spirv-tools/src/source/extinst.opencl.debuginfo.100.grammar.json",
     ],
-    cmd: "$(location) --spirv-core-grammar $(location third_party/spirv-headers/src/include/spirv/unified1/spirv.core.grammar.json) --core-insts-output $(location core.insts-unified1.inc) --extinst-debuginfo-grammar $(location third_party/spirv-tools/src/source/extinst.debuginfo.grammar.json) --extinst-cldebuginfo100-grammar $(location third_party/spirv-tools/src/source/extinst.opencl.debuginfo.100.grammar.json) --operand-kinds-output $(location operand.kinds-unified1.inc)",
-    name: "angle_spvtools_core_tables_unified1",
+    sdk_version: "28",
     out: [
         "core.insts-unified1.inc",
         "operand.kinds-unified1.inc",
     ],
 }
 cc_genrule {
+    name: "angle_spvtools_core_enums_unified1",
     tool_files: [
         "third_party/spirv-tools/src/utils/generate_grammar_tables.py",
     ],
+    cmd: "$(location) --spirv-core-grammar $(location third_party/spirv-headers/src/include/spirv/unified1/spirv.core.grammar.json) --extinst-debuginfo-grammar $(location third_party/spirv-tools/src/source/extinst.debuginfo.grammar.json) --extinst-cldebuginfo100-grammar $(location third_party/spirv-tools/src/source/extinst.opencl.debuginfo.100.grammar.json) --extension-enum-output $(location extension_enum.inc) --enum-string-mapping-output $(location enum_string_mapping.inc)",
     srcs: [
         "third_party/spirv-headers/src/include/spirv/unified1/spirv.core.grammar.json",
         "third_party/spirv-tools/src/source/extinst.debuginfo.grammar.json",
         "third_party/spirv-tools/src/source/extinst.opencl.debuginfo.100.grammar.json",
     ],
-    cmd: "$(location) --spirv-core-grammar $(location third_party/spirv-headers/src/include/spirv/unified1/spirv.core.grammar.json) --extinst-debuginfo-grammar $(location third_party/spirv-tools/src/source/extinst.debuginfo.grammar.json) --extinst-cldebuginfo100-grammar $(location third_party/spirv-tools/src/source/extinst.opencl.debuginfo.100.grammar.json) --extension-enum-output $(location extension_enum.inc) --enum-string-mapping-output $(location enum_string_mapping.inc)",
-    name: "angle_spvtools_core_enums_unified1",
+    sdk_version: "28",
     out: [
         "enum_string_mapping.inc",
         "extension_enum.inc",
@@ -1464,6 +1555,7 @@
         "src/libANGLE/renderer/vulkan/MemoryObjectVk.cpp",
         "src/libANGLE/renderer/vulkan/OverlayVk.cpp",
         "src/libANGLE/renderer/vulkan/PersistentCommandPool.cpp",
+        "src/libANGLE/renderer/vulkan/ProgramExecutableVk.cpp",
         "src/libANGLE/renderer/vulkan/ProgramPipelineVk.cpp",
         "src/libANGLE/renderer/vulkan/ProgramVk.cpp",
         "src/libANGLE/renderer/vulkan/QueryVk.cpp",
@@ -1533,6 +1625,7 @@
     defaults: [
         "angle_glslang_wrapper",
         "angle_libANGLE_headers",
+        "angle_vk_mem_alloc_wrapper",
         "angle_vulkan_entry_points",
         "angle_vulkan_headers",
     ],
@@ -1725,6 +1818,7 @@
         "src/compiler/translator/tree_ops/ClampPointSize.cpp",
         "src/compiler/translator/tree_ops/DeclareAndInitBuiltinsForInstancedMultiview.cpp",
         "src/compiler/translator/tree_ops/DeferGlobalInitializers.cpp",
+        "src/compiler/translator/tree_ops/EarlyFragmentTestsOptimization.cpp",
         "src/compiler/translator/tree_ops/EmulateGLFragColorBroadcast.cpp",
         "src/compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.cpp",
         "src/compiler/translator/tree_ops/EmulatePrecision.cpp",
@@ -2126,42 +2220,23 @@
         },
     },
 }
-cc_library_static {
-    generated_headers: [
-        "angle_commit_id",
-    ],
-    name: "angle_gpu_info_util",
+cc_defaults {
+    name: "angle_vulkan_headers",
     stl: "libc++_static",
-    static_libs: [
-        "angle_common",
-    ],
-    shared_libs: [
-        "liblog",
-    ],
     local_include_dirs: [
         "",
-        "include/",
-        "src/",
-        "src/common/third_party/base/",
-    ],
-    srcs: [
-        "src/gpu_info_util/SystemInfo.cpp",
-        "src/gpu_info_util/SystemInfo_android.cpp",
-        "src/gpu_info_util/SystemInfo_vulkan.cpp",
+        "third_party/vulkan-headers/src/include/",
     ],
     sdk_version: "28",
     cflags: [
         "-DANDROID",
         "-DANDROID_NDK_VERSION_ROLL=r20_1",
-        "-DANGLE_ENABLE_OPENGL",
-        "-DANGLE_ENABLE_OPENGL_NULL",
-        "-DANGLE_ENABLE_VULKAN",
-        "-DANGLE_USE_CUSTOM_VULKAN_CMD_BUFFERS=1",
         "-DCR_CLANG_REVISION=\"n344329-9284abd0-6\"",
         "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
         "-DHAVE_SYS_UIO_H",
         "-DNDEBUG",
         "-DNVALGRIND",
+        "-DVK_USE_PLATFORM_ANDROID_KHR",
         "-D_FORTIFY_SOURCE=2",
         "-D_GNU_SOURCE",
         "-D__STDC_CONSTANT_MACROS",
@@ -2182,6 +2257,68 @@
         "-Wno-unneeded-internal-declaration",
         "-Wno-unused-parameter",
     ],
+}
+cc_library_static {
+    generated_headers: [
+        "angle_commit_id",
+    ],
+    name: "angle_gpu_info_util",
+    stl: "libc++_static",
+    static_libs: [
+        "angle_common",
+    ],
+    shared_libs: [
+        "liblog",
+    ],
+    local_include_dirs: [
+        "",
+        "include/",
+        "src/",
+        "src/common/third_party/base/",
+        "third_party/vulkan-headers/src/include/",
+    ],
+    srcs: [
+        "src/gpu_info_util/SystemInfo.cpp",
+        "src/gpu_info_util/SystemInfo_android.cpp",
+        "src/gpu_info_util/SystemInfo_vulkan.cpp",
+    ],
+    sdk_version: "28",
+    cflags: [
+        "-DANDROID",
+        "-DANDROID_NDK_VERSION_ROLL=r20_1",
+        "-DANGLE_ENABLE_OPENGL",
+        "-DANGLE_ENABLE_OPENGL_NULL",
+        "-DANGLE_ENABLE_VULKAN",
+        "-DANGLE_USE_CUSTOM_VULKAN_CMD_BUFFERS=1",
+        "-DCR_CLANG_REVISION=\"n344329-9284abd0-6\"",
+        "-DDYNAMIC_ANNOTATIONS_ENABLED=0",
+        "-DHAVE_SYS_UIO_H",
+        "-DNDEBUG",
+        "-DNVALGRIND",
+        "-DVK_USE_PLATFORM_ANDROID_KHR",
+        "-D_FORTIFY_SOURCE=2",
+        "-D_GNU_SOURCE",
+        "-D__STDC_CONSTANT_MACROS",
+        "-D__STDC_FORMAT_MACROS",
+        "-Wno-bitwise-conditional-parentheses",
+        "-Wno-builtin-assume-aligned-alignment",
+        "-Wno-builtin-macro-redefined",
+        "-Wno-c++11-narrowing",
+        "-Wno-deprecated-copy",
+        "-Wno-final-dtor-non-final-class",
+        "-Wno-ignored-pragma-optimize",
+        "-Wno-implicit-fallthrough",
+        "-Wno-implicit-int-float-conversion",
+        "-Wno-missing-field-initializers",
+        "-Wno-non-c-typedef-for-linkage",
+        "-Wno-undefined-var-template",
+        "-Wno-unknown-warning-option",
+        "-Wno-unneeded-internal-declaration",
+        "-Wno-unused-parameter",
+    ],
+    defaults: [
+        "angle_vulkan_headers",
+    ],
     arch: {
         arm64: {
             cflags: [
@@ -2487,7 +2624,6 @@
         "src/libANGLE/GLES1Renderer.cpp",
         "src/libANGLE/GLES1State.cpp",
         "src/libANGLE/HandleAllocator.cpp",
-        "src/libANGLE/HandleRangeAllocator.cpp",
         "src/libANGLE/Image.cpp",
         "src/libANGLE/ImageIndex.cpp",
         "src/libANGLE/IndexRangeCache.cpp",
@@ -2495,9 +2631,9 @@
         "src/libANGLE/MemoryObject.cpp",
         "src/libANGLE/MemoryProgramCache.cpp",
         "src/libANGLE/Observer.cpp",
-        "src/libANGLE/Path.cpp",
         "src/libANGLE/Platform.cpp",
         "src/libANGLE/Program.cpp",
+        "src/libANGLE/ProgramExecutable.cpp",
         "src/libANGLE/ProgramLinkedResources.cpp",
         "src/libANGLE/ProgramPipeline.cpp",
         "src/libANGLE/Query.cpp",
@@ -2529,6 +2665,7 @@
         "src/libANGLE/renderer/DeviceImpl.cpp",
         "src/libANGLE/renderer/DisplayImpl.cpp",
         "src/libANGLE/renderer/Format_table_autogen.cpp",
+        "src/libANGLE/renderer/ProgramPipelineImpl.cpp",
         "src/libANGLE/renderer/QueryImpl.cpp",
         "src/libANGLE/renderer/ShaderImpl.cpp",
         "src/libANGLE/renderer/SurfaceImpl.cpp",
@@ -2546,7 +2683,6 @@
         "src/libANGLE/renderer/gl/FunctionsGL.cpp",
         "src/libANGLE/renderer/gl/ImageGL.cpp",
         "src/libANGLE/renderer/gl/MemoryObjectGL.cpp",
-        "src/libANGLE/renderer/gl/PathGL.cpp",
         "src/libANGLE/renderer/gl/ProgramGL.cpp",
         "src/libANGLE/renderer/gl/ProgramPipelineGL.cpp",
         "src/libANGLE/renderer/gl/QueryGL.cpp",
@@ -2834,11 +2970,12 @@
     },
 }
 cc_genrule {
+    name: "angle_commit_id",
     tool_files: [
         "src/commit_id.py",
     ],
     cmd: "$(location) gen $(location commit.h)",
-    name: "angle_commit_id",
+    sdk_version: "28",
     out: [
         "commit.h",
     ],
@@ -3047,16 +3184,19 @@
     srcs: [
         ":ANGLE_srcs",
     ],
-    sdk_version: "system_current",
+    plugins: [
+        "java_api_finder",
+    ],
+    owner: "google",
     name: "ANGLE_java_defaults",
+    use_embedded_native_libs: true,
+    min_sdk_version: "28",
+    sdk_version: "system_current",
     aaptflags: [
         "--extra-packages com.android.angle.common",
         "-0 .json",
     ],
-    use_embedded_native_libs: true,
-    owner: "google",
     compile_multilib: "both",
-    min_sdk_version: "28",
     privileged: true,
 }
 android_library {
diff --git a/BUILD.gn b/BUILD.gn
index ad7675f..ee9bd39 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -331,6 +331,7 @@
 
   if (is_android || is_fuchsia) {
     sources += libangle_gpu_info_util_vulkan_sources
+    deps += [ "$angle_root/third_party/vulkan-headers/src:vulkan_headers" ]
   }
 
   if (is_android) {
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index a30eeae..ac2bed3 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -164,6 +164,7 @@
  Mohan Maiya
  Peter Mowry
  Sangwon Park
+ Saurabh Badenkal
 
 Arm Ltd.
  Fei Yang
diff --git a/DEPS b/DEPS
index d7c54e2..62a49e9 100644
--- a/DEPS
+++ b/DEPS
@@ -25,7 +25,7 @@
   'vk_gl_cts_revision': 'a6b249819f7177821d4b7eefff36af07fef71825',
 
   # Current revision of glslang, the Khronos SPIRV compiler.
-  'glslang_revision': '4b2483ee88ab2ce904f6bac27c7796823c45564c',
+  'glslang_revision': 'c9b28b9f3388c607ea5506f5e6197b7150238ad3',
 
   # Current revision of googletest.
   # Note: this dep cannot be auto-rolled b/c of nesting.
@@ -46,19 +46,19 @@
   'spirv_headers_revision': 'f8bf11a0253a32375c32cad92c841237b96696c0',
 
   # Current revision of SPIRV-Tools for Vulkan.
-  'spirv_tools_revision': '60104cd97446877dad8ed1010a635218937a2f18',
+  'spirv_tools_revision': '67f4838659f475d618c120e13d1a196d7e00ba4b',
 
   # Current revision of Khronos Vulkan-Headers.
-  'vulkan_headers_revision': '74556a131735598a5ae7a94ec5500a9d9f908b3a',
+  'vulkan_headers_revision': '382bf3de06fc8c8961055afc37957fe65846c33b',
 
   # Current revision of Khronos Vulkan-Loader.
-  'vulkan_loader_revision': '64c36933d4f28b1609a087a94baec56bd6338215',
+  'vulkan_loader_revision': '4fb0e0374a3912263606d9ed0243bbef22e23597',
 
   # Current revision of Khronos Vulkan-Tools.
-  'vulkan_tools_revision': '94ed4c384c3425963b459a735045706e5f83f01b',
+  'vulkan_tools_revision': '84463fe2902f4b50b54abe053684e6fcb7a60c4f',
 
   # Current revision of Khronos Vulkan-ValidationLayers.
-  'vulkan_validation_revision': 'caeb15a056a0e6af7f9f99d089e6db460f1050d7',
+  'vulkan_validation_revision': '36d7cca6fdc9ed86b01208bfb13721fdffb30af1',
 
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
@@ -89,6 +89,10 @@
     'condition': 'not build_with_chromium',
   },
 
+  'third_party/VulkanMemoryAllocator': {
+    'url': '{chromium_git}/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator@ec44c3121c73ae243fe59acfcc0ce1ba19e43947',
+  },
+
   'third_party/VK-GL-CTS/src': {
     'url': '{chromium_git}/external/github.com/KhronosGroup/VK-GL-CTS@{vk_gl_cts_revision}',
   },
@@ -182,7 +186,7 @@
   },
 
   'third_party/SwiftShader': {
-    'url': '{swiftshader_git}/SwiftShader@1c9f24263e6c39591d821a2ebb09a11e55cd957c',
+    'url': '{swiftshader_git}/SwiftShader@ceb6258ae1016ebaffb7036561e0cba14c8cc2a7',
     'condition': 'not build_with_chromium',
   },
 
diff --git a/METADATA b/METADATA
index 5d1fa6c..ee30afa 100644
--- a/METADATA
+++ b/METADATA
@@ -19,9 +19,10 @@
     value: "https://chromium.googlesource.com/angle/angle"
   }
   version: "1.0"
+  license_type: RESTRICTED
   last_upgrade_date {
     year: 2020
     month: 2
     day: 21
   }
-}
\ No newline at end of file
+}
diff --git a/OWNERS b/OWNERS
index c0c7555..df48cfa 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,5 +1,18 @@
-# See https://chromium.googlesource.com/angle/angle/+/master/doc/ContributingCode.md#selecting-reviewers for per-file owners
+# See https://chromium.googlesource.com/angle/angle/+/master/doc/ContributingCode.md#selecting-reviewers for more info
+geofflang@chromium.org
 geofflang@google.com
+jmadill@chromium.org
+jmadill@google.com
+jonahr@google.com
+syoussefi@chromium.org
+syoussefi@google.com
+ynovikov@chromium.org
+ynovikov@google.com
+
+per-file AUTHORS=*
+per-file CONTRIBUTORS=*
+per-file DEPS=*
+per-file WATCHLISTS=*
 
 # COMPONENT: Internals>GPU>ANGLE
 # TEAM: angleproject@googlegroups.com
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index bc286b8..9ffc53a 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -43,8 +43,8 @@
     if len(bugs) == 1 and bugs[0] == 'None':
         return []
 
-    projects = ['angleproject', 'chromium', 'dawn', 'fuchsia', 'skia', 'swiftshader', 'b']
-    bug_regex = re.compile(r"([a-z]+):(\d+)")
+    projects = ['angleproject:', 'chromium:', 'dawn:', 'fuchsia:', 'skia:', 'swiftshader:', 'b/']
+    bug_regex = re.compile(r"([a-z]+[:/])(\d+)")
     errors = []
     extra_help = None
 
diff --git a/WATCHLISTS b/WATCHLISTS
index f4139e5..cd81475 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -19,6 +19,8 @@
   # Please keep alphabetical
   ##############################################################################
   'WATCHLISTS': {
-    'vulkan': ['jmadill+watch@chromium.org'],
+    'vulkan': ['cclao+angleWatchVk@google.com',
+               'jmadill+watch@chromium.org',
+               'timvp+angleWatchVk@google.com'],
   },
 }
diff --git a/additional_readme_paths.json b/additional_readme_paths.json
index 4bb2934..87c0736 100644
--- a/additional_readme_paths.json
+++ b/additional_readme_paths.json
@@ -1,4 +1,5 @@
 [
     "src/common/third_party/xxhash",
-    "src/third_party/compiler"
+    "src/third_party/compiler",
+    "third_party/VulkanMemoryAllocator"
 ]
\ No newline at end of file
diff --git a/doc/ContributingCode.md b/doc/ContributingCode.md
index 7926814..4d8cf82 100644
--- a/doc/ContributingCode.md
+++ b/doc/ContributingCode.md
@@ -4,8 +4,7 @@
 
 * Whether you're writing a new feature or fixing an existing bug, it pays to get a second opinion
   before you get too far. If it's a new feature idea, post to the discussion group
-  ([angleproject][ANGLE-website]) and propose it or talk with the ANGLE team on IRC in the
-  `#ANGLEproject` channel on FreeNode.
+  ([angleproject][ANGLE-website]).
 * Not all bugs in our [bug system][anglebug.com] are assigned, but if the one you're interested in
   fixing is, send a note to the person it's assigned to and ask if they would like a patch.
 * Behavior changes and anything nontrivial (i.e. anything other than simple cleanups and style
@@ -22,28 +21,32 @@
 ### Code
 
 1. Must conform to the [ANGLE style][ANGLE-style] guidelines.
-2. Must be tested. (see the 'Testing' section below)
+2. Must be tested. (see the [Testing][Testing] section below)
 3. Should be a reasonable size to review.  Giant patches are unlikely to get reviewed quickly.
 
 [ANGLE-style]: CodingStandard.md
+[Testing]: #Testing
 
 ### Build maintenance
 
 1. If you added or removed source files:
-   * You _must_ update the build files with your changes. See `src/libGLESv2.gni` and
-   `src/compiler.gni`.
+   * You _must_ update the build files with your changes. See [`src/libGLESv2.gni`][libGLESv2.gni]
+     and [`src/compiler.gni`][compiler.gni].
 2. ANGLE's BUILD.gn script is used by [Chromium's gn build][gn-build-config]. If you change build
    files other than to add or remove source files be aware you could break the Chromium build.
    ANGLE's commit queue (CQ) will detect such breakage. Ask a project member for help with Chromium
    issues if you don't have a Chromium checkout.
 3. Some generated code is baked into the repository. If you modify the source of these files, such
-   as the translator's `glslang.l`, or one of the internal shaders in the Vulkan backend, you will
-   need to run `scripts/run_code_generation.py` and include the autogenerated files in your change.
+   as the translator's [`glslang.l`][glslang.l], or one of the internal shaders in the Vulkan
+   backend, you will need to run [`scripts/run_code_generation.py`][run_code_generation.py] and
+   include the autogenerated files in your change.
    `git cl upload` should warn you if you are missing this step.
-    * Note that updating the translator's lexer and parser (using `flex` and `bison`) is only
-      supported on Linux and Windows.
 
 [gn-build-config]: https://www.chromium.org/developers/gn-build-configuration
+[compiler.gni]: https://chromium.googlesource.com/angle/angle/+/refs/heads/master/src/compiler.gni
+[libGLESv2.gni]: https://chromium.googlesource.com/angle/angle/+/refs/heads/master/src/libGLESv2.gni
+[glslang.l]: https://chromium.googlesource.com/angle/angle/+/refs/heads/master/src/compiler/translator/glslang.l
+[run_code_generation.py]: https://chromium.googlesource.com/angle/angle/+/refs/heads/master/scripts/run_code_generation.py
 
 ### Testing
 
@@ -179,14 +182,23 @@
 
 ### Selecting reviewers
 
-When your CL is ready to review, add any of the following reviewers. They will be able to route your
-CL to additional reviewers as neccessary and answer any questions you may have about the process. All
-non-trival CLs should be reviewed by two reviewers.
+When your CL is ready to review, you can use the "Find Owners" button in
+Gerrit to select appropriate code reviewers. They will be able to route your
+CL to additional reviewers as neccessary and answer any questions you may have
+about the process.
 
-* `geofflang at chromium dot org`
-* `jmadill at chromium dot org`
-* `syoussefi at chromium dot org`
-* `ynovikov at chromium dot org`
+### Rules for submission
+
+ * At least one **Owner** must give approval.
+ * The owner must be from the **most specific** directory.
+ * At least two **Committers** must give approval for non-trival CLs.
+   For trivial CLs, a single Owner approval is sufficient.
+ * Only **Committers** may submit CLs. If you aren't a committer please ask for help submitting.
+ * Committers may submit high-priority small CLs immediately using **TBR**.
+   See [the Chromium docs][TBR] for more info.
+ * There are exceptions to these rules. Use your best judgement.
+
+[TBR]: https://chromium.googlesource.com/chromium/src/+/master/docs/code_reviews.md#tbr-to-be-reviewed
 
 ### Committer status
 
@@ -194,7 +206,13 @@
 project may request to join the `angle-committers` group.  This allows you to give `+2` on code
 reviews and land patches without assistance.  After about 6 months of regular contributions, you may
 request committer status from a core ANGLE team member via email or code review.  Chromium
-committers may ask at any time.
+committers and Googlers may ask at any time.
+
+### OWNERS files and becoming an Owner
+
+See these Chromium docs for some good guidelines: [link][Owners].
+
+### More info
 
 See also:
 
@@ -207,3 +225,4 @@
 [Contributing-code]: http://www.chromium.org/developers/contributing-code/
 [depot-tools-tutorial]: http://commondatastorage.googleapis.com/chrome-infra-docs/flat/depot_tools/docs/html/depot_tools_tutorial.html
 [Perftest-README]: ../src/tests/perf_tests/README.md
+[Owners]: https://chromium.googlesource.com/chromium/src/+/master/docs/code_reviews.md#expectations-of-owners
diff --git a/extensions/EGL_ANGLE_sync_control_rate.txt b/extensions/EGL_ANGLE_sync_control_rate.txt
new file mode 100644
index 0000000..2056ae8
--- /dev/null
+++ b/extensions/EGL_ANGLE_sync_control_rate.txt
@@ -0,0 +1,110 @@
+Name
+
+   ANGLE_sync_control_rate
+
+Name Strings
+
+   EGL_ANGLE_sync_control_rate
+
+Contact
+
+   Jonah Ryan-Davis, Google (jonahr 'at' google.com)
+
+Status
+
+   Draft.
+
+Version
+
+   Version 1, 2020-03-24
+
+   Based on GLX_OML_sync_control Revision 6.0
+
+Number
+
+   ???
+
+Dependencies
+
+   The extension is written against the EGL 1.2 Specification, although it
+   should work on other versions of these specifications. This extension
+   also requires an operating system which supports CLOCK_MONOTONIC.
+
+Overview
+
+   This extension provides counters which let applications know about the
+   timing of the last vertical retrace. By looking at the system clock, as
+   well as the refresh rate of the monitor, this should enable applications
+   to predict the position of future retraces so as to schedule an optimal
+   workload.
+
+   This extension incorporates the use of three counters that provide
+   the necessary synchronization. The Unadjusted System Time (or UST)
+   is the 64-bit CLOCK_MONOTONIC clock; in particular this lets the
+   application schedule future vertical retraces by querying this clock.
+   The graphics Media Stream Counter (or graphics MSC) is a counter
+   that is unique to the graphics subsystem and increments for each
+   vertical retrace that occurs. The Swap Buffer Counter (SBC) is an
+   attribute of an EGLSurface and is incremented each time a swap
+   buffer action is performed on the associated surface.
+
+   The use of these three counters allows the application to
+   synchronize graphics rendering to vertical retraces and/or swap
+   buffer actions. For example, by querying the synchronization values for
+   a given surface, the application can accurately predict the timing for
+   the next vertical retraces and schedule rendering accordingly.
+
+Issues
+
+   None.
+
+IP Status
+
+   No known issues.
+
+New Procedures and Functions
+
+   Bool eglGetMscRateANGLE(EGLDisplay* dpy,
+                           EGLSurface surface,
+                           int32_t* numerator,
+                           int32_t* denominator)
+
+New Tokens
+
+   None
+
+Additions to the EGL 1.3 Specification
+
+   The graphics MSC value is incremented once for each screen refresh.
+   For a non-interlaced display, this means that the graphics MSC value
+   is incremented for each frame. For an interlaced display, it means
+   that it will be incremented for each field. For a multi-monitor
+   system, the monitor used to determine MSC is the one where the surface
+   is located. If the surface spans multiple monitors, the monitor used
+   to determine MSC is the one with the biggest coverage in pixels.
+
+   eglGetMscRateANGLE returns the rate at which the MSC will be incremented
+   for the display associated with <hdc>. The rate is expressed in Hertz
+   as <numerator> / <denominator>. If the MSC rate in Hertz is an
+   integer, then <denominator> will be 1 and <numerator> will be
+   the MSC rate.
+
+   The function eglGetMscRateANGLE will return TRUE if the function
+   completed successfully, FALSE otherwise.
+
+   Each time eglSwapBuffer succeeds, the SBC will be increased within a
+   finite time period.
+
+Errors
+
+   The function eglGetMscRateANGLE will return FALSE if there is no
+   current EGLContext.
+
+New Implementation Dependent State
+
+   None
+
+Revision History
+
+    Version 1, 2020-03-24 (Jonah Ryan-Davis)
+       - Initial draft, based on GLX_OML_sync_control revision 6.0.
diff --git a/extensions/EGL_CHROMIUM_sync_control.txt b/extensions/EGL_CHROMIUM_sync_control.txt
index 14f4e56..f699f61 100644
--- a/extensions/EGL_CHROMIUM_sync_control.txt
+++ b/extensions/EGL_CHROMIUM_sync_control.txt
@@ -16,7 +16,7 @@
 
 Version
 
-   Version 3, 2020-01-23
+   Version 2, 2015-05-05
 
    Based on GLX_OML_sync_control Revision 6.0
 
@@ -70,12 +70,6 @@
                                  int64_t* msc,
                                  int64_t* sbc)
 
-   Bool eglGetMscRateCHROMIUM(EGLDisplay* dpy,
-                              EGLSurface surface,
-                              int32_t* numerator,
-                              int32_t* denominator)
-
-
 New Tokens
 
    None
@@ -112,22 +106,16 @@
    is located. If the surface spans multiple monitors, the monitor used
    to determine MSC is the one with the biggest coverage in pixels.
 
-   eglGetMscRateCHROMIUM returns the rate at which the MSC will be incremented
-   for the display associated with <hdc>. The rate is expressed in Hertz
-   as <numerator> / <denominator>. If the MSC rate in Hertz is an
-   integer, then <denominator> will be 1 and <numerator> will be
-   the MSC rate.
-
-   The functions eglGetSyncValuesCHROMIUM, and eglGetMscRateCHROMIUM will
-   return TRUE if the function completed successfully, FALSE otherwise.
+   The function eglGetSyncValuesCHROMIUM will return TRUE if the function
+   completed successfully, FALSE otherwise.
 
    Each time eglSwapBuffer succeeds, the SBC will be increased within a
    finite time period.
 
 Errors
 
-   The functions eglGetSyncValuesCHROMIUM, and eglGetMscRateCHROMIUM will
-   return FALSE if there is no current EGLContext.
+   The function eglGetSyncValuesCHROMIUM will return FALSE if there is no
+   current EGLContext.
 
 
 New State
@@ -144,10 +132,6 @@
 
 Revision History
 
-    Version 3, 2020-01-23 (Jonah Ryan-Davis)
-       - Add the function eglGetMscRateCHROMIUM based on glXGetMscRateOML from
-         GLX_OML_sync_control revision 6.0.
-
     Version 2, 2015-05-05 (Chad Versace)
        - Rename to EGL_CHROMIUM_sync_control from EGL_CHROMIUM_get_sync_values.
          EGL_CHROMIUM_sync_control is the de facto extension name because all
diff --git a/include/EGL/eglext_angle.h b/include/EGL/eglext_angle.h
index 50bd6f1..4bb2628 100644
--- a/include/EGL/eglext_angle.h
+++ b/include/EGL/eglext_angle.h
@@ -217,22 +217,28 @@
                                                              EGLuint64KHR *ust,
                                                              EGLuint64KHR *msc,
                                                              EGLuint64KHR *sbc);
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETMSCRATECHROMIUMPROC) (EGLDisplay dpy,
-                                                             EGLSurface surface,
-                                                             EGLint *numerator,
-                                                             EGLint *denominator);
 #ifdef EGL_EGLEXT_PROTOTYPES
 EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncValuesCHROMIUM(EGLDisplay dpy,
                                                              EGLSurface surface,
                                                              EGLuint64KHR *ust,
                                                              EGLuint64KHR *msc,
                                                              EGLuint64KHR *sbc);
-EGLAPI EGLBoolean EGLAPIENTRY eglGetMscRateCHROMIUM(EGLDisplay dpy,
+#endif
+#endif /* EGL_CHROMIUM_sync_control */
+
+#ifndef EGL_ANGLE_sync_control_rate
+#define EGL_ANGLE_sync_control_rate 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETMSCRATEANGLEPROC) (EGLDisplay dpy,
+                                                             EGLSurface surface,
+                                                             EGLint *numerator,
+                                                             EGLint *denominator);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglGetMscRateANGLE(EGLDisplay dpy,
                                                              EGLSurface surface,
                                                              EGLint *numerator,
                                                              EGLint *denominator);
 #endif
-#endif /* EGL_CHROMIUM_sync_control */
+#endif /* EGL_ANGLE_sync_control_rate */
 
 #ifndef EGL_ANGLE_power_preference
 #define EGL_ANGLE_power_preference 1
diff --git a/include/GLES2/gl2ext_angle.h b/include/GLES2/gl2ext_angle.h
index 5195eff..bc56c14 100644
--- a/include/GLES2/gl2ext_angle.h
+++ b/include/GLES2/gl2ext_angle.h
@@ -75,237 +75,6 @@
 #endif
 #endif /* GL_EXT_direct_state_access */
 
-#ifndef GL_CHROMIUM_path_rendering
-#define GL_CHROMIUM_path_rendering 1
-#define GL_PATH_MODELVIEW_CHROMIUM 0x1700
-#define GL_PATH_PROJECTION_CHROMIUM 0x1701
-#define GL_CLOSE_PATH_CHROMIUM 0x00
-#define GL_MOVE_TO_CHROMIUM 0x02
-#define GL_LINE_TO_CHROMIUM 0x04
-#define GL_QUADRATIC_CURVE_TO_CHROMIUM 0x0A
-#define GL_CUBIC_CURVE_TO_CHROMIUM 0x0C
-#define GL_CONIC_CURVE_TO_CHROMIUM 0x1A
-#define GL_PATH_MODELVIEW_MATRIX_CHROMIUM 0x0BA6
-#define GL_PATH_PROJECTION_MATRIX_CHROMIUM 0x0BA7
-#define GL_PATH_STROKE_WIDTH_CHROMIUM 0x9075
-#define GL_PATH_END_CAPS_CHROMIUM 0x9076
-#define GL_PATH_JOIN_STYLE_CHROMIUM 0x9079
-#define GL_PATH_MITER_LIMIT_CHROMIUM 0x907a
-#define GL_PATH_STROKE_BOUND_CHROMIUM 0x9086
-#define GL_FLAT_CHROMIUM 0x1D00
-#define GL_SQUARE_CHROMIUM 0x90a3
-#define GL_ROUND_CHROMIUM 0x90a4
-#define GL_BEVEL_CHROMIUM 0x90A6
-#define GL_MITER_REVERT_CHROMIUM 0x90A7
-#define GL_COUNT_UP_CHROMIUM 0x9088
-#define GL_COUNT_DOWN_CHROMIUM 0x9089
-#define GL_CONVEX_HULL_CHROMIUM 0x908B
-#define GL_BOUNDING_BOX_CHROMIUM 0x908D
-#define GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM 0x909C
-#define GL_EYE_LINEAR_CHROMIUM 0x2400
-#define GL_OBJECT_LINEAR_CHROMIUM 0x2401
-#define GL_CONSTANT_CHROMIUM 0x8576
-#define GL_TRANSLATE_X_CHROMIUM 0x908E
-#define GL_TRANSLATE_Y_CHROMIUM 0x908F
-#define GL_TRANSLATE_2D_CHROMIUM 0x9090
-#define GL_TRANSLATE_3D_CHROMIUM 0x9091
-#define GL_AFFINE_2D_CHROMIUM 0x9092
-#define GL_AFFINE_3D_CHROMIUM 0x9094
-#define GL_TRANSPOSE_AFFINE_2D_CHROMIUM 0x9096
-#define GL_TRANSPOSE_AFFINE_3D_CHROMIUM 0x9098
-typedef void(GL_APIENTRYP PFNGLMATRIXLOADFCHROMIUMPROC)(GLenum matrixMode, const GLfloat *m);
-typedef void(GL_APIENTRYP PFNGLMATRIXLOADIDENTITYCHROMIUMPROC)(GLenum matrixMode);
-typedef GLuint(GL_APIENTRYP PFNGLGENPATHSCHROMIUMPROC)(GLsizei range);
-typedef void(GL_APIENTRYP PFNGLDELETEPATHSCHROMIUMPROC)(GLuint path, GLsizei range);
-typedef GLboolean(GL_APIENTRYP PFNGLISPATHCHROMIUMPROC)(GLuint path);
-typedef void(GL_APIENTRYP PFNGLPATHCOMMANDSCHROMIUMPROC)(GLuint path,
-                                                         GLsizei numCommands,
-                                                         const GLubyte *commands,
-                                                         GLsizei numCoords,
-                                                         GLenum coordType,
-                                                         const void *coords);
-typedef void(GL_APIENTRYP PFNGLPATHPARAMETERICHROMIUMPROC)(GLuint path, GLenum pname, GLint value);
-typedef void(GL_APIENTRYP PFNGLPATHPARAMETERFCHROMIUMPROC)(GLuint path,
-                                                           GLenum pname,
-                                                           GLfloat value);
-typedef void(GL_APIENTRYP PFNGLGETPATHPARAMETERIVCHROMIUMPROC)(GLuint path,
-                                                               GLenum pname,
-                                                               GLint *value);
-typedef void(GL_APIENTRYP PFNGLGETPATHPARAMETERFVCHROMIUMPROC)(GLuint path,
-                                                               GLenum pname,
-                                                               GLfloat *value);
-typedef void(GL_APIENTRYP PFNGLPATHSTENCILFUNCCHROMIUMPROC)(GLenum func, GLint ref, GLuint mask);
-typedef void(GL_APIENTRYP PFNGLSTENCILFILLPATHCHROMIUMPROC)(GLuint path,
-                                                            GLenum fillMode,
-                                                            GLuint mask);
-typedef void(GL_APIENTRYP PFNGLSTENCILSTROKEPATHCHROMIUMPROC)(GLuint path,
-                                                              GLint reference,
-                                                              GLuint mask);
-typedef void(GL_APIENTRYP PFNGLCOVERFILLPATHCHROMIUMPROC)(GLuint path, GLenum coverMode);
-typedef void(GL_APIENTRYP PFNGLCOVERSTROKEPATHCHROMIUMPROC)(GLuint path, GLenum coverMode);
-typedef void(GL_APIENTRYP PFNGLSTENCILTHENCOVERFILLPATHCHROMIUMPROC)(GLuint path,
-                                                                     GLenum fillMode,
-                                                                     GLuint mask,
-                                                                     GLenum coverMode);
-typedef void(GL_APIENTRYP PFNGLSTENCILTHENCOVERSTROKEPATHCHROMIUMPROC)(GLuint path,
-                                                                       GLint reference,
-                                                                       GLuint mask,
-                                                                       GLenum coverMode);
-typedef void(GL_APIENTRYP PFNGLCOVERFILLPATHINSTANCEDCHROMIUMPROC)(GLsizei numPaths,
-                                                                   GLenum pathNameType,
-                                                                   const void *paths,
-                                                                   GLuint pathBase,
-                                                                   GLenum coverMode,
-                                                                   GLenum transformType,
-                                                                   const GLfloat *transformValues);
-typedef void(GL_APIENTRYP PFNGLCOVERSTROKEPATHINSTANCEDCHROMIUMPROC)(
-    GLsizei numPaths,
-    GLenum pathNameType,
-    const void *paths,
-    GLuint pathBase,
-    GLenum coverMode,
-    GLenum transformType,
-    const GLfloat *transformValues);
-typedef void(GL_APIENTRYP PFNGLSTENCILFILLPATHINSTANCEDCHROMIUMPROC)(
-    GLsizei numPaths,
-    GLenum pathNameType,
-    const void *paths,
-    GLuint pathBase,
-    GLenum fillMode,
-    GLuint mask,
-    GLenum transformType,
-    const GLfloat *transformValues);
-typedef void(GL_APIENTRYP PFNGLSTENCILSTROKEPATHINSTANCEDCHROMIUMPROC)(
-    GLsizei numPaths,
-    GLenum pathNameType,
-    const void *paths,
-    GLuint pathBase,
-    GLint reference,
-    GLuint mask,
-    GLenum transformType,
-    const GLfloat *transformValues);
-typedef void(GL_APIENTRYP PFNGLSTENCILTHENCOVERFILLPATHINSTANCEDCHROMIUMPROC)(
-    GLsizei numPaths,
-    GLenum pathNameType,
-    const void *paths,
-    GLuint pathBase,
-    GLenum fillMode,
-    GLuint mask,
-    GLenum coverMode,
-    GLenum transformType,
-    const GLfloat *transformValues);
-typedef void(GL_APIENTRYP PFNGLSTENCILTHENCOVERSTROKEPATHINSTANCEDCHROMIUMPROC)(
-    GLsizei numPaths,
-    GLenum pathNameType,
-    const void *paths,
-    GLuint pathBase,
-    GLint reference,
-    GLuint mask,
-    GLenum coverMode,
-    GLenum transformType,
-    const GLfloat *transformValues);
-
-typedef void(GL_APIENTRYP PFNGLBINDFRAGMENTINPUTLOCATIONCHROMIUMPROC)(GLuint program,
-                                                                     GLint location,
-                                                                     const GLchar *name);
-typedef void(GL_APIENTRYP PFNGLPROGRAMPATHFRAGMENTINPUTGENCHROMIUMPROC)(GLuint program,
-                                                                        GLint location,
-                                                                        GLenum genMode,
-                                                                        GLint components,
-                                                                        const GLfloat *coeffs);
-#ifdef GL_GLEXT_PROTOTYPES
-GL_APICALL void GL_APIENTRY glMatrixLoadfCHROMIUM(GLenum matrixMode, const GLfloat *m);
-GL_APICALL void GL_APIENTRY glMatrixLoadIdentityCHROMIUM(GLenum matrixMode);
-GL_APICALL GLuint GL_APIENTRY glGenPathsCHROMIUM(GLsizei range);
-GL_APICALL void GL_APIENTRY glDeletePathsCHROMIUM(GLuint path, GLsizei range);
-GL_APICALL GLboolean GL_APIENTRY glIsPathCHROMIUM(GLuint path);
-GL_APICALL void GL_APIENTRY glPathCommandsCHROMIUM(GLuint path,
-                                                   GLsizei numCommands,
-                                                   const GLubyte *commands,
-                                                   GLsizei numCoords,
-                                                   GLenum coordType,
-                                                   const void *coords);
-GL_APICALL void GL_APIENTRY glPathParameteriCHROMIUM(GLuint path, GLenum pname, GLint value);
-GL_APICALL void GL_APIENTRY glPathParameterfCHROMIUM(GLuint path, GLenum pname, GLfloat value);
-GL_APICALL void GL_APIENTRY glGetPathParameterivCHROMIUM(GLuint path, GLenum pname, GLint *value);
-GL_APICALL void GL_APIENTRY glGetPathParameterfvCHROMIUM(GLuint path, GLenum pname, GLfloat *value);
-GL_APICALL void GL_APIENTRY glPathStencilFuncCHROMIUM(GLenum func, GLint ref, GLuint mask);
-GL_APICALL void GL_APIENTRY glStencilFillPathCHROMIUM(GLuint path, GLenum fillMode, GLuint mask);
-GL_APICALL void GL_APIENTRY glStencilStrokePathCHROMIUM(GLuint path, GLint reference, GLuint mask);
-GL_APICALL void GL_APIENTRY glCoverFillPathCHROMIUM(GLuint path, GLenum coverMode);
-GL_APICALL void GL_APIENTRY glCoverStrokePathCHROMIUM(GLuint path, GLenum coverMode);
-GL_APICALL void GL_APIENTRY glStencilThenCoverFillPathCHROMIUM(GLuint path,
-                                                               GLenum fillMode,
-                                                               GLuint mask,
-                                                               GLenum coverMode);
-GL_APICALL void GL_APIENTRY glStencilThenCoverStrokePathCHROMIUM(GLuint path,
-                                                                 GLint reference,
-                                                                 GLuint mask,
-                                                                 GLenum coverMode);
-GL_APICALL void GL_APIENTRY glCoverFillPathInstancedCHROMIUM(GLsizei numPaths,
-                                                             GLenum pathNameType,
-                                                             const void *paths,
-                                                             GLuint pathBase,
-                                                             GLenum coverMode,
-                                                             GLenum transformType,
-                                                             const GLfloat *transformValues);
-GL_APICALL void GL_APIENTRY glCoverStrokePathInstancedCHROMIUM(GLsizei numPaths,
-                                                               GLenum pathNameType,
-                                                               const void *paths,
-                                                               GLuint pathBase,
-                                                               GLenum coverMode,
-                                                               GLenum transformType,
-                                                               const GLfloat *transformValues);
-GL_APICALL void GL_APIENTRY glStencilFillPathInstancedCHROMIUM(GLsizei numPaths,
-                                                               GLenum pathNameType,
-                                                               const void *paths,
-                                                               GLuint pathBase,
-                                                               GLenum fillMode,
-                                                               GLuint mask,
-                                                               GLenum transformType,
-                                                               const GLfloat *transformValues);
-GL_APICALL void GL_APIENTRY glStencilStrokePathInstancedCHROMIUM(GLsizei numPaths,
-                                                                 GLenum pathNameType,
-                                                                 const void *paths,
-                                                                 GLuint pathBase,
-                                                                 GLint reference,
-                                                                 GLuint mask,
-                                                                 GLenum transformType,
-                                                                 const GLfloat *transformValues);
-GL_APICALL void GL_APIENTRY
-glStencilThenCoverFillPathInstancedCHROMIUM(GLsizei numPaths,
-                                            GLenum pathNameType,
-                                            const void *paths,
-                                            GLuint pathBase,
-                                            GLenum fillMode,
-                                            GLuint mask,
-                                            GLenum coverMode,
-                                            GLenum transformType,
-                                            const GLfloat *transformValues);
-
-GL_APICALL void GL_APIENTRY
-glStencilThenCoverStrokePathInstancedCHROMIUM(GLsizei numPaths,
-                                              GLenum pathNameType,
-                                              const void *paths,
-                                              GLuint pathBase,
-                                              GLint reference,
-                                              GLuint mask,
-                                              GLenum coverMode,
-                                              GLenum transformType,
-                                              const GLfloat *transformValues);
-
-GL_APICALL void GL_APIENTRY glBindFragmentInputLocationCHROMIUM(GLuint program,
-                                                                GLint location,
-                                                                const GLchar *name);
-GL_APICALL void GL_APIENTRY glProgramPathFragmentInputGenCHROMIUM(GLuint program,
-                                                                  GLint location,
-                                                                  GLenum genMode,
-                                                                  GLint components,
-                                                                  const GLfloat *coeffs);
-
-#endif
-#endif /* GL_CHROMIUM_path_rendering */
-
 #ifndef GL_CHROMIUM_copy_texture
 #define GL_CHROMIUM_copy_texture 1
 typedef void(GL_APIENTRYP PFNGLCOPYTEXTURECHROMIUMPROC)(GLuint sourceId,
diff --git a/include/GLES2/gl2ext_explicit_context_autogen.inc b/include/GLES2/gl2ext_explicit_context_autogen.inc
index eb7d62e..ea8be5c 100644
--- a/include/GLES2/gl2ext_explicit_context_autogen.inc
+++ b/include/GLES2/gl2ext_explicit_context_autogen.inc
@@ -284,31 +284,6 @@
 typedef void (GL_APIENTRYP PFNGLWAITSEMAPHOREEXTCONTEXTANGLEPROC)(GLeglContext ctx, GLuint semaphore, GLuint numBufferBarriers, const GLuint *buffers, GLuint numTextureBarriers, const GLuint *textures, const GLenum *srcLayouts);
 typedef void (GL_APIENTRYP PFNGLBINDUNIFORMLOCATIONCHROMIUMCONTEXTANGLEPROC)(GLeglContext ctx, GLuint program, GLint location, const GLchar* name);
 typedef void (GL_APIENTRYP PFNGLCOVERAGEMODULATIONCHROMIUMCONTEXTANGLEPROC)(GLeglContext ctx, GLenum components);
-typedef void (GL_APIENTRYP PFNGLMATRIXLOADFCHROMIUMCONTEXTANGLEPROC)(GLeglContext ctx, GLenum matrixMode, const GLfloat * matrix);
-typedef void (GL_APIENTRYP PFNGLMATRIXLOADIDENTITYCHROMIUMCONTEXTANGLEPROC)(GLeglContext ctx, GLenum matrixMode);
-typedef GLuint (GL_APIENTRYP PFNGLGENPATHSCHROMIUMCONTEXTANGLEPROC)(GLeglContext ctx, GLsizei range);
-typedef void (GL_APIENTRYP PFNGLDELETEPATHSCHROMIUMCONTEXTANGLEPROC)(GLeglContext ctx, GLuint first, GLsizei range);
-typedef GLboolean (GL_APIENTRYP PFNGLISPATHCHROMIUMCONTEXTANGLEPROC)(GLeglContext ctx, GLuint path);
-typedef void (GL_APIENTRYP PFNGLPATHCOMMANDSCHROMIUMCONTEXTANGLEPROC)(GLeglContext ctx, GLuint path, GLsizei numCommands, const GLubyte * commands, GLsizei numCoords, GLenum coordType, const void* coords);
-typedef void (GL_APIENTRYP PFNGLPATHPARAMETERFCHROMIUMCONTEXTANGLEPROC)(GLeglContext ctx, GLuint path, GLenum pname, GLfloat value);
-typedef void (GL_APIENTRYP PFNGLPATHPARAMETERICHROMIUMCONTEXTANGLEPROC)(GLeglContext ctx, GLuint path, GLenum pname, GLint value);
-typedef void (GL_APIENTRYP PFNGLGETPATHPARAMETERFVCHROMIUMCONTEXTANGLEPROC)(GLeglContext ctx, GLuint path, GLenum pname, GLfloat * value);
-typedef void (GL_APIENTRYP PFNGLGETPATHPARAMETERIVCHROMIUMCONTEXTANGLEPROC)(GLeglContext ctx, GLuint path, GLenum pname, GLint * value);
-typedef void (GL_APIENTRYP PFNGLPATHSTENCILFUNCCHROMIUMCONTEXTANGLEPROC)(GLeglContext ctx, GLenum func, GLint ref, GLuint mask);
-typedef void (GL_APIENTRYP PFNGLSTENCILFILLPATHCHROMIUMCONTEXTANGLEPROC)(GLeglContext ctx, GLuint path, GLenum fillMode, GLuint mask);
-typedef void (GL_APIENTRYP PFNGLSTENCILSTROKEPATHCHROMIUMCONTEXTANGLEPROC)(GLeglContext ctx, GLuint path, GLint reference, GLuint mask);
-typedef void (GL_APIENTRYP PFNGLCOVERFILLPATHCHROMIUMCONTEXTANGLEPROC)(GLeglContext ctx, GLuint path, GLenum coverMode);
-typedef void (GL_APIENTRYP PFNGLCOVERSTROKEPATHCHROMIUMCONTEXTANGLEPROC)(GLeglContext ctx, GLuint path, GLenum coverMode);
-typedef void (GL_APIENTRYP PFNGLSTENCILTHENCOVERFILLPATHCHROMIUMCONTEXTANGLEPROC)(GLeglContext ctx, GLuint path, GLenum fillMode, GLuint mask, GLenum coverMode);
-typedef void (GL_APIENTRYP PFNGLSTENCILTHENCOVERSTROKEPATHCHROMIUMCONTEXTANGLEPROC)(GLeglContext ctx, GLuint path, GLint reference, GLuint mask, GLenum coverMode);
-typedef void (GL_APIENTRYP PFNGLCOVERFILLPATHINSTANCEDCHROMIUMCONTEXTANGLEPROC)(GLeglContext ctx, GLsizei numPath, GLenum pathNameType, const void * paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat * transformValues);
-typedef void (GL_APIENTRYP PFNGLCOVERSTROKEPATHINSTANCEDCHROMIUMCONTEXTANGLEPROC)(GLeglContext ctx, GLsizei numPath, GLenum pathNameType, const void * paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat * transformValues);
-typedef void (GL_APIENTRYP PFNGLSTENCILSTROKEPATHINSTANCEDCHROMIUMCONTEXTANGLEPROC)(GLeglContext ctx, GLsizei numPath, GLenum pathNameType, const void * paths, GLuint pathBase, GLint reference, GLuint mask, GLenum transformType, const GLfloat * transformValues);
-typedef void (GL_APIENTRYP PFNGLSTENCILFILLPATHINSTANCEDCHROMIUMCONTEXTANGLEPROC)(GLeglContext ctx, GLsizei numPaths, GLenum pathNameType, const void * paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum transformType, const GLfloat * transformValues);
-typedef void (GL_APIENTRYP PFNGLSTENCILTHENCOVERFILLPATHINSTANCEDCHROMIUMCONTEXTANGLEPROC)(GLeglContext ctx, GLsizei numPaths, GLenum pathNameType, const void * paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat * transformValues);
-typedef void (GL_APIENTRYP PFNGLSTENCILTHENCOVERSTROKEPATHINSTANCEDCHROMIUMCONTEXTANGLEPROC)(GLeglContext ctx, GLsizei numPaths, GLenum pathNameType, const void * paths, GLuint pathBase, GLint reference, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat * transformValues);
-typedef void (GL_APIENTRYP PFNGLBINDFRAGMENTINPUTLOCATIONCHROMIUMCONTEXTANGLEPROC)(GLeglContext ctx, GLuint programs, GLint location, const GLchar * name);
-typedef void (GL_APIENTRYP PFNGLPROGRAMPATHFRAGMENTINPUTGENCHROMIUMCONTEXTANGLEPROC)(GLeglContext ctx, GLuint program, GLint location, GLenum genMode, GLint components, const GLfloat * coeffs);
 typedef void (GL_APIENTRYP PFNGLCOPYTEXTURECHROMIUMCONTEXTANGLEPROC)(GLeglContext ctx, GLuint sourceId, GLint sourceLevel, GLenum destTarget, GLuint destId, GLint destLevel, GLint internalFormat, GLenum destType, GLboolean unpackFlipY, GLboolean unpackPremultiplyAlpha, GLboolean unpackUnmultiplyAlpha);
 typedef void (GL_APIENTRYP PFNGLCOPYSUBTEXTURECHROMIUMCONTEXTANGLEPROC)(GLeglContext ctx, GLuint sourceId, GLint sourceLevel, GLenum destTarget, GLuint destId, GLint destLevel, GLint xoffset, GLint yoffset, GLint x, GLint y, GLint width, GLint height, GLboolean unpackFlipY, GLboolean unpackPremultiplyAlpha, GLboolean unpackUnmultiplyAlpha);
 typedef void (GL_APIENTRYP PFNGLCOMPRESSEDCOPYTEXTURECHROMIUMCONTEXTANGLEPROC)(GLeglContext ctx, GLuint sourceId, GLuint destId);
@@ -678,31 +653,6 @@
 GL_APICALL void GL_APIENTRY glWaitSemaphoreEXTContextANGLE(GLeglContext ctx, GLuint semaphore, GLuint numBufferBarriers, const GLuint *buffers, GLuint numTextureBarriers, const GLuint *textures, const GLenum *srcLayouts);
 GL_APICALL void GL_APIENTRY glBindUniformLocationCHROMIUMContextANGLE(GLeglContext ctx, GLuint program, GLint location, const GLchar* name);
 GL_APICALL void GL_APIENTRY glCoverageModulationCHROMIUMContextANGLE(GLeglContext ctx, GLenum components);
-GL_APICALL void GL_APIENTRY glMatrixLoadfCHROMIUMContextANGLE(GLeglContext ctx, GLenum matrixMode, const GLfloat * matrix);
-GL_APICALL void GL_APIENTRY glMatrixLoadIdentityCHROMIUMContextANGLE(GLeglContext ctx, GLenum matrixMode);
-GL_APICALL GLuint GL_APIENTRY glGenPathsCHROMIUMContextANGLE(GLeglContext ctx, GLsizei range);
-GL_APICALL void GL_APIENTRY glDeletePathsCHROMIUMContextANGLE(GLeglContext ctx, GLuint first, GLsizei range);
-GL_APICALL GLboolean GL_APIENTRY glIsPathCHROMIUMContextANGLE(GLeglContext ctx, GLuint path);
-GL_APICALL void GL_APIENTRY glPathCommandsCHROMIUMContextANGLE(GLeglContext ctx, GLuint path, GLsizei numCommands, const GLubyte * commands, GLsizei numCoords, GLenum coordType, const void* coords);
-GL_APICALL void GL_APIENTRY glPathParameterfCHROMIUMContextANGLE(GLeglContext ctx, GLuint path, GLenum pname, GLfloat value);
-GL_APICALL void GL_APIENTRY glPathParameteriCHROMIUMContextANGLE(GLeglContext ctx, GLuint path, GLenum pname, GLint value);
-GL_APICALL void GL_APIENTRY glGetPathParameterfvCHROMIUMContextANGLE(GLeglContext ctx, GLuint path, GLenum pname, GLfloat * value);
-GL_APICALL void GL_APIENTRY glGetPathParameterivCHROMIUMContextANGLE(GLeglContext ctx, GLuint path, GLenum pname, GLint * value);
-GL_APICALL void GL_APIENTRY glPathStencilFuncCHROMIUMContextANGLE(GLeglContext ctx, GLenum func, GLint ref, GLuint mask);
-GL_APICALL void GL_APIENTRY glStencilFillPathCHROMIUMContextANGLE(GLeglContext ctx, GLuint path, GLenum fillMode, GLuint mask);
-GL_APICALL void GL_APIENTRY glStencilStrokePathCHROMIUMContextANGLE(GLeglContext ctx, GLuint path, GLint reference, GLuint mask);
-GL_APICALL void GL_APIENTRY glCoverFillPathCHROMIUMContextANGLE(GLeglContext ctx, GLuint path, GLenum coverMode);
-GL_APICALL void GL_APIENTRY glCoverStrokePathCHROMIUMContextANGLE(GLeglContext ctx, GLuint path, GLenum coverMode);
-GL_APICALL void GL_APIENTRY glStencilThenCoverFillPathCHROMIUMContextANGLE(GLeglContext ctx, GLuint path, GLenum fillMode, GLuint mask, GLenum coverMode);
-GL_APICALL void GL_APIENTRY glStencilThenCoverStrokePathCHROMIUMContextANGLE(GLeglContext ctx, GLuint path, GLint reference, GLuint mask, GLenum coverMode);
-GL_APICALL void GL_APIENTRY glCoverFillPathInstancedCHROMIUMContextANGLE(GLeglContext ctx, GLsizei numPath, GLenum pathNameType, const void * paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat * transformValues);
-GL_APICALL void GL_APIENTRY glCoverStrokePathInstancedCHROMIUMContextANGLE(GLeglContext ctx, GLsizei numPath, GLenum pathNameType, const void * paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat * transformValues);
-GL_APICALL void GL_APIENTRY glStencilStrokePathInstancedCHROMIUMContextANGLE(GLeglContext ctx, GLsizei numPath, GLenum pathNameType, const void * paths, GLuint pathBase, GLint reference, GLuint mask, GLenum transformType, const GLfloat * transformValues);
-GL_APICALL void GL_APIENTRY glStencilFillPathInstancedCHROMIUMContextANGLE(GLeglContext ctx, GLsizei numPaths, GLenum pathNameType, const void * paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum transformType, const GLfloat * transformValues);
-GL_APICALL void GL_APIENTRY glStencilThenCoverFillPathInstancedCHROMIUMContextANGLE(GLeglContext ctx, GLsizei numPaths, GLenum pathNameType, const void * paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat * transformValues);
-GL_APICALL void GL_APIENTRY glStencilThenCoverStrokePathInstancedCHROMIUMContextANGLE(GLeglContext ctx, GLsizei numPaths, GLenum pathNameType, const void * paths, GLuint pathBase, GLint reference, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat * transformValues);
-GL_APICALL void GL_APIENTRY glBindFragmentInputLocationCHROMIUMContextANGLE(GLeglContext ctx, GLuint programs, GLint location, const GLchar * name);
-GL_APICALL void GL_APIENTRY glProgramPathFragmentInputGenCHROMIUMContextANGLE(GLeglContext ctx, GLuint program, GLint location, GLenum genMode, GLint components, const GLfloat * coeffs);
 GL_APICALL void GL_APIENTRY glCopyTextureCHROMIUMContextANGLE(GLeglContext ctx, GLuint sourceId, GLint sourceLevel, GLenum destTarget, GLuint destId, GLint destLevel, GLint internalFormat, GLenum destType, GLboolean unpackFlipY, GLboolean unpackPremultiplyAlpha, GLboolean unpackUnmultiplyAlpha);
 GL_APICALL void GL_APIENTRY glCopySubTextureCHROMIUMContextANGLE(GLeglContext ctx, GLuint sourceId, GLint sourceLevel, GLenum destTarget, GLuint destId, GLint destLevel, GLint xoffset, GLint yoffset, GLint x, GLint y, GLint width, GLint height, GLboolean unpackFlipY, GLboolean unpackPremultiplyAlpha, GLboolean unpackUnmultiplyAlpha);
 GL_APICALL void GL_APIENTRY glCompressedCopyTextureCHROMIUMContextANGLE(GLeglContext ctx, GLuint sourceId, GLuint destId);
diff --git a/include/GLSLANG/ShaderLang.h b/include/GLSLANG/ShaderLang.h
index a8da590..31ada88 100644
--- a/include/GLSLANG/ShaderLang.h
+++ b/include/GLSLANG/ShaderLang.h
@@ -26,7 +26,7 @@
 
 // Version number for shader translation API.
 // It is incremented every time the API changes.
-#define ANGLE_SH_VERSION 225
+#define ANGLE_SH_VERSION 228
 
 enum ShShaderSpec
 {
@@ -336,6 +336,9 @@
 // Drop any explicit precision qualifiers from shader.
 const ShCompileOptions SH_IGNORE_PRECISION_QUALIFIERS = UINT64_C(1) << 54;
 
+// Allow compiler to do early fragment tests as an optimization.
+const ShCompileOptions SH_EARLY_FRAGMENT_TESTS_OPTIMIZATION = UINT64_C(1) << 55;
+
 // Defines alternate strategies for implementing array index clamping.
 enum ShArrayIndexClampingStrategy
 {
@@ -380,6 +383,7 @@
     int WEBGL_debug_shader_precision;
     int EXT_shader_framebuffer_fetch;
     int NV_shader_framebuffer_fetch;
+    int NV_shader_noperspective_interpolation;
     int ARM_shader_framebuffer_fetch;
     int OVR_multiview;
     int OVR_multiview2;
@@ -387,6 +391,7 @@
     int EXT_YUV_target;
     int EXT_geometry_shader;
     int EXT_gpu_shader5;
+    int EXT_shader_non_constant_global_initializers;
     int OES_texture_storage_multisample_2d_array;
     int OES_texture_3D;
     int ANGLE_texture_multisample;
@@ -663,6 +668,8 @@
 // Returns the number of views specified through the num_views layout qualifier. If num_views is
 // not set, the function returns -1.
 int GetVertexShaderNumViews(const ShHandle handle);
+// Returns true if compiler has injected instructions for early fragment tests as an optimization
+bool HasEarlyFragmentTestsOptimization(const ShHandle handle);
 
 // Returns true if the passed in variables pack in maxVectors followingthe packing rules from the
 // GLSL 1.017 spec, Appendix A, section 7.
diff --git a/include/GLSLANG/ShaderVars.h b/include/GLSLANG/ShaderVars.h
index 52f6ad0..477d2d2 100644
--- a/include/GLSLANG/ShaderVars.h
+++ b/include/GLSLANG/ShaderVars.h
@@ -28,7 +28,8 @@
 {
     INTERPOLATION_SMOOTH,
     INTERPOLATION_CENTROID,
-    INTERPOLATION_FLAT
+    INTERPOLATION_FLAT,
+    INTERPOLATION_NOPERSPECTIVE
 };
 
 // Validate link & SSO consistency of interpolation qualifiers
diff --git a/include/platform/Feature.h b/include/platform/Feature.h
index 7af4174..87329f4 100644
--- a/include/platform/Feature.h
+++ b/include/platform/Feature.h
@@ -13,11 +13,11 @@
 #include <string>
 #include <vector>
 
-#define ANGLE_FEATURE_CONDITION(set, feature, cond)     \
-    do                                                  \
-    {                                                   \
-        set->feature.enabled   = cond;                  \
-        set->feature.condition = ANGLE_STRINGIFY(cond); \
+#define ANGLE_FEATURE_CONDITION(set, feature, cond)       \
+    do                                                    \
+    {                                                     \
+        (set)->feature.enabled   = cond;                  \
+        (set)->feature.condition = ANGLE_STRINGIFY(cond); \
     } while (0)
 
 namespace angle
@@ -139,7 +139,7 @@
       description(description),
       bug(bug),
       enabled(false),
-      condition(nullptr)
+      condition("")
 {
     if (mapPtr != nullptr)
     {
diff --git a/include/platform/FeaturesGL.h b/include/platform/FeaturesGL.h
index 5b36f27..2c3f405 100644
--- a/include/platform/FeaturesGL.h
+++ b/include/platform/FeaturesGL.h
@@ -364,6 +364,12 @@
         "GL_PRIMITIVE_RESTART and glPrimitiveRestartIndex.",
         &members, "http://anglebug.com/3997"};
 
+    Feature setPrimitiveRestartFixedIndexForDrawArrays = {
+        "set_primitive_restart_fixed_index_for_draw_arrays", FeatureCategory::OpenGLWorkarounds,
+        "Some drivers discard vertex data in DrawArrays calls when the fixed primitive restart "
+        "index is within the number of primitives being drawn.",
+        &members, "http://anglebug.com/3997"};
+
     // Dynamic indexing of swizzled l-values doesn't work correctly on various platforms.
     Feature removeDynamicIndexingOfSwizzledVector = {
         "remove_dynamic_indexing_of_swizzled_vector", FeatureCategory::OpenGLWorkarounds,
diff --git a/include/platform/FeaturesVk.h b/include/platform/FeaturesVk.h
index 66fd5b7..febc24b 100644
--- a/include/platform/FeaturesVk.h
+++ b/include/platform/FeaturesVk.h
@@ -251,6 +251,13 @@
         "Fill new allocations with non-zero values to flush out errors.", &members,
         "http://anglebug.com/4384"};
 
+    // Persistently map buffer memory until destroy, saves on map/unmap IOCTL overhead
+    // for buffers that are updated frequently.
+    Feature persistentlyMappedBuffers = {
+        "persistently_mapped_buffers", FeatureCategory::VulkanFeatures,
+        "Persistently map buffer memory to reduce map/unmap IOCTL overhead.", &members,
+        "http://anglebug.com/2162"};
+
     // Android needs to pre-rotate surfaces that are not oriented per the native device's
     // orientation (e.g. a landscape application on a Pixel phone).  This feature works for
     // full-screen applications. http://anglebug.com/3502
@@ -268,6 +275,12 @@
     Feature enablePrecisionQualifiers = {
         "enable_precision_qualifiers", FeatureCategory::VulkanFeatures,
         "Enable precision qualifiers in shaders", &members, "http://anglebug.com/3078"};
+
+    // Support Depth/Stencil rendering feedback loops by masking out the depth/stencil buffer.
+    // Manhattan uses this feature in a few draw calls.
+    Feature supportDepthStencilRenderingFeedbackLoops = {
+        "support_depth_stencil_rendering_feedback_loops", FeatureCategory::VulkanFeatures,
+        "Suport depth/stencil rendering feedback loops", &members, "http://anglebug.com/4490"};
 };
 
 inline FeaturesVk::FeaturesVk()  = default;
diff --git a/infra/ANGLEWrangling.md b/infra/ANGLEWrangling.md
index 361f3d1..74378ab 100644
--- a/infra/ANGLEWrangling.md
+++ b/infra/ANGLEWrangling.md
@@ -2,13 +2,15 @@
 
 As an ANGLE Sheriff. Your job is to:
 
- 1. Keep the [ANGLE Try Waterfall](https://ci.chromium.org/p/chromium/g/angle.try/builders) in good
+ 1. Keep the [ANGLE Try Waterfall](https://ci.chromium.org/p/chromium/g/tryserver.chromium.angle/builders) in good
     working order.
  1. Monitor the
     [Chromium GPU FYI Waterfall](https://ci.chromium.org/p/chromium/g/chromium.gpu.fyi/console)
     and respond to ANGLE bugs.
  1. Control and monitor the [ANGLE auto-rollers](#task-3_the-auto_rollers).
  1. Keep the [ANGLE Standalone Testers](README.md) in good working order.
+ 1. Keep the [SwANGLE Try Waterfall](https://luci-milo.appspot.com/p/chromium/g/tryserver.chromium.swangle/builders) in good
+    working order.
 
 If you're not an ANGLE team member, you can contact us on the public ANGLE project
 [Google group](https://groups.google.com/forum/#!forum/angleproject).
@@ -21,7 +23,7 @@
 ## Task 1: Monitor ANGLE CI and Try Testers
 
 Your first job is to keep the
-[ANGLE Try Waterfall](https://ci.chromium.org/p/chromium/g/angle.try/builders) healthy.  Some
+[ANGLE Try Waterfall](https://ci.chromium.org/p/chromium/g/tryserver.chromium.angle/builders) healthy.  Some
 failures are expected on this waterfall. Developers might be testing expectedly buggy code. But
 persistent flakiness and failures should be reported and reverted.
 
@@ -90,8 +92,19 @@
  * [Vulkan-Headers into ANGLE](https://autoroll.skia.org/r/vulkan-headers-angle-autoroll)
  * [Vulkan-ValidationLayers into ANGLE](https://autoroll.skia.org/r/vulkan-validation-layers-angle-autoroll)
 
-Please ensure these rollers are also healthy and unblocked. You can trigger manual rolls using the dashboards
-to land high-priority changes.
+Please ensure these rollers are also healthy and unblocked. You can trigger manual rolls using the
+dashboards to land high-priority changes.
+
+**NOTE: When Vulkan-Headers roll is broken:**
+
+The Vulkan-Tools, Vulkan-Loader, and Vulkan-ValidationLayers repos all depend on the Vulkan-Headers
+repo. When Vulkan-Headers updates, all of those repos have a roll process managed by LunarG to
+update them for the new Vulkan-Headers. This usually takes 2-3 business days after the
+Vulkan-Headers update. If Vulkan-Headers roll fails, pause the roller with a note that it should be
+re-enabled when the dependent repos have been updated for the latest Vulkan-Headers changes. This
+will require a manual roll if the two repos have to be rolled in unison. To perform a manual roll,
+create a CL that updates the DEPS file with the new SHA1 value from the desired checkout of each
+dependent repo. Once the manual roll lands, re-enable the auto-rollers for the relevant repos.
 
 The autoroller configurations live in the [skia/buildbot repository](https://skia.googlesource.com/buildbot/)
 in the [autoroll/config](https://skia.googlesource.com/buildbot/+/master/autoroll/config) folder.
@@ -99,3 +112,31 @@
 ## Task 4: ANGLE Standalone Testing
 
 See more detailed instructions on by following [this link](README.md).
+
+## Task 5: Monitor SwANGLE CI and Try Testers
+
+Most important task here is to keep healthy the 2 SwANGLE bots on ANGLE CQ,
+[linux-swangle-try-tot-angle-x64](https://luci-milo.appspot.com/p/chromium/builders/try/linux-swangle-try-tot-angle-x64)
+and
+[win-swangle-try-tot-angle-x86](https://luci-milo.appspot.com/p/chromium/builders/try/win-swangle-try-tot-angle-x86).
+As well as the 2 SwANGLE bots used for ANGLE rolls on Chromium CQ,
+[linux-swangle-try-x64](https://luci-milo.appspot.com/p/chromium/builders/try/linux-swangle-try-x64)
+and
+[win-swangle-try-x86](https://luci-milo.appspot.com/p/chromium/builders/try/win-swangle-try-x86).
+
+Same instructions as for [Task 1](#task-1_monitor-angle-ci-and-try-testers) apply here.
+Some failures on these bots may be due to SwiftShader changes, however.
+The possible ways to handle these failures are:
+1. If possible, suppress the failing tests in ANGLE, opening a bug to investigate these later.
+1. If it is clear that an ANGLE CL caused a regression,
+   consider whether reverting it or suppressing the failures is a better course of action.
+1. If a SwiftShader CL is suspected, and the breakage is too severe to be suppressed,
+   (a lot of tests fail in multiple suites),
+   it is possible to revert the responsible SwiftShader roll into Chromium
+   and open a SwiftShader [bug](http://go/swiftshaderbugs). SwiftShader rolls into Chromium
+   should fail afterwards, but if the bad roll manages to reland,
+   the [autoroller](https://autoroll.skia.org/r/swiftshader-chromium-autoroll) needs to be stopped.
+
+A lower priority task here is to keep healthy all the SwANGLE
+[CI](https://luci-milo.appspot.com/p/chromium/g/chromium.swangle/builders) and
+[Try](https://luci-milo.appspot.com/p/chromium/g/tryserver.chromium.swangle/builders) bots.
diff --git a/infra/README.md b/infra/README.md
index ea45ea4..0d4b56c 100644
--- a/infra/README.md
+++ b/infra/README.md
@@ -12,7 +12,7 @@
 
 See the pre-commit try waterfall here:
 
-[`https://ci.chromium.org/p/chromium/g/angle.try/builders`](https://ci.chromium.org/p/chromium/g/angle.try/builders)
+[`https://ci.chromium.org/p/angle/g/try/builders`](https://ci.chromium.org/p/angle/g/try/builders)
 
 We currently run pre-commit tests on:
 
diff --git a/infra/config/global/commit-queue.cfg b/infra/config/global/commit-queue.cfg
index c306800..9069bec 100644
--- a/infra/config/global/commit-queue.cfg
+++ b/infra/config/global/commit-queue.cfg
@@ -99,6 +99,9 @@
         name: "chromium/try/linux-angle-rel"
       }
       builders {
+        name: "chromium/try/linux-swangle-try-tot-angle-x64"
+      }
+      builders {
         name: "chromium/try/mac-angle-rel"
       }
       builders {
@@ -113,6 +116,9 @@
       builders {
         name: "chromium/try/win-angle-rel-64"
       }
+      builders {
+        name: "chromium/try/win-swangle-try-tot-angle-x86"
+      }
       retry_config {
         single_quota: 1
         global_quota: 2
diff --git a/samples/BUILD.gn b/samples/BUILD.gn
index 0147f4a..b0ce208 100644
--- a/samples/BUILD.gn
+++ b/samples/BUILD.gn
@@ -58,9 +58,10 @@
                            [
                              "cflags",
                              "defines",
+                             "deps",
                              "sources",
                            ])
-    deps = [ ":sample_util" ]
+    deps += [ ":sample_util" ]
     if (defined(invoker.data)) {
       deps += [ ":${target_name}_data" ]
     }
@@ -71,6 +72,10 @@
   }
 }
 
+set_defaults("angle_sample") {
+  deps = []
+}
+
 angle_sample("hello_triangle") {
   sources = [ "hello_triangle/HelloTriangle.cpp" ]
 }
@@ -188,6 +193,8 @@
           "capture_replay/angle_capture_context${_contextid}.h",
         ]
 
+    deps = [ "$angle_root:angle_compression" ]
+
     _data_path = rebase_path("capture_replay", root_out_dir)
     defines = [
       "ANGLE_CAPTURE_REPLAY_SAMPLE_DATA_DIR=\"${_data_path}\"",
diff --git a/samples/capture_replay/CaptureReplay.cpp b/samples/capture_replay/CaptureReplay.cpp
index c282476..a38c23b 100644
--- a/samples/capture_replay/CaptureReplay.cpp
+++ b/samples/capture_replay/CaptureReplay.cpp
@@ -9,6 +9,8 @@
 
 #include <functional>
 
+#include "util/frame_capture_utils.h"
+
 #define ANGLE_MACRO_STRINGIZE_AUX(a) #a
 #define ANGLE_MACRO_STRINGIZE(a) ANGLE_MACRO_STRINGIZE_AUX(a)
 #define ANGLE_MACRO_CONCAT_AUX(a, b) a##b
@@ -39,6 +41,10 @@
         std::string exeDir = angle::GetExecutableDirectory();
         if (!angle::SetCWD(exeDir.c_str()))
             return false;
+        if (kIsBinaryDataCompressed)
+        {
+            SetBinaryDataDecompressCallback(angle::DecompressBinaryData);
+        }
         SetBinaryDataDir(ANGLE_CAPTURE_REPLAY_SAMPLE_DATA_DIR);
         SetupContextReplay();
 
diff --git a/scripts/code_generation_hashes/ANGLE_format.json b/scripts/code_generation_hashes/ANGLE_format.json
index 0139154..1785532 100644
--- a/scripts/code_generation_hashes/ANGLE_format.json
+++ b/scripts/code_generation_hashes/ANGLE_format.json
@@ -1,14 +1,14 @@
 {
   "src/libANGLE/renderer/FormatID_autogen.h":
-    "24fdce4072d7f9e76337ffbe4c58b4ab",
+    "bbdb3beae2da4629e3583d6d014ebb2d",
   "src/libANGLE/renderer/Format_table_autogen.cpp":
-    "894eaa150949d32c563e94024312295d",
+    "ef632d9cf04b4ba6103f80b61ac26bc9",
   "src/libANGLE/renderer/angle_format.py":
     "32ba71942c0fd00e6807104f1bb80a3c",
   "src/libANGLE/renderer/angle_format_data.json":
     "b8bfe470c31b12b27f3a2bdb0288e4be",
   "src/libANGLE/renderer/angle_format_map.json":
-    "fad58117657b6bde9488a10d35872d45",
+    "c79d833aea7007c7d0d51cdaa9b265a6",
   "src/libANGLE/renderer/gen_angle_format_table.py":
     "8e349a643e81a028ebb54bde3756f9f7"
 }
\ No newline at end of file
diff --git a/scripts/code_generation_hashes/ANGLE_load_functions_table.json b/scripts/code_generation_hashes/ANGLE_load_functions_table.json
index af7876e..58dbe72 100644
--- a/scripts/code_generation_hashes/ANGLE_load_functions_table.json
+++ b/scripts/code_generation_hashes/ANGLE_load_functions_table.json
@@ -4,7 +4,7 @@
   "src/libANGLE/renderer/gen_load_functions_table.py":
     "9b4ea6bcb4eb4c43f48a097a9ec920f1",
   "src/libANGLE/renderer/load_functions_data.json":
-    "7df64a5481f55f3096aff11649d9992d",
+    "82e599f6a6cd9a314406f610f71dc660",
   "src/libANGLE/renderer/load_functions_table_autogen.cpp":
-    "82658e05a1019375501076c4043d6f82"
+    "7a594fed0385de81c402bcd3ff7f6412"
 }
\ No newline at end of file
diff --git a/scripts/code_generation_hashes/ANGLE_shader_translator.json b/scripts/code_generation_hashes/ANGLE_shader_translator.json
index 8cca82c..ce72f6e 100644
--- a/scripts/code_generation_hashes/ANGLE_shader_translator.json
+++ b/scripts/code_generation_hashes/ANGLE_shader_translator.json
@@ -4,15 +4,15 @@
   "src/compiler/translator/generate_parser.py":
     "566178ecdfae3a29803b3687fc518ebb",
   "src/compiler/translator/glslang.l":
-    "2f602a853e4c4d669edc3cc36a1a8c4a",
+    "76676b64d51f4312e8060f4a00bc8f1b",
   "src/compiler/translator/glslang.y":
-    "928cfcdd99877b5a289694a4057d5d76",
+    "609c38a1997b77a9affec84541daf9c9",
   "src/compiler/translator/glslang_lex_autogen.cpp":
-    "809307250ccc9a6c6d026da45b57dcec",
+    "edc229f6d1b48f8588301219df80760e",
   "src/compiler/translator/glslang_tab_autogen.cpp":
-    "f693228f495aac4629ee8e30c12dc62f",
+    "8872811534b4e8aeef0df354bbd05044",
   "src/compiler/translator/glslang_tab_autogen.h":
-    "286139e7a8f2dd3458fbf39bff09d2ad",
+    "1bb42872dd5fd0a6f647201b142b67b6",
   "tools/flex-bison/linux/bison.sha1":
     "efa86001f00e7bcfdbe899dd15fc88e0",
   "tools/flex-bison/linux/flex.sha1":
diff --git a/scripts/code_generation_hashes/D3D11_format.json b/scripts/code_generation_hashes/D3D11_format.json
index d5f651f..9451d6c 100644
--- a/scripts/code_generation_hashes/D3D11_format.json
+++ b/scripts/code_generation_hashes/D3D11_format.json
@@ -6,7 +6,7 @@
   "src/libANGLE/renderer/d3d/d3d11/texture_format_data.json":
     "c80708c18348fd89a3b918e58e74c1f8",
   "src/libANGLE/renderer/d3d/d3d11/texture_format_map.json":
-    "e9dfbd51ff183809f595f8fc5db9c217",
+    "d45aee3519b8c9a15411617bbb00c77f",
   "src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp":
-    "f48864159c3a1fe6ca7567e3eb8215fb"
+    "ef6da258ffbd0245d6a592f5c0f8b455"
 }
\ No newline at end of file
diff --git a/scripts/code_generation_hashes/DXGI_format.json b/scripts/code_generation_hashes/DXGI_format.json
index 12ef84e..1628f1e 100644
--- a/scripts/code_generation_hashes/DXGI_format.json
+++ b/scripts/code_generation_hashes/DXGI_format.json
@@ -2,7 +2,7 @@
   "src/libANGLE/renderer/angle_format.py":
     "32ba71942c0fd00e6807104f1bb80a3c",
   "src/libANGLE/renderer/angle_format_map.json":
-    "fad58117657b6bde9488a10d35872d45",
+    "c79d833aea7007c7d0d51cdaa9b265a6",
   "src/libANGLE/renderer/d3d/d3d11/dxgi_format_data.json":
     "3428e4761ccd05f960adffd6ccbd86c5",
   "src/libANGLE/renderer/d3d/d3d11/dxgi_format_map_autogen.cpp":
diff --git a/scripts/code_generation_hashes/GL_EGL_WGL_loader.json b/scripts/code_generation_hashes/GL_EGL_WGL_loader.json
index ae51152..9e471fc 100644
--- a/scripts/code_generation_hashes/GL_EGL_WGL_loader.json
+++ b/scripts/code_generation_hashes/GL_EGL_WGL_loader.json
@@ -2,29 +2,29 @@
   "scripts/egl.xml":
     "842e24514c4cfe09fba703c17a0fd292",
   "scripts/egl_angle_ext.xml":
-    "63f18dc9b7183ead4ddd3dfd1571973a",
+    "854e99785af19f8f4eea4f73005a0451",
   "scripts/generate_loader.py":
     "792c41d7ae93a4518f0c73e45626d19b",
   "scripts/gl.xml":
     "e74a595068cbdd6064300be1e71b7cc9",
   "scripts/gl_angle_ext.xml":
-    "872ecabf7ca7767c7801ba835ddbd1eb",
+    "079cc4829de7ce638faf7bbf66e141ad",
   "scripts/registry_xml.py":
-    "06c837b395c8cd0c4fc937b193365042",
+    "d48b9fcf30e2f98210f0b98824e7bd49",
   "scripts/wgl.xml":
     "aa96419c582af2f6673430e2847693f4",
   "src/libEGL/egl_loader_autogen.cpp":
-    "6de27557530d1dff3780d83745c0a0fd",
+    "64cb617726751808af6a64607cba39eb",
   "src/libEGL/egl_loader_autogen.h":
-    "2fca11a29bb6e5cadb25d4862360ddd8",
+    "e79b89b5f1f704383c96dbc99124efff",
   "util/egl_loader_autogen.cpp":
-    "780b317fbd6ac03e300a7ee0122ab3cf",
+    "44c9d17a658aec04dfa7b57fca5386a0",
   "util/egl_loader_autogen.h":
-    "55b54071e61b3e7beab28178dc20fd28",
+    "e0ae6f29162d13d8d825fc9cd58baf94",
   "util/gles_loader_autogen.cpp":
-    "1eeaa7649d906a8ff5d8a7889f983071",
+    "b73fa86312a71c76f6a8402548d21204",
   "util/gles_loader_autogen.h":
-    "1605f0b90bb32b01ccd2470db574cdf6",
+    "f5df94d354db0d26275b1828f4083633",
   "util/windows/wgl_loader_autogen.cpp":
     "c0d9a65eaa9aac356c6fd3f88638d2be",
   "util/windows/wgl_loader_autogen.h":
diff --git a/scripts/code_generation_hashes/GL_EGL_entry_points.json b/scripts/code_generation_hashes/GL_EGL_entry_points.json
index d4f41c7..4477c4e 100644
--- a/scripts/code_generation_hashes/GL_EGL_entry_points.json
+++ b/scripts/code_generation_hashes/GL_EGL_entry_points.json
@@ -2,7 +2,7 @@
   "scripts/egl.xml":
     "842e24514c4cfe09fba703c17a0fd292",
   "scripts/egl_angle_ext.xml":
-    "63f18dc9b7183ead4ddd3dfd1571973a",
+    "854e99785af19f8f4eea4f73005a0451",
   "scripts/entry_point_packed_gl_enums.json":
     "63f508a08611e75810daedb297dca0e9",
   "scripts/generate_entry_points.py":
@@ -10,9 +10,9 @@
   "scripts/gl.xml":
     "e74a595068cbdd6064300be1e71b7cc9",
   "scripts/gl_angle_ext.xml":
-    "872ecabf7ca7767c7801ba835ddbd1eb",
+    "079cc4829de7ce638faf7bbf66e141ad",
   "scripts/registry_xml.py":
-    "06c837b395c8cd0c4fc937b193365042",
+    "d48b9fcf30e2f98210f0b98824e7bd49",
   "scripts/wgl.xml":
     "aa96419c582af2f6673430e2847693f4",
   "src/libANGLE/Context_gl_1_0_autogen.h":
@@ -64,7 +64,7 @@
   "src/libANGLE/Context_gles_3_2_autogen.h":
     "e26f7ee7b59a89a4f5337171816b8336",
   "src/libANGLE/Context_gles_ext_autogen.h":
-    "3530773b0510e590e1120d4fccefe627",
+    "c4882553e6cef2a53b922ebe9ec88556",
   "src/libANGLE/capture_gles_1_0_autogen.cpp":
     "96fc0f501e2e696ab911dad8b400dfb2",
   "src/libANGLE/capture_gles_1_0_autogen.h":
@@ -86,19 +86,19 @@
   "src/libANGLE/capture_gles_3_2_autogen.h":
     "2fbca7168541c2e9ff8a055c256f8531",
   "src/libANGLE/capture_gles_ext_autogen.cpp":
-    "a98b5bb10ecf372e6e269e29d74ea47b",
+    "96cb5043ebfce349c89ece3afec6d9f8",
   "src/libANGLE/capture_gles_ext_autogen.h":
-    "f051219bf14f07e0dad99362570db4c1",
+    "f6604f279558cf5d965e3dce61e0dc91",
   "src/libANGLE/entry_points_enum_autogen.cpp":
-    "e2f6704ac7f7bec6ca042b4e9dfd3f6e",
+    "66f09d4f9e6f8e83f2f6f0cf8fc3f3d9",
   "src/libANGLE/entry_points_enum_autogen.h":
-    "20e8b2073f2fcc6d06030cd3488180ac",
+    "872069598e67c358ee4cbb14260d28bf",
   "src/libANGLE/frame_capture_replay_autogen.cpp":
     "c0d57704c21e0032a486a6195ddb87e4",
   "src/libANGLE/frame_capture_utils_autogen.cpp":
-    "cf2257638fb6df56061721775efda084",
+    "7a4f16a96714e43faaa0bef299ad7028",
   "src/libANGLE/frame_capture_utils_autogen.h":
-    "1cd48ca4faeba4379456943d002ea412",
+    "86e368be9083fa542a08c1c143c8b87e",
   "src/libANGLE/validationES1_autogen.h":
     "c8edb0a5b26303bf7c4692b9d0b05c1f",
   "src/libANGLE/validationES2_autogen.h":
@@ -110,7 +110,7 @@
   "src/libANGLE/validationES3_autogen.h":
     "86ba503835328438158d9a464943f3bd",
   "src/libANGLE/validationESEXT_autogen.h":
-    "791c9d4c47d43a8a66b1eb8e8de785fb",
+    "a48272ec357016df88899f85ad33d0ef",
   "src/libANGLE/validationGL11_autogen.h":
     "aadd145c1404de9c34d6b7c00404f10f",
   "src/libANGLE/validationGL12_autogen.h":
@@ -250,15 +250,15 @@
   "src/libGLESv2/entry_points_gles_3_2_autogen.h":
     "5798aa0a73af1d4ba5dfe99b6217a247",
   "src/libGLESv2/entry_points_gles_ext_autogen.cpp":
-    "1151ad20de418b5d06d20e21e6c0bcc8",
+    "b10a0a6c1becd3bfc8149c29dfc268b1",
   "src/libGLESv2/entry_points_gles_ext_autogen.h":
-    "d79b251c643deed5f26b5768f1af2a50",
+    "b564ae1ca4e312bd9d8138f593d8110c",
   "src/libGLESv2/libGLESv2_autogen.cpp":
-    "e4c15c09605f1e83452f73b943a9d7d4",
+    "0f02d0cef8752453648ea10862a63535",
   "src/libGLESv2/libGLESv2_autogen.def":
-    "e7d40f9f0e47cfcd0e90900a4d279d6c",
+    "266fc07e2657fc96eabb4ae29f330e07",
   "src/libGLESv2/libGLESv2_no_capture_autogen.def":
-    "bd298c16f94e5b259c92bfb5ffa3991d",
+    "f67114b49f9dcd1b7f9d5abaf0dfe190",
   "src/libGLESv2/libGLESv2_with_capture_autogen.def":
-    "3cd12ebdc7f21923c6f2357f94a13348"
+    "5e272fd38bfe01cf0a31def20d9b70e8"
 }
\ No newline at end of file
diff --git a/scripts/code_generation_hashes/GL_format_map.json b/scripts/code_generation_hashes/GL_format_map.json
index 3418db1..6ecc5fd 100644
--- a/scripts/code_generation_hashes/GL_format_map.json
+++ b/scripts/code_generation_hashes/GL_format_map.json
@@ -1,10 +1,10 @@
 {
   "src/libANGLE/es3_format_type_combinations.json":
-    "b44b222c27eea6839c0da3076ee540fc",
+    "3c4288394162b20f5ccdc29d3b4eecbb",
   "src/libANGLE/format_map_autogen.cpp":
-    "e0dedb4a47ca7eab2d33d20430a30d05",
+    "baae22cedf176b776d0a2331abb4abcc",
   "src/libANGLE/format_map_data.json":
-    "2edab4db12a1cc131f26e0e5680b7d0c",
+    "742cf47524160757a2cec43116dc153c",
   "src/libANGLE/gen_format_map.py":
     "38320d844e6629e09afc5ccdc484e9aa",
   "src/libANGLE/renderer/angle_format.py":
diff --git a/scripts/code_generation_hashes/GLenum_value_to_string_map.json b/scripts/code_generation_hashes/GLenum_value_to_string_map.json
index b15dca2..447f623 100644
--- a/scripts/code_generation_hashes/GLenum_value_to_string_map.json
+++ b/scripts/code_generation_hashes/GLenum_value_to_string_map.json
@@ -1,14 +1,14 @@
 {
   "scripts/gen_gl_enum_utils.py":
-    "f25cdc74b57d10a1cbc4194a72e971af",
+    "af9ec09ac89a73c9fe0dd510a1db4b38",
   "scripts/gl.xml":
     "e74a595068cbdd6064300be1e71b7cc9",
   "scripts/gl_angle_ext.xml":
-    "872ecabf7ca7767c7801ba835ddbd1eb",
+    "079cc4829de7ce638faf7bbf66e141ad",
   "scripts/registry_xml.py":
-    "06c837b395c8cd0c4fc937b193365042",
+    "d48b9fcf30e2f98210f0b98824e7bd49",
   "src/libANGLE/gl_enum_utils_autogen.cpp":
-    "cfc52f413272c061ee4a037876792726",
+    "48627c0865d15bf4014327de5858d3c5",
   "src/libANGLE/gl_enum_utils_autogen.h":
     "dd54f34be733affcb994fc315c3b972d"
 }
\ No newline at end of file
diff --git a/scripts/code_generation_hashes/OpenGL_dispatch_table.json b/scripts/code_generation_hashes/OpenGL_dispatch_table.json
index a409205..c21ede9 100644
--- a/scripts/code_generation_hashes/OpenGL_dispatch_table.json
+++ b/scripts/code_generation_hashes/OpenGL_dispatch_table.json
@@ -4,15 +4,15 @@
   "src/libANGLE/renderer/angle_format.py":
     "32ba71942c0fd00e6807104f1bb80a3c",
   "src/libANGLE/renderer/gl/DispatchTableGL_autogen.cpp":
-    "a791d8035d16b98b6e139a159968117c",
+    "0947622fea50d18eb9f0557ca4c85bfa",
   "src/libANGLE/renderer/gl/DispatchTableGL_autogen.h":
-    "175946b4d8e0e7ce161f97a2244c1283",
+    "1c6824d0c5499b3c1c765d25d942c896",
   "src/libANGLE/renderer/gl/generate_gl_dispatch_table.py":
     "4f19a7eee17679b3a0ad4abad6fab2c9",
   "src/libANGLE/renderer/gl/gl_bindings_data.json":
-    "e870a4d86dc69e52dcab9afd78a47c9b",
+    "6ae55e912777b695f27b9dd99bce1d98",
   "src/libANGLE/renderer/gl/null_functions.cpp":
-    "93ce4fd50259c693a34c9940b33a7822",
+    "0036f8600c968bb53f7bb311cc54041c",
   "src/libANGLE/renderer/gl/null_functions.h":
-    "d281ba915f4be744c7d519f3c6a1b84d"
+    "edba419bcbfcc1830673e8bafd1a4bfb"
 }
\ No newline at end of file
diff --git a/scripts/code_generation_hashes/Vulkan_format.json b/scripts/code_generation_hashes/Vulkan_format.json
index 878ccc5..90dc06e 100644
--- a/scripts/code_generation_hashes/Vulkan_format.json
+++ b/scripts/code_generation_hashes/Vulkan_format.json
@@ -2,11 +2,11 @@
   "src/libANGLE/renderer/angle_format.py":
     "32ba71942c0fd00e6807104f1bb80a3c",
   "src/libANGLE/renderer/angle_format_map.json":
-    "fad58117657b6bde9488a10d35872d45",
+    "c79d833aea7007c7d0d51cdaa9b265a6",
   "src/libANGLE/renderer/vulkan/gen_vk_format_table.py":
     "d8a0f2278c09a49049a73930b9da3719",
   "src/libANGLE/renderer/vulkan/vk_format_map.json":
-    "893950f630c95c653ec907901939afd8",
+    "738c8dc36fbe212669944e88ae918f9c",
   "src/libANGLE/renderer/vulkan/vk_format_table_autogen.cpp":
-    "4557259cadb45c9db3301039cda3a7bc"
+    "383749c786e957bdbbbce9d8b5c2441a"
 }
\ No newline at end of file
diff --git a/scripts/code_generation_hashes/Vulkan_mandatory_format_support_table.json b/scripts/code_generation_hashes/Vulkan_mandatory_format_support_table.json
index f9f0d52..f31c021 100644
--- a/scripts/code_generation_hashes/Vulkan_mandatory_format_support_table.json
+++ b/scripts/code_generation_hashes/Vulkan_mandatory_format_support_table.json
@@ -8,5 +8,5 @@
   "src/libANGLE/renderer/vulkan/vk_mandatory_format_support_table_autogen.cpp":
     "8bfd8a3857c2b9062d7ada46c7d27bcf",
   "third_party/vulkan-headers/src/registry/vk.xml":
-    "0ecdb9708d2a1ddea2359ec7254981fa"
+    "f3f753be7339f84d8c344662aa4f7422"
 }
\ No newline at end of file
diff --git a/scripts/code_generation_hashes/proc_table.json b/scripts/code_generation_hashes/proc_table.json
index 1a5e64c..0048033 100644
--- a/scripts/code_generation_hashes/proc_table.json
+++ b/scripts/code_generation_hashes/proc_table.json
@@ -2,19 +2,19 @@
   "scripts/egl.xml":
     "842e24514c4cfe09fba703c17a0fd292",
   "scripts/egl_angle_ext.xml":
-    "63f18dc9b7183ead4ddd3dfd1571973a",
+    "854e99785af19f8f4eea4f73005a0451",
   "scripts/gen_proc_table.py":
     "24dbcc78fd3f000f58ca98237ccc0da4",
   "scripts/gl.xml":
     "e74a595068cbdd6064300be1e71b7cc9",
   "scripts/gl_angle_ext.xml":
-    "872ecabf7ca7767c7801ba835ddbd1eb",
+    "079cc4829de7ce638faf7bbf66e141ad",
   "scripts/registry_xml.py":
-    "06c837b395c8cd0c4fc937b193365042",
+    "d48b9fcf30e2f98210f0b98824e7bd49",
   "scripts/wgl.xml":
     "aa96419c582af2f6673430e2847693f4",
   "src/libGL/proc_table_wgl_autogen.cpp":
     "03c05f20c57c1de822b0ddaf6d4f9607",
   "src/libGLESv2/proc_table_egl_autogen.cpp":
-    "29dbd578aeded8fb3412ab2adc3a1cde"
+    "0154d2734e6d89520d3697890df2164e"
 }
\ No newline at end of file
diff --git a/scripts/egl_angle_ext.xml b/scripts/egl_angle_ext.xml
index df089db..7206573 100644
--- a/scripts/egl_angle_ext.xml
+++ b/scripts/egl_angle_ext.xml
@@ -34,7 +34,7 @@
             <param>const <ptype>EGLAttrib</ptype> *<name>attrib_list</name></param>
         </command>
         <command>
-            <proto><ptype>EGLBoolean</ptype> <name>eglGetMscRateCHROMIUM</name></proto>
+            <proto><ptype>EGLBoolean</ptype> <name>eglGetMscRateANGLE</name></proto>
             <param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
             <param><ptype>EGLSurface</ptype> <name>surface</name></param>
             <param><ptype>EGLint</ptype> *<name>numerator</name></param>
@@ -118,7 +118,11 @@
         <extension name="EGL_CHROMIUM_sync_control" supported="egl">
             <require>
                 <command name="eglGetSyncValuesCHROMIUM"/>
-                <command name="eglGetMscRateCHROMIUM"/>
+            </require>
+        </extension>
+        <extension name="EGL_ANGLE_sync_control_rate" supported="egl">
+            <require>
+                <command name="eglGetMscRateANGLE"/>
             </require>
         </extension>
         <extension name="EGL_ANGLE_program_cache_control" supported="egl">
diff --git a/scripts/gen_gl_enum_utils.py b/scripts/gen_gl_enum_utils.py
index c4317f6..0d614f5 100755
--- a/scripts/gen_gl_enum_utils.py
+++ b/scripts/gen_gl_enum_utils.py
@@ -73,6 +73,11 @@
 {{
     std::stringstream st;
 
+    if (value == 0)
+    {{
+        return "0";
+    }}
+
     const angle::BitSet<32> bitSet(value);
     bool first = true;
     for (const auto index : bitSet)
diff --git a/scripts/generate_android_bp.py b/scripts/generate_android_bp.py
index fdc953d..37f5273 100644
--- a/scripts/generate_android_bp.py
+++ b/scripts/generate_android_bp.py
@@ -365,6 +365,8 @@
                                                              target_info['args'])
     bp['cmd'] = ' '.join(cmd)
 
+    bp['sdk_version'] = sdk_version
+
     return (blueprint_type, bp)
 
 
@@ -445,6 +447,7 @@
                 '--extra-packages com.android.angle.common',
             ],
             'srcs': [':ANGLE_srcs'],
+            'plugins': ['java_api_finder',],
             'privileged':
                 True,
             'owner':
@@ -488,7 +491,7 @@
     for (blueprint_type, blueprint_data) in blueprint_targets:
         write_blueprint(output, blueprint_type, blueprint_data)
 
-    print '\n'.join(output)
+    print('\n'.join(output))
 
 
 if __name__ == '__main__':
diff --git a/scripts/gl_angle_ext.xml b/scripts/gl_angle_ext.xml
index cc09820..344a1fa 100644
--- a/scripts/gl_angle_ext.xml
+++ b/scripts/gl_angle_ext.xml
@@ -39,174 +39,6 @@
             <param><ptype>GLenum</ptype> <name>matrixMode</name></param>
         </command>
         <command>
-            <proto>GLuint <name>glGenPathsCHROMIUM</name></proto>
-            <param><ptype>GLsizei</ptype> <name>range</name></param>
-        </command>
-        <command>
-            <proto>void <name>glDeletePathsCHROMIUM</name></proto>
-            <param><ptype>GLuint</ptype> <name>first</name></param>
-            <param><ptype>GLsizei</ptype> <name>range</name></param>
-        </command>
-        <command>
-            <proto>GLboolean <name>glIsPathCHROMIUM</name></proto>
-            <param><ptype>GLuint</ptype> <name>path</name></param>
-        </command>
-        <command>
-            <proto>void <name>glPathCommandsCHROMIUM</name></proto>
-            <param><ptype>GLuint</ptype> <name>path</name></param>
-            <param><ptype>GLsizei</ptype> <name>numCommands</name></param>
-            <param><ptype>const GLubyte *</ptype> <name>commands</name></param>
-            <param><ptype>GLsizei</ptype> <name>numCoords</name></param>
-            <param><ptype>GLenum</ptype> <name>coordType</name></param>
-            <param><ptype>const void*</ptype> <name>coords</name></param>
-        </command>
-        <command>
-            <proto>void <name>glPathParameterfCHROMIUM</name></proto>
-            <param><ptype>GLuint</ptype> <name>path</name></param>
-            <param><ptype>GLenum</ptype> <name>pname</name></param>
-            <param><ptype>GLfloat</ptype> <name>value</name></param>
-        </command>
-        <command>
-            <proto>void <name>glPathParameteriCHROMIUM</name></proto>
-            <param><ptype>GLuint</ptype> <name>path</name></param>
-            <param><ptype>GLenum</ptype> <name>pname</name></param>
-            <param><ptype>GLint</ptype> <name>value</name></param>
-        </command>
-        <command>
-            <proto>void <name>glGetPathParameterfvCHROMIUM</name></proto>
-            <param><ptype>GLuint</ptype> <name>path</name></param>
-            <param><ptype>GLenum</ptype> <name>pname</name></param>
-            <param><ptype>GLfloat *</ptype> <name>value</name></param>
-        </command>
-        <command>
-            <proto>void <name>glGetPathParameterivCHROMIUM</name></proto>
-            <param><ptype>GLuint</ptype> <name>path</name></param>
-            <param><ptype>GLenum</ptype> <name>pname</name></param>
-            <param><ptype>GLint *</ptype> <name>value</name></param>
-        </command>
-        <command>
-            <proto>void <name>glPathStencilFuncCHROMIUM</name></proto>
-            <param><ptype>GLenum</ptype> <name>func</name></param>
-            <param><ptype>GLint</ptype> <name>ref</name></param>
-            <param><ptype>GLuint</ptype> <name>mask</name></param>
-        </command>
-        <command>
-            <proto>void <name>glStencilFillPathCHROMIUM</name></proto>
-            <param><ptype>GLuint</ptype> <name>path</name></param>
-            <param><ptype>GLenum</ptype> <name>fillMode</name></param>
-            <param><ptype>GLuint</ptype> <name>mask</name></param>
-        </command>
-        <command>
-            <proto>void <name>glStencilStrokePathCHROMIUM</name></proto>
-            <param><ptype>GLuint</ptype> <name>path</name></param>
-            <param><ptype>GLint</ptype> <name>reference</name></param>
-            <param><ptype>GLuint</ptype> <name>mask</name></param>
-        </command>
-        <command>
-            <proto>void <name>glCoverFillPathCHROMIUM</name></proto>
-            <param><ptype>GLuint</ptype> <name>path</name></param>
-            <param><ptype>GLenum</ptype> <name>coverMode</name></param>
-        </command>
-        <command>
-            <proto>void <name>glCoverStrokePathCHROMIUM</name></proto>
-            <param><ptype>GLuint</ptype> <name>path</name></param>
-            <param><ptype>GLenum</ptype> <name>coverMode</name></param>
-        </command>
-        <command>
-            <proto>void <name>glStencilThenCoverFillPathCHROMIUM</name></proto>
-            <param><ptype>GLuint</ptype> <name>path</name></param>
-            <param><ptype>GLenum</ptype> <name>fillMode</name></param>
-            <param><ptype>GLuint</ptype> <name>mask</name></param>
-            <param><ptype>GLenum</ptype> <name>coverMode</name></param>
-        </command>
-        <command>
-            <proto>void <name>glStencilThenCoverStrokePathCHROMIUM</name></proto>
-            <param><ptype>GLuint</ptype> <name>path</name></param>
-            <param><ptype>GLint</ptype> <name>reference</name></param>
-            <param><ptype>GLuint</ptype> <name>mask</name></param>
-            <param><ptype>GLenum</ptype> <name>coverMode</name></param>
-        </command>
-        <command>
-            <proto>void <name>glCoverFillPathInstancedCHROMIUM</name></proto>
-            <param><ptype>GLsizei</ptype> <name>numPath</name></param>
-            <param><ptype>GLenum</ptype> <name>pathNameType</name></param>
-            <param><ptype>const void *</ptype> <name>paths</name></param>
-            <param><ptype>GLuint</ptype> <name>pathBase</name></param>
-            <param><ptype>GLenum</ptype> <name>coverMode</name></param>
-            <param><ptype>GLenum</ptype> <name>transformType</name></param>
-            <param><ptype>const GLfloat *</ptype> <name>transformValues</name></param>
-        </command>
-        <command>
-            <proto>void <name>glCoverStrokePathInstancedCHROMIUM</name></proto>
-            <param><ptype>GLsizei</ptype> <name>numPath</name></param>
-            <param><ptype>GLenum</ptype> <name>pathNameType</name></param>
-            <param><ptype>const void *</ptype> <name>paths</name></param>
-            <param><ptype>GLuint</ptype> <name>pathBase</name></param>
-            <param><ptype>GLenum</ptype> <name>coverMode</name></param>
-            <param><ptype>GLenum</ptype> <name>transformType</name></param>
-            <param><ptype>const GLfloat *</ptype> <name>transformValues</name></param>
-        </command>
-        <command>
-            <proto>void <name>glStencilStrokePathInstancedCHROMIUM</name></proto>
-            <param><ptype>GLsizei</ptype> <name>numPath</name></param>
-            <param><ptype>GLenum</ptype> <name>pathNameType</name></param>
-            <param><ptype>const void *</ptype> <name>paths</name></param>
-            <param><ptype>GLuint</ptype> <name>pathBase</name></param>
-            <param><ptype>GLint</ptype> <name>reference</name></param>
-            <param><ptype>GLuint</ptype> <name>mask</name></param>
-            <param><ptype>GLenum</ptype> <name>transformType</name></param>
-            <param><ptype>const GLfloat *</ptype> <name>transformValues</name></param>
-        </command>
-        <command>
-            <proto>void <name>glStencilFillPathInstancedCHROMIUM</name></proto>
-            <param><ptype>GLsizei</ptype> <name>numPaths</name></param>
-            <param><ptype>GLenum</ptype> <name>pathNameType</name></param>
-            <param><ptype>const void *</ptype> <name>paths</name></param>
-            <param><ptype>GLuint</ptype> <name>pathBase</name></param>
-            <param><ptype>GLenum</ptype> <name>fillMode</name></param>
-            <param><ptype>GLuint</ptype> <name>mask</name></param>
-            <param><ptype>GLenum</ptype> <name>transformType</name></param>
-            <param><ptype>const GLfloat *</ptype> <name>transformValues</name></param>
-        </command>
-        <command>
-            <proto>void <name>glStencilThenCoverFillPathInstancedCHROMIUM</name></proto>
-            <param><ptype>GLsizei</ptype> <name>numPaths</name></param>
-            <param><ptype>GLenum</ptype> <name>pathNameType</name></param>
-            <param><ptype>const void *</ptype> <name>paths</name></param>
-            <param><ptype>GLuint</ptype> <name>pathBase</name></param>
-            <param><ptype>GLenum</ptype> <name>fillMode</name></param>
-            <param><ptype>GLuint</ptype> <name>mask</name></param>
-            <param><ptype>GLenum</ptype> <name>coverMode</name></param>
-            <param><ptype>GLenum</ptype> <name>transformType</name></param>
-            <param><ptype>const GLfloat *</ptype> <name>transformValues</name></param>
-        </command>
-        <command>
-            <proto>void <name>glStencilThenCoverStrokePathInstancedCHROMIUM</name></proto>
-            <param><ptype>GLsizei</ptype> <name>numPaths</name></param>
-            <param><ptype>GLenum</ptype> <name>pathNameType</name></param>
-            <param><ptype>const void *</ptype> <name>paths</name></param>
-            <param><ptype>GLuint</ptype> <name>pathBase</name></param>
-            <param><ptype>GLint</ptype> <name>reference</name></param>
-            <param><ptype>GLuint</ptype> <name>mask</name></param>
-            <param><ptype>GLenum</ptype> <name>coverMode</name></param>
-            <param><ptype>GLenum</ptype> <name>transformType</name></param>
-            <param><ptype>const GLfloat *</ptype> <name>transformValues</name></param>
-        </command>
-        <command>
-        <proto>void <name>glBindFragmentInputLocationCHROMIUM</name></proto>
-            <param><ptype>GLuint</ptype> <name>programs</name></param>
-            <param><ptype>GLint</ptype> <name>location</name></param>
-            <param><ptype>const GLchar *</ptype> <name>name</name></param>
-        </command>
-        <command>
-        <proto>void <name>glProgramPathFragmentInputGenCHROMIUM</name></proto>
-            <param><ptype>GLuint</ptype> <name>program</name></param>
-            <param><ptype>GLint</ptype> <name>location</name></param>
-            <param><ptype>GLenum</ptype> <name>genMode</name></param>
-            <param><ptype>GLint</ptype> <name>components</name></param>
-            <param><ptype>const GLfloat *</ptype> <name>coeffs</name></param>
-        </command>
-        <command>
         <proto>void <name>glCopyTextureCHROMIUM</name></proto>
             <param><ptype>GLuint</ptype> <name>sourceId</name></param>
             <param><ptype>GLint</ptype> <name>sourceLevel</name></param>
@@ -1010,38 +842,9 @@
         </extension>
         <extension name="GL_CHROMIUM_framebuffer_mixed_samples" supported='gles2'>
             <require>
-                <command name="glMatrixLoadfCHROMIUM"/>
-                <command name="glMatrixLoadIdentityCHROMIUM"/>
                 <command name="glCoverageModulationCHROMIUM"/>
             </require>
         </extension>
-        <extension name="GL_CHROMIUM_path_rendering" supported='gles2'>
-        <require>
-            <command name="glGenPathsCHROMIUM"/>
-            <command name="glDeletePathsCHROMIUM"/>
-            <command name="glIsPathCHROMIUM"/>
-            <command name="glPathCommandsCHROMIUM"/>
-            <command name="glPathParameterfCHROMIUM"/>
-            <command name="glPathParameteriCHROMIUM"/>
-            <command name="glGetPathParameterfvCHROMIUM"/>
-            <command name="glGetPathParameterivCHROMIUM"/>
-            <command name="glPathStencilFuncCHROMIUM"/>
-            <command name="glStencilFillPathCHROMIUM"/>
-            <command name="glStencilStrokePathCHROMIUM"/>
-            <command name="glCoverFillPathCHROMIUM"/>
-            <command name="glCoverStrokePathCHROMIUM"/>
-            <command name="glStencilThenCoverFillPathCHROMIUM"/>
-            <command name="glStencilThenCoverStrokePathCHROMIUM"/>
-            <command name="glCoverFillPathInstancedCHROMIUM"/>
-            <command name="glCoverStrokePathInstancedCHROMIUM"/>
-            <command name="glStencilFillPathInstancedCHROMIUM"/>
-            <command name="glStencilStrokePathInstancedCHROMIUM"/>
-            <command name="glStencilThenCoverFillPathInstancedCHROMIUM"/>
-            <command name="glStencilThenCoverStrokePathInstancedCHROMIUM"/>
-            <command name="glBindFragmentInputLocationCHROMIUM"/>
-            <command name="glProgramPathFragmentInputGenCHROMIUM"/>
-        </require>
-        </extension>
         <extension name="GL_CHROMIUM_copy_texture" supported='gles2'>
             <require>
                 <command name="glCopyTextureCHROMIUM"/>
diff --git a/scripts/registry_xml.py b/scripts/registry_xml.py
index 87ca969..8054579 100644
--- a/scripts/registry_xml.py
+++ b/scripts/registry_xml.py
@@ -88,10 +88,12 @@
     "GL_EXT_texture_filter_anisotropic",
     "GL_EXT_texture_format_BGRA8888",
     "GL_EXT_texture_storage",
+    "GL_EXT_texture_sRGB_R8",
     "GL_KHR_debug",
     "GL_KHR_parallel_shader_compile",
     "GL_NV_fence",
     "GL_OES_compressed_ETC1_RGB8_texture",
+    "GL_EXT_compressed_ETC1_RGB8_sub_texture",
     "GL_OES_depth32",
     "GL_OES_draw_buffers_indexed",
     "GL_OES_draw_elements_base_vertex",
@@ -128,8 +130,10 @@
     "EGL_ANGLE_swap_with_frame_token",
     "EGL_ANGLE_window_fixed_size",
     "EGL_CHROMIUM_sync_control",
+    "EGL_ANGLE_sync_control_rate",
     "EGL_EXT_create_context_robustness",
     "EGL_EXT_device_query",
+    "EGL_EXT_image_gl_colorspace",
     "EGL_EXT_pixel_format_float",
     "EGL_EXT_platform_base",
     "EGL_EXT_platform_device",
diff --git a/scripts/roll_aosp.sh b/scripts/roll_aosp.sh
index 7fcbd4b..5580074 100755
--- a/scripts/roll_aosp.sh
+++ b/scripts/roll_aosp.sh
@@ -6,8 +6,6 @@
 #
 # Generates a roll CL within the ANGLE repository of AOSP.
 
-git merge -X theirs aosp/upstream-mirror
-
 deps=(
     "third_party/spirv-tools/src"
     "third_party/glslang/src"
@@ -15,11 +13,12 @@
     "third_party/vulkan-headers/src"
     "third_party/jsoncpp"
     "third_party/jsoncpp/source"
+    "third_party/VulkanMemoryAllocator"
 )
 
 # Delete dep directories so that gclient can check them out
 for dep in ${deps[@]}; do
-    rm -rf --preserve-root $dep
+    rm -rf $dep
 done
 
 # Sync all of ANGLE's deps so that 'gn gen' works
@@ -68,7 +67,18 @@
 # Delete the .git files in each dep so that it can be added to this repo. Some deps like jsoncpp
 # have multiple layers of deps so delete everything before adding them.
 for dep in ${deps[@]}; do
-    rm -rf --preserve-root $dep/.git
+    rm -rf $dep/.git
+done
+
+extra_removal_files=(
+    # The jsoncpp OWNERS and VulkanMemoryAllocator file contains users that have not logged into
+    # the Android gerrit so it fails to upload.
+    "third_party/jsoncpp/OWNERS"
+    "third_party/VulkanMemoryAllocator/OWNERS"
+)
+
+for removal_file in ${extra_removal_files[@]}; do
+    rm $removal_file
 done
 
 for dep in ${deps[@]}; do
diff --git a/src/android_system_settings/src/com/android/angle/AndroidManifest.xml b/src/android_system_settings/src/com/android/angle/AndroidManifest.xml
index ea5b445..41bfa0c 100644
--- a/src/android_system_settings/src/com/android/angle/AndroidManifest.xml
+++ b/src/android_system_settings/src/com/android/angle/AndroidManifest.xml
@@ -49,6 +49,21 @@
                 <action android:name="android.app.action.ANGLE_FOR_ANDROID" />
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
+
+            <intent-filter>
+                <action android:name="android.service.quicksettings.action.QS_TILE_PREFERENCES" />
+            </intent-filter>
+
+            <!-- Mark this fragment as a dynamic setting in the development category. -->
+            <intent-filter>
+                <action android:name="com.android.settings.action.IA_SETTINGS" />
+            </intent-filter>
+            <meta-data android:name="com.android.settings.category"
+                       android:value="com.android.settings.category.ia.development" />
+            <meta-data android:name="com.android.settings.summary" android:resource="@string/angle_preferences_summary" />
+            <meta-data android:name="com.android.settings.order" android:value="20" />
+            <meta-data android:name="com.android.settings.profile" android:value="primary_profile_only" />
+            <meta-data android:name="instantapps.clients.allowed" android:value="true" />
         </activity>
 
         <receiver android:name="com.android.angle.common.Receiver"
@@ -59,5 +74,17 @@
                 <action android:name="android.app.action.ANGLE_FOR_ANDROID_TOAST_MESSAGE" />
             </intent-filter>
         </receiver>
+
+        <provider
+            android:name="com.android.angle.common.SearchProvider"
+            android:authorities="com.android.angle"
+            android:multiprocess="false"
+            android:grantUriPermissions="true"
+            android:permission="android.permission.READ_SEARCH_INDEXABLES"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="android.content.action.SEARCH_INDEXABLES_PROVIDER" />
+            </intent-filter>
+        </provider>
     </application>
 </manifest>
diff --git a/src/common/PackedEnums.cpp b/src/common/PackedEnums.cpp
index b2f90a7..aeb8023 100644
--- a/src/common/PackedEnums.cpp
+++ b/src/common/PackedEnums.cpp
@@ -254,6 +254,102 @@
     return os;
 }
 
+std::ostream &operator<<(std::ostream &os, BlendEquationType value)
+{
+    switch (value)
+    {
+        case BlendEquationType::Add:
+            os << "GL_FUNC_ADD";
+            break;
+        case BlendEquationType::Min:
+            os << "GL_MIN";
+            break;
+        case BlendEquationType::Max:
+            os << "GL_MAX";
+            break;
+        case BlendEquationType::Subtract:
+            os << "GL_FUNC_SUBTRACT";
+            break;
+        case BlendEquationType::ReverseSubtract:
+            os << "GL_FUNC_REVERSE_SUBTRACT";
+            break;
+        default:
+            os << "GL_INVALID_ENUM";
+            break;
+    }
+
+    return os;
+}
+
+std::ostream &operator<<(std::ostream &os, BlendFactorType value)
+{
+    switch (value)
+    {
+        case BlendFactorType::Zero:
+            os << "GL_ZERO";
+            break;
+        case BlendFactorType::One:
+            os << "GL_ONE";
+            break;
+        case BlendFactorType::SrcColor:
+            os << "GL_SRC_COLOR";
+            break;
+        case BlendFactorType::OneMinusSrcColor:
+            os << "GL_ONE_MINUS_SRC_COLOR";
+            break;
+        case BlendFactorType::SrcAlpha:
+            os << "GL_SRC_ALPHA";
+            break;
+        case BlendFactorType::OneMinusSrcAlpha:
+            os << "GL_ONE_MINUS_SRC_ALPHA";
+            break;
+        case BlendFactorType::DstAlpha:
+            os << "GL_DST_ALPHA";
+            break;
+        case BlendFactorType::OneMinusDstAlpha:
+            os << "GL_ONE_MINUS_DST_ALPHA";
+            break;
+        case BlendFactorType::DstColor:
+            os << "GL_DST_COLOR";
+            break;
+        case BlendFactorType::OneMinusDstColor:
+            os << "GL_ONE_MINUS_DST_COLOR";
+            break;
+        case BlendFactorType::SrcAlphaSaturate:
+            os << "GL_SRC_ALPHA_SATURATE";
+            break;
+        case BlendFactorType::ConstantColor:
+            os << "GL_CONSTANT_COLOR";
+            break;
+        case BlendFactorType::OneMinusConstantColor:
+            os << "GL_ONE_MINUS_CONSTANT_COLOR";
+            break;
+        case BlendFactorType::ConstantAlpha:
+            os << "GL_CONSTANT_ALPHA";
+            break;
+        case BlendFactorType::OneMinusConstantAlpha:
+            os << "GL_ONE_MINUS_CONSTANT_ALPHA";
+            break;
+        case BlendFactorType::Src1Alpha:
+            os << "GL_SRC1_ALPHA_EXT";
+            break;
+        case BlendFactorType::Src1Color:
+            os << "GL_SRC1_COLOR_EXT";
+            break;
+        case BlendFactorType::OneMinusSrc1Color:
+            os << "GL_ONE_MINUS_SRC1_COLOR_EXT";
+            break;
+        case BlendFactorType::OneMinusSrc1Alpha:
+            os << "GL_ONE_MINUS_SRC1_ALPHA_EXT";
+            break;
+        default:
+            os << "GL_INVALID_ENUM";
+            break;
+    }
+
+    return os;
+}
+
 std::ostream &operator<<(std::ostream &os, VertexAttribType value)
 {
     switch (value)
diff --git a/src/common/PackedEnums.h b/src/common/PackedEnums.h
index 38c6910..aa576d1 100644
--- a/src/common/PackedEnums.h
+++ b/src/common/PackedEnums.h
@@ -323,6 +323,129 @@
 
 std::ostream &operator<<(std::ostream &os, DrawElementsType value);
 
+enum class BlendEquationType
+{
+    Add             = 0,  // GLenum == 0x8006
+    Min             = 1,  // GLenum == 0x8007
+    Max             = 2,  // GLenum == 0x8008
+    Unused          = 3,
+    Subtract        = 4,  // GLenum == 0x800A
+    ReverseSubtract = 5,  // GLenum == 0x800B
+    InvalidEnum     = 6,
+    EnumCount       = 6
+};
+
+template <>
+constexpr BlendEquationType FromGLenum<BlendEquationType>(GLenum from)
+{
+    const GLenum scaled = (from - GL_FUNC_ADD);
+    return (scaled == static_cast<GLenum>(BlendEquationType::Unused) ||
+            scaled >= static_cast<GLenum>(BlendEquationType::EnumCount))
+               ? BlendEquationType::InvalidEnum
+               : static_cast<BlendEquationType>(scaled);
+}
+
+constexpr GLenum ToGLenum(BlendEquationType from)
+{
+    return static_cast<GLenum>(from) + GL_FUNC_ADD;
+}
+
+ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Add, GL_FUNC_ADD);
+ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Min, GL_MIN);
+ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Max, GL_MAX);
+ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, Subtract, GL_FUNC_SUBTRACT);
+ANGLE_VALIDATE_PACKED_ENUM(BlendEquationType, ReverseSubtract, GL_FUNC_REVERSE_SUBTRACT);
+
+std::ostream &operator<<(std::ostream &os, BlendEquationType value);
+
+enum class BlendFactorType
+{
+    Zero = 0,  // GLenum == 0
+    One  = 1,  // GLenum == 1
+
+    MinSrcDstType    = 2,
+    SrcColor         = 2,   // GLenum == 0x0300
+    OneMinusSrcColor = 3,   // GLenum == 0x0301
+    SrcAlpha         = 4,   // GLenum == 0x0302
+    OneMinusSrcAlpha = 5,   // GLenum == 0x0303
+    DstAlpha         = 6,   // GLenum == 0x0304
+    OneMinusDstAlpha = 7,   // GLenum == 0x0305
+    DstColor         = 8,   // GLenum == 0x0306
+    OneMinusDstColor = 9,   // GLenum == 0x0307
+    SrcAlphaSaturate = 10,  // GLenum == 0x0308
+    MaxSrcDstType    = 10,
+
+    MinConstantType       = 11,
+    ConstantColor         = 11,  // GLenum == 0x8001
+    OneMinusConstantColor = 12,  // GLenum == 0x8002
+    ConstantAlpha         = 13,  // GLenum == 0x8003
+    OneMinusConstantAlpha = 14,  // GLenum == 0x8004
+    MaxConstantType       = 14,
+
+    // GL_EXT_blend_func_extended
+
+    Src1Alpha = 15,  // GLenum == 0x8589
+
+    Src1Color         = 16,  // GLenum == 0x88F9
+    OneMinusSrc1Color = 17,  // GLenum == 0x88FA
+    OneMinusSrc1Alpha = 18,  // GLenum == 0x88FB
+
+    InvalidEnum = 19,
+    EnumCount   = 19
+};
+
+template <>
+constexpr BlendFactorType FromGLenum<BlendFactorType>(GLenum from)
+{
+    if (from <= 1)
+        return static_cast<BlendFactorType>(from);
+    if (from >= GL_SRC_COLOR && from <= GL_SRC_ALPHA_SATURATE)
+        return static_cast<BlendFactorType>(from - GL_SRC_COLOR + 2);
+    if (from >= GL_CONSTANT_COLOR && from <= GL_ONE_MINUS_CONSTANT_ALPHA)
+        return static_cast<BlendFactorType>(from - GL_CONSTANT_COLOR + 11);
+    if (from == GL_SRC1_ALPHA_EXT)
+        return BlendFactorType::Src1Alpha;
+    if (from >= GL_SRC1_COLOR_EXT && from <= GL_ONE_MINUS_SRC1_ALPHA_EXT)
+        return static_cast<BlendFactorType>(from - GL_SRC1_COLOR_EXT + 16);
+    return BlendFactorType::InvalidEnum;
+}
+
+constexpr GLenum ToGLenum(BlendFactorType from)
+{
+    const GLenum value = static_cast<GLenum>(from);
+    if (value <= 1)
+        return value;
+    if (from >= BlendFactorType::MinSrcDstType && from <= BlendFactorType::MaxSrcDstType)
+        return value - 2 + GL_SRC_COLOR;
+    if (from >= BlendFactorType::MinConstantType && from <= BlendFactorType::MaxConstantType)
+        return value - 11 + GL_CONSTANT_COLOR;
+    if (from == BlendFactorType::Src1Alpha)
+        return GL_SRC1_ALPHA_EXT;
+    return value - 16 + GL_SRC1_COLOR_EXT;
+}
+
+ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, Zero, GL_ZERO);
+ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, One, GL_ONE);
+ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, SrcColor, GL_SRC_COLOR);
+ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusSrcColor, GL_ONE_MINUS_SRC_COLOR);
+ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, SrcAlpha, GL_SRC_ALPHA);
+ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusSrcAlpha, GL_ONE_MINUS_SRC_ALPHA);
+ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, DstAlpha, GL_DST_ALPHA);
+ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusDstAlpha, GL_ONE_MINUS_DST_ALPHA);
+ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, DstColor, GL_DST_COLOR);
+ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusDstColor, GL_ONE_MINUS_DST_COLOR);
+ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, SrcAlphaSaturate, GL_SRC_ALPHA_SATURATE);
+ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, ConstantColor, GL_CONSTANT_COLOR);
+ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusConstantColor, GL_ONE_MINUS_CONSTANT_COLOR);
+ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, ConstantAlpha, GL_CONSTANT_ALPHA);
+ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusConstantAlpha, GL_ONE_MINUS_CONSTANT_ALPHA);
+ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, Src1Alpha, GL_SRC1_ALPHA_EXT);
+ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, Src1Color, GL_SRC1_COLOR_EXT);
+ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusSrc1Color, GL_ONE_MINUS_SRC1_COLOR_EXT);
+ANGLE_VALIDATE_PACKED_ENUM(BlendFactorType, OneMinusSrc1Alpha, GL_ONE_MINUS_SRC1_ALPHA_EXT);
+
+std::ostream &operator<<(std::ostream &os, BlendFactorType value);
+
 enum class VertexAttribType
 {
     Byte               = 0,   // GLenum == 0x1400
diff --git a/src/common/mathutil.cpp b/src/common/mathutil.cpp
index 9a2c2ec..306cde1 100644
--- a/src/common/mathutil.cpp
+++ b/src/common/mathutil.cpp
@@ -79,15 +79,4 @@
         inputData->B * pow(2.0f, (int)inputData->E - g_sharedexp_bias - g_sharedexp_mantissabits);
 }
 
-int BitCountPolyfill(uint32_t bits)
-{
-    int ones = 0;
-    while (bits)
-    {
-        ones += bool(bits & 1);
-        bits >>= 1;
-    }
-    return ones;
-}
-
 }  // namespace gl
diff --git a/src/common/mathutil.h b/src/common/mathutil.h
index dd7786c..f47d217 100644
--- a/src/common/mathutil.h
+++ b/src/common/mathutil.h
@@ -981,54 +981,96 @@
 }
 
 // Count the 1 bits.
-#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
-#    define ANGLE_HAS_BITCOUNT_32
+#if defined(_MSC_VER) && !defined(__clang__)
+#    if defined(_M_IX86) || defined(_M_X64)
+namespace priv
+{
+// Check POPCNT instruction support and cache the result.
+// https://docs.microsoft.com/en-us/cpp/intrinsics/popcnt16-popcnt-popcnt64#remarks
+static const bool kHasPopcnt = [] {
+    int info[4];
+    __cpuid(&info[0], 1);
+    return static_cast<bool>(info[2] & 0x800000);
+}();
+}  // namespace priv
+
+// Polyfills for x86/x64 CPUs without POPCNT.
+// https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
+inline int BitCountPolyfill(uint32_t bits)
+{
+    bits = bits - ((bits >> 1) & 0x55555555);
+    bits = (bits & 0x33333333) + ((bits >> 2) & 0x33333333);
+    bits = ((bits + (bits >> 4) & 0x0F0F0F0F) * 0x01010101) >> 24;
+    return static_cast<int>(bits);
+}
+
+inline int BitCountPolyfill(uint64_t bits)
+{
+    bits = bits - ((bits >> 1) & 0x5555555555555555ull);
+    bits = (bits & 0x3333333333333333ull) + ((bits >> 2) & 0x3333333333333333ull);
+    bits = ((bits + (bits >> 4) & 0x0F0F0F0F0F0F0F0Full) * 0x0101010101010101ull) >> 56;
+    return static_cast<int>(bits);
+}
+
 inline int BitCount(uint32_t bits)
 {
-    return static_cast<int>(__popcnt(bits));
+    if (priv::kHasPopcnt)
+    {
+        return static_cast<int>(__popcnt(bits));
+    }
+    return BitCountPolyfill(bits);
 }
-#    if defined(_M_X64)
-#        define ANGLE_HAS_BITCOUNT_64
+
 inline int BitCount(uint64_t bits)
 {
-    return static_cast<int>(__popcnt64(bits));
+    if (priv::kHasPopcnt)
+    {
+#        if defined(_M_X64)
+        return static_cast<int>(__popcnt64(bits));
+#        else   // x86
+        return static_cast<int>(__popcnt(static_cast<uint32_t>(bits >> 32)) +
+                                __popcnt(static_cast<uint32_t>(bits)));
+#        endif  // defined(_M_X64)
+    }
+    return BitCountPolyfill(bits);
 }
-#    endif  // defined(_M_X64)
-#endif      // defined(_M_IX86) || defined(_M_X64)
 
-#if defined(ANGLE_PLATFORM_POSIX)
-#    define ANGLE_HAS_BITCOUNT_32
+#    elif defined(_M_ARM) || defined(_M_ARM64)
+
+// MSVC's _CountOneBits* intrinsics are not defined for ARM64, moreover they do not use dedicated
+// NEON instructions.
+
+inline int BitCount(uint32_t bits)
+{
+    // cast bits to 8x8 datatype and use VCNT on it
+    const uint8x8_t vsum = vcnt_u8(vcreate_u8(static_cast<uint64_t>(bits)));
+
+    // pairwise sums: 8x8 -> 16x4 -> 32x2
+    return static_cast<int>(vget_lane_u32(vpaddl_u16(vpaddl_u8(vsum)), 0));
+}
+
+inline int BitCount(uint64_t bits)
+{
+    // cast bits to 8x8 datatype and use VCNT on it
+    const uint8x8_t vsum = vcnt_u8(vcreate_u8(bits));
+
+    // pairwise sums: 8x8 -> 16x4 -> 32x2 -> 64x1
+    return static_cast<int>(vget_lane_u64(vpaddl_u32(vpaddl_u16(vpaddl_u8(vsum))), 0));
+}
+#    endif  // defined(_M_IX86) || defined(_M_X64)
+#endif      // defined(_MSC_VER) && !defined(__clang__)
+
+#if defined(ANGLE_PLATFORM_POSIX) || defined(__clang__)
 inline int BitCount(uint32_t bits)
 {
     return __builtin_popcount(bits);
 }
 
-#    if defined(ANGLE_IS_64_BIT_CPU)
-#        define ANGLE_HAS_BITCOUNT_64
 inline int BitCount(uint64_t bits)
 {
     return __builtin_popcountll(bits);
 }
-#    endif  // defined(ANGLE_IS_64_BIT_CPU)
-#endif      // defined(ANGLE_PLATFORM_POSIX)
-
-int BitCountPolyfill(uint32_t bits);
-
-#if !defined(ANGLE_HAS_BITCOUNT_32)
-inline int BitCount(const uint32_t bits)
-{
-    return BitCountPolyfill(bits);
-}
-#endif  // !defined(ANGLE_HAS_BITCOUNT_32)
-
-#if !defined(ANGLE_HAS_BITCOUNT_64)
-inline int BitCount(const uint64_t bits)
-{
-    return BitCount(static_cast<uint32_t>(bits >> 32)) + BitCount(static_cast<uint32_t>(bits));
-}
-#endif  // !defined(ANGLE_HAS_BITCOUNT_64)
-#undef ANGLE_HAS_BITCOUNT_32
-#undef ANGLE_HAS_BITCOUNT_64
+#endif  // defined(ANGLE_PLATFORM_POSIX) || defined(__clang__)
 
 inline int BitCount(uint8_t bits)
 {
diff --git a/src/common/mathutil_unittest.cpp b/src/common/mathutil_unittest.cpp
index 4dd4cd5..60df6d0 100644
--- a/src/common/mathutil_unittest.cpp
+++ b/src/common/mathutil_unittest.cpp
@@ -258,11 +258,12 @@
     EXPECT_EQ(32, gl::BitCount(0xFFFFFFFFu));
     EXPECT_EQ(10, gl::BitCount(0x17103121u));
 
-#if defined(ANGLE_IS_64_BIT_CPU)
     EXPECT_EQ(0, gl::BitCount(static_cast<uint64_t>(0ull)));
     EXPECT_EQ(32, gl::BitCount(static_cast<uint64_t>(0xFFFFFFFFull)));
     EXPECT_EQ(10, gl::BitCount(static_cast<uint64_t>(0x17103121ull)));
-#endif  // defined(ANGLE_IS_64_BIT_CPU)
+
+    EXPECT_EQ(33, gl::BitCount(static_cast<uint64_t>(0xFFFFFFFF80000000ull)));
+    EXPECT_EQ(11, gl::BitCount(static_cast<uint64_t>(0x1710312180000000ull)));
 }
 
 // Test ScanForward, which scans for the least significant 1 bit from a non-zero integer.
diff --git a/src/common/system_utils_posix.cpp b/src/common/system_utils_posix.cpp
index 4ea9960..f9c0195 100644
--- a/src/common/system_utils_posix.cpp
+++ b/src/common/system_utils_posix.cpp
@@ -9,6 +9,7 @@
 #include "system_utils.h"
 
 #include <array>
+#include <iostream>
 
 #include <dlfcn.h>
 #include <sys/stat.h>
@@ -81,6 +82,10 @@
 
         std::string fullPath = directory + libraryName + "." + GetSharedLibraryExtension();
         mModule              = dlopen(fullPath.c_str(), RTLD_NOW);
+        if (!mModule)
+        {
+            std::cerr << "Failed to load " << libraryName << ": " << dlerror() << std::endl;
+        }
     }
 
     ~PosixLibrary() override
diff --git a/src/common/system_utils_unittest.cpp b/src/common/system_utils_unittest.cpp
index 7b189b9..6c467a3 100644
--- a/src/common/system_utils_unittest.cpp
+++ b/src/common/system_utils_unittest.cpp
@@ -17,29 +17,25 @@
 // Test getting the executable path
 TEST(SystemUtils, ExecutablePath)
 {
-#if defined(ANGLE_PLATFORM_FUCHSIA)
     // TODO: fuchsia support. http://anglebug.com/3161
-    return;
-#endif
-
+#if !defined(ANGLE_PLATFORM_FUCHSIA)
     std::string executablePath = GetExecutablePath();
     EXPECT_NE("", executablePath);
+#endif
 }
 
 // Test getting the executable directory
 TEST(SystemUtils, ExecutableDir)
 {
-#if defined(ANGLE_PLATFORM_FUCHSIA)
     // TODO: fuchsia support. http://anglebug.com/3161
-    return;
-#endif
-
+#if !defined(ANGLE_PLATFORM_FUCHSIA)
     std::string executableDir = GetExecutableDirectory();
     EXPECT_NE("", executableDir);
 
     std::string executablePath = GetExecutablePath();
     EXPECT_LT(executableDir.size(), executablePath.size());
     EXPECT_EQ(0, strncmp(executableDir.c_str(), executablePath.c_str(), executableDir.size()));
+#endif
 }
 
 // Test setting environment variables
diff --git a/src/compiler.gni b/src/compiler.gni
index 5230a41..bbe41e2 100644
--- a/src/compiler.gni
+++ b/src/compiler.gni
@@ -124,6 +124,8 @@
   "src/compiler/translator/tree_ops/DeclareAndInitBuiltinsForInstancedMultiview.h",
   "src/compiler/translator/tree_ops/DeferGlobalInitializers.cpp",
   "src/compiler/translator/tree_ops/DeferGlobalInitializers.h",
+  "src/compiler/translator/tree_ops/EarlyFragmentTestsOptimization.cpp",
+  "src/compiler/translator/tree_ops/EarlyFragmentTestsOptimization.h",
   "src/compiler/translator/tree_ops/EmulateGLFragColorBroadcast.cpp",
   "src/compiler/translator/tree_ops/EmulateGLFragColorBroadcast.h",
   "src/compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.cpp",
diff --git a/src/compiler/translator/BaseTypes.h b/src/compiler/translator/BaseTypes.h
index 18d0142..562e64a 100644
--- a/src/compiler/translator/BaseTypes.h
+++ b/src/compiler/translator/BaseTypes.h
@@ -970,14 +970,17 @@
     EvqLastFragData,
 
     // GLSL ES 3.0 vertex output and fragment input
-    EvqSmooth,    // Incomplete qualifier, smooth is the default
-    EvqFlat,      // Incomplete qualifier
-    EvqCentroid,  // Incomplete qualifier
+    EvqSmooth,         // Incomplete qualifier, smooth is the default
+    EvqFlat,           // Incomplete qualifier
+    EvqNoPerspective,  // Incomplete qualifier
+    EvqCentroid,       // Incomplete qualifier
     EvqSmoothOut,
     EvqFlatOut,
+    EvqNoPerspectiveOut,
     EvqCentroidOut,  // Implies smooth
     EvqSmoothIn,
     EvqFlatIn,
+    EvqNoPerspectiveIn,
     EvqCentroidIn,  // Implies smooth
 
     // GLSL ES 3.1 compute shader special variables
@@ -1034,6 +1037,7 @@
         case EvqVaryingIn:
         case EvqSmoothIn:
         case EvqFlatIn:
+        case EvqNoPerspectiveIn:
         case EvqCentroidIn:
             return true;
         default:
@@ -1051,6 +1055,7 @@
         case EvqVaryingOut:
         case EvqSmoothOut:
         case EvqFlatOut:
+        case EvqNoPerspectiveOut:
         case EvqCentroidOut:
             return true;
         default:
@@ -1301,11 +1306,14 @@
     case EvqSmoothOut:              return "smooth out";
     case EvqCentroidOut:            return "smooth centroid out";
     case EvqFlatOut:                return "flat out";
+    case EvqNoPerspectiveOut:       return "noperspective out";
     case EvqSmoothIn:               return "smooth in";
     case EvqFlatIn:                 return "flat in";
+    case EvqNoPerspectiveIn:        return "noperspective in";
     case EvqCentroidIn:             return "smooth centroid in";
     case EvqCentroid:               return "centroid";
     case EvqFlat:                   return "flat";
+    case EvqNoPerspective:          return "noperspective";
     case EvqSmooth:                 return "smooth";
     case EvqShared:                 return "shared";
     case EvqComputeIn:              return "in";
diff --git a/src/compiler/translator/CollectVariables.cpp b/src/compiler/translator/CollectVariables.cpp
index 2db3b17..4c4d2f8 100644
--- a/src/compiler/translator/CollectVariables.cpp
+++ b/src/compiler/translator/CollectVariables.cpp
@@ -724,6 +724,7 @@
         case EvqVertexOut:
         case EvqSmoothOut:
         case EvqFlatOut:
+        case EvqNoPerspectiveOut:
         case EvqCentroidOut:
         case EvqGeometryOut:
             if (mSymbolTable->isVaryingInvariant(variable.variable()) || type.isInvariant())
diff --git a/src/compiler/translator/Compiler.cpp b/src/compiler/translator/Compiler.cpp
index 303fd21..d8bc390 100644
--- a/src/compiler/translator/Compiler.cpp
+++ b/src/compiler/translator/Compiler.cpp
@@ -26,6 +26,7 @@
 #include "compiler/translator/tree_ops/ClampPointSize.h"
 #include "compiler/translator/tree_ops/DeclareAndInitBuiltinsForInstancedMultiview.h"
 #include "compiler/translator/tree_ops/DeferGlobalInitializers.h"
+#include "compiler/translator/tree_ops/EarlyFragmentTestsOptimization.h"
 #include "compiler/translator/tree_ops/EmulateGLFragColorBroadcast.h"
 #include "compiler/translator/tree_ops/EmulateMultiDrawShaderBuiltins.h"
 #include "compiler/translator/tree_ops/EmulatePrecision.h"
@@ -557,6 +558,21 @@
         return false;
     }
 
+    // We need to generate globals early if we have non constant initializers enabled
+    bool initializeLocalsAndGlobals =
+        (compileOptions & SH_INITIALIZE_UNINITIALIZED_LOCALS) && !IsOutputHLSL(getOutputType());
+    bool canUseLoopsToInitialize = !(compileOptions & SH_DONT_USE_LOOPS_TO_INITIALIZE_VARIABLES);
+    bool highPrecisionSupported  = mShaderVersion > 100 || mShaderType != GL_FRAGMENT_SHADER ||
+                                  mResources.FragmentPrecisionHigh == 1;
+    bool enableNonConstantInitializers = IsExtensionEnabled(
+        mExtensionBehavior, TExtension::EXT_shader_non_constant_global_initializers);
+    if (enableNonConstantInitializers &&
+        !DeferGlobalInitializers(this, root, initializeLocalsAndGlobals, canUseLoopsToInitialize,
+                                 highPrecisionSupported, &mSymbolTable))
+    {
+        return false;
+    }
+
     // Create the function DAG and check there is no recursion
     if (!initCallDag(root))
     {
@@ -765,8 +781,6 @@
     GetGlobalPoolAllocator()->unlock();
     mBuiltInFunctionEmulator.markBuiltInFunctionsForEmulation(root);
 
-    bool highPrecisionSupported = mShaderVersion > 100 || mShaderType != GL_FRAGMENT_SHADER ||
-                                  mResources.FragmentPrecisionHigh == 1;
     if (compileOptions & SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS)
     {
         if (!ScalarizeVecAndMatConstructorArgs(this, root, mShaderType, highPrecisionSupported,
@@ -839,10 +853,11 @@
     // statements from expressions. But it's fine to run DeferGlobalInitializers after the above
     // SplitSequenceOperator and RemoveArrayLengthMethod since they only have an effect on the AST
     // on ESSL >= 3.00, and the initializers that need to be deferred can only exist in ESSL < 3.00.
-    bool initializeLocalsAndGlobals =
-        (compileOptions & SH_INITIALIZE_UNINITIALIZED_LOCALS) && !IsOutputHLSL(getOutputType());
-    bool canUseLoopsToInitialize = !(compileOptions & SH_DONT_USE_LOOPS_TO_INITIALIZE_VARIABLES);
-    if (!DeferGlobalInitializers(this, root, initializeLocalsAndGlobals, canUseLoopsToInitialize,
+    // Exception: if EXT_shader_non_constant_global_initializers is enabled, we must generate global
+    // initializers before we generate the DAG, since initializers may call functions which must not
+    // be optimized out
+    if (!enableNonConstantInitializers &&
+        !DeferGlobalInitializers(this, root, initializeLocalsAndGlobals, canUseLoopsToInitialize,
                                  highPrecisionSupported, &mSymbolTable))
     {
         return false;
@@ -916,6 +931,16 @@
         }
     }
 
+    mEarlyFragmentTestsOptimized = false;
+    if (compileOptions & SH_EARLY_FRAGMENT_TESTS_OPTIMIZATION)
+    {
+        if (mShaderVersion <= 300 && mShaderType == GL_FRAGMENT_SHADER &&
+            !isEarlyFragmentTestsSpecified())
+        {
+            mEarlyFragmentTestsOptimized = CheckEarlyFragmentTestsFeasible(this, root);
+        }
+    }
+
     return true;
 }
 
@@ -1478,7 +1503,7 @@
 
 void EmitEarlyFragmentTestsGLSL(const TCompiler &compiler, TInfoSinkBase &sink)
 {
-    if (compiler.isEarlyFragmentTestsSpecified())
+    if (compiler.isEarlyFragmentTestsSpecified() || compiler.isEarlyFragmentTestsOptimized())
     {
         sink << "layout (early_fragment_tests) in;\n";
     }
diff --git a/src/compiler/translator/Compiler.h b/src/compiler/translator/Compiler.h
index 950b6a1..d0b24ba 100644
--- a/src/compiler/translator/Compiler.h
+++ b/src/compiler/translator/Compiler.h
@@ -99,6 +99,7 @@
     TInfoSink &getInfoSink() { return mInfoSink; }
 
     bool isEarlyFragmentTestsSpecified() const { return mEarlyFragmentTestsSpecified; }
+    bool isEarlyFragmentTestsOptimized() const { return mEarlyFragmentTestsOptimized; }
 
     bool isComputeShaderLocalSizeDeclared() const { return mComputeShaderLocalSizeDeclared; }
     const sh::WorkGroupSize &getComputeShaderLocalSize() const { return mComputeShaderLocalSize; }
@@ -278,6 +279,7 @@
 
     // fragment shader early fragment tests
     bool mEarlyFragmentTestsSpecified;
+    bool mEarlyFragmentTestsOptimized;
 
     // compute shader local group size
     bool mComputeShaderLocalSizeDeclared;
diff --git a/src/compiler/translator/ExtensionBehavior.cpp b/src/compiler/translator/ExtensionBehavior.cpp
index 664a6a9..5144b6e 100644
--- a/src/compiler/translator/ExtensionBehavior.cpp
+++ b/src/compiler/translator/ExtensionBehavior.cpp
@@ -12,29 +12,31 @@
 
 #include <string.h>
 
-#define LIST_EXTENSIONS(OP)                      \
-    OP(ARB_texture_rectangle)                    \
-    OP(ANGLE_texture_multisample)                \
-    OP(ARM_shader_framebuffer_fetch)             \
-    OP(EXT_blend_func_extended)                  \
-    OP(EXT_draw_buffers)                         \
-    OP(EXT_frag_depth)                           \
-    OP(EXT_geometry_shader)                      \
-    OP(EXT_gpu_shader5)                          \
-    OP(EXT_shader_framebuffer_fetch)             \
-    OP(EXT_shader_texture_lod)                   \
-    OP(EXT_YUV_target)                           \
-    OP(NV_EGL_stream_consumer_external)          \
-    OP(NV_shader_framebuffer_fetch)              \
-    OP(OES_EGL_image_external)                   \
-    OP(OES_EGL_image_external_essl3)             \
-    OP(OES_standard_derivatives)                 \
-    OP(OES_texture_storage_multisample_2d_array) \
-    OP(OES_texture_3D)                           \
-    OP(OVR_multiview)                            \
-    OP(OVR_multiview2)                           \
-    OP(ANGLE_multi_draw)                         \
-    OP(ANGLE_base_vertex_base_instance)          \
+#define LIST_EXTENSIONS(OP)                         \
+    OP(ARB_texture_rectangle)                       \
+    OP(ANGLE_texture_multisample)                   \
+    OP(ARM_shader_framebuffer_fetch)                \
+    OP(EXT_blend_func_extended)                     \
+    OP(EXT_draw_buffers)                            \
+    OP(EXT_frag_depth)                              \
+    OP(EXT_geometry_shader)                         \
+    OP(EXT_gpu_shader5)                             \
+    OP(EXT_shader_framebuffer_fetch)                \
+    OP(EXT_shader_texture_lod)                      \
+    OP(EXT_YUV_target)                              \
+    OP(EXT_shader_non_constant_global_initializers) \
+    OP(NV_shader_noperspective_interpolation)       \
+    OP(NV_EGL_stream_consumer_external)             \
+    OP(NV_shader_framebuffer_fetch)                 \
+    OP(OES_EGL_image_external)                      \
+    OP(OES_EGL_image_external_essl3)                \
+    OP(OES_standard_derivatives)                    \
+    OP(OES_texture_storage_multisample_2d_array)    \
+    OP(OES_texture_3D)                              \
+    OP(OVR_multiview)                               \
+    OP(OVR_multiview2)                              \
+    OP(ANGLE_multi_draw)                            \
+    OP(ANGLE_base_vertex_base_instance)             \
     OP(WEBGL_video_texture)
 
 namespace sh
diff --git a/src/compiler/translator/ExtensionBehavior.h b/src/compiler/translator/ExtensionBehavior.h
index b2c3597..f9cf855 100644
--- a/src/compiler/translator/ExtensionBehavior.h
+++ b/src/compiler/translator/ExtensionBehavior.h
@@ -29,8 +29,10 @@
     EXT_shader_framebuffer_fetch,
     EXT_shader_texture_lod,
     EXT_YUV_target,
+    EXT_shader_non_constant_global_initializers,
     NV_EGL_stream_consumer_external,
     NV_shader_framebuffer_fetch,
+    NV_shader_noperspective_interpolation,
     OES_EGL_image_external,
     OES_EGL_image_external_essl3,
     OES_standard_derivatives,
diff --git a/src/compiler/translator/Initialize.cpp b/src/compiler/translator/Initialize.cpp
index 82e7e0f..b7bc846 100644
--- a/src/compiler/translator/Initialize.cpp
+++ b/src/compiler/translator/Initialize.cpp
@@ -57,6 +57,10 @@
     {
         extBehavior[TExtension::NV_shader_framebuffer_fetch] = EBhUndefined;
     }
+    if (resources.NV_shader_noperspective_interpolation)
+    {
+        extBehavior[TExtension::NV_shader_noperspective_interpolation] = EBhUndefined;
+    }
     if (resources.ARM_shader_framebuffer_fetch)
     {
         extBehavior[TExtension::ARM_shader_framebuffer_fetch] = EBhUndefined;
@@ -81,6 +85,10 @@
     {
         extBehavior[TExtension::EXT_gpu_shader5] = EBhUndefined;
     }
+    if (resources.EXT_shader_non_constant_global_initializers)
+    {
+        extBehavior[TExtension::EXT_shader_non_constant_global_initializers] = EBhUndefined;
+    }
     if (resources.OES_texture_storage_multisample_2d_array)
     {
         extBehavior[TExtension::OES_texture_storage_multisample_2d_array] = EBhUndefined;
diff --git a/src/compiler/translator/OutputHLSL.cpp b/src/compiler/translator/OutputHLSL.cpp
index 89dcdc9..e10e6ae 100644
--- a/src/compiler/translator/OutputHLSL.cpp
+++ b/src/compiler/translator/OutputHLSL.cpp
@@ -86,6 +86,30 @@
     return false;
 }
 
+bool IsInstanceUniformBlock(TIntermTyped *node)
+{
+    TIntermBinary *binaryNode = node->getAsBinaryNode();
+
+    if (binaryNode)
+    {
+        return IsInstanceUniformBlock(binaryNode->getLeft());
+    }
+
+    const TVariable &variable = node->getAsSymbolNode()->variable();
+    const TType &variableType = variable.getType();
+
+    const TType &type = node->getType();
+
+    if (type.getQualifier() == EvqUniform)
+    {
+        // determine if it is instance uniform block.
+        const TInterfaceBlock *interfaceBlock = type.getInterfaceBlock();
+        return interfaceBlock && variableType.isInterfaceBlock();
+    }
+
+    return false;
+}
+
 const char *GetHLSLAtomicFunctionStringAndLeftParenthesis(TOperator op)
 {
     switch (op)
@@ -1683,7 +1707,11 @@
                     node->getLeft()->getType().getInterfaceBlock();
                 const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion();
                 const TField *field               = interfaceBlock->fields()[index->getIConst(0)];
-                if (structInStd140UniformBlock)
+                bool instanceUniformBlock         = IsInstanceUniformBlock(node->getLeft());
+                if (structInStd140UniformBlock ||
+                    (instanceUniformBlock &&
+                     mResourcesHLSL->shouldTranslateUniformBlockToStructuredBuffer(
+                         *interfaceBlock)))
                 {
                     out << "_";
                 }
diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp
index 14eec7e..8638426 100644
--- a/src/compiler/translator/ParseContext.cpp
+++ b/src/compiler/translator/ParseContext.cpp
@@ -530,6 +530,7 @@
         case EvqVertexIn:
         case EvqGeometryIn:
         case EvqFlatIn:
+        case EvqNoPerspectiveIn:
         case EvqSmoothIn:
         case EvqCentroidIn:
             message = "can't modify an input";
@@ -2038,10 +2039,13 @@
         return false;
     }
 
+    bool nonConstGlobalInitializers =
+        IsExtensionEnabled(mDirectiveHandler.extensionBehavior(),
+                           TExtension::EXT_shader_non_constant_global_initializers);
     bool globalInitWarning = false;
     if (symbolTable.atGlobalLevel() &&
         !ValidateGlobalInitializer(initializer, mShaderVersion, sh::IsWebGLBasedSpec(mShaderSpec),
-                                   &globalInitWarning))
+                                   nonConstGlobalInitializers, &globalInitWarning))
     {
         // Error message does not completely match behavior with ESSL 1.00, but
         // we want to steer developers towards only using constant expressions.
diff --git a/src/compiler/translator/QualifierTypes.cpp b/src/compiler/translator/QualifierTypes.cpp
index 3e0d733..6f549a2 100644
--- a/src/compiler/translator/QualifierTypes.cpp
+++ b/src/compiler/translator/QualifierTypes.cpp
@@ -403,6 +403,26 @@
             }
             break;
         }
+        case EvqNoPerspective:
+        {
+            switch (storageQualifier)
+            {
+                case EvqCentroid:
+                    *joinedQualifier = EvqNoPerspective;
+                    break;
+                case EvqVertexOut:
+                case EvqGeometryOut:
+                    *joinedQualifier = EvqNoPerspectiveOut;
+                    break;
+                case EvqFragmentIn:
+                case EvqGeometryIn:
+                    *joinedQualifier = EvqNoPerspectiveIn;
+                    break;
+                default:
+                    return false;
+            }
+            break;
+        }
         case EvqCentroid:
         {
             switch (storageQualifier)
diff --git a/src/compiler/translator/ResourcesHLSL.cpp b/src/compiler/translator/ResourcesHLSL.cpp
index b39d59e..5a78b7b 100644
--- a/src/compiler/translator/ResourcesHLSL.cpp
+++ b/src/compiler/translator/ResourcesHLSL.cpp
@@ -656,16 +656,29 @@
 
         // In order to avoid compile performance issue, translate uniform block to structured
         // buffer. anglebug.com/3682.
-        // TODO(anglebug.com/4205): Support uniform block with an instance name.
-        if (instanceVariable == nullptr &&
-            shouldTranslateUniformBlockToStructuredBuffer(interfaceBlock))
+        if (shouldTranslateUniformBlockToStructuredBuffer(interfaceBlock))
         {
             unsigned int structuredBufferRegister = mSRVRegister;
-            interfaceBlocks +=
-                uniformBlockWithOneLargeArrayMemberString(interfaceBlock, structuredBufferRegister);
+            if (instanceVariable != nullptr && instanceVariable->getType().isArray())
+            {
+                unsigned int instanceArraySize =
+                    instanceVariable->getType().getOutermostArraySize();
+                for (unsigned int arrayIndex = 0; arrayIndex < instanceArraySize; arrayIndex++)
+                {
+                    interfaceBlocks += uniformBlockWithOneLargeArrayMemberString(
+                        interfaceBlock, instanceVariable, structuredBufferRegister + arrayIndex,
+                        arrayIndex);
+                }
+                mSRVRegister += instanceArraySize;
+            }
+            else
+            {
+                interfaceBlocks += uniformBlockWithOneLargeArrayMemberString(
+                    interfaceBlock, instanceVariable, structuredBufferRegister, GL_INVALID_INDEX);
+                mSRVRegister += 1u;
+            }
             mUniformBlockRegisterMap[interfaceBlock.name().data()] = structuredBufferRegister;
             mUniformBlockUseStructuredBufferMap[interfaceBlock.name().data()] = true;
-            mSRVRegister += 1u;
             continue;
         }
 
@@ -758,7 +771,9 @@
 
 TString ResourcesHLSL::uniformBlockWithOneLargeArrayMemberString(
     const TInterfaceBlock &interfaceBlock,
-    unsigned int registerIndex)
+    const TVariable *instanceVariable,
+    unsigned int registerIndex,
+    unsigned int arrayIndex)
 {
     TString hlsl, typeString;
 
@@ -766,8 +781,18 @@
     const TLayoutBlockStorage blockStorage = interfaceBlock.blockStorage();
     typeString = InterfaceBlockFieldTypeString(field, blockStorage, true);
 
-    hlsl += "StructuredBuffer <" + typeString + "> " + Decorate(field.name()) + " : register(t" +
-            str(registerIndex) + ");\n";
+    if (instanceVariable != nullptr)
+    {
+
+        hlsl += "StructuredBuffer <" + typeString + "> " +
+                InterfaceBlockInstanceString(instanceVariable->name(), arrayIndex) + "_" +
+                Decorate(field.name()) + +" : register(t" + str(registerIndex) + ");\n";
+    }
+    else
+    {
+        hlsl += "StructuredBuffer <" + typeString + "> " + Decorate(field.name()) +
+                " : register(t" + str(registerIndex) + ");\n";
+    }
 
     return hlsl;
 }
diff --git a/src/compiler/translator/ResourcesHLSL.h b/src/compiler/translator/ResourcesHLSL.h
index 9764129..f7fde41 100644
--- a/src/compiler/translator/ResourcesHLSL.h
+++ b/src/compiler/translator/ResourcesHLSL.h
@@ -68,6 +68,7 @@
 
     unsigned int getReadonlyImage2DRegisterIndex() const { return mReadonlyImage2DRegisterIndex; }
     unsigned int getImage2DRegisterIndex() const { return mImage2DRegisterIndex; }
+    bool shouldTranslateUniformBlockToStructuredBuffer(const TInterfaceBlock &interfaceBlock);
 
   private:
     TString uniformBlockString(const TInterfaceBlock &interfaceBlock,
@@ -75,7 +76,9 @@
                                unsigned int registerIndex,
                                unsigned int arrayIndex);
     TString uniformBlockWithOneLargeArrayMemberString(const TInterfaceBlock &interfaceBlock,
-                                                      unsigned int registerIndex);
+                                                      const TVariable *instanceVariable,
+                                                      unsigned int registerIndex,
+                                                      unsigned int arrayIndex);
 
     TString shaderStorageBlockString(const TInterfaceBlock &interfaceBlock,
                                      const TVariable *instanceVariable,
@@ -125,7 +128,6 @@
                                      const HLSLRWTextureGroup textureGroup,
                                      const TVector<const TVariable *> &group,
                                      unsigned int *groupTextureRegisterIndex);
-    bool shouldTranslateUniformBlockToStructuredBuffer(const TInterfaceBlock &interfaceBlock);
 
     unsigned int mUniformRegister;
     unsigned int mUniformBlockRegister;
diff --git a/src/compiler/translator/ShaderLang.cpp b/src/compiler/translator/ShaderLang.cpp
index 7136b54..e202f0e 100644
--- a/src/compiler/translator/ShaderLang.cpp
+++ b/src/compiler/translator/ShaderLang.cpp
@@ -149,30 +149,32 @@
     resources->MaxDrawBuffers               = 1;
 
     // Extensions.
-    resources->OES_standard_derivatives                 = 0;
-    resources->OES_EGL_image_external                   = 0;
-    resources->OES_EGL_image_external_essl3             = 0;
-    resources->NV_EGL_stream_consumer_external          = 0;
-    resources->ARB_texture_rectangle                    = 0;
-    resources->EXT_blend_func_extended                  = 0;
-    resources->EXT_draw_buffers                         = 0;
-    resources->EXT_frag_depth                           = 0;
-    resources->EXT_shader_texture_lod                   = 0;
-    resources->WEBGL_debug_shader_precision             = 0;
-    resources->EXT_shader_framebuffer_fetch             = 0;
-    resources->NV_shader_framebuffer_fetch              = 0;
-    resources->ARM_shader_framebuffer_fetch             = 0;
-    resources->OVR_multiview                            = 0;
-    resources->OVR_multiview2                           = 0;
-    resources->EXT_YUV_target                           = 0;
-    resources->EXT_geometry_shader                      = 0;
-    resources->EXT_gpu_shader5                          = 0;
-    resources->OES_texture_storage_multisample_2d_array = 0;
-    resources->OES_texture_3D                           = 0;
-    resources->ANGLE_texture_multisample                = 0;
-    resources->ANGLE_multi_draw                         = 0;
-    resources->ANGLE_base_vertex_base_instance          = 0;
-    resources->WEBGL_video_texture                      = 0;
+    resources->OES_standard_derivatives                    = 0;
+    resources->OES_EGL_image_external                      = 0;
+    resources->OES_EGL_image_external_essl3                = 0;
+    resources->NV_EGL_stream_consumer_external             = 0;
+    resources->ARB_texture_rectangle                       = 0;
+    resources->EXT_blend_func_extended                     = 0;
+    resources->EXT_draw_buffers                            = 0;
+    resources->EXT_frag_depth                              = 0;
+    resources->EXT_shader_texture_lod                      = 0;
+    resources->WEBGL_debug_shader_precision                = 0;
+    resources->EXT_shader_framebuffer_fetch                = 0;
+    resources->NV_shader_framebuffer_fetch                 = 0;
+    resources->ARM_shader_framebuffer_fetch                = 0;
+    resources->OVR_multiview                               = 0;
+    resources->OVR_multiview2                              = 0;
+    resources->EXT_YUV_target                              = 0;
+    resources->EXT_geometry_shader                         = 0;
+    resources->EXT_gpu_shader5                             = 0;
+    resources->EXT_shader_non_constant_global_initializers = 0;
+    resources->NV_shader_noperspective_interpolation       = 0;
+    resources->OES_texture_storage_multisample_2d_array    = 0;
+    resources->OES_texture_3D                              = 0;
+    resources->ANGLE_texture_multisample                   = 0;
+    resources->ANGLE_multi_draw                            = 0;
+    resources->ANGLE_base_vertex_base_instance             = 0;
+    resources->WEBGL_video_texture                         = 0;
 
     resources->NV_draw_buffers = 0;
 
@@ -497,6 +499,16 @@
     return compiler->getNumViews();
 }
 
+bool HasEarlyFragmentTestsOptimization(const ShHandle handle)
+{
+    TCompiler *compiler = GetCompilerFromHandle(handle);
+    if (compiler == nullptr)
+    {
+        return false;
+    }
+    return compiler->isEarlyFragmentTestsOptimized();
+}
+
 bool CheckVariablesWithinPackingLimits(int maxVectors, const std::vector<ShaderVariable> &variables)
 {
     return CheckVariablesInPackingLimits(maxVectors, variables);
diff --git a/src/compiler/translator/ShaderVars.cpp b/src/compiler/translator/ShaderVars.cpp
index f5e4f21..4478094 100644
--- a/src/compiler/translator/ShaderVars.cpp
+++ b/src/compiler/translator/ShaderVars.cpp
@@ -163,7 +163,15 @@
 unsigned int ShaderVariable::getNestedArraySize(unsigned int arrayNestingIndex) const
 {
     ASSERT(arraySizes.size() > arrayNestingIndex);
-    return arraySizes[arraySizes.size() - 1u - arrayNestingIndex];
+    unsigned int arraySize = arraySizes[arraySizes.size() - 1u - arrayNestingIndex];
+
+    if (arraySize == 0)
+    {
+        // Unsized array, so give it at least 1 entry
+        arraySize = 1;
+    }
+
+    return arraySize;
 }
 
 unsigned int ShaderVariable::getBasicTypeElementCount() const
diff --git a/src/compiler/translator/ValidateGlobalInitializer.cpp b/src/compiler/translator/ValidateGlobalInitializer.cpp
index 06f51ed..fedc8b49 100644
--- a/src/compiler/translator/ValidateGlobalInitializer.cpp
+++ b/src/compiler/translator/ValidateGlobalInitializer.cpp
@@ -19,7 +19,9 @@
 class ValidateGlobalInitializerTraverser : public TIntermTraverser
 {
   public:
-    ValidateGlobalInitializerTraverser(int shaderVersion, bool isWebGL);
+    ValidateGlobalInitializerTraverser(int shaderVersion,
+                                       bool isWebGL,
+                                       bool hasExtNonConstGlobalInitializers);
 
     void visitSymbol(TIntermSymbol *node) override;
     void visitConstantUnion(TIntermConstantUnion *node) override;
@@ -31,8 +33,24 @@
     bool issueWarning() const { return mIssueWarning; }
 
   private:
+    ANGLE_INLINE void onNonConstInitializerVisit(bool accept)
+    {
+        if (accept)
+        {
+            if (!mExtNonConstGlobalInitializers)
+            {
+                mIssueWarning = true;
+            }
+        }
+        else
+        {
+            mIsValid = false;
+        }
+    }
+
     int mShaderVersion;
     bool mIsWebGL;
+    bool mExtNonConstGlobalInitializers;
     bool mIsValid;
     bool mIssueWarning;
 };
@@ -51,14 +69,8 @@
             // We allow these cases to be compatible with legacy ESSL 1.00 content.
             // Implement stricter rules for ESSL 3.00 since there's no legacy content to deal
             // with.
-            if ((mShaderVersion >= 300) || !mIsWebGL)
-            {
-                mIsValid = false;
-            }
-            else
-            {
-                mIssueWarning = true;
-            }
+            onNonConstInitializerVisit(mExtNonConstGlobalInitializers ||
+                                       ((mShaderVersion < 300) && mIsWebGL));
             break;
         default:
             mIsValid = false;
@@ -74,14 +86,8 @@
         case EvqConst:
             break;
         case EvqTemporary:
-            if ((mShaderVersion >= 300) || !mIsWebGL)
-            {
-                mIsValid = false;
-            }
-            else
-            {
-                mIssueWarning = true;
-            }
+            onNonConstInitializerVisit(mExtNonConstGlobalInitializers ||
+                                       ((mShaderVersion < 300) && mIsWebGL));
             break;
         default:
             UNREACHABLE();
@@ -96,7 +102,7 @@
     // the function call ops.
     if (node->isFunctionCall())
     {
-        mIsValid = false;
+        onNonConstInitializerVisit(mExtNonConstGlobalInitializers);
     }
     return true;
 }
@@ -105,7 +111,7 @@
 {
     if (node->isAssignment())
     {
-        mIsValid = false;
+        onNonConstInitializerVisit(mExtNonConstGlobalInitializers);
     }
     return true;
 }
@@ -114,16 +120,19 @@
 {
     if (node->isAssignment())
     {
-        mIsValid = false;
+        onNonConstInitializerVisit(mExtNonConstGlobalInitializers);
     }
     return true;
 }
 
-ValidateGlobalInitializerTraverser::ValidateGlobalInitializerTraverser(int shaderVersion,
-                                                                       bool isWebGL)
+ValidateGlobalInitializerTraverser::ValidateGlobalInitializerTraverser(
+    int shaderVersion,
+    bool isWebGL,
+    bool hasExtNonConstGlobalInitializers)
     : TIntermTraverser(true, false, false, nullptr),
       mShaderVersion(shaderVersion),
       mIsWebGL(isWebGL),
+      mExtNonConstGlobalInitializers(hasExtNonConstGlobalInitializers),
       mIsValid(true),
       mIssueWarning(false)
 {
@@ -135,9 +144,11 @@
 bool ValidateGlobalInitializer(TIntermTyped *initializer,
                                int shaderVersion,
                                bool isWebGL,
+                               bool hasExtNonConstGlobalInitializers,
                                bool *warning)
 {
-    ValidateGlobalInitializerTraverser validate(shaderVersion, isWebGL);
+    ValidateGlobalInitializerTraverser validate(shaderVersion, isWebGL,
+                                                hasExtNonConstGlobalInitializers);
     initializer->traverse(&validate);
     ASSERT(warning != nullptr);
     *warning = validate.issueWarning();
diff --git a/src/compiler/translator/ValidateGlobalInitializer.h b/src/compiler/translator/ValidateGlobalInitializer.h
index d4d75fa..cb4b652 100644
--- a/src/compiler/translator/ValidateGlobalInitializer.h
+++ b/src/compiler/translator/ValidateGlobalInitializer.h
@@ -16,6 +16,7 @@
 bool ValidateGlobalInitializer(TIntermTyped *initializer,
                                int shaderVersion,
                                bool isWebGL,
+                               bool hasExtNonConstGlobalInitializers,
                                bool *warning);
 
 }  // namespace sh
diff --git a/src/compiler/translator/blocklayout.cpp b/src/compiler/translator/blocklayout.cpp
index 9cbc96b..d681e4a 100644
--- a/src/compiler/translator/blocklayout.cpp
+++ b/src/compiler/translator/blocklayout.cpp
@@ -82,8 +82,7 @@
     // Nested arrays are processed starting from outermost (arrayNestingIndex 0u) and ending at the
     // innermost. We make a special case for unsized arrays.
     const unsigned int currentArraySize = variable.getNestedArraySize(0);
-    unsigned int count                  = std::max(currentArraySize, 1u);
-    for (unsigned int arrayElement = 0u; arrayElement < count; ++arrayElement)
+    for (unsigned int arrayElement = 0u; arrayElement < currentArraySize; ++arrayElement)
     {
         visitor->enterArrayElement(variable, arrayElement);
         ShaderVariable elementVar = variable;
diff --git a/src/compiler/translator/glslang.l b/src/compiler/translator/glslang.l
index 5982ed8..a77728b 100644
--- a/src/compiler/translator/glslang.l
+++ b/src/compiler/translator/glslang.l
@@ -105,6 +105,7 @@
 static int ES2_reserved_ES2_extension_ES3_keyword(TParseContext *context, TExtension extension, int token);
 static int ES3_extension(TParseContext *context, TExtension extension, int token);
 static int ES3_reserved_ES3_1_extension_ES3_2_keyword(TParseContext *context, TExtension extension, int token);
+static int ES3_reserved_ES3_extension(TParseContext *context, TExtension extension, int token);
 static int ES3_reserved_ES3_extension_ES3_1_keyword(TParseContext *context, TExtension extension, int token);
 static int ES3_1_reserved_ES3_1_extension_ES3_2_keyword(TParseContext *context, TExtension extension, int token);
 static int WEBGL_video_texture_extension(TParseContext *context, int token);
@@ -156,9 +157,10 @@
 "case"         { return ES3_keyword(context, CASE); }
 "default"      { return ES2_reserved_ES3_keyword(context, DEFAULT); }
 
-"centroid"     { return ES3_keyword(context, CENTROID); }
-"flat"         { return ES2_reserved_ES3_keyword(context, FLAT); }
-"smooth"       { return ES3_keyword(context, SMOOTH); }
+"centroid"      { return ES3_keyword(context, CENTROID); }
+"flat"          { return ES2_reserved_ES3_keyword(context, FLAT); }
+"smooth"        { return ES3_keyword(context, SMOOTH); }
+"noperspective" { return ES3_reserved_ES3_extension(context, TExtension::NV_shader_noperspective_interpolation, NOPERSPECTIVE); }
 
 "in"           { return IN_QUAL; }
 "out"          { return OUT_QUAL; }
@@ -262,7 +264,6 @@
 
     /* Reserved keywords for GLSL ES 3.00 that are not reserved for GLSL ES 1.00 */
 "resource"          |
-"noperspective"     |
 "patch"             |
 "sample"            |
 "subroutine"        |
@@ -651,6 +652,24 @@
     return check_type(yyscanner);
 }
 
+int ES3_reserved_ES3_extension(TParseContext *context, TExtension extension, int token)
+{
+    struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
+    yyscan_t yyscanner = (yyscan_t) context->getScanner();
+
+    if(context->getShaderVersion() >= 300)
+    {
+        if (context->isExtensionEnabled(extension)) {
+            return token;
+        } else {
+            return reserved_word(yyscanner);
+        }
+    }
+
+    yylval->lex.string = AllocatePoolCharArray(yytext, yyleng);
+    return check_type(yyscanner);
+}
+
 int ES3_reserved_ES3_extension_ES3_1_keyword(TParseContext *context, TExtension extension, int token)
 {
     struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
diff --git a/src/compiler/translator/glslang.y b/src/compiler/translator/glslang.y
index 7a1cc4c..8a0c52f 100644
--- a/src/compiler/translator/glslang.y
+++ b/src/compiler/translator/glslang.y
@@ -164,7 +164,7 @@
 %token <lex> BVEC2 BVEC3 BVEC4 IVEC2 IVEC3 IVEC4 VEC2 VEC3 VEC4 UVEC2 UVEC3 UVEC4
 %token <lex> MATRIX2 MATRIX3 MATRIX4 IN_QUAL OUT_QUAL INOUT_QUAL UNIFORM BUFFER VARYING
 %token <lex> MATRIX2x3 MATRIX3x2 MATRIX2x4 MATRIX4x2 MATRIX3x4 MATRIX4x3
-%token <lex> CENTROID FLAT SMOOTH
+%token <lex> CENTROID FLAT SMOOTH NOPERSPECTIVE
 %token <lex> READONLY WRITEONLY COHERENT RESTRICT VOLATILE SHARED
 %token <lex> STRUCT VOID_TYPE WHILE
 %token <lex> SAMPLER2D SAMPLERCUBE SAMPLER_EXTERNAL_OES SAMPLER2DRECT SAMPLER2DARRAY
@@ -777,6 +777,13 @@
     | FLAT {
         $$ = EvqFlat;
     }
+    | NOPERSPECTIVE {
+        if (!context->checkCanUseExtension(@1, TExtension::NV_shader_noperspective_interpolation))
+        {
+            context->error(@1, "unsupported interpolation qualifier", "noperspective");
+        }
+        $$ = EvqNoPerspective;
+    }
     ;
 
 type_qualifier
diff --git a/src/compiler/translator/glslang_lex_autogen.cpp b/src/compiler/translator/glslang_lex_autogen.cpp
index f2f79e9..c6ef03e 100644
--- a/src/compiler/translator/glslang_lex_autogen.cpp
+++ b/src/compiler/translator/glslang_lex_autogen.cpp
@@ -432,60 +432,60 @@
     216, 215, 219, 186, 207, 213, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186,
 
     186, 186, 186, 186, 13,  186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186,
-    186, 16,  186, 186, 24,  186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186,
+    186, 16,  186, 186, 25,  186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186,
     186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186,
     186, 186, 186, 186, 186, 186, 208, 212, 244, 0,   198, 194, 0,   197, 191, 0,   193,
     187, 204, 205, 186, 186, 146, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186,
     186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 14,  186,
 
-    186, 186, 186, 186, 186, 186, 186, 186, 186, 29,  186, 186, 186, 186, 186, 186, 186,
-    186, 186, 186, 186, 186, 25,  186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186,
+    186, 186, 186, 186, 186, 186, 186, 186, 186, 30,  186, 186, 186, 186, 186, 186, 186,
+    186, 186, 186, 186, 186, 26,  186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186,
     186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186,
     186, 186, 186, 186, 186, 186, 186, 186, 0,   195, 0,   194, 196, 190, 186, 186, 186,
-    186, 32,  186, 186, 186, 19,  183, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186,
+    186, 33,  186, 186, 186, 19,  183, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186,
     17,  149, 186, 186, 186, 186, 22,  186, 186, 153, 164, 186, 186, 186, 186,
 
-    186, 186, 186, 186, 186, 186, 186, 186, 186, 161, 4,   37,  38,  39,  186, 186, 186,
+    186, 186, 186, 186, 186, 186, 186, 186, 186, 161, 4,   38,  39,  40,  186, 186, 186,
     186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186,
-    186, 186, 186, 186, 186, 152, 33,  186, 186, 30,  186, 186, 186, 186, 186, 186, 186,
-    49,  50,  51,  31,  186, 186, 186, 186, 186, 186, 186, 186, 11,  186, 55,  56,  57,
-    186, 147, 186, 186, 7,   186, 186, 186, 186, 173, 174, 175, 186, 34,  186, 165, 28,
-    176, 177, 178, 2,   170, 171, 172, 186, 186, 186, 26,  168, 186, 186, 186,
+    186, 186, 186, 186, 186, 152, 34,  186, 186, 31,  186, 186, 186, 186, 186, 186, 186,
+    50,  51,  52,  32,  186, 186, 186, 186, 186, 186, 186, 186, 11,  186, 56,  57,  58,
+    186, 147, 186, 186, 7,   186, 186, 186, 186, 173, 174, 175, 186, 35,  186, 165, 29,
+    176, 177, 178, 2,   170, 171, 172, 186, 186, 186, 27,  168, 186, 186, 186,
 
-    186, 186, 52,  53,  54,  186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 114,
+    186, 186, 53,  54,  55,  186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 114,
     186, 186, 186, 186, 186, 186, 186, 186, 162, 186, 186, 186, 186, 186, 186, 186, 186,
-    186, 186, 186, 148, 186, 186, 185, 58,  59,  60,  186, 186, 15,  186, 186, 186, 119,
+    186, 186, 186, 148, 186, 186, 185, 59,  60,  61,  186, 186, 15,  186, 186, 186, 119,
     186, 186, 9,   186, 186, 117, 186, 186, 186, 163, 158, 120, 186, 186, 186, 186, 186,
-    186, 154, 186, 186, 186, 186, 186, 88,  40,  43,  45,  44,  41,  47,  46,  48,  42,
-    186, 186, 186, 186, 169, 145, 186, 186, 156, 186, 186, 186, 36,  115, 27,
+    186, 154, 186, 186, 186, 186, 186, 89,  41,  44,  46,  45,  42,  48,  47,  49,  43,
+    186, 186, 186, 186, 169, 145, 186, 186, 156, 186, 186, 186, 37,  115, 28,
 
-    182, 23,  157, 87,  186, 167, 18,  186, 186, 186, 186, 186, 186, 186, 186, 186, 186,
-    186, 186, 186, 186, 186, 186, 20,  35,  186, 186, 186, 186, 186, 186, 121, 93,  99,
-    186, 186, 186, 186, 186, 90,  92,  3,   186, 186, 186, 186, 111, 186, 186, 186, 186,
+    182, 23,  157, 88,  186, 167, 18,  186, 186, 186, 186, 186, 186, 186, 186, 186, 186,
+    186, 186, 186, 186, 186, 186, 20,  36,  186, 186, 186, 186, 186, 186, 121, 94,  100,
+    186, 186, 186, 186, 186, 91,  93,  3,   186, 186, 186, 186, 112, 186, 186, 186, 186,
     186, 186, 186, 150, 186, 186, 186, 186, 186, 8,   186, 186, 10,  186, 186, 186, 186,
-    186, 186, 21,  107, 12,  159, 122, 94,  101, 186, 186, 186, 186, 186, 186, 186, 186,
-    186, 186, 186, 186, 186, 155, 186, 186, 186, 105, 112, 108, 186, 186, 186,
+    186, 186, 21,  108, 12,  159, 122, 95,  102, 186, 186, 186, 186, 186, 186, 186, 186,
+    186, 186, 186, 186, 186, 155, 186, 186, 186, 106, 113, 109, 186, 186, 186,
 
-    186, 186, 186, 186, 186, 151, 123, 95,  100, 186, 186, 166, 186, 109, 186, 186, 186,
-    186, 6,   186, 186, 186, 186, 186, 186, 186, 186, 186, 104, 160, 1,   186, 186, 186,
-    186, 186, 186, 184, 186, 118, 5,   179, 61,  64,  186, 186, 186, 186, 186, 186, 186,
-    186, 186, 186, 186, 186, 186, 186, 106, 186, 186, 186, 186, 186, 186, 102, 186, 186,
-    186, 186, 186, 136, 69,  70,  186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186,
-    186, 186, 186, 186, 116, 186, 186, 186, 103, 138, 74,  75,  186, 186, 186,
+    186, 186, 186, 186, 186, 151, 123, 96,  101, 186, 186, 166, 186, 110, 186, 186, 186,
+    186, 6,   186, 186, 186, 186, 186, 186, 186, 186, 186, 105, 160, 1,   186, 186, 186,
+    186, 186, 186, 184, 186, 118, 5,   179, 62,  65,  186, 186, 186, 186, 186, 186, 186,
+    186, 186, 186, 186, 186, 186, 186, 107, 186, 186, 186, 186, 186, 186, 103, 186, 186,
+    186, 186, 186, 136, 70,  71,  186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186,
+    186, 186, 186, 186, 116, 186, 186, 186, 104, 138, 75,  76,  186, 186, 186,
 
-    186, 110, 186, 186, 186, 186, 186, 186, 186, 131, 186, 186, 186, 186, 186, 186, 186,
-    186, 186, 186, 186, 68,  186, 186, 186, 186, 62,  186, 186, 186, 186, 186, 186, 186,
-    186, 186, 186, 186, 186, 186, 186, 186, 132, 124, 186, 96,  186, 186, 186, 73,  186,
-    186, 71,  186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186,
-    133, 186, 186, 78,  186, 186, 76,  186, 186, 125, 97,  186, 127, 186, 128, 186, 186,
-    186, 186, 186, 186, 113, 186, 186, 186, 186, 66,  186, 65,  142, 186, 186,
+    186, 111, 186, 186, 186, 186, 186, 186, 186, 131, 186, 186, 186, 186, 186, 186, 186,
+    186, 186, 186, 186, 69,  186, 186, 186, 186, 63,  186, 186, 186, 186, 186, 186, 186,
+    186, 186, 186, 186, 186, 186, 186, 186, 132, 124, 186, 97,  186, 186, 186, 74,  186,
+    186, 72,  186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186,
+    133, 186, 186, 79,  186, 186, 77,  186, 186, 125, 98,  186, 127, 186, 128, 186, 186,
+    186, 186, 186, 186, 24,  186, 186, 186, 186, 67,  186, 66,  142, 186, 186,
 
-    186, 126, 98,  186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 140, 143,
-    186, 134, 186, 67,  186, 186, 186, 186, 186, 186, 186, 186, 186, 141, 144, 186, 186,
-    186, 186, 137, 72,  186, 186, 186, 180, 186, 186, 186, 79,  186, 186, 186, 139, 77,
-    186, 186, 186, 186, 186, 186, 186, 186, 186, 83,  186, 186, 186, 186, 186, 186, 186,
-    186, 186, 84,  186, 186, 186, 186, 80,  186, 86,  85,  89,  186, 129, 130, 91,  186,
-    186, 186, 63,  186, 186, 186, 181, 186, 135, 81,  186, 186, 186, 186, 82,
+    186, 126, 99,  186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 140, 143,
+    186, 134, 186, 68,  186, 186, 186, 186, 186, 186, 186, 186, 186, 141, 144, 186, 186,
+    186, 186, 137, 73,  186, 186, 186, 180, 186, 186, 186, 80,  186, 186, 186, 139, 78,
+    186, 186, 186, 186, 186, 186, 186, 186, 186, 84,  186, 186, 186, 186, 186, 186, 186,
+    186, 186, 85,  186, 186, 186, 186, 81,  186, 87,  86,  90,  186, 129, 130, 92,  186,
+    186, 186, 64,  186, 186, 186, 181, 186, 135, 82,  186, 186, 186, 186, 83,
 
     0};
 
@@ -921,6 +921,7 @@
 static int ES3_reserved_ES3_1_extension_ES3_2_keyword(TParseContext *context,
                                                       TExtension extension,
                                                       int token);
+static int ES3_reserved_ES3_extension(TParseContext *context, TExtension extension, int token);
 static int ES3_reserved_ES3_extension_ES3_1_keyword(TParseContext *context,
                                                     TExtension extension,
                                                     int token);
@@ -1342,216 +1343,216 @@
                     YY_RULE_SETUP { return ES3_keyword(context, SMOOTH); }
                     YY_BREAK
                 case 24:
-                    YY_RULE_SETUP { return IN_QUAL; }
+                    YY_RULE_SETUP
+                    {
+                        return ES3_reserved_ES3_extension(
+                            context, TExtension::NV_shader_noperspective_interpolation,
+                            NOPERSPECTIVE);
+                    }
                     YY_BREAK
                 case 25:
-                    YY_RULE_SETUP { return OUT_QUAL; }
+                    YY_RULE_SETUP { return IN_QUAL; }
                     YY_BREAK
                 case 26:
-                    YY_RULE_SETUP { return INOUT_QUAL; }
+                    YY_RULE_SETUP { return OUT_QUAL; }
                     YY_BREAK
                 case 27:
-                    YY_RULE_SETUP { return ES3_1_keyword(context, SHARED); }
+                    YY_RULE_SETUP { return INOUT_QUAL; }
                     YY_BREAK
                 case 28:
-                    YY_RULE_SETUP { return FLOAT_TYPE; }
+                    YY_RULE_SETUP { return ES3_1_keyword(context, SHARED); }
                     YY_BREAK
                 case 29:
-                    YY_RULE_SETUP { return INT_TYPE; }
+                    YY_RULE_SETUP { return FLOAT_TYPE; }
                     YY_BREAK
                 case 30:
-                    YY_RULE_SETUP { return ES3_keyword(context, UINT_TYPE); }
+                    YY_RULE_SETUP { return INT_TYPE; }
                     YY_BREAK
                 case 31:
-                    YY_RULE_SETUP { return VOID_TYPE; }
+                    YY_RULE_SETUP { return ES3_keyword(context, UINT_TYPE); }
                     YY_BREAK
                 case 32:
-                    YY_RULE_SETUP { return BOOL_TYPE; }
+                    YY_RULE_SETUP { return VOID_TYPE; }
                     YY_BREAK
                 case 33:
+                    YY_RULE_SETUP { return BOOL_TYPE; }
+                    YY_BREAK
+                case 34:
                     YY_RULE_SETUP
                     {
                         yylval->lex.b = true;
                         return BOOLCONSTANT;
                     }
                     YY_BREAK
-                case 34:
+                case 35:
                     YY_RULE_SETUP
                     {
                         yylval->lex.b = false;
                         return BOOLCONSTANT;
                     }
                     YY_BREAK
-                case 35:
+                case 36:
                     YY_RULE_SETUP { return DISCARD; }
                     YY_BREAK
-                case 36:
+                case 37:
                     YY_RULE_SETUP { return RETURN; }
                     YY_BREAK
-                case 37:
+                case 38:
                     YY_RULE_SETUP { return MATRIX2; }
                     YY_BREAK
-                case 38:
+                case 39:
                     YY_RULE_SETUP { return MATRIX3; }
                     YY_BREAK
-                case 39:
+                case 40:
                     YY_RULE_SETUP { return MATRIX4; }
                     YY_BREAK
-                case 40:
+                case 41:
                     YY_RULE_SETUP { return ES3_keyword(context, MATRIX2); }
                     YY_BREAK
-                case 41:
+                case 42:
                     YY_RULE_SETUP { return ES3_keyword(context, MATRIX3); }
                     YY_BREAK
-                case 42:
+                case 43:
                     YY_RULE_SETUP { return ES3_keyword(context, MATRIX4); }
                     YY_BREAK
-                case 43:
+                case 44:
                     YY_RULE_SETUP { return ES3_keyword(context, MATRIX2x3); }
                     YY_BREAK
-                case 44:
+                case 45:
                     YY_RULE_SETUP { return ES3_keyword(context, MATRIX3x2); }
                     YY_BREAK
-                case 45:
+                case 46:
                     YY_RULE_SETUP { return ES3_keyword(context, MATRIX2x4); }
                     YY_BREAK
-                case 46:
+                case 47:
                     YY_RULE_SETUP { return ES3_keyword(context, MATRIX4x2); }
                     YY_BREAK
-                case 47:
+                case 48:
                     YY_RULE_SETUP { return ES3_keyword(context, MATRIX3x4); }
                     YY_BREAK
-                case 48:
+                case 49:
                     YY_RULE_SETUP { return ES3_keyword(context, MATRIX4x3); }
                     YY_BREAK
-                case 49:
+                case 50:
                     YY_RULE_SETUP { return VEC2; }
                     YY_BREAK
-                case 50:
+                case 51:
                     YY_RULE_SETUP { return VEC3; }
                     YY_BREAK
-                case 51:
+                case 52:
                     YY_RULE_SETUP { return VEC4; }
                     YY_BREAK
-                case 52:
+                case 53:
                     YY_RULE_SETUP { return IVEC2; }
                     YY_BREAK
-                case 53:
+                case 54:
                     YY_RULE_SETUP { return IVEC3; }
                     YY_BREAK
-                case 54:
+                case 55:
                     YY_RULE_SETUP { return IVEC4; }
                     YY_BREAK
-                case 55:
+                case 56:
                     YY_RULE_SETUP { return BVEC2; }
                     YY_BREAK
-                case 56:
+                case 57:
                     YY_RULE_SETUP { return BVEC3; }
                     YY_BREAK
-                case 57:
+                case 58:
                     YY_RULE_SETUP { return BVEC4; }
                     YY_BREAK
-                case 58:
+                case 59:
                     YY_RULE_SETUP { return ES3_keyword(context, UVEC2); }
                     YY_BREAK
-                case 59:
+                case 60:
                     YY_RULE_SETUP { return ES3_keyword(context, UVEC3); }
                     YY_BREAK
-                case 60:
+                case 61:
                     YY_RULE_SETUP { return ES3_keyword(context, UVEC4); }
                     YY_BREAK
-                case 61:
+                case 62:
                     YY_RULE_SETUP { return SAMPLER2D; }
                     YY_BREAK
-                case 62:
+                case 63:
                     YY_RULE_SETUP { return SAMPLERCUBE; }
                     YY_BREAK
-                case 63:
+                case 64:
                     YY_RULE_SETUP { return SAMPLER_EXTERNAL_OES; }
                     YY_BREAK
-                case 64:
+                case 65:
                     YY_RULE_SETUP
                     {
                         return ES2_reserved_ES2_extension_ES3_keyword(
                             context, TExtension::OES_texture_3D, SAMPLER3D);
                     }
                     YY_BREAK
-                case 65:
+                case 66:
                     YY_RULE_SETUP { return ES2_reserved_ES3_keyword(context, SAMPLER3DRECT); }
                     YY_BREAK
-                case 66:
+                case 67:
                     YY_RULE_SETUP { return SAMPLER2DRECT; }
                     YY_BREAK
-                case 67:
+                case 68:
                     YY_RULE_SETUP { return ES3_keyword(context, SAMPLER2DARRAY); }
                     YY_BREAK
-                case 68:
+                case 69:
                     YY_RULE_SETUP
                     {
                         return ES3_reserved_ES3_extension_ES3_1_keyword(
                             context, TExtension::ANGLE_texture_multisample, SAMPLER2DMS);
                     }
                     YY_BREAK
-                case 69:
+                case 70:
                     YY_RULE_SETUP { return ES3_keyword(context, ISAMPLER2D); }
                     YY_BREAK
-                case 70:
+                case 71:
                     YY_RULE_SETUP { return ES3_keyword(context, ISAMPLER3D); }
                     YY_BREAK
-                case 71:
+                case 72:
                     YY_RULE_SETUP { return ES3_keyword(context, ISAMPLERCUBE); }
                     YY_BREAK
-                case 72:
+                case 73:
                     YY_RULE_SETUP { return ES3_keyword(context, ISAMPLER2DARRAY); }
                     YY_BREAK
-                case 73:
+                case 74:
                     YY_RULE_SETUP
                     {
                         return ES3_reserved_ES3_extension_ES3_1_keyword(
                             context, TExtension::ANGLE_texture_multisample, ISAMPLER2DMS);
                     }
                     YY_BREAK
-                case 74:
+                case 75:
                     YY_RULE_SETUP { return ES3_keyword(context, USAMPLER2D); }
                     YY_BREAK
-                case 75:
+                case 76:
                     YY_RULE_SETUP { return ES3_keyword(context, USAMPLER3D); }
                     YY_BREAK
-                case 76:
+                case 77:
                     YY_RULE_SETUP { return ES3_keyword(context, USAMPLERCUBE); }
                     YY_BREAK
-                case 77:
+                case 78:
                     YY_RULE_SETUP { return ES3_keyword(context, USAMPLER2DARRAY); }
                     YY_BREAK
-                case 78:
+                case 79:
                     YY_RULE_SETUP
                     {
                         return ES3_reserved_ES3_extension_ES3_1_keyword(
                             context, TExtension::ANGLE_texture_multisample, USAMPLER2DMS);
                     }
                     YY_BREAK
-                case 79:
+                case 80:
                     YY_RULE_SETUP { return ES2_reserved_ES3_keyword(context, SAMPLER2DSHADOW); }
                     YY_BREAK
-                case 80:
+                case 81:
                     YY_RULE_SETUP { return ES3_keyword(context, SAMPLERCUBESHADOW); }
                     YY_BREAK
-                case 81:
-                    YY_RULE_SETUP { return ES3_keyword(context, SAMPLER2DARRAYSHADOW); }
-                    YY_BREAK
                 case 82:
-                    YY_RULE_SETUP
-                    {
-                        return ES3_extension(context, TExtension::EXT_YUV_target,
-                                             SAMPLEREXTERNAL2DY2YEXT);
-                    }
+                    YY_RULE_SETUP { return ES3_keyword(context, SAMPLER2DARRAYSHADOW); }
                     YY_BREAK
                 case 83:
                     YY_RULE_SETUP
                     {
-                        return ES3_reserved_ES3_1_extension_ES3_2_keyword(
-                            context, TExtension::OES_texture_storage_multisample_2d_array,
-                            SAMPLER2DMSARRAY);
+                        return ES3_extension(context, TExtension::EXT_YUV_target,
+                                             SAMPLEREXTERNAL2DY2YEXT);
                     }
                     YY_BREAK
                 case 84:
@@ -1559,7 +1560,7 @@
                     {
                         return ES3_reserved_ES3_1_extension_ES3_2_keyword(
                             context, TExtension::OES_texture_storage_multisample_2d_array,
-                            ISAMPLER2DMSARRAY);
+                            SAMPLER2DMSARRAY);
                     }
                     YY_BREAK
                 case 85:
@@ -1567,31 +1568,36 @@
                     {
                         return ES3_reserved_ES3_1_extension_ES3_2_keyword(
                             context, TExtension::OES_texture_storage_multisample_2d_array,
-                            USAMPLER2DMSARRAY);
+                            ISAMPLER2DMSARRAY);
                     }
                     YY_BREAK
                 case 86:
                     YY_RULE_SETUP
                     {
-                        return WEBGL_video_texture_extension(context, SAMPLERVIDEOWEBGL);
+                        return ES3_reserved_ES3_1_extension_ES3_2_keyword(
+                            context, TExtension::OES_texture_storage_multisample_2d_array,
+                            USAMPLER2DMSARRAY);
                     }
                     YY_BREAK
                 case 87:
-                    YY_RULE_SETUP { return STRUCT; }
+                    YY_RULE_SETUP
+                    {
+                        return WEBGL_video_texture_extension(context, SAMPLERVIDEOWEBGL);
+                    }
                     YY_BREAK
                 case 88:
-                    YY_RULE_SETUP { return ES3_keyword(context, LAYOUT); }
+                    YY_RULE_SETUP { return STRUCT; }
                     YY_BREAK
                 case 89:
+                    YY_RULE_SETUP { return ES3_keyword(context, LAYOUT); }
+                    YY_BREAK
+                case 90:
                     YY_RULE_SETUP
                     {
                         return ES3_extension(context, TExtension::EXT_YUV_target,
                                              YUVCSCSTANDARDEXT);
                     }
                     YY_BREAK
-                case 90:
-                    YY_RULE_SETUP { return yuvcscstandardext_constant(context); }
-                    YY_BREAK
                 case 91:
                     YY_RULE_SETUP { return yuvcscstandardext_constant(context); }
                     YY_BREAK
@@ -1599,60 +1605,63 @@
                     YY_RULE_SETUP { return yuvcscstandardext_constant(context); }
                     YY_BREAK
                 case 93:
-                    YY_RULE_SETUP { return ES3_reserved_ES3_1_keyword(context, IMAGE2D); }
+                    YY_RULE_SETUP { return yuvcscstandardext_constant(context); }
                     YY_BREAK
                 case 94:
-                    YY_RULE_SETUP { return ES3_reserved_ES3_1_keyword(context, IIMAGE2D); }
+                    YY_RULE_SETUP { return ES3_reserved_ES3_1_keyword(context, IMAGE2D); }
                     YY_BREAK
                 case 95:
-                    YY_RULE_SETUP { return ES3_reserved_ES3_1_keyword(context, UIMAGE2D); }
+                    YY_RULE_SETUP { return ES3_reserved_ES3_1_keyword(context, IIMAGE2D); }
                     YY_BREAK
                 case 96:
-                    YY_RULE_SETUP { return ES3_reserved_ES3_1_keyword(context, IMAGE2DARRAY); }
+                    YY_RULE_SETUP { return ES3_reserved_ES3_1_keyword(context, UIMAGE2D); }
                     YY_BREAK
                 case 97:
-                    YY_RULE_SETUP { return ES3_reserved_ES3_1_keyword(context, IIMAGE2DARRAY); }
+                    YY_RULE_SETUP { return ES3_reserved_ES3_1_keyword(context, IMAGE2DARRAY); }
                     YY_BREAK
                 case 98:
-                    YY_RULE_SETUP { return ES3_reserved_ES3_1_keyword(context, UIMAGE2DARRAY); }
+                    YY_RULE_SETUP { return ES3_reserved_ES3_1_keyword(context, IIMAGE2DARRAY); }
                     YY_BREAK
                 case 99:
-                    YY_RULE_SETUP { return ES3_reserved_ES3_1_keyword(context, IMAGE3D); }
+                    YY_RULE_SETUP { return ES3_reserved_ES3_1_keyword(context, UIMAGE2DARRAY); }
                     YY_BREAK
                 case 100:
-                    YY_RULE_SETUP { return ES3_reserved_ES3_1_keyword(context, UIMAGE3D); }
+                    YY_RULE_SETUP { return ES3_reserved_ES3_1_keyword(context, IMAGE3D); }
                     YY_BREAK
                 case 101:
-                    YY_RULE_SETUP { return ES3_reserved_ES3_1_keyword(context, IIMAGE3D); }
+                    YY_RULE_SETUP { return ES3_reserved_ES3_1_keyword(context, UIMAGE3D); }
                     YY_BREAK
                 case 102:
-                    YY_RULE_SETUP { return ES3_reserved_ES3_1_keyword(context, IIMAGECUBE); }
+                    YY_RULE_SETUP { return ES3_reserved_ES3_1_keyword(context, IIMAGE3D); }
                     YY_BREAK
                 case 103:
-                    YY_RULE_SETUP { return ES3_reserved_ES3_1_keyword(context, UIMAGECUBE); }
+                    YY_RULE_SETUP { return ES3_reserved_ES3_1_keyword(context, IIMAGECUBE); }
                     YY_BREAK
                 case 104:
-                    YY_RULE_SETUP { return ES3_reserved_ES3_1_keyword(context, IMAGECUBE); }
+                    YY_RULE_SETUP { return ES3_reserved_ES3_1_keyword(context, UIMAGECUBE); }
                     YY_BREAK
                 case 105:
-                    YY_RULE_SETUP { return ES3_reserved_ES3_1_keyword(context, READONLY); }
+                    YY_RULE_SETUP { return ES3_reserved_ES3_1_keyword(context, IMAGECUBE); }
                     YY_BREAK
                 case 106:
-                    YY_RULE_SETUP { return ES3_reserved_ES3_1_keyword(context, WRITEONLY); }
+                    YY_RULE_SETUP { return ES3_reserved_ES3_1_keyword(context, READONLY); }
                     YY_BREAK
                 case 107:
-                    YY_RULE_SETUP { return ES3_reserved_ES3_1_keyword(context, COHERENT); }
+                    YY_RULE_SETUP { return ES3_reserved_ES3_1_keyword(context, WRITEONLY); }
                     YY_BREAK
                 case 108:
-                    YY_RULE_SETUP { return ES3_reserved_ES3_1_keyword(context, RESTRICT); }
+                    YY_RULE_SETUP { return ES3_reserved_ES3_1_keyword(context, COHERENT); }
                     YY_BREAK
                 case 109:
-                    YY_RULE_SETUP { return ES2_reserved_ES3_1_keyword(context, VOLATILE); }
+                    YY_RULE_SETUP { return ES3_reserved_ES3_1_keyword(context, RESTRICT); }
                     YY_BREAK
                 case 110:
-                    YY_RULE_SETUP { return ES3_reserved_ES3_1_keyword(context, ATOMICUINT); }
+                    YY_RULE_SETUP { return ES2_reserved_ES3_1_keyword(context, VOLATILE); }
                     YY_BREAK
                 case 111:
+                    YY_RULE_SETUP { return ES3_reserved_ES3_1_keyword(context, ATOMICUINT); }
+                    YY_BREAK
+                case 112:
                     YY_RULE_SETUP
                     {
                         return ES3_1_reserved_ES3_1_extension_ES3_2_keyword(
@@ -1660,7 +1669,6 @@
                     }
                     YY_BREAK
                 /* Reserved keywords for GLSL ES 3.00 that are not reserved for GLSL ES 1.00 */
-                case 112:
                 case 113:
                 case 114:
                 case 115:
@@ -3350,6 +3358,27 @@
     return check_type(yyscanner);
 }
 
+int ES3_reserved_ES3_extension(TParseContext *context, TExtension extension, int token)
+{
+    struct yyguts_t *yyg = (struct yyguts_t *)context->getScanner();
+    yyscan_t yyscanner   = (yyscan_t)context->getScanner();
+
+    if (context->getShaderVersion() >= 300)
+    {
+        if (context->isExtensionEnabled(extension))
+        {
+            return token;
+        }
+        else
+        {
+            return reserved_word(yyscanner);
+        }
+    }
+
+    yylval->lex.string = AllocatePoolCharArray(yytext, yyleng);
+    return check_type(yyscanner);
+}
+
 int ES3_reserved_ES3_extension_ES3_1_keyword(TParseContext *context,
                                              TExtension extension,
                                              int token)
diff --git a/src/compiler/translator/glslang_tab_autogen.cpp b/src/compiler/translator/glslang_tab_autogen.cpp
index 8c9fd32..2fcd81e 100644
--- a/src/compiler/translator/glslang_tab_autogen.cpp
+++ b/src/compiler/translator/glslang_tab_autogen.cpp
@@ -196,109 +196,110 @@
     CENTROID                  = 308,
     FLAT                      = 309,
     SMOOTH                    = 310,
-    READONLY                  = 311,
-    WRITEONLY                 = 312,
-    COHERENT                  = 313,
-    RESTRICT                  = 314,
-    VOLATILE                  = 315,
-    SHARED                    = 316,
-    STRUCT                    = 317,
-    VOID_TYPE                 = 318,
-    WHILE                     = 319,
-    SAMPLER2D                 = 320,
-    SAMPLERCUBE               = 321,
-    SAMPLER_EXTERNAL_OES      = 322,
-    SAMPLER2DRECT             = 323,
-    SAMPLER2DARRAY            = 324,
-    ISAMPLER2D                = 325,
-    ISAMPLER3D                = 326,
-    ISAMPLERCUBE              = 327,
-    ISAMPLER2DARRAY           = 328,
-    USAMPLER2D                = 329,
-    USAMPLER3D                = 330,
-    USAMPLERCUBE              = 331,
-    USAMPLER2DARRAY           = 332,
-    SAMPLER2DMS               = 333,
-    ISAMPLER2DMS              = 334,
-    USAMPLER2DMS              = 335,
-    SAMPLER2DMSARRAY          = 336,
-    ISAMPLER2DMSARRAY         = 337,
-    USAMPLER2DMSARRAY         = 338,
-    SAMPLER3D                 = 339,
-    SAMPLER3DRECT             = 340,
-    SAMPLER2DSHADOW           = 341,
-    SAMPLERCUBESHADOW         = 342,
-    SAMPLER2DARRAYSHADOW      = 343,
-    SAMPLERVIDEOWEBGL         = 344,
-    SAMPLEREXTERNAL2DY2YEXT   = 345,
-    IMAGE2D                   = 346,
-    IIMAGE2D                  = 347,
-    UIMAGE2D                  = 348,
-    IMAGE3D                   = 349,
-    IIMAGE3D                  = 350,
-    UIMAGE3D                  = 351,
-    IMAGE2DARRAY              = 352,
-    IIMAGE2DARRAY             = 353,
-    UIMAGE2DARRAY             = 354,
-    IMAGECUBE                 = 355,
-    IIMAGECUBE                = 356,
-    UIMAGECUBE                = 357,
-    ATOMICUINT                = 358,
-    LAYOUT                    = 359,
-    YUVCSCSTANDARDEXT         = 360,
-    YUVCSCSTANDARDEXTCONSTANT = 361,
-    IDENTIFIER                = 362,
-    TYPE_NAME                 = 363,
-    FLOATCONSTANT             = 364,
-    INTCONSTANT               = 365,
-    UINTCONSTANT              = 366,
-    BOOLCONSTANT              = 367,
-    FIELD_SELECTION           = 368,
-    LEFT_OP                   = 369,
-    RIGHT_OP                  = 370,
-    INC_OP                    = 371,
-    DEC_OP                    = 372,
-    LE_OP                     = 373,
-    GE_OP                     = 374,
-    EQ_OP                     = 375,
-    NE_OP                     = 376,
-    AND_OP                    = 377,
-    OR_OP                     = 378,
-    XOR_OP                    = 379,
-    MUL_ASSIGN                = 380,
-    DIV_ASSIGN                = 381,
-    ADD_ASSIGN                = 382,
-    MOD_ASSIGN                = 383,
-    LEFT_ASSIGN               = 384,
-    RIGHT_ASSIGN              = 385,
-    AND_ASSIGN                = 386,
-    XOR_ASSIGN                = 387,
-    OR_ASSIGN                 = 388,
-    SUB_ASSIGN                = 389,
-    LEFT_PAREN                = 390,
-    RIGHT_PAREN               = 391,
-    LEFT_BRACKET              = 392,
-    RIGHT_BRACKET             = 393,
-    LEFT_BRACE                = 394,
-    RIGHT_BRACE               = 395,
-    DOT                       = 396,
-    COMMA                     = 397,
-    COLON                     = 398,
-    EQUAL                     = 399,
-    SEMICOLON                 = 400,
-    BANG                      = 401,
-    DASH                      = 402,
-    TILDE                     = 403,
-    PLUS                      = 404,
-    STAR                      = 405,
-    SLASH                     = 406,
-    PERCENT                   = 407,
-    LEFT_ANGLE                = 408,
-    RIGHT_ANGLE               = 409,
-    VERTICAL_BAR              = 410,
-    CARET                     = 411,
-    AMPERSAND                 = 412,
-    QUESTION                  = 413
+    NOPERSPECTIVE             = 311,
+    READONLY                  = 312,
+    WRITEONLY                 = 313,
+    COHERENT                  = 314,
+    RESTRICT                  = 315,
+    VOLATILE                  = 316,
+    SHARED                    = 317,
+    STRUCT                    = 318,
+    VOID_TYPE                 = 319,
+    WHILE                     = 320,
+    SAMPLER2D                 = 321,
+    SAMPLERCUBE               = 322,
+    SAMPLER_EXTERNAL_OES      = 323,
+    SAMPLER2DRECT             = 324,
+    SAMPLER2DARRAY            = 325,
+    ISAMPLER2D                = 326,
+    ISAMPLER3D                = 327,
+    ISAMPLERCUBE              = 328,
+    ISAMPLER2DARRAY           = 329,
+    USAMPLER2D                = 330,
+    USAMPLER3D                = 331,
+    USAMPLERCUBE              = 332,
+    USAMPLER2DARRAY           = 333,
+    SAMPLER2DMS               = 334,
+    ISAMPLER2DMS              = 335,
+    USAMPLER2DMS              = 336,
+    SAMPLER2DMSARRAY          = 337,
+    ISAMPLER2DMSARRAY         = 338,
+    USAMPLER2DMSARRAY         = 339,
+    SAMPLER3D                 = 340,
+    SAMPLER3DRECT             = 341,
+    SAMPLER2DSHADOW           = 342,
+    SAMPLERCUBESHADOW         = 343,
+    SAMPLER2DARRAYSHADOW      = 344,
+    SAMPLERVIDEOWEBGL         = 345,
+    SAMPLEREXTERNAL2DY2YEXT   = 346,
+    IMAGE2D                   = 347,
+    IIMAGE2D                  = 348,
+    UIMAGE2D                  = 349,
+    IMAGE3D                   = 350,
+    IIMAGE3D                  = 351,
+    UIMAGE3D                  = 352,
+    IMAGE2DARRAY              = 353,
+    IIMAGE2DARRAY             = 354,
+    UIMAGE2DARRAY             = 355,
+    IMAGECUBE                 = 356,
+    IIMAGECUBE                = 357,
+    UIMAGECUBE                = 358,
+    ATOMICUINT                = 359,
+    LAYOUT                    = 360,
+    YUVCSCSTANDARDEXT         = 361,
+    YUVCSCSTANDARDEXTCONSTANT = 362,
+    IDENTIFIER                = 363,
+    TYPE_NAME                 = 364,
+    FLOATCONSTANT             = 365,
+    INTCONSTANT               = 366,
+    UINTCONSTANT              = 367,
+    BOOLCONSTANT              = 368,
+    FIELD_SELECTION           = 369,
+    LEFT_OP                   = 370,
+    RIGHT_OP                  = 371,
+    INC_OP                    = 372,
+    DEC_OP                    = 373,
+    LE_OP                     = 374,
+    GE_OP                     = 375,
+    EQ_OP                     = 376,
+    NE_OP                     = 377,
+    AND_OP                    = 378,
+    OR_OP                     = 379,
+    XOR_OP                    = 380,
+    MUL_ASSIGN                = 381,
+    DIV_ASSIGN                = 382,
+    ADD_ASSIGN                = 383,
+    MOD_ASSIGN                = 384,
+    LEFT_ASSIGN               = 385,
+    RIGHT_ASSIGN              = 386,
+    AND_ASSIGN                = 387,
+    XOR_ASSIGN                = 388,
+    OR_ASSIGN                 = 389,
+    SUB_ASSIGN                = 390,
+    LEFT_PAREN                = 391,
+    RIGHT_PAREN               = 392,
+    LEFT_BRACKET              = 393,
+    RIGHT_BRACKET             = 394,
+    LEFT_BRACE                = 395,
+    RIGHT_BRACE               = 396,
+    DOT                       = 397,
+    COMMA                     = 398,
+    COLON                     = 399,
+    EQUAL                     = 400,
+    SEMICOLON                 = 401,
+    BANG                      = 402,
+    DASH                      = 403,
+    TILDE                     = 404,
+    PLUS                      = 405,
+    STAR                      = 406,
+    SLASH                     = 407,
+    PERCENT                   = 408,
+    LEFT_ANGLE                = 409,
+    RIGHT_ANGLE               = 410,
+    VERTICAL_BAR              = 411,
+    CARET                     = 412,
+    AMPERSAND                 = 413,
+    QUESTION                  = 414
 };
 #    endif
 
@@ -671,21 +672,21 @@
 #endif /* !YYCOPY_NEEDED */
 
 /* YYFINAL -- State number of the termination state.  */
-#define YYFINAL 141
+#define YYFINAL 142
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST 2995
+#define YYLAST 3017
 
 /* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS 159
+#define YYNTOKENS 160
 /* YYNNTS -- Number of nonterminals.  */
 #define YYNNTS 96
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES 303
+#define YYNRULES 304
 /* YYNSTATES -- Number of states.  */
-#define YYNSTATES 429
+#define YYNSTATES 430
 
 #define YYUNDEFTOK 2
-#define YYMAXUTOK 413
+#define YYMAXUTOK 414
 
 /* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
    as returned by yylex, with out-of-bounds checking.  */
@@ -715,7 +716,7 @@
     87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,  99,  100, 101, 102, 103, 104, 105,
     106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124,
     125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
-    144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158};
+    144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159};
 
 #if YYDEBUG
 /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
@@ -727,18 +728,19 @@
     507,  508,  514,  515,  521,  522,  528,  529,  535,  536,  542,  543,  544,  545,  549,  550,
     551,  555,  559,  563,  567,  574,  577,  583,  590,  597,  600,  603,  607,  611,  615,  619,
     623,  630,  637,  640,  647,  655,  672,  682,  685,  691,  695,  699,  703,  710,  717,  720,
-    724,  728,  733,  740,  744,  748,  752,  757,  764,  768,  774,  777,  783,  787,  794,  800,
-    806,  810,  814,  817,  820,  824,  832,  837,  841,  844,  847,  850,  853,  857,  860,  864,
-    867,  870,  873,  876,  879,  886,  893,  896,  899,  905,  912,  915,  921,  924,  927,  930,
-    936,  939,  946,  951,  958,  963,  974,  977,  980,  983,  986,  989,  993,  997,  1001, 1005,
-    1009, 1013, 1017, 1021, 1025, 1029, 1033, 1037, 1041, 1045, 1049, 1053, 1057, 1061, 1065, 1069,
-    1073, 1080, 1083, 1086, 1089, 1092, 1095, 1098, 1101, 1104, 1107, 1110, 1113, 1116, 1119, 1122,
-    1125, 1128, 1131, 1134, 1137, 1140, 1143, 1150, 1160, 1167, 1174, 1177, 1180, 1183, 1186, 1189,
-    1192, 1195, 1198, 1201, 1204, 1207, 1210, 1213, 1216, 1224, 1224, 1227, 1227, 1233, 1236, 1242,
-    1245, 1252, 1256, 1262, 1265, 1271, 1275, 1279, 1280, 1286, 1287, 1288, 1289, 1290, 1291, 1292,
-    1296, 1300, 1300, 1300, 1307, 1308, 1312, 1312, 1313, 1313, 1318, 1322, 1329, 1333, 1340, 1341,
-    1345, 1351, 1355, 1364, 1364, 1371, 1374, 1380, 1384, 1390, 1390, 1395, 1395, 1399, 1399, 1407,
-    1410, 1416, 1419, 1425, 1429, 1436, 1439, 1442, 1445, 1448, 1456, 1462, 1468, 1471, 1477, 1477};
+    724,  728,  733,  740,  744,  748,  752,  757,  764,  768,  774,  777,  780,  790,  794,  801,
+    807,  813,  817,  821,  824,  827,  831,  839,  844,  848,  851,  854,  857,  860,  864,  867,
+    871,  874,  877,  880,  883,  886,  893,  900,  903,  906,  912,  919,  922,  928,  931,  934,
+    937,  943,  946,  953,  958,  965,  970,  981,  984,  987,  990,  993,  996,  1000, 1004, 1008,
+    1012, 1016, 1020, 1024, 1028, 1032, 1036, 1040, 1044, 1048, 1052, 1056, 1060, 1064, 1068, 1072,
+    1076, 1080, 1087, 1090, 1093, 1096, 1099, 1102, 1105, 1108, 1111, 1114, 1117, 1120, 1123, 1126,
+    1129, 1132, 1135, 1138, 1141, 1144, 1147, 1150, 1157, 1167, 1174, 1181, 1184, 1187, 1190, 1193,
+    1196, 1199, 1202, 1205, 1208, 1211, 1214, 1217, 1220, 1223, 1231, 1231, 1234, 1234, 1240, 1243,
+    1249, 1252, 1259, 1263, 1269, 1272, 1278, 1282, 1286, 1287, 1293, 1294, 1295, 1296, 1297, 1298,
+    1299, 1303, 1307, 1307, 1307, 1314, 1315, 1319, 1319, 1320, 1320, 1325, 1329, 1336, 1340, 1347,
+    1348, 1352, 1358, 1362, 1371, 1371, 1378, 1381, 1387, 1391, 1397, 1397, 1402, 1402, 1406, 1406,
+    1414, 1417, 1423, 1426, 1432, 1436, 1443, 1446, 1449, 1452, 1455, 1463, 1469, 1475, 1478, 1484,
+    1484};
 #endif
 
 #if YYDEBUG || YYERROR_VERBOSE || 0
@@ -800,6 +802,7 @@
                                       "CENTROID",
                                       "FLAT",
                                       "SMOOTH",
+                                      "NOPERSPECTIVE",
                                       "READONLY",
                                       "WRITEONLY",
                                       "COHERENT",
@@ -1014,462 +1017,465 @@
     345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362,
     363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380,
     381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398,
-    399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413};
+    399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414};
 #endif
 
-#define YYPACT_NINF -370
+#define YYPACT_NINF -368
 
-#define yypact_value_is_default(Yystate) (!!((Yystate) == (-370)))
+#define yypact_value_is_default(Yystate) (!!((Yystate) == (-368)))
 
-#define YYTABLE_NINF -263
+#define YYTABLE_NINF -264
 
 #define yytable_value_is_error(Yytable_value) 0
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
    STATE-NUM.  */
 static const yytype_int16 yypact[] = {
-    2585, -370, -370, -370, -370, -370, 120,  -370, -370, -370, -370, -370, -370, -370, -370, -370,
-    -370, -370, -370, -370, -370, -370, -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
-    -370, -370, -370, -370, -370, -370, -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
-    -370, -68,  -370, -370, -370, -370, -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
-    -370, -370, -370, -370, -370, -370, -370, -370, -370, -370, -370, -370, -370, -370, -370, -370,
-    -370, -370, -370, -370, -370, -370, -370, -370, -370, -82,  -370, -370, -370, -88,  -60,  -58,
-    2691, -36,  -370, -77,  -370, 1402, -370, -370, -370, -370, -370, -370, -370, -370, -40,  -370,
-    2479, -370, -370, 2887, -370, -370, -370, -59,  -45,  -370, -50,  -370, 2691, -370, -370, -370,
-    2691, 49,   49,   -370, -30,  -109, -62,  -370, 2691, -370, -370, 1501, 4,    -370, -370, -8,
-    2691, -370, -370, 3,    -57,  -370, 413,  -370, -370, -370, -370, -40,  -96,  -370, 1882, -95,
-    -370, -370, 2691, 49,   2134, -370, -370, 14,   -370, -370, -370, -370, -370, 1882, 1882, 1882,
-    -370, -370, -370, -370, -370, -370, -370, -51,  -370, -370, -370, 15,   -44,  2007, 28,   -370,
-    1882, 2,    -80,  44,   -98,  40,   8,    13,   20,   58,   61,   -97,  -370, 48,   -370, 1629,
-    -370, 2249, 2691, 57,   -370, -45,  53,   56,   -370, 67,   68,   60,   1757, 73,   1882, 69,
-    76,   74,   -370, -370, 63,   -370, -370, -31,  -370, -88,  78,   -370, -370, -370, -370, 560,
-    -370, -370, -370, -370, -370, -370, 4,    1882, -69,  -370, -370, 1882, 49,   -40,  -29,  -370,
-    -85,  -370, -370, -370, -43,  -370, -370, 1882, 2789, -370, -370, 1882, 79,   -370, -370, -370,
-    1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882, 1882,
-    1882, 1882, 1882, 1882, -370, -370, 80,   -370, 2364, -370, -370, -370, -370, -370, 77,   -370,
-    1882, -370, -370, -3,   1882, 97,   -370, -370, -370, 707,  -370, -370, -370, -370, -370, -370,
-    -370, -370, -370, -370, -370, 1882, 1882, -370, -370, -370, -370, 1882, -370, 1,    4,    49,
-    -370, -112, -370, -370, 81,   75,   -370, 106,  -370, -370, -370, -370, -370, 2,    2,    -80,
-    -80,  44,   44,   44,   44,   -98,  -98,  40,   8,    13,   20,   58,   61,   29,   -370, -370,
-    179,  -50,  1001, 1148, -42,  -370, -34,  -370, 1275, 707,  -370, -370, -370, -370, -370, 1882,
-    -370, -370, 1882, 109,  -370, -370, -370, -370, 1275, 77,   -370, 75,   49,   2691, 110,  105,
-    114,  -370, 1882, -370, 102,  112,  235,  -370, 115,  111,  854,  -370, 113,  -32,  1882, 854,
-    77,   -370, 1882, -370, -370, -370, -370, 116,  75,   -370, -370, -370, -370};
+    2603, -368, -368, -368, -368, -368, 151,  -368, -368, -368, -368, -368, -368, -368, -368, -368,
+    -368, -368, -368, -368, -368, -368, -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
+    -368, -368, -368, -368, -368, -368, -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
+    -368, -368, -85,  -368, -368, -368, -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
+    -368, -368, -368, -368, -368, -368, -368, -368, -368, -368, -368, -368, -368, -368, -368, -368,
+    -368, -368, -368, -368, -368, -368, -368, -368, -368, -368, -79,  -368, -368, -368, -98,  -57,
+    -76,  2710, -113, -368, -24,  -368, 1410, -368, -368, -368, -368, -368, -368, -368, -368, -47,
+    -368, 2496, -368, -368, 2908, -368, -368, -368, -26,  -46,  -368, -5,   -368, 2710, -368, -368,
+    -368, 2710, 33,   33,   -368, -35,  -110, -97,  -368, 2710, -368, -368, 1510, -42,  -368, -368,
+    -2,   2710, -368, -368, 19,   -90,  -368, 414,  -368, -368, -368, -368, -47,  -70,  -368, 1894,
+    -69,  -368, -368, 2710, 33,   2148, -368, -368, 26,   -368, -368, -368, -368, -368, 1894, 1894,
+    1894, -368, -368, -368, -368, -368, -368, -368, -52,  -368, -368, -368, 29,   -48,  2020, 38,
+    -368, 1894, 8,    -40,  31,   -94,  28,   20,   23,   21,   61,   73,   -82,  -368, 60,   -368,
+    1639, -368, 2264, 2710, 41,   -368, -46,  54,   55,   -368, 66,   67,   59,   1768, 72,   1894,
+    65,   76,   74,   -368, -368, 62,   -368, -368, -37,  -368, -98,  77,   -368, -368, -368, -368,
+    562,  -368, -368, -368, -368, -368, -368, -42,  1894, -67,  -368, -368, 1894, 33,   -47,  -31,
+    -368, -88,  -368, -368, -368, -44,  -368, -368, 1894, 2809, -368, -368, 1894, 79,   -368, -368,
+    -368, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894, 1894,
+    1894, 1894, 1894, 1894, 1894, -368, -368, 75,   -368, 2380, -368, -368, -368, -368, -368, 78,
+    -368, 1894, -368, -368, -19,  1894, 97,   -368, -368, -368, 710,  -368, -368, -368, -368, -368,
+    -368, -368, -368, -368, -368, -368, 1894, 1894, -368, -368, -368, -368, 1894, -368, -7,   -42,
+    33,   -368, -107, -368, -368, 80,   100,  -368, 81,   -368, -368, -368, -368, -368, 8,    8,
+    -40,  -40,  31,   31,   31,   31,   -94,  -94,  28,   20,   23,   21,   61,   73,   25,   -368,
+    -368, 179,  -5,   1006, 1154, -43,  -368, -39,  -368, 1282, 710,  -368, -368, -368, -368, -368,
+    1894, -368, -368, 1894, 109,  -368, -368, -368, -368, 1282, 78,   -368, 100,  33,   2710, 110,
+    105,  112,  -368, 1894, -368, 102,  115,  235,  -368, 114,  111,  858,  -368, 113,  -32,  1894,
+    858,  78,   -368, 1894, -368, -368, -368, -368, 116,  100,  -368, -368, -368, -368};
 
 /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
    Performed when YYTABLE does not specify something else to do.  Zero
    means the default is an error.  */
 static const yytype_uint16 yydefact[] = {
-    0,   126, 127, 150, 151, 152, 0,   134, 136, 170, 167, 168, 169, 174, 175, 176, 177, 178, 179,
-    171, 172, 173, 180, 181, 182, 183, 184, 185, 137, 138, 139, 141, 142, 135, 186, 187, 188, 189,
-    190, 191, 140, 123, 122, 143, 144, 145, 146, 147, 148, 0,   166, 193, 195, 215, 217, 196, 199,
-    200, 201, 202, 205, 206, 207, 208, 197, 203, 209, 198, 204, 210, 194, 211, 212, 213, 214, 216,
-    218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 0,   192, 232, 301, 302, 0,
-    99,  98,  0,   110, 115, 131, 0,   132, 133, 124, 128, 120, 130, 129, 149, 160, 231, 0,   298,
-    300, 0,   2,   3,   235, 0,   0,   89,  0,   97,  0,   106, 100, 108, 0,   109, 0,   90,  2,
-    116, 0,   95,  0,   125, 121, 0,   161, 1,   299, 0,   0,   233, 159, 156, 0,   154, 0,   303,
-    101, 105, 107, 103, 111, 102, 0,   117, 88,  96,  0,   0,   0,   237, 10,  4,   8,   6,   7,
-    9,   31,  0,   0,   0,   162, 38,  37,  39,  36,  5,   12,  32,  14,  19,  20,  0,   0,   25,
-    0,   40,  0,   44,  47,  50,  55,  58,  60,  62,  64,  66,  68,  70,  87,  0,   29,  0,   91,
-    0,   0,   0,   153, 0,   0,   0,   283, 0,   0,   0,   0,   0,   0,   0,   0,   257, 266, 270,
-    40,  72,  85,  0,   246, 0,   149, 249, 268, 248, 247, 0,   250, 251, 252, 253, 254, 255, 104,
-    0,   112, 245, 119, 0,   0,   243, 0,   241, 0,   238, 33,  34,  0,   16,  17,  0,   0,   23,
-    22,  0,   166, 26,  28,  35,  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-    0,   0,   0,   0,   0,   0,   0,   163, 164, 0,   236, 0,   157, 158, 155, 294, 293, 264, 285,
-    0,   297, 295, 0,   0,   0,   278, 281, 256, 0,   75,  76,  78,  77,  80,  81,  82,  83,  84,
-    79,  74,  0,   0,   271, 267, 269, 114, 0,   118, 0,   244, 0,   239, 0,   92,  11,  0,   18,
-    30,  15,  21,  27,  41,  42,  43,  46,  45,  48,  49,  53,  54,  51,  52,  56,  57,  59,  61,
-    63,  65,  67,  69,  0,   165, 234, 0,   0,   0,   0,   0,   296, 0,   277, 0,   258, 73,  86,
-    113, 240, 242, 0,   93,  13,  0,   0,   263, 265, 288, 287, 290, 264, 275, 279, 0,   0,   0,
-    0,   0,   71,  0,   289, 0,   0,   274, 272, 0,   0,   0,   259, 0,   0,   291, 0,   264, 276,
-    0,   261, 282, 260, 94,  0,   292, 286, 273, 280, 284};
+    0,   127, 128, 151, 152, 153, 0,   135, 137, 171, 168, 169, 170, 175, 176, 177, 178, 179, 180,
+    172, 173, 174, 181, 182, 183, 184, 185, 186, 138, 139, 140, 142, 143, 136, 187, 188, 189, 190,
+    191, 192, 141, 123, 122, 124, 144, 145, 146, 147, 148, 149, 0,   167, 194, 196, 216, 218, 197,
+    200, 201, 202, 203, 206, 207, 208, 209, 198, 204, 210, 199, 205, 211, 195, 212, 213, 214, 215,
+    217, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 0,   193, 233, 302, 303,
+    0,   99,  98,  0,   110, 115, 132, 0,   133, 134, 125, 129, 120, 131, 130, 150, 161, 232, 0,
+    299, 301, 0,   2,   3,   236, 0,   0,   89,  0,   97,  0,   106, 100, 108, 0,   109, 0,   90,
+    2,   116, 0,   95,  0,   126, 121, 0,   162, 1,   300, 0,   0,   234, 160, 157, 0,   155, 0,
+    304, 101, 105, 107, 103, 111, 102, 0,   117, 88,  96,  0,   0,   0,   238, 10,  4,   8,   6,
+    7,   9,   31,  0,   0,   0,   163, 38,  37,  39,  36,  5,   12,  32,  14,  19,  20,  0,   0,
+    25,  0,   40,  0,   44,  47,  50,  55,  58,  60,  62,  64,  66,  68,  70,  87,  0,   29,  0,
+    91,  0,   0,   0,   154, 0,   0,   0,   284, 0,   0,   0,   0,   0,   0,   0,   0,   258, 267,
+    271, 40,  72,  85,  0,   247, 0,   150, 250, 269, 249, 248, 0,   251, 252, 253, 254, 255, 256,
+    104, 0,   112, 246, 119, 0,   0,   244, 0,   242, 0,   239, 33,  34,  0,   16,  17,  0,   0,
+    23,  22,  0,   167, 26,  28,  35,  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+    0,   0,   0,   0,   0,   0,   0,   0,   164, 165, 0,   237, 0,   158, 159, 156, 295, 294, 265,
+    286, 0,   298, 296, 0,   0,   0,   279, 282, 257, 0,   75,  76,  78,  77,  80,  81,  82,  83,
+    84,  79,  74,  0,   0,   272, 268, 270, 114, 0,   118, 0,   245, 0,   240, 0,   92,  11,  0,
+    18,  30,  15,  21,  27,  41,  42,  43,  46,  45,  48,  49,  53,  54,  51,  52,  56,  57,  59,
+    61,  63,  65,  67,  69,  0,   166, 235, 0,   0,   0,   0,   0,   297, 0,   278, 0,   259, 73,
+    86,  113, 241, 243, 0,   93,  13,  0,   0,   264, 266, 289, 288, 291, 265, 276, 280, 0,   0,
+    0,   0,   0,   71,  0,   290, 0,   0,   275, 273, 0,   0,   0,   260, 0,   0,   292, 0,   265,
+    277, 0,   262, 283, 261, 94,  0,   293, 287, 274, 281, 285};
 
 /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int16 yypgoto[] = {
-    -370, -48,  -370, -370, -370, -370, -370, -370, -7,   -370, -370, -370, -370, -52,  -370, -102,
-    -101, -148, -84,  -26,  -24,  -27,  -25,  -33,  -22,  -370, -134, -144, -370, -125, -199, -370,
-    17,   18,   -370, -370, -370, 136,  141,  138,  -370, -370, -349, -370, -90,  -370, -370, -99,
-    -370, -92,  263,  -370, -370, 59,   0,    -118, -370, -370, -370, -370, -132, -151, 19,   -65,
-    -240, -93,  -229, -351, -135, -370, -370, -140, -369, -370, -370, -119, -37,  -91,  -370, -370,
-    -370, -370, -370, -113, -370, -370, -370, -370, -370, -370, -370, -370, -370, 169,  -370, -370};
+    -368, -49,  -368, -368, -368, -368, -368, -368, -8,   -368, -368, -368, -368, -53,  -368, -104,
+    -103, -149, -99,  -28,  -27,  -25,  -23,  -29,  -22,  -368, -135, -145, -368, -138, -201, -368,
+    15,   17,   -368, -368, -368, 135,  142,  139,  -368, -368, -356, -368, -91,  -368, -368, -100,
+    -368, -93,  264,  -368, -368, 57,   0,    -116, -368, -368, -368, -368, -132, -154, 22,   -64,
+    -240, -96,  -230, -352, -136, -368, -368, -137, -367, -368, -368, -120, -36,  -92,  -368, -368,
+    -368, -368, -368, -112, -368, -368, -368, -368, -368, -368, -368, -368, -368, 169,  -368, -368};
 
 /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int16 yydefgoto[] = {
-    -1,  253, 181, 182, 183, 340, 184, 185, 186, 187, 188, 189, 190, 228, 192, 193,
-    194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 229, 230, 325, 231, 205, 136,
-    232, 233, 94,  95,  96,  125, 126, 127, 97,  98,  99,  100, 101, 102, 103, 104,
-    105, 106, 107, 108, 148, 149, 206, 140, 110, 111, 210, 144, 164, 165, 254, 255,
-    250, 235, 236, 237, 238, 313, 399, 420, 368, 369, 370, 421, 239, 240, 241, 407,
-    242, 408, 243, 398, 244, 376, 302, 371, 392, 404, 405, 245, 112, 113, 114, 122};
+    -1,  254, 182, 183, 184, 341, 185, 186, 187, 188, 189, 190, 191, 229, 193, 194,
+    195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 230, 231, 326, 232, 206, 137,
+    233, 234, 95,  96,  97,  126, 127, 128, 98,  99,  100, 101, 102, 103, 104, 105,
+    106, 107, 108, 109, 149, 150, 207, 141, 111, 112, 211, 145, 165, 166, 255, 256,
+    251, 236, 237, 238, 239, 314, 400, 421, 369, 370, 371, 422, 240, 241, 242, 408,
+    243, 409, 244, 399, 245, 377, 303, 372, 393, 405, 406, 246, 113, 114, 115, 123};
 
 /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM.  If
    positive, shift that token.  If negative, reduce the rule whose
    number is the opposite.  If YYTABLE_NINF, syntax error.  */
 static const yytype_int16 yytable[] = {
-    109, 119, 137, 151, 129, 204, 128, 330,  294, 138, 329, 332, 209, 257, 249, 159, 146, 92,  93,
-    389, 279, 280, 337, 309, 406, 383, 290,  396, 139, 137, 132, 117, 129, 384, 128, 158, 129, 246,
-    248, 116, 117, 139, 207, 396, 163, 269,  162, 426, 247, 251, 260, 133, 163, 120, 162, 281, 282,
-    121, 257, 419, 338, 291, 147, 137, 419,  261, 262, 275, 207, 276, 252, 118, 163, 204, 162, 331,
-    123, 160, 296, 212, 145, 155, 156, 161,  124, 213, 263, 191, 204, 150, 264, 380, 266, 339, 393,
-    307, 109, 139, 267, 326, 326, 109, 394,  249, 423, 157, 130, 249, 326, 131, 326, 326, 109, 335,
-    327, 143, 336, 163, 163, 162, 162, 258,  259, 345, 109, 3,   4,   5,   109, 92,  93,  353, 354,
-    355, 356, 334, 109, 208, 341, 326, 271,  207, 373, 335, 109, 257, 381, 211, 329, -30, 234, 265,
-    272, 273, 274, 191, 116, 117, 277, 278,  283, 284, 109, 270, 109, 285, 365, 297, 298, 286, 191,
-    326, 386, 349, 350, 287, 351, 352, 427,  372, 288, 378, 379, 374, 400, 289, 292, 249, 314, 315,
-    316, 317, 318, 319, 320, 321, 322, 323,  300, 357, 358, 301, 303, 304, 163, 305, 162, 324, 308,
-    109, 109, 311, 310, -29, 312, -24, -262, 326, 366, 385, 346, 347, 348, 191, 191, 191, 191, 191,
-    191, 191, 191, 191, 191, 191, 191, 191,  191, 191, 191, 234, 375, -31, 401, 387, 402, 411, 410,
-    414, 415, 204, 388, 395, 412, 416, 225,  418, 363, 344, 422, 359, 361, 428, 360, 362, 153, 152,
-    154, 395, 364, 115, 382, 333, 299, 417,  249, 425, 377, 413, 390, 403, 391, 142, 0,   0,   0,
-    0,   397, 0,   0,   424, 0,   0,   0,    0,   0,   0,   109, 0,   137, 0,   0,   0,   397, 0,
-    0,   138, 0,   0,   0,   0,   0,   0,    0,   234, 0,   0,   0,   0,   0,   0,   0,   0,   0,
-    0,   0,   0,   0,   0,   0,   0,   0,    191, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-    0,   0,   0,   0,   0,   0,   409, 0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-    0,   0,   0,   0,   0,   0,   0,   0,    0,   234, 234, 0,   0,   0,   0,   234, 234, 0,   0,
-    0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   234, 0,   0,   0,   0,   109, 0,
-    0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   234, 0,   0,   0,   0,   234, 1,   2,
-    3,   4,   5,   6,   7,   8,   9,   10,   11,  12,  214, 215, 216, 0,   217, 218, 219, 220, 221,
-    222, 223, 13,  14,  15,  16,  17,  18,   19,  20,  21,  22,  23,  24,  25,  26,  27,  28,  29,
-    30,  31,  32,  33,  34,  35,  36,  37,   38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,
-    49,  50,  224, 51,  52,  53,  54,  55,   56,  57,  58,  59,  60,  61,  62,  63,  64,  65,  66,
-    67,  68,  69,  70,  0,   71,  72,  73,   74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,
-    85,  86,  87,  88,  89,  90,  166, 167,  91,  168, 169, 170, 171, 172, 0,   0,   173, 174, 0,
-    0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,   0,   0,   0,   175, 0,   0,
-    0,   225, 226, 0,   0,   0,   0,   227,  177, 178, 179, 180, 1,   2,   3,   4,   5,   6,   7,
-    8,   9,   10,  11,  12,  214, 215, 216,  0,   217, 218, 219, 220, 221, 222, 223, 13,  14,  15,
-    16,  17,  18,  19,  20,  21,  22,  23,   24,  25,  26,  27,  28,  29,  30,  31,  32,  33,  34,
-    35,  36,  37,  38,  39,  40,  41,  42,   43,  44,  45,  46,  47,  48,  49,  50,  224, 51,  52,
-    53,  54,  55,  56,  57,  58,  59,  60,   61,  62,  63,  64,  65,  66,  67,  68,  69,  70,  0,
-    71,  72,  73,  74,  75,  76,  77,  78,   79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,
-    90,  166, 167, 91,  168, 169, 170, 171,  172, 0,   0,   173, 174, 0,   0,   0,   0,   0,   0,
-    0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   175, 0,   0,   0,   225, 328, 0,   0,
-    0,   0,   227, 177, 178, 179, 180, 1,    2,   3,   4,   5,   6,   7,   8,   9,   10,  11,  12,
-    214, 215, 216, 0,   217, 218, 219, 220,  221, 222, 223, 13,  14,  15,  16,  17,  18,  19,  20,
-    21,  22,  23,  24,  25,  26,  27,  28,   29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,
-    40,  41,  42,  43,  44,  45,  46,  47,   48,  49,  50,  224, 51,  52,  53,  54,  55,  56,  57,
-    58,  59,  60,  61,  62,  63,  64,  65,   66,  67,  68,  69,  70,  0,   71,  72,  73,  74,  75,
-    76,  77,  78,  79,  80,  81,  82,  83,   84,  85,  86,  87,  88,  89,  90,  166, 167, 91,  168,
-    169, 170, 171, 172, 0,   0,   173, 174,  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-    0,   0,   0,   0,   0,   0,   175, 0,    0,   0,   225, 0,   0,   0,   0,   0,   227, 177, 178,
-    179, 180, 1,   2,   3,   4,   5,   6,    7,   8,   9,   10,  11,  12,  214, 215, 216, 0,   217,
-    218, 219, 220, 221, 222, 223, 13,  14,   15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,
-    26,  27,  28,  29,  30,  31,  32,  33,   34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,
-    45,  46,  47,  48,  49,  50,  224, 51,   52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,
-    63,  64,  65,  66,  67,  68,  69,  70,   0,   71,  72,  73,  74,  75,  76,  77,  78,  79,  80,
-    81,  82,  83,  84,  85,  86,  87,  88,   89,  90,  166, 167, 91,  168, 169, 170, 171, 172, 0,
-    0,   173, 174, 0,   0,   0,   0,   0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-    0,   175, 0,   0,   0,   150, 0,   0,    0,   0,   0,   227, 177, 178, 179, 180, 1,   2,   3,
-    4,   5,   6,   7,   8,   9,   10,  11,   12,  214, 215, 216, 0,   217, 218, 219, 220, 221, 222,
-    223, 13,  14,  15,  16,  17,  18,  19,   20,  21,  22,  23,  24,  25,  26,  27,  28,  29,  30,
-    31,  32,  33,  34,  35,  36,  37,  38,   39,  40,  41,  42,  43,  44,  45,  46,  47,  48,  49,
-    50,  224, 51,  52,  53,  54,  55,  56,   57,  58,  59,  60,  61,  62,  63,  64,  65,  66,  67,
-    68,  69,  70,  0,   71,  72,  73,  74,   75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  85,
-    86,  87,  88,  89,  90,  166, 167, 91,   168, 169, 170, 171, 172, 0,   0,   173, 174, 0,   0,
-    0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,   0,   0,   175, 0,   0,   0,
-    0,   0,   0,   0,   0,   0,   227, 177,  178, 179, 180, 1,   2,   3,   4,   5,   6,   7,   8,
-    9,   10,  11,  12,  0,   0,   0,   0,    0,   0,   0,   0,   0,   0,   0,   13,  14,  15,  16,
-    17,  18,  19,  20,  21,  22,  23,  24,   25,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,
-    36,  37,  38,  39,  40,  41,  42,  43,   44,  45,  46,  47,  48,  49,  50,  0,   51,  52,  53,
-    54,  55,  56,  57,  58,  59,  60,  61,   62,  63,  64,  65,  66,  67,  68,  69,  70,  0,   71,
-    72,  73,  74,  75,  76,  77,  78,  79,   80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,
-    166, 167, 91,  168, 169, 170, 171, 172,  0,   0,   173, 174, 0,   0,   0,   0,   0,   0,   0,
-    0,   0,   0,   0,   0,   1,   2,   3,    4,   5,   175, 7,   8,   9,   10,  11,  12,  0,   0,
-    0,   227, 177, 178, 179, 180, 0,   0,    0,   13,  14,  15,  16,  17,  18,  19,  20,  21,  22,
-    23,  24,  25,  26,  27,  28,  29,  30,   31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,
-    42,  43,  44,  45,  46,  47,  48,  49,   50,  0,   51,  52,  53,  54,  55,  56,  57,  58,  59,
-    60,  61,  62,  63,  64,  65,  66,  67,   68,  69,  70,  0,   71,  72,  73,  74,  75,  76,  77,
-    78,  79,  80,  81,  82,  83,  84,  85,   86,  87,  88,  89,  90,  166, 167, 91,  168, 169, 170,
-    171, 172, 0,   0,   173, 174, 0,   0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,
-    2,   3,   4,   5,   175, 7,   8,   9,    10,  11,  12,  0,   0,   0,   0,   177, 178, 179, 180,
-    0,   0,   0,   13,  14,  15,  16,  17,   18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,
-    29,  30,  31,  32,  33,  34,  35,  36,   37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,
-    48,  49,  50,  0,   51,  52,  53,  54,   55,  56,  57,  58,  59,  60,  61,  62,  63,  64,  65,
-    66,  67,  68,  69,  70,  0,   71,  72,   73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,
-    84,  85,  86,  87,  88,  89,  90,  0,    134, 91,  0,   9,   10,  11,  12,  0,   0,   0,   0,
-    0,   0,   0,   0,   0,   0,   0,   13,   14,  15,  16,  17,  18,  19,  20,  21,  22,  23,  24,
-    25,  26,  27,  0,   0,   0,   0,   0,    135, 34,  35,  36,  37,  38,  39,  0,   0,   0,   0,
-    0,   0,   0,   0,   0,   49,  50,  0,    51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,
-    62,  63,  64,  65,  66,  67,  68,  69,   70,  0,   71,  72,  73,  74,  75,  76,  77,  78,  79,
-    80,  81,  82,  83,  84,  85,  86,  87,   88,  0,   90,  166, 167, 91,  168, 169, 170, 171, 172,
-    0,   0,   173, 174, 0,   0,   0,   0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-    0,   0,   175, 0,   0,   176, 9,   10,   11,  12,  0,   0,   0,   177, 178, 179, 180, 0,   0,
-    0,   0,   13,  14,  15,  16,  17,  18,   19,  20,  21,  22,  23,  24,  25,  26,  27,  0,   0,
-    0,   0,   0,   0,   34,  35,  36,  37,   38,  39,  0,   0,   0,   0,   0,   0,   0,   0,   0,
-    49,  50,  0,   51,  52,  53,  54,  55,   56,  57,  58,  59,  60,  61,  62,  63,  64,  65,  66,
-    67,  68,  69,  70,  0,   71,  72,  73,   74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,
-    85,  86,  87,  88,  0,   90,  166, 167,  91,  168, 169, 170, 171, 172, 0,   0,   173, 174, 0,
-    0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,   0,   0,   0,   175, 0,   0,
-    293, 9,   10,  11,  12,  0,   0,   0,    177, 178, 179, 180, 0,   0,   0,   0,   13,  14,  15,
-    16,  17,  18,  19,  20,  21,  22,  23,   24,  25,  26,  27,  0,   0,   0,   0,   0,   0,   34,
-    35,  36,  37,  38,  39,  0,   0,   0,    0,   0,   0,   0,   0,   0,   49,  50,  0,   51,  52,
-    53,  54,  55,  56,  57,  58,  59,  60,   61,  62,  63,  64,  65,  66,  67,  68,  69,  70,  0,
-    71,  72,  73,  74,  75,  76,  77,  78,   79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  0,
-    90,  166, 167, 91,  168, 169, 170, 171,  172, 0,   0,   173, 174, 0,   0,   0,   0,   0,   0,
-    0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   175, 9,   10,  11,  12,  0,   0,   0,
-    0,   0,   306, 177, 178, 179, 180, 0,    13,  14,  15,  16,  17,  18,  19,  20,  21,  22,  23,
-    24,  25,  26,  27,  0,   0,   0,   0,    0,   0,   34,  35,  36,  37,  38,  39,  0,   0,   0,
-    0,   0,   0,   0,   0,   0,   49,  50,   0,   51,  52,  53,  54,  55,  56,  57,  58,  59,  60,
-    61,  62,  63,  64,  65,  66,  67,  68,   69,  70,  0,   71,  72,  73,  74,  75,  76,  77,  78,
-    79,  80,  81,  82,  83,  84,  85,  86,   87,  88,  0,   90,  166, 167, 91,  168, 169, 170, 171,
-    172, 0,   0,   173, 174, 0,   0,   0,    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-    0,   0,   0,   175, 9,   10,  11,  12,   0,   0,   0,   0,   0,   0,   177, 178, 179, 180, 0,
-    13,  14,  15,  16,  17,  18,  19,  20,   21,  22,  23,  24,  25,  26,  27,  0,   0,   0,   0,
-    0,   0,   34,  35,  36,  37,  38,  39,   0,   0,   0,   0,   0,   0,   0,   0,   0,   49,  268,
-    0,   51,  52,  53,  54,  55,  56,  57,   58,  59,  60,  61,  62,  63,  64,  65,  66,  67,  68,
-    69,  70,  0,   71,  72,  73,  74,  75,   76,  77,  78,  79,  80,  81,  82,  83,  84,  85,  86,
-    87,  88,  0,   90,  166, 167, 91,  168,  169, 170, 171, 172, 0,   0,   173, 174, 0,   0,   0,
-    0,   0,   0,   0,   0,   0,   0,   0,    0,   1,   2,   3,   4,   5,   175, 7,   8,   9,   10,
-    11,  12,  0,   0,   0,   0,   177, 178,  179, 180, 0,   0,   0,   13,  14,  15,  16,  17,  18,
-    19,  20,  21,  22,  23,  24,  25,  26,   27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,
-    38,  39,  40,  41,  42,  43,  44,  45,   46,  47,  48,  49,  50,  0,   51,  52,  53,  54,  55,
-    56,  57,  58,  59,  60,  61,  62,  63,   64,  65,  66,  67,  68,  69,  70,  0,   71,  72,  73,
-    74,  75,  76,  77,  78,  79,  80,  81,   82,  83,  84,  85,  86,  87,  88,  89,  90,  0,   0,
-    91,  0,   0,   0,   0,   0,   0,   0,    0,   0,   1,   2,   3,   4,   5,   0,   7,   8,   9,
-    10,  11,  12,  0,   0,   0,   0,   0,    0,   0,   0,   0,   0,   256, 13,  14,  15,  16,  17,
-    18,  19,  20,  21,  22,  23,  24,  25,   26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,
-    37,  38,  39,  40,  41,  42,  43,  44,   45,  46,  47,  48,  49,  50,  0,   51,  52,  53,  54,
-    55,  56,  57,  58,  59,  60,  61,  62,   63,  64,  65,  66,  67,  68,  69,  70,  0,   71,  72,
-    73,  74,  75,  76,  77,  78,  79,  80,   81,  82,  83,  84,  85,  86,  87,  88,  89,  90,  0,
-    0,   91,  0,   0,   0,   0,   0,   0,    0,   0,   0,   1,   2,   3,   4,   5,   0,   7,   8,
-    9,   10,  11,  12,  0,   0,   0,   0,    0,   0,   0,   0,   0,   0,   295, 13,  14,  15,  16,
-    17,  18,  19,  20,  21,  22,  23,  24,   25,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,
-    36,  37,  38,  39,  40,  41,  42,  43,   44,  45,  46,  47,  48,  49,  50,  0,   51,  52,  53,
-    54,  55,  56,  57,  58,  59,  60,  61,   62,  63,  64,  65,  66,  67,  68,  69,  70,  0,   71,
-    72,  73,  74,  75,  76,  77,  78,  79,   80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,
-    0,   0,   91,  0,   0,   0,   0,   0,    0,   141, 0,   0,   1,   2,   3,   4,   5,   6,   7,
-    8,   9,   10,  11,  12,  0,   0,   0,    0,   0,   0,   0,   0,   0,   0,   367, 13,  14,  15,
-    16,  17,  18,  19,  20,  21,  22,  23,   24,  25,  26,  27,  28,  29,  30,  31,  32,  33,  34,
-    35,  36,  37,  38,  39,  40,  41,  42,   43,  44,  45,  46,  47,  48,  49,  50,  0,   51,  52,
-    53,  54,  55,  56,  57,  58,  59,  60,   61,  62,  63,  64,  65,  66,  67,  68,  69,  70,  0,
-    71,  72,  73,  74,  75,  76,  77,  78,   79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,
-    90,  0,   0,   91,  1,   2,   3,   4,    5,   6,   7,   8,   9,   10,  11,  12,  0,   0,   0,
-    0,   0,   0,   0,   0,   0,   0,   0,    13,  14,  15,  16,  17,  18,  19,  20,  21,  22,  23,
-    24,  25,  26,  27,  28,  29,  30,  31,   32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,
-    43,  44,  45,  46,  47,  48,  49,  50,   0,   51,  52,  53,  54,  55,  56,  57,  58,  59,  60,
-    61,  62,  63,  64,  65,  66,  67,  68,   69,  70,  0,   71,  72,  73,  74,  75,  76,  77,  78,
-    79,  80,  81,  82,  83,  84,  85,  86,   87,  88,  89,  90,  0,   0,   91,  1,   2,   3,   4,
-    5,   0,   7,   8,   9,   10,  11,  12,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-    13,  14,  15,  16,  17,  18,  19,  20,   21,  22,  23,  24,  25,  26,  27,  28,  29,  30,  31,
-    32,  33,  34,  35,  36,  37,  38,  39,   40,  41,  42,  43,  44,  45,  46,  47,  48,  49,  50,
-    0,   51,  52,  53,  54,  55,  56,  57,   58,  59,  60,  61,  62,  63,  64,  65,  66,  67,  68,
-    69,  70,  0,   71,  72,  73,  74,  75,   76,  77,  78,  79,  80,  81,  82,  83,  84,  85,  86,
-    87,  88,  89,  90,  0,   0,   91,  9,    10,  11,  12,  0,   0,   0,   0,   0,   0,   0,   0,
-    0,   0,   0,   13,  14,  15,  16,  17,   18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  0,
-    0,   0,   0,   0,   0,   34,  35,  36,   37,  38,  39,  0,   0,   0,   0,   0,   0,   0,   0,
-    0,   49,  50,  0,   51,  52,  53,  54,   55,  56,  57,  58,  59,  60,  61,  62,  63,  64,  65,
-    66,  67,  68,  69,  70,  0,   71,  72,   73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,
-    84,  85,  86,  87,  88,  0,   90,  0,    342, 91,  9,   10,  11,  12,  343, 0,   0,   0,   0,
-    0,   0,   0,   0,   0,   0,   13,  14,   15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25,
-    26,  27,  0,   0,   0,   0,   0,   0,    34,  35,  36,  37,  38,  39,  0,   0,   0,   0,   0,
-    0,   0,   0,   0,   49,  50,  0,   51,   52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,
-    63,  64,  65,  66,  67,  68,  69,  70,   0,   71,  72,  73,  74,  75,  76,  77,  78,  79,  80,
-    81,  82,  83,  84,  85,  86,  87,  88,   0,   90,  0,   0,   91};
+    110, 120, 138, 152, 130, 205, 129, 295, 331, 139,  330, 258, 333, 210, 250, 93,  147, 94,  160,
+    390, 338, 397, 310, 117, 118, 280, 281, 407, 140,  138, 131, 384, 130, 132, 129, 159, 130, 397,
+    261, 385, 247, 249, 291, 161, 164, 270, 163, 213,  122, 162, 427, 134, 164, 214, 163, 119, 258,
+    121, 339, 420, 282, 283, 148, 138, 420, 262, 263,  125, 140, 208, 253, 208, 164, 205, 163, 248,
+    252, 292, 332, 297, 124, 156, 157, 308, 133, 118,  264, 192, 205, 267, 265, 140, 381, 340, 394,
+    268, 208, 110, 395, 327, 327, 158, 110, 250, 327,  424, 327, 250, 276, 328, 277, 327, 336, 110,
+    146, 337, 144, 164, 164, 163, 163, 259, 260, 346,  327, 110, 342, 374, 93,  110, 94,  354, 355,
+    356, 357, 151, 336, 110, 335, 382, 272, 117, 118,  258, 209, 110, 278, 279, 330, 284, 285, 235,
+    298, 299, 366, 192, 3,   4,   5,   273, 274, 275,  -30, 110, 212, 110, 266, 373, 327, 387, 192,
+    375, 350, 351, 271, 352, 353, 288, 286, 428, 287,  379, 380, 401, 289, 358, 359, 250, 315, 316,
+    317, 318, 319, 320, 321, 322, 323, 324, 290, 293,  301, 302, 304, 305, 164, 306, 163, 325, 309,
+    311, 110, 110, 312, -29, 367, 313, -24, -31, -263, 386, 347, 348, 349, 192, 192, 192, 192, 192,
+    192, 192, 192, 192, 192, 192, 192, 192, 192, 192,  192, 396, 235, 376, 402, 327, 388, 403, 412,
+    411, 415, 205, 389, 413, 416, 417, 226, 396, 419,  345, 360, 423, 361, 364, 429, 362, 154, 414,
+    363, 153, 155, 365, 116, 300, 383, 418, 250, 334,  391, 425, 378, 426, 392, 404, 143, 0,   0,
+    0,   398, 0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   110, 138, 0,   0,   0,   398, 0,
+    0,   139, 0,   0,   0,   0,   0,   0,   0,   0,    235, 0,   0,   0,   0,   0,   0,   0,   0,
+    0,   0,   0,   0,   0,   0,   0,   0,   192, 0,    0,   0,   0,   0,   0,   0,   0,   0,   0,
+    0,   0,   0,   0,   0,   0,   410, 0,   0,   0,    0,   0,   0,   0,   0,   0,   0,   0,   0,
+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,    235, 235, 0,   0,   0,   0,   235, 235, 0,
+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   235, 0,   0,   0,   0,   110,
+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   235, 0,   0,   0,   0,   235, 1,
+    2,   3,   4,   5,   6,   7,   8,   9,   10,  11,   12,  215, 216, 217, 0,   218, 219, 220, 221,
+    222, 223, 224, 13,  14,  15,  16,  17,  18,  19,   20,  21,  22,  23,  24,  25,  26,  27,  28,
+    29,  30,  31,  32,  33,  34,  35,  36,  37,  38,   39,  40,  41,  42,  43,  44,  45,  46,  47,
+    48,  49,  50,  51,  225, 52,  53,  54,  55,  56,   57,  58,  59,  60,  61,  62,  63,  64,  65,
+    66,  67,  68,  69,  70,  71,  0,   72,  73,  74,   75,  76,  77,  78,  79,  80,  81,  82,  83,
+    84,  85,  86,  87,  88,  89,  90,  91,  167, 168,  92,  169, 170, 171, 172, 173, 0,   0,   174,
+    175, 0,   0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,   0,   0,   0,   176,
+    0,   0,   0,   226, 227, 0,   0,   0,   0,   228,  178, 179, 180, 181, 1,   2,   3,   4,   5,
+    6,   7,   8,   9,   10,  11,  12,  215, 216, 217,  0,   218, 219, 220, 221, 222, 223, 224, 13,
+    14,  15,  16,  17,  18,  19,  20,  21,  22,  23,   24,  25,  26,  27,  28,  29,  30,  31,  32,
+    33,  34,  35,  36,  37,  38,  39,  40,  41,  42,   43,  44,  45,  46,  47,  48,  49,  50,  51,
+    225, 52,  53,  54,  55,  56,  57,  58,  59,  60,   61,  62,  63,  64,  65,  66,  67,  68,  69,
+    70,  71,  0,   72,  73,  74,  75,  76,  77,  78,   79,  80,  81,  82,  83,  84,  85,  86,  87,
+    88,  89,  90,  91,  167, 168, 92,  169, 170, 171,  172, 173, 0,   0,   174, 175, 0,   0,   0,
+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   176, 0,   0,   0,   226,
+    329, 0,   0,   0,   0,   228, 178, 179, 180, 181,  1,   2,   3,   4,   5,   6,   7,   8,   9,
+    10,  11,  12,  215, 216, 217, 0,   218, 219, 220,  221, 222, 223, 224, 13,  14,  15,  16,  17,
+    18,  19,  20,  21,  22,  23,  24,  25,  26,  27,   28,  29,  30,  31,  32,  33,  34,  35,  36,
+    37,  38,  39,  40,  41,  42,  43,  44,  45,  46,   47,  48,  49,  50,  51,  225, 52,  53,  54,
+    55,  56,  57,  58,  59,  60,  61,  62,  63,  64,   65,  66,  67,  68,  69,  70,  71,  0,   72,
+    73,  74,  75,  76,  77,  78,  79,  80,  81,  82,   83,  84,  85,  86,  87,  88,  89,  90,  91,
+    167, 168, 92,  169, 170, 171, 172, 173, 0,   0,    174, 175, 0,   0,   0,   0,   0,   0,   0,
+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,    176, 0,   0,   0,   226, 0,   0,   0,   0,
+    0,   228, 178, 179, 180, 181, 1,   2,   3,   4,    5,   6,   7,   8,   9,   10,  11,  12,  215,
+    216, 217, 0,   218, 219, 220, 221, 222, 223, 224,  13,  14,  15,  16,  17,  18,  19,  20,  21,
+    22,  23,  24,  25,  26,  27,  28,  29,  30,  31,   32,  33,  34,  35,  36,  37,  38,  39,  40,
+    41,  42,  43,  44,  45,  46,  47,  48,  49,  50,   51,  225, 52,  53,  54,  55,  56,  57,  58,
+    59,  60,  61,  62,  63,  64,  65,  66,  67,  68,   69,  70,  71,  0,   72,  73,  74,  75,  76,
+    77,  78,  79,  80,  81,  82,  83,  84,  85,  86,   87,  88,  89,  90,  91,  167, 168, 92,  169,
+    170, 171, 172, 173, 0,   0,   174, 175, 0,   0,    0,   0,   0,   0,   0,   0,   0,   0,   0,
+    0,   0,   0,   0,   0,   0,   176, 0,   0,   0,    151, 0,   0,   0,   0,   0,   228, 178, 179,
+    180, 181, 1,   2,   3,   4,   5,   6,   7,   8,    9,   10,  11,  12,  215, 216, 217, 0,   218,
+    219, 220, 221, 222, 223, 224, 13,  14,  15,  16,   17,  18,  19,  20,  21,  22,  23,  24,  25,
+    26,  27,  28,  29,  30,  31,  32,  33,  34,  35,   36,  37,  38,  39,  40,  41,  42,  43,  44,
+    45,  46,  47,  48,  49,  50,  51,  225, 52,  53,   54,  55,  56,  57,  58,  59,  60,  61,  62,
+    63,  64,  65,  66,  67,  68,  69,  70,  71,  0,    72,  73,  74,  75,  76,  77,  78,  79,  80,
+    81,  82,  83,  84,  85,  86,  87,  88,  89,  90,   91,  167, 168, 92,  169, 170, 171, 172, 173,
+    0,   0,   174, 175, 0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,   0,   0,   0,   0,
+    0,   0,   176, 0,   0,   0,   0,   0,   0,   0,    0,   0,   228, 178, 179, 180, 181, 1,   2,
+    3,   4,   5,   6,   7,   8,   9,   10,  11,  12,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+    0,   0,   13,  14,  15,  16,  17,  18,  19,  20,   21,  22,  23,  24,  25,  26,  27,  28,  29,
+    30,  31,  32,  33,  34,  35,  36,  37,  38,  39,   40,  41,  42,  43,  44,  45,  46,  47,  48,
+    49,  50,  51,  0,   52,  53,  54,  55,  56,  57,   58,  59,  60,  61,  62,  63,  64,  65,  66,
+    67,  68,  69,  70,  71,  0,   72,  73,  74,  75,   76,  77,  78,  79,  80,  81,  82,  83,  84,
+    85,  86,  87,  88,  89,  90,  91,  167, 168, 92,   169, 170, 171, 172, 173, 0,   0,   174, 175,
+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   1,   2,   3,   4,   5,   176, 7,
+    8,   9,   10,  11,  12,  0,   0,   0,   228, 178,  179, 180, 181, 0,   0,   0,   13,  14,  15,
+    16,  17,  18,  19,  20,  21,  22,  23,  24,  25,   26,  27,  28,  29,  30,  31,  32,  33,  34,
+    35,  36,  37,  38,  39,  40,  41,  42,  43,  44,   45,  46,  47,  48,  49,  50,  51,  0,   52,
+    53,  54,  55,  56,  57,  58,  59,  60,  61,  62,   63,  64,  65,  66,  67,  68,  69,  70,  71,
+    0,   72,  73,  74,  75,  76,  77,  78,  79,  80,   81,  82,  83,  84,  85,  86,  87,  88,  89,
+    90,  91,  167, 168, 92,  169, 170, 171, 172, 173,  0,   0,   174, 175, 0,   0,   0,   0,   0,
+    0,   0,   0,   0,   0,   0,   0,   1,   2,   3,    4,   5,   176, 7,   8,   9,   10,  11,  12,
+    0,   0,   0,   0,   178, 179, 180, 181, 0,   0,    0,   13,  14,  15,  16,  17,  18,  19,  20,
+    21,  22,  23,  24,  25,  26,  27,  28,  29,  30,   31,  32,  33,  34,  35,  36,  37,  38,  39,
+    40,  41,  42,  43,  44,  45,  46,  47,  48,  49,   50,  51,  0,   52,  53,  54,  55,  56,  57,
+    58,  59,  60,  61,  62,  63,  64,  65,  66,  67,   68,  69,  70,  71,  0,   72,  73,  74,  75,
+    76,  77,  78,  79,  80,  81,  82,  83,  84,  85,   86,  87,  88,  89,  90,  91,  0,   135, 92,
+    0,   9,   10,  11,  12,  0,   0,   0,   0,   0,    0,   0,   0,   0,   0,   0,   13,  14,  15,
+    16,  17,  18,  19,  20,  21,  22,  23,  24,  25,   26,  27,  0,   0,   0,   0,   0,   136, 34,
+    35,  36,  37,  38,  39,  0,   0,   0,   0,   0,    0,   0,   0,   0,   0,   50,  51,  0,   52,
+    53,  54,  55,  56,  57,  58,  59,  60,  61,  62,   63,  64,  65,  66,  67,  68,  69,  70,  71,
+    0,   72,  73,  74,  75,  76,  77,  78,  79,  80,   81,  82,  83,  84,  85,  86,  87,  88,  89,
+    0,   91,  167, 168, 92,  169, 170, 171, 172, 173,  0,   0,   174, 175, 0,   0,   0,   0,   0,
+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   176, 0,   0,   177, 9,   10,  11,
+    12,  0,   0,   0,   178, 179, 180, 181, 0,   0,    0,   0,   13,  14,  15,  16,  17,  18,  19,
+    20,  21,  22,  23,  24,  25,  26,  27,  0,   0,    0,   0,   0,   0,   34,  35,  36,  37,  38,
+    39,  0,   0,   0,   0,   0,   0,   0,   0,   0,    0,   50,  51,  0,   52,  53,  54,  55,  56,
+    57,  58,  59,  60,  61,  62,  63,  64,  65,  66,   67,  68,  69,  70,  71,  0,   72,  73,  74,
+    75,  76,  77,  78,  79,  80,  81,  82,  83,  84,   85,  86,  87,  88,  89,  0,   91,  167, 168,
+    92,  169, 170, 171, 172, 173, 0,   0,   174, 175,  0,   0,   0,   0,   0,   0,   0,   0,   0,
+    0,   0,   0,   0,   0,   0,   0,   0,   176, 0,    0,   294, 9,   10,  11,  12,  0,   0,   0,
+    178, 179, 180, 181, 0,   0,   0,   0,   13,  14,   15,  16,  17,  18,  19,  20,  21,  22,  23,
+    24,  25,  26,  27,  0,   0,   0,   0,   0,   0,    34,  35,  36,  37,  38,  39,  0,   0,   0,
+    0,   0,   0,   0,   0,   0,   0,   50,  51,  0,    52,  53,  54,  55,  56,  57,  58,  59,  60,
+    61,  62,  63,  64,  65,  66,  67,  68,  69,  70,   71,  0,   72,  73,  74,  75,  76,  77,  78,
+    79,  80,  81,  82,  83,  84,  85,  86,  87,  88,   89,  0,   91,  167, 168, 92,  169, 170, 171,
+    172, 173, 0,   0,   174, 175, 0,   0,   0,   0,    0,   0,   0,   0,   0,   0,   0,   0,   0,
+    0,   0,   0,   0,   176, 9,   10,  11,  12,  0,    0,   0,   0,   0,   307, 178, 179, 180, 181,
+    0,   13,  14,  15,  16,  17,  18,  19,  20,  21,   22,  23,  24,  25,  26,  27,  0,   0,   0,
+    0,   0,   0,   34,  35,  36,  37,  38,  39,  0,    0,   0,   0,   0,   0,   0,   0,   0,   0,
+    50,  51,  0,   52,  53,  54,  55,  56,  57,  58,   59,  60,  61,  62,  63,  64,  65,  66,  67,
+    68,  69,  70,  71,  0,   72,  73,  74,  75,  76,   77,  78,  79,  80,  81,  82,  83,  84,  85,
+    86,  87,  88,  89,  0,   91,  167, 168, 92,  169,  170, 171, 172, 173, 0,   0,   174, 175, 0,
+    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,   0,   176, 9,   10,
+    11,  12,  0,   0,   0,   0,   0,   0,   178, 179,  180, 181, 0,   13,  14,  15,  16,  17,  18,
+    19,  20,  21,  22,  23,  24,  25,  26,  27,  0,    0,   0,   0,   0,   0,   34,  35,  36,  37,
+    38,  39,  0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   50,  269, 0,   52,  53,  54,  55,
+    56,  57,  58,  59,  60,  61,  62,  63,  64,  65,   66,  67,  68,  69,  70,  71,  0,   72,  73,
+    74,  75,  76,  77,  78,  79,  80,  81,  82,  83,   84,  85,  86,  87,  88,  89,  0,   91,  167,
+    168, 92,  169, 170, 171, 172, 173, 0,   0,   174,  175, 0,   0,   0,   0,   0,   0,   0,   0,
+    0,   0,   0,   0,   1,   2,   3,   4,   5,   176,  7,   8,   9,   10,  11,  12,  0,   0,   0,
+    0,   178, 179, 180, 181, 0,   0,   0,   13,  14,   15,  16,  17,  18,  19,  20,  21,  22,  23,
+    24,  25,  26,  27,  28,  29,  30,  31,  32,  33,   34,  35,  36,  37,  38,  39,  40,  41,  42,
+    43,  44,  45,  46,  47,  48,  49,  50,  51,  0,    52,  53,  54,  55,  56,  57,  58,  59,  60,
+    61,  62,  63,  64,  65,  66,  67,  68,  69,  70,   71,  0,   72,  73,  74,  75,  76,  77,  78,
+    79,  80,  81,  82,  83,  84,  85,  86,  87,  88,   89,  90,  91,  0,   0,   92,  0,   0,   0,
+    0,   0,   0,   0,   0,   0,   1,   2,   3,   4,    5,   0,   7,   8,   9,   10,  11,  12,  0,
+    0,   0,   0,   0,   0,   0,   0,   0,   0,   257,  13,  14,  15,  16,  17,  18,  19,  20,  21,
+    22,  23,  24,  25,  26,  27,  28,  29,  30,  31,   32,  33,  34,  35,  36,  37,  38,  39,  40,
+    41,  42,  43,  44,  45,  46,  47,  48,  49,  50,   51,  0,   52,  53,  54,  55,  56,  57,  58,
+    59,  60,  61,  62,  63,  64,  65,  66,  67,  68,   69,  70,  71,  0,   72,  73,  74,  75,  76,
+    77,  78,  79,  80,  81,  82,  83,  84,  85,  86,   87,  88,  89,  90,  91,  0,   0,   92,  0,
+    0,   0,   0,   0,   0,   0,   0,   0,   1,   2,    3,   4,   5,   0,   7,   8,   9,   10,  11,
+    12,  0,   0,   0,   0,   0,   0,   0,   0,   0,    0,   296, 13,  14,  15,  16,  17,  18,  19,
+    20,  21,  22,  23,  24,  25,  26,  27,  28,  29,   30,  31,  32,  33,  34,  35,  36,  37,  38,
+    39,  40,  41,  42,  43,  44,  45,  46,  47,  48,   49,  50,  51,  0,   52,  53,  54,  55,  56,
+    57,  58,  59,  60,  61,  62,  63,  64,  65,  66,   67,  68,  69,  70,  71,  0,   72,  73,  74,
+    75,  76,  77,  78,  79,  80,  81,  82,  83,  84,   85,  86,  87,  88,  89,  90,  91,  0,   0,
+    92,  0,   0,   0,   0,   0,   0,   142, 0,   0,    1,   2,   3,   4,   5,   6,   7,   8,   9,
+    10,  11,  12,  0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   368, 13,  14,  15,  16,  17,
+    18,  19,  20,  21,  22,  23,  24,  25,  26,  27,   28,  29,  30,  31,  32,  33,  34,  35,  36,
+    37,  38,  39,  40,  41,  42,  43,  44,  45,  46,   47,  48,  49,  50,  51,  0,   52,  53,  54,
+    55,  56,  57,  58,  59,  60,  61,  62,  63,  64,   65,  66,  67,  68,  69,  70,  71,  0,   72,
+    73,  74,  75,  76,  77,  78,  79,  80,  81,  82,   83,  84,  85,  86,  87,  88,  89,  90,  91,
+    0,   0,   92,  1,   2,   3,   4,   5,   6,   7,    8,   9,   10,  11,  12,  0,   0,   0,   0,
+    0,   0,   0,   0,   0,   0,   0,   13,  14,  15,   16,  17,  18,  19,  20,  21,  22,  23,  24,
+    25,  26,  27,  28,  29,  30,  31,  32,  33,  34,   35,  36,  37,  38,  39,  40,  41,  42,  43,
+    44,  45,  46,  47,  48,  49,  50,  51,  0,   52,   53,  54,  55,  56,  57,  58,  59,  60,  61,
+    62,  63,  64,  65,  66,  67,  68,  69,  70,  71,   0,   72,  73,  74,  75,  76,  77,  78,  79,
+    80,  81,  82,  83,  84,  85,  86,  87,  88,  89,   90,  91,  0,   0,   92,  1,   2,   3,   4,
+    5,   0,   7,   8,   9,   10,  11,  12,  0,   0,    0,   0,   0,   0,   0,   0,   0,   0,   0,
+    13,  14,  15,  16,  17,  18,  19,  20,  21,  22,   23,  24,  25,  26,  27,  28,  29,  30,  31,
+    32,  33,  34,  35,  36,  37,  38,  39,  40,  41,   42,  43,  44,  45,  46,  47,  48,  49,  50,
+    51,  0,   52,  53,  54,  55,  56,  57,  58,  59,   60,  61,  62,  63,  64,  65,  66,  67,  68,
+    69,  70,  71,  0,   72,  73,  74,  75,  76,  77,   78,  79,  80,  81,  82,  83,  84,  85,  86,
+    87,  88,  89,  90,  91,  0,   0,   92,  9,   10,   11,  12,  0,   0,   0,   0,   0,   0,   0,
+    0,   0,   0,   0,   13,  14,  15,  16,  17,  18,   19,  20,  21,  22,  23,  24,  25,  26,  27,
+    0,   0,   0,   0,   0,   0,   34,  35,  36,  37,   38,  39,  0,   0,   0,   0,   0,   0,   0,
+    0,   0,   0,   50,  51,  0,   52,  53,  54,  55,   56,  57,  58,  59,  60,  61,  62,  63,  64,
+    65,  66,  67,  68,  69,  70,  71,  0,   72,  73,   74,  75,  76,  77,  78,  79,  80,  81,  82,
+    83,  84,  85,  86,  87,  88,  89,  0,   91,  0,    343, 92,  9,   10,  11,  12,  344, 0,   0,
+    0,   0,   0,   0,   0,   0,   0,   0,   13,  14,   15,  16,  17,  18,  19,  20,  21,  22,  23,
+    24,  25,  26,  27,  0,   0,   0,   0,   0,   0,    34,  35,  36,  37,  38,  39,  0,   0,   0,
+    0,   0,   0,   0,   0,   0,   0,   50,  51,  0,    52,  53,  54,  55,  56,  57,  58,  59,  60,
+    61,  62,  63,  64,  65,  66,  67,  68,  69,  70,   71,  0,   72,  73,  74,  75,  76,  77,  78,
+    79,  80,  81,  82,  83,  84,  85,  86,  87,  88,   89,  0,   91,  0,   0,   92};
 
 static const yytype_int16 yycheck[] = {
-    0,   49,  101, 122, 96,  139, 96,  247, 207, 101, 239, 251, 144, 164, 158, 133, 61,  0,   0,
-    370, 118, 119, 107, 222, 393, 137, 123, 376, 137, 128, 107, 108, 124, 145, 124, 144, 128, 155,
-    156, 107, 108, 137, 137, 392, 136, 189, 136, 416, 144, 144, 175, 99,  144, 135, 144, 153, 154,
-    145, 209, 410, 145, 158, 107, 162, 415, 116, 117, 147, 137, 149, 162, 139, 164, 207, 164, 144,
-    136, 139, 210, 136, 139, 129, 130, 145, 142, 142, 137, 139, 222, 139, 141, 331, 136, 136, 136,
-    220, 96,  137, 142, 142, 142, 101, 136, 247, 136, 135, 142, 251, 142, 145, 142, 142, 112, 142,
-    145, 115, 145, 209, 210, 209, 210, 173, 174, 267, 124, 5,   6,   7,   128, 112, 112, 279, 280,
-    281, 282, 253, 136, 145, 263, 142, 192, 137, 145, 142, 144, 296, 145, 144, 377, 135, 150, 136,
-    150, 151, 152, 207, 107, 108, 114, 115, 120, 121, 162, 135, 164, 157, 291, 110, 111, 156, 222,
-    142, 143, 275, 276, 155, 277, 278, 418, 304, 122, 325, 326, 308, 383, 124, 138, 331, 125, 126,
-    127, 128, 129, 130, 131, 132, 133, 134, 145, 283, 284, 145, 135, 135, 296, 145, 296, 144, 135,
-    209, 210, 135, 143, 135, 140, 136, 139, 142, 138, 138, 272, 273, 274, 275, 276, 277, 278, 279,
-    280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 239, 143, 135, 386, 64,  135, 140, 136,
-    145, 136, 383, 369, 376, 138, 18,  139, 144, 289, 264, 145, 285, 287, 145, 286, 288, 128, 124,
-    128, 392, 290, 6,   335, 252, 213, 408, 418, 415, 313, 402, 371, 392, 371, 112, -1,  -1,  -1,
-    -1,  376, -1,  -1,  414, -1,  -1,  -1,  -1,  -1,  -1,  296, -1,  397, -1,  -1,  -1,  392, -1,
-    -1,  397, -1,  -1,  -1,  -1,  -1,  -1,  -1,  313, -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
-    -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  383, -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
-    -1,  -1,  -1,  -1,  -1,  -1,  396, -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
-    -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  370, 371, -1,  -1,  -1,  -1,  376, 377, -1,  -1,
-    -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  392, -1,  -1,  -1,  -1,  397, -1,
-    -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  410, -1,  -1,  -1,  -1,  415, 3,   4,
-    5,   6,   7,   8,   9,   10,  11,  12,  13,  14,  15,  16,  17,  -1,  19,  20,  21,  22,  23,
-    24,  25,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,
-    43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,
-    62,  63,  64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  80,
-    81,  82,  83,  84,  -1,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,  99,
-    100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, -1,  -1,  116, 117, -1,
-    -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  135, -1,  -1,
-    -1,  139, 140, -1,  -1,  -1,  -1,  145, 146, 147, 148, 149, 3,   4,   5,   6,   7,   8,   9,
-    10,  11,  12,  13,  14,  15,  16,  17,  -1,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,
-    29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,
-    48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,  64,  65,  66,
-    67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  -1,
-    86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,  99,  100, 101, 102, 103, 104,
-    105, 106, 107, 108, 109, 110, 111, 112, 113, -1,  -1,  116, 117, -1,  -1,  -1,  -1,  -1,  -1,
-    -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  135, -1,  -1,  -1,  139, 140, -1,  -1,
-    -1,  -1,  145, 146, 147, 148, 149, 3,   4,   5,   6,   7,   8,   9,   10,  11,  12,  13,  14,
-    15,  16,  17,  -1,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,  29,  30,  31,  32,  33,
-    34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  52,
-    53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,  71,
-    72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  -1,  86,  87,  88,  89,  90,
-    91,  92,  93,  94,  95,  96,  97,  98,  99,  100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
-    110, 111, 112, 113, -1,  -1,  116, 117, -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
-    -1,  -1,  -1,  -1,  -1,  -1,  135, -1,  -1,  -1,  139, -1,  -1,  -1,  -1,  -1,  145, 146, 147,
-    148, 149, 3,   4,   5,   6,   7,   8,   9,   10,  11,  12,  13,  14,  15,  16,  17,  -1,  19,
+    0,   50,  102, 123, 97,  140, 97,  208, 248, 102, 240, 165, 252, 145, 159, 0,   62,  0,   134,
+    371, 108, 377, 223, 108, 109, 119, 120, 394, 138, 129, 143, 138, 125, 146, 125, 145, 129, 393,
+    176, 146, 156, 157, 124, 140, 137, 190, 137, 137, 146, 146, 417, 100, 145, 143, 145, 140, 210,
+    136, 146, 411, 154, 155, 108, 163, 416, 117, 118, 143, 138, 138, 163, 138, 165, 208, 165, 145,
+    145, 159, 145, 211, 137, 130, 131, 221, 108, 109, 138, 140, 223, 137, 142, 138, 332, 137, 137,
+    143, 138, 97,  137, 143, 143, 136, 102, 248, 143, 137, 143, 252, 148, 146, 150, 143, 143, 113,
+    140, 146, 116, 210, 211, 210, 211, 174, 175, 268, 143, 125, 264, 146, 113, 129, 113, 280, 281,
+    282, 283, 140, 143, 137, 254, 146, 193, 108, 109, 297, 146, 145, 115, 116, 378, 121, 122, 151,
+    111, 112, 292, 208, 5,   6,   7,   151, 152, 153, 136, 163, 145, 165, 137, 305, 143, 144, 223,
+    309, 276, 277, 136, 278, 279, 156, 158, 419, 157, 326, 327, 384, 123, 284, 285, 332, 126, 127,
+    128, 129, 130, 131, 132, 133, 134, 135, 125, 139, 146, 146, 136, 136, 297, 146, 297, 145, 136,
+    144, 210, 211, 136, 136, 139, 141, 137, 136, 140, 139, 273, 274, 275, 276, 277, 278, 279, 280,
+    281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 377, 240, 144, 387, 143, 65,  136, 141,
+    137, 146, 384, 370, 139, 137, 18,  140, 393, 145, 265, 286, 146, 287, 290, 146, 288, 129, 403,
+    289, 125, 129, 291, 6,   214, 336, 409, 419, 253, 372, 415, 314, 416, 372, 393, 113, -1,  -1,
+    -1,  377, -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  297, 398, -1,  -1,  -1,  393, -1,
+    -1,  398, -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  314, -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
+    -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  384, -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
+    -1,  -1,  -1,  -1,  -1,  -1,  397, -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
+    -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  371, 372, -1,  -1,  -1,  -1,  377, 378, -1,
+    -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  393, -1,  -1,  -1,  -1,  398,
+    -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  411, -1,  -1,  -1,  -1,  416, 3,
+    4,   5,   6,   7,   8,   9,   10,  11,  12,  13,  14,  15,  16,  17,  -1,  19,  20,  21,  22,
+    23,  24,  25,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,
+    42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,
+    61,  62,  63,  64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,
+    80,  81,  82,  83,  84,  85,  -1,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,
+    99,  100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, -1,  -1,  117,
+    118, -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  136,
+    -1,  -1,  -1,  140, 141, -1,  -1,  -1,  -1,  146, 147, 148, 149, 150, 3,   4,   5,   6,   7,
+    8,   9,   10,  11,  12,  13,  14,  15,  16,  17,  -1,  19,  20,  21,  22,  23,  24,  25,  26,
+    27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,
+    46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,  64,
+    65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,
+    84,  85,  -1,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,  99,  100, 101, 102,
+    103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, -1,  -1,  117, 118, -1,  -1,  -1,
+    -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  136, -1,  -1,  -1,  140,
+    141, -1,  -1,  -1,  -1,  146, 147, 148, 149, 150, 3,   4,   5,   6,   7,   8,   9,   10,  11,
+    12,  13,  14,  15,  16,  17,  -1,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,  29,  30,
+    31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,  49,
+    50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,  64,  65,  66,  67,  68,
+    69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  85,  -1,  87,
+    88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,  99,  100, 101, 102, 103, 104, 105, 106,
+    107, 108, 109, 110, 111, 112, 113, 114, -1,  -1,  117, 118, -1,  -1,  -1,  -1,  -1,  -1,  -1,
+    -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  136, -1,  -1,  -1,  140, -1,  -1,  -1,  -1,
+    -1,  146, 147, 148, 149, 150, 3,   4,   5,   6,   7,   8,   9,   10,  11,  12,  13,  14,  15,
+    16,  17,  -1,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,  29,  30,  31,  32,  33,  34,
+    35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,
+    54,  55,  56,  57,  58,  59,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,  71,  72,
+    73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  85,  -1,  87,  88,  89,  90,  91,
+    92,  93,  94,  95,  96,  97,  98,  99,  100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
+    111, 112, 113, 114, -1,  -1,  117, 118, -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
+    -1,  -1,  -1,  -1,  -1,  -1,  136, -1,  -1,  -1,  140, -1,  -1,  -1,  -1,  -1,  146, 147, 148,
+    149, 150, 3,   4,   5,   6,   7,   8,   9,   10,  11,  12,  13,  14,  15,  16,  17,  -1,  19,
     20,  21,  22,  23,  24,  25,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,
     39,  40,  41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,
     58,  59,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,
-    77,  78,  79,  80,  81,  82,  83,  84,  -1,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,
-    96,  97,  98,  99,  100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, -1,
-    -1,  116, 117, -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
-    -1,  135, -1,  -1,  -1,  139, -1,  -1,  -1,  -1,  -1,  145, 146, 147, 148, 149, 3,   4,   5,
-    6,   7,   8,   9,   10,  11,  12,  13,  14,  15,  16,  17,  -1,  19,  20,  21,  22,  23,  24,
-    25,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,
-    44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,
-    63,  64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,
-    82,  83,  84,  -1,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,  99,  100,
-    101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, -1,  -1,  116, 117, -1,  -1,
-    -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  135, -1,  -1,  -1,
-    -1,  -1,  -1,  -1,  -1,  -1,  145, 146, 147, 148, 149, 3,   4,   5,   6,   7,   8,   9,   10,
-    11,  12,  13,  14,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  26,  27,  28,  29,
-    30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,
-    49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,  -1,  65,  66,  67,
-    68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  -1,  86,
-    87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,  99,  100, 101, 102, 103, 104, 105,
-    106, 107, 108, 109, 110, 111, 112, 113, -1,  -1,  116, 117, -1,  -1,  -1,  -1,  -1,  -1,  -1,
-    -1,  -1,  -1,  -1,  -1,  3,   4,   5,   6,   7,   135, 9,   10,  11,  12,  13,  14,  -1,  -1,
-    -1,  145, 146, 147, 148, 149, -1,  -1,  -1,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,
-    36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,
-    55,  56,  57,  58,  59,  60,  61,  62,  63,  -1,  65,  66,  67,  68,  69,  70,  71,  72,  73,
-    74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  -1,  86,  87,  88,  89,  90,  91,  92,
-    93,  94,  95,  96,  97,  98,  99,  100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
-    112, 113, -1,  -1,  116, 117, -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  3,
-    4,   5,   6,   7,   135, 9,   10,  11,  12,  13,  14,  -1,  -1,  -1,  -1,  146, 147, 148, 149,
-    -1,  -1,  -1,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,
-    42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,
-    61,  62,  63,  -1,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,
-    80,  81,  82,  83,  84,  -1,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,
-    99,  100, 101, 102, 103, 104, 105, -1,  107, 108, -1,  11,  12,  13,  14,  -1,  -1,  -1,  -1,
-    -1,  -1,  -1,  -1,  -1,  -1,  -1,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,
-    38,  39,  40,  -1,  -1,  -1,  -1,  -1,  145, 47,  48,  49,  50,  51,  52,  -1,  -1,  -1,  -1,
-    -1,  -1,  -1,  -1,  -1,  62,  63,  -1,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,
-    76,  77,  78,  79,  80,  81,  82,  83,  84,  -1,  86,  87,  88,  89,  90,  91,  92,  93,  94,
-    95,  96,  97,  98,  99,  100, 101, 102, 103, -1,  105, 106, 107, 108, 109, 110, 111, 112, 113,
-    -1,  -1,  116, 117, -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
-    -1,  -1,  135, -1,  -1,  138, 11,  12,  13,  14,  -1,  -1,  -1,  146, 147, 148, 149, -1,  -1,
-    -1,  -1,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  -1,  -1,
-    -1,  -1,  -1,  -1,  47,  48,  49,  50,  51,  52,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
-    62,  63,  -1,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  80,
-    81,  82,  83,  84,  -1,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,  99,
-    100, 101, 102, 103, -1,  105, 106, 107, 108, 109, 110, 111, 112, 113, -1,  -1,  116, 117, -1,
-    -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  135, -1,  -1,
-    138, 11,  12,  13,  14,  -1,  -1,  -1,  146, 147, 148, 149, -1,  -1,  -1,  -1,  26,  27,  28,
-    29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  -1,  -1,  -1,  -1,  -1,  -1,  47,
-    48,  49,  50,  51,  52,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  62,  63,  -1,  65,  66,
-    67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  -1,
-    86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,  99,  100, 101, 102, 103, -1,
-    105, 106, 107, 108, 109, 110, 111, 112, 113, -1,  -1,  116, 117, -1,  -1,  -1,  -1,  -1,  -1,
-    -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  135, 11,  12,  13,  14,  -1,  -1,  -1,
-    -1,  -1,  145, 146, 147, 148, 149, -1,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,
-    37,  38,  39,  40,  -1,  -1,  -1,  -1,  -1,  -1,  47,  48,  49,  50,  51,  52,  -1,  -1,  -1,
-    -1,  -1,  -1,  -1,  -1,  -1,  62,  63,  -1,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,
-    75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  -1,  86,  87,  88,  89,  90,  91,  92,  93,
-    94,  95,  96,  97,  98,  99,  100, 101, 102, 103, -1,  105, 106, 107, 108, 109, 110, 111, 112,
-    113, -1,  -1,  116, 117, -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
-    -1,  -1,  -1,  135, 11,  12,  13,  14,  -1,  -1,  -1,  -1,  -1,  -1,  146, 147, 148, 149, -1,
-    26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  -1,  -1,  -1,  -1,
-    -1,  -1,  47,  48,  49,  50,  51,  52,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  62,  63,
-    -1,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,
-    83,  84,  -1,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,  99,  100, 101,
-    102, 103, -1,  105, 106, 107, 108, 109, 110, 111, 112, 113, -1,  -1,  116, 117, -1,  -1,  -1,
-    -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  3,   4,   5,   6,   7,   135, 9,   10,  11,  12,
-    13,  14,  -1,  -1,  -1,  -1,  146, 147, 148, 149, -1,  -1,  -1,  26,  27,  28,  29,  30,  31,
-    32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,  49,  50,
-    51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,  -1,  65,  66,  67,  68,  69,
-    70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  -1,  86,  87,  88,
-    89,  90,  91,  92,  93,  94,  95,  96,  97,  98,  99,  100, 101, 102, 103, 104, 105, -1,  -1,
-    108, -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  3,   4,   5,   6,   7,   -1,  9,   10,  11,
-    12,  13,  14,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  140, 26,  27,  28,  29,  30,
-    31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,  49,
-    50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,  -1,  65,  66,  67,  68,
-    69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  -1,  86,  87,
-    88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,  99,  100, 101, 102, 103, 104, 105, -1,
-    -1,  108, -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  3,   4,   5,   6,   7,   -1,  9,   10,
-    11,  12,  13,  14,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  140, 26,  27,  28,  29,
-    30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,
-    49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,  -1,  65,  66,  67,
-    68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  -1,  86,
-    87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,  99,  100, 101, 102, 103, 104, 105,
-    -1,  -1,  108, -1,  -1,  -1,  -1,  -1,  -1,  0,   -1,  -1,  3,   4,   5,   6,   7,   8,   9,
-    10,  11,  12,  13,  14,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  140, 26,  27,  28,
+    77,  78,  79,  80,  81,  82,  83,  84,  85,  -1,  87,  88,  89,  90,  91,  92,  93,  94,  95,
+    96,  97,  98,  99,  100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114,
+    -1,  -1,  117, 118, -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
+    -1,  -1,  136, -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  146, 147, 148, 149, 150, 3,   4,
+    5,   6,   7,   8,   9,   10,  11,  12,  13,  14,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
+    -1,  -1,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,
+    43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,
+    62,  63,  64,  -1,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  80,
+    81,  82,  83,  84,  85,  -1,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,  99,
+    100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, -1,  -1,  117, 118,
+    -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  3,   4,   5,   6,   7,   136, 9,
+    10,  11,  12,  13,  14,  -1,  -1,  -1,  146, 147, 148, 149, 150, -1,  -1,  -1,  26,  27,  28,
     29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,
-    48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,  -1,  65,  66,
-    67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  -1,
-    86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,  99,  100, 101, 102, 103, 104,
-    105, -1,  -1,  108, 3,   4,   5,   6,   7,   8,   9,   10,  11,  12,  13,  14,  -1,  -1,  -1,
-    -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,
+    48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,  64,  -1,  66,
+    67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  85,
+    -1,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,  99,  100, 101, 102, 103, 104,
+    105, 106, 107, 108, 109, 110, 111, 112, 113, 114, -1,  -1,  117, 118, -1,  -1,  -1,  -1,  -1,
+    -1,  -1,  -1,  -1,  -1,  -1,  -1,  3,   4,   5,   6,   7,   136, 9,   10,  11,  12,  13,  14,
+    -1,  -1,  -1,  -1,  147, 148, 149, 150, -1,  -1,  -1,  26,  27,  28,  29,  30,  31,  32,  33,
+    34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  52,
+    53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,  64,  -1,  66,  67,  68,  69,  70,  71,
+    72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  85,  -1,  87,  88,  89,  90,
+    91,  92,  93,  94,  95,  96,  97,  98,  99,  100, 101, 102, 103, 104, 105, 106, -1,  108, 109,
+    -1,  11,  12,  13,  14,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  26,  27,  28,
+    29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  -1,  -1,  -1,  -1,  -1,  146, 47,
+    48,  49,  50,  51,  52,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  63,  64,  -1,  66,
+    67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  85,
+    -1,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,  99,  100, 101, 102, 103, 104,
+    -1,  106, 107, 108, 109, 110, 111, 112, 113, 114, -1,  -1,  117, 118, -1,  -1,  -1,  -1,  -1,
+    -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  136, -1,  -1,  139, 11,  12,  13,
+    14,  -1,  -1,  -1,  147, 148, 149, 150, -1,  -1,  -1,  -1,  26,  27,  28,  29,  30,  31,  32,
+    33,  34,  35,  36,  37,  38,  39,  40,  -1,  -1,  -1,  -1,  -1,  -1,  47,  48,  49,  50,  51,
+    52,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  63,  64,  -1,  66,  67,  68,  69,  70,
+    71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  85,  -1,  87,  88,  89,
+    90,  91,  92,  93,  94,  95,  96,  97,  98,  99,  100, 101, 102, 103, 104, -1,  106, 107, 108,
+    109, 110, 111, 112, 113, 114, -1,  -1,  117, 118, -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
+    -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  136, -1,  -1,  139, 11,  12,  13,  14,  -1,  -1,  -1,
+    147, 148, 149, 150, -1,  -1,  -1,  -1,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,
+    37,  38,  39,  40,  -1,  -1,  -1,  -1,  -1,  -1,  47,  48,  49,  50,  51,  52,  -1,  -1,  -1,
+    -1,  -1,  -1,  -1,  -1,  -1,  -1,  63,  64,  -1,  66,  67,  68,  69,  70,  71,  72,  73,  74,
+    75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  85,  -1,  87,  88,  89,  90,  91,  92,  93,
+    94,  95,  96,  97,  98,  99,  100, 101, 102, 103, 104, -1,  106, 107, 108, 109, 110, 111, 112,
+    113, 114, -1,  -1,  117, 118, -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
+    -1,  -1,  -1,  -1,  136, 11,  12,  13,  14,  -1,  -1,  -1,  -1,  -1,  146, 147, 148, 149, 150,
+    -1,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  -1,  -1,  -1,
+    -1,  -1,  -1,  47,  48,  49,  50,  51,  52,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
+    63,  64,  -1,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,
+    82,  83,  84,  85,  -1,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,  99,  100,
+    101, 102, 103, 104, -1,  106, 107, 108, 109, 110, 111, 112, 113, 114, -1,  -1,  117, 118, -1,
+    -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  136, 11,  12,
+    13,  14,  -1,  -1,  -1,  -1,  -1,  -1,  147, 148, 149, 150, -1,  26,  27,  28,  29,  30,  31,
+    32,  33,  34,  35,  36,  37,  38,  39,  40,  -1,  -1,  -1,  -1,  -1,  -1,  47,  48,  49,  50,
+    51,  52,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  63,  64,  -1,  66,  67,  68,  69,
+    70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  85,  -1,  87,  88,
+    89,  90,  91,  92,  93,  94,  95,  96,  97,  98,  99,  100, 101, 102, 103, 104, -1,  106, 107,
+    108, 109, 110, 111, 112, 113, 114, -1,  -1,  117, 118, -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
+    -1,  -1,  -1,  -1,  3,   4,   5,   6,   7,   136, 9,   10,  11,  12,  13,  14,  -1,  -1,  -1,
+    -1,  147, 148, 149, 150, -1,  -1,  -1,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,
     37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,
-    56,  57,  58,  59,  60,  61,  62,  63,  -1,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,
-    75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  -1,  86,  87,  88,  89,  90,  91,  92,  93,
-    94,  95,  96,  97,  98,  99,  100, 101, 102, 103, 104, 105, -1,  -1,  108, 3,   4,   5,   6,
+    56,  57,  58,  59,  60,  61,  62,  63,  64,  -1,  66,  67,  68,  69,  70,  71,  72,  73,  74,
+    75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  85,  -1,  87,  88,  89,  90,  91,  92,  93,
+    94,  95,  96,  97,  98,  99,  100, 101, 102, 103, 104, 105, 106, -1,  -1,  109, -1,  -1,  -1,
+    -1,  -1,  -1,  -1,  -1,  -1,  3,   4,   5,   6,   7,   -1,  9,   10,  11,  12,  13,  14,  -1,
+    -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  141, 26,  27,  28,  29,  30,  31,  32,  33,  34,
+    35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,
+    54,  55,  56,  57,  58,  59,  60,  61,  62,  63,  64,  -1,  66,  67,  68,  69,  70,  71,  72,
+    73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  85,  -1,  87,  88,  89,  90,  91,
+    92,  93,  94,  95,  96,  97,  98,  99,  100, 101, 102, 103, 104, 105, 106, -1,  -1,  109, -1,
+    -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  3,   4,   5,   6,   7,   -1,  9,   10,  11,  12,  13,
+    14,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  141, 26,  27,  28,  29,  30,  31,  32,
+    33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51,
+    52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,  64,  -1,  66,  67,  68,  69,  70,
+    71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  85,  -1,  87,  88,  89,
+    90,  91,  92,  93,  94,  95,  96,  97,  98,  99,  100, 101, 102, 103, 104, 105, 106, -1,  -1,
+    109, -1,  -1,  -1,  -1,  -1,  -1,  0,   -1,  -1,  3,   4,   5,   6,   7,   8,   9,   10,  11,
+    12,  13,  14,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  141, 26,  27,  28,  29,  30,
+    31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,  49,
+    50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,  64,  -1,  66,  67,  68,
+    69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  85,  -1,  87,
+    88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,  99,  100, 101, 102, 103, 104, 105, 106,
+    -1,  -1,  109, 3,   4,   5,   6,   7,   8,   9,   10,  11,  12,  13,  14,  -1,  -1,  -1,  -1,
+    -1,  -1,  -1,  -1,  -1,  -1,  -1,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,
+    38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,
+    57,  58,  59,  60,  61,  62,  63,  64,  -1,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,
+    76,  77,  78,  79,  80,  81,  82,  83,  84,  85,  -1,  87,  88,  89,  90,  91,  92,  93,  94,
+    95,  96,  97,  98,  99,  100, 101, 102, 103, 104, 105, 106, -1,  -1,  109, 3,   4,   5,   6,
     7,   -1,  9,   10,  11,  12,  13,  14,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
     26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,
     45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,
-    -1,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,
-    83,  84,  -1,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,  99,  100, 101,
-    102, 103, 104, 105, -1,  -1,  108, 11,  12,  13,  14,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
-    -1,  -1,  -1,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,  -1,
-    -1,  -1,  -1,  -1,  -1,  47,  48,  49,  50,  51,  52,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
-    -1,  62,  63,  -1,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,
-    80,  81,  82,  83,  84,  -1,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,
-    99,  100, 101, 102, 103, -1,  105, -1,  107, 108, 11,  12,  13,  14,  113, -1,  -1,  -1,  -1,
-    -1,  -1,  -1,  -1,  -1,  -1,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,
-    39,  40,  -1,  -1,  -1,  -1,  -1,  -1,  47,  48,  49,  50,  51,  52,  -1,  -1,  -1,  -1,  -1,
-    -1,  -1,  -1,  -1,  62,  63,  -1,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,
-    77,  78,  79,  80,  81,  82,  83,  84,  -1,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,
-    96,  97,  98,  99,  100, 101, 102, 103, -1,  105, -1,  -1,  108};
+    64,  -1,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,
+    83,  84,  85,  -1,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,  98,  99,  100, 101,
+    102, 103, 104, 105, 106, -1,  -1,  109, 11,  12,  13,  14,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
+    -1,  -1,  -1,  -1,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,
+    -1,  -1,  -1,  -1,  -1,  -1,  47,  48,  49,  50,  51,  52,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
+    -1,  -1,  -1,  63,  64,  -1,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,
+    79,  80,  81,  82,  83,  84,  85,  -1,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,
+    98,  99,  100, 101, 102, 103, 104, -1,  106, -1,  108, 109, 11,  12,  13,  14,  114, -1,  -1,
+    -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,
+    37,  38,  39,  40,  -1,  -1,  -1,  -1,  -1,  -1,  47,  48,  49,  50,  51,  52,  -1,  -1,  -1,
+    -1,  -1,  -1,  -1,  -1,  -1,  -1,  63,  64,  -1,  66,  67,  68,  69,  70,  71,  72,  73,  74,
+    75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  85,  -1,  87,  88,  89,  90,  91,  92,  93,
+    94,  95,  96,  97,  98,  99,  100, 101, 102, 103, 104, -1,  106, -1,  -1,  109};
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
    symbol of state STATE-NUM.  */
 static const yytype_uint8 yystos[] = {
     0,   3,   4,   5,   6,   7,   8,   9,   10,  11,  12,  13,  14,  26,  27,  28,  29,  30,  31,
     32,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,  49,  50,
-    51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,  65,  66,  67,  68,  69,  70,
-    71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  86,  87,  88,  89,  90,
-    91,  92,  93,  94,  95,  96,  97,  98,  99,  100, 101, 102, 103, 104, 105, 108, 191, 192, 193,
-    194, 195, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 213, 215, 216, 251, 252,
-    253, 209, 107, 108, 139, 160, 135, 145, 254, 136, 142, 196, 197, 198, 203, 208, 142, 145, 107,
-    160, 107, 145, 190, 206, 208, 137, 214, 0,   252, 213, 218, 139, 61,  107, 211, 212, 139, 234,
-    197, 196, 198, 160, 160, 135, 144, 214, 139, 145, 203, 208, 219, 220, 106, 107, 109, 110, 111,
-    112, 113, 116, 117, 135, 138, 146, 147, 148, 149, 161, 162, 163, 165, 166, 167, 168, 169, 170,
-    171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 189, 213, 137, 145,
-    219, 217, 144, 136, 142, 15,  16,  17,  19,  20,  21,  22,  23,  24,  25,  64,  139, 140, 145,
-    172, 185, 186, 188, 191, 192, 213, 224, 225, 226, 227, 235, 236, 237, 239, 241, 243, 250, 214,
-    144, 214, 186, 223, 144, 208, 160, 221, 222, 140, 220, 172, 172, 188, 116, 117, 137, 141, 136,
-    136, 142, 63,  186, 135, 172, 150, 151, 152, 147, 149, 114, 115, 118, 119, 153, 154, 120, 121,
-    157, 156, 155, 122, 124, 123, 158, 138, 138, 189, 140, 219, 110, 111, 212, 145, 145, 245, 135,
-    135, 145, 145, 188, 135, 189, 143, 135, 140, 228, 125, 126, 127, 128, 129, 130, 131, 132, 133,
-    134, 144, 187, 142, 145, 140, 225, 223, 144, 223, 221, 214, 142, 145, 107, 145, 136, 164, 188,
-    107, 113, 167, 186, 172, 172, 172, 174, 174, 175, 175, 176, 176, 176, 176, 177, 177, 178, 179,
-    180, 181, 182, 183, 188, 138, 140, 231, 232, 233, 246, 188, 145, 188, 143, 244, 235, 186, 186,
-    223, 145, 222, 137, 145, 138, 143, 64,  234, 226, 224, 236, 247, 136, 136, 188, 201, 203, 242,
-    229, 189, 186, 135, 242, 248, 249, 231, 238, 240, 160, 136, 140, 138, 188, 145, 136, 18,  227,
-    144, 226, 230, 234, 145, 136, 188, 230, 231, 223, 145};
+    51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,  64,  66,  67,  68,  69,  70,
+    71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  85,  87,  88,  89,  90,
+    91,  92,  93,  94,  95,  96,  97,  98,  99,  100, 101, 102, 103, 104, 105, 106, 109, 192, 193,
+    194, 195, 196, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 214, 216, 217, 252,
+    253, 254, 210, 108, 109, 140, 161, 136, 146, 255, 137, 143, 197, 198, 199, 204, 209, 143, 146,
+    108, 161, 108, 146, 191, 207, 209, 138, 215, 0,   253, 214, 219, 140, 62,  108, 212, 213, 140,
+    235, 198, 197, 199, 161, 161, 136, 145, 215, 140, 146, 204, 209, 220, 221, 107, 108, 110, 111,
+    112, 113, 114, 117, 118, 136, 139, 147, 148, 149, 150, 162, 163, 164, 166, 167, 168, 169, 170,
+    171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 190, 214, 138,
+    146, 220, 218, 145, 137, 143, 15,  16,  17,  19,  20,  21,  22,  23,  24,  25,  65,  140, 141,
+    146, 173, 186, 187, 189, 192, 193, 214, 225, 226, 227, 228, 236, 237, 238, 240, 242, 244, 251,
+    215, 145, 215, 187, 224, 145, 209, 161, 222, 223, 141, 221, 173, 173, 189, 117, 118, 138, 142,
+    137, 137, 143, 64,  187, 136, 173, 151, 152, 153, 148, 150, 115, 116, 119, 120, 154, 155, 121,
+    122, 158, 157, 156, 123, 125, 124, 159, 139, 139, 190, 141, 220, 111, 112, 213, 146, 146, 246,
+    136, 136, 146, 146, 189, 136, 190, 144, 136, 141, 229, 126, 127, 128, 129, 130, 131, 132, 133,
+    134, 135, 145, 188, 143, 146, 141, 226, 224, 145, 224, 222, 215, 143, 146, 108, 146, 137, 165,
+    189, 108, 114, 168, 187, 173, 173, 173, 175, 175, 176, 176, 177, 177, 177, 177, 178, 178, 179,
+    180, 181, 182, 183, 184, 189, 139, 141, 232, 233, 234, 247, 189, 146, 189, 144, 245, 236, 187,
+    187, 224, 146, 223, 138, 146, 139, 144, 65,  235, 227, 225, 237, 248, 137, 137, 189, 202, 204,
+    243, 230, 190, 187, 136, 243, 249, 250, 232, 239, 241, 161, 137, 141, 139, 189, 146, 137, 18,
+    228, 145, 227, 231, 235, 146, 137, 189, 231, 232, 224, 146};
 
 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const yytype_uint8 yyr1[] = {
-    0,   159, 160, 160, 161, 162, 162, 162, 162, 162, 162, 162, 163, 163, 163, 163, 163, 163, 164,
-    165, 166, 166, 167, 167, 168, 168, 169, 169, 170, 171, 171, 171, 172, 172, 172, 172, 173, 173,
-    173, 173, 174, 174, 174, 174, 175, 175, 175, 176, 176, 176, 177, 177, 177, 177, 177, 178, 178,
-    178, 179, 179, 180, 180, 181, 181, 182, 182, 183, 183, 184, 184, 185, 185, 186, 186, 187, 187,
-    187, 187, 187, 187, 187, 187, 187, 187, 187, 188, 188, 189, 190, 191, 191, 191, 191, 191, 191,
-    191, 191, 192, 193, 193, 194, 194, 195, 196, 196, 197, 197, 197, 197, 198, 199, 199, 199, 199,
-    199, 200, 200, 200, 200, 200, 201, 201, 202, 202, 203, 203, 204, 205, 206, 206, 206, 206, 206,
-    206, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 208, 209, 209,
-    209, 210, 211, 211, 212, 212, 212, 212, 213, 213, 214, 214, 214, 214, 215, 215, 215, 215, 215,
-    215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215,
-    215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215,
-    215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215,
-    215, 215, 215, 215, 215, 217, 216, 218, 216, 219, 219, 220, 220, 221, 221, 222, 222, 223, 224,
-    225, 225, 226, 226, 226, 226, 226, 226, 226, 227, 228, 229, 227, 230, 230, 232, 231, 233, 231,
-    234, 234, 235, 235, 236, 236, 237, 238, 238, 240, 239, 241, 241, 242, 242, 244, 243, 245, 243,
-    246, 243, 247, 247, 248, 248, 249, 249, 250, 250, 250, 250, 250, 251, 251, 252, 252, 254, 253};
+    0,   160, 161, 161, 162, 163, 163, 163, 163, 163, 163, 163, 164, 164, 164, 164, 164, 164,
+    165, 166, 167, 167, 168, 168, 169, 169, 170, 170, 171, 172, 172, 172, 173, 173, 173, 173,
+    174, 174, 174, 174, 175, 175, 175, 175, 176, 176, 176, 177, 177, 177, 178, 178, 178, 178,
+    178, 179, 179, 179, 180, 180, 181, 181, 182, 182, 183, 183, 184, 184, 185, 185, 186, 186,
+    187, 187, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 189, 189, 190, 191, 192,
+    192, 192, 192, 192, 192, 192, 192, 193, 194, 194, 195, 195, 196, 197, 197, 198, 198, 198,
+    198, 199, 200, 200, 200, 200, 200, 201, 201, 201, 201, 201, 202, 202, 203, 203, 203, 204,
+    204, 205, 206, 207, 207, 207, 207, 207, 207, 208, 208, 208, 208, 208, 208, 208, 208, 208,
+    208, 208, 208, 208, 208, 208, 209, 210, 210, 210, 211, 212, 212, 213, 213, 213, 213, 214,
+    214, 215, 215, 215, 215, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216,
+    216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216,
+    216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216,
+    216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216,
+    218, 217, 219, 217, 220, 220, 221, 221, 222, 222, 223, 223, 224, 225, 226, 226, 227, 227,
+    227, 227, 227, 227, 227, 228, 229, 230, 228, 231, 231, 233, 232, 234, 232, 235, 235, 236,
+    236, 237, 237, 238, 239, 239, 241, 240, 242, 242, 243, 243, 245, 244, 246, 244, 247, 244,
+    248, 248, 249, 249, 250, 250, 251, 251, 251, 251, 251, 252, 252, 253, 253, 255, 254};
 
 /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN.  */
 static const yytype_uint8 yyr2[] = {
@@ -1477,12 +1483,12 @@
     1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 3, 3, 3, 1, 3, 3, 1, 3, 3, 1, 3, 3, 3, 3, 1, 3, 3, 1, 3, 1, 3,
     1, 3, 1, 3, 1, 3, 1, 3, 1, 5, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 2, 2, 2, 4, 5,
     6, 9, 2, 3, 2, 1, 1, 2, 3, 3, 2, 3, 2, 1, 2, 1, 1, 1, 3, 4, 6, 5, 1, 2, 3, 5, 4, 1, 2, 1, 1,
-    1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 1,
-    3, 1, 3, 3, 1, 1, 2, 2, 3, 3, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4,
+    1, 3, 1, 3, 3, 1, 1, 2, 2, 3, 3, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 6, 0, 5, 1, 2, 3, 4, 1, 3, 1, 2, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 5, 1, 1, 0, 2, 0, 2, 2, 3, 1, 2, 1, 2, 5, 3, 1, 0, 6, 3, 2,
-    1, 4, 0, 6, 0, 8, 0, 7, 1, 1, 1, 0, 2, 3, 2, 2, 2, 3, 2, 1, 2, 1, 1, 0, 3};
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 6, 0, 5, 1, 2, 3, 4, 1, 3, 1, 2, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 5, 1, 1, 0, 2, 0, 2, 2, 3, 1, 2, 1, 2, 5, 3, 1, 0, 6, 3,
+    2, 1, 4, 0, 6, 0, 8, 0, 7, 1, 1, 1, 0, 2, 3, 2, 2, 2, 3, 2, 1, 2, 1, 1, 0, 3};
 
 #define yyerrok (yyerrstatus = 0)
 #define yyclearin (yychar = YYEMPTY)
@@ -3395,9 +3401,12 @@
         case 124:
 
         {
-            (yyval.interm.typeQualifierBuilder) = context->createTypeQualifierBuilder((yylsp[0]));
-            (yyval.interm.typeQualifierBuilder)
-                ->appendQualifier((yyvsp[0].interm.qualifierWrapper));
+            if (!context->checkCanUseExtension((yylsp[0]),
+                                               TExtension::NV_shader_noperspective_interpolation))
+            {
+                context->error((yylsp[0]), "unsupported interpolation qualifier", "noperspective");
+            }
+            (yyval.interm.qualifier) = EvqNoPerspective;
         }
 
         break;
@@ -3405,7 +3414,7 @@
         case 125:
 
         {
-            (yyval.interm.typeQualifierBuilder) = (yyvsp[-1].interm.typeQualifierBuilder);
+            (yyval.interm.typeQualifierBuilder) = context->createTypeQualifierBuilder((yylsp[0]));
             (yyval.interm.typeQualifierBuilder)
                 ->appendQualifier((yyvsp[0].interm.qualifierWrapper));
         }
@@ -3415,7 +3424,9 @@
         case 126:
 
         {
-            // empty
+            (yyval.interm.typeQualifierBuilder) = (yyvsp[-1].interm.typeQualifierBuilder);
+            (yyval.interm.typeQualifierBuilder)
+                ->appendQualifier((yyvsp[0].interm.qualifierWrapper));
         }
 
         break;
@@ -3431,13 +3442,21 @@
         case 128:
 
         {
+            // empty
+        }
+
+        break;
+
+        case 129:
+
+        {
             context->checkLocalVariableConstStorageQualifier(*(yyvsp[0].interm.qualifierWrapper));
             (yyval.interm.qualifierWrapper) = (yyvsp[0].interm.qualifierWrapper);
         }
 
         break;
 
-        case 129:
+        case 130:
 
         {
             context->checkIsAtGlobalLevel((yylsp[0]), "layout");
@@ -3447,7 +3466,7 @@
 
         break;
 
-        case 130:
+        case 131:
 
         {
             (yyval.interm.qualifierWrapper) =
@@ -3456,7 +3475,7 @@
 
         break;
 
-        case 131:
+        case 132:
 
         {
             (yyval.interm.qualifierWrapper) =
@@ -3465,7 +3484,7 @@
 
         break;
 
-        case 132:
+        case 133:
 
         {
             context->checkIsAtGlobalLevel((yylsp[0]), "invariant");
@@ -3474,7 +3493,7 @@
 
         break;
 
-        case 133:
+        case 134:
 
         {
             (yyval.interm.qualifierWrapper) = new TPreciseQualifierWrapper((yylsp[0]));
@@ -3482,7 +3501,7 @@
 
         break;
 
-        case 134:
+        case 135:
 
         {
             VERTEX_ONLY("attribute", (yylsp[0]));
@@ -3493,7 +3512,7 @@
 
         break;
 
-        case 135:
+        case 136:
 
         {
             ES2_ONLY("varying", (yylsp[0]));
@@ -3502,7 +3521,7 @@
 
         break;
 
-        case 136:
+        case 137:
 
         {
             (yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqConst, (yylsp[0]));
@@ -3510,7 +3529,7 @@
 
         break;
 
-        case 137:
+        case 138:
 
         {
             (yyval.interm.qualifierWrapper) = context->parseInQualifier((yylsp[0]));
@@ -3518,7 +3537,7 @@
 
         break;
 
-        case 138:
+        case 139:
 
         {
             (yyval.interm.qualifierWrapper) = context->parseOutQualifier((yylsp[0]));
@@ -3526,7 +3545,7 @@
 
         break;
 
-        case 139:
+        case 140:
 
         {
             (yyval.interm.qualifierWrapper) = context->parseInOutQualifier((yylsp[0]));
@@ -3534,7 +3553,7 @@
 
         break;
 
-        case 140:
+        case 141:
 
         {
             ES3_OR_NEWER("centroid", (yylsp[0]), "storage qualifier");
@@ -3543,7 +3562,7 @@
 
         break;
 
-        case 141:
+        case 142:
 
         {
             (yyval.interm.qualifierWrapper) =
@@ -3552,7 +3571,7 @@
 
         break;
 
-        case 142:
+        case 143:
 
         {
             ES3_1_ONLY("buffer", (yylsp[0]), "storage qualifier");
@@ -3562,7 +3581,7 @@
 
         break;
 
-        case 143:
+        case 144:
 
         {
             (yyval.interm.qualifierWrapper) = new TMemoryQualifierWrapper(EvqReadOnly, (yylsp[0]));
@@ -3570,7 +3589,7 @@
 
         break;
 
-        case 144:
+        case 145:
 
         {
             (yyval.interm.qualifierWrapper) = new TMemoryQualifierWrapper(EvqWriteOnly, (yylsp[0]));
@@ -3578,7 +3597,7 @@
 
         break;
 
-        case 145:
+        case 146:
 
         {
             (yyval.interm.qualifierWrapper) = new TMemoryQualifierWrapper(EvqCoherent, (yylsp[0]));
@@ -3586,7 +3605,7 @@
 
         break;
 
-        case 146:
+        case 147:
 
         {
             (yyval.interm.qualifierWrapper) = new TMemoryQualifierWrapper(EvqRestrict, (yylsp[0]));
@@ -3594,7 +3613,7 @@
 
         break;
 
-        case 147:
+        case 148:
 
         {
             (yyval.interm.qualifierWrapper) = new TMemoryQualifierWrapper(EvqVolatile, (yylsp[0]));
@@ -3602,7 +3621,7 @@
 
         break;
 
-        case 148:
+        case 149:
 
         {
             COMPUTE_ONLY("shared", (yylsp[0]));
@@ -3612,7 +3631,7 @@
 
         break;
 
-        case 149:
+        case 150:
 
         {
             (yyval.interm.type) = (yyvsp[0].interm.type);
@@ -3622,7 +3641,7 @@
 
         break;
 
-        case 150:
+        case 151:
 
         {
             (yyval.interm.precision) = EbpHigh;
@@ -3630,7 +3649,7 @@
 
         break;
 
-        case 151:
+        case 152:
 
         {
             (yyval.interm.precision) = EbpMedium;
@@ -3638,7 +3657,7 @@
 
         break;
 
-        case 152:
+        case 153:
 
         {
             (yyval.interm.precision) = EbpLow;
@@ -3646,7 +3665,7 @@
 
         break;
 
-        case 153:
+        case 154:
 
         {
             ES3_OR_NEWER("layout", (yylsp[-3]), "qualifier");
@@ -3655,7 +3674,7 @@
 
         break;
 
-        case 154:
+        case 155:
 
         {
             (yyval.interm.layoutQualifier) = (yyvsp[0].interm.layoutQualifier);
@@ -3663,7 +3682,7 @@
 
         break;
 
-        case 155:
+        case 156:
 
         {
             (yyval.interm.layoutQualifier) = context->joinLayoutQualifiers(
@@ -3672,7 +3691,7 @@
 
         break;
 
-        case 156:
+        case 157:
 
         {
             (yyval.interm.layoutQualifier) =
@@ -3681,15 +3700,6 @@
 
         break;
 
-        case 157:
-
-        {
-            (yyval.interm.layoutQualifier) = context->parseLayoutQualifier(
-                ImmutableString((yyvsp[-2].lex).string), (yylsp[-2]), (yyvsp[0].lex).i, (yylsp[0]));
-        }
-
-        break;
-
         case 158:
 
         {
@@ -3702,13 +3712,22 @@
         case 159:
 
         {
+            (yyval.interm.layoutQualifier) = context->parseLayoutQualifier(
+                ImmutableString((yyvsp[-2].lex).string), (yylsp[-2]), (yyvsp[0].lex).i, (yylsp[0]));
+        }
+
+        break;
+
+        case 160:
+
+        {
             (yyval.interm.layoutQualifier) =
                 context->parseLayoutQualifier(ImmutableString("shared"), (yylsp[0]));
         }
 
         break;
 
-        case 160:
+        case 161:
 
         {
             (yyval.interm.type)
@@ -3718,7 +3737,7 @@
 
         break;
 
-        case 161:
+        case 162:
 
         {
             (yyval.interm.type)
@@ -3729,7 +3748,7 @@
 
         break;
 
-        case 162:
+        case 163:
 
         {
             ES3_OR_NEWER("[]", (yylsp[-1]), "implicitly sized array");
@@ -3739,7 +3758,7 @@
 
         break;
 
-        case 163:
+        case 164:
 
         {
             (yyval.interm.arraySizes) = new TVector<unsigned int>();
@@ -3753,7 +3772,7 @@
 
         break;
 
-        case 164:
+        case 165:
 
         {
             ES3_1_ONLY("[]", (yylsp[-1]), "arrays of arrays");
@@ -3763,7 +3782,7 @@
 
         break;
 
-        case 165:
+        case 166:
 
         {
             ES3_1_ONLY("[]", (yylsp[-2]), "arrays of arrays");
@@ -3778,7 +3797,7 @@
 
         break;
 
-        case 166:
+        case 167:
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtVoid, (yylsp[0]));
@@ -3786,18 +3805,10 @@
 
         break;
 
-        case 167:
-
-        {
-            (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
-        }
-
-        break;
-
         case 168:
 
         {
-            (yyval.interm.typeSpecifierNonArray).initialize(EbtInt, (yylsp[0]));
+            (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
         }
 
         break;
@@ -3805,7 +3816,7 @@
         case 169:
 
         {
-            (yyval.interm.typeSpecifierNonArray).initialize(EbtUInt, (yylsp[0]));
+            (yyval.interm.typeSpecifierNonArray).initialize(EbtInt, (yylsp[0]));
         }
 
         break;
@@ -3813,7 +3824,7 @@
         case 170:
 
         {
-            (yyval.interm.typeSpecifierNonArray).initialize(EbtBool, (yylsp[0]));
+            (yyval.interm.typeSpecifierNonArray).initialize(EbtUInt, (yylsp[0]));
         }
 
         break;
@@ -3821,8 +3832,7 @@
         case 171:
 
         {
-            (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
-            (yyval.interm.typeSpecifierNonArray).setAggregate(2);
+            (yyval.interm.typeSpecifierNonArray).initialize(EbtBool, (yylsp[0]));
         }
 
         break;
@@ -3831,7 +3841,7 @@
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
-            (yyval.interm.typeSpecifierNonArray).setAggregate(3);
+            (yyval.interm.typeSpecifierNonArray).setAggregate(2);
         }
 
         break;
@@ -3840,7 +3850,7 @@
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
-            (yyval.interm.typeSpecifierNonArray).setAggregate(4);
+            (yyval.interm.typeSpecifierNonArray).setAggregate(3);
         }
 
         break;
@@ -3848,8 +3858,8 @@
         case 174:
 
         {
-            (yyval.interm.typeSpecifierNonArray).initialize(EbtBool, (yylsp[0]));
-            (yyval.interm.typeSpecifierNonArray).setAggregate(2);
+            (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
+            (yyval.interm.typeSpecifierNonArray).setAggregate(4);
         }
 
         break;
@@ -3858,7 +3868,7 @@
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtBool, (yylsp[0]));
-            (yyval.interm.typeSpecifierNonArray).setAggregate(3);
+            (yyval.interm.typeSpecifierNonArray).setAggregate(2);
         }
 
         break;
@@ -3867,7 +3877,7 @@
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtBool, (yylsp[0]));
-            (yyval.interm.typeSpecifierNonArray).setAggregate(4);
+            (yyval.interm.typeSpecifierNonArray).setAggregate(3);
         }
 
         break;
@@ -3875,8 +3885,8 @@
         case 177:
 
         {
-            (yyval.interm.typeSpecifierNonArray).initialize(EbtInt, (yylsp[0]));
-            (yyval.interm.typeSpecifierNonArray).setAggregate(2);
+            (yyval.interm.typeSpecifierNonArray).initialize(EbtBool, (yylsp[0]));
+            (yyval.interm.typeSpecifierNonArray).setAggregate(4);
         }
 
         break;
@@ -3885,7 +3895,7 @@
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtInt, (yylsp[0]));
-            (yyval.interm.typeSpecifierNonArray).setAggregate(3);
+            (yyval.interm.typeSpecifierNonArray).setAggregate(2);
         }
 
         break;
@@ -3894,7 +3904,7 @@
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtInt, (yylsp[0]));
-            (yyval.interm.typeSpecifierNonArray).setAggregate(4);
+            (yyval.interm.typeSpecifierNonArray).setAggregate(3);
         }
 
         break;
@@ -3902,8 +3912,8 @@
         case 180:
 
         {
-            (yyval.interm.typeSpecifierNonArray).initialize(EbtUInt, (yylsp[0]));
-            (yyval.interm.typeSpecifierNonArray).setAggregate(2);
+            (yyval.interm.typeSpecifierNonArray).initialize(EbtInt, (yylsp[0]));
+            (yyval.interm.typeSpecifierNonArray).setAggregate(4);
         }
 
         break;
@@ -3912,7 +3922,7 @@
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtUInt, (yylsp[0]));
-            (yyval.interm.typeSpecifierNonArray).setAggregate(3);
+            (yyval.interm.typeSpecifierNonArray).setAggregate(2);
         }
 
         break;
@@ -3921,7 +3931,7 @@
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtUInt, (yylsp[0]));
-            (yyval.interm.typeSpecifierNonArray).setAggregate(4);
+            (yyval.interm.typeSpecifierNonArray).setAggregate(3);
         }
 
         break;
@@ -3929,8 +3939,8 @@
         case 183:
 
         {
-            (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
-            (yyval.interm.typeSpecifierNonArray).setMatrix(2, 2);
+            (yyval.interm.typeSpecifierNonArray).initialize(EbtUInt, (yylsp[0]));
+            (yyval.interm.typeSpecifierNonArray).setAggregate(4);
         }
 
         break;
@@ -3939,7 +3949,7 @@
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
-            (yyval.interm.typeSpecifierNonArray).setMatrix(3, 3);
+            (yyval.interm.typeSpecifierNonArray).setMatrix(2, 2);
         }
 
         break;
@@ -3948,7 +3958,7 @@
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
-            (yyval.interm.typeSpecifierNonArray).setMatrix(4, 4);
+            (yyval.interm.typeSpecifierNonArray).setMatrix(3, 3);
         }
 
         break;
@@ -3957,7 +3967,7 @@
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
-            (yyval.interm.typeSpecifierNonArray).setMatrix(2, 3);
+            (yyval.interm.typeSpecifierNonArray).setMatrix(4, 4);
         }
 
         break;
@@ -3966,7 +3976,7 @@
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
-            (yyval.interm.typeSpecifierNonArray).setMatrix(3, 2);
+            (yyval.interm.typeSpecifierNonArray).setMatrix(2, 3);
         }
 
         break;
@@ -3975,7 +3985,7 @@
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
-            (yyval.interm.typeSpecifierNonArray).setMatrix(2, 4);
+            (yyval.interm.typeSpecifierNonArray).setMatrix(3, 2);
         }
 
         break;
@@ -3984,7 +3994,7 @@
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
-            (yyval.interm.typeSpecifierNonArray).setMatrix(4, 2);
+            (yyval.interm.typeSpecifierNonArray).setMatrix(2, 4);
         }
 
         break;
@@ -3993,7 +4003,7 @@
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
-            (yyval.interm.typeSpecifierNonArray).setMatrix(3, 4);
+            (yyval.interm.typeSpecifierNonArray).setMatrix(4, 2);
         }
 
         break;
@@ -4002,7 +4012,7 @@
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
-            (yyval.interm.typeSpecifierNonArray).setMatrix(4, 3);
+            (yyval.interm.typeSpecifierNonArray).setMatrix(3, 4);
         }
 
         break;
@@ -4010,6 +4020,15 @@
         case 192:
 
         {
+            (yyval.interm.typeSpecifierNonArray).initialize(EbtFloat, (yylsp[0]));
+            (yyval.interm.typeSpecifierNonArray).setMatrix(4, 3);
+        }
+
+        break;
+
+        case 193:
+
+        {
             if (!context->checkCanUseExtension((yylsp[0]), TExtension::EXT_YUV_target))
             {
                 context->error((yylsp[0]), "unsupported type", "yuvCscStandardEXT");
@@ -4019,7 +4038,7 @@
 
         break;
 
-        case 193:
+        case 194:
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler2D, (yylsp[0]));
@@ -4027,7 +4046,7 @@
 
         break;
 
-        case 194:
+        case 195:
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler3D, (yylsp[0]));
@@ -4035,7 +4054,7 @@
 
         break;
 
-        case 195:
+        case 196:
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtSamplerCube, (yylsp[0]));
@@ -4043,7 +4062,7 @@
 
         break;
 
-        case 196:
+        case 197:
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler2DArray, (yylsp[0]));
@@ -4051,7 +4070,7 @@
 
         break;
 
-        case 197:
+        case 198:
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler2DMS, (yylsp[0]));
@@ -4059,7 +4078,7 @@
 
         break;
 
-        case 198:
+        case 199:
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler2DMSArray, (yylsp[0]));
@@ -4067,7 +4086,7 @@
 
         break;
 
-        case 199:
+        case 200:
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtISampler2D, (yylsp[0]));
@@ -4075,7 +4094,7 @@
 
         break;
 
-        case 200:
+        case 201:
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtISampler3D, (yylsp[0]));
@@ -4083,7 +4102,7 @@
 
         break;
 
-        case 201:
+        case 202:
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtISamplerCube, (yylsp[0]));
@@ -4091,7 +4110,7 @@
 
         break;
 
-        case 202:
+        case 203:
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtISampler2DArray, (yylsp[0]));
@@ -4099,7 +4118,7 @@
 
         break;
 
-        case 203:
+        case 204:
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtISampler2DMS, (yylsp[0]));
@@ -4107,7 +4126,7 @@
 
         break;
 
-        case 204:
+        case 205:
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtISampler2DMSArray, (yylsp[0]));
@@ -4115,7 +4134,7 @@
 
         break;
 
-        case 205:
+        case 206:
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtUSampler2D, (yylsp[0]));
@@ -4123,7 +4142,7 @@
 
         break;
 
-        case 206:
+        case 207:
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtUSampler3D, (yylsp[0]));
@@ -4131,7 +4150,7 @@
 
         break;
 
-        case 207:
+        case 208:
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtUSamplerCube, (yylsp[0]));
@@ -4139,7 +4158,7 @@
 
         break;
 
-        case 208:
+        case 209:
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtUSampler2DArray, (yylsp[0]));
@@ -4147,7 +4166,7 @@
 
         break;
 
-        case 209:
+        case 210:
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtUSampler2DMS, (yylsp[0]));
@@ -4155,7 +4174,7 @@
 
         break;
 
-        case 210:
+        case 211:
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtUSampler2DMSArray, (yylsp[0]));
@@ -4163,7 +4182,7 @@
 
         break;
 
-        case 211:
+        case 212:
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler2DShadow, (yylsp[0]));
@@ -4171,7 +4190,7 @@
 
         break;
 
-        case 212:
+        case 213:
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtSamplerCubeShadow, (yylsp[0]));
@@ -4179,7 +4198,7 @@
 
         break;
 
-        case 213:
+        case 214:
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler2DArrayShadow, (yylsp[0]));
@@ -4187,7 +4206,7 @@
 
         break;
 
-        case 214:
+        case 215:
 
         {
             if (!context->checkCanUseExtension((yylsp[0]), TExtension::WEBGL_video_texture))
@@ -4199,7 +4218,7 @@
 
         break;
 
-        case 215:
+        case 216:
 
         {
             constexpr std::array<TExtension, 3u> extensions{
@@ -4214,7 +4233,7 @@
 
         break;
 
-        case 216:
+        case 217:
 
         {
             if (!context->checkCanUseExtension((yylsp[0]), TExtension::EXT_YUV_target))
@@ -4226,7 +4245,7 @@
 
         break;
 
-        case 217:
+        case 218:
 
         {
             if (!context->checkCanUseExtension((yylsp[0]), TExtension::ARB_texture_rectangle))
@@ -4238,7 +4257,7 @@
 
         break;
 
-        case 218:
+        case 219:
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtImage2D, (yylsp[0]));
@@ -4246,7 +4265,7 @@
 
         break;
 
-        case 219:
+        case 220:
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtIImage2D, (yylsp[0]));
@@ -4254,7 +4273,7 @@
 
         break;
 
-        case 220:
+        case 221:
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtUImage2D, (yylsp[0]));
@@ -4262,7 +4281,7 @@
 
         break;
 
-        case 221:
+        case 222:
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtImage3D, (yylsp[0]));
@@ -4270,7 +4289,7 @@
 
         break;
 
-        case 222:
+        case 223:
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtIImage3D, (yylsp[0]));
@@ -4278,7 +4297,7 @@
 
         break;
 
-        case 223:
+        case 224:
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtUImage3D, (yylsp[0]));
@@ -4286,7 +4305,7 @@
 
         break;
 
-        case 224:
+        case 225:
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtImage2DArray, (yylsp[0]));
@@ -4294,7 +4313,7 @@
 
         break;
 
-        case 225:
+        case 226:
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtIImage2DArray, (yylsp[0]));
@@ -4302,7 +4321,7 @@
 
         break;
 
-        case 226:
+        case 227:
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtUImage2DArray, (yylsp[0]));
@@ -4310,7 +4329,7 @@
 
         break;
 
-        case 227:
+        case 228:
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtImageCube, (yylsp[0]));
@@ -4318,7 +4337,7 @@
 
         break;
 
-        case 228:
+        case 229:
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtIImageCube, (yylsp[0]));
@@ -4326,7 +4345,7 @@
 
         break;
 
-        case 229:
+        case 230:
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtUImageCube, (yylsp[0]));
@@ -4334,7 +4353,7 @@
 
         break;
 
-        case 230:
+        case 231:
 
         {
             (yyval.interm.typeSpecifierNonArray).initialize(EbtAtomicCounter, (yylsp[0]));
@@ -4342,7 +4361,7 @@
 
         break;
 
-        case 231:
+        case 232:
 
         {
             (yyval.interm.typeSpecifierNonArray) = (yyvsp[0].interm.typeSpecifierNonArray);
@@ -4350,7 +4369,7 @@
 
         break;
 
-        case 232:
+        case 233:
 
         {
             // This is for user defined type names. The lexical phase looked up the type.
@@ -4360,7 +4379,7 @@
 
         break;
 
-        case 233:
+        case 234:
 
         {
             context->enterStructDeclaration((yylsp[-1]), ImmutableString((yyvsp[-1].lex).string));
@@ -4368,7 +4387,7 @@
 
         break;
 
-        case 234:
+        case 235:
 
         {
             (yyval.interm.typeSpecifierNonArray) = context->addStructure(
@@ -4378,7 +4397,7 @@
 
         break;
 
-        case 235:
+        case 236:
 
         {
             context->enterStructDeclaration((yylsp[0]), kEmptyImmutableString);
@@ -4386,7 +4405,7 @@
 
         break;
 
-        case 236:
+        case 237:
 
         {
             (yyval.interm.typeSpecifierNonArray) = context->addStructure(
@@ -4395,7 +4414,7 @@
 
         break;
 
-        case 237:
+        case 238:
 
         {
             (yyval.interm.fieldList) =
@@ -4404,7 +4423,7 @@
 
         break;
 
-        case 238:
+        case 239:
 
         {
             (yyval.interm.fieldList) = context->combineStructFieldLists(
@@ -4413,7 +4432,7 @@
 
         break;
 
-        case 239:
+        case 240:
 
         {
             (yyval.interm.fieldList) = context->addStructDeclaratorList(
@@ -4422,7 +4441,7 @@
 
         break;
 
-        case 240:
+        case 241:
 
         {
             // ES3 Only, but errors should be handled elsewhere
@@ -4433,7 +4452,7 @@
 
         break;
 
-        case 241:
+        case 242:
 
         {
             (yyval.interm.declaratorList) = new TDeclaratorList();
@@ -4442,7 +4461,7 @@
 
         break;
 
-        case 242:
+        case 243:
 
         {
             (yyval.interm.declaratorList)->push_back((yyvsp[0].interm.declarator));
@@ -4450,7 +4469,7 @@
 
         break;
 
-        case 243:
+        case 244:
 
         {
             (yyval.interm.declarator) =
@@ -4459,7 +4478,7 @@
 
         break;
 
-        case 244:
+        case 245:
 
         {
             (yyval.interm.declarator) = context->parseStructArrayDeclarator(
@@ -4468,7 +4487,7 @@
 
         break;
 
-        case 245:
+        case 246:
 
         {
             (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
@@ -4476,18 +4495,10 @@
 
         break;
 
-        case 246:
-
-        {
-            (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
-        }
-
-        break;
-
         case 247:
 
         {
-            (yyval.interm.intermNode) = (yyvsp[0].interm.intermBlock);
+            (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
         }
 
         break;
@@ -4495,7 +4506,7 @@
         case 248:
 
         {
-            (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
+            (yyval.interm.intermNode) = (yyvsp[0].interm.intermBlock);
         }
 
         break;
@@ -4527,7 +4538,7 @@
         case 252:
 
         {
-            (yyval.interm.intermNode) = (yyvsp[0].interm.intermSwitch);
+            (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
         }
 
         break;
@@ -4535,7 +4546,7 @@
         case 253:
 
         {
-            (yyval.interm.intermNode) = (yyvsp[0].interm.intermCase);
+            (yyval.interm.intermNode) = (yyvsp[0].interm.intermSwitch);
         }
 
         break;
@@ -4543,7 +4554,7 @@
         case 254:
 
         {
-            (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
+            (yyval.interm.intermNode) = (yyvsp[0].interm.intermCase);
         }
 
         break;
@@ -4559,8 +4570,7 @@
         case 256:
 
         {
-            (yyval.interm.intermBlock) = new TIntermBlock();
-            (yyval.interm.intermBlock)->setLine((yyloc));
+            (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
         }
 
         break;
@@ -4568,7 +4578,8 @@
         case 257:
 
         {
-            context->symbolTable.push();
+            (yyval.interm.intermBlock) = new TIntermBlock();
+            (yyval.interm.intermBlock)->setLine((yyloc));
         }
 
         break;
@@ -4576,7 +4587,7 @@
         case 258:
 
         {
-            context->symbolTable.pop();
+            context->symbolTable.push();
         }
 
         break;
@@ -4584,24 +4595,24 @@
         case 259:
 
         {
+            context->symbolTable.pop();
+        }
+
+        break;
+
+        case 260:
+
+        {
             (yyvsp[-2].interm.intermBlock)->setLine((yyloc));
             (yyval.interm.intermBlock) = (yyvsp[-2].interm.intermBlock);
         }
 
         break;
 
-        case 260:
-
-        {
-            (yyval.interm.intermNode) = (yyvsp[0].interm.intermBlock);
-        }
-
-        break;
-
         case 261:
 
         {
-            (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
+            (yyval.interm.intermNode) = (yyvsp[0].interm.intermBlock);
         }
 
         break;
@@ -4609,7 +4620,7 @@
         case 262:
 
         {
-            context->symbolTable.push();
+            (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
         }
 
         break;
@@ -4617,13 +4628,21 @@
         case 263:
 
         {
+            context->symbolTable.push();
+        }
+
+        break;
+
+        case 264:
+
+        {
             context->symbolTable.pop();
             (yyval.interm.intermNode) = (yyvsp[0].interm.intermBlock);
         }
 
         break;
 
-        case 264:
+        case 265:
 
         {
             context->symbolTable.push();
@@ -4631,7 +4650,7 @@
 
         break;
 
-        case 265:
+        case 266:
 
         {
             context->symbolTable.pop();
@@ -4640,7 +4659,7 @@
 
         break;
 
-        case 266:
+        case 267:
 
         {
             (yyval.interm.intermBlock) = new TIntermBlock();
@@ -4649,7 +4668,7 @@
 
         break;
 
-        case 267:
+        case 268:
 
         {
             (yyvsp[-1].interm.intermBlock)->setLine((yyloc));
@@ -4658,7 +4677,7 @@
 
         break;
 
-        case 268:
+        case 269:
 
         {
             (yyval.interm.intermBlock) = new TIntermBlock();
@@ -4667,7 +4686,7 @@
 
         break;
 
-        case 269:
+        case 270:
 
         {
             (yyval.interm.intermBlock) = (yyvsp[-1].interm.intermBlock);
@@ -4676,7 +4695,7 @@
 
         break;
 
-        case 270:
+        case 271:
 
         {
             (yyval.interm.intermNode) = context->addEmptyStatement((yyloc));
@@ -4684,7 +4703,7 @@
 
         break;
 
-        case 271:
+        case 272:
 
         {
             (yyval.interm.intermNode) = (yyvsp[-1].interm.intermTypedNode);
@@ -4692,7 +4711,7 @@
 
         break;
 
-        case 272:
+        case 273:
 
         {
             (yyval.interm.intermNode) = context->addIfElse((yyvsp[-2].interm.intermTypedNode),
@@ -4701,7 +4720,7 @@
 
         break;
 
-        case 273:
+        case 274:
 
         {
             (yyval.interm.nodePair).node1 = (yyvsp[-2].interm.intermNode);
@@ -4710,7 +4729,7 @@
 
         break;
 
-        case 274:
+        case 275:
 
         {
             (yyval.interm.nodePair).node1 = (yyvsp[0].interm.intermNode);
@@ -4719,7 +4738,7 @@
 
         break;
 
-        case 275:
+        case 276:
 
         {
             context->incrSwitchNestingLevel();
@@ -4727,7 +4746,7 @@
 
         break;
 
-        case 276:
+        case 277:
 
         {
             (yyval.interm.intermSwitch) = context->addSwitch(
@@ -4737,7 +4756,7 @@
 
         break;
 
-        case 277:
+        case 278:
 
         {
             (yyval.interm.intermCase) =
@@ -4746,7 +4765,7 @@
 
         break;
 
-        case 278:
+        case 279:
 
         {
             (yyval.interm.intermCase) = context->addDefault((yylsp[-1]));
@@ -4754,7 +4773,7 @@
 
         break;
 
-        case 279:
+        case 280:
 
         {
             (yyval.interm.intermNode) = (yyvsp[0].interm.intermTypedNode);
@@ -4764,7 +4783,7 @@
 
         break;
 
-        case 280:
+        case 281:
 
         {
             (yyval.interm.intermNode) = context->addConditionInitializer(
@@ -4774,7 +4793,7 @@
 
         break;
 
-        case 281:
+        case 282:
 
         {
             context->symbolTable.push();
@@ -4783,7 +4802,7 @@
 
         break;
 
-        case 282:
+        case 283:
 
         {
             context->symbolTable.pop();
@@ -4795,7 +4814,7 @@
 
         break;
 
-        case 283:
+        case 284:
 
         {
             context->incrLoopNestingLevel();
@@ -4803,7 +4822,7 @@
 
         break;
 
-        case 284:
+        case 285:
 
         {
             (yyval.interm.intermNode) =
@@ -4814,7 +4833,7 @@
 
         break;
 
-        case 285:
+        case 286:
 
         {
             context->symbolTable.push();
@@ -4823,7 +4842,7 @@
 
         break;
 
-        case 286:
+        case 287:
 
         {
             context->symbolTable.pop();
@@ -4836,14 +4855,6 @@
 
         break;
 
-        case 287:
-
-        {
-            (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
-        }
-
-        break;
-
         case 288:
 
         {
@@ -4863,7 +4874,7 @@
         case 290:
 
         {
-            (yyval.interm.intermNode) = nullptr;
+            (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
         }
 
         break;
@@ -4871,13 +4882,21 @@
         case 291:
 
         {
+            (yyval.interm.intermNode) = nullptr;
+        }
+
+        break;
+
+        case 292:
+
+        {
             (yyval.interm.nodePair).node1 = (yyvsp[-1].interm.intermNode);
             (yyval.interm.nodePair).node2 = 0;
         }
 
         break;
 
-        case 292:
+        case 293:
 
         {
             (yyval.interm.nodePair).node1 = (yyvsp[-2].interm.intermNode);
@@ -4886,7 +4905,7 @@
 
         break;
 
-        case 293:
+        case 294:
 
         {
             (yyval.interm.intermNode) = context->addBranch(EOpContinue, (yylsp[-1]));
@@ -4894,7 +4913,7 @@
 
         break;
 
-        case 294:
+        case 295:
 
         {
             (yyval.interm.intermNode) = context->addBranch(EOpBreak, (yylsp[-1]));
@@ -4902,7 +4921,7 @@
 
         break;
 
-        case 295:
+        case 296:
 
         {
             (yyval.interm.intermNode) = context->addBranch(EOpReturn, (yylsp[-1]));
@@ -4910,7 +4929,7 @@
 
         break;
 
-        case 296:
+        case 297:
 
         {
             (yyval.interm.intermNode) =
@@ -4919,7 +4938,7 @@
 
         break;
 
-        case 297:
+        case 298:
 
         {
             (yyval.interm.intermNode) = context->addBranch(EOpKill, (yylsp[-1]));
@@ -4927,7 +4946,7 @@
 
         break;
 
-        case 298:
+        case 299:
 
         {
             (yyval.interm.intermBlock) = new TIntermBlock();
@@ -4938,18 +4957,10 @@
 
         break;
 
-        case 299:
-
-        {
-            (yyval.interm.intermBlock)->appendStatement((yyvsp[0].interm.intermNode));
-        }
-
-        break;
-
         case 300:
 
         {
-            (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
+            (yyval.interm.intermBlock)->appendStatement((yyvsp[0].interm.intermNode));
         }
 
         break;
@@ -4965,13 +4976,21 @@
         case 302:
 
         {
+            (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
+        }
+
+        break;
+
+        case 303:
+
+        {
             context->parseFunctionDefinitionHeader((yylsp[0]), (yyvsp[0].interm).function,
                                                    &((yyvsp[0].interm).intermFunctionPrototype));
         }
 
         break;
 
-        case 303:
+        case 304:
 
         {
             (yyval.interm.intermNode) =
diff --git a/src/compiler/translator/glslang_tab_autogen.h b/src/compiler/translator/glslang_tab_autogen.h
index e0e8d64..6a11361 100644
--- a/src/compiler/translator/glslang_tab_autogen.h
+++ b/src/compiler/translator/glslang_tab_autogen.h
@@ -107,109 +107,110 @@
     CENTROID                  = 308,
     FLAT                      = 309,
     SMOOTH                    = 310,
-    READONLY                  = 311,
-    WRITEONLY                 = 312,
-    COHERENT                  = 313,
-    RESTRICT                  = 314,
-    VOLATILE                  = 315,
-    SHARED                    = 316,
-    STRUCT                    = 317,
-    VOID_TYPE                 = 318,
-    WHILE                     = 319,
-    SAMPLER2D                 = 320,
-    SAMPLERCUBE               = 321,
-    SAMPLER_EXTERNAL_OES      = 322,
-    SAMPLER2DRECT             = 323,
-    SAMPLER2DARRAY            = 324,
-    ISAMPLER2D                = 325,
-    ISAMPLER3D                = 326,
-    ISAMPLERCUBE              = 327,
-    ISAMPLER2DARRAY           = 328,
-    USAMPLER2D                = 329,
-    USAMPLER3D                = 330,
-    USAMPLERCUBE              = 331,
-    USAMPLER2DARRAY           = 332,
-    SAMPLER2DMS               = 333,
-    ISAMPLER2DMS              = 334,
-    USAMPLER2DMS              = 335,
-    SAMPLER2DMSARRAY          = 336,
-    ISAMPLER2DMSARRAY         = 337,
-    USAMPLER2DMSARRAY         = 338,
-    SAMPLER3D                 = 339,
-    SAMPLER3DRECT             = 340,
-    SAMPLER2DSHADOW           = 341,
-    SAMPLERCUBESHADOW         = 342,
-    SAMPLER2DARRAYSHADOW      = 343,
-    SAMPLERVIDEOWEBGL         = 344,
-    SAMPLEREXTERNAL2DY2YEXT   = 345,
-    IMAGE2D                   = 346,
-    IIMAGE2D                  = 347,
-    UIMAGE2D                  = 348,
-    IMAGE3D                   = 349,
-    IIMAGE3D                  = 350,
-    UIMAGE3D                  = 351,
-    IMAGE2DARRAY              = 352,
-    IIMAGE2DARRAY             = 353,
-    UIMAGE2DARRAY             = 354,
-    IMAGECUBE                 = 355,
-    IIMAGECUBE                = 356,
-    UIMAGECUBE                = 357,
-    ATOMICUINT                = 358,
-    LAYOUT                    = 359,
-    YUVCSCSTANDARDEXT         = 360,
-    YUVCSCSTANDARDEXTCONSTANT = 361,
-    IDENTIFIER                = 362,
-    TYPE_NAME                 = 363,
-    FLOATCONSTANT             = 364,
-    INTCONSTANT               = 365,
-    UINTCONSTANT              = 366,
-    BOOLCONSTANT              = 367,
-    FIELD_SELECTION           = 368,
-    LEFT_OP                   = 369,
-    RIGHT_OP                  = 370,
-    INC_OP                    = 371,
-    DEC_OP                    = 372,
-    LE_OP                     = 373,
-    GE_OP                     = 374,
-    EQ_OP                     = 375,
-    NE_OP                     = 376,
-    AND_OP                    = 377,
-    OR_OP                     = 378,
-    XOR_OP                    = 379,
-    MUL_ASSIGN                = 380,
-    DIV_ASSIGN                = 381,
-    ADD_ASSIGN                = 382,
-    MOD_ASSIGN                = 383,
-    LEFT_ASSIGN               = 384,
-    RIGHT_ASSIGN              = 385,
-    AND_ASSIGN                = 386,
-    XOR_ASSIGN                = 387,
-    OR_ASSIGN                 = 388,
-    SUB_ASSIGN                = 389,
-    LEFT_PAREN                = 390,
-    RIGHT_PAREN               = 391,
-    LEFT_BRACKET              = 392,
-    RIGHT_BRACKET             = 393,
-    LEFT_BRACE                = 394,
-    RIGHT_BRACE               = 395,
-    DOT                       = 396,
-    COMMA                     = 397,
-    COLON                     = 398,
-    EQUAL                     = 399,
-    SEMICOLON                 = 400,
-    BANG                      = 401,
-    DASH                      = 402,
-    TILDE                     = 403,
-    PLUS                      = 404,
-    STAR                      = 405,
-    SLASH                     = 406,
-    PERCENT                   = 407,
-    LEFT_ANGLE                = 408,
-    RIGHT_ANGLE               = 409,
-    VERTICAL_BAR              = 410,
-    CARET                     = 411,
-    AMPERSAND                 = 412,
-    QUESTION                  = 413
+    NOPERSPECTIVE             = 311,
+    READONLY                  = 312,
+    WRITEONLY                 = 313,
+    COHERENT                  = 314,
+    RESTRICT                  = 315,
+    VOLATILE                  = 316,
+    SHARED                    = 317,
+    STRUCT                    = 318,
+    VOID_TYPE                 = 319,
+    WHILE                     = 320,
+    SAMPLER2D                 = 321,
+    SAMPLERCUBE               = 322,
+    SAMPLER_EXTERNAL_OES      = 323,
+    SAMPLER2DRECT             = 324,
+    SAMPLER2DARRAY            = 325,
+    ISAMPLER2D                = 326,
+    ISAMPLER3D                = 327,
+    ISAMPLERCUBE              = 328,
+    ISAMPLER2DARRAY           = 329,
+    USAMPLER2D                = 330,
+    USAMPLER3D                = 331,
+    USAMPLERCUBE              = 332,
+    USAMPLER2DARRAY           = 333,
+    SAMPLER2DMS               = 334,
+    ISAMPLER2DMS              = 335,
+    USAMPLER2DMS              = 336,
+    SAMPLER2DMSARRAY          = 337,
+    ISAMPLER2DMSARRAY         = 338,
+    USAMPLER2DMSARRAY         = 339,
+    SAMPLER3D                 = 340,
+    SAMPLER3DRECT             = 341,
+    SAMPLER2DSHADOW           = 342,
+    SAMPLERCUBESHADOW         = 343,
+    SAMPLER2DARRAYSHADOW      = 344,
+    SAMPLERVIDEOWEBGL         = 345,
+    SAMPLEREXTERNAL2DY2YEXT   = 346,
+    IMAGE2D                   = 347,
+    IIMAGE2D                  = 348,
+    UIMAGE2D                  = 349,
+    IMAGE3D                   = 350,
+    IIMAGE3D                  = 351,
+    UIMAGE3D                  = 352,
+    IMAGE2DARRAY              = 353,
+    IIMAGE2DARRAY             = 354,
+    UIMAGE2DARRAY             = 355,
+    IMAGECUBE                 = 356,
+    IIMAGECUBE                = 357,
+    UIMAGECUBE                = 358,
+    ATOMICUINT                = 359,
+    LAYOUT                    = 360,
+    YUVCSCSTANDARDEXT         = 361,
+    YUVCSCSTANDARDEXTCONSTANT = 362,
+    IDENTIFIER                = 363,
+    TYPE_NAME                 = 364,
+    FLOATCONSTANT             = 365,
+    INTCONSTANT               = 366,
+    UINTCONSTANT              = 367,
+    BOOLCONSTANT              = 368,
+    FIELD_SELECTION           = 369,
+    LEFT_OP                   = 370,
+    RIGHT_OP                  = 371,
+    INC_OP                    = 372,
+    DEC_OP                    = 373,
+    LE_OP                     = 374,
+    GE_OP                     = 375,
+    EQ_OP                     = 376,
+    NE_OP                     = 377,
+    AND_OP                    = 378,
+    OR_OP                     = 379,
+    XOR_OP                    = 380,
+    MUL_ASSIGN                = 381,
+    DIV_ASSIGN                = 382,
+    ADD_ASSIGN                = 383,
+    MOD_ASSIGN                = 384,
+    LEFT_ASSIGN               = 385,
+    RIGHT_ASSIGN              = 386,
+    AND_ASSIGN                = 387,
+    XOR_ASSIGN                = 388,
+    OR_ASSIGN                 = 389,
+    SUB_ASSIGN                = 390,
+    LEFT_PAREN                = 391,
+    RIGHT_PAREN               = 392,
+    LEFT_BRACKET              = 393,
+    RIGHT_BRACKET             = 394,
+    LEFT_BRACE                = 395,
+    RIGHT_BRACE               = 396,
+    DOT                       = 397,
+    COMMA                     = 398,
+    COLON                     = 399,
+    EQUAL                     = 400,
+    SEMICOLON                 = 401,
+    BANG                      = 402,
+    DASH                      = 403,
+    TILDE                     = 404,
+    PLUS                      = 405,
+    STAR                      = 406,
+    SLASH                     = 407,
+    PERCENT                   = 408,
+    LEFT_ANGLE                = 409,
+    RIGHT_ANGLE               = 410,
+    VERTICAL_BAR              = 411,
+    CARET                     = 412,
+    AMPERSAND                 = 413,
+    QUESTION                  = 414
 };
 #endif
 
diff --git a/src/compiler/translator/tree_ops/EarlyFragmentTestsOptimization.cpp b/src/compiler/translator/tree_ops/EarlyFragmentTestsOptimization.cpp
new file mode 100644
index 0000000..882fc40
--- /dev/null
+++ b/src/compiler/translator/tree_ops/EarlyFragmentTestsOptimization.cpp
@@ -0,0 +1,79 @@
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// CheckEarlyFragmentTestOptimization is an AST traverser to check if early fragment
+// test as an optimization is feasible.
+//
+
+#include "compiler/translator/tree_ops/EarlyFragmentTestsOptimization.h"
+
+#include "compiler/translator/InfoSink.h"
+#include "compiler/translator/Symbol.h"
+#include "compiler/translator/tree_util/IntermNode_util.h"
+#include "compiler/translator/tree_util/IntermTraverse.h"
+
+namespace sh
+{
+
+namespace
+{
+
+// Traverser that check conditions that would prevent early fragment tests optmization.
+class CheckEFTOptimizationTraverser : public TIntermTraverser
+{
+  public:
+    CheckEFTOptimizationTraverser();
+
+    void visitSymbol(TIntermSymbol *node) override;
+    bool visitBranch(Visit visit, TIntermBranch *node) override;
+
+    bool isFragDepthUsed() { return mFragDepthUsed; }
+    bool isDiscardOpUsed() { return mDiscardOpUsed; }
+
+  protected:
+    bool mFragDepthUsed;
+    bool mDiscardOpUsed;
+};
+
+CheckEFTOptimizationTraverser::CheckEFTOptimizationTraverser()
+    : TIntermTraverser(true, false, false), mFragDepthUsed(false), mDiscardOpUsed(false)
+{}
+
+void CheckEFTOptimizationTraverser::visitSymbol(TIntermSymbol *node)
+{
+    // Check the qualifier from the variable, not from the symbol node. The node may have a
+    // different qualifier if it's the result of a folded ternary node.
+    TQualifier qualifier = node->variable().getType().getQualifier();
+
+    if (qualifier == EvqFragDepth || qualifier == EvqFragDepthEXT)
+    {
+        mFragDepthUsed = true;
+    }
+}
+
+bool CheckEFTOptimizationTraverser::visitBranch(Visit visit, TIntermBranch *node)
+{
+    if (node->getFlowOp() == EOpKill)
+    {
+        mDiscardOpUsed = true;
+    }
+    return true;
+}
+
+}  // namespace
+
+bool CheckEarlyFragmentTestsFeasible(TCompiler *compiler, TIntermNode *root)
+{
+    CheckEFTOptimizationTraverser traverser;
+    root->traverse(&traverser);
+
+    if (traverser.isFragDepthUsed() || traverser.isDiscardOpUsed())
+    {
+        return false;
+    }
+    return true;
+}
+
+}  // namespace sh
diff --git a/src/compiler/translator/tree_ops/EarlyFragmentTestsOptimization.h b/src/compiler/translator/tree_ops/EarlyFragmentTestsOptimization.h
new file mode 100644
index 0000000..4b0e556
--- /dev/null
+++ b/src/compiler/translator/tree_ops/EarlyFragmentTestsOptimization.h
@@ -0,0 +1,23 @@
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// CheckEarlyFragmentTestsOptimization is an AST traverser to check if early fragment
+// tests as an optimization is feasible.
+//
+
+#ifndef COMPILER_TRANSLATOR_TREEOPS_EARLYFRAGMENTTESTSOPTIMIZATION_H_
+#define COMPILER_TRANSLATOR_TREEOPS_EARLYFRAGMENTTESTSOPTIMIZATION_H_
+
+#include "common/angleutils.h"
+
+namespace sh
+{
+class TCompiler;
+class TIntermNode;
+
+ANGLE_NO_DISCARD bool CheckEarlyFragmentTestsFeasible(TCompiler *compiler, TIntermNode *root);
+}  // namespace sh
+
+#endif  // COMPILER_TRANSLATOR_TREEOPS_EARLYFRAGMENTTESTSOPTIMIZATION_H_
diff --git a/src/compiler/translator/util.cpp b/src/compiler/translator/util.cpp
index dfabb32..cddbd43 100644
--- a/src/compiler/translator/util.cpp
+++ b/src/compiler/translator/util.cpp
@@ -33,6 +33,7 @@
     {
         case EvqSmoothIn:
         case EvqFlatIn:
+        case EvqNoPerspectiveIn:
         case EvqCentroidIn:
             return true;
         default:
@@ -519,6 +520,7 @@
         case EvqVaryingOut:
         case EvqSmoothOut:
         case EvqFlatOut:
+        case EvqNoPerspectiveOut:
         case EvqCentroidOut:
         case EvqVertexOut:
         case EvqGeometryOut:
@@ -538,6 +540,7 @@
         case EvqVaryingIn:
         case EvqSmoothIn:
         case EvqFlatIn:
+        case EvqNoPerspectiveIn:
         case EvqCentroidIn:
         case EvqFragmentIn:
         case EvqGeometryIn:
@@ -569,6 +572,10 @@
         case EvqFlatOut:
             return INTERPOLATION_FLAT;
 
+        case EvqNoPerspectiveIn:
+        case EvqNoPerspectiveOut:
+            return INTERPOLATION_NOPERSPECTIVE;
+
         case EvqSmoothIn:
         case EvqSmoothOut:
         case EvqVertexOut:
diff --git a/src/feature_support_util/OWNERS b/src/feature_support_util/OWNERS
new file mode 100644
index 0000000..a8c6596
--- /dev/null
+++ b/src/feature_support_util/OWNERS
@@ -0,0 +1 @@
+ianelliot@google.com
diff --git a/src/libANGLE/Caps.cpp b/src/libANGLE/Caps.cpp
index 06c038e..460cbe2 100644
--- a/src/libANGLE/Caps.cpp
+++ b/src/libANGLE/Caps.cpp
@@ -223,19 +223,32 @@
 // Checks for GL_NV_read_depth support
 static bool DetermineReadDepthSupport(const TextureCapsMap &textureCaps)
 {
-    return false;
+    constexpr GLenum requiredFormats[] = {
+        GL_DEPTH_COMPONENT16,
+    };
+
+    return GetFormatSupport(textureCaps, requiredFormats, true, false, true, false, false);
 }
 
 // Checks for GL_NV_read_stencil support
 static bool DetermineReadStencilSupport(const TextureCapsMap &textureCaps)
 {
-    return false;
+    constexpr GLenum requiredFormats[] = {
+        GL_STENCIL_INDEX8,
+    };
+
+    return GetFormatSupport(textureCaps, requiredFormats, false, false, true, false, false);
 }
 
 // Checks for GL_NV_depth_buffer_float2 support
 static bool DetermineDepthBufferFloat2Support(const TextureCapsMap &textureCaps)
 {
-    return false;
+    constexpr GLenum requiredFormats[] = {
+        GL_DEPTH_COMPONENT32F,
+        GL_DEPTH32F_STENCIL8,
+    };
+
+    return GetFormatSupport(textureCaps, requiredFormats, true, false, true, false, false);
 }
 
 // Checks for GL_OES_rgb8_rgba8 support
@@ -599,6 +612,14 @@
            GetFormatSupport(textureCaps, requiredRenderFormats, true, false, true, true, false);
 }
 
+// Check for GL_EXT_texture_sRGB_R8 support
+static bool DetermineSRGBR8TextureSupport(const TextureCapsMap &textureCaps)
+{
+    constexpr GLenum requiredFilterFormats[] = {GL_SR8_EXT};
+
+    return GetFormatSupport(textureCaps, requiredFilterFormats, true, true, false, false, false);
+}
+
 // Check for GL_ANGLE_depth_texture support
 static bool DetermineDepthTextureANGLESupport(const TextureCapsMap &textureCaps)
 {
@@ -807,6 +828,7 @@
     compressedEACRG11UnsignedTextureOES = DetermineEACRG11UnsignedTextureSupport(textureCaps);
     compressedEACRG11SignedTextureOES   = DetermineEACRG11SignedTextureSupport(textureCaps);
     sRGB                                = DetermineSRGBTextureSupport(textureCaps);
+    sRGBR8EXT                           = DetermineSRGBR8TextureSupport(textureCaps);
     depthTextureANGLE                   = DetermineDepthTextureANGLESupport(textureCaps);
     depthTextureOES                     = DetermineDepthTextureOESSupport(textureCaps);
     depth24OES                          = DetermineDepth24OESSupport(textureCaps);
@@ -850,9 +872,9 @@
         map["GL_OES_packed_depth_stencil"] = esOnlyExtension(&Extensions::packedDepthStencilOES);
         map["GL_OES_get_program_binary"] = enableableExtension(&Extensions::getProgramBinaryOES);
         map["GL_OES_rgb8_rgba8"] = enableableExtension(&Extensions::rgb8rgba8OES);
-        map["GL_NV_read_depth"] = esOnlyExtension(&Extensions::readDepthNV);
-        map["GL_NV_read_stencil"] = esOnlyExtension(&Extensions::readStencilNV);
-        map["GL_NV_depth_buffer_float2"] = esOnlyExtension(&Extensions::depthBufferFloat2NV);
+        map["GL_NV_read_depth"] = enableableExtension(&Extensions::readDepthNV);
+        map["GL_NV_read_stencil"] = enableableExtension(&Extensions::readStencilNV);
+        map["GL_NV_depth_buffer_float2"] = enableableExtension(&Extensions::depthBufferFloat2NV);
         map["GL_EXT_texture_format_BGRA8888"] = enableableExtension(&Extensions::textureFormatBGRA8888);
         map["GL_EXT_texture_type_2_10_10_10_REV"] = enableableExtension(&Extensions::textureFormat2101010REV);
         map["GL_EXT_read_format_bgra"] = enableableExtension(&Extensions::readFormatBGRA);
@@ -872,10 +894,12 @@
         map["GL_EXT_texture_compression_s3tc_srgb"] = enableableExtension(&Extensions::textureCompressionS3TCsRGB);
         map["GL_KHR_texture_compression_astc_ldr"] = enableableExtension(&Extensions::textureCompressionASTCLDRKHR);
         map["GL_KHR_texture_compression_astc_hdr"] = enableableExtension(&Extensions::textureCompressionASTCHDRKHR);
+        map["GL_KHR_texture_compression_astc_sliced_3d"] = enableableExtension(&Extensions::textureCompressionSliced3dASTCKHR);
         map["GL_OES_texture_compression_astc"] = enableableExtension(&Extensions::textureCompressionASTCOES);
         map["GL_EXT_texture_compression_bptc"] = enableableExtension(&Extensions::textureCompressionBPTC);
         map["GL_EXT_texture_compression_rgtc"] = enableableExtension(&Extensions::textureCompressionRGTC);
         map["GL_OES_compressed_ETC1_RGB8_texture"] = enableableExtension(&Extensions::compressedETC1RGB8TextureOES);
+        map["GL_EXT_compressed_ETC1_RGB8_sub_texture"] = enableableExtension(&Extensions::compressedETC1RGB8SubTexture);
         map["GL_OES_compressed_ETC2_RGB8_texture"] = enableableExtension(&Extensions::compressedETC2RGB8TextureOES);
         map["GL_OES_compressed_ETC2_sRGB8_texture"] = enableableExtension(&Extensions::compressedETC2sRGB8TextureOES);
         map["GL_OES_compressed_ETC2_punchthroughA_RGBA8_texture"] = enableableExtension(&Extensions::compressedETC2PunchthroughARGB8TextureOES);
@@ -890,6 +914,7 @@
         map["GL_IMG_texture_compression_pvrtc"] = enableableExtension(&Extensions::compressedTexturePVRTC);
         map["GL_EXT_pvrtc_sRGB"] = enableableExtension(&Extensions::compressedTexturePVRTCsRGB);
         map["GL_EXT_sRGB"] = enableableExtension(&Extensions::sRGB);
+        map["GL_EXT_texture_sRGB_R8"] = enableableExtension(&Extensions::sRGBR8EXT);
         map["GL_ANGLE_depth_texture"] = esOnlyExtension(&Extensions::depthTextureANGLE);
         map["GL_OES_depth_texture"] = esOnlyExtension(&Extensions::depthTextureOES);
         map["GL_OES_depth_texture_cube_map"] = enableableExtension(&Extensions::depthTextureCubeMapOES);
@@ -935,6 +960,7 @@
         map["GL_EXT_semaphore"] = enableableExtension(&Extensions::semaphore);
         map["GL_EXT_semaphore_fd"] = enableableExtension(&Extensions::semaphoreFd);
         map["GL_NV_EGL_stream_consumer_external"] = enableableExtension(&Extensions::eglStreamConsumerExternalNV);
+        map["GL_NV_shader_noperspective_interpolation"] = enableableExtension(&Extensions::noperspectiveInterpolationNV);
         map["GL_ANGLE_semaphore_fuchsia"] = enableableExtension(&Extensions::semaphoreFuchsiaANGLE);
         map["GL_EXT_unpack_subimage"] = enableableExtension(&Extensions::unpackSubimage);
         map["GL_NV_pack_subimage"] = enableableExtension(&Extensions::packSubimage);
@@ -962,7 +988,6 @@
         map["GL_EXT_multisample_compatibility"] = esOnlyExtension(&Extensions::multisampleCompatibility);
         map["GL_CHROMIUM_framebuffer_mixed_samples"] = esOnlyExtension(&Extensions::framebufferMixedSamples);
         map["GL_EXT_texture_norm16"] = enableableExtension(&Extensions::textureNorm16);
-        map["GL_CHROMIUM_path_rendering"] = esOnlyExtension(&Extensions::pathRendering);
         map["GL_OES_surfaceless_context"] = esOnlyExtension(&Extensions::surfacelessContextOES);
         map["GL_ANGLE_client_arrays"] = esOnlyExtension(&Extensions::clientArrays);
         map["GL_ANGLE_robust_resource_initialization"] = esOnlyExtension(&Extensions::robustResourceInitialization);
@@ -992,6 +1017,7 @@
         map["GL_OES_point_sprite"] = enableableExtension(&Extensions::pointSpriteOES);
         map["GL_OES_draw_texture"] = enableableExtension(&Extensions::drawTextureOES);
         map["GL_ANGLE_memory_size"] = enableableExtension(&Extensions::memorySize);
+        map["GL_EXT_shader_non_constant_global_initializers"] = enableableExtension(&Extensions::shaderNonConstGlobalInitializersEXT);
         map["GL_WEBGL_video_texture"] = enableableExtension(&Extensions::webglVideoTexture);
         // clang-format on
 
@@ -1312,6 +1338,7 @@
     InsertExtensionString("EGL_KHR_image",                                       image,                              &extensionStrings);
     InsertExtensionString("EGL_KHR_image_base",                                  imageBase,                          &extensionStrings);
     InsertExtensionString("EGL_KHR_image_pixmap",                                imagePixmap,                        &extensionStrings);
+    InsertExtensionString("EGL_EXT_image_gl_colorspace",                         imageGlColorspace,                  &extensionStrings);
     InsertExtensionString("EGL_KHR_gl_colorspace",                               glColorspace,                       &extensionStrings);
     InsertExtensionString("EGL_EXT_gl_colorspace_scrgb",                         glColorspaceScrgb,                  &extensionStrings);
     InsertExtensionString("EGL_EXT_gl_colorspace_scrgb_linear",                  glColorspaceScrgbLinear,            &extensionStrings);
@@ -1333,6 +1360,7 @@
     InsertExtensionString("EGL_ANGLE_create_context_webgl_compatibility",        createContextWebGLCompatibility,    &extensionStrings);
     InsertExtensionString("EGL_CHROMIUM_create_context_bind_generates_resource", createContextBindGeneratesResource, &extensionStrings);
     InsertExtensionString("EGL_CHROMIUM_sync_control",                           syncControlCHROMIUM,                &extensionStrings);
+    InsertExtensionString("EGL_ANGLE_sync_control_rate",                         syncControlRateANGLE,               &extensionStrings);
     InsertExtensionString("EGL_KHR_swap_buffers_with_damage",                    swapBuffersWithDamage,              &extensionStrings);
     InsertExtensionString("EGL_EXT_pixel_format_float",                          pixelFormatFloat,                   &extensionStrings);
     InsertExtensionString("EGL_KHR_surfaceless_context",                         surfacelessContext,                 &extensionStrings);
diff --git a/src/libANGLE/Caps.h b/src/libANGLE/Caps.h
index 17b9de2..157870d 100644
--- a/src/libANGLE/Caps.h
+++ b/src/libANGLE/Caps.h
@@ -213,6 +213,9 @@
     // GL_OES_texture_compression_astc
     bool textureCompressionASTCOES = false;
 
+    // GL_KHR_texture_compression_astc_sliced_3d
+    bool textureCompressionSliced3dASTCKHR = false;
+
     // GL_EXT_texture_compression_bptc
     bool textureCompressionBPTC = false;
 
@@ -223,6 +226,9 @@
     // Implies that TextureCaps for GL_ETC1_RGB8_OES exist
     bool compressedETC1RGB8TextureOES = false;
 
+    // GL_EXT_compressed_ETC1_RGB8_sub_texture
+    bool compressedETC1RGB8SubTexture = false;
+
     // OES_compressed_ETC2_RGB8_texture
     bool compressedETC2RGB8TextureOES = false;
 
@@ -271,6 +277,9 @@
     // TODO: Don't advertise this extension in ES3
     bool sRGB = false;
 
+    // GL_EXT_texture_sRGB_R8
+    bool sRGBR8EXT = false;
+
     // GL_ANGLE_depth_texture
     bool depthTextureANGLE = false;
 
@@ -425,6 +434,9 @@
     // NV_pack_subimage
     bool packSubimage = false;
 
+    // GL_NV_shader_noperspective_interpolation
+    bool noperspectiveInterpolationNV = false;
+
     // GL_OES_vertex_half_float
     bool vertexHalfFloatOES = false;
 
@@ -505,9 +517,6 @@
     // written against ES 3.1 but can apply to ES 3.0 as well.
     bool textureNorm16 = false;
 
-    // GL_CHROMIUM_path_rendering
-    bool pathRendering = false;
-
     // GL_OES_surfaceless_context
     bool surfacelessContextOES = false;
 
@@ -595,6 +604,9 @@
         return (drawElementsBaseVertexOES || drawElementsBaseVertexEXT);
     }
 
+    // GL_EXT_shader_non_constant_global_initializers
+    bool shaderNonConstGlobalInitializersEXT = false;
+
     // GL_EXT_gpu_shader5
     bool gpuShader5EXT = false;
     // WEBGL_video_texture
@@ -944,6 +956,9 @@
     // EGL_CHROMIUM_sync_control
     bool syncControlCHROMIUM = false;
 
+    // EGL_ANGLE_sync_control_rate
+    bool syncControlRateANGLE = false;
+
     // EGL_KHR_swap_buffers_with_damage
     bool swapBuffersWithDamage = false;
 
@@ -1033,6 +1048,9 @@
 
     // EGL_ANDROID_framebuffer_target
     bool framebufferTargetANDROID = false;
+
+    // EGL_EXT_image_gl_colorspace
+    bool imageGlColorspace = false;
 };
 
 struct DeviceExtensions
diff --git a/src/libANGLE/Compiler.cpp b/src/libANGLE/Compiler.cpp
index 4163223..d7822d2 100644
--- a/src/libANGLE/Compiler.cpp
+++ b/src/libANGLE/Compiler.cpp
@@ -90,11 +90,14 @@
     mResources.OES_standard_derivatives     = extensions.standardDerivativesOES;
     mResources.EXT_draw_buffers             = extensions.drawBuffers;
     mResources.EXT_shader_texture_lod       = extensions.shaderTextureLOD;
-    mResources.OES_EGL_image_external       = extensions.eglImageExternalOES;
-    mResources.OES_EGL_image_external_essl3 = extensions.eglImageExternalEssl3OES;
-    mResources.NV_EGL_stream_consumer_external = extensions.eglStreamConsumerExternalNV;
-    mResources.ARB_texture_rectangle           = extensions.textureRectangle;
-    mResources.EXT_gpu_shader5                 = extensions.gpuShader5EXT;
+    mResources.EXT_shader_non_constant_global_initializers =
+        extensions.shaderNonConstGlobalInitializersEXT;
+    mResources.OES_EGL_image_external                = extensions.eglImageExternalOES;
+    mResources.OES_EGL_image_external_essl3          = extensions.eglImageExternalEssl3OES;
+    mResources.NV_EGL_stream_consumer_external       = extensions.eglStreamConsumerExternalNV;
+    mResources.NV_shader_noperspective_interpolation = extensions.noperspectiveInterpolationNV;
+    mResources.ARB_texture_rectangle                 = extensions.textureRectangle;
+    mResources.EXT_gpu_shader5                       = extensions.gpuShader5EXT;
     mResources.OES_texture_storage_multisample_2d_array =
         extensions.textureStorageMultisample2DArrayOES;
     mResources.OES_texture_3D                  = extensions.texture3DOES;
diff --git a/src/libANGLE/Context.cpp b/src/libANGLE/Context.cpp
index 3be9404..2e517b0 100644
--- a/src/libANGLE/Context.cpp
+++ b/src/libANGLE/Context.cpp
@@ -28,7 +28,6 @@
 #include "libANGLE/Framebuffer.h"
 #include "libANGLE/FramebufferAttachment.h"
 #include "libANGLE/MemoryObject.h"
-#include "libANGLE/Path.h"
 #include "libANGLE/Program.h"
 #include "libANGLE/ProgramPipeline.h"
 #include "libANGLE/Query.h"
@@ -52,58 +51,6 @@
 namespace
 {
 template <typename T>
-std::vector<Path *> GatherPaths(PathManager &resourceManager,
-                                GLsizei numPaths,
-                                const void *paths,
-                                PathID pathBase)
-{
-    std::vector<Path *> ret;
-    ret.reserve(numPaths);
-
-    const auto *nameArray = static_cast<const T *>(paths);
-
-    for (GLsizei i = 0; i < numPaths; ++i)
-    {
-        const GLuint pathName = nameArray[i] + pathBase.value;
-
-        ret.push_back(resourceManager.getPath({pathName}));
-    }
-
-    return ret;
-}
-
-std::vector<Path *> GatherPaths(PathManager &resourceManager,
-                                GLsizei numPaths,
-                                GLenum pathNameType,
-                                const void *paths,
-                                PathID pathBase)
-{
-    switch (pathNameType)
-    {
-        case GL_UNSIGNED_BYTE:
-            return GatherPaths<GLubyte>(resourceManager, numPaths, paths, pathBase);
-
-        case GL_BYTE:
-            return GatherPaths<GLbyte>(resourceManager, numPaths, paths, pathBase);
-
-        case GL_UNSIGNED_SHORT:
-            return GatherPaths<GLushort>(resourceManager, numPaths, paths, pathBase);
-
-        case GL_SHORT:
-            return GatherPaths<GLshort>(resourceManager, numPaths, paths, pathBase);
-
-        case GL_UNSIGNED_INT:
-            return GatherPaths<GLuint>(resourceManager, numPaths, paths, pathBase);
-
-        case GL_INT:
-            return GatherPaths<GLint>(resourceManager, numPaths, paths, pathBase);
-    }
-
-    UNREACHABLE();
-    return std::vector<Path *>();
-}
-
-template <typename T>
 angle::Result GetQueryObjectParameter(const Context *context, Query *query, GLenum pname, T *params)
 {
     ASSERT(query != nullptr || pname == GL_QUERY_RESULT_AVAILABLE_EXT);
@@ -308,8 +255,7 @@
                  const egl::AttributeMap &attribs,
                  const egl::DisplayExtensions &displayExtensions,
                  const egl::ClientExtensions &clientExtensions)
-    : mState(reinterpret_cast<ContextID>(this),
-             shareContext ? &shareContext->mState : nullptr,
+    : mState(shareContext ? &shareContext->mState : nullptr,
              shareTextures,
              &mOverlay,
              clientType,
@@ -495,14 +441,10 @@
     mDrawDirtyObjects.set(State::DIRTY_OBJECT_VERTEX_ARRAY);
     mDrawDirtyObjects.set(State::DIRTY_OBJECT_TEXTURES);
     mDrawDirtyObjects.set(State::DIRTY_OBJECT_PROGRAM);
+    mDrawDirtyObjects.set(State::DIRTY_OBJECT_PROGRAM_PIPELINE);
     mDrawDirtyObjects.set(State::DIRTY_OBJECT_SAMPLERS);
     mDrawDirtyObjects.set(State::DIRTY_OBJECT_IMAGES);
 
-    mPathOperationDirtyObjects.set(State::DIRTY_OBJECT_DRAW_FRAMEBUFFER);
-    mPathOperationDirtyObjects.set(State::DIRTY_OBJECT_VERTEX_ARRAY);
-    mPathOperationDirtyObjects.set(State::DIRTY_OBJECT_TEXTURES);
-    mPathOperationDirtyObjects.set(State::DIRTY_OBJECT_SAMPLERS);
-
     mTexImageDirtyBits.set(State::DIRTY_BIT_UNPACK_STATE);
     mTexImageDirtyBits.set(State::DIRTY_BIT_UNPACK_BUFFER_BINDING);
     // No dirty objects.
@@ -548,6 +490,7 @@
     mComputeDirtyBits.set(State::DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING);
     mComputeDirtyObjects.set(State::DIRTY_OBJECT_TEXTURES);
     mComputeDirtyObjects.set(State::DIRTY_OBJECT_PROGRAM);
+    mComputeDirtyObjects.set(State::DIRTY_OBJECT_PROGRAM_PIPELINE);
     mComputeDirtyObjects.set(State::DIRTY_OBJECT_IMAGES);
     mComputeDirtyObjects.set(State::DIRTY_OBJECT_SAMPLERS);
 
@@ -622,14 +565,16 @@
     mState.reset(this);
 
     mState.mBufferManager->release(this);
+    // mProgramPipelineManager must be before mShaderProgramManager to give each
+    // PPO the chance to release any references they have to the Programs that
+    // are bound to them before the Programs are released()'ed.
+    mState.mProgramPipelineManager->release(this);
     mState.mShaderProgramManager->release(this);
     mState.mTextureManager->release(this);
     mState.mRenderbufferManager->release(this);
     mState.mSamplerManager->release(this);
     mState.mSyncManager->release(this);
-    mState.mPathManager->release(this);
     mState.mFramebufferManager->release(this);
-    mState.mProgramPipelineManager->release(this);
     mState.mMemoryObjectManager->release(this);
     mState.mSemaphoreManager->release(this);
 
@@ -747,18 +692,6 @@
     return mState.mRenderbufferManager->createRenderbuffer();
 }
 
-void Context::tryGenPaths(GLsizei range, PathID *createdOut)
-{
-    ANGLE_CONTEXT_TRY(mState.mPathManager->createPaths(this, range, createdOut));
-}
-
-GLuint Context::genPaths(GLsizei range)
-{
-    PathID created = {0};
-    tryGenPaths(range, &created);
-    return created.value;
-}
-
 // Returns an unused framebuffer name
 FramebufferID Context::createFramebuffer()
 {
@@ -782,7 +715,57 @@
 
 GLuint Context::createShaderProgramv(ShaderType type, GLsizei count, const GLchar *const *strings)
 {
-    UNIMPLEMENTED();
+    const ShaderProgramID shaderID = FromGL<ShaderProgramID>(createShader(type));
+    if (shaderID.value)
+    {
+        Shader *shaderObject = getShader(shaderID);
+        ASSERT(shaderObject);
+        shaderObject->setSource(count, strings, nullptr);
+        shaderObject->compile(this);
+        const ShaderProgramID programID = FromGL<ShaderProgramID>(createProgram());
+        if (programID.value)
+        {
+            gl::Program *programObject = getProgramNoResolveLink(programID);
+            ASSERT(programObject);
+
+            if (shaderObject->isCompiled())
+            {
+                // As per Khronos issue 2261:
+                // https://gitlab.khronos.org/Tracker/vk-gl-cts/issues/2261
+                // We must wait to mark the program separable until it's successfully compiled.
+                programObject->setSeparable(true);
+
+                programObject->attachShader(this, shaderObject);
+
+                if (programObject->link(this) != angle::Result::Continue)
+                {
+                    deleteShader(shaderID);
+                    deleteProgram(programID);
+                    return 0u;
+                }
+                if (onProgramLink(programObject) != angle::Result::Continue)
+                {
+                    deleteShader(shaderID);
+                    deleteProgram(programID);
+                    return 0u;
+                }
+
+                // Need to manually resolveLink(), since onProgramLink() doesn't think the program
+                // is in use.   For the normal glDetachShader() API call path, this is done during
+                // ValidateDetachShader() via gl::GetValidProgram().
+                programObject->resolveLink(this);
+                programObject->detachShader(this, shaderObject);
+            }
+
+            InfoLog &programInfoLog = programObject->getExecutable().getInfoLog();
+            programInfoLog << shaderObject->getInfoLogString();
+        }
+
+        deleteShader(shaderID);
+
+        return programID.value;
+    }
+
     return 0u;
 }
 
@@ -846,14 +829,15 @@
     mState.mSyncManager->deleteObject(this, static_cast<GLuint>(reinterpret_cast<uintptr_t>(sync)));
 }
 
-void Context::deleteProgramPipeline(ProgramPipelineID pipeline)
+void Context::deleteProgramPipeline(ProgramPipelineID pipelineID)
 {
-    if (mState.mProgramPipelineManager->getProgramPipeline(pipeline))
+    ProgramPipeline *pipeline = mState.mProgramPipelineManager->getProgramPipeline(pipelineID);
+    if (pipeline)
     {
-        detachProgramPipeline(pipeline);
+        detachProgramPipeline(pipelineID);
     }
 
-    mState.mProgramPipelineManager->deleteObject(this, pipeline);
+    mState.mProgramPipelineManager->deleteObject(this, pipelineID);
 }
 
 void Context::deleteMemoryObject(MemoryObjectID memoryObject)
@@ -866,110 +850,6 @@
     mState.mSemaphoreManager->deleteSemaphore(this, semaphore);
 }
 
-void Context::deletePaths(PathID first, GLsizei range)
-{
-    mState.mPathManager->deletePaths(first, range);
-}
-
-GLboolean Context::isPath(PathID path) const
-{
-    const auto *pathObj = mState.mPathManager->getPath(path);
-    if (pathObj == nullptr)
-        return false;
-
-    return pathObj->hasPathData();
-}
-
-bool Context::isPathGenerated(PathID path) const
-{
-    return mState.mPathManager->hasPath(path);
-}
-
-void Context::pathCommands(PathID path,
-                           GLsizei numCommands,
-                           const GLubyte *commands,
-                           GLsizei numCoords,
-                           GLenum coordType,
-                           const void *coords)
-{
-    auto *pathObject = mState.mPathManager->getPath(path);
-
-    ANGLE_CONTEXT_TRY(pathObject->setCommands(numCommands, commands, numCoords, coordType, coords));
-}
-
-void Context::pathParameterf(PathID path, GLenum pname, GLfloat value)
-{
-    Path *pathObj = mState.mPathManager->getPath(path);
-
-    switch (pname)
-    {
-        case GL_PATH_STROKE_WIDTH_CHROMIUM:
-            pathObj->setStrokeWidth(value);
-            break;
-        case GL_PATH_END_CAPS_CHROMIUM:
-            pathObj->setEndCaps(static_cast<GLenum>(value));
-            break;
-        case GL_PATH_JOIN_STYLE_CHROMIUM:
-            pathObj->setJoinStyle(static_cast<GLenum>(value));
-            break;
-        case GL_PATH_MITER_LIMIT_CHROMIUM:
-            pathObj->setMiterLimit(value);
-            break;
-        case GL_PATH_STROKE_BOUND_CHROMIUM:
-            pathObj->setStrokeBound(value);
-            break;
-        default:
-            UNREACHABLE();
-            break;
-    }
-}
-
-void Context::pathParameteri(PathID path, GLenum pname, GLint value)
-{
-    // TODO(jmadill): Should use proper clamping/casting.
-    pathParameterf(path, pname, static_cast<GLfloat>(value));
-}
-
-void Context::getPathParameterfv(PathID path, GLenum pname, GLfloat *value)
-{
-    const Path *pathObj = mState.mPathManager->getPath(path);
-
-    switch (pname)
-    {
-        case GL_PATH_STROKE_WIDTH_CHROMIUM:
-            *value = pathObj->getStrokeWidth();
-            break;
-        case GL_PATH_END_CAPS_CHROMIUM:
-            *value = static_cast<GLfloat>(pathObj->getEndCaps());
-            break;
-        case GL_PATH_JOIN_STYLE_CHROMIUM:
-            *value = static_cast<GLfloat>(pathObj->getJoinStyle());
-            break;
-        case GL_PATH_MITER_LIMIT_CHROMIUM:
-            *value = pathObj->getMiterLimit();
-            break;
-        case GL_PATH_STROKE_BOUND_CHROMIUM:
-            *value = pathObj->getStrokeBound();
-            break;
-        default:
-            UNREACHABLE();
-            break;
-    }
-}
-
-void Context::getPathParameteriv(PathID path, GLenum pname, GLint *value)
-{
-    GLfloat val = 0.0f;
-    getPathParameterfv(path, pname, value != nullptr ? &val : nullptr);
-    if (value)
-        *value = static_cast<GLint>(val);
-}
-
-void Context::pathStencilFunc(GLenum func, GLint ref, GLuint mask)
-{
-    mState.setPathStencilFunc(func, ref, mask);
-}
-
 // GL_CHROMIUM_lose_context
 void Context::loseContext(GraphicsResetStatus current, GraphicsResetStatus other)
 {
@@ -1071,6 +951,8 @@
             return getRenderbuffer({name});
         case GL_FRAMEBUFFER:
             return getFramebuffer({name});
+        case GL_PROGRAM_PIPELINE:
+            return getProgramPipeline({name});
         default:
             UNREACHABLE();
             return nullptr;
@@ -1153,7 +1035,7 @@
 void Context::bindReadFramebuffer(FramebufferID framebufferHandle)
 {
     Framebuffer *framebuffer = mState.mFramebufferManager->checkFramebufferAllocation(
-        mImplementation.get(), mState.mCaps, framebufferHandle);
+        mImplementation.get(), mState.mCaps, framebufferHandle, mState.getContextID());
     mState.setReadFramebufferBinding(framebuffer);
     mReadFramebufferObserverBinding.bind(framebuffer);
 }
@@ -1161,7 +1043,7 @@
 void Context::bindDrawFramebuffer(FramebufferID framebufferHandle)
 {
     Framebuffer *framebuffer = mState.mFramebufferManager->checkFramebufferAllocation(
-        mImplementation.get(), mState.mCaps, framebufferHandle);
+        mImplementation.get(), mState.mCaps, framebufferHandle, mState.getContextID());
     mState.setDrawFramebufferBinding(framebuffer);
     mDrawFramebufferObserverBinding.bind(framebuffer);
     mStateCache.onDrawFramebufferChange(this);
@@ -1219,7 +1101,14 @@
                                GLbitfield stages,
                                ShaderProgramID program)
 {
-    UNIMPLEMENTED();
+    Program *shaderProgram = getProgramNoResolveLink(program);
+    ProgramPipeline *programPipeline =
+        mState.mProgramPipelineManager->checkProgramPipelineAllocation(mImplementation.get(),
+                                                                       pipeline);
+
+    ASSERT(programPipeline);
+    ANGLE_CONTEXT_TRY(mState.useProgramStages(this, programPipeline, stages, shaderProgram));
+    mStateCache.onProgramExecutableChange(this);
 }
 
 void Context::bindTransformFeedback(GLenum target, TransformFeedbackID transformFeedbackHandle)
@@ -1234,7 +1123,7 @@
 {
     ProgramPipeline *pipeline = mState.mProgramPipelineManager->checkProgramPipelineAllocation(
         mImplementation.get(), pipelineHandle);
-    mState.setProgramPipelineBinding(this, pipeline);
+    ANGLE_CONTEXT_TRY(mState.setProgramPipelineBinding(this, pipeline));
 }
 
 void Context::beginQuery(QueryType target, QueryID query)
@@ -1480,25 +1369,6 @@
         case GL_MAX_TEXTURE_LOD_BIAS:
             *params = mState.mCaps.maxLODBias;
             break;
-
-        case GL_PATH_MODELVIEW_MATRIX_CHROMIUM:
-        case GL_PATH_PROJECTION_MATRIX_CHROMIUM:
-        {
-            // GLES1 emulation: // GL_PATH_(MODELVIEW|PROJECTION)_MATRIX_CHROMIUM collides with the
-            // GLES1 constants for modelview/projection matrix.
-            if (getClientVersion() < Version(2, 0))
-            {
-                mState.getFloatv(pname, params);
-            }
-            else
-            {
-                ASSERT(mState.mExtensions.pathRendering);
-                const GLfloat *m = mState.getPathRenderingMatrix(pname);
-                memcpy(params, m, 16 * sizeof(GLfloat));
-            }
-        }
-        break;
-
         default:
             mState.getFloatv(pname, params);
             break;
@@ -2486,215 +2356,6 @@
     mState.setCoverageModulation(components);
 }
 
-void Context::matrixLoadf(GLenum matrixMode, const GLfloat *matrix)
-{
-    mState.loadPathRenderingMatrix(matrixMode, matrix);
-}
-
-void Context::matrixLoadIdentity(GLenum matrixMode)
-{
-    GLfloat I[16];
-    angle::Matrix<GLfloat>::setToIdentity(I);
-
-    mState.loadPathRenderingMatrix(matrixMode, I);
-}
-
-void Context::stencilFillPath(PathID path, GLenum fillMode, GLuint mask)
-{
-    const auto *pathObj = mState.mPathManager->getPath(path);
-    if (!pathObj)
-        return;
-
-    ANGLE_CONTEXT_TRY(syncStateForPathOperation());
-
-    mImplementation->stencilFillPath(pathObj, fillMode, mask);
-}
-
-void Context::stencilStrokePath(PathID path, GLint reference, GLuint mask)
-{
-    const auto *pathObj = mState.mPathManager->getPath(path);
-    if (!pathObj)
-        return;
-
-    ANGLE_CONTEXT_TRY(syncStateForPathOperation());
-
-    mImplementation->stencilStrokePath(pathObj, reference, mask);
-}
-
-void Context::coverFillPath(PathID path, GLenum coverMode)
-{
-    const auto *pathObj = mState.mPathManager->getPath(path);
-    if (!pathObj)
-        return;
-
-    ANGLE_CONTEXT_TRY(syncStateForPathOperation());
-
-    mImplementation->coverFillPath(pathObj, coverMode);
-}
-
-void Context::coverStrokePath(PathID path, GLenum coverMode)
-{
-    const auto *pathObj = mState.mPathManager->getPath(path);
-    if (!pathObj)
-        return;
-
-    ANGLE_CONTEXT_TRY(syncStateForPathOperation());
-
-    mImplementation->coverStrokePath(pathObj, coverMode);
-}
-
-void Context::stencilThenCoverFillPath(PathID path, GLenum fillMode, GLuint mask, GLenum coverMode)
-{
-    const auto *pathObj = mState.mPathManager->getPath(path);
-    if (!pathObj)
-        return;
-
-    ANGLE_CONTEXT_TRY(syncStateForPathOperation());
-
-    mImplementation->stencilThenCoverFillPath(pathObj, fillMode, mask, coverMode);
-}
-
-void Context::stencilThenCoverStrokePath(PathID path,
-                                         GLint reference,
-                                         GLuint mask,
-                                         GLenum coverMode)
-{
-    const auto *pathObj = mState.mPathManager->getPath(path);
-    if (!pathObj)
-        return;
-
-    ANGLE_CONTEXT_TRY(syncStateForPathOperation());
-
-    mImplementation->stencilThenCoverStrokePath(pathObj, reference, mask, coverMode);
-}
-
-void Context::coverFillPathInstanced(GLsizei numPaths,
-                                     GLenum pathNameType,
-                                     const void *paths,
-                                     PathID pathBase,
-                                     GLenum coverMode,
-                                     GLenum transformType,
-                                     const GLfloat *transformValues)
-{
-    const auto &pathObjects =
-        GatherPaths(*mState.mPathManager, numPaths, pathNameType, paths, pathBase);
-
-    ANGLE_CONTEXT_TRY(syncStateForPathOperation());
-
-    mImplementation->coverFillPathInstanced(pathObjects, coverMode, transformType, transformValues);
-}
-
-void Context::coverStrokePathInstanced(GLsizei numPaths,
-                                       GLenum pathNameType,
-                                       const void *paths,
-                                       PathID pathBase,
-                                       GLenum coverMode,
-                                       GLenum transformType,
-                                       const GLfloat *transformValues)
-{
-    const auto &pathObjects =
-        GatherPaths(*mState.mPathManager, numPaths, pathNameType, paths, pathBase);
-
-    // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
-    ANGLE_CONTEXT_TRY(syncStateForPathOperation());
-
-    mImplementation->coverStrokePathInstanced(pathObjects, coverMode, transformType,
-                                              transformValues);
-}
-
-void Context::stencilFillPathInstanced(GLsizei numPaths,
-                                       GLenum pathNameType,
-                                       const void *paths,
-                                       PathID pathBase,
-                                       GLenum fillMode,
-                                       GLuint mask,
-                                       GLenum transformType,
-                                       const GLfloat *transformValues)
-{
-    const auto &pathObjects =
-        GatherPaths(*mState.mPathManager, numPaths, pathNameType, paths, pathBase);
-
-    // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
-    ANGLE_CONTEXT_TRY(syncStateForPathOperation());
-
-    mImplementation->stencilFillPathInstanced(pathObjects, fillMode, mask, transformType,
-                                              transformValues);
-}
-
-void Context::stencilStrokePathInstanced(GLsizei numPaths,
-                                         GLenum pathNameType,
-                                         const void *paths,
-                                         PathID pathBase,
-                                         GLint reference,
-                                         GLuint mask,
-                                         GLenum transformType,
-                                         const GLfloat *transformValues)
-{
-    const auto &pathObjects =
-        GatherPaths(*mState.mPathManager, numPaths, pathNameType, paths, pathBase);
-
-    ANGLE_CONTEXT_TRY(syncStateForPathOperation());
-
-    mImplementation->stencilStrokePathInstanced(pathObjects, reference, mask, transformType,
-                                                transformValues);
-}
-
-void Context::stencilThenCoverFillPathInstanced(GLsizei numPaths,
-                                                GLenum pathNameType,
-                                                const void *paths,
-                                                PathID pathBase,
-                                                GLenum fillMode,
-                                                GLuint mask,
-                                                GLenum coverMode,
-                                                GLenum transformType,
-                                                const GLfloat *transformValues)
-{
-    const auto &pathObjects =
-        GatherPaths(*mState.mPathManager, numPaths, pathNameType, paths, pathBase);
-
-    ANGLE_CONTEXT_TRY(syncStateForPathOperation());
-
-    mImplementation->stencilThenCoverFillPathInstanced(pathObjects, coverMode, fillMode, mask,
-                                                       transformType, transformValues);
-}
-
-void Context::stencilThenCoverStrokePathInstanced(GLsizei numPaths,
-                                                  GLenum pathNameType,
-                                                  const void *paths,
-                                                  PathID pathBase,
-                                                  GLint reference,
-                                                  GLuint mask,
-                                                  GLenum coverMode,
-                                                  GLenum transformType,
-                                                  const GLfloat *transformValues)
-{
-    const auto &pathObjects =
-        GatherPaths(*mState.mPathManager, numPaths, pathNameType, paths, pathBase);
-
-    ANGLE_CONTEXT_TRY(syncStateForPathOperation());
-
-    mImplementation->stencilThenCoverStrokePathInstanced(pathObjects, coverMode, reference, mask,
-                                                         transformType, transformValues);
-}
-
-void Context::bindFragmentInputLocation(ShaderProgramID program, GLint location, const GLchar *name)
-{
-    auto *programObject = getProgramResolveLink(program);
-
-    programObject->bindFragmentInputLocation(location, name);
-}
-
-void Context::programPathFragmentInputGen(ShaderProgramID program,
-                                          GLint location,
-                                          GLenum genMode,
-                                          GLint components,
-                                          const GLfloat *coeffs)
-{
-    auto *programObject = getProgramResolveLink(program);
-
-    programObject->pathFragmentInputGen(location, genMode, components, coeffs);
-}
-
 GLuint Context::getProgramResourceIndex(ShaderProgramID program,
                                         GLenum programInterface,
                                         const GLchar *name)
@@ -3379,6 +3040,7 @@
     ASSERT(transformFeedback != nullptr);
     ASSERT(!transformFeedback->isPaused());
 
+    // TODO: http://anglebug.com/3570: Handle PPOs
     ANGLE_CONTEXT_TRY(transformFeedback->begin(this, primitiveMode, mState.getProgram()));
     mStateCache.onActiveTransformFeedbackChange(this);
 }
@@ -3543,7 +3205,8 @@
     supportedExtensions.loseContextCHROMIUM = true;
 
     // The ASTC texture extensions have dependency requirements.
-    if (supportedExtensions.textureCompressionASTCHDRKHR)
+    if (supportedExtensions.textureCompressionASTCHDRKHR ||
+        supportedExtensions.textureCompressionSliced3dASTCKHR)
     {
         // GL_KHR_texture_compression_astc_hdr cannot be exposed without also exposing
         // GL_KHR_texture_compression_astc_ldr
@@ -3585,6 +3248,16 @@
         mState.mCaps.maxSmoothLineWidth            = 1.0f;
     }
 
+    // If we're capturing application calls for replay, don't expose any binary formats to prevent
+    // traces from trying to use cached results
+    if (getFrameCapture()->enabled())
+    {
+        INFO() << "Limiting binary format support count to zero while FrameCapture enabled"
+               << std::endl;
+        mState.mCaps.shaderBinaryFormats.clear();
+        mState.mCaps.programBinaryFormats.clear();
+    }
+
 #if 0
 // This logging can generate a lot of spam in test suites that create many contexts
 #    define ANGLE_LOG_LIMITED_CAP(cap, limit)                                               \
@@ -4405,9 +4078,11 @@
 {
     ANGLE_CONTEXT_TRY(syncStateForTexImage());
 
+    gl::Buffer *unpackBuffer = mState.getTargetBuffer(gl::BufferBinding::PixelUnpack);
+
     Extents size(width, height, 1);
     Texture *texture = getTextureByTarget(target);
-    ANGLE_CONTEXT_TRY(texture->setImage(this, mState.getUnpackState(), target, level,
+    ANGLE_CONTEXT_TRY(texture->setImage(this, mState.getUnpackState(), unpackBuffer, target, level,
                                         internalformat, size, format, type,
                                         static_cast<const uint8_t *>(pixels)));
 }
@@ -4439,9 +4114,11 @@
 {
     ANGLE_CONTEXT_TRY(syncStateForTexImage());
 
+    gl::Buffer *unpackBuffer = mState.getTargetBuffer(gl::BufferBinding::PixelUnpack);
+
     Extents size(width, height, depth);
     Texture *texture = getTextureByTarget(target);
-    ANGLE_CONTEXT_TRY(texture->setImage(this, mState.getUnpackState(), target, level,
+    ANGLE_CONTEXT_TRY(texture->setImage(this, mState.getUnpackState(), unpackBuffer, target, level,
                                         internalformat, size, format, type,
                                         static_cast<const uint8_t *>(pixels)));
 }
@@ -4901,19 +4578,15 @@
     return syncState(mBlitDirtyBits, mBlitDirtyObjects);
 }
 
-angle::Result Context::syncStateForPathOperation()
-{
-    ANGLE_TRY(syncDirtyObjects(mPathOperationDirtyObjects));
-
-    // TODO(svaisanen@nvidia.com): maybe sync only state required for path rendering?
-    ANGLE_TRY(syncDirtyBits());
-
-    return angle::Result::Continue;
-}
-
 void Context::activeShaderProgram(ProgramPipelineID pipeline, ShaderProgramID program)
 {
-    UNIMPLEMENTED();
+    Program *shaderProgram = getProgramNoResolveLink(program);
+    ProgramPipeline *programPipeline =
+        mState.mProgramPipelineManager->checkProgramPipelineAllocation(mImplementation.get(),
+                                                                       pipeline);
+    ASSERT(programPipeline);
+
+    programPipeline->activeShaderProgram(shaderProgram);
 }
 
 void Context::activeTexture(GLenum texture)
@@ -5556,7 +5229,7 @@
     Program *programObject = mState.mShaderProgramManager->getProgram(program);
     Shader *shaderObject   = mState.mShaderProgramManager->getShader(shader);
     ASSERT(programObject && shaderObject);
-    programObject->attachShader(shaderObject);
+    programObject->attachShader(this, shaderObject);
 }
 
 void Context::copyBufferSubData(BufferBinding readTarget,
@@ -6518,7 +6191,12 @@
 
 void Context::getProgramPipelineiv(ProgramPipelineID pipeline, GLenum pname, GLint *params)
 {
-    UNIMPLEMENTED();
+    ProgramPipeline *programPipeline = nullptr;
+    if (!mContextLost)
+    {
+        programPipeline = getProgramPipeline(pipeline);
+    }
+    QueryProgramPipelineiv(this, programPipeline, pname, params);
 }
 
 MemoryObject *Context::getMemoryObject(MemoryObjectID handle) const
@@ -6538,7 +6216,7 @@
 {
     Program *programObject = getProgramResolveLink(program);
     ASSERT(programObject);
-    programObject->getInfoLog(bufsize, length, infolog);
+    programObject->getExecutable().getInfoLog(bufsize, length, infolog);
 }
 
 void Context::getProgramPipelineInfoLog(ProgramPipelineID pipeline,
@@ -6546,7 +6224,16 @@
                                         GLsizei *length,
                                         GLchar *infoLog)
 {
-    UNIMPLEMENTED();
+    ProgramPipeline *programPipeline = getProgramPipeline(pipeline);
+    if (programPipeline)
+    {
+        programPipeline->getExecutable().getInfoLog(bufSize, length, infoLog);
+    }
+    else
+    {
+        *length  = 0;
+        *infoLog = '\0';
+    }
 }
 
 void Context::getShaderiv(ShaderProgramID shader, GLenum pname, GLint *params)
@@ -6854,15 +6541,30 @@
     UNIMPLEMENTED();
 }
 
+Program *Context::getActiveLinkedProgram() const
+{
+    Program *program = mState.getLinkedProgram(this);
+    if (!program)
+    {
+        ProgramPipeline *programPipelineObject = mState.getProgramPipeline();
+        if (programPipelineObject)
+        {
+            program = programPipelineObject->getLinkedActiveShaderProgram(this);
+        }
+    }
+
+    return program;
+}
+
 void Context::uniform1f(UniformLocation location, GLfloat x)
 {
-    Program *program = mState.getProgram();
+    Program *program = getActiveLinkedProgram();
     program->setUniform1fv(location, 1, &x);
 }
 
 void Context::uniform1fv(UniformLocation location, GLsizei count, const GLfloat *v)
 {
-    Program *program = mState.getProgram();
+    Program *program = getActiveLinkedProgram();
     program->setUniform1fv(location, count, v);
 }
 
@@ -6882,89 +6584,91 @@
 
 void Context::uniform1i(UniformLocation location, GLint x)
 {
-    setUniform1iImpl(mState.getProgram(), location, 1, &x);
+    Program *program = getActiveLinkedProgram();
+    setUniform1iImpl(program, location, 1, &x);
 }
 
 void Context::uniform1iv(UniformLocation location, GLsizei count, const GLint *v)
 {
-    setUniform1iImpl(mState.getProgram(), location, count, v);
+    Program *program = getActiveLinkedProgram();
+    setUniform1iImpl(program, location, count, v);
 }
 
 void Context::uniform2f(UniformLocation location, GLfloat x, GLfloat y)
 {
     GLfloat xy[2]    = {x, y};
-    Program *program = mState.getProgram();
+    Program *program = getActiveLinkedProgram();
     program->setUniform2fv(location, 1, xy);
 }
 
 void Context::uniform2fv(UniformLocation location, GLsizei count, const GLfloat *v)
 {
-    Program *program = mState.getProgram();
+    Program *program = getActiveLinkedProgram();
     program->setUniform2fv(location, count, v);
 }
 
 void Context::uniform2i(UniformLocation location, GLint x, GLint y)
 {
     GLint xy[2]      = {x, y};
-    Program *program = mState.getProgram();
+    Program *program = getActiveLinkedProgram();
     program->setUniform2iv(location, 1, xy);
 }
 
 void Context::uniform2iv(UniformLocation location, GLsizei count, const GLint *v)
 {
-    Program *program = mState.getProgram();
+    Program *program = getActiveLinkedProgram();
     program->setUniform2iv(location, count, v);
 }
 
 void Context::uniform3f(UniformLocation location, GLfloat x, GLfloat y, GLfloat z)
 {
     GLfloat xyz[3]   = {x, y, z};
-    Program *program = mState.getProgram();
+    Program *program = getActiveLinkedProgram();
     program->setUniform3fv(location, 1, xyz);
 }
 
 void Context::uniform3fv(UniformLocation location, GLsizei count, const GLfloat *v)
 {
-    Program *program = mState.getProgram();
+    Program *program = getActiveLinkedProgram();
     program->setUniform3fv(location, count, v);
 }
 
 void Context::uniform3i(UniformLocation location, GLint x, GLint y, GLint z)
 {
     GLint xyz[3]     = {x, y, z};
-    Program *program = mState.getProgram();
+    Program *program = getActiveLinkedProgram();
     program->setUniform3iv(location, 1, xyz);
 }
 
 void Context::uniform3iv(UniformLocation location, GLsizei count, const GLint *v)
 {
-    Program *program = mState.getProgram();
+    Program *program = getActiveLinkedProgram();
     program->setUniform3iv(location, count, v);
 }
 
 void Context::uniform4f(UniformLocation location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
 {
     GLfloat xyzw[4]  = {x, y, z, w};
-    Program *program = mState.getProgram();
+    Program *program = getActiveLinkedProgram();
     program->setUniform4fv(location, 1, xyzw);
 }
 
 void Context::uniform4fv(UniformLocation location, GLsizei count, const GLfloat *v)
 {
-    Program *program = mState.getProgram();
+    Program *program = getActiveLinkedProgram();
     program->setUniform4fv(location, count, v);
 }
 
 void Context::uniform4i(UniformLocation location, GLint x, GLint y, GLint z, GLint w)
 {
     GLint xyzw[4]    = {x, y, z, w};
-    Program *program = mState.getProgram();
+    Program *program = getActiveLinkedProgram();
     program->setUniform4iv(location, 1, xyzw);
 }
 
 void Context::uniform4iv(UniformLocation location, GLsizei count, const GLint *v)
 {
-    Program *program = mState.getProgram();
+    Program *program = getActiveLinkedProgram();
     program->setUniform4iv(location, count, v);
 }
 
@@ -6973,7 +6677,7 @@
                                GLboolean transpose,
                                const GLfloat *value)
 {
-    Program *program = mState.getProgram();
+    Program *program = getActiveLinkedProgram();
     program->setUniformMatrix2fv(location, count, transpose, value);
 }
 
@@ -6982,7 +6686,7 @@
                                GLboolean transpose,
                                const GLfloat *value)
 {
-    Program *program = mState.getProgram();
+    Program *program = getActiveLinkedProgram();
     program->setUniformMatrix3fv(location, count, transpose, value);
 }
 
@@ -6991,7 +6695,7 @@
                                GLboolean transpose,
                                const GLfloat *value)
 {
-    Program *program = mState.getProgram();
+    Program *program = getActiveLinkedProgram();
     program->setUniformMatrix4fv(location, count, transpose, value);
 }
 
@@ -7004,7 +6708,12 @@
 
 void Context::validateProgramPipeline(ProgramPipelineID pipeline)
 {
-    UNIMPLEMENTED();
+    ProgramPipeline *programPipeline =
+        mState.mProgramPipelineManager->checkProgramPipelineAllocation(mImplementation.get(),
+                                                                       pipeline);
+    ASSERT(programPipeline);
+
+    programPipeline->validate(this);
 }
 
 void Context::getProgramBinary(ShaderProgramID program,
@@ -7033,51 +6742,51 @@
 
 void Context::uniform1ui(UniformLocation location, GLuint v0)
 {
-    Program *program = mState.getProgram();
+    Program *program = getActiveLinkedProgram();
     program->setUniform1uiv(location, 1, &v0);
 }
 
 void Context::uniform2ui(UniformLocation location, GLuint v0, GLuint v1)
 {
-    Program *program  = mState.getProgram();
+    Program *program  = getActiveLinkedProgram();
     const GLuint xy[] = {v0, v1};
     program->setUniform2uiv(location, 1, xy);
 }
 
 void Context::uniform3ui(UniformLocation location, GLuint v0, GLuint v1, GLuint v2)
 {
-    Program *program   = mState.getProgram();
+    Program *program   = getActiveLinkedProgram();
     const GLuint xyz[] = {v0, v1, v2};
     program->setUniform3uiv(location, 1, xyz);
 }
 
 void Context::uniform4ui(UniformLocation location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
 {
-    Program *program    = mState.getProgram();
+    Program *program    = getActiveLinkedProgram();
     const GLuint xyzw[] = {v0, v1, v2, v3};
     program->setUniform4uiv(location, 1, xyzw);
 }
 
 void Context::uniform1uiv(UniformLocation location, GLsizei count, const GLuint *value)
 {
-    Program *program = mState.getProgram();
+    Program *program = getActiveLinkedProgram();
     program->setUniform1uiv(location, count, value);
 }
 void Context::uniform2uiv(UniformLocation location, GLsizei count, const GLuint *value)
 {
-    Program *program = mState.getProgram();
+    Program *program = getActiveLinkedProgram();
     program->setUniform2uiv(location, count, value);
 }
 
 void Context::uniform3uiv(UniformLocation location, GLsizei count, const GLuint *value)
 {
-    Program *program = mState.getProgram();
+    Program *program = getActiveLinkedProgram();
     program->setUniform3uiv(location, count, value);
 }
 
 void Context::uniform4uiv(UniformLocation location, GLsizei count, const GLuint *value)
 {
-    Program *program = mState.getProgram();
+    Program *program = getActiveLinkedProgram();
     program->setUniform4uiv(location, count, value);
 }
 
@@ -7124,7 +6833,7 @@
                                  GLboolean transpose,
                                  const GLfloat *value)
 {
-    Program *program = mState.getProgram();
+    Program *program = getActiveLinkedProgram();
     program->setUniformMatrix2x3fv(location, count, transpose, value);
 }
 
@@ -7133,7 +6842,7 @@
                                  GLboolean transpose,
                                  const GLfloat *value)
 {
-    Program *program = mState.getProgram();
+    Program *program = getActiveLinkedProgram();
     program->setUniformMatrix3x2fv(location, count, transpose, value);
 }
 
@@ -7142,7 +6851,7 @@
                                  GLboolean transpose,
                                  const GLfloat *value)
 {
-    Program *program = mState.getProgram();
+    Program *program = getActiveLinkedProgram();
     program->setUniformMatrix2x4fv(location, count, transpose, value);
 }
 
@@ -7151,7 +6860,7 @@
                                  GLboolean transpose,
                                  const GLfloat *value)
 {
-    Program *program = mState.getProgram();
+    Program *program = getActiveLinkedProgram();
     program->setUniformMatrix4x2fv(location, count, transpose, value);
 }
 
@@ -7160,7 +6869,7 @@
                                  GLboolean transpose,
                                  const GLfloat *value)
 {
-    Program *program = mState.getProgram();
+    Program *program = getActiveLinkedProgram();
     program->setUniformMatrix3x4fv(location, count, transpose, value);
 }
 
@@ -7169,7 +6878,7 @@
                                  GLboolean transpose,
                                  const GLfloat *value)
 {
-    Program *program = mState.getProgram();
+    Program *program = getActiveLinkedProgram();
     program->setUniformMatrix4x3fv(location, count, transpose, value);
 }
 
@@ -7892,7 +7601,12 @@
         return GL_FALSE;
     }
 
-    return ConvertToGLBoolean(getProgramPipeline(pipeline));
+    if (getProgramPipeline(pipeline))
+    {
+        return GL_TRUE;
+    }
+
+    return GL_FALSE;
 }
 
 void Context::finishFenceNV(FenceNVID fence)
@@ -8074,16 +7788,18 @@
     }
 }
 
-void Context::memoryObjectParameteriv(MemoryObjectID memoryObject,
-                                      GLenum pname,
-                                      const GLint *params)
+void Context::memoryObjectParameteriv(MemoryObjectID memory, GLenum pname, const GLint *params)
 {
-    UNIMPLEMENTED();
+    MemoryObject *memoryObject = getMemoryObject(memory);
+    ASSERT(memoryObject);
+    ANGLE_CONTEXT_TRY(SetMemoryObjectParameteriv(this, memoryObject, pname, params));
 }
 
-void Context::getMemoryObjectParameteriv(MemoryObjectID memoryObject, GLenum pname, GLint *params)
+void Context::getMemoryObjectParameteriv(MemoryObjectID memory, GLenum pname, GLint *params)
 {
-    UNIMPLEMENTED();
+    const MemoryObject *memoryObject = getMemoryObject(memory);
+    ASSERT(memoryObject);
+    QueryMemoryObjectParameteriv(memoryObject, pname, params);
 }
 
 void Context::texStorageMem2D(TextureType target,
@@ -8542,6 +8258,25 @@
         mStateCache.onProgramExecutableChange(this);
     }
 
+    // TODO(http://anglebug.com/4559): Use the Subject/Observer pattern for
+    // Programs in PPOs so we can remove this.
+    // Need to mark any PPOs that this Program is bound to as dirty
+    bool foundPipeline = false;
+    for (ResourceMap<ProgramPipeline, ProgramPipelineID>::Iterator ppoIterator =
+             mState.mProgramPipelineManager->begin();
+         ppoIterator != mState.mProgramPipelineManager->end(); ++ppoIterator)
+    {
+        ProgramPipeline *pipeline = ppoIterator->second;
+        pipeline->setDirtyBit(ProgramPipeline::DirtyBitType::DIRTY_BIT_PROGRAM_STAGE);
+        foundPipeline = true;
+    }
+    // Also need to make sure the PPO dirty bits get handled by marking the PPO
+    // objects dirty.
+    if (foundPipeline)
+    {
+        mState.mDirtyObjects.set(State::DIRTY_OBJECT_PROGRAM_PIPELINE);
+    }
+
     return angle::Result::Continue;
 }
 
@@ -8746,7 +8481,7 @@
     bool isGLES1         = context->isGLES1();
     const State &glState = context->getState();
 
-    if (!isGLES1 && !glState.getProgram())
+    if (!isGLES1 && !glState.getProgramExecutable())
     {
         mCachedActiveBufferedAttribsMask = AttributesMask();
         mCachedActiveClientAttribsMask   = AttributesMask();
@@ -8754,8 +8489,9 @@
         return;
     }
 
-    AttributesMask activeAttribs = isGLES1 ? glState.gles1().getActiveAttributesMask()
-                                           : glState.getProgram()->getActiveAttribLocationsMask();
+    AttributesMask activeAttribs =
+        isGLES1 ? glState.gles1().getActiveAttributesMask()
+                : glState.getProgramExecutable()->getActiveAttribLocationsMask();
 
     const VertexArray *vao = glState.getVertexArray();
     ASSERT(vao);
@@ -8795,7 +8531,7 @@
 
         const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
         ASSERT(context->isGLES1() ||
-               context->getState().getProgram()->isAttribLocationActive(attributeIndex));
+               context->getState().getProgramExecutable()->isAttribLocationActive(attributeIndex));
 
         GLint64 limit = attrib.getCachedElementLimit();
         if (binding.getDivisor() > 0)
@@ -8990,13 +8726,14 @@
         return;
     }
 
-    if (!program || !program->hasLinkedShaderStage(ShaderType::Geometry))
+    const ProgramExecutable *programExecutable = context->getState().getProgramExecutable();
+    if (!programExecutable || !programExecutable->hasLinkedShaderStage(ShaderType::Geometry))
     {
         mCachedValidDrawModes = kValidBasicDrawModes;
         return;
     }
 
-    ASSERT(program && program->hasLinkedShaderStage(ShaderType::Geometry));
+    ASSERT(programExecutable->hasLinkedShaderStage(ShaderType::Geometry));
     PrimitiveMode gsMode = program->getGeometryShaderInputPrimitiveType();
 
     bool pointsOK  = gsMode == PrimitiveMode::Points;
diff --git a/src/libANGLE/Context.h b/src/libANGLE/Context.h
index a7d0c6e..260fc9c 100644
--- a/src/libANGLE/Context.h
+++ b/src/libANGLE/Context.h
@@ -344,7 +344,7 @@
             const egl::ClientExtensions &clientExtensions);
 
     // Use for debugging.
-    int id() const { return mState.mID; }
+    ContextID id() const { return mState.getContextID(); }
 
     egl::Error onDestroy(const egl::Display *display);
     ~Context() override;
@@ -373,9 +373,6 @@
     void deleteMemoryObject(MemoryObjectID memoryObject);
     void deleteSemaphore(SemaphoreID semaphore);
 
-    // CHROMIUM_path_rendering
-    bool isPathGenerated(PathID path) const;
-
     void bindReadFramebuffer(FramebufferID framebufferHandle);
     void bindDrawFramebuffer(FramebufferID framebufferHandle);
 
@@ -602,6 +599,8 @@
 
     void onPostSwap() const;
 
+    Program *getActiveLinkedProgram() const;
+
   private:
     void initialize();
 
@@ -618,7 +617,6 @@
     angle::Result syncStateForReadPixels();
     angle::Result syncStateForTexImage();
     angle::Result syncStateForBlit();
-    angle::Result syncStateForPathOperation();
 
     VertexArray *checkVertexArrayAllocation(VertexArrayID vertexArrayHandle);
     TransformFeedback *checkTransformFeedbackAllocation(TransformFeedbackID transformFeedback);
@@ -634,9 +632,6 @@
     void detachSampler(SamplerID sampler);
     void detachProgramPipeline(ProgramPipelineID pipeline);
 
-    // A small helper method to facilitate using the ANGLE_CONTEXT_TRY macro.
-    void tryGenPaths(GLsizei range, PathID *createdOut);
-
     egl::Error setDefaultFramebuffer(egl::Surface *drawSurface, egl::Surface *readSurface);
     egl::Error unsetDefaultFramebuffer();
 
@@ -723,7 +718,6 @@
     MemoryProgramCache *mMemoryProgramCache;
 
     State::DirtyObjects mDrawDirtyObjects;
-    State::DirtyObjects mPathOperationDirtyObjects;
 
     StateCache mStateCache;
 
diff --git a/src/libANGLE/Context.inl.h b/src/libANGLE/Context.inl.h
index 43fa3fe..186d727 100644
--- a/src/libANGLE/Context.inl.h
+++ b/src/libANGLE/Context.inl.h
@@ -59,6 +59,9 @@
 }
 
 // Return true if the draw is a no-op, else return false.
+//  If there is no active program for the vertex or fragment shader stages, the results of vertex
+//  and fragment shader execution will respectively be undefined. However, this is not
+//  an error. ANGLE will treat this as a no-op.
 //  A no-op draw occurs if the count of vertices is less than the minimum required to
 //  have a valid primitive for this mode (0 for points, 0-1 for lines, 0-2 for tris).
 ANGLE_INLINE bool Context::noopDraw(PrimitiveMode mode, GLsizei count)
diff --git a/src/libANGLE/Context_gles_ext_autogen.h b/src/libANGLE/Context_gles_ext_autogen.h
index dbb09e2..0237824 100644
--- a/src/libANGLE/Context_gles_ext_autogen.h
+++ b/src/libANGLE/Context_gles_ext_autogen.h
@@ -227,53 +227,9 @@
                         GLboolean unpackUnmultiplyAlpha);                                          \
     /* GL_CHROMIUM_framebuffer_mixed_samples */                                                    \
     void coverageModulation(GLenum components);                                                    \
-    void matrixLoadf(GLenum matrixMode, const GLfloat *matrix);                                    \
-    void matrixLoadIdentity(GLenum matrixMode);                                                    \
     /* GL_CHROMIUM_lose_context */                                                                 \
     void loseContext(GraphicsResetStatus currentPacked, GraphicsResetStatus otherPacked);          \
     /* GL_CHROMIUM_path_rendering */                                                               \
-    GLuint genPaths(GLsizei range);                                                                \
-    void deletePaths(PathID firstPacked, GLsizei range);                                           \
-    GLboolean isPath(PathID pathPacked) const;                                                     \
-    void pathCommands(PathID pathPacked, GLsizei numCommands, const GLubyte *commands,             \
-                      GLsizei numCoords, GLenum coordType, const void *coords);                    \
-    void pathParameterf(PathID pathPacked, GLenum pname, GLfloat value);                           \
-    void pathParameteri(PathID pathPacked, GLenum pname, GLint value);                             \
-    void getPathParameterfv(PathID pathPacked, GLenum pname, GLfloat *value);                      \
-    void getPathParameteriv(PathID pathPacked, GLenum pname, GLint *value);                        \
-    void pathStencilFunc(GLenum func, GLint ref, GLuint mask);                                     \
-    void stencilFillPath(PathID pathPacked, GLenum fillMode, GLuint mask);                         \
-    void stencilStrokePath(PathID pathPacked, GLint reference, GLuint mask);                       \
-    void coverFillPath(PathID pathPacked, GLenum coverMode);                                       \
-    void coverStrokePath(PathID pathPacked, GLenum coverMode);                                     \
-    void stencilThenCoverFillPath(PathID pathPacked, GLenum fillMode, GLuint mask,                 \
-                                  GLenum coverMode);                                               \
-    void stencilThenCoverStrokePath(PathID pathPacked, GLint reference, GLuint mask,               \
-                                    GLenum coverMode);                                             \
-    void coverFillPathInstanced(GLsizei numPath, GLenum pathNameType, const void *paths,           \
-                                PathID pathBasePacked, GLenum coverMode, GLenum transformType,     \
-                                const GLfloat *transformValues);                                   \
-    void coverStrokePathInstanced(GLsizei numPath, GLenum pathNameType, const void *paths,         \
-                                  PathID pathBasePacked, GLenum coverMode, GLenum transformType,   \
-                                  const GLfloat *transformValues);                                 \
-    void stencilStrokePathInstanced(GLsizei numPath, GLenum pathNameType, const void *paths,       \
-                                    PathID pathBasePacked, GLint reference, GLuint mask,           \
-                                    GLenum transformType, const GLfloat *transformValues);         \
-    void stencilFillPathInstanced(GLsizei numPaths, GLenum pathNameType, const void *paths,        \
-                                  PathID pathBasePacked, GLenum fillMode, GLuint mask,             \
-                                  GLenum transformType, const GLfloat *transformValues);           \
-    void stencilThenCoverFillPathInstanced(GLsizei numPaths, GLenum pathNameType,                  \
-                                           const void *paths, PathID pathBasePacked,               \
-                                           GLenum fillMode, GLuint mask, GLenum coverMode,         \
-                                           GLenum transformType, const GLfloat *transformValues);  \
-    void stencilThenCoverStrokePathInstanced(                                                      \
-        GLsizei numPaths, GLenum pathNameType, const void *paths, PathID pathBasePacked,           \
-        GLint reference, GLuint mask, GLenum coverMode, GLenum transformType,                      \
-        const GLfloat *transformValues);                                                           \
-    void bindFragmentInputLocation(ShaderProgramID programsPacked, GLint location,                 \
-                                   const GLchar *name);                                            \
-    void programPathFragmentInputGen(ShaderProgramID programPacked, GLint location,                \
-                                     GLenum genMode, GLint components, const GLfloat *coeffs);     \
                                                                                                    \
     /* GLES2+ Extensions */                                                                        \
                                                                                                    \
@@ -324,6 +280,7 @@
     GLint getFragDataIndex(ShaderProgramID programPacked, const GLchar *name);                     \
     GLint getProgramResourceLocationIndex(ShaderProgramID programPacked, GLenum programInterface,  \
                                           const GLchar *name);                                     \
+    /* GL_EXT_compressed_ETC1_RGB8_sub_texture */                                                  \
     /* GL_EXT_debug_marker */                                                                      \
     void insertEventMarker(GLsizei length, const GLchar *marker);                                  \
     void popGroupMarker();                                                                         \
@@ -402,6 +359,7 @@
     /* GL_EXT_texture_compression_s3tc_srgb */                                                     \
     /* GL_EXT_texture_filter_anisotropic */                                                        \
     /* GL_EXT_texture_format_BGRA8888 */                                                           \
+    /* GL_EXT_texture_sRGB_R8 */                                                                   \
     /* GL_EXT_texture_storage */                                                                   \
     void texStorage1D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);        \
     /* GL_KHR_debug */                                                                             \
diff --git a/src/libANGLE/Display.cpp b/src/libANGLE/Display.cpp
index f3b6ebf..b10711c 100644
--- a/src/libANGLE/Display.cpp
+++ b/src/libANGLE/Display.cpp
@@ -655,6 +655,14 @@
     ASSERT(mImplementation != nullptr);
     mImplementation->setBlobCache(&mBlobCache);
 
+    // Enable shader caching if debug layers are turned on. This allows us to test that shaders are
+    // properly saved & restored on all platforms. The cache won't allocate space until it's used
+    // and will be ignored entirely if the application / system sets it's own cache functions.
+    if (rx::ShouldUseDebugLayers(mAttributeMap))
+    {
+        mBlobCache.resize(1024 * 1024);
+    }
+
     gl::InitializeDebugAnnotations(&mAnnotator);
 
     gl::InitializeDebugMutexIfNeeded();
diff --git a/src/libANGLE/ErrorStrings.h b/src/libANGLE/ErrorStrings.h
index de01251..795e71b 100644
--- a/src/libANGLE/ErrorStrings.h
+++ b/src/libANGLE/ErrorStrings.h
@@ -141,6 +141,7 @@
 MSG kGLES1Only = "GLES1-only function.";
 MSG kImageSizeMustBeZero = "imageSize must be 0 if no texture data is provided.";
 MSG kImageSizeTooSmall = "imageSize is too small.";
+MSG kImmutableMemoryObject = "The memory object is immutable.";
 MSG kImmutableTextureBound = "The value of TEXTURE_IMMUTABLE_FORMAT for the texture currently bound to target on the active texture unit is true.";
 MSG kIncompatibleDrawModeAgainstGeometryShader = "Primitive mode is incompatible with the input primitive type of the geometry shader.";
 MSG kIndexExceedsActiveUniformBlockCount = "Index exceeds active uniform block count.";
@@ -240,31 +241,14 @@
 MSG kInvalidMaterialParameter = "Invalid material parameter.";
 MSG kInvalidMatrixMode = "Invalid matrix mode.";
 MSG kInvalidMemoryBarrierBit = "Invalid memory barrier bit.";
+MSG kInvalidMemoryObject = "Invalid memory object.";
+MSG kInvalidMemoryObjectParameter = "Invalid memory object parameter.";
 MSG kInvalidMipLevel = "Level of detail outside of range.";
 MSG kInvalidMipLevels = "Invalid level count.";
 MSG kInvalidMultisampledFramebufferOperation = "Invalid operation on multisampled framebuffer";
 MSG kInvalidMultitextureUnit = "Specified unit must be in [GL_TEXTURE0, GL_TEXTURE0 + GL_MAX_TEXTURE_UNITS)";
 MSG kInvalidName = "Invalid name.";
 MSG kInvalidNameCharacters = "Name contains invalid characters.";
-MSG kInvalidPathCoefficientsArray = "No coefficients array given.";
-MSG kInvalidPathCommand = "Invalid command.";
-MSG kInvalidPathCommandsArray = "No commands array given.";
-MSG kInvalidPathComponents = "Unexpected number of components";
-MSG kInvalidPathCoordinateType = "Invalid coordinate type.";
-MSG kInvalidPathEndCaps = "Invalid end caps.";
-MSG kInvalidPathGenMode = "Invalid gen mode.";
-MSG kInvalidPathJoinStyle = "Invalid join style.";
-MSG kInvalidPathMatrix = "Invalid matrix.";
-MSG kInvalidPathMiterLimit = "Invalid miter limit.";
-MSG kInvalidPathNameArray = "No path name array.";
-MSG kInvalidPathNameType = "Invalid path name type.";
-MSG kInvalidPathNumCommands = "Invalid number of commands.";
-MSG kInvalidPathNumCoords = "Invalid number of coordinates.";
-MSG kInvalidPathNumCoordsArray = "No coordinate array given.";
-MSG kInvalidPathNumPaths = "Invalid (negative) numPaths.";
-MSG kInvalidPathParameter = "Invalid path parameter.";
-MSG kInvalidPathStrokeWidth = "Invalid stroke width.";
-MSG kInvalidPathValueArray = "No value array.";
 MSG kInvalidPname = "Invalid pname.";
 MSG kInvalidPointerQuery = "Invalid pointer query.";
 MSG kInvalidPointParameter = "Invalid point parameter.";
@@ -275,6 +259,7 @@
 MSG kInvalidProgramBinaryFormat = "Program binary format is not valid.";
 MSG kInvalidProgramInterface = "Invalid program interface.";
 MSG kInvalidProgramName = "Program object expected.";
+MSG kInvalidProgramPipelineName = "name is not a valid program pipeline.";
 MSG kInvalidProgramResourceIndex = "Invalid program resource index.";
 MSG kInvalidProgramResourceProperty = "Invalid program resource property.";
 MSG kInvalidProjectionMatrix = "Invalid projection matrix. Left/right, top/bottom, near/far intervals cannot be zero, and near/far cannot be less than zero.";
@@ -395,11 +380,9 @@
 MSG kNoActiveProgramWithComputeShader = "No active program for the compute shader stage.";
 MSG kNoDefinedClearConversion = "No defined conversion between clear value and attachment format.";
 MSG kNonPositiveDrawTextureDimension = "Both width and height argument of drawn texture must be positive.";
-MSG kNoPathOrNoPathData = "No such path or path has no data.";
 MSG kNoProgramBinaryFormats = "No program binary formats supported.";
 MSG kNoReadFramebuffer = "No active read framebuffer.";
 MSG kNoSampleAlphaToCoveragesLimitation = "Current renderer doesn't support alpha-to-coverage.";
-MSG kNoSuchPath = "No such path object.";
 MSG kNoTransformArray = "No transform array given.";
 MSG kNoTransformFeedbackOutputVariables = "The active program has specified no output variables to record.";
 MSG kNoZeroDivisor = "At least one enabled attribute must have a divisor of zero.";
@@ -499,6 +482,11 @@
 MSG kWebglBindAttribLocationReservedPrefix = "Attributes that begin with 'webgl_', or '_webgl_' are not allowed.";
 MSG kWebglNameLengthLimitExceeded = "Location name lengths must not be greater than 256 characters.";
 MSG kZeroBoundToTarget = "Zero is bound to target.";
+MSG kUnrecognizedShaderStageBit = "Unrecognized shader stage bit.";
+MSG kProgramNotSeparable = "Program object was not linked with its PROGRAM_SEPARABLE status set.";
+MSG kProgramPipelineDoesNotExist = "Program pipeline does not exist.";
+MSG kNotAllStagesOfSeparableProgramUsed = "A program object is active for at least one, but not all of the shader stages that were present when the program was linked.";
+
 // clang-format on
 
 #undef MSG
diff --git a/src/libANGLE/FrameCapture.cpp b/src/libANGLE/FrameCapture.cpp
index 46303df..c99be3b 100644
--- a/src/libANGLE/FrameCapture.cpp
+++ b/src/libANGLE/FrameCapture.cpp
@@ -171,10 +171,10 @@
 
 struct FmtCapturePrefix
 {
-    FmtCapturePrefix(int contextIdIn, const std::string &captureLabelIn)
+    FmtCapturePrefix(gl::ContextID contextIdIn, const std::string &captureLabelIn)
         : contextId(contextIdIn), captureLabel(captureLabelIn)
     {}
-    int contextId;
+    gl::ContextID contextId;
     const std::string &captureLabel;
 };
 
@@ -188,26 +188,26 @@
     {
         os << fmt.captureLabel;
     }
-    os << "_capture_context" << fmt.contextId;
+    os << "_capture_context" << static_cast<int>(fmt.contextId);
     return os;
 }
 
 struct FmtReplayFunction
 {
-    FmtReplayFunction(int contextIdIn, uint32_t frameIndexIn)
+    FmtReplayFunction(gl::ContextID contextIdIn, uint32_t frameIndexIn)
         : contextId(contextIdIn), frameIndex(frameIndexIn)
     {}
-    int contextId;
+    gl::ContextID contextId;
     uint32_t frameIndex;
 };
 
 std::ostream &operator<<(std::ostream &os, const FmtReplayFunction &fmt)
 {
-    os << "ReplayContext" << fmt.contextId << "Frame" << fmt.frameIndex << "()";
+    os << "ReplayContext" << static_cast<int>(fmt.contextId) << "Frame" << fmt.frameIndex << "()";
     return os;
 }
 
-std::string GetCaptureFileName(int contextId,
+std::string GetCaptureFileName(gl::ContextID contextId,
                                const std::string &captureLabel,
                                uint32_t frameIndex,
                                const char *suffix)
@@ -219,7 +219,7 @@
 }
 
 std::string GetCaptureFilePath(const std::string &outDir,
-                               int contextId,
+                               gl::ContextID contextId,
                                const std::string &captureLabel,
                                uint32_t frameIndex,
                                const char *suffix)
@@ -299,6 +299,30 @@
     }
 }
 
+template <>
+void WriteInlineData<GLchar>(const std::vector<uint8_t> &vec, std::ostream &out)
+{
+    const GLchar *data = reinterpret_cast<const GLchar *>(vec.data());
+    size_t count       = vec.size() / sizeof(GLchar);
+
+    if (data == nullptr || data[0] == '\0')
+    {
+        return;
+    }
+
+    out << "\"";
+
+    for (size_t dataIndex = 0; dataIndex < count; ++dataIndex)
+    {
+        if (data[dataIndex] == '\0')
+            break;
+
+        out << static_cast<GLchar>(data[dataIndex]);
+    }
+
+    out << "\"";
+}
+
 constexpr size_t kInlineDataThreshold = 128;
 
 void WriteStringParamReplay(std::ostream &out, const ParamCapture &param)
@@ -429,7 +453,12 @@
             case ParamType::TGLenumConstPointer:
                 WriteInlineData<GLuint>(data, header);
                 break;
+            case ParamType::TGLcharPointer:
+                WriteInlineData<GLchar>(data, header);
+                break;
             default:
+                INFO() << "Unhandled ParamType: " << angle::ParamTypeToString(overrideType)
+                       << " in " << call.name();
                 UNIMPLEMENTED();
                 break;
         }
@@ -440,6 +469,11 @@
     }
 }
 
+uintptr_t SyncIndexValue(GLsync sync)
+{
+    return reinterpret_cast<uintptr_t>(sync);
+}
+
 void WriteCppReplayForCall(const CallCapture &call,
                            DataCounters *counters,
                            std::ostream &out,
@@ -455,15 +489,25 @@
         callOut << "gShaderProgramMap[" << id << "] = ";
     }
 
-    if (call.entryPoint == gl::EntryPoint::MapBufferRange)
+    if (call.entryPoint == gl::EntryPoint::FenceSync)
+    {
+        GLsync sync = call.params.getReturnValue().value.GLsyncVal;
+        callOut << "gSyncMap[" << SyncIndexValue(sync) << "] = ";
+    }
+
+    if (call.entryPoint == gl::EntryPoint::MapBufferRange ||
+        call.entryPoint == gl::EntryPoint::MapBufferRangeEXT)
     {
         GLbitfield access =
             call.params.getParam("access", ParamType::TGLbitfield, 3).value.GLbitfieldVal;
 
         if (access & GL_MAP_WRITE_BIT)
         {
-            // Track the returned pointer so we update its data
-            callOut << "gMappedBufferData = ";
+            // Track the returned pointer so we update its data when unmapped
+            gl::BufferID bufferID = call.params.getMappedBufferID();
+            callOut << "gMappedBufferData[";
+            WriteParamValueReplay<ParamType::TBufferID>(callOut, call, bufferID);
+            callOut << "] = ";
         }
     }
 
@@ -499,6 +543,21 @@
             {
                 WriteGLFloatValue(callOut, param.value.GLfloatVal);
             }
+            else if (param.type == ParamType::TGLsync)
+            {
+                callOut << "gSyncMap[" << SyncIndexValue(param.value.GLsyncVal) << "]";
+            }
+            else if (param.type == ParamType::TGLuint64 && param.name == "timeout")
+            {
+                if (param.value.GLuint64Val == GL_TIMEOUT_IGNORED)
+                {
+                    callOut << "GL_TIMEOUT_IGNORED";
+                }
+                else
+                {
+                    WriteParamCaptureReplay(callOut, call, param);
+                }
+            }
             else
             {
                 WriteParamCaptureReplay(callOut, call, param);
@@ -616,7 +675,9 @@
     std::string filePath;
 };
 
-std::string GetBinaryDataFilePath(bool compression, int contextId, const std::string &captureLabel)
+std::string GetBinaryDataFilePath(bool compression,
+                                  gl::ContextID contextId,
+                                  const std::string &captureLabel)
 {
     std::stringstream fnameStream;
     fnameStream << FmtCapturePrefix(contextId, captureLabel) << ".angledata";
@@ -629,7 +690,7 @@
 
 void SaveBinaryData(bool compression,
                     const std::string &outDir,
-                    int contextId,
+                    gl::ContextID contextId,
                     const std::string &captureLabel,
                     const std::vector<uint8_t> &binaryData)
 {
@@ -666,7 +727,7 @@
 
 void WriteLoadBinaryDataCall(bool compression,
                              std::ostream &out,
-                             int contextId,
+                             gl::ContextID contextId,
                              const std::string &captureLabel)
 {
     std::string binaryDataFileName = GetBinaryDataFilePath(compression, contextId, captureLabel);
@@ -675,7 +736,7 @@
 
 void WriteCppReplay(bool compression,
                     const std::string &outDir,
-                    int contextId,
+                    gl::ContextID contextId,
                     const std::string &captureLabel,
                     uint32_t frameIndex,
                     const std::vector<CallCapture> &frameCalls,
@@ -701,7 +762,7 @@
 
     if (frameIndex == 0 || !setupCalls.empty())
     {
-        out << "void SetupContext" << Str(contextId) << "Replay()\n";
+        out << "void SetupContext" << Str(static_cast<int>(contextId)) << "Replay()\n";
         out << "{\n";
 
         std::stringstream setupCallStream;
@@ -757,7 +818,7 @@
 
 void WriteCppReplayIndexFiles(bool compression,
                               const std::string &outDir,
-                              int contextId,
+                              gl::ContextID contextId,
                               const std::string &captureLabel,
                               uint32_t frameStart,
                               uint32_t frameEnd,
@@ -805,8 +866,9 @@
     header << "constexpr uint32_t kReplayFrameStart = " << frameStart << ";\n";
     header << "constexpr uint32_t kReplayFrameEnd = " << frameEnd << ";\n";
     header << "\n";
-    header << "void SetupContext" << contextId << "Replay();\n";
-    header << "void ReplayContext" << contextId << "Frame(uint32_t frameIndex);\n";
+    header << "void SetupContext" << static_cast<int>(contextId) << "Replay();\n";
+    header << "void ReplayContext" << static_cast<int>(contextId)
+           << "Frame(uint32_t frameIndex);\n";
     header << "\n";
     header << "using FramebufferChangeCallback = void(*)(void *userData, GLenum target, GLuint "
               "framebuffer);\n";
@@ -830,7 +892,6 @@
     header << "// Global state\n";
     header << "\n";
     header << "extern uint8_t *gBinaryData;\n";
-    header << "extern void *gMappedBufferData;\n";
 
     source << "#include \"" << FmtCapturePrefix(contextId, captureLabel) << ".h\"\n";
     source << "\n";
@@ -877,7 +938,6 @@
     source << "\n";
 
     source << "uint8_t *gBinaryData = nullptr;\n";
-    source << "void* gMappedBufferData = nullptr;\n";
 
     if (readBufferSize > 0)
     {
@@ -899,6 +959,10 @@
         source << "ResourceMap g" << name << "Map;\n";
     }
 
+    header << "using SyncResourceMap = std::unordered_map<uintptr_t, GLsync>;\n";
+    header << "extern SyncResourceMap gSyncMap;\n";
+    source << "SyncResourceMap gSyncMap;\n";
+
     header << "\n";
 
     source << "\n";
@@ -917,14 +981,15 @@
     source << "}\n";
 
     source << "\n";
-    source << "void ReplayContext" << contextId << "Frame(uint32_t frameIndex)\n";
+    source << "void ReplayContext" << static_cast<int>(contextId) << "Frame(uint32_t frameIndex)\n";
     source << "{\n";
     source << "    switch (frameIndex)\n";
     source << "    {\n";
     for (uint32_t frameIndex = frameStart; frameIndex < frameEnd; ++frameIndex)
     {
         source << "        case " << frameIndex << ":\n";
-        source << "            ReplayContext" << contextId << "Frame" << frameIndex << "();\n";
+        source << "            ReplayContext" << static_cast<int>(contextId) << "Frame"
+               << frameIndex << "();\n";
         source << "            break;\n";
     }
     source << "        default:\n";
@@ -961,12 +1026,22 @@
     source << "    fseek(fp, 0, SEEK_SET);\n";
     source << "    if (gDecompressCallback)\n";
     source << "    {\n";
+    source << "        if (!strstr(fileName, \".gz\"))\n";
+    source << "        {\n";
+    source << "            fprintf(stderr, \"Filename does not end in .gz\");\n";
+    source << "            exit(1);\n";
+    source << "        }\n";
     source << "        std::vector<uint8_t> compressedData(size);\n";
     source << "        (void)fread(compressedData.data(), 1, size, fp);\n";
     source << "        gBinaryData = gDecompressCallback(compressedData);\n";
     source << "    }\n";
     source << "    else\n";
     source << "    {\n";
+    source << "        if (!strstr(fileName, \".angledata\"))\n";
+    source << "        {\n";
+    source << "            fprintf(stderr, \"Filename does not end in .angledata\");\n";
+    source << "            exit(1);\n";
+    source << "        }\n";
     source << "        gBinaryData = new uint8_t[size];\n";
     source << "        (void)fread(gBinaryData, 1, size, fp);\n";
     source << "    }\n";
@@ -986,12 +1061,16 @@
         source << "}\n";
     }
 
-    header << "void UpdateClientBufferData(const void *source, GLsizei size);\n";
+    // Data types and functions for tracking contents of mapped buffers
+    header << "using BufferHandleMap = std::unordered_map<GLuint, void*>;\n";
+    header << "extern BufferHandleMap gMappedBufferData;\n";
+    header << "void UpdateClientBufferData(GLuint bufferID, const void *source, GLsizei size);\n";
+    source << "BufferHandleMap gMappedBufferData;\n";
     source << "\n";
-    source << "void UpdateClientBufferData(const void *source, GLsizei size)";
+    source << "void UpdateClientBufferData(GLuint bufferID, const void *source, GLsizei size)";
     source << "\n";
     source << "{\n";
-    source << "    memcpy(gMappedBufferData, source, size);\n";
+    source << "    memcpy(gMappedBufferData[gBufferMap[bufferID]], source, size);\n";
     source << "}\n";
 
     for (ResourceIDType resourceType : AllEnums<ResourceIDType>())
@@ -1181,12 +1260,6 @@
             break;
         }
 
-        case gl::EntryPoint::GenPathsCHROMIUM:
-        {
-            // TODO(jmadill): Handle path IDs. http://anglebug.com/3662
-            break;
-        }
-
         case gl::EntryPoint::GenProgramPipelines:
         {
             const ParamCapture &pipelines =
@@ -1325,6 +1398,167 @@
     }
 }
 
+void CaptureUpdateUniformValues(const gl::State &replayState,
+                                const gl::Context *context,
+                                const gl::Program *program,
+                                std::vector<CallCapture> *callsOut)
+{
+    const std::vector<gl::LinkedUniform> &uniforms     = program->getState().getUniforms();
+    const std::vector<gl::VariableLocation> &locations = program->getUniformLocations();
+
+    for (const gl::VariableLocation &location : locations)
+    {
+        const gl::LinkedUniform &uniform = uniforms[location.index];
+
+        if (!program->isLinked())
+        {
+            // We can't populate uniforms if the program hasn't been linked
+            continue;
+        }
+
+        if (uniform.isArray())
+        {
+            UNIMPLEMENTED();
+        }
+
+        // We need to bind the program and update its uniforms
+        // TODO (http://anglebug.com/3662): Only bind if different from currently bound
+        Capture(callsOut, CaptureUseProgram(replayState, true, program->id()));
+        CaptureUpdateCurrentProgram(callsOut->back(), callsOut);
+
+        const gl::UniformTypeInfo *typeInfo = uniform.typeInfo;
+        gl::UniformLocation uniformLoc      = {static_cast<int>(location.index)};
+
+        switch (typeInfo->componentType)
+        {
+            case GL_FLOAT:
+            {
+                std::vector<GLfloat> components(typeInfo->componentCount);
+                program->getUniformfv(context, uniformLoc, components.data());
+                switch (typeInfo->type)
+                {
+                    // Note: All matrix uniforms are populated without transpose
+                    case GL_FLOAT_MAT4x3:
+                        Capture(callsOut, CaptureUniformMatrix4x3fv(replayState, true, uniformLoc,
+                                                                    1, false, components.data()));
+                        break;
+                    case GL_FLOAT_MAT4x2:
+                        Capture(callsOut, CaptureUniformMatrix4x2fv(replayState, true, uniformLoc,
+                                                                    1, false, components.data()));
+                        break;
+                    case GL_FLOAT_MAT4:
+                        Capture(callsOut, CaptureUniformMatrix4fv(replayState, true, uniformLoc, 1,
+                                                                  false, components.data()));
+                        break;
+                    case GL_FLOAT_MAT3x4:
+                        Capture(callsOut, CaptureUniformMatrix3x4fv(replayState, true, uniformLoc,
+                                                                    1, false, components.data()));
+                        break;
+                    case GL_FLOAT_MAT3x2:
+                        Capture(callsOut, CaptureUniformMatrix3x2fv(replayState, true, uniformLoc,
+                                                                    1, false, components.data()));
+                        break;
+                    case GL_FLOAT_MAT3:
+                        Capture(callsOut, CaptureUniformMatrix3fv(replayState, true, uniformLoc, 1,
+                                                                  false, components.data()));
+                        break;
+                    case GL_FLOAT_MAT2x4:
+                        Capture(callsOut, CaptureUniformMatrix2x4fv(replayState, true, uniformLoc,
+                                                                    1, false, components.data()));
+                        break;
+                    case GL_FLOAT_MAT2x3:
+                        Capture(callsOut, CaptureUniformMatrix2x3fv(replayState, true, uniformLoc,
+                                                                    1, false, components.data()));
+                        break;
+                    case GL_FLOAT_MAT2:
+                        Capture(callsOut, CaptureUniformMatrix2fv(replayState, true, uniformLoc, 1,
+                                                                  false, components.data()));
+                        break;
+                    case GL_FLOAT_VEC4:
+                        Capture(callsOut, CaptureUniform4fv(replayState, true, uniformLoc, 1,
+                                                            components.data()));
+                        break;
+                    case GL_FLOAT_VEC3:
+                        Capture(callsOut, CaptureUniform3fv(replayState, true, uniformLoc, 1,
+                                                            components.data()));
+                        break;
+                    case GL_FLOAT_VEC2:
+                        Capture(callsOut, CaptureUniform2fv(replayState, true, uniformLoc, 1,
+                                                            components.data()));
+                        break;
+                    case GL_FLOAT:
+                        Capture(callsOut, CaptureUniform1fv(replayState, true, uniformLoc, 1,
+                                                            components.data()));
+                        break;
+                    default:
+                        UNIMPLEMENTED();
+                        break;
+                }
+                break;
+            }
+            case GL_INT:
+            {
+                std::vector<GLint> components(typeInfo->componentCount);
+                program->getUniformiv(context, uniformLoc, components.data());
+                switch (typeInfo->componentCount)
+                {
+                    case 4:
+                        Capture(callsOut, CaptureUniform4iv(replayState, true, uniformLoc, 1,
+                                                            components.data()));
+                        break;
+                    case 3:
+                        Capture(callsOut, CaptureUniform3iv(replayState, true, uniformLoc, 1,
+                                                            components.data()));
+                        break;
+                    case 2:
+                        Capture(callsOut, CaptureUniform2iv(replayState, true, uniformLoc, 1,
+                                                            components.data()));
+                        break;
+                    case 1:
+                        Capture(callsOut, CaptureUniform1iv(replayState, true, uniformLoc, 1,
+                                                            components.data()));
+                        break;
+                    default:
+                        UNIMPLEMENTED();
+                        break;
+                }
+                break;
+            }
+            case GL_UNSIGNED_INT:
+            {
+                std::vector<GLuint> components(typeInfo->componentCount);
+                program->getUniformuiv(context, uniformLoc, components.data());
+                switch (typeInfo->componentCount)
+                {
+                    case 4:
+                        Capture(callsOut, CaptureUniform4uiv(replayState, true, uniformLoc, 1,
+                                                             components.data()));
+                        break;
+                    case 3:
+                        Capture(callsOut, CaptureUniform3uiv(replayState, true, uniformLoc, 1,
+                                                             components.data()));
+                        break;
+                    case 2:
+                        Capture(callsOut, CaptureUniform2uiv(replayState, true, uniformLoc, 1,
+                                                             components.data()));
+                        break;
+                    case 1:
+                        Capture(callsOut, CaptureUniform1uiv(replayState, true, uniformLoc, 1,
+                                                             components.data()));
+                        break;
+                    default:
+                        UNIMPLEMENTED();
+                        break;
+                }
+                break;
+            }
+            default:
+                UNIMPLEMENTED();
+                break;
+        }
+    }
+}
+
 void CaptureVertexArrayData(std::vector<CallCapture> *setupCalls,
                             const gl::Context *context,
                             const gl::VertexArray *vertexArray,
@@ -1373,6 +1607,133 @@
     }
 }
 
+void CaptureTextureStorage(std::vector<CallCapture> *setupCalls,
+                           gl::State *replayState,
+                           const gl::Texture *texture)
+{
+    // Use mip-level 0 for the base dimensions
+    gl::ImageIndex imageIndex = gl::ImageIndex::MakeFromType(texture->getType(), 0);
+    const gl::ImageDesc &desc = texture->getTextureState().getImageDesc(imageIndex);
+
+    switch (texture->getType())
+    {
+        case gl::TextureType::_2D:
+        case gl::TextureType::CubeMap:
+        {
+            Capture(setupCalls, CaptureTexStorage2D(*replayState, true, texture->getType(),
+                                                    texture->getImmutableLevels(),
+                                                    desc.format.info->internalFormat,
+                                                    desc.size.width, desc.size.height));
+            break;
+        }
+        case gl::TextureType::_3D:
+        case gl::TextureType::_2DArray:
+        {
+            Capture(setupCalls, CaptureTexStorage3D(
+                                    *replayState, true, texture->getType(),
+                                    texture->getImmutableLevels(), desc.format.info->internalFormat,
+                                    desc.size.width, desc.size.height, desc.size.depth));
+            break;
+        }
+        default:
+            UNIMPLEMENTED();
+            break;
+    }
+}
+
+void CaptureTextureContents(std::vector<CallCapture> *setupCalls,
+                            gl::State *replayState,
+                            const gl::Texture *texture,
+                            const gl::ImageIndex &index,
+                            const gl::ImageDesc &desc,
+                            GLuint size,
+                            const void *data)
+{
+    const gl::InternalFormat &format = *desc.format.info;
+
+    bool is3D =
+        (index.getType() == gl::TextureType::_3D || index.getType() == gl::TextureType::_2DArray);
+
+    if (format.compressed)
+    {
+        if (is3D)
+        {
+            if (texture->getImmutableFormat())
+            {
+                Capture(setupCalls,
+                        CaptureCompressedTexSubImage3D(
+                            *replayState, true, index.getTarget(), index.getLevelIndex(), 0, 0, 0,
+                            desc.size.width, desc.size.height, desc.size.depth,
+                            format.internalFormat, size, data));
+            }
+            else
+            {
+                Capture(setupCalls,
+                        CaptureCompressedTexImage3D(*replayState, true, index.getTarget(),
+                                                    index.getLevelIndex(), format.internalFormat,
+                                                    desc.size.width, desc.size.height,
+                                                    desc.size.depth, 0, size, data));
+            }
+        }
+        else
+        {
+            if (texture->getImmutableFormat())
+            {
+                Capture(setupCalls,
+                        CaptureCompressedTexSubImage2D(
+                            *replayState, true, index.getTarget(), index.getLevelIndex(), 0, 0,
+                            desc.size.width, desc.size.height, format.internalFormat, size, data));
+            }
+            else
+            {
+                Capture(setupCalls, CaptureCompressedTexImage2D(
+                                        *replayState, true, index.getTarget(),
+                                        index.getLevelIndex(), format.internalFormat,
+                                        desc.size.width, desc.size.height, 0, size, data));
+            }
+        }
+    }
+    else
+    {
+        if (is3D)
+        {
+            if (texture->getImmutableFormat())
+            {
+                Capture(setupCalls,
+                        CaptureTexSubImage3D(*replayState, true, index.getTarget(),
+                                             index.getLevelIndex(), 0, 0, 0, desc.size.width,
+                                             desc.size.height, desc.size.depth, format.format,
+                                             format.type, data));
+            }
+            else
+            {
+                Capture(
+                    setupCalls,
+                    CaptureTexImage3D(*replayState, true, index.getTarget(), index.getLevelIndex(),
+                                      format.internalFormat, desc.size.width, desc.size.height,
+                                      desc.size.depth, 0, format.format, format.type, data));
+            }
+        }
+        else
+        {
+            if (texture->getImmutableFormat())
+            {
+                Capture(setupCalls,
+                        CaptureTexSubImage2D(*replayState, true, index.getTarget(),
+                                             index.getLevelIndex(), 0, 0, desc.size.width,
+                                             desc.size.height, format.format, format.type, data));
+            }
+            else
+            {
+                Capture(setupCalls, CaptureTexImage2D(*replayState, true, index.getTarget(),
+                                                      index.getLevelIndex(), format.internalFormat,
+                                                      desc.size.width, desc.size.height, 0,
+                                                      format.format, format.type, data));
+            }
+        }
+    }
+}
+
 void CaptureMidExecutionSetup(const gl::Context *context,
                               std::vector<CallCapture> *setupCalls,
                               const ShaderSourceMap &cachedShaderSources,
@@ -1380,9 +1741,8 @@
                               const TextureLevelDataMap &cachedTextureLevelData)
 {
     const gl::State &apiState = context->getState();
-    gl::State replayState(0, nullptr, nullptr, nullptr, EGL_OPENGL_ES_API,
-                          apiState.getClientVersion(), false, true, true, true, false,
-                          EGL_CONTEXT_PRIORITY_MEDIUM_IMG);
+    gl::State replayState(nullptr, nullptr, nullptr, EGL_OPENGL_ES_API, apiState.getClientVersion(),
+                          false, true, true, true, false, EGL_CONTEXT_PRIORITY_MEDIUM_IMG);
 
     // Small helper function to make the code more readable.
     auto cap = [setupCalls](CallCapture &&call) { setupCalls->emplace_back(std::move(call)); };
@@ -1589,7 +1949,6 @@
         }
 
         // Texture parameters
-        // TODO: Add immutable and base/max when TexStorage is handled (http://anglebug.com/3662)
         if (texture->getSwizzleRed() != GL_RED)
         {
             capTexParam(GL_TEXTURE_SWIZZLE_R, texture->getSwizzleRed());
@@ -1610,6 +1969,22 @@
             capTexParam(GL_TEXTURE_SWIZZLE_A, texture->getSwizzleAlpha());
         }
 
+        if (texture->getBaseLevel() != 0)
+        {
+            capTexParam(GL_TEXTURE_BASE_LEVEL, texture->getBaseLevel());
+        }
+
+        if (texture->getMaxLevel() != 1000)
+        {
+            capTexParam(GL_TEXTURE_MAX_LEVEL, texture->getMaxLevel());
+        }
+
+        // If the texture is immutable, initialize it with TexStorage
+        if (texture->getImmutableFormat())
+        {
+            CaptureTextureStorage(setupCalls, &replayState, texture);
+        }
+
         // Iterate texture levels and layers.
         gl::ImageIndexIterator imageIter = gl::ImageIndexIterator::MakeGeneric(
             texture->getType(), 0, texture->getMipmapMaxLevel() + 1, gl::ImageIndex::kEntireLevel,
@@ -1631,9 +2006,6 @@
                    index.getType() == gl::TextureType::_2DArray ||
                    index.getType() == gl::TextureType::CubeMap);
 
-            bool is3D = (index.getType() == gl::TextureType::_3D ||
-                         index.getType() == gl::TextureType::_2DArray);
-
             if (format.compressed)
             {
                 // For compressed images, we've tracked a copy of the incoming data, so we can
@@ -1650,22 +2022,9 @@
                 const std::vector<uint8_t> &capturedTextureLevel = foundTextureLevel->second;
 
                 // Use the shadow copy of the data to populate the call
-                if (is3D)
-                {
-                    cap(CaptureCompressedTexImage3D(
-                        replayState, true, index.getTarget(), index.getLevelIndex(),
-                        format.internalFormat, desc.size.width, desc.size.height, desc.size.depth,
-                        0, static_cast<GLuint>(capturedTextureLevel.size()),
-                        capturedTextureLevel.data()));
-                }
-                else
-                {
-                    cap(CaptureCompressedTexImage2D(
-                        replayState, true, index.getTarget(), index.getLevelIndex(),
-                        format.internalFormat, desc.size.width, desc.size.height, 0,
-                        static_cast<GLuint>(capturedTextureLevel.size()),
-                        capturedTextureLevel.data()));
-                }
+                CaptureTextureContents(setupCalls, &replayState, texture, index, desc,
+                                       static_cast<GLuint>(capturedTextureLevel.size()),
+                                       capturedTextureLevel.data());
             }
             else
             {
@@ -1695,37 +2054,13 @@
                                                index.getLevelIndex(), getFormat, getType,
                                                data.data());
 
-                    if (is3D)
-                    {
-                        cap(CaptureTexImage3D(replayState, true, index.getTarget(),
-                                              index.getLevelIndex(), format.internalFormat,
-                                              desc.size.width, desc.size.height, desc.size.depth, 0,
-                                              getFormat, getType, data.data()));
-                    }
-                    else
-                    {
-                        cap(CaptureTexImage2D(replayState, true, index.getTarget(),
-                                              index.getLevelIndex(), format.internalFormat,
-                                              desc.size.width, desc.size.height, 0, getFormat,
-                                              getType, data.data()));
-                    }
+                    CaptureTextureContents(setupCalls, &replayState, texture, index, desc,
+                                           static_cast<GLuint>(data.size()), data.data());
                 }
                 else
                 {
-                    if (is3D)
-                    {
-                        cap(CaptureTexImage3D(replayState, true, index.getTarget(),
-                                              index.getLevelIndex(), format.internalFormat,
-                                              desc.size.width, desc.size.height, desc.size.depth, 0,
-                                              format.format, format.type, nullptr));
-                    }
-                    else
-                    {
-                        cap(CaptureTexImage2D(replayState, true, index.getTarget(),
-                                              index.getLevelIndex(), format.internalFormat,
-                                              desc.size.width, desc.size.height, 0, format.format,
-                                              format.type, nullptr));
-                    }
+                    CaptureTextureContents(setupCalls, &replayState, texture, index, desc, 0,
+                                           nullptr);
                 }
             }
         }
@@ -1913,7 +2248,7 @@
         cap(CaptureCreateProgram(replayState, true, id.value));
 
         // Compile with last linked sources.
-        for (gl::ShaderType shaderType : program->getState().getLinkedShaderStages())
+        for (gl::ShaderType shaderType : program->getExecutable().getLinkedShaderStages())
         {
             const std::string &sourceString = linkedSources[shaderType];
             const char *sourcePointer       = sourceString.c_str();
@@ -1950,6 +2285,7 @@
 
         cap(CaptureLinkProgram(replayState, true, id));
         CaptureUpdateUniformLocations(program, setupCalls);
+        CaptureUpdateUniformValues(replayState, context, program, setupCalls);
     }
 
     // Handle shaders.
@@ -2392,6 +2728,11 @@
                            currentScissor.width, currentScissor.height));
     }
 
+    if (apiState.isDitherEnabled())
+    {
+        capCap(GL_DITHER, apiState.isDitherEnabled());
+    }
+
     const gl::SyncManager &syncs = apiState.getSyncManagerForCapture();
     for (const auto &syncIter : syncs)
     {
@@ -2446,6 +2787,7 @@
     std::swap(mClientArrayDataParam, other.mClientArrayDataParam);
     std::swap(mReadBufferSize, other.mReadBufferSize);
     std::swap(mReturnValueCapture, other.mReturnValueCapture);
+    std::swap(mMappedBufferID, other.mMappedBufferID);
     return *this;
 }
 
@@ -2826,7 +3168,7 @@
     }
 }
 
-void FrameCapture::maybeCaptureClientData(const gl::Context *context, const CallCapture &call)
+void FrameCapture::maybeCaptureClientData(const gl::Context *context, CallCapture &call)
 {
     switch (call.entryPoint)
     {
@@ -2846,6 +3188,24 @@
             break;
         }
 
+        case gl::EntryPoint::DeleteBuffers:
+        {
+            GLsizei count = call.params.getParam("n", ParamType::TGLsizei, 0).value.GLsizeiVal;
+            const gl::BufferID *bufferIDs =
+                call.params.getParam("buffersPacked", ParamType::TBufferIDConstPointer, 1)
+                    .value.BufferIDConstPointerVal;
+            for (GLsizei i = 0; i < count; i++)
+            {
+                // For each buffer being deleted, check our backup of data and remove it
+                const auto &bufferDataInfo = mBufferDataMap.find(bufferIDs[i]);
+                if (bufferDataInfo != mBufferDataMap.end())
+                {
+                    mBufferDataMap.erase(bufferDataInfo);
+                }
+            }
+            break;
+        }
+
         case gl::EntryPoint::DrawArrays:
         {
             if (context->getStateCache().hasAnyActiveClientAttrib())
@@ -2963,9 +3323,15 @@
         }
 
         case gl::EntryPoint::MapBuffer:
+        {
+            UNIMPLEMENTED();
+            break;
+        }
         case gl::EntryPoint::MapBufferOES:
-        case gl::EntryPoint::MapBufferRangeEXT:
-        case gl::EntryPoint::UnmapBufferOES:
+        {
+            UNIMPLEMENTED();
+            break;
+        }
         case gl::EntryPoint::UnmapNamedBuffer:
         {
             UNIMPLEMENTED();
@@ -2973,6 +3339,7 @@
         }
 
         case gl::EntryPoint::MapBufferRange:
+        case gl::EntryPoint::MapBufferRangeEXT:
         {
             // Use the access bits to see if contents may be modified
             GLbitfield access =
@@ -2992,17 +3359,23 @@
                 GLsizeiptr length =
                     call.params.getParam("length", ParamType::TGLsizeiptr, 2).value.GLsizeiptrVal;
 
-                mBufferDataMap[target] = std::make_pair(offset, length);
+                gl::Buffer *buffer           = context->getState().getTargetBuffer(target);
+                mBufferDataMap[buffer->id()] = std::make_pair(offset, length);
+
+                // Track the bufferID that was just mapped
+                call.params.setMappedBufferID(buffer->id());
             }
             break;
         }
 
         case gl::EntryPoint::UnmapBuffer:
+        case gl::EntryPoint::UnmapBufferOES:
         {
             // See if we need to capture the buffer contents
             captureMappedBufferSnapshot(context, call);
             break;
         }
+
         default:
             break;
     }
@@ -3115,9 +3488,10 @@
     // into what the client did to the buffer while mapped
     // This sequence will result in replay calls like this:
     //   ...
-    //   gMappedBufferData = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, 65536, GL_MAP_WRITE_BIT);
+    //   gMappedBufferData[gBufferMap[42]] = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, 65536,
+    //                                                        GL_MAP_WRITE_BIT);
     //   ...
-    //   UpdateClientBufferData(&gBinaryData[164631024], 65536);
+    //   UpdateClientBufferData(42, &gBinaryData[164631024], 65536);
     //   glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
     //   ...
 
@@ -3125,7 +3499,8 @@
     gl::BufferBinding target =
         call.params.getParam("targetPacked", ParamType::TBufferBinding, 0).value.BufferBindingVal;
 
-    const auto &bufferDataInfo = mBufferDataMap.find(target);
+    gl::Buffer *buffer         = context->getState().getTargetBuffer(target);
+    const auto &bufferDataInfo = mBufferDataMap.find(buffer->id());
     if (bufferDataInfo == mBufferDataMap.end())
     {
         // This buffer was not marked writable, so we did not back it up
@@ -3136,14 +3511,20 @@
     GLsizeiptr length = bufferDataInfo->second.second;
 
     // Map the buffer so we can copy its contents out
-    gl::Buffer *buffer = context->getState().getTargetBuffer(target);
     ASSERT(!buffer->isMapped());
-    (void)buffer->mapRange(context, offset, length, GL_MAP_READ_BIT);
+    angle::Result result = buffer->mapRange(context, offset, length, GL_MAP_READ_BIT);
+    if (result != angle::Result::Continue)
+    {
+        ERR() << "Failed to mapRange of buffer" << std::endl;
+    }
     const uint8_t *data = reinterpret_cast<const uint8_t *>(buffer->getMapPointer());
 
     // Create the parameters to our helper for use during replay
     ParamBuffer dataParamBuffer;
 
+    // Pass in the target buffer ID
+    dataParamBuffer.addValueParam("dest", ParamType::TGLuint, buffer->id().value);
+
     // Capture the current buffer data with a binary param
     ParamCapture captureData("source", ParamType::TvoidConstPointer);
     CaptureMemory(data, length, &captureData);
@@ -3219,7 +3600,7 @@
     return mData[counterKey]++;
 }
 
-bool FrameCapture::enabled() const
+bool FrameCapture::isCapturing() const
 {
     // Currently we will always do a capture up until the last frame. In the future we could improve
     // mid execution capture by only capturing between the start and end frames. The only necessary
@@ -3286,6 +3667,24 @@
     CaptureMemory(str, strlen(str) + 1, paramCapture);
 }
 
+void CaptureStringLimit(const GLchar *str, uint32_t limit, ParamCapture *paramCapture)
+{
+    // Write the incoming string up to limit, including null terminator
+    size_t length = strlen(str) + 1;
+
+    if (length > limit)
+    {
+        // If too many characters, resize the string to fit in the limit
+        std::string newStr = str;
+        newStr.resize(limit - 1);
+        CaptureString(newStr.c_str(), paramCapture);
+    }
+    else
+    {
+        CaptureMemory(str, length, paramCapture);
+    }
+}
+
 gl::Program *GetLinkedProgramForCapture(const gl::State &glState, gl::ShaderProgramID handle)
 {
     gl::Program *program = glState.getShaderProgramManagerForCapture().getProgram(handle);
@@ -3393,14 +3792,6 @@
 }
 
 template <>
-void WriteParamValueReplay<ParamType::TPathID>(std::ostream &os,
-                                               const CallCapture &call,
-                                               gl::PathID value)
-{
-    os << "gPathMap[" << value.value << "]";
-}
-
-template <>
 void WriteParamValueReplay<ParamType::TProgramPipelineID>(std::ostream &os,
                                                           const CallCapture &call,
                                                           gl::ProgramPipelineID value)
@@ -3449,6 +3840,14 @@
 }
 
 template <>
+void WriteParamValueReplay<ParamType::TGLsync>(std::ostream &os,
+                                               const CallCapture &call,
+                                               GLsync value)
+{
+    os << "gSyncMap[" << SyncIndexValue(value) << "]";
+}
+
+template <>
 void WriteParamValueReplay<ParamType::TTextureID>(std::ostream &os,
                                                   const CallCapture &call,
                                                   gl::TextureID value)
diff --git a/src/libANGLE/FrameCapture.h b/src/libANGLE/FrameCapture.h
index 41c8b59..511d24c 100644
--- a/src/libANGLE/FrameCapture.h
+++ b/src/libANGLE/FrameCapture.h
@@ -78,11 +78,18 @@
 
     const std::vector<ParamCapture> &getParamCaptures() const { return mParamCaptures; }
 
+    // These helpers allow us to track the ID of the buffer that was active when
+    // MapBufferRange was called.  We'll use it during replay to track the
+    // buffer's contents, as they can be modified by the host.
+    void setMappedBufferID(gl::BufferID bufferID) { mMappedBufferID = bufferID; }
+    gl::BufferID getMappedBufferID() const { return mMappedBufferID; }
+
   private:
     std::vector<ParamCapture> mParamCaptures;
     ParamCapture mReturnValueCapture;
     int mClientArrayDataParam = -1;
     size_t mReadBufferSize    = 0;
+    gl::BufferID mMappedBufferID;
 };
 
 struct CallCapture
@@ -173,8 +180,8 @@
 // Used by the CPP replay to filter out unnecessary code.
 using HasResourceTypeMap = angle::PackedEnumBitSet<ResourceIDType>;
 
-// Map of buffing bindings to offset and size used when mapped
-using BufferDataMap = std::map<gl::BufferBinding, std::pair<GLintptr, GLsizeiptr>>;
+// Map of buffer ID to offset and size used when mapped
+using BufferDataMap = std::map<gl::BufferID, std::pair<GLintptr, GLsizeiptr>>;
 
 // A dictionary of sources indexed by shader type.
 using ProgramSources = gl::ShaderMap<std::string>;
@@ -195,7 +202,9 @@
 
     void captureCall(const gl::Context *context, CallCapture &&call);
     void onEndFrame(const gl::Context *context);
-    bool enabled() const;
+    bool enabled() const { return mEnabled; }
+
+    bool isCapturing() const;
     void replay(gl::Context *context);
 
   private:
@@ -207,7 +216,7 @@
     void captureCompressedTextureData(const gl::Context *context, const CallCapture &call);
 
     void reset();
-    void maybeCaptureClientData(const gl::Context *context, const CallCapture &call);
+    void maybeCaptureClientData(const gl::Context *context, CallCapture &call);
     void maybeCapturePostCallUpdates(const gl::Context *context);
 
     static void ReplayCall(gl::Context *context,
@@ -222,7 +231,7 @@
     // This simplifies a lot of file management.
     std::vector<uint8_t> mBinaryData;
 
-    bool mEnabled;
+    bool mEnabled = false;
     std::string mOutDirectory;
     std::string mCaptureLabel;
     bool mCompression;
@@ -251,7 +260,7 @@
                                ArgsT... captureParams)
 {
     FrameCapture *frameCapture = context->getFrameCapture();
-    if (!frameCapture->enabled())
+    if (!frameCapture->isCapturing())
         return;
 
     CallCapture call = captureFunc(context->getState(), isCallValid, captureParams...);
@@ -283,6 +292,7 @@
 // Pointer capture helpers.
 void CaptureMemory(const void *source, size_t size, ParamCapture *paramCapture);
 void CaptureString(const GLchar *str, ParamCapture *paramCapture);
+void CaptureStringLimit(const GLchar *str, uint32_t limit, ParamCapture *paramCapture);
 
 gl::Program *GetLinkedProgramForCapture(const gl::State &glState, gl::ShaderProgramID handle);
 
@@ -344,11 +354,6 @@
                                                        gl::MemoryObjectID value);
 
 template <>
-void WriteParamValueReplay<ParamType::TPathID>(std::ostream &os,
-                                               const CallCapture &call,
-                                               gl::PathID value);
-
-template <>
 void WriteParamValueReplay<ParamType::TProgramPipelineID>(std::ostream &os,
                                                           const CallCapture &call,
                                                           gl::ProgramPipelineID value);
@@ -398,6 +403,11 @@
                                                         const CallCapture &call,
                                                         gl::UniformLocation value);
 
+template <>
+void WriteParamValueReplay<ParamType::TGLsync>(std::ostream &os,
+                                               const CallCapture &call,
+                                               GLsync value);
+
 // General fallback for any unspecific type.
 template <ParamType ParamT, typename T>
 void WriteParamValueReplay(std::ostream &os, const CallCapture &call, T value)
diff --git a/src/libANGLE/Framebuffer.cpp b/src/libANGLE/Framebuffer.cpp
index 1e81dc8..7a9966f 100644
--- a/src/libANGLE/Framebuffer.cpp
+++ b/src/libANGLE/Framebuffer.cpp
@@ -303,8 +303,9 @@
 }  // anonymous namespace
 
 // This constructor is only used for default framebuffers.
-FramebufferState::FramebufferState()
+FramebufferState::FramebufferState(ContextID owningContextID)
     : mId(Framebuffer::kDefaultDrawFramebufferHandle),
+      mOwningContextID(owningContextID),
       mLabel(),
       mColorAttachments(1),
       mDrawBufferStates(1, GL_BACK),
@@ -318,14 +319,16 @@
       mWebGLDepthStencilConsistent(true),
       mDepthBufferFeedbackLoop(false),
       mStencilBufferFeedbackLoop(false),
+      mHasRenderingFeedbackLoop(false),
       mDefaultFramebufferReadAttachmentInitialized(false)
 {
     ASSERT(mDrawBufferStates.size() > 0);
     mEnabledDrawBuffers.set(0);
 }
 
-FramebufferState::FramebufferState(const Caps &caps, FramebufferID id)
+FramebufferState::FramebufferState(const Caps &caps, FramebufferID id, ContextID owningContextID)
     : mId(id),
+      mOwningContextID(owningContextID),
       mLabel(),
       mColorAttachments(caps.maxColorAttachments),
       mDrawBufferStates(caps.maxDrawBuffers, GL_NONE),
@@ -339,6 +342,7 @@
       mWebGLDepthStencilConsistent(true),
       mDepthBufferFeedbackLoop(false),
       mStencilBufferFeedbackLoop(false),
+      mHasRenderingFeedbackLoop(false),
       mDefaultFramebufferReadAttachmentInitialized(false)
 {
     ASSERT(mId != Framebuffer::kDefaultDrawFramebufferHandle);
@@ -430,6 +434,19 @@
     return framebufferAttachment.isAttached() ? &framebufferAttachment : nullptr;
 }
 
+const FramebufferAttachment *FramebufferState::getReadPixelsAttachment(GLenum readFormat) const
+{
+    switch (readFormat)
+    {
+        case GL_DEPTH_COMPONENT:
+            return getDepthAttachment();
+        case GL_STENCIL_INDEX_OES:
+            return getStencilOrDepthStencilAttachment();
+        default:
+            return getReadAttachment();
+    }
+}
+
 const FramebufferAttachment *FramebufferState::getFirstNonNullAttachment() const
 {
     auto *colorAttachment = getFirstColorAttachment();
@@ -677,31 +694,61 @@
     return mId == Framebuffer::kDefaultDrawFramebufferHandle;
 }
 
-bool FramebufferState::updateAttachmentFeedbackLoop(size_t dirtyBit)
+bool FramebufferState::updateAttachmentFeedbackLoopAndReturnIfChanged(size_t dirtyBit)
 {
+    bool previous;
+    bool loop;
+
     switch (dirtyBit)
     {
         case Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT:
-            mDepthBufferFeedbackLoop = mDepthAttachment.isBoundAsSamplerOrImage();
-            return mDepthBufferFeedbackLoop;
+            previous                 = mDepthBufferFeedbackLoop;
+            loop                     = mDepthAttachment.isBoundAsSamplerOrImage(mOwningContextID);
+            mDepthBufferFeedbackLoop = loop;
+            break;
 
         case Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT:
-            mStencilBufferFeedbackLoop = mStencilAttachment.isBoundAsSamplerOrImage();
-            return mStencilBufferFeedbackLoop;
+            previous = mStencilBufferFeedbackLoop;
+            loop     = mStencilAttachment.isBoundAsSamplerOrImage(mOwningContextID);
+            mStencilBufferFeedbackLoop = loop;
+            break;
 
         default:
+        {
             ASSERT(dirtyBit <= Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX);
-            mDrawBufferFeedbackLoops[dirtyBit] =
-                mColorAttachments[dirtyBit].isBoundAsSamplerOrImage();
-            return mDrawBufferFeedbackLoops.test(dirtyBit);
+            previous = mDrawBufferFeedbackLoops.test(dirtyBit);
+            loop     = mColorAttachments[dirtyBit].isBoundAsSamplerOrImage(mOwningContextID);
+            mDrawBufferFeedbackLoops[dirtyBit] = loop;
+            break;
+        }
     }
+
+    updateHasRenderingFeedbackLoop();
+    return previous != loop;
+}
+
+void FramebufferState::updateHasRenderingFeedbackLoop()
+{
+    // We don't handle tricky cases where the default FBO is bound as a sampler.
+    // We also don't handle tricky cases with EGLImages and mipmap selection.
+    // TODO(http://anglebug.com/4500): Tricky rendering feedback loop cases.
+    if (isDefault())
+    {
+        return;
+    }
+
+    mHasRenderingFeedbackLoop =
+        mDrawBufferFeedbackLoops.any() || mDepthBufferFeedbackLoop || mStencilBufferFeedbackLoop;
 }
 
 const FramebufferID Framebuffer::kDefaultDrawFramebufferHandle = {0};
 
-Framebuffer::Framebuffer(const Caps &caps, rx::GLImplFactory *factory, FramebufferID id)
+Framebuffer::Framebuffer(const Caps &caps,
+                         rx::GLImplFactory *factory,
+                         FramebufferID id,
+                         ContextID owningContextID)
     : mSerial(factory->generateSerial()),
-      mState(caps, id),
+      mState(caps, id, owningContextID),
       mImpl(factory->createFramebuffer(mState)),
       mCachedStatus(),
       mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
@@ -720,7 +767,7 @@
 
 Framebuffer::Framebuffer(const Context *context, egl::Surface *surface, egl::Surface *readSurface)
     : mSerial(context->getImplementation()->generateSerial()),
-      mState(),
+      mState(context->id()),
       mImpl(surface->getImplementation()->createDefaultFramebuffer(context, mState)),
       mCachedStatus(GL_FRAMEBUFFER_COMPLETE),
       mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
@@ -760,7 +807,7 @@
 Framebuffer::Framebuffer(const Context *context,
                          rx::GLImplFactory *factory,
                          egl::Surface *readSurface)
-    : mState(),
+    : mState(context->id()),
       mImpl(factory->createFramebuffer(mState)),
       mCachedStatus(GL_FRAMEBUFFER_UNDEFINED_OES),
       mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
@@ -1093,7 +1140,9 @@
         // We can skip syncState on several back-ends.
         if (mImpl->shouldSyncStateBeforeCheckStatus())
         {
-            angle::Result err = syncState(context);
+            // This binding is not totally correct. It is ok because the parameter isn't used in
+            // the GL back-end and the GL back-end is the only user of syncStateBeforeCheckStatus.
+            angle::Result err = syncState(context, GL_FRAMEBUFFER);
             if (err != angle::Result::Continue)
             {
                 return 0;
@@ -1560,19 +1609,16 @@
     return angle::Result::Continue;
 }
 
-angle::Result Framebuffer::getImplementationColorReadFormat(const Context *context,
-                                                            GLenum *formatOut)
+GLenum Framebuffer::getImplementationColorReadFormat(const Context *context)
 {
-    ANGLE_TRY(syncState(context));
-    *formatOut = mImpl->getImplementationColorReadFormat(context);
-    return angle::Result::Continue;
+    const gl::InternalFormat &format = mImpl->getImplementationColorReadFormat(context);
+    return format.getReadPixelsFormat(context->getExtensions());
 }
 
-angle::Result Framebuffer::getImplementationColorReadType(const Context *context, GLenum *typeOut)
+GLenum Framebuffer::getImplementationColorReadType(const Context *context)
 {
-    ANGLE_TRY(syncState(context));
-    *typeOut = mImpl->getImplementationColorReadType(context);
-    return angle::Result::Continue;
+    const gl::InternalFormat &format = mImpl->getImplementationColorReadFormat(context);
+    return format.getReadPixelsType(context->getClientVersion());
 }
 
 angle::Result Framebuffer::readPixels(const Context *context,
@@ -1919,7 +1965,7 @@
     mState.mResourceNeedsInit.set(dirtyBit, attachment->initState() == InitState::MayNeedInit);
     onDirtyBinding->bind(resource);
 
-    mState.updateAttachmentFeedbackLoop(dirtyBit);
+    mState.updateAttachmentFeedbackLoopAndReturnIfChanged(dirtyBit);
     invalidateCompletenessCache();
 }
 
@@ -1928,12 +1974,12 @@
     setAttachment(context, GL_NONE, binding, ImageIndex(), nullptr);
 }
 
-angle::Result Framebuffer::syncState(const Context *context) const
+angle::Result Framebuffer::syncState(const Context *context, GLenum framebufferBinding) const
 {
     if (mDirtyBits.any())
     {
         mDirtyBitsGuard = mDirtyBits;
-        ANGLE_TRY(mImpl->syncState(context, mDirtyBits));
+        ANGLE_TRY(mImpl->syncState(context, framebufferBinding, mDirtyBits));
         mDirtyBits.reset();
         mDirtyBitsGuard.reset();
     }
@@ -1955,7 +2001,7 @@
         // Triggered by changes to Texture feedback loops.
         if (message == angle::SubjectMessage::BindingChanged)
         {
-            if (mState.updateAttachmentFeedbackLoop(index))
+            if (mState.updateAttachmentFeedbackLoopAndReturnIfChanged(index))
             {
                 mDirtyBits.set(index);
                 onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
@@ -2003,20 +2049,6 @@
     }
 }
 
-bool Framebuffer::formsRenderingFeedbackLoopWith(const Context *context) const
-{
-    // We don't handle tricky cases where the default FBO is bound as a sampler.
-    // We also don't handle tricky cases with EGLImages and mipmap selection.
-    // TODO(http://anglebug.com/4500): Tricky rendering feedback loop cases.
-    if (mState.isDefault())
-    {
-        return false;
-    }
-
-    return mState.mDrawBufferFeedbackLoops.any() || mState.mDepthBufferFeedbackLoop ||
-           mState.mStencilBufferFeedbackLoop;
-}
-
 bool Framebuffer::formsCopyingFeedbackLoopWith(TextureID copyTextureID,
                                                GLint copyTextureLevel,
                                                GLint copyTextureLayer) const
diff --git a/src/libANGLE/Framebuffer.h b/src/libANGLE/Framebuffer.h
index 4c550f2..6e55509 100644
--- a/src/libANGLE/Framebuffer.h
+++ b/src/libANGLE/Framebuffer.h
@@ -61,8 +61,8 @@
 class FramebufferState final : angle::NonCopyable
 {
   public:
-    FramebufferState();
-    explicit FramebufferState(const Caps &caps, FramebufferID id);
+    explicit FramebufferState(ContextID owningContextID);
+    FramebufferState(const Caps &caps, FramebufferID id, ContextID owningContextID);
     ~FramebufferState();
 
     const std::string &getLabel();
@@ -78,6 +78,7 @@
     const FramebufferAttachment *getDepthAttachment() const;
     const FramebufferAttachment *getStencilAttachment() const;
     const FramebufferAttachment *getDepthStencilAttachment() const;
+    const FramebufferAttachment *getReadPixelsAttachment(GLenum readFormat) const;
 
     const std::vector<GLenum> &getDrawBufferStates() const { return mDrawBufferStates; }
     DrawBufferMask getEnabledDrawBuffers() const { return mEnabledDrawBuffers; }
@@ -123,15 +124,24 @@
 
     bool isDefault() const;
 
+    bool hasDepthStencilFeedbackLoop() const
+    {
+        return mDepthBufferFeedbackLoop || mStencilBufferFeedbackLoop;
+    }
+
   private:
     const FramebufferAttachment *getWebGLDepthStencilAttachment() const;
     const FramebufferAttachment *getWebGLDepthAttachment() const;
     const FramebufferAttachment *getWebGLStencilAttachment() const;
-    bool updateAttachmentFeedbackLoop(size_t dirtyBit);
+
+    // Returns true if there was a change in this attachments feedback-loop-ness.
+    bool updateAttachmentFeedbackLoopAndReturnIfChanged(size_t dirtyBit);
+    void updateHasRenderingFeedbackLoop();
 
     friend class Framebuffer;
 
     FramebufferID mId;
+    ContextID mOwningContextID;
     std::string mLabel;
 
     std::vector<FramebufferAttachment> mColorAttachments;
@@ -160,6 +170,7 @@
     DrawBufferMask mDrawBufferFeedbackLoops;
     bool mDepthBufferFeedbackLoop;
     bool mStencilBufferFeedbackLoop;
+    bool mHasRenderingFeedbackLoop;
 
     // Tracks if we need to initialize the resources for each attachment.
     angle::BitSet<IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS + 2> mResourceNeedsInit;
@@ -174,7 +185,10 @@
 {
   public:
     // Constructor to build application-defined framebuffers
-    Framebuffer(const Caps &caps, rx::GLImplFactory *factory, FramebufferID id);
+    Framebuffer(const Caps &caps,
+                rx::GLImplFactory *factory,
+                FramebufferID id,
+                ContextID owningContextID);
     // Constructor to build default framebuffers for a surface and context pair
     Framebuffer(const Context *context, egl::Surface *surface, egl::Surface *readSurface);
     // Constructor to build a fake default framebuffer when surfaceless
@@ -326,9 +340,8 @@
                                 GLfloat depth,
                                 GLint stencil);
 
-    // These two methods call syncState() internally.
-    angle::Result getImplementationColorReadFormat(const Context *context, GLenum *formatOut);
-    angle::Result getImplementationColorReadType(const Context *context, GLenum *typeOut);
+    GLenum getImplementationColorReadFormat(const Context *context);
+    GLenum getImplementationColorReadType(const Context *context);
 
     angle::Result readPixels(const Context *context,
                              const Rectangle &area,
@@ -376,12 +389,12 @@
 
     bool hasResourceThatNeedsInit() const { return mState.mResourceNeedsInit.any(); }
 
-    angle::Result syncState(const Context *context) const;
+    angle::Result syncState(const Context *context, GLenum framebufferBinding) const;
 
     // Observer implementation
     void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override;
 
-    bool formsRenderingFeedbackLoopWith(const Context *context) const;
+    bool hasRenderingFeedbackLoop() const { return mState.mHasRenderingFeedbackLoop; }
     bool formsCopyingFeedbackLoopWith(TextureID copyTextureID,
                                       GLint copyTextureLevel,
                                       GLint copyTextureLayer) const;
diff --git a/src/libANGLE/FramebufferAttachment.cpp b/src/libANGLE/FramebufferAttachment.cpp
index 2848019..d458262 100644
--- a/src/libANGLE/FramebufferAttachment.cpp
+++ b/src/libANGLE/FramebufferAttachment.cpp
@@ -281,7 +281,7 @@
     mResource->setInitState(mTarget.textureIndex(), initState);
 }
 
-bool FramebufferAttachment::isBoundAsSamplerOrImage() const
+bool FramebufferAttachment::isBoundAsSamplerOrImage(ContextID contextID) const
 {
     if (mType != GL_TEXTURE)
     {
@@ -289,7 +289,8 @@
     }
 
     const gl::TextureState &textureState = getTexture()->getTextureState();
-    return textureState.isBoundAsImageTexture() || textureState.isBoundAsSamplerTexture();
+    return textureState.isBoundAsImageTexture(contextID) ||
+           textureState.isBoundAsSamplerTexture(contextID);
 }
 
 ////// FramebufferAttachmentObject Implementation //////
@@ -318,8 +319,11 @@
     // initializing entire mip levels for 2D array textures.
     if (imageIndex.getType() == TextureType::_2DArray && imageIndex.hasLayer())
     {
-        ImageIndex fullMipIndex =
-            ImageIndex::Make2DArray(imageIndex.getLevelIndex(), ImageIndex::kEntireLevel);
+        // Compute the layer count so we get a correct 2D array index.
+        const gl::Extents &size = getAttachmentSize(imageIndex);
+
+        ImageIndex fullMipIndex = ImageIndex::Make2DArrayRange(
+            imageIndex.getLevelIndex(), ImageIndex::kEntireLevel, size.depth);
         return getAttachmentImpl()->initializeContents(context, fullMipIndex);
     }
     else if (imageIndex.getType() == TextureType::_2DMultisampleArray && imageIndex.hasLayer())
diff --git a/src/libANGLE/FramebufferAttachment.h b/src/libANGLE/FramebufferAttachment.h
index 2887305..3195dc6 100644
--- a/src/libANGLE/FramebufferAttachment.h
+++ b/src/libANGLE/FramebufferAttachment.h
@@ -92,7 +92,7 @@
     GLenum getComponentType() const;
     GLenum getColorEncoding() const;
 
-    bool isBoundAsSamplerOrImage() const;
+    bool isBoundAsSamplerOrImage(ContextID contextID) const;
 
     bool isTextureWithId(TextureID textureId) const
     {
diff --git a/src/libANGLE/GLES1Renderer.cpp b/src/libANGLE/GLES1Renderer.cpp
index d1b7533..3fbf034 100644
--- a/src/libANGLE/GLES1Renderer.cpp
+++ b/src/libANGLE/GLES1Renderer.cpp
@@ -559,8 +559,8 @@
 
     *programOut = program;
 
-    programObject->attachShader(getShader(vertexShader));
-    programObject->attachShader(getShader(fragmentShader));
+    programObject->attachShader(context, getShader(vertexShader));
+    programObject->attachShader(context, getShader(fragmentShader));
 
     for (auto it : attribLocs)
     {
@@ -576,9 +576,9 @@
 
     if (!programObject->isLinked())
     {
-        GLint infoLogLength = programObject->getInfoLogLength();
+        GLint infoLogLength = programObject->getExecutable().getInfoLogLength();
         std::vector<char> infoLog(infoLogLength, 0);
-        programObject->getInfoLog(infoLogLength - 1, nullptr, infoLog.data());
+        programObject->getExecutable().getInfoLog(infoLogLength - 1, nullptr, infoLog.data());
 
         ERR() << "Internal GLES 1 shader link failed. Info log: " << infoLog.data();
         ANGLE_CHECK(context, false, "GLES1Renderer program link failed.", GL_INVALID_OPERATION);
diff --git a/src/libANGLE/HandleRangeAllocator.cpp b/src/libANGLE/HandleRangeAllocator.cpp
deleted file mode 100644
index 510d3d4..0000000
--- a/src/libANGLE/HandleRangeAllocator.cpp
+++ /dev/null
@@ -1,227 +0,0 @@
-//
-// Copyright 2016 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// HandleRangeAllocator.cpp : Implementation for HandleRangeAllocator.h
-
-#include "libANGLE/HandleRangeAllocator.h"
-
-#include <algorithm>
-#include <limits>
-#include <utility>
-
-#include "common/angleutils.h"
-#include "common/debug.h"
-
-namespace gl
-{
-
-const GLuint HandleRangeAllocator::kInvalidHandle = 0;
-
-HandleRangeAllocator::HandleRangeAllocator()
-{
-    // Simplify the code by making sure that lower_bound(id) never
-    // returns the beginning of the map, if id is valid (eg != kInvalidHandle).
-    mUsed.insert(std::make_pair(0u, 0u));
-}
-
-HandleRangeAllocator::~HandleRangeAllocator() {}
-
-GLuint HandleRangeAllocator::allocate()
-{
-    return allocateRange(1u);
-}
-
-GLuint HandleRangeAllocator::allocateAtOrAbove(GLuint wanted)
-{
-    if (wanted == 0u || wanted == 1u)
-        return allocateRange(1u);
-
-    auto current = mUsed.lower_bound(wanted);
-    auto next    = current;
-    if (current == mUsed.end() || current->first > wanted)
-    {
-        current--;
-    }
-    else
-    {
-        next++;
-    }
-
-    GLuint firstId = current->first;
-    GLuint lastId  = current->second;
-    ASSERT(wanted >= firstId);
-
-    if (wanted - 1u <= lastId)
-    {
-        // Append to current range.
-        lastId++;
-        if (lastId == 0)
-        {
-            // The increment overflowed.
-            return allocateRange(1u);
-        }
-
-        current->second = lastId;
-
-        if (next != mUsed.end() && next->first - 1u == lastId)
-        {
-            // Merge with next range.
-            current->second = next->second;
-            mUsed.erase(next);
-        }
-        return lastId;
-    }
-    else if (next != mUsed.end() && next->first - 1u == wanted)
-    {
-        // Prepend to next range.
-        GLuint lastExisting = next->second;
-        mUsed.erase(next);
-        mUsed.insert(std::make_pair(wanted, lastExisting));
-        return wanted;
-    }
-    mUsed.insert(std::make_pair(wanted, wanted));
-    return wanted;
-}
-
-GLuint HandleRangeAllocator::allocateRange(GLuint range)
-{
-    ASSERT(range != 0);
-
-    auto current = mUsed.begin();
-    auto next    = current;
-
-    while (++next != mUsed.end())
-    {
-        if (next->first - current->second > range)
-            break;
-        current = next;
-    }
-    const GLuint firstId = current->second + 1u;
-    const GLuint lastId  = firstId + range - 1u;
-
-    // deal with wraparound
-    if (firstId == 0u || lastId < firstId)
-        return kInvalidHandle;
-
-    current->second = lastId;
-
-    if (next != mUsed.end() && next->first - 1u == lastId)
-    {
-        // merge with next range
-        current->second = next->second;
-        mUsed.erase(next);
-    }
-    return firstId;
-}
-
-bool HandleRangeAllocator::markAsUsed(GLuint handle)
-{
-    ASSERT(handle);
-    auto current = mUsed.lower_bound(handle);
-    if (current != mUsed.end() && current->first == handle)
-        return false;
-
-    auto next = current;
-    --current;
-
-    if (current->second >= handle)
-        return false;
-
-    ASSERT(current->first < handle && current->second < handle);
-
-    if (current->second + 1u == handle)
-    {
-        // Append to current range.
-        current->second = handle;
-        if (next != mUsed.end() && next->first - 1u == handle)
-        {
-            // Merge with next range.
-            current->second = next->second;
-            mUsed.erase(next);
-        }
-        return true;
-    }
-    else if (next != mUsed.end() && next->first - 1u == handle)
-    {
-        // Prepend to next range.
-        GLuint lastExisting = next->second;
-        mUsed.erase(next);
-        mUsed.insert(std::make_pair(handle, lastExisting));
-        return true;
-    }
-
-    mUsed.insert(std::make_pair(handle, handle));
-    return true;
-}
-
-void HandleRangeAllocator::release(GLuint handle)
-{
-    releaseRange(handle, 1u);
-}
-
-void HandleRangeAllocator::releaseRange(GLuint first, GLuint range)
-{
-    if (range == 0u || (first == 0u && range == 1u))
-        return;
-
-    if (first == 0u)
-    {
-        first++;
-        range--;
-    }
-
-    GLuint last = first + range - 1u;
-    if (last < first)
-        last = std::numeric_limits<GLuint>::max();
-
-    while (true)
-    {
-        auto current = mUsed.lower_bound(last);
-        if (current == mUsed.end() || current->first > last)
-            --current;
-
-        if (current->second < first)
-            return;
-
-        if (current->first >= first)
-        {
-            const GLuint lastExisting = current->second;
-            mUsed.erase(current);
-            if (last < lastExisting)
-            {
-                mUsed.insert(std::make_pair(last + 1u, lastExisting));
-            }
-        }
-        else if (current->second <= last)
-        {
-            current->second = first - 1u;
-        }
-        else
-        {
-            ASSERT(current->first < first && current->second > last);
-            const GLuint lastExisting = current->second;
-            current->second           = first - 1u;
-            mUsed.insert(std::make_pair(last + 1u, lastExisting));
-        }
-    }
-}
-
-bool HandleRangeAllocator::isUsed(GLuint handle) const
-{
-    if (handle == kInvalidHandle)
-        return false;
-
-    auto current = mUsed.lower_bound(handle);
-    if (current != mUsed.end())
-    {
-        if (current->first == handle)
-            return true;
-    }
-    --current;
-    return current->second >= handle;
-}
-
-}  // namespace gl
diff --git a/src/libANGLE/HandleRangeAllocator.h b/src/libANGLE/HandleRangeAllocator.h
deleted file mode 100644
index 6a49b16..0000000
--- a/src/libANGLE/HandleRangeAllocator.h
+++ /dev/null
@@ -1,60 +0,0 @@
-//
-// Copyright 2002 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// HandleRangeAllocator.h: Defines the gl::HandleRangeAllocator class, which is used to
-// allocate contiguous ranges of GL path handles.
-
-#ifndef LIBANGLE_HANDLERANGEALLOCATOR_H_
-#define LIBANGLE_HANDLERANGEALLOCATOR_H_
-
-#include <map>
-
-#include "angle_gl.h"
-#include "common/angleutils.h"
-
-namespace gl
-{
-
-// Allocates contiguous ranges of path object handles.
-class HandleRangeAllocator final : angle::NonCopyable
-{
-  public:
-    static const GLuint kInvalidHandle;
-
-    HandleRangeAllocator();
-    ~HandleRangeAllocator();
-
-    // Allocates a new path handle.
-    GLuint allocate();
-
-    // Allocates a handle starting at or above the value of |wanted|.
-    // Note: may wrap if it starts near limit.
-    GLuint allocateAtOrAbove(GLuint wanted);
-
-    // Allocates |range| amount of contiguous paths.
-    // Returns the first id to |first_id| or |kInvalidHandle| if
-    // allocation failed.
-    GLuint allocateRange(GLuint range);
-
-    // Marks an id as used. Returns false if handle was already used.
-    bool markAsUsed(GLuint handle);
-
-    // Release handle.
-    void release(GLuint handle);
-
-    // Release a |range| amount of contiguous handles, starting from |first|
-    void releaseRange(GLuint first, GLuint range);
-
-    // Checks whether or not a resource ID is in use.
-    bool isUsed(GLuint handle) const;
-
-  private:
-    std::map<GLuint, GLuint> mUsed;
-};
-
-}  // namespace gl
-
-#endif  // LIBANGLE_HANDLERANGEALLOCATOR_H_
diff --git a/src/libANGLE/HandleRangeAllocator_unittest.cpp b/src/libANGLE/HandleRangeAllocator_unittest.cpp
deleted file mode 100644
index ffbd53a..0000000
--- a/src/libANGLE/HandleRangeAllocator_unittest.cpp
+++ /dev/null
@@ -1,275 +0,0 @@
-//
-// Copyright 2016 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// Unit tests for HandleRangeAllocator.
-//
-
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-
-#include "libANGLE/HandleRangeAllocator.h"
-
-namespace
-{
-
-class HandleRangeAllocatorTest : public testing::Test
-{
-  protected:
-    gl::HandleRangeAllocator *getAllocator() { return &mAllocator; }
-
-  private:
-    gl::HandleRangeAllocator mAllocator;
-};
-
-// Checks basic functionality: allocate, release, isUsed.
-TEST_F(HandleRangeAllocatorTest, TestBasic)
-{
-    auto *allocator = getAllocator();
-    // Check that resource 1 is not in use
-    EXPECT_FALSE(allocator->isUsed(1));
-
-    // Allocate an ID, check that it's in use.
-    GLuint id1 = allocator->allocate();
-    EXPECT_TRUE(allocator->isUsed(id1));
-
-    // Allocate another ID, check that it's in use, and different from the first
-    // one.
-    GLuint id2 = allocator->allocate();
-    EXPECT_TRUE(allocator->isUsed(id2));
-    EXPECT_NE(id1, id2);
-
-    // Free one of the IDs, check that it's not in use any more.
-    allocator->release(id1);
-    EXPECT_FALSE(allocator->isUsed(id1));
-
-    // Frees the other ID, check that it's not in use any more.
-    allocator->release(id2);
-    EXPECT_FALSE(allocator->isUsed(id2));
-}
-
-// Checks that the resource handles are re-used after being freed.
-TEST_F(HandleRangeAllocatorTest, TestAdvanced)
-{
-    auto *allocator = getAllocator();
-
-    // Allocate the highest possible ID, to make life awkward.
-    allocator->allocateAtOrAbove(~static_cast<GLuint>(0));
-
-    // Allocate a significant number of resources.
-    const unsigned int kNumResources = 100;
-    GLuint ids[kNumResources];
-    for (unsigned int i = 0; i < kNumResources; ++i)
-    {
-        ids[i] = allocator->allocate();
-        EXPECT_TRUE(allocator->isUsed(ids[i]));
-    }
-
-    // Check that a new allocation re-uses the resource we just freed.
-    GLuint id1 = ids[kNumResources / 2];
-    allocator->release(id1);
-    EXPECT_FALSE(allocator->isUsed(id1));
-    GLuint id2 = allocator->allocate();
-    EXPECT_TRUE(allocator->isUsed(id2));
-    EXPECT_EQ(id1, id2);
-}
-
-// Checks that we can choose our own ids and they won't be reused.
-TEST_F(HandleRangeAllocatorTest, MarkAsUsed)
-{
-    auto *allocator = getAllocator();
-    GLuint id       = allocator->allocate();
-    allocator->release(id);
-    EXPECT_FALSE(allocator->isUsed(id));
-    EXPECT_TRUE(allocator->markAsUsed(id));
-    EXPECT_TRUE(allocator->isUsed(id));
-    GLuint id2 = allocator->allocate();
-    EXPECT_NE(id, id2);
-    EXPECT_TRUE(allocator->markAsUsed(id2 + 1));
-    GLuint id3 = allocator->allocate();
-    // Checks our algorithm. If the algorithm changes this check should be
-    // changed.
-    EXPECT_EQ(id3, id2 + 2);
-}
-
-// Checks allocateAtOrAbove.
-TEST_F(HandleRangeAllocatorTest, AllocateAtOrAbove)
-{
-    const GLuint kOffset = 123456;
-    auto *allocator      = getAllocator();
-    GLuint id1           = allocator->allocateAtOrAbove(kOffset);
-    EXPECT_EQ(kOffset, id1);
-    GLuint id2 = allocator->allocateAtOrAbove(kOffset);
-    EXPECT_GT(id2, kOffset);
-    GLuint id3 = allocator->allocateAtOrAbove(kOffset);
-    EXPECT_GT(id3, kOffset);
-}
-
-// Checks that allocateAtOrAbove wraps around at the maximum value.
-TEST_F(HandleRangeAllocatorTest, AllocateIdAtOrAboveWrapsAround)
-{
-    const GLuint kMaxPossibleOffset = ~static_cast<GLuint>(0);
-    auto *allocator                 = getAllocator();
-    GLuint id1                      = allocator->allocateAtOrAbove(kMaxPossibleOffset);
-    EXPECT_EQ(kMaxPossibleOffset, id1);
-    GLuint id2 = allocator->allocateAtOrAbove(kMaxPossibleOffset);
-    EXPECT_EQ(1u, id2);
-    GLuint id3 = allocator->allocateAtOrAbove(kMaxPossibleOffset);
-    EXPECT_EQ(2u, id3);
-}
-
-// Checks that freeing an already freed range causes no harm.
-TEST_F(HandleRangeAllocatorTest, RedundantFreeIsIgnored)
-{
-    auto *allocator = getAllocator();
-    GLuint id1      = allocator->allocate();
-    allocator->release(0);
-    allocator->release(id1);
-    allocator->release(id1);
-    allocator->release(id1 + 1);
-    GLuint id2 = allocator->allocate();
-    GLuint id3 = allocator->allocate();
-    EXPECT_NE(id2, id3);
-    EXPECT_NE(allocator->kInvalidHandle, id2);
-    EXPECT_NE(allocator->kInvalidHandle, id3);
-}
-
-// Check allocating and releasing multiple ranges.
-TEST_F(HandleRangeAllocatorTest, allocateRange)
-{
-    const GLuint kMaxPossibleOffset = std::numeric_limits<GLuint>::max();
-
-    auto *allocator = getAllocator();
-
-    GLuint id1 = allocator->allocateRange(1);
-    EXPECT_EQ(1u, id1);
-    GLuint id2 = allocator->allocateRange(2);
-    EXPECT_EQ(2u, id2);
-    GLuint id3 = allocator->allocateRange(3);
-    EXPECT_EQ(4u, id3);
-    GLuint id4 = allocator->allocate();
-    EXPECT_EQ(7u, id4);
-    allocator->release(3);
-    GLuint id5 = allocator->allocateRange(1);
-    EXPECT_EQ(3u, id5);
-    allocator->release(5);
-    allocator->release(2);
-    allocator->release(4);
-    GLuint id6 = allocator->allocateRange(2);
-    EXPECT_EQ(4u, id6);
-    GLuint id7 = allocator->allocateAtOrAbove(kMaxPossibleOffset);
-    EXPECT_EQ(kMaxPossibleOffset, id7);
-    GLuint id8 = allocator->allocateAtOrAbove(kMaxPossibleOffset);
-    EXPECT_EQ(2u, id8);
-    GLuint id9 = allocator->allocateRange(50);
-    EXPECT_EQ(8u, id9);
-    GLuint id10 = allocator->allocateRange(50);
-    EXPECT_EQ(58u, id10);
-    // Remove all the low-numbered ids.
-    allocator->release(1);
-    allocator->release(15);
-    allocator->releaseRange(2, 107);
-    GLuint id11 = allocator->allocateRange(100);
-    EXPECT_EQ(1u, id11);
-    allocator->release(kMaxPossibleOffset);
-    GLuint id12 = allocator->allocateRange(100);
-    EXPECT_EQ(101u, id12);
-
-    GLuint id13 = allocator->allocateAtOrAbove(kMaxPossibleOffset - 2u);
-    EXPECT_EQ(kMaxPossibleOffset - 2u, id13);
-    GLuint id14 = allocator->allocateRange(3);
-    EXPECT_EQ(201u, id14);
-}
-
-// Checks that having allocated a high range doesn't interfere
-// with normal low range allocation.
-TEST_F(HandleRangeAllocatorTest, AllocateRangeEndNoEffect)
-{
-    const GLuint kMaxPossibleOffset = std::numeric_limits<GLuint>::max();
-
-    auto *allocator = getAllocator();
-    GLuint id1      = allocator->allocateAtOrAbove(kMaxPossibleOffset - 2u);
-    EXPECT_EQ(kMaxPossibleOffset - 2u, id1);
-    GLuint id3 = allocator->allocateRange(3);
-    EXPECT_EQ(1u, id3);
-    GLuint id2 = allocator->allocateRange(2);
-    EXPECT_EQ(4u, id2);
-}
-
-// Checks allocating a range that consumes the whole uint32 space.
-TEST_F(HandleRangeAllocatorTest, AllocateMax)
-{
-    const uint32_t kMaxPossibleRange = std::numeric_limits<uint32_t>::max();
-
-    auto *allocator = getAllocator();
-    GLuint id       = allocator->allocateRange(kMaxPossibleRange);
-    EXPECT_EQ(1u, id);
-    allocator->releaseRange(id, kMaxPossibleRange - 1u);
-    GLuint id2 = allocator->allocateRange(kMaxPossibleRange);
-    EXPECT_EQ(0u, id2);
-    allocator->releaseRange(id, kMaxPossibleRange);
-    GLuint id3 = allocator->allocateRange(kMaxPossibleRange);
-    EXPECT_EQ(1u, id3);
-}
-
-// Checks allocating a range that consumes the whole uint32 space
-// causes next allocation to fail.
-// Subsequently checks that once the big range is reduced new allocations
-// are possible.
-TEST_F(HandleRangeAllocatorTest, AllocateFullRange)
-{
-    const uint32_t kMaxPossibleRange = std::numeric_limits<uint32_t>::max();
-    const GLuint kFreedId            = 555u;
-    auto *allocator                  = getAllocator();
-
-    GLuint id1 = allocator->allocateRange(kMaxPossibleRange);
-    EXPECT_EQ(1u, id1);
-    GLuint id2 = allocator->allocate();
-    EXPECT_EQ(gl::HandleRangeAllocator::kInvalidHandle, id2);
-    allocator->release(kFreedId);
-    GLuint id3 = allocator->allocate();
-    EXPECT_EQ(kFreedId, id3);
-    GLuint id4 = allocator->allocate();
-    EXPECT_EQ(0u, id4);
-    allocator->release(kFreedId + 1u);
-    allocator->release(kFreedId + 4u);
-    allocator->release(kFreedId + 3u);
-    allocator->release(kFreedId + 5u);
-    allocator->release(kFreedId + 2u);
-    GLuint id5 = allocator->allocateRange(5);
-    EXPECT_EQ(kFreedId + 1u, id5);
-}
-
-// Checks that allocating a range that exceeds uint32
-// does not wrap incorrectly and fails.
-TEST_F(HandleRangeAllocatorTest, AllocateRangeNoWrapInRange)
-{
-    const uint32_t kMaxPossibleRange = std::numeric_limits<uint32_t>::max();
-    const GLuint kAllocId            = 10u;
-    auto *allocator                  = getAllocator();
-
-    GLuint id1 = allocator->allocateAtOrAbove(kAllocId);
-    EXPECT_EQ(kAllocId, id1);
-    GLuint id2 = allocator->allocateRange(kMaxPossibleRange - 5u);
-    EXPECT_EQ(0u, id2);
-    GLuint id3 = allocator->allocateRange(kMaxPossibleRange - kAllocId);
-    EXPECT_EQ(kAllocId + 1u, id3);
-}
-
-// Check special cases for 0 range allocations and zero handles.
-TEST_F(HandleRangeAllocatorTest, ZeroIdCases)
-{
-    auto *allocator = getAllocator();
-    EXPECT_FALSE(allocator->isUsed(0));
-    GLuint id1 = allocator->allocateAtOrAbove(0);
-    EXPECT_NE(0u, id1);
-    EXPECT_FALSE(allocator->isUsed(0));
-    allocator->release(0);
-    EXPECT_FALSE(allocator->isUsed(0));
-    EXPECT_TRUE(allocator->isUsed(id1));
-    allocator->release(id1);
-    EXPECT_FALSE(allocator->isUsed(id1));
-}
-
-}  // namespace
\ No newline at end of file
diff --git a/src/libANGLE/Image.cpp b/src/libANGLE/Image.cpp
index 5c1e1ef..917975d 100644
--- a/src/libANGLE/Image.cpp
+++ b/src/libANGLE/Image.cpp
@@ -225,7 +225,9 @@
       format(GL_NONE),
       size(),
       samples(),
-      sourceType(target)
+      sourceType(target),
+      colorspace(
+          static_cast<EGLenum>(attribs.get(EGL_GL_COLORSPACE, EGL_GL_COLORSPACE_DEFAULT_EXT)))
 {}
 
 ImageState::~ImageState() {}
@@ -392,7 +394,19 @@
         ANGLE_TRY(rx::GetAs<ExternalImageSibling>(mState.source)->initialize(display));
     }
 
-    mState.format  = mState.source->getAttachmentFormat(GL_NONE, mState.imageIndex);
+    mState.format = mState.source->getAttachmentFormat(GL_NONE, mState.imageIndex);
+
+    if (mState.colorspace != EGL_GL_COLORSPACE_DEFAULT_EXT)
+    {
+        GLenum nonLinearFormat = mState.format.info->sizedInternalFormat;
+        if (!gl::ColorspaceFormatOverride(mState.colorspace, &nonLinearFormat))
+        {
+            // the colorspace format is not supported
+            return egl::EglBadMatch();
+        }
+        mState.format = gl::Format(nonLinearFormat);
+    }
+
     mState.size    = mState.source->getAttachmentSize(mState.imageIndex);
     mState.samples = mState.source->getAttachmentSamples(mState.imageIndex);
 
diff --git a/src/libANGLE/Image.h b/src/libANGLE/Image.h
index d5fd646..57634a2 100644
--- a/src/libANGLE/Image.h
+++ b/src/libANGLE/Image.h
@@ -135,6 +135,7 @@
     gl::Extents size;
     size_t samples;
     EGLenum sourceType;
+    EGLenum colorspace;
 };
 
 class Image final : public RefCountObject, public LabeledObject
diff --git a/src/libANGLE/Image_unittest.cpp b/src/libANGLE/Image_unittest.cpp
index d358216..53be11e 100644
--- a/src/libANGLE/Image_unittest.cpp
+++ b/src/libANGLE/Image_unittest.cpp
@@ -111,12 +111,13 @@
 
     gl::PixelUnpackState defaultUnpackState;
 
-    EXPECT_CALL(*textureImpl, setImage(_, _, _, _, _, _, _, _))
+    EXPECT_CALL(*textureImpl, setImage(_, _, _, _, _, _, _, _, _))
         .WillOnce(Return(angle::Result::Continue))
         .RetiresOnSaturation();
-    EXPECT_EQ(angle::Result::Continue,
-              texture->setImage(nullptr, defaultUnpackState, gl::TextureTarget::_2D, 0, GL_RGBA8,
-                                gl::Extents(1, 1, 1), GL_RGBA, GL_UNSIGNED_BYTE, nullptr));
+    EXPECT_EQ(
+        angle::Result::Continue,
+        texture->setImage(nullptr, defaultUnpackState, nullptr, gl::TextureTarget::_2D, 0, GL_RGBA8,
+                          gl::Extents(1, 1, 1), GL_RGBA, GL_UNSIGNED_BYTE, nullptr));
 
     EXPECT_CALL(mockEGLFactory, createImage(_, _, _, _))
         .WillOnce(CreateMockImageImpl())
@@ -135,13 +136,14 @@
     EXPECT_CALL(*imageImpl, orphan(_, _))
         .WillOnce(Return(angle::Result::Continue))
         .RetiresOnSaturation();
-    EXPECT_CALL(*textureImpl, setImage(_, _, _, _, _, _, _, _))
+    EXPECT_CALL(*textureImpl, setImage(_, _, _, _, _, _, _, _, _))
         .WillOnce(Return(angle::Result::Continue))
         .RetiresOnSaturation();
 
-    EXPECT_EQ(angle::Result::Continue,
-              texture->setImage(nullptr, defaultUnpackState, gl::TextureTarget::_2D, 0, GL_RGBA8,
-                                gl::Extents(1, 1, 1), GL_RGBA, GL_UNSIGNED_BYTE, nullptr));
+    EXPECT_EQ(
+        angle::Result::Continue,
+        texture->setImage(nullptr, defaultUnpackState, nullptr, gl::TextureTarget::_2D, 0, GL_RGBA8,
+                          gl::Extents(1, 1, 1), GL_RGBA, GL_UNSIGNED_BYTE, nullptr));
 
     EXPECT_EQ(1u, texture->getRefCount());
     EXPECT_EQ(1u, image->getRefCount());
diff --git a/src/libANGLE/InfoLog.h b/src/libANGLE/InfoLog.h
new file mode 100644
index 0000000..7dacdce
--- /dev/null
+++ b/src/libANGLE/InfoLog.h
@@ -0,0 +1,90 @@
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// InfoLog.h: Defines the gl::InfoLog class to handle the logs generated when
+// compiling/linking shaders so useful error messages can be returned to the caller.
+
+#ifndef LIBANGLE_INFOLOG_H_
+#define LIBANGLE_INFOLOG_H_
+
+namespace gl
+{
+
+class InfoLog : angle::NonCopyable
+{
+  public:
+    InfoLog();
+    ~InfoLog();
+
+    size_t getLength() const;
+    void getLog(GLsizei bufSize, GLsizei *length, char *infoLog) const;
+
+    void appendSanitized(const char *message);
+    void reset();
+
+    // This helper class ensures we append a newline after writing a line.
+    class StreamHelper : angle::NonCopyable
+    {
+      public:
+        StreamHelper(StreamHelper &&rhs) : mStream(rhs.mStream) { rhs.mStream = nullptr; }
+
+        StreamHelper &operator=(StreamHelper &&rhs)
+        {
+            std::swap(mStream, rhs.mStream);
+            return *this;
+        }
+
+        ~StreamHelper()
+        {
+            // Write newline when destroyed on the stack
+            if (mStream)
+            {
+                (*mStream) << std::endl;
+            }
+        }
+
+        template <typename T>
+        StreamHelper &operator<<(const T &value)
+        {
+            (*mStream) << value;
+            return *this;
+        }
+
+      private:
+        friend class InfoLog;
+
+        StreamHelper(std::stringstream *stream) : mStream(stream) { ASSERT(stream); }
+
+        std::stringstream *mStream;
+    };
+
+    template <typename T>
+    StreamHelper operator<<(const T &value)
+    {
+        ensureInitialized();
+        StreamHelper helper(mLazyStream.get());
+        helper << value;
+        return helper;
+    }
+
+    std::string str() const { return mLazyStream ? mLazyStream->str() : ""; }
+
+    bool empty() const;
+
+  private:
+    void ensureInitialized()
+    {
+        if (!mLazyStream)
+        {
+            mLazyStream.reset(new std::stringstream());
+        }
+    }
+
+    std::unique_ptr<std::stringstream> mLazyStream;
+};
+
+}  // namespace gl
+
+#endif  // LIBANGLE_INFOLOG_H_
diff --git a/src/libANGLE/MemoryObject.cpp b/src/libANGLE/MemoryObject.cpp
index 05f69da..c854faf 100644
--- a/src/libANGLE/MemoryObject.cpp
+++ b/src/libANGLE/MemoryObject.cpp
@@ -15,7 +15,10 @@
 {
 
 MemoryObject::MemoryObject(rx::GLImplFactory *factory, MemoryObjectID id)
-    : RefCountObject(factory->generateSerial(), id), mImplementation(factory->createMemoryObject())
+    : RefCountObject(factory->generateSerial(), id),
+      mImplementation(factory->createMemoryObject()),
+      mImmutable(false),
+      mDedicatedMemory(false)
 {}
 
 MemoryObject::~MemoryObject() {}
@@ -25,12 +28,21 @@
     mImplementation->onDestroy(context);
 }
 
+angle::Result MemoryObject::setDedicatedMemory(const Context *context, bool dedicatedMemory)
+{
+    ANGLE_TRY(mImplementation->setDedicatedMemory(context, dedicatedMemory));
+    mDedicatedMemory = dedicatedMemory;
+    return angle::Result::Continue;
+}
+
 angle::Result MemoryObject::importFd(Context *context,
                                      GLuint64 size,
                                      HandleType handleType,
                                      GLint fd)
 {
-    return mImplementation->importFd(context, size, handleType, fd);
+    ANGLE_TRY(mImplementation->importFd(context, size, handleType, fd));
+    mImmutable = true;
+    return angle::Result::Continue;
 }
 
 angle::Result MemoryObject::importZirconHandle(Context *context,
@@ -38,7 +50,9 @@
                                                HandleType handleType,
                                                GLuint handle)
 {
-    return mImplementation->importZirconHandle(context, size, handleType, handle);
+    ANGLE_TRY(mImplementation->importZirconHandle(context, size, handleType, handle));
+    mImmutable = true;
+    return angle::Result::Continue;
 }
 
 }  // namespace gl
diff --git a/src/libANGLE/MemoryObject.h b/src/libANGLE/MemoryObject.h
index 22ead0b..3e36262 100644
--- a/src/libANGLE/MemoryObject.h
+++ b/src/libANGLE/MemoryObject.h
@@ -34,6 +34,11 @@
 
     rx::MemoryObjectImpl *getImplementation() const { return mImplementation.get(); }
 
+    bool isImmutable() const { return mImmutable; }
+
+    angle::Result setDedicatedMemory(const Context *context, bool dedicatedMemory);
+    bool isDedicatedMemory() const { return mDedicatedMemory; }
+
     angle::Result importFd(Context *context, GLuint64 size, HandleType handleType, GLint fd);
     angle::Result importZirconHandle(Context *context,
                                      GLuint64 size,
@@ -42,6 +47,9 @@
 
   private:
     std::unique_ptr<rx::MemoryObjectImpl> mImplementation;
+
+    bool mImmutable;
+    bool mDedicatedMemory;
 };
 
 }  // namespace gl
diff --git a/src/libANGLE/MemoryProgramCache.cpp b/src/libANGLE/MemoryProgramCache.cpp
index ac1ac53..7fea58c 100644
--- a/src/libANGLE/MemoryProgramCache.cpp
+++ b/src/libANGLE/MemoryProgramCache.cpp
@@ -116,7 +116,7 @@
 
     // Hash pre-link program properties.
     hashStream << program->getAttributeBindings() << program->getUniformLocationBindings()
-               << program->getFragmentInputBindings()
+               << program->getFragmentOutputLocations() << program->getFragmentOutputIndexes()
                << program->getState().getTransformFeedbackVaryingNames()
                << program->getState().getTransformFeedbackBufferMode()
                << program->getState().getOutputLocations()
diff --git a/src/libANGLE/OWNERS b/src/libANGLE/OWNERS
new file mode 100644
index 0000000..c61bc77
--- /dev/null
+++ b/src/libANGLE/OWNERS
@@ -0,0 +1,2 @@
+per-file *capture*=cnorthrop@google.com
+per-file *Capture*=cnorthrop@google.com
diff --git a/src/libANGLE/Path.cpp b/src/libANGLE/Path.cpp
deleted file mode 100644
index d14afc6..0000000
--- a/src/libANGLE/Path.cpp
+++ /dev/null
@@ -1,77 +0,0 @@
-//
-// Copyright 2002 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Path.h: Defines the gl::Path class, representing CHROMIUM_path_rendering
-// path object.
-
-#include "libANGLE/Path.h"
-#include "libANGLE/renderer/PathImpl.h"
-
-#include "common/debug.h"
-#include "common/mathutil.h"
-
-namespace gl
-{
-
-Path::Path(rx::PathImpl *impl)
-    : mPath(impl),
-      mHasData(false),
-      mEndCaps(GL_FLAT_CHROMIUM),
-      mJoinStyle(GL_MITER_REVERT_CHROMIUM),
-      mStrokeWidth(1.0f),
-      mStrokeBound(0.2f),
-      mMiterLimit(4.0f)
-{}
-
-Path::~Path()
-{
-    delete mPath;
-}
-
-angle::Result Path::setCommands(GLsizei numCommands,
-                                const GLubyte *commands,
-                                GLsizei numCoords,
-                                GLenum coordType,
-                                const void *coords)
-{
-    ANGLE_TRY(mPath->setCommands(numCommands, commands, numCoords, coordType, coords));
-
-    mHasData = true;
-
-    return angle::Result::Continue;
-}
-
-void Path::setStrokeWidth(GLfloat width)
-{
-    mStrokeWidth = width;
-    mPath->setPathParameter(GL_PATH_STROKE_WIDTH_CHROMIUM, mStrokeWidth);
-}
-
-void Path::setStrokeBound(GLfloat bound)
-{
-    mStrokeBound = clamp(bound, 0.0f, 1.0f);
-    mPath->setPathParameter(GL_PATH_STROKE_BOUND_CHROMIUM, mStrokeBound);
-}
-
-void Path::setEndCaps(GLenum type)
-{
-    mEndCaps = type;
-    mPath->setPathParameter(GL_PATH_END_CAPS_CHROMIUM, static_cast<GLfloat>(type));
-}
-
-void Path::setJoinStyle(GLenum type)
-{
-    mJoinStyle = type;
-    mPath->setPathParameter(GL_PATH_JOIN_STYLE_CHROMIUM, static_cast<GLfloat>(type));
-}
-
-void Path::setMiterLimit(GLfloat value)
-{
-    mMiterLimit = value;
-    mPath->setPathParameter(GL_PATH_MITER_LIMIT_CHROMIUM, value);
-}
-
-}  // namespace gl
diff --git a/src/libANGLE/Path.h b/src/libANGLE/Path.h
deleted file mode 100644
index c6b3ea3..0000000
--- a/src/libANGLE/Path.h
+++ /dev/null
@@ -1,71 +0,0 @@
-//
-// Copyright 2002 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Path.h: Defines the gl::Path class, representing CHROMIUM_path_rendering
-// path object.
-
-#ifndef LIBANGLE_PATH_H_
-#define LIBANGLE_PATH_H_
-
-#include "angle_gl.h"
-#include "common/angleutils.h"
-#include "libANGLE/Error.h"
-#include "libANGLE/RefCountObject.h"
-
-namespace rx
-{
-class PathImpl;
-}
-
-namespace gl
-{
-class Path final : angle::NonCopyable
-{
-  public:
-    Path(rx::PathImpl *impl);
-
-    ~Path();
-
-    angle::Result setCommands(GLsizei numCommands,
-                              const GLubyte *commands,
-                              GLsizei numCoords,
-                              GLenum coordType,
-                              const void *coords);
-
-    void setStrokeWidth(GLfloat width);
-    void setStrokeBound(GLfloat bound);
-    void setEndCaps(GLenum type);
-    void setJoinStyle(GLenum type);
-    void setMiterLimit(GLfloat value);
-
-    GLfloat getStrokeWidth() const { return mStrokeWidth; }
-    GLfloat getStrokeBound() const { return mStrokeBound; }
-    GLfloat getMiterLimit() const { return mMiterLimit; }
-    GLenum getEndCaps() const { return mEndCaps; }
-    GLenum getJoinStyle() const { return mJoinStyle; }
-
-    bool hasPathData() const { return mHasData; }
-
-    rx::PathImpl *getImplementation() const { return mPath; }
-
-  private:
-    rx::PathImpl *mPath;
-
-    // a Path object is not actually considered "a path"
-    // untill it has been specified with data. So we'll
-    // keep this flag to support this semantics.
-    bool mHasData;
-
-    GLenum mEndCaps;
-    GLenum mJoinStyle;
-    GLfloat mStrokeWidth;
-    GLfloat mStrokeBound;
-    GLfloat mMiterLimit;
-};
-
-}  // namespace gl
-
-#endif  // LIBANGLE_PATH_H_
diff --git a/src/libANGLE/Program.cpp b/src/libANGLE/Program.cpp
index e101c07..d4467b5 100644
--- a/src/libANGLE/Program.cpp
+++ b/src/libANGLE/Program.cpp
@@ -20,6 +20,7 @@
 #include "common/version.h"
 #include "compiler/translator/blocklayout.h"
 #include "libANGLE/Context.h"
+#include "libANGLE/ErrorStrings.h"
 #include "libANGLE/MemoryProgramCache.h"
 #include "libANGLE/ProgramLinkedResources.h"
 #include "libANGLE/ResourceManager.h"
@@ -650,35 +651,6 @@
     return true;
 }
 
-void WriteShaderVar(BinaryOutputStream *stream, const sh::ShaderVariable &var)
-{
-    stream->writeInt(var.type);
-    stream->writeInt(var.precision);
-    stream->writeString(var.name);
-    stream->writeString(var.mappedName);
-    stream->writeIntVector(var.arraySizes);
-    stream->writeInt(var.staticUse);
-    stream->writeInt(var.active);
-    stream->writeInt(var.binding);
-    stream->writeString(var.structName);
-    stream->writeInt(var.hasParentArrayIndex() ? var.parentArrayIndex() : -1);
-    ASSERT(var.fields.empty());
-}
-
-void LoadShaderVar(BinaryInputStream *stream, sh::ShaderVariable *var)
-{
-    var->type       = stream->readInt<GLenum>();
-    var->precision  = stream->readInt<GLenum>();
-    var->name       = stream->readString();
-    var->mappedName = stream->readString();
-    stream->readIntVector<unsigned int>(&var->arraySizes);
-    var->staticUse  = stream->readBool();
-    var->active     = stream->readBool();
-    var->binding    = stream->readInt<int>();
-    var->structName = stream->readString();
-    var->setParentArrayIndex(stream->readInt<int>());
-}
-
 void WriteShaderVariableBuffer(BinaryOutputStream *stream, const ShaderVariableBuffer &var)
 {
     stream->writeInt(var.binding);
@@ -760,19 +732,6 @@
 
     LoadShaderVariableBuffer(stream, block);
 }
-
-size_t CountUniqueBlocks(const std::vector<InterfaceBlock> &blocks)
-{
-    size_t count = 0;
-    for (const InterfaceBlock &block : blocks)
-    {
-        if (!block.isArray || block.arrayElement == 0)
-        {
-            ++count;
-        }
-    }
-    return count;
-}
 }  // anonymous namespace
 
 // Saves the linking context for later use in resolveLink().
@@ -912,6 +871,46 @@
     var->topLevelArrayStride = stream->readInt<int>();
 }
 
+void WriteShaderVar(BinaryOutputStream *stream, const sh::ShaderVariable &var)
+{
+    stream->writeInt(var.type);
+    stream->writeInt(var.precision);
+    stream->writeString(var.name);
+    stream->writeString(var.mappedName);
+    stream->writeIntVector(var.arraySizes);
+    stream->writeInt(var.staticUse);
+    stream->writeInt(var.active);
+    stream->writeInt(var.binding);
+    stream->writeString(var.structName);
+    stream->writeInt(var.hasParentArrayIndex() ? var.parentArrayIndex() : -1);
+
+    stream->writeInt(var.imageUnitFormat);
+    stream->writeInt(var.offset);
+    stream->writeInt(var.readonly);
+    stream->writeInt(var.writeonly);
+
+    ASSERT(var.fields.empty());
+}
+
+void LoadShaderVar(BinaryInputStream *stream, sh::ShaderVariable *var)
+{
+    var->type       = stream->readInt<GLenum>();
+    var->precision  = stream->readInt<GLenum>();
+    var->name       = stream->readString();
+    var->mappedName = stream->readString();
+    stream->readIntVector<unsigned int>(&var->arraySizes);
+    var->staticUse  = stream->readBool();
+    var->active     = stream->readBool();
+    var->binding    = stream->readInt<int>();
+    var->structName = stream->readString();
+    var->setParentArrayIndex(stream->readInt<int>());
+
+    var->imageUnitFormat = stream->readInt<GLenum>();
+    var->offset          = stream->readInt<int>();
+    var->readonly        = stream->readBool();
+    var->writeonly       = stream->readBool();
+}
+
 // VariableLocation implementation.
 VariableLocation::VariableLocation() : arrayIndex(0), index(kUnused), ignored(false) {}
 
@@ -1079,8 +1078,8 @@
 ProgramState::ProgramState()
     : mLabel(),
       mAttachedShaders{},
+      mAttachedShadersMarkedForDetach{},
       mTransformFeedbackBufferMode(GL_INTERLEAVED_ATTRIBS),
-      mMaxActiveAttribLocation(0),
       mDefaultUniformRange(0, 0),
       mSamplerUniformRange(0, 0),
       mImageUniformRange(0, 0),
@@ -1097,11 +1096,10 @@
       mBaseVertexLocation(-1),
       mBaseInstanceLocation(-1),
       mCachedBaseVertex(0),
-      mCachedBaseInstance(0),
-      mActiveSamplerRefCounts{}
+      mCachedBaseInstance(0)
 {
     mComputeShaderLocalSize.fill(1);
-    mActiveSamplerTypes.fill(TextureType::InvalidEnum);
+    mExecutable.setProgramState(this);
 }
 
 ProgramState::~ProgramState()
@@ -1120,14 +1118,9 @@
     return mAttachedShaders[shaderType];
 }
 
-size_t ProgramState::getUniqueUniformBlockCount() const
+size_t ProgramState::getTransformFeedbackBufferCount() const
 {
-    return CountUniqueBlocks(mUniformBlocks);
-}
-
-size_t ProgramState::getUniqueStorageBlockCount() const
-{
-    return CountUniqueBlocks(mShaderStorageBlocks);
+    return mTransformFeedbackStrides.size();
 }
 
 GLuint ProgramState::getUniformIndexFromName(const std::string &name) const
@@ -1220,13 +1213,13 @@
 {
     for (const gl::ShaderType shaderType : gl::kAllGraphicsShaderTypes)
     {
-        if (hasLinkedShaderStage(shaderType))
+        if (mExecutable.hasLinkedShaderStage(shaderType))
         {
             return shaderType;
         }
     }
 
-    if (hasLinkedShaderStage(ShaderType::Compute))
+    if (mExecutable.hasLinkedShaderStage(ShaderType::Compute))
     {
         return ShaderType::Compute;
     }
@@ -1240,13 +1233,13 @@
     {
         const gl::ShaderType shaderType = gl::kAllGraphicsShaderTypes[i];
 
-        if (hasLinkedShaderStage(shaderType))
+        if (mExecutable.hasLinkedShaderStage(shaderType))
         {
             return shaderType;
         }
     }
 
-    if (hasLinkedShaderStage(ShaderType::Compute))
+    if (mExecutable.hasLinkedShaderStage(ShaderType::Compute))
     {
         return ShaderType::Compute;
     }
@@ -1283,7 +1276,8 @@
         if (mState.mAttachedShaders[shaderType])
         {
             mState.mAttachedShaders[shaderType]->release(context);
-            mState.mAttachedShaders[shaderType] = nullptr;
+            mState.mAttachedShaders[shaderType]                = nullptr;
+            mState.mAttachedShadersMarkedForDetach[shaderType] = false;
         }
     }
 
@@ -1312,12 +1306,21 @@
     return mState.mLabel;
 }
 
-void Program::attachShader(Shader *shader)
+void Program::attachShader(const Context *context, Shader *shader)
 {
     ASSERT(mLinkResolved);
     ShaderType shaderType = shader->getType();
     ASSERT(shaderType != ShaderType::InvalidEnum);
 
+    // Since detachShader doesn't actually detach anymore, we need to do that work when attaching a
+    // new shader to make sure we don't lose track of it and free the resources.
+    if (mState.mAttachedShaders[shaderType])
+    {
+        mState.mAttachedShaders[shaderType]->release(context);
+        mState.mAttachedShaders[shaderType]                = nullptr;
+        mState.mAttachedShadersMarkedForDetach[shaderType] = false;
+    }
+
     mState.mAttachedShaders[shaderType] = shader;
     mState.mAttachedShaders[shaderType]->addRef();
 }
@@ -1329,8 +1332,19 @@
     ASSERT(shaderType != ShaderType::InvalidEnum);
 
     ASSERT(mState.mAttachedShaders[shaderType] == shader);
+
+    if (isSeparable())
+    {
+        // Don't actually detach the shader since we still need it in case this
+        // Program is part of a Program Pipeline Object. Instead, leave a mark
+        // that indicates we intended to.
+        mState.mAttachedShadersMarkedForDetach[shaderType] = true;
+        return;
+    }
+
     shader->release(context);
-    mState.mAttachedShaders[shaderType] = nullptr;
+    mState.mAttachedShaders[shaderType]                = nullptr;
+    mState.mAttachedShadersMarkedForDetach[shaderType] = false;
 }
 
 int Program::getAttachedShadersCount() const
@@ -1366,12 +1380,6 @@
     mState.mUniformLocationBindings.bindLocation(location.value, name);
 }
 
-void Program::bindFragmentInputLocation(GLint index, const char *name)
-{
-    ASSERT(mLinkResolved);
-    mFragmentInputBindings.bindLocation(index, name);
-}
-
 void Program::bindFragmentOutputLocation(GLuint index, const char *name)
 {
     mFragmentOutputLocations.bindLocation(index, name);
@@ -1382,78 +1390,29 @@
     mFragmentOutputIndexes.bindLocation(index, name);
 }
 
-BindingInfo Program::getFragmentInputBindingInfo(GLint index) const
+angle::Result Program::linkMergedVaryings(const Context *context,
+                                          const ProgramMergedVaryings &mergedVaryings)
 {
-    ASSERT(mLinkResolved);
-    BindingInfo ret;
-    ret.type  = GL_NONE;
-    ret.valid = false;
+    ShaderType tfStage =
+        mState.mAttachedShaders[ShaderType::Geometry] ? ShaderType::Geometry : ShaderType::Vertex;
+    InfoLog &infoLog = getExecutable().getInfoLog();
 
-    Shader *fragmentShader = mState.getAttachedShader(ShaderType::Fragment);
-    ASSERT(fragmentShader);
-
-    // Find the actual fragment shader varying we're interested in
-    const std::vector<sh::ShaderVariable> &inputs = fragmentShader->getInputVaryings();
-
-    for (const auto &binding : mFragmentInputBindings)
+    if (!linkValidateTransformFeedback(context->getClientVersion(), infoLog, mergedVaryings,
+                                       tfStage, context->getCaps()))
     {
-        if (binding.second != static_cast<GLuint>(index))
-            continue;
-
-        ret.valid = true;
-
-        size_t nameLengthWithoutArrayIndex;
-        unsigned int arrayIndex = ParseArrayIndex(binding.first, &nameLengthWithoutArrayIndex);
-
-        for (const auto &in : inputs)
-        {
-            if (in.name.length() == nameLengthWithoutArrayIndex &&
-                angle::BeginsWith(in.name, binding.first, nameLengthWithoutArrayIndex))
-            {
-                if (in.isArray())
-                {
-                    // The client wants to bind either "name" or "name[0]".
-                    // GL ES 3.1 spec refers to active array names with language such as:
-                    // "if the string identifies the base name of an active array, where the
-                    // string would exactly match the name of the variable if the suffix "[0]"
-                    // were appended to the string".
-                    if (arrayIndex == GL_INVALID_INDEX)
-                        arrayIndex = 0;
-
-                    ret.name = in.mappedName + "[" + ToString(arrayIndex) + "]";
-                }
-                else
-                {
-                    ret.name = in.mappedName;
-                }
-                ret.type = in.type;
-                return ret;
-            }
-        }
+        return angle::Result::Stop;
     }
 
-    return ret;
-}
+    if (!mResources->varyingPacking.collectAndPackUserVaryings(
+            infoLog, mergedVaryings, mState.getTransformFeedbackVaryingNames(), isSeparable()))
+    {
+        return angle::Result::Stop;
+    }
 
-void Program::pathFragmentInputGen(GLint index,
-                                   GLenum genMode,
-                                   GLint components,
-                                   const GLfloat *coeffs)
-{
-    ASSERT(mLinkResolved);
-    // If the location is -1 then the command is silently ignored
-    if (index == -1)
-        return;
+    gatherTransformFeedbackVaryings(mergedVaryings, tfStage);
+    mState.updateTransformFeedbackStrides();
 
-    const auto &binding = getFragmentInputBindingInfo(index);
-
-    // If the input doesn't exist then then the command is silently ignored
-    // This could happen through optimization for example, the shader translator
-    // decides that a variable is not actually being used and optimizes it away.
-    if (binding.name.empty())
-        return;
-
-    mProgram->setPathFragmentInputGen(binding.name, genMode, components, coeffs);
+    return angle::Result::Continue;
 }
 
 // The attached shaders are checked for linking errors by matching up their variables.
@@ -1463,15 +1422,16 @@
 {
     ASSERT(mLinkResolved);
     const auto &data = context->getState();
+    InfoLog &infoLog = mState.mExecutable.getInfoLog();
 
     auto *platform   = ANGLEPlatformCurrent();
     double startTime = platform->currentTime(platform);
 
     unlink();
-    mInfoLog.reset();
+    infoLog.reset();
 
     // Validate we have properly attached shaders before checking the cache.
-    if (!linkValidateShaders(mInfoLog))
+    if (!linkValidateShaders(infoLog))
     {
         return angle::Result::Continue;
     }
@@ -1479,7 +1439,8 @@
     egl::BlobCache::Key programHash = {0};
     MemoryProgramCache *cache       = context->getMemoryProgramCache();
 
-    if (cache)
+    // TODO: http://anglebug.com/4530: Enable program caching for separable programs
+    if (cache && !isSeparable())
     {
         angle::Result cacheResult = cache->getProgram(context, this, &programHash);
         ANGLE_TRY(cacheResult);
@@ -1500,27 +1461,26 @@
     unlink();
 
     // Re-link shaders after the unlink call.
-    bool result = linkValidateShaders(mInfoLog);
+    bool result = linkValidateShaders(infoLog);
     ASSERT(result);
 
-    std::unique_ptr<ProgramLinkedResources> resources;
     if (mState.mAttachedShaders[ShaderType::Compute])
     {
-        resources.reset(new ProgramLinkedResources(
+        mResources.reset(new ProgramLinkedResources(
             0, PackMode::ANGLE_RELAXED, &mState.mUniformBlocks, &mState.mUniforms,
             &mState.mShaderStorageBlocks, &mState.mBufferVariables, &mState.mAtomicCounterBuffers));
 
         GLuint combinedImageUniforms = 0u;
-        if (!linkUniforms(context->getCaps(), context->getClientVersion(), mInfoLog,
+        if (!linkUniforms(context->getCaps(), context->getClientVersion(), infoLog,
                           mState.mUniformLocationBindings, &combinedImageUniforms,
-                          &resources->unusedUniforms))
+                          &mResources->unusedUniforms))
         {
             return angle::Result::Continue;
         }
 
         GLuint combinedShaderStorageBlocks = 0u;
         if (!linkInterfaceBlocks(context->getCaps(), context->getClientVersion(),
-                                 context->getExtensions().webglCompatibility, mInfoLog,
+                                 context->getExtensions().webglCompatibility, infoLog,
                                  &combinedShaderStorageBlocks))
         {
             return angle::Result::Continue;
@@ -1534,7 +1494,7 @@
         if (combinedImageUniforms + combinedShaderStorageBlocks >
             static_cast<GLuint>(context->getCaps().maxCombinedShaderOutputResources))
         {
-            mInfoLog
+            infoLog
                 << "The sum of the number of active image uniforms, active shader storage blocks "
                    "and active fragment shader outputs exceeds "
                    "MAX_COMBINED_SHADER_OUTPUT_RESOURCES ("
@@ -1542,8 +1502,8 @@
             return angle::Result::Continue;
         }
 
-        InitUniformBlockLinker(mState, &resources->uniformBlockLinker);
-        InitShaderStorageBlockLinker(mState, &resources->shaderStorageBlockLinker);
+        InitUniformBlockLinker(mState, &mResources->uniformBlockLinker);
+        InitShaderStorageBlockLinker(mState, &mResources->shaderStorageBlockLinker);
     }
     else
     {
@@ -1560,38 +1520,38 @@
             packMode = PackMode::WEBGL_STRICT;
         }
 
-        resources.reset(new ProgramLinkedResources(
+        mResources.reset(new ProgramLinkedResources(
             static_cast<GLuint>(data.getCaps().maxVaryingVectors), packMode, &mState.mUniformBlocks,
             &mState.mUniforms, &mState.mShaderStorageBlocks, &mState.mBufferVariables,
             &mState.mAtomicCounterBuffers));
 
-        if (!linkAttributes(context, mInfoLog))
+        if (!linkAttributes(context, infoLog))
         {
             return angle::Result::Continue;
         }
 
-        if (!linkVaryings(mInfoLog))
+        if (!linkVaryings(infoLog))
         {
             return angle::Result::Continue;
         }
 
         GLuint combinedImageUniforms = 0u;
-        if (!linkUniforms(context->getCaps(), context->getClientVersion(), mInfoLog,
+        if (!linkUniforms(context->getCaps(), context->getClientVersion(), infoLog,
                           mState.mUniformLocationBindings, &combinedImageUniforms,
-                          &resources->unusedUniforms))
+                          &mResources->unusedUniforms))
         {
             return angle::Result::Continue;
         }
 
         GLuint combinedShaderStorageBlocks = 0u;
         if (!linkInterfaceBlocks(context->getCaps(), context->getClientVersion(),
-                                 context->getExtensions().webglCompatibility, mInfoLog,
+                                 context->getExtensions().webglCompatibility, infoLog,
                                  &combinedShaderStorageBlocks))
         {
             return angle::Result::Continue;
         }
 
-        if (!linkValidateGlobalNames(mInfoLog))
+        if (!mState.mExecutable.linkValidateGlobalNames(infoLog))
         {
             return angle::Result::Continue;
         }
@@ -1603,34 +1563,34 @@
             return angle::Result::Continue;
         }
 
-        const ProgramMergedVaryings &mergedVaryings = getMergedVaryings();
-
         gl::Shader *vertexShader = mState.mAttachedShaders[ShaderType::Vertex];
         if (vertexShader)
         {
             mState.mNumViews = vertexShader->getNumViews();
         }
 
-        InitUniformBlockLinker(mState, &resources->uniformBlockLinker);
-        InitShaderStorageBlockLinker(mState, &resources->shaderStorageBlockLinker);
-
-        ShaderType tfStage = mState.mAttachedShaders[ShaderType::Geometry] ? ShaderType::Geometry
-                                                                           : ShaderType::Vertex;
-
-        if (!linkValidateTransformFeedback(context->getClientVersion(), mInfoLog, mergedVaryings,
-                                           tfStage, context->getCaps()))
+        gl::Shader *fragmentShader = mState.mAttachedShaders[ShaderType::Fragment];
+        if (fragmentShader)
         {
-            return angle::Result::Continue;
+            mState.mEarlyFramentTestsOptimization =
+                fragmentShader->hasEarlyFragmentTestsOptimization();
         }
 
-        if (!resources->varyingPacking.collectAndPackUserVaryings(
-                mInfoLog, mergedVaryings, mState.getTransformFeedbackVaryingNames(), isSeparable()))
-        {
-            return angle::Result::Continue;
-        }
+        InitUniformBlockLinker(mState, &mResources->uniformBlockLinker);
+        InitShaderStorageBlockLinker(mState, &mResources->shaderStorageBlockLinker);
 
-        gatherTransformFeedbackVaryings(mergedVaryings, tfStage);
-        mState.updateTransformFeedbackStrides();
+        ProgramPipeline *programPipeline = context->getState().getProgramPipeline();
+        if (programPipeline && programPipeline->usesShaderProgram(id()))
+        {
+            const ProgramMergedVaryings &mergedVaryings =
+                context->getState().getProgramPipeline()->getMergedVaryings();
+            ANGLE_TRY(linkMergedVaryings(context, mergedVaryings));
+        }
+        else
+        {
+            const ProgramMergedVaryings &mergedVaryings = getMergedVaryings();
+            ANGLE_TRY(linkMergedVaryings(context, mergedVaryings));
+        }
     }
 
     updateLinkedShaderStages();
@@ -1638,8 +1598,7 @@
     mLinkingState.reset(new LinkingState());
     mLinkingState->linkingFromBinary = false;
     mLinkingState->programHash       = programHash;
-    mLinkingState->linkEvent         = mProgram->link(context, *resources, mInfoLog);
-    mLinkingState->resources         = std::move(resources);
+    mLinkingState->linkEvent         = mProgram->link(context, *mResources, infoLog);
     mLinkResolved                    = false;
 
     // Must be after mProgram->link() to avoid misleading the linker about output variables.
@@ -1651,7 +1610,8 @@
 
 bool Program::isLinking() const
 {
-    return (mLinkingState.get() && mLinkingState->linkEvent->isLinking());
+    return (mLinkingState.get() && mLinkingState->linkEvent &&
+            mLinkingState->linkEvent->isLinking());
 }
 
 void Program::resolveLinkImpl(const Context *context)
@@ -1689,7 +1649,8 @@
 
     // Save to the program cache.
     MemoryProgramCache *cache = context->getMemoryProgramCache();
-    if (cache &&
+    // TODO: http://anglebug.com/4530: Enable program caching for separable programs
+    if (cache && !isSeparable() &&
         (mState.mLinkedTransformFeedbackVaryings.empty() ||
          !context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled))
     {
@@ -1704,13 +1665,13 @@
 
 void Program::updateLinkedShaderStages()
 {
-    mState.mLinkedShaderStages.reset();
+    mState.mExecutable.getLinkedShaderStages().reset();
 
     for (const Shader *shader : mState.mAttachedShaders)
     {
         if (shader)
         {
-            mState.mLinkedShaderStages.set(shader->getType());
+            mState.mExecutable.getLinkedShaderStages().set(shader->getType());
         }
     }
 }
@@ -1741,48 +1702,13 @@
 
 void ProgramState::updateActiveSamplers()
 {
-    mActiveSamplerRefCounts.fill(0);
-
-    for (SamplerBinding &samplerBinding : mSamplerBindings)
-    {
-        if (samplerBinding.unreferenced)
-            continue;
-
-        for (GLint textureUnit : samplerBinding.boundTextureUnits)
-        {
-            if (++mActiveSamplerRefCounts[textureUnit] == 1)
-            {
-                mActiveSamplerTypes[textureUnit]   = samplerBinding.textureType;
-                mActiveSamplerFormats[textureUnit] = samplerBinding.format;
-            }
-            else
-            {
-                if (mActiveSamplerTypes[textureUnit] != samplerBinding.textureType)
-                {
-                    mActiveSamplerTypes[textureUnit] = TextureType::InvalidEnum;
-                }
-                if (mActiveSamplerFormats[textureUnit] != samplerBinding.format)
-                {
-                    mActiveSamplerFormats[textureUnit] = SamplerFormat::InvalidEnum;
-                }
-            }
-            mActiveSamplersMask.set(textureUnit);
-        }
-    }
+    mExecutable.mActiveSamplerRefCounts.fill(0);
+    mExecutable.updateActiveSamplers(*this);
 }
 
 void ProgramState::updateActiveImages()
 {
-    for (ImageBinding &imageBinding : mImageBindings)
-    {
-        if (imageBinding.unreferenced)
-            continue;
-
-        for (GLint imageUnit : imageBinding.boundImageUnits)
-        {
-            mActiveImagesMask.set(imageUnit);
-        }
-    }
+    mExecutable.updateActiveImages(mImageBindings);
 }
 
 void ProgramState::updateProgramInterfaceInputs()
@@ -1878,10 +1804,6 @@
 void Program::unlink()
 {
     mState.mProgramInputs.clear();
-    mState.mAttributesTypeMask.reset();
-    mState.mAttributesMask.reset();
-    mState.mActiveAttribLocationsMask.reset();
-    mState.mMaxActiveAttribLocation = 0;
     mState.mLinkedTransformFeedbackVaryings.clear();
     mState.mUniforms.clear();
     mState.mUniformLocations.clear();
@@ -1899,7 +1821,6 @@
     mState.mComputeShaderLocalSize.fill(1);
     mState.mSamplerBindings.clear();
     mState.mImageBindings.clear();
-    mState.mActiveImagesMask.reset();
     mState.mNumViews                          = -1;
     mState.mGeometryShaderInputPrimitiveType  = PrimitiveMode::Triangles;
     mState.mGeometryShaderOutputPrimitiveType = PrimitiveMode::TriangleStrip;
@@ -1910,11 +1831,13 @@
     mState.mBaseInstanceLocation              = -1;
     mState.mCachedBaseVertex                  = 0;
     mState.mCachedBaseInstance                = 0;
+    mState.mEarlyFramentTestsOptimization     = false;
 
     mValidated = false;
 
     mLinked = false;
-    mInfoLog.reset();
+
+    mState.mExecutable.reset();
 }
 
 angle::Result Program::loadBinary(const Context *context,
@@ -1922,6 +1845,7 @@
                                   const void *binary,
                                   GLsizei length)
 {
+    InfoLog &infoLog = mState.mExecutable.getInfoLog();
     ASSERT(mLinkResolved);
     unlink();
 
@@ -1931,12 +1855,12 @@
     ASSERT(binaryFormat == GL_PROGRAM_BINARY_ANGLE);
     if (binaryFormat != GL_PROGRAM_BINARY_ANGLE)
     {
-        mInfoLog << "Invalid program binary format.";
+        infoLog << "Invalid program binary format.";
         return angle::Result::Continue;
     }
 
     BinaryInputStream stream(binary, length);
-    ANGLE_TRY(deserialize(context, stream, mInfoLog));
+    ANGLE_TRY(deserialize(context, stream, infoLog));
 
     // Currently we require the full shader text to compute the program hash.
     // We could also store the binary in the internal program cache.
@@ -1949,7 +1873,7 @@
 
     mLinkingState.reset(new LinkingState());
     mLinkingState->linkingFromBinary = true;
-    mLinkingState->linkEvent         = mProgram->load(context, &stream, mInfoLog);
+    mLinkingState->linkEvent         = mProgram->load(context, &stream, infoLog);
     mLinkResolved                    = false;
 
     return angle::Result::Continue;
@@ -2066,18 +1990,6 @@
     return mRefCount;
 }
 
-int Program::getInfoLogLength() const
-{
-    ASSERT(mLinkResolved);
-    return static_cast<int>(mInfoLog.getLength());
-}
-
-void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
-{
-    ASSERT(mLinkResolved);
-    return mInfoLog.getLog(bufSize, length, infoLog);
-}
-
 void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, ShaderProgramID *shaders) const
 {
     ASSERT(mLinkResolved);
@@ -2104,13 +2016,6 @@
     return mState.getAttributeLocation(name);
 }
 
-bool Program::isAttribLocationActive(size_t attribLocation) const
-{
-    ASSERT(mLinkResolved);
-    ASSERT(attribLocation < mState.mActiveAttribLocationsMask.size());
-    return mState.mActiveAttribLocationsMask[attribLocation];
-}
-
 void Program::getActiveAttribute(GLuint index,
                                  GLsizei bufsize,
                                  GLsizei *length,
@@ -2457,10 +2362,17 @@
     ASSERT(mLinkResolved);
     return mState.mUniformLocationBindings;
 }
-const ProgramBindings &Program::getFragmentInputBindings() const
+
+const gl::ProgramAliasedBindings &Program::getFragmentOutputLocations() const
 {
     ASSERT(mLinkResolved);
-    return mFragmentInputBindings;
+    return mFragmentOutputLocations;
+}
+
+const gl::ProgramAliasedBindings &Program::getFragmentOutputIndexes() const
+{
+    ASSERT(mLinkResolved);
+    return mFragmentOutputIndexes;
 }
 
 ComponentTypeMask Program::getDrawBufferTypeMask() const
@@ -2468,16 +2380,6 @@
     ASSERT(mLinkResolved);
     return mState.mDrawBufferTypeMask;
 }
-ComponentTypeMask Program::getAttributesTypeMask() const
-{
-    ASSERT(mLinkResolved);
-    return mState.mAttributesTypeMask;
-}
-AttributesMask Program::getAttributesMask() const
-{
-    ASSERT(mLinkResolved);
-    return mState.mAttributesMask;
-}
 
 const std::vector<GLsizei> &Program::getTransformFeedbackStrides() const
 {
@@ -3069,28 +2971,30 @@
 void Program::validate(const Caps &caps)
 {
     ASSERT(mLinkResolved);
-    mInfoLog.reset();
+    mState.mExecutable.resetInfoLog();
+    InfoLog &infoLog = mState.mExecutable.getInfoLog();
 
     if (mLinked)
     {
-        mValidated = ConvertToBool(mProgram->validate(caps, &mInfoLog));
+        mValidated = ConvertToBool(mProgram->validate(caps, &infoLog));
     }
     else
     {
-        mInfoLog << "Program has not been successfully linked.";
+        infoLog << "Program has not been successfully linked.";
     }
 }
 
 bool Program::validateSamplersImpl(InfoLog *infoLog, const Caps &caps)
 {
+    const ProgramExecutable &executable = mState.mExecutable;
     ASSERT(mLinkResolved);
 
     // if any two active samplers in a program are of different types, but refer to the same
     // texture image unit, and this is the current program, then ValidateProgram will fail, and
     // DrawArrays and DrawElements will issue the INVALID_OPERATION error.
-    for (size_t textureUnit : mState.mActiveSamplersMask)
+    for (size_t textureUnit : executable.mActiveSamplersMask)
     {
-        if (mState.mActiveSamplerTypes[textureUnit] == TextureType::InvalidEnum)
+        if (executable.mActiveSamplerTypes[textureUnit] == TextureType::InvalidEnum)
         {
             if (infoLog)
             {
@@ -3339,6 +3243,12 @@
     {
         if (isSeparable())
         {
+            if (!fragmentShader && !vertexShader)
+            {
+                infoLog << "No compiled shaders.";
+                return false;
+            }
+
             ASSERT(!fragmentShader || fragmentShader->getType() == ShaderType::Fragment);
             if (fragmentShader && !fragmentShader->isCompiled())
             {
@@ -3405,7 +3315,7 @@
             if (vertexShader &&
                 (geometryShader->getShaderVersion() != vertexShader->getShaderVersion()))
             {
-                mInfoLog << "Geometry shader version does not match vertex shader version.";
+                infoLog << "Geometry shader version does not match vertex shader version.";
                 return false;
             }
             ASSERT(geometryShader->getType() == ShaderType::Geometry);
@@ -3414,7 +3324,7 @@
                 geometryShader->getGeometryShaderInputPrimitiveType();
             if (!inputPrimitive.valid())
             {
-                mInfoLog << "Input primitive type is not specified in the geometry shader.";
+                infoLog << "Input primitive type is not specified in the geometry shader.";
                 return false;
             }
 
@@ -3422,14 +3332,14 @@
                 geometryShader->getGeometryShaderOutputPrimitiveType();
             if (!outputPrimitive.valid())
             {
-                mInfoLog << "Output primitive type is not specified in the geometry shader.";
+                infoLog << "Output primitive type is not specified in the geometry shader.";
                 return false;
             }
 
             Optional<GLint> maxVertices = geometryShader->getGeometryShaderMaxVertices();
             if (!maxVertices.valid())
             {
-                mInfoLog << "'max_vertices' is not specified in the geometry shader.";
+                infoLog << "'max_vertices' is not specified in the geometry shader.";
                 return false;
             }
 
@@ -3527,7 +3437,8 @@
 
         if (previousShader)
         {
-            if (!linkValidateShaderInterfaceMatching(previousShader, currentShader, infoLog))
+            if (!linkValidateShaderInterfaceMatching(previousShader, currentShader, isSeparable(),
+                                                     infoLog))
             {
                 return false;
             }
@@ -3535,12 +3446,9 @@
         previousShader = currentShader;
     }
 
-    if (!linkValidateBuiltInVaryings(infoLog))
-    {
-        return false;
-    }
-
-    if (!linkValidateFragmentInputBindings(infoLog))
+    Shader *vertexShader   = mState.mAttachedShaders[ShaderType::Vertex];
+    Shader *fragmentShader = mState.mAttachedShaders[ShaderType::Fragment];
+    if (!linkValidateBuiltInVaryings(vertexShader, fragmentShader, infoLog))
     {
         return false;
     }
@@ -3548,56 +3456,101 @@
     return true;
 }
 
+void Program::getFilteredVaryings(const std::vector<sh::ShaderVariable> &varyings,
+                                  std::vector<const sh::ShaderVariable *> *filteredVaryingsOut)
+{
+    for (const sh::ShaderVariable &varying : varyings)
+    {
+        // Built-in varyings obey special rules
+        if (varying.isBuiltIn())
+        {
+            continue;
+        }
+
+        filteredVaryingsOut->push_back(&varying);
+    }
+}
+
+bool Program::doShaderVariablesMatch(gl::Shader *generatingShader,
+                                     gl::Shader *consumingShader,
+                                     const sh::ShaderVariable &input,
+                                     const sh::ShaderVariable &output,
+                                     bool validateGeometryShaderInputs,
+                                     bool isSeparable,
+                                     gl::InfoLog &infoLog)
+{
+    bool namesMatch     = input.name == output.name;
+    bool locationsMatch = (input.location != -1) && (input.location == output.location);
+
+    // An output variable is considered to match an input variable in the subsequent
+    // shader if:
+    // - the two variables match in name, type, and qualification; or
+    // - the two variables are declared with the same location qualifier and
+    //   match in type and qualification.
+
+    if (namesMatch || locationsMatch)
+    {
+        std::string mismatchedStructFieldName;
+        LinkMismatchError linkError = LinkValidateVaryings(
+            output, input, generatingShader->getShaderVersion(), validateGeometryShaderInputs,
+            isSeparable, &mismatchedStructFieldName);
+        if (linkError != LinkMismatchError::NO_MISMATCH)
+        {
+            LogLinkMismatch(infoLog, input.name, "varying", linkError, mismatchedStructFieldName,
+                            generatingShader->getType(), consumingShader->getType());
+            return false;
+        }
+
+        return true;
+    }
+
+    return false;
+}
+
 // [OpenGL ES 3.1] Chapter 7.4.1 "Shader Interface Matching" Page 91
 // TODO(jiawei.shao@intel.com): add validation on input/output blocks matching
 bool Program::linkValidateShaderInterfaceMatching(gl::Shader *generatingShader,
                                                   gl::Shader *consumingShader,
-                                                  gl::InfoLog &infoLog) const
+                                                  bool isSeparable,
+                                                  gl::InfoLog &infoLog)
 {
     ASSERT(generatingShader->getShaderVersion() == consumingShader->getShaderVersion());
 
     const std::vector<sh::ShaderVariable> &outputVaryings = generatingShader->getOutputVaryings();
     const std::vector<sh::ShaderVariable> &inputVaryings  = consumingShader->getInputVaryings();
-
+    std::vector<const sh::ShaderVariable *> filteredInputVaryings;
+    std::vector<const sh::ShaderVariable *> filteredOutputVaryings;
     bool validateGeometryShaderInputs = consumingShader->getType() == ShaderType::Geometry;
 
-    for (const sh::ShaderVariable &input : inputVaryings)
+    getFilteredVaryings(inputVaryings, &filteredInputVaryings);
+    getFilteredVaryings(outputVaryings, &filteredOutputVaryings);
+
+    // Separable programs require the number of inputs and outputs match
+    if (isSeparable && filteredInputVaryings.size() < filteredOutputVaryings.size())
     {
-        bool matched = false;
+        infoLog << GetShaderTypeString(consumingShader->getType())
+                << " does not consume all varyings generated by "
+                << GetShaderTypeString(generatingShader->getType());
+        return false;
+    }
+    if (isSeparable && filteredInputVaryings.size() > filteredOutputVaryings.size())
+    {
+        infoLog << GetShaderTypeString(generatingShader->getType())
+                << " does not generate all varyings consumed by "
+                << GetShaderTypeString(consumingShader->getType());
+        return false;
+    }
 
-        // Built-in varyings obey special rules
-        if (input.isBuiltIn())
+    // All inputs must match all outputs
+    for (const sh::ShaderVariable *input : filteredInputVaryings)
+    {
+        bool match = false;
+        for (const sh::ShaderVariable *output : filteredOutputVaryings)
         {
-            continue;
-        }
-
-        // An output variable is considered to match an input variable in the subsequent
-        // shader if:
-        // - the two variables match in name, type, and qualification; or
-        // - the two variables are declared with the same location qualifier and
-        //   match in type and qualification.
-        for (const sh::ShaderVariable &output : outputVaryings)
-        {
-            bool namesMatch     = input.name == output.name;
-            bool locationsMatch = (input.location != -1) && (input.location == output.location);
-
-            if (namesMatch || locationsMatch)
+            if (doShaderVariablesMatch(generatingShader, consumingShader, *input, *output,
+                                       validateGeometryShaderInputs, isSeparable, infoLog))
             {
-                ASSERT(!output.isBuiltIn());
-
-                std::string mismatchedStructFieldName;
-                LinkMismatchError linkError =
-                    LinkValidateVaryings(output, input, generatingShader->getShaderVersion(),
-                                         validateGeometryShaderInputs, &mismatchedStructFieldName);
-                if (linkError != LinkMismatchError::NO_MISMATCH)
-                {
-                    LogLinkMismatch(infoLog, input.name, "varying", linkError,
-                                    mismatchedStructFieldName, generatingShader->getType(),
-                                    consumingShader->getType());
-                    return false;
-                }
-
-                matched = true;
+                match = true;
                 break;
             }
         }
@@ -3605,55 +3558,15 @@
         // We permit unmatched, unreferenced varyings. Note that this specifically depends on
         // whether the input is statically used - a statically used input should fail this test even
         // if it is not active. GLSL ES 3.00.6 section 4.3.10.
-        if (!matched && input.staticUse)
+        if (!match && input->staticUse)
         {
-            infoLog << GetShaderTypeString(consumingShader->getType()) << " varying " << input.name
+            infoLog << GetShaderTypeString(consumingShader->getType()) << " varying " << input->name
                     << " does not match any " << GetShaderTypeString(generatingShader->getType())
                     << " varying";
             return false;
         }
     }
 
-    // TODO(jmadill): verify no unmatched output varyings?
-
-    return true;
-}
-
-bool Program::linkValidateFragmentInputBindings(gl::InfoLog &infoLog) const
-{
-    std::map<GLuint, std::string> staticFragmentInputLocations;
-
-    Shader *fragmentShader = mState.mAttachedShaders[ShaderType::Fragment];
-
-    if (!fragmentShader)
-    {
-        return true;
-    }
-
-    for (const sh::ShaderVariable &input : fragmentShader->getInputVaryings())
-    {
-        if (input.isBuiltIn() || !input.staticUse)
-        {
-            continue;
-        }
-
-        const auto inputBinding = mFragmentInputBindings.getBinding(input);
-        if (inputBinding == -1)
-            continue;
-
-        const auto it = staticFragmentInputLocations.find(inputBinding);
-        if (it == std::end(staticFragmentInputLocations))
-        {
-            staticFragmentInputLocations.insert(std::make_pair(inputBinding, input.name));
-        }
-        else
-        {
-            infoLog << "Binding for fragment input " << input.name << " conflicts with "
-                    << it->second;
-            return false;
-        }
-    }
-
     return true;
 }
 
@@ -3922,8 +3835,8 @@
         }
     }
 
-    ASSERT(mState.mAttributesTypeMask.none());
-    ASSERT(mState.mAttributesMask.none());
+    ASSERT(mState.mExecutable.mAttributesTypeMask.none());
+    ASSERT(mState.mExecutable.mAttributesMask.none());
 
     // Prune inactive attributes. This step is only needed on shaderVersion >= 300 since on earlier
     // shader versions we're only processing active attributes to begin with.
@@ -3955,15 +3868,16 @@
             // Built-in active program inputs don't have a bound attribute.
             if (!attribute.isBuiltIn())
             {
-                mState.mActiveAttribLocationsMask.set(location);
-                mState.mMaxActiveAttribLocation =
-                    std::max(mState.mMaxActiveAttribLocation, location + 1);
+                mState.mExecutable.mActiveAttribLocationsMask.set(location);
+                mState.mExecutable.mMaxActiveAttribLocation =
+                    std::max(mState.mExecutable.mMaxActiveAttribLocation, location + 1);
 
                 ComponentType componentType =
                     GLenumToComponentType(VariableComponentType(attribute.type));
 
-                SetComponentTypeMask(componentType, location, &mState.mAttributesTypeMask);
-                mState.mAttributesMask.set(location);
+                SetComponentTypeMask(componentType, location,
+                                     &mState.mExecutable.mAttributesTypeMask);
+                mState.mExecutable.mAttributesMask.set(location);
 
                 location++;
             }
@@ -4127,6 +4041,7 @@
                                                 const sh::ShaderVariable &inputVarying,
                                                 int shaderVersion,
                                                 bool validateGeometryShaderInputVarying,
+                                                bool isSeparable,
                                                 std::string *mismatchedStructFieldName)
 {
     if (validateGeometryShaderInputVarying)
@@ -4151,14 +4066,22 @@
 
     // Skip the validation on the array sizes between a vertex output varying and a geometry input
     // varying as it has been done before.
+    bool validatePrecision = isSeparable && (shaderVersion > 100);
     LinkMismatchError linkError =
-        LinkValidateVariablesBase(outputVarying, inputVarying, false,
+        LinkValidateVariablesBase(outputVarying, inputVarying, validatePrecision,
                                   !validateGeometryShaderInputVarying, mismatchedStructFieldName);
     if (linkError != LinkMismatchError::NO_MISMATCH)
     {
         return linkError;
     }
 
+    // Explicit locations must match if the names match.
+    if ((outputVarying.name == inputVarying.name) &&
+        (outputVarying.location != inputVarying.location))
+    {
+        return LinkMismatchError::LOCATION_MISMATCH;
+    }
+
     if (!sh::InterpolationTypesMatch(outputVarying.interpolation, inputVarying.interpolation))
     {
         return LinkMismatchError::INTERPOLATION_TYPE_MISMATCH;
@@ -4172,11 +4095,10 @@
     return LinkMismatchError::NO_MISMATCH;
 }
 
-bool Program::linkValidateBuiltInVaryings(InfoLog &infoLog) const
+bool Program::linkValidateBuiltInVaryings(Shader *vertexShader,
+                                          Shader *fragmentShader,
+                                          InfoLog &infoLog)
 {
-    Shader *vertexShader   = mState.mAttachedShaders[ShaderType::Vertex];
-    Shader *fragmentShader = mState.mAttachedShaders[ShaderType::Fragment];
-
     if (!vertexShader || !fragmentShader)
     {
         // We can't validate an interface if we don't have both a producer and a consumer
@@ -4365,116 +4287,6 @@
     return true;
 }
 
-bool Program::linkValidateGlobalNames(InfoLog &infoLog) const
-{
-    std::unordered_map<std::string, const sh::ShaderVariable *> uniformMap;
-    using BlockAndFieldPair = std::pair<const sh::InterfaceBlock *, const sh::ShaderVariable *>;
-    std::unordered_map<std::string, std::vector<BlockAndFieldPair>> uniformBlockFieldMap;
-
-    for (ShaderType shaderType : kAllGraphicsShaderTypes)
-    {
-        Shader *shader = mState.mAttachedShaders[shaderType];
-        if (!shader)
-        {
-            continue;
-        }
-
-        // Build a map of Uniforms
-        const std::vector<sh::ShaderVariable> uniforms = shader->getUniforms();
-        for (const auto &uniform : uniforms)
-        {
-            uniformMap[uniform.name] = &uniform;
-        }
-
-        // Build a map of Uniform Blocks
-        // This will also detect any field name conflicts between Uniform Blocks without instance
-        // names
-        const std::vector<sh::InterfaceBlock> &uniformBlocks = shader->getUniformBlocks();
-        for (const auto &uniformBlock : uniformBlocks)
-        {
-            // Only uniform blocks without an instance name can create a conflict with their field
-            // names
-            if (!uniformBlock.instanceName.empty())
-            {
-                continue;
-            }
-
-            for (const auto &field : uniformBlock.fields)
-            {
-                if (!uniformBlockFieldMap.count(field.name))
-                {
-                    // First time we've seen this uniform block field name, so add the
-                    // (Uniform Block, Field) pair immediately since there can't be a conflict yet
-                    BlockAndFieldPair blockAndFieldPair(&uniformBlock, &field);
-                    std::vector<BlockAndFieldPair> newUniformBlockList;
-                    newUniformBlockList.push_back(blockAndFieldPair);
-                    uniformBlockFieldMap[field.name] = newUniformBlockList;
-                    continue;
-                }
-
-                // We've seen this name before.
-                // We need to check each of the uniform blocks that contain a field with this name
-                // to see if there's a conflict or not.
-                std::vector<BlockAndFieldPair> prevBlockFieldPairs =
-                    uniformBlockFieldMap[field.name];
-                for (const auto &prevBlockFieldPair : prevBlockFieldPairs)
-                {
-                    const sh::InterfaceBlock *prevUniformBlock      = prevBlockFieldPair.first;
-                    const sh::ShaderVariable *prevUniformBlockField = prevBlockFieldPair.second;
-
-                    if (uniformBlock.isSameInterfaceBlockAtLinkTime(*prevUniformBlock))
-                    {
-                        // The same uniform block should, by definition, contain the same field name
-                        continue;
-                    }
-
-                    // The uniform blocks don't match, so check if the necessary field properties
-                    // also match
-                    if ((field.name == prevUniformBlockField->name) &&
-                        (field.type == prevUniformBlockField->type) &&
-                        (field.precision == prevUniformBlockField->precision))
-                    {
-                        infoLog << "Name conflicts between uniform block field names: "
-                                << field.name;
-                        return false;
-                    }
-                }
-
-                // No conflict, so record this pair
-                BlockAndFieldPair blockAndFieldPair(&uniformBlock, &field);
-                uniformBlockFieldMap[field.name].push_back(blockAndFieldPair);
-            }
-        }
-    }
-
-    // Validate no uniform names conflict with attribute names
-    gl::Shader *vertexShader = mState.mAttachedShaders[ShaderType::Vertex];
-    if (vertexShader)
-    {
-        for (const auto &attrib : vertexShader->getActiveAttributes())
-        {
-            if (uniformMap.count(attrib.name))
-            {
-                infoLog << "Name conflicts between a uniform and an attribute: " << attrib.name;
-                return false;
-            }
-        }
-    }
-
-    // Validate no Uniform Block fields conflict with other Uniforms
-    for (const auto &uniformBlockField : uniformBlockFieldMap)
-    {
-        const std::string &fieldName = uniformBlockField.first;
-        if (uniformMap.count(fieldName))
-        {
-            infoLog << "Name conflicts between a uniform and a uniform block field: " << fieldName;
-            return false;
-        }
-    }
-
-    return true;
-}
-
 void Program::gatherTransformFeedbackVaryings(const ProgramMergedVaryings &varyings,
                                               ShaderType stage)
 {
@@ -4733,6 +4545,7 @@
                                   GLuint combinedImageUniformsCount,
                                   GLuint combinedShaderStorageBlocksCount)
 {
+    InfoLog &infoLog       = mState.mExecutable.getInfoLog();
     Shader *fragmentShader = mState.mAttachedShaders[ShaderType::Fragment];
 
     ASSERT(mState.mOutputVariableTypes.empty());
@@ -4790,7 +4603,7 @@
                 mState.mActiveOutputVariables.count() >
             static_cast<GLuint>(caps.maxCombinedShaderOutputResources))
         {
-            mInfoLog
+            infoLog
                 << "The sum of the number of active image uniforms, active shader storage blocks "
                    "and active fragment shader outputs exceeds "
                    "MAX_COMBINED_SHADER_OUTPUT_RESOURCES ("
@@ -4864,8 +4677,8 @@
             }
             if (outputLocations[location].used())
             {
-                mInfoLog << "Location of variable " << outputVariable.name
-                         << " conflicts with another variable.";
+                infoLog << "Location of variable " << outputVariable.name
+                        << " conflicts with another variable.";
                 return false;
             }
             outputLocations[location] = locationInfo;
@@ -4904,8 +4717,8 @@
         if (FindUsedOutputLocation(outputLocations, baseLocation, elementCount, reservedLocations,
                                    outputVariableIndex))
         {
-            mInfoLog << "Location of variable " << outputVariable.name
-                     << " conflicts with another variable.";
+            infoLog << "Location of variable " << outputVariable.name
+                    << " conflicts with another variable.";
             return false;
         }
         AssignOutputLocations(outputLocations, baseLocation, elementCount, reservedLocations,
@@ -4972,8 +4785,8 @@
             // "if the explicit binding assignments do not leave enough space for the linker to
             // automatically assign a location for a varying out array, which requires multiple
             // contiguous locations."
-            mInfoLog << "Could not fit output variable into available locations: "
-                     << outputVariable.name;
+            infoLog << "Could not fit output variable into available locations: "
+                    << outputVariable.name;
             return false;
         }
     }
@@ -5040,24 +4853,26 @@
         boundTextureUnits[arrayIndex + locationInfo.arrayIndex] = newTextureUnit;
 
         // Update the reference counts.
-        uint32_t &oldRefCount = mState.mActiveSamplerRefCounts[oldTextureUnit];
-        uint32_t &newRefCount = mState.mActiveSamplerRefCounts[newTextureUnit];
+        uint32_t &oldRefCount = mState.mExecutable.mActiveSamplerRefCounts[oldTextureUnit];
+        uint32_t &newRefCount = mState.mExecutable.mActiveSamplerRefCounts[newTextureUnit];
         ASSERT(oldRefCount > 0);
         ASSERT(newRefCount < std::numeric_limits<uint32_t>::max());
         oldRefCount--;
         newRefCount++;
 
         // Check for binding type change.
-        TextureType &newSamplerType     = mState.mActiveSamplerTypes[newTextureUnit];
-        TextureType &oldSamplerType     = mState.mActiveSamplerTypes[oldTextureUnit];
-        SamplerFormat &newSamplerFormat = mState.mActiveSamplerFormats[newTextureUnit];
-        SamplerFormat &oldSamplerFormat = mState.mActiveSamplerFormats[oldTextureUnit];
+        TextureType &newSamplerType     = mState.mExecutable.mActiveSamplerTypes[newTextureUnit];
+        TextureType &oldSamplerType     = mState.mExecutable.mActiveSamplerTypes[oldTextureUnit];
+        SamplerFormat &newSamplerFormat = mState.mExecutable.mActiveSamplerFormats[newTextureUnit];
+        SamplerFormat &oldSamplerFormat = mState.mExecutable.mActiveSamplerFormats[oldTextureUnit];
 
         if (newRefCount == 1)
         {
             newSamplerType   = samplerBinding.textureType;
             newSamplerFormat = samplerBinding.format;
-            mState.mActiveSamplersMask.set(newTextureUnit);
+            mState.mExecutable.mActiveSamplersMask.set(newTextureUnit);
+            mState.mExecutable.mActiveSamplerShaderBits[newTextureUnit] =
+                mState.mUniforms[locationInfo.index].activeShaders();
         }
         else
         {
@@ -5077,7 +4892,7 @@
         {
             oldSamplerType   = TextureType::InvalidEnum;
             oldSamplerFormat = SamplerFormat::InvalidEnum;
-            mState.mActiveSamplersMask.reset(oldTextureUnit);
+            mState.mExecutable.mActiveSamplersMask.reset(oldTextureUnit);
         }
         else
         {
@@ -5103,44 +4918,7 @@
 
 void ProgramState::setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex)
 {
-    bool foundBinding         = false;
-    TextureType foundType     = TextureType::InvalidEnum;
-    SamplerFormat foundFormat = SamplerFormat::InvalidEnum;
-
-    for (const SamplerBinding &binding : mSamplerBindings)
-    {
-        if (binding.unreferenced)
-            continue;
-
-        // A conflict exists if samplers of different types are sourced by the same texture unit.
-        // We need to check all bound textures to detect this error case.
-        for (GLuint textureUnit : binding.boundTextureUnits)
-        {
-            if (textureUnit == textureUnitIndex)
-            {
-                if (!foundBinding)
-                {
-                    foundBinding = true;
-                    foundType    = binding.textureType;
-                    foundFormat  = binding.format;
-                }
-                else
-                {
-                    if (foundType != binding.textureType)
-                    {
-                        foundType = TextureType::InvalidEnum;
-                    }
-                    if (foundFormat != binding.format)
-                    {
-                        foundFormat = SamplerFormat::InvalidEnum;
-                    }
-                }
-            }
-        }
-    }
-
-    mActiveSamplerTypes[textureUnitIndex]   = foundType;
-    mActiveSamplerFormats[textureUnitIndex] = foundFormat;
+    mExecutable.setSamplerUniformTextureTypeAndFormat(textureUnitIndex, mSamplerBindings);
 }
 
 template <typename T>
@@ -5284,15 +5062,14 @@
     stream.writeInt(mState.mGeometryShaderMaxVertices);
 
     stream.writeInt(mState.mNumViews);
-
-    stream.writeInt(mState.mMaxActiveAttribLocation);
+    stream.writeInt(mState.mEarlyFramentTestsOptimization);
 
     static_assert(MAX_VERTEX_ATTRIBS * 2 <= sizeof(uint32_t) * 8,
                   "All bits of mAttributesTypeMask types and mask fit into 32 bits each");
-    stream.writeInt(static_cast<int>(mState.mAttributesTypeMask.to_ulong()));
-    stream.writeInt(static_cast<int>(mState.mAttributesMask.to_ulong()));
-
-    stream.writeInt(mState.getActiveAttribLocationsMask().to_ulong());
+    stream.writeInt(static_cast<int>(mState.mExecutable.mAttributesTypeMask.to_ulong()));
+    stream.writeInt(static_cast<int>(mState.mExecutable.mAttributesMask.to_ulong()));
+    stream.writeInt(mState.mExecutable.getActiveAttribLocationsMask().to_ulong());
+    stream.writeInt(mState.mExecutable.mMaxActiveAttribLocation);
 
     stream.writeInt(mState.getProgramInputs().size());
     for (const sh::ShaderVariable &attrib : mState.getProgramInputs())
@@ -5311,6 +5088,8 @@
         stream.writeInt(uniform.bufferIndex);
         WriteBlockMemberInfo(&stream, uniform.blockInfo);
 
+        stream.writeIntVector(uniform.outerArraySizes);
+
         // Active shader info
         for (ShaderType shaderType : gl::AllShaderTypes())
         {
@@ -5437,7 +5216,7 @@
     stream.writeInt(mState.getAtomicCounterUniformRange().low());
     stream.writeInt(mState.getAtomicCounterUniformRange().high());
 
-    stream.writeInt(mState.getLinkedShaderStages().to_ulong());
+    stream.writeInt(mState.mExecutable.getLinkedShaderStages().to_ulong());
 
     mProgram->save(context, &stream);
 
@@ -5483,18 +5262,16 @@
     mState.mGeometryShaderInvocations         = stream.readInt<int>();
     mState.mGeometryShaderMaxVertices         = stream.readInt<int>();
 
-    mState.mNumViews = stream.readInt<int>();
-
-    mState.mMaxActiveAttribLocation = stream.readInt<unsigned int>();
+    mState.mNumViews                      = stream.readInt<int>();
+    mState.mEarlyFramentTestsOptimization = stream.readInt<bool>();
 
     static_assert(MAX_VERTEX_ATTRIBS * 2 <= sizeof(uint32_t) * 8,
-                  "All bits of mAttributesTypeMask types and mask fit into 32 bits each");
-    mState.mAttributesTypeMask = gl::ComponentTypeMask(stream.readInt<uint32_t>());
-    mState.mAttributesMask     = stream.readInt<gl::AttributesMask>();
-
-    static_assert(MAX_VERTEX_ATTRIBS <= sizeof(unsigned long) * 8,
-                  "Too many vertex attribs for mask");
-    mState.mActiveAttribLocationsMask = stream.readInt<gl::AttributesMask>();
+                  "Too many vertex attribs for mask: All bits of mAttributesTypeMask types and "
+                  "mask fit into 32 bits each");
+    mState.mExecutable.mAttributesTypeMask = gl::ComponentTypeMask(stream.readInt<uint32_t>());
+    mState.mExecutable.mAttributesMask     = stream.readInt<gl::AttributesMask>();
+    mState.mExecutable.mActiveAttribLocationsMask = stream.readInt<gl::AttributesMask>();
+    mState.mExecutable.mMaxActiveAttribLocation   = stream.readInt<unsigned int>();
 
     unsigned int attribCount = stream.readInt<unsigned int>();
     ASSERT(mState.mProgramInputs.empty());
@@ -5516,6 +5293,8 @@
         uniform.bufferIndex = stream.readInt<int>();
         LoadBlockMemberInfo(&stream, &uniform.blockInfo);
 
+        stream.readIntVector<unsigned int>(&uniform.outerArraySizes);
+
         uniform.typeInfo = &GetUniformTypeInfo(uniform.type);
 
         // Active shader info
@@ -5691,7 +5470,7 @@
 
     static_assert(static_cast<unsigned long>(ShaderType::EnumCount) <= sizeof(unsigned long) * 8,
                   "Too many shader types");
-    mState.mLinkedShaderStages = ShaderBitSet(stream.readInt<uint8_t>());
+    mState.mExecutable.getLinkedShaderStages() = ShaderBitSet(stream.readInt<uint8_t>());
 
     if (!mState.mAttachedShaders[ShaderType::Compute])
     {
diff --git a/src/libANGLE/Program.h b/src/libANGLE/Program.h
index 60debd8..11dcc49 100644
--- a/src/libANGLE/Program.h
+++ b/src/libANGLE/Program.h
@@ -28,6 +28,9 @@
 #include "libANGLE/Constants.h"
 #include "libANGLE/Debug.h"
 #include "libANGLE/Error.h"
+#include "libANGLE/InfoLog.h"
+#include "libANGLE/ProgramExecutable.h"
+#include "libANGLE/ProgramLinkedResources.h"
 #include "libANGLE/RefCountObject.h"
 #include "libANGLE/Uniform.h"
 #include "libANGLE/angletypes.h"
@@ -48,7 +51,6 @@
 class Context;
 struct Extensions;
 class Framebuffer;
-class InfoLog;
 class Shader;
 class ShaderProgramManager;
 class State;
@@ -84,79 +86,6 @@
     MATRIX_PACKING_MISMATCH,
 };
 
-class InfoLog : angle::NonCopyable
-{
-  public:
-    InfoLog();
-    ~InfoLog();
-
-    size_t getLength() const;
-    void getLog(GLsizei bufSize, GLsizei *length, char *infoLog) const;
-
-    void appendSanitized(const char *message);
-    void reset();
-
-    // This helper class ensures we append a newline after writing a line.
-    class StreamHelper : angle::NonCopyable
-    {
-      public:
-        StreamHelper(StreamHelper &&rhs) : mStream(rhs.mStream) { rhs.mStream = nullptr; }
-
-        StreamHelper &operator=(StreamHelper &&rhs)
-        {
-            std::swap(mStream, rhs.mStream);
-            return *this;
-        }
-
-        ~StreamHelper()
-        {
-            // Write newline when destroyed on the stack
-            if (mStream)
-            {
-                (*mStream) << std::endl;
-            }
-        }
-
-        template <typename T>
-        StreamHelper &operator<<(const T &value)
-        {
-            (*mStream) << value;
-            return *this;
-        }
-
-      private:
-        friend class InfoLog;
-
-        StreamHelper(std::stringstream *stream) : mStream(stream) { ASSERT(stream); }
-
-        std::stringstream *mStream;
-    };
-
-    template <typename T>
-    StreamHelper operator<<(const T &value)
-    {
-        ensureInitialized();
-        StreamHelper helper(mLazyStream.get());
-        helper << value;
-        return helper;
-    }
-
-    std::string str() const { return mLazyStream ? mLazyStream->str() : ""; }
-
-    bool empty() const;
-
-  private:
-    void ensureInitialized()
-    {
-        if (!mLazyStream)
-        {
-            mLazyStream.reset(new std::stringstream());
-        }
-    }
-
-    std::unique_ptr<std::stringstream> mLazyStream;
-};
-
 void LogLinkMismatch(InfoLog &infoLog,
                      const std::string &variableName,
                      const char *variableType,
@@ -170,6 +99,9 @@
 void WriteBlockMemberInfo(BinaryOutputStream *stream, const sh::BlockMemberInfo &var);
 void LoadBlockMemberInfo(BinaryInputStream *stream, sh::BlockMemberInfo *var);
 
+void WriteShaderVar(BinaryOutputStream *stream, const sh::ShaderVariable &var);
+void LoadShaderVar(BinaryInputStream *stream, sh::ShaderVariable *var);
+
 // Struct used for correlating uniforms/elements of uniform arrays to handles
 struct VariableLocation
 {
@@ -219,28 +151,6 @@
     bool valid;
 };
 
-// This small structure encapsulates binding sampler uniforms to active GL textures.
-struct SamplerBinding
-{
-    SamplerBinding(TextureType textureTypeIn,
-                   SamplerFormat formatIn,
-                   size_t elementCount,
-                   bool unreferenced);
-    SamplerBinding(const SamplerBinding &other);
-    ~SamplerBinding();
-
-    // Necessary for retrieving active textures from the GL state.
-    TextureType textureType;
-
-    SamplerFormat format;
-
-    // List of all textures bound to this sampler, of type textureType.
-    std::vector<GLuint> boundTextureUnits;
-
-    // A note if this sampler is an unreferenced uniform.
-    bool unreferenced;
-};
-
 // A varying with tranform feedback enabled. If it's an array, either the whole array or one of its
 // elements specified by 'arrayIndex' can set to be enabled.
 struct TransformFeedbackVarying : public sh::ShaderVariable
@@ -280,19 +190,6 @@
     GLuint arrayIndex;
 };
 
-struct ImageBinding
-{
-    ImageBinding(size_t count);
-    ImageBinding(GLuint imageUnit, size_t count, bool unreferenced);
-    ImageBinding(const ImageBinding &other);
-    ~ImageBinding();
-
-    std::vector<GLuint> boundImageUnits;
-
-    // A note if this image unit is an unreferenced uniform.
-    bool unreferenced;
-};
-
 struct ProgramBinding
 {
     ProgramBinding() : location(GL_INVALID_INDEX), aliased(false) {}
@@ -371,12 +268,6 @@
         return mActiveUniformBlockBindings;
     }
     const std::vector<sh::ShaderVariable> &getProgramInputs() const { return mProgramInputs; }
-    const AttributesMask &getActiveAttribLocationsMask() const
-    {
-        return mActiveAttribLocationsMask;
-    }
-    const AttributesMask &getNonBuiltinAttribLocationsMask() const { return mAttributesMask; }
-    unsigned int getMaxActiveAttribLocation() const { return mMaxActiveAttribLocation; }
     DrawBufferMask getActiveOutputVariables() const { return mActiveOutputVariables; }
     const std::vector<sh::ShaderVariable> &getOutputVariables() const { return mOutputVariables; }
     const std::vector<VariableLocation> &getOutputLocations() const { return mOutputLocations; }
@@ -399,7 +290,6 @@
     const RangeUI &getSamplerUniformRange() const { return mSamplerUniformRange; }
     const RangeUI &getImageUniformRange() const { return mImageUniformRange; }
     const RangeUI &getAtomicCounterUniformRange() const { return mAtomicCounterUniformRange; }
-    const ComponentTypeMask &getAttributesTypeMask() const { return mAttributesTypeMask; }
 
     const std::vector<TransformFeedbackVarying> &getLinkedTransformFeedbackVaryings() const
     {
@@ -409,15 +299,13 @@
     {
         return mTransformFeedbackStrides;
     }
-    size_t getTransformFeedbackBufferCount() const { return mTransformFeedbackStrides.size(); }
     const std::vector<AtomicCounterBuffer> &getAtomicCounterBuffers() const
     {
         return mAtomicCounterBuffers;
     }
 
     // Count the number of uniform and storage buffer declarations, counting arrays as one.
-    size_t getUniqueUniformBlockCount() const;
-    size_t getUniqueStorageBlockCount() const;
+    size_t getTransformFeedbackBufferCount() const;
 
     GLuint getUniformIndexFromName(const std::string &name) const;
     GLuint getUniformIndexFromLocation(UniformLocation location) const;
@@ -435,21 +323,8 @@
     int getNumViews() const { return mNumViews; }
     bool usesMultiview() const { return mNumViews != -1; }
 
-    const ShaderBitSet &getLinkedShaderStages() const { return mLinkedShaderStages; }
-    bool hasLinkedShaderStage(ShaderType shaderType) const
-    {
-        return mLinkedShaderStages[shaderType];
-    }
-    size_t getLinkedShaderStageCount() const { return mLinkedShaderStages.count(); }
-    bool isCompute() const { return hasLinkedShaderStage(ShaderType::Compute); }
-
     bool hasAttachedShader() const;
 
-    const ActiveTextureMask &getActiveSamplersMask() const { return mActiveSamplersMask; }
-    SamplerFormat getSamplerFormatForTextureUnitIndex(size_t textureUnitIndex) const
-    {
-        return mActiveSamplerFormats[textureUnitIndex];
-    }
     ShaderType getFirstAttachedShaderStageType() const;
     ShaderType getLastAttachedShaderStageType() const;
 
@@ -458,6 +333,26 @@
         return mUniformLocationBindings;
     }
 
+    const ProgramExecutable &getProgramExecutable() const { return mExecutable; }
+    ProgramExecutable &getProgramExecutable() { return mExecutable; }
+
+    bool hasDefaultUniforms() const { return !getDefaultUniformRange().empty(); }
+    bool hasTextures() const { return !getSamplerBindings().empty(); }
+    bool hasUniformBuffers() const { return !getUniformBlocks().empty(); }
+    bool hasStorageBuffers() const { return !getShaderStorageBlocks().empty(); }
+    bool hasAtomicCounterBuffers() const { return !getAtomicCounterBuffers().empty(); }
+    bool hasImages() const { return !getImageBindings().empty(); }
+    bool hasTransformFeedbackOutput() const
+    {
+        return !getLinkedTransformFeedbackVaryings().empty();
+    }
+    bool hasEarlyFragmentTestsOptimization() const { return mEarlyFramentTestsOptimization; }
+
+    bool isShaderMarkedForDetach(gl::ShaderType shaderType) const
+    {
+        return mAttachedShadersMarkedForDetach[shaderType];
+    }
+
   private:
     friend class MemoryProgramCache;
     friend class Program;
@@ -476,7 +371,9 @@
     sh::WorkGroupSize mComputeShaderLocalSize;
 
     ShaderMap<Shader *> mAttachedShaders;
+    ShaderMap<bool> mAttachedShadersMarkedForDetach;
 
+    uint32_t mLocationsUsedForXfbExtension;
     std::vector<std::string> mTransformFeedbackVaryingNames;
     std::vector<TransformFeedbackVarying> mLinkedTransformFeedbackVaryings;
     GLenum mTransformFeedbackBufferMode;
@@ -486,11 +383,6 @@
 
     // Vertex attributes, Fragment input varyings, etc.
     std::vector<sh::ShaderVariable> mProgramInputs;
-    angle::BitSet<MAX_VERTEX_ATTRIBS> mActiveAttribLocationsMask;
-    unsigned int mMaxActiveAttribLocation;
-    ComponentTypeMask mAttributesTypeMask;
-    // mAttributesMask is identical to mActiveAttribLocationsMask with built-in attributes removed.
-    AttributesMask mAttributesMask;
 
     // Uniforms are sorted in order:
     //  1. Non-opaque uniforms
@@ -537,7 +429,7 @@
 
     bool mBinaryRetrieveableHint;
     bool mSeparable;
-    ShaderBitSet mLinkedShaderStages;
+    bool mEarlyFramentTestsOptimization;
 
     // ANGLE_multiview.
     int mNumViews;
@@ -562,18 +454,11 @@
     // The size of the data written to each transform feedback buffer per vertex.
     std::vector<GLsizei> mTransformFeedbackStrides;
 
-    // Cached mask of active samplers and sampler types.
-    ActiveTextureMask mActiveSamplersMask;
-    ActiveTextureArray<uint32_t> mActiveSamplerRefCounts;
-    ActiveTextureArray<TextureType> mActiveSamplerTypes;
-    ActiveTextureArray<SamplerFormat> mActiveSamplerFormats;
-
-    // Cached mask of active images.
-    ActiveTextureMask mActiveImagesMask;
-
     // Note that this has nothing to do with binding layout qualifiers that can be set for some
     // uniforms in GLES3.1+. It is used to pre-set the location of uniforms.
     ProgramAliasedBindings mUniformLocationBindings;
+
+    ProgramExecutable mExecutable;
 };
 
 struct ProgramVaryingRef
@@ -611,7 +496,7 @@
         return mProgram;
     }
 
-    void attachShader(Shader *shader);
+    void attachShader(const Context *context, Shader *shader);
     void detachShader(const Context *context, Shader *shader);
     int getAttachedShadersCount() const;
 
@@ -620,15 +505,13 @@
     void bindAttributeLocation(GLuint index, const char *name);
     void bindUniformLocation(UniformLocation location, const char *name);
 
-    // CHROMIUM_path_rendering
-    BindingInfo getFragmentInputBindingInfo(GLint index) const;
-    void bindFragmentInputLocation(GLint index, const char *name);
-    void pathFragmentInputGen(GLint index, GLenum genMode, GLint components, const GLfloat *coeffs);
-
     // EXT_blend_func_extended
     void bindFragmentOutputLocation(GLuint index, const char *name);
     void bindFragmentOutputIndex(GLuint index, const char *name);
 
+    angle::Result linkMergedVaryings(const Context *context,
+                                     const ProgramMergedVaryings &mergedVaryings);
+
     // KHR_parallel_shader_compile
     // Try to link the program asynchrously. As a result, background threads may be launched to
     // execute the linking tasks concurrently.
@@ -643,13 +526,6 @@
         return mLinked;
     }
 
-    bool hasLinkedShaderStage(ShaderType shaderType) const
-    {
-        ASSERT(shaderType != ShaderType::InvalidEnum);
-        return mState.hasLinkedShaderStage(shaderType);
-    }
-    bool isCompute() const { return mState.isCompute(); }
-
     angle::Result loadBinary(const Context *context,
                              GLenum binaryFormat,
                              const void *binary,
@@ -666,12 +542,9 @@
     void setSeparable(bool separable);
     bool isSeparable() const;
 
-    int getInfoLogLength() const;
-    void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const;
     void getAttachedShaders(GLsizei maxCount, GLsizei *count, ShaderProgramID *shaders) const;
 
     GLuint getAttributeLocation(const std::string &name) const;
-    bool isAttribLocationActive(size_t attribLocation) const;
 
     void getActiveAttribute(GLuint index,
                             GLsizei bufsize,
@@ -884,11 +757,8 @@
 
     bool isValidated() const;
 
-    const AttributesMask &getActiveAttribLocationsMask() const
-    {
-        ASSERT(mLinkResolved);
-        return mState.mActiveAttribLocationsMask;
-    }
+    Optional<bool> getCachedValidateSamplersResult() { return mCachedValidateSamplersResult; }
+    void setCachedValidateSamplersResult(bool result) { mCachedValidateSamplersResult = result; }
 
     const std::vector<SamplerBinding> &getSamplerBindings() const;
     const std::vector<ImageBinding> &getImageBindings() const
@@ -937,8 +807,9 @@
     const sh::ShaderVariable &getOutputResource(size_t index) const;
 
     const ProgramBindings &getAttributeBindings() const;
-    const ProgramBindings &getFragmentInputBindings() const;
     const ProgramAliasedBindings &getUniformLocationBindings() const;
+    const ProgramAliasedBindings &getFragmentOutputLocations() const;
+    const ProgramAliasedBindings &getFragmentOutputIndexes() const;
 
     int getNumViews() const
     {
@@ -949,19 +820,9 @@
     bool usesMultiview() const { return mState.usesMultiview(); }
 
     ComponentTypeMask getDrawBufferTypeMask() const;
-    ComponentTypeMask getAttributesTypeMask() const;
-    AttributesMask getAttributesMask() const;
 
     const std::vector<GLsizei> &getTransformFeedbackStrides() const;
 
-    const ActiveTextureMask &getActiveSamplersMask() const { return mState.mActiveSamplersMask; }
-    const ActiveTextureMask &getActiveImagesMask() const { return mState.mActiveImagesMask; }
-
-    const ActiveTextureArray<TextureType> &getActiveSamplerTypes() const
-    {
-        return mState.mActiveSamplerTypes;
-    }
-
     // Program dirty bits.
     enum DirtyBitType
     {
@@ -987,11 +848,39 @@
 
     ANGLE_INLINE bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
 
+    gl::ProgramLinkedResources &getResources() const
+    {
+        ASSERT(mResources);
+        return *mResources;
+    }
+
     // Writes a program's binary to the output memory buffer.
     angle::Result serialize(const Context *context, angle::MemoryBuffer *binaryOut) const;
 
     rx::Serial serial() const { return mSerial; }
 
+    const ProgramExecutable &getExecutable() const { return mState.getProgramExecutable(); }
+    ProgramExecutable &getExecutable() { return mState.getProgramExecutable(); }
+
+    const char *validateDrawStates(const State &state, const gl::Extensions &extensions) const;
+
+    static void getFilteredVaryings(const std::vector<sh::ShaderVariable> &varyings,
+                                    std::vector<const sh::ShaderVariable *> *filteredVaryingsOut);
+    static bool doShaderVariablesMatch(gl::Shader *generatingShader,
+                                       gl::Shader *consumingShader,
+                                       const sh::ShaderVariable &input,
+                                       const sh::ShaderVariable &output,
+                                       bool validateGeometryShaderInputs,
+                                       bool isSeparable,
+                                       gl::InfoLog &infoLog);
+    static bool linkValidateShaderInterfaceMatching(Shader *generatingShader,
+                                                    Shader *consumingShader,
+                                                    bool isSeparable,
+                                                    InfoLog &infoLog);
+    static bool linkValidateBuiltInVaryings(Shader *vertexShader,
+                                            Shader *fragmentShader,
+                                            InfoLog &infoLog);
+
   private:
     struct LinkingState;
 
@@ -1027,23 +916,14 @@
                                                   const sh::ShaderVariable &inputVarying,
                                                   int shaderVersion,
                                                   bool validateGeometryShaderInputVarying,
+                                                  bool isSeparable,
                                                   std::string *mismatchedStructFieldName);
 
-    bool linkValidateShaderInterfaceMatching(Shader *generatingShader,
-                                             Shader *consumingShader,
-                                             InfoLog &infoLog) const;
-
-    // Check for aliased path rendering input bindings (if any).
-    // If more than one binding refer statically to the same location the link must fail.
-    bool linkValidateFragmentInputBindings(InfoLog &infoLog) const;
-
-    bool linkValidateBuiltInVaryings(InfoLog &infoLog) const;
     bool linkValidateTransformFeedback(const Version &version,
                                        InfoLog &infoLog,
                                        const ProgramMergedVaryings &linkedVaryings,
                                        ShaderType stage,
                                        const Caps &caps) const;
-    bool linkValidateGlobalNames(InfoLog &infoLog) const;
 
     void gatherTransformFeedbackVaryings(const ProgramMergedVaryings &varyings, ShaderType stage);
 
@@ -1112,9 +992,6 @@
 
     ProgramBindings mAttributeBindings;
 
-    // CHROMIUM_path_rendering
-    ProgramBindings mFragmentInputBindings;
-
     // EXT_blend_func_extended
     ProgramAliasedBindings mFragmentOutputLocations;
     ProgramAliasedBindings mFragmentOutputIndexes;
@@ -1129,12 +1006,13 @@
     ShaderProgramManager *mResourceManager;
     const ShaderProgramID mHandle;
 
-    InfoLog mInfoLog;
-
     // Cache for sampler validation
     Optional<bool> mCachedValidateSamplersResult;
 
     DirtyBits mDirtyBits;
+
+    // TODO: http://anglebug.com/4514: Remove
+    std::unique_ptr<gl::ProgramLinkedResources> mResources;
 };
 }  // namespace gl
 
diff --git a/src/libANGLE/ProgramExecutable.cpp b/src/libANGLE/ProgramExecutable.cpp
new file mode 100644
index 0000000..17e62eb
--- /dev/null
+++ b/src/libANGLE/ProgramExecutable.cpp
@@ -0,0 +1,410 @@
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ProgramExecutable.cpp: Collects the interfaces common to both Programs and
+// ProgramPipelines in order to execute/draw with either.
+
+#include "libANGLE/ProgramExecutable.h"
+
+#include "libANGLE/Context.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/ProgramPipeline.h"
+#include "libANGLE/Shader.h"
+
+namespace gl
+{
+
+ProgramExecutable::ProgramExecutable()
+    : mProgramState(nullptr),
+      mProgramPipelineState(nullptr),
+      mMaxActiveAttribLocation(0),
+      mAttributesTypeMask(0),
+      mAttributesMask(0),
+      mActiveSamplersMask(0),
+      mActiveSamplerRefCounts{},
+      mActiveImagesMask(0)
+{
+    mActiveSamplerTypes.fill(TextureType::InvalidEnum);
+    mActiveSamplerFormats.fill(SamplerFormat::InvalidEnum);
+}
+
+ProgramExecutable::~ProgramExecutable() = default;
+
+void ProgramExecutable::reset()
+{
+    resetInfoLog();
+    mActiveAttribLocationsMask.reset();
+    mAttributesTypeMask.reset();
+    mAttributesMask.reset();
+    mMaxActiveAttribLocation = 0;
+
+    mActiveSamplersMask.reset();
+    mActiveSamplerRefCounts = {};
+    mActiveSamplerTypes.fill(TextureType::InvalidEnum);
+    mActiveSamplerFormats.fill(SamplerFormat::InvalidEnum);
+
+    mActiveImagesMask.reset();
+}
+
+const ProgramState *ProgramExecutable::getProgramState(ShaderType shaderType) const
+{
+    if (mProgramState &&
+        (hasLinkedShaderStage(shaderType) || mProgramState->getAttachedShader(shaderType)))
+    {
+        return mProgramState;
+    }
+    else if (mProgramPipelineState && (hasLinkedShaderStage(shaderType) ||
+                                       mProgramPipelineState->getShaderProgram(shaderType)))
+    {
+        return &mProgramPipelineState->getShaderProgram(shaderType)->getState();
+    }
+
+    return nullptr;
+}
+
+int ProgramExecutable::getInfoLogLength() const
+{
+    return static_cast<int>(mInfoLog.getLength());
+}
+
+void ProgramExecutable::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
+{
+    return mInfoLog.getLog(bufSize, length, infoLog);
+}
+
+std::string ProgramExecutable::getInfoLogString() const
+{
+    return mInfoLog.str();
+}
+
+bool ProgramExecutable::isAttribLocationActive(size_t attribLocation) const
+{
+    // TODO(timvp): http://anglebug.com/3570: Enable this assert here somehow.
+    //    ASSERT(mLinkResolved);
+    ASSERT(attribLocation < mActiveAttribLocationsMask.size());
+    return mActiveAttribLocationsMask[attribLocation];
+}
+
+AttributesMask ProgramExecutable::getAttributesMask() const
+{
+    // TODO(timvp): http://anglebug.com/3570: Enable this assert here somehow.
+    //    ASSERT(mLinkResolved);
+    return mAttributesMask;
+}
+
+bool ProgramExecutable::hasDefaultUniforms() const
+{
+    ASSERT(mProgramState || mProgramPipelineState);
+    if (mProgramState)
+    {
+        return mProgramState->hasDefaultUniforms();
+    }
+
+    return mProgramPipelineState->hasDefaultUniforms();
+}
+
+bool ProgramExecutable::hasTextures() const
+{
+    ASSERT(mProgramState || mProgramPipelineState);
+    if (mProgramState)
+    {
+        return mProgramState->hasTextures();
+    }
+
+    return mProgramPipelineState->hasTextures();
+}
+
+bool ProgramExecutable::hasUniformBuffers() const
+{
+    ASSERT(mProgramState || mProgramPipelineState);
+    if (mProgramState)
+    {
+        return mProgramState->hasUniformBuffers();
+    }
+
+    return mProgramPipelineState->hasUniformBuffers();
+}
+
+bool ProgramExecutable::hasStorageBuffers() const
+{
+    ASSERT(mProgramState || mProgramPipelineState);
+    if (mProgramState)
+    {
+        return mProgramState->hasStorageBuffers();
+    }
+
+    return mProgramPipelineState->hasStorageBuffers();
+}
+
+bool ProgramExecutable::hasAtomicCounterBuffers() const
+{
+    ASSERT(mProgramState || mProgramPipelineState);
+    if (mProgramState)
+    {
+        return mProgramState->hasAtomicCounterBuffers();
+    }
+
+    return mProgramPipelineState->hasAtomicCounterBuffers();
+}
+
+bool ProgramExecutable::hasImages() const
+{
+    ASSERT(mProgramState || mProgramPipelineState);
+    if (mProgramState)
+    {
+        return mProgramState->hasImages();
+    }
+
+    return mProgramPipelineState->hasImages();
+}
+
+bool ProgramExecutable::hasTransformFeedbackOutput() const
+{
+    ASSERT(mProgramState || mProgramPipelineState);
+    if (mProgramState)
+    {
+        return mProgramState->hasTransformFeedbackOutput();
+    }
+
+    return mProgramPipelineState->hasTransformFeedbackOutput();
+}
+
+size_t ProgramExecutable::getTransformFeedbackBufferCount(const gl::State &glState) const
+{
+    ASSERT(mProgramState || mProgramPipelineState);
+    if (mProgramState)
+    {
+        return mProgramState->getTransformFeedbackBufferCount();
+    }
+
+    // TODO(timvp): http://anglebug.com/3570: Support program pipelines
+
+    return 0;
+}
+
+void ProgramExecutable::updateActiveSamplers(const ProgramState &programState)
+{
+    const std::vector<SamplerBinding> &samplerBindings = programState.getSamplerBindings();
+
+    for (uint32_t samplerIndex = 0; samplerIndex < samplerBindings.size(); ++samplerIndex)
+    {
+        const SamplerBinding &samplerBinding = samplerBindings[samplerIndex];
+        if (samplerBinding.unreferenced)
+            continue;
+
+        uint32_t uniformIndex = programState.getUniformIndexFromSamplerIndex(samplerIndex);
+        const gl::LinkedUniform &samplerUniform = programState.getUniforms()[uniformIndex];
+
+        for (GLint textureUnit : samplerBinding.boundTextureUnits)
+        {
+            if (++mActiveSamplerRefCounts[textureUnit] == 1)
+            {
+                mActiveSamplerTypes[textureUnit]      = samplerBinding.textureType;
+                mActiveSamplerFormats[textureUnit]    = samplerBinding.format;
+                mActiveSamplerShaderBits[textureUnit] = samplerUniform.activeShaders();
+            }
+            else
+            {
+                if (mActiveSamplerTypes[textureUnit] != samplerBinding.textureType)
+                {
+                    mActiveSamplerTypes[textureUnit] = TextureType::InvalidEnum;
+                }
+                if (mActiveSamplerFormats[textureUnit] != samplerBinding.format)
+                {
+                    mActiveSamplerFormats[textureUnit] = SamplerFormat::InvalidEnum;
+                }
+            }
+            mActiveSamplersMask.set(textureUnit);
+        }
+    }
+}
+
+void ProgramExecutable::updateActiveImages(std::vector<ImageBinding> &imageBindings)
+{
+    const bool compute = isCompute() ? true : false;
+    for (uint32_t imageIndex = 0; imageIndex < imageBindings.size(); ++imageIndex)
+    {
+        const gl::ImageBinding &imageBinding = imageBindings[imageIndex];
+        if (imageBinding.unreferenced)
+            continue;
+
+        uint32_t uniformIndex = mProgramState->getUniformIndexFromImageIndex(imageIndex);
+        const gl::LinkedUniform &imageUniform = mProgramState->getUniforms()[uniformIndex];
+        const ShaderBitSet shaderBits         = imageUniform.activeShaders();
+        for (GLint imageUnit : imageBinding.boundImageUnits)
+        {
+            mActiveImagesMask.set(imageUnit);
+            if (compute)
+                mActiveImageShaderBits[imageUnit].set(gl::ShaderType::Compute);
+            else
+                mActiveImageShaderBits[imageUnit] = shaderBits;
+        }
+    }
+}
+
+void ProgramExecutable::setSamplerUniformTextureTypeAndFormat(
+    size_t textureUnitIndex,
+    std::vector<SamplerBinding> &samplerBindings)
+{
+    bool foundBinding         = false;
+    TextureType foundType     = TextureType::InvalidEnum;
+    SamplerFormat foundFormat = SamplerFormat::InvalidEnum;
+
+    for (const SamplerBinding &binding : samplerBindings)
+    {
+        if (binding.unreferenced)
+            continue;
+
+        // A conflict exists if samplers of different types are sourced by the same texture unit.
+        // We need to check all bound textures to detect this error case.
+        for (GLuint textureUnit : binding.boundTextureUnits)
+        {
+            if (textureUnit == textureUnitIndex)
+            {
+                if (!foundBinding)
+                {
+                    foundBinding = true;
+                    foundType    = binding.textureType;
+                    foundFormat  = binding.format;
+                }
+                else
+                {
+                    if (foundType != binding.textureType)
+                    {
+                        foundType = TextureType::InvalidEnum;
+                    }
+                    if (foundFormat != binding.format)
+                    {
+                        foundFormat = SamplerFormat::InvalidEnum;
+                    }
+                }
+            }
+        }
+    }
+
+    mActiveSamplerTypes[textureUnitIndex]   = foundType;
+    mActiveSamplerFormats[textureUnitIndex] = foundFormat;
+}
+
+bool ProgramExecutable::linkValidateGlobalNames(InfoLog &infoLog) const
+{
+    std::unordered_map<std::string, const sh::ShaderVariable *> uniformMap;
+    using BlockAndFieldPair = std::pair<const sh::InterfaceBlock *, const sh::ShaderVariable *>;
+    std::unordered_map<std::string, std::vector<BlockAndFieldPair>> uniformBlockFieldMap;
+
+    for (ShaderType shaderType : kAllGraphicsShaderTypes)
+    {
+        const ProgramState *programState = getProgramState(shaderType);
+        if (!programState)
+        {
+            continue;
+        }
+        Shader *shader = programState->getAttachedShader(shaderType);
+        if (!shader)
+        {
+            continue;
+        }
+
+        // Build a map of Uniforms
+        const std::vector<sh::ShaderVariable> uniforms = shader->getUniforms();
+        for (const auto &uniform : uniforms)
+        {
+            uniformMap[uniform.name] = &uniform;
+        }
+
+        // Build a map of Uniform Blocks
+        // This will also detect any field name conflicts between Uniform Blocks without instance
+        // names
+        const std::vector<sh::InterfaceBlock> &uniformBlocks = shader->getUniformBlocks();
+        for (const auto &uniformBlock : uniformBlocks)
+        {
+            // Only uniform blocks without an instance name can create a conflict with their field
+            // names
+            if (!uniformBlock.instanceName.empty())
+            {
+                continue;
+            }
+
+            for (const auto &field : uniformBlock.fields)
+            {
+                if (!uniformBlockFieldMap.count(field.name))
+                {
+                    // First time we've seen this uniform block field name, so add the
+                    // (Uniform Block, Field) pair immediately since there can't be a conflict yet
+                    BlockAndFieldPair blockAndFieldPair(&uniformBlock, &field);
+                    std::vector<BlockAndFieldPair> newUniformBlockList;
+                    newUniformBlockList.push_back(blockAndFieldPair);
+                    uniformBlockFieldMap[field.name] = newUniformBlockList;
+                    continue;
+                }
+
+                // We've seen this name before.
+                // We need to check each of the uniform blocks that contain a field with this name
+                // to see if there's a conflict or not.
+                std::vector<BlockAndFieldPair> prevBlockFieldPairs =
+                    uniformBlockFieldMap[field.name];
+                for (const auto &prevBlockFieldPair : prevBlockFieldPairs)
+                {
+                    const sh::InterfaceBlock *prevUniformBlock      = prevBlockFieldPair.first;
+                    const sh::ShaderVariable *prevUniformBlockField = prevBlockFieldPair.second;
+
+                    if (uniformBlock.isSameInterfaceBlockAtLinkTime(*prevUniformBlock))
+                    {
+                        // The same uniform block should, by definition, contain the same field name
+                        continue;
+                    }
+
+                    // The uniform blocks don't match, so check if the necessary field properties
+                    // also match
+                    if ((field.name == prevUniformBlockField->name) &&
+                        (field.type == prevUniformBlockField->type) &&
+                        (field.precision == prevUniformBlockField->precision))
+                    {
+                        infoLog << "Name conflicts between uniform block field names: "
+                                << field.name;
+                        return false;
+                    }
+                }
+
+                // No conflict, so record this pair
+                BlockAndFieldPair blockAndFieldPair(&uniformBlock, &field);
+                uniformBlockFieldMap[field.name].push_back(blockAndFieldPair);
+            }
+        }
+    }
+
+    // Validate no uniform names conflict with attribute names
+    const ProgramState *programState = getProgramState(ShaderType::Vertex);
+    if (programState)
+    {
+        Shader *vertexShader = programState->getAttachedShader(ShaderType::Vertex);
+        if (vertexShader)
+        {
+            for (const auto &attrib : vertexShader->getActiveAttributes())
+            {
+                if (uniformMap.count(attrib.name))
+                {
+                    infoLog << "Name conflicts between a uniform and an attribute: " << attrib.name;
+                    return false;
+                }
+            }
+        }
+    }
+
+    // Validate no Uniform Block fields conflict with other Uniforms
+    for (const auto &uniformBlockField : uniformBlockFieldMap)
+    {
+        const std::string &fieldName = uniformBlockField.first;
+        if (uniformMap.count(fieldName))
+        {
+            infoLog << "Name conflicts between a uniform and a uniform block field: " << fieldName;
+            return false;
+        }
+    }
+
+    return true;
+}
+
+}  // namespace gl
diff --git a/src/libANGLE/ProgramExecutable.h b/src/libANGLE/ProgramExecutable.h
new file mode 100644
index 0000000..c08b549
--- /dev/null
+++ b/src/libANGLE/ProgramExecutable.h
@@ -0,0 +1,181 @@
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ProgramExecutable.h: Collects the information and interfaces common to both Programs and
+// ProgramPipelines in order to execute/draw with either.
+
+#ifndef LIBANGLE_PROGRAMEXECUTABLE_H_
+#define LIBANGLE_PROGRAMEXECUTABLE_H_
+
+#include "libANGLE/Caps.h"
+#include "libANGLE/InfoLog.h"
+#include "libANGLE/VaryingPacking.h"
+#include "libANGLE/angletypes.h"
+
+namespace gl
+{
+
+// This small structure encapsulates binding sampler uniforms to active GL textures.
+struct SamplerBinding
+{
+    SamplerBinding(TextureType textureTypeIn,
+                   SamplerFormat formatIn,
+                   size_t elementCount,
+                   bool unreferenced);
+    SamplerBinding(const SamplerBinding &other);
+    ~SamplerBinding();
+
+    // Necessary for retrieving active textures from the GL state.
+    TextureType textureType;
+
+    SamplerFormat format;
+
+    // List of all textures bound to this sampler, of type textureType.
+    std::vector<GLuint> boundTextureUnits;
+
+    // A note if this sampler is an unreferenced uniform.
+    bool unreferenced;
+};
+
+struct ImageBinding
+{
+    ImageBinding(size_t count);
+    ImageBinding(GLuint imageUnit, size_t count, bool unreferenced);
+    ImageBinding(const ImageBinding &other);
+    ~ImageBinding();
+
+    std::vector<GLuint> boundImageUnits;
+
+    // A note if this image unit is an unreferenced uniform.
+    bool unreferenced;
+};
+
+class ProgramState;
+class ProgramPipelineState;
+
+class ProgramExecutable
+{
+  public:
+    ProgramExecutable();
+    virtual ~ProgramExecutable();
+
+    void reset();
+
+    const ProgramState *getProgramState(ShaderType shaderType) const;
+
+    int getInfoLogLength() const;
+    InfoLog &getInfoLog() { return mInfoLog; }
+    void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const;
+    std::string getInfoLogString() const;
+    void resetInfoLog() { mInfoLog.reset(); }
+
+    const ShaderBitSet &getLinkedShaderStages() const { return mLinkedShaderStages; }
+    ShaderBitSet &getLinkedShaderStages() { return mLinkedShaderStages; }
+    bool hasLinkedShaderStage(ShaderType shaderType) const
+    {
+        ASSERT(shaderType != ShaderType::InvalidEnum);
+        return mLinkedShaderStages[shaderType];
+    }
+    size_t getLinkedShaderStageCount() const { return mLinkedShaderStages.count(); }
+    bool isCompute() const { return hasLinkedShaderStage(ShaderType::Compute); }
+
+    const AttributesMask &getActiveAttribLocationsMask() const
+    {
+        return mActiveAttribLocationsMask;
+    }
+    bool isAttribLocationActive(size_t attribLocation) const;
+    const AttributesMask &getNonBuiltinAttribLocationsMask() const { return mAttributesMask; }
+    unsigned int getMaxActiveAttribLocation() const { return mMaxActiveAttribLocation; }
+    const ComponentTypeMask &getAttributesTypeMask() const { return mAttributesTypeMask; }
+    AttributesMask getAttributesMask() const;
+
+    const ActiveTextureMask &getActiveSamplersMask() const { return mActiveSamplersMask; }
+    SamplerFormat getSamplerFormatForTextureUnitIndex(size_t textureUnitIndex) const
+    {
+        return mActiveSamplerFormats[textureUnitIndex];
+    }
+    const ShaderBitSet getSamplerShaderBitsForTextureUnitIndex(size_t textureUnitIndex) const
+    {
+        return mActiveSamplerShaderBits[textureUnitIndex];
+    }
+    const ActiveTextureMask &getActiveImagesMask() const { return mActiveImagesMask; }
+    const ActiveTextureArray<ShaderBitSet> &getActiveImageShaderBits() const
+    {
+        return mActiveImageShaderBits;
+    }
+
+    const ActiveTextureArray<TextureType> &getActiveSamplerTypes() const
+    {
+        return mActiveSamplerTypes;
+    }
+
+    bool hasDefaultUniforms() const;
+    bool hasTextures() const;
+    bool hasUniformBuffers() const;
+    bool hasStorageBuffers() const;
+    bool hasAtomicCounterBuffers() const;
+    bool hasImages() const;
+    bool hasTransformFeedbackOutput() const;
+
+    // Count the number of uniform and storage buffer declarations, counting arrays as one.
+    size_t getTransformFeedbackBufferCount(const gl::State &glState) const;
+
+    bool linkValidateGlobalNames(InfoLog &infoLog) const;
+
+    // TODO: http://anglebug.com/4520: Remove mProgramState/mProgramPipelineState
+    void setProgramState(ProgramState *state)
+    {
+        ASSERT(!mProgramState && !mProgramPipelineState);
+        mProgramState = state;
+    }
+    void setProgramPipelineState(ProgramPipelineState *state)
+    {
+        ASSERT(!mProgramState && !mProgramPipelineState);
+        mProgramPipelineState = state;
+    }
+
+  private:
+    // TODO(timvp): http://anglebug.com/3570: Investigate removing these friend
+    // class declarations and accessing the necessary members with getters/setters.
+    friend class Program;
+    friend class ProgramPipeline;
+    friend class ProgramState;
+
+    void updateActiveSamplers(const ProgramState &programState);
+    void updateActiveImages(std::vector<ImageBinding> &imageBindings);
+
+    // Scans the sampler bindings for type conflicts with sampler 'textureUnitIndex'.
+    void setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex,
+                                               std::vector<SamplerBinding> &samplerBindings);
+
+    // TODO: http://anglebug.com/4520: Remove mProgramState/mProgramPipelineState
+    ProgramState *mProgramState;
+    ProgramPipelineState *mProgramPipelineState;
+
+    InfoLog mInfoLog;
+
+    ShaderBitSet mLinkedShaderStages;
+
+    angle::BitSet<MAX_VERTEX_ATTRIBS> mActiveAttribLocationsMask;
+    unsigned int mMaxActiveAttribLocation;
+    ComponentTypeMask mAttributesTypeMask;
+    // mAttributesMask is identical to mActiveAttribLocationsMask with built-in attributes removed.
+    AttributesMask mAttributesMask;
+
+    // Cached mask of active samplers and sampler types.
+    ActiveTextureMask mActiveSamplersMask;
+    ActiveTextureArray<uint32_t> mActiveSamplerRefCounts;
+    ActiveTextureArray<TextureType> mActiveSamplerTypes;
+    ActiveTextureArray<SamplerFormat> mActiveSamplerFormats;
+    ActiveTextureArray<ShaderBitSet> mActiveSamplerShaderBits;
+
+    // Cached mask of active images.
+    ActiveTextureMask mActiveImagesMask;
+    ActiveTextureArray<ShaderBitSet> mActiveImageShaderBits;
+};
+
+}  // namespace gl
+
+#endif  // LIBANGLE_PROGRAMEXECUTABLE_H_
diff --git a/src/libANGLE/ProgramPipeline.cpp b/src/libANGLE/ProgramPipeline.cpp
index e197e99..1ddeea8 100644
--- a/src/libANGLE/ProgramPipeline.cpp
+++ b/src/libANGLE/ProgramPipeline.cpp
@@ -10,6 +10,11 @@
 
 #include "libANGLE/ProgramPipeline.h"
 
+#include <algorithm>
+
+#include "libANGLE/Context.h"
+#include "libANGLE/ErrorStrings.h"
+#include "libANGLE/Program.h"
 #include "libANGLE/angletypes.h"
 #include "libANGLE/renderer/GLImplFactory.h"
 #include "libANGLE/renderer/ProgramPipelineImpl.h"
@@ -17,7 +22,16 @@
 namespace gl
 {
 
-ProgramPipelineState::ProgramPipelineState() : mLabel() {}
+ProgramPipelineState::ProgramPipelineState()
+    : mLabel(), mActiveShaderProgram(nullptr), mValid(false), mHasBeenBound(false)
+{
+    mExecutable.setProgramPipelineState(this);
+
+    for (const ShaderType shaderType : gl::AllShaderTypes())
+    {
+        mPrograms[shaderType] = nullptr;
+    }
+}
 
 ProgramPipelineState::~ProgramPipelineState() {}
 
@@ -26,19 +40,205 @@
     return mLabel;
 }
 
+void ProgramPipelineState::activeShaderProgram(Program *shaderProgram)
+{
+    mActiveShaderProgram = shaderProgram;
+}
+
+void ProgramPipelineState::useProgramStage(const Context *context,
+                                           const ShaderType shaderType,
+                                           Program *shaderProgram)
+{
+    Program *oldProgram = mPrograms[shaderType];
+    if (oldProgram)
+    {
+        oldProgram->release(context);
+    }
+
+    // If program refers to a program object with a valid shader attached for the indicated shader
+    // stage, glUseProgramStages installs the executable code for that stage in the indicated
+    // program pipeline object pipeline.
+    if (shaderProgram && (shaderProgram->id().value != 0) &&
+        shaderProgram->getExecutable().hasLinkedShaderStage(shaderType))
+    {
+        mPrograms[shaderType] = shaderProgram;
+        shaderProgram->addRef();
+    }
+    else
+    {
+        // If program is zero, or refers to a program object with no valid shader executable for the
+        // given stage, it is as if the pipeline object has no programmable stage configured for the
+        // indicated shader stage.
+        mPrograms[shaderType] = nullptr;
+    }
+}
+
+void ProgramPipelineState::useProgramStages(const Context *context,
+                                            GLbitfield stages,
+                                            Program *shaderProgram)
+{
+    if (stages == GL_ALL_SHADER_BITS)
+    {
+        for (const ShaderType shaderType : gl::AllShaderTypes())
+        {
+            useProgramStage(context, shaderType, shaderProgram);
+        }
+    }
+    else
+    {
+        if (stages & GL_VERTEX_SHADER_BIT)
+        {
+            useProgramStage(context, ShaderType::Vertex, shaderProgram);
+        }
+
+        if (stages & GL_FRAGMENT_SHADER_BIT)
+        {
+            useProgramStage(context, ShaderType::Fragment, shaderProgram);
+        }
+
+        if (stages & GL_COMPUTE_SHADER_BIT)
+        {
+            useProgramStage(context, ShaderType::Compute, shaderProgram);
+        }
+    }
+}
+
+bool ProgramPipelineState::usesShaderProgram(ShaderProgramID programId) const
+{
+    for (const Program *program : mPrograms)
+    {
+        if (program && (program->id() == programId))
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+bool ProgramPipelineState::hasDefaultUniforms() const
+{
+    for (const gl::ShaderType shaderType : gl::AllShaderTypes())
+    {
+        const Program *shaderProgram = getShaderProgram(shaderType);
+        if (shaderProgram && shaderProgram->getState().hasDefaultUniforms())
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+bool ProgramPipelineState::hasTextures() const
+{
+    for (const gl::ShaderType shaderType : gl::AllShaderTypes())
+    {
+        const Program *shaderProgram = getShaderProgram(shaderType);
+        if (shaderProgram && shaderProgram->getState().hasTextures())
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+bool ProgramPipelineState::hasUniformBuffers() const
+{
+    for (const gl::ShaderType shaderType : gl::AllShaderTypes())
+    {
+        const Program *shaderProgram = getShaderProgram(shaderType);
+        if (shaderProgram && shaderProgram->getState().hasUniformBuffers())
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+bool ProgramPipelineState::hasStorageBuffers() const
+{
+    for (const gl::ShaderType shaderType : gl::AllShaderTypes())
+    {
+        const Program *shaderProgram = getShaderProgram(shaderType);
+        if (shaderProgram && shaderProgram->getState().hasStorageBuffers())
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+bool ProgramPipelineState::hasAtomicCounterBuffers() const
+{
+    for (const gl::ShaderType shaderType : gl::AllShaderTypes())
+    {
+        const Program *shaderProgram = getShaderProgram(shaderType);
+        if (shaderProgram && shaderProgram->getState().hasAtomicCounterBuffers())
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+bool ProgramPipelineState::hasImages() const
+{
+    for (const gl::ShaderType shaderType : gl::AllShaderTypes())
+    {
+        const Program *shaderProgram = getShaderProgram(shaderType);
+        if (shaderProgram && shaderProgram->getState().hasImages())
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+bool ProgramPipelineState::hasTransformFeedbackOutput() const
+{
+    for (const gl::ShaderType shaderType : gl::AllShaderTypes())
+    {
+        const Program *shaderProgram = getShaderProgram(shaderType);
+        if (shaderProgram && shaderProgram->getState().hasTransformFeedbackOutput())
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
 ProgramPipeline::ProgramPipeline(rx::GLImplFactory *factory, ProgramPipelineID handle)
     : RefCountObject(factory->generateSerial(), handle),
-      mProgramPipeline(factory->createProgramPipeline(mState))
+      mProgramPipelineImpl(factory->createProgramPipeline(mState))
 {
-    ASSERT(mProgramPipeline);
+    ASSERT(mProgramPipelineImpl);
 }
 
 ProgramPipeline::~ProgramPipeline()
 {
-    mProgramPipeline.release();
+    mProgramPipelineImpl.release();
 }
 
-void ProgramPipeline::onDestroy(const Context *context) {}
+void ProgramPipeline::onDestroy(const Context *context)
+{
+    for (Program *program : mState.mPrograms)
+    {
+        if (program)
+        {
+            ASSERT(program->getRefCount());
+            program->release(context);
+        }
+    }
+
+    getImplementation()->destroy(context);
+}
 
 void ProgramPipeline::setLabel(const Context *context, const std::string &label)
 {
@@ -52,7 +252,393 @@
 
 rx::ProgramPipelineImpl *ProgramPipeline::getImplementation() const
 {
-    return mProgramPipeline.get();
+    return mProgramPipelineImpl.get();
+}
+
+void ProgramPipeline::activeShaderProgram(Program *shaderProgram)
+{
+    mState.activeShaderProgram(shaderProgram);
+}
+
+void ProgramPipeline::useProgramStages(const Context *context,
+                                       GLbitfield stages,
+                                       Program *shaderProgram)
+{
+    mState.useProgramStages(context, stages, shaderProgram);
+    updateLinkedShaderStages();
+    updateExecutable();
+
+    mDirtyBits.set(DIRTY_BIT_PROGRAM_STAGE);
+}
+
+void ProgramPipeline::updateLinkedShaderStages()
+{
+    mState.mExecutable.mLinkedShaderStages.reset();
+
+    for (const ShaderType shaderType : gl::AllShaderTypes())
+    {
+        if (mState.mPrograms[shaderType])
+        {
+            mState.mExecutable.mLinkedShaderStages.set(shaderType);
+        }
+    }
+}
+
+void ProgramPipeline::updateExecutableAttributes()
+{
+    Program *vertexProgram = getShaderProgram(gl::ShaderType::Vertex);
+
+    if (!vertexProgram)
+    {
+        return;
+    }
+
+    const ProgramExecutable &vertexExecutable     = vertexProgram->getExecutable();
+    mState.mExecutable.mActiveAttribLocationsMask = vertexExecutable.mActiveAttribLocationsMask;
+    mState.mExecutable.mMaxActiveAttribLocation   = vertexExecutable.mMaxActiveAttribLocation;
+    mState.mExecutable.mAttributesTypeMask        = vertexExecutable.mAttributesTypeMask;
+    mState.mExecutable.mAttributesMask            = vertexExecutable.mAttributesMask;
+}
+
+void ProgramPipeline::updateExecutableTextures()
+{
+    for (const ShaderType shaderType : gl::AllShaderTypes())
+    {
+        const Program *program = getShaderProgram(shaderType);
+        if (program)
+        {
+            mState.mExecutable.mActiveSamplersMask |=
+                program->getExecutable().getActiveSamplersMask();
+            mState.mExecutable.mActiveImagesMask |= program->getExecutable().getActiveImagesMask();
+            // Updates mActiveSamplerRefCounts, mActiveSamplerTypes, and mActiveSamplerFormats
+            mState.mExecutable.updateActiveSamplers(program->getState());
+        }
+    }
+}
+
+void ProgramPipeline::updateExecutable()
+{
+    mState.mExecutable.reset();
+
+    // Vertex Shader ProgramExecutable properties
+    updateExecutableAttributes();
+
+    // All Shader ProgramExecutable properties
+    updateExecutableTextures();
+}
+
+ProgramMergedVaryings ProgramPipeline::getMergedVaryings() const
+{
+    ASSERT(!mState.mExecutable.isCompute());
+
+    // Varyings are matched between pairs of consecutive stages, by location if assigned or
+    // by name otherwise.  Note that it's possible for one stage to specify location and the other
+    // not: https://cvs.khronos.org/bugzilla/show_bug.cgi?id=16261
+
+    // Map stages to the previous active stage in the rendering pipeline.  When looking at input
+    // varyings of a stage, this is used to find the stage whose output varyings are being linked
+    // with them.
+    ShaderMap<ShaderType> previousActiveStage;
+
+    // Note that kAllGraphicsShaderTypes is sorted according to the rendering pipeline.
+    ShaderType lastActiveStage = ShaderType::InvalidEnum;
+    for (ShaderType stage : kAllGraphicsShaderTypes)
+    {
+        previousActiveStage[stage] = lastActiveStage;
+
+        const Program *program = getShaderProgram(stage);
+        if (program)
+        {
+            lastActiveStage = stage;
+        }
+    }
+
+    // First, go through output varyings and create two maps (one by name, one by location) for
+    // faster lookup when matching input varyings.
+
+    ShaderMap<std::map<std::string, size_t>> outputVaryingNameToIndexShaderMap;
+    ShaderMap<std::map<int, size_t>> outputVaryingLocationToIndexShaderMap;
+
+    ProgramMergedVaryings merged;
+
+    // Gather output varyings.
+    for (ShaderType shaderType : kAllGraphicsShaderTypes)
+    {
+        const Program *program = getShaderProgram(shaderType);
+        if (!program)
+        {
+            continue;
+        }
+        Shader *shader = program->getState().getAttachedShader(shaderType);
+        if (!shader)
+        {
+            continue;
+        }
+
+        for (const sh::ShaderVariable &varying : shader->getOutputVaryings())
+        {
+            merged.push_back({});
+            ProgramVaryingRef *ref = &merged.back();
+
+            ref->frontShader      = &varying;
+            ref->frontShaderStage = shaderType;
+
+            // Always map by name.  Even if location is provided in this stage, it may not be in the
+            // paired stage.
+            outputVaryingNameToIndexShaderMap[shaderType][varying.name] = merged.size() - 1;
+
+            // If location is provided, also keep it in a map by location.
+            if (varying.location != -1)
+            {
+                outputVaryingLocationToIndexShaderMap[shaderType][varying.location] =
+                    merged.size() - 1;
+            }
+        }
+    }
+
+    // Gather input varyings, and match them with output varyings of the previous stage.
+    for (ShaderType shaderType : kAllGraphicsShaderTypes)
+    {
+        const Program *program = getShaderProgram(shaderType);
+        if (!program)
+        {
+            continue;
+        }
+        Shader *shader = program->getState().getAttachedShader(shaderType);
+        if (!shader)
+        {
+            continue;
+        }
+        ShaderType previousStage = previousActiveStage[shaderType];
+
+        for (const sh::ShaderVariable &varying : shader->getInputVaryings())
+        {
+            size_t mergedIndex = merged.size();
+            if (previousStage != ShaderType::InvalidEnum)
+            {
+                // If location is provided, see if we can match by location.
+                if (varying.location != -1)
+                {
+                    std::map<int, size_t> outputVaryingLocationToIndex =
+                        outputVaryingLocationToIndexShaderMap[previousStage];
+                    auto byLocationIter = outputVaryingLocationToIndex.find(varying.location);
+                    if (byLocationIter != outputVaryingLocationToIndex.end())
+                    {
+                        mergedIndex = byLocationIter->second;
+                    }
+                }
+
+                // If not found, try to match by name.
+                if (mergedIndex == merged.size())
+                {
+                    std::map<std::string, size_t> outputVaryingNameToIndex =
+                        outputVaryingNameToIndexShaderMap[previousStage];
+                    auto byNameIter = outputVaryingNameToIndex.find(varying.name);
+                    if (byNameIter != outputVaryingNameToIndex.end())
+                    {
+                        mergedIndex = byNameIter->second;
+                    }
+                }
+            }
+
+            // If no previous stage, or not matched by location or name, create a new entry for it.
+            if (mergedIndex == merged.size())
+            {
+                merged.push_back({});
+                mergedIndex = merged.size() - 1;
+            }
+
+            ProgramVaryingRef *ref = &merged[mergedIndex];
+
+            ref->backShader      = &varying;
+            ref->backShaderStage = shaderType;
+        }
+    }
+
+    return merged;
+}
+
+// The attached shaders are checked for linking errors by matching up their variables.
+// Uniform, input and output variables get collected.
+// The code gets compiled into binaries.
+angle::Result ProgramPipeline::link(const Context *context)
+{
+    if (!getExecutable().isCompute())
+    {
+        InfoLog &infoLog = mState.mExecutable.getInfoLog();
+        infoLog.reset();
+        const State &state = context->getState();
+
+        // Map the varyings to the register file
+        gl::PackMode packMode = PackMode::ANGLE_RELAXED;
+        if (state.getLimitations().noFlexibleVaryingPacking)
+        {
+            // D3D9 pack mode is strictly more strict than WebGL, so takes priority.
+            packMode = PackMode::ANGLE_NON_CONFORMANT_D3D9;
+        }
+        else if (state.getExtensions().webglCompatibility)
+        {
+            // In WebGL, we use a slightly different handling for packing variables.
+            packMode = PackMode::WEBGL_STRICT;
+        }
+
+        if (!linkVaryings(infoLog))
+        {
+            return angle::Result::Stop;
+        }
+
+        if (!mState.mExecutable.linkValidateGlobalNames(infoLog))
+        {
+            return angle::Result::Stop;
+        }
+
+        GLuint maxVaryingVectors =
+            static_cast<GLuint>(context->getState().getCaps().maxVaryingVectors);
+        VaryingPacking varyingPacking(maxVaryingVectors, packMode);
+
+        const ProgramMergedVaryings &mergedVaryings = getMergedVaryings();
+        for (ShaderType shaderType : kAllGraphicsShaderTypes)
+        {
+            Program *program = mState.mPrograms[shaderType];
+            if (program)
+            {
+                program->getResources().varyingPacking.reset();
+                ANGLE_TRY(program->linkMergedVaryings(context, mergedVaryings));
+            }
+        }
+    }
+
+    ANGLE_TRY(getImplementation()->link(context));
+
+    return angle::Result::Continue;
+}
+
+bool ProgramPipeline::linkVaryings(InfoLog &infoLog) const
+{
+    Shader *previousShader = nullptr;
+    for (ShaderType shaderType : kAllGraphicsShaderTypes)
+    {
+        Program *currentProgram = mState.mPrograms[shaderType];
+        if (!currentProgram)
+        {
+            continue;
+        }
+
+        Shader *currentShader =
+            const_cast<Shader *>(currentProgram->getState().getAttachedShader(shaderType));
+        if (!currentShader)
+        {
+            continue;
+        }
+
+        if (previousShader)
+        {
+            if (!Program::linkValidateShaderInterfaceMatching(
+                    previousShader, currentShader, currentProgram->isSeparable(), infoLog))
+            {
+                return false;
+            }
+        }
+        previousShader = currentShader;
+    }
+
+    Program *vertexProgram   = mState.mPrograms[ShaderType::Vertex];
+    Program *fragmentProgram = mState.mPrograms[ShaderType::Fragment];
+    if (!vertexProgram || !fragmentProgram)
+    {
+        return false;
+    }
+
+    Shader *vertexShader =
+        const_cast<Shader *>(vertexProgram->getState().getAttachedShader(ShaderType::Vertex));
+    Shader *fragmentShader =
+        const_cast<Shader *>(fragmentProgram->getState().getAttachedShader(ShaderType::Fragment));
+    return Program::linkValidateBuiltInVaryings(vertexShader, fragmentShader, infoLog);
+}
+
+void ProgramPipeline::validate(const gl::Context *context)
+{
+    const Caps &caps = context->getCaps();
+    mState.mValid    = true;
+    InfoLog &infoLog = mState.mExecutable.getInfoLog();
+    infoLog.reset();
+
+    for (const ShaderType shaderType : gl::AllShaderTypes())
+    {
+        Program *shaderProgram = mState.mPrograms[shaderType];
+        if (shaderProgram)
+        {
+            shaderProgram->resolveLink(context);
+            shaderProgram->validate(caps);
+            std::string shaderInfoString = shaderProgram->getExecutable().getInfoLogString();
+            if (shaderInfoString.length())
+            {
+                mState.mValid = false;
+                infoLog << shaderInfoString << "\n";
+                return;
+            }
+            if (!shaderProgram->isSeparable())
+            {
+                mState.mValid = false;
+                infoLog << GetShaderTypeString(shaderType) << " is not marked separable."
+                        << "\n";
+                return;
+            }
+        }
+    }
+
+    if (!linkVaryings(infoLog))
+    {
+        mState.mValid = false;
+
+        for (const ShaderType shaderType : gl::AllShaderTypes())
+        {
+            Program *shaderProgram = mState.mPrograms[shaderType];
+            if (shaderProgram)
+            {
+                shaderProgram->validate(caps);
+                std::string shaderInfoString = shaderProgram->getExecutable().getInfoLogString();
+                if (shaderInfoString.length())
+                {
+                    infoLog << shaderInfoString << "\n";
+                }
+            }
+        }
+    }
+}
+
+bool ProgramPipeline::validateSamplers(InfoLog *infoLog, const Caps &caps)
+{
+    for (const ShaderType shaderType : gl::AllShaderTypes())
+    {
+        Program *shaderProgram = mState.mPrograms[shaderType];
+        if (shaderProgram && !shaderProgram->validateSamplers(infoLog, caps))
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+angle::Result ProgramPipeline::syncState(const Context *context)
+{
+    if (mDirtyBits.any())
+    {
+        mDirtyBits.reset();
+
+        // If there's a Program bound, we still want to link the PPO so we don't
+        // lose the dirty bit, but, we don't want to signal any errors if it fails
+        // since the failure would be unrelated to drawing with the Program.
+        bool goodResult = link(context) == angle::Result::Continue;
+        if (!context->getState().getProgram())
+        {
+            ANGLE_CHECK(const_cast<Context *>(context), goodResult, "Program pipeline link failed",
+                        GL_INVALID_OPERATION);
+        }
+    }
+
+    return angle::Result::Continue;
 }
 
 }  // namespace gl
diff --git a/src/libANGLE/ProgramPipeline.h b/src/libANGLE/ProgramPipeline.h
index 6da4103..a47ac57 100644
--- a/src/libANGLE/ProgramPipeline.h
+++ b/src/libANGLE/ProgramPipeline.h
@@ -15,6 +15,8 @@
 
 #include "common/angleutils.h"
 #include "libANGLE/Debug.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/ProgramExecutable.h"
 #include "libANGLE/RefCountObject.h"
 
 namespace rx
@@ -36,10 +38,45 @@
 
     const std::string &getLabel() const;
 
+    const ProgramExecutable &getProgramExecutable() const { return mExecutable; }
+    ProgramExecutable &getProgramExecutable() { return mExecutable; }
+
+    void activeShaderProgram(Program *shaderProgram);
+    void useProgramStages(const Context *context, GLbitfield stages, Program *shaderProgram);
+
+    Program *getActiveShaderProgram() { return mActiveShaderProgram; }
+
+    GLboolean isValid() const { return mValid; }
+
+    const Program *getShaderProgram(ShaderType shaderType) const { return mPrograms[shaderType]; }
+
+    bool usesShaderProgram(ShaderProgramID program) const;
+
+    bool hasDefaultUniforms() const;
+    bool hasTextures() const;
+    bool hasUniformBuffers() const;
+    bool hasStorageBuffers() const;
+    bool hasAtomicCounterBuffers() const;
+    bool hasImages() const;
+    bool hasTransformFeedbackOutput() const;
+
   private:
+    void useProgramStage(const Context *context, ShaderType shaderType, Program *shaderProgram);
+
     friend class ProgramPipeline;
 
     std::string mLabel;
+
+    // The active shader program
+    Program *mActiveShaderProgram;
+    // The shader programs for each stage.
+    ShaderMap<Program *> mPrograms;
+
+    GLboolean mValid;
+
+    GLboolean mHasBeenBound;
+
+    ProgramExecutable mExecutable;
 };
 
 class ProgramPipeline final : public RefCountObject<ProgramPipelineID>, public LabeledObject
@@ -53,12 +90,74 @@
     void setLabel(const Context *context, const std::string &label) override;
     const std::string &getLabel() const override;
 
+    const ProgramPipelineState &getState() const { return mState; }
+
+    const ProgramExecutable &getExecutable() const { return mState.getProgramExecutable(); }
+    ProgramExecutable &getExecutable() { return mState.getProgramExecutable(); }
+
     rx::ProgramPipelineImpl *getImplementation() const;
 
+    Program *getActiveShaderProgram() { return mState.getActiveShaderProgram(); }
+    void activeShaderProgram(Program *shaderProgram);
+    Program *getLinkedActiveShaderProgram(const Context *context)
+    {
+        Program *program = mState.getActiveShaderProgram();
+        if (program)
+        {
+            program->resolveLink(context);
+        }
+        return program;
+    }
+
+    void useProgramStages(const Context *context, GLbitfield stages, Program *shaderProgram);
+
+    void updateExecutableAttributes();
+    void updateExecutableTextures();
+    void updateExecutable();
+
+    Program *getShaderProgram(ShaderType shaderType) const { return mState.mPrograms[shaderType]; }
+
+    ProgramMergedVaryings getMergedVaryings() const;
+    angle::Result link(const gl::Context *context);
+    bool linkVaryings(InfoLog &infoLog) const;
+    void validate(const gl::Context *context);
+    bool validateSamplers(InfoLog *infoLog, const Caps &caps);
+
+    bool usesShaderProgram(ShaderProgramID program) const
+    {
+        return mState.usesShaderProgram(program);
+    }
+
+    bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
+
+    GLboolean isValid() const { return mState.isValid(); }
+
+    void bind() { mState.mHasBeenBound = true; }
+    GLboolean hasBeenBound() const { return mState.mHasBeenBound; }
+
+    // Program pipeline dirty bits.
+    enum DirtyBitType
+    {
+        // One of the program stages in the PPO changed.
+        DIRTY_BIT_PROGRAM_STAGE,
+        DIRTY_BIT_DUMMY,  // Used to make DIRTY_BIT_COUNT > 0
+
+        DIRTY_BIT_COUNT = DIRTY_BIT_DUMMY,
+    };
+
+    using DirtyBits = angle::BitSet<DIRTY_BIT_COUNT>;
+
+    angle::Result syncState(const Context *context);
+    void setDirtyBit(DirtyBitType dirtyBitType) { mDirtyBits.set(dirtyBitType); }
+
   private:
-    std::unique_ptr<rx::ProgramPipelineImpl> mProgramPipeline;
+    void updateLinkedShaderStages();
+
+    std::unique_ptr<rx::ProgramPipelineImpl> mProgramPipelineImpl;
 
     ProgramPipelineState mState;
+
+    DirtyBits mDirtyBits;
 };
 }  // namespace gl
 
diff --git a/src/libANGLE/ResourceManager.cpp b/src/libANGLE/ResourceManager.cpp
index 7c0c576..f2c0a8f 100644
--- a/src/libANGLE/ResourceManager.cpp
+++ b/src/libANGLE/ResourceManager.cpp
@@ -13,7 +13,6 @@
 #include "libANGLE/Context.h"
 #include "libANGLE/Fence.h"
 #include "libANGLE/MemoryObject.h"
-#include "libANGLE/Path.h"
 #include "libANGLE/Program.h"
 #include "libANGLE/ProgramPipeline.h"
 #include "libANGLE/Query.h"
@@ -103,7 +102,6 @@
 }
 
 template class ResourceManagerBase<HandleAllocator>;
-template class ResourceManagerBase<HandleRangeAllocator>;
 template class TypedResourceManager<Buffer, HandleAllocator, BufferManager, BufferID>;
 template class TypedResourceManager<Texture, HandleAllocator, TextureManager, TextureID>;
 template class TypedResourceManager<Renderbuffer,
@@ -347,90 +345,17 @@
     return mObjectMap.query(handle);
 }
 
-// PathManager Implementation.
-
-PathManager::PathManager() = default;
-
-angle::Result PathManager::createPaths(Context *context, GLsizei range, PathID *createdOut)
-{
-    *createdOut = {0};
-
-    // Allocate client side handles.
-    const GLuint client = mHandleAllocator.allocateRange(static_cast<GLuint>(range));
-    if (client == HandleRangeAllocator::kInvalidHandle)
-    {
-        context->handleError(GL_OUT_OF_MEMORY, "Failed to allocate path handle range.", __FILE__,
-                             ANGLE_FUNCTION, __LINE__);
-        return angle::Result::Stop;
-    }
-
-    const auto &paths = context->getImplementation()->createPaths(range);
-    if (paths.empty())
-    {
-        mHandleAllocator.releaseRange(client, range);
-        context->handleError(GL_OUT_OF_MEMORY, "Failed to allocate path objects.", __FILE__,
-                             ANGLE_FUNCTION, __LINE__);
-        return angle::Result::Stop;
-    }
-
-    for (GLsizei i = 0; i < range; ++i)
-    {
-        rx::PathImpl *impl = paths[static_cast<unsigned>(i)];
-        PathID id          = PathID{client + i};
-        mPaths.assign(id, new Path(impl));
-    }
-    *createdOut = PathID{client};
-    return angle::Result::Continue;
-}
-
-void PathManager::deletePaths(PathID first, GLsizei range)
-{
-    GLuint firstHandle = first.value;
-    for (GLsizei i = 0; i < range; ++i)
-    {
-        GLuint id = firstHandle + i;
-        Path *p   = nullptr;
-        if (!mPaths.erase({id}, &p))
-            continue;
-        delete p;
-    }
-    mHandleAllocator.releaseRange(firstHandle, static_cast<GLuint>(range));
-}
-
-Path *PathManager::getPath(PathID handle) const
-{
-    return mPaths.query(handle);
-}
-
-bool PathManager::hasPath(PathID handle) const
-{
-    return mHandleAllocator.isUsed(GetIDValue(handle));
-}
-
-PathManager::~PathManager()
-{
-    ASSERT(mPaths.empty());
-}
-
-void PathManager::reset(const Context *context)
-{
-    for (auto path : mPaths)
-    {
-        SafeDelete(path.second);
-    }
-    mPaths.clear();
-}
-
 // FramebufferManager Implementation.
 
 // static
 Framebuffer *FramebufferManager::AllocateNewObject(rx::GLImplFactory *factory,
                                                    FramebufferID handle,
-                                                   const Caps &caps)
+                                                   const Caps &caps,
+                                                   ContextID owningContextID)
 {
     // Make sure the caller isn't using a reserved handle.
     ASSERT(handle != Framebuffer::kDefaultDrawFramebufferHandle);
-    return new Framebuffer(caps, factory, handle);
+    return new Framebuffer(caps, factory, handle, owningContextID);
 }
 
 // static
diff --git a/src/libANGLE/ResourceManager.h b/src/libANGLE/ResourceManager.h
index ca51bd8..dcf08c2 100644
--- a/src/libANGLE/ResourceManager.h
+++ b/src/libANGLE/ResourceManager.h
@@ -14,7 +14,6 @@
 #include "common/angleutils.h"
 #include "libANGLE/Error.h"
 #include "libANGLE/HandleAllocator.h"
-#include "libANGLE/HandleRangeAllocator.h"
 #include "libANGLE/ResourceMap.h"
 
 namespace rx
@@ -264,24 +263,6 @@
     ~SyncManager() override {}
 };
 
-class PathManager : public ResourceManagerBase<HandleRangeAllocator>
-{
-  public:
-    PathManager();
-
-    angle::Result createPaths(Context *context, GLsizei range, PathID *numCreated);
-    void deletePaths(PathID first, GLsizei range);
-    Path *getPath(PathID handle) const;
-    bool hasPath(PathID handle) const;
-
-  protected:
-    ~PathManager() override;
-    void reset(const Context *context) override;
-
-  private:
-    ResourceMap<Path, PathID> mPaths;
-};
-
 class FramebufferManager
     : public TypedResourceManager<Framebuffer, HandleAllocator, FramebufferManager, FramebufferID>
 {
@@ -294,14 +275,16 @@
 
     Framebuffer *checkFramebufferAllocation(rx::GLImplFactory *factory,
                                             const Caps &caps,
-                                            FramebufferID handle)
+                                            FramebufferID handle,
+                                            ContextID owningContextID)
     {
-        return checkObjectAllocation<const Caps &>(factory, handle, caps);
+        return checkObjectAllocation<const Caps &>(factory, handle, caps, owningContextID);
     }
 
     static Framebuffer *AllocateNewObject(rx::GLImplFactory *factory,
                                           FramebufferID handle,
-                                          const Caps &caps);
+                                          const Caps &caps,
+                                          ContextID owningContextID);
     static void DeleteObject(const Context *context, Framebuffer *framebuffer);
 
   protected:
diff --git a/src/libANGLE/Shader.cpp b/src/libANGLE/Shader.cpp
index 04b0dc0..847a088 100644
--- a/src/libANGLE/Shader.cpp
+++ b/src/libANGLE/Shader.cpp
@@ -317,7 +317,8 @@
     mState.mGeometryShaderInputPrimitiveType.reset();
     mState.mGeometryShaderOutputPrimitiveType.reset();
     mState.mGeometryShaderMaxVertices.reset();
-    mState.mGeometryShaderInvocations = 1;
+    mState.mGeometryShaderInvocations      = 1;
+    mState.mEarlyFragmentTestsOptimization = false;
 
     mState.mCompileStatus = CompileStatus::COMPILE_REQUESTED;
     mBoundCompiler.set(context, context->getCompiler());
@@ -490,6 +491,8 @@
             std::sort(mState.mInputVaryings.begin(), mState.mInputVaryings.end(), CompareShaderVar);
             mState.mActiveOutputVariables =
                 GetActiveShaderVariables(sh::GetOutputVariables(compilerHandle));
+            mState.mEarlyFragmentTestsOptimization =
+                sh::HasEarlyFragmentTestsOptimization(compilerHandle);
             break;
         }
         case ShaderType::Geometry:
diff --git a/src/libANGLE/Shader.h b/src/libANGLE/Shader.h
index 707ac89..5dc6025 100644
--- a/src/libANGLE/Shader.h
+++ b/src/libANGLE/Shader.h
@@ -85,6 +85,8 @@
         return mActiveOutputVariables;
     }
 
+    bool isEarlyFragmentTeststOptimization() const { return mEarlyFragmentTestsOptimization; }
+
     bool compilePending() const { return mCompileStatus == CompileStatus::COMPILE_REQUESTED; }
 
   private:
@@ -108,6 +110,8 @@
     std::vector<sh::ShaderVariable> mActiveAttributes;
     std::vector<sh::ShaderVariable> mActiveOutputVariables;
 
+    bool mEarlyFragmentTestsOptimization;
+
     // ANGLE_multiview.
     int mNumViews;
 
@@ -143,6 +147,7 @@
     void setSource(GLsizei count, const char *const *string, const GLint *length);
     int getInfoLogLength();
     void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog);
+    std::string getInfoLogString() const { return mInfoLog; }
     int getSourceLength() const;
     const std::string &getSourceString() const { return mState.getSource(); }
     void getSource(GLsizei bufSize, GLsizei *length, char *buffer) const;
@@ -161,6 +166,10 @@
     unsigned int getRefCount() const;
     bool isFlaggedForDeletion() const;
     void flagForDeletion();
+    bool hasEarlyFragmentTestsOptimization() const
+    {
+        return mState.mEarlyFragmentTestsOptimization;
+    }
 
     int getShaderVersion();
 
diff --git a/src/libANGLE/State.cpp b/src/libANGLE/State.cpp
index 51ed4d4..d341278 100644
--- a/src/libANGLE/State.cpp
+++ b/src/libANGLE/State.cpp
@@ -253,8 +253,59 @@
     GetBufferBindingSetter<BufferBinding::Uniform>(),
 }};
 
-State::State(ContextID contextIn,
-             const State *shareContextState,
+ActiveTexturesCache::ActiveTexturesCache() : mTextures{} {}
+
+ActiveTexturesCache::~ActiveTexturesCache()
+{
+    ASSERT(empty());
+}
+
+void ActiveTexturesCache::clear(ContextID contextID)
+{
+    for (size_t textureIndex = 0; textureIndex < mTextures.size(); ++textureIndex)
+    {
+        reset(contextID, textureIndex);
+    }
+}
+
+bool ActiveTexturesCache::empty() const
+{
+    for (Texture *texture : mTextures)
+    {
+        if (texture)
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+ANGLE_INLINE void ActiveTexturesCache::reset(ContextID contextID, size_t textureIndex)
+{
+    if (mTextures[textureIndex])
+    {
+        mTextures[textureIndex]->onUnbindAsSamplerTexture(contextID);
+        mTextures[textureIndex] = nullptr;
+    }
+}
+
+ANGLE_INLINE void ActiveTexturesCache::set(ContextID contextID,
+                                           size_t textureIndex,
+                                           Texture *texture)
+{
+    // We don't call reset() here to avoid setting nullptr before rebind.
+    if (mTextures[textureIndex])
+    {
+        mTextures[textureIndex]->onUnbindAsSamplerTexture(contextID);
+    }
+
+    ASSERT(texture);
+    texture->onBindAsSamplerTexture(contextID);
+    mTextures[textureIndex] = texture;
+}
+
+State::State(const State *shareContextState,
              TextureManager *shareTextures,
              const OverlayType *overlay,
              const EGLenum clientType,
@@ -269,7 +320,6 @@
       mClientType(clientType),
       mContextPriority(contextPriority),
       mClientVersion(clientVersion),
-      mContext(contextIn),
       mBufferManager(AllocateOrGetSharedResourceManager(shareContextState, &State::mBufferManager)),
       mShaderProgramManager(
           AllocateOrGetSharedResourceManager(shareContextState, &State::mShaderProgramManager)),
@@ -281,7 +331,6 @@
       mSamplerManager(
           AllocateOrGetSharedResourceManager(shareContextState, &State::mSamplerManager)),
       mSyncManager(AllocateOrGetSharedResourceManager(shareContextState, &State::mSyncManager)),
-      mPathManager(AllocateOrGetSharedResourceManager(shareContextState, &State::mPathManager)),
       mFramebufferManager(new FramebufferManager()),
       mProgramPipelineManager(new ProgramPipelineManager()),
       mMemoryObjectManager(
@@ -311,10 +360,10 @@
       mReadFramebuffer(nullptr),
       mDrawFramebuffer(nullptr),
       mProgram(nullptr),
+      mExecutable(nullptr),
       mProvokingVertex(gl::ProvokingVertexConvention::LastVertexConvention),
       mVertexArray(nullptr),
       mActiveSampler(0),
-      mActiveTexturesCache{},
       mTexturesIncompatibleWithSamplers(0),
       mPrimitiveRestart(false),
       mDebug(debug),
@@ -440,7 +489,8 @@
         mActiveQueries[type].set(context, nullptr);
     }
 
-    mProgram = nullptr;
+    mProgram    = nullptr;
+    mExecutable = nullptr;
 
     mReadFramebuffer = nullptr;
     mDrawFramebuffer = nullptr;
@@ -454,12 +504,6 @@
 
     mCoverageModulation = GL_NONE;
 
-    angle::Matrix<GLfloat>::setToIdentity(mPathMatrixProj);
-    angle::Matrix<GLfloat>::setToIdentity(mPathMatrixMV);
-    mPathStencilFunc = GL_ALWAYS;
-    mPathStencilRef  = 0;
-    mPathStencilMask = std::numeric_limits<GLuint>::max();
-
     mNoSimultaneousConstantColorAndAlphaBlendFunc =
         context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
         context->getExtensions().webglCompatibility;
@@ -474,6 +518,8 @@
 
 void State::reset(const Context *context)
 {
+    mActiveTexturesCache.clear(mID);
+
     for (auto &bindingVec : mSamplerTextures)
     {
         for (size_t textureIdx = 0; textureIdx < bindingVec.size(); textureIdx++)
@@ -508,8 +554,8 @@
         mProgram->release(context);
     }
     mProgram = nullptr;
-
     mProgramPipeline.set(context, nullptr);
+    mExecutable = nullptr;
 
     if (mTransformFeedback.get())
         mTransformFeedback->onBindingChanged(context, false);
@@ -535,45 +581,19 @@
         UpdateIndexedBufferBinding(context, &buf, nullptr, BufferBinding::ShaderStorage, 0, 0);
     }
 
-    angle::Matrix<GLfloat>::setToIdentity(mPathMatrixProj);
-    angle::Matrix<GLfloat>::setToIdentity(mPathMatrixMV);
-    mPathStencilFunc = GL_ALWAYS;
-    mPathStencilRef  = 0;
-    mPathStencilMask = std::numeric_limits<GLuint>::max();
-
     setAllDirtyBits();
 }
 
-ANGLE_INLINE void State::unsetActiveTexture(size_t textureIndex)
-{
-    if (mActiveTexturesCache[textureIndex])
-    {
-        mActiveTexturesCache[textureIndex]->onUnbindAsSamplerTexture();
-        mActiveTexturesCache[textureIndex] = nullptr;
-    }
-}
-
 ANGLE_INLINE void State::unsetActiveTextures(ActiveTextureMask textureMask)
 {
     // Unset any relevant bound textures.
-    for (size_t textureIndex : mProgram->getActiveSamplersMask())
+    for (size_t textureIndex : textureMask)
     {
-        unsetActiveTexture(textureIndex);
+        mActiveTexturesCache.reset(mID, textureIndex);
         mCompleteTextureBindings[textureIndex].reset();
     }
 }
 
-ANGLE_INLINE void State::setActiveTexture(size_t textureIndex, Texture *texture)
-{
-    if (mActiveTexturesCache[textureIndex])
-    {
-        mActiveTexturesCache[textureIndex]->onUnbindAsSamplerTexture();
-    }
-
-    texture->onBindAsSamplerTexture();
-    mActiveTexturesCache[textureIndex] = texture;
-}
-
 ANGLE_INLINE void State::updateActiveTextureState(const Context *context,
                                                   size_t textureIndex,
                                                   const Sampler *sampler,
@@ -581,11 +601,11 @@
 {
     if (!texture->isSamplerComplete(context, sampler))
     {
-        unsetActiveTexture(textureIndex);
+        mActiveTexturesCache.reset(mID, textureIndex);
     }
     else
     {
-        setActiveTexture(textureIndex, texture);
+        mActiveTexturesCache.set(mID, textureIndex, texture);
 
         if (texture->hasAnyDirtyBit())
         {
@@ -604,8 +624,7 @@
             sampler ? sampler->getSamplerState() : texture->getSamplerState();
         mTexturesIncompatibleWithSamplers[textureIndex] =
             !texture->getTextureState().compatibleWithSamplerFormat(
-                mProgram->getState().getSamplerFormatForTextureUnitIndex(textureIndex),
-                samplerState);
+                mExecutable->getSamplerFormatForTextureUnitIndex(textureIndex), samplerState);
     }
     else
     {
@@ -625,7 +644,7 @@
 
     if (!texture)
     {
-        unsetActiveTexture(textureIndex);
+        mActiveTexturesCache.reset(mID, textureIndex);
         mDirtyBits.set(DIRTY_BIT_TEXTURE_BINDINGS);
         return;
     }
@@ -1081,60 +1100,66 @@
     {
         case GL_MULTISAMPLE_EXT:
             setMultisampling(enabled);
-            break;
+            return;
         case GL_SAMPLE_ALPHA_TO_ONE_EXT:
             setSampleAlphaToOne(enabled);
-            break;
+            return;
         case GL_CULL_FACE:
             setCullFace(enabled);
-            break;
+            return;
         case GL_POLYGON_OFFSET_FILL:
             setPolygonOffsetFill(enabled);
-            break;
+            return;
         case GL_SAMPLE_ALPHA_TO_COVERAGE:
             setSampleAlphaToCoverage(enabled);
-            break;
+            return;
         case GL_SAMPLE_COVERAGE:
             setSampleCoverage(enabled);
-            break;
+            return;
         case GL_SCISSOR_TEST:
             setScissorTest(enabled);
-            break;
+            return;
         case GL_STENCIL_TEST:
             setStencilTest(enabled);
-            break;
+            return;
         case GL_DEPTH_TEST:
             setDepthTest(enabled);
-            break;
+            return;
         case GL_BLEND:
             setBlend(enabled);
-            break;
+            return;
         case GL_DITHER:
             setDither(enabled);
-            break;
+            return;
         case GL_PRIMITIVE_RESTART_FIXED_INDEX:
             setPrimitiveRestart(enabled);
-            break;
+            return;
         case GL_RASTERIZER_DISCARD:
             setRasterizerDiscard(enabled);
-            break;
+            return;
         case GL_SAMPLE_MASK:
             setSampleMaskEnabled(enabled);
-            break;
+            return;
         case GL_DEBUG_OUTPUT_SYNCHRONOUS:
             mDebug.setOutputSynchronous(enabled);
-            break;
+            return;
         case GL_DEBUG_OUTPUT:
             mDebug.setOutputEnabled(enabled);
-            break;
+            return;
         case GL_FRAMEBUFFER_SRGB_EXT:
             setFramebufferSRGB(enabled);
-            break;
+            return;
         case GL_TEXTURE_RECTANGLE_ANGLE:
             mTextureRectangleEnabled = enabled;
-            break;
+            return;
+    }
 
-        // GLES1 emulation
+    ASSERT(mClientVersion.major == 1);
+
+    // GLES1 emulation. Need to separate from main switch due to some enums that
+    // could be conflicted between GLES1 & GLES2+
+    switch (feature)
+    {
         case GL_ALPHA_TEST:
             mGLES1State.mAlphaTestEnabled = enabled;
             break;
@@ -1254,7 +1279,12 @@
             return mProgramBinaryCacheEnabled;
         case GL_TEXTURE_RECTANGLE_ANGLE:
             return mTextureRectangleEnabled;
+    }
 
+    ASSERT(mClientVersion.major == 1);
+
+    switch (feature)
+    {
         // GLES1 emulation
         case GL_ALPHA_TEST:
             return mGLES1State.mAlphaTestEnabled;
@@ -1318,7 +1348,6 @@
     {
         case GL_BLEND:
             return isBlendEnabledIndexed(index);
-            break;
         default:
             UNREACHABLE();
             return false;
@@ -1367,14 +1396,14 @@
 
 void State::setSamplerTexture(const Context *context, TextureType type, Texture *texture)
 {
-    mSamplerTextures[type][mActiveSampler].set(context, texture);
-
-    if (mProgram && mProgram->getActiveSamplersMask()[mActiveSampler] &&
-        IsTextureCompatibleWithSampler(type, mProgram->getActiveSamplerTypes()[mActiveSampler]))
+    if (mExecutable && mExecutable->getActiveSamplersMask()[mActiveSampler] &&
+        IsTextureCompatibleWithSampler(type, mExecutable->getActiveSamplerTypes()[mActiveSampler]))
     {
         updateActiveTexture(context, mActiveSampler, texture);
     }
 
+    mSamplerTextures[type][mActiveSampler].set(context, texture);
+
     mDirtyBits.set(DIRTY_BIT_TEXTURE_BINDINGS);
 }
 
@@ -1468,6 +1497,9 @@
 
 void State::setSamplerBinding(const Context *context, GLuint textureUnit, Sampler *sampler)
 {
+    if (mSamplers[textureUnit].get() == sampler)
+        return;
+
     mSamplers[textureUnit].set(context, sampler);
     mDirtyBits.set(DIRTY_BIT_SAMPLER_BINDINGS);
     // This is overly conservative as it assumes the sampler has never been bound.
@@ -1675,17 +1707,23 @@
     {
         if (mProgram)
         {
-            unsetActiveTextures(mProgram->getActiveSamplersMask());
+            unsetActiveTextures(mExecutable->getActiveSamplersMask());
             mProgram->release(context);
         }
 
-        mProgram = newProgram;
+        mProgram    = newProgram;
+        mExecutable = nullptr;
 
         if (mProgram)
         {
+            mExecutable = &mProgram->getExecutable();
             newProgram->addRef();
             ANGLE_TRY(onProgramExecutableChange(context, newProgram));
         }
+        else if (mProgramPipeline.get())
+        {
+            mExecutable = &mProgramPipeline->getExecutable();
+        }
 
         // Note that rendering is undefined if glUseProgram(0) is called. But ANGLE will generate
         // an error if the app tries to draw in this case.
@@ -1723,14 +1761,71 @@
     return false;
 }
 
-void State::setProgramPipelineBinding(const Context *context, ProgramPipeline *pipeline)
+angle::Result State::useProgramStages(const Context *context,
+                                      ProgramPipeline *programPipeline,
+                                      GLbitfield stages,
+                                      Program *shaderProgram)
 {
+    programPipeline->useProgramStages(context, stages, shaderProgram);
+    ANGLE_TRY(onProgramPipelineExecutableChange(context, programPipeline));
+    mDirtyObjects.set(DIRTY_OBJECT_PROGRAM_PIPELINE);
+
+    return angle::Result::Continue;
+}
+
+angle::Result State::setProgramPipelineBinding(const Context *context, ProgramPipeline *pipeline)
+{
+    if (mProgramPipeline.get() == pipeline)
+    {
+        return angle::Result::Continue;
+    }
+
+    if (mProgramPipeline.get())
+    {
+        unsetActiveTextures(mProgramPipeline->getExecutable().getActiveSamplersMask());
+    }
+
     mProgramPipeline.set(context, pipeline);
+    mDirtyBits.set(DIRTY_BIT_PROGRAM_BINDING);
+
+    // A bound Program always overrides the ProgramPipeline, so only update the
+    // current ProgramExecutable if there isn't currently a Program bound.
+    if (!mProgram)
+    {
+        if (mProgramPipeline.get())
+        {
+            mExecutable = &mProgramPipeline->getExecutable();
+        }
+        else
+        {
+            mExecutable = nullptr;
+        }
+    }
+
+    if (mProgramPipeline.get())
+    {
+        mProgramPipeline->bind();
+        ANGLE_TRY(onProgramPipelineExecutableChange(context, mProgramPipeline.get()));
+
+        if (mProgramPipeline->hasAnyDirtyBit())
+        {
+            mDirtyObjects.set(DIRTY_OBJECT_PROGRAM_PIPELINE);
+        }
+    }
+
+    return angle::Result::Continue;
 }
 
 void State::detachProgramPipeline(const Context *context, ProgramPipelineID pipeline)
 {
     mProgramPipeline.set(context, nullptr);
+
+    // A bound Program always overrides the ProgramPipeline, so only update the
+    // current ProgramExecutable if there isn't currently a Program bound.
+    if (!mProgram)
+    {
+        mExecutable = nullptr;
+    }
 }
 
 bool State::isQueryActive(QueryType type) const
@@ -2007,47 +2102,6 @@
     mDirtyBits.set(DIRTY_BIT_COVERAGE_MODULATION);
 }
 
-void State::loadPathRenderingMatrix(GLenum matrixMode, const GLfloat *matrix)
-{
-    if (matrixMode == GL_PATH_MODELVIEW_CHROMIUM)
-    {
-        memcpy(mPathMatrixMV, matrix, 16 * sizeof(GLfloat));
-        mDirtyBits.set(DIRTY_BIT_PATH_RENDERING);
-    }
-    else if (matrixMode == GL_PATH_PROJECTION_CHROMIUM)
-    {
-        memcpy(mPathMatrixProj, matrix, 16 * sizeof(GLfloat));
-        mDirtyBits.set(DIRTY_BIT_PATH_RENDERING);
-    }
-    else
-    {
-        UNREACHABLE();
-    }
-}
-
-const GLfloat *State::getPathRenderingMatrix(GLenum which) const
-{
-    if (which == GL_PATH_MODELVIEW_MATRIX_CHROMIUM)
-    {
-        return mPathMatrixMV;
-    }
-    else if (which == GL_PATH_PROJECTION_MATRIX_CHROMIUM)
-    {
-        return mPathMatrixProj;
-    }
-
-    UNREACHABLE();
-    return nullptr;
-}
-
-void State::setPathStencilFunc(GLenum func, GLint ref, GLuint mask)
-{
-    mPathStencilFunc = func;
-    mPathStencilRef  = ref;
-    mPathStencilMask = mask;
-    mDirtyBits.set(DIRTY_BIT_PATH_RENDERING);
-}
-
 void State::setFramebufferSRGB(bool sRGB)
 {
     mFramebufferSRGB = sRGB;
@@ -2436,12 +2490,10 @@
             *params = mStencilClearValue;
             break;
         case GL_IMPLEMENTATION_COLOR_READ_TYPE:
-            ANGLE_TRY(mReadFramebuffer->getImplementationColorReadType(
-                context, reinterpret_cast<GLenum *>(params)));
+            *params = mReadFramebuffer->getImplementationColorReadType(context);
             break;
         case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
-            ANGLE_TRY(mReadFramebuffer->getImplementationColorReadFormat(
-                context, reinterpret_cast<GLenum *>(params)));
+            *params = mReadFramebuffer->getImplementationColorReadFormat(context);
             break;
         case GL_SAMPLE_BUFFERS:
         case GL_SAMPLES:
@@ -2695,6 +2747,20 @@
             *params = ToGLenum(mProvokingVertex);
             break;
 
+        case GL_PROGRAM_PIPELINE_BINDING:
+        {
+            ProgramPipeline *pipeline = getProgramPipeline();
+            if (pipeline)
+            {
+                *params = pipeline->id().value;
+            }
+            else
+            {
+                *params = 0;
+            }
+            break;
+        }
+
         default:
             UNREACHABLE();
             break;
@@ -2910,7 +2976,7 @@
     if (!mProgram)
         return angle::Result::Continue;
 
-    for (size_t textureUnitIndex : mProgram->getActiveSamplersMask())
+    for (size_t textureUnitIndex : mExecutable->getActiveSamplersMask())
     {
         Texture *texture = mActiveTexturesCache[textureUnitIndex];
         if (texture)
@@ -2925,7 +2991,7 @@
 {
     ASSERT(mRobustResourceInit);
     ASSERT(mProgram);
-    for (size_t imageUnitIndex : mProgram->getActiveImagesMask())
+    for (size_t imageUnitIndex : mExecutable->getActiveImagesMask())
     {
         Texture *texture = mImageUnits[imageUnitIndex].texture.get();
         if (texture)
@@ -2953,13 +3019,13 @@
 angle::Result State::syncReadFramebuffer(const Context *context)
 {
     ASSERT(mReadFramebuffer);
-    return mReadFramebuffer->syncState(context);
+    return mReadFramebuffer->syncState(context, GL_READ_FRAMEBUFFER);
 }
 
 angle::Result State::syncDrawFramebuffer(const Context *context)
 {
     ASSERT(mDrawFramebuffer);
-    return mDrawFramebuffer->syncState(context);
+    return mDrawFramebuffer->syncState(context, GL_DRAW_FRAMEBUFFER);
 }
 
 angle::Result State::syncTextures(const Context *context)
@@ -3025,7 +3091,22 @@
 
 angle::Result State::syncProgram(const Context *context)
 {
-    return mProgram->syncState(context);
+    // There may not be a program if the calling application only uses program pipelines.
+    if (mProgram)
+    {
+        return mProgram->syncState(context);
+    }
+    return angle::Result::Continue;
+}
+
+angle::Result State::syncProgramPipeline(const Context *context)
+{
+    // There may not be a program pipeline if the calling application only uses programs.
+    if (mProgramPipeline.get())
+    {
+        return mProgramPipeline->syncState(context);
+    }
+    return angle::Result::Continue;
 }
 
 angle::Result State::syncDirtyObject(const Context *context, GLenum target)
@@ -3102,8 +3183,9 @@
     }
 
     // Set any bound textures.
-    const ActiveTextureTypeArray &textureTypes = program->getActiveSamplerTypes();
-    for (size_t textureIndex : program->getActiveSamplersMask())
+    const ProgramExecutable &executable        = program->getExecutable();
+    const ActiveTextureTypeArray &textureTypes = executable.getActiveSamplerTypes();
+    for (size_t textureIndex : executable.getActiveSamplersMask())
     {
         TextureType type = textureTypes[textureIndex];
 
@@ -3115,7 +3197,52 @@
         updateActiveTexture(context, textureIndex, texture);
     }
 
-    for (size_t imageUnitIndex : program->getActiveImagesMask())
+    for (size_t imageUnitIndex : executable.getActiveImagesMask())
+    {
+        Texture *image = mImageUnits[imageUnitIndex].texture.get();
+        if (!image)
+            continue;
+
+        if (image->hasAnyDirtyBit())
+        {
+            ANGLE_TRY(image->syncState(context));
+        }
+
+        if (mRobustResourceInit && image->initState() == InitState::MayNeedInit)
+        {
+            mDirtyObjects.set(DIRTY_OBJECT_IMAGES_INIT);
+        }
+    }
+
+    return angle::Result::Continue;
+}
+
+angle::Result State::onProgramPipelineExecutableChange(const Context *context,
+                                                       ProgramPipeline *programPipeline)
+{
+    mDirtyBits.set(DIRTY_BIT_PROGRAM_EXECUTABLE);
+
+    if (programPipeline->hasAnyDirtyBit())
+    {
+        mDirtyObjects.set(DIRTY_OBJECT_PROGRAM);
+    }
+
+    // Set any bound textures.
+    const ActiveTextureTypeArray &textureTypes =
+        programPipeline->getExecutable().getActiveSamplerTypes();
+    for (size_t textureIndex : programPipeline->getExecutable().getActiveSamplersMask())
+    {
+        TextureType type = textureTypes[textureIndex];
+
+        // This can happen if there is a conflicting texture type.
+        if (type == TextureType::InvalidEnum)
+            continue;
+
+        Texture *texture = getTextureForActiveSampler(type, textureIndex);
+        updateActiveTexture(context, textureIndex, texture);
+    }
+
+    for (size_t imageUnitIndex : programPipeline->getExecutable().getActiveImagesMask())
     {
         Texture *image = mImageUnits[imageUnitIndex].texture.get();
         if (!image)
@@ -3160,11 +3287,11 @@
 
     if (imageUnit.texture.get())
     {
-        imageUnit.texture->onUnbindAsImageTexture();
+        imageUnit.texture->onUnbindAsImageTexture(mID);
     }
     if (texture)
     {
-        texture->onBindAsImageTexture();
+        texture->onBindAsImageTexture(mID);
     }
     imageUnit.texture.set(context, texture);
     imageUnit.level   = level;
@@ -3182,7 +3309,7 @@
 {
     if (mProgram)
     {
-        TextureType type = mProgram->getActiveSamplerTypes()[textureUnit];
+        TextureType type = mExecutable->getActiveSamplerTypes()[textureUnit];
         if (type != TextureType::InvalidEnum)
         {
             Texture *activeTexture = getTextureForActiveSampler(type, textureUnit);
@@ -3195,7 +3322,7 @@
 {
     if (mProgram)
     {
-        TextureType type = mProgram->getActiveSamplerTypes()[textureUnit];
+        TextureType type = mExecutable->getActiveSamplerTypes()[textureUnit];
         if (type != TextureType::InvalidEnum)
         {
             Texture *activeTexture = getTextureForActiveSampler(type, textureUnit);
diff --git a/src/libANGLE/State.h b/src/libANGLE/State.h
index 67924cc..12ff5b9 100644
--- a/src/libANGLE/State.h
+++ b/src/libANGLE/State.h
@@ -19,6 +19,7 @@
 #include "libANGLE/GLES1State.h"
 #include "libANGLE/Overlay.h"
 #include "libANGLE/Program.h"
+#include "libANGLE/ProgramExecutable.h"
 #include "libANGLE/ProgramPipeline.h"
 #include "libANGLE/RefCountObject.h"
 #include "libANGLE/Renderbuffer.h"
@@ -36,7 +37,6 @@
 class Context;
 class FramebufferManager;
 class MemoryObjectManager;
-class PathManager;
 class ProgramPipelineManager;
 class Query;
 class RenderbufferManager;
@@ -64,11 +64,27 @@
 using TextureBindingMap    = angle::PackedEnumMap<TextureType, TextureBindingVector>;
 using ActiveQueryMap       = angle::PackedEnumMap<QueryType, BindingPointer<Query>>;
 
+class ActiveTexturesCache final : angle::NonCopyable
+{
+  public:
+    ActiveTexturesCache();
+    ~ActiveTexturesCache();
+
+    Texture *operator[](size_t textureIndex) const { return mTextures[textureIndex]; }
+
+    void clear(ContextID contextID);
+    void set(ContextID contextID, size_t textureIndex, Texture *texture);
+    void reset(ContextID contextID, size_t textureIndex);
+    bool empty() const;
+
+  private:
+    ActiveTextureArray<Texture *> mTextures;
+};
+
 class State : angle::NonCopyable
 {
   public:
-    State(ContextID contextIn,
-          const State *shareContextState,
+    State(const State *shareContextState,
           TextureManager *shareTextures,
           const OverlayType *overlay,
           const EGLenum clientType,
@@ -81,13 +97,11 @@
           EGLenum contextPriority);
     ~State();
 
-    int id() const { return mID; }
-
     void initialize(Context *context);
     void reset(const Context *context);
 
     // Getters
-    ContextID getContextID() const { return mContext; }
+    ContextID getContextID() const { return mID; }
     EGLenum getClientType() const { return mClientType; }
     EGLenum getContextPriority() const { return mContextPriority; }
     GLint getClientMajorVersion() const { return mClientVersion.major; }
@@ -313,6 +327,10 @@
         return mVertexArray;
     }
 
+    // If both a Program and a ProgramPipeline are bound, the Program will
+    // always override the ProgramPipeline.
+    const ProgramExecutable *getProgramExecutable() const { return mExecutable; }
+
     // Program binding manipulation
     angle::Result setProgram(const Context *context, Program *newProgram);
 
@@ -331,6 +349,8 @@
         return mProgram;
     }
 
+    ProgramPipeline *getProgramPipeline() const { return mProgramPipeline.get(); }
+
     // Transform feedback object (not buffer) binding manipulation
     void setTransformFeedbackBinding(const Context *context, TransformFeedback *transformFeedback);
     TransformFeedback *getCurrentTransformFeedback() const { return mTransformFeedback.get(); }
@@ -358,7 +378,11 @@
     Query *getActiveQuery(QueryType type) const;
 
     // Program Pipeline binding manipulation
-    void setProgramPipelineBinding(const Context *context, ProgramPipeline *pipeline);
+    angle::Result useProgramStages(const Context *context,
+                                   ProgramPipeline *programPipeline,
+                                   GLbitfield stages,
+                                   Program *shaderProgram);
+    angle::Result setProgramPipelineBinding(const Context *context, ProgramPipeline *pipeline);
     void detachProgramPipeline(const Context *context, ProgramPipelineID pipeline);
 
     //// Typed buffer binding point manipulation ////
@@ -501,14 +525,6 @@
     void setCoverageModulation(GLenum components);
     GLenum getCoverageModulation() const { return mCoverageModulation; }
 
-    // CHROMIUM_path_rendering
-    void loadPathRenderingMatrix(GLenum matrixMode, const GLfloat *matrix);
-    const GLfloat *getPathRenderingMatrix(GLenum which) const;
-    void setPathStencilFunc(GLenum func, GLint ref, GLuint mask);
-    GLenum getPathStencilFunc() const { return mPathStencilFunc; }
-    GLint getPathStencilRef() const { return mPathStencilRef; }
-    GLuint getPathStencilMask() const { return mPathStencilMask; }
-
     // GL_EXT_sRGB_write_control
     void setFramebufferSRGB(bool sRGB);
     bool getFramebufferSRGB() const { return mFramebufferSRGB; }
@@ -530,6 +546,9 @@
 
     // Sets the dirty bit for the program executable.
     angle::Result onProgramExecutableChange(const Context *context, Program *program);
+    // Sets the dirty bit for the program pipeline executable.
+    angle::Result onProgramPipelineExecutableChange(const Context *context,
+                                                    ProgramPipeline *program);
 
     enum DirtyBitType
     {
@@ -585,7 +604,7 @@
         DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING,
         DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING,
         // TODO(jmadill): Fine-grained dirty bits for each index.
-        DIRTY_BIT_PROGRAM_BINDING,
+        DIRTY_BIT_PROGRAM_BINDING,  // Must be before DIRTY_BIT_PROGRAM_EXECUTABLE
         DIRTY_BIT_PROGRAM_EXECUTABLE,
         // TODO(jmadill): Fine-grained dirty bits for each texture/sampler.
         DIRTY_BIT_SAMPLER_BINDINGS,
@@ -598,8 +617,7 @@
         DIRTY_BIT_MULTISAMPLING,
         DIRTY_BIT_SAMPLE_ALPHA_TO_ONE,
         DIRTY_BIT_COVERAGE_MODULATION,  // CHROMIUM_framebuffer_mixed_samples
-        DIRTY_BIT_PATH_RENDERING,
-        DIRTY_BIT_FRAMEBUFFER_SRGB,  // GL_EXT_sRGB_write_control
+        DIRTY_BIT_FRAMEBUFFER_SRGB,     // GL_EXT_sRGB_write_control
         DIRTY_BIT_CURRENT_VALUES,
         DIRTY_BIT_PROVOKING_VERTEX,
         DIRTY_BIT_INVALID,
@@ -622,6 +640,7 @@
         DIRTY_OBJECT_IMAGES,    // Top-level dirty bit. Also see mDirtyImages.
         DIRTY_OBJECT_SAMPLERS,  // Top-level dirty bit. Also see mDirtySamplers.
         DIRTY_OBJECT_PROGRAM,
+        DIRTY_OBJECT_PROGRAM_PIPELINE,
         DIRTY_OBJECT_UNKNOWN,
         DIRTY_OBJECT_MAX = DIRTY_OBJECT_UNKNOWN,
     };
@@ -671,7 +690,7 @@
                       GLenum format);
 
     const ImageUnit &getImageUnit(size_t unit) const { return mImageUnits[unit]; }
-    const ActiveTexturePointerArray &getActiveTexturesCache() const { return mActiveTexturesCache; }
+    const ActiveTexturesCache &getActiveTexturesCache() const { return mActiveTexturesCache; }
     ComponentTypeMask getCurrentValuesTypeMask() const { return mCurrentValuesTypeMask; }
 
     // "onActiveTextureChange" is called when a texture binding changes.
@@ -705,7 +724,7 @@
 
     ANGLE_INLINE bool validateSamplerFormats() const
     {
-        return (mTexturesIncompatibleWithSamplers & mProgram->getActiveSamplersMask()).none();
+        return (mTexturesIncompatibleWithSamplers & mExecutable->getActiveSamplersMask()).none();
     }
 
     ProvokingVertexConvention getProvokingVertex() const { return mProvokingVertex; }
@@ -756,12 +775,12 @@
         return mNoSimultaneousConstantColorAndAlphaBlendFunc;
     }
 
+    bool isEarlyFragmentTestsOptimizationAllowed() const { return isSampleCoverageEnabled(); }
+
   private:
     friend class Context;
 
-    void unsetActiveTexture(size_t textureIndex);
     void unsetActiveTextures(ActiveTextureMask textureMask);
-    void setActiveTexture(size_t textureIndex, Texture *texture);
     void updateActiveTexture(const Context *context, size_t textureIndex, Texture *texture);
     void updateActiveTextureState(const Context *context,
                                   size_t textureIndex,
@@ -784,13 +803,14 @@
     angle::Result syncImages(const Context *context);
     angle::Result syncSamplers(const Context *context);
     angle::Result syncProgram(const Context *context);
+    angle::Result syncProgramPipeline(const Context *context);
 
     using DirtyObjectHandler = angle::Result (State::*)(const Context *context);
     static constexpr DirtyObjectHandler kDirtyObjectHandlers[DIRTY_OBJECT_MAX] = {
         &State::syncTexturesInit,    &State::syncImagesInit,      &State::syncReadAttachments,
         &State::syncDrawAttachments, &State::syncReadFramebuffer, &State::syncDrawFramebuffer,
         &State::syncVertexArray,     &State::syncTextures,        &State::syncImages,
-        &State::syncSamplers,        &State::syncProgram,
+        &State::syncSamplers,        &State::syncProgram,         &State::syncProgramPipeline,
     };
 
     // Robust init must happen before Framebuffer init for the Vulkan back-end.
@@ -810,16 +830,16 @@
     static_assert(DIRTY_OBJECT_IMAGES == 8, "check DIRTY_OBJECT_IMAGES index");
     static_assert(DIRTY_OBJECT_SAMPLERS == 9, "check DIRTY_OBJECT_SAMPLERS index");
     static_assert(DIRTY_OBJECT_PROGRAM == 10, "check DIRTY_OBJECT_PROGRAM index");
+    static_assert(DIRTY_OBJECT_PROGRAM_PIPELINE == 11, "check DIRTY_OBJECT_PROGRAM_PIPELINE index");
 
     // Dispatch table for buffer update functions.
     static const angle::PackedEnumMap<BufferBinding, BufferBindingSetter> kBufferSetters;
 
-    int mID;
+    ContextID mID;
 
     EGLenum mClientType;
     EGLenum mContextPriority;
     Version mClientVersion;
-    ContextID mContext;
 
     // Caps to use for validation
     Caps mCaps;
@@ -834,7 +854,6 @@
     RenderbufferManager *mRenderbufferManager;
     SamplerManager *mSamplerManager;
     SyncManager *mSyncManager;
-    PathManager *mPathManager;
     FramebufferManager *mFramebufferManager;
     ProgramPipelineManager *mProgramPipelineManager;
     MemoryObjectManager *mMemoryObjectManager;
@@ -883,6 +902,7 @@
     BindingPointer<Renderbuffer> mRenderbuffer;
     Program *mProgram;
     BindingPointer<ProgramPipeline> mProgramPipeline;
+    ProgramExecutable *mExecutable;
 
     // GL_ANGLE_provoking_vertex
     ProvokingVertexConvention mProvokingVertex;
@@ -911,7 +931,7 @@
     // A cache of complete textures. nullptr indicates unbound or incomplete.
     // Don't use BindingPointer because this cache is only valid within a draw call.
     // Also stores a notification channel to the texture itself to handle texture change events.
-    ActiveTexturePointerArray mActiveTexturesCache;
+    ActiveTexturesCache mActiveTexturesCache;
     std::vector<angle::ObserverBinding> mCompleteTextureBindings;
 
     ActiveTextureMask mTexturesIncompatibleWithSamplers;
@@ -947,17 +967,10 @@
 
     GLenum mCoverageModulation;
 
-    // CHROMIUM_path_rendering
-    GLfloat mPathMatrixMV[16];
-    GLfloat mPathMatrixProj[16];
-    GLenum mPathStencilFunc;
-    GLint mPathStencilRef;
-    GLuint mPathStencilMask;
-
     // GL_EXT_sRGB_write_control
     bool mFramebufferSRGB;
 
-    // GL_ANGLE_robust_resource_intialization
+    // GL_ANGLE_robust_resource_initialization
     const bool mRobustResourceInit;
 
     // GL_ANGLE_program_cache_control
diff --git a/src/libANGLE/Texture.cpp b/src/libANGLE/Texture.cpp
index 26e7179..22ea53a 100644
--- a/src/libANGLE/Texture.cpp
+++ b/src/libANGLE/Texture.cpp
@@ -37,16 +37,15 @@
                                        : level;
 }
 
-InitState DetermineInitState(const Context *context, const uint8_t *pixels)
+InitState DetermineInitState(const Context *context, Buffer *unpackBuffer, const uint8_t *pixels)
 {
     // Can happen in tests.
     if (!context || !context->isRobustResourceInitEnabled())
+    {
         return InitState::Initialized;
+    }
 
-    const auto &glState = context->getState();
-    return (pixels == nullptr && glState.getTargetBuffer(gl::BufferBinding::PixelUnpack) == nullptr)
-               ? InitState::MayNeedInit
-               : InitState::Initialized;
+    return (!pixels && !unpackBuffer) ? InitState::MayNeedInit : InitState::Initialized;
 }
 }  // namespace
 
@@ -99,8 +98,6 @@
       mBaseLevel(0),
       mMaxLevel(1000),
       mDepthStencilTextureMode(GL_DEPTH_COMPONENT),
-      mSamplerBindingCount(0),
-      mImageBindingCount(0),
       mImmutableFormat(false),
       mImmutableLevels(0),
       mUsage(GL_NONE),
@@ -223,12 +220,12 @@
     return getImageDesc(getBaseImageTarget(), getEffectiveBaseLevel());
 }
 
-void TextureState::setCrop(const gl::Rectangle &rect)
+void TextureState::setCrop(const Rectangle &rect)
 {
     mCropRect = rect;
 }
 
-const gl::Rectangle &TextureState::getCrop() const
+const Rectangle &TextureState::getCrop() const
 {
     return mCropRect;
 }
@@ -527,7 +524,7 @@
 }
 
 ImageDesc::ImageDesc()
-    : ImageDesc(Extents(0, 0, 0), Format::Invalid(), 0, GL_TRUE, InitState::Initialized)
+    : ImageDesc(Extents(0, 0, 0), Format::Invalid(), 0, GL_TRUE, InitState::MayNeedInit)
 {}
 
 ImageDesc::ImageDesc(const Extents &size, const Format &format, const InitState initState)
@@ -936,7 +933,7 @@
     return mState;
 }
 
-const gl::Extents &Texture::getExtents(TextureTarget target, size_t level) const
+const Extents &Texture::getExtents(TextureTarget target, size_t level) const
 {
     ASSERT(TextureTargetToType(target) == mState.mType);
     return mState.getImageDesc(target, level).size;
@@ -1043,6 +1040,7 @@
 
 angle::Result Texture::setImage(Context *context,
                                 const PixelUnpackState &unpackState,
+                                Buffer *unpackBuffer,
                                 TextureTarget target,
                                 GLint level,
                                 GLenum internalFormat,
@@ -1060,9 +1058,9 @@
     ImageIndex index = ImageIndex::MakeFromTarget(target, level, size.depth);
 
     ANGLE_TRY(mTexture->setImage(context, index, internalFormat, size, format, type, unpackState,
-                                 pixels));
+                                 unpackBuffer, pixels));
 
-    InitState initState = DetermineInitState(context, pixels);
+    InitState initState = DetermineInitState(context, unpackBuffer, pixels);
     mState.setImageDesc(target, level, ImageDesc(size, Format(internalFormat, type), initState));
 
     ANGLE_TRY(handleMipmapGenerationHint(context, level));
@@ -1084,9 +1082,8 @@
 {
     ASSERT(TextureTargetToType(target) == mState.mType);
 
-    ANGLE_TRY(ensureSubImageInitialized(context, target, level, area));
-
     ImageIndex index = ImageIndex::MakeFromTarget(target, level, area.depth);
+    ANGLE_TRY(ensureSubImageInitialized(context, index, area));
 
     ANGLE_TRY(mTexture->setSubImage(context, index, area, format, type, unpackState, unpackBuffer,
                                     pixels));
@@ -1118,7 +1115,9 @@
     ANGLE_TRY(mTexture->setCompressedImage(context, index, internalFormat, size, unpackState,
                                            imageSize, pixels));
 
-    InitState initState = DetermineInitState(context, pixels);
+    Buffer *unpackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelUnpack);
+
+    InitState initState = DetermineInitState(context, unpackBuffer, pixels);
     mState.setImageDesc(target, level, ImageDesc(size, Format(internalFormat), initState));
     signalDirtyStorage(initState);
 
@@ -1136,9 +1135,8 @@
 {
     ASSERT(TextureTargetToType(target) == mState.mType);
 
-    ANGLE_TRY(ensureSubImageInitialized(context, target, level, area));
-
     ImageIndex index = ImageIndex::MakeFromTarget(target, level, area.depth);
+    ANGLE_TRY(ensureSubImageInitialized(context, index, area));
 
     ANGLE_TRY(mTexture->setCompressedSubImage(context, index, area, format, unpackState, imageSize,
                                               pixels));
@@ -1161,25 +1159,56 @@
     ANGLE_TRY(releaseTexImageInternal(context));
     ANGLE_TRY(orphanImages(context));
 
-    // Use the source FBO size as the init image area.
-    Box destBox(0, 0, 0, sourceArea.width, sourceArea.height, 1);
-    ANGLE_TRY(ensureSubImageInitialized(context, target, level, destBox));
-
     ImageIndex index = ImageIndex::MakeFromTarget(target, level, 1);
 
-    ANGLE_TRY(mTexture->copyImage(context, index, sourceArea, internalFormat, source));
-
     const InternalFormat &internalFormatInfo =
         GetInternalFormatInfo(internalFormat, GL_UNSIGNED_BYTE);
 
+    // Most if not all renderers clip these copies to the size of the source framebuffer, leaving
+    // other pixels untouched. For safety in robust resource initialization, assume that that
+    // clipping is going to occur when computing the region for which to ensure initialization. If
+    // the copy lies entirely off the source framebuffer, initialize as though a zero-size box is
+    // going to be set during the copy operation.
+    Box destBox;
+    if (context->isRobustResourceInitEnabled())
+    {
+        Extents fbSize = source->getReadColorAttachment()->getSize();
+        Rectangle clippedArea;
+        if (ClipRectangle(sourceArea, Rectangle(0, 0, fbSize.width, fbSize.height), &clippedArea))
+        {
+            const Offset clippedOffset(clippedArea.x - sourceArea.x, clippedArea.y - sourceArea.y,
+                                       0);
+            destBox = Box(clippedOffset.x, clippedOffset.y, clippedOffset.z, clippedArea.width,
+                          clippedArea.height, 1);
+        }
+    }
+
+    // If we need to initialize the destination texture we split the call into a create call,
+    // an initializeContents call, and then a copySubImage call. This ensures the destination
+    // texture exists before we try to clear it.
+    Extents size(sourceArea.width, sourceArea.height, 1);
+    if (doesSubImageNeedInit(context, index, destBox))
+    {
+        ANGLE_TRY(mTexture->setImage(context, index, internalFormat, size,
+                                     internalFormatInfo.format, internalFormatInfo.type,
+                                     PixelUnpackState(), nullptr, nullptr));
+        mState.setImageDesc(target, level,
+                            ImageDesc(size, Format(internalFormatInfo), InitState::MayNeedInit));
+        ANGLE_TRY(ensureSubImageInitialized(context, index, destBox));
+        ANGLE_TRY(mTexture->copySubImage(context, index, Offset(), sourceArea, source));
+    }
+    else
+    {
+        ANGLE_TRY(mTexture->copyImage(context, index, sourceArea, internalFormat, source));
+    }
+
     mState.setImageDesc(target, level,
-                        ImageDesc(Extents(sourceArea.width, sourceArea.height, 1),
-                                  Format(internalFormatInfo), InitState::Initialized));
+                        ImageDesc(size, Format(internalFormatInfo), InitState::Initialized));
 
     ANGLE_TRY(handleMipmapGenerationHint(context, level));
 
-    // We need to initialize this texture only if the source attachment is not initialized.
-    signalDirtyStorage(InitState::Initialized);
+    // Because this could affect the texture storage we might need to init other layers/levels.
+    signalDirtyStorage(InitState::MayNeedInit);
 
     return angle::Result::Continue;
 }
@@ -1192,9 +1221,28 @@
 {
     ASSERT(TextureTargetToType(index.getTarget()) == mState.mType);
 
-    Box destBox(destOffset.x, destOffset.y, destOffset.z, sourceArea.width, sourceArea.height, 1);
-    ANGLE_TRY(
-        ensureSubImageInitialized(context, index.getTarget(), index.getLevelIndex(), destBox));
+    // Most if not all renderers clip these copies to the size of the source framebuffer, leaving
+    // other pixels untouched. For safety in robust resource initialization, assume that that
+    // clipping is going to occur when computing the region for which to ensure initialization. If
+    // the copy lies entirely off the source framebuffer, initialize as though a zero-size box is
+    // going to be set during the copy operation. Note that this assumes that
+    // ensureSubImageInitialized ensures initialization of the entire destination texture, and not
+    // just a sub-region.
+    Box destBox;
+    if (context->isRobustResourceInitEnabled())
+    {
+        Extents fbSize = source->getReadColorAttachment()->getSize();
+        Rectangle clippedArea;
+        if (ClipRectangle(sourceArea, Rectangle(0, 0, fbSize.width, fbSize.height), &clippedArea))
+        {
+            const Offset clippedOffset(destOffset.x + clippedArea.x - sourceArea.x,
+                                       destOffset.y + clippedArea.y - sourceArea.y, 0);
+            destBox = Box(clippedOffset.x, clippedOffset.y, clippedOffset.z, clippedArea.width,
+                          clippedArea.height, 1);
+        }
+    }
+
+    ANGLE_TRY(ensureSubImageInitialized(context, index, destBox));
 
     ANGLE_TRY(mTexture->copySubImage(context, index, destOffset, sourceArea, source));
     ANGLE_TRY(handleMipmapGenerationHint(context, index.getLevelIndex()));
@@ -1261,9 +1309,8 @@
 
     Box destBox(destOffset.x, destOffset.y, destOffset.z, sourceBox.width, sourceBox.height,
                 sourceBox.depth);
-    ANGLE_TRY(ensureSubImageInitialized(context, target, level, destBox));
-
     ImageIndex index = ImageIndex::MakeFromTarget(target, level, sourceBox.depth);
+    ANGLE_TRY(ensureSubImageInitialized(context, index, destBox));
 
     ANGLE_TRY(mTexture->copySubTexture(context, index, destOffset, sourceLevel, sourceBox,
                                        unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha,
@@ -1682,12 +1729,12 @@
     return mState.mSamplerState.getBorderColor();
 }
 
-void Texture::setCrop(const gl::Rectangle &rect)
+void Texture::setCrop(const Rectangle &rect)
 {
     mState.setCrop(rect);
 }
 
-const gl::Rectangle &Texture::getCrop() const
+const Rectangle &Texture::getCrop() const
 {
     return mState.getCrop();
 }
@@ -1779,7 +1826,7 @@
         const ImageIndex index = it.next();
         ImageDesc &desc =
             mState.mImageDescs[GetImageDescIndex(index.getTarget(), index.getLevelIndex())];
-        if (desc.initState == InitState::MayNeedInit)
+        if (desc.initState == InitState::MayNeedInit && !desc.size.empty())
         {
             ASSERT(mState.mInitState == InitState::MayNeedInit);
             ANGLE_TRY(initializeContents(context, index));
@@ -1836,40 +1883,45 @@
     }
 }
 
-angle::Result Texture::ensureSubImageInitialized(const Context *context,
-                                                 TextureTarget target,
-                                                 size_t level,
-                                                 const gl::Box &area)
+bool Texture::doesSubImageNeedInit(const Context *context,
+                                   const ImageIndex &imageIndex,
+                                   const Box &area) const
 {
     if (!context->isRobustResourceInitEnabled() || mState.mInitState == InitState::Initialized)
     {
-        return angle::Result::Continue;
+        return false;
     }
 
     // Pre-initialize the texture contents if necessary.
-    // TODO(jmadill): Check if area overlaps the entire texture.
-    ImageIndex imageIndex =
-        ImageIndex::MakeFromTarget(target, static_cast<GLint>(level), area.depth);
-    const auto &desc = mState.getImageDesc(imageIndex);
-    if (desc.initState == InitState::MayNeedInit)
+    const ImageDesc &desc = mState.getImageDesc(imageIndex);
+    if (desc.initState != InitState::MayNeedInit)
     {
-        ASSERT(mState.mInitState == InitState::MayNeedInit);
-        bool coversWholeImage = area.x == 0 && area.y == 0 && area.z == 0 &&
-                                area.width == desc.size.width && area.height == desc.size.height &&
-                                area.depth == desc.size.depth;
-        if (!coversWholeImage)
-        {
-            ANGLE_TRY(initializeContents(context, imageIndex));
-        }
-        setInitState(imageIndex, InitState::Initialized);
+        return false;
     }
 
+    ASSERT(mState.mInitState == InitState::MayNeedInit);
+    bool coversWholeImage = area.x == 0 && area.y == 0 && area.z == 0 &&
+                            area.width == desc.size.width && area.height == desc.size.height &&
+                            area.depth == desc.size.depth;
+    return !coversWholeImage;
+}
+
+angle::Result Texture::ensureSubImageInitialized(const Context *context,
+                                                 const ImageIndex &imageIndex,
+                                                 const Box &area)
+{
+    if (doesSubImageNeedInit(context, imageIndex, area))
+    {
+        // NOTE: do not optimize this to only initialize the passed area of the texture, or the
+        // initialization logic in copySubImage will be incorrect.
+        ANGLE_TRY(initializeContents(context, imageIndex));
+    }
+    setInitState(imageIndex, InitState::Initialized);
     return angle::Result::Continue;
 }
 
 angle::Result Texture::handleMipmapGenerationHint(Context *context, int level)
 {
-
     if (getGenerateMipmapHint() == GL_TRUE && level == 0)
     {
         ANGLE_TRY(generateMipmap(context));
@@ -1888,9 +1940,8 @@
             // Texture will signal dirty storage to invalidate its own cache and the
             // attached framebuffer's cache.
             signalDirtyStorage(InitState::Initialized);
-            return;
-        case angle::SubjectMessage::SubjectChanged:
-            mDirtyBits.set(DIRTY_BIT_IMPLEMENTATION);
+            break;
+        case angle::SubjectMessage::DirtyBitsFlagged:
             signalDirtyState(DIRTY_BIT_IMPLEMENTATION);
 
             // Notify siblings that we are dirty.
@@ -1898,9 +1949,21 @@
             {
                 notifySiblings(message);
             }
-            return;
+            break;
+        case angle::SubjectMessage::SubjectChanged:
+            mState.mInitState = InitState::MayNeedInit;
+            signalDirtyState(DIRTY_BIT_IMPLEMENTATION);
+            onStateChange(angle::SubjectMessage::ContentsChanged);
+
+            // Notify siblings that we are dirty.
+            if (index == rx::kTextureImageImplObserverMessageIndex)
+            {
+                notifySiblings(message);
+            }
+            break;
         default:
-            return;
+            UNREACHABLE();
+            break;
     }
 }
 
@@ -1927,13 +1990,16 @@
                                  pixels);
 }
 
-void Texture::onBindAsImageTexture()
+void Texture::onBindAsImageTexture(ContextID contextID)
 {
-    if (!mState.isBoundAsImageTexture())
+    ContextBindingCount &bindingCount = mState.getBindingCount(contextID);
+
+    ASSERT(bindingCount.imageBindingCount < std::numeric_limits<uint32_t>::max());
+    mState.getBindingCount(contextID).imageBindingCount++;
+    if (bindingCount.imageBindingCount == 1)
     {
         mDirtyBits.set(DIRTY_BIT_BOUND_AS_IMAGE);
     }
-    mState.mImageBindingCount++;
 }
 
 }  // namespace gl
diff --git a/src/libANGLE/Texture.h b/src/libANGLE/Texture.h
index e69532a..7309b17 100644
--- a/src/libANGLE/Texture.h
+++ b/src/libANGLE/Texture.h
@@ -92,6 +92,13 @@
     GLenum swizzleAlpha;
 };
 
+struct ContextBindingCount
+{
+    ContextID contextID;
+    uint32_t samplerBindingCount;
+    uint32_t imageBindingCount;
+};
+
 // State from Table 6.9 (state per texture object) in the OpenGL ES 3.0.2 spec.
 class TextureState final : private angle::NonCopyable
 {
@@ -135,15 +142,21 @@
     GLenum getUsage() const { return mUsage; }
     GLenum getDepthStencilTextureMode() const { return mDepthStencilTextureMode; }
     bool isStencilMode() const { return mDepthStencilTextureMode == GL_STENCIL_INDEX; }
-    bool isBoundAsSamplerTexture() const { return mSamplerBindingCount > 0; }
-    bool isBoundAsImageTexture() const { return mImageBindingCount > 0; }
+    bool isBoundAsSamplerTexture(ContextID contextID) const
+    {
+        return getBindingCount(contextID).samplerBindingCount > 0;
+    }
+    bool isBoundAsImageTexture(ContextID contextID) const
+    {
+        return getBindingCount(contextID).imageBindingCount > 0;
+    }
 
     // Returns the desc of the base level. Only valid for cube-complete/mip-complete textures.
     const ImageDesc &getBaseLevelDesc() const;
 
     // GLES1 emulation: For GL_OES_draw_texture
-    void setCrop(const gl::Rectangle &rect);
-    const gl::Rectangle &getCrop() const;
+    void setCrop(const Rectangle &rect);
+    const Rectangle &getCrop() const;
 
     // GLES1 emulation: Auto-mipmap generation is a texparameter
     void setGenerateMipmapHint(GLenum hint);
@@ -181,6 +194,22 @@
     void clearImageDesc(TextureTarget target, size_t level);
     void clearImageDescs();
 
+    ContextBindingCount &getBindingCount(ContextID contextID)
+    {
+        for (ContextBindingCount &bindingCount : mBindingCounts)
+        {
+            if (bindingCount.contextID == contextID)
+                return bindingCount;
+        }
+        mBindingCounts.push_back({contextID, 0, 0});
+        return mBindingCounts.back();
+    }
+
+    const ContextBindingCount &getBindingCount(ContextID contextID) const
+    {
+        return const_cast<TextureState *>(this)->getBindingCount(contextID);
+    }
+
     const TextureType mType;
 
     SwizzleState mSwizzleState;
@@ -192,8 +221,8 @@
 
     GLenum mDepthStencilTextureMode;
 
-    uint32_t mSamplerBindingCount;
-    uint32_t mImageBindingCount;
+    std::vector<ContextBindingCount> mBindingCounts;
+
     bool mImmutableFormat;
     GLuint mImmutableLevels;
 
@@ -204,7 +233,7 @@
 
     // GLES1 emulation: Texture crop rectangle
     // For GL_OES_draw_texture
-    gl::Rectangle mCropRect;
+    Rectangle mCropRect;
 
     // GLES1 emulation: Generate-mipmap hint per texture
     GLenum mGenerateMipmapHint;
@@ -302,7 +331,7 @@
 
     const TextureState &getTextureState() const;
 
-    const gl::Extents &getExtents(TextureTarget target, size_t level) const;
+    const Extents &getExtents(TextureTarget target, size_t level) const;
     size_t getWidth(TextureTarget target, size_t level) const;
     size_t getHeight(TextureTarget target, size_t level) const;
     size_t getDepth(TextureTarget target, size_t level) const;
@@ -317,6 +346,7 @@
 
     angle::Result setImage(Context *context,
                            const PixelUnpackState &unpackState,
+                           Buffer *unpackBuffer,
                            TextureTarget target,
                            GLint level,
                            GLenum internalFormat,
@@ -418,28 +448,33 @@
 
     angle::Result generateMipmap(Context *context);
 
-    void onBindAsImageTexture();
+    void onBindAsImageTexture(ContextID contextID);
 
-    ANGLE_INLINE void onUnbindAsImageTexture()
+    ANGLE_INLINE void onUnbindAsImageTexture(ContextID contextID)
     {
-        ASSERT(mState.isBoundAsImageTexture());
-        mState.mImageBindingCount--;
+        ASSERT(mState.isBoundAsImageTexture(contextID));
+        mState.getBindingCount(contextID).imageBindingCount--;
     }
 
-    ANGLE_INLINE void onBindAsSamplerTexture()
+    ANGLE_INLINE void onBindAsSamplerTexture(ContextID contextID)
     {
-        mState.mSamplerBindingCount++;
-        if (mState.mSamplerBindingCount == 1)
+        ContextBindingCount &bindingCount = mState.getBindingCount(contextID);
+
+        ASSERT(bindingCount.samplerBindingCount < std::numeric_limits<uint32_t>::max());
+        bindingCount.samplerBindingCount++;
+        if (bindingCount.samplerBindingCount == 1)
         {
             onStateChange(angle::SubjectMessage::BindingChanged);
         }
     }
 
-    ANGLE_INLINE void onUnbindAsSamplerTexture()
+    ANGLE_INLINE void onUnbindAsSamplerTexture(ContextID contextID)
     {
-        ASSERT(mState.isBoundAsSamplerTexture());
-        mState.mSamplerBindingCount--;
-        if (mState.mSamplerBindingCount == 0)
+        ContextBindingCount &bindingCount = mState.getBindingCount(contextID);
+
+        ASSERT(mState.isBoundAsSamplerTexture(contextID));
+        bindingCount.samplerBindingCount--;
+        if (bindingCount.samplerBindingCount == 0)
         {
             onStateChange(angle::SubjectMessage::BindingChanged);
         }
@@ -481,8 +516,8 @@
     bool getAttachmentFixedSampleLocations(const ImageIndex &imageIndex) const;
 
     // GLES1 emulation
-    void setCrop(const gl::Rectangle &rect);
-    const gl::Rectangle &getCrop() const;
+    void setCrop(const Rectangle &rect);
+    const Rectangle &getCrop() const;
     void setGenerateMipmapHint(GLenum generate);
     GLenum getGenerateMipmapHint() const;
 
@@ -562,10 +597,12 @@
     void invalidateCompletenessCache() const;
     angle::Result releaseTexImageInternal(Context *context);
 
+    bool doesSubImageNeedInit(const Context *context,
+                              const ImageIndex &imageIndex,
+                              const Box &area) const;
     angle::Result ensureSubImageInitialized(const Context *context,
-                                            TextureTarget target,
-                                            size_t level,
-                                            const gl::Box &area);
+                                            const ImageIndex &imageIndex,
+                                            const Box &area);
 
     angle::Result handleMipmapGenerationHint(Context *context, int level);
 
diff --git a/src/libANGLE/VaryingPacking.cpp b/src/libANGLE/VaryingPacking.cpp
index 49fe7c2..df73f53 100644
--- a/src/libANGLE/VaryingPacking.cpp
+++ b/src/libANGLE/VaryingPacking.cpp
@@ -118,6 +118,23 @@
 
 VaryingPacking::~VaryingPacking() = default;
 
+void VaryingPacking::reset()
+{
+    clearRegisterMap();
+    mRegisterList.clear();
+    mPackedVaryings.clear();
+
+    for (std::vector<std::string> inactiveVaryingMappedNames : mInactiveVaryingMappedNames)
+    {
+        inactiveVaryingMappedNames.clear();
+    }
+}
+
+void VaryingPacking::clearRegisterMap()
+{
+    std::fill(mRegisterMap.begin(), mRegisterMap.end(), Register());
+}
+
 // Packs varyings into generic varying registers, using the algorithm from
 // See [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111
 // Also [OpenGL ES Shading Language 3.00 rev. 4] Section 11 page 119
@@ -438,6 +455,7 @@
 {
     VaryingUniqueFullNames uniqueFullNames;
     mPackedVaryings.clear();
+    clearRegisterMap();
 
     for (const ProgramVaryingRef &ref : mergedVaryings)
     {
@@ -486,7 +504,8 @@
             }
         }
 
-        // If the varying is not used in the input, we know it is inactive.
+        // If the varying is not used in the input, we know it is inactive, unless it's a separable
+        // program, in which case the input shader may not exist in this program.
         if (!input && !isSeparableProgram)
         {
             mInactiveVaryingMappedNames[ref.backShaderStage].push_back(output->mappedName);
diff --git a/src/libANGLE/VaryingPacking.h b/src/libANGLE/VaryingPacking.h
index c4874d9..251191d 100644
--- a/src/libANGLE/VaryingPacking.h
+++ b/src/libANGLE/VaryingPacking.h
@@ -221,6 +221,8 @@
         return mInactiveVaryingMappedNames;
     }
 
+    void reset();
+
   private:
     bool packVarying(const PackedVarying &packedVarying);
     bool isFree(unsigned int registerRow,
@@ -241,6 +243,8 @@
                                 const sh::ShaderVariable &field,
                                 GLuint fieldIndex);
 
+    void clearRegisterMap();
+
     std::vector<Register> mRegisterMap;
     std::vector<PackedVaryingRegister> mRegisterList;
     std::vector<PackedVarying> mPackedVaryings;
diff --git a/src/libANGLE/angletypes.h b/src/libANGLE/angletypes.h
index efba50d..54d6dd7 100644
--- a/src/libANGLE/angletypes.h
+++ b/src/libANGLE/angletypes.h
@@ -487,8 +487,7 @@
 template <typename T>
 using ActiveTextureArray = std::array<T, IMPLEMENTATION_MAX_ACTIVE_TEXTURES>;
 
-using ActiveTexturePointerArray = ActiveTextureArray<Texture *>;
-using ActiveTextureTypeArray    = ActiveTextureArray<TextureType>;
+using ActiveTextureTypeArray = ActiveTextureArray<TextureType>;
 
 template <typename T>
 using UniformBuffersArray = std::array<T, IMPLEMENTATION_MAX_UNIFORM_BUFFER_BINDINGS>;
diff --git a/src/libANGLE/capture_gles_2_0_params.cpp b/src/libANGLE/capture_gles_2_0_params.cpp
index 380988a..295bd25 100644
--- a/src/libANGLE/capture_gles_2_0_params.cpp
+++ b/src/libANGLE/capture_gles_2_0_params.cpp
@@ -240,7 +240,7 @@
                                  GLchar *name,
                                  ParamCapture *paramCapture)
 {
-    UNIMPLEMENTED();
+    CaptureStringLimit(name, bufSize, paramCapture);
 }
 
 void CaptureGetActiveUniform_length(const State &glState,
@@ -254,7 +254,7 @@
                                     GLchar *name,
                                     ParamCapture *paramCapture)
 {
-    UNIMPLEMENTED();
+    paramCapture->readBufferSizeBytes = sizeof(GLsizei);
 }
 
 void CaptureGetActiveUniform_size(const State &glState,
@@ -268,7 +268,7 @@
                                   GLchar *name,
                                   ParamCapture *paramCapture)
 {
-    UNIMPLEMENTED();
+    paramCapture->readBufferSizeBytes = sizeof(GLint);
 }
 
 void CaptureGetActiveUniform_type(const State &glState,
@@ -282,7 +282,7 @@
                                   GLchar *name,
                                   ParamCapture *paramCapture)
 {
-    UNIMPLEMENTED();
+    paramCapture->readBufferSizeBytes = sizeof(GLenum);
 }
 
 void CaptureGetActiveUniform_name(const State &glState,
@@ -296,7 +296,7 @@
                                   GLchar *name,
                                   ParamCapture *paramCapture)
 {
-    UNIMPLEMENTED();
+    CaptureStringLimit(name, bufSize, paramCapture);
 }
 
 void CaptureGetAttachedShaders_count(const State &glState,
@@ -400,7 +400,7 @@
 {
     gl::Program *programObj = GetLinkedProgramForCapture(glState, program);
     ASSERT(programObj);
-    paramCapture->readBufferSizeBytes = programObj->getInfoLogLength() + 1;
+    paramCapture->readBufferSizeBytes = programObj->getExecutable().getInfoLogLength() + 1;
 }
 
 void CaptureGetProgramiv_params(const State &glState,
@@ -458,7 +458,8 @@
                                            GLint *precision,
                                            ParamCapture *paramCapture)
 {
-    UNIMPLEMENTED();
+    // range specifies a pointer to two-element array containing log2 of min and max
+    paramCapture->readBufferSizeBytes = 2 * sizeof(GLint);
 }
 
 void CaptureGetShaderPrecisionFormat_precision(const State &glState,
@@ -469,7 +470,7 @@
                                                GLint *precision,
                                                ParamCapture *paramCapture)
 {
-    UNIMPLEMENTED();
+    paramCapture->readBufferSizeBytes = sizeof(GLint);
 }
 
 void CaptureGetShaderSource_length(const State &glState,
@@ -524,7 +525,10 @@
                                      GLint *params,
                                      ParamCapture *paramCapture)
 {
-    UNIMPLEMENTED();
+    if (params)
+    {
+        paramCapture->readBufferSizeBytes = sizeof(GLint);
+    }
 }
 
 void CaptureGetUniformLocation_name(const State &glState,
@@ -859,7 +863,7 @@
                               const GLfloat *v,
                               ParamCapture *paramCapture)
 {
-    UNIMPLEMENTED();
+    CaptureMemory(v, sizeof(GLfloat), paramCapture);
 }
 
 void CaptureVertexAttrib2fv_v(const State &glState,
@@ -868,7 +872,7 @@
                               const GLfloat *v,
                               ParamCapture *paramCapture)
 {
-    UNIMPLEMENTED();
+    CaptureMemory(v, sizeof(GLfloat) * 2, paramCapture);
 }
 
 void CaptureVertexAttrib3fv_v(const State &glState,
@@ -877,7 +881,7 @@
                               const GLfloat *v,
                               ParamCapture *paramCapture)
 {
-    UNIMPLEMENTED();
+    CaptureMemory(v, sizeof(GLfloat) * 3, paramCapture);
 }
 
 void CaptureVertexAttrib4fv_v(const State &glState,
@@ -886,7 +890,7 @@
                               const GLfloat *v,
                               ParamCapture *paramCapture)
 {
-    UNIMPLEMENTED();
+    CaptureMemory(v, sizeof(GLfloat) * 4, paramCapture);
 }
 
 void CaptureVertexAttribPointer_pointer(const State &glState,
diff --git a/src/libANGLE/capture_gles_3_0_params.cpp b/src/libANGLE/capture_gles_3_0_params.cpp
index 5e7e2f5..5d7e5b4 100644
--- a/src/libANGLE/capture_gles_3_0_params.cpp
+++ b/src/libANGLE/capture_gles_3_0_params.cpp
@@ -156,7 +156,8 @@
                                       const void *indices,
                                       ParamCapture *paramCapture)
 {
-    UNIMPLEMENTED();
+    CaptureDrawElements_indices(glState, isCallValid, modePacked, count, typePacked, indices,
+                                paramCapture);
 }
 
 void CaptureGenQueries_idsPacked(const State &glState,
@@ -321,7 +322,33 @@
                                        GLint *params,
                                        ParamCapture *paramCapture)
 {
-    UNIMPLEMENTED();
+    // From the OpenGL ES 3.0 spec:
+    //
+    // The information retrieved will be written to memory addressed by the pointer specified in
+    // params.
+    //
+    // No more than bufSize integers will be written to this memory.
+    //
+    // If pname is GL_NUM_SAMPLE_COUNTS, the number of sample counts that would be returned by
+    // querying GL_SAMPLES will be returned in params.
+    //
+    // If pname is GL_SAMPLES, the sample counts supported for internalformat and target are written
+    // into params in descending numeric order. Only positive values are returned.
+    //
+    // Querying GL_SAMPLES with bufSize of one will return just the maximum supported number of
+    // samples for this format.
+
+    if (bufSize == 0)
+        return;
+
+    if (params)
+    {
+        // For GL_NUM_SAMPLE_COUNTS, only one value is returned
+        // For GL_SAMPLES, two values will be returned, unless bufSize limits it to one
+        uint32_t paramCount = (pname == GL_SAMPLES && bufSize > 1) ? 2 : 1;
+
+        paramCapture->readBufferSizeBytes = sizeof(GLint) * paramCount;
+    }
 }
 
 void CaptureGetProgramBinary_length(const State &glState,
@@ -333,7 +360,10 @@
                                     void *binary,
                                     ParamCapture *paramCapture)
 {
-    UNIMPLEMENTED();
+    if (length)
+    {
+        paramCapture->readBufferSizeBytes = sizeof(GLsizei);
+    }
 }
 
 void CaptureGetProgramBinary_binaryFormat(const State &glState,
@@ -345,7 +375,7 @@
                                           void *binary,
                                           ParamCapture *paramCapture)
 {
-    UNIMPLEMENTED();
+    paramCapture->readBufferSizeBytes = sizeof(GLenum);
 }
 
 void CaptureGetProgramBinary_binary(const State &glState,
@@ -357,7 +387,22 @@
                                     void *binary,
                                     ParamCapture *paramCapture)
 {
-    UNIMPLEMENTED();
+    // If we have length, then actual binarySize was written there
+    // Otherwise, we don't know how many bytes were written
+    if (!length)
+    {
+        UNIMPLEMENTED();
+        return;
+    }
+
+    GLsizei binarySize = *length;
+    if (binarySize > bufSize)
+    {
+        // This is a GL error, but clamp it anyway
+        binarySize = bufSize;
+    }
+
+    paramCapture->readBufferSizeBytes = binarySize;
 }
 
 void CaptureGetQueryObjectuiv_params(const State &glState,
@@ -410,7 +455,10 @@
                              GLint *values,
                              ParamCapture *paramCapture)
 {
-    UNIMPLEMENTED();
+    if (length)
+    {
+        paramCapture->readBufferSizeBytes = sizeof(GLsizei);
+    }
 }
 
 void CaptureGetSynciv_values(const State &glState,
@@ -422,7 +470,16 @@
                              GLint *values,
                              ParamCapture *paramCapture)
 {
-    UNIMPLEMENTED();
+    // Spec: On success, GetSynciv replaces up to bufSize integers in values with the corresponding
+    // property values of the object being queried. The actual number of integers replaced is
+    // returned in *length.If length is NULL, no length is returned.
+    if (bufSize == 0)
+        return;
+
+    if (values)
+    {
+        paramCapture->readBufferSizeBytes = sizeof(GLint) * bufSize;
+    }
 }
 
 void CaptureGetTransformFeedbackVarying_length(const State &glState,
@@ -549,7 +606,8 @@
                                               const GLenum *attachments,
                                               ParamCapture *paramCapture)
 {
-    UNIMPLEMENTED();
+    CaptureMemory(attachments, sizeof(GLenum) * numAttachments, paramCapture);
+    paramCapture->value.voidConstPointerVal = paramCapture->data[0].data();
 }
 
 void CaptureInvalidateSubFramebuffer_attachments(const State &glState,
@@ -800,7 +858,8 @@
                                          const void *pointer,
                                          ParamCapture *paramCapture)
 {
-    UNIMPLEMENTED();
+    CaptureVertexAttribPointer_pointer(glState, isCallValid, index, size, typePacked, false, stride,
+                                       pointer, paramCapture);
 }
 
 }  // namespace gl
diff --git a/src/libANGLE/capture_gles_ext_autogen.cpp b/src/libANGLE/capture_gles_ext_autogen.cpp
index 016041b..2ee527b 100644
--- a/src/libANGLE/capture_gles_ext_autogen.cpp
+++ b/src/libANGLE/capture_gles_ext_autogen.cpp
@@ -2797,36 +2797,6 @@
     return CallCapture(gl::EntryPoint::CoverageModulationCHROMIUM, std::move(paramBuffer));
 }
 
-CallCapture CaptureMatrixLoadfCHROMIUM(const State &glState,
-                                       bool isCallValid,
-                                       GLenum matrixMode,
-                                       const GLfloat *matrix)
-{
-    ParamBuffer paramBuffer;
-
-    paramBuffer.addEnumParam("matrixMode", GLenumGroup::DefaultGroup, ParamType::TGLenum,
-                             matrixMode);
-
-    ParamCapture matrixParam("matrix", ParamType::TGLfloatConstPointer);
-    InitParamValue(ParamType::TGLfloatConstPointer, matrix, &matrixParam.value);
-    CaptureMatrixLoadfCHROMIUM_matrix(glState, isCallValid, matrixMode, matrix, &matrixParam);
-    paramBuffer.addParam(std::move(matrixParam));
-
-    return CallCapture(gl::EntryPoint::MatrixLoadfCHROMIUM, std::move(paramBuffer));
-}
-
-CallCapture CaptureMatrixLoadIdentityCHROMIUM(const State &glState,
-                                              bool isCallValid,
-                                              GLenum matrixMode)
-{
-    ParamBuffer paramBuffer;
-
-    paramBuffer.addEnumParam("matrixMode", GLenumGroup::DefaultGroup, ParamType::TGLenum,
-                             matrixMode);
-
-    return CallCapture(gl::EntryPoint::MatrixLoadIdentityCHROMIUM, std::move(paramBuffer));
-}
-
 CallCapture CaptureLoseContextCHROMIUM(const State &glState,
                                        bool isCallValid,
                                        GraphicsResetStatus currentPacked,
@@ -2840,544 +2810,6 @@
     return CallCapture(gl::EntryPoint::LoseContextCHROMIUM, std::move(paramBuffer));
 }
 
-CallCapture CaptureGenPathsCHROMIUM(const State &glState,
-                                    bool isCallValid,
-                                    GLsizei range,
-                                    GLuint returnValue)
-{
-    ParamBuffer paramBuffer;
-
-    paramBuffer.addValueParam("range", ParamType::TGLsizei, range);
-
-    ParamCapture returnValueCapture("returnValue", ParamType::TGLuint);
-    InitParamValue(ParamType::TGLuint, returnValue, &returnValueCapture.value);
-    paramBuffer.addReturnValue(std::move(returnValueCapture));
-
-    return CallCapture(gl::EntryPoint::GenPathsCHROMIUM, std::move(paramBuffer));
-}
-
-CallCapture CaptureDeletePathsCHROMIUM(const State &glState,
-                                       bool isCallValid,
-                                       PathID firstPacked,
-                                       GLsizei range)
-{
-    ParamBuffer paramBuffer;
-
-    paramBuffer.addValueParam("firstPacked", ParamType::TPathID, firstPacked);
-    paramBuffer.addValueParam("range", ParamType::TGLsizei, range);
-
-    return CallCapture(gl::EntryPoint::DeletePathsCHROMIUM, std::move(paramBuffer));
-}
-
-CallCapture CaptureIsPathCHROMIUM(const State &glState,
-                                  bool isCallValid,
-                                  PathID pathPacked,
-                                  GLboolean returnValue)
-{
-    ParamBuffer paramBuffer;
-
-    paramBuffer.addValueParam("pathPacked", ParamType::TPathID, pathPacked);
-
-    ParamCapture returnValueCapture("returnValue", ParamType::TGLboolean);
-    InitParamValue(ParamType::TGLboolean, returnValue, &returnValueCapture.value);
-    paramBuffer.addReturnValue(std::move(returnValueCapture));
-
-    return CallCapture(gl::EntryPoint::IsPathCHROMIUM, std::move(paramBuffer));
-}
-
-CallCapture CapturePathCommandsCHROMIUM(const State &glState,
-                                        bool isCallValid,
-                                        PathID pathPacked,
-                                        GLsizei numCommands,
-                                        const GLubyte *commands,
-                                        GLsizei numCoords,
-                                        GLenum coordType,
-                                        const void *coords)
-{
-    ParamBuffer paramBuffer;
-
-    paramBuffer.addValueParam("pathPacked", ParamType::TPathID, pathPacked);
-    paramBuffer.addValueParam("numCommands", ParamType::TGLsizei, numCommands);
-
-    ParamCapture commandsParam("commands", ParamType::TGLubyteConstPointer);
-    InitParamValue(ParamType::TGLubyteConstPointer, commands, &commandsParam.value);
-    CapturePathCommandsCHROMIUM_commands(glState, isCallValid, pathPacked, numCommands, commands,
-                                         numCoords, coordType, coords, &commandsParam);
-    paramBuffer.addParam(std::move(commandsParam));
-
-    paramBuffer.addValueParam("numCoords", ParamType::TGLsizei, numCoords);
-    paramBuffer.addEnumParam("coordType", GLenumGroup::DefaultGroup, ParamType::TGLenum, coordType);
-
-    ParamCapture coordsParam("coords", ParamType::TvoidConstPointer);
-    InitParamValue(ParamType::TvoidConstPointer, coords, &coordsParam.value);
-    CapturePathCommandsCHROMIUM_coords(glState, isCallValid, pathPacked, numCommands, commands,
-                                       numCoords, coordType, coords, &coordsParam);
-    paramBuffer.addParam(std::move(coordsParam));
-
-    return CallCapture(gl::EntryPoint::PathCommandsCHROMIUM, std::move(paramBuffer));
-}
-
-CallCapture CapturePathParameterfCHROMIUM(const State &glState,
-                                          bool isCallValid,
-                                          PathID pathPacked,
-                                          GLenum pname,
-                                          GLfloat value)
-{
-    ParamBuffer paramBuffer;
-
-    paramBuffer.addValueParam("pathPacked", ParamType::TPathID, pathPacked);
-    paramBuffer.addEnumParam("pname", GLenumGroup::DefaultGroup, ParamType::TGLenum, pname);
-    paramBuffer.addValueParam("value", ParamType::TGLfloat, value);
-
-    return CallCapture(gl::EntryPoint::PathParameterfCHROMIUM, std::move(paramBuffer));
-}
-
-CallCapture CapturePathParameteriCHROMIUM(const State &glState,
-                                          bool isCallValid,
-                                          PathID pathPacked,
-                                          GLenum pname,
-                                          GLint value)
-{
-    ParamBuffer paramBuffer;
-
-    paramBuffer.addValueParam("pathPacked", ParamType::TPathID, pathPacked);
-    paramBuffer.addEnumParam("pname", GLenumGroup::DefaultGroup, ParamType::TGLenum, pname);
-    paramBuffer.addValueParam("value", ParamType::TGLint, value);
-
-    return CallCapture(gl::EntryPoint::PathParameteriCHROMIUM, std::move(paramBuffer));
-}
-
-CallCapture CaptureGetPathParameterfvCHROMIUM(const State &glState,
-                                              bool isCallValid,
-                                              PathID pathPacked,
-                                              GLenum pname,
-                                              GLfloat *value)
-{
-    ParamBuffer paramBuffer;
-
-    paramBuffer.addValueParam("pathPacked", ParamType::TPathID, pathPacked);
-    paramBuffer.addEnumParam("pname", GLenumGroup::DefaultGroup, ParamType::TGLenum, pname);
-
-    ParamCapture valueParam("value", ParamType::TGLfloatPointer);
-    InitParamValue(ParamType::TGLfloatPointer, value, &valueParam.value);
-    CaptureGetPathParameterfvCHROMIUM_value(glState, isCallValid, pathPacked, pname, value,
-                                            &valueParam);
-    paramBuffer.addParam(std::move(valueParam));
-
-    return CallCapture(gl::EntryPoint::GetPathParameterfvCHROMIUM, std::move(paramBuffer));
-}
-
-CallCapture CaptureGetPathParameterivCHROMIUM(const State &glState,
-                                              bool isCallValid,
-                                              PathID pathPacked,
-                                              GLenum pname,
-                                              GLint *value)
-{
-    ParamBuffer paramBuffer;
-
-    paramBuffer.addValueParam("pathPacked", ParamType::TPathID, pathPacked);
-    paramBuffer.addEnumParam("pname", GLenumGroup::DefaultGroup, ParamType::TGLenum, pname);
-
-    ParamCapture valueParam("value", ParamType::TGLintPointer);
-    InitParamValue(ParamType::TGLintPointer, value, &valueParam.value);
-    CaptureGetPathParameterivCHROMIUM_value(glState, isCallValid, pathPacked, pname, value,
-                                            &valueParam);
-    paramBuffer.addParam(std::move(valueParam));
-
-    return CallCapture(gl::EntryPoint::GetPathParameterivCHROMIUM, std::move(paramBuffer));
-}
-
-CallCapture CapturePathStencilFuncCHROMIUM(const State &glState,
-                                           bool isCallValid,
-                                           GLenum func,
-                                           GLint ref,
-                                           GLuint mask)
-{
-    ParamBuffer paramBuffer;
-
-    paramBuffer.addEnumParam("func", GLenumGroup::DefaultGroup, ParamType::TGLenum, func);
-    paramBuffer.addValueParam("ref", ParamType::TGLint, ref);
-    paramBuffer.addValueParam("mask", ParamType::TGLuint, mask);
-
-    return CallCapture(gl::EntryPoint::PathStencilFuncCHROMIUM, std::move(paramBuffer));
-}
-
-CallCapture CaptureStencilFillPathCHROMIUM(const State &glState,
-                                           bool isCallValid,
-                                           PathID pathPacked,
-                                           GLenum fillMode,
-                                           GLuint mask)
-{
-    ParamBuffer paramBuffer;
-
-    paramBuffer.addValueParam("pathPacked", ParamType::TPathID, pathPacked);
-    paramBuffer.addEnumParam("fillMode", GLenumGroup::DefaultGroup, ParamType::TGLenum, fillMode);
-    paramBuffer.addValueParam("mask", ParamType::TGLuint, mask);
-
-    return CallCapture(gl::EntryPoint::StencilFillPathCHROMIUM, std::move(paramBuffer));
-}
-
-CallCapture CaptureStencilStrokePathCHROMIUM(const State &glState,
-                                             bool isCallValid,
-                                             PathID pathPacked,
-                                             GLint reference,
-                                             GLuint mask)
-{
-    ParamBuffer paramBuffer;
-
-    paramBuffer.addValueParam("pathPacked", ParamType::TPathID, pathPacked);
-    paramBuffer.addValueParam("reference", ParamType::TGLint, reference);
-    paramBuffer.addValueParam("mask", ParamType::TGLuint, mask);
-
-    return CallCapture(gl::EntryPoint::StencilStrokePathCHROMIUM, std::move(paramBuffer));
-}
-
-CallCapture CaptureCoverFillPathCHROMIUM(const State &glState,
-                                         bool isCallValid,
-                                         PathID pathPacked,
-                                         GLenum coverMode)
-{
-    ParamBuffer paramBuffer;
-
-    paramBuffer.addValueParam("pathPacked", ParamType::TPathID, pathPacked);
-    paramBuffer.addEnumParam("coverMode", GLenumGroup::DefaultGroup, ParamType::TGLenum, coverMode);
-
-    return CallCapture(gl::EntryPoint::CoverFillPathCHROMIUM, std::move(paramBuffer));
-}
-
-CallCapture CaptureCoverStrokePathCHROMIUM(const State &glState,
-                                           bool isCallValid,
-                                           PathID pathPacked,
-                                           GLenum coverMode)
-{
-    ParamBuffer paramBuffer;
-
-    paramBuffer.addValueParam("pathPacked", ParamType::TPathID, pathPacked);
-    paramBuffer.addEnumParam("coverMode", GLenumGroup::DefaultGroup, ParamType::TGLenum, coverMode);
-
-    return CallCapture(gl::EntryPoint::CoverStrokePathCHROMIUM, std::move(paramBuffer));
-}
-
-CallCapture CaptureStencilThenCoverFillPathCHROMIUM(const State &glState,
-                                                    bool isCallValid,
-                                                    PathID pathPacked,
-                                                    GLenum fillMode,
-                                                    GLuint mask,
-                                                    GLenum coverMode)
-{
-    ParamBuffer paramBuffer;
-
-    paramBuffer.addValueParam("pathPacked", ParamType::TPathID, pathPacked);
-    paramBuffer.addEnumParam("fillMode", GLenumGroup::DefaultGroup, ParamType::TGLenum, fillMode);
-    paramBuffer.addValueParam("mask", ParamType::TGLuint, mask);
-    paramBuffer.addEnumParam("coverMode", GLenumGroup::DefaultGroup, ParamType::TGLenum, coverMode);
-
-    return CallCapture(gl::EntryPoint::StencilThenCoverFillPathCHROMIUM, std::move(paramBuffer));
-}
-
-CallCapture CaptureStencilThenCoverStrokePathCHROMIUM(const State &glState,
-                                                      bool isCallValid,
-                                                      PathID pathPacked,
-                                                      GLint reference,
-                                                      GLuint mask,
-                                                      GLenum coverMode)
-{
-    ParamBuffer paramBuffer;
-
-    paramBuffer.addValueParam("pathPacked", ParamType::TPathID, pathPacked);
-    paramBuffer.addValueParam("reference", ParamType::TGLint, reference);
-    paramBuffer.addValueParam("mask", ParamType::TGLuint, mask);
-    paramBuffer.addEnumParam("coverMode", GLenumGroup::DefaultGroup, ParamType::TGLenum, coverMode);
-
-    return CallCapture(gl::EntryPoint::StencilThenCoverStrokePathCHROMIUM, std::move(paramBuffer));
-}
-
-CallCapture CaptureCoverFillPathInstancedCHROMIUM(const State &glState,
-                                                  bool isCallValid,
-                                                  GLsizei numPath,
-                                                  GLenum pathNameType,
-                                                  const void *paths,
-                                                  PathID pathBasePacked,
-                                                  GLenum coverMode,
-                                                  GLenum transformType,
-                                                  const GLfloat *transformValues)
-{
-    ParamBuffer paramBuffer;
-
-    paramBuffer.addValueParam("numPath", ParamType::TGLsizei, numPath);
-    paramBuffer.addEnumParam("pathNameType", GLenumGroup::DefaultGroup, ParamType::TGLenum,
-                             pathNameType);
-
-    ParamCapture pathsParam("paths", ParamType::TvoidConstPointer);
-    InitParamValue(ParamType::TvoidConstPointer, paths, &pathsParam.value);
-    CaptureCoverFillPathInstancedCHROMIUM_paths(glState, isCallValid, numPath, pathNameType, paths,
-                                                pathBasePacked, coverMode, transformType,
-                                                transformValues, &pathsParam);
-    paramBuffer.addParam(std::move(pathsParam));
-
-    paramBuffer.addValueParam("pathBasePacked", ParamType::TPathID, pathBasePacked);
-    paramBuffer.addEnumParam("coverMode", GLenumGroup::DefaultGroup, ParamType::TGLenum, coverMode);
-    paramBuffer.addEnumParam("transformType", GLenumGroup::DefaultGroup, ParamType::TGLenum,
-                             transformType);
-
-    ParamCapture transformValuesParam("transformValues", ParamType::TGLfloatConstPointer);
-    InitParamValue(ParamType::TGLfloatConstPointer, transformValues, &transformValuesParam.value);
-    CaptureCoverFillPathInstancedCHROMIUM_transformValues(
-        glState, isCallValid, numPath, pathNameType, paths, pathBasePacked, coverMode,
-        transformType, transformValues, &transformValuesParam);
-    paramBuffer.addParam(std::move(transformValuesParam));
-
-    return CallCapture(gl::EntryPoint::CoverFillPathInstancedCHROMIUM, std::move(paramBuffer));
-}
-
-CallCapture CaptureCoverStrokePathInstancedCHROMIUM(const State &glState,
-                                                    bool isCallValid,
-                                                    GLsizei numPath,
-                                                    GLenum pathNameType,
-                                                    const void *paths,
-                                                    PathID pathBasePacked,
-                                                    GLenum coverMode,
-                                                    GLenum transformType,
-                                                    const GLfloat *transformValues)
-{
-    ParamBuffer paramBuffer;
-
-    paramBuffer.addValueParam("numPath", ParamType::TGLsizei, numPath);
-    paramBuffer.addEnumParam("pathNameType", GLenumGroup::DefaultGroup, ParamType::TGLenum,
-                             pathNameType);
-
-    ParamCapture pathsParam("paths", ParamType::TvoidConstPointer);
-    InitParamValue(ParamType::TvoidConstPointer, paths, &pathsParam.value);
-    CaptureCoverStrokePathInstancedCHROMIUM_paths(glState, isCallValid, numPath, pathNameType,
-                                                  paths, pathBasePacked, coverMode, transformType,
-                                                  transformValues, &pathsParam);
-    paramBuffer.addParam(std::move(pathsParam));
-
-    paramBuffer.addValueParam("pathBasePacked", ParamType::TPathID, pathBasePacked);
-    paramBuffer.addEnumParam("coverMode", GLenumGroup::DefaultGroup, ParamType::TGLenum, coverMode);
-    paramBuffer.addEnumParam("transformType", GLenumGroup::DefaultGroup, ParamType::TGLenum,
-                             transformType);
-
-    ParamCapture transformValuesParam("transformValues", ParamType::TGLfloatConstPointer);
-    InitParamValue(ParamType::TGLfloatConstPointer, transformValues, &transformValuesParam.value);
-    CaptureCoverStrokePathInstancedCHROMIUM_transformValues(
-        glState, isCallValid, numPath, pathNameType, paths, pathBasePacked, coverMode,
-        transformType, transformValues, &transformValuesParam);
-    paramBuffer.addParam(std::move(transformValuesParam));
-
-    return CallCapture(gl::EntryPoint::CoverStrokePathInstancedCHROMIUM, std::move(paramBuffer));
-}
-
-CallCapture CaptureStencilStrokePathInstancedCHROMIUM(const State &glState,
-                                                      bool isCallValid,
-                                                      GLsizei numPath,
-                                                      GLenum pathNameType,
-                                                      const void *paths,
-                                                      PathID pathBasePacked,
-                                                      GLint reference,
-                                                      GLuint mask,
-                                                      GLenum transformType,
-                                                      const GLfloat *transformValues)
-{
-    ParamBuffer paramBuffer;
-
-    paramBuffer.addValueParam("numPath", ParamType::TGLsizei, numPath);
-    paramBuffer.addEnumParam("pathNameType", GLenumGroup::DefaultGroup, ParamType::TGLenum,
-                             pathNameType);
-
-    ParamCapture pathsParam("paths", ParamType::TvoidConstPointer);
-    InitParamValue(ParamType::TvoidConstPointer, paths, &pathsParam.value);
-    CaptureStencilStrokePathInstancedCHROMIUM_paths(glState, isCallValid, numPath, pathNameType,
-                                                    paths, pathBasePacked, reference, mask,
-                                                    transformType, transformValues, &pathsParam);
-    paramBuffer.addParam(std::move(pathsParam));
-
-    paramBuffer.addValueParam("pathBasePacked", ParamType::TPathID, pathBasePacked);
-    paramBuffer.addValueParam("reference", ParamType::TGLint, reference);
-    paramBuffer.addValueParam("mask", ParamType::TGLuint, mask);
-    paramBuffer.addEnumParam("transformType", GLenumGroup::DefaultGroup, ParamType::TGLenum,
-                             transformType);
-
-    ParamCapture transformValuesParam("transformValues", ParamType::TGLfloatConstPointer);
-    InitParamValue(ParamType::TGLfloatConstPointer, transformValues, &transformValuesParam.value);
-    CaptureStencilStrokePathInstancedCHROMIUM_transformValues(
-        glState, isCallValid, numPath, pathNameType, paths, pathBasePacked, reference, mask,
-        transformType, transformValues, &transformValuesParam);
-    paramBuffer.addParam(std::move(transformValuesParam));
-
-    return CallCapture(gl::EntryPoint::StencilStrokePathInstancedCHROMIUM, std::move(paramBuffer));
-}
-
-CallCapture CaptureStencilFillPathInstancedCHROMIUM(const State &glState,
-                                                    bool isCallValid,
-                                                    GLsizei numPaths,
-                                                    GLenum pathNameType,
-                                                    const void *paths,
-                                                    PathID pathBasePacked,
-                                                    GLenum fillMode,
-                                                    GLuint mask,
-                                                    GLenum transformType,
-                                                    const GLfloat *transformValues)
-{
-    ParamBuffer paramBuffer;
-
-    paramBuffer.addValueParam("numPaths", ParamType::TGLsizei, numPaths);
-    paramBuffer.addEnumParam("pathNameType", GLenumGroup::DefaultGroup, ParamType::TGLenum,
-                             pathNameType);
-
-    ParamCapture pathsParam("paths", ParamType::TvoidConstPointer);
-    InitParamValue(ParamType::TvoidConstPointer, paths, &pathsParam.value);
-    CaptureStencilFillPathInstancedCHROMIUM_paths(glState, isCallValid, numPaths, pathNameType,
-                                                  paths, pathBasePacked, fillMode, mask,
-                                                  transformType, transformValues, &pathsParam);
-    paramBuffer.addParam(std::move(pathsParam));
-
-    paramBuffer.addValueParam("pathBasePacked", ParamType::TPathID, pathBasePacked);
-    paramBuffer.addEnumParam("fillMode", GLenumGroup::DefaultGroup, ParamType::TGLenum, fillMode);
-    paramBuffer.addValueParam("mask", ParamType::TGLuint, mask);
-    paramBuffer.addEnumParam("transformType", GLenumGroup::DefaultGroup, ParamType::TGLenum,
-                             transformType);
-
-    ParamCapture transformValuesParam("transformValues", ParamType::TGLfloatConstPointer);
-    InitParamValue(ParamType::TGLfloatConstPointer, transformValues, &transformValuesParam.value);
-    CaptureStencilFillPathInstancedCHROMIUM_transformValues(
-        glState, isCallValid, numPaths, pathNameType, paths, pathBasePacked, fillMode, mask,
-        transformType, transformValues, &transformValuesParam);
-    paramBuffer.addParam(std::move(transformValuesParam));
-
-    return CallCapture(gl::EntryPoint::StencilFillPathInstancedCHROMIUM, std::move(paramBuffer));
-}
-
-CallCapture CaptureStencilThenCoverFillPathInstancedCHROMIUM(const State &glState,
-                                                             bool isCallValid,
-                                                             GLsizei numPaths,
-                                                             GLenum pathNameType,
-                                                             const void *paths,
-                                                             PathID pathBasePacked,
-                                                             GLenum fillMode,
-                                                             GLuint mask,
-                                                             GLenum coverMode,
-                                                             GLenum transformType,
-                                                             const GLfloat *transformValues)
-{
-    ParamBuffer paramBuffer;
-
-    paramBuffer.addValueParam("numPaths", ParamType::TGLsizei, numPaths);
-    paramBuffer.addEnumParam("pathNameType", GLenumGroup::DefaultGroup, ParamType::TGLenum,
-                             pathNameType);
-
-    ParamCapture pathsParam("paths", ParamType::TvoidConstPointer);
-    InitParamValue(ParamType::TvoidConstPointer, paths, &pathsParam.value);
-    CaptureStencilThenCoverFillPathInstancedCHROMIUM_paths(
-        glState, isCallValid, numPaths, pathNameType, paths, pathBasePacked, fillMode, mask,
-        coverMode, transformType, transformValues, &pathsParam);
-    paramBuffer.addParam(std::move(pathsParam));
-
-    paramBuffer.addValueParam("pathBasePacked", ParamType::TPathID, pathBasePacked);
-    paramBuffer.addEnumParam("fillMode", GLenumGroup::DefaultGroup, ParamType::TGLenum, fillMode);
-    paramBuffer.addValueParam("mask", ParamType::TGLuint, mask);
-    paramBuffer.addEnumParam("coverMode", GLenumGroup::DefaultGroup, ParamType::TGLenum, coverMode);
-    paramBuffer.addEnumParam("transformType", GLenumGroup::DefaultGroup, ParamType::TGLenum,
-                             transformType);
-
-    ParamCapture transformValuesParam("transformValues", ParamType::TGLfloatConstPointer);
-    InitParamValue(ParamType::TGLfloatConstPointer, transformValues, &transformValuesParam.value);
-    CaptureStencilThenCoverFillPathInstancedCHROMIUM_transformValues(
-        glState, isCallValid, numPaths, pathNameType, paths, pathBasePacked, fillMode, mask,
-        coverMode, transformType, transformValues, &transformValuesParam);
-    paramBuffer.addParam(std::move(transformValuesParam));
-
-    return CallCapture(gl::EntryPoint::StencilThenCoverFillPathInstancedCHROMIUM,
-                       std::move(paramBuffer));
-}
-
-CallCapture CaptureStencilThenCoverStrokePathInstancedCHROMIUM(const State &glState,
-                                                               bool isCallValid,
-                                                               GLsizei numPaths,
-                                                               GLenum pathNameType,
-                                                               const void *paths,
-                                                               PathID pathBasePacked,
-                                                               GLint reference,
-                                                               GLuint mask,
-                                                               GLenum coverMode,
-                                                               GLenum transformType,
-                                                               const GLfloat *transformValues)
-{
-    ParamBuffer paramBuffer;
-
-    paramBuffer.addValueParam("numPaths", ParamType::TGLsizei, numPaths);
-    paramBuffer.addEnumParam("pathNameType", GLenumGroup::DefaultGroup, ParamType::TGLenum,
-                             pathNameType);
-
-    ParamCapture pathsParam("paths", ParamType::TvoidConstPointer);
-    InitParamValue(ParamType::TvoidConstPointer, paths, &pathsParam.value);
-    CaptureStencilThenCoverStrokePathInstancedCHROMIUM_paths(
-        glState, isCallValid, numPaths, pathNameType, paths, pathBasePacked, reference, mask,
-        coverMode, transformType, transformValues, &pathsParam);
-    paramBuffer.addParam(std::move(pathsParam));
-
-    paramBuffer.addValueParam("pathBasePacked", ParamType::TPathID, pathBasePacked);
-    paramBuffer.addValueParam("reference", ParamType::TGLint, reference);
-    paramBuffer.addValueParam("mask", ParamType::TGLuint, mask);
-    paramBuffer.addEnumParam("coverMode", GLenumGroup::DefaultGroup, ParamType::TGLenum, coverMode);
-    paramBuffer.addEnumParam("transformType", GLenumGroup::DefaultGroup, ParamType::TGLenum,
-                             transformType);
-
-    ParamCapture transformValuesParam("transformValues", ParamType::TGLfloatConstPointer);
-    InitParamValue(ParamType::TGLfloatConstPointer, transformValues, &transformValuesParam.value);
-    CaptureStencilThenCoverStrokePathInstancedCHROMIUM_transformValues(
-        glState, isCallValid, numPaths, pathNameType, paths, pathBasePacked, reference, mask,
-        coverMode, transformType, transformValues, &transformValuesParam);
-    paramBuffer.addParam(std::move(transformValuesParam));
-
-    return CallCapture(gl::EntryPoint::StencilThenCoverStrokePathInstancedCHROMIUM,
-                       std::move(paramBuffer));
-}
-
-CallCapture CaptureBindFragmentInputLocationCHROMIUM(const State &glState,
-                                                     bool isCallValid,
-                                                     ShaderProgramID programsPacked,
-                                                     GLint location,
-                                                     const GLchar *name)
-{
-    ParamBuffer paramBuffer;
-
-    paramBuffer.addValueParam("programsPacked", ParamType::TShaderProgramID, programsPacked);
-    paramBuffer.addValueParam("location", ParamType::TGLint, location);
-
-    ParamCapture nameParam("name", ParamType::TGLcharConstPointer);
-    InitParamValue(ParamType::TGLcharConstPointer, name, &nameParam.value);
-    CaptureBindFragmentInputLocationCHROMIUM_name(glState, isCallValid, programsPacked, location,
-                                                  name, &nameParam);
-    paramBuffer.addParam(std::move(nameParam));
-
-    return CallCapture(gl::EntryPoint::BindFragmentInputLocationCHROMIUM, std::move(paramBuffer));
-}
-
-CallCapture CaptureProgramPathFragmentInputGenCHROMIUM(const State &glState,
-                                                       bool isCallValid,
-                                                       ShaderProgramID programPacked,
-                                                       GLint location,
-                                                       GLenum genMode,
-                                                       GLint components,
-                                                       const GLfloat *coeffs)
-{
-    ParamBuffer paramBuffer;
-
-    paramBuffer.addValueParam("programPacked", ParamType::TShaderProgramID, programPacked);
-    paramBuffer.addValueParam("location", ParamType::TGLint, location);
-    paramBuffer.addEnumParam("genMode", GLenumGroup::DefaultGroup, ParamType::TGLenum, genMode);
-    paramBuffer.addValueParam("components", ParamType::TGLint, components);
-
-    ParamCapture coeffsParam("coeffs", ParamType::TGLfloatConstPointer);
-    InitParamValue(ParamType::TGLfloatConstPointer, coeffs, &coeffsParam.value);
-    CaptureProgramPathFragmentInputGenCHROMIUM_coeffs(glState, isCallValid, programPacked, location,
-                                                      genMode, components, coeffs, &coeffsParam);
-    paramBuffer.addParam(std::move(coeffsParam));
-
-    return CallCapture(gl::EntryPoint::ProgramPathFragmentInputGenCHROMIUM, std::move(paramBuffer));
-}
-
 CallCapture CaptureBindFragDataLocationEXT(const State &glState,
                                            bool isCallValid,
                                            ShaderProgramID programPacked,
diff --git a/src/libANGLE/capture_gles_ext_autogen.h b/src/libANGLE/capture_gles_ext_autogen.h
index 9e05b40..a427f0f 100644
--- a/src/libANGLE/capture_gles_ext_autogen.h
+++ b/src/libANGLE/capture_gles_ext_autogen.h
@@ -807,13 +807,6 @@
 angle::CallCapture CaptureCoverageModulationCHROMIUM(const State &glState,
                                                      bool isCallValid,
                                                      GLenum components);
-angle::CallCapture CaptureMatrixLoadfCHROMIUM(const State &glState,
-                                              bool isCallValid,
-                                              GLenum matrixMode,
-                                              const GLfloat *matrix);
-angle::CallCapture CaptureMatrixLoadIdentityCHROMIUM(const State &glState,
-                                                     bool isCallValid,
-                                                     GLenum matrixMode);
 
 // GL_CHROMIUM_lose_context
 angle::CallCapture CaptureLoseContextCHROMIUM(const State &glState,
@@ -821,156 +814,6 @@
                                               GraphicsResetStatus currentPacked,
                                               GraphicsResetStatus otherPacked);
 
-// GL_CHROMIUM_path_rendering
-angle::CallCapture CaptureGenPathsCHROMIUM(const State &glState,
-                                           bool isCallValid,
-                                           GLsizei range,
-                                           GLuint returnValue);
-angle::CallCapture CaptureDeletePathsCHROMIUM(const State &glState,
-                                              bool isCallValid,
-                                              PathID firstPacked,
-                                              GLsizei range);
-angle::CallCapture CaptureIsPathCHROMIUM(const State &glState,
-                                         bool isCallValid,
-                                         PathID pathPacked,
-                                         GLboolean returnValue);
-angle::CallCapture CapturePathCommandsCHROMIUM(const State &glState,
-                                               bool isCallValid,
-                                               PathID pathPacked,
-                                               GLsizei numCommands,
-                                               const GLubyte *commands,
-                                               GLsizei numCoords,
-                                               GLenum coordType,
-                                               const void *coords);
-angle::CallCapture CapturePathParameterfCHROMIUM(const State &glState,
-                                                 bool isCallValid,
-                                                 PathID pathPacked,
-                                                 GLenum pname,
-                                                 GLfloat value);
-angle::CallCapture CapturePathParameteriCHROMIUM(const State &glState,
-                                                 bool isCallValid,
-                                                 PathID pathPacked,
-                                                 GLenum pname,
-                                                 GLint value);
-angle::CallCapture CaptureGetPathParameterfvCHROMIUM(const State &glState,
-                                                     bool isCallValid,
-                                                     PathID pathPacked,
-                                                     GLenum pname,
-                                                     GLfloat *value);
-angle::CallCapture CaptureGetPathParameterivCHROMIUM(const State &glState,
-                                                     bool isCallValid,
-                                                     PathID pathPacked,
-                                                     GLenum pname,
-                                                     GLint *value);
-angle::CallCapture CapturePathStencilFuncCHROMIUM(const State &glState,
-                                                  bool isCallValid,
-                                                  GLenum func,
-                                                  GLint ref,
-                                                  GLuint mask);
-angle::CallCapture CaptureStencilFillPathCHROMIUM(const State &glState,
-                                                  bool isCallValid,
-                                                  PathID pathPacked,
-                                                  GLenum fillMode,
-                                                  GLuint mask);
-angle::CallCapture CaptureStencilStrokePathCHROMIUM(const State &glState,
-                                                    bool isCallValid,
-                                                    PathID pathPacked,
-                                                    GLint reference,
-                                                    GLuint mask);
-angle::CallCapture CaptureCoverFillPathCHROMIUM(const State &glState,
-                                                bool isCallValid,
-                                                PathID pathPacked,
-                                                GLenum coverMode);
-angle::CallCapture CaptureCoverStrokePathCHROMIUM(const State &glState,
-                                                  bool isCallValid,
-                                                  PathID pathPacked,
-                                                  GLenum coverMode);
-angle::CallCapture CaptureStencilThenCoverFillPathCHROMIUM(const State &glState,
-                                                           bool isCallValid,
-                                                           PathID pathPacked,
-                                                           GLenum fillMode,
-                                                           GLuint mask,
-                                                           GLenum coverMode);
-angle::CallCapture CaptureStencilThenCoverStrokePathCHROMIUM(const State &glState,
-                                                             bool isCallValid,
-                                                             PathID pathPacked,
-                                                             GLint reference,
-                                                             GLuint mask,
-                                                             GLenum coverMode);
-angle::CallCapture CaptureCoverFillPathInstancedCHROMIUM(const State &glState,
-                                                         bool isCallValid,
-                                                         GLsizei numPath,
-                                                         GLenum pathNameType,
-                                                         const void *paths,
-                                                         PathID pathBasePacked,
-                                                         GLenum coverMode,
-                                                         GLenum transformType,
-                                                         const GLfloat *transformValues);
-angle::CallCapture CaptureCoverStrokePathInstancedCHROMIUM(const State &glState,
-                                                           bool isCallValid,
-                                                           GLsizei numPath,
-                                                           GLenum pathNameType,
-                                                           const void *paths,
-                                                           PathID pathBasePacked,
-                                                           GLenum coverMode,
-                                                           GLenum transformType,
-                                                           const GLfloat *transformValues);
-angle::CallCapture CaptureStencilStrokePathInstancedCHROMIUM(const State &glState,
-                                                             bool isCallValid,
-                                                             GLsizei numPath,
-                                                             GLenum pathNameType,
-                                                             const void *paths,
-                                                             PathID pathBasePacked,
-                                                             GLint reference,
-                                                             GLuint mask,
-                                                             GLenum transformType,
-                                                             const GLfloat *transformValues);
-angle::CallCapture CaptureStencilFillPathInstancedCHROMIUM(const State &glState,
-                                                           bool isCallValid,
-                                                           GLsizei numPaths,
-                                                           GLenum pathNameType,
-                                                           const void *paths,
-                                                           PathID pathBasePacked,
-                                                           GLenum fillMode,
-                                                           GLuint mask,
-                                                           GLenum transformType,
-                                                           const GLfloat *transformValues);
-angle::CallCapture CaptureStencilThenCoverFillPathInstancedCHROMIUM(const State &glState,
-                                                                    bool isCallValid,
-                                                                    GLsizei numPaths,
-                                                                    GLenum pathNameType,
-                                                                    const void *paths,
-                                                                    PathID pathBasePacked,
-                                                                    GLenum fillMode,
-                                                                    GLuint mask,
-                                                                    GLenum coverMode,
-                                                                    GLenum transformType,
-                                                                    const GLfloat *transformValues);
-angle::CallCapture CaptureStencilThenCoverStrokePathInstancedCHROMIUM(
-    const State &glState,
-    bool isCallValid,
-    GLsizei numPaths,
-    GLenum pathNameType,
-    const void *paths,
-    PathID pathBasePacked,
-    GLint reference,
-    GLuint mask,
-    GLenum coverMode,
-    GLenum transformType,
-    const GLfloat *transformValues);
-angle::CallCapture CaptureBindFragmentInputLocationCHROMIUM(const State &glState,
-                                                            bool isCallValid,
-                                                            ShaderProgramID programsPacked,
-                                                            GLint location,
-                                                            const GLchar *name);
-angle::CallCapture CaptureProgramPathFragmentInputGenCHROMIUM(const State &glState,
-                                                              bool isCallValid,
-                                                              ShaderProgramID programPacked,
-                                                              GLint location,
-                                                              GLenum genMode,
-                                                              GLint components,
-                                                              const GLfloat *coeffs);
-
 // GL_EXT_blend_func_extended
 angle::CallCapture CaptureBindFragDataLocationEXT(const State &glState,
                                                   bool isCallValid,
@@ -1389,6 +1232,8 @@
 
 // GL_EXT_texture_format_BGRA8888
 
+// GL_EXT_texture_sRGB_R8
+
 // GL_EXT_texture_storage
 angle::CallCapture CaptureTexStorage1DEXT(const State &glState,
                                           bool isCallValid,
@@ -3252,189 +3097,6 @@
                                              UniformLocation locationPacked,
                                              const GLchar *name,
                                              angle::ParamCapture *paramCapture);
-void CaptureMatrixLoadfCHROMIUM_matrix(const State &glState,
-                                       bool isCallValid,
-                                       GLenum matrixMode,
-                                       const GLfloat *matrix,
-                                       angle::ParamCapture *paramCapture);
-void CapturePathCommandsCHROMIUM_commands(const State &glState,
-                                          bool isCallValid,
-                                          PathID pathPacked,
-                                          GLsizei numCommands,
-                                          const GLubyte *commands,
-                                          GLsizei numCoords,
-                                          GLenum coordType,
-                                          const void *coords,
-                                          angle::ParamCapture *paramCapture);
-void CapturePathCommandsCHROMIUM_coords(const State &glState,
-                                        bool isCallValid,
-                                        PathID pathPacked,
-                                        GLsizei numCommands,
-                                        const GLubyte *commands,
-                                        GLsizei numCoords,
-                                        GLenum coordType,
-                                        const void *coords,
-                                        angle::ParamCapture *paramCapture);
-void CaptureGetPathParameterfvCHROMIUM_value(const State &glState,
-                                             bool isCallValid,
-                                             PathID pathPacked,
-                                             GLenum pname,
-                                             GLfloat *value,
-                                             angle::ParamCapture *paramCapture);
-void CaptureGetPathParameterivCHROMIUM_value(const State &glState,
-                                             bool isCallValid,
-                                             PathID pathPacked,
-                                             GLenum pname,
-                                             GLint *value,
-                                             angle::ParamCapture *paramCapture);
-void CaptureCoverFillPathInstancedCHROMIUM_paths(const State &glState,
-                                                 bool isCallValid,
-                                                 GLsizei numPath,
-                                                 GLenum pathNameType,
-                                                 const void *paths,
-                                                 PathID pathBasePacked,
-                                                 GLenum coverMode,
-                                                 GLenum transformType,
-                                                 const GLfloat *transformValues,
-                                                 angle::ParamCapture *paramCapture);
-void CaptureCoverFillPathInstancedCHROMIUM_transformValues(const State &glState,
-                                                           bool isCallValid,
-                                                           GLsizei numPath,
-                                                           GLenum pathNameType,
-                                                           const void *paths,
-                                                           PathID pathBasePacked,
-                                                           GLenum coverMode,
-                                                           GLenum transformType,
-                                                           const GLfloat *transformValues,
-                                                           angle::ParamCapture *paramCapture);
-void CaptureCoverStrokePathInstancedCHROMIUM_paths(const State &glState,
-                                                   bool isCallValid,
-                                                   GLsizei numPath,
-                                                   GLenum pathNameType,
-                                                   const void *paths,
-                                                   PathID pathBasePacked,
-                                                   GLenum coverMode,
-                                                   GLenum transformType,
-                                                   const GLfloat *transformValues,
-                                                   angle::ParamCapture *paramCapture);
-void CaptureCoverStrokePathInstancedCHROMIUM_transformValues(const State &glState,
-                                                             bool isCallValid,
-                                                             GLsizei numPath,
-                                                             GLenum pathNameType,
-                                                             const void *paths,
-                                                             PathID pathBasePacked,
-                                                             GLenum coverMode,
-                                                             GLenum transformType,
-                                                             const GLfloat *transformValues,
-                                                             angle::ParamCapture *paramCapture);
-void CaptureStencilStrokePathInstancedCHROMIUM_paths(const State &glState,
-                                                     bool isCallValid,
-                                                     GLsizei numPath,
-                                                     GLenum pathNameType,
-                                                     const void *paths,
-                                                     PathID pathBasePacked,
-                                                     GLint reference,
-                                                     GLuint mask,
-                                                     GLenum transformType,
-                                                     const GLfloat *transformValues,
-                                                     angle::ParamCapture *paramCapture);
-void CaptureStencilStrokePathInstancedCHROMIUM_transformValues(const State &glState,
-                                                               bool isCallValid,
-                                                               GLsizei numPath,
-                                                               GLenum pathNameType,
-                                                               const void *paths,
-                                                               PathID pathBasePacked,
-                                                               GLint reference,
-                                                               GLuint mask,
-                                                               GLenum transformType,
-                                                               const GLfloat *transformValues,
-                                                               angle::ParamCapture *paramCapture);
-void CaptureStencilFillPathInstancedCHROMIUM_paths(const State &glState,
-                                                   bool isCallValid,
-                                                   GLsizei numPaths,
-                                                   GLenum pathNameType,
-                                                   const void *paths,
-                                                   PathID pathBasePacked,
-                                                   GLenum fillMode,
-                                                   GLuint mask,
-                                                   GLenum transformType,
-                                                   const GLfloat *transformValues,
-                                                   angle::ParamCapture *paramCapture);
-void CaptureStencilFillPathInstancedCHROMIUM_transformValues(const State &glState,
-                                                             bool isCallValid,
-                                                             GLsizei numPaths,
-                                                             GLenum pathNameType,
-                                                             const void *paths,
-                                                             PathID pathBasePacked,
-                                                             GLenum fillMode,
-                                                             GLuint mask,
-                                                             GLenum transformType,
-                                                             const GLfloat *transformValues,
-                                                             angle::ParamCapture *paramCapture);
-void CaptureStencilThenCoverFillPathInstancedCHROMIUM_paths(const State &glState,
-                                                            bool isCallValid,
-                                                            GLsizei numPaths,
-                                                            GLenum pathNameType,
-                                                            const void *paths,
-                                                            PathID pathBasePacked,
-                                                            GLenum fillMode,
-                                                            GLuint mask,
-                                                            GLenum coverMode,
-                                                            GLenum transformType,
-                                                            const GLfloat *transformValues,
-                                                            angle::ParamCapture *paramCapture);
-void CaptureStencilThenCoverFillPathInstancedCHROMIUM_transformValues(
-    const State &glState,
-    bool isCallValid,
-    GLsizei numPaths,
-    GLenum pathNameType,
-    const void *paths,
-    PathID pathBasePacked,
-    GLenum fillMode,
-    GLuint mask,
-    GLenum coverMode,
-    GLenum transformType,
-    const GLfloat *transformValues,
-    angle::ParamCapture *paramCapture);
-void CaptureStencilThenCoverStrokePathInstancedCHROMIUM_paths(const State &glState,
-                                                              bool isCallValid,
-                                                              GLsizei numPaths,
-                                                              GLenum pathNameType,
-                                                              const void *paths,
-                                                              PathID pathBasePacked,
-                                                              GLint reference,
-                                                              GLuint mask,
-                                                              GLenum coverMode,
-                                                              GLenum transformType,
-                                                              const GLfloat *transformValues,
-                                                              angle::ParamCapture *paramCapture);
-void CaptureStencilThenCoverStrokePathInstancedCHROMIUM_transformValues(
-    const State &glState,
-    bool isCallValid,
-    GLsizei numPaths,
-    GLenum pathNameType,
-    const void *paths,
-    PathID pathBasePacked,
-    GLint reference,
-    GLuint mask,
-    GLenum coverMode,
-    GLenum transformType,
-    const GLfloat *transformValues,
-    angle::ParamCapture *paramCapture);
-void CaptureBindFragmentInputLocationCHROMIUM_name(const State &glState,
-                                                   bool isCallValid,
-                                                   ShaderProgramID programsPacked,
-                                                   GLint location,
-                                                   const GLchar *name,
-                                                   angle::ParamCapture *paramCapture);
-void CaptureProgramPathFragmentInputGenCHROMIUM_coeffs(const State &glState,
-                                                       bool isCallValid,
-                                                       ShaderProgramID programPacked,
-                                                       GLint location,
-                                                       GLenum genMode,
-                                                       GLint components,
-                                                       const GLfloat *coeffs,
-                                                       angle::ParamCapture *paramCapture);
 void CaptureBindFragDataLocationEXT_name(const State &glState,
                                          bool isCallValid,
                                          ShaderProgramID programPacked,
diff --git a/src/libANGLE/capture_gles_ext_params.cpp b/src/libANGLE/capture_gles_ext_params.cpp
index e459e88..3e66880 100644
--- a/src/libANGLE/capture_gles_ext_params.cpp
+++ b/src/libANGLE/capture_gles_ext_params.cpp
@@ -8,6 +8,7 @@
 
 #include "libANGLE/capture_gles_ext_autogen.h"
 
+#include "libANGLE/capture_gles_2_0_autogen.h"
 #include "libANGLE/capture_gles_3_0_autogen.h"
 
 using namespace angle;
@@ -262,7 +263,8 @@
                                               GLint basevertex,
                                               ParamCapture *indicesParam)
 {
-    UNIMPLEMENTED();
+    CaptureDrawElements_indices(glState, isCallValid, modePacked, count, typePacked, indices,
+                                indicesParam);
 }
 
 void CaptureDrawElementsInstancedBaseVertexOES_indices(const State &glState,
@@ -418,7 +420,7 @@
                                        const GLchar *name,
                                        ParamCapture *paramCapture)
 {
-    UNIMPLEMENTED();
+    CaptureString(name, paramCapture);
 }
 
 void CaptureDisableExtensionANGLE_name(const State &glState,
@@ -426,7 +428,7 @@
                                        const GLchar *name,
                                        ParamCapture *paramCapture)
 {
-    UNIMPLEMENTED();
+    CaptureString(name, paramCapture);
 }
 
 void CaptureGetBooleanvRobustANGLE_length(const State &glState,
@@ -1968,7 +1970,7 @@
                                              const GLchar *name,
                                              ParamCapture *paramCapture)
 {
-    UNIMPLEMENTED();
+    CaptureString(name, paramCapture);
 }
 
 void CaptureMatrixLoadfCHROMIUM_matrix(const State &glState,
@@ -2215,7 +2217,7 @@
                                                    const GLchar *name,
                                                    ParamCapture *paramCapture)
 {
-    UNIMPLEMENTED();
+    CaptureString(name, paramCapture);
 }
 
 void CaptureProgramPathFragmentInputGenCHROMIUM_coeffs(const State &glState,
@@ -2237,7 +2239,7 @@
                                          const GLchar *name,
                                          ParamCapture *paramCapture)
 {
-    UNIMPLEMENTED();
+    CaptureString(name, paramCapture);
 }
 
 void CaptureBindFragDataLocationIndexedEXT_name(const State &glState,
@@ -2248,7 +2250,7 @@
                                                 const GLchar *name,
                                                 ParamCapture *paramCapture)
 {
-    UNIMPLEMENTED();
+    CaptureString(name, paramCapture);
 }
 
 void CaptureGetFragDataIndexEXT_name(const State &glState,
@@ -2257,7 +2259,7 @@
                                      const GLchar *name,
                                      ParamCapture *paramCapture)
 {
-    UNIMPLEMENTED();
+    CaptureString(name, paramCapture);
 }
 
 void CaptureGetProgramResourceLocationIndexEXT_name(const State &glState,
@@ -2267,7 +2269,7 @@
                                                     const GLchar *name,
                                                     ParamCapture *paramCapture)
 {
-    UNIMPLEMENTED();
+    CaptureString(name, paramCapture);
 }
 
 void CaptureInsertEventMarkerEXT_marker(const State &glState,
@@ -3111,7 +3113,8 @@
                                  const void *pixels,
                                  ParamCapture *paramCapture)
 {
-    UNIMPLEMENTED();
+    CaptureTexImage3D_pixels(glState, isCallValid, targetPacked, level, internalformat, width,
+                             height, depth, border, format, type, pixels, paramCapture);
 }
 
 void CaptureTexSubImage3DOES_pixels(const State &glState,
@@ -3129,7 +3132,8 @@
                                     const void *pixels,
                                     ParamCapture *paramCapture)
 {
-    UNIMPLEMENTED();
+    CaptureTexSubImage3D_pixels(glState, isCallValid, targetPacked, level, xoffset, yoffset,
+                                zoffset, width, height, depth, format, type, pixels, paramCapture);
 }
 
 void CaptureGetSamplerParameterIivOES_params(const State &glState,
diff --git a/src/libANGLE/entry_points_enum_autogen.cpp b/src/libANGLE/entry_points_enum_autogen.cpp
index 8615c00..e2a2262 100644
--- a/src/libANGLE/entry_points_enum_autogen.cpp
+++ b/src/libANGLE/entry_points_enum_autogen.cpp
@@ -66,8 +66,6 @@
             return "glBindFragDataLocationIndexed";
         case EntryPoint::BindFragDataLocationIndexedEXT:
             return "glBindFragDataLocationIndexedEXT";
-        case EntryPoint::BindFragmentInputLocationCHROMIUM:
-            return "glBindFragmentInputLocationCHROMIUM";
         case EntryPoint::BindFramebuffer:
             return "glBindFramebuffer";
         case EntryPoint::BindFramebufferOES:
@@ -380,14 +378,6 @@
             return "glCopyTextureSubImage2D";
         case EntryPoint::CopyTextureSubImage3D:
             return "glCopyTextureSubImage3D";
-        case EntryPoint::CoverFillPathCHROMIUM:
-            return "glCoverFillPathCHROMIUM";
-        case EntryPoint::CoverFillPathInstancedCHROMIUM:
-            return "glCoverFillPathInstancedCHROMIUM";
-        case EntryPoint::CoverStrokePathCHROMIUM:
-            return "glCoverStrokePathCHROMIUM";
-        case EntryPoint::CoverStrokePathInstancedCHROMIUM:
-            return "glCoverStrokePathInstancedCHROMIUM";
         case EntryPoint::CoverageModulationCHROMIUM:
             return "glCoverageModulationCHROMIUM";
         case EntryPoint::CreateBuffers:
@@ -444,8 +434,6 @@
             return "glDeleteLists";
         case EntryPoint::DeleteMemoryObjectsEXT:
             return "glDeleteMemoryObjectsEXT";
-        case EntryPoint::DeletePathsCHROMIUM:
-            return "glDeletePathsCHROMIUM";
         case EntryPoint::DeleteProgram:
             return "glDeleteProgram";
         case EntryPoint::DeleteProgramPipelines:
@@ -738,8 +726,6 @@
             return "glGenFramebuffersOES";
         case EntryPoint::GenLists:
             return "glGenLists";
-        case EntryPoint::GenPathsCHROMIUM:
-            return "glGenPathsCHROMIUM";
         case EntryPoint::GenProgramPipelines:
             return "glGenProgramPipelines";
         case EntryPoint::GenQueries:
@@ -942,10 +928,6 @@
             return "glGetObjectPtrLabel";
         case EntryPoint::GetObjectPtrLabelKHR:
             return "glGetObjectPtrLabelKHR";
-        case EntryPoint::GetPathParameterfvCHROMIUM:
-            return "glGetPathParameterfvCHROMIUM";
-        case EntryPoint::GetPathParameterivCHROMIUM:
-            return "glGetPathParameterivCHROMIUM";
         case EntryPoint::GetPixelMapfv:
             return "glGetPixelMapfv";
         case EntryPoint::GetPixelMapuiv:
@@ -1346,8 +1328,6 @@
             return "glIsList";
         case EntryPoint::IsMemoryObjectEXT:
             return "glIsMemoryObjectEXT";
-        case EntryPoint::IsPathCHROMIUM:
-            return "glIsPathCHROMIUM";
         case EntryPoint::IsProgram:
             return "glIsProgram";
         case EntryPoint::IsProgramPipeline:
@@ -1472,10 +1452,6 @@
             return "glMaterialxv";
         case EntryPoint::MatrixIndexPointerOES:
             return "glMatrixIndexPointerOES";
-        case EntryPoint::MatrixLoadIdentityCHROMIUM:
-            return "glMatrixLoadIdentityCHROMIUM";
-        case EntryPoint::MatrixLoadfCHROMIUM:
-            return "glMatrixLoadfCHROMIUM";
         case EntryPoint::MatrixMode:
             return "glMatrixMode";
         case EntryPoint::MaxShaderCompilerThreadsKHR:
@@ -1682,14 +1658,6 @@
             return "glPatchParameterfv";
         case EntryPoint::PatchParameteri:
             return "glPatchParameteri";
-        case EntryPoint::PathCommandsCHROMIUM:
-            return "glPathCommandsCHROMIUM";
-        case EntryPoint::PathParameterfCHROMIUM:
-            return "glPathParameterfCHROMIUM";
-        case EntryPoint::PathParameteriCHROMIUM:
-            return "glPathParameteriCHROMIUM";
-        case EntryPoint::PathStencilFuncCHROMIUM:
-            return "glPathStencilFuncCHROMIUM";
         case EntryPoint::PauseTransformFeedback:
             return "glPauseTransformFeedback";
         case EntryPoint::PixelMapfv:
@@ -1762,8 +1730,6 @@
             return "glProgramBinaryOES";
         case EntryPoint::ProgramParameteri:
             return "glProgramParameteri";
-        case EntryPoint::ProgramPathFragmentInputGenCHROMIUM:
-            return "glProgramPathFragmentInputGenCHROMIUM";
         case EntryPoint::ProgramUniform1d:
             return "glProgramUniform1d";
         case EntryPoint::ProgramUniform1dv:
@@ -2090,10 +2056,6 @@
             return "glSignalSemaphoreEXT";
         case EntryPoint::SpecializeShader:
             return "glSpecializeShader";
-        case EntryPoint::StencilFillPathCHROMIUM:
-            return "glStencilFillPathCHROMIUM";
-        case EntryPoint::StencilFillPathInstancedCHROMIUM:
-            return "glStencilFillPathInstancedCHROMIUM";
         case EntryPoint::StencilFunc:
             return "glStencilFunc";
         case EntryPoint::StencilFuncSeparate:
@@ -2106,18 +2068,6 @@
             return "glStencilOp";
         case EntryPoint::StencilOpSeparate:
             return "glStencilOpSeparate";
-        case EntryPoint::StencilStrokePathCHROMIUM:
-            return "glStencilStrokePathCHROMIUM";
-        case EntryPoint::StencilStrokePathInstancedCHROMIUM:
-            return "glStencilStrokePathInstancedCHROMIUM";
-        case EntryPoint::StencilThenCoverFillPathCHROMIUM:
-            return "glStencilThenCoverFillPathCHROMIUM";
-        case EntryPoint::StencilThenCoverFillPathInstancedCHROMIUM:
-            return "glStencilThenCoverFillPathInstancedCHROMIUM";
-        case EntryPoint::StencilThenCoverStrokePathCHROMIUM:
-            return "glStencilThenCoverStrokePathCHROMIUM";
-        case EntryPoint::StencilThenCoverStrokePathInstancedCHROMIUM:
-            return "glStencilThenCoverStrokePathInstancedCHROMIUM";
         case EntryPoint::TestFenceNV:
             return "glTestFenceNV";
         case EntryPoint::TexBuffer:
diff --git a/src/libANGLE/entry_points_enum_autogen.h b/src/libANGLE/entry_points_enum_autogen.h
index 2335f1f..01dc3f2 100644
--- a/src/libANGLE/entry_points_enum_autogen.h
+++ b/src/libANGLE/entry_points_enum_autogen.h
@@ -39,7 +39,6 @@
     BindFragDataLocationEXT,
     BindFragDataLocationIndexed,
     BindFragDataLocationIndexedEXT,
-    BindFragmentInputLocationCHROMIUM,
     BindFramebuffer,
     BindFramebufferOES,
     BindImageTexture,
@@ -196,10 +195,6 @@
     CopyTextureSubImage1D,
     CopyTextureSubImage2D,
     CopyTextureSubImage3D,
-    CoverFillPathCHROMIUM,
-    CoverFillPathInstancedCHROMIUM,
-    CoverStrokePathCHROMIUM,
-    CoverStrokePathInstancedCHROMIUM,
     CoverageModulationCHROMIUM,
     CreateBuffers,
     CreateFramebuffers,
@@ -228,7 +223,6 @@
     DeleteFramebuffersOES,
     DeleteLists,
     DeleteMemoryObjectsEXT,
-    DeletePathsCHROMIUM,
     DeleteProgram,
     DeleteProgramPipelines,
     DeleteQueries,
@@ -375,7 +369,6 @@
     GenFramebuffers,
     GenFramebuffersOES,
     GenLists,
-    GenPathsCHROMIUM,
     GenProgramPipelines,
     GenQueries,
     GenQueriesEXT,
@@ -477,8 +470,6 @@
     GetObjectLabelKHR,
     GetObjectPtrLabel,
     GetObjectPtrLabelKHR,
-    GetPathParameterfvCHROMIUM,
-    GetPathParameterivCHROMIUM,
     GetPixelMapfv,
     GetPixelMapuiv,
     GetPixelMapusv,
@@ -679,7 +670,6 @@
     IsFramebufferOES,
     IsList,
     IsMemoryObjectEXT,
-    IsPathCHROMIUM,
     IsProgram,
     IsProgramPipeline,
     IsQuery,
@@ -742,8 +732,6 @@
     Materialx,
     Materialxv,
     MatrixIndexPointerOES,
-    MatrixLoadIdentityCHROMIUM,
-    MatrixLoadfCHROMIUM,
     MatrixMode,
     MaxShaderCompilerThreadsKHR,
     MemoryBarrier,
@@ -847,10 +835,6 @@
     PassThrough,
     PatchParameterfv,
     PatchParameteri,
-    PathCommandsCHROMIUM,
-    PathParameterfCHROMIUM,
-    PathParameteriCHROMIUM,
-    PathStencilFuncCHROMIUM,
     PauseTransformFeedback,
     PixelMapfv,
     PixelMapuiv,
@@ -887,7 +871,6 @@
     ProgramBinary,
     ProgramBinaryOES,
     ProgramParameteri,
-    ProgramPathFragmentInputGenCHROMIUM,
     ProgramUniform1d,
     ProgramUniform1dv,
     ProgramUniform1f,
@@ -1051,20 +1034,12 @@
     ShaderStorageBlockBinding,
     SignalSemaphoreEXT,
     SpecializeShader,
-    StencilFillPathCHROMIUM,
-    StencilFillPathInstancedCHROMIUM,
     StencilFunc,
     StencilFuncSeparate,
     StencilMask,
     StencilMaskSeparate,
     StencilOp,
     StencilOpSeparate,
-    StencilStrokePathCHROMIUM,
-    StencilStrokePathInstancedCHROMIUM,
-    StencilThenCoverFillPathCHROMIUM,
-    StencilThenCoverFillPathInstancedCHROMIUM,
-    StencilThenCoverStrokePathCHROMIUM,
-    StencilThenCoverStrokePathInstancedCHROMIUM,
     TestFenceNV,
     TexBuffer,
     TexBufferRange,
diff --git a/src/libANGLE/entry_points_utils.h b/src/libANGLE/entry_points_utils.h
index 4d1886e..e8094a8 100644
--- a/src/libANGLE/entry_points_utils.h
+++ b/src/libANGLE/entry_points_utils.h
@@ -99,7 +99,7 @@
 
 inline int CID(const Context *context)
 {
-    return context != nullptr ? context->id() : 0;
+    return context != nullptr ? static_cast<int>(context->id()) : 0;
 }
 }  // namespace gl
 
diff --git a/src/libANGLE/es3_format_type_combinations.json b/src/libANGLE/es3_format_type_combinations.json
index 4068fc7..a528bb9 100644
--- a/src/libANGLE/es3_format_type_combinations.json
+++ b/src/libANGLE/es3_format_type_combinations.json
@@ -105,6 +105,10 @@
         [ "GL_SRGB8_ALPHA8_EXT",   "GL_SRGB_ALPHA_EXT", "GL_UNSIGNED_BYTE" ],
         [ "GL_SRGB8",              "GL_SRGB_EXT",       "GL_UNSIGNED_BYTE" ]
     ],
+    "From GL_EXT_texture_sRGB_R8":
+    [
+        [ "GL_SR8_EXT",            "GL_RED",       "GL_UNSIGNED_BYTE" ]
+    ],
     "From GL_OES_texture_float":
     [
         [ "GL_RGBA",               "GL_RGBA",            "GL_FLOAT" ],
diff --git a/src/libANGLE/format_map_autogen.cpp b/src/libANGLE/format_map_autogen.cpp
index 0248fab..b485143 100644
--- a/src/libANGLE/format_map_autogen.cpp
+++ b/src/libANGLE/format_map_autogen.cpp
@@ -299,6 +299,8 @@
                     return GL_DEPTH_COMPONENT32F;
                 case GL_UNSIGNED_INT:
                     return GL_DEPTH_COMPONENT32_OES;
+                case GL_UNSIGNED_INT_24_8:
+                    return GL_DEPTH24_STENCIL8;
                 case GL_UNSIGNED_SHORT:
                     return GL_DEPTH_COMPONENT16;
                 default:
@@ -564,6 +566,16 @@
             }
             break;
 
+        case GL_STENCIL_INDEX_OES:
+            switch (type)
+            {
+                case GL_UNSIGNED_BYTE:
+                    return GL_STENCIL_INDEX8;
+                default:
+                    break;
+            }
+            break;
+
         case GL_NONE:
             return GL_NONE;
 
@@ -843,14 +855,15 @@
                     }
                     break;
                 }
-                case GL_UNSIGNED_BYTE:
+                case GL_FLOAT:
                 {
                     switch (internalFormat)
                     {
                         case GL_RGB:
-                        case GL_RGB8:
-                        case GL_RGB565:
-                        case GL_SRGB8:
+                        case GL_RGB32F:
+                        case GL_RGB16F:
+                        case GL_R11F_G11F_B10F:
+                        case GL_RGB9_E5:
                             return true;
                         default:
                             break;
@@ -896,15 +909,14 @@
                     }
                     break;
                 }
-                case GL_FLOAT:
+                case GL_UNSIGNED_BYTE:
                 {
                     switch (internalFormat)
                     {
                         case GL_RGB:
-                        case GL_RGB32F:
-                        case GL_RGB16F:
-                        case GL_R11F_G11F_B10F:
-                        case GL_RGB9_E5:
+                        case GL_RGB8:
+                        case GL_RGB565:
+                        case GL_SRGB8:
                             return true;
                         default:
                             break;
@@ -945,20 +957,8 @@
                 {
                     switch (internalFormat)
                     {
-                        case GL_LUMINANCE_ALPHA:
                         case GL_LUMINANCE_ALPHA16F_EXT:
-                            return true;
-                        default:
-                            break;
-                    }
-                    break;
-                }
-                case GL_FLOAT:
-                {
-                    switch (internalFormat)
-                    {
                         case GL_LUMINANCE_ALPHA:
-                        case GL_LUMINANCE_ALPHA32F_EXT:
                             return true;
                         default:
                             break;
@@ -977,12 +977,24 @@
                     }
                     break;
                 }
-                case GL_HALF_FLOAT_OES:
+                case GL_FLOAT:
                 {
                     switch (internalFormat)
                     {
                         case GL_LUMINANCE_ALPHA:
+                        case GL_LUMINANCE_ALPHA32F_EXT:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_HALF_FLOAT_OES:
+                {
+                    switch (internalFormat)
+                    {
                         case GL_LUMINANCE_ALPHA16F_EXT:
+                        case GL_LUMINANCE_ALPHA:
                             return true;
                         default:
                             break;
@@ -1001,20 +1013,8 @@
                 {
                     switch (internalFormat)
                     {
-                        case GL_ALPHA:
                         case GL_ALPHA16F_EXT:
-                            return true;
-                        default:
-                            break;
-                    }
-                    break;
-                }
-                case GL_FLOAT:
-                {
-                    switch (internalFormat)
-                    {
                         case GL_ALPHA:
-                        case GL_ALPHA32F_EXT:
                             return true;
                         default:
                             break;
@@ -1033,12 +1033,24 @@
                     }
                     break;
                 }
-                case GL_HALF_FLOAT_OES:
+                case GL_FLOAT:
                 {
                     switch (internalFormat)
                     {
                         case GL_ALPHA:
+                        case GL_ALPHA32F_EXT:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_HALF_FLOAT_OES:
+                {
+                    switch (internalFormat)
+                    {
                         case GL_ALPHA16F_EXT:
+                        case GL_ALPHA:
                             return true;
                         default:
                             break;
@@ -1100,15 +1112,13 @@
                     }
                     break;
                 }
-                case GL_UNSIGNED_BYTE:
+                case GL_FLOAT:
                 {
                     switch (internalFormat)
                     {
                         case GL_RGBA:
-                        case GL_RGBA8:
-                        case GL_RGB5_A1:
-                        case GL_RGBA4:
-                        case GL_SRGB8_ALPHA8:
+                        case GL_RGBA32F:
+                        case GL_RGBA16F:
                             return true;
                         default:
                             break;
@@ -1138,13 +1148,15 @@
                     }
                     break;
                 }
-                case GL_FLOAT:
+                case GL_UNSIGNED_BYTE:
                 {
                     switch (internalFormat)
                     {
                         case GL_RGBA:
-                        case GL_RGBA32F:
-                        case GL_RGBA16F:
+                        case GL_RGBA8:
+                        case GL_RGB5_A1:
+                        case GL_RGBA4:
+                        case GL_SRGB8_ALPHA8:
                             return true;
                         default:
                             break;
@@ -1186,20 +1198,8 @@
                 {
                     switch (internalFormat)
                     {
-                        case GL_LUMINANCE:
                         case GL_LUMINANCE16F_EXT:
-                            return true;
-                        default:
-                            break;
-                    }
-                    break;
-                }
-                case GL_FLOAT:
-                {
-                    switch (internalFormat)
-                    {
                         case GL_LUMINANCE:
-                        case GL_LUMINANCE32F_EXT:
                             return true;
                         default:
                             break;
@@ -1218,12 +1218,24 @@
                     }
                     break;
                 }
-                case GL_HALF_FLOAT_OES:
+                case GL_FLOAT:
                 {
                     switch (internalFormat)
                     {
                         case GL_LUMINANCE:
+                        case GL_LUMINANCE32F_EXT:
+                            return true;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+                case GL_HALF_FLOAT_OES:
+                {
+                    switch (internalFormat)
+                    {
                         case GL_LUMINANCE16F_EXT:
+                        case GL_LUMINANCE:
                             return true;
                         default:
                             break;
@@ -1450,6 +1462,7 @@
                     switch (internalFormat)
                     {
                         case GL_RED:
+                        case GL_SR8_EXT:
                         case GL_R8:
                             return true;
                         default:
diff --git a/src/libANGLE/format_map_data.json b/src/libANGLE/format_map_data.json
index d30187b..a3c8984 100644
--- a/src/libANGLE/format_map_data.json
+++ b/src/libANGLE/format_map_data.json
@@ -155,11 +155,15 @@
     "GL_DEPTH_COMPONENT": {
         "GL_UNSIGNED_SHORT": "GL_DEPTH_COMPONENT16",
         "GL_UNSIGNED_INT": "GL_DEPTH_COMPONENT32_OES",
+        "GL_UNSIGNED_INT_24_8": "GL_DEPTH24_STENCIL8",
         "GL_FLOAT": "GL_DEPTH_COMPONENT32F"
     },
     "GL_STENCIL": {
         "GL_UNSIGNED_BYTE": "GL_STENCIL_INDEX8"
     },
+    "GL_STENCIL_INDEX_OES": {
+        "GL_UNSIGNED_BYTE": "GL_STENCIL_INDEX8"
+    },
     "GL_DEPTH_STENCIL": {
         "GL_UNSIGNED_INT_24_8": "GL_DEPTH24_STENCIL8",
         "GL_FLOAT_32_UNSIGNED_INT_24_8_REV": "GL_DEPTH32F_STENCIL8"
diff --git a/src/libANGLE/formatutils.cpp b/src/libANGLE/formatutils.cpp
index eb82749..057d954 100644
--- a/src/libANGLE/formatutils.cpp
+++ b/src/libANGLE/formatutils.cpp
@@ -374,11 +374,7 @@
             {
                 return GL_RGBA;
             }
-            else
-            {
-                return GL_BGRA_EXT;
-            }
-            break;
+            return GL_BGRA_EXT;
 
         default:
             return format;
@@ -399,10 +395,7 @@
                 // as an IMPLEMENTATION_READ_TYPE.
                 return GL_HALF_FLOAT_OES;
             }
-            else
-            {
-                return GL_HALF_FLOAT;
-            }
+            return GL_HALF_FLOAT;
 
         default:
             return type;
@@ -789,7 +782,7 @@
     AddRGBAFormat(&map, GL_RGB10_A2,          true, 10, 10, 10,  2, 0, GL_RGBA,         GL_UNSIGNED_INT_2_10_10_10_REV,    GL_UNSIGNED_NORMALIZED, false, RequireES<3, 0>,                                   AlwaysSupported, RequireES<3, 0>,                                   RequireES<3, 0>,                                 RequireES<3, 0>);
     AddRGBAFormat(&map, GL_RGB10_A2UI,        true, 10, 10, 10,  2, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV,    GL_UNSIGNED_INT,        false, RequireES<3, 0>,                                   NeverSupported,  RequireES<3, 0>,                                   RequireES<3, 0>,                                 NeverSupported);
     AddRGBAFormat(&map, GL_SRGB8,             true,  8,  8,  8,  0, 0, GL_RGB,          GL_UNSIGNED_BYTE,                  GL_UNSIGNED_NORMALIZED, true,  RequireES<3, 0>,                                   AlwaysSupported, NeverSupported,                                    NeverSupported,                                  NeverSupported);
-    AddRGBAFormat(&map, GL_SRGB8_ALPHA8,      true,  8,  8,  8,  8, 0, GL_RGBA,         GL_UNSIGNED_BYTE,                  GL_UNSIGNED_NORMALIZED, true,  RequireES<3, 0>,                                   AlwaysSupported, RequireES<3, 0>,                                   RequireESOrExt<3, 0, &Extensions::sRGB>,         RequireESOrExt<3, 0, &Extensions::sRGB>);
+    AddRGBAFormat(&map, GL_SRGB8_ALPHA8,      true,  8,  8,  8,  8, 0, GL_RGBA,         GL_UNSIGNED_BYTE,                  GL_UNSIGNED_NORMALIZED, true,  RequireESOrExt<3, 0, &Extensions::sRGB>,           AlwaysSupported, RequireES<3, 0>,                                   RequireESOrExt<3, 0, &Extensions::sRGB>,         RequireESOrExt<3, 0, &Extensions::sRGB>);
     AddRGBAFormat(&map, GL_R11F_G11F_B10F,    true, 11, 11, 10,  0, 0, GL_RGB,          GL_UNSIGNED_INT_10F_11F_11F_REV,   GL_FLOAT,               false, RequireES<3, 0>,                                   AlwaysSupported, RequireExt<&Extensions::colorBufferFloat>,         RequireExt<&Extensions::colorBufferFloat>,       RequireExt<&Extensions::colorBufferFloat>);
     AddRGBAFormat(&map, GL_RGB9_E5,           true,  9,  9,  9,  0, 5, GL_RGB,          GL_UNSIGNED_INT_5_9_9_9_REV,       GL_FLOAT,               false, RequireES<3, 0>,                                   AlwaysSupported, NeverSupported,                                    NeverSupported,                                  NeverSupported);
     AddRGBAFormat(&map, GL_R8I,               true,  8,  0,  0,  0, 0, GL_RED_INTEGER,  GL_BYTE,                           GL_INT,                 false, RequireES<3, 0>,                                   NeverSupported,  RequireES<3, 0>,                                   RequireES<3, 0>,                                 NeverSupported);
@@ -852,7 +845,7 @@
     AddDepthStencilFormat(&map, GL_DEPTH_COMPONENT32F,    true, 32, 0,  0, GL_DEPTH_COMPONENT, GL_FLOAT,                          GL_FLOAT,               RequireES<3, 0>,                                                               RequireESOrExt<3, 0, &Extensions::depthTextureANGLE>,                                    RequireES<3, 0>,                                                                               RequireES<3, 0>,                                                                                             RequireES<3, 0>);
     AddDepthStencilFormat(&map, GL_DEPTH_COMPONENT32_OES, true, 32, 0,  0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT,                   GL_UNSIGNED_NORMALIZED, RequireExtOrExt<&Extensions::depthTextureANGLE, &Extensions::depthTextureOES>, AlwaysSupported,                                                                         RequireExtOrExt<&Extensions::depthTextureANGLE, &Extensions::depthTextureOES>,                 RequireExtOrExtOrExt<&Extensions::depthTextureANGLE, &Extensions::depthTextureOES, &Extensions::depth32OES>, RequireExtOrExtOrExt<&Extensions::depthTextureANGLE, &Extensions::depthTextureOES, &Extensions::depth32OES>);
     AddDepthStencilFormat(&map, GL_DEPTH24_STENCIL8,      true, 24, 8,  0, GL_DEPTH_STENCIL,   GL_UNSIGNED_INT_24_8,              GL_UNSIGNED_NORMALIZED, RequireESOrExt<3, 0, &Extensions::depthTextureANGLE>,                          AlwaysSupported,                                                                         RequireESOrExtOrExt<3, 0, &Extensions::depthTextureANGLE, &Extensions::packedDepthStencilOES>, RequireESOrExtOrExt<3, 0, &Extensions::depthTextureANGLE, &Extensions::packedDepthStencilOES>,               RequireESOrExtOrExt<3, 0, &Extensions::depthTextureANGLE, &Extensions::packedDepthStencilOES>);
-    AddDepthStencilFormat(&map, GL_DEPTH32F_STENCIL8,     true, 32, 8, 24, GL_DEPTH_STENCIL,   GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_FLOAT,               RequireES<3, 0>,                                                               AlwaysSupported,                                                                         RequireES<3, 0>,                                                                               RequireES<3, 0>,                                                                                             RequireES<3, 0>);
+    AddDepthStencilFormat(&map, GL_DEPTH32F_STENCIL8,     true, 32, 8, 24, GL_DEPTH_STENCIL,   GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_FLOAT,               RequireESOrExt<3, 0, &Extensions::depthBufferFloat2NV>,                        AlwaysSupported,                                                                         RequireESOrExt<3, 0, &Extensions::depthBufferFloat2NV>,                                        RequireESOrExt<3, 0, &Extensions::depthBufferFloat2NV>,                                                      RequireESOrExt<3, 0, &Extensions::depthBufferFloat2NV>);
     // STENCIL_INDEX8 is special-cased, see around the bottom of the list.
 
     // Luminance alpha formats
@@ -1009,6 +1002,10 @@
     AddRGBAFormat(&map, GL_RGBA16_EXT,       true, 16, 16, 16, 16, 0, GL_RGBA, GL_UNSIGNED_SHORT, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureNorm16>, AlwaysSupported, RequireExt<&Extensions::textureNorm16>, RequireExt<&Extensions::textureNorm16>, RequireExt<&Extensions::textureNorm16>);
     AddRGBAFormat(&map, GL_RGBA16_SNORM_EXT, true, 16, 16, 16, 16, 0, GL_RGBA, GL_SHORT,          GL_SIGNED_NORMALIZED,   false, RequireExt<&Extensions::textureNorm16>, AlwaysSupported, NeverSupported,                         NeverSupported,                         NeverSupported);
 
+    // From EXT_texture_sRGB_R8
+    //                 | Internal format    |sized| R | G | B | A |S | Format | Type             | Component type        | SRGB | Texture supported                     | Filterable     | Texture attachment                    | Renderbuffer                          | Blend
+    AddRGBAFormat(&map, GL_SR8_EXT,          true,  8,  0,  0,  0, 0, GL_RED,  GL_UNSIGNED_BYTE,  GL_UNSIGNED_NORMALIZED, true,  RequireExt<&Extensions::sRGBR8EXT>,     AlwaysSupported, NeverSupported,                         NeverSupported,                         NeverSupported);
+
     // Unsized formats
     //                 | Internal format  |sized | R | G | B | A |S | Format           | Type                          | Component type        | SRGB | Texture supported                               | Filterable     | Texture attachment                            | Renderbuffer  | Blend
     AddRGBAFormat(&map, GL_RED,            false,  8,  0,  0,  0, 0, GL_RED,            GL_UNSIGNED_BYTE,               GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureRG>,               AlwaysSupported, RequireExt<&Extensions::textureRG>,             NeverSupported, NeverSupported);
@@ -1097,9 +1094,11 @@
     AddDepthStencilFormat(&map, GL_DEPTH_COMPONENT, false, 16, 0,  0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT,                 GL_UNSIGNED_NORMALIZED, RequireES<1, 0>,                                          AlwaysSupported, RequireExtOrExt<&Extensions::depthTextureANGLE, &Extensions::depthTextureOES>,        RequireExtOrExt<&Extensions::depthTextureANGLE, &Extensions::depthTextureOES>,        RequireExtOrExt<&Extensions::depthTextureANGLE, &Extensions::depthTextureOES>);
     AddDepthStencilFormat(&map, GL_DEPTH_COMPONENT, false, 24, 0,  0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT,                   GL_UNSIGNED_NORMALIZED, RequireES<1, 0>,                                          AlwaysSupported, RequireExtOrExt<&Extensions::depthTextureANGLE, &Extensions::depthTextureOES>,        RequireExtOrExt<&Extensions::depthTextureANGLE, &Extensions::depthTextureOES>,        RequireExtOrExt<&Extensions::depthTextureANGLE, &Extensions::depthTextureOES>);
     AddDepthStencilFormat(&map, GL_DEPTH_COMPONENT, false, 32, 0,  0, GL_DEPTH_COMPONENT, GL_FLOAT,                          GL_FLOAT,               RequireES<1, 0>,                                          AlwaysSupported, RequireES<1, 0>,                                                                      RequireES<1, 0>,                                                                      RequireES<1, 0>);
+    AddDepthStencilFormat(&map, GL_DEPTH_COMPONENT, false, 24, 8,  0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT_24_8,              GL_UNSIGNED_NORMALIZED, RequireESOrExt<3, 0, &Extensions::packedDepthStencilOES>, AlwaysSupported, RequireExtAndExt<&Extensions::packedDepthStencilOES, &Extensions::depthTextureANGLE>, RequireExtAndExt<&Extensions::packedDepthStencilOES, &Extensions::depthTextureANGLE>, RequireExtAndExt<&Extensions::packedDepthStencilOES, &Extensions::depthTextureANGLE>);
     AddDepthStencilFormat(&map, GL_DEPTH_STENCIL,   false, 24, 8,  0, GL_DEPTH_STENCIL,   GL_UNSIGNED_INT_24_8,              GL_UNSIGNED_NORMALIZED, RequireESOrExt<3, 0, &Extensions::packedDepthStencilOES>, AlwaysSupported, RequireExtAndExt<&Extensions::packedDepthStencilOES, &Extensions::depthTextureANGLE>, RequireExtAndExt<&Extensions::packedDepthStencilOES, &Extensions::depthTextureANGLE>, RequireExtAndExt<&Extensions::packedDepthStencilOES, &Extensions::depthTextureANGLE>);
     AddDepthStencilFormat(&map, GL_DEPTH_STENCIL,   false, 32, 8, 24, GL_DEPTH_STENCIL,   GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_FLOAT,               RequireESOrExt<3, 0, &Extensions::packedDepthStencilOES>, AlwaysSupported, RequireExt<&Extensions::packedDepthStencilOES>,                                       RequireExt<&Extensions::packedDepthStencilOES>,                                       RequireExt<&Extensions::packedDepthStencilOES>);
     AddDepthStencilFormat(&map, GL_STENCIL,         false,  0, 8,  0, GL_STENCIL,         GL_UNSIGNED_BYTE,                  GL_UNSIGNED_NORMALIZED, RequireES<1, 0>,                                          NeverSupported , RequireES<1, 0>,                                                                      RequireES<1, 0>,                                                                      RequireES<1, 0>);
+    AddDepthStencilFormat(&map, GL_STENCIL_INDEX,   false,  0, 8,  0, GL_STENCIL_INDEX,   GL_UNSIGNED_BYTE,                  GL_UNSIGNED_NORMALIZED, RequireES<3, 1>,                                          NeverSupported , RequireES<3, 1>,                                                                      RequireES<3, 1>,                                                                      RequireES<3, 1>);
     // clang-format on
 
     return map;
diff --git a/src/libANGLE/frame_capture_utils_autogen.cpp b/src/libANGLE/frame_capture_utils_autogen.cpp
index b89fc79..96250a0 100644
--- a/src/libANGLE/frame_capture_utils_autogen.cpp
+++ b/src/libANGLE/frame_capture_utils_autogen.cpp
@@ -300,9 +300,6 @@
             WriteParamValueReplay<ParamType::TMemoryObjectIDPointer>(
                 os, call, param.value.MemoryObjectIDPointerVal);
             break;
-        case ParamType::TPathID:
-            WriteParamValueReplay<ParamType::TPathID>(os, call, param.value.PathIDVal);
-            break;
         case ParamType::TPointParameter:
             WriteParamValueReplay<ParamType::TPointParameter>(os, call,
                                                               param.value.PointParameterVal);
@@ -630,8 +627,6 @@
             return "const GLuint *";
         case ParamType::TMemoryObjectIDPointer:
             return "GLuint *";
-        case ParamType::TPathID:
-            return "GLuint";
         case ParamType::TPointParameter:
             return "GLenum";
         case ParamType::TPrimitiveMode:
@@ -752,8 +747,6 @@
             return ResourceIDType::MemoryObject;
         case ParamType::TMemoryObjectIDPointer:
             return ResourceIDType::MemoryObject;
-        case ParamType::TPathID:
-            return ResourceIDType::Path;
         case ParamType::TProgramPipelineID:
             return ResourceIDType::ProgramPipeline;
         case ParamType::TProgramPipelineIDConstPointer:
@@ -825,8 +818,6 @@
             return "Framebuffer";
         case ResourceIDType::MemoryObject:
             return "MemoryObject";
-        case ResourceIDType::Path:
-            return "Path";
         case ResourceIDType::ProgramPipeline:
             return "ProgramPipeline";
         case ResourceIDType::Query:
diff --git a/src/libANGLE/frame_capture_utils_autogen.h b/src/libANGLE/frame_capture_utils_autogen.h
index 95630e3..7410e0b 100644
--- a/src/libANGLE/frame_capture_utils_autogen.h
+++ b/src/libANGLE/frame_capture_utils_autogen.h
@@ -94,7 +94,6 @@
     TMemoryObjectID,
     TMemoryObjectIDConstPointer,
     TMemoryObjectIDPointer,
-    TPathID,
     TPointParameter,
     TPrimitiveMode,
     TProgramPipelineID,
@@ -140,7 +139,7 @@
     TvoidPointerPointer,
 };
 
-constexpr uint32_t kParamTypeCount = 121;
+constexpr uint32_t kParamTypeCount = 120;
 
 union ParamValue
 {
@@ -221,7 +220,6 @@
     gl::MemoryObjectID MemoryObjectIDVal;
     const gl::MemoryObjectID *MemoryObjectIDConstPointerVal;
     gl::MemoryObjectID *MemoryObjectIDPointerVal;
-    gl::PathID PathIDVal;
     gl::PointParameter PointParameterVal;
     gl::PrimitiveMode PrimitiveModeVal;
     gl::ProgramPipelineID ProgramPipelineIDVal;
@@ -773,12 +771,6 @@
 }
 
 template <>
-inline gl::PathID GetParamVal<ParamType::TPathID, gl::PathID>(const ParamValue &value)
-{
-    return value.PathIDVal;
-}
-
-template <>
 inline gl::PointParameter GetParamVal<ParamType::TPointParameter, gl::PointParameter>(
     const ParamValue &value)
 {
@@ -1239,8 +1231,6 @@
             return GetParamVal<ParamType::TMemoryObjectIDConstPointer, T>(value);
         case ParamType::TMemoryObjectIDPointer:
             return GetParamVal<ParamType::TMemoryObjectIDPointer, T>(value);
-        case ParamType::TPathID:
-            return GetParamVal<ParamType::TPathID, T>(value);
         case ParamType::TPointParameter:
             return GetParamVal<ParamType::TPointParameter, T>(value);
         case ParamType::TPrimitiveMode:
@@ -1822,12 +1812,6 @@
 }
 
 template <>
-inline void SetParamVal<ParamType::TPathID>(gl::PathID valueIn, ParamValue *valueOut)
-{
-    valueOut->PathIDVal = valueIn;
-}
-
-template <>
 inline void SetParamVal<ParamType::TPointParameter>(gl::PointParameter valueIn,
                                                     ParamValue *valueOut)
 {
@@ -2356,9 +2340,6 @@
         case ParamType::TMemoryObjectIDPointer:
             SetParamVal<ParamType::TMemoryObjectIDPointer>(valueIn, valueOut);
             break;
-        case ParamType::TPathID:
-            SetParamVal<ParamType::TPathID>(valueIn, valueOut);
-            break;
         case ParamType::TPointParameter:
             SetParamVal<ParamType::TPointParameter>(valueIn, valueOut);
             break;
@@ -2503,7 +2484,6 @@
     FenceNV,
     Framebuffer,
     MemoryObject,
-    Path,
     ProgramPipeline,
     Query,
     Renderbuffer,
diff --git a/src/libANGLE/gl_enum_utils_autogen.cpp b/src/libANGLE/gl_enum_utils_autogen.cpp
index f74f53c..fed5ae4 100644
--- a/src/libANGLE/gl_enum_utils_autogen.cpp
+++ b/src/libANGLE/gl_enum_utils_autogen.cpp
@@ -1402,6 +1402,8 @@
                     return "GL_SIGNED_NORMALIZED";
                 case 0x8FBB:
                     return "GL_GPU_DISJOINT_EXT";
+                case 0x8FBD:
+                    return "GL_SR8_EXT";
                 case 0x900A:
                     return "GL_TEXTURE_BINDING_CUBE_MAP_ARRAY";
                 case 0x900C:
@@ -4036,6 +4038,11 @@
 {
     std::stringstream st;
 
+    if (value == 0)
+    {
+        return "0";
+    }
+
     const angle::BitSet<32> bitSet(value);
     bool first = true;
     for (const auto index : bitSet)
diff --git a/src/libANGLE/queryutils.cpp b/src/libANGLE/queryutils.cpp
index e9dc66e..24d54f9 100644
--- a/src/libANGLE/queryutils.cpp
+++ b/src/libANGLE/queryutils.cpp
@@ -18,6 +18,7 @@
 #include "libANGLE/Fence.h"
 #include "libANGLE/Framebuffer.h"
 #include "libANGLE/GLES1State.h"
+#include "libANGLE/MemoryObject.h"
 #include "libANGLE/Program.h"
 #include "libANGLE/Renderbuffer.h"
 #include "libANGLE/Sampler.h"
@@ -1228,7 +1229,7 @@
             *params = program->isValidated();
             return;
         case GL_INFO_LOG_LENGTH:
-            *params = program->getInfoLogLength();
+            *params = program->getExecutable().getInfoLogLength();
             return;
         case GL_ATTACHED_SHADERS:
             *params = program->getAttachedShadersCount();
@@ -1269,7 +1270,14 @@
             *params = program->getBinaryRetrievableHint();
             break;
         case GL_PROGRAM_SEPARABLE:
-            *params = program->isSeparable();
+            // From es31cSeparateShaderObjsTests.cpp:
+            // ProgramParameteri PROGRAM_SEPARABLE
+            // NOTE: The query for PROGRAM_SEPARABLE must query latched
+            //       state. In other words, the state of the binary after
+            //       it was linked. So in the tests below, the queries
+            //       should return the default state GL_FALSE since the
+            //       program has no linked binary.
+            *params = program->isSeparable() && program->isLinked();
             break;
         case GL_COMPUTE_WORK_GROUP_SIZE:
         {
@@ -2075,6 +2083,37 @@
     }
 }
 
+angle::Result SetMemoryObjectParameteriv(const Context *context,
+                                         MemoryObject *memoryObject,
+                                         GLenum pname,
+                                         const GLint *params)
+{
+    switch (pname)
+    {
+        case GL_DEDICATED_MEMORY_OBJECT_EXT:
+            ANGLE_TRY(memoryObject->setDedicatedMemory(context, ConvertToBool(params[0])));
+            break;
+
+        default:
+            UNREACHABLE();
+    }
+
+    return angle::Result::Continue;
+}
+
+void QueryMemoryObjectParameteriv(const MemoryObject *memoryObject, GLenum pname, GLint *params)
+{
+    switch (pname)
+    {
+        case GL_DEDICATED_MEMORY_OBJECT_EXT:
+            *params = memoryObject->isDedicatedMemory();
+            break;
+
+        default:
+            UNREACHABLE();
+    }
+}
+
 ClientVertexArrayType ParamToVertexArrayType(GLenum param)
 {
     switch (param)
@@ -3167,18 +3206,6 @@
         }
     }
 
-    if (extensions.pathRendering)
-    {
-        switch (pname)
-        {
-            case GL_PATH_MODELVIEW_MATRIX_CHROMIUM:
-            case GL_PATH_PROJECTION_MATRIX_CHROMIUM:
-                *type      = GL_FLOAT;
-                *numParams = 16;
-                return true;
-        }
-    }
-
     if (extensions.bindGeneratesResource)
     {
         switch (pname)
@@ -3559,6 +3586,7 @@
         return false;
     }
 
+    // Check for ES3.1+ parameter names
     switch (pname)
     {
         case GL_ATOMIC_COUNTER_BUFFER_BINDING:
@@ -3608,6 +3636,7 @@
         case GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT:
         case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
         case GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY:
+        case GL_PROGRAM_PIPELINE_BINDING:
             *type      = GL_INT;
             *numParams = 1;
             return true;
@@ -3648,6 +3677,113 @@
 
     return false;
 }
+
+void QueryProgramPipelineiv(const Context *context,
+                            ProgramPipeline *programPipeline,
+                            GLenum pname,
+                            GLint *params)
+{
+    if (!params)
+    {
+        // Can't write the result anywhere, so just return immediately.
+        return;
+    }
+
+    switch (pname)
+    {
+        case GL_ACTIVE_PROGRAM:
+        {
+            // the name of the active program object of the program pipeline object is returned in
+            // params
+            *params = 0;
+            if (programPipeline)
+            {
+                const Program *program = programPipeline->getActiveShaderProgram();
+                if (program)
+                {
+                    *params = program->id().value;
+                }
+            }
+            break;
+        }
+
+        case GL_VERTEX_SHADER:
+        {
+            // the name of the current program object for the vertex shader type of the program
+            // pipeline object is returned in params
+            *params = 0;
+            if (programPipeline)
+            {
+                const Program *program = programPipeline->getShaderProgram(ShaderType::Vertex);
+                if (program)
+                {
+                    *params = program->id().value;
+                }
+            }
+            break;
+        }
+
+        case GL_FRAGMENT_SHADER:
+        {
+            // the name of the current program object for the fragment shader type of the program
+            // pipeline object is returned in params
+            *params = 0;
+            if (programPipeline)
+            {
+                const Program *program = programPipeline->getShaderProgram(ShaderType::Fragment);
+                if (program)
+                {
+                    *params = program->id().value;
+                }
+            }
+            break;
+        }
+
+        case GL_COMPUTE_SHADER:
+        {
+            // the name of the current program object for the compute shader type of the program
+            // pipeline object is returned in params
+            *params = 0;
+            if (programPipeline)
+            {
+                const Program *program = programPipeline->getShaderProgram(ShaderType::Compute);
+                if (program)
+                {
+                    *params = program->id().value;
+                }
+            }
+            break;
+        }
+
+        case GL_INFO_LOG_LENGTH:
+        {
+            // the length of the info log, including the null terminator, is returned in params. If
+            // there is no info log, zero is returned.
+            *params = 0;
+            if (programPipeline)
+            {
+                *params = programPipeline->getExecutable().getInfoLogLength();
+            }
+            break;
+        }
+
+        case GL_VALIDATE_STATUS:
+        {
+            // the validation status of pipeline, as determined by glValidateProgramPipeline, is
+            // returned in params
+            *params = 0;
+            if (programPipeline)
+            {
+                *params = programPipeline->isValid();
+            }
+            break;
+        }
+
+        default:
+            break;
+    }
+}
+
 }  // namespace gl
 
 namespace egl
diff --git a/src/libANGLE/queryutils.h b/src/libANGLE/queryutils.h
index 6233164..422cadd 100644
--- a/src/libANGLE/queryutils.h
+++ b/src/libANGLE/queryutils.h
@@ -183,6 +183,13 @@
                              GLenum programInterface,
                              GLenum pname,
                              GLint *params);
+
+angle::Result SetMemoryObjectParameteriv(const Context *context,
+                                         MemoryObject *memoryObject,
+                                         GLenum pname,
+                                         const GLint *params);
+void QueryMemoryObjectParameteriv(const MemoryObject *memoryObject, GLenum pname, GLint *params);
+
 // GLES1 emulation
 
 ClientVertexArrayType ParamToVertexArrayType(GLenum param);
@@ -249,6 +256,11 @@
                            GLenum pname,
                            GLenum *type,
                            unsigned int *numParams);
+
+void QueryProgramPipelineiv(const Context *context,
+                            ProgramPipeline *programPipeline,
+                            GLenum pname,
+                            GLint *params);
 }  // namespace gl
 
 namespace egl
diff --git a/src/libANGLE/renderer/ContextImpl.cpp b/src/libANGLE/renderer/ContextImpl.cpp
index 32004a1..a2fce07 100644
--- a/src/libANGLE/renderer/ContextImpl.cpp
+++ b/src/libANGLE/renderer/ContextImpl.cpp
@@ -19,96 +19,6 @@
 
 ContextImpl::~ContextImpl() {}
 
-void ContextImpl::stencilFillPath(const gl::Path *path, GLenum fillMode, GLuint mask)
-{
-    UNREACHABLE();
-}
-
-void ContextImpl::stencilStrokePath(const gl::Path *path, GLint reference, GLuint mask)
-{
-    UNREACHABLE();
-}
-
-void ContextImpl::coverFillPath(const gl::Path *path, GLenum coverMode)
-{
-    UNREACHABLE();
-}
-
-void ContextImpl::coverStrokePath(const gl::Path *path, GLenum coverMode)
-{
-    UNREACHABLE();
-}
-
-void ContextImpl::stencilThenCoverFillPath(const gl::Path *path,
-                                           GLenum fillMode,
-                                           GLuint mask,
-                                           GLenum coverMode)
-{
-    UNREACHABLE();
-}
-
-void ContextImpl::stencilThenCoverStrokePath(const gl::Path *path,
-                                             GLint reference,
-                                             GLuint mask,
-                                             GLenum coverMode)
-{
-    UNREACHABLE();
-}
-
-void ContextImpl::coverFillPathInstanced(const std::vector<gl::Path *> &paths,
-                                         GLenum coverMode,
-                                         GLenum transformType,
-                                         const GLfloat *transformValues)
-{
-    UNREACHABLE();
-}
-
-void ContextImpl::coverStrokePathInstanced(const std::vector<gl::Path *> &paths,
-                                           GLenum coverMode,
-                                           GLenum transformType,
-                                           const GLfloat *transformValues)
-{
-    UNREACHABLE();
-}
-
-void ContextImpl::stencilFillPathInstanced(const std::vector<gl::Path *> &paths,
-                                           GLenum fillMode,
-                                           GLuint mask,
-                                           GLenum transformType,
-                                           const GLfloat *transformValues)
-{
-    UNREACHABLE();
-}
-
-void ContextImpl::stencilStrokePathInstanced(const std::vector<gl::Path *> &paths,
-                                             GLint reference,
-                                             GLuint mask,
-                                             GLenum transformType,
-                                             const GLfloat *transformValues)
-{
-    UNREACHABLE();
-}
-
-void ContextImpl::stencilThenCoverFillPathInstanced(const std::vector<gl::Path *> &paths,
-                                                    GLenum coverMode,
-                                                    GLenum fillMode,
-                                                    GLuint mask,
-                                                    GLenum transformType,
-                                                    const GLfloat *transformValues)
-{
-    UNREACHABLE();
-}
-
-void ContextImpl::stencilThenCoverStrokePathInstanced(const std::vector<gl::Path *> &paths,
-                                                      GLenum coverMode,
-                                                      GLint reference,
-                                                      GLuint mask,
-                                                      GLenum transformType,
-                                                      const GLfloat *transformValues)
-{
-    UNREACHABLE();
-}
-
 void ContextImpl::invalidateTexture(gl::TextureType target)
 {
     UNREACHABLE();
diff --git a/src/libANGLE/renderer/ContextImpl.h b/src/libANGLE/renderer/ContextImpl.h
index ba8f797..93df2b8 100644
--- a/src/libANGLE/renderer/ContextImpl.h
+++ b/src/libANGLE/renderer/ContextImpl.h
@@ -115,52 +115,6 @@
                                                gl::DrawElementsType type,
                                                const void *indirect) = 0;
 
-    // CHROMIUM_path_rendering path drawing methods.
-    virtual void stencilFillPath(const gl::Path *path, GLenum fillMode, GLuint mask);
-    virtual void stencilStrokePath(const gl::Path *path, GLint reference, GLuint mask);
-    virtual void coverFillPath(const gl::Path *path, GLenum coverMode);
-    virtual void coverStrokePath(const gl::Path *path, GLenum coverMode);
-    virtual void stencilThenCoverFillPath(const gl::Path *path,
-                                          GLenum fillMode,
-                                          GLuint mask,
-                                          GLenum coverMode);
-
-    virtual void stencilThenCoverStrokePath(const gl::Path *path,
-                                            GLint reference,
-                                            GLuint mask,
-                                            GLenum coverMode);
-
-    virtual void coverFillPathInstanced(const std::vector<gl::Path *> &paths,
-                                        GLenum coverMode,
-                                        GLenum transformType,
-                                        const GLfloat *transformValues);
-    virtual void coverStrokePathInstanced(const std::vector<gl::Path *> &paths,
-                                          GLenum coverMode,
-                                          GLenum transformType,
-                                          const GLfloat *transformValues);
-    virtual void stencilFillPathInstanced(const std::vector<gl::Path *> &paths,
-                                          GLenum fillMode,
-                                          GLuint mask,
-                                          GLenum transformType,
-                                          const GLfloat *transformValues);
-    virtual void stencilStrokePathInstanced(const std::vector<gl::Path *> &paths,
-                                            GLint reference,
-                                            GLuint mask,
-                                            GLenum transformType,
-                                            const GLfloat *transformValues);
-    virtual void stencilThenCoverFillPathInstanced(const std::vector<gl::Path *> &paths,
-                                                   GLenum coverMode,
-                                                   GLenum fillMode,
-                                                   GLuint mask,
-                                                   GLenum transformType,
-                                                   const GLfloat *transformValues);
-    virtual void stencilThenCoverStrokePathInstanced(const std::vector<gl::Path *> &paths,
-                                                     GLenum coverMode,
-                                                     GLint reference,
-                                                     GLuint mask,
-                                                     GLenum transformType,
-                                                     const GLfloat *transformValues);
-
     // Device loss
     virtual gl::GraphicsResetStatus getResetStatus() = 0;
 
diff --git a/src/libANGLE/renderer/FormatID_autogen.h b/src/libANGLE/renderer/FormatID_autogen.h
index be5fae2..fc693a3 100644
--- a/src/libANGLE/renderer/FormatID_autogen.h
+++ b/src/libANGLE/renderer/FormatID_autogen.h
@@ -230,6 +230,7 @@
     R8_SSCALED,
     R8_UINT,
     R8_UNORM,
+    R8_UNORM_SRGB,
     R8_USCALED,
     R9G9B9E5_SHAREDEXP,
     S8_UINT,
@@ -241,7 +242,7 @@
     X2R10G10B10_USCALED_VERTEX
 };
 
-constexpr uint32_t kNumANGLEFormats = 222;
+constexpr uint32_t kNumANGLEFormats = 223;
 
 }  // namespace angle
 
diff --git a/src/libANGLE/renderer/Format_table_autogen.cpp b/src/libANGLE/renderer/Format_table_autogen.cpp
index eae0f01..1ed9965 100644
--- a/src/libANGLE/renderer/Format_table_autogen.cpp
+++ b/src/libANGLE/renderer/Format_table_autogen.cpp
@@ -237,6 +237,7 @@
     { FormatID::R8_SSCALED, GL_R8_SSCALED_ANGLEX, GL_R8_SSCALED_ANGLEX, GenerateMip<R8S>, NoCopyFunctions, ReadColor<R8S, GLint>, WriteColor<R8S, GLint>, GL_INT, 8, 0, 0, 0, 0, 0, 0, 1, 0, false, false, true, gl::VertexAttribType::Byte },
     { FormatID::R8_UINT, GL_R8UI, GL_R8UI, GenerateMip<R8>, NoCopyFunctions, ReadColor<R8, GLuint>, WriteColor<R8, GLuint>, GL_UNSIGNED_INT, 8, 0, 0, 0, 0, 0, 0, 1, 0, false, false, false, gl::VertexAttribType::UnsignedByte },
     { FormatID::R8_UNORM, GL_R8, GL_R8, GenerateMip<R8>, NoCopyFunctions, ReadColor<R8, GLfloat>, WriteColor<R8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 0, 0, 0, 0, 0, 0, 1, 0, false, false, false, gl::VertexAttribType::UnsignedByte },
+    { FormatID::R8_UNORM_SRGB, GL_SR8_EXT, GL_SR8_EXT, GenerateMip<R8>, NoCopyFunctions, ReadColor<R8, GLfloat>, WriteColor<R8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 0, 0, 0, 0, 0, 0, 1, 0, false, false, false, gl::VertexAttribType::Byte },
     { FormatID::R8_USCALED, GL_R8_USCALED_ANGLEX, GL_R8_USCALED_ANGLEX, GenerateMip<R8>, NoCopyFunctions, ReadColor<R8, GLuint>, WriteColor<R8, GLuint>, GL_UNSIGNED_INT, 8, 0, 0, 0, 0, 0, 0, 1, 0, false, false, true, gl::VertexAttribType::UnsignedByte },
     { FormatID::R9G9B9E5_SHAREDEXP, GL_RGB9_E5, GL_RGB9_E5, GenerateMip<R9G9B9E5>, NoCopyFunctions, ReadColor<R9G9B9E5, GLfloat>, WriteColor<R9G9B9E5, GLfloat>, GL_FLOAT, 9, 9, 9, 0, 0, 0, 0, 4, std::numeric_limits<GLuint>::max(), false, false, false, gl::VertexAttribType::InvalidEnum },
     { FormatID::S8_UINT, GL_STENCIL_INDEX8, GL_STENCIL_INDEX8, nullptr, NoCopyFunctions, ReadDepthStencil<S8>, WriteDepthStencil<S8>, GL_UNSIGNED_INT, 0, 0, 0, 0, 0, 0, 8, 1, std::numeric_limits<GLuint>::max(), false, false, false, gl::VertexAttribType::InvalidEnum },
@@ -682,6 +683,8 @@
             return FormatID::R8G8B8A8_TYPELESS_SRGB;
         case GL_RGBA8_USCALED_ANGLEX:
             return FormatID::R8G8B8A8_USCALED;
+        case GL_SR8_EXT:
+            return FormatID::R8_UNORM_SRGB;
         case GL_SRGB8:
             return FormatID::R8G8B8_UNORM_SRGB;
         case GL_SRGB8_ALPHA8:
diff --git a/src/libANGLE/renderer/FramebufferImpl.h b/src/libANGLE/renderer/FramebufferImpl.h
index b6db048..e132e15 100644
--- a/src/libANGLE/renderer/FramebufferImpl.h
+++ b/src/libANGLE/renderer/FramebufferImpl.h
@@ -63,13 +63,13 @@
                                         GLfloat depth,
                                         GLint stencil)                       = 0;
 
-    virtual GLenum getImplementationColorReadFormat(const gl::Context *context) const = 0;
-    virtual GLenum getImplementationColorReadType(const gl::Context *context) const   = 0;
+    virtual const gl::InternalFormat &getImplementationColorReadFormat(
+        const gl::Context *context) const;
     virtual angle::Result readPixels(const gl::Context *context,
                                      const gl::Rectangle &area,
                                      GLenum format,
                                      GLenum type,
-                                     void *pixels)                                    = 0;
+                                     void *pixels) = 0;
 
     virtual angle::Result blit(const gl::Context *context,
                                const gl::Rectangle &sourceArea,
@@ -80,6 +80,7 @@
     virtual bool checkStatus(const gl::Context *context) const = 0;
 
     virtual angle::Result syncState(const gl::Context *context,
+                                    GLenum binding,
                                     const gl::Framebuffer::DirtyBits &dirtyBits) = 0;
 
     virtual angle::Result getSamplePosition(const gl::Context *context,
@@ -103,6 +104,13 @@
     return false;
 }
 
+// Default implementation returns the format specified in the attachment.
+inline const gl::InternalFormat &FramebufferImpl::getImplementationColorReadFormat(
+    const gl::Context *context) const
+{
+    const gl::FramebufferAttachment *readAttachment = mState.getReadAttachment();
+    return *readAttachment->getFormat().info;
+}
 }  // namespace rx
 
 #endif  // LIBANGLE_RENDERER_FRAMEBUFFERIMPL_H_
diff --git a/src/libANGLE/renderer/FramebufferImpl_mock.h b/src/libANGLE/renderer/FramebufferImpl_mock.h
index 8d841e7..aef2dce 100644
--- a/src/libANGLE/renderer/FramebufferImpl_mock.h
+++ b/src/libANGLE/renderer/FramebufferImpl_mock.h
@@ -20,7 +20,7 @@
 class MockFramebufferImpl : public rx::FramebufferImpl
 {
   public:
-    MockFramebufferImpl() : rx::FramebufferImpl(gl::FramebufferState()) {}
+    MockFramebufferImpl() : rx::FramebufferImpl(gl::FramebufferState(1)) {}
     virtual ~MockFramebufferImpl() { destructor(); }
 
     MOCK_METHOD3(discard, angle::Result(const gl::Context *, size_t, const GLenum *));
@@ -34,8 +34,6 @@
     MOCK_METHOD4(clearBufferiv, angle::Result(const gl::Context *, GLenum, GLint, const GLint *));
     MOCK_METHOD5(clearBufferfi, angle::Result(const gl::Context *, GLenum, GLint, GLfloat, GLint));
 
-    MOCK_CONST_METHOD1(getImplementationColorReadFormat, GLenum(const gl::Context *));
-    MOCK_CONST_METHOD1(getImplementationColorReadType, GLenum(const gl::Context *));
     MOCK_METHOD5(readPixels,
                  angle::Result(const gl::Context *, const gl::Rectangle &, GLenum, GLenum, void *));
 
@@ -50,7 +48,8 @@
 
     MOCK_CONST_METHOD1(checkStatus, bool(const gl::Context *));
 
-    MOCK_METHOD2(syncState, angle::Result(const gl::Context *, const gl::Framebuffer::DirtyBits &));
+    MOCK_METHOD3(syncState,
+                 angle::Result(const gl::Context *, GLenum, const gl::Framebuffer::DirtyBits &));
 
     MOCK_METHOD0(destructor, void());
 };
diff --git a/src/libANGLE/renderer/GLImplFactory.h b/src/libANGLE/renderer/GLImplFactory.h
index 9a054f6..1995197 100644
--- a/src/libANGLE/renderer/GLImplFactory.h
+++ b/src/libANGLE/renderer/GLImplFactory.h
@@ -92,8 +92,6 @@
     // Program Pipeline object creation
     virtual ProgramPipelineImpl *createProgramPipeline(const gl::ProgramPipelineState &data) = 0;
 
-    virtual std::vector<PathImpl *> createPaths(GLsizei range) = 0;
-
     // Memory object creation
     virtual MemoryObjectImpl *createMemoryObject() = 0;
 
diff --git a/src/libANGLE/renderer/MemoryObjectImpl.h b/src/libANGLE/renderer/MemoryObjectImpl.h
index 62d12da..9bb4154 100644
--- a/src/libANGLE/renderer/MemoryObjectImpl.h
+++ b/src/libANGLE/renderer/MemoryObjectImpl.h
@@ -29,6 +29,8 @@
 
     virtual void onDestroy(const gl::Context *context) = 0;
 
+    virtual angle::Result setDedicatedMemory(const gl::Context *context, bool dedicatedMemory) = 0;
+
     virtual angle::Result importFd(gl::Context *context,
                                    GLuint64 size,
                                    gl::HandleType handleType,
diff --git a/src/libANGLE/renderer/PathImpl.h b/src/libANGLE/renderer/PathImpl.h
deleted file mode 100644
index f07cbc5..0000000
--- a/src/libANGLE/renderer/PathImpl.h
+++ /dev/null
@@ -1,36 +0,0 @@
-//
-// Copyright 2002 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// PathImpl.h: Defines the Path implementation interface for
-// CHROMIUM_path_rendering path objects.
-
-#ifndef LIBANGLE_RENDERER_PATHIMPL_H_
-#define LIBANGLE_RENDERER_PATHIMPL_H_
-
-#include "angle_gl.h"
-#include "common/angleutils.h"
-#include "libANGLE/Error.h"
-
-namespace rx
-{
-
-class PathImpl : angle::NonCopyable
-{
-  public:
-    virtual ~PathImpl() {}
-
-    virtual angle::Result setCommands(GLsizei numCommands,
-                                      const GLubyte *commands,
-                                      GLsizei numCoords,
-                                      GLenum coordType,
-                                      const void *coords) = 0;
-
-    virtual void setPathParameter(GLenum pname, GLfloat value) = 0;
-};
-
-}  // namespace rx
-
-#endif  // LIBANGLE_RENDERER_PATHIMPL_H_
diff --git a/src/libANGLE/renderer/ProgramImpl.h b/src/libANGLE/renderer/ProgramImpl.h
index 2bc0704..cf6ee66 100644
--- a/src/libANGLE/renderer/ProgramImpl.h
+++ b/src/libANGLE/renderer/ProgramImpl.h
@@ -145,13 +145,6 @@
                                GLint location,
                                GLuint *params) const                                           = 0;
 
-    // CHROMIUM_path_rendering
-    // Set parameters to control fragment shader input variable interpolation
-    virtual void setPathFragmentInputGen(const std::string &inputName,
-                                         GLenum genMode,
-                                         GLint components,
-                                         const GLfloat *coeffs) = 0;
-
     // Implementation-specific method for ignoring unreferenced uniforms. Some implementations may
     // perform more extensive analysis and ignore some locations that ANGLE doesn't detect as
     // unreferenced. This method is not required to be overriden by a back-end.
diff --git a/src/libANGLE/renderer/ProgramPipelineImpl.cpp b/src/libANGLE/renderer/ProgramPipelineImpl.cpp
new file mode 100644
index 0000000..4589705
--- /dev/null
+++ b/src/libANGLE/renderer/ProgramPipelineImpl.cpp
@@ -0,0 +1,19 @@
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ProgramPipelineImpl.cpp: Defines the abstract rx::ProgramPipelineImpl class.
+
+#include "libANGLE/renderer/ProgramPipelineImpl.h"
+
+namespace rx
+{
+
+angle::Result ProgramPipelineImpl::link(const gl::Context *context)
+{
+    return angle::Result::Continue;
+}
+
+}  // namespace rx
diff --git a/src/libANGLE/renderer/ProgramPipelineImpl.h b/src/libANGLE/renderer/ProgramPipelineImpl.h
index 242e926..b488ca4 100644
--- a/src/libANGLE/renderer/ProgramPipelineImpl.h
+++ b/src/libANGLE/renderer/ProgramPipelineImpl.h
@@ -21,7 +21,11 @@
   public:
     ProgramPipelineImpl(const gl::ProgramPipelineState &state) : mState(state) {}
     virtual ~ProgramPipelineImpl() {}
-    virtual void destroy(const ContextImpl *contextImpl) {}
+    virtual void destroy(const gl::Context *context) {}
+
+    virtual angle::Result link(const gl::Context *context);
+
+    const gl::ProgramPipelineState &getState() const { return mState; }
 
   protected:
     const gl::ProgramPipelineState &mState;
diff --git a/src/libANGLE/renderer/QueryImpl.h b/src/libANGLE/renderer/QueryImpl.h
index c46b3d3..34ccb80 100644
--- a/src/libANGLE/renderer/QueryImpl.h
+++ b/src/libANGLE/renderer/QueryImpl.h
@@ -39,6 +39,15 @@
 
     gl::QueryType getType() const { return mType; }
 
+    // Convenient functions
+    bool isOcclusionQuery() const { return isAnySamplesQuery() || isAnySamplesConservativeQuery(); }
+    bool isAnySamplesQuery() const { return getType() == gl::QueryType::AnySamples; }
+
+    bool isAnySamplesConservativeQuery() const
+    {
+        return getType() == gl::QueryType::AnySamplesConservative;
+    }
+
   private:
     gl::QueryType mType;
 };
diff --git a/src/libANGLE/renderer/RenderTargetCache.h b/src/libANGLE/renderer/RenderTargetCache.h
index 5274963..49a4ae1 100644
--- a/src/libANGLE/renderer/RenderTargetCache.h
+++ b/src/libANGLE/renderer/RenderTargetCache.h
@@ -43,7 +43,7 @@
     using RenderTargetArray = gl::AttachmentArray<RenderTargetT *>;
 
     const RenderTargetArray &getColors() const;
-    RenderTargetT *getDepthStencil() const;
+    RenderTargetT *getDepthStencil(bool allowFeedbackLoop) const;
 
     RenderTargetT *getColorDraw(const gl::FramebufferState &state, size_t colorIndex) const;
     RenderTargetT *getColorRead(const gl::FramebufferState &state) const;
@@ -53,20 +53,18 @@
                                            const gl::FramebufferAttachment *attachment,
                                            RenderTargetT **cachedRenderTarget);
 
-    RenderTargetT *mReadRenderTarget;
-    gl::AttachmentArray<RenderTargetT *> mColorRenderTargets;
+    RenderTargetT *mReadRenderTarget                         = nullptr;
+    gl::AttachmentArray<RenderTargetT *> mColorRenderTargets = {};
     // We only support a single Depth/Stencil RenderTarget currently.
-    RenderTargetT *mDepthStencilRenderTarget;
+    bool mDepthStencilFeedbackLoop           = false;
+    RenderTargetT *mDepthStencilRenderTarget = nullptr;
 };
 
 template <typename RenderTargetT>
-RenderTargetCache<RenderTargetT>::RenderTargetCache()
-    : mReadRenderTarget{nullptr}, mColorRenderTargets{{nullptr}}, mDepthStencilRenderTarget(nullptr)
-{}
+RenderTargetCache<RenderTargetT>::RenderTargetCache() = default;
 
 template <typename RenderTargetT>
-RenderTargetCache<RenderTargetT>::~RenderTargetCache()
-{}
+RenderTargetCache<RenderTargetT>::~RenderTargetCache() = default;
 
 template <typename RenderTargetT>
 angle::Result RenderTargetCache<RenderTargetT>::update(const gl::Context *context,
@@ -114,9 +112,9 @@
 }
 
 template <typename RenderTargetT>
-RenderTargetT *RenderTargetCache<RenderTargetT>::getDepthStencil() const
+RenderTargetT *RenderTargetCache<RenderTargetT>::getDepthStencil(bool allowFeedbackLoop) const
 {
-    return mDepthStencilRenderTarget;
+    return (allowFeedbackLoop || !mDepthStencilFeedbackLoop) ? mDepthStencilRenderTarget : nullptr;
 }
 
 template <typename RenderTargetT>
@@ -149,6 +147,7 @@
     const gl::Context *context,
     const gl::FramebufferState &state)
 {
+    mDepthStencilFeedbackLoop = state.hasDepthStencilFeedbackLoop();
     return updateCachedRenderTarget(context, state.getDepthOrStencilAttachment(),
                                     &mDepthStencilRenderTarget);
 }
diff --git a/src/libANGLE/renderer/TextureImpl.h b/src/libANGLE/renderer/TextureImpl.h
index d202cbb..7eb09e1 100644
--- a/src/libANGLE/renderer/TextureImpl.h
+++ b/src/libANGLE/renderer/TextureImpl.h
@@ -56,6 +56,7 @@
                                    GLenum format,
                                    GLenum type,
                                    const gl::PixelUnpackState &unpack,
+                                   gl::Buffer *unpackBuffer,
                                    const uint8_t *pixels)    = 0;
     virtual angle::Result setSubImage(const gl::Context *context,
                                       const gl::ImageIndex &index,
diff --git a/src/libANGLE/renderer/TextureImpl_mock.h b/src/libANGLE/renderer/TextureImpl_mock.h
index ba9bee0..abc0440 100644
--- a/src/libANGLE/renderer/TextureImpl_mock.h
+++ b/src/libANGLE/renderer/TextureImpl_mock.h
@@ -21,7 +21,7 @@
   public:
     MockTextureImpl() : TextureImpl(mMockState), mMockState(gl::TextureType::_2D) {}
     virtual ~MockTextureImpl() { destructor(); }
-    MOCK_METHOD8(setImage,
+    MOCK_METHOD9(setImage,
                  angle::Result(const gl::Context *,
                                const gl::ImageIndex &,
                                GLenum,
@@ -29,6 +29,7 @@
                                GLenum,
                                GLenum,
                                const gl::PixelUnpackState &,
+                               gl::Buffer *,
                                const uint8_t *));
     MOCK_METHOD8(setSubImage,
                  angle::Result(const gl::Context *,
diff --git a/src/libANGLE/renderer/angle_format_map.json b/src/libANGLE/renderer/angle_format_map.json
index 318ba38..8fdfac2 100644
--- a/src/libANGLE/renderer/angle_format_map.json
+++ b/src/libANGLE/renderer/angle_format_map.json
@@ -151,6 +151,7 @@
   [ "GL_RGBA8UI", "R8G8B8A8_UINT" ],
   [ "GL_RGBA8_SNORM", "R8G8B8A8_SNORM" ],
   [ "GL_SRGB8", "R8G8B8_UNORM_SRGB" ],
+  [ "GL_SR8_EXT", "R8_UNORM_SRGB" ],
   [ "GL_SRGB8_ALPHA8", "R8G8B8A8_UNORM_SRGB" ],
   [ "GL_STENCIL_INDEX8", "S8_UINT" ],
   [ "GL_R16_EXT", "R16_UNORM" ],
diff --git a/src/libANGLE/renderer/d3d/FramebufferD3D.cpp b/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
index b782fa7..4575b06 100644
--- a/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
+++ b/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
@@ -184,54 +184,6 @@
     return clearImpl(context, clearParams);
 }
 
-GLenum FramebufferD3D::getImplementationColorReadFormat(const gl::Context *context) const
-{
-    const gl::FramebufferAttachment *readAttachment = mState.getReadAttachment();
-
-    if (readAttachment == nullptr)
-    {
-        return GL_NONE;
-    }
-
-    RenderTargetD3D *attachmentRenderTarget = nullptr;
-    angle::Result error                     = readAttachment->getRenderTarget(
-        context, readAttachment->getRenderToTextureSamples(), &attachmentRenderTarget);
-    if (error != angle::Result::Continue)
-    {
-        return GL_NONE;
-    }
-
-    GLenum implementationFormat = getRenderTargetImplementationFormat(attachmentRenderTarget);
-    const gl::InternalFormat &implementationFormatInfo =
-        gl::GetSizedInternalFormatInfo(implementationFormat);
-
-    return implementationFormatInfo.getReadPixelsFormat(context->getExtensions());
-}
-
-GLenum FramebufferD3D::getImplementationColorReadType(const gl::Context *context) const
-{
-    const gl::FramebufferAttachment *readAttachment = mState.getReadAttachment();
-
-    if (readAttachment == nullptr)
-    {
-        return GL_NONE;
-    }
-
-    RenderTargetD3D *attachmentRenderTarget = nullptr;
-    angle::Result error                     = readAttachment->getRenderTarget(
-        context, readAttachment->getRenderToTextureSamples(), &attachmentRenderTarget);
-    if (error != angle::Result::Continue)
-    {
-        return GL_NONE;
-    }
-
-    GLenum implementationFormat = getRenderTargetImplementationFormat(attachmentRenderTarget);
-    const gl::InternalFormat &implementationFormatInfo =
-        gl::GetSizedInternalFormatInfo(implementationFormat);
-
-    return implementationFormatInfo.getReadPixelsType(context->getClientVersion());
-}
-
 angle::Result FramebufferD3D::readPixels(const gl::Context *context,
                                          const gl::Rectangle &area,
                                          GLenum format,
@@ -239,7 +191,7 @@
                                          void *pixels)
 {
     // Clip read area to framebuffer.
-    const gl::Extents fbSize = getState().getReadAttachment()->getSize();
+    const gl::Extents fbSize = getState().getReadPixelsAttachment(format)->getSize();
     const gl::Rectangle fbRect(0, 0, fbSize.width, fbSize.height);
     gl::Rectangle clippedArea;
     if (!ClipRectangle(area, fbRect, &clippedArea))
@@ -316,6 +268,7 @@
 }
 
 angle::Result FramebufferD3D::syncState(const gl::Context *context,
+                                        GLenum binding,
                                         const gl::Framebuffer::DirtyBits &dirtyBits)
 {
     if (!mColorAttachmentsForRender.valid())
diff --git a/src/libANGLE/renderer/d3d/FramebufferD3D.h b/src/libANGLE/renderer/d3d/FramebufferD3D.h
index 9f98edf..1d35774 100644
--- a/src/libANGLE/renderer/d3d/FramebufferD3D.h
+++ b/src/libANGLE/renderer/d3d/FramebufferD3D.h
@@ -81,8 +81,6 @@
                                 GLfloat depth,
                                 GLint stencil) override;
 
-    GLenum getImplementationColorReadFormat(const gl::Context *context) const override;
-    GLenum getImplementationColorReadType(const gl::Context *context) const override;
     angle::Result readPixels(const gl::Context *context,
                              const gl::Rectangle &area,
                              GLenum format,
@@ -98,6 +96,7 @@
     bool checkStatus(const gl::Context *context) const override;
 
     angle::Result syncState(const gl::Context *context,
+                            GLenum binding,
                             const gl::Framebuffer::DirtyBits &dirtyBits) override;
 
     const gl::AttachmentList &getColorAttachmentsForRender(const gl::Context *context);
@@ -131,8 +130,6 @@
                                    GLenum filter,
                                    const gl::Framebuffer *sourceFramebuffer) = 0;
 
-    virtual GLenum getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const = 0;
-
     RendererD3D *mRenderer;
     Optional<gl::AttachmentList> mColorAttachmentsForRender;
     gl::DrawBufferMask mCurrentActiveProgramOutputs;
diff --git a/src/libANGLE/renderer/d3d/OWNERS b/src/libANGLE/renderer/d3d/OWNERS
new file mode 100644
index 0000000..9a1736e
--- /dev/null
+++ b/src/libANGLE/renderer/d3d/OWNERS
@@ -0,0 +1,2 @@
+geofflang@chromium.org
+jmadill@chromium.org
diff --git a/src/libANGLE/renderer/d3d/ProgramD3D.cpp b/src/libANGLE/renderer/d3d/ProgramD3D.cpp
index 17c80cd..ee18c16 100644
--- a/src/libANGLE/renderer/d3d/ProgramD3D.cpp
+++ b/src/libANGLE/renderer/d3d/ProgramD3D.cpp
@@ -1047,6 +1047,22 @@
         mD3DShaderStorageBlocks.push_back(shaderStorageBlock);
     }
 
+    const unsigned int image2DUniformCount = stream->readInt<unsigned int>();
+    if (stream->error())
+    {
+        infoLog << "Invalid program binary.";
+        return std::make_unique<LinkEventDone>(angle::Result::Incomplete);
+    }
+
+    ASSERT(mImage2DUniforms.empty());
+    for (unsigned int image2DUniformIndex = 0; image2DUniformIndex < image2DUniformCount;
+         ++image2DUniformIndex)
+    {
+        sh::ShaderVariable image2Duniform;
+        gl::LoadShaderVar(stream, &image2Duniform);
+        mImage2DUniforms.push_back(image2Duniform);
+    }
+
     for (unsigned int ii = 0; ii < gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS; ++ii)
     {
         unsigned int index                             = stream->readInt<unsigned int>();
@@ -1291,7 +1307,7 @@
             stream->readInt<unsigned int>(), gl::TextureType::_2D));
     }
 
-    initializeUniformStorage(mState.getLinkedShaderStages());
+    initializeUniformStorage(mState.getProgramExecutable().getLinkedShaderStages());
 
     dirtyAllUniforms();
 
@@ -1358,6 +1374,12 @@
         }
     }
 
+    stream->writeInt(mImage2DUniforms.size());
+    for (const sh::ShaderVariable &image2DUniform : mImage2DUniforms)
+    {
+        gl::WriteShaderVar(stream, image2DUniform);
+    }
+
     for (unsigned int ii = 0; ii < gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS; ++ii)
     {
         stream->writeInt(mComputeAtomicCounterBufferRegisterIndices[ii]);
@@ -2331,7 +2353,7 @@
 
 void ProgramD3D::dirtyAllUniforms()
 {
-    mShaderUniformsDirty = mState.getLinkedShaderStages();
+    mShaderUniformsDirty = mState.getProgramExecutable().getLinkedShaderStages();
 }
 
 void ProgramD3D::markUniformsClean()
@@ -3026,8 +3048,10 @@
     mCachedInputLayout.clear();
 
     const auto &vertexAttributes = state.getVertexArray()->getVertexAttributes();
+    const gl::AttributesMask &attributesMask =
+        mState.getProgramExecutable().getActiveAttribLocationsMask();
 
-    for (size_t locationIndex : mState.getActiveAttribLocationsMask())
+    for (size_t locationIndex : attributesMask)
     {
         int d3dSemantic = mAttribLocationToD3DSemantic[locationIndex];
 
@@ -3168,14 +3192,6 @@
     return mD3DUniforms[mState.getUniformLocations()[location].index];
 }
 
-void ProgramD3D::setPathFragmentInputGen(const std::string &inputName,
-                                         GLenum genMode,
-                                         GLint components,
-                                         const GLfloat *coeffs)
-{
-    UNREACHABLE();
-}
-
 bool ProgramD3D::hasVertexExecutableForCachedInputLayout()
 {
     return mCachedVertexExecutableIndex.valid();
diff --git a/src/libANGLE/renderer/d3d/ProgramD3D.h b/src/libANGLE/renderer/d3d/ProgramD3D.h
index 1de0ef0..4fca19d 100644
--- a/src/libANGLE/renderer/d3d/ProgramD3D.h
+++ b/src/libANGLE/renderer/d3d/ProgramD3D.h
@@ -236,11 +236,6 @@
                                     gl::InfoLog &infoLog) override;
     GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override;
 
-    void setPathFragmentInputGen(const std::string &inputName,
-                                 GLenum genMode,
-                                 GLint components,
-                                 const GLfloat *coeffs) override;
-
     void updateUniformBufferCache(const gl::Caps &caps);
 
     unsigned int getAtomicCounterBufferRegisterIndex(GLuint binding,
@@ -344,7 +339,7 @@
 
     bool hasShaderStage(gl::ShaderType shaderType) const
     {
-        return mState.getLinkedShaderStages()[shaderType];
+        return mState.getProgramExecutable().getLinkedShaderStages()[shaderType];
     }
 
     void assignImage2DRegisters(unsigned int startImageIndex,
diff --git a/src/libANGLE/renderer/d3d/RendererD3D.h b/src/libANGLE/renderer/d3d/RendererD3D.h
index ebe9051..89c5e27 100644
--- a/src/libANGLE/renderer/d3d/RendererD3D.h
+++ b/src/libANGLE/renderer/d3d/RendererD3D.h
@@ -345,6 +345,7 @@
     virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const = 0;
     virtual angle::Result fastCopyBufferToTexture(const gl::Context *context,
                                                   const gl::PixelUnpackState &unpack,
+                                                  gl::Buffer *unpackBuffer,
                                                   unsigned int offset,
                                                   RenderTargetD3D *destRenderTarget,
                                                   GLenum destinationFormat,
diff --git a/src/libANGLE/renderer/d3d/TextureD3D.cpp b/src/libANGLE/renderer/d3d/TextureD3D.cpp
index 252d97e..15fc053 100644
--- a/src/libANGLE/renderer/d3d/TextureD3D.cpp
+++ b/src/libANGLE/renderer/d3d/TextureD3D.cpp
@@ -226,11 +226,11 @@
                                        const gl::ImageIndex &index,
                                        GLenum type,
                                        const gl::PixelUnpackState &unpack,
+                                       gl::Buffer *unpackBuffer,
                                        const uint8_t *pixels,
                                        ptrdiff_t layerOffset)
 {
-    ImageD3D *image          = getImage(index);
-    gl::Buffer *unpackBuffer = context->getState().getTargetBuffer(gl::BufferBinding::PixelUnpack);
+    ImageD3D *image = getImage(index);
     ASSERT(image);
 
     // No-op
@@ -363,6 +363,7 @@
 
 angle::Result TextureD3D::fastUnpackPixels(const gl::Context *context,
                                            const gl::PixelUnpackState &unpack,
+                                           gl::Buffer *unpackBuffer,
                                            const uint8_t *pixels,
                                            const gl::Box &destArea,
                                            GLenum sizedInternalFormat,
@@ -386,9 +387,9 @@
 
     uintptr_t offset = reinterpret_cast<uintptr_t>(pixels);
 
-    ANGLE_TRY(mRenderer->fastCopyBufferToTexture(context, unpack, static_cast<unsigned int>(offset),
-                                                 destRenderTarget, sizedInternalFormat, type,
-                                                 destArea));
+    ANGLE_TRY(mRenderer->fastCopyBufferToTexture(
+        context, unpack, unpackBuffer, static_cast<unsigned int>(offset), destRenderTarget,
+        sizedInternalFormat, type, destArea));
 
     return angle::Result::Continue;
 }
@@ -889,6 +890,7 @@
                                       GLenum format,
                                       GLenum type,
                                       const gl::PixelUnpackState &unpack,
+                                      gl::Buffer *unpackBuffer,
                                       const uint8_t *pixels)
 {
     ASSERT((index.getTarget() == gl::TextureTarget::_2D ||
@@ -903,7 +905,6 @@
                             size, false));
 
     // Attempt a fast gpu copy of the pixel data to the surface
-    gl::Buffer *unpackBuffer = context->getState().getTargetBuffer(gl::BufferBinding::PixelUnpack);
     if (mTexStorage)
     {
         ANGLE_TRY(mTexStorage->releaseMultisampledTexStorageForLevel(index.getLevelIndex()));
@@ -918,7 +919,7 @@
         gl::Box destArea(0, 0, 0, getWidth(index.getLevelIndex()), getHeight(index.getLevelIndex()),
                          1);
 
-        ANGLE_TRY(fastUnpackPixels(context, unpack, pixels, destArea,
+        ANGLE_TRY(fastUnpackPixels(context, unpack, unpackBuffer, pixels, destArea,
                                    internalFormatInfo.sizedInternalFormat, type, destRenderTarget));
 
         // Ensure we don't overwrite our newly initialized data
@@ -929,7 +930,7 @@
 
     if (!fastUnpacked)
     {
-        ANGLE_TRY(setImageImpl(context, index, type, unpack, pixels, 0));
+        ANGLE_TRY(setImageImpl(context, index, type, unpack, unpackBuffer, pixels, 0));
     }
 
     return angle::Result::Continue;
@@ -957,7 +958,8 @@
         ANGLE_TRY(getRenderTarget(context, index, getRenderToTextureSamples(), &renderTarget));
         ASSERT(!mImageArray[index.getLevelIndex()]->isDirty());
 
-        return fastUnpackPixels(context, unpack, pixels, area, mipFormat, type, renderTarget);
+        return fastUnpackPixels(context, unpack, unpackBuffer, pixels, area, mipFormat, type,
+                                renderTarget);
     }
     else
     {
@@ -1692,6 +1694,7 @@
                                         GLenum format,
                                         GLenum type,
                                         const gl::PixelUnpackState &unpack,
+                                        gl::Buffer *unpackBuffer,
                                         const uint8_t *pixels)
 {
     ASSERT(size.depth == 1);
@@ -1700,7 +1703,7 @@
     ANGLE_TRY(redefineImage(context, index.cubeMapFaceIndex(), index.getLevelIndex(),
                             internalFormatInfo.sizedInternalFormat, size, false));
 
-    return setImageImpl(context, index, type, unpack, pixels, 0);
+    return setImageImpl(context, index, type, unpack, unpackBuffer, pixels, 0);
 }
 
 angle::Result TextureD3D_Cube::setSubImage(const gl::Context *context,
@@ -2425,6 +2428,7 @@
                                       GLenum format,
                                       GLenum type,
                                       const gl::PixelUnpackState &unpack,
+                                      gl::Buffer *unpackBuffer,
                                       const uint8_t *pixels)
 {
     ASSERT(index.getTarget() == gl::TextureTarget::_3D);
@@ -2436,7 +2440,6 @@
     bool fastUnpacked = false;
 
     // Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer
-    gl::Buffer *unpackBuffer = context->getState().getTargetBuffer(gl::BufferBinding::PixelUnpack);
     if (isFastUnpackable(unpackBuffer, internalFormatInfo.sizedInternalFormat) && !size.empty() &&
         isLevelComplete(index.getLevelIndex()))
     {
@@ -2447,7 +2450,7 @@
         gl::Box destArea(0, 0, 0, getWidth(index.getLevelIndex()), getHeight(index.getLevelIndex()),
                          getDepth(index.getLevelIndex()));
 
-        ANGLE_TRY(fastUnpackPixels(context, unpack, pixels, destArea,
+        ANGLE_TRY(fastUnpackPixels(context, unpack, unpackBuffer, pixels, destArea,
                                    internalFormatInfo.sizedInternalFormat, type, destRenderTarget));
 
         // Ensure we don't overwrite our newly initialized data
@@ -2458,7 +2461,7 @@
 
     if (!fastUnpacked)
     {
-        ANGLE_TRY(setImageImpl(context, index, type, unpack, pixels, 0));
+        ANGLE_TRY(setImageImpl(context, index, type, unpack, unpackBuffer, pixels, 0));
     }
 
     return angle::Result::Continue;
@@ -2483,7 +2486,8 @@
         ANGLE_TRY(getRenderTarget(context, index, getRenderToTextureSamples(), &destRenderTarget));
         ASSERT(!mImageArray[index.getLevelIndex()]->isDirty());
 
-        return fastUnpackPixels(context, unpack, pixels, area, mipFormat, type, destRenderTarget);
+        return fastUnpackPixels(context, unpack, unpackBuffer, pixels, area, mipFormat, type,
+                                destRenderTarget);
     }
     else
     {
@@ -3090,6 +3094,7 @@
                                            GLenum format,
                                            GLenum type,
                                            const gl::PixelUnpackState &unpack,
+                                           gl::Buffer *unpackBuffer,
                                            const uint8_t *pixels)
 {
     ASSERT(index.getTarget() == gl::TextureTarget::_2DArray);
@@ -3110,7 +3115,8 @@
     {
         const ptrdiff_t layerOffset = (inputDepthPitch * i);
         gl::ImageIndex layerIndex   = gl::ImageIndex::Make2DArray(index.getLevelIndex(), i);
-        ANGLE_TRY(setImageImpl(context, layerIndex, type, unpack, pixels, layerOffset));
+        ANGLE_TRY(
+            setImageImpl(context, layerIndex, type, unpack, unpackBuffer, pixels, layerOffset));
     }
 
     return angle::Result::Continue;
@@ -3806,6 +3812,7 @@
                                                 GLenum format,
                                                 GLenum type,
                                                 const gl::PixelUnpackState &unpack,
+                                                gl::Buffer *unpackBuffer,
                                                 const uint8_t *pixels)
 {
     ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
diff --git a/src/libANGLE/renderer/d3d/TextureD3D.h b/src/libANGLE/renderer/d3d/TextureD3D.h
index 8451313..c0ab57b 100644
--- a/src/libANGLE/renderer/d3d/TextureD3D.h
+++ b/src/libANGLE/renderer/d3d/TextureD3D.h
@@ -122,6 +122,7 @@
                                const gl::ImageIndex &index,
                                GLenum type,
                                const gl::PixelUnpackState &unpack,
+                               gl::Buffer *unpackBuffer,
                                const uint8_t *pixels,
                                ptrdiff_t layerOffset);
     angle::Result subImage(const gl::Context *context,
@@ -148,6 +149,7 @@
     bool isFastUnpackable(const gl::Buffer *unpackBuffer, GLenum sizedInternalFormat);
     angle::Result fastUnpackPixels(const gl::Context *context,
                                    const gl::PixelUnpackState &unpack,
+                                   gl::Buffer *unpackBuffer,
                                    const uint8_t *pixels,
                                    const gl::Box &destArea,
                                    GLenum sizedInternalFormat,
@@ -227,6 +229,7 @@
                            GLenum format,
                            GLenum type,
                            const gl::PixelUnpackState &unpack,
+                           gl::Buffer *unpackBuffer,
                            const uint8_t *pixels) override;
     angle::Result setSubImage(const gl::Context *context,
                               const gl::ImageIndex &index,
@@ -358,6 +361,7 @@
                            GLenum format,
                            GLenum type,
                            const gl::PixelUnpackState &unpack,
+                           gl::Buffer *unpackBuffer,
                            const uint8_t *pixels) override;
     angle::Result setSubImage(const gl::Context *context,
                               const gl::ImageIndex &index,
@@ -490,6 +494,7 @@
                            GLenum format,
                            GLenum type,
                            const gl::PixelUnpackState &unpack,
+                           gl::Buffer *unpackBuffer,
                            const uint8_t *pixels) override;
     angle::Result setSubImage(const gl::Context *context,
                               const gl::ImageIndex &index,
@@ -619,6 +624,7 @@
                            GLenum format,
                            GLenum type,
                            const gl::PixelUnpackState &unpack,
+                           gl::Buffer *unpackBuffer,
                            const uint8_t *pixels) override;
     angle::Result setSubImage(const gl::Context *context,
                               const gl::ImageIndex &index,
@@ -746,6 +752,7 @@
                            GLenum format,
                            GLenum type,
                            const gl::PixelUnpackState &unpack,
+                           gl::Buffer *unpackBuffer,
                            const uint8_t *pixels) override;
     angle::Result setSubImage(const gl::Context *context,
                               const gl::ImageIndex &index,
diff --git a/src/libANGLE/renderer/d3d/VertexDataManager.cpp b/src/libANGLE/renderer/d3d/VertexDataManager.cpp
index c1ffc1c..b418b5d 100644
--- a/src/libANGLE/renderer/d3d/VertexDataManager.cpp
+++ b/src/libANGLE/renderer/d3d/VertexDataManager.cpp
@@ -248,20 +248,20 @@
     std::vector<TranslatedAttribute> *translatedAttribs,
     GLsizei instances)
 {
-    const gl::State &state             = context->getState();
-    const gl::VertexArray *vertexArray = state.getVertexArray();
-    const auto &vertexAttributes       = vertexArray->getVertexAttributes();
-    const auto &vertexBindings         = vertexArray->getVertexBindings();
+    const gl::State &state                  = context->getState();
+    const gl::ProgramExecutable *executable = state.getProgramExecutable();
+    const gl::VertexArray *vertexArray      = state.getVertexArray();
+    const auto &vertexAttributes            = vertexArray->getVertexAttributes();
+    const auto &vertexBindings              = vertexArray->getVertexBindings();
 
     mDynamicAttribsMaskCache.reset();
-    const gl::Program *program = state.getProgram();
 
     translatedAttribs->clear();
 
     for (size_t attribIndex = 0; attribIndex < vertexAttributes.size(); ++attribIndex)
     {
         // Skip attrib locations the program doesn't use.
-        if (!program->isAttribLocationActive(attribIndex))
+        if (!executable->isAttribLocationActive(attribIndex))
             continue;
 
         const auto &attrib  = vertexAttributes[attribIndex];
diff --git a/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp b/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp
index 0d5b25c..fe1d402 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp
@@ -426,7 +426,16 @@
                 size <= static_cast<UINT>(mRenderer->getNativeCaps().maxUniformBlockSize) &&
                 !mRenderer->getFeatures().useSystemMemoryForConstantBuffers.enabled)
             {
-                ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_UNIFORM, &writeBuffer));
+                BufferStorage *latestStorage = nullptr;
+                ANGLE_TRY(getLatestBufferStorage(context, &latestStorage));
+                if (latestStorage && (latestStorage->getUsage() == BUFFER_USAGE_STRUCTURED))
+                {
+                    ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_STRUCTURED, &writeBuffer));
+                }
+                else
+                {
+                    ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_UNIFORM, &writeBuffer));
+                }
             }
             else
             {
diff --git a/src/libANGLE/renderer/d3d/d3d11/Context11.cpp b/src/libANGLE/renderer/d3d/d3d11/Context11.cpp
index 9dc658f..659ad5c 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Context11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/Context11.cpp
@@ -229,11 +229,6 @@
     return new ProgramPipeline11(data);
 }
 
-std::vector<PathImpl *> Context11::createPaths(GLsizei)
-{
-    return std::vector<PathImpl *>();
-}
-
 MemoryObjectImpl *Context11::createMemoryObject()
 {
     UNREACHABLE();
@@ -346,9 +341,7 @@
                                                 const void *indices,
                                                 GLint baseVertex)
 {
-    // TODO: angleproject:3402
-    UNIMPLEMENTED();
-    return angle::Result::Stop;
+    return drawElementsImpl(context, mode, count, type, indices, 0, baseVertex, 0);
 }
 
 angle::Result Context11::drawElementsInstanced(const gl::Context *context,
@@ -369,9 +362,7 @@
                                                          GLsizei instances,
                                                          GLint baseVertex)
 {
-    // TODO: angleproject:3402
-    UNIMPLEMENTED();
-    return angle::Result::Stop;
+    return drawElementsImpl(context, mode, count, type, indices, instances, baseVertex, 0);
 }
 
 angle::Result Context11::drawElementsInstancedBaseVertexBaseInstance(const gl::Context *context,
@@ -407,9 +398,7 @@
                                                      const void *indices,
                                                      GLint baseVertex)
 {
-    // TODO: angleproject:3402
-    UNIMPLEMENTED();
-    return angle::Result::Stop;
+    return drawElementsImpl(context, mode, count, type, indices, 0, baseVertex, 0);
 }
 
 angle::Result Context11::drawArraysIndirect(const gl::Context *context,
diff --git a/src/libANGLE/renderer/d3d/d3d11/Context11.h b/src/libANGLE/renderer/d3d/d3d11/Context11.h
index fa267d2..ac477cb 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Context11.h
+++ b/src/libANGLE/renderer/d3d/d3d11/Context11.h
@@ -62,9 +62,6 @@
     // Program Pipeline object creation
     ProgramPipelineImpl *createProgramPipeline(const gl::ProgramPipelineState &data) override;
 
-    // Path object creation.
-    std::vector<PathImpl *> createPaths(GLsizei) override;
-
     // Memory object creation.
     MemoryObjectImpl *createMemoryObject() override;
 
diff --git a/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp b/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp
index 138eab3..2561eca 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp
@@ -17,6 +17,7 @@
 #include "libANGLE/renderer/d3d/TextureD3D.h"
 #include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
 #include "libANGLE/renderer/d3d/d3d11/Clear11.h"
+#include "libANGLE/renderer/d3d/d3d11/Context11.h"
 #include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
 #include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
 #include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
@@ -253,7 +254,7 @@
                                             const gl::PixelPackState &pack,
                                             uint8_t *pixels)
 {
-    const gl::FramebufferAttachment *readAttachment = mState.getReadAttachment();
+    const gl::FramebufferAttachment *readAttachment = mState.getReadPixelsAttachment(format);
     ASSERT(readAttachment);
 
     gl::Buffer *packBuffer = context->getState().getTargetBuffer(gl::BufferBinding::PixelPack);
@@ -374,17 +375,22 @@
     return angle::Result::Continue;
 }
 
-GLenum Framebuffer11::getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const
+const gl::InternalFormat &Framebuffer11::getImplementationColorReadFormat(
+    const gl::Context *context) const
 {
-    RenderTarget11 *renderTarget11 = GetAs<RenderTarget11>(renderTarget);
-    return renderTarget11->getFormatSet().format().fboImplementationInternalFormat;
+    Context11 *context11             = GetImplAs<Context11>(context);
+    const Renderer11DeviceCaps &caps = context11->getRenderer()->getRenderer11DeviceCaps();
+    GLenum sizedFormat = mState.getReadAttachment()->getFormat().info->sizedInternalFormat;
+    const angle::Format &angleFormat = d3d11::Format::Get(sizedFormat, caps).format();
+    return gl::GetSizedInternalFormatInfo(angleFormat.fboImplementationInternalFormat);
 }
 
 angle::Result Framebuffer11::syncState(const gl::Context *context,
+                                       GLenum binding,
                                        const gl::Framebuffer::DirtyBits &dirtyBits)
 {
     ANGLE_TRY(mRenderTargetCache.update(context, mState, dirtyBits));
-    ANGLE_TRY(FramebufferD3D::syncState(context, dirtyBits));
+    ANGLE_TRY(FramebufferD3D::syncState(context, binding, dirtyBits));
 
     // Call this last to allow the state manager to take advantage of the cached render targets.
     mRenderer->getStateManager()->invalidateRenderTarget();
@@ -420,7 +426,7 @@
         }
     }
 
-    return mRenderTargetCache.getDepthStencil();
+    return mRenderTargetCache.getDepthStencil(true);
 }
 
 }  // namespace rx
diff --git a/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h b/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h
index 8516d7d..e90b4af 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h
+++ b/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h
@@ -39,6 +39,7 @@
     angle::Result markAttachmentsDirty(const gl::Context *context) const;
 
     angle::Result syncState(const gl::Context *context,
+                            GLenum binding,
                             const gl::Framebuffer::DirtyBits &dirtyBits) override;
 
     const gl::AttachmentArray<RenderTarget11 *> &getCachedColorRenderTargets() const
@@ -47,7 +48,7 @@
     }
     const RenderTarget11 *getCachedDepthStencilRenderTarget() const
     {
-        return mRenderTargetCache.getDepthStencil();
+        return mRenderTargetCache.getDepthStencil(true);
     }
 
     RenderTarget11 *getFirstRenderTarget() const;
@@ -56,6 +57,9 @@
                                     size_t index,
                                     GLfloat *xy) const override;
 
+    const gl::InternalFormat &getImplementationColorReadFormat(
+        const gl::Context *context) const override;
+
   private:
     angle::Result clearImpl(const gl::Context *context,
                             const ClearParameters &clearParams) override;
@@ -85,8 +89,6 @@
     angle::Result invalidateAttachment(const gl::Context *context,
                                        const gl::FramebufferAttachment *attachment) const;
 
-    GLenum getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const override;
-
     Renderer11 *const mRenderer;
     RenderTargetCache<RenderTarget11> mRenderTargetCache;
 };
diff --git a/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp b/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp
index c184d7c..3902b0f 100644
--- a/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp
@@ -149,7 +149,7 @@
     const auto &locationToSemantic = programD3D->getAttribLocationToD3DSemantics();
     int divisorMultiplier          = program->usesMultiview() ? program->getNumViews() : 1;
 
-    for (size_t attribIndex : program->getActiveAttribLocationsMask())
+    for (size_t attribIndex : state.getProgramExecutable()->getActiveAttribLocationsMask())
     {
         // Record the type of the associated vertex shader vector in our key
         // This will prevent mismatched vertex shaders from using the same input layout
diff --git a/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp b/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp
index 4736a8c..eb4d5ea 100644
--- a/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp
@@ -150,12 +150,15 @@
 
 angle::Result PixelTransfer11::copyBufferToTexture(const gl::Context *context,
                                                    const gl::PixelUnpackState &unpack,
+                                                   gl::Buffer *unpackBuffer,
                                                    unsigned int offset,
                                                    RenderTargetD3D *destRenderTarget,
                                                    GLenum destinationFormat,
                                                    GLenum sourcePixelsType,
                                                    const gl::Box &destArea)
 {
+    ASSERT(unpackBuffer);
+
     ANGLE_TRY(loadResources(context));
 
     gl::Extents destSize = destRenderTarget->getExtents();
@@ -164,9 +167,6 @@
            destArea.y + destArea.height <= destSize.height && destArea.z >= 0 &&
            destArea.z + destArea.depth <= destSize.depth);
 
-    const gl::Buffer &sourceBuffer =
-        *context->getState().getTargetBuffer(gl::BufferBinding::PixelUnpack);
-
     ASSERT(mRenderer->supportsFastCopyBufferToTexture(destinationFormat));
 
     const d3d11::PixelShader *pixelShader = findBufferToTexturePS(destinationFormat);
@@ -182,7 +182,7 @@
         sourceglFormatInfo.sizedInternalFormat, mRenderer->getRenderer11DeviceCaps());
     DXGI_FORMAT srvFormat = sourceFormatInfo.srvFormat;
     ASSERT(srvFormat != DXGI_FORMAT_UNKNOWN);
-    Buffer11 *bufferStorage11                  = GetAs<Buffer11>(sourceBuffer.getImplementation());
+    Buffer11 *bufferStorage11                  = GetAs<Buffer11>(unpackBuffer->getImplementation());
     const d3d11::ShaderResourceView *bufferSRV = nullptr;
     ANGLE_TRY(bufferStorage11->getSRV(context, srvFormat, &bufferSRV));
     ASSERT(bufferSRV != nullptr);
diff --git a/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h b/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h
index 4a5e853..bdb11b9 100644
--- a/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h
+++ b/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h
@@ -46,6 +46,7 @@
     // destArea: the sub-section of destRenderTarget to copy to
     angle::Result copyBufferToTexture(const gl::Context *context,
                                       const gl::PixelUnpackState &unpack,
+                                      gl::Buffer *unpackBuffer,
                                       unsigned int offset,
                                       RenderTargetD3D *destRenderTarget,
                                       GLenum destinationFormat,
diff --git a/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp b/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp
index d24420d..feda997 100644
--- a/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp
@@ -70,15 +70,15 @@
         // enforcing default values.
         keyBlendState = gl::BlendState();
 
-        if (blendState.blend)
+        ASSERT(keyBlendIndex < colorbuffers.size());
+        const gl::FramebufferAttachment *attachment = colorbuffers[keyBlendIndex];
+
+        // Do not set blend state for null attachments that may be present when
+        // mrt_perf_workaround is disabled.
+        if (attachment == nullptr)
         {
-            keyBlendState.blend              = true;
-            keyBlendState.sourceBlendRGB     = blendState.sourceBlendRGB;
-            keyBlendState.sourceBlendAlpha   = blendState.sourceBlendAlpha;
-            keyBlendState.destBlendRGB       = blendState.destBlendRGB;
-            keyBlendState.destBlendAlpha     = blendState.destBlendAlpha;
-            keyBlendState.blendEquationRGB   = blendState.blendEquationRGB;
-            keyBlendState.blendEquationAlpha = blendState.blendEquationAlpha;
+            keyBlendIndex++;
+            continue;
         }
 
         // These values are used only for caching (hash calculation) purposes.
@@ -88,16 +88,26 @@
         keyBlendState.colorMaskBlue  = blendState.colorMaskBlue;
         keyBlendState.colorMaskAlpha = blendState.colorMaskAlpha;
 
-        ASSERT(keyBlendIndex < colorbuffers.size());
-        const gl::FramebufferAttachment *attachment = colorbuffers[keyBlendIndex];
+        const gl::InternalFormat &internalFormat = *attachment->getFormat().info;
 
-        if (attachment)  // when mrt_perf_workaround is disabled, nullptr attachments may exist
+        key.rtvMax = static_cast<uint16_t>(keyBlendIndex) + 1;
+        key.rtvMasks[keyBlendIndex] =
+            gl_d3d11::GetColorMask(internalFormat) &
+            gl_d3d11::ConvertColorMask(blendState.colorMaskRed, blendState.colorMaskGreen,
+                                       blendState.colorMaskBlue, blendState.colorMaskAlpha);
+
+        // Some D3D11 drivers produce unexpected results when blending is enabled for integer
+        // attachments. Per OpenGL ES spec, it must be ignored anyway. When blending is disabled,
+        // the state remains default to reduce the number of unique keys.
+        if (blendState.blend && !internalFormat.isInt())
         {
-            key.rtvMax = static_cast<uint16_t>(keyBlendIndex) + 1;
-            key.rtvMasks[keyBlendIndex] =
-                (gl_d3d11::GetColorMask(*attachment->getFormat().info)) &
-                gl_d3d11::ConvertColorMask(blendState.colorMaskRed, blendState.colorMaskGreen,
-                                           blendState.colorMaskBlue, blendState.colorMaskAlpha);
+            keyBlendState.blend              = true;
+            keyBlendState.sourceBlendRGB     = blendState.sourceBlendRGB;
+            keyBlendState.sourceBlendAlpha   = blendState.sourceBlendAlpha;
+            keyBlendState.destBlendRGB       = blendState.destBlendRGB;
+            keyBlendState.destBlendAlpha     = blendState.destBlendAlpha;
+            keyBlendState.blendEquationRGB   = blendState.blendEquationRGB;
+            keyBlendState.blendEquationAlpha = blendState.blendEquationAlpha;
         }
         keyBlendIndex++;
     }
diff --git a/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
index a7ce0e9..0d70418 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
@@ -3104,6 +3104,7 @@
 
 angle::Result Renderer11::fastCopyBufferToTexture(const gl::Context *context,
                                                   const gl::PixelUnpackState &unpack,
+                                                  gl::Buffer *unpackBuffer,
                                                   unsigned int offset,
                                                   RenderTargetD3D *destRenderTarget,
                                                   GLenum destinationFormat,
@@ -3111,8 +3112,9 @@
                                                   const gl::Box &destArea)
 {
     ASSERT(supportsFastCopyBufferToTexture(destinationFormat));
-    return mPixelTransfer->copyBufferToTexture(context, unpack, offset, destRenderTarget,
-                                               destinationFormat, sourcePixelsType, destArea);
+    return mPixelTransfer->copyBufferToTexture(context, unpack, unpackBuffer, offset,
+                                               destRenderTarget, destinationFormat,
+                                               sourcePixelsType, destArea);
 }
 
 ImageD3D *Renderer11::createImage()
diff --git a/src/libANGLE/renderer/d3d/d3d11/Renderer11.h b/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
index 4e3da9a..cb98bfa 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
+++ b/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
@@ -351,6 +351,7 @@
     bool supportsFastCopyBufferToTexture(GLenum internalFormat) const override;
     angle::Result fastCopyBufferToTexture(const gl::Context *context,
                                           const gl::PixelUnpackState &unpack,
+                                          gl::Buffer *unpackBuffer,
                                           unsigned int offset,
                                           RenderTargetD3D *destRenderTarget,
                                           GLenum destinationFormat,
diff --git a/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp b/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp
index e4d1b75..7eb7f18 100644
--- a/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp
@@ -193,8 +193,9 @@
     sortedAttributesOut->clear();
 
     const AttribIndexArray &locationToSemantic = programD3D.getAttribLocationToD3DSemantics();
+    const gl::ProgramExecutable &executable    = programD3D.getState().getProgramExecutable();
 
-    for (auto locationIndex : programD3D.getState().getActiveAttribLocationsMask())
+    for (auto locationIndex : executable.getActiveAttribLocationsMask())
     {
         int d3dSemantic = locationToSemantic[locationIndex];
         if (sortedAttributesOut->size() <= static_cast<size_t>(d3dSemantic))
@@ -1205,8 +1206,8 @@
                 invalidateProgramAtomicCounterBuffers();
                 invalidateProgramShaderStorageBuffers();
                 invalidateDriverUniforms();
-                const gl::Program *program = state.getProgram();
-                if (!program || !program->hasLinkedShaderStage(gl::ShaderType::Compute))
+                const gl::ProgramExecutable *executable = state.getProgramExecutable();
+                if (!executable || !executable->isCompute())
                 {
                     mInternalDirtyBits.set(DIRTY_BIT_PRIMITIVE_TOPOLOGY);
                     invalidateVertexBuffer();
@@ -2052,8 +2053,9 @@
     const gl::Context *context,
     const std::vector<gl::VertexAttribCurrentValueData> &currentValues)
 {
-    const auto &activeAttribsMask  = mProgramD3D->getState().getActiveAttribLocationsMask();
-    const auto &dirtyActiveAttribs = (activeAttribsMask & mDirtyCurrentValueAttribs);
+    const gl::ProgramExecutable &executable = mProgramD3D->getState().getProgramExecutable();
+    const auto &activeAttribsMask           = executable.getActiveAttribLocationsMask();
+    const auto &dirtyActiveAttribs          = (activeAttribsMask & mDirtyCurrentValueAttribs);
 
     if (!dirtyActiveAttribs.any())
     {
@@ -2729,7 +2731,7 @@
     ASSERT(!mProgramD3D->isSamplerMappingDirty());
 
     // TODO(jmadill): Use the Program's sampler bindings.
-    const gl::ActiveTexturePointerArray &completeTextures = glState.getActiveTexturesCache();
+    const gl::ActiveTexturesCache &completeTextures = glState.getActiveTexturesCache();
 
     const gl::RangeUI samplerRange = mProgramD3D->getUsedSamplerRange(shaderType);
     for (unsigned int samplerIndex = samplerRange.low(); samplerIndex < samplerRange.high();
diff --git a/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp b/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp
index 8fbb77a..5f834b5 100644
--- a/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp
@@ -135,13 +135,14 @@
     const gl::State &glState   = context->getState();
     const gl::Program *program = glState.getProgram();
     ASSERT(program);
+    const gl::ProgramExecutable &executable = program->getExecutable();
+
     mAppliedNumViewsToDivisor = (program->usesMultiview() ? program->getNumViews() : 1);
 
     if (mAttribsToTranslate.any())
     {
-        const gl::AttributesMask &activeLocations =
-            glState.getProgram()->getActiveAttribLocationsMask();
-        gl::AttributesMask activeDirtyAttribs = (mAttribsToTranslate & activeLocations);
+        const gl::AttributesMask &activeLocations = executable.getActiveAttribLocationsMask();
+        gl::AttributesMask activeDirtyAttribs     = (mAttribsToTranslate & activeLocations);
         if (activeDirtyAttribs.any())
         {
             ANGLE_TRY(updateDirtyAttribs(context, activeDirtyAttribs));
@@ -151,9 +152,8 @@
 
     if (mDynamicAttribsMask.any())
     {
-        const gl::AttributesMask &activeLocations =
-            glState.getProgram()->getActiveAttribLocationsMask();
-        gl::AttributesMask activeDynamicAttribs = (mDynamicAttribsMask & activeLocations);
+        const gl::AttributesMask &activeLocations = executable.getActiveAttribLocationsMask();
+        gl::AttributesMask activeDynamicAttribs   = (mDynamicAttribsMask & activeLocations);
 
         if (activeDynamicAttribs.any())
         {
@@ -235,7 +235,8 @@
 
 bool VertexArray11::hasActiveDynamicAttrib(const gl::Context *context)
 {
-    const auto &activeLocations = context->getState().getProgram()->getActiveAttribLocationsMask();
+    const auto &activeLocations =
+        context->getState().getProgramExecutable()->getActiveAttribLocationsMask();
     gl::AttributesMask activeDynamicAttribs = (mDynamicAttribsMask & activeLocations);
     return activeDynamicAttribs.any();
 }
diff --git a/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp b/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
index dc6726e..5ea6f95 100644
--- a/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
@@ -1569,6 +1569,7 @@
     // Explicitly disable GL_OES_compressed_ETC1_RGB8_texture because it's emulated and never
     // becomes core. WebGL doesn't want to expose it unless there is native support.
     extensions->compressedETC1RGB8TextureOES = false;
+    extensions->compressedETC1RGB8SubTexture = false;
 
     extensions->elementIndexUintOES = true;
     extensions->getProgramBinaryOES = true;
@@ -1633,16 +1634,18 @@
     extensions->copyTexture                         = true;
     extensions->copyCompressedTexture               = true;
     extensions->textureStorageMultisample2DArrayOES = true;
-    extensions->multiviewMultisample     = ((extensions->multiview || extensions->multiview2) &&
+    extensions->multiviewMultisample      = ((extensions->multiview || extensions->multiview2) &&
                                         extensions->textureStorageMultisample2DArrayOES);
-    extensions->copyTexture3d            = true;
-    extensions->textureBorderClampOES    = true;
-    extensions->textureMultisample       = true;
-    extensions->provokingVertex          = true;
-    extensions->blendFuncExtended        = true;
-    extensions->maxDualSourceDrawBuffers = 1;
-    extensions->texture3DOES             = true;
-    extensions->baseVertexBaseInstance   = true;
+    extensions->copyTexture3d             = true;
+    extensions->textureBorderClampOES     = true;
+    extensions->textureMultisample        = true;
+    extensions->provokingVertex           = true;
+    extensions->blendFuncExtended         = true;
+    extensions->maxDualSourceDrawBuffers  = 1;
+    extensions->texture3DOES              = true;
+    extensions->baseVertexBaseInstance    = true;
+    extensions->drawElementsBaseVertexOES = true;
+    extensions->drawElementsBaseVertexEXT = true;
     if (!strstr(description, "Adreno"))
     {
         extensions->multisampledRenderToTexture = true;
@@ -1653,6 +1656,11 @@
     // It treats it as a red-channel-only texture.
     extensions->depthTextureOES = false;
 
+    // readPixels on depth & stencil not working with D3D11 backend.
+    extensions->readDepthNV         = false;
+    extensions->readStencilNV       = false;
+    extensions->depthBufferFloat2NV = false;
+
     // D3D11 Feature Level 10_0+ uses SV_IsFrontFace in HLSL to emulate gl_FrontFacing.
     // D3D11 Feature Level 9_3 doesn't support SV_IsFrontFace, and has no equivalent, so can't
     // support gl_FrontFacing.
@@ -2457,9 +2465,9 @@
     ANGLE_FEATURE_CONDITION(features, selectViewInGeometryShader,
                             !deviceCaps.supportsVpRtIndexWriteFromVertexShader);
 
-    // Intel and AMD drivers have trouble clearing textures without causing corruption. NVidia,
-    // on the other hand, can handle.
-    ANGLE_FEATURE_CONDITION(features, allowClearForRobustResourceInit, isNvidia);
+    // NVidia drivers have no trouble clearing textures without showing corruption. AMD ones do.
+    // Intel drivers that have trouble have been blocklisted to the DX9 runtime by Chromium.
+    ANGLE_FEATURE_CONDITION(features, allowClearForRobustResourceInit, isNvidia || isIntel);
 
     // Don't translate uniform block to StructuredBuffer on Windows 7 and earlier. This is targeted
     // to work around a bug that fails to allocate ShaderResourceView for StructuredBuffer.
diff --git a/src/libANGLE/renderer/d3d/d3d11/texture_format_map.json b/src/libANGLE/renderer/d3d/d3d11/texture_format_map.json
index 6ac4939..fd610f1 100644
--- a/src/libANGLE/renderer/d3d/d3d11/texture_format_map.json
+++ b/src/libANGLE/renderer/d3d/d3d11/texture_format_map.json
@@ -102,5 +102,6 @@
   "GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT": "NONE",
   "GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT": "NONE",
   "GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT": "NONE",
-  "GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT": "NONE"
+  "GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT": "NONE",
+  "GL_SR8_EXT": "NONE"
 }
diff --git a/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp b/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp
index a3691f4..6e140a3 100644
--- a/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp
@@ -2541,6 +2541,20 @@
                                          nullptr);
             return info;
         }
+        case GL_SR8_EXT:
+        {
+            static constexpr Format info(GL_SR8_EXT,
+                                         angle::FormatID::NONE,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         DXGI_FORMAT_UNKNOWN,
+                                         GL_NONE,
+                                         nullptr);
+            return info;
+        }
         case GL_SRGB8:
         {
             static constexpr Format info(GL_SRGB8,
diff --git a/src/libANGLE/renderer/d3d/d3d9/Context9.cpp b/src/libANGLE/renderer/d3d/d3d9/Context9.cpp
index 8132be1..29d4091 100644
--- a/src/libANGLE/renderer/d3d/d3d9/Context9.cpp
+++ b/src/libANGLE/renderer/d3d/d3d9/Context9.cpp
@@ -131,11 +131,6 @@
     return nullptr;
 }
 
-std::vector<PathImpl *> Context9::createPaths(GLsizei)
-{
-    return std::vector<PathImpl *>();
-}
-
 MemoryObjectImpl *Context9::createMemoryObject()
 {
     UNREACHABLE();
diff --git a/src/libANGLE/renderer/d3d/d3d9/Context9.h b/src/libANGLE/renderer/d3d/d3d9/Context9.h
index f2a180c..f6f394f 100644
--- a/src/libANGLE/renderer/d3d/d3d9/Context9.h
+++ b/src/libANGLE/renderer/d3d/d3d9/Context9.h
@@ -61,9 +61,6 @@
     // Program Pipeline object creation
     ProgramPipelineImpl *createProgramPipeline(const gl::ProgramPipelineState &data) override;
 
-    // Path object creation
-    std::vector<PathImpl *> createPaths(GLsizei) override;
-
     // Memory object creation.
     MemoryObjectImpl *createMemoryObject() override;
 
diff --git a/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp b/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp
index 87fe744..7193694 100644
--- a/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp
+++ b/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp
@@ -61,7 +61,7 @@
                                       const ClearParameters &clearParams)
 {
     ANGLE_TRY(mRenderer->applyRenderTarget(context, mRenderTargetCache.getColors()[0],
-                                           mRenderTargetCache.getDepthStencil()));
+                                           mRenderTargetCache.getDepthStencil(true)));
 
     const gl::State &glState = context->getState();
     float nearZ              = glState.getNearPlane();
@@ -72,7 +72,7 @@
     mRenderer->setScissorRectangle(glState.getScissor(), glState.isScissorTestEnabled());
 
     mRenderer->clear(clearParams, mRenderTargetCache.getColors()[0],
-                     mRenderTargetCache.getDepthStencil());
+                     mRenderTargetCache.getDepthStencil(true));
     return angle::Result::Continue;
 }
 
@@ -385,11 +385,14 @@
     return angle::Result::Continue;
 }
 
-GLenum Framebuffer9::getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const
+const gl::InternalFormat &Framebuffer9::getImplementationColorReadFormat(
+    const gl::Context *context) const
 {
-    RenderTarget9 *renderTarget9         = GetAs<RenderTarget9>(renderTarget);
-    const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(renderTarget9->getD3DFormat());
-    return d3dFormatInfo.info().glInternalFormat;
+    GLenum sizedFormat = mState.getReadAttachment()->getFormat().info->sizedInternalFormat;
+    const d3d9::TextureFormat &textureFormat = d3d9::GetTextureFormatInfo(sizedFormat);
+    const d3d9::D3DFormat &d3dFormatInfo     = d3d9::GetD3DFormatInfo(textureFormat.renderFormat);
+    const angle::Format &angleFormat         = angle::Format::Get(d3dFormatInfo.formatID);
+    return gl::GetSizedInternalFormatInfo(angleFormat.fboImplementationInternalFormat);
 }
 
 angle::Result Framebuffer9::getSamplePosition(const gl::Context *context,
@@ -401,9 +404,10 @@
 }
 
 angle::Result Framebuffer9::syncState(const gl::Context *context,
+                                      GLenum binding,
                                       const gl::Framebuffer::DirtyBits &dirtyBits)
 {
-    ANGLE_TRY(FramebufferD3D::syncState(context, dirtyBits));
+    ANGLE_TRY(FramebufferD3D::syncState(context, binding, dirtyBits));
     ANGLE_TRY(mRenderTargetCache.update(context, mState, dirtyBits));
     return angle::Result::Continue;
 }
diff --git a/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h b/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h
index d9c4d7b..e68ffbc 100644
--- a/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h
+++ b/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h
@@ -39,6 +39,7 @@
                                     GLfloat *xy) const override;
 
     angle::Result syncState(const gl::Context *context,
+                            GLenum binding,
                             const gl::Framebuffer::DirtyBits &dirtyBits) override;
 
     const gl::AttachmentArray<RenderTarget9 *> &getCachedColorRenderTargets() const
@@ -48,9 +49,12 @@
 
     const RenderTarget9 *getCachedDepthStencilRenderTarget() const
     {
-        return mRenderTargetCache.getDepthStencil();
+        return mRenderTargetCache.getDepthStencil(true);
     }
 
+    const gl::InternalFormat &getImplementationColorReadFormat(
+        const gl::Context *context) const override;
+
   private:
     angle::Result clearImpl(const gl::Context *context,
                             const ClearParameters &clearParams) override;
@@ -73,8 +77,6 @@
                            GLenum filter,
                            const gl::Framebuffer *sourceFramebuffer) override;
 
-    GLenum getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const override;
-
     Renderer9 *const mRenderer;
 
     RenderTargetCache<RenderTarget9> mRenderTargetCache;
diff --git a/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp b/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
index 74f5126..d783db1 100644
--- a/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
+++ b/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
@@ -949,6 +949,7 @@
 
 angle::Result Renderer9::fastCopyBufferToTexture(const gl::Context *context,
                                                  const gl::PixelUnpackState &unpack,
+                                                 gl::Buffer *unpackBuffer,
                                                  unsigned int offset,
                                                  RenderTargetD3D *destRenderTarget,
                                                  GLenum destinationFormat,
@@ -3184,7 +3185,7 @@
     ASSERT(!programD3D->isSamplerMappingDirty());
 
     // TODO(jmadill): Use the Program's sampler bindings.
-    const gl::ActiveTexturePointerArray &activeTextures = glState.getActiveTexturesCache();
+    const gl::ActiveTexturesCache &activeTextures = glState.getActiveTexturesCache();
 
     const gl::RangeUI samplerRange = programD3D->getUsedSamplerRange(shaderType);
     for (unsigned int samplerIndex = samplerRange.low(); samplerIndex < samplerRange.high();
diff --git a/src/libANGLE/renderer/d3d/d3d9/Renderer9.h b/src/libANGLE/renderer/d3d/d3d9/Renderer9.h
index c6e82a7..5c8eee4 100644
--- a/src/libANGLE/renderer/d3d/d3d9/Renderer9.h
+++ b/src/libANGLE/renderer/d3d/d3d9/Renderer9.h
@@ -351,6 +351,7 @@
     bool supportsFastCopyBufferToTexture(GLenum internalFormat) const override;
     angle::Result fastCopyBufferToTexture(const gl::Context *context,
                                           const gl::PixelUnpackState &unpack,
+                                          gl::Buffer *unpackBuffer,
                                           unsigned int offset,
                                           RenderTargetD3D *destRenderTarget,
                                           GLenum destinationFormat,
diff --git a/src/libANGLE/renderer/gl/BlitGL.cpp b/src/libANGLE/renderer/gl/BlitGL.cpp
index c5bbe9e..a08fc10 100644
--- a/src/libANGLE/renderer/gl/BlitGL.cpp
+++ b/src/libANGLE/renderer/gl/BlitGL.cpp
@@ -276,10 +276,8 @@
     mStateManager->bindTexture(textureType, texture);
 
     // Allocate the texture memory
-    GLenum format = gl::GetUnsizedFormat(internalFormat);
-
-    GLenum readType = GL_NONE;
-    ANGLE_TRY(source->getImplementationColorReadType(context, &readType));
+    GLenum format   = gl::GetUnsizedFormat(internalFormat);
+    GLenum readType = source->getImplementationColorReadType(context);
 
     gl::PixelUnpackState unpack;
     mStateManager->setPixelUnpackState(unpack);
@@ -313,11 +311,8 @@
     const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(source);
     mStateManager->bindFramebuffer(GL_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
 
-    GLenum readFormat = GL_NONE;
-    ANGLE_TRY(source->getImplementationColorReadFormat(context, &readFormat));
-
-    GLenum readType = GL_NONE;
-    ANGLE_TRY(source->getImplementationColorReadType(context, &readType));
+    GLenum readFormat = source->getImplementationColorReadFormat(context);
+    GLenum readType   = source->getImplementationColorReadType(context);
 
     nativegl::CopyTexImageImageFormat copyTexImageFormat =
         nativegl::GetCopyTexImageImageFormat(mFunctions, mFeatures, readFormat, readType);
diff --git a/src/libANGLE/renderer/gl/ContextGL.cpp b/src/libANGLE/renderer/gl/ContextGL.cpp
index dd1c50c..869f2a1 100644
--- a/src/libANGLE/renderer/gl/ContextGL.cpp
+++ b/src/libANGLE/renderer/gl/ContextGL.cpp
@@ -17,7 +17,6 @@
 #include "libANGLE/renderer/gl/FramebufferGL.h"
 #include "libANGLE/renderer/gl/FunctionsGL.h"
 #include "libANGLE/renderer/gl/MemoryObjectGL.h"
-#include "libANGLE/renderer/gl/PathGL.h"
 #include "libANGLE/renderer/gl/ProgramGL.h"
 #include "libANGLE/renderer/gl/ProgramPipelineGL.h"
 #include "libANGLE/renderer/gl/QueryGL.h"
@@ -63,8 +62,7 @@
 
 ProgramImpl *ContextGL::createProgram(const gl::ProgramState &data)
 {
-    return new ProgramGL(data, getFunctions(), getFeaturesGL(), getStateManager(),
-                         getExtensions().pathRendering, mRenderer);
+    return new ProgramGL(data, getFunctions(), getFeaturesGL(), getStateManager(), mRenderer);
 }
 
 FramebufferImpl *ContextGL::createFramebuffer(const gl::FramebufferState &data)
@@ -157,26 +155,6 @@
     return new ProgramPipelineGL(data, getFunctions());
 }
 
-std::vector<PathImpl *> ContextGL::createPaths(GLsizei range)
-{
-    const FunctionsGL *funcs = getFunctions();
-
-    std::vector<PathImpl *> ret;
-    ret.reserve(range);
-
-    const GLuint first = funcs->genPathsNV(range);
-    if (first == 0)
-        return ret;
-
-    for (GLsizei i = 0; i < range; ++i)
-    {
-        const auto id = first + i;
-        ret.push_back(new PathGL(funcs, id));
-    }
-
-    return ret;
-}
-
 MemoryObjectImpl *ContextGL::createMemoryObject()
 {
     const FunctionsGL *functions = getFunctions();
@@ -220,19 +198,27 @@
 {
     if (context->getStateCache().hasAnyActiveClientAttrib())
     {
-        const gl::State &glState   = context->getState();
-        const gl::Program *program = glState.getProgram();
-        const gl::VertexArray *vao = glState.getVertexArray();
-        const VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(vao);
+        const gl::State &glState                = context->getState();
+        const gl::ProgramExecutable *executable = getState().getProgramExecutable();
+        const gl::VertexArray *vao              = glState.getVertexArray();
+        const VertexArrayGL *vaoGL              = GetImplAs<VertexArrayGL>(vao);
 
-        ANGLE_TRY(vaoGL->syncClientSideData(context, program->getActiveAttribLocationsMask(), first,
-                                            count, instanceCount));
+        ANGLE_TRY(vaoGL->syncClientSideData(context, executable->getActiveAttribLocationsMask(),
+                                            first, count, instanceCount));
 
 #if defined(ANGLE_STATE_VALIDATION_ENABLED)
         vaoGL->validateState();
 #endif  // ANGLE_STATE_VALIDATION_ENABLED
     }
 
+    const angle::FeaturesGL &features = getFeaturesGL();
+    if (features.setPrimitiveRestartFixedIndexForDrawArrays.enabled)
+    {
+        StateManagerGL *stateManager           = getStateManager();
+        constexpr GLuint primitiveRestartIndex = gl::GetPrimitiveRestartIndexFromType<GLuint>();
+        ANGLE_TRY(stateManager->setPrimitiveRestartIndex(context, primitiveRestartIndex));
+    }
+
     return angle::Result::Continue;
 }
 
@@ -243,17 +229,15 @@
                                                            GLsizei instanceCount,
                                                            const void **outIndices)
 {
-    const gl::State &glState = context->getState();
+    const gl::State &glState                = context->getState();
+    const gl::ProgramExecutable *executable = getState().getProgramExecutable();
+    const gl::VertexArray *vao              = glState.getVertexArray();
+    const gl::StateCache &stateCache        = context->getStateCache();
 
-    const gl::Program *program = glState.getProgram();
-
-    const gl::VertexArray *vao = glState.getVertexArray();
-
-    const gl::StateCache &stateCache = context->getStateCache();
     if (stateCache.hasAnyActiveClientAttrib() || vao->getElementArrayBuffer() == nullptr)
     {
         const VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(vao);
-        ANGLE_TRY(vaoGL->syncDrawElementsState(context, program->getActiveAttribLocationsMask(),
+        ANGLE_TRY(vaoGL->syncDrawElementsState(context, executable->getActiveAttribLocationsMask(),
                                                count, type, indices, instanceCount,
                                                glState.isPrimitiveRestartEnabled(), outIndices));
     }
@@ -268,7 +252,7 @@
         StateManagerGL *stateManager = getStateManager();
 
         GLuint primitiveRestartIndex = gl::GetPrimitiveRestartIndex(type);
-        stateManager->setPrimitiveRestartIndex(primitiveRestartIndex);
+        ANGLE_TRY(stateManager->setPrimitiveRestartIndex(context, primitiveRestartIndex));
     }
 
 #if defined(ANGLE_STATE_VALIDATION_ENABLED)
@@ -325,6 +309,7 @@
 gl::AttributesMask ContextGL::updateAttributesForBaseInstance(const gl::Program *program,
                                                               GLuint baseInstance)
 {
+    const gl::ProgramExecutable *executable = getState().getProgramExecutable();
     gl::AttributesMask attribToUpdateMask;
 
     if (baseInstance != 0)
@@ -336,7 +321,7 @@
         {
             const gl::VertexAttribute &attrib = attribs[attribIndex];
             const gl::VertexBinding &binding  = bindings[attrib.bindingIndex];
-            if (program->isAttribLocationActive(attribIndex) && binding.getDivisor() != 0)
+            if (executable->isAttribLocationActive(attribIndex) && binding.getDivisor() != 0)
             {
                 attribToUpdateMask.set(attribIndex);
                 const char *p             = static_cast<const char *>(attrib.pointer);
@@ -665,100 +650,6 @@
     return angle::Result::Continue;
 }
 
-void ContextGL::stencilFillPath(const gl::Path *path, GLenum fillMode, GLuint mask)
-{
-    mRenderer->stencilFillPath(mState, path, fillMode, mask);
-}
-
-void ContextGL::stencilStrokePath(const gl::Path *path, GLint reference, GLuint mask)
-{
-    mRenderer->stencilStrokePath(mState, path, reference, mask);
-}
-
-void ContextGL::coverFillPath(const gl::Path *path, GLenum coverMode)
-{
-    mRenderer->coverFillPath(mState, path, coverMode);
-}
-
-void ContextGL::coverStrokePath(const gl::Path *path, GLenum coverMode)
-{
-    mRenderer->coverStrokePath(mState, path, coverMode);
-}
-
-void ContextGL::stencilThenCoverFillPath(const gl::Path *path,
-                                         GLenum fillMode,
-                                         GLuint mask,
-                                         GLenum coverMode)
-{
-    mRenderer->stencilThenCoverFillPath(mState, path, fillMode, mask, coverMode);
-}
-
-void ContextGL::stencilThenCoverStrokePath(const gl::Path *path,
-                                           GLint reference,
-                                           GLuint mask,
-                                           GLenum coverMode)
-{
-    mRenderer->stencilThenCoverStrokePath(mState, path, reference, mask, coverMode);
-}
-
-void ContextGL::coverFillPathInstanced(const std::vector<gl::Path *> &paths,
-                                       GLenum coverMode,
-                                       GLenum transformType,
-                                       const GLfloat *transformValues)
-{
-    mRenderer->coverFillPathInstanced(mState, paths, coverMode, transformType, transformValues);
-}
-
-void ContextGL::coverStrokePathInstanced(const std::vector<gl::Path *> &paths,
-                                         GLenum coverMode,
-                                         GLenum transformType,
-                                         const GLfloat *transformValues)
-{
-    mRenderer->coverStrokePathInstanced(mState, paths, coverMode, transformType, transformValues);
-}
-
-void ContextGL::stencilFillPathInstanced(const std::vector<gl::Path *> &paths,
-                                         GLenum fillMode,
-                                         GLuint mask,
-                                         GLenum transformType,
-                                         const GLfloat *transformValues)
-{
-    mRenderer->stencilFillPathInstanced(mState, paths, fillMode, mask, transformType,
-                                        transformValues);
-}
-
-void ContextGL::stencilStrokePathInstanced(const std::vector<gl::Path *> &paths,
-                                           GLint reference,
-                                           GLuint mask,
-                                           GLenum transformType,
-                                           const GLfloat *transformValues)
-{
-    mRenderer->stencilStrokePathInstanced(mState, paths, reference, mask, transformType,
-                                          transformValues);
-}
-
-void ContextGL::stencilThenCoverFillPathInstanced(const std::vector<gl::Path *> &paths,
-                                                  GLenum coverMode,
-                                                  GLenum fillMode,
-                                                  GLuint mask,
-                                                  GLenum transformType,
-                                                  const GLfloat *transformValues)
-{
-    mRenderer->stencilThenCoverFillPathInstanced(mState, paths, coverMode, fillMode, mask,
-                                                 transformType, transformValues);
-}
-
-void ContextGL::stencilThenCoverStrokePathInstanced(const std::vector<gl::Path *> &paths,
-                                                    GLenum coverMode,
-                                                    GLint reference,
-                                                    GLuint mask,
-                                                    GLenum transformType,
-                                                    const GLfloat *transformValues)
-{
-    mRenderer->stencilThenCoverStrokePathInstanced(mState, paths, coverMode, reference, mask,
-                                                   transformType, transformValues);
-}
-
 gl::GraphicsResetStatus ContextGL::getResetStatus()
 {
     return mRenderer->getResetStatus();
@@ -811,8 +702,7 @@
                                    const gl::State::DirtyBits &dirtyBits,
                                    const gl::State::DirtyBits &bitMask)
 {
-    mRenderer->getStateManager()->syncState(context, dirtyBits, bitMask);
-    return angle::Result::Continue;
+    return mRenderer->getStateManager()->syncState(context, dirtyBits, bitMask);
 }
 
 GLint ContextGL::getGPUDisjoint()
diff --git a/src/libANGLE/renderer/gl/ContextGL.h b/src/libANGLE/renderer/gl/ContextGL.h
index 0e2f7a7..b14a4c1 100644
--- a/src/libANGLE/renderer/gl/ContextGL.h
+++ b/src/libANGLE/renderer/gl/ContextGL.h
@@ -76,9 +76,6 @@
     // Program Pipeline object creation
     ProgramPipelineImpl *createProgramPipeline(const gl::ProgramPipelineState &data) override;
 
-    // Path object creation
-    std::vector<PathImpl *> createPaths(GLsizei range) override;
-
     // Memory object creation.
     MemoryObjectImpl *createMemoryObject() override;
 
@@ -164,50 +161,6 @@
                                        gl::DrawElementsType type,
                                        const void *indirect) override;
 
-    // CHROMIUM_path_rendering implementation
-    void stencilFillPath(const gl::Path *path, GLenum fillMode, GLuint mask) override;
-    void stencilStrokePath(const gl::Path *path, GLint reference, GLuint mask) override;
-    void coverFillPath(const gl::Path *path, GLenum coverMode) override;
-    void coverStrokePath(const gl::Path *path, GLenum coverMode) override;
-    void stencilThenCoverFillPath(const gl::Path *path,
-                                  GLenum fillMode,
-                                  GLuint mask,
-                                  GLenum coverMode) override;
-    void stencilThenCoverStrokePath(const gl::Path *path,
-                                    GLint reference,
-                                    GLuint mask,
-                                    GLenum coverMode) override;
-    void coverFillPathInstanced(const std::vector<gl::Path *> &paths,
-                                GLenum coverMode,
-                                GLenum transformType,
-                                const GLfloat *transformValues) override;
-    void coverStrokePathInstanced(const std::vector<gl::Path *> &paths,
-                                  GLenum coverMode,
-                                  GLenum transformType,
-                                  const GLfloat *transformValues) override;
-    void stencilFillPathInstanced(const std::vector<gl::Path *> &paths,
-                                  GLenum fillMode,
-                                  GLuint mask,
-                                  GLenum transformType,
-                                  const GLfloat *transformValues) override;
-    void stencilStrokePathInstanced(const std::vector<gl::Path *> &paths,
-                                    GLint reference,
-                                    GLuint mask,
-                                    GLenum transformType,
-                                    const GLfloat *transformValues) override;
-    void stencilThenCoverFillPathInstanced(const std::vector<gl::Path *> &paths,
-                                           GLenum coverMode,
-                                           GLenum fillMode,
-                                           GLuint mask,
-                                           GLenum transformType,
-                                           const GLfloat *transformValues) override;
-    void stencilThenCoverStrokePathInstanced(const std::vector<gl::Path *> &paths,
-                                             GLenum coverMode,
-                                             GLint reference,
-                                             GLuint mask,
-                                             GLenum transformType,
-                                             const GLfloat *transformValues) override;
-
     // Device loss
     gl::GraphicsResetStatus getResetStatus() override;
 
diff --git a/src/libANGLE/renderer/gl/DispatchTableGL_autogen.cpp b/src/libANGLE/renderer/gl/DispatchTableGL_autogen.cpp
index ede360d..ef44054 100644
--- a/src/libANGLE/renderer/gl/DispatchTableGL_autogen.cpp
+++ b/src/libANGLE/renderer/gl/DispatchTableGL_autogen.cpp
@@ -2787,33 +2787,6 @@
         ASSIGN("glGetInternalformatSampleivNV", getInternalformatSampleivNV);
     }
 
-    if (extensions.count("GL_NV_path_rendering") != 0)
-    {
-        ASSIGN("glCoverFillPathInstancedNV", coverFillPathInstancedNV);
-        ASSIGN("glCoverFillPathNV", coverFillPathNV);
-        ASSIGN("glCoverStrokePathInstancedNV", coverStrokePathInstancedNV);
-        ASSIGN("glCoverStrokePathNV", coverStrokePathNV);
-        ASSIGN("glDeletePathsNV", deletePathsNV);
-        ASSIGN("glGenPathsNV", genPathsNV);
-        ASSIGN("glGetPathParameterfvNV", getPathParameterfvNV);
-        ASSIGN("glGetPathParameterivNV", getPathParameterivNV);
-        ASSIGN("glIsPathNV", isPathNV);
-        ASSIGN("glMatrixLoadfEXT", matrixLoadfEXT);
-        ASSIGN("glPathCommandsNV", pathCommandsNV);
-        ASSIGN("glPathParameterfNV", pathParameterfNV);
-        ASSIGN("glPathParameteriNV", pathParameteriNV);
-        ASSIGN("glPathStencilFuncNV", pathStencilFuncNV);
-        ASSIGN("glProgramPathFragmentInputGenNV", programPathFragmentInputGenNV);
-        ASSIGN("glStencilFillPathInstancedNV", stencilFillPathInstancedNV);
-        ASSIGN("glStencilFillPathNV", stencilFillPathNV);
-        ASSIGN("glStencilStrokePathInstancedNV", stencilStrokePathInstancedNV);
-        ASSIGN("glStencilStrokePathNV", stencilStrokePathNV);
-        ASSIGN("glStencilThenCoverFillPathInstancedNV", stencilThenCoverFillPathInstancedNV);
-        ASSIGN("glStencilThenCoverFillPathNV", stencilThenCoverFillPathNV);
-        ASSIGN("glStencilThenCoverStrokePathInstancedNV", stencilThenCoverStrokePathInstancedNV);
-        ASSIGN("glStencilThenCoverStrokePathNV", stencilThenCoverStrokePathNV);
-    }
-
     if (extensions.count("GL_OVR_multiview") != 0)
     {
         ASSIGN("glFramebufferTextureMultiviewOVR", framebufferTextureMultiviewOVR);
@@ -5579,33 +5552,6 @@
         getInternalformatSampleivNV = &glGetInternalformatSampleivNVNULL;
     }
 
-    if (extensions.count("GL_NV_path_rendering") != 0)
-    {
-        coverFillPathInstancedNV              = &glCoverFillPathInstancedNVNULL;
-        coverFillPathNV                       = &glCoverFillPathNVNULL;
-        coverStrokePathInstancedNV            = &glCoverStrokePathInstancedNVNULL;
-        coverStrokePathNV                     = &glCoverStrokePathNVNULL;
-        deletePathsNV                         = &glDeletePathsNVNULL;
-        genPathsNV                            = &glGenPathsNVNULL;
-        getPathParameterfvNV                  = &glGetPathParameterfvNVNULL;
-        getPathParameterivNV                  = &glGetPathParameterivNVNULL;
-        isPathNV                              = &glIsPathNVNULL;
-        matrixLoadfEXT                        = &glMatrixLoadfEXTNULL;
-        pathCommandsNV                        = &glPathCommandsNVNULL;
-        pathParameterfNV                      = &glPathParameterfNVNULL;
-        pathParameteriNV                      = &glPathParameteriNVNULL;
-        pathStencilFuncNV                     = &glPathStencilFuncNVNULL;
-        programPathFragmentInputGenNV         = &glProgramPathFragmentInputGenNVNULL;
-        stencilFillPathInstancedNV            = &glStencilFillPathInstancedNVNULL;
-        stencilFillPathNV                     = &glStencilFillPathNVNULL;
-        stencilStrokePathInstancedNV          = &glStencilStrokePathInstancedNVNULL;
-        stencilStrokePathNV                   = &glStencilStrokePathNVNULL;
-        stencilThenCoverFillPathInstancedNV   = &glStencilThenCoverFillPathInstancedNVNULL;
-        stencilThenCoverFillPathNV            = &glStencilThenCoverFillPathNVNULL;
-        stencilThenCoverStrokePathInstancedNV = &glStencilThenCoverStrokePathInstancedNVNULL;
-        stencilThenCoverStrokePathNV          = &glStencilThenCoverStrokePathNVNULL;
-    }
-
     if (extensions.count("GL_OVR_multiview") != 0)
     {
         framebufferTextureMultiviewOVR = &glFramebufferTextureMultiviewOVRNULL;
diff --git a/src/libANGLE/renderer/gl/DispatchTableGL_autogen.h b/src/libANGLE/renderer/gl/DispatchTableGL_autogen.h
index a18295c..4451e9c 100644
--- a/src/libANGLE/renderer/gl/DispatchTableGL_autogen.h
+++ b/src/libANGLE/renderer/gl/DispatchTableGL_autogen.h
@@ -795,31 +795,6 @@
 
     // GL_OVR_multiview2
     PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC framebufferTextureMultiviewOVR = nullptr;
-
-    // NV_path_rendering (originally written against 3.2 compatibility profile)
-    PFNGLCOVERFILLPATHINSTANCEDNVPROC coverFillPathInstancedNV = nullptr;
-    PFNGLCOVERFILLPATHNVPROC coverFillPathNV = nullptr;
-    PFNGLCOVERSTROKEPATHINSTANCEDNVPROC coverStrokePathInstancedNV = nullptr;
-    PFNGLCOVERSTROKEPATHNVPROC coverStrokePathNV = nullptr;
-    PFNGLDELETEPATHSNVPROC deletePathsNV = nullptr;
-    PFNGLGENPATHSNVPROC genPathsNV = nullptr;
-    PFNGLGETPATHPARAMETERFVNVPROC getPathParameterfvNV = nullptr;
-    PFNGLGETPATHPARAMETERIVNVPROC getPathParameterivNV = nullptr;
-    PFNGLISPATHNVPROC isPathNV = nullptr;
-    PFNGLMATRIXLOADFEXTPROC matrixLoadfEXT = nullptr;
-    PFNGLPATHCOMMANDSNVPROC pathCommandsNV = nullptr;
-    PFNGLPATHPARAMETERFNVPROC pathParameterfNV = nullptr;
-    PFNGLPATHPARAMETERINVPROC pathParameteriNV = nullptr;
-    PFNGLPATHSTENCILFUNCNVPROC pathStencilFuncNV = nullptr;
-    PFNGLPROGRAMPATHFRAGMENTINPUTGENNVPROC programPathFragmentInputGenNV = nullptr;
-    PFNGLSTENCILFILLPATHINSTANCEDNVPROC stencilFillPathInstancedNV = nullptr;
-    PFNGLSTENCILFILLPATHNVPROC stencilFillPathNV = nullptr;
-    PFNGLSTENCILSTROKEPATHINSTANCEDNVPROC stencilStrokePathInstancedNV = nullptr;
-    PFNGLSTENCILSTROKEPATHNVPROC stencilStrokePathNV = nullptr;
-    PFNGLSTENCILTHENCOVERFILLPATHINSTANCEDNVPROC stencilThenCoverFillPathInstancedNV = nullptr;
-    PFNGLSTENCILTHENCOVERFILLPATHNVPROC stencilThenCoverFillPathNV = nullptr;
-    PFNGLSTENCILTHENCOVERSTROKEPATHINSTANCEDNVPROC stencilThenCoverStrokePathInstancedNV = nullptr;
-    PFNGLSTENCILTHENCOVERSTROKEPATHNVPROC stencilThenCoverStrokePathNV = nullptr;
     // clang-format on
 
     DispatchTableGL();
diff --git a/src/libANGLE/renderer/gl/FramebufferGL.cpp b/src/libANGLE/renderer/gl/FramebufferGL.cpp
index 05abad8..1dc65d2 100644
--- a/src/libANGLE/renderer/gl/FramebufferGL.cpp
+++ b/src/libANGLE/renderer/gl/FramebufferGL.cpp
@@ -374,6 +374,12 @@
     return angle::Result::Continue;
 }
 
+bool IsValidUnsignedShortReadPixelsFormat(GLenum readFormat, const gl::Context *context)
+{
+    return (readFormat == GL_RED) || (readFormat == GL_RG) || (readFormat == GL_RGBA) ||
+           ((readFormat == GL_DEPTH_COMPONENT) && (context->getExtensions().readDepthNV));
+}
+
 }  // namespace
 
 FramebufferGL::FramebufferGL(const gl::FramebufferState &data,
@@ -601,20 +607,6 @@
     return angle::Result::Continue;
 }
 
-GLenum FramebufferGL::getImplementationColorReadFormat(const gl::Context *context) const
-{
-    const auto *readAttachment = mState.getReadAttachment();
-    const Format &format       = readAttachment->getFormat();
-    return format.info->getReadPixelsFormat(context->getExtensions());
-}
-
-GLenum FramebufferGL::getImplementationColorReadType(const gl::Context *context) const
-{
-    const auto *readAttachment = mState.getReadAttachment();
-    const Format &format       = readAttachment->getFormat();
-    return format.info->getReadPixelsType(context->getClientVersion());
-}
-
 angle::Result FramebufferGL::readPixels(const gl::Context *context,
                                         const gl::Rectangle &area,
                                         GLenum format,
@@ -627,7 +619,7 @@
     const angle::FeaturesGL &features = GetFeaturesGL(context);
 
     // Clip read area to framebuffer.
-    const auto *readAttachment = mState.getReadAttachment();
+    const auto *readAttachment = mState.getReadPixelsAttachment(format);
     const gl::Extents fbSize   = readAttachment->getSize();
     const gl::Rectangle fbRect(0, 0, fbSize.width, fbSize.height);
     gl::Rectangle clippedArea;
@@ -650,7 +642,7 @@
     if (features.readPixelsUsingImplementationColorReadFormatForNorm16.enabled &&
         readType == GL_UNSIGNED_SHORT)
     {
-        ANGLE_CHECK(contextGL, readFormat == GL_RED || readFormat == GL_RG || readFormat == GL_RGBA,
+        ANGLE_CHECK(contextGL, IsValidUnsignedShortReadPixelsFormat(readFormat, context),
                     "glReadPixels: GL_IMPLEMENTATION_COLOR_READ_FORMAT advertised by the driver is "
                     "not handled by RGBA16 readPixels workaround.",
                     GL_INVALID_OPERATION);
@@ -1193,6 +1185,7 @@
 }
 
 angle::Result FramebufferGL::syncState(const gl::Context *context,
+                                       GLenum binding,
                                        const gl::Framebuffer::DirtyBits &dirtyBits)
 {
     // Don't need to sync state for the default FBO.
diff --git a/src/libANGLE/renderer/gl/FramebufferGL.h b/src/libANGLE/renderer/gl/FramebufferGL.h
index 6226575..e361ce4 100644
--- a/src/libANGLE/renderer/gl/FramebufferGL.h
+++ b/src/libANGLE/renderer/gl/FramebufferGL.h
@@ -58,9 +58,6 @@
                                 GLfloat depth,
                                 GLint stencil) override;
 
-    GLenum getImplementationColorReadFormat(const gl::Context *context) const override;
-    GLenum getImplementationColorReadType(const gl::Context *context) const override;
-
     angle::Result readPixels(const gl::Context *context,
                              const gl::Rectangle &area,
                              GLenum format,
@@ -83,6 +80,7 @@
     bool checkStatus(const gl::Context *context) const override;
 
     angle::Result syncState(const gl::Context *context,
+                            GLenum binding,
                             const gl::Framebuffer::DirtyBits &dirtyBits) override;
 
     GLuint getFramebufferID() const;
diff --git a/src/libANGLE/renderer/gl/MemoryObjectGL.cpp b/src/libANGLE/renderer/gl/MemoryObjectGL.cpp
index 7c2d0d9..7807860 100644
--- a/src/libANGLE/renderer/gl/MemoryObjectGL.cpp
+++ b/src/libANGLE/renderer/gl/MemoryObjectGL.cpp
@@ -6,6 +6,7 @@
 #include "libANGLE/renderer/gl/MemoryObjectGL.h"
 
 #include "libANGLE/Context.h"
+#include "libANGLE/queryconversions.h"
 #include "libANGLE/renderer/gl/ContextGL.h"
 #include "libANGLE/renderer/gl/FunctionsGL.h"
 #include "libANGLE/renderer/gl/renderergl_utils.h"
@@ -29,13 +30,24 @@
     mMemoryObject = 0;
 }
 
+angle::Result MemoryObjectGL::setDedicatedMemory(const gl::Context *context, bool dedicatedMemory)
+{
+    const FunctionsGL *functions = GetFunctionsGL(context);
+
+    GLint params = gl::ConvertToGLBoolean(dedicatedMemory);
+    ANGLE_GL_TRY(context, functions->memoryObjectParameterivEXT(
+                              mMemoryObject, GL_DEDICATED_MEMORY_OBJECT_EXT, &params));
+    return angle::Result::Continue;
+}
+
 angle::Result MemoryObjectGL::importFd(gl::Context *context,
                                        GLuint64 size,
                                        gl::HandleType handleType,
                                        GLint fd)
 {
     const FunctionsGL *functions = GetFunctionsGL(context);
-    functions->importMemoryFdEXT(mMemoryObject, size, ToGLenum(handleType), fd);
+    ANGLE_GL_TRY(context,
+                 functions->importMemoryFdEXT(mMemoryObject, size, ToGLenum(handleType), fd));
     return angle::Result::Continue;
 }
 
diff --git a/src/libANGLE/renderer/gl/MemoryObjectGL.h b/src/libANGLE/renderer/gl/MemoryObjectGL.h
index f3408a8..5c36478 100644
--- a/src/libANGLE/renderer/gl/MemoryObjectGL.h
+++ b/src/libANGLE/renderer/gl/MemoryObjectGL.h
@@ -21,6 +21,8 @@
 
     void onDestroy(const gl::Context *context) override;
 
+    angle::Result setDedicatedMemory(const gl::Context *context, bool dedicatedMemory) override;
+
     angle::Result importFd(gl::Context *context,
                            GLuint64 size,
                            gl::HandleType handleType,
diff --git a/src/libANGLE/renderer/gl/OWNERS b/src/libANGLE/renderer/gl/OWNERS
new file mode 100644
index 0000000..f220a7a
--- /dev/null
+++ b/src/libANGLE/renderer/gl/OWNERS
@@ -0,0 +1,2 @@
+geofflang@chromium.org
+jonahr@google.com
diff --git a/src/libANGLE/renderer/gl/PathGL.cpp b/src/libANGLE/renderer/gl/PathGL.cpp
deleted file mode 100644
index 7203437..0000000
--- a/src/libANGLE/renderer/gl/PathGL.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-//
-// Copyright 2016 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// PathGL.cpp: Implementation for PathGL class.
-
-#include "libANGLE/renderer/gl/PathGL.h"
-#include "libANGLE/renderer/gl/FunctionsGL.h"
-
-namespace rx
-{
-PathGL::PathGL(const FunctionsGL *functions, GLuint path) : mFunctions(functions), mPathID(path) {}
-
-PathGL::~PathGL() {}
-
-angle::Result PathGL::setCommands(GLsizei numCommands,
-                                  const GLubyte *commands,
-                                  GLsizei numCoords,
-                                  GLenum coordType,
-                                  const void *coords)
-{
-    mFunctions->pathCommandsNV(mPathID, numCommands, commands, numCoords, coordType, coords);
-    return angle::Result::Continue;
-}
-
-void PathGL::setPathParameter(GLenum pname, GLfloat value)
-{
-    mFunctions->pathParameterfNV(mPathID, pname, value);
-}
-}  // namespace rx
diff --git a/src/libANGLE/renderer/gl/PathGL.h b/src/libANGLE/renderer/gl/PathGL.h
deleted file mode 100644
index fe2fea1..0000000
--- a/src/libANGLE/renderer/gl/PathGL.h
+++ /dev/null
@@ -1,44 +0,0 @@
-//
-// Copyright 2016 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// PathGL.h: Class definition for CHROMIUM_path_rendering path object for the
-// GL backend.
-
-#ifndef LIBANGLE_RENDERER_GL_PATHIMPL_H_
-#define LIBANGLE_RENDERER_GL_PATHIMPL_H_
-
-#include "libANGLE/renderer/PathImpl.h"
-
-namespace rx
-{
-
-class FunctionsGL;
-
-class PathGL : public PathImpl
-{
-  public:
-    PathGL(const FunctionsGL *functions, GLuint path);
-    ~PathGL() override;
-
-    angle::Result setCommands(GLsizei numCommands,
-                              const GLubyte *commands,
-                              GLsizei numCoords,
-                              GLenum coordType,
-                              const void *coords) override;
-
-    void setPathParameter(GLenum pname, GLfloat value) override;
-
-    GLuint getPathID() const { return mPathID; }
-
-  private:
-    const FunctionsGL *mFunctions;
-
-    GLuint mPathID;
-};
-
-}  // namespace rx
-
-#endif  // LIBANGLE_RENDERER_GL_PATHIMPL_H_
diff --git a/src/libANGLE/renderer/gl/ProgramGL.cpp b/src/libANGLE/renderer/gl/ProgramGL.cpp
index 2677944..5e8ccaf 100644
--- a/src/libANGLE/renderer/gl/ProgramGL.cpp
+++ b/src/libANGLE/renderer/gl/ProgramGL.cpp
@@ -33,13 +33,11 @@
                      const FunctionsGL *functions,
                      const angle::FeaturesGL &features,
                      StateManagerGL *stateManager,
-                     bool enablePathRendering,
                      const std::shared_ptr<RendererGL> &renderer)
     : ProgramImpl(data),
       mFunctions(functions),
       mFeatures(features),
       mStateManager(stateManager),
-      mEnablePathRendering(enablePathRendering),
       mMultiviewBaseViewLayerIndexUniformLocation(-1),
       mProgramID(0),
       mRenderer(renderer),
@@ -229,9 +227,10 @@
         std::vector<std::string> transformFeedbackVaryingMappedNames;
         for (const auto &tfVarying : mState.getTransformFeedbackVaryingNames())
         {
-            gl::ShaderType tfShaderType = mState.hasLinkedShaderStage(gl::ShaderType::Geometry)
-                                              ? gl::ShaderType::Geometry
-                                              : gl::ShaderType::Vertex;
+            gl::ShaderType tfShaderType =
+                mState.getProgramExecutable().hasLinkedShaderStage(gl::ShaderType::Geometry)
+                    ? gl::ShaderType::Geometry
+                    : gl::ShaderType::Vertex;
             std::string tfVaryingMappedName =
                 mState.getAttachedShader(tfShaderType)
                     ->getTransformFeedbackVaryingMappedName(tfVarying);
@@ -940,31 +939,11 @@
     }
 }
 
-void ProgramGL::setPathFragmentInputGen(const std::string &inputName,
-                                        GLenum genMode,
-                                        GLint components,
-                                        const GLfloat *coeffs)
-{
-    ASSERT(mEnablePathRendering);
-
-    for (const auto &input : mPathRenderingFragmentInputs)
-    {
-        if (input.mappedName == inputName)
-        {
-            mFunctions->programPathFragmentInputGenNV(mProgramID, input.location, genMode,
-                                                      components, coeffs);
-            ASSERT(mFunctions->getError() == GL_NO_ERROR);
-            return;
-        }
-    }
-}
-
 void ProgramGL::preLink()
 {
     // Reset the program state
     mUniformRealLocationMap.clear();
     mUniformBlockRealLocationMap.clear();
-    mPathRenderingFragmentInputs.clear();
 
     mMultiviewBaseViewLayerIndexUniformLocation = -1;
 }
@@ -1045,71 +1024,6 @@
             mFunctions->getUniformLocation(mProgramID, "multiviewBaseViewLayerIndex");
         ASSERT(mMultiviewBaseViewLayerIndexUniformLocation != -1);
     }
-
-    // Discover CHROMIUM_path_rendering fragment inputs if enabled.
-    if (!mEnablePathRendering)
-        return;
-
-    GLint numFragmentInputs = 0;
-    mFunctions->getProgramInterfaceiv(mProgramID, GL_FRAGMENT_INPUT_NV, GL_ACTIVE_RESOURCES,
-                                      &numFragmentInputs);
-    if (numFragmentInputs <= 0)
-        return;
-
-    GLint maxNameLength = 0;
-    mFunctions->getProgramInterfaceiv(mProgramID, GL_FRAGMENT_INPUT_NV, GL_MAX_NAME_LENGTH,
-                                      &maxNameLength);
-    ASSERT(maxNameLength);
-
-    for (GLint i = 0; i < numFragmentInputs; ++i)
-    {
-        std::string mappedName;
-        mappedName.resize(maxNameLength);
-
-        GLsizei nameLen = 0;
-        mFunctions->getProgramResourceName(mProgramID, GL_FRAGMENT_INPUT_NV, i, maxNameLength,
-                                           &nameLen, &mappedName[0]);
-        mappedName.resize(nameLen);
-
-        // Ignore built-ins
-        if (angle::BeginsWith(mappedName, "gl_"))
-            continue;
-
-        const GLenum kQueryProperties[] = {GL_LOCATION, GL_ARRAY_SIZE};
-        GLint queryResults[ArraySize(kQueryProperties)];
-        GLsizei queryLength = 0;
-
-        mFunctions->getProgramResourceiv(
-            mProgramID, GL_FRAGMENT_INPUT_NV, i, static_cast<GLsizei>(ArraySize(kQueryProperties)),
-            kQueryProperties, static_cast<GLsizei>(ArraySize(queryResults)), &queryLength,
-            queryResults);
-
-        ASSERT(queryLength == static_cast<GLsizei>(ArraySize(kQueryProperties)));
-
-        PathRenderingFragmentInput baseElementInput;
-        baseElementInput.mappedName = mappedName;
-        baseElementInput.location   = queryResults[0];
-        mPathRenderingFragmentInputs.push_back(std::move(baseElementInput));
-
-        // If the input is an array it's denoted by [0] suffix on the variable
-        // name. We'll then create an entry per each array index where index > 0
-        if (angle::EndsWith(mappedName, "[0]"))
-        {
-            // drop the suffix
-            mappedName.resize(mappedName.size() - 3);
-
-            const auto arraySize    = queryResults[1];
-            const auto baseLocation = queryResults[0];
-
-            for (GLint arrayIndex = 1; arrayIndex < arraySize; ++arrayIndex)
-            {
-                PathRenderingFragmentInput arrayElementInput;
-                arrayElementInput.mappedName = mappedName + "[" + ToString(arrayIndex) + "]";
-                arrayElementInput.location   = baseLocation + arrayIndex;
-                mPathRenderingFragmentInputs.push_back(std::move(arrayElementInput));
-            }
-        }
-    }
 }
 
 void ProgramGL::enableSideBySideRenderingPath() const
diff --git a/src/libANGLE/renderer/gl/ProgramGL.h b/src/libANGLE/renderer/gl/ProgramGL.h
index e4a0009..30e7699 100644
--- a/src/libANGLE/renderer/gl/ProgramGL.h
+++ b/src/libANGLE/renderer/gl/ProgramGL.h
@@ -33,7 +33,6 @@
               const FunctionsGL *functions,
               const angle::FeaturesGL &features,
               StateManagerGL *stateManager,
-              bool enablePathRendering,
               const std::shared_ptr<RendererGL> &renderer);
     ~ProgramGL() override;
 
@@ -102,11 +101,6 @@
     void getUniformiv(const gl::Context *context, GLint location, GLint *params) const override;
     void getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const override;
 
-    void setPathFragmentInputGen(const std::string &inputName,
-                                 GLenum genMode,
-                                 GLint components,
-                                 const GLfloat *coeffs) override;
-
     void markUnusedUniformLocations(std::vector<gl::VariableLocation> *uniformLocations,
                                     std::vector<gl::SamplerBinding> *samplerBindings,
                                     std::vector<gl::ImageBinding> *imageBindings) override;
@@ -157,14 +151,6 @@
     std::vector<GLint> mUniformRealLocationMap;
     std::vector<GLuint> mUniformBlockRealLocationMap;
 
-    struct PathRenderingFragmentInput
-    {
-        std::string mappedName;
-        GLint location;
-    };
-    std::vector<PathRenderingFragmentInput> mPathRenderingFragmentInputs;
-
-    bool mEnablePathRendering;
     GLint mMultiviewBaseViewLayerIndexUniformLocation;
 
     GLuint mProgramID;
diff --git a/src/libANGLE/renderer/gl/RendererGL.cpp b/src/libANGLE/renderer/gl/RendererGL.cpp
index e9e5ea6..09789b5 100644
--- a/src/libANGLE/renderer/gl/RendererGL.cpp
+++ b/src/libANGLE/renderer/gl/RendererGL.cpp
@@ -14,7 +14,6 @@
 #include "libANGLE/AttributeMap.h"
 #include "libANGLE/Context.h"
 #include "libANGLE/Display.h"
-#include "libANGLE/Path.h"
 #include "libANGLE/State.h"
 #include "libANGLE/Surface.h"
 #include "libANGLE/renderer/gl/BlitGL.h"
@@ -26,7 +25,6 @@
 #include "libANGLE/renderer/gl/FenceNVGL.h"
 #include "libANGLE/renderer/gl/FramebufferGL.h"
 #include "libANGLE/renderer/gl/FunctionsGL.h"
-#include "libANGLE/renderer/gl/PathGL.h"
 #include "libANGLE/renderer/gl/ProgramGL.h"
 #include "libANGLE/renderer/gl/QueryGL.h"
 #include "libANGLE/renderer/gl/RenderbufferGL.h"
@@ -44,19 +42,6 @@
 namespace
 {
 
-std::vector<GLuint> GatherPaths(const std::vector<gl::Path *> &paths)
-{
-    std::vector<GLuint> ret;
-    ret.reserve(paths.size());
-
-    for (const auto *p : paths)
-    {
-        const auto *pathObj = rx::GetImplAs<rx::PathGL>(p);
-        ret.push_back(pathObj->getPathID());
-    }
-    return ret;
-}
-
 void SetMaxShaderCompilerThreads(const rx::FunctionsGL *functions, GLuint count)
 {
     if (functions->maxShaderCompilerThreadsKHR != nullptr)
@@ -236,165 +221,6 @@
     return angle::Result::Continue;
 }
 
-void RendererGL::stencilFillPath(const gl::State &state,
-                                 const gl::Path *path,
-                                 GLenum fillMode,
-                                 GLuint mask)
-{
-    const auto *pathObj = GetImplAs<PathGL>(path);
-
-    mFunctions->stencilFillPathNV(pathObj->getPathID(), fillMode, mask);
-
-    ASSERT(mFunctions->getError() == GL_NO_ERROR);
-}
-
-void RendererGL::stencilStrokePath(const gl::State &state,
-                                   const gl::Path *path,
-                                   GLint reference,
-                                   GLuint mask)
-{
-    const auto *pathObj = GetImplAs<PathGL>(path);
-
-    mFunctions->stencilStrokePathNV(pathObj->getPathID(), reference, mask);
-
-    ASSERT(mFunctions->getError() == GL_NO_ERROR);
-}
-
-void RendererGL::coverFillPath(const gl::State &state, const gl::Path *path, GLenum coverMode)
-{
-
-    const auto *pathObj = GetImplAs<PathGL>(path);
-    mFunctions->coverFillPathNV(pathObj->getPathID(), coverMode);
-
-    ASSERT(mFunctions->getError() == GL_NO_ERROR);
-}
-
-void RendererGL::coverStrokePath(const gl::State &state, const gl::Path *path, GLenum coverMode)
-{
-    const auto *pathObj = GetImplAs<PathGL>(path);
-    mFunctions->coverStrokePathNV(pathObj->getPathID(), coverMode);
-
-    ASSERT(mFunctions->getError() == GL_NO_ERROR);
-}
-
-void RendererGL::stencilThenCoverFillPath(const gl::State &state,
-                                          const gl::Path *path,
-                                          GLenum fillMode,
-                                          GLuint mask,
-                                          GLenum coverMode)
-{
-
-    const auto *pathObj = GetImplAs<PathGL>(path);
-    mFunctions->stencilThenCoverFillPathNV(pathObj->getPathID(), fillMode, mask, coverMode);
-
-    ASSERT(mFunctions->getError() == GL_NO_ERROR);
-}
-
-void RendererGL::stencilThenCoverStrokePath(const gl::State &state,
-                                            const gl::Path *path,
-                                            GLint reference,
-                                            GLuint mask,
-                                            GLenum coverMode)
-{
-
-    const auto *pathObj = GetImplAs<PathGL>(path);
-    mFunctions->stencilThenCoverStrokePathNV(pathObj->getPathID(), reference, mask, coverMode);
-
-    ASSERT(mFunctions->getError() == GL_NO_ERROR);
-}
-
-void RendererGL::coverFillPathInstanced(const gl::State &state,
-                                        const std::vector<gl::Path *> &paths,
-                                        GLenum coverMode,
-                                        GLenum transformType,
-                                        const GLfloat *transformValues)
-{
-    const auto &pathObjs = GatherPaths(paths);
-
-    mFunctions->coverFillPathInstancedNV(static_cast<GLsizei>(pathObjs.size()), GL_UNSIGNED_INT,
-                                         &pathObjs[0], 0, coverMode, transformType,
-                                         transformValues);
-
-    ASSERT(mFunctions->getError() == GL_NO_ERROR);
-}
-void RendererGL::coverStrokePathInstanced(const gl::State &state,
-                                          const std::vector<gl::Path *> &paths,
-                                          GLenum coverMode,
-                                          GLenum transformType,
-                                          const GLfloat *transformValues)
-{
-    const auto &pathObjs = GatherPaths(paths);
-
-    mFunctions->coverStrokePathInstancedNV(static_cast<GLsizei>(pathObjs.size()), GL_UNSIGNED_INT,
-                                           &pathObjs[0], 0, coverMode, transformType,
-                                           transformValues);
-
-    ASSERT(mFunctions->getError() == GL_NO_ERROR);
-}
-void RendererGL::stencilFillPathInstanced(const gl::State &state,
-                                          const std::vector<gl::Path *> &paths,
-                                          GLenum fillMode,
-                                          GLuint mask,
-                                          GLenum transformType,
-                                          const GLfloat *transformValues)
-{
-    const auto &pathObjs = GatherPaths(paths);
-
-    mFunctions->stencilFillPathInstancedNV(static_cast<GLsizei>(pathObjs.size()), GL_UNSIGNED_INT,
-                                           &pathObjs[0], 0, fillMode, mask, transformType,
-                                           transformValues);
-
-    ASSERT(mFunctions->getError() == GL_NO_ERROR);
-}
-void RendererGL::stencilStrokePathInstanced(const gl::State &state,
-                                            const std::vector<gl::Path *> &paths,
-                                            GLint reference,
-                                            GLuint mask,
-                                            GLenum transformType,
-                                            const GLfloat *transformValues)
-{
-    const auto &pathObjs = GatherPaths(paths);
-
-    mFunctions->stencilStrokePathInstancedNV(static_cast<GLsizei>(pathObjs.size()), GL_UNSIGNED_INT,
-                                             &pathObjs[0], 0, reference, mask, transformType,
-                                             transformValues);
-
-    ASSERT(mFunctions->getError() == GL_NO_ERROR);
-}
-
-void RendererGL::stencilThenCoverFillPathInstanced(const gl::State &state,
-                                                   const std::vector<gl::Path *> &paths,
-                                                   GLenum coverMode,
-                                                   GLenum fillMode,
-                                                   GLuint mask,
-                                                   GLenum transformType,
-                                                   const GLfloat *transformValues)
-{
-    const auto &pathObjs = GatherPaths(paths);
-
-    mFunctions->stencilThenCoverFillPathInstancedNV(
-        static_cast<GLsizei>(pathObjs.size()), GL_UNSIGNED_INT, &pathObjs[0], 0, fillMode, mask,
-        coverMode, transformType, transformValues);
-
-    ASSERT(mFunctions->getError() == GL_NO_ERROR);
-}
-void RendererGL::stencilThenCoverStrokePathInstanced(const gl::State &state,
-                                                     const std::vector<gl::Path *> &paths,
-                                                     GLenum coverMode,
-                                                     GLint reference,
-                                                     GLuint mask,
-                                                     GLenum transformType,
-                                                     const GLfloat *transformValues)
-{
-    const auto &pathObjs = GatherPaths(paths);
-
-    mFunctions->stencilThenCoverStrokePathInstancedNV(
-        static_cast<GLsizei>(pathObjs.size()), GL_UNSIGNED_INT, &pathObjs[0], 0, reference, mask,
-        coverMode, transformType, transformValues);
-
-    ASSERT(mFunctions->getError() == GL_NO_ERROR);
-}
-
 gl::GraphicsResetStatus RendererGL::getResetStatus()
 {
     return gl::FromGLenum<gl::GraphicsResetStatus>(mFunctions->getGraphicsResetStatus());
diff --git a/src/libANGLE/renderer/gl/RendererGL.h b/src/libANGLE/renderer/gl/RendererGL.h
index 98d5942..1c36c82 100644
--- a/src/libANGLE/renderer/gl/RendererGL.h
+++ b/src/libANGLE/renderer/gl/RendererGL.h
@@ -86,65 +86,6 @@
     angle::Result flush();
     angle::Result finish();
 
-    // CHROMIUM_path_rendering implementation
-    void stencilFillPath(const gl::State &state,
-                         const gl::Path *path,
-                         GLenum fillMode,
-                         GLuint mask);
-    void stencilStrokePath(const gl::State &state,
-                           const gl::Path *path,
-                           GLint reference,
-                           GLuint mask);
-    void coverFillPath(const gl::State &state, const gl::Path *path, GLenum coverMode);
-    void coverStrokePath(const gl::State &state, const gl::Path *path, GLenum coverMode);
-    void stencilThenCoverFillPath(const gl::State &state,
-                                  const gl::Path *path,
-                                  GLenum fillMode,
-                                  GLuint mask,
-                                  GLenum coverMode);
-    void stencilThenCoverStrokePath(const gl::State &state,
-                                    const gl::Path *path,
-                                    GLint reference,
-                                    GLuint mask,
-                                    GLenum coverMode);
-    void coverFillPathInstanced(const gl::State &state,
-                                const std::vector<gl::Path *> &paths,
-                                GLenum coverMode,
-                                GLenum transformType,
-                                const GLfloat *transformValues);
-    void coverStrokePathInstanced(const gl::State &state,
-                                  const std::vector<gl::Path *> &paths,
-                                  GLenum coverMode,
-                                  GLenum transformType,
-                                  const GLfloat *transformValues);
-    void stencilFillPathInstanced(const gl::State &state,
-                                  const std::vector<gl::Path *> &paths,
-                                  GLenum fillMode,
-                                  GLuint mask,
-                                  GLenum transformType,
-                                  const GLfloat *transformValues);
-    void stencilStrokePathInstanced(const gl::State &state,
-                                    const std::vector<gl::Path *> &paths,
-                                    GLint reference,
-                                    GLuint mask,
-                                    GLenum transformType,
-                                    const GLfloat *transformValues);
-
-    void stencilThenCoverFillPathInstanced(const gl::State &state,
-                                           const std::vector<gl::Path *> &paths,
-                                           GLenum coverMode,
-                                           GLenum fillMode,
-                                           GLuint mask,
-                                           GLenum transformType,
-                                           const GLfloat *transformValues);
-    void stencilThenCoverStrokePathInstanced(const gl::State &state,
-                                             const std::vector<gl::Path *> &paths,
-                                             GLenum coverMode,
-                                             GLint reference,
-                                             GLuint mask,
-                                             GLenum transformType,
-                                             const GLfloat *transformValues);
-
     gl::GraphicsResetStatus getResetStatus();
 
     // EXT_debug_marker
diff --git a/src/libANGLE/renderer/gl/StateManagerGL.cpp b/src/libANGLE/renderer/gl/StateManagerGL.cpp
index 772c24a..b28bd19 100644
--- a/src/libANGLE/renderer/gl/StateManagerGL.cpp
+++ b/src/libANGLE/renderer/gl/StateManagerGL.cpp
@@ -148,9 +148,6 @@
       mMultisamplingEnabled(true),
       mSampleAlphaToOneEnabled(false),
       mCoverageModulation(GL_NONE),
-      mPathStencilFunc(GL_ALWAYS),
-      mPathStencilRef(0),
-      mPathStencilMask(std::numeric_limits<GLuint>::max()),
       mIsMultiviewEnabled(extensions.multiview || extensions.multiview2),
       mProvokingVertex(GL_LAST_VERTEX_CONVENTION),
       mLocalDirtyBits()
@@ -183,8 +180,13 @@
         }
     }
 
-    angle::Matrix<GLfloat>::setToIdentity(mPathMatrixProj);
-    angle::Matrix<GLfloat>::setToIdentity(mPathMatrixMV);
+    if (features.emulatePrimitiveRestartFixedIndex.enabled)
+    {
+        // There is no consistent default value for primitive restart index. Set it to UINT -1.
+        constexpr GLuint primitiveRestartIndex = gl::GetPrimitiveRestartIndexFromType<GLuint>();
+        mFunctions->primitiveRestartIndex(primitiveRestartIndex);
+        mPrimitiveRestartIndex = primitiveRestartIndex;
+    }
 }
 
 StateManagerGL::~StateManagerGL() {}
@@ -820,16 +822,16 @@
 
 void StateManagerGL::updateProgramTextureBindings(const gl::Context *context)
 {
-    const gl::State &glState   = context->getState();
-    const gl::Program *program = glState.getProgram();
+    const gl::State &glState                = context->getState();
+    const gl::ProgramExecutable *executable = glState.getProgramExecutable();
 
     // It is possible there is no active program during a path operation.
-    if (!program)
+    if (!executable)
         return;
 
-    const gl::ActiveTexturePointerArray &textures  = glState.getActiveTexturesCache();
-    const gl::ActiveTextureMask &activeTextures    = program->getActiveSamplersMask();
-    const gl::ActiveTextureTypeArray &textureTypes = program->getActiveSamplerTypes();
+    const gl::ActiveTexturesCache &textures        = glState.getActiveTexturesCache();
+    const gl::ActiveTextureMask &activeTextures    = executable->getActiveSamplersMask();
+    const gl::ActiveTextureTypeArray &textureTypes = executable->getActiveSamplerTypes();
 
     for (size_t textureUnitIndex : activeTextures)
     {
@@ -859,10 +861,6 @@
     const gl::State &glState   = context->getState();
     const gl::Program *program = glState.getProgram();
 
-    // It is possible there is no active program during a path operation.
-    if (!program)
-        return;
-
     for (size_t blockIndex = 0; blockIndex < program->getActiveShaderStorageBlockCount();
          blockIndex++)
     {
@@ -892,10 +890,6 @@
     const gl::State &glState   = context->getState();
     const gl::Program *program = glState.getProgram();
 
-    // It is possible there is no active program during a path operation.
-    if (!program)
-        return;
-
     for (size_t uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount();
          uniformBlockIndex++)
     {
@@ -924,10 +918,6 @@
     const gl::State &glState   = context->getState();
     const gl::Program *program = glState.getProgram();
 
-    // It is possible there is no active program during a path operation.
-    if (!program)
-        return;
-
     for (const auto &atomicCounterBuffer : program->getState().getAtomicCounterBuffers())
     {
         GLuint binding     = atomicCounterBuffer.binding;
@@ -952,15 +942,16 @@
 
 void StateManagerGL::updateProgramImageBindings(const gl::Context *context)
 {
-    const gl::State &glState   = context->getState();
-    const gl::Program *program = glState.getProgram();
+    const gl::State &glState                = context->getState();
+    const gl::ProgramExecutable *executable = glState.getProgramExecutable();
+    const gl::Program *program              = glState.getProgram();
 
     // It is possible there is no active program during a path operation.
-    if (!program)
+    if (!executable || !program)
         return;
 
-    ASSERT(context->getClientVersion() >= gl::ES_3_1 || program->getImageBindings().size() == 0);
-    for (size_t imageUnitIndex : program->getActiveImagesMask())
+    ASSERT(context->getClientVersion() >= gl::ES_3_1 || program->getImageBindings().empty());
+    for (size_t imageUnitIndex : executable->getActiveImagesMask())
     {
         const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex);
         const TextureGL *textureGL     = SafeGetImplAs<TextureGL>(imageUnit.texture.get());
@@ -1434,39 +1425,41 @@
     }
 }
 
-void StateManagerGL::setPrimitiveRestartEnabled(bool enabled)
+angle::Result StateManagerGL::setPrimitiveRestartEnabled(const gl::Context *context, bool enabled)
 {
     if (mPrimitiveRestartEnabled != enabled)
     {
-        mPrimitiveRestartEnabled = enabled;
-
         GLenum cap = mFeatures.emulatePrimitiveRestartFixedIndex.enabled
                          ? GL_PRIMITIVE_RESTART
                          : GL_PRIMITIVE_RESTART_FIXED_INDEX;
 
-        if (mPrimitiveRestartEnabled)
+        if (enabled)
         {
-            mFunctions->enable(cap);
+            ANGLE_GL_TRY(context, mFunctions->enable(cap));
         }
         else
         {
-            mFunctions->disable(cap);
+            ANGLE_GL_TRY(context, mFunctions->disable(cap));
         }
+        mPrimitiveRestartEnabled = enabled;
 
         mLocalDirtyBits.set(gl::State::DIRTY_BIT_PRIMITIVE_RESTART_ENABLED);
     }
+
+    return angle::Result::Continue;
 }
 
-void StateManagerGL::setPrimitiveRestartIndex(GLuint index)
+angle::Result StateManagerGL::setPrimitiveRestartIndex(const gl::Context *context, GLuint index)
 {
     if (mPrimitiveRestartIndex != index)
     {
+        ANGLE_GL_TRY(context, mFunctions->primitiveRestartIndex(index));
         mPrimitiveRestartIndex = index;
 
-        mFunctions->primitiveRestartIndex(index);
-
         // No dirty bit for this state, it is not exposed to the frontend.
     }
+
+    return angle::Result::Continue;
 }
 
 void StateManagerGL::setClearDepth(float clearDepth)
@@ -1531,16 +1524,16 @@
     }
 }
 
-void StateManagerGL::syncState(const gl::Context *context,
-                               const gl::State::DirtyBits &glDirtyBits,
-                               const gl::State::DirtyBits &bitMask)
+angle::Result StateManagerGL::syncState(const gl::Context *context,
+                                        const gl::State::DirtyBits &glDirtyBits,
+                                        const gl::State::DirtyBits &bitMask)
 {
     const gl::State &state = context->getState();
 
     const gl::State::DirtyBits glAndLocalDirtyBits = (glDirtyBits | mLocalDirtyBits) & bitMask;
     if (!glAndLocalDirtyBits.any())
     {
-        return;
+        return angle::Result::Continue;
     }
 
     // TODO(jmadill): Investigate only syncing vertex state for active attributes
@@ -1680,7 +1673,7 @@
                 setLineWidth(state.getLineWidth());
                 break;
             case gl::State::DIRTY_BIT_PRIMITIVE_RESTART_ENABLED:
-                setPrimitiveRestartEnabled(state.isPrimitiveRestartEnabled());
+                ANGLE_TRY(setPrimitiveRestartEnabled(context, state.isPrimitiveRestartEnabled()));
                 break;
             case gl::State::DIRTY_BIT_CLEAR_COLOR:
                 setClearColor(state.getColorClearValue());
@@ -1781,12 +1774,14 @@
             }
             case gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE:
             {
-                const gl::Program *program = state.getProgram();
-                if (program)
+                const gl::Program *program              = state.getProgram();
+                const gl::ProgramExecutable *executable = state.getProgramExecutable();
+
+                if (program && executable)
                 {
                     iter.setLaterBit(gl::State::DIRTY_BIT_TEXTURE_BINDINGS);
 
-                    if (program->getActiveImagesMask().any())
+                    if (executable->getActiveImagesMask().any())
                     {
                         iter.setLaterBit(gl::State::DIRTY_BIT_IMAGE_BINDINGS);
                     }
@@ -1813,7 +1808,8 @@
                     }
                 }
 
-                if (!program || !program->hasLinkedShaderStage(gl::ShaderType::Compute))
+                if (!program ||
+                    !program->getExecutable().hasLinkedShaderStage(gl::ShaderType::Compute))
                 {
                     propagateProgramToVAO(program,
                                           GetImplAs<VertexArrayGL>(state.getVertexArray()));
@@ -1850,14 +1846,6 @@
             case gl::State::DIRTY_BIT_COVERAGE_MODULATION:
                 setCoverageModulation(state.getCoverageModulation());
                 break;
-            case gl::State::DIRTY_BIT_PATH_RENDERING:
-                setPathRenderingModelViewMatrix(
-                    state.getPathRenderingMatrix(GL_PATH_MODELVIEW_MATRIX_CHROMIUM));
-                setPathRenderingProjectionMatrix(
-                    state.getPathRenderingMatrix(GL_PATH_PROJECTION_MATRIX_CHROMIUM));
-                setPathRenderingStencilState(state.getPathStencilFunc(), state.getPathStencilRef(),
-                                             state.getPathStencilMask());
-                break;
             case gl::State::DIRTY_BIT_FRAMEBUFFER_SRGB:
                 setFramebufferSRGBEnabledForFramebuffer(
                     context, state.getFramebufferSRGB(),
@@ -1898,6 +1886,8 @@
     }
 
     mLocalDirtyBits &= ~(bitMask);
+
+    return angle::Result::Continue;
 }
 
 void StateManagerGL::setFramebufferSRGBEnabled(const gl::Context *context, bool enabled)
@@ -2016,41 +2006,6 @@
     }
 }
 
-void StateManagerGL::setPathRenderingModelViewMatrix(const GLfloat *m)
-{
-    if (memcmp(mPathMatrixMV, m, sizeof(mPathMatrixMV)) != 0)
-    {
-        memcpy(mPathMatrixMV, m, sizeof(mPathMatrixMV));
-        mFunctions->matrixLoadfEXT(GL_PATH_MODELVIEW_CHROMIUM, m);
-
-        mLocalDirtyBits.set(gl::State::DIRTY_BIT_PATH_RENDERING);
-    }
-}
-
-void StateManagerGL::setPathRenderingProjectionMatrix(const GLfloat *m)
-{
-    if (memcmp(mPathMatrixProj, m, sizeof(mPathMatrixProj)) != 0)
-    {
-        memcpy(mPathMatrixProj, m, sizeof(mPathMatrixProj));
-        mFunctions->matrixLoadfEXT(GL_PATH_PROJECTION_CHROMIUM, m);
-
-        mLocalDirtyBits.set(gl::State::DIRTY_BIT_PATH_RENDERING);
-    }
-}
-
-void StateManagerGL::setPathRenderingStencilState(GLenum func, GLint ref, GLuint mask)
-{
-    if (func != mPathStencilFunc || ref != mPathStencilRef || mask != mPathStencilMask)
-    {
-        mPathStencilFunc = func;
-        mPathStencilRef  = ref;
-        mPathStencilMask = mask;
-        mFunctions->pathStencilFuncNV(func, ref, mask);
-
-        mLocalDirtyBits.set(gl::State::DIRTY_BIT_PATH_RENDERING);
-    }
-}
-
 void StateManagerGL::setProvokingVertex(GLenum mode)
 {
     if (mode != mProvokingVertex)
@@ -2105,7 +2060,8 @@
     // Attribute enabled mask:
     if (program)
     {
-        vao->applyActiveAttribLocationsMask(program->getActiveAttribLocationsMask());
+        vao->applyActiveAttribLocationsMask(
+            program->getExecutable().getActiveAttribLocationsMask());
     }
 }
 
diff --git a/src/libANGLE/renderer/gl/StateManagerGL.h b/src/libANGLE/renderer/gl/StateManagerGL.h
index 97a68b1..240a897 100644
--- a/src/libANGLE/renderer/gl/StateManagerGL.h
+++ b/src/libANGLE/renderer/gl/StateManagerGL.h
@@ -121,8 +121,8 @@
     void setRasterizerDiscardEnabled(bool enabled);
     void setLineWidth(float width);
 
-    void setPrimitiveRestartEnabled(bool enabled);
-    void setPrimitiveRestartIndex(GLuint index);
+    angle::Result setPrimitiveRestartEnabled(const gl::Context *context, bool enabled);
+    angle::Result setPrimitiveRestartIndex(const gl::Context *context, GLuint index);
 
     void setClearColor(const gl::ColorF &clearColor);
     void setClearDepth(float clearDepth);
@@ -150,10 +150,6 @@
 
     void setCoverageModulation(GLenum components);
 
-    void setPathRenderingModelViewMatrix(const GLfloat *m);
-    void setPathRenderingProjectionMatrix(const GLfloat *m);
-    void setPathRenderingStencilState(GLenum func, GLint ref, GLuint mask);
-
     void setProvokingVertex(GLenum mode);
 
     void pauseTransformFeedback();
@@ -163,9 +159,9 @@
     angle::Result resumeQuery(const gl::Context *context, gl::QueryType type);
     angle::Result onMakeCurrent(const gl::Context *context);
 
-    void syncState(const gl::Context *context,
-                   const gl::State::DirtyBits &glDirtyBits,
-                   const gl::State::DirtyBits &bitMask);
+    angle::Result syncState(const gl::Context *context,
+                            const gl::State::DirtyBits &glDirtyBits,
+                            const gl::State::DirtyBits &bitMask);
 
     ANGLE_INLINE void updateMultiviewBaseViewLayerIndexUniform(
         const gl::Program *program,
@@ -344,12 +340,6 @@
 
     GLenum mCoverageModulation;
 
-    GLfloat mPathMatrixMV[16];
-    GLfloat mPathMatrixProj[16];
-    GLenum mPathStencilFunc;
-    GLint mPathStencilRef;
-    GLuint mPathStencilMask;
-
     const bool mIsMultiviewEnabled;
 
     GLenum mProvokingVertex;
diff --git a/src/libANGLE/renderer/gl/TextureGL.cpp b/src/libANGLE/renderer/gl/TextureGL.cpp
index c562896..8ffb475 100644
--- a/src/libANGLE/renderer/gl/TextureGL.cpp
+++ b/src/libANGLE/renderer/gl/TextureGL.cpp
@@ -164,13 +164,11 @@
                                   GLenum format,
                                   GLenum type,
                                   const gl::PixelUnpackState &unpack,
+                                  gl::Buffer *unpackBuffer,
                                   const uint8_t *pixels)
 {
     const angle::FeaturesGL &features = GetFeaturesGL(context);
 
-    const gl::Buffer *unpackBuffer =
-        context->getState().getTargetBuffer(gl::BufferBinding::PixelUnpack);
-
     gl::TextureTarget target = index.getTarget();
     size_t level             = static_cast<size_t>(index.getLevelIndex());
 
@@ -619,8 +617,7 @@
 
     gl::TextureTarget target = index.getTarget();
     size_t level             = static_cast<size_t>(index.getLevelIndex());
-    GLenum type              = GL_NONE;
-    ANGLE_TRY(source->getImplementationColorReadType(context, &type));
+    GLenum type              = source->getImplementationColorReadType(context);
     nativegl::CopyTexImageImageFormat copyTexImageFormat =
         nativegl::GetCopyTexImageImageFormat(functions, features, internalFormat, type);
 
@@ -749,8 +746,8 @@
                                       const gl::Rectangle &sourceArea,
                                       gl::Framebuffer *source)
 {
-    const FunctionsGL *functions = GetFunctionsGL(context);
-    StateManagerGL *stateManager = GetStateManagerGL(context);
+    const FunctionsGL *functions      = GetFunctionsGL(context);
+    StateManagerGL *stateManager      = GetStateManagerGL(context);
     const angle::FeaturesGL &features = GetFeaturesGL(context);
 
     gl::TextureTarget target                 = index.getTarget();
@@ -1522,7 +1519,7 @@
         mLocalDirtyBits.set(gl::Texture::DIRTY_BIT_BASE_LEVEL);
 
         // Signal to the GL layer that the Impl has dirty bits.
-        onStateChange(angle::SubjectMessage::SubjectChanged);
+        onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
 
         stateManager->bindTexture(getType(), mTextureID);
         ANGLE_GL_TRY(context, functions->texParameteri(ToGLenum(getType()), GL_TEXTURE_BASE_LEVEL,
@@ -1542,7 +1539,7 @@
         mLocalDirtyBits.set(gl::Texture::DIRTY_BIT_MAX_LEVEL);
 
         // Signal to the GL layer that the Impl has dirty bits.
-        onStateChange(angle::SubjectMessage::SubjectChanged);
+        onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
 
         stateManager->bindTexture(getType(), mTextureID);
         ANGLE_GL_TRY(context,
@@ -1562,7 +1559,7 @@
         mLocalDirtyBits.set(gl::Texture::DIRTY_BIT_MIN_FILTER);
 
         // Signal to the GL layer that the Impl has dirty bits.
-        onStateChange(angle::SubjectMessage::SubjectChanged);
+        onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
 
         stateManager->bindTexture(getType(), mTextureID);
         ANGLE_GL_TRY(context,
@@ -1581,7 +1578,7 @@
         mLocalDirtyBits.set(gl::Texture::DIRTY_BIT_MAG_FILTER);
 
         // Signal to the GL layer that the Impl has dirty bits.
-        onStateChange(angle::SubjectMessage::SubjectChanged);
+        onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
 
         stateManager->bindTexture(getType(), mTextureID);
         ANGLE_GL_TRY(context,
@@ -1607,7 +1604,7 @@
         mLocalDirtyBits.set(gl::Texture::DIRTY_BIT_SWIZZLE_ALPHA);
 
         // Signal to the GL layer that the Impl has dirty bits.
-        onStateChange(angle::SubjectMessage::SubjectChanged);
+        onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
 
         stateManager->bindTexture(getType(), mTextureID);
         ANGLE_GL_TRY(context, functions->texParameteriv(ToGLenum(getType()),
@@ -1775,7 +1772,7 @@
     if (updateWorkarounds)
     {
         mLocalDirtyBits |= GetLevelWorkaroundDirtyBits();
-        onStateChange(angle::SubjectMessage::SubjectChanged);
+        onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
     }
 }
 
diff --git a/src/libANGLE/renderer/gl/TextureGL.h b/src/libANGLE/renderer/gl/TextureGL.h
index 4191911..517b3d9 100644
--- a/src/libANGLE/renderer/gl/TextureGL.h
+++ b/src/libANGLE/renderer/gl/TextureGL.h
@@ -74,6 +74,7 @@
                            GLenum format,
                            GLenum type,
                            const gl::PixelUnpackState &unpack,
+                           gl::Buffer *unpackBuffer,
                            const uint8_t *pixels) override;
     angle::Result setSubImage(const gl::Context *context,
                               const gl::ImageIndex &index,
diff --git a/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.mm b/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.mm
index 1c1fd22..d6a86f5 100644
--- a/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.mm
+++ b/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.mm
@@ -212,6 +212,7 @@
                                                withContext:mContext
                                              withFunctions:mFunctions];
     [mLayer addSublayer:mSwapLayer];
+    [mSwapLayer setContentsScale:[mLayer contentsScale]];
 
     mFunctions->genRenderbuffers(1, &mDSRenderbuffer);
     mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mDSRenderbuffer);
@@ -301,12 +302,12 @@
 
 EGLint WindowSurfaceCGL::getWidth() const
 {
-    return (EGLint)CGRectGetWidth([mLayer frame]);
+    return static_cast<EGLint>(CGRectGetWidth([mLayer frame]) * [mLayer contentsScale]);
 }
 
 EGLint WindowSurfaceCGL::getHeight() const
 {
-    return (EGLint)CGRectGetHeight([mLayer frame]);
+    return static_cast<EGLint>(CGRectGetHeight([mLayer frame]) * [mLayer contentsScale]);
 }
 
 EGLint WindowSurfaceCGL::isPostSubBufferSupported() const
diff --git a/src/libANGLE/renderer/gl/eagl/WindowSurfaceEAGL.mm b/src/libANGLE/renderer/gl/eagl/WindowSurfaceEAGL.mm
index cb482d0..59c5c2f 100644
--- a/src/libANGLE/renderer/gl/eagl/WindowSurfaceEAGL.mm
+++ b/src/libANGLE/renderer/gl/eagl/WindowSurfaceEAGL.mm
@@ -177,6 +177,7 @@
                                                withContext:mContext
                                              withFunctions:mFunctions];
     [mLayer addSublayer:mSwapLayer];
+    [mSwapLayer setContentsScale:[mLayer contentsScale]];
 
     mFunctions->genRenderbuffers(1, &mDSRenderbuffer);
     mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mDSRenderbuffer);
@@ -266,12 +267,12 @@
 
 EGLint WindowSurfaceEAGL::getWidth() const
 {
-    return (EGLint)CGRectGetWidth([mLayer frame]);
+    return static_cast<EGLint>(CGRectGetWidth([mLayer frame]) * [mLayer contentsScale]);
 }
 
 EGLint WindowSurfaceEAGL::getHeight() const
 {
-    return (EGLint)CGRectGetHeight([mLayer frame]);
+    return static_cast<EGLint>(CGRectGetHeight([mLayer frame]) * [mLayer contentsScale]);
 }
 
 EGLint WindowSurfaceEAGL::isPostSubBufferSupported() const
diff --git a/src/libANGLE/renderer/gl/egl/DisplayEGL.cpp b/src/libANGLE/renderer/gl/egl/DisplayEGL.cpp
index 3bf532c..15c9ea7 100644
--- a/src/libANGLE/renderer/gl/egl/DisplayEGL.cpp
+++ b/src/libANGLE/renderer/gl/egl/DisplayEGL.cpp
@@ -621,6 +621,7 @@
             mEGL->hasExtension("EGL_EXT_gl_colorspace_scrgb_linear");
         outExtensions->glColorspaceDisplayP3Passthrough =
             mEGL->hasExtension("EGL_EXT_gl_colorspace_display_p3_passthrough");
+        outExtensions->imageGlColorspace = mEGL->hasExtension("EGL_EXT_image_gl_colorspace");
     }
 
     outExtensions->imageNativeBuffer = mEGL->hasExtension("EGL_ANDROID_image_native_buffer");
diff --git a/src/libANGLE/renderer/gl/functionsgl_typedefs.h b/src/libANGLE/renderer/gl/functionsgl_typedefs.h
index 2a86b77..5f2c138 100644
--- a/src/libANGLE/renderer/gl/functionsgl_typedefs.h
+++ b/src/libANGLE/renderer/gl/functionsgl_typedefs.h
@@ -1726,112 +1726,6 @@
     GLenum target,
     GLeglImageOES image);
 
-// NV_path_rendering (originally written against 3.2 compatibility profile)
-typedef void(INTERNAL_GL_APIENTRY *PFNGLMATRIXLOADFEXTPROC)(GLenum matrixMode, const GLfloat *m);
-typedef void(INTERNAL_GL_APIENTRY *PFNGLMATRIXLOADFNVPROC)(GLenum matrixMode, const GLfloat *m);
-typedef void(INTERNAL_GL_APIENTRY *PFNGLMATRIXLOADIDENTITYNVPROC)(GLenum matrixMode);
-typedef GLuint(INTERNAL_GL_APIENTRY *PFNGLGENPATHSNVPROC)(GLsizei range);
-typedef void(INTERNAL_GL_APIENTRY *PFNGLDELETEPATHSNVPROC)(GLuint path, GLsizei range);
-typedef GLboolean(INTERNAL_GL_APIENTRY *PFNGLISPATHNVPROC)(GLuint path);
-typedef void(INTERNAL_GL_APIENTRY *PFNGLPATHCOMMANDSNVPROC)(GLuint path,
-                                                            GLsizei numCommands,
-                                                            const GLubyte *commands,
-                                                            GLsizei numCoords,
-                                                            GLenum coordType,
-                                                            const void *coords);
-typedef void(INTERNAL_GL_APIENTRY *PFNGLPATHPARAMETERINVPROC)(GLuint path,
-                                                              GLenum pname,
-                                                              GLint value);
-typedef void(INTERNAL_GL_APIENTRY *PFNGLPATHPARAMETERFNVPROC)(GLuint path,
-                                                              GLenum pname,
-                                                              GLfloat value);
-typedef void(INTERNAL_GL_APIENTRY *PFNGLGETPATHPARAMETERIVNVPROC)(GLuint path,
-                                                                  GLenum pname,
-                                                                  GLint *value);
-typedef void(INTERNAL_GL_APIENTRY *PFNGLGETPATHPARAMETERFVNVPROC)(GLuint path,
-                                                                  GLenum pname,
-                                                                  GLfloat *value);
-typedef void(INTERNAL_GL_APIENTRY *PFNGLPATHSTENCILFUNCNVPROC)(GLenum func, GLint ref, GLuint mask);
-typedef void(INTERNAL_GL_APIENTRY *PFNGLSTENCILFILLPATHNVPROC)(GLuint path,
-                                                               GLenum fillMode,
-                                                               GLuint mask);
-typedef void(INTERNAL_GL_APIENTRY *PFNGLSTENCILSTROKEPATHNVPROC)(GLuint path,
-                                                                 GLint reference,
-                                                                 GLuint mask);
-typedef void(INTERNAL_GL_APIENTRY *PFNGLCOVERFILLPATHNVPROC)(GLuint path, GLenum coverMode);
-typedef void(INTERNAL_GL_APIENTRY *PFNGLCOVERSTROKEPATHNVPROC)(GLuint path, GLenum coverMode);
-typedef void(INTERNAL_GL_APIENTRY *PFNGLSTENCILTHENCOVERFILLPATHNVPROC)(GLuint path,
-                                                                        GLenum fillMode,
-                                                                        GLuint mask,
-                                                                        GLenum coverMode);
-typedef void(INTERNAL_GL_APIENTRY *PFNGLSTENCILTHENCOVERSTROKEPATHNVPROC)(GLuint path,
-                                                                          GLint reference,
-                                                                          GLuint mask,
-                                                                          GLenum coverMode);
-typedef void(INTERNAL_GL_APIENTRY *PFNGLCOVERFILLPATHINSTANCEDNVPROC)(
-    GLsizei numPaths,
-    GLenum pathNameType,
-    const void *paths,
-    GLuint pathBase,
-    GLenum coverMode,
-    GLenum transformType,
-    const GLfloat *transformValues);
-typedef void(INTERNAL_GL_APIENTRY *PFNGLCOVERSTROKEPATHINSTANCEDNVPROC)(
-    GLsizei numPaths,
-    GLenum pathNameType,
-    const void *paths,
-    GLuint pathBase,
-    GLenum coverMode,
-    GLenum transformType,
-    const GLfloat *transformValues);
-typedef void(INTERNAL_GL_APIENTRY *PFNGLSTENCILFILLPATHINSTANCEDNVPROC)(
-    GLsizei numPaths,
-    GLenum pathNameType,
-    const void *paths,
-    GLuint pathBase,
-    GLenum fillMode,
-    GLuint mask,
-    GLenum transformType,
-    const GLfloat *transformValues);
-typedef void(INTERNAL_GL_APIENTRY *PFNGLSTENCILSTROKEPATHINSTANCEDNVPROC)(
-    GLsizei numPaths,
-    GLenum pathNameType,
-    const void *paths,
-    GLuint pathBase,
-    GLint reference,
-    GLuint mask,
-    GLenum transformType,
-    const GLfloat *transformValues);
-typedef void(INTERNAL_GL_APIENTRY *PFNGLSTENCILTHENCOVERFILLPATHINSTANCEDNVPROC)(
-    GLsizei numPaths,
-    GLenum pathNameType,
-    const void *paths,
-    GLuint pathBase,
-    GLenum fillMode,
-    GLuint mask,
-    GLenum coverMode,
-    GLenum transformType,
-    const GLfloat *transformValues);
-typedef void(INTERNAL_GL_APIENTRY *PFNGLSTENCILTHENCOVERSTROKEPATHINSTANCEDNVPROC)(
-    GLsizei numPaths,
-    GLenum pathNameType,
-    const void *paths,
-    GLuint pathBase,
-    GLint reference,
-    GLuint mask,
-    GLenum coverMode,
-    GLenum transformType,
-    const GLfloat *transformValues);
-
-typedef void(INTERNAL_GL_APIENTRY *PFNGLBINDFRAGMENTINPUTLOCATIONNVPROC)(GLuint program,
-                                                                         GLint location,
-                                                                         const GLchar *name);
-typedef void(INTERNAL_GL_APIENTRY *PFNGLPROGRAMPATHFRAGMENTINPUTGENNVPROC)(GLuint program,
-                                                                           GLint location,
-                                                                           GLenum genMode,
-                                                                           GLint components,
-                                                                           const GLfloat *coeffs);
-
 // ES 3.2
 typedef void(INTERNAL_GL_APIENTRY *PFNGLBLENDBARRIERPROC)(void);
 typedef void(INTERNAL_GL_APIENTRY *PFNGLPRIMITIVEBOUNDINGBOXPROC)(GLfloat minX,
diff --git a/src/libANGLE/renderer/gl/gl_bindings_data.json b/src/libANGLE/renderer/gl/gl_bindings_data.json
index 4ae04ad..9053164 100644
--- a/src/libANGLE/renderer/gl/gl_bindings_data.json
+++ b/src/libANGLE/renderer/gl/gl_bindings_data.json
@@ -370,33 +370,6 @@
         "WaitSync"
     ],
 
-    "NV_path_rendering (originally written against 3.2 compatibility profile)":
-    [
-        "MatrixLoadfEXT",
-        "GenPathsNV",
-        "DeletePathsNV",
-        "PathCommandsNV",
-        "IsPathNV",
-        "PathParameterfNV",
-        "PathParameteriNV",
-        "GetPathParameterfvNV",
-        "GetPathParameterivNV",
-        "PathStencilFuncNV",
-        "StencilFillPathNV",
-        "StencilStrokePathNV",
-        "CoverFillPathNV",
-        "CoverStrokePathNV",
-        "StencilThenCoverFillPathNV",
-        "StencilThenCoverStrokePathNV",
-        "CoverFillPathInstancedNV",
-        "CoverStrokePathInstancedNV",
-        "StencilFillPathInstancedNV",
-        "StencilStrokePathInstancedNV",
-        "StencilThenCoverFillPathInstancedNV",
-        "StencilThenCoverStrokePathInstancedNV",
-        "ProgramPathFragmentInputGenNV"
-    ],
-
     "3.3":
     [
         "BindFragDataLocationIndexed",
diff --git a/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp b/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp
index c737f2b..6f2e175 100644
--- a/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp
+++ b/src/libANGLE/renderer/gl/glx/DisplayGLX.cpp
@@ -830,7 +830,9 @@
 
     outExtensions->surfacelessContext = true;
 
-    outExtensions->syncControlCHROMIUM = mGLX.hasExtension("GLX_OML_sync_control");
+    const bool hasSyncControlOML        = mGLX.hasExtension("GLX_OML_sync_control");
+    outExtensions->syncControlCHROMIUM  = hasSyncControlOML;
+    outExtensions->syncControlRateANGLE = hasSyncControlOML;
 
     DisplayGL::generateExtensions(outExtensions);
 }
diff --git a/src/libANGLE/renderer/gl/null_functions.cpp b/src/libANGLE/renderer/gl/null_functions.cpp
index 2982773..6dbf6fa 100644
--- a/src/libANGLE/renderer/gl/null_functions.cpp
+++ b/src/libANGLE/renderer/gl/null_functions.cpp
@@ -518,28 +518,6 @@
                                                       GLsizei height)
 {}
 
-void INTERNAL_GL_APIENTRY glCoverFillPathInstancedNVNULL(GLsizei numPaths,
-                                                         GLenum pathNameType,
-                                                         const void *paths,
-                                                         GLuint pathBase,
-                                                         GLenum coverMode,
-                                                         GLenum transformType,
-                                                         const GLfloat *transformValues)
-{}
-
-void INTERNAL_GL_APIENTRY glCoverFillPathNVNULL(GLuint path, GLenum coverMode) {}
-
-void INTERNAL_GL_APIENTRY glCoverStrokePathInstancedNVNULL(GLsizei numPaths,
-                                                           GLenum pathNameType,
-                                                           const void *paths,
-                                                           GLuint pathBase,
-                                                           GLenum coverMode,
-                                                           GLenum transformType,
-                                                           const GLfloat *transformValues)
-{}
-
-void INTERNAL_GL_APIENTRY glCoverStrokePathNVNULL(GLuint path, GLenum coverMode) {}
-
 void INTERNAL_GL_APIENTRY glCoverageModulationNVNULL(GLenum components) {}
 
 void INTERNAL_GL_APIENTRY glCreateBuffersNULL(GLsizei n, GLuint *buffers) {}
@@ -607,8 +585,6 @@
 
 void INTERNAL_GL_APIENTRY glDeleteMemoryObjectsEXTNULL(GLsizei n, const GLuint *memoryObjects) {}
 
-void INTERNAL_GL_APIENTRY glDeletePathsNVNULL(GLuint path, GLsizei range) {}
-
 void INTERNAL_GL_APIENTRY glDeleteProgramNULL(GLuint program) {}
 
 void INTERNAL_GL_APIENTRY glDeleteProgramPipelinesNULL(GLsizei n, const GLuint *pipelines) {}
@@ -869,11 +845,6 @@
 
 void INTERNAL_GL_APIENTRY glGenFramebuffersNULL(GLsizei n, GLuint *framebuffers) {}
 
-GLuint INTERNAL_GL_APIENTRY glGenPathsNVNULL(GLsizei range)
-{
-    return static_cast<GLuint>(0);
-}
-
 void INTERNAL_GL_APIENTRY glGenProgramPipelinesNULL(GLsizei n, GLuint *pipelines) {}
 
 void INTERNAL_GL_APIENTRY glGenQueriesNULL(GLsizei n, GLuint *ids) {}
@@ -1154,10 +1125,6 @@
                                                   GLchar *label)
 {}
 
-void INTERNAL_GL_APIENTRY glGetPathParameterfvNVNULL(GLuint path, GLenum pname, GLfloat *value) {}
-
-void INTERNAL_GL_APIENTRY glGetPathParameterivNVNULL(GLuint path, GLenum pname, GLint *value) {}
-
 void INTERNAL_GL_APIENTRY glGetPointervNULL(GLenum pname, void **params) {}
 
 void INTERNAL_GL_APIENTRY glGetProgramBinaryNULL(GLuint program,
@@ -1655,11 +1622,6 @@
     return static_cast<GLboolean>(0);
 }
 
-GLboolean INTERNAL_GL_APIENTRY glIsPathNVNULL(GLuint path)
-{
-    return static_cast<GLboolean>(0);
-}
-
 GLboolean INTERNAL_GL_APIENTRY glIsProgramNULL(GLuint program)
 {
     return static_cast<GLboolean>(0);
@@ -1747,8 +1709,6 @@
     return static_cast<void *>(0);
 }
 
-void INTERNAL_GL_APIENTRY glMatrixLoadfEXTNULL(GLenum mode, const GLfloat *m) {}
-
 void INTERNAL_GL_APIENTRY glMaxShaderCompilerThreadsARBNULL(GLuint count) {}
 
 void INTERNAL_GL_APIENTRY glMaxShaderCompilerThreadsKHRNULL(GLuint count) {}
@@ -1881,20 +1841,6 @@
 
 void INTERNAL_GL_APIENTRY glPatchParameteriNULL(GLenum pname, GLint value) {}
 
-void INTERNAL_GL_APIENTRY glPathCommandsNVNULL(GLuint path,
-                                               GLsizei numCommands,
-                                               const GLubyte *commands,
-                                               GLsizei numCoords,
-                                               GLenum coordType,
-                                               const void *coords)
-{}
-
-void INTERNAL_GL_APIENTRY glPathParameterfNVNULL(GLuint path, GLenum pname, GLfloat value) {}
-
-void INTERNAL_GL_APIENTRY glPathParameteriNVNULL(GLuint path, GLenum pname, GLint value) {}
-
-void INTERNAL_GL_APIENTRY glPathStencilFuncNVNULL(GLenum func, GLint ref, GLuint mask) {}
-
 void INTERNAL_GL_APIENTRY glPauseTransformFeedbackNULL() {}
 
 void INTERNAL_GL_APIENTRY glPixelStorefNULL(GLenum pname, GLfloat param) {}
@@ -1939,13 +1885,6 @@
 
 void INTERNAL_GL_APIENTRY glProgramParameteriNULL(GLuint program, GLenum pname, GLint value) {}
 
-void INTERNAL_GL_APIENTRY glProgramPathFragmentInputGenNVNULL(GLuint program,
-                                                              GLint location,
-                                                              GLenum genMode,
-                                                              GLint components,
-                                                              const GLfloat *coeffs)
-{}
-
 void INTERNAL_GL_APIENTRY glProgramUniform1dNULL(GLuint program, GLint location, GLdouble v0) {}
 
 void INTERNAL_GL_APIENTRY glProgramUniform1dvNULL(GLuint program,
@@ -2356,18 +2295,6 @@
                                                    const GLenum *dstLayouts)
 {}
 
-void INTERNAL_GL_APIENTRY glStencilFillPathInstancedNVNULL(GLsizei numPaths,
-                                                           GLenum pathNameType,
-                                                           const void *paths,
-                                                           GLuint pathBase,
-                                                           GLenum fillMode,
-                                                           GLuint mask,
-                                                           GLenum transformType,
-                                                           const GLfloat *transformValues)
-{}
-
-void INTERNAL_GL_APIENTRY glStencilFillPathNVNULL(GLuint path, GLenum fillMode, GLuint mask) {}
-
 void INTERNAL_GL_APIENTRY glStencilFuncNULL(GLenum func, GLint ref, GLuint mask) {}
 
 void INTERNAL_GL_APIENTRY glStencilFuncSeparateNULL(GLenum face,
@@ -2388,53 +2315,6 @@
                                                   GLenum dppass)
 {}
 
-void INTERNAL_GL_APIENTRY glStencilStrokePathInstancedNVNULL(GLsizei numPaths,
-                                                             GLenum pathNameType,
-                                                             const void *paths,
-                                                             GLuint pathBase,
-                                                             GLint reference,
-                                                             GLuint mask,
-                                                             GLenum transformType,
-                                                             const GLfloat *transformValues)
-{}
-
-void INTERNAL_GL_APIENTRY glStencilStrokePathNVNULL(GLuint path, GLint reference, GLuint mask) {}
-
-void INTERNAL_GL_APIENTRY glStencilThenCoverFillPathInstancedNVNULL(GLsizei numPaths,
-                                                                    GLenum pathNameType,
-                                                                    const void *paths,
-                                                                    GLuint pathBase,
-                                                                    GLenum fillMode,
-                                                                    GLuint mask,
-                                                                    GLenum coverMode,
-                                                                    GLenum transformType,
-                                                                    const GLfloat *transformValues)
-{}
-
-void INTERNAL_GL_APIENTRY glStencilThenCoverFillPathNVNULL(GLuint path,
-                                                           GLenum fillMode,
-                                                           GLuint mask,
-                                                           GLenum coverMode)
-{}
-
-void INTERNAL_GL_APIENTRY
-glStencilThenCoverStrokePathInstancedNVNULL(GLsizei numPaths,
-                                            GLenum pathNameType,
-                                            const void *paths,
-                                            GLuint pathBase,
-                                            GLint reference,
-                                            GLuint mask,
-                                            GLenum coverMode,
-                                            GLenum transformType,
-                                            const GLfloat *transformValues)
-{}
-
-void INTERNAL_GL_APIENTRY glStencilThenCoverStrokePathNVNULL(GLuint path,
-                                                             GLint reference,
-                                                             GLuint mask,
-                                                             GLenum coverMode)
-{}
-
 GLboolean INTERNAL_GL_APIENTRY glTestFenceNVNULL(GLuint fence)
 {
     return static_cast<GLboolean>(0);
diff --git a/src/libANGLE/renderer/gl/null_functions.h b/src/libANGLE/renderer/gl/null_functions.h
index 2617996..84e9856 100644
--- a/src/libANGLE/renderer/gl/null_functions.h
+++ b/src/libANGLE/renderer/gl/null_functions.h
@@ -374,22 +374,6 @@
                                                       GLint y,
                                                       GLsizei width,
                                                       GLsizei height);
-void INTERNAL_GL_APIENTRY glCoverFillPathInstancedNVNULL(GLsizei numPaths,
-                                                         GLenum pathNameType,
-                                                         const void *paths,
-                                                         GLuint pathBase,
-                                                         GLenum coverMode,
-                                                         GLenum transformType,
-                                                         const GLfloat *transformValues);
-void INTERNAL_GL_APIENTRY glCoverFillPathNVNULL(GLuint path, GLenum coverMode);
-void INTERNAL_GL_APIENTRY glCoverStrokePathInstancedNVNULL(GLsizei numPaths,
-                                                           GLenum pathNameType,
-                                                           const void *paths,
-                                                           GLuint pathBase,
-                                                           GLenum coverMode,
-                                                           GLenum transformType,
-                                                           const GLfloat *transformValues);
-void INTERNAL_GL_APIENTRY glCoverStrokePathNVNULL(GLuint path, GLenum coverMode);
 void INTERNAL_GL_APIENTRY glCoverageModulationNVNULL(GLenum components);
 void INTERNAL_GL_APIENTRY glCreateBuffersNULL(GLsizei n, GLuint *buffers);
 void INTERNAL_GL_APIENTRY glCreateFramebuffersNULL(GLsizei n, GLuint *framebuffers);
@@ -424,7 +408,6 @@
 void INTERNAL_GL_APIENTRY glDeleteFencesNVNULL(GLsizei n, const GLuint *fences);
 void INTERNAL_GL_APIENTRY glDeleteFramebuffersNULL(GLsizei n, const GLuint *framebuffers);
 void INTERNAL_GL_APIENTRY glDeleteMemoryObjectsEXTNULL(GLsizei n, const GLuint *memoryObjects);
-void INTERNAL_GL_APIENTRY glDeletePathsNVNULL(GLuint path, GLsizei range);
 void INTERNAL_GL_APIENTRY glDeleteProgramNULL(GLuint program);
 void INTERNAL_GL_APIENTRY glDeleteProgramPipelinesNULL(GLsizei n, const GLuint *pipelines);
 void INTERNAL_GL_APIENTRY glDeleteQueriesNULL(GLsizei n, const GLuint *ids);
@@ -586,7 +569,6 @@
 void INTERNAL_GL_APIENTRY glGenBuffersNULL(GLsizei n, GLuint *buffers);
 void INTERNAL_GL_APIENTRY glGenFencesNVNULL(GLsizei n, GLuint *fences);
 void INTERNAL_GL_APIENTRY glGenFramebuffersNULL(GLsizei n, GLuint *framebuffers);
-GLuint INTERNAL_GL_APIENTRY glGenPathsNVNULL(GLsizei range);
 void INTERNAL_GL_APIENTRY glGenProgramPipelinesNULL(GLsizei n, GLuint *pipelines);
 void INTERNAL_GL_APIENTRY glGenQueriesNULL(GLsizei n, GLuint *ids);
 void INTERNAL_GL_APIENTRY glGenRenderbuffersNULL(GLsizei n, GLuint *renderbuffers);
@@ -760,8 +742,6 @@
                                                   GLsizei bufSize,
                                                   GLsizei *length,
                                                   GLchar *label);
-void INTERNAL_GL_APIENTRY glGetPathParameterfvNVNULL(GLuint path, GLenum pname, GLfloat *value);
-void INTERNAL_GL_APIENTRY glGetPathParameterivNVNULL(GLuint path, GLenum pname, GLint *value);
 void INTERNAL_GL_APIENTRY glGetPointervNULL(GLenum pname, void **params);
 void INTERNAL_GL_APIENTRY glGetProgramBinaryNULL(GLuint program,
                                                  GLsizei bufSize,
@@ -1053,7 +1033,6 @@
 GLboolean INTERNAL_GL_APIENTRY glIsFenceNVNULL(GLuint fence);
 GLboolean INTERNAL_GL_APIENTRY glIsFramebufferNULL(GLuint framebuffer);
 GLboolean INTERNAL_GL_APIENTRY glIsMemoryObjectEXTNULL(GLuint memoryObject);
-GLboolean INTERNAL_GL_APIENTRY glIsPathNVNULL(GLuint path);
 GLboolean INTERNAL_GL_APIENTRY glIsProgramNULL(GLuint program);
 GLboolean INTERNAL_GL_APIENTRY glIsProgramPipelineNULL(GLuint pipeline);
 GLboolean INTERNAL_GL_APIENTRY glIsQueryNULL(GLuint id);
@@ -1078,7 +1057,6 @@
                                                      GLintptr offset,
                                                      GLsizeiptr length,
                                                      GLbitfield access);
-void INTERNAL_GL_APIENTRY glMatrixLoadfEXTNULL(GLenum mode, const GLfloat *m);
 void INTERNAL_GL_APIENTRY glMaxShaderCompilerThreadsARBNULL(GLuint count);
 void INTERNAL_GL_APIENTRY glMaxShaderCompilerThreadsKHRNULL(GLuint count);
 void INTERNAL_GL_APIENTRY glMemoryBarrierNULL(GLbitfield barriers);
@@ -1166,15 +1144,6 @@
                                                const GLchar *label);
 void INTERNAL_GL_APIENTRY glPatchParameterfvNULL(GLenum pname, const GLfloat *values);
 void INTERNAL_GL_APIENTRY glPatchParameteriNULL(GLenum pname, GLint value);
-void INTERNAL_GL_APIENTRY glPathCommandsNVNULL(GLuint path,
-                                               GLsizei numCommands,
-                                               const GLubyte *commands,
-                                               GLsizei numCoords,
-                                               GLenum coordType,
-                                               const void *coords);
-void INTERNAL_GL_APIENTRY glPathParameterfNVNULL(GLuint path, GLenum pname, GLfloat value);
-void INTERNAL_GL_APIENTRY glPathParameteriNVNULL(GLuint path, GLenum pname, GLint value);
-void INTERNAL_GL_APIENTRY glPathStencilFuncNVNULL(GLenum func, GLint ref, GLuint mask);
 void INTERNAL_GL_APIENTRY glPauseTransformFeedbackNULL();
 void INTERNAL_GL_APIENTRY glPixelStorefNULL(GLenum pname, GLfloat param);
 void INTERNAL_GL_APIENTRY glPixelStoreiNULL(GLenum pname, GLint param);
@@ -1201,11 +1170,6 @@
                                               const void *binary,
                                               GLsizei length);
 void INTERNAL_GL_APIENTRY glProgramParameteriNULL(GLuint program, GLenum pname, GLint value);
-void INTERNAL_GL_APIENTRY glProgramPathFragmentInputGenNVNULL(GLuint program,
-                                                              GLint location,
-                                                              GLenum genMode,
-                                                              GLint components,
-                                                              const GLfloat *coeffs);
 void INTERNAL_GL_APIENTRY glProgramUniform1dNULL(GLuint program, GLint location, GLdouble v0);
 void INTERNAL_GL_APIENTRY glProgramUniform1dvNULL(GLuint program,
                                                   GLint location,
@@ -1481,15 +1445,6 @@
                                                    GLuint numTextureBarriers,
                                                    const GLuint *textures,
                                                    const GLenum *dstLayouts);
-void INTERNAL_GL_APIENTRY glStencilFillPathInstancedNVNULL(GLsizei numPaths,
-                                                           GLenum pathNameType,
-                                                           const void *paths,
-                                                           GLuint pathBase,
-                                                           GLenum fillMode,
-                                                           GLuint mask,
-                                                           GLenum transformType,
-                                                           const GLfloat *transformValues);
-void INTERNAL_GL_APIENTRY glStencilFillPathNVNULL(GLuint path, GLenum fillMode, GLuint mask);
 void INTERNAL_GL_APIENTRY glStencilFuncNULL(GLenum func, GLint ref, GLuint mask);
 void INTERNAL_GL_APIENTRY glStencilFuncSeparateNULL(GLenum face,
                                                     GLenum func,
@@ -1502,42 +1457,6 @@
                                                   GLenum sfail,
                                                   GLenum dpfail,
                                                   GLenum dppass);
-void INTERNAL_GL_APIENTRY glStencilStrokePathInstancedNVNULL(GLsizei numPaths,
-                                                             GLenum pathNameType,
-                                                             const void *paths,
-                                                             GLuint pathBase,
-                                                             GLint reference,
-                                                             GLuint mask,
-                                                             GLenum transformType,
-                                                             const GLfloat *transformValues);
-void INTERNAL_GL_APIENTRY glStencilStrokePathNVNULL(GLuint path, GLint reference, GLuint mask);
-void INTERNAL_GL_APIENTRY glStencilThenCoverFillPathInstancedNVNULL(GLsizei numPaths,
-                                                                    GLenum pathNameType,
-                                                                    const void *paths,
-                                                                    GLuint pathBase,
-                                                                    GLenum fillMode,
-                                                                    GLuint mask,
-                                                                    GLenum coverMode,
-                                                                    GLenum transformType,
-                                                                    const GLfloat *transformValues);
-void INTERNAL_GL_APIENTRY glStencilThenCoverFillPathNVNULL(GLuint path,
-                                                           GLenum fillMode,
-                                                           GLuint mask,
-                                                           GLenum coverMode);
-void INTERNAL_GL_APIENTRY
-glStencilThenCoverStrokePathInstancedNVNULL(GLsizei numPaths,
-                                            GLenum pathNameType,
-                                            const void *paths,
-                                            GLuint pathBase,
-                                            GLint reference,
-                                            GLuint mask,
-                                            GLenum coverMode,
-                                            GLenum transformType,
-                                            const GLfloat *transformValues);
-void INTERNAL_GL_APIENTRY glStencilThenCoverStrokePathNVNULL(GLuint path,
-                                                             GLint reference,
-                                                             GLuint mask,
-                                                             GLenum coverMode);
 GLboolean INTERNAL_GL_APIENTRY glTestFenceNVNULL(GLuint fence);
 void INTERNAL_GL_APIENTRY glTexBufferNULL(GLenum target, GLenum internalformat, GLuint buffer);
 void INTERNAL_GL_APIENTRY glTexBufferRangeNULL(GLenum target,
diff --git a/src/libANGLE/renderer/gl/renderergl_utils.cpp b/src/libANGLE/renderer/gl/renderergl_utils.cpp
index 273c7aa..9b0f0aa 100644
--- a/src/libANGLE/renderer/gl/renderergl_utils.cpp
+++ b/src/libANGLE/renderer/gl/renderergl_utils.cpp
@@ -1131,6 +1131,10 @@
     extensions->textureCompressionASTCHDRKHR =
         extensions->textureCompressionASTCLDRKHR &&
         functions->hasExtension("GL_KHR_texture_compression_astc_hdr");
+    extensions->textureCompressionSliced3dASTCKHR =
+        (extensions->textureCompressionASTCLDRKHR &&
+         functions->hasExtension("GL_KHR_texture_compression_astc_sliced_3d")) ||
+        extensions->textureCompressionASTCHDRKHR;
     extensions->elementIndexUintOES = functions->standard == STANDARD_GL_DESKTOP ||
                                       functions->isAtLeastGLES(gl::Version(3, 0)) ||
                                       functions->hasGLESExtension("GL_OES_element_index_uint");
@@ -1222,7 +1226,8 @@
     extensions->unpackSubimage     = functions->standard == STANDARD_GL_DESKTOP ||
                                  functions->isAtLeastGLES(gl::Version(3, 0)) ||
                                  functions->hasGLESExtension("GL_EXT_unpack_subimage");
-    extensions->packSubimage = functions->standard == STANDARD_GL_DESKTOP ||
+    extensions->noperspectiveInterpolationNV = functions->isAtLeastGL(gl::Version(3, 0));
+    extensions->packSubimage                 = functions->standard == STANDARD_GL_DESKTOP ||
                                functions->isAtLeastGLES(gl::Version(3, 0)) ||
                                functions->hasGLESExtension("GL_NV_pack_subimage");
     extensions->vertexArrayObjectOES = functions->isAtLeastGL(gl::Version(3, 0)) ||
@@ -1297,22 +1302,15 @@
     extensions->textureMultisample = functions->isAtLeastGL(gl::Version(3, 2)) ||
                                      functions->hasGLExtension("GL_ARB_texture_multisample");
 
-    // NV_path_rendering
-    // We also need interface query which is available in
-    // >= 4.3 core or ARB_interface_query or >= GLES 3.1
-    const bool canEnableGLPathRendering =
-        functions->hasGLExtension("GL_NV_path_rendering") &&
-        (functions->hasGLExtension("GL_ARB_program_interface_query") ||
-         functions->isAtLeastGL(gl::Version(4, 3)));
-
-    const bool canEnableESPathRendering = functions->hasGLESExtension("GL_NV_path_rendering") &&
-                                          functions->isAtLeastGLES(gl::Version(3, 1));
-
-    extensions->pathRendering = canEnableGLPathRendering || canEnableESPathRendering;
-
     extensions->textureSRGBDecode = functions->hasGLExtension("GL_EXT_texture_sRGB_decode") ||
                                     functions->hasGLESExtension("GL_EXT_texture_sRGB_decode");
 
+    // ANGLE treats ETC1 as ETC2 for ES 3.0 and higher because it becomes a core format, and they
+    // are backwards compatible.
+    extensions->compressedETC1RGB8SubTexture =
+        functions->isAtLeastGLES(gl::Version(3, 0)) ||
+        functions->hasGLESExtension("GL_EXT_compressed_ETC1_RGB8_sub_texture");
+
 #if defined(ANGLE_PLATFORM_MACOS) || defined(ANGLE_PLATFORM_MACCATALYST)
     VendorID vendor = GetVendorID(functions);
     if ((IsAMD(vendor) || IsIntel(vendor)) && *maxSupportedESVersion >= gl::Version(3, 0))
@@ -1624,7 +1622,10 @@
     bool limitMaxTextureSize = isIntel && IsLinux() && GetLinuxOSVersion() < OSVersion(5, 0, 0);
     ANGLE_FEATURE_CONDITION(features, limitMaxTextureSizeTo4096,
                             IsAndroid() || limitMaxTextureSize);
-    ANGLE_FEATURE_CONDITION(features, limitMaxMSAASamplesTo4, IsAndroid());
+    // On Apple switchable graphics, GL_MAX_SAMPLES may differ between the GPUs.
+    // 4 is a lowest common denominator that is always supported.
+    ANGLE_FEATURE_CONDITION(features, limitMaxMSAASamplesTo4,
+                            IsAndroid() || (IsApple() && (isIntel || isAMD || isNvidia)));
     ANGLE_FEATURE_CONDITION(features, limitMax3dArrayTextureSizeTo1024, limitMaxTextureSize);
 
     ANGLE_FEATURE_CONDITION(features, allowClearForRobustResourceInit, IsApple());
@@ -1656,6 +1657,14 @@
 
     ANGLE_FEATURE_CONDITION(features, unfoldShortCircuits, IsApple());
 
+    ANGLE_FEATURE_CONDITION(features, emulatePrimitiveRestartFixedIndex,
+                            functions->standard == STANDARD_GL_DESKTOP &&
+                                functions->isAtLeastGL(gl::Version(3, 1)) &&
+                                !functions->isAtLeastGL(gl::Version(4, 3)));
+    ANGLE_FEATURE_CONDITION(
+        features, setPrimitiveRestartFixedIndexForDrawArrays,
+        features->emulatePrimitiveRestartFixedIndex.enabled && IsApple() && isIntel);
+
     ANGLE_FEATURE_CONDITION(features, removeDynamicIndexingOfSwizzledVector,
                             IsApple() || IsAndroid() || IsWindows());
 
@@ -1964,9 +1973,11 @@
         ERR() << "GL call " << call << " generated error " << gl::FmtHex(error) << " in " << file
               << ", " << function << ":" << line << ". ";
 
-        // Check that only one GL error was generated, ClearErrors should have been called first
+        // Check that only one GL error was generated, ClearErrors should have been called first.
+        // Skip GL_CONTEXT_LOST errors, they will be generated continuously and result in an
+        // infinite loop.
         GLenum nextError = functions->getError();
-        while (nextError != GL_NO_ERROR)
+        while (nextError != GL_NO_ERROR && nextError != GL_CONTEXT_LOST)
         {
             ERR() << "Additional GL error " << gl::FmtHex(nextError) << " generated.";
             nextError = functions->getError();
diff --git a/src/libANGLE/renderer/glslang_wrapper_utils.cpp b/src/libANGLE/renderer/glslang_wrapper_utils.cpp
index ffc74a5..1893a2b 100644
--- a/src/libANGLE/renderer/glslang_wrapper_utils.cpp
+++ b/src/libANGLE/renderer/glslang_wrapper_utils.cpp
@@ -55,13 +55,6 @@
 constexpr char kXfbOutMarker[]     = "@@ XFB-OUT @@;";
 constexpr char kXfbBuiltInPrefix[] = "xfbANGLE";
 
-constexpr gl::ShaderMap<const char *> kDefaultUniformNames = {
-    {gl::ShaderType::Vertex, sh::vk::kDefaultUniformsNameVS},
-    {gl::ShaderType::Geometry, sh::vk::kDefaultUniformsNameGS},
-    {gl::ShaderType::Fragment, sh::vk::kDefaultUniformsNameFS},
-    {gl::ShaderType::Compute, sh::vk::kDefaultUniformsNameCS},
-};
-
 template <size_t N>
 constexpr size_t ConstStrLen(const char (&)[N])
 {
@@ -146,49 +139,11 @@
     return true;
 }
 
-// Strip indices from the name.  If there are non-zero indices, return false to indicate that this
-// image uniform doesn't require set/binding.  That is done on index 0.
-bool GetImageNameWithoutIndices(std::string *name)
-{
-    if (name->back() != ']')
-    {
-        return true;
-    }
-
-    if (!UniformNameIsIndexZero(*name, false))
-    {
-        return false;
-    }
-
-    // Strip all indices
-    *name = name->substr(0, name->find('['));
-    return true;
-}
-
 bool MappedSamplerNameNeedsUserDefinedPrefix(const std::string &originalName)
 {
     return originalName.find('.') == std::string::npos;
 }
 
-std::string GetMappedSamplerNameOld(const std::string &originalName)
-{
-    std::string samplerName = gl::ParseResourceName(originalName, nullptr);
-
-    // Samplers in structs are extracted.
-    std::replace(samplerName.begin(), samplerName.end(), '.', '_');
-
-    // Samplers in arrays of structs are also extracted.
-    std::replace(samplerName.begin(), samplerName.end(), '[', '_');
-    samplerName.erase(std::remove(samplerName.begin(), samplerName.end(), ']'), samplerName.end());
-
-    if (MappedSamplerNameNeedsUserDefinedPrefix(originalName))
-    {
-        samplerName = sh::kUserDefinedNamePrefix + samplerName;
-    }
-
-    return samplerName;
-}
-
 template <typename OutputIter, typename ImplicitIter>
 uint32_t CountExplicitOutputs(OutputIter outputsBegin,
                               OutputIter outputsEnd,
@@ -217,10 +172,10 @@
     return &(*infoMap)[varName];
 }
 
-ShaderInterfaceVariableInfo *AddResourceInfo(ShaderInterfaceVariableInfoMap *infoMap,
-                                             const std::string &varName,
-                                             uint32_t descriptorSet,
-                                             uint32_t binding)
+ShaderInterfaceVariableInfo *AddResourceInfoToAllStages(ShaderInterfaceVariableInfoMap *infoMap,
+                                                        const std::string &varName,
+                                                        uint32_t descriptorSet,
+                                                        uint32_t binding)
 {
     gl::ShaderBitSet allStages;
     allStages.set();
@@ -232,6 +187,22 @@
     return info;
 }
 
+ShaderInterfaceVariableInfo *AddResourceInfo(ShaderInterfaceVariableInfoMap *infoMap,
+                                             const std::string &varName,
+                                             uint32_t descriptorSet,
+                                             uint32_t binding,
+                                             const gl::ShaderType shaderType)
+{
+    gl::ShaderBitSet stages;
+    stages.set(shaderType);
+
+    ShaderInterfaceVariableInfo *info = AddShaderInterfaceVariable(infoMap, varName);
+    info->descriptorSet               = descriptorSet;
+    info->binding                     = binding;
+    info->activeStages                = stages;
+    return info;
+}
+
 // Add location information for an in/out variable.
 ShaderInterfaceVariableInfo *AddLocationInfo(ShaderInterfaceVariableInfoMap *infoMap,
                                              const std::string &varName,
@@ -245,11 +216,11 @@
 
     ASSERT(info->descriptorSet == ShaderInterfaceVariableInfo::kInvalid);
     ASSERT(info->binding == ShaderInterfaceVariableInfo::kInvalid);
-    ASSERT(info->location[stage] == ShaderInterfaceVariableInfo::kInvalid);
-    ASSERT(info->component[stage] == ShaderInterfaceVariableInfo::kInvalid);
+    ASSERT(info->location == ShaderInterfaceVariableInfo::kInvalid);
+    ASSERT(info->component == ShaderInterfaceVariableInfo::kInvalid);
 
-    info->location[stage]  = location;
-    info->component[stage] = component;
+    info->location  = location;
+    info->component = component;
     info->activeStages.set(stage);
 
     return info;
@@ -356,8 +327,9 @@
     return result.str();
 }
 
-void GenerateTransformFeedbackEmulationOutputs(const GlslangSourceOptions &options,
+void GenerateTransformFeedbackEmulationOutputs(GlslangSourceOptions &options,
                                                const gl::ProgramState &programState,
+                                               GlslangProgramInterfaceInfo *programInterfaceInfo,
                                                std::string *vertexShader,
                                                ShaderInterfaceVariableInfoMap *variableInfoMapOut)
 {
@@ -368,25 +340,27 @@
         programState.getTransformFeedbackBufferMode() == GL_INTERLEAVED_ATTRIBS;
     const size_t bufferCount = isInterleaved ? 1 : varyings.size();
 
-    const std::string xfbSet = Str(options.uniformsAndXfbDescriptorSetIndex);
+    const std::string xfbSet = Str(programInterfaceInfo->uniformsAndXfbDescriptorSetIndex);
     std::vector<std::string> xfbIndices(bufferCount);
 
     std::string xfbDecl;
 
     for (uint32_t bufferIndex = 0; bufferIndex < bufferCount; ++bufferIndex)
     {
-        const std::string xfbBinding = Str(options.xfbBindingIndexStart + bufferIndex);
+        const std::string xfbBinding = Str(programInterfaceInfo->currentUniformBindingIndex);
         xfbIndices[bufferIndex]      = Str(bufferIndex);
 
-        std::string bufferName = "xfbBuffer" + xfbIndices[bufferIndex];
+        std::string bufferName = GetXfbBufferName(bufferIndex);
 
         xfbDecl += "layout(set = " + xfbSet + ", binding = " + xfbBinding + ") buffer " +
-                   bufferName + " { float xfbOut" + xfbIndices[bufferIndex] + "[]; };\n";
+                   bufferName + " { float xfbOut" + Str(bufferIndex) + "[]; };\n";
 
         // Add this entry to the info map, so we can easily assert that every resource has an entry
         // in this map.
-        AddResourceInfo(variableInfoMapOut, bufferName, options.uniformsAndXfbDescriptorSetIndex,
-                        options.xfbBindingIndexStart + bufferIndex);
+        AddResourceInfo(variableInfoMapOut, bufferName,
+                        programInterfaceInfo->uniformsAndXfbDescriptorSetIndex,
+                        programInterfaceInfo->currentUniformBindingIndex, gl::ShaderType::Vertex);
+        ++programInterfaceInfo->currentUniformBindingIndex;
     }
 
     std::string xfbOut =
@@ -444,7 +418,6 @@
 void GenerateTransformFeedbackExtensionOutputs(const gl::ProgramState &programState,
                                                const gl::ProgramLinkedResources &resources,
                                                std::string *vertexShader,
-                                               ShaderInterfaceVariableInfoMap *variableInfoMapOut,
                                                uint32_t *locationsUsedForXfbExtensionOut)
 {
     const std::vector<gl::TransformFeedbackVarying> &tfVaryings =
@@ -484,6 +457,7 @@
 }
 
 void AssignAttributeLocations(const gl::ProgramState &programState,
+                              gl::ShaderType stage,
                               ShaderInterfaceVariableInfoMap *variableInfoMapOut)
 {
     // Assign attribute locations for the vertex shader.
@@ -492,14 +466,16 @@
         ASSERT(attribute.active);
 
         AddLocationInfo(variableInfoMapOut, attribute.mappedName, attribute.location,
-                        ShaderInterfaceVariableInfo::kInvalid, gl::ShaderType::Vertex);
+                        ShaderInterfaceVariableInfo::kInvalid, stage);
     }
 }
 
 void AssignOutputLocations(const gl::ProgramState &programState,
+                           const gl::ShaderType shaderType,
                            ShaderInterfaceVariableInfoMap *variableInfoMapOut)
 {
     // Assign output locations for the fragment shader.
+    ASSERT(shaderType == gl::ShaderType::Fragment);
     // TODO(syoussefi): Add support for EXT_blend_func_extended.  http://anglebug.com/3385
     const auto &outputLocations                      = programState.getOutputLocations();
     const auto &outputVariables                      = programState.getOutputVariables();
@@ -527,7 +503,7 @@
             }
 
             AddLocationInfo(variableInfoMapOut, outputVar.mappedName, location,
-                            ShaderInterfaceVariableInfo::kInvalid, gl::ShaderType::Fragment);
+                            ShaderInterfaceVariableInfo::kInvalid, shaderType);
         }
     }
 
@@ -536,17 +512,18 @@
     // location 0 to these entries, adding an entry for them here allows us to ASSERT that every
     // shader interface variable is processed during the SPIR-V transformation.  This is done when
     // iterating the ids provided by OpEntryPoint.
-    AddLocationInfo(variableInfoMapOut, "webgl_FragColor", 0, 0, gl::ShaderType::Fragment);
-    AddLocationInfo(variableInfoMapOut, "webgl_FragData", 0, 0, gl::ShaderType::Fragment);
+    AddLocationInfo(variableInfoMapOut, "webgl_FragColor", 0, 0, shaderType);
+    AddLocationInfo(variableInfoMapOut, "webgl_FragData", 0, 0, shaderType);
 }
 
 void AssignVaryingLocations(const GlslangSourceOptions &options,
                             const gl::ProgramState &programState,
                             const gl::ProgramLinkedResources &resources,
-                            uint32_t locationsUsedForXfbExtension,
-                            ShaderInterfaceVariableInfoMap *variableInfoMapOut)
+                            const gl::ShaderType shaderType,
+                            GlslangProgramInterfaceInfo *programInterfaceInfo,
+                            ShaderMapInterfaceVariableInfoMap *variableInfoMapOut)
 {
-    uint32_t locationsUsedForEmulation = locationsUsedForXfbExtension;
+    uint32_t locationsUsedForEmulation = programInterfaceInfo->locationsUsedForXfbExtension;
 
     // Substitute layout and qualifier strings for the position varying added for line raster
     // emulation.
@@ -554,12 +531,9 @@
     {
         uint32_t lineRasterEmulationPositionLocation = locationsUsedForEmulation++;
 
-        for (const gl::ShaderType shaderType : programState.getLinkedShaderStages())
-        {
-            AddLocationInfo(variableInfoMapOut, sh::vk::kLineRasterEmulationPosition,
-                            lineRasterEmulationPositionLocation,
-                            ShaderInterfaceVariableInfo::kInvalid, shaderType);
-        }
+        AddLocationInfo(&(*variableInfoMapOut)[shaderType], sh::vk::kLineRasterEmulationPosition,
+                        lineRasterEmulationPositionLocation, ShaderInterfaceVariableInfo::kInvalid,
+                        shaderType);
     }
 
     // Assign varying locations.
@@ -588,48 +562,46 @@
         //
         // "_uvarStruct" is found through |parentStructMappedName|, with |varying->mappedName|
         // being "_ufield".  In such a case, use |parentStructMappedName|.
-        if (varying.frontVarying.varying)
+        if (varying.frontVarying.varying && (varying.frontVarying.stage == shaderType))
         {
             const std::string &name = varying.isStructField()
                                           ? varying.frontVarying.parentStructMappedName
                                           : varying.frontVarying.varying->mappedName;
-            AddLocationInfo(variableInfoMapOut, name, location, component,
-                            varying.frontVarying.stage);
+            AddLocationInfo(&(*variableInfoMapOut)[varying.frontVarying.stage], name, location,
+                            component, varying.frontVarying.stage);
         }
-        if (varying.backVarying.varying)
+        if (varying.backVarying.varying && (varying.backVarying.stage == shaderType))
         {
             const std::string &name = varying.isStructField()
                                           ? varying.backVarying.parentStructMappedName
                                           : varying.backVarying.varying->mappedName;
-            AddLocationInfo(variableInfoMapOut, name, location, component,
-                            varying.backVarying.stage);
+            AddLocationInfo(&(*variableInfoMapOut)[varying.backVarying.stage], name, location,
+                            component, varying.backVarying.stage);
         }
     }
 
     // Add an entry for inactive varyings.
     const gl::ShaderMap<std::vector<std::string>> &inactiveVaryingMappedNames =
         resources.varyingPacking.getInactiveVaryingMappedNames();
-    for (const gl::ShaderType shaderType : programState.getLinkedShaderStages())
+    for (const std::string &varyingName : inactiveVaryingMappedNames[shaderType])
     {
-        for (const std::string &varyingName : inactiveVaryingMappedNames[shaderType])
+        bool isBuiltin = angle::BeginsWith(varyingName, "gl_");
+        if (isBuiltin)
         {
-            bool isBuiltin = angle::BeginsWith(varyingName, "gl_");
-            if (isBuiltin)
-            {
-                continue;
-            }
-
-            // If name is already in the map, it will automatically have marked all other stages
-            // inactive.
-            if (variableInfoMapOut->find(varyingName) != variableInfoMapOut->end())
-            {
-                continue;
-            }
-
-            // Otherwise, add an entry for it with all locations inactive.
-            ShaderInterfaceVariableInfo *info = &(*variableInfoMapOut)[varyingName];
-            ASSERT(info->location[shaderType] == ShaderInterfaceVariableInfo::kInvalid);
+            continue;
         }
+
+        // If name is already in the map, it will automatically have marked all other stages
+        // inactive.
+        if ((*variableInfoMapOut)[shaderType].find(varyingName) !=
+            (*variableInfoMapOut)[shaderType].end())
+        {
+            continue;
+        }
+
+        // Otherwise, add an entry for it with all locations inactive.
+        ShaderInterfaceVariableInfo *info = &(*variableInfoMapOut)[shaderType][varyingName];
+        ASSERT(info->location == ShaderInterfaceVariableInfo::kInvalid);
     }
 }
 
@@ -638,6 +610,7 @@
 void AssignTransformFeedbackExtensionQualifiers(const gl::ProgramState &programState,
                                                 const gl::ProgramLinkedResources &resources,
                                                 uint32_t locationsUsedForXfbExtension,
+                                                const gl::ShaderType shaderType,
                                                 ShaderInterfaceVariableInfoMap *variableInfoMapOut)
 {
     const std::vector<gl::TransformFeedbackVarying> &tfVaryings =
@@ -683,7 +656,7 @@
             ASSERT(xfbVaryingLocation < locationsUsedForXfbExtension);
 
             AddLocationInfo(variableInfoMapOut, xfbVaryingName, xfbVaryingLocation,
-                            ShaderInterfaceVariableInfo::kInvalid, gl::ShaderType::Vertex);
+                            ShaderInterfaceVariableInfo::kInvalid, shaderType);
             SetXfbInfo(variableInfoMapOut, xfbVaryingName, bufferIndex, currentOffset,
                        currentStride);
         }
@@ -730,70 +703,87 @@
     }
 }
 
-void AssignUniformBindings(const GlslangSourceOptions &options,
-                           gl::ShaderMap<std::string> *shaderSources,
-                           ShaderInterfaceVariableInfoMap *variableInfoMapOut)
+void AssignUniformBindings(GlslangSourceOptions &options,
+                           const gl::ProgramState &programState,
+                           const gl::ShaderType shaderType,
+                           GlslangProgramInterfaceInfo *programInterfaceInfo,
+                           ShaderMapInterfaceVariableInfoMap *variableInfoMapOut)
 {
-    // Assign binding to the default uniforms block of each shader stage.
-    uint32_t bindingIndex = 0;
-    for (const gl::ShaderType shaderType : gl::AllShaderTypes())
+    if (programState.getAttachedShader(shaderType) ||
+        programState.getProgramExecutable().hasLinkedShaderStage(shaderType))
     {
-        const std::string &shaderSource = (*shaderSources)[shaderType];
-        if (!shaderSource.empty())
-        {
-            AddResourceInfo(variableInfoMapOut, kDefaultUniformNames[shaderType],
-                            options.uniformsAndXfbDescriptorSetIndex, bindingIndex);
-            ++bindingIndex;
-        }
-    }
+        AddResourceInfo(&(*variableInfoMapOut)[shaderType], kDefaultUniformNames[shaderType],
+                        programInterfaceInfo->uniformsAndXfbDescriptorSetIndex,
+                        programInterfaceInfo->currentUniformBindingIndex, shaderType);
+        ++programInterfaceInfo->currentUniformBindingIndex;
 
-    // Assign binding to the driver uniforms block
-    AddResourceInfo(variableInfoMapOut, sh::vk::kDriverUniformsBlockName,
-                    options.driverUniformsDescriptorSetIndex, 0);
+        // Assign binding to the driver uniforms block
+        AddResourceInfoToAllStages(&(*variableInfoMapOut)[shaderType],
+                                   sh::vk::kDriverUniformsBlockName,
+                                   programInterfaceInfo->driverUniformsDescriptorSetIndex, 0);
+    }
 }
 
-uint32_t AssignInterfaceBlockBindings(const GlslangSourceOptions &options,
-                                      const std::vector<gl::InterfaceBlock> &blocks,
-                                      uint32_t bindingStart,
-                                      ShaderInterfaceVariableInfoMap *variableInfoMapOut)
+// TODO: http://anglebug.com/4512: Need to combine descriptor set bindings across
+// shader stages.
+void AssignInterfaceBlockBindings(GlslangSourceOptions &options,
+                                  const gl::ProgramState &programState,
+                                  const std::vector<gl::InterfaceBlock> &blocks,
+                                  const gl::ShaderType shaderType,
+                                  GlslangProgramInterfaceInfo *programInterfaceInfo,
+                                  ShaderMapInterfaceVariableInfoMap *variableInfoMapOut)
 {
-    uint32_t bindingIndex = bindingStart;
     for (const gl::InterfaceBlock &block : blocks)
     {
         if (!block.isArray || block.arrayElement == 0)
         {
-            AddResourceInfo(variableInfoMapOut, block.mappedName,
-                            options.shaderResourceDescriptorSetIndex, bindingIndex);
-            ++bindingIndex;
+            // TODO: http://anglebug.com/4523: All blocks should be active
+            if (programState.getProgramExecutable().hasLinkedShaderStage(shaderType) &&
+                block.isActive(shaderType))
+            {
+                AddResourceInfo(&(*variableInfoMapOut)[shaderType], block.mappedName,
+                                programInterfaceInfo->shaderResourceDescriptorSetIndex,
+                                programInterfaceInfo->currentShaderResourceBindingIndex,
+                                shaderType);
+                ++programInterfaceInfo->currentShaderResourceBindingIndex;
+            }
         }
     }
-
-    return bindingIndex;
 }
 
-uint32_t AssignAtomicCounterBufferBindings(const GlslangSourceOptions &options,
-                                           const std::vector<gl::AtomicCounterBuffer> &buffers,
-                                           uint32_t bindingStart,
-                                           ShaderInterfaceVariableInfoMap *variableInfoMapOut)
+// TODO: http://anglebug.com/4512: Need to combine descriptor set bindings across
+// shader stages.
+void AssignAtomicCounterBufferBindings(GlslangSourceOptions &options,
+                                       const gl::ProgramState &programState,
+                                       const std::vector<gl::AtomicCounterBuffer> &buffers,
+                                       const gl::ShaderType shaderType,
+                                       GlslangProgramInterfaceInfo *programInterfaceInfo,
+                                       ShaderMapInterfaceVariableInfoMap *variableInfoMapOut)
 {
     if (buffers.size() == 0)
     {
-        return bindingStart;
+        return;
     }
 
-    AddResourceInfo(variableInfoMapOut, sh::vk::kAtomicCountersBlockName,
-                    options.shaderResourceDescriptorSetIndex, bindingStart);
-
-    return bindingStart + 1;
+    if (programState.getProgramExecutable().hasLinkedShaderStage(shaderType))
+    {
+        AddResourceInfo(&(*variableInfoMapOut)[shaderType], sh::vk::kAtomicCountersBlockName,
+                        programInterfaceInfo->shaderResourceDescriptorSetIndex,
+                        programInterfaceInfo->currentShaderResourceBindingIndex, shaderType);
+        ++programInterfaceInfo->currentShaderResourceBindingIndex;
+    }
 }
 
-uint32_t AssignImageBindings(const GlslangSourceOptions &options,
-                             const std::vector<gl::LinkedUniform> &uniforms,
-                             const gl::RangeUI &imageUniformRange,
-                             uint32_t bindingStart,
-                             ShaderInterfaceVariableInfoMap *variableInfoMapOut)
+// TODO: http://anglebug.com/4512: Need to combine descriptor set bindings across
+// shader stages.
+void AssignImageBindings(GlslangSourceOptions &options,
+                         const gl::ProgramState &programState,
+                         const std::vector<gl::LinkedUniform> &uniforms,
+                         const gl::RangeUI &imageUniformRange,
+                         const gl::ShaderType shaderType,
+                         GlslangProgramInterfaceInfo *programInterfaceInfo,
+                         ShaderMapInterfaceVariableInfoMap *variableInfoMapOut)
 {
-    uint32_t bindingIndex = bindingStart;
     for (unsigned int uniformIndex : imageUniformRange)
     {
         const gl::LinkedUniform &imageUniform = uniforms[uniformIndex];
@@ -801,46 +791,52 @@
         std::string name = imageUniform.mappedName;
         if (GetImageNameWithoutIndices(&name))
         {
-            AddResourceInfo(variableInfoMapOut, name, options.shaderResourceDescriptorSetIndex,
-                            bindingIndex);
+            if (programState.getProgramExecutable().hasLinkedShaderStage(shaderType))
+            {
+                AddResourceInfo(&(*variableInfoMapOut)[shaderType], name,
+                                programInterfaceInfo->shaderResourceDescriptorSetIndex,
+                                programInterfaceInfo->currentShaderResourceBindingIndex,
+                                shaderType);
+                ++programInterfaceInfo->currentShaderResourceBindingIndex;
+            }
         }
-        ++bindingIndex;
     }
-
-    return bindingIndex;
 }
 
-void AssignNonTextureBindings(const GlslangSourceOptions &options,
+void AssignNonTextureBindings(GlslangSourceOptions &options,
                               const gl::ProgramState &programState,
-                              ShaderInterfaceVariableInfoMap *variableInfoMapOut)
+                              const gl::ShaderType shaderType,
+                              GlslangProgramInterfaceInfo *programInterfaceInfo,
+                              ShaderMapInterfaceVariableInfoMap *variableInfoMapOut)
 {
-    uint32_t bindingStart = 0;
-
     const std::vector<gl::InterfaceBlock> &uniformBlocks = programState.getUniformBlocks();
-    bindingStart =
-        AssignInterfaceBlockBindings(options, uniformBlocks, bindingStart, variableInfoMapOut);
+    AssignInterfaceBlockBindings(options, programState, uniformBlocks, shaderType,
+                                 programInterfaceInfo, variableInfoMapOut);
 
     const std::vector<gl::InterfaceBlock> &storageBlocks = programState.getShaderStorageBlocks();
-    bindingStart =
-        AssignInterfaceBlockBindings(options, storageBlocks, bindingStart, variableInfoMapOut);
+    AssignInterfaceBlockBindings(options, programState, storageBlocks, shaderType,
+                                 programInterfaceInfo, variableInfoMapOut);
 
     const std::vector<gl::AtomicCounterBuffer> &atomicCounterBuffers =
         programState.getAtomicCounterBuffers();
-    bindingStart = AssignAtomicCounterBufferBindings(options, atomicCounterBuffers, bindingStart,
-                                                     variableInfoMapOut);
+    AssignAtomicCounterBufferBindings(options, programState, atomicCounterBuffers, shaderType,
+                                      programInterfaceInfo, variableInfoMapOut);
 
     const std::vector<gl::LinkedUniform> &uniforms = programState.getUniforms();
     const gl::RangeUI &imageUniformRange           = programState.getImageUniformRange();
-    bindingStart =
-        AssignImageBindings(options, uniforms, imageUniformRange, bindingStart, variableInfoMapOut);
+    AssignImageBindings(options, programState, uniforms, imageUniformRange, shaderType,
+                        programInterfaceInfo, variableInfoMapOut);
 }
 
-void AssignTextureBindings(const GlslangSourceOptions &options,
+// TODO: http://anglebug.com/4512: Need to combine descriptor set bindings across
+// shader stages.
+void AssignTextureBindings(GlslangSourceOptions &options,
                            const gl::ProgramState &programState,
-                           ShaderInterfaceVariableInfoMap *variableInfoMapOut)
+                           const gl::ShaderType shaderType,
+                           GlslangProgramInterfaceInfo *programInterfaceInfo,
+                           ShaderMapInterfaceVariableInfoMap *variableInfoMapOut)
 {
     // Assign textures to a descriptor set and binding.
-    uint32_t bindingIndex                          = 0;
     const std::vector<gl::LinkedUniform> &uniforms = programState.getUniforms();
 
     for (unsigned int uniformIndex : programState.getSamplerUniformRange())
@@ -860,11 +856,16 @@
                                                 ? GetMappedSamplerNameOld(samplerUniform.name)
                                                 : GlslangGetMappedSamplerName(samplerUniform.name);
 
-            AddResourceInfo(variableInfoMapOut, samplerName, options.textureDescriptorSetIndex,
-                            bindingIndex);
+            // TODO: http://anglebug.com/4523: All uniforms should be active
+            if (programState.getProgramExecutable().hasLinkedShaderStage(shaderType) &&
+                samplerUniform.isActive(shaderType))
+            {
+                AddResourceInfo(&(*variableInfoMapOut)[shaderType], samplerName,
+                                programInterfaceInfo->textureDescriptorSetIndex,
+                                programInterfaceInfo->currentTextureBindingIndex, shaderType);
+                ++programInterfaceInfo->currentTextureBindingIndex;
+            }
         }
-
-        ++bindingIndex;
     }
 }
 
@@ -977,6 +978,7 @@
 {
   public:
     SpirvTransformer(const std::vector<uint32_t> &spirvBlobIn,
+                     bool removeEarlyFragmentTestsOptimization,
                      const ShaderInterfaceVariableInfoMap &variableInfoMap,
                      gl::ShaderType shaderType,
                      SpirvBlob *spirvBlobOut)
@@ -988,8 +990,8 @@
     {
         gl::ShaderBitSet allStages;
         allStages.set();
-
-        mBuiltinVariableInfo.activeStages = allStages;
+        mRemoveEarlyFragmentTestsOptimization = removeEarlyFragmentTestsOptimization;
+        mBuiltinVariableInfo.activeStages     = allStages;
     }
 
     bool transform();
@@ -1027,6 +1029,7 @@
     bool transformDecorate(const uint32_t *instruction, size_t wordCount);
     bool transformTypePointer(const uint32_t *instruction, size_t wordCount);
     bool transformVariable(const uint32_t *instruction, size_t wordCount);
+    bool transformExecutionMode(const uint32_t *instruction, size_t wordCount);
 
     // Any other instructions:
     size_t copyInstruction(const uint32_t *instruction, size_t wordCount);
@@ -1037,6 +1040,8 @@
     const gl::ShaderType mShaderType;
     bool mHasTransformFeedbackOutput;
 
+    bool mRemoveEarlyFragmentTestsOptimization;
+
     // Input shader variable info map:
     const ShaderInterfaceVariableInfoMap &mVariableInfoMap;
     ShaderInterfaceVariableInfo mBuiltinVariableInfo;
@@ -1236,6 +1241,9 @@
             case spv::OpVariable:
                 transformed = transformVariable(instruction, wordCount);
                 break;
+            case spv::OpExecutionMode:
+                transformed = transformExecutionMode(instruction, wordCount);
+                break;
             default:
                 break;
         }
@@ -1410,7 +1418,7 @@
     switch (decoration)
     {
         case spv::DecorationLocation:
-            newDecorationValue = info->location[mShaderType];
+            newDecorationValue = info->location;
             break;
         case spv::DecorationBinding:
             newDecorationValue = info->binding;
@@ -1440,13 +1448,13 @@
     }
 
     // Add component decoration, if any.
-    if (info->component[mShaderType] != ShaderInterfaceVariableInfo::kInvalid)
+    if (info->component != ShaderInterfaceVariableInfo::kInvalid)
     {
         // Copy the location decoration declaration and modify it to contain the Component
         // decoration.
         const size_t instOffset                         = copyInstruction(instruction, wordCount);
         (*mSpirvBlobOut)[instOffset + kDecorationIndex] = spv::DecorationComponent;
-        (*mSpirvBlobOut)[instOffset + kDecorationValueIndex] = info->component[mShaderType];
+        (*mSpirvBlobOut)[instOffset + kDecorationValueIndex] = info->component;
     }
 
     // Add Xfb decorations, if any.
@@ -1713,6 +1721,22 @@
     return true;
 }
 
+bool SpirvTransformer::transformExecutionMode(const uint32_t *instruction, size_t wordCount)
+{
+    // SPIR-V 1.0 Section 3.32 Instructions, OpAccessChain, OpInBoundsAccessChain, OpPtrAccessChain,
+    // OpInBoundsPtrAccessChain
+    constexpr size_t kModeIndex  = 2;
+    const uint32_t executionMode = instruction[kModeIndex];
+
+    if (executionMode == spv::ExecutionModeEarlyFragmentTests &&
+        mRemoveEarlyFragmentTestsOptimization)
+    {
+        // skip the copy
+        return true;
+    }
+    return false;
+}
+
 size_t SpirvTransformer::copyInstruction(const uint32_t *instruction, size_t wordCount)
 {
     size_t instructionOffset = mSpirvBlobOut->size();
@@ -1728,11 +1752,7 @@
 
 const uint32_t ShaderInterfaceVariableInfo::kInvalid;
 
-ShaderInterfaceVariableInfo::ShaderInterfaceVariableInfo()
-{
-    location.fill(kInvalid);
-    component.fill(kInvalid);
-}
+ShaderInterfaceVariableInfo::ShaderInterfaceVariableInfo() {}
 
 void GlslangInitialize()
 {
@@ -1746,6 +1766,44 @@
     ASSERT(result != 0);
 }
 
+// Strip indices from the name.  If there are non-zero indices, return false to indicate that this
+// image uniform doesn't require set/binding.  That is done on index 0.
+bool GetImageNameWithoutIndices(std::string *name)
+{
+    if (name->back() != ']')
+    {
+        return true;
+    }
+
+    if (!UniformNameIsIndexZero(*name, false))
+    {
+        return false;
+    }
+
+    // Strip all indices
+    *name = name->substr(0, name->find('['));
+    return true;
+}
+
+std::string GetMappedSamplerNameOld(const std::string &originalName)
+{
+    std::string samplerName = gl::ParseResourceName(originalName, nullptr);
+
+    // Samplers in structs are extracted.
+    std::replace(samplerName.begin(), samplerName.end(), '.', '_');
+
+    // Samplers in arrays of structs are also extracted.
+    std::replace(samplerName.begin(), samplerName.end(), '[', '_');
+    samplerName.erase(std::remove(samplerName.begin(), samplerName.end(), ']'), samplerName.end());
+
+    if (MappedSamplerNameNeedsUserDefinedPrefix(originalName))
+    {
+        samplerName = sh::kUserDefinedNamePrefix + samplerName;
+    }
+
+    return samplerName;
+}
+
 std::string GlslangGetMappedSamplerName(const std::string &originalName)
 {
     std::string samplerName = originalName;
@@ -1781,25 +1839,76 @@
     return samplerName;
 }
 
-void GlslangGetShaderSource(const GlslangSourceOptions &options,
+std::string GetXfbBufferName(const uint32_t bufferIndex)
+{
+    return "xfbBuffer" + Str(bufferIndex);
+}
+
+void GlslangAssignLocations(GlslangSourceOptions &options,
                             const gl::ProgramState &programState,
                             const gl::ProgramLinkedResources &resources,
-                            gl::ShaderMap<std::string> *shaderSourcesOut,
-                            ShaderInterfaceVariableInfoMap *variableInfoMapOut)
+                            const gl::ShaderType shaderType,
+                            GlslangProgramInterfaceInfo *programInterfaceInfo,
+                            ShaderMapInterfaceVariableInfoMap *variableInfoMapOut)
 {
-    variableInfoMapOut->clear();
+    const gl::ProgramExecutable &executable = programState.getProgramExecutable();
 
-    uint32_t locationsUsedForXfbExtension = 0;
+    // Assign outputs to the fragment shader, if any.
+    if ((shaderType == gl::ShaderType::Fragment) &&
+        (programState.getAttachedShader(gl::ShaderType::Fragment) ||
+         executable.hasLinkedShaderStage(gl::ShaderType::Fragment)))
+    {
+        AssignOutputLocations(programState, gl::ShaderType::Fragment,
+                              &(*variableInfoMapOut)[gl::ShaderType::Fragment]);
+    }
 
+    // Assign attributes to the vertex shader, if any.
+    if ((shaderType == gl::ShaderType::Vertex) &&
+        (programState.getAttachedShader(gl::ShaderType::Vertex) ||
+         executable.hasLinkedShaderStage(gl::ShaderType::Vertex)))
+    {
+        AssignAttributeLocations(programState, gl::ShaderType::Vertex,
+                                 &(*variableInfoMapOut)[gl::ShaderType::Vertex]);
+    }
+
+    if (!programState.getAttachedShader(gl::ShaderType::Compute) &&
+        !executable.hasLinkedShaderStage(gl::ShaderType::Compute))
+    {
+        // Assign varying locations.
+        AssignVaryingLocations(options, programState, resources, shaderType, programInterfaceInfo,
+                               variableInfoMapOut);
+
+        if (!programState.getLinkedTransformFeedbackVaryings().empty() &&
+            options.supportsTransformFeedbackExtension && (shaderType == gl::ShaderType::Vertex))
+        {
+            AssignTransformFeedbackExtensionQualifiers(
+                programState, resources, programInterfaceInfo->locationsUsedForXfbExtension,
+                gl::ShaderType::Vertex, &(*variableInfoMapOut)[gl::ShaderType::Vertex]);
+        }
+    }
+
+    AssignUniformBindings(options, programState, shaderType, programInterfaceInfo,
+                          variableInfoMapOut);
+    AssignTextureBindings(options, programState, shaderType, programInterfaceInfo,
+                          variableInfoMapOut);
+    AssignNonTextureBindings(options, programState, shaderType, programInterfaceInfo,
+                             variableInfoMapOut);
+}
+
+void GlslangGetShaderSource(GlslangSourceOptions &options,
+                            const gl::ProgramState &programState,
+                            const gl::ProgramLinkedResources &resources,
+                            GlslangProgramInterfaceInfo *programInterfaceInfo,
+                            gl::ShaderMap<std::string> *shaderSourcesOut,
+                            ShaderMapInterfaceVariableInfoMap *variableInfoMapOut)
+{
     for (const gl::ShaderType shaderType : gl::AllShaderTypes())
     {
         gl::Shader *glShader            = programState.getAttachedShader(shaderType);
         (*shaderSourcesOut)[shaderType] = glShader ? glShader->getTranslatedSource() : "";
     }
 
-    std::string *vertexSource         = &(*shaderSourcesOut)[gl::ShaderType::Vertex];
-    const std::string &fragmentSource = (*shaderSourcesOut)[gl::ShaderType::Fragment];
-    const std::string &computeSource  = (*shaderSourcesOut)[gl::ShaderType::Compute];
+    std::string *vertexSource = &(*shaderSourcesOut)[gl::ShaderType::Vertex];
 
     // Write transform feedback output code.
     if (!vertexSource->empty())
@@ -1812,74 +1921,71 @@
         {
             if (options.supportsTransformFeedbackExtension)
             {
-                GenerateTransformFeedbackExtensionOutputs(programState, resources, vertexSource,
-                                                          variableInfoMapOut,
-                                                          &locationsUsedForXfbExtension);
+                GenerateTransformFeedbackExtensionOutputs(
+                    programState, resources, vertexSource,
+                    &programInterfaceInfo->locationsUsedForXfbExtension);
             }
             else if (options.emulateTransformFeedback)
             {
-                GenerateTransformFeedbackEmulationOutputs(options, programState, vertexSource,
-                                                          variableInfoMapOut);
+                GenerateTransformFeedbackEmulationOutputs(
+                    options, programState, programInterfaceInfo, vertexSource,
+                    &(*variableInfoMapOut)[gl::ShaderType::Vertex]);
             }
         }
     }
 
-    // Assign outputs to the fragment shader, if any.
-    if (!fragmentSource.empty())
+    for (const gl::ShaderType shaderType :
+         programState.getProgramExecutable().getLinkedShaderStages())
     {
-        AssignOutputLocations(programState, variableInfoMapOut);
-    }
-
-    // Assign attributes to the vertex shader, if any.
-    if (!vertexSource->empty())
-    {
-        AssignAttributeLocations(programState, variableInfoMapOut);
-    }
-
-    if (computeSource.empty())
-    {
-        // Assign varying locations.
-        AssignVaryingLocations(options, programState, resources, locationsUsedForXfbExtension,
+        GlslangAssignLocations(options, programState, resources, shaderType, programInterfaceInfo,
                                variableInfoMapOut);
-
-        if (!programState.getLinkedTransformFeedbackVaryings().empty() &&
-            options.supportsTransformFeedbackExtension)
-        {
-            AssignTransformFeedbackExtensionQualifiers(
-                programState, resources, locationsUsedForXfbExtension, variableInfoMapOut);
-        }
     }
-
-    AssignUniformBindings(options, shaderSourcesOut, variableInfoMapOut);
-    AssignTextureBindings(options, programState, variableInfoMapOut);
-    AssignNonTextureBindings(options, programState, variableInfoMapOut);
 }
 
-angle::Result GlslangGetShaderSpirvCode(GlslangErrorCallback callback,
-                                        const gl::Caps &glCaps,
-                                        const gl::ShaderMap<std::string> &shaderSources,
+angle::Result GlslangTransformSpirvCode(const GlslangErrorCallback &callback,
+                                        const gl::ShaderType shaderType,
+                                        bool removeEarlyFragmentTestsOptimization,
                                         const ShaderInterfaceVariableInfoMap &variableInfoMap,
-                                        gl::ShaderMap<SpirvBlob> *spirvBlobsOut)
+                                        const SpirvBlob &initialSpirvBlob,
+                                        SpirvBlob *spirvBlobOut)
 {
-    gl::ShaderMap<std::vector<uint32_t>> initialSpirvBlobs;
-    ANGLE_TRY(GetShaderSpirvCode(callback, glCaps, shaderSources, &initialSpirvBlobs));
+    if (initialSpirvBlob.empty())
+    {
+        return angle::Result::Continue;
+    }
 
     // Transform the SPIR-V code by assigning location/set/binding values.
+    SpirvTransformer transformer(initialSpirvBlob, removeEarlyFragmentTestsOptimization,
+                                 variableInfoMap, shaderType, spirvBlobOut);
+    ANGLE_GLSLANG_CHECK(callback, transformer.transform(), GlslangError::InvalidSpirv);
+
+    ASSERT(ValidateSpirv(*spirvBlobOut));
+
+    return angle::Result::Continue;
+}
+
+angle::Result GlslangGetShaderSpirvCode(const GlslangErrorCallback &callback,
+                                        const gl::Caps &glCaps,
+                                        const gl::ShaderMap<std::string> &shaderSources,
+                                        const ShaderMapInterfaceVariableInfoMap &variableInfoMap,
+                                        gl::ShaderMap<SpirvBlob> *spirvBlobsOut)
+{
+    gl::ShaderMap<SpirvBlob> initialSpirvBlobs;
+    ANGLE_TRY(GetShaderSpirvCode(callback, glCaps, shaderSources, &initialSpirvBlobs));
+
     for (const gl::ShaderType shaderType : gl::AllShaderTypes())
     {
-        const std::vector<uint32_t> initialSpirvBlob = initialSpirvBlobs[shaderType];
-
-        if (initialSpirvBlob.empty())
+        // we pass in false here to skip modifications related to  early fragment tests
+        // optimizations and line rasterization. These are done in the initProgram time since they
+        // are related to context state. We must keep original untouched spriv blobs here because we
+        // do not have ability to add back in at initProgram time.
+        angle::Result status =
+            GlslangTransformSpirvCode(callback, shaderType, false, variableInfoMap[shaderType],
+                                      initialSpirvBlobs[shaderType], &(*spirvBlobsOut)[shaderType]);
+        if (status != angle::Result::Continue)
         {
-            continue;
+            return status;
         }
-
-        SpirvBlob *spirvBlob = &(*spirvBlobsOut)[shaderType];
-
-        SpirvTransformer transformer(initialSpirvBlob, variableInfoMap, shaderType, spirvBlob);
-        ANGLE_GLSLANG_CHECK(callback, transformer.transform(), GlslangError::InvalidSpirv);
-
-        ASSERT(ValidateSpirv(*spirvBlob));
     }
 
     return angle::Result::Continue;
diff --git a/src/libANGLE/renderer/glslang_wrapper_utils.h b/src/libANGLE/renderer/glslang_wrapper_utils.h
index 3f817b0..5163592 100644
--- a/src/libANGLE/renderer/glslang_wrapper_utils.h
+++ b/src/libANGLE/renderer/glslang_wrapper_utils.h
@@ -21,20 +21,32 @@
     InvalidSpirv,
 };
 
-struct GlslangSourceOptions
+constexpr gl::ShaderMap<const char *> kDefaultUniformNames = {
+    {gl::ShaderType::Vertex, sh::vk::kDefaultUniformsNameVS},
+    {gl::ShaderType::Geometry, sh::vk::kDefaultUniformsNameGS},
+    {gl::ShaderType::Fragment, sh::vk::kDefaultUniformsNameFS},
+    {gl::ShaderType::Compute, sh::vk::kDefaultUniformsNameCS},
+};
+
+struct GlslangProgramInterfaceInfo
 {
     // Uniforms set index:
-    uint32_t uniformsAndXfbDescriptorSetIndex = 0;
+    uint32_t uniformsAndXfbDescriptorSetIndex;
+    uint32_t currentUniformBindingIndex;
     // Textures set index:
-    uint32_t textureDescriptorSetIndex = 1;
+    uint32_t textureDescriptorSetIndex;
+    uint32_t currentTextureBindingIndex;
     // Other shader resources set index:
-    uint32_t shaderResourceDescriptorSetIndex = 2;
+    uint32_t shaderResourceDescriptorSetIndex;
+    uint32_t currentShaderResourceBindingIndex;
     // ANGLE driver uniforms set index:
-    uint32_t driverUniformsDescriptorSetIndex = 3;
+    uint32_t driverUniformsDescriptorSetIndex;
 
-    // Binding index start for transform feedback buffers:
-    uint32_t xfbBindingIndexStart = 16;
+    uint32_t locationsUsedForXfbExtension;
+};
 
+struct GlslangSourceOptions
+{
     bool useOldRewriteStructSamplers        = false;
     bool supportsTransformFeedbackExtension = false;
     bool emulateTransformFeedback           = false;
@@ -61,8 +73,8 @@
     // variables that share the same name, such as a vertex attribute and a fragment output.  They
     // will share this object since they have the same name, but will find possibly different
     // locations in their respective slots.
-    gl::ShaderMap<uint32_t> location;
-    gl::ShaderMap<uint32_t> component;
+    uint32_t location  = kInvalid;
+    uint32_t component = kInvalid;
     // The stages this shader interface variable is active.
     gl::ShaderBitSet activeStages;
     // Used for transform feedback extension to decorate vertex shader output.
@@ -71,28 +83,50 @@
     uint32_t xfbStride = kInvalid;
 };
 
+// TODO: http://anglebug.com/4524: Need a different hash key than a string, since
+// that's slow to calculate.
 using ShaderInterfaceVariableInfoMap = std::unordered_map<std::string, ShaderInterfaceVariableInfo>;
+using ShaderMapInterfaceVariableInfoMap = gl::ShaderMap<ShaderInterfaceVariableInfoMap>;
 
 void GlslangInitialize();
 void GlslangRelease();
 
+bool GetImageNameWithoutIndices(std::string *name);
+
 // Get the mapped sampler name after the soure is transformed by GlslangGetShaderSource()
+std::string GetMappedSamplerNameOld(const std::string &originalName);
 std::string GlslangGetMappedSamplerName(const std::string &originalName);
+std::string GetXfbBufferName(const uint32_t bufferIndex);
+
+void GlslangAssignLocations(GlslangSourceOptions &options,
+                            const gl::ProgramState &programState,
+                            const gl::ProgramLinkedResources &resources,
+                            const gl::ShaderType shaderType,
+                            GlslangProgramInterfaceInfo *programInterfaceInfo,
+                            gl::ShaderMap<ShaderInterfaceVariableInfoMap> *variableInfoMapOut);
 
 // Transform the source to include actual binding points for various shader resources (textures,
 // buffers, xfb, etc).  For some variables, these values are instead output to the variableInfoMap
 // to be set during a SPIR-V transformation.  This is a transitory step towards moving all variables
 // to this map, at which point GlslangGetShaderSpirvCode will also be called by this function.
-void GlslangGetShaderSource(const GlslangSourceOptions &options,
+void GlslangGetShaderSource(GlslangSourceOptions &options,
                             const gl::ProgramState &programState,
                             const gl::ProgramLinkedResources &resources,
+                            GlslangProgramInterfaceInfo *programInterfaceInfo,
                             gl::ShaderMap<std::string> *shaderSourcesOut,
-                            ShaderInterfaceVariableInfoMap *variableInfoMapOut);
+                            ShaderMapInterfaceVariableInfoMap *variableInfoMapOut);
 
-angle::Result GlslangGetShaderSpirvCode(GlslangErrorCallback callback,
+angle::Result GlslangTransformSpirvCode(const GlslangErrorCallback &callback,
+                                        const gl::ShaderType shaderType,
+                                        bool removeEarlyFragmentTestsOptimization,
+                                        const ShaderInterfaceVariableInfoMap &variableInfoMap,
+                                        const SpirvBlob &initialSpirvBlob,
+                                        SpirvBlob *spirvBlobOut);
+
+angle::Result GlslangGetShaderSpirvCode(const GlslangErrorCallback &callback,
                                         const gl::Caps &glCaps,
                                         const gl::ShaderMap<std::string> &shaderSources,
-                                        const ShaderInterfaceVariableInfoMap &variableInfoMap,
+                                        const ShaderMapInterfaceVariableInfoMap &variableInfoMap,
                                         gl::ShaderMap<SpirvBlob> *spirvBlobsOut);
 
 }  // namespace rx
diff --git a/src/libANGLE/renderer/load_functions_data.json b/src/libANGLE/renderer/load_functions_data.json
index bd55700..4b443ea 100644
--- a/src/libANGLE/renderer/load_functions_data.json
+++ b/src/libANGLE/renderer/load_functions_data.json
@@ -12,6 +12,11 @@
       "GL_UNSIGNED_BYTE": "LoadToNative<GLbyte, 3>"
     }
   },
+  "GL_SR8_EXT": {
+    "R8_UNORM_SRGB": {
+      "GL_UNSIGNED_BYTE": "LoadToNative<GLbyte, 1>"
+    }
+  },
   "GL_RGBA8I": {
     "R8G8B8A8_SINT": {
       "GL_BYTE": "LoadToNative<GLbyte, 4>"
diff --git a/src/libANGLE/renderer/load_functions_table_autogen.cpp b/src/libANGLE/renderer/load_functions_table_autogen.cpp
index f577bb8..5294f4d 100644
--- a/src/libANGLE/renderer/load_functions_table_autogen.cpp
+++ b/src/libANGLE/renderer/load_functions_table_autogen.cpp
@@ -3066,6 +3066,18 @@
     }
 }
 
+LoadImageFunctionInfo SR8_EXT_to_R8_UNORM_SRGB(GLenum type)
+{
+    switch (type)
+    {
+        case GL_UNSIGNED_BYTE:
+            return LoadImageFunctionInfo(LoadToNative<GLbyte, 1>, false);
+        default:
+            UNREACHABLE();
+            return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+    }
+}
+
 LoadImageFunctionInfo SRGB8_to_R8G8B8A8_UNORM_SRGB(GLenum type)
 {
     switch (type)
@@ -4437,6 +4449,17 @@
             return RGBA8_SSCALED_ANGLEX_to_default;
         case GL_RGBA8_USCALED_ANGLEX:
             return RGBA8_USCALED_ANGLEX_to_default;
+        case GL_SR8_EXT:
+        {
+            switch (angleFormat)
+            {
+                case FormatID::R8_UNORM_SRGB:
+                    return SR8_EXT_to_R8_UNORM_SRGB;
+                default:
+                    break;
+            }
+            break;
+        }
         case GL_SRGB8:
         {
             switch (angleFormat)
diff --git a/src/libANGLE/renderer/metal/ContextMtl.h b/src/libANGLE/renderer/metal/ContextMtl.h
index 13c9dda..03872a8 100644
--- a/src/libANGLE/renderer/metal/ContextMtl.h
+++ b/src/libANGLE/renderer/metal/ContextMtl.h
@@ -187,9 +187,6 @@
     // Program Pipeline object creation
     ProgramPipelineImpl *createProgramPipeline(const gl::ProgramPipelineState &data) override;
 
-    // Path object creation
-    std::vector<PathImpl *> createPaths(GLsizei) override;
-
     // Memory object creation.
     MemoryObjectImpl *createMemoryObject() override;
 
diff --git a/src/libANGLE/renderer/metal/ContextMtl.mm b/src/libANGLE/renderer/metal/ContextMtl.mm
index 5813f04..80dee57 100644
--- a/src/libANGLE/renderer/metal/ContextMtl.mm
+++ b/src/libANGLE/renderer/metal/ContextMtl.mm
@@ -718,8 +718,6 @@
                 break;
             case gl::State::DIRTY_BIT_COVERAGE_MODULATION:
                 break;
-            case gl::State::DIRTY_BIT_PATH_RENDERING:
-                break;
             case gl::State::DIRTY_BIT_FRAMEBUFFER_SRGB:
                 break;
             case gl::State::DIRTY_BIT_CURRENT_VALUES:
@@ -866,13 +864,6 @@
     return nullptr;
 }
 
-// Path object creation
-std::vector<PathImpl *> ContextMtl::createPaths(GLsizei)
-{
-    UNIMPLEMENTED();
-    return std::vector<PathImpl *>();
-}
-
 // Memory object creation.
 MemoryObjectImpl *ContextMtl::createMemoryObject()
 {
@@ -1546,8 +1537,8 @@
     const gl::State &glState   = mState;
     const gl::Program *program = glState.getProgram();
 
-    const gl::ActiveTexturePointerArray &textures = glState.getActiveTexturesCache();
-    const gl::ActiveTextureMask &activeTextures   = program->getActiveSamplersMask();
+    const gl::ActiveTexturesCache &textures     = glState.getActiveTexturesCache();
+    const gl::ActiveTextureMask &activeTextures = program->getExecutable().getActiveSamplersMask();
 
     for (size_t textureUnit : activeTextures)
     {
diff --git a/src/libANGLE/renderer/metal/DisplayMtl.mm b/src/libANGLE/renderer/metal/DisplayMtl.mm
index 0c8c281..46a2300 100644
--- a/src/libANGLE/renderer/metal/DisplayMtl.mm
+++ b/src/libANGLE/renderer/metal/DisplayMtl.mm
@@ -618,6 +618,11 @@
 
     // Re-verify texture extensions.
     mNativeExtensions.setTextureExtensionSupport(mNativeTextureCaps);
+
+    // Disable all depth buffer and stencil buffer readback extensions until we need them
+    mNativeExtensions.readDepthNV         = false;
+    mNativeExtensions.readStencilNV       = false;
+    mNativeExtensions.depthBufferFloat2NV = false;
 }
 
 void DisplayMtl::initializeFeatures()
diff --git a/src/libANGLE/renderer/metal/FrameBufferMtl.h b/src/libANGLE/renderer/metal/FrameBufferMtl.h
index d220a02..66f0c60 100644
--- a/src/libANGLE/renderer/metal/FrameBufferMtl.h
+++ b/src/libANGLE/renderer/metal/FrameBufferMtl.h
@@ -58,8 +58,8 @@
                                 GLfloat depth,
                                 GLint stencil) override;
 
-    GLenum getImplementationColorReadFormat(const gl::Context *context) const override;
-    GLenum getImplementationColorReadType(const gl::Context *context) const override;
+    const gl::InternalFormat &getImplementationColorReadFormat(
+        const gl::Context *context) const override;
     angle::Result readPixels(const gl::Context *context,
                              const gl::Rectangle &area,
                              GLenum format,
@@ -75,6 +75,7 @@
     bool checkStatus(const gl::Context *context) const override;
 
     angle::Result syncState(const gl::Context *context,
+                            GLenum binding,
                             const gl::Framebuffer::DirtyBits &dirtyBits) override;
 
     angle::Result getSamplePosition(const gl::Context *context,
diff --git a/src/libANGLE/renderer/metal/FrameBufferMtl.mm b/src/libANGLE/renderer/metal/FrameBufferMtl.mm
index 72eaea5..99ba927 100644
--- a/src/libANGLE/renderer/metal/FrameBufferMtl.mm
+++ b/src/libANGLE/renderer/metal/FrameBufferMtl.mm
@@ -22,28 +22,6 @@
 
 namespace rx
 {
-
-namespace
-{
-
-const gl::InternalFormat &GetReadAttachmentInfo(const gl::Context *context,
-                                                RenderTargetMtl *renderTarget)
-{
-    GLenum implFormat;
-
-    if (renderTarget && renderTarget->getFormat())
-    {
-        implFormat = renderTarget->getFormat()->actualAngleFormat().fboImplementationInternalFormat;
-    }
-    else
-    {
-        implFormat = GL_NONE;
-    }
-
-    return gl::GetSizedInternalFormatInfo(implFormat);
-}
-}
-
 // FramebufferMtl implementation
 FramebufferMtl::FramebufferMtl(const gl::FramebufferState &state, bool flipY)
     : FramebufferImpl(state), mFlipY(flipY)
@@ -157,14 +135,15 @@
     return angle::Result::Stop;
 }
 
-GLenum FramebufferMtl::getImplementationColorReadFormat(const gl::Context *context) const
+const gl::InternalFormat &FramebufferMtl::getImplementationColorReadFormat(
+    const gl::Context *context) const
 {
-    return GetReadAttachmentInfo(context, getColorReadRenderTarget()).format;
-}
-
-GLenum FramebufferMtl::getImplementationColorReadType(const gl::Context *context) const
-{
-    return GetReadAttachmentInfo(context, getColorReadRenderTarget()).type;
+    ContextMtl *contextMtl   = mtl::GetImpl(context);
+    GLenum sizedFormat       = mState.getReadAttachment()->getFormat().info->sizedInternalFormat;
+    angle::FormatID formatID = angle::Format::InternalFormatToID(sizedFormat);
+    const mtl::Format &mtlFormat = contextMtl->getDisplay()->getPixelFormat(formatID);
+    GLenum implFormat            = mtlFormat.actualAngleFormat().fboImplementationInternalFormat;
+    return gl::GetSizedInternalFormatInfo(implFormat);
 }
 
 angle::Result FramebufferMtl::readPixels(const gl::Context *context,
@@ -246,6 +225,7 @@
 }
 
 angle::Result FramebufferMtl::syncState(const gl::Context *context,
+                                        GLenum binding,
                                         const gl::Framebuffer::DirtyBits &dirtyBits)
 {
     ContextMtl *contextMtl = mtl::GetImpl(context);
diff --git a/src/libANGLE/renderer/metal/ProgramMtl.h b/src/libANGLE/renderer/metal/ProgramMtl.h
index 897e4f0..e286254 100644
--- a/src/libANGLE/renderer/metal/ProgramMtl.h
+++ b/src/libANGLE/renderer/metal/ProgramMtl.h
@@ -99,11 +99,6 @@
     void getUniformiv(const gl::Context *context, GLint location, GLint *params) const override;
     void getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const override;
 
-    void setPathFragmentInputGen(const std::string &inputName,
-                                 GLenum genMode,
-                                 GLint components,
-                                 const GLfloat *coeffs) override;
-
     // Calls this before drawing, changedPipelineDesc is passed when vertex attributes desc and/or
     // shader program changed.
     angle::Result setupDraw(const gl::Context *glContext,
diff --git a/src/libANGLE/renderer/metal/ProgramMtl.mm b/src/libANGLE/renderer/metal/ProgramMtl.mm
index 4e43a42..979dacf 100644
--- a/src/libANGLE/renderer/metal/ProgramMtl.mm
+++ b/src/libANGLE/renderer/metal/ProgramMtl.mm
@@ -312,7 +312,7 @@
 
     // Gather variable info and transform sources.
     gl::ShaderMap<std::string> shaderSources;
-    ShaderInterfaceVariableInfoMap variableInfoMap;
+    ShaderMapInterfaceVariableInfoMap variableInfoMap;
     mtl::GlslangGetShaderSource(mState, resources, &shaderSources, &variableInfoMap);
 
     // Convert GLSL to spirv code
@@ -782,14 +782,6 @@
     setUniformMatrixfv<4, 3>(location, count, transpose, value);
 }
 
-void ProgramMtl::setPathFragmentInputGen(const std::string &inputName,
-                                         GLenum genMode,
-                                         GLint components,
-                                         const GLfloat *coeffs)
-{
-    UNIMPLEMENTED();
-}
-
 void ProgramMtl::getUniformfv(const gl::Context *context, GLint location, GLfloat *params) const
 {
     getUniformImpl(location, params, GL_FLOAT);
@@ -877,7 +869,7 @@
 {
     const auto &glState = glContext->getState();
 
-    const gl::ActiveTexturePointerArray &completeTextures = glState.getActiveTexturesCache();
+    const gl::ActiveTexturesCache &completeTextures = glState.getActiveTexturesCache();
 
     for (gl::ShaderType shaderType : gl::AllGLES2ShaderTypes())
     {
diff --git a/src/libANGLE/renderer/metal/SurfaceMtl.mm b/src/libANGLE/renderer/metal/SurfaceMtl.mm
index a2bcfe5..3396e75 100644
--- a/src/libANGLE/renderer/metal/SurfaceMtl.mm
+++ b/src/libANGLE/renderer/metal/SurfaceMtl.mm
@@ -549,7 +549,7 @@
         if (defaultFbo)
         {
             FramebufferMtl *framebufferMtl = mtl::GetImpl(defaultFbo);
-            ANGLE_TRY(framebufferMtl->syncState(context, fboDirtyBits));
+            ANGLE_TRY(framebufferMtl->syncState(context, GL_FRAMEBUFFER, fboDirtyBits));
         }
 
         return angle::Result::Continue;
diff --git a/src/libANGLE/renderer/metal/TextureMtl.h b/src/libANGLE/renderer/metal/TextureMtl.h
index 053942c..c5a811f 100644
--- a/src/libANGLE/renderer/metal/TextureMtl.h
+++ b/src/libANGLE/renderer/metal/TextureMtl.h
@@ -35,6 +35,7 @@
                            GLenum format,
                            GLenum type,
                            const gl::PixelUnpackState &unpack,
+                           gl::Buffer *unpackBuffer,
                            const uint8_t *pixels) override;
     angle::Result setSubImage(const gl::Context *context,
                               const gl::ImageIndex &index,
diff --git a/src/libANGLE/renderer/metal/TextureMtl.mm b/src/libANGLE/renderer/metal/TextureMtl.mm
index 0f32474..c402d64 100644
--- a/src/libANGLE/renderer/metal/TextureMtl.mm
+++ b/src/libANGLE/renderer/metal/TextureMtl.mm
@@ -397,7 +397,7 @@
     ANGLE_TRY(checkForEmulatedChannels(context, mFormat, mNativeTexture));
 
     // Transfer data from images to actual texture object
-    mtl::BlitCommandEncoder *encoder                = nullptr;
+    mtl::BlitCommandEncoder *encoder = nullptr;
     for (int layer = 0; layer < layers; ++layer)
     {
         for (GLuint mip = 0; mip < mips; ++mip)
@@ -489,6 +489,7 @@
                                    GLenum format,
                                    GLenum type,
                                    const gl::PixelUnpackState &unpack,
+                                   gl::Buffer *unpackBuffer,
                                    const uint8_t *pixels)
 {
     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
diff --git a/src/libANGLE/renderer/metal/mtl_glslang_utils.h b/src/libANGLE/renderer/metal/mtl_glslang_utils.h
index 92bd1cb..4e351ea 100644
--- a/src/libANGLE/renderer/metal/mtl_glslang_utils.h
+++ b/src/libANGLE/renderer/metal/mtl_glslang_utils.h
@@ -22,12 +22,12 @@
 void GlslangGetShaderSource(const gl::ProgramState &programState,
                             const gl::ProgramLinkedResources &resources,
                             gl::ShaderMap<std::string> *shaderSourcesOut,
-                            ShaderInterfaceVariableInfoMap *variableInfoMapOut);
+                            ShaderMapInterfaceVariableInfoMap *variableInfoMapOut);
 
 angle::Result GlslangGetShaderSpirvCode(ErrorHandler *context,
                                         const gl::Caps &glCaps,
                                         const gl::ShaderMap<std::string> &shaderSources,
-                                        const ShaderInterfaceVariableInfoMap &variableInfoMap,
+                                        const ShaderMapInterfaceVariableInfoMap &variableInfoMap,
                                         gl::ShaderMap<std::vector<uint32_t>> *shaderCodeOut);
 }  // namespace mtl
 }  // namespace rx
diff --git a/src/libANGLE/renderer/metal/mtl_glslang_utils.mm b/src/libANGLE/renderer/metal/mtl_glslang_utils.mm
index 3cecb85..942c7f8 100644
--- a/src/libANGLE/renderer/metal/mtl_glslang_utils.mm
+++ b/src/libANGLE/renderer/metal/mtl_glslang_utils.mm
@@ -22,21 +22,25 @@
     return angle::Result::Stop;
 }
 
-GlslangSourceOptions CreateSourceOptions()
+void ResetGlslangProgramInterfaceInfo(GlslangProgramInterfaceInfo *programInterfaceInfo)
 {
-    GlslangSourceOptions options;
-    // We don't actually use descriptor set for now, the actual binding will be done inside
-    // ProgramMtl using spirv-cross.
-    options.uniformsAndXfbDescriptorSetIndex = kDefaultUniformsBindingIndex;
-    options.textureDescriptorSetIndex        = 0;
-    options.driverUniformsDescriptorSetIndex = kDriverUniformsBindingIndex;
+    programInterfaceInfo->uniformsAndXfbDescriptorSetIndex = kDefaultUniformsBindingIndex;
+    programInterfaceInfo->currentUniformBindingIndex       = 0;
+    programInterfaceInfo->textureDescriptorSetIndex        = 0;
+    programInterfaceInfo->currentTextureBindingIndex       = 0;
+    programInterfaceInfo->driverUniformsDescriptorSetIndex = kDriverUniformsBindingIndex;
     // NOTE(hqle): Unused for now, until we support ES 3.0
-    options.shaderResourceDescriptorSetIndex = -1;
-    options.xfbBindingIndexStart             = -1;
+    programInterfaceInfo->shaderResourceDescriptorSetIndex  = -1;
+    programInterfaceInfo->currentShaderResourceBindingIndex = 0;
+    programInterfaceInfo->locationsUsedForXfbExtension      = 0;
 
     static_assert(kDefaultUniformsBindingIndex != 0, "kDefaultUniformsBindingIndex must not be 0");
     static_assert(kDriverUniformsBindingIndex != 0, "kDriverUniformsBindingIndex must not be 0");
+}
 
+GlslangSourceOptions CreateSourceOptions()
+{
+    GlslangSourceOptions options;
     return options;
 }
 }  // namespace
@@ -44,16 +48,20 @@
 void GlslangGetShaderSource(const gl::ProgramState &programState,
                             const gl::ProgramLinkedResources &resources,
                             gl::ShaderMap<std::string> *shaderSourcesOut,
-                            ShaderInterfaceVariableInfoMap *variableInfoMapOut)
+                            ShaderMapInterfaceVariableInfoMap *variableInfoMapOut)
 {
-    rx::GlslangGetShaderSource(CreateSourceOptions(), programState, resources, shaderSourcesOut,
-                               variableInfoMapOut);
+    GlslangSourceOptions options = CreateSourceOptions();
+    GlslangProgramInterfaceInfo programInterfaceInfo;
+    ResetGlslangProgramInterfaceInfo(&programInterfaceInfo);
+
+    rx::GlslangGetShaderSource(options, programState, resources, &programInterfaceInfo,
+                               shaderSourcesOut, variableInfoMapOut);
 }
 
 angle::Result GlslangGetShaderSpirvCode(ErrorHandler *context,
                                         const gl::Caps &glCaps,
                                         const gl::ShaderMap<std::string> &shaderSources,
-                                        const ShaderInterfaceVariableInfoMap &variableInfoMap,
+                                        const ShaderMapInterfaceVariableInfoMap &variableInfoMap,
                                         gl::ShaderMap<std::vector<uint32_t>> *shaderCodeOut)
 {
     return rx::GlslangGetShaderSpirvCode(
diff --git a/src/libANGLE/renderer/null/ContextNULL.cpp b/src/libANGLE/renderer/null/ContextNULL.cpp
index 6dd645c..a413b3c 100644
--- a/src/libANGLE/renderer/null/ContextNULL.cpp
+++ b/src/libANGLE/renderer/null/ContextNULL.cpp
@@ -19,7 +19,6 @@
 #include "libANGLE/renderer/null/FenceNVNULL.h"
 #include "libANGLE/renderer/null/FramebufferNULL.h"
 #include "libANGLE/renderer/null/ImageNULL.h"
-#include "libANGLE/renderer/null/PathNULL.h"
 #include "libANGLE/renderer/null/ProgramNULL.h"
 #include "libANGLE/renderer/null/ProgramPipelineNULL.h"
 #include "libANGLE/renderer/null/QueryNULL.h"
@@ -93,6 +92,7 @@
     mExtensions.textureCompressionASTCLDRKHR = true;
     mExtensions.textureCompressionASTCOES    = true;
     mExtensions.compressedETC1RGB8TextureOES = true;
+    mExtensions.compressedETC1RGB8SubTexture = true;
     mExtensions.lossyETCDecode               = true;
     mExtensions.geometryShader               = true;
 
@@ -241,68 +241,6 @@
     return angle::Result::Continue;
 }
 
-void ContextNULL::stencilFillPath(const gl::Path *path, GLenum fillMode, GLuint mask) {}
-
-void ContextNULL::stencilStrokePath(const gl::Path *path, GLint reference, GLuint mask) {}
-
-void ContextNULL::coverFillPath(const gl::Path *path, GLenum coverMode) {}
-
-void ContextNULL::coverStrokePath(const gl::Path *path, GLenum coverMode) {}
-
-void ContextNULL::stencilThenCoverFillPath(const gl::Path *path,
-                                           GLenum fillMode,
-                                           GLuint mask,
-                                           GLenum coverMode)
-{}
-
-void ContextNULL::stencilThenCoverStrokePath(const gl::Path *path,
-                                             GLint reference,
-                                             GLuint mask,
-                                             GLenum coverMode)
-{}
-
-void ContextNULL::coverFillPathInstanced(const std::vector<gl::Path *> &paths,
-                                         GLenum coverMode,
-                                         GLenum transformType,
-                                         const GLfloat *transformValues)
-{}
-
-void ContextNULL::coverStrokePathInstanced(const std::vector<gl::Path *> &paths,
-                                           GLenum coverMode,
-                                           GLenum transformType,
-                                           const GLfloat *transformValues)
-{}
-
-void ContextNULL::stencilFillPathInstanced(const std::vector<gl::Path *> &paths,
-                                           GLenum fillMode,
-                                           GLuint mask,
-                                           GLenum transformType,
-                                           const GLfloat *transformValues)
-{}
-
-void ContextNULL::stencilStrokePathInstanced(const std::vector<gl::Path *> &paths,
-                                             GLint reference,
-                                             GLuint mask,
-                                             GLenum transformType,
-                                             const GLfloat *transformValues)
-{}
-
-void ContextNULL::stencilThenCoverFillPathInstanced(const std::vector<gl::Path *> &paths,
-                                                    GLenum coverMode,
-                                                    GLenum fillMode,
-                                                    GLuint mask,
-                                                    GLenum transformType,
-                                                    const GLfloat *transformValues)
-{}
-
-void ContextNULL::stencilThenCoverStrokePathInstanced(const std::vector<gl::Path *> &paths,
-                                                      GLenum coverMode,
-                                                      GLint reference,
-                                                      GLuint mask,
-                                                      GLenum transformType,
-                                                      const GLfloat *transformValues)
-{}
-
 gl::GraphicsResetStatus ContextNULL::getResetStatus()
 {
     return gl::GraphicsResetStatus::NoError;
@@ -458,16 +396,6 @@
     return new ProgramPipelineNULL(state);
 }
 
-std::vector<PathImpl *> ContextNULL::createPaths(GLsizei range)
-{
-    std::vector<PathImpl *> result(range);
-    for (GLsizei idx = 0; idx < range; idx++)
-    {
-        result[idx] = new PathNULL();
-    }
-    return result;
-}
-
 MemoryObjectImpl *ContextNULL::createMemoryObject()
 {
     UNREACHABLE();
diff --git a/src/libANGLE/renderer/null/ContextNULL.h b/src/libANGLE/renderer/null/ContextNULL.h
index 4c3cf84..ad98055 100644
--- a/src/libANGLE/renderer/null/ContextNULL.h
+++ b/src/libANGLE/renderer/null/ContextNULL.h
@@ -116,52 +116,6 @@
                                        gl::DrawElementsType type,
                                        const void *indirect) override;
 
-    // CHROMIUM_path_rendering path drawing methods.
-    void stencilFillPath(const gl::Path *path, GLenum fillMode, GLuint mask) override;
-    void stencilStrokePath(const gl::Path *path, GLint reference, GLuint mask) override;
-    void coverFillPath(const gl::Path *path, GLenum coverMode) override;
-    void coverStrokePath(const gl::Path *path, GLenum coverMode) override;
-    void stencilThenCoverFillPath(const gl::Path *path,
-                                  GLenum fillMode,
-                                  GLuint mask,
-                                  GLenum coverMode) override;
-
-    void stencilThenCoverStrokePath(const gl::Path *path,
-                                    GLint reference,
-                                    GLuint mask,
-                                    GLenum coverMode) override;
-
-    void coverFillPathInstanced(const std::vector<gl::Path *> &paths,
-                                GLenum coverMode,
-                                GLenum transformType,
-                                const GLfloat *transformValues) override;
-    void coverStrokePathInstanced(const std::vector<gl::Path *> &paths,
-                                  GLenum coverMode,
-                                  GLenum transformType,
-                                  const GLfloat *transformValues) override;
-    void stencilFillPathInstanced(const std::vector<gl::Path *> &paths,
-                                  GLenum fillMode,
-                                  GLuint mask,
-                                  GLenum transformType,
-                                  const GLfloat *transformValues) override;
-    void stencilStrokePathInstanced(const std::vector<gl::Path *> &paths,
-                                    GLint reference,
-                                    GLuint mask,
-                                    GLenum transformType,
-                                    const GLfloat *transformValues) override;
-    void stencilThenCoverFillPathInstanced(const std::vector<gl::Path *> &paths,
-                                           GLenum coverMode,
-                                           GLenum fillMode,
-                                           GLuint mask,
-                                           GLenum transformType,
-                                           const GLfloat *transformValues) override;
-    void stencilThenCoverStrokePathInstanced(const std::vector<gl::Path *> &paths,
-                                             GLenum coverMode,
-                                             GLint reference,
-                                             GLuint mask,
-                                             GLenum transformType,
-                                             const GLfloat *transformValues) override;
-
     // Device loss
     gl::GraphicsResetStatus getResetStatus() override;
 
@@ -234,8 +188,6 @@
     // Program Pipeline object creation
     ProgramPipelineImpl *createProgramPipeline(const gl::ProgramPipelineState &data) override;
 
-    std::vector<PathImpl *> createPaths(GLsizei range) override;
-
     // Memory object creation.
     MemoryObjectImpl *createMemoryObject() override;
 
diff --git a/src/libANGLE/renderer/null/FramebufferNULL.cpp b/src/libANGLE/renderer/null/FramebufferNULL.cpp
index 94510c6..5b78fef 100644
--- a/src/libANGLE/renderer/null/FramebufferNULL.cpp
+++ b/src/libANGLE/renderer/null/FramebufferNULL.cpp
@@ -82,32 +82,6 @@
     return angle::Result::Continue;
 }
 
-GLenum FramebufferNULL::getImplementationColorReadFormat(const gl::Context *context) const
-{
-    const gl::FramebufferAttachment *readAttachment = mState.getReadAttachment();
-    if (readAttachment == nullptr)
-    {
-        return GL_NONE;
-    }
-
-    const gl::Format &format = readAttachment->getFormat();
-    ASSERT(format.info != nullptr);
-    return format.info->getReadPixelsFormat(context->getExtensions());
-}
-
-GLenum FramebufferNULL::getImplementationColorReadType(const gl::Context *context) const
-{
-    const gl::FramebufferAttachment *readAttachment = mState.getReadAttachment();
-    if (readAttachment == nullptr)
-    {
-        return GL_NONE;
-    }
-
-    const gl::Format &format = readAttachment->getFormat();
-    ASSERT(format.info != nullptr);
-    return format.info->getReadPixelsType(context->getClientVersion());
-}
-
 angle::Result FramebufferNULL::readPixels(const gl::Context *context,
                                           const gl::Rectangle &origArea,
                                           GLenum format,
@@ -131,7 +105,7 @@
     }
 
     // Clip read area to framebuffer.
-    const gl::Extents fbSize = getState().getReadAttachment()->getSize();
+    const gl::Extents fbSize = getState().getReadPixelsAttachment(format)->getSize();
     const gl::Rectangle fbRect(0, 0, fbSize.width, fbSize.height);
     gl::Rectangle area;
     if (!ClipRectangle(origArea, fbRect, &area))
@@ -185,6 +159,7 @@
 }
 
 angle::Result FramebufferNULL::syncState(const gl::Context *context,
+                                         GLenum binding,
                                          const gl::Framebuffer::DirtyBits &dirtyBits)
 {
     return angle::Result::Continue;
diff --git a/src/libANGLE/renderer/null/FramebufferNULL.h b/src/libANGLE/renderer/null/FramebufferNULL.h
index 41f1650..92290a5 100644
--- a/src/libANGLE/renderer/null/FramebufferNULL.h
+++ b/src/libANGLE/renderer/null/FramebufferNULL.h
@@ -51,8 +51,6 @@
                                 GLfloat depth,
                                 GLint stencil) override;
 
-    GLenum getImplementationColorReadFormat(const gl::Context *context) const override;
-    GLenum getImplementationColorReadType(const gl::Context *context) const override;
     angle::Result readPixels(const gl::Context *context,
                              const gl::Rectangle &area,
                              GLenum format,
@@ -68,6 +66,7 @@
     bool checkStatus(const gl::Context *context) const override;
 
     angle::Result syncState(const gl::Context *context,
+                            GLenum binding,
                             const gl::Framebuffer::DirtyBits &dirtyBits) override;
 
     angle::Result getSamplePosition(const gl::Context *context,
diff --git a/src/libANGLE/renderer/null/PathNULL.cpp b/src/libANGLE/renderer/null/PathNULL.cpp
deleted file mode 100644
index a408e4f..0000000
--- a/src/libANGLE/renderer/null/PathNULL.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-//
-// Copyright 2016 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// PathNULL.cpp:
-//    Implements the class methods for PathNULL.
-//
-
-#include "libANGLE/renderer/null/PathNULL.h"
-
-#include "common/debug.h"
-
-namespace rx
-{
-PathNULL::PathNULL() : PathImpl() {}
-
-PathNULL::~PathNULL() {}
-
-angle::Result PathNULL::setCommands(GLsizei numCommands,
-                                    const GLubyte *commands,
-                                    GLsizei numCoords,
-                                    GLenum coordType,
-                                    const void *coords)
-{
-    return angle::Result::Continue;
-}
-
-void PathNULL::setPathParameter(GLenum pname, GLfloat value) {}
-}  // namespace rx
diff --git a/src/libANGLE/renderer/null/PathNULL.h b/src/libANGLE/renderer/null/PathNULL.h
deleted file mode 100644
index b07a80b..0000000
--- a/src/libANGLE/renderer/null/PathNULL.h
+++ /dev/null
@@ -1,35 +0,0 @@
-//
-// Copyright 2016 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// PathNULL.h:
-//    Defines the class interface for PathNULL, implementing PathImpl.
-//
-
-#ifndef LIBANGLE_RENDERER_NULL_PATHNULL_H_
-#define LIBANGLE_RENDERER_NULL_PATHNULL_H_
-
-#include "libANGLE/renderer/PathImpl.h"
-
-namespace rx
-{
-
-class PathNULL : public PathImpl
-{
-  public:
-    PathNULL();
-    ~PathNULL() override;
-
-    angle::Result setCommands(GLsizei numCommands,
-                              const GLubyte *commands,
-                              GLsizei numCoords,
-                              GLenum coordType,
-                              const void *coords) override;
-
-    void setPathParameter(GLenum pname, GLfloat value) override;
-};
-
-}  // namespace rx
-
-#endif  // LIBANGLE_RENDERER_NULL_PATHNULL_H_
diff --git a/src/libANGLE/renderer/null/ProgramNULL.cpp b/src/libANGLE/renderer/null/ProgramNULL.cpp
index 77b2e1e..6139de3 100644
--- a/src/libANGLE/renderer/null/ProgramNULL.cpp
+++ b/src/libANGLE/renderer/null/ProgramNULL.cpp
@@ -136,10 +136,4 @@
     // TODO(jmadill): Write some values.
 }
 
-void ProgramNULL::setPathFragmentInputGen(const std::string &inputName,
-                                          GLenum genMode,
-                                          GLint components,
-                                          const GLfloat *coeffs)
-{}
-
 }  // namespace rx
diff --git a/src/libANGLE/renderer/null/ProgramNULL.h b/src/libANGLE/renderer/null/ProgramNULL.h
index 8260577..2e15f85 100644
--- a/src/libANGLE/renderer/null/ProgramNULL.h
+++ b/src/libANGLE/renderer/null/ProgramNULL.h
@@ -85,13 +85,6 @@
     void getUniformfv(const gl::Context *context, GLint location, GLfloat *params) const override;
     void getUniformiv(const gl::Context *context, GLint location, GLint *params) const override;
     void getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const override;
-
-    // CHROMIUM_path_rendering
-    // Set parameters to control fragment shader input variable interpolation
-    void setPathFragmentInputGen(const std::string &inputName,
-                                 GLenum genMode,
-                                 GLint components,
-                                 const GLfloat *coeffs) override;
 };
 
 }  // namespace rx
diff --git a/src/libANGLE/renderer/null/TextureNULL.cpp b/src/libANGLE/renderer/null/TextureNULL.cpp
index a7b6f04..dde950f 100644
--- a/src/libANGLE/renderer/null/TextureNULL.cpp
+++ b/src/libANGLE/renderer/null/TextureNULL.cpp
@@ -25,6 +25,7 @@
                                     GLenum format,
                                     GLenum type,
                                     const gl::PixelUnpackState &unpack,
+                                    gl::Buffer *unpackBuffer,
                                     const uint8_t *pixels)
 {
     // TODO(geofflang): Read all incoming pixel data (maybe hash it?) to make sure we don't read out
diff --git a/src/libANGLE/renderer/null/TextureNULL.h b/src/libANGLE/renderer/null/TextureNULL.h
index 4b2ddb9..5b6ef5c 100644
--- a/src/libANGLE/renderer/null/TextureNULL.h
+++ b/src/libANGLE/renderer/null/TextureNULL.h
@@ -28,6 +28,7 @@
                            GLenum format,
                            GLenum type,
                            const gl::PixelUnpackState &unpack,
+                           gl::Buffer *unpackBuffer,
                            const uint8_t *pixels) override;
     angle::Result setSubImage(const gl::Context *context,
                               const gl::ImageIndex &index,
diff --git a/src/libANGLE/renderer/serial_utils.h b/src/libANGLE/renderer/serial_utils.h
index be7015d..e81fb7a 100644
--- a/src/libANGLE/renderer/serial_utils.h
+++ b/src/libANGLE/renderer/serial_utils.h
@@ -69,6 +69,7 @@
 
     // Useful for serialization.
     constexpr uint64_t getValue() const { return mValue; }
+    constexpr bool valid() const { return mValue != kInvalid; }
 
   private:
     template <typename T>
diff --git a/src/libANGLE/renderer/vulkan/BUILD.gn b/src/libANGLE/renderer/vulkan/BUILD.gn
index 2468486..36c6cfe 100644
--- a/src/libANGLE/renderer/vulkan/BUILD.gn
+++ b/src/libANGLE/renderer/vulkan/BUILD.gn
@@ -43,6 +43,8 @@
   "OverlayVk.h",
   "PersistentCommandPool.cpp",
   "PersistentCommandPool.h",
+  "ProgramExecutableVk.cpp",
+  "ProgramExecutableVk.h",
   "ProgramPipelineVk.cpp",
   "ProgramPipelineVk.h",
   "ProgramVk.cpp",
@@ -161,10 +163,7 @@
 
 group("angle_vulkan_entry_points") {
   public_configs = [ ":angle_vulkan_lib_android" ]
-  public_deps = [
-    "$angle_root/src/third_party/volk:volk",
-    "$angle_root/third_party/vulkan-headers/src:vulkan_headers",
-  ]
+  public_deps = [ "$angle_root/src/third_party/volk" ]
   if (is_fuchsia) {
     public_deps += [
       "$angle_root/src/common/fuchsia_egl",
@@ -190,10 +189,28 @@
   }
 }
 
+angle_source_set("angle_vk_mem_alloc_wrapper") {
+  deps = [
+    "$angle_root/third_party/VulkanMemoryAllocator:vulkan_memory_allocator",
+  ]
+  sources = [
+    "vk_mem_alloc_wrapper.cpp",
+    "vk_mem_alloc_wrapper.h",
+  ]
+  defines = [ "VMA_IMPLEMENTATION" ]
+  if (is_clang) {
+    cflags_cc = [
+      "-Wno-extra-semi-stmt",
+      "-Wno-missing-field-initializers",
+    ]
+  }
+}
+
 angle_source_set("angle_vulkan_backend") {
   sources = _vulkan_backend_sources
   libs = []
   deps = [
+    ":angle_vk_mem_alloc_wrapper",
     ":angle_vulkan_entry_points",
     "$angle_root:angle_gpu_info_util",
     "$angle_root:angle_image_util",
diff --git a/src/libANGLE/renderer/vulkan/BufferVk.cpp b/src/libANGLE/renderer/vulkan/BufferVk.cpp
index a02167c..c98218f 100644
--- a/src/libANGLE/renderer/vulkan/BufferVk.cpp
+++ b/src/libANGLE/renderer/vulkan/BufferVk.cpp
@@ -72,6 +72,8 @@
     constexpr VkMemoryPropertyFlags kHostCachedFlags =
         (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
          VK_MEMORY_PROPERTY_HOST_CACHED_BIT);
+    constexpr VkMemoryPropertyFlags kHostUncachedFlags =
+        (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
 
     if (target == gl::BufferBinding::PixelUnpack)
     {
@@ -85,8 +87,19 @@
         case gl::BufferUsage::StaticRead:
             // For static usage, request a device local memory
             return kDeviceLocalFlags;
+        case gl::BufferUsage::DynamicDraw:
+        case gl::BufferUsage::StreamDraw:
+            // For non-static usage where the CPU performs a write-only access, request
+            // a host uncached memory
+            return kHostUncachedFlags;
+        case gl::BufferUsage::DynamicCopy:
+        case gl::BufferUsage::DynamicRead:
+        case gl::BufferUsage::StreamCopy:
+        case gl::BufferUsage::StreamRead:
+            // For all other types of usage, request a host cached memory
+            return kHostCachedFlags;
         default:
-            // For non-static usage, request a host cached memory
+            UNREACHABLE();
             return kHostCachedFlags;
     }
 }
@@ -144,6 +157,7 @@
     RendererVk *renderer = contextVk->getRenderer();
     mBuffer.release(renderer);
     mStagingBuffer.release(renderer);
+    mShadowBuffer.release();
 
     for (ConversionBuffer &buffer : mVertexConversionBuffers)
     {
@@ -163,6 +177,33 @@
     mStagingBuffer.init(rendererVk, kBufferUsageFlags, alignment, stagingBufferSize, true);
 }
 
+angle::Result BufferVk::initializeShadowBuffer(ContextVk *contextVk,
+                                               gl::BufferBinding target,
+                                               size_t size)
+{
+    // For now, enable shadow buffers only for pixel unpack buffers.
+    // If usecases present themselves, we can enable them for other buffer types.
+    if (target == gl::BufferBinding::PixelUnpack)
+    {
+        // Initialize the shadow buffer
+        mShadowBuffer.init(size);
+
+        // Allocate required memory. If allocation fails, treat it is a non-fatal error
+        // since we do not need the shadow buffer for functionality
+        ANGLE_TRY(mShadowBuffer.allocate(size));
+    }
+
+    return angle::Result::Continue;
+}
+
+void BufferVk::updateShadowBuffer(const uint8_t *data, size_t size, size_t offset)
+{
+    if (mShadowBuffer.valid())
+    {
+        mShadowBuffer.updateData(data, size, offset);
+    }
+}
+
 angle::Result BufferVk::setData(const gl::Context *context,
                                 gl::BufferBinding target,
                                 const void *data,
@@ -205,6 +246,9 @@
 
         // Initialize the staging buffer
         initializeStagingBuffer(contextVk, target, size);
+
+        // Initialize the shadow buffer
+        ANGLE_TRY(initializeShadowBuffer(contextVk, target, size));
     }
 
     if (data && size > 0)
@@ -239,6 +283,24 @@
 
     ContextVk *contextVk = vk::GetImpl(context);
     auto *sourceBuffer   = GetAs<BufferVk>(source);
+    ASSERT(sourceBuffer->getBuffer().valid());
+
+    // If the shadow buffer is enabled for the destination buffer then
+    // we need to update that as well. This will require us to complete
+    // all recorded and in-flight commands involving the source buffer.
+    if (mShadowBuffer.valid())
+    {
+        ANGLE_TRY(sourceBuffer->getBuffer().waitForIdle(contextVk));
+
+        // Update the shadow buffer
+        uint8_t *srcPtr;
+        ANGLE_TRY(sourceBuffer->getBuffer().mapWithOffset(contextVk, &srcPtr, sourceOffset));
+
+        updateShadowBuffer(srcPtr, size, destOffset);
+
+        // Unmap the source buffer
+        sourceBuffer->getBuffer().unmap(contextVk->getRenderer());
+    }
 
     vk::CommandBuffer *commandBuffer = nullptr;
 
@@ -287,33 +349,35 @@
                                      GLbitfield access,
                                      void **mapPtr)
 {
-    ASSERT(mBuffer.valid());
-
-    if ((access & GL_MAP_UNSYNCHRONIZED_BIT) == 0)
+    if (!mShadowBuffer.valid())
     {
-        // If there are pending commands for the buffer, flush them.
-        if (mBuffer.usedInRecordedCommands())
+        ASSERT(mBuffer.valid());
+
+        if ((access & GL_MAP_UNSYNCHRONIZED_BIT) == 0)
         {
-            ANGLE_TRY(contextVk->flushImpl(nullptr));
+            ANGLE_TRY(mBuffer.waitForIdle(contextVk));
         }
 
-        // Make sure the driver is done with the buffer.
-        if (mBuffer.usedInRunningCommands(contextVk->getLastCompletedQueueSerial()))
-        {
-            ANGLE_TRY(mBuffer.finishRunningCommands(contextVk));
-        }
-
-        ASSERT(!mBuffer.isCurrentlyInUse(contextVk->getLastCompletedQueueSerial()));
+        ANGLE_TRY(mBuffer.mapWithOffset(contextVk, reinterpret_cast<uint8_t **>(mapPtr),
+                                        static_cast<size_t>(offset)));
+    }
+    else
+    {
+        // If the app requested a GL_MAP_UNSYNCHRONIZED_BIT access, the spec states -
+        //      No GL error is generated if pending operations which source or modify the
+        //      buffer overlap the mapped region, but the result of such previous and any
+        //      subsequent operations is undefined
+        // To keep the code simple, irrespective of whether the access was GL_MAP_UNSYNCHRONIZED_BIT
+        // or not, just return the shadow buffer.
+        mShadowBuffer.map(static_cast<size_t>(offset), mapPtr);
     }
 
-    ANGLE_VK_TRY(contextVk, mBuffer.getDeviceMemory().map(contextVk->getDevice(), offset, length, 0,
-                                                          reinterpret_cast<uint8_t **>(mapPtr)));
     return angle::Result::Continue;
 }
 
 angle::Result BufferVk::unmap(const gl::Context *context, GLboolean *result)
 {
-    unmapImpl(vk::GetImpl(context));
+    ANGLE_TRY(unmapImpl(vk::GetImpl(context)));
 
     // This should be false if the contents have been corrupted through external means.  Vulkan
     // doesn't provide such information.
@@ -322,14 +386,36 @@
     return angle::Result::Continue;
 }
 
-void BufferVk::unmapImpl(ContextVk *contextVk)
+angle::Result BufferVk::unmapImpl(ContextVk *contextVk)
 {
     ASSERT(mBuffer.valid());
 
-    mBuffer.getDeviceMemory().unmap(contextVk->getDevice());
-    mBuffer.onExternalWrite(VK_ACCESS_HOST_WRITE_BIT);
+    if (!mShadowBuffer.valid())
+    {
+        mBuffer.unmap(contextVk->getRenderer());
+        mBuffer.onExternalWrite(VK_ACCESS_HOST_WRITE_BIT);
+    }
+    else
+    {
+        bool writeOperation = ((mState.getAccessFlags() & GL_MAP_WRITE_BIT) != 0);
+        size_t offset       = static_cast<size_t>(mState.getMapOffset());
+        size_t size         = static_cast<size_t>(mState.getMapLength());
+
+        // If it was a write operation we need to update the GPU buffer.
+        if (writeOperation)
+        {
+            // We do not yet know if thie data will ever be used. Perform a staged
+            // update which will get flushed if and when necessary.
+            const uint8_t *data = getShadowBuffer(offset);
+            ANGLE_TRY(stagedUpdate(contextVk, data, size, offset));
+        }
+
+        mShadowBuffer.unmap();
+    }
 
     markConversionBuffersDirty();
+
+    return angle::Result::Continue;
 }
 
 angle::Result BufferVk::getIndexRange(const gl::Context *context,
@@ -352,21 +438,74 @@
     }
 
     ANGLE_TRACE_EVENT0("gpu.angle", "BufferVk::getIndexRange");
-    // Needed before reading buffer or we could get stale data.
-    ANGLE_TRY(mBuffer.finishRunningCommands(contextVk));
 
-    // TODO(jmadill): Consider keeping a shadow system memory copy in some cases.
-    ASSERT(mBuffer.valid());
+    uint8_t *mapPointer;
 
-    const GLuint &typeBytes = gl::GetDrawElementsTypeSize(type);
+    if (!mShadowBuffer.valid())
+    {
+        // Needed before reading buffer or we could get stale data.
+        ANGLE_TRY(mBuffer.finishRunningCommands(contextVk));
 
-    uint8_t *mapPointer = nullptr;
-    ANGLE_VK_TRY(contextVk, mBuffer.getDeviceMemory().map(contextVk->getDevice(), offset,
-                                                          typeBytes * count, 0, &mapPointer));
+        ASSERT(mBuffer.valid());
+
+        ANGLE_TRY(mBuffer.mapWithOffset(contextVk, &mapPointer, offset));
+    }
+    else
+    {
+        mapPointer = getShadowBuffer(offset);
+    }
 
     *outRange = gl::ComputeIndexRange(type, mapPointer, count, primitiveRestartEnabled);
 
-    mBuffer.getDeviceMemory().unmap(contextVk->getDevice());
+    mBuffer.unmap(renderer);
+    return angle::Result::Continue;
+}
+
+angle::Result BufferVk::directUpdate(ContextVk *contextVk,
+                                     const uint8_t *data,
+                                     size_t size,
+                                     size_t offset)
+{
+    uint8_t *mapPointer = nullptr;
+
+    ANGLE_TRY(mBuffer.mapWithOffset(contextVk, &mapPointer, offset));
+    ASSERT(mapPointer);
+
+    memcpy(mapPointer, data, size);
+
+    mBuffer.unmap(contextVk->getRenderer());
+    mBuffer.onExternalWrite(VK_ACCESS_HOST_WRITE_BIT);
+
+    return angle::Result::Continue;
+}
+
+angle::Result BufferVk::stagedUpdate(ContextVk *contextVk,
+                                     const uint8_t *data,
+                                     size_t size,
+                                     size_t offset)
+{
+    // Acquire a "new" staging buffer
+    bool needToReleasePreviousBuffers = false;
+    uint8_t *mapPointer               = nullptr;
+    VkDeviceSize stagingBufferOffset  = 0;
+
+    ANGLE_TRY(mStagingBuffer.allocate(contextVk, size, &mapPointer, nullptr, &stagingBufferOffset,
+                                      &needToReleasePreviousBuffers));
+    if (needToReleasePreviousBuffers)
+    {
+        // Release previous staging buffers
+        mStagingBuffer.releaseInFlightBuffers(contextVk);
+    }
+    ASSERT(mapPointer);
+
+    memcpy(mapPointer, data, size);
+
+    // Enqueue a copy command on the GPU.
+    VkBufferCopy copyRegion = {stagingBufferOffset, offset, size};
+    ANGLE_TRY(mBuffer.copyFromBuffer(contextVk, mStagingBuffer.getCurrentBuffer(),
+                                     VK_ACCESS_HOST_WRITE_BIT, copyRegion));
+    mStagingBuffer.getCurrentBuffer()->retain(&contextVk->getResourceUseList());
+
     return angle::Result::Continue;
 }
 
@@ -375,44 +514,17 @@
                                     size_t size,
                                     size_t offset)
 {
-    VkDevice device = contextVk->getDevice();
+    // Update shadow buffer
+    updateShadowBuffer(data, size, offset);
 
-    // Use map when available.
+    // If the buffer is currently in use, stage the update. Otherwise update the buffer directly.
     if (mBuffer.isCurrentlyInUse(contextVk->getLastCompletedQueueSerial()))
     {
-        // Acquire a "new" staging buffer
-        bool needToReleasePreviousBuffers = false;
-        uint8_t *mapPointer               = nullptr;
-        VkDeviceSize stagingBufferOffset  = 0;
-
-        ANGLE_TRY(mStagingBuffer.allocate(contextVk, size, &mapPointer, nullptr,
-                                          &stagingBufferOffset, &needToReleasePreviousBuffers));
-        if (needToReleasePreviousBuffers)
-        {
-            // Release previous staging buffers
-            mStagingBuffer.releaseInFlightBuffers(contextVk);
-        }
-        ASSERT(mapPointer);
-
-        memcpy(mapPointer, data, size);
-
-        // Enqueue a copy command on the GPU.
-        VkBufferCopy copyRegion = {stagingBufferOffset, offset, size};
-        ANGLE_TRY(mBuffer.copyFromBuffer(contextVk, mStagingBuffer.getCurrentBuffer(),
-                                         VK_ACCESS_HOST_WRITE_BIT, copyRegion));
-        mStagingBuffer.getCurrentBuffer()->retain(&contextVk->getResourceUseList());
+        ANGLE_TRY(stagedUpdate(contextVk, data, size, offset));
     }
     else
     {
-        uint8_t *mapPointer = nullptr;
-        ANGLE_VK_TRY(contextVk,
-                     mBuffer.getDeviceMemory().map(device, offset, size, 0, &mapPointer));
-        ASSERT(mapPointer);
-
-        memcpy(mapPointer, data, size);
-
-        mBuffer.getDeviceMemory().unmap(device);
-        mBuffer.onExternalWrite(VK_ACCESS_HOST_WRITE_BIT);
+        ANGLE_TRY(directUpdate(contextVk, data, size, offset));
     }
 
     // Update conversions
@@ -421,10 +533,10 @@
     return angle::Result::Continue;
 }
 
-angle::Result BufferVk::copyToBuffer(ContextVk *contextVk,
-                                     vk::BufferHelper *destBuffer,
-                                     uint32_t copyCount,
-                                     const VkBufferCopy *copies)
+angle::Result BufferVk::copyToBufferImpl(ContextVk *contextVk,
+                                         vk::BufferHelper *destBuffer,
+                                         uint32_t copyCount,
+                                         const VkBufferCopy *copies)
 {
     vk::CommandBuffer *commandBuffer;
     ANGLE_TRY(contextVk->onBufferWrite(VK_ACCESS_TRANSFER_WRITE_BIT, destBuffer));
diff --git a/src/libANGLE/renderer/vulkan/BufferVk.h b/src/libANGLE/renderer/vulkan/BufferVk.h
index 5ba5078..2c28f41 100644
--- a/src/libANGLE/renderer/vulkan/BufferVk.h
+++ b/src/libANGLE/renderer/vulkan/BufferVk.h
@@ -100,13 +100,13 @@
                                VkDeviceSize length,
                                GLbitfield access,
                                void **mapPtr);
-    void unmapImpl(ContextVk *contextVk);
+    angle::Result unmapImpl(ContextVk *contextVk);
 
     // Calls copyBuffer internally.
-    angle::Result copyToBuffer(ContextVk *contextVk,
-                               vk::BufferHelper *destBuffer,
-                               uint32_t copyCount,
-                               const VkBufferCopy *copies);
+    angle::Result copyToBufferImpl(ContextVk *contextVk,
+                                   vk::BufferHelper *destBuffer,
+                                   uint32_t copyCount,
+                                   const VkBufferCopy *copies);
 
     ConversionBuffer *getVertexConversionBuffer(RendererVk *renderer,
                                                 angle::FormatID formatID,
@@ -116,6 +116,29 @@
 
   private:
     void initializeStagingBuffer(ContextVk *contextVk, gl::BufferBinding target, size_t size);
+    angle::Result initializeShadowBuffer(ContextVk *contextVk,
+                                         gl::BufferBinding target,
+                                         size_t size);
+
+    ANGLE_INLINE uint8_t *getShadowBuffer(size_t offset)
+    {
+        return (mShadowBuffer.getCurrentBuffer() + offset);
+    }
+
+    ANGLE_INLINE const uint8_t *getShadowBuffer(size_t offset) const
+    {
+        return (mShadowBuffer.getCurrentBuffer() + offset);
+    }
+
+    void updateShadowBuffer(const uint8_t *data, size_t size, size_t offset);
+    angle::Result directUpdate(ContextVk *contextVk,
+                               const uint8_t *data,
+                               size_t size,
+                               size_t offset);
+    angle::Result stagedUpdate(ContextVk *contextVk,
+                               const uint8_t *data,
+                               size_t size,
+                               size_t offset);
     angle::Result setDataImpl(ContextVk *contextVk,
                               const uint8_t *data,
                               size_t size,
@@ -145,6 +168,13 @@
     // All staging buffer support is provided by a DynamicBuffer.
     vk::DynamicBuffer mStagingBuffer;
 
+    // For GPU-read only buffers glMap* latency is reduced by maintaining a copy
+    // of the buffer which is writeable only by the CPU. The contents are updated on all
+    // glData/glSubData/glCopy calls. With this, a glMap* call becomes a non-blocking
+    // operation by elimnating the need to wait on any recorded or in-flight GPU commands.
+    // We use DynamicShadowBuffer class to encapsulate all the bookeeping logic.
+    vk::DynamicShadowBuffer mShadowBuffer;
+
     // A cache of converted vertex data.
     std::vector<VertexConversionBuffer> mVertexConversionBuffers;
 };
diff --git a/src/libANGLE/renderer/vulkan/ContextVk.cpp b/src/libANGLE/renderer/vulkan/ContextVk.cpp
index 6d1226a..35cde1a 100644
--- a/src/libANGLE/renderer/vulkan/ContextVk.cpp
+++ b/src/libANGLE/renderer/vulkan/ContextVk.cpp
@@ -100,6 +100,18 @@
     }
 }
 
+constexpr gl::ShaderMap<vk::ImageLayout> kShaderReadOnlyImageLayouts = {
+    {gl::ShaderType::Vertex, vk::ImageLayout::VertexShaderReadOnly},
+    {gl::ShaderType::Fragment, vk::ImageLayout::FragmentShaderReadOnly},
+    {gl::ShaderType::Geometry, vk::ImageLayout::GeometryShaderReadOnly},
+    {gl::ShaderType::Compute, vk::ImageLayout::ComputeShaderReadOnly}};
+
+constexpr gl::ShaderMap<vk::ImageLayout> kShaderWriteImageLayouts = {
+    {gl::ShaderType::Vertex, vk::ImageLayout::VertexShaderWrite},
+    {gl::ShaderType::Fragment, vk::ImageLayout::FragmentShaderWrite},
+    {gl::ShaderType::Geometry, vk::ImageLayout::GeometryShaderWrite},
+    {gl::ShaderType::Compute, vk::ImageLayout::ComputeShaderWrite}};
+
 constexpr VkColorComponentFlags kAllColorChannelsMask =
     (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT |
      VK_COLOR_COMPONENT_A_BIT);
@@ -290,11 +302,11 @@
                        kDriverUniformsAllocatorPageSize, true);
 }
 
-void ContextVk::DriverUniformsDescriptorSet::destroy(VkDevice device)
+void ContextVk::DriverUniformsDescriptorSet::destroy(RendererVk *renderer)
 {
     descriptorSetLayout.reset();
     descriptorPoolBinding.reset();
-    dynamicBuffer.destroy(device);
+    dynamicBuffer.destroy(renderer);
 }
 
 // CommandBatch implementation.
@@ -385,7 +397,7 @@
         {
             for (vk::GarbageObject &garbage : garbageList.get())
             {
-                garbage.destroy(device);
+                garbage.destroy(renderer);
             }
         }
         else
@@ -428,13 +440,13 @@
     return angle::Result::Continue;
 }
 
-void CommandQueue::clearAllGarbage(VkDevice device)
+void CommandQueue::clearAllGarbage(RendererVk *renderer)
 {
     for (vk::GarbageAndSerial &garbageList : mGarbageQueue)
     {
         for (vk::GarbageObject &garbage : garbageList.get())
         {
-            garbage.destroy(device);
+            garbage.destroy(renderer);
         }
     }
     mGarbageQueue.clear();
@@ -598,6 +610,9 @@
       mVertexArray(nullptr),
       mDrawFramebuffer(nullptr),
       mProgram(nullptr),
+      mExecutable(nullptr),
+      mActiveQueryAnySamples(nullptr),
+      mActiveQueryAnySamplesConservative(nullptr),
       mLastIndexBufferOffset(0),
       mCurrentDrawElementsType(gl::DrawElementsType::InvalidEnum),
       mXfbBaseVertex(0),
@@ -638,6 +653,7 @@
     if (getFeatures().supportsTransformFeedbackExtension.enabled)
     {
         mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_STATE);
+        mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME);
     }
     mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
     mNewGraphicsCommandBufferDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS_BINDING);
@@ -648,6 +664,12 @@
     mNewComputeCommandBufferDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
     mNewComputeCommandBufferDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS_BINDING);
 
+    mNewGraphicsPipelineDirtyBits.set(DIRTY_BIT_PIPELINE);
+    if (getFeatures().supportsTransformFeedbackExtension.enabled)
+    {
+        mNewGraphicsPipelineDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME);
+    }
+
     mGraphicsDirtyBitHandlers[DIRTY_BIT_DEFAULT_ATTRIBS] =
         &ContextVk::handleDirtyGraphicsDefaultAttribs;
     mGraphicsDirtyBitHandlers[DIRTY_BIT_PIPELINE] = &ContextVk::handleDirtyGraphicsPipeline;
@@ -667,6 +689,8 @@
             &ContextVk::handleDirtyGraphicsTransformFeedbackBuffersExtension;
         mGraphicsDirtyBitHandlers[DIRTY_BIT_TRANSFORM_FEEDBACK_STATE] =
             &ContextVk::handleDirtyGraphicsTransformFeedbackState;
+        mGraphicsDirtyBitHandlers[DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME] =
+            &ContextVk::handleDirtyGraphicsTransformFeedbackResume;
     }
     else if (getFeatures().emulateTransformFeedback.enabled)
     {
@@ -710,14 +734,14 @@
 
     for (DriverUniformsDescriptorSet &driverUniforms : mDriverUniforms)
     {
-        driverUniforms.destroy(device);
+        driverUniforms.destroy(mRenderer);
     }
 
     mDriverUniformsDescriptorPool.destroy(device);
 
     for (vk::DynamicBuffer &defaultBuffer : mDefaultAttribBuffers)
     {
-        defaultBuffer.destroy(device);
+        defaultBuffer.destroy(mRenderer);
     }
 
     for (vk::DynamicQueryPool &queryPool : mQueryPools)
@@ -898,11 +922,8 @@
     // TODO(jmadill): Use dirty bit. http://anglebug.com/3014
     if (!mRenderPassCommandBuffer)
     {
-        mGraphicsDirtyBits |= mNewGraphicsCommandBufferDirtyBits;
-
         gl::Rectangle scissoredRenderArea = mDrawFramebuffer->getScissoredRenderArea(this);
-        ANGLE_TRY(mDrawFramebuffer->startNewRenderPass(this, scissoredRenderArea,
-                                                       &mRenderPassCommandBuffer));
+        ANGLE_TRY(startRenderPass(scissoredRenderArea));
     }
 
     // We keep a local copy of the command buffer. It's possible that some state changes could
@@ -912,11 +933,16 @@
     *commandBufferOut = mRenderPassCommandBuffer;
     ASSERT(*commandBufferOut);
 
-    if (mProgram->dirtyUniforms())
+    if (mProgram && mProgram->dirtyUniforms())
     {
         ANGLE_TRY(mProgram->updateUniforms(this));
         mGraphicsDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
     }
+    else if (mProgramPipeline && mProgramPipeline->dirtyUniforms(getState()))
+    {
+        ANGLE_TRY(mProgramPipeline->updateUniforms(this));
+        mGraphicsDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
+    }
 
     // Update transform feedback offsets on every draw call.
     if (mState.isTransformFeedbackActiveUnpaused())
@@ -988,7 +1014,7 @@
                 const size_t byteCount = static_cast<size_t>(elementArrayBuffer->getSize()) -
                                          reinterpret_cast<uintptr_t>(indices);
                 ANGLE_TRY(mVertexArray->convertIndexBufferCPU(this, indexType, byteCount, src));
-                bufferVk->unmapImpl(this);
+                ANGLE_TRY(bufferVk->unmapImpl(this));
             }
             else
             {
@@ -1129,11 +1155,16 @@
     ANGLE_TRY(endRenderPass());
     *commandBufferOut = &mOutsideRenderPassCommands.getCommandBuffer();
 
-    if (mProgram->dirtyUniforms())
+    if (mProgram && mProgram->dirtyUniforms())
     {
         ANGLE_TRY(mProgram->updateUniforms(this));
         mComputeDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
     }
+    else if (mProgramPipeline && mProgramPipeline->dirtyUniforms(getState()))
+    {
+        ANGLE_TRY(mProgramPipeline->updateUniforms(this));
+        mComputeDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
+    }
 
     DirtyBits dirtyBits = mComputeDirtyBits;
 
@@ -1166,15 +1197,18 @@
 angle::Result ContextVk::handleDirtyGraphicsPipeline(const gl::Context *context,
                                                      vk::CommandBuffer *commandBuffer)
 {
+    ASSERT(mExecutable);
+    mExecutable->updateEarlyFragmentTestsOptimization(this);
+
     if (!mCurrentGraphicsPipeline)
     {
         const vk::GraphicsPipelineDesc *descPtr;
 
         // Draw call shader patching, shader compilation, and pipeline cache query.
-        ANGLE_TRY(
-            mProgram->getGraphicsPipeline(this, mCurrentDrawMode, *mGraphicsPipelineDesc,
-                                          mProgram->getState().getNonBuiltinAttribLocationsMask(),
-                                          &descPtr, &mCurrentGraphicsPipeline));
+        ANGLE_TRY(mExecutable->getGraphicsPipeline(
+            this, mCurrentDrawMode, *mGraphicsPipelineDesc,
+            context->getState().getProgramExecutable()->getNonBuiltinAttribLocationsMask(),
+            &descPtr, &mCurrentGraphicsPipeline));
         mGraphicsPipelineTransition.reset();
     }
     else if (mGraphicsPipelineTransition.any())
@@ -1183,13 +1217,12 @@
                 mGraphicsPipelineTransition, *mGraphicsPipelineDesc, &mCurrentGraphicsPipeline))
         {
             vk::PipelineHelper *oldPipeline = mCurrentGraphicsPipeline;
-
             const vk::GraphicsPipelineDesc *descPtr;
 
-            ANGLE_TRY(mProgram->getGraphicsPipeline(
+            ANGLE_TRY(mExecutable->getGraphicsPipeline(
                 this, mCurrentDrawMode, *mGraphicsPipelineDesc,
-                mProgram->getState().getNonBuiltinAttribLocationsMask(), &descPtr,
-                &mCurrentGraphicsPipeline));
+                context->getState().getProgramExecutable()->getNonBuiltinAttribLocationsMask(),
+                &descPtr, &mCurrentGraphicsPipeline));
 
             oldPipeline->addTransition(mGraphicsPipelineTransition, descPtr,
                                        mCurrentGraphicsPipeline);
@@ -1197,6 +1230,7 @@
 
         mGraphicsPipelineTransition.reset();
     }
+    mRenderPassCommands.pauseTransformFeedbackIfStarted();
     commandBuffer->bindGraphicsPipeline(mCurrentGraphicsPipeline->getPipeline());
     // Update the queue serial for the pipeline object.
     ASSERT(mCurrentGraphicsPipeline && mCurrentGraphicsPipeline->valid());
@@ -1209,7 +1243,8 @@
 {
     if (!mCurrentComputePipeline)
     {
-        ANGLE_TRY(mProgram->getComputePipeline(this, &mCurrentComputePipeline));
+        ASSERT(mExecutable);
+        ANGLE_TRY(mExecutable->getComputePipeline(this, &mCurrentComputePipeline));
     }
 
     commandBuffer->bindComputePipeline(mCurrentComputePipeline->get());
@@ -1219,11 +1254,11 @@
 }
 
 ANGLE_INLINE angle::Result ContextVk::handleDirtyTexturesImpl(
-    const gl::Context *context,
-    vk::CommandBuffer *commandBuffer,
     CommandBufferHelper *commandBufferHelper)
 {
-    const gl::ActiveTextureMask &activeTextures = mProgram->getState().getActiveSamplersMask();
+    const gl::ProgramExecutable *executable = mState.getProgramExecutable();
+    ASSERT(executable);
+    const gl::ActiveTextureMask &activeTextures = executable->getActiveSamplersMask();
 
     for (size_t textureUnit : activeTextures)
     {
@@ -1238,18 +1273,37 @@
         // Select the appropriate vk::ImageLayout depending on whether the texture is also bound as
         // a GL image, and whether the program is a compute or graphics shader.
         vk::ImageLayout textureLayout;
-        if (textureVk->isBoundAsImageTexture())
+        if (textureVk->isBoundAsImageTexture(mState.getContextID()))
         {
-            textureLayout = mProgram->getState().isCompute()
-                                ? vk::ImageLayout::ComputeShaderWrite
-                                : vk::ImageLayout::AllGraphicsShadersWrite;
+            textureLayout = executable->isCompute() ? vk::ImageLayout::ComputeShaderWrite
+                                                    : vk::ImageLayout::AllGraphicsShadersReadWrite;
         }
         else
         {
-            textureLayout = mProgram->getState().isCompute()
-                                ? vk::ImageLayout::ComputeShaderReadOnly
-                                : vk::ImageLayout::AllGraphicsShadersReadOnly;
+            gl::ShaderBitSet shaderBits =
+                executable->getSamplerShaderBitsForTextureUnitIndex(textureUnit);
+            if (shaderBits.any())
+            {
+                gl::ShaderType shader =
+                    static_cast<gl::ShaderType>(gl::ScanForward(shaderBits.bits()));
+                shaderBits.reset(shader);
+                // If we have multiple shader accessing it, we barrier against all shader stage read
+                // given that we only support vertex/frag shaders
+                if (shaderBits.any())
+                {
+                    textureLayout = vk::ImageLayout::AllGraphicsShadersReadOnly;
+                }
+                else
+                {
+                    textureLayout = kShaderReadOnlyImageLayouts[shader];
+                }
+            }
+            else
+            {
+                textureLayout = vk::ImageLayout::AllGraphicsShadersReadOnly;
+            }
         }
+        // Ensure the image is in read-only layout
         commandBufferHelper->imageRead(&mResourceUseList, image.getAspectFlags(), textureLayout,
                                        &image);
 
@@ -1265,9 +1319,9 @@
         }
     }
 
-    if (mProgram->hasTextures())
+    if (executable->hasTextures())
     {
-        ANGLE_TRY(mProgram->updateTexturesDescriptorSet(this));
+        ANGLE_TRY(mExecutable->updateTexturesDescriptorSet(this));
     }
 
     return angle::Result::Continue;
@@ -1276,19 +1330,19 @@
 angle::Result ContextVk::handleDirtyGraphicsTextures(const gl::Context *context,
                                                      vk::CommandBuffer *commandBuffer)
 {
-    return handleDirtyTexturesImpl(context, commandBuffer, &mRenderPassCommands);
+    return handleDirtyTexturesImpl(&mRenderPassCommands);
 }
 
 angle::Result ContextVk::handleDirtyComputeTextures(const gl::Context *context,
                                                     vk::CommandBuffer *commandBuffer)
 {
-    return handleDirtyTexturesImpl(context, commandBuffer, &mOutsideRenderPassCommands);
+    return handleDirtyTexturesImpl(&mOutsideRenderPassCommands);
 }
 
 angle::Result ContextVk::handleDirtyGraphicsVertexBuffers(const gl::Context *context,
                                                           vk::CommandBuffer *commandBuffer)
 {
-    uint32_t maxAttrib = mProgram->getState().getMaxActiveAttribLocation();
+    uint32_t maxAttrib = context->getState().getProgramExecutable()->getMaxActiveAttribLocation();
     const gl::AttribArray<VkBuffer> &bufferHandles = mVertexArray->getCurrentArrayBufferHandles();
     const gl::AttribArray<VkDeviceSize> &bufferOffsets =
         mVertexArray->getCurrentArrayBufferOffsets();
@@ -1299,7 +1353,8 @@
         mVertexArray->getCurrentArrayBuffers();
 
     // Mark all active vertex buffers as accessed.
-    gl::AttributesMask attribsMask = mProgram->getState().getActiveAttribLocationsMask();
+    const gl::ProgramExecutable *executable = context->getState().getProgramExecutable();
+    gl::AttributesMask attribsMask          = executable->getActiveAttribLocationsMask();
     for (size_t attribIndex : attribsMask)
     {
         vk::BufferHelper *arrayBuffer = arrayBufferResources[attribIndex];
@@ -1330,19 +1385,21 @@
 
 ANGLE_INLINE angle::Result ContextVk::handleDirtyShaderResourcesImpl(
     const gl::Context *context,
-    vk::CommandBuffer *commandBuffer,
     CommandBufferHelper *commandBufferHelper)
 {
-    if (mProgram->hasImages())
+    const gl::ProgramExecutable *executable = mState.getProgramExecutable();
+    ASSERT(executable);
+
+    if (executable->hasImages())
     {
         ANGLE_TRY(updateActiveImages(context, commandBufferHelper));
     }
 
-    if (mProgram->hasUniformBuffers() || mProgram->hasStorageBuffers() ||
-        mProgram->hasAtomicCounterBuffers() || mProgram->hasImages())
+    if (executable->hasUniformBuffers() || executable->hasStorageBuffers() ||
+        executable->hasAtomicCounterBuffers() || executable->hasImages())
     {
-        ANGLE_TRY(mProgram->updateShaderResourcesDescriptorSet(this, &mResourceUseList,
-                                                               commandBufferHelper));
+        ANGLE_TRY(mExecutable->updateShaderResourcesDescriptorSet(this, &mResourceUseList,
+                                                                  commandBufferHelper));
     }
     return angle::Result::Continue;
 }
@@ -1350,22 +1407,25 @@
 angle::Result ContextVk::handleDirtyGraphicsShaderResources(const gl::Context *context,
                                                             vk::CommandBuffer *commandBuffer)
 {
-    return handleDirtyShaderResourcesImpl(context, commandBuffer, &mRenderPassCommands);
+    return handleDirtyShaderResourcesImpl(context, &mRenderPassCommands);
 }
 
 angle::Result ContextVk::handleDirtyComputeShaderResources(const gl::Context *context,
                                                            vk::CommandBuffer *commandBuffer)
 {
-    return handleDirtyShaderResourcesImpl(context, commandBuffer, &mOutsideRenderPassCommands);
+    return handleDirtyShaderResourcesImpl(context, &mOutsideRenderPassCommands);
 }
 
 angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackBuffersEmulation(
     const gl::Context *context,
     vk::CommandBuffer *commandBuffer)
 {
-    if (mProgram->hasTransformFeedbackOutput() && mState.isTransformFeedbackActive())
+    const gl::ProgramExecutable *executable = mState.getProgramExecutable();
+    ASSERT(executable);
+
+    if (executable->hasTransformFeedbackOutput() && mState.isTransformFeedbackActive())
     {
-        size_t bufferCount = mProgram->getState().getTransformFeedbackBufferCount();
+        size_t bufferCount = executable->getTransformFeedbackBufferCount(mState);
         const std::vector<gl::OffsetBindingPointer<gl::Buffer>> &xfbBuffers =
             mState.getCurrentTransformFeedback()->getIndexedBuffers();
 
@@ -1381,7 +1441,9 @@
                 &mResourceUseList, VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, &bufferHelper);
         }
 
-        ANGLE_TRY(mProgram->updateTransformFeedbackDescriptorSet(this));
+        // TODO(http://anglebug.com/3570): Need to update to handle Program Pipelines
+        ANGLE_TRY(mProgram->getExecutable().updateTransformFeedbackDescriptorSet(
+            mProgram->getState(), mProgram->getDefaultUniformBlocks(), this));
     }
     return angle::Result::Continue;
 }
@@ -1390,13 +1452,16 @@
     const gl::Context *context,
     vk::CommandBuffer *commandBuffer)
 {
-    if (!mProgram->hasTransformFeedbackOutput() || !mState.isTransformFeedbackActive())
+    const gl::ProgramExecutable *executable = mState.getProgramExecutable();
+    ASSERT(executable);
+
+    if (!executable->hasTransformFeedbackOutput() || !mState.isTransformFeedbackActive())
         return angle::Result::Continue;
 
     size_t bufferIndex                       = 0;
     TransformFeedbackVk *transformFeedbackVk = vk::GetImpl(mState.getCurrentTransformFeedback());
 
-    size_t bufferCount = mProgram->getState().getTransformFeedbackBufferCount();
+    size_t bufferCount = executable->getTransformFeedbackBufferCount(mState);
     gl::TransformFeedbackBuffersArray<VkBuffer> bufferHandles;
 
     const std::vector<gl::OffsetBindingPointer<gl::Buffer>> &xfbBuffers =
@@ -1429,13 +1494,16 @@
 angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackState(const gl::Context *context,
                                                                    vk::CommandBuffer *commandBuffer)
 {
-    if (!mProgram->hasTransformFeedbackOutput() || !mState.isTransformFeedbackActiveUnpaused())
+    const gl::ProgramExecutable *executable = mState.getProgramExecutable();
+    ASSERT(executable);
+
+    if (!executable->hasTransformFeedbackOutput() || !mState.isTransformFeedbackActiveUnpaused())
         return angle::Result::Continue;
 
     TransformFeedbackVk *transformFeedbackVk = vk::GetImpl(mState.getCurrentTransformFeedback());
 
     // We should have same number of counter buffers as xfb buffers have
-    size_t bufferCount = mProgram->getState().getTransformFeedbackBufferCount();
+    size_t bufferCount = executable->getTransformFeedbackBufferCount(mState);
     const gl::TransformFeedbackBuffersArray<VkBuffer> &counterBufferHandles =
         transformFeedbackVk->getCounterBufferHandles();
 
@@ -1449,10 +1517,18 @@
     return angle::Result::Continue;
 }
 
+angle::Result ContextVk::handleDirtyGraphicsTransformFeedbackResume(
+    const gl::Context *context,
+    vk::CommandBuffer *commandBuffer)
+{
+    mRenderPassCommands.resumeTransformFeedbackIfStarted();
+    return angle::Result::Continue;
+}
+
 angle::Result ContextVk::handleDirtyDescriptorSets(const gl::Context *context,
                                                    vk::CommandBuffer *commandBuffer)
 {
-    ANGLE_TRY(mProgram->updateDescriptorSets(this, commandBuffer));
+    ANGLE_TRY(mExecutable->updateDescriptorSets(this, commandBuffer));
     return angle::Result::Continue;
 }
 
@@ -1612,7 +1688,7 @@
         commandBuffer.waitEvents(1, cpuReady.get().ptr(), VK_PIPELINE_STAGE_HOST_BIT,
                                  VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0, nullptr, 0, nullptr, 0,
                                  nullptr);
-        timestampQuery.writeTimestamp(&commandBuffer);
+        timestampQuery.writeTimestamp(this, &commandBuffer);
         commandBuffer.setEvent(gpuDone.get().getHandle(), VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT);
 
         ANGLE_VK_TRY(this, commandBuffer.end());
@@ -1702,7 +1778,7 @@
     gpuEvent.phase = phase;
     ANGLE_TRY(mGpuEventQueryPool.allocateQuery(this, &gpuEvent.queryHelper));
 
-    gpuEvent.queryHelper.writeTimestamp(commandBuffer);
+    gpuEvent.queryHelper.writeTimestamp(this, commandBuffer);
 
     mInFlightGpuEventQueries.push_back(std::move(gpuEvent));
     return angle::Result::Continue;
@@ -1808,13 +1884,12 @@
 
 void ContextVk::clearAllGarbage()
 {
-    VkDevice device = getDevice();
     for (vk::GarbageObject &garbage : mCurrentGarbage)
     {
-        garbage.destroy(device);
+        garbage.destroy(mRenderer);
     }
     mCurrentGarbage.clear();
-    mCommandQueue.clearAllGarbage(device);
+    mCommandQueue.clearAllGarbage(mRenderer);
 }
 
 void ContextVk::handleDeviceLost()
@@ -2075,7 +2150,7 @@
         // We have instanced vertex attributes that need to be emulated for Vulkan.
         // invalidate any cache and map the buffer so that we can read the indirect data.
         // Mapping the buffer will cause a flush.
-        ANGLE_TRY(currentIndirectBuf->invalidate(this, 0, sizeof(VkDrawIndirectCommand)));
+        ANGLE_TRY(currentIndirectBuf->invalidate(mRenderer, 0, sizeof(VkDrawIndirectCommand)));
         uint8_t *buffPtr;
         ANGLE_TRY(currentIndirectBuf->map(this, &buffPtr));
         const VkDrawIndirectCommand *indirectData =
@@ -2084,7 +2159,7 @@
         ANGLE_TRY(drawArraysInstanced(context, mode, indirectData->firstVertex,
                                       indirectData->vertexCount, indirectData->instanceCount));
 
-        currentIndirectBuf->unmap(getDevice());
+        currentIndirectBuf->unmap(mRenderer);
         return angle::Result::Continue;
     }
 
@@ -2129,7 +2204,8 @@
         // We have instanced vertex attributes that need to be emulated for Vulkan.
         // invalidate any cache and map the buffer so that we can read the indirect data.
         // Mapping the buffer will cause a flush.
-        ANGLE_TRY(currentIndirectBuf->invalidate(this, 0, sizeof(VkDrawIndexedIndirectCommand)));
+        ANGLE_TRY(
+            currentIndirectBuf->invalidate(mRenderer, 0, sizeof(VkDrawIndexedIndirectCommand)));
         uint8_t *buffPtr;
         ANGLE_TRY(currentIndirectBuf->map(this, &buffPtr));
         const VkDrawIndexedIndirectCommand *indirectData =
@@ -2138,7 +2214,7 @@
         ANGLE_TRY(drawElementsInstanced(context, mode, indirectData->indexCount, type, nullptr,
                                         indirectData->instanceCount));
 
-        currentIndirectBuf->unmap(getDevice());
+        currentIndirectBuf->unmap(mRenderer);
         return angle::Result::Continue;
     }
 
@@ -2203,8 +2279,7 @@
         (mRenderPassCommands.started() && !mRenderPassCommands.empty()) ||
         mRenderPassCommands.getRenderArea() != clearArea)
     {
-        mGraphicsDirtyBits |= mNewGraphicsCommandBufferDirtyBits;
-        ANGLE_TRY(mDrawFramebuffer->startNewRenderPass(this, clearArea, &mRenderPassCommandBuffer));
+        ANGLE_TRY(startRenderPass(clearArea));
     }
     else
     {
@@ -2287,6 +2362,43 @@
     return angle::Result::Continue;
 }
 
+void ContextVk::optimizeRenderPassForPresent(VkFramebuffer framebufferHandle)
+{
+    if (!mRenderPassCommands.started())
+    {
+        return;
+    }
+
+    if (framebufferHandle != mRenderPassCommands.getFramebufferHandle())
+    {
+        return;
+    }
+
+    RenderTargetVk *color0RenderTarget = mDrawFramebuffer->getColorDrawRenderTarget(0);
+    if (!color0RenderTarget)
+    {
+        return;
+    }
+
+    // EGL1.5 spec: The contents of ancillary buffers are always undefined after calling
+    // eglSwapBuffers
+    RenderTargetVk *depthStencilRenderTarget = mDrawFramebuffer->getDepthStencilRenderTarget();
+    if (depthStencilRenderTarget)
+    {
+        size_t depthStencilAttachmentIndexVk = mDrawFramebuffer->getDepthStencilAttachmentIndexVk();
+        // Change depthstencil attachment storeOp to DONT_CARE
+        mRenderPassCommands.invalidateRenderPassStencilAttachment(depthStencilAttachmentIndexVk);
+        mRenderPassCommands.invalidateRenderPassDepthAttachment(depthStencilAttachmentIndexVk);
+        // Mark content as invalid so that we will not load them in next renderpass
+        depthStencilRenderTarget->invalidateContent();
+    }
+
+    // Use finalLayout instead of extra barrier for layout change to present
+    vk::ImageHelper &image = color0RenderTarget->getImage();
+    image.setCurrentImageLayout(vk::ImageLayout::Present);
+    mRenderPassCommands.updateRenderPassAttachmentFinalLayout(0, image.getCurrentImageLayout());
+}
+
 gl::GraphicsResetStatus ContextVk::getResetStatus()
 {
     if (mRenderer->isDeviceLost())
@@ -2541,14 +2653,69 @@
     return angle::Result::Continue;
 }
 
+void ContextVk::invalidateProgramBindingHelper(const gl::State &glState)
+{
+    mExecutable = nullptr;
+
+    if (glState.getProgram())
+    {
+        mProgram    = vk::GetImpl(glState.getProgram());
+        mExecutable = &mProgram->getExecutable();
+    }
+    else
+    {
+        mProgram    = nullptr;
+        mExecutable = nullptr;
+    }
+
+    if (glState.getProgramPipeline())
+    {
+        mProgramPipeline = vk::GetImpl(glState.getProgramPipeline());
+        if (!mExecutable)
+        {
+            // A bound program always overrides a program pipeline
+            mExecutable = &mProgramPipeline->getExecutable();
+        }
+    }
+    else
+    {
+        mProgramPipeline = nullptr;
+    }
+}
+
+angle::Result ContextVk::invalidateProgramExecutableHelper(const gl::Context *context)
+{
+    const gl::State &glState = context->getState();
+
+    if (glState.getProgramExecutable()->isCompute())
+    {
+        invalidateCurrentComputePipeline();
+    }
+    else
+    {
+        // No additional work is needed here. We will update the pipeline desc
+        // later.
+        invalidateDefaultAttributes(context->getStateCache().getActiveDefaultAttribsMask());
+        invalidateVertexAndIndexBuffers();
+        bool useVertexBuffer = (glState.getProgramExecutable()->getMaxActiveAttribLocation() > 0);
+        mNonIndexedDirtyBitsMask.set(DIRTY_BIT_VERTEX_BUFFERS, useVertexBuffer);
+        mIndexedDirtyBitsMask.set(DIRTY_BIT_VERTEX_BUFFERS, useVertexBuffer);
+        mCurrentGraphicsPipeline = nullptr;
+        mGraphicsPipelineTransition.reset();
+    }
+
+    return angle::Result::Continue;
+}
+
 angle::Result ContextVk::syncState(const gl::Context *context,
                                    const gl::State::DirtyBits &dirtyBits,
                                    const gl::State::DirtyBits &bitMask)
 {
-    const gl::State &glState = context->getState();
+    const gl::State &glState                       = context->getState();
+    const gl::ProgramExecutable *programExecutable = glState.getProgramExecutable();
 
     if ((dirtyBits & mPipelineDirtyBitsMask).any() &&
-        (glState.getProgram() == nullptr || !glState.getProgram()->isCompute()))
+        (programExecutable == nullptr || !programExecutable->isCompute()))
     {
         invalidateCurrentGraphicsPipeline();
     }
@@ -2596,6 +2763,9 @@
             case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED:
                 mGraphicsPipelineDesc->updateAlphaToCoverageEnable(
                     &mGraphicsPipelineTransition, glState.isSampleAlphaToCoverageEnabled());
+                ASSERT(gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE >
+                       gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED);
+                iter.setLaterBit(gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE);
                 break;
             case gl::State::DIRTY_BIT_SAMPLE_COVERAGE_ENABLED:
                 updateSampleMask(glState);
@@ -2768,6 +2938,7 @@
                 mVertexArray = vk::GetImpl(glState.getVertexArray());
                 invalidateDefaultAttributes(context->getStateCache().getActiveDefaultAttribsMask());
                 mVertexArray->updateActiveAttribInfo(this);
+                setIndexBufferDirty();
                 break;
             }
             case gl::State::DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING:
@@ -2775,32 +2946,17 @@
             case gl::State::DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING:
                 break;
             case gl::State::DIRTY_BIT_PROGRAM_BINDING:
-                mProgram = vk::GetImpl(glState.getProgram());
+                invalidateProgramBindingHelper(glState);
                 break;
             case gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE:
             {
+                ASSERT(programExecutable);
                 invalidateCurrentDefaultUniforms();
                 ASSERT(gl::State::DIRTY_BIT_TEXTURE_BINDINGS >
                        gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE);
                 iter.setLaterBit(gl::State::DIRTY_BIT_TEXTURE_BINDINGS);
                 invalidateCurrentShaderResources();
-                if (glState.getProgram()->isCompute())
-                {
-                    invalidateCurrentComputePipeline();
-                }
-                else
-                {
-                    // No additional work is needed here. We will update the pipeline desc
-                    // later.
-                    invalidateDefaultAttributes(
-                        context->getStateCache().getActiveDefaultAttribsMask());
-                    invalidateVertexAndIndexBuffers();
-                    bool useVertexBuffer = (mProgram->getState().getMaxActiveAttribLocation() > 0);
-                    mNonIndexedDirtyBitsMask.set(DIRTY_BIT_VERTEX_BUFFERS, useVertexBuffer);
-                    mIndexedDirtyBitsMask.set(DIRTY_BIT_VERTEX_BUFFERS, useVertexBuffer);
-                    mCurrentGraphicsPipeline = nullptr;
-                    mGraphicsPipelineTransition.reset();
-                }
+                ANGLE_TRY(invalidateProgramExecutableHelper(context));
                 break;
             }
             case gl::State::DIRTY_BIT_SAMPLER_BINDINGS:
@@ -2843,8 +2999,6 @@
                 break;
             case gl::State::DIRTY_BIT_COVERAGE_MODULATION:
                 break;
-            case gl::State::DIRTY_BIT_PATH_RENDERING:
-                break;
             case gl::State::DIRTY_BIT_FRAMEBUFFER_SRGB:
                 break;
             case gl::State::DIRTY_BIT_CURRENT_VALUES:
@@ -3036,11 +3190,6 @@
     return new ProgramPipelineVk(state);
 }
 
-std::vector<PathImpl *> ContextVk::createPaths(GLsizei)
-{
-    return std::vector<PathImpl *>();
-}
-
 MemoryObjectImpl *ContextVk::createMemoryObject()
 {
     return new MemoryObjectVk();
@@ -3058,8 +3207,10 @@
 
 void ContextVk::invalidateCurrentDefaultUniforms()
 {
-    ASSERT(mProgram);
-    if (mProgram->hasDefaultUniforms())
+    const gl::ProgramExecutable *executable = mState.getProgramExecutable();
+    ASSERT(executable);
+
+    if (executable->hasDefaultUniforms())
     {
         mGraphicsDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
         mComputeDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
@@ -3068,8 +3219,10 @@
 
 angle::Result ContextVk::invalidateCurrentTextures(const gl::Context *context)
 {
-    ASSERT(mProgram);
-    if (mProgram->hasTextures())
+    const gl::ProgramExecutable *executable = mState.getProgramExecutable();
+    ASSERT(executable);
+
+    if (executable->hasTextures())
     {
         mGraphicsDirtyBits.set(DIRTY_BIT_TEXTURES);
         mGraphicsDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
@@ -3084,9 +3237,11 @@
 
 void ContextVk::invalidateCurrentShaderResources()
 {
-    ASSERT(mProgram);
-    if (mProgram->hasUniformBuffers() || mProgram->hasStorageBuffers() ||
-        mProgram->hasAtomicCounterBuffers() || mProgram->hasImages())
+    const gl::ProgramExecutable *executable = mState.getProgramExecutable();
+    ASSERT(executable);
+
+    if (executable->hasUniformBuffers() || executable->hasStorageBuffers() ||
+        executable->hasAtomicCounterBuffers() || executable->hasImages())
     {
         mGraphicsDirtyBits.set(DIRTY_BIT_SHADER_RESOURCES);
         mGraphicsDirtyBits.set(DIRTY_BIT_DESCRIPTOR_SETS);
@@ -3368,7 +3523,7 @@
     {
         TransformFeedbackVk *transformFeedbackVk =
             vk::GetImpl(mState.getCurrentTransformFeedback());
-        transformFeedbackVk->getBufferOffsets(this, mState.getProgram()->getState(), mXfbBaseVertex,
+        transformFeedbackVk->getBufferOffsets(this, mXfbBaseVertex,
                                               driverUniforms->xfbBufferOffsets.data(),
                                               driverUniforms->xfbBufferOffsets.size());
     }
@@ -3408,7 +3563,7 @@
     const DriverUniformsDescriptorSet &driverUniforms)
 {
     commandBuffer->bindDescriptorSets(
-        mProgram->getPipelineLayout(), bindPoint, kDriverUniformsDescriptorSetIndex, 1,
+        mExecutable->getPipelineLayout(), bindPoint, kDriverUniformsDescriptorSetIndex, 1,
         &driverUniforms.descriptorSet, 1, &driverUniforms.dynamicOffset);
 }
 
@@ -3512,16 +3667,17 @@
 
 angle::Result ContextVk::updateActiveTextures(const gl::Context *context)
 {
-    const gl::State &glState   = mState;
-    const gl::Program *program = glState.getProgram();
+    const gl::State &glState                = mState;
+    const gl::ProgramExecutable *executable = glState.getProgramExecutable();
+    ASSERT(executable);
 
     uint32_t prevMaxIndex = mActiveTexturesDesc.getMaxIndex();
     memset(mActiveTextures.data(), 0, sizeof(mActiveTextures[0]) * prevMaxIndex);
     mActiveTexturesDesc.reset();
 
-    const gl::ActiveTexturePointerArray &textures  = glState.getActiveTexturesCache();
-    const gl::ActiveTextureMask &activeTextures    = program->getActiveSamplersMask();
-    const gl::ActiveTextureTypeArray &textureTypes = program->getActiveSamplerTypes();
+    const gl::ActiveTexturesCache &textures        = glState.getActiveTexturesCache();
+    const gl::ActiveTextureMask &activeTextures    = executable->getActiveSamplersMask();
+    const gl::ActiveTextureTypeArray &textureTypes = executable->getActiveSamplerTypes();
 
     for (size_t textureUnit : activeTextures)
     {
@@ -3563,12 +3719,15 @@
 angle::Result ContextVk::updateActiveImages(const gl::Context *context,
                                             CommandBufferHelper *commandBufferHelper)
 {
-    const gl::State &glState   = mState;
-    const gl::Program *program = glState.getProgram();
+    const gl::State &glState                = mState;
+    const gl::ProgramExecutable *executable = glState.getProgramExecutable();
+    ASSERT(executable);
 
     mActiveImages.fill(nullptr);
 
-    const gl::ActiveTextureMask &activeImages = program->getActiveImagesMask();
+    const gl::ActiveTextureMask &activeImages = executable->getActiveImagesMask();
+    const gl::ActiveTextureArray<gl::ShaderBitSet> &activeImageShaderBits =
+        executable->getActiveImageShaderBits();
 
     // Note: currently, the image layout is transitioned entirely even if only one level or layer is
     // used.  This is an issue if one subresource of the image is used as framebuffer attachment and
@@ -3601,13 +3760,26 @@
         // The image should be flushed and ready to use at this point. There may still be
         // lingering staged updates in its staging buffer for unused texture mip levels or
         // layers. Therefore we can't verify it has no staged updates right here.
-
-        vk::ImageLayout imageLayout = vk::ImageLayout::AllGraphicsShadersWrite;
-        if (program->isCompute())
+        vk::ImageLayout imageLayout;
+        gl::ShaderBitSet shaderBits = activeImageShaderBits[imageUnitIndex];
+        if (shaderBits.any())
         {
-            imageLayout = vk::ImageLayout::ComputeShaderWrite;
+            gl::ShaderType shader = static_cast<gl::ShaderType>(gl::ScanForward(shaderBits.bits()));
+            shaderBits.reset(shader);
+            // This is accessed by multiple shaders
+            if (shaderBits.any())
+            {
+                imageLayout = vk::ImageLayout::AllGraphicsShadersReadWrite;
+            }
+            else
+            {
+                imageLayout = kShaderWriteImageLayouts[shader];
+            }
         }
-
+        else
+        {
+            imageLayout = vk::ImageLayout::AllGraphicsShadersReadWrite;
+        }
         VkImageAspectFlags aspectFlags = image->getAspectFlags();
 
         commandBufferHelper->imageWrite(&mResourceUseList, aspectFlags, imageLayout, image);
@@ -3838,7 +4010,7 @@
     beginInfo.pInheritanceInfo         = nullptr;
 
     ANGLE_VK_TRY(this, commandBuffer.begin(beginInfo));
-    timestampQuery.writeTimestamp(&commandBuffer);
+    timestampQuery.writeTimestamp(this, &commandBuffer);
     ANGLE_VK_TRY(this, commandBuffer.end());
 
     // Create fence for the submission
@@ -4049,14 +4221,45 @@
     return angle::Result::Continue;
 }
 
+ANGLE_INLINE angle::Result ContextVk::startRenderPass(gl::Rectangle renderArea)
+{
+    mGraphicsDirtyBits |= mNewGraphicsCommandBufferDirtyBits;
+    ANGLE_TRY(mDrawFramebuffer->startNewRenderPass(this, renderArea, &mRenderPassCommandBuffer));
+    if (mActiveQueryAnySamples)
+    {
+        mActiveQueryAnySamples->getQueryHelper()->beginOcclusionQuery(this, &mPrimaryCommands,
+                                                                      mRenderPassCommandBuffer);
+    }
+    if (mActiveQueryAnySamplesConservative)
+    {
+        mActiveQueryAnySamplesConservative->getQueryHelper()->beginOcclusionQuery(
+            this, &mPrimaryCommands, mRenderPassCommandBuffer);
+    }
+    return angle::Result::Continue;
+}
+
 angle::Result ContextVk::endRenderPass()
 {
-    onRenderPassFinished();
     if (mRenderPassCommands.empty())
     {
+        onRenderPassFinished();
         return angle::Result::Continue;
     }
 
+    if (mActiveQueryAnySamples)
+    {
+        mActiveQueryAnySamples->getQueryHelper()->endOcclusionQuery(this, mRenderPassCommandBuffer);
+        ANGLE_TRY(mActiveQueryAnySamples->stashQueryHelper(this));
+    }
+    if (mActiveQueryAnySamplesConservative)
+    {
+        mActiveQueryAnySamplesConservative->getQueryHelper()->endOcclusionQuery(
+            this, mRenderPassCommandBuffer);
+        ANGLE_TRY(mActiveQueryAnySamplesConservative->stashQueryHelper(this));
+    }
+
+    onRenderPassFinished();
+
     if (mGpuEventsEnabled)
     {
         mRenderPassCounter++;
@@ -4065,6 +4268,8 @@
         ANGLE_TRY(traceGpuEvent(&mPrimaryCommands, TRACE_EVENT_PHASE_BEGIN, eventName));
     }
 
+    mRenderPassCommands.pauseTransformFeedbackIfStarted();
+
     ANGLE_TRY(mRenderPassCommands.flushToPrimary(this, &mPrimaryCommands));
 
     if (mGpuEventsEnabled)
@@ -4170,6 +4375,58 @@
     }
 }
 
+void ContextVk::beginOcclusionQuery(QueryVk *queryVk)
+{
+    // To avoid complexity, we always start and end occlusion query inside renderpass. if renderpass
+    // not yet started, we just remember it and defer the start call.
+    if (mRenderPassCommands.started())
+    {
+        queryVk->getQueryHelper()->beginOcclusionQuery(this, &mPrimaryCommands,
+                                                       mRenderPassCommandBuffer);
+    }
+    if (queryVk->isAnySamplesQuery())
+    {
+        ASSERT(mActiveQueryAnySamples == nullptr);
+        mActiveQueryAnySamples = queryVk;
+    }
+    else if (queryVk->isAnySamplesConservativeQuery())
+    {
+        ASSERT(mActiveQueryAnySamplesConservative == nullptr);
+        mActiveQueryAnySamplesConservative = queryVk;
+    }
+    else
+    {
+        UNREACHABLE();
+    }
+}
+
+void ContextVk::endOcclusionQuery(QueryVk *queryVk)
+{
+    if (mRenderPassCommands.started())
+    {
+        queryVk->getQueryHelper()->endOcclusionQuery(this, mRenderPassCommandBuffer);
+    }
+    if (queryVk->isAnySamplesQuery())
+    {
+        ASSERT(mActiveQueryAnySamples == queryVk);
+        mActiveQueryAnySamples = nullptr;
+    }
+    else if (queryVk->isAnySamplesConservativeQuery())
+    {
+        ASSERT(mActiveQueryAnySamplesConservative == queryVk);
+        mActiveQueryAnySamplesConservative = nullptr;
+    }
+    else
+    {
+        UNREACHABLE();
+    }
+}
+
+bool ContextVk::isRobustResourceInitEnabled() const
+{
+    return mState.isRobustResourceInitEnabled();
+}
+
 CommandBufferHelper::CommandBufferHelper()
     : mImageBarrierSrcStageMask(0),
       mImageBarrierDstStageMask(0),
@@ -4399,15 +4656,7 @@
     }
     else
     {
-        uint32_t numCounterBuffers =
-            (mRebindTransformFeedbackBuffers) ? 0 : mValidTransformFeedbackBufferCount;
-
-        primary->beginTransformFeedbackEXT(0, numCounterBuffers,
-                                           mTransformFeedbackCounterBuffers.data(), nullptr);
         mCommandBuffer.executeCommands(primary->getHandle());
-        primary->endTransformFeedbackEXT(0, mValidTransformFeedbackBufferCount,
-                                         mTransformFeedbackCounterBuffers.data(), nullptr);
-
         primary->endRenderPass();
 
         // Would be better to accumulate this barrier using the command APIs.
@@ -4493,4 +4742,32 @@
     mValidTransformFeedbackBufferCount = 0;
     mRebindTransformFeedbackBuffers    = false;
 }
+
+void RenderPassCommandBuffer::resumeTransformFeedbackIfStarted()
+{
+    if (mValidTransformFeedbackBufferCount == 0)
+    {
+        return;
+    }
+
+    uint32_t numCounterBuffers =
+        mRebindTransformFeedbackBuffers ? 0 : mValidTransformFeedbackBufferCount;
+
+    mRebindTransformFeedbackBuffers = false;
+
+    mCommandBuffer.beginTransformFeedback(numCounterBuffers,
+                                          mTransformFeedbackCounterBuffers.data());
+}
+
+void RenderPassCommandBuffer::pauseTransformFeedbackIfStarted()
+{
+    if (mValidTransformFeedbackBufferCount == 0)
+    {
+        return;
+    }
+
+    mCommandBuffer.endTransformFeedback(mValidTransformFeedbackBufferCount,
+                                        mTransformFeedbackCounterBuffers.data());
+}
+
 }  // namespace rx
diff --git a/src/libANGLE/renderer/vulkan/ContextVk.h b/src/libANGLE/renderer/vulkan/ContextVk.h
index 72477cf..6c4d58f 100644
--- a/src/libANGLE/renderer/vulkan/ContextVk.h
+++ b/src/libANGLE/renderer/vulkan/ContextVk.h
@@ -26,6 +26,7 @@
 
 namespace rx
 {
+class ProgramExecutableVk;
 class RendererVk;
 class WindowSurfaceVk;
 
@@ -80,7 +81,7 @@
     angle::Result releasePrimaryCommandBuffer(vk::Context *context,
                                               vk::PrimaryCommandBuffer &&commandBuffer);
 
-    void clearAllGarbage(VkDevice device);
+    void clearAllGarbage(RendererVk *renderer);
 
     angle::Result finishToSerial(vk::Context *context, Serial serial, uint64_t timeout);
 
@@ -186,35 +187,41 @@
 
     void clearRenderPassColorAttachment(size_t attachmentIndex, const VkClearColorValue &clearValue)
     {
-        mAttachmentOps[attachmentIndex].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
-        mClearValues[attachmentIndex].color    = clearValue;
+        SetBitField(mAttachmentOps[attachmentIndex].loadOp, VK_ATTACHMENT_LOAD_OP_CLEAR);
+        mClearValues[attachmentIndex].color = clearValue;
     }
 
     void clearRenderPassDepthAttachment(size_t attachmentIndex, float depth)
     {
-        mAttachmentOps[attachmentIndex].loadOp           = VK_ATTACHMENT_LOAD_OP_CLEAR;
-        mClearValues[attachmentIndex].depthStencil.depth = depth;
+        SetBitField(mAttachmentOps[attachmentIndex].loadOp, VK_ATTACHMENT_LOAD_OP_CLEAR);
+        SetBitField(mClearValues[attachmentIndex].depthStencil.depth, depth);
     }
 
     void clearRenderPassStencilAttachment(size_t attachmentIndex, uint32_t stencil)
     {
-        mAttachmentOps[attachmentIndex].stencilLoadOp      = VK_ATTACHMENT_LOAD_OP_CLEAR;
-        mClearValues[attachmentIndex].depthStencil.stencil = stencil;
+        SetBitField(mAttachmentOps[attachmentIndex].stencilLoadOp, VK_ATTACHMENT_LOAD_OP_CLEAR);
+        SetBitField(mClearValues[attachmentIndex].depthStencil.stencil, stencil);
     }
 
     void invalidateRenderPassColorAttachment(size_t attachmentIndex)
     {
-        mAttachmentOps[attachmentIndex].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+        SetBitField(mAttachmentOps[attachmentIndex].storeOp, VK_ATTACHMENT_STORE_OP_DONT_CARE);
     }
 
     void invalidateRenderPassDepthAttachment(size_t attachmentIndex)
     {
-        mAttachmentOps[attachmentIndex].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+        SetBitField(mAttachmentOps[attachmentIndex].storeOp, VK_ATTACHMENT_STORE_OP_DONT_CARE);
     }
 
     void invalidateRenderPassStencilAttachment(size_t attachmentIndex)
     {
-        mAttachmentOps[attachmentIndex].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+        SetBitField(mAttachmentOps[attachmentIndex].stencilStoreOp,
+                    VK_ATTACHMENT_STORE_OP_DONT_CARE);
+    }
+
+    void updateRenderPassAttachmentFinalLayout(size_t attachmentIndex, vk::ImageLayout finalLayout)
+    {
+        SetBitField(mAttachmentOps[attachmentIndex].finalLayout, finalLayout);
     }
 
     const gl::Rectangle &getRenderArea() const { return mRenderArea; }
@@ -225,6 +232,9 @@
     bool started() const { return mRenderPassStarted; }
     void reset();
 
+    void resumeTransformFeedbackIfStarted();
+    void pauseTransformFeedbackIfStarted();
+
     uint32_t getAndResetCounter()
     {
         uint32_t count = mCounter;
@@ -232,6 +242,8 @@
         return count;
     }
 
+    VkFramebuffer getFramebufferHandle() const { return mFramebuffer.getHandle(); }
+
   private:
     void addRenderPassCommandDiagnostics(ContextVk *contextVk);
 
@@ -371,6 +383,9 @@
     bool isRotatedAspectRatioForDrawFBO() const;
     bool isRotatedAspectRatioForReadFBO() const;
 
+    void invalidateProgramBindingHelper(const gl::State &glState);
+    angle::Result invalidateProgramExecutableHelper(const gl::Context *context);
+
     // State sync with dirty bits.
     angle::Result syncState(const gl::Context *context,
                             const gl::State::DirtyBits &dirtyBits,
@@ -425,9 +440,6 @@
     // Program Pipeline object creation
     ProgramPipelineImpl *createProgramPipeline(const gl::ProgramPipelineState &data) override;
 
-    // Path object creation
-    std::vector<PathImpl *> createPaths(GLsizei) override;
-
     // Memory object creation.
     MemoryObjectImpl *createMemoryObject() override;
 
@@ -493,6 +505,8 @@
     void invalidateGraphicsDescriptorSet(uint32_t usedDescriptorSet);
     void invalidateComputeDescriptorSet(uint32_t usedDescriptorSet);
 
+    void optimizeRenderPassForPresent(VkFramebuffer framebufferHandle);
+
     vk::DynamicQueryPool *getQueryPool(gl::QueryType queryType);
 
     const VkClearValue &getClearColorValue() const;
@@ -650,6 +664,7 @@
     }
 
     egl::ContextPriority getContextPriority() const override { return mContextPriority; }
+    angle::Result startRenderPass(gl::Rectangle renderArea);
     angle::Result endRenderPass();
 
     angle::Result syncExternalMemory();
@@ -660,6 +675,20 @@
     size_t getVkIndexTypeSize(gl::DrawElementsType glIndexType) const;
     bool shouldConvertUint8VkIndexType(gl::DrawElementsType glIndexType) const;
 
+    ANGLE_INLINE bool isBresenhamEmulationEnabled(const gl::PrimitiveMode mode)
+    {
+        return getFeatures().basicGLLineRasterization.enabled && gl::IsLineMode(mode);
+    }
+
+    const ProgramExecutableVk *getExecutable() const { return mExecutable; }
+    ProgramExecutableVk *getExecutable() { return mExecutable; }
+
+    bool isRobustResourceInitEnabled() const override;
+
+    // occlusion query
+    void beginOcclusionQuery(QueryVk *queryVk);
+    void endOcclusionQuery(QueryVk *queryVk);
+
   private:
     // Dirty bits.
     enum DirtyBitType : size_t
@@ -674,6 +703,7 @@
         DIRTY_BIT_SHADER_RESOURCES,  // excluding textures, which are handled separately.
         DIRTY_BIT_TRANSFORM_FEEDBACK_BUFFERS,
         DIRTY_BIT_TRANSFORM_FEEDBACK_STATE,
+        DIRTY_BIT_TRANSFORM_FEEDBACK_RESUME,
         DIRTY_BIT_DESCRIPTOR_SETS,
         DIRTY_BIT_MAX,
     };
@@ -695,7 +725,7 @@
         ~DriverUniformsDescriptorSet();
 
         void init(RendererVk *rendererVk);
-        void destroy(VkDevice device);
+        void destroy(RendererVk *rendererVk);
     };
 
     enum class PipelineType
@@ -813,7 +843,10 @@
 
     ANGLE_INLINE void invalidateCurrentGraphicsPipeline()
     {
-        mGraphicsDirtyBits.set(DIRTY_BIT_PIPELINE);
+        mGraphicsDirtyBits |= mNewGraphicsPipelineDirtyBits;
+        // The draw mode may have changed, toggling whether line rasterization is
+        // enabled or not, which means we need to recreate the graphics pipeline.
+        mCurrentGraphicsPipeline = nullptr;
     }
     ANGLE_INLINE void invalidateCurrentComputePipeline()
     {
@@ -852,6 +885,8 @@
         vk::CommandBuffer *commandBuffer);
     angle::Result handleDirtyGraphicsTransformFeedbackState(const gl::Context *context,
                                                             vk::CommandBuffer *commandBuffer);
+    angle::Result handleDirtyGraphicsTransformFeedbackResume(const gl::Context *context,
+                                                             vk::CommandBuffer *commandBuffer);
 
     // Handlers for compute pipeline dirty bits.
     angle::Result handleDirtyComputePipeline(const gl::Context *context,
@@ -866,11 +901,8 @@
                                                     vk::CommandBuffer *commandBuffer);
 
     // Common parts of the common dirty bit handlers.
-    angle::Result handleDirtyTexturesImpl(const gl::Context *context,
-                                          vk::CommandBuffer *commandBuffer,
-                                          CommandBufferHelper *commandBufferHelper);
+    angle::Result handleDirtyTexturesImpl(CommandBufferHelper *commandBufferHelper);
     angle::Result handleDirtyShaderResourcesImpl(const gl::Context *context,
-                                                 vk::CommandBuffer *commandBuffer,
                                                  CommandBufferHelper *commandBufferHelper);
     void handleDirtyDriverUniformsBindingImpl(vk::CommandBuffer *commandBuffer,
                                               VkPipelineBindPoint bindPoint,
@@ -948,11 +980,18 @@
     DirtyBits mIndexedDirtyBitsMask;
     DirtyBits mNewGraphicsCommandBufferDirtyBits;
     DirtyBits mNewComputeCommandBufferDirtyBits;
+    DirtyBits mNewGraphicsPipelineDirtyBits;
 
     // Cached back-end objects.
     VertexArrayVk *mVertexArray;
     FramebufferVk *mDrawFramebuffer;
     ProgramVk *mProgram;
+    ProgramPipelineVk *mProgramPipeline;
+    ProgramExecutableVk *mExecutable;
+
+    // occlusion query
+    QueryVk *mActiveQueryAnySamples;
+    QueryVk *mActiveQueryAnySamplesConservative;
 
     // Graph resource used to record dispatch commands and hold resource dependencies.
     vk::DispatchHelper mDispatcher;
diff --git a/src/libANGLE/renderer/vulkan/DisplayVk.cpp b/src/libANGLE/renderer/vulkan/DisplayVk.cpp
index 294aa72..d45777c 100644
--- a/src/libANGLE/renderer/vulkan/DisplayVk.cpp
+++ b/src/libANGLE/renderer/vulkan/DisplayVk.cpp
@@ -23,7 +23,10 @@
 {
 
 DisplayVk::DisplayVk(const egl::DisplayState &state)
-    : DisplayImpl(state), vk::Context(new RendererVk()), mScratchBuffer(1000u)
+    : DisplayImpl(state),
+      vk::Context(new RendererVk()),
+      mScratchBuffer(1000u),
+      mHasSurfaceWithRobustInit(false)
 {}
 
 DisplayVk::~DisplayVk()
@@ -44,7 +47,7 @@
     mRenderer->reloadVolkIfNeeded();
 
     ASSERT(mRenderer);
-    mRenderer->onDestroy(this);
+    mRenderer->onDestroy();
 }
 
 egl::Error DisplayVk::makeCurrent(egl::Surface * /*drawSurface*/,
@@ -105,12 +108,22 @@
                                             EGLNativeWindowType window,
                                             const egl::AttributeMap &attribs)
 {
+    if (attribs.get(EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE, EGL_FALSE) == EGL_TRUE)
+    {
+        mHasSurfaceWithRobustInit = true;
+    }
+
     return createWindowSurfaceVk(state, window);
 }
 
 SurfaceImpl *DisplayVk::createPbufferSurface(const egl::SurfaceState &state,
                                              const egl::AttributeMap &attribs)
 {
+    if (attribs.get(EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE, EGL_FALSE) == EGL_TRUE)
+    {
+        mHasSurfaceWithRobustInit = true;
+    }
+
     ASSERT(mRenderer);
     return new OffscreenSurfaceVk(state);
 }
@@ -198,6 +211,7 @@
         getRenderer()->getFeatures().supportsAndroidHardwareBuffer.enabled;
     outExtensions->surfacelessContext = true;
     outExtensions->glColorspace = getRenderer()->getFeatures().supportsSwapchainColorspace.enabled;
+    outExtensions->imageGlColorspace = outExtensions->glColorspace;
 
 #if defined(ANGLE_PLATFORM_ANDROID)
     outExtensions->framebufferTargetANDROID = true;
@@ -259,4 +273,9 @@
     mRenderer->getFeatures().populateFeatureList(features);
 }
 
+bool DisplayVk::isRobustResourceInitEnabled() const
+{
+    // We return true if any surface was created with robust resource init enabled.
+    return mHasSurfaceWithRobustInit;
+}
 }  // namespace rx
diff --git a/src/libANGLE/renderer/vulkan/DisplayVk.h b/src/libANGLE/renderer/vulkan/DisplayVk.h
index 392eb1a..2ce1fb0 100644
--- a/src/libANGLE/renderer/vulkan/DisplayVk.h
+++ b/src/libANGLE/renderer/vulkan/DisplayVk.h
@@ -95,6 +95,8 @@
 
     void populateFeatureList(angle::FeatureList *features) override;
 
+    bool isRobustResourceInitEnabled() const override;
+
   protected:
     void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
 
@@ -108,6 +110,7 @@
     mutable angle::ScratchBuffer mScratchBuffer;
 
     std::string mStoredErrorString;
+    bool mHasSurfaceWithRobustInit;
 };
 
 }  // namespace rx
diff --git a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
index abe3ace..805ffc3 100644
--- a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
+++ b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
@@ -43,14 +43,6 @@
 // in case of a bug.
 constexpr VkClearValue kUninitializedClearValue = {{{0.95, 0.05, 0.95, 0.95}}};
 
-const gl::InternalFormat &GetReadAttachmentInfo(const gl::Context *context,
-                                                RenderTargetVk *renderTarget)
-{
-    GLenum implFormat =
-        renderTarget->getImageFormat().actualImageFormat().fboImplementationInternalFormat;
-    return gl::GetSizedInternalFormatInfo(implFormat);
-}
-
 bool HasSrcBlitFeature(RendererVk *renderer, RenderTargetVk *srcRenderTarget)
 {
     const VkFormat srcFormat = srcRenderTarget->getImageFormat().vkImageFormat;
@@ -114,7 +106,9 @@
     : FramebufferImpl(state),
       mBackbuffer(backbuffer),
       mFramebuffer(nullptr),
-      mActiveColorComponents(0)
+      mActiveColorComponents(0),
+      mSupportDepthStencilFeedbackLoops(
+          renderer->getFeatures().supportDepthStencilRenderingFeedbackLoops.enabled)
 {
     mReadPixelBuffer.init(renderer, VK_BUFFER_USAGE_TRANSFER_DST_BIT, kReadPixelsBufferAlignment,
                           kMinReadPixelsBufferSize, true);
@@ -229,6 +223,36 @@
     // The front-end should ensure we don't attempt to clear stencil if all bits are masked.
     ASSERT(!clearStencil || stencilMask != 0);
 
+    // Special case for rendering feedback loops: clears are always valid in GL since they don't
+    // sample from any textures.
+    if ((clearDepth || clearStencil) && mState.hasDepthStencilFeedbackLoop())
+    {
+        // We currently don't handle scissored clears with rendering feedback loops.
+        ANGLE_VK_CHECK(contextVk, scissoredRenderArea == getCompleteRenderArea(),
+                       VK_ERROR_INCOMPATIBLE_DRIVER);
+
+        RenderTargetVk *depthStencilRT = mRenderTargetCache.getDepthStencil(true);
+        vk::ImageHelper &image         = depthStencilRT->getImage();
+
+        vk::CommandBuffer *commandBuffer;
+        ANGLE_TRY(
+            contextVk->onImageWrite(image.getAspectFlags(), vk::ImageLayout::TransferDst, &image));
+        ANGLE_TRY(contextVk->endRenderPassAndGetCommandBuffer(&commandBuffer));
+
+        VkImageSubresourceRange range;
+        range.aspectMask     = image.getAspectFlags();
+        range.baseMipLevel   = depthStencilRT->getLevelIndex();
+        range.levelCount     = 1;
+        range.baseArrayLayer = depthStencilRT->getLayerIndex();
+        range.layerCount     = 1;
+
+        commandBuffer->clearDepthStencilImage(image.getImage(),
+                                              VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+                                              clearDepthStencilValue, 1, &range);
+        clearDepth   = false;
+        clearStencil = false;
+    }
+
     // If there is nothing to clear, return right away (for example, if asked to clear depth, but
     // there is no depth attachment).
     if (!clearColor && !clearDepth && !clearStencil)
@@ -388,21 +412,14 @@
                      clearValue.depthStencil);
 }
 
-GLenum FramebufferVk::getImplementationColorReadFormat(const gl::Context *context) const
+const gl::InternalFormat &FramebufferVk::getImplementationColorReadFormat(
+    const gl::Context *context) const
 {
-    return GetReadAttachmentInfo(context, mRenderTargetCache.getColorRead(mState)).format;
-}
-
-GLenum FramebufferVk::getImplementationColorReadType(const gl::Context *context) const
-{
-    GLenum readType = GetReadAttachmentInfo(context, mRenderTargetCache.getColorRead(mState)).type;
-    if (context->getClientMajorVersion() < 3 && readType == GL_HALF_FLOAT)
-    {
-        // GL_HALF_FLOAT was not introduced until GLES 3.0, and has a different value from
-        // GL_HALF_FLOAT_OES
-        readType = GL_HALF_FLOAT_OES;
-    }
-    return readType;
+    ContextVk *contextVk       = vk::GetImpl(context);
+    GLenum sizedFormat         = mState.getReadAttachment()->getFormat().info->sizedInternalFormat;
+    const vk::Format &vkFormat = contextVk->getRenderer()->getFormat(sizedFormat);
+    GLenum implFormat          = vkFormat.actualImageFormat().fboImplementationInternalFormat;
+    return gl::GetSizedInternalFormatInfo(implFormat);
 }
 
 angle::Result FramebufferVk::readPixels(const gl::Context *context,
@@ -412,7 +429,7 @@
                                         void *pixels)
 {
     // Clip read area to framebuffer.
-    const gl::Extents &fbSize = getState().getReadAttachment()->getSize();
+    const gl::Extents &fbSize = getState().getReadPixelsAttachment(format)->getSize();
     const gl::Rectangle fbRect(0, 0, fbSize.width, fbSize.height);
     ContextVk *contextVk = vk::GetImpl(context);
 
@@ -438,8 +455,8 @@
         params.reverseRowOrder = !params.reverseRowOrder;
     }
 
-    ANGLE_TRY(readPixelsImpl(contextVk, params.area, params, VK_IMAGE_ASPECT_COLOR_BIT,
-                             getColorReadRenderTarget(),
+    ANGLE_TRY(readPixelsImpl(contextVk, params.area, params, getReadPixelsAspectFlags(format),
+                             getReadPixelsRenderTarget(format),
                              static_cast<uint8_t *>(pixels) + outputSkipBytes));
     mReadPixelBuffer.releaseInFlightBuffers(contextVk);
     return angle::Result::Continue;
@@ -447,7 +464,9 @@
 
 RenderTargetVk *FramebufferVk::getDepthStencilRenderTarget() const
 {
-    return mRenderTargetCache.getDepthStencil();
+    // If we mask out depth/stencil feedback loops, do not allow the user to access the looped DS
+    // render target. Passing "false" to getDepthStencil forces a return of "nullptr" for loops.
+    return mRenderTargetCache.getDepthStencil(!mSupportDepthStencilFeedbackLoops);
 }
 
 RenderTargetVk *FramebufferVk::getColorDrawRenderTarget(size_t colorIndex) const
@@ -464,6 +483,31 @@
     return renderTarget;
 }
 
+RenderTargetVk *FramebufferVk::getReadPixelsRenderTarget(GLenum format) const
+{
+    switch (format)
+    {
+        case GL_DEPTH_COMPONENT:
+        case GL_STENCIL_INDEX_OES:
+            return getDepthStencilRenderTarget();
+        default:
+            return getColorReadRenderTarget();
+    }
+}
+
+VkImageAspectFlagBits FramebufferVk::getReadPixelsAspectFlags(GLenum format) const
+{
+    switch (format)
+    {
+        case GL_DEPTH_COMPONENT:
+            return VK_IMAGE_ASPECT_DEPTH_BIT;
+        case GL_STENCIL_INDEX_OES:
+            return VK_IMAGE_ASPECT_STENCIL_BIT;
+        default:
+            return VK_IMAGE_ASPECT_COLOR_BIT;
+    }
+}
+
 angle::Result FramebufferVk::blitWithCommand(ContextVk *contextVk,
                                              const gl::Rectangle &sourceArea,
                                              const gl::Rectangle &destArea,
@@ -737,7 +781,7 @@
     if (blitDepthBuffer || blitStencilBuffer)
     {
         RenderTargetVk *readRenderTarget = srcFramebufferVk->getDepthStencilRenderTarget();
-        RenderTargetVk *drawRenderTarget = mRenderTargetCache.getDepthStencil();
+        RenderTargetVk *drawRenderTarget = mRenderTargetCache.getDepthStencil(true);
         params.srcLayer                  = readRenderTarget->getLayerIndex();
 
         // Multisampled images are not allowed to have mips.
@@ -947,7 +991,7 @@
         ++attachmentIndexVk;
     }
 
-    RenderTargetVk *depthStencilRenderTarget = mRenderTargetCache.getDepthStencil();
+    RenderTargetVk *depthStencilRenderTarget = mRenderTargetCache.getDepthStencil(true);
     if (depthStencilRenderTarget)
     {
         if (invalidateDepthBuffer)
@@ -981,11 +1025,30 @@
     return angle::Result::Continue;
 }
 
+void FramebufferVk::updateDepthStencilAttachmentSerial(ContextVk *contextVk)
+{
+    RenderTargetVk *depthStencilRT = getDepthStencilRenderTarget();
+
+    if (depthStencilRT != nullptr)
+    {
+        mCurrentFramebufferDesc.update(vk::kFramebufferDescDepthStencilIndex,
+                                       depthStencilRT->getAssignSerial(contextVk));
+    }
+    else
+    {
+        mCurrentFramebufferDesc.update(vk::kFramebufferDescDepthStencilIndex,
+                                       vk::kZeroAttachmentSerial);
+    }
+}
+
 angle::Result FramebufferVk::syncState(const gl::Context *context,
+                                       GLenum binding,
                                        const gl::Framebuffer::DirtyBits &dirtyBits)
 {
     ContextVk *contextVk = vk::GetImpl(context);
 
+    vk::FramebufferDesc priorFramebufferDesc = mCurrentFramebufferDesc;
+
     // For any updated attachments we'll update their Serials below
     ASSERT(dirtyBits.any());
     for (size_t dirtyBit : dirtyBits)
@@ -994,45 +1057,15 @@
         {
             case gl::Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT:
                 ANGLE_TRY(mRenderTargetCache.updateDepthStencilRenderTarget(context, mState));
-                if (mRenderTargetCache.getDepthStencil() != nullptr)
-                {
-                    mCurrentFramebufferDesc.update(
-                        vk::kFramebufferDescDepthIndex,
-                        mRenderTargetCache.getDepthStencil()->getAssignSerial(contextVk));
-                }
-                else
-                {
-                    mCurrentFramebufferDesc.update(vk::kFramebufferDescDepthIndex,
-                                                   vk::kZeroAttachmentSerial);
-                }
+                updateDepthStencilAttachmentSerial(contextVk);
                 break;
             case gl::Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT:
                 ANGLE_TRY(mRenderTargetCache.updateDepthStencilRenderTarget(context, mState));
-                if (mRenderTargetCache.getDepthStencil() != nullptr)
-                {
-                    mCurrentFramebufferDesc.update(
-                        vk::kFramebufferDescStencilIndex,
-                        mRenderTargetCache.getDepthStencil()->getAssignSerial(contextVk));
-                }
-                else
-                {
-                    mCurrentFramebufferDesc.update(vk::kFramebufferDescStencilIndex,
-                                                   vk::kZeroAttachmentSerial);
-                }
+                updateDepthStencilAttachmentSerial(contextVk);
                 break;
             case gl::Framebuffer::DIRTY_BIT_DEPTH_BUFFER_CONTENTS:
-                ANGLE_TRY(mRenderTargetCache.getDepthStencil()->flushStagedUpdates(contextVk));
-                ASSERT(mRenderTargetCache.getDepthStencil() != nullptr);
-                mCurrentFramebufferDesc.update(
-                    vk::kFramebufferDescDepthIndex,
-                    mRenderTargetCache.getDepthStencil()->getAssignSerial(contextVk));
-                break;
             case gl::Framebuffer::DIRTY_BIT_STENCIL_BUFFER_CONTENTS:
-                ANGLE_TRY(mRenderTargetCache.getDepthStencil()->flushStagedUpdates(contextVk));
-                ASSERT(mRenderTargetCache.getDepthStencil() != nullptr);
-                mCurrentFramebufferDesc.update(
-                    vk::kFramebufferDescStencilIndex,
-                    mRenderTargetCache.getDepthStencil()->getAssignSerial(contextVk));
+                updateDepthStencilAttachmentSerial(contextVk);
                 break;
             case gl::Framebuffer::DIRTY_BIT_READ_BUFFER:
                 ANGLE_TRY(mRenderTargetCache.update(context, mState, dirtyBits));
@@ -1046,6 +1079,7 @@
                         static_cast<uint32_t>(colorIndexGL),
                         mRenderTargetCache.getColors()[colorIndexGL]->getAssignSerial(contextVk));
                 }
+                updateDepthStencilAttachmentSerial(contextVk);
                 break;
             case gl::Framebuffer::DIRTY_BIT_DEFAULT_WIDTH:
             case gl::Framebuffer::DIRTY_BIT_DEFAULT_HEIGHT:
@@ -1058,42 +1092,45 @@
             default:
             {
                 static_assert(gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 == 0, "FB dirty bits");
+                uint32_t colorIndexGL;
                 if (dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX)
                 {
-                    size_t colorIndexGL = static_cast<size_t>(
+                    colorIndexGL = static_cast<uint32_t>(
                         dirtyBit - gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0);
                     ANGLE_TRY(updateColorAttachment(context, colorIndexGL));
-                    if (mRenderTargetCache.getColors()[colorIndexGL] != nullptr &&
-                        mState.getEnabledDrawBuffers()[colorIndexGL])
-                    {
-                        mCurrentFramebufferDesc.update(
-                            static_cast<uint32_t>(colorIndexGL),
-                            mRenderTargetCache.getColors()[colorIndexGL]->getAssignSerial(
-                                contextVk));
-                    }
-                    else
-                    {
-                        mCurrentFramebufferDesc.update(static_cast<uint32_t>(colorIndexGL),
-                                                       vk::kZeroAttachmentSerial);
-                    }
                 }
                 else
                 {
                     ASSERT(dirtyBit >= gl::Framebuffer::DIRTY_BIT_COLOR_BUFFER_CONTENTS_0 &&
                            dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_BUFFER_CONTENTS_MAX);
-                    size_t colorIndexGL = static_cast<size_t>(
+                    colorIndexGL = static_cast<uint32_t>(
                         dirtyBit - gl::Framebuffer::DIRTY_BIT_COLOR_BUFFER_CONTENTS_0);
                     ANGLE_TRY(mRenderTargetCache.getColors()[colorIndexGL]->flushStagedUpdates(
                         contextVk));
-                    ASSERT(mRenderTargetCache.getColors()[colorIndexGL] != nullptr);
-                    mCurrentFramebufferDesc.update(
-                        static_cast<uint32_t>(colorIndexGL),
-                        mRenderTargetCache.getColors()[colorIndexGL]->getAssignSerial(contextVk));
                 }
+
+                RenderTargetVk *renderTarget = mRenderTargetCache.getColors()[colorIndexGL];
+
+                if (renderTarget && mState.getEnabledDrawBuffers()[colorIndexGL])
+                {
+                    mCurrentFramebufferDesc.update(colorIndexGL,
+                                                   renderTarget->getAssignSerial(contextVk));
+                }
+                else
+                {
+                    mCurrentFramebufferDesc.update(colorIndexGL, vk::kZeroAttachmentSerial);
+                }
+                break;
             }
         }
     }
 
+    // No-op redundant changes to prevent closing the RenderPass.
+    if (mCurrentFramebufferDesc == priorFramebufferDesc)
+    {
+        return angle::Result::Continue;
+    }
+
     // The FBO's new attachment may have changed the renderable area
     const gl::State &glState = context->getState();
     ANGLE_TRY(contextVk->updateScissor(glState));
@@ -1140,7 +1177,7 @@
         }
     }
 
-    RenderTargetVk *depthStencilRenderTarget = mRenderTargetCache.getDepthStencil();
+    RenderTargetVk *depthStencilRenderTarget = getDepthStencilRenderTarget();
     if (depthStencilRenderTarget)
     {
         mRenderPassDesc.packDepthStencilAttachment(
@@ -1199,7 +1236,7 @@
         attachmentsSize = colorRenderTarget->getExtents();
     }
 
-    RenderTargetVk *depthStencilRenderTarget = mRenderTargetCache.getDepthStencil();
+    RenderTargetVk *depthStencilRenderTarget = getDepthStencilRenderTarget();
     if (depthStencilRenderTarget)
     {
         const vk::ImageView *imageView = nullptr;
@@ -1233,6 +1270,9 @@
     vk::FramebufferHelper newFramebuffer;
     ANGLE_TRY(newFramebuffer.init(contextVk, framebufferInfo));
 
+    // Sanity check that our description matches our attachments. Can catch implementation bugs.
+    ASSERT(static_cast<uint32_t>(attachments.size()) == mCurrentFramebufferDesc.attachmentCount());
+
     mFramebufferCache[mCurrentFramebufferDesc] = std::move(newFramebuffer);
     mFramebuffer                               = &mFramebufferCache[mCurrentFramebufferDesc];
     *framebufferOut                            = &mFramebuffer->getFramebuffer();
@@ -1317,20 +1357,34 @@
 
         ANGLE_TRY(colorRenderTarget->onColorDraw(contextVk));
 
-        renderPassAttachmentOps.initWithLoadStore(attachmentClearValues.size(),
-                                                  VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
-                                                  VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
+        renderPassAttachmentOps.initWithStore(
+            attachmentClearValues.size(), VK_ATTACHMENT_LOAD_OP_LOAD,
+            vk::ImageLayout::ColorAttachment, vk::ImageLayout::ColorAttachment);
         attachmentClearValues.emplace_back(kUninitializedClearValue);
     }
 
-    RenderTargetVk *depthStencilRenderTarget = mRenderTargetCache.getDepthStencil();
+    RenderTargetVk *depthStencilRenderTarget = getDepthStencilRenderTarget();
     if (depthStencilRenderTarget)
     {
+        VkAttachmentLoadOp loadOp;
+        if (depthStencilRenderTarget->hasDefinedContent())
+        {
+            loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
+        }
+        else
+        {
+            loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+        }
+        renderPassAttachmentOps.initWithStore(attachmentClearValues.size(), loadOp,
+                                              vk::ImageLayout::DepthStencilAttachment,
+                                              vk::ImageLayout::DepthStencilAttachment);
+
+        // This must be called after hasDefinedContent() since it will set content to valid. We are
+        // tracking content valid very loosely here that as long as it is attached, it assumes will
+        // have valid content. The only time it has undefined content is between swap and
+        // startNewRenderPass
         ANGLE_TRY(depthStencilRenderTarget->onDepthStencilDraw(contextVk));
 
-        renderPassAttachmentOps.initWithLoadStore(attachmentClearValues.size(),
-                                                  VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
-                                                  VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
         attachmentClearValues.emplace_back(kUninitializedClearValue);
     }
 
@@ -1401,7 +1455,7 @@
         }
     }
 
-    return mRenderTargetCache.getDepthStencil();
+    return getDepthStencilRenderTarget();
 }
 
 GLint FramebufferVk::getSamples() const
diff --git a/src/libANGLE/renderer/vulkan/FramebufferVk.h b/src/libANGLE/renderer/vulkan/FramebufferVk.h
index 76a91fb..ea44388 100644
--- a/src/libANGLE/renderer/vulkan/FramebufferVk.h
+++ b/src/libANGLE/renderer/vulkan/FramebufferVk.h
@@ -69,8 +69,8 @@
                                 GLfloat depth,
                                 GLint stencil) override;
 
-    GLenum getImplementationColorReadFormat(const gl::Context *context) const override;
-    GLenum getImplementationColorReadType(const gl::Context *context) const override;
+    const gl::InternalFormat &getImplementationColorReadFormat(
+        const gl::Context *context) const override;
     angle::Result readPixels(const gl::Context *context,
                              const gl::Rectangle &area,
                              GLenum format,
@@ -86,6 +86,7 @@
     bool checkStatus(const gl::Context *context) const override;
 
     angle::Result syncState(const gl::Context *context,
+                            GLenum binding,
                             const gl::Framebuffer::DirtyBits &dirtyBits) override;
 
     angle::Result getSamplePosition(const gl::Context *context,
@@ -118,6 +119,12 @@
 
     const vk::RenderPassDesc &getRenderPassDesc() const { return mRenderPassDesc; }
     const vk::FramebufferDesc &getFramebufferDesc() const { return mCurrentFramebufferDesc; }
+    // We only support depth/stencil packed format and depthstencil attachment always follow all
+    // color attachments
+    size_t getDepthStencilAttachmentIndexVk() const
+    {
+        return getState().getEnabledDrawBuffers().count();
+    }
 
   private:
     FramebufferVk(RendererVk *renderer,
@@ -164,6 +171,10 @@
     angle::Result invalidateImpl(ContextVk *contextVk, size_t count, const GLenum *attachments);
     // Release all FramebufferVk objects in the cache and clear cache
     void clearCache(ContextVk *contextVk);
+    void updateDepthStencilAttachmentSerial(ContextVk *contextVk);
+
+    RenderTargetVk *getReadPixelsRenderTarget(GLenum format) const;
+    VkImageAspectFlagBits getReadPixelsAspectFlags(GLenum format) const;
 
     WindowSurfaceVk *mBackbuffer;
 
@@ -185,6 +196,7 @@
 
     vk::FramebufferDesc mCurrentFramebufferDesc;
     std::unordered_map<vk::FramebufferDesc, vk::FramebufferHelper> mFramebufferCache;
+    bool mSupportDepthStencilFeedbackLoops;
 };
 }  // namespace rx
 
diff --git a/src/libANGLE/renderer/vulkan/GlslangWrapperVk.cpp b/src/libANGLE/renderer/vulkan/GlslangWrapperVk.cpp
index 9bc93dd..9557ac6 100644
--- a/src/libANGLE/renderer/vulkan/GlslangWrapperVk.cpp
+++ b/src/libANGLE/renderer/vulkan/GlslangWrapperVk.cpp
@@ -21,43 +21,77 @@
     return angle::Result::Stop;
 }
 
-GlslangSourceOptions CreateSourceOptions(const angle::FeaturesVk &features)
+}  // namespace
+
+// static
+GlslangSourceOptions GlslangWrapperVk::CreateSourceOptions(const angle::FeaturesVk &features)
 {
     GlslangSourceOptions options;
-    options.uniformsAndXfbDescriptorSetIndex = kUniformsAndXfbDescriptorSetIndex;
-    options.textureDescriptorSetIndex        = kTextureDescriptorSetIndex;
-    options.shaderResourceDescriptorSetIndex = kShaderResourceDescriptorSetIndex;
-    options.driverUniformsDescriptorSetIndex = kDriverUniformsDescriptorSetIndex;
-    options.xfbBindingIndexStart             = kXfbBindingIndexStart;
-    options.useOldRewriteStructSamplers      = features.forceOldRewriteStructSamplers.enabled;
+
+    options.useOldRewriteStructSamplers = features.forceOldRewriteStructSamplers.enabled;
     options.supportsTransformFeedbackExtension =
         features.supportsTransformFeedbackExtension.enabled;
     options.emulateTransformFeedback = features.emulateTransformFeedback.enabled;
     options.emulateBresenhamLines    = features.basicGLLineRasterization.enabled;
+
     return options;
 }
-}  // namespace
+
+// static
+void GlslangWrapperVk::ResetGlslangProgramInterfaceInfo(
+    GlslangProgramInterfaceInfo *glslangProgramInterfaceInfo)
+{
+    glslangProgramInterfaceInfo->uniformsAndXfbDescriptorSetIndex =
+        kUniformsAndXfbDescriptorSetIndex;
+    glslangProgramInterfaceInfo->currentUniformBindingIndex = 0;
+    glslangProgramInterfaceInfo->textureDescriptorSetIndex  = kTextureDescriptorSetIndex;
+    glslangProgramInterfaceInfo->currentTextureBindingIndex = 0;
+    glslangProgramInterfaceInfo->shaderResourceDescriptorSetIndex =
+        kShaderResourceDescriptorSetIndex;
+    glslangProgramInterfaceInfo->currentShaderResourceBindingIndex = 0;
+    glslangProgramInterfaceInfo->driverUniformsDescriptorSetIndex =
+        kDriverUniformsDescriptorSetIndex;
+
+    glslangProgramInterfaceInfo->locationsUsedForXfbExtension = 0;
+}
 
 // static
 void GlslangWrapperVk::GetShaderSource(const angle::FeaturesVk &features,
                                        const gl::ProgramState &programState,
                                        const gl::ProgramLinkedResources &resources,
+                                       GlslangProgramInterfaceInfo *programInterfaceInfo,
                                        gl::ShaderMap<std::string> *shaderSourcesOut,
-                                       ShaderInterfaceVariableInfoMap *variableInfoMapOut)
+                                       ShaderMapInterfaceVariableInfoMap *variableInfoMapOut)
 {
-    GlslangGetShaderSource(CreateSourceOptions(features), programState, resources, shaderSourcesOut,
+    GlslangSourceOptions options = CreateSourceOptions(features);
+    GlslangGetShaderSource(options, programState, resources, programInterfaceInfo, shaderSourcesOut,
                            variableInfoMapOut);
 }
 
 // static
-angle::Result GlslangWrapperVk::GetShaderCode(vk::Context *context,
-                                              const gl::Caps &glCaps,
-                                              const gl::ShaderMap<std::string> &shaderSources,
-                                              const ShaderInterfaceVariableInfoMap &variableInfoMap,
-                                              gl::ShaderMap<std::vector<uint32_t>> *shaderCodeOut)
+angle::Result GlslangWrapperVk::GetShaderCode(
+    vk::Context *context,
+    const gl::Caps &glCaps,
+    const gl::ShaderMap<std::string> &shaderSources,
+    const ShaderMapInterfaceVariableInfoMap &variableInfoMap,
+    gl::ShaderMap<std::vector<uint32_t>> *shaderCodeOut)
 {
     return GlslangGetShaderSpirvCode(
         [context](GlslangError error) { return ErrorHandler(context, error); }, glCaps,
         shaderSources, variableInfoMap, shaderCodeOut);
 }
+
+// static
+angle::Result GlslangWrapperVk::TransformSpirV(
+    vk::Context *context,
+    const gl::ShaderType shaderType,
+    bool removeEarlyFragmentTestsOptimization,
+    const ShaderInterfaceVariableInfoMap &variableInfoMap,
+    const SpirvBlob &initialSpirvBlob,
+    SpirvBlob *shaderCodeOut)
+{
+    return GlslangTransformSpirvCode(
+        [context](GlslangError error) { return ErrorHandler(context, error); }, shaderType,
+        removeEarlyFragmentTestsOptimization, variableInfoMap, initialSpirvBlob, shaderCodeOut);
+}
 }  // namespace rx
diff --git a/src/libANGLE/renderer/vulkan/GlslangWrapperVk.h b/src/libANGLE/renderer/vulkan/GlslangWrapperVk.h
index fa4866c..3c1d3a8 100644
--- a/src/libANGLE/renderer/vulkan/GlslangWrapperVk.h
+++ b/src/libANGLE/renderer/vulkan/GlslangWrapperVk.h
@@ -25,17 +25,30 @@
 class GlslangWrapperVk
 {
   public:
+    static GlslangSourceOptions CreateSourceOptions(const angle::FeaturesVk &features);
+
+    static void ResetGlslangProgramInterfaceInfo(
+        GlslangProgramInterfaceInfo *glslangProgramInterfaceInfo);
+
     static void GetShaderSource(const angle::FeaturesVk &features,
                                 const gl::ProgramState &programState,
                                 const gl::ProgramLinkedResources &resources,
+                                GlslangProgramInterfaceInfo *programInterfaceInfo,
                                 gl::ShaderMap<std::string> *shaderSourcesOut,
-                                ShaderInterfaceVariableInfoMap *variableInfoMapOut);
+                                ShaderMapInterfaceVariableInfoMap *variableInfoMapOut);
 
     static angle::Result GetShaderCode(vk::Context *context,
                                        const gl::Caps &glCaps,
                                        const gl::ShaderMap<std::string> &shaderSources,
-                                       const ShaderInterfaceVariableInfoMap &variableInfoMap,
+                                       const ShaderMapInterfaceVariableInfoMap &variableInfoMap,
                                        gl::ShaderMap<std::vector<uint32_t>> *shaderCodesOut);
+
+    static angle::Result TransformSpirV(vk::Context *context,
+                                        const gl::ShaderType shaderType,
+                                        bool removeEarlyFragmentTestsOptimization,
+                                        const ShaderInterfaceVariableInfoMap &variableInfoMap,
+                                        const SpirvBlob &initialSpirvBlob,
+                                        SpirvBlob *shaderCodeOut);
 };
 }  // namespace rx
 
diff --git a/src/libANGLE/renderer/vulkan/MemoryObjectVk.cpp b/src/libANGLE/renderer/vulkan/MemoryObjectVk.cpp
index 32d3e8e..948e092 100644
--- a/src/libANGLE/renderer/vulkan/MemoryObjectVk.cpp
+++ b/src/libANGLE/renderer/vulkan/MemoryObjectVk.cpp
@@ -95,6 +95,12 @@
     }
 }
 
+angle::Result MemoryObjectVk::setDedicatedMemory(const gl::Context *context, bool dedicatedMemory)
+{
+    UNIMPLEMENTED();
+    return angle::Result::Continue;
+}
+
 angle::Result MemoryObjectVk::importFd(gl::Context *context,
                                        GLuint64 size,
                                        gl::HandleType handleType,
diff --git a/src/libANGLE/renderer/vulkan/MemoryObjectVk.h b/src/libANGLE/renderer/vulkan/MemoryObjectVk.h
index 46f4452..b557fbf 100644
--- a/src/libANGLE/renderer/vulkan/MemoryObjectVk.h
+++ b/src/libANGLE/renderer/vulkan/MemoryObjectVk.h
@@ -23,6 +23,8 @@
 
     void onDestroy(const gl::Context *context) override;
 
+    angle::Result setDedicatedMemory(const gl::Context *context, bool dedicatedMemory) override;
+
     angle::Result importFd(gl::Context *context,
                            GLuint64 size,
                            gl::HandleType handleType,
diff --git a/src/libANGLE/renderer/vulkan/OWNERS b/src/libANGLE/renderer/vulkan/OWNERS
new file mode 100644
index 0000000..ebbbea6
--- /dev/null
+++ b/src/libANGLE/renderer/vulkan/OWNERS
@@ -0,0 +1,2 @@
+jmadill@chromium.org
+syoussefi@chromium.org
diff --git a/src/libANGLE/renderer/vulkan/OverlayVk.cpp b/src/libANGLE/renderer/vulkan/OverlayVk.cpp
index 1c82e5f..f62469a 100644
--- a/src/libANGLE/renderer/vulkan/OverlayVk.cpp
+++ b/src/libANGLE/renderer/vulkan/OverlayVk.cpp
@@ -70,12 +70,13 @@
 
 void OverlayVk::onDestroy(const gl::Context *context)
 {
-    VkDevice device = vk::GetImpl(context)->getDevice();
+    RendererVk *renderer = vk::GetImpl(context)->getRenderer();
+    VkDevice device      = renderer->getDevice();
 
-    mCulledWidgets.destroy(device);
+    mCulledWidgets.destroy(renderer);
     mCulledWidgetsView.destroy(device);
 
-    mFontImage.destroy(device);
+    mFontImage.destroy(renderer);
     mFontImageView.destroy(device);
 }
 
@@ -101,8 +102,8 @@
 
     mState.initFontData(fontData);
 
-    ANGLE_TRY(fontDataBuffer.get().flush(contextVk, 0, fontDataBuffer.get().getSize()));
-    fontDataBuffer.get().unmap(contextVk->getDevice());
+    ANGLE_TRY(fontDataBuffer.get().flush(renderer, 0, fontDataBuffer.get().getSize()));
+    fontDataBuffer.get().unmap(renderer);
 
     fontDataBuffer.get().onExternalWrite(VK_ACCESS_HOST_WRITE_BIT);
 
@@ -170,8 +171,8 @@
     gl::Extents presentImageExtents(mPresentImageExtent.width, mPresentImageExtent.height, 1);
     mState.fillEnabledWidgetCoordinates(presentImageExtents, enabledWidgets);
 
-    ANGLE_TRY(enabledWidgetsBuffer.get().flush(contextVk, 0, enabledWidgetsBuffer.get().getSize()));
-    enabledWidgetsBuffer.get().unmap(contextVk->getDevice());
+    ANGLE_TRY(enabledWidgetsBuffer.get().flush(renderer, 0, enabledWidgetsBuffer.get().getSize()));
+    enabledWidgetsBuffer.get().unmap(renderer);
 
     enabledWidgetsBuffer.get().onExternalWrite(VK_ACCESS_HOST_WRITE_BIT);
 
@@ -260,10 +261,10 @@
     gl::Extents presentImageExtents(mPresentImageExtent.width, mPresentImageExtent.height, 1);
     mState.fillWidgetData(presentImageExtents, textData, graphData);
 
-    ANGLE_TRY(textDataBuffer.get().flush(contextVk, 0, textDataBuffer.get().getSize()));
-    ANGLE_TRY(graphDataBuffer.get().flush(contextVk, 0, graphDataBuffer.get().getSize()));
-    textDataBuffer.get().unmap(contextVk->getDevice());
-    graphDataBuffer.get().unmap(contextVk->getDevice());
+    ANGLE_TRY(textDataBuffer.get().flush(renderer, 0, textDataBuffer.get().getSize()));
+    ANGLE_TRY(graphDataBuffer.get().flush(renderer, 0, graphDataBuffer.get().getSize()));
+    textDataBuffer.get().unmap(renderer);
+    graphDataBuffer.get().unmap(renderer);
 
     UtilsVk::OverlayDrawParameters params;
     params.subgroupSize[0] = mSubgroupSize[0];
diff --git a/src/libANGLE/renderer/vulkan/OverlayVk.h b/src/libANGLE/renderer/vulkan/OverlayVk.h
index 68188dc..ec74cf0 100644
--- a/src/libANGLE/renderer/vulkan/OverlayVk.h
+++ b/src/libANGLE/renderer/vulkan/OverlayVk.h
@@ -11,6 +11,7 @@
 #define LIBANGLE_RENDERER_VULKAN_OVERLAYVK_H_
 
 #include "common/angleutils.h"
+#include "libANGLE/Overlay.h"
 #include "libANGLE/renderer/OverlayImpl.h"
 #include "libANGLE/renderer/vulkan/vk_helpers.h"
 
@@ -31,6 +32,8 @@
                             vk::ImageHelper *imageToPresent,
                             const vk::ImageView *imageToPresentView);
 
+    uint32_t getEnabledWidgetCount() const { return mState.getEnabledWidgetCount(); }
+
   private:
     angle::Result createFont(ContextVk *contextVk);
     angle::Result cullWidgets(ContextVk *contextVk);
diff --git a/src/libANGLE/renderer/vulkan/ProgramExecutableVk.cpp b/src/libANGLE/renderer/vulkan/ProgramExecutableVk.cpp
new file mode 100644
index 0000000..e4fd521
--- /dev/null
+++ b/src/libANGLE/renderer/vulkan/ProgramExecutableVk.cpp
@@ -0,0 +1,1440 @@
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ProgramExecutableVk.cpp: Collects the information and interfaces common to both ProgramVks and
+// ProgramPipelineVks in order to execute/draw with either.
+
+#include "libANGLE/renderer/vulkan/ProgramExecutableVk.h"
+
+#include "libANGLE/renderer/glslang_wrapper_utils.h"
+#include "libANGLE/renderer/vulkan/BufferVk.h"
+#include "libANGLE/renderer/vulkan/GlslangWrapperVk.h"
+#include "libANGLE/renderer/vulkan/ProgramPipelineVk.h"
+#include "libANGLE/renderer/vulkan/ProgramVk.h"
+#include "libANGLE/renderer/vulkan/TextureVk.h"
+#include "libANGLE/renderer/vulkan/TransformFeedbackVk.h"
+#include "libANGLE/renderer/vulkan/vk_helpers.h"
+#include "libANGLE/renderer/vulkan/vk_utils.h"
+
+namespace rx
+{
+
+DefaultUniformBlock::DefaultUniformBlock() = default;
+
+DefaultUniformBlock::~DefaultUniformBlock() = default;
+
+// ShaderInfo implementation.
+ShaderInfo::ShaderInfo() {}
+
+ShaderInfo::~ShaderInfo() = default;
+
+angle::Result ShaderInfo::initShaders(ContextVk *contextVk,
+                                      const gl::ShaderMap<std::string> &shaderSources,
+                                      const ShaderMapInterfaceVariableInfoMap &variableInfoMap)
+{
+    ASSERT(!valid());
+
+    ANGLE_TRY(GlslangWrapperVk::GetShaderCode(contextVk, contextVk->getCaps(), shaderSources,
+                                              variableInfoMap, &mSpirvBlobs));
+
+    mIsInitialized = true;
+    return angle::Result::Continue;
+}
+
+void ShaderInfo::release(ContextVk *contextVk)
+{
+    for (SpirvBlob &spirvBlob : mSpirvBlobs)
+    {
+        spirvBlob.clear();
+    }
+    mIsInitialized = false;
+}
+
+void ShaderInfo::load(gl::BinaryInputStream *stream)
+{
+    // Read in shader codes for all shader types
+    for (const gl::ShaderType shaderType : gl::AllShaderTypes())
+    {
+        SpirvBlob *spirvBlob = &mSpirvBlobs[shaderType];
+
+        // Read the SPIR-V
+        stream->readIntVector<uint32_t>(spirvBlob);
+    }
+
+    mIsInitialized = true;
+}
+
+void ShaderInfo::save(gl::BinaryOutputStream *stream)
+{
+    ASSERT(valid());
+
+    // Write out shader codes for all shader types
+    for (const gl::ShaderType shaderType : gl::AllShaderTypes())
+    {
+        const SpirvBlob &spirvBlob = mSpirvBlobs[shaderType];
+
+        // Write the SPIR-V
+        stream->writeIntVector(spirvBlob);
+    }
+}
+
+// ProgramInfo implementation.
+ProgramInfo::ProgramInfo() {}
+
+ProgramInfo::~ProgramInfo() = default;
+
+angle::Result ProgramInfo::initProgram(ContextVk *contextVk,
+                                       const gl::ShaderType shaderType,
+                                       const ShaderInfo &shaderInfo,
+                                       const ShaderMapInterfaceVariableInfoMap &variableInfoMap,
+                                       ProgramTransformOptionBits optionBits)
+{
+    const gl::ShaderMap<SpirvBlob> &spirvBlobs = shaderInfo.getSpirvBlobs();
+
+    const SpirvBlob &spirvBlob = spirvBlobs[shaderType];
+
+    if (!spirvBlob.empty())
+    {
+        if (shaderType == gl::ShaderType::Fragment &&
+            optionBits[ProgramTransformOption::RemoveEarlyFragmentTestsOptimization])
+        {
+            SpirvBlob spirvBlobTransformed;
+            ANGLE_TRY(GlslangWrapperVk::TransformSpirV(contextVk, shaderType, true,
+                                                       variableInfoMap[shaderType], spirvBlob,
+                                                       &spirvBlobTransformed));
+            ANGLE_TRY(vk::InitShaderAndSerial(contextVk, &mShaders[shaderType].get(),
+                                              spirvBlobTransformed.data(),
+                                              spirvBlobTransformed.size() * sizeof(uint32_t)));
+        }
+        else
+        {
+            ANGLE_TRY(vk::InitShaderAndSerial(contextVk, &mShaders[shaderType].get(),
+                                              spirvBlob.data(),
+                                              spirvBlob.size() * sizeof(uint32_t)));
+        }
+
+        mProgramHelper.setShader(shaderType, &mShaders[shaderType]);
+    }
+
+    if (optionBits[ProgramTransformOption::EnableLineRasterEmulation])
+    {
+        mProgramHelper.enableSpecializationConstant(
+            sh::vk::SpecializationConstantId::LineRasterEmulation);
+    }
+
+    return angle::Result::Continue;
+}
+
+void ProgramInfo::release(ContextVk *contextVk)
+{
+    mProgramHelper.release(contextVk);
+
+    for (vk::RefCounted<vk::ShaderAndSerial> &shader : mShaders)
+    {
+        shader.get().destroy(contextVk->getDevice());
+    }
+}
+
+ProgramExecutableVk::ProgramExecutableVk()
+    : mEmptyDescriptorSets{},
+      mNumDefaultUniformDescriptors(0),
+      mPipelineLayoutCreated(false),
+      mDynamicBufferOffsets{},
+      mProgram(nullptr),
+      mProgramPipeline(nullptr)
+{}
+
+ProgramExecutableVk::~ProgramExecutableVk() = default;
+
+void ProgramExecutableVk::reset(ContextVk *contextVk)
+{
+    RendererVk *renderer = contextVk->getRenderer();
+
+    for (auto &descriptorSetLayout : mDescriptorSetLayouts)
+    {
+        descriptorSetLayout.reset();
+    }
+    mPipelineLayout.reset();
+
+    mEmptyBuffer.release(renderer);
+
+    mDescriptorSets.clear();
+    mEmptyDescriptorSets.fill(VK_NULL_HANDLE);
+    mPipelineLayoutCreated        = false;
+    mNumDefaultUniformDescriptors = 0;
+    mTransformOptionBits.reset();
+
+    for (vk::RefCountedDescriptorPoolBinding &binding : mDescriptorPoolBindings)
+    {
+        binding.reset();
+    }
+
+    for (vk::DynamicDescriptorPool &descriptorPool : mDynamicDescriptorPools)
+    {
+        descriptorPool.release(contextVk);
+    }
+
+    mTextureDescriptorsCache.clear();
+    mDescriptorBuffersCache.clear();
+
+    for (ProgramInfo &programInfo : mProgramInfos)
+    {
+        programInfo.release(contextVk);
+    }
+}
+
+std::unique_ptr<rx::LinkEvent> ProgramExecutableVk::load(gl::BinaryInputStream *stream)
+{
+    clearVariableInfoMap();
+
+    for (gl::ShaderType shaderType : gl::AllShaderTypes())
+    {
+        size_t variableInfoMapSize = stream->readInt<size_t>();
+
+        for (size_t i = 0; i < variableInfoMapSize; ++i)
+        {
+            const std::string variableName    = stream->readString();
+            ShaderInterfaceVariableInfo *info = &mVariableInfoMap[shaderType][variableName];
+
+            info->descriptorSet = stream->readInt<uint32_t>();
+            info->binding       = stream->readInt<uint32_t>();
+            info->location      = stream->readInt<uint32_t>();
+            info->component     = stream->readInt<uint32_t>();
+            // PackedEnumBitSet uses uint8_t
+            info->activeStages = gl::ShaderBitSet(stream->readInt<uint8_t>());
+            info->xfbBuffer    = stream->readInt<uint32_t>();
+            info->xfbOffset    = stream->readInt<uint32_t>();
+            info->xfbStride    = stream->readInt<uint32_t>();
+        }
+    }
+
+    return std::make_unique<LinkEventDone>(angle::Result::Continue);
+}
+
+void ProgramExecutableVk::save(gl::BinaryOutputStream *stream)
+{
+    for (gl::ShaderType shaderType : gl::AllShaderTypes())
+    {
+        stream->writeInt<size_t>(mVariableInfoMap[shaderType].size());
+        for (const auto &it : mVariableInfoMap[shaderType])
+        {
+            stream->writeString(it.first);
+            stream->writeInt<uint32_t>(it.second.descriptorSet);
+            stream->writeInt<uint32_t>(it.second.binding);
+            stream->writeInt<uint32_t>(it.second.location);
+            stream->writeInt<uint32_t>(it.second.component);
+            // PackedEnumBitSet uses uint8_t
+            stream->writeInt<uint8_t>(it.second.activeStages.bits());
+            stream->writeInt<uint32_t>(it.second.xfbBuffer);
+            stream->writeInt<uint32_t>(it.second.xfbOffset);
+            stream->writeInt<uint32_t>(it.second.xfbStride);
+        }
+    }
+}
+
+void ProgramExecutableVk::clearVariableInfoMap()
+{
+    for (const gl::ShaderType shaderType : gl::AllShaderTypes())
+    {
+        mVariableInfoMap[shaderType].clear();
+    }
+}
+
+ProgramVk *ProgramExecutableVk::getShaderProgram(const gl::State &glState,
+                                                 gl::ShaderType shaderType) const
+{
+    if (mProgram)
+    {
+        const gl::ProgramExecutable &glExecutable = mProgram->getState().getProgramExecutable();
+        if (glExecutable.hasLinkedShaderStage(shaderType))
+        {
+            return mProgram;
+        }
+    }
+    else if (mProgramPipeline)
+    {
+        return mProgramPipeline->getShaderProgram(glState, shaderType);
+    }
+
+    return nullptr;
+}
+
+// TODO: http://anglebug.com/3570: Move/Copy all of the necessary information into
+// the ProgramExecutable, so this function can be removed.
+void ProgramExecutableVk::fillProgramStateMap(
+    const ContextVk *contextVk,
+    gl::ShaderMap<const gl::ProgramState *> *programStatesOut)
+{
+    ASSERT(mProgram || mProgramPipeline);
+    if (mProgram)
+    {
+        mProgram->fillProgramStateMap(programStatesOut);
+    }
+    else if (mProgramPipeline)
+    {
+        mProgramPipeline->fillProgramStateMap(contextVk, programStatesOut);
+    }
+}
+
+const gl::ProgramExecutable &ProgramExecutableVk::getGlExecutable()
+{
+    ASSERT(mProgram || mProgramPipeline);
+    if (mProgram)
+    {
+        return mProgram->getState().getProgramExecutable();
+    }
+    return mProgramPipeline->getState().getProgramExecutable();
+}
+
+uint32_t GetInterfaceBlockArraySize(const std::vector<gl::InterfaceBlock> &blocks,
+                                    uint32_t bufferIndex)
+{
+    const gl::InterfaceBlock &block = blocks[bufferIndex];
+
+    if (!block.isArray)
+    {
+        return 1;
+    }
+
+    ASSERT(block.arrayElement == 0);
+
+    // Search consecutively until all array indices of this block are visited.
+    uint32_t arraySize;
+    for (arraySize = 1; bufferIndex + arraySize < blocks.size(); ++arraySize)
+    {
+        const gl::InterfaceBlock &nextBlock = blocks[bufferIndex + arraySize];
+
+        if (nextBlock.arrayElement != arraySize)
+        {
+            break;
+        }
+
+        // It's unexpected for an array to start at a non-zero array size, so we can always rely on
+        // the sequential `arrayElement`s to belong to the same block.
+        ASSERT(nextBlock.name == block.name);
+        ASSERT(nextBlock.isArray);
+    }
+
+    return arraySize;
+}
+
+angle::Result ProgramExecutableVk::allocateDescriptorSet(ContextVk *contextVk,
+                                                         uint32_t descriptorSetIndex)
+{
+    bool ignoreNewPoolAllocated;
+    return allocateDescriptorSetAndGetInfo(contextVk, descriptorSetIndex, &ignoreNewPoolAllocated);
+}
+
+angle::Result ProgramExecutableVk::allocateDescriptorSetAndGetInfo(ContextVk *contextVk,
+                                                                   uint32_t descriptorSetIndex,
+                                                                   bool *newPoolAllocatedOut)
+{
+    vk::DynamicDescriptorPool &dynamicDescriptorPool = mDynamicDescriptorPools[descriptorSetIndex];
+
+    uint32_t potentialNewCount = descriptorSetIndex + 1;
+    if (potentialNewCount > mDescriptorSets.size())
+    {
+        mDescriptorSets.resize(potentialNewCount, VK_NULL_HANDLE);
+    }
+
+    const vk::DescriptorSetLayout &descriptorSetLayout =
+        mDescriptorSetLayouts[descriptorSetIndex].get();
+    ANGLE_TRY(dynamicDescriptorPool.allocateSetsAndGetInfo(
+        contextVk, descriptorSetLayout.ptr(), 1, &mDescriptorPoolBindings[descriptorSetIndex],
+        &mDescriptorSets[descriptorSetIndex], newPoolAllocatedOut));
+    mEmptyDescriptorSets[descriptorSetIndex] = VK_NULL_HANDLE;
+
+    return angle::Result::Continue;
+}
+
+void ProgramExecutableVk::addInterfaceBlockDescriptorSetDesc(
+    const std::vector<gl::InterfaceBlock> &blocks,
+    const gl::ShaderType shaderType,
+    VkDescriptorType descType,
+    vk::DescriptorSetLayoutDesc *descOut)
+{
+    for (uint32_t bufferIndex = 0; bufferIndex < blocks.size();)
+    {
+        gl::InterfaceBlock block = blocks[bufferIndex];
+        const uint32_t arraySize = GetInterfaceBlockArraySize(blocks, bufferIndex);
+        bufferIndex += arraySize;
+
+        if (!block.isActive(shaderType))
+        {
+            continue;
+        }
+
+        const std::string blockName             = block.mappedName;
+        const ShaderInterfaceVariableInfo &info = mVariableInfoMap[shaderType][blockName];
+
+        descOut->update(info.binding, descType, arraySize, gl_vk::kShaderStageMap[shaderType]);
+    }
+}
+
+void ProgramExecutableVk::addAtomicCounterBufferDescriptorSetDesc(
+    const std::vector<gl::AtomicCounterBuffer> &atomicCounterBuffers,
+    const gl::ShaderType shaderType,
+    vk::DescriptorSetLayoutDesc *descOut)
+{
+    if (atomicCounterBuffers.empty())
+    {
+        return;
+    }
+
+    std::string blockName(sh::vk::kAtomicCountersBlockName);
+    const ShaderInterfaceVariableInfo &info = mVariableInfoMap[shaderType][blockName];
+
+    if (!info.activeStages[shaderType])
+    {
+        return;
+    }
+
+    // A single storage buffer array is used for all stages for simplicity.
+    descOut->update(info.binding, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+                    gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS,
+                    gl_vk::kShaderStageMap[shaderType]);
+}
+
+void ProgramExecutableVk::addImageDescriptorSetDesc(const gl::ProgramState &programState,
+                                                    vk::DescriptorSetLayoutDesc *descOut)
+{
+    const std::vector<gl::ImageBinding> &imageBindings = programState.getImageBindings();
+    const std::vector<gl::LinkedUniform> &uniforms     = programState.getUniforms();
+
+    for (uint32_t imageIndex = 0; imageIndex < imageBindings.size(); ++imageIndex)
+    {
+        const gl::ImageBinding &imageBinding = imageBindings[imageIndex];
+
+        uint32_t uniformIndex = programState.getUniformIndexFromImageIndex(imageIndex);
+        const gl::LinkedUniform &imageUniform = uniforms[uniformIndex];
+
+        // The front-end always binds array image units sequentially.
+        uint32_t arraySize = static_cast<uint32_t>(imageBinding.boundImageUnits.size());
+
+        for (const gl::ShaderType shaderType :
+             programState.getProgramExecutable().getLinkedShaderStages())
+        {
+            if (!imageUniform.isActive(shaderType))
+            {
+                continue;
+            }
+
+            std::string name = imageUniform.mappedName;
+            GetImageNameWithoutIndices(&name);
+            ShaderInterfaceVariableInfo &info = mVariableInfoMap[shaderType][name];
+            VkShaderStageFlags activeStages   = gl_vk::kShaderStageMap[shaderType];
+            descOut->update(info.binding, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, arraySize,
+                            activeStages);
+        }
+    }
+}
+
+void ProgramExecutableVk::addTextureDescriptorSetDesc(const gl::ProgramState &programState,
+                                                      bool useOldRewriteStructSamplers,
+                                                      vk::DescriptorSetLayoutDesc *descOut)
+{
+    const std::vector<gl::SamplerBinding> &samplerBindings = programState.getSamplerBindings();
+    const std::vector<gl::LinkedUniform> &uniforms         = programState.getUniforms();
+
+    for (uint32_t textureIndex = 0; textureIndex < samplerBindings.size(); ++textureIndex)
+    {
+        const gl::SamplerBinding &samplerBinding = samplerBindings[textureIndex];
+
+        uint32_t uniformIndex = programState.getUniformIndexFromSamplerIndex(textureIndex);
+        const gl::LinkedUniform &samplerUniform = uniforms[uniformIndex];
+
+        const std::string samplerName = useOldRewriteStructSamplers
+                                            ? GetMappedSamplerNameOld(samplerUniform.name)
+                                            : GlslangGetMappedSamplerName(samplerUniform.name);
+
+        // The front-end always binds array sampler units sequentially.
+        uint32_t arraySize = static_cast<uint32_t>(samplerBinding.boundTextureUnits.size());
+
+        if (!useOldRewriteStructSamplers)
+        {
+            // 2D arrays are split into multiple 1D arrays when generating
+            // LinkedUniforms. Since they are flattened into one array, ignore the
+            // nonzero elements and expand the array to the total array size.
+            if (gl::SamplerNameContainsNonZeroArrayElement(samplerUniform.name))
+            {
+                continue;
+            }
+
+            for (unsigned int outerArraySize : samplerUniform.outerArraySizes)
+            {
+                arraySize *= outerArraySize;
+            }
+        }
+
+        for (const gl::ShaderType shaderType :
+             programState.getProgramExecutable().getLinkedShaderStages())
+        {
+            if (!samplerUniform.isActive(shaderType))
+            {
+                continue;
+            }
+
+            ShaderInterfaceVariableInfo &info = mVariableInfoMap[shaderType][samplerName];
+            VkShaderStageFlags activeStages   = gl_vk::kShaderStageMap[shaderType];
+
+            descOut->update(info.binding, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, arraySize,
+                            activeStages);
+        }
+    }
+}
+
+void WriteBufferDescriptorSetBinding(const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding,
+                                     VkDeviceSize maxSize,
+                                     VkDescriptorSet descSet,
+                                     VkDescriptorType descType,
+                                     uint32_t bindingIndex,
+                                     uint32_t arrayElement,
+                                     VkDeviceSize requiredOffsetAlignment,
+                                     VkDescriptorBufferInfo *bufferInfoOut,
+                                     VkWriteDescriptorSet *writeInfoOut)
+{
+    gl::Buffer *buffer = bufferBinding.get();
+    ASSERT(buffer != nullptr);
+
+    // Make sure there's no possible under/overflow with binding size.
+    static_assert(sizeof(VkDeviceSize) >= sizeof(bufferBinding.getSize()),
+                  "VkDeviceSize too small");
+    ASSERT(bufferBinding.getSize() >= 0);
+
+    BufferVk *bufferVk             = vk::GetImpl(buffer);
+    VkDeviceSize offset            = bufferBinding.getOffset();
+    VkDeviceSize size              = bufferBinding.getSize();
+    vk::BufferHelper &bufferHelper = bufferVk->getBuffer();
+
+    // If size is 0, we can't always use VK_WHOLE_SIZE (or bufferHelper.getSize()), as the
+    // backing buffer may be larger than max*BufferRange.  In that case, we use the minimum of
+    // the backing buffer size (what's left after offset) and the buffer size as defined by the
+    // shader.  That latter is only valid for UBOs, as SSBOs may have variable length arrays.
+    size = size > 0 ? size : (bufferHelper.getSize() - offset);
+    if (maxSize > 0)
+    {
+        size = std::min(size, maxSize);
+    }
+
+    // If requiredOffsetAlignment is 0, the buffer offset is guaranteed to have the necessary
+    // alignment through other means (the backend specifying the alignment through a GLES limit that
+    // the frontend then enforces).  If it's not 0, we need to bind the buffer at an offset that's
+    // aligned.  The difference in offsets is communicated to the shader via driver uniforms.
+    if (requiredOffsetAlignment)
+    {
+        VkDeviceSize alignedOffset = (offset / requiredOffsetAlignment) * requiredOffsetAlignment;
+        VkDeviceSize offsetDiff    = offset - alignedOffset;
+
+        offset = alignedOffset;
+        size += offsetDiff;
+    }
+
+    bufferInfoOut->buffer = bufferHelper.getBuffer().getHandle();
+    bufferInfoOut->offset = offset;
+    bufferInfoOut->range  = size;
+
+    writeInfoOut->sType            = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+    writeInfoOut->pNext            = nullptr;
+    writeInfoOut->dstSet           = descSet;
+    writeInfoOut->dstBinding       = bindingIndex;
+    writeInfoOut->dstArrayElement  = arrayElement;
+    writeInfoOut->descriptorCount  = 1;
+    writeInfoOut->descriptorType   = descType;
+    writeInfoOut->pImageInfo       = nullptr;
+    writeInfoOut->pBufferInfo      = bufferInfoOut;
+    writeInfoOut->pTexelBufferView = nullptr;
+    ASSERT(writeInfoOut->pBufferInfo[0].buffer != VK_NULL_HANDLE);
+}
+
+void ProgramExecutableVk::updateEarlyFragmentTestsOptimization(ContextVk *contextVk)
+{
+    const gl::State &glState = contextVk->getState();
+
+    mTransformOptionBits[ProgramTransformOption::RemoveEarlyFragmentTestsOptimization] = false;
+    if (!glState.isEarlyFragmentTestsOptimizationAllowed())
+    {
+        ProgramVk *programVk = getShaderProgram(glState, gl::ShaderType::Fragment);
+        if (programVk->getState().hasEarlyFragmentTestsOptimization())
+        {
+            mTransformOptionBits[ProgramTransformOption::RemoveEarlyFragmentTestsOptimization] =
+                true;
+        }
+    }
+}
+
+angle::Result ProgramExecutableVk::getGraphicsPipeline(
+    ContextVk *contextVk,
+    gl::PrimitiveMode mode,
+    const vk::GraphicsPipelineDesc &desc,
+    const gl::AttributesMask &activeAttribLocations,
+    const vk::GraphicsPipelineDesc **descPtrOut,
+    vk::PipelineHelper **pipelineOut)
+{
+    const gl::State &glState = contextVk->getState();
+    mTransformOptionBits[ProgramTransformOption::EnableLineRasterEmulation] =
+        contextVk->isBresenhamEmulationEnabled(mode);
+    ProgramInfo &programInfo         = getProgramInfo(mTransformOptionBits);
+    RendererVk *renderer             = contextVk->getRenderer();
+    vk::PipelineCache *pipelineCache = nullptr;
+
+    const gl::ProgramExecutable *executable = glState.getProgramExecutable();
+    ASSERT(executable);
+
+    for (const gl::ShaderType shaderType : executable->getLinkedShaderStages())
+    {
+        ProgramVk *programVk = getShaderProgram(glState, shaderType);
+        if (programVk)
+        {
+            ANGLE_TRY(programVk->initGraphicsShaderProgram(contextVk, shaderType,
+                                                           mTransformOptionBits, programInfo));
+        }
+    }
+
+    vk::ShaderProgramHelper *shaderProgram = programInfo.getShaderProgram();
+    ASSERT(shaderProgram && shaderProgram->isGraphicsProgram());
+    ANGLE_TRY(renderer->getPipelineCache(&pipelineCache));
+    return shaderProgram->getGraphicsPipeline(
+        contextVk, &contextVk->getRenderPassCache(), *pipelineCache,
+        contextVk->getCurrentQueueSerial(), getPipelineLayout(), desc, activeAttribLocations,
+        glState.getProgramExecutable()->getAttributesTypeMask(), descPtrOut, pipelineOut);
+}
+
+angle::Result ProgramExecutableVk::getComputePipeline(ContextVk *contextVk,
+                                                      vk::PipelineAndSerial **pipelineOut)
+{
+    const gl::State &glState = contextVk->getState();
+    ProgramInfo &programInfo = getDefaultProgramInfo();
+
+    ProgramVk *programVk = getShaderProgram(glState, gl::ShaderType::Compute);
+    ASSERT(programVk);
+    ANGLE_TRY(programVk->initComputeProgram(contextVk, programInfo));
+
+    vk::ShaderProgramHelper *shaderProgram = programInfo.getShaderProgram();
+    ASSERT(shaderProgram && !shaderProgram->isGraphicsProgram());
+    return shaderProgram->getComputePipeline(contextVk, getPipelineLayout(), pipelineOut);
+}
+
+angle::Result ProgramExecutableVk::createPipelineLayout(const gl::Context *glContext)
+{
+    if (mPipelineLayoutCreated)
+    {
+        return angle::Result::Continue;
+    }
+
+    const gl::State &glState                   = glContext->getState();
+    ContextVk *contextVk                       = vk::GetImpl(glContext);
+    RendererVk *renderer                       = contextVk->getRenderer();
+    gl::TransformFeedback *transformFeedback   = glState.getCurrentTransformFeedback();
+    const gl::ProgramExecutable &glExecutable  = getGlExecutable();
+    const gl::ShaderBitSet &linkedShaderStages = glExecutable.getLinkedShaderStages();
+    gl::ShaderMap<const gl::ProgramState *> programStates;
+    fillProgramStateMap(contextVk, &programStates);
+
+    reset(contextVk);
+
+    // Store a reference to the pipeline and descriptor set layouts. This will create them if they
+    // don't already exist in the cache.
+
+    // Default uniforms and transform feedback:
+    vk::DescriptorSetLayoutDesc uniformsAndXfbSetDesc;
+    for (const gl::ShaderType shaderType : linkedShaderStages)
+    {
+        const std::string uniformBlockName = kDefaultUniformNames[shaderType];
+        ShaderInterfaceVariableInfo &info  = mVariableInfoMap[shaderType][uniformBlockName];
+        if (!info.activeStages[shaderType])
+        {
+            continue;
+        }
+
+        uniformsAndXfbSetDesc.update(info.binding, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1,
+                                     gl_vk::kShaderStageMap[shaderType]);
+        mNumDefaultUniformDescriptors++;
+    }
+    bool hasVertexShader = glExecutable.hasLinkedShaderStage(gl::ShaderType::Vertex);
+    bool hasXfbVaryings =
+        (programStates[gl::ShaderType::Vertex] &&
+         !programStates[gl::ShaderType::Vertex]->getLinkedTransformFeedbackVaryings().empty());
+    if (hasVertexShader && transformFeedback && hasXfbVaryings)
+    {
+        size_t xfbBufferCount =
+            programStates[gl::ShaderType::Vertex]->getTransformFeedbackBufferCount();
+        TransformFeedbackVk *transformFeedbackVk = vk::GetImpl(transformFeedback);
+        transformFeedbackVk->updateDescriptorSetLayout(contextVk,
+                                                       mVariableInfoMap[gl::ShaderType::Vertex],
+                                                       xfbBufferCount, &uniformsAndXfbSetDesc);
+    }
+
+    ANGLE_TRY(renderer->getDescriptorSetLayout(
+        contextVk, uniformsAndXfbSetDesc,
+        &mDescriptorSetLayouts[kUniformsAndXfbDescriptorSetIndex]));
+
+    // Uniform and storage buffers, atomic counter buffers and images:
+    vk::DescriptorSetLayoutDesc resourcesSetDesc;
+
+    for (const gl::ShaderType shaderType : linkedShaderStages)
+    {
+        addInterfaceBlockDescriptorSetDesc(programStates[shaderType]->getUniformBlocks(),
+                                           shaderType, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+                                           &resourcesSetDesc);
+        addInterfaceBlockDescriptorSetDesc(programStates[shaderType]->getShaderStorageBlocks(),
+                                           shaderType, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+                                           &resourcesSetDesc);
+        addAtomicCounterBufferDescriptorSetDesc(
+            programStates[shaderType]->getAtomicCounterBuffers(), shaderType, &resourcesSetDesc);
+    }
+
+    for (const gl::ShaderType shaderType : linkedShaderStages)
+    {
+        const gl::ProgramState *programState = programStates[shaderType];
+        ASSERT(programState);
+        addImageDescriptorSetDesc(*programState, &resourcesSetDesc);
+    }
+
+    ANGLE_TRY(renderer->getDescriptorSetLayout(
+        contextVk, resourcesSetDesc, &mDescriptorSetLayouts[kShaderResourceDescriptorSetIndex]));
+
+    // Textures:
+    vk::DescriptorSetLayoutDesc texturesSetDesc;
+
+    for (const gl::ShaderType shaderType : linkedShaderStages)
+    {
+        const gl::ProgramState *programState = programStates[shaderType];
+        ASSERT(programState);
+        addTextureDescriptorSetDesc(*programState, contextVk->useOldRewriteStructSamplers(),
+                                    &texturesSetDesc);
+    }
+
+    ANGLE_TRY(renderer->getDescriptorSetLayout(contextVk, texturesSetDesc,
+                                               &mDescriptorSetLayouts[kTextureDescriptorSetIndex]));
+
+    // Driver uniforms:
+    VkShaderStageFlags driverUniformsStages =
+        glExecutable.isCompute() ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_ALL_GRAPHICS;
+    vk::DescriptorSetLayoutDesc driverUniformsSetDesc =
+        contextVk->getDriverUniformsDescriptorSetDesc(driverUniformsStages);
+    ANGLE_TRY(renderer->getDescriptorSetLayout(
+        contextVk, driverUniformsSetDesc,
+        &mDescriptorSetLayouts[kDriverUniformsDescriptorSetIndex]));
+
+    // Create pipeline layout with these 4 descriptor sets.
+    vk::PipelineLayoutDesc pipelineLayoutDesc;
+    pipelineLayoutDesc.updateDescriptorSetLayout(kUniformsAndXfbDescriptorSetIndex,
+                                                 uniformsAndXfbSetDesc);
+    pipelineLayoutDesc.updateDescriptorSetLayout(kShaderResourceDescriptorSetIndex,
+                                                 resourcesSetDesc);
+    pipelineLayoutDesc.updateDescriptorSetLayout(kTextureDescriptorSetIndex, texturesSetDesc);
+    pipelineLayoutDesc.updateDescriptorSetLayout(kDriverUniformsDescriptorSetIndex,
+                                                 driverUniformsSetDesc);
+
+    ANGLE_TRY(renderer->getPipelineLayout(contextVk, pipelineLayoutDesc, mDescriptorSetLayouts,
+                                          &mPipelineLayout));
+
+    // Initialize descriptor pools.
+    std::array<VkDescriptorPoolSize, 2> uniformAndXfbSetSize = {
+        {{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
+          static_cast<uint32_t>(mNumDefaultUniformDescriptors)},
+         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS}}};
+
+    uint32_t uniformBlockCount        = 0;
+    uint32_t storageBlockCount        = 0;
+    uint32_t atomicCounterBufferCount = 0;
+    uint32_t imageCount               = 0;
+    uint32_t textureCount             = 0;
+    for (const gl::ShaderType shaderType : linkedShaderStages)
+    {
+        const gl::ProgramState *programState = programStates[shaderType];
+        ASSERT(programState);
+        // TODO(timvp): http://anglebug.com/3570: These counts will be too high for monolithic
+        // programs, since it's the same ProgramState for each shader type.
+        uniformBlockCount += static_cast<uint32_t>(programState->getUniformBlocks().size());
+        storageBlockCount += static_cast<uint32_t>(programState->getShaderStorageBlocks().size());
+        atomicCounterBufferCount +=
+            static_cast<uint32_t>(programState->getAtomicCounterBuffers().size());
+        imageCount += static_cast<uint32_t>(programState->getImageBindings().size());
+        textureCount += static_cast<uint32_t>(programState->getSamplerBindings().size());
+    }
+
+    if (renderer->getFeatures().bindEmptyForUnusedDescriptorSets.enabled)
+    {
+        // For this workaround, we have to create an empty descriptor set for each descriptor set
+        // index, so make sure their pools are initialized.
+        uniformBlockCount = std::max(uniformBlockCount, 1u);
+        textureCount      = std::max(textureCount, 1u);
+    }
+
+    constexpr size_t kResourceTypesInResourcesSet = 3;
+    angle::FixedVector<VkDescriptorPoolSize, kResourceTypesInResourcesSet> resourceSetSize;
+    if (uniformBlockCount > 0)
+    {
+        resourceSetSize.emplace_back(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, uniformBlockCount);
+    }
+    if (storageBlockCount > 0 || atomicCounterBufferCount > 0)
+    {
+        // Note that we always use an array of IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS storage
+        // buffers for emulating atomic counters, so if there are any atomic counter buffers, we
+        // need to allocate IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS descriptors.
+        const uint32_t atomicCounterStorageBufferCount =
+            atomicCounterBufferCount > 0 ? gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS : 0;
+        const uint32_t storageBufferDescCount = storageBlockCount + atomicCounterStorageBufferCount;
+        resourceSetSize.emplace_back(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, storageBufferDescCount);
+    }
+    if (imageCount > 0)
+    {
+        resourceSetSize.emplace_back(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, imageCount);
+    }
+
+    VkDescriptorPoolSize textureSetSize = {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, textureCount};
+
+    ANGLE_TRY(mDynamicDescriptorPools[kUniformsAndXfbDescriptorSetIndex].init(
+        contextVk, uniformAndXfbSetSize.data(), uniformAndXfbSetSize.size()));
+    if (resourceSetSize.size() > 0)
+    {
+        ANGLE_TRY(mDynamicDescriptorPools[kShaderResourceDescriptorSetIndex].init(
+            contextVk, resourceSetSize.data(), static_cast<uint32_t>(resourceSetSize.size())));
+    }
+    if (textureCount > 0)
+    {
+        ANGLE_TRY(mDynamicDescriptorPools[kTextureDescriptorSetIndex].init(contextVk,
+                                                                           &textureSetSize, 1));
+    }
+
+    mDynamicBufferOffsets.resize(glExecutable.getLinkedShaderStageCount());
+
+    // Initialize an "empty" buffer for use with default uniform blocks where there are no uniforms,
+    // or atomic counter buffer array indices that are unused.
+    constexpr VkBufferUsageFlags kEmptyBufferUsage =
+        VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
+
+    VkBufferCreateInfo emptyBufferInfo    = {};
+    emptyBufferInfo.sType                 = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+    emptyBufferInfo.flags                 = 0;
+    emptyBufferInfo.size                  = 4;
+    emptyBufferInfo.usage                 = kEmptyBufferUsage;
+    emptyBufferInfo.sharingMode           = VK_SHARING_MODE_EXCLUSIVE;
+    emptyBufferInfo.queueFamilyIndexCount = 0;
+    emptyBufferInfo.pQueueFamilyIndices   = nullptr;
+
+    constexpr VkMemoryPropertyFlags kMemoryType = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+    angle::Result status = mEmptyBuffer.init(contextVk, emptyBufferInfo, kMemoryType);
+
+    mPipelineLayoutCreated = true;
+
+    return status;
+}
+
+void ProgramExecutableVk::updateDefaultUniformsDescriptorSet(
+    const gl::ShaderType shaderType,
+    gl::ShaderMap<DefaultUniformBlock> &defaultUniformBlocks,
+    ContextVk *contextVk)
+{
+    const std::string uniformBlockName = kDefaultUniformNames[shaderType];
+    ShaderInterfaceVariableInfo &info  = mVariableInfoMap[shaderType][uniformBlockName];
+    if (!info.activeStages[shaderType])
+    {
+        return;
+    }
+
+    DefaultUniformBlock &uniformBlock = defaultUniformBlocks[shaderType];
+    VkDescriptorBufferInfo bufferInfo;
+    VkWriteDescriptorSet writeInfo;
+
+    if (!uniformBlock.uniformData.empty())
+    {
+        vk::BufferHelper *bufferHelper = uniformBlock.storage.getCurrentBuffer();
+        bufferInfo.buffer              = bufferHelper->getBuffer().getHandle();
+        mDescriptorBuffersCache.emplace_back(bufferHelper);
+    }
+    else
+    {
+        mEmptyBuffer.retain(&contextVk->getResourceUseList());
+        bufferInfo.buffer = mEmptyBuffer.getBuffer().getHandle();
+        mDescriptorBuffersCache.emplace_back(&mEmptyBuffer);
+    }
+
+    bufferInfo.offset = 0;
+    bufferInfo.range  = VK_WHOLE_SIZE;
+
+    writeInfo.sType            = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+    writeInfo.pNext            = nullptr;
+    writeInfo.dstSet           = mDescriptorSets[kUniformsAndXfbDescriptorSetIndex];
+    writeInfo.dstBinding       = info.binding;
+    writeInfo.dstArrayElement  = 0;
+    writeInfo.descriptorCount  = 1;
+    writeInfo.descriptorType   = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
+    writeInfo.pImageInfo       = nullptr;
+    writeInfo.pBufferInfo      = &bufferInfo;
+    writeInfo.pTexelBufferView = nullptr;
+
+    VkDevice device = contextVk->getDevice();
+
+    vkUpdateDescriptorSets(device, 1, &writeInfo, 0, nullptr);
+}
+
+void ProgramExecutableVk::updateBuffersDescriptorSet(ContextVk *contextVk,
+                                                     const gl::ShaderType shaderType,
+                                                     vk::ResourceUseList *resourceUseList,
+                                                     CommandBufferHelper *commandBufferHelper,
+                                                     const std::vector<gl::InterfaceBlock> &blocks,
+                                                     VkDescriptorType descriptorType)
+{
+    if (blocks.empty())
+    {
+        return;
+    }
+
+    VkDescriptorSet descriptorSet = mDescriptorSets[kShaderResourceDescriptorSetIndex];
+
+    ASSERT(descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ||
+           descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
+    const bool isStorageBuffer = descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+
+    static_assert(
+        gl::IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS >=
+            gl::IMPLEMENTATION_MAX_UNIFORM_BUFFER_BINDINGS,
+        "The descriptor arrays here would have inadequate size for uniform buffer objects");
+
+    gl::StorageBuffersArray<VkDescriptorBufferInfo> descriptorBufferInfo;
+    gl::StorageBuffersArray<VkWriteDescriptorSet> writeDescriptorInfo;
+    uint32_t writeCount = 0;
+
+    // Write uniform or storage buffers.
+    const gl::State &glState = contextVk->getState();
+    for (uint32_t bufferIndex = 0; bufferIndex < blocks.size(); ++bufferIndex)
+    {
+        const gl::InterfaceBlock &block = blocks[bufferIndex];
+        const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding =
+            isStorageBuffer ? glState.getIndexedShaderStorageBuffer(block.binding)
+                            : glState.getIndexedUniformBuffer(block.binding);
+
+        if (!block.isActive(shaderType))
+        {
+            continue;
+        }
+
+        if (bufferBinding.get() == nullptr)
+        {
+            continue;
+        }
+
+        ShaderInterfaceVariableInfo info = mVariableInfoMap[shaderType][block.mappedName];
+        uint32_t binding                 = info.binding;
+        uint32_t arrayElement            = block.isArray ? block.arrayElement : 0;
+        VkDeviceSize maxBlockSize        = isStorageBuffer ? 0 : block.dataSize;
+
+        VkDescriptorBufferInfo &bufferInfo = descriptorBufferInfo[writeCount];
+        VkWriteDescriptorSet &writeInfo    = writeDescriptorInfo[writeCount];
+
+        WriteBufferDescriptorSetBinding(bufferBinding, maxBlockSize, descriptorSet, descriptorType,
+                                        binding, arrayElement, 0, &bufferInfo, &writeInfo);
+
+        BufferVk *bufferVk             = vk::GetImpl(bufferBinding.get());
+        vk::BufferHelper &bufferHelper = bufferVk->getBuffer();
+
+        if (isStorageBuffer)
+        {
+            // We set the SHADER_READ_BIT to be conservative.
+            VkAccessFlags accessFlags = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
+            commandBufferHelper->bufferWrite(resourceUseList, accessFlags, &bufferHelper);
+        }
+        else
+        {
+            commandBufferHelper->bufferRead(resourceUseList, VK_ACCESS_UNIFORM_READ_BIT,
+                                            &bufferHelper);
+        }
+
+        ++writeCount;
+    }
+
+    VkDevice device = contextVk->getDevice();
+
+    vkUpdateDescriptorSets(device, writeCount, writeDescriptorInfo.data(), 0, nullptr);
+}
+
+void ProgramExecutableVk::updateAtomicCounterBuffersDescriptorSet(
+    const gl::ProgramState &programState,
+    const gl::ShaderType shaderType,
+    ContextVk *contextVk,
+    vk::ResourceUseList *resourceUseList,
+    CommandBufferHelper *commandBufferHelper)
+{
+    const gl::State &glState = contextVk->getState();
+    const std::vector<gl::AtomicCounterBuffer> &atomicCounterBuffers =
+        programState.getAtomicCounterBuffers();
+
+    if (atomicCounterBuffers.empty())
+    {
+        return;
+    }
+
+    VkDescriptorSet descriptorSet = mDescriptorSets[kShaderResourceDescriptorSetIndex];
+
+    std::string blockName(sh::vk::kAtomicCountersBlockName);
+    const ShaderInterfaceVariableInfo &info = mVariableInfoMap[shaderType][blockName];
+
+    if (!info.activeStages[shaderType])
+    {
+        return;
+    }
+
+    gl::AtomicCounterBuffersArray<VkDescriptorBufferInfo> descriptorBufferInfo;
+    gl::AtomicCounterBuffersArray<VkWriteDescriptorSet> writeDescriptorInfo;
+    gl::AtomicCounterBufferMask writtenBindings;
+
+    RendererVk *rendererVk = contextVk->getRenderer();
+    const VkDeviceSize requiredOffsetAlignment =
+        rendererVk->getPhysicalDeviceProperties().limits.minStorageBufferOffsetAlignment;
+
+    // Write atomic counter buffers.
+    for (uint32_t bufferIndex = 0; bufferIndex < atomicCounterBuffers.size(); ++bufferIndex)
+    {
+        const gl::AtomicCounterBuffer &atomicCounterBuffer = atomicCounterBuffers[bufferIndex];
+        uint32_t binding                                   = atomicCounterBuffer.binding;
+        const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding =
+            glState.getIndexedAtomicCounterBuffer(binding);
+
+        if (bufferBinding.get() == nullptr)
+        {
+            continue;
+        }
+
+        VkDescriptorBufferInfo &bufferInfo = descriptorBufferInfo[binding];
+        VkWriteDescriptorSet &writeInfo    = writeDescriptorInfo[binding];
+
+        WriteBufferDescriptorSetBinding(bufferBinding, 0, descriptorSet,
+                                        VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, info.binding, binding,
+                                        requiredOffsetAlignment, &bufferInfo, &writeInfo);
+
+        BufferVk *bufferVk             = vk::GetImpl(bufferBinding.get());
+        vk::BufferHelper &bufferHelper = bufferVk->getBuffer();
+
+        // We set SHADER_READ_BIT to be conservative.
+        commandBufferHelper->bufferWrite(
+            resourceUseList, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, &bufferHelper);
+
+        writtenBindings.set(binding);
+    }
+
+    // Bind the empty buffer to every array slot that's unused.
+    mEmptyBuffer.retain(&contextVk->getResourceUseList());
+    for (size_t binding : ~writtenBindings)
+    {
+        VkDescriptorBufferInfo &bufferInfo = descriptorBufferInfo[binding];
+        VkWriteDescriptorSet &writeInfo    = writeDescriptorInfo[binding];
+
+        bufferInfo.buffer = mEmptyBuffer.getBuffer().getHandle();
+        bufferInfo.offset = 0;
+        bufferInfo.range  = VK_WHOLE_SIZE;
+
+        writeInfo.sType            = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+        writeInfo.pNext            = nullptr;
+        writeInfo.dstSet           = descriptorSet;
+        writeInfo.dstBinding       = info.binding;
+        writeInfo.dstArrayElement  = static_cast<uint32_t>(binding);
+        writeInfo.descriptorCount  = 1;
+        writeInfo.descriptorType   = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+        writeInfo.pImageInfo       = nullptr;
+        writeInfo.pBufferInfo      = &bufferInfo;
+        writeInfo.pTexelBufferView = nullptr;
+    }
+
+    VkDevice device = contextVk->getDevice();
+
+    vkUpdateDescriptorSets(device, gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS,
+                           writeDescriptorInfo.data(), 0, nullptr);
+}
+
+angle::Result ProgramExecutableVk::updateImagesDescriptorSet(const gl::ProgramState &programState,
+                                                             const gl::ShaderType shaderType,
+                                                             ContextVk *contextVk)
+{
+    const gl::State &glState                           = contextVk->getState();
+    const std::vector<gl::ImageBinding> &imageBindings = programState.getImageBindings();
+    const std::vector<gl::LinkedUniform> &uniforms     = programState.getUniforms();
+
+    if (imageBindings.empty())
+    {
+        return angle::Result::Continue;
+    }
+
+    VkDescriptorSet descriptorSet = mDescriptorSets[kShaderResourceDescriptorSetIndex];
+
+    const gl::ActiveTextureArray<TextureVk *> &activeImages = contextVk->getActiveImages();
+
+    gl::ImagesArray<VkDescriptorImageInfo> descriptorImageInfo;
+    gl::ImagesArray<VkWriteDescriptorSet> writeDescriptorInfo;
+    uint32_t writeCount = 0;
+
+    // Write images.
+    for (uint32_t imageIndex = 0; imageIndex < imageBindings.size(); ++imageIndex)
+    {
+        const gl::ImageBinding &imageBinding = imageBindings[imageIndex];
+        uint32_t uniformIndex = programState.getUniformIndexFromImageIndex(imageIndex);
+        const gl::LinkedUniform &imageUniform = uniforms[uniformIndex];
+
+        if (!imageUniform.isActive(shaderType))
+        {
+            continue;
+        }
+
+        std::string name = imageUniform.mappedName;
+        GetImageNameWithoutIndices(&name);
+        ShaderInterfaceVariableInfo &info = mVariableInfoMap[shaderType][name];
+
+        ASSERT(!imageBinding.unreferenced);
+
+        for (uint32_t arrayElement = 0; arrayElement < imageBinding.boundImageUnits.size();
+             ++arrayElement)
+        {
+            GLuint imageUnit             = imageBinding.boundImageUnits[arrayElement];
+            const gl::ImageUnit &binding = glState.getImageUnit(imageUnit);
+            TextureVk *textureVk         = activeImages[imageUnit];
+
+            vk::ImageHelper *image         = &textureVk->getImage();
+            const vk::ImageView *imageView = nullptr;
+
+            ANGLE_TRY(textureVk->getStorageImageView(contextVk, (binding.layered == GL_TRUE),
+                                                     binding.level, binding.layer, &imageView));
+
+            // Note: binding.access is unused because it is implied by the shader.
+
+            // TODO(syoussefi): Support image data reinterpretation by using binding.format.
+            // http://anglebug.com/3563
+
+            VkDescriptorImageInfo &imageInfo = descriptorImageInfo[writeCount];
+            VkWriteDescriptorSet &writeInfo  = writeDescriptorInfo[writeCount];
+
+            imageInfo.sampler     = VK_NULL_HANDLE;
+            imageInfo.imageView   = imageView->getHandle();
+            imageInfo.imageLayout = image->getCurrentLayout();
+
+            writeInfo.sType            = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+            writeInfo.pNext            = nullptr;
+            writeInfo.dstSet           = descriptorSet;
+            writeInfo.dstBinding       = info.binding;
+            writeInfo.dstArrayElement  = arrayElement;
+            writeInfo.descriptorCount  = 1;
+            writeInfo.descriptorType   = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
+            writeInfo.pImageInfo       = &imageInfo;
+            writeInfo.pBufferInfo      = nullptr;
+            writeInfo.pTexelBufferView = nullptr;
+
+            ++writeCount;
+        }
+    }
+
+    VkDevice device = contextVk->getDevice();
+
+    vkUpdateDescriptorSets(device, writeCount, writeDescriptorInfo.data(), 0, nullptr);
+
+    return angle::Result::Continue;
+}
+
+angle::Result ProgramExecutableVk::updateShaderResourcesDescriptorSet(
+    ContextVk *contextVk,
+    vk::ResourceUseList *resourceUseList,
+    CommandBufferHelper *commandBufferHelper)
+{
+    const gl::ProgramExecutable *executable = contextVk->getState().getProgramExecutable();
+    ASSERT(executable);
+    gl::ShaderMap<const gl::ProgramState *> programStates;
+    fillProgramStateMap(contextVk, &programStates);
+
+    ANGLE_TRY(allocateDescriptorSet(contextVk, kShaderResourceDescriptorSetIndex));
+
+    for (const gl::ShaderType shaderType : executable->getLinkedShaderStages())
+    {
+        const gl::ProgramState *programState = programStates[shaderType];
+        ASSERT(programState);
+
+        updateBuffersDescriptorSet(contextVk, shaderType, resourceUseList, commandBufferHelper,
+                                   programState->getUniformBlocks(),
+                                   VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
+        updateBuffersDescriptorSet(contextVk, shaderType, resourceUseList, commandBufferHelper,
+                                   programState->getShaderStorageBlocks(),
+                                   VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
+        updateAtomicCounterBuffersDescriptorSet(*programState, shaderType, contextVk,
+                                                resourceUseList, commandBufferHelper);
+        angle::Result status = updateImagesDescriptorSet(*programState, shaderType, contextVk);
+        if (status != angle::Result::Continue)
+        {
+            return status;
+        }
+    }
+
+    return angle::Result::Continue;
+}
+
+angle::Result ProgramExecutableVk::updateTransformFeedbackDescriptorSet(
+    const gl::ProgramState &programState,
+    gl::ShaderMap<DefaultUniformBlock> &defaultUniformBlocks,
+    ContextVk *contextVk)
+{
+    const gl::ProgramExecutable &executable = programState.getProgramExecutable();
+    ASSERT(executable.hasTransformFeedbackOutput());
+
+    ANGLE_TRY(allocateDescriptorSet(contextVk, kUniformsAndXfbDescriptorSetIndex));
+
+    mDescriptorBuffersCache.clear();
+    for (const gl::ShaderType shaderType : executable.getLinkedShaderStages())
+    {
+        updateDefaultUniformsDescriptorSet(shaderType, defaultUniformBlocks, contextVk);
+    }
+
+    updateTransformFeedbackDescriptorSetImpl(programState, contextVk);
+
+    return angle::Result::Continue;
+}
+
+void ProgramExecutableVk::updateTransformFeedbackDescriptorSetImpl(
+    const gl::ProgramState &programState,
+    ContextVk *contextVk)
+{
+    const gl::State &glState                 = contextVk->getState();
+    gl::TransformFeedback *transformFeedback = glState.getCurrentTransformFeedback();
+    const gl::ProgramExecutable &executable  = programState.getProgramExecutable();
+
+    if (!executable.hasTransformFeedbackOutput())
+    {
+        // If xfb has no output there is no need to update descriptor set.
+        return;
+    }
+    if (!glState.isTransformFeedbackActive())
+    {
+        // We set empty Buffer to xfb descriptor set because xfb descriptor set
+        // requires valid buffer bindings, even if they are empty buffer,
+        // otherwise Vulkan validation layer generates errors.
+        if (transformFeedback)
+        {
+            TransformFeedbackVk *transformFeedbackVk = vk::GetImpl(transformFeedback);
+            transformFeedbackVk->initDescriptorSet(
+                contextVk, programState.getTransformFeedbackBufferCount(), &mEmptyBuffer,
+                mDescriptorSets[kUniformsAndXfbDescriptorSetIndex]);
+        }
+        return;
+    }
+
+    TransformFeedbackVk *transformFeedbackVk = vk::GetImpl(glState.getCurrentTransformFeedback());
+    transformFeedbackVk->updateDescriptorSet(contextVk, programState,
+                                             mDescriptorSets[kUniformsAndXfbDescriptorSetIndex]);
+}
+
+angle::Result ProgramExecutableVk::updateTexturesDescriptorSet(ContextVk *contextVk)
+{
+    const gl::ProgramExecutable *executable = contextVk->getState().getProgramExecutable();
+    ASSERT(executable);
+
+    if (!executable->hasTextures())
+    {
+        return angle::Result::Continue;
+    }
+
+    const vk::TextureDescriptorDesc &texturesDesc = contextVk->getActiveTexturesDesc();
+
+    auto iter = mTextureDescriptorsCache.find(texturesDesc);
+    if (iter != mTextureDescriptorsCache.end())
+    {
+        mDescriptorSets[kTextureDescriptorSetIndex] = iter->second;
+        return angle::Result::Continue;
+    }
+
+    bool newPoolAllocated;
+    ANGLE_TRY(
+        allocateDescriptorSetAndGetInfo(contextVk, kTextureDescriptorSetIndex, &newPoolAllocated));
+
+    // Clear descriptor set cache. It may no longer be valid.
+    if (newPoolAllocated)
+    {
+        mTextureDescriptorsCache.clear();
+    }
+
+    VkDescriptorSet descriptorSet = mDescriptorSets[kTextureDescriptorSetIndex];
+
+    gl::ActiveTextureArray<VkDescriptorImageInfo> descriptorImageInfo;
+    gl::ActiveTextureArray<VkWriteDescriptorSet> writeDescriptorInfo;
+    uint32_t writeCount = 0;
+
+    const gl::ActiveTextureArray<vk::TextureUnit> &activeTextures = contextVk->getActiveTextures();
+
+    bool emulateSeamfulCubeMapSampling = contextVk->emulateSeamfulCubeMapSampling();
+    bool useOldRewriteStructSamplers   = contextVk->useOldRewriteStructSamplers();
+
+    gl::ShaderMap<const gl::ProgramState *> programStates;
+    fillProgramStateMap(contextVk, &programStates);
+
+    for (const gl::ShaderType shaderType : executable->getLinkedShaderStages())
+    {
+        std::unordered_map<std::string, uint32_t> mappedSamplerNameToArrayOffset;
+        const gl::ProgramState *programState = programStates[shaderType];
+        ASSERT(programState);
+        for (uint32_t textureIndex = 0; textureIndex < programState->getSamplerBindings().size();
+             ++textureIndex)
+        {
+            const gl::SamplerBinding &samplerBinding =
+                programState->getSamplerBindings()[textureIndex];
+
+            ASSERT(!samplerBinding.unreferenced);
+
+            uint32_t uniformIndex = programState->getUniformIndexFromSamplerIndex(textureIndex);
+            const gl::LinkedUniform &samplerUniform = programState->getUniforms()[uniformIndex];
+            std::string mappedSamplerName = GlslangGetMappedSamplerName(samplerUniform.name);
+
+            if (!samplerUniform.isActive(shaderType))
+            {
+                continue;
+            }
+
+            uint32_t arrayOffset = 0;
+            uint32_t arraySize   = static_cast<uint32_t>(samplerBinding.boundTextureUnits.size());
+
+            if (!useOldRewriteStructSamplers)
+            {
+                arrayOffset = mappedSamplerNameToArrayOffset[mappedSamplerName];
+                // Front-end generates array elements in order, so we can just increment
+                // the offset each time we process a nested array.
+                mappedSamplerNameToArrayOffset[mappedSamplerName] += arraySize;
+            }
+
+            for (uint32_t arrayElement = 0; arrayElement < arraySize; ++arrayElement)
+            {
+                GLuint textureUnit   = samplerBinding.boundTextureUnits[arrayElement];
+                TextureVk *textureVk = activeTextures[textureUnit].texture;
+                SamplerVk *samplerVk = activeTextures[textureUnit].sampler;
+
+                vk::ImageHelper &image = textureVk->getImage();
+
+                VkDescriptorImageInfo &imageInfo = descriptorImageInfo[writeCount];
+
+                // Use bound sampler object if one present, otherwise use texture's sampler
+                const vk::Sampler &sampler =
+                    (samplerVk != nullptr) ? samplerVk->getSampler() : textureVk->getSampler();
+
+                imageInfo.sampler     = sampler.getHandle();
+                imageInfo.imageLayout = image.getCurrentLayout();
+
+                if (emulateSeamfulCubeMapSampling)
+                {
+                    // If emulating seamful cubemapping, use the fetch image view.  This is
+                    // basically the same image view as read, except it's a 2DArray view for
+                    // cube maps.
+                    imageInfo.imageView =
+                        textureVk->getFetchImageViewAndRecordUse(contextVk).getHandle();
+                }
+                else
+                {
+                    imageInfo.imageView =
+                        textureVk->getReadImageViewAndRecordUse(contextVk).getHandle();
+                }
+
+                ShaderInterfaceVariableInfoMap &variableInfoMap = mVariableInfoMap[shaderType];
+                const std::string samplerName =
+                    contextVk->getRenderer()->getFeatures().forceOldRewriteStructSamplers.enabled
+                        ? GetMappedSamplerNameOld(samplerUniform.name)
+                        : GlslangGetMappedSamplerName(samplerUniform.name);
+                ShaderInterfaceVariableInfo &info = variableInfoMap[samplerName];
+
+                VkWriteDescriptorSet &writeInfo = writeDescriptorInfo[writeCount];
+
+                writeInfo.sType            = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+                writeInfo.pNext            = nullptr;
+                writeInfo.dstSet           = descriptorSet;
+                writeInfo.dstBinding       = info.binding;
+                writeInfo.dstArrayElement  = arrayOffset + arrayElement;
+                writeInfo.descriptorCount  = 1;
+                writeInfo.descriptorType   = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+                writeInfo.pImageInfo       = &imageInfo;
+                writeInfo.pBufferInfo      = nullptr;
+                writeInfo.pTexelBufferView = nullptr;
+
+                ++writeCount;
+            }
+        }
+    }
+
+    VkDevice device = contextVk->getDevice();
+
+    ASSERT(writeCount > 0);
+
+    vkUpdateDescriptorSets(device, writeCount, writeDescriptorInfo.data(), 0, nullptr);
+
+    mTextureDescriptorsCache.emplace(texturesDesc, descriptorSet);
+
+    return angle::Result::Continue;
+}
+
+angle::Result ProgramExecutableVk::updateDescriptorSets(ContextVk *contextVk,
+                                                        vk::CommandBuffer *commandBuffer)
+{
+    // Can probably use better dirty bits here.
+
+    if (mDescriptorSets.empty())
+        return angle::Result::Continue;
+
+    // Find the maximum non-null descriptor set.  This is used in conjunction with a driver
+    // workaround to bind empty descriptor sets only for gaps in between 0 and max and avoid
+    // binding unnecessary empty descriptor sets for the sets beyond max.
+    const size_t descriptorSetStart = kUniformsAndXfbDescriptorSetIndex;
+    size_t descriptorSetRange       = 0;
+    for (size_t descriptorSetIndex = descriptorSetStart;
+         descriptorSetIndex < mDescriptorSets.size(); ++descriptorSetIndex)
+    {
+        if (mDescriptorSets[descriptorSetIndex] != VK_NULL_HANDLE)
+        {
+            descriptorSetRange = descriptorSetIndex + 1;
+        }
+    }
+
+    const gl::State &glState                    = contextVk->getState();
+    const VkPipelineBindPoint pipelineBindPoint = glState.getProgramExecutable()->isCompute()
+                                                      ? VK_PIPELINE_BIND_POINT_COMPUTE
+                                                      : VK_PIPELINE_BIND_POINT_GRAPHICS;
+
+    for (uint32_t descriptorSetIndex = descriptorSetStart; descriptorSetIndex < descriptorSetRange;
+         ++descriptorSetIndex)
+    {
+        VkDescriptorSet descSet = mDescriptorSets[descriptorSetIndex];
+        if (descSet == VK_NULL_HANDLE)
+        {
+            if (!contextVk->getRenderer()->getFeatures().bindEmptyForUnusedDescriptorSets.enabled)
+            {
+                continue;
+            }
+
+            // Workaround a driver bug where missing (though unused) descriptor sets indices cause
+            // later sets to misbehave.
+            if (mEmptyDescriptorSets[descriptorSetIndex] == VK_NULL_HANDLE)
+            {
+                const vk::DescriptorSetLayout &descriptorSetLayout =
+                    mDescriptorSetLayouts[descriptorSetIndex].get();
+
+                ANGLE_TRY(mDynamicDescriptorPools[descriptorSetIndex].allocateSets(
+                    contextVk, descriptorSetLayout.ptr(), 1,
+                    &mDescriptorPoolBindings[descriptorSetIndex],
+                    &mEmptyDescriptorSets[descriptorSetIndex]));
+            }
+            descSet = mEmptyDescriptorSets[descriptorSetIndex];
+        }
+
+        // Default uniforms are encompassed in a block per shader stage, and they are assigned
+        // through dynamic uniform buffers (requiring dynamic offsets).  No other descriptor
+        // requires a dynamic offset.
+        const uint32_t uniformBlockOffsetCount =
+            descriptorSetIndex == kUniformsAndXfbDescriptorSetIndex
+                ? static_cast<uint32_t>(mNumDefaultUniformDescriptors)
+                : 0;
+
+        commandBuffer->bindDescriptorSets(getPipelineLayout(), pipelineBindPoint,
+                                          descriptorSetIndex, 1, &descSet, uniformBlockOffsetCount,
+                                          mDynamicBufferOffsets.data());
+    }
+
+    for (vk::BufferHelper *buffer : mDescriptorBuffersCache)
+    {
+        buffer->retain(&contextVk->getResourceUseList());
+    }
+
+    return angle::Result::Continue;
+}
+
+}  // namespace rx
diff --git a/src/libANGLE/renderer/vulkan/ProgramExecutableVk.h b/src/libANGLE/renderer/vulkan/ProgramExecutableVk.h
new file mode 100644
index 0000000..546c889
--- /dev/null
+++ b/src/libANGLE/renderer/vulkan/ProgramExecutableVk.h
@@ -0,0 +1,253 @@
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ProgramExecutableVk.h: Collects the information and interfaces common to both ProgramVks and
+// ProgramPipelineVks in order to execute/draw with either.
+
+#ifndef LIBANGLE_RENDERER_VULKAN_PROGRAMEXECUTABLEVK_H_
+#define LIBANGLE_RENDERER_VULKAN_PROGRAMEXECUTABLEVK_H_
+
+#include "common/bitset_utils.h"
+#include "common/utilities.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/InfoLog.h"
+#include "libANGLE/renderer/glslang_wrapper_utils.h"
+#include "libANGLE/renderer/vulkan/ContextVk.h"
+#include "libANGLE/renderer/vulkan/vk_helpers.h"
+
+namespace rx
+{
+
+class ShaderInfo final : angle::NonCopyable
+{
+  public:
+    ShaderInfo();
+    ~ShaderInfo();
+
+    angle::Result initShaders(ContextVk *contextVk,
+                              const gl::ShaderMap<std::string> &shaderSources,
+                              const ShaderMapInterfaceVariableInfoMap &variableInfoMap);
+    void release(ContextVk *contextVk);
+
+    ANGLE_INLINE bool valid() const { return mIsInitialized; }
+
+    const gl::ShaderMap<SpirvBlob> &getSpirvBlobs() const { return mSpirvBlobs; }
+    gl::ShaderMap<SpirvBlob> &getSpirvBlobs() { return mSpirvBlobs; }
+
+    // Save and load implementation for GLES Program Binary support.
+    void load(gl::BinaryInputStream *stream);
+    void save(gl::BinaryOutputStream *stream);
+
+  private:
+    gl::ShaderMap<SpirvBlob> mSpirvBlobs;
+    bool mIsInitialized = false;
+};
+
+enum class ProgramTransformOption : uint8_t
+{
+    EnableLineRasterEmulation            = 0,
+    RemoveEarlyFragmentTestsOptimization = 1,
+    EnumCount                            = 2,
+    PermutationCount                     = 4,
+};
+using ProgramTransformOptionBits = angle::PackedEnumBitSet<ProgramTransformOption, uint8_t>;
+
+class ProgramInfo final : angle::NonCopyable
+{
+  public:
+    ProgramInfo();
+    ~ProgramInfo();
+
+    angle::Result initProgram(ContextVk *contextVk,
+                              const gl::ShaderType shaderType,
+                              const ShaderInfo &shaderInfo,
+                              const ShaderMapInterfaceVariableInfoMap &variableInfoMap,
+                              ProgramTransformOptionBits optionBits);
+    void release(ContextVk *contextVk);
+
+    ANGLE_INLINE bool valid(const gl::ShaderType shaderType) const
+    {
+        return mProgramHelper.valid(shaderType);
+    }
+
+    vk::ShaderProgramHelper *getShaderProgram() { return &mProgramHelper; }
+
+  private:
+    vk::ShaderProgramHelper mProgramHelper;
+    gl::ShaderMap<vk::RefCounted<vk::ShaderAndSerial>> mShaders;
+};
+
+// State for the default uniform blocks.
+struct DefaultUniformBlock final : private angle::NonCopyable
+{
+    DefaultUniformBlock();
+    ~DefaultUniformBlock();
+
+    vk::DynamicBuffer storage;
+
+    // Shadow copies of the shader uniform data.
+    angle::MemoryBuffer uniformData;
+
+    // Since the default blocks are laid out in std140, this tells us where to write on a call
+    // to a setUniform method. They are arranged in uniform location order.
+    std::vector<sh::BlockMemberInfo> uniformLayout;
+};
+
+class ProgramExecutableVk
+{
+  public:
+    ProgramExecutableVk();
+    virtual ~ProgramExecutableVk();
+
+    void reset(ContextVk *contextVk);
+
+    void save(gl::BinaryOutputStream *stream);
+    std::unique_ptr<rx::LinkEvent> load(gl::BinaryInputStream *stream);
+
+    void clearVariableInfoMap();
+    ShaderMapInterfaceVariableInfoMap &getShaderInterfaceVariableInfoMap()
+    {
+        return mVariableInfoMap;
+    }
+
+    ProgramVk *getShaderProgram(const gl::State &glState, gl::ShaderType shaderType) const;
+
+    void fillProgramStateMap(const ContextVk *contextVk,
+                             gl::ShaderMap<const gl::ProgramState *> *programStatesOut);
+    const gl::ProgramExecutable &getGlExecutable();
+
+    ProgramInfo &getDefaultProgramInfo() { return mProgramInfos[0]; }
+    ProgramInfo &getProgramInfo(ProgramTransformOptionBits optionBits)
+    {
+        return mProgramInfos[optionBits.to_ulong()];
+    }
+
+    angle::Result getGraphicsPipeline(ContextVk *contextVk,
+                                      gl::PrimitiveMode mode,
+                                      const vk::GraphicsPipelineDesc &desc,
+                                      const gl::AttributesMask &activeAttribLocations,
+                                      const vk::GraphicsPipelineDesc **descPtrOut,
+                                      vk::PipelineHelper **pipelineOut);
+
+    angle::Result getComputePipeline(ContextVk *contextVk, vk::PipelineAndSerial **pipelineOut);
+
+    const vk::PipelineLayout &getPipelineLayout() const { return mPipelineLayout.get(); }
+    angle::Result createPipelineLayout(const gl::Context *glContext);
+
+    angle::Result updateTexturesDescriptorSet(ContextVk *contextVk);
+    angle::Result updateShaderResourcesDescriptorSet(ContextVk *contextVk,
+                                                     vk::ResourceUseList *resourceUseList,
+                                                     CommandBufferHelper *commandBufferHelper);
+    angle::Result updateTransformFeedbackDescriptorSet(
+        const gl::ProgramState &programState,
+        gl::ShaderMap<DefaultUniformBlock> &defaultUniformBlocks,
+        ContextVk *contextVk);
+
+    angle::Result updateDescriptorSets(ContextVk *contextVk, vk::CommandBuffer *commandBuffer);
+
+    void updateEarlyFragmentTestsOptimization(ContextVk *contextVk);
+
+    void setProgram(ProgramVk *program)
+    {
+        ASSERT(!mProgram && !mProgramPipeline);
+        mProgram = program;
+    }
+    void setProgramPipeline(ProgramPipelineVk *pipeline)
+    {
+        ASSERT(!mProgram && !mProgramPipeline);
+        mProgramPipeline = pipeline;
+    }
+
+  private:
+    friend class ProgramVk;
+    friend class ProgramPipelineVk;
+
+    angle::Result allocateDescriptorSet(ContextVk *contextVk, uint32_t descriptorSetIndex);
+    angle::Result allocateDescriptorSetAndGetInfo(ContextVk *contextVk,
+                                                  uint32_t descriptorSetIndex,
+                                                  bool *newPoolAllocatedOut);
+    void addInterfaceBlockDescriptorSetDesc(const std::vector<gl::InterfaceBlock> &blocks,
+                                            const gl::ShaderType shaderType,
+                                            VkDescriptorType descType,
+                                            vk::DescriptorSetLayoutDesc *descOut);
+    void addAtomicCounterBufferDescriptorSetDesc(
+        const std::vector<gl::AtomicCounterBuffer> &atomicCounterBuffers,
+        const gl::ShaderType shaderType,
+        vk::DescriptorSetLayoutDesc *descOut);
+    void addImageDescriptorSetDesc(const gl::ProgramState &programState,
+                                   vk::DescriptorSetLayoutDesc *descOut);
+    void addTextureDescriptorSetDesc(const gl::ProgramState &programState,
+                                     bool useOldRewriteStructSamplers,
+                                     vk::DescriptorSetLayoutDesc *descOut);
+
+    void updateDefaultUniformsDescriptorSet(
+        const gl::ShaderType shaderType,
+        gl::ShaderMap<DefaultUniformBlock> &defaultUniformBlocks,
+        ContextVk *contextVk);
+    void updateTransformFeedbackDescriptorSetImpl(const gl::ProgramState &programState,
+                                                  ContextVk *contextVk);
+    void updateBuffersDescriptorSet(ContextVk *contextVk,
+                                    const gl::ShaderType shaderType,
+                                    vk::ResourceUseList *resourceUseList,
+                                    CommandBufferHelper *commandBufferHelper,
+                                    const std::vector<gl::InterfaceBlock> &blocks,
+                                    VkDescriptorType descriptorType);
+    void updateAtomicCounterBuffersDescriptorSet(const gl::ProgramState &programState,
+                                                 const gl::ShaderType shaderType,
+                                                 ContextVk *contextVk,
+                                                 vk::ResourceUseList *resourceUseList,
+                                                 CommandBufferHelper *commandBufferHelper);
+    angle::Result updateImagesDescriptorSet(const gl::ProgramState &programState,
+                                            const gl::ShaderType shaderType,
+                                            ContextVk *contextVk);
+
+    // This is a special "empty" placeholder buffer for when a shader has no uniforms or doesn't
+    // use all slots in the atomic counter buffer array.
+    //
+    // It is necessary because we want to keep a compatible pipeline layout in all cases,
+    // and Vulkan does not tolerate having null handles in a descriptor set.
+    vk::BufferHelper mEmptyBuffer;
+
+    // Descriptor sets for uniform blocks and textures for this program.
+    std::vector<VkDescriptorSet> mDescriptorSets;
+    vk::DescriptorSetLayoutArray<VkDescriptorSet> mEmptyDescriptorSets;
+    std::vector<vk::BufferHelper *> mDescriptorBuffersCache;
+    size_t mNumDefaultUniformDescriptors;
+
+    std::unordered_map<vk::TextureDescriptorDesc, VkDescriptorSet> mTextureDescriptorsCache;
+
+    // We keep a reference to the pipeline and descriptor set layouts. This ensures they don't get
+    // deleted while this program is in use.
+    vk::BindingPointer<vk::PipelineLayout> mPipelineLayout;
+    vk::DescriptorSetLayoutPointerArray mDescriptorSetLayouts;
+    bool mPipelineLayoutCreated;
+
+    // Keep bindings to the descriptor pools. This ensures the pools stay valid while the Program
+    // is in use.
+    vk::DescriptorSetLayoutArray<vk::RefCountedDescriptorPoolBinding> mDescriptorPoolBindings;
+
+    // Store descriptor pools here. We store the descriptors in the Program to facilitate descriptor
+    // cache management. It can also allow fewer descriptors for shaders which use fewer
+    // textures/buffers.
+    vk::DescriptorSetLayoutArray<vk::DynamicDescriptorPool> mDynamicDescriptorPools;
+
+    gl::ShaderVector<uint32_t> mDynamicBufferOffsets;
+
+    // TODO: http://anglebug.com/4524: Need a different hash key than a string,
+    // since that's slow to calculate.
+    ShaderMapInterfaceVariableInfoMap mVariableInfoMap;
+
+    ProgramInfo mProgramInfos[static_cast<int>(ProgramTransformOption::PermutationCount)];
+
+    ProgramTransformOptionBits mTransformOptionBits;
+
+    ProgramVk *mProgram;
+    ProgramPipelineVk *mProgramPipeline;
+};
+
+}  // namespace rx
+
+#endif  // LIBANGLE_RENDERER_VULKAN_PROGRAMEXECUTABLEVK_H_
diff --git a/src/libANGLE/renderer/vulkan/ProgramPipelineVk.cpp b/src/libANGLE/renderer/vulkan/ProgramPipelineVk.cpp
index df63878..5982570 100644
--- a/src/libANGLE/renderer/vulkan/ProgramPipelineVk.cpp
+++ b/src/libANGLE/renderer/vulkan/ProgramPipelineVk.cpp
@@ -9,13 +9,172 @@
 
 #include "libANGLE/renderer/vulkan/ProgramPipelineVk.h"
 
+#include "libANGLE/renderer/glslang_wrapper_utils.h"
+#include "libANGLE/renderer/vulkan/GlslangWrapperVk.h"
+
 namespace rx
 {
 
 ProgramPipelineVk::ProgramPipelineVk(const gl::ProgramPipelineState &state)
     : ProgramPipelineImpl(state)
-{}
+{
+    mExecutable.setProgramPipeline(this);
+}
 
 ProgramPipelineVk::~ProgramPipelineVk() {}
 
+void ProgramPipelineVk::destroy(const gl::Context *context)
+{
+    ContextVk *contextVk = vk::GetImpl(context);
+    reset(contextVk);
+}
+
+void ProgramPipelineVk::reset(ContextVk *contextVk)
+{
+    mExecutable.reset(contextVk);
+}
+
+// TODO: http://anglebug.com/3570: Move/Copy all of the necessary information into
+// the ProgramExecutable, so this function can be removed.
+void ProgramPipelineVk::fillProgramStateMap(
+    const ContextVk *contextVk,
+    gl::ShaderMap<const gl::ProgramState *> *programStatesOut)
+{
+    for (gl::ShaderType shaderType : gl::AllShaderTypes())
+    {
+        (*programStatesOut)[shaderType] = nullptr;
+
+        ProgramVk *programVk = getShaderProgram(contextVk->getState(), shaderType);
+        if (programVk)
+        {
+            (*programStatesOut)[shaderType] = &programVk->getState();
+        }
+    }
+}
+
+angle::Result ProgramPipelineVk::link(const gl::Context *glContext)
+{
+    ContextVk *contextVk                  = vk::GetImpl(glContext);
+    const gl::State &glState              = glContext->getState();
+    const gl::ProgramPipeline *glPipeline = glState.getProgramPipeline();
+    GlslangSourceOptions options =
+        GlslangWrapperVk::CreateSourceOptions(contextVk->getRenderer()->getFeatures());
+    GlslangProgramInterfaceInfo glslangProgramInterfaceInfo;
+    GlslangWrapperVk::ResetGlslangProgramInterfaceInfo(&glslangProgramInterfaceInfo);
+
+    mExecutable.clearVariableInfoMap();
+
+    // Now that the program pipeline has all of the programs attached, the various descriptor
+    // set/binding locations need to be re-assigned to their correct values.
+    for (const gl::ShaderType shaderType : glPipeline->getExecutable().getLinkedShaderStages())
+    {
+        gl::Program *glProgram =
+            const_cast<gl::Program *>(glPipeline->getShaderProgram(shaderType));
+        if (glProgram)
+        {
+            // The program interface info must survive across shaders, except
+            // for some program-specific values.
+            ProgramVk *programVk = vk::GetImpl(glProgram);
+            GlslangProgramInterfaceInfo &programProgramInterfaceInfo =
+                programVk->getGlslangProgramInterfaceInfo();
+            glslangProgramInterfaceInfo.locationsUsedForXfbExtension =
+                programProgramInterfaceInfo.locationsUsedForXfbExtension;
+
+            GlslangAssignLocations(options, glProgram->getState(), glProgram->getResources(),
+                                   shaderType, &glslangProgramInterfaceInfo,
+                                   &mExecutable.getShaderInterfaceVariableInfoMap());
+        }
+    }
+
+    ANGLE_TRY(transformShaderSpirV(glContext));
+
+    return mExecutable.createPipelineLayout(glContext);
+}
+
+angle::Result ProgramPipelineVk::transformShaderSpirV(const gl::Context *glContext)
+{
+    ContextVk *contextVk                    = vk::GetImpl(glContext);
+    const gl::ProgramExecutable *executable = contextVk->getState().getProgramExecutable();
+    ASSERT(executable);
+
+    for (const gl::ShaderType shaderType : executable->getLinkedShaderStages())
+    {
+        ProgramVk *programVk = getShaderProgram(contextVk->getState(), shaderType);
+        if (programVk)
+        {
+            ShaderInterfaceVariableInfoMap &variableInfoMap =
+                mExecutable.mVariableInfoMap[shaderType];
+            std::vector<uint32_t> transformedSpirvBlob;
+
+            // We skip early fragment tests optimization modification here since we need to keep
+            // original spriv blob here.
+            ANGLE_TRY(GlslangWrapperVk::TransformSpirV(
+                contextVk, shaderType, false, variableInfoMap,
+                programVk->getShaderInfo().getSpirvBlobs()[shaderType], &transformedSpirvBlob));
+
+            // Save the newly transformed SPIR-V
+            // TODO: http://anglebug.com/4513: Keep the original SPIR-V and
+            // translated SPIR-V in separate buffers in ShaderInfo to avoid the
+            // extra copy here.
+            programVk->getShaderInfo().getSpirvBlobs()[shaderType] = transformedSpirvBlob;
+        }
+    }
+    return angle::Result::Continue;
+}
+
+angle::Result ProgramPipelineVk::updateUniforms(ContextVk *contextVk)
+{
+    uint32_t offsetIndex                      = 0;
+    bool anyNewBufferAllocated                = false;
+    const gl::ProgramExecutable *glExecutable = contextVk->getState().getProgramExecutable();
+
+    for (const gl::ShaderType shaderType : glExecutable->getLinkedShaderStages())
+    {
+        ProgramVk *programVk = getShaderProgram(contextVk->getState(), shaderType);
+        if (programVk && programVk->dirtyUniforms())
+        {
+            ANGLE_TRY(programVk->updateShaderUniforms(
+                contextVk, shaderType, &mExecutable.mDynamicBufferOffsets[offsetIndex],
+                &anyNewBufferAllocated));
+        }
+        ++offsetIndex;
+    }
+
+    if (anyNewBufferAllocated)
+    {
+        // We need to reinitialize the descriptor sets if we newly allocated buffers since we can't
+        // modify the descriptor sets once initialized.
+        ANGLE_TRY(mExecutable.allocateDescriptorSet(contextVk, kUniformsAndXfbDescriptorSetIndex));
+
+        mExecutable.mDescriptorBuffersCache.clear();
+        for (const gl::ShaderType shaderType : glExecutable->getLinkedShaderStages())
+        {
+            ProgramVk *programVk = getShaderProgram(contextVk->getState(), shaderType);
+            if (programVk)
+            {
+                mExecutable.updateDefaultUniformsDescriptorSet(
+                    shaderType, programVk->getDefaultUniformBlocks(), contextVk);
+                mExecutable.updateTransformFeedbackDescriptorSetImpl(programVk->getState(),
+                                                                     contextVk);
+            }
+        }
+    }
+
+    return angle::Result::Continue;
+}
+
+bool ProgramPipelineVk::dirtyUniforms(const gl::State &glState)
+{
+    for (const gl::ShaderType shaderType : gl::AllShaderTypes())
+    {
+        const ProgramVk *program = getShaderProgram(glState, shaderType);
+        if (program && program->dirtyUniforms())
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
 }  // namespace rx
diff --git a/src/libANGLE/renderer/vulkan/ProgramPipelineVk.h b/src/libANGLE/renderer/vulkan/ProgramPipelineVk.h
index d98810f..6947d97 100644
--- a/src/libANGLE/renderer/vulkan/ProgramPipelineVk.h
+++ b/src/libANGLE/renderer/vulkan/ProgramPipelineVk.h
@@ -12,6 +12,10 @@
 
 #include "libANGLE/renderer/ProgramPipelineImpl.h"
 
+#include "libANGLE/renderer/vulkan/ContextVk.h"
+#include "libANGLE/renderer/vulkan/ProgramExecutableVk.h"
+#include "libANGLE/renderer/vulkan/ProgramVk.h"
+
 namespace rx
 {
 
@@ -20,6 +24,37 @@
   public:
     ProgramPipelineVk(const gl::ProgramPipelineState &state);
     ~ProgramPipelineVk() override;
+
+    void destroy(const gl::Context *context) override;
+    void reset(ContextVk *contextVk);
+
+    const ProgramExecutableVk &getExecutable() const { return mExecutable; }
+    ProgramExecutableVk &getExecutable() { return mExecutable; }
+
+    ProgramVk *getShaderProgram(const gl::State &glState, gl::ShaderType shaderType) const
+    {
+        gl::ProgramPipeline *pipeline = glState.getProgramPipeline();
+        const gl::Program *program    = pipeline->getShaderProgram(shaderType);
+        if (program)
+        {
+            return vk::GetImpl(program);
+        }
+        return nullptr;
+    }
+
+    void fillProgramStateMap(const ContextVk *contextVk,
+                             gl::ShaderMap<const gl::ProgramState *> *programStatesOut);
+
+    angle::Result link(const gl::Context *context) override;
+
+    angle::Result transformShaderSpirV(const gl::Context *glContext);
+
+    angle::Result updateUniforms(ContextVk *contextVk);
+
+    bool dirtyUniforms(const gl::State &glState);
+
+  private:
+    ProgramExecutableVk mExecutable;
 };
 
 }  // namespace rx
diff --git a/src/libANGLE/renderer/vulkan/ProgramVk.cpp b/src/libANGLE/renderer/vulkan/ProgramVk.cpp
index b05b870..e79c8fa 100644
--- a/src/libANGLE/renderer/vulkan/ProgramVk.cpp
+++ b/src/libANGLE/renderer/vulkan/ProgramVk.cpp
@@ -153,205 +153,6 @@
     return angle::Result::Continue;
 }
 
-uint32_t GetInterfaceBlockArraySize(const std::vector<gl::InterfaceBlock> &blocks,
-                                    uint32_t bufferIndex)
-{
-    const gl::InterfaceBlock &block = blocks[bufferIndex];
-
-    if (!block.isArray)
-    {
-        return 1;
-    }
-
-    ASSERT(block.arrayElement == 0);
-
-    // Search consecutively until all array indices of this block are visited.
-    uint32_t arraySize;
-    for (arraySize = 1; bufferIndex + arraySize < blocks.size(); ++arraySize)
-    {
-        const gl::InterfaceBlock &nextBlock = blocks[bufferIndex + arraySize];
-
-        if (nextBlock.arrayElement != arraySize)
-        {
-            break;
-        }
-
-        // It's unexpected for an array to start at a non-zero array size, so we can always rely on
-        // the sequential `arrayElement`s to belong to the same block.
-        ASSERT(nextBlock.name == block.name);
-        ASSERT(nextBlock.isArray);
-    }
-
-    return arraySize;
-}
-
-void AddInterfaceBlockDescriptorSetDesc(const std::vector<gl::InterfaceBlock> &blocks,
-                                        uint32_t bindingStart,
-                                        VkDescriptorType descType,
-                                        vk::DescriptorSetLayoutDesc *descOut)
-{
-    uint32_t bindingIndex = 0;
-    for (uint32_t bufferIndex = 0; bufferIndex < blocks.size();)
-    {
-        const uint32_t arraySize = GetInterfaceBlockArraySize(blocks, bufferIndex);
-        VkShaderStageFlags activeStages =
-            gl_vk::GetShaderStageFlags(blocks[bufferIndex].activeShaders());
-
-        descOut->update(bindingStart + bindingIndex, descType, arraySize, activeStages);
-
-        bufferIndex += arraySize;
-        ++bindingIndex;
-    }
-}
-
-void AddAtomicCounterBufferDescriptorSetDesc(
-    const std::vector<gl::AtomicCounterBuffer> &atomicCounterBuffers,
-    uint32_t bindingStart,
-    vk::DescriptorSetLayoutDesc *descOut)
-{
-    if (atomicCounterBuffers.empty())
-    {
-        return;
-    }
-
-    VkShaderStageFlags activeStages = 0;
-    for (const gl::AtomicCounterBuffer &buffer : atomicCounterBuffers)
-    {
-        activeStages |= gl_vk::GetShaderStageFlags(buffer.activeShaders());
-    }
-
-    // A single storage buffer array is used for all stages for simplicity.
-    descOut->update(bindingStart, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
-                    gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS, activeStages);
-}
-
-void AddImageDescriptorSetDesc(const gl::ProgramState &programState,
-                               uint32_t bindingStart,
-                               vk::DescriptorSetLayoutDesc *descOut)
-{
-    const std::vector<gl::ImageBinding> &imageBindings = programState.getImageBindings();
-    const std::vector<gl::LinkedUniform> &uniforms     = programState.getUniforms();
-
-    for (uint32_t imageIndex = 0; imageIndex < imageBindings.size(); ++imageIndex)
-    {
-        const gl::ImageBinding &imageBinding = imageBindings[imageIndex];
-
-        uint32_t uniformIndex = programState.getUniformIndexFromImageIndex(imageIndex);
-        const gl::LinkedUniform &imageUniform = uniforms[uniformIndex];
-
-        // The front-end always binds array image units sequentially.
-        uint32_t arraySize = static_cast<uint32_t>(imageBinding.boundImageUnits.size());
-        VkShaderStageFlags activeStages = gl_vk::GetShaderStageFlags(imageUniform.activeShaders());
-
-        uint32_t bindingIndex = bindingStart + imageIndex;
-        descOut->update(bindingIndex, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, arraySize, activeStages);
-    }
-}
-
-void AddTextureDescriptorSetDesc(const gl::ProgramState &programState,
-                                 bool useOldRewriteStructSamplers,
-                                 vk::DescriptorSetLayoutDesc *descOut)
-{
-    uint32_t bindingIndex                                  = 0;
-    const std::vector<gl::SamplerBinding> &samplerBindings = programState.getSamplerBindings();
-    const std::vector<gl::LinkedUniform> &uniforms         = programState.getUniforms();
-
-    for (uint32_t textureIndex = 0; textureIndex < samplerBindings.size(); ++textureIndex)
-    {
-        const gl::SamplerBinding &samplerBinding = samplerBindings[textureIndex];
-
-        uint32_t uniformIndex = programState.getUniformIndexFromSamplerIndex(textureIndex);
-        const gl::LinkedUniform &samplerUniform = uniforms[uniformIndex];
-
-        // The front-end always binds array sampler units sequentially.
-        uint32_t arraySize = static_cast<uint32_t>(samplerBinding.boundTextureUnits.size());
-        VkShaderStageFlags activeStages =
-            gl_vk::GetShaderStageFlags(samplerUniform.activeShaders());
-
-        if (!useOldRewriteStructSamplers)
-        {
-            // 2D arrays are split into multiple 1D arrays when generating
-            // LinkedUniforms. Since they are flattened into one array, ignore the
-            // nonzero elements and expand the array to the total array size.
-            if (gl::SamplerNameContainsNonZeroArrayElement(samplerUniform.name))
-            {
-                continue;
-            }
-
-            for (unsigned int outerArraySize : samplerUniform.outerArraySizes)
-            {
-                arraySize *= outerArraySize;
-            }
-        }
-
-        descOut->update(bindingIndex++, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, arraySize,
-                        activeStages);
-    }
-}
-
-void WriteBufferDescriptorSetBinding(const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding,
-                                     VkDeviceSize maxSize,
-                                     VkDescriptorSet descSet,
-                                     VkDescriptorType descType,
-                                     uint32_t bindingIndex,
-                                     uint32_t arrayElement,
-                                     VkDeviceSize requiredOffsetAlignment,
-                                     VkDescriptorBufferInfo *bufferInfoOut,
-                                     VkWriteDescriptorSet *writeInfoOut)
-{
-    gl::Buffer *buffer = bufferBinding.get();
-    ASSERT(buffer != nullptr);
-
-    // Make sure there's no possible under/overflow with binding size.
-    static_assert(sizeof(VkDeviceSize) >= sizeof(bufferBinding.getSize()),
-                  "VkDeviceSize too small");
-    ASSERT(bufferBinding.getSize() >= 0);
-
-    BufferVk *bufferVk             = vk::GetImpl(buffer);
-    VkDeviceSize offset            = bufferBinding.getOffset();
-    VkDeviceSize size              = bufferBinding.getSize();
-    vk::BufferHelper &bufferHelper = bufferVk->getBuffer();
-
-    // If size is 0, we can't always use VK_WHOLE_SIZE (or bufferHelper.getSize()), as the
-    // backing buffer may be larger than max*BufferRange.  In that case, we use the minimum of
-    // the backing buffer size (what's left after offset) and the buffer size as defined by the
-    // shader.  That latter is only valid for UBOs, as SSBOs may have variable length arrays.
-    size = size > 0 ? size : (bufferHelper.getSize() - offset);
-    if (maxSize > 0)
-    {
-        size = std::min(size, maxSize);
-    }
-
-    // If requiredOffsetAlignment is 0, the buffer offset is guaranteed to have the necessary
-    // alignment through other means (the backend specifying the alignment through a GLES limit that
-    // the frontend then enforces).  If it's not 0, we need to bind the buffer at an offset that's
-    // aligned.  The difference in offsets is communicated to the shader via driver uniforms.
-    if (requiredOffsetAlignment)
-    {
-        VkDeviceSize alignedOffset = (offset / requiredOffsetAlignment) * requiredOffsetAlignment;
-        VkDeviceSize offsetDiff    = offset - alignedOffset;
-
-        offset = alignedOffset;
-        size += offsetDiff;
-    }
-
-    bufferInfoOut->buffer = bufferHelper.getBuffer().getHandle();
-    bufferInfoOut->offset = offset;
-    bufferInfoOut->range  = size;
-
-    writeInfoOut->sType            = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
-    writeInfoOut->pNext            = nullptr;
-    writeInfoOut->dstSet           = descSet;
-    writeInfoOut->dstBinding       = bindingIndex;
-    writeInfoOut->dstArrayElement  = arrayElement;
-    writeInfoOut->descriptorCount  = 1;
-    writeInfoOut->descriptorType   = descType;
-    writeInfoOut->pImageInfo       = nullptr;
-    writeInfoOut->pBufferInfo      = bufferInfoOut;
-    writeInfoOut->pTexelBufferView = nullptr;
-    ASSERT(writeInfoOut->pBufferInfo[0].buffer != VK_NULL_HANDLE);
-}
-
 class Std140BlockLayoutEncoderFactory : public gl::CustomBlockLayoutEncoderFactory
 {
   public:
@@ -359,118 +160,12 @@
 };
 }  // anonymous namespace
 
-// ProgramVk::ShaderInfo implementation.
-ProgramVk::ShaderInfo::ShaderInfo() {}
-
-ProgramVk::ShaderInfo::~ShaderInfo() = default;
-
-angle::Result ProgramVk::ShaderInfo::initShaders(
-    ContextVk *contextVk,
-    const gl::ShaderMap<std::string> &shaderSources,
-    const ShaderInterfaceVariableInfoMap &variableInfoMap)
-{
-    ASSERT(!valid());
-
-    ANGLE_TRY(GlslangWrapperVk::GetShaderCode(contextVk, contextVk->getCaps(), shaderSources,
-                                              variableInfoMap, &mSpirvBlobs));
-
-    mIsInitialized = true;
-    return angle::Result::Continue;
-}
-
-void ProgramVk::ShaderInfo::release(ContextVk *contextVk)
-{
-    for (SpirvBlob &spirvBlob : mSpirvBlobs)
-    {
-        spirvBlob.clear();
-    }
-    mIsInitialized = false;
-}
-
-void ProgramVk::ShaderInfo::load(gl::BinaryInputStream *stream)
-{
-    // Read in shader codes for all shader types
-    for (const gl::ShaderType shaderType : gl::AllShaderTypes())
-    {
-        SpirvBlob *spirvBlob = &mSpirvBlobs[shaderType];
-
-        // Read the SPIR-V
-        stream->readIntVector<uint32_t>(spirvBlob);
-    }
-
-    mIsInitialized = true;
-}
-
-void ProgramVk::ShaderInfo::save(gl::BinaryOutputStream *stream)
-{
-    ASSERT(valid());
-
-    // Write out shader codes for all shader types
-    for (const gl::ShaderType shaderType : gl::AllShaderTypes())
-    {
-        const SpirvBlob &spirvBlob = mSpirvBlobs[shaderType];
-
-        // Write the SPIR-V
-        stream->writeIntVector(spirvBlob);
-    }
-}
-
-// ProgramVk::ProgramInfo implementation.
-ProgramVk::ProgramInfo::ProgramInfo() {}
-
-ProgramVk::ProgramInfo::~ProgramInfo() = default;
-
-angle::Result ProgramVk::ProgramInfo::initProgram(ContextVk *contextVk,
-                                                  const ShaderInfo &shaderInfo,
-                                                  bool enableLineRasterEmulation)
-{
-    const gl::ShaderMap<SpirvBlob> &spirvBlobs = shaderInfo.getSpirvBlobs();
-
-    for (const gl::ShaderType shaderType : gl::AllShaderTypes())
-    {
-        const SpirvBlob &spirvBlob = spirvBlobs[shaderType];
-
-        if (!spirvBlob.empty())
-        {
-            ANGLE_TRY(vk::InitShaderAndSerial(contextVk, &mShaders[shaderType].get(),
-                                              spirvBlob.data(),
-                                              spirvBlob.size() * sizeof(uint32_t)));
-
-            mProgramHelper.setShader(shaderType, &mShaders[shaderType]);
-        }
-    }
-
-    if (enableLineRasterEmulation)
-    {
-        mProgramHelper.enableSpecializationConstant(
-            sh::vk::SpecializationConstantId::LineRasterEmulation);
-    }
-
-    return angle::Result::Continue;
-}
-
-void ProgramVk::ProgramInfo::release(ContextVk *contextVk)
-{
-    mProgramHelper.release(contextVk);
-
-    for (vk::RefCounted<vk::ShaderAndSerial> &shader : mShaders)
-    {
-        shader.get().destroy(contextVk->getDevice());
-    }
-}
-
 // ProgramVk implementation.
-ProgramVk::DefaultUniformBlock::DefaultUniformBlock() {}
-
-ProgramVk::DefaultUniformBlock::~DefaultUniformBlock() = default;
-
-ProgramVk::ProgramVk(const gl::ProgramState &state)
-    : ProgramImpl(state),
-      mDynamicBufferOffsets{},
-      mStorageBlockBindingsOffset(0),
-      mAtomicCounterBufferBindingsOffset(0),
-      mImageBindingsOffset(0)
-{}
+ProgramVk::ProgramVk(const gl::ProgramState &state) : ProgramImpl(state)
+{
+    GlslangWrapperVk::ResetGlslangProgramInterfaceInfo(&mGlslangProgramInterfaceInfo);
+    mExecutable.setProgram(this);
+}
 
 ProgramVk::~ProgramVk() = default;
 
@@ -482,40 +177,18 @@
 
 void ProgramVk::reset(ContextVk *contextVk)
 {
-    for (auto &descriptorSetLayout : mDescriptorSetLayouts)
-    {
-        descriptorSetLayout.reset();
-    }
-    mPipelineLayout.reset();
-
     RendererVk *renderer = contextVk->getRenderer();
 
+    mShaderInfo.release(contextVk);
+
     for (auto &uniformBlock : mDefaultUniformBlocks)
     {
         uniformBlock.storage.release(renderer);
     }
 
-    mShaderInfo.release(contextVk);
-    mDefaultProgramInfo.release(contextVk);
-    mLineRasterProgramInfo.release(contextVk);
+    GlslangWrapperVk::ResetGlslangProgramInterfaceInfo(&mGlslangProgramInterfaceInfo);
 
-    mEmptyBuffer.release(renderer);
-
-    mDescriptorSets.clear();
-    mEmptyDescriptorSets.fill(VK_NULL_HANDLE);
-
-    for (vk::RefCountedDescriptorPoolBinding &binding : mDescriptorPoolBindings)
-    {
-        binding.reset();
-    }
-
-    for (vk::DynamicDescriptorPool &descriptorPool : mDynamicDescriptorPools)
-    {
-        descriptorPool.release(contextVk);
-    }
-
-    mTextureDescriptorsCache.clear();
-    mDescriptorBuffersCache.clear();
+    mExecutable.reset(contextVk);
 }
 
 std::unique_ptr<rx::LinkEvent> ProgramVk::load(const gl::Context *context,
@@ -529,6 +202,7 @@
     reset(contextVk);
 
     mShaderInfo.load(stream);
+    mExecutable.load(stream);
 
     // Deserializes the uniformLayout data of mDefaultUniformBlocks
     for (gl::ShaderType shaderType : gl::AllShaderTypes())
@@ -555,12 +229,14 @@
         return std::make_unique<LinkEventDone>(status);
     }
 
-    return std::make_unique<LinkEventDone>(linkImpl(context, infoLog));
+    status = mExecutable.createPipelineLayout(context);
+    return std::make_unique<LinkEventDone>(status);
 }
 
 void ProgramVk::save(const gl::Context *context, gl::BinaryOutputStream *stream)
 {
     mShaderInfo.save(stream);
+    mExecutable.save(stream);
 
     // Serializes the uniformLayout data of mDefaultUniformBlocks
     for (gl::ShaderType shaderType : gl::AllShaderTypes())
@@ -592,6 +268,20 @@
     // Nohting to do here yet.
 }
 
+// TODO: http://anglebug.com/3570: Move/Copy all of the necessary information into
+// the ProgramExecutable, so this function can be removed.
+void ProgramVk::fillProgramStateMap(gl::ShaderMap<const gl::ProgramState *> *programStatesOut)
+{
+    for (gl::ShaderType shaderType : gl::AllShaderTypes())
+    {
+        (*programStatesOut)[shaderType] = nullptr;
+        if (mState.getProgramExecutable().hasLinkedShaderStage(shaderType))
+        {
+            (*programStatesOut)[shaderType] = &mState;
+        }
+    }
+}
+
 std::unique_ptr<LinkEvent> ProgramVk::link(const gl::Context *context,
                                            const gl::ProgramLinkedResources &resources,
                                            gl::InfoLog &infoLog)
@@ -602,15 +292,17 @@
     linkResources(resources);
 
     reset(contextVk);
+    mExecutable.clearVariableInfoMap();
 
     // Gather variable info and transform sources.
     gl::ShaderMap<std::string> shaderSources;
-    ShaderInterfaceVariableInfoMap variableInfoMap;
     GlslangWrapperVk::GetShaderSource(contextVk->getRenderer()->getFeatures(), mState, resources,
-                                      &shaderSources, &variableInfoMap);
+                                      &mGlslangProgramInterfaceInfo, &shaderSources,
+                                      &mExecutable.mVariableInfoMap);
 
     // Compile the shaders.
-    angle::Result status = mShaderInfo.initShaders(contextVk, shaderSources, variableInfoMap);
+    angle::Result status =
+        mShaderInfo.initShaders(contextVk, shaderSources, mExecutable.mVariableInfoMap);
     if (status != angle::Result::Continue)
     {
         return std::make_unique<LinkEventDone>(status);
@@ -624,173 +316,8 @@
 
     // TODO(jie.a.chen@intel.com): Parallelize linking.
     // http://crbug.com/849576
-    return std::make_unique<LinkEventDone>(linkImpl(context, infoLog));
-}
-
-angle::Result ProgramVk::linkImpl(const gl::Context *glContext, gl::InfoLog &infoLog)
-{
-    const gl::State &glState                 = glContext->getState();
-    ContextVk *contextVk                     = vk::GetImpl(glContext);
-    RendererVk *renderer                     = contextVk->getRenderer();
-    gl::TransformFeedback *transformFeedback = glState.getCurrentTransformFeedback();
-
-    updateBindingOffsets();
-
-    // Store a reference to the pipeline and descriptor set layouts. This will create them if they
-    // don't already exist in the cache.
-
-    // Default uniforms and transform feedback:
-    vk::DescriptorSetLayoutDesc uniformsAndXfbSetDesc;
-    uint32_t uniformBindingIndex = 0;
-    for (const gl::ShaderType shaderType : mState.getLinkedShaderStages())
-    {
-        uniformsAndXfbSetDesc.update(uniformBindingIndex++,
-                                     VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1,
-                                     gl_vk::kShaderStageMap[shaderType]);
-    }
-    if (mState.hasLinkedShaderStage(gl::ShaderType::Vertex) && transformFeedback &&
-        !mState.getLinkedTransformFeedbackVaryings().empty())
-    {
-        TransformFeedbackVk *transformFeedbackVk = vk::GetImpl(transformFeedback);
-        transformFeedbackVk->updateDescriptorSetLayout(contextVk, mState, &uniformsAndXfbSetDesc);
-    }
-
-    ANGLE_TRY(renderer->getDescriptorSetLayout(
-        contextVk, uniformsAndXfbSetDesc,
-        &mDescriptorSetLayouts[kUniformsAndXfbDescriptorSetIndex]));
-
-    // Uniform and storage buffers, atomic counter buffers and images:
-    vk::DescriptorSetLayoutDesc resourcesSetDesc;
-
-    AddInterfaceBlockDescriptorSetDesc(mState.getUniformBlocks(), getUniformBlockBindingsOffset(),
-                                       VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &resourcesSetDesc);
-    AddInterfaceBlockDescriptorSetDesc(mState.getShaderStorageBlocks(),
-                                       getStorageBlockBindingsOffset(),
-                                       VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resourcesSetDesc);
-    AddAtomicCounterBufferDescriptorSetDesc(mState.getAtomicCounterBuffers(),
-                                            getAtomicCounterBufferBindingsOffset(),
-                                            &resourcesSetDesc);
-    AddImageDescriptorSetDesc(mState, getImageBindingsOffset(), &resourcesSetDesc);
-
-    ANGLE_TRY(renderer->getDescriptorSetLayout(
-        contextVk, resourcesSetDesc, &mDescriptorSetLayouts[kShaderResourceDescriptorSetIndex]));
-
-    // Textures:
-    vk::DescriptorSetLayoutDesc texturesSetDesc;
-
-    AddTextureDescriptorSetDesc(mState, contextVk->useOldRewriteStructSamplers(), &texturesSetDesc);
-
-    ANGLE_TRY(renderer->getDescriptorSetLayout(contextVk, texturesSetDesc,
-                                               &mDescriptorSetLayouts[kTextureDescriptorSetIndex]));
-
-    // Driver uniforms:
-    VkShaderStageFlags driverUniformsStages =
-        mState.isCompute() ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_ALL_GRAPHICS;
-    vk::DescriptorSetLayoutDesc driverUniformsSetDesc =
-        contextVk->getDriverUniformsDescriptorSetDesc(driverUniformsStages);
-    ANGLE_TRY(renderer->getDescriptorSetLayout(
-        contextVk, driverUniformsSetDesc,
-        &mDescriptorSetLayouts[kDriverUniformsDescriptorSetIndex]));
-
-    // Create pipeline layout with these 4 descriptor sets.
-    vk::PipelineLayoutDesc pipelineLayoutDesc;
-    pipelineLayoutDesc.updateDescriptorSetLayout(kUniformsAndXfbDescriptorSetIndex,
-                                                 uniformsAndXfbSetDesc);
-    pipelineLayoutDesc.updateDescriptorSetLayout(kShaderResourceDescriptorSetIndex,
-                                                 resourcesSetDesc);
-    pipelineLayoutDesc.updateDescriptorSetLayout(kTextureDescriptorSetIndex, texturesSetDesc);
-    pipelineLayoutDesc.updateDescriptorSetLayout(kDriverUniformsDescriptorSetIndex,
-                                                 driverUniformsSetDesc);
-
-    ANGLE_TRY(renderer->getPipelineLayout(contextVk, pipelineLayoutDesc, mDescriptorSetLayouts,
-                                          &mPipelineLayout));
-
-    // Initialize descriptor pools.
-    std::array<VkDescriptorPoolSize, 2> uniformAndXfbSetSize = {
-        {{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
-          static_cast<uint32_t>(mState.getLinkedShaderStageCount())},
-         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS}}};
-
-    uint32_t uniformBlockCount = static_cast<uint32_t>(mState.getUniformBlocks().size());
-    uint32_t storageBlockCount = static_cast<uint32_t>(mState.getShaderStorageBlocks().size());
-    uint32_t atomicCounterBufferCount =
-        static_cast<uint32_t>(mState.getAtomicCounterBuffers().size());
-    uint32_t imageCount   = static_cast<uint32_t>(mState.getImageBindings().size());
-    uint32_t textureCount = static_cast<uint32_t>(mState.getSamplerBindings().size());
-
-    if (renderer->getFeatures().bindEmptyForUnusedDescriptorSets.enabled)
-    {
-        // For this workaround, we have to create an empty descriptor set for each descriptor set
-        // index, so make sure their pools are initialized.
-        uniformBlockCount = std::max(uniformBlockCount, 1u);
-        textureCount      = std::max(textureCount, 1u);
-    }
-
-    constexpr size_t kResourceTypesInResourcesSet = 3;
-    angle::FixedVector<VkDescriptorPoolSize, kResourceTypesInResourcesSet> resourceSetSize;
-    if (uniformBlockCount > 0)
-    {
-        resourceSetSize.emplace_back(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, uniformBlockCount);
-    }
-    if (storageBlockCount > 0 || atomicCounterBufferCount > 0)
-    {
-        // Note that we always use an array of IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS storage
-        // buffers for emulating atomic counters, so if there are any atomic counter buffers, we
-        // need to allocate IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS descriptors.
-        const uint32_t atomicCounterStorageBufferCount =
-            atomicCounterBufferCount > 0 ? gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS : 0;
-        const uint32_t storageBufferDescCount = storageBlockCount + atomicCounterStorageBufferCount;
-        resourceSetSize.emplace_back(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, storageBufferDescCount);
-    }
-    if (imageCount > 0)
-    {
-        resourceSetSize.emplace_back(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, imageCount);
-    }
-
-    VkDescriptorPoolSize textureSetSize = {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, textureCount};
-
-    ANGLE_TRY(mDynamicDescriptorPools[kUniformsAndXfbDescriptorSetIndex].init(
-        contextVk, uniformAndXfbSetSize.data(), uniformAndXfbSetSize.size()));
-    if (resourceSetSize.size() > 0)
-    {
-        ANGLE_TRY(mDynamicDescriptorPools[kShaderResourceDescriptorSetIndex].init(
-            contextVk, resourceSetSize.data(), static_cast<uint32_t>(resourceSetSize.size())));
-    }
-    if (textureCount > 0)
-    {
-        ANGLE_TRY(mDynamicDescriptorPools[kTextureDescriptorSetIndex].init(contextVk,
-                                                                           &textureSetSize, 1));
-    }
-
-    mDynamicBufferOffsets.resize(mState.getLinkedShaderStageCount());
-
-    // Initialize an "empty" buffer for use with default uniform blocks where there are no uniforms,
-    // or atomic counter buffer array indices that are unused.
-    constexpr VkBufferUsageFlags kEmptyBufferUsage =
-        VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
-
-    VkBufferCreateInfo emptyBufferInfo    = {};
-    emptyBufferInfo.sType                 = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
-    emptyBufferInfo.flags                 = 0;
-    emptyBufferInfo.size                  = 4;
-    emptyBufferInfo.usage                 = kEmptyBufferUsage;
-    emptyBufferInfo.sharingMode           = VK_SHARING_MODE_EXCLUSIVE;
-    emptyBufferInfo.queueFamilyIndexCount = 0;
-    emptyBufferInfo.pQueueFamilyIndices   = nullptr;
-
-    constexpr VkMemoryPropertyFlags kMemoryType = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
-    return mEmptyBuffer.init(contextVk, emptyBufferInfo, kMemoryType);
-}
-
-void ProgramVk::updateBindingOffsets()
-{
-    mStorageBlockBindingsOffset = static_cast<uint32_t>(mState.getUniqueUniformBlockCount());
-
-    mAtomicCounterBufferBindingsOffset =
-        static_cast<uint32_t>(mStorageBlockBindingsOffset + mState.getUniqueStorageBlockCount());
-
-    uint32_t atomicCounterBindingCount = mState.getAtomicCounterBuffers().empty() ? 0 : 1;
-    mImageBindingsOffset = mAtomicCounterBufferBindingsOffset + atomicCounterBindingCount;
+    status = mExecutable.createPipelineLayout(context);
+    return std::make_unique<LinkEventDone>(status);
 }
 
 void ProgramVk::linkResources(const gl::ProgramLinkedResources &resources)
@@ -820,7 +347,9 @@
 void ProgramVk::generateUniformLayoutMapping(gl::ShaderMap<sh::BlockLayoutMap> &layoutMap,
                                              gl::ShaderMap<size_t> &requiredBufferSize)
 {
-    for (const gl::ShaderType shaderType : mState.getLinkedShaderStages())
+    const gl::ProgramExecutable &glExecutable = mState.getProgramExecutable();
+
+    for (const gl::ShaderType shaderType : glExecutable.getLinkedShaderStages())
     {
         gl::Shader *shader = mState.getAttachedShader(shaderType);
 
@@ -836,7 +365,9 @@
 void ProgramVk::initDefaultUniformLayoutMapping(gl::ShaderMap<sh::BlockLayoutMap> &layoutMap)
 {
     // Init the default block layout info.
-    const auto &uniforms = mState.getUniforms();
+    const auto &uniforms                      = mState.getUniforms();
+    const gl::ProgramExecutable &glExecutable = mState.getProgramExecutable();
+
     for (const gl::VariableLocation &location : mState.getUniformLocations())
     {
         gl::ShaderMap<sh::BlockMemberInfo> layoutInfo;
@@ -856,7 +387,7 @@
 
                 bool found = false;
 
-                for (const gl::ShaderType shaderType : mState.getLinkedShaderStages())
+                for (const gl::ShaderType shaderType : glExecutable.getLinkedShaderStages())
                 {
                     auto it = layoutMap[shaderType].find(uniformName);
                     if (it != layoutMap[shaderType].end())
@@ -870,7 +401,7 @@
             }
         }
 
-        for (const gl::ShaderType shaderType : mState.getLinkedShaderStages())
+        for (const gl::ShaderType shaderType : glExecutable.getLinkedShaderStages())
         {
             mDefaultUniformBlocks[shaderType].uniformLayout.push_back(layoutInfo[shaderType]);
         }
@@ -880,8 +411,10 @@
 angle::Result ProgramVk::resizeUniformBlockMemory(ContextVk *contextVk,
                                                   gl::ShaderMap<size_t> &requiredBufferSize)
 {
-    RendererVk *renderer = contextVk->getRenderer();
-    for (const gl::ShaderType shaderType : mState.getLinkedShaderStages())
+    RendererVk *renderer                      = contextVk->getRenderer();
+    const gl::ProgramExecutable &glExecutable = mState.getProgramExecutable();
+
+    for (const gl::ShaderType shaderType : glExecutable.getLinkedShaderStages())
     {
         if (requiredBufferSize[shaderType] > 0)
         {
@@ -915,14 +448,15 @@
 template <typename T>
 void ProgramVk::setUniformImpl(GLint location, GLsizei count, const T *v, GLenum entryPointType)
 {
-    const gl::VariableLocation &locationInfo = mState.getUniformLocations()[location];
-    const gl::LinkedUniform &linkedUniform   = mState.getUniforms()[locationInfo.index];
+    const gl::VariableLocation &locationInfo  = mState.getUniformLocations()[location];
+    const gl::LinkedUniform &linkedUniform    = mState.getUniforms()[locationInfo.index];
+    const gl::ProgramExecutable &glExecutable = mState.getProgramExecutable();
 
     ASSERT(!linkedUniform.isSampler());
 
     if (linkedUniform.typeInfo->type == entryPointType)
     {
-        for (const gl::ShaderType shaderType : mState.getLinkedShaderStages())
+        for (const gl::ShaderType shaderType : glExecutable.getLinkedShaderStages())
         {
             DefaultUniformBlock &uniformBlock     = mDefaultUniformBlocks[shaderType];
             const sh::BlockMemberInfo &layoutInfo = uniformBlock.uniformLayout[location];
@@ -941,7 +475,7 @@
     }
     else
     {
-        for (const gl::ShaderType shaderType : mState.getLinkedShaderStages())
+        for (const gl::ShaderType shaderType : glExecutable.getLinkedShaderStages())
         {
             DefaultUniformBlock &uniformBlock     = mDefaultUniformBlocks[shaderType];
             const sh::BlockMemberInfo &layoutInfo = uniformBlock.uniformLayout[location];
@@ -1081,10 +615,11 @@
                                    GLboolean transpose,
                                    const GLfloat *value)
 {
-    const gl::VariableLocation &locationInfo = mState.getUniformLocations()[location];
-    const gl::LinkedUniform &linkedUniform   = mState.getUniforms()[locationInfo.index];
+    const gl::VariableLocation &locationInfo  = mState.getUniformLocations()[location];
+    const gl::LinkedUniform &linkedUniform    = mState.getUniforms()[locationInfo.index];
+    const gl::ProgramExecutable &glExecutable = mState.getProgramExecutable();
 
-    for (const gl::ShaderType shaderType : mState.getLinkedShaderStages())
+    for (const gl::ShaderType shaderType : glExecutable.getLinkedShaderStages())
     {
         DefaultUniformBlock &uniformBlock     = mDefaultUniformBlocks[shaderType];
         const sh::BlockMemberInfo &layoutInfo = uniformBlock.uniformLayout[location];
@@ -1175,42 +710,6 @@
     setUniformMatrixfv<4, 3>(location, count, transpose, value);
 }
 
-void ProgramVk::setPathFragmentInputGen(const std::string &inputName,
-                                        GLenum genMode,
-                                        GLint components,
-                                        const GLfloat *coeffs)
-{
-    UNIMPLEMENTED();
-}
-
-angle::Result ProgramVk::allocateDescriptorSet(ContextVk *contextVk, uint32_t descriptorSetIndex)
-{
-    bool ignoreNewPoolAllocated;
-    return allocateDescriptorSetAndGetInfo(contextVk, descriptorSetIndex, &ignoreNewPoolAllocated);
-}
-
-angle::Result ProgramVk::allocateDescriptorSetAndGetInfo(ContextVk *contextVk,
-                                                         uint32_t descriptorSetIndex,
-                                                         bool *newPoolAllocatedOut)
-{
-    vk::DynamicDescriptorPool &dynamicDescriptorPool = mDynamicDescriptorPools[descriptorSetIndex];
-
-    uint32_t potentialNewCount = descriptorSetIndex + 1;
-    if (potentialNewCount > mDescriptorSets.size())
-    {
-        mDescriptorSets.resize(potentialNewCount, VK_NULL_HANDLE);
-    }
-
-    const vk::DescriptorSetLayout &descriptorSetLayout =
-        mDescriptorSetLayouts[descriptorSetIndex].get();
-    ANGLE_TRY(dynamicDescriptorPool.allocateSetsAndGetInfo(
-        contextVk, descriptorSetLayout.ptr(), 1, &mDescriptorPoolBindings[descriptorSetIndex],
-        &mDescriptorSets[descriptorSetIndex], newPoolAllocatedOut));
-    mEmptyDescriptorSets[descriptorSetIndex] = VK_NULL_HANDLE;
-
-    return angle::Result::Continue;
-}
-
 void ProgramVk::getUniformfv(const gl::Context *context, GLint location, GLfloat *params) const
 {
     getUniformImpl(location, params, GL_FLOAT);
@@ -1226,32 +725,44 @@
     getUniformImpl(location, params, GL_UNSIGNED_INT);
 }
 
+angle::Result ProgramVk::updateShaderUniforms(ContextVk *contextVk,
+                                              gl::ShaderType shaderType,
+                                              uint32_t *outOffset,
+                                              bool *anyNewBufferAllocated)
+{
+    // Update buffer memory by immediate mapping. This immediate update only works once.
+    DefaultUniformBlock &uniformBlock = mDefaultUniformBlocks[shaderType];
+
+    if (mDefaultUniformBlocksDirty[shaderType])
+    {
+        bool bufferModified = false;
+        ANGLE_TRY(SyncDefaultUniformBlock(contextVk, &uniformBlock.storage,
+                                          uniformBlock.uniformData, outOffset, &bufferModified));
+        mDefaultUniformBlocksDirty.reset(shaderType);
+
+        if (bufferModified)
+        {
+            *anyNewBufferAllocated = true;
+        }
+    }
+
+    return angle::Result::Continue;
+}
+
 angle::Result ProgramVk::updateUniforms(ContextVk *contextVk)
 {
     ASSERT(dirtyUniforms());
 
-    bool anyNewBufferAllocated = false;
-    uint32_t offsetIndex       = 0;
+    bool anyNewBufferAllocated                = false;
+    uint32_t offsetIndex                      = 0;
+    const gl::ProgramExecutable &glExecutable = mState.getProgramExecutable();
 
     // Update buffer memory by immediate mapping. This immediate update only works once.
-    for (gl::ShaderType shaderType : mState.getLinkedShaderStages())
+    for (const gl::ShaderType shaderType : glExecutable.getLinkedShaderStages())
     {
-        DefaultUniformBlock &uniformBlock = mDefaultUniformBlocks[shaderType];
-
-        if (mDefaultUniformBlocksDirty[shaderType])
-        {
-            bool bufferModified = false;
-            ANGLE_TRY(
-                SyncDefaultUniformBlock(contextVk, &uniformBlock.storage, uniformBlock.uniformData,
-                                        &mDynamicBufferOffsets[offsetIndex], &bufferModified));
-            mDefaultUniformBlocksDirty.reset(shaderType);
-
-            if (bufferModified)
-            {
-                anyNewBufferAllocated = true;
-            }
-        }
-
+        ANGLE_TRY(updateShaderUniforms(contextVk, shaderType,
+                                       &mExecutable.mDynamicBufferOffsets[offsetIndex],
+                                       &anyNewBufferAllocated));
         ++offsetIndex;
     }
 
@@ -1259,493 +770,17 @@
     {
         // We need to reinitialize the descriptor sets if we newly allocated buffers since we can't
         // modify the descriptor sets once initialized.
-        ANGLE_TRY(allocateDescriptorSet(contextVk, kUniformsAndXfbDescriptorSetIndex));
-        updateDefaultUniformsDescriptorSet(contextVk);
-        updateTransformFeedbackDescriptorSetImpl(contextVk);
-    }
+        ANGLE_TRY(mExecutable.allocateDescriptorSet(contextVk, kUniformsAndXfbDescriptorSetIndex));
 
-    return angle::Result::Continue;
-}
-
-void ProgramVk::updateDefaultUniformsDescriptorSet(ContextVk *contextVk)
-{
-    uint32_t shaderStageCount = static_cast<uint32_t>(mState.getLinkedShaderStageCount());
-
-    gl::ShaderVector<VkDescriptorBufferInfo> descriptorBufferInfo(shaderStageCount);
-    gl::ShaderVector<VkWriteDescriptorSet> writeDescriptorInfo(shaderStageCount);
-
-    uint32_t bindingIndex = 0;
-
-    mDescriptorBuffersCache.clear();
-
-    // Write default uniforms for each shader type.
-    for (const gl::ShaderType shaderType : mState.getLinkedShaderStages())
-    {
-        DefaultUniformBlock &uniformBlock  = mDefaultUniformBlocks[shaderType];
-        VkDescriptorBufferInfo &bufferInfo = descriptorBufferInfo[bindingIndex];
-        VkWriteDescriptorSet &writeInfo    = writeDescriptorInfo[bindingIndex];
-
-        if (!uniformBlock.uniformData.empty())
+        mExecutable.mDescriptorBuffersCache.clear();
+        for (const gl::ShaderType shaderType : glExecutable.getLinkedShaderStages())
         {
-            vk::BufferHelper *bufferHelper = uniformBlock.storage.getCurrentBuffer();
-            bufferInfo.buffer              = bufferHelper->getBuffer().getHandle();
-            mDescriptorBuffersCache.emplace_back(bufferHelper);
-        }
-        else
-        {
-            mEmptyBuffer.retain(&contextVk->getResourceUseList());
-            bufferInfo.buffer = mEmptyBuffer.getBuffer().getHandle();
-            mDescriptorBuffersCache.emplace_back(&mEmptyBuffer);
-        }
-
-        bufferInfo.offset = 0;
-        bufferInfo.range  = VK_WHOLE_SIZE;
-
-        writeInfo.sType            = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
-        writeInfo.pNext            = nullptr;
-        writeInfo.dstSet           = mDescriptorSets[kUniformsAndXfbDescriptorSetIndex];
-        writeInfo.dstBinding       = bindingIndex;
-        writeInfo.dstArrayElement  = 0;
-        writeInfo.descriptorCount  = 1;
-        writeInfo.descriptorType   = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
-        writeInfo.pImageInfo       = nullptr;
-        writeInfo.pBufferInfo      = &bufferInfo;
-        writeInfo.pTexelBufferView = nullptr;
-
-        ++bindingIndex;
-    }
-
-    VkDevice device = contextVk->getDevice();
-
-    ASSERT(bindingIndex == shaderStageCount);
-    ASSERT(shaderStageCount <= kReservedDefaultUniformBindingCount);
-
-    vkUpdateDescriptorSets(device, shaderStageCount, writeDescriptorInfo.data(), 0, nullptr);
-}
-
-void ProgramVk::updateBuffersDescriptorSet(ContextVk *contextVk,
-                                           vk::ResourceUseList *resourceUseList,
-                                           CommandBufferHelper *commandBufferHelper,
-                                           const std::vector<gl::InterfaceBlock> &blocks,
-                                           VkDescriptorType descriptorType)
-{
-    if (blocks.empty())
-    {
-        return;
-    }
-
-    VkDescriptorSet descriptorSet = mDescriptorSets[kShaderResourceDescriptorSetIndex];
-
-    ASSERT(descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ||
-           descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
-    const bool isStorageBuffer = descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
-    const uint32_t bindingStart =
-        isStorageBuffer ? getStorageBlockBindingsOffset() : getUniformBlockBindingsOffset();
-
-    static_assert(
-        gl::IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS >=
-            gl::IMPLEMENTATION_MAX_UNIFORM_BUFFER_BINDINGS,
-        "The descriptor arrays here would have inadequate size for uniform buffer objects");
-
-    gl::StorageBuffersArray<VkDescriptorBufferInfo> descriptorBufferInfo;
-    gl::StorageBuffersArray<VkWriteDescriptorSet> writeDescriptorInfo;
-    uint32_t writeCount = 0;
-    // The binding is incremented every time arrayElement 0 is encountered, which means there will
-    // be an increment right at the start.  Start from -1 to get 0 as the first binding.
-    int32_t currentBinding = -1;
-
-    // Write uniform or storage buffers.
-    const gl::State &glState = contextVk->getState();
-    for (uint32_t bufferIndex = 0; bufferIndex < blocks.size(); ++bufferIndex)
-    {
-        const gl::InterfaceBlock &block = blocks[bufferIndex];
-        const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding =
-            isStorageBuffer ? glState.getIndexedShaderStorageBuffer(block.binding)
-                            : glState.getIndexedUniformBuffer(block.binding);
-
-        if (!block.isArray || block.arrayElement == 0)
-        {
-            // Array indices of the same buffer binding are placed sequentially in `blocks`.
-            // Thus, the block binding is updated only when array index 0 is encountered.
-            ++currentBinding;
-        }
-
-        if (bufferBinding.get() == nullptr)
-        {
-            continue;
-        }
-
-        uint32_t binding          = bindingStart + currentBinding;
-        uint32_t arrayElement     = block.isArray ? block.arrayElement : 0;
-        VkDeviceSize maxBlockSize = isStorageBuffer ? 0 : block.dataSize;
-
-        VkDescriptorBufferInfo &bufferInfo = descriptorBufferInfo[writeCount];
-        VkWriteDescriptorSet &writeInfo    = writeDescriptorInfo[writeCount];
-
-        WriteBufferDescriptorSetBinding(bufferBinding, maxBlockSize, descriptorSet, descriptorType,
-                                        binding, arrayElement, 0, &bufferInfo, &writeInfo);
-
-        BufferVk *bufferVk             = vk::GetImpl(bufferBinding.get());
-        vk::BufferHelper &bufferHelper = bufferVk->getBuffer();
-
-        if (isStorageBuffer)
-        {
-            // We set the SHADER_READ_BIT to be conservative.
-            VkAccessFlags accessFlags = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
-            commandBufferHelper->bufferWrite(resourceUseList, accessFlags, &bufferHelper);
-        }
-        else
-        {
-            commandBufferHelper->bufferRead(resourceUseList, VK_ACCESS_UNIFORM_READ_BIT,
-                                            &bufferHelper);
-        }
-
-        ++writeCount;
-    }
-
-    VkDevice device = contextVk->getDevice();
-
-    vkUpdateDescriptorSets(device, writeCount, writeDescriptorInfo.data(), 0, nullptr);
-}
-
-void ProgramVk::updateAtomicCounterBuffersDescriptorSet(ContextVk *contextVk,
-                                                        vk::ResourceUseList *resourceUseList,
-                                                        CommandBufferHelper *commandBufferHelper)
-{
-    const gl::State &glState = contextVk->getState();
-    const std::vector<gl::AtomicCounterBuffer> &atomicCounterBuffers =
-        mState.getAtomicCounterBuffers();
-
-    if (atomicCounterBuffers.empty())
-    {
-        return;
-    }
-
-    VkDescriptorSet descriptorSet = mDescriptorSets[kShaderResourceDescriptorSetIndex];
-
-    const uint32_t bindingStart = getAtomicCounterBufferBindingsOffset();
-
-    gl::AtomicCounterBuffersArray<VkDescriptorBufferInfo> descriptorBufferInfo;
-    gl::AtomicCounterBuffersArray<VkWriteDescriptorSet> writeDescriptorInfo;
-    gl::AtomicCounterBufferMask writtenBindings;
-
-    RendererVk *rendererVk = contextVk->getRenderer();
-    const VkDeviceSize requiredOffsetAlignment =
-        rendererVk->getPhysicalDeviceProperties().limits.minStorageBufferOffsetAlignment;
-
-    // Write atomic counter buffers.
-    for (uint32_t bufferIndex = 0; bufferIndex < atomicCounterBuffers.size(); ++bufferIndex)
-    {
-        const gl::AtomicCounterBuffer &atomicCounterBuffer = atomicCounterBuffers[bufferIndex];
-        uint32_t binding                                   = atomicCounterBuffer.binding;
-        const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding =
-            glState.getIndexedAtomicCounterBuffer(binding);
-
-        if (bufferBinding.get() == nullptr)
-        {
-            continue;
-        }
-
-        VkDescriptorBufferInfo &bufferInfo = descriptorBufferInfo[binding];
-        VkWriteDescriptorSet &writeInfo    = writeDescriptorInfo[binding];
-
-        WriteBufferDescriptorSetBinding(bufferBinding, 0, descriptorSet,
-                                        VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, bindingStart, binding,
-                                        requiredOffsetAlignment, &bufferInfo, &writeInfo);
-
-        BufferVk *bufferVk             = vk::GetImpl(bufferBinding.get());
-        vk::BufferHelper &bufferHelper = bufferVk->getBuffer();
-
-        // We set SHADER_READ_BIT to be conservative.
-        commandBufferHelper->bufferWrite(
-            resourceUseList, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, &bufferHelper);
-
-        writtenBindings.set(binding);
-    }
-
-    // Bind the empty buffer to every array slot that's unused.
-    mEmptyBuffer.retain(&contextVk->getResourceUseList());
-    for (size_t binding : ~writtenBindings)
-    {
-        VkDescriptorBufferInfo &bufferInfo = descriptorBufferInfo[binding];
-        VkWriteDescriptorSet &writeInfo    = writeDescriptorInfo[binding];
-
-        bufferInfo.buffer = mEmptyBuffer.getBuffer().getHandle();
-        bufferInfo.offset = 0;
-        bufferInfo.range  = VK_WHOLE_SIZE;
-
-        writeInfo.sType            = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
-        writeInfo.pNext            = nullptr;
-        writeInfo.dstSet           = descriptorSet;
-        writeInfo.dstBinding       = bindingStart;
-        writeInfo.dstArrayElement  = static_cast<uint32_t>(binding);
-        writeInfo.descriptorCount  = 1;
-        writeInfo.descriptorType   = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
-        writeInfo.pImageInfo       = nullptr;
-        writeInfo.pBufferInfo      = &bufferInfo;
-        writeInfo.pTexelBufferView = nullptr;
-    }
-
-    VkDevice device = contextVk->getDevice();
-
-    vkUpdateDescriptorSets(device, gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS,
-                           writeDescriptorInfo.data(), 0, nullptr);
-}
-
-angle::Result ProgramVk::updateImagesDescriptorSet(ContextVk *contextVk)
-{
-    const gl::State &glState                           = contextVk->getState();
-    const std::vector<gl::ImageBinding> &imageBindings = mState.getImageBindings();
-
-    if (imageBindings.empty())
-    {
-        return angle::Result::Continue;
-    }
-
-    VkDescriptorSet descriptorSet = mDescriptorSets[kShaderResourceDescriptorSetIndex];
-
-    const gl::ActiveTextureArray<TextureVk *> &activeImages = contextVk->getActiveImages();
-
-    const uint32_t bindingStart = getImageBindingsOffset();
-
-    gl::ImagesArray<VkDescriptorImageInfo> descriptorImageInfo;
-    gl::ImagesArray<VkWriteDescriptorSet> writeDescriptorInfo;
-    uint32_t writeCount = 0;
-
-    // Write images.
-    for (uint32_t imageIndex = 0; imageIndex < imageBindings.size(); ++imageIndex)
-    {
-        const gl::ImageBinding &imageBinding = imageBindings[imageIndex];
-
-        ASSERT(!imageBinding.unreferenced);
-
-        for (uint32_t arrayElement = 0; arrayElement < imageBinding.boundImageUnits.size();
-             ++arrayElement)
-        {
-            GLuint imageUnit             = imageBinding.boundImageUnits[arrayElement];
-            const gl::ImageUnit &binding = glState.getImageUnit(imageUnit);
-            TextureVk *textureVk         = activeImages[imageUnit];
-
-            vk::ImageHelper *image         = &textureVk->getImage();
-            const vk::ImageView *imageView = nullptr;
-
-            ANGLE_TRY(textureVk->getStorageImageView(contextVk, (binding.layered == GL_TRUE),
-                                                     binding.level, binding.layer, &imageView));
-
-            // Note: binding.access is unused because it is implied by the shader.
-
-            // TODO(syoussefi): Support image data reinterpretation by using binding.format.
-            // http://anglebug.com/3563
-
-            VkDescriptorImageInfo &imageInfo = descriptorImageInfo[writeCount];
-            VkWriteDescriptorSet &writeInfo  = writeDescriptorInfo[writeCount];
-
-            imageInfo.sampler     = VK_NULL_HANDLE;
-            imageInfo.imageView   = imageView->getHandle();
-            imageInfo.imageLayout = image->getCurrentLayout();
-
-            writeInfo.sType            = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
-            writeInfo.pNext            = nullptr;
-            writeInfo.dstSet           = descriptorSet;
-            writeInfo.dstBinding       = bindingStart + imageIndex;
-            writeInfo.dstArrayElement  = arrayElement;
-            writeInfo.descriptorCount  = 1;
-            writeInfo.descriptorType   = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
-            writeInfo.pImageInfo       = &imageInfo;
-            writeInfo.pBufferInfo      = nullptr;
-            writeInfo.pTexelBufferView = nullptr;
-
-            ++writeCount;
+            mExecutable.updateDefaultUniformsDescriptorSet(shaderType, mDefaultUniformBlocks,
+                                                           contextVk);
+            mExecutable.updateTransformFeedbackDescriptorSetImpl(mState, contextVk);
         }
     }
 
-    VkDevice device = contextVk->getDevice();
-
-    vkUpdateDescriptorSets(device, writeCount, writeDescriptorInfo.data(), 0, nullptr);
-
-    return angle::Result::Continue;
-}
-
-angle::Result ProgramVk::updateShaderResourcesDescriptorSet(
-    ContextVk *contextVk,
-    vk::ResourceUseList *resourceUseList,
-    CommandBufferHelper *commandBufferHelper)
-{
-    ANGLE_TRY(allocateDescriptorSet(contextVk, kShaderResourceDescriptorSetIndex));
-
-    updateBuffersDescriptorSet(contextVk, resourceUseList, commandBufferHelper,
-                               mState.getUniformBlocks(), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
-    updateBuffersDescriptorSet(contextVk, resourceUseList, commandBufferHelper,
-                               mState.getShaderStorageBlocks(), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
-    updateAtomicCounterBuffersDescriptorSet(contextVk, resourceUseList, commandBufferHelper);
-    return updateImagesDescriptorSet(contextVk);
-}
-
-angle::Result ProgramVk::updateTransformFeedbackDescriptorSet(ContextVk *contextVk)
-{
-    ASSERT(hasTransformFeedbackOutput());
-
-    ANGLE_TRY(allocateDescriptorSet(contextVk, kUniformsAndXfbDescriptorSetIndex));
-
-    updateDefaultUniformsDescriptorSet(contextVk);
-    updateTransformFeedbackDescriptorSetImpl(contextVk);
-
-    return angle::Result::Continue;
-}
-
-void ProgramVk::updateTransformFeedbackDescriptorSetImpl(ContextVk *contextVk)
-{
-    const gl::State &glState                 = contextVk->getState();
-    gl::TransformFeedback *transformFeedback = glState.getCurrentTransformFeedback();
-
-    if (!hasTransformFeedbackOutput())
-    {
-        // If xfb has no output there is no need to update descriptor set.
-        return;
-    }
-    if (!glState.isTransformFeedbackActive())
-    {
-        // We set empty Buffer to xfb descriptor set because xfb descriptor set
-        // requires valid buffer bindings, even if they are empty buffer,
-        // otherwise Vulkan validation layer generates errors.
-        if (transformFeedback)
-        {
-            TransformFeedbackVk *transformFeedbackVk = vk::GetImpl(transformFeedback);
-            transformFeedbackVk->initDescriptorSet(
-                contextVk, mState.getTransformFeedbackBufferCount(), &mEmptyBuffer,
-                mDescriptorSets[kUniformsAndXfbDescriptorSetIndex]);
-        }
-        return;
-    }
-
-    TransformFeedbackVk *transformFeedbackVk = vk::GetImpl(glState.getCurrentTransformFeedback());
-    transformFeedbackVk->updateDescriptorSet(contextVk, mState,
-                                             mDescriptorSets[kUniformsAndXfbDescriptorSetIndex]);
-}
-
-angle::Result ProgramVk::updateTexturesDescriptorSet(ContextVk *contextVk)
-{
-    const vk::TextureDescriptorDesc &texturesDesc = contextVk->getActiveTexturesDesc();
-
-    auto iter = mTextureDescriptorsCache.find(texturesDesc);
-    if (iter != mTextureDescriptorsCache.end())
-    {
-        mDescriptorSets[kTextureDescriptorSetIndex] = iter->second;
-        return angle::Result::Continue;
-    }
-
-    ASSERT(hasTextures());
-    bool newPoolAllocated;
-    ANGLE_TRY(
-        allocateDescriptorSetAndGetInfo(contextVk, kTextureDescriptorSetIndex, &newPoolAllocated));
-
-    // Clear descriptor set cache. It may no longer be valid.
-    if (newPoolAllocated)
-    {
-        mTextureDescriptorsCache.clear();
-    }
-
-    VkDescriptorSet descriptorSet = mDescriptorSets[kTextureDescriptorSetIndex];
-
-    gl::ActiveTextureArray<VkDescriptorImageInfo> descriptorImageInfo;
-    gl::ActiveTextureArray<VkWriteDescriptorSet> writeDescriptorInfo;
-    uint32_t writeCount = 0;
-
-    const gl::ActiveTextureArray<vk::TextureUnit> &activeTextures = contextVk->getActiveTextures();
-
-    bool emulateSeamfulCubeMapSampling = contextVk->emulateSeamfulCubeMapSampling();
-    bool useOldRewriteStructSamplers   = contextVk->useOldRewriteStructSamplers();
-
-    std::unordered_map<std::string, uint32_t> mappedSamplerNameToBindingIndex;
-    std::unordered_map<std::string, uint32_t> mappedSamplerNameToArrayOffset;
-
-    uint32_t currentBindingIndex = 0;
-
-    for (uint32_t textureIndex = 0; textureIndex < mState.getSamplerBindings().size();
-         ++textureIndex)
-    {
-        const gl::SamplerBinding &samplerBinding = mState.getSamplerBindings()[textureIndex];
-
-        ASSERT(!samplerBinding.unreferenced);
-
-        uint32_t uniformIndex = mState.getUniformIndexFromSamplerIndex(textureIndex);
-        const gl::LinkedUniform &samplerUniform = mState.getUniforms()[uniformIndex];
-        std::string mappedSamplerName           = GlslangGetMappedSamplerName(samplerUniform.name);
-
-        if (useOldRewriteStructSamplers ||
-            mappedSamplerNameToBindingIndex.emplace(mappedSamplerName, currentBindingIndex).second)
-        {
-            currentBindingIndex++;
-        }
-
-        uint32_t bindingIndex = textureIndex;
-        uint32_t arrayOffset  = 0;
-        uint32_t arraySize    = static_cast<uint32_t>(samplerBinding.boundTextureUnits.size());
-
-        if (!useOldRewriteStructSamplers)
-        {
-            bindingIndex = mappedSamplerNameToBindingIndex[mappedSamplerName];
-            arrayOffset  = mappedSamplerNameToArrayOffset[mappedSamplerName];
-            // Front-end generates array elements in order, so we can just increment
-            // the offset each time we process a nested array.
-            mappedSamplerNameToArrayOffset[mappedSamplerName] += arraySize;
-        }
-
-        for (uint32_t arrayElement = 0; arrayElement < arraySize; ++arrayElement)
-        {
-            GLuint textureUnit   = samplerBinding.boundTextureUnits[arrayElement];
-            TextureVk *textureVk = activeTextures[textureUnit].texture;
-            SamplerVk *samplerVk = activeTextures[textureUnit].sampler;
-
-            vk::ImageHelper &image = textureVk->getImage();
-
-            VkDescriptorImageInfo &imageInfo = descriptorImageInfo[writeCount];
-
-            // Use bound sampler object if one present, otherwise use texture's sampler
-            const vk::Sampler &sampler =
-                (samplerVk != nullptr) ? samplerVk->getSampler() : textureVk->getSampler();
-
-            imageInfo.sampler     = sampler.getHandle();
-            imageInfo.imageLayout = image.getCurrentLayout();
-
-            if (emulateSeamfulCubeMapSampling)
-            {
-                // If emulating seamful cubemapping, use the fetch image view.  This is basically
-                // the same image view as read, except it's a 2DArray view for cube maps.
-                imageInfo.imageView =
-                    textureVk->getFetchImageViewAndRecordUse(contextVk).getHandle();
-            }
-            else
-            {
-                imageInfo.imageView =
-                    textureVk->getReadImageViewAndRecordUse(contextVk).getHandle();
-            }
-
-            VkWriteDescriptorSet &writeInfo = writeDescriptorInfo[writeCount];
-
-            writeInfo.sType            = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
-            writeInfo.pNext            = nullptr;
-            writeInfo.dstSet           = descriptorSet;
-            writeInfo.dstBinding       = bindingIndex;
-            writeInfo.dstArrayElement  = arrayOffset + arrayElement;
-            writeInfo.descriptorCount  = 1;
-            writeInfo.descriptorType   = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
-            writeInfo.pImageInfo       = &imageInfo;
-            writeInfo.pBufferInfo      = nullptr;
-            writeInfo.pTexelBufferView = nullptr;
-
-            ++writeCount;
-        }
-    }
-
-    VkDevice device = contextVk->getDevice();
-
-    ASSERT(writeCount > 0);
-
-    vkUpdateDescriptorSets(device, writeCount, writeDescriptorInfo.data(), 0, nullptr);
-
-    mTextureDescriptorsCache.emplace(texturesDesc, descriptorSet);
-
     return angle::Result::Continue;
 }
 
@@ -1757,75 +792,4 @@
     }
 }
 
-angle::Result ProgramVk::updateDescriptorSets(ContextVk *contextVk,
-                                              vk::CommandBuffer *commandBuffer)
-{
-    // Can probably use better dirty bits here.
-
-    if (mDescriptorSets.empty())
-        return angle::Result::Continue;
-
-    // Find the maximum non-null descriptor set.  This is used in conjunction with a driver
-    // workaround to bind empty descriptor sets only for gaps in between 0 and max and avoid
-    // binding unnecessary empty descriptor sets for the sets beyond max.
-    const size_t descriptorSetStart = kUniformsAndXfbDescriptorSetIndex;
-    size_t descriptorSetRange       = 0;
-    for (size_t descriptorSetIndex = descriptorSetStart;
-         descriptorSetIndex < mDescriptorSets.size(); ++descriptorSetIndex)
-    {
-        if (mDescriptorSets[descriptorSetIndex] != VK_NULL_HANDLE)
-        {
-            descriptorSetRange = descriptorSetIndex + 1;
-        }
-    }
-
-    const VkPipelineBindPoint pipelineBindPoint =
-        mState.isCompute() ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS;
-
-    for (uint32_t descriptorSetIndex = descriptorSetStart; descriptorSetIndex < descriptorSetRange;
-         ++descriptorSetIndex)
-    {
-        VkDescriptorSet descSet = mDescriptorSets[descriptorSetIndex];
-        if (descSet == VK_NULL_HANDLE)
-        {
-            if (!contextVk->getRenderer()->getFeatures().bindEmptyForUnusedDescriptorSets.enabled)
-            {
-                continue;
-            }
-
-            // Workaround a driver bug where missing (though unused) descriptor sets indices cause
-            // later sets to misbehave.
-            if (mEmptyDescriptorSets[descriptorSetIndex] == VK_NULL_HANDLE)
-            {
-                const vk::DescriptorSetLayout &descriptorSetLayout =
-                    mDescriptorSetLayouts[descriptorSetIndex].get();
-
-                ANGLE_TRY(mDynamicDescriptorPools[descriptorSetIndex].allocateSets(
-                    contextVk, descriptorSetLayout.ptr(), 1,
-                    &mDescriptorPoolBindings[descriptorSetIndex],
-                    &mEmptyDescriptorSets[descriptorSetIndex]));
-            }
-            descSet = mEmptyDescriptorSets[descriptorSetIndex];
-        }
-
-        // Default uniforms are encompassed in a block per shader stage, and they are assigned
-        // through dynamic uniform buffers (requiring dynamic offsets).  No other descriptor
-        // requires a dynamic offset.
-        const uint32_t uniformBlockOffsetCount =
-            descriptorSetIndex == kUniformsAndXfbDescriptorSetIndex
-                ? static_cast<uint32_t>(mDynamicBufferOffsets.size())
-                : 0;
-
-        commandBuffer->bindDescriptorSets(mPipelineLayout.get(), pipelineBindPoint,
-                                          descriptorSetIndex, 1, &descSet, uniformBlockOffsetCount,
-                                          mDynamicBufferOffsets.data());
-    }
-
-    for (vk::BufferHelper *buffer : mDescriptorBuffersCache)
-    {
-        buffer->retain(&contextVk->getResourceUseList());
-    }
-
-    return angle::Result::Continue;
-}
 }  // namespace rx
diff --git a/src/libANGLE/renderer/vulkan/ProgramVk.h b/src/libANGLE/renderer/vulkan/ProgramVk.h
index 51a08ef..117138f 100644
--- a/src/libANGLE/renderer/vulkan/ProgramVk.h
+++ b/src/libANGLE/renderer/vulkan/ProgramVk.h
@@ -16,6 +16,7 @@
 #include "libANGLE/renderer/ProgramImpl.h"
 #include "libANGLE/renderer/glslang_wrapper_utils.h"
 #include "libANGLE/renderer/vulkan/ContextVk.h"
+#include "libANGLE/renderer/vulkan/ProgramExecutableVk.h"
 #include "libANGLE/renderer/vulkan/RendererVk.h"
 #include "libANGLE/renderer/vulkan/TransformFeedbackVk.h"
 #include "libANGLE/renderer/vulkan/vk_helpers.h"
@@ -41,6 +42,8 @@
     void setBinaryRetrievableHint(bool retrievable) override;
     void setSeparable(bool separable) override;
 
+    void fillProgramStateMap(gl::ShaderMap<const gl::ProgramState *> *programStatesOut);
+
     std::unique_ptr<LinkEvent> link(const gl::Context *context,
                                     const gl::ProgramLinkedResources &resources,
                                     gl::InfoLog &infoLog) override;
@@ -99,71 +102,47 @@
     void getUniformiv(const gl::Context *context, GLint location, GLint *params) const override;
     void getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const override;
 
-    void setPathFragmentInputGen(const std::string &inputName,
-                                 GLenum genMode,
-                                 GLint components,
-                                 const GLfloat *coeffs) override;
-
-    // Also initializes the pipeline layout, descriptor set layouts, and used descriptor ranges.
-
+    angle::Result updateShaderUniforms(ContextVk *contextVk,
+                                       gl::ShaderType shaderType,
+                                       uint32_t *outOffset,
+                                       bool *anyNewBufferAllocated);
     angle::Result updateUniforms(ContextVk *contextVk);
-    angle::Result updateTexturesDescriptorSet(ContextVk *contextVk);
-    angle::Result updateShaderResourcesDescriptorSet(ContextVk *contextVk,
-                                                     vk::ResourceUseList *resourceUseList,
-                                                     CommandBufferHelper *commandBufferHelper);
-    angle::Result updateTransformFeedbackDescriptorSet(ContextVk *contextVk);
-
-    angle::Result updateDescriptorSets(ContextVk *contextVk, vk::CommandBuffer *commandBuffer);
 
     // For testing only.
     void setDefaultUniformBlocksMinSizeForTesting(size_t minSize);
 
-    const vk::PipelineLayout &getPipelineLayout() const { return mPipelineLayout.get(); }
-
-    bool hasDefaultUniforms() const { return !mState.getDefaultUniformRange().empty(); }
-    bool hasTextures() const { return !mState.getSamplerBindings().empty(); }
-    bool hasUniformBuffers() const { return !mState.getUniformBlocks().empty(); }
-    bool hasStorageBuffers() const { return !mState.getShaderStorageBlocks().empty(); }
-    bool hasAtomicCounterBuffers() const { return !mState.getAtomicCounterBuffers().empty(); }
-    bool hasImages() const { return !mState.getImageBindings().empty(); }
-    bool hasTransformFeedbackOutput() const
-    {
-        return !mState.getLinkedTransformFeedbackVaryings().empty();
-    }
-
     bool dirtyUniforms() const { return mDefaultUniformBlocksDirty.any(); }
 
-    angle::Result getGraphicsPipeline(ContextVk *contextVk,
-                                      gl::PrimitiveMode mode,
-                                      const vk::GraphicsPipelineDesc &desc,
-                                      const gl::AttributesMask &activeAttribLocations,
-                                      const vk::GraphicsPipelineDesc **descPtrOut,
-                                      vk::PipelineHelper **pipelineOut)
-    {
-        vk::ShaderProgramHelper *shaderProgram;
-        ANGLE_TRY(initGraphicsProgram(contextVk, mode, &shaderProgram));
-        ASSERT(shaderProgram->isGraphicsProgram());
-        RendererVk *renderer             = contextVk->getRenderer();
-        vk::PipelineCache *pipelineCache = nullptr;
-        ANGLE_TRY(renderer->getPipelineCache(&pipelineCache));
-        return shaderProgram->getGraphicsPipeline(
-            contextVk, &contextVk->getRenderPassCache(), *pipelineCache,
-            contextVk->getCurrentQueueSerial(), mPipelineLayout.get(), desc, activeAttribLocations,
-            mState.getAttributesTypeMask(), descPtrOut, pipelineOut);
-    }
-
-    angle::Result getComputePipeline(ContextVk *contextVk, vk::PipelineAndSerial **pipelineOut)
-    {
-        vk::ShaderProgramHelper *shaderProgram;
-        ANGLE_TRY(initComputeProgram(contextVk, &shaderProgram));
-        ASSERT(!shaderProgram->isGraphicsProgram());
-        return shaderProgram->getComputePipeline(contextVk, mPipelineLayout.get(), pipelineOut);
-    }
-
     // Used in testing only.
     vk::DynamicDescriptorPool *getDynamicDescriptorPool(uint32_t poolIndex)
     {
-        return &mDynamicDescriptorPools[poolIndex];
+        return &mExecutable.mDynamicDescriptorPools[poolIndex];
+    }
+
+    const ProgramExecutableVk &getExecutable() const { return mExecutable; }
+    ProgramExecutableVk &getExecutable() { return mExecutable; }
+
+    gl::ShaderMap<DefaultUniformBlock> &getDefaultUniformBlocks() { return mDefaultUniformBlocks; }
+
+    ANGLE_INLINE angle::Result initGraphicsShaderProgram(ContextVk *contextVk,
+                                                         const gl::ShaderType shaderType,
+                                                         ProgramTransformOptionBits optionBits,
+                                                         ProgramInfo &programInfo)
+    {
+        return initProgram(contextVk, shaderType, optionBits, &programInfo);
+    }
+
+    ANGLE_INLINE angle::Result initComputeProgram(ContextVk *contextVk, ProgramInfo &programInfo)
+    {
+        ProgramTransformOptionBits optionBits;
+        return initProgram(contextVk, gl::ShaderType::Compute, optionBits, &programInfo);
+    }
+
+    ShaderInfo &getShaderInfo() { return mShaderInfo; }
+
+    GlslangProgramInterfaceInfo &getGlslangProgramInterfaceInfo()
+    {
+        return mGlslangProgramInterfaceInfo;
     }
 
   private:
@@ -174,10 +153,6 @@
                             const GLfloat *value);
 
     void reset(ContextVk *contextVk);
-    angle::Result allocateDescriptorSet(ContextVk *contextVk, uint32_t descriptorSetIndex);
-    angle::Result allocateDescriptorSetAndGetInfo(ContextVk *contextVk,
-                                                  uint32_t descriptorSetIndex,
-                                                  bool *newPoolAllocatedOut);
     angle::Result initDefaultUniformBlocks(const gl::Context *glContext);
     void generateUniformLayoutMapping(gl::ShaderMap<sh::BlockLayoutMap> &layoutMap,
                                       gl::ShaderMap<size_t> &requiredBufferSize);
@@ -185,18 +160,6 @@
     angle::Result resizeUniformBlockMemory(ContextVk *contextVk,
                                            gl::ShaderMap<size_t> &requiredBufferSize);
 
-    void updateDefaultUniformsDescriptorSet(ContextVk *contextVk);
-    void updateTransformFeedbackDescriptorSetImpl(ContextVk *contextVk);
-    void updateBuffersDescriptorSet(ContextVk *contextVk,
-                                    vk::ResourceUseList *resourceUseList,
-                                    CommandBufferHelper *commandBufferHelper,
-                                    const std::vector<gl::InterfaceBlock> &blocks,
-                                    VkDescriptorType descriptorType);
-    void updateAtomicCounterBuffersDescriptorSet(ContextVk *contextVk,
-                                                 vk::ResourceUseList *resourceUseList,
-                                                 CommandBufferHelper *commandBufferHelper);
-    angle::Result updateImagesDescriptorSet(ContextVk *contextVk);
-
     template <class T>
     void getUniformImpl(GLint location, T *v, GLenum entryPointType) const;
 
@@ -205,158 +168,34 @@
     angle::Result linkImpl(const gl::Context *glContext, gl::InfoLog &infoLog);
     void linkResources(const gl::ProgramLinkedResources &resources);
 
-    void updateBindingOffsets();
-    uint32_t getUniformBlockBindingsOffset() const { return 0; }
-    uint32_t getStorageBlockBindingsOffset() const { return mStorageBlockBindingsOffset; }
-    uint32_t getAtomicCounterBufferBindingsOffset() const
-    {
-        return mAtomicCounterBufferBindingsOffset;
-    }
-    uint32_t getImageBindingsOffset() const { return mImageBindingsOffset; }
-
-    class ProgramInfo;
     ANGLE_INLINE angle::Result initProgram(ContextVk *contextVk,
-                                           bool enableLineRasterEmulation,
-                                           ProgramInfo *programInfo,
-                                           vk::ShaderProgramHelper **shaderProgramOut)
+                                           const gl::ShaderType shaderType,
+                                           ProgramTransformOptionBits optionBits,
+                                           ProgramInfo *programInfo)
     {
         ASSERT(mShaderInfo.valid());
 
         // Create the program pipeline.  This is done lazily and once per combination of
         // specialization constants.
-        if (!programInfo->valid())
+        if (!programInfo->valid(shaderType))
         {
-            ANGLE_TRY(programInfo->initProgram(contextVk, mShaderInfo, enableLineRasterEmulation));
+            ANGLE_TRY(programInfo->initProgram(contextVk, shaderType, mShaderInfo,
+                                               mExecutable.mVariableInfoMap, optionBits));
         }
-        ASSERT(programInfo->valid());
+        ASSERT(programInfo->valid(shaderType));
 
-        *shaderProgramOut = programInfo->getShaderProgram();
         return angle::Result::Continue;
     }
 
-    ANGLE_INLINE angle::Result initGraphicsProgram(ContextVk *contextVk,
-                                                   gl::PrimitiveMode mode,
-                                                   vk::ShaderProgramHelper **shaderProgramOut)
-    {
-        bool enableLineRasterEmulation = UseLineRaster(contextVk, mode);
-
-        ProgramInfo &programInfo =
-            enableLineRasterEmulation ? mLineRasterProgramInfo : mDefaultProgramInfo;
-
-        return initProgram(contextVk, enableLineRasterEmulation, &programInfo, shaderProgramOut);
-    }
-
-    ANGLE_INLINE angle::Result initComputeProgram(ContextVk *contextVk,
-                                                  vk::ShaderProgramHelper **shaderProgramOut)
-    {
-        return initProgram(contextVk, false, &mDefaultProgramInfo, shaderProgramOut);
-    }
-
-    // State for the default uniform blocks.
-    struct DefaultUniformBlock final : private angle::NonCopyable
-    {
-        DefaultUniformBlock();
-        ~DefaultUniformBlock();
-
-        vk::DynamicBuffer storage;
-
-        // Shadow copies of the shader uniform data.
-        angle::MemoryBuffer uniformData;
-
-        // Since the default blocks are laid out in std140, this tells us where to write on a call
-        // to a setUniform method. They are arranged in uniform location order.
-        std::vector<sh::BlockMemberInfo> uniformLayout;
-    };
-
     gl::ShaderMap<DefaultUniformBlock> mDefaultUniformBlocks;
     gl::ShaderBitSet mDefaultUniformBlocksDirty;
 
-    gl::ShaderVector<uint32_t> mDynamicBufferOffsets;
-
-    // This is a special "empty" placeholder buffer for when a shader has no uniforms or doesn't
-    // use all slots in the atomic counter buffer array.
-    //
-    // It is necessary because we want to keep a compatible pipeline layout in all cases,
-    // and Vulkan does not tolerate having null handles in a descriptor set.
-    vk::BufferHelper mEmptyBuffer;
-
-    // Descriptor sets for uniform blocks and textures for this program.
-    std::vector<VkDescriptorSet> mDescriptorSets;
-    vk::DescriptorSetLayoutArray<VkDescriptorSet> mEmptyDescriptorSets;
-    std::vector<vk::BufferHelper *> mDescriptorBuffersCache;
-
-    std::unordered_map<vk::TextureDescriptorDesc, VkDescriptorSet> mTextureDescriptorsCache;
-
-    // We keep a reference to the pipeline and descriptor set layouts. This ensures they don't get
-    // deleted while this program is in use.
-    vk::BindingPointer<vk::PipelineLayout> mPipelineLayout;
-    vk::DescriptorSetLayoutPointerArray mDescriptorSetLayouts;
-
-    // Keep bindings to the descriptor pools. This ensures the pools stay valid while the Program
-    // is in use.
-    vk::DescriptorSetLayoutArray<vk::RefCountedDescriptorPoolBinding> mDescriptorPoolBindings;
-
-    class ShaderInfo final : angle::NonCopyable
-    {
-      public:
-        ShaderInfo();
-        ~ShaderInfo();
-
-        angle::Result initShaders(ContextVk *contextVk,
-                                  const gl::ShaderMap<std::string> &shaderSources,
-                                  const ShaderInterfaceVariableInfoMap &variableInfoMap);
-        void release(ContextVk *contextVk);
-
-        ANGLE_INLINE bool valid() const { return mIsInitialized; }
-
-        const gl::ShaderMap<SpirvBlob> &getSpirvBlobs() const { return mSpirvBlobs; }
-
-        // Save and load implementation for GLES Program Binary support.
-        void load(gl::BinaryInputStream *stream);
-        void save(gl::BinaryOutputStream *stream);
-
-      private:
-        gl::ShaderMap<SpirvBlob> mSpirvBlobs;
-        bool mIsInitialized = false;
-    };
-
-    class ProgramInfo final : angle::NonCopyable
-    {
-      public:
-        ProgramInfo();
-        ~ProgramInfo();
-
-        angle::Result initProgram(ContextVk *contextVk,
-                                  const ShaderInfo &shaderInfo,
-                                  bool enableLineRasterEmulation);
-        void release(ContextVk *contextVk);
-
-        ANGLE_INLINE bool valid() const { return mProgramHelper.valid(); }
-
-        vk::ShaderProgramHelper *getShaderProgram() { return &mProgramHelper; }
-
-      private:
-        vk::ShaderProgramHelper mProgramHelper;
-        gl::ShaderMap<vk::RefCounted<vk::ShaderAndSerial>> mShaders;
-    };
-
-    ProgramInfo mDefaultProgramInfo;
-    ProgramInfo mLineRasterProgramInfo;
-
     // We keep the SPIR-V code to use for draw call pipeline creation.
     ShaderInfo mShaderInfo;
 
-    // In their descriptor set, uniform buffers are placed first, then storage buffers, then atomic
-    // counter buffers and then images.  These cached values contain the offsets where storage
-    // buffer, atomic counter buffer and image bindings start.
-    uint32_t mStorageBlockBindingsOffset;
-    uint32_t mAtomicCounterBufferBindingsOffset;
-    uint32_t mImageBindingsOffset;
+    GlslangProgramInterfaceInfo mGlslangProgramInterfaceInfo;
 
-    // Store descriptor pools here. We store the descriptors in the Program to facilitate descriptor
-    // cache management. It can also allow fewer descriptors for shaders which use fewer
-    // textures/buffers.
-    vk::DescriptorSetLayoutArray<vk::DynamicDescriptorPool> mDynamicDescriptorPools;
+    ProgramExecutableVk mExecutable;
 };
 
 }  // namespace rx
diff --git a/src/libANGLE/renderer/vulkan/QueryVk.cpp b/src/libANGLE/renderer/vulkan/QueryVk.cpp
index c2e47a8..2f01ebc 100644
--- a/src/libANGLE/renderer/vulkan/QueryVk.cpp
+++ b/src/libANGLE/renderer/vulkan/QueryVk.cpp
@@ -39,6 +39,29 @@
     }
 }
 
+angle::Result QueryVk::stashQueryHelper(ContextVk *contextVk)
+{
+    ASSERT(isOcclusionQuery());
+    mStashedQueryHelpers.emplace_back(mQueryHelper);
+    mQueryHelper.deinit();
+    ANGLE_TRY(contextVk->getQueryPool(getType())->allocateQuery(contextVk, &mQueryHelper));
+    return angle::Result::Continue;
+}
+
+angle::Result QueryVk::retrieveStashedQueryResult(ContextVk *contextVk, uint64_t *result)
+{
+    uint64_t total = 0;
+    for (vk::QueryHelper &query : mStashedQueryHelpers)
+    {
+        uint64_t v;
+        ANGLE_TRY(query.getUint64Result(contextVk, &v));
+        total += v;
+    }
+    mStashedQueryHelpers.clear();
+    *result = total;
+    return angle::Result::Continue;
+}
+
 angle::Result QueryVk::begin(const gl::Context *context)
 {
     ContextVk *contextVk = vk::GetImpl(context);
@@ -58,9 +81,25 @@
         ANGLE_TRY(contextVk->getQueryPool(getType())->allocateQuery(contextVk, &mQueryHelper));
     }
 
-    // Note: TimeElapsed is implemented by using two Timestamp queries and taking the diff.
-    if (getType() == gl::QueryType::TimeElapsed)
+    if (isOcclusionQuery())
     {
+        // For pathological usage case where begin/end is called back to back without flush and get
+        // result, we have to force flush so that the same mQueryHelper will not encoded in the same
+        // renderpass twice without resetting it.
+        if (mQueryHelper.hasPendingWork(contextVk))
+        {
+            ANGLE_TRY(contextVk->flushImpl(nullptr));
+            // As soon as beginQuery is called, previous query's result will not retrievable by API.
+            // We must clear it so that it will not count against current beginQuery call.
+            mStashedQueryHelpers.clear();
+            mQueryHelper.deinit();
+            ANGLE_TRY(contextVk->getQueryPool(getType())->allocateQuery(contextVk, &mQueryHelper));
+        }
+        contextVk->beginOcclusionQuery(this);
+    }
+    else if (getType() == gl::QueryType::TimeElapsed)
+    {
+        // Note: TimeElapsed is implemented by using two Timestamp queries and taking the diff.
         if (!mQueryHelperTimeElapsedBegin.valid())
         {
             ANGLE_TRY(contextVk->getQueryPool(getType())->allocateQuery(
@@ -96,6 +135,10 @@
         mCachedResultValid = true;
         // We could consider using VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT.
     }
+    else if (isOcclusionQuery())
+    {
+        contextVk->endOcclusionQuery(this);
+    }
     else if (getType() == gl::QueryType::TimeElapsed)
     {
         ANGLE_TRY(mQueryHelper.flushAndWriteTimestamp(contextVk));
@@ -110,6 +153,7 @@
 
 angle::Result QueryVk::queryCounter(const gl::Context *context)
 {
+    ASSERT(getType() == gl::QueryType::Timestamp);
     ContextVk *contextVk = vk::GetImpl(context);
 
     mCachedResultValid = false;
@@ -119,8 +163,6 @@
         ANGLE_TRY(contextVk->getQueryPool(getType())->allocateQuery(contextVk, &mQueryHelper));
     }
 
-    ASSERT(getType() == gl::QueryType::Timestamp);
-
     return mQueryHelper.flushAndWriteTimestamp(contextVk);
 }
 
@@ -162,6 +204,9 @@
     if (wait)
     {
         ANGLE_TRY(mQueryHelper.getUint64Result(contextVk, &mCachedResult));
+        uint64_t v;
+        ANGLE_TRY(retrieveStashedQueryResult(contextVk, &v));
+        mCachedResult += v;
     }
     else
     {
@@ -172,6 +217,9 @@
             // If the results are not ready, do nothing.  mCachedResultValid remains false.
             return angle::Result::Continue;
         }
+        uint64_t v;
+        ANGLE_TRY(retrieveStashedQueryResult(contextVk, &v));
+        mCachedResult += v;
     }
 
     double timestampPeriod = renderer->getPhysicalDeviceProperties().limits.timestampPeriod;
diff --git a/src/libANGLE/renderer/vulkan/QueryVk.h b/src/libANGLE/renderer/vulkan/QueryVk.h
index bca6682..c6a01b5 100644
--- a/src/libANGLE/renderer/vulkan/QueryVk.h
+++ b/src/libANGLE/renderer/vulkan/QueryVk.h
@@ -35,12 +35,17 @@
     angle::Result isResultAvailable(const gl::Context *context, bool *available) override;
 
     void onTransformFeedbackEnd(const gl::Context *context);
+    vk::QueryHelper *getQueryHelper() { return &mQueryHelper; }
+    angle::Result stashQueryHelper(ContextVk *contextVk);
+    angle::Result retrieveStashedQueryResult(ContextVk *contextVk, uint64_t *result);
 
   private:
     angle::Result getResult(const gl::Context *context, bool wait);
 
     // Used for AnySamples, AnySamplesConservative, Timestamp and TimeElapsed (end).
     vk::QueryHelper mQueryHelper;
+    // Used for occlusion query that we may end up with multiple outstanding query helper objects.
+    std::vector<vk::QueryHelper> mStashedQueryHelpers;
     // An additional query used for TimeElapsed (begin), as it is implemented using Timestamp.
     vk::QueryHelper mQueryHelperTimeElapsedBegin;
     // Used with TransformFeedbackPrimitivesWritten when transform feedback is emulated.
diff --git a/src/libANGLE/renderer/vulkan/RenderTargetVk.cpp b/src/libANGLE/renderer/vulkan/RenderTargetVk.cpp
index da6adec..d10bed7 100644
--- a/src/libANGLE/renderer/vulkan/RenderTargetVk.cpp
+++ b/src/libANGLE/renderer/vulkan/RenderTargetVk.cpp
@@ -17,9 +17,11 @@
 
 namespace rx
 {
+
 RenderTargetVk::RenderTargetVk()
-    : mImage(nullptr), mImageViews(nullptr), mLevelIndex(0), mLayerIndex(0)
-{}
+{
+    reset();
+}
 
 RenderTargetVk::~RenderTargetVk() {}
 
@@ -27,12 +29,10 @@
     : mImage(other.mImage),
       mImageViews(other.mImageViews),
       mLevelIndex(other.mLevelIndex),
-      mLayerIndex(other.mLayerIndex)
+      mLayerIndex(other.mLayerIndex),
+      mContentDefined(other.mContentDefined)
 {
-    other.mImage      = nullptr;
-    other.mImageViews = nullptr;
-    other.mLevelIndex = 0;
-    other.mLayerIndex = 0;
+    other.reset();
 }
 
 void RenderTargetVk::init(vk::ImageHelper *image,
@@ -44,14 +44,18 @@
     mImageViews = imageViews;
     mLevelIndex = levelIndex;
     mLayerIndex = layerIndex;
+    // We are being conservative here since our targeted optimization is to skip surfaceVK's depth
+    // buffer load after swap call.
+    mContentDefined = true;
 }
 
 void RenderTargetVk::reset()
 {
-    mImage      = nullptr;
-    mImageViews = nullptr;
-    mLevelIndex = 0;
-    mLayerIndex = 0;
+    mImage          = nullptr;
+    mImageViews     = nullptr;
+    mLevelIndex     = 0;
+    mLayerIndex     = 0;
+    mContentDefined = false;
 }
 
 vk::AttachmentSerial RenderTargetVk::getAssignSerial(ContextVk *contextVk)
@@ -74,6 +78,7 @@
 
     contextVk->onRenderPassImageWrite(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::ColorAttachment,
                                       mImage);
+    mContentDefined = true;
     retainImageViews(contextVk);
 
     return angle::Result::Continue;
@@ -87,6 +92,7 @@
     VkImageAspectFlags aspectFlags = vk::GetDepthStencilAspectFlags(format);
 
     contextVk->onRenderPassImageWrite(aspectFlags, vk::ImageLayout::DepthStencilAttachment, mImage);
+    mContentDefined = true;
     retainImageViews(contextVk);
 
     return angle::Result::Continue;
diff --git a/src/libANGLE/renderer/vulkan/RenderTargetVk.h b/src/libANGLE/renderer/vulkan/RenderTargetVk.h
index 13b722a..6ead767 100644
--- a/src/libANGLE/renderer/vulkan/RenderTargetVk.h
+++ b/src/libANGLE/renderer/vulkan/RenderTargetVk.h
@@ -77,11 +77,18 @@
 
     void retainImageViews(ContextVk *contextVk) const;
 
+    bool hasDefinedContent() const { return mContentDefined; }
+    // mark content as undefined so that certain optimizations are possible
+    void invalidateContent() { mContentDefined = false; }
+
   private:
     vk::ImageHelper *mImage;
     vk::ImageViewHelper *mImageViews;
     uint32_t mLevelIndex;
     uint32_t mLayerIndex;
+    // Right now we are only tracking depth/stencil buffer. We could expand it to cover color
+    // buffers if needed in future.
+    bool mContentDefined;
 };
 
 // A vector of rendertargets
diff --git a/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp b/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp
index 7cab272..97b673e 100644
--- a/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp
+++ b/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp
@@ -78,9 +78,6 @@
         VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
         ANGLE_TRY(mImage->initMemory(contextVk, renderer->getMemoryProperties(), flags));
 
-        // Clear the renderbuffer if it has emulated channels.
-        mImage->stageClearIfEmulatedFormat(gl::ImageIndex::Make2D(0), vkFormat);
-
         mRenderTarget.init(mImage, &mImageViews, 0, 0);
     }
 
@@ -160,7 +157,7 @@
                                                  const gl::ImageIndex &imageIndex)
 {
     // Note: stageSubresourceRobustClear only uses the intended format to count channels.
-    mImage->stageSubresourceRobustClear(imageIndex, mImage->getFormat());
+    mImage->stageSubresourceClear(imageIndex);
     return mImage->flushAllStagedUpdates(vk::GetImpl(context));
 }
 
diff --git a/src/libANGLE/renderer/vulkan/RendererVk.cpp b/src/libANGLE/renderer/vulkan/RendererVk.cpp
index 1149702..dc4144d 100644
--- a/src/libANGLE/renderer/vulkan/RendererVk.cpp
+++ b/src/libANGLE/renderer/vulkan/RendererVk.cpp
@@ -123,9 +123,24 @@
     "VUID-vkDestroySemaphore-semaphore-parameter",
     // http://anglebug.com/4063
     "VUID-VkDeviceCreateInfo-pNext-pNext",
-    "VUID-VkPipelineRasterizationStateCreateInfo-pNext-pNext", "VUID_Undefined",
+    "VUID-VkPipelineRasterizationStateCreateInfo-pNext-pNext",
+    "VUID_Undefined",
     // http://anglebug.com/3078
-    "UNASSIGNED-CoreValidation-Shader-InterfaceTypeMismatch"};
+    "UNASSIGNED-CoreValidation-Shader-InterfaceTypeMismatch",
+    // http://anglebug.com/4510
+    "VUID-vkQueuePresentKHR-pWaitSemaphores-03268",
+    // http://anglebug.com/4572
+    "VUID-vkCmdCopyImageToBuffer-srcImage-01998",
+    // http://anglebug.com/4577
+    "VUID-vkCmdClearColorImage-image-01993",
+    // http://anglebug.com/4578 for next two
+    "VUID-vkCmdBlitImage-srcImage-01999",
+    "VUID-vkCmdBlitImage-filter-02001",
+    // http://anglebug.com/4579
+    "VUID-vkCmdBlitImage-dstImage-02000",
+    // http://anglebug.com/4580
+    "VUID-vkCmdResolveImage-dstImage-02003",
+};
 
 // Suppress validation errors that are known
 //  return "true" if given code/prefix/message is known, else return "false"
@@ -215,9 +230,7 @@
             return "Display Mode";
         case VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT:
             return "Debug Report Callback";
-        case VK_OBJECT_TYPE_OBJECT_TABLE_NVX:
-            return "Object Table";
-        case VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX:
+        case VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NV:
             return "Indirect Commands Layout";
         case VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT:
             return "Debug Utils Messenger";
@@ -590,7 +603,7 @@
     ASSERT(mSharedGarbage.empty());
 }
 
-void RendererVk::onDestroy(vk::Context *context)
+void RendererVk::onDestroy()
 {
     // Force all commands to finish by flushing all queues.
     for (VkQueue queue : mQueues)
@@ -603,7 +616,7 @@
 
     // Then assign an infinite "last completed" serial to force garbage to delete.
     mLastCompletedQueueSerial = Serial::Infinite();
-    (void)cleanupGarbage(context, true);
+    (void)cleanupGarbage(true);
     ASSERT(mSharedGarbage.empty());
 
     for (PendingOneOffCommands &pending : mPendingOneOffCommands)
@@ -620,6 +633,8 @@
 
     mPipelineCache.destroy(mDevice);
 
+    vma::DestroyAllocator(mAllocator);
+
     if (mGlslangInitialized)
     {
         GlslangRelease();
@@ -765,7 +780,7 @@
     if (ExtensionFound(VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME, instanceExtensionNames))
     {
         enabledInstanceExtensions.push_back(VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME);
-        ANGLE_FEATURE_CONDITION((&mFeatures), supportsSwapchainColorspace, true);
+        ANGLE_FEATURE_CONDITION(&mFeatures, supportsSwapchainColorspace, true);
     }
 
     // Verify the required extensions are in the extension names set. Fail if not.
@@ -922,6 +937,9 @@
         ANGLE_TRY(initializeDevice(displayVk, firstGraphicsQueueFamily));
     }
 
+    // Create VMA allocator
+    ANGLE_VK_TRY(displayVk, vma::InitAllocator(mPhysicalDevice, mDevice, mInstance, &mAllocator));
+
     // Store the physical device memory properties so we can find the right memory pools.
     mMemoryProperties.init(mPhysicalDevice);
 
@@ -1534,6 +1552,7 @@
     bool isIntel    = IsIntel(mPhysicalDeviceProperties.vendorID);
     bool isNvidia   = IsNvidia(mPhysicalDeviceProperties.vendorID);
     bool isQualcomm = IsQualcomm(mPhysicalDeviceProperties.vendorID);
+    bool isARM      = IsARM(mPhysicalDeviceProperties.vendorID);
     bool isSwS =
         IsSwiftshader(mPhysicalDeviceProperties.vendorID, mPhysicalDeviceProperties.deviceID);
 
@@ -1541,35 +1560,35 @@
     {
         ASSERT(mLineRasterizationFeatures.sType ==
                VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT);
-        ANGLE_FEATURE_CONDITION((&mFeatures), bresenhamLineRasterization, true);
+        ANGLE_FEATURE_CONDITION(&mFeatures, bresenhamLineRasterization, true);
     }
     else
     {
         // Use OpenGL line rasterization rules if extension not available by default.
         // TODO(jmadill): Fix Android support. http://anglebug.com/2830
-        ANGLE_FEATURE_CONDITION((&mFeatures), basicGLLineRasterization, !IsAndroid());
+        ANGLE_FEATURE_CONDITION(&mFeatures, basicGLLineRasterization, !IsAndroid());
     }
 
     if (mProvokingVertexFeatures.provokingVertexLast == VK_TRUE)
     {
         ASSERT(mProvokingVertexFeatures.sType ==
                VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT);
-        ANGLE_FEATURE_CONDITION((&mFeatures), provokingVertex, true);
+        ANGLE_FEATURE_CONDITION(&mFeatures, provokingVertex, true);
     }
 
     // TODO(lucferron): Currently disabled on Intel only since many tests are failing and need
     // investigation. http://anglebug.com/2728
     ANGLE_FEATURE_CONDITION(
-        (&mFeatures), flipViewportY,
+        &mFeatures, flipViewportY,
         !IsIntel(mPhysicalDeviceProperties.vendorID) &&
                 (mPhysicalDeviceProperties.apiVersion >= VK_MAKE_VERSION(1, 1, 0)) ||
             ExtensionFound(VK_KHR_MAINTENANCE1_EXTENSION_NAME, deviceExtensionNames));
 
     // http://anglebug.com/2838
-    ANGLE_FEATURE_CONDITION((&mFeatures), extraCopyBufferRegion, IsWindows() && isIntel);
+    ANGLE_FEATURE_CONDITION(&mFeatures, extraCopyBufferRegion, IsWindows() && isIntel);
 
     // http://anglebug.com/3055
-    ANGLE_FEATURE_CONDITION((&mFeatures), forceCPUPathForCubeMapCopy, IsWindows() && isIntel);
+    ANGLE_FEATURE_CONDITION(&mFeatures, forceCPUPathForCubeMapCopy, IsWindows() && isIntel);
 
     // Work around incorrect NVIDIA point size range clamping.
     // http://anglebug.com/2970#c10
@@ -1582,23 +1601,23 @@
         nvidiaVersion =
             angle::ParseNvidiaDriverVersion(this->mPhysicalDeviceProperties.driverVersion);
     }
-    ANGLE_FEATURE_CONDITION((&mFeatures), clampPointSize,
+    ANGLE_FEATURE_CONDITION(&mFeatures, clampPointSize,
                             isNvidia && nvidiaVersion.major < uint32_t(IsWindows() ? 430 : 421));
 
     // Work around ineffective compute-graphics barriers on Nexus 5X.
     // TODO(syoussefi): Figure out which other vendors and driver versions are affected.
     // http://anglebug.com/3019
-    ANGLE_FEATURE_CONDITION((&mFeatures), flushAfterVertexConversion,
+    ANGLE_FEATURE_CONDITION(&mFeatures, flushAfterVertexConversion,
                             IsAndroid() && IsNexus5X(mPhysicalDeviceProperties.vendorID,
                                                      mPhysicalDeviceProperties.deviceID));
 
     ANGLE_FEATURE_CONDITION(
-        (&mFeatures), supportsIncrementalPresent,
+        &mFeatures, supportsIncrementalPresent,
         ExtensionFound(VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME, deviceExtensionNames));
 
 #if defined(ANGLE_PLATFORM_ANDROID)
     ANGLE_FEATURE_CONDITION(
-        (&mFeatures), supportsAndroidHardwareBuffer,
+        &mFeatures, supportsAndroidHardwareBuffer,
         IsAndroid() &&
             ExtensionFound(VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME,
                            deviceExtensionNames) &&
@@ -1606,73 +1625,76 @@
 #endif
 
     ANGLE_FEATURE_CONDITION(
-        (&mFeatures), supportsExternalMemoryFd,
+        &mFeatures, supportsExternalMemoryFd,
         ExtensionFound(VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, deviceExtensionNames));
 
     ANGLE_FEATURE_CONDITION(
-        (&mFeatures), supportsExternalMemoryFuchsia,
+        &mFeatures, supportsExternalMemoryFuchsia,
         ExtensionFound(VK_FUCHSIA_EXTERNAL_MEMORY_EXTENSION_NAME, deviceExtensionNames));
 
     ANGLE_FEATURE_CONDITION(
-        (&mFeatures), supportsExternalSemaphoreFd,
+        &mFeatures, supportsExternalSemaphoreFd,
         ExtensionFound(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, deviceExtensionNames));
 
     ANGLE_FEATURE_CONDITION(
-        (&mFeatures), supportsExternalSemaphoreFuchsia,
+        &mFeatures, supportsExternalSemaphoreFuchsia,
         ExtensionFound(VK_FUCHSIA_EXTERNAL_SEMAPHORE_EXTENSION_NAME, deviceExtensionNames));
 
     ANGLE_FEATURE_CONDITION(
-        (&mFeatures), supportsShaderStencilExport,
+        &mFeatures, supportsShaderStencilExport,
         ExtensionFound(VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME, deviceExtensionNames));
 
-    ANGLE_FEATURE_CONDITION((&mFeatures), supportsTransformFeedbackExtension,
+    ANGLE_FEATURE_CONDITION(&mFeatures, supportsTransformFeedbackExtension,
                             mTransformFeedbackFeatures.transformFeedback == VK_TRUE);
 
-    ANGLE_FEATURE_CONDITION((&mFeatures), supportsIndexTypeUint8,
+    ANGLE_FEATURE_CONDITION(&mFeatures, supportsIndexTypeUint8,
                             mIndexTypeUint8Features.indexTypeUint8 == VK_TRUE);
 
-    ANGLE_FEATURE_CONDITION((&mFeatures), emulateTransformFeedback,
+    ANGLE_FEATURE_CONDITION(&mFeatures, emulateTransformFeedback,
                             (mFeatures.supportsTransformFeedbackExtension.enabled == VK_FALSE &&
                              mPhysicalDeviceFeatures.vertexPipelineStoresAndAtomics == VK_TRUE));
 
-    ANGLE_FEATURE_CONDITION((&mFeatures), disableFifoPresentMode, IsLinux() && isIntel);
+    ANGLE_FEATURE_CONDITION(&mFeatures, disableFifoPresentMode, IsLinux() && isIntel);
 
-    ANGLE_FEATURE_CONDITION((&mFeatures), bindEmptyForUnusedDescriptorSets,
+    ANGLE_FEATURE_CONDITION(&mFeatures, bindEmptyForUnusedDescriptorSets,
                             IsAndroid() && isQualcomm);
 
-    ANGLE_FEATURE_CONDITION((&mFeatures), forceOldRewriteStructSamplers, IsAndroid() && !isSwS);
+    ANGLE_FEATURE_CONDITION(&mFeatures, forceOldRewriteStructSamplers, IsAndroid() && !isSwS);
 
-    ANGLE_FEATURE_CONDITION((&mFeatures), perFrameWindowSizeQuery,
-                            isIntel || (IsWindows() && isAMD) || IsFuchsia());
+    ANGLE_FEATURE_CONDITION(&mFeatures, perFrameWindowSizeQuery,
+                            isIntel || (IsWindows() && isAMD) || IsFuchsia() || isARM);
 
     // Disabled on AMD/windows due to buggy behavior.
-    ANGLE_FEATURE_CONDITION((&mFeatures), disallowSeamfulCubeMapEmulation, IsWindows() && isAMD);
+    ANGLE_FEATURE_CONDITION(&mFeatures, disallowSeamfulCubeMapEmulation, IsWindows() && isAMD);
 
-    ANGLE_FEATURE_CONDITION((&mFeatures), padBuffersToMaxVertexAttribStride, isAMD);
+    ANGLE_FEATURE_CONDITION(&mFeatures, padBuffersToMaxVertexAttribStride, isAMD);
     mMaxVertexAttribStride = std::min(static_cast<uint32_t>(gl::limits::kMaxVertexAttribStride),
                                       mPhysicalDeviceProperties.limits.maxVertexInputBindingStride);
 
-    ANGLE_FEATURE_CONDITION((&mFeatures), forceD16TexFilter, IsAndroid() && isQualcomm);
+    ANGLE_FEATURE_CONDITION(&mFeatures, forceD16TexFilter, IsAndroid() && isQualcomm);
 
-    ANGLE_FEATURE_CONDITION((&mFeatures), disableFlippingBlitWithCommand,
-                            IsAndroid() && isQualcomm);
+    ANGLE_FEATURE_CONDITION(&mFeatures, disableFlippingBlitWithCommand, IsAndroid() && isQualcomm);
 
     // Allocation sanitization disabled by default because of a heaveyweight implementation
     // that can cause OOM and timeouts.
-    ANGLE_FEATURE_CONDITION((&mFeatures), allocateNonZeroMemory, false);
+    ANGLE_FEATURE_CONDITION(&mFeatures, allocateNonZeroMemory, false);
+
+    ANGLE_FEATURE_CONDITION(&mFeatures, persistentlyMappedBuffers, true);
 
     ANGLE_FEATURE_CONDITION(
-        (&mFeatures), supportsExternalMemoryHost,
+        &mFeatures, supportsExternalMemoryHost,
         ExtensionFound(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME, deviceExtensionNames));
 
     // Pre-rotation support is not fully ready to be enabled.
-    ANGLE_FEATURE_CONDITION((&mFeatures), enablePreRotateSurfaces, false);
+    ANGLE_FEATURE_CONDITION(&mFeatures, enablePreRotateSurfaces, false);
 
     // Currently disable FramebufferVk cache on Apple: http://anglebug.com/4442
-    ANGLE_FEATURE_CONDITION((&mFeatures), enableFramebufferVkCache, !IsApple());
+    ANGLE_FEATURE_CONDITION(&mFeatures, enableFramebufferVkCache, !IsApple());
 
     // Currently disabled by default: http://anglebug.com/3078
-    ANGLE_FEATURE_CONDITION((&mFeatures), enablePrecisionQualifiers, false);
+    ANGLE_FEATURE_CONDITION(&mFeatures, enablePrecisionQualifiers, false);
+
+    ANGLE_FEATURE_CONDITION(&mFeatures, supportDepthStencilRenderingFeedbackLoops, true);
 
     angle::PlatformMethods *platform = ANGLEPlatformCurrent();
     platform->overrideFeaturesVk(platform, &mFeatures);
@@ -1910,7 +1932,7 @@
         ANGLE_VK_TRY(context, vkQueueSubmit(mQueues[priority], 1, &submitInfo, handle));
     }
 
-    ANGLE_TRY(cleanupGarbage(context, false));
+    ANGLE_TRY(cleanupGarbage(false));
 
     *serialOut                = mCurrentQueueSerial;
     mLastSubmittedQueueSerial = mCurrentQueueSerial;
@@ -1943,7 +1965,7 @@
         ANGLE_VK_TRY(context, vkQueueWaitIdle(mQueues[priority]));
     }
 
-    ANGLE_TRY(cleanupGarbage(context, false));
+    ANGLE_TRY(cleanupGarbage(false));
 
     return angle::Result::Continue;
 }
@@ -1955,7 +1977,7 @@
         ANGLE_VK_TRY(context, vkDeviceWaitIdle(mDevice));
     }
 
-    ANGLE_TRY(cleanupGarbage(context, false));
+    ANGLE_TRY(cleanupGarbage(false));
 
     return angle::Result::Continue;
 }
@@ -2029,7 +2051,7 @@
     return IsMaskFlagSet(getFormatFeatureBits<features>(format, featureBits), featureBits);
 }
 
-angle::Result RendererVk::cleanupGarbage(vk::Context *context, bool block)
+angle::Result RendererVk::cleanupGarbage(bool block)
 {
     std::lock_guard<decltype(mGarbageMutex)> lock(mGarbageMutex);
 
@@ -2037,7 +2059,7 @@
     {
         // Possibly 'counter' should be always zero when we add the object to garbage.
         vk::SharedGarbage &garbage = *garbageIter;
-        if (garbage.destroyIfComplete(mDevice, mLastCompletedQueueSerial))
+        if (garbage.destroyIfComplete(this, mLastCompletedQueueSerial))
         {
             garbageIter = mSharedGarbage.erase(garbageIter);
         }
diff --git a/src/libANGLE/renderer/vulkan/RendererVk.h b/src/libANGLE/renderer/vulkan/RendererVk.h
index d23ef88..47dba80 100644
--- a/src/libANGLE/renderer/vulkan/RendererVk.h
+++ b/src/libANGLE/renderer/vulkan/RendererVk.h
@@ -28,6 +28,7 @@
 #include "libANGLE/renderer/vulkan/vk_format_utils.h"
 #include "libANGLE/renderer/vulkan/vk_helpers.h"
 #include "libANGLE/renderer/vulkan/vk_internal_shaders_autogen.h"
+#include "libANGLE/renderer/vulkan/vk_mem_alloc_wrapper.h"
 
 namespace egl
 {
@@ -73,7 +74,7 @@
                              const char *wsiLayer);
     // Reload volk vk* function ptrs if needed for an already initialized RendererVk
     void reloadVolkIfNeeded() const;
-    void onDestroy(vk::Context *context);
+    void onDestroy();
 
     void notifyDeviceLost();
     bool isDeviceLost() const;
@@ -100,6 +101,8 @@
     }
     VkDevice getDevice() const { return mDevice; }
 
+    const VmaAllocator &getAllocator() const { return mAllocator; }
+
     angle::Result selectPresentQueueForSurface(DisplayVk *displayVk,
                                                VkSurfaceKHR surface,
                                                uint32_t *presentQueueOut);
@@ -117,7 +120,6 @@
 
     const vk::MemoryProperties &getMemoryProperties() const { return mMemoryProperties; }
 
-    // TODO(jmadill): We could pass angle::FormatID here.
     const vk::Format &getFormat(GLenum internalFormat) const
     {
         return mFormatTable[internalFormat];
@@ -262,7 +264,7 @@
     template <VkFormatFeatureFlags VkFormatProperties::*features>
     bool hasFormatFeatureBits(VkFormat format, const VkFormatFeatureFlags featureBits);
 
-    angle::Result cleanupGarbage(vk::Context *context, bool block);
+    angle::Result cleanupGarbage(bool block);
 
     egl::Display *mDisplay;
 
@@ -356,6 +358,8 @@
 
     // track whether we initialized (or released) glslang
     bool mGlslangInitialized;
+
+    VmaAllocator mAllocator;
 };
 
 }  // namespace rx
diff --git a/src/libANGLE/renderer/vulkan/ResourceVk.cpp b/src/libANGLE/renderer/vulkan/ResourceVk.cpp
index 340ff28..806750f 100644
--- a/src/libANGLE/renderer/vulkan/ResourceVk.cpp
+++ b/src/libANGLE/renderer/vulkan/ResourceVk.cpp
@@ -31,6 +31,25 @@
     return contextVk->finishToSerial(mUse.getSerial());
 }
 
+angle::Result Resource::waitForIdle(ContextVk *contextVk)
+{
+    // If there are pending commands for the resource, flush them.
+    if (usedInRecordedCommands())
+    {
+        ANGLE_TRY(contextVk->flushImpl(nullptr));
+    }
+
+    // Make sure the driver is done with the resource.
+    if (usedInRunningCommands(contextVk->getLastCompletedQueueSerial()))
+    {
+        ANGLE_TRY(finishRunningCommands(contextVk));
+    }
+
+    ASSERT(!isCurrentlyInUse(contextVk->getLastCompletedQueueSerial()));
+
+    return angle::Result::Continue;
+}
+
 // SharedGarbage implementation.
 SharedGarbage::SharedGarbage() = default;
 
@@ -52,7 +71,7 @@
     return *this;
 }
 
-bool SharedGarbage::destroyIfComplete(VkDevice device, Serial completedSerial)
+bool SharedGarbage::destroyIfComplete(RendererVk *renderer, Serial completedSerial)
 {
     if (mLifetime.isCurrentlyInUse(completedSerial))
         return false;
@@ -61,7 +80,7 @@
 
     for (GarbageObject &object : mGarbage)
     {
-        object.destroy(device);
+        object.destroy(renderer);
     }
 
     return true;
diff --git a/src/libANGLE/renderer/vulkan/ResourceVk.h b/src/libANGLE/renderer/vulkan/ResourceVk.h
index 34b7b2f..8d4c632 100644
--- a/src/libANGLE/renderer/vulkan/ResourceVk.h
+++ b/src/libANGLE/renderer/vulkan/ResourceVk.h
@@ -122,7 +122,7 @@
     ~SharedGarbage();
     SharedGarbage &operator=(SharedGarbage &&rhs);
 
-    bool destroyIfComplete(VkDevice device, Serial completedSerial);
+    bool destroyIfComplete(RendererVk *renderer, Serial completedSerial);
 
   private:
     SharedResourceUse mLifetime;
@@ -179,6 +179,9 @@
     // Ensures the driver is caught up to this resource and it is only in use by ANGLE.
     angle::Result finishRunningCommands(ContextVk *contextVk);
 
+    // Complete all recorded and in-flight commands involving this resource
+    angle::Result waitForIdle(ContextVk *contextVk);
+
     // Adds the resource to a resource use list.
     void retain(ResourceUseList *resourceUseList);
 
diff --git a/src/libANGLE/renderer/vulkan/SecondaryCommandBuffer.cpp b/src/libANGLE/renderer/vulkan/SecondaryCommandBuffer.cpp
index ccbb343..e0d67ce 100644
--- a/src/libANGLE/renderer/vulkan/SecondaryCommandBuffer.cpp
+++ b/src/libANGLE/renderer/vulkan/SecondaryCommandBuffer.cpp
@@ -27,6 +27,8 @@
             return "--Invalid--";
         case CommandID::BeginQuery:
             return "BeginQuery";
+        case CommandID::BeginTransformFeedback:
+            return "BeginTransformFeedback";
         case CommandID::BindComputePipeline:
             return "BindComputePipeline";
         case CommandID::BindDescriptorSets:
@@ -35,10 +37,10 @@
             return "BindGraphicsPipeline";
         case CommandID::BindIndexBuffer:
             return "BindIndexBuffer";
-        case CommandID::BindVertexBuffers:
-            return "BindVertexBuffers";
         case CommandID::BindTransformFeedbackBuffers:
             return "BindTransformFeedbackBuffers";
+        case CommandID::BindVertexBuffers:
+            return "BindVertexBuffers";
         case CommandID::BlitImage:
             return "BlitImage";
         case CommandID::BufferBarrier:
@@ -67,22 +69,24 @@
             return "DrawIndexed";
         case CommandID::DrawIndexedBaseVertex:
             return "DrawIndexedBaseVertex";
+        case CommandID::DrawIndexedIndirect:
+            return "DrawIndexedIndirect";
         case CommandID::DrawIndexedInstanced:
             return "DrawIndexedInstanced";
         case CommandID::DrawIndexedInstancedBaseVertex:
             return "DrawIndexedInstancedBaseVertex";
         case CommandID::DrawIndexedInstancedBaseVertexBaseInstance:
             return "DrawIndexedInstancedBaseVertexBaseInstance";
+        case CommandID::DrawIndirect:
+            return "DrawIndirect";
         case CommandID::DrawInstanced:
             return "DrawInstanced";
         case CommandID::DrawInstancedBaseInstance:
             return "DrawInstancedBaseInstance";
-        case CommandID::DrawIndexedIndirect:
-            return "DrawIndexedIndirect";
-        case CommandID::DrawIndirect:
-            return "DrawIndirect";
         case CommandID::EndQuery:
             return "EndQuery";
+        case CommandID::EndTransformFeedback:
+            return "EndTransformFeedback";
         case CommandID::ExecutionBarrier:
             return "ExecutionBarrier";
         case CommandID::FillBuffer:
@@ -137,6 +141,20 @@
                     vkCmdBeginQuery(cmdBuffer, params->queryPool, params->query, params->flags);
                     break;
                 }
+                case CommandID::BeginTransformFeedback:
+                {
+                    const BeginTransformFeedbackParams *params =
+                        getParamPtr<BeginTransformFeedbackParams>(currentCommand);
+                    const VkBuffer *counterBuffers =
+                        Offset<VkBuffer>(params, sizeof(BeginTransformFeedbackParams));
+                    // Workaround for AMD driver bug where it expects the offsets array to be
+                    // non-null
+                    gl::TransformFeedbackBuffersArray<VkDeviceSize> offsets;
+                    offsets.fill(0);
+                    vkCmdBeginTransformFeedbackEXT(cmdBuffer, 0, params->bufferCount,
+                                                   counterBuffers, offsets.data());
+                    break;
+                }
                 case CommandID::BindComputePipeline:
                 {
                     const BindPipelineParams *params =
@@ -307,6 +325,13 @@
                     vkCmdDrawIndexed(cmdBuffer, params->indexCount, 1, 0, params->vertexOffset, 0);
                     break;
                 }
+                case CommandID::DrawIndexedIndirect:
+                {
+                    const DrawIndexedIndirectParams *params =
+                        getParamPtr<DrawIndexedIndirectParams>(currentCommand);
+                    vkCmdDrawIndexedIndirect(cmdBuffer, params->buffer, params->offset, 1, 0);
+                    break;
+                }
                 case CommandID::DrawIndexedInstanced:
                 {
                     const DrawIndexedInstancedParams *params =
@@ -332,6 +357,13 @@
                                      params->firstInstance);
                     break;
                 }
+                case CommandID::DrawIndirect:
+                {
+                    const DrawIndirectParams *params =
+                        getParamPtr<DrawIndirectParams>(currentCommand);
+                    vkCmdDrawIndirect(cmdBuffer, params->buffer, params->offset, 1, 0);
+                    break;
+                }
                 case CommandID::DrawInstanced:
                 {
                     const DrawInstancedParams *params =
@@ -348,26 +380,26 @@
                               params->firstVertex, params->firstInstance);
                     break;
                 }
-                case CommandID::DrawIndirect:
-                {
-                    const DrawIndirectParams *params =
-                        getParamPtr<DrawIndirectParams>(currentCommand);
-                    vkCmdDrawIndirect(cmdBuffer, params->buffer, params->offset, 1, 0);
-                    break;
-                }
-                case CommandID::DrawIndexedIndirect:
-                {
-                    const DrawIndexedIndirectParams *params =
-                        getParamPtr<DrawIndexedIndirectParams>(currentCommand);
-                    vkCmdDrawIndexedIndirect(cmdBuffer, params->buffer, params->offset, 1, 0);
-                    break;
-                }
                 case CommandID::EndQuery:
                 {
                     const EndQueryParams *params = getParamPtr<EndQueryParams>(currentCommand);
                     vkCmdEndQuery(cmdBuffer, params->queryPool, params->query);
                     break;
                 }
+                case CommandID::EndTransformFeedback:
+                {
+                    const EndTransformFeedbackParams *params =
+                        getParamPtr<EndTransformFeedbackParams>(currentCommand);
+                    const VkBuffer *counterBuffers =
+                        Offset<VkBuffer>(params, sizeof(EndTransformFeedbackParams));
+                    // Workaround for AMD driver bug where it expects the offsets array to be
+                    // non-null
+                    gl::TransformFeedbackBuffersArray<VkDeviceSize> offsets;
+                    offsets.fill(0);
+                    vkCmdEndTransformFeedbackEXT(cmdBuffer, 0, params->bufferCount, counterBuffers,
+                                                 offsets.data());
+                    break;
+                }
                 case CommandID::ExecutionBarrier:
                 {
                     const ExecutionBarrierParams *params =
diff --git a/src/libANGLE/renderer/vulkan/SecondaryCommandBuffer.h b/src/libANGLE/renderer/vulkan/SecondaryCommandBuffer.h
index 4398397..f8fde79 100644
--- a/src/libANGLE/renderer/vulkan/SecondaryCommandBuffer.h
+++ b/src/libANGLE/renderer/vulkan/SecondaryCommandBuffer.h
@@ -24,12 +24,15 @@
 
 namespace priv
 {
-
+// NOTE: Please keep command-related enums, stucts, functions
+//  and other code dealing with commands in alphabetical order
+//  This simplifies searching and updating commands.
 enum class CommandID : uint16_t
 {
     // Invalid cmd used to mark end of sequence of commands
     Invalid = 0,
     BeginQuery,
+    BeginTransformFeedback,
     BindComputePipeline,
     BindDescriptorSets,
     BindGraphicsPipeline,
@@ -50,14 +53,15 @@
     Draw,
     DrawIndexed,
     DrawIndexedBaseVertex,
+    DrawIndexedIndirect,
     DrawIndexedInstanced,
     DrawIndexedInstancedBaseVertex,
     DrawIndexedInstancedBaseVertexBaseInstance,
+    DrawIndirect,
     DrawInstanced,
     DrawInstancedBaseInstance,
-    DrawIndirect,
-    DrawIndexedIndirect,
     EndQuery,
+    EndTransformFeedback,
     ExecutionBarrier,
     FillBuffer,
     ImageBarrier,
@@ -79,11 +83,19 @@
 // This makes it easy to know the size of params & to copy params
 // TODO: Could optimize the size of some of these structs through bit-packing
 //  and customizing sizing based on limited parameter sets used by ANGLE
-struct BindPipelineParams
+struct BeginQueryParams
 {
-    VkPipeline pipeline;
+    VkQueryPool queryPool;
+    uint32_t query;
+    VkQueryControlFlags flags;
 };
-VERIFY_4_BYTE_ALIGNMENT(BindPipelineParams)
+VERIFY_4_BYTE_ALIGNMENT(BeginQueryParams)
+
+struct BeginTransformFeedbackParams
+{
+    uint32_t bufferCount;
+};
+VERIFY_4_BYTE_ALIGNMENT(BeginTransformFeedbackParams)
 
 struct BindDescriptorSetParams
 {
@@ -103,6 +115,12 @@
 };
 VERIFY_4_BYTE_ALIGNMENT(BindIndexBufferParams)
 
+struct BindPipelineParams
+{
+    VkPipeline pipeline;
+};
+VERIFY_4_BYTE_ALIGNMENT(BindPipelineParams)
+
 struct BindTransformFeedbackBuffersParams
 {
     // ANGLE always has firstBinding of 0 so not storing that currently
@@ -110,12 +128,7 @@
 };
 VERIFY_4_BYTE_ALIGNMENT(BindTransformFeedbackBuffersParams)
 
-struct BindVertexBuffersParams
-{
-    // ANGLE always has firstBinding of 0 so not storing that currently
-    uint32_t bindingCount;
-};
-VERIFY_4_BYTE_ALIGNMENT(BindVertexBuffersParams)
+using BindVertexBuffersParams = BindTransformFeedbackBuffersParams;
 
 struct BlitImageParams
 {
@@ -126,6 +139,39 @@
 };
 VERIFY_4_BYTE_ALIGNMENT(BlitImageParams)
 
+struct BufferBarrierParams
+{
+    VkPipelineStageFlags srcStageMask;
+    VkPipelineStageFlags dstStageMask;
+    VkBufferMemoryBarrier bufferMemoryBarrier;
+};
+VERIFY_4_BYTE_ALIGNMENT(BufferBarrierParams)
+
+struct ClearAttachmentsParams
+{
+    uint32_t attachmentCount;
+    VkClearRect rect;
+};
+VERIFY_4_BYTE_ALIGNMENT(ClearAttachmentsParams)
+
+struct ClearColorImageParams
+{
+    VkImage image;
+    VkImageLayout imageLayout;
+    VkClearColorValue color;
+    VkImageSubresourceRange range;
+};
+VERIFY_4_BYTE_ALIGNMENT(ClearColorImageParams)
+
+struct ClearDepthStencilImageParams
+{
+    VkImage image;
+    VkImageLayout imageLayout;
+    VkClearDepthStencilValue depthStencil;
+    VkImageSubresourceRange range;
+};
+VERIFY_4_BYTE_ALIGNMENT(ClearDepthStencilImageParams)
+
 struct CopyBufferParams
 {
     VkBuffer srcBuffer;
@@ -162,39 +208,20 @@
 };
 VERIFY_4_BYTE_ALIGNMENT(CopyImageToBufferParams)
 
-struct ClearAttachmentsParams
+struct DispatchParams
 {
-    uint32_t attachmentCount;
-    VkClearRect rect;
+    uint32_t groupCountX;
+    uint32_t groupCountY;
+    uint32_t groupCountZ;
 };
-VERIFY_4_BYTE_ALIGNMENT(ClearAttachmentsParams)
+VERIFY_4_BYTE_ALIGNMENT(DispatchParams)
 
-struct ClearColorImageParams
+struct DispatchIndirectParams
 {
-    VkImage image;
-    VkImageLayout imageLayout;
-    VkClearColorValue color;
-    VkImageSubresourceRange range;
+    VkBuffer buffer;
+    VkDeviceSize offset;
 };
-VERIFY_4_BYTE_ALIGNMENT(ClearColorImageParams)
-
-struct ClearDepthStencilImageParams
-{
-    VkImage image;
-    VkImageLayout imageLayout;
-    VkClearDepthStencilValue depthStencil;
-    VkImageSubresourceRange range;
-};
-VERIFY_4_BYTE_ALIGNMENT(ClearDepthStencilImageParams)
-
-struct PushConstantsParams
-{
-    VkPipelineLayout layout;
-    VkShaderStageFlags flag;
-    uint32_t offset;
-    uint32_t size;
-};
-VERIFY_4_BYTE_ALIGNMENT(PushConstantsParams)
+VERIFY_4_BYTE_ALIGNMENT(DispatchIndirectParams)
 
 struct DrawParams
 {
@@ -203,23 +230,6 @@
 };
 VERIFY_4_BYTE_ALIGNMENT(DrawParams)
 
-struct DrawInstancedParams
-{
-    uint32_t vertexCount;
-    uint32_t instanceCount;
-    uint32_t firstVertex;
-};
-VERIFY_4_BYTE_ALIGNMENT(DrawInstancedParams)
-
-struct DrawInstancedBaseInstanceParams
-{
-    uint32_t vertexCount;
-    uint32_t instanceCount;
-    uint32_t firstVertex;
-    uint32_t firstInstance;
-};
-VERIFY_4_BYTE_ALIGNMENT(DrawInstancedBaseInstanceParams)
-
 struct DrawIndexedParams
 {
     uint32_t indexCount;
@@ -233,6 +243,13 @@
 };
 VERIFY_4_BYTE_ALIGNMENT(DrawIndexedBaseVertexParams)
 
+struct DrawIndexedIndirectParams
+{
+    VkBuffer buffer;
+    VkDeviceSize offset;
+};
+VERIFY_4_BYTE_ALIGNMENT(DrawIndexedIndirectParams)
+
 struct DrawIndexedInstancedParams
 {
     uint32_t indexCount;
@@ -258,21 +275,6 @@
 };
 VERIFY_4_BYTE_ALIGNMENT(DrawIndexedInstancedBaseVertexBaseInstanceParams)
 
-struct DrawIndexedIndirectParams
-{
-    VkBuffer buffer;
-    VkDeviceSize offset;
-};
-VERIFY_4_BYTE_ALIGNMENT(DrawIndexedIndirectParams)
-
-struct DispatchParams
-{
-    uint32_t groupCountX;
-    uint32_t groupCountY;
-    uint32_t groupCountZ;
-};
-VERIFY_4_BYTE_ALIGNMENT(DispatchParams)
-
 struct DrawIndirectParams
 {
     VkBuffer buffer;
@@ -280,12 +282,41 @@
 };
 VERIFY_4_BYTE_ALIGNMENT(DrawIndirectParams)
 
-struct DispatchIndirectParams
+struct DrawInstancedParams
 {
-    VkBuffer buffer;
-    VkDeviceSize offset;
+    uint32_t vertexCount;
+    uint32_t instanceCount;
+    uint32_t firstVertex;
 };
-VERIFY_4_BYTE_ALIGNMENT(DispatchIndirectParams)
+VERIFY_4_BYTE_ALIGNMENT(DrawInstancedParams)
+
+struct DrawInstancedBaseInstanceParams
+{
+    uint32_t vertexCount;
+    uint32_t instanceCount;
+    uint32_t firstVertex;
+    uint32_t firstInstance;
+};
+VERIFY_4_BYTE_ALIGNMENT(DrawInstancedBaseInstanceParams)
+
+struct EndQueryParams
+{
+    VkQueryPool queryPool;
+    uint32_t query;
+};
+VERIFY_4_BYTE_ALIGNMENT(EndQueryParams)
+
+struct EndTransformFeedbackParams
+{
+    uint32_t bufferCount;
+};
+VERIFY_4_BYTE_ALIGNMENT(EndTransformFeedbackParams)
+
+struct ExecutionBarrierParams
+{
+    VkPipelineStageFlags stageMask;
+};
+VERIFY_4_BYTE_ALIGNMENT(ExecutionBarrierParams)
 
 struct FillBufferParams
 {
@@ -296,6 +327,14 @@
 };
 VERIFY_4_BYTE_ALIGNMENT(FillBufferParams)
 
+struct ImageBarrierParams
+{
+    VkPipelineStageFlags srcStageMask;
+    VkPipelineStageFlags dstStageMask;
+    VkImageMemoryBarrier imageMemoryBarrier;
+};
+VERIFY_4_BYTE_ALIGNMENT(ImageBarrierParams)
+
 struct MemoryBarrierParams
 {
     VkPipelineStageFlags srcStageMask;
@@ -315,34 +354,14 @@
 };
 VERIFY_4_BYTE_ALIGNMENT(PipelineBarrierParams)
 
-struct ExecutionBarrierParams
+struct PushConstantsParams
 {
-    VkPipelineStageFlags stageMask;
+    VkPipelineLayout layout;
+    VkShaderStageFlags flag;
+    uint32_t offset;
+    uint32_t size;
 };
-VERIFY_4_BYTE_ALIGNMENT(ExecutionBarrierParams)
-
-struct BufferBarrierParams
-{
-    VkPipelineStageFlags srcStageMask;
-    VkPipelineStageFlags dstStageMask;
-    VkBufferMemoryBarrier bufferMemoryBarrier;
-};
-VERIFY_4_BYTE_ALIGNMENT(BufferBarrierParams)
-
-struct ImageBarrierParams
-{
-    VkPipelineStageFlags srcStageMask;
-    VkPipelineStageFlags dstStageMask;
-    VkImageMemoryBarrier imageMemoryBarrier;
-};
-VERIFY_4_BYTE_ALIGNMENT(ImageBarrierParams)
-
-struct SetEventParams
-{
-    VkEvent event;
-    VkPipelineStageFlags stageMask;
-};
-VERIFY_4_BYTE_ALIGNMENT(SetEventParams)
+VERIFY_4_BYTE_ALIGNMENT(PushConstantsParams)
 
 struct ResetEventParams
 {
@@ -351,17 +370,6 @@
 };
 VERIFY_4_BYTE_ALIGNMENT(ResetEventParams)
 
-struct WaitEventsParams
-{
-    uint32_t eventCount;
-    VkPipelineStageFlags srcStageMask;
-    VkPipelineStageFlags dstStageMask;
-    uint32_t memoryBarrierCount;
-    uint32_t bufferMemoryBarrierCount;
-    uint32_t imageMemoryBarrierCount;
-};
-VERIFY_4_BYTE_ALIGNMENT(WaitEventsParams)
-
 struct ResetQueryPoolParams
 {
     VkQueryPool queryPool;
@@ -378,20 +386,23 @@
 };
 VERIFY_4_BYTE_ALIGNMENT(ResolveImageParams)
 
-struct BeginQueryParams
+struct SetEventParams
 {
-    VkQueryPool queryPool;
-    uint32_t query;
-    VkQueryControlFlags flags;
+    VkEvent event;
+    VkPipelineStageFlags stageMask;
 };
-VERIFY_4_BYTE_ALIGNMENT(BeginQueryParams)
+VERIFY_4_BYTE_ALIGNMENT(SetEventParams)
 
-struct EndQueryParams
+struct WaitEventsParams
 {
-    VkQueryPool queryPool;
-    uint32_t query;
+    uint32_t eventCount;
+    VkPipelineStageFlags srcStageMask;
+    VkPipelineStageFlags dstStageMask;
+    uint32_t memoryBarrierCount;
+    uint32_t bufferMemoryBarrierCount;
+    uint32_t imageMemoryBarrierCount;
 };
-VERIFY_4_BYTE_ALIGNMENT(EndQueryParams)
+VERIFY_4_BYTE_ALIGNMENT(WaitEventsParams)
 
 struct WriteTimestampParams
 {
@@ -407,7 +418,6 @@
     CommandID id;
     uint16_t size;
 };
-
 static_assert(sizeof(CommandHeader) == 4, "Check CommandHeader size");
 
 template <typename DestT, typename T>
@@ -437,6 +447,8 @@
     // Add commands
     void beginQuery(VkQueryPool queryPool, uint32_t query, VkQueryControlFlags flags);
 
+    void beginTransformFeedback(uint32_t counterBufferCount, const VkBuffer *pCounterBuffers);
+
     void bindComputePipeline(const Pipeline &pipeline);
 
     void bindDescriptorSets(const PipelineLayout &layout,
@@ -522,7 +534,10 @@
 
     void drawIndexed(uint32_t indexCount);
     void drawIndexedBaseVertex(uint32_t indexCount, uint32_t vertexOffset);
-
+    void drawIndexedIndirect(const Buffer &buffer,
+                             VkDeviceSize offset,
+                             uint32_t drawCount,
+                             uint32_t stride);
     void drawIndexedInstanced(uint32_t indexCount, uint32_t instanceCount);
     void drawIndexedInstancedBaseVertex(uint32_t indexCount,
                                         uint32_t instanceCount,
@@ -533,23 +548,21 @@
                                                     int32_t vertexOffset,
                                                     uint32_t firstInstance);
 
+    void drawIndirect(const Buffer &buffer,
+                      VkDeviceSize offset,
+                      uint32_t drawCount,
+                      uint32_t stride);
+
     void drawInstanced(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex);
     void drawInstancedBaseInstance(uint32_t vertexCount,
                                    uint32_t instanceCount,
                                    uint32_t firstVertex,
                                    uint32_t firstInstance);
 
-    void drawIndirect(const Buffer &buffer,
-                      VkDeviceSize offset,
-                      uint32_t drawCount,
-                      uint32_t stride);
-    void drawIndexedIndirect(const Buffer &buffer,
-                             VkDeviceSize offset,
-                             uint32_t drawCount,
-                             uint32_t stride);
-
     void endQuery(VkQueryPool queryPool, uint32_t query);
 
+    void endTransformFeedback(uint32_t counterBufferCount, const VkBuffer *pCounterBuffers);
+
     void executionBarrier(VkPipelineStageFlags stageMask);
 
     void fillBuffer(const Buffer &dstBuffer,
@@ -608,6 +621,7 @@
     void writeTimestamp(VkPipelineStageFlagBits pipelineStage,
                         VkQueryPool queryPool,
                         uint32_t query);
+
     // No-op for compatibility
     VkResult end() { return VK_SUCCESS; }
 
@@ -685,7 +699,7 @@
         constexpr size_t fixedAllocationSize = sizeof(StructType) + sizeof(CommandHeader);
         const size_t allocationSize          = fixedAllocationSize + variableSize;
         // Make sure we have enough room to mark follow-on header "Invalid"
-        if (mCurrentBytesRemaining <= (allocationSize + sizeof(CommandHeader)))
+        if (mCurrentBytesRemaining < (allocationSize + sizeof(CommandHeader)))
         {
             allocateNewBlock();
         }
@@ -699,7 +713,7 @@
     {
         constexpr size_t allocationSize = sizeof(StructType) + sizeof(CommandHeader);
         // Make sure we have enough room to mark follow-on header "Invalid"
-        if (mCurrentBytesRemaining <= (allocationSize + sizeof(CommandHeader)))
+        if (mCurrentBytesRemaining < (allocationSize + sizeof(CommandHeader)))
         {
             allocateNewBlock();
         }
@@ -747,6 +761,17 @@
     paramStruct->flags            = flags;
 }
 
+ANGLE_INLINE void SecondaryCommandBuffer::beginTransformFeedback(uint32_t bufferCount,
+                                                                 const VkBuffer *counterBuffers)
+{
+    uint8_t *writePtr;
+    size_t bufferSize                         = bufferCount * sizeof(VkBuffer);
+    BeginTransformFeedbackParams *paramStruct = initCommand<BeginTransformFeedbackParams>(
+        CommandID::BeginTransformFeedback, bufferSize, &writePtr);
+    paramStruct->bufferCount = bufferCount;
+    storePointerParameter(writePtr, counterBuffers, bufferSize);
+}
+
 ANGLE_INLINE void SecondaryCommandBuffer::bindComputePipeline(const Pipeline &pipeline)
 {
     BindPipelineParams *paramStruct =
@@ -1013,6 +1038,18 @@
     paramStruct->vertexOffset = vertexOffset;
 }
 
+ANGLE_INLINE void SecondaryCommandBuffer::drawIndexedIndirect(const Buffer &buffer,
+                                                              VkDeviceSize offset,
+                                                              uint32_t drawCount,
+                                                              uint32_t stride)
+{
+    DrawIndexedIndirectParams *paramStruct =
+        initCommand<DrawIndexedIndirectParams>(CommandID::DrawIndexedIndirect);
+    paramStruct->buffer = buffer.getHandle();
+    paramStruct->offset = offset;
+    ASSERT(drawCount == 1);
+}
+
 ANGLE_INLINE void SecondaryCommandBuffer::drawIndexedInstanced(uint32_t indexCount,
                                                                uint32_t instanceCount)
 {
@@ -1051,6 +1088,20 @@
     paramStruct->firstInstance = firstInstance;
 }
 
+ANGLE_INLINE void SecondaryCommandBuffer::drawIndirect(const Buffer &buffer,
+                                                       VkDeviceSize offset,
+                                                       uint32_t drawCount,
+                                                       uint32_t stride)
+{
+    DrawIndirectParams *paramStruct = initCommand<DrawIndirectParams>(CommandID::DrawIndirect);
+    paramStruct->buffer             = buffer.getHandle();
+    paramStruct->offset             = offset;
+
+    // OpenGL ES doesn't have a way to specify a drawCount or stride, throw assert if something
+    // changes.
+    ASSERT(drawCount == 1);
+}
+
 ANGLE_INLINE void SecondaryCommandBuffer::drawInstanced(uint32_t vertexCount,
                                                         uint32_t instanceCount,
                                                         uint32_t firstVertex)
@@ -1074,32 +1125,6 @@
     paramStruct->firstInstance = firstInstance;
 }
 
-ANGLE_INLINE void SecondaryCommandBuffer::drawIndirect(const Buffer &buffer,
-                                                       VkDeviceSize offset,
-                                                       uint32_t drawCount,
-                                                       uint32_t stride)
-{
-    DrawIndirectParams *paramStruct = initCommand<DrawIndirectParams>(CommandID::DrawIndirect);
-    paramStruct->buffer             = buffer.getHandle();
-    paramStruct->offset             = offset;
-
-    // OpenGL ES doesn't have a way to specify a drawCount or stride, throw assert if something
-    // changes.
-    ASSERT(drawCount == 1);
-}
-
-ANGLE_INLINE void SecondaryCommandBuffer::drawIndexedIndirect(const Buffer &buffer,
-                                                              VkDeviceSize offset,
-                                                              uint32_t drawCount,
-                                                              uint32_t stride)
-{
-    DrawIndexedIndirectParams *paramStruct =
-        initCommand<DrawIndexedIndirectParams>(CommandID::DrawIndexedIndirect);
-    paramStruct->buffer = buffer.getHandle();
-    paramStruct->offset = offset;
-    ASSERT(drawCount == 1);
-}
-
 ANGLE_INLINE void SecondaryCommandBuffer::endQuery(VkQueryPool queryPool, uint32_t query)
 {
     EndQueryParams *paramStruct = initCommand<EndQueryParams>(CommandID::EndQuery);
@@ -1107,6 +1132,17 @@
     paramStruct->query          = query;
 }
 
+ANGLE_INLINE void SecondaryCommandBuffer::endTransformFeedback(uint32_t bufferCount,
+                                                               const VkBuffer *counterBuffers)
+{
+    uint8_t *writePtr;
+    size_t bufferSize                       = bufferCount * sizeof(VkBuffer);
+    EndTransformFeedbackParams *paramStruct = initCommand<EndTransformFeedbackParams>(
+        CommandID::EndTransformFeedback, bufferSize, &writePtr);
+    paramStruct->bufferCount = bufferCount;
+    storePointerParameter(writePtr, counterBuffers, bufferSize);
+}
+
 ANGLE_INLINE void SecondaryCommandBuffer::executionBarrier(VkPipelineStageFlags stageMask)
 {
     ExecutionBarrierParams *paramStruct =
diff --git a/src/libANGLE/renderer/vulkan/ShaderVk.cpp b/src/libANGLE/renderer/vulkan/ShaderVk.cpp
index 6e81457..ad54b86 100644
--- a/src/libANGLE/renderer/vulkan/ShaderVk.cpp
+++ b/src/libANGLE/renderer/vulkan/ShaderVk.cpp
@@ -60,6 +60,10 @@
         compileOptions |= SH_IGNORE_PRECISION_QUALIFIERS;
     }
 
+    // Let compiler detect and emit early fragment test execution mode. We will remove it if
+    // context state does not allow it
+    compileOptions |= SH_EARLY_FRAGMENT_TESTS_OPTIMIZATION;
+
     return compileImpl(context, compilerInstance, mData.getSource(), compileOptions | options);
 }
 
diff --git a/src/libANGLE/renderer/vulkan/SurfaceVk.cpp b/src/libANGLE/renderer/vulkan/SurfaceVk.cpp
index 23f16d6..881d35d 100644
--- a/src/libANGLE/renderer/vulkan/SurfaceVk.cpp
+++ b/src/libANGLE/renderer/vulkan/SurfaceVk.cpp
@@ -162,9 +162,6 @@
     VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
     ANGLE_TRY(image.initMemory(displayVk, renderer->getMemoryProperties(), flags));
 
-    // Clear the image if it has emulated channels.
-    image.stageClearIfEmulatedFormat(gl::ImageIndex::Make2D(0), vkFormat);
-
     return angle::Result::Continue;
 }
 
@@ -205,9 +202,6 @@
                                        externalMemoryRequirements, &importMemoryHostPointerInfo,
                                        VK_QUEUE_FAMILY_EXTERNAL, flags));
 
-    // Clear the image if it has emulated channels.
-    image.stageClearIfEmulatedFormat(gl::ImageIndex::Make2D(0), vkFormat);
-
     return angle::Result::Continue;
 }
 
@@ -357,15 +351,13 @@
 
     if (mColorAttachment.image.valid())
     {
-        mColorAttachment.image.stageSubresourceRobustClear(imageIndex,
-                                                           mColorAttachment.image.getFormat());
+        mColorAttachment.image.stageSubresourceClear(imageIndex);
         ANGLE_TRY(mColorAttachment.image.flushAllStagedUpdates(contextVk));
     }
 
     if (mDepthStencilAttachment.image.valid())
     {
-        mDepthStencilAttachment.image.stageSubresourceRobustClear(
-            imageIndex, mDepthStencilAttachment.image.getFormat());
+        mDepthStencilAttachment.image.stageSubresourceClear(imageIndex);
         ANGLE_TRY(mDepthStencilAttachment.image.flushAllStagedUpdates(contextVk));
     }
     return angle::Result::Continue;
@@ -899,9 +891,6 @@
         // Initialize the color render target with the multisampled targets.  If not multisampled,
         // the render target will be updated to refer to a swapchain image on every acquire.
         mColorRenderTarget.init(&mColorImageMS, &mColorImageMSViews, 0, 0);
-
-        // Clear the image if it has emulated channels.
-        mColorImageMS.stageClearIfEmulatedFormat(gl::ImageIndex::Make2D(0), format);
     }
 
     ANGLE_TRY(resizeSwapchainImages(context, imageCount));
@@ -909,15 +898,7 @@
     for (uint32_t imageIndex = 0; imageIndex < imageCount; ++imageIndex)
     {
         SwapchainImage &member = mSwapchainImages[imageIndex];
-        member.image.init2DWeakReference(swapchainImages[imageIndex], extents, format, 1);
-
-        if (!mColorImageMS.valid())
-        {
-            // Clear the image if it has emulated channels.  If a multisampled image exists, this
-            // image will be unused until a pre-present resolve, at which point it will be fully
-            // initialized and wouldn't need a clear.
-            member.image.stageClearIfEmulatedFormat(gl::ImageIndex::Make2D(0), format);
-        }
+        member.image.init2DWeakReference(context, swapchainImages[imageIndex], extents, format, 1);
     }
 
     // Initialize depth/stencil if requested.
@@ -935,9 +916,6 @@
         mDepthStencilRenderTarget.init(&mDepthStencilImage, &mDepthStencilImageViews, 0, 0);
 
         // We will need to pass depth/stencil image views to the RenderTargetVk in the future.
-
-        // Clear the image if it has emulated channels.
-        mDepthStencilImage.stageClearIfEmulatedFormat(gl::ImageIndex::Make2D(0), dsFormat);
     }
 
     return angle::Result::Continue;
@@ -1022,7 +1000,7 @@
     {
         // We don't own the swapchain image handles, so we just remove our reference to it.
         swapchainImage.image.resetImageWeakReference();
-        swapchainImage.image.destroy(contextVk->getDevice());
+        swapchainImage.image.destroy(renderer);
 
         swapchainImage.imageViews.release(renderer);
         contextVk->addGarbage(&swapchainImage.framebuffer);
@@ -1040,11 +1018,12 @@
 
 void WindowSurfaceVk::destroySwapChainImages(DisplayVk *displayVk)
 {
-    VkDevice device = displayVk->getDevice();
+    RendererVk *renderer = displayVk->getRenderer();
+    VkDevice device      = displayVk->getDevice();
 
-    mDepthStencilImage.destroy(device);
+    mDepthStencilImage.destroy(renderer);
     mDepthStencilImageViews.destroy(device);
-    mColorImageMS.destroy(device);
+    mColorImageMS.destroy(renderer);
     mColorImageMSViews.destroy(device);
     mFramebufferMS.destroy(device);
 
@@ -1052,7 +1031,7 @@
     {
         // We don't own the swapchain image handles, so we just remove our reference to it.
         swapchainImage.image.resetImageWeakReference();
-        swapchainImage.image.destroy(device);
+        swapchainImage.image.destroy(renderer);
         swapchainImage.imageViews.destroy(device);
         swapchainImage.framebuffer.destroy(device);
 
@@ -1114,7 +1093,18 @@
         }
     }
 
-    SwapchainImage &image = mSwapchainImages[mCurrentSwapchainImageIndex];
+    SwapchainImage &image               = mSwapchainImages[mCurrentSwapchainImageIndex];
+    vk::Framebuffer &currentFramebuffer = mSwapchainImages[mCurrentSwapchainImageIndex].framebuffer;
+    updateOverlay(contextVk);
+    bool overlayHasWidget = overlayHasEnabledWidget(contextVk);
+
+    // We can only do present related optimization if this is the last renderpass that touches the
+    // swapchain image. MSAA resolve and overlay will insert another renderpass which disqualifies
+    // the optimization.
+    if (!mColorImageMS.valid() && !overlayHasWidget && currentFramebuffer.valid())
+    {
+        contextVk->optimizeRenderPassForPresent(currentFramebuffer.getHandle());
+    }
 
     vk::CommandBuffer *commandBuffer = nullptr;
     ANGLE_TRY(contextVk->endRenderPassAndGetCommandBuffer(&commandBuffer));
@@ -1141,8 +1131,12 @@
         mColorImageMS.resolve(&image.image, resolveRegion, commandBuffer);
     }
 
-    ANGLE_TRY(updateAndDrawOverlay(contextVk, &image));
+    if (overlayHasWidget)
+    {
+        ANGLE_TRY(drawOverlay(contextVk, &image));
+    }
 
+    // This does nothing if it already in the requested layout
     image.image.changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::Present, commandBuffer);
 
     // Knowing that the kSwapHistorySize'th submission ago has finished, we can know that the
@@ -1503,21 +1497,19 @@
 
     vk::ImageHelper *image =
         isMultiSampled() ? &mColorImageMS : &mSwapchainImages[mCurrentSwapchainImageIndex].image;
-    image->stageSubresourceRobustClear(imageIndex, image->getFormat());
+    image->stageSubresourceClear(imageIndex);
     ANGLE_TRY(image->flushAllStagedUpdates(contextVk));
 
     if (mDepthStencilImage.valid())
     {
-        mDepthStencilImage.stageSubresourceRobustClear(gl::ImageIndex::Make2D(0),
-                                                       mDepthStencilImage.getFormat());
+        mDepthStencilImage.stageSubresourceClear(gl::ImageIndex::Make2D(0));
         ANGLE_TRY(mDepthStencilImage.flushAllStagedUpdates(contextVk));
     }
 
     return angle::Result::Continue;
 }
 
-angle::Result WindowSurfaceVk::updateAndDrawOverlay(ContextVk *contextVk,
-                                                    SwapchainImage *image) const
+void WindowSurfaceVk::updateOverlay(ContextVk *contextVk) const
 {
     const gl::OverlayType *overlay = contextVk->getOverlay();
     OverlayVk *overlayVk           = vk::GetImpl(overlay);
@@ -1525,7 +1517,7 @@
     // If overlay is disabled, nothing to do.
     if (overlayVk == nullptr)
     {
-        return angle::Result::Continue;
+        return;
     }
 
     RendererVk *rendererVk = contextVk->getRenderer();
@@ -1540,6 +1532,19 @@
         overlay->getCountWidget(gl::WidgetId::VulkanValidationMessageCount)
             ->add(validationMessageCount);
     }
+}
+
+ANGLE_INLINE bool WindowSurfaceVk::overlayHasEnabledWidget(ContextVk *contextVk) const
+{
+    const gl::OverlayType *overlay = contextVk->getOverlay();
+    OverlayVk *overlayVk           = vk::GetImpl(overlay);
+    return overlayVk && overlayVk->getEnabledWidgetCount() > 0;
+}
+
+angle::Result WindowSurfaceVk::drawOverlay(ContextVk *contextVk, SwapchainImage *image) const
+{
+    const gl::OverlayType *overlay = contextVk->getOverlay();
+    OverlayVk *overlayVk           = vk::GetImpl(overlay);
 
     // Draw overlay
     const vk::ImageView *imageView = nullptr;
diff --git a/src/libANGLE/renderer/vulkan/SurfaceVk.h b/src/libANGLE/renderer/vulkan/SurfaceVk.h
index e069a03..f350699 100644
--- a/src/libANGLE/renderer/vulkan/SurfaceVk.h
+++ b/src/libANGLE/renderer/vulkan/SurfaceVk.h
@@ -260,7 +260,9 @@
                           const void *pNextChain,
                           bool *presentOutOfDate);
 
-    angle::Result updateAndDrawOverlay(ContextVk *contextVk, impl::SwapchainImage *image) const;
+    void updateOverlay(ContextVk *contextVk) const;
+    bool overlayHasEnabledWidget(ContextVk *contextVk) const;
+    angle::Result drawOverlay(ContextVk *contextVk, impl::SwapchainImage *image) const;
 
     angle::Result newPresentSemaphore(vk::Context *context, vk::Semaphore *semaphoreOut);
 
diff --git a/src/libANGLE/renderer/vulkan/TextureVk.cpp b/src/libANGLE/renderer/vulkan/TextureVk.cpp
index ff42c1f..4502ad3 100644
--- a/src/libANGLE/renderer/vulkan/TextureVk.cpp
+++ b/src/libANGLE/renderer/vulkan/TextureVk.cpp
@@ -8,6 +8,7 @@
 //
 
 #include "libANGLE/renderer/vulkan/TextureVk.h"
+#include <vulkan/vulkan.h>
 
 #include "common/debug.h"
 #include "image_util/generatemip.inc"
@@ -39,6 +40,8 @@
 constexpr VkFormatFeatureFlags kBlitFeatureFlags =
     VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT;
 
+constexpr angle::SubjectIndex kStagingBufferSubjectIndex = 0;
+
 bool CanCopyWithTransfer(RendererVk *renderer,
                          const vk::Format &srcFormat,
                          const vk::Format &destFormat)
@@ -111,7 +114,8 @@
       mImageLevelOffset(0),
       mImage(nullptr),
       mStagingBufferInitialSize(vk::kStagingBufferSize),
-      mImageUsageFlags(0)
+      mImageUsageFlags(0),
+      mStagingBufferObserverBinding(this, kStagingBufferSubjectIndex)
 {}
 
 TextureVk::~TextureVk() = default;
@@ -131,11 +135,12 @@
                                   GLenum format,
                                   GLenum type,
                                   const gl::PixelUnpackState &unpack,
+                                  gl::Buffer *unpackBuffer,
                                   const uint8_t *pixels)
 {
     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
 
-    return setImageImpl(context, index, formatInfo, size, type, unpack, pixels);
+    return setImageImpl(context, index, formatInfo, size, type, unpack, unpackBuffer, pixels);
 }
 
 angle::Result TextureVk::setSubImage(const gl::Context *context,
@@ -167,7 +172,11 @@
 {
     const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
 
-    return setImageImpl(context, index, formatInfo, size, GL_UNSIGNED_BYTE, unpack, pixels);
+    const gl::State &glState = context->getState();
+    gl::Buffer *unpackBuffer = glState.getTargetBuffer(gl::BufferBinding::PixelUnpack);
+
+    return setImageImpl(context, index, formatInfo, size, GL_UNSIGNED_BYTE, unpack, unpackBuffer,
+                        pixels);
 }
 
 angle::Result TextureVk::setCompressedSubImage(const gl::Context *context,
@@ -197,6 +206,7 @@
                                       const gl::Extents &size,
                                       GLenum type,
                                       const gl::PixelUnpackState &unpack,
+                                      gl::Buffer *unpackBuffer,
                                       const uint8_t *pixels)
 {
     ContextVk *contextVk = vk::GetImpl(context);
@@ -211,8 +221,6 @@
     {
         return angle::Result::Continue;
     }
-    const gl::State &glState = contextVk->getState();
-    gl::Buffer *unpackBuffer = glState.getTargetBuffer(gl::BufferBinding::PixelUnpack);
 
     return setSubImageImpl(context, index, gl::Box(0, 0, 0, size.width, size.height, size.depth),
                            formatInfo, type, unpack, unpackBuffer, pixels, vkFormat);
@@ -279,8 +287,7 @@
                 gl::Offset(area.x, area.y, area.z), formatInfo, unpack, type, source, vkFormat,
                 inputRowPitch, inputDepthPitch, inputSkipBytes));
 
-            unpackBufferVk->unmapImpl(contextVk);
-            onStagingBufferChange();
+            ANGLE_TRY(unpackBufferVk->unmapImpl(contextVk));
         }
     }
     else if (pixels)
@@ -288,7 +295,6 @@
         ANGLE_TRY(mImage->stageSubresourceUpdate(
             contextVk, getNativeImageIndex(index), gl::Extents(area.width, area.height, area.depth),
             gl::Offset(area.x, area.y, area.z), formatInfo, unpack, type, pixels, vkFormat));
-        onStagingBufferChange();
     }
 
     return angle::Result::Continue;
@@ -460,7 +466,6 @@
         context, offsetImageIndex, clippedSourceArea, modifiedDestOffset,
         gl::Extents(clippedSourceArea.width, clippedSourceArea.height, 1), internalFormat,
         framebufferVk));
-    onStagingBufferChange();
 
     return angle::Result::Continue;
 }
@@ -526,7 +531,6 @@
     ANGLE_TRY(mImage->stageSubresourceUpdateAndGetData(
         contextVk, destinationAllocationSize, offsetImageIndex,
         gl::Extents(sourceArea.width, sourceArea.height, 1), destOffset, &destData));
-    onStagingBufferChange();
 
     // Source and dest data is tightly packed
     GLuint sourceDataRowPitch = sourceArea.width * sourceTextureFormat.pixelBytes;
@@ -635,7 +639,6 @@
         VkImageType imageType = gl_vk::GetImageType(mState.getType());
         mImage->stageSubresourceUpdateFromImage(stagingImage.release(), index, destOffset, extents,
                                                 imageType);
-        onStagingBufferChange();
     }
 
     return angle::Result::Continue;
@@ -731,7 +734,6 @@
         mImage->stageSubresourceUpdateFromImage(stagingImage.release(), index, destOffset,
                                                 gl::Extents(sourceArea.width, sourceArea.height, 1),
                                                 imageType);
-        onStagingBufferChange();
     }
 
     return angle::Result::Continue;
@@ -877,6 +879,7 @@
     {
         releaseImage(contextVk);
         releaseStagingBuffer(contextVk);
+        mStagingBufferObserverBinding.bind(nullptr);
         SafeDelete(mImage);
     }
 }
@@ -921,6 +924,8 @@
 {
     ASSERT(mImage == nullptr);
 
+    mStagingBufferObserverBinding.bind(imageHelper);
+
     mOwnsImage        = selfOwned;
     mImageNativeType  = imageType;
     mImageLevelOffset = imageLevelOffset;
@@ -1151,7 +1156,6 @@
         ANGLE_TRY(copyAndStageImageSubresource(contextVk, baseLevelDesc, false,
                                                getNativeImageLayer(0), 0, mImage->getBaseLevel()));
 
-        onStagingBufferChange();
         // Release the origin image and recreate it with new mipmap counts.
         releaseImage(contextVk);
 
@@ -1312,8 +1316,6 @@
         }
     }
 
-    // Inform the front end that we've updated the staging buffer
-    onStagingBufferChange();
     // Now that we've staged all the updates, release the current image so that it will be
     // recreated with the correct number of mip levels, base level, and max level.
     releaseImage(contextVk);
@@ -1547,12 +1549,13 @@
 angle::Result TextureVk::initializeContents(const gl::Context *context,
                                             const gl::ImageIndex &imageIndex)
 {
+    ContextVk *contextVk      = vk::GetImpl(context);
     const gl::ImageDesc &desc = mState.getImageDesc(imageIndex);
     const vk::Format &format =
-        vk::GetImpl(context)->getRenderer()->getFormat(desc.format.info->sizedInternalFormat);
+        contextVk->getRenderer()->getFormat(desc.format.info->sizedInternalFormat);
 
-    mImage->stageSubresourceRobustClear(imageIndex, format);
-    onStagingBufferChange();
+    ASSERT(mImage);
+    mImage->stageRobustResourceClear(imageIndex, format);
 
     // Note that we cannot ensure the image is initialized because we might be calling subImage
     // on a non-complete cube map.
@@ -1647,21 +1650,6 @@
 
     ANGLE_TRY(initImageViews(contextVk, format, sized, levelCount, layerCount));
 
-    // If the image has an emulated channel or robust resource init is enabled, always clear it.
-    // These channels will be masked out in future writes, and shouldn't contain uninitialized
-    // values.
-    if (contextVk->getState().isRobustResourceInitEnabled() || format.hasEmulatedImageChannels())
-    {
-        uint32_t levelCount = mImage->getLevelCount();
-
-        for (uint32_t level = 0; level < levelCount; ++level)
-        {
-            gl::ImageIndex index = gl::ImageIndex::Make2DArrayRange(level, 0, layerCount);
-            mImage->stageSubresourceRobustClear(index, format);
-            onStagingBufferChange();
-        }
-    }
-
     mSerial = contextVk->generateTextureSerial();
 
     return angle::Result::Continue;
@@ -1698,6 +1686,7 @@
         }
         else
         {
+            mStagingBufferObserverBinding.bind(nullptr);
             mImage = nullptr;
         }
     }
@@ -1712,7 +1701,7 @@
     // Then clear the levels
     mRenderTargets.clear();
 
-    onStagingBufferChange();
+    onStateChange(angle::SubjectMessage::SubjectChanged);
 }
 
 void TextureVk::releaseStagingBuffer(ContextVk *contextVk)
@@ -1783,7 +1772,6 @@
             contextVk, mipAllocationSize,
             gl::ImageIndex::MakeFromType(mState.getType(), currentMipLevel, layer), mipLevelExtents,
             gl::Offset(), &destData));
-        onStagingBufferChange();
 
         // Generate the mipmap into that new buffer
         sourceFormat.mipGenerationFunction(
@@ -1861,4 +1849,12 @@
     const gl::ImageDesc &baseLevelDesc = mState.getBaseLevelDesc();
     return renderer->getFormat(baseLevelDesc.format.info->sizedInternalFormat);
 }
+
+void TextureVk::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
+{
+    ASSERT(index == kStagingBufferSubjectIndex && message == angle::SubjectMessage::SubjectChanged);
+
+    // Forward the notification to vk::Texture that the staging buffer changed.
+    onStateChange(angle::SubjectMessage::SubjectChanged);
+}
 }  // namespace rx
diff --git a/src/libANGLE/renderer/vulkan/TextureVk.h b/src/libANGLE/renderer/vulkan/TextureVk.h
index 071c2f6..8f474f1 100644
--- a/src/libANGLE/renderer/vulkan/TextureVk.h
+++ b/src/libANGLE/renderer/vulkan/TextureVk.h
@@ -30,7 +30,7 @@
 // vkCmdCopyBufferToImage buffer offset multiple
 constexpr VkDeviceSize kBufferOffsetMultiple = 4;
 
-class TextureVk : public TextureImpl
+class TextureVk : public TextureImpl, public angle::ObserverInterface
 {
   public:
     TextureVk(const gl::TextureState &state, RendererVk *renderer);
@@ -44,6 +44,7 @@
                            GLenum format,
                            GLenum type,
                            const gl::PixelUnpackState &unpack,
+                           gl::Buffer *unpackBuffer,
                            const uint8_t *pixels) override;
     angle::Result setSubImage(const gl::Context *context,
                               const gl::ImageIndex &index,
@@ -226,7 +227,10 @@
                               GLenum type,
                               void *pixels) override;
 
-    ANGLE_INLINE bool isBoundAsImageTexture() const { return mState.isBoundAsImageTexture(); }
+    ANGLE_INLINE bool isBoundAsImageTexture(gl::ContextID contextID) const
+    {
+        return mState.isBoundAsImageTexture(contextID);
+    }
 
   private:
     // Transform an image index from the frontend into one that can be used on the backing
@@ -258,6 +262,7 @@
                                const gl::Extents &size,
                                GLenum type,
                                const gl::PixelUnpackState &unpack,
+                               gl::Buffer *unpackBuffer,
                                const uint8_t *pixels);
     angle::Result setSubImageImpl(const gl::Context *context,
                                   const gl::ImageIndex &index,
@@ -371,8 +376,6 @@
                                              uint32_t levelCount,
                                              const vk::Format &format);
 
-    void onStagingBufferChange() { onStateChange(angle::SubjectMessage::SubjectChanged); }
-
     const gl::InternalFormat &getImplementationSizedFormat(const gl::Context *context) const;
     const vk::Format &getBaseLevelFormat(RendererVk *renderer) const;
     // Re-create the image.
@@ -384,6 +387,10 @@
     // Update base and max levels, and re-create image if needed.
     angle::Result updateBaseMaxLevels(ContextVk *contextVk, GLuint baseLevel, GLuint maxLevel);
 
+    // We monitor the staging buffer and set dirty bits if the staging buffer changes. Note that we
+    // support changes in the staging buffer even outside the TextureVk class.
+    void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override;
+
     bool mOwnsImage;
 
     gl::TextureType mImageNativeType;
@@ -422,6 +429,8 @@
 
     // The created vkImage usage flag.
     VkImageUsageFlags mImageUsageFlags;
+
+    angle::ObserverBinding mStagingBufferObserverBinding;
 };
 
 }  // namespace rx
diff --git a/src/libANGLE/renderer/vulkan/TransformFeedbackVk.cpp b/src/libANGLE/renderer/vulkan/TransformFeedbackVk.cpp
index 1184b6c..a7a1307 100644
--- a/src/libANGLE/renderer/vulkan/TransformFeedbackVk.cpp
+++ b/src/libANGLE/renderer/vulkan/TransformFeedbackVk.cpp
@@ -11,6 +11,7 @@
 
 #include "libANGLE/Context.h"
 #include "libANGLE/Query.h"
+#include "libANGLE/renderer/glslang_wrapper_utils.h"
 #include "libANGLE/renderer/vulkan/BufferVk.h"
 #include "libANGLE/renderer/vulkan/ContextVk.h"
 #include "libANGLE/renderer/vulkan/FramebufferVk.h"
@@ -161,18 +162,20 @@
 
 void TransformFeedbackVk::updateDescriptorSetLayout(
     ContextVk *contextVk,
-    const gl::ProgramState &programState,
+    ShaderInterfaceVariableInfoMap &vsVariableInfoMap,
+    size_t xfbBufferCount,
     vk::DescriptorSetLayoutDesc *descSetLayoutOut) const
 {
     if (!contextVk->getFeatures().emulateTransformFeedback.enabled)
         return;
 
-    size_t xfbBufferCount = programState.getTransformFeedbackBufferCount();
-
     for (uint32_t bufferIndex = 0; bufferIndex < xfbBufferCount; ++bufferIndex)
     {
-        descSetLayoutOut->update(kXfbBindingIndexStart + bufferIndex,
-                                 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT);
+        const std::string bufferName            = GetXfbBufferName(bufferIndex);
+        const ShaderInterfaceVariableInfo &info = vsVariableInfoMap[bufferName];
+
+        descSetLayoutOut->update(info.binding, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1,
+                                 VK_SHADER_STAGE_VERTEX_BIT);
     }
 }
 
@@ -207,7 +210,9 @@
 
     const std::vector<gl::OffsetBindingPointer<gl::Buffer>> &xfbBuffers =
         mState.getIndexedBuffers();
-    size_t xfbBufferCount = programState.getTransformFeedbackBufferCount();
+    const gl::ProgramExecutable *executable = contextVk->getState().getProgramExecutable();
+    ASSERT(executable);
+    size_t xfbBufferCount = executable->getTransformFeedbackBufferCount(contextVk->getState());
 
     ASSERT(xfbBufferCount > 0);
     ASSERT(programState.getTransformFeedbackBufferMode() != GL_INTERLEAVED_ATTRIBS ||
@@ -239,7 +244,6 @@
 }
 
 void TransformFeedbackVk::getBufferOffsets(ContextVk *contextVk,
-                                           const gl::ProgramState &programState,
                                            GLint drawCallFirstVertex,
                                            int32_t *offsetsOut,
                                            size_t offsetsSize) const
@@ -250,7 +254,9 @@
     GLsizeiptr verticesDrawn = mState.getVerticesDrawn();
     const std::vector<GLsizei> &bufferStrides =
         mState.getBoundProgram()->getTransformFeedbackStrides();
-    size_t xfbBufferCount = programState.getTransformFeedbackBufferCount();
+    const gl::ProgramExecutable *executable = contextVk->getState().getProgramExecutable();
+    ASSERT(executable);
+    size_t xfbBufferCount = executable->getTransformFeedbackBufferCount(contextVk->getState());
 
     ASSERT(xfbBufferCount > 0);
 
@@ -295,12 +301,17 @@
                                              VkDescriptorBufferInfo *pBufferInfo,
                                              VkDescriptorSet descSet) const
 {
-    VkDevice device = contextVk->getDevice();
+    VkDevice device                   = contextVk->getDevice();
+    ProgramExecutableVk *executableVk = contextVk->getExecutable();
+    ShaderMapInterfaceVariableInfoMap variableInfoMap =
+        executableVk->getShaderInterfaceVariableInfoMap();
+    const std::string bufferName      = GetXfbBufferName(0);
+    ShaderInterfaceVariableInfo &info = variableInfoMap[gl::ShaderType::Vertex][bufferName];
 
     VkWriteDescriptorSet writeDescriptorInfo = {};
     writeDescriptorInfo.sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
     writeDescriptorInfo.dstSet               = descSet;
-    writeDescriptorInfo.dstBinding           = kXfbBindingIndexStart;
+    writeDescriptorInfo.dstBinding           = info.binding;
     writeDescriptorInfo.dstArrayElement      = 0;
     writeDescriptorInfo.descriptorCount      = static_cast<uint32_t>(xfbBufferCount);
     writeDescriptorInfo.descriptorType       = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
diff --git a/src/libANGLE/renderer/vulkan/TransformFeedbackVk.h b/src/libANGLE/renderer/vulkan/TransformFeedbackVk.h
index 4e862b0..3219890 100644
--- a/src/libANGLE/renderer/vulkan/TransformFeedbackVk.h
+++ b/src/libANGLE/renderer/vulkan/TransformFeedbackVk.h
@@ -11,6 +11,8 @@
 #define LIBANGLE_RENDERER_VULKAN_TRANSFORMFEEDBACKVK_H_
 
 #include "libANGLE/renderer/TransformFeedbackImpl.h"
+
+#include "libANGLE/renderer/glslang_wrapper_utils.h"
 #include "libANGLE/renderer/vulkan/vk_helpers.h"
 
 namespace gl
@@ -54,7 +56,8 @@
                                     const gl::OffsetBindingPointer<gl::Buffer> &binding) override;
 
     void updateDescriptorSetLayout(ContextVk *contextVk,
-                                   const gl::ProgramState &programState,
+                                   ShaderInterfaceVariableInfoMap &vsVariableInfoMap,
+                                   size_t xfbBufferCount,
                                    vk::DescriptorSetLayoutDesc *descSetLayoutOut) const;
     void initDescriptorSet(ContextVk *contextVk,
                            size_t xfbBufferCount,
@@ -64,7 +67,6 @@
                              const gl::ProgramState &programState,
                              VkDescriptorSet descSet) const;
     void getBufferOffsets(ContextVk *contextVk,
-                          const gl::ProgramState &programState,
                           GLint drawCallFirstVertex,
                           int32_t *offsetsOut,
                           size_t offsetsSize) const;
diff --git a/src/libANGLE/renderer/vulkan/UtilsVk.cpp b/src/libANGLE/renderer/vulkan/UtilsVk.cpp
index 6c4ac0b..8cdc1f2 100644
--- a/src/libANGLE/renderer/vulkan/UtilsVk.cpp
+++ b/src/libANGLE/renderer/vulkan/UtilsVk.cpp
@@ -1189,8 +1189,9 @@
     std::vector<VkClearValue> clearValues = {{}};
     ASSERT(clearValues.size() == 1);
 
-    renderPassAttachmentOps.initWithLoadStore(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
-                                              VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
+    renderPassAttachmentOps.initWithStore(0, VK_ATTACHMENT_LOAD_OP_LOAD,
+                                          vk::ImageLayout::ColorAttachment,
+                                          vk::ImageLayout::ColorAttachment);
 
     ANGLE_TRY(contextVk->flushAndBeginRenderPass(framebuffer, renderArea, renderPassDesc,
                                                  renderPassAttachmentOps, clearValues,
@@ -1426,8 +1427,8 @@
     pipelineDesc.setScissor(gl_vk::GetRect(params.blitArea));
 
     // Change source layout outside render pass
-    ANGLE_TRY(contextVk->onImageRead(src->getAspectFlags(),
-                                     vk::ImageLayout::AllGraphicsShadersReadOnly, src));
+    ANGLE_TRY(contextVk->onImageRead(src->getAspectFlags(), vk::ImageLayout::FragmentShaderReadOnly,
+                                     src));
 
     vk::CommandBuffer *commandBuffer;
     ANGLE_TRY(framebuffer->startNewRenderPass(contextVk, params.blitArea, &commandBuffer));
@@ -1735,7 +1736,7 @@
 
     // Change source layout outside render pass
     ANGLE_TRY(contextVk->onImageRead(VK_IMAGE_ASPECT_COLOR_BIT,
-                                     vk::ImageLayout::AllGraphicsShadersReadOnly, src));
+                                     vk::ImageLayout::FragmentShaderReadOnly, src));
     ANGLE_TRY(
         contextVk->onImageWrite(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::ColorAttachment, dest));
 
diff --git a/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp b/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
index a4fcb0b..c39be66 100644
--- a/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
+++ b/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
@@ -425,7 +425,7 @@
                                0, numVertices, binding.getStride(), srcFormatSize,
                                vertexFormat.vertexLoadFunction, &mCurrentArrayBuffers[attribIndex],
                                &conversion->lastAllocationOffset, 1));
-    srcBuffer->unmapImpl(contextVk);
+    ANGLE_TRY(srcBuffer->unmapImpl(contextVk));
 
     ASSERT(conversion->dirty);
     conversion->dirty = false;
@@ -757,7 +757,7 @@
                                            &mCurrentArrayBufferOffsets[attribIndex], divisor));
                 if (bufferVk)
                 {
-                    bufferVk->unmapImpl(contextVk);
+                    ANGLE_TRY(bufferVk->unmapImpl(contextVk));
                 }
             }
             else
diff --git a/src/libANGLE/renderer/vulkan/vk_cache_utils.cpp b/src/libANGLE/renderer/vulkan/vk_cache_utils.cpp
index e3f8708..ecc43e1 100644
--- a/src/libANGLE/renderer/vulkan/vk_cache_utils.cpp
+++ b/src/libANGLE/renderer/vulkan/vk_cache_utils.cpp
@@ -155,8 +155,10 @@
     desc->storeOp        = static_cast<VkAttachmentStoreOp>(ops.storeOp);
     desc->stencilLoadOp  = static_cast<VkAttachmentLoadOp>(ops.stencilLoadOp);
     desc->stencilStoreOp = static_cast<VkAttachmentStoreOp>(ops.stencilStoreOp);
-    desc->initialLayout  = static_cast<VkImageLayout>(ops.initialLayout);
-    desc->finalLayout    = static_cast<VkImageLayout>(ops.finalLayout);
+    desc->initialLayout =
+        ConvertImageLayoutToVkImageLayout(static_cast<ImageLayout>(ops.initialLayout));
+    desc->finalLayout =
+        ConvertImageLayoutToVkImageLayout(static_cast<ImageLayout>(ops.finalLayout));
 }
 
 void UnpackStencilState(const vk::PackedStencilOpState &packedState,
@@ -1441,8 +1443,8 @@
 }
 
 void AttachmentOpsArray::initDummyOp(size_t index,
-                                     VkImageLayout initialLayout,
-                                     VkImageLayout finalLayout)
+                                     ImageLayout initialLayout,
+                                     ImageLayout finalLayout)
 {
     PackedAttachmentOpsDesc &ops = mOps[index];
 
@@ -1454,16 +1456,17 @@
     SetBitField(ops.stencilStoreOp, VK_ATTACHMENT_STORE_OP_DONT_CARE);
 }
 
-void AttachmentOpsArray::initWithLoadStore(size_t index,
-                                           VkImageLayout initialLayout,
-                                           VkImageLayout finalLayout)
+void AttachmentOpsArray::initWithStore(size_t index,
+                                       VkAttachmentLoadOp loadOp,
+                                       ImageLayout initialLayout,
+                                       ImageLayout finalLayout)
 {
     PackedAttachmentOpsDesc &ops = mOps[index];
 
     SetBitField(ops.initialLayout, initialLayout);
     SetBitField(ops.finalLayout, finalLayout);
-    SetBitField(ops.loadOp, VK_ATTACHMENT_LOAD_OP_LOAD);
-    SetBitField(ops.stencilLoadOp, VK_ATTACHMENT_LOAD_OP_LOAD);
+    SetBitField(ops.loadOp, loadOp);
+    SetBitField(ops.stencilLoadOp, loadOp);
     SetBitField(ops.storeOp, VK_ATTACHMENT_STORE_OP_STORE);
     SetBitField(ops.stencilStoreOp, VK_ATTACHMENT_STORE_OP_STORE);
 }
@@ -1645,6 +1648,8 @@
     return memcmp(mSerials.data(), other.mSerials.data(), sizeof(TexUnitSerials) * mMaxIndex) == 0;
 }
 
+// FramebufferDesc implementation.
+
 FramebufferDesc::FramebufferDesc()
 {
     reset();
@@ -1676,6 +1681,18 @@
     return memcmp(&mSerials, &other.mSerials, sizeof(Serial) * kMaxFramebufferAttachments) == 0;
 }
 
+uint32_t FramebufferDesc::attachmentCount() const
+{
+    uint32_t count = 0;
+    for (const AttachmentSerial &serial : mSerials)
+    {
+        if (serial.imageSerial != 0)
+        {
+            count++;
+        }
+    }
+    return count;
+}
 }  // namespace vk
 
 // RenderPassCache implementation.
@@ -1718,15 +1735,15 @@
         }
 
         uint32_t colorIndexVk = colorAttachmentCount++;
-        ops.initDummyOp(colorIndexVk, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
-                        VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
+        ops.initDummyOp(colorIndexVk, vk::ImageLayout::ColorAttachment,
+                        vk::ImageLayout::ColorAttachment);
     }
 
     if (desc.hasDepthStencilAttachment())
     {
         uint32_t depthStencilIndexVk = colorAttachmentCount;
-        ops.initDummyOp(depthStencilIndexVk, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
-                        VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
+        ops.initDummyOp(depthStencilIndexVk, vk::ImageLayout::DepthStencilAttachment,
+                        vk::ImageLayout::DepthStencilAttachment);
     }
 
     return getRenderPassWithOps(contextVk, serial, desc, ops, renderPassOut);
diff --git a/src/libANGLE/renderer/vulkan/vk_cache_utils.h b/src/libANGLE/renderer/vulkan/vk_cache_utils.h
index f3ad9ca..2a031fd 100644
--- a/src/libANGLE/renderer/vulkan/vk_cache_utils.h
+++ b/src/libANGLE/renderer/vulkan/vk_cache_utils.h
@@ -21,6 +21,7 @@
 namespace vk
 {
 class ImageHelper;
+enum class ImageLayout;
 
 using RenderPassAndSerial = ObjectAndSerial<RenderPass>;
 using PipelineAndSerial   = ObjectAndSerial<Pipeline>;
@@ -152,9 +153,12 @@
     PackedAttachmentOpsDesc &operator[](size_t index);
 
     // Initializes an attachment op with whatever values. Used for compatible RenderPass checks.
-    void initDummyOp(size_t index, VkImageLayout initialLayout, VkImageLayout finalLayout);
-    // Initialize an attachment op with all load and store operations.
-    void initWithLoadStore(size_t index, VkImageLayout initialLayout, VkImageLayout finalLayout);
+    void initDummyOp(size_t index, ImageLayout initialLayout, ImageLayout finalLayout);
+    // Initialize an attachment op with store operations.
+    void initWithStore(size_t index,
+                       VkAttachmentLoadOp loadOp,
+                       ImageLayout initialLayout,
+                       ImageLayout finalLayout);
 
     size_t hash() const;
 
@@ -724,10 +728,8 @@
 // This is IMPLEMENTATION_MAX_DRAW_BUFFERS + 1 for DS attachment
 constexpr size_t kMaxFramebufferAttachments = gl::IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS;
 // Color serials are at index [0:gl::IMPLEMENTATION_MAX_DRAW_BUFFERS-1]
-// Depth index is at gl::IMPLEMENTATION_MAX_DRAW_BUFFERS
-// Stencil index is at gl::IMPLEMENTATION_MAX_DRAW_BUFFERS + 1
-constexpr size_t kFramebufferDescDepthIndex   = gl::IMPLEMENTATION_MAX_DRAW_BUFFERS;
-constexpr size_t kFramebufferDescStencilIndex = gl::IMPLEMENTATION_MAX_DRAW_BUFFERS + 1;
+// Depth/stencil index is at gl::IMPLEMENTATION_MAX_DRAW_BUFFERS
+constexpr size_t kFramebufferDescDepthStencilIndex = gl::IMPLEMENTATION_MAX_DRAW_BUFFERS;
 // Struct for AttachmentSerial cache signatures. Includes level/layer for imageView as
 //  well as a unique Serial value for the underlying image
 struct AttachmentSerial
@@ -752,6 +754,8 @@
 
     bool operator==(const FramebufferDesc &other) const;
 
+    uint32_t attachmentCount() const;
+
   private:
     gl::AttachmentArray<AttachmentSerial> mSerials;
 };
@@ -979,8 +983,6 @@
 // supported.
 constexpr uint32_t kReservedPerStageDefaultUniformBindingCount = 1;
 constexpr uint32_t kReservedDefaultUniformBindingCount         = 3;
-// Binding index start for transform feedback buffers:
-constexpr uint32_t kXfbBindingIndexStart = kReservedDefaultUniformBindingCount;
 }  // namespace rx
 
 #endif  // LIBANGLE_RENDERER_VULKAN_VK_CACHE_UTILS_H_
diff --git a/src/libANGLE/renderer/vulkan/vk_caps_utils.cpp b/src/libANGLE/renderer/vulkan/vk_caps_utils.cpp
index 9867b96..72f342e 100644
--- a/src/libANGLE/renderer/vulkan/vk_caps_utils.cpp
+++ b/src/libANGLE/renderer/vulkan/vk_caps_utils.cpp
@@ -55,9 +55,19 @@
         (mPhysicalDeviceFeatures.textureCompressionETC2 == VK_TRUE) &&
         gl::DetermineCompressedTextureETCSupport(mNativeTextureCaps);
 
-    // Vulkan technically only supports the LDR profile but driver all appear to support the HDR
-    // profile as well. http://anglebug.com/1185#c8
-    mNativeExtensions.textureCompressionASTCHDRKHR = mNativeExtensions.textureCompressionASTCLDRKHR;
+    // Vulkan doesn't support ASTC 3D block textures, which are required by
+    // GL_OES_texture_compression_astc.
+    mNativeExtensions.textureCompressionASTCOES = false;
+
+    // Vulkan doesn't guarantee HDR blocks decoding without VK_EXT_texture_compression_astc_hdr.
+    mNativeExtensions.textureCompressionASTCHDRKHR = false;
+
+    // Vulkan supports sliced 3D ASTC texture uploads when ASTC is supported.
+    mNativeExtensions.textureCompressionSliced3dASTCKHR =
+        mNativeExtensions.textureCompressionASTCLDRKHR;
+
+    // Enable EXT_compressed_ETC1_RGB8_sub_texture
+    mNativeExtensions.compressedETC1RGB8SubTexture = mNativeExtensions.compressedETC1RGB8TextureOES;
 
     // Enable this for simple buffer readback testing, but some functionality is missing.
     // TODO(jmadill): Support full mapBufferRange extension.
@@ -147,6 +157,9 @@
     // Vulkan natively supports standard derivatives
     mNativeExtensions.standardDerivativesOES = true;
 
+    // Vulkan natively supports noperspective interpolation
+    mNativeExtensions.noperspectiveInterpolationNV = true;
+
     // Vulkan natively supports 32-bit indices, entry in kIndexTypeMap
     mNativeExtensions.elementIndexUintOES = true;
 
@@ -155,6 +168,9 @@
     // We support getting image data for Textures and Renderbuffers.
     mNativeExtensions.getImageANGLE = true;
 
+    // Implemented in the translator
+    mNativeExtensions.shaderNonConstGlobalInitializersEXT = true;
+
     // Vulkan has no restrictions of the format of cubemaps, so if the proper formats are supported,
     // creating a cube of any of these formats should be implicitly supported.
     mNativeExtensions.depthTextureCubeMapOES =
diff --git a/src/libANGLE/renderer/vulkan/vk_format_map.json b/src/libANGLE/renderer/vulkan/vk_format_map.json
index 3ec7160..7d7e6e1 100644
--- a/src/libANGLE/renderer/vulkan/vk_format_map.json
+++ b/src/libANGLE/renderer/vulkan/vk_format_map.json
@@ -29,6 +29,7 @@
         "B5G6R5_UNORM": "VK_FORMAT_B5G6R5_UNORM_PACK16",
         "B5G5R5A1_UNORM": "VK_FORMAT_B5G5R5A1_UNORM_PACK16",
         "R8_UNORM": "VK_FORMAT_R8_UNORM",
+        "R8_UNORM_SRGB": "VK_FORMAT_R8_SRGB",
         "R8_SNORM": "VK_FORMAT_R8_SNORM",
         "R8_UINT": "VK_FORMAT_R8_UINT",
         "R8_SINT": "VK_FORMAT_R8_SINT",
diff --git a/src/libANGLE/renderer/vulkan/vk_format_table_autogen.cpp b/src/libANGLE/renderer/vulkan/vk_format_table_autogen.cpp
index bef59dc..f7fb1e7 100644
--- a/src/libANGLE/renderer/vulkan/vk_format_table_autogen.cpp
+++ b/src/libANGLE/renderer/vulkan/vk_format_table_autogen.cpp
@@ -2469,6 +2469,18 @@
             }
             break;
 
+        case angle::FormatID::R8_UNORM_SRGB:
+            internalFormat               = GL_SR8_EXT;
+            actualImageFormatID          = angle::FormatID::R8_UNORM_SRGB;
+            vkImageFormat                = VK_FORMAT_R8_SRGB;
+            imageInitializerFunction     = nullptr;
+            actualBufferFormatID         = angle::FormatID::R8_UNORM_SRGB;
+            vkBufferFormat               = VK_FORMAT_R8_SRGB;
+            vkBufferFormatIsPacked       = false;
+            vertexLoadFunction           = CopyNativeVertexData<GLubyte, 1, 1, 0>;
+            vertexLoadRequiresConversion = false;
+            break;
+
         case angle::FormatID::R8_USCALED:
             internalFormat           = GL_R8_USCALED_ANGLEX;
             actualImageFormatID      = angle::FormatID::R8_USCALED;
diff --git a/src/libANGLE/renderer/vulkan/vk_helpers.cpp b/src/libANGLE/renderer/vulkan/vk_helpers.cpp
index fac4663..64bdc14 100644
--- a/src/libANGLE/renderer/vulkan/vk_helpers.cpp
+++ b/src/libANGLE/renderer/vulkan/vk_helpers.cpp
@@ -27,13 +27,13 @@
 {
 namespace
 {
-// WebGL requires color textures to be initialized to transparent black.
-constexpr VkClearColorValue kWebGLInitColorValue = {{0, 0, 0, 0}};
+// ANGLE_robust_resource_initialization requires color textures to be initialized to zero.
+constexpr VkClearColorValue kRobustInitColorValue = {{0, 0, 0, 0}};
 // When emulating a texture, we want the emulated channels to be 0, with alpha 1.
 constexpr VkClearColorValue kEmulatedInitColorValue = {{0, 0, 0, 1.0f}};
-// WebGL requires depth/stencil textures to be initialized to depth=1, stencil=0.  We are fine with
-// these values for emulated depth/stencil textures too.
-constexpr VkClearDepthStencilValue kWebGLInitDepthStencilValue = {1.0f, 0};
+// ANGLE_robust_resource_initialization requires depth to be initialized to 1 and stencil to 0.
+// We are fine with these values for emulated depth/stencil textures too.
+constexpr VkClearDepthStencilValue kRobustInitDepthStencilValue = {1.0f, 0};
 
 constexpr VkBufferUsageFlags kLineLoopDynamicBufferUsage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT |
                                                            VK_BUFFER_USAGE_TRANSFER_DST_BIT |
@@ -151,6 +151,84 @@
         },
     },
     {
+        ImageLayout::VertexShaderReadOnly,
+        {
+            VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
+            VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
+            VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
+            // Transition to: all reads must happen after barrier.
+            VK_ACCESS_SHADER_READ_BIT,
+            // Transition from: RAR and WAR don't need memory barrier.
+            0,
+            false,
+        },
+    },
+    {
+        ImageLayout::VertexShaderWrite,
+        {
+            VK_IMAGE_LAYOUT_GENERAL,
+            VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
+            VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
+            // Transition to: all reads and writes must happen after barrier.
+            VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
+            // Transition from: all writes must finish before barrier.
+            VK_ACCESS_SHADER_WRITE_BIT,
+            true,
+        },
+    },
+    {
+        ImageLayout::GeometryShaderReadOnly,
+        {
+            VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
+            VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT,
+            VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT,
+            // Transition to: all reads must happen after barrier.
+            VK_ACCESS_SHADER_READ_BIT,
+            // Transition from: RAR and WAR don't need memory barrier.
+            0,
+            false,
+        },
+    },
+    {
+        ImageLayout::GeometryShaderWrite,
+        {
+            VK_IMAGE_LAYOUT_GENERAL,
+            VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT,
+            VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT,
+            // Transition to: all reads and writes must happen after barrier.
+            VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
+            // Transition from: all writes must finish before barrier.
+            VK_ACCESS_SHADER_WRITE_BIT,
+            true,
+        },
+    },
+    {
+        ImageLayout::FragmentShaderReadOnly,
+        {
+            VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
+            VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
+            VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
+            // Transition to: all reads must happen after barrier.
+            VK_ACCESS_SHADER_READ_BIT,
+            // Transition from: RAR and WAR don't need memory barrier.
+            0,
+            false,
+        },
+    },
+    {
+        ImageLayout::FragmentShaderWrite,
+        {
+            VK_IMAGE_LAYOUT_GENERAL,
+            VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
+            VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
+            // Transition to: all reads and writes must happen after barrier.
+            VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
+            // Transition from: all writes must finish before barrier.
+            VK_ACCESS_SHADER_WRITE_BIT,
+            true,
+        },
+    },
+    {
         ImageLayout::ComputeShaderReadOnly,
         {
             VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
@@ -190,7 +268,7 @@
         },
     },
     {
-        ImageLayout::AllGraphicsShadersWrite,
+        ImageLayout::AllGraphicsShadersReadWrite,
         {
             VK_IMAGE_LAYOUT_GENERAL,
             VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
@@ -353,8 +431,28 @@
             return imageFormat;
     }
 }
+
+VkClearValue GetClearValue(const vk::Format &format)
+{
+    VkClearValue clearValue;
+    if (format.intendedFormat().hasDepthOrStencilBits())
+    {
+        clearValue.depthStencil = kRobustInitDepthStencilValue;
+    }
+    else
+    {
+        clearValue.color =
+            format.hasEmulatedImageChannels() ? kEmulatedInitColorValue : kRobustInitColorValue;
+    }
+    return clearValue;
+}
 }  // anonymous namespace
 
+VkImageLayout ConvertImageLayoutToVkImageLayout(ImageLayout imageLayout)
+{
+    return kImageMemoryBarrierData[imageLayout].layout;
+}
+
 // DynamicBuffer implementation.
 DynamicBuffer::DynamicBuffer()
     : mUsage(0),
@@ -452,7 +550,7 @@
         if (mBuffer)
         {
             ANGLE_TRY(flush(contextVk));
-            mBuffer->unmap(contextVk->getDevice());
+            mBuffer->unmap(contextVk->getRenderer());
 
             mInFlightBuffers.push_back(mBuffer);
             mBuffer = nullptr;
@@ -524,7 +622,7 @@
     if (mHostVisible && (mNextAllocationOffset > mLastFlushOrInvalidateOffset))
     {
         ASSERT(mBuffer != nullptr);
-        ANGLE_TRY(mBuffer->flush(contextVk, mLastFlushOrInvalidateOffset,
+        ANGLE_TRY(mBuffer->flush(contextVk->getRenderer(), mLastFlushOrInvalidateOffset,
                                  mNextAllocationOffset - mLastFlushOrInvalidateOffset));
         mLastFlushOrInvalidateOffset = mNextAllocationOffset;
     }
@@ -536,7 +634,7 @@
     if (mHostVisible && (mNextAllocationOffset > mLastFlushOrInvalidateOffset))
     {
         ASSERT(mBuffer != nullptr);
-        ANGLE_TRY(mBuffer->invalidate(contextVk, mLastFlushOrInvalidateOffset,
+        ANGLE_TRY(mBuffer->invalidate(contextVk->getRenderer(), mLastFlushOrInvalidateOffset,
                                       mNextAllocationOffset - mLastFlushOrInvalidateOffset));
         mLastFlushOrInvalidateOffset = mNextAllocationOffset;
     }
@@ -555,11 +653,11 @@
     buffers->clear();
 }
 
-void DynamicBuffer::destroyBufferList(VkDevice device, std::vector<BufferHelper *> *buffers)
+void DynamicBuffer::destroyBufferList(RendererVk *renderer, std::vector<BufferHelper *> *buffers)
 {
     for (BufferHelper *toFree : *buffers)
     {
-        toFree->destroy(device);
+        toFree->destroy(renderer);
         delete toFree;
     }
 
@@ -598,17 +696,17 @@
     mInFlightBuffers.clear();
 }
 
-void DynamicBuffer::destroy(VkDevice device)
+void DynamicBuffer::destroy(RendererVk *renderer)
 {
     reset();
 
-    destroyBufferList(device, &mInFlightBuffers);
-    destroyBufferList(device, &mBufferFreeList);
+    destroyBufferList(renderer, &mInFlightBuffers);
+    destroyBufferList(renderer, &mBufferFreeList);
 
     if (mBuffer)
     {
-        mBuffer->unmap(device);
-        mBuffer->destroy(device);
+        mBuffer->unmap(renderer);
+        mBuffer->destroy(renderer);
         delete mBuffer;
         mBuffer = nullptr;
     }
@@ -666,6 +764,69 @@
     mLastFlushOrInvalidateOffset = 0;
 }
 
+// DynamicShadowBuffer implementation.
+DynamicShadowBuffer::DynamicShadowBuffer() : mInitialSize(0), mSize(0) {}
+
+DynamicShadowBuffer::DynamicShadowBuffer(DynamicShadowBuffer &&other)
+    : mInitialSize(other.mInitialSize), mSize(other.mSize), mBuffer(std::move(other.mBuffer))
+{}
+
+void DynamicShadowBuffer::init(size_t initialSize)
+{
+    mInitialSize = initialSize;
+}
+
+DynamicShadowBuffer::~DynamicShadowBuffer()
+{
+    ASSERT(mBuffer.empty());
+}
+
+angle::Result DynamicShadowBuffer::allocate(size_t sizeInBytes)
+{
+    bool result = true;
+
+    // Delete the current buffer, if any
+    if (!mBuffer.empty())
+    {
+        result &= mBuffer.resize(0);
+    }
+
+    // Cache the new size
+    mSize = std::max(mInitialSize, sizeInBytes);
+
+    // Allocate the buffer
+    result &= mBuffer.resize(mSize);
+
+    // If allocation failed, release the buffer and return error.
+    if (!result)
+    {
+        release();
+        return angle::Result::Stop;
+    }
+
+    return angle::Result::Continue;
+}
+
+void DynamicShadowBuffer::release()
+{
+    reset();
+
+    if (!mBuffer.empty())
+    {
+        (void)mBuffer.resize(0);
+    }
+}
+
+void DynamicShadowBuffer::destroy(VkDevice device)
+{
+    release();
+}
+
+void DynamicShadowBuffer::reset()
+{
+    mSize = 0;
+}
+
 // DescriptorPoolHelper implementation.
 DescriptorPoolHelper::DescriptorPoolHelper() : mFreeDescriptorSets(0) {}
 
@@ -1006,6 +1167,7 @@
     mDynamicQueryPool = nullptr;
     mQueryPoolIndex   = 0;
     mQuery            = 0;
+    mMostRecentSerial = Serial();
 }
 
 angle::Result QueryHelper::beginQuery(ContextVk *contextVk)
@@ -1028,27 +1190,44 @@
     return angle::Result::Continue;
 }
 
+void QueryHelper::beginOcclusionQuery(ContextVk *contextVk,
+                                      PrimaryCommandBuffer *primaryCommands,
+                                      CommandBuffer *renderPassCommandBuffer)
+{
+    const QueryPool &queryPool = getQueryPool();
+    // reset has to be encoded in primary command buffer per spec
+    primaryCommands->resetQueryPool(queryPool, mQuery, 1);
+    renderPassCommandBuffer->beginQuery(queryPool.getHandle(), mQuery, 0);
+    mMostRecentSerial = contextVk->getCurrentQueueSerial();
+}
+
+void QueryHelper::endOcclusionQuery(ContextVk *contextVk, CommandBuffer *renderPassCommandBuffer)
+{
+    renderPassCommandBuffer->endQuery(getQueryPool().getHandle(), mQuery);
+    mMostRecentSerial = contextVk->getCurrentQueueSerial();
+}
+
 angle::Result QueryHelper::flushAndWriteTimestamp(ContextVk *contextVk)
 {
     vk::PrimaryCommandBuffer *primary;
     ANGLE_TRY(contextVk->flushAndGetPrimaryCommandBuffer(&primary));
-    writeTimestamp(primary);
-    mMostRecentSerial = contextVk->getCurrentQueueSerial();
+    writeTimestamp(contextVk, primary);
     return angle::Result::Continue;
 }
 
-void QueryHelper::writeTimestamp(vk::PrimaryCommandBuffer *primary)
+void QueryHelper::writeTimestamp(ContextVk *contextVk, PrimaryCommandBuffer *primary)
 {
     const QueryPool &queryPool = getQueryPool();
     primary->resetQueryPool(queryPool, mQuery, 1);
     primary->writeTimestamp(VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, queryPool, mQuery);
+    mMostRecentSerial = contextVk->getCurrentQueueSerial();
 }
 
 bool QueryHelper::hasPendingWork(ContextVk *contextVk)
 {
     // If the renderer has a queue serial higher than the stored one, the command buffers that
     // recorded this query have already been submitted, so there is no pending work.
-    return mMostRecentSerial == contextVk->getCurrentQueueSerial();
+    return mMostRecentSerial.valid() && (mMostRecentSerial == contextVk->getCurrentQueueSerial());
 }
 
 angle::Result QueryHelper::getUint64ResultNonBlocking(ContextVk *contextVk,
@@ -1056,10 +1235,22 @@
                                                       bool *availableOut)
 {
     ASSERT(valid());
-    VkDevice device                     = contextVk->getDevice();
-    constexpr VkQueryResultFlags kFlags = VK_QUERY_RESULT_64_BIT;
-    VkResult result = getQueryPool().getResults(device, mQuery, 1, sizeof(uint64_t), resultOut,
-                                                sizeof(uint64_t), kFlags);
+    VkResult result;
+
+    // Ensure that we only wait if we have inserted a query in command buffer. Otherwise you will
+    // wait forever and trigger GPU timeout.
+    if (mMostRecentSerial.valid())
+    {
+        VkDevice device                     = contextVk->getDevice();
+        constexpr VkQueryResultFlags kFlags = VK_QUERY_RESULT_64_BIT;
+        result = getQueryPool().getResults(device, mQuery, 1, sizeof(uint64_t), resultOut,
+                                           sizeof(uint64_t), kFlags);
+    }
+    else
+    {
+        result     = VK_SUCCESS;
+        *resultOut = 0;
+    }
 
     if (result == VK_NOT_READY)
     {
@@ -1077,10 +1268,17 @@
 angle::Result QueryHelper::getUint64Result(ContextVk *contextVk, uint64_t *resultOut)
 {
     ASSERT(valid());
-    VkDevice device                     = contextVk->getDevice();
-    constexpr VkQueryResultFlags kFlags = VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT;
-    ANGLE_VK_TRY(contextVk, getQueryPool().getResults(device, mQuery, 1, sizeof(uint64_t),
-                                                      resultOut, sizeof(uint64_t), kFlags));
+    if (mMostRecentSerial.valid())
+    {
+        VkDevice device                     = contextVk->getDevice();
+        constexpr VkQueryResultFlags kFlags = VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT;
+        ANGLE_VK_TRY(contextVk, getQueryPool().getResults(device, mQuery, 1, sizeof(uint64_t),
+                                                          resultOut, sizeof(uint64_t), kFlags));
+    }
+    else
+    {
+        *resultOut = 0;
+    }
     return angle::Result::Continue;
 }
 
@@ -1256,7 +1454,7 @@
         ANGLE_TRY(streamIndices(contextVk, glIndexType, indexCount,
                                 static_cast<const uint8_t *>(srcDataMapping) + elementArrayOffset,
                                 bufferOut, bufferOffsetOut, indexCountOut));
-        elementArrayBufferVk->unmapImpl(contextVk);
+        ANGLE_TRY(elementArrayBufferVk->unmapImpl(contextVk));
         return angle::Result::Continue;
     }
 
@@ -1281,7 +1479,7 @@
     if (contextVk->getRenderer()->getFeatures().extraCopyBufferRegion.enabled)
         copies.push_back({sourceOffset, *bufferOffsetOut + (unitCount + 1) * unitSize, 1});
 
-    ANGLE_TRY(elementArrayBufferVk->copyToBuffer(
+    ANGLE_TRY(elementArrayBufferVk->copyToBufferImpl(
         contextVk, *bufferOut, static_cast<uint32_t>(copies.size()), copies.data()));
     ANGLE_TRY(mDynamicIndexBuffer.flush(contextVk));
     return angle::Result::Continue;
@@ -1442,10 +1640,10 @@
     mDynamicIndirectBuffer.release(contextVk->getRenderer());
 }
 
-void LineLoopHelper::destroy(VkDevice device)
+void LineLoopHelper::destroy(RendererVk *renderer)
 {
-    mDynamicIndexBuffer.destroy(device);
-    mDynamicIndirectBuffer.destroy(device);
+    mDynamicIndexBuffer.destroy(renderer);
+    mDynamicIndirectBuffer.destroy(renderer);
 }
 
 // static
@@ -1496,11 +1694,15 @@
         createInfo = &modifiedCreateInfo;
     }
 
-    ANGLE_VK_TRY(contextVk, mBuffer.init(contextVk->getDevice(), *createInfo));
+    VkMemoryPropertyFlags requiredFlags =
+        (memoryPropertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
+    VkMemoryPropertyFlags preferredFlags =
+        (memoryPropertyFlags & (~VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT));
 
-    VkDeviceSize size;
-    ANGLE_TRY(AllocateBufferMemory(contextVk, memoryPropertyFlags, &mMemoryPropertyFlags, nullptr,
-                                   &mBuffer, &mDeviceMemory, &size));
+    mAllocation.createBufferAndMemory(
+        renderer->getAllocator(), createInfo, requiredFlags, preferredFlags,
+        renderer->getFeatures().persistentlyMappedBuffers.enabled, &mBuffer, &mMemoryPropertyFlags);
+
     mCurrentQueueFamilyIndex = contextVk->getRenderer()->getQueueFamilyIndex();
 
     if (renderer->getFeatures().allocateNonZeroMemory.enabled)
@@ -1508,10 +1710,18 @@
         // This memory can't be mapped, so the buffer must be marked as a transfer destination so we
         // can use a staging resource to initialize it to a non-zero value. If the memory is
         // mappable we do the initialization in AllocateBufferMemory.
-        if ((memoryPropertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0 &&
+        if ((mMemoryPropertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0 &&
             (requestedCreateInfo.usage & VK_BUFFER_USAGE_TRANSFER_DST_BIT) != 0)
         {
-            ANGLE_TRY(initializeNonZeroMemory(contextVk, size));
+            ANGLE_TRY(initializeNonZeroMemory(contextVk, createInfo->size));
+        }
+        else if ((mMemoryPropertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0)
+        {
+            // Can map the memory.
+            // Pick an arbitrary value to initialize non-zero memory for sanitization.
+            constexpr int kNonZeroInitValue = 55;
+            ANGLE_TRY(InitMappableAllocation(renderer->getAllocator(), &mAllocation, mSize,
+                                             kNonZeroInitValue, mMemoryPropertyFlags));
         }
     }
 
@@ -1549,24 +1759,25 @@
     return angle::Result::Continue;
 }
 
-void BufferHelper::destroy(VkDevice device)
+void BufferHelper::destroy(RendererVk *renderer)
 {
-    unmap(device);
+    VkDevice device = renderer->getDevice();
+    unmap(renderer);
     mSize       = 0;
     mViewFormat = nullptr;
 
     mBuffer.destroy(device);
     mBufferView.destroy(device);
-    mDeviceMemory.destroy(device);
+    mAllocation.destroy(renderer->getAllocator());
 }
 
 void BufferHelper::release(RendererVk *renderer)
 {
-    unmap(renderer->getDevice());
+    unmap(renderer);
     mSize       = 0;
     mViewFormat = nullptr;
 
-    renderer->collectGarbageAndReinit(&mUse, &mBuffer, &mBufferView, &mDeviceMemory);
+    renderer->collectGarbageAndReinit(&mUse, &mBuffer, &mBufferView, &mAllocation);
 }
 
 bool BufferHelper::needsOnWriteBarrier(VkAccessFlags writeAccessType,
@@ -1626,47 +1837,39 @@
 
 angle::Result BufferHelper::mapImpl(ContextVk *contextVk)
 {
-    ANGLE_VK_TRY(contextVk, mDeviceMemory.map(contextVk->getDevice(), 0, mSize, 0, &mMappedMemory));
+    ANGLE_VK_TRY(contextVk,
+                 mAllocation.map(contextVk->getRenderer()->getAllocator(), &mMappedMemory));
+
     return angle::Result::Continue;
 }
 
-void BufferHelper::unmap(VkDevice device)
+void BufferHelper::unmap(RendererVk *renderer)
 {
     if (mMappedMemory)
     {
-        mDeviceMemory.unmap(device);
+        mAllocation.unmap(renderer->getAllocator());
         mMappedMemory = nullptr;
     }
 }
 
-angle::Result BufferHelper::flush(ContextVk *contextVk, VkDeviceSize offset, VkDeviceSize size)
+angle::Result BufferHelper::flush(RendererVk *renderer, VkDeviceSize offset, VkDeviceSize size)
 {
     bool hostVisible  = mMemoryPropertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
     bool hostCoherent = mMemoryPropertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
     if (hostVisible && !hostCoherent)
     {
-        VkMappedMemoryRange range = {};
-        range.sType               = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
-        range.memory              = mDeviceMemory.getHandle();
-        range.offset              = offset;
-        range.size                = size;
-        ANGLE_VK_TRY(contextVk, vkFlushMappedMemoryRanges(contextVk->getDevice(), 1, &range));
+        mAllocation.flush(renderer->getAllocator(), offset, size);
     }
     return angle::Result::Continue;
 }
 
-angle::Result BufferHelper::invalidate(ContextVk *contextVk, VkDeviceSize offset, VkDeviceSize size)
+angle::Result BufferHelper::invalidate(RendererVk *renderer, VkDeviceSize offset, VkDeviceSize size)
 {
     bool hostVisible  = mMemoryPropertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
     bool hostCoherent = mMemoryPropertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
     if (hostVisible && !hostCoherent)
     {
-        VkMappedMemoryRange range = {};
-        range.sType               = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
-        range.memory              = mDeviceMemory.getHandle();
-        range.offset              = offset;
-        range.size                = size;
-        ANGLE_VK_TRY(contextVk, vkInvalidateMappedMemoryRanges(contextVk->getDevice(), 1, &range));
+        mAllocation.invalidate(renderer->getAllocator(), offset, size);
     }
     return angle::Result::Continue;
 }
@@ -1736,20 +1939,14 @@
 
 // ImageHelper implementation.
 ImageHelper::ImageHelper()
-    : mFormat(nullptr),
-      mSamples(1),
-      mSerial(rx::kZeroSerial),
-      mCurrentLayout(ImageLayout::Undefined),
-      mCurrentQueueFamilyIndex(std::numeric_limits<uint32_t>::max()),
-      mBaseLevel(0),
-      mMaxLevel(0),
-      mLayerCount(0),
-      mLevelCount(0)
-{}
+{
+    resetCachedProperties();
+}
 
 ImageHelper::ImageHelper(ImageHelper &&other)
     : mImage(std::move(other.mImage)),
       mDeviceMemory(std::move(other.mDeviceMemory)),
+      mImageType(other.mImageType),
       mExtents(other.mExtents),
       mFormat(other.mFormat),
       mSamples(other.mSamples),
@@ -1764,12 +1961,7 @@
       mSubresourceUpdates(std::move(other.mSubresourceUpdates))
 {
     ASSERT(this != &other);
-    other.mCurrentLayout = ImageLayout::Undefined;
-    other.mBaseLevel     = 0;
-    other.mMaxLevel      = 0;
-    other.mLayerCount    = 0;
-    other.mLevelCount    = 0;
-    other.mSerial        = rx::kZeroSerial;
+    other.resetCachedProperties();
 }
 
 ImageHelper::~ImageHelper()
@@ -1777,6 +1969,21 @@
     ASSERT(!valid());
 }
 
+void ImageHelper::resetCachedProperties()
+{
+    mImageType               = VK_IMAGE_TYPE_2D;
+    mExtents                 = {};
+    mFormat                  = nullptr;
+    mSamples                 = 1;
+    mSerial                  = rx::kZeroSerial;
+    mCurrentLayout           = ImageLayout::Undefined;
+    mCurrentQueueFamilyIndex = std::numeric_limits<uint32_t>::max();
+    mBaseLevel               = 0;
+    mMaxLevel                = 0;
+    mLayerCount              = 0;
+    mLevelCount              = 0;
+}
+
 void ImageHelper::initStagingBuffer(RendererVk *renderer,
                                     const Format &format,
                                     VkBufferUsageFlags usageFlags,
@@ -1818,6 +2025,7 @@
 {
     ASSERT(!valid());
 
+    mImageType  = gl_vk::GetImageType(textureType);
     mExtents    = extents;
     mFormat     = &format;
     mSamples    = samples;
@@ -1837,7 +2045,7 @@
     imageInfo.sType                 = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
     imageInfo.pNext                 = externalImageCreateInfo;
     imageInfo.flags                 = GetImageCreateFlags(textureType);
-    imageInfo.imageType             = gl_vk::GetImageType(textureType);
+    imageInfo.imageType             = mImageType;
     imageInfo.format                = format.vkImageFormat;
     imageInfo.extent                = mExtents;
     imageInfo.mipLevels             = mipLevels;
@@ -1854,6 +2062,8 @@
 
     ANGLE_VK_TRY(context, mImage.init(context->getDevice(), imageInfo));
 
+    stageClearIfEmulatedFormat(context);
+
     return angle::Result::Continue;
 }
 
@@ -2012,18 +2222,22 @@
     return angle::Result::Continue;
 }
 
-void ImageHelper::destroy(VkDevice device)
+void ImageHelper::destroy(RendererVk *renderer)
 {
+    VkDevice device = renderer->getDevice();
+
     mImage.destroy(device);
     mDeviceMemory.destroy(device);
-    mStagingBuffer.destroy(device);
+    mStagingBuffer.destroy(renderer);
     mCurrentLayout = ImageLayout::Undefined;
+    mImageType     = VK_IMAGE_TYPE_2D;
     mLayerCount    = 0;
     mLevelCount    = 0;
     mSerial        = rx::kZeroSerial;
 }
 
-void ImageHelper::init2DWeakReference(VkImage handle,
+void ImageHelper::init2DWeakReference(Context *context,
+                                      VkImage handle,
                                       const gl::Extents &glExtents,
                                       const Format &format,
                                       GLint samples)
@@ -2038,6 +2252,8 @@
     mLevelCount    = 1;
 
     mImage.setHandle(handle);
+
+    stageClearIfEmulatedFormat(context);
 }
 
 angle::Result ImageHelper::init2DStaging(Context *context,
@@ -2050,6 +2266,7 @@
     ASSERT(!valid());
 
     gl_vk::GetExtent(glExtents, &mExtents);
+    mImageType  = VK_IMAGE_TYPE_2D;
     mFormat     = &format;
     mSamples    = 1;
     mLayerCount = layerCount;
@@ -2060,7 +2277,7 @@
     VkImageCreateInfo imageInfo     = {};
     imageInfo.sType                 = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
     imageInfo.flags                 = 0;
-    imageInfo.imageType             = VK_IMAGE_TYPE_2D;
+    imageInfo.imageType             = mImageType;
     imageInfo.format                = format.vkImageFormat;
     imageInfo.extent                = mExtents;
     imageInfo.mipLevels             = 1;
@@ -2208,8 +2425,7 @@
     commandBuffer->clearColorImage(mImage, getCurrentLayout(), color, 1, &range);
 }
 
-void ImageHelper::clearDepthStencil(VkImageAspectFlags imageAspectFlags,
-                                    VkImageAspectFlags clearAspectFlags,
+void ImageHelper::clearDepthStencil(VkImageAspectFlags clearAspectFlags,
                                     const VkClearDepthStencilValue &depthStencil,
                                     uint32_t baseMipLevel,
                                     uint32_t levelCount,
@@ -2232,7 +2448,8 @@
     commandBuffer->clearDepthStencilImage(mImage, getCurrentLayout(), depthStencil, 1, &clearRange);
 }
 
-void ImageHelper::clear(const VkClearValue &value,
+void ImageHelper::clear(VkImageAspectFlags aspectFlags,
+                        const VkClearValue &value,
                         uint32_t mipLevel,
                         uint32_t baseArrayLayer,
                         uint32_t layerCount,
@@ -2243,9 +2460,8 @@
 
     if (isDepthStencil)
     {
-        const VkImageAspectFlags aspect = GetDepthStencilAspectFlags(mFormat->actualImageFormat());
-        clearDepthStencil(aspect, aspect, value.depthStencil, mipLevel, 1, baseArrayLayer,
-                          layerCount, commandBuffer);
+        clearDepthStencil(aspectFlags, value.depthStencil, mipLevel, 1, baseArrayLayer, layerCount,
+                          commandBuffer);
     }
     else
     {
@@ -2594,7 +2810,7 @@
         stencilCopy.imageOffset                     = copy.imageOffset;
         stencilCopy.imageExtent                     = copy.imageExtent;
         stencilCopy.imageSubresource.aspectMask     = VK_IMAGE_ASPECT_STENCIL_BIT;
-        mSubresourceUpdates.emplace_back(mStagingBuffer.getCurrentBuffer(), stencilCopy);
+        appendSubresourceUpdate(SubresourceUpdate(mStagingBuffer.getCurrentBuffer(), stencilCopy));
 
         aspectFlags &= ~VK_IMAGE_ASPECT_STENCIL_BIT;
     }
@@ -2618,7 +2834,7 @@
     if (aspectFlags)
     {
         copy.imageSubresource.aspectMask = aspectFlags;
-        mSubresourceUpdates.emplace_back(mStagingBuffer.getCurrentBuffer(), copy);
+        appendSubresourceUpdate(SubresourceUpdate(mStagingBuffer.getCurrentBuffer(), copy));
     }
 
     return angle::Result::Continue;
@@ -2699,7 +2915,7 @@
     gl_vk::GetOffset(offset, &copy.imageOffset);
     gl_vk::GetExtent(glExtents, &copy.imageExtent);
 
-    mSubresourceUpdates.emplace_back(mStagingBuffer.getCurrentBuffer(), copy);
+    appendSubresourceUpdate(SubresourceUpdate(mStagingBuffer.getCurrentBuffer(), copy));
 
     return angle::Result::Continue;
 }
@@ -2742,10 +2958,10 @@
         copy[1].imageSubresource.layerCount     = layerCount;
         copy[1].imageOffset                     = offset;
         copy[1].imageExtent                     = extent;
-        mSubresourceUpdates.emplace_back(bufferHelper, copy[1]);
+        appendSubresourceUpdate(SubresourceUpdate(bufferHelper, copy[1]));
     }
 
-    mSubresourceUpdates.emplace_back(bufferHelper, copy[0]);
+    appendSubresourceUpdate(SubresourceUpdate(bufferHelper, copy[0]));
 
     return angle::Result::Continue;
 }
@@ -2845,7 +3061,7 @@
     gl_vk::GetExtent(dstExtent, &copyToImage.imageExtent);
 
     // 3- enqueue the destination image subresource update
-    mSubresourceUpdates.emplace_back(mStagingBuffer.getCurrentBuffer(), copyToImage);
+    appendSubresourceUpdate(SubresourceUpdate(mStagingBuffer.getCurrentBuffer(), copyToImage));
     return angle::Result::Continue;
 }
 
@@ -2882,50 +3098,54 @@
     gl_vk::GetOffset(destOffset, &copyToImage.dstOffset);
     gl_vk::GetExtent(glExtents, &copyToImage.extent);
 
-    mSubresourceUpdates.emplace_back(image, copyToImage);
+    appendSubresourceUpdate(SubresourceUpdate(image, copyToImage));
 }
 
-void ImageHelper::stageSubresourceRobustClear(const gl::ImageIndex &index, const Format &format)
+void ImageHelper::stageSubresourceClear(const gl::ImageIndex &index)
 {
-    VkClearColorValue initValue =
-        format.hasEmulatedImageChannels() ? kEmulatedInitColorValue : kWebGLInitColorValue;
-    stageSubresourceClear(index, format.intendedFormat(), initValue, kWebGLInitDepthStencilValue);
+    const VkImageAspectFlags aspectFlags = getAspectFlags();
+
+    ASSERT(mFormat);
+    VkClearValue clearValue = GetClearValue(*mFormat);
+    appendSubresourceUpdate(SubresourceUpdate(aspectFlags, clearValue, index));
 }
 
-void ImageHelper::stageSubresourceEmulatedClear(const gl::ImageIndex &index,
-                                                const angle::Format &format)
+void ImageHelper::stageRobustResourceClear(const gl::ImageIndex &index, const vk::Format &format)
 {
-    stageSubresourceClear(index, format, kEmulatedInitColorValue, kWebGLInitDepthStencilValue);
+    const VkImageAspectFlags aspectFlags = GetFormatAspectFlags(format.actualImageFormat());
+
+    // Robust clears must only be staged if we do not have any prior data for this subresource.
+    ASSERT(!isUpdateStaged(index.getLevelIndex(), index.getLayerIndex()));
+    VkClearValue clearValue = GetClearValue(format);
+    appendSubresourceUpdate(SubresourceUpdate(aspectFlags, clearValue, index));
 }
 
-void ImageHelper::stageClearIfEmulatedFormat(const gl::ImageIndex &index, const Format &format)
+void ImageHelper::stageClearIfEmulatedFormat(Context *context)
 {
-    if (format.hasEmulatedImageChannels())
-    {
-        stageSubresourceEmulatedClear(index, format.intendedFormat());
-    }
-}
+    // Skip staging extra clears if robust resource init is enabled.
+    if (!mFormat->hasEmulatedImageChannels() || context->isRobustResourceInitEnabled())
+        return;
 
-void ImageHelper::stageSubresourceClear(const gl::ImageIndex &index,
-                                        const angle::Format &format,
-                                        const VkClearColorValue &colorValue,
-                                        const VkClearDepthStencilValue &depthStencilValue)
-{
     VkClearValue clearValue;
-
-    bool isDepthStencil = format.depthBits > 0 || format.stencilBits > 0;
-    if (isDepthStencil)
+    if (mFormat->intendedFormat().hasDepthOrStencilBits())
     {
-        clearValue.depthStencil = depthStencilValue;
+        clearValue.depthStencil = kRobustInitDepthStencilValue;
     }
     else
     {
-        clearValue.color = colorValue;
+        clearValue.color = kEmulatedInitColorValue;
     }
 
-    // Note that clears can arrive out of order from the front-end with respect to staged changes,
-    // but they are intended to be done first.
-    mSubresourceUpdates.emplace(mSubresourceUpdates.begin(), clearValue, index);
+    const VkImageAspectFlags aspectFlags = getAspectFlags();
+
+    // If the image has an emulated channel and robust resource init is not enabled, always clear
+    // it. These channels will be masked out in future writes, and shouldn't contain uninitialized
+    // values.
+    for (uint32_t level = 0; level < mLevelCount; ++level)
+    {
+        gl::ImageIndex index = gl::ImageIndex::Make2DArrayRange(level, 0, mLayerCount);
+        prependSubresourceUpdate(SubresourceUpdate(aspectFlags, clearValue, index));
+    }
 }
 
 angle::Result ImageHelper::allocateStagingMemory(ContextVk *contextVk,
@@ -3056,8 +3276,8 @@
 
         if (update.updateSource == UpdateSource::Clear)
         {
-            clear(update.clear.value, updateMipLevel, updateBaseLayer, updateLayerCount,
-                  commandBuffer);
+            clear(update.clear.aspectFlags, update.clear.value, updateMipLevel, updateBaseLayer,
+                  updateLayerCount, commandBuffer);
         }
         else if (update.updateSource == UpdateSource::Buffer)
         {
@@ -3359,7 +3579,7 @@
     // If the source image is multisampled, we need to resolve it into a temporary image before
     // performing a readback.
     bool isMultisampled = mSamples > 1;
-    DeviceScoped<ImageHelper> resolvedImage(contextVk->getDevice());
+    RendererScoped<ImageHelper> resolvedImage(contextVk->getRenderer());
 
     ImageHelper *src = this;
 
@@ -3371,14 +3591,16 @@
         resolvedImage.get().retain(&contextVk->getResourceUseList());
     }
 
+    VkImageAspectFlags layoutChangeAspectFlags = src->getAspectFlags();
+
     // Note that although we're reading from the image, we need to update the layout below.
     CommandBuffer *commandBuffer;
     if (isMultisampled)
     {
-        ANGLE_TRY(contextVk->onImageWrite(copyAspectFlags, ImageLayout::TransferDst,
+        ANGLE_TRY(contextVk->onImageWrite(layoutChangeAspectFlags, ImageLayout::TransferDst,
                                           &resolvedImage.get()));
     }
-    ANGLE_TRY(contextVk->onImageRead(copyAspectFlags, ImageLayout::TransferSrc, this));
+    ANGLE_TRY(contextVk->onImageRead(layoutChangeAspectFlags, ImageLayout::TransferSrc, this));
     ANGLE_TRY(contextVk->endRenderPassAndGetCommandBuffer(&commandBuffer));
 
     const angle::Format *readFormat = &mFormat->actualImageFormat();
@@ -3426,7 +3648,7 @@
 
         resolve(&resolvedImage.get(), resolveRegion, commandBuffer);
 
-        ANGLE_TRY(contextVk->onImageRead(copyAspectFlags, ImageLayout::TransferSrc,
+        ANGLE_TRY(contextVk->onImageRead(layoutChangeAspectFlags, ImageLayout::TransferSrc,
                                          &resolvedImage.get()));
 
         // Make the resolved image the target of buffer copy.
@@ -3475,7 +3697,7 @@
         uint8_t *dest = static_cast<uint8_t *>(mapPtr) + reinterpret_cast<ptrdiff_t>(pixels);
         PackPixels(packPixelsParams, *readFormat, area.width * readFormat->pixelBytes,
                    readPixelBuffer, static_cast<uint8_t *>(dest));
-        packBufferVk->unmapImpl(contextVk);
+        ANGLE_TRY(packBufferVk->unmapImpl(contextVk));
     }
     else
     {
@@ -3500,14 +3722,16 @@
     : updateSource(UpdateSource::Image), image{imageIn, copyRegionIn}
 {}
 
-ImageHelper::SubresourceUpdate::SubresourceUpdate(const VkClearValue &clearValue,
+ImageHelper::SubresourceUpdate::SubresourceUpdate(VkImageAspectFlags aspectFlags,
+                                                  const VkClearValue &clearValue,
                                                   const gl::ImageIndex &imageIndex)
     : updateSource(UpdateSource::Clear)
 {
-    clear.value      = clearValue;
-    clear.levelIndex = imageIndex.getLevelIndex();
-    clear.layerIndex = imageIndex.hasLayer() ? imageIndex.getLayerIndex() : 0;
-    clear.layerCount = imageIndex.getLayerCount();
+    clear.aspectFlags = aspectFlags;
+    clear.value       = clearValue;
+    clear.levelIndex  = imageIndex.getLevelIndex();
+    clear.layerIndex  = imageIndex.hasLayer() ? imageIndex.getLayerIndex() : 0;
+    clear.layerCount  = imageIndex.getLayerCount();
 }
 
 ImageHelper::SubresourceUpdate::SubresourceUpdate(const SubresourceUpdate &other)
@@ -3549,6 +3773,18 @@
     return dst.baseArrayLayer == layerIndex && dst.mipLevel == levelIndex;
 }
 
+void ImageHelper::appendSubresourceUpdate(SubresourceUpdate &&update)
+{
+    mSubresourceUpdates.emplace_back(std::move(update));
+    onStateChange(angle::SubjectMessage::SubjectChanged);
+}
+
+void ImageHelper::prependSubresourceUpdate(SubresourceUpdate &&update)
+{
+    mSubresourceUpdates.insert(mSubresourceUpdates.begin(), std::move(update));
+    onStateChange(angle::SubjectMessage::SubjectChanged);
+}
+
 // FramebufferHelper implementation.
 FramebufferHelper::FramebufferHelper() = default;
 
@@ -3792,9 +4028,9 @@
 
 ShaderProgramHelper::~ShaderProgramHelper() = default;
 
-bool ShaderProgramHelper::valid() const
+bool ShaderProgramHelper::valid(const gl::ShaderType shaderType) const
 {
-    return mShaders[gl::ShaderType::Vertex].valid() || mShaders[gl::ShaderType::Compute].valid();
+    return mShaders[shaderType].valid();
 }
 
 void ShaderProgramHelper::destroy(VkDevice device)
diff --git a/src/libANGLE/renderer/vulkan/vk_helpers.h b/src/libANGLE/renderer/vulkan/vk_helpers.h
index d9d46b7..a935a03 100644
--- a/src/libANGLE/renderer/vulkan/vk_helpers.h
+++ b/src/libANGLE/renderer/vulkan/vk_helpers.h
@@ -9,6 +9,7 @@
 #ifndef LIBANGLE_RENDERER_VULKAN_VK_HELPERS_H_
 #define LIBANGLE_RENDERER_VULKAN_VK_HELPERS_H_
 
+#include "common/MemoryBuffer.h"
 #include "libANGLE/renderer/vulkan/ResourceVk.h"
 #include "libANGLE/renderer/vulkan/vk_cache_utils.h"
 
@@ -93,7 +94,7 @@
     void releaseInFlightBuffers(ContextVk *contextVk);
 
     // This frees resources immediately.
-    void destroy(VkDevice device);
+    void destroy(RendererVk *renderer);
 
     BufferHelper *getCurrentBuffer() { return mBuffer; }
 
@@ -106,7 +107,7 @@
     void reset();
     angle::Result allocateNewBuffer(ContextVk *contextVk);
     void releaseBufferListToRenderer(RendererVk *renderer, std::vector<BufferHelper *> *buffers);
-    void destroyBufferList(VkDevice device, std::vector<BufferHelper *> *buffers);
+    void destroyBufferList(RendererVk *renderer, std::vector<BufferHelper *> *buffers);
 
     VkBufferUsageFlags mUsage;
     bool mHostVisible;
@@ -121,6 +122,77 @@
     std::vector<BufferHelper *> mBufferFreeList;
 };
 
+// Based off of the DynamicBuffer class, DynamicShadowBuffer provides
+// a similar conceptually infinitely long buffer that will only be written
+// to and read by the CPU. This can be used to provide CPU cached copies of
+// GPU-read only buffers. The value add here is that when an app requests
+// CPU access to a buffer we can fullfil such a request in O(1) time since
+// we don't need to wait for GPU to be done with in-flight commands.
+//
+// The hidden cost here is that any operation that updates a buffer, either
+// through a buffer sub data update or a buffer-to-buffer copy will have an
+// additional overhead of having to update its CPU only buffer
+class DynamicShadowBuffer : public angle::NonCopyable
+{
+  public:
+    DynamicShadowBuffer();
+    DynamicShadowBuffer(DynamicShadowBuffer &&other);
+    ~DynamicShadowBuffer();
+
+    // Initialize the DynamicShadowBuffer.
+    void init(size_t initialSize);
+
+    // Returns whether this DynamicShadowBuffer is active
+    ANGLE_INLINE bool valid() { return (mSize != 0); }
+
+    // This call will actually allocate a new CPU only memory from the heap.
+    // The size can be different than the one specified during `init`.
+    angle::Result allocate(size_t sizeInBytes);
+
+    ANGLE_INLINE void updateData(const uint8_t *data, size_t size, size_t offset)
+    {
+        ASSERT(!mBuffer.empty());
+        // Memcopy data into the buffer
+        memcpy((mBuffer.data() + offset), data, size);
+    }
+
+    // Map the CPU only buffer and return the pointer. We map the entire buffer for now.
+    ANGLE_INLINE void map(size_t offset, void **mapPtr)
+    {
+        ASSERT(mapPtr);
+        ASSERT(!mBuffer.empty());
+        *mapPtr = mBuffer.data() + offset;
+    }
+
+    // Unmap the CPU only buffer, NOOP for now
+    ANGLE_INLINE void unmap() {}
+
+    // This releases resources when they might currently be in use.
+    void release();
+
+    // This frees resources immediately.
+    void destroy(VkDevice device);
+
+    ANGLE_INLINE uint8_t *getCurrentBuffer()
+    {
+        ASSERT(!mBuffer.empty());
+        return mBuffer.data();
+    }
+
+    ANGLE_INLINE const uint8_t *getCurrentBuffer() const
+    {
+        ASSERT(!mBuffer.empty());
+        return mBuffer.data();
+    }
+
+  private:
+    void reset();
+
+    size_t mInitialSize;
+    size_t mSize;
+    angle::MemoryBuffer mBuffer;
+};
+
 // Uses DescriptorPool to allocate descriptor sets as needed. If a descriptor pool becomes full, we
 // allocate new pools internally as needed. RendererVk takes care of the lifetime of the discarded
 // pools. Note that we used a fixed layout for descriptor pools in ANGLE. Uniform buffers must
@@ -315,8 +387,14 @@
     angle::Result beginQuery(ContextVk *contextVk);
     angle::Result endQuery(ContextVk *contextVk);
 
+    // for occlusion query
+    void beginOcclusionQuery(ContextVk *contextVk,
+                             PrimaryCommandBuffer *primaryCommands,
+                             CommandBuffer *renderPassCommandBuffer);
+    void endOcclusionQuery(ContextVk *contextVk, CommandBuffer *renderPassCommandBuffer);
+
     angle::Result flushAndWriteTimestamp(ContextVk *contextVk);
-    void writeTimestamp(vk::PrimaryCommandBuffer *primary);
+    void writeTimestamp(ContextVk *contextVk, PrimaryCommandBuffer *primary);
 
     Serial getStoredQueueSerial() { return mMostRecentSerial; }
     bool hasPendingWork(ContextVk *contextVk);
@@ -449,7 +527,7 @@
                                       VkDeviceSize *indexIndirectBufferOffsetOut);
 
     void release(ContextVk *contextVk);
-    void destroy(VkDevice device);
+    void destroy(RendererVk *renderer);
 
     static void Draw(uint32_t count, uint32_t baseVertex, CommandBuffer *commandBuffer);
 
@@ -469,13 +547,12 @@
     angle::Result init(ContextVk *contextVk,
                        const VkBufferCreateInfo &createInfo,
                        VkMemoryPropertyFlags memoryPropertyFlags);
-    void destroy(VkDevice device);
+    void destroy(RendererVk *renderer);
 
     void release(RendererVk *renderer);
 
     bool valid() const { return mBuffer.valid(); }
     const Buffer &getBuffer() const { return mBuffer; }
-    const DeviceMemory &getDeviceMemory() const { return mDeviceMemory; }
     VkDeviceSize getSize() const { return mSize; }
     bool isHostVisible() const
     {
@@ -517,13 +594,22 @@
         *ptrOut = mMappedMemory;
         return angle::Result::Continue;
     }
-    void unmap(VkDevice device);
+
+    angle::Result mapWithOffset(ContextVk *contextVk, uint8_t **ptrOut, size_t offset)
+    {
+        uint8_t *mapBufPointer;
+        ANGLE_TRY(map(contextVk, &mapBufPointer));
+        *ptrOut = mapBufPointer + offset;
+        return angle::Result::Continue;
+    }
+
+    void unmap(RendererVk *renderer);
 
     // After a sequence of writes, call flush to ensure the data is visible to the device.
-    angle::Result flush(ContextVk *contextVk, VkDeviceSize offset, VkDeviceSize size);
+    angle::Result flush(RendererVk *renderer, VkDeviceSize offset, VkDeviceSize size);
 
     // After a sequence of writes, call invalidate to ensure the data is visible to the host.
-    angle::Result invalidate(ContextVk *contextVk, VkDeviceSize offset, VkDeviceSize size);
+    angle::Result invalidate(RendererVk *renderer, VkDeviceSize offset, VkDeviceSize size);
 
     void changeQueue(uint32_t newQueueFamilyIndex, CommandBuffer *commandBuffer);
 
@@ -563,7 +649,7 @@
     // Vulkan objects.
     Buffer mBuffer;
     BufferView mBufferView;
-    DeviceMemory mDeviceMemory;
+    Allocation mAllocation;
 
     // Cached properties.
     VkMemoryPropertyFlags mMemoryPropertyFlags;
@@ -609,25 +695,33 @@
 // are the same, they may occasionally be BOTTOM_OF_PIPE and TOP_OF_PIPE respectively.
 enum class ImageLayout
 {
-    Undefined                  = 0,
-    ExternalPreInitialized     = 1,
-    ExternalShadersReadOnly    = 2,
-    ExternalShadersWrite       = 3,
-    TransferSrc                = 4,
-    TransferDst                = 5,
-    ComputeShaderReadOnly      = 6,
-    ComputeShaderWrite         = 7,
-    AllGraphicsShadersReadOnly = 8,
-    AllGraphicsShadersWrite    = 9,
-    ColorAttachment            = 10,
-    DepthStencilAttachment     = 11,
-    Present                    = 12,
+    Undefined                   = 0,
+    ExternalPreInitialized      = 1,
+    ExternalShadersReadOnly     = 2,
+    ExternalShadersWrite        = 3,
+    TransferSrc                 = 4,
+    TransferDst                 = 5,
+    VertexShaderReadOnly        = 6,
+    VertexShaderWrite           = 7,
+    GeometryShaderReadOnly      = 8,
+    GeometryShaderWrite         = 9,
+    FragmentShaderReadOnly      = 10,
+    FragmentShaderWrite         = 11,
+    ComputeShaderReadOnly       = 12,
+    ComputeShaderWrite          = 13,
+    AllGraphicsShadersReadOnly  = 14,
+    AllGraphicsShadersReadWrite = 15,
+    ColorAttachment             = 16,
+    DepthStencilAttachment      = 17,
+    Present                     = 18,
 
-    InvalidEnum = 13,
-    EnumCount   = 13,
+    InvalidEnum = 19,
+    EnumCount   = 19,
 };
 
-class ImageHelper final : public Resource
+VkImageLayout ConvertImageLayoutToVkImageLayout(ImageLayout imageLayout);
+
+class ImageHelper final : public Resource, public angle::Subject
 {
   public:
     ImageHelper();
@@ -706,9 +800,11 @@
     VkImageAspectFlags getAspectFlags() const;
     // True if image contains both depth & stencil aspects
     bool isCombinedDepthStencilFormat() const;
-    void destroy(VkDevice device);
+    void destroy(RendererVk *renderer);
+    void release(RendererVk *renderer) { destroy(renderer); }
 
-    void init2DWeakReference(VkImage handle,
+    void init2DWeakReference(Context *context,
+                             VkImage handle,
                              const gl::Extents &glExtents,
                              const Format &format,
                              GLint samples);
@@ -717,12 +813,14 @@
     const Image &getImage() const { return mImage; }
     const DeviceMemory &getDeviceMemory() const { return mDeviceMemory; }
 
+    VkImageType getType() const { return mImageType; }
     const VkExtent3D &getExtents() const { return mExtents; }
     uint32_t getLayerCount() const { return mLayerCount; }
     uint32_t getLevelCount() const { return mLevelCount; }
     const Format &getFormat() const { return *mFormat; }
     GLint getSamples() const { return mSamples; }
 
+    void setCurrentImageLayout(ImageLayout newLayout) { mCurrentLayout = newLayout; }
     ImageLayout getCurrentImageLayout() const { return mCurrentLayout; }
     VkImageLayout getCurrentLayout() const;
 
@@ -731,7 +829,8 @@
     gl::Extents getLevelExtents2D(uint32_t level) const;
 
     // Clear either color or depth/stencil based on image format.
-    void clear(const VkClearValue &value,
+    void clear(VkImageAspectFlags aspectFlags,
+               const VkClearValue &value,
                uint32_t mipLevel,
                uint32_t baseArrayLayer,
                uint32_t layerCount,
@@ -815,16 +914,9 @@
                                          const gl::Extents &glExtents,
                                          const VkImageType imageType);
 
-    // Stage a clear operation to a clear value based on WebGL requirements.
-    void stageSubresourceRobustClear(const gl::ImageIndex &index, const Format &format);
-
-    // Stage a clear operation to a clear value that initializes emulated channels to the desired
-    // values.
-    void stageSubresourceEmulatedClear(const gl::ImageIndex &index, const angle::Format &format);
-
-    // If the image has emulated channels, we clear them once so as not to leave garbage on those
-    // channels.
-    void stageClearIfEmulatedFormat(const gl::ImageIndex &index, const Format &format);
+    // Stage a clear based on robust resource init.
+    void stageRobustResourceClear(const gl::ImageIndex &index, const vk::Format &format);
+    void stageSubresourceClear(const gl::ImageIndex &index);
 
     // This will use the underlying dynamic buffer to allocate some memory to be used as a src or
     // dst.
@@ -850,7 +942,6 @@
     angle::Result flushAllStagedUpdates(ContextVk *contextVk);
 
     bool isUpdateStaged(uint32_t level, uint32_t layer);
-
     bool hasStagedUpdates() const { return !mSubresourceUpdates.empty(); }
 
     // changeLayout automatically skips the layout change if it's unnecessary.  This function can be
@@ -937,36 +1028,6 @@
                                       GLuint *inputSkipBytes);
 
   private:
-    // Generalized to accept both "primary" and "secondary" command buffers.
-    template <typename CommandBufferT>
-    void forceChangeLayoutAndQueue(VkImageAspectFlags aspectMask,
-                                   ImageLayout newLayout,
-                                   uint32_t newQueueFamilyIndex,
-                                   CommandBufferT *commandBuffer);
-
-    void stageSubresourceClear(const gl::ImageIndex &index,
-                               const angle::Format &format,
-                               const VkClearColorValue &colorValue,
-                               const VkClearDepthStencilValue &depthStencilValue);
-
-    void clearColor(const VkClearColorValue &color,
-                    uint32_t baseMipLevel,
-                    uint32_t levelCount,
-                    uint32_t baseArrayLayer,
-                    uint32_t layerCount,
-                    CommandBuffer *commandBuffer);
-
-    void clearDepthStencil(VkImageAspectFlags imageAspectFlags,
-                           VkImageAspectFlags clearAspectFlags,
-                           const VkClearDepthStencilValue &depthStencil,
-                           uint32_t baseMipLevel,
-                           uint32_t levelCount,
-                           uint32_t baseArrayLayer,
-                           uint32_t layerCount,
-                           CommandBuffer *commandBuffer);
-
-    angle::Result initializeNonZeroMemory(Context *context, VkDeviceSize size);
-
     enum class UpdateSource
     {
         Clear,
@@ -975,6 +1036,7 @@
     };
     struct ClearUpdate
     {
+        VkImageAspectFlags aspectFlags;
         VkClearValue value;
         uint32_t levelIndex;
         uint32_t layerIndex;
@@ -996,7 +1058,9 @@
         SubresourceUpdate();
         SubresourceUpdate(BufferHelper *bufferHelperIn, const VkBufferImageCopy &copyRegion);
         SubresourceUpdate(ImageHelper *image, const VkImageCopy &copyRegion);
-        SubresourceUpdate(const VkClearValue &clearValue, const gl::ImageIndex &imageIndex);
+        SubresourceUpdate(VkImageAspectFlags aspectFlags,
+                          const VkClearValue &clearValue,
+                          const gl::ImageIndex &imageIndex);
         SubresourceUpdate(const SubresourceUpdate &other);
 
         void release(RendererVk *renderer);
@@ -1018,11 +1082,44 @@
         };
     };
 
+    // Generalized to accept both "primary" and "secondary" command buffers.
+    template <typename CommandBufferT>
+    void forceChangeLayoutAndQueue(VkImageAspectFlags aspectMask,
+                                   ImageLayout newLayout,
+                                   uint32_t newQueueFamilyIndex,
+                                   CommandBufferT *commandBuffer);
+
+    // If the image has emulated channels, we clear them once so as not to leave garbage on those
+    // channels.
+    void stageClearIfEmulatedFormat(Context *context);
+
+    void clearColor(const VkClearColorValue &color,
+                    uint32_t baseMipLevel,
+                    uint32_t levelCount,
+                    uint32_t baseArrayLayer,
+                    uint32_t layerCount,
+                    CommandBuffer *commandBuffer);
+
+    void clearDepthStencil(VkImageAspectFlags clearAspectFlags,
+                           const VkClearDepthStencilValue &depthStencil,
+                           uint32_t baseMipLevel,
+                           uint32_t levelCount,
+                           uint32_t baseArrayLayer,
+                           uint32_t layerCount,
+                           CommandBuffer *commandBuffer);
+
+    angle::Result initializeNonZeroMemory(Context *context, VkDeviceSize size);
+
+    void appendSubresourceUpdate(SubresourceUpdate &&update);
+    void prependSubresourceUpdate(SubresourceUpdate &&update);
+    void resetCachedProperties();
+
     // Vulkan objects.
     Image mImage;
     DeviceMemory mDeviceMemory;
 
     // Image properties.
+    VkImageType mImageType;
     VkExtent3D mExtents;
     const Format *mFormat;
     GLint mSamples;
@@ -1177,15 +1274,16 @@
     ShaderProgramHelper();
     ~ShaderProgramHelper();
 
-    bool valid() const;
+    bool valid(const gl::ShaderType shaderType) const;
     void destroy(VkDevice device);
     void release(ContextVk *contextVk);
 
     bool isGraphicsProgram() const
     {
-        ASSERT(mShaders[gl::ShaderType::Vertex].valid() !=
+        ASSERT((mShaders[gl::ShaderType::Vertex].valid() ||
+                mShaders[gl::ShaderType::Fragment].valid()) !=
                mShaders[gl::ShaderType::Compute].valid());
-        return mShaders[gl::ShaderType::Vertex].valid();
+        return !mShaders[gl::ShaderType::Compute].valid();
     }
 
     ShaderAndSerial &getShader(gl::ShaderType shaderType) { return mShaders[shaderType].get(); }
diff --git a/src/libANGLE/renderer/vulkan/vk_mem_alloc_wrapper.cpp b/src/libANGLE/renderer/vulkan/vk_mem_alloc_wrapper.cpp
new file mode 100644
index 0000000..1e59f24
--- /dev/null
+++ b/src/libANGLE/renderer/vulkan/vk_mem_alloc_wrapper.cpp
@@ -0,0 +1,116 @@
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// vma_allocator_wrapper.cpp:
+//    Hides VMA functions so we can use separate warning sets.
+//
+
+#include "vk_mem_alloc_wrapper.h"
+
+#include <vk_mem_alloc.h>
+
+namespace vma
+{
+VkResult InitAllocator(VkPhysicalDevice physicalDevice,
+                       VkDevice device,
+                       VkInstance instance,
+                       VmaAllocator *pAllocator)
+{
+    VmaVulkanFunctions funcs;
+    funcs.vkGetPhysicalDeviceProperties       = vkGetPhysicalDeviceProperties;
+    funcs.vkGetPhysicalDeviceMemoryProperties = vkGetPhysicalDeviceMemoryProperties;
+    funcs.vkAllocateMemory                    = vkAllocateMemory;
+    funcs.vkFreeMemory                        = vkFreeMemory;
+    funcs.vkMapMemory                         = vkMapMemory;
+    funcs.vkUnmapMemory                       = vkUnmapMemory;
+    funcs.vkFlushMappedMemoryRanges           = vkFlushMappedMemoryRanges;
+    funcs.vkInvalidateMappedMemoryRanges      = vkInvalidateMappedMemoryRanges;
+    funcs.vkBindBufferMemory                  = vkBindBufferMemory;
+    funcs.vkBindImageMemory                   = vkBindImageMemory;
+    funcs.vkGetBufferMemoryRequirements       = vkGetBufferMemoryRequirements;
+    funcs.vkGetImageMemoryRequirements        = vkGetImageMemoryRequirements;
+    funcs.vkCreateBuffer                      = vkCreateBuffer;
+    funcs.vkDestroyBuffer                     = vkDestroyBuffer;
+    funcs.vkCreateImage                       = vkCreateImage;
+    funcs.vkDestroyImage                      = vkDestroyImage;
+    funcs.vkCmdCopyBuffer                     = vkCmdCopyBuffer;
+    funcs.vkGetBufferMemoryRequirements2KHR   = vkGetBufferMemoryRequirements2KHR;
+    funcs.vkGetImageMemoryRequirements2KHR    = vkGetImageMemoryRequirements2KHR;
+
+    VmaAllocatorCreateInfo allocatorInfo = {};
+    allocatorInfo.physicalDevice         = physicalDevice;
+    allocatorInfo.device                 = device;
+    allocatorInfo.instance               = instance;
+    allocatorInfo.pVulkanFunctions       = &funcs;
+
+    return vmaCreateAllocator(&allocatorInfo, pAllocator);
+}
+
+void DestroyAllocator(VmaAllocator allocator)
+{
+    vmaDestroyAllocator(allocator);
+}
+
+void FreeMemory(VmaAllocator allocator, VmaAllocation allocation)
+{
+    vmaFreeMemory(allocator, allocation);
+}
+
+VkResult CreateBuffer(VmaAllocator allocator,
+                      const VkBufferCreateInfo *pBufferCreateInfo,
+                      VkMemoryPropertyFlags requiredFlags,
+                      VkMemoryPropertyFlags preferredFlags,
+                      bool persistentlyMappedBuffers,
+                      uint32_t *pMemoryTypeIndexOut,
+                      VkBuffer *pBuffer,
+                      VmaAllocation *pAllocation)
+{
+    VkResult result;
+    VmaAllocationCreateInfo allocationCreateInfo = {};
+    allocationCreateInfo.requiredFlags           = requiredFlags;
+    allocationCreateInfo.preferredFlags          = preferredFlags;
+    allocationCreateInfo.flags = (persistentlyMappedBuffers) ? VMA_ALLOCATION_CREATE_MAPPED_BIT : 0;
+    VmaAllocationInfo allocationInfo = {};
+
+    result = vmaCreateBuffer(allocator, pBufferCreateInfo, &allocationCreateInfo, pBuffer,
+                             pAllocation, &allocationInfo);
+    *pMemoryTypeIndexOut = allocationInfo.memoryType;
+
+    return result;
+}
+
+void GetMemoryTypeProperties(VmaAllocator allocator,
+                             uint32_t memoryTypeIndex,
+                             VkMemoryPropertyFlags *pFlags)
+{
+    vmaGetMemoryTypeProperties(allocator, memoryTypeIndex, pFlags);
+}
+
+VkResult MapMemory(VmaAllocator allocator, VmaAllocation allocation, void **ppData)
+{
+    return vmaMapMemory(allocator, allocation, ppData);
+}
+
+void UnmapMemory(VmaAllocator allocator, VmaAllocation allocation)
+{
+    return vmaUnmapMemory(allocator, allocation);
+}
+
+void FlushAllocation(VmaAllocator allocator,
+                     VmaAllocation allocation,
+                     VkDeviceSize offset,
+                     VkDeviceSize size)
+{
+    vmaFlushAllocation(allocator, allocation, offset, size);
+}
+
+void InvalidateAllocation(VmaAllocator allocator,
+                          VmaAllocation allocation,
+                          VkDeviceSize offset,
+                          VkDeviceSize size)
+{
+    vmaInvalidateAllocation(allocator, allocation, offset, size);
+}
+}  // namespace vma
diff --git a/src/libANGLE/renderer/vulkan/vk_mem_alloc_wrapper.h b/src/libANGLE/renderer/vulkan/vk_mem_alloc_wrapper.h
new file mode 100644
index 0000000..14f2f1c
--- /dev/null
+++ b/src/libANGLE/renderer/vulkan/vk_mem_alloc_wrapper.h
@@ -0,0 +1,58 @@
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// vma_allocator_wrapper.h:
+//    Hides VMA functions so we can use separate warning sets.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_VK_MEM_ALLOC_WRAPPER_H_
+#define LIBANGLE_RENDERER_VULKAN_VK_MEM_ALLOC_WRAPPER_H_
+
+#include <volk.h>
+
+VK_DEFINE_HANDLE(VmaAllocator)
+VK_DEFINE_HANDLE(VmaAllocation)
+
+namespace vma
+{
+VkResult InitAllocator(VkPhysicalDevice physicalDevice,
+                       VkDevice device,
+                       VkInstance instance,
+                       VmaAllocator *pAllocator);
+
+void DestroyAllocator(VmaAllocator allocator);
+
+void FreeMemory(VmaAllocator allocator, VmaAllocation allocation);
+
+VkResult CreateBuffer(VmaAllocator allocator,
+                      const VkBufferCreateInfo *pBufferCreateInfo,
+                      VkMemoryPropertyFlags requiredFlags,
+                      VkMemoryPropertyFlags preferredFlags,
+                      bool persistentlyMappedBuffers,
+                      uint32_t *pMemoryTypeIndexOut,
+                      VkBuffer *pBuffer,
+                      VmaAllocation *pAllocation);
+
+void GetMemoryTypeProperties(VmaAllocator allocator,
+                             uint32_t memoryTypeIndex,
+                             VkMemoryPropertyFlags *pFlags);
+
+VkResult MapMemory(VmaAllocator allocator, VmaAllocation allocation, void **ppData);
+
+void UnmapMemory(VmaAllocator allocator, VmaAllocation allocation);
+
+void FlushAllocation(VmaAllocator allocator,
+                     VmaAllocation allocation,
+                     VkDeviceSize offset,
+                     VkDeviceSize size);
+
+void InvalidateAllocation(VmaAllocator allocator,
+                          VmaAllocation allocation,
+                          VkDeviceSize offset,
+                          VkDeviceSize size);
+
+}  // namespace vma
+
+#endif  // LIBANGLE_RENDERER_VULKAN_VK_MEM_ALLOC_WRAPPER_H_
\ No newline at end of file
diff --git a/src/libANGLE/renderer/vulkan/vk_utils.cpp b/src/libANGLE/renderer/vulkan/vk_utils.cpp
index 3b7db11..df5b9f5 100644
--- a/src/libANGLE/renderer/vulkan/vk_utils.cpp
+++ b/src/libANGLE/renderer/vulkan/vk_utils.cpp
@@ -15,6 +15,7 @@
 #include "libANGLE/renderer/vulkan/DisplayVk.h"
 #include "libANGLE/renderer/vulkan/RendererVk.h"
 #include "libANGLE/renderer/vulkan/ResourceVk.h"
+#include "libANGLE/renderer/vulkan/vk_mem_alloc_wrapper.h"
 
 namespace angle
 {
@@ -86,7 +87,8 @@
         {
             // Can map the memory.
             ANGLE_TRY(vk::InitMappableDeviceMemory(context, deviceMemoryOut,
-                                                   memoryRequirements.size, kNonZeroInitValue));
+                                                   memoryRequirements.size, kNonZeroInitValue,
+                                                   *memoryPropertyFlagsOut));
         }
     }
 
@@ -382,10 +384,11 @@
 // StagingBuffer implementation.
 StagingBuffer::StagingBuffer() : mSize(0) {}
 
-void StagingBuffer::destroy(VkDevice device)
+void StagingBuffer::destroy(RendererVk *renderer)
 {
+    VkDevice device = renderer->getDevice();
     mBuffer.destroy(device);
-    mDeviceMemory.destroy(device);
+    mAllocation.destroy(renderer->getAllocator());
     mSize = 0;
 }
 
@@ -400,14 +403,16 @@
     createInfo.queueFamilyIndexCount = 0;
     createInfo.pQueueFamilyIndices   = nullptr;
 
-    VkMemoryPropertyFlags flags =
-        (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
+    VkMemoryPropertyFlags memoryPropertyOutFlags;
+    VkMemoryPropertyFlags preferredFlags = 0;
+    VkMemoryPropertyFlags requiredFlags =
+        VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
 
-    ANGLE_VK_TRY(context, mBuffer.init(context->getDevice(), createInfo));
-    VkMemoryPropertyFlags flagsOut = 0;
-    VkDeviceSize sizeIgnored;
-    ANGLE_TRY(AllocateBufferMemory(context, flags, &flagsOut, nullptr, &mBuffer, &mDeviceMemory,
-                                   &sizeIgnored));
+    mAllocation.createBufferAndMemory(
+        context->getRenderer()->getAllocator(), &createInfo, requiredFlags, preferredFlags,
+        context->getRenderer()->getFeatures().persistentlyMappedBuffers.enabled, &mBuffer,
+        &memoryPropertyOutFlags);
+
     mSize = static_cast<size_t>(size);
     return angle::Result::Continue;
 }
@@ -415,14 +420,14 @@
 void StagingBuffer::release(ContextVk *contextVk)
 {
     contextVk->addGarbage(&mBuffer);
-    contextVk->addGarbage(&mDeviceMemory);
+    contextVk->addGarbage(&mAllocation);
 }
 
 void StagingBuffer::collectGarbage(RendererVk *renderer, Serial serial)
 {
     vk::GarbageList garbageList;
     garbageList.emplace_back(vk::GetGarbage(&mBuffer));
-    garbageList.emplace_back(vk::GetGarbage(&mDeviceMemory));
+    garbageList.emplace_back(vk::GetGarbage(&mAllocation));
 
     vk::SharedResourceUse sharedUse;
     sharedUse.init();
@@ -430,10 +435,31 @@
     renderer->collectGarbage(std::move(sharedUse), std::move(garbageList));
 }
 
+angle::Result InitMappableAllocation(VmaAllocator allocator,
+                                     Allocation *allocation,
+                                     VkDeviceSize size,
+                                     int value,
+                                     VkMemoryPropertyFlags memoryPropertyFlags)
+{
+    uint8_t *mapPointer;
+    allocation->map(allocator, &mapPointer);
+    memset(mapPointer, value, static_cast<size_t>(size));
+
+    if ((memoryPropertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0)
+    {
+        allocation->flush(allocator, 0, size);
+    }
+
+    allocation->unmap(allocator);
+
+    return angle::Result::Continue;
+}
+
 angle::Result InitMappableDeviceMemory(Context *context,
                                        DeviceMemory *deviceMemory,
                                        VkDeviceSize size,
-                                       int value)
+                                       int value,
+                                       VkMemoryPropertyFlags memoryPropertyFlags)
 {
     VkDevice device = context->getDevice();
 
@@ -441,11 +467,15 @@
     ANGLE_VK_TRY(context, deviceMemory->map(device, 0, VK_WHOLE_SIZE, 0, &mapPointer));
     memset(mapPointer, value, static_cast<size_t>(size));
 
-    VkMappedMemoryRange mappedRange = {};
-    mappedRange.sType               = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
-    mappedRange.memory              = deviceMemory->getHandle();
-    mappedRange.size                = VK_WHOLE_SIZE;
-    ANGLE_VK_TRY(context, vkFlushMappedMemoryRanges(device, 1, &mappedRange));
+    // if the memory type is not host coherent, we perform an explicit flush
+    if ((memoryPropertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0)
+    {
+        VkMappedMemoryRange mappedRange = {};
+        mappedRange.sType               = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
+        mappedRange.memory              = deviceMemory->getHandle();
+        mappedRange.size                = VK_WHOLE_SIZE;
+        ANGLE_VK_TRY(context, vkFlushMappedMemoryRanges(device, 1, &mappedRange));
+    }
 
     deviceMemory->unmap(device);
 
@@ -553,8 +583,9 @@
 // GarbageObject implementation
 // Using c-style casts here to avoid conditional compile for MSVC 32-bit
 //  which fails to compile with reinterpret_cast, requiring static_cast.
-void GarbageObject::destroy(VkDevice device)
+void GarbageObject::destroy(RendererVk *renderer)
 {
+    VkDevice device = renderer->getDevice();
     switch (mHandleType)
     {
         case HandleType::Semaphore:
@@ -615,6 +646,9 @@
         case HandleType::QueryPool:
             vkDestroyQueryPool(device, (VkQueryPool)mHandle, nullptr);
             break;
+        case HandleType::Allocation:
+            vma::FreeMemory(renderer->getAllocator(), (VmaAllocation)mHandle);
+            break;
         default:
             UNREACHABLE();
             break;
diff --git a/src/libANGLE/renderer/vulkan/vk_utils.h b/src/libANGLE/renderer/vulkan/vk_utils.h
index bd61d96..dee8c6a 100644
--- a/src/libANGLE/renderer/vulkan/vk_utils.h
+++ b/src/libANGLE/renderer/vulkan/vk_utils.h
@@ -33,6 +33,7 @@
     PROC(Query)                  \
     PROC(Overlay)                \
     PROC(Program)                \
+    PROC(ProgramPipeline)        \
     PROC(Sampler)                \
     PROC(Semaphore)              \
     PROC(Texture)                \
@@ -141,6 +142,10 @@
     VkDevice getDevice() const;
     RendererVk *getRenderer() const { return mRenderer; }
 
+    // This is a special override needed so we can determine if we need to initialize images.
+    // It corresponds to the EGL or GL extensions depending on the vk::Context type.
+    virtual bool isRobustResourceInitEnabled() const = 0;
+
   protected:
     RendererVk *const mRenderer;
 };
@@ -250,7 +255,7 @@
     GarbageObject &operator=(GarbageObject &&rhs);
 
     bool valid() const { return mHandle != VK_NULL_HANDLE; }
-    void destroy(VkDevice device);
+    void destroy(RendererVk *renderer);
 
     template <typename DerivedT, typename HandleT>
     static GarbageObject Get(WrappedObject<DerivedT, HandleT> *object)
@@ -309,26 +314,31 @@
     StagingBuffer();
     void release(ContextVk *contextVk);
     void collectGarbage(RendererVk *renderer, Serial serial);
-    void destroy(VkDevice device);
+    void destroy(RendererVk *renderer);
 
     angle::Result init(Context *context, VkDeviceSize size, StagingUsage usage);
 
     Buffer &getBuffer() { return mBuffer; }
     const Buffer &getBuffer() const { return mBuffer; }
-    DeviceMemory &getDeviceMemory() { return mDeviceMemory; }
-    const DeviceMemory &getDeviceMemory() const { return mDeviceMemory; }
     size_t getSize() const { return mSize; }
 
   private:
     Buffer mBuffer;
-    DeviceMemory mDeviceMemory;
+    Allocation mAllocation;
     size_t mSize;
 };
 
+angle::Result InitMappableAllocation(VmaAllocator allocator,
+                                     Allocation *allcation,
+                                     VkDeviceSize size,
+                                     int value,
+                                     VkMemoryPropertyFlags memoryPropertyFlags);
+
 angle::Result InitMappableDeviceMemory(vk::Context *context,
                                        vk::DeviceMemory *deviceMemory,
                                        VkDeviceSize size,
-                                       int value);
+                                       int value,
+                                       VkMemoryPropertyFlags memoryPropertyFlags);
 
 angle::Result AllocateBufferMemory(Context *context,
                                    VkMemoryPropertyFlags requestedMemoryPropertyFlags,
diff --git a/src/libANGLE/renderer/vulkan/vk_wrapper.h b/src/libANGLE/renderer/vulkan/vk_wrapper.h
index ecb6f58..c331434 100644
--- a/src/libANGLE/renderer/vulkan/vk_wrapper.h
+++ b/src/libANGLE/renderer/vulkan/vk_wrapper.h
@@ -14,6 +14,7 @@
 #include "volk.h"
 
 #include "libANGLE/renderer/renderer_utils.h"
+#include "libANGLE/renderer/vulkan/vk_mem_alloc_wrapper.h"
 
 namespace rx
 {
@@ -46,7 +47,8 @@
     FUNC(RenderPass)               \
     FUNC(Sampler)                  \
     FUNC(Semaphore)                \
-    FUNC(ShaderModule)
+    FUNC(ShaderModule)             \
+    FUNC(Allocation)
 
 #define ANGLE_COMMA_SEP_FUNC(TYPE) TYPE,
 
@@ -93,6 +95,7 @@
 {
   public:
     HandleT getHandle() const { return mHandle; }
+    void setHandle(HandleT handle) { mHandle = handle; }
     bool valid() const { return (mHandle != VK_NULL_HANDLE); }
 
     const HandleT *ptr() const { return &mHandle; }
@@ -453,6 +456,25 @@
     void unmap(VkDevice device) const;
 };
 
+class Allocation final : public WrappedObject<Allocation, VmaAllocation>
+{
+  public:
+    Allocation() = default;
+    void destroy(VmaAllocator allocator);
+
+    VkResult createBufferAndMemory(VmaAllocator allocator,
+                                   const VkBufferCreateInfo *pBufferCreateInfo,
+                                   VkMemoryPropertyFlags requiredFlags,
+                                   VkMemoryPropertyFlags preferredFlags,
+                                   bool persistentlyMappedBuffers,
+                                   Buffer *buffer,
+                                   VkMemoryPropertyFlags *pMemPropertyOut);
+    VkResult map(VmaAllocator allocator, uint8_t **mapPointer) const;
+    void unmap(VmaAllocator allocator) const;
+    void flush(VmaAllocator allocator, VkDeviceSize offset, VkDeviceSize size);
+    void invalidate(VmaAllocator allocator, VkDeviceSize offset, VkDeviceSize size);
+};
+
 class RenderPass final : public WrappedObject<RenderPass, VkRenderPass>
 {
   public:
@@ -1294,6 +1316,63 @@
     vkUnmapMemory(device, mHandle);
 }
 
+// Allocation implementation.
+ANGLE_INLINE void Allocation::destroy(VmaAllocator allocator)
+{
+    if (valid())
+    {
+        vma::FreeMemory(allocator, mHandle);
+        mHandle = VK_NULL_HANDLE;
+    }
+}
+
+ANGLE_INLINE VkResult Allocation::createBufferAndMemory(VmaAllocator allocator,
+                                                        const VkBufferCreateInfo *pBufferCreateInfo,
+                                                        VkMemoryPropertyFlags requiredFlags,
+                                                        VkMemoryPropertyFlags preferredFlags,
+                                                        bool persistentlyMappedBuffers,
+                                                        Buffer *buffer,
+                                                        VkMemoryPropertyFlags *pMemPropertyOut)
+{
+    ASSERT(!valid());
+    VkResult result;
+    uint32_t memoryTypeIndex;
+    VkBuffer bufferHandle;
+    result =
+        vma::CreateBuffer(allocator, pBufferCreateInfo, requiredFlags, preferredFlags,
+                          persistentlyMappedBuffers, &memoryTypeIndex, &bufferHandle, &mHandle);
+    vma::GetMemoryTypeProperties(allocator, memoryTypeIndex, pMemPropertyOut);
+    buffer->setHandle(bufferHandle);
+
+    return result;
+}
+
+ANGLE_INLINE VkResult Allocation::map(VmaAllocator allocator, uint8_t **mapPointer) const
+{
+    ASSERT(valid());
+    return vma::MapMemory(allocator, mHandle, (void **)mapPointer);
+}
+
+ANGLE_INLINE void Allocation::unmap(VmaAllocator allocator) const
+{
+    ASSERT(valid());
+    vma::UnmapMemory(allocator, mHandle);
+}
+
+ANGLE_INLINE void Allocation::flush(VmaAllocator allocator, VkDeviceSize offset, VkDeviceSize size)
+{
+    ASSERT(valid());
+    vma::FlushAllocation(allocator, mHandle, offset, size);
+}
+
+ANGLE_INLINE void Allocation::invalidate(VmaAllocator allocator,
+                                         VkDeviceSize offset,
+                                         VkDeviceSize size)
+{
+    ASSERT(valid());
+    vma::InvalidateAllocation(allocator, mHandle, offset, size);
+}
+
 // RenderPass implementation.
 ANGLE_INLINE void RenderPass::destroy(VkDevice device)
 {
diff --git a/src/libANGLE/validationEGL.cpp b/src/libANGLE/validationEGL.cpp
index aff624d..24ed7d8 100644
--- a/src/libANGLE/validationEGL.cpp
+++ b/src/libANGLE/validationEGL.cpp
@@ -2140,6 +2140,22 @@
                 }
                 break;
 
+            case EGL_GL_COLORSPACE:
+                if (!displayExtensions.glColorspace)
+                {
+                    return EglBadParameter() << "EGL_GL_COLORSPACE cannot be used "
+                                                "without EGL_KHR_gl_colorspace support.";
+                }
+                switch (value)
+                {
+                    case EGL_GL_COLORSPACE_DEFAULT_EXT:
+                        break;
+                    default:
+                        ANGLE_TRY(ValidateColorspaceAttribute(displayExtensions, value));
+                        break;
+                }
+                break;
+
             case EGL_TEXTURE_INTERNAL_FORMAT_ANGLE:
                 if (!displayExtensions.imageD3D11Texture)
                 {
@@ -3147,12 +3163,26 @@
     return NoError();
 }
 
-Error ValidateGetMscRateCHROMIUM(const Display *display,
-                                 const Surface *eglSurface,
-                                 const EGLint *numerator,
-                                 const EGLint *denominator)
+Error ValidateSyncControlRateANGLE(const Display *display, const Surface *eglSurface)
 {
-    ANGLE_TRY(ValidateSyncControlCHROMIUM(display, eglSurface));
+    ANGLE_TRY(ValidateDisplay(display));
+    ANGLE_TRY(ValidateSurface(display, eglSurface));
+
+    const DisplayExtensions &displayExtensions = display->getExtensions();
+    if (!displayExtensions.syncControlRateANGLE)
+    {
+        return EglBadAccess() << "syncControlRateANGLE extension not active";
+    }
+
+    return NoError();
+}
+
+Error ValidateGetMscRateANGLE(const Display *display,
+                              const Surface *eglSurface,
+                              const EGLint *numerator,
+                              const EGLint *denominator)
+{
+    ANGLE_TRY(ValidateSyncControlRateANGLE(display, eglSurface));
 
     if (numerator == nullptr)
     {
diff --git a/src/libANGLE/validationEGL.h b/src/libANGLE/validationEGL.h
index 48f74c6..df5523a 100644
--- a/src/libANGLE/validationEGL.h
+++ b/src/libANGLE/validationEGL.h
@@ -174,10 +174,10 @@
                                         void *texture,
                                         const AttributeMap &attribs);
 
-Error ValidateGetMscRateCHROMIUM(const Display *display,
-                                 const Surface *surface,
-                                 const EGLint *numerator,
-                                 const EGLint *denominator);
+Error ValidateGetMscRateANGLE(const Display *display,
+                              const Surface *surface,
+                              const EGLint *numerator,
+                              const EGLint *denominator);
 Error ValidateGetSyncValuesCHROMIUM(const Display *display,
                                     const Surface *surface,
                                     const EGLuint64KHR *ust,
diff --git a/src/libANGLE/validationES.cpp b/src/libANGLE/validationES.cpp
index cd3efd3..80f1b3f 100644
--- a/src/libANGLE/validationES.cpp
+++ b/src/libANGLE/validationES.cpp
@@ -161,6 +161,38 @@
     }
 }
 
+bool ValidReadPixelsUnsignedNormalizedDepthType(const Context *context,
+                                                const gl::InternalFormat *info,
+                                                GLenum type)
+{
+    bool supportsReadDepthNV = (context->getExtensions().readDepthNV && (info->depthBits > 0) &&
+                                (info->componentCount == 1));
+    bool isGLES31            = (context->getClientVersion() >= ES_3_1);
+    switch (type)
+    {
+        case GL_UNSIGNED_SHORT:
+            return supportsReadDepthNV ||
+                   (isGLES31 && (info->sizedInternalFormat == GL_DEPTH_COMPONENT16));
+        case GL_UNSIGNED_INT:
+            return supportsReadDepthNV ||
+                   (isGLES31 && ((info->sizedInternalFormat == GL_DEPTH_COMPONENT16) ||
+                                 (info->internalFormat == GL_DEPTH_COMPONENT24)));
+        case GL_UNSIGNED_INT_24_8:
+            return supportsReadDepthNV ||
+                   (isGLES31 && (info->sizedInternalFormat == GL_DEPTH24_STENCIL8));
+        default:
+            return false;
+    }
+}
+
+bool ValidReadPixelsFloatDepthType(const Context *context,
+                                   const gl::InternalFormat *info,
+                                   GLenum type)
+{
+    return context->getExtensions().readDepthNV && (type == GL_FLOAT) &&
+           context->getExtensions().depthBufferFloat2NV && (info->componentCount == 1);
+}
+
 bool ValidReadPixelsFormatType(const Context *context,
                                const gl::InternalFormat *info,
                                GLenum format,
@@ -171,12 +203,21 @@
         case GL_UNSIGNED_NORMALIZED:
             // TODO(geofflang): Don't accept BGRA here.  Some chrome internals appear to try to use
             // ReadPixels with BGRA even if the extension is not present
-            return (format == GL_RGBA && type == GL_UNSIGNED_BYTE && info->pixelBytes >= 1) ||
-                   (context->getExtensions().textureNorm16 && format == GL_RGBA &&
-                    type == GL_UNSIGNED_SHORT && info->pixelBytes >= 2) ||
-                   (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
-                    type == GL_UNSIGNED_BYTE);
-
+            switch (format)
+            {
+                case GL_RGBA:
+                    return ((type == GL_UNSIGNED_BYTE) && info->pixelBytes >= 1) ||
+                           (context->getExtensions().textureNorm16 && (type == GL_UNSIGNED_SHORT) &&
+                            info->pixelBytes >= 2);
+                case GL_BGRA_EXT:
+                    return context->getExtensions().readFormatBGRA && (type == GL_UNSIGNED_BYTE);
+                case GL_STENCIL_INDEX_OES:
+                    return context->getExtensions().readStencilNV && (type == GL_UNSIGNED_BYTE);
+                case GL_DEPTH_COMPONENT:
+                    return ValidReadPixelsUnsignedNormalizedDepthType(context, info, type);
+                default:
+                    return false;
+            }
         case GL_SIGNED_NORMALIZED:
             return (format == GL_RGBA && type == GL_BYTE && info->pixelBytes >= 1) ||
                    (context->getExtensions().textureNorm16 && format == GL_RGBA &&
@@ -189,8 +230,15 @@
             return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
 
         case GL_FLOAT:
-            return (format == GL_RGBA && type == GL_FLOAT);
-
+            switch (format)
+            {
+                case GL_RGBA:
+                    return (type == GL_FLOAT);
+                case GL_DEPTH_COMPONENT:
+                    return ValidReadPixelsFloatDepthType(context, info, type);
+                default:
+                    return false;
+            }
         default:
             UNREACHABLE();
             return false;
@@ -377,7 +425,7 @@
 
 bool ValidateFragmentShaderColorBufferMaskMatch(const Context *context)
 {
-    const Program *program         = context->getState().getLinkedProgram(context);
+    const Program *program         = context->getActiveLinkedProgram();
     const Framebuffer *framebuffer = context->getState().getDrawFramebuffer();
 
     auto drawBufferMask     = framebuffer->getDrawBufferMask().to_ulong();
@@ -388,7 +436,7 @@
 
 bool ValidateFragmentShaderColorBufferTypeMatch(const Context *context)
 {
-    const Program *program         = context->getState().getLinkedProgram(context);
+    const Program *program         = context->getActiveLinkedProgram();
     const Framebuffer *framebuffer = context->getState().getDrawFramebuffer();
 
     return ValidateComponentTypeMasks(program->getDrawBufferTypeMask().to_ulong(),
@@ -400,7 +448,7 @@
 bool ValidateVertexShaderAttributeTypeMatch(const Context *context)
 {
     const auto &glState    = context->getState();
-    const Program *program = context->getState().getLinkedProgram(context);
+    const Program *program = context->getActiveLinkedProgram();
     const VertexArray *vao = context->getState().getVertexArray();
 
     unsigned long stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().to_ulong();
@@ -411,9 +459,9 @@
     vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits);
     vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits);
 
-    return ValidateComponentTypeMasks(program->getAttributesTypeMask().to_ulong(),
-                                      vaoAttribTypeBits, program->getAttributesMask().to_ulong(),
-                                      0xFFFF);
+    return ValidateComponentTypeMasks(
+        program->getExecutable().getAttributesTypeMask().to_ulong(), vaoAttribTypeBits,
+        program->getExecutable().getAttributesMask().to_ulong(), 0xFFFF);
 }
 
 bool IsCompatibleDrawModeWithGeometryShader(PrimitiveMode drawMode,
@@ -682,9 +730,8 @@
 bool ValidateDrawInstancedANGLE(const Context *context)
 {
     // Verify there is at least one active attribute with a divisor of zero
-    const State &state = context->getState();
-
-    Program *program = state.getLinkedProgram(context);
+    const State &state                  = context->getState();
+    const ProgramExecutable *executable = state.getProgramExecutable();
 
     const auto &attribs  = state.getVertexArray()->getVertexAttributes();
     const auto &bindings = state.getVertexArray()->getVertexBindings();
@@ -692,7 +739,7 @@
     {
         const VertexAttribute &attrib = attribs[attributeIndex];
         const VertexBinding &binding  = bindings[attrib.bindingIndex];
-        if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
+        if (executable->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
         {
             return true;
         }
@@ -2221,7 +2268,7 @@
                      GLsizei count)
 {
     const LinkedUniform *uniform = nullptr;
-    Program *programObject       = context->getState().getLinkedProgram(context);
+    Program *programObject       = context->getActiveLinkedProgram();
     return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
            ValidateUniformValue(context, valueType, uniform->type);
 }
@@ -2232,7 +2279,7 @@
                         const GLint *value)
 {
     const LinkedUniform *uniform = nullptr;
-    Program *programObject       = context->getState().getLinkedProgram(context);
+    Program *programObject       = context->getActiveLinkedProgram();
     return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
            ValidateUniform1ivValue(context, uniform->type, count, value);
 }
@@ -2250,7 +2297,7 @@
     }
 
     const LinkedUniform *uniform = nullptr;
-    Program *programObject       = context->getState().getLinkedProgram(context);
+    Program *programObject       = context->getActiveLinkedProgram();
     return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
            ValidateUniformMatrixValue(context, valueType, uniform->type);
 }
@@ -2649,6 +2696,111 @@
     return true;
 }
 
+const char *ValidateProgramDrawStates(const State &state,
+                                      const Extensions &extensions,
+                                      Program *program)
+{
+    if (extensions.multiview || extensions.multiview2)
+    {
+        const int programNumViews     = program->usesMultiview() ? program->getNumViews() : 1;
+        Framebuffer *framebuffer      = state.getDrawFramebuffer();
+        const int framebufferNumViews = framebuffer->getNumViews();
+
+        if (framebufferNumViews != programNumViews)
+        {
+            return gl::err::kMultiviewMismatch;
+        }
+
+        if (state.isTransformFeedbackActiveUnpaused() && framebufferNumViews > 1)
+        {
+            return gl::err::kMultiviewTransformFeedback;
+        }
+
+        if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
+            state.isQueryActive(QueryType::TimeElapsed))
+        {
+            return gl::err::kMultiviewTimerQuery;
+        }
+    }
+
+    // Uniform buffer validation
+    for (unsigned int uniformBlockIndex = 0;
+         uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
+    {
+        const InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
+        GLuint blockBinding                = program->getUniformBlockBinding(uniformBlockIndex);
+        const OffsetBindingPointer<Buffer> &uniformBuffer =
+            state.getIndexedUniformBuffer(blockBinding);
+
+        if (uniformBuffer.get() == nullptr)
+        {
+            // undefined behaviour
+            return gl::err::kUniformBufferUnbound;
+        }
+
+        size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
+        if (uniformBufferSize < uniformBlock.dataSize)
+        {
+            // undefined behaviour
+            return gl::err::kUniformBufferTooSmall;
+        }
+
+        if (extensions.webglCompatibility &&
+            uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
+        {
+            return gl::err::kUniformBufferBoundForTransformFeedback;
+        }
+    }
+
+    return nullptr;
+}
+
+const char *ValidateProgramPipelineDrawStates(const State &state,
+                                              const Extensions &extensions,
+                                              ProgramPipeline *programPipeline)
+{
+    for (const ShaderType shaderType : gl::AllShaderTypes())
+    {
+        Program *program = programPipeline->getShaderProgram(shaderType);
+        if (program)
+        {
+            const char *errorMsg = ValidateProgramDrawStates(state, extensions, program);
+            if (errorMsg)
+            {
+                return errorMsg;
+            }
+        }
+    }
+
+    return nullptr;
+}
+
+const char *ValidateProgramPipelineAttachedPrograms(ProgramPipeline *programPipeline)
+{
+    // An INVALID_OPERATION error is generated by any command that transfers vertices to the
+    // GL or launches compute work if the current set of active
+    // program objects cannot be executed, for reasons including:
+    // - A program object is active for at least one, but not all of the shader
+    // stages that were present when the program was linked.
+    for (const ShaderType shaderType : gl::AllShaderTypes())
+    {
+        Program *shaderProgram = programPipeline->getShaderProgram(shaderType);
+        if (shaderProgram)
+        {
+            ProgramExecutable &executable = shaderProgram->getExecutable();
+            for (const ShaderType programShaderType : executable.getLinkedShaderStages())
+            {
+                if (shaderProgram != programPipeline->getShaderProgram(programShaderType))
+                {
+                    return gl::err::kNotAllStagesOfSeparableProgramUsed;
+                }
+            }
+        }
+    }
+
+    return nullptr;
+}
+
 // Note all errors returned from this function are INVALID_OPERATION except for the draw framebuffer
 // completeness check.
 const char *ValidateDrawStates(const Context *context)
@@ -2759,78 +2911,67 @@
     // If we are running GLES1, there is no current program.
     if (context->getClientVersion() >= Version(2, 0))
     {
-        Program *program = state.getLinkedProgram(context);
-        if (!program)
+        Program *program                 = state.getLinkedProgram(context);
+        ProgramPipeline *programPipeline = state.getProgramPipeline();
+
+        if (program)
+        {
+            // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
+            // vertex shader stage or fragment shader stage is a undefined behaviour.
+            // But ANGLE should clearly generate an INVALID_OPERATION error instead of
+            // produce undefined result.
+            if (!program->getExecutable().hasLinkedShaderStage(ShaderType::Vertex) ||
+                !program->getExecutable().hasLinkedShaderStage(ShaderType::Fragment))
+            {
+                return kNoActiveGraphicsShaderStage;
+            }
+
+            if (!program->validateSamplers(nullptr, context->getCaps()))
+            {
+                return kTextureTypeConflict;
+            }
+
+            const char *errorMsg = ValidateProgramDrawStates(state, extensions, program);
+            if (errorMsg)
+            {
+                return errorMsg;
+            }
+        }
+        else if (programPipeline)
+        {
+            // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
+            // vertex shader stage or fragment shader stage is a undefined behaviour.
+            // But ANGLE should clearly generate an INVALID_OPERATION error instead of
+            // produce undefined result.
+            if (!programPipeline->getExecutable().hasLinkedShaderStage(ShaderType::Vertex) ||
+                !programPipeline->getExecutable().hasLinkedShaderStage(ShaderType::Fragment))
+            {
+                return kNoActiveGraphicsShaderStage;
+            }
+
+            const char *errorMsg = ValidateProgramPipelineAttachedPrograms(programPipeline);
+            if (errorMsg)
+            {
+                return errorMsg;
+            }
+
+            if (!programPipeline->validateSamplers(nullptr, context->getCaps()))
+            {
+                return kTextureTypeConflict;
+            }
+
+            errorMsg = ValidateProgramPipelineDrawStates(state, extensions, programPipeline);
+            if (errorMsg)
+            {
+                return errorMsg;
+            }
+        }
+        else
         {
             return kProgramNotBound;
         }
 
-        // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
-        // vertex shader stage or fragment shader stage is a undefined behaviour.
-        // But ANGLE should clearly generate an INVALID_OPERATION error instead of
-        // produce undefined result.
-        if (!program->hasLinkedShaderStage(ShaderType::Vertex) ||
-            !program->hasLinkedShaderStage(ShaderType::Fragment))
-        {
-            return kNoActiveGraphicsShaderStage;
-        }
-
-        if (!program->validateSamplers(nullptr, context->getCaps()))
-        {
-            return kTextureTypeConflict;
-        }
-
-        if (extensions.multiview || extensions.multiview2)
-        {
-            const int programNumViews     = program->usesMultiview() ? program->getNumViews() : 1;
-            const int framebufferNumViews = framebuffer->getNumViews();
-            if (framebufferNumViews != programNumViews)
-            {
-                return kMultiviewMismatch;
-            }
-
-            if (state.isTransformFeedbackActiveUnpaused() && framebufferNumViews > 1)
-            {
-                return kMultiviewTransformFeedback;
-            }
-
-            if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
-                state.isQueryActive(QueryType::TimeElapsed))
-            {
-                return kMultiviewTimerQuery;
-            }
-        }
-
-        // Uniform buffer validation
-        for (unsigned int uniformBlockIndex = 0;
-             uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
-        {
-            const InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
-            GLuint blockBinding                = program->getUniformBlockBinding(uniformBlockIndex);
-            const OffsetBindingPointer<Buffer> &uniformBuffer =
-                state.getIndexedUniformBuffer(blockBinding);
-
-            if (uniformBuffer.get() == nullptr)
-            {
-                // undefined behaviour
-                return kUniformBufferUnbound;
-            }
-
-            size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
-            if (uniformBufferSize < uniformBlock.dataSize)
-            {
-                // undefined behaviour
-                return kUniformBufferTooSmall;
-            }
-
-            if (extensions.webglCompatibility &&
-                uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
-            {
-                return kUniformBufferBoundForTransformFeedback;
-            }
-        }
-
-        // Do some additonal WebGL-specific validation
+        // Do some additional WebGL-specific validation
         if (extensions.webglCompatibility)
         {
             if (!state.validateSamplerFormats())
@@ -2846,7 +2987,7 @@
             }
 
             // Detect rendering feedback loops for WebGL.
-            if (framebuffer->formsRenderingFeedbackLoopWith(context))
+            if (framebuffer->hasRenderingFeedbackLoop())
             {
                 return kFeedbackLoop;
             }
@@ -2929,11 +3070,11 @@
     // If we are running GLES1, there is no current program.
     if (context->getClientVersion() >= Version(2, 0))
     {
-        Program *program = state.getLinkedProgram(context);
+        Program *program = context->getActiveLinkedProgram();
         ASSERT(program);
 
         // Do geometry shader specific validations
-        if (program->hasLinkedShaderStage(ShaderType::Geometry))
+        if (program->getExecutable().hasLinkedShaderStage(ShaderType::Geometry))
         {
             if (!IsCompatibleDrawModeWithGeometryShader(
                     mode, program->getGeometryShaderInputPrimitiveType()))
@@ -4372,7 +4513,7 @@
                 context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
                 return false;
             }
-            if (!programObject->hasLinkedShaderStage(ShaderType::Compute))
+            if (!programObject->getExecutable().hasLinkedShaderStage(ShaderType::Compute))
             {
                 context->validationError(GL_INVALID_OPERATION, kNoActiveComputeShaderStage);
                 return false;
@@ -4399,7 +4540,7 @@
                 context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
                 return false;
             }
-            if (!programObject->hasLinkedShaderStage(ShaderType::Geometry))
+            if (!programObject->getExecutable().hasLinkedShaderStage(ShaderType::Geometry))
             {
                 context->validationError(GL_INVALID_OPERATION, kNoActiveGeometryShaderStage);
                 return false;
@@ -5621,7 +5762,20 @@
         return false;
     }
 
-    const FramebufferAttachment *readBuffer = readFramebuffer->getReadColorAttachment();
+    const FramebufferAttachment *readBuffer = nullptr;
+    switch (format)
+    {
+        case GL_DEPTH_COMPONENT:
+            readBuffer = readFramebuffer->getDepthAttachment();
+            break;
+        case GL_STENCIL_INDEX_OES:
+            readBuffer = readFramebuffer->getStencilOrDepthStencilAttachment();
+            break;
+        default:
+            readBuffer = readFramebuffer->getReadColorAttachment();
+            break;
+    }
+
     // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
     // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
     // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
@@ -5664,11 +5818,19 @@
     }
 
     GLenum currentFormat = GL_NONE;
-    ANGLE_VALIDATION_TRY(
-        readFramebuffer->getImplementationColorReadFormat(context, &currentFormat));
+    GLenum currentType   = GL_NONE;
 
-    GLenum currentType = GL_NONE;
-    ANGLE_VALIDATION_TRY(readFramebuffer->getImplementationColorReadType(context, &currentType));
+    switch (format)
+    {
+        case GL_DEPTH_COMPONENT:
+        case GL_STENCIL_INDEX_OES:
+            // Only rely on ValidReadPixelsFormatType for depth/stencil formats
+            break;
+        default:
+            currentFormat = readFramebuffer->getImplementationColorReadFormat(context);
+            currentType   = readFramebuffer->getImplementationColorReadType(context);
+            break;
+    }
 
     bool validFormatTypeCombination =
         ValidReadPixelsFormatType(context, readBuffer->getFormat().info, format, type);
diff --git a/src/libANGLE/validationES.h b/src/libANGLE/validationES.h
index ac7d77d..a16ef66 100644
--- a/src/libANGLE/validationES.h
+++ b/src/libANGLE/validationES.h
@@ -756,6 +756,13 @@
     return true;
 }
 
+const char *ValidateProgramDrawStates(const State &state,
+                                      const Extensions &extensions,
+                                      Program *program);
+const char *ValidateProgramPipelineDrawStates(const State &state,
+                                              const Extensions &extensions,
+                                              ProgramPipeline *programPipeline);
+const char *ValidateProgramPipelineAttachedPrograms(ProgramPipeline *programPipeline);
 const char *ValidateDrawStates(const Context *context);
 
 void RecordDrawAttribsError(const Context *context);
diff --git a/src/libANGLE/validationES2.cpp b/src/libANGLE/validationES2.cpp
index 26c1a2b..baca3b9 100644
--- a/src/libANGLE/validationES2.cpp
+++ b/src/libANGLE/validationES2.cpp
@@ -18,6 +18,7 @@
 #include "libANGLE/Fence.h"
 #include "libANGLE/Framebuffer.h"
 #include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/MemoryObject.h"
 #include "libANGLE/Renderbuffer.h"
 #include "libANGLE/Shader.h"
 #include "libANGLE/Texture.h"
@@ -66,149 +67,6 @@
     return false;
 }
 
-template <typename T>
-bool ValidatePathInstances(const Context *context,
-                           GLsizei numPaths,
-                           const void *paths,
-                           PathID pathBase)
-{
-    const auto *array = static_cast<const T *>(paths);
-
-    for (GLsizei i = 0; i < numPaths; ++i)
-    {
-        const GLuint pathName = array[i] + pathBase.value;
-        if (context->isPathGenerated({pathName}) && !context->isPath({pathName}))
-        {
-            context->validationError(GL_INVALID_OPERATION, kNoSuchPath);
-            return false;
-        }
-    }
-    return true;
-}
-
-bool ValidateInstancedPathParameters(const Context *context,
-                                     GLsizei numPaths,
-                                     GLenum pathNameType,
-                                     const void *paths,
-                                     PathID pathBase,
-                                     GLenum transformType,
-                                     const GLfloat *transformValues)
-{
-    if (!context->getExtensions().pathRendering)
-    {
-        context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
-        return false;
-    }
-
-    if (paths == nullptr)
-    {
-        context->validationError(GL_INVALID_VALUE, kInvalidPathNameArray);
-        return false;
-    }
-
-    if (numPaths < 0)
-    {
-        context->validationError(GL_INVALID_VALUE, kInvalidPathNumPaths);
-        return false;
-    }
-
-    if (!angle::IsValueInRangeForNumericType<std::uint32_t>(numPaths))
-    {
-        context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
-        return false;
-    }
-
-    std::uint32_t pathNameTypeSize = 0;
-    std::uint32_t componentCount   = 0;
-
-    switch (pathNameType)
-    {
-        case GL_UNSIGNED_BYTE:
-            pathNameTypeSize = sizeof(GLubyte);
-            if (!ValidatePathInstances<GLubyte>(context, numPaths, paths, pathBase))
-                return false;
-            break;
-
-        case GL_BYTE:
-            pathNameTypeSize = sizeof(GLbyte);
-            if (!ValidatePathInstances<GLbyte>(context, numPaths, paths, pathBase))
-                return false;
-            break;
-
-        case GL_UNSIGNED_SHORT:
-            pathNameTypeSize = sizeof(GLushort);
-            if (!ValidatePathInstances<GLushort>(context, numPaths, paths, pathBase))
-                return false;
-            break;
-
-        case GL_SHORT:
-            pathNameTypeSize = sizeof(GLshort);
-            if (!ValidatePathInstances<GLshort>(context, numPaths, paths, pathBase))
-                return false;
-            break;
-
-        case GL_UNSIGNED_INT:
-            pathNameTypeSize = sizeof(GLuint);
-            if (!ValidatePathInstances<GLuint>(context, numPaths, paths, pathBase))
-                return false;
-            break;
-
-        case GL_INT:
-            pathNameTypeSize = sizeof(GLint);
-            if (!ValidatePathInstances<GLint>(context, numPaths, paths, pathBase))
-                return false;
-            break;
-
-        default:
-            context->validationError(GL_INVALID_ENUM, kInvalidPathNameType);
-            return false;
-    }
-
-    switch (transformType)
-    {
-        case GL_NONE:
-            componentCount = 0;
-            break;
-        case GL_TRANSLATE_X_CHROMIUM:
-        case GL_TRANSLATE_Y_CHROMIUM:
-            componentCount = 1;
-            break;
-        case GL_TRANSLATE_2D_CHROMIUM:
-            componentCount = 2;
-            break;
-        case GL_TRANSLATE_3D_CHROMIUM:
-            componentCount = 3;
-            break;
-        case GL_AFFINE_2D_CHROMIUM:
-        case GL_TRANSPOSE_AFFINE_2D_CHROMIUM:
-            componentCount = 6;
-            break;
-        case GL_AFFINE_3D_CHROMIUM:
-        case GL_TRANSPOSE_AFFINE_3D_CHROMIUM:
-            componentCount = 12;
-            break;
-        default:
-            context->validationError(GL_INVALID_ENUM, kInvalidTransformation);
-            return false;
-    }
-    if (componentCount != 0 && transformValues == nullptr)
-    {
-        context->validationError(GL_INVALID_VALUE, kNoTransformArray);
-        return false;
-    }
-
-    angle::CheckedNumeric<std::uint32_t> checkedSize(0);
-    checkedSize += (numPaths * pathNameTypeSize);
-    checkedSize += (numPaths * sizeof(GLfloat) * componentCount);
-    if (!checkedSize.IsValid())
-    {
-        context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
-        return false;
-    }
-
-    return true;
-}
-
 bool IsValidCopyTextureSourceInternalFormatEnum(GLenum internalFormat)
 {
     // Table 1.1 from the CHROMIUM_copy_texture spec
@@ -673,48 +531,32 @@
                     context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
                     return false;
                 }
-                else
-                {
-                    context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
-                    return false;
-                }
-                break;
+                context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
+                return false;
             case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
                 if (context->getExtensions().textureCompressionDXT3)
                 {
                     context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
                     return false;
                 }
-                else
-                {
-                    context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
-                    return false;
-                }
-                break;
+                context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
+                return false;
             case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
                 if (context->getExtensions().textureCompressionDXT5)
                 {
                     context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
                     return false;
                 }
-                else
-                {
-                    context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
-                    return false;
-                }
-                break;
+                context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
+                return false;
             case GL_ETC1_RGB8_OES:
                 if (context->getExtensions().compressedETC1RGB8TextureOES)
                 {
                     context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
                     return false;
                 }
-                else
-                {
-                    context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
-                    return false;
-                }
-                break;
+                context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
+                return false;
             case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
             case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
             case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
@@ -725,12 +567,8 @@
                     context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
                     return false;
                 }
-                else
-                {
-                    context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
-                    return false;
-                }
-                break;
+                context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
+                return false;
             case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
             case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
             case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
@@ -740,12 +578,8 @@
                     context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
                     return false;
                 }
-                else
-                {
-                    context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
-                    return false;
-                }
-                break;
+                context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
+                return false;
             case GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT:
             case GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT:
             case GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT:
@@ -755,12 +589,8 @@
                     context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
                     return false;
                 }
-                else
-                {
-                    context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
-                    return false;
-                }
-                break;
+                context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
+                return false;
             case GL_DEPTH_COMPONENT:
             case GL_DEPTH_COMPONENT16:
             case GL_DEPTH_COMPONENT32_OES:
@@ -769,12 +599,8 @@
                     context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
                     return false;
                 }
-                else
-                {
-                    context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
-                    return false;
-                }
-                break;
+                context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
+                return false;
             case GL_DEPTH_STENCIL_OES:
             case GL_DEPTH24_STENCIL8_OES:
                 if (context->getExtensions().depthTextureAny() ||
@@ -784,12 +610,8 @@
                     context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
                     return false;
                 }
-                else
-                {
-                    context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
-                    return false;
-                }
-                break;
+                context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
+                return false;
             default:
                 context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
                 return false;
@@ -843,7 +665,18 @@
         case GL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
             return queryOnly && context->getExtensions().robustResourceInitialization;
 
-        // GLES1 emulation: GLES1-specific caps
+        case GL_TEXTURE_RECTANGLE_ANGLE:
+            return context->getExtensions().webglCompatibility;
+    }
+
+    // GLES1 emulation: GLES1-specific caps after this point
+    if (context->getClientVersion().major != 1)
+    {
+        return false;
+    }
+
+    switch (cap)
+    {
         case GL_ALPHA_TEST:
         case GL_VERTEX_ARRAY:
         case GL_NORMAL_ARRAY:
@@ -882,8 +715,6 @@
         case GL_POINT_SPRITE_OES:
             return context->getClientVersion() < Version(2, 0) &&
                    context->getExtensions().pointSpriteOES;
-        case GL_TEXTURE_RECTANGLE_ANGLE:
-            return context->getExtensions().webglCompatibility;
         default:
             return false;
     }
@@ -1085,22 +916,6 @@
     return true;
 }
 
-bool ValidateMatrixMode(const Context *context, GLenum matrixMode)
-{
-    if (!context->getExtensions().pathRendering)
-    {
-        context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
-        return false;
-    }
-
-    if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
-    {
-        context->validationError(GL_INVALID_ENUM, kInvalidMatrixMode);
-        return false;
-    }
-    return true;
-}
-
 bool ValidBlendFunc(const Context *context, GLenum val)
 {
     const Extensions &ext = context->getExtensions();
@@ -1210,6 +1025,18 @@
                                              format, type, imageSize, pixels);
 }
 
+bool IsValidMemoryObjectParamater(const Context *context, GLenum pname)
+{
+    switch (pname)
+    {
+        case GL_DEDICATED_MEMORY_OBJECT_EXT:
+            return true;
+
+        default:
+            return false;
+    }
+}
+
 }  // anonymous namespace
 
 bool ValidateES2TexImageParametersBase(const Context *context,
@@ -1338,10 +1165,14 @@
         if (isSubImage)
         {
             // From the OES_compressed_ETC1_RGB8_texture spec:
+            //
             // INVALID_OPERATION is generated by CompressedTexSubImage2D, TexSubImage2D, or
             // CopyTexSubImage2D if the texture image <level> bound to <target> has internal format
             // ETC1_RGB8_OES.
-            if (actualInternalFormat == GL_ETC1_RGB8_OES)
+            //
+            // This is relaxed if GL_EXT_compressed_ETC1_RGB8_sub_texture is supported.
+            if (actualInternalFormat == GL_ETC1_RGB8_OES &&
+                !context->getExtensions().compressedETC1RGB8SubTexture)
             {
                 context->validationError(GL_INVALID_OPERATION, kInvalidInternalFormat);
                 return false;
@@ -1539,6 +1370,14 @@
                     case GL_UNSIGNED_SHORT:
                     case GL_UNSIGNED_INT:
                         break;
+                    case GL_FLOAT:
+                        if (!context->getExtensions().depthBufferFloat2NV)
+                        {
+                            context->validationError(GL_INVALID_OPERATION,
+                                                     kMismatchedTypeAndFormat);
+                            return false;
+                        }
+                        break;
                     default:
                         context->validationError(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
                         return false;
@@ -1580,36 +1419,24 @@
                     context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
                     return false;
                 }
-                else
-                {
-                    context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
-                    return false;
-                }
-                break;
+                context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
+                return false;
             case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
                 if (context->getExtensions().textureCompressionDXT5)
                 {
                     context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
                     return false;
                 }
-                else
-                {
-                    context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
-                    return false;
-                }
-                break;
+                context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
+                return false;
             case GL_ETC1_RGB8_OES:
                 if (context->getExtensions().compressedETC1RGB8TextureOES)
                 {
                     context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
                     return false;
                 }
-                else
-                {
-                    context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
-                    return false;
-                }
-                break;
+                context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
+                return false;
             case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
             case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
             case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
@@ -1620,12 +1447,8 @@
                     context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
                     return false;
                 }
-                else
-                {
-                    context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
-                    return false;
-                }
-                break;
+                context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
+                return false;
             case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
             case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
             case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
@@ -1635,12 +1458,8 @@
                     context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
                     return false;
                 }
-                else
-                {
-                    context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
-                    return false;
-                }
-                break;
+                context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
+                return false;
             case GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT:
             case GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT:
             case GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT:
@@ -1650,12 +1469,8 @@
                     context->validationError(GL_INVALID_OPERATION, kInvalidFormat);
                     return false;
                 }
-                else
-                {
-                    context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
-                    return false;
-                }
-                break;
+                context->validationError(GL_INVALID_ENUM, kEnumNotSupported);
+                return false;
             case GL_DEPTH_COMPONENT:
             case GL_DEPTH_STENCIL_OES:
                 if (!context->getExtensions().depthTextureANGLE &&
@@ -2656,6 +2471,14 @@
             }
             return true;
 
+        case GL_PROGRAM_PIPELINE:
+            if (context->getProgramPipeline({name}) == nullptr)
+            {
+                context->validationError(GL_INVALID_VALUE, kInvalidProgramPipelineName);
+                return false;
+            }
+            return true;
+
         default:
             context->validationError(GL_INVALID_ENUM, kInvalidIndentifier);
             return false;
@@ -3450,8 +3273,19 @@
         return false;
     }
 
-    UNIMPLEMENTED();
-    return false;
+    const MemoryObject *memory = context->getMemoryObject(memoryObject);
+    if (memory == nullptr)
+    {
+        context->validationError(GL_INVALID_VALUE, kInvalidMemoryObject);
+    }
+
+    if (!IsValidMemoryObjectParamater(context, pname))
+    {
+        context->validationError(GL_INVALID_ENUM, kInvalidMemoryObjectParameter);
+        return false;
+    }
+
+    return true;
 }
 
 bool ValidateGetUnsignedBytevEXT(const Context *context, GLenum pname, const GLubyte *data)
@@ -3503,8 +3337,26 @@
         return false;
     }
 
-    UNIMPLEMENTED();
-    return false;
+    const MemoryObject *memory = context->getMemoryObject(memoryObject);
+    if (memory == nullptr)
+    {
+        context->validationError(GL_INVALID_VALUE, kInvalidMemoryObject);
+        return false;
+    }
+
+    if (memory->isImmutable())
+    {
+        context->validationError(GL_INVALID_OPERATION, kImmutableMemoryObject);
+        return false;
+    }
+
+    if (!IsValidMemoryObjectParamater(context, pname))
+    {
+        context->validationError(GL_INVALID_ENUM, kInvalidMemoryObjectParameter);
+        return false;
+    }
+
+    return true;
 }
 
 bool ValidateTexStorageMem2DEXT(const Context *context,
@@ -3876,799 +3728,6 @@
     return true;
 }
 
-// CHROMIUM_path_rendering
-
-bool ValidateMatrixLoadfCHROMIUM(const Context *context, GLenum matrixMode, const GLfloat *matrix)
-{
-    if (!ValidateMatrixMode(context, matrixMode))
-    {
-        return false;
-    }
-
-    if (matrix == nullptr)
-    {
-        context->validationError(GL_INVALID_OPERATION, kInvalidPathMatrix);
-        return false;
-    }
-
-    return true;
-}
-
-bool ValidateMatrixLoadIdentityCHROMIUM(const Context *context, GLenum matrixMode)
-{
-    return ValidateMatrixMode(context, matrixMode);
-}
-
-bool ValidateGenPathsCHROMIUM(const Context *context, GLsizei range)
-{
-    if (!context->getExtensions().pathRendering)
-    {
-        context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
-        return false;
-    }
-
-    // range = 0 is undefined in NV_path_rendering.
-    // we add stricter semantic check here and require a non zero positive range.
-    if (range <= 0)
-    {
-        context->validationError(GL_INVALID_VALUE, kInvalidRange);
-        return false;
-    }
-
-    if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
-    {
-        context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
-        return false;
-    }
-
-    return true;
-}
-
-bool ValidateDeletePathsCHROMIUM(const Context *context, PathID path, GLsizei range)
-{
-    if (!context->getExtensions().pathRendering)
-    {
-        context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
-        return false;
-    }
-
-    // range = 0 is undefined in NV_path_rendering.
-    // we add stricter semantic check here and require a non zero positive range.
-    if (range <= 0)
-    {
-        context->validationError(GL_INVALID_VALUE, kInvalidRange);
-        return false;
-    }
-
-    angle::CheckedNumeric<std::uint32_t> checkedRange(path.value);
-    checkedRange += range;
-
-    if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
-    {
-        context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
-        return false;
-    }
-    return true;
-}
-
-bool ValidatePathCommandsCHROMIUM(const Context *context,
-                                  PathID path,
-                                  GLsizei numCommands,
-                                  const GLubyte *commands,
-                                  GLsizei numCoords,
-                                  GLenum coordType,
-                                  const void *coords)
-{
-    if (!context->getExtensions().pathRendering)
-    {
-        context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
-        return false;
-    }
-    if (!context->isPathGenerated(path))
-    {
-        context->validationError(GL_INVALID_OPERATION, kNoSuchPath);
-        return false;
-    }
-
-    if (numCommands < 0)
-    {
-        context->validationError(GL_INVALID_VALUE, kInvalidPathNumCommands);
-        return false;
-    }
-    else if (numCommands > 0)
-    {
-        if (!commands)
-        {
-            context->validationError(GL_INVALID_VALUE, kInvalidPathCommandsArray);
-            return false;
-        }
-    }
-
-    if (numCoords < 0)
-    {
-        context->validationError(GL_INVALID_VALUE, kInvalidPathNumCoords);
-        return false;
-    }
-    else if (numCoords > 0)
-    {
-        if (!coords)
-        {
-            context->validationError(GL_INVALID_VALUE, kInvalidPathNumCoordsArray);
-            return false;
-        }
-    }
-
-    std::uint32_t coordTypeSize = 0;
-    switch (coordType)
-    {
-        case GL_BYTE:
-            coordTypeSize = sizeof(GLbyte);
-            break;
-
-        case GL_UNSIGNED_BYTE:
-            coordTypeSize = sizeof(GLubyte);
-            break;
-
-        case GL_SHORT:
-            coordTypeSize = sizeof(GLshort);
-            break;
-
-        case GL_UNSIGNED_SHORT:
-            coordTypeSize = sizeof(GLushort);
-            break;
-
-        case GL_FLOAT:
-            coordTypeSize = sizeof(GLfloat);
-            break;
-
-        default:
-            context->validationError(GL_INVALID_ENUM, kInvalidPathCoordinateType);
-            return false;
-    }
-
-    angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
-    checkedSize += (coordTypeSize * numCoords);
-    if (!checkedSize.IsValid())
-    {
-        context->validationError(GL_INVALID_OPERATION, kIntegerOverflow);
-        return false;
-    }
-
-    // early return skips command data validation when it doesn't exist.
-    if (!commands)
-        return true;
-
-    GLsizei expectedNumCoords = 0;
-    for (GLsizei i = 0; i < numCommands; ++i)
-    {
-        switch (commands[i])
-        {
-            case GL_CLOSE_PATH_CHROMIUM:  // no coordinates.
-                break;
-            case GL_MOVE_TO_CHROMIUM:
-            case GL_LINE_TO_CHROMIUM:
-                expectedNumCoords += 2;
-                break;
-            case GL_QUADRATIC_CURVE_TO_CHROMIUM:
-                expectedNumCoords += 4;
-                break;
-            case GL_CUBIC_CURVE_TO_CHROMIUM:
-                expectedNumCoords += 6;
-                break;
-            case GL_CONIC_CURVE_TO_CHROMIUM:
-                expectedNumCoords += 5;
-                break;
-            default:
-                context->validationError(GL_INVALID_ENUM, kInvalidPathCommand);
-                return false;
-        }
-    }
-
-    if (expectedNumCoords != numCoords)
-    {
-        context->validationError(GL_INVALID_VALUE, kInvalidPathNumCoords);
-        return false;
-    }
-
-    return true;
-}
-
-bool ValidatePathParameterfCHROMIUM(const Context *context,
-                                    PathID path,
-                                    GLenum pname,
-                                    GLfloat value)
-{
-    if (!context->getExtensions().pathRendering)
-    {
-        context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
-        return false;
-    }
-    if (!context->isPathGenerated(path))
-    {
-        context->validationError(GL_INVALID_OPERATION, kNoSuchPath);
-        return false;
-    }
-
-    switch (pname)
-    {
-        case GL_PATH_STROKE_WIDTH_CHROMIUM:
-            if (value < 0.0f)
-            {
-                context->validationError(GL_INVALID_VALUE, kInvalidPathStrokeWidth);
-                return false;
-            }
-            break;
-        case GL_PATH_END_CAPS_CHROMIUM:
-            switch (static_cast<GLenum>(value))
-            {
-                case GL_FLAT_CHROMIUM:
-                case GL_SQUARE_CHROMIUM:
-                case GL_ROUND_CHROMIUM:
-                    break;
-                default:
-                    context->validationError(GL_INVALID_ENUM, kInvalidPathEndCaps);
-                    return false;
-            }
-            break;
-        case GL_PATH_JOIN_STYLE_CHROMIUM:
-            switch (static_cast<GLenum>(value))
-            {
-                case GL_MITER_REVERT_CHROMIUM:
-                case GL_BEVEL_CHROMIUM:
-                case GL_ROUND_CHROMIUM:
-                    break;
-                default:
-                    context->validationError(GL_INVALID_ENUM, kInvalidPathJoinStyle);
-                    return false;
-            }
-            break;
-        case GL_PATH_MITER_LIMIT_CHROMIUM:
-            if (value < 0.0f)
-            {
-                context->validationError(GL_INVALID_VALUE, kInvalidPathMiterLimit);
-                return false;
-            }
-            break;
-
-        case GL_PATH_STROKE_BOUND_CHROMIUM:
-            // no errors, only clamping.
-            break;
-
-        default:
-            context->validationError(GL_INVALID_ENUM, kInvalidPathParameter);
-            return false;
-    }
-    return true;
-}
-
-bool ValidatePathParameteriCHROMIUM(const Context *context, PathID path, GLenum pname, GLint value)
-{
-    // TODO(jmadill): Use proper clamping cast.
-    return ValidatePathParameterfCHROMIUM(context, path, pname, static_cast<GLfloat>(value));
-}
-
-bool ValidateGetPathParameterfvCHROMIUM(const Context *context,
-                                        PathID path,
-                                        GLenum pname,
-                                        const GLfloat *value)
-{
-    if (!context->getExtensions().pathRendering)
-    {
-        context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
-        return false;
-    }
-
-    if (!context->isPathGenerated(path))
-    {
-        context->validationError(GL_INVALID_OPERATION, kNoSuchPath);
-        return false;
-    }
-
-    if (!value)
-    {
-        context->validationError(GL_INVALID_VALUE, kInvalidPathValueArray);
-        return false;
-    }
-
-    switch (pname)
-    {
-        case GL_PATH_STROKE_WIDTH_CHROMIUM:
-        case GL_PATH_END_CAPS_CHROMIUM:
-        case GL_PATH_JOIN_STYLE_CHROMIUM:
-        case GL_PATH_MITER_LIMIT_CHROMIUM:
-        case GL_PATH_STROKE_BOUND_CHROMIUM:
-            break;
-
-        default:
-            context->validationError(GL_INVALID_ENUM, kInvalidPathParameter);
-            return false;
-    }
-
-    return true;
-}
-
-bool ValidateGetPathParameterivCHROMIUM(const Context *context,
-                                        PathID path,
-                                        GLenum pname,
-                                        const GLint *value)
-{
-    return ValidateGetPathParameterfvCHROMIUM(context, path, pname,
-                                              reinterpret_cast<const GLfloat *>(value));
-}
-
-bool ValidatePathStencilFuncCHROMIUM(const Context *context, GLenum func, GLint ref, GLuint mask)
-{
-    if (!context->getExtensions().pathRendering)
-    {
-        context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
-        return false;
-    }
-
-    switch (func)
-    {
-        case GL_NEVER:
-        case GL_ALWAYS:
-        case GL_LESS:
-        case GL_LEQUAL:
-        case GL_EQUAL:
-        case GL_GEQUAL:
-        case GL_GREATER:
-        case GL_NOTEQUAL:
-            break;
-        default:
-            context->validationError(GL_INVALID_ENUM, kInvalidStencil);
-            return false;
-    }
-
-    return true;
-}
-
-// Note that the spec specifies that for the path drawing commands
-// if the path object is not an existing path object the command
-// does nothing and no error is generated.
-// However if the path object exists but has not been specified any
-// commands then an error is generated.
-
-bool ValidateStencilFillPathCHROMIUM(const Context *context,
-                                     PathID path,
-                                     GLenum fillMode,
-                                     GLuint mask)
-{
-    if (!context->getExtensions().pathRendering)
-    {
-        context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
-        return false;
-    }
-    if (context->isPathGenerated(path) && !context->isPath(path))
-    {
-        context->validationError(GL_INVALID_OPERATION, kNoSuchPath);
-        return false;
-    }
-
-    switch (fillMode)
-    {
-        case GL_INVERT:
-        case GL_COUNT_UP_CHROMIUM:
-        case GL_COUNT_DOWN_CHROMIUM:
-            break;
-        default:
-            context->validationError(GL_INVALID_ENUM, kInvalidFillMode);
-            return false;
-    }
-
-    if (!isPow2(mask + 1))
-    {
-        context->validationError(GL_INVALID_VALUE, kInvalidStencilBitMask);
-        return false;
-    }
-
-    return true;
-}
-
-bool ValidateStencilStrokePathCHROMIUM(const Context *context,
-                                       PathID path,
-                                       GLint reference,
-                                       GLuint mask)
-{
-    if (!context->getExtensions().pathRendering)
-    {
-        context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
-        return false;
-    }
-
-    if (context->isPathGenerated(path) && !context->isPath(path))
-    {
-        context->validationError(GL_INVALID_OPERATION, kNoPathOrNoPathData);
-        return false;
-    }
-
-    return true;
-}
-
-bool ValidateCoverPathCHROMIUM(const Context *context, PathID path, GLenum coverMode)
-{
-    if (!context->getExtensions().pathRendering)
-    {
-        context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
-        return false;
-    }
-    if (context->isPathGenerated(path) && !context->isPath(path))
-    {
-        context->validationError(GL_INVALID_OPERATION, kNoSuchPath);
-        return false;
-    }
-
-    switch (coverMode)
-    {
-        case GL_CONVEX_HULL_CHROMIUM:
-        case GL_BOUNDING_BOX_CHROMIUM:
-            break;
-        default:
-            context->validationError(GL_INVALID_ENUM, kInvalidCoverMode);
-            return false;
-    }
-    return true;
-}
-
-bool ValidateCoverFillPathCHROMIUM(const Context *context, PathID path, GLenum coverMode)
-{
-    return ValidateCoverPathCHROMIUM(context, path, coverMode);
-}
-
-bool ValidateCoverStrokePathCHROMIUM(const Context *context, PathID path, GLenum coverMode)
-{
-    return ValidateCoverPathCHROMIUM(context, path, coverMode);
-}
-
-bool ValidateStencilThenCoverFillPathCHROMIUM(const Context *context,
-                                              PathID path,
-                                              GLenum fillMode,
-                                              GLuint mask,
-                                              GLenum coverMode)
-{
-    return ValidateStencilFillPathCHROMIUM(context, path, fillMode, mask) &&
-           ValidateCoverPathCHROMIUM(context, path, coverMode);
-}
-
-bool ValidateStencilThenCoverStrokePathCHROMIUM(const Context *context,
-                                                PathID path,
-                                                GLint reference,
-                                                GLuint mask,
-                                                GLenum coverMode)
-{
-    return ValidateStencilStrokePathCHROMIUM(context, path, reference, mask) &&
-           ValidateCoverPathCHROMIUM(context, path, coverMode);
-}
-
-bool ValidateIsPathCHROMIUM(const Context *context, PathID path)
-{
-    if (!context->getExtensions().pathRendering)
-    {
-        context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
-        return false;
-    }
-    return true;
-}
-
-bool ValidateCoverFillPathInstancedCHROMIUM(const Context *context,
-                                            GLsizei numPaths,
-                                            GLenum pathNameType,
-                                            const void *paths,
-                                            PathID pathBase,
-                                            GLenum coverMode,
-                                            GLenum transformType,
-                                            const GLfloat *transformValues)
-{
-    if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
-                                         transformType, transformValues))
-        return false;
-
-    switch (coverMode)
-    {
-        case GL_CONVEX_HULL_CHROMIUM:
-        case GL_BOUNDING_BOX_CHROMIUM:
-        case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
-            break;
-        default:
-            context->validationError(GL_INVALID_ENUM, kInvalidCoverMode);
-            return false;
-    }
-
-    return true;
-}
-
-bool ValidateCoverStrokePathInstancedCHROMIUM(const Context *context,
-                                              GLsizei numPaths,
-                                              GLenum pathNameType,
-                                              const void *paths,
-                                              PathID pathBase,
-                                              GLenum coverMode,
-                                              GLenum transformType,
-                                              const GLfloat *transformValues)
-{
-    if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
-                                         transformType, transformValues))
-        return false;
-
-    switch (coverMode)
-    {
-        case GL_CONVEX_HULL_CHROMIUM:
-        case GL_BOUNDING_BOX_CHROMIUM:
-        case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
-            break;
-        default:
-            context->validationError(GL_INVALID_ENUM, kInvalidCoverMode);
-            return false;
-    }
-
-    return true;
-}
-
-bool ValidateStencilFillPathInstancedCHROMIUM(const Context *context,
-                                              GLsizei numPaths,
-                                              GLenum pathNameType,
-                                              const void *paths,
-                                              PathID pathBase,
-                                              GLenum fillMode,
-                                              GLuint mask,
-                                              GLenum transformType,
-                                              const GLfloat *transformValues)
-{
-
-    if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
-                                         transformType, transformValues))
-        return false;
-
-    switch (fillMode)
-    {
-        case GL_INVERT:
-        case GL_COUNT_UP_CHROMIUM:
-        case GL_COUNT_DOWN_CHROMIUM:
-            break;
-        default:
-            context->validationError(GL_INVALID_ENUM, kInvalidFillMode);
-            return false;
-    }
-    if (!isPow2(mask + 1))
-    {
-        context->validationError(GL_INVALID_VALUE, kInvalidStencilBitMask);
-        return false;
-    }
-    return true;
-}
-
-bool ValidateStencilStrokePathInstancedCHROMIUM(const Context *context,
-                                                GLsizei numPaths,
-                                                GLenum pathNameType,
-                                                const void *paths,
-                                                PathID pathBase,
-                                                GLint reference,
-                                                GLuint mask,
-                                                GLenum transformType,
-                                                const GLfloat *transformValues)
-{
-    if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
-                                         transformType, transformValues))
-        return false;
-
-    // no more validation here.
-
-    return true;
-}
-
-bool ValidateStencilThenCoverFillPathInstancedCHROMIUM(const Context *context,
-                                                       GLsizei numPaths,
-                                                       GLenum pathNameType,
-                                                       const void *paths,
-                                                       PathID pathBase,
-                                                       GLenum fillMode,
-                                                       GLuint mask,
-                                                       GLenum coverMode,
-                                                       GLenum transformType,
-                                                       const GLfloat *transformValues)
-{
-    if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
-                                         transformType, transformValues))
-        return false;
-
-    switch (coverMode)
-    {
-        case GL_CONVEX_HULL_CHROMIUM:
-        case GL_BOUNDING_BOX_CHROMIUM:
-        case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
-            break;
-        default:
-            context->validationError(GL_INVALID_ENUM, kInvalidCoverMode);
-            return false;
-    }
-
-    switch (fillMode)
-    {
-        case GL_INVERT:
-        case GL_COUNT_UP_CHROMIUM:
-        case GL_COUNT_DOWN_CHROMIUM:
-            break;
-        default:
-            context->validationError(GL_INVALID_ENUM, kInvalidFillMode);
-            return false;
-    }
-    if (!isPow2(mask + 1))
-    {
-        context->validationError(GL_INVALID_VALUE, kInvalidStencilBitMask);
-        return false;
-    }
-
-    return true;
-}
-
-bool ValidateStencilThenCoverStrokePathInstancedCHROMIUM(const Context *context,
-                                                         GLsizei numPaths,
-                                                         GLenum pathNameType,
-                                                         const void *paths,
-                                                         PathID pathBase,
-                                                         GLint reference,
-                                                         GLuint mask,
-                                                         GLenum coverMode,
-                                                         GLenum transformType,
-                                                         const GLfloat *transformValues)
-{
-    if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
-                                         transformType, transformValues))
-        return false;
-
-    switch (coverMode)
-    {
-        case GL_CONVEX_HULL_CHROMIUM:
-        case GL_BOUNDING_BOX_CHROMIUM:
-        case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
-            break;
-        default:
-            context->validationError(GL_INVALID_ENUM, kInvalidCoverMode);
-            return false;
-    }
-
-    return true;
-}
-
-bool ValidateBindFragmentInputLocationCHROMIUM(const Context *context,
-                                               ShaderProgramID program,
-                                               GLint location,
-                                               const GLchar *name)
-{
-    if (!context->getExtensions().pathRendering)
-    {
-        context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
-        return false;
-    }
-
-    const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
-    if (location >= MaxLocation)
-    {
-        context->validationError(GL_INVALID_VALUE, kInvalidVaryingLocation);
-        return false;
-    }
-
-    const auto *programObject = context->getProgramNoResolveLink(program);
-    if (!programObject)
-    {
-        context->validationError(GL_INVALID_OPERATION, kProgramNotBound);
-        return false;
-    }
-
-    if (!name)
-    {
-        context->validationError(GL_INVALID_VALUE, kMissingName);
-        return false;
-    }
-
-    if (angle::BeginsWith(name, "gl_"))
-    {
-        context->validationError(GL_INVALID_OPERATION, kNameBeginsWithGL);
-        return false;
-    }
-
-    return true;
-}
-
-bool ValidateProgramPathFragmentInputGenCHROMIUM(const Context *context,
-                                                 ShaderProgramID program,
-                                                 GLint location,
-                                                 GLenum genMode,
-                                                 GLint components,
-                                                 const GLfloat *coeffs)
-{
-    if (!context->getExtensions().pathRendering)
-    {
-        context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
-        return false;
-    }
-
-    const auto *programObject = context->getProgramResolveLink(program);
-    if (!programObject || programObject->isFlaggedForDeletion())
-    {
-        context->validationError(GL_INVALID_OPERATION, kProgramDoesNotExist);
-        return false;
-    }
-
-    if (!programObject->isLinked())
-    {
-        context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
-        return false;
-    }
-
-    switch (genMode)
-    {
-        case GL_NONE:
-            if (components != 0)
-            {
-                context->validationError(GL_INVALID_VALUE, kInvalidComponents);
-                return false;
-            }
-            break;
-
-        case GL_OBJECT_LINEAR_CHROMIUM:
-        case GL_EYE_LINEAR_CHROMIUM:
-        case GL_CONSTANT_CHROMIUM:
-            if (components < 1 || components > 4)
-            {
-                context->validationError(GL_INVALID_VALUE, kInvalidComponents);
-                return false;
-            }
-            if (!coeffs)
-            {
-                context->validationError(GL_INVALID_VALUE, kInvalidPathCoefficientsArray);
-                return false;
-            }
-            break;
-
-        default:
-            context->validationError(GL_INVALID_ENUM, kInvalidPathGenMode);
-            return false;
-    }
-
-    // If the location is -1 then the command is silently ignored
-    // and no further validation is needed.
-    if (location == -1)
-        return true;
-
-    const auto &binding = programObject->getFragmentInputBindingInfo(location);
-
-    if (!binding.valid)
-    {
-        context->validationError(GL_INVALID_OPERATION, kInvalidFragmentInputBinding);
-        return false;
-    }
-
-    if (binding.type != GL_NONE)
-    {
-        GLint expectedComponents = 0;
-        switch (binding.type)
-        {
-            case GL_FLOAT:
-                expectedComponents = 1;
-                break;
-            case GL_FLOAT_VEC2:
-                expectedComponents = 2;
-                break;
-            case GL_FLOAT_VEC3:
-                expectedComponents = 3;
-                break;
-            case GL_FLOAT_VEC4:
-                expectedComponents = 4;
-                break;
-            default:
-                context->validationError(GL_INVALID_OPERATION, kFragmentInputTypeNotFloatingPoint);
-                return false;
-        }
-        if (expectedComponents != components && genMode != GL_NONE)
-        {
-            context->validationError(GL_INVALID_OPERATION, kInvalidPathComponents);
-            return false;
-        }
-    }
-    return true;
-}
-
 bool ValidateCopyTextureCHROMIUM(const Context *context,
                                  TextureID sourceId,
                                  GLint sourceLevel,
@@ -5184,7 +4243,8 @@
         return false;
     }
 
-    if (programObject->getAttachedShader(shaderObject->getType()))
+    if (programObject->getAttachedShader(shaderObject->getType()) &&
+        !programObject->getState().isShaderMarkedForDetach(shaderObject->getType()))
     {
         context->validationError(GL_INVALID_OPERATION, kShaderAttachmentHasShader);
         return false;
diff --git a/src/libANGLE/validationES3.cpp b/src/libANGLE/validationES3.cpp
index 493f0da..9fb94b0 100644
--- a/src/libANGLE/validationES3.cpp
+++ b/src/libANGLE/validationES3.cpp
@@ -358,7 +358,8 @@
         return false;
     }
 
-    if (IsASTC2DFormat(format) && !context->getExtensions().textureCompressionASTCHDRKHR)
+    if (IsASTC2DFormat(format) && !(context->getExtensions().textureCompressionASTCHDRKHR ||
+                                    context->getExtensions().textureCompressionSliced3dASTCKHR))
     {
         // GL_KHR_texture_compression_astc_hdr, TEXTURE_3D is not supported without HDR profile
         context->validationError(GL_INVALID_OPERATION, kInternalFormatRequiresTexture2DArrayASTC);
@@ -556,7 +557,9 @@
                 return false;
             }
 
-            if (actualInternalFormat == GL_ETC1_RGB8_OES)
+            // GL_EXT_compressed_ETC1_RGB8_sub_texture allows this format
+            if (actualInternalFormat == GL_ETC1_RGB8_OES &&
+                !context->getExtensions().compressedETC1RGB8SubTexture)
             {
                 context->validationError(GL_INVALID_OPERATION, kInvalidInternalFormat);
                 return false;
diff --git a/src/libANGLE/validationES31.cpp b/src/libANGLE/validationES31.cpp
index 676371a..dab1e72 100644
--- a/src/libANGLE/validationES31.cpp
+++ b/src/libANGLE/validationES31.cpp
@@ -11,6 +11,7 @@
 #include "libANGLE/Context.h"
 #include "libANGLE/ErrorStrings.h"
 #include "libANGLE/Framebuffer.h"
+#include "libANGLE/ProgramExecutable.h"
 #include "libANGLE/VertexArray.h"
 #include "libANGLE/validationES.h"
 #include "libANGLE/validationES2_autogen.h"
@@ -1359,10 +1360,10 @@
         return false;
     }
 
-    const State &state = context->getState();
-    Program *program   = state.getLinkedProgram(context);
+    const State &state                  = context->getState();
+    const ProgramExecutable *executable = state.getProgramExecutable();
 
-    if (program == nullptr || !program->hasLinkedShaderStage(ShaderType::Compute))
+    if (executable == nullptr || !executable->hasLinkedShaderStage(ShaderType::Compute))
     {
         context->validationError(GL_INVALID_OPERATION, kNoActiveProgramWithComputeShader);
         return false;
@@ -1396,10 +1397,10 @@
         return false;
     }
 
-    const State &state = context->getState();
-    Program *program   = state.getLinkedProgram(context);
+    const State &state                  = context->getState();
+    const ProgramExecutable *executable = state.getProgramExecutable();
 
-    if (program == nullptr || !program->hasLinkedShaderStage(ShaderType::Compute))
+    if (executable == nullptr || !executable->hasLinkedShaderStage(ShaderType::Compute))
     {
         context->validationError(GL_INVALID_OPERATION, kNoActiveProgramWithComputeShader);
         return false;
@@ -1727,18 +1728,108 @@
 bool ValidateUseProgramStages(const Context *context,
                               ProgramPipelineID pipeline,
                               GLbitfield stages,
-                              ShaderProgramID program)
+                              ShaderProgramID programId)
 {
-    UNIMPLEMENTED();
-    return false;
+    if (context->getClientVersion() < ES_3_1)
+    {
+        context->validationError(GL_INVALID_OPERATION, kES31Required);
+        return false;
+    }
+
+    // GL_INVALID_VALUE is generated if shaders contains set bits that are not recognized, and is
+    // not the reserved value GL_ALL_SHADER_BITS.
+    const GLbitfield knownShaderBits =
+        GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT | GL_COMPUTE_SHADER_BIT;
+    if ((stages & ~knownShaderBits) && (stages != GL_ALL_SHADER_BITS))
+    {
+        context->validationError(GL_INVALID_VALUE, kUnrecognizedShaderStageBit);
+        return false;
+    }
+
+    // GL_INVALID_OPERATION is generated if pipeline is not a name previously returned from a call
+    // to glGenProgramPipelines or if such a name has been deleted by a call to
+    // glDeleteProgramPipelines.
+    if (!context->isProgramPipelineGenerated({pipeline}))
+    {
+        context->validationError(GL_INVALID_OPERATION, kObjectNotGenerated);
+        return false;
+    }
+
+    // If program is zero, or refers to a program object with no valid shader executable for a given
+    // stage, it is as if the pipeline object has no programmable stage configured for the indicated
+    // shader stages.
+    if (programId.value == 0)
+    {
+        return true;
+    }
+
+    Program *program = context->getProgramNoResolveLink(programId);
+    if (!program)
+    {
+        context->validationError(GL_INVALID_VALUE, kProgramDoesNotExist);
+        return false;
+    }
+
+    // GL_INVALID_OPERATION is generated if program refers to a program object that was not linked
+    // with its GL_PROGRAM_SEPARABLE status set.
+    // resolveLink() may not have been called if glCreateShaderProgramv() was not used and
+    // glDetachShader() was not called.
+    program->resolveLink(context);
+    if (!program->isSeparable())
+    {
+        context->validationError(GL_INVALID_OPERATION, kProgramNotSeparable);
+        return false;
+    }
+
+    // GL_INVALID_OPERATION is generated if program refers to a program object that has not been
+    // successfully linked.
+    if (!program->isLinked())
+    {
+        context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
+        return false;
+    }
+
+    return true;
 }
 
 bool ValidateActiveShaderProgram(const Context *context,
                                  ProgramPipelineID pipeline,
-                                 ShaderProgramID program)
+                                 ShaderProgramID programId)
 {
-    UNIMPLEMENTED();
-    return false;
+    // An INVALID_OPERATION error is generated if pipeline is not a name returned from a previous
+    // call to GenProgramPipelines or if such a name has since been deleted by
+    // DeleteProgramPipelines.
+    if (!context->isProgramPipelineGenerated({pipeline}))
+    {
+        context->validationError(GL_INVALID_OPERATION, kObjectNotGenerated);
+        return false;
+    }
+
+    // An INVALID_VALUE error is generated if program is not zero and is not the name of either a
+    // program or shader object.
+    if ((programId.value != 0) && !context->isProgram(programId) && !context->isShader(programId))
+    {
+        context->validationError(GL_INVALID_VALUE, kProgramDoesNotExist);
+        return false;
+    }
+
+    // An INVALID_OPERATION error is generated if program is the name of a shader object.
+    if (context->isShader(programId))
+    {
+        context->validationError(GL_INVALID_OPERATION, kExpectedProgramName);
+        return false;
+    }
+
+    // An INVALID_OPERATION error is generated if program is not zero and has not been linked, or
+    // was last linked unsuccessfully. The active program is not modified.
+    Program *program = context->getProgramNoResolveLink(programId);
+    if ((programId.value != 0) && !program->isLinked())
+    {
+        context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
+        return false;
+    }
+
+    return true;
 }
 
 bool ValidateCreateShaderProgramv(const Context *context,
@@ -1746,8 +1837,28 @@
                                   GLsizei count,
                                   const GLchar *const *strings)
 {
-    UNIMPLEMENTED();
-    return false;
+    if (context->getClientVersion() < ES_3_1)
+    {
+        context->validationError(GL_INVALID_OPERATION, kES31Required);
+        return false;
+    }
+
+    // GL_INVALID_ENUM is generated if type is not an accepted shader type.
+    if ((type != ShaderType::Vertex) && (type != ShaderType::Fragment) &&
+        (type != ShaderType::Compute))
+    {
+        context->validationError(GL_INVALID_ENUM, kInvalidShaderType);
+        return false;
+    }
+
+    // GL_INVALID_VALUE is generated if count is negative.
+    if (count < 0)
+    {
+        context->validationError(GL_INVALID_VALUE, kNegativeCount);
+        return false;
+    }
+
+    return true;
 }
 
 bool ValidateGetProgramPipelineiv(const Context *context,
@@ -1755,14 +1866,50 @@
                                   GLenum pname,
                                   const GLint *params)
 {
-    UNIMPLEMENTED();
-    return false;
+    // An INVALID_OPERATION error is generated if pipeline is not a name returned from a previous
+    // call to GenProgramPipelines or if such a name has since been deleted by
+    // DeleteProgramPipelines.
+    if ((pipeline.value == 0) || (!context->isProgramPipelineGenerated(pipeline)))
+    {
+        context->validationError(GL_INVALID_OPERATION, kProgramPipelineDoesNotExist);
+        return false;
+    }
+
+    // An INVALID_ENUM error is generated if pname is not ACTIVE_PROGRAM,
+    // INFO_LOG_LENGTH, VALIDATE_STATUS, or one of the type arguments in
+    // table 7.1.
+    switch (pname)
+    {
+        case GL_ACTIVE_PROGRAM:
+        case GL_INFO_LOG_LENGTH:
+        case GL_VALIDATE_STATUS:
+        case GL_VERTEX_SHADER:
+        case GL_FRAGMENT_SHADER:
+        case GL_COMPUTE_SHADER:
+            break;
+
+        default:
+            context->validationError(GL_INVALID_ENUM, kInvalidPname);
+            return false;
+    }
+
+    return true;
 }
 
 bool ValidateValidateProgramPipeline(const Context *context, ProgramPipelineID pipeline)
 {
-    UNIMPLEMENTED();
-    return false;
+    if (pipeline.value == 0)
+    {
+        return false;
+    }
+
+    if (!context->isProgramPipelineGenerated(pipeline))
+    {
+        context->validationError(GL_INVALID_OPERATION, kProgramPipelineDoesNotExist);
+        return false;
+    }
+
+    return true;
 }
 
 bool ValidateGetProgramPipelineInfoLog(const Context *context,
@@ -1771,8 +1918,19 @@
                                        const GLsizei *length,
                                        const GLchar *infoLog)
 {
-    UNIMPLEMENTED();
-    return false;
+    if (bufSize < 0)
+    {
+        context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
+        return false;
+    }
+
+    if (!context->isProgramPipelineGenerated(pipeline))
+    {
+        context->validationError(GL_INVALID_VALUE, kProgramPipelineDoesNotExist);
+        return false;
+    }
+
+    return true;
 }
 
 bool ValidateMemoryBarrier(const Context *context, GLbitfield barriers)
diff --git a/src/libANGLE/validationESEXT_autogen.h b/src/libANGLE/validationESEXT_autogen.h
index b37095c..9c17d07 100644
--- a/src/libANGLE/validationESEXT_autogen.h
+++ b/src/libANGLE/validationESEXT_autogen.h
@@ -695,127 +695,12 @@
 
 // GL_CHROMIUM_framebuffer_mixed_samples
 bool ValidateCoverageModulationCHROMIUM(const Context *context, GLenum components);
-bool ValidateMatrixLoadfCHROMIUM(const Context *context, GLenum matrixMode, const GLfloat *matrix);
-bool ValidateMatrixLoadIdentityCHROMIUM(const Context *context, GLenum matrixMode);
 
 // GL_CHROMIUM_lose_context
 bool ValidateLoseContextCHROMIUM(const Context *context,
                                  GraphicsResetStatus currentPacked,
                                  GraphicsResetStatus otherPacked);
 
-// GL_CHROMIUM_path_rendering
-bool ValidateGenPathsCHROMIUM(const Context *context, GLsizei range);
-bool ValidateDeletePathsCHROMIUM(const Context *context, PathID firstPacked, GLsizei range);
-bool ValidateIsPathCHROMIUM(const Context *context, PathID pathPacked);
-bool ValidatePathCommandsCHROMIUM(const Context *context,
-                                  PathID pathPacked,
-                                  GLsizei numCommands,
-                                  const GLubyte *commands,
-                                  GLsizei numCoords,
-                                  GLenum coordType,
-                                  const void *coords);
-bool ValidatePathParameterfCHROMIUM(const Context *context,
-                                    PathID pathPacked,
-                                    GLenum pname,
-                                    GLfloat value);
-bool ValidatePathParameteriCHROMIUM(const Context *context,
-                                    PathID pathPacked,
-                                    GLenum pname,
-                                    GLint value);
-bool ValidateGetPathParameterfvCHROMIUM(const Context *context,
-                                        PathID pathPacked,
-                                        GLenum pname,
-                                        const GLfloat *value);
-bool ValidateGetPathParameterivCHROMIUM(const Context *context,
-                                        PathID pathPacked,
-                                        GLenum pname,
-                                        const GLint *value);
-bool ValidatePathStencilFuncCHROMIUM(const Context *context, GLenum func, GLint ref, GLuint mask);
-bool ValidateStencilFillPathCHROMIUM(const Context *context,
-                                     PathID pathPacked,
-                                     GLenum fillMode,
-                                     GLuint mask);
-bool ValidateStencilStrokePathCHROMIUM(const Context *context,
-                                       PathID pathPacked,
-                                       GLint reference,
-                                       GLuint mask);
-bool ValidateCoverFillPathCHROMIUM(const Context *context, PathID pathPacked, GLenum coverMode);
-bool ValidateCoverStrokePathCHROMIUM(const Context *context, PathID pathPacked, GLenum coverMode);
-bool ValidateStencilThenCoverFillPathCHROMIUM(const Context *context,
-                                              PathID pathPacked,
-                                              GLenum fillMode,
-                                              GLuint mask,
-                                              GLenum coverMode);
-bool ValidateStencilThenCoverStrokePathCHROMIUM(const Context *context,
-                                                PathID pathPacked,
-                                                GLint reference,
-                                                GLuint mask,
-                                                GLenum coverMode);
-bool ValidateCoverFillPathInstancedCHROMIUM(const Context *context,
-                                            GLsizei numPath,
-                                            GLenum pathNameType,
-                                            const void *paths,
-                                            PathID pathBasePacked,
-                                            GLenum coverMode,
-                                            GLenum transformType,
-                                            const GLfloat *transformValues);
-bool ValidateCoverStrokePathInstancedCHROMIUM(const Context *context,
-                                              GLsizei numPath,
-                                              GLenum pathNameType,
-                                              const void *paths,
-                                              PathID pathBasePacked,
-                                              GLenum coverMode,
-                                              GLenum transformType,
-                                              const GLfloat *transformValues);
-bool ValidateStencilStrokePathInstancedCHROMIUM(const Context *context,
-                                                GLsizei numPath,
-                                                GLenum pathNameType,
-                                                const void *paths,
-                                                PathID pathBasePacked,
-                                                GLint reference,
-                                                GLuint mask,
-                                                GLenum transformType,
-                                                const GLfloat *transformValues);
-bool ValidateStencilFillPathInstancedCHROMIUM(const Context *context,
-                                              GLsizei numPaths,
-                                              GLenum pathNameType,
-                                              const void *paths,
-                                              PathID pathBasePacked,
-                                              GLenum fillMode,
-                                              GLuint mask,
-                                              GLenum transformType,
-                                              const GLfloat *transformValues);
-bool ValidateStencilThenCoverFillPathInstancedCHROMIUM(const Context *context,
-                                                       GLsizei numPaths,
-                                                       GLenum pathNameType,
-                                                       const void *paths,
-                                                       PathID pathBasePacked,
-                                                       GLenum fillMode,
-                                                       GLuint mask,
-                                                       GLenum coverMode,
-                                                       GLenum transformType,
-                                                       const GLfloat *transformValues);
-bool ValidateStencilThenCoverStrokePathInstancedCHROMIUM(const Context *context,
-                                                         GLsizei numPaths,
-                                                         GLenum pathNameType,
-                                                         const void *paths,
-                                                         PathID pathBasePacked,
-                                                         GLint reference,
-                                                         GLuint mask,
-                                                         GLenum coverMode,
-                                                         GLenum transformType,
-                                                         const GLfloat *transformValues);
-bool ValidateBindFragmentInputLocationCHROMIUM(const Context *context,
-                                               ShaderProgramID programsPacked,
-                                               GLint location,
-                                               const GLchar *name);
-bool ValidateProgramPathFragmentInputGenCHROMIUM(const Context *context,
-                                                 ShaderProgramID programPacked,
-                                                 GLint location,
-                                                 GLenum genMode,
-                                                 GLint components,
-                                                 const GLfloat *coeffs);
-
 // GL_EXT_blend_func_extended
 bool ValidateBindFragDataLocationEXT(const Context *context,
                                      ShaderProgramID programPacked,
@@ -1126,6 +1011,8 @@
 
 // GL_EXT_texture_format_BGRA8888
 
+// GL_EXT_texture_sRGB_R8
+
 // GL_EXT_texture_storage
 bool ValidateTexStorage1DEXT(const Context *context,
                              GLenum target,
diff --git a/src/libEGL/egl_loader_autogen.cpp b/src/libEGL/egl_loader_autogen.cpp
index 5a88c3f..8c08895 100644
--- a/src/libEGL/egl_loader_autogen.cpp
+++ b/src/libEGL/egl_loader_autogen.cpp
@@ -75,7 +75,7 @@
 PFNEGLCREATESTREAMPRODUCERD3DTEXTUREANGLEPROC EGL_CreateStreamProducerD3DTextureANGLE;
 PFNEGLSTREAMPOSTD3DTEXTUREANGLEPROC EGL_StreamPostD3DTextureANGLE;
 PFNEGLSWAPBUFFERSWITHFRAMETOKENANGLEPROC EGL_SwapBuffersWithFrameTokenANGLE;
-PFNEGLGETMSCRATECHROMIUMPROC EGL_GetMscRateCHROMIUM;
+PFNEGLGETMSCRATEANGLEPROC EGL_GetMscRateANGLE;
 PFNEGLGETSYNCVALUESCHROMIUMPROC EGL_GetSyncValuesCHROMIUM;
 PFNEGLQUERYDEVICEATTRIBEXTPROC EGL_QueryDeviceAttribEXT;
 PFNEGLQUERYDEVICESTRINGEXTPROC EGL_QueryDeviceStringEXT;
@@ -210,8 +210,8 @@
         loadProc("EGL_StreamPostD3DTextureANGLE"));
     EGL_SwapBuffersWithFrameTokenANGLE = reinterpret_cast<PFNEGLSWAPBUFFERSWITHFRAMETOKENANGLEPROC>(
         loadProc("EGL_SwapBuffersWithFrameTokenANGLE"));
-    EGL_GetMscRateCHROMIUM =
-        reinterpret_cast<PFNEGLGETMSCRATECHROMIUMPROC>(loadProc("EGL_GetMscRateCHROMIUM"));
+    EGL_GetMscRateANGLE =
+        reinterpret_cast<PFNEGLGETMSCRATEANGLEPROC>(loadProc("EGL_GetMscRateANGLE"));
     EGL_GetSyncValuesCHROMIUM =
         reinterpret_cast<PFNEGLGETSYNCVALUESCHROMIUMPROC>(loadProc("EGL_GetSyncValuesCHROMIUM"));
     EGL_QueryDeviceAttribEXT =
diff --git a/src/libEGL/egl_loader_autogen.h b/src/libEGL/egl_loader_autogen.h
index 8f50c66..a1effbf 100644
--- a/src/libEGL/egl_loader_autogen.h
+++ b/src/libEGL/egl_loader_autogen.h
@@ -83,7 +83,7 @@
     EGL_CreateStreamProducerD3DTextureANGLE;
 ANGLE_NO_EXPORT extern PFNEGLSTREAMPOSTD3DTEXTUREANGLEPROC EGL_StreamPostD3DTextureANGLE;
 ANGLE_NO_EXPORT extern PFNEGLSWAPBUFFERSWITHFRAMETOKENANGLEPROC EGL_SwapBuffersWithFrameTokenANGLE;
-ANGLE_NO_EXPORT extern PFNEGLGETMSCRATECHROMIUMPROC EGL_GetMscRateCHROMIUM;
+ANGLE_NO_EXPORT extern PFNEGLGETMSCRATEANGLEPROC EGL_GetMscRateANGLE;
 ANGLE_NO_EXPORT extern PFNEGLGETSYNCVALUESCHROMIUMPROC EGL_GetSyncValuesCHROMIUM;
 ANGLE_NO_EXPORT extern PFNEGLQUERYDEVICEATTRIBEXTPROC EGL_QueryDeviceAttribEXT;
 ANGLE_NO_EXPORT extern PFNEGLQUERYDEVICESTRINGEXTPROC EGL_QueryDeviceStringEXT;
diff --git a/src/libEGL/libEGL.cpp b/src/libEGL/libEGL.cpp
index cf400fd..7b834db 100644
--- a/src/libEGL/libEGL.cpp
+++ b/src/libEGL/libEGL.cpp
@@ -572,13 +572,13 @@
     return EGL_GetSyncValuesCHROMIUM(dpy, surface, ust, msc, sbc);
 }
 
-EGLBoolean EGLAPIENTRY eglGetMscRateCHROMIUM(EGLDisplay dpy,
-                                             EGLSurface surface,
-                                             EGLint *numerator,
-                                             EGLint *denominator)
+EGLBoolean EGLAPIENTRY eglGetMscRateANGLE(EGLDisplay dpy,
+                                          EGLSurface surface,
+                                          EGLint *numerator,
+                                          EGLint *denominator)
 {
     EnsureEGLLoaded();
-    return EGL_GetMscRateCHROMIUM(dpy, surface, numerator, denominator);
+    return EGL_GetMscRateANGLE(dpy, surface, numerator, denominator);
 }
 
 EGLBoolean EGLAPIENTRY eglSwapBuffersWithDamageKHR(EGLDisplay dpy,
diff --git a/src/libEGL/libEGL.def b/src/libEGL/libEGL.def
index 26018b0..3f8f5db 100644
--- a/src/libEGL/libEGL.def
+++ b/src/libEGL/libEGL.def
@@ -74,7 +74,7 @@
     eglQueryStringiANGLE                        @80
     eglGetNativeClientBufferANDROID             @81
     eglDupNativeFenceFDANDROID                  @82
-    eglGetMscRateCHROMIUM                       @83
+    eglGetMscRateANGLE                          @83
 
     ; 1.5 entry points
     eglCreateSync                               @38
diff --git a/src/libGLESv2.gni b/src/libGLESv2.gni
index 1cba64f..2f45703 100644
--- a/src/libGLESv2.gni
+++ b/src/libGLESv2.gni
@@ -229,10 +229,10 @@
   "src/libANGLE/GLES1Shaders.inc",
   "src/libANGLE/GLES1State.h",
   "src/libANGLE/HandleAllocator.h",
-  "src/libANGLE/HandleRangeAllocator.h",
   "src/libANGLE/Image.h",
   "src/libANGLE/ImageIndex.h",
   "src/libANGLE/IndexRangeCache.h",
+  "src/libANGLE/InfoLog.h",
   "src/libANGLE/LoggingAnnotator.h",
   "src/libANGLE/MemoryObject.h",
   "src/libANGLE/MemoryProgramCache.h",
@@ -244,8 +244,8 @@
   "src/libANGLE/Overlay_autogen.cpp",
   "src/libANGLE/Overlay_font_autogen.cpp",
   "src/libANGLE/Overlay_font_autogen.h",
-  "src/libANGLE/Path.h",
   "src/libANGLE/Program.h",
+  "src/libANGLE/ProgramExecutable.h",
   "src/libANGLE/ProgramLinkedResources.h",
   "src/libANGLE/ProgramPipeline.h",
   "src/libANGLE/Query.h",
@@ -298,7 +298,6 @@
   "src/libANGLE/renderer/ImageImpl.h",
   "src/libANGLE/renderer/MemoryObjectImpl.h",
   "src/libANGLE/renderer/OverlayImpl.h",
-  "src/libANGLE/renderer/PathImpl.h",
   "src/libANGLE/renderer/ProgramImpl.h",
   "src/libANGLE/renderer/ProgramPipelineImpl.h",
   "src/libANGLE/renderer/QueryImpl.h",
@@ -375,7 +374,6 @@
   "src/libANGLE/GLES1Renderer.cpp",
   "src/libANGLE/GLES1State.cpp",
   "src/libANGLE/HandleAllocator.cpp",
-  "src/libANGLE/HandleRangeAllocator.cpp",
   "src/libANGLE/Image.cpp",
   "src/libANGLE/ImageIndex.cpp",
   "src/libANGLE/IndexRangeCache.cpp",
@@ -383,9 +381,9 @@
   "src/libANGLE/MemoryObject.cpp",
   "src/libANGLE/MemoryProgramCache.cpp",
   "src/libANGLE/Observer.cpp",
-  "src/libANGLE/Path.cpp",
   "src/libANGLE/Platform.cpp",
   "src/libANGLE/Program.cpp",
+  "src/libANGLE/ProgramExecutable.cpp",
   "src/libANGLE/ProgramLinkedResources.cpp",
   "src/libANGLE/ProgramPipeline.cpp",
   "src/libANGLE/Query.cpp",
@@ -417,6 +415,7 @@
   "src/libANGLE/renderer/DeviceImpl.cpp",
   "src/libANGLE/renderer/DisplayImpl.cpp",
   "src/libANGLE/renderer/Format_table_autogen.cpp",
+  "src/libANGLE/renderer/ProgramPipelineImpl.cpp",
   "src/libANGLE/renderer/QueryImpl.cpp",
   "src/libANGLE/renderer/ShaderImpl.cpp",
   "src/libANGLE/renderer/SurfaceImpl.cpp",
@@ -735,8 +734,6 @@
   "src/libANGLE/renderer/gl/ImageGL.h",
   "src/libANGLE/renderer/gl/MemoryObjectGL.cpp",
   "src/libANGLE/renderer/gl/MemoryObjectGL.h",
-  "src/libANGLE/renderer/gl/PathGL.cpp",
-  "src/libANGLE/renderer/gl/PathGL.h",
   "src/libANGLE/renderer/gl/ProgramGL.cpp",
   "src/libANGLE/renderer/gl/ProgramGL.h",
   "src/libANGLE/renderer/gl/ProgramPipelineGL.cpp",
@@ -931,8 +928,6 @@
   "src/libANGLE/renderer/null/FramebufferNULL.h",
   "src/libANGLE/renderer/null/ImageNULL.cpp",
   "src/libANGLE/renderer/null/ImageNULL.h",
-  "src/libANGLE/renderer/null/PathNULL.cpp",
-  "src/libANGLE/renderer/null/PathNULL.h",
   "src/libANGLE/renderer/null/ProgramNULL.cpp",
   "src/libANGLE/renderer/null/ProgramNULL.h",
   "src/libANGLE/renderer/null/ProgramPipelineNULL.cpp",
diff --git a/src/libGLESv2/entry_points_egl_ext.cpp b/src/libGLESv2/entry_points_egl_ext.cpp
index 7366ba8..5e44300 100644
--- a/src/libGLESv2/entry_points_egl_ext.cpp
+++ b/src/libGLESv2/entry_points_egl_ext.cpp
@@ -1020,10 +1020,10 @@
     return EGL_TRUE;
 }
 
-EGLBoolean EGLAPIENTRY EGL_GetMscRateCHROMIUM(EGLDisplay dpy,
-                                              EGLSurface surface,
-                                              EGLint *numerator,
-                                              EGLint *denominator)
+EGLBoolean EGLAPIENTRY EGL_GetMscRateANGLE(EGLDisplay dpy,
+                                           EGLSurface surface,
+                                           EGLint *numerator,
+                                           EGLint *denominator)
 {
     ANGLE_SCOPED_GLOBAL_LOCK();
     FUNC_EVENT("EGLDisplay dpy = 0x%016" PRIxPTR ", EGLSurface surface = 0x%016" PRIxPTR
@@ -1036,10 +1036,10 @@
     egl::Display *display = static_cast<egl::Display *>(dpy);
     Surface *eglSurface   = static_cast<Surface *>(surface);
 
-    Error error = ValidateGetMscRateCHROMIUM(display, eglSurface, numerator, denominator);
+    Error error = ValidateGetMscRateANGLE(display, eglSurface, numerator, denominator);
     if (error.isError())
     {
-        thread->setError(error, GetDebug(), "eglGetMscRateCHROMIUM",
+        thread->setError(error, GetDebug(), "eglGetMscRateANGLE",
                          GetSurfaceIfValid(display, eglSurface));
         return EGL_FALSE;
     }
@@ -1047,7 +1047,7 @@
     error = eglSurface->getMscRate(numerator, denominator);
     if (error.isError())
     {
-        thread->setError(error, GetDebug(), "eglGetMscRateCHROMIUM",
+        thread->setError(error, GetDebug(), "eglGetMscRateANGLE",
                          GetSurfaceIfValid(display, eglSurface));
         return EGL_FALSE;
     }
diff --git a/src/libGLESv2/entry_points_egl_ext.h b/src/libGLESv2/entry_points_egl_ext.h
index 8ab0175..6bfbc5a 100644
--- a/src/libGLESv2/entry_points_egl_ext.h
+++ b/src/libGLESv2/entry_points_egl_ext.h
@@ -134,10 +134,12 @@
                                                               EGLuint64KHR *ust,
                                                               EGLuint64KHR *msc,
                                                               EGLuint64KHR *sbc);
-ANGLE_EXPORT EGLBoolean EGLAPIENTRY EGL_GetMscRateCHROMIUM(EGLDisplay dpy,
-                                                           EGLSurface surface,
-                                                           EGLint *numerator,
-                                                           EGLint *denominator);
+
+// EGL_ANGLE_sync_control_rate
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY EGL_GetMscRateANGLE(EGLDisplay dpy,
+                                                        EGLSurface surface,
+                                                        EGLint *numerator,
+                                                        EGLint *denominator);
 
 // EGL_KHR_swap_buffers_with_damage
 ANGLE_EXPORT EGLBoolean EGLAPIENTRY EGL_SwapBuffersWithDamageKHR(EGLDisplay dpy,
diff --git a/src/libGLESv2/entry_points_gles_ext_autogen.cpp b/src/libGLESv2/entry_points_gles_ext_autogen.cpp
index 956218b..c72f7ad 100644
--- a/src/libGLESv2/entry_points_gles_ext_autogen.cpp
+++ b/src/libGLESv2/entry_points_gles_ext_autogen.cpp
@@ -3043,45 +3043,6 @@
     }
 }
 
-void GL_APIENTRY MatrixLoadfCHROMIUM(GLenum matrixMode, const GLfloat *matrix)
-{
-    Context *context = GetValidGlobalContext();
-    EVENT("glMatrixLoadfCHROMIUM",
-          "context = %d, GLenum matrixMode = %s, const GLfloat * matrix = 0x%016" PRIxPTR "",
-          CID(context), GLenumToString(GLenumGroup::DefaultGroup, matrixMode), (uintptr_t)matrix);
-
-    if (context)
-    {
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid =
-            (context->skipValidation() || ValidateMatrixLoadfCHROMIUM(context, matrixMode, matrix));
-        if (isCallValid)
-        {
-            context->matrixLoadf(matrixMode, matrix);
-        }
-        ANGLE_CAPTURE(MatrixLoadfCHROMIUM, isCallValid, context, matrixMode, matrix);
-    }
-}
-
-void GL_APIENTRY MatrixLoadIdentityCHROMIUM(GLenum matrixMode)
-{
-    Context *context = GetValidGlobalContext();
-    EVENT("glMatrixLoadIdentityCHROMIUM", "context = %d, GLenum matrixMode = %s", CID(context),
-          GLenumToString(GLenumGroup::DefaultGroup, matrixMode));
-
-    if (context)
-    {
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid =
-            (context->skipValidation() || ValidateMatrixLoadIdentityCHROMIUM(context, matrixMode));
-        if (isCallValid)
-        {
-            context->matrixLoadIdentity(matrixMode);
-        }
-        ANGLE_CAPTURE(MatrixLoadIdentityCHROMIUM, isCallValid, context, matrixMode);
-    }
-}
-
 // GL_CHROMIUM_lose_context
 void GL_APIENTRY LoseContextCHROMIUM(GLenum current, GLenum other)
 {
@@ -3105,642 +3066,6 @@
     }
 }
 
-// GL_CHROMIUM_path_rendering
-GLuint GL_APIENTRY GenPathsCHROMIUM(GLsizei range)
-{
-    Context *context = GetValidGlobalContext();
-    EVENT("glGenPathsCHROMIUM", "context = %d, GLsizei range = %d", CID(context), range);
-
-    GLuint returnValue;
-    if (context)
-    {
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid = (context->skipValidation() || ValidateGenPathsCHROMIUM(context, range));
-        if (isCallValid)
-        {
-            returnValue = context->genPaths(range);
-        }
-        else
-        {
-            returnValue = GetDefaultReturnValue<EntryPoint::GenPathsCHROMIUM, GLuint>();
-        }
-        ANGLE_CAPTURE(GenPathsCHROMIUM, isCallValid, context, range, returnValue);
-    }
-    else
-    {
-        returnValue = GetDefaultReturnValue<EntryPoint::GenPathsCHROMIUM, GLuint>();
-    }
-    return returnValue;
-}
-
-void GL_APIENTRY DeletePathsCHROMIUM(GLuint first, GLsizei range)
-{
-    Context *context = GetValidGlobalContext();
-    EVENT("glDeletePathsCHROMIUM", "context = %d, GLuint first = %u, GLsizei range = %d",
-          CID(context), first, range);
-
-    if (context)
-    {
-        PathID firstPacked                                    = FromGL<PathID>(first);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid =
-            (context->skipValidation() || ValidateDeletePathsCHROMIUM(context, firstPacked, range));
-        if (isCallValid)
-        {
-            context->deletePaths(firstPacked, range);
-        }
-        ANGLE_CAPTURE(DeletePathsCHROMIUM, isCallValid, context, firstPacked, range);
-    }
-}
-
-GLboolean GL_APIENTRY IsPathCHROMIUM(GLuint path)
-{
-    Context *context = GetValidGlobalContext();
-    EVENT("glIsPathCHROMIUM", "context = %d, GLuint path = %u", CID(context), path);
-
-    GLboolean returnValue;
-    if (context)
-    {
-        PathID pathPacked                                     = FromGL<PathID>(path);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid =
-            (context->skipValidation() || ValidateIsPathCHROMIUM(context, pathPacked));
-        if (isCallValid)
-        {
-            returnValue = context->isPath(pathPacked);
-        }
-        else
-        {
-            returnValue = GetDefaultReturnValue<EntryPoint::IsPathCHROMIUM, GLboolean>();
-        }
-        ANGLE_CAPTURE(IsPathCHROMIUM, isCallValid, context, pathPacked, returnValue);
-    }
-    else
-    {
-        returnValue = GetDefaultReturnValue<EntryPoint::IsPathCHROMIUM, GLboolean>();
-    }
-    return returnValue;
-}
-
-void GL_APIENTRY PathCommandsCHROMIUM(GLuint path,
-                                      GLsizei numCommands,
-                                      const GLubyte *commands,
-                                      GLsizei numCoords,
-                                      GLenum coordType,
-                                      const void *coords)
-{
-    Context *context = GetValidGlobalContext();
-    EVENT("glPathCommandsCHROMIUM",
-          "context = %d, GLuint path = %u, GLsizei numCommands = %d, const GLubyte * commands = "
-          "0x%016" PRIxPTR
-          ", GLsizei numCoords = %d, GLenum coordType = %s, const void* coords = 0x%016" PRIxPTR "",
-          CID(context), path, numCommands, (uintptr_t)commands, numCoords,
-          GLenumToString(GLenumGroup::DefaultGroup, coordType), (uintptr_t)coords);
-
-    if (context)
-    {
-        PathID pathPacked                                     = FromGL<PathID>(path);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid                                      = (context->skipValidation() ||
-                            ValidatePathCommandsCHROMIUM(context, pathPacked, numCommands, commands,
-                                                         numCoords, coordType, coords));
-        if (isCallValid)
-        {
-            context->pathCommands(pathPacked, numCommands, commands, numCoords, coordType, coords);
-        }
-        ANGLE_CAPTURE(PathCommandsCHROMIUM, isCallValid, context, pathPacked, numCommands, commands,
-                      numCoords, coordType, coords);
-    }
-}
-
-void GL_APIENTRY PathParameterfCHROMIUM(GLuint path, GLenum pname, GLfloat value)
-{
-    Context *context = GetValidGlobalContext();
-    EVENT("glPathParameterfCHROMIUM",
-          "context = %d, GLuint path = %u, GLenum pname = %s, GLfloat value = %f", CID(context),
-          path, GLenumToString(GLenumGroup::DefaultGroup, pname), value);
-
-    if (context)
-    {
-        PathID pathPacked                                     = FromGL<PathID>(path);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid                                      = (context->skipValidation() ||
-                            ValidatePathParameterfCHROMIUM(context, pathPacked, pname, value));
-        if (isCallValid)
-        {
-            context->pathParameterf(pathPacked, pname, value);
-        }
-        ANGLE_CAPTURE(PathParameterfCHROMIUM, isCallValid, context, pathPacked, pname, value);
-    }
-}
-
-void GL_APIENTRY PathParameteriCHROMIUM(GLuint path, GLenum pname, GLint value)
-{
-    Context *context = GetValidGlobalContext();
-    EVENT("glPathParameteriCHROMIUM",
-          "context = %d, GLuint path = %u, GLenum pname = %s, GLint value = %d", CID(context), path,
-          GLenumToString(GLenumGroup::DefaultGroup, pname), value);
-
-    if (context)
-    {
-        PathID pathPacked                                     = FromGL<PathID>(path);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid                                      = (context->skipValidation() ||
-                            ValidatePathParameteriCHROMIUM(context, pathPacked, pname, value));
-        if (isCallValid)
-        {
-            context->pathParameteri(pathPacked, pname, value);
-        }
-        ANGLE_CAPTURE(PathParameteriCHROMIUM, isCallValid, context, pathPacked, pname, value);
-    }
-}
-
-void GL_APIENTRY GetPathParameterfvCHROMIUM(GLuint path, GLenum pname, GLfloat *value)
-{
-    Context *context = GetValidGlobalContext();
-    EVENT("glGetPathParameterfvCHROMIUM",
-          "context = %d, GLuint path = %u, GLenum pname = %s, GLfloat * value = 0x%016" PRIxPTR "",
-          CID(context), path, GLenumToString(GLenumGroup::DefaultGroup, pname), (uintptr_t)value);
-
-    if (context)
-    {
-        PathID pathPacked                                     = FromGL<PathID>(path);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid                                      = (context->skipValidation() ||
-                            ValidateGetPathParameterfvCHROMIUM(context, pathPacked, pname, value));
-        if (isCallValid)
-        {
-            context->getPathParameterfv(pathPacked, pname, value);
-        }
-        ANGLE_CAPTURE(GetPathParameterfvCHROMIUM, isCallValid, context, pathPacked, pname, value);
-    }
-}
-
-void GL_APIENTRY GetPathParameterivCHROMIUM(GLuint path, GLenum pname, GLint *value)
-{
-    Context *context = GetValidGlobalContext();
-    EVENT("glGetPathParameterivCHROMIUM",
-          "context = %d, GLuint path = %u, GLenum pname = %s, GLint * value = 0x%016" PRIxPTR "",
-          CID(context), path, GLenumToString(GLenumGroup::DefaultGroup, pname), (uintptr_t)value);
-
-    if (context)
-    {
-        PathID pathPacked                                     = FromGL<PathID>(path);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid                                      = (context->skipValidation() ||
-                            ValidateGetPathParameterivCHROMIUM(context, pathPacked, pname, value));
-        if (isCallValid)
-        {
-            context->getPathParameteriv(pathPacked, pname, value);
-        }
-        ANGLE_CAPTURE(GetPathParameterivCHROMIUM, isCallValid, context, pathPacked, pname, value);
-    }
-}
-
-void GL_APIENTRY PathStencilFuncCHROMIUM(GLenum func, GLint ref, GLuint mask)
-{
-    Context *context = GetValidGlobalContext();
-    EVENT("glPathStencilFuncCHROMIUM",
-          "context = %d, GLenum func = %s, GLint ref = %d, GLuint mask = %u", CID(context),
-          GLenumToString(GLenumGroup::DefaultGroup, func), ref, mask);
-
-    if (context)
-    {
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid                                      = (context->skipValidation() ||
-                            ValidatePathStencilFuncCHROMIUM(context, func, ref, mask));
-        if (isCallValid)
-        {
-            context->pathStencilFunc(func, ref, mask);
-        }
-        ANGLE_CAPTURE(PathStencilFuncCHROMIUM, isCallValid, context, func, ref, mask);
-    }
-}
-
-void GL_APIENTRY StencilFillPathCHROMIUM(GLuint path, GLenum fillMode, GLuint mask)
-{
-    Context *context = GetValidGlobalContext();
-    EVENT("glStencilFillPathCHROMIUM",
-          "context = %d, GLuint path = %u, GLenum fillMode = %s, GLuint mask = %u", CID(context),
-          path, GLenumToString(GLenumGroup::DefaultGroup, fillMode), mask);
-
-    if (context)
-    {
-        PathID pathPacked                                     = FromGL<PathID>(path);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid                                      = (context->skipValidation() ||
-                            ValidateStencilFillPathCHROMIUM(context, pathPacked, fillMode, mask));
-        if (isCallValid)
-        {
-            context->stencilFillPath(pathPacked, fillMode, mask);
-        }
-        ANGLE_CAPTURE(StencilFillPathCHROMIUM, isCallValid, context, pathPacked, fillMode, mask);
-    }
-}
-
-void GL_APIENTRY StencilStrokePathCHROMIUM(GLuint path, GLint reference, GLuint mask)
-{
-    Context *context = GetValidGlobalContext();
-    EVENT("glStencilStrokePathCHROMIUM",
-          "context = %d, GLuint path = %u, GLint reference = %d, GLuint mask = %u", CID(context),
-          path, reference, mask);
-
-    if (context)
-    {
-        PathID pathPacked                                     = FromGL<PathID>(path);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid = (context->skipValidation() || ValidateStencilStrokePathCHROMIUM(
-                                                             context, pathPacked, reference, mask));
-        if (isCallValid)
-        {
-            context->stencilStrokePath(pathPacked, reference, mask);
-        }
-        ANGLE_CAPTURE(StencilStrokePathCHROMIUM, isCallValid, context, pathPacked, reference, mask);
-    }
-}
-
-void GL_APIENTRY CoverFillPathCHROMIUM(GLuint path, GLenum coverMode)
-{
-    Context *context = GetValidGlobalContext();
-    EVENT("glCoverFillPathCHROMIUM", "context = %d, GLuint path = %u, GLenum coverMode = %s",
-          CID(context), path, GLenumToString(GLenumGroup::DefaultGroup, coverMode));
-
-    if (context)
-    {
-        PathID pathPacked                                     = FromGL<PathID>(path);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid                                      = (context->skipValidation() ||
-                            ValidateCoverFillPathCHROMIUM(context, pathPacked, coverMode));
-        if (isCallValid)
-        {
-            context->coverFillPath(pathPacked, coverMode);
-        }
-        ANGLE_CAPTURE(CoverFillPathCHROMIUM, isCallValid, context, pathPacked, coverMode);
-    }
-}
-
-void GL_APIENTRY CoverStrokePathCHROMIUM(GLuint path, GLenum coverMode)
-{
-    Context *context = GetValidGlobalContext();
-    EVENT("glCoverStrokePathCHROMIUM", "context = %d, GLuint path = %u, GLenum coverMode = %s",
-          CID(context), path, GLenumToString(GLenumGroup::DefaultGroup, coverMode));
-
-    if (context)
-    {
-        PathID pathPacked                                     = FromGL<PathID>(path);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid                                      = (context->skipValidation() ||
-                            ValidateCoverStrokePathCHROMIUM(context, pathPacked, coverMode));
-        if (isCallValid)
-        {
-            context->coverStrokePath(pathPacked, coverMode);
-        }
-        ANGLE_CAPTURE(CoverStrokePathCHROMIUM, isCallValid, context, pathPacked, coverMode);
-    }
-}
-
-void GL_APIENTRY StencilThenCoverFillPathCHROMIUM(GLuint path,
-                                                  GLenum fillMode,
-                                                  GLuint mask,
-                                                  GLenum coverMode)
-{
-    Context *context = GetValidGlobalContext();
-    EVENT("glStencilThenCoverFillPathCHROMIUM",
-          "context = %d, GLuint path = %u, GLenum fillMode = %s, GLuint mask = %u, GLenum "
-          "coverMode = %s",
-          CID(context), path, GLenumToString(GLenumGroup::DefaultGroup, fillMode), mask,
-          GLenumToString(GLenumGroup::DefaultGroup, coverMode));
-
-    if (context)
-    {
-        PathID pathPacked                                     = FromGL<PathID>(path);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid =
-            (context->skipValidation() || ValidateStencilThenCoverFillPathCHROMIUM(
-                                              context, pathPacked, fillMode, mask, coverMode));
-        if (isCallValid)
-        {
-            context->stencilThenCoverFillPath(pathPacked, fillMode, mask, coverMode);
-        }
-        ANGLE_CAPTURE(StencilThenCoverFillPathCHROMIUM, isCallValid, context, pathPacked, fillMode,
-                      mask, coverMode);
-    }
-}
-
-void GL_APIENTRY StencilThenCoverStrokePathCHROMIUM(GLuint path,
-                                                    GLint reference,
-                                                    GLuint mask,
-                                                    GLenum coverMode)
-{
-    Context *context = GetValidGlobalContext();
-    EVENT("glStencilThenCoverStrokePathCHROMIUM",
-          "context = %d, GLuint path = %u, GLint reference = %d, GLuint mask = %u, GLenum "
-          "coverMode = %s",
-          CID(context), path, reference, mask,
-          GLenumToString(GLenumGroup::DefaultGroup, coverMode));
-
-    if (context)
-    {
-        PathID pathPacked                                     = FromGL<PathID>(path);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid =
-            (context->skipValidation() || ValidateStencilThenCoverStrokePathCHROMIUM(
-                                              context, pathPacked, reference, mask, coverMode));
-        if (isCallValid)
-        {
-            context->stencilThenCoverStrokePath(pathPacked, reference, mask, coverMode);
-        }
-        ANGLE_CAPTURE(StencilThenCoverStrokePathCHROMIUM, isCallValid, context, pathPacked,
-                      reference, mask, coverMode);
-    }
-}
-
-void GL_APIENTRY CoverFillPathInstancedCHROMIUM(GLsizei numPath,
-                                                GLenum pathNameType,
-                                                const void *paths,
-                                                GLuint pathBase,
-                                                GLenum coverMode,
-                                                GLenum transformType,
-                                                const GLfloat *transformValues)
-{
-    Context *context = GetValidGlobalContext();
-    EVENT("glCoverFillPathInstancedCHROMIUM",
-          "context = %d, GLsizei numPath = %d, GLenum pathNameType = %s, const void * paths = "
-          "0x%016" PRIxPTR
-          ", GLuint pathBase = %u, GLenum coverMode = %s, GLenum transformType = %s, const GLfloat "
-          "* transformValues = 0x%016" PRIxPTR "",
-          CID(context), numPath, GLenumToString(GLenumGroup::DefaultGroup, pathNameType),
-          (uintptr_t)paths, pathBase, GLenumToString(GLenumGroup::DefaultGroup, coverMode),
-          GLenumToString(GLenumGroup::DefaultGroup, transformType), (uintptr_t)transformValues);
-
-    if (context)
-    {
-        PathID pathBasePacked                                 = FromGL<PathID>(pathBase);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid =
-            (context->skipValidation() || ValidateCoverFillPathInstancedCHROMIUM(
-                                              context, numPath, pathNameType, paths, pathBasePacked,
-                                              coverMode, transformType, transformValues));
-        if (isCallValid)
-        {
-            context->coverFillPathInstanced(numPath, pathNameType, paths, pathBasePacked, coverMode,
-                                            transformType, transformValues);
-        }
-        ANGLE_CAPTURE(CoverFillPathInstancedCHROMIUM, isCallValid, context, numPath, pathNameType,
-                      paths, pathBasePacked, coverMode, transformType, transformValues);
-    }
-}
-
-void GL_APIENTRY CoverStrokePathInstancedCHROMIUM(GLsizei numPath,
-                                                  GLenum pathNameType,
-                                                  const void *paths,
-                                                  GLuint pathBase,
-                                                  GLenum coverMode,
-                                                  GLenum transformType,
-                                                  const GLfloat *transformValues)
-{
-    Context *context = GetValidGlobalContext();
-    EVENT("glCoverStrokePathInstancedCHROMIUM",
-          "context = %d, GLsizei numPath = %d, GLenum pathNameType = %s, const void * paths = "
-          "0x%016" PRIxPTR
-          ", GLuint pathBase = %u, GLenum coverMode = %s, GLenum transformType = %s, const GLfloat "
-          "* transformValues = 0x%016" PRIxPTR "",
-          CID(context), numPath, GLenumToString(GLenumGroup::DefaultGroup, pathNameType),
-          (uintptr_t)paths, pathBase, GLenumToString(GLenumGroup::DefaultGroup, coverMode),
-          GLenumToString(GLenumGroup::DefaultGroup, transformType), (uintptr_t)transformValues);
-
-    if (context)
-    {
-        PathID pathBasePacked                                 = FromGL<PathID>(pathBase);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid =
-            (context->skipValidation() || ValidateCoverStrokePathInstancedCHROMIUM(
-                                              context, numPath, pathNameType, paths, pathBasePacked,
-                                              coverMode, transformType, transformValues));
-        if (isCallValid)
-        {
-            context->coverStrokePathInstanced(numPath, pathNameType, paths, pathBasePacked,
-                                              coverMode, transformType, transformValues);
-        }
-        ANGLE_CAPTURE(CoverStrokePathInstancedCHROMIUM, isCallValid, context, numPath, pathNameType,
-                      paths, pathBasePacked, coverMode, transformType, transformValues);
-    }
-}
-
-void GL_APIENTRY StencilStrokePathInstancedCHROMIUM(GLsizei numPath,
-                                                    GLenum pathNameType,
-                                                    const void *paths,
-                                                    GLuint pathBase,
-                                                    GLint reference,
-                                                    GLuint mask,
-                                                    GLenum transformType,
-                                                    const GLfloat *transformValues)
-{
-    Context *context = GetValidGlobalContext();
-    EVENT("glStencilStrokePathInstancedCHROMIUM",
-          "context = %d, GLsizei numPath = %d, GLenum pathNameType = %s, const void * paths = "
-          "0x%016" PRIxPTR
-          ", GLuint pathBase = %u, GLint reference = %d, GLuint mask = %u, GLenum transformType = "
-          "%s, const GLfloat * transformValues = 0x%016" PRIxPTR "",
-          CID(context), numPath, GLenumToString(GLenumGroup::DefaultGroup, pathNameType),
-          (uintptr_t)paths, pathBase, reference, mask,
-          GLenumToString(GLenumGroup::DefaultGroup, transformType), (uintptr_t)transformValues);
-
-    if (context)
-    {
-        PathID pathBasePacked                                 = FromGL<PathID>(pathBase);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid =
-            (context->skipValidation() || ValidateStencilStrokePathInstancedCHROMIUM(
-                                              context, numPath, pathNameType, paths, pathBasePacked,
-                                              reference, mask, transformType, transformValues));
-        if (isCallValid)
-        {
-            context->stencilStrokePathInstanced(numPath, pathNameType, paths, pathBasePacked,
-                                                reference, mask, transformType, transformValues);
-        }
-        ANGLE_CAPTURE(StencilStrokePathInstancedCHROMIUM, isCallValid, context, numPath,
-                      pathNameType, paths, pathBasePacked, reference, mask, transformType,
-                      transformValues);
-    }
-}
-
-void GL_APIENTRY StencilFillPathInstancedCHROMIUM(GLsizei numPaths,
-                                                  GLenum pathNameType,
-                                                  const void *paths,
-                                                  GLuint pathBase,
-                                                  GLenum fillMode,
-                                                  GLuint mask,
-                                                  GLenum transformType,
-                                                  const GLfloat *transformValues)
-{
-    Context *context = GetValidGlobalContext();
-    EVENT("glStencilFillPathInstancedCHROMIUM",
-          "context = %d, GLsizei numPaths = %d, GLenum pathNameType = %s, const void * paths = "
-          "0x%016" PRIxPTR
-          ", GLuint pathBase = %u, GLenum fillMode = %s, GLuint mask = %u, GLenum transformType = "
-          "%s, const GLfloat * transformValues = 0x%016" PRIxPTR "",
-          CID(context), numPaths, GLenumToString(GLenumGroup::DefaultGroup, pathNameType),
-          (uintptr_t)paths, pathBase, GLenumToString(GLenumGroup::DefaultGroup, fillMode), mask,
-          GLenumToString(GLenumGroup::DefaultGroup, transformType), (uintptr_t)transformValues);
-
-    if (context)
-    {
-        PathID pathBasePacked                                 = FromGL<PathID>(pathBase);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid                                      = (context->skipValidation() ||
-                            ValidateStencilFillPathInstancedCHROMIUM(
-                                context, numPaths, pathNameType, paths, pathBasePacked, fillMode,
-                                mask, transformType, transformValues));
-        if (isCallValid)
-        {
-            context->stencilFillPathInstanced(numPaths, pathNameType, paths, pathBasePacked,
-                                              fillMode, mask, transformType, transformValues);
-        }
-        ANGLE_CAPTURE(StencilFillPathInstancedCHROMIUM, isCallValid, context, numPaths,
-                      pathNameType, paths, pathBasePacked, fillMode, mask, transformType,
-                      transformValues);
-    }
-}
-
-void GL_APIENTRY StencilThenCoverFillPathInstancedCHROMIUM(GLsizei numPaths,
-                                                           GLenum pathNameType,
-                                                           const void *paths,
-                                                           GLuint pathBase,
-                                                           GLenum fillMode,
-                                                           GLuint mask,
-                                                           GLenum coverMode,
-                                                           GLenum transformType,
-                                                           const GLfloat *transformValues)
-{
-    Context *context = GetValidGlobalContext();
-    EVENT("glStencilThenCoverFillPathInstancedCHROMIUM",
-          "context = %d, GLsizei numPaths = %d, GLenum pathNameType = %s, const void * paths = "
-          "0x%016" PRIxPTR
-          ", GLuint pathBase = %u, GLenum fillMode = %s, GLuint mask = %u, GLenum coverMode = %s, "
-          "GLenum transformType = %s, const GLfloat * transformValues = 0x%016" PRIxPTR "",
-          CID(context), numPaths, GLenumToString(GLenumGroup::DefaultGroup, pathNameType),
-          (uintptr_t)paths, pathBase, GLenumToString(GLenumGroup::DefaultGroup, fillMode), mask,
-          GLenumToString(GLenumGroup::DefaultGroup, coverMode),
-          GLenumToString(GLenumGroup::DefaultGroup, transformType), (uintptr_t)transformValues);
-
-    if (context)
-    {
-        PathID pathBasePacked                                 = FromGL<PathID>(pathBase);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid                                      = (context->skipValidation() ||
-                            ValidateStencilThenCoverFillPathInstancedCHROMIUM(
-                                context, numPaths, pathNameType, paths, pathBasePacked, fillMode,
-                                mask, coverMode, transformType, transformValues));
-        if (isCallValid)
-        {
-            context->stencilThenCoverFillPathInstanced(numPaths, pathNameType, paths,
-                                                       pathBasePacked, fillMode, mask, coverMode,
-                                                       transformType, transformValues);
-        }
-        ANGLE_CAPTURE(StencilThenCoverFillPathInstancedCHROMIUM, isCallValid, context, numPaths,
-                      pathNameType, paths, pathBasePacked, fillMode, mask, coverMode, transformType,
-                      transformValues);
-    }
-}
-
-void GL_APIENTRY StencilThenCoverStrokePathInstancedCHROMIUM(GLsizei numPaths,
-                                                             GLenum pathNameType,
-                                                             const void *paths,
-                                                             GLuint pathBase,
-                                                             GLint reference,
-                                                             GLuint mask,
-                                                             GLenum coverMode,
-                                                             GLenum transformType,
-                                                             const GLfloat *transformValues)
-{
-    Context *context = GetValidGlobalContext();
-    EVENT("glStencilThenCoverStrokePathInstancedCHROMIUM",
-          "context = %d, GLsizei numPaths = %d, GLenum pathNameType = %s, const void * paths = "
-          "0x%016" PRIxPTR
-          ", GLuint pathBase = %u, GLint reference = %d, GLuint mask = %u, GLenum coverMode = %s, "
-          "GLenum transformType = %s, const GLfloat * transformValues = 0x%016" PRIxPTR "",
-          CID(context), numPaths, GLenumToString(GLenumGroup::DefaultGroup, pathNameType),
-          (uintptr_t)paths, pathBase, reference, mask,
-          GLenumToString(GLenumGroup::DefaultGroup, coverMode),
-          GLenumToString(GLenumGroup::DefaultGroup, transformType), (uintptr_t)transformValues);
-
-    if (context)
-    {
-        PathID pathBasePacked                                 = FromGL<PathID>(pathBase);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid                                      = (context->skipValidation() ||
-                            ValidateStencilThenCoverStrokePathInstancedCHROMIUM(
-                                context, numPaths, pathNameType, paths, pathBasePacked, reference,
-                                mask, coverMode, transformType, transformValues));
-        if (isCallValid)
-        {
-            context->stencilThenCoverStrokePathInstanced(numPaths, pathNameType, paths,
-                                                         pathBasePacked, reference, mask, coverMode,
-                                                         transformType, transformValues);
-        }
-        ANGLE_CAPTURE(StencilThenCoverStrokePathInstancedCHROMIUM, isCallValid, context, numPaths,
-                      pathNameType, paths, pathBasePacked, reference, mask, coverMode,
-                      transformType, transformValues);
-    }
-}
-
-void GL_APIENTRY BindFragmentInputLocationCHROMIUM(GLuint programs,
-                                                   GLint location,
-                                                   const GLchar *name)
-{
-    Context *context = GetValidGlobalContext();
-    EVENT("glBindFragmentInputLocationCHROMIUM",
-          "context = %d, GLuint programs = %u, GLint location = %d, const GLchar * name = "
-          "0x%016" PRIxPTR "",
-          CID(context), programs, location, (uintptr_t)name);
-
-    if (context)
-    {
-        ShaderProgramID programsPacked                        = FromGL<ShaderProgramID>(programs);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid =
-            (context->skipValidation() ||
-             ValidateBindFragmentInputLocationCHROMIUM(context, programsPacked, location, name));
-        if (isCallValid)
-        {
-            context->bindFragmentInputLocation(programsPacked, location, name);
-        }
-        ANGLE_CAPTURE(BindFragmentInputLocationCHROMIUM, isCallValid, context, programsPacked,
-                      location, name);
-    }
-}
-
-void GL_APIENTRY ProgramPathFragmentInputGenCHROMIUM(GLuint program,
-                                                     GLint location,
-                                                     GLenum genMode,
-                                                     GLint components,
-                                                     const GLfloat *coeffs)
-{
-    Context *context = GetValidGlobalContext();
-    EVENT("glProgramPathFragmentInputGenCHROMIUM",
-          "context = %d, GLuint program = %u, GLint location = %d, GLenum genMode = %s, GLint "
-          "components = %d, const GLfloat * coeffs = 0x%016" PRIxPTR "",
-          CID(context), program, location, GLenumToString(GLenumGroup::DefaultGroup, genMode),
-          components, (uintptr_t)coeffs);
-
-    if (context)
-    {
-        ShaderProgramID programPacked                         = FromGL<ShaderProgramID>(program);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid                                      = (context->skipValidation() ||
-                            ValidateProgramPathFragmentInputGenCHROMIUM(
-                                context, programPacked, location, genMode, components, coeffs));
-        if (isCallValid)
-        {
-            context->programPathFragmentInputGen(programPacked, location, genMode, components,
-                                                 coeffs);
-        }
-        ANGLE_CAPTURE(ProgramPathFragmentInputGenCHROMIUM, isCallValid, context, programPacked,
-                      location, genMode, components, coeffs);
-    }
-}
-
 // GL_EXT_blend_func_extended
 void GL_APIENTRY BindFragDataLocationEXT(GLuint program, GLuint color, const GLchar *name)
 {
@@ -5503,6 +4828,8 @@
 
 // GL_EXT_texture_format_BGRA8888
 
+// GL_EXT_texture_sRGB_R8
+
 // GL_EXT_texture_storage
 void GL_APIENTRY TexStorage1DEXT(GLenum target,
                                  GLsizei levels,
@@ -24187,743 +23514,6 @@
     }
 }
 
-void GL_APIENTRY MatrixLoadfCHROMIUMContextANGLE(GLeglContext ctx,
-                                                 GLenum matrixMode,
-                                                 const GLfloat *matrix)
-{
-    Context *context = static_cast<gl::Context *>(ctx);
-    EVENT("glMatrixLoadfCHROMIUM",
-          "context = %d, GLenum matrixMode = %s, const GLfloat * matrix = 0x%016" PRIxPTR "",
-          CID(context), GLenumToString(GLenumGroup::DefaultGroup, matrixMode), (uintptr_t)matrix);
-
-    if (context)
-    {
-        ASSERT(context == GetValidGlobalContext());
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid =
-            (context->skipValidation() || ValidateMatrixLoadfCHROMIUM(context, matrixMode, matrix));
-        if (isCallValid)
-        {
-            context->matrixLoadf(matrixMode, matrix);
-        }
-        ANGLE_CAPTURE(MatrixLoadfCHROMIUM, isCallValid, context, matrixMode, matrix);
-    }
-}
-
-void GL_APIENTRY MatrixLoadIdentityCHROMIUMContextANGLE(GLeglContext ctx, GLenum matrixMode)
-{
-    Context *context = static_cast<gl::Context *>(ctx);
-    EVENT("glMatrixLoadIdentityCHROMIUM", "context = %d, GLenum matrixMode = %s", CID(context),
-          GLenumToString(GLenumGroup::DefaultGroup, matrixMode));
-
-    if (context)
-    {
-        ASSERT(context == GetValidGlobalContext());
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid =
-            (context->skipValidation() || ValidateMatrixLoadIdentityCHROMIUM(context, matrixMode));
-        if (isCallValid)
-        {
-            context->matrixLoadIdentity(matrixMode);
-        }
-        ANGLE_CAPTURE(MatrixLoadIdentityCHROMIUM, isCallValid, context, matrixMode);
-    }
-}
-
-GLuint GL_APIENTRY GenPathsCHROMIUMContextANGLE(GLeglContext ctx, GLsizei range)
-{
-    Context *context = static_cast<gl::Context *>(ctx);
-    EVENT("glGenPathsCHROMIUM", "context = %d, GLsizei range = %d", CID(context), range);
-
-    GLuint returnValue;
-    if (context)
-    {
-        ASSERT(context == GetValidGlobalContext());
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid = (context->skipValidation() || ValidateGenPathsCHROMIUM(context, range));
-        if (isCallValid)
-        {
-            returnValue = context->genPaths(range);
-        }
-        else
-        {
-            returnValue = GetDefaultReturnValue<EntryPoint::GenPathsCHROMIUM, GLuint>();
-        }
-        ANGLE_CAPTURE(GenPathsCHROMIUM, isCallValid, context, range, returnValue);
-    }
-    else
-    {
-        returnValue = GetDefaultReturnValue<EntryPoint::GenPathsCHROMIUM, GLuint>();
-    }
-    return returnValue;
-}
-
-void GL_APIENTRY DeletePathsCHROMIUMContextANGLE(GLeglContext ctx, GLuint first, GLsizei range)
-{
-    Context *context = static_cast<gl::Context *>(ctx);
-    EVENT("glDeletePathsCHROMIUM", "context = %d, GLuint first = %u, GLsizei range = %d",
-          CID(context), first, range);
-
-    if (context)
-    {
-        ASSERT(context == GetValidGlobalContext());
-        PathID firstPacked                                    = FromGL<PathID>(first);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid =
-            (context->skipValidation() || ValidateDeletePathsCHROMIUM(context, firstPacked, range));
-        if (isCallValid)
-        {
-            context->deletePaths(firstPacked, range);
-        }
-        ANGLE_CAPTURE(DeletePathsCHROMIUM, isCallValid, context, firstPacked, range);
-    }
-}
-
-GLboolean GL_APIENTRY IsPathCHROMIUMContextANGLE(GLeglContext ctx, GLuint path)
-{
-    Context *context = static_cast<gl::Context *>(ctx);
-    EVENT("glIsPathCHROMIUM", "context = %d, GLuint path = %u", CID(context), path);
-
-    GLboolean returnValue;
-    if (context)
-    {
-        ASSERT(context == GetValidGlobalContext());
-        PathID pathPacked                                     = FromGL<PathID>(path);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid =
-            (context->skipValidation() || ValidateIsPathCHROMIUM(context, pathPacked));
-        if (isCallValid)
-        {
-            returnValue = context->isPath(pathPacked);
-        }
-        else
-        {
-            returnValue = GetDefaultReturnValue<EntryPoint::IsPathCHROMIUM, GLboolean>();
-        }
-        ANGLE_CAPTURE(IsPathCHROMIUM, isCallValid, context, pathPacked, returnValue);
-    }
-    else
-    {
-        returnValue = GetDefaultReturnValue<EntryPoint::IsPathCHROMIUM, GLboolean>();
-    }
-    return returnValue;
-}
-
-void GL_APIENTRY PathCommandsCHROMIUMContextANGLE(GLeglContext ctx,
-                                                  GLuint path,
-                                                  GLsizei numCommands,
-                                                  const GLubyte *commands,
-                                                  GLsizei numCoords,
-                                                  GLenum coordType,
-                                                  const void *coords)
-{
-    Context *context = static_cast<gl::Context *>(ctx);
-    EVENT("glPathCommandsCHROMIUM",
-          "context = %d, GLuint path = %u, GLsizei numCommands = %d, const GLubyte * commands = "
-          "0x%016" PRIxPTR
-          ", GLsizei numCoords = %d, GLenum coordType = %s, const void* coords = 0x%016" PRIxPTR "",
-          CID(context), path, numCommands, (uintptr_t)commands, numCoords,
-          GLenumToString(GLenumGroup::DefaultGroup, coordType), (uintptr_t)coords);
-
-    if (context)
-    {
-        ASSERT(context == GetValidGlobalContext());
-        PathID pathPacked                                     = FromGL<PathID>(path);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid                                      = (context->skipValidation() ||
-                            ValidatePathCommandsCHROMIUM(context, pathPacked, numCommands, commands,
-                                                         numCoords, coordType, coords));
-        if (isCallValid)
-        {
-            context->pathCommands(pathPacked, numCommands, commands, numCoords, coordType, coords);
-        }
-        ANGLE_CAPTURE(PathCommandsCHROMIUM, isCallValid, context, pathPacked, numCommands, commands,
-                      numCoords, coordType, coords);
-    }
-}
-
-void GL_APIENTRY PathParameterfCHROMIUMContextANGLE(GLeglContext ctx,
-                                                    GLuint path,
-                                                    GLenum pname,
-                                                    GLfloat value)
-{
-    Context *context = static_cast<gl::Context *>(ctx);
-    EVENT("glPathParameterfCHROMIUM",
-          "context = %d, GLuint path = %u, GLenum pname = %s, GLfloat value = %f", CID(context),
-          path, GLenumToString(GLenumGroup::DefaultGroup, pname), value);
-
-    if (context)
-    {
-        ASSERT(context == GetValidGlobalContext());
-        PathID pathPacked                                     = FromGL<PathID>(path);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid                                      = (context->skipValidation() ||
-                            ValidatePathParameterfCHROMIUM(context, pathPacked, pname, value));
-        if (isCallValid)
-        {
-            context->pathParameterf(pathPacked, pname, value);
-        }
-        ANGLE_CAPTURE(PathParameterfCHROMIUM, isCallValid, context, pathPacked, pname, value);
-    }
-}
-
-void GL_APIENTRY PathParameteriCHROMIUMContextANGLE(GLeglContext ctx,
-                                                    GLuint path,
-                                                    GLenum pname,
-                                                    GLint value)
-{
-    Context *context = static_cast<gl::Context *>(ctx);
-    EVENT("glPathParameteriCHROMIUM",
-          "context = %d, GLuint path = %u, GLenum pname = %s, GLint value = %d", CID(context), path,
-          GLenumToString(GLenumGroup::DefaultGroup, pname), value);
-
-    if (context)
-    {
-        ASSERT(context == GetValidGlobalContext());
-        PathID pathPacked                                     = FromGL<PathID>(path);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid                                      = (context->skipValidation() ||
-                            ValidatePathParameteriCHROMIUM(context, pathPacked, pname, value));
-        if (isCallValid)
-        {
-            context->pathParameteri(pathPacked, pname, value);
-        }
-        ANGLE_CAPTURE(PathParameteriCHROMIUM, isCallValid, context, pathPacked, pname, value);
-    }
-}
-
-void GL_APIENTRY GetPathParameterfvCHROMIUMContextANGLE(GLeglContext ctx,
-                                                        GLuint path,
-                                                        GLenum pname,
-                                                        GLfloat *value)
-{
-    Context *context = static_cast<gl::Context *>(ctx);
-    EVENT("glGetPathParameterfvCHROMIUM",
-          "context = %d, GLuint path = %u, GLenum pname = %s, GLfloat * value = 0x%016" PRIxPTR "",
-          CID(context), path, GLenumToString(GLenumGroup::DefaultGroup, pname), (uintptr_t)value);
-
-    if (context)
-    {
-        ASSERT(context == GetValidGlobalContext());
-        PathID pathPacked                                     = FromGL<PathID>(path);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid                                      = (context->skipValidation() ||
-                            ValidateGetPathParameterfvCHROMIUM(context, pathPacked, pname, value));
-        if (isCallValid)
-        {
-            context->getPathParameterfv(pathPacked, pname, value);
-        }
-        ANGLE_CAPTURE(GetPathParameterfvCHROMIUM, isCallValid, context, pathPacked, pname, value);
-    }
-}
-
-void GL_APIENTRY GetPathParameterivCHROMIUMContextANGLE(GLeglContext ctx,
-                                                        GLuint path,
-                                                        GLenum pname,
-                                                        GLint *value)
-{
-    Context *context = static_cast<gl::Context *>(ctx);
-    EVENT("glGetPathParameterivCHROMIUM",
-          "context = %d, GLuint path = %u, GLenum pname = %s, GLint * value = 0x%016" PRIxPTR "",
-          CID(context), path, GLenumToString(GLenumGroup::DefaultGroup, pname), (uintptr_t)value);
-
-    if (context)
-    {
-        ASSERT(context == GetValidGlobalContext());
-        PathID pathPacked                                     = FromGL<PathID>(path);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid                                      = (context->skipValidation() ||
-                            ValidateGetPathParameterivCHROMIUM(context, pathPacked, pname, value));
-        if (isCallValid)
-        {
-            context->getPathParameteriv(pathPacked, pname, value);
-        }
-        ANGLE_CAPTURE(GetPathParameterivCHROMIUM, isCallValid, context, pathPacked, pname, value);
-    }
-}
-
-void GL_APIENTRY PathStencilFuncCHROMIUMContextANGLE(GLeglContext ctx,
-                                                     GLenum func,
-                                                     GLint ref,
-                                                     GLuint mask)
-{
-    Context *context = static_cast<gl::Context *>(ctx);
-    EVENT("glPathStencilFuncCHROMIUM",
-          "context = %d, GLenum func = %s, GLint ref = %d, GLuint mask = %u", CID(context),
-          GLenumToString(GLenumGroup::DefaultGroup, func), ref, mask);
-
-    if (context)
-    {
-        ASSERT(context == GetValidGlobalContext());
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid                                      = (context->skipValidation() ||
-                            ValidatePathStencilFuncCHROMIUM(context, func, ref, mask));
-        if (isCallValid)
-        {
-            context->pathStencilFunc(func, ref, mask);
-        }
-        ANGLE_CAPTURE(PathStencilFuncCHROMIUM, isCallValid, context, func, ref, mask);
-    }
-}
-
-void GL_APIENTRY StencilFillPathCHROMIUMContextANGLE(GLeglContext ctx,
-                                                     GLuint path,
-                                                     GLenum fillMode,
-                                                     GLuint mask)
-{
-    Context *context = static_cast<gl::Context *>(ctx);
-    EVENT("glStencilFillPathCHROMIUM",
-          "context = %d, GLuint path = %u, GLenum fillMode = %s, GLuint mask = %u", CID(context),
-          path, GLenumToString(GLenumGroup::DefaultGroup, fillMode), mask);
-
-    if (context)
-    {
-        ASSERT(context == GetValidGlobalContext());
-        PathID pathPacked                                     = FromGL<PathID>(path);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid                                      = (context->skipValidation() ||
-                            ValidateStencilFillPathCHROMIUM(context, pathPacked, fillMode, mask));
-        if (isCallValid)
-        {
-            context->stencilFillPath(pathPacked, fillMode, mask);
-        }
-        ANGLE_CAPTURE(StencilFillPathCHROMIUM, isCallValid, context, pathPacked, fillMode, mask);
-    }
-}
-
-void GL_APIENTRY StencilStrokePathCHROMIUMContextANGLE(GLeglContext ctx,
-                                                       GLuint path,
-                                                       GLint reference,
-                                                       GLuint mask)
-{
-    Context *context = static_cast<gl::Context *>(ctx);
-    EVENT("glStencilStrokePathCHROMIUM",
-          "context = %d, GLuint path = %u, GLint reference = %d, GLuint mask = %u", CID(context),
-          path, reference, mask);
-
-    if (context)
-    {
-        ASSERT(context == GetValidGlobalContext());
-        PathID pathPacked                                     = FromGL<PathID>(path);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid = (context->skipValidation() || ValidateStencilStrokePathCHROMIUM(
-                                                             context, pathPacked, reference, mask));
-        if (isCallValid)
-        {
-            context->stencilStrokePath(pathPacked, reference, mask);
-        }
-        ANGLE_CAPTURE(StencilStrokePathCHROMIUM, isCallValid, context, pathPacked, reference, mask);
-    }
-}
-
-void GL_APIENTRY CoverFillPathCHROMIUMContextANGLE(GLeglContext ctx, GLuint path, GLenum coverMode)
-{
-    Context *context = static_cast<gl::Context *>(ctx);
-    EVENT("glCoverFillPathCHROMIUM", "context = %d, GLuint path = %u, GLenum coverMode = %s",
-          CID(context), path, GLenumToString(GLenumGroup::DefaultGroup, coverMode));
-
-    if (context)
-    {
-        ASSERT(context == GetValidGlobalContext());
-        PathID pathPacked                                     = FromGL<PathID>(path);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid                                      = (context->skipValidation() ||
-                            ValidateCoverFillPathCHROMIUM(context, pathPacked, coverMode));
-        if (isCallValid)
-        {
-            context->coverFillPath(pathPacked, coverMode);
-        }
-        ANGLE_CAPTURE(CoverFillPathCHROMIUM, isCallValid, context, pathPacked, coverMode);
-    }
-}
-
-void GL_APIENTRY CoverStrokePathCHROMIUMContextANGLE(GLeglContext ctx,
-                                                     GLuint path,
-                                                     GLenum coverMode)
-{
-    Context *context = static_cast<gl::Context *>(ctx);
-    EVENT("glCoverStrokePathCHROMIUM", "context = %d, GLuint path = %u, GLenum coverMode = %s",
-          CID(context), path, GLenumToString(GLenumGroup::DefaultGroup, coverMode));
-
-    if (context)
-    {
-        ASSERT(context == GetValidGlobalContext());
-        PathID pathPacked                                     = FromGL<PathID>(path);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid                                      = (context->skipValidation() ||
-                            ValidateCoverStrokePathCHROMIUM(context, pathPacked, coverMode));
-        if (isCallValid)
-        {
-            context->coverStrokePath(pathPacked, coverMode);
-        }
-        ANGLE_CAPTURE(CoverStrokePathCHROMIUM, isCallValid, context, pathPacked, coverMode);
-    }
-}
-
-void GL_APIENTRY StencilThenCoverFillPathCHROMIUMContextANGLE(GLeglContext ctx,
-                                                              GLuint path,
-                                                              GLenum fillMode,
-                                                              GLuint mask,
-                                                              GLenum coverMode)
-{
-    Context *context = static_cast<gl::Context *>(ctx);
-    EVENT("glStencilThenCoverFillPathCHROMIUM",
-          "context = %d, GLuint path = %u, GLenum fillMode = %s, GLuint mask = %u, GLenum "
-          "coverMode = %s",
-          CID(context), path, GLenumToString(GLenumGroup::DefaultGroup, fillMode), mask,
-          GLenumToString(GLenumGroup::DefaultGroup, coverMode));
-
-    if (context)
-    {
-        ASSERT(context == GetValidGlobalContext());
-        PathID pathPacked                                     = FromGL<PathID>(path);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid =
-            (context->skipValidation() || ValidateStencilThenCoverFillPathCHROMIUM(
-                                              context, pathPacked, fillMode, mask, coverMode));
-        if (isCallValid)
-        {
-            context->stencilThenCoverFillPath(pathPacked, fillMode, mask, coverMode);
-        }
-        ANGLE_CAPTURE(StencilThenCoverFillPathCHROMIUM, isCallValid, context, pathPacked, fillMode,
-                      mask, coverMode);
-    }
-}
-
-void GL_APIENTRY StencilThenCoverStrokePathCHROMIUMContextANGLE(GLeglContext ctx,
-                                                                GLuint path,
-                                                                GLint reference,
-                                                                GLuint mask,
-                                                                GLenum coverMode)
-{
-    Context *context = static_cast<gl::Context *>(ctx);
-    EVENT("glStencilThenCoverStrokePathCHROMIUM",
-          "context = %d, GLuint path = %u, GLint reference = %d, GLuint mask = %u, GLenum "
-          "coverMode = %s",
-          CID(context), path, reference, mask,
-          GLenumToString(GLenumGroup::DefaultGroup, coverMode));
-
-    if (context)
-    {
-        ASSERT(context == GetValidGlobalContext());
-        PathID pathPacked                                     = FromGL<PathID>(path);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid =
-            (context->skipValidation() || ValidateStencilThenCoverStrokePathCHROMIUM(
-                                              context, pathPacked, reference, mask, coverMode));
-        if (isCallValid)
-        {
-            context->stencilThenCoverStrokePath(pathPacked, reference, mask, coverMode);
-        }
-        ANGLE_CAPTURE(StencilThenCoverStrokePathCHROMIUM, isCallValid, context, pathPacked,
-                      reference, mask, coverMode);
-    }
-}
-
-void GL_APIENTRY CoverFillPathInstancedCHROMIUMContextANGLE(GLeglContext ctx,
-                                                            GLsizei numPath,
-                                                            GLenum pathNameType,
-                                                            const void *paths,
-                                                            GLuint pathBase,
-                                                            GLenum coverMode,
-                                                            GLenum transformType,
-                                                            const GLfloat *transformValues)
-{
-    Context *context = static_cast<gl::Context *>(ctx);
-    EVENT("glCoverFillPathInstancedCHROMIUM",
-          "context = %d, GLsizei numPath = %d, GLenum pathNameType = %s, const void * paths = "
-          "0x%016" PRIxPTR
-          ", GLuint pathBase = %u, GLenum coverMode = %s, GLenum transformType = %s, const GLfloat "
-          "* transformValues = 0x%016" PRIxPTR "",
-          CID(context), numPath, GLenumToString(GLenumGroup::DefaultGroup, pathNameType),
-          (uintptr_t)paths, pathBase, GLenumToString(GLenumGroup::DefaultGroup, coverMode),
-          GLenumToString(GLenumGroup::DefaultGroup, transformType), (uintptr_t)transformValues);
-
-    if (context)
-    {
-        ASSERT(context == GetValidGlobalContext());
-        PathID pathBasePacked                                 = FromGL<PathID>(pathBase);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid =
-            (context->skipValidation() || ValidateCoverFillPathInstancedCHROMIUM(
-                                              context, numPath, pathNameType, paths, pathBasePacked,
-                                              coverMode, transformType, transformValues));
-        if (isCallValid)
-        {
-            context->coverFillPathInstanced(numPath, pathNameType, paths, pathBasePacked, coverMode,
-                                            transformType, transformValues);
-        }
-        ANGLE_CAPTURE(CoverFillPathInstancedCHROMIUM, isCallValid, context, numPath, pathNameType,
-                      paths, pathBasePacked, coverMode, transformType, transformValues);
-    }
-}
-
-void GL_APIENTRY CoverStrokePathInstancedCHROMIUMContextANGLE(GLeglContext ctx,
-                                                              GLsizei numPath,
-                                                              GLenum pathNameType,
-                                                              const void *paths,
-                                                              GLuint pathBase,
-                                                              GLenum coverMode,
-                                                              GLenum transformType,
-                                                              const GLfloat *transformValues)
-{
-    Context *context = static_cast<gl::Context *>(ctx);
-    EVENT("glCoverStrokePathInstancedCHROMIUM",
-          "context = %d, GLsizei numPath = %d, GLenum pathNameType = %s, const void * paths = "
-          "0x%016" PRIxPTR
-          ", GLuint pathBase = %u, GLenum coverMode = %s, GLenum transformType = %s, const GLfloat "
-          "* transformValues = 0x%016" PRIxPTR "",
-          CID(context), numPath, GLenumToString(GLenumGroup::DefaultGroup, pathNameType),
-          (uintptr_t)paths, pathBase, GLenumToString(GLenumGroup::DefaultGroup, coverMode),
-          GLenumToString(GLenumGroup::DefaultGroup, transformType), (uintptr_t)transformValues);
-
-    if (context)
-    {
-        ASSERT(context == GetValidGlobalContext());
-        PathID pathBasePacked                                 = FromGL<PathID>(pathBase);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid =
-            (context->skipValidation() || ValidateCoverStrokePathInstancedCHROMIUM(
-                                              context, numPath, pathNameType, paths, pathBasePacked,
-                                              coverMode, transformType, transformValues));
-        if (isCallValid)
-        {
-            context->coverStrokePathInstanced(numPath, pathNameType, paths, pathBasePacked,
-                                              coverMode, transformType, transformValues);
-        }
-        ANGLE_CAPTURE(CoverStrokePathInstancedCHROMIUM, isCallValid, context, numPath, pathNameType,
-                      paths, pathBasePacked, coverMode, transformType, transformValues);
-    }
-}
-
-void GL_APIENTRY StencilStrokePathInstancedCHROMIUMContextANGLE(GLeglContext ctx,
-                                                                GLsizei numPath,
-                                                                GLenum pathNameType,
-                                                                const void *paths,
-                                                                GLuint pathBase,
-                                                                GLint reference,
-                                                                GLuint mask,
-                                                                GLenum transformType,
-                                                                const GLfloat *transformValues)
-{
-    Context *context = static_cast<gl::Context *>(ctx);
-    EVENT("glStencilStrokePathInstancedCHROMIUM",
-          "context = %d, GLsizei numPath = %d, GLenum pathNameType = %s, const void * paths = "
-          "0x%016" PRIxPTR
-          ", GLuint pathBase = %u, GLint reference = %d, GLuint mask = %u, GLenum transformType = "
-          "%s, const GLfloat * transformValues = 0x%016" PRIxPTR "",
-          CID(context), numPath, GLenumToString(GLenumGroup::DefaultGroup, pathNameType),
-          (uintptr_t)paths, pathBase, reference, mask,
-          GLenumToString(GLenumGroup::DefaultGroup, transformType), (uintptr_t)transformValues);
-
-    if (context)
-    {
-        ASSERT(context == GetValidGlobalContext());
-        PathID pathBasePacked                                 = FromGL<PathID>(pathBase);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid =
-            (context->skipValidation() || ValidateStencilStrokePathInstancedCHROMIUM(
-                                              context, numPath, pathNameType, paths, pathBasePacked,
-                                              reference, mask, transformType, transformValues));
-        if (isCallValid)
-        {
-            context->stencilStrokePathInstanced(numPath, pathNameType, paths, pathBasePacked,
-                                                reference, mask, transformType, transformValues);
-        }
-        ANGLE_CAPTURE(StencilStrokePathInstancedCHROMIUM, isCallValid, context, numPath,
-                      pathNameType, paths, pathBasePacked, reference, mask, transformType,
-                      transformValues);
-    }
-}
-
-void GL_APIENTRY StencilFillPathInstancedCHROMIUMContextANGLE(GLeglContext ctx,
-                                                              GLsizei numPaths,
-                                                              GLenum pathNameType,
-                                                              const void *paths,
-                                                              GLuint pathBase,
-                                                              GLenum fillMode,
-                                                              GLuint mask,
-                                                              GLenum transformType,
-                                                              const GLfloat *transformValues)
-{
-    Context *context = static_cast<gl::Context *>(ctx);
-    EVENT("glStencilFillPathInstancedCHROMIUM",
-          "context = %d, GLsizei numPaths = %d, GLenum pathNameType = %s, const void * paths = "
-          "0x%016" PRIxPTR
-          ", GLuint pathBase = %u, GLenum fillMode = %s, GLuint mask = %u, GLenum transformType = "
-          "%s, const GLfloat * transformValues = 0x%016" PRIxPTR "",
-          CID(context), numPaths, GLenumToString(GLenumGroup::DefaultGroup, pathNameType),
-          (uintptr_t)paths, pathBase, GLenumToString(GLenumGroup::DefaultGroup, fillMode), mask,
-          GLenumToString(GLenumGroup::DefaultGroup, transformType), (uintptr_t)transformValues);
-
-    if (context)
-    {
-        ASSERT(context == GetValidGlobalContext());
-        PathID pathBasePacked                                 = FromGL<PathID>(pathBase);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid                                      = (context->skipValidation() ||
-                            ValidateStencilFillPathInstancedCHROMIUM(
-                                context, numPaths, pathNameType, paths, pathBasePacked, fillMode,
-                                mask, transformType, transformValues));
-        if (isCallValid)
-        {
-            context->stencilFillPathInstanced(numPaths, pathNameType, paths, pathBasePacked,
-                                              fillMode, mask, transformType, transformValues);
-        }
-        ANGLE_CAPTURE(StencilFillPathInstancedCHROMIUM, isCallValid, context, numPaths,
-                      pathNameType, paths, pathBasePacked, fillMode, mask, transformType,
-                      transformValues);
-    }
-}
-
-void GL_APIENTRY
-StencilThenCoverFillPathInstancedCHROMIUMContextANGLE(GLeglContext ctx,
-                                                      GLsizei numPaths,
-                                                      GLenum pathNameType,
-                                                      const void *paths,
-                                                      GLuint pathBase,
-                                                      GLenum fillMode,
-                                                      GLuint mask,
-                                                      GLenum coverMode,
-                                                      GLenum transformType,
-                                                      const GLfloat *transformValues)
-{
-    Context *context = static_cast<gl::Context *>(ctx);
-    EVENT("glStencilThenCoverFillPathInstancedCHROMIUM",
-          "context = %d, GLsizei numPaths = %d, GLenum pathNameType = %s, const void * paths = "
-          "0x%016" PRIxPTR
-          ", GLuint pathBase = %u, GLenum fillMode = %s, GLuint mask = %u, GLenum coverMode = %s, "
-          "GLenum transformType = %s, const GLfloat * transformValues = 0x%016" PRIxPTR "",
-          CID(context), numPaths, GLenumToString(GLenumGroup::DefaultGroup, pathNameType),
-          (uintptr_t)paths, pathBase, GLenumToString(GLenumGroup::DefaultGroup, fillMode), mask,
-          GLenumToString(GLenumGroup::DefaultGroup, coverMode),
-          GLenumToString(GLenumGroup::DefaultGroup, transformType), (uintptr_t)transformValues);
-
-    if (context)
-    {
-        ASSERT(context == GetValidGlobalContext());
-        PathID pathBasePacked                                 = FromGL<PathID>(pathBase);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid                                      = (context->skipValidation() ||
-                            ValidateStencilThenCoverFillPathInstancedCHROMIUM(
-                                context, numPaths, pathNameType, paths, pathBasePacked, fillMode,
-                                mask, coverMode, transformType, transformValues));
-        if (isCallValid)
-        {
-            context->stencilThenCoverFillPathInstanced(numPaths, pathNameType, paths,
-                                                       pathBasePacked, fillMode, mask, coverMode,
-                                                       transformType, transformValues);
-        }
-        ANGLE_CAPTURE(StencilThenCoverFillPathInstancedCHROMIUM, isCallValid, context, numPaths,
-                      pathNameType, paths, pathBasePacked, fillMode, mask, coverMode, transformType,
-                      transformValues);
-    }
-}
-
-void GL_APIENTRY
-StencilThenCoverStrokePathInstancedCHROMIUMContextANGLE(GLeglContext ctx,
-                                                        GLsizei numPaths,
-                                                        GLenum pathNameType,
-                                                        const void *paths,
-                                                        GLuint pathBase,
-                                                        GLint reference,
-                                                        GLuint mask,
-                                                        GLenum coverMode,
-                                                        GLenum transformType,
-                                                        const GLfloat *transformValues)
-{
-    Context *context = static_cast<gl::Context *>(ctx);
-    EVENT("glStencilThenCoverStrokePathInstancedCHROMIUM",
-          "context = %d, GLsizei numPaths = %d, GLenum pathNameType = %s, const void * paths = "
-          "0x%016" PRIxPTR
-          ", GLuint pathBase = %u, GLint reference = %d, GLuint mask = %u, GLenum coverMode = %s, "
-          "GLenum transformType = %s, const GLfloat * transformValues = 0x%016" PRIxPTR "",
-          CID(context), numPaths, GLenumToString(GLenumGroup::DefaultGroup, pathNameType),
-          (uintptr_t)paths, pathBase, reference, mask,
-          GLenumToString(GLenumGroup::DefaultGroup, coverMode),
-          GLenumToString(GLenumGroup::DefaultGroup, transformType), (uintptr_t)transformValues);
-
-    if (context)
-    {
-        ASSERT(context == GetValidGlobalContext());
-        PathID pathBasePacked                                 = FromGL<PathID>(pathBase);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid                                      = (context->skipValidation() ||
-                            ValidateStencilThenCoverStrokePathInstancedCHROMIUM(
-                                context, numPaths, pathNameType, paths, pathBasePacked, reference,
-                                mask, coverMode, transformType, transformValues));
-        if (isCallValid)
-        {
-            context->stencilThenCoverStrokePathInstanced(numPaths, pathNameType, paths,
-                                                         pathBasePacked, reference, mask, coverMode,
-                                                         transformType, transformValues);
-        }
-        ANGLE_CAPTURE(StencilThenCoverStrokePathInstancedCHROMIUM, isCallValid, context, numPaths,
-                      pathNameType, paths, pathBasePacked, reference, mask, coverMode,
-                      transformType, transformValues);
-    }
-}
-
-void GL_APIENTRY BindFragmentInputLocationCHROMIUMContextANGLE(GLeglContext ctx,
-                                                               GLuint programs,
-                                                               GLint location,
-                                                               const GLchar *name)
-{
-    Context *context = static_cast<gl::Context *>(ctx);
-    EVENT("glBindFragmentInputLocationCHROMIUM",
-          "context = %d, GLuint programs = %u, GLint location = %d, const GLchar * name = "
-          "0x%016" PRIxPTR "",
-          CID(context), programs, location, (uintptr_t)name);
-
-    if (context)
-    {
-        ASSERT(context == GetValidGlobalContext());
-        ShaderProgramID programsPacked                        = FromGL<ShaderProgramID>(programs);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid =
-            (context->skipValidation() ||
-             ValidateBindFragmentInputLocationCHROMIUM(context, programsPacked, location, name));
-        if (isCallValid)
-        {
-            context->bindFragmentInputLocation(programsPacked, location, name);
-        }
-        ANGLE_CAPTURE(BindFragmentInputLocationCHROMIUM, isCallValid, context, programsPacked,
-                      location, name);
-    }
-}
-
-void GL_APIENTRY ProgramPathFragmentInputGenCHROMIUMContextANGLE(GLeglContext ctx,
-                                                                 GLuint program,
-                                                                 GLint location,
-                                                                 GLenum genMode,
-                                                                 GLint components,
-                                                                 const GLfloat *coeffs)
-{
-    Context *context = static_cast<gl::Context *>(ctx);
-    EVENT("glProgramPathFragmentInputGenCHROMIUM",
-          "context = %d, GLuint program = %u, GLint location = %d, GLenum genMode = %s, GLint "
-          "components = %d, const GLfloat * coeffs = 0x%016" PRIxPTR "",
-          CID(context), program, location, GLenumToString(GLenumGroup::DefaultGroup, genMode),
-          components, (uintptr_t)coeffs);
-
-    if (context)
-    {
-        ASSERT(context == GetValidGlobalContext());
-        ShaderProgramID programPacked                         = FromGL<ShaderProgramID>(program);
-        std::unique_lock<angle::GlobalMutex> shareContextLock = GetShareGroupLock(context);
-        bool isCallValid                                      = (context->skipValidation() ||
-                            ValidateProgramPathFragmentInputGenCHROMIUM(
-                                context, programPacked, location, genMode, components, coeffs));
-        if (isCallValid)
-        {
-            context->programPathFragmentInputGen(programPacked, location, genMode, components,
-                                                 coeffs);
-        }
-        ANGLE_CAPTURE(ProgramPathFragmentInputGenCHROMIUM, isCallValid, context, programPacked,
-                      location, genMode, components, coeffs);
-    }
-}
-
 void GL_APIENTRY CopyTextureCHROMIUMContextANGLE(GLeglContext ctx,
                                                  GLuint sourceId,
                                                  GLint sourceLevel,
diff --git a/src/libGLESv2/entry_points_gles_ext_autogen.h b/src/libGLESv2/entry_points_gles_ext_autogen.h
index 7ee0c66..345c248 100644
--- a/src/libGLESv2/entry_points_gles_ext_autogen.h
+++ b/src/libGLESv2/entry_points_gles_ext_autogen.h
@@ -601,98 +601,10 @@
 
 // GL_CHROMIUM_framebuffer_mixed_samples
 ANGLE_EXPORT void GL_APIENTRY CoverageModulationCHROMIUM(GLenum components);
-ANGLE_EXPORT void GL_APIENTRY MatrixLoadfCHROMIUM(GLenum matrixMode, const GLfloat *matrix);
-ANGLE_EXPORT void GL_APIENTRY MatrixLoadIdentityCHROMIUM(GLenum matrixMode);
 
 // GL_CHROMIUM_lose_context
 ANGLE_EXPORT void GL_APIENTRY LoseContextCHROMIUM(GLenum current, GLenum other);
 
-// GL_CHROMIUM_path_rendering
-ANGLE_EXPORT GLuint GL_APIENTRY GenPathsCHROMIUM(GLsizei range);
-ANGLE_EXPORT void GL_APIENTRY DeletePathsCHROMIUM(GLuint first, GLsizei range);
-ANGLE_EXPORT GLboolean GL_APIENTRY IsPathCHROMIUM(GLuint path);
-ANGLE_EXPORT void GL_APIENTRY PathCommandsCHROMIUM(GLuint path,
-                                                   GLsizei numCommands,
-                                                   const GLubyte *commands,
-                                                   GLsizei numCoords,
-                                                   GLenum coordType,
-                                                   const void *coords);
-ANGLE_EXPORT void GL_APIENTRY PathParameterfCHROMIUM(GLuint path, GLenum pname, GLfloat value);
-ANGLE_EXPORT void GL_APIENTRY PathParameteriCHROMIUM(GLuint path, GLenum pname, GLint value);
-ANGLE_EXPORT void GL_APIENTRY GetPathParameterfvCHROMIUM(GLuint path, GLenum pname, GLfloat *value);
-ANGLE_EXPORT void GL_APIENTRY GetPathParameterivCHROMIUM(GLuint path, GLenum pname, GLint *value);
-ANGLE_EXPORT void GL_APIENTRY PathStencilFuncCHROMIUM(GLenum func, GLint ref, GLuint mask);
-ANGLE_EXPORT void GL_APIENTRY StencilFillPathCHROMIUM(GLuint path, GLenum fillMode, GLuint mask);
-ANGLE_EXPORT void GL_APIENTRY StencilStrokePathCHROMIUM(GLuint path, GLint reference, GLuint mask);
-ANGLE_EXPORT void GL_APIENTRY CoverFillPathCHROMIUM(GLuint path, GLenum coverMode);
-ANGLE_EXPORT void GL_APIENTRY CoverStrokePathCHROMIUM(GLuint path, GLenum coverMode);
-ANGLE_EXPORT void GL_APIENTRY StencilThenCoverFillPathCHROMIUM(GLuint path,
-                                                               GLenum fillMode,
-                                                               GLuint mask,
-                                                               GLenum coverMode);
-ANGLE_EXPORT void GL_APIENTRY StencilThenCoverStrokePathCHROMIUM(GLuint path,
-                                                                 GLint reference,
-                                                                 GLuint mask,
-                                                                 GLenum coverMode);
-ANGLE_EXPORT void GL_APIENTRY CoverFillPathInstancedCHROMIUM(GLsizei numPath,
-                                                             GLenum pathNameType,
-                                                             const void *paths,
-                                                             GLuint pathBase,
-                                                             GLenum coverMode,
-                                                             GLenum transformType,
-                                                             const GLfloat *transformValues);
-ANGLE_EXPORT void GL_APIENTRY CoverStrokePathInstancedCHROMIUM(GLsizei numPath,
-                                                               GLenum pathNameType,
-                                                               const void *paths,
-                                                               GLuint pathBase,
-                                                               GLenum coverMode,
-                                                               GLenum transformType,
-                                                               const GLfloat *transformValues);
-ANGLE_EXPORT void GL_APIENTRY StencilStrokePathInstancedCHROMIUM(GLsizei numPath,
-                                                                 GLenum pathNameType,
-                                                                 const void *paths,
-                                                                 GLuint pathBase,
-                                                                 GLint reference,
-                                                                 GLuint mask,
-                                                                 GLenum transformType,
-                                                                 const GLfloat *transformValues);
-ANGLE_EXPORT void GL_APIENTRY StencilFillPathInstancedCHROMIUM(GLsizei numPaths,
-                                                               GLenum pathNameType,
-                                                               const void *paths,
-                                                               GLuint pathBase,
-                                                               GLenum fillMode,
-                                                               GLuint mask,
-                                                               GLenum transformType,
-                                                               const GLfloat *transformValues);
-ANGLE_EXPORT void GL_APIENTRY
-StencilThenCoverFillPathInstancedCHROMIUM(GLsizei numPaths,
-                                          GLenum pathNameType,
-                                          const void *paths,
-                                          GLuint pathBase,
-                                          GLenum fillMode,
-                                          GLuint mask,
-                                          GLenum coverMode,
-                                          GLenum transformType,
-                                          const GLfloat *transformValues);
-ANGLE_EXPORT void GL_APIENTRY
-StencilThenCoverStrokePathInstancedCHROMIUM(GLsizei numPaths,
-                                            GLenum pathNameType,
-                                            const void *paths,
-                                            GLuint pathBase,
-                                            GLint reference,
-                                            GLuint mask,
-                                            GLenum coverMode,
-                                            GLenum transformType,
-                                            const GLfloat *transformValues);
-ANGLE_EXPORT void GL_APIENTRY BindFragmentInputLocationCHROMIUM(GLuint programs,
-                                                                GLint location,
-                                                                const GLchar *name);
-ANGLE_EXPORT void GL_APIENTRY ProgramPathFragmentInputGenCHROMIUM(GLuint program,
-                                                                  GLint location,
-                                                                  GLenum genMode,
-                                                                  GLint components,
-                                                                  const GLfloat *coeffs);
-
 // GL_EXT_blend_func_extended
 ANGLE_EXPORT void GL_APIENTRY BindFragDataLocationEXT(GLuint program,
                                                       GLuint color,
@@ -933,6 +845,8 @@
 
 // GL_EXT_texture_format_BGRA8888
 
+// GL_EXT_texture_sRGB_R8
+
 // GL_EXT_texture_storage
 ANGLE_EXPORT void GL_APIENTRY TexStorage1DEXT(GLenum target,
                                               GLsizei levels,
@@ -3677,138 +3591,6 @@
                                                                       const GLchar *name);
 ANGLE_EXPORT void GL_APIENTRY CoverageModulationCHROMIUMContextANGLE(GLeglContext ctx,
                                                                      GLenum components);
-ANGLE_EXPORT void GL_APIENTRY MatrixLoadfCHROMIUMContextANGLE(GLeglContext ctx,
-                                                              GLenum matrixMode,
-                                                              const GLfloat *matrix);
-ANGLE_EXPORT void GL_APIENTRY MatrixLoadIdentityCHROMIUMContextANGLE(GLeglContext ctx,
-                                                                     GLenum matrixMode);
-ANGLE_EXPORT GLuint GL_APIENTRY GenPathsCHROMIUMContextANGLE(GLeglContext ctx, GLsizei range);
-ANGLE_EXPORT void GL_APIENTRY DeletePathsCHROMIUMContextANGLE(GLeglContext ctx,
-                                                              GLuint first,
-                                                              GLsizei range);
-ANGLE_EXPORT GLboolean GL_APIENTRY IsPathCHROMIUMContextANGLE(GLeglContext ctx, GLuint path);
-ANGLE_EXPORT void GL_APIENTRY PathCommandsCHROMIUMContextANGLE(GLeglContext ctx,
-                                                               GLuint path,
-                                                               GLsizei numCommands,
-                                                               const GLubyte *commands,
-                                                               GLsizei numCoords,
-                                                               GLenum coordType,
-                                                               const void *coords);
-ANGLE_EXPORT void GL_APIENTRY PathParameterfCHROMIUMContextANGLE(GLeglContext ctx,
-                                                                 GLuint path,
-                                                                 GLenum pname,
-                                                                 GLfloat value);
-ANGLE_EXPORT void GL_APIENTRY PathParameteriCHROMIUMContextANGLE(GLeglContext ctx,
-                                                                 GLuint path,
-                                                                 GLenum pname,
-                                                                 GLint value);
-ANGLE_EXPORT void GL_APIENTRY GetPathParameterfvCHROMIUMContextANGLE(GLeglContext ctx,
-                                                                     GLuint path,
-                                                                     GLenum pname,
-                                                                     GLfloat *value);
-ANGLE_EXPORT void GL_APIENTRY GetPathParameterivCHROMIUMContextANGLE(GLeglContext ctx,
-                                                                     GLuint path,
-                                                                     GLenum pname,
-                                                                     GLint *value);
-ANGLE_EXPORT void GL_APIENTRY PathStencilFuncCHROMIUMContextANGLE(GLeglContext ctx,
-                                                                  GLenum func,
-                                                                  GLint ref,
-                                                                  GLuint mask);
-ANGLE_EXPORT void GL_APIENTRY StencilFillPathCHROMIUMContextANGLE(GLeglContext ctx,
-                                                                  GLuint path,
-                                                                  GLenum fillMode,
-                                                                  GLuint mask);
-ANGLE_EXPORT void GL_APIENTRY StencilStrokePathCHROMIUMContextANGLE(GLeglContext ctx,
-                                                                    GLuint path,
-                                                                    GLint reference,
-                                                                    GLuint mask);
-ANGLE_EXPORT void GL_APIENTRY CoverFillPathCHROMIUMContextANGLE(GLeglContext ctx,
-                                                                GLuint path,
-                                                                GLenum coverMode);
-ANGLE_EXPORT void GL_APIENTRY CoverStrokePathCHROMIUMContextANGLE(GLeglContext ctx,
-                                                                  GLuint path,
-                                                                  GLenum coverMode);
-ANGLE_EXPORT void GL_APIENTRY StencilThenCoverFillPathCHROMIUMContextANGLE(GLeglContext ctx,
-                                                                           GLuint path,
-                                                                           GLenum fillMode,
-                                                                           GLuint mask,
-                                                                           GLenum coverMode);
-ANGLE_EXPORT void GL_APIENTRY StencilThenCoverStrokePathCHROMIUMContextANGLE(GLeglContext ctx,
-                                                                             GLuint path,
-                                                                             GLint reference,
-                                                                             GLuint mask,
-                                                                             GLenum coverMode);
-ANGLE_EXPORT void GL_APIENTRY
-CoverFillPathInstancedCHROMIUMContextANGLE(GLeglContext ctx,
-                                           GLsizei numPath,
-                                           GLenum pathNameType,
-                                           const void *paths,
-                                           GLuint pathBase,
-                                           GLenum coverMode,
-                                           GLenum transformType,
-                                           const GLfloat *transformValues);
-ANGLE_EXPORT void GL_APIENTRY
-CoverStrokePathInstancedCHROMIUMContextANGLE(GLeglContext ctx,
-                                             GLsizei numPath,
-                                             GLenum pathNameType,
-                                             const void *paths,
-                                             GLuint pathBase,
-                                             GLenum coverMode,
-                                             GLenum transformType,
-                                             const GLfloat *transformValues);
-ANGLE_EXPORT void GL_APIENTRY
-StencilStrokePathInstancedCHROMIUMContextANGLE(GLeglContext ctx,
-                                               GLsizei numPath,
-                                               GLenum pathNameType,
-                                               const void *paths,
-                                               GLuint pathBase,
-                                               GLint reference,
-                                               GLuint mask,
-                                               GLenum transformType,
-                                               const GLfloat *transformValues);
-ANGLE_EXPORT void GL_APIENTRY
-StencilFillPathInstancedCHROMIUMContextANGLE(GLeglContext ctx,
-                                             GLsizei numPaths,
-                                             GLenum pathNameType,
-                                             const void *paths,
-                                             GLuint pathBase,
-                                             GLenum fillMode,
-                                             GLuint mask,
-                                             GLenum transformType,
-                                             const GLfloat *transformValues);
-ANGLE_EXPORT void GL_APIENTRY
-StencilThenCoverFillPathInstancedCHROMIUMContextANGLE(GLeglContext ctx,
-                                                      GLsizei numPaths,
-                                                      GLenum pathNameType,
-                                                      const void *paths,
-                                                      GLuint pathBase,
-                                                      GLenum fillMode,
-                                                      GLuint mask,
-                                                      GLenum coverMode,
-                                                      GLenum transformType,
-                                                      const GLfloat *transformValues);
-ANGLE_EXPORT void GL_APIENTRY
-StencilThenCoverStrokePathInstancedCHROMIUMContextANGLE(GLeglContext ctx,
-                                                        GLsizei numPaths,
-                                                        GLenum pathNameType,
-                                                        const void *paths,
-                                                        GLuint pathBase,
-                                                        GLint reference,
-                                                        GLuint mask,
-                                                        GLenum coverMode,
-                                                        GLenum transformType,
-                                                        const GLfloat *transformValues);
-ANGLE_EXPORT void GL_APIENTRY BindFragmentInputLocationCHROMIUMContextANGLE(GLeglContext ctx,
-                                                                            GLuint programs,
-                                                                            GLint location,
-                                                                            const GLchar *name);
-ANGLE_EXPORT void GL_APIENTRY
-ProgramPathFragmentInputGenCHROMIUMContextANGLE(GLeglContext ctx,
-                                                GLuint program,
-                                                GLint location,
-                                                GLenum genMode,
-                                                GLint components,
-                                                const GLfloat *coeffs);
 ANGLE_EXPORT void GL_APIENTRY CopyTextureCHROMIUMContextANGLE(GLeglContext ctx,
                                                               GLuint sourceId,
                                                               GLint sourceLevel,
diff --git a/src/libGLESv2/libGLESv2_autogen.cpp b/src/libGLESv2/libGLESv2_autogen.cpp
index 0e0ead4..9115710 100644
--- a/src/libGLESv2/libGLESv2_autogen.cpp
+++ b/src/libGLESv2/libGLESv2_autogen.cpp
@@ -3701,205 +3701,12 @@
     return gl::CoverageModulationCHROMIUM(components);
 }
 
-void GL_APIENTRY glMatrixLoadfCHROMIUM(GLenum matrixMode, const GLfloat *matrix)
-{
-    return gl::MatrixLoadfCHROMIUM(matrixMode, matrix);
-}
-
-void GL_APIENTRY glMatrixLoadIdentityCHROMIUM(GLenum matrixMode)
-{
-    return gl::MatrixLoadIdentityCHROMIUM(matrixMode);
-}
-
 // GL_CHROMIUM_lose_context
 void GL_APIENTRY glLoseContextCHROMIUM(GLenum current, GLenum other)
 {
     return gl::LoseContextCHROMIUM(current, other);
 }
 
-// GL_CHROMIUM_path_rendering
-GLuint GL_APIENTRY glGenPathsCHROMIUM(GLsizei range)
-{
-    return gl::GenPathsCHROMIUM(range);
-}
-
-void GL_APIENTRY glDeletePathsCHROMIUM(GLuint first, GLsizei range)
-{
-    return gl::DeletePathsCHROMIUM(first, range);
-}
-
-GLboolean GL_APIENTRY glIsPathCHROMIUM(GLuint path)
-{
-    return gl::IsPathCHROMIUM(path);
-}
-
-void GL_APIENTRY glPathCommandsCHROMIUM(GLuint path,
-                                        GLsizei numCommands,
-                                        const GLubyte *commands,
-                                        GLsizei numCoords,
-                                        GLenum coordType,
-                                        const void *coords)
-{
-    return gl::PathCommandsCHROMIUM(path, numCommands, commands, numCoords, coordType, coords);
-}
-
-void GL_APIENTRY glPathParameterfCHROMIUM(GLuint path, GLenum pname, GLfloat value)
-{
-    return gl::PathParameterfCHROMIUM(path, pname, value);
-}
-
-void GL_APIENTRY glPathParameteriCHROMIUM(GLuint path, GLenum pname, GLint value)
-{
-    return gl::PathParameteriCHROMIUM(path, pname, value);
-}
-
-void GL_APIENTRY glGetPathParameterfvCHROMIUM(GLuint path, GLenum pname, GLfloat *value)
-{
-    return gl::GetPathParameterfvCHROMIUM(path, pname, value);
-}
-
-void GL_APIENTRY glGetPathParameterivCHROMIUM(GLuint path, GLenum pname, GLint *value)
-{
-    return gl::GetPathParameterivCHROMIUM(path, pname, value);
-}
-
-void GL_APIENTRY glPathStencilFuncCHROMIUM(GLenum func, GLint ref, GLuint mask)
-{
-    return gl::PathStencilFuncCHROMIUM(func, ref, mask);
-}
-
-void GL_APIENTRY glStencilFillPathCHROMIUM(GLuint path, GLenum fillMode, GLuint mask)
-{
-    return gl::StencilFillPathCHROMIUM(path, fillMode, mask);
-}
-
-void GL_APIENTRY glStencilStrokePathCHROMIUM(GLuint path, GLint reference, GLuint mask)
-{
-    return gl::StencilStrokePathCHROMIUM(path, reference, mask);
-}
-
-void GL_APIENTRY glCoverFillPathCHROMIUM(GLuint path, GLenum coverMode)
-{
-    return gl::CoverFillPathCHROMIUM(path, coverMode);
-}
-
-void GL_APIENTRY glCoverStrokePathCHROMIUM(GLuint path, GLenum coverMode)
-{
-    return gl::CoverStrokePathCHROMIUM(path, coverMode);
-}
-
-void GL_APIENTRY glStencilThenCoverFillPathCHROMIUM(GLuint path,
-                                                    GLenum fillMode,
-                                                    GLuint mask,
-                                                    GLenum coverMode)
-{
-    return gl::StencilThenCoverFillPathCHROMIUM(path, fillMode, mask, coverMode);
-}
-
-void GL_APIENTRY glStencilThenCoverStrokePathCHROMIUM(GLuint path,
-                                                      GLint reference,
-                                                      GLuint mask,
-                                                      GLenum coverMode)
-{
-    return gl::StencilThenCoverStrokePathCHROMIUM(path, reference, mask, coverMode);
-}
-
-void GL_APIENTRY glCoverFillPathInstancedCHROMIUM(GLsizei numPath,
-                                                  GLenum pathNameType,
-                                                  const void *paths,
-                                                  GLuint pathBase,
-                                                  GLenum coverMode,
-                                                  GLenum transformType,
-                                                  const GLfloat *transformValues)
-{
-    return gl::CoverFillPathInstancedCHROMIUM(numPath, pathNameType, paths, pathBase, coverMode,
-                                              transformType, transformValues);
-}
-
-void GL_APIENTRY glCoverStrokePathInstancedCHROMIUM(GLsizei numPath,
-                                                    GLenum pathNameType,
-                                                    const void *paths,
-                                                    GLuint pathBase,
-                                                    GLenum coverMode,
-                                                    GLenum transformType,
-                                                    const GLfloat *transformValues)
-{
-    return gl::CoverStrokePathInstancedCHROMIUM(numPath, pathNameType, paths, pathBase, coverMode,
-                                                transformType, transformValues);
-}
-
-void GL_APIENTRY glStencilStrokePathInstancedCHROMIUM(GLsizei numPath,
-                                                      GLenum pathNameType,
-                                                      const void *paths,
-                                                      GLuint pathBase,
-                                                      GLint reference,
-                                                      GLuint mask,
-                                                      GLenum transformType,
-                                                      const GLfloat *transformValues)
-{
-    return gl::StencilStrokePathInstancedCHROMIUM(numPath, pathNameType, paths, pathBase, reference,
-                                                  mask, transformType, transformValues);
-}
-
-void GL_APIENTRY glStencilFillPathInstancedCHROMIUM(GLsizei numPaths,
-                                                    GLenum pathNameType,
-                                                    const void *paths,
-                                                    GLuint pathBase,
-                                                    GLenum fillMode,
-                                                    GLuint mask,
-                                                    GLenum transformType,
-                                                    const GLfloat *transformValues)
-{
-    return gl::StencilFillPathInstancedCHROMIUM(numPaths, pathNameType, paths, pathBase, fillMode,
-                                                mask, transformType, transformValues);
-}
-
-void GL_APIENTRY glStencilThenCoverFillPathInstancedCHROMIUM(GLsizei numPaths,
-                                                             GLenum pathNameType,
-                                                             const void *paths,
-                                                             GLuint pathBase,
-                                                             GLenum fillMode,
-                                                             GLuint mask,
-                                                             GLenum coverMode,
-                                                             GLenum transformType,
-                                                             const GLfloat *transformValues)
-{
-    return gl::StencilThenCoverFillPathInstancedCHROMIUM(numPaths, pathNameType, paths, pathBase,
-                                                         fillMode, mask, coverMode, transformType,
-                                                         transformValues);
-}
-
-void GL_APIENTRY glStencilThenCoverStrokePathInstancedCHROMIUM(GLsizei numPaths,
-                                                               GLenum pathNameType,
-                                                               const void *paths,
-                                                               GLuint pathBase,
-                                                               GLint reference,
-                                                               GLuint mask,
-                                                               GLenum coverMode,
-                                                               GLenum transformType,
-                                                               const GLfloat *transformValues)
-{
-    return gl::StencilThenCoverStrokePathInstancedCHROMIUM(numPaths, pathNameType, paths, pathBase,
-                                                           reference, mask, coverMode,
-                                                           transformType, transformValues);
-}
-
-void GL_APIENTRY glBindFragmentInputLocationCHROMIUM(GLuint programs,
-                                                     GLint location,
-                                                     const GLchar *name)
-{
-    return gl::BindFragmentInputLocationCHROMIUM(programs, location, name);
-}
-
-void GL_APIENTRY glProgramPathFragmentInputGenCHROMIUM(GLuint program,
-                                                       GLint location,
-                                                       GLenum genMode,
-                                                       GLint components,
-                                                       const GLfloat *coeffs)
-{
-    return gl::ProgramPathFragmentInputGenCHROMIUM(program, location, genMode, components, coeffs);
-}
-
 // GL_EXT_blend_func_extended
 void GL_APIENTRY glBindFragDataLocationEXT(GLuint program, GLuint color, const GLchar *name)
 {
@@ -4378,6 +4185,8 @@
 
 // GL_EXT_texture_format_BGRA8888
 
+// GL_EXT_texture_sRGB_R8
+
 // GL_EXT_texture_storage
 void GL_APIENTRY glTexStorage1DEXT(GLenum target,
                                    GLsizei levels,
@@ -9788,243 +9597,6 @@
     return gl::CoverageModulationCHROMIUMContextANGLE(ctx, components);
 }
 
-void GL_APIENTRY glMatrixLoadfCHROMIUMContextANGLE(GLeglContext ctx,
-                                                   GLenum matrixMode,
-                                                   const GLfloat *matrix)
-{
-    return gl::MatrixLoadfCHROMIUMContextANGLE(ctx, matrixMode, matrix);
-}
-
-void GL_APIENTRY glMatrixLoadIdentityCHROMIUMContextANGLE(GLeglContext ctx, GLenum matrixMode)
-{
-    return gl::MatrixLoadIdentityCHROMIUMContextANGLE(ctx, matrixMode);
-}
-
-GLuint GL_APIENTRY glGenPathsCHROMIUMContextANGLE(GLeglContext ctx, GLsizei range)
-{
-    return gl::GenPathsCHROMIUMContextANGLE(ctx, range);
-}
-
-void GL_APIENTRY glDeletePathsCHROMIUMContextANGLE(GLeglContext ctx, GLuint first, GLsizei range)
-{
-    return gl::DeletePathsCHROMIUMContextANGLE(ctx, first, range);
-}
-
-GLboolean GL_APIENTRY glIsPathCHROMIUMContextANGLE(GLeglContext ctx, GLuint path)
-{
-    return gl::IsPathCHROMIUMContextANGLE(ctx, path);
-}
-
-void GL_APIENTRY glPathCommandsCHROMIUMContextANGLE(GLeglContext ctx,
-                                                    GLuint path,
-                                                    GLsizei numCommands,
-                                                    const GLubyte *commands,
-                                                    GLsizei numCoords,
-                                                    GLenum coordType,
-                                                    const void *coords)
-{
-    return gl::PathCommandsCHROMIUMContextANGLE(ctx, path, numCommands, commands, numCoords,
-                                                coordType, coords);
-}
-
-void GL_APIENTRY glPathParameterfCHROMIUMContextANGLE(GLeglContext ctx,
-                                                      GLuint path,
-                                                      GLenum pname,
-                                                      GLfloat value)
-{
-    return gl::PathParameterfCHROMIUMContextANGLE(ctx, path, pname, value);
-}
-
-void GL_APIENTRY glPathParameteriCHROMIUMContextANGLE(GLeglContext ctx,
-                                                      GLuint path,
-                                                      GLenum pname,
-                                                      GLint value)
-{
-    return gl::PathParameteriCHROMIUMContextANGLE(ctx, path, pname, value);
-}
-
-void GL_APIENTRY glGetPathParameterfvCHROMIUMContextANGLE(GLeglContext ctx,
-                                                          GLuint path,
-                                                          GLenum pname,
-                                                          GLfloat *value)
-{
-    return gl::GetPathParameterfvCHROMIUMContextANGLE(ctx, path, pname, value);
-}
-
-void GL_APIENTRY glGetPathParameterivCHROMIUMContextANGLE(GLeglContext ctx,
-                                                          GLuint path,
-                                                          GLenum pname,
-                                                          GLint *value)
-{
-    return gl::GetPathParameterivCHROMIUMContextANGLE(ctx, path, pname, value);
-}
-
-void GL_APIENTRY glPathStencilFuncCHROMIUMContextANGLE(GLeglContext ctx,
-                                                       GLenum func,
-                                                       GLint ref,
-                                                       GLuint mask)
-{
-    return gl::PathStencilFuncCHROMIUMContextANGLE(ctx, func, ref, mask);
-}
-
-void GL_APIENTRY glStencilFillPathCHROMIUMContextANGLE(GLeglContext ctx,
-                                                       GLuint path,
-                                                       GLenum fillMode,
-                                                       GLuint mask)
-{
-    return gl::StencilFillPathCHROMIUMContextANGLE(ctx, path, fillMode, mask);
-}
-
-void GL_APIENTRY glStencilStrokePathCHROMIUMContextANGLE(GLeglContext ctx,
-                                                         GLuint path,
-                                                         GLint reference,
-                                                         GLuint mask)
-{
-    return gl::StencilStrokePathCHROMIUMContextANGLE(ctx, path, reference, mask);
-}
-
-void GL_APIENTRY glCoverFillPathCHROMIUMContextANGLE(GLeglContext ctx,
-                                                     GLuint path,
-                                                     GLenum coverMode)
-{
-    return gl::CoverFillPathCHROMIUMContextANGLE(ctx, path, coverMode);
-}
-
-void GL_APIENTRY glCoverStrokePathCHROMIUMContextANGLE(GLeglContext ctx,
-                                                       GLuint path,
-                                                       GLenum coverMode)
-{
-    return gl::CoverStrokePathCHROMIUMContextANGLE(ctx, path, coverMode);
-}
-
-void GL_APIENTRY glStencilThenCoverFillPathCHROMIUMContextANGLE(GLeglContext ctx,
-                                                                GLuint path,
-                                                                GLenum fillMode,
-                                                                GLuint mask,
-                                                                GLenum coverMode)
-{
-    return gl::StencilThenCoverFillPathCHROMIUMContextANGLE(ctx, path, fillMode, mask, coverMode);
-}
-
-void GL_APIENTRY glStencilThenCoverStrokePathCHROMIUMContextANGLE(GLeglContext ctx,
-                                                                  GLuint path,
-                                                                  GLint reference,
-                                                                  GLuint mask,
-                                                                  GLenum coverMode)
-{
-    return gl::StencilThenCoverStrokePathCHROMIUMContextANGLE(ctx, path, reference, mask,
-                                                              coverMode);
-}
-
-void GL_APIENTRY glCoverFillPathInstancedCHROMIUMContextANGLE(GLeglContext ctx,
-                                                              GLsizei numPath,
-                                                              GLenum pathNameType,
-                                                              const void *paths,
-                                                              GLuint pathBase,
-                                                              GLenum coverMode,
-                                                              GLenum transformType,
-                                                              const GLfloat *transformValues)
-{
-    return gl::CoverFillPathInstancedCHROMIUMContextANGLE(
-        ctx, numPath, pathNameType, paths, pathBase, coverMode, transformType, transformValues);
-}
-
-void GL_APIENTRY glCoverStrokePathInstancedCHROMIUMContextANGLE(GLeglContext ctx,
-                                                                GLsizei numPath,
-                                                                GLenum pathNameType,
-                                                                const void *paths,
-                                                                GLuint pathBase,
-                                                                GLenum coverMode,
-                                                                GLenum transformType,
-                                                                const GLfloat *transformValues)
-{
-    return gl::CoverStrokePathInstancedCHROMIUMContextANGLE(
-        ctx, numPath, pathNameType, paths, pathBase, coverMode, transformType, transformValues);
-}
-
-void GL_APIENTRY glStencilStrokePathInstancedCHROMIUMContextANGLE(GLeglContext ctx,
-                                                                  GLsizei numPath,
-                                                                  GLenum pathNameType,
-                                                                  const void *paths,
-                                                                  GLuint pathBase,
-                                                                  GLint reference,
-                                                                  GLuint mask,
-                                                                  GLenum transformType,
-                                                                  const GLfloat *transformValues)
-{
-    return gl::StencilStrokePathInstancedCHROMIUMContextANGLE(ctx, numPath, pathNameType, paths,
-                                                              pathBase, reference, mask,
-                                                              transformType, transformValues);
-}
-
-void GL_APIENTRY glStencilFillPathInstancedCHROMIUMContextANGLE(GLeglContext ctx,
-                                                                GLsizei numPaths,
-                                                                GLenum pathNameType,
-                                                                const void *paths,
-                                                                GLuint pathBase,
-                                                                GLenum fillMode,
-                                                                GLuint mask,
-                                                                GLenum transformType,
-                                                                const GLfloat *transformValues)
-{
-    return gl::StencilFillPathInstancedCHROMIUMContextANGLE(ctx, numPaths, pathNameType, paths,
-                                                            pathBase, fillMode, mask, transformType,
-                                                            transformValues);
-}
-
-void GL_APIENTRY
-glStencilThenCoverFillPathInstancedCHROMIUMContextANGLE(GLeglContext ctx,
-                                                        GLsizei numPaths,
-                                                        GLenum pathNameType,
-                                                        const void *paths,
-                                                        GLuint pathBase,
-                                                        GLenum fillMode,
-                                                        GLuint mask,
-                                                        GLenum coverMode,
-                                                        GLenum transformType,
-                                                        const GLfloat *transformValues)
-{
-    return gl::StencilThenCoverFillPathInstancedCHROMIUMContextANGLE(
-        ctx, numPaths, pathNameType, paths, pathBase, fillMode, mask, coverMode, transformType,
-        transformValues);
-}
-
-void GL_APIENTRY
-glStencilThenCoverStrokePathInstancedCHROMIUMContextANGLE(GLeglContext ctx,
-                                                          GLsizei numPaths,
-                                                          GLenum pathNameType,
-                                                          const void *paths,
-                                                          GLuint pathBase,
-                                                          GLint reference,
-                                                          GLuint mask,
-                                                          GLenum coverMode,
-                                                          GLenum transformType,
-                                                          const GLfloat *transformValues)
-{
-    return gl::StencilThenCoverStrokePathInstancedCHROMIUMContextANGLE(
-        ctx, numPaths, pathNameType, paths, pathBase, reference, mask, coverMode, transformType,
-        transformValues);
-}
-
-void GL_APIENTRY glBindFragmentInputLocationCHROMIUMContextANGLE(GLeglContext ctx,
-                                                                 GLuint programs,
-                                                                 GLint location,
-                                                                 const GLchar *name)
-{
-    return gl::BindFragmentInputLocationCHROMIUMContextANGLE(ctx, programs, location, name);
-}
-
-void GL_APIENTRY glProgramPathFragmentInputGenCHROMIUMContextANGLE(GLeglContext ctx,
-                                                                   GLuint program,
-                                                                   GLint location,
-                                                                   GLenum genMode,
-                                                                   GLint components,
-                                                                   const GLfloat *coeffs)
-{
-    return gl::ProgramPathFragmentInputGenCHROMIUMContextANGLE(ctx, program, location, genMode,
-                                                               components, coeffs);
-}
-
 void GL_APIENTRY glCopyTextureCHROMIUMContextANGLE(GLeglContext ctx,
                                                    GLuint sourceId,
                                                    GLint sourceLevel,
diff --git a/src/libGLESv2/libGLESv2_autogen.def b/src/libGLESv2/libGLESv2_autogen.def
index c91363c..a0697d7 100644
--- a/src/libGLESv2/libGLESv2_autogen.def
+++ b/src/libGLESv2/libGLESv2_autogen.def
@@ -598,37 +598,10 @@
 
     ; GL_CHROMIUM_framebuffer_mixed_samples
     glCoverageModulationCHROMIUM
-    glMatrixLoadIdentityCHROMIUM
-    glMatrixLoadfCHROMIUM
 
     ; GL_CHROMIUM_lose_context
     glLoseContextCHROMIUM
 
-    ; GL_CHROMIUM_path_rendering
-    glBindFragmentInputLocationCHROMIUM
-    glCoverFillPathCHROMIUM
-    glCoverFillPathInstancedCHROMIUM
-    glCoverStrokePathCHROMIUM
-    glCoverStrokePathInstancedCHROMIUM
-    glDeletePathsCHROMIUM
-    glGenPathsCHROMIUM
-    glGetPathParameterfvCHROMIUM
-    glGetPathParameterivCHROMIUM
-    glIsPathCHROMIUM
-    glPathCommandsCHROMIUM
-    glPathParameterfCHROMIUM
-    glPathParameteriCHROMIUM
-    glPathStencilFuncCHROMIUM
-    glProgramPathFragmentInputGenCHROMIUM
-    glStencilFillPathCHROMIUM
-    glStencilFillPathInstancedCHROMIUM
-    glStencilStrokePathCHROMIUM
-    glStencilStrokePathInstancedCHROMIUM
-    glStencilThenCoverFillPathCHROMIUM
-    glStencilThenCoverFillPathInstancedCHROMIUM
-    glStencilThenCoverStrokePathCHROMIUM
-    glStencilThenCoverStrokePathInstancedCHROMIUM
-
     ; GL_EXT_blend_func_extended
     glBindFragDataLocationEXT
     glBindFragDataLocationIndexedEXT
@@ -747,6 +720,8 @@
 
     ; GL_EXT_texture_format_BGRA8888
 
+    ; GL_EXT_texture_sRGB_R8
+
     ; GL_EXT_texture_storage
     glTexStorage1DEXT
     glTexStorage2DEXT
@@ -908,7 +883,6 @@
     glBindBufferRangeContextANGLE
     glBindFragDataLocationEXTContextANGLE
     glBindFragDataLocationIndexedEXTContextANGLE
-    glBindFragmentInputLocationCHROMIUMContextANGLE
     glBindFramebufferContextANGLE
     glBindFramebufferOESContextANGLE
     glBindImageTextureContextANGLE
@@ -991,10 +965,6 @@
     glCopyTexSubImage3DOESContextANGLE
     glCopyTexture3DANGLEContextANGLE
     glCopyTextureCHROMIUMContextANGLE
-    glCoverFillPathCHROMIUMContextANGLE
-    glCoverFillPathInstancedCHROMIUMContextANGLE
-    glCoverStrokePathCHROMIUMContextANGLE
-    glCoverStrokePathInstancedCHROMIUMContextANGLE
     glCoverageModulationCHROMIUMContextANGLE
     glCreateMemoryObjectsEXTContextANGLE
     glCreateProgramContextANGLE
@@ -1013,7 +983,6 @@
     glDeleteFramebuffersContextANGLE
     glDeleteFramebuffersOESContextANGLE
     glDeleteMemoryObjectsEXTContextANGLE
-    glDeletePathsCHROMIUMContextANGLE
     glDeleteProgramContextANGLE
     glDeleteProgramPipelinesContextANGLE
     glDeleteQueriesContextANGLE
@@ -1114,7 +1083,6 @@
     glGenFencesNVContextANGLE
     glGenFramebuffersContextANGLE
     glGenFramebuffersOESContextANGLE
-    glGenPathsCHROMIUMContextANGLE
     glGenProgramPipelinesContextANGLE
     glGenQueriesContextANGLE
     glGenQueriesEXTContextANGLE
@@ -1188,8 +1156,6 @@
     glGetObjectLabelKHRContextANGLE
     glGetObjectPtrLabelContextANGLE
     glGetObjectPtrLabelKHRContextANGLE
-    glGetPathParameterfvCHROMIUMContextANGLE
-    glGetPathParameterivCHROMIUMContextANGLE
     glGetPointervContextANGLE
     glGetPointervKHRContextANGLE
     glGetPointervRobustANGLERobustANGLEContextANGLE
@@ -1315,7 +1281,6 @@
     glIsFramebufferContextANGLE
     glIsFramebufferOESContextANGLE
     glIsMemoryObjectEXTContextANGLE
-    glIsPathCHROMIUMContextANGLE
     glIsProgramContextANGLE
     glIsProgramPipelineContextANGLE
     glIsQueryContextANGLE
@@ -1355,8 +1320,6 @@
     glMaterialxContextANGLE
     glMaterialxvContextANGLE
     glMatrixIndexPointerOESContextANGLE
-    glMatrixLoadIdentityCHROMIUMContextANGLE
-    glMatrixLoadfCHROMIUMContextANGLE
     glMatrixModeContextANGLE
     glMaxShaderCompilerThreadsKHRContextANGLE
     glMemoryBarrierContextANGLE
@@ -1384,10 +1347,6 @@
     glOrthofContextANGLE
     glOrthoxContextANGLE
     glPatchParameteriContextANGLE
-    glPathCommandsCHROMIUMContextANGLE
-    glPathParameterfCHROMIUMContextANGLE
-    glPathParameteriCHROMIUMContextANGLE
-    glPathStencilFuncCHROMIUMContextANGLE
     glPauseTransformFeedbackContextANGLE
     glPixelStoreiContextANGLE
     glPointParameterfContextANGLE
@@ -1407,7 +1366,6 @@
     glProgramBinaryContextANGLE
     glProgramBinaryOESContextANGLE
     glProgramParameteriContextANGLE
-    glProgramPathFragmentInputGenCHROMIUMContextANGLE
     glProgramUniform1fContextANGLE
     glProgramUniform1fvContextANGLE
     glProgramUniform1iContextANGLE
@@ -1489,20 +1447,12 @@
     glShaderBinaryContextANGLE
     glShaderSourceContextANGLE
     glSignalSemaphoreEXTContextANGLE
-    glStencilFillPathCHROMIUMContextANGLE
-    glStencilFillPathInstancedCHROMIUMContextANGLE
     glStencilFuncContextANGLE
     glStencilFuncSeparateContextANGLE
     glStencilMaskContextANGLE
     glStencilMaskSeparateContextANGLE
     glStencilOpContextANGLE
     glStencilOpSeparateContextANGLE
-    glStencilStrokePathCHROMIUMContextANGLE
-    glStencilStrokePathInstancedCHROMIUMContextANGLE
-    glStencilThenCoverFillPathCHROMIUMContextANGLE
-    glStencilThenCoverFillPathInstancedCHROMIUMContextANGLE
-    glStencilThenCoverStrokePathCHROMIUMContextANGLE
-    glStencilThenCoverStrokePathInstancedCHROMIUMContextANGLE
     glTestFenceNVContextANGLE
     glTexBufferContextANGLE
     glTexBufferRangeContextANGLE
@@ -1724,8 +1674,10 @@
     ; EGL_ANGLE_swap_with_frame_token
     EGL_SwapBuffersWithFrameTokenANGLE
 
+    ; EGL_ANGLE_sync_control_rate
+    EGL_GetMscRateANGLE
+
     ; EGL_CHROMIUM_sync_control
-    EGL_GetMscRateCHROMIUM
     EGL_GetSyncValuesCHROMIUM
 
     ; EGL_EXT_device_query
diff --git a/src/libGLESv2/libGLESv2_no_capture_autogen.def b/src/libGLESv2/libGLESv2_no_capture_autogen.def
index 0f9258e..db9521d 100644
--- a/src/libGLESv2/libGLESv2_no_capture_autogen.def
+++ b/src/libGLESv2/libGLESv2_no_capture_autogen.def
@@ -598,37 +598,10 @@
 
     ; GL_CHROMIUM_framebuffer_mixed_samples
     glCoverageModulationCHROMIUM
-    glMatrixLoadIdentityCHROMIUM
-    glMatrixLoadfCHROMIUM
 
     ; GL_CHROMIUM_lose_context
     glLoseContextCHROMIUM
 
-    ; GL_CHROMIUM_path_rendering
-    glBindFragmentInputLocationCHROMIUM
-    glCoverFillPathCHROMIUM
-    glCoverFillPathInstancedCHROMIUM
-    glCoverStrokePathCHROMIUM
-    glCoverStrokePathInstancedCHROMIUM
-    glDeletePathsCHROMIUM
-    glGenPathsCHROMIUM
-    glGetPathParameterfvCHROMIUM
-    glGetPathParameterivCHROMIUM
-    glIsPathCHROMIUM
-    glPathCommandsCHROMIUM
-    glPathParameterfCHROMIUM
-    glPathParameteriCHROMIUM
-    glPathStencilFuncCHROMIUM
-    glProgramPathFragmentInputGenCHROMIUM
-    glStencilFillPathCHROMIUM
-    glStencilFillPathInstancedCHROMIUM
-    glStencilStrokePathCHROMIUM
-    glStencilStrokePathInstancedCHROMIUM
-    glStencilThenCoverFillPathCHROMIUM
-    glStencilThenCoverFillPathInstancedCHROMIUM
-    glStencilThenCoverStrokePathCHROMIUM
-    glStencilThenCoverStrokePathInstancedCHROMIUM
-
     ; GL_EXT_blend_func_extended
     glBindFragDataLocationEXT
     glBindFragDataLocationIndexedEXT
@@ -747,6 +720,8 @@
 
     ; GL_EXT_texture_format_BGRA8888
 
+    ; GL_EXT_texture_sRGB_R8
+
     ; GL_EXT_texture_storage
     glTexStorage1DEXT
     glTexStorage2DEXT
@@ -908,7 +883,6 @@
     glBindBufferRangeContextANGLE
     glBindFragDataLocationEXTContextANGLE
     glBindFragDataLocationIndexedEXTContextANGLE
-    glBindFragmentInputLocationCHROMIUMContextANGLE
     glBindFramebufferContextANGLE
     glBindFramebufferOESContextANGLE
     glBindImageTextureContextANGLE
@@ -991,10 +965,6 @@
     glCopyTexSubImage3DOESContextANGLE
     glCopyTexture3DANGLEContextANGLE
     glCopyTextureCHROMIUMContextANGLE
-    glCoverFillPathCHROMIUMContextANGLE
-    glCoverFillPathInstancedCHROMIUMContextANGLE
-    glCoverStrokePathCHROMIUMContextANGLE
-    glCoverStrokePathInstancedCHROMIUMContextANGLE
     glCoverageModulationCHROMIUMContextANGLE
     glCreateMemoryObjectsEXTContextANGLE
     glCreateProgramContextANGLE
@@ -1013,7 +983,6 @@
     glDeleteFramebuffersContextANGLE
     glDeleteFramebuffersOESContextANGLE
     glDeleteMemoryObjectsEXTContextANGLE
-    glDeletePathsCHROMIUMContextANGLE
     glDeleteProgramContextANGLE
     glDeleteProgramPipelinesContextANGLE
     glDeleteQueriesContextANGLE
@@ -1114,7 +1083,6 @@
     glGenFencesNVContextANGLE
     glGenFramebuffersContextANGLE
     glGenFramebuffersOESContextANGLE
-    glGenPathsCHROMIUMContextANGLE
     glGenProgramPipelinesContextANGLE
     glGenQueriesContextANGLE
     glGenQueriesEXTContextANGLE
@@ -1188,8 +1156,6 @@
     glGetObjectLabelKHRContextANGLE
     glGetObjectPtrLabelContextANGLE
     glGetObjectPtrLabelKHRContextANGLE
-    glGetPathParameterfvCHROMIUMContextANGLE
-    glGetPathParameterivCHROMIUMContextANGLE
     glGetPointervContextANGLE
     glGetPointervKHRContextANGLE
     glGetPointervRobustANGLERobustANGLEContextANGLE
@@ -1315,7 +1281,6 @@
     glIsFramebufferContextANGLE
     glIsFramebufferOESContextANGLE
     glIsMemoryObjectEXTContextANGLE
-    glIsPathCHROMIUMContextANGLE
     glIsProgramContextANGLE
     glIsProgramPipelineContextANGLE
     glIsQueryContextANGLE
@@ -1355,8 +1320,6 @@
     glMaterialxContextANGLE
     glMaterialxvContextANGLE
     glMatrixIndexPointerOESContextANGLE
-    glMatrixLoadIdentityCHROMIUMContextANGLE
-    glMatrixLoadfCHROMIUMContextANGLE
     glMatrixModeContextANGLE
     glMaxShaderCompilerThreadsKHRContextANGLE
     glMemoryBarrierContextANGLE
@@ -1384,10 +1347,6 @@
     glOrthofContextANGLE
     glOrthoxContextANGLE
     glPatchParameteriContextANGLE
-    glPathCommandsCHROMIUMContextANGLE
-    glPathParameterfCHROMIUMContextANGLE
-    glPathParameteriCHROMIUMContextANGLE
-    glPathStencilFuncCHROMIUMContextANGLE
     glPauseTransformFeedbackContextANGLE
     glPixelStoreiContextANGLE
     glPointParameterfContextANGLE
@@ -1407,7 +1366,6 @@
     glProgramBinaryContextANGLE
     glProgramBinaryOESContextANGLE
     glProgramParameteriContextANGLE
-    glProgramPathFragmentInputGenCHROMIUMContextANGLE
     glProgramUniform1fContextANGLE
     glProgramUniform1fvContextANGLE
     glProgramUniform1iContextANGLE
@@ -1489,20 +1447,12 @@
     glShaderBinaryContextANGLE
     glShaderSourceContextANGLE
     glSignalSemaphoreEXTContextANGLE
-    glStencilFillPathCHROMIUMContextANGLE
-    glStencilFillPathInstancedCHROMIUMContextANGLE
     glStencilFuncContextANGLE
     glStencilFuncSeparateContextANGLE
     glStencilMaskContextANGLE
     glStencilMaskSeparateContextANGLE
     glStencilOpContextANGLE
     glStencilOpSeparateContextANGLE
-    glStencilStrokePathCHROMIUMContextANGLE
-    glStencilStrokePathInstancedCHROMIUMContextANGLE
-    glStencilThenCoverFillPathCHROMIUMContextANGLE
-    glStencilThenCoverFillPathInstancedCHROMIUMContextANGLE
-    glStencilThenCoverStrokePathCHROMIUMContextANGLE
-    glStencilThenCoverStrokePathInstancedCHROMIUMContextANGLE
     glTestFenceNVContextANGLE
     glTexBufferContextANGLE
     glTexBufferRangeContextANGLE
@@ -1724,8 +1674,10 @@
     ; EGL_ANGLE_swap_with_frame_token
     EGL_SwapBuffersWithFrameTokenANGLE
 
+    ; EGL_ANGLE_sync_control_rate
+    EGL_GetMscRateANGLE
+
     ; EGL_CHROMIUM_sync_control
-    EGL_GetMscRateCHROMIUM
     EGL_GetSyncValuesCHROMIUM
 
     ; EGL_EXT_device_query
diff --git a/src/libGLESv2/libGLESv2_with_capture_autogen.def b/src/libGLESv2/libGLESv2_with_capture_autogen.def
index 460ea0d..b601aa8 100644
--- a/src/libGLESv2/libGLESv2_with_capture_autogen.def
+++ b/src/libGLESv2/libGLESv2_with_capture_autogen.def
@@ -598,37 +598,10 @@
 
     ; GL_CHROMIUM_framebuffer_mixed_samples
     glCoverageModulationCHROMIUM
-    glMatrixLoadIdentityCHROMIUM
-    glMatrixLoadfCHROMIUM
 
     ; GL_CHROMIUM_lose_context
     glLoseContextCHROMIUM
 
-    ; GL_CHROMIUM_path_rendering
-    glBindFragmentInputLocationCHROMIUM
-    glCoverFillPathCHROMIUM
-    glCoverFillPathInstancedCHROMIUM
-    glCoverStrokePathCHROMIUM
-    glCoverStrokePathInstancedCHROMIUM
-    glDeletePathsCHROMIUM
-    glGenPathsCHROMIUM
-    glGetPathParameterfvCHROMIUM
-    glGetPathParameterivCHROMIUM
-    glIsPathCHROMIUM
-    glPathCommandsCHROMIUM
-    glPathParameterfCHROMIUM
-    glPathParameteriCHROMIUM
-    glPathStencilFuncCHROMIUM
-    glProgramPathFragmentInputGenCHROMIUM
-    glStencilFillPathCHROMIUM
-    glStencilFillPathInstancedCHROMIUM
-    glStencilStrokePathCHROMIUM
-    glStencilStrokePathInstancedCHROMIUM
-    glStencilThenCoverFillPathCHROMIUM
-    glStencilThenCoverFillPathInstancedCHROMIUM
-    glStencilThenCoverStrokePathCHROMIUM
-    glStencilThenCoverStrokePathInstancedCHROMIUM
-
     ; GL_EXT_blend_func_extended
     glBindFragDataLocationEXT
     glBindFragDataLocationIndexedEXT
@@ -747,6 +720,8 @@
 
     ; GL_EXT_texture_format_BGRA8888
 
+    ; GL_EXT_texture_sRGB_R8
+
     ; GL_EXT_texture_storage
     glTexStorage1DEXT
     glTexStorage2DEXT
@@ -908,7 +883,6 @@
     glBindBufferRangeContextANGLE
     glBindFragDataLocationEXTContextANGLE
     glBindFragDataLocationIndexedEXTContextANGLE
-    glBindFragmentInputLocationCHROMIUMContextANGLE
     glBindFramebufferContextANGLE
     glBindFramebufferOESContextANGLE
     glBindImageTextureContextANGLE
@@ -991,10 +965,6 @@
     glCopyTexSubImage3DOESContextANGLE
     glCopyTexture3DANGLEContextANGLE
     glCopyTextureCHROMIUMContextANGLE
-    glCoverFillPathCHROMIUMContextANGLE
-    glCoverFillPathInstancedCHROMIUMContextANGLE
-    glCoverStrokePathCHROMIUMContextANGLE
-    glCoverStrokePathInstancedCHROMIUMContextANGLE
     glCoverageModulationCHROMIUMContextANGLE
     glCreateMemoryObjectsEXTContextANGLE
     glCreateProgramContextANGLE
@@ -1013,7 +983,6 @@
     glDeleteFramebuffersContextANGLE
     glDeleteFramebuffersOESContextANGLE
     glDeleteMemoryObjectsEXTContextANGLE
-    glDeletePathsCHROMIUMContextANGLE
     glDeleteProgramContextANGLE
     glDeleteProgramPipelinesContextANGLE
     glDeleteQueriesContextANGLE
@@ -1114,7 +1083,6 @@
     glGenFencesNVContextANGLE
     glGenFramebuffersContextANGLE
     glGenFramebuffersOESContextANGLE
-    glGenPathsCHROMIUMContextANGLE
     glGenProgramPipelinesContextANGLE
     glGenQueriesContextANGLE
     glGenQueriesEXTContextANGLE
@@ -1188,8 +1156,6 @@
     glGetObjectLabelKHRContextANGLE
     glGetObjectPtrLabelContextANGLE
     glGetObjectPtrLabelKHRContextANGLE
-    glGetPathParameterfvCHROMIUMContextANGLE
-    glGetPathParameterivCHROMIUMContextANGLE
     glGetPointervContextANGLE
     glGetPointervKHRContextANGLE
     glGetPointervRobustANGLERobustANGLEContextANGLE
@@ -1315,7 +1281,6 @@
     glIsFramebufferContextANGLE
     glIsFramebufferOESContextANGLE
     glIsMemoryObjectEXTContextANGLE
-    glIsPathCHROMIUMContextANGLE
     glIsProgramContextANGLE
     glIsProgramPipelineContextANGLE
     glIsQueryContextANGLE
@@ -1355,8 +1320,6 @@
     glMaterialxContextANGLE
     glMaterialxvContextANGLE
     glMatrixIndexPointerOESContextANGLE
-    glMatrixLoadIdentityCHROMIUMContextANGLE
-    glMatrixLoadfCHROMIUMContextANGLE
     glMatrixModeContextANGLE
     glMaxShaderCompilerThreadsKHRContextANGLE
     glMemoryBarrierContextANGLE
@@ -1384,10 +1347,6 @@
     glOrthofContextANGLE
     glOrthoxContextANGLE
     glPatchParameteriContextANGLE
-    glPathCommandsCHROMIUMContextANGLE
-    glPathParameterfCHROMIUMContextANGLE
-    glPathParameteriCHROMIUMContextANGLE
-    glPathStencilFuncCHROMIUMContextANGLE
     glPauseTransformFeedbackContextANGLE
     glPixelStoreiContextANGLE
     glPointParameterfContextANGLE
@@ -1407,7 +1366,6 @@
     glProgramBinaryContextANGLE
     glProgramBinaryOESContextANGLE
     glProgramParameteriContextANGLE
-    glProgramPathFragmentInputGenCHROMIUMContextANGLE
     glProgramUniform1fContextANGLE
     glProgramUniform1fvContextANGLE
     glProgramUniform1iContextANGLE
@@ -1489,20 +1447,12 @@
     glShaderBinaryContextANGLE
     glShaderSourceContextANGLE
     glSignalSemaphoreEXTContextANGLE
-    glStencilFillPathCHROMIUMContextANGLE
-    glStencilFillPathInstancedCHROMIUMContextANGLE
     glStencilFuncContextANGLE
     glStencilFuncSeparateContextANGLE
     glStencilMaskContextANGLE
     glStencilMaskSeparateContextANGLE
     glStencilOpContextANGLE
     glStencilOpSeparateContextANGLE
-    glStencilStrokePathCHROMIUMContextANGLE
-    glStencilStrokePathInstancedCHROMIUMContextANGLE
-    glStencilThenCoverFillPathCHROMIUMContextANGLE
-    glStencilThenCoverFillPathInstancedCHROMIUMContextANGLE
-    glStencilThenCoverStrokePathCHROMIUMContextANGLE
-    glStencilThenCoverStrokePathInstancedCHROMIUMContextANGLE
     glTestFenceNVContextANGLE
     glTexBufferContextANGLE
     glTexBufferRangeContextANGLE
@@ -1724,8 +1674,10 @@
     ; EGL_ANGLE_swap_with_frame_token
     EGL_SwapBuffersWithFrameTokenANGLE
 
+    ; EGL_ANGLE_sync_control_rate
+    EGL_GetMscRateANGLE
+
     ; EGL_CHROMIUM_sync_control
-    EGL_GetMscRateCHROMIUM
     EGL_GetSyncValuesCHROMIUM
 
     ; EGL_EXT_device_query
diff --git a/src/libGLESv2/proc_table_egl_autogen.cpp b/src/libGLESv2/proc_table_egl_autogen.cpp
index dcf19eb..5c10462 100644
--- a/src/libGLESv2/proc_table_egl_autogen.cpp
+++ b/src/libGLESv2/proc_table_egl_autogen.cpp
@@ -71,7 +71,7 @@
     {"eglGetError", P(EGL_GetError)},
     {"eglGetFrameTimestampSupportedANDROID", P(EGL_GetFrameTimestampSupportedANDROID)},
     {"eglGetFrameTimestampsANDROID", P(EGL_GetFrameTimestampsANDROID)},
-    {"eglGetMscRateCHROMIUM", P(EGL_GetMscRateCHROMIUM)},
+    {"eglGetMscRateANGLE", P(EGL_GetMscRateANGLE)},
     {"eglGetNativeClientBufferANDROID", P(EGL_GetNativeClientBufferANDROID)},
     {"eglGetNextFrameIdANDROID", P(EGL_GetNextFrameIdANDROID)},
     {"eglGetPlatformDisplay", P(EGL_GetPlatformDisplay)},
@@ -153,9 +153,6 @@
     {"glBindFragDataLocationIndexedEXT", P(gl::BindFragDataLocationIndexedEXT)},
     {"glBindFragDataLocationIndexedEXTContextANGLE",
      P(gl::BindFragDataLocationIndexedEXTContextANGLE)},
-    {"glBindFragmentInputLocationCHROMIUM", P(gl::BindFragmentInputLocationCHROMIUM)},
-    {"glBindFragmentInputLocationCHROMIUMContextANGLE",
-     P(gl::BindFragmentInputLocationCHROMIUMContextANGLE)},
     {"glBindFramebuffer", P(gl::BindFramebuffer)},
     {"glBindFramebufferContextANGLE", P(gl::BindFramebufferContextANGLE)},
     {"glBindFramebufferOES", P(gl::BindFramebufferOES)},
@@ -311,16 +308,6 @@
     {"glCopyTexture3DANGLEContextANGLE", P(gl::CopyTexture3DANGLEContextANGLE)},
     {"glCopyTextureCHROMIUM", P(gl::CopyTextureCHROMIUM)},
     {"glCopyTextureCHROMIUMContextANGLE", P(gl::CopyTextureCHROMIUMContextANGLE)},
-    {"glCoverFillPathCHROMIUM", P(gl::CoverFillPathCHROMIUM)},
-    {"glCoverFillPathCHROMIUMContextANGLE", P(gl::CoverFillPathCHROMIUMContextANGLE)},
-    {"glCoverFillPathInstancedCHROMIUM", P(gl::CoverFillPathInstancedCHROMIUM)},
-    {"glCoverFillPathInstancedCHROMIUMContextANGLE",
-     P(gl::CoverFillPathInstancedCHROMIUMContextANGLE)},
-    {"glCoverStrokePathCHROMIUM", P(gl::CoverStrokePathCHROMIUM)},
-    {"glCoverStrokePathCHROMIUMContextANGLE", P(gl::CoverStrokePathCHROMIUMContextANGLE)},
-    {"glCoverStrokePathInstancedCHROMIUM", P(gl::CoverStrokePathInstancedCHROMIUM)},
-    {"glCoverStrokePathInstancedCHROMIUMContextANGLE",
-     P(gl::CoverStrokePathInstancedCHROMIUMContextANGLE)},
     {"glCoverageModulationCHROMIUM", P(gl::CoverageModulationCHROMIUM)},
     {"glCoverageModulationCHROMIUMContextANGLE", P(gl::CoverageModulationCHROMIUMContextANGLE)},
     {"glCreateMemoryObjectsEXT", P(gl::CreateMemoryObjectsEXT)},
@@ -351,8 +338,6 @@
     {"glDeleteFramebuffersOESContextANGLE", P(gl::DeleteFramebuffersOESContextANGLE)},
     {"glDeleteMemoryObjectsEXT", P(gl::DeleteMemoryObjectsEXT)},
     {"glDeleteMemoryObjectsEXTContextANGLE", P(gl::DeleteMemoryObjectsEXTContextANGLE)},
-    {"glDeletePathsCHROMIUM", P(gl::DeletePathsCHROMIUM)},
-    {"glDeletePathsCHROMIUMContextANGLE", P(gl::DeletePathsCHROMIUMContextANGLE)},
     {"glDeleteProgram", P(gl::DeleteProgram)},
     {"glDeleteProgramContextANGLE", P(gl::DeleteProgramContextANGLE)},
     {"glDeleteProgramPipelines", P(gl::DeleteProgramPipelines)},
@@ -551,8 +536,6 @@
     {"glGenFramebuffersContextANGLE", P(gl::GenFramebuffersContextANGLE)},
     {"glGenFramebuffersOES", P(gl::GenFramebuffersOES)},
     {"glGenFramebuffersOESContextANGLE", P(gl::GenFramebuffersOESContextANGLE)},
-    {"glGenPathsCHROMIUM", P(gl::GenPathsCHROMIUM)},
-    {"glGenPathsCHROMIUMContextANGLE", P(gl::GenPathsCHROMIUMContextANGLE)},
     {"glGenProgramPipelines", P(gl::GenProgramPipelines)},
     {"glGenProgramPipelinesContextANGLE", P(gl::GenProgramPipelinesContextANGLE)},
     {"glGenQueries", P(gl::GenQueries)},
@@ -701,10 +684,6 @@
     {"glGetObjectLabelKHRContextANGLE", P(gl::GetObjectLabelKHRContextANGLE)},
     {"glGetObjectPtrLabelKHR", P(gl::GetObjectPtrLabelKHR)},
     {"glGetObjectPtrLabelKHRContextANGLE", P(gl::GetObjectPtrLabelKHRContextANGLE)},
-    {"glGetPathParameterfvCHROMIUM", P(gl::GetPathParameterfvCHROMIUM)},
-    {"glGetPathParameterfvCHROMIUMContextANGLE", P(gl::GetPathParameterfvCHROMIUMContextANGLE)},
-    {"glGetPathParameterivCHROMIUM", P(gl::GetPathParameterivCHROMIUM)},
-    {"glGetPathParameterivCHROMIUMContextANGLE", P(gl::GetPathParameterivCHROMIUMContextANGLE)},
     {"glGetPointerv", P(gl::GetPointerv)},
     {"glGetPointervContextANGLE", P(gl::GetPointervContextANGLE)},
     {"glGetPointervKHR", P(gl::GetPointervKHR)},
@@ -961,8 +940,6 @@
     {"glIsFramebufferOESContextANGLE", P(gl::IsFramebufferOESContextANGLE)},
     {"glIsMemoryObjectEXT", P(gl::IsMemoryObjectEXT)},
     {"glIsMemoryObjectEXTContextANGLE", P(gl::IsMemoryObjectEXTContextANGLE)},
-    {"glIsPathCHROMIUM", P(gl::IsPathCHROMIUM)},
-    {"glIsPathCHROMIUMContextANGLE", P(gl::IsPathCHROMIUMContextANGLE)},
     {"glIsProgram", P(gl::IsProgram)},
     {"glIsProgramContextANGLE", P(gl::IsProgramContextANGLE)},
     {"glIsProgramPipeline", P(gl::IsProgramPipeline)},
@@ -1042,10 +1019,6 @@
     {"glMaterialxvContextANGLE", P(gl::MaterialxvContextANGLE)},
     {"glMatrixIndexPointerOES", P(gl::MatrixIndexPointerOES)},
     {"glMatrixIndexPointerOESContextANGLE", P(gl::MatrixIndexPointerOESContextANGLE)},
-    {"glMatrixLoadIdentityCHROMIUM", P(gl::MatrixLoadIdentityCHROMIUM)},
-    {"glMatrixLoadIdentityCHROMIUMContextANGLE", P(gl::MatrixLoadIdentityCHROMIUMContextANGLE)},
-    {"glMatrixLoadfCHROMIUM", P(gl::MatrixLoadfCHROMIUM)},
-    {"glMatrixLoadfCHROMIUMContextANGLE", P(gl::MatrixLoadfCHROMIUMContextANGLE)},
     {"glMatrixMode", P(gl::MatrixMode)},
     {"glMatrixModeContextANGLE", P(gl::MatrixModeContextANGLE)},
     {"glMaxShaderCompilerThreadsKHR", P(gl::MaxShaderCompilerThreadsKHR)},
@@ -1099,14 +1072,6 @@
     {"glOrthofContextANGLE", P(gl::OrthofContextANGLE)},
     {"glOrthox", P(gl::Orthox)},
     {"glOrthoxContextANGLE", P(gl::OrthoxContextANGLE)},
-    {"glPathCommandsCHROMIUM", P(gl::PathCommandsCHROMIUM)},
-    {"glPathCommandsCHROMIUMContextANGLE", P(gl::PathCommandsCHROMIUMContextANGLE)},
-    {"glPathParameterfCHROMIUM", P(gl::PathParameterfCHROMIUM)},
-    {"glPathParameterfCHROMIUMContextANGLE", P(gl::PathParameterfCHROMIUMContextANGLE)},
-    {"glPathParameteriCHROMIUM", P(gl::PathParameteriCHROMIUM)},
-    {"glPathParameteriCHROMIUMContextANGLE", P(gl::PathParameteriCHROMIUMContextANGLE)},
-    {"glPathStencilFuncCHROMIUM", P(gl::PathStencilFuncCHROMIUM)},
-    {"glPathStencilFuncCHROMIUMContextANGLE", P(gl::PathStencilFuncCHROMIUMContextANGLE)},
     {"glPauseTransformFeedback", P(gl::PauseTransformFeedback)},
     {"glPauseTransformFeedbackContextANGLE", P(gl::PauseTransformFeedbackContextANGLE)},
     {"glPixelStorei", P(gl::PixelStorei)},
@@ -1141,9 +1106,6 @@
     {"glProgramBinaryOESContextANGLE", P(gl::ProgramBinaryOESContextANGLE)},
     {"glProgramParameteri", P(gl::ProgramParameteri)},
     {"glProgramParameteriContextANGLE", P(gl::ProgramParameteriContextANGLE)},
-    {"glProgramPathFragmentInputGenCHROMIUM", P(gl::ProgramPathFragmentInputGenCHROMIUM)},
-    {"glProgramPathFragmentInputGenCHROMIUMContextANGLE",
-     P(gl::ProgramPathFragmentInputGenCHROMIUMContextANGLE)},
     {"glProgramUniform1f", P(gl::ProgramUniform1f)},
     {"glProgramUniform1fContextANGLE", P(gl::ProgramUniform1fContextANGLE)},
     {"glProgramUniform1fv", P(gl::ProgramUniform1fv)},
@@ -1305,11 +1267,6 @@
     {"glShaderSourceContextANGLE", P(gl::ShaderSourceContextANGLE)},
     {"glSignalSemaphoreEXT", P(gl::SignalSemaphoreEXT)},
     {"glSignalSemaphoreEXTContextANGLE", P(gl::SignalSemaphoreEXTContextANGLE)},
-    {"glStencilFillPathCHROMIUM", P(gl::StencilFillPathCHROMIUM)},
-    {"glStencilFillPathCHROMIUMContextANGLE", P(gl::StencilFillPathCHROMIUMContextANGLE)},
-    {"glStencilFillPathInstancedCHROMIUM", P(gl::StencilFillPathInstancedCHROMIUM)},
-    {"glStencilFillPathInstancedCHROMIUMContextANGLE",
-     P(gl::StencilFillPathInstancedCHROMIUMContextANGLE)},
     {"glStencilFunc", P(gl::StencilFunc)},
     {"glStencilFuncContextANGLE", P(gl::StencilFuncContextANGLE)},
     {"glStencilFuncSeparate", P(gl::StencilFuncSeparate)},
@@ -1322,25 +1279,6 @@
     {"glStencilOpContextANGLE", P(gl::StencilOpContextANGLE)},
     {"glStencilOpSeparate", P(gl::StencilOpSeparate)},
     {"glStencilOpSeparateContextANGLE", P(gl::StencilOpSeparateContextANGLE)},
-    {"glStencilStrokePathCHROMIUM", P(gl::StencilStrokePathCHROMIUM)},
-    {"glStencilStrokePathCHROMIUMContextANGLE", P(gl::StencilStrokePathCHROMIUMContextANGLE)},
-    {"glStencilStrokePathInstancedCHROMIUM", P(gl::StencilStrokePathInstancedCHROMIUM)},
-    {"glStencilStrokePathInstancedCHROMIUMContextANGLE",
-     P(gl::StencilStrokePathInstancedCHROMIUMContextANGLE)},
-    {"glStencilThenCoverFillPathCHROMIUM", P(gl::StencilThenCoverFillPathCHROMIUM)},
-    {"glStencilThenCoverFillPathCHROMIUMContextANGLE",
-     P(gl::StencilThenCoverFillPathCHROMIUMContextANGLE)},
-    {"glStencilThenCoverFillPathInstancedCHROMIUM",
-     P(gl::StencilThenCoverFillPathInstancedCHROMIUM)},
-    {"glStencilThenCoverFillPathInstancedCHROMIUMContextANGLE",
-     P(gl::StencilThenCoverFillPathInstancedCHROMIUMContextANGLE)},
-    {"glStencilThenCoverStrokePathCHROMIUM", P(gl::StencilThenCoverStrokePathCHROMIUM)},
-    {"glStencilThenCoverStrokePathCHROMIUMContextANGLE",
-     P(gl::StencilThenCoverStrokePathCHROMIUMContextANGLE)},
-    {"glStencilThenCoverStrokePathInstancedCHROMIUM",
-     P(gl::StencilThenCoverStrokePathInstancedCHROMIUM)},
-    {"glStencilThenCoverStrokePathInstancedCHROMIUMContextANGLE",
-     P(gl::StencilThenCoverStrokePathInstancedCHROMIUMContextANGLE)},
     {"glTestFenceNV", P(gl::TestFenceNV)},
     {"glTestFenceNVContextANGLE", P(gl::TestFenceNVContextANGLE)},
     {"glTexCoordPointer", P(gl::TexCoordPointer)},
@@ -1580,5 +1518,5 @@
     {"glWeightPointerOES", P(gl::WeightPointerOES)},
     {"glWeightPointerOESContextANGLE", P(gl::WeightPointerOESContextANGLE)}};
 
-size_t g_numProcs = 1474;
+size_t g_numProcs = 1424;
 }  // namespace egl
diff --git a/src/tests/BUILD.gn b/src/tests/BUILD.gn
index 59772b7..db44781 100644
--- a/src/tests/BUILD.gn
+++ b/src/tests/BUILD.gn
@@ -397,6 +397,29 @@
   }
 
   # This source set is a bit special so we don't use angle_source_set.
+  angle_gles1_conform_common_source = [
+    "$gles1_conform_root/ctk/ctk.h",
+    "$gles1_conform_root/ctk/ctkn.c",
+    "$gles1_conform_root/ctk/glext.c",
+    "$gles1_conform_root/fixed/fixed.c",
+    "$gles1_conform_root/fixed/float64.c",
+    "$gles1_conform_root/fixed/int32.c",
+    "$gles1_conform_root/fixed/int64.c",
+    "$gles1_conform_root/platform/gl_fixed_point.h",
+    "$gles1_conform_root/platform/gl_single_precision.h",
+    "$gles1_conform_root/platform/math_fixed.h",
+    "$gles1_conform_root/platform/math_float.h",
+    "$gles1_conform_root/platform/platform.h",
+    "$gles1_conform_root/platform/platform_gl.h",
+    "$gles1_conform_root/platform/platform_random.h",
+    "$gles1_conform_root/platform/platform_stdlib.h",
+    "$gles1_conform_root/platform/platform_types.h",
+    "$gles1_conform_root/platform/printf_fixed.h",
+    "$gles1_conform_root/platform/printf_float.h",
+    "$gles1_conform_root/platform/random.c",
+    "$gles1_conform_root/platform/stdlib_ansi.h",
+  ]
+
   source_set("angle_gles1_conformance_no_gtest") {
     configs += [
       ":angle_gles1_conform_support",
@@ -524,27 +547,9 @@
       "$gles1_conform_root/conform/conformshell/utils.h",
       "$gles1_conform_root/conform/conformshell/utilt.c",
       "$gles1_conform_root/conform/conformshell/utilt.h",
-      "$gles1_conform_root/ctk/ctk.h",
-      "$gles1_conform_root/ctk/ctkn.c",
-      "$gles1_conform_root/ctk/glext.c",
-      "$gles1_conform_root/fixed/fixed.c",
-      "$gles1_conform_root/fixed/float64.c",
-      "$gles1_conform_root/fixed/int32.c",
-      "$gles1_conform_root/fixed/int64.c",
-      "$gles1_conform_root/platform/gl_fixed_point.h",
-      "$gles1_conform_root/platform/gl_single_precision.h",
-      "$gles1_conform_root/platform/math_fixed.h",
-      "$gles1_conform_root/platform/math_float.h",
-      "$gles1_conform_root/platform/platform.h",
-      "$gles1_conform_root/platform/platform_gl.h",
-      "$gles1_conform_root/platform/platform_random.h",
-      "$gles1_conform_root/platform/platform_stdlib.h",
-      "$gles1_conform_root/platform/platform_types.h",
-      "$gles1_conform_root/platform/printf_fixed.h",
-      "$gles1_conform_root/platform/printf_float.h",
-      "$gles1_conform_root/platform/random.c",
-      "$gles1_conform_root/platform/stdlib_ansi.h",
     ]
+
+    sources += angle_gles1_conform_common_source
   }
 
   angle_test("angle_gles1_conformance_tests") {
@@ -567,6 +572,159 @@
       "${angle_root}:angle_backend_config",
     ]
   }
+
+  if (!is_win && !is_mac) {
+    source_set("angle_gles1_covgl_no_gtest") {
+      configs += [
+        ":angle_gles1_conform_support",
+        "$angle_root:internal_config",
+      ]
+
+      public_configs = [
+        "$angle_root/util:angle_util_config",
+        "$angle_root:angle_static",
+        "$angle_root:gl_prototypes",
+      ]
+
+      testonly = true
+
+      public_deps = [
+        "$angle_root:angle_common",
+        "$angle_root:libEGL_static",
+        "$angle_root:libGLESv1_CM_static",
+        "$angle_root:libGLESv2_static",
+        "$angle_root:preprocessor",
+        "$angle_root:translator",
+        "$angle_root/util:angle_util_static",
+      ]
+
+      sources = [
+        "$gles1_conform_root/conform/covgl/a.c",
+        "$gles1_conform_root/conform/covgl/b.c",
+        "$gles1_conform_root/conform/covgl/c.c",
+        "$gles1_conform_root/conform/covgl/d.c",
+        "$gles1_conform_root/conform/covgl/data.c",
+        "$gles1_conform_root/conform/covgl/e.c",
+        "$gles1_conform_root/conform/covgl/enum.c",
+        "$gles1_conform_root/conform/covgl/f.c",
+        "$gles1_conform_root/conform/covgl/g.c",
+        "$gles1_conform_root/conform/covgl/h.c",
+        "$gles1_conform_root/conform/covgl/i.c",
+        "$gles1_conform_root/conform/covgl/l.c",
+        "$gles1_conform_root/conform/covgl/m.c",
+        "$gles1_conform_root/conform/covgl/n.c",
+        "$gles1_conform_root/conform/covgl/o.c",
+        "$gles1_conform_root/conform/covgl/p.c",
+        "$gles1_conform_root/conform/covgl/q.c",
+        "$gles1_conform_root/conform/covgl/r.c",
+        "$gles1_conform_root/conform/covgl/s.c",
+        "$gles1_conform_root/conform/covgl/shell.h",
+        "$gles1_conform_root/conform/covgl/t.c",
+        "$gles1_conform_root/conform/covgl/v.c",
+        "$gles1_conform_root/conform/covgl/w.c",
+      ]
+
+      sources += angle_gles1_conform_common_source
+
+      defines = [ "ProbeEnum=ProbeEnumANGLE" ]
+    }
+
+    angle_test("angle_gles1_covgl_tests") {
+      deps = [
+        ":angle_common_test_utils_static",
+        ":angle_gles1_covgl_no_gtest",
+      ]
+
+      include_dirs = [ "." ]
+
+      sources = [
+        "$gles1_conform_root/conform/covgl/shell.c",
+        "gles1_conformance_tests/CovglTests.cpp",
+        "test_utils/ANGLETest.cpp",
+        "test_utils/ANGLETest.h",
+      ]
+      main = "angle_end2end_tests_main"
+
+      configs += [
+        ":angle_gles1_conform_support",
+        "${angle_root}:libANGLE_config",
+        "${angle_root}:angle_backend_config",
+      ]
+    }
+  }
+  source_set("angle_gles1_primtest_no_gtest") {
+    configs += [
+      ":angle_gles1_conform_support",
+      "$angle_root:internal_config",
+    ]
+
+    public_configs = [
+      "$angle_root/util:angle_util_config",
+      "$angle_root:angle_static",
+      "$angle_root:gl_prototypes",
+    ]
+
+    testonly = true
+
+    public_deps = [
+      "$angle_root:angle_common",
+      "$angle_root:libEGL_static",
+      "$angle_root:libGLESv1_CM_static",
+      "$angle_root:libGLESv2_static",
+      "$angle_root:preprocessor",
+      "$angle_root:translator",
+      "$angle_root/util:angle_util_static",
+    ]
+
+    sources = [
+      "$gles1_conform_root/conform/primtest/alias.c",
+      "$gles1_conform_root/conform/primtest/alpha.c",
+      "$gles1_conform_root/conform/primtest/blend.c",
+      "$gles1_conform_root/conform/primtest/depth.c",
+      "$gles1_conform_root/conform/primtest/dither.c",
+      "$gles1_conform_root/conform/primtest/driver.c",
+      "$gles1_conform_root/conform/primtest/driver.h",
+      "$gles1_conform_root/conform/primtest/fog.c",
+      "$gles1_conform_root/conform/primtest/hint.c",
+      "$gles1_conform_root/conform/primtest/light.c",
+      "$gles1_conform_root/conform/primtest/logic.c",
+      "$gles1_conform_root/conform/primtest/prim.c",
+      "$gles1_conform_root/conform/primtest/scissor.c",
+      "$gles1_conform_root/conform/primtest/shade.c",
+      "$gles1_conform_root/conform/primtest/shell.c",
+      "$gles1_conform_root/conform/primtest/shell.h",
+      "$gles1_conform_root/conform/primtest/stencil.c",
+      "$gles1_conform_root/conform/primtest/texture.c",
+      "$gles1_conform_root/conform/primtest/tproto.h",
+    ]
+
+    sources += angle_gles1_conform_common_source
+  }
+
+  angle_test("angle_gles1_primtest_tests") {
+    deps = [
+      ":angle_common_test_utils_static",
+      ":angle_gles1_primtest_no_gtest",
+    ]
+
+    include_dirs = [
+      ".",
+      "$gles1_conform_root/conform",
+    ]
+
+    sources = [
+      "gles1_conformance_tests/PrimtestTests.cpp",
+      "test_utils/ANGLETest.cpp",
+      "test_utils/ANGLETest.h",
+    ]
+    main = "angle_end2end_tests_main"
+
+    configs += [
+      ":angle_gles1_conform_support",
+      "${angle_root}:libANGLE_config",
+      "${angle_root}:angle_backend_config",
+    ]
+  }
 }
 
 ###-----------------------------------------------------
@@ -1077,6 +1235,12 @@
     }
   }
   if (build_angle_gles1_conform_tests) {
-    deps += [ ":angle_gles1_conformance_tests" ]
+    deps += [
+      ":angle_gles1_conformance_tests",
+      ":angle_gles1_primtest_tests",
+    ]
+    if (!is_win && !is_mac) {
+      deps += [ ":angle_gles1_covgl_tests" ]
+    }
   }
 }
diff --git a/src/tests/OWNERS b/src/tests/OWNERS
new file mode 100644
index 0000000..299725a
--- /dev/null
+++ b/src/tests/OWNERS
@@ -0,0 +1,2 @@
+# All committers are de-facto owners of the tests.
+per-file *=*
diff --git a/src/tests/angle_end2end_tests.gni b/src/tests/angle_end2end_tests.gni
index aca4e78..1f22930 100644
--- a/src/tests/angle_end2end_tests.gni
+++ b/src/tests/angle_end2end_tests.gni
@@ -27,6 +27,7 @@
   "gl_tests/BindGeneratesResourceTest.cpp",
   "gl_tests/BindUniformLocationTest.cpp",
   "gl_tests/BlendFuncExtendedTest.cpp",
+  "gl_tests/BlendIntegerTest.cpp",
   "gl_tests/BlendMinMaxTest.cpp",
   "gl_tests/BlitFramebufferANGLETest.cpp",
   "gl_tests/BufferDataTest.cpp",
@@ -51,6 +52,7 @@
   "gl_tests/DifferentStencilMasksTest.cpp",
   "gl_tests/DiscardFramebufferEXTTest.cpp",
   "gl_tests/DrawBaseVertexBaseInstanceTest.cpp",
+  "gl_tests/DrawBaseVertexVariantsTest.cpp",
   "gl_tests/DrawBuffersTest.cpp",
   "gl_tests/DrawElementsTest.cpp",
   "gl_tests/ETCTextureTest.cpp",
@@ -88,7 +90,6 @@
   "gl_tests/PBOExtensionTest.cpp",
   "gl_tests/PackUnpackTest.cpp",
   "gl_tests/ParallelShaderCompileTest.cpp",
-  "gl_tests/PathRenderingTest.cpp",
   "gl_tests/PbufferTest.cpp",
   "gl_tests/PointSpritesTest.cpp",
   "gl_tests/ProgramBinaryTest.cpp",
@@ -107,6 +108,8 @@
   "gl_tests/SRGBTextureTest.cpp",
   "gl_tests/SamplersTest.cpp",
   "gl_tests/SemaphoreTest.cpp",
+  "gl_tests/ShaderInterpTest.cpp",
+  "gl_tests/ShaderNonConstGlobalInitializerTest.cpp",
   "gl_tests/ShaderStorageBufferTest.cpp",
   "gl_tests/SimpleOperationTest.cpp",
   "gl_tests/SixteenBppTextureTest.cpp",
diff --git a/src/tests/angle_unittests.gni b/src/tests/angle_unittests.gni
index 54b80cd..f04e942 100644
--- a/src/tests/angle_unittests.gni
+++ b/src/tests/angle_unittests.gni
@@ -27,7 +27,6 @@
   "../libANGLE/Config_unittest.cpp",
   "../libANGLE/Fence_unittest.cpp",
   "../libANGLE/HandleAllocator_unittest.cpp",
-  "../libANGLE/HandleRangeAllocator_unittest.cpp",
   "../libANGLE/ImageIndexIterator_unittest.cpp",
   "../libANGLE/Image_unittest.cpp",
   "../libANGLE/Observer_unittest.cpp",
diff --git a/src/tests/angle_unittests_utils.h b/src/tests/angle_unittests_utils.h
index 48fecc3..c2b4e25 100644
--- a/src/tests/angle_unittests_utils.h
+++ b/src/tests/angle_unittests_utils.h
@@ -72,11 +72,6 @@
         return nullptr;
     }
 
-    std::vector<PathImpl *> createPaths(GLsizei range) override
-    {
-        return std::vector<PathImpl *>();
-    }
-
     SemaphoreImpl *createSemaphore() override { return nullptr; }
 
     OverlayImpl *createOverlay(const gl::OverlayState &state) override { return nullptr; }
@@ -103,7 +98,6 @@
     MOCK_METHOD1(createTransformFeedback,
                  TransformFeedbackImpl *(const gl::TransformFeedbackState &));
     MOCK_METHOD1(createSampler, SamplerImpl *(const gl::SamplerState &));
-    MOCK_METHOD1(createPaths, std::vector<PathImpl *>(GLsizei));
     MOCK_METHOD0(createSemaphore, SemaphoreImpl *());
     MOCK_METHOD1(createOverlay, OverlayImpl *(const gl::OverlayState &));
 };
diff --git a/src/tests/deqp_support/angle_deqp_gtest.cpp b/src/tests/deqp_support/angle_deqp_gtest.cpp
index b03a276..ad4d2ef 100644
--- a/src/tests/deqp_support/angle_deqp_gtest.cpp
+++ b/src/tests/deqp_support/angle_deqp_gtest.cpp
@@ -514,6 +514,12 @@
     std::string configArgString  = std::string(gdEQPEGLConfigNameString) + targetConfigName;
     argv.push_back(configArgString.c_str());
 
+    // Hide SwiftShader window to prevent a race with Xvfb causing hangs on test bots
+    if (gInitAPI && gInitAPI->second == GPUTestConfig::kAPISwiftShader)
+    {
+        argv.push_back("--deqp-visibility=hidden");
+    }
+
     // Init the platform.
     if (!deqp_libtester_init_platform(static_cast<int>(argv.size()), argv.data(),
                                       reinterpret_cast<void *>(&HandlePlatformError)))
diff --git a/src/tests/deqp_support/deqp_egl_test_expectations.txt b/src/tests/deqp_support/deqp_egl_test_expectations.txt
index 56f534d..c72aeb8 100644
--- a/src/tests/deqp_support/deqp_egl_test_expectations.txt
+++ b/src/tests/deqp_support/deqp_egl_test_expectations.txt
@@ -250,3 +250,6 @@
 2546 NEXUS5X : dEQP-EGL.functional.query_context.get_current_display.* = SKIP
 2546 NEXUS5X : dEQP-EGL.functional.query_context.get_current_surface.r* = FAIL
 2546 NEXUS5X : dEQP-EGL.functional.query_context.query_context.* = SKIP
+
+// SwANGLE bots
+4495 WIN SWIFTSHADER : dEQP-EGL.functional.sharing.gles2.multithread.random_egl_server_sync.shaders.compile.9 = SKIP
\ No newline at end of file
diff --git a/src/tests/deqp_support/deqp_gles31_test_expectations.txt b/src/tests/deqp_support/deqp_gles31_test_expectations.txt
index 01b0b96..f165f87 100644
--- a/src/tests/deqp_support/deqp_gles31_test_expectations.txt
+++ b/src/tests/deqp_support/deqp_gles31_test_expectations.txt
@@ -114,13 +114,13 @@
 // Failing with dEQP roll
 3447 D3D11 : dEQP-GLES31.functional.ssbo.layout.random.all_per_block_buffers.22 = FAIL
 3447 D3D11 : dEQP-GLES31.functional.ssbo.layout.random.all_per_block_buffers.41 = FAIL
-4234 D3D11 : dEQP-GLES31.functional.debug.negative_coverage.get_error.compute.program_not_active = FAIL
-4234 OPENGL : dEQP-GLES31.functional.debug.negative_coverage.get_error.compute.program_not_active = FAIL
-4234 D3D11 : dEQP-GLES31.functional.debug.negative_coverage.log.compute.program_not_active = FAIL
-4234 OPENGL : dEQP-GLES31.functional.debug.negative_coverage.log.compute.program_not_active = FAIL
+4234 D3D11 : dEQP-GLES31.functional.debug.negative_coverage.get_error.compute.program_not_active = SKIP
+4234 OPENGL : dEQP-GLES31.functional.debug.negative_coverage.get_error.compute.program_not_active = SKIP
+4234 D3D11 : dEQP-GLES31.functional.debug.negative_coverage.log.compute.program_not_active = SKIP
+4234 OPENGL : dEQP-GLES31.functional.debug.negative_coverage.log.compute.program_not_active = SKIP
 4234 D3D11 : dEQP-GLES31.functional.debug.negative_coverage.get_error.buffer.renderbuffer_storage_multisample = FAIL
-4234 D3D11 : dEQP-GLES31.functional.debug.negative_coverage.callbacks.compute.program_not_active = FAIL
-4234 OPENGL : dEQP-GLES31.functional.debug.negative_coverage.callbacks.compute.program_not_active = FAIL
+4234 D3D11 : dEQP-GLES31.functional.debug.negative_coverage.callbacks.compute.program_not_active = SKIP
+4234 OPENGL : dEQP-GLES31.functional.debug.negative_coverage.callbacks.compute.program_not_active = SKIP
 
 // OPENGL Failing Tests
 1665 WIN NVIDIA OPENGL : dEQP-GLES31.functional.draw_indirect.negative.command_offset_not_in_buffer_unsigned32_wrap = FAIL
@@ -140,6 +140,12 @@
 // OpenGL/D3D11 Failing Tests
 1442 OPENGL : dEQP-GLES31.functional.shaders.opaque_type_indexing.* = FAIL
 1442 D3D11 : dEQP-GLES31.functional.shaders.opaque_type_indexing.* = FAIL
+1442 OPENGL : dEQP-GLES31.functional.separate_shader.* = SKIP
+1442 D3D11 : dEQP-GLES31.functional.separate_shader.* = SKIP
+1442 OPENGL : dEQP-GLES31.functional.state_query.program.program_separable_get_programiv = FAIL
+1442 D3D11 : dEQP-GLES31.functional.state_query.program.program_separable_get_programiv = FAIL
+1442 OPENGL : dEQP-GLES31.functional.state_query.program_pipeline.* = SKIP
+1442 D3D11 : dEQP-GLES31.functional.state_query.program_pipeline.* = SKIP
 
 // These tests are failing because of compile errors with SSBOs in compute shaders.
 
@@ -171,18 +177,13 @@
 //// Failures blocking an official GLES 3.1 conformance run on SwiftShader
 ////
 
-// Waiting for Program pipeline functionality
-3570 : dEQP-GLES31.functional.state_query.integer.program_pipeline_binding_* = FAIL
-3570 : dEQP-GLES31.functional.state_query.program.program_separable_get_programiv = FAIL
-3570 : dEQP-GLES31.functional.state_query.program_pipeline.* = SKIP
-3570 : dEQP-GLES31.functional.debug.object_labels.program_pipeline = FAIL
-3570 : dEQP-GLES31.functional.separate_shader.* = FAIL
-
 // Debug (test bug):
 3590 SWIFTSHADER : dEQP-GLES31.functional.debug.negative_coverage.get_error.buffer.framebuffer_texture2d = FAIL
 
-// Front-end query bugs:
-3596 VULKAN : dEQP-GLES31.functional.program_interface_query.shader_storage_block.buffer_data_size.* = FAIL
+// GLSL length() method returning number of bytes in an array instead of number of items
+4098 SWIFTSHADER : dEQP-GLES31.functional.compute.basic.write_multiple_unsized_arr_multiple_groups = FAIL
+4098 SWIFTSHADER : dEQP-GLES31.functional.compute.basic.write_multiple_unsized_arr_single_invocation = FAIL
+
 
 // Not failing in last official run, but failed recently:
 4110 SWIFTSHADER : dEQP-GLES31.functional.shaders.helper_invocation.* = FAIL
@@ -191,19 +192,9 @@
 3881 VULKAN : dEQP-GLES31.functional.program_interface_query.uniform.location.default_block.array.array.image_2d = SKIP
 3881 VULKAN : dEQP-GLES31.functional.program_interface_query.uniform.location.default_block.array.array.iimage_2d_array = SKIP
 
-// Crashes in Windows x86 Subzero Reactor
-4482 WIN SWIFTSHADER : dEQP-GLES31.functional.compute.basic.shared_atomic_op_* = SKIP
-4482 WIN SWIFTSHADER : dEQP-GLES31.functional.compute.basic.shared_var_* = SKIP
-4482 WIN SWIFTSHADER : dEQP-GLES31.functional.compute.basic.ssbo_local_barrier_* = SKIP
-4482 WIN SWIFTSHADER : dEQP-GLES31.functional.compute.shared_var.* = SKIP
-4482 WIN SWIFTSHADER : dEQP-GLES31.functional.image_load_store.2d.qualifiers.* = SKIP
-4482 WIN SWIFTSHADER : dEQP-GLES31.functional.image_load_store.2d_array.qualifiers.* = SKIP
-4482 WIN SWIFTSHADER : dEQP-GLES31.functional.image_load_store.3d.qualifiers.* = SKIP
-4482 WIN SWIFTSHADER : dEQP-GLES31.functional.image_load_store.cube.qualifiers.* = SKIP
-4482 WIN SWIFTSHADER : dEQP-GLES31.functional.ssbo.atomic.compswap.* = SKIP
+// Flaky crashes in Windows x86 Subzero Reactor
 4482 WIN SWIFTSHADER : dEQP-GLES31.functional.synchronization.inter_invocation.* = SKIP
 
-
 ////
 //// General Vulkan expectations
 ////
@@ -280,4 +271,4 @@
 4371 VULKAN ANDROID : dEQP-GLES31.functional.shaders.implicit_conversions.es31.arithmetic.input_before_literal.add.int_to_vec3_vertex = FAIL
 4371 VULKAN ANDROID : dEQP-GLES31.functional.shaders.implicit_conversions.es31.arithmetic.input_before_literal.add.int_to_uvec3_vertex = FAIL
 4371 SWIFTSHADER : dEQP-GLES31.functional.shaders.implicit_conversions.* = FAIL
-
+3609 VULKAN : dEQP-GLES31.functional.srgb_texture_decode.skip_decode.sr8.* = FAIL
diff --git a/src/tests/deqp_support/deqp_gles3_test_expectations.txt b/src/tests/deqp_support/deqp_gles3_test_expectations.txt
index 23b7dd4..3ad9f46 100644
--- a/src/tests/deqp_support/deqp_gles3_test_expectations.txt
+++ b/src/tests/deqp_support/deqp_gles3_test_expectations.txt
@@ -595,57 +595,5 @@
 4016 SWIFTSHADER : dEQP-GLES3.functional.fragment_ops.interaction.basic_shader.27 = FAIL
 4016 SWIFTSHADER : dEQP-GLES3.functional.fragment_ops.interaction.basic_shader.80 = FAIL
 
-// These only fail on Android
-4045 SWIFTSHADER : dEQP-GLES3.functional.uniform_api.value.assigned.by_pointer.render.nested_structs_arrays.sampler2D_samplerCube_both = FAIL
-4045 SWIFTSHADER : dEQP-GLES3.functional.uniform_api.value.assigned.by_pointer.render.nested_structs_arrays.sampler2D_samplerCube_fragment = FAIL
-4045 SWIFTSHADER : dEQP-GLES3.functional.uniform_api.value.assigned.by_pointer.render.nested_structs_arrays.sampler2D_samplerCube_vertex = FAIL
-4045 SWIFTSHADER : dEQP-GLES3.functional.uniform_api.value.assigned.by_pointer.render.struct_in_array.sampler2D_samplerCube_both = FAIL
-4045 SWIFTSHADER : dEQP-GLES3.functional.uniform_api.value.assigned.by_pointer.render.struct_in_array.sampler2D_samplerCube_fragment = FAIL
-4045 SWIFTSHADER : dEQP-GLES3.functional.uniform_api.value.assigned.by_pointer.render.struct_in_array.sampler2D_samplerCube_vertex = FAIL
-4045 SWIFTSHADER : dEQP-GLES3.functional.uniform_api.value.assigned.by_value.render.nested_structs_arrays.sampler2D_samplerCube_both = FAIL
-4045 SWIFTSHADER : dEQP-GLES3.functional.uniform_api.value.assigned.by_value.render.nested_structs_arrays.sampler2D_samplerCube_fragment = FAIL
-4045 SWIFTSHADER : dEQP-GLES3.functional.uniform_api.value.assigned.by_value.render.nested_structs_arrays.sampler2D_samplerCube_vertex = FAIL
-4045 SWIFTSHADER : dEQP-GLES3.functional.uniform_api.value.assigned.by_value.render.struct_in_array.sampler2D_samplerCube_both = FAIL
-4045 SWIFTSHADER : dEQP-GLES3.functional.uniform_api.value.assigned.by_value.render.struct_in_array.sampler2D_samplerCube_fragment = FAIL
-
 // Fails on SwANGLE bots
-4416 SWIFTSHADER : dEQP-GLES3.functional.fbo.blit.conversion.r11f_g11f_b10f_to_r16f = FAIL
-4416 SWIFTSHADER : dEQP-GLES3.functional.fbo.blit.conversion.r11f_g11f_b10f_to_rg16f = FAIL
-4416 SWIFTSHADER : dEQP-GLES3.functional.fbo.blit.conversion.r11f_g11f_b10f_to_rgba16f = FAIL
-4416 SWIFTSHADER : dEQP-GLES3.functional.fbo.blit.conversion.r16f_to_r11f_g11f_b10f = FAIL
-4416 SWIFTSHADER : dEQP-GLES3.functional.fbo.blit.conversion.rg16f_to_r11f_g11f_b10f = FAIL
-4416 SWIFTSHADER : dEQP-GLES3.functional.fbo.blit.conversion.rgba16f_to_r11f_g11f_b10f = FAIL
-
 4418 SWIFTSHADER : dEQP-GLES3.functional.negative_api.buffer.framebuffer_texture_layer = FAIL
-
-4447 SWIFTSHADER : dEQP-GLES3.functional.texture.compressed.astc.void_extent_hdr.* = FAIL
-4447 SWIFTSHADER : dEQP-GLES3.functional.texture.compressed.astc.color_endpoint_modes.4x4 = FAIL
-4447 SWIFTSHADER : dEQP-GLES3.functional.texture.compressed.astc.color_endpoint_modes.5x4 = FAIL
-4447 SWIFTSHADER : dEQP-GLES3.functional.texture.compressed.astc.color_endpoint_modes.5x5 = FAIL
-4447 SWIFTSHADER : dEQP-GLES3.functional.texture.compressed.astc.color_endpoint_modes.6x5 = FAIL
-4447 SWIFTSHADER : dEQP-GLES3.functional.texture.compressed.astc.color_endpoint_modes.6x6 = FAIL
-4447 SWIFTSHADER : dEQP-GLES3.functional.texture.compressed.astc.color_endpoint_modes.8x5 = FAIL
-4447 SWIFTSHADER : dEQP-GLES3.functional.texture.compressed.astc.color_endpoint_modes.8x6 = FAIL
-4447 SWIFTSHADER : dEQP-GLES3.functional.texture.compressed.astc.color_endpoint_modes.8x8 = FAIL
-4447 SWIFTSHADER : dEQP-GLES3.functional.texture.compressed.astc.color_endpoint_modes.10x5 = FAIL
-4447 SWIFTSHADER : dEQP-GLES3.functional.texture.compressed.astc.color_endpoint_modes.10x6 = FAIL
-4447 SWIFTSHADER : dEQP-GLES3.functional.texture.compressed.astc.color_endpoint_modes.10x8 = FAIL
-4447 SWIFTSHADER : dEQP-GLES3.functional.texture.compressed.astc.color_endpoint_modes.10x10 = FAIL
-4447 SWIFTSHADER : dEQP-GLES3.functional.texture.compressed.astc.color_endpoint_modes.12x10 = FAIL
-4447 SWIFTSHADER : dEQP-GLES3.functional.texture.compressed.astc.color_endpoint_modes.12x12 = FAIL
-4447 SWIFTSHADER : dEQP-GLES3.functional.texture.compressed.astc.endpoint_value_hdr_cem_* = FAIL
-4447 SWIFTSHADER : dEQP-GLES3.functional.texture.compressed.astc.random.4x4 = FAIL
-4447 SWIFTSHADER : dEQP-GLES3.functional.texture.compressed.astc.random.5x4 = FAIL
-4447 SWIFTSHADER : dEQP-GLES3.functional.texture.compressed.astc.random.5x5 = FAIL
-4447 SWIFTSHADER : dEQP-GLES3.functional.texture.compressed.astc.random.6x5 = FAIL
-4447 SWIFTSHADER : dEQP-GLES3.functional.texture.compressed.astc.random.6x6 = FAIL
-4447 SWIFTSHADER : dEQP-GLES3.functional.texture.compressed.astc.random.8x5 = FAIL
-4447 SWIFTSHADER : dEQP-GLES3.functional.texture.compressed.astc.random.8x6 = FAIL
-4447 SWIFTSHADER : dEQP-GLES3.functional.texture.compressed.astc.random.8x8 = FAIL
-4447 SWIFTSHADER : dEQP-GLES3.functional.texture.compressed.astc.random.10x5 = FAIL
-4447 SWIFTSHADER : dEQP-GLES3.functional.texture.compressed.astc.random.10x6 = FAIL
-4447 SWIFTSHADER : dEQP-GLES3.functional.texture.compressed.astc.random.10x8 = FAIL
-4447 SWIFTSHADER : dEQP-GLES3.functional.texture.compressed.astc.random.10x10 = FAIL
-4447 SWIFTSHADER : dEQP-GLES3.functional.texture.compressed.astc.random.12x10 = FAIL
-4447 SWIFTSHADER : dEQP-GLES3.functional.texture.compressed.astc.random.12x12 = FAIL
-
diff --git a/src/tests/deqp_support/deqp_khr_gles31_test_expectations.txt b/src/tests/deqp_support/deqp_khr_gles31_test_expectations.txt
index 6a6d640..0e06112 100644
--- a/src/tests/deqp_support/deqp_khr_gles31_test_expectations.txt
+++ b/src/tests/deqp_support/deqp_khr_gles31_test_expectations.txt
@@ -36,25 +36,13 @@
 //// Failures blocking an official GLES 3.1 conformance run on SwiftShader
 ////
 
-// Dispatch indirect:
-3570 VULKAN : KHR-GLES31.core.compute_shader.build-separable = SKIP
+// Verify that compute and non-compute stages can be attached to one pipeline object:
 3570 VULKAN : KHR-GLES31.core.compute_shader.sso-compute-pipeline = SKIP
 3570 VULKAN : KHR-GLES31.core.compute_shader.sso-case2 = SKIP
 3570 VULKAN : KHR-GLES31.core.compute_shader.sso-case3 = SKIP
-// Program Pipeline Objects:
-3570 VULKAN : KHR-GLES31.core.shader_atomic_counters.advanced-usage-many-draw-calls2 = FAIL
-3570 VULKAN : KHR-GLES31.core.shader_atomic_counters.advanced-usage-many-dispatches = FAIL
-3570 VULKAN : KHR-GLES31.core.vertex_attrib_binding.basic-usage = FAIL
-3570 VULKAN : KHR-GLES31.core.shader_image_load_store.advanced-sso-simple = FAIL
+3570 SWIFTSHADER : KHR-GLES31.core.shader_image_load_store.advanced-sso-simple = SKIP
 // Separate shader objects:
-3570 VULKAN : KHR-GLES31.core.sepshaderobjs* = FAIL
-
-// Shader support:
-4402 : KHR-GLES31.core.shader_bitfield_operation.frexp.* = SKIP
-4402 : KHR-GLES31.core.shader_bitfield_operation.uaddCarry.* = SKIP
-4402 : KHR-GLES31.core.shader_bitfield_operation.usubBorrow.* = SKIP
-4402 : KHR-GLES31.core.shader_bitfield_operation.umulExtended.* = SKIP
-4402 : KHR-GLES31.core.shader_bitfield_operation.imulExtended.* = SKIP
+3570 VULKAN : KHR-GLES31.core.sepshaderobjs.StateInteraction = SKIP
 
 // Program interface query.
 3596 VULKAN : KHR-GLES31.core.program_interface_query.* = FAIL
@@ -69,8 +57,8 @@
 4146 : KHR-GLES31.core.vertex_attrib_binding.advanced-largeStrideAndOffsetsNewAndLegacyAPI = FAIL
 
 // Failing on SwiftShader
-4414 SWIFTSHADER : KHR-GLES31.core.shader_image_load_store.advanced-allMips-cs = FAIL
-4414 SWIFTSHADER : KHR-GLES31.core.shader_image_load_store.advanced-allMips-fs = FAIL
+4414 SWIFTSHADER : KHR-GLES31.core.shader_image_load_store.advanced-allMips-cs = SKIP
+4414 SWIFTSHADER : KHR-GLES31.core.shader_image_load_store.advanced-allMips-fs = SKIP
 
 ////
 //// General Vulkan expectations
diff --git a/src/tests/egl_tests/EGLBlobCacheTest.cpp b/src/tests/egl_tests/EGLBlobCacheTest.cpp
index 8cf8499..3b23083 100644
--- a/src/tests/egl_tests/EGLBlobCacheTest.cpp
+++ b/src/tests/egl_tests/EGLBlobCacheTest.cpp
@@ -108,10 +108,7 @@
 
     void testTearDown() override { gApplicationCache.clear(); }
 
-    bool programBinaryAvailable()
-    {
-        return (getClientMajorVersion() >= 3 || IsGLExtensionEnabled("GL_OES_get_program_binary"));
-    }
+    bool programBinaryAvailable() { return IsGLExtensionEnabled("GL_OES_get_program_binary"); }
 
     bool mHasBlobCache;
 };
@@ -232,4 +229,57 @@
     EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
 }
 
-ANGLE_INSTANTIATE_TEST_ES2(EGLBlobCacheTest);
+// Regression test for including the fragment output locatins in the program key.
+// http://anglebug.com/4535
+TEST_P(EGLBlobCacheTest, FragmentOutputLocationKey)
+{
+    ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_blend_func_extended") ||
+                       getClientMajorVersion() < 3);
+
+    EGLDisplay display = getEGLWindow()->getDisplay();
+
+    EXPECT_TRUE(mHasBlobCache);
+    eglSetBlobCacheFuncsANDROID(display, SetBlob, GetBlob);
+    ASSERT_EGL_SUCCESS();
+
+    // Compile a shader so it puts something in the cache
+    if (programBinaryAvailable())
+    {
+        constexpr char kFragmentShaderSrc[] = R"(#version 300 es
+#extension GL_EXT_blend_func_extended : require
+precision mediump float;
+uniform vec4 src;
+uniform vec4 src1;
+out vec4 FragData;
+out vec4 SecondaryFragData;
+void main() {
+    FragData = src;
+    SecondaryFragData = src1;
+})";
+
+        constexpr char kVertexShaderSrc[] = R"(#version 300 es
+in vec4 position;
+void main() {
+    gl_Position = position;
+})";
+
+        GLuint program = CompileProgram(kVertexShaderSrc, kFragmentShaderSrc, [](GLuint p) {
+            glBindFragDataLocationEXT(p, 0, "FragData[0]");
+            glBindFragDataLocationIndexedEXT(p, 0, 1, "SecondaryFragData[0]");
+        });
+        ASSERT_NE(0u, program);
+        EXPECT_EQ(CacheOpResult::SetSuccess, gLastCacheOpResult);
+        gLastCacheOpResult = CacheOpResult::ValueNotSet;
+
+        // Re-link the program with different fragment output bindings
+        program = CompileProgram(kVertexShaderSrc, kFragmentShaderSrc, [](GLuint p) {
+            glBindFragDataLocationEXT(p, 0, "FragData");
+            glBindFragDataLocationIndexedEXT(p, 0, 1, "SecondaryFragData");
+        });
+        ASSERT_NE(0u, program);
+        EXPECT_EQ(CacheOpResult::SetSuccess, gLastCacheOpResult);
+        gLastCacheOpResult = CacheOpResult::ValueNotSet;
+    }
+}
+
+ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(EGLBlobCacheTest);
diff --git a/src/tests/egl_tests/EGLDirectCompositionTest.cpp b/src/tests/egl_tests/EGLDirectCompositionTest.cpp
index fc06302..ac58077 100644
--- a/src/tests/egl_tests/EGLDirectCompositionTest.cpp
+++ b/src/tests/egl_tests/EGLDirectCompositionTest.cpp
@@ -51,7 +51,7 @@
 
         mOSWindow->initialize("EGLDirectCompositionTest", WINDOWWIDTH, WINDOWHEIGHT);
         auto nativeWindow = mOSWindow->getNativeWindow();
-        mOSWindow->setVisible(true);
+        setWindowVisible(mOSWindow, true);
 
         // Create DispatcherQueue for window to process compositor callbacks
         CreateDispatcherQueue(mDispatcherController);
@@ -256,6 +256,9 @@
     // Only attempt this test when on Windows 10 1803+
     ANGLE_SKIP_TEST_IF(!mRoHelper.SupportedWindowsRelease());
 
+    // http://crbug.com/1063962
+    ANGLE_SKIP_TEST_IF(isD3D11Renderer() && IsIntel());
+
     EGLSurface s{nullptr};
     CreateSurface(mAngleHost, s);
 
diff --git a/src/tests/egl_tests/EGLRobustnessTest.cpp b/src/tests/egl_tests/EGLRobustnessTest.cpp
index b7d7d4c..c0ad2b4 100644
--- a/src/tests/egl_tests/EGLRobustnessTest.cpp
+++ b/src/tests/egl_tests/EGLRobustnessTest.cpp
@@ -23,7 +23,7 @@
     {
         mOSWindow = OSWindow::New();
         mOSWindow->initialize("EGLRobustnessTest", 500, 500);
-        mOSWindow->setVisible(true);
+        setWindowVisible(mOSWindow, true);
 
         const auto &platform = GetParam().eglParameters;
 
diff --git a/src/tests/egl_tests/EGLSurfaceTest.cpp b/src/tests/egl_tests/EGLSurfaceTest.cpp
index 675911a..d3dcd99 100644
--- a/src/tests/egl_tests/EGLSurfaceTest.cpp
+++ b/src/tests/egl_tests/EGLSurfaceTest.cpp
@@ -401,9 +401,11 @@
 {
     // http://anglebug.com/4453
     ANGLE_SKIP_TEST_IF(isVulkanRenderer() && IsLinux() && IsIntel());
+    // Flaky on Linux SwANGLE http://anglebug.com/4453
+    ANGLE_SKIP_TEST_IF(IsLinux() && isSwiftshader());
 
     // Necessary for a window resizing test if there is no per-frame window size query
-    mOSWindow->setVisible(true);
+    setWindowVisible(mOSWindow, true);
 
     GLenum platform               = GetParam().getRenderer();
     bool platformSupportsZeroSize = platform == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE ||
@@ -454,8 +456,11 @@
     // http://anglebug.com/4453
     ANGLE_SKIP_TEST_IF(isVulkanRenderer() && IsLinux() && IsIntel());
 
+    // Flaky on Linux SwANGLE http://anglebug.com/4453
+    ANGLE_SKIP_TEST_IF(IsLinux() && isSwiftshader());
+
     // Necessary for a window resizing test if there is no per-frame window size query
-    mOSWindow->setVisible(true);
+    setWindowVisible(mOSWindow, true);
 
     initializeDisplay();
     initializeSurfaceWithDefaultConfig();
@@ -538,7 +543,7 @@
 // Test that the window can be reset repeatedly before surface creation.
 TEST_P(EGLSurfaceTest, ResetNativeWindow)
 {
-    mOSWindow->setVisible(true);
+    setWindowVisible(mOSWindow, true);
 
     initializeDisplay();
 
diff --git a/src/tests/egl_tests/EGLX11VisualTest.cpp b/src/tests/egl_tests/EGLX11VisualTest.cpp
index 18b3ea8..b639024 100644
--- a/src/tests/egl_tests/EGLX11VisualTest.cpp
+++ b/src/tests/egl_tests/EGLX11VisualTest.cpp
@@ -92,7 +92,7 @@
     // can use OSWindow to create a window and just grab its visual.
     OSWindow *osWindow = OSWindow::New();
     osWindow->initialize("EGLX11VisualHintTest", 500, 500);
-    osWindow->setVisible(true);
+    setWindowVisible(osWindow, true);
 
     Window xWindow = osWindow->getNativeWindow();
 
@@ -162,7 +162,7 @@
     {
         OSWindow *osWindow = OSWindow::New();
         osWindow->initialize("EGLX11VisualHintTest", 500, 500);
-        osWindow->setVisible(true);
+        setWindowVisible(osWindow, true);
 
         Window xWindow = osWindow->getNativeWindow();
 
@@ -186,7 +186,7 @@
 
     OSWindow *osWindow = new X11Window(otherVisualId);
     osWindow->initialize("EGLX11VisualHintTest", 500, 500);
-    osWindow->setVisible(true);
+    setWindowVisible(osWindow, true);
 
     Window xWindow = osWindow->getNativeWindow();
 
diff --git a/src/tests/gl_tests/AttributeLayoutTest.cpp b/src/tests/gl_tests/AttributeLayoutTest.cpp
index 441a5f6..a6a0dc6 100644
--- a/src/tests/gl_tests/AttributeLayoutTest.cpp
+++ b/src/tests/gl_tests/AttributeLayoutTest.cpp
@@ -454,6 +454,9 @@
 
 TEST_P(AttributeLayoutNonIndexed, Test)
 {
+    // Flaky on Linux SwANGLE http://anglebug.com/4502
+    ANGLE_SKIP_TEST_IF(IsLinux() && isSwiftshader());
+
     Run(true);
     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
     Run(false);
@@ -461,6 +464,9 @@
 
 TEST_P(AttributeLayoutMemoryIndexed, Test)
 {
+    // Flaky on Linux SwANGLE http://anglebug.com/4502
+    ANGLE_SKIP_TEST_IF(IsLinux() && isSwiftshader());
+
     Run(true);
     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && (IsOpenGL() || IsD3D11_FL93()));
     Run(false);
@@ -468,6 +474,9 @@
 
 TEST_P(AttributeLayoutBufferIndexed, Test)
 {
+    // Flaky on Linux SwANGLE http://anglebug.com/4502
+    ANGLE_SKIP_TEST_IF(IsLinux() && isSwiftshader());
+
     Run(true);
     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && (IsOpenGL() || IsD3D11_FL93()));
     Run(false);
diff --git a/src/tests/gl_tests/BlendIntegerTest.cpp b/src/tests/gl_tests/BlendIntegerTest.cpp
new file mode 100644
index 0000000..c0a8d9a
--- /dev/null
+++ b/src/tests/gl_tests/BlendIntegerTest.cpp
@@ -0,0 +1,251 @@
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "test_utils/ANGLETest.h"
+#include "test_utils/gl_raii.h"
+
+using namespace angle;
+
+class BlendIntegerTest : public ANGLETest
+{
+  protected:
+    BlendIntegerTest()
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+    }
+
+    template <typename T, GLuint components>
+    void compareValue(const T *value, const char *name)
+    {
+        T pixel[4];
+        glReadBuffer(GL_COLOR_ATTACHMENT0);
+        glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER,
+                     std::is_same<T, int32_t>::value ? GL_INT : GL_UNSIGNED_INT, pixel);
+        for (size_t componentIdx = 0; componentIdx < components; componentIdx++)
+        {
+            EXPECT_EQ(value[componentIdx], pixel[componentIdx])
+                << " componentIdx=" << componentIdx << std::endl
+                << " " << name << "[0]=" << value[0] << " pixel[0]=" << pixel[0] << std::endl
+                << " " << name << "[1]=" << value[1] << " pixel[1]=" << pixel[1] << std::endl
+                << " " << name << "[2]=" << value[2] << " pixel[2]=" << pixel[2] << std::endl
+                << " " << name << "[3]=" << value[3] << " pixel[3]=" << pixel[3];
+        }
+    }
+
+    template <GLenum internalformat, GLuint components, bool isSigned>
+    void runTest()
+    {
+        // https://crbug.com/angleproject/4548
+        ANGLE_SKIP_TEST_IF(isVulkanRenderer() && IsIntel() && !isVulkanSwiftshaderRenderer());
+
+        constexpr char kFsui[] =
+            "#version 300 es\n"
+            "out highp uvec4 o_drawBuffer0;\n"
+            "void main(void)\n"
+            "{\n"
+            "    o_drawBuffer0 = uvec4(1, 1, 1, 1);\n"
+            "}\n";
+
+        constexpr char kFssi[] =
+            "#version 300 es\n"
+            "out highp ivec4 o_drawBuffer0;\n"
+            "void main(void)\n"
+            "{\n"
+            "    o_drawBuffer0 = ivec4(-1, -1, -1, -1);\n"
+            "}\n";
+
+        ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), isSigned ? kFssi : kFsui);
+        glUseProgram(program);
+
+        GLFramebuffer framebuffer;
+        glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
+
+        GLRenderbuffer colorRenderbuffer;
+        glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
+        glRenderbufferStorage(GL_RENDERBUFFER, internalformat, getWindowWidth(), getWindowHeight());
+        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
+                                  colorRenderbuffer);
+
+        if (isSigned)
+        {
+            const int32_t clearValueSigned[4] = {-128, -128, -128, -128};
+            glClearBufferiv(GL_COLOR, 0, clearValueSigned);
+            ASSERT_GL_NO_ERROR();
+            compareValue<int32_t, components>(clearValueSigned, "clearValueSigned");
+        }
+        else
+        {
+            const uint32_t clearValueUnsigned[4] = {127, 127, 127, 3};
+            glClearBufferuiv(GL_COLOR, 0, clearValueUnsigned);
+            ASSERT_GL_NO_ERROR();
+            compareValue<uint32_t, components>(clearValueUnsigned, "clearValueUnsigned");
+        }
+
+        glEnable(GL_BLEND);
+        glBlendEquation(GL_FUNC_ADD);
+        glBlendFunc(GL_ONE, GL_ONE);
+
+        drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
+
+        ASSERT_GL_NO_ERROR();
+
+        // Enabled blending must be ignored for integer color attachment.
+        if (isSigned)
+        {
+            const int32_t colorValueSigned[4] = {-1, -1, -1, -1};
+            compareValue<int32_t, components>(colorValueSigned, "colorValueSigned");
+        }
+        else
+        {
+            const uint32_t colorValueUnsigned[4] = {1, 1, 1, 1};
+            compareValue<uint32_t, components>(colorValueUnsigned, "colorValueUnsigned");
+        }
+    }
+};
+
+// Test that blending is not applied to signed integer attachments.
+TEST_P(BlendIntegerTest, R8I)
+{
+    // TODO(http://anglebug.com/4571)
+    ANGLE_SKIP_TEST_IF(isVulkanRenderer());
+    runTest<GL_R8I, 1, true>();
+}
+
+TEST_P(BlendIntegerTest, R16I)
+{
+    // TODO(http://anglebug.com/4571)
+    ANGLE_SKIP_TEST_IF(isVulkanRenderer());
+    runTest<GL_R16I, 1, true>();
+}
+
+TEST_P(BlendIntegerTest, R32I)
+{
+    // TODO(http://anglebug.com/4571)
+    ANGLE_SKIP_TEST_IF(isVulkanRenderer());
+    runTest<GL_R32I, 1, true>();
+}
+
+TEST_P(BlendIntegerTest, RG8I)
+{
+    // TODO(http://anglebug.com/4571)
+    ANGLE_SKIP_TEST_IF(isVulkanRenderer());
+    runTest<GL_RG8I, 2, true>();
+}
+
+TEST_P(BlendIntegerTest, RG16I)
+{
+    // TODO(http://anglebug.com/4571)
+    ANGLE_SKIP_TEST_IF(isVulkanRenderer());
+    runTest<GL_RG16I, 2, true>();
+}
+
+TEST_P(BlendIntegerTest, RG32I)
+{
+    // TODO(http://anglebug.com/4571)
+    ANGLE_SKIP_TEST_IF(isVulkanRenderer());
+    runTest<GL_RG32I, 2, true>();
+}
+
+TEST_P(BlendIntegerTest, RGBA8I)
+{
+    // TODO(http://anglebug.com/4571)
+    ANGLE_SKIP_TEST_IF(isVulkanRenderer());
+    runTest<GL_RGBA8I, 4, true>();
+}
+
+TEST_P(BlendIntegerTest, RGBA16I)
+{
+    // TODO(http://anglebug.com/4571)
+    ANGLE_SKIP_TEST_IF(isVulkanRenderer());
+    runTest<GL_RGBA16I, 4, true>();
+}
+
+TEST_P(BlendIntegerTest, RGBA32I)
+{
+    // TODO(http://anglebug.com/4571)
+    ANGLE_SKIP_TEST_IF(isVulkanRenderer());
+    runTest<GL_RGBA32I, 4, true>();
+}
+
+// Test that blending is not applied to unsigned integer attachments.
+TEST_P(BlendIntegerTest, R8UI)
+{
+    // TODO(http://anglebug.com/4571)
+    ANGLE_SKIP_TEST_IF(isVulkanRenderer());
+    runTest<GL_R8UI, 1, false>();
+}
+
+TEST_P(BlendIntegerTest, R16UI)
+{
+    // TODO(http://anglebug.com/4571)
+    ANGLE_SKIP_TEST_IF(isVulkanRenderer());
+    runTest<GL_R16UI, 1, false>();
+}
+
+TEST_P(BlendIntegerTest, R32UI)
+{
+    // TODO(http://anglebug.com/4571)
+    ANGLE_SKIP_TEST_IF(isVulkanRenderer());
+    runTest<GL_R32UI, 1, false>();
+}
+
+TEST_P(BlendIntegerTest, RG8UI)
+{
+    // TODO(http://anglebug.com/4571)
+    ANGLE_SKIP_TEST_IF(isVulkanRenderer());
+    runTest<GL_RG8UI, 2, false>();
+}
+
+TEST_P(BlendIntegerTest, RG16UI)
+{
+    // TODO(http://anglebug.com/4571)
+    ANGLE_SKIP_TEST_IF(isVulkanRenderer());
+    runTest<GL_RG16UI, 2, false>();
+}
+
+TEST_P(BlendIntegerTest, RG32UI)
+{
+    // TODO(http://anglebug.com/4571)
+    ANGLE_SKIP_TEST_IF(isVulkanRenderer());
+    runTest<GL_RG32UI, 2, false>();
+}
+
+TEST_P(BlendIntegerTest, RGBA8UI)
+{
+    // TODO(http://anglebug.com/4571)
+    ANGLE_SKIP_TEST_IF(isVulkanRenderer());
+    runTest<GL_RGBA8UI, 4, false>();
+}
+
+TEST_P(BlendIntegerTest, RGBA16UI)
+{
+    // TODO(http://anglebug.com/4571)
+    ANGLE_SKIP_TEST_IF(isVulkanRenderer());
+    runTest<GL_RGBA16UI, 4, false>();
+}
+
+TEST_P(BlendIntegerTest, RGBA32UI)
+{
+    // TODO(http://anglebug.com/4571)
+    ANGLE_SKIP_TEST_IF(isVulkanRenderer());
+    runTest<GL_RGBA32UI, 4, false>();
+}
+
+TEST_P(BlendIntegerTest, RGB10_A2UI)
+{
+    // TODO(http://anglebug.com/4571)
+    ANGLE_SKIP_TEST_IF(isVulkanRenderer());
+    runTest<GL_RGB10_A2UI, 4, false>();
+}
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these
+// tests should be run against.
+ANGLE_INSTANTIATE_TEST_ES3(BlendIntegerTest);
diff --git a/src/tests/gl_tests/BlitFramebufferANGLETest.cpp b/src/tests/gl_tests/BlitFramebufferANGLETest.cpp
index 4f0d60e..88e6292 100644
--- a/src/tests/gl_tests/BlitFramebufferANGLETest.cpp
+++ b/src/tests/gl_tests/BlitFramebufferANGLETest.cpp
@@ -409,10 +409,10 @@
 
     glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
 
-    EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 255, 0, 0, 255);
-    EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, getWindowHeight() / 4, 0, 255, 0, 255);
-    EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, 255, 0, 0, 255);
-    EXPECT_PIXEL_EQ(getWindowWidth() / 4, 3 * getWindowHeight() / 4, 0, 255, 0, 255);
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4, getWindowHeight() / 4, GLColor::red);
+    EXPECT_PIXEL_COLOR_EQ(3 * getWindowWidth() / 4, getWindowHeight() / 4, GLColor::green);
+    EXPECT_PIXEL_COLOR_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, GLColor::red);
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4, 3 * getWindowHeight() / 4, GLColor::green);
 }
 
 // Draw to system framebuffer, blit whole-buffer color to user-created framebuffer.
@@ -633,10 +633,10 @@
 
     glDisable(GL_DEPTH_TEST);
 
-    EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 255, 0, 0, 255);
-    EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, getWindowHeight() / 4, 255, 0, 0, 255);
-    EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, 0, 0, 255, 255);
-    EXPECT_PIXEL_EQ(getWindowWidth() / 4, 3 * getWindowHeight() / 4, 0, 0, 255, 255);
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4, getWindowHeight() / 4, GLColor::red);
+    EXPECT_PIXEL_COLOR_EQ(3 * getWindowWidth() / 4, getWindowHeight() / 4, GLColor::red);
+    EXPECT_PIXEL_COLOR_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, GLColor::blue);
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4, 3 * getWindowHeight() / 4, GLColor::blue);
 }
 
 // blit from system FBO to user-created framebuffer, with depth buffer.
@@ -754,10 +754,10 @@
 
     glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
 
-    EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 255, 255, 255, 255);
-    EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, getWindowHeight() / 4, 255, 255, 255, 255);
-    EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, 255, 255, 255, 255);
-    EXPECT_PIXEL_EQ(getWindowWidth() / 4, 3 * getWindowHeight() / 4, 255, 0, 0, 255);
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4, getWindowHeight() / 4, GLColor::white);
+    EXPECT_PIXEL_COLOR_EQ(3 * getWindowWidth() / 4, getWindowHeight() / 4, GLColor::white);
+    EXPECT_PIXEL_COLOR_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, GLColor::white);
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4, 3 * getWindowHeight() / 4, GLColor::red);
 }
 
 TEST_P(BlitFramebufferANGLETest, BlitDifferentSizes)
@@ -831,15 +831,14 @@
 {
     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_framebuffer_blit"));
 
-    // TODO(jmadill): Figure out if we can fix this on D3D9.
-    // https://code.google.com/p/angleproject/issues/detail?id=2205
+    // http://anglebug.com/2205
     ANGLE_SKIP_TEST_IF(IsIntel() && IsD3D9());
 
     glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
 
     glClearColor(0.0, 1.0, 0.0, 1.0);
-    glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     glClearStencil(0x0);
+    glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
     // Scissor half the screen so we fill the stencil only halfway
     glScissor(0, 0, getWindowWidth(), getWindowHeight() / 2);
diff --git a/src/tests/gl_tests/BufferDataTest.cpp b/src/tests/gl_tests/BufferDataTest.cpp
index 9a6782b..4b1269e 100644
--- a/src/tests/gl_tests/BufferDataTest.cpp
+++ b/src/tests/gl_tests/BufferDataTest.cpp
@@ -411,6 +411,166 @@
     EXPECT_GL_NO_ERROR();
 }
 
+// Test to verify mapping a buffer after copying to it contains flushed/updated data
+TEST_P(BufferDataTestES3, CopyBufferSubDataMapReadTest)
+{
+    const char simpleVertex[]   = R"(attribute vec2 position;
+attribute vec4 color;
+varying vec4 vColor;
+void main()
+{
+    gl_Position = vec4(position, 0, 1);
+    vColor = color;
+}
+)";
+    const char simpleFragment[] = R"(precision mediump float;
+varying vec4 vColor;
+void main()
+{
+    gl_FragColor = vColor;
+}
+)";
+
+    const uint32_t numComponents = 3;
+    const uint32_t width         = 4;
+    const uint32_t height        = 4;
+    const size_t numElements     = width * height * numComponents;
+    std::vector<uint8_t> srcData(numElements);
+    std::vector<uint8_t> dstData(numElements);
+
+    for (uint8_t i = 0; i < srcData.size(); i++)
+    {
+        srcData[i] = 128;
+    }
+    for (uint8_t i = 0; i < dstData.size(); i++)
+    {
+        dstData[i] = 0;
+    }
+
+    GLBuffer srcBuffer;
+    GLBuffer dstBuffer;
+
+    glBindBuffer(GL_ARRAY_BUFFER, srcBuffer);
+    glBufferData(GL_ARRAY_BUFFER, srcData.size(), srcData.data(), GL_STATIC_DRAW);
+    ASSERT_GL_NO_ERROR();
+
+    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, dstBuffer);
+    glBufferData(GL_PIXEL_UNPACK_BUFFER, dstData.size(), dstData.data(), GL_STATIC_READ);
+    ASSERT_GL_NO_ERROR();
+
+    ANGLE_GL_PROGRAM(program, simpleVertex, simpleFragment);
+    glUseProgram(program);
+
+    GLint colorLoc = glGetAttribLocation(program, "color");
+    ASSERT_NE(-1, colorLoc);
+
+    glBindBuffer(GL_ARRAY_BUFFER, srcBuffer);
+    glVertexAttribPointer(colorLoc, 3, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
+    glEnableVertexAttribArray(colorLoc);
+
+    drawQuad(program, "position", 0.5f, 1.0f, true);
+    ASSERT_GL_NO_ERROR();
+
+    glCopyBufferSubData(GL_ARRAY_BUFFER, GL_PIXEL_UNPACK_BUFFER, 0, 0, numElements);
+
+    // With GL_MAP_READ_BIT, we expect the data to be flushed and updated to match srcData
+    uint8_t *data = reinterpret_cast<uint8_t *>(
+        glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, numElements, GL_MAP_READ_BIT));
+    EXPECT_GL_NO_ERROR();
+    for (size_t i = 0; i < numElements; ++i)
+    {
+        EXPECT_EQ(srcData[i], data[i]);
+    }
+    glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test to verify mapping a buffer after copying to it contains expected data
+// with GL_MAP_UNSYNCHRONIZED_BIT
+TEST_P(BufferDataTestES3, MapBufferUnsynchronizedReadTest)
+{
+    const char simpleVertex[]   = R"(attribute vec2 position;
+attribute vec4 color;
+varying vec4 vColor;
+void main()
+{
+    gl_Position = vec4(position, 0, 1);
+    vColor = color;
+}
+)";
+    const char simpleFragment[] = R"(precision mediump float;
+varying vec4 vColor;
+void main()
+{
+    gl_FragColor = vColor;
+}
+)";
+
+    const uint32_t numComponents = 3;
+    const uint32_t width         = 4;
+    const uint32_t height        = 4;
+    const size_t numElements     = width * height * numComponents;
+    std::vector<uint8_t> srcData(numElements);
+    std::vector<uint8_t> dstData(numElements);
+
+    for (uint8_t i = 0; i < srcData.size(); i++)
+    {
+        srcData[i] = 128;
+    }
+    for (uint8_t i = 0; i < dstData.size(); i++)
+    {
+        dstData[i] = 0;
+    }
+
+    GLBuffer srcBuffer;
+    GLBuffer dstBuffer;
+
+    glBindBuffer(GL_ARRAY_BUFFER, srcBuffer);
+    glBufferData(GL_ARRAY_BUFFER, srcData.size(), srcData.data(), GL_STATIC_DRAW);
+    ASSERT_GL_NO_ERROR();
+
+    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, dstBuffer);
+    glBufferData(GL_PIXEL_UNPACK_BUFFER, dstData.size(), dstData.data(), GL_STATIC_READ);
+    ASSERT_GL_NO_ERROR();
+
+    ANGLE_GL_PROGRAM(program, simpleVertex, simpleFragment);
+    glUseProgram(program);
+
+    GLint colorLoc = glGetAttribLocation(program, "color");
+    ASSERT_NE(-1, colorLoc);
+
+    glBindBuffer(GL_ARRAY_BUFFER, srcBuffer);
+    glVertexAttribPointer(colorLoc, 3, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
+    glEnableVertexAttribArray(colorLoc);
+
+    drawQuad(program, "position", 0.5f, 1.0f, true);
+    ASSERT_GL_NO_ERROR();
+
+    glCopyBufferSubData(GL_ARRAY_BUFFER, GL_PIXEL_UNPACK_BUFFER, 0, 0, numElements);
+
+    // Synchronize.
+    glFinish();
+
+    // Map with GL_MAP_UNSYNCHRONIZED_BIT and overwrite buffers data with srcData
+    uint8_t *data = reinterpret_cast<uint8_t *>(glMapBufferRange(
+        GL_PIXEL_UNPACK_BUFFER, 0, numElements, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT));
+    EXPECT_GL_NO_ERROR();
+    memcpy(data, srcData.data(), srcData.size());
+    glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
+    EXPECT_GL_NO_ERROR();
+
+    // Map without GL_MAP_UNSYNCHRONIZED_BIT and read data. We expect it to be srcData
+    data = reinterpret_cast<uint8_t *>(
+        glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, numElements, GL_MAP_READ_BIT));
+    EXPECT_GL_NO_ERROR();
+    for (size_t i = 0; i < numElements; ++i)
+    {
+        EXPECT_EQ(srcData[i], data[i]);
+    }
+    glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
+    EXPECT_GL_NO_ERROR();
+}
+
 // Verify the functionality of glMapBufferRange()'s GL_MAP_UNSYNCHRONIZED_BIT
 // NOTE: On Vulkan, if we ever use memory that's not `VK_MEMORY_PROPERTY_HOST_COHERENT_BIT`, then
 // this could incorrectly pass.
diff --git a/src/tests/gl_tests/ClearTest.cpp b/src/tests/gl_tests/ClearTest.cpp
index a34c043..27cccec 100644
--- a/src/tests/gl_tests/ClearTest.cpp
+++ b/src/tests/gl_tests/ClearTest.cpp
@@ -215,7 +215,7 @@
         setConfigStencilBits(8);
     }
 
-    void MaskedScissoredColorDepthStencilClear(
+    void maskedScissoredColorDepthStencilClear(
         const MaskedScissoredClearVariationsTestParams &params);
 
     bool mHasDepth   = true;
@@ -1268,7 +1268,7 @@
     ASSERT_GL_NO_ERROR();
 }
 
-void MaskedScissoredClearTestBase::MaskedScissoredColorDepthStencilClear(
+void MaskedScissoredClearTestBase::maskedScissoredColorDepthStencilClear(
     const MaskedScissoredClearVariationsTestParams &params)
 {
     // Flaky on Android Nexus 5x and Pixel 2, possible Qualcomm driver bug.
@@ -1449,7 +1449,7 @@
 // Tests combinations of color, depth, stencil clears with or without masks or scissor.
 TEST_P(MaskedScissoredClearTest, Test)
 {
-    MaskedScissoredColorDepthStencilClear(GetParam());
+    maskedScissoredColorDepthStencilClear(GetParam());
 }
 
 // Tests combinations of color, depth, stencil clears with or without masks or scissor.
@@ -1483,7 +1483,7 @@
         bindColorStencilFBO();
     }
 
-    MaskedScissoredColorDepthStencilClear(GetParam());
+    maskedScissoredColorDepthStencilClear(GetParam());
 }
 
 // Test that just clearing a nonexistent drawbuffer of the default framebuffer doesn't cause an
diff --git a/src/tests/gl_tests/ComputeShaderTest.cpp b/src/tests/gl_tests/ComputeShaderTest.cpp
index 9c4efa9..4cc568b 100644
--- a/src/tests/gl_tests/ComputeShaderTest.cpp
+++ b/src/tests/gl_tests/ComputeShaderTest.cpp
@@ -1721,11 +1721,6 @@
 // order of multiple shader invocations in compute shader.
 TEST_P(ComputeShaderTest, groupMemoryBarrierAndBarrierTest)
 {
-    // Crashes on Windows 32-bit SwiftShader Subzero. http://anglebug.com/4482
-#if defined(ANGLE_IS_32_BIT_CPU)
-    ANGLE_SKIP_TEST_IF(isSwiftshader() && IsWindows());
-#endif
-
     // TODO(xinghua.cao@intel.com): Figure out why we get this error message
     // that shader uses features not recognized by this D3D version.
     ANGLE_SKIP_TEST_IF((IsAMD() || IsNVIDIA()) && IsD3D11());
@@ -1887,11 +1882,6 @@
 // Verify shared non-array variables can work correctly.
 TEST_P(ComputeShaderTest, NonArraySharedVariable)
 {
-    // Crashes on Windows 32-bit SwiftShader Subzero. http://anglebug.com/4482
-#if defined(ANGLE_IS_32_BIT_CPU)
-    ANGLE_SKIP_TEST_IF(isSwiftshader() && IsWindows());
-#endif
-
     const char kCSShader[] = R"(#version 310 es
 layout (local_size_x = 2, local_size_y = 2, local_size_z = 1) in;
 layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;
@@ -1925,11 +1915,6 @@
 // Verify shared non-struct array variables can work correctly.
 TEST_P(ComputeShaderTest, NonStructArrayAsSharedVariable)
 {
-    // Crashes on Windows 32-bit SwiftShader Subzero. http://anglebug.com/4482
-#if defined(ANGLE_IS_32_BIT_CPU)
-    ANGLE_SKIP_TEST_IF(isSwiftshader() && IsWindows());
-#endif
-
     const char kCSShader[] = R"(#version 310 es
 layout (local_size_x = 2, local_size_y = 2, local_size_z = 1) in;
 layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;
@@ -1954,11 +1939,6 @@
 // Verify shared struct array variables work correctly.
 TEST_P(ComputeShaderTest, StructArrayAsSharedVariable)
 {
-    // Crashes on Windows 32-bit SwiftShader Subzero. http://anglebug.com/4482
-#if defined(ANGLE_IS_32_BIT_CPU)
-    ANGLE_SKIP_TEST_IF(isSwiftshader() && IsWindows());
-#endif
-
     const char kCSShader[] = R"(#version 310 es
 layout (local_size_x = 2, local_size_y = 2, local_size_z = 1) in;
 layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;
@@ -1987,11 +1967,6 @@
 // Verify using atomic functions without return value can work correctly.
 TEST_P(ComputeShaderTest, AtomicFunctionsNoReturnValue)
 {
-    // Crashes on Windows 32-bit SwiftShader Subzero. http://anglebug.com/4482
-#if defined(ANGLE_IS_32_BIT_CPU)
-    ANGLE_SKIP_TEST_IF(isSwiftshader() && IsWindows());
-#endif
-
     // Fails on AMD windows drivers.  http://anglebug.com/3872
     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
 
@@ -2058,11 +2033,6 @@
 // Verify using atomic functions in a non-initializer single assignment can work correctly.
 TEST_P(ComputeShaderTest, AtomicFunctionsInNonInitializerSingleAssignment)
 {
-    // Crashes on Windows 32-bit SwiftShader Subzero. http://anglebug.com/4482
-#if defined(ANGLE_IS_32_BIT_CPU)
-    ANGLE_SKIP_TEST_IF(isSwiftshader() && IsWindows());
-#endif
-
     // Fails on AMD windows drivers.  http://anglebug.com/3872
     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
 
@@ -2112,11 +2082,6 @@
 // Verify using atomic functions in an initializers and using unsigned int works correctly.
 TEST_P(ComputeShaderTest, AtomicFunctionsInitializerWithUnsigned)
 {
-    // Crashes on Windows 32-bit SwiftShader Subzero. http://anglebug.com/4482
-#if defined(ANGLE_IS_32_BIT_CPU)
-    ANGLE_SKIP_TEST_IF(isSwiftshader() && IsWindows());
-#endif
-
     // Fails on AMD windows drivers.  http://anglebug.com/3872
     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
 
@@ -2177,11 +2142,6 @@
 // Verify using atomic functions inside expressions as unsigned int.
 TEST_P(ComputeShaderTest, AtomicFunctionsReturnWithUnsigned)
 {
-    // Crashes on Windows 32-bit SwiftShader Subzero. http://anglebug.com/4482
-#if defined(ANGLE_IS_32_BIT_CPU)
-    ANGLE_SKIP_TEST_IF(isSwiftshader() && IsWindows());
-#endif
-
     // Fails on AMD windows drivers.  http://anglebug.com/3872
     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
 
@@ -2232,11 +2192,6 @@
 // Verify using nested atomic functions in expressions.
 TEST_P(ComputeShaderTest, AtomicFunctionsReturnWithMultipleTypes)
 {
-    // Crashes on Windows 32-bit SwiftShader Subzero. http://anglebug.com/4482
-#if defined(ANGLE_IS_32_BIT_CPU)
-    ANGLE_SKIP_TEST_IF(isSwiftshader() && IsWindows());
-#endif
-
     constexpr char kCShader[] = R"(#version 310 es
 layout (local_size_x = 4, local_size_y = 1, local_size_z = 1) in;
 layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;
diff --git a/src/tests/gl_tests/DepthStencilFormatsTest.cpp b/src/tests/gl_tests/DepthStencilFormatsTest.cpp
index a496e0e..f378f43 100644
--- a/src/tests/gl_tests/DepthStencilFormatsTest.cpp
+++ b/src/tests/gl_tests/DepthStencilFormatsTest.cpp
@@ -12,6 +12,16 @@
 
 using namespace angle;
 
+struct ReadbackTestParam
+{
+    GLuint attachment;
+    GLuint format;
+    GLuint type;
+    void *data;
+    int depthBits;
+    int stencilBits;
+};
+
 class DepthStencilFormatsTestBase : public ANGLETest
 {
   protected:
@@ -160,6 +170,14 @@
         glDeleteTextures(1, &mTexture);
     }
 
+    bool hasReadDepthSupport() const { return IsGLExtensionEnabled("GL_NV_read_depth"); }
+
+    bool hasReadStencilSupport() const { return IsGLExtensionEnabled("GL_NV_read_stencil"); }
+
+    bool hasFloatDepthSupport() const { return IsGLExtensionEnabled("GL_NV_depth_buffer_float2"); }
+
+    void depthStencilReadbackCase(const ReadbackTestParam &type);
+
     GLuint mProgram;
     GLuint mTexture;
     GLint mTextureUniformLocation;
@@ -214,6 +232,216 @@
     }
 }
 
+void DepthStencilFormatsTestBase::depthStencilReadbackCase(const ReadbackTestParam &type)
+{
+    ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_depth_texture"));
+
+    const bool hasFloatDepth = (type.type == GL_FLOAT);
+    ANGLE_SKIP_TEST_IF(hasFloatDepth && !hasFloatDepthSupport());
+
+    const bool hasStencil = (type.format != GL_DEPTH_COMPONENT);
+
+    const bool supportPackedDepthStencilFramebuffer = getClientMajorVersion() >= 3;
+
+    const int res     = 2;
+    const int destRes = 4;
+
+    GLTexture tex;
+    glBindTexture(GL_TEXTURE_2D, tex);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+    // test level > 0
+    glTexImage2D(GL_TEXTURE_2D, 1, type.format, 1, 1, 0, type.format, type.type, nullptr);
+    EXPECT_GL_NO_ERROR();
+
+    // test with data
+    glTexImage2D(GL_TEXTURE_2D, 0, type.format, 1, 1, 0, type.format, type.type, type.data);
+    EXPECT_GL_NO_ERROR();
+
+    // test real thing
+    glTexImage2D(GL_TEXTURE_2D, 0, type.format, res, res, 0, type.format, type.type, nullptr);
+    EXPECT_GL_NO_ERROR();
+
+    // test texSubImage2D
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, type.format, type.type, type.data);
+    EXPECT_GL_NO_ERROR();
+
+    GLuint fbo = 0;
+    glGenFramebuffers(1, &fbo);
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+    if (type.depthBits > 0 && type.stencilBits > 0 && !supportPackedDepthStencilFramebuffer)
+    {
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, tex, 0);
+        EXPECT_GL_NO_ERROR();
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, tex, 0);
+        EXPECT_GL_NO_ERROR();
+    }
+    else
+    {
+        glFramebufferTexture2D(GL_FRAMEBUFFER, type.attachment, GL_TEXTURE_2D, tex, 0);
+        EXPECT_GL_NO_ERROR();
+    }
+
+    // Ensure DEPTH_BITS returns >= 16 bits for UNSIGNED_SHORT and UNSIGNED_INT, >= 24
+    // UNSIGNED_INT_24_8_WEBGL. If there is stencil, ensure STENCIL_BITS reports >= 8 for
+    // UNSIGNED_INT_24_8_WEBGL.
+
+    GLint depthBits = 0;
+    glGetIntegerv(GL_DEPTH_BITS, &depthBits);
+    EXPECT_GE(depthBits, type.depthBits);
+
+    GLint stencilBits = 0;
+    glGetIntegerv(GL_STENCIL_BITS, &stencilBits);
+    EXPECT_GE(stencilBits, type.stencilBits);
+
+    // TODO: remove this check if the spec is updated to require these combinations to work.
+    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+    {
+        // try adding a color buffer.
+        GLuint colorTex = 0;
+        glGenTextures(1, &colorTex);
+        glBindTexture(GL_TEXTURE_2D, colorTex);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, res, res, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTex, 0);
+        EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+    }
+
+    EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+    // use the default texture to render with while we return to the depth texture.
+    glBindTexture(GL_TEXTURE_2D, 0);
+
+    /* Setup 2x2 depth texture:
+     * 1 0.6 0.8
+     * |
+     * 0 0.2 0.4
+     *    0---1
+     */
+    GLbitfield clearBits = GL_DEPTH_BUFFER_BIT;
+    if (hasStencil)
+    {
+        clearBits |= GL_STENCIL_BUFFER_BIT;
+    }
+
+    const GLfloat d00 = 0.2;
+    const GLfloat d01 = 0.4;
+    const GLfloat d10 = 0.6;
+    const GLfloat d11 = 0.8;
+    glEnable(GL_SCISSOR_TEST);
+    glScissor(0, 0, 1, 1);
+    glClearDepthf(d00);
+    glClearStencil(1);
+    glClear(clearBits);
+    glScissor(1, 0, 1, 1);
+    glClearDepthf(d10);
+    glClearStencil(2);
+    glClear(clearBits);
+    glScissor(0, 1, 1, 1);
+    glClearDepthf(d01);
+    glClearStencil(3);
+    glClear(clearBits);
+    glScissor(1, 1, 1, 1);
+    glClearDepthf(d11);
+    glClearStencil(4);
+    glClear(clearBits);
+    glDisable(GL_SCISSOR_TEST);
+
+    GLubyte actualPixels[destRes * destRes * 8];
+    glReadPixels(0, 0, destRes, destRes, GL_DEPTH_COMPONENT,
+                 hasFloatDepth ? GL_FLOAT : GL_UNSIGNED_SHORT, actualPixels);
+    // NV_read_depth and NV_read_stencil do not support packed depth/stencil
+    if (hasReadDepthSupport() && type.format != GL_DEPTH_STENCIL)
+    {
+        EXPECT_GL_NO_ERROR();
+        if (hasFloatDepth)
+        {
+            constexpr float kEpsilon = 0.002f;
+            const float *pixels      = reinterpret_cast<const float *>(actualPixels);
+            ASSERT_NEAR(pixels[0], d00, kEpsilon);
+            ASSERT_NEAR(pixels[0 + destRes], d01, kEpsilon);
+            ASSERT_NEAR(pixels[1], d10, kEpsilon);
+            ASSERT_NEAR(pixels[1 + destRes], d11, kEpsilon);
+        }
+        else
+        {
+            auto scale = [](float f) {
+                return static_cast<uint16_t>(
+                    static_cast<float>(std::numeric_limits<uint16_t>::max()) * f);
+            };
+
+            constexpr unsigned short kEpsilon = 2;
+            const unsigned short *pixels = reinterpret_cast<const unsigned short *>(actualPixels);
+            ASSERT_NEAR(pixels[0], scale(d00), kEpsilon);
+            ASSERT_NEAR(pixels[0 + destRes], scale(d01), kEpsilon);
+            ASSERT_NEAR(pixels[1], scale(d10), kEpsilon);
+            ASSERT_NEAR(pixels[1 + destRes], scale(d11), kEpsilon);
+        }
+    }
+    else
+    {
+        EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+    }
+    if (hasStencil)
+    {
+        glReadPixels(0, 0, destRes, destRes, GL_STENCIL_INDEX_OES, GL_UNSIGNED_BYTE, actualPixels);
+        if (hasReadStencilSupport())
+        {
+            EXPECT_GL_NO_ERROR();
+            ASSERT_TRUE((actualPixels[0] == 1) && (actualPixels[1] == 2) &&
+                        (actualPixels[0 + destRes] == 3) && (actualPixels[1 + destRes] = 4));
+        }
+        else
+        {
+            EXPECT_GL_ERROR(GL_INVALID_OPERATION);
+        }
+    }
+}
+
+// This test will initialize a depth texture, clear it and read it back, if possible
+TEST_P(DepthStencilFormatsTest, DepthStencilReadback_UShort)
+{
+    GLuint fakeData[10]    = {0};
+    ReadbackTestParam type = {
+        GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, fakeData, 16, 0};
+    depthStencilReadbackCase(type);
+}
+
+// This test will initialize a depth texture, clear it and read it back, if possible
+TEST_P(DepthStencilFormatsTest, DepthStencilReadback_UInt)
+{
+    // http://anglebug.com/4573
+    ANGLE_SKIP_TEST_IF(IsWindows() && IsVulkan());
+
+    GLuint fakeData[10]    = {0};
+    ReadbackTestParam type = {
+        GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, fakeData, 16, 0};
+    depthStencilReadbackCase(type);
+}
+
+// This test will initialize a depth texture, clear it and read it back, if possible
+TEST_P(DepthStencilFormatsTest, DepthStencilReadback_Float)
+{
+    GLuint fakeData[10]    = {0};
+    ReadbackTestParam type = {GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT, GL_FLOAT, fakeData, 32, 0};
+    depthStencilReadbackCase(type);
+}
+
+// This test will initialize a depth texture, clear it and read it back, if possible
+TEST_P(DepthStencilFormatsTest, DepthStencilReadback_DepthStencil)
+{
+    GLuint fakeData[10]    = {0};
+    ReadbackTestParam type = {
+        GL_DEPTH_STENCIL_ATTACHMENT, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8_OES, fakeData, 24, 8};
+    depthStencilReadbackCase(type);
+}
+
 // This test will initialize a depth texture and then render with it and verify
 // pixel correctness.
 // This is modeled after webgl-depth-texture.html
@@ -266,14 +494,8 @@
     // OpenGL ES does not have a FLIPY PixelStore attribute
     // glPixelStorei(GL_UNPACK_FLIP)
 
-    enum ObjType
-    {
-        GL,
-        EXT
-    };
     struct TypeInfo
     {
-        ObjType obj;
         GLuint attachment;
         GLuint format;
         GLuint type;
@@ -285,10 +507,9 @@
     GLuint fakeData[10] = {0};
 
     std::vector<TypeInfo> types = {
-        {ObjType::GL, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, fakeData, 16, 0},
-        {ObjType::GL, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, fakeData, 16, 0},
-        {ObjType::EXT, GL_DEPTH_STENCIL_ATTACHMENT, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8_OES,
-         fakeData, 24, 8},
+        {GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, fakeData, 16, 0},
+        {GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, fakeData, 16, 0},
+        {GL_DEPTH_STENCIL_ATTACHMENT, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8_OES, fakeData, 24, 8},
     };
 
     for (const TypeInfo &type : types)
diff --git a/src/tests/gl_tests/DrawBaseVertexVariantsTest.cpp b/src/tests/gl_tests/DrawBaseVertexVariantsTest.cpp
new file mode 100644
index 0000000..c84fad7
--- /dev/null
+++ b/src/tests/gl_tests/DrawBaseVertexVariantsTest.cpp
@@ -0,0 +1,370 @@
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// DrawBaseVertexVariantsTest: Tests variants of drawElements*BaseVertex* call from different
+// extensions
+
+#include "gpu_info_util/SystemInfo.h"
+#include "test_utils/ANGLETest.h"
+#include "test_utils/gl_raii.h"
+
+#include <numeric>
+
+using namespace angle;
+
+namespace
+{
+
+// Create a kWidth * kHeight canvas equally split into kCountX * kCountY tiles
+// each containing a quad partially covering each tile
+constexpr uint32_t kWidth                   = 256;
+constexpr uint32_t kHeight                  = 256;
+constexpr uint32_t kCountX                  = 8;
+constexpr uint32_t kCountY                  = 8;
+constexpr int kBoxCount                     = kCountX * kCountY;
+constexpr uint32_t kIndexPatternRepeatCount = 3;
+constexpr std::array<GLfloat, 2> kTileSize  = {
+    1.f / static_cast<GLfloat>(kCountX),
+    1.f / static_cast<GLfloat>(kCountY),
+};
+constexpr std::array<uint32_t, 2> kTilePixelSize  = {kWidth / kCountX, kHeight / kCountY};
+constexpr std::array<GLfloat, 2> kQuadRadius      = {0.25f * kTileSize[0], 0.25f * kTileSize[1]};
+constexpr std::array<uint32_t, 2> kPixelCheckSize = {
+    static_cast<uint32_t>(kQuadRadius[0] * kWidth),
+    static_cast<uint32_t>(kQuadRadius[1] * kHeight)};
+
+constexpr std::array<GLfloat, 2> GetTileCenter(uint32_t x, uint32_t y)
+{
+    return {
+        kTileSize[0] * (0.5f + static_cast<GLfloat>(x)),
+        kTileSize[1] * (0.5f + static_cast<GLfloat>(y)),
+    };
+}
+constexpr std::array<std::array<GLfloat, 2>, 4> GetQuadVertices(uint32_t x, uint32_t y)
+{
+    const auto center = GetTileCenter(x, y);
+    return {
+        std::array<GLfloat, 2>{center[0] - kQuadRadius[0], center[1] - kQuadRadius[1]},
+        std::array<GLfloat, 2>{center[0] + kQuadRadius[0], center[1] - kQuadRadius[1]},
+        std::array<GLfloat, 2>{center[0] + kQuadRadius[0], center[1] + kQuadRadius[1]},
+        std::array<GLfloat, 2>{center[0] - kQuadRadius[0], center[1] + kQuadRadius[1]},
+    };
+}
+
+enum class DrawCallVariants
+{
+    DrawElementsBaseVertex,
+    DrawElementsInstancedBaseVertex,
+    DrawRangeElementsBaseVertex,
+    DrawElementsInstancedBaseVertexBaseInstance
+};
+
+// These tests check correctness of variants of baseVertex draw calls from different extensions
+
+class DrawBaseVertexVariantsTest : public ANGLETest
+{
+  protected:
+    DrawBaseVertexVariantsTest()
+    {
+        setWindowWidth(kWidth);
+        setWindowHeight(kHeight);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+
+        std::array<GLushort, 6> indices = {0, 1, 2, 0, 2, 3};
+        mIndices.resize(indices.size() * kIndexPatternRepeatCount);
+        for (uint32_t i = 0; i < kIndexPatternRepeatCount; i++)
+        {
+            size_t o  = i * indices.size();
+            size_t vo = i * 4;  // each quad has 4 vertices, index offset by 4
+            for (size_t j = 0; j < indices.size(); j++)
+            {
+                mIndices[o + j] = vo + indices[j];
+            }
+        }
+
+        mColorPalette = {GLColor(0x7f, 0x7f, 0x7f, 0xff),
+                         GLColor::red,
+                         GLColor::green,
+                         GLColor::yellow,
+                         GLColor::blue,
+                         GLColor::magenta,
+                         GLColor::cyan,
+                         GLColor::white};
+
+        for (uint32_t y = 0; y < kCountY; ++y)
+        {
+            for (uint32_t x = 0; x < kCountX; ++x)
+            {
+                // v3 ---- v2
+                // |       |
+                // |       |
+                // v0 ---- v1
+
+                const auto vs = ::GetQuadVertices(x, y);
+
+                for (const auto &v : vs)
+                {
+                    mVertices.insert(mVertices.end(), v.begin(), v.end());
+                }
+
+                const auto &colorPicked = mColorPalette[(x + y) % mColorPalette.size()];
+                for (int i = 0; i < 4; ++i)
+                {
+                    mVertexColors.push_back(colorPicked.R);
+                    mVertexColors.push_back(colorPicked.G);
+                    mVertexColors.push_back(colorPicked.B);
+                    mVertexColors.push_back(colorPicked.A);
+                }
+            }
+        }
+
+        mRegularIndices.resize(kCountY * kCountX * mIndices.size());
+        for (uint32_t y = 0; y < kCountY; y++)
+        {
+            for (uint32_t x = 0; x < kCountX; x++)
+            {
+                uint32_t i  = x + y * kCountX;
+                uint32_t oi = 6 * i;
+                uint32_t ov = 4 * i;
+                for (uint32_t j = 0; j < 6; j++)
+                {
+                    mRegularIndices[oi + j] = mIndices[j] + ov;
+                }
+            }
+        }
+    }
+
+    void setupProgram(GLProgram &program)
+    {
+        constexpr char vs[] = R"(
+precision mediump float;
+attribute vec2 vPosition;
+attribute vec4 vColor;
+varying vec4 color;
+void main()
+{
+    gl_Position = vec4(vec3(vPosition, 1.0) * 2.0 - 1.0, 1.0);
+    color = vColor;
+})";
+        constexpr char fs[] = R"(
+precision mediump float;
+varying vec4 color;
+void main()
+{
+    gl_FragColor = color;
+})";
+        program.makeRaster(vs, fs);
+        EXPECT_GL_NO_ERROR();
+        ASSERT_TRUE(program.valid());
+        glUseProgram(program.get());
+        mPositionLoc = glGetAttribLocation(program.get(), "vPosition");
+        ASSERT_NE(-1, mPositionLoc);
+        mColorLoc = glGetAttribLocation(program.get(), "vColor");
+        ASSERT_NE(-1, mColorLoc);
+    }
+
+    void setupIndexedBuffers(GLBuffer &vertexPositionBuffer,
+                             GLBuffer &vertexColorBuffer,
+                             GLBuffer &indexBuffer)
+    {
+        glBindBuffer(GL_ARRAY_BUFFER, vertexColorBuffer);
+        glBufferData(GL_ARRAY_BUFFER, sizeof(GLubyte) * mVertexColors.size(), mVertexColors.data(),
+                     GL_STATIC_DRAW);
+
+        glEnableVertexAttribArray(mColorLoc);
+        glVertexAttribPointer(mColorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
+
+        glBindBuffer(GL_ARRAY_BUFFER, vertexPositionBuffer);
+        glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * mVertices.size(), mVertices.data(),
+                     GL_STATIC_DRAW);
+
+        glEnableVertexAttribArray(mPositionLoc);
+        glVertexAttribPointer(mPositionLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
+
+        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
+        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * mIndices.size(), mIndices.data(),
+                     GL_STATIC_DRAW);
+
+        ASSERT_GL_NO_ERROR();
+    }
+
+    void doDrawElementsBaseVertexVariants(DrawCallVariants drawCallType)
+    {
+        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+        int baseRepetition = 0;
+        int i              = 0;
+
+        // Start at various repetitions within the patterned index buffer to exercise base
+        // index.
+
+        static_assert(kIndexPatternRepeatCount >= 3, "Repeat pattern count should be at least 3");
+
+        while (i < kBoxCount)
+        {
+            int repetitionCount = std::min(3 - baseRepetition, kBoxCount - i);
+
+            switch (drawCallType)
+            {
+                case DrawCallVariants::DrawElementsInstancedBaseVertexBaseInstance:
+                    glDrawElementsInstancedBaseVertexBaseInstanceANGLE(
+                        GL_TRIANGLES, repetitionCount * 6, GL_UNSIGNED_SHORT,
+                        reinterpret_cast<GLvoid *>(
+                            static_cast<uintptr_t>(baseRepetition * 6 * sizeof(GLushort))),
+                        1, (i - baseRepetition) * 4, 0);
+                    break;
+                case DrawCallVariants::DrawElementsBaseVertex:
+                    glDrawElementsBaseVertexEXT(
+                        GL_TRIANGLES, repetitionCount * 6, GL_UNSIGNED_SHORT,
+                        reinterpret_cast<GLvoid *>(
+                            static_cast<uintptr_t>(baseRepetition * 6 * sizeof(GLushort))),
+                        (i - baseRepetition) * 4);
+                    break;
+                case DrawCallVariants::DrawElementsInstancedBaseVertex:
+                    glDrawElementsInstancedBaseVertexEXT(
+                        GL_TRIANGLES, repetitionCount * 6, GL_UNSIGNED_SHORT,
+                        reinterpret_cast<GLvoid *>(
+                            static_cast<uintptr_t>(baseRepetition * 6 * sizeof(GLushort))),
+                        1, (i - baseRepetition) * 4);
+                    break;
+                case DrawCallVariants::DrawRangeElementsBaseVertex:
+                    glDrawRangeElementsBaseVertexEXT(
+                        GL_TRIANGLES, baseRepetition * 4,
+                        (baseRepetition + repetitionCount) * 4 - 1, repetitionCount * 6,
+                        GL_UNSIGNED_SHORT,
+                        reinterpret_cast<GLvoid *>(
+                            static_cast<uintptr_t>(baseRepetition * 6 * sizeof(GLushort))),
+                        (i - baseRepetition) * 4);
+                    break;
+                default:
+                    EXPECT_TRUE(false);
+                    break;
+            }
+
+            baseRepetition = (baseRepetition + 1) % 3;
+            i += repetitionCount;
+        }
+
+        EXPECT_GL_NO_ERROR();
+        checkDrawResult();
+    }
+
+    void checkDrawResult()
+    {
+        for (uint32_t y = 0; y < kCountY; ++y)
+        {
+            for (uint32_t x = 0; x < kCountX; ++x)
+            {
+                uint32_t center_x = x * kTilePixelSize[0] + kTilePixelSize[0] / 2;
+                uint32_t center_y = y * kTilePixelSize[1] + kTilePixelSize[1] / 2;
+
+                const auto &color = mColorPalette[(x + y) % mColorPalette.size()];
+
+                EXPECT_PIXEL_NEAR(center_x - kPixelCheckSize[0] / 2,
+                                  center_y - kPixelCheckSize[1] / 2, color[0], color[1], color[2],
+                                  color[3], 1);
+            }
+        }
+    }
+
+    bool requestAngleBaseVertexBaseInstanceExtensions()
+    {
+        if (getClientMajorVersion() <= 2)
+        {
+            if (!EnsureGLExtensionEnabled("GL_ANGLE_instanced_arrays"))
+            {
+                return false;
+            }
+        }
+        return EnsureGLExtensionEnabled("GL_ANGLE_base_vertex_base_instance");
+    }
+
+    bool requestNativeBaseVertexExtensions()
+    {
+        return (EnsureGLExtensionEnabled("GL_OES_draw_elements_base_vertex") ||
+                EnsureGLExtensionEnabled("GL_EXT_draw_elements_base_vertex"));
+    }
+
+    std::vector<GLushort> mIndices;
+    std::vector<GLfloat> mVertices;
+    std::vector<GLubyte> mVertexColors;
+
+    std::vector<GLColor> mColorPalette;
+    std::vector<GLushort> mRegularIndices;
+    GLint mPositionLoc;
+    GLint mColorLoc;
+};
+
+// Test drawElementsBaseVertex from OES/EXT_draw_elements_base_vertex
+TEST_P(DrawBaseVertexVariantsTest, DrawElementsBaseVertex)
+{
+    ANGLE_SKIP_TEST_IF(!requestNativeBaseVertexExtensions());
+
+    GLProgram program;
+    setupProgram(program);
+
+    GLBuffer indexBuffer;
+    GLBuffer vertexPositionBuffer;
+    GLBuffer vertexColorBuffer;
+    setupIndexedBuffers(vertexPositionBuffer, vertexColorBuffer, indexBuffer);
+
+    doDrawElementsBaseVertexVariants(DrawCallVariants::DrawElementsBaseVertex);
+}
+
+// Test drawElementsInstancedBaseVertex from OES/EXT_draw_elements_base_vertex
+TEST_P(DrawBaseVertexVariantsTest, DrawElementsInstancedBaseVertex)
+{
+    ANGLE_SKIP_TEST_IF(!requestNativeBaseVertexExtensions());
+
+    GLProgram program;
+    setupProgram(program);
+
+    GLBuffer indexBuffer;
+    GLBuffer vertexPositionBuffer;
+    GLBuffer vertexColorBuffer;
+    setupIndexedBuffers(vertexPositionBuffer, vertexColorBuffer, indexBuffer);
+
+    doDrawElementsBaseVertexVariants(DrawCallVariants::DrawElementsInstancedBaseVertex);
+}
+
+// Test drawRangeElementsBaseVertex from OES/EXT_draw_elements_base_vertex
+TEST_P(DrawBaseVertexVariantsTest, DrawRangeElementsBaseVertex)
+{
+    ANGLE_SKIP_TEST_IF(!requestNativeBaseVertexExtensions());
+
+    GLProgram program;
+    setupProgram(program);
+
+    GLBuffer indexBuffer;
+    GLBuffer vertexPositionBuffer;
+    GLBuffer vertexColorBuffer;
+    setupIndexedBuffers(vertexPositionBuffer, vertexColorBuffer, indexBuffer);
+
+    doDrawElementsBaseVertexVariants(DrawCallVariants::DrawRangeElementsBaseVertex);
+}
+
+// Test drawElementsInstancedBaseVertexBaseInstance from ANGLE_base_vertex_base_instance
+TEST_P(DrawBaseVertexVariantsTest, DrawElementsInstancedBaseVertexBaseInstance)
+{
+    ANGLE_SKIP_TEST_IF(!requestAngleBaseVertexBaseInstanceExtensions());
+
+    GLProgram program;
+    setupProgram(program);
+
+    GLBuffer indexBuffer;
+    GLBuffer vertexPositionBuffer;
+    GLBuffer vertexColorBuffer;
+    setupIndexedBuffers(vertexPositionBuffer, vertexColorBuffer, indexBuffer);
+
+    doDrawElementsBaseVertexVariants(DrawCallVariants::DrawElementsInstancedBaseVertexBaseInstance);
+}
+
+ANGLE_INSTANTIATE_TEST_ES3(DrawBaseVertexVariantsTest);
+
+}  // namespace
diff --git a/src/tests/gl_tests/DrawBuffersTest.cpp b/src/tests/gl_tests/DrawBuffersTest.cpp
index 1a585f1..bd07cc7 100644
--- a/src/tests/gl_tests/DrawBuffersTest.cpp
+++ b/src/tests/gl_tests/DrawBuffersTest.cpp
@@ -55,7 +55,7 @@
         }
 
         // This test seems to fail on an nVidia machine when the window is hidden
-        setWindowVisible(true);
+        setWindowVisible(getOSWindow(), true);
 
         glGenFramebuffers(1, &mFBO);
         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFBO);
diff --git a/src/tests/gl_tests/DrawElementsTest.cpp b/src/tests/gl_tests/DrawElementsTest.cpp
index f642c3f..fa12427 100644
--- a/src/tests/gl_tests/DrawElementsTest.cpp
+++ b/src/tests/gl_tests/DrawElementsTest.cpp
@@ -111,7 +111,7 @@
 // deleting the applied index buffer.
 TEST_P(DrawElementsTest, DeletingAfterStreamingIndexes)
 {
-    // http://anglebug.com/4092
+    // http://anglebug.com/4575 - Test skipped on D3D11 (alpha channel not correct)
     ANGLE_SKIP_TEST_IF(IsWindows() && IsD3D11());
     // Init program
     constexpr char kVS[] =
@@ -162,47 +162,15 @@
         item += 4u;
     }
 
-    std::vector<GLfloat> positionData;
-    // quad verts
-    positionData.push_back(-1.0f);
-    positionData.push_back(1.0f);
-    positionData.push_back(-1.0f);
-    positionData.push_back(-1.0f);
-    positionData.push_back(1.0f);
-    positionData.push_back(-1.0f);
-    positionData.push_back(1.0f);
-    positionData.push_back(1.0f);
+    std::vector<GLfloat> positionData = {// quad verts
+                                         -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f,
+                                         // Repeat position data
+                                         -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f};
 
-    // Repeat position data
-    positionData.push_back(-1.0f);
-    positionData.push_back(1.0f);
-    positionData.push_back(-1.0f);
-    positionData.push_back(-1.0f);
-    positionData.push_back(1.0f);
-    positionData.push_back(-1.0f);
-    positionData.push_back(1.0f);
-    positionData.push_back(1.0f);
-
-    std::vector<GLfloat> testFlagData;
-    // red
-    testFlagData.push_back(1.0f);
-    testFlagData.push_back(0.0f);
-    testFlagData.push_back(1.0f);
-    testFlagData.push_back(0.0f);
-    testFlagData.push_back(1.0f);
-    testFlagData.push_back(0.0f);
-    testFlagData.push_back(1.0f);
-    testFlagData.push_back(0.0f);
-
-    // green
-    testFlagData.push_back(0.0f);
-    testFlagData.push_back(1.0f);
-    testFlagData.push_back(0.0f);
-    testFlagData.push_back(1.0f);
-    testFlagData.push_back(0.0f);
-    testFlagData.push_back(1.0f);
-    testFlagData.push_back(0.0f);
-    testFlagData.push_back(1.0f);
+    std::vector<GLfloat> testFlagData = {// red
+                                         1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
+                                         // green
+                                         0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f};
 
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffers[0]);
     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * indexData[0].size(), &indexData[0][0],
@@ -249,24 +217,149 @@
 
     glBindVertexArray(mVertexArrays[0]);
     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
-    EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 
     glBindVertexArray(mVertexArrays[1]);
     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
-    EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
 
     glBindVertexArray(mVertexArrays[0]);
     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
-    EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 
     // Trigger the bug here.
     glDeleteBuffers(1, &mIndexBuffers[2]);
 
     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
-    EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 
     ASSERT_GL_NO_ERROR();
 }
+
+// Test drawing to part of the indices in an index buffer, and then all of them.
+TEST_P(DrawElementsTest, PartOfIndexBufferThenAll)
+{
+    // http://anglebug.com/4575 - Test skipped on D3D11 (alpha channel not correct)
+    // http://anglebug.com/4576 - Test skipped on SwiftShader (alpha channel not drawn)
+    ANGLE_SKIP_TEST_IF(IsWindows() && (IsD3D11() || isSwiftshader()));
+    // Init program
+    constexpr char kVS[] =
+        "attribute vec2 position;\n"
+        "attribute vec2 testFlag;\n"
+        "varying vec2 v_data;\n"
+        "void main() {\n"
+        "  gl_Position = vec4(position, 0, 1);\n"
+        "  v_data = testFlag;\n"
+        "}";
+
+    constexpr char kFS[] =
+        "varying highp vec2 v_data;\n"
+        "void main() {\n"
+        "  gl_FragColor = vec4(v_data, 0, 1);\n"
+        "}";
+
+    mProgram = CompileProgram(kVS, kFS);
+    ASSERT_NE(0u, mProgram);
+    glUseProgram(mProgram);
+
+    GLint positionLocation = glGetAttribLocation(mProgram, "position");
+    ASSERT_NE(-1, positionLocation);
+
+    GLint testFlagLocation = glGetAttribLocation(mProgram, "testFlag");
+    ASSERT_NE(-1, testFlagLocation);
+
+    mIndexBuffers.resize(1);
+    glGenBuffers(1, &mIndexBuffers[0]);
+
+    mVertexArrays.resize(1);
+    glGenVertexArrays(1, &mVertexArrays[0]);
+
+    mVertexBuffers.resize(2);
+    glGenBuffers(2, &mVertexBuffers[0]);
+
+    std::vector<GLubyte> indexData[2];
+    indexData[0].push_back(0);
+    indexData[0].push_back(1);
+    indexData[0].push_back(2);
+    indexData[0].push_back(2);
+    indexData[0].push_back(3);
+    indexData[0].push_back(0);
+    indexData[0].push_back(4);
+    indexData[0].push_back(5);
+    indexData[0].push_back(6);
+    indexData[0].push_back(6);
+    indexData[0].push_back(7);
+    indexData[0].push_back(4);
+
+    // Make a copy:
+    indexData[1] = indexData[0];
+
+    std::vector<GLfloat> positionData = {// quad verts
+                                         -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f,
+                                         // Repeat position data
+                                         -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f};
+
+    std::vector<GLfloat> testFlagData = {// red
+                                         1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
+                                         // green
+                                         0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f};
+
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffers[0]);
+    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLubyte) * indexData[0].size(), &indexData[0][0],
+                 GL_STATIC_DRAW);
+
+    glBindVertexArray(mVertexArrays[0]);
+
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffers[0]);
+    glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffers[0]);
+    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * positionData.size(), &positionData[0],
+                 GL_STATIC_DRAW);
+    glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 2, nullptr);
+    glEnableVertexAttribArray(positionLocation);
+
+    glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffers[1]);
+    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * testFlagData.size(), &testFlagData[0],
+                 GL_STATIC_DRAW);
+    glVertexAttribPointer(testFlagLocation, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 2, nullptr);
+    glEnableVertexAttribArray(testFlagLocation);
+
+    ASSERT_GL_NO_ERROR();
+
+    // Draw with just the second set of 6 items, then first 6, and then the entire index buffer
+    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, reinterpret_cast<const void *>(6));
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+
+    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, nullptr);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
+
+    glDrawElements(GL_TRIANGLES, 12, GL_UNSIGNED_BYTE, nullptr);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+
+    // Reload the buffer again with a copy of the same data
+    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLubyte) * indexData[1].size(), &indexData[1][0],
+                 GL_STATIC_DRAW);
+
+    // Draw with just the first 6 indices, and then with the entire index buffer
+    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, nullptr);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
+
+    glDrawElements(GL_TRIANGLES, 12, GL_UNSIGNED_BYTE, nullptr);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+
+    // Reload the buffer again with a copy of the same data
+    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLubyte) * indexData[0].size(), &indexData[0][0],
+                 GL_STATIC_DRAW);
+
+    // This time, do not check color between draws (which causes a flush):
+    // Draw with just the second set of 6 items, then first 6, and then the entire index buffer
+    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, reinterpret_cast<const void *>(6));
+    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, nullptr);
+    glDrawElements(GL_TRIANGLES, 12, GL_UNSIGNED_BYTE, nullptr);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+
+    ASSERT_GL_NO_ERROR();
+}
+
 // Test that the offset in the index buffer is forced to be a multiple of the element size
 TEST_P(WebGLDrawElementsTest, DrawElementsTypeAlignment)
 {
diff --git a/src/tests/gl_tests/ExternalWrapTest.cpp b/src/tests/gl_tests/ExternalWrapTest.cpp
index ffc3117..529b6d0 100644
--- a/src/tests/gl_tests/ExternalWrapTest.cpp
+++ b/src/tests/gl_tests/ExternalWrapTest.cpp
@@ -153,6 +153,9 @@
     ANGLE_SKIP_TEST_IF(
         !IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), "EGL_KHR_gl_texture_2D_image"));
 
+    // Ozone only supports external target for images created with EGL_EXT_image_dma_buf_import
+    ANGLE_SKIP_TEST_IF(IsOzone());
+
     createExternalTexture();
 
     ASSERT_NE(mProgram, 0u);
@@ -175,6 +178,9 @@
     ANGLE_SKIP_TEST_IF(
         !IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), "EGL_KHR_gl_texture_2D_image"));
 
+    // Ozone only supports external target for images created with EGL_EXT_image_dma_buf_import
+    ANGLE_SKIP_TEST_IF(IsOzone());
+
     createExternalTexture();
 
     ASSERT_NE(mProgram, 0u);
@@ -200,6 +206,9 @@
         !IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), "EGL_KHR_gl_texture_2D_image"));
     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_EGL_image_external_wrap_modes"));
 
+    // Ozone only supports external target for images created with EGL_EXT_image_dma_buf_import
+    ANGLE_SKIP_TEST_IF(IsOzone());
+
     createExternalTexture();
 
     ASSERT_NE(mProgram, 0u);
@@ -229,6 +238,9 @@
         !IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), "EGL_KHR_gl_texture_2D_image"));
     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_EGL_image_external_wrap_modes"));
 
+    // Ozone only supports external target for images created with EGL_EXT_image_dma_buf_import
+    ANGLE_SKIP_TEST_IF(IsOzone());
+
     createExternalTexture();
 
     ASSERT_NE(mProgram, 0u);
diff --git a/src/tests/gl_tests/FenceSyncTests.cpp b/src/tests/gl_tests/FenceSyncTests.cpp
index e45afb3..db0c975 100644
--- a/src/tests/gl_tests/FenceSyncTests.cpp
+++ b/src/tests/gl_tests/FenceSyncTests.cpp
@@ -195,7 +195,7 @@
     EXPECT_EQ(20, length);
     EXPECT_EQ(30, value);
 
-    // glGetSynciv generates GL_INVALID_VALUE if the sync object tis not valid, results should be
+    // glGetSynciv generates GL_INVALID_VALUE if the sync object is not valid, results should be
     // untouched
     glGetSynciv(reinterpret_cast<GLsync>(30), GL_OBJECT_TYPE, 1, &length, &value);
     EXPECT_GL_ERROR(GL_INVALID_VALUE);
diff --git a/src/tests/gl_tests/FramebufferTest.cpp b/src/tests/gl_tests/FramebufferTest.cpp
index 6f21169..0bd1cbf 100644
--- a/src/tests/gl_tests/FramebufferTest.cpp
+++ b/src/tests/gl_tests/FramebufferTest.cpp
@@ -1208,7 +1208,306 @@
     ASSERT_GL_NO_ERROR();
 }
 
+// Covers a bug in ANGLE's Vulkan back-end framebuffer cache which ignored depth/stencil after
+// calls to DrawBuffers.
+TEST_P(FramebufferTest_ES3, AttachmentStateChange)
+{
+    constexpr GLuint kSize = 2;
+
+    ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
+
+    GLTexture colorTexture;
+    glBindTexture(GL_TEXTURE_2D, colorTexture);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+
+    GLFramebuffer fbo;
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
+
+    ASSERT_GL_NO_ERROR();
+    ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
+
+    // First draw without a depth buffer.
+    drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
+
+    GLRenderbuffer depthBuffer;
+    glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, kSize, kSize);
+
+    // Bind just a renderbuffer and draw.
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer);
+
+    ASSERT_GL_NO_ERROR();
+    ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
+
+    glDrawBuffers(0, nullptr);
+    drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
+
+    // Re-enable color buffer and draw one final time. This previously triggered a crash.
+    GLenum drawBuffs = {GL_COLOR_ATTACHMENT0};
+    glDrawBuffers(1, &drawBuffs);
+
+    drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
+    ASSERT_GL_NO_ERROR();
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+}
+
+// Tests that we can support a feedback loop between a depth textures and the depth buffer.
+// Does not totally mirror the case used in Manhattan. The Manhattan case seems to handle
+// "clear" specially instead of rendering to depth in the same RP.
+TEST_P(FramebufferTest_ES3, DepthFeedbackLoopSupported)
+{
+    // Feedback loops not supported on D3D11 and may not ever be.
+    ANGLE_SKIP_TEST_IF(IsD3D11());
+
+    // Also this particular test doesn't work on Android despite similar support in Manhattan.
+    ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
+
+    constexpr GLuint kSize = 2;
+    glViewport(0, 0, kSize, kSize);
+
+    constexpr char kFS[] = R"(precision mediump float;
+varying vec2 v_texCoord;
+uniform sampler2D depth;
+void main()
+{
+    if (abs(texture2D(depth, v_texCoord).x - 0.5) < 0.1)
+    {
+        gl_FragColor = vec4(0, 1, 0, 1);
+    }
+    else
+    {
+        gl_FragColor = vec4(1, 0, 0, 1);
+    }
+})";
+
+    ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), kFS);
+
+    GLFramebuffer framebuffer;
+    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
+
+    GLTexture colorTexture;
+    glBindTexture(GL_TEXTURE_2D, colorTexture);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
+
+    GLTexture depthTexture;
+    glBindTexture(GL_TEXTURE_2D, depthTexture);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, kSize, kSize, 0, GL_DEPTH_COMPONENT,
+                 GL_UNSIGNED_INT, nullptr);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
+
+    ASSERT_GL_NO_ERROR();
+    ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
+
+    // Clear depth to 0.5.
+    glClearDepthf(0.5f);
+    glClear(GL_DEPTH_BUFFER_BIT);
+
+    // Disable the depth mask. Although this does not remove the feedback loop as defined by the
+    // spec it mimics what gfxbench does in its rendering tests.
+    glDepthMask(false);
+
+    // Verify we can sample the depth texture and get 0.5.
+    drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
+
+    ASSERT_GL_NO_ERROR();
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+}
+
+// Covers a bug in ANGLE's Vulkan back-end. Our VkFramebuffer cache would in some cases forget to
+// check the draw states when computing a cache key.
+TEST_P(FramebufferTest_ES3, DisabledAttachmentRedefinition)
+{
+    constexpr GLuint kSize = 2;
+
+    // Make a Framebuffer with two attachments with one enabled and one disabled.
+    GLTexture texA, texB;
+    glBindTexture(GL_TEXTURE_2D, texA);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glBindTexture(GL_TEXTURE_2D, texB);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+
+    GLFramebuffer fbo;
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texA, 0);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, texB, 0);
+
+    // Mask out the second texture.
+    constexpr GLenum kOneDrawBuf = GL_COLOR_ATTACHMENT0;
+    glDrawBuffers(1, &kOneDrawBuf);
+
+    ASSERT_GL_NO_ERROR();
+    ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
+
+    // Set up a very simple shader.
+    ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
+    glViewport(0, 0, kSize, kSize);
+
+    // Draw
+    drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
+    ASSERT_GL_NO_ERROR();
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+
+    // Update the masked out attachment and draw again.
+    std::vector<GLColor> redPixels(kSize * kSize, GLColor::red);
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE,
+                    redPixels.data());
+
+    // Draw
+    drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
+    ASSERT_GL_NO_ERROR();
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+
+    glReadBuffer(GL_COLOR_ATTACHMENT1);
+    ASSERT_GL_NO_ERROR();
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
+}
+
+class FramebufferTest : public ANGLETest
+{};
+
+template <typename T>
+void FillTexture2D(GLuint texture,
+                   GLsizei width,
+                   GLsizei height,
+                   const T &onePixelData,
+                   GLint level,
+                   GLint internalFormat,
+                   GLenum format,
+                   GLenum type)
+{
+    std::vector<T> allPixelsData(width * height, onePixelData);
+
+    glBindTexture(GL_TEXTURE_2D, texture);
+    glTexImage2D(GL_TEXTURE_2D, level, internalFormat, width, height, 0, format, type,
+                 allPixelsData.data());
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+}
+
+// Multi-context uses of textures should not cause rendering feedback loops.
+TEST_P(FramebufferTest, MultiContextNoRenderingFeedbackLoops)
+{
+    constexpr char kTextureVS[] =
+        R"(attribute vec4 a_position;
+varying vec2 v_texCoord;
+void main() {
+    gl_Position = a_position;
+    v_texCoord = (a_position.xy * 0.5) + 0.5;
+})";
+
+    constexpr char kTextureFS[] =
+        R"(precision mediump float;
+varying vec2 v_texCoord;
+uniform sampler2D u_texture;
+void main() {
+    gl_FragColor = texture2D(u_texture, v_texCoord).rgba;
+})";
+
+    ANGLE_GL_PROGRAM(textureProgram, kTextureVS, kTextureFS);
+
+    glUseProgram(textureProgram.get());
+    GLint uniformLoc = glGetUniformLocation(textureProgram.get(), "u_texture");
+    ASSERT_NE(-1, uniformLoc);
+    glUniform1i(uniformLoc, 0);
+
+    GLTexture texture;
+    FillTexture2D(texture.get(), 1, 1, GLColor::red, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
+    glBindTexture(GL_TEXTURE_2D, texture.get());
+    // Note that _texture_ is still bound to GL_TEXTURE_2D in this context at this point.
+
+    EGLWindow *window          = getEGLWindow();
+    EGLDisplay display         = window->getDisplay();
+    EGLConfig config           = window->getConfig();
+    EGLSurface surface         = window->getSurface();
+    EGLint contextAttributes[] = {
+        EGL_CONTEXT_MAJOR_VERSION_KHR,
+        GetParam().majorVersion,
+        EGL_CONTEXT_MINOR_VERSION_KHR,
+        GetParam().minorVersion,
+        EGL_NONE,
+    };
+    EGLContext context1 = eglGetCurrentContext();
+    // Create context2, sharing resources with context1.
+    EGLContext context2 = eglCreateContext(display, config, context1, contextAttributes);
+    ASSERT_NE(context2, EGL_NO_CONTEXT);
+    eglMakeCurrent(display, surface, surface, context2);
+
+    constexpr char kVS[] =
+        R"(attribute vec4 a_position;
+void main() {
+    gl_Position = a_position;
+})";
+
+    constexpr char kFS[] =
+        R"(precision mediump float;
+void main() {
+    gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+})";
+
+    ANGLE_GL_PROGRAM(program, kVS, kFS);
+    glUseProgram(program.get());
+
+    ASSERT_GL_NO_ERROR();
+
+    // Render to the texture in context2.
+    GLFramebuffer framebuffer;
+    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
+    // Texture is still a valid name in context2.
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
+    ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+    // There is no rendering feedback loop at this point.
+
+    glDisable(GL_BLEND);
+    glDisable(GL_DEPTH_TEST);
+    ASSERT_GL_NO_ERROR();
+
+    // If draw is no-op'ed, texture will not be filled appropriately.
+    drawQuad(program.get(), "a_position", 0.5f, 1.0f, true);
+    ASSERT_GL_NO_ERROR();
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+
+    // Make context1 current again.
+    eglMakeCurrent(display, surface, surface, context1);
+
+    // Render texture to screen.
+    drawQuad(textureProgram.get(), "a_position", 0.5f, 1.0f, true);
+    ASSERT_GL_NO_ERROR();
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+
+    eglDestroyContext(display, context2);
+}
+
+// Ensure cube-incomplete attachments cause incomplete Framebuffers.
+TEST_P(FramebufferTest, IncompleteCubeMap)
+{
+    constexpr GLuint kSize = 2;
+
+    GLTexture srcTex;
+    glBindTexture(GL_TEXTURE_CUBE_MAP, srcTex);
+    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA,
+                 GL_UNSIGNED_BYTE, nullptr);
+
+    GLFramebuffer fbo;
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X,
+                           srcTex, 0);
+
+    ASSERT_GL_NO_ERROR();
+    ASSERT_GLENUM_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
+                     GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
+}
+
 ANGLE_INSTANTIATE_TEST_ES2(AddDummyTextureNoRenderTargetTest);
+ANGLE_INSTANTIATE_TEST_ES2(FramebufferTest);
 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(FramebufferFormatsTest);
 ANGLE_INSTANTIATE_TEST_ES3(FramebufferTest_ES3);
 ANGLE_INSTANTIATE_TEST_ES31(FramebufferTest_ES31);
diff --git a/src/tests/gl_tests/ImageTest.cpp b/src/tests/gl_tests/ImageTest.cpp
index fef9f7b..1c421aa 100644
--- a/src/tests/gl_tests/ImageTest.cpp
+++ b/src/tests/gl_tests/ImageTest.cpp
@@ -15,15 +15,24 @@
 {
 namespace
 {
-constexpr char kOESExt[]           = "GL_OES_EGL_image";
-constexpr char kExternalExt[]      = "GL_OES_EGL_image_external";
-constexpr char kExternalESSL3Ext[] = "GL_OES_EGL_image_external_essl3";
-constexpr char kBaseExt[]          = "EGL_KHR_image_base";
-constexpr char k2DTextureExt[]     = "EGL_KHR_gl_texture_2D_image";
-constexpr char k3DTextureExt[]     = "EGL_KHR_gl_texture_3D_image";
-constexpr char kPixmapExt[]        = "EGL_KHR_image_pixmap";
-constexpr char kRenderbufferExt[]  = "EGL_KHR_gl_renderbuffer_image";
-constexpr char kCubemapExt[]       = "EGL_KHR_gl_texture_cubemap_image";
+constexpr char kOESExt[]               = "GL_OES_EGL_image";
+constexpr char kExternalExt[]          = "GL_OES_EGL_image_external";
+constexpr char kExternalESSL3Ext[]     = "GL_OES_EGL_image_external_essl3";
+constexpr char kBaseExt[]              = "EGL_KHR_image_base";
+constexpr char k2DTextureExt[]         = "EGL_KHR_gl_texture_2D_image";
+constexpr char k3DTextureExt[]         = "EGL_KHR_gl_texture_3D_image";
+constexpr char kPixmapExt[]            = "EGL_KHR_image_pixmap";
+constexpr char kRenderbufferExt[]      = "EGL_KHR_gl_renderbuffer_image";
+constexpr char kCubemapExt[]           = "EGL_KHR_gl_texture_cubemap_image";
+constexpr char kImageGLColorspaceExt[] = "EGL_EXT_image_gl_colorspace";
+constexpr EGLint kDefaultAttribs[]     = {
+    EGL_IMAGE_PRESERVED,
+    EGL_TRUE,
+    EGL_NONE,
+};
+constexpr EGLint kColorspaceAttribs[] = {
+    EGL_IMAGE_PRESERVED, EGL_TRUE, EGL_GL_COLORSPACE, EGL_GL_COLORSPACE_SRGB_KHR, EGL_NONE,
+};
 }  // anonymous namespace
 
 class ImageTest : public ANGLETest
@@ -137,6 +146,7 @@
                                        size_t height,
                                        GLenum format,
                                        GLenum type,
+                                       const EGLint *attribs,
                                        void *data,
                                        GLuint *outSourceTexture,
                                        EGLImageKHR *outSourceImage)
@@ -158,12 +168,6 @@
         // Create an image from the source texture
         EGLWindow *window = getEGLWindow();
 
-        EGLint attribs[] = {
-            EGL_IMAGE_PRESERVED,
-            EGL_TRUE,
-            EGL_NONE,
-        };
-
         EGLImageKHR image =
             eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_2D_KHR,
                               reinterpretHelper<EGLClientBuffer>(source), attribs);
@@ -178,6 +182,7 @@
                                             size_t height,
                                             GLenum format,
                                             GLenum type,
+                                            const EGLint *attribs,
                                             uint8_t *data,
                                             size_t dataStride,
                                             EGLenum imageTarget,
@@ -205,12 +210,6 @@
         // Create an image from the source texture
         EGLWindow *window = getEGLWindow();
 
-        EGLint attribs[] = {
-            EGL_IMAGE_PRESERVED,
-            EGL_TRUE,
-            EGL_NONE,
-        };
-
         EGLImageKHR image =
             eglCreateImageKHR(window->getDisplay(), window->getContext(), imageTarget,
                               reinterpretHelper<EGLClientBuffer>(source), attribs);
@@ -226,8 +225,8 @@
                                        size_t depth,
                                        GLenum format,
                                        GLenum type,
+                                       const EGLint *attribs,
                                        void *data,
-                                       size_t imageLayer,
                                        GLuint *outSourceTexture,
                                        EGLImageKHR *outSourceImage)
     {
@@ -249,13 +248,6 @@
         // Create an image from the source texture
         EGLWindow *window = getEGLWindow();
 
-        EGLint attribs[] = {
-            EGL_GL_TEXTURE_ZOFFSET_KHR,
-            static_cast<EGLint>(imageLayer),
-            EGL_IMAGE_PRESERVED,
-            EGL_TRUE,
-            EGL_NONE,
-        };
         EGLImageKHR image =
             eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_3D_KHR,
                               reinterpretHelper<EGLClientBuffer>(source), attribs);
@@ -269,6 +261,7 @@
     void createEGLImageRenderbufferSource(size_t width,
                                           size_t height,
                                           GLenum internalFormat,
+                                          const EGLint *attribs,
                                           GLubyte data[4],
                                           GLuint *outSourceRenderbuffer,
                                           EGLImageKHR *outSourceImage)
@@ -296,12 +289,6 @@
         // Create an image from the source renderbuffer
         EGLWindow *window = getEGLWindow();
 
-        EGLint attribs[] = {
-            EGL_IMAGE_PRESERVED,
-            EGL_TRUE,
-            EGL_NONE,
-        };
-
         EGLImageKHR image =
             eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_RENDERBUFFER_KHR,
                               reinterpretHelper<EGLClientBuffer>(source), attribs);
@@ -359,6 +346,24 @@
         *outTargetRenderbuffer = target;
     }
 
+    void ValidationGLEGLImage_helper(const EGLint *attribs);
+    void Source2DTarget2D_helper(const EGLint *attribs);
+    void Source2DTargetRenderbuffer_helper(const EGLint *attribs);
+    void Source2DTargetExternal_helper(const EGLint *attribs);
+    void Source2DTargetExternalESSL3_helper(const EGLint *attribs);
+    void SourceCubeTarget2D_helper(const EGLint *attribs);
+    void SourceCubeTargetRenderbuffer_helper(const EGLint *attribs);
+    void SourceCubeTargetExternal_helper(const EGLint *attribs);
+    void SourceCubeTargetExternalESSL3_helper(const EGLint *attribs);
+    void Source3DTargetTexture_helper(const bool withColorspace);
+    void Source3DTargetRenderbuffer_helper(const bool withColorspace);
+    void Source3DTargetExternal_helper(const bool withColorspace);
+    void Source3DTargetExternalESSL3_helper(const bool withColorspace);
+    void SourceRenderbufferTargetTexture_helper(const EGLint *attribs);
+    void SourceRenderbufferTargetTextureExternal_helper(const EGLint *attribs);
+    void SourceRenderbufferTargetRenderbuffer_helper(const EGLint *attribs);
+    void SourceRenderbufferTargetTextureExternalESSL3_helper(const EGLint *attribs);
+
     void verifyResultsTexture(GLuint texture,
                               GLubyte data[4],
                               GLenum textureTarget,
@@ -418,6 +423,11 @@
         return reinterpret_cast<destType>(sourceSizeT);
     }
 
+    bool hasImageGLColorspaceExt() const
+    {
+        return IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), kImageGLColorspaceExt);
+    }
+
     bool hasOESExt() const { return IsGLExtensionEnabled(kOESExt); }
 
     bool hasExternalExt() const { return IsGLExtensionEnabled(kExternalExt); }
@@ -454,6 +464,30 @@
         return IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), kCubemapExt);
     }
 
+    EGLint *get3DAttributes(const bool withColorspace = false, EGLint layer = 0)
+    {
+        if (!withColorspace)
+        {
+            default3DAttribs[1] = static_cast<EGLint>(layer);
+            return default3DAttribs;
+        }
+
+        colorspace3DAttribs[1] = static_cast<EGLint>(layer);
+        return colorspace3DAttribs;
+    }
+
+    EGLint default3DAttribs[5] = {
+        EGL_GL_TEXTURE_ZOFFSET_KHR, static_cast<EGLint>(0), EGL_IMAGE_PRESERVED, EGL_TRUE, EGL_NONE,
+    };
+    EGLint colorspace3DAttribs[7] = {
+        EGL_GL_TEXTURE_ZOFFSET_KHR,
+        static_cast<EGLint>(0),
+        EGL_IMAGE_PRESERVED,
+        EGL_TRUE,
+        EGL_GL_COLORSPACE,
+        EGL_GL_COLORSPACE_SRGB_KHR,
+        EGL_NONE,
+    };
     GLuint mTextureProgram;
     GLint mTextureUniformLocation;
 
@@ -922,6 +956,18 @@
 // Check validation from the GL_OES_EGL_image extension
 TEST_P(ImageTest, ValidationGLEGLImage)
 {
+    ValidationGLEGLImage_helper(kDefaultAttribs);
+}
+
+TEST_P(ImageTest, ValidationGLEGLImage_Colorspace)
+{
+    ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
+    ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
+    ValidationGLEGLImage_helper(kColorspaceAttribs);
+}
+
+void ImageTest::ValidationGLEGLImage_helper(const EGLint *attribs)
+{
     ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
 
     GLubyte data[4] = {255, 0, 255, 255};
@@ -929,7 +975,7 @@
     // Create the Image
     GLuint source;
     EGLImageKHR image;
-    createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data, &source, &image);
+    createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, attribs, data, &source, &image);
 
     // If <target> is not TEXTURE_2D, the error INVALID_ENUM is generated.
     glEGLImageTargetTexture2DOES(GL_TEXTURE_CUBE_MAP_POSITIVE_X, image);
@@ -1088,6 +1134,18 @@
 
 TEST_P(ImageTest, Source2DTarget2D)
 {
+    Source2DTarget2D_helper(kDefaultAttribs);
+}
+
+TEST_P(ImageTest, Source2DTarget2D_Colorspace)
+{
+    ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
+    ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
+    Source2DTarget2D_helper(kColorspaceAttribs);
+}
+
+void ImageTest::Source2DTarget2D_helper(const EGLint *attribs)
+{
     EGLWindow *window = getEGLWindow();
     ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
 
@@ -1096,7 +1154,7 @@
     // Create the Image
     GLuint source;
     EGLImageKHR image;
-    createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data, &source, &image);
+    createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, attribs, data, &source, &image);
 
     // Create the target
     GLuint target;
@@ -1113,6 +1171,19 @@
 
 TEST_P(ImageTest, Source2DTargetRenderbuffer)
 {
+    Source2DTargetRenderbuffer_helper(kDefaultAttribs);
+}
+
+TEST_P(ImageTest, Source2DTargetRenderbuffer_Colorspace)
+{
+    ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
+    ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
+    Source2DTargetRenderbuffer_helper(kColorspaceAttribs);
+}
+
+void ImageTest::Source2DTargetRenderbuffer_helper(const EGLint *attribs)
+{
+
     EGLWindow *window = getEGLWindow();
     ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
 
@@ -1121,7 +1192,7 @@
     // Create the Image
     GLuint source;
     EGLImageKHR image;
-    createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data, &source, &image);
+    createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, attribs, data, &source, &image);
 
     // Create the target
     GLuint target;
@@ -1138,6 +1209,18 @@
 
 TEST_P(ImageTest, Source2DTargetExternal)
 {
+    Source2DTargetExternal_helper(kDefaultAttribs);
+}
+
+TEST_P(ImageTest, Source2DTargetExternal_Colorspace)
+{
+    ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
+    ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
+    Source2DTargetExternal_helper(kColorspaceAttribs);
+}
+
+void ImageTest::Source2DTargetExternal_helper(const EGLint *attribs)
+{
     EGLWindow *window = getEGLWindow();
     ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() || !hasExternalExt());
 
@@ -1149,7 +1232,7 @@
     // Create the Image
     GLuint source;
     EGLImageKHR image;
-    createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data, &source, &image);
+    createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, attribs, data, &source, &image);
 
     // Create the target
     GLuint target;
@@ -1166,6 +1249,18 @@
 
 TEST_P(ImageTestES3, Source2DTargetExternalESSL3)
 {
+    Source2DTargetExternalESSL3_helper(kDefaultAttribs);
+}
+
+TEST_P(ImageTestES3, Source2DTargetExternalESSL3_Colorspace)
+{
+    ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
+    ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
+    Source2DTargetExternalESSL3_helper(kColorspaceAttribs);
+}
+
+void ImageTest::Source2DTargetExternalESSL3_helper(const EGLint *attribs)
+{
     EGLWindow *window = getEGLWindow();
     ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() ||
                        !hasExternalESSL3Ext());
@@ -1175,7 +1270,7 @@
     // Create the Image
     GLuint source;
     EGLImageKHR image;
-    createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data, &source, &image);
+    createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, attribs, data, &source, &image);
 
     // Create the target
     GLuint target;
@@ -1192,6 +1287,18 @@
 
 TEST_P(ImageTest, SourceCubeTarget2D)
 {
+    SourceCubeTarget2D_helper(kDefaultAttribs);
+}
+
+TEST_P(ImageTest, SourceCubeTarget2D_Colorspace)
+{
+    ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
+    ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
+    SourceCubeTarget2D_helper(kColorspaceAttribs);
+}
+
+void ImageTest::SourceCubeTarget2D_helper(const EGLint *attribs)
+{
     EGLWindow *window = getEGLWindow();
     ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !hasCubemapExt());
 
@@ -1206,8 +1313,8 @@
         GLuint source;
         EGLImageKHR image;
         createEGLImageCubemapTextureSource(
-            1, 1, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<uint8_t *>(data), sizeof(GLubyte) * 4,
-            EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR + faceIdx, &source, &image);
+            1, 1, GL_RGBA, GL_UNSIGNED_BYTE, attribs, reinterpret_cast<uint8_t *>(data),
+            sizeof(GLubyte) * 4, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR + faceIdx, &source, &image);
 
         // Create the target
         GLuint target;
@@ -1225,6 +1332,18 @@
 
 TEST_P(ImageTest, SourceCubeTargetRenderbuffer)
 {
+    SourceCubeTargetRenderbuffer_helper(kDefaultAttribs);
+}
+
+TEST_P(ImageTest, SourceCubeTargetRenderbuffer_Colorspace)
+{
+    ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
+    ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
+    SourceCubeTargetRenderbuffer_helper(kColorspaceAttribs);
+}
+
+void ImageTest::SourceCubeTargetRenderbuffer_helper(const EGLint *attribs)
+{
     EGLWindow *window = getEGLWindow();
     ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !hasCubemapExt());
 
@@ -1242,8 +1361,8 @@
         GLuint source;
         EGLImageKHR image;
         createEGLImageCubemapTextureSource(
-            1, 1, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<uint8_t *>(data), sizeof(GLubyte) * 4,
-            EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR + faceIdx, &source, &image);
+            1, 1, GL_RGBA, GL_UNSIGNED_BYTE, attribs, reinterpret_cast<uint8_t *>(data),
+            sizeof(GLubyte) * 4, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR + faceIdx, &source, &image);
 
         // Create the target
         GLuint target;
@@ -1262,6 +1381,18 @@
 // Test cubemap -> external texture EGL images.
 TEST_P(ImageTest, SourceCubeTargetExternal)
 {
+    SourceCubeTargetExternal_helper(kDefaultAttribs);
+}
+
+TEST_P(ImageTest, SourceCubeTargetExternal_Colorspace)
+{
+    ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
+    ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
+    SourceCubeTargetExternal_helper(kColorspaceAttribs);
+}
+
+void ImageTest::SourceCubeTargetExternal_helper(const EGLint *attribs)
+{
     EGLWindow *window = getEGLWindow();
     ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !hasCubemapExt() || !hasExternalExt());
 
@@ -1279,8 +1410,8 @@
         GLuint source;
         EGLImageKHR image;
         createEGLImageCubemapTextureSource(
-            1, 1, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<uint8_t *>(data), sizeof(GLubyte) * 4,
-            EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR + faceIdx, &source, &image);
+            1, 1, GL_RGBA, GL_UNSIGNED_BYTE, attribs, reinterpret_cast<uint8_t *>(data),
+            sizeof(GLubyte) * 4, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR + faceIdx, &source, &image);
 
         // Create the target
         GLuint target;
@@ -1299,6 +1430,18 @@
 // Test cubemap -> external texture EGL images using ESSL3 shaders.
 TEST_P(ImageTestES3, SourceCubeTargetExternalESSL3)
 {
+    SourceCubeTargetExternalESSL3_helper(kDefaultAttribs);
+}
+
+TEST_P(ImageTestES3, SourceCubeTargetExternalESSL3_Colorspace)
+{
+    ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
+    ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
+    SourceCubeTargetExternalESSL3_helper(kColorspaceAttribs);
+}
+
+void ImageTest::SourceCubeTargetExternalESSL3_helper(const EGLint *attribs)
+{
     EGLWindow *window = getEGLWindow();
     ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasExternalESSL3Ext() || !hasBaseExt() || !hasCubemapExt());
 
@@ -1313,8 +1456,8 @@
         GLuint source;
         EGLImageKHR image;
         createEGLImageCubemapTextureSource(
-            1, 1, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<uint8_t *>(data), sizeof(GLubyte) * 4,
-            EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR + faceIdx, &source, &image);
+            1, 1, GL_RGBA, GL_UNSIGNED_BYTE, attribs, reinterpret_cast<uint8_t *>(data),
+            sizeof(GLubyte) * 4, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR + faceIdx, &source, &image);
 
         // Create the target
         GLuint target;
@@ -1332,6 +1475,18 @@
 
 TEST_P(ImageTest, Source3DTargetTexture)
 {
+    Source3DTargetTexture_helper(false);
+}
+
+TEST_P(ImageTest, Source3DTargetTexture_Colorspace)
+{
+    ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
+    ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
+    Source3DTargetTexture_helper(true);
+}
+
+void ImageTest::Source3DTargetTexture_helper(const bool withColorspace)
+{
     EGLWindow *window = getEGLWindow();
     ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has3DTextureExt());
 
@@ -1347,7 +1502,8 @@
         // Create the Image
         GLuint source;
         EGLImageKHR image;
-        createEGLImage3DTextureSource(1, 1, depth, GL_RGBA, GL_UNSIGNED_BYTE, data, layer, &source,
+        createEGLImage3DTextureSource(1, 1, depth, GL_RGBA, GL_UNSIGNED_BYTE,
+                                      get3DAttributes(withColorspace, layer), data, &source,
                                       &image);
 
         // Create the target
@@ -1366,8 +1522,21 @@
 
 TEST_P(ImageTest, Source3DTargetRenderbuffer)
 {
-    // Qualcom drivers appear to always bind the 0 layer of the source 3D texture when the target is
-    // a renderbuffer. They work correctly when the target is a 2D texture. http://anglebug.com/2745
+    Source3DTargetRenderbuffer_helper(false);
+}
+
+TEST_P(ImageTest, Source3DTargetRenderbuffer_Colorspace)
+{
+    ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
+    ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
+    Source3DTargetRenderbuffer_helper(true);
+}
+
+void ImageTest::Source3DTargetRenderbuffer_helper(const bool withColorspace)
+{
+    // Qualcom drivers appear to always bind the 0 layer of the source 3D texture when the
+    // target is a renderbuffer. They work correctly when the target is a 2D texture.
+    // http://anglebug.com/2745
     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
 
     EGLWindow *window = getEGLWindow();
@@ -1385,7 +1554,9 @@
         // Create the Image
         GLuint source;
         EGLImageKHR image;
-        createEGLImage3DTextureSource(1, 1, depth, GL_RGBA, GL_UNSIGNED_BYTE, data, layer, &source,
+
+        createEGLImage3DTextureSource(1, 1, depth, GL_RGBA, GL_UNSIGNED_BYTE,
+                                      get3DAttributes(withColorspace, layer), data, &source,
                                       &image);
 
         // Create the target
@@ -1405,6 +1576,18 @@
 // Test 3D -> external texture EGL images.
 TEST_P(ImageTest, Source3DTargetExternal)
 {
+    Source3DTargetExternal_helper(false);
+}
+
+TEST_P(ImageTest, Source3DTargetExternal_Colorspace)
+{
+    ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
+    ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
+    Source3DTargetExternal_helper(true);
+}
+
+void ImageTest::Source3DTargetExternal_helper(const bool withColorspace)
+{
     EGLWindow *window = getEGLWindow();
     ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasExternalExt() || !hasBaseExt() || !has3DTextureExt());
 
@@ -1423,7 +1606,8 @@
         // Create the Image
         GLuint source;
         EGLImageKHR image;
-        createEGLImage3DTextureSource(1, 1, depth, GL_RGBA, GL_UNSIGNED_BYTE, data, layer, &source,
+        createEGLImage3DTextureSource(1, 1, depth, GL_RGBA, GL_UNSIGNED_BYTE,
+                                      get3DAttributes(withColorspace, layer), data, &source,
                                       &image);
 
         // Create the target
@@ -1443,6 +1627,18 @@
 // Test 3D -> external texture EGL images using ESSL3 shaders.
 TEST_P(ImageTestES3, Source3DTargetExternalESSL3)
 {
+    Source3DTargetExternalESSL3_helper(false);
+}
+
+TEST_P(ImageTestES3, Source3DTargetExternalESSL3_Colorspace)
+{
+    ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
+    ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
+    Source3DTargetExternalESSL3_helper(true);
+}
+
+void ImageTest::Source3DTargetExternalESSL3_helper(const bool withColorspace)
+{
     EGLWindow *window = getEGLWindow();
     ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasExternalESSL3Ext() || !hasBaseExt() ||
                        !has3DTextureExt());
@@ -1459,7 +1655,9 @@
         // Create the Image
         GLuint source;
         EGLImageKHR image;
-        createEGLImage3DTextureSource(1, 1, depth, GL_RGBA, GL_UNSIGNED_BYTE, data, layer, &source,
+
+        createEGLImage3DTextureSource(1, 1, depth, GL_RGBA, GL_UNSIGNED_BYTE,
+                                      get3DAttributes(withColorspace, layer), data, &source,
                                       &image);
 
         // Create the target
@@ -1478,6 +1676,17 @@
 
 TEST_P(ImageTest, SourceRenderbufferTargetTexture)
 {
+    SourceRenderbufferTargetTexture_helper(kDefaultAttribs);
+}
+
+TEST_P(ImageTest, SourceRenderbufferTargetTexture_Colorspace)
+{
+    ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
+    SourceRenderbufferTargetTexture_helper(kColorspaceAttribs);
+}
+
+void ImageTest::SourceRenderbufferTargetTexture_helper(const EGLint *attribs)
+{
     EGLWindow *window = getEGLWindow();
     ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !hasRenderbufferExt());
 
@@ -1486,7 +1695,7 @@
     // Create the Image
     GLuint source;
     EGLImageKHR image;
-    createEGLImageRenderbufferSource(1, 1, GL_RGBA8_OES, data, &source, &image);
+    createEGLImageRenderbufferSource(1, 1, GL_RGBA8_OES, attribs, data, &source, &image);
 
     // Create the target
     GLuint target;
@@ -1504,6 +1713,17 @@
 // Test renderbuffer -> external texture EGL images.
 TEST_P(ImageTest, SourceRenderbufferTargetTextureExternal)
 {
+    SourceRenderbufferTargetTextureExternal_helper(kDefaultAttribs);
+}
+
+TEST_P(ImageTest, SourceRenderbufferTargetTextureExternal_Colorspace)
+{
+    ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
+    SourceRenderbufferTargetTextureExternal_helper(kColorspaceAttribs);
+}
+
+void ImageTest::SourceRenderbufferTargetTextureExternal_helper(const EGLint *attribs)
+{
     EGLWindow *window = getEGLWindow();
     ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasExternalExt() || !hasBaseExt() || !hasRenderbufferExt());
 
@@ -1515,7 +1735,7 @@
     // Create the Image
     GLuint source;
     EGLImageKHR image;
-    createEGLImageRenderbufferSource(1, 1, GL_RGBA8_OES, data, &source, &image);
+    createEGLImageRenderbufferSource(1, 1, GL_RGBA8_OES, attribs, data, &source, &image);
 
     // Create the target
     GLuint target;
@@ -1533,6 +1753,17 @@
 // Test renderbuffer -> external texture EGL images using ESSL3 shaders.
 TEST_P(ImageTestES3, SourceRenderbufferTargetTextureExternalESSL3)
 {
+    SourceRenderbufferTargetTextureExternalESSL3_helper(kDefaultAttribs);
+}
+
+TEST_P(ImageTestES3, SourceRenderbufferTargetTextureExternalESSL3_Colorspace)
+{
+    ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
+    SourceRenderbufferTargetTextureExternalESSL3_helper(kColorspaceAttribs);
+}
+
+void ImageTest::SourceRenderbufferTargetTextureExternalESSL3_helper(const EGLint *attribs)
+{
     EGLWindow *window = getEGLWindow();
     ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasExternalESSL3Ext() || !hasBaseExt() ||
                        !hasRenderbufferExt());
@@ -1542,7 +1773,7 @@
     // Create the Image
     GLuint source;
     EGLImageKHR image;
-    createEGLImageRenderbufferSource(1, 1, GL_RGBA8_OES, data, &source, &image);
+    createEGLImageRenderbufferSource(1, 1, GL_RGBA8_OES, attribs, data, &source, &image);
 
     // Create the target
     GLuint target;
@@ -1559,6 +1790,18 @@
 
 TEST_P(ImageTest, SourceRenderbufferTargetRenderbuffer)
 {
+    SourceRenderbufferTargetRenderbuffer_helper(kDefaultAttribs);
+}
+
+TEST_P(ImageTest, SourceRenderbufferTargetRenderbuffer_Colorspace)
+{
+    ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
+    ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
+    SourceRenderbufferTargetRenderbuffer_helper(kColorspaceAttribs);
+}
+
+void ImageTest::SourceRenderbufferTargetRenderbuffer_helper(const EGLint *attribs)
+{
     EGLWindow *window = getEGLWindow();
     ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !hasRenderbufferExt());
 
@@ -1567,7 +1810,7 @@
     // Create the Image
     GLuint source;
     EGLImageKHR image;
-    createEGLImageRenderbufferSource(1, 1, GL_RGBA8_OES, data, &source, &image);
+    createEGLImageRenderbufferSource(1, 1, GL_RGBA8_OES, attribs, data, &source, &image);
 
     // Create the target
     GLuint target;
@@ -1596,7 +1839,8 @@
     // Create the Image
     GLuint source;
     EGLImageKHR image;
-    createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, originalData, &source, &image);
+    createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs, originalData,
+                                  &source, &image);
 
     // Create multiple targets
     GLuint targetTexture;
@@ -1762,7 +2006,8 @@
     // Create the Image
     GLuint source;
     EGLImageKHR image;
-    createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, originalData, &source, &image);
+    createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs, originalData,
+                                  &source, &image);
 
     // Create the target
     GLuint target;
@@ -1797,7 +2042,8 @@
     // Create the Image
     GLuint source;
     EGLImageKHR image;
-    createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, originalData, &source, &image);
+    createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs, originalData,
+                                  &source, &image);
 
     // Create the target
     GLuint target;
@@ -1835,7 +2081,8 @@
     // Create the Image
     GLuint source;
     EGLImageKHR image;
-    createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, originalData, &source, &image);
+    createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs, originalData,
+                                  &source, &image);
 
     // Create the target
     GLuint target;
@@ -1894,7 +2141,8 @@
     // Create the Image
     GLuint source;
     EGLImageKHR image;
-    createEGLImage2DTextureSource(2, 2, GL_RGBA, GL_UNSIGNED_BYTE, originalData, &source, &image);
+    createEGLImage2DTextureSource(2, 2, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs, originalData,
+                                  &source, &image);
 
     // Create the target
     GLuint target;
@@ -1939,7 +2187,8 @@
     // Create the Image
     GLuint source;
     EGLImageKHR image;
-    createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, originalData, &source, &image);
+    createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs, originalData,
+                                  &source, &image);
 
     // Create multiple targets
     GLuint targetTexture;
@@ -1982,4 +2231,4 @@
 // tests should be run against.
 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(ImageTest);
 ANGLE_INSTANTIATE_TEST_ES3(ImageTestES3);
-}  // namespace angle
+}  // namespace angle
\ No newline at end of file
diff --git a/src/tests/gl_tests/MemoryObjectTest.cpp b/src/tests/gl_tests/MemoryObjectTest.cpp
index 2eec218..6e8d019 100644
--- a/src/tests/gl_tests/MemoryObjectTest.cpp
+++ b/src/tests/gl_tests/MemoryObjectTest.cpp
@@ -64,6 +64,42 @@
     EXPECT_GL_NO_ERROR();
 }
 
+// Test memory object queries
+TEST_P(MemoryObjectTest, MemoryObjectQueries)
+{
+    ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object"));
+
+    GLMemoryObject memoryObject;
+
+    // Validate that the initial state of GL_DEDICATED_MEMORY_OBJECT_EXT is GL_FALSE
+    {
+        GLint dedicatedMemory = 0;
+        glGetMemoryObjectParameterivEXT(memoryObject, GL_DEDICATED_MEMORY_OBJECT_EXT,
+                                        &dedicatedMemory);
+        EXPECT_GL_NO_ERROR();
+        EXPECT_GL_FALSE(dedicatedMemory);
+    }
+
+    // Change GL_DEDICATED_MEMORY_OBJECT_EXT to GL_TRUE
+    {
+        GLint dedicatedMemory = GL_TRUE;
+        glMemoryObjectParameterivEXT(memoryObject, GL_DEDICATED_MEMORY_OBJECT_EXT,
+                                     &dedicatedMemory);
+        EXPECT_GL_NO_ERROR();
+    }
+
+    // Confirm that GL_DEDICATED_MEMORY_OBJECT_EXT is now TRUE
+    {
+        GLint dedicatedMemory = 0;
+        glGetMemoryObjectParameterivEXT(memoryObject, GL_DEDICATED_MEMORY_OBJECT_EXT,
+                                        &dedicatedMemory);
+        EXPECT_GL_NO_ERROR();
+        EXPECT_GL_TRUE(dedicatedMemory);
+    }
+
+    EXPECT_GL_NO_ERROR();
+}
+
 // Use this to select which configurations (e.g. which renderer, which GLES major version) these
 // tests should be run against.
 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(MemoryObjectTest);
diff --git a/src/tests/gl_tests/MipmapTest.cpp b/src/tests/gl_tests/MipmapTest.cpp
index 3169801..e07b356 100644
--- a/src/tests/gl_tests/MipmapTest.cpp
+++ b/src/tests/gl_tests/MipmapTest.cpp
@@ -954,10 +954,6 @@
 // Then tests if the mipmaps are rendered correctly for all two layers.
 TEST_P(MipmapTestES3, MipmapsForTexture3D)
 {
-    // Currently block on swiftshader Blit3D support, tracked on
-    // https://issuetracker.google.com/issues/150155499
-    ANGLE_SKIP_TEST_IF(isVulkanSwiftshaderRenderer());
-
     int px = getWindowWidth() / 2;
     int py = getWindowHeight() / 2;
 
diff --git a/src/tests/gl_tests/MultisampleTest.cpp b/src/tests/gl_tests/MultisampleTest.cpp
index 6cd263c..b3649fd 100644
--- a/src/tests/gl_tests/MultisampleTest.cpp
+++ b/src/tests/gl_tests/MultisampleTest.cpp
@@ -53,7 +53,7 @@
         // Create a window, context and surface if multisampling is possible.
         mOSWindow = OSWindow::New();
         mOSWindow->initialize("MultisampleTest", kWindowSize, kWindowSize);
-        mOSWindow->setVisible(true);
+        setWindowVisible(mOSWindow, true);
 
         EGLint contextAttributes[] = {
             EGL_CONTEXT_MAJOR_VERSION_KHR,
diff --git a/src/tests/gl_tests/PathRenderingTest.cpp b/src/tests/gl_tests/PathRenderingTest.cpp
deleted file mode 100644
index b6a3793..0000000
--- a/src/tests/gl_tests/PathRenderingTest.cpp
+++ /dev/null
@@ -1,1994 +0,0 @@
-//
-// Copyright 2016 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// CHROMIUMPathRenderingTest
-//   Test CHROMIUM subset of NV_path_rendering
-//   This extension allows to render geometric paths as first class GL objects.
-
-#include "test_utils/ANGLETest.h"
-
-#include "common/angleutils.h"
-#include "util/shader_utils.h"
-
-#include <cmath>
-#include <cstddef>
-#include <cstring>
-#include <fstream>
-
-using namespace angle;
-
-namespace
-{
-
-bool CheckPixels(GLint x,
-                 GLint y,
-                 GLsizei width,
-                 GLsizei height,
-                 GLint tolerance,
-                 const angle::GLColor &color)
-{
-    for (GLint yy = 0; yy < height; ++yy)
-    {
-        for (GLint xx = 0; xx < width; ++xx)
-        {
-            const auto px = x + xx;
-            const auto py = y + yy;
-            EXPECT_PIXEL_NEAR(px, py, color.R, color.G, color.B, color.A, tolerance);
-        }
-    }
-
-    return true;
-}
-
-void ExpectEqualMatrix(const GLfloat *expected, const GLfloat *actual)
-{
-    for (size_t i = 0; i < 16; ++i)
-    {
-        EXPECT_EQ(expected[i], actual[i]);
-    }
-}
-
-void ExpectEqualMatrix(const GLfloat *expected, const GLint *actual)
-{
-    for (size_t i = 0; i < 16; ++i)
-    {
-        EXPECT_EQ(static_cast<GLint>(std::roundf(expected[i])), actual[i]);
-    }
-}
-
-const int kResolution = 300;
-
-class CHROMIUMPathRenderingTest : public ANGLETest
-{
-  protected:
-    CHROMIUMPathRenderingTest()
-    {
-        setWindowWidth(kResolution);
-        setWindowHeight(kResolution);
-        setConfigRedBits(8);
-        setConfigGreenBits(8);
-        setConfigBlueBits(8);
-        setConfigAlphaBits(8);
-        setConfigDepthBits(24);
-        setConfigStencilBits(8);
-    }
-
-    bool isApplicable() const { return IsGLExtensionEnabled("GL_CHROMIUM_path_rendering"); }
-
-    void tryAllDrawFunctions(GLuint path, GLenum err)
-    {
-        glStencilFillPathCHROMIUM(path, GL_COUNT_UP_CHROMIUM, 0x7F);
-        EXPECT_GL_ERROR(err);
-
-        glStencilFillPathCHROMIUM(path, GL_COUNT_DOWN_CHROMIUM, 0x7F);
-        EXPECT_GL_ERROR(err);
-
-        glStencilStrokePathCHROMIUM(path, 0x80, 0x80);
-        EXPECT_GL_ERROR(err);
-
-        glCoverFillPathCHROMIUM(path, GL_BOUNDING_BOX_CHROMIUM);
-        EXPECT_GL_ERROR(err);
-
-        glCoverStrokePathCHROMIUM(path, GL_BOUNDING_BOX_CHROMIUM);
-        EXPECT_GL_ERROR(err);
-
-        glStencilThenCoverStrokePathCHROMIUM(path, 0x80, 0x80, GL_BOUNDING_BOX_CHROMIUM);
-        EXPECT_GL_ERROR(err);
-
-        glStencilThenCoverFillPathCHROMIUM(path, GL_COUNT_UP_CHROMIUM, 0x7F,
-                                           GL_BOUNDING_BOX_CHROMIUM);
-        EXPECT_GL_ERROR(err);
-    }
-};
-
-// Test setting and getting of path rendering matrices.
-TEST_P(CHROMIUMPathRenderingTest, TestMatrix)
-{
-    if (!isApplicable())
-        return;
-
-    static const GLfloat kIdentityMatrix[16] = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
-                                                0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
-
-    static const GLfloat kSeqMatrix[16] = {0.5f,   -0.5f,  -0.1f,  -0.8f, 4.4f,   5.5f,
-                                           6.6f,   7.7f,   8.8f,   9.9f,  10.11f, 11.22f,
-                                           12.33f, 13.44f, 14.55f, 15.66f};
-
-    static const GLenum kMatrixModes[] = {GL_PATH_MODELVIEW_CHROMIUM, GL_PATH_PROJECTION_CHROMIUM};
-
-    static const GLenum kGetMatrixModes[] = {GL_PATH_MODELVIEW_MATRIX_CHROMIUM,
-                                             GL_PATH_PROJECTION_MATRIX_CHROMIUM};
-
-    for (size_t i = 0; i < 2; ++i)
-    {
-        GLfloat mf[16];
-        GLint mi[16];
-        std::memset(mf, 0, sizeof(mf));
-        std::memset(mi, 0, sizeof(mi));
-        glGetFloatv(kGetMatrixModes[i], mf);
-        glGetIntegerv(kGetMatrixModes[i], mi);
-        ExpectEqualMatrix(kIdentityMatrix, mf);
-        ExpectEqualMatrix(kIdentityMatrix, mi);
-
-        glMatrixLoadfCHROMIUM(kMatrixModes[i], kSeqMatrix);
-        std::memset(mf, 0, sizeof(mf));
-        std::memset(mi, 0, sizeof(mi));
-        glGetFloatv(kGetMatrixModes[i], mf);
-        glGetIntegerv(kGetMatrixModes[i], mi);
-        ExpectEqualMatrix(kSeqMatrix, mf);
-        ExpectEqualMatrix(kSeqMatrix, mi);
-
-        glMatrixLoadIdentityCHROMIUM(kMatrixModes[i]);
-        std::memset(mf, 0, sizeof(mf));
-        std::memset(mi, 0, sizeof(mi));
-        glGetFloatv(kGetMatrixModes[i], mf);
-        glGetIntegerv(kGetMatrixModes[i], mi);
-        ExpectEqualMatrix(kIdentityMatrix, mf);
-        ExpectEqualMatrix(kIdentityMatrix, mi);
-
-        ASSERT_GL_NO_ERROR();
-    }
-}
-
-// Test that trying to set incorrect matrix target results
-// in a GL error.
-TEST_P(CHROMIUMPathRenderingTest, TestMatrixErrors)
-{
-    if (!isApplicable())
-        return;
-
-    GLfloat mf[16];
-    std::memset(mf, 0, sizeof(mf));
-
-    glMatrixLoadfCHROMIUM(GL_PATH_MODELVIEW_CHROMIUM, mf);
-    ASSERT_GL_NO_ERROR();
-
-    glMatrixLoadIdentityCHROMIUM(GL_PATH_PROJECTION_CHROMIUM);
-    ASSERT_GL_NO_ERROR();
-
-    // Test that invalid matrix targets fail.
-    glMatrixLoadfCHROMIUM(GL_PATH_MODELVIEW_CHROMIUM - 1, mf);
-    EXPECT_GL_ERROR(GL_INVALID_ENUM);
-
-    // Test that invalid matrix targets fail.
-    glMatrixLoadIdentityCHROMIUM(GL_PATH_PROJECTION_CHROMIUM + 1);
-    EXPECT_GL_ERROR(GL_INVALID_ENUM);
-}
-
-// Test basic path create and delete.
-TEST_P(CHROMIUMPathRenderingTest, TestGenDelete)
-{
-    if (!isApplicable())
-        return;
-
-    // This is unspecified in NV_path_rendering.
-    EXPECT_EQ(0u, glGenPathsCHROMIUM(0));
-    EXPECT_GL_ERROR(GL_INVALID_VALUE);
-
-    GLuint path = glGenPathsCHROMIUM(1);
-    EXPECT_NE(0u, path);
-    glDeletePathsCHROMIUM(path, 1);
-    ASSERT_GL_NO_ERROR();
-
-    GLuint first_path = glGenPathsCHROMIUM(5);
-    EXPECT_NE(0u, first_path);
-    glDeletePathsCHROMIUM(first_path, 5);
-    ASSERT_GL_NO_ERROR();
-
-    // Test deleting paths that are not actually allocated:
-    // "unused names in /paths/ are silently ignored".
-    first_path = glGenPathsCHROMIUM(5);
-    EXPECT_NE(0u, first_path);
-    glDeletePathsCHROMIUM(first_path, 6);
-    ASSERT_GL_NO_ERROR();
-
-    GLsizei big_range = 0xffff;
-    first_path        = glGenPathsCHROMIUM(big_range);
-    EXPECT_NE(0u, first_path);
-    glDeletePathsCHROMIUM(first_path, big_range);
-    ASSERT_GL_NO_ERROR();
-
-    // Test glIsPathCHROMIUM(). A path object is not considered a path untill
-    // it has actually been specified with a path data.
-
-    path = glGenPathsCHROMIUM(1);
-    ASSERT_TRUE(glIsPathCHROMIUM(path) == GL_FALSE);
-
-    // specify the data.
-    GLubyte commands[] = {GL_MOVE_TO_CHROMIUM, GL_CLOSE_PATH_CHROMIUM};
-    GLfloat coords[]   = {50.0f, 50.0f};
-    glPathCommandsCHROMIUM(path, 2, commands, 2, GL_FLOAT, coords);
-    ASSERT_TRUE(glIsPathCHROMIUM(path) == GL_TRUE);
-    glDeletePathsCHROMIUM(path, 1);
-    ASSERT_TRUE(glIsPathCHROMIUM(path) == GL_FALSE);
-}
-
-// Test incorrect path creation and deletion and expect GL errors.
-TEST_P(CHROMIUMPathRenderingTest, TestGenDeleteErrors)
-{
-    if (!isApplicable())
-        return;
-
-    // GenPaths / DeletePaths tests.
-    // std::numeric_limits<GLuint>::max() is wrong for GLsizei.
-    GLuint first_path = glGenPathsCHROMIUM(std::numeric_limits<GLuint>::max());
-    EXPECT_EQ(first_path, 0u);
-    EXPECT_GL_ERROR(GL_INVALID_VALUE);
-
-    first_path = glGenPathsCHROMIUM(-1);
-    EXPECT_EQ(0u, first_path);
-    EXPECT_GL_ERROR(GL_INVALID_VALUE);
-
-    glDeletePathsCHROMIUM(1, -5);
-    EXPECT_GL_ERROR(GL_INVALID_VALUE);
-
-    first_path = glGenPathsCHROMIUM(-1);
-    EXPECT_EQ(0u, first_path);
-    EXPECT_GL_ERROR(GL_INVALID_VALUE);
-}
-
-// Test setting and getting path parameters.
-TEST_P(CHROMIUMPathRenderingTest, TestPathParameter)
-{
-    if (!isApplicable())
-        return;
-
-    GLuint path = glGenPathsCHROMIUM(1);
-
-    // specify the data.
-    GLubyte commands[] = {GL_MOVE_TO_CHROMIUM, GL_CLOSE_PATH_CHROMIUM};
-    GLfloat coords[]   = {50.0f, 50.0f};
-    glPathCommandsCHROMIUM(path, 2, commands, 2, GL_FLOAT, coords);
-    ASSERT_GL_NO_ERROR();
-    EXPECT_GL_TRUE(glIsPathCHROMIUM(path));
-
-    static const GLenum kEndCaps[] = {GL_FLAT_CHROMIUM, GL_SQUARE_CHROMIUM, GL_ROUND_CHROMIUM};
-    for (std::size_t i = 0; i < 3; ++i)
-    {
-        GLint x;
-        glPathParameteriCHROMIUM(path, GL_PATH_END_CAPS_CHROMIUM, static_cast<GLenum>(kEndCaps[i]));
-        ASSERT_GL_NO_ERROR();
-        glGetPathParameterivCHROMIUM(path, GL_PATH_END_CAPS_CHROMIUM, &x);
-        ASSERT_GL_NO_ERROR();
-        EXPECT_EQ(kEndCaps[i], static_cast<GLenum>(x));
-
-        GLfloat f;
-        glPathParameterfCHROMIUM(path, GL_PATH_END_CAPS_CHROMIUM,
-                                 static_cast<GLfloat>(kEndCaps[(i + 1) % 3]));
-        glGetPathParameterfvCHROMIUM(path, GL_PATH_END_CAPS_CHROMIUM, &f);
-        ASSERT_GL_NO_ERROR();
-        EXPECT_EQ(kEndCaps[(i + 1) % 3], static_cast<GLenum>(f));
-    }
-
-    static const GLenum kJoinStyles[] = {GL_MITER_REVERT_CHROMIUM, GL_BEVEL_CHROMIUM,
-                                         GL_ROUND_CHROMIUM};
-    for (std::size_t i = 0; i < 3; ++i)
-    {
-        GLint x;
-        glPathParameteriCHROMIUM(path, GL_PATH_JOIN_STYLE_CHROMIUM,
-                                 static_cast<GLenum>(kJoinStyles[i]));
-        ASSERT_GL_NO_ERROR();
-        glGetPathParameterivCHROMIUM(path, GL_PATH_JOIN_STYLE_CHROMIUM, &x);
-        ASSERT_GL_NO_ERROR();
-        EXPECT_EQ(kJoinStyles[i], static_cast<GLenum>(x));
-
-        GLfloat f;
-        glPathParameterfCHROMIUM(path, GL_PATH_JOIN_STYLE_CHROMIUM,
-                                 static_cast<GLfloat>(kJoinStyles[(i + 1) % 3]));
-        ASSERT_GL_NO_ERROR();
-        glGetPathParameterfvCHROMIUM(path, GL_PATH_JOIN_STYLE_CHROMIUM, &f);
-        ASSERT_GL_NO_ERROR();
-        EXPECT_EQ(kJoinStyles[(i + 1) % 3], static_cast<GLenum>(f));
-    }
-
-    {
-        glPathParameterfCHROMIUM(path, GL_PATH_STROKE_WIDTH_CHROMIUM, 5.0f);
-        ASSERT_GL_NO_ERROR();
-
-        GLfloat f;
-        glGetPathParameterfvCHROMIUM(path, GL_PATH_STROKE_WIDTH_CHROMIUM, &f);
-        EXPECT_EQ(5.0f, f);
-    }
-
-    glDeletePathsCHROMIUM(path, 1);
-}
-
-// Test that setting incorrect path parameter generates GL error.
-TEST_P(CHROMIUMPathRenderingTest, TestPathParameterErrors)
-{
-    if (!isApplicable())
-        return;
-
-    GLuint path = glGenPathsCHROMIUM(1);
-
-    // PathParameter*: Wrong value for the pname should fail.
-    glPathParameteriCHROMIUM(path, GL_PATH_JOIN_STYLE_CHROMIUM, GL_FLAT_CHROMIUM);
-    EXPECT_GL_ERROR(GL_INVALID_ENUM);
-
-    glPathParameterfCHROMIUM(path, GL_PATH_END_CAPS_CHROMIUM, GL_MITER_REVERT_CHROMIUM);
-    EXPECT_GL_ERROR(GL_INVALID_ENUM);
-
-    // PathParameter*: Wrong floating-point value should fail.
-    glPathParameterfCHROMIUM(path, GL_PATH_STROKE_WIDTH_CHROMIUM, -0.1f);
-    EXPECT_GL_ERROR(GL_INVALID_VALUE);
-
-    // PathParameter*: Wrong pname should fail.
-    glPathParameteriCHROMIUM(path, GL_PATH_STROKE_WIDTH_CHROMIUM - 1, 5);
-    EXPECT_GL_ERROR(GL_INVALID_ENUM);
-
-    glDeletePathsCHROMIUM(path, 1);
-}
-
-// Test expected path object state.
-TEST_P(CHROMIUMPathRenderingTest, TestPathObjectState)
-{
-    if (!isApplicable())
-        return;
-
-    glViewport(0, 0, kResolution, kResolution);
-    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
-    glStencilMask(0xffffffff);
-    glClearStencil(0);
-    glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-    glPathStencilFuncCHROMIUM(GL_ALWAYS, 0, 0xFF);
-    glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
-    ASSERT_GL_NO_ERROR();
-
-    // Test that trying to draw non-existing paths does not produce errors or results.
-    GLuint non_existing_paths[] = {0, 55, 74744};
-    for (auto &p : non_existing_paths)
-    {
-        EXPECT_GL_FALSE(glIsPathCHROMIUM(p));
-        ASSERT_GL_NO_ERROR();
-        tryAllDrawFunctions(p, GL_NO_ERROR);
-    }
-
-    // Path name marked as used but without path object state causes
-    // a GL error upon any draw command.
-    GLuint path = glGenPathsCHROMIUM(1);
-    EXPECT_GL_FALSE(glIsPathCHROMIUM(path));
-    tryAllDrawFunctions(path, GL_INVALID_OPERATION);
-    glDeletePathsCHROMIUM(path, 1);
-
-    // Document a bit of an inconsistency: path name marked as used but without
-    // path object state causes a GL error upon any draw command (tested above).
-    // Path name that had path object state, but then was "cleared", still has a
-    // path object state, even though the state is empty.
-    path = glGenPathsCHROMIUM(1);
-    EXPECT_GL_FALSE(glIsPathCHROMIUM(path));
-
-    GLubyte commands[] = {GL_MOVE_TO_CHROMIUM, GL_CLOSE_PATH_CHROMIUM};
-    GLfloat coords[]   = {50.0f, 50.0f};
-    glPathCommandsCHROMIUM(path, 2, commands, 2, GL_FLOAT, coords);
-    EXPECT_GL_TRUE(glIsPathCHROMIUM(path));
-
-    glPathCommandsCHROMIUM(path, 0, nullptr, 0, GL_FLOAT, nullptr);
-    EXPECT_GL_TRUE(glIsPathCHROMIUM(path));  // The surprise.
-
-    tryAllDrawFunctions(path, GL_NO_ERROR);
-    glDeletePathsCHROMIUM(path, 1);
-
-    // Make sure nothing got drawn by the drawing commands that should not produce
-    // anything.
-    const angle::GLColor black = {0, 0, 0, 0};
-    EXPECT_TRUE(CheckPixels(0, 0, kResolution, kResolution, 0, black));
-}
-
-// Test that trying to use path object that doesn't exist generates
-// a GL error.
-TEST_P(CHROMIUMPathRenderingTest, TestUnnamedPathsErrors)
-{
-    if (!isApplicable())
-        return;
-
-    // Unnamed paths: Trying to create a path object with non-existing path name
-    // produces error.  (Not a error in real NV_path_rendering).
-    ASSERT_GL_NO_ERROR();
-    GLubyte commands[] = {GL_MOVE_TO_CHROMIUM, GL_CLOSE_PATH_CHROMIUM};
-    GLfloat coords[]   = {50.0f, 50.0f};
-    glPathCommandsCHROMIUM(555, 2, commands, 2, GL_FLOAT, coords);
-    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
-
-    // PathParameter*: Using non-existing path object produces error.
-    ASSERT_GL_NO_ERROR();
-    glPathParameterfCHROMIUM(555, GL_PATH_STROKE_WIDTH_CHROMIUM, 5.0f);
-    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
-
-    ASSERT_GL_NO_ERROR();
-    glPathParameteriCHROMIUM(555, GL_PATH_JOIN_STYLE_CHROMIUM, GL_ROUND_CHROMIUM);
-    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
-}
-
-// Test that setting incorrect path data generates a GL error.
-TEST_P(CHROMIUMPathRenderingTest, TestPathCommandsErrors)
-{
-    if (!isApplicable())
-        return;
-
-    static const GLenum kInvalidCoordType = GL_NONE;
-
-    GLuint path        = glGenPathsCHROMIUM(1);
-    GLubyte commands[] = {GL_MOVE_TO_CHROMIUM, GL_CLOSE_PATH_CHROMIUM};
-    GLfloat coords[]   = {50.0f, 50.0f};
-
-    glPathCommandsCHROMIUM(path, 2, commands, -4, GL_FLOAT, coords);
-    EXPECT_GL_ERROR(GL_INVALID_VALUE);
-
-    glPathCommandsCHROMIUM(path, -1, commands, 2, GL_FLOAT, coords);
-    EXPECT_GL_ERROR(GL_INVALID_VALUE);
-
-    glPathCommandsCHROMIUM(path, 2, commands, 2, kInvalidCoordType, coords);
-    EXPECT_GL_ERROR(GL_INVALID_ENUM);
-
-    // incorrect number of coordinates
-    glPathCommandsCHROMIUM(path, 2, commands, std::numeric_limits<GLsizei>::max(), GL_FLOAT,
-                           coords);
-    EXPECT_GL_ERROR(GL_INVALID_VALUE);
-
-    // This should fail due to cmd count + coord count * short size.
-    glPathCommandsCHROMIUM(path, 2, commands, std::numeric_limits<GLsizei>::max(), GL_SHORT,
-                           coords);
-    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
-
-    glDeletePathsCHROMIUM(path, 1);
-}
-
-// Test that trying to render a path with invalid arguments
-// generates a GL error.
-TEST_P(CHROMIUMPathRenderingTest, TestPathRenderingInvalidArgs)
-{
-    if (!isApplicable())
-        return;
-
-    GLuint path = glGenPathsCHROMIUM(1);
-    glPathCommandsCHROMIUM(path, 0, nullptr, 0, GL_FLOAT, nullptr);
-
-    // Verify that normal calls work.
-    glStencilFillPathCHROMIUM(path, GL_COUNT_UP_CHROMIUM, 0x7F);
-    ASSERT_GL_NO_ERROR();
-    glStencilThenCoverFillPathCHROMIUM(path, GL_COUNT_UP_CHROMIUM, 0x7F, GL_BOUNDING_BOX_CHROMIUM);
-    ASSERT_GL_NO_ERROR();
-
-    // Using invalid fill mode causes INVALID_ENUM.
-    glStencilFillPathCHROMIUM(path, GL_COUNT_UP_CHROMIUM - 1, 0x7F);
-    EXPECT_GL_ERROR(GL_INVALID_ENUM);
-    glStencilThenCoverFillPathCHROMIUM(path, GL_COUNT_UP_CHROMIUM - 1, 0x7F,
-                                       GL_BOUNDING_BOX_CHROMIUM);
-    EXPECT_GL_ERROR(GL_INVALID_ENUM);
-
-    // Using invalid cover mode causes INVALID_ENUM.
-    glCoverFillPathCHROMIUM(path, GL_CONVEX_HULL_CHROMIUM - 1);
-    EXPECT_EQ(static_cast<GLenum>(GL_INVALID_ENUM), glGetError());
-    glStencilThenCoverFillPathCHROMIUM(path, GL_COUNT_UP_CHROMIUM, 0x7F,
-                                       GL_BOUNDING_BOX_CHROMIUM + 1);
-    EXPECT_GL_ERROR(GL_INVALID_ENUM);
-
-    // Using mask+1 not being power of two causes INVALID_VALUE with up/down fill mode
-    glStencilFillPathCHROMIUM(path, GL_COUNT_UP_CHROMIUM, 0x40);
-    EXPECT_GL_ERROR(GL_INVALID_VALUE);
-
-    glStencilThenCoverFillPathCHROMIUM(path, GL_COUNT_DOWN_CHROMIUM, 12, GL_BOUNDING_BOX_CHROMIUM);
-    EXPECT_GL_ERROR(GL_INVALID_VALUE);
-
-    // check incorrect instance parameters.
-
-    // CoverFillPathInstanced
-    {
-        glCoverFillPathInstancedCHROMIUM(-1, GL_UNSIGNED_INT, &path, 0, GL_CONVEX_HULL_CHROMIUM,
-                                         GL_NONE, nullptr);
-        EXPECT_GL_ERROR(GL_INVALID_VALUE);
-
-        glCoverFillPathInstancedCHROMIUM(1, GL_FLOAT, &path, 0, GL_CONVEX_HULL_CHROMIUM, GL_NONE,
-                                         nullptr);
-        EXPECT_GL_ERROR(GL_INVALID_ENUM);
-
-        glCoverFillPathInstancedCHROMIUM(1, GL_UNSIGNED_INT, nullptr, 0, GL_CONVEX_HULL_CHROMIUM,
-                                         GL_NONE, nullptr);
-        EXPECT_GL_ERROR(GL_INVALID_VALUE);
-
-        glCoverFillPathInstancedCHROMIUM(1, GL_UNSIGNED_INT, &path, 0, GL_UNSIGNED_INT, GL_NONE,
-                                         nullptr);
-        EXPECT_GL_ERROR(GL_INVALID_ENUM);
-
-        glCoverFillPathInstancedCHROMIUM(1, GL_UNSIGNED_INT, &path, 0, GL_CONVEX_HULL_CHROMIUM,
-                                         GL_UNSIGNED_INT, nullptr);
-        EXPECT_GL_ERROR(GL_INVALID_ENUM);
-
-        glCoverFillPathInstancedCHROMIUM(1, GL_UNSIGNED_INT, &path, 0, GL_CONVEX_HULL_CHROMIUM,
-                                         GL_TRANSLATE_X_CHROMIUM, nullptr);
-        EXPECT_GL_ERROR(GL_INVALID_VALUE);
-    }
-
-    // CoverStrokePathInstanced
-    {
-        glCoverStrokePathInstancedCHROMIUM(-1, GL_UNSIGNED_INT, &path, 0, GL_CONVEX_HULL_CHROMIUM,
-                                           GL_NONE, nullptr);
-        EXPECT_GL_ERROR(GL_INVALID_VALUE);
-
-        glCoverStrokePathInstancedCHROMIUM(1, GL_FLOAT, &path, 0, GL_CONVEX_HULL_CHROMIUM, GL_NONE,
-                                           nullptr);
-        EXPECT_GL_ERROR(GL_INVALID_ENUM);
-
-        glCoverStrokePathInstancedCHROMIUM(1, GL_UNSIGNED_INT, nullptr, 0, GL_CONVEX_HULL_CHROMIUM,
-                                           GL_NONE, nullptr);
-        EXPECT_GL_ERROR(GL_INVALID_VALUE);
-
-        glCoverStrokePathInstancedCHROMIUM(1, GL_UNSIGNED_INT, &path, 0, GL_UNSIGNED_INT, GL_NONE,
-                                           nullptr);
-        EXPECT_GL_ERROR(GL_INVALID_ENUM);
-
-        glCoverStrokePathInstancedCHROMIUM(1, GL_UNSIGNED_INT, &path, 0, GL_CONVEX_HULL_CHROMIUM,
-                                           GL_UNSIGNED_INT, nullptr);
-        EXPECT_GL_ERROR(GL_INVALID_ENUM);
-
-        glCoverStrokePathInstancedCHROMIUM(1, GL_UNSIGNED_INT, &path, 0, GL_CONVEX_HULL_CHROMIUM,
-                                           GL_TRANSLATE_X_CHROMIUM, nullptr);
-        EXPECT_GL_ERROR(GL_INVALID_VALUE);
-    }
-
-    // StencilFillPathInstanced
-    {
-        glStencilFillPathInstancedCHROMIUM(-1, GL_UNSIGNED_INT, &path, 0, GL_COUNT_UP_CHROMIUM, 0x0,
-                                           GL_NONE, nullptr);
-        EXPECT_GL_ERROR(GL_INVALID_VALUE);
-
-        glStencilFillPathInstancedCHROMIUM(1, GL_FLOAT, &path, 0, GL_COUNT_UP_CHROMIUM, 0x0,
-                                           GL_NONE, nullptr);
-        EXPECT_GL_ERROR(GL_INVALID_ENUM);
-
-        glStencilFillPathInstancedCHROMIUM(1, GL_UNSIGNED_INT, nullptr, 0, GL_COUNT_UP_CHROMIUM,
-                                           0x0, GL_NONE, nullptr);
-        EXPECT_GL_ERROR(GL_INVALID_VALUE);
-
-        glStencilFillPathInstancedCHROMIUM(1, GL_UNSIGNED_INT, &path, 0, GL_UNSIGNED_INT, 0x0,
-                                           GL_NONE, nullptr);
-        EXPECT_GL_ERROR(GL_INVALID_ENUM);
-
-        glStencilFillPathInstancedCHROMIUM(1, GL_UNSIGNED_INT, &path, 0, GL_COUNT_UP_CHROMIUM, 0x2,
-                                           GL_NONE, nullptr);
-        EXPECT_GL_ERROR(GL_INVALID_VALUE);
-
-        glStencilFillPathInstancedCHROMIUM(1, GL_UNSIGNED_INT, &path, 0, GL_COUNT_UP_CHROMIUM, 0x0,
-                                           GL_UNSIGNED_INT, nullptr);
-        EXPECT_GL_ERROR(GL_INVALID_ENUM);
-
-        glStencilFillPathInstancedCHROMIUM(1, GL_UNSIGNED_INT, &path, 0, GL_COUNT_UP_CHROMIUM, 0x0,
-                                           GL_TRANSLATE_X_CHROMIUM, nullptr);
-        EXPECT_GL_ERROR(GL_INVALID_VALUE);
-    }
-
-    // StencilStrokePathInstanced
-    {
-        glStencilStrokePathInstancedCHROMIUM(-1, GL_UNSIGNED_INT, &path, 0, 0x00, 0x00, GL_NONE,
-                                             nullptr);
-        EXPECT_GL_ERROR(GL_INVALID_VALUE);
-
-        glStencilStrokePathInstancedCHROMIUM(1, GL_FLOAT, &path, 0, 0x00, 0x00, GL_NONE, nullptr);
-        EXPECT_GL_ERROR(GL_INVALID_ENUM);
-
-        glStencilStrokePathInstancedCHROMIUM(1, GL_UNSIGNED_INT, nullptr, 0, 0x00, 0x00, GL_NONE,
-                                             nullptr);
-        EXPECT_GL_ERROR(GL_INVALID_VALUE);
-
-        glStencilStrokePathInstancedCHROMIUM(1, GL_UNSIGNED_INT, &path, 0, 0x00, 0x00,
-                                             GL_UNSIGNED_INT, nullptr);
-        EXPECT_GL_ERROR(GL_INVALID_ENUM);
-
-        glStencilStrokePathInstancedCHROMIUM(1, GL_UNSIGNED_INT, &path, 0, 0x00, 0x00,
-                                             GL_TRANSLATE_X_CHROMIUM, nullptr);
-        EXPECT_GL_ERROR(GL_INVALID_VALUE);
-    }
-
-    // StencilThenCoverFillPathInstanced
-    {
-        glStencilThenCoverFillPathInstancedCHROMIUM(-1, GL_UNSIGNED_INT, &path, 0,
-                                                    GL_COUNT_UP_CHROMIUM, 0, GL_COUNT_UP_CHROMIUM,
-                                                    GL_NONE, nullptr);
-        EXPECT_GL_ERROR(GL_INVALID_VALUE);
-
-        glStencilThenCoverFillPathInstancedCHROMIUM(1, GL_FLOAT, &path, 0, GL_CONVEX_HULL_CHROMIUM,
-                                                    0, GL_COUNT_UP_CHROMIUM, GL_NONE, nullptr);
-        EXPECT_GL_ERROR(GL_INVALID_ENUM);
-
-        glStencilThenCoverFillPathInstancedCHROMIUM(1, GL_UNSIGNED_INT, nullptr, 0,
-                                                    GL_CONVEX_HULL_CHROMIUM, 0,
-                                                    GL_COUNT_UP_CHROMIUM, GL_NONE, nullptr);
-        EXPECT_GL_ERROR(GL_INVALID_VALUE);
-
-        glStencilThenCoverFillPathInstancedCHROMIUM(1, GL_UNSIGNED_INT, &path, 0, GL_UNSIGNED_INT,
-                                                    0, GL_COUNT_UP_CHROMIUM, GL_NONE, nullptr);
-        EXPECT_GL_ERROR(GL_INVALID_ENUM);
-
-        glStencilThenCoverFillPathInstancedCHROMIUM(1, GL_UNSIGNED_INT, &path, 0,
-                                                    GL_CONVEX_HULL_CHROMIUM, 0, GL_UNSIGNED_INT,
-                                                    GL_NONE, nullptr);
-        EXPECT_GL_ERROR(GL_INVALID_ENUM);
-
-        glStencilThenCoverFillPathInstancedCHROMIUM(1, GL_UNSIGNED_INT, &path, 0,
-                                                    GL_CONVEX_HULL_CHROMIUM, 0,
-                                                    GL_COUNT_UP_CHROMIUM, GL_FLOAT, nullptr);
-        EXPECT_GL_ERROR(GL_INVALID_ENUM);
-
-        glStencilThenCoverFillPathInstancedCHROMIUM(
-            1, GL_UNSIGNED_INT, &path, 0, GL_CONVEX_HULL_CHROMIUM, 0, GL_COUNT_UP_CHROMIUM,
-            GL_TRANSLATE_X_CHROMIUM, nullptr);
-        EXPECT_GL_ERROR(GL_INVALID_VALUE);
-    }
-
-    // StencilThenCoverStrokePathInstanced
-    {
-        glStencilThenCoverStrokePathInstancedCHROMIUM(-1, GL_UNSIGNED_INT, &path, 0, 0x0, 0x0,
-                                                      GL_CONVEX_HULL_CHROMIUM, GL_NONE, nullptr);
-        EXPECT_GL_ERROR(GL_INVALID_VALUE);
-
-        glStencilThenCoverStrokePathInstancedCHROMIUM(1, GL_FLOAT, &path, 0, 0x0, 0x0,
-                                                      GL_CONVEX_HULL_CHROMIUM, GL_NONE, nullptr);
-        EXPECT_GL_ERROR(GL_INVALID_ENUM);
-
-        glStencilThenCoverStrokePathInstancedCHROMIUM(1, GL_UNSIGNED_INT, nullptr, 0, 0x0, 0x0,
-                                                      GL_CONVEX_HULL_CHROMIUM, GL_NONE, nullptr);
-        EXPECT_GL_ERROR(GL_INVALID_VALUE);
-
-        glStencilThenCoverStrokePathInstancedCHROMIUM(1, GL_UNSIGNED_INT, &path, 0, 0x0, 0x0,
-                                                      GL_FLOAT, GL_NONE, nullptr);
-        EXPECT_GL_ERROR(GL_INVALID_ENUM);
-
-        glStencilThenCoverStrokePathInstancedCHROMIUM(1, GL_UNSIGNED_INT, &path, 0, 0x0, 0x0,
-                                                      GL_CONVEX_HULL_CHROMIUM, GL_FLOAT, nullptr);
-        EXPECT_GL_ERROR(GL_INVALID_ENUM);
-
-        glStencilThenCoverStrokePathInstancedCHROMIUM(1, GL_UNSIGNED_INT, &path, 0, 0x0, 0x0,
-                                                      GL_CONVEX_HULL_CHROMIUM,
-                                                      GL_TRANSLATE_X_CHROMIUM, nullptr);
-        EXPECT_GL_ERROR(GL_INVALID_VALUE);
-    }
-
-    glDeletePathsCHROMIUM(path, 1);
-}
-
-const GLfloat kProjectionMatrix[16] = {2.0f / kResolution,
-                                       0.0f,
-                                       0.0f,
-                                       0.0f,
-                                       0.0f,
-                                       2.0f / kResolution,
-                                       0.0f,
-                                       0.0f,
-                                       0.0f,
-                                       0.0f,
-                                       -1.0f,
-                                       0.0f,
-                                       -1.0f,
-                                       -1.0f,
-                                       0.0f,
-                                       1.0f};
-
-class CHROMIUMPathRenderingDrawTest : public ANGLETest
-{
-  protected:
-    CHROMIUMPathRenderingDrawTest()
-    {
-        setWindowWidth(kResolution);
-        setWindowHeight(kResolution);
-        setConfigRedBits(8);
-        setConfigGreenBits(8);
-        setConfigBlueBits(8);
-        setConfigAlphaBits(8);
-        setConfigDepthBits(24);
-        setConfigStencilBits(8);
-    }
-
-    bool isApplicable() const { return IsGLExtensionEnabled("GL_CHROMIUM_path_rendering"); }
-
-    void setupStateForTestPattern()
-    {
-        glViewport(0, 0, kResolution, kResolution);
-        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
-        glStencilMask(0xffffffff);
-        glClearStencil(0);
-        glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-        glEnable(GL_STENCIL_TEST);
-
-        constexpr char kVertexShaderSource[] =
-            "void main() {\n"
-            "  gl_Position = vec4(1.0); \n"
-            "}";
-
-        constexpr char kFragmentShaderSource[] =
-            "precision mediump float;\n"
-            "uniform vec4 color;\n"
-            "void main() {\n"
-            "  gl_FragColor = color;\n"
-            "}";
-
-        GLuint program = CompileProgram(kVertexShaderSource, kFragmentShaderSource);
-        glUseProgram(program);
-        mColorLoc = glGetUniformLocation(program, "color");
-        glDeleteProgram(program);
-
-        // Set up orthogonal projection with near/far plane distance of 2.
-        glMatrixLoadfCHROMIUM(GL_PATH_PROJECTION_CHROMIUM, kProjectionMatrix);
-        glMatrixLoadIdentityCHROMIUM(GL_PATH_MODELVIEW_CHROMIUM);
-
-        ASSERT_GL_NO_ERROR();
-    }
-
-    void setupPathStateForTestPattern(GLuint path)
-    {
-        static const GLubyte kCommands[] = {GL_MOVE_TO_CHROMIUM, GL_LINE_TO_CHROMIUM,
-                                            GL_QUADRATIC_CURVE_TO_CHROMIUM,
-                                            GL_CUBIC_CURVE_TO_CHROMIUM, GL_CLOSE_PATH_CHROMIUM};
-
-        static const GLfloat kCoords[] = {50.0f, 50.0f, 75.0f, 75.0f, 100.0f, 62.5f, 50.0f,
-                                          25.5f, 0.0f,  62.5f, 50.0f, 50.0f,  25.0f, 75.0f};
-
-        glPathCommandsCHROMIUM(path, 5, kCommands, 14, GL_FLOAT, kCoords);
-        glPathParameterfCHROMIUM(path, GL_PATH_STROKE_WIDTH_CHROMIUM, 5.0f);
-        glPathParameterfCHROMIUM(path, GL_PATH_MITER_LIMIT_CHROMIUM, 1.0f);
-        glPathParameterfCHROMIUM(path, GL_PATH_STROKE_BOUND_CHROMIUM, .02f);
-        glPathParameteriCHROMIUM(path, GL_PATH_JOIN_STYLE_CHROMIUM, GL_ROUND_CHROMIUM);
-        glPathParameteriCHROMIUM(path, GL_PATH_END_CAPS_CHROMIUM, GL_SQUARE_CHROMIUM);
-        ASSERT_GL_NO_ERROR();
-    }
-
-    void verifyTestPatternFill(GLfloat flx, GLfloat fly)
-    {
-        static const GLint kFillCoords[]  = {55, 54, 50, 28, 66, 63};
-        static const angle::GLColor kBlue = {0, 0, 255, 255};
-
-        GLint x = static_cast<GLint>(flx);
-        GLint y = static_cast<GLint>(fly);
-
-        for (size_t i = 0; i < 6; i += 2)
-        {
-            GLint fx = kFillCoords[i];
-            GLint fy = kFillCoords[i + 1];
-            EXPECT_TRUE(CheckPixels(x + fx, y + fy, 1, 1, 0, kBlue));
-        }
-    }
-    void verifyTestPatternBg(GLfloat fx, GLfloat fy)
-    {
-        static const GLint kBackgroundCoords[]     = {80, 80, 20, 20, 90, 1};
-        static const angle::GLColor kExpectedColor = {0, 0, 0, 0};
-
-        GLint x = static_cast<GLint>(fx);
-        GLint y = static_cast<GLint>(fy);
-
-        for (size_t i = 0; i < 6; i += 2)
-        {
-            GLint bx = kBackgroundCoords[i];
-            GLint by = kBackgroundCoords[i + 1];
-            EXPECT_TRUE(CheckPixels(x + bx, y + by, 1, 1, 0, kExpectedColor));
-        }
-    }
-
-    void verifyTestPatternStroke(GLfloat fx, GLfloat fy)
-    {
-        GLint x = static_cast<GLint>(fx);
-        GLint y = static_cast<GLint>(fy);
-
-        // Inside the stroke we should have green.
-        static const angle::GLColor kGreen = {0, 255, 0, 255};
-        EXPECT_TRUE(CheckPixels(x + 50, y + 53, 1, 1, 0, kGreen));
-        EXPECT_TRUE(CheckPixels(x + 26, y + 76, 1, 1, 0, kGreen));
-
-        // Outside the path we should have black.
-        static const angle::GLColor black = {0, 0, 0, 0};
-        EXPECT_TRUE(CheckPixels(x + 10, y + 10, 1, 1, 0, black));
-        EXPECT_TRUE(CheckPixels(x + 80, y + 80, 1, 1, 0, black));
-    }
-
-    GLuint mColorLoc;
-};
-
-// Tests that basic path rendering functions work.
-TEST_P(CHROMIUMPathRenderingDrawTest, TestPathRendering)
-{
-    if (!isApplicable())
-        return;
-
-    static const float kBlue[]  = {0.0f, 0.0f, 1.0f, 1.0f};
-    static const float kGreen[] = {0.0f, 1.0f, 0.0f, 1.0f};
-
-    setupStateForTestPattern();
-
-    GLuint path = glGenPathsCHROMIUM(1);
-    setupPathStateForTestPattern(path);
-
-    // Do the stencil fill, cover fill, stencil stroke, cover stroke
-    // in unconventional order:
-    // 1) stencil the stroke in stencil high bit
-    // 2) stencil the fill in low bits
-    // 3) cover the fill
-    // 4) cover the stroke
-    // This is done to check that glPathStencilFunc works, eg the mask
-    // goes through. Stencil func is not tested ATM, for simplicity.
-
-    glPathStencilFuncCHROMIUM(GL_ALWAYS, 0, 0xFF);
-    glStencilStrokePathCHROMIUM(path, 0x80, 0x80);
-
-    glPathStencilFuncCHROMIUM(GL_ALWAYS, 0, 0x7F);
-    glStencilFillPathCHROMIUM(path, GL_COUNT_UP_CHROMIUM, 0x7F);
-
-    glStencilFunc(GL_LESS, 0, 0x7F);
-    glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
-    glUniform4fv(mColorLoc, 1, kBlue);
-    glCoverFillPathCHROMIUM(path, GL_BOUNDING_BOX_CHROMIUM);
-
-    glStencilFunc(GL_EQUAL, 0x80, 0x80);
-    glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
-    glUniform4fv(mColorLoc, 1, kGreen);
-    glCoverStrokePathCHROMIUM(path, GL_CONVEX_HULL_CHROMIUM);
-
-    glDeletePathsCHROMIUM(path, 1);
-
-    ASSERT_GL_NO_ERROR();
-
-    // Verify the image.
-    verifyTestPatternFill(0, 0);
-    verifyTestPatternBg(0, 0);
-    verifyTestPatternStroke(0, 0);
-}
-
-// Test that StencilThen{Stroke,Fill} path rendering functions work
-TEST_P(CHROMIUMPathRenderingDrawTest, TestPathRenderingThenFunctions)
-{
-    if (!isApplicable())
-        return;
-
-    static float kBlue[]  = {0.0f, 0.0f, 1.0f, 1.0f};
-    static float kGreen[] = {0.0f, 1.0f, 0.0f, 1.0f};
-
-    setupStateForTestPattern();
-
-    GLuint path = glGenPathsCHROMIUM(1);
-    setupPathStateForTestPattern(path);
-
-    glPathStencilFuncCHROMIUM(GL_ALWAYS, 0, 0xFF);
-    glStencilFunc(GL_EQUAL, 0x80, 0x80);
-    glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
-    glUniform4fv(mColorLoc, 1, kGreen);
-    glStencilThenCoverStrokePathCHROMIUM(path, 0x80, 0x80, GL_BOUNDING_BOX_CHROMIUM);
-
-    glPathStencilFuncCHROMIUM(GL_ALWAYS, 0, 0x7F);
-    glStencilFunc(GL_LESS, 0, 0x7F);
-    glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
-    glUniform4fv(mColorLoc, 1, kBlue);
-    glStencilThenCoverFillPathCHROMIUM(path, GL_COUNT_UP_CHROMIUM, 0x7F, GL_CONVEX_HULL_CHROMIUM);
-
-    glDeletePathsCHROMIUM(path, 1);
-
-    // Verify the image.
-    verifyTestPatternFill(0, 0);
-    verifyTestPatternBg(0, 0);
-    verifyTestPatternStroke(0, 0);
-}
-
-// Tests that drawing with *Instanced functions work.
-TEST_P(CHROMIUMPathRenderingDrawTest, TestPathRenderingInstanced)
-{
-    if (!isApplicable())
-        return;
-
-    static const float kBlue[]  = {0.0f, 0.0f, 1.0f, 1.0f};
-    static const float kGreen[] = {0.0f, 1.0f, 0.0f, 1.0f};
-
-    setupStateForTestPattern();
-
-    GLuint path = glGenPathsCHROMIUM(1);
-    setupPathStateForTestPattern(path);
-
-    const GLuint kPaths[]                             = {1, 1, 1, 1, 1};
-    const GLsizei kPathCount                          = 5;
-    const GLfloat kShapeSize                          = 80.0f;
-    static const GLfloat kTransforms[kPathCount * 12] = {
-        1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,           0.0f,       0.0f,
-        1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, kShapeSize,     0.0f,       0.0f,
-        1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, kShapeSize * 2, 0.0f,       0.0f,
-        1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,           kShapeSize, 0.0f,
-        1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, kShapeSize,     kShapeSize, 0.0f};
-
-    // The test pattern is the same as in the simple draw case above,
-    // except that the path is drawn kPathCount times with different offsets.
-    glPathStencilFuncCHROMIUM(GL_ALWAYS, 0, 0xFF);
-    glStencilStrokePathInstancedCHROMIUM(kPathCount, GL_UNSIGNED_INT, kPaths, path - 1, 0x80, 0x80,
-                                         GL_AFFINE_3D_CHROMIUM, kTransforms);
-
-    glPathStencilFuncCHROMIUM(GL_ALWAYS, 0, 0x7F);
-    glUniform4fv(mColorLoc, 1, kBlue);
-    glStencilFillPathInstancedCHROMIUM(kPathCount, GL_UNSIGNED_INT, kPaths, path - 1,
-                                       GL_COUNT_UP_CHROMIUM, 0x7F, GL_AFFINE_3D_CHROMIUM,
-                                       kTransforms);
-
-    ASSERT_GL_NO_ERROR();
-
-    glStencilFunc(GL_LESS, 0, 0x7F);
-    glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
-    glCoverFillPathInstancedCHROMIUM(kPathCount, GL_UNSIGNED_INT, kPaths, path - 1,
-                                     GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM,
-                                     GL_AFFINE_3D_CHROMIUM, kTransforms);
-
-    ASSERT_GL_NO_ERROR();
-
-    glStencilFunc(GL_EQUAL, 0x80, 0x80);
-    glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
-    glUniform4fv(mColorLoc, 1, kGreen);
-    glCoverStrokePathInstancedCHROMIUM(kPathCount, GL_UNSIGNED_INT, kPaths, path - 1,
-                                       GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM,
-                                       GL_AFFINE_3D_CHROMIUM, kTransforms);
-
-    ASSERT_GL_NO_ERROR();
-
-    glDeletePathsCHROMIUM(path, 1);
-
-    // Verify the image.
-    verifyTestPatternFill(0.0f, 0.0f);
-    verifyTestPatternBg(0.0f, 0.0f);
-    verifyTestPatternStroke(0.0f, 0.0f);
-
-    verifyTestPatternFill(kShapeSize, 0.0f);
-    verifyTestPatternBg(kShapeSize, 0.0f);
-    verifyTestPatternStroke(kShapeSize, 0.0f);
-
-    verifyTestPatternFill(kShapeSize * 2, 0.0f);
-    verifyTestPatternBg(kShapeSize * 2, 0.0f);
-    verifyTestPatternStroke(kShapeSize * 2, 0.0f);
-
-    verifyTestPatternFill(0.0f, kShapeSize);
-    verifyTestPatternBg(0.0f, kShapeSize);
-    verifyTestPatternStroke(0.0f, kShapeSize);
-
-    verifyTestPatternFill(kShapeSize, kShapeSize);
-    verifyTestPatternBg(kShapeSize, kShapeSize);
-    verifyTestPatternStroke(kShapeSize, kShapeSize);
-}
-
-// Test that instanced fill/stroke then cover functions work.
-TEST_P(CHROMIUMPathRenderingDrawTest, TestPathRenderingThenFunctionsInstanced)
-{
-    if (!isApplicable())
-        return;
-
-    static const float kBlue[]  = {0.0f, 0.0f, 1.0f, 1.0f};
-    static const float kGreen[] = {0.0f, 1.0f, 0.0f, 1.0f};
-
-    setupStateForTestPattern();
-
-    GLuint path = glGenPathsCHROMIUM(1);
-    setupPathStateForTestPattern(path);
-
-    const GLuint kPaths[]              = {1, 1, 1, 1, 1};
-    const GLsizei kPathCount           = 5;
-    const GLfloat kShapeSize           = 80.0f;
-    static const GLfloat kTransforms[] = {
-        0.0f, 0.0f, kShapeSize, 0.0f,       kShapeSize * 2,
-        0.0f, 0.0f, kShapeSize, kShapeSize, kShapeSize,
-    };
-
-    glPathStencilFuncCHROMIUM(GL_ALWAYS, 0, 0xFF);
-    glStencilFunc(GL_EQUAL, 0x80, 0x80);
-    glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
-    glUniform4fv(mColorLoc, 1, kGreen);
-    glStencilThenCoverStrokePathInstancedCHROMIUM(
-        kPathCount, GL_UNSIGNED_INT, kPaths, path - 1, 0x80, 0x80,
-        GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM, GL_TRANSLATE_2D_CHROMIUM, kTransforms);
-
-    ASSERT_GL_NO_ERROR();
-
-    glPathStencilFuncCHROMIUM(GL_ALWAYS, 0, 0x7F);
-    glStencilFunc(GL_LESS, 0, 0x7F);
-    glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
-    glUniform4fv(mColorLoc, 1, kBlue);
-    glStencilThenCoverFillPathInstancedCHROMIUM(
-        kPathCount, GL_UNSIGNED_INT, kPaths, path - 1, GL_COUNT_UP_CHROMIUM, 0x7F,
-        GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM, GL_TRANSLATE_2D_CHROMIUM, kTransforms);
-
-    ASSERT_GL_NO_ERROR();
-
-    glDeletePathsCHROMIUM(path, 1);
-
-    // Verify the image.
-    verifyTestPatternFill(0.0f, 0.0f);
-    verifyTestPatternBg(0.0f, 0.0f);
-    verifyTestPatternStroke(0.0f, 0.0f);
-
-    verifyTestPatternFill(kShapeSize, 0.0f);
-    verifyTestPatternBg(kShapeSize, 0.0f);
-    verifyTestPatternStroke(kShapeSize, 0.0f);
-
-    verifyTestPatternFill(kShapeSize * 2, 0.0f);
-    verifyTestPatternBg(kShapeSize * 2, 0.0f);
-    verifyTestPatternStroke(kShapeSize * 2, 0.0f);
-
-    verifyTestPatternFill(0.0f, kShapeSize);
-    verifyTestPatternBg(0.0f, kShapeSize);
-    verifyTestPatternStroke(0.0f, kShapeSize);
-
-    verifyTestPatternFill(kShapeSize, kShapeSize);
-    verifyTestPatternBg(kShapeSize, kShapeSize);
-    verifyTestPatternStroke(kShapeSize, kShapeSize);
-}
-
-// This class implements a test that draws a grid of v-shapes. The grid is
-// drawn so that even rows (from the bottom) are drawn with DrawArrays and odd
-// rows are drawn with path rendering.  It can be used to test various texturing
-// modes, comparing how the fill would work in normal GL rendering and how to
-// setup same sort of fill with path rendering.
-// The texturing test is parametrized to run the test with and without
-// ANGLE name hashing.
-class CHROMIUMPathRenderingWithTexturingTest : public ANGLETest
-{
-  protected:
-    CHROMIUMPathRenderingWithTexturingTest() : mProgram(0)
-    {
-        setWindowWidth(kResolution);
-        setWindowHeight(kResolution);
-        setConfigRedBits(8);
-        setConfigGreenBits(8);
-        setConfigBlueBits(8);
-        setConfigAlphaBits(8);
-        setConfigDepthBits(24);
-        setConfigStencilBits(8);
-    }
-
-    bool isApplicable() const { return IsGLExtensionEnabled("GL_CHROMIUM_path_rendering"); }
-
-    void testTearDown() override
-    {
-        if (mProgram)
-        {
-            glDeleteProgram(mProgram);
-            ASSERT_GL_NO_ERROR();
-        }
-    }
-
-    // Sets up the GL program state for the test.
-    // Vertex shader needs at least following variables:
-    //  uniform mat4 view_matrix;
-    //  uniform mat? color_matrix; (accessible with kColorMatrixLocation)
-    //  uniform vec2 model_translate;
-    //  attribute vec2 position;
-    //  varying vec4 color;
-    //
-    // Fragment shader needs at least following variables:
-    //  varying vec4 color;
-    //
-    //  (? can be anything)
-    void CompileProgram(const char *vertexShaderSource, const char *fragmentShaderSource)
-    {
-        glViewport(0, 0, kResolution, kResolution);
-        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
-        glStencilMask(0xffffffff);
-        glClearStencil(0);
-        glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-        glEnable(GL_BLEND);
-        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
-        ASSERT_GL_NO_ERROR();
-
-        GLuint vShader = CompileShader(GL_VERTEX_SHADER, vertexShaderSource);
-        GLuint fShader = CompileShader(GL_FRAGMENT_SHADER, fragmentShaderSource);
-        ASSERT_NE(0u, vShader);
-        ASSERT_NE(0u, fShader);
-
-        mProgram = glCreateProgram();
-
-        glAttachShader(mProgram, vShader);
-        glAttachShader(mProgram, fShader);
-        glDeleteShader(vShader);
-        glDeleteShader(fShader);
-
-        ASSERT_GL_NO_ERROR();
-    }
-
-    void bindProgram()
-    {
-        glBindAttribLocation(mProgram, kPositionLocation, "position");
-        glBindUniformLocationCHROMIUM(mProgram, kViewMatrixLocation, "view_matrix");
-        glBindUniformLocationCHROMIUM(mProgram, kColorMatrixLocation, "color_matrix");
-        glBindUniformLocationCHROMIUM(mProgram, kModelTranslateLocation, "model_translate");
-        glBindFragmentInputLocationCHROMIUM(mProgram, kColorFragmentInputLocation, "color");
-
-        ASSERT_GL_NO_ERROR();
-    }
-
-    bool linkProgram()
-    {
-        glLinkProgram(mProgram);
-
-        GLint linked = 0;
-        glGetProgramiv(mProgram, GL_LINK_STATUS, &linked);
-        if (linked)
-        {
-            glUseProgram(mProgram);
-        }
-
-        return (linked == 1);
-    }
-
-    void drawTestPattern()
-    {
-        // This v-shape is used both for DrawArrays and path rendering.
-        static const GLfloat kVertices[] = {75.0f, 75.0f, 50.0f, 25.5f, 50.0f, 50.0f, 25.0f, 75.0f};
-
-        GLuint vbo = 0;
-        glGenBuffers(1, &vbo);
-        glBindBuffer(GL_ARRAY_BUFFER, vbo);
-        glBufferData(GL_ARRAY_BUFFER, sizeof(kVertices), kVertices, GL_STATIC_DRAW);
-        glEnableVertexAttribArray(kPositionLocation);
-        glVertexAttribPointer(kPositionLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
-
-        // Setup state for drawing the shape with path rendering.
-        glPathStencilFuncCHROMIUM(GL_ALWAYS, 0, 0x7F);
-        glStencilFunc(GL_LESS, 0, 0x7F);
-        glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
-        glMatrixLoadfCHROMIUM(GL_PATH_PROJECTION_CHROMIUM, kProjectionMatrix);
-        glMatrixLoadIdentityCHROMIUM(GL_PATH_MODELVIEW_CHROMIUM);
-
-        static const GLubyte kCommands[] = {GL_MOVE_TO_CHROMIUM, GL_LINE_TO_CHROMIUM,
-                                            GL_LINE_TO_CHROMIUM, GL_LINE_TO_CHROMIUM,
-                                            GL_CLOSE_PATH_CHROMIUM};
-
-        static const GLfloat kCoords[] = {
-            kVertices[0], kVertices[1], kVertices[2], kVertices[3],
-            kVertices[6], kVertices[7], kVertices[4], kVertices[5],
-        };
-
-        GLuint path = glGenPathsCHROMIUM(1);
-        glPathCommandsCHROMIUM(path, static_cast<GLsizei>(ArraySize(kCommands)), kCommands,
-                               static_cast<GLsizei>(ArraySize(kCoords)), GL_FLOAT, kCoords);
-        ASSERT_GL_NO_ERROR();
-
-        GLfloat path_model_translate[16] = {
-            1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
-            0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
-        };
-
-        // Draws the shapes. Every even row from the bottom is drawn with
-        // DrawArrays, odd row with path rendering. The shader program is
-        // the same for the both draws.
-        for (int j = 0; j < kTestRows; ++j)
-        {
-            for (int i = 0; i < kTestColumns; ++i)
-            {
-                if (j % 2 == 0)
-                {
-                    glDisable(GL_STENCIL_TEST);
-                    glUniform2f(kModelTranslateLocation, static_cast<GLfloat>(i * kShapeWidth),
-                                static_cast<GLfloat>(j * kShapeHeight));
-                    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
-                }
-                else
-                {
-                    glEnable(GL_STENCIL_TEST);
-                    path_model_translate[12] = static_cast<GLfloat>(i * kShapeWidth);
-                    path_model_translate[13] = static_cast<GLfloat>(j * kShapeHeight);
-                    glMatrixLoadfCHROMIUM(GL_PATH_MODELVIEW_CHROMIUM, path_model_translate);
-                    glStencilThenCoverFillPathCHROMIUM(path, GL_COUNT_UP_CHROMIUM, 0x7F,
-                                                       GL_BOUNDING_BOX_CHROMIUM);
-                }
-            }
-        }
-        ASSERT_GL_NO_ERROR();
-
-        glDisableVertexAttribArray(kPositionLocation);
-        glDeleteBuffers(1, &vbo);
-        glDeletePathsCHROMIUM(path, 1);
-        ASSERT_GL_NO_ERROR();
-    }
-
-    enum
-    {
-        kShapeWidth  = 75,
-        kShapeHeight = 75,
-        kTestRows    = kResolution / kShapeHeight,
-        kTestColumns = kResolution / kShapeWidth,
-    };
-
-    GLuint mProgram;
-
-    // This uniform be can set by the test. It should be used to set the color for
-    // drawing with DrawArrays.
-    static const GLint kColorMatrixLocation = 4;
-
-    // This fragment input can be set by the test. It should be used to set the
-    // color for drawing with path rendering.
-    static const GLint kColorFragmentInputLocation = 7;
-
-    static const GLint kModelTranslateLocation = 3;
-    static const GLint kPositionLocation       = 0;
-    static const GLint kViewMatrixLocation     = 7;
-};
-
-// Test success and error cases for binding fragment input location.
-TEST_P(CHROMIUMPathRenderingWithTexturingTest, TestBindFragmentInputLocation)
-{
-    if (!isApplicable())
-        return;
-
-    // original NV_path_rendering specification doesn't define whether the
-    // fragment shader input variables should be defined in the vertex shader or
-    // not. In fact it doesn't even require a vertex shader.
-    // However the GLES3.1 spec basically says that fragment inputs are
-    // either built-ins or come from the previous shader stage.
-    // (§ 14.1, Fragment Shader Variables).
-    // Additionally there are many places that are based on the assumption of having
-    // a vertex shader (command buffer, angle) so we're going to stick to the same
-    // semantics and require a vertex shader and to have the vertex shader define the
-    // varying fragment shader input.
-
-    // clang-format off
-    const char* kVertexShaderSource =
-       "varying vec4 color;\n"
-       "void main() {}\n";
-
-    const char* kFragmentShaderSource =
-        "precision mediump float;\n"
-        "varying vec4 color;\n"
-        "void main() {\n"
-        "  gl_FragColor = vec4(1.0);\n"
-        "}\n";
-
-    // clang-format on
-    CompileProgram(kVertexShaderSource, kFragmentShaderSource);
-
-    enum kBindLocations
-    {
-        kColorLocation     = 5,
-        kFragColorLocation = 6
-    };
-
-    // successful bind.
-    glBindFragmentInputLocationCHROMIUM(mProgram, kColorLocation, "color");
-    ASSERT_GL_NO_ERROR();
-
-    // any name can be bound and names that do not actually exist in the program after
-    // linking are ignored.
-    glBindFragmentInputLocationCHROMIUM(mProgram, kColorLocation, "doesnt_exist");
-    ASSERT_GL_NO_ERROR();
-
-    // illegal program
-    glBindFragmentInputLocationCHROMIUM(mProgram + 1, kColorLocation, "color");
-    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
-
-    // illegal bind (built-in)
-    glBindFragmentInputLocationCHROMIUM(mProgram, kFragColorLocation, "gl_FragColor");
-    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
-
-    glBindFragmentInputLocationCHROMIUM(mProgram, kFragColorLocation, nullptr);
-    EXPECT_GL_ERROR(GL_INVALID_VALUE);
-
-    glBindFragmentInputLocationCHROMIUM(mProgram, 0xffffff, "color");
-    EXPECT_GL_ERROR(GL_INVALID_VALUE);
-
-    ASSERT_TRUE(linkProgram() == true);
-
-    const GLfloat kCoefficients16[] = {1.0f, 2.0f,  3.0f,  4.0f,  5.0f,  6.0f,  7.0f,  8.0f,
-                                       9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f};
-
-    glProgramPathFragmentInputGenCHROMIUM(mProgram, kColorLocation, GL_EYE_LINEAR_CHROMIUM, 4,
-                                          kCoefficients16);
-    ASSERT_GL_NO_ERROR();
-
-    glProgramPathFragmentInputGenCHROMIUM(mProgram, -1, GL_EYE_LINEAR_CHROMIUM, 4, kCoefficients16);
-    ASSERT_GL_NO_ERROR();
-}
-
-// Test fragment input interpolation in CHROMIUM_EYE coordinates.
-TEST_P(CHROMIUMPathRenderingWithTexturingTest, TestProgramPathFragmentInputGenCHROMIUM_EYE)
-{
-    if (!isApplicable())
-        return;
-
-    // clang-format off
-    const char *kVertexShaderSource =
-        "uniform mat4 view_matrix;\n"
-        "uniform mat4 color_matrix;\n"
-        "uniform vec2 model_translate;\n"
-        "attribute vec2 position;\n"
-        "varying vec3 color;\n"
-        "void main() {\n"
-        "  vec4 p = vec4(model_translate + position, 1.0, 1.0);\n"
-        "  color = (color_matrix * p).rgb;\n"
-        "  gl_Position = view_matrix * p;\n"
-        "}\n";
-
-    const char *kFragmentShaderSource =
-        "precision mediump float;\n"
-        "varying vec3 color;\n"
-        "void main() {\n"
-        "  gl_FragColor = vec4(color, 1.0);\n"
-        "}\n";
-    // clang-format on
-
-    CompileProgram(kVertexShaderSource, kFragmentShaderSource);
-    bindProgram();
-    ASSERT_TRUE(linkProgram() == true);
-
-    glUniformMatrix4fv(kViewMatrixLocation, 1, GL_FALSE, kProjectionMatrix);
-
-    static const GLfloat kColorMatrix[16] = {1.0f / kResolution,
-                                             0.0f,
-                                             0.0f,
-                                             0.0f,
-                                             0.0f,
-                                             1.0f / kResolution,
-                                             0.0f,
-                                             0.0f,
-                                             0.0f,
-                                             0.0f,
-                                             0.0f,
-                                             0.0f,
-                                             0.0f,
-                                             0.0f,
-                                             0.0f,
-                                             0.0f};
-
-    glUniformMatrix4fv(kColorMatrixLocation, 1, GL_FALSE, kColorMatrix);
-
-    // This is the functionality we are testing: ProgramPathFragmentInputGen
-    // does the same work as the color transform in vertex shader.
-    static const GLfloat kColorCoefficients[12] = {1.0f / kResolution,
-                                                   0.0f,
-                                                   0.0f,
-                                                   0.0f,
-                                                   0.0f,
-                                                   1.0f / kResolution,
-                                                   0.0f,
-                                                   0.0f,
-                                                   0.0f,
-                                                   0.0f,
-                                                   0.0f,
-                                                   0.0f};
-    glProgramPathFragmentInputGenCHROMIUM(mProgram, kColorFragmentInputLocation,
-                                          GL_EYE_LINEAR_CHROMIUM, 3, kColorCoefficients);
-    ASSERT_GL_NO_ERROR();
-
-    drawTestPattern();
-
-    const GLfloat kFillCoords[6] = {59.0f, 50.0f, 50.0f, 28.0f, 66.0f, 63.0f};
-
-    for (int j = 0; j < kTestRows; ++j)
-    {
-        for (int i = 0; i < kTestColumns; ++i)
-        {
-            for (size_t k = 0; k < ArraySize(kFillCoords); k += 2)
-            {
-                const float fx = kFillCoords[k];
-                const float fy = kFillCoords[k + 1];
-                const float px = static_cast<float>(i * kShapeWidth);
-                const float py = static_cast<float>(j * kShapeHeight);
-
-                angle::GLColor color;
-                color.R = static_cast<GLubyte>(std::roundf((px + fx) / kResolution * 255.0f));
-                color.G = static_cast<GLubyte>(std::roundf((py + fy) / kResolution * 255.0f));
-                color.B = 0;
-                color.A = 255;
-                CheckPixels(static_cast<GLint>(px + fx), static_cast<GLint>(py + fy), 1, 1, 2,
-                            color);
-            }
-        }
-    }
-}
-
-// Test fragment input interpolation in CHROMIUM_OBJECT coordinates.
-TEST_P(CHROMIUMPathRenderingWithTexturingTest, TestProgramPathFragmentInputGenCHROMIUM_OBJECT)
-{
-    if (!isApplicable())
-        return;
-
-    // clang-format off
-    const char *kVertexShaderSource =
-        "uniform mat4 view_matrix;\n"
-        "uniform mat4 color_matrix;\n"
-        "uniform vec2 model_translate;\n"
-        "attribute vec2 position;\n"
-        "varying vec3 color;\n"
-        "void main() {\n"
-        "  color = (color_matrix * vec4(position, 1.0, 1.0)).rgb;\n"
-        "  vec4 p = vec4(model_translate + position, 1.0, 1.0);\n"
-        "  gl_Position = view_matrix * p;\n"
-        "}";
-
-    const char *kFragmentShaderSource =
-        "precision mediump float;\n"
-        "varying vec3 color;\n"
-        "void main() {\n"
-        "  gl_FragColor = vec4(color.rgb, 1.0);\n"
-        "}";
-    // clang-format on
-
-    CompileProgram(kVertexShaderSource, kFragmentShaderSource);
-    bindProgram();
-    ASSERT_TRUE(linkProgram() == true);
-
-    glUniformMatrix4fv(kViewMatrixLocation, 1, GL_FALSE, kProjectionMatrix);
-
-    static const GLfloat kColorMatrix[16] = {1.0f / kShapeWidth,
-                                             0.0f,
-                                             0.0f,
-                                             0.0f,
-                                             0.0f,
-                                             1.0f / kShapeHeight,
-                                             0.0f,
-                                             0.0f,
-                                             0.0f,
-                                             0.0f,
-                                             0.0f,
-                                             0.0f,
-                                             0.0f,
-                                             0.0f,
-                                             0.0f,
-                                             0.0f};
-    glUniformMatrix4fv(kColorMatrixLocation, 1, GL_FALSE, kColorMatrix);
-
-    // This is the functionality we are testing: ProgramPathFragmentInputGen
-    // does the same work as the color transform in vertex shader.
-    static const GLfloat kColorCoefficients[9] = {
-        1.0f / kShapeWidth, 0.0f, 0.0f, 0.0f, 1.0f / kShapeHeight, 0.0f, 0.0f, 0.0f, 0.0f};
-    glProgramPathFragmentInputGenCHROMIUM(mProgram, kColorFragmentInputLocation,
-                                          GL_OBJECT_LINEAR_CHROMIUM, 3, kColorCoefficients);
-
-    ASSERT_GL_NO_ERROR();
-
-    drawTestPattern();
-
-    const GLfloat kFillCoords[6] = {59.0f, 50.0f, 50.0f, 28.0f, 66.0f, 63.0f};
-
-    for (int j = 0; j < kTestRows; ++j)
-    {
-        for (int i = 0; i < kTestColumns; ++i)
-        {
-            for (size_t k = 0; k < ArraySize(kFillCoords); k += 2)
-            {
-                const float fx = kFillCoords[k];
-                const float fy = kFillCoords[k + 1];
-                const float px = static_cast<float>(i * kShapeWidth);
-                const float py = static_cast<float>(j * kShapeHeight);
-
-                angle::GLColor color;
-                color.R = static_cast<GLubyte>(std::roundf(fx / kShapeWidth * 255.0f));
-                color.G = static_cast<GLubyte>(std::roundf(fy / kShapeHeight * 255.0f));
-                color.B = 0;
-                color.A = 255;
-                CheckPixels(static_cast<GLint>(px + fx), static_cast<GLint>(py + fy), 1, 1, 2,
-                            color);
-            }
-        }
-    }
-}
-
-// Test success and error cases for setting interpolation parameters.
-TEST_P(CHROMIUMPathRenderingWithTexturingTest, TestProgramPathFragmentInputGenArgs)
-{
-    if (!isApplicable())
-        return;
-
-    // clang-format off
-    const char *kVertexShaderSource =
-        "varying vec2 vec2_var;\n"
-        "varying vec3 vec3_var;\n"
-        "varying vec4 vec4_var;\n"
-        "varying float float_var;\n"
-        "varying mat2 mat2_var;\n"
-        "varying mat3 mat3_var;\n"
-        "varying mat4 mat4_var;\n"
-        "attribute float avoid_opt;\n"
-        "void main() {\n"
-        "  vec2_var = vec2(1.0, 2.0 + avoid_opt);\n"
-        "  vec3_var = vec3(1.0, 2.0, 3.0 + avoid_opt);\n"
-        "  vec4_var = vec4(1.0, 2.0, 3.0, 4.0 + avoid_opt);\n"
-        "  float_var = 5.0 + avoid_opt;\n"
-        "  mat2_var = mat2(2.0 + avoid_opt);\n"
-        "  mat3_var = mat3(3.0 + avoid_opt);\n"
-        "  mat4_var = mat4(4.0 + avoid_opt);\n"
-        "  gl_Position = vec4(1.0);\n"
-        "}";
-
-    const char* kFragmentShaderSource =
-        "precision mediump float;\n"
-        "varying vec2 vec2_var;\n"
-        "varying vec3 vec3_var;\n"
-        "varying vec4 vec4_var;\n"
-        "varying float float_var;\n"
-        "varying mat2 mat2_var;\n"
-        "varying mat3 mat3_var;\n"
-        "varying mat4 mat4_var;\n"
-        "void main() {\n"
-        "  gl_FragColor = vec4(vec2_var, 0, 0) + vec4(vec3_var, 0) + vec4_var + "
-        "               vec4(float_var) + "
-        "               vec4(mat2_var[0][0], mat3_var[1][1], mat4_var[2][2], 1);\n"
-        "}";
-    // clang-format on
-
-    enum
-    {
-        kVec2Location = 0,
-        kVec3Location,
-        kVec4Location,
-        kFloatLocation,
-        kMat2Location,
-        kMat3Location,
-        kMat4Location,
-    };
-    struct
-    {
-        GLint location;
-        const char *name;
-        GLint components;
-    } variables[] = {
-        {kVec2Location, "vec2_var", 2},
-        {kVec3Location, "vec3_var", 3},
-        {kVec4Location, "vec4_var", 4},
-        {kFloatLocation, "float_var", 1},
-        // If a varying is not single-precision floating-point scalar or
-        // vector, it always causes an invalid operation.
-        {kMat2Location, "mat2_var", -1},
-        {kMat3Location, "mat3_var", -1},
-        {kMat4Location, "mat4_var", -1},
-    };
-
-    CompileProgram(kVertexShaderSource, kFragmentShaderSource);
-
-    for (size_t i = 0; i < ArraySize(variables); ++i)
-    {
-        glBindFragmentInputLocationCHROMIUM(mProgram, variables[i].location, variables[i].name);
-    }
-
-    // test that using invalid (not linked) program is an invalid operation.
-    // See similar calls at the end of the test for discussion about the arguments.
-    glProgramPathFragmentInputGenCHROMIUM(mProgram, -1, GL_NONE, 0, nullptr);
-    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
-
-    ASSERT_TRUE(linkProgram() == true);
-
-    const GLfloat kCoefficients16[] = {1.0f, 2.0f,  3.0f,  4.0f,  5.0f,  6.0f,  7.0f,  8.0f,
-                                       9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f};
-    const GLenum kGenModes[]        = {GL_NONE, GL_EYE_LINEAR_CHROMIUM, GL_OBJECT_LINEAR_CHROMIUM,
-                                GL_CONSTANT_CHROMIUM};
-
-    for (size_t variable = 0; variable < ArraySize(variables); ++variable)
-    {
-        for (GLint components = 0; components <= 4; ++components)
-        {
-            for (size_t genmode = 0; genmode < ArraySize(kGenModes); ++genmode)
-            {
-                glProgramPathFragmentInputGenCHROMIUM(mProgram, variables[variable].location,
-                                                      kGenModes[genmode], components,
-                                                      kCoefficients16);
-
-                if (components == 0 && kGenModes[genmode] == GL_NONE)
-                {
-                    if (variables[variable].components == -1)
-                    {
-                        // Clearing a fragment input that is not single-precision floating
-                        // point scalar or vector is an invalid operation.
-                        ASSERT_GL_ERROR(GL_INVALID_OPERATION);
-                    }
-                    else
-                    {
-                        // Clearing a valid fragment input is ok.
-                        ASSERT_GL_NO_ERROR();
-                    }
-                }
-                else if (components == 0 || kGenModes[genmode] == GL_NONE)
-                {
-                    ASSERT_GL_ERROR(GL_INVALID_VALUE);
-                }
-                else
-                {
-                    if (components == variables[variable].components)
-                    {
-                        // Setting a generator for a single-precision floating point
-                        // scalar or vector fragment input is ok.
-                        ASSERT_GL_NO_ERROR();
-                    }
-                    else
-                    {
-                        // Setting a generator when components do not match is an invalid operation.
-                        ASSERT_GL_ERROR(GL_INVALID_OPERATION);
-                    }
-                }
-            }
-        }
-    }
-
-    enum
-    {
-        kValidGenMode      = GL_CONSTANT_CHROMIUM,
-        kValidComponents   = 3,
-        kInvalidGenMode    = 0xAB,
-        kInvalidComponents = 5,
-    };
-
-    // The location == -1 would mean fragment input was optimized away. At the
-    // time of writing, -1 can not happen because the only way to obtain the
-    // location numbers is through bind. Test just to be consistent.
-    glProgramPathFragmentInputGenCHROMIUM(mProgram, -1, kValidGenMode, kValidComponents,
-                                          kCoefficients16);
-    ASSERT_GL_NO_ERROR();
-
-    // Test that even though the spec says location == -1 causes the operation to
-    // be skipped, the verification of other parameters is still done. This is a
-    // GL policy.
-    glProgramPathFragmentInputGenCHROMIUM(mProgram, -1, kInvalidGenMode, kValidComponents,
-                                          kCoefficients16);
-    ASSERT_GL_ERROR(GL_INVALID_ENUM);
-
-    glProgramPathFragmentInputGenCHROMIUM(mProgram, -1, kInvalidGenMode, kInvalidComponents,
-                                          kCoefficients16);
-    ASSERT_GL_ERROR(GL_INVALID_ENUM);
-
-    glProgramPathFragmentInputGenCHROMIUM(mProgram, -1, kValidGenMode, kInvalidComponents,
-                                          kCoefficients16);
-    ASSERT_GL_ERROR(GL_INVALID_VALUE);
-
-    glDeleteProgram(mProgram);
-
-    // Test that using invalid (deleted) program is an invalid operation.
-    EXPECT_GL_TRUE(glIsProgram(mProgram));
-
-    glProgramPathFragmentInputGenCHROMIUM(mProgram, -1, kValidGenMode, kValidComponents,
-                                          kCoefficients16);
-    ASSERT_GL_ERROR(GL_INVALID_OPERATION);
-
-    glProgramPathFragmentInputGenCHROMIUM(mProgram, -1, kInvalidGenMode, kValidComponents,
-                                          kCoefficients16);
-    ASSERT_GL_ERROR(GL_INVALID_OPERATION);
-
-    glProgramPathFragmentInputGenCHROMIUM(mProgram, -1, kInvalidGenMode, kInvalidComponents,
-                                          kCoefficients16);
-    ASSERT_GL_ERROR(GL_INVALID_OPERATION);
-
-    glProgramPathFragmentInputGenCHROMIUM(mProgram, -1, kValidGenMode, kInvalidComponents,
-                                          kCoefficients16);
-    ASSERT_GL_ERROR(GL_INVALID_OPERATION);
-
-    mProgram = 0u;
-}
-
-// Test that having input statically aliased fragment inputs the linking fails
-// and then succeeds when the conflict is resolved.
-TEST_P(CHROMIUMPathRenderingWithTexturingTest, TestConflictingBind)
-{
-    if (!isApplicable())
-        return;
-
-    // clang-format off
-    const char* kVertexShaderSource =
-        "attribute vec4 position;\n"
-        "varying vec4 colorA;\n"
-        "varying vec4 colorB;\n"
-        "void main() {\n"
-        "  gl_Position = position;\n"
-        "  colorA = position + vec4(1);\n"
-        "  colorB = position + vec4(2);\n"
-        "}";
-
-    const char* kFragmentShaderSource =
-        "precision mediump float;\n"
-        "varying vec4 colorA;\n"
-        "varying vec4 colorB;\n"
-        "void main() {\n"
-        "  gl_FragColor = colorA + colorB;\n"
-        "}";
-    // clang-format on
-
-    const GLint kColorALocation = 3;
-    const GLint kColorBLocation = 4;
-
-    CompileProgram(kVertexShaderSource, kFragmentShaderSource);
-
-    glBindFragmentInputLocationCHROMIUM(mProgram, kColorALocation, "colorA");
-    // Bind colorB to location a, causing conflicts. Linking should fail.
-    glBindFragmentInputLocationCHROMIUM(mProgram, kColorALocation, "colorB");
-
-    // Should fail now.
-    ASSERT_TRUE(linkProgram() == false);
-    ASSERT_GL_NO_ERROR();
-
-    // Resolve the bind conflict.
-    glBindFragmentInputLocationCHROMIUM(mProgram, kColorBLocation, "colorB");
-
-    ASSERT_TRUE(linkProgram() == true);
-    ASSERT_GL_NO_ERROR();
-}
-
-// Test binding with array variables, using zero indices. Tests that
-// binding colorA[0] with explicit "colorA[0]" as well as "colorA" produces
-// a correct location that can be used with PathProgramFragmentInputGen.
-// For path rendering, colorA[0] is bound to a location. The input generator for
-// the location is set to produce vec4(0, 0.1, 0, 0.1).
-// The default varying, color, is bound to a location and its generator
-// will produce vec4(10.0).  The shader program produces green pixels.
-// For vertex-based rendering, the vertex shader produces the same effect as
-// the input generator for path rendering.
-TEST_P(CHROMIUMPathRenderingWithTexturingTest, BindFragmentInputArray)
-{
-    if (!isApplicable())
-        return;
-
-    //clang-format off
-    const char *kVertexShaderSource =
-        "uniform mat4 view_matrix;\n"
-        "uniform mat4 color_matrix;\n"
-        "uniform vec2 model_translate;\n"
-        "attribute vec2 position;\n"
-        "varying vec4 color;\n"
-        "varying vec4 colorA[4];\n"
-        "void main() {\n"
-        "  vec4 p = vec4(model_translate + position, 1, 1);\n"
-        "  gl_Position = view_matrix * p;\n"
-        "  colorA[0] = vec4(0.0, 0.1, 0, 0.1);\n"
-        "  colorA[1] = vec4(0.2);\n"
-        "  colorA[2] = vec4(0.3);\n"
-        "  colorA[3] = vec4(0.4);\n"
-        "  color = vec4(10.0);\n"
-        "}";
-
-    const char *kFragmentShaderSource =
-        "precision mediump float;\n"
-        "varying vec4 color;\n"
-        "varying vec4 colorA[4];\n"
-        "void main() {\n"
-        "  gl_FragColor = colorA[0] * color;\n"
-        "}";
-    // clang-format on
-
-    const GLint kColorA0Location = 4;
-    const GLint kUnusedLocation  = 5;
-    const GLfloat kColorA0[]     = {0.0f, 0.1f, 0.0f, 0.1f};
-    const GLfloat kColor[]       = {10.0f, 10.0f, 10.0f, 10.0f};
-    const GLfloat kFillCoords[6] = {59.0f, 50.0f, 50.0f, 28.0f, 66.0f, 63.0f};
-
-    for (int pass = 0; pass < 2; ++pass)
-    {
-        CompileProgram(kVertexShaderSource, kFragmentShaderSource);
-        if (pass == 0)
-        {
-            glBindFragmentInputLocationCHROMIUM(mProgram, kUnusedLocation, "colorA[0]");
-            glBindFragmentInputLocationCHROMIUM(mProgram, kColorA0Location, "colorA");
-        }
-        else
-        {
-            glBindFragmentInputLocationCHROMIUM(mProgram, kUnusedLocation, "colorA");
-            glBindFragmentInputLocationCHROMIUM(mProgram, kColorA0Location, "colorA[0]");
-        }
-
-        bindProgram();
-
-        ASSERT_TRUE(linkProgram() == true);
-
-        glUniformMatrix4fv(kViewMatrixLocation, 1, GL_FALSE, kProjectionMatrix);
-        glProgramPathFragmentInputGenCHROMIUM(mProgram, kColorA0Location, GL_CONSTANT_CHROMIUM, 4,
-                                              kColorA0);
-        glProgramPathFragmentInputGenCHROMIUM(mProgram, kColorFragmentInputLocation,
-                                              GL_CONSTANT_CHROMIUM, 4, kColor);
-        ASSERT_GL_NO_ERROR();
-
-        drawTestPattern();
-
-        for (int j = 0; j < kTestRows; ++j)
-        {
-            for (int i = 0; i < kTestColumns; ++i)
-            {
-                for (size_t k = 0; k < ArraySize(kFillCoords); k += 2)
-                {
-                    const float fx = kFillCoords[k];
-                    const float fy = kFillCoords[k + 1];
-                    const float px = static_cast<float>(i * kShapeWidth);
-                    const float py = static_cast<float>(j * kShapeHeight);
-
-                    angle::GLColor color;
-                    color.R = 0;
-                    color.G = 255;
-                    color.B = 0;
-                    color.A = 255;
-                    CheckPixels(static_cast<GLint>(px + fx), static_cast<GLint>(py + fy), 1, 1, 2,
-                                color);
-                }
-            }
-        }
-    }
-}
-
-// Test binding array variables. This is like BindFragmentInputArray.
-// Currently disabled since it seems there's a driver bug with the
-// older drivers. This should work with driver >= 364.12
-TEST_P(CHROMIUMPathRenderingWithTexturingTest, DISABLED_BindFragmentInputArrayNonZeroIndex)
-{
-    if (!isApplicable())
-        return;
-
-    // clang-format off
-    const char* kVertexShaderSource =
-        "uniform mat4 view_matrix;\n"
-        "uniform mat4 color_matrix;\n"
-        "uniform vec2 model_translate;\n"
-        "attribute vec2 position;\n"
-        "varying vec4 color;\n"
-        "varying vec4 colorA[4];\n"
-        "void main() {\n"
-        "  vec4 p = vec4(model_translate + position, 1, 1);\n"
-        "  gl_Position = view_matrix * p;\n"
-        "  colorA[0] = vec4(0, 0.1, 0, 0.1);\n"
-        "  colorA[1] = vec4(0, 1, 0, 1);\n"
-        "  colorA[2] = vec4(0, 0.8, 0, 0.8);\n"
-        "  colorA[3] = vec4(0, 0.5, 0, 0.5);\n"
-        "  color = vec4(0.2);\n"
-        "}\n";
-
-    const char* kFragmentShaderSource =
-        "precision mediump float;\n"
-        "varying vec4 colorA[4];\n"
-        "varying vec4 color;\n"
-        "void main() {\n"
-        "  gl_FragColor = (colorA[0] * colorA[1]) +\n"
-        "      colorA[2] + (colorA[3] * color);\n"
-        "}\n";
-    // clang-format on
-
-    const GLint kColorA0Location = 4;
-    const GLint kColorA1Location = 1;
-    const GLint kColorA2Location = 2;
-    const GLint kColorA3Location = 3;
-    const GLint kUnusedLocation  = 5;
-    const GLfloat kColorA0[]     = {0.0f, 0.1f, 0.0f, 0.1f};
-    const GLfloat kColorA1[]     = {0.0f, 1.0f, 0.0f, 1.0f};
-    const GLfloat kColorA2[]     = {0.0f, 0.8f, 0.0f, 0.8f};
-    const GLfloat kColorA3[]     = {0.0f, 0.5f, 0.0f, 0.5f};
-    const GLfloat kColor[]       = {0.2f, 0.2f, 0.2f, 0.2f};
-    const GLfloat kFillCoords[6] = {59.0f, 50.0f, 50.0f, 28.0f, 66.0f, 63.0f};
-
-    CompileProgram(kVertexShaderSource, kFragmentShaderSource);
-
-    glBindFragmentInputLocationCHROMIUM(mProgram, kUnusedLocation, "colorA[0]");
-    glBindFragmentInputLocationCHROMIUM(mProgram, kColorA1Location, "colorA[1]");
-    glBindFragmentInputLocationCHROMIUM(mProgram, kColorA2Location, "colorA[2]");
-    glBindFragmentInputLocationCHROMIUM(mProgram, kColorA3Location, "colorA[3]");
-    glBindFragmentInputLocationCHROMIUM(mProgram, kColorA0Location, "colorA");
-    ASSERT_GL_NO_ERROR();
-
-    bindProgram();
-    ASSERT_TRUE(linkProgram() == true);
-
-    glUniformMatrix4fv(kViewMatrixLocation, 1, GL_FALSE, kProjectionMatrix);
-
-    glProgramPathFragmentInputGenCHROMIUM(mProgram, kColorA0Location, GL_CONSTANT_CHROMIUM, 4,
-                                          kColorA0);
-    glProgramPathFragmentInputGenCHROMIUM(mProgram, kColorA1Location, GL_CONSTANT_CHROMIUM, 4,
-                                          kColorA1);
-    glProgramPathFragmentInputGenCHROMIUM(mProgram, kColorA2Location, GL_CONSTANT_CHROMIUM, 4,
-                                          kColorA2);
-    glProgramPathFragmentInputGenCHROMIUM(mProgram, kColorA3Location, GL_CONSTANT_CHROMIUM, 4,
-                                          kColorA3);
-    glProgramPathFragmentInputGenCHROMIUM(mProgram, kColorFragmentInputLocation,
-                                          GL_CONSTANT_CHROMIUM, 4, kColor);
-    ASSERT_GL_NO_ERROR();
-
-    drawTestPattern();
-
-    for (int j = 0; j < kTestRows; ++j)
-    {
-        for (int i = 0; i < kTestColumns; ++i)
-        {
-            for (size_t k = 0; k < ArraySize(kFillCoords); k += 2)
-            {
-                const float fx = kFillCoords[k];
-                const float fy = kFillCoords[k + 1];
-                const float px = static_cast<float>(i * kShapeWidth);
-                const float py = static_cast<float>(j * kShapeHeight);
-
-                angle::GLColor color;
-                color.R = 0;
-                color.G = 255;
-                color.B = 0;
-                color.A = 255;
-                CheckPixels(static_cast<GLint>(px + fx), static_cast<GLint>(py + fy), 1, 1, 2,
-                            color);
-            }
-        }
-    }
-}
-
-TEST_P(CHROMIUMPathRenderingWithTexturingTest, UnusedFragmentInputUpdate)
-{
-    if (!isApplicable())
-        return;
-
-    // clang-format off
-    const char* kVertexShaderString =
-        "attribute vec4 a_position;\n"
-        "void main() {\n"
-        "  gl_Position = a_position;\n"
-        "}";
-
-    const char* kFragmentShaderString =
-        "precision mediump float;\n"
-        "uniform vec4 u_colorA;\n"
-        "uniform float u_colorU;\n"
-        "uniform vec4 u_colorC;\n"
-        "void main() {\n"
-        "  gl_FragColor = u_colorA + u_colorC;\n"
-        "}";
-    // clang-format on
-
-    const GLint kColorULocation      = 1;
-    const GLint kNonexistingLocation = 5;
-    const GLint kUnboundLocation     = 6;
-
-    CompileProgram(kVertexShaderString, kFragmentShaderString);
-
-    glBindFragmentInputLocationCHROMIUM(mProgram, kColorULocation, "u_colorU");
-
-    // The non-existing input should behave like existing but optimized away input.
-    glBindFragmentInputLocationCHROMIUM(mProgram, kNonexistingLocation, "nonexisting");
-
-    // Let A and C be assigned automatic locations.
-    ASSERT_TRUE(linkProgram() == true);
-
-    const GLfloat kColor[16] = {};
-
-    // No errors on bound locations, since caller does not know
-    // if the driver optimizes them away or not.
-    glProgramPathFragmentInputGenCHROMIUM(mProgram, kColorULocation, GL_CONSTANT_CHROMIUM, 1,
-                                          kColor);
-    ASSERT_GL_NO_ERROR();
-
-    // No errors on bound locations of names that do not exist
-    // in the shader. Otherwise it would be inconsistent wrt the
-    // optimization case.
-    glProgramPathFragmentInputGenCHROMIUM(mProgram, kNonexistingLocation, GL_CONSTANT_CHROMIUM, 1,
-                                          kColor);
-    ASSERT_GL_NO_ERROR();
-
-    // The above are equal to updating -1.
-    glProgramPathFragmentInputGenCHROMIUM(mProgram, -1, GL_CONSTANT_CHROMIUM, 1, kColor);
-    ASSERT_GL_NO_ERROR();
-
-    // No errors when updating with other type either.
-    // The type can not be known with the non-existing case.
-    glProgramPathFragmentInputGenCHROMIUM(mProgram, kColorULocation, GL_CONSTANT_CHROMIUM, 4,
-                                          kColor);
-    ASSERT_GL_NO_ERROR();
-
-    glProgramPathFragmentInputGenCHROMIUM(mProgram, kNonexistingLocation, GL_CONSTANT_CHROMIUM, 4,
-                                          kColor);
-    ASSERT_GL_NO_ERROR();
-
-    glProgramPathFragmentInputGenCHROMIUM(mProgram, -1, GL_CONSTANT_CHROMIUM, 4, kColor);
-    ASSERT_GL_NO_ERROR();
-
-    // Updating an unbound, non-existing location still causes an error.
-    glProgramPathFragmentInputGenCHROMIUM(mProgram, kUnboundLocation, GL_CONSTANT_CHROMIUM, 4,
-                                          kColor);
-    ASSERT_GL_ERROR(GL_INVALID_OPERATION);
-}
-
-}  // namespace
-
-ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(CHROMIUMPathRenderingTest);
-ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(CHROMIUMPathRenderingDrawTest);
-ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(CHROMIUMPathRenderingWithTexturingTest);
diff --git a/src/tests/gl_tests/ProgramBinaryTest.cpp b/src/tests/gl_tests/ProgramBinaryTest.cpp
index 1f87cee..6cc1efd 100644
--- a/src/tests/gl_tests/ProgramBinaryTest.cpp
+++ b/src/tests/gl_tests/ProgramBinaryTest.cpp
@@ -293,7 +293,7 @@
     // We can't run the test if no program binary formats are supported.
     GLint binaryFormatCount = 0;
     glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &binaryFormatCount);
-    ANGLE_SKIP_TEST_IF(!binaryFormatCount);
+    ANGLE_SKIP_TEST_IF(binaryFormatCount == 0);
 
     constexpr char kVS[] =
         "#version 300 es\n"
@@ -381,13 +381,147 @@
     testBinaryAndUBOBlockIndexes(false);
 }
 
+// Test the shaders with arrays-of-struct uniforms are properly saved and restored
+TEST_P(ProgramBinaryES3Test, TestArrayOfStructUniform)
+{
+    // We can't run the test if no program binary formats are supported.
+    GLint binaryFormatCount = 0;
+    glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &binaryFormatCount);
+    ANGLE_SKIP_TEST_IF(binaryFormatCount == 0);
+
+    constexpr char kVS[] =
+        "#version 300 es\n"
+        "in highp vec4 position;\n"
+        "out mediump float v_vtxOut;\n"
+        "\n"
+        "struct structType\n"
+        "{\n"
+        "    mediump vec4 m0;\n"
+        "    mediump vec4 m1;\n"
+        "};\n"
+        "uniform structType u_var[3];\n"
+        "\n"
+        "mediump float compare_float(mediump float a, mediump float b)\n"
+        "{\n"
+        "    return abs(a - b) < 0.05 ? 1.0 : 0.0;\n"
+        "}\n"
+        "mediump float compare_vec4(mediump vec4 a, mediump vec4 b)\n"
+        "{\n"
+        "    return compare_float(a.x, b.x)*compare_float(a.y, b.y)*\n"
+        "           compare_float(a.z, b.z)*compare_float(a.w, b.w);\n"
+        "}\n"
+        "\n"
+        "void main (void)\n"
+        "{\n"
+        "    gl_Position = position;\n"
+        "    v_vtxOut = 1.0;\n"
+        "    v_vtxOut *= compare_vec4(u_var[0].m0, vec4(0.15, 0.52, 0.26, 0.35));\n"
+        "    v_vtxOut *= compare_vec4(u_var[0].m1, vec4(0.88, 0.09, 0.30, 0.61));\n"
+        "    v_vtxOut *= compare_vec4(u_var[1].m0, vec4(0.85, 0.59, 0.33, 0.71));\n"
+        "    v_vtxOut *= compare_vec4(u_var[1].m1, vec4(0.62, 0.89, 0.09, 0.99));\n"
+        "    v_vtxOut *= compare_vec4(u_var[2].m0, vec4(0.53, 0.89, 0.01, 0.08));\n"
+        "    v_vtxOut *= compare_vec4(u_var[2].m1, vec4(0.26, 0.72, 0.60, 0.12));\n"
+        "}";
+
+    constexpr char kFS[] =
+        "#version 300 es\n"
+        "in mediump float v_vtxOut;\n"
+        "\n"
+        "layout(location = 0) out mediump vec4 dEQP_FragColor;\n"
+        "\n"
+        "void main (void)\n"
+        "{\n"
+        "    mediump float result = v_vtxOut;\n"
+        "    dEQP_FragColor = vec4(result, result, result, 1.0);\n"
+        "}";
+
+    // Init and draw with the program.
+    ANGLE_GL_PROGRAM(program, kVS, kFS);
+
+    glUseProgram(program.get());
+
+    int location = glGetUniformLocation(program.get(), "u_var[0].m0");
+    ASSERT_NE(location, -1);
+    glUniform4f(location, 0.15, 0.52, 0.26, 0.35);
+    location = glGetUniformLocation(program.get(), "u_var[0].m1");
+    ASSERT_NE(location, -1);
+    glUniform4f(location, 0.88, 0.09, 0.30, 0.61);
+    location = glGetUniformLocation(program.get(), "u_var[1].m0");
+    ASSERT_NE(location, -1);
+    glUniform4f(location, 0.85, 0.59, 0.33, 0.71);
+    location = glGetUniformLocation(program.get(), "u_var[1].m1");
+    ASSERT_NE(location, -1);
+    glUniform4f(location, 0.62, 0.89, 0.09, 0.99);
+    location = glGetUniformLocation(program.get(), "u_var[2].m0");
+    ASSERT_NE(location, -1);
+    glUniform4f(location, 0.53, 0.89, 0.01, 0.08);
+    location = glGetUniformLocation(program.get(), "u_var[2].m1");
+    ASSERT_NE(location, -1);
+    glUniform4f(location, 0.26, 0.72, 0.60, 0.12);
+    ASSERT_GL_NO_ERROR();
+
+    // Clear and draw with the original program:
+    glClearColor(1.0, 0.0, 0.0, 1.0);
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
+    drawQuad(program.get(), "position", 0.5f);
+    ASSERT_GL_NO_ERROR();
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
+
+    // Read back the binary.
+    GLint programLength = 0;
+    glGetProgramiv(program.get(), GL_PROGRAM_BINARY_LENGTH_OES, &programLength);
+    ASSERT_GL_NO_ERROR();
+
+    GLsizei readLength  = 0;
+    GLenum binaryFormat = GL_NONE;
+    std::vector<uint8_t> binary(programLength);
+    glGetProgramBinary(program.get(), programLength, &readLength, &binaryFormat, binary.data());
+    ASSERT_GL_NO_ERROR();
+
+    EXPECT_EQ(static_cast<GLsizei>(programLength), readLength);
+
+    // Load a new program with the binary and draw.
+    ANGLE_GL_BINARY_ES3_PROGRAM(binaryProgram, binary, binaryFormat);
+
+    glUseProgram(binaryProgram.get());
+
+    location = glGetUniformLocation(binaryProgram.get(), "u_var[0].m0");
+    ASSERT_NE(location, -1);
+    glUniform4f(location, 0.15, 0.52, 0.26, 0.35);
+    location = glGetUniformLocation(binaryProgram.get(), "u_var[0].m1");
+    ASSERT_NE(location, -1);
+    glUniform4f(location, 0.88, 0.09, 0.30, 0.61);
+    location = glGetUniformLocation(binaryProgram.get(), "u_var[1].m0");
+    ASSERT_NE(location, -1);
+    glUniform4f(location, 0.85, 0.59, 0.33, 0.71);
+    location = glGetUniformLocation(binaryProgram.get(), "u_var[1].m1");
+    ASSERT_NE(location, -1);
+    glUniform4f(location, 0.62, 0.89, 0.09, 0.99);
+    location = glGetUniformLocation(binaryProgram.get(), "u_var[2].m0");
+    ASSERT_NE(location, -1);
+    glUniform4f(location, 0.53, 0.89, 0.01, 0.08);
+    location = glGetUniformLocation(binaryProgram.get(), "u_var[2].m1");
+    ASSERT_NE(location, -1);
+    glUniform4f(location, 0.26, 0.72, 0.60, 0.12);
+    ASSERT_GL_NO_ERROR();
+
+    // Clear and draw with the restored program:
+    glClearColor(1.0, 0.0, 0.0, 1.0);
+    glClear(GL_COLOR_BUFFER_BIT);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
+    drawQuad(binaryProgram.get(), "position", 0.5f);
+    ASSERT_GL_NO_ERROR();
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
+}
+
 // Tests the difference between uniform static and active use
 TEST_P(ProgramBinaryES3Test, ActiveUniformShader)
 {
     // We can't run the test if no program binary formats are supported.
     GLint binaryFormatCount = 0;
     glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &binaryFormatCount);
-    ANGLE_SKIP_TEST_IF(!binaryFormatCount);
+    ANGLE_SKIP_TEST_IF(binaryFormatCount == 0);
 
     constexpr char kVS[] =
         "#version 300 es\n"
@@ -470,7 +604,7 @@
     // We can't run the test if no program binary formats are supported.
     GLint binaryFormatCount = 0;
     glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &binaryFormatCount);
-    ANGLE_SKIP_TEST_IF(!binaryFormatCount);
+    ANGLE_SKIP_TEST_IF(binaryFormatCount == 0);
 
     constexpr char kVS[] =
         "#version 300 es\n"
@@ -638,7 +772,7 @@
     // We can't run the test if no program binary formats are supported.
     GLint binaryFormatCount = 0;
     glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &binaryFormatCount);
-    ANGLE_SKIP_TEST_IF(!binaryFormatCount);
+    ANGLE_SKIP_TEST_IF(binaryFormatCount == 0);
     // http://anglebug.com/4092
     ANGLE_SKIP_TEST_IF(IsVulkan());
 
@@ -750,7 +884,7 @@
     // We can't run the test if no program binary formats are supported.
     GLint binaryFormatCount = 0;
     glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &binaryFormatCount);
-    ANGLE_SKIP_TEST_IF(!binaryFormatCount);
+    ANGLE_SKIP_TEST_IF(binaryFormatCount == 0);
 
     const char kComputeShader[] =
         R"(#version 310 es
diff --git a/src/tests/gl_tests/ProgramPipelineTest.cpp b/src/tests/gl_tests/ProgramPipelineTest.cpp
index 65351f5..1167c71 100644
--- a/src/tests/gl_tests/ProgramPipelineTest.cpp
+++ b/src/tests/gl_tests/ProgramPipelineTest.cpp
@@ -32,6 +32,8 @@
 // Verify that program pipeline is not supported in version lower than ES31.
 TEST_P(ProgramPipelineTest, GenerateProgramPipelineObject)
 {
+    ANGLE_SKIP_TEST_IF(!IsVulkan());
+
     GLuint pipeline;
     glGenProgramPipelines(1, &pipeline);
     if (getClientMajorVersion() < 3 || getClientMinorVersion() < 1)
@@ -48,11 +50,48 @@
 }
 
 class ProgramPipelineTest31 : public ProgramPipelineTest
-{};
+{
+  protected:
+    ~ProgramPipelineTest31()
+    {
+        glDeleteProgram(mVertProg);
+        glDeleteProgram(mFragProg);
+        glDeleteProgramPipelines(1, &mPipeline);
+    }
+
+    void bindProgramPipeline(const GLchar *vertString, const GLchar *fragString);
+    void drawQuad(const std::string &positionAttribName,
+                  const GLfloat positionAttribZ,
+                  const GLfloat positionAttribXYScale);
+
+    GLuint mVertProg;
+    GLuint mFragProg;
+    GLuint mPipeline;
+};
+
+void ProgramPipelineTest31::bindProgramPipeline(const GLchar *vertString, const GLchar *fragString)
+{
+    mVertProg = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &vertString);
+    ASSERT_NE(mVertProg, 0u);
+    mFragProg = glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &fragString);
+    ASSERT_NE(mFragProg, 0u);
+
+    // Generate a program pipeline and attach the programs to their respective stages
+    glGenProgramPipelines(1, &mPipeline);
+    EXPECT_GL_NO_ERROR();
+    glUseProgramStages(mPipeline, GL_VERTEX_SHADER_BIT, mVertProg);
+    EXPECT_GL_NO_ERROR();
+    glUseProgramStages(mPipeline, GL_FRAGMENT_SHADER_BIT, mFragProg);
+    EXPECT_GL_NO_ERROR();
+    glBindProgramPipeline(mPipeline);
+    EXPECT_GL_NO_ERROR();
+}
 
 // Test generate or delete program pipeline.
 TEST_P(ProgramPipelineTest31, GenOrDeleteProgramPipelineTest)
 {
+    ANGLE_SKIP_TEST_IF(!IsVulkan());
+
     GLuint pipeline;
     glGenProgramPipelines(-1, &pipeline);
     EXPECT_GL_ERROR(GL_INVALID_VALUE);
@@ -68,6 +107,8 @@
 // Test BindProgramPipeline.
 TEST_P(ProgramPipelineTest31, BindProgramPipelineTest)
 {
+    ANGLE_SKIP_TEST_IF(!IsVulkan());
+
     glBindProgramPipeline(0);
     EXPECT_GL_NO_ERROR();
 
@@ -87,6 +128,8 @@
 // Test IsProgramPipeline
 TEST_P(ProgramPipelineTest31, IsProgramPipelineTest)
 {
+    ANGLE_SKIP_TEST_IF(!IsVulkan());
+
     EXPECT_GL_FALSE(glIsProgramPipeline(0));
     EXPECT_GL_NO_ERROR();
 
@@ -105,6 +148,250 @@
     EXPECT_GL_NO_ERROR();
 }
 
+// Simulates a call to glCreateShaderProgramv()
+GLuint createShaderProgram(GLenum type, const GLchar *shaderString)
+{
+    GLShader shader(type);
+    if (!shader.get())
+    {
+        return 0;
+    }
+
+    glShaderSource(shader, 1, &shaderString, nullptr);
+    glCompileShader(shader);
+
+    GLuint program = glCreateProgram();
+
+    if (program)
+    {
+        GLint compiled;
+        glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
+        glProgramParameteri(program, GL_PROGRAM_SEPARABLE, GL_TRUE);
+        if (compiled)
+        {
+            glAttachShader(program, shader);
+            glLinkProgram(program);
+            glDetachShader(program, shader);
+        }
+    }
+
+    EXPECT_GL_NO_ERROR();
+
+    return program;
+}
+
+void ProgramPipelineTest31::drawQuad(const std::string &positionAttribName,
+                                     const GLfloat positionAttribZ,
+                                     const GLfloat positionAttribXYScale)
+{
+    glUseProgram(0);
+
+    std::array<Vector3, 6> quadVertices = ANGLETestBase::GetQuadVertices();
+
+    for (Vector3 &vertex : quadVertices)
+    {
+        vertex.x() *= positionAttribXYScale;
+        vertex.y() *= positionAttribXYScale;
+        vertex.z() = positionAttribZ;
+    }
+
+    GLint positionLocation = glGetAttribLocation(mVertProg, positionAttribName.c_str());
+
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+    glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, quadVertices.data());
+    glEnableVertexAttribArray(positionLocation);
+
+    glDrawArrays(GL_TRIANGLES, 0, 6);
+
+    glDisableVertexAttribArray(positionLocation);
+    glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
+}
+
+// Test glUseProgramStages
+TEST_P(ProgramPipelineTest31, UseProgramStages)
+{
+    ANGLE_SKIP_TEST_IF(!IsVulkan());
+
+    // Create two separable program objects from a
+    // single source string respectively (vertSrc and fragSrc)
+    const GLchar *vertString = essl31_shaders::vs::Simple();
+    const GLchar *fragString = essl31_shaders::fs::Red();
+
+    mVertProg = createShaderProgram(GL_VERTEX_SHADER, vertString);
+    ASSERT_NE(mVertProg, 0u);
+    mFragProg = createShaderProgram(GL_FRAGMENT_SHADER, fragString);
+    ASSERT_NE(mFragProg, 0u);
+
+    // Generate a program pipeline and attach the programs to their respective stages
+    GLuint pipeline;
+    glGenProgramPipelines(1, &pipeline);
+    EXPECT_GL_NO_ERROR();
+    glUseProgramStages(pipeline, GL_VERTEX_SHADER_BIT, mVertProg);
+    EXPECT_GL_NO_ERROR();
+    glUseProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, mFragProg);
+    EXPECT_GL_NO_ERROR();
+    glBindProgramPipeline(pipeline);
+    EXPECT_GL_NO_ERROR();
+
+    ProgramPipelineTest31::drawQuad("a_position", 0.5f, 1.0f);
+    ASSERT_GL_NO_ERROR();
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
+}
+
+// Test glUseProgramStages
+TEST_P(ProgramPipelineTest31, UseCreateShaderProgramv)
+{
+    ANGLE_SKIP_TEST_IF(!IsVulkan());
+
+    // Create two separable program objects from a
+    // single source string respectively (vertSrc and fragSrc)
+    const GLchar *vertString = essl31_shaders::vs::Simple();
+    const GLchar *fragString = essl31_shaders::fs::Red();
+
+    bindProgramPipeline(vertString, fragString);
+
+    ProgramPipelineTest31::drawQuad("a_position", 0.5f, 1.0f);
+    ASSERT_GL_NO_ERROR();
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
+}
+
+// Test glUniform
+TEST_P(ProgramPipelineTest31, FragmentStageUniformTest)
+{
+    ANGLE_SKIP_TEST_IF(!IsVulkan());
+
+    // Create two separable program objects from a
+    // single source string respectively (vertSrc and fragSrc)
+    const GLchar *vertString = essl31_shaders::vs::Simple();
+    const GLchar *fragString = R"(#version 310 es
+precision highp float;
+uniform float redColorIn;
+uniform float greenColorIn;
+out vec4 my_FragColor;
+void main()
+{
+    my_FragColor = vec4(redColorIn, greenColorIn, 0.0, 1.0);
+})";
+
+    bindProgramPipeline(vertString, fragString);
+
+    // Set the output color to yellow
+    GLint location = glGetUniformLocation(mFragProg, "redColorIn");
+    glActiveShaderProgram(mPipeline, mFragProg);
+    glUniform1f(location, 1.0);
+    location = glGetUniformLocation(mFragProg, "greenColorIn");
+    glActiveShaderProgram(mPipeline, mFragProg);
+    glUniform1f(location, 1.0);
+
+    ProgramPipelineTest31::drawQuad("a_position", 0.5f, 1.0f);
+    ASSERT_GL_NO_ERROR();
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
+
+    glClearColor(0.0, 0.0, 0.0, 0.0);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    ProgramPipelineTest31::drawQuad("a_position", 0.5f, 1.0f);
+    ASSERT_GL_NO_ERROR();
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
+
+    glClearColor(0.0, 0.0, 0.0, 0.0);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    // Set the output color to red
+    location = glGetUniformLocation(mFragProg, "redColorIn");
+    glActiveShaderProgram(mPipeline, mFragProg);
+    glUniform1f(location, 1.0);
+    location = glGetUniformLocation(mFragProg, "greenColorIn");
+    glActiveShaderProgram(mPipeline, mFragProg);
+    glUniform1f(location, 0.0);
+
+    ProgramPipelineTest31::drawQuad("a_position", 0.5f, 1.0f);
+    ASSERT_GL_NO_ERROR();
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
+
+    glDeleteProgram(mVertProg);
+    glDeleteProgram(mFragProg);
+}
+
+// Test varyings
+TEST_P(ProgramPipelineTest31, ProgramPipelineVaryings)
+{
+    ANGLE_SKIP_TEST_IF(!IsVulkan());
+
+    // Create two separable program objects from a
+    // single source string respectively (vertSrc and fragSrc)
+    const GLchar *vertString = essl31_shaders::vs::Passthrough();
+    const GLchar *fragString = R"(#version 310 es
+precision highp float;
+in vec4 v_position;
+out vec4 my_FragColor;
+void main()
+{
+    my_FragColor = round(v_position);
+})";
+
+    bindProgramPipeline(vertString, fragString);
+
+    ProgramPipelineTest31::drawQuad("a_position", 0.5f, 1.0f);
+    ASSERT_GL_NO_ERROR();
+
+    int w = getWindowWidth() - 2;
+    int h = getWindowHeight() - 2;
+
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
+    EXPECT_PIXEL_COLOR_EQ(w, 0, GLColor::red);
+    EXPECT_PIXEL_COLOR_EQ(0, h, GLColor::green);
+    EXPECT_PIXEL_COLOR_EQ(w, h, GLColor::yellow);
+}
+
+// Creates a program pipeline with a 2D texture and renders with it.
+TEST_P(ProgramPipelineTest31, DrawWith2DTexture)
+{
+    ANGLE_SKIP_TEST_IF(!IsVulkan());
+
+    const GLchar *vertString = R"(#version 310 es
+precision highp float;
+in vec4 a_position;
+out vec2 texCoord;
+void main()
+{
+    gl_Position = a_position;
+    texCoord = vec2(a_position.x, a_position.y) * 0.5 + vec2(0.5);
+})";
+
+    const GLchar *fragString = R"(#version 310 es
+precision highp float;
+in vec2 texCoord;
+uniform sampler2D tex;
+out vec4 my_FragColor;
+void main()
+{
+    my_FragColor = texture(tex, texCoord);
+})";
+
+    std::array<GLColor, 4> colors = {
+        {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
+
+    GLTexture tex;
+    glBindTexture(GL_TEXTURE_2D, tex);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+    bindProgramPipeline(vertString, fragString);
+
+    ProgramPipelineTest31::drawQuad("a_position", 0.5f, 1.0f);
+    ASSERT_GL_NO_ERROR();
+
+    int w = getWindowWidth() - 2;
+    int h = getWindowHeight() - 2;
+
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
+    EXPECT_PIXEL_COLOR_EQ(w, 0, GLColor::green);
+    EXPECT_PIXEL_COLOR_EQ(0, h, GLColor::blue);
+    EXPECT_PIXEL_COLOR_EQ(w, h, GLColor::yellow);
+}
+
 ANGLE_INSTANTIATE_TEST_ES3_AND_ES31(ProgramPipelineTest);
 ANGLE_INSTANTIATE_TEST_ES31(ProgramPipelineTest31);
 
diff --git a/src/tests/gl_tests/RobustResourceInitTest.cpp b/src/tests/gl_tests/RobustResourceInitTest.cpp
index 83bcafc..e31ae79 100644
--- a/src/tests/gl_tests/RobustResourceInitTest.cpp
+++ b/src/tests/gl_tests/RobustResourceInitTest.cpp
@@ -291,6 +291,8 @@
 
     template <typename ClearFunc>
     void maskedStencilClear(ClearFunc clearFunc);
+
+    void copyTexSubImage2DCustomFBOTest(int offsetX, int offsetY);
 };
 
 class RobustResourceInitTestES3 : public RobustResourceInitTest
@@ -1531,6 +1533,60 @@
     VerifyRGBA8PixelRect<kDestSize>(destInitTest);
 }
 
+void RobustResourceInitTest::copyTexSubImage2DCustomFBOTest(int offsetX, int offsetY)
+{
+    const int texSize = 512;
+    const int fboSize = 16;
+
+    GLTexture texture;
+    glBindTexture(GL_TEXTURE_2D, texture.get());
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texSize, texSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 nullptr);
+    ASSERT_GL_NO_ERROR();
+
+    GLRenderbuffer renderbuffer;
+    glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer.get());
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, fboSize, fboSize);
+    ASSERT_GL_NO_ERROR();
+
+    GLFramebuffer framebuffer;
+    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
+                              renderbuffer.get());
+    ASSERT_GL_NO_ERROR();
+    ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
+
+    glClearColor(1.0, 0.0, 0.0, 1.0);
+    glClear(GL_COLOR_BUFFER_BIT);
+    ASSERT_GL_NO_ERROR();
+
+    glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, offsetX, offsetY, texSize, texSize);
+    ASSERT_GL_NO_ERROR();
+
+    GLFramebuffer readbackFBO;
+    glBindFramebuffer(GL_FRAMEBUFFER, readbackFBO.get());
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
+    ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
+    checkCustomFramebufferNonZeroPixels(texSize, texSize, -offsetX, -offsetY, fboSize, fboSize,
+                                        GLColor::red);
+}
+
+// Test CopyTexSubImage2D clipped to size of custom FBO, zero x/y source offset.
+TEST_P(RobustResourceInitTest, CopyTexSubImage2DCustomFBOZeroOffsets)
+{
+    // TODO(anglebug.com/4507): pass this test on the Metal backend.
+    ANGLE_SKIP_TEST_IF(IsMetal());
+    copyTexSubImage2DCustomFBOTest(0, 0);
+}
+
+// Test CopyTexSubImage2D clipped to size of custom FBO, negative x/y source offset.
+TEST_P(RobustResourceInitTest, CopyTexSubImage2DCustomFBONegativeOffsets)
+{
+    // TODO(anglebug.com/4507): pass this test on the Metal backend.
+    ANGLE_SKIP_TEST_IF(IsMetal());
+    copyTexSubImage2DCustomFBOTest(-8, -8);
+}
+
 // Tests that calling CopyTexSubImage3D will initialize the source & destination.
 TEST_P(RobustResourceInitTestES3, CopyTexSubImage3D)
 {
@@ -1944,6 +2000,58 @@
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 }
 
+// Corner case for robust resource init: CopyTexImage to a cube map.
+TEST_P(RobustResourceInitTest, CopyTexImageToOffsetCubeMap)
+{
+    // http://anglebug.com/4549
+    ANGLE_SKIP_TEST_IF(IsMetal());
+
+    constexpr GLuint kSize = 2;
+
+    std::vector<GLColor> redPixels(kSize * kSize, GLColor::red);
+
+    GLTexture srcTex;
+    glBindTexture(GL_TEXTURE_2D, srcTex);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
+                 redPixels.data());
+
+    GLFramebuffer fbo;
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, srcTex, 0);
+
+    ASSERT_GL_NO_ERROR();
+    ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
+
+    GLTexture dstTex;
+    glBindTexture(GL_TEXTURE_CUBE_MAP, dstTex);
+    glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 1, 1, kSize, kSize, 0);
+    glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, -1, -1, kSize, kSize, 0);
+    glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, 2, 2, kSize, kSize, 0);
+    glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, -2, -2, kSize, kSize, 0);
+    glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, 0, 0, kSize, kSize, 0);
+    glCopyTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 0, 0, kSize, kSize, 0);
+
+    ASSERT_GL_NO_ERROR();
+
+    // Verify the offset attachments.
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X,
+                           dstTex, 0);
+    ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
+    EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::transparentBlack);
+    EXPECT_PIXEL_COLOR_EQ(0, 1, GLColor::transparentBlack);
+    EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::transparentBlack);
+
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
+                           dstTex, 0);
+    ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
+    EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::transparentBlack);
+    EXPECT_PIXEL_COLOR_EQ(0, 1, GLColor::transparentBlack);
+    EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red);
+}
+
 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(RobustResourceInitTest,
                                        WithAllocateNonZeroMemory(ES2_VULKAN()));
 
diff --git a/src/tests/gl_tests/ShaderInterpTest.cpp b/src/tests/gl_tests/ShaderInterpTest.cpp
new file mode 100644
index 0000000..41115e3
--- /dev/null
+++ b/src/tests/gl_tests/ShaderInterpTest.cpp
@@ -0,0 +1,212 @@
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Tests for shader interpolation qualifiers
+//
+
+#include "common/mathutil.h"
+#include "test_utils/ANGLETest.h"
+#include "test_utils/gl_raii.h"
+
+using namespace angle;
+
+constexpr int kPixelColorThreshhold = 8;
+
+class ShaderInterpTest : public ANGLETest
+{
+  protected:
+    ShaderInterpTest() : ANGLETest()
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+    }
+
+    void draw(GLuint program, float skew)
+    {
+        glUseProgram(program);
+
+        std::array<Vector4, 3> vertices;
+        vertices[0] = {-1.0, -1.0, 0.0, 1.0};
+        vertices[1] = {1.0, -1.0, 0.0, 1.0};
+        vertices[2] = {0.0, 1.0 * skew, 0.0, skew};
+
+        std::array<Vector4, 3> colors;
+        colors[0] = {1.0, 0.0, 0.0, 1.0};
+        colors[1] = {0.0, 1.0, 0.0, 1.0};
+        colors[2] = {0.0, 0.0, 1.0, 1.0};
+
+        GLint positionLocation = glGetAttribLocation(program, "position");
+        GLint colorLocation    = glGetAttribLocation(program, "vertex_color");
+
+        glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, vertices.data());
+        glVertexAttribPointer(colorLocation, 4, GL_FLOAT, GL_FALSE, 0, colors.data());
+
+        glEnableVertexAttribArray(positionLocation);
+        glEnableVertexAttribArray(colorLocation);
+
+        glDrawArrays(GL_TRIANGLES, 0, 3);
+    }
+};
+
+// Test that regular "smooth" interpolation works correctly
+TEST_P(ShaderInterpTest, Smooth)
+{
+    const char *vertSrc = R"(#version 300 es
+precision highp float;
+in vec4 position;
+in vec4 vertex_color;
+smooth out vec4 interp_color;
+
+void main()
+{
+    gl_Position = position;
+    interp_color = vertex_color;
+}
+)";
+    const char *fragSrc = R"(#version 300 es
+precision highp float;
+smooth in vec4 interp_color;
+out vec4 fragColor;
+
+void main()
+{
+    fragColor = interp_color;
+}
+)";
+
+    ANGLE_GL_PROGRAM(program, vertSrc, fragSrc);
+    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+
+    glClear(GL_COLOR_BUFFER_BIT);
+    draw(program, 1.0);
+    EXPECT_PIXEL_COLOR_NEAR(64, 64, GLColor(62, 64, 128, 255), kPixelColorThreshhold);
+
+    glClear(GL_COLOR_BUFFER_BIT);
+    draw(program, 2.0);
+    EXPECT_PIXEL_COLOR_NEAR(64, 64, GLColor(83, 86, 86, 255), kPixelColorThreshhold);
+}
+
+// Test that uninterpolated "Flat" interpolation works correctly
+TEST_P(ShaderInterpTest, Flat)
+{
+    // TODO: anglebug.com/4085
+    // No vendors currently support VK_EXT_provoking_vertex, which is necessary for conformant flat
+    // shading. SwiftShader does technically support this extension, but as it has not yet been
+    // ratified by Khronos, the vulkan validation layers do not recognize the create info struct,
+    // causing it to be stripped and thus causing the extension to behave as if it is disabled.
+    ANGLE_SKIP_TEST_IF(IsVulkan());
+
+    const char *vertSrc = R"(#version 300 es
+precision highp float;
+in vec4 position;
+in vec4 vertex_color;
+flat out vec4 interp_color;
+
+void main()
+{
+    gl_Position = position;
+    interp_color = vertex_color;
+}
+)";
+    const char *fragSrc = R"(#version 300 es
+precision highp float;
+flat in vec4 interp_color;
+out vec4 fragColor;
+
+void main()
+{
+    fragColor = interp_color;
+}
+)";
+
+    ANGLE_GL_PROGRAM(program, vertSrc, fragSrc);
+    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+
+    glClear(GL_COLOR_BUFFER_BIT);
+    draw(program, 1.0);
+    GLColor smooth_reference;
+    glReadPixels(64, 64, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &smooth_reference);
+    EXPECT_PIXEL_COLOR_EQ(64, 64, GLColor(0, 0, 255, 255));
+}
+
+// Test that "noperspective" interpolation correctly interpolates in screenspace
+TEST_P(ShaderInterpTest, NoPerspective)
+{
+    ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_NV_shader_noperspective_interpolation"));
+
+    const char *vertSrcSmooth = R"(#version 300 es
+precision highp float;
+in vec4 position;
+in vec4 vertex_color;
+smooth out vec4 interp_color;
+
+void main()
+{
+    gl_Position = position;
+    interp_color = vertex_color;
+}
+)";
+    const char *fragSrcSmooth = R"(#version 300 es
+precision highp float;
+smooth in vec4 interp_color;
+out vec4 fragColor;
+
+void main()
+{
+    fragColor = interp_color;
+}
+)";
+    ANGLE_GL_PROGRAM(programSmooth, vertSrcSmooth, fragSrcSmooth);
+    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT);
+    draw(programSmooth, 1.0);
+    GLColor smooth_reference;
+    glReadPixels(64, 64, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &smooth_reference);
+
+    const char *vertSrcNoPerspective = R"(#version 300 es
+#extension GL_NV_shader_noperspective_interpolation : require
+
+#ifndef GL_NV_shader_noperspective_interpolation
+#error GL_NV_shader_noperspective_interpolation is not defined
+#endif
+
+precision highp float;
+in vec4 position;
+in vec4 vertex_color;
+noperspective out vec4 interp_color;
+
+void main()
+{
+    gl_Position = position;
+    interp_color = vertex_color;
+}
+)";
+    const char *fragSrcNoPerspective = R"(#version 300 es
+#extension GL_NV_shader_noperspective_interpolation : require
+
+#ifndef GL_NV_shader_noperspective_interpolation
+#error GL_NV_shader_noperspective_interpolation is not defined
+#endif
+
+precision highp float;
+noperspective in vec4 interp_color;
+out vec4 fragColor;
+
+void main()
+{
+    fragColor = interp_color;
+}
+)";
+    ANGLE_GL_PROGRAM(programNoPerspective, vertSrcNoPerspective, fragSrcNoPerspective);
+    glClear(GL_COLOR_BUFFER_BIT);
+    draw(programNoPerspective, 1.0);
+    EXPECT_PIXEL_COLOR_EQ(64, 64, smooth_reference);
+
+    glClear(GL_COLOR_BUFFER_BIT);
+    draw(programNoPerspective, 2.0);
+    EXPECT_PIXEL_COLOR_EQ(64, 64, smooth_reference);
+}
+
+ANGLE_INSTANTIATE_TEST_ES3(ShaderInterpTest);
\ No newline at end of file
diff --git a/src/tests/gl_tests/ShaderNonConstGlobalInitializerTest.cpp b/src/tests/gl_tests/ShaderNonConstGlobalInitializerTest.cpp
new file mode 100644
index 0000000..8b0b0fe
--- /dev/null
+++ b/src/tests/gl_tests/ShaderNonConstGlobalInitializerTest.cpp
@@ -0,0 +1,169 @@
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Tests for GL_EXT_shader_non_constant_global_initializers
+//
+
+#include "common/mathutil.h"
+#include "test_utils/ANGLETest.h"
+#include "test_utils/gl_raii.h"
+
+using namespace angle;
+
+class ShaderNonConstGlobalInitializerTest : public ANGLETest
+{
+  protected:
+    ShaderNonConstGlobalInitializerTest() : ANGLETest()
+    {
+        setWindowWidth(128);
+        setWindowHeight(128);
+    }
+
+    void draw(GLuint program)
+    {
+        std::array<Vector4, 3> vertices;
+        vertices[0] = {-1.0, -1.0, 0.0, 1.0};
+        vertices[1] = {1.0, -1.0, 0.0, 1.0};
+        vertices[2] = {0.0, 1.0, 0.0, 2.0};
+
+        GLint positionLocation = glGetAttribLocation(program, "a_position");
+
+        glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, vertices.data());
+
+        glEnableVertexAttribArray(positionLocation);
+
+        glDrawArrays(GL_TRIANGLES, 0, 3);
+    }
+};
+
+// Tests that the extension is disabled if not explicitly enabled- non constant initializers should
+// be forbidden in all cases unless this extension is explicitly requested
+TEST_P(ShaderNonConstGlobalInitializerTest, Disabled)
+{
+    const char *fragSrc = R"(#version 100
+
+precision lowp float;
+
+uniform float nondeterministic_uniform;
+
+float nonConstInitializer();
+
+float nonConstGlobal = nonConstInitializer();
+float sideEffectGlobal = 0.0;
+
+float nonConstInitializer() {
+    sideEffectGlobal = 1.0;
+    return nondeterministic_uniform;
+}
+
+void main()
+{
+    gl_FragColor = vec4(nondeterministic_uniform, nonConstGlobal, sideEffectGlobal, 1.0);
+}
+)";
+
+    GLShader badFragment(GL_FRAGMENT_SHADER);
+    glShaderSource(badFragment, 1, &fragSrc, nullptr);
+    glCompileShader(badFragment);
+
+    GLint compileResult;
+    glGetShaderiv(badFragment, GL_COMPILE_STATUS, &compileResult);
+    EXPECT_EQ(compileResult, 0);
+
+    EXPECT_GL_NO_ERROR();
+}
+
+// Test that non constant initializers are evaluated correctly in ESSL 100
+TEST_P(ShaderNonConstGlobalInitializerTest, v100)
+{
+    ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_non_constant_global_initializers"));
+
+    const char *fragSrc = R"(#version 100
+#extension GL_EXT_shader_non_constant_global_initializers : require
+
+precision lowp float;
+
+#ifndef GL_EXT_shader_non_constant_global_initializers
+#error GL_EXT_shader_non_constant_global_initializers is not defined
+#endif
+
+uniform float nondeterministic_uniform;
+
+float nonConstInitializer();
+
+float nonConstGlobal = nonConstInitializer();
+float sideEffectGlobal = 0.0;
+
+float nonConstInitializer() {
+    sideEffectGlobal = 1.0;
+    return nondeterministic_uniform;
+}
+
+void main()
+{
+    gl_FragColor = vec4(nondeterministic_uniform, nonConstGlobal, sideEffectGlobal, 1.0);
+}
+)";
+
+    ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), fragSrc);
+    EXPECT_GL_NO_ERROR();
+
+    glUseProgram(program);
+    glUniform1f(glGetUniformLocation(program, "nondeterministic_uniform"), 1.0f);
+    ASSERT_GL_NO_ERROR();
+
+    draw(program);
+    EXPECT_GL_NO_ERROR();
+
+    EXPECT_PIXEL_COLOR_EQ(64, 64, GLColor::white);
+}
+
+// Test that non constant initializers are evaluated correctly in ESSL 300
+TEST_P(ShaderNonConstGlobalInitializerTest, v300es)
+{
+    ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_non_constant_global_initializers"));
+
+    const char *fragSrc = R"(#version 300 es
+#extension GL_EXT_shader_non_constant_global_initializers : require
+
+precision highp float;
+out vec4 fragColor;
+
+#ifndef GL_EXT_shader_non_constant_global_initializers
+#error GL_EXT_shader_non_constant_global_initializers is not defined
+#endif
+
+uniform float nondeterministic_uniform;
+
+float nonConstInitializer();
+
+float nonConstGlobal = nonConstInitializer();
+float sideEffectGlobal = 0.0;
+
+float nonConstInitializer() {
+    sideEffectGlobal = 1.0;
+    return nondeterministic_uniform;
+}
+
+void main()
+{
+    fragColor = vec4(nondeterministic_uniform, nonConstGlobal, sideEffectGlobal, 1.0);
+}
+)";
+
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), fragSrc);
+    EXPECT_GL_NO_ERROR();
+
+    glUseProgram(program);
+    glUniform1f(glGetUniformLocation(program, "nondeterministic_uniform"), 1.0f);
+    ASSERT_GL_NO_ERROR();
+
+    draw(program);
+    EXPECT_GL_NO_ERROR();
+
+    EXPECT_PIXEL_COLOR_EQ(64, 64, GLColor::white);
+}
+
+ANGLE_INSTANTIATE_TEST_ES3(ShaderNonConstGlobalInitializerTest);
\ No newline at end of file
diff --git a/src/tests/gl_tests/ShaderStorageBufferTest.cpp b/src/tests/gl_tests/ShaderStorageBufferTest.cpp
index d73a1b1..b2472ad 100644
--- a/src/tests/gl_tests/ShaderStorageBufferTest.cpp
+++ b/src/tests/gl_tests/ShaderStorageBufferTest.cpp
@@ -2258,6 +2258,106 @@
     EXPECT_GL_NO_ERROR();
 }
 
+// Verify the size of the buffer with unsized struct array is calculated correctly
+TEST_P(ShaderStorageBufferTest31, BigStructUnsizedStructArraySize)
+{
+    // TODO(http://anglebug.com/3596)
+    ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsOpenGL());
+
+    constexpr char kComputeShaderSource[] =
+        R"(#version 310 es
+layout (local_size_x=1) in;
+
+struct S
+{
+    mat4 m;     // 4 vec4 = 16 floats
+    vec4 a[10]; // 10 vec4 = 40 floats
+};
+
+layout(binding=0) buffer B
+{
+    vec4 precedingMember;               // 4 floats
+    S precedingMemberUnsizedArray[];    // 56 floats
+} b;
+
+void main()
+{
+    if (false)
+    {
+        b.precedingMember = vec4(1.0, 1.0, 1.0, 1.0);
+    }
+}
+)";
+
+    ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
+    EXPECT_GL_NO_ERROR();
+
+    glUseProgram(program);
+    glDispatchCompute(1, 1, 1);
+    EXPECT_GL_NO_ERROR();
+
+    GLuint resourceIndex = glGetProgramResourceIndex(program, GL_SHADER_STORAGE_BLOCK, "B");
+    EXPECT_GL_NO_ERROR();
+    EXPECT_NE(resourceIndex, 0xFFFFFFFF);
+
+    GLenum property = GL_BUFFER_DATA_SIZE;
+    GLint queryData = -1;
+    glGetProgramResourceiv(program, GL_SHADER_STORAGE_BLOCK, resourceIndex, 1, &property, 1,
+                           nullptr, &queryData);
+    EXPECT_GL_NO_ERROR();
+
+    // 60 * sizeof(float) = 240
+    // Vulkan rounds up to the required buffer alignment, so >= 240
+    EXPECT_GE(queryData, 240);
+}
+
+// Verify the size of the buffer with unsized float array is calculated correctly
+TEST_P(ShaderStorageBufferTest31, BigStructUnsizedFloatArraySize)
+{
+    // TODO(http://anglebug.com/3596)
+    ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsOpenGL());
+
+    constexpr char kComputeShaderSource[] =
+        R"(#version 310 es
+layout (local_size_x=1) in;
+
+layout(binding=0) buffer B
+{
+    vec4 precedingMember;                   // 4 floats
+    float precedingMemberUnsizedArray[];    // "1" float
+} b;
+
+void main()
+{
+    if (false)
+    {
+        b.precedingMember = vec4(1.0, 1.0, 1.0, 1.0);
+    }
+}
+)";
+
+    ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
+    EXPECT_GL_NO_ERROR();
+
+    glUseProgram(program);
+    glDispatchCompute(1, 1, 1);
+    EXPECT_GL_NO_ERROR();
+
+    GLuint resourceIndex = glGetProgramResourceIndex(program, GL_SHADER_STORAGE_BLOCK, "B");
+    EXPECT_GL_NO_ERROR();
+    EXPECT_NE(resourceIndex, 0xFFFFFFFF);
+
+    GLenum property = GL_BUFFER_DATA_SIZE;
+    GLint queryData = -1;
+    glGetProgramResourceiv(program, GL_SHADER_STORAGE_BLOCK, resourceIndex, 1, &property, 1,
+                           nullptr, &queryData);
+    EXPECT_GL_NO_ERROR();
+
+    // 5 * sizeof(float) = 20
+    // Vulkan rounds up to the required buffer alignment, so >= 20
+    EXPECT_GE(queryData, 20);
+}
+
 ANGLE_INSTANTIATE_TEST_ES31(ShaderStorageBufferTest31);
 
 }  // namespace
diff --git a/src/tests/gl_tests/SimpleOperationTest.cpp b/src/tests/gl_tests/SimpleOperationTest.cpp
index 1d8c360..274e1a7 100644
--- a/src/tests/gl_tests/SimpleOperationTest.cpp
+++ b/src/tests/gl_tests/SimpleOperationTest.cpp
@@ -372,7 +372,7 @@
 
     ASSERT_GL_NO_ERROR();
 
-    for (auto x = 0; x < getWindowWidth(); x++)
+    for (int x = 0; x < getWindowWidth(); x++)
     {
         EXPECT_PIXEL_COLOR_EQ(x, x, GLColor::green);
     }
diff --git a/src/tests/gl_tests/StateChangeTest.cpp b/src/tests/gl_tests/StateChangeTest.cpp
index 254f8e6..452d932 100644
--- a/src/tests/gl_tests/StateChangeTest.cpp
+++ b/src/tests/gl_tests/StateChangeTest.cpp
@@ -730,29 +730,26 @@
     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mRenderbuffer);
 
     // Explictly check FBO status sync in some versions of ANGLE no_error skips FBO checks.
-    ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+    ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
 
     // Draw with red to the FBO.
-    GLColor red(255, 0, 0, 255);
-    setUniformColor(red);
+    setUniformColor(GLColor::red);
     drawQuad(mProgram, "position", 0.5f);
-    EXPECT_PIXEL_COLOR_EQ(0, 0, red);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
 
     // Recreate the renderbuffer and clear to green.
     glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 32, 32);
     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
     glClear(GL_COLOR_BUFFER_BIT);
-    GLColor green(0, 255, 0, 255);
-    EXPECT_PIXEL_COLOR_EQ(0, 0, green);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
 
     // Explictly check FBO status sync in some versions of ANGLE no_error skips FBO checks.
-    ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+    ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
 
     // Verify drawing blue gives blue. This covers the FBO sync with D3D dirty bits.
-    GLColor blue(0, 0, 255, 255);
-    setUniformColor(blue);
+    setUniformColor(GLColor::blue);
     drawQuad(mProgram, "position", 0.5f);
-    EXPECT_PIXEL_COLOR_EQ(0, 0, blue);
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
 
     EXPECT_GL_NO_ERROR();
 }
@@ -3981,6 +3978,9 @@
 {
     ANGLE_SKIP_TEST_IF(IsAMD() && IsOSX());
 
+    // TODO(anglebug.com/4533) This fails after the upgrade to the 26.20.100.7870 driver.
+    ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsVulkan());
+
     constexpr char kFS[] = R"(#version 300 es
 precision mediump float;
 uniform block { vec4 color; };
diff --git a/src/tests/gl_tests/TextureTest.cpp b/src/tests/gl_tests/TextureTest.cpp
index 46d866b..32993d6 100644
--- a/src/tests/gl_tests/TextureTest.cpp
+++ b/src/tests/gl_tests/TextureTest.cpp
@@ -1448,6 +1448,24 @@
     GLuint mPBO;
 };
 
+class ETC1CompressedTextureTest : public Texture2DTest
+{
+  protected:
+    ETC1CompressedTextureTest() : Texture2DTest() {}
+
+    void testSetUp() override
+    {
+        TexCoordDrawTest::testSetUp();
+        glGenTextures(1, &mTexture2D);
+        glBindTexture(GL_TEXTURE_2D, mTexture2D);
+        EXPECT_GL_NO_ERROR();
+
+        setUpProgram();
+    }
+
+    void testTearDown() override { Texture2DTest::testTearDown(); }
+};
+
 TEST_P(Texture2DTest, NegativeAPISubImage)
 {
     glBindTexture(GL_TEXTURE_2D, mTexture2D);
@@ -3998,6 +4016,12 @@
 // Test rendering with maximum combined texture units.
 TEST_P(TextureLimitsTest, MaxCombinedTextures)
 {
+    // TODO(timvp): http://anglebug.com/3570
+    // Currently only fails on SwiftShader but we don't have an IsSwiftShader().
+    // max per-stage sampled image bindings count (32) exceeds device
+    // maxPerStageDescriptorSampledImages limit (16)
+    ANGLE_SKIP_TEST_IF(IsVulkan());
+
     GLint vertexTextures = mMaxVertexTextures;
 
     if (vertexTextures + mMaxFragmentTextures > mMaxCombinedTextures)
@@ -6077,6 +6101,50 @@
     ASSERT_GL_NO_ERROR();
 }
 
+// Test using ETC1_RGB8 with subimage updates
+TEST_P(ETC1CompressedTextureTest, ETC1CompressedSubImage)
+{
+    // ETC texture formats are not supported on Mac OpenGL. http://anglebug.com/3853
+    ANGLE_SKIP_TEST_IF(IsOSX() && IsDesktopOpenGL());
+
+    ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
+                       !IsGLExtensionEnabled("GL_EXT_texture_storage"));
+    ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_compressed_ETC1_RGB8_sub_texture"));
+
+    const GLuint width  = 4u;
+    const GLuint height = 4u;
+
+    setWindowWidth(width);
+    setWindowHeight(height);
+
+    // Setup primary Texture
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+
+    if (getClientMajorVersion() < 3)
+    {
+        glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_ETC1_RGB8_OES, width, height);
+    }
+    else
+    {
+        glTexStorage2D(GL_TEXTURE_2D, 1, GL_ETC1_RGB8_OES, width, height);
+    }
+    ASSERT_GL_NO_ERROR();
+
+    // Populate a subimage of the texture
+    glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_ETC1_RGB8_OES,
+                              width * height / 2u, kCompressedImageETC2);
+    ASSERT_GL_NO_ERROR();
+
+    // Render and ensure we get red
+    glUseProgram(mProgram);
+    drawQuad(mProgram, "position", 0.5f);
+    ASSERT_GL_NO_ERROR();
+
+    EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::red);
+    ASSERT_GL_NO_ERROR();
+}
+
 // Use this to select which configurations (e.g. which renderer, which GLES major version) these
 // tests should be run against.
 ANGLE_INSTANTIATE_TEST_ES2(Texture2DTest);
@@ -6116,5 +6184,6 @@
 ANGLE_INSTANTIATE_TEST_ES3(Texture3DIntegerTestES3);
 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(Texture2DDepthTest);
 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(PBOCompressedTextureTest);
+ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(ETC1CompressedTextureTest);
 
 }  // anonymous namespace
diff --git a/src/tests/gl_tests/TransformFeedbackTest.cpp b/src/tests/gl_tests/TransformFeedbackTest.cpp
index 1a1d54f..6d3c67b 100644
--- a/src/tests/gl_tests/TransformFeedbackTest.cpp
+++ b/src/tests/gl_tests/TransformFeedbackTest.cpp
@@ -199,6 +199,9 @@
 // afterward.
 TEST_P(TransformFeedbackTest, RecordAndDraw)
 {
+    // TODO(anglebug.com/4533) This fails after the upgrade to the 26.20.100.7870 driver.
+    ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsVulkan());
+
     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
     glClear(GL_COLOR_BUFFER_BIT);
 
@@ -391,6 +394,9 @@
 // Test that we can capture varyings only used in the vertex shader.
 TEST_P(TransformFeedbackTest, VertexOnly)
 {
+    // TODO(anglebug.com/4533) This fails after the upgrade to the 26.20.100.7870 driver.
+    ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsVulkan());
+
     constexpr char kVS[] =
         "#version 300 es\n"
         "in vec2 position;\n"
@@ -720,6 +726,9 @@
 // Test that when two vec2s are packed into the same register, we can still capture both of them.
 TEST_P(TransformFeedbackTest, PackingBug)
 {
+    // TODO(anglebug.com/4533) This fails after the upgrade to the 26.20.100.7870 driver.
+    ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsVulkan());
+
     // TODO(jmadill): With points and rasterizer discard?
     constexpr char kVS[] =
         "#version 300 es\n"
@@ -849,6 +858,9 @@
 // Test an edge case where two varyings are unreferenced in the frag shader.
 TEST_P(TransformFeedbackTest, TwoUnreferencedInFragShader)
 {
+    // TODO(anglebug.com/4533) This fails after the upgrade to the 26.20.100.7870 driver.
+    ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsVulkan());
+
     // TODO(jmadill): With points and rasterizer discard?
     constexpr char kVS[] =
         "#version 300 es\n"
@@ -918,6 +930,9 @@
 
     ANGLE_SKIP_TEST_IF((IsNexus5X() || IsNexus6P()) && IsOpenGLES());
 
+    // TODO(anglebug.com/4533) This fails after the upgrade to the 26.20.100.7870 driver.
+    ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsVulkan());
+
     constexpr char kVS[] =
         "#version 300 es\n"
         "in vec4 position;\n"
@@ -1415,6 +1430,9 @@
 // GLSL ES.
 TEST_P(TransformFeedbackTest, VaryingReservedOpenGLName)
 {
+    // TODO(anglebug.com/4533) This fails after the upgrade to the 26.20.100.7870 driver.
+    ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsVulkan());
+
     constexpr char kVS[] =
         "#version 300 es\n"
         "in vec3 position;\n"
diff --git a/src/tests/gl_tests/UniformBufferTest.cpp b/src/tests/gl_tests/UniformBufferTest.cpp
index 6de756b..02e9bfe 100644
--- a/src/tests/gl_tests/UniformBufferTest.cpp
+++ b/src/tests/gl_tests/UniformBufferTest.cpp
@@ -1744,6 +1744,252 @@
     }
 }
 
+// Test instance uniform buffer with large struct array member, where the struct
+// itself contains a mat4 member.
+TEST_P(UniformBufferTest, InstanceUniformBlockWithOneLargeStructArray)
+{
+    GLint64 maxUniformBlockSize;
+    glGetInteger64v(GL_MAX_UNIFORM_BLOCK_SIZE, &maxUniformBlockSize);
+    std::ostringstream stream;
+    GLuint arraySize;
+    // Ensure that shader uniform block do not exceed MAX_UNIFORM_BLOCK_SIZE limit.
+    if (maxUniformBlockSize >= 16384 && maxUniformBlockSize < 32768)
+    {
+        arraySize = 128;
+        stream << "const uint arraySize = 128u;\n"
+                  "const uint divisor1 = 128u;\n"
+                  "const uint divisor2 = 32u;\n";
+    }
+    else if (maxUniformBlockSize >= 32768 && maxUniformBlockSize < 65536)
+    {
+        arraySize = 256;
+        stream << "const uint arraySize = 256u;\n"
+                  "const uint divisor1 = 64u;\n"
+                  "const uint divisor2 = 16u;\n";
+    }
+    else
+    {
+        arraySize = 512;
+        stream << "const uint arraySize = 512u;\n"
+                  "const uint divisor1 = 32u;\n"
+                  "const uint divisor2 = 8u;\n";
+    }
+
+    const std::string &kFS =
+        "#version 300 es\n"
+        "precision highp float;\n" +
+        stream.str() +
+        "out vec4 my_FragColor;\n"
+        "struct S { mat4 color;};\n"
+        "layout(std140) uniform buffer { S s[arraySize]; } instance;\n"
+        "void main()\n"
+        "{\n"
+        "    uvec2 coord = uvec2(floor(gl_FragCoord.xy));\n"
+        "    uint index = coord.x +  coord.y * 128u;\n"
+        "    uint index_x = index / divisor1;\n"
+        "    uint index_y = (index % divisor1) / divisor2;\n"
+        "    my_FragColor = instance.s[index_x].color[index_y];\n"
+        "}\n";
+
+    GLint blockSize;
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS.c_str());
+    GLint uniformBufferIndex = glGetUniformBlockIndex(program, "buffer");
+    glGetActiveUniformBlockiv(program, uniformBufferIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize);
+
+    glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
+    glBufferData(GL_UNIFORM_BUFFER, blockSize, nullptr, GL_STATIC_DRAW);
+
+    glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
+    glUniformBlockBinding(program, uniformBufferIndex, 0);
+
+    const GLuint kVectorPerMat   = 4;
+    const GLuint kFloatPerVector = 4;
+    GLuint kVectorCount          = arraySize * kVectorPerMat;
+    GLuint kFloatCount           = kVectorCount * kFloatPerVector;
+    std::vector<GLfloat> floatData(kFloatCount, 0.0f);
+    const GLuint kPositionCount                    = 12;
+    unsigned int positionToTest[kPositionCount][2] = {{0, 0},  {75, 0},  {98, 13},  {31, 31},
+                                                      {0, 32}, {65, 33}, {23, 54},  {63, 63},
+                                                      {0, 64}, {43, 86}, {53, 100}, {127, 127}};
+
+    for (GLuint i = 0; i < kVectorCount; i++)
+    {
+        floatData[4 * i + 2] = 1.0f;
+        floatData[4 * i + 3] = 1.0f;
+    }
+    glBufferSubData(GL_UNIFORM_BUFFER, 0, kFloatCount * sizeof(GLfloat), floatData.data());
+    drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
+    for (GLuint i = 0; i < kPositionCount; i++)
+    {
+        EXPECT_PIXEL_COLOR_EQ(positionToTest[i][0], positionToTest[i][1], GLColor::blue);
+    }
+
+    for (GLuint i = 0; i < kVectorCount; i++)
+    {
+        floatData[4 * i + 1] = 1.0f;
+        floatData[4 * i + 2] = 0.0f;
+    }
+    glBufferSubData(GL_UNIFORM_BUFFER, 0, kFloatCount * sizeof(GLfloat), floatData.data());
+    drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
+    for (GLuint i = 0; i < kPositionCount; i++)
+    {
+        EXPECT_PIXEL_COLOR_EQ(positionToTest[i][0], positionToTest[i][1], GLColor::green);
+    }
+
+    for (GLuint i = kVectorCount / 4; i < kVectorCount / 2; i++)
+    {
+        floatData[4 * i]     = 1.0f;
+        floatData[4 * i + 1] = 0.0f;
+    }
+    glBufferSubData(GL_UNIFORM_BUFFER, 0, kFloatCount * sizeof(GLfloat), floatData.data());
+    drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
+    for (GLuint i = 0; i < kPositionCount; i++)
+    {
+        if (positionToTest[i][1] > 31 && positionToTest[i][1] < 64)
+        {
+            EXPECT_PIXEL_COLOR_EQ(positionToTest[i][0], positionToTest[i][1], GLColor::red);
+        }
+        else
+        {
+            EXPECT_PIXEL_COLOR_EQ(positionToTest[i][0], positionToTest[i][1], GLColor::green);
+        }
+    }
+}
+
+// Test instance array uniform buffer with large struct array member, where the
+// struct itself contains a mat4 member.
+TEST_P(UniformBufferTest, InstanceArrayUniformBlockWithOneLargeStructArray)
+{
+    GLint64 maxUniformBlockSize;
+    glGetInteger64v(GL_MAX_UNIFORM_BLOCK_SIZE, &maxUniformBlockSize);
+    std::ostringstream stream;
+    GLuint arraySize;
+    // Ensure that shader uniform block do not exceed MAX_UNIFORM_BLOCK_SIZE limit.
+    if (maxUniformBlockSize >= 16384 && maxUniformBlockSize < 32768)
+    {
+        arraySize = 128;
+        stream << "const uint arraySize = 128u;\n"
+                  "const uint divisor1 = 128u;\n"
+                  "const uint divisor2 = 32u;\n";
+    }
+    else if (maxUniformBlockSize >= 32768 && maxUniformBlockSize < 65536)
+    {
+        arraySize = 256;
+        stream << "const uint arraySize = 256u;\n"
+                  "const uint divisor1 = 64u;\n"
+                  "const uint divisor2 = 16u;\n";
+    }
+    else
+    {
+        arraySize = 512;
+        stream << "const uint arraySize = 512u;\n"
+                  "const uint divisor1 = 32u;\n"
+                  "const uint divisor2 = 8u;\n";
+    }
+
+    const std::string &kFS =
+        "#version 300 es\n"
+        "precision highp float;\n" +
+        stream.str() +
+        "out vec4 my_FragColor;\n"
+        "struct S { mat4 color;};\n"
+        "layout(std140) uniform buffer { S s[arraySize]; } instance[2];\n"
+        "void main()\n"
+        "{\n"
+        "    uvec2 coord = uvec2(floor(gl_FragCoord.xy));\n"
+        "    uint index = coord.x +  coord.y * 128u;\n"
+        "    uint index_x = index / divisor1;\n"
+        "    uint index_y = (index % divisor1) / divisor2;\n"
+        "    my_FragColor = instance[0].s[index_x].color[index_y] + "
+        "instance[1].s[index_x].color[index_y];\n"
+        "}\n";
+
+    GLint blockSize0, blockSize1;
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS.c_str());
+    GLint uniformBufferIndex0 = glGetUniformBlockIndex(program, "buffer[0]");
+    GLint uniformBufferIndex1 = glGetUniformBlockIndex(program, "buffer[1]");
+    glGetActiveUniformBlockiv(program, uniformBufferIndex0, GL_UNIFORM_BLOCK_DATA_SIZE,
+                              &blockSize0);
+    glGetActiveUniformBlockiv(program, uniformBufferIndex1, GL_UNIFORM_BLOCK_DATA_SIZE,
+                              &blockSize1);
+
+    glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
+    glBufferData(GL_UNIFORM_BUFFER, blockSize0, nullptr, GL_STATIC_DRAW);
+
+    glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
+    glUniformBlockBinding(program, uniformBufferIndex0, 0);
+
+    const GLuint kVectorPerMat   = 4;
+    const GLuint kFloatPerVector = 4;
+    GLuint kVectorCount          = arraySize * kVectorPerMat;
+    GLuint kFloatCount           = kVectorCount * kFloatPerVector;
+    std::vector<GLfloat> floatData0(kFloatCount, 0.0f);
+    std::vector<GLfloat> floatData1(kFloatCount, 0.0f);
+    const GLuint kPositionCount                    = 12;
+    unsigned int positionToTest[kPositionCount][2] = {{0, 0},  {75, 0},  {98, 13},  {31, 31},
+                                                      {0, 32}, {65, 33}, {23, 54},  {63, 63},
+                                                      {0, 64}, {43, 86}, {53, 100}, {127, 127}};
+
+    for (GLuint i = 0; i < kVectorCount; i++)
+    {
+        floatData0[4 * i + 2] = 1.0f;
+        floatData0[4 * i + 3] = 1.0f;
+    }
+    glBufferSubData(GL_UNIFORM_BUFFER, 0, kFloatCount * sizeof(GLfloat), floatData0.data());
+
+    GLBuffer uniformBuffer1;
+    glBindBuffer(GL_UNIFORM_BUFFER, uniformBuffer1);
+    glBufferData(GL_UNIFORM_BUFFER, blockSize1, nullptr, GL_STATIC_DRAW);
+
+    glBindBufferBase(GL_UNIFORM_BUFFER, 1, uniformBuffer1);
+    glUniformBlockBinding(program, uniformBufferIndex0, 1);
+
+    for (GLuint i = 0; i < kVectorCount; i++)
+    {
+        floatData1[4 * i + 1] = 1.0f;
+    }
+    glBufferSubData(GL_UNIFORM_BUFFER, 0, kFloatCount * sizeof(GLfloat), floatData1.data());
+
+    drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
+    for (GLuint i = 0; i < kPositionCount; i++)
+    {
+        EXPECT_PIXEL_COLOR_EQ(positionToTest[i][0], positionToTest[i][1], GLColor::cyan);
+    }
+
+    glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
+    for (GLuint i = 0; i < kVectorCount; i++)
+    {
+        floatData0[4 * i]     = 1.0f;
+        floatData0[4 * i + 2] = 0.0f;
+    }
+    glBufferSubData(GL_UNIFORM_BUFFER, 0, kFloatCount * sizeof(GLfloat), floatData0.data());
+    drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
+    for (GLuint i = 0; i < kPositionCount; i++)
+    {
+        EXPECT_PIXEL_COLOR_EQ(positionToTest[i][0], positionToTest[i][1], GLColor::yellow);
+    }
+
+    glBindBuffer(GL_UNIFORM_BUFFER, uniformBuffer1);
+    for (GLuint i = kVectorCount / 4; i < kVectorCount / 2; i++)
+    {
+        floatData1[4 * i + 2] = 1.0f;
+        floatData1[4 * i + 1] = 0.0f;
+    }
+    glBufferSubData(GL_UNIFORM_BUFFER, 0, kFloatCount * sizeof(GLfloat), floatData1.data());
+    drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
+    for (GLuint i = 0; i < kPositionCount; i++)
+    {
+        if (positionToTest[i][1] > 31 && positionToTest[i][1] < 64)
+        {
+            EXPECT_PIXEL_COLOR_EQ(positionToTest[i][0], positionToTest[i][1], GLColor::magenta);
+        }
+        else
+        {
+            EXPECT_PIXEL_COLOR_EQ(positionToTest[i][0], positionToTest[i][1], GLColor::yellow);
+        }
+    }
+}
+
 // Test uniform buffer with large struct array member, where the struct itself contains
 // a mat4 member and a float member.
 TEST_P(UniformBufferTest, UniformBlockWithOneLargeMixStructArray)
@@ -2151,6 +2397,126 @@
     }
 }
 
+// Test two uniform blocks share the same uniform buffer. On D3D backend, one uniform
+// block with a large array member will be translated to StructuredBuffer, and the
+// other uniform block will be translated to cbuffer, this case verifies that update
+// buffer data correctly.
+TEST_P(UniformBufferTest, UniformBlocksSharedSameUniformBuffer)
+{
+    ANGLE_SKIP_TEST_IF(IsIntel() && IsOSX());
+
+    GLint64 maxUniformBlockSize;
+    glGetInteger64v(GL_MAX_UNIFORM_BLOCK_SIZE, &maxUniformBlockSize);
+    std::ostringstream stream;
+    GLuint arraySize;
+    // Ensure that shader uniform block do not exceed MAX_UNIFORM_BLOCK_SIZE limit.
+    if (maxUniformBlockSize >= 16384 && maxUniformBlockSize < 32768)
+    {
+        arraySize = 128;
+        stream << "const uint arraySize = 128u;\n"
+                  "const uint divisor1 = 128u;\n"
+                  "const uint divisor2 = 32u;\n";
+    }
+    else if (maxUniformBlockSize >= 32768 && maxUniformBlockSize < 65536)
+    {
+        arraySize = 256;
+        stream << "const uint arraySize = 256u;\n"
+                  "const uint divisor1 = 64u;\n"
+                  "const uint divisor2 = 16u;\n";
+    }
+    else
+    {
+        arraySize = 512;
+        stream << "const uint arraySize = 512u;\n"
+                  "const uint divisor1 = 32u;\n"
+                  "const uint divisor2 = 8u;\n";
+    }
+
+    const std::string &kFS =
+        "#version 300 es\n"
+        "precision highp float;\n" +
+        stream.str() +
+        "out vec4 my_FragColor;\n"
+        "struct S { mat4 color;};\n"
+        "layout(std140) uniform buffer { S s[arraySize]; };\n"
+        "layout(std140) uniform buffer1 { vec4 factor; };\n"
+        "void main()\n"
+        "{\n"
+        "    uvec2 coord = uvec2(floor(gl_FragCoord.xy));\n"
+        "    uint index = coord.x +  coord.y * 128u;\n"
+        "    uint index_x = index / divisor1;\n"
+        "    uint index_y = (index % divisor1) / divisor2;\n"
+        "    my_FragColor = s[index_x].color[index_y] + factor;\n"
+        "}\n";
+
+    GLint blockSize;
+    ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS.c_str());
+    GLint uniformBufferIndex = glGetUniformBlockIndex(program, "buffer");
+    glGetActiveUniformBlockiv(program, uniformBufferIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize);
+    GLint uniformBufferIndex1 = glGetUniformBlockIndex(program, "buffer1");
+    GLint alignment;
+    glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &alignment);
+    while (alignment >= 0 && alignment < 16)
+    {
+        alignment += alignment;
+    }
+
+    glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
+    glBufferData(GL_UNIFORM_BUFFER, alignment + blockSize, nullptr, GL_STATIC_DRAW);
+
+    const GLuint kVectorPerMat   = 4;
+    const GLuint kFloatPerVector = 4;
+    GLuint kVectorCount          = arraySize * kVectorPerMat;
+    GLuint kFloatCount           = kVectorCount * kFloatPerVector;
+    std::vector<GLfloat> floatData(kFloatCount, 0.0f);
+    std::vector<GLfloat> floatData1(4, 0.0f);
+    const GLuint kPositionCount                    = 12;
+    unsigned int positionToTest[kPositionCount][2] = {{0, 0},  {75, 0},  {98, 13},  {31, 31},
+                                                      {0, 32}, {65, 33}, {23, 54},  {63, 63},
+                                                      {0, 64}, {43, 86}, {53, 100}, {127, 127}};
+
+    for (GLuint i = 0; i < kVectorCount; i++)
+    {
+        floatData[4 * i + 2] = 0.5f;
+        floatData[4 * i + 3] = 0.5f;
+    }
+    floatData1[0] = 1.0f;
+    floatData1[1] = 0.0f;
+    floatData1[2] = 0.5f;
+    floatData1[3] = 0.5f;
+
+    glBindBufferRange(GL_UNIFORM_BUFFER, 0, mUniformBuffer, 0, 4 * sizeof(float));
+    glUniformBlockBinding(program, uniformBufferIndex1, 0);
+    glBindBufferRange(GL_UNIFORM_BUFFER, 1, mUniformBuffer, alignment,
+                      kVectorCount * kFloatPerVector * sizeof(float));
+    glUniformBlockBinding(program, uniformBufferIndex, 1);
+
+    glBufferSubData(GL_UNIFORM_BUFFER, alignment, kFloatCount * sizeof(GLfloat), floatData.data());
+    glBufferSubData(GL_UNIFORM_BUFFER, 0, 4 * sizeof(GLfloat), floatData1.data());
+    drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
+    for (GLuint i = 0; i < kPositionCount; i++)
+    {
+        EXPECT_PIXEL_COLOR_EQ(positionToTest[i][0], positionToTest[i][1], GLColor::magenta);
+    }
+
+    for (GLuint i = 0; i < kVectorCount; i++)
+    {
+        floatData[4 * i + 1] = 0.5f;
+        floatData[4 * i + 2] = 0.0f;
+    }
+    floatData1[0] = 0.0f;
+    floatData1[1] = 0.5f;
+    floatData1[2] = 0.0f;
+    floatData1[3] = 0.5f;
+    glBufferSubData(GL_UNIFORM_BUFFER, alignment, kFloatCount * sizeof(GLfloat), floatData.data());
+    glBufferSubData(GL_UNIFORM_BUFFER, 0, 4 * sizeof(GLfloat), floatData1.data());
+    drawQuad(program.get(), essl3_shaders::PositionAttrib(), 0.5f);
+    for (GLuint i = 0; i < kPositionCount; i++)
+    {
+        EXPECT_PIXEL_COLOR_EQ(positionToTest[i][0], positionToTest[i][1], GLColor::green);
+    }
+}
+
 // Test a uniform block where an array of row-major matrices is dynamically indexed.
 TEST_P(UniformBufferTest, Std140UniformBlockWithDynamicallyIndexedRowMajorArray)
 {
diff --git a/src/tests/gl_tests/VulkanExternalImageTest.cpp b/src/tests/gl_tests/VulkanExternalImageTest.cpp
index ccadd35..a69338a 100644
--- a/src/tests/gl_tests/VulkanExternalImageTest.cpp
+++ b/src/tests/gl_tests/VulkanExternalImageTest.cpp
@@ -111,6 +111,13 @@
     {
         GLMemoryObject memoryObject;
         glImportMemoryFdEXT(memoryObject, deviceMemorySize, GL_HANDLE_TYPE_OPAQUE_FD_EXT, fd);
+
+        // Test that after calling glImportMemoryFdEXT, the parameters of the memory object cannot
+        // be changed
+        GLint dedicatedMemory = GL_TRUE;
+        glMemoryObjectParameterivEXT(memoryObject, GL_DEDICATED_MEMORY_OBJECT_EXT,
+                                     &dedicatedMemory);
+        EXPECT_GL_ERROR(GL_INVALID_OPERATION);
     }
 
     EXPECT_GL_NO_ERROR();
diff --git a/src/tests/gl_tests/WebGLCompatibilityTest.cpp b/src/tests/gl_tests/WebGLCompatibilityTest.cpp
index fd265e5..cac355c 100644
--- a/src/tests/gl_tests/WebGLCompatibilityTest.cpp
+++ b/src/tests/gl_tests/WebGLCompatibilityTest.cpp
@@ -2370,6 +2370,93 @@
     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
 }
 
+// Multi-context uses of textures should not cause rendering feedback loops.
+TEST_P(WebGLCompatibilityTest, MultiContextNoRenderingFeedbackLoops)
+{
+    constexpr char kUnusedTextureVS[] =
+        R"(attribute vec4 a_position;
+varying vec2 v_texCoord;
+void main() {
+    gl_Position = a_position;
+    v_texCoord = (a_position.xy * 0.5) + 0.5;
+})";
+
+    constexpr char kUnusedTextureFS[] =
+        R"(precision mediump float;
+varying vec2 v_texCoord;
+uniform sampler2D u_texture;
+void main() {
+    gl_FragColor = texture2D(u_texture, v_texCoord).rgba;
+})";
+
+    ANGLE_GL_PROGRAM(unusedProgram, kUnusedTextureVS, kUnusedTextureFS);
+
+    glUseProgram(unusedProgram.get());
+    GLint uniformLoc = glGetUniformLocation(unusedProgram.get(), "u_texture");
+    ASSERT_NE(-1, uniformLoc);
+    glUniform1i(uniformLoc, 0);
+
+    GLTexture texture;
+    FillTexture2D(texture.get(), 1, 1, GLColor::red, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
+    glBindTexture(GL_TEXTURE_2D, texture.get());
+    // Note that _texture_ is still bound to GL_TEXTURE_2D in this context at this point.
+
+    EGLWindow *window          = getEGLWindow();
+    EGLDisplay display         = window->getDisplay();
+    EGLConfig config           = window->getConfig();
+    EGLSurface surface         = window->getSurface();
+    EGLint contextAttributes[] = {
+        EGL_CONTEXT_MAJOR_VERSION_KHR,
+        GetParam().majorVersion,
+        EGL_CONTEXT_MINOR_VERSION_KHR,
+        GetParam().minorVersion,
+        EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE,
+        EGL_TRUE,
+        EGL_NONE,
+    };
+    auto context1 = eglGetCurrentContext();
+    // Create context2, sharing resources with context1.
+    auto context2 = eglCreateContext(display, config, context1, contextAttributes);
+    ASSERT_NE(context2, EGL_NO_CONTEXT);
+    eglMakeCurrent(display, surface, surface, context2);
+
+    constexpr char kVS[] =
+        R"(attribute vec4 a_position;
+void main() {
+    gl_Position = a_position;
+})";
+
+    constexpr char kFS[] =
+        R"(precision mediump float;
+void main() {
+    gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
+})";
+
+    ANGLE_GL_PROGRAM(program, kVS, kFS);
+    glUseProgram(program.get());
+
+    ASSERT_GL_NO_ERROR();
+
+    // Render to the texture in context2.
+    GLFramebuffer framebuffer;
+    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
+    // Texture is still a valid name in context2.
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
+    ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
+    // There is no rendering feedback loop at this point.
+
+    glDisable(GL_BLEND);
+    glDisable(GL_DEPTH_TEST);
+    ASSERT_GL_NO_ERROR();
+
+    drawQuad(program.get(), "a_position", 0.5f, 1.0f, true);
+    ASSERT_GL_NO_ERROR();
+    EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
+
+    eglMakeCurrent(display, surface, surface, context1);
+    eglDestroyContext(display, context2);
+}
+
 // Test for the max draw buffers and color attachments.
 TEST_P(WebGLCompatibilityTest, MaxDrawBuffersAttachmentPoints)
 {
@@ -4293,13 +4380,13 @@
         GLFramebuffer readFBO;
         glBindFramebuffer(GL_FRAMEBUFFER, readFBO);
 
-        for (int i = 0; i < 4; ++i)
+        for (int attachmentIndex = 0; attachmentIndex < 4; ++attachmentIndex)
         {
-            if (mask & (1 << i))
+            if (mask & (1 << attachmentIndex))
             {
                 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
-                                          renderbuffers[i]);
-                EXPECT_PIXEL_COLOR_EQ(0, 0, color);
+                                          renderbuffers[attachmentIndex]);
+                EXPECT_PIXEL_COLOR_EQ(0, 0, color) << "attachment " << attachmentIndex;
             }
         }
         ASSERT_GL_NO_ERROR();
@@ -4669,8 +4756,9 @@
 // Test enabling GL_OES_compressed_ETC1_RGB8_texture
 TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionETC1)
 {
-    validateCompressedTexImageExtensionFormat(GL_ETC1_RGB8_OES, 4, 4, 8,
-                                              "GL_OES_compressed_ETC1_RGB8_texture", false);
+    validateCompressedTexImageExtensionFormat(
+        GL_ETC1_RGB8_OES, 4, 4, 8, "GL_OES_compressed_ETC1_RGB8_texture",
+        IsGLExtensionEnabled("GL_EXT_compressed_ETC1_RGB8_sub_texture"));
 }
 
 // Test enabling GL_ANGLE_lossy_etc_decode
diff --git a/src/tests/gles1_conformance_tests/CovglTests.cpp b/src/tests/gles1_conformance_tests/CovglTests.cpp
new file mode 100644
index 0000000..9846018
--- /dev/null
+++ b/src/tests/gles1_conformance_tests/CovglTests.cpp
@@ -0,0 +1,604 @@
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// CovglTests.cpp:
+//   GLES1 conformance covgl tests.
+//   Function prototypes taken from tproto.h and turned into gtest tests using a macro.
+//
+
+#include "test_utils/ANGLETest.h"
+#include "test_utils/gl_raii.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(GL_OES_VERSION_1_1) && defined(GL_VERSION_ES_CM_1_1) && defined(GL_VERSION_ES_CL_1_1)
+#    if GL_VERSION_ES_CM_1_1 || GL_VERSION_ES_CL_1_1
+#        define GL_OES_VERSION_1_1
+#    endif
+#endif
+
+// ES 1.0
+extern void StateReset(void);
+extern void ProbeError(void (*)(void));
+extern GLboolean tkCheckExtension(const char *name);
+
+extern void CallActiveTexture(void);
+extern void CallAlphaFunc(void);
+extern void CallBlendFunc(void);
+extern void CallBindDeleteTexture(void);
+extern void CallClear(void);
+extern void CallClearColor(void);
+extern void CallClearDepth(void);
+extern void CallClearStencil(void);
+extern void CallClientActiveTexture(void);
+extern void CallColor(void);
+extern void CallColorMask(void);
+extern void CallColorPointer(void);
+extern void CallCompressedTexImage2D(void);
+extern void CallCompressedTexSubImage2D(void);
+extern void CallCopyTexImage2D(void);
+extern void CallCopyTexSubImage2D(void);
+extern void CallCullFace(void);
+extern void CallDepthFunc(void);
+extern void CallDepthMask(void);
+extern void CallDepthRange(void);
+extern void CallDrawArrays(void);
+extern void CallDrawElements(void);
+
+#ifdef GL_OES_draw_texture
+extern void CallDrawTex(void);
+#endif /* GL_OES_draw_texture */
+
+extern void CallEdgeFlag(void);
+extern void CallEnableDisable(void);
+extern void CallEnableDisableClientState(void);
+extern void CallFinish(void);
+extern void CallFlush(void);
+extern void CallFog(void);
+extern void CallFrontFace(void);
+extern void CallFrustum(void);
+extern void CallGenTextures(void);
+extern void CallGet(void);
+extern void CallGetError(void);
+extern void CallGetString(void);
+#ifdef GL_OES_VERSION_1_1
+extern void CallGetTexEnv(void);
+extern void CallGetLight(void);
+extern void CallGetMaterial(void);
+extern void CallGetClipPlane(void);
+extern void CallGetPointer(void);
+#endif /* GL_OES_VERSION_1_1 */
+
+#ifdef GL_OES_VERSION_1_1
+extern void CallGetBufferParameter(void);
+extern void CallGetTexParameter(void);
+#endif /* GL_OES_VERSION_1_1 */
+
+extern void CallHint(void);
+extern void CallLight(void);
+extern void CallLightModel(void);
+extern void CallLineWidth(void);
+extern void CallLoadIdentity(void);
+extern void CallLoadMatrix(void);
+extern void CallLogicOp(void);
+extern void CallMaterial(void);
+extern void CallMatrixMode(void);
+extern void CallMultiTexCoord(void);
+extern void CallMultMatrix(void);
+extern void CallNormal(void);
+extern void CallNormalPointer(void);
+extern void CallOrtho(void);
+extern void CallPixelStore(void);
+#ifdef GL_OES_VERSION_1_1
+extern void CallPointParameter(void);
+#endif /* GL_OES_VERSION_1_1 */
+extern void CallPointSize(void);
+extern void CallPolygonOffset(void);
+extern void CallPopMatrix(void);
+extern void CallPushMatrix(void);
+extern void CallReadPixels(void);
+extern void CallRotate(void);
+extern void CallSampleCoverage(void);
+extern void CallScale(void);
+extern void CallScissor(void);
+extern void CallShadeModel(void);
+extern void CallStencilFunc(void);
+extern void CallStencilMask(void);
+extern void CallStencilOp(void);
+#ifdef GL_OES_VERSION_1_1
+extern void CallIsTexture(void);
+extern void CallIsEnabled(void);
+#endif /* GL_OES_VERSION_1_1 */
+extern void CallTexCoord(void);
+extern void CallTexCoordPointer(void);
+extern void CallTexEnv(void);
+extern void CallTexImage2D(void);
+extern void CallTexParameter(void);
+extern void CallTexSubImage2D(void);
+extern void CallTranslate(void);
+extern void CallVertexPointer(void);
+extern void CallViewport(void);
+
+#ifdef GL_OES_VERSION_1_1
+extern void CallBindDeleteBuffer(void);
+extern void CallBufferData(void);
+extern void CallBufferSubData(void);
+extern void CallGenBuffers(void);
+extern void CallIsBuffer(void);
+extern void CallPointSizePointerOES(void);
+extern void CallClipPlane(void);
+#endif /* GL_OES_VERSION_1_1 */
+
+#ifdef GL_OES_matrix_palette
+extern void CallCurrentPaletteMatrixOES(void);
+extern void CallLoadPaletteFromModelViewMatrixOES(void);
+extern void CallMatrixIndexPointerOES(void);
+extern void CallWeightPointerOES(void);
+#endif /* GL_OES_matrix_palette */
+
+#ifdef GL_OES_query_matrix
+extern void CallQueryMatrix(void);
+#endif
+
+void ProbeEnumANGLE(void)
+{
+    ASSERT_GL_NO_ERROR();
+}
+
+#ifdef __cplusplus
+}
+
+#endif
+
+namespace angle
+{
+class GLES1CovglTest : public ANGLETest
+{
+  protected:
+    GLES1CovglTest()
+    {
+        setWindowWidth(48);
+        setWindowHeight(48);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setConfigDepthBits(24);
+        setConfigStencilBits(8);
+    }
+
+    void testSetUp() override
+    {
+        StateReset();
+        glViewport(0, 0, 48, 48);
+        glScissor(0, 0, 48, 48);
+    }
+};
+
+TEST_P(GLES1CovglTest, Get)
+{
+    ProbeError(CallGet);
+}
+
+TEST_P(GLES1CovglTest, GetError)
+{
+    ProbeError(CallGetError);
+}
+TEST_P(GLES1CovglTest, GetString)
+{
+    ProbeError(CallGetString);
+}
+
+#ifdef GL_OES_VERSION_1_1
+TEST_P(GLES1CovglTest, GetTexEnv)
+{
+    ProbeError(CallGetTexEnv);
+}
+TEST_P(GLES1CovglTest, GetLight)
+{
+    ProbeError(CallGetLight);
+}
+TEST_P(GLES1CovglTest, GetMaterial)
+{
+    ProbeError(CallGetMaterial);
+}
+TEST_P(GLES1CovglTest, GetClipPlane)
+{
+    ProbeError(CallGetClipPlane);
+}
+TEST_P(GLES1CovglTest, GetPointer)
+{
+    ProbeError(CallGetPointer);
+}
+TEST_P(GLES1CovglTest, GetTexParameter)
+{
+    ProbeError(CallGetTexParameter);
+}
+TEST_P(GLES1CovglTest, GetBufferParameter)
+{
+    ProbeError(CallGetBufferParameter);
+}
+#endif /* GL_OES_VERSION_1_1 */
+
+TEST_P(GLES1CovglTest, EnableDisable)
+{
+    ProbeError(CallEnableDisable);
+}
+
+TEST_P(GLES1CovglTest, Hint)
+{
+    ProbeError(CallHint);
+}
+
+TEST_P(GLES1CovglTest, Viewport)
+{
+    ProbeError(CallViewport);
+}
+TEST_P(GLES1CovglTest, Ortho)
+{
+    ProbeError(CallOrtho);
+}
+TEST_P(GLES1CovglTest, Frustum)
+{
+    ProbeError(CallFrustum);
+}
+TEST_P(GLES1CovglTest, Scissor)
+{
+    ProbeError(CallScissor);
+}
+
+TEST_P(GLES1CovglTest, LoadIdentity)
+{
+    ProbeError(CallLoadIdentity);
+}
+TEST_P(GLES1CovglTest, MatrixMode)
+{
+    ProbeError(CallMatrixMode);
+}
+TEST_P(GLES1CovglTest, PushMatrix)
+{
+    ProbeError(CallPushMatrix);
+}
+TEST_P(GLES1CovglTest, LoadMatrix)
+{
+    ProbeError(CallLoadMatrix);
+}
+TEST_P(GLES1CovglTest, MultMatrix)
+{
+    ProbeError(CallMultMatrix);
+}
+TEST_P(GLES1CovglTest, Rotate)
+{
+    ProbeError(CallRotate);
+}
+TEST_P(GLES1CovglTest, Scale)
+{
+    ProbeError(CallScale);
+}
+TEST_P(GLES1CovglTest, Translate)
+{
+    ProbeError(CallTranslate);
+}
+TEST_P(GLES1CovglTest, PopMatrix)
+{
+    ProbeError(CallPopMatrix);
+}
+
+TEST_P(GLES1CovglTest, Clear)
+{
+    ProbeError(CallClear);
+}
+TEST_P(GLES1CovglTest, ClearColor)
+{
+    ProbeError(CallClearColor);
+}
+TEST_P(GLES1CovglTest, ClearDepth)
+{
+    ProbeError(CallClearDepth);
+}
+TEST_P(GLES1CovglTest, ClearStencil)
+{
+    ProbeError(CallClearStencil);
+}
+
+TEST_P(GLES1CovglTest, ColorMask)
+{
+    ProbeError(CallColorMask);
+}
+TEST_P(GLES1CovglTest, Color)
+{
+    ProbeError(CallColor);
+}
+
+TEST_P(GLES1CovglTest, Normal)
+{
+    ProbeError(CallNormal);
+}
+
+TEST_P(GLES1CovglTest, AlphaFunc)
+{
+    ProbeError(CallAlphaFunc);
+}
+TEST_P(GLES1CovglTest, BlendFunc)
+{
+    ProbeError(CallBlendFunc);
+}
+TEST_P(GLES1CovglTest, DepthFunc)
+{
+    ProbeError(CallDepthFunc);
+}
+TEST_P(GLES1CovglTest, DepthMask)
+{
+    ProbeError(CallDepthMask);
+}
+TEST_P(GLES1CovglTest, DepthRange)
+{
+    ProbeError(CallDepthRange);
+}
+TEST_P(GLES1CovglTest, LogicOp)
+{
+    ProbeError(CallLogicOp);
+}
+TEST_P(GLES1CovglTest, StencilFunc)
+{
+    ProbeError(CallStencilFunc);
+}
+TEST_P(GLES1CovglTest, StencilMask)
+{
+    ProbeError(CallStencilMask);
+}
+TEST_P(GLES1CovglTest, StencilOp)
+{
+    ProbeError(CallStencilOp);
+}
+
+TEST_P(GLES1CovglTest, PixelStore)
+{
+    ProbeError(CallPixelStore);
+}
+TEST_P(GLES1CovglTest, ReadPixels)
+{
+    ProbeError(CallReadPixels);
+}
+
+TEST_P(GLES1CovglTest, Fog)
+{
+    ProbeError(CallFog);
+}
+TEST_P(GLES1CovglTest, LightModel)
+{
+    ProbeError(CallLightModel);
+}
+TEST_P(GLES1CovglTest, Light)
+{
+    ProbeError(CallLight);
+}
+TEST_P(GLES1CovglTest, Material)
+{
+    ProbeError(CallMaterial);
+}
+
+#ifdef GL_OES_VERSION_1_1
+TEST_P(GLES1CovglTest, IsTexture)
+{
+    ProbeError(CallIsTexture);
+}
+TEST_P(GLES1CovglTest, IsEnabled)
+{
+    ProbeError(CallIsEnabled);
+}
+#endif /* GL_OES_VERSION_1_1 */
+
+TEST_P(GLES1CovglTest, TexEnv)
+{
+    ProbeError(CallTexEnv);
+}
+TEST_P(GLES1CovglTest, TexParameter)
+{
+    ProbeError(CallTexParameter);
+}
+TEST_P(GLES1CovglTest, TexImage2D)
+{
+    ProbeError(CallTexImage2D);
+}
+TEST_P(GLES1CovglTest, TexSubImage2D)
+{
+    ProbeError(CallTexSubImage2D);
+}
+TEST_P(GLES1CovglTest, GenTextures)
+{
+    ProbeError(CallGenTextures);
+}
+TEST_P(GLES1CovglTest, BindDeleteTexture)
+{
+    ProbeError(CallBindDeleteTexture);
+}
+TEST_P(GLES1CovglTest, CopyTexImage2D)
+{
+    ProbeError(CallCopyTexImage2D);
+}
+TEST_P(GLES1CovglTest, CopyTexSubImage2D)
+{
+    ProbeError(CallCopyTexSubImage2D);
+}
+TEST_P(GLES1CovglTest, CompressedTexImage2D)
+{
+    ProbeError(CallCompressedTexImage2D);
+}
+TEST_P(GLES1CovglTest, CompressedTexSubImage2D)
+{
+    ProbeError(CallCompressedTexSubImage2D);
+}
+
+#ifdef GL_OES_VERSION_1_1
+TEST_P(GLES1CovglTest, BindDeleteBuffer)
+{
+    ProbeError(CallBindDeleteBuffer);
+}
+TEST_P(GLES1CovglTest, IsBuffer)
+{
+    ProbeError(CallIsBuffer);
+}
+TEST_P(GLES1CovglTest, BufferData)
+{
+    ProbeError(CallBufferData);
+}
+TEST_P(GLES1CovglTest, BufferSubData)
+{
+    ProbeError(CallBufferSubData);
+}
+TEST_P(GLES1CovglTest, GenBuffers)
+{
+    ProbeError(CallGenBuffers);
+}
+#endif /* GL_OES_VERSION_1_1 */
+
+TEST_P(GLES1CovglTest, ShadeModel)
+{
+    ProbeError(CallShadeModel);
+}
+TEST_P(GLES1CovglTest, PointSize)
+{
+    ProbeError(CallPointSize);
+}
+TEST_P(GLES1CovglTest, LineWidth)
+{
+    ProbeError(CallLineWidth);
+}
+TEST_P(GLES1CovglTest, CullFace)
+{
+    ProbeError(CallCullFace);
+}
+TEST_P(GLES1CovglTest, FrontFace)
+{
+    ProbeError(CallFrontFace);
+}
+TEST_P(GLES1CovglTest, PolygonOffset)
+{
+    ProbeError(CallPolygonOffset);
+}
+
+#ifdef GL_OES_VERSION_1_1
+TEST_P(GLES1CovglTest, PointParameter)
+{
+    ProbeError(CallPointParameter);
+}
+#endif /* GL_OES_VERSION_1_1 */
+
+TEST_P(GLES1CovglTest, Flush)
+{
+    ProbeError(CallFlush);
+}
+TEST_P(GLES1CovglTest, Finish)
+{
+    ProbeError(CallFinish);
+}
+
+TEST_P(GLES1CovglTest, ColorPointer)
+{
+    ProbeError(CallColorPointer);
+}
+TEST_P(GLES1CovglTest, DrawArrays)
+{
+    ProbeError(CallDrawArrays);
+}
+TEST_P(GLES1CovglTest, DrawElements)
+{
+    ProbeError(CallDrawElements);
+}
+#ifdef GL_OES_draw_texture
+TEST_P(GLES1CovglTest, DrawTex)
+{
+    ANGLE_SKIP_TEST_IF(!tkCheckExtension("GL_OES_draw_texture"));
+
+    ProbeError(CallDrawTex);
+}
+#endif /*GL_OES_draw_texture */
+TEST_P(GLES1CovglTest, NormalPointer)
+{
+    ProbeError(CallNormalPointer);
+}
+TEST_P(GLES1CovglTest, TexCoordPointer)
+{
+    ProbeError(CallTexCoordPointer);
+}
+TEST_P(GLES1CovglTest, VertexPointer)
+{
+    ProbeError(CallVertexPointer);
+}
+#ifdef GL_OES_VERSION_1_1
+TEST_P(GLES1CovglTest, PointSizePointerOES)
+{
+    ProbeError(CallPointSizePointerOES);
+}
+#endif
+TEST_P(GLES1CovglTest, EnableDisableClientState)
+{
+    ProbeError(CallEnableDisableClientState);
+}
+
+TEST_P(GLES1CovglTest, ActiveTexture)
+{
+    ProbeError(CallActiveTexture);
+}
+TEST_P(GLES1CovglTest, ClientActiveTexture)
+{
+    ProbeError(CallClientActiveTexture);
+}
+TEST_P(GLES1CovglTest, MultiTexCoord)
+{
+    ProbeError(CallMultiTexCoord);
+}
+
+TEST_P(GLES1CovglTest, SampleCoverage)
+{
+    ProbeError(CallSampleCoverage);
+}
+
+#ifdef GL_OES_query_matrix
+TEST_P(GLES1CovglTest, QueryMatrix)
+{
+    ANGLE_SKIP_TEST_IF(!tkCheckExtension("GL_OES_query_matrix"));
+    ProbeError(CallQueryMatrix);
+}
+#endif
+
+#ifdef GL_OES_matrix_palette
+TEST_P(GLES1CovglTest, CurrentPaletteMatrixOES)
+{
+    ANGLE_SKIP_TEST_IF(!tkCheckExtension("GL_OES_matrix_palette"));
+    ProbeError(CallCurrentPaletteMatrixOES);
+}
+TEST_P(GLES1CovglTest, LoadPaletteFromModelViewMatrixOES)
+{
+    ANGLE_SKIP_TEST_IF(!tkCheckExtension("GL_OES_matrix_palette"));
+    ProbeError(CallLoadPaletteFromModelViewMatrixOES);
+}
+TEST_P(GLES1CovglTest, MatrixIndexPointerOES)
+{
+    ANGLE_SKIP_TEST_IF(!tkCheckExtension("GL_OES_matrix_palette"));
+    ProbeError(CallMatrixIndexPointerOES);
+}
+TEST_P(GLES1CovglTest, WeightPointerOES)
+{
+    ANGLE_SKIP_TEST_IF(!tkCheckExtension("GL_OES_matrix_palette"));
+    ProbeError(CallWeightPointerOES);
+}
+#endif
+
+#ifdef GL_OES_VERSION_1_1
+TEST_P(GLES1CovglTest, ClipPlane)
+{
+    ProbeError(CallClipPlane);
+}
+#endif
+
+ANGLE_INSTANTIATE_TEST(GLES1CovglTest, ES1_OPENGL(), ES1_VULKAN());
+}  // namespace angle
+
+// Included here to fix a compile error due to white box tests using angle_end2end_tests_main.
+void RegisterContextCompatibilityTests() {}
diff --git a/src/tests/gles1_conformance_tests/PrimtestTests.cpp b/src/tests/gles1_conformance_tests/PrimtestTests.cpp
new file mode 100644
index 0000000..12a2895
--- /dev/null
+++ b/src/tests/gles1_conformance_tests/PrimtestTests.cpp
@@ -0,0 +1,166 @@
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// PrimtestTests.cpp:
+//   GLES1 conformance primtest tests.
+//
+
+#include "GLES/gl.h"
+#include "test_utils/ANGLETest.h"
+#include "test_utils/gl_raii.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// ES 1.0
+extern void DrawPrims(void);
+
+#include "primtest/driver.h"
+#include "primtest/tproto.h"
+
+#ifdef __cplusplus
+}
+
+#endif
+
+namespace angle
+{
+class GLES1PrimtestTest : public ANGLETest
+{
+  protected:
+    GLES1PrimtestTest()
+    {
+        setWindowWidth(48);
+        setWindowHeight(48);
+        setConfigRedBits(8);
+        setConfigGreenBits(8);
+        setConfigBlueBits(8);
+        setConfigAlphaBits(8);
+        setConfigDepthBits(24);
+        setConfigStencilBits(8);
+    }
+
+    void testTearDown() override
+    {
+        if (mTestData != nullptr)
+        {
+            free(mTestData);
+        }
+    }
+
+    void execTest(long test)
+    {
+        long i;
+        for (i = 0; driver[i].test != TEST_NULL; i++)
+        {
+            if (driver[i].test == test)
+            {
+                break;
+            }
+        }
+
+        ASSERT_NE(TEST_NULL, driver[i].test);
+
+        driverRec &op = driver[i];
+
+        op.funcInit((void *)&mTestData);
+        op.finish = 0;
+        ASSERT_GL_NO_ERROR();
+
+        for (;;)
+        {
+            op.funcStatus(1, mTestData);
+            ASSERT_GL_NO_ERROR();
+
+            op.funcSet(1, mTestData);
+            ASSERT_GL_NO_ERROR();
+
+            DrawPrims();
+            ASSERT_GL_NO_ERROR();
+
+            long finish = op.funcUpdate(mTestData);
+            ASSERT_GL_NO_ERROR();
+            if (finish)
+            {
+                break;
+            }
+        };
+    }
+
+  protected:
+    void *mTestData;
+};
+
+TEST_P(GLES1PrimtestTest, Hint)
+{
+    execTest(TEST_HINT);
+}
+
+TEST_P(GLES1PrimtestTest, Alias)
+{
+    execTest(TEST_ALIAS);
+}
+
+TEST_P(GLES1PrimtestTest, Alpha)
+{
+    execTest(TEST_ALPHA);
+}
+
+TEST_P(GLES1PrimtestTest, Blend)
+{
+    execTest(TEST_BLEND);
+}
+
+TEST_P(GLES1PrimtestTest, Depth)
+{
+    execTest(TEST_DEPTH);
+}
+
+TEST_P(GLES1PrimtestTest, Dither)
+{
+    execTest(TEST_DITHER);
+}
+
+TEST_P(GLES1PrimtestTest, Fog)
+{
+    execTest(TEST_FOG);
+}
+
+TEST_P(GLES1PrimtestTest, Light)
+{
+    execTest(TEST_LIGHT);
+}
+
+TEST_P(GLES1PrimtestTest, Logic)
+{
+    execTest(TEST_LOGICOP);
+}
+
+TEST_P(GLES1PrimtestTest, Scissor)
+{
+    execTest(TEST_SCISSOR);
+}
+
+TEST_P(GLES1PrimtestTest, Shade)
+{
+    execTest(TEST_SHADE);
+}
+
+TEST_P(GLES1PrimtestTest, Stencil)
+{
+    execTest(TEST_STENCIL);
+}
+
+TEST_P(GLES1PrimtestTest, Texture)
+{
+    execTest(TEST_TEXTURE);
+}
+
+ANGLE_INSTANTIATE_TEST(GLES1PrimtestTest, ES1_OPENGL(), ES1_VULKAN());
+}  // namespace angle
+
+// Included here to fix a compile error due to white box tests using angle_end2end_tests_main.
+void RegisterContextCompatibilityTests() {}
\ No newline at end of file
diff --git a/src/tests/perf_tests/ANGLEPerfTest.cpp b/src/tests/perf_tests/ANGLEPerfTest.cpp
index ec4abb9..2425ef1 100644
--- a/src/tests/perf_tests/ANGLEPerfTest.cpp
+++ b/src/tests/perf_tests/ANGLEPerfTest.cpp
@@ -189,7 +189,6 @@
       mBackend(backend),
       mStory(story),
       mGPUTimeNs(0),
-      mIgnoreErrors(false),
       mSkipTest(false),
       mStepsToRun(std::numeric_limits<unsigned int>::max()),
       mNumStepsPerformed(0),
@@ -649,11 +648,7 @@
         mOSWindow->messageLoop();
 
 #if defined(ANGLE_ENABLE_ASSERTS)
-        // Some gfxbench tests have expected errors that don't affect replay
-        if (!mIgnoreErrors)
-        {
-            EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
-        }
+        EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
 #endif  // defined(ANGLE_ENABLE_ASSERTS)
     }
 
diff --git a/src/tests/perf_tests/ANGLEPerfTest.h b/src/tests/perf_tests/ANGLEPerfTest.h
index 89603e8..236d863 100644
--- a/src/tests/perf_tests/ANGLEPerfTest.h
+++ b/src/tests/perf_tests/ANGLEPerfTest.h
@@ -89,7 +89,6 @@
     std::string mStory;
     Timer mTimer;
     uint64_t mGPUTimeNs;
-    bool mIgnoreErrors;
     bool mSkipTest;
     std::unique_ptr<perf_test::PerfResultReporter> mReporter;
 
diff --git a/src/tests/perf_tests/TracePerfTest.cpp b/src/tests/perf_tests/TracePerfTest.cpp
index 8895913..5763a7d 100644
--- a/src/tests/perf_tests/TracePerfTest.cpp
+++ b/src/tests/perf_tests/TracePerfTest.cpp
@@ -13,16 +13,15 @@
 #include "tests/perf_tests/ANGLEPerfTest.h"
 #include "tests/perf_tests/DrawCallPerfParams.h"
 #include "util/egl_loader_autogen.h"
+#include "util/frame_capture_utils.h"
 
+#include "restricted_traces/manhattan_10/manhattan_10_capture_context1.h"
 #include "restricted_traces/trex_200/trex_200_capture_context1.h"
 
 #include <cassert>
 #include <functional>
 #include <sstream>
 
-#define USE_SYSTEM_ZLIB
-#include "compression_utils_portable.h"
-
 using namespace angle;
 using namespace egl_platform;
 
@@ -30,30 +29,9 @@
 {
 void FramebufferChangeCallback(void *userData, GLenum target, GLuint framebuffer);
 
-ANGLE_MAYBE_UNUSED uint8_t *DecompressBinaryData(const std::vector<uint8_t> &compressedData)
-{
-    uint32_t uncompressedSize =
-        zlib_internal::GetGzipUncompressedSize(compressedData.data(), compressedData.size());
-
-    std::unique_ptr<uint8_t[]> uncompressedData(new uint8_t[uncompressedSize]);
-    uLong destLen = uncompressedSize;
-    int zResult =
-        zlib_internal::GzipUncompressHelper(uncompressedData.get(), &destLen, compressedData.data(),
-                                            static_cast<uLong>(compressedData.size()));
-
-    if (zResult != Z_OK)
-    {
-        std::cerr << "Failure to decompressed binary data: " << zResult << "\n";
-        return nullptr;
-    }
-
-    return uncompressedData.release();
-}
-
-// TODO (anglebug.com/4496)
-// Temporarily limit the tests to a single trace to get the bots going
 enum class TracePerfTestID
 {
+    Manhattan10,
     TRex200,
     InvalidEnum,
 };
@@ -81,6 +59,9 @@
 
         switch (testID)
         {
+            case TracePerfTestID::Manhattan10:
+                strstr << "_manhattan_10";
+                break;
             case TracePerfTestID::TRex200:
                 strstr << "_trex_200";
                 break;
@@ -138,24 +119,37 @@
     QueryInfo mCurrentQuery = {};
     std::vector<QueryInfo> mRunningQueries;
     std::vector<TimeSample> mTimeline;
+
+    std::string mStartingDirectory;
 };
 
 TracePerfTest::TracePerfTest()
     : ANGLERenderTest("TracePerf", GetParam()), mStartFrame(0), mEndFrame(0)
-{}
+{
+    // TODO(anglebug.com/4533) This fails after the upgrade to the 26.20.100.7870 driver.
+    if (IsWindows() && IsIntel() &&
+        GetParam().getRenderer() == EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE &&
+        GetParam().testID == TracePerfTestID::Manhattan10)
+    {
+        mSkipTest = true;
+    }
+}
 
 // TODO(jmadill/cnorthrop): Use decompression path. http://anglebug.com/3630
-#define TRACE_TEST_CASE(NAME)                            \
-    mStartFrame = NAME::kReplayFrameStart;               \
-    mEndFrame   = NAME::kReplayFrameEnd;                 \
-    mReplayFunc = NAME::ReplayContext1Frame;             \
-    NAME::SetBinaryDataDir(ANGLE_TRACE_DATA_DIR_##NAME); \
+#define TRACE_TEST_CASE(NAME)                                    \
+    mStartFrame = NAME::kReplayFrameStart;                       \
+    mEndFrame   = NAME::kReplayFrameEnd;                         \
+    mReplayFunc = NAME::ReplayContext1Frame;                     \
+    NAME::SetBinaryDataDecompressCallback(DecompressBinaryData); \
+    NAME::SetBinaryDataDir(ANGLE_TRACE_DATA_DIR_##NAME);         \
     NAME::SetupContext1Replay()
 
 void TracePerfTest::initializeBenchmark()
 {
     const auto &params = GetParam();
 
+    mStartingDirectory = angle::GetCWD().value();
+
     // To load the trace data path correctly we set the CWD to the executable dir.
     if (!IsAndroid())
     {
@@ -165,8 +159,10 @@
 
     switch (params.testID)
     {
+        case TracePerfTestID::Manhattan10:
+            TRACE_TEST_CASE(manhattan_10);
+            break;
         case TracePerfTestID::TRex200:
-            trex_200::SetBinaryDataDecompressCallback(DecompressBinaryData);
             TRACE_TEST_CASE(trex_200);
             break;
         default:
@@ -177,13 +173,15 @@
     ASSERT_TRUE(mEndFrame > mStartFrame);
 
     getWindow()->setVisible(true);
-
-    mIgnoreErrors = true;
 }
 
 #undef TRACE_TEST_CASE
 
-void TracePerfTest::destroyBenchmark() {}
+void TracePerfTest::destroyBenchmark()
+{
+    // In order for the next test to load, restore the working directory
+    angle::SetCWD(mStartingDirectory.c_str());
+}
 
 void TracePerfTest::sampleTime()
 {
@@ -310,8 +308,8 @@
     if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER)
         return;
 
-    // We have at most one active timestamp query at a time. This code will end the current query
-    // and immediately start a new one.
+    // We have at most one active timestamp query at a time. This code will end the current
+    // query and immediately start a new one.
     if (mCurrentQuery.beginTimestampQuery != 0)
     {
         glGenQueriesEXT(1, &mCurrentQuery.endTimestampQuery);
diff --git a/src/tests/perf_tests/restricted_traces/.gitignore b/src/tests/perf_tests/restricted_traces/.gitignore
index 125737c..ef56682 100644
--- a/src/tests/perf_tests/restricted_traces/.gitignore
+++ b/src/tests/perf_tests/restricted_traces/.gitignore
@@ -1,16 +1,4 @@
-manhattan_10_20
-manhattan_10_20.tar.gz
-manhattan_1100_1110
-manhattan_1100_1110.tar.gz
-manhattan_1440_1450
-manhattan_1440_1450.tar.gz
-manhattan_750_760
-manhattan_750_760.tar.gz
-trex_200_210
-trex_200_210.tar.gz
-trex_800_810
-trex_800_810.tar.gz
-trex_900_910
-trex_900_910.tar.gz
-trex_1300_1310
-trex_1300_1310.tar.gz
+manhattan_10
+manhattan_10.tar.gz
+trex_200
+trex_200.tar.gz
diff --git a/src/tests/perf_tests/restricted_traces/OWNERS b/src/tests/perf_tests/restricted_traces/OWNERS
new file mode 100644
index 0000000..ea7391a
--- /dev/null
+++ b/src/tests/perf_tests/restricted_traces/OWNERS
@@ -0,0 +1,2 @@
+cnorthrop@google.com
+jmadill@chromium.org
diff --git a/src/tests/perf_tests/restricted_traces/RestrictedTraceTests.md b/src/tests/perf_tests/restricted_traces/RestrictedTraceTests.md
index 7b2cbe5..29f8312 100644
--- a/src/tests/perf_tests/restricted_traces/RestrictedTraceTests.md
+++ b/src/tests/perf_tests/restricted_traces/RestrictedTraceTests.md
@@ -33,14 +33,10 @@
 ```
 autoninja -C out/Release angle_perftests
 ```
-On desktop, run them like so:
+Run them like so:
 ```
 out/Release/angle_perftests --gtest_filter=TracePerfTest*
 ```
-On Android, run them like so:
-```
-out/Release/bin/run_angle_perftests --gtest_filter=TracePerfTest*
-```
 
 ## Updating traces
 
@@ -56,6 +52,7 @@
 set TFW_PACKAGE_DIR=../../../build/vs2017-x64/testfw/tfw-dev
 set ANGLE_DEFAULT_PLATFORM=vulkan
 
+# TRex
 set START=200
 set END=210
 set LABEL=trex
@@ -65,6 +62,17 @@
 set ANGLE_CAPTURE_FRAME_END=%END%
 set ANGLE_CAPTURE_OUT_DIR=..\..\..\..\..\angle\src\tests\perf_tests\restricted_traces\%LABEL%_%START%
 ..\bin\testfw_app.exe -b ../../../build/vs2017-x64/testfw/tfw-dev --gfx egl -w 1920 -h 1080 -t gl_trex --ei -frame_step_time=40
+
+# Manhattan
+set START=10
+set END=20
+set LABEL=manhattan
+mkdir ..\..\..\..\..\angle\src\tests\perf_tests\restricted_traces\%LABEL%_%START%
+set ANGLE_CAPTURE_LABEL=%LABEL%_%START%
+set ANGLE_CAPTURE_FRAME_START=%START%
+set ANGLE_CAPTURE_FRAME_END=%END%
+set ANGLE_CAPTURE_OUT_DIR=..\..\..\..\..\angle\src\tests\perf_tests\restricted_traces\%LABEL%_%START%
+..\bin\testfw_app.exe -b ../../../build/vs2017-x64/testfw/tfw-dev --gfx egl -w 1920 -h 1080 -t gl_manhattan --ei -frame_step_time=40
 ```
 
 ### Linux
@@ -87,6 +95,17 @@
 export ANGLE_CAPTURE_FRAME_END=$END
 export ANGLE_CAPTURE_OUT_DIR=../../../../../angle/src/tests/perf_tests/restricted_traces/${LABEL}_${START}
 ../bin/testfw_app -b $TFW_PACKAGE_DIR --gfx egl -w 1920 -h 1080 -t gl_trex --ei -frame_step_time=40
+
+# Manhattan
+export START=10
+export END=20
+export LABEL=manhattan
+mkdir -p ../../../../../angle/src/tests/perf_tests/restricted_traces/${LABEL}_${START}
+export ANGLE_CAPTURE_LABEL=${LABEL}_${START}
+export ANGLE_CAPTURE_FRAME_START=$START
+export ANGLE_CAPTURE_FRAME_END=$END
+export ANGLE_CAPTURE_OUT_DIR=../../../../../angle/src/tests/perf_tests/restricted_traces/${LABEL}_${START}
+../bin/testfw_app -b $TFW_PACKAGE_DIR --gfx egl -w 1920 -h 1080 -t gl_manhattan --ei -frame_step_time=40
 ```
 
 ## Upload to the cloud
@@ -94,6 +113,7 @@
 ```
 cd ~/chromium/src/third_party/angle/src/tests/perf_tests/restricted_traces
 upload_to_google_storage.py --bucket chrome-angle-capture-binaries --archive trex_200
+upload_to_google_storage.py --bucket chrome-angle-capture-binaries --archive manhattan_10
 ```
 
 ## Adding new tests
diff --git a/src/tests/perf_tests/restricted_traces/angle_trace_perf_tests.gni b/src/tests/perf_tests/restricted_traces/angle_trace_perf_tests.gni
index 3953762..1eecb9e 100644
--- a/src/tests/perf_tests/restricted_traces/angle_trace_perf_tests.gni
+++ b/src/tests/perf_tests/restricted_traces/angle_trace_perf_tests.gni
@@ -7,9 +7,10 @@
 
 import("../../../../gni/angle.gni")
 
-# TODO: anglebug.com/4496
-# Temporarily limit the data uploaded to a single trace to get the bots going
-_tests = [ "trex_200" ]
+_tests = [
+  "manhattan_10",
+  "trex_200",
+]
 
 angle_trace_perf_sources = [ "perf_tests/TracePerfTest.cpp" ]
 
diff --git a/src/tests/perf_tests/restricted_traces/manhattan_10.tar.gz.sha1 b/src/tests/perf_tests/restricted_traces/manhattan_10.tar.gz.sha1
new file mode 100644
index 0000000..7d28cf8
--- /dev/null
+++ b/src/tests/perf_tests/restricted_traces/manhattan_10.tar.gz.sha1
@@ -0,0 +1 @@
+f801199c7958b20531cbd02289daa5127090d3a5
\ No newline at end of file
diff --git a/src/tests/test_utils/ANGLETest.cpp b/src/tests/test_utils/ANGLETest.cpp
index 405d5f4..aa94e9f 100644
--- a/src/tests/test_utils/ANGLETest.cpp
+++ b/src/tests/test_utils/ANGLETest.cpp
@@ -420,8 +420,9 @@
     windowNameStream << "ANGLE Tests - " << *mCurrentParams;
     std::string windowName = windowNameStream.str();
 
-    if (mAlwaysForceNewDisplay)
+    if (IsAndroid())
     {
+        // Only one window per test application on Android, shared among all fixtures
         mFixture->osWindow = mOSWindowSingleton;
     }
 
@@ -433,11 +434,15 @@
             std::cerr << "Failed to initialize OS Window.";
         }
 
-        mOSWindowSingleton = mFixture->osWindow;
+        if (IsAndroid())
+        {
+            // Initialize the single window on Andoird only once
+            mOSWindowSingleton = mFixture->osWindow;
+        }
     }
 
     // On Linux we must keep the test windows visible. On Windows it doesn't seem to need it.
-    mFixture->osWindow->setVisible(!IsWindows());
+    setWindowVisible(getOSWindow(), !IsWindows());
 
     switch (mCurrentParams->driver)
     {
@@ -1226,9 +1231,15 @@
     return mFixture->eglWindow->isMultisample();
 }
 
-void ANGLETestBase::setWindowVisible(bool isVisible)
+void ANGLETestBase::setWindowVisible(OSWindow *osWindow, bool isVisible)
 {
-    mFixture->osWindow->setVisible(isVisible);
+    // SwiftShader windows are not required to be visible for test correctness,
+    // moreover, making a SwiftShader window visible flaky hangs on Xvfb, so we keep them hidden.
+    if (isSwiftshader())
+    {
+        return;
+    }
+    osWindow->setVisible(isVisible);
 }
 
 ANGLETestBase::TestFixture::TestFixture()  = default;
diff --git a/src/tests/test_utils/ANGLETest.h b/src/tests/test_utils/ANGLETest.h
index ccefde2..509b1eb 100644
--- a/src/tests/test_utils/ANGLETest.h
+++ b/src/tests/test_utils/ANGLETest.h
@@ -322,7 +322,7 @@
     virtual ~ANGLETestBase();
 
   public:
-    void setWindowVisible(bool isVisible);
+    void setWindowVisible(OSWindow *osWindow, bool isVisible);
 
     virtual void overrideWorkaroundsD3D(angle::FeaturesD3D *featuresD3D) {}
     virtual void overrideFeaturesVk(angle::FeaturesVk *featuresVulkan) {}
@@ -526,9 +526,14 @@
     bool mSetUpCalled;
     bool mTearDownCalled;
 
-    // On most systems we force a new display on every test instance. For these configs we can
-    // share a single OSWindow instance. With display reuse we need a separate OSWindow for each
-    // different config. This OSWindow sharing seemed to lead to driver bugs on some platforms.
+    // Usually, we use an OS Window per "fixture" (a frontend and backend combination).
+    // This allows:
+    // 1. Reusing EGL Display on Windows.
+    //    Other platforms have issues with display reuse even if a window per fixture is used.
+    // 2. Hiding only SwiftShader OS Window on Linux.
+    //    OS Windows for other backends must be visible, to allow driver to communicate with X11.
+    // However, we must use a single OS Window for all backends on Android,
+    // since test Application can have only one window.
     static OSWindow *mOSWindowSingleton;
 
     static std::map<angle::PlatformParameters, TestFixture> gFixtures;
diff --git a/src/tests/test_utils/angle_test_instantiate.cpp b/src/tests/test_utils/angle_test_instantiate.cpp
index e491fa7..a394d08 100644
--- a/src/tests/test_utils/angle_test_instantiate.cpp
+++ b/src/tests/test_utils/angle_test_instantiate.cpp
@@ -551,15 +551,6 @@
         case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE:
 #if !defined(ANGLE_ENABLE_VULKAN)
             return false;
-#elif defined(ANGLE_IS_32_BIT_CPU)
-            // http://anglebug.com/4092
-            //  Currently hitting crashes in SwS w/ 32-bit Windows so skipping for now
-            if (IsWindows() && (param.eglParameters.deviceType ==
-                                EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE))
-            {
-                return false;
-            }
-            break;
 #else
             break;
 #endif
diff --git a/third_party/VulkanMemoryAllocator/.gitignore b/third_party/VulkanMemoryAllocator/.gitignore
new file mode 100644
index 0000000..dc84959
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/.gitignore
@@ -0,0 +1,2 @@
+build/
+
diff --git a/third_party/VulkanMemoryAllocator/.travis.yml b/third_party/VulkanMemoryAllocator/.travis.yml
new file mode 100644
index 0000000..6a59b1e
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/.travis.yml
@@ -0,0 +1,39 @@
+language: cpp
+sudo: required
+os: linux
+dist: trusty
+
+branches:
+  only:
+    - master
+
+compiler:
+  - clang
+  - gcc
+
+before_script:
+  - sudo apt-get install 
+
+install:
+  - wget https://github.com/premake/premake-core/releases/download/v5.0.0-alpha11/premake-5.0.0-alpha11-linux.tar.gz?Human=true -O premake-5.0.0-alpha11-linux.tar.gz
+  - tar -xzvf premake-5.0.0-alpha11-linux.tar.gz
+  - sudo apt-get -qq update
+  - sudo apt-get install -y libassimp-dev libglm-dev graphviz libxcb-dri3-0 libxcb-present0 libpciaccess0 cmake libpng-dev libxcb-dri3-dev libx11-dev libx11-xcb-dev libmirclient-dev libwayland-dev libxrandr-dev
+  - export VK_VERSION=1.2.131.1
+  - wget -O vulkansdk-linux-x86_64-$VK_VERSION.tar.gz https://sdk.lunarg.com/sdk/download/$VK_VERSION/linux/vulkansdk-linux-x86_64-$VK_VERSION.tar.gz
+  - tar zxf vulkansdk-linux-x86_64-$VK_VERSION.tar.gz
+  - export VULKAN_SDK=$TRAVIS_BUILD_DIR/$VK_VERSION/x86_64
+
+script:
+  - cd premake
+  - ../premake5 gmake
+  - cd ../build
+  - make config=debug_linux-x64
+  - cd ..
+
+notifications:
+  email:
+    recipients:
+      - adam.sawicki@amd.com
+    on_success: change
+    on_failure: always
diff --git a/third_party/VulkanMemoryAllocator/BUILD.gn b/third_party/VulkanMemoryAllocator/BUILD.gn
new file mode 100644
index 0000000..527fc5a
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/BUILD.gn
@@ -0,0 +1,37 @@
+# Copyright 2020 The ANGLE Project Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# Custom GN integration for VulkanMemoryAllocator.
+
+# This could be set via build_overrides if necessary
+vulkan_memory_allocator_vulkan_dep = "../../src/third_party/volk"
+
+config("vulkan_memory_allocator_config") {
+  include_dirs = [ "src" ]
+  if (is_clang) {
+    cflags_cc = [
+      "-Wno-implicit-fallthrough",
+      "-Wno-unused-variable",
+    ]
+  }
+  if (is_win && !is_clang) {
+    cflags_cc = [
+      "/wd4189",  # local variable is initialized but not referenced
+    ]
+  }
+}
+
+source_set("vulkan_memory_allocator") {
+  sources = [
+    # vk_mem_alloc.cpp allows the functions to be compiled into an object file
+    # and the consumers of vulkan_memory_allocator to use the prototypes.
+    "src/vk_mem_alloc.h",
+  ]
+
+  public_deps = [ "$vulkan_memory_allocator_vulkan_dep" ]
+
+  defines = [ "VMA_IMPLEMENTATION" ]
+
+  public_configs = [ ":vulkan_memory_allocator_config" ]
+}
diff --git a/third_party/VulkanMemoryAllocator/CHANGELOG.md b/third_party/VulkanMemoryAllocator/CHANGELOG.md
new file mode 100644
index 0000000..218a98b
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/CHANGELOG.md
@@ -0,0 +1,123 @@
+# 2.3.0 (2019-12-04)
+
+Major release after a year of development in "master" branch and feature branches. Notable new features: supporting Vulkan 1.1, supporting query for memory budget.
+
+Major changes:
+
+- Added support for Vulkan 1.1.
+    - Added member `VmaAllocatorCreateInfo::vulkanApiVersion`.
+    - When Vulkan 1.1 is used, there is no need to enable VK_KHR_dedicated_allocation or VK_KHR_bind_memory2 extensions, as they are promoted to Vulkan itself.
+- Added support for query for memory budget and staying within the budget.
+    - Added function `vmaGetBudget`, structure `VmaBudget`. This can also serve as simple statistics, more efficient than `vmaCalculateStats`.
+    - By default the budget it is estimated based on memory heap sizes. It may be queried from the system using VK_EXT_memory_budget extension if you use `VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT` flag and `VmaAllocatorCreateInfo::instance` member.
+    - Added flag `VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT` that fails an allocation if it would exceed the budget.
+- Added new memory usage options:
+    - `VMA_MEMORY_USAGE_CPU_COPY` for memory that is preferably not `DEVICE_LOCAL` but not guaranteed to be `HOST_VISIBLE`.
+    - `VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED` for memory that is `LAZILY_ALLOCATED`.
+- Added support for VK_KHR_bind_memory2 extension:
+    - Added `VMA_ALLOCATION_CREATE_DONT_BIND_BIT` flag that lets you create both buffer/image and allocation, but don't bind them together.
+    - Added flag `VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT`, functions `vmaBindBufferMemory2`, `vmaBindImageMemory2` that let you specify additional local offset and `pNext` pointer while binding.
+- Added functions `vmaSetPoolName`, `vmaGetPoolName` that let you assign string names to custom pools. JSON dump file format and VmaDumpVis tool is updated to show these names.
+- Defragmentation is legal only on buffers and images in `VK_IMAGE_TILING_LINEAR`. This is due to the way it is currently implemented in the library and the restrictions of the Vulkan specification. Clarified documentation in this regard. See discussion in #59.
+
+Minor changes:
+
+- Made `vmaResizeAllocation` function deprecated, always returning failure.
+- Made changes in the internal algorithm for the choice of memory type. Be careful! You may now get a type that is not `HOST_VISIBLE` or `HOST_COHERENT` if it's not stated as always ensured by some `VMA_MEMORY_USAGE_*` flag.
+- Extended VmaReplay application with more detailed statistics printed at the end.
+- Added macros `VMA_CALL_PRE`, `VMA_CALL_POST` that let you decorate declarations of all library functions if you want to e.g. export/import them as dynamically linked library.
+- Optimized `VmaAllocation` objects to be allocated out of an internal free-list allocator. This makes allocation and deallocation causing 0 dynamic CPU heap allocations on average.
+- Updated recording CSV file format version to 1.8, to support new functions.
+- Many additions and fixes in documentation. Many compatibility fixes for various compilers and platforms. Other internal bugfixes, optimizations, updates, refactoring...
+
+# 2.2.0 (2018-12-13)
+
+Major release after many months of development in "master" branch and feature branches. Notable new features: defragmentation of GPU memory, buddy algorithm, convenience functions for sparse binding.
+
+Major changes:
+
+- New, more powerful defragmentation:
+  - Added structure `VmaDefragmentationInfo2`, functions `vmaDefragmentationBegin`, `vmaDefragmentationEnd`.
+  - Added support for defragmentation of GPU memory.
+  - Defragmentation of CPU memory now uses `memmove`, so it can move data to overlapping regions.
+  - Defragmentation of CPU memory is now available for memory types that are `HOST_VISIBLE` but not `HOST_COHERENT`.
+  - Added structure member `VmaVulkanFunctions::vkCmdCopyBuffer`.
+  - Major internal changes in defragmentation algorithm.
+  - VmaReplay: added parameters: `--DefragmentAfterLine`, `--DefragmentationFlags`.
+  - Old interface (structure `VmaDefragmentationInfo`, function `vmaDefragment`) is now deprecated.
+- Added buddy algorithm, available for custom pools - flag `VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT`.
+- Added convenience functions for multiple allocations and deallocations at once, intended for sparse binding resources - functions `vmaAllocateMemoryPages`, `vmaFreeMemoryPages`.
+- Added function that tries to resize existing allocation in place: `vmaResizeAllocation`.
+- Added flags for allocation strategy: `VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT`, `VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT`, `VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT`, and their aliases: `VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT`, `VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT`, `VMA_ALLOCATION_CREATE_STRATEGY_MIN_FRAGMENTATION_BIT`.
+
+Minor changes:
+
+- Changed behavior of allocation functions to return `VK_ERROR_VALIDATION_FAILED_EXT` when trying to allocate memory of size 0, create buffer with size 0, or image with one of the dimensions 0.
+- VmaReplay: Added support for Windows end of lines.
+- Updated recording CSV file format version to 1.5, to support new functions.
+- Internal optimization: using read-write mutex on some platforms.
+- Many additions and fixes in documentation. Many compatibility fixes for various compilers. Other internal bugfixes, optimizations, refactoring, added more internal validation...
+
+# 2.1.0 (2018-09-10)
+
+Minor bugfixes.
+
+# 2.1.0-beta.1 (2018-08-27)
+
+Major release after many months of development in "development" branch and features branches. Many new features added, some bugs fixed. API stays backward-compatible.
+
+Major changes:
+
+- Added linear allocation algorithm, accessible for custom pools, that can be used as free-at-once, stack, double stack, or ring buffer. See "Linear allocation algorithm" documentation chapter.
+  - Added `VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT`, `VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT`.
+- Added feature to record sequence of calls to the library to a file and replay it using dedicated application. See documentation chapter "Record and replay".
+  - Recording: added `VmaAllocatorCreateInfo::pRecordSettings`.
+  - Replaying: added VmaReplay project.
+  - Recording file format: added document "docs/Recording file format.md".
+- Improved support for non-coherent memory.
+  - Added functions: `vmaFlushAllocation`, `vmaInvalidateAllocation`.
+  - `nonCoherentAtomSize` is now respected automatically.
+  - Added `VmaVulkanFunctions::vkFlushMappedMemoryRanges`, `vkInvalidateMappedMemoryRanges`.
+- Improved debug features related to detecting incorrect mapped memory usage. See documentation chapter "Debugging incorrect memory usage".
+  - Added debug macro `VMA_DEBUG_DETECT_CORRUPTION`, functions `vmaCheckCorruption`, `vmaCheckPoolCorruption`.
+  - Added debug macro `VMA_DEBUG_INITIALIZE_ALLOCATIONS` to initialize contents of allocations with a bit pattern.
+  - Changed behavior of `VMA_DEBUG_MARGIN` macro - it now adds margin also before first and after last allocation in a block.
+- Changed format of JSON dump returned by `vmaBuildStatsString` (not backward compatible!).
+  - Custom pools and memory blocks now have IDs that don't change after sorting.
+  - Added properties: "CreationFrameIndex", "LastUseFrameIndex", "Usage".
+  - Changed VmaDumpVis tool to use these new properties for better coloring.
+  - Changed behavior of `vmaGetAllocationInfo` and `vmaTouchAllocation` to update `allocation.lastUseFrameIndex` even if allocation cannot become lost.
+
+Minor changes:
+
+- Changes in custom pools:
+  - Added new structure member `VmaPoolStats::blockCount`.
+  - Changed behavior of `VmaPoolCreateInfo::blockSize` = 0 (default) - it now means that pool may use variable block sizes, just like default pools do.
+- Improved logic of `vmaFindMemoryTypeIndex` for some cases, especially integrated GPUs.
+- VulkanSample application: Removed dependency on external library MathFu. Added own vector and matrix structures.
+- Changes that improve compatibility with various platforms, including: Visual Studio 2012, 32-bit code, C compilers.
+  - Changed usage of "VK_KHR_dedicated_allocation" extension in the code to be optional, driven by macro `VMA_DEDICATED_ALLOCATION`, for compatibility with Android.
+- Many additions and fixes in documentation, including description of new features, as well as "Validation layer warnings".
+- Other bugfixes.
+
+# 2.0.0 (2018-03-19)
+
+A major release with many compatibility-breaking changes.
+
+Notable new features:
+
+- Introduction of `VmaAllocation` handle that you must retrieve from allocation functions and pass to deallocation functions next to normal `VkBuffer` and `VkImage`.
+- Introduction of `VmaAllocationInfo` structure that you can retrieve from `VmaAllocation` handle to access parameters of the allocation (like `VkDeviceMemory` and offset) instead of retrieving them directly from allocation functions.
+- Support for reference-counted mapping and persistently mapped allocations - see `vmaMapMemory`, `VMA_ALLOCATION_CREATE_MAPPED_BIT`.
+- Support for custom memory pools - see `VmaPool` handle, `VmaPoolCreateInfo` structure, `vmaCreatePool` function.
+- Support for defragmentation (compaction) of allocations - see function `vmaDefragment` and related structures.
+- Support for "lost allocations" - see appropriate chapter on documentation Main Page.
+
+# 1.0.1 (2017-07-04)
+
+- Fixes for Linux GCC compilation.
+- Changed "CONFIGURATION SECTION" to contain #ifndef so you can define these macros before including this header, not necessarily change them in the file.
+
+# 1.0.0 (2017-06-16)
+
+First public release.
diff --git a/third_party/VulkanMemoryAllocator/LICENSE.txt b/third_party/VulkanMemoryAllocator/LICENSE.txt
new file mode 100644
index 0000000..bee6af7
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/LICENSE.txt
@@ -0,0 +1,19 @@
+Copyright (c) 2017-2020 Advanced Micro Devices, Inc. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/third_party/VulkanMemoryAllocator/README.chromium b/third_party/VulkanMemoryAllocator/README.chromium
new file mode 100644
index 0000000..7c38cf1
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/README.chromium
@@ -0,0 +1,10 @@
+Name: VulkanMemoryAllocator
+URL: https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator
+License: MIT
+License File: LICENSE.txt
+
+Description:
+Easy to integrate Vulkan memory allocation library.
+
+Modifications:
+Added OWNERS, BUILD.gn, README.chromium and codereview.settings.
diff --git a/third_party/VulkanMemoryAllocator/README.md b/third_party/VulkanMemoryAllocator/README.md
new file mode 100644
index 0000000..656e753
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/README.md
@@ -0,0 +1,129 @@
+# Vulkan Memory Allocator
+
+Easy to integrate Vulkan memory allocation library.
+
+**Documentation:** See [Vulkan Memory Allocator](https://gpuopen-librariesandsdks.github.io/VulkanMemoryAllocator/html/) (generated from Doxygen-style comments in [src/vk_mem_alloc.h](src/vk_mem_alloc.h))
+
+**License:** MIT. See [LICENSE.txt](LICENSE.txt)
+
+**Changelog:** See [CHANGELOG.md](CHANGELOG.md)
+
+**Product page:** [Vulkan Memory Allocator on GPUOpen](https://gpuopen.com/gaming-product/vulkan-memory-allocator/)
+
+**Build status:**
+
+- Windows: [![Build status](https://ci.appveyor.com/api/projects/status/4vlcrb0emkaio2pn/branch/master?svg=true)](https://ci.appveyor.com/project/adam-sawicki-amd/vulkanmemoryallocator/branch/master)  
+- Linux: [![Build Status](https://travis-ci.org/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.svg?branch=master)](https://travis-ci.org/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator)
+
+# Problem
+
+Memory allocation and resource (buffer and image) creation in Vulkan is difficult (comparing to older graphics API-s, like D3D11 or OpenGL) for several reasons:
+
+- It requires a lot of boilerplate code, just like everything else in Vulkan, because it is a low-level and high-performance API.
+- There is additional level of indirection: `VkDeviceMemory` is allocated separately from creating `VkBuffer`/`VkImage` and they must be bound together.
+- Driver must be queried for supported memory heaps and memory types. Different IHVs provide different types of it.
+- It is recommended practice to allocate bigger chunks of memory and assign parts of them to particular resources.
+
+# Features
+
+This library can help game developers to manage memory allocations and resource creation by offering some higher-level functions:
+
+1. Functions that help to choose correct and optimal memory type based on intended usage of the memory.
+   - Required or preferred traits of the memory are expressed using higher-level description comparing to Vulkan flags.
+2. Functions that allocate memory blocks, reserve and return parts of them (`VkDeviceMemory` + offset + size) to the user.
+   - Library keeps track of allocated memory blocks, used and unused ranges inside them, finds best matching unused ranges for new allocations, respects all the rules of alignment and buffer/image granularity.
+3. Functions that can create an image/buffer, allocate memory for it and bind them together - all in one call.
+
+Additional features:
+
+- Well-documented - description of all functions and structures provided, along with chapters that contain general description and example code.
+- Thread-safety: Library is designed to be used by multithreaded code.
+- Configuration: Fill optional members of CreateInfo structure to provide custom CPU memory allocator, pointers to Vulkan functions and other parameters.
+- Customization: Predefine appropriate macros to provide your own implementation of all external facilities used by the library, from assert, mutex, and atomic, to vector and linked list. 
+- Support for memory mapping, reference-counted internally. Support for persistently mapped memory: Just allocate with appropriate flag and you get access to mapped pointer.
+- Support for non-coherent memory. Functions that flush/invalidate memory. `nonCoherentAtomSize` is respected automatically.
+- Support for sparse binding and sparse residency: Convenience functions that allocate or free multiple memory pages at once.
+- Custom memory pools: Create a pool with desired parameters (e.g. fixed or limited maximum size) and allocate memory out of it.
+- Linear allocator: Create a pool with linear algorithm and use it for much faster allocations and deallocations in free-at-once, stack, double stack, or ring buffer fashion.
+- Support for Vulkan 1.0, 1.1, 1.2.
+- Support for extensions (and equivalent functionality included in new Vulkan versions):
+   - VK_EXT_memory_budget: Used internally if available to query for current usage and budget. If not available, it falls back to an estimation based on memory heap sizes.
+   - VK_KHR_dedicated_allocation: Just enable it and it will be used automatically by the library.
+   - VK_AMD_device_coherent_memory
+   - VK_KHR_buffer_device_address
+- Defragmentation of GPU and CPU memory: Let the library move data around to free some memory blocks and make your allocations better compacted.
+- Lost allocations: Allocate memory with appropriate flags and let the library remove allocations that are not used for many frames to make room for new ones.
+- Statistics: Obtain detailed statistics about the amount of memory used, unused, number of allocated blocks, number of allocations etc. - globally, per memory heap, and per memory type.
+- Debug annotations: Associate string with name or opaque pointer to your own data with every allocation.
+- JSON dump: Obtain a string in JSON format with detailed map of internal state, including list of allocations and gaps between them.
+- Convert this JSON dump into a picture to visualize your memory. See [tools/VmaDumpVis](tools/VmaDumpVis/README.md).
+- Debugging incorrect memory usage: Enable initialization of all allocated memory with a bit pattern to detect usage of uninitialized or freed memory. Enable validation of a magic number before and after every allocation to detect out-of-bounds memory corruption.
+- Record and replay sequence of calls to library functions to a file to check correctness, measure performance, and gather statistics.
+
+# Prequisites
+
+- Self-contained C++ library in single header file. No external dependencies other than standard C and C++ library and of course Vulkan. STL containers are not used by default.
+- Public interface in C, in same convention as Vulkan API. Implementation in C++.
+- Error handling implemented by returning `VkResult` error codes - same way as in Vulkan.
+- Interface documented using Doxygen-style comments.
+- Platform-independent, but developed and tested on Windows using Visual Studio. Continuous integration setup for Windows and Linux. Used also on Android, MacOS, and other platforms.
+
+# Example
+
+Basic usage of this library is very simple. Advanced features are optional. After you created global `VmaAllocator` object, a complete code needed to create a buffer may look like this:
+
+```cpp
+VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+bufferInfo.size = 65536;
+bufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+
+VmaAllocationCreateInfo allocInfo = {};
+allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+
+VkBuffer buffer;
+VmaAllocation allocation;
+vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr);
+```
+
+With this one function call:
+
+1. `VkBuffer` is created.
+2. `VkDeviceMemory` block is allocated if needed.
+3. An unused region of the memory block is bound to this buffer.
+
+`VmaAllocation` is an object that represents memory assigned to this buffer. It can be queried for parameters like Vulkan memory handle and offset.
+
+# Binariers
+
+The release comes with precompiled binary executables for "VulkanSample" application which contains test suite and "VmaReplay" tool. They are compiled using Visual Studio 2017, so they require appropriate libraries to work, including "vcruntime140.dll" and "msvcp140.dll". If their launch fails with error message telling about those files missing, please download and install [Microsoft Visual C++ Redistributable for Visual Studio 2015, 2017 and 2019](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads), "x64" version.
+
+# Read more
+
+See **[Documentation](https://gpuopen-librariesandsdks.github.io/VulkanMemoryAllocator/html/)**.
+
+# Software using this library
+
+- **[Vulkan Samples](https://github.com/LunarG/VulkanSamples)** - official Khronos Vulkan samples. License: Apache-style.
+- **[Anvil](https://github.com/GPUOpen-LibrariesAndSDKs/Anvil)** - cross-platform framework for Vulkan. License: MIT.
+- **[Filament](https://github.com/google/filament)** - physically based rendering engine for Android, Windows, Linux and macOS, from Google. Apache License 2.0.
+- **[Flax Engine](https://flaxengine.com/)**
+- **[Lightweight Java Game Library (LWJGL)](https://www.lwjgl.org/)** - includes binding of the library for Java. License: BSD.
+- **[PowerVR SDK](https://github.com/powervr-graphics/Native_SDK)** - C++ cross-platform 3D graphics SDK, from Imagination. License: MIT.
+- **[Skia](https://github.com/google/skia)** - complete 2D graphic library for drawing Text, Geometries, and Images, from Google.
+- **[The Forge](https://github.com/ConfettiFX/The-Forge)** - cross-platform rendering framework. Apache License 2.0.
+- **[VK9](https://github.com/disks86/VK9)** - Direct3D 9 compatibility layer using Vulkan. Zlib lincese.
+- **[vkDOOM3](https://github.com/DustinHLand/vkDOOM3)** - Vulkan port of GPL DOOM 3 BFG Edition. License: GNU GPL.
+- **[vkQuake2](https://github.com/kondrak/vkQuake2)** - vanilla Quake 2 with Vulkan support. License: GNU GPL.
+- **[Vulkan Best Practice for Mobile Developers](https://github.com/ARM-software/vulkan_best_practice_for_mobile_developers)** from ARM. License: MIT.
+
+[Many other projects on GitHub](https://github.com/search?q=AMD_VULKAN_MEMORY_ALLOCATOR_H&type=Code) and some game development studios that use Vulkan in their games.
+
+# See also
+
+- **[D3D12 Memory Allocator](https://github.com/GPUOpen-LibrariesAndSDKs/D3D12MemoryAllocator)** - equivalent library for Direct3D 12. License: MIT.
+- **[Awesome Vulkan](https://github.com/vinjn/awesome-vulkan)** - a curated list of awesome Vulkan libraries, debuggers and resources.
+- **[VulkanMemoryAllocator-Hpp](https://github.com/malte-v/VulkanMemoryAllocator-Hpp)** - C++ binding for this library. License: CC0-1.0.
+- **[PyVMA](https://github.com/realitix/pyvma)** - Python wrapper for this library. Author: Jean-Sébastien B. (@realitix). License: Apache 2.0.
+- **[vk-mem](https://github.com/gwihlidal/vk-mem-rs)** - Rust binding for this library. Author: Graham Wihlidal. License: Apache 2.0 or MIT.
+- **[vma_sample_sdl](https://github.com/rextimmy/vma_sample_sdl)** - SDL port of the sample app of this library (with the goal of running it on multiple platforms, including MacOS). Author: @rextimmy. License: MIT.
+- **[vulkan-malloc](https://github.com/dylanede/vulkan-malloc)** - Vulkan memory allocation library for Rust. Based on version 1 of this library. Author: Dylan Ede (@dylanede). License: MIT / Apache 2.0.
diff --git a/third_party/VulkanMemoryAllocator/bin/Shader.frag.spv b/third_party/VulkanMemoryAllocator/bin/Shader.frag.spv
new file mode 100644
index 0000000..f09dacb
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/bin/Shader.frag.spv
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/bin/Shader.vert.spv b/third_party/VulkanMemoryAllocator/bin/Shader.vert.spv
new file mode 100644
index 0000000..7b42b9e
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/bin/Shader.vert.spv
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/bin/SparseBindingTest.comp.spv b/third_party/VulkanMemoryAllocator/bin/SparseBindingTest.comp.spv
new file mode 100644
index 0000000..d56e0a9
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/bin/SparseBindingTest.comp.spv
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/bin/VmaReplay_Release_vs2017.exe b/third_party/VulkanMemoryAllocator/bin/VmaReplay_Release_vs2017.exe
new file mode 100644
index 0000000..eb99d7f
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/bin/VmaReplay_Release_vs2017.exe
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/bin/VulkanSample_Release_vs2017.exe b/third_party/VulkanMemoryAllocator/bin/VulkanSample_Release_vs2017.exe
new file mode 100644
index 0000000..c195d29
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/bin/VulkanSample_Release_vs2017.exe
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/codereview.settings b/third_party/VulkanMemoryAllocator/codereview.settings
new file mode 100644
index 0000000..0fe9bc4
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/codereview.settings
@@ -0,0 +1,3 @@
+# This file is used by git cl to get repository specific information.
+GERRIT_HOST: True
+GERRIT_SQUASH_UPLOADS: False
diff --git a/third_party/VulkanMemoryAllocator/docs/Recording file format.md b/third_party/VulkanMemoryAllocator/docs/Recording file format.md
new file mode 100644
index 0000000..4b972b6
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/Recording file format.md
@@ -0,0 +1,343 @@
+This is an official documentation for file format used by Vulkan Memory Allocator library
+to record and replay sequence of calls to its functions.
+This feature can be enabled by using `VmaAllocatorCreateInfo::pRecordSettings` structure members.
+For details, see main documentation of the library.
+Playback can be launched using **VmaReplay** console application.
+
+Recording is a text file.
+Line endings: Unix `'\n'`.
+Character encoding: single-byte (can be ASCII or UTF-8, whaterver you use in custom strings).
+Suggested file extension: **csv**. File can be processed sequentially - no random access is needed.
+Each line forms a separate entry.
+Each line consists of a set of values (also called columns), separated by comma `','` (hence "CSV" format - Comma Separated Values).
+Number of columns is different in different lines.
+
+# Header
+
+First line identifies file format. It must always be:
+
+    Vulkan Memory Allocator,Calls recording
+
+Second line identifies format version, where first column is major version and second column is minor version.
+Formats with only minor version incremented are backward compatible.
+VmaReplay application supports all older versions.
+Current version is:
+
+    1,8
+
+# Configuration
+
+Header is followed by mandatory configuration section (min format version 1.3). It starts with line:
+
+    Config,Begin
+
+And ends with line:
+
+    Config,End
+
+Between them there can be zero or more lines with configuration options. They store values of various variables from the current environment from the time of recording, like properties and limits of Vulkan physical device, available memory heaps and types, enabled Vulkan extensions, as well macros that configure VMA internals. Supported configuration options are:
+
+    VulkanApiVersion,<uint32>,<uint32>
+    
+    PhysicalDevice,apiVersion,<uint32>
+    PhysicalDevice,driverVersion,<uint32>
+    PhysicalDevice,vendorID,<uint32>
+    PhysicalDevice,deviceID,<uint32>
+    PhysicalDevice,deviceType,<uint32>
+    PhysicalDevice,deviceName,<string>
+    
+    PhysicalDeviceLimits,maxMemoryAllocationCount,<uint32>
+    PhysicalDeviceLimits,bufferImageGranularity,<uint64>
+    PhysicalDeviceLimits,nonCoherentAtomSize,<uint64>
+    
+    PhysicalDeviceMemory,HeapCount,<uint32>
+    PhysicalDeviceMemory,Heap,<index:uint32>,size,<uint64>
+    PhysicalDeviceMemory,Heap,<index:uint32>,flags,<uint32>
+    PhysicalDeviceMemory,TypeCount,<uint32>
+    PhysicalDeviceMemory,Type,<index:uint32>,heapIndex,<uint32>
+    PhysicalDeviceMemory,Type,<index:uint32>,propertyFlags,<uint32>
+    
+    Extension,VK_KHR_dedicated_allocation,<bool>
+    Extension,VK_KHR_bind_memory2,<bool>
+    Extension,VK_EXT_memory_budget,<bool>
+    Extension,VK_AMD_device_coherent_memory,<bool>
+    
+    Macro,VMA_DEBUG_ALWAYS_DEDICATED_MEMORY,<bool>
+    Macro,VMA_DEBUG_ALIGNMENT,<uint64>
+    Macro,VMA_DEBUG_MARGIN,<uint64>
+    Macro,VMA_DEBUG_INITIALIZE_ALLOCATIONS,<bool>
+    Macro,VMA_DEBUG_DETECT_CORRUPTION,<bool>
+    Macro,VMA_DEBUG_GLOBAL_MUTEX,<bool>
+    Macro,VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY,<uint64>
+    Macro,VMA_SMALL_HEAP_MAX_SIZE,<uint64>
+    Macro,VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE,<uint64>
+
+# Function calls
+
+Remaining lines contain recorded calls to VMA functions. First columns are always:
+
+- Thread ID : uint32
+- Time since first call : float, in seconds
+- VMA frame index : uint32
+- Function name : string
+
+Remaining columns are function parameters and output, depending on function name, which can be:
+
+**vmaCreateAllocator, vmaDestroyAllocator**
+
+No parameters.
+
+**vmaCreatePool**
+
+- memoryTypeIndex : uint32
+- flags : uint32
+- blockSize : uint64
+- minBlockCount : uint64
+- maxBlockCount : uint64
+- frameInUseCount : uint32
+- pool (output) : pointer
+
+**vmaDestroyPool**
+
+- pool : pointer
+
+**vmaSetAllocationUserData**
+
+- allocation : pointer
+- pUserData : string (may contain additional commas)
+
+**vmaCreateBuffer**
+
+- bufferCreateInfo.flags : uint32
+- bufferCreateInfo.size : uint64
+- bufferCreateInfo.usage : uint32
+- bufferCreateInfo.sharingMode : uint32
+- allocationCreateInfo.flags : uint32
+- allocationCreateInfo.usage : uint32
+- allocationCreateInfo.requiredFlags : uint32
+- allocationCreateInfo.preferredFlags : uint32
+- allocationCreateInfo.memoryTypeBits : uint32
+- allocationCreateInfo.pool : pointer
+- allocation (output) : pointer
+- allocationCreateInfo.pUserData : string (may contain additional commas)
+
+**vmaDestroyBuffer**
+
+- allocation : pointer
+
+**vmaCreateImage**
+
+- imageCreateInfo.flags : uint32
+- imageCreateInfo.imageType : uint32
+- imageCreateInfo.format : uint32
+- imageCreateInfo.extent.width : uint32
+- imageCreateInfo.extent.height : uint32
+- imageCreateInfo.extent.depth : uint32
+- imageCreateInfo.mipLevels : uint32
+- imageCreateInfo.arrayLayers : uint32
+- imageCreateInfo.samples : uint32
+- imageCreateInfo.tiling : uint32
+- imageCreateInfo.usage : uint32
+- imageCreateInfo.sharingMode : uint32
+- imageCreateInfo.initialLayout : uint32
+- allocationCreateInfo.flags : uint32
+- allocationCreateInfo.usage : uint32
+- allocationCreateInfo.requiredFlags : uint32
+- allocationCreateInfo.preferredFlags : uint32
+- allocationCreateInfo.memoryTypeBits : uint32
+- allocationCreateInfo.pool : pointer
+- allocation (output) : pointer
+- allocationCreateInfo.pUserData : string (may contain additional commas)
+
+**vmaDestroyImage**
+
+- allocation : pointer
+
+**vmaFreeMemory** (min format version 1.1)
+
+- allocation : pointer
+
+**vmaFreeMemoryPages** (min format version: 1.5)
+
+- allocations : list of pointers
+
+**vmaCreateLostAllocation** (min format version 1.2)
+
+- allocation (output) : pointer
+
+**vmaAllocateMemory** (min format version 1.2)
+
+- vkMemoryRequirements.size : uint64
+- vkMemoryRequirements.alignment : uint64
+- vkMemoryRequirements.memoryTypeBits : uint32
+- allocationCreateInfo.flags : uint32
+- allocationCreateInfo.usage : uint32
+- allocationCreateInfo.requiredFlags : uint32
+- allocationCreateInfo.preferredFlags : uint32
+- allocationCreateInfo.memoryTypeBits : uint32
+- allocationCreateInfo.pool : pointer
+- allocation (output) : pointer
+- allocationCreateInfo.pUserData : string (may contain additional commas)
+
+**vmaAllocateMemoryPages** (min format version 1.5)
+
+- vkMemoryRequirements.size : uint64
+- vkMemoryRequirements.alignment : uint64
+- vkMemoryRequirements.memoryTypeBits : uint32
+- allocationCreateInfo.flags : uint32
+- allocationCreateInfo.usage : uint32
+- allocationCreateInfo.requiredFlags : uint32
+- allocationCreateInfo.preferredFlags : uint32
+- allocationCreateInfo.memoryTypeBits : uint32
+- allocationCreateInfo.pool : pointer
+- allocations (output) : list of pointers
+- allocationCreateInfo.pUserData : string (may contain additional commas)
+
+**vmaAllocateMemoryForBuffer, vmaAllocateMemoryForImage** (min format version 1.2)
+
+- vkMemoryRequirements.size : uint64
+- vkMemoryRequirements.alignment : uint64
+- vkMemoryRequirements.memoryTypeBits : uint32
+- requiresDedicatedAllocation : bool
+- prefersDedicatedAllocation : bool
+- allocationCreateInfo.flags : uint32
+- allocationCreateInfo.usage : uint32
+- allocationCreateInfo.requiredFlags : uint32
+- allocationCreateInfo.preferredFlags : uint32
+- allocationCreateInfo.memoryTypeBits : uint32
+- allocationCreateInfo.pool : pointer
+- allocation (output) : pointer
+- allocationCreateInfo.pUserData : string (may contain additional commas)
+
+**vmaMapMemory, vmaUnmapMemory** (min format version 1.2)
+
+- allocation : pointer
+
+**vmaFlushAllocation, vmaInvalidateAllocation** (min format version 1.2)
+
+- allocation : pointer
+- offset : uint64
+- size : uint64
+
+**vmaTouchAllocation, vmaGetAllocationInfo** (min format version 1.2)
+
+- allocation : pointer
+
+**vmaMakePoolAllocationsLost** (min format version: 1.2)
+
+- pool : pointer
+
+**vmaResizeAllocation** (min format version: 1.4, max format version: 1.5)
+
+- allocation : pointer
+- newSize : uint64
+
+**vmaDefragmentationBegin** (min format version: 1.5)
+
+- defragmentationInfo2.flags : uint32
+- defragmentationInfo2.pAllocations : list of pointers
+- defragmentationInfo2.pPools : list of pointers
+- defragmentationInfo2.maxCpuBytesToMove : uint64
+- defragmentationInfo2.maxCpuAllocationsToMove : uint32
+- defragmentationInfo2.maxGpuBytesToMove : uint64
+- defragmentationInfo2.maxGpuAllocationsToMove : uint32
+- defragmentationInfo2.commandBuffer : pointer
+- context (output) : pointer
+
+**vmaDefragmentationEnd** (min format version: 1.5)
+
+- context : pointer
+
+**vmaSetPoolName** (min format version: 1.7)
+
+- pool : pointer
+- pName : string (may contain additional commas)
+
+# Data types
+
+**bool**
+
+Encoded as `0` for false or `1` for true.
+
+**uint32, uint64**
+
+Encoded in decimal format.
+
+**pointer**
+
+Encoded in hexadecimal format.
+
+**pUserData**
+
+If `pUserData` was a pointer, it is encoded as hexadecimal string.
+If `VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT` was used with the allocation, the string is written as-is.
+It may contain additional commas.
+It should not contain end-of-line characters - results are then undefined.
+
+**list of (...)** (min format version: 1.5)
+
+An ordered sequence of values of some type, separated by single space.
+
+# Example file
+
+    Vulkan Memory Allocator,Calls recording
+    1,8
+    Config,Begin
+    VulkanApiVersion,1,1
+    PhysicalDevice,apiVersion,4198477
+    PhysicalDevice,driverVersion,8388653
+    PhysicalDevice,vendorID,4098
+    PhysicalDevice,deviceID,26751
+    PhysicalDevice,deviceType,2
+    PhysicalDevice,deviceName,Radeon RX Vega
+    PhysicalDeviceLimits,maxMemoryAllocationCount,4096
+    PhysicalDeviceLimits,bufferImageGranularity,1
+    PhysicalDeviceLimits,nonCoherentAtomSize,128
+    PhysicalDeviceMemory,HeapCount,3
+    PhysicalDeviceMemory,Heap,0,size,8304721920
+    PhysicalDeviceMemory,Heap,0,flags,3
+    PhysicalDeviceMemory,Heap,1,size,8286175232
+    PhysicalDeviceMemory,Heap,1,flags,0
+    PhysicalDeviceMemory,Heap,2,size,268435456
+    PhysicalDeviceMemory,Heap,2,flags,3
+    PhysicalDeviceMemory,TypeCount,4
+    PhysicalDeviceMemory,Type,0,heapIndex,0
+    PhysicalDeviceMemory,Type,0,propertyFlags,1
+    PhysicalDeviceMemory,Type,1,heapIndex,1
+    PhysicalDeviceMemory,Type,1,propertyFlags,6
+    PhysicalDeviceMemory,Type,2,heapIndex,2
+    PhysicalDeviceMemory,Type,2,propertyFlags,7
+    PhysicalDeviceMemory,Type,3,heapIndex,1
+    PhysicalDeviceMemory,Type,3,propertyFlags,14
+    Extension,VK_KHR_dedicated_allocation,1
+    Extension,VK_KHR_bind_memory2,1
+    Extension,VK_EXT_memory_budget,1
+    Macro,VMA_DEBUG_ALWAYS_DEDICATED_MEMORY,0
+    Macro,VMA_DEBUG_ALIGNMENT,1
+    Macro,VMA_DEBUG_MARGIN,0
+    Macro,VMA_DEBUG_INITIALIZE_ALLOCATIONS,0
+    Macro,VMA_DEBUG_DETECT_CORRUPTION,0
+    Macro,VMA_DEBUG_GLOBAL_MUTEX,0
+    Macro,VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY,1
+    Macro,VMA_SMALL_HEAP_MAX_SIZE,1073741824
+    Macro,VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE,268435456
+    Config,End 
+    12552,0.000,0,vmaCreateAllocator
+    12552,0.010,0,vmaCreateImage,0,1,37,128,128,1,1,1,1,1,1,0,8,36,2,0,0,0,0000000000000000,000001D85B8B1A80,
+    12552,0.010,0,vmaSetAllocationUserData,000001D85B8B1A80,Ala ma kota
+    12552,0.015,0,vmaCreateImage,0,1,37,128,128,1,1,1,1,0,6,0,0,0,1,0,0,0,0000000000000000,000001D85B8B1620,
+    12552,0.017,0,vmaDestroyImage,000001D85B8B1A80
+    12552,0.017,0,vmaCreateBuffer,0,768,1,0,4,2,0,0,0,0000000000000000,000001D85B8B19E0,
+    12552,0.017,0,vmaCreateBuffer,0,768,130,0,0,1,0,0,0,0000000000000000,000001D85B8B1A80,
+    12552,0.017,0,vmaCreateBuffer,0,60,1,0,4,2,0,0,0,0000000000000000,000001D85B8B1DA0,
+    12552,0.017,0,vmaCreateBuffer,0,60,66,0,0,1,0,0,0,0000000000000000,000001D85B8B16C0,
+    12552,0.017,0,vmaDestroyBuffer,000001D85B8B1DA0
+    12552,0.017,0,vmaDestroyBuffer,000001D85B8B19E0
+    12552,0.022,0,vmaCreateImage,0,1,126,1424,704,1,1,1,1,0,32,0,0,0,1,0,0,0,0000000000000000,000001D85B8B1EE0,
+    12552,0.048,0,vmaDestroyImage,000001D85B8B1EE0
+    12552,0.053,0,vmaCreateImage,0,1,126,1424,704,1,1,1,1,0,32,0,0,0,1,0,0,0,0000000000000000,000001D85B8B1EE0,
+    12552,0.662,0,vmaDestroyImage,000001D85B8B1EE0
+    12552,0.695,0,vmaDestroyImage,000001D85B8B1620
+    12552,0.695,0,vmaDestroyBuffer,000001D85B8B16C0
+    12552,0.695,0,vmaDestroyBuffer,000001D85B8B1A80
+    12552,0.695,0,vmaDestroyAllocator
diff --git a/third_party/VulkanMemoryAllocator/docs/gfx/Buddy_allocator.png b/third_party/VulkanMemoryAllocator/docs/gfx/Buddy_allocator.png
new file mode 100644
index 0000000..507314d
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/gfx/Buddy_allocator.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/docs/gfx/Linear_allocator_1_algo_default.png b/third_party/VulkanMemoryAllocator/docs/gfx/Linear_allocator_1_algo_default.png
new file mode 100644
index 0000000..e3e8f47
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/gfx/Linear_allocator_1_algo_default.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/docs/gfx/Linear_allocator_2_algo_linear.png b/third_party/VulkanMemoryAllocator/docs/gfx/Linear_allocator_2_algo_linear.png
new file mode 100644
index 0000000..c2a38b2
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/gfx/Linear_allocator_2_algo_linear.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/docs/gfx/Linear_allocator_3_free_at_once.png b/third_party/VulkanMemoryAllocator/docs/gfx/Linear_allocator_3_free_at_once.png
new file mode 100644
index 0000000..a000ad5
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/gfx/Linear_allocator_3_free_at_once.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/docs/gfx/Linear_allocator_4_stack.png b/third_party/VulkanMemoryAllocator/docs/gfx/Linear_allocator_4_stack.png
new file mode 100644
index 0000000..4dba064
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/gfx/Linear_allocator_4_stack.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/docs/gfx/Linear_allocator_5_ring_buffer.png b/third_party/VulkanMemoryAllocator/docs/gfx/Linear_allocator_5_ring_buffer.png
new file mode 100644
index 0000000..0686702
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/gfx/Linear_allocator_5_ring_buffer.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/docs/gfx/Linear_allocator_6_ring_buffer_lost.png b/third_party/VulkanMemoryAllocator/docs/gfx/Linear_allocator_6_ring_buffer_lost.png
new file mode 100644
index 0000000..9a2338c
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/gfx/Linear_allocator_6_ring_buffer_lost.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/docs/gfx/Linear_allocator_7_double_stack.png b/third_party/VulkanMemoryAllocator/docs/gfx/Linear_allocator_7_double_stack.png
new file mode 100644
index 0000000..77d1468
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/gfx/Linear_allocator_7_double_stack.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/docs/gfx/Margins_1.png b/third_party/VulkanMemoryAllocator/docs/gfx/Margins_1.png
new file mode 100644
index 0000000..8c9e184
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/gfx/Margins_1.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/docs/gfx/Margins_2.png b/third_party/VulkanMemoryAllocator/docs/gfx/Margins_2.png
new file mode 100644
index 0000000..6f75877
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/gfx/Margins_2.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/docs/gfx/VMA_class_diagram.png b/third_party/VulkanMemoryAllocator/docs/gfx/VMA_class_diagram.png
new file mode 100644
index 0000000..b472578
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/gfx/VMA_class_diagram.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/docs/html/allocation_annotation.html b/third_party/VulkanMemoryAllocator/docs/html/allocation_annotation.html
new file mode 100644
index 0000000..2fa2acd
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/allocation_annotation.html
@@ -0,0 +1,138 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: Allocation names and user data</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+  <ul>
+<li class="navelem"><a class="el" href="index.html">Vulkan Memory Allocator</a></li>  </ul>
+</div>
+</div><!-- top -->
+<div class="PageDoc"><div class="header">
+  <div class="headertitle">
+<div class="title">Allocation names and user data </div>  </div>
+</div><!--header-->
+<div class="contents">
+<div class="textblock"><h1><a class="anchor" id="allocation_user_data"></a>
+Allocation user data</h1>
+<p>You can annotate allocations with your own information, e.g. for debugging purposes. To do that, fill <a class="el" href="struct_vma_allocation_create_info.html#a8259e85c272683434f4abb4ddddffe19" title="Custom general-purpose pointer that will be stored in VmaAllocation, can be read as VmaAllocationInfo...">VmaAllocationCreateInfo::pUserData</a> field when creating an allocation. It's an opaque <code>void*</code> pointer. You can use it e.g. as a pointer, some handle, index, key, ordinal number or any other value that would associate the allocation with your custom metadata.</p>
+<div class="fragment"><div class="line">VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };</div>
+<div class="line"><span class="comment">// Fill bufferInfo...</span></div>
+<div class="line"> </div>
+<div class="line">MyBufferMetadata* pMetadata = CreateBufferMetadata();</div>
+<div class="line"> </div>
+<div class="line"><a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> allocCreateInfo = {};</div>
+<div class="line">allocCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910">usage</a> = <a class="code" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7">VMA_MEMORY_USAGE_GPU_ONLY</a>;</div>
+<div class="line">allocCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#a8259e85c272683434f4abb4ddddffe19">pUserData</a> = pMetadata;</div>
+<div class="line"> </div>
+<div class="line">VkBuffer buffer;</div>
+<div class="line"><a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation;</div>
+<div class="line"><a class="code" href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer</a>(allocator, &amp;bufferInfo, &amp;allocCreateInfo, &amp;buffer, &amp;allocation, <span class="keyword">nullptr</span>);</div>
+</div><!-- fragment --><p>The pointer may be later retrieved as <a class="el" href="struct_vma_allocation_info.html#adc507656149c04de7ed95d0042ba2a13" title="Custom general-purpose pointer that was passed as VmaAllocationCreateInfo::pUserData or set using vma...">VmaAllocationInfo::pUserData</a>:</p>
+<div class="fragment"><div class="line"><a class="code" href="struct_vma_allocation_info.html">VmaAllocationInfo</a> allocInfo;</div>
+<div class="line"><a class="code" href="vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b">vmaGetAllocationInfo</a>(allocator, allocation, &amp;allocInfo);</div>
+<div class="line">MyBufferMetadata* pMetadata = (MyBufferMetadata*)allocInfo.<a class="code" href="struct_vma_allocation_info.html#adc507656149c04de7ed95d0042ba2a13">pUserData</a>;</div>
+</div><!-- fragment --><p>It can also be changed using function <a class="el" href="vk__mem__alloc_8h.html#af9147d31ffc11d62fc187bde283ed14f" title="Sets pUserData in given allocation to new value.">vmaSetAllocationUserData()</a>.</p>
+<p>Values of (non-zero) allocations' <code>pUserData</code> are printed in JSON report created by <a class="el" href="vk__mem__alloc_8h.html#aa4fee7eb5253377599ef4fd38c93c2a0" title="Builds and returns statistics as string in JSON format.">vmaBuildStatsString()</a>, in hexadecimal form.</p>
+<h1><a class="anchor" id="allocation_names"></a>
+Allocation names</h1>
+<p>There is alternative mode available where <code>pUserData</code> pointer is used to point to a null-terminated string, giving a name to the allocation. To use this mode, set <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597aa6f24f821cd6a7c5e4a443f7bf59c520">VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT</a> flag in <a class="el" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b" title="Use VmaAllocationCreateFlagBits enum.">VmaAllocationCreateInfo::flags</a>. Then <code>pUserData</code> passed as <a class="el" href="struct_vma_allocation_create_info.html#a8259e85c272683434f4abb4ddddffe19" title="Custom general-purpose pointer that will be stored in VmaAllocation, can be read as VmaAllocationInfo...">VmaAllocationCreateInfo::pUserData</a> or argument to <a class="el" href="vk__mem__alloc_8h.html#af9147d31ffc11d62fc187bde283ed14f" title="Sets pUserData in given allocation to new value.">vmaSetAllocationUserData()</a> must be either null or pointer to a null-terminated string. The library creates internal copy of the string, so the pointer you pass doesn't need to be valid for whole lifetime of the allocation. You can free it after the call.</p>
+<div class="fragment"><div class="line">VkImageCreateInfo imageInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };</div>
+<div class="line"><span class="comment">// Fill imageInfo...</span></div>
+<div class="line"> </div>
+<div class="line">std::string imageName = <span class="stringliteral">&quot;Texture: &quot;</span>;</div>
+<div class="line">imageName += fileName;</div>
+<div class="line"> </div>
+<div class="line"><a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> allocCreateInfo = {};</div>
+<div class="line">allocCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910">usage</a> = <a class="code" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7">VMA_MEMORY_USAGE_GPU_ONLY</a>;</div>
+<div class="line">allocCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a> = <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597aa6f24f821cd6a7c5e4a443f7bf59c520">VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT</a>;</div>
+<div class="line">allocCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#a8259e85c272683434f4abb4ddddffe19">pUserData</a> = imageName.c_str();</div>
+<div class="line"> </div>
+<div class="line">VkImage image;</div>
+<div class="line"><a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation;</div>
+<div class="line"><a class="code" href="vk__mem__alloc_8h.html#a02a94f25679275851a53e82eacbcfc73">vmaCreateImage</a>(allocator, &amp;imageInfo, &amp;allocCreateInfo, &amp;image, &amp;allocation, <span class="keyword">nullptr</span>);</div>
+</div><!-- fragment --><p>The value of <code>pUserData</code> pointer of the allocation will be different than the one you passed when setting allocation's name - pointing to a buffer managed internally that holds copy of the string.</p>
+<div class="fragment"><div class="line"><a class="code" href="struct_vma_allocation_info.html">VmaAllocationInfo</a> allocInfo;</div>
+<div class="line"><a class="code" href="vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b">vmaGetAllocationInfo</a>(allocator, allocation, &amp;allocInfo);</div>
+<div class="line"><span class="keyword">const</span> <span class="keywordtype">char</span>* imageName = (<span class="keyword">const</span> <span class="keywordtype">char</span>*)allocInfo.<a class="code" href="struct_vma_allocation_info.html#adc507656149c04de7ed95d0042ba2a13">pUserData</a>;</div>
+<div class="line">printf(<span class="stringliteral">&quot;Image name: %s\n&quot;</span>, imageName);</div>
+</div><!-- fragment --><p>That string is also printed in JSON report created by <a class="el" href="vk__mem__alloc_8h.html#aa4fee7eb5253377599ef4fd38c93c2a0" title="Builds and returns statistics as string in JSON format.">vmaBuildStatsString()</a>.</p>
+<dl class="section note"><dt>Note</dt><dd>Passing string name to VMA allocation doesn't automatically set it to the Vulkan buffer or image created with it. You must do it manually using an extension like VK_EXT_debug_utils, which is independent of this library. </dd></dl>
+</div></div><!-- contents -->
+</div><!-- PageDoc -->
+<div class="ttc" id="avk__mem__alloc_8h_html_ad9889c10c798b040d59c92f257cae597aa6f24f821cd6a7c5e4a443f7bf59c520"><div class="ttname"><a href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597aa6f24f821cd6a7c5e4a443f7bf59c520">VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT</a></div><div class="ttdeci">@ VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2584</div></div>
+<div class="ttc" id="astruct_vma_allocation_create_info_html_a8259e85c272683434f4abb4ddddffe19"><div class="ttname"><a href="struct_vma_allocation_create_info.html#a8259e85c272683434f4abb4ddddffe19">VmaAllocationCreateInfo::pUserData</a></div><div class="ttdeci">void * pUserData</div><div class="ttdoc">Custom general-purpose pointer that will be stored in VmaAllocation, can be read as VmaAllocationInfo...</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2678</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a86dd08aba8633bfa4ad0df2e76481d8b"><div class="ttname"><a href="vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b">vmaGetAllocationInfo</a></div><div class="ttdeci">void vmaGetAllocationInfo(VmaAllocator allocator, VmaAllocation allocation, VmaAllocationInfo *pAllocationInfo)</div><div class="ttdoc">Returns current information about specified allocation and atomically marks it as used in current fra...</div></div>
+<div class="ttc" id="astruct_vma_allocation_html"><div class="ttname"><a href="struct_vma_allocation.html">VmaAllocation</a></div><div class="ttdoc">Represents single memory allocation.</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7"><div class="ttname"><a href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7">VMA_MEMORY_USAGE_GPU_ONLY</a></div><div class="ttdeci">@ VMA_MEMORY_USAGE_GPU_ONLY</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2481</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a02a94f25679275851a53e82eacbcfc73"><div class="ttname"><a href="vk__mem__alloc_8h.html#a02a94f25679275851a53e82eacbcfc73">vmaCreateImage</a></div><div class="ttdeci">VkResult vmaCreateImage(VmaAllocator allocator, const VkImageCreateInfo *pImageCreateInfo, const VmaAllocationCreateInfo *pAllocationCreateInfo, VkImage *pImage, VmaAllocation *pAllocation, VmaAllocationInfo *pAllocationInfo)</div><div class="ttdoc">Function similar to vmaCreateBuffer().</div></div>
+<div class="ttc" id="astruct_vma_allocation_create_info_html_accb8b06b1f677d858cb9af20705fa910"><div class="ttname"><a href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910">VmaAllocationCreateInfo::usage</a></div><div class="ttdeci">VmaMemoryUsage usage</div><div class="ttdoc">Intended usage of memory.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2647</div></div>
+<div class="ttc" id="astruct_vma_allocation_info_html_adc507656149c04de7ed95d0042ba2a13"><div class="ttname"><a href="struct_vma_allocation_info.html#adc507656149c04de7ed95d0042ba2a13">VmaAllocationInfo::pUserData</a></div><div class="ttdeci">void * pUserData</div><div class="ttdoc">Custom general-purpose pointer that was passed as VmaAllocationCreateInfo::pUserData or set using vma...</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3014</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ac72ee55598617e8eecca384e746bab51"><div class="ttname"><a href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer</a></div><div class="ttdeci">VkResult vmaCreateBuffer(VmaAllocator allocator, const VkBufferCreateInfo *pBufferCreateInfo, const VmaAllocationCreateInfo *pAllocationCreateInfo, VkBuffer *pBuffer, VmaAllocation *pAllocation, VmaAllocationInfo *pAllocationInfo)</div></div>
+<div class="ttc" id="astruct_vma_allocation_create_info_html_add09658ac14fe290ace25470ddd6d41b"><div class="ttname"><a href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">VmaAllocationCreateInfo::flags</a></div><div class="ttdeci">VmaAllocationCreateFlags flags</div><div class="ttdoc">Use VmaAllocationCreateFlagBits enum.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2641</div></div>
+<div class="ttc" id="astruct_vma_allocation_create_info_html"><div class="ttname"><a href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a></div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2638</div></div>
+<div class="ttc" id="astruct_vma_allocation_info_html"><div class="ttname"><a href="struct_vma_allocation_info.html">VmaAllocationInfo</a></div><div class="ttdoc">Parameters of VmaAllocation objects, that can be retrieved using function vmaGetAllocationInfo().</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2976</div></div>
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/annotated.html b/third_party/VulkanMemoryAllocator/docs/html/annotated.html
new file mode 100644
index 0000000..a7b103c
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/annotated.html
@@ -0,0 +1,101 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: Class List</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+  <div class="headertitle">
+<div class="title">Class List</div>  </div>
+</div><!--header-->
+<div class="contents">
+<div class="textblock">Here are the classes, structs, unions and interfaces with brief descriptions:</div><div class="directory">
+<table class="directory">
+<tr id="row_0_" class="even"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><span class="icona"><span class="icon">C</span></span><a class="el" href="struct_vma_allocation.html" target="_self">VmaAllocation</a></td><td class="desc">Represents single memory allocation </td></tr>
+<tr id="row_1_"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><span class="icona"><span class="icon">C</span></span><a class="el" href="struct_vma_allocation_create_info.html" target="_self">VmaAllocationCreateInfo</a></td><td class="desc"></td></tr>
+<tr id="row_2_" class="even"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><span class="icona"><span class="icon">C</span></span><a class="el" href="struct_vma_allocation_info.html" target="_self">VmaAllocationInfo</a></td><td class="desc">Parameters of <a class="el" href="struct_vma_allocation.html" title="Represents single memory allocation.">VmaAllocation</a> objects, that can be retrieved using function <a class="el" href="vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b" title="Returns current information about specified allocation and atomically marks it as used in current fra...">vmaGetAllocationInfo()</a> </td></tr>
+<tr id="row_3_"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><span class="icona"><span class="icon">C</span></span><a class="el" href="struct_vma_allocator.html" target="_self">VmaAllocator</a></td><td class="desc">Represents main object of this library initialized </td></tr>
+<tr id="row_4_" class="even"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><span class="icona"><span class="icon">C</span></span><a class="el" href="struct_vma_allocator_create_info.html" target="_self">VmaAllocatorCreateInfo</a></td><td class="desc">Description of a Allocator to be created </td></tr>
+<tr id="row_5_"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><span class="icona"><span class="icon">C</span></span><a class="el" href="struct_vma_allocator_info.html" target="_self">VmaAllocatorInfo</a></td><td class="desc">Information about existing <a class="el" href="struct_vma_allocator.html" title="Represents main object of this library initialized.">VmaAllocator</a> object </td></tr>
+<tr id="row_6_" class="even"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><span class="icona"><span class="icon">C</span></span><a class="el" href="struct_vma_budget.html" target="_self">VmaBudget</a></td><td class="desc">Statistics of current memory usage and available budget, in bytes, for specific memory heap </td></tr>
+<tr id="row_7_"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><span class="icona"><span class="icon">C</span></span><a class="el" href="struct_vma_defragmentation_context.html" target="_self">VmaDefragmentationContext</a></td><td class="desc">Represents Opaque object that represents started defragmentation process </td></tr>
+<tr id="row_8_" class="even"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><span class="icona"><span class="icon">C</span></span><a class="el" href="struct_vma_defragmentation_info.html" target="_self">VmaDefragmentationInfo</a></td><td class="desc">Deprecated. Optional configuration parameters to be passed to function <a class="el" href="vk__mem__alloc_8h.html#a6aced90fcc7b39882b6654a740a0b9bb" title="Deprecated. Compacts memory by moving allocations.">vmaDefragment()</a> </td></tr>
+<tr id="row_9_"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><span class="icona"><span class="icon">C</span></span><a class="el" href="struct_vma_defragmentation_info2.html" target="_self">VmaDefragmentationInfo2</a></td><td class="desc">Parameters for defragmentation </td></tr>
+<tr id="row_10_" class="even"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><span class="icona"><span class="icon">C</span></span><a class="el" href="struct_vma_defragmentation_pass_info.html" target="_self">VmaDefragmentationPassInfo</a></td><td class="desc">Parameters for incremental defragmentation steps </td></tr>
+<tr id="row_11_"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><span class="icona"><span class="icon">C</span></span><a class="el" href="struct_vma_defragmentation_pass_move_info.html" target="_self">VmaDefragmentationPassMoveInfo</a></td><td class="desc"></td></tr>
+<tr id="row_12_" class="even"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><span class="icona"><span class="icon">C</span></span><a class="el" href="struct_vma_defragmentation_stats.html" target="_self">VmaDefragmentationStats</a></td><td class="desc">Statistics returned by function <a class="el" href="vk__mem__alloc_8h.html#a6aced90fcc7b39882b6654a740a0b9bb" title="Deprecated. Compacts memory by moving allocations.">vmaDefragment()</a> </td></tr>
+<tr id="row_13_"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><span class="icona"><span class="icon">C</span></span><a class="el" href="struct_vma_device_memory_callbacks.html" target="_self">VmaDeviceMemoryCallbacks</a></td><td class="desc">Set of callbacks that the library will call for <code>vkAllocateMemory</code> and <code>vkFreeMemory</code> </td></tr>
+<tr id="row_14_" class="even"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><span class="icona"><span class="icon">C</span></span><a class="el" href="struct_vma_pool.html" target="_self">VmaPool</a></td><td class="desc">Represents custom memory pool </td></tr>
+<tr id="row_15_"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><span class="icona"><span class="icon">C</span></span><a class="el" href="struct_vma_pool_create_info.html" target="_self">VmaPoolCreateInfo</a></td><td class="desc">Describes parameter of created <a class="el" href="struct_vma_pool.html" title="Represents custom memory pool.">VmaPool</a> </td></tr>
+<tr id="row_16_" class="even"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><span class="icona"><span class="icon">C</span></span><a class="el" href="struct_vma_pool_stats.html" target="_self">VmaPoolStats</a></td><td class="desc">Describes parameter of existing <a class="el" href="struct_vma_pool.html" title="Represents custom memory pool.">VmaPool</a> </td></tr>
+<tr id="row_17_"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><span class="icona"><span class="icon">C</span></span><a class="el" href="struct_vma_record_settings.html" target="_self">VmaRecordSettings</a></td><td class="desc">Parameters for recording calls to VMA functions. To be used in <a class="el" href="struct_vma_allocator_create_info.html#ace2aa4877b16a42b0b7673d4e26000ee" title="Parameters for recording of VMA calls. Can be null.">VmaAllocatorCreateInfo::pRecordSettings</a> </td></tr>
+<tr id="row_18_" class="even"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><span class="icona"><span class="icon">C</span></span><a class="el" href="struct_vma_stat_info.html" target="_self">VmaStatInfo</a></td><td class="desc">Calculated statistics of memory usage in entire allocator </td></tr>
+<tr id="row_19_"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><span class="icona"><span class="icon">C</span></span><a class="el" href="struct_vma_stats.html" target="_self">VmaStats</a></td><td class="desc">General statistics from current state of Allocator </td></tr>
+<tr id="row_20_" class="even"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><span class="icona"><span class="icon">C</span></span><a class="el" href="struct_vma_vulkan_functions.html" target="_self">VmaVulkanFunctions</a></td><td class="desc">Pointers to some Vulkan functions - a subset used by the library </td></tr>
+</table>
+</div><!-- directory -->
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/bc_s.png b/third_party/VulkanMemoryAllocator/docs/html/bc_s.png
new file mode 100644
index 0000000..224b29a
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/bc_s.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/docs/html/bdwn.png b/third_party/VulkanMemoryAllocator/docs/html/bdwn.png
new file mode 100644
index 0000000..940a0b9
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/bdwn.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/docs/html/choosing_memory_type.html b/third_party/VulkanMemoryAllocator/docs/html/choosing_memory_type.html
new file mode 100644
index 0000000..903a985
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/choosing_memory_type.html
@@ -0,0 +1,151 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: Choosing memory type</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+  <ul>
+<li class="navelem"><a class="el" href="index.html">Vulkan Memory Allocator</a></li>  </ul>
+</div>
+</div><!-- top -->
+<div class="PageDoc"><div class="header">
+  <div class="headertitle">
+<div class="title">Choosing memory type </div>  </div>
+</div><!--header-->
+<div class="contents">
+<div class="textblock"><p>Physical devices in Vulkan support various combinations of memory heaps and types. Help with choosing correct and optimal memory type for your specific resource is one of the key features of this library. You can use it by filling appropriate members of <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> structure, as described below. You can also combine multiple methods.</p>
+<ol type="1">
+<li>If you just want to find memory type index that meets your requirements, you can use function: <a class="el" href="vk__mem__alloc_8h.html#aef15a94b58fbcb0fe706d5720e84a74a" title="Helps to find memoryTypeIndex, given memoryTypeBits and VmaAllocationCreateInfo.">vmaFindMemoryTypeIndex()</a>, <a class="el" href="vk__mem__alloc_8h.html#ae790ab9ffaf7667fb8f62523e6897888" title="Helps to find memoryTypeIndex, given VkBufferCreateInfo and VmaAllocationCreateInfo.">vmaFindMemoryTypeIndexForBufferInfo()</a>, <a class="el" href="vk__mem__alloc_8h.html#a088da83d8eaf3ce9056d9ea0b981d472" title="Helps to find memoryTypeIndex, given VkImageCreateInfo and VmaAllocationCreateInfo.">vmaFindMemoryTypeIndexForImageInfo()</a>.</li>
+<li>If you want to allocate a region of device memory without association with any specific image or buffer, you can use function <a class="el" href="vk__mem__alloc_8h.html#abf28077dbf82d0908b8acbe8ee8dd9b8" title="General purpose memory allocation.">vmaAllocateMemory()</a>. Usage of this function is not recommended and usually not needed. <a class="el" href="vk__mem__alloc_8h.html#ad37e82e492b3de38fc3f4cffd9ad0ae1" title="General purpose memory allocation for multiple allocation objects at once.">vmaAllocateMemoryPages()</a> function is also provided for creating multiple allocations at once, which may be useful for sparse binding.</li>
+<li>If you already have a buffer or an image created, you want to allocate memory for it and then you will bind it yourself, you can use function <a class="el" href="vk__mem__alloc_8h.html#a7fdf64415b6c3d83c454f28d2c53df7b">vmaAllocateMemoryForBuffer()</a>, <a class="el" href="vk__mem__alloc_8h.html#a0faa3f9e5fb233d29d1e00390650febb" title="Function similar to vmaAllocateMemoryForBuffer().">vmaAllocateMemoryForImage()</a>. For binding you should use functions: <a class="el" href="vk__mem__alloc_8h.html#a6b0929b914b60cf2d45cac4bf3547470" title="Binds buffer to allocation.">vmaBindBufferMemory()</a>, <a class="el" href="vk__mem__alloc_8h.html#a3d3ca45799923aa5d138e9e5f9eb2da5" title="Binds image to allocation.">vmaBindImageMemory()</a> or their extended versions: <a class="el" href="vk__mem__alloc_8h.html#a927c944f45e0f2941182abb6f608e64a" title="Binds buffer to allocation with additional parameters.">vmaBindBufferMemory2()</a>, <a class="el" href="vk__mem__alloc_8h.html#aa8251ee81b0045a443e35b8e8aa021bc" title="Binds image to allocation with additional parameters.">vmaBindImageMemory2()</a>.</li>
+<li>If you want to create a buffer or an image, allocate memory for it and bind them together, all in one call, you can use function <a class="el" href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer()</a>, <a class="el" href="vk__mem__alloc_8h.html#a02a94f25679275851a53e82eacbcfc73" title="Function similar to vmaCreateBuffer().">vmaCreateImage()</a>. This is the easiest and recommended way to use this library.</li>
+</ol>
+<p>When using 3. or 4., the library internally queries Vulkan for memory types supported for that buffer or image (function <code>vkGetBufferMemoryRequirements()</code>) and uses only one of these types.</p>
+<p>If no memory type can be found that meets all the requirements, these functions return <code>VK_ERROR_FEATURE_NOT_PRESENT</code>.</p>
+<p>You can leave <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> structure completely filled with zeros. It means no requirements are specified for memory type. It is valid, although not very useful.</p>
+<h1><a class="anchor" id="choosing_memory_type_usage"></a>
+Usage</h1>
+<p>The easiest way to specify memory requirements is to fill member <a class="el" href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910" title="Intended usage of memory.">VmaAllocationCreateInfo::usage</a> using one of the values of enum <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cc">VmaMemoryUsage</a>. It defines high level, common usage types. For more details, see description of this enum.</p>
+<p>For example, if you want to create a uniform buffer that will be filled using transfer only once or infrequently and used for rendering every frame, you can do it using following code:</p>
+<div class="fragment"><div class="line">VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };</div>
+<div class="line">bufferInfo.size = 65536;</div>
+<div class="line">bufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;</div>
+<div class="line"> </div>
+<div class="line"><a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> allocInfo = {};</div>
+<div class="line">allocInfo.<a class="code" href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910">usage</a> = <a class="code" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7">VMA_MEMORY_USAGE_GPU_ONLY</a>;</div>
+<div class="line"> </div>
+<div class="line">VkBuffer buffer;</div>
+<div class="line"><a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation;</div>
+<div class="line"><a class="code" href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer</a>(allocator, &amp;bufferInfo, &amp;allocInfo, &amp;buffer, &amp;allocation, <span class="keyword">nullptr</span>);</div>
+</div><!-- fragment --><h1><a class="anchor" id="choosing_memory_type_required_preferred_flags"></a>
+Required and preferred flags</h1>
+<p>You can specify more detailed requirements by filling members <a class="el" href="struct_vma_allocation_create_info.html#a9166390303ff42d783305bc31c2b6b90" title="Flags that must be set in a Memory Type chosen for an allocation.">VmaAllocationCreateInfo::requiredFlags</a> and <a class="el" href="struct_vma_allocation_create_info.html#a7fe8d81a1ad10b2a2faacacee5b15d6d" title="Flags that preferably should be set in a memory type chosen for an allocation.">VmaAllocationCreateInfo::preferredFlags</a> with a combination of bits from enum <code>VkMemoryPropertyFlags</code>. For example, if you want to create a buffer that will be persistently mapped on host (so it must be <code>HOST_VISIBLE</code>) and preferably will also be <code>HOST_COHERENT</code> and <code>HOST_CACHED</code>, use following code:</p>
+<div class="fragment"><div class="line"><a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> allocInfo = {};</div>
+<div class="line">allocInfo.<a class="code" href="struct_vma_allocation_create_info.html#a9166390303ff42d783305bc31c2b6b90">requiredFlags</a> = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;</div>
+<div class="line">allocInfo.<a class="code" href="struct_vma_allocation_create_info.html#a7fe8d81a1ad10b2a2faacacee5b15d6d">preferredFlags</a> = VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT;</div>
+<div class="line">allocInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a> = <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a11da372cc3a82931c5e5d6146cd9dd1f">VMA_ALLOCATION_CREATE_MAPPED_BIT</a>;</div>
+<div class="line"> </div>
+<div class="line">VkBuffer buffer;</div>
+<div class="line"><a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation;</div>
+<div class="line"><a class="code" href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer</a>(allocator, &amp;bufferInfo, &amp;allocInfo, &amp;buffer, &amp;allocation, <span class="keyword">nullptr</span>);</div>
+</div><!-- fragment --><p>A memory type is chosen that has all the required flags and as many preferred flags set as possible.</p>
+<p>If you use <a class="el" href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910" title="Intended usage of memory.">VmaAllocationCreateInfo::usage</a>, it is just internally converted to a set of required and preferred flags.</p>
+<h1><a class="anchor" id="choosing_memory_type_explicit_memory_types"></a>
+Explicit memory types</h1>
+<p>If you inspected memory types available on the physical device and you have a preference for memory types that you want to use, you can fill member <a class="el" href="struct_vma_allocation_create_info.html#a3bf940c0271d85d6ba32a4d820075055" title="Bitmask containing one bit set for every memory type acceptable for this allocation.">VmaAllocationCreateInfo::memoryTypeBits</a>. It is a bit mask, where each bit set means that a memory type with that index is allowed to be used for the allocation. Special value 0, just like <code>UINT32_MAX</code>, means there are no restrictions to memory type index.</p>
+<p>Please note that this member is NOT just a memory type index. Still you can use it to choose just one, specific memory type. For example, if you already determined that your buffer should be created in memory type 2, use following code:</p>
+<div class="fragment"><div class="line">uint32_t memoryTypeIndex = 2;</div>
+<div class="line"> </div>
+<div class="line"><a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> allocInfo = {};</div>
+<div class="line">allocInfo.<a class="code" href="struct_vma_allocation_create_info.html#a3bf940c0271d85d6ba32a4d820075055">memoryTypeBits</a> = 1u &lt;&lt; memoryTypeIndex;</div>
+<div class="line"> </div>
+<div class="line">VkBuffer buffer;</div>
+<div class="line"><a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation;</div>
+<div class="line"><a class="code" href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer</a>(allocator, &amp;bufferInfo, &amp;allocInfo, &amp;buffer, &amp;allocation, <span class="keyword">nullptr</span>);</div>
+</div><!-- fragment --><h1><a class="anchor" id="choosing_memory_type_custom_memory_pools"></a>
+Custom memory pools</h1>
+<p>If you allocate from custom memory pool, all the ways of specifying memory requirements described above are not applicable and the aforementioned members of <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> structure are ignored. Memory type is selected explicitly when creating the pool and then used to make all the allocations from that pool. For further details, see <a class="el" href="custom_memory_pools.html">Custom memory pools</a>.</p>
+<h1><a class="anchor" id="choosing_memory_type_dedicated_allocations"></a>
+Dedicated allocations</h1>
+<p>Memory for allocations is reserved out of larger block of <code>VkDeviceMemory</code> allocated from Vulkan internally. That's the main feature of this whole library. You can still request a separate memory block to be created for an allocation, just like you would do in a trivial solution without using any allocator. In that case, a buffer or image is always bound to that memory at offset 0. This is called a "dedicated allocation". You can explicitly request it by using flag <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a3fc311d855c2ff53f1090ef5c722b38f" title="Set this flag if the allocation should have its own memory block.">VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT</a>. The library can also internally decide to use dedicated allocation in some cases, e.g.:</p>
+<ul>
+<li>When the size of the allocation is large.</li>
+<li>When <a class="el" href="vk_khr_dedicated_allocation.html">VK_KHR_dedicated_allocation</a> extension is enabled and it reports that dedicated allocation is required or recommended for the resource.</li>
+<li>When allocation of next big memory block fails due to not enough device memory, but allocation with the exact requested size succeeds. </li>
+</ul>
+</div></div><!-- contents -->
+</div><!-- PageDoc -->
+<div class="ttc" id="astruct_vma_allocation_html"><div class="ttname"><a href="struct_vma_allocation.html">VmaAllocation</a></div><div class="ttdoc">Represents single memory allocation.</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7"><div class="ttname"><a href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7">VMA_MEMORY_USAGE_GPU_ONLY</a></div><div class="ttdeci">@ VMA_MEMORY_USAGE_GPU_ONLY</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2481</div></div>
+<div class="ttc" id="astruct_vma_allocation_create_info_html_a9166390303ff42d783305bc31c2b6b90"><div class="ttname"><a href="struct_vma_allocation_create_info.html#a9166390303ff42d783305bc31c2b6b90">VmaAllocationCreateInfo::requiredFlags</a></div><div class="ttdeci">VkMemoryPropertyFlags requiredFlags</div><div class="ttdoc">Flags that must be set in a Memory Type chosen for an allocation.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2652</div></div>
+<div class="ttc" id="astruct_vma_allocation_create_info_html_accb8b06b1f677d858cb9af20705fa910"><div class="ttname"><a href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910">VmaAllocationCreateInfo::usage</a></div><div class="ttdeci">VmaMemoryUsage usage</div><div class="ttdoc">Intended usage of memory.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2647</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ac72ee55598617e8eecca384e746bab51"><div class="ttname"><a href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer</a></div><div class="ttdeci">VkResult vmaCreateBuffer(VmaAllocator allocator, const VkBufferCreateInfo *pBufferCreateInfo, const VmaAllocationCreateInfo *pAllocationCreateInfo, VkBuffer *pBuffer, VmaAllocation *pAllocation, VmaAllocationInfo *pAllocationInfo)</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ad9889c10c798b040d59c92f257cae597a11da372cc3a82931c5e5d6146cd9dd1f"><div class="ttname"><a href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a11da372cc3a82931c5e5d6146cd9dd1f">VMA_ALLOCATION_CREATE_MAPPED_BIT</a></div><div class="ttdeci">@ VMA_ALLOCATION_CREATE_MAPPED_BIT</div><div class="ttdoc">Set this flag to use a memory that will be persistently mapped and retrieve pointer to it.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2558</div></div>
+<div class="ttc" id="astruct_vma_allocation_create_info_html_add09658ac14fe290ace25470ddd6d41b"><div class="ttname"><a href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">VmaAllocationCreateInfo::flags</a></div><div class="ttdeci">VmaAllocationCreateFlags flags</div><div class="ttdoc">Use VmaAllocationCreateFlagBits enum.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2641</div></div>
+<div class="ttc" id="astruct_vma_allocation_create_info_html"><div class="ttname"><a href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a></div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2638</div></div>
+<div class="ttc" id="astruct_vma_allocation_create_info_html_a7fe8d81a1ad10b2a2faacacee5b15d6d"><div class="ttname"><a href="struct_vma_allocation_create_info.html#a7fe8d81a1ad10b2a2faacacee5b15d6d">VmaAllocationCreateInfo::preferredFlags</a></div><div class="ttdeci">VkMemoryPropertyFlags preferredFlags</div><div class="ttdoc">Flags that preferably should be set in a memory type chosen for an allocation.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2657</div></div>
+<div class="ttc" id="astruct_vma_allocation_create_info_html_a3bf940c0271d85d6ba32a4d820075055"><div class="ttname"><a href="struct_vma_allocation_create_info.html#a3bf940c0271d85d6ba32a4d820075055">VmaAllocationCreateInfo::memoryTypeBits</a></div><div class="ttdeci">uint32_t memoryTypeBits</div><div class="ttdoc">Bitmask containing one bit set for every memory type acceptable for this allocation.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2665</div></div>
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/classes.html b/third_party/VulkanMemoryAllocator/docs/html/classes.html
new file mode 100644
index 0000000..0206f55
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/classes.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: Class Index</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+  <div class="headertitle">
+<div class="title">Class Index</div>  </div>
+</div><!--header-->
+<div class="contents">
+<div class="qindex"><a class="qindex" href="#letter_v">v</a></div>
+<table class="classindex">
+<tr><td rowspan="2" valign="bottom"><a name="letter_v"></a><table border="0" cellspacing="0" cellpadding="0"><tr><td><div class="ah">&#160;&#160;v&#160;&#160;</div></td></tr></table>
+</td>
+<td valign="top"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;&#160;&#160;</td>
+<td valign="top"><a class="el" href="struct_vma_defragmentation_info.html">VmaDefragmentationInfo</a>&#160;&#160;&#160;</td>
+<td valign="top"><a class="el" href="struct_vma_device_memory_callbacks.html">VmaDeviceMemoryCallbacks</a>&#160;&#160;&#160;</td>
+<td valign="top"><a class="el" href="struct_vma_stat_info.html">VmaStatInfo</a>&#160;&#160;&#160;</td>
+</tr>
+<tr><td valign="top"><a class="el" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a>&#160;&#160;&#160;</td>
+<td valign="top"><a class="el" href="struct_vma_defragmentation_info2.html">VmaDefragmentationInfo2</a>&#160;&#160;&#160;</td>
+<td valign="top"><a class="el" href="struct_vma_pool.html">VmaPool</a>&#160;&#160;&#160;</td>
+<td valign="top"><a class="el" href="struct_vma_stats.html">VmaStats</a>&#160;&#160;&#160;</td>
+</tr>
+<tr><td valign="top"><a class="el" href="struct_vma_allocation.html">VmaAllocation</a>&#160;&#160;&#160;</td>
+<td valign="top"><a class="el" href="struct_vma_allocator_info.html">VmaAllocatorInfo</a>&#160;&#160;&#160;</td>
+<td valign="top"><a class="el" href="struct_vma_defragmentation_pass_info.html">VmaDefragmentationPassInfo</a>&#160;&#160;&#160;</td>
+<td valign="top"><a class="el" href="struct_vma_pool_create_info.html">VmaPoolCreateInfo</a>&#160;&#160;&#160;</td>
+<td valign="top"><a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a>&#160;&#160;&#160;</td>
+</tr>
+<tr><td valign="top"><a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>&#160;&#160;&#160;</td>
+<td valign="top"><a class="el" href="struct_vma_budget.html">VmaBudget</a>&#160;&#160;&#160;</td>
+<td valign="top"><a class="el" href="struct_vma_defragmentation_pass_move_info.html">VmaDefragmentationPassMoveInfo</a>&#160;&#160;&#160;</td>
+<td valign="top"><a class="el" href="struct_vma_pool_stats.html">VmaPoolStats</a>&#160;&#160;&#160;</td>
+<td></td></tr>
+<tr><td valign="top"><a class="el" href="struct_vma_allocation_info.html">VmaAllocationInfo</a>&#160;&#160;&#160;</td>
+<td valign="top"><a class="el" href="struct_vma_defragmentation_context.html">VmaDefragmentationContext</a>&#160;&#160;&#160;</td>
+<td valign="top"><a class="el" href="struct_vma_defragmentation_stats.html">VmaDefragmentationStats</a>&#160;&#160;&#160;</td>
+<td valign="top"><a class="el" href="struct_vma_record_settings.html">VmaRecordSettings</a>&#160;&#160;&#160;</td>
+<td></td></tr>
+<tr><td></td><td></td><td></td><td></td><td></td></tr>
+</table>
+<div class="qindex"><a class="qindex" href="#letter_v">v</a></div>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/closed.png b/third_party/VulkanMemoryAllocator/docs/html/closed.png
new file mode 100644
index 0000000..98cc2c9
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/closed.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/docs/html/configuration.html b/third_party/VulkanMemoryAllocator/docs/html/configuration.html
new file mode 100644
index 0000000..e7d280b
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/configuration.html
@@ -0,0 +1,103 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: Configuration</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+  <ul>
+<li class="navelem"><a class="el" href="index.html">Vulkan Memory Allocator</a></li>  </ul>
+</div>
+</div><!-- top -->
+<div class="PageDoc"><div class="header">
+  <div class="headertitle">
+<div class="title">Configuration </div>  </div>
+</div><!--header-->
+<div class="contents">
+<div class="textblock"><p>Please check "CONFIGURATION SECTION" in the code to find macros that you can define before each include of this file or change directly in this file to provide your own implementation of basic facilities like assert, <code>min()</code> and <code>max()</code> functions, mutex, atomic etc. The library uses its own implementation of containers by default, but you can switch to using STL containers instead.</p>
+<p>For example, define <code>VMA_ASSERT(expr)</code> before including the library to provide custom implementation of the assertion, compatible with your project. By default it is defined to standard C <code>assert(expr)</code> in <code>_DEBUG</code> configuration and empty otherwise.</p>
+<h1><a class="anchor" id="config_Vulkan_functions"></a>
+Pointers to Vulkan functions</h1>
+<p>There are multiple ways to import pointers to Vulkan functions in the library. In the simplest case you don't need to do anything. If the compilation or linking of your program or the initialization of the <a class="el" href="struct_vma_allocator.html" title="Represents main object of this library initialized.">VmaAllocator</a> doesn't work for you, you can try to reconfigure it.</p>
+<p>First, the allocator tries to fetch pointers to Vulkan functions linked statically, like this:</p>
+<div class="fragment"><div class="line">m_VulkanFunctions.vkAllocateMemory = (PFN_vkAllocateMemory)vkAllocateMemory;</div>
+</div><!-- fragment --><p>If you want to disable this feature, set configuration macro: <code>#define VMA_STATIC_VULKAN_FUNCTIONS 0</code>.</p>
+<p>Second, you can provide the pointers yourself by setting member <a class="el" href="struct_vma_allocator_create_info.html#a3dc197be3227da7338b1643f70db36bd" title="Pointers to Vulkan functions. Can be null.">VmaAllocatorCreateInfo::pVulkanFunctions</a>. You can fetch them e.g. using functions <code>vkGetInstanceProcAddr</code> and <code>vkGetDeviceProcAddr</code> or by using a helper library like <a href="https://github.com/zeux/volk">volk</a>.</p>
+<p>Third, VMA tries to fetch remaining pointers that are still null by calling <code>vkGetInstanceProcAddr</code> and <code>vkGetDeviceProcAddr</code> on its own. If you want to disable this feature, set configuration macro: <code>#define VMA_DYNAMIC_VULKAN_FUNCTIONS 0</code>.</p>
+<p>Finally, all the function pointers required by the library (considering selected Vulkan version and enabled extensions) are checked with <code>VMA_ASSERT</code> if they are not null.</p>
+<h1><a class="anchor" id="custom_memory_allocator"></a>
+Custom host memory allocator</h1>
+<p>If you use custom allocator for CPU memory rather than default operator <code>new</code> and <code>delete</code> from C++, you can make this library using your allocator as well by filling optional member <a class="el" href="struct_vma_allocator_create_info.html#a6e409087e3be55400d0e4ccbe43c608d" title="Custom CPU memory allocation callbacks. Optional.">VmaAllocatorCreateInfo::pAllocationCallbacks</a>. These functions will be passed to Vulkan, as well as used by the library itself to make any CPU-side allocations.</p>
+<h1><a class="anchor" id="allocation_callbacks"></a>
+Device memory allocation callbacks</h1>
+<p>The library makes calls to <code>vkAllocateMemory()</code> and <code>vkFreeMemory()</code> internally. You can setup callbacks to be informed about these calls, e.g. for the purpose of gathering some statistics. To do it, fill optional member <a class="el" href="struct_vma_allocator_create_info.html#af1380969b5e1ea4c3184a877892d260e" title="Informative callbacks for vkAllocateMemory, vkFreeMemory. Optional.">VmaAllocatorCreateInfo::pDeviceMemoryCallbacks</a>.</p>
+<h1><a class="anchor" id="heap_memory_limit"></a>
+Device heap memory limit</h1>
+<p>When device memory of certain heap runs out of free space, new allocations may fail (returning error code) or they may succeed, silently pushing some existing memory blocks from GPU VRAM to system RAM (which degrades performance). This behavior is implementation-dependant - it depends on GPU vendor and graphics driver.</p>
+<p>On AMD cards it can be controlled while creating Vulkan device object by using VK_AMD_memory_overallocation_behavior extension, if available.</p>
+<p>Alternatively, if you want to test how your program behaves with limited amount of Vulkan device memory available without switching your graphics card to one that really has smaller VRAM, you can use a feature of this library intended for this purpose. To do it, fill optional member <a class="el" href="struct_vma_allocator_create_info.html#a31c192aa6cbffa33279f6d9f0c47c44b" title="Either null or a pointer to an array of limits on maximum number of bytes that can be allocated out o...">VmaAllocatorCreateInfo::pHeapSizeLimit</a>. </p>
+</div></div><!-- contents -->
+</div><!-- PageDoc -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/custom_memory_pools.html b/third_party/VulkanMemoryAllocator/docs/html/custom_memory_pools.html
new file mode 100644
index 0000000..a4bf412
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/custom_memory_pools.html
@@ -0,0 +1,205 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: Custom memory pools</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+  <ul>
+<li class="navelem"><a class="el" href="index.html">Vulkan Memory Allocator</a></li>  </ul>
+</div>
+</div><!-- top -->
+<div class="PageDoc"><div class="header">
+  <div class="headertitle">
+<div class="title">Custom memory pools </div>  </div>
+</div><!--header-->
+<div class="contents">
+<div class="textblock"><p>A memory pool contains a number of <code>VkDeviceMemory</code> blocks. The library automatically creates and manages default pool for each memory type available on the device. Default memory pool automatically grows in size. Size of allocated blocks is also variable and managed automatically.</p>
+<p>You can create custom pool and allocate memory out of it. It can be useful if you want to:</p>
+<ul>
+<li>Keep certain kind of allocations separate from others.</li>
+<li>Enforce particular, fixed size of Vulkan memory blocks.</li>
+<li>Limit maximum amount of Vulkan memory allocated for that pool.</li>
+<li>Reserve minimum or fixed amount of Vulkan memory always preallocated for that pool.</li>
+</ul>
+<p>To use custom memory pools:</p>
+<ol type="1">
+<li>Fill <a class="el" href="struct_vma_pool_create_info.html" title="Describes parameter of created VmaPool.">VmaPoolCreateInfo</a> structure.</li>
+<li>Call <a class="el" href="vk__mem__alloc_8h.html#a5c8770ded7c59c8caac6de0c2cb00b50" title="Allocates Vulkan device memory and creates VmaPool object.">vmaCreatePool()</a> to obtain <a class="el" href="struct_vma_pool.html" title="Represents custom memory pool.">VmaPool</a> handle.</li>
+<li>When making an allocation, set <a class="el" href="struct_vma_allocation_create_info.html#a6272c0555cfd1fe28bff1afeb6190150" title="Pool that this allocation should be created in.">VmaAllocationCreateInfo::pool</a> to this handle. You don't need to specify any other parameters of this structure, like <code>usage</code>.</li>
+</ol>
+<p>Example:</p>
+<div class="fragment"><div class="line"><span class="comment">// Create a pool that can have at most 2 blocks, 128 MiB each.</span></div>
+<div class="line"><a class="code" href="struct_vma_pool_create_info.html">VmaPoolCreateInfo</a> poolCreateInfo = {};</div>
+<div class="line">poolCreateInfo.<a class="code" href="struct_vma_pool_create_info.html#a596fa76b685d3f1f688f84a709a5b319">memoryTypeIndex</a> = ...</div>
+<div class="line">poolCreateInfo.blockSize = 128ull * 1024 * 1024;</div>
+<div class="line">poolCreateInfo.<a class="code" href="struct_vma_pool_create_info.html#ae41142f2834fcdc82baa4883c187b75c">maxBlockCount</a> = 2;</div>
+<div class="line"> </div>
+<div class="line"><a class="code" href="struct_vma_pool.html">VmaPool</a> pool;</div>
+<div class="line"><a class="code" href="vk__mem__alloc_8h.html#a5c8770ded7c59c8caac6de0c2cb00b50">vmaCreatePool</a>(allocator, &amp;poolCreateInfo, &amp;pool);</div>
+<div class="line"> </div>
+<div class="line"><span class="comment">// Allocate a buffer out of it.</span></div>
+<div class="line">VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };</div>
+<div class="line">bufCreateInfo.size = 1024;</div>
+<div class="line">bufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;</div>
+<div class="line"> </div>
+<div class="line"><a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> allocCreateInfo = {};</div>
+<div class="line">allocCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#a6272c0555cfd1fe28bff1afeb6190150">pool</a> = pool;</div>
+<div class="line"> </div>
+<div class="line">VkBuffer buf;</div>
+<div class="line"><a class="code" href="struct_vma_allocation.html">VmaAllocation</a> alloc;</div>
+<div class="line"><a class="code" href="struct_vma_allocation_info.html">VmaAllocationInfo</a> allocInfo;</div>
+<div class="line"><a class="code" href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer</a>(allocator, &amp;bufCreateInfo, &amp;allocCreateInfo, &amp;buf, &amp;alloc, &amp;allocInfo);</div>
+</div><!-- fragment --><p>You have to free all allocations made from this pool before destroying it.</p>
+<div class="fragment"><div class="line"><a class="code" href="vk__mem__alloc_8h.html#a0d9f4e4ba5bf9aab1f1c746387753d77">vmaDestroyBuffer</a>(allocator, buf, alloc);</div>
+<div class="line"><a class="code" href="vk__mem__alloc_8h.html#a5485779c8f1948238fc4e92232fa65e1">vmaDestroyPool</a>(allocator, pool);</div>
+</div><!-- fragment --><h1><a class="anchor" id="custom_memory_pools_MemTypeIndex"></a>
+Choosing memory type index</h1>
+<p>When creating a pool, you must explicitly specify memory type index. To find the one suitable for your buffers or images, you can use helper functions <a class="el" href="vk__mem__alloc_8h.html#ae790ab9ffaf7667fb8f62523e6897888" title="Helps to find memoryTypeIndex, given VkBufferCreateInfo and VmaAllocationCreateInfo.">vmaFindMemoryTypeIndexForBufferInfo()</a>, <a class="el" href="vk__mem__alloc_8h.html#a088da83d8eaf3ce9056d9ea0b981d472" title="Helps to find memoryTypeIndex, given VkImageCreateInfo and VmaAllocationCreateInfo.">vmaFindMemoryTypeIndexForImageInfo()</a>. You need to provide structures with example parameters of buffers or images that you are going to create in that pool.</p>
+<div class="fragment"><div class="line">VkBufferCreateInfo exampleBufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };</div>
+<div class="line">exampleBufCreateInfo.size = 1024; <span class="comment">// Whatever.</span></div>
+<div class="line">exampleBufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; <span class="comment">// Change if needed.</span></div>
+<div class="line"> </div>
+<div class="line"><a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> allocCreateInfo = {};</div>
+<div class="line">allocCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910">usage</a> = <a class="code" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7">VMA_MEMORY_USAGE_GPU_ONLY</a>; <span class="comment">// Change if needed.</span></div>
+<div class="line"> </div>
+<div class="line">uint32_t memTypeIndex;</div>
+<div class="line"><a class="code" href="vk__mem__alloc_8h.html#ae790ab9ffaf7667fb8f62523e6897888">vmaFindMemoryTypeIndexForBufferInfo</a>(allocator, &amp;exampleBufCreateInfo, &amp;allocCreateInfo, &amp;memTypeIndex);</div>
+<div class="line"> </div>
+<div class="line"><a class="code" href="struct_vma_pool_create_info.html">VmaPoolCreateInfo</a> poolCreateInfo = {};</div>
+<div class="line">poolCreateInfo.<a class="code" href="struct_vma_pool_create_info.html#a596fa76b685d3f1f688f84a709a5b319">memoryTypeIndex</a> = memTypeIndex;</div>
+<div class="line"><span class="comment">// ...</span></div>
+</div><!-- fragment --><p>When creating buffers/images allocated in that pool, provide following parameters:</p>
+<ul>
+<li><code>VkBufferCreateInfo</code>: Prefer to pass same parameters as above. Otherwise you risk creating resources in a memory type that is not suitable for them, which may result in undefined behavior. Using different <code>VK_BUFFER_USAGE_</code> flags may work, but you shouldn't create images in a pool intended for buffers or the other way around.</li>
+<li><a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>: You don't need to pass same parameters. Fill only <code>pool</code> member. Other members are ignored anyway.</li>
+</ul>
+<h1><a class="anchor" id="linear_algorithm"></a>
+Linear allocation algorithm</h1>
+<p>Each Vulkan memory block managed by this library has accompanying metadata that keeps track of used and unused regions. By default, the metadata structure and algorithm tries to find best place for new allocations among free regions to optimize memory usage. This way you can allocate and free objects in any order.</p>
+<p><img src="../gfx/Linear_allocator_1_algo_default.png" alt="Default allocation algorithm" class="inline"/></p>
+<p>Sometimes there is a need to use simpler, linear allocation algorithm. You can create custom pool that uses such algorithm by adding flag <a class="el" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a13c8a444197c67866be9cb05599fc726" title="Enables alternative, linear allocation algorithm in this pool.">VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT</a> to <a class="el" href="struct_vma_pool_create_info.html#a8405139f63d078340ae74513a59f5446" title="Use combination of VmaPoolCreateFlagBits.">VmaPoolCreateInfo::flags</a> while creating <a class="el" href="struct_vma_pool.html" title="Represents custom memory pool.">VmaPool</a> object. Then an alternative metadata management is used. It always creates new allocations after last one and doesn't reuse free regions after allocations freed in the middle. It results in better allocation performance and less memory consumed by metadata.</p>
+<p><img src="../gfx/Linear_allocator_2_algo_linear.png" alt="Linear allocation algorithm" class="inline"/></p>
+<p>With this one flag, you can create a custom pool that can be used in many ways: free-at-once, stack, double stack, and ring buffer. See below for details.</p>
+<h2><a class="anchor" id="linear_algorithm_free_at_once"></a>
+Free-at-once</h2>
+<p>In a pool that uses linear algorithm, you still need to free all the allocations individually, e.g. by using <a class="el" href="vk__mem__alloc_8h.html#a11f0fbc034fa81a4efedd73d61ce7568" title="Frees memory previously allocated using vmaAllocateMemory(), vmaAllocateMemoryForBuffer(),...">vmaFreeMemory()</a> or <a class="el" href="vk__mem__alloc_8h.html#a0d9f4e4ba5bf9aab1f1c746387753d77" title="Destroys Vulkan buffer and frees allocated memory.">vmaDestroyBuffer()</a>. You can free them in any order. New allocations are always made after last one - free space in the middle is not reused. However, when you release all the allocation and the pool becomes empty, allocation starts from the beginning again. This way you can use linear algorithm to speed up creation of allocations that you are going to release all at once.</p>
+<p><img src="../gfx/Linear_allocator_3_free_at_once.png" alt="Free-at-once" class="inline"/></p>
+<p>This mode is also available for pools created with <a class="el" href="struct_vma_pool_create_info.html#ae41142f2834fcdc82baa4883c187b75c" title="Maximum number of blocks that can be allocated in this pool. Optional.">VmaPoolCreateInfo::maxBlockCount</a> value that allows multiple memory blocks.</p>
+<h2><a class="anchor" id="linear_algorithm_stack"></a>
+Stack</h2>
+<p>When you free an allocation that was created last, its space can be reused. Thanks to this, if you always release allocations in the order opposite to their creation (LIFO - Last In First Out), you can achieve behavior of a stack.</p>
+<p><img src="../gfx/Linear_allocator_4_stack.png" alt="Stack" class="inline"/></p>
+<p>This mode is also available for pools created with <a class="el" href="struct_vma_pool_create_info.html#ae41142f2834fcdc82baa4883c187b75c" title="Maximum number of blocks that can be allocated in this pool. Optional.">VmaPoolCreateInfo::maxBlockCount</a> value that allows multiple memory blocks.</p>
+<h2><a class="anchor" id="linear_algorithm_double_stack"></a>
+Double stack</h2>
+<p>The space reserved by a custom pool with linear algorithm may be used by two stacks:</p>
+<ul>
+<li>First, default one, growing up from offset 0.</li>
+<li>Second, "upper" one, growing down from the end towards lower offsets.</li>
+</ul>
+<p>To make allocation from upper stack, add flag <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a42ba3a2d2c7117953210b7c3ef8da0df">VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT</a> to <a class="el" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b" title="Use VmaAllocationCreateFlagBits enum.">VmaAllocationCreateInfo::flags</a>.</p>
+<p><img src="../gfx/Linear_allocator_7_double_stack.png" alt="Double stack" class="inline"/></p>
+<p>Double stack is available only in pools with one memory block - <a class="el" href="struct_vma_pool_create_info.html#ae41142f2834fcdc82baa4883c187b75c" title="Maximum number of blocks that can be allocated in this pool. Optional.">VmaPoolCreateInfo::maxBlockCount</a> must be 1. Otherwise behavior is undefined.</p>
+<p>When the two stacks' ends meet so there is not enough space between them for a new allocation, such allocation fails with usual <code>VK_ERROR_OUT_OF_DEVICE_MEMORY</code> error.</p>
+<h2><a class="anchor" id="linear_algorithm_ring_buffer"></a>
+Ring buffer</h2>
+<p>When you free some allocations from the beginning and there is not enough free space for a new one at the end of a pool, allocator's "cursor" wraps around to the beginning and starts allocation there. Thanks to this, if you always release allocations in the same order as you created them (FIFO - First In First Out), you can achieve behavior of a ring buffer / queue.</p>
+<p><img src="../gfx/Linear_allocator_5_ring_buffer.png" alt="Ring buffer" class="inline"/></p>
+<p>Pools with linear algorithm support <a class="el" href="lost_allocations.html">lost allocations</a> when used as ring buffer. If there is not enough free space for a new allocation, but existing allocations from the front of the queue can become lost, they become lost and the allocation succeeds.</p>
+<p><img src="../gfx/Linear_allocator_6_ring_buffer_lost.png" alt="Ring buffer with lost allocations" class="inline"/></p>
+<p>Ring buffer is available only in pools with one memory block - <a class="el" href="struct_vma_pool_create_info.html#ae41142f2834fcdc82baa4883c187b75c" title="Maximum number of blocks that can be allocated in this pool. Optional.">VmaPoolCreateInfo::maxBlockCount</a> must be 1. Otherwise behavior is undefined.</p>
+<h1><a class="anchor" id="buddy_algorithm"></a>
+Buddy allocation algorithm</h1>
+<p>There is another allocation algorithm that can be used with custom pools, called "buddy". Its internal data structure is based on a tree of blocks, each having size that is a power of two and a half of its parent's size. When you want to allocate memory of certain size, a free node in the tree is located. If it's too large, it is recursively split into two halves (called "buddies"). However, if requested allocation size is not a power of two, the size of a tree node is aligned up to the nearest power of two and the remaining space is wasted. When two buddy nodes become free, they are merged back into one larger node.</p>
+<p><img src="../gfx/Buddy_allocator.png" alt="Buddy allocator" class="inline"/></p>
+<p>The advantage of buddy allocation algorithm over default algorithm is faster allocation and deallocation, as well as smaller external fragmentation. The disadvantage is more wasted space (internal fragmentation).</p>
+<p>For more information, please read <a href="https://en.wikipedia.org/wiki/Buddy_memory_allocation">"Buddy memory allocation" on Wikipedia</a> or other sources that describe this concept in general.</p>
+<p>To use buddy allocation algorithm with a custom pool, add flag <a class="el" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a97a0dc38e5161b780594d998d313d35e" title="Enables alternative, buddy allocation algorithm in this pool.">VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT</a> to <a class="el" href="struct_vma_pool_create_info.html#a8405139f63d078340ae74513a59f5446" title="Use combination of VmaPoolCreateFlagBits.">VmaPoolCreateInfo::flags</a> while creating <a class="el" href="struct_vma_pool.html" title="Represents custom memory pool.">VmaPool</a> object.</p>
+<p>Several limitations apply to pools that use buddy algorithm:</p>
+<ul>
+<li>It is recommended to use <a class="el" href="struct_vma_pool_create_info.html#aa4265160536cdb9be821b7686c16c676" title="Size of a single VkDeviceMemory block to be allocated as part of this pool, in bytes....">VmaPoolCreateInfo::blockSize</a> that is a power of two. Otherwise, only largest power of two smaller than the size is used for allocations. The remaining space always stays unused.</li>
+<li><a class="el" href="debugging_memory_usage.html#debugging_memory_usage_margins">Margins</a> and <a class="el" href="debugging_memory_usage.html#debugging_memory_usage_corruption_detection">corruption detection</a> don't work in such pools.</li>
+<li><a class="el" href="lost_allocations.html">Lost allocations</a> don't work in such pools. You can use them, but they never become lost. Support may be added in the future.</li>
+<li><a class="el" href="defragmentation.html">Defragmentation</a> doesn't work with allocations made from such pool. </li>
+</ul>
+</div></div><!-- contents -->
+</div><!-- PageDoc -->
+<div class="ttc" id="astruct_vma_pool_create_info_html_a596fa76b685d3f1f688f84a709a5b319"><div class="ttname"><a href="struct_vma_pool_create_info.html#a596fa76b685d3f1f688f84a709a5b319">VmaPoolCreateInfo::memoryTypeIndex</a></div><div class="ttdeci">uint32_t memoryTypeIndex</div><div class="ttdoc">Vulkan memory type index to allocate this pool from.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2803</div></div>
+<div class="ttc" id="astruct_vma_allocation_create_info_html_a6272c0555cfd1fe28bff1afeb6190150"><div class="ttname"><a href="struct_vma_allocation_create_info.html#a6272c0555cfd1fe28bff1afeb6190150">VmaAllocationCreateInfo::pool</a></div><div class="ttdeci">VmaPool pool</div><div class="ttdoc">Pool that this allocation should be created in.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2671</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a5485779c8f1948238fc4e92232fa65e1"><div class="ttname"><a href="vk__mem__alloc_8h.html#a5485779c8f1948238fc4e92232fa65e1">vmaDestroyPool</a></div><div class="ttdeci">void vmaDestroyPool(VmaAllocator allocator, VmaPool pool)</div><div class="ttdoc">Destroys VmaPool object and frees Vulkan device memory.</div></div>
+<div class="ttc" id="astruct_vma_allocation_html"><div class="ttname"><a href="struct_vma_allocation.html">VmaAllocation</a></div><div class="ttdoc">Represents single memory allocation.</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7"><div class="ttname"><a href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7">VMA_MEMORY_USAGE_GPU_ONLY</a></div><div class="ttdeci">@ VMA_MEMORY_USAGE_GPU_ONLY</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2481</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a5c8770ded7c59c8caac6de0c2cb00b50"><div class="ttname"><a href="vk__mem__alloc_8h.html#a5c8770ded7c59c8caac6de0c2cb00b50">vmaCreatePool</a></div><div class="ttdeci">VkResult vmaCreatePool(VmaAllocator allocator, const VmaPoolCreateInfo *pCreateInfo, VmaPool *pPool)</div><div class="ttdoc">Allocates Vulkan device memory and creates VmaPool object.</div></div>
+<div class="ttc" id="astruct_vma_pool_create_info_html_ae41142f2834fcdc82baa4883c187b75c"><div class="ttname"><a href="struct_vma_pool_create_info.html#ae41142f2834fcdc82baa4883c187b75c">VmaPoolCreateInfo::maxBlockCount</a></div><div class="ttdeci">size_t maxBlockCount</div><div class="ttdoc">Maximum number of blocks that can be allocated in this pool. Optional.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2828</div></div>
+<div class="ttc" id="astruct_vma_pool_create_info_html"><div class="ttname"><a href="struct_vma_pool_create_info.html">VmaPoolCreateInfo</a></div><div class="ttdoc">Describes parameter of created VmaPool.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2800</div></div>
+<div class="ttc" id="astruct_vma_pool_html"><div class="ttname"><a href="struct_vma_pool.html">VmaPool</a></div><div class="ttdoc">Represents custom memory pool.</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ae790ab9ffaf7667fb8f62523e6897888"><div class="ttname"><a href="vk__mem__alloc_8h.html#ae790ab9ffaf7667fb8f62523e6897888">vmaFindMemoryTypeIndexForBufferInfo</a></div><div class="ttdeci">VkResult vmaFindMemoryTypeIndexForBufferInfo(VmaAllocator allocator, const VkBufferCreateInfo *pBufferCreateInfo, const VmaAllocationCreateInfo *pAllocationCreateInfo, uint32_t *pMemoryTypeIndex)</div><div class="ttdoc">Helps to find memoryTypeIndex, given VkBufferCreateInfo and VmaAllocationCreateInfo.</div></div>
+<div class="ttc" id="astruct_vma_allocation_create_info_html_accb8b06b1f677d858cb9af20705fa910"><div class="ttname"><a href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910">VmaAllocationCreateInfo::usage</a></div><div class="ttdeci">VmaMemoryUsage usage</div><div class="ttdoc">Intended usage of memory.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2647</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ac72ee55598617e8eecca384e746bab51"><div class="ttname"><a href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer</a></div><div class="ttdeci">VkResult vmaCreateBuffer(VmaAllocator allocator, const VkBufferCreateInfo *pBufferCreateInfo, const VmaAllocationCreateInfo *pAllocationCreateInfo, VkBuffer *pBuffer, VmaAllocation *pAllocation, VmaAllocationInfo *pAllocationInfo)</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a0d9f4e4ba5bf9aab1f1c746387753d77"><div class="ttname"><a href="vk__mem__alloc_8h.html#a0d9f4e4ba5bf9aab1f1c746387753d77">vmaDestroyBuffer</a></div><div class="ttdeci">void vmaDestroyBuffer(VmaAllocator allocator, VkBuffer buffer, VmaAllocation allocation)</div><div class="ttdoc">Destroys Vulkan buffer and frees allocated memory.</div></div>
+<div class="ttc" id="astruct_vma_allocation_create_info_html"><div class="ttname"><a href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a></div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2638</div></div>
+<div class="ttc" id="astruct_vma_allocation_info_html"><div class="ttname"><a href="struct_vma_allocation_info.html">VmaAllocationInfo</a></div><div class="ttdoc">Parameters of VmaAllocation objects, that can be retrieved using function vmaGetAllocationInfo().</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2976</div></div>
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/debugging_memory_usage.html b/third_party/VulkanMemoryAllocator/docs/html/debugging_memory_usage.html
new file mode 100644
index 0000000..ec48f79
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/debugging_memory_usage.html
@@ -0,0 +1,114 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: Debugging incorrect memory usage</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+  <ul>
+<li class="navelem"><a class="el" href="index.html">Vulkan Memory Allocator</a></li>  </ul>
+</div>
+</div><!-- top -->
+<div class="PageDoc"><div class="header">
+  <div class="headertitle">
+<div class="title">Debugging incorrect memory usage </div>  </div>
+</div><!--header-->
+<div class="contents">
+<div class="textblock"><p>If you suspect a bug with memory usage, like usage of uninitialized memory or memory being overwritten out of bounds of an allocation, you can use debug features of this library to verify this.</p>
+<h1><a class="anchor" id="debugging_memory_usage_initialization"></a>
+Memory initialization</h1>
+<p>If you experience a bug with incorrect and nondeterministic data in your program and you suspect uninitialized memory to be used, you can enable automatic memory initialization to verify this. To do it, define macro <code>VMA_DEBUG_INITIALIZE_ALLOCATIONS</code> to 1.</p>
+<div class="fragment"><div class="line"><span class="preprocessor">#define VMA_DEBUG_INITIALIZE_ALLOCATIONS 1</span></div>
+<div class="line"><span class="preprocessor">#include &quot;vk_mem_alloc.h&quot;</span></div>
+</div><!-- fragment --><p>It makes memory of all new allocations initialized to bit pattern <code>0xDCDCDCDC</code>. Before an allocation is destroyed, its memory is filled with bit pattern <code>0xEFEFEFEF</code>. Memory is automatically mapped and unmapped if necessary.</p>
+<p>If you find these values while debugging your program, good chances are that you incorrectly read Vulkan memory that is allocated but not initialized, or already freed, respectively.</p>
+<p>Memory initialization works only with memory types that are <code>HOST_VISIBLE</code>. It works also with dedicated allocations. It doesn't work with allocations created with <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a5f436af6c8fe8540573a6d22627a6fd2">VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT</a> flag, as they cannot be mapped.</p>
+<h1><a class="anchor" id="debugging_memory_usage_margins"></a>
+Margins</h1>
+<p>By default, allocations are laid out in memory blocks next to each other if possible (considering required alignment, <code>bufferImageGranularity</code>, and <code>nonCoherentAtomSize</code>).</p>
+<p><img src="../gfx/Margins_1.png" alt="Allocations without margin" class="inline"/></p>
+<p>Define macro <code>VMA_DEBUG_MARGIN</code> to some non-zero value (e.g. 16) to enforce specified number of bytes as a margin before and after every allocation.</p>
+<div class="fragment"><div class="line"><span class="preprocessor">#define VMA_DEBUG_MARGIN 16</span></div>
+<div class="line"><span class="preprocessor">#include &quot;vk_mem_alloc.h&quot;</span></div>
+</div><!-- fragment --><p><img src="../gfx/Margins_2.png" alt="Allocations with margin" class="inline"/></p>
+<p>If your bug goes away after enabling margins, it means it may be caused by memory being overwritten outside of allocation boundaries. It is not 100% certain though. Change in application behavior may also be caused by different order and distribution of allocations across memory blocks after margins are applied.</p>
+<p>The margin is applied also before first and after last allocation in a block. It may occur only once between two adjacent allocations.</p>
+<p>Margins work with all types of memory.</p>
+<p>Margin is applied only to allocations made out of memory blocks and not to dedicated allocations, which have their own memory block of specific size. It is thus not applied to allocations made using <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a3fc311d855c2ff53f1090ef5c722b38f" title="Set this flag if the allocation should have its own memory block.">VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT</a> flag or those automatically decided to put into dedicated allocations, e.g. due to its large size or recommended by VK_KHR_dedicated_allocation extension. Margins are also not active in custom pools created with <a class="el" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a97a0dc38e5161b780594d998d313d35e" title="Enables alternative, buddy allocation algorithm in this pool.">VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT</a> flag.</p>
+<p>Margins appear in <a class="el" href="statistics.html#statistics_json_dump">JSON dump</a> as part of free space.</p>
+<p>Note that enabling margins increases memory usage and fragmentation.</p>
+<h1><a class="anchor" id="debugging_memory_usage_corruption_detection"></a>
+Corruption detection</h1>
+<p>You can additionally define macro <code>VMA_DEBUG_DETECT_CORRUPTION</code> to 1 to enable validation of contents of the margins.</p>
+<div class="fragment"><div class="line"><span class="preprocessor">#define VMA_DEBUG_MARGIN 16</span></div>
+<div class="line"><span class="preprocessor">#define VMA_DEBUG_DETECT_CORRUPTION 1</span></div>
+<div class="line"><span class="preprocessor">#include &quot;vk_mem_alloc.h&quot;</span></div>
+</div><!-- fragment --><p>When this feature is enabled, number of bytes specified as <code>VMA_DEBUG_MARGIN</code> (it must be multiply of 4) before and after every allocation is filled with a magic number. This idea is also know as "canary". Memory is automatically mapped and unmapped if necessary.</p>
+<p>This number is validated automatically when the allocation is destroyed. If it's not equal to the expected value, <code>VMA_ASSERT()</code> is executed. It clearly means that either CPU or GPU overwritten the memory outside of boundaries of the allocation, which indicates a serious bug.</p>
+<p>You can also explicitly request checking margins of all allocations in all memory blocks that belong to specified memory types by using function <a class="el" href="vk__mem__alloc_8h.html#a49329a7f030dafcf82f7b73334c22e98" title="Checks magic number in margins around all allocations in given memory types (in both default and cust...">vmaCheckCorruption()</a>, or in memory blocks that belong to specified custom pool, by using function <a class="el" href="vk__mem__alloc_8h.html#ad535935619c7a549bf837e1bb0068f89" title="Checks magic number in margins around all allocations in given memory pool in search for corruptions.">vmaCheckPoolCorruption()</a>.</p>
+<p>Margin validation (corruption detection) works only for memory types that are <code>HOST_VISIBLE</code> and <code>HOST_COHERENT</code>. </p>
+</div></div><!-- contents -->
+</div><!-- PageDoc -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/defragmentation.html b/third_party/VulkanMemoryAllocator/docs/html/defragmentation.html
new file mode 100644
index 0000000..807960b
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/defragmentation.html
@@ -0,0 +1,240 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: Defragmentation</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+  <ul>
+<li class="navelem"><a class="el" href="index.html">Vulkan Memory Allocator</a></li>  </ul>
+</div>
+</div><!-- top -->
+<div class="PageDoc"><div class="header">
+  <div class="headertitle">
+<div class="title">Defragmentation </div>  </div>
+</div><!--header-->
+<div class="contents">
+<div class="textblock"><p>Interleaved allocations and deallocations of many objects of varying size can cause fragmentation over time, which can lead to a situation where the library is unable to find a continuous range of free memory for a new allocation despite there is enough free space, just scattered across many small free ranges between existing allocations.</p>
+<p>To mitigate this problem, you can use defragmentation feature: structure <a class="el" href="struct_vma_defragmentation_info2.html" title="Parameters for defragmentation.">VmaDefragmentationInfo2</a>, function <a class="el" href="vk__mem__alloc_8h.html#a36ba776fd7fd5cb1e9359fdc0d8e6e8a" title="Begins defragmentation process.">vmaDefragmentationBegin()</a>, <a class="el" href="vk__mem__alloc_8h.html#a8774e20e91e245aae959ba63efa15dd2" title="Ends defragmentation process.">vmaDefragmentationEnd()</a>. Given set of allocations, this function can move them to compact used memory, ensure more continuous free space and possibly also free some <code>VkDeviceMemory</code> blocks.</p>
+<p>What the defragmentation does is:</p>
+<ul>
+<li>Updates <a class="el" href="struct_vma_allocation.html" title="Represents single memory allocation.">VmaAllocation</a> objects to point to new <code>VkDeviceMemory</code> and offset. After allocation has been moved, its <a class="el" href="struct_vma_allocation_info.html#ae0bfb7dfdf79a76ffefc9a94677a2f67" title="Handle to Vulkan memory object.">VmaAllocationInfo::deviceMemory</a> and/or <a class="el" href="struct_vma_allocation_info.html#a4a3c732388dbdc7a23f9365b00825268" title="Offset into deviceMemory object to the beginning of this allocation, in bytes. (deviceMemory,...">VmaAllocationInfo::offset</a> changes. You must query them again using <a class="el" href="vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b" title="Returns current information about specified allocation and atomically marks it as used in current fra...">vmaGetAllocationInfo()</a> if you need them.</li>
+<li>Moves actual data in memory.</li>
+</ul>
+<p>What it doesn't do, so you need to do it yourself:</p>
+<ul>
+<li>Recreate buffers and images that were bound to allocations that were defragmented and bind them with their new places in memory. You must use <code>vkDestroyBuffer()</code>, <code>vkDestroyImage()</code>, <code>vkCreateBuffer()</code>, <code>vkCreateImage()</code>, <a class="el" href="vk__mem__alloc_8h.html#a6b0929b914b60cf2d45cac4bf3547470" title="Binds buffer to allocation.">vmaBindBufferMemory()</a>, <a class="el" href="vk__mem__alloc_8h.html#a3d3ca45799923aa5d138e9e5f9eb2da5" title="Binds image to allocation.">vmaBindImageMemory()</a> for that purpose and NOT <a class="el" href="vk__mem__alloc_8h.html#a0d9f4e4ba5bf9aab1f1c746387753d77" title="Destroys Vulkan buffer and frees allocated memory.">vmaDestroyBuffer()</a>, <a class="el" href="vk__mem__alloc_8h.html#ae50d2cb3b4a3bfd4dd40987234e50e7e" title="Destroys Vulkan image and frees allocated memory.">vmaDestroyImage()</a>, <a class="el" href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer()</a>, <a class="el" href="vk__mem__alloc_8h.html#a02a94f25679275851a53e82eacbcfc73" title="Function similar to vmaCreateBuffer().">vmaCreateImage()</a>, because you don't need to destroy or create allocation objects!</li>
+<li>Recreate views and update descriptors that point to these buffers and images.</li>
+</ul>
+<h1><a class="anchor" id="defragmentation_cpu"></a>
+Defragmenting CPU memory</h1>
+<p>Following example demonstrates how you can run defragmentation on CPU. Only allocations created in memory types that are <code>HOST_VISIBLE</code> can be defragmented. Others are ignored.</p>
+<p>The way it works is:</p>
+<ul>
+<li>It temporarily maps entire memory blocks when necessary.</li>
+<li>It moves data using <code>memmove()</code> function.</li>
+</ul>
+<div class="fragment"><div class="line"><span class="comment">// Given following variables already initialized:</span></div>
+<div class="line">VkDevice device;</div>
+<div class="line"><a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator;</div>
+<div class="line">std::vector&lt;VkBuffer&gt; buffers;</div>
+<div class="line">std::vector&lt;VmaAllocation&gt; allocations;</div>
+<div class="line"> </div>
+<div class="line"> </div>
+<div class="line"><span class="keyword">const</span> uint32_t allocCount = (uint32_t)allocations.size();</div>
+<div class="line">std::vector&lt;VkBool32&gt; allocationsChanged(allocCount);</div>
+<div class="line"> </div>
+<div class="line"><a class="code" href="struct_vma_defragmentation_info2.html">VmaDefragmentationInfo2</a> defragInfo = {};</div>
+<div class="line">defragInfo.<a class="code" href="struct_vma_defragmentation_info2.html#a3cf86ab32c1da779b4923d301a3056ba">allocationCount</a> = allocCount;</div>
+<div class="line">defragInfo.<a class="code" href="struct_vma_defragmentation_info2.html#a8943f8d65969ce8e2189a1cdf3205e96">pAllocations</a> = allocations.data();</div>
+<div class="line">defragInfo.<a class="code" href="struct_vma_defragmentation_info2.html#a76d51a644dc7f5405d0cdd0025ecd0cc">pAllocationsChanged</a> = allocationsChanged.data();</div>
+<div class="line">defragInfo.<a class="code" href="struct_vma_defragmentation_info2.html#af78e1ea40c22d85137b65f6b384a4d0a">maxCpuBytesToMove</a> = VK_WHOLE_SIZE; <span class="comment">// No limit.</span></div>
+<div class="line">defragInfo.<a class="code" href="struct_vma_defragmentation_info2.html#a94c2c7223d52878445a8cccce396b671">maxCpuAllocationsToMove</a> = UINT32_MAX; <span class="comment">// No limit.</span></div>
+<div class="line"> </div>
+<div class="line"><a class="code" href="struct_vma_defragmentation_context.html">VmaDefragmentationContext</a> defragCtx;</div>
+<div class="line"><a class="code" href="vk__mem__alloc_8h.html#a36ba776fd7fd5cb1e9359fdc0d8e6e8a">vmaDefragmentationBegin</a>(allocator, &amp;defragInfo, <span class="keyword">nullptr</span>, &amp;defragCtx);</div>
+<div class="line"><a class="code" href="vk__mem__alloc_8h.html#a8774e20e91e245aae959ba63efa15dd2">vmaDefragmentationEnd</a>(allocator, defragCtx);</div>
+<div class="line"> </div>
+<div class="line"><span class="keywordflow">for</span>(uint32_t i = 0; i &lt; allocCount; ++i)</div>
+<div class="line">{</div>
+<div class="line">    <span class="keywordflow">if</span>(allocationsChanged[i])</div>
+<div class="line">    {</div>
+<div class="line">        <span class="comment">// Destroy buffer that is immutably bound to memory region which is no longer valid.</span></div>
+<div class="line">        vkDestroyBuffer(device, buffers[i], <span class="keyword">nullptr</span>);</div>
+<div class="line"> </div>
+<div class="line">        <span class="comment">// Create new buffer with same parameters.</span></div>
+<div class="line">        VkBufferCreateInfo bufferInfo = ...;</div>
+<div class="line">        vkCreateBuffer(device, &amp;bufferInfo, <span class="keyword">nullptr</span>, &amp;buffers[i]);</div>
+<div class="line">            </div>
+<div class="line">        <span class="comment">// You can make dummy call to vkGetBufferMemoryRequirements here to silence validation layer warning.</span></div>
+<div class="line">            </div>
+<div class="line">        <span class="comment">// Bind new buffer to new memory region. Data contained in it is already moved.</span></div>
+<div class="line">        <a class="code" href="struct_vma_allocation_info.html">VmaAllocationInfo</a> allocInfo;</div>
+<div class="line">        <a class="code" href="vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b">vmaGetAllocationInfo</a>(allocator, allocations[i], &amp;allocInfo);</div>
+<div class="line">        <a class="code" href="vk__mem__alloc_8h.html#a6b0929b914b60cf2d45cac4bf3547470">vmaBindBufferMemory</a>(allocator, allocations[i], buffers[i]);</div>
+<div class="line">    }</div>
+<div class="line">}</div>
+</div><!-- fragment --><p>Setting <a class="el" href="struct_vma_defragmentation_info2.html#a76d51a644dc7f5405d0cdd0025ecd0cc" title="Optional, output. Pointer to array that will be filled with information whether the allocation at cer...">VmaDefragmentationInfo2::pAllocationsChanged</a> is optional. This output array tells whether particular allocation in <a class="el" href="struct_vma_defragmentation_info2.html#a8943f8d65969ce8e2189a1cdf3205e96" title="Pointer to array of allocations that can be defragmented.">VmaDefragmentationInfo2::pAllocations</a> at the same index has been modified during defragmentation. You can pass null, but you then need to query every allocation passed to defragmentation for new parameters using <a class="el" href="vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b" title="Returns current information about specified allocation and atomically marks it as used in current fra...">vmaGetAllocationInfo()</a> if you might need to recreate and rebind a buffer or image associated with it.</p>
+<p>If you use <a class="el" href="choosing_memory_type.html#choosing_memory_type_custom_memory_pools">Custom memory pools</a>, you can fill <a class="el" href="struct_vma_defragmentation_info2.html#a7e70aa2a1081d849dcc7829b19d3ec9d" title="Numer of pools in pPools array.">VmaDefragmentationInfo2::poolCount</a> and <a class="el" href="struct_vma_defragmentation_info2.html#a0b3effd57f3fcdeb2ed62210b4ef20e1" title="Either null or pointer to array of pools to be defragmented.">VmaDefragmentationInfo2::pPools</a> instead of <a class="el" href="struct_vma_defragmentation_info2.html#a3cf86ab32c1da779b4923d301a3056ba" title="Number of allocations in pAllocations array.">VmaDefragmentationInfo2::allocationCount</a> and <a class="el" href="struct_vma_defragmentation_info2.html#a8943f8d65969ce8e2189a1cdf3205e96" title="Pointer to array of allocations that can be defragmented.">VmaDefragmentationInfo2::pAllocations</a> to defragment all allocations in given pools. You cannot use <a class="el" href="struct_vma_defragmentation_info2.html#a76d51a644dc7f5405d0cdd0025ecd0cc" title="Optional, output. Pointer to array that will be filled with information whether the allocation at cer...">VmaDefragmentationInfo2::pAllocationsChanged</a> in that case. You can also combine both methods.</p>
+<h1><a class="anchor" id="defragmentation_gpu"></a>
+Defragmenting GPU memory</h1>
+<p>It is also possible to defragment allocations created in memory types that are not <code>HOST_VISIBLE</code>. To do that, you need to pass a command buffer that meets requirements as described in <a class="el" href="struct_vma_defragmentation_info2.html#a7f71f39590c5316771493d2333f9c1bd" title="Optional. Command buffer where GPU copy commands will be posted.">VmaDefragmentationInfo2::commandBuffer</a>. The way it works is:</p>
+<ul>
+<li>It creates temporary buffers and binds them to entire memory blocks when necessary.</li>
+<li>It issues <code>vkCmdCopyBuffer()</code> to passed command buffer.</li>
+</ul>
+<p>Example:</p>
+<div class="fragment"><div class="line"><span class="comment">// Given following variables already initialized:</span></div>
+<div class="line">VkDevice device;</div>
+<div class="line"><a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator;</div>
+<div class="line">VkCommandBuffer commandBuffer;</div>
+<div class="line">std::vector&lt;VkBuffer&gt; buffers;</div>
+<div class="line">std::vector&lt;VmaAllocation&gt; allocations;</div>
+<div class="line"> </div>
+<div class="line"> </div>
+<div class="line"><span class="keyword">const</span> uint32_t allocCount = (uint32_t)allocations.size();</div>
+<div class="line">std::vector&lt;VkBool32&gt; allocationsChanged(allocCount);</div>
+<div class="line"> </div>
+<div class="line">VkCommandBufferBeginInfo cmdBufBeginInfo = ...;</div>
+<div class="line">vkBeginCommandBuffer(commandBuffer, &amp;cmdBufBeginInfo);</div>
+<div class="line"> </div>
+<div class="line"><a class="code" href="struct_vma_defragmentation_info2.html">VmaDefragmentationInfo2</a> defragInfo = {};</div>
+<div class="line">defragInfo.<a class="code" href="struct_vma_defragmentation_info2.html#a3cf86ab32c1da779b4923d301a3056ba">allocationCount</a> = allocCount;</div>
+<div class="line">defragInfo.<a class="code" href="struct_vma_defragmentation_info2.html#a8943f8d65969ce8e2189a1cdf3205e96">pAllocations</a> = allocations.data();</div>
+<div class="line">defragInfo.<a class="code" href="struct_vma_defragmentation_info2.html#a76d51a644dc7f5405d0cdd0025ecd0cc">pAllocationsChanged</a> = allocationsChanged.data();</div>
+<div class="line">defragInfo.<a class="code" href="struct_vma_defragmentation_info2.html#a4ddbc898d0afe1518f863a3763628f08">maxGpuBytesToMove</a> = VK_WHOLE_SIZE; <span class="comment">// Notice it&#39;s &quot;GPU&quot; this time.</span></div>
+<div class="line">defragInfo.<a class="code" href="struct_vma_defragmentation_info2.html#a40d53d33e71ba0b66f844ed63c05a3f6">maxGpuAllocationsToMove</a> = UINT32_MAX; <span class="comment">// Notice it&#39;s &quot;GPU&quot; this time.</span></div>
+<div class="line">defragInfo.<a class="code" href="struct_vma_defragmentation_info2.html#a7f71f39590c5316771493d2333f9c1bd">commandBuffer</a> = commandBuffer;</div>
+<div class="line"> </div>
+<div class="line"><a class="code" href="struct_vma_defragmentation_context.html">VmaDefragmentationContext</a> defragCtx;</div>
+<div class="line"><a class="code" href="vk__mem__alloc_8h.html#a36ba776fd7fd5cb1e9359fdc0d8e6e8a">vmaDefragmentationBegin</a>(allocator, &amp;defragInfo, <span class="keyword">nullptr</span>, &amp;defragCtx);</div>
+<div class="line"> </div>
+<div class="line">vkEndCommandBuffer(commandBuffer);</div>
+<div class="line"> </div>
+<div class="line"><span class="comment">// Submit commandBuffer.</span></div>
+<div class="line"><span class="comment">// Wait for a fence that ensures commandBuffer execution finished.</span></div>
+<div class="line"> </div>
+<div class="line"><a class="code" href="vk__mem__alloc_8h.html#a8774e20e91e245aae959ba63efa15dd2">vmaDefragmentationEnd</a>(allocator, defragCtx);</div>
+<div class="line"> </div>
+<div class="line"><span class="keywordflow">for</span>(uint32_t i = 0; i &lt; allocCount; ++i)</div>
+<div class="line">{</div>
+<div class="line">    <span class="keywordflow">if</span>(allocationsChanged[i])</div>
+<div class="line">    {</div>
+<div class="line">        <span class="comment">// Destroy buffer that is immutably bound to memory region which is no longer valid.</span></div>
+<div class="line">        vkDestroyBuffer(device, buffers[i], <span class="keyword">nullptr</span>);</div>
+<div class="line"> </div>
+<div class="line">        <span class="comment">// Create new buffer with same parameters.</span></div>
+<div class="line">        VkBufferCreateInfo bufferInfo = ...;</div>
+<div class="line">        vkCreateBuffer(device, &amp;bufferInfo, <span class="keyword">nullptr</span>, &amp;buffers[i]);</div>
+<div class="line">            </div>
+<div class="line">        <span class="comment">// You can make dummy call to vkGetBufferMemoryRequirements here to silence validation layer warning.</span></div>
+<div class="line">            </div>
+<div class="line">        <span class="comment">// Bind new buffer to new memory region. Data contained in it is already moved.</span></div>
+<div class="line">        <a class="code" href="struct_vma_allocation_info.html">VmaAllocationInfo</a> allocInfo;</div>
+<div class="line">        <a class="code" href="vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b">vmaGetAllocationInfo</a>(allocator, allocations[i], &amp;allocInfo);</div>
+<div class="line">        <a class="code" href="vk__mem__alloc_8h.html#a6b0929b914b60cf2d45cac4bf3547470">vmaBindBufferMemory</a>(allocator, allocations[i], buffers[i]);</div>
+<div class="line">    }</div>
+<div class="line">}</div>
+</div><!-- fragment --><p>You can combine these two methods by specifying non-zero <code>maxGpu*</code> as well as <code>maxCpu*</code> parameters. The library automatically chooses best method to defragment each memory pool.</p>
+<p>You may try not to block your entire program to wait until defragmentation finishes, but do it in the background, as long as you carefully fullfill requirements described in function <a class="el" href="vk__mem__alloc_8h.html#a36ba776fd7fd5cb1e9359fdc0d8e6e8a" title="Begins defragmentation process.">vmaDefragmentationBegin()</a>.</p>
+<h1><a class="anchor" id="defragmentation_additional_notes"></a>
+Additional notes</h1>
+<p>It is only legal to defragment allocations bound to:</p>
+<ul>
+<li>buffers</li>
+<li>images created with <code>VK_IMAGE_CREATE_ALIAS_BIT</code>, <code>VK_IMAGE_TILING_LINEAR</code>, and being currently in <code>VK_IMAGE_LAYOUT_GENERAL</code> or <code>VK_IMAGE_LAYOUT_PREINITIALIZED</code>.</li>
+</ul>
+<p>Defragmentation of images created with <code>VK_IMAGE_TILING_OPTIMAL</code> or in any other layout may give undefined results.</p>
+<p>If you defragment allocations bound to images, new images to be bound to new memory region after defragmentation should be created with <code>VK_IMAGE_LAYOUT_PREINITIALIZED</code> and then transitioned to their original layout from before defragmentation if needed using an image memory barrier.</p>
+<p>While using defragmentation, you may experience validation layer warnings, which you just need to ignore. See <a class="el" href="general_considerations.html#general_considerations_validation_layer_warnings">Validation layer warnings</a>.</p>
+<p>Please don't expect memory to be fully compacted after defragmentation. Algorithms inside are based on some heuristics that try to maximize number of Vulkan memory blocks to make totally empty to release them, as well as to maximimze continuous empty space inside remaining blocks, while minimizing the number and size of allocations that need to be moved. Some fragmentation may still remain - this is normal.</p>
+<h1><a class="anchor" id="defragmentation_custom_algorithm"></a>
+Writing custom defragmentation algorithm</h1>
+<p>If you want to implement your own, custom defragmentation algorithm, there is infrastructure prepared for that, but it is not exposed through the library API - you need to hack its source code. Here are steps needed to do this:</p>
+<ol type="1">
+<li>Main thing you need to do is to define your own class derived from base abstract class <code>VmaDefragmentationAlgorithm</code> and implement your version of its pure virtual methods. See definition and comments of this class for details.</li>
+<li>Your code needs to interact with device memory block metadata. If you need more access to its data than it's provided by its public interface, declare your new class as a friend class e.g. in class <code>VmaBlockMetadata_Generic</code>.</li>
+<li>If you want to create a flag that would enable your algorithm or pass some additional flags to configure it, add them to <code>VmaDefragmentationFlagBits</code> and use them in <a class="el" href="struct_vma_defragmentation_info2.html#a53e844ee5633e229cf6daf14b2d9fff9" title="Reserved for future use. Should be 0.">VmaDefragmentationInfo2::flags</a>.</li>
+<li>Modify function <code>VmaBlockVectorDefragmentationContext::Begin</code> to create object of your new class whenever needed. </li>
+</ol>
+</div></div><!-- contents -->
+</div><!-- PageDoc -->
+<div class="ttc" id="astruct_vma_defragmentation_info2_html_a3cf86ab32c1da779b4923d301a3056ba"><div class="ttname"><a href="struct_vma_defragmentation_info2.html#a3cf86ab32c1da779b4923d301a3056ba">VmaDefragmentationInfo2::allocationCount</a></div><div class="ttdeci">uint32_t allocationCount</div><div class="ttdoc">Number of allocations in pAllocations array.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3326</div></div>
+<div class="ttc" id="astruct_vma_allocator_html"><div class="ttname"><a href="struct_vma_allocator.html">VmaAllocator</a></div><div class="ttdoc">Represents main object of this library initialized.</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a86dd08aba8633bfa4ad0df2e76481d8b"><div class="ttname"><a href="vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b">vmaGetAllocationInfo</a></div><div class="ttdeci">void vmaGetAllocationInfo(VmaAllocator allocator, VmaAllocation allocation, VmaAllocationInfo *pAllocationInfo)</div><div class="ttdoc">Returns current information about specified allocation and atomically marks it as used in current fra...</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a8774e20e91e245aae959ba63efa15dd2"><div class="ttname"><a href="vk__mem__alloc_8h.html#a8774e20e91e245aae959ba63efa15dd2">vmaDefragmentationEnd</a></div><div class="ttdeci">VkResult vmaDefragmentationEnd(VmaAllocator allocator, VmaDefragmentationContext context)</div><div class="ttdoc">Ends defragmentation process.</div></div>
+<div class="ttc" id="astruct_vma_defragmentation_info2_html_a4ddbc898d0afe1518f863a3763628f08"><div class="ttname"><a href="struct_vma_defragmentation_info2.html#a4ddbc898d0afe1518f863a3763628f08">VmaDefragmentationInfo2::maxGpuBytesToMove</a></div><div class="ttdeci">VkDeviceSize maxGpuBytesToMove</div><div class="ttdoc">Maximum total numbers of bytes that can be copied while moving allocations to different places using ...</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3375</div></div>
+<div class="ttc" id="astruct_vma_defragmentation_info2_html_a7f71f39590c5316771493d2333f9c1bd"><div class="ttname"><a href="struct_vma_defragmentation_info2.html#a7f71f39590c5316771493d2333f9c1bd">VmaDefragmentationInfo2::commandBuffer</a></div><div class="ttdeci">VkCommandBuffer commandBuffer</div><div class="ttdoc">Optional. Command buffer where GPU copy commands will be posted.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3389</div></div>
+<div class="ttc" id="astruct_vma_defragmentation_info2_html"><div class="ttname"><a href="struct_vma_defragmentation_info2.html">VmaDefragmentationInfo2</a></div><div class="ttdoc">Parameters for defragmentation.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3320</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a6b0929b914b60cf2d45cac4bf3547470"><div class="ttname"><a href="vk__mem__alloc_8h.html#a6b0929b914b60cf2d45cac4bf3547470">vmaBindBufferMemory</a></div><div class="ttdeci">VkResult vmaBindBufferMemory(VmaAllocator allocator, VmaAllocation allocation, VkBuffer buffer)</div><div class="ttdoc">Binds buffer to allocation.</div></div>
+<div class="ttc" id="astruct_vma_defragmentation_info2_html_a40d53d33e71ba0b66f844ed63c05a3f6"><div class="ttname"><a href="struct_vma_defragmentation_info2.html#a40d53d33e71ba0b66f844ed63c05a3f6">VmaDefragmentationInfo2::maxGpuAllocationsToMove</a></div><div class="ttdeci">uint32_t maxGpuAllocationsToMove</div><div class="ttdoc">Maximum number of allocations that can be moved to a different place using transfers on GPU side,...</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3380</div></div>
+<div class="ttc" id="astruct_vma_defragmentation_info2_html_af78e1ea40c22d85137b65f6b384a4d0a"><div class="ttname"><a href="struct_vma_defragmentation_info2.html#af78e1ea40c22d85137b65f6b384a4d0a">VmaDefragmentationInfo2::maxCpuBytesToMove</a></div><div class="ttdeci">VkDeviceSize maxCpuBytesToMove</div><div class="ttdoc">Maximum total numbers of bytes that can be copied while moving allocations to different places using ...</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3365</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a36ba776fd7fd5cb1e9359fdc0d8e6e8a"><div class="ttname"><a href="vk__mem__alloc_8h.html#a36ba776fd7fd5cb1e9359fdc0d8e6e8a">vmaDefragmentationBegin</a></div><div class="ttdeci">VkResult vmaDefragmentationBegin(VmaAllocator allocator, const VmaDefragmentationInfo2 *pInfo, VmaDefragmentationStats *pStats, VmaDefragmentationContext *pContext)</div><div class="ttdoc">Begins defragmentation process.</div></div>
+<div class="ttc" id="astruct_vma_defragmentation_info2_html_a76d51a644dc7f5405d0cdd0025ecd0cc"><div class="ttname"><a href="struct_vma_defragmentation_info2.html#a76d51a644dc7f5405d0cdd0025ecd0cc">VmaDefragmentationInfo2::pAllocationsChanged</a></div><div class="ttdeci">VkBool32 * pAllocationsChanged</div><div class="ttdoc">Optional, output. Pointer to array that will be filled with information whether the allocation at cer...</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3341</div></div>
+<div class="ttc" id="astruct_vma_allocation_info_html"><div class="ttname"><a href="struct_vma_allocation_info.html">VmaAllocationInfo</a></div><div class="ttdoc">Parameters of VmaAllocation objects, that can be retrieved using function vmaGetAllocationInfo().</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2976</div></div>
+<div class="ttc" id="astruct_vma_defragmentation_context_html"><div class="ttname"><a href="struct_vma_defragmentation_context.html">VmaDefragmentationContext</a></div><div class="ttdoc">Represents Opaque object that represents started defragmentation process.</div></div>
+<div class="ttc" id="astruct_vma_defragmentation_info2_html_a8943f8d65969ce8e2189a1cdf3205e96"><div class="ttname"><a href="struct_vma_defragmentation_info2.html#a8943f8d65969ce8e2189a1cdf3205e96">VmaDefragmentationInfo2::pAllocations</a></div><div class="ttdeci">VmaAllocation * pAllocations</div><div class="ttdoc">Pointer to array of allocations that can be defragmented.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3335</div></div>
+<div class="ttc" id="astruct_vma_defragmentation_info2_html_a94c2c7223d52878445a8cccce396b671"><div class="ttname"><a href="struct_vma_defragmentation_info2.html#a94c2c7223d52878445a8cccce396b671">VmaDefragmentationInfo2::maxCpuAllocationsToMove</a></div><div class="ttdeci">uint32_t maxCpuAllocationsToMove</div><div class="ttdoc">Maximum number of allocations that can be moved to a different place using transfers on CPU side,...</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3370</div></div>
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/deprecated.html b/third_party/VulkanMemoryAllocator/docs/html/deprecated.html
new file mode 100644
index 0000000..b273847
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/deprecated.html
@@ -0,0 +1,85 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: Deprecated List</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="PageDoc"><div class="header">
+  <div class="headertitle">
+<div class="title">Deprecated List </div>  </div>
+</div><!--header-->
+<div class="contents">
+<div class="textblock"><dl class="reflist">
+<dt>Member <a class="el" href="vk__mem__alloc_8h.html#a6aced90fcc7b39882b6654a740a0b9bb">vmaDefragment</a>  (<a class="el" href="struct_vma_allocator.html" title="Represents main object of this library initialized.">VmaAllocator</a> allocator, <a class="el" href="struct_vma_allocation.html" title="Represents single memory allocation.">VmaAllocation</a> *pAllocations, size_t allocationCount, VkBool32 *pAllocationsChanged, const <a class="el" href="struct_vma_defragmentation_info.html" title="Deprecated. Optional configuration parameters to be passed to function vmaDefragment().">VmaDefragmentationInfo</a> *pDefragmentationInfo, <a class="el" href="struct_vma_defragmentation_stats.html" title="Statistics returned by function vmaDefragment().">VmaDefragmentationStats</a> *pDefragmentationStats)</dt>
+<dd><a class="anchor" id="_deprecated000003"></a>This is a part of the old interface. It is recommended to use structure <a class="el" href="struct_vma_defragmentation_info2.html" title="Parameters for defragmentation.">VmaDefragmentationInfo2</a> and function <a class="el" href="vk__mem__alloc_8h.html#a36ba776fd7fd5cb1e9359fdc0d8e6e8a" title="Begins defragmentation process.">vmaDefragmentationBegin()</a> instead. </dd>
+<dt>Member <a class="el" href="vk__mem__alloc_8h.html#a2bf47f96bf92bed2a49461bd9af3acfa">VmaDefragmentationInfo</a>  </dt>
+<dd><a class="anchor" id="_deprecated000002"></a>This is a part of the old interface. It is recommended to use structure <a class="el" href="struct_vma_defragmentation_info2.html" title="Parameters for defragmentation.">VmaDefragmentationInfo2</a> and function <a class="el" href="vk__mem__alloc_8h.html#a36ba776fd7fd5cb1e9359fdc0d8e6e8a" title="Begins defragmentation process.">vmaDefragmentationBegin()</a> instead.  </dd>
+<dt>Member <a class="el" href="vk__mem__alloc_8h.html#a0ff488958ca72b28e545880463cb8696">vmaResizeAllocation</a>  (<a class="el" href="struct_vma_allocator.html" title="Represents main object of this library initialized.">VmaAllocator</a> allocator, <a class="el" href="struct_vma_allocation.html" title="Represents single memory allocation.">VmaAllocation</a> allocation, VkDeviceSize newSize)</dt>
+<dd><a class="anchor" id="_deprecated000001"></a> In version 2.2.0 it used to try to change allocation's size without moving or reallocating it. In current version it returns <code>VK_SUCCESS</code> only if <code>newSize</code> equals current allocation's size. Otherwise returns <code>VK_ERROR_OUT_OF_POOL_MEMORY</code>, indicating that allocation's size could not be changed. </dd>
+</dl>
+</div></div><!-- contents -->
+</div><!-- PageDoc -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/doc.png b/third_party/VulkanMemoryAllocator/docs/html/doc.png
new file mode 100644
index 0000000..17edabf
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/doc.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/docs/html/doxygen.css b/third_party/VulkanMemoryAllocator/docs/html/doxygen.css
new file mode 100644
index 0000000..73ecbb2
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/doxygen.css
@@ -0,0 +1,1771 @@
+/* The standard CSS for doxygen 1.8.17 */
+
+body, table, div, p, dl {
+	font: 400 14px/22px Roboto,sans-serif;
+}
+
+p.reference, p.definition {
+	font: 400 14px/22px Roboto,sans-serif;
+}
+
+/* @group Heading Levels */
+
+h1.groupheader {
+	font-size: 150%;
+}
+
+.title {
+	font: 400 14px/28px Roboto,sans-serif;
+	font-size: 150%;
+	font-weight: bold;
+	margin: 10px 2px;
+}
+
+h2.groupheader {
+	border-bottom: 1px solid #879ECB;
+	color: #354C7B;
+	font-size: 150%;
+	font-weight: normal;
+	margin-top: 1.75em;
+	padding-top: 8px;
+	padding-bottom: 4px;
+	width: 100%;
+}
+
+h3.groupheader {
+	font-size: 100%;
+}
+
+h1, h2, h3, h4, h5, h6 {
+	-webkit-transition: text-shadow 0.5s linear;
+	-moz-transition: text-shadow 0.5s linear;
+	-ms-transition: text-shadow 0.5s linear;
+	-o-transition: text-shadow 0.5s linear;
+	transition: text-shadow 0.5s linear;
+	margin-right: 15px;
+}
+
+h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow {
+	text-shadow: 0 0 15px cyan;
+}
+
+dt {
+	font-weight: bold;
+}
+
+ul.multicol {
+	-moz-column-gap: 1em;
+	-webkit-column-gap: 1em;
+	column-gap: 1em;
+	-moz-column-count: 3;
+	-webkit-column-count: 3;
+	column-count: 3;
+}
+
+p.startli, p.startdd {
+	margin-top: 2px;
+}
+
+th p.starttd, p.intertd, p.endtd {
+        font-size: 100%;
+        font-weight: 700;
+}
+
+p.starttd {
+	margin-top: 0px;
+}
+
+p.endli {
+	margin-bottom: 0px;
+}
+
+p.enddd {
+	margin-bottom: 4px;
+}
+
+p.endtd {
+	margin-bottom: 2px;
+}
+
+p.interli {
+}
+
+p.interdd {
+}
+
+p.intertd {
+}
+
+/* @end */
+
+caption {
+	font-weight: bold;
+}
+
+span.legend {
+        font-size: 70%;
+        text-align: center;
+}
+
+h3.version {
+        font-size: 90%;
+        text-align: center;
+}
+
+div.qindex, div.navtab{
+	background-color: #EBEFF6;
+	border: 1px solid #A3B4D7;
+	text-align: center;
+}
+
+div.qindex, div.navpath {
+	width: 100%;
+	line-height: 140%;
+}
+
+div.navtab {
+	margin-right: 15px;
+}
+
+/* @group Link Styling */
+
+a {
+	color: #3D578C;
+	font-weight: normal;
+	text-decoration: none;
+}
+
+.contents a:visited {
+	color: #4665A2;
+}
+
+a:hover {
+	text-decoration: underline;
+}
+
+a.qindex {
+	font-weight: bold;
+}
+
+a.qindexHL {
+	font-weight: bold;
+	background-color: #9CAFD4;
+	color: #FFFFFF;
+	border: 1px double #869DCA;
+}
+
+.contents a.qindexHL:visited {
+        color: #FFFFFF;
+}
+
+a.el {
+	font-weight: bold;
+}
+
+a.elRef {
+}
+
+a.code, a.code:visited, a.line, a.line:visited {
+	color: #4665A2; 
+}
+
+a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited {
+	color: #4665A2; 
+}
+
+/* @end */
+
+dl.el {
+	margin-left: -1cm;
+}
+
+ul {
+  overflow: hidden; /*Fixed: list item bullets overlap floating elements*/
+}
+
+#side-nav ul {
+  overflow: visible; /* reset ul rule for scroll bar in GENERATE_TREEVIEW window */
+}
+
+#main-nav ul {
+  overflow: visible; /* reset ul rule for the navigation bar drop down lists */
+}
+
+.fragment {
+  text-align: left;
+  direction: ltr;
+  overflow-x: auto; /*Fixed: fragment lines overlap floating elements*/
+  overflow-y: hidden;
+}
+
+pre.fragment {
+        border: 1px solid #C4CFE5;
+        background-color: #FBFCFD;
+        padding: 4px 6px;
+        margin: 4px 8px 4px 2px;
+        overflow: auto;
+        word-wrap: break-word;
+        font-size:  9pt;
+        line-height: 125%;
+        font-family: monospace, fixed;
+        font-size: 105%;
+}
+
+div.fragment {
+  padding: 0 0 1px 0; /*Fixed: last line underline overlap border*/
+  margin: 4px 8px 4px 2px;
+	background-color: #FBFCFD;
+	border: 1px solid #C4CFE5;
+}
+
+div.line {
+	font-family: monospace, fixed;
+        font-size: 13px;
+	min-height: 13px;
+	line-height: 1.0;
+	text-wrap: unrestricted;
+	white-space: -moz-pre-wrap; /* Moz */
+	white-space: -pre-wrap;     /* Opera 4-6 */
+	white-space: -o-pre-wrap;   /* Opera 7 */
+	white-space: pre-wrap;      /* CSS3  */
+	word-wrap: break-word;      /* IE 5.5+ */
+	text-indent: -53px;
+	padding-left: 53px;
+	padding-bottom: 0px;
+	margin: 0px;
+	-webkit-transition-property: background-color, box-shadow;
+	-webkit-transition-duration: 0.5s;
+	-moz-transition-property: background-color, box-shadow;
+	-moz-transition-duration: 0.5s;
+	-ms-transition-property: background-color, box-shadow;
+	-ms-transition-duration: 0.5s;
+	-o-transition-property: background-color, box-shadow;
+	-o-transition-duration: 0.5s;
+	transition-property: background-color, box-shadow;
+	transition-duration: 0.5s;
+}
+
+div.line:after {
+    content:"\000A";
+    white-space: pre;
+}
+
+div.line.glow {
+	background-color: cyan;
+	box-shadow: 0 0 10px cyan;
+}
+
+
+span.lineno {
+	padding-right: 4px;
+	text-align: right;
+	border-right: 2px solid #0F0;
+	background-color: #E8E8E8;
+        white-space: pre;
+}
+span.lineno a {
+	background-color: #D8D8D8;
+}
+
+span.lineno a:hover {
+	background-color: #C8C8C8;
+}
+
+.lineno {
+	-webkit-touch-callout: none;
+	-webkit-user-select: none;
+	-khtml-user-select: none;
+	-moz-user-select: none;
+	-ms-user-select: none;
+	user-select: none;
+}
+
+div.ah, span.ah {
+	background-color: black;
+	font-weight: bold;
+	color: #FFFFFF;
+	margin-bottom: 3px;
+	margin-top: 3px;
+	padding: 0.2em;
+	border: solid thin #333;
+	border-radius: 0.5em;
+	-webkit-border-radius: .5em;
+	-moz-border-radius: .5em;
+	box-shadow: 2px 2px 3px #999;
+	-webkit-box-shadow: 2px 2px 3px #999;
+	-moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px;
+	background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444));
+	background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000 110%);
+}
+
+div.classindex ul {
+        list-style: none;
+        padding-left: 0;
+}
+
+div.classindex span.ai {
+        display: inline-block;
+}
+
+div.groupHeader {
+	margin-left: 16px;
+	margin-top: 12px;
+	font-weight: bold;
+}
+
+div.groupText {
+	margin-left: 16px;
+	font-style: italic;
+}
+
+body {
+	background-color: white;
+	color: black;
+        margin: 0;
+}
+
+div.contents {
+	margin-top: 10px;
+	margin-left: 12px;
+	margin-right: 8px;
+}
+
+td.indexkey {
+	background-color: #EBEFF6;
+	font-weight: bold;
+	border: 1px solid #C4CFE5;
+	margin: 2px 0px 2px 0;
+	padding: 2px 10px;
+        white-space: nowrap;
+        vertical-align: top;
+}
+
+td.indexvalue {
+	background-color: #EBEFF6;
+	border: 1px solid #C4CFE5;
+	padding: 2px 10px;
+	margin: 2px 0px;
+}
+
+tr.memlist {
+	background-color: #EEF1F7;
+}
+
+p.formulaDsp {
+	text-align: center;
+}
+
+img.formulaDsp {
+	
+}
+
+img.formulaInl, img.inline {
+	vertical-align: middle;
+}
+
+div.center {
+	text-align: center;
+        margin-top: 0px;
+        margin-bottom: 0px;
+        padding: 0px;
+}
+
+div.center img {
+	border: 0px;
+}
+
+address.footer {
+	text-align: right;
+	padding-right: 12px;
+}
+
+img.footer {
+	border: 0px;
+	vertical-align: middle;
+}
+
+/* @group Code Colorization */
+
+span.keyword {
+	color: #008000
+}
+
+span.keywordtype {
+	color: #604020
+}
+
+span.keywordflow {
+	color: #e08000
+}
+
+span.comment {
+	color: #800000
+}
+
+span.preprocessor {
+	color: #806020
+}
+
+span.stringliteral {
+	color: #002080
+}
+
+span.charliteral {
+	color: #008080
+}
+
+span.vhdldigit { 
+	color: #ff00ff 
+}
+
+span.vhdlchar { 
+	color: #000000 
+}
+
+span.vhdlkeyword { 
+	color: #700070 
+}
+
+span.vhdllogic { 
+	color: #ff0000 
+}
+
+blockquote {
+        background-color: #F7F8FB;
+        border-left: 2px solid #9CAFD4;
+        margin: 0 24px 0 4px;
+        padding: 0 12px 0 16px;
+}
+
+blockquote.DocNodeRTL {
+   border-left: 0;
+   border-right: 2px solid #9CAFD4;
+   margin: 0 4px 0 24px;
+   padding: 0 16px 0 12px;
+}
+
+/* @end */
+
+/*
+.search {
+	color: #003399;
+	font-weight: bold;
+}
+
+form.search {
+	margin-bottom: 0px;
+	margin-top: 0px;
+}
+
+input.search {
+	font-size: 75%;
+	color: #000080;
+	font-weight: normal;
+	background-color: #e8eef2;
+}
+*/
+
+td.tiny {
+	font-size: 75%;
+}
+
+.dirtab {
+	padding: 4px;
+	border-collapse: collapse;
+	border: 1px solid #A3B4D7;
+}
+
+th.dirtab {
+	background: #EBEFF6;
+	font-weight: bold;
+}
+
+hr {
+	height: 0px;
+	border: none;
+	border-top: 1px solid #4A6AAA;
+}
+
+hr.footer {
+	height: 1px;
+}
+
+/* @group Member Descriptions */
+
+table.memberdecls {
+	border-spacing: 0px;
+	padding: 0px;
+}
+
+.memberdecls td, .fieldtable tr {
+	-webkit-transition-property: background-color, box-shadow;
+	-webkit-transition-duration: 0.5s;
+	-moz-transition-property: background-color, box-shadow;
+	-moz-transition-duration: 0.5s;
+	-ms-transition-property: background-color, box-shadow;
+	-ms-transition-duration: 0.5s;
+	-o-transition-property: background-color, box-shadow;
+	-o-transition-duration: 0.5s;
+	transition-property: background-color, box-shadow;
+	transition-duration: 0.5s;
+}
+
+.memberdecls td.glow, .fieldtable tr.glow {
+	background-color: cyan;
+	box-shadow: 0 0 15px cyan;
+}
+
+.mdescLeft, .mdescRight,
+.memItemLeft, .memItemRight,
+.memTemplItemLeft, .memTemplItemRight, .memTemplParams {
+	background-color: #F9FAFC;
+	border: none;
+	margin: 4px;
+	padding: 1px 0 0 8px;
+}
+
+.mdescLeft, .mdescRight {
+	padding: 0px 8px 4px 8px;
+	color: #555;
+}
+
+.memSeparator {
+        border-bottom: 1px solid #DEE4F0;
+        line-height: 1px;
+        margin: 0px;
+        padding: 0px;
+}
+
+.memItemLeft, .memTemplItemLeft {
+        white-space: nowrap;
+}
+
+.memItemRight, .memTemplItemRight {
+	width: 100%;
+}
+
+.memTemplParams {
+	color: #4665A2;
+        white-space: nowrap;
+	font-size: 80%;
+}
+
+/* @end */
+
+/* @group Member Details */
+
+/* Styles for detailed member documentation */
+
+.memtitle {
+	padding: 8px;
+	border-top: 1px solid #A8B8D9;
+	border-left: 1px solid #A8B8D9;
+	border-right: 1px solid #A8B8D9;
+	border-top-right-radius: 4px;
+	border-top-left-radius: 4px;
+	margin-bottom: -1px;
+	background-image: url('nav_f.png');
+	background-repeat: repeat-x;
+	background-color: #E2E8F2;
+	line-height: 1.25;
+	font-weight: 300;
+	float:left;
+}
+
+.permalink
+{
+        font-size: 65%;
+        display: inline-block;
+        vertical-align: middle;
+}
+
+.memtemplate {
+	font-size: 80%;
+	color: #4665A2;
+	font-weight: normal;
+	margin-left: 9px;
+}
+
+.memnav {
+	background-color: #EBEFF6;
+	border: 1px solid #A3B4D7;
+	text-align: center;
+	margin: 2px;
+	margin-right: 15px;
+	padding: 2px;
+}
+
+.mempage {
+	width: 100%;
+}
+
+.memitem {
+	padding: 0;
+	margin-bottom: 10px;
+	margin-right: 5px;
+        -webkit-transition: box-shadow 0.5s linear;
+        -moz-transition: box-shadow 0.5s linear;
+        -ms-transition: box-shadow 0.5s linear;
+        -o-transition: box-shadow 0.5s linear;
+        transition: box-shadow 0.5s linear;
+        display: table !important;
+        width: 100%;
+}
+
+.memitem.glow {
+         box-shadow: 0 0 15px cyan;
+}
+
+.memname {
+        font-weight: 400;
+        margin-left: 6px;
+}
+
+.memname td {
+	vertical-align: bottom;
+}
+
+.memproto, dl.reflist dt {
+        border-top: 1px solid #A8B8D9;
+        border-left: 1px solid #A8B8D9;
+        border-right: 1px solid #A8B8D9;
+        padding: 6px 0px 6px 0px;
+        color: #253555;
+        font-weight: bold;
+        text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9);
+        background-color: #DFE5F1;
+        /* opera specific markup */
+        box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
+        border-top-right-radius: 4px;
+        /* firefox specific markup */
+        -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px;
+        -moz-border-radius-topright: 4px;
+        /* webkit specific markup */
+        -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
+        -webkit-border-top-right-radius: 4px;
+
+}
+
+.overload {
+        font-family: "courier new",courier,monospace;
+	font-size: 65%;
+}
+
+.memdoc, dl.reflist dd {
+        border-bottom: 1px solid #A8B8D9;      
+        border-left: 1px solid #A8B8D9;      
+        border-right: 1px solid #A8B8D9; 
+        padding: 6px 10px 2px 10px;
+        background-color: #FBFCFD;
+        border-top-width: 0;
+        background-image:url('nav_g.png');
+        background-repeat:repeat-x;
+        background-color: #FFFFFF;
+        /* opera specific markup */
+        border-bottom-left-radius: 4px;
+        border-bottom-right-radius: 4px;
+        box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
+        /* firefox specific markup */
+        -moz-border-radius-bottomleft: 4px;
+        -moz-border-radius-bottomright: 4px;
+        -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px;
+        /* webkit specific markup */
+        -webkit-border-bottom-left-radius: 4px;
+        -webkit-border-bottom-right-radius: 4px;
+        -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
+}
+
+dl.reflist dt {
+        padding: 5px;
+}
+
+dl.reflist dd {
+        margin: 0px 0px 10px 0px;
+        padding: 5px;
+}
+
+.paramkey {
+	text-align: right;
+}
+
+.paramtype {
+	white-space: nowrap;
+}
+
+.paramname {
+	color: #602020;
+	white-space: nowrap;
+}
+.paramname em {
+	font-style: normal;
+}
+.paramname code {
+        line-height: 14px;
+}
+
+.params, .retval, .exception, .tparams {
+        margin-left: 0px;
+        padding-left: 0px;
+}       
+
+.params .paramname, .retval .paramname, .tparams .paramname, .exception .paramname {
+        font-weight: bold;
+        vertical-align: top;
+}
+        
+.params .paramtype, .tparams .paramtype {
+        font-style: italic;
+        vertical-align: top;
+}       
+        
+.params .paramdir, .tparams .paramdir {
+        font-family: "courier new",courier,monospace;
+        vertical-align: top;
+}
+
+table.mlabels {
+	border-spacing: 0px;
+}
+
+td.mlabels-left {
+	width: 100%;
+	padding: 0px;
+}
+
+td.mlabels-right {
+	vertical-align: bottom;
+	padding: 0px;
+	white-space: nowrap;
+}
+
+span.mlabels {
+        margin-left: 8px;
+}
+
+span.mlabel {
+        background-color: #728DC1;
+        border-top:1px solid #5373B4;
+        border-left:1px solid #5373B4;
+        border-right:1px solid #C4CFE5;
+        border-bottom:1px solid #C4CFE5;
+	text-shadow: none;
+	color: white;
+	margin-right: 4px;
+	padding: 2px 3px;
+	border-radius: 3px;
+	font-size: 7pt;
+	white-space: nowrap;
+	vertical-align: middle;
+}
+
+
+
+/* @end */
+
+/* these are for tree view inside a (index) page */
+
+div.directory {
+        margin: 10px 0px;
+        border-top: 1px solid #9CAFD4;
+        border-bottom: 1px solid #9CAFD4;
+        width: 100%;
+}
+
+.directory table {
+        border-collapse:collapse;
+}
+
+.directory td {
+        margin: 0px;
+        padding: 0px;
+	vertical-align: top;
+}
+
+.directory td.entry {
+        white-space: nowrap;
+        padding-right: 6px;
+	padding-top: 3px;
+}
+
+.directory td.entry a {
+        outline:none;
+}
+
+.directory td.entry a img {
+        border: none;
+}
+
+.directory td.desc {
+        width: 100%;
+        padding-left: 6px;
+	padding-right: 6px;
+	padding-top: 3px;
+	border-left: 1px solid rgba(0,0,0,0.05);
+}
+
+.directory tr.even {
+	padding-left: 6px;
+	background-color: #F7F8FB;
+}
+
+.directory img {
+	vertical-align: -30%;
+}
+
+.directory .levels {
+        white-space: nowrap;
+        width: 100%;
+        text-align: right;
+        font-size: 9pt;
+}
+
+.directory .levels span {
+        cursor: pointer;
+        padding-left: 2px;
+        padding-right: 2px;
+	color: #3D578C;
+}
+
+.arrow {
+    color: #9CAFD4;
+    -webkit-user-select: none;
+    -khtml-user-select: none;
+    -moz-user-select: none;
+    -ms-user-select: none;
+    user-select: none;
+    cursor: pointer;
+    font-size: 80%;
+    display: inline-block;
+    width: 16px;
+    height: 22px;
+}
+
+.icon {
+    font-family: Arial, Helvetica;
+    font-weight: bold;
+    font-size: 12px;
+    height: 14px;
+    width: 16px;
+    display: inline-block;
+    background-color: #728DC1;
+    color: white;
+    text-align: center;
+    border-radius: 4px;
+    margin-left: 2px;
+    margin-right: 2px;
+}
+
+.icona {
+    width: 24px;
+    height: 22px;
+    display: inline-block;
+}
+
+.iconfopen {
+    width: 24px;
+    height: 18px;
+    margin-bottom: 4px;
+    background-image:url('folderopen.png');
+    background-position: 0px -4px;
+    background-repeat: repeat-y;
+    vertical-align:top;
+    display: inline-block;
+}
+
+.iconfclosed {
+    width: 24px;
+    height: 18px;
+    margin-bottom: 4px;
+    background-image:url('folderclosed.png');
+    background-position: 0px -4px;
+    background-repeat: repeat-y;
+    vertical-align:top;
+    display: inline-block;
+}
+
+.icondoc {
+    width: 24px;
+    height: 18px;
+    margin-bottom: 4px;
+    background-image:url('doc.png');
+    background-position: 0px -4px;
+    background-repeat: repeat-y;
+    vertical-align:top;
+    display: inline-block;
+}
+
+table.directory {
+    font: 400 14px Roboto,sans-serif;
+}
+
+/* @end */
+
+div.dynheader {
+        margin-top: 8px;
+	-webkit-touch-callout: none;
+	-webkit-user-select: none;
+	-khtml-user-select: none;
+	-moz-user-select: none;
+	-ms-user-select: none;
+	user-select: none;
+}
+
+address {
+	font-style: normal;
+	color: #2A3D61;
+}
+
+table.doxtable caption {
+	caption-side: top;
+}
+
+table.doxtable {
+	border-collapse:collapse;
+        margin-top: 4px;
+        margin-bottom: 4px;
+}
+
+table.doxtable td, table.doxtable th {
+	border: 1px solid #2D4068;
+	padding: 3px 7px 2px;
+}
+
+table.doxtable th {
+	background-color: #374F7F;
+	color: #FFFFFF;
+	font-size: 110%;
+	padding-bottom: 4px;
+	padding-top: 5px;
+}
+
+table.fieldtable {
+        /*width: 100%;*/
+        margin-bottom: 10px;
+        border: 1px solid #A8B8D9;
+        border-spacing: 0px;
+        -moz-border-radius: 4px;
+        -webkit-border-radius: 4px;
+        border-radius: 4px;
+        -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px;
+        -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15);
+        box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15);
+}
+
+.fieldtable td, .fieldtable th {
+        padding: 3px 7px 2px;
+}
+
+.fieldtable td.fieldtype, .fieldtable td.fieldname {
+        white-space: nowrap;
+        border-right: 1px solid #A8B8D9;
+        border-bottom: 1px solid #A8B8D9;
+        vertical-align: top;
+}
+
+.fieldtable td.fieldname {
+        padding-top: 3px;
+}
+
+.fieldtable td.fielddoc {
+        border-bottom: 1px solid #A8B8D9;
+        /*width: 100%;*/
+}
+
+.fieldtable td.fielddoc p:first-child {
+        margin-top: 0px;
+}       
+        
+.fieldtable td.fielddoc p:last-child {
+        margin-bottom: 2px;
+}
+
+.fieldtable tr:last-child td {
+        border-bottom: none;
+}
+
+.fieldtable th {
+        background-image:url('nav_f.png');
+        background-repeat:repeat-x;
+        background-color: #E2E8F2;
+        font-size: 90%;
+        color: #253555;
+        padding-bottom: 4px;
+        padding-top: 5px;
+        text-align:left;
+        font-weight: 400;
+        -moz-border-radius-topleft: 4px;
+        -moz-border-radius-topright: 4px;
+        -webkit-border-top-left-radius: 4px;
+        -webkit-border-top-right-radius: 4px;
+        border-top-left-radius: 4px;
+        border-top-right-radius: 4px;
+        border-bottom: 1px solid #A8B8D9;
+}
+
+
+.tabsearch {
+	top: 0px;
+	left: 10px;
+	height: 36px;
+	background-image: url('tab_b.png');
+	z-index: 101;
+	overflow: hidden;
+	font-size: 13px;
+}
+
+.navpath ul
+{
+	font-size: 11px;
+	background-image:url('tab_b.png');
+	background-repeat:repeat-x;
+	background-position: 0 -5px;
+	height:30px;
+	line-height:30px;
+	color:#8AA0CC;
+	border:solid 1px #C2CDE4;
+	overflow:hidden;
+	margin:0px;
+	padding:0px;
+}
+
+.navpath li
+{
+	list-style-type:none;
+	float:left;
+	padding-left:10px;
+	padding-right:15px;
+	background-image:url('bc_s.png');
+	background-repeat:no-repeat;
+	background-position:right;
+	color:#364D7C;
+}
+
+.navpath li.navelem a
+{
+	height:32px;
+	display:block;
+	text-decoration: none;
+	outline: none;
+	color: #283A5D;
+	font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif;
+	text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9);
+	text-decoration: none;        
+}
+
+.navpath li.navelem a:hover
+{
+	color:#6884BD;
+}
+
+.navpath li.footer
+{
+        list-style-type:none;
+        float:right;
+        padding-left:10px;
+        padding-right:15px;
+        background-image:none;
+        background-repeat:no-repeat;
+        background-position:right;
+        color:#364D7C;
+        font-size: 8pt;
+}
+
+
+div.summary
+{
+	float: right;
+	font-size: 8pt;
+	padding-right: 5px;
+	width: 50%;
+	text-align: right;
+}       
+
+div.summary a
+{
+	white-space: nowrap;
+}
+
+table.classindex
+{
+        margin: 10px;
+        white-space: nowrap;
+        margin-left: 3%;
+        margin-right: 3%;
+        width: 94%;
+        border: 0;
+        border-spacing: 0; 
+        padding: 0;
+}
+
+div.ingroups
+{
+	font-size: 8pt;
+	width: 50%;
+	text-align: left;
+}
+
+div.ingroups a
+{
+	white-space: nowrap;
+}
+
+div.header
+{
+        background-image:url('nav_h.png');
+        background-repeat:repeat-x;
+	background-color: #F9FAFC;
+	margin:  0px;
+	border-bottom: 1px solid #C4CFE5;
+}
+
+div.headertitle
+{
+	padding: 5px 5px 5px 10px;
+}
+
+.PageDocRTL-title div.headertitle {
+  text-align: right;
+  direction: rtl;
+}
+
+dl {
+        padding: 0 0 0 0;
+}
+
+/* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug, dl.examples */
+dl.section {
+	margin-left: 0px;
+	padding-left: 0px;
+}
+
+dl.section.DocNodeRTL {
+  margin-right: 0px;
+  padding-right: 0px;
+}
+
+dl.note {
+  margin-left: -7px;
+  padding-left: 3px;
+  border-left: 4px solid;
+  border-color: #D0C000;
+}
+
+dl.note.DocNodeRTL {
+  margin-left: 0;
+  padding-left: 0;
+  border-left: 0;
+  margin-right: -7px;
+  padding-right: 3px;
+  border-right: 4px solid;
+  border-color: #D0C000;
+}
+
+dl.warning, dl.attention {
+  margin-left: -7px;
+  padding-left: 3px;
+  border-left: 4px solid;
+  border-color: #FF0000;
+}
+
+dl.warning.DocNodeRTL, dl.attention.DocNodeRTL {
+  margin-left: 0;
+  padding-left: 0;
+  border-left: 0;
+  margin-right: -7px;
+  padding-right: 3px;
+  border-right: 4px solid;
+  border-color: #FF0000;
+}
+
+dl.pre, dl.post, dl.invariant {
+  margin-left: -7px;
+  padding-left: 3px;
+  border-left: 4px solid;
+  border-color: #00D000;
+}
+
+dl.pre.DocNodeRTL, dl.post.DocNodeRTL, dl.invariant.DocNodeRTL {
+  margin-left: 0;
+  padding-left: 0;
+  border-left: 0;
+  margin-right: -7px;
+  padding-right: 3px;
+  border-right: 4px solid;
+  border-color: #00D000;
+}
+
+dl.deprecated {
+  margin-left: -7px;
+  padding-left: 3px;
+  border-left: 4px solid;
+  border-color: #505050;
+}
+
+dl.deprecated.DocNodeRTL {
+  margin-left: 0;
+  padding-left: 0;
+  border-left: 0;
+  margin-right: -7px;
+  padding-right: 3px;
+  border-right: 4px solid;
+  border-color: #505050;
+}
+
+dl.todo {
+  margin-left: -7px;
+  padding-left: 3px;
+  border-left: 4px solid;
+  border-color: #00C0E0;
+}
+
+dl.todo.DocNodeRTL {
+  margin-left: 0;
+  padding-left: 0;
+  border-left: 0;
+  margin-right: -7px;
+  padding-right: 3px;
+  border-right: 4px solid;
+  border-color: #00C0E0;
+}
+
+dl.test {
+  margin-left: -7px;
+  padding-left: 3px;
+  border-left: 4px solid;
+  border-color: #3030E0;
+}
+
+dl.test.DocNodeRTL {
+  margin-left: 0;
+  padding-left: 0;
+  border-left: 0;
+  margin-right: -7px;
+  padding-right: 3px;
+  border-right: 4px solid;
+  border-color: #3030E0;
+}
+
+dl.bug {
+  margin-left: -7px;
+  padding-left: 3px;
+  border-left: 4px solid;
+  border-color: #C08050;
+}
+
+dl.bug.DocNodeRTL {
+  margin-left: 0;
+  padding-left: 0;
+  border-left: 0;
+  margin-right: -7px;
+  padding-right: 3px;
+  border-right: 4px solid;
+  border-color: #C08050;
+}
+
+dl.section dd {
+	margin-bottom: 6px;
+}
+
+
+#projectlogo
+{
+	text-align: center;
+	vertical-align: bottom;
+	border-collapse: separate;
+}
+ 
+#projectlogo img
+{ 
+	border: 0px none;
+}
+ 
+#projectalign
+{
+        vertical-align: middle;
+}
+
+#projectname
+{
+	font: 300% Tahoma, Arial,sans-serif;
+	margin: 0px;
+	padding: 2px 0px;
+}
+    
+#projectbrief
+{
+	font: 120% Tahoma, Arial,sans-serif;
+	margin: 0px;
+	padding: 0px;
+}
+
+#projectnumber
+{
+	font: 50% Tahoma, Arial,sans-serif;
+	margin: 0px;
+	padding: 0px;
+}
+
+#titlearea
+{
+	padding: 0px;
+	margin: 0px;
+	width: 100%;
+	border-bottom: 1px solid #5373B4;
+}
+
+.image
+{
+        text-align: center;
+}
+
+.dotgraph
+{
+        text-align: center;
+}
+
+.mscgraph
+{
+        text-align: center;
+}
+
+.plantumlgraph
+{
+        text-align: center;
+}
+
+.diagraph
+{
+        text-align: center;
+}
+
+.caption
+{
+	font-weight: bold;
+}
+
+div.zoom
+{
+	border: 1px solid #90A5CE;
+}
+
+dl.citelist {
+        margin-bottom:50px;
+}
+
+dl.citelist dt {
+        color:#334975;
+        float:left;
+        font-weight:bold;
+        margin-right:10px;
+        padding:5px;
+}
+
+dl.citelist dd {
+        margin:2px 0;
+        padding:5px 0;
+}
+
+div.toc {
+        padding: 14px 25px;
+        background-color: #F4F6FA;
+        border: 1px solid #D8DFEE;
+        border-radius: 7px 7px 7px 7px;
+        float: right;
+        height: auto;
+        margin: 0 8px 10px 10px;
+        width: 200px;
+}
+
+.PageDocRTL-title div.toc {
+  float: left !important;
+  text-align: right;
+}
+
+div.toc li {
+        background: url("bdwn.png") no-repeat scroll 0 5px transparent;
+        font: 10px/1.2 Verdana,DejaVu Sans,Geneva,sans-serif;
+        margin-top: 5px;
+        padding-left: 10px;
+        padding-top: 2px;
+}
+
+.PageDocRTL-title div.toc li {
+  background-position-x: right !important;
+  padding-left: 0 !important;
+  padding-right: 10px;
+}
+
+div.toc h3 {
+        font: bold 12px/1.2 Arial,FreeSans,sans-serif;
+	color: #4665A2;
+        border-bottom: 0 none;
+        margin: 0;
+}
+
+div.toc ul {
+        list-style: none outside none;
+        border: medium none;
+        padding: 0px;
+}       
+
+div.toc li.level1 {
+        margin-left: 0px;
+}
+
+div.toc li.level2 {
+        margin-left: 15px;
+}
+
+div.toc li.level3 {
+        margin-left: 30px;
+}
+
+div.toc li.level4 {
+        margin-left: 45px;
+}
+
+.PageDocRTL-title div.toc li.level1 {
+  margin-left: 0 !important;
+  margin-right: 0;
+}
+
+.PageDocRTL-title div.toc li.level2 {
+  margin-left: 0 !important;
+  margin-right: 15px;
+}
+
+.PageDocRTL-title div.toc li.level3 {
+  margin-left: 0 !important;
+  margin-right: 30px;
+}
+
+.PageDocRTL-title div.toc li.level4 {
+  margin-left: 0 !important;
+  margin-right: 45px;
+}
+
+.inherit_header {
+        font-weight: bold;
+        color: gray;
+        cursor: pointer;
+	-webkit-touch-callout: none;
+	-webkit-user-select: none;
+	-khtml-user-select: none;
+	-moz-user-select: none;
+	-ms-user-select: none;
+	user-select: none;
+}
+
+.inherit_header td {
+        padding: 6px 0px 2px 5px;
+}
+
+.inherit {
+        display: none;
+}
+
+tr.heading h2 {
+        margin-top: 12px;
+        margin-bottom: 4px;
+}
+
+/* tooltip related style info */
+
+.ttc {
+        position: absolute;
+        display: none;
+}
+
+#powerTip {
+	cursor: default;
+	white-space: nowrap;
+	background-color: white;
+	border: 1px solid gray;
+	border-radius: 4px 4px 4px 4px;
+	box-shadow: 1px 1px 7px gray;
+	display: none;
+	font-size: smaller;
+	max-width: 80%;
+	opacity: 0.9;
+	padding: 1ex 1em 1em;
+	position: absolute;
+	z-index: 2147483647;
+}
+
+#powerTip div.ttdoc {
+        color: grey;
+	font-style: italic;
+}
+
+#powerTip div.ttname a {
+        font-weight: bold;
+}
+
+#powerTip div.ttname {
+        font-weight: bold;
+}
+
+#powerTip div.ttdeci {
+        color: #006318;
+}
+
+#powerTip div {
+        margin: 0px;
+        padding: 0px;
+        font: 12px/16px Roboto,sans-serif;
+}
+
+#powerTip:before, #powerTip:after {
+	content: "";
+	position: absolute;
+	margin: 0px;
+}
+
+#powerTip.n:after,  #powerTip.n:before,
+#powerTip.s:after,  #powerTip.s:before,
+#powerTip.w:after,  #powerTip.w:before,
+#powerTip.e:after,  #powerTip.e:before,
+#powerTip.ne:after, #powerTip.ne:before,
+#powerTip.se:after, #powerTip.se:before,
+#powerTip.nw:after, #powerTip.nw:before,
+#powerTip.sw:after, #powerTip.sw:before {
+	border: solid transparent;
+	content: " ";
+	height: 0;
+	width: 0;
+	position: absolute;
+}
+
+#powerTip.n:after,  #powerTip.s:after,
+#powerTip.w:after,  #powerTip.e:after,
+#powerTip.nw:after, #powerTip.ne:after,
+#powerTip.sw:after, #powerTip.se:after {
+	border-color: rgba(255, 255, 255, 0);
+}
+
+#powerTip.n:before,  #powerTip.s:before,
+#powerTip.w:before,  #powerTip.e:before,
+#powerTip.nw:before, #powerTip.ne:before,
+#powerTip.sw:before, #powerTip.se:before {
+	border-color: rgba(128, 128, 128, 0);
+}
+
+#powerTip.n:after,  #powerTip.n:before,
+#powerTip.ne:after, #powerTip.ne:before,
+#powerTip.nw:after, #powerTip.nw:before {
+	top: 100%;
+}
+
+#powerTip.n:after, #powerTip.ne:after, #powerTip.nw:after {
+	border-top-color: #FFFFFF;
+	border-width: 10px;
+	margin: 0px -10px;
+}
+#powerTip.n:before {
+	border-top-color: #808080;
+	border-width: 11px;
+	margin: 0px -11px;
+}
+#powerTip.n:after, #powerTip.n:before {
+	left: 50%;
+}
+
+#powerTip.nw:after, #powerTip.nw:before {
+	right: 14px;
+}
+
+#powerTip.ne:after, #powerTip.ne:before {
+	left: 14px;
+}
+
+#powerTip.s:after,  #powerTip.s:before,
+#powerTip.se:after, #powerTip.se:before,
+#powerTip.sw:after, #powerTip.sw:before {
+	bottom: 100%;
+}
+
+#powerTip.s:after, #powerTip.se:after, #powerTip.sw:after {
+	border-bottom-color: #FFFFFF;
+	border-width: 10px;
+	margin: 0px -10px;
+}
+
+#powerTip.s:before, #powerTip.se:before, #powerTip.sw:before {
+	border-bottom-color: #808080;
+	border-width: 11px;
+	margin: 0px -11px;
+}
+
+#powerTip.s:after, #powerTip.s:before {
+	left: 50%;
+}
+
+#powerTip.sw:after, #powerTip.sw:before {
+	right: 14px;
+}
+
+#powerTip.se:after, #powerTip.se:before {
+	left: 14px;
+}
+
+#powerTip.e:after, #powerTip.e:before {
+	left: 100%;
+}
+#powerTip.e:after {
+	border-left-color: #FFFFFF;
+	border-width: 10px;
+	top: 50%;
+	margin-top: -10px;
+}
+#powerTip.e:before {
+	border-left-color: #808080;
+	border-width: 11px;
+	top: 50%;
+	margin-top: -11px;
+}
+
+#powerTip.w:after, #powerTip.w:before {
+	right: 100%;
+}
+#powerTip.w:after {
+	border-right-color: #FFFFFF;
+	border-width: 10px;
+	top: 50%;
+	margin-top: -10px;
+}
+#powerTip.w:before {
+	border-right-color: #808080;
+	border-width: 11px;
+	top: 50%;
+	margin-top: -11px;
+}
+
+@media print
+{
+  #top { display: none; }
+  #side-nav { display: none; }
+  #nav-path { display: none; }
+  body { overflow:visible; }
+  h1, h2, h3, h4, h5, h6 { page-break-after: avoid; }
+  .summary { display: none; }
+  .memitem { page-break-inside: avoid; }
+  #doc-content
+  {
+    margin-left:0 !important;
+    height:auto !important;
+    width:auto !important;
+    overflow:inherit;
+    display:inline;
+  }
+}
+
+/* @group Markdown */
+
+/*
+table.markdownTable {
+	border-collapse:collapse;
+        margin-top: 4px;
+        margin-bottom: 4px;
+}
+
+table.markdownTable td, table.markdownTable th {
+	border: 1px solid #2D4068;
+	padding: 3px 7px 2px;
+}
+
+table.markdownTableHead tr {
+}
+
+table.markdownTableBodyLeft td, table.markdownTable th {
+	border: 1px solid #2D4068;
+	padding: 3px 7px 2px;
+}
+
+th.markdownTableHeadLeft th.markdownTableHeadRight th.markdownTableHeadCenter th.markdownTableHeadNone {
+	background-color: #374F7F;
+	color: #FFFFFF;
+	font-size: 110%;
+	padding-bottom: 4px;
+	padding-top: 5px;
+}
+
+th.markdownTableHeadLeft {
+	text-align: left
+}
+
+th.markdownTableHeadRight {
+	text-align: right
+}
+
+th.markdownTableHeadCenter {
+	text-align: center
+}
+*/
+
+table.markdownTable {
+	border-collapse:collapse;
+        margin-top: 4px;
+        margin-bottom: 4px;
+}
+
+table.markdownTable td, table.markdownTable th {
+	border: 1px solid #2D4068;
+	padding: 3px 7px 2px;
+}
+
+table.markdownTable tr {
+}
+
+th.markdownTableHeadLeft, th.markdownTableHeadRight, th.markdownTableHeadCenter, th.markdownTableHeadNone {
+	background-color: #374F7F;
+	color: #FFFFFF;
+	font-size: 110%;
+	padding-bottom: 4px;
+	padding-top: 5px;
+}
+
+th.markdownTableHeadLeft, td.markdownTableBodyLeft {
+	text-align: left
+}
+
+th.markdownTableHeadRight, td.markdownTableBodyRight {
+	text-align: right
+}
+
+th.markdownTableHeadCenter, td.markdownTableBodyCenter {
+	text-align: center
+}
+
+.DocNodeRTL {
+  text-align: right;
+  direction: rtl;
+}
+
+.DocNodeLTR {
+  text-align: left;
+  direction: ltr;
+}
+
+table.DocNodeRTL {
+   width: auto;
+   margin-right: 0;
+   margin-left: auto;
+}
+
+table.DocNodeLTR {
+   width: auto;
+   margin-right: auto;
+   margin-left: 0;
+}
+
+tt, code, kbd, samp
+{
+  display: inline-block;
+  direction:ltr; 
+}
+/* @end */
+
+u {
+	text-decoration: underline;
+}
+
diff --git a/third_party/VulkanMemoryAllocator/docs/html/doxygen.png b/third_party/VulkanMemoryAllocator/docs/html/doxygen.png
new file mode 100644
index 0000000..3ff17d8
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/doxygen.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/docs/html/dynsections.js b/third_party/VulkanMemoryAllocator/docs/html/dynsections.js
new file mode 100644
index 0000000..ea0a7b3
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/dynsections.js
@@ -0,0 +1,120 @@
+/*
+ @licstart  The following is the entire license notice for the
+ JavaScript code in this file.
+
+ Copyright (C) 1997-2017 by Dimitri van Heesch
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ @licend  The above is the entire license notice
+ for the JavaScript code in this file
+ */
+function toggleVisibility(linkObj)
+{
+ var base = $(linkObj).attr('id');
+ var summary = $('#'+base+'-summary');
+ var content = $('#'+base+'-content');
+ var trigger = $('#'+base+'-trigger');
+ var src=$(trigger).attr('src');
+ if (content.is(':visible')===true) {
+   content.hide();
+   summary.show();
+   $(linkObj).addClass('closed').removeClass('opened');
+   $(trigger).attr('src',src.substring(0,src.length-8)+'closed.png');
+ } else {
+   content.show();
+   summary.hide();
+   $(linkObj).removeClass('closed').addClass('opened');
+   $(trigger).attr('src',src.substring(0,src.length-10)+'open.png');
+ }
+ return false;
+}
+
+function updateStripes()
+{
+  $('table.directory tr').
+       removeClass('even').filter(':visible:even').addClass('even');
+}
+
+function toggleLevel(level)
+{
+  $('table.directory tr').each(function() {
+    var l = this.id.split('_').length-1;
+    var i = $('#img'+this.id.substring(3));
+    var a = $('#arr'+this.id.substring(3));
+    if (l<level+1) {
+      i.removeClass('iconfopen iconfclosed').addClass('iconfopen');
+      a.html('&#9660;');
+      $(this).show();
+    } else if (l==level+1) {
+      i.removeClass('iconfclosed iconfopen').addClass('iconfclosed');
+      a.html('&#9658;');
+      $(this).show();
+    } else {
+      $(this).hide();
+    }
+  });
+  updateStripes();
+}
+
+function toggleFolder(id)
+{
+  // the clicked row
+  var currentRow = $('#row_'+id);
+
+  // all rows after the clicked row
+  var rows = currentRow.nextAll("tr");
+
+  var re = new RegExp('^row_'+id+'\\d+_$', "i"); //only one sub
+
+  // only match elements AFTER this one (can't hide elements before)
+  var childRows = rows.filter(function() { return this.id.match(re); });
+
+  // first row is visible we are HIDING
+  if (childRows.filter(':first').is(':visible')===true) {
+    // replace down arrow by right arrow for current row
+    var currentRowSpans = currentRow.find("span");
+    currentRowSpans.filter(".iconfopen").removeClass("iconfopen").addClass("iconfclosed");
+    currentRowSpans.filter(".arrow").html('&#9658;');
+    rows.filter("[id^=row_"+id+"]").hide(); // hide all children
+  } else { // we are SHOWING
+    // replace right arrow by down arrow for current row
+    var currentRowSpans = currentRow.find("span");
+    currentRowSpans.filter(".iconfclosed").removeClass("iconfclosed").addClass("iconfopen");
+    currentRowSpans.filter(".arrow").html('&#9660;');
+    // replace down arrows by right arrows for child rows
+    var childRowsSpans = childRows.find("span");
+    childRowsSpans.filter(".iconfopen").removeClass("iconfopen").addClass("iconfclosed");
+    childRowsSpans.filter(".arrow").html('&#9658;');
+    childRows.show(); //show all children
+  }
+  updateStripes();
+}
+
+
+function toggleInherit(id)
+{
+  var rows = $('tr.inherit.'+id);
+  var img = $('tr.inherit_header.'+id+' img');
+  var src = $(img).attr('src');
+  if (rows.filter(':first').is(':visible')===true) {
+    rows.css('display','none');
+    $(img).attr('src',src.substring(0,src.length-8)+'closed.png');
+  } else {
+    rows.css('display','table-row'); // using show() causes jump in firefox
+    $(img).attr('src',src.substring(0,src.length-10)+'open.png');
+  }
+}
+/* @license-end */
diff --git a/third_party/VulkanMemoryAllocator/docs/html/enabling_buffer_device_address.html b/third_party/VulkanMemoryAllocator/docs/html/enabling_buffer_device_address.html
new file mode 100644
index 0000000..8abeaf6
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/enabling_buffer_device_address.html
@@ -0,0 +1,98 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: Enabling buffer device address</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+  <ul>
+<li class="navelem"><a class="el" href="index.html">Vulkan Memory Allocator</a></li>  </ul>
+</div>
+</div><!-- top -->
+<div class="PageDoc"><div class="header">
+  <div class="headertitle">
+<div class="title">Enabling buffer device address </div>  </div>
+</div><!--header-->
+<div class="contents">
+<div class="textblock"><p>Device extension VK_KHR_buffer_device_address allow to fetch raw GPU pointer to a buffer and pass it for usage in a shader code. It is promoted to core Vulkan 1.2.</p>
+<p>If you want to use this feature in connection with VMA, follow these steps:</p>
+<h1><a class="anchor" id="enabling_buffer_device_address_initialization"></a>
+Initialization</h1>
+<p>1) (For Vulkan version &lt; 1.2) Call <code>vkEnumerateDeviceExtensionProperties</code> for the physical device. Check if the extension is supported - if returned array of <code>VkExtensionProperties</code> contains "VK_KHR_buffer_device_address".</p>
+<p>2) Call <code>vkGetPhysicalDeviceFeatures2</code> for the physical device instead of old <code>vkGetPhysicalDeviceFeatures</code>. Attach additional structure <code>VkPhysicalDeviceBufferDeviceAddressFeatures*</code> to <code>VkPhysicalDeviceFeatures2::pNext</code> to be returned. Check if the device feature is really supported - check if <code>VkPhysicalDeviceBufferDeviceAddressFeatures*::bufferDeviceAddress</code> is true.</p>
+<p>3) (For Vulkan version &lt; 1.2) While creating device with <code>vkCreateDevice</code>, enable this extension - add "VK_KHR_buffer_device_address" to the list passed as <code>VkDeviceCreateInfo::ppEnabledExtensionNames</code>.</p>
+<p>4) While creating the device, also don't set <code>VkDeviceCreateInfo::pEnabledFeatures</code>. Fill in <code>VkPhysicalDeviceFeatures2</code> structure instead and pass it as <code>VkDeviceCreateInfo::pNext</code>. Enable this device feature - attach additional structure <code>VkPhysicalDeviceBufferDeviceAddressFeatures*</code> to <code>VkPhysicalDeviceFeatures2::pNext</code> and set its member <code>bufferDeviceAddress</code> to <code>VK_TRUE</code>.</p>
+<p>5) While creating <a class="el" href="struct_vma_allocator.html" title="Represents main object of this library initialized.">VmaAllocator</a> with <a class="el" href="vk__mem__alloc_8h.html#a200692051ddb34240248234f5f4c17bb" title="Creates Allocator object.">vmaCreateAllocator()</a> inform VMA that you have enabled this feature - add <a class="el" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca5f1b28b0414319d1687e1f2b30ab0089">VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT</a> to <a class="el" href="struct_vma_allocator_create_info.html#a392ea2ecbaff93f91a7c49f735ad4346" title="Flags for created allocator. Use VmaAllocatorCreateFlagBits enum.">VmaAllocatorCreateInfo::flags</a>.</p>
+<h1><a class="anchor" id="enabling_buffer_device_address_usage"></a>
+Usage</h1>
+<p>After following steps described above, you can create buffers with <code>VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT*</code> using VMA. The library automatically adds <code>VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT*</code> to allocated memory blocks wherever it might be needed.</p>
+<p>Please note that the library supports only <code>VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT*</code>. The second part of this functionality related to "capture and replay" is not supported, as it is intended for usage in debugging tools like RenderDoc, not in everyday Vulkan usage.</p>
+<h1><a class="anchor" id="enabling_buffer_device_address_more_information"></a>
+More information</h1>
+<p>To learn more about this extension, see <a href="https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/chap46.html#VK_KHR_buffer_device_address">VK_KHR_buffer_device_address in Vulkan specification</a></p>
+<p>Example use of this extension can be found in the code of the sample and test suite accompanying this library. </p>
+</div></div><!-- contents -->
+</div><!-- PageDoc -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/files.html b/third_party/VulkanMemoryAllocator/docs/html/files.html
new file mode 100644
index 0000000..ca2e5e4
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/files.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: File List</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+  <div class="headertitle">
+<div class="title">File List</div>  </div>
+</div><!--header-->
+<div class="contents">
+<div class="textblock">Here is a list of all files with brief descriptions:</div><div class="directory">
+<table class="directory">
+<tr id="row_0_" class="even"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><a href="vk__mem__alloc_8h_source.html"><span class="icondoc"></span></a><a class="el" href="vk__mem__alloc_8h.html" target="_self">vk_mem_alloc.h</a></td><td class="desc"></td></tr>
+</table>
+</div><!-- directory -->
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/folderclosed.png b/third_party/VulkanMemoryAllocator/docs/html/folderclosed.png
new file mode 100644
index 0000000..bb8ab35
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/folderclosed.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/docs/html/folderopen.png b/third_party/VulkanMemoryAllocator/docs/html/folderopen.png
new file mode 100644
index 0000000..d6c7f67
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/folderopen.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/docs/html/functions.html b/third_party/VulkanMemoryAllocator/docs/html/functions.html
new file mode 100644
index 0000000..cf31089
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/functions.html
@@ -0,0 +1,396 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: Class Members</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="contents">
+<div class="textblock">Here is a list of all class members with links to the classes they belong to:</div>
+
+<h3><a id="index_a"></a>- a -</h3><ul>
+<li>allocation
+: <a class="el" href="struct_vma_defragmentation_pass_move_info.html#ae885c861c2dd8d622e6c19e281d035cc">VmaDefragmentationPassMoveInfo</a>
+</li>
+<li>allocationBytes
+: <a class="el" href="struct_vma_budget.html#a7e2a6583ebd63e194951c542563804d8">VmaBudget</a>
+</li>
+<li>allocationCount
+: <a class="el" href="struct_vma_defragmentation_info2.html#a3cf86ab32c1da779b4923d301a3056ba">VmaDefragmentationInfo2</a>
+, <a class="el" href="struct_vma_pool_stats.html#ad1924eb54fffa45e9e0e65670c8fe5eb">VmaPoolStats</a>
+, <a class="el" href="struct_vma_stat_info.html#a537741e4d5cdddc1c0ab95ec650afaff">VmaStatInfo</a>
+</li>
+<li>allocationSizeAvg
+: <a class="el" href="struct_vma_stat_info.html#a1081a039964e566c672e7a2347f9e599">VmaStatInfo</a>
+</li>
+<li>allocationSizeMax
+: <a class="el" href="struct_vma_stat_info.html#a17e9733a5ecd76287d4db6e66f71f50c">VmaStatInfo</a>
+</li>
+<li>allocationSizeMin
+: <a class="el" href="struct_vma_stat_info.html#ade8b40bd3139c04aabd2fc538a356fea">VmaStatInfo</a>
+</li>
+<li>allocationsMoved
+: <a class="el" href="struct_vma_defragmentation_stats.html#aefeabf130022008eadd75999478af3f9">VmaDefragmentationStats</a>
+</li>
+</ul>
+
+
+<h3><a id="index_b"></a>- b -</h3><ul>
+<li>blockBytes
+: <a class="el" href="struct_vma_budget.html#a58b492901baab685f466199124e514a0">VmaBudget</a>
+</li>
+<li>blockCount
+: <a class="el" href="struct_vma_pool_stats.html#aa0b5cb45cef6f18571cefb03b9a230e7">VmaPoolStats</a>
+, <a class="el" href="struct_vma_stat_info.html#abc4bb7cd611900778464c56e50c970a4">VmaStatInfo</a>
+</li>
+<li>blockSize
+: <a class="el" href="struct_vma_pool_create_info.html#aa4265160536cdb9be821b7686c16c676">VmaPoolCreateInfo</a>
+</li>
+<li>budget
+: <a class="el" href="struct_vma_budget.html#ab82e1d1754c2d210d0bdf90220bc6cdd">VmaBudget</a>
+</li>
+<li>bytesFreed
+: <a class="el" href="struct_vma_defragmentation_stats.html#ab0cb9ac0dbc106c77e384ea676422f28">VmaDefragmentationStats</a>
+</li>
+<li>bytesMoved
+: <a class="el" href="struct_vma_defragmentation_stats.html#a36f9d5df2a10ba2a36b16e126d60572d">VmaDefragmentationStats</a>
+</li>
+</ul>
+
+
+<h3><a id="index_c"></a>- c -</h3><ul>
+<li>commandBuffer
+: <a class="el" href="struct_vma_defragmentation_info2.html#a7f71f39590c5316771493d2333f9c1bd">VmaDefragmentationInfo2</a>
+</li>
+</ul>
+
+
+<h3><a id="index_d"></a>- d -</h3><ul>
+<li>device
+: <a class="el" href="struct_vma_allocator_create_info.html#ad924ddd77b04039c88d0c09b0ffcd500">VmaAllocatorCreateInfo</a>
+, <a class="el" href="struct_vma_allocator_info.html#a012b4c485bf3b0ea8921352c5ee0c357">VmaAllocatorInfo</a>
+</li>
+<li>deviceMemory
+: <a class="el" href="struct_vma_allocation_info.html#ae0bfb7dfdf79a76ffefc9a94677a2f67">VmaAllocationInfo</a>
+</li>
+<li>deviceMemoryBlocksFreed
+: <a class="el" href="struct_vma_defragmentation_stats.html#a0113f1877904a5d1ee8f409216ff276b">VmaDefragmentationStats</a>
+</li>
+</ul>
+
+
+<h3><a id="index_f"></a>- f -</h3><ul>
+<li>flags
+: <a class="el" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">VmaAllocationCreateInfo</a>
+, <a class="el" href="struct_vma_allocator_create_info.html#a392ea2ecbaff93f91a7c49f735ad4346">VmaAllocatorCreateInfo</a>
+, <a class="el" href="struct_vma_defragmentation_info2.html#a53e844ee5633e229cf6daf14b2d9fff9">VmaDefragmentationInfo2</a>
+, <a class="el" href="struct_vma_pool_create_info.html#a8405139f63d078340ae74513a59f5446">VmaPoolCreateInfo</a>
+, <a class="el" href="struct_vma_record_settings.html#ad8fdcc92119ae7a8c08c1a564c01d63a">VmaRecordSettings</a>
+</li>
+<li>frameInUseCount
+: <a class="el" href="struct_vma_allocator_create_info.html#a21ea188dd212b8171cb9ecbed4a2a3a7">VmaAllocatorCreateInfo</a>
+, <a class="el" href="struct_vma_pool_create_info.html#a9437e43ffbb644dbbf7fc4e50cfad6aa">VmaPoolCreateInfo</a>
+</li>
+</ul>
+
+
+<h3><a id="index_i"></a>- i -</h3><ul>
+<li>instance
+: <a class="el" href="struct_vma_allocator_create_info.html#a70dd42e29b1df1d1b9b61532ae0b370b">VmaAllocatorCreateInfo</a>
+, <a class="el" href="struct_vma_allocator_info.html#a2ed6a4d2d3fea039d66a13f15d0ce5fe">VmaAllocatorInfo</a>
+</li>
+</ul>
+
+
+<h3><a id="index_m"></a>- m -</h3><ul>
+<li>maxAllocationsToMove
+: <a class="el" href="struct_vma_defragmentation_info.html#aa7c7304e13c71f604c907196c4e28fbc">VmaDefragmentationInfo</a>
+</li>
+<li>maxBlockCount
+: <a class="el" href="struct_vma_pool_create_info.html#ae41142f2834fcdc82baa4883c187b75c">VmaPoolCreateInfo</a>
+</li>
+<li>maxBytesToMove
+: <a class="el" href="struct_vma_defragmentation_info.html#acb311c940a777270e67e1b81c5ab6a1d">VmaDefragmentationInfo</a>
+</li>
+<li>maxCpuAllocationsToMove
+: <a class="el" href="struct_vma_defragmentation_info2.html#a94c2c7223d52878445a8cccce396b671">VmaDefragmentationInfo2</a>
+</li>
+<li>maxCpuBytesToMove
+: <a class="el" href="struct_vma_defragmentation_info2.html#af78e1ea40c22d85137b65f6b384a4d0a">VmaDefragmentationInfo2</a>
+</li>
+<li>maxGpuAllocationsToMove
+: <a class="el" href="struct_vma_defragmentation_info2.html#a40d53d33e71ba0b66f844ed63c05a3f6">VmaDefragmentationInfo2</a>
+</li>
+<li>maxGpuBytesToMove
+: <a class="el" href="struct_vma_defragmentation_info2.html#a4ddbc898d0afe1518f863a3763628f08">VmaDefragmentationInfo2</a>
+</li>
+<li>memory
+: <a class="el" href="struct_vma_defragmentation_pass_move_info.html#a06eb0c8690aa0d3478a036753492e769">VmaDefragmentationPassMoveInfo</a>
+</li>
+<li>memoryHeap
+: <a class="el" href="struct_vma_stats.html#a0e6611508c29a187f0fd14ff1a0329c0">VmaStats</a>
+</li>
+<li>memoryType
+: <a class="el" href="struct_vma_allocation_info.html#a7f6b0aa58c135e488e6b40a388dad9d5">VmaAllocationInfo</a>
+, <a class="el" href="struct_vma_stats.html#a13e3caf754be79352c42408756309331">VmaStats</a>
+</li>
+<li>memoryTypeBits
+: <a class="el" href="struct_vma_allocation_create_info.html#a3bf940c0271d85d6ba32a4d820075055">VmaAllocationCreateInfo</a>
+</li>
+<li>memoryTypeIndex
+: <a class="el" href="struct_vma_pool_create_info.html#a596fa76b685d3f1f688f84a709a5b319">VmaPoolCreateInfo</a>
+</li>
+<li>minBlockCount
+: <a class="el" href="struct_vma_pool_create_info.html#ad8006fb803185c0a699d30f3e9a865ae">VmaPoolCreateInfo</a>
+</li>
+<li>moveCount
+: <a class="el" href="struct_vma_defragmentation_pass_info.html#ac1086e657ba995f8d1f4e49b83dcfb6c">VmaDefragmentationPassInfo</a>
+</li>
+</ul>
+
+
+<h3><a id="index_o"></a>- o -</h3><ul>
+<li>offset
+: <a class="el" href="struct_vma_allocation_info.html#a4a3c732388dbdc7a23f9365b00825268">VmaAllocationInfo</a>
+, <a class="el" href="struct_vma_defragmentation_pass_move_info.html#a8ab4508bc03625b0653c880576be96c6">VmaDefragmentationPassMoveInfo</a>
+</li>
+</ul>
+
+
+<h3><a id="index_p"></a>- p -</h3><ul>
+<li>pAllocationCallbacks
+: <a class="el" href="struct_vma_allocator_create_info.html#a6e409087e3be55400d0e4ccbe43c608d">VmaAllocatorCreateInfo</a>
+</li>
+<li>pAllocations
+: <a class="el" href="struct_vma_defragmentation_info2.html#a8943f8d65969ce8e2189a1cdf3205e96">VmaDefragmentationInfo2</a>
+</li>
+<li>pAllocationsChanged
+: <a class="el" href="struct_vma_defragmentation_info2.html#a76d51a644dc7f5405d0cdd0025ecd0cc">VmaDefragmentationInfo2</a>
+</li>
+<li>pDeviceMemoryCallbacks
+: <a class="el" href="struct_vma_allocator_create_info.html#af1380969b5e1ea4c3184a877892d260e">VmaAllocatorCreateInfo</a>
+</li>
+<li>pFilePath
+: <a class="el" href="struct_vma_record_settings.html#a6cb1fdbf6bcb610b68f2010dd629e89d">VmaRecordSettings</a>
+</li>
+<li>pfnAllocate
+: <a class="el" href="struct_vma_device_memory_callbacks.html#a4f17f7b255101e733b44d5633aceabfb">VmaDeviceMemoryCallbacks</a>
+</li>
+<li>pfnFree
+: <a class="el" href="struct_vma_device_memory_callbacks.html#abe8a3328bbc916f6f712fdb6b299444c">VmaDeviceMemoryCallbacks</a>
+</li>
+<li>pHeapSizeLimit
+: <a class="el" href="struct_vma_allocator_create_info.html#a31c192aa6cbffa33279f6d9f0c47c44b">VmaAllocatorCreateInfo</a>
+</li>
+<li>physicalDevice
+: <a class="el" href="struct_vma_allocator_create_info.html#a08230f04ae6ccf8a78150a9e829a7156">VmaAllocatorCreateInfo</a>
+, <a class="el" href="struct_vma_allocator_info.html#aba2b703f96e51d567717e1fb2935b47a">VmaAllocatorInfo</a>
+</li>
+<li>pMappedData
+: <a class="el" href="struct_vma_allocation_info.html#a5eeffbe2d2f30f53370ff14aefbadbe2">VmaAllocationInfo</a>
+</li>
+<li>pMoves
+: <a class="el" href="struct_vma_defragmentation_pass_info.html#acbd42d4a3357999da130a95cd99a3792">VmaDefragmentationPassInfo</a>
+</li>
+<li>pool
+: <a class="el" href="struct_vma_allocation_create_info.html#a6272c0555cfd1fe28bff1afeb6190150">VmaAllocationCreateInfo</a>
+</li>
+<li>poolCount
+: <a class="el" href="struct_vma_defragmentation_info2.html#a7e70aa2a1081d849dcc7829b19d3ec9d">VmaDefragmentationInfo2</a>
+</li>
+<li>pPools
+: <a class="el" href="struct_vma_defragmentation_info2.html#a0b3effd57f3fcdeb2ed62210b4ef20e1">VmaDefragmentationInfo2</a>
+</li>
+<li>pRecordSettings
+: <a class="el" href="struct_vma_allocator_create_info.html#ace2aa4877b16a42b0b7673d4e26000ee">VmaAllocatorCreateInfo</a>
+</li>
+<li>preferredFlags
+: <a class="el" href="struct_vma_allocation_create_info.html#a7fe8d81a1ad10b2a2faacacee5b15d6d">VmaAllocationCreateInfo</a>
+</li>
+<li>preferredLargeHeapBlockSize
+: <a class="el" href="struct_vma_allocator_create_info.html#a8e4714298e3121cdd8b214a1ae7a637a">VmaAllocatorCreateInfo</a>
+</li>
+<li>pUserData
+: <a class="el" href="struct_vma_allocation_create_info.html#a8259e85c272683434f4abb4ddddffe19">VmaAllocationCreateInfo</a>
+, <a class="el" href="struct_vma_allocation_info.html#adc507656149c04de7ed95d0042ba2a13">VmaAllocationInfo</a>
+, <a class="el" href="struct_vma_device_memory_callbacks.html#a24052de0937ddd54015a2df0363903c6">VmaDeviceMemoryCallbacks</a>
+</li>
+<li>pVulkanFunctions
+: <a class="el" href="struct_vma_allocator_create_info.html#a3dc197be3227da7338b1643f70db36bd">VmaAllocatorCreateInfo</a>
+</li>
+</ul>
+
+
+<h3><a id="index_r"></a>- r -</h3><ul>
+<li>requiredFlags
+: <a class="el" href="struct_vma_allocation_create_info.html#a9166390303ff42d783305bc31c2b6b90">VmaAllocationCreateInfo</a>
+</li>
+</ul>
+
+
+<h3><a id="index_s"></a>- s -</h3><ul>
+<li>size
+: <a class="el" href="struct_vma_allocation_info.html#aac76d113a6a5ccbb09fea00fb25fd18f">VmaAllocationInfo</a>
+, <a class="el" href="struct_vma_pool_stats.html#a326807b2de2b0931cee4ed9a5f2e420c">VmaPoolStats</a>
+</li>
+</ul>
+
+
+<h3><a id="index_t"></a>- t -</h3><ul>
+<li>total
+: <a class="el" href="struct_vma_stats.html#a2e8f5b3353f2fefef3c27f29e245a1f9">VmaStats</a>
+</li>
+</ul>
+
+
+<h3><a id="index_u"></a>- u -</h3><ul>
+<li>unusedBytes
+: <a class="el" href="struct_vma_stat_info.html#a1859d290aca2cd582d8dc25922092669">VmaStatInfo</a>
+</li>
+<li>unusedRangeCount
+: <a class="el" href="struct_vma_pool_stats.html#ae4f3546ffa4d1e598b64d8e6134854f4">VmaPoolStats</a>
+, <a class="el" href="struct_vma_stat_info.html#ae06129c771bfebfd6468a7f4276502a9">VmaStatInfo</a>
+</li>
+<li>unusedRangeSizeAvg
+: <a class="el" href="struct_vma_stat_info.html#a2f9b3452af90c9768a30b7fb6ae194fc">VmaStatInfo</a>
+</li>
+<li>unusedRangeSizeMax
+: <a class="el" href="struct_vma_pool_stats.html#ab4c8f52dd42ab01998f60f0b6acc722b">VmaPoolStats</a>
+, <a class="el" href="struct_vma_stat_info.html#a5ba1a2476c4d39b10f7e2f7ebbb72ac4">VmaStatInfo</a>
+</li>
+<li>unusedRangeSizeMin
+: <a class="el" href="struct_vma_stat_info.html#aedeba931324f16589cd2416c0d2dd0d4">VmaStatInfo</a>
+</li>
+<li>unusedSize
+: <a class="el" href="struct_vma_pool_stats.html#ad7c54874724fce7b06aba526202d82a8">VmaPoolStats</a>
+</li>
+<li>usage
+: <a class="el" href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910">VmaAllocationCreateInfo</a>
+, <a class="el" href="struct_vma_budget.html#a84dd1ecca8b0110259eb206dbadb11f6">VmaBudget</a>
+</li>
+<li>usedBytes
+: <a class="el" href="struct_vma_stat_info.html#ab0c6c73837e5a70c749fbd4f6064895a">VmaStatInfo</a>
+</li>
+</ul>
+
+
+<h3><a id="index_v"></a>- v -</h3><ul>
+<li>vkAllocateMemory
+: <a class="el" href="struct_vma_vulkan_functions.html#a2943bf99dfd784a0e8f599d987e22e6c">VmaVulkanFunctions</a>
+</li>
+<li>vkBindBufferMemory
+: <a class="el" href="struct_vma_vulkan_functions.html#a94fc4f3a605d9880bb3c0ba2c2fc80b2">VmaVulkanFunctions</a>
+</li>
+<li>vkBindImageMemory
+: <a class="el" href="struct_vma_vulkan_functions.html#a1338d96a128a5ade648b8d934907c637">VmaVulkanFunctions</a>
+</li>
+<li>vkCmdCopyBuffer
+: <a class="el" href="struct_vma_vulkan_functions.html#ae5c0db8c89a3b82593dc16aa6a49fa3a">VmaVulkanFunctions</a>
+</li>
+<li>vkCreateBuffer
+: <a class="el" href="struct_vma_vulkan_functions.html#ae8084315a25006271a2edfc3a447519f">VmaVulkanFunctions</a>
+</li>
+<li>vkCreateImage
+: <a class="el" href="struct_vma_vulkan_functions.html#a23ebe70be515b9b5010a1d691200e325">VmaVulkanFunctions</a>
+</li>
+<li>vkDestroyBuffer
+: <a class="el" href="struct_vma_vulkan_functions.html#a7e054606faddb07f0e8556f3ed317d45">VmaVulkanFunctions</a>
+</li>
+<li>vkDestroyImage
+: <a class="el" href="struct_vma_vulkan_functions.html#a90b898227039b1dcb3520f6e91f09ffa">VmaVulkanFunctions</a>
+</li>
+<li>vkFlushMappedMemoryRanges
+: <a class="el" href="struct_vma_vulkan_functions.html#a33c322f4c4ad2810f8a9c97a277572f9">VmaVulkanFunctions</a>
+</li>
+<li>vkFreeMemory
+: <a class="el" href="struct_vma_vulkan_functions.html#a4c658701778564d62034255b5dda91b4">VmaVulkanFunctions</a>
+</li>
+<li>vkGetBufferMemoryRequirements
+: <a class="el" href="struct_vma_vulkan_functions.html#a5b92901df89a4194b0d12f6071d4d143">VmaVulkanFunctions</a>
+</li>
+<li>vkGetImageMemoryRequirements
+: <a class="el" href="struct_vma_vulkan_functions.html#a475f6f49f8debe4d10800592606d53f4">VmaVulkanFunctions</a>
+</li>
+<li>vkGetPhysicalDeviceMemoryProperties
+: <a class="el" href="struct_vma_vulkan_functions.html#a60d25c33bba06bb8592e6875cbaa9830">VmaVulkanFunctions</a>
+</li>
+<li>vkGetPhysicalDeviceProperties
+: <a class="el" href="struct_vma_vulkan_functions.html#a77b7a74082823e865dd6546623468f96">VmaVulkanFunctions</a>
+</li>
+<li>vkInvalidateMappedMemoryRanges
+: <a class="el" href="struct_vma_vulkan_functions.html#a5c1093bc32386a8060c37c9f282078a1">VmaVulkanFunctions</a>
+</li>
+<li>vkMapMemory
+: <a class="el" href="struct_vma_vulkan_functions.html#ab5c1f38dea3a2cf00dc9eb4f57218c49">VmaVulkanFunctions</a>
+</li>
+<li>vkUnmapMemory
+: <a class="el" href="struct_vma_vulkan_functions.html#acc798589736f0becb317fc2196c1d8b9">VmaVulkanFunctions</a>
+</li>
+<li>vulkanApiVersion
+: <a class="el" href="struct_vma_allocator_create_info.html#ae0ffc55139b54520a6bb704b29ffc285">VmaAllocatorCreateInfo</a>
+</li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/functions_vars.html b/third_party/VulkanMemoryAllocator/docs/html/functions_vars.html
new file mode 100644
index 0000000..55805cf
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/functions_vars.html
@@ -0,0 +1,396 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: Class Members - Variables</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="contents">
+&#160;
+
+<h3><a id="index_a"></a>- a -</h3><ul>
+<li>allocation
+: <a class="el" href="struct_vma_defragmentation_pass_move_info.html#ae885c861c2dd8d622e6c19e281d035cc">VmaDefragmentationPassMoveInfo</a>
+</li>
+<li>allocationBytes
+: <a class="el" href="struct_vma_budget.html#a7e2a6583ebd63e194951c542563804d8">VmaBudget</a>
+</li>
+<li>allocationCount
+: <a class="el" href="struct_vma_defragmentation_info2.html#a3cf86ab32c1da779b4923d301a3056ba">VmaDefragmentationInfo2</a>
+, <a class="el" href="struct_vma_pool_stats.html#ad1924eb54fffa45e9e0e65670c8fe5eb">VmaPoolStats</a>
+, <a class="el" href="struct_vma_stat_info.html#a537741e4d5cdddc1c0ab95ec650afaff">VmaStatInfo</a>
+</li>
+<li>allocationSizeAvg
+: <a class="el" href="struct_vma_stat_info.html#a1081a039964e566c672e7a2347f9e599">VmaStatInfo</a>
+</li>
+<li>allocationSizeMax
+: <a class="el" href="struct_vma_stat_info.html#a17e9733a5ecd76287d4db6e66f71f50c">VmaStatInfo</a>
+</li>
+<li>allocationSizeMin
+: <a class="el" href="struct_vma_stat_info.html#ade8b40bd3139c04aabd2fc538a356fea">VmaStatInfo</a>
+</li>
+<li>allocationsMoved
+: <a class="el" href="struct_vma_defragmentation_stats.html#aefeabf130022008eadd75999478af3f9">VmaDefragmentationStats</a>
+</li>
+</ul>
+
+
+<h3><a id="index_b"></a>- b -</h3><ul>
+<li>blockBytes
+: <a class="el" href="struct_vma_budget.html#a58b492901baab685f466199124e514a0">VmaBudget</a>
+</li>
+<li>blockCount
+: <a class="el" href="struct_vma_pool_stats.html#aa0b5cb45cef6f18571cefb03b9a230e7">VmaPoolStats</a>
+, <a class="el" href="struct_vma_stat_info.html#abc4bb7cd611900778464c56e50c970a4">VmaStatInfo</a>
+</li>
+<li>blockSize
+: <a class="el" href="struct_vma_pool_create_info.html#aa4265160536cdb9be821b7686c16c676">VmaPoolCreateInfo</a>
+</li>
+<li>budget
+: <a class="el" href="struct_vma_budget.html#ab82e1d1754c2d210d0bdf90220bc6cdd">VmaBudget</a>
+</li>
+<li>bytesFreed
+: <a class="el" href="struct_vma_defragmentation_stats.html#ab0cb9ac0dbc106c77e384ea676422f28">VmaDefragmentationStats</a>
+</li>
+<li>bytesMoved
+: <a class="el" href="struct_vma_defragmentation_stats.html#a36f9d5df2a10ba2a36b16e126d60572d">VmaDefragmentationStats</a>
+</li>
+</ul>
+
+
+<h3><a id="index_c"></a>- c -</h3><ul>
+<li>commandBuffer
+: <a class="el" href="struct_vma_defragmentation_info2.html#a7f71f39590c5316771493d2333f9c1bd">VmaDefragmentationInfo2</a>
+</li>
+</ul>
+
+
+<h3><a id="index_d"></a>- d -</h3><ul>
+<li>device
+: <a class="el" href="struct_vma_allocator_create_info.html#ad924ddd77b04039c88d0c09b0ffcd500">VmaAllocatorCreateInfo</a>
+, <a class="el" href="struct_vma_allocator_info.html#a012b4c485bf3b0ea8921352c5ee0c357">VmaAllocatorInfo</a>
+</li>
+<li>deviceMemory
+: <a class="el" href="struct_vma_allocation_info.html#ae0bfb7dfdf79a76ffefc9a94677a2f67">VmaAllocationInfo</a>
+</li>
+<li>deviceMemoryBlocksFreed
+: <a class="el" href="struct_vma_defragmentation_stats.html#a0113f1877904a5d1ee8f409216ff276b">VmaDefragmentationStats</a>
+</li>
+</ul>
+
+
+<h3><a id="index_f"></a>- f -</h3><ul>
+<li>flags
+: <a class="el" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">VmaAllocationCreateInfo</a>
+, <a class="el" href="struct_vma_allocator_create_info.html#a392ea2ecbaff93f91a7c49f735ad4346">VmaAllocatorCreateInfo</a>
+, <a class="el" href="struct_vma_defragmentation_info2.html#a53e844ee5633e229cf6daf14b2d9fff9">VmaDefragmentationInfo2</a>
+, <a class="el" href="struct_vma_pool_create_info.html#a8405139f63d078340ae74513a59f5446">VmaPoolCreateInfo</a>
+, <a class="el" href="struct_vma_record_settings.html#ad8fdcc92119ae7a8c08c1a564c01d63a">VmaRecordSettings</a>
+</li>
+<li>frameInUseCount
+: <a class="el" href="struct_vma_allocator_create_info.html#a21ea188dd212b8171cb9ecbed4a2a3a7">VmaAllocatorCreateInfo</a>
+, <a class="el" href="struct_vma_pool_create_info.html#a9437e43ffbb644dbbf7fc4e50cfad6aa">VmaPoolCreateInfo</a>
+</li>
+</ul>
+
+
+<h3><a id="index_i"></a>- i -</h3><ul>
+<li>instance
+: <a class="el" href="struct_vma_allocator_create_info.html#a70dd42e29b1df1d1b9b61532ae0b370b">VmaAllocatorCreateInfo</a>
+, <a class="el" href="struct_vma_allocator_info.html#a2ed6a4d2d3fea039d66a13f15d0ce5fe">VmaAllocatorInfo</a>
+</li>
+</ul>
+
+
+<h3><a id="index_m"></a>- m -</h3><ul>
+<li>maxAllocationsToMove
+: <a class="el" href="struct_vma_defragmentation_info.html#aa7c7304e13c71f604c907196c4e28fbc">VmaDefragmentationInfo</a>
+</li>
+<li>maxBlockCount
+: <a class="el" href="struct_vma_pool_create_info.html#ae41142f2834fcdc82baa4883c187b75c">VmaPoolCreateInfo</a>
+</li>
+<li>maxBytesToMove
+: <a class="el" href="struct_vma_defragmentation_info.html#acb311c940a777270e67e1b81c5ab6a1d">VmaDefragmentationInfo</a>
+</li>
+<li>maxCpuAllocationsToMove
+: <a class="el" href="struct_vma_defragmentation_info2.html#a94c2c7223d52878445a8cccce396b671">VmaDefragmentationInfo2</a>
+</li>
+<li>maxCpuBytesToMove
+: <a class="el" href="struct_vma_defragmentation_info2.html#af78e1ea40c22d85137b65f6b384a4d0a">VmaDefragmentationInfo2</a>
+</li>
+<li>maxGpuAllocationsToMove
+: <a class="el" href="struct_vma_defragmentation_info2.html#a40d53d33e71ba0b66f844ed63c05a3f6">VmaDefragmentationInfo2</a>
+</li>
+<li>maxGpuBytesToMove
+: <a class="el" href="struct_vma_defragmentation_info2.html#a4ddbc898d0afe1518f863a3763628f08">VmaDefragmentationInfo2</a>
+</li>
+<li>memory
+: <a class="el" href="struct_vma_defragmentation_pass_move_info.html#a06eb0c8690aa0d3478a036753492e769">VmaDefragmentationPassMoveInfo</a>
+</li>
+<li>memoryHeap
+: <a class="el" href="struct_vma_stats.html#a0e6611508c29a187f0fd14ff1a0329c0">VmaStats</a>
+</li>
+<li>memoryType
+: <a class="el" href="struct_vma_allocation_info.html#a7f6b0aa58c135e488e6b40a388dad9d5">VmaAllocationInfo</a>
+, <a class="el" href="struct_vma_stats.html#a13e3caf754be79352c42408756309331">VmaStats</a>
+</li>
+<li>memoryTypeBits
+: <a class="el" href="struct_vma_allocation_create_info.html#a3bf940c0271d85d6ba32a4d820075055">VmaAllocationCreateInfo</a>
+</li>
+<li>memoryTypeIndex
+: <a class="el" href="struct_vma_pool_create_info.html#a596fa76b685d3f1f688f84a709a5b319">VmaPoolCreateInfo</a>
+</li>
+<li>minBlockCount
+: <a class="el" href="struct_vma_pool_create_info.html#ad8006fb803185c0a699d30f3e9a865ae">VmaPoolCreateInfo</a>
+</li>
+<li>moveCount
+: <a class="el" href="struct_vma_defragmentation_pass_info.html#ac1086e657ba995f8d1f4e49b83dcfb6c">VmaDefragmentationPassInfo</a>
+</li>
+</ul>
+
+
+<h3><a id="index_o"></a>- o -</h3><ul>
+<li>offset
+: <a class="el" href="struct_vma_allocation_info.html#a4a3c732388dbdc7a23f9365b00825268">VmaAllocationInfo</a>
+, <a class="el" href="struct_vma_defragmentation_pass_move_info.html#a8ab4508bc03625b0653c880576be96c6">VmaDefragmentationPassMoveInfo</a>
+</li>
+</ul>
+
+
+<h3><a id="index_p"></a>- p -</h3><ul>
+<li>pAllocationCallbacks
+: <a class="el" href="struct_vma_allocator_create_info.html#a6e409087e3be55400d0e4ccbe43c608d">VmaAllocatorCreateInfo</a>
+</li>
+<li>pAllocations
+: <a class="el" href="struct_vma_defragmentation_info2.html#a8943f8d65969ce8e2189a1cdf3205e96">VmaDefragmentationInfo2</a>
+</li>
+<li>pAllocationsChanged
+: <a class="el" href="struct_vma_defragmentation_info2.html#a76d51a644dc7f5405d0cdd0025ecd0cc">VmaDefragmentationInfo2</a>
+</li>
+<li>pDeviceMemoryCallbacks
+: <a class="el" href="struct_vma_allocator_create_info.html#af1380969b5e1ea4c3184a877892d260e">VmaAllocatorCreateInfo</a>
+</li>
+<li>pFilePath
+: <a class="el" href="struct_vma_record_settings.html#a6cb1fdbf6bcb610b68f2010dd629e89d">VmaRecordSettings</a>
+</li>
+<li>pfnAllocate
+: <a class="el" href="struct_vma_device_memory_callbacks.html#a4f17f7b255101e733b44d5633aceabfb">VmaDeviceMemoryCallbacks</a>
+</li>
+<li>pfnFree
+: <a class="el" href="struct_vma_device_memory_callbacks.html#abe8a3328bbc916f6f712fdb6b299444c">VmaDeviceMemoryCallbacks</a>
+</li>
+<li>pHeapSizeLimit
+: <a class="el" href="struct_vma_allocator_create_info.html#a31c192aa6cbffa33279f6d9f0c47c44b">VmaAllocatorCreateInfo</a>
+</li>
+<li>physicalDevice
+: <a class="el" href="struct_vma_allocator_create_info.html#a08230f04ae6ccf8a78150a9e829a7156">VmaAllocatorCreateInfo</a>
+, <a class="el" href="struct_vma_allocator_info.html#aba2b703f96e51d567717e1fb2935b47a">VmaAllocatorInfo</a>
+</li>
+<li>pMappedData
+: <a class="el" href="struct_vma_allocation_info.html#a5eeffbe2d2f30f53370ff14aefbadbe2">VmaAllocationInfo</a>
+</li>
+<li>pMoves
+: <a class="el" href="struct_vma_defragmentation_pass_info.html#acbd42d4a3357999da130a95cd99a3792">VmaDefragmentationPassInfo</a>
+</li>
+<li>pool
+: <a class="el" href="struct_vma_allocation_create_info.html#a6272c0555cfd1fe28bff1afeb6190150">VmaAllocationCreateInfo</a>
+</li>
+<li>poolCount
+: <a class="el" href="struct_vma_defragmentation_info2.html#a7e70aa2a1081d849dcc7829b19d3ec9d">VmaDefragmentationInfo2</a>
+</li>
+<li>pPools
+: <a class="el" href="struct_vma_defragmentation_info2.html#a0b3effd57f3fcdeb2ed62210b4ef20e1">VmaDefragmentationInfo2</a>
+</li>
+<li>pRecordSettings
+: <a class="el" href="struct_vma_allocator_create_info.html#ace2aa4877b16a42b0b7673d4e26000ee">VmaAllocatorCreateInfo</a>
+</li>
+<li>preferredFlags
+: <a class="el" href="struct_vma_allocation_create_info.html#a7fe8d81a1ad10b2a2faacacee5b15d6d">VmaAllocationCreateInfo</a>
+</li>
+<li>preferredLargeHeapBlockSize
+: <a class="el" href="struct_vma_allocator_create_info.html#a8e4714298e3121cdd8b214a1ae7a637a">VmaAllocatorCreateInfo</a>
+</li>
+<li>pUserData
+: <a class="el" href="struct_vma_allocation_create_info.html#a8259e85c272683434f4abb4ddddffe19">VmaAllocationCreateInfo</a>
+, <a class="el" href="struct_vma_allocation_info.html#adc507656149c04de7ed95d0042ba2a13">VmaAllocationInfo</a>
+, <a class="el" href="struct_vma_device_memory_callbacks.html#a24052de0937ddd54015a2df0363903c6">VmaDeviceMemoryCallbacks</a>
+</li>
+<li>pVulkanFunctions
+: <a class="el" href="struct_vma_allocator_create_info.html#a3dc197be3227da7338b1643f70db36bd">VmaAllocatorCreateInfo</a>
+</li>
+</ul>
+
+
+<h3><a id="index_r"></a>- r -</h3><ul>
+<li>requiredFlags
+: <a class="el" href="struct_vma_allocation_create_info.html#a9166390303ff42d783305bc31c2b6b90">VmaAllocationCreateInfo</a>
+</li>
+</ul>
+
+
+<h3><a id="index_s"></a>- s -</h3><ul>
+<li>size
+: <a class="el" href="struct_vma_allocation_info.html#aac76d113a6a5ccbb09fea00fb25fd18f">VmaAllocationInfo</a>
+, <a class="el" href="struct_vma_pool_stats.html#a326807b2de2b0931cee4ed9a5f2e420c">VmaPoolStats</a>
+</li>
+</ul>
+
+
+<h3><a id="index_t"></a>- t -</h3><ul>
+<li>total
+: <a class="el" href="struct_vma_stats.html#a2e8f5b3353f2fefef3c27f29e245a1f9">VmaStats</a>
+</li>
+</ul>
+
+
+<h3><a id="index_u"></a>- u -</h3><ul>
+<li>unusedBytes
+: <a class="el" href="struct_vma_stat_info.html#a1859d290aca2cd582d8dc25922092669">VmaStatInfo</a>
+</li>
+<li>unusedRangeCount
+: <a class="el" href="struct_vma_pool_stats.html#ae4f3546ffa4d1e598b64d8e6134854f4">VmaPoolStats</a>
+, <a class="el" href="struct_vma_stat_info.html#ae06129c771bfebfd6468a7f4276502a9">VmaStatInfo</a>
+</li>
+<li>unusedRangeSizeAvg
+: <a class="el" href="struct_vma_stat_info.html#a2f9b3452af90c9768a30b7fb6ae194fc">VmaStatInfo</a>
+</li>
+<li>unusedRangeSizeMax
+: <a class="el" href="struct_vma_pool_stats.html#ab4c8f52dd42ab01998f60f0b6acc722b">VmaPoolStats</a>
+, <a class="el" href="struct_vma_stat_info.html#a5ba1a2476c4d39b10f7e2f7ebbb72ac4">VmaStatInfo</a>
+</li>
+<li>unusedRangeSizeMin
+: <a class="el" href="struct_vma_stat_info.html#aedeba931324f16589cd2416c0d2dd0d4">VmaStatInfo</a>
+</li>
+<li>unusedSize
+: <a class="el" href="struct_vma_pool_stats.html#ad7c54874724fce7b06aba526202d82a8">VmaPoolStats</a>
+</li>
+<li>usage
+: <a class="el" href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910">VmaAllocationCreateInfo</a>
+, <a class="el" href="struct_vma_budget.html#a84dd1ecca8b0110259eb206dbadb11f6">VmaBudget</a>
+</li>
+<li>usedBytes
+: <a class="el" href="struct_vma_stat_info.html#ab0c6c73837e5a70c749fbd4f6064895a">VmaStatInfo</a>
+</li>
+</ul>
+
+
+<h3><a id="index_v"></a>- v -</h3><ul>
+<li>vkAllocateMemory
+: <a class="el" href="struct_vma_vulkan_functions.html#a2943bf99dfd784a0e8f599d987e22e6c">VmaVulkanFunctions</a>
+</li>
+<li>vkBindBufferMemory
+: <a class="el" href="struct_vma_vulkan_functions.html#a94fc4f3a605d9880bb3c0ba2c2fc80b2">VmaVulkanFunctions</a>
+</li>
+<li>vkBindImageMemory
+: <a class="el" href="struct_vma_vulkan_functions.html#a1338d96a128a5ade648b8d934907c637">VmaVulkanFunctions</a>
+</li>
+<li>vkCmdCopyBuffer
+: <a class="el" href="struct_vma_vulkan_functions.html#ae5c0db8c89a3b82593dc16aa6a49fa3a">VmaVulkanFunctions</a>
+</li>
+<li>vkCreateBuffer
+: <a class="el" href="struct_vma_vulkan_functions.html#ae8084315a25006271a2edfc3a447519f">VmaVulkanFunctions</a>
+</li>
+<li>vkCreateImage
+: <a class="el" href="struct_vma_vulkan_functions.html#a23ebe70be515b9b5010a1d691200e325">VmaVulkanFunctions</a>
+</li>
+<li>vkDestroyBuffer
+: <a class="el" href="struct_vma_vulkan_functions.html#a7e054606faddb07f0e8556f3ed317d45">VmaVulkanFunctions</a>
+</li>
+<li>vkDestroyImage
+: <a class="el" href="struct_vma_vulkan_functions.html#a90b898227039b1dcb3520f6e91f09ffa">VmaVulkanFunctions</a>
+</li>
+<li>vkFlushMappedMemoryRanges
+: <a class="el" href="struct_vma_vulkan_functions.html#a33c322f4c4ad2810f8a9c97a277572f9">VmaVulkanFunctions</a>
+</li>
+<li>vkFreeMemory
+: <a class="el" href="struct_vma_vulkan_functions.html#a4c658701778564d62034255b5dda91b4">VmaVulkanFunctions</a>
+</li>
+<li>vkGetBufferMemoryRequirements
+: <a class="el" href="struct_vma_vulkan_functions.html#a5b92901df89a4194b0d12f6071d4d143">VmaVulkanFunctions</a>
+</li>
+<li>vkGetImageMemoryRequirements
+: <a class="el" href="struct_vma_vulkan_functions.html#a475f6f49f8debe4d10800592606d53f4">VmaVulkanFunctions</a>
+</li>
+<li>vkGetPhysicalDeviceMemoryProperties
+: <a class="el" href="struct_vma_vulkan_functions.html#a60d25c33bba06bb8592e6875cbaa9830">VmaVulkanFunctions</a>
+</li>
+<li>vkGetPhysicalDeviceProperties
+: <a class="el" href="struct_vma_vulkan_functions.html#a77b7a74082823e865dd6546623468f96">VmaVulkanFunctions</a>
+</li>
+<li>vkInvalidateMappedMemoryRanges
+: <a class="el" href="struct_vma_vulkan_functions.html#a5c1093bc32386a8060c37c9f282078a1">VmaVulkanFunctions</a>
+</li>
+<li>vkMapMemory
+: <a class="el" href="struct_vma_vulkan_functions.html#ab5c1f38dea3a2cf00dc9eb4f57218c49">VmaVulkanFunctions</a>
+</li>
+<li>vkUnmapMemory
+: <a class="el" href="struct_vma_vulkan_functions.html#acc798589736f0becb317fc2196c1d8b9">VmaVulkanFunctions</a>
+</li>
+<li>vulkanApiVersion
+: <a class="el" href="struct_vma_allocator_create_info.html#ae0ffc55139b54520a6bb704b29ffc285">VmaAllocatorCreateInfo</a>
+</li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/general_considerations.html b/third_party/VulkanMemoryAllocator/docs/html/general_considerations.html
new file mode 100644
index 0000000..d9a65b2
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/general_considerations.html
@@ -0,0 +1,130 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: General considerations</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+  <ul>
+<li class="navelem"><a class="el" href="index.html">Vulkan Memory Allocator</a></li>  </ul>
+</div>
+</div><!-- top -->
+<div class="PageDoc"><div class="header">
+  <div class="headertitle">
+<div class="title">General considerations </div>  </div>
+</div><!--header-->
+<div class="contents">
+<div class="textblock"><h1><a class="anchor" id="general_considerations_thread_safety"></a>
+Thread safety</h1>
+<ul>
+<li>The library has no global state, so separate <a class="el" href="struct_vma_allocator.html" title="Represents main object of this library initialized.">VmaAllocator</a> objects can be used independently. There should be no need to create multiple such objects though - one per <code>VkDevice</code> is enough.</li>
+<li>By default, all calls to functions that take <a class="el" href="struct_vma_allocator.html" title="Represents main object of this library initialized.">VmaAllocator</a> as first parameter are safe to call from multiple threads simultaneously because they are synchronized internally when needed.</li>
+<li>When the allocator is created with <a class="el" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca4816ddaed324ba110172ca608a20f29d" title="Allocator and all objects created from it will not be synchronized internally, so you must guarantee ...">VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT</a> flag, calls to functions that take such <a class="el" href="struct_vma_allocator.html" title="Represents main object of this library initialized.">VmaAllocator</a> object must be synchronized externally.</li>
+<li>Access to a <a class="el" href="struct_vma_allocation.html" title="Represents single memory allocation.">VmaAllocation</a> object must be externally synchronized. For example, you must not call <a class="el" href="vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b" title="Returns current information about specified allocation and atomically marks it as used in current fra...">vmaGetAllocationInfo()</a> and <a class="el" href="vk__mem__alloc_8h.html#ad5bd1243512d099706de88168992f069" title="Maps memory represented by given allocation and returns pointer to it.">vmaMapMemory()</a> from different threads at the same time if you pass the same <a class="el" href="struct_vma_allocation.html" title="Represents single memory allocation.">VmaAllocation</a> object to these functions.</li>
+</ul>
+<h1><a class="anchor" id="general_considerations_validation_layer_warnings"></a>
+Validation layer warnings</h1>
+<p>When using this library, you can meet following types of warnings issued by Vulkan validation layer. They don't necessarily indicate a bug, so you may need to just ignore them.</p>
+<ul>
+<li><em>vkBindBufferMemory(): Binding memory to buffer 0xeb8e4 but vkGetBufferMemoryRequirements() has not been called on that buffer.</em><ul>
+<li>It happens when VK_KHR_dedicated_allocation extension is enabled. <code>vkGetBufferMemoryRequirements2KHR</code> function is used instead, while validation layer seems to be unaware of it.</li>
+</ul>
+</li>
+<li><em>Mapping an image with layout VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL can result in undefined behavior if this memory is used by the device. Only GENERAL or PREINITIALIZED should be used.</em><ul>
+<li>It happens when you map a buffer or image, because the library maps entire <code>VkDeviceMemory</code> block, where different types of images and buffers may end up together, especially on GPUs with unified memory like Intel.</li>
+</ul>
+</li>
+<li><em>Non-linear image 0xebc91 is aliased with linear buffer 0xeb8e4 which may indicate a bug.</em><ul>
+<li>It happens when you use lost allocations, and a new image or buffer is created in place of an existing object that bacame lost.</li>
+<li>It may happen also when you use <a class="el" href="defragmentation.html">defragmentation</a>.</li>
+</ul>
+</li>
+</ul>
+<h1><a class="anchor" id="general_considerations_allocation_algorithm"></a>
+Allocation algorithm</h1>
+<p>The library uses following algorithm for allocation, in order:</p>
+<ol type="1">
+<li>Try to find free range of memory in existing blocks.</li>
+<li>If failed, try to create a new block of <code>VkDeviceMemory</code>, with preferred block size.</li>
+<li>If failed, try to create such block with size/2, size/4, size/8.</li>
+<li>If failed and <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a68686d0ce9beb0d4d1b9f2b8b1389a7e">VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT</a> flag was specified, try to find space in existing blocks, possilby making some other allocations lost.</li>
+<li>If failed, try to allocate separate <code>VkDeviceMemory</code> for this allocation, just like when you use <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a3fc311d855c2ff53f1090ef5c722b38f" title="Set this flag if the allocation should have its own memory block.">VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT</a>.</li>
+<li>If failed, choose other memory type that meets the requirements specified in <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> and go to point 1.</li>
+<li>If failed, return <code>VK_ERROR_OUT_OF_DEVICE_MEMORY</code>.</li>
+</ol>
+<h1><a class="anchor" id="general_considerations_features_not_supported"></a>
+Features not supported</h1>
+<p>Features deliberately excluded from the scope of this library:</p>
+<ul>
+<li>Data transfer. Uploading (straming) and downloading data of buffers and images between CPU and GPU memory and related synchronization is responsibility of the user. Defining some "texture" object that would automatically stream its data from a staging copy in CPU memory to GPU memory would rather be a feature of another, higher-level library implemented on top of VMA.</li>
+<li>Allocations for imported/exported external memory. They tend to require explicit memory type index and dedicated allocation anyway, so they don't interact with main features of this library. Such special purpose allocations should be made manually, using <code>vkCreateBuffer()</code> and <code>vkAllocateMemory()</code>.</li>
+<li>Recreation of buffers and images. Although the library has functions for buffer and image creation (<a class="el" href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer()</a>, <a class="el" href="vk__mem__alloc_8h.html#a02a94f25679275851a53e82eacbcfc73" title="Function similar to vmaCreateBuffer().">vmaCreateImage()</a>), you need to recreate these objects yourself after defragmentation. That's because the big structures <code>VkBufferCreateInfo</code>, <code>VkImageCreateInfo</code> are not stored in <a class="el" href="struct_vma_allocation.html" title="Represents single memory allocation.">VmaAllocation</a> object.</li>
+<li>Handling CPU memory allocation failures. When dynamically creating small C++ objects in CPU memory (not Vulkan memory), allocation failures are not checked and handled gracefully, because that would complicate code significantly and is usually not needed in desktop PC applications anyway.</li>
+<li>Code free of any compiler warnings. Maintaining the library to compile and work correctly on so many different platforms is hard enough. Being free of any warnings, on any version of any compiler, is simply not feasible.</li>
+<li>This is a C++ library with C interface. Bindings or ports to any other programming languages are welcomed as external projects and are not going to be included into this repository. </li>
+</ul>
+</div></div><!-- contents -->
+</div><!-- PageDoc -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/globals.html b/third_party/VulkanMemoryAllocator/docs/html/globals.html
new file mode 100644
index 0000000..c83a887
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/globals.html
@@ -0,0 +1,471 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: File Members</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="contents">
+<div class="textblock">Here is a list of all file members with links to the files they belong to:</div>
+
+<h3><a id="index_n"></a>- n -</h3><ul>
+<li>NOMINMAX
+: <a class="el" href="vk__mem__alloc_8h.html#a9f918755b601cf4bffca775992e6fb90">vk_mem_alloc.h</a>
+</li>
+</ul>
+
+
+<h3><a id="index_p"></a>- p -</h3><ul>
+<li>PFN_vmaAllocateDeviceMemoryFunction
+: <a class="el" href="vk__mem__alloc_8h.html#a7e1ed85f7799600b03ad51a77acc21f3">vk_mem_alloc.h</a>
+</li>
+<li>PFN_vmaFreeDeviceMemoryFunction
+: <a class="el" href="vk__mem__alloc_8h.html#a154ccaaf53dc2c36378f80f0c4f3679b">vk_mem_alloc.h</a>
+</li>
+</ul>
+
+
+<h3><a id="index_v"></a>- v -</h3><ul>
+<li>VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a5f436af6c8fe8540573a6d22627a6fd2">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a68686d0ce9beb0d4d1b9f2b8b1389a7e">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a3fc311d855c2ff53f1090ef5c722b38f">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATION_CREATE_DONT_BIND_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a2310568c62208af432724305fe29ccea">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATION_CREATE_FLAG_BITS_MAX_ENUM
+: <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597ae5633ec569f4899cf8f29e7385b2f882">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATION_CREATE_MAPPED_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a11da372cc3a82931c5e5d6146cd9dd1f">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a89759603401014eb325eb22a3839f2ff">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a839826775c62319466441f86496f036d">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a33eb2052674f3ad92386c714a65fb777">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATION_CREATE_STRATEGY_MASK
+: <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a8e16845d81ae3d27c47106d4770d5c7e">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATION_CREATE_STRATEGY_MIN_FRAGMENTATION_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a621b704103eb3360230c860acf36e706">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a8af1210cf591784afa026d94998f735d">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a0729e932b7ea170e3a128cad96c5cf6d">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597ad242a04f802e25fef0b880afe8bb0a62">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a42ba3a2d2c7117953210b7c3ef8da0df">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597aa6f24f821cd6a7c5e4a443f7bf59c520">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597ab8b1764f3e9022368e440c057783b92d">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca2acce4886d8078552efa38878413970f">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca5f1b28b0414319d1687e1f2b30ab0089">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca4d4687863f7bd4b418c6006dc04400b0">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca4816ddaed324ba110172ca608a20f29d">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATOR_CREATE_FLAG_BITS_MAX_ENUM
+: <a class="el" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7cae4d5ad929caba5f23eb502b13bd5286c">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca8fb75bf07cd184ab903596295e863dee">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7cace7da7cc6e71a625dfa763c55a597878">vk_mem_alloc.h</a>
+</li>
+<li>VMA_BIND_MEMORY2
+: <a class="el" href="vk__mem__alloc_8h.html#a88bef97f86d70a34a4c0746e09a2680d">vk_mem_alloc.h</a>
+</li>
+<li>VMA_BUFFER_DEVICE_ADDRESS
+: <a class="el" href="vk__mem__alloc_8h.html#a7f9d5e71b70dd1a137c303a8a8262c10">vk_mem_alloc.h</a>
+</li>
+<li>VMA_DEDICATED_ALLOCATION
+: <a class="el" href="vk__mem__alloc_8h.html#af7b860e63b96d11e44ae8587ba06bbf4">vk_mem_alloc.h</a>
+</li>
+<li>VMA_DEFRAGMENTATION_FLAG_BITS_MAX_ENUM
+: <a class="el" href="vk__mem__alloc_8h.html#a6552a65b71d16f378c6994b3ceaef50cab87ec33154803bfeb5ac2b379f1d6a97">vk_mem_alloc.h</a>
+</li>
+<li>VMA_DEFRAGMENTATION_FLAG_INCREMENTAL
+: <a class="el" href="vk__mem__alloc_8h.html#a6552a65b71d16f378c6994b3ceaef50ca31af49446af2459284a568ce2f3fdd33">vk_mem_alloc.h</a>
+</li>
+<li>VMA_MEMORY_BUDGET
+: <a class="el" href="vk__mem__alloc_8h.html#a05decf1cf4ebf767beba7acca6c1ec3a">vk_mem_alloc.h</a>
+</li>
+<li>VMA_MEMORY_USAGE_CPU_COPY
+: <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca416a444d4d0fc20067c3f76f32ff2500">vk_mem_alloc.h</a>
+</li>
+<li>VMA_MEMORY_USAGE_CPU_ONLY
+: <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca40bdf4cddeffeb12f43d45ca1286e0a5">vk_mem_alloc.h</a>
+</li>
+<li>VMA_MEMORY_USAGE_CPU_TO_GPU
+: <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca9066b52c5a7079bb74a69aaf8b92ff67">vk_mem_alloc.h</a>
+</li>
+<li>VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED
+: <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca835333d9072db63a653818030e17614d">vk_mem_alloc.h</a>
+</li>
+<li>VMA_MEMORY_USAGE_GPU_ONLY
+: <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7">vk_mem_alloc.h</a>
+</li>
+<li>VMA_MEMORY_USAGE_GPU_TO_CPU
+: <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca7b586d2fdaf82a463b58f581ed72be27">vk_mem_alloc.h</a>
+</li>
+<li>VMA_MEMORY_USAGE_MAX_ENUM
+: <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca091e69437ef693e8d0d287f1c719ba6e">vk_mem_alloc.h</a>
+</li>
+<li>VMA_MEMORY_USAGE_UNKNOWN
+: <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccaf50d27e34e0925cf3a63db8c839121dd">vk_mem_alloc.h</a>
+</li>
+<li>VMA_POOL_CREATE_ALGORITHM_MASK
+: <a class="el" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7af4d270f8f42517a0f70037ceb6ac1d9c">vk_mem_alloc.h</a>
+</li>
+<li>VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a97a0dc38e5161b780594d998d313d35e">vk_mem_alloc.h</a>
+</li>
+<li>VMA_POOL_CREATE_FLAG_BITS_MAX_ENUM
+: <a class="el" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a1c7312bea9ea246846b9054fd6bd6aec">vk_mem_alloc.h</a>
+</li>
+<li>VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a9f1a499508a8edb4e8ba40aa0290a3d2">vk_mem_alloc.h</a>
+</li>
+<li>VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a13c8a444197c67866be9cb05599fc726">vk_mem_alloc.h</a>
+</li>
+<li>VMA_RECORD_FLAG_BITS_MAX_ENUM
+: <a class="el" href="vk__mem__alloc_8h.html#a4dd2c44642312a147a4e93373a6e64d2a20dd17d69966dbffa054739d6090b85e">vk_mem_alloc.h</a>
+</li>
+<li>VMA_RECORD_FLUSH_AFTER_CALL_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#a4dd2c44642312a147a4e93373a6e64d2a8e7ab322e8732654be627c4ea8f36cc7">vk_mem_alloc.h</a>
+</li>
+<li>VMA_RECORDING_ENABLED
+: <a class="el" href="vk__mem__alloc_8h.html#a1f0c126759fc96ccb6e2d23c101d770c">vk_mem_alloc.h</a>
+</li>
+<li>VMA_STATS_STRING_ENABLED
+: <a class="el" href="vk__mem__alloc_8h.html#ae25f0d55fd91cb166f002b63244800e1">vk_mem_alloc.h</a>
+</li>
+<li>VMA_VULKAN_VERSION
+: <a class="el" href="vk__mem__alloc_8h.html#a1a2407c283893638cc039bb31fcd74b6">vk_mem_alloc.h</a>
+</li>
+<li>vmaAllocateMemory()
+: <a class="el" href="vk__mem__alloc_8h.html#abf28077dbf82d0908b8acbe8ee8dd9b8">vk_mem_alloc.h</a>
+</li>
+<li>vmaAllocateMemoryForBuffer()
+: <a class="el" href="vk__mem__alloc_8h.html#a7fdf64415b6c3d83c454f28d2c53df7b">vk_mem_alloc.h</a>
+</li>
+<li>vmaAllocateMemoryForImage()
+: <a class="el" href="vk__mem__alloc_8h.html#a0faa3f9e5fb233d29d1e00390650febb">vk_mem_alloc.h</a>
+</li>
+<li>vmaAllocateMemoryPages()
+: <a class="el" href="vk__mem__alloc_8h.html#ad37e82e492b3de38fc3f4cffd9ad0ae1">vk_mem_alloc.h</a>
+</li>
+<li>VmaAllocationCreateFlagBits
+: <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597">vk_mem_alloc.h</a>
+</li>
+<li>VmaAllocationCreateFlags
+: <a class="el" href="vk__mem__alloc_8h.html#a5225e5e11f8376f6a31a1791f3d6e817">vk_mem_alloc.h</a>
+</li>
+<li>VmaAllocationCreateInfo
+: <a class="el" href="vk__mem__alloc_8h.html#a3bf110892ea2fb4649fedb68488d026a">vk_mem_alloc.h</a>
+</li>
+<li>VmaAllocationInfo
+: <a class="el" href="vk__mem__alloc_8h.html#a1cf7774606721026a68aabe3af2e5b50">vk_mem_alloc.h</a>
+</li>
+<li>VmaAllocatorCreateFlagBits
+: <a class="el" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7c">vk_mem_alloc.h</a>
+</li>
+<li>VmaAllocatorCreateFlags
+: <a class="el" href="vk__mem__alloc_8h.html#acfe6863e160722c2c1bbcf7573fddc4d">vk_mem_alloc.h</a>
+</li>
+<li>VmaAllocatorCreateInfo
+: <a class="el" href="vk__mem__alloc_8h.html#aad9652301d33759b83e52d4f3605a14a">vk_mem_alloc.h</a>
+</li>
+<li>VmaAllocatorInfo
+: <a class="el" href="vk__mem__alloc_8h.html#a1988031b0223fdbd564250fa1edd942c">vk_mem_alloc.h</a>
+</li>
+<li>vmaBeginDefragmentationPass()
+: <a class="el" href="vk__mem__alloc_8h.html#ac0f01545b6262f7d4d128fc8f8e5c77b">vk_mem_alloc.h</a>
+</li>
+<li>vmaBindBufferMemory()
+: <a class="el" href="vk__mem__alloc_8h.html#a6b0929b914b60cf2d45cac4bf3547470">vk_mem_alloc.h</a>
+</li>
+<li>vmaBindBufferMemory2()
+: <a class="el" href="vk__mem__alloc_8h.html#a927c944f45e0f2941182abb6f608e64a">vk_mem_alloc.h</a>
+</li>
+<li>vmaBindImageMemory()
+: <a class="el" href="vk__mem__alloc_8h.html#a3d3ca45799923aa5d138e9e5f9eb2da5">vk_mem_alloc.h</a>
+</li>
+<li>vmaBindImageMemory2()
+: <a class="el" href="vk__mem__alloc_8h.html#aa8251ee81b0045a443e35b8e8aa021bc">vk_mem_alloc.h</a>
+</li>
+<li>VmaBudget
+: <a class="el" href="vk__mem__alloc_8h.html#aa078667e71b1ef24e87a6a30d128381d">vk_mem_alloc.h</a>
+</li>
+<li>vmaBuildStatsString()
+: <a class="el" href="vk__mem__alloc_8h.html#aa4fee7eb5253377599ef4fd38c93c2a0">vk_mem_alloc.h</a>
+</li>
+<li>vmaCalculateStats()
+: <a class="el" href="vk__mem__alloc_8h.html#a333b61c1788cb23559177531e6a93ca3">vk_mem_alloc.h</a>
+</li>
+<li>vmaCheckCorruption()
+: <a class="el" href="vk__mem__alloc_8h.html#a49329a7f030dafcf82f7b73334c22e98">vk_mem_alloc.h</a>
+</li>
+<li>vmaCheckPoolCorruption()
+: <a class="el" href="vk__mem__alloc_8h.html#ad535935619c7a549bf837e1bb0068f89">vk_mem_alloc.h</a>
+</li>
+<li>vmaCreateAllocator()
+: <a class="el" href="vk__mem__alloc_8h.html#a200692051ddb34240248234f5f4c17bb">vk_mem_alloc.h</a>
+</li>
+<li>vmaCreateBuffer()
+: <a class="el" href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vk_mem_alloc.h</a>
+</li>
+<li>vmaCreateImage()
+: <a class="el" href="vk__mem__alloc_8h.html#a02a94f25679275851a53e82eacbcfc73">vk_mem_alloc.h</a>
+</li>
+<li>vmaCreateLostAllocation()
+: <a class="el" href="vk__mem__alloc_8h.html#ae5c9657d9e94756269145b01c05d16f1">vk_mem_alloc.h</a>
+</li>
+<li>vmaCreatePool()
+: <a class="el" href="vk__mem__alloc_8h.html#a5c8770ded7c59c8caac6de0c2cb00b50">vk_mem_alloc.h</a>
+</li>
+<li>vmaDefragment()
+: <a class="el" href="vk__mem__alloc_8h.html#a6aced90fcc7b39882b6654a740a0b9bb">vk_mem_alloc.h</a>
+</li>
+<li>vmaDefragmentationBegin()
+: <a class="el" href="vk__mem__alloc_8h.html#a36ba776fd7fd5cb1e9359fdc0d8e6e8a">vk_mem_alloc.h</a>
+</li>
+<li>vmaDefragmentationEnd()
+: <a class="el" href="vk__mem__alloc_8h.html#a8774e20e91e245aae959ba63efa15dd2">vk_mem_alloc.h</a>
+</li>
+<li>VmaDefragmentationFlagBits
+: <a class="el" href="vk__mem__alloc_8h.html#a6552a65b71d16f378c6994b3ceaef50c">vk_mem_alloc.h</a>
+</li>
+<li>VmaDefragmentationFlags
+: <a class="el" href="vk__mem__alloc_8h.html#a88a77cef37e5d3c4fc9eb328885d048d">vk_mem_alloc.h</a>
+</li>
+<li>VmaDefragmentationInfo
+: <a class="el" href="vk__mem__alloc_8h.html#a2bf47f96bf92bed2a49461bd9af3acfa">vk_mem_alloc.h</a>
+</li>
+<li>VmaDefragmentationInfo2
+: <a class="el" href="vk__mem__alloc_8h.html#ad6daeffaa670ce6d11a203a6224c9937">vk_mem_alloc.h</a>
+</li>
+<li>VmaDefragmentationPassInfo
+: <a class="el" href="vk__mem__alloc_8h.html#a72aebd522242d56abea67b4f47f6549e">vk_mem_alloc.h</a>
+</li>
+<li>VmaDefragmentationPassMoveInfo
+: <a class="el" href="vk__mem__alloc_8h.html#ad6799e8e2b1527abfc84d33bc44aeaf5">vk_mem_alloc.h</a>
+</li>
+<li>VmaDefragmentationStats
+: <a class="el" href="vk__mem__alloc_8h.html#ad94034192259c2e34a4d1c5e27810403">vk_mem_alloc.h</a>
+</li>
+<li>vmaDestroyAllocator()
+: <a class="el" href="vk__mem__alloc_8h.html#aa8d164061c88f22fb1fd3c8f3534bc1d">vk_mem_alloc.h</a>
+</li>
+<li>vmaDestroyBuffer()
+: <a class="el" href="vk__mem__alloc_8h.html#a0d9f4e4ba5bf9aab1f1c746387753d77">vk_mem_alloc.h</a>
+</li>
+<li>vmaDestroyImage()
+: <a class="el" href="vk__mem__alloc_8h.html#ae50d2cb3b4a3bfd4dd40987234e50e7e">vk_mem_alloc.h</a>
+</li>
+<li>vmaDestroyPool()
+: <a class="el" href="vk__mem__alloc_8h.html#a5485779c8f1948238fc4e92232fa65e1">vk_mem_alloc.h</a>
+</li>
+<li>VmaDeviceMemoryCallbacks
+: <a class="el" href="vk__mem__alloc_8h.html#a77692d3c8770ea8882d573206bd27b2b">vk_mem_alloc.h</a>
+</li>
+<li>vmaEndDefragmentationPass()
+: <a class="el" href="vk__mem__alloc_8h.html#a1b9ffa538bed905af55c747cc48963bd">vk_mem_alloc.h</a>
+</li>
+<li>vmaFindMemoryTypeIndex()
+: <a class="el" href="vk__mem__alloc_8h.html#aef15a94b58fbcb0fe706d5720e84a74a">vk_mem_alloc.h</a>
+</li>
+<li>vmaFindMemoryTypeIndexForBufferInfo()
+: <a class="el" href="vk__mem__alloc_8h.html#ae790ab9ffaf7667fb8f62523e6897888">vk_mem_alloc.h</a>
+</li>
+<li>vmaFindMemoryTypeIndexForImageInfo()
+: <a class="el" href="vk__mem__alloc_8h.html#a088da83d8eaf3ce9056d9ea0b981d472">vk_mem_alloc.h</a>
+</li>
+<li>vmaFlushAllocation()
+: <a class="el" href="vk__mem__alloc_8h.html#abc34ee6f021f459aff885f3758c435de">vk_mem_alloc.h</a>
+</li>
+<li>vmaFreeMemory()
+: <a class="el" href="vk__mem__alloc_8h.html#a11f0fbc034fa81a4efedd73d61ce7568">vk_mem_alloc.h</a>
+</li>
+<li>vmaFreeMemoryPages()
+: <a class="el" href="vk__mem__alloc_8h.html#ab9e709de044c5d8476bea77a4e755840">vk_mem_alloc.h</a>
+</li>
+<li>vmaFreeStatsString()
+: <a class="el" href="vk__mem__alloc_8h.html#a3104eb30d8122c84dd8541063f145288">vk_mem_alloc.h</a>
+</li>
+<li>vmaGetAllocationInfo()
+: <a class="el" href="vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b">vk_mem_alloc.h</a>
+</li>
+<li>vmaGetAllocatorInfo()
+: <a class="el" href="vk__mem__alloc_8h.html#afa02231a791b37255720d566a52683e7">vk_mem_alloc.h</a>
+</li>
+<li>vmaGetBudget()
+: <a class="el" href="vk__mem__alloc_8h.html#aec0ed24ebea2d0099eed5f801daaefba">vk_mem_alloc.h</a>
+</li>
+<li>vmaGetMemoryProperties()
+: <a class="el" href="vk__mem__alloc_8h.html#ab88db292a17974f911182543fda52d19">vk_mem_alloc.h</a>
+</li>
+<li>vmaGetMemoryTypeProperties()
+: <a class="el" href="vk__mem__alloc_8h.html#a8701444752eb5de4464adb5a2b514bca">vk_mem_alloc.h</a>
+</li>
+<li>vmaGetPhysicalDeviceProperties()
+: <a class="el" href="vk__mem__alloc_8h.html#aecabf7b6e91ea87d0316fa0a9e014fe0">vk_mem_alloc.h</a>
+</li>
+<li>vmaGetPoolName()
+: <a class="el" href="vk__mem__alloc_8h.html#af09b4e4eafdbee812e8d73ddf960f030">vk_mem_alloc.h</a>
+</li>
+<li>vmaGetPoolStats()
+: <a class="el" href="vk__mem__alloc_8h.html#ae8bf76997b234ef68aad922616df4153">vk_mem_alloc.h</a>
+</li>
+<li>vmaInvalidateAllocation()
+: <a class="el" href="vk__mem__alloc_8h.html#a0d0eb0c1102268fa9a476d12ecbe4006">vk_mem_alloc.h</a>
+</li>
+<li>vmaMakePoolAllocationsLost()
+: <a class="el" href="vk__mem__alloc_8h.html#a736bd6cbda886f36c891727e73bd4024">vk_mem_alloc.h</a>
+</li>
+<li>vmaMapMemory()
+: <a class="el" href="vk__mem__alloc_8h.html#ad5bd1243512d099706de88168992f069">vk_mem_alloc.h</a>
+</li>
+<li>VmaMemoryUsage
+: <a class="el" href="vk__mem__alloc_8h.html#a806e8499dde802e59eb72a1dc811c35f">vk_mem_alloc.h</a>
+</li>
+<li>VmaPoolCreateFlagBits
+: <a class="el" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7">vk_mem_alloc.h</a>
+</li>
+<li>VmaPoolCreateFlags
+: <a class="el" href="vk__mem__alloc_8h.html#a2770e325ea42e087c1b91fdf46d0292a">vk_mem_alloc.h</a>
+</li>
+<li>VmaPoolCreateInfo
+: <a class="el" href="vk__mem__alloc_8h.html#a1017aa83489c0eee8d2163d2bf253f67">vk_mem_alloc.h</a>
+</li>
+<li>VmaPoolStats
+: <a class="el" href="vk__mem__alloc_8h.html#a4759a2d9f99c19ba7627553c847132f1">vk_mem_alloc.h</a>
+</li>
+<li>VmaRecordFlagBits
+: <a class="el" href="vk__mem__alloc_8h.html#a4dd2c44642312a147a4e93373a6e64d2">vk_mem_alloc.h</a>
+</li>
+<li>VmaRecordFlags
+: <a class="el" href="vk__mem__alloc_8h.html#af3929a1a4547c592fc0b0e55ef452828">vk_mem_alloc.h</a>
+</li>
+<li>VmaRecordSettings
+: <a class="el" href="vk__mem__alloc_8h.html#a16e21c877101493fce582664cd8754fc">vk_mem_alloc.h</a>
+</li>
+<li>vmaResizeAllocation()
+: <a class="el" href="vk__mem__alloc_8h.html#a0ff488958ca72b28e545880463cb8696">vk_mem_alloc.h</a>
+</li>
+<li>vmaSetAllocationUserData()
+: <a class="el" href="vk__mem__alloc_8h.html#af9147d31ffc11d62fc187bde283ed14f">vk_mem_alloc.h</a>
+</li>
+<li>vmaSetCurrentFrameIndex()
+: <a class="el" href="vk__mem__alloc_8h.html#ade56bf8dc9f5a5eaddf5f119ed525236">vk_mem_alloc.h</a>
+</li>
+<li>vmaSetPoolName()
+: <a class="el" href="vk__mem__alloc_8h.html#adbae3a0b4ab078024462fc85c37f3b58">vk_mem_alloc.h</a>
+</li>
+<li>VmaStatInfo
+: <a class="el" href="vk__mem__alloc_8h.html#aec5b57e29c97b5d69c6d5654d60df878">vk_mem_alloc.h</a>
+</li>
+<li>VmaStats
+: <a class="el" href="vk__mem__alloc_8h.html#a21813b2efdf3836767a9058cd8a94034">vk_mem_alloc.h</a>
+</li>
+<li>vmaTouchAllocation()
+: <a class="el" href="vk__mem__alloc_8h.html#a43d8ba9673c846f049089a5029d5c73a">vk_mem_alloc.h</a>
+</li>
+<li>vmaUnmapMemory()
+: <a class="el" href="vk__mem__alloc_8h.html#a9bc268595cb33f6ec4d519cfce81ff45">vk_mem_alloc.h</a>
+</li>
+<li>VmaVulkanFunctions
+: <a class="el" href="vk__mem__alloc_8h.html#abb0a8e3b5040d847571cca6c7f9a8074">vk_mem_alloc.h</a>
+</li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/globals_defs.html b/third_party/VulkanMemoryAllocator/docs/html/globals_defs.html
new file mode 100644
index 0000000..0a00e60
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/globals_defs.html
@@ -0,0 +1,98 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: File Members</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="contents">
+&#160;<ul>
+<li>NOMINMAX
+: <a class="el" href="vk__mem__alloc_8h.html#a9f918755b601cf4bffca775992e6fb90">vk_mem_alloc.h</a>
+</li>
+<li>VMA_BIND_MEMORY2
+: <a class="el" href="vk__mem__alloc_8h.html#a88bef97f86d70a34a4c0746e09a2680d">vk_mem_alloc.h</a>
+</li>
+<li>VMA_BUFFER_DEVICE_ADDRESS
+: <a class="el" href="vk__mem__alloc_8h.html#a7f9d5e71b70dd1a137c303a8a8262c10">vk_mem_alloc.h</a>
+</li>
+<li>VMA_DEDICATED_ALLOCATION
+: <a class="el" href="vk__mem__alloc_8h.html#af7b860e63b96d11e44ae8587ba06bbf4">vk_mem_alloc.h</a>
+</li>
+<li>VMA_MEMORY_BUDGET
+: <a class="el" href="vk__mem__alloc_8h.html#a05decf1cf4ebf767beba7acca6c1ec3a">vk_mem_alloc.h</a>
+</li>
+<li>VMA_RECORDING_ENABLED
+: <a class="el" href="vk__mem__alloc_8h.html#a1f0c126759fc96ccb6e2d23c101d770c">vk_mem_alloc.h</a>
+</li>
+<li>VMA_STATS_STRING_ENABLED
+: <a class="el" href="vk__mem__alloc_8h.html#ae25f0d55fd91cb166f002b63244800e1">vk_mem_alloc.h</a>
+</li>
+<li>VMA_VULKAN_VERSION
+: <a class="el" href="vk__mem__alloc_8h.html#a1a2407c283893638cc039bb31fcd74b6">vk_mem_alloc.h</a>
+</li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/globals_enum.html b/third_party/VulkanMemoryAllocator/docs/html/globals_enum.html
new file mode 100644
index 0000000..1319762
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/globals_enum.html
@@ -0,0 +1,92 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: File Members</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="contents">
+&#160;<ul>
+<li>VmaAllocationCreateFlagBits
+: <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597">vk_mem_alloc.h</a>
+</li>
+<li>VmaAllocatorCreateFlagBits
+: <a class="el" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7c">vk_mem_alloc.h</a>
+</li>
+<li>VmaDefragmentationFlagBits
+: <a class="el" href="vk__mem__alloc_8h.html#a6552a65b71d16f378c6994b3ceaef50c">vk_mem_alloc.h</a>
+</li>
+<li>VmaMemoryUsage
+: <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cc">vk_mem_alloc.h</a>
+</li>
+<li>VmaPoolCreateFlagBits
+: <a class="el" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7">vk_mem_alloc.h</a>
+</li>
+<li>VmaRecordFlagBits
+: <a class="el" href="vk__mem__alloc_8h.html#a4dd2c44642312a147a4e93373a6e64d2">vk_mem_alloc.h</a>
+</li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/globals_eval.html b/third_party/VulkanMemoryAllocator/docs/html/globals_eval.html
new file mode 100644
index 0000000..f9dc612
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/globals_eval.html
@@ -0,0 +1,199 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: File Members</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="contents">
+&#160;
+
+<h3><a id="index_v"></a>- v -</h3><ul>
+<li>VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a5f436af6c8fe8540573a6d22627a6fd2">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a68686d0ce9beb0d4d1b9f2b8b1389a7e">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a3fc311d855c2ff53f1090ef5c722b38f">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATION_CREATE_DONT_BIND_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a2310568c62208af432724305fe29ccea">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATION_CREATE_FLAG_BITS_MAX_ENUM
+: <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597ae5633ec569f4899cf8f29e7385b2f882">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATION_CREATE_MAPPED_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a11da372cc3a82931c5e5d6146cd9dd1f">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a89759603401014eb325eb22a3839f2ff">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a839826775c62319466441f86496f036d">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a33eb2052674f3ad92386c714a65fb777">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATION_CREATE_STRATEGY_MASK
+: <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a8e16845d81ae3d27c47106d4770d5c7e">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATION_CREATE_STRATEGY_MIN_FRAGMENTATION_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a621b704103eb3360230c860acf36e706">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a8af1210cf591784afa026d94998f735d">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a0729e932b7ea170e3a128cad96c5cf6d">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597ad242a04f802e25fef0b880afe8bb0a62">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a42ba3a2d2c7117953210b7c3ef8da0df">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597aa6f24f821cd6a7c5e4a443f7bf59c520">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597ab8b1764f3e9022368e440c057783b92d">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca2acce4886d8078552efa38878413970f">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca5f1b28b0414319d1687e1f2b30ab0089">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca4d4687863f7bd4b418c6006dc04400b0">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca4816ddaed324ba110172ca608a20f29d">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATOR_CREATE_FLAG_BITS_MAX_ENUM
+: <a class="el" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7cae4d5ad929caba5f23eb502b13bd5286c">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca8fb75bf07cd184ab903596295e863dee">vk_mem_alloc.h</a>
+</li>
+<li>VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7cace7da7cc6e71a625dfa763c55a597878">vk_mem_alloc.h</a>
+</li>
+<li>VMA_DEFRAGMENTATION_FLAG_BITS_MAX_ENUM
+: <a class="el" href="vk__mem__alloc_8h.html#a6552a65b71d16f378c6994b3ceaef50cab87ec33154803bfeb5ac2b379f1d6a97">vk_mem_alloc.h</a>
+</li>
+<li>VMA_DEFRAGMENTATION_FLAG_INCREMENTAL
+: <a class="el" href="vk__mem__alloc_8h.html#a6552a65b71d16f378c6994b3ceaef50ca31af49446af2459284a568ce2f3fdd33">vk_mem_alloc.h</a>
+</li>
+<li>VMA_MEMORY_USAGE_CPU_COPY
+: <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca416a444d4d0fc20067c3f76f32ff2500">vk_mem_alloc.h</a>
+</li>
+<li>VMA_MEMORY_USAGE_CPU_ONLY
+: <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca40bdf4cddeffeb12f43d45ca1286e0a5">vk_mem_alloc.h</a>
+</li>
+<li>VMA_MEMORY_USAGE_CPU_TO_GPU
+: <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca9066b52c5a7079bb74a69aaf8b92ff67">vk_mem_alloc.h</a>
+</li>
+<li>VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED
+: <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca835333d9072db63a653818030e17614d">vk_mem_alloc.h</a>
+</li>
+<li>VMA_MEMORY_USAGE_GPU_ONLY
+: <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7">vk_mem_alloc.h</a>
+</li>
+<li>VMA_MEMORY_USAGE_GPU_TO_CPU
+: <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca7b586d2fdaf82a463b58f581ed72be27">vk_mem_alloc.h</a>
+</li>
+<li>VMA_MEMORY_USAGE_MAX_ENUM
+: <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca091e69437ef693e8d0d287f1c719ba6e">vk_mem_alloc.h</a>
+</li>
+<li>VMA_MEMORY_USAGE_UNKNOWN
+: <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccaf50d27e34e0925cf3a63db8c839121dd">vk_mem_alloc.h</a>
+</li>
+<li>VMA_POOL_CREATE_ALGORITHM_MASK
+: <a class="el" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7af4d270f8f42517a0f70037ceb6ac1d9c">vk_mem_alloc.h</a>
+</li>
+<li>VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a97a0dc38e5161b780594d998d313d35e">vk_mem_alloc.h</a>
+</li>
+<li>VMA_POOL_CREATE_FLAG_BITS_MAX_ENUM
+: <a class="el" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a1c7312bea9ea246846b9054fd6bd6aec">vk_mem_alloc.h</a>
+</li>
+<li>VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a9f1a499508a8edb4e8ba40aa0290a3d2">vk_mem_alloc.h</a>
+</li>
+<li>VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a13c8a444197c67866be9cb05599fc726">vk_mem_alloc.h</a>
+</li>
+<li>VMA_RECORD_FLAG_BITS_MAX_ENUM
+: <a class="el" href="vk__mem__alloc_8h.html#a4dd2c44642312a147a4e93373a6e64d2a20dd17d69966dbffa054739d6090b85e">vk_mem_alloc.h</a>
+</li>
+<li>VMA_RECORD_FLUSH_AFTER_CALL_BIT
+: <a class="el" href="vk__mem__alloc_8h.html#a4dd2c44642312a147a4e93373a6e64d2a8e7ab322e8732654be627c4ea8f36cc7">vk_mem_alloc.h</a>
+</li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/globals_func.html b/third_party/VulkanMemoryAllocator/docs/html/globals_func.html
new file mode 100644
index 0000000..628dc47
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/globals_func.html
@@ -0,0 +1,226 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: File Members</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="contents">
+&#160;
+
+<h3><a id="index_v"></a>- v -</h3><ul>
+<li>vmaAllocateMemory()
+: <a class="el" href="vk__mem__alloc_8h.html#abf28077dbf82d0908b8acbe8ee8dd9b8">vk_mem_alloc.h</a>
+</li>
+<li>vmaAllocateMemoryForBuffer()
+: <a class="el" href="vk__mem__alloc_8h.html#a7fdf64415b6c3d83c454f28d2c53df7b">vk_mem_alloc.h</a>
+</li>
+<li>vmaAllocateMemoryForImage()
+: <a class="el" href="vk__mem__alloc_8h.html#a0faa3f9e5fb233d29d1e00390650febb">vk_mem_alloc.h</a>
+</li>
+<li>vmaAllocateMemoryPages()
+: <a class="el" href="vk__mem__alloc_8h.html#ad37e82e492b3de38fc3f4cffd9ad0ae1">vk_mem_alloc.h</a>
+</li>
+<li>vmaBeginDefragmentationPass()
+: <a class="el" href="vk__mem__alloc_8h.html#ac0f01545b6262f7d4d128fc8f8e5c77b">vk_mem_alloc.h</a>
+</li>
+<li>vmaBindBufferMemory()
+: <a class="el" href="vk__mem__alloc_8h.html#a6b0929b914b60cf2d45cac4bf3547470">vk_mem_alloc.h</a>
+</li>
+<li>vmaBindBufferMemory2()
+: <a class="el" href="vk__mem__alloc_8h.html#a927c944f45e0f2941182abb6f608e64a">vk_mem_alloc.h</a>
+</li>
+<li>vmaBindImageMemory()
+: <a class="el" href="vk__mem__alloc_8h.html#a3d3ca45799923aa5d138e9e5f9eb2da5">vk_mem_alloc.h</a>
+</li>
+<li>vmaBindImageMemory2()
+: <a class="el" href="vk__mem__alloc_8h.html#aa8251ee81b0045a443e35b8e8aa021bc">vk_mem_alloc.h</a>
+</li>
+<li>vmaBuildStatsString()
+: <a class="el" href="vk__mem__alloc_8h.html#aa4fee7eb5253377599ef4fd38c93c2a0">vk_mem_alloc.h</a>
+</li>
+<li>vmaCalculateStats()
+: <a class="el" href="vk__mem__alloc_8h.html#a333b61c1788cb23559177531e6a93ca3">vk_mem_alloc.h</a>
+</li>
+<li>vmaCheckCorruption()
+: <a class="el" href="vk__mem__alloc_8h.html#a49329a7f030dafcf82f7b73334c22e98">vk_mem_alloc.h</a>
+</li>
+<li>vmaCheckPoolCorruption()
+: <a class="el" href="vk__mem__alloc_8h.html#ad535935619c7a549bf837e1bb0068f89">vk_mem_alloc.h</a>
+</li>
+<li>vmaCreateAllocator()
+: <a class="el" href="vk__mem__alloc_8h.html#a200692051ddb34240248234f5f4c17bb">vk_mem_alloc.h</a>
+</li>
+<li>vmaCreateBuffer()
+: <a class="el" href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vk_mem_alloc.h</a>
+</li>
+<li>vmaCreateImage()
+: <a class="el" href="vk__mem__alloc_8h.html#a02a94f25679275851a53e82eacbcfc73">vk_mem_alloc.h</a>
+</li>
+<li>vmaCreateLostAllocation()
+: <a class="el" href="vk__mem__alloc_8h.html#ae5c9657d9e94756269145b01c05d16f1">vk_mem_alloc.h</a>
+</li>
+<li>vmaCreatePool()
+: <a class="el" href="vk__mem__alloc_8h.html#a5c8770ded7c59c8caac6de0c2cb00b50">vk_mem_alloc.h</a>
+</li>
+<li>vmaDefragment()
+: <a class="el" href="vk__mem__alloc_8h.html#a6aced90fcc7b39882b6654a740a0b9bb">vk_mem_alloc.h</a>
+</li>
+<li>vmaDefragmentationBegin()
+: <a class="el" href="vk__mem__alloc_8h.html#a36ba776fd7fd5cb1e9359fdc0d8e6e8a">vk_mem_alloc.h</a>
+</li>
+<li>vmaDefragmentationEnd()
+: <a class="el" href="vk__mem__alloc_8h.html#a8774e20e91e245aae959ba63efa15dd2">vk_mem_alloc.h</a>
+</li>
+<li>vmaDestroyAllocator()
+: <a class="el" href="vk__mem__alloc_8h.html#aa8d164061c88f22fb1fd3c8f3534bc1d">vk_mem_alloc.h</a>
+</li>
+<li>vmaDestroyBuffer()
+: <a class="el" href="vk__mem__alloc_8h.html#a0d9f4e4ba5bf9aab1f1c746387753d77">vk_mem_alloc.h</a>
+</li>
+<li>vmaDestroyImage()
+: <a class="el" href="vk__mem__alloc_8h.html#ae50d2cb3b4a3bfd4dd40987234e50e7e">vk_mem_alloc.h</a>
+</li>
+<li>vmaDestroyPool()
+: <a class="el" href="vk__mem__alloc_8h.html#a5485779c8f1948238fc4e92232fa65e1">vk_mem_alloc.h</a>
+</li>
+<li>vmaEndDefragmentationPass()
+: <a class="el" href="vk__mem__alloc_8h.html#a1b9ffa538bed905af55c747cc48963bd">vk_mem_alloc.h</a>
+</li>
+<li>vmaFindMemoryTypeIndex()
+: <a class="el" href="vk__mem__alloc_8h.html#aef15a94b58fbcb0fe706d5720e84a74a">vk_mem_alloc.h</a>
+</li>
+<li>vmaFindMemoryTypeIndexForBufferInfo()
+: <a class="el" href="vk__mem__alloc_8h.html#ae790ab9ffaf7667fb8f62523e6897888">vk_mem_alloc.h</a>
+</li>
+<li>vmaFindMemoryTypeIndexForImageInfo()
+: <a class="el" href="vk__mem__alloc_8h.html#a088da83d8eaf3ce9056d9ea0b981d472">vk_mem_alloc.h</a>
+</li>
+<li>vmaFlushAllocation()
+: <a class="el" href="vk__mem__alloc_8h.html#abc34ee6f021f459aff885f3758c435de">vk_mem_alloc.h</a>
+</li>
+<li>vmaFreeMemory()
+: <a class="el" href="vk__mem__alloc_8h.html#a11f0fbc034fa81a4efedd73d61ce7568">vk_mem_alloc.h</a>
+</li>
+<li>vmaFreeMemoryPages()
+: <a class="el" href="vk__mem__alloc_8h.html#ab9e709de044c5d8476bea77a4e755840">vk_mem_alloc.h</a>
+</li>
+<li>vmaFreeStatsString()
+: <a class="el" href="vk__mem__alloc_8h.html#a3104eb30d8122c84dd8541063f145288">vk_mem_alloc.h</a>
+</li>
+<li>vmaGetAllocationInfo()
+: <a class="el" href="vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b">vk_mem_alloc.h</a>
+</li>
+<li>vmaGetAllocatorInfo()
+: <a class="el" href="vk__mem__alloc_8h.html#afa02231a791b37255720d566a52683e7">vk_mem_alloc.h</a>
+</li>
+<li>vmaGetBudget()
+: <a class="el" href="vk__mem__alloc_8h.html#aec0ed24ebea2d0099eed5f801daaefba">vk_mem_alloc.h</a>
+</li>
+<li>vmaGetMemoryProperties()
+: <a class="el" href="vk__mem__alloc_8h.html#ab88db292a17974f911182543fda52d19">vk_mem_alloc.h</a>
+</li>
+<li>vmaGetMemoryTypeProperties()
+: <a class="el" href="vk__mem__alloc_8h.html#a8701444752eb5de4464adb5a2b514bca">vk_mem_alloc.h</a>
+</li>
+<li>vmaGetPhysicalDeviceProperties()
+: <a class="el" href="vk__mem__alloc_8h.html#aecabf7b6e91ea87d0316fa0a9e014fe0">vk_mem_alloc.h</a>
+</li>
+<li>vmaGetPoolName()
+: <a class="el" href="vk__mem__alloc_8h.html#af09b4e4eafdbee812e8d73ddf960f030">vk_mem_alloc.h</a>
+</li>
+<li>vmaGetPoolStats()
+: <a class="el" href="vk__mem__alloc_8h.html#ae8bf76997b234ef68aad922616df4153">vk_mem_alloc.h</a>
+</li>
+<li>vmaInvalidateAllocation()
+: <a class="el" href="vk__mem__alloc_8h.html#a0d0eb0c1102268fa9a476d12ecbe4006">vk_mem_alloc.h</a>
+</li>
+<li>vmaMakePoolAllocationsLost()
+: <a class="el" href="vk__mem__alloc_8h.html#a736bd6cbda886f36c891727e73bd4024">vk_mem_alloc.h</a>
+</li>
+<li>vmaMapMemory()
+: <a class="el" href="vk__mem__alloc_8h.html#ad5bd1243512d099706de88168992f069">vk_mem_alloc.h</a>
+</li>
+<li>vmaResizeAllocation()
+: <a class="el" href="vk__mem__alloc_8h.html#a0ff488958ca72b28e545880463cb8696">vk_mem_alloc.h</a>
+</li>
+<li>vmaSetAllocationUserData()
+: <a class="el" href="vk__mem__alloc_8h.html#af9147d31ffc11d62fc187bde283ed14f">vk_mem_alloc.h</a>
+</li>
+<li>vmaSetCurrentFrameIndex()
+: <a class="el" href="vk__mem__alloc_8h.html#ade56bf8dc9f5a5eaddf5f119ed525236">vk_mem_alloc.h</a>
+</li>
+<li>vmaSetPoolName()
+: <a class="el" href="vk__mem__alloc_8h.html#adbae3a0b4ab078024462fc85c37f3b58">vk_mem_alloc.h</a>
+</li>
+<li>vmaTouchAllocation()
+: <a class="el" href="vk__mem__alloc_8h.html#a43d8ba9673c846f049089a5029d5c73a">vk_mem_alloc.h</a>
+</li>
+<li>vmaUnmapMemory()
+: <a class="el" href="vk__mem__alloc_8h.html#a9bc268595cb33f6ec4d519cfce81ff45">vk_mem_alloc.h</a>
+</li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/globals_type.html b/third_party/VulkanMemoryAllocator/docs/html/globals_type.html
new file mode 100644
index 0000000..aea31de
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/globals_type.html
@@ -0,0 +1,164 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: File Members</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="contents">
+&#160;<ul>
+<li>PFN_vmaAllocateDeviceMemoryFunction
+: <a class="el" href="vk__mem__alloc_8h.html#a7e1ed85f7799600b03ad51a77acc21f3">vk_mem_alloc.h</a>
+</li>
+<li>PFN_vmaFreeDeviceMemoryFunction
+: <a class="el" href="vk__mem__alloc_8h.html#a154ccaaf53dc2c36378f80f0c4f3679b">vk_mem_alloc.h</a>
+</li>
+<li>VmaAllocationCreateFlagBits
+: <a class="el" href="vk__mem__alloc_8h.html#a4fceecc301f4064dc808d3cd6c038941">vk_mem_alloc.h</a>
+</li>
+<li>VmaAllocationCreateFlags
+: <a class="el" href="vk__mem__alloc_8h.html#a5225e5e11f8376f6a31a1791f3d6e817">vk_mem_alloc.h</a>
+</li>
+<li>VmaAllocationCreateInfo
+: <a class="el" href="vk__mem__alloc_8h.html#a3bf110892ea2fb4649fedb68488d026a">vk_mem_alloc.h</a>
+</li>
+<li>VmaAllocationInfo
+: <a class="el" href="vk__mem__alloc_8h.html#a1cf7774606721026a68aabe3af2e5b50">vk_mem_alloc.h</a>
+</li>
+<li>VmaAllocatorCreateFlagBits
+: <a class="el" href="vk__mem__alloc_8h.html#afd73b95e737ee7e76f827cb5472f559f">vk_mem_alloc.h</a>
+</li>
+<li>VmaAllocatorCreateFlags
+: <a class="el" href="vk__mem__alloc_8h.html#acfe6863e160722c2c1bbcf7573fddc4d">vk_mem_alloc.h</a>
+</li>
+<li>VmaAllocatorCreateInfo
+: <a class="el" href="vk__mem__alloc_8h.html#aad9652301d33759b83e52d4f3605a14a">vk_mem_alloc.h</a>
+</li>
+<li>VmaAllocatorInfo
+: <a class="el" href="vk__mem__alloc_8h.html#a1988031b0223fdbd564250fa1edd942c">vk_mem_alloc.h</a>
+</li>
+<li>VmaBudget
+: <a class="el" href="vk__mem__alloc_8h.html#aa078667e71b1ef24e87a6a30d128381d">vk_mem_alloc.h</a>
+</li>
+<li>VmaDefragmentationFlagBits
+: <a class="el" href="vk__mem__alloc_8h.html#a13415cc0b443353a7b5abda300b833fc">vk_mem_alloc.h</a>
+</li>
+<li>VmaDefragmentationFlags
+: <a class="el" href="vk__mem__alloc_8h.html#a88a77cef37e5d3c4fc9eb328885d048d">vk_mem_alloc.h</a>
+</li>
+<li>VmaDefragmentationInfo
+: <a class="el" href="vk__mem__alloc_8h.html#a2bf47f96bf92bed2a49461bd9af3acfa">vk_mem_alloc.h</a>
+</li>
+<li>VmaDefragmentationInfo2
+: <a class="el" href="vk__mem__alloc_8h.html#ad6daeffaa670ce6d11a203a6224c9937">vk_mem_alloc.h</a>
+</li>
+<li>VmaDefragmentationPassInfo
+: <a class="el" href="vk__mem__alloc_8h.html#a72aebd522242d56abea67b4f47f6549e">vk_mem_alloc.h</a>
+</li>
+<li>VmaDefragmentationPassMoveInfo
+: <a class="el" href="vk__mem__alloc_8h.html#ad6799e8e2b1527abfc84d33bc44aeaf5">vk_mem_alloc.h</a>
+</li>
+<li>VmaDefragmentationStats
+: <a class="el" href="vk__mem__alloc_8h.html#ad94034192259c2e34a4d1c5e27810403">vk_mem_alloc.h</a>
+</li>
+<li>VmaDeviceMemoryCallbacks
+: <a class="el" href="vk__mem__alloc_8h.html#a77692d3c8770ea8882d573206bd27b2b">vk_mem_alloc.h</a>
+</li>
+<li>VmaMemoryUsage
+: <a class="el" href="vk__mem__alloc_8h.html#a806e8499dde802e59eb72a1dc811c35f">vk_mem_alloc.h</a>
+</li>
+<li>VmaPoolCreateFlagBits
+: <a class="el" href="vk__mem__alloc_8h.html#a4d4f2efc2509157a9e4ecd4fd7942303">vk_mem_alloc.h</a>
+</li>
+<li>VmaPoolCreateFlags
+: <a class="el" href="vk__mem__alloc_8h.html#a2770e325ea42e087c1b91fdf46d0292a">vk_mem_alloc.h</a>
+</li>
+<li>VmaPoolCreateInfo
+: <a class="el" href="vk__mem__alloc_8h.html#a1017aa83489c0eee8d2163d2bf253f67">vk_mem_alloc.h</a>
+</li>
+<li>VmaPoolStats
+: <a class="el" href="vk__mem__alloc_8h.html#a4759a2d9f99c19ba7627553c847132f1">vk_mem_alloc.h</a>
+</li>
+<li>VmaRecordFlagBits
+: <a class="el" href="vk__mem__alloc_8h.html#acd24d5eb58abff7e1f43cb32a1ba1413">vk_mem_alloc.h</a>
+</li>
+<li>VmaRecordFlags
+: <a class="el" href="vk__mem__alloc_8h.html#af3929a1a4547c592fc0b0e55ef452828">vk_mem_alloc.h</a>
+</li>
+<li>VmaRecordSettings
+: <a class="el" href="vk__mem__alloc_8h.html#a16e21c877101493fce582664cd8754fc">vk_mem_alloc.h</a>
+</li>
+<li>VmaStatInfo
+: <a class="el" href="vk__mem__alloc_8h.html#aec5b57e29c97b5d69c6d5654d60df878">vk_mem_alloc.h</a>
+</li>
+<li>VmaStats
+: <a class="el" href="vk__mem__alloc_8h.html#a21813b2efdf3836767a9058cd8a94034">vk_mem_alloc.h</a>
+</li>
+<li>VmaVulkanFunctions
+: <a class="el" href="vk__mem__alloc_8h.html#abb0a8e3b5040d847571cca6c7f9a8074">vk_mem_alloc.h</a>
+</li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/index.html b/third_party/VulkanMemoryAllocator/docs/html/index.html
new file mode 100644
index 0000000..c7adb70
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/index.html
@@ -0,0 +1,180 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: Vulkan Memory Allocator</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="PageDoc"><div class="header">
+  <div class="headertitle">
+<div class="title">Vulkan Memory Allocator </div>  </div>
+</div><!--header-->
+<div class="contents">
+<div class="textblock"><p><b>Version 3.0.0-development</b> (2020-03-23)</p>
+<p>Copyright (c) 2017-2020 Advanced Micro Devices, Inc. All rights reserved. <br  />
+License: MIT</p>
+<p>Documentation of all members: <a class="el" href="vk__mem__alloc_8h.html">vk_mem_alloc.h</a></p>
+<h1><a class="anchor" id="main_table_of_contents"></a>
+Table of contents</h1>
+<ul>
+<li><b>User guide</b><ul>
+<li><a class="el" href="quick_start.html">Quick start</a><ul>
+<li><a class="el" href="quick_start.html#quick_start_project_setup">Project setup</a></li>
+<li><a class="el" href="quick_start.html#quick_start_initialization">Initialization</a></li>
+<li><a class="el" href="quick_start.html#quick_start_resource_allocation">Resource allocation</a></li>
+</ul>
+</li>
+<li><a class="el" href="choosing_memory_type.html">Choosing memory type</a><ul>
+<li><a class="el" href="choosing_memory_type.html#choosing_memory_type_usage">Usage</a></li>
+<li><a class="el" href="choosing_memory_type.html#choosing_memory_type_required_preferred_flags">Required and preferred flags</a></li>
+<li><a class="el" href="choosing_memory_type.html#choosing_memory_type_explicit_memory_types">Explicit memory types</a></li>
+<li><a class="el" href="choosing_memory_type.html#choosing_memory_type_custom_memory_pools">Custom memory pools</a></li>
+<li><a class="el" href="choosing_memory_type.html#choosing_memory_type_dedicated_allocations">Dedicated allocations</a></li>
+</ul>
+</li>
+<li><a class="el" href="memory_mapping.html">Memory mapping</a><ul>
+<li><a class="el" href="memory_mapping.html#memory_mapping_mapping_functions">Mapping functions</a></li>
+<li><a class="el" href="memory_mapping.html#memory_mapping_persistently_mapped_memory">Persistently mapped memory</a></li>
+<li><a class="el" href="memory_mapping.html#memory_mapping_cache_control">Cache flush and invalidate</a></li>
+<li><a class="el" href="memory_mapping.html#memory_mapping_finding_if_memory_mappable">Finding out if memory is mappable</a></li>
+</ul>
+</li>
+<li><a class="el" href="staying_within_budget.html">Staying within budget</a><ul>
+<li><a class="el" href="staying_within_budget.html#staying_within_budget_querying_for_budget">Querying for budget</a></li>
+<li><a class="el" href="staying_within_budget.html#staying_within_budget_controlling_memory_usage">Controlling memory usage</a></li>
+</ul>
+</li>
+<li><a class="el" href="custom_memory_pools.html">Custom memory pools</a><ul>
+<li><a class="el" href="custom_memory_pools.html#custom_memory_pools_MemTypeIndex">Choosing memory type index</a></li>
+<li><a class="el" href="custom_memory_pools.html#linear_algorithm">Linear allocation algorithm</a><ul>
+<li><a class="el" href="custom_memory_pools.html#linear_algorithm_free_at_once">Free-at-once</a></li>
+<li><a class="el" href="custom_memory_pools.html#linear_algorithm_stack">Stack</a></li>
+<li><a class="el" href="custom_memory_pools.html#linear_algorithm_double_stack">Double stack</a></li>
+<li><a class="el" href="custom_memory_pools.html#linear_algorithm_ring_buffer">Ring buffer</a></li>
+</ul>
+</li>
+<li><a class="el" href="custom_memory_pools.html#buddy_algorithm">Buddy allocation algorithm</a></li>
+</ul>
+</li>
+<li><a class="el" href="defragmentation.html">Defragmentation</a><ul>
+<li><a class="el" href="defragmentation.html#defragmentation_cpu">Defragmenting CPU memory</a></li>
+<li><a class="el" href="defragmentation.html#defragmentation_gpu">Defragmenting GPU memory</a></li>
+<li><a class="el" href="defragmentation.html#defragmentation_additional_notes">Additional notes</a></li>
+<li><a class="el" href="defragmentation.html#defragmentation_custom_algorithm">Writing custom allocation algorithm</a></li>
+</ul>
+</li>
+<li><a class="el" href="lost_allocations.html">Lost allocations</a></li>
+<li><a class="el" href="statistics.html">Statistics</a><ul>
+<li><a class="el" href="statistics.html#statistics_numeric_statistics">Numeric statistics</a></li>
+<li><a class="el" href="statistics.html#statistics_json_dump">JSON dump</a></li>
+</ul>
+</li>
+<li><a class="el" href="allocation_annotation.html">Allocation names and user data</a><ul>
+<li><a class="el" href="allocation_annotation.html#allocation_user_data">Allocation user data</a></li>
+<li><a class="el" href="allocation_annotation.html#allocation_names">Allocation names</a></li>
+</ul>
+</li>
+<li><a class="el" href="debugging_memory_usage.html">Debugging incorrect memory usage</a><ul>
+<li><a class="el" href="debugging_memory_usage.html#debugging_memory_usage_initialization">Memory initialization</a></li>
+<li><a class="el" href="debugging_memory_usage.html#debugging_memory_usage_margins">Margins</a></li>
+<li><a class="el" href="debugging_memory_usage.html#debugging_memory_usage_corruption_detection">Corruption detection</a></li>
+</ul>
+</li>
+<li><a class="el" href="record_and_replay.html">Record and replay</a></li>
+</ul>
+</li>
+<li><a class="el" href="usage_patterns.html">Recommended usage patterns</a><ul>
+<li><a class="el" href="usage_patterns.html#usage_patterns_common_mistakes">Common mistakes</a></li>
+<li><a class="el" href="usage_patterns.html#usage_patterns_simple">Simple patterns</a></li>
+<li><a class="el" href="usage_patterns.html#usage_patterns_advanced">Advanced patterns</a></li>
+</ul>
+</li>
+<li><a class="el" href="configuration.html">Configuration</a><ul>
+<li><a class="el" href="configuration.html#config_Vulkan_functions">Pointers to Vulkan functions</a></li>
+<li><a class="el" href="configuration.html#custom_memory_allocator">Custom host memory allocator</a></li>
+<li><a class="el" href="configuration.html#allocation_callbacks">Device memory allocation callbacks</a></li>
+<li><a class="el" href="configuration.html#heap_memory_limit">Device heap memory limit</a></li>
+<li><a class="el" href="vk_khr_dedicated_allocation.html">VK_KHR_dedicated_allocation</a></li>
+<li><a class="el" href="enabling_buffer_device_address.html">Enabling buffer device address</a></li>
+<li><a class="el" href="vk_amd_device_coherent_memory.html">VK_AMD_device_coherent_memory</a></li>
+</ul>
+</li>
+<li><a class="el" href="general_considerations.html">General considerations</a><ul>
+<li><a class="el" href="general_considerations.html#general_considerations_thread_safety">Thread safety</a></li>
+<li><a class="el" href="general_considerations.html#general_considerations_validation_layer_warnings">Validation layer warnings</a></li>
+<li><a class="el" href="general_considerations.html#general_considerations_allocation_algorithm">Allocation algorithm</a></li>
+<li><a class="el" href="general_considerations.html#general_considerations_features_not_supported">Features not supported</a></li>
+</ul>
+</li>
+</ul>
+<h1><a class="anchor" id="main_see_also"></a>
+See also</h1>
+<ul>
+<li><a href="https://gpuopen.com/gaming-product/vulkan-memory-allocator/">Product page on GPUOpen</a></li>
+<li><a href="https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator">Source repository on GitHub</a> </li>
+</ul>
+</div></div><!-- PageDoc -->
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/jquery.js b/third_party/VulkanMemoryAllocator/docs/html/jquery.js
new file mode 100644
index 0000000..103c32d
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/jquery.js
@@ -0,0 +1,35 @@
+/*! jQuery v3.4.1 | (c) JS Foundation and other contributors | jquery.org/license */
+!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],E=C.document,r=Object.getPrototypeOf,s=t.slice,g=t.concat,u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.4.1",k=function(e,t){return new k.fn.init(e,t)},p=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;function d(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0<t&&t-1 in e)}k.fn=k.prototype={jquery:f,constructor:k,length:0,toArray:function(){return s.call(this)},get:function(e){return null==e?s.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=k.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return k.each(this,e)},map:function(n){return this.pushStack(k.map(this,function(e,t){return n.call(e,t,e)}))},slice:function(){return this.pushStack(s.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(0<=n&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:u,sort:t.sort,splice:t.splice},k.extend=k.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for("boolean"==typeof a&&(l=a,a=arguments[s]||{},s++),"object"==typeof a||m(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(e=arguments[s]))for(t in e)r=e[t],"__proto__"!==t&&a!==r&&(l&&r&&(k.isPlainObject(r)||(i=Array.isArray(r)))?(n=a[t],o=i&&!Array.isArray(n)?[]:i||k.isPlainObject(n)?n:{},i=!1,a[t]=k.extend(l,o,r)):void 0!==r&&(a[t]=r));return a},k.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isPlainObject:function(e){var t,n;return!(!e||"[object Object]"!==o.call(e))&&(!(t=r(e))||"function"==typeof(n=v.call(t,"constructor")&&t.constructor)&&a.call(n)===l)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},globalEval:function(e,t){b(e,{nonce:t&&t.nonce})},each:function(e,t){var n,r=0;if(d(e)){for(n=e.length;r<n;r++)if(!1===t.call(e[r],r,e[r]))break}else for(r in e)if(!1===t.call(e[r],r,e[r]))break;return e},trim:function(e){return null==e?"":(e+"").replace(p,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(d(Object(e))?k.merge(n,"string"==typeof e?[e]:e):u.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:i.call(t,e,n)},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;r++)e[i++]=t[r];return e.length=i,e},grep:function(e,t,n){for(var r=[],i=0,o=e.length,a=!n;i<o;i++)!t(e[i],i)!==a&&r.push(e[i]);return r},map:function(e,t,n){var r,i,o=0,a=[];if(d(e))for(r=e.length;o<r;o++)null!=(i=t(e[o],o,n))&&a.push(i);else for(o in e)null!=(i=t(e[o],o,n))&&a.push(i);return g.apply([],a)},guid:1,support:y}),"function"==typeof Symbol&&(k.fn[Symbol.iterator]=t[Symbol.iterator]),k.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(e,t){n["[object "+t+"]"]=t.toLowerCase()});var h=function(n){var e,d,b,o,i,h,f,g,w,u,l,T,C,a,E,v,s,c,y,k="sizzle"+1*new Date,m=n.document,S=0,r=0,p=ue(),x=ue(),N=ue(),A=ue(),D=function(e,t){return e===t&&(l=!0),0},j={}.hasOwnProperty,t=[],q=t.pop,L=t.push,H=t.push,O=t.slice,P=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},R="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",I="(?:\\\\.|[\\w-]|[^\0-\\xa0])+",W="\\["+M+"*("+I+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+I+"))|)"+M+"*\\]",$=":("+I+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+W+")*)|.*)\\)|)",F=new RegExp(M+"+","g"),B=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),_=new RegExp("^"+M+"*,"+M+"*"),z=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp($),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+$),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),ne=function(e,t,n){var r="0x"+t-65536;return r!=r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(m.childNodes),m.childNodes),t[m.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&((e?e.ownerDocument||e:m)!==C&&T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!A[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&U.test(t)){(s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=k),o=(l=h(t)).length;while(o--)l[o]="#"+s+" "+xe(l[o]);c=l.join(","),f=ee.test(t)&&ye(e.parentNode)||e}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){A(t,!0)}finally{s===k&&e.removeAttribute("id")}}}return g(t.replace(B,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[k]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:m;return r!==C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),m!==C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=k,!C.getElementsByName||!C.getElementsByName(k).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){a.appendChild(e).innerHTML="<a id='"+k+"'></a><select id='"+k+"-\r\\' msallowcapture=''><option selected=''></option></select>",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+k+"-]").length||v.push("~="),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+k+"+*").length||v.push(".#.+[+~]")}),ce(function(e){e.innerHTML="<a href='' disabled='disabled'></a><select disabled='disabled'><option/></select>";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",$)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e===C||e.ownerDocument===m&&y(m,e)?-1:t===C||t.ownerDocument===m&&y(m,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===C?-1:t===C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]===m?-1:s[r]===m?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if((e.ownerDocument||e)!==C&&T(e),d.matchesSelector&&E&&!A[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){A(t,!0)}return 0<se(t,C,null,[e]).length},se.contains=function(e,t){return(e.ownerDocument||e)!==C&&T(e),y(e,t)},se.attr=function(e,t){(e.ownerDocument||e)!==C&&T(e);var n=b.attrHandle[t.toLowerCase()],r=n&&j.call(b.attrHandle,t.toLowerCase())?n(e,t,!E):void 0;return void 0!==r?r:d.attributes||!E?e.getAttribute(t):(r=e.getAttributeNode(t))&&r.specified?r.value:null},se.escape=function(e){return(e+"").replace(re,ie)},se.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},se.uniqueSort=function(e){var t,n=[],r=0,i=0;if(l=!d.detectDuplicates,u=!d.sortStable&&e.slice(0),e.sort(D),l){while(t=e[i++])t===e[i]&&(r=n.push(i));while(r--)e.splice(n[r],1)}return u=null,e},o=se.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else while(t=e[r++])n+=o(t);return n},(b=se.selectors={cacheLength:50,createPseudo:le,match:G,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=p[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&p(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1<t.indexOf(i):"$="===r?i&&t.slice(-i.length)===i:"~="===r?-1<(" "+t.replace(F," ")+" ").indexOf(i):"|="===r&&(t===i||t.slice(0,i.length+1)===i+"-"))}},CHILD:function(h,e,t,g,v){var y="nth"!==h.slice(0,3),m="last"!==h.slice(-4),x="of-type"===e;return 1===g&&0===v?function(e){return!!e.parentNode}:function(e,t,n){var r,i,o,a,s,u,l=y!==m?"nextSibling":"previousSibling",c=e.parentNode,f=x&&e.nodeName.toLowerCase(),p=!n&&!x,d=!1;if(c){if(y){while(l){a=e;while(a=a[l])if(x?a.nodeName.toLowerCase()===f:1===a.nodeType)return!1;u=l="only"===h&&!u&&"nextSibling"}return!0}if(u=[m?c.firstChild:c.lastChild],m&&p){d=(s=(r=(i=(o=(a=c)[k]||(a[k]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]||[])[0]===S&&r[1])&&r[2],a=s&&c.childNodes[s];while(a=++s&&a&&a[l]||(d=s=0)||u.pop())if(1===a.nodeType&&++d&&a===e){i[h]=[S,s,d];break}}else if(p&&(d=s=(r=(i=(o=(a=e)[k]||(a[k]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]||[])[0]===S&&r[1]),!1===d)while(a=++s&&a&&a[l]||(d=s=0)||u.pop())if((x?a.nodeName.toLowerCase()===f:1===a.nodeType)&&++d&&(p&&((i=(o=a[k]||(a[k]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]=[S,d]),a===e))break;return(d-=v)===g||d%g==0&&0<=d/g}}},PSEUDO:function(e,o){var t,a=b.pseudos[e]||b.setFilters[e.toLowerCase()]||se.error("unsupported pseudo: "+e);return a[k]?a(o):1<a.length?(t=[e,e,"",o],b.setFilters.hasOwnProperty(e.toLowerCase())?le(function(e,t){var n,r=a(e,o),i=r.length;while(i--)e[n=P(e,r[i])]=!(t[n]=r[i])}):function(e){return a(e,0,t)}):a}},pseudos:{not:le(function(e){var r=[],i=[],s=f(e.replace(B,"$1"));return s[k]?le(function(e,t,n,r){var i,o=s(e,null,r,[]),a=e.length;while(a--)(i=o[a])&&(e[a]=!(t[a]=i))}):function(e,t,n){return r[0]=e,s(r,null,n,i),r[0]=null,!i.pop()}}),has:le(function(t){return function(e){return 0<se(t,e).length}}),contains:le(function(t){return t=t.replace(te,ne),function(e){return-1<(e.textContent||o(e)).indexOf(t)}}),lang:le(function(n){return V.test(n||"")||se.error("unsupported lang: "+n),n=n.replace(te,ne).toLowerCase(),function(e){var t;do{if(t=E?e.lang:e.getAttribute("xml:lang")||e.getAttribute("lang"))return(t=t.toLowerCase())===n||0===t.indexOf(n+"-")}while((e=e.parentNode)&&1===e.nodeType);return!1}}),target:function(e){var t=n.location&&n.location.hash;return t&&t.slice(1)===e.id},root:function(e){return e===a},focus:function(e){return e===C.activeElement&&(!C.hasFocus||C.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:ge(!1),disabled:ge(!0),checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!b.pseudos.empty(e)},header:function(e){return J.test(e.nodeName)},input:function(e){return Q.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:ve(function(){return[0]}),last:ve(function(e,t){return[t-1]}),eq:ve(function(e,t,n){return[n<0?n+t:n]}),even:ve(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:ve(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:ve(function(e,t,n){for(var r=n<0?n+t:t<n?t:n;0<=--r;)e.push(r);return e}),gt:ve(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}}).pseudos.nth=b.pseudos.eq,{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})b.pseudos[e]=de(e);for(e in{submit:!0,reset:!0})b.pseudos[e]=he(e);function me(){}function xe(e){for(var t=0,n=e.length,r="";t<n;t++)r+=e[t].value;return r}function be(s,e,t){var u=e.dir,l=e.next,c=l||u,f=t&&"parentNode"===c,p=r++;return e.first?function(e,t,n){while(e=e[u])if(1===e.nodeType||f)return s(e,t,n);return!1}:function(e,t,n){var r,i,o,a=[S,p];if(n){while(e=e[u])if((1===e.nodeType||f)&&s(e,t,n))return!0}else while(e=e[u])if(1===e.nodeType||f)if(i=(o=e[k]||(e[k]={}))[e.uniqueID]||(o[e.uniqueID]={}),l&&l===e.nodeName.toLowerCase())e=e[u]||e;else{if((r=i[c])&&r[0]===S&&r[1]===p)return a[2]=r[2];if((i[c]=a)[2]=s(e,t,n))return!0}return!1}}function we(i){return 1<i.length?function(e,t,n){var r=i.length;while(r--)if(!i[r](e,t,n))return!1;return!0}:i[0]}function Te(e,t,n,r,i){for(var o,a=[],s=0,u=e.length,l=null!=t;s<u;s++)(o=e[s])&&(n&&!n(o,r,i)||(a.push(o),l&&t.push(s)));return a}function Ce(d,h,g,v,y,e){return v&&!v[k]&&(v=Ce(v)),y&&!y[k]&&(y=Ce(y,e)),le(function(e,t,n,r){var i,o,a,s=[],u=[],l=t.length,c=e||function(e,t,n){for(var r=0,i=t.length;r<i;r++)se(e,t[r],n);return n}(h||"*",n.nodeType?[n]:n,[]),f=!d||!e&&h?c:Te(c,s,d,n,r),p=g?y||(e?d:l||v)?[]:t:f;if(g&&g(f,p,n,r),v){i=Te(p,u),v(i,[],n,r),o=i.length;while(o--)(a=i[o])&&(p[u[o]]=!(f[u[o]]=a))}if(e){if(y||d){if(y){i=[],o=p.length;while(o--)(a=p[o])&&i.push(f[o]=a);y(null,p=[],i,r)}o=p.length;while(o--)(a=p[o])&&-1<(i=y?P(e,a):s[o])&&(e[i]=!(t[i]=a))}}else p=Te(p===t?p.splice(l,p.length):p),y?y(null,t,p,r):H.apply(t,p)})}function Ee(e){for(var i,t,n,r=e.length,o=b.relative[e[0].type],a=o||b.relative[" "],s=o?1:0,u=be(function(e){return e===i},a,!0),l=be(function(e){return-1<P(i,e)},a,!0),c=[function(e,t,n){var r=!o&&(n||t!==w)||((i=t).nodeType?u(e,t,n):l(e,t,n));return i=null,r}];s<r;s++)if(t=b.relative[e[s].type])c=[be(we(c),t)];else{if((t=b.filter[e[s].type].apply(null,e[s].matches))[k]){for(n=++s;n<r;n++)if(b.relative[e[n].type])break;return Ce(1<s&&we(c),1<s&&xe(e.slice(0,s-1).concat({value:" "===e[s-2].type?"*":""})).replace(B,"$1"),t,s<n&&Ee(e.slice(s,n)),n<r&&Ee(e=e.slice(n)),n<r&&xe(e))}c.push(t)}return we(c)}return me.prototype=b.filters=b.pseudos,b.setFilters=new me,h=se.tokenize=function(e,t){var n,r,i,o,a,s,u,l=x[e+" "];if(l)return t?0:l.slice(0);a=e,s=[],u=b.preFilter;while(a){for(o in n&&!(r=_.exec(a))||(r&&(a=a.slice(r[0].length)||a),s.push(i=[])),n=!1,(r=z.exec(a))&&(n=r.shift(),i.push({value:n,type:r[0].replace(B," ")}),a=a.slice(n.length)),b.filter)!(r=G[o].exec(a))||u[o]&&!(r=u[o](r))||(n=r.shift(),i.push({value:n,type:o,matches:r}),a=a.slice(n.length));if(!n)break}return t?a.length:a?se.error(e):x(e,s).slice(0)},f=se.compile=function(e,t){var n,v,y,m,x,r,i=[],o=[],a=N[e+" "];if(!a){t||(t=h(e)),n=t.length;while(n--)(a=Ee(t[n]))[k]?i.push(a):o.push(a);(a=N(e,(v=o,m=0<(y=i).length,x=0<v.length,r=function(e,t,n,r,i){var o,a,s,u=0,l="0",c=e&&[],f=[],p=w,d=e||x&&b.find.TAG("*",i),h=S+=null==p?1:Math.random()||.1,g=d.length;for(i&&(w=t===C||t||i);l!==g&&null!=(o=d[l]);l++){if(x&&o){a=0,t||o.ownerDocument===C||(T(o),n=!E);while(s=v[a++])if(s(o,t||C,n)){r.push(o);break}i&&(S=h)}m&&((o=!s&&o)&&u--,e&&c.push(o))}if(u+=l,m&&l!==u){a=0;while(s=y[a++])s(c,f,t,n);if(e){if(0<u)while(l--)c[l]||f[l]||(f[l]=q.call(r));f=Te(f)}H.apply(r,f),i&&!e&&0<f.length&&1<u+y.length&&se.uniqueSort(r)}return i&&(S=h,w=p),c},m?le(r):r))).selector=e}return a},g=se.select=function(e,t,n,r){var i,o,a,s,u,l="function"==typeof e&&e,c=!r&&h(e=l.selector||e);if(n=n||[],1===c.length){if(2<(o=c[0]=c[0].slice(0)).length&&"ID"===(a=o[0]).type&&9===t.nodeType&&E&&b.relative[o[1].type]){if(!(t=(b.find.ID(a.matches[0].replace(te,ne),t)||[])[0]))return n;l&&(t=t.parentNode),e=e.slice(o.shift().value.length)}i=G.needsContext.test(e)?0:o.length;while(i--){if(a=o[i],b.relative[s=a.type])break;if((u=b.find[s])&&(r=u(a.matches[0].replace(te,ne),ee.test(o[0].type)&&ye(t.parentNode)||t))){if(o.splice(i,1),!(e=r.length&&xe(o)))return H.apply(n,r),n;break}}}return(l||f(e,c))(r,t,!E,n,!t||ee.test(e)&&ye(t.parentNode)||t),n},d.sortStable=k.split("").sort(D).join("")===k,d.detectDuplicates=!!l,T(),d.sortDetached=ce(function(e){return 1&e.compareDocumentPosition(C.createElement("fieldset"))}),ce(function(e){return e.innerHTML="<a href='#'></a>","#"===e.firstChild.getAttribute("href")})||fe("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),d.attributes&&ce(function(e){return e.innerHTML="<input/>",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||fe("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),ce(function(e){return null==e.getAttribute("disabled")})||fe(R,function(e,t,n){var r;if(!n)return!0===e[t]?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),se}(C);k.find=h,k.expr=h.selectors,k.expr[":"]=k.expr.pseudos,k.uniqueSort=k.unique=h.uniqueSort,k.text=h.getText,k.isXMLDoc=h.isXML,k.contains=h.contains,k.escapeSelector=h.escape;var T=function(e,t,n){var r=[],i=void 0!==n;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&k(e).is(n))break;r.push(e)}return r},S=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},N=k.expr.match.needsContext;function A(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var D=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?k.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?k.grep(e,function(e){return e===n!==r}):"string"!=typeof n?k.grep(e,function(e){return-1<i.call(n,e)!==r}):k.filter(n,e,r)}k.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?k.find.matchesSelector(r,e)?[r]:[]:k.find.matches(e,k.grep(t,function(e){return 1===e.nodeType}))},k.fn.extend({find:function(e){var t,n,r=this.length,i=this;if("string"!=typeof e)return this.pushStack(k(e).filter(function(){for(t=0;t<r;t++)if(k.contains(i[t],this))return!0}));for(n=this.pushStack([]),t=0;t<r;t++)k.find(e,i[t],n);return 1<r?k.uniqueSort(n):n},filter:function(e){return this.pushStack(j(this,e||[],!1))},not:function(e){return this.pushStack(j(this,e||[],!0))},is:function(e){return!!j(this,"string"==typeof e&&N.test(e)?k(e):e||[],!1).length}});var q,L=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;(k.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||q,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:L.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof k?t[0]:t,k.merge(this,k.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),D.test(r[1])&&k.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(k):k.makeArray(e,this)}).prototype=k.fn,q=k(E);var H=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}k.fn.extend({has:function(e){var t=k(e,this),n=t.length;return this.filter(function(){for(var e=0;e<n;e++)if(k.contains(this,t[e]))return!0})},closest:function(e,t){var n,r=0,i=this.length,o=[],a="string"!=typeof e&&k(e);if(!N.test(e))for(;r<i;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(n.nodeType<11&&(a?-1<a.index(n):1===n.nodeType&&k.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(1<o.length?k.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?i.call(k(e),this[0]):i.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(k.uniqueSort(k.merge(this.get(),k(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),k.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return T(e,"parentNode")},parentsUntil:function(e,t,n){return T(e,"parentNode",n)},next:function(e){return P(e,"nextSibling")},prev:function(e){return P(e,"previousSibling")},nextAll:function(e){return T(e,"nextSibling")},prevAll:function(e){return T(e,"previousSibling")},nextUntil:function(e,t,n){return T(e,"nextSibling",n)},prevUntil:function(e,t,n){return T(e,"previousSibling",n)},siblings:function(e){return S((e.parentNode||{}).firstChild,e)},children:function(e){return S(e.firstChild)},contents:function(e){return"undefined"!=typeof e.contentDocument?e.contentDocument:(A(e,"template")&&(e=e.content||e),k.merge([],e.childNodes))}},function(r,i){k.fn[r]=function(e,t){var n=k.map(this,i,e);return"Until"!==r.slice(-5)&&(t=e),t&&"string"==typeof t&&(n=k.filter(t,n)),1<this.length&&(O[r]||k.uniqueSort(n),H.test(r)&&n.reverse()),this.pushStack(n)}});var R=/[^\x20\t\r\n\f]+/g;function M(e){return e}function I(e){throw e}function W(e,t,n,r){var i;try{e&&m(i=e.promise)?i.call(e).done(t).fail(n):e&&m(i=e.then)?i.call(e,t,n):t.apply(void 0,[e].slice(r))}catch(e){n.apply(void 0,[e])}}k.Callbacks=function(r){var e,n;r="string"==typeof r?(e=r,n={},k.each(e.match(R)||[],function(e,t){n[t]=!0}),n):k.extend({},r);var i,t,o,a,s=[],u=[],l=-1,c=function(){for(a=a||r.once,o=i=!0;u.length;l=-1){t=u.shift();while(++l<s.length)!1===s[l].apply(t[0],t[1])&&r.stopOnFalse&&(l=s.length,t=!1)}r.memory||(t=!1),i=!1,a&&(s=t?[]:"")},f={add:function(){return s&&(t&&!i&&(l=s.length-1,u.push(t)),function n(e){k.each(e,function(e,t){m(t)?r.unique&&f.has(t)||s.push(t):t&&t.length&&"string"!==w(t)&&n(t)})}(arguments),t&&!i&&c()),this},remove:function(){return k.each(arguments,function(e,t){var n;while(-1<(n=k.inArray(t,s,n)))s.splice(n,1),n<=l&&l--}),this},has:function(e){return e?-1<k.inArray(e,s):0<s.length},empty:function(){return s&&(s=[]),this},disable:function(){return a=u=[],s=t="",this},disabled:function(){return!s},lock:function(){return a=u=[],t||i||(s=t=""),this},locked:function(){return!!a},fireWith:function(e,t){return a||(t=[e,(t=t||[]).slice?t.slice():t],u.push(t),i||c()),this},fire:function(){return f.fireWith(this,arguments),this},fired:function(){return!!o}};return f},k.extend({Deferred:function(e){var o=[["notify","progress",k.Callbacks("memory"),k.Callbacks("memory"),2],["resolve","done",k.Callbacks("once memory"),k.Callbacks("once memory"),0,"resolved"],["reject","fail",k.Callbacks("once memory"),k.Callbacks("once memory"),1,"rejected"]],i="pending",a={state:function(){return i},always:function(){return s.done(arguments).fail(arguments),this},"catch":function(e){return a.then(null,e)},pipe:function(){var i=arguments;return k.Deferred(function(r){k.each(o,function(e,t){var n=m(i[t[4]])&&i[t[4]];s[t[1]](function(){var e=n&&n.apply(this,arguments);e&&m(e.promise)?e.promise().progress(r.notify).done(r.resolve).fail(r.reject):r[t[0]+"With"](this,n?[e]:arguments)})}),i=null}).promise()},then:function(t,n,r){var u=0;function l(i,o,a,s){return function(){var n=this,r=arguments,e=function(){var e,t;if(!(i<u)){if((e=a.apply(n,r))===o.promise())throw new TypeError("Thenable self-resolution");t=e&&("object"==typeof e||"function"==typeof e)&&e.then,m(t)?s?t.call(e,l(u,o,M,s),l(u,o,I,s)):(u++,t.call(e,l(u,o,M,s),l(u,o,I,s),l(u,o,M,o.notifyWith))):(a!==M&&(n=void 0,r=[e]),(s||o.resolveWith)(n,r))}},t=s?e:function(){try{e()}catch(e){k.Deferred.exceptionHook&&k.Deferred.exceptionHook(e,t.stackTrace),u<=i+1&&(a!==I&&(n=void 0,r=[e]),o.rejectWith(n,r))}};i?t():(k.Deferred.getStackHook&&(t.stackTrace=k.Deferred.getStackHook()),C.setTimeout(t))}}return k.Deferred(function(e){o[0][3].add(l(0,e,m(r)?r:M,e.notifyWith)),o[1][3].add(l(0,e,m(t)?t:M)),o[2][3].add(l(0,e,m(n)?n:I))}).promise()},promise:function(e){return null!=e?k.extend(e,a):a}},s={};return k.each(o,function(e,t){var n=t[2],r=t[5];a[t[1]]=n.add,r&&n.add(function(){i=r},o[3-e][2].disable,o[3-e][3].disable,o[0][2].lock,o[0][3].lock),n.add(t[3].fire),s[t[0]]=function(){return s[t[0]+"With"](this===s?void 0:this,arguments),this},s[t[0]+"With"]=n.fireWith}),a.promise(s),e&&e.call(s,s),s},when:function(e){var n=arguments.length,t=n,r=Array(t),i=s.call(arguments),o=k.Deferred(),a=function(t){return function(e){r[t]=this,i[t]=1<arguments.length?s.call(arguments):e,--n||o.resolveWith(r,i)}};if(n<=1&&(W(e,o.done(a(t)).resolve,o.reject,!n),"pending"===o.state()||m(i[t]&&i[t].then)))return o.then();while(t--)W(i[t],a(t),o.reject);return o.promise()}});var $=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;k.Deferred.exceptionHook=function(e,t){C.console&&C.console.warn&&e&&$.test(e.name)&&C.console.warn("jQuery.Deferred exception: "+e.message,e.stack,t)},k.readyException=function(e){C.setTimeout(function(){throw e})};var F=k.Deferred();function B(){E.removeEventListener("DOMContentLoaded",B),C.removeEventListener("load",B),k.ready()}k.fn.ready=function(e){return F.then(e)["catch"](function(e){k.readyException(e)}),this},k.extend({isReady:!1,readyWait:1,ready:function(e){(!0===e?--k.readyWait:k.isReady)||(k.isReady=!0)!==e&&0<--k.readyWait||F.resolveWith(E,[k])}}),k.ready.then=F.then,"complete"===E.readyState||"loading"!==E.readyState&&!E.documentElement.doScroll?C.setTimeout(k.ready):(E.addEventListener("DOMContentLoaded",B),C.addEventListener("load",B));var _=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if("object"===w(n))for(s in i=!0,n)_(e,t,s,n[s],!0,o,a);else if(void 0!==r&&(i=!0,m(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(k(e),n)})),t))for(;s<u;s++)t(e[s],n,a?r:r.call(e[s],s,t(e[s],n)));return i?e:l?t.call(e):u?t(e[0],n):o},z=/^-ms-/,U=/-([a-z])/g;function X(e,t){return t.toUpperCase()}function V(e){return e.replace(z,"ms-").replace(U,X)}var G=function(e){return 1===e.nodeType||9===e.nodeType||!+e.nodeType};function Y(){this.expando=k.expando+Y.uid++}Y.uid=1,Y.prototype={cache:function(e){var t=e[this.expando];return t||(t={},G(e)&&(e.nodeType?e[this.expando]=t:Object.defineProperty(e,this.expando,{value:t,configurable:!0}))),t},set:function(e,t,n){var r,i=this.cache(e);if("string"==typeof t)i[V(t)]=n;else for(r in t)i[V(r)]=t[r];return i},get:function(e,t){return void 0===t?this.cache(e):e[this.expando]&&e[this.expando][V(t)]},access:function(e,t,n){return void 0===t||t&&"string"==typeof t&&void 0===n?this.get(e,t):(this.set(e,t,n),void 0!==n?n:t)},remove:function(e,t){var n,r=e[this.expando];if(void 0!==r){if(void 0!==t){n=(t=Array.isArray(t)?t.map(V):(t=V(t))in r?[t]:t.match(R)||[]).length;while(n--)delete r[t[n]]}(void 0===t||k.isEmptyObject(r))&&(e.nodeType?e[this.expando]=void 0:delete e[this.expando])}},hasData:function(e){var t=e[this.expando];return void 0!==t&&!k.isEmptyObject(t)}};var Q=new Y,J=new Y,K=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,Z=/[A-Z]/g;function ee(e,t,n){var r,i;if(void 0===n&&1===e.nodeType)if(r="data-"+t.replace(Z,"-$&").toLowerCase(),"string"==typeof(n=e.getAttribute(r))){try{n="true"===(i=n)||"false"!==i&&("null"===i?null:i===+i+""?+i:K.test(i)?JSON.parse(i):i)}catch(e){}J.set(e,t,n)}else n=void 0;return n}k.extend({hasData:function(e){return J.hasData(e)||Q.hasData(e)},data:function(e,t,n){return J.access(e,t,n)},removeData:function(e,t){J.remove(e,t)},_data:function(e,t,n){return Q.access(e,t,n)},_removeData:function(e,t){Q.remove(e,t)}}),k.fn.extend({data:function(n,e){var t,r,i,o=this[0],a=o&&o.attributes;if(void 0===n){if(this.length&&(i=J.get(o),1===o.nodeType&&!Q.get(o,"hasDataAttrs"))){t=a.length;while(t--)a[t]&&0===(r=a[t].name).indexOf("data-")&&(r=V(r.slice(5)),ee(o,r,i[r]));Q.set(o,"hasDataAttrs",!0)}return i}return"object"==typeof n?this.each(function(){J.set(this,n)}):_(this,function(e){var t;if(o&&void 0===e)return void 0!==(t=J.get(o,n))?t:void 0!==(t=ee(o,n))?t:void 0;this.each(function(){J.set(this,n,e)})},null,e,1<arguments.length,null,!0)},removeData:function(e){return this.each(function(){J.remove(this,e)})}}),k.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=Q.get(e,t),n&&(!r||Array.isArray(n)?r=Q.access(e,t,k.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=k.queue(e,t),r=n.length,i=n.shift(),o=k._queueHooks(e,t);"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,function(){k.dequeue(e,t)},o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return Q.get(e,n)||Q.access(e,n,{empty:k.Callbacks("once memory").add(function(){Q.remove(e,[t+"queue",n])})})}}),k.fn.extend({queue:function(t,n){var e=2;return"string"!=typeof t&&(n=t,t="fx",e--),arguments.length<e?k.queue(this[0],t):void 0===n?this:this.each(function(){var e=k.queue(this,t,n);k._queueHooks(this,t),"fx"===t&&"inprogress"!==e[0]&&k.dequeue(this,t)})},dequeue:function(e){return this.each(function(){k.dequeue(this,e)})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,t){var n,r=1,i=k.Deferred(),o=this,a=this.length,s=function(){--r||i.resolveWith(o,[o])};"string"!=typeof e&&(t=e,e=void 0),e=e||"fx";while(a--)(n=Q.get(o[a],e+"queueHooks"))&&n.empty&&(r++,n.empty.add(s));return s(),i.promise(t)}});var te=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,ne=new RegExp("^(?:([+-])=|)("+te+")([a-z%]*)$","i"),re=["Top","Right","Bottom","Left"],ie=E.documentElement,oe=function(e){return k.contains(e.ownerDocument,e)},ae={composed:!0};ie.getRootNode&&(oe=function(e){return k.contains(e.ownerDocument,e)||e.getRootNode(ae)===e.ownerDocument});var se=function(e,t){return"none"===(e=t||e).style.display||""===e.style.display&&oe(e)&&"none"===k.css(e,"display")},ue=function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];for(o in i=n.apply(e,r||[]),t)e.style[o]=a[o];return i};function le(e,t,n,r){var i,o,a=20,s=r?function(){return r.cur()}:function(){return k.css(e,t,"")},u=s(),l=n&&n[3]||(k.cssNumber[t]?"":"px"),c=e.nodeType&&(k.cssNumber[t]||"px"!==l&&+u)&&ne.exec(k.css(e,t));if(c&&c[3]!==l){u/=2,l=l||c[3],c=+u||1;while(a--)k.style(e,t,c+l),(1-o)*(1-(o=s()/u||.5))<=0&&(a=0),c/=o;c*=2,k.style(e,t,c+l),n=n||[]}return n&&(c=+c||+u||0,i=n[1]?c+(n[1]+1)*n[2]:+n[2],r&&(r.unit=l,r.start=c,r.end=i)),i}var ce={};function fe(e,t){for(var n,r,i,o,a,s,u,l=[],c=0,f=e.length;c<f;c++)(r=e[c]).style&&(n=r.style.display,t?("none"===n&&(l[c]=Q.get(r,"display")||null,l[c]||(r.style.display="")),""===r.style.display&&se(r)&&(l[c]=(u=a=o=void 0,a=(i=r).ownerDocument,s=i.nodeName,(u=ce[s])||(o=a.body.appendChild(a.createElement(s)),u=k.css(o,"display"),o.parentNode.removeChild(o),"none"===u&&(u="block"),ce[s]=u)))):"none"!==n&&(l[c]="none",Q.set(r,"display",n)));for(c=0;c<f;c++)null!=l[c]&&(e[c].style.display=l[c]);return e}k.fn.extend({show:function(){return fe(this,!0)},hide:function(){return fe(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){se(this)?k(this).show():k(this).hide()})}});var pe=/^(?:checkbox|radio)$/i,de=/<([a-z][^\/\0>\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i,ge={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?k.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n<r;n++)Q.set(e[n],"globalEval",!t||Q.get(t[n],"globalEval"))}ge.optgroup=ge.option,ge.tbody=ge.tfoot=ge.colgroup=ge.caption=ge.thead,ge.th=ge.td;var me,xe,be=/<|&#?\w+;/;function we(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d<h;d++)if((o=e[d])||0===o)if("object"===w(o))k.merge(p,o.nodeType?[o]:o);else if(be.test(o)){a=a||f.appendChild(t.createElement("div")),s=(de.exec(o)||["",""])[1].toLowerCase(),u=ge[s]||ge._default,a.innerHTML=u[1]+k.htmlPrefilter(o)+u[2],c=u[0];while(c--)a=a.lastChild;k.merge(p,a.childNodes),(a=f.firstChild).textContent=""}else p.push(t.createTextNode(o));f.textContent="",d=0;while(o=p[d++])if(r&&-1<k.inArray(o,r))i&&i.push(o);else if(l=oe(o),a=ve(f.appendChild(o),"script"),l&&ye(a),n){c=0;while(o=a[c++])he.test(o.type||"")&&n.push(o)}return f}me=E.createDocumentFragment().appendChild(E.createElement("div")),(xe=E.createElement("input")).setAttribute("type","radio"),xe.setAttribute("checked","checked"),xe.setAttribute("name","t"),me.appendChild(xe),y.checkClone=me.cloneNode(!0).cloneNode(!0).lastChild.checked,me.innerHTML="<textarea>x</textarea>",y.noCloneChecked=!!me.cloneNode(!0).lastChild.defaultValue;var Te=/^key/,Ce=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ee=/^([^.]*)(?:\.(.+)|)/;function ke(){return!0}function Se(){return!1}function Ne(e,t){return e===function(){try{return E.activeElement}catch(e){}}()==("focus"===t)}function Ae(e,t,n,r,i,o){var a,s;if("object"==typeof t){for(s in"string"!=typeof n&&(r=r||n,n=void 0),t)Ae(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=Se;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return k().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=k.guid++)),e.each(function(){k.event.add(this,t,i,r,n)})}function De(e,i,o){o?(Q.set(e,i,!1),k.event.add(e,i,{namespace:!1,handler:function(e){var t,n,r=Q.get(this,i);if(1&e.isTrigger&&this[i]){if(r.length)(k.event.special[i]||{}).delegateType&&e.stopPropagation();else if(r=s.call(arguments),Q.set(this,i,r),t=o(this,i),this[i](),r!==(n=Q.get(this,i))||t?Q.set(this,i,!1):n={},r!==n)return e.stopImmediatePropagation(),e.preventDefault(),n.value}else r.length&&(Q.set(this,i,{value:k.event.trigger(k.extend(r[0],k.Event.prototype),r.slice(1),this)}),e.stopImmediatePropagation())}})):void 0===Q.get(e,i)&&k.event.add(e,i,ke)}k.event={global:{},add:function(t,e,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.get(t);if(v){n.handler&&(n=(o=n).handler,i=o.selector),i&&k.find.matchesSelector(ie,i),n.guid||(n.guid=k.guid++),(u=v.events)||(u=v.events={}),(a=v.handle)||(a=v.handle=function(e){return"undefined"!=typeof k&&k.event.triggered!==e.type?k.event.dispatch.apply(t,arguments):void 0}),l=(e=(e||"").match(R)||[""]).length;while(l--)d=g=(s=Ee.exec(e[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=k.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=k.event.special[d]||{},c=k.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&k.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,r,h,a)||t.addEventListener&&t.addEventListener(d,a)),f.add&&(f.add.call(t,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),k.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.hasData(e)&&Q.get(e);if(v&&(u=v.events)){l=(t=(t||"").match(R)||[""]).length;while(l--)if(d=g=(s=Ee.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d){f=k.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,v.handle)||k.removeEvent(e,d,v.handle),delete u[d])}else for(d in u)k.event.remove(e,d+t[l],n,r,!0);k.isEmptyObject(u)&&Q.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=k.event.fix(e),u=new Array(arguments.length),l=(Q.get(this,"events")||{})[s.type]||[],c=k.event.special[s.type]||{};for(u[0]=s,t=1;t<arguments.length;t++)u[t]=arguments[t];if(s.delegateTarget=this,!c.preDispatch||!1!==c.preDispatch.call(this,s)){a=k.event.handlers.call(this,s,l),t=0;while((i=a[t++])&&!s.isPropagationStopped()){s.currentTarget=i.elem,n=0;while((o=i.handlers[n++])&&!s.isImmediatePropagationStopped())s.rnamespace&&!1!==o.namespace&&!s.rnamespace.test(o.namespace)||(s.handleObj=o,s.data=o.data,void 0!==(r=((k.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,u))&&!1===(s.result=r)&&(s.preventDefault(),s.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,s),s.result}},handlers:function(e,t){var n,r,i,o,a,s=[],u=t.delegateCount,l=e.target;if(u&&l.nodeType&&!("click"===e.type&&1<=e.button))for(;l!==this;l=l.parentNode||this)if(1===l.nodeType&&("click"!==e.type||!0!==l.disabled)){for(o=[],a={},n=0;n<u;n++)void 0===a[i=(r=t[n]).selector+" "]&&(a[i]=r.needsContext?-1<k(i,this).index(l):k.find(i,this,null,[l]).length),a[i]&&o.push(r);o.length&&s.push({elem:l,handlers:o})}return l=this,u<t.length&&s.push({elem:l,handlers:t.slice(u)}),s},addProp:function(t,e){Object.defineProperty(k.Event.prototype,t,{enumerable:!0,configurable:!0,get:m(e)?function(){if(this.originalEvent)return e(this.originalEvent)}:function(){if(this.originalEvent)return this.originalEvent[t]},set:function(e){Object.defineProperty(this,t,{enumerable:!0,configurable:!0,writable:!0,value:e})}})},fix:function(e){return e[k.expando]?e:new k.Event(e)},special:{load:{noBubble:!0},click:{setup:function(e){var t=this||e;return pe.test(t.type)&&t.click&&A(t,"input")&&De(t,"click",ke),!1},trigger:function(e){var t=this||e;return pe.test(t.type)&&t.click&&A(t,"input")&&De(t,"click"),!0},_default:function(e){var t=e.target;return pe.test(t.type)&&t.click&&A(t,"input")&&Q.get(t,"click")||A(t,"a")}},beforeunload:{postDispatch:function(e){void 0!==e.result&&e.originalEvent&&(e.originalEvent.returnValue=e.result)}}}},k.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n)},k.Event=function(e,t){if(!(this instanceof k.Event))return new k.Event(e,t);e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||void 0===e.defaultPrevented&&!1===e.returnValue?ke:Se,this.target=e.target&&3===e.target.nodeType?e.target.parentNode:e.target,this.currentTarget=e.currentTarget,this.relatedTarget=e.relatedTarget):this.type=e,t&&k.extend(this,t),this.timeStamp=e&&e.timeStamp||Date.now(),this[k.expando]=!0},k.Event.prototype={constructor:k.Event,isDefaultPrevented:Se,isPropagationStopped:Se,isImmediatePropagationStopped:Se,isSimulated:!1,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=ke,e&&!this.isSimulated&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=ke,e&&!this.isSimulated&&e.stopPropagation()},stopImmediatePropagation:function(){var e=this.originalEvent;this.isImmediatePropagationStopped=ke,e&&!this.isSimulated&&e.stopImmediatePropagation(),this.stopPropagation()}},k.each({altKey:!0,bubbles:!0,cancelable:!0,changedTouches:!0,ctrlKey:!0,detail:!0,eventPhase:!0,metaKey:!0,pageX:!0,pageY:!0,shiftKey:!0,view:!0,"char":!0,code:!0,charCode:!0,key:!0,keyCode:!0,button:!0,buttons:!0,clientX:!0,clientY:!0,offsetX:!0,offsetY:!0,pointerId:!0,pointerType:!0,screenX:!0,screenY:!0,targetTouches:!0,toElement:!0,touches:!0,which:function(e){var t=e.button;return null==e.which&&Te.test(e.type)?null!=e.charCode?e.charCode:e.keyCode:!e.which&&void 0!==t&&Ce.test(e.type)?1&t?1:2&t?3:4&t?2:0:e.which}},k.event.addProp),k.each({focus:"focusin",blur:"focusout"},function(e,t){k.event.special[e]={setup:function(){return De(this,e,Ne),!1},trigger:function(){return De(this,e),!0},delegateType:t}}),k.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(e,i){k.event.special[e]={delegateType:i,bindType:i,handle:function(e){var t,n=e.relatedTarget,r=e.handleObj;return n&&(n===this||k.contains(this,n))||(e.type=r.origType,t=r.handler.apply(this,arguments),e.type=i),t}}}),k.fn.extend({on:function(e,t,n,r){return Ae(this,e,t,n,r)},one:function(e,t,n,r){return Ae(this,e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,k(e.delegateTarget).off(r.namespace?r.origType+"."+r.namespace:r.origType,r.selector,r.handler),this;if("object"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return!1!==t&&"function"!=typeof t||(n=t,t=void 0),!1===n&&(n=Se),this.each(function(){k.event.remove(this,e,n,t)})}});var je=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,qe=/<script|<style|<link/i,Le=/checked\s*(?:[^=]|=\s*.checked.)/i,He=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;function Oe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&k(e).children("tbody")[0]||e}function Pe(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Re(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Me(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(Q.hasData(e)&&(o=Q.access(e),a=Q.set(t,o),l=o.events))for(i in delete a.handle,a.events={},l)for(n=0,r=l[i].length;n<r;n++)k.event.add(t,i,l[i][n]);J.hasData(e)&&(s=J.access(e),u=k.extend({},s),J.set(t,u))}}function Ie(n,r,i,o){r=g.apply([],r);var e,t,a,s,u,l,c=0,f=n.length,p=f-1,d=r[0],h=m(d);if(h||1<f&&"string"==typeof d&&!y.checkClone&&Le.test(d))return n.each(function(e){var t=n.eq(e);h&&(r[0]=d.call(this,e,t.html())),Ie(t,r,i,o)});if(f&&(t=(e=we(r,n[0].ownerDocument,!1,n,o)).firstChild,1===e.childNodes.length&&(e=t),t||o)){for(s=(a=k.map(ve(e,"script"),Pe)).length;c<f;c++)u=e,c!==p&&(u=k.clone(u,!0,!0),s&&k.merge(a,ve(u,"script"))),i.call(n[c],u,c);if(s)for(l=a[a.length-1].ownerDocument,k.map(a,Re),c=0;c<s;c++)u=a[c],he.test(u.type||"")&&!Q.access(u,"globalEval")&&k.contains(l,u)&&(u.src&&"module"!==(u.type||"").toLowerCase()?k._evalUrl&&!u.noModule&&k._evalUrl(u.src,{nonce:u.nonce||u.getAttribute("nonce")}):b(u.textContent.replace(He,""),u,l))}return n}function We(e,t,n){for(var r,i=t?k.filter(t,e):e,o=0;null!=(r=i[o]);o++)n||1!==r.nodeType||k.cleanData(ve(r)),r.parentNode&&(n&&oe(r)&&ye(ve(r,"script")),r.parentNode.removeChild(r));return e}k.extend({htmlPrefilter:function(e){return e.replace(je,"<$1></$2>")},clone:function(e,t,n){var r,i,o,a,s,u,l,c=e.cloneNode(!0),f=oe(e);if(!(y.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||k.isXMLDoc(e)))for(a=ve(c),r=0,i=(o=ve(e)).length;r<i;r++)s=o[r],u=a[r],void 0,"input"===(l=u.nodeName.toLowerCase())&&pe.test(s.type)?u.checked=s.checked:"input"!==l&&"textarea"!==l||(u.defaultValue=s.defaultValue);if(t)if(n)for(o=o||ve(e),a=a||ve(c),r=0,i=o.length;r<i;r++)Me(o[r],a[r]);else Me(e,c);return 0<(a=ve(c,"script")).length&&ye(a,!f&&ve(e,"script")),c},cleanData:function(e){for(var t,n,r,i=k.event.special,o=0;void 0!==(n=e[o]);o++)if(G(n)){if(t=n[Q.expando]){if(t.events)for(r in t.events)i[r]?k.event.remove(n,r):k.removeEvent(n,r,t.handle);n[Q.expando]=void 0}n[J.expando]&&(n[J.expando]=void 0)}}}),k.fn.extend({detach:function(e){return We(this,e,!0)},remove:function(e){return We(this,e)},text:function(e){return _(this,function(e){return void 0===e?k.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return Ie(this,arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||Oe(this,e).appendChild(e)})},prepend:function(){return Ie(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Oe(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return Ie(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return Ie(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(k.cleanData(ve(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return k.clone(this,e,t)})},html:function(e){return _(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!qe.test(e)&&!ge[(de.exec(e)||["",""])[1].toLowerCase()]){e=k.htmlPrefilter(e);try{for(;n<r;n++)1===(t=this[n]||{}).nodeType&&(k.cleanData(ve(t,!1)),t.innerHTML=e);t=0}catch(e){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var n=[];return Ie(this,arguments,function(e){var t=this.parentNode;k.inArray(this,n)<0&&(k.cleanData(ve(this)),t&&t.replaceChild(e,this))},n)}}),k.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,a){k.fn[e]=function(e){for(var t,n=[],r=k(e),i=r.length-1,o=0;o<=i;o++)t=o===i?this:this.clone(!0),k(r[o])[a](t),u.apply(n,t.get());return this.pushStack(n)}});var $e=new RegExp("^("+te+")(?!px)[a-z%]+$","i"),Fe=function(e){var t=e.ownerDocument.defaultView;return t&&t.opener||(t=C),t.getComputedStyle(e)},Be=new RegExp(re.join("|"),"i");function _e(e,t,n){var r,i,o,a,s=e.style;return(n=n||Fe(e))&&(""!==(a=n.getPropertyValue(t)||n[t])||oe(e)||(a=k.style(e,t)),!y.pixelBoxStyles()&&$e.test(a)&&Be.test(t)&&(r=s.width,i=s.minWidth,o=s.maxWidth,s.minWidth=s.maxWidth=s.width=a,a=n.width,s.width=r,s.minWidth=i,s.maxWidth=o)),void 0!==a?a+"":a}function ze(e,t){return{get:function(){if(!e())return(this.get=t).apply(this,arguments);delete this.get}}}!function(){function e(){if(u){s.style.cssText="position:absolute;left:-11111px;width:60px;margin-top:1px;padding:0;border:0",u.style.cssText="position:relative;display:block;box-sizing:border-box;overflow:scroll;margin:auto;border:1px;padding:1px;width:60%;top:1%",ie.appendChild(s).appendChild(u);var e=C.getComputedStyle(u);n="1%"!==e.top,a=12===t(e.marginLeft),u.style.right="60%",o=36===t(e.right),r=36===t(e.width),u.style.position="absolute",i=12===t(u.offsetWidth/3),ie.removeChild(s),u=null}}function t(e){return Math.round(parseFloat(e))}var n,r,i,o,a,s=E.createElement("div"),u=E.createElement("div");u.style&&(u.style.backgroundClip="content-box",u.cloneNode(!0).style.backgroundClip="",y.clearCloneStyle="content-box"===u.style.backgroundClip,k.extend(y,{boxSizingReliable:function(){return e(),r},pixelBoxStyles:function(){return e(),o},pixelPosition:function(){return e(),n},reliableMarginLeft:function(){return e(),a},scrollboxSize:function(){return e(),i}}))}();var Ue=["Webkit","Moz","ms"],Xe=E.createElement("div").style,Ve={};function Ge(e){var t=k.cssProps[e]||Ve[e];return t||(e in Xe?e:Ve[e]=function(e){var t=e[0].toUpperCase()+e.slice(1),n=Ue.length;while(n--)if((e=Ue[n]+t)in Xe)return e}(e)||e)}var Ye=/^(none|table(?!-c[ea]).+)/,Qe=/^--/,Je={position:"absolute",visibility:"hidden",display:"block"},Ke={letterSpacing:"0",fontWeight:"400"};function Ze(e,t,n){var r=ne.exec(t);return r?Math.max(0,r[2]-(n||0))+(r[3]||"px"):t}function et(e,t,n,r,i,o){var a="width"===t?1:0,s=0,u=0;if(n===(r?"border":"content"))return 0;for(;a<4;a+=2)"margin"===n&&(u+=k.css(e,n+re[a],!0,i)),r?("content"===n&&(u-=k.css(e,"padding"+re[a],!0,i)),"margin"!==n&&(u-=k.css(e,"border"+re[a]+"Width",!0,i))):(u+=k.css(e,"padding"+re[a],!0,i),"padding"!==n?u+=k.css(e,"border"+re[a]+"Width",!0,i):s+=k.css(e,"border"+re[a]+"Width",!0,i));return!r&&0<=o&&(u+=Math.max(0,Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-o-u-s-.5))||0),u}function tt(e,t,n){var r=Fe(e),i=(!y.boxSizingReliable()||n)&&"border-box"===k.css(e,"boxSizing",!1,r),o=i,a=_e(e,t,r),s="offset"+t[0].toUpperCase()+t.slice(1);if($e.test(a)){if(!n)return a;a="auto"}return(!y.boxSizingReliable()&&i||"auto"===a||!parseFloat(a)&&"inline"===k.css(e,"display",!1,r))&&e.getClientRects().length&&(i="border-box"===k.css(e,"boxSizing",!1,r),(o=s in e)&&(a=e[s])),(a=parseFloat(a)||0)+et(e,t,n||(i?"border":"content"),o,r,a)+"px"}function nt(e,t,n,r,i){return new nt.prototype.init(e,t,n,r,i)}k.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=_e(e,"opacity");return""===n?"1":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,gridArea:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnStart:!0,gridRow:!0,gridRowEnd:!0,gridRowStart:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=V(t),u=Qe.test(t),l=e.style;if(u||(t=Ge(s)),a=k.cssHooks[t]||k.cssHooks[s],void 0===n)return a&&"get"in a&&void 0!==(i=a.get(e,!1,r))?i:l[t];"string"===(o=typeof n)&&(i=ne.exec(n))&&i[1]&&(n=le(e,t,i),o="number"),null!=n&&n==n&&("number"!==o||u||(n+=i&&i[3]||(k.cssNumber[s]?"":"px")),y.clearCloneStyle||""!==n||0!==t.indexOf("background")||(l[t]="inherit"),a&&"set"in a&&void 0===(n=a.set(e,n,r))||(u?l.setProperty(t,n):l[t]=n))}},css:function(e,t,n,r){var i,o,a,s=V(t);return Qe.test(t)||(t=Ge(s)),(a=k.cssHooks[t]||k.cssHooks[s])&&"get"in a&&(i=a.get(e,!0,n)),void 0===i&&(i=_e(e,t,r)),"normal"===i&&t in Ke&&(i=Ke[t]),""===n||n?(o=parseFloat(i),!0===n||isFinite(o)?o||0:i):i}}),k.each(["height","width"],function(e,u){k.cssHooks[u]={get:function(e,t,n){if(t)return!Ye.test(k.css(e,"display"))||e.getClientRects().length&&e.getBoundingClientRect().width?tt(e,u,n):ue(e,Je,function(){return tt(e,u,n)})},set:function(e,t,n){var r,i=Fe(e),o=!y.scrollboxSize()&&"absolute"===i.position,a=(o||n)&&"border-box"===k.css(e,"boxSizing",!1,i),s=n?et(e,u,n,a,i):0;return a&&o&&(s-=Math.ceil(e["offset"+u[0].toUpperCase()+u.slice(1)]-parseFloat(i[u])-et(e,u,"border",!1,i)-.5)),s&&(r=ne.exec(t))&&"px"!==(r[3]||"px")&&(e.style[u]=t,t=k.css(e,u)),Ze(0,t,s)}}}),k.cssHooks.marginLeft=ze(y.reliableMarginLeft,function(e,t){if(t)return(parseFloat(_e(e,"marginLeft"))||e.getBoundingClientRect().left-ue(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}))+"px"}),k.each({margin:"",padding:"",border:"Width"},function(i,o){k.cssHooks[i+o]={expand:function(e){for(var t=0,n={},r="string"==typeof e?e.split(" "):[e];t<4;t++)n[i+re[t]+o]=r[t]||r[t-2]||r[0];return n}},"margin"!==i&&(k.cssHooks[i+o].set=Ze)}),k.fn.extend({css:function(e,t){return _(this,function(e,t,n){var r,i,o={},a=0;if(Array.isArray(t)){for(r=Fe(e),i=t.length;a<i;a++)o[t[a]]=k.css(e,t[a],!1,r);return o}return void 0!==n?k.style(e,t,n):k.css(e,t)},e,t,1<arguments.length)}}),((k.Tween=nt).prototype={constructor:nt,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||k.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(k.cssNumber[n]?"":"px")},cur:function(){var e=nt.propHooks[this.prop];return e&&e.get?e.get(this):nt.propHooks._default.get(this)},run:function(e){var t,n=nt.propHooks[this.prop];return this.options.duration?this.pos=t=k.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):nt.propHooks._default.set(this),this}}).init.prototype=nt.prototype,(nt.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=k.css(e.elem,e.prop,""))&&"auto"!==t?t:0},set:function(e){k.fx.step[e.prop]?k.fx.step[e.prop](e):1!==e.elem.nodeType||!k.cssHooks[e.prop]&&null==e.elem.style[Ge(e.prop)]?e.elem[e.prop]=e.now:k.style(e.elem,e.prop,e.now+e.unit)}}}).scrollTop=nt.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},k.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},k.fx=nt.prototype.init,k.fx.step={};var rt,it,ot,at,st=/^(?:toggle|show|hide)$/,ut=/queueHooks$/;function lt(){it&&(!1===E.hidden&&C.requestAnimationFrame?C.requestAnimationFrame(lt):C.setTimeout(lt,k.fx.interval),k.fx.tick())}function ct(){return C.setTimeout(function(){rt=void 0}),rt=Date.now()}function ft(e,t){var n,r=0,i={height:e};for(t=t?1:0;r<4;r+=2-t)i["margin"+(n=re[r])]=i["padding"+n]=e;return t&&(i.opacity=i.width=e),i}function pt(e,t,n){for(var r,i=(dt.tweeners[t]||[]).concat(dt.tweeners["*"]),o=0,a=i.length;o<a;o++)if(r=i[o].call(n,t,e))return r}function dt(o,e,t){var n,a,r=0,i=dt.prefilters.length,s=k.Deferred().always(function(){delete u.elem}),u=function(){if(a)return!1;for(var e=rt||ct(),t=Math.max(0,l.startTime+l.duration-e),n=1-(t/l.duration||0),r=0,i=l.tweens.length;r<i;r++)l.tweens[r].run(n);return s.notifyWith(o,[l,n,t]),n<1&&i?t:(i||s.notifyWith(o,[l,1,0]),s.resolveWith(o,[l]),!1)},l=s.promise({elem:o,props:k.extend({},e),opts:k.extend(!0,{specialEasing:{},easing:k.easing._default},t),originalProperties:e,originalOptions:t,startTime:rt||ct(),duration:t.duration,tweens:[],createTween:function(e,t){var n=k.Tween(o,l.opts,e,t,l.opts.specialEasing[e]||l.opts.easing);return l.tweens.push(n),n},stop:function(e){var t=0,n=e?l.tweens.length:0;if(a)return this;for(a=!0;t<n;t++)l.tweens[t].run(1);return e?(s.notifyWith(o,[l,1,0]),s.resolveWith(o,[l,e])):s.rejectWith(o,[l,e]),this}}),c=l.props;for(!function(e,t){var n,r,i,o,a;for(n in e)if(i=t[r=V(n)],o=e[n],Array.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),(a=k.cssHooks[r])&&"expand"in a)for(n in o=a.expand(o),delete e[r],o)n in e||(e[n]=o[n],t[n]=i);else t[r]=i}(c,l.opts.specialEasing);r<i;r++)if(n=dt.prefilters[r].call(l,o,c,l.opts))return m(n.stop)&&(k._queueHooks(l.elem,l.opts.queue).stop=n.stop.bind(n)),n;return k.map(c,pt,l),m(l.opts.start)&&l.opts.start.call(o,l),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always),k.fx.timer(k.extend(u,{elem:o,anim:l,queue:l.opts.queue})),l}k.Animation=k.extend(dt,{tweeners:{"*":[function(e,t){var n=this.createTween(e,t);return le(n.elem,e,ne.exec(t),n),n}]},tweener:function(e,t){m(e)?(t=e,e=["*"]):e=e.match(R);for(var n,r=0,i=e.length;r<i;r++)n=e[r],dt.tweeners[n]=dt.tweeners[n]||[],dt.tweeners[n].unshift(t)},prefilters:[function(e,t,n){var r,i,o,a,s,u,l,c,f="width"in t||"height"in t,p=this,d={},h=e.style,g=e.nodeType&&se(e),v=Q.get(e,"fxshow");for(r in n.queue||(null==(a=k._queueHooks(e,"fx")).unqueued&&(a.unqueued=0,s=a.empty.fire,a.empty.fire=function(){a.unqueued||s()}),a.unqueued++,p.always(function(){p.always(function(){a.unqueued--,k.queue(e,"fx").length||a.empty.fire()})})),t)if(i=t[r],st.test(i)){if(delete t[r],o=o||"toggle"===i,i===(g?"hide":"show")){if("show"!==i||!v||void 0===v[r])continue;g=!0}d[r]=v&&v[r]||k.style(e,r)}if((u=!k.isEmptyObject(t))||!k.isEmptyObject(d))for(r in f&&1===e.nodeType&&(n.overflow=[h.overflow,h.overflowX,h.overflowY],null==(l=v&&v.display)&&(l=Q.get(e,"display")),"none"===(c=k.css(e,"display"))&&(l?c=l:(fe([e],!0),l=e.style.display||l,c=k.css(e,"display"),fe([e]))),("inline"===c||"inline-block"===c&&null!=l)&&"none"===k.css(e,"float")&&(u||(p.done(function(){h.display=l}),null==l&&(c=h.display,l="none"===c?"":c)),h.display="inline-block")),n.overflow&&(h.overflow="hidden",p.always(function(){h.overflow=n.overflow[0],h.overflowX=n.overflow[1],h.overflowY=n.overflow[2]})),u=!1,d)u||(v?"hidden"in v&&(g=v.hidden):v=Q.access(e,"fxshow",{display:l}),o&&(v.hidden=!g),g&&fe([e],!0),p.done(function(){for(r in g||fe([e]),Q.remove(e,"fxshow"),d)k.style(e,r,d[r])})),u=pt(g?v[r]:0,r,p),r in v||(v[r]=u.start,g&&(u.end=u.start,u.start=0))}],prefilter:function(e,t){t?dt.prefilters.unshift(e):dt.prefilters.push(e)}}),k.speed=function(e,t,n){var r=e&&"object"==typeof e?k.extend({},e):{complete:n||!n&&t||m(e)&&e,duration:e,easing:n&&t||t&&!m(t)&&t};return k.fx.off?r.duration=0:"number"!=typeof r.duration&&(r.duration in k.fx.speeds?r.duration=k.fx.speeds[r.duration]:r.duration=k.fx.speeds._default),null!=r.queue&&!0!==r.queue||(r.queue="fx"),r.old=r.complete,r.complete=function(){m(r.old)&&r.old.call(this),r.queue&&k.dequeue(this,r.queue)},r},k.fn.extend({fadeTo:function(e,t,n,r){return this.filter(se).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(t,e,n,r){var i=k.isEmptyObject(t),o=k.speed(e,n,r),a=function(){var e=dt(this,k.extend({},t),o);(i||Q.get(this,"finish"))&&e.stop(!0)};return a.finish=a,i||!1===o.queue?this.each(a):this.queue(o.queue,a)},stop:function(i,e,o){var a=function(e){var t=e.stop;delete e.stop,t(o)};return"string"!=typeof i&&(o=e,e=i,i=void 0),e&&!1!==i&&this.queue(i||"fx",[]),this.each(function(){var e=!0,t=null!=i&&i+"queueHooks",n=k.timers,r=Q.get(this);if(t)r[t]&&r[t].stop&&a(r[t]);else for(t in r)r[t]&&r[t].stop&&ut.test(t)&&a(r[t]);for(t=n.length;t--;)n[t].elem!==this||null!=i&&n[t].queue!==i||(n[t].anim.stop(o),e=!1,n.splice(t,1));!e&&o||k.dequeue(this,i)})},finish:function(a){return!1!==a&&(a=a||"fx"),this.each(function(){var e,t=Q.get(this),n=t[a+"queue"],r=t[a+"queueHooks"],i=k.timers,o=n?n.length:0;for(t.finish=!0,k.queue(this,a,[]),r&&r.stop&&r.stop.call(this,!0),e=i.length;e--;)i[e].elem===this&&i[e].queue===a&&(i[e].anim.stop(!0),i.splice(e,1));for(e=0;e<o;e++)n[e]&&n[e].finish&&n[e].finish.call(this);delete t.finish})}}),k.each(["toggle","show","hide"],function(e,r){var i=k.fn[r];k.fn[r]=function(e,t,n){return null==e||"boolean"==typeof e?i.apply(this,arguments):this.animate(ft(r,!0),e,t,n)}}),k.each({slideDown:ft("show"),slideUp:ft("hide"),slideToggle:ft("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,r){k.fn[e]=function(e,t,n){return this.animate(r,e,t,n)}}),k.timers=[],k.fx.tick=function(){var e,t=0,n=k.timers;for(rt=Date.now();t<n.length;t++)(e=n[t])()||n[t]!==e||n.splice(t--,1);n.length||k.fx.stop(),rt=void 0},k.fx.timer=function(e){k.timers.push(e),k.fx.start()},k.fx.interval=13,k.fx.start=function(){it||(it=!0,lt())},k.fx.stop=function(){it=null},k.fx.speeds={slow:600,fast:200,_default:400},k.fn.delay=function(r,e){return r=k.fx&&k.fx.speeds[r]||r,e=e||"fx",this.queue(e,function(e,t){var n=C.setTimeout(e,r);t.stop=function(){C.clearTimeout(n)}})},ot=E.createElement("input"),at=E.createElement("select").appendChild(E.createElement("option")),ot.type="checkbox",y.checkOn=""!==ot.value,y.optSelected=at.selected,(ot=E.createElement("input")).value="t",ot.type="radio",y.radioValue="t"===ot.value;var ht,gt=k.expr.attrHandle;k.fn.extend({attr:function(e,t){return _(this,k.attr,e,t,1<arguments.length)},removeAttr:function(e){return this.each(function(){k.removeAttr(this,e)})}}),k.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return"undefined"==typeof e.getAttribute?k.prop(e,t,n):(1===o&&k.isXMLDoc(e)||(i=k.attrHooks[t.toLowerCase()]||(k.expr.match.bool.test(t)?ht:void 0)),void 0!==n?null===n?void k.removeAttr(e,t):i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+""),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:null==(r=k.find.attr(e,t))?void 0:r)},attrHooks:{type:{set:function(e,t){if(!y.radioValue&&"radio"===t&&A(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,i=t&&t.match(R);if(i&&1===e.nodeType)while(n=i[r++])e.removeAttribute(n)}}),ht={set:function(e,t,n){return!1===t?k.removeAttr(e,n):e.setAttribute(n,n),n}},k.each(k.expr.match.bool.source.match(/\w+/g),function(e,t){var a=gt[t]||k.find.attr;gt[t]=function(e,t,n){var r,i,o=t.toLowerCase();return n||(i=gt[o],gt[o]=r,r=null!=a(e,t,n)?o:null,gt[o]=i),r}});var vt=/^(?:input|select|textarea|button)$/i,yt=/^(?:a|area)$/i;function mt(e){return(e.match(R)||[]).join(" ")}function xt(e){return e.getAttribute&&e.getAttribute("class")||""}function bt(e){return Array.isArray(e)?e:"string"==typeof e&&e.match(R)||[]}k.fn.extend({prop:function(e,t){return _(this,k.prop,e,t,1<arguments.length)},removeProp:function(e){return this.each(function(){delete this[k.propFix[e]||e]})}}),k.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&k.isXMLDoc(e)||(t=k.propFix[t]||t,i=k.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=k.find.attr(e,"tabindex");return t?parseInt(t,10):vt.test(e.nodeName)||yt.test(e.nodeName)&&e.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),y.optSelected||(k.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),k.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){k.propFix[this.toLowerCase()]=this}),k.fn.extend({addClass:function(t){var e,n,r,i,o,a,s,u=0;if(m(t))return this.each(function(e){k(this).addClass(t.call(this,e,xt(this)))});if((e=bt(t)).length)while(n=this[u++])if(i=xt(n),r=1===n.nodeType&&" "+mt(i)+" "){a=0;while(o=e[a++])r.indexOf(" "+o+" ")<0&&(r+=o+" ");i!==(s=mt(r))&&n.setAttribute("class",s)}return this},removeClass:function(t){var e,n,r,i,o,a,s,u=0;if(m(t))return this.each(function(e){k(this).removeClass(t.call(this,e,xt(this)))});if(!arguments.length)return this.attr("class","");if((e=bt(t)).length)while(n=this[u++])if(i=xt(n),r=1===n.nodeType&&" "+mt(i)+" "){a=0;while(o=e[a++])while(-1<r.indexOf(" "+o+" "))r=r.replace(" "+o+" "," ");i!==(s=mt(r))&&n.setAttribute("class",s)}return this},toggleClass:function(i,t){var o=typeof i,a="string"===o||Array.isArray(i);return"boolean"==typeof t&&a?t?this.addClass(i):this.removeClass(i):m(i)?this.each(function(e){k(this).toggleClass(i.call(this,e,xt(this),t),t)}):this.each(function(){var e,t,n,r;if(a){t=0,n=k(this),r=bt(i);while(e=r[t++])n.hasClass(e)?n.removeClass(e):n.addClass(e)}else void 0!==i&&"boolean"!==o||((e=xt(this))&&Q.set(this,"__className__",e),this.setAttribute&&this.setAttribute("class",e||!1===i?"":Q.get(this,"__className__")||""))})},hasClass:function(e){var t,n,r=0;t=" "+e+" ";while(n=this[r++])if(1===n.nodeType&&-1<(" "+mt(xt(n))+" ").indexOf(t))return!0;return!1}});var wt=/\r/g;k.fn.extend({val:function(n){var r,e,i,t=this[0];return arguments.length?(i=m(n),this.each(function(e){var t;1===this.nodeType&&(null==(t=i?n.call(this,e,k(this).val()):n)?t="":"number"==typeof t?t+="":Array.isArray(t)&&(t=k.map(t,function(e){return null==e?"":e+""})),(r=k.valHooks[this.type]||k.valHooks[this.nodeName.toLowerCase()])&&"set"in r&&void 0!==r.set(this,t,"value")||(this.value=t))})):t?(r=k.valHooks[t.type]||k.valHooks[t.nodeName.toLowerCase()])&&"get"in r&&void 0!==(e=r.get(t,"value"))?e:"string"==typeof(e=t.value)?e.replace(wt,""):null==e?"":e:void 0}}),k.extend({valHooks:{option:{get:function(e){var t=k.find.attr(e,"value");return null!=t?t:mt(k.text(e))}},select:{get:function(e){var t,n,r,i=e.options,o=e.selectedIndex,a="select-one"===e.type,s=a?null:[],u=a?o+1:i.length;for(r=o<0?u:a?o:0;r<u;r++)if(((n=i[r]).selected||r===o)&&!n.disabled&&(!n.parentNode.disabled||!A(n.parentNode,"optgroup"))){if(t=k(n).val(),a)return t;s.push(t)}return s},set:function(e,t){var n,r,i=e.options,o=k.makeArray(t),a=i.length;while(a--)((r=i[a]).selected=-1<k.inArray(k.valHooks.option.get(r),o))&&(n=!0);return n||(e.selectedIndex=-1),o}}}}),k.each(["radio","checkbox"],function(){k.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=-1<k.inArray(k(e).val(),t)}},y.checkOn||(k.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})}),y.focusin="onfocusin"in C;var Tt=/^(?:focusinfocus|focusoutblur)$/,Ct=function(e){e.stopPropagation()};k.extend(k.event,{trigger:function(e,t,n,r){var i,o,a,s,u,l,c,f,p=[n||E],d=v.call(e,"type")?e.type:e,h=v.call(e,"namespace")?e.namespace.split("."):[];if(o=f=a=n=n||E,3!==n.nodeType&&8!==n.nodeType&&!Tt.test(d+k.event.triggered)&&(-1<d.indexOf(".")&&(d=(h=d.split(".")).shift(),h.sort()),u=d.indexOf(":")<0&&"on"+d,(e=e[k.expando]?e:new k.Event(d,"object"==typeof e&&e)).isTrigger=r?2:3,e.namespace=h.join("."),e.rnamespace=e.namespace?new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,e.result=void 0,e.target||(e.target=n),t=null==t?[e]:k.makeArray(t,[e]),c=k.event.special[d]||{},r||!c.trigger||!1!==c.trigger.apply(n,t))){if(!r&&!c.noBubble&&!x(n)){for(s=c.delegateType||d,Tt.test(s+d)||(o=o.parentNode);o;o=o.parentNode)p.push(o),a=o;a===(n.ownerDocument||E)&&p.push(a.defaultView||a.parentWindow||C)}i=0;while((o=p[i++])&&!e.isPropagationStopped())f=o,e.type=1<i?s:c.bindType||d,(l=(Q.get(o,"events")||{})[e.type]&&Q.get(o,"handle"))&&l.apply(o,t),(l=u&&o[u])&&l.apply&&G(o)&&(e.result=l.apply(o,t),!1===e.result&&e.preventDefault());return e.type=d,r||e.isDefaultPrevented()||c._default&&!1!==c._default.apply(p.pop(),t)||!G(n)||u&&m(n[d])&&!x(n)&&((a=n[u])&&(n[u]=null),k.event.triggered=d,e.isPropagationStopped()&&f.addEventListener(d,Ct),n[d](),e.isPropagationStopped()&&f.removeEventListener(d,Ct),k.event.triggered=void 0,a&&(n[u]=a)),e.result}},simulate:function(e,t,n){var r=k.extend(new k.Event,n,{type:e,isSimulated:!0});k.event.trigger(r,null,t)}}),k.fn.extend({trigger:function(e,t){return this.each(function(){k.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return k.event.trigger(e,t,n,!0)}}),y.focusin||k.each({focus:"focusin",blur:"focusout"},function(n,r){var i=function(e){k.event.simulate(r,e.target,k.event.fix(e))};k.event.special[r]={setup:function(){var e=this.ownerDocument||this,t=Q.access(e,r);t||e.addEventListener(n,i,!0),Q.access(e,r,(t||0)+1)},teardown:function(){var e=this.ownerDocument||this,t=Q.access(e,r)-1;t?Q.access(e,r,t):(e.removeEventListener(n,i,!0),Q.remove(e,r))}}});var Et=C.location,kt=Date.now(),St=/\?/;k.parseXML=function(e){var t;if(!e||"string"!=typeof e)return null;try{t=(new C.DOMParser).parseFromString(e,"text/xml")}catch(e){t=void 0}return t&&!t.getElementsByTagName("parsererror").length||k.error("Invalid XML: "+e),t};var Nt=/\[\]$/,At=/\r?\n/g,Dt=/^(?:submit|button|image|reset|file)$/i,jt=/^(?:input|select|textarea|keygen)/i;function qt(n,e,r,i){var t;if(Array.isArray(e))k.each(e,function(e,t){r||Nt.test(n)?i(n,t):qt(n+"["+("object"==typeof t&&null!=t?e:"")+"]",t,r,i)});else if(r||"object"!==w(e))i(n,e);else for(t in e)qt(n+"["+t+"]",e[t],r,i)}k.param=function(e,t){var n,r=[],i=function(e,t){var n=m(t)?t():t;r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==n?"":n)};if(null==e)return"";if(Array.isArray(e)||e.jquery&&!k.isPlainObject(e))k.each(e,function(){i(this.name,this.value)});else for(n in e)qt(n,e[n],t,i);return r.join("&")},k.fn.extend({serialize:function(){return k.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=k.prop(this,"elements");return e?k.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!k(this).is(":disabled")&&jt.test(this.nodeName)&&!Dt.test(e)&&(this.checked||!pe.test(e))}).map(function(e,t){var n=k(this).val();return null==n?null:Array.isArray(n)?k.map(n,function(e){return{name:t.name,value:e.replace(At,"\r\n")}}):{name:t.name,value:n.replace(At,"\r\n")}}).get()}});var Lt=/%20/g,Ht=/#.*$/,Ot=/([?&])_=[^&]*/,Pt=/^(.*?):[ \t]*([^\r\n]*)$/gm,Rt=/^(?:GET|HEAD)$/,Mt=/^\/\//,It={},Wt={},$t="*/".concat("*"),Ft=E.createElement("a");function Bt(o){return function(e,t){"string"!=typeof e&&(t=e,e="*");var n,r=0,i=e.toLowerCase().match(R)||[];if(m(t))while(n=i[r++])"+"===n[0]?(n=n.slice(1)||"*",(o[n]=o[n]||[]).unshift(t)):(o[n]=o[n]||[]).push(t)}}function _t(t,i,o,a){var s={},u=t===Wt;function l(e){var r;return s[e]=!0,k.each(t[e]||[],function(e,t){var n=t(i,o,a);return"string"!=typeof n||u||s[n]?u?!(r=n):void 0:(i.dataTypes.unshift(n),l(n),!1)}),r}return l(i.dataTypes[0])||!s["*"]&&l("*")}function zt(e,t){var n,r,i=k.ajaxSettings.flatOptions||{};for(n in t)void 0!==t[n]&&((i[n]?e:r||(r={}))[n]=t[n]);return r&&k.extend(!0,e,r),e}Ft.href=Et.href,k.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Et.href,type:"GET",isLocal:/^(?:about|app|app-storage|.+-extension|file|res|widget):$/.test(Et.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":$t,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":k.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?zt(zt(e,k.ajaxSettings),t):zt(k.ajaxSettings,e)},ajaxPrefilter:Bt(It),ajaxTransport:Bt(Wt),ajax:function(e,t){"object"==typeof e&&(t=e,e=void 0),t=t||{};var c,f,p,n,d,r,h,g,i,o,v=k.ajaxSetup({},t),y=v.context||v,m=v.context&&(y.nodeType||y.jquery)?k(y):k.event,x=k.Deferred(),b=k.Callbacks("once memory"),w=v.statusCode||{},a={},s={},u="canceled",T={readyState:0,getResponseHeader:function(e){var t;if(h){if(!n){n={};while(t=Pt.exec(p))n[t[1].toLowerCase()+" "]=(n[t[1].toLowerCase()+" "]||[]).concat(t[2])}t=n[e.toLowerCase()+" "]}return null==t?null:t.join(", ")},getAllResponseHeaders:function(){return h?p:null},setRequestHeader:function(e,t){return null==h&&(e=s[e.toLowerCase()]=s[e.toLowerCase()]||e,a[e]=t),this},overrideMimeType:function(e){return null==h&&(v.mimeType=e),this},statusCode:function(e){var t;if(e)if(h)T.always(e[T.status]);else for(t in e)w[t]=[w[t],e[t]];return this},abort:function(e){var t=e||u;return c&&c.abort(t),l(0,t),this}};if(x.promise(T),v.url=((e||v.url||Et.href)+"").replace(Mt,Et.protocol+"//"),v.type=t.method||t.type||v.method||v.type,v.dataTypes=(v.dataType||"*").toLowerCase().match(R)||[""],null==v.crossDomain){r=E.createElement("a");try{r.href=v.url,r.href=r.href,v.crossDomain=Ft.protocol+"//"+Ft.host!=r.protocol+"//"+r.host}catch(e){v.crossDomain=!0}}if(v.data&&v.processData&&"string"!=typeof v.data&&(v.data=k.param(v.data,v.traditional)),_t(It,v,t,T),h)return T;for(i in(g=k.event&&v.global)&&0==k.active++&&k.event.trigger("ajaxStart"),v.type=v.type.toUpperCase(),v.hasContent=!Rt.test(v.type),f=v.url.replace(Ht,""),v.hasContent?v.data&&v.processData&&0===(v.contentType||"").indexOf("application/x-www-form-urlencoded")&&(v.data=v.data.replace(Lt,"+")):(o=v.url.slice(f.length),v.data&&(v.processData||"string"==typeof v.data)&&(f+=(St.test(f)?"&":"?")+v.data,delete v.data),!1===v.cache&&(f=f.replace(Ot,"$1"),o=(St.test(f)?"&":"?")+"_="+kt+++o),v.url=f+o),v.ifModified&&(k.lastModified[f]&&T.setRequestHeader("If-Modified-Since",k.lastModified[f]),k.etag[f]&&T.setRequestHeader("If-None-Match",k.etag[f])),(v.data&&v.hasContent&&!1!==v.contentType||t.contentType)&&T.setRequestHeader("Content-Type",v.contentType),T.setRequestHeader("Accept",v.dataTypes[0]&&v.accepts[v.dataTypes[0]]?v.accepts[v.dataTypes[0]]+("*"!==v.dataTypes[0]?", "+$t+"; q=0.01":""):v.accepts["*"]),v.headers)T.setRequestHeader(i,v.headers[i]);if(v.beforeSend&&(!1===v.beforeSend.call(y,T,v)||h))return T.abort();if(u="abort",b.add(v.complete),T.done(v.success),T.fail(v.error),c=_t(Wt,v,t,T)){if(T.readyState=1,g&&m.trigger("ajaxSend",[T,v]),h)return T;v.async&&0<v.timeout&&(d=C.setTimeout(function(){T.abort("timeout")},v.timeout));try{h=!1,c.send(a,l)}catch(e){if(h)throw e;l(-1,e)}}else l(-1,"No Transport");function l(e,t,n,r){var i,o,a,s,u,l=t;h||(h=!0,d&&C.clearTimeout(d),c=void 0,p=r||"",T.readyState=0<e?4:0,i=200<=e&&e<300||304===e,n&&(s=function(e,t,n){var r,i,o,a,s=e.contents,u=e.dataTypes;while("*"===u[0])u.shift(),void 0===r&&(r=e.mimeType||t.getResponseHeader("Content-Type"));if(r)for(i in s)if(s[i]&&s[i].test(r)){u.unshift(i);break}if(u[0]in n)o=u[0];else{for(i in n){if(!u[0]||e.converters[i+" "+u[0]]){o=i;break}a||(a=i)}o=o||a}if(o)return o!==u[0]&&u.unshift(o),n[o]}(v,T,n)),s=function(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if("*"===o)o=u;else if("*"!==u&&u!==o){if(!(a=l[u+" "+o]||l["* "+o]))for(i in l)if((s=i.split(" "))[1]===o&&(a=l[u+" "+s[0]]||l["* "+s[0]])){!0===a?a=l[i]:!0!==l[i]&&(o=s[0],c.unshift(s[1]));break}if(!0!==a)if(a&&e["throws"])t=a(t);else try{t=a(t)}catch(e){return{state:"parsererror",error:a?e:"No conversion from "+u+" to "+o}}}return{state:"success",data:t}}(v,s,T,i),i?(v.ifModified&&((u=T.getResponseHeader("Last-Modified"))&&(k.lastModified[f]=u),(u=T.getResponseHeader("etag"))&&(k.etag[f]=u)),204===e||"HEAD"===v.type?l="nocontent":304===e?l="notmodified":(l=s.state,o=s.data,i=!(a=s.error))):(a=l,!e&&l||(l="error",e<0&&(e=0))),T.status=e,T.statusText=(t||l)+"",i?x.resolveWith(y,[o,l,T]):x.rejectWith(y,[T,l,a]),T.statusCode(w),w=void 0,g&&m.trigger(i?"ajaxSuccess":"ajaxError",[T,v,i?o:a]),b.fireWith(y,[T,l]),g&&(m.trigger("ajaxComplete",[T,v]),--k.active||k.event.trigger("ajaxStop")))}return T},getJSON:function(e,t,n){return k.get(e,t,n,"json")},getScript:function(e,t){return k.get(e,void 0,t,"script")}}),k.each(["get","post"],function(e,i){k[i]=function(e,t,n,r){return m(t)&&(r=r||n,n=t,t=void 0),k.ajax(k.extend({url:e,type:i,dataType:r,data:t,success:n},k.isPlainObject(e)&&e))}}),k._evalUrl=function(e,t){return k.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,converters:{"text script":function(){}},dataFilter:function(e){k.globalEval(e,t)}})},k.fn.extend({wrapAll:function(e){var t;return this[0]&&(m(e)&&(e=e.call(this[0])),t=k(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(n){return m(n)?this.each(function(e){k(this).wrapInner(n.call(this,e))}):this.each(function(){var e=k(this),t=e.contents();t.length?t.wrapAll(n):e.append(n)})},wrap:function(t){var n=m(t);return this.each(function(e){k(this).wrapAll(n?t.call(this,e):t)})},unwrap:function(e){return this.parent(e).not("body").each(function(){k(this).replaceWith(this.childNodes)}),this}}),k.expr.pseudos.hidden=function(e){return!k.expr.pseudos.visible(e)},k.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},k.ajaxSettings.xhr=function(){try{return new C.XMLHttpRequest}catch(e){}};var Ut={0:200,1223:204},Xt=k.ajaxSettings.xhr();y.cors=!!Xt&&"withCredentials"in Xt,y.ajax=Xt=!!Xt,k.ajaxTransport(function(i){var o,a;if(y.cors||Xt&&!i.crossDomain)return{send:function(e,t){var n,r=i.xhr();if(r.open(i.type,i.url,i.async,i.username,i.password),i.xhrFields)for(n in i.xhrFields)r[n]=i.xhrFields[n];for(n in i.mimeType&&r.overrideMimeType&&r.overrideMimeType(i.mimeType),i.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest"),e)r.setRequestHeader(n,e[n]);o=function(e){return function(){o&&(o=a=r.onload=r.onerror=r.onabort=r.ontimeout=r.onreadystatechange=null,"abort"===e?r.abort():"error"===e?"number"!=typeof r.status?t(0,"error"):t(r.status,r.statusText):t(Ut[r.status]||r.status,r.statusText,"text"!==(r.responseType||"text")||"string"!=typeof r.responseText?{binary:r.response}:{text:r.responseText},r.getAllResponseHeaders()))}},r.onload=o(),a=r.onerror=r.ontimeout=o("error"),void 0!==r.onabort?r.onabort=a:r.onreadystatechange=function(){4===r.readyState&&C.setTimeout(function(){o&&a()})},o=o("abort");try{r.send(i.hasContent&&i.data||null)}catch(e){if(o)throw e}},abort:function(){o&&o()}}}),k.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),k.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return k.globalEval(e),e}}}),k.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),k.ajaxTransport("script",function(n){var r,i;if(n.crossDomain||n.scriptAttrs)return{send:function(e,t){r=k("<script>").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Vt,Gt=[],Yt=/(=)\?(?=&|$)|\?\?/;k.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Gt.pop()||k.expando+"_"+kt++;return this[e]=!0,e}}),k.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Yt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Yt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Yt,"$1"+r):!1!==e.jsonp&&(e.url+=(St.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||k.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?k(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Gt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Vt=E.implementation.createHTMLDocument("").body).innerHTML="<form></form><form></form>",2===Vt.childNodes.length),k.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=D.exec(e))?[t.createElement(i[1])]:(i=we([e],t,o),o&&o.length&&k(o).remove(),k.merge([],i.childNodes)));var r,i,o},k.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1<s&&(r=mt(e.slice(s)),e=e.slice(0,s)),m(t)?(n=t,t=void 0):t&&"object"==typeof t&&(i="POST"),0<a.length&&k.ajax({url:e,type:i||"GET",dataType:"html",data:t}).done(function(e){o=arguments,a.html(r?k("<div>").append(k.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},k.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){k.fn[t]=function(e){return this.on(t,e)}}),k.expr.pseudos.animated=function(t){return k.grep(k.timers,function(e){return t===e.elem}).length},k.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=k.css(e,"position"),c=k(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=k.css(e,"top"),u=k.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,k.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},k.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){k.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===k.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===k.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=k(e).offset()).top+=k.css(e,"borderTopWidth",!0),i.left+=k.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-k.css(r,"marginTop",!0),left:t.left-i.left-k.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===k.css(e,"position"))e=e.offsetParent;return e||ie})}}),k.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;k.fn[t]=function(e){return _(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),k.each(["top","left"],function(e,n){k.cssHooks[n]=ze(y.pixelPosition,function(e,t){if(t)return t=_e(e,n),$e.test(t)?k(e).position()[n]+"px":t})}),k.each({Height:"height",Width:"width"},function(a,s){k.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){k.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return _(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?k.css(e,t,i):k.style(e,t,n,i)},s,n?e:void 0,n)}})}),k.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){k.fn[n]=function(e,t){return 0<arguments.length?this.on(n,null,e,t):this.trigger(n)}}),k.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),k.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)}}),k.proxy=function(e,t){var n,r,i;if("string"==typeof t&&(n=e[t],t=e,e=n),m(e))return r=s.call(arguments,2),(i=function(){return e.apply(t||this,r.concat(s.call(arguments)))}).guid=e.guid=e.guid||k.guid++,i},k.holdReady=function(e){e?k.readyWait++:k.ready(!0)},k.isArray=Array.isArray,k.parseJSON=JSON.parse,k.nodeName=A,k.isFunction=m,k.isWindow=x,k.camelCase=V,k.type=w,k.now=Date.now,k.isNumeric=function(e){var t=k.type(e);return("number"===t||"string"===t)&&!isNaN(e-parseFloat(e))},"function"==typeof define&&define.amd&&define("jquery",[],function(){return k});var Qt=C.jQuery,Jt=C.$;return k.noConflict=function(e){return C.$===k&&(C.$=Jt),e&&C.jQuery===k&&(C.jQuery=Qt),k},e||(C.jQuery=C.$=k),k});
+/*! jQuery UI - v1.12.1 - 2019-01-27
+* http://jqueryui.com
+* Includes: widget.js, position.js, data.js, disable-selection.js, focusable.js, form-reset-mixin.js, jquery-1-7.js, keycode.js, labels.js, scroll-parent.js, tabbable.js, unique-id.js, widgets/resizable.js, widgets/mouse.js
+* Copyright jQuery Foundation and other contributors; Licensed MIT */
+
+(function(t){"function"==typeof define&&define.amd?define(["jquery"],t):t(jQuery)})(function(t){function e(t){for(var e=t.css("visibility");"inherit"===e;)t=t.parent(),e=t.css("visibility");return"hidden"!==e}t.ui=t.ui||{},t.ui.version="1.12.1";var i=0,s=Array.prototype.slice;t.cleanData=function(e){return function(i){var s,n,o;for(o=0;null!=(n=i[o]);o++)try{s=t._data(n,"events"),s&&s.remove&&t(n).triggerHandler("remove")}catch(a){}e(i)}}(t.cleanData),t.widget=function(e,i,s){var n,o,a,r={},h=e.split(".")[0];e=e.split(".")[1];var l=h+"-"+e;return s||(s=i,i=t.Widget),t.isArray(s)&&(s=t.extend.apply(null,[{}].concat(s))),t.expr[":"][l.toLowerCase()]=function(e){return!!t.data(e,l)},t[h]=t[h]||{},n=t[h][e],o=t[h][e]=function(t,e){return this._createWidget?(arguments.length&&this._createWidget(t,e),void 0):new o(t,e)},t.extend(o,n,{version:s.version,_proto:t.extend({},s),_childConstructors:[]}),a=new i,a.options=t.widget.extend({},a.options),t.each(s,function(e,s){return t.isFunction(s)?(r[e]=function(){function t(){return i.prototype[e].apply(this,arguments)}function n(t){return i.prototype[e].apply(this,t)}return function(){var e,i=this._super,o=this._superApply;return this._super=t,this._superApply=n,e=s.apply(this,arguments),this._super=i,this._superApply=o,e}}(),void 0):(r[e]=s,void 0)}),o.prototype=t.widget.extend(a,{widgetEventPrefix:n?a.widgetEventPrefix||e:e},r,{constructor:o,namespace:h,widgetName:e,widgetFullName:l}),n?(t.each(n._childConstructors,function(e,i){var s=i.prototype;t.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete n._childConstructors):i._childConstructors.push(o),t.widget.bridge(e,o),o},t.widget.extend=function(e){for(var i,n,o=s.call(arguments,1),a=0,r=o.length;r>a;a++)for(i in o[a])n=o[a][i],o[a].hasOwnProperty(i)&&void 0!==n&&(e[i]=t.isPlainObject(n)?t.isPlainObject(e[i])?t.widget.extend({},e[i],n):t.widget.extend({},n):n);return e},t.widget.bridge=function(e,i){var n=i.prototype.widgetFullName||e;t.fn[e]=function(o){var a="string"==typeof o,r=s.call(arguments,1),h=this;return a?this.length||"instance"!==o?this.each(function(){var i,s=t.data(this,n);return"instance"===o?(h=s,!1):s?t.isFunction(s[o])&&"_"!==o.charAt(0)?(i=s[o].apply(s,r),i!==s&&void 0!==i?(h=i&&i.jquery?h.pushStack(i.get()):i,!1):void 0):t.error("no such method '"+o+"' for "+e+" widget instance"):t.error("cannot call methods on "+e+" prior to initialization; "+"attempted to call method '"+o+"'")}):h=void 0:(r.length&&(o=t.widget.extend.apply(null,[o].concat(r))),this.each(function(){var e=t.data(this,n);e?(e.option(o||{}),e._init&&e._init()):t.data(this,n,new i(o,this))})),h}},t.Widget=function(){},t.Widget._childConstructors=[],t.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{classes:{},disabled:!1,create:null},_createWidget:function(e,s){s=t(s||this.defaultElement||this)[0],this.element=t(s),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=t(),this.hoverable=t(),this.focusable=t(),this.classesElementLookup={},s!==this&&(t.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t){t.target===s&&this.destroy()}}),this.document=t(s.style?s.ownerDocument:s.document||s),this.window=t(this.document[0].defaultView||this.document[0].parentWindow)),this.options=t.widget.extend({},this.options,this._getCreateOptions(),e),this._create(),this.options.disabled&&this._setOptionDisabled(this.options.disabled),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:function(){return{}},_getCreateEventData:t.noop,_create:t.noop,_init:t.noop,destroy:function(){var e=this;this._destroy(),t.each(this.classesElementLookup,function(t,i){e._removeClass(i,t)}),this.element.off(this.eventNamespace).removeData(this.widgetFullName),this.widget().off(this.eventNamespace).removeAttr("aria-disabled"),this.bindings.off(this.eventNamespace)},_destroy:t.noop,widget:function(){return this.element},option:function(e,i){var s,n,o,a=e;if(0===arguments.length)return t.widget.extend({},this.options);if("string"==typeof e)if(a={},s=e.split("."),e=s.shift(),s.length){for(n=a[e]=t.widget.extend({},this.options[e]),o=0;s.length-1>o;o++)n[s[o]]=n[s[o]]||{},n=n[s[o]];if(e=s.pop(),1===arguments.length)return void 0===n[e]?null:n[e];n[e]=i}else{if(1===arguments.length)return void 0===this.options[e]?null:this.options[e];a[e]=i}return this._setOptions(a),this},_setOptions:function(t){var e;for(e in t)this._setOption(e,t[e]);return this},_setOption:function(t,e){return"classes"===t&&this._setOptionClasses(e),this.options[t]=e,"disabled"===t&&this._setOptionDisabled(e),this},_setOptionClasses:function(e){var i,s,n;for(i in e)n=this.classesElementLookup[i],e[i]!==this.options.classes[i]&&n&&n.length&&(s=t(n.get()),this._removeClass(n,i),s.addClass(this._classes({element:s,keys:i,classes:e,add:!0})))},_setOptionDisabled:function(t){this._toggleClass(this.widget(),this.widgetFullName+"-disabled",null,!!t),t&&(this._removeClass(this.hoverable,null,"ui-state-hover"),this._removeClass(this.focusable,null,"ui-state-focus"))},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_classes:function(e){function i(i,o){var a,r;for(r=0;i.length>r;r++)a=n.classesElementLookup[i[r]]||t(),a=e.add?t(t.unique(a.get().concat(e.element.get()))):t(a.not(e.element).get()),n.classesElementLookup[i[r]]=a,s.push(i[r]),o&&e.classes[i[r]]&&s.push(e.classes[i[r]])}var s=[],n=this;return e=t.extend({element:this.element,classes:this.options.classes||{}},e),this._on(e.element,{remove:"_untrackClassesElement"}),e.keys&&i(e.keys.match(/\S+/g)||[],!0),e.extra&&i(e.extra.match(/\S+/g)||[]),s.join(" ")},_untrackClassesElement:function(e){var i=this;t.each(i.classesElementLookup,function(s,n){-1!==t.inArray(e.target,n)&&(i.classesElementLookup[s]=t(n.not(e.target).get()))})},_removeClass:function(t,e,i){return this._toggleClass(t,e,i,!1)},_addClass:function(t,e,i){return this._toggleClass(t,e,i,!0)},_toggleClass:function(t,e,i,s){s="boolean"==typeof s?s:i;var n="string"==typeof t||null===t,o={extra:n?e:i,keys:n?t:e,element:n?this.element:t,add:s};return o.element.toggleClass(this._classes(o),s),this},_on:function(e,i,s){var n,o=this;"boolean"!=typeof e&&(s=i,i=e,e=!1),s?(i=n=t(i),this.bindings=this.bindings.add(i)):(s=i,i=this.element,n=this.widget()),t.each(s,function(s,a){function r(){return e||o.options.disabled!==!0&&!t(this).hasClass("ui-state-disabled")?("string"==typeof a?o[a]:a).apply(o,arguments):void 0}"string"!=typeof a&&(r.guid=a.guid=a.guid||r.guid||t.guid++);var h=s.match(/^([\w:-]*)\s*(.*)$/),l=h[1]+o.eventNamespace,c=h[2];c?n.on(l,c,r):i.on(l,r)})},_off:function(e,i){i=(i||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.off(i).off(i),this.bindings=t(this.bindings.not(e).get()),this.focusable=t(this.focusable.not(e).get()),this.hoverable=t(this.hoverable.not(e).get())},_delay:function(t,e){function i(){return("string"==typeof t?s[t]:t).apply(s,arguments)}var s=this;return setTimeout(i,e||0)},_hoverable:function(e){this.hoverable=this.hoverable.add(e),this._on(e,{mouseenter:function(e){this._addClass(t(e.currentTarget),null,"ui-state-hover")},mouseleave:function(e){this._removeClass(t(e.currentTarget),null,"ui-state-hover")}})},_focusable:function(e){this.focusable=this.focusable.add(e),this._on(e,{focusin:function(e){this._addClass(t(e.currentTarget),null,"ui-state-focus")},focusout:function(e){this._removeClass(t(e.currentTarget),null,"ui-state-focus")}})},_trigger:function(e,i,s){var n,o,a=this.options[e];if(s=s||{},i=t.Event(i),i.type=(e===this.widgetEventPrefix?e:this.widgetEventPrefix+e).toLowerCase(),i.target=this.element[0],o=i.originalEvent)for(n in o)n in i||(i[n]=o[n]);return this.element.trigger(i,s),!(t.isFunction(a)&&a.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},t.each({show:"fadeIn",hide:"fadeOut"},function(e,i){t.Widget.prototype["_"+e]=function(s,n,o){"string"==typeof n&&(n={effect:n});var a,r=n?n===!0||"number"==typeof n?i:n.effect||i:e;n=n||{},"number"==typeof n&&(n={duration:n}),a=!t.isEmptyObject(n),n.complete=o,n.delay&&s.delay(n.delay),a&&t.effects&&t.effects.effect[r]?s[e](n):r!==e&&s[r]?s[r](n.duration,n.easing,o):s.queue(function(i){t(this)[e](),o&&o.call(s[0]),i()})}}),t.widget,function(){function e(t,e,i){return[parseFloat(t[0])*(u.test(t[0])?e/100:1),parseFloat(t[1])*(u.test(t[1])?i/100:1)]}function i(e,i){return parseInt(t.css(e,i),10)||0}function s(e){var i=e[0];return 9===i.nodeType?{width:e.width(),height:e.height(),offset:{top:0,left:0}}:t.isWindow(i)?{width:e.width(),height:e.height(),offset:{top:e.scrollTop(),left:e.scrollLeft()}}:i.preventDefault?{width:0,height:0,offset:{top:i.pageY,left:i.pageX}}:{width:e.outerWidth(),height:e.outerHeight(),offset:e.offset()}}var n,o=Math.max,a=Math.abs,r=/left|center|right/,h=/top|center|bottom/,l=/[\+\-]\d+(\.[\d]+)?%?/,c=/^\w+/,u=/%$/,d=t.fn.position;t.position={scrollbarWidth:function(){if(void 0!==n)return n;var e,i,s=t("<div style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>"),o=s.children()[0];return t("body").append(s),e=o.offsetWidth,s.css("overflow","scroll"),i=o.offsetWidth,e===i&&(i=s[0].clientWidth),s.remove(),n=e-i},getScrollInfo:function(e){var i=e.isWindow||e.isDocument?"":e.element.css("overflow-x"),s=e.isWindow||e.isDocument?"":e.element.css("overflow-y"),n="scroll"===i||"auto"===i&&e.width<e.element[0].scrollWidth,o="scroll"===s||"auto"===s&&e.height<e.element[0].scrollHeight;return{width:o?t.position.scrollbarWidth():0,height:n?t.position.scrollbarWidth():0}},getWithinInfo:function(e){var i=t(e||window),s=t.isWindow(i[0]),n=!!i[0]&&9===i[0].nodeType,o=!s&&!n;return{element:i,isWindow:s,isDocument:n,offset:o?t(e).offset():{left:0,top:0},scrollLeft:i.scrollLeft(),scrollTop:i.scrollTop(),width:i.outerWidth(),height:i.outerHeight()}}},t.fn.position=function(n){if(!n||!n.of)return d.apply(this,arguments);n=t.extend({},n);var u,p,f,m,g,_,v=t(n.of),b=t.position.getWithinInfo(n.within),y=t.position.getScrollInfo(b),w=(n.collision||"flip").split(" "),x={};return _=s(v),v[0].preventDefault&&(n.at="left top"),p=_.width,f=_.height,m=_.offset,g=t.extend({},m),t.each(["my","at"],function(){var t,e,i=(n[this]||"").split(" ");1===i.length&&(i=r.test(i[0])?i.concat(["center"]):h.test(i[0])?["center"].concat(i):["center","center"]),i[0]=r.test(i[0])?i[0]:"center",i[1]=h.test(i[1])?i[1]:"center",t=l.exec(i[0]),e=l.exec(i[1]),x[this]=[t?t[0]:0,e?e[0]:0],n[this]=[c.exec(i[0])[0],c.exec(i[1])[0]]}),1===w.length&&(w[1]=w[0]),"right"===n.at[0]?g.left+=p:"center"===n.at[0]&&(g.left+=p/2),"bottom"===n.at[1]?g.top+=f:"center"===n.at[1]&&(g.top+=f/2),u=e(x.at,p,f),g.left+=u[0],g.top+=u[1],this.each(function(){var s,r,h=t(this),l=h.outerWidth(),c=h.outerHeight(),d=i(this,"marginLeft"),_=i(this,"marginTop"),k=l+d+i(this,"marginRight")+y.width,C=c+_+i(this,"marginBottom")+y.height,D=t.extend({},g),T=e(x.my,h.outerWidth(),h.outerHeight());"right"===n.my[0]?D.left-=l:"center"===n.my[0]&&(D.left-=l/2),"bottom"===n.my[1]?D.top-=c:"center"===n.my[1]&&(D.top-=c/2),D.left+=T[0],D.top+=T[1],s={marginLeft:d,marginTop:_},t.each(["left","top"],function(e,i){t.ui.position[w[e]]&&t.ui.position[w[e]][i](D,{targetWidth:p,targetHeight:f,elemWidth:l,elemHeight:c,collisionPosition:s,collisionWidth:k,collisionHeight:C,offset:[u[0]+T[0],u[1]+T[1]],my:n.my,at:n.at,within:b,elem:h})}),n.using&&(r=function(t){var e=m.left-D.left,i=e+p-l,s=m.top-D.top,r=s+f-c,u={target:{element:v,left:m.left,top:m.top,width:p,height:f},element:{element:h,left:D.left,top:D.top,width:l,height:c},horizontal:0>i?"left":e>0?"right":"center",vertical:0>r?"top":s>0?"bottom":"middle"};l>p&&p>a(e+i)&&(u.horizontal="center"),c>f&&f>a(s+r)&&(u.vertical="middle"),u.important=o(a(e),a(i))>o(a(s),a(r))?"horizontal":"vertical",n.using.call(this,t,u)}),h.offset(t.extend(D,{using:r}))})},t.ui.position={fit:{left:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollLeft:s.offset.left,a=s.width,r=t.left-e.collisionPosition.marginLeft,h=n-r,l=r+e.collisionWidth-a-n;e.collisionWidth>a?h>0&&0>=l?(i=t.left+h+e.collisionWidth-a-n,t.left+=h-i):t.left=l>0&&0>=h?n:h>l?n+a-e.collisionWidth:n:h>0?t.left+=h:l>0?t.left-=l:t.left=o(t.left-r,t.left)},top:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollTop:s.offset.top,a=e.within.height,r=t.top-e.collisionPosition.marginTop,h=n-r,l=r+e.collisionHeight-a-n;e.collisionHeight>a?h>0&&0>=l?(i=t.top+h+e.collisionHeight-a-n,t.top+=h-i):t.top=l>0&&0>=h?n:h>l?n+a-e.collisionHeight:n:h>0?t.top+=h:l>0?t.top-=l:t.top=o(t.top-r,t.top)}},flip:{left:function(t,e){var i,s,n=e.within,o=n.offset.left+n.scrollLeft,r=n.width,h=n.isWindow?n.scrollLeft:n.offset.left,l=t.left-e.collisionPosition.marginLeft,c=l-h,u=l+e.collisionWidth-r-h,d="left"===e.my[0]?-e.elemWidth:"right"===e.my[0]?e.elemWidth:0,p="left"===e.at[0]?e.targetWidth:"right"===e.at[0]?-e.targetWidth:0,f=-2*e.offset[0];0>c?(i=t.left+d+p+f+e.collisionWidth-r-o,(0>i||a(c)>i)&&(t.left+=d+p+f)):u>0&&(s=t.left-e.collisionPosition.marginLeft+d+p+f-h,(s>0||u>a(s))&&(t.left+=d+p+f))},top:function(t,e){var i,s,n=e.within,o=n.offset.top+n.scrollTop,r=n.height,h=n.isWindow?n.scrollTop:n.offset.top,l=t.top-e.collisionPosition.marginTop,c=l-h,u=l+e.collisionHeight-r-h,d="top"===e.my[1],p=d?-e.elemHeight:"bottom"===e.my[1]?e.elemHeight:0,f="top"===e.at[1]?e.targetHeight:"bottom"===e.at[1]?-e.targetHeight:0,m=-2*e.offset[1];0>c?(s=t.top+p+f+m+e.collisionHeight-r-o,(0>s||a(c)>s)&&(t.top+=p+f+m)):u>0&&(i=t.top-e.collisionPosition.marginTop+p+f+m-h,(i>0||u>a(i))&&(t.top+=p+f+m))}},flipfit:{left:function(){t.ui.position.flip.left.apply(this,arguments),t.ui.position.fit.left.apply(this,arguments)},top:function(){t.ui.position.flip.top.apply(this,arguments),t.ui.position.fit.top.apply(this,arguments)}}}}(),t.ui.position,t.extend(t.expr[":"],{data:t.expr.createPseudo?t.expr.createPseudo(function(e){return function(i){return!!t.data(i,e)}}):function(e,i,s){return!!t.data(e,s[3])}}),t.fn.extend({disableSelection:function(){var t="onselectstart"in document.createElement("div")?"selectstart":"mousedown";return function(){return this.on(t+".ui-disableSelection",function(t){t.preventDefault()})}}(),enableSelection:function(){return this.off(".ui-disableSelection")}}),t.ui.focusable=function(i,s){var n,o,a,r,h,l=i.nodeName.toLowerCase();return"area"===l?(n=i.parentNode,o=n.name,i.href&&o&&"map"===n.nodeName.toLowerCase()?(a=t("img[usemap='#"+o+"']"),a.length>0&&a.is(":visible")):!1):(/^(input|select|textarea|button|object)$/.test(l)?(r=!i.disabled,r&&(h=t(i).closest("fieldset")[0],h&&(r=!h.disabled))):r="a"===l?i.href||s:s,r&&t(i).is(":visible")&&e(t(i)))},t.extend(t.expr[":"],{focusable:function(e){return t.ui.focusable(e,null!=t.attr(e,"tabindex"))}}),t.ui.focusable,t.fn.form=function(){return"string"==typeof this[0].form?this.closest("form"):t(this[0].form)},t.ui.formResetMixin={_formResetHandler:function(){var e=t(this);setTimeout(function(){var i=e.data("ui-form-reset-instances");t.each(i,function(){this.refresh()})})},_bindFormResetHandler:function(){if(this.form=this.element.form(),this.form.length){var t=this.form.data("ui-form-reset-instances")||[];t.length||this.form.on("reset.ui-form-reset",this._formResetHandler),t.push(this),this.form.data("ui-form-reset-instances",t)}},_unbindFormResetHandler:function(){if(this.form.length){var e=this.form.data("ui-form-reset-instances");e.splice(t.inArray(this,e),1),e.length?this.form.data("ui-form-reset-instances",e):this.form.removeData("ui-form-reset-instances").off("reset.ui-form-reset")}}},"1.7"===t.fn.jquery.substring(0,3)&&(t.each(["Width","Height"],function(e,i){function s(e,i,s,o){return t.each(n,function(){i-=parseFloat(t.css(e,"padding"+this))||0,s&&(i-=parseFloat(t.css(e,"border"+this+"Width"))||0),o&&(i-=parseFloat(t.css(e,"margin"+this))||0)}),i}var n="Width"===i?["Left","Right"]:["Top","Bottom"],o=i.toLowerCase(),a={innerWidth:t.fn.innerWidth,innerHeight:t.fn.innerHeight,outerWidth:t.fn.outerWidth,outerHeight:t.fn.outerHeight};t.fn["inner"+i]=function(e){return void 0===e?a["inner"+i].call(this):this.each(function(){t(this).css(o,s(this,e)+"px")})},t.fn["outer"+i]=function(e,n){return"number"!=typeof e?a["outer"+i].call(this,e):this.each(function(){t(this).css(o,s(this,e,!0,n)+"px")})}}),t.fn.addBack=function(t){return this.add(null==t?this.prevObject:this.prevObject.filter(t))}),t.ui.keyCode={BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38},t.ui.escapeSelector=function(){var t=/([!"#$%&'()*+,./:;<=>?@[\]^`{|}~])/g;return function(e){return e.replace(t,"\\$1")}}(),t.fn.labels=function(){var e,i,s,n,o;return this[0].labels&&this[0].labels.length?this.pushStack(this[0].labels):(n=this.eq(0).parents("label"),s=this.attr("id"),s&&(e=this.eq(0).parents().last(),o=e.add(e.length?e.siblings():this.siblings()),i="label[for='"+t.ui.escapeSelector(s)+"']",n=n.add(o.find(i).addBack(i))),this.pushStack(n))},t.fn.scrollParent=function(e){var i=this.css("position"),s="absolute"===i,n=e?/(auto|scroll|hidden)/:/(auto|scroll)/,o=this.parents().filter(function(){var e=t(this);return s&&"static"===e.css("position")?!1:n.test(e.css("overflow")+e.css("overflow-y")+e.css("overflow-x"))}).eq(0);return"fixed"!==i&&o.length?o:t(this[0].ownerDocument||document)},t.extend(t.expr[":"],{tabbable:function(e){var i=t.attr(e,"tabindex"),s=null!=i;return(!s||i>=0)&&t.ui.focusable(e,s)}}),t.fn.extend({uniqueId:function(){var t=0;return function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++t)})}}(),removeUniqueId:function(){return this.each(function(){/^ui-id-\d+$/.test(this.id)&&t(this).removeAttr("id")})}}),t.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase());var n=!1;t(document).on("mouseup",function(){n=!1}),t.widget("ui.mouse",{version:"1.12.1",options:{cancel:"input, textarea, button, select, option",distance:1,delay:0},_mouseInit:function(){var e=this;this.element.on("mousedown."+this.widgetName,function(t){return e._mouseDown(t)}).on("click."+this.widgetName,function(i){return!0===t.data(i.target,e.widgetName+".preventClickEvent")?(t.removeData(i.target,e.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):void 0}),this.started=!1},_mouseDestroy:function(){this.element.off("."+this.widgetName),this._mouseMoveDelegate&&this.document.off("mousemove."+this.widgetName,this._mouseMoveDelegate).off("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(e){if(!n){this._mouseMoved=!1,this._mouseStarted&&this._mouseUp(e),this._mouseDownEvent=e;var i=this,s=1===e.which,o="string"==typeof this.options.cancel&&e.target.nodeName?t(e.target).closest(this.options.cancel).length:!1;return s&&!o&&this._mouseCapture(e)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){i.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(e)&&this._mouseDelayMet(e)&&(this._mouseStarted=this._mouseStart(e)!==!1,!this._mouseStarted)?(e.preventDefault(),!0):(!0===t.data(e.target,this.widgetName+".preventClickEvent")&&t.removeData(e.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(t){return i._mouseMove(t)},this._mouseUpDelegate=function(t){return i._mouseUp(t)},this.document.on("mousemove."+this.widgetName,this._mouseMoveDelegate).on("mouseup."+this.widgetName,this._mouseUpDelegate),e.preventDefault(),n=!0,!0)):!0}},_mouseMove:function(e){if(this._mouseMoved){if(t.ui.ie&&(!document.documentMode||9>document.documentMode)&&!e.button)return this._mouseUp(e);if(!e.which)if(e.originalEvent.altKey||e.originalEvent.ctrlKey||e.originalEvent.metaKey||e.originalEvent.shiftKey)this.ignoreMissingWhich=!0;else if(!this.ignoreMissingWhich)return this._mouseUp(e)}return(e.which||e.button)&&(this._mouseMoved=!0),this._mouseStarted?(this._mouseDrag(e),e.preventDefault()):(this._mouseDistanceMet(e)&&this._mouseDelayMet(e)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,e)!==!1,this._mouseStarted?this._mouseDrag(e):this._mouseUp(e)),!this._mouseStarted)},_mouseUp:function(e){this.document.off("mousemove."+this.widgetName,this._mouseMoveDelegate).off("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,e.target===this._mouseDownEvent.target&&t.data(e.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(e)),this._mouseDelayTimer&&(clearTimeout(this._mouseDelayTimer),delete this._mouseDelayTimer),this.ignoreMissingWhich=!1,n=!1,e.preventDefault()},_mouseDistanceMet:function(t){return Math.max(Math.abs(this._mouseDownEvent.pageX-t.pageX),Math.abs(this._mouseDownEvent.pageY-t.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}}),t.ui.plugin={add:function(e,i,s){var n,o=t.ui[e].prototype;for(n in s)o.plugins[n]=o.plugins[n]||[],o.plugins[n].push([i,s[n]])},call:function(t,e,i,s){var n,o=t.plugins[e];if(o&&(s||t.element[0].parentNode&&11!==t.element[0].parentNode.nodeType))for(n=0;o.length>n;n++)t.options[o[n][0]]&&o[n][1].apply(t.element,i)}},t.widget("ui.resizable",t.ui.mouse,{version:"1.12.1",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,classes:{"ui-resizable-se":"ui-icon ui-icon-gripsmall-diagonal-se"},containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_num:function(t){return parseFloat(t)||0},_isNumber:function(t){return!isNaN(parseFloat(t))},_hasScroll:function(e,i){if("hidden"===t(e).css("overflow"))return!1;var s=i&&"left"===i?"scrollLeft":"scrollTop",n=!1;return e[s]>0?!0:(e[s]=1,n=e[s]>0,e[s]=0,n)},_create:function(){var e,i=this.options,s=this;this._addClass("ui-resizable"),t.extend(this,{_aspectRatio:!!i.aspectRatio,aspectRatio:i.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:i.helper||i.ghost||i.animate?i.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/^(canvas|textarea|input|select|button|img)$/i)&&(this.element.wrap(t("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.resizable("instance")),this.elementIsWrapper=!0,e={marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom"),marginLeft:this.originalElement.css("marginLeft")},this.element.css(e),this.originalElement.css("margin",0),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css(e),this._proportionallyResize()),this._setupHandles(),i.autoHide&&t(this.element).on("mouseenter",function(){i.disabled||(s._removeClass("ui-resizable-autohide"),s._handles.show())}).on("mouseleave",function(){i.disabled||s.resizing||(s._addClass("ui-resizable-autohide"),s._handles.hide())}),this._mouseInit()},_destroy:function(){this._mouseDestroy();var e,i=function(e){t(e).removeData("resizable").removeData("ui-resizable").off(".resizable").find(".ui-resizable-handle").remove()};return this.elementIsWrapper&&(i(this.element),e=this.element,this.originalElement.css({position:e.css("position"),width:e.outerWidth(),height:e.outerHeight(),top:e.css("top"),left:e.css("left")}).insertAfter(e),e.remove()),this.originalElement.css("resize",this.originalResizeStyle),i(this.originalElement),this},_setOption:function(t,e){switch(this._super(t,e),t){case"handles":this._removeHandles(),this._setupHandles();break;default:}},_setupHandles:function(){var e,i,s,n,o,a=this.options,r=this;if(this.handles=a.handles||(t(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this._handles=t(),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),s=this.handles.split(","),this.handles={},i=0;s.length>i;i++)e=t.trim(s[i]),n="ui-resizable-"+e,o=t("<div>"),this._addClass(o,"ui-resizable-handle "+n),o.css({zIndex:a.zIndex}),this.handles[e]=".ui-resizable-"+e,this.element.append(o);this._renderAxis=function(e){var i,s,n,o;e=e||this.element;for(i in this.handles)this.handles[i].constructor===String?this.handles[i]=this.element.children(this.handles[i]).first().show():(this.handles[i].jquery||this.handles[i].nodeType)&&(this.handles[i]=t(this.handles[i]),this._on(this.handles[i],{mousedown:r._mouseDown})),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/^(textarea|input|select|button)$/i)&&(s=t(this.handles[i],this.element),o=/sw|ne|nw|se|n|s/.test(i)?s.outerHeight():s.outerWidth(),n=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join(""),e.css(n,o),this._proportionallyResize()),this._handles=this._handles.add(this.handles[i])},this._renderAxis(this.element),this._handles=this._handles.add(this.element.find(".ui-resizable-handle")),this._handles.disableSelection(),this._handles.on("mouseover",function(){r.resizing||(this.className&&(o=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),r.axis=o&&o[1]?o[1]:"se")}),a.autoHide&&(this._handles.hide(),this._addClass("ui-resizable-autohide"))},_removeHandles:function(){this._handles.remove()},_mouseCapture:function(e){var i,s,n=!1;for(i in this.handles)s=t(this.handles[i])[0],(s===e.target||t.contains(s,e.target))&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(e){var i,s,n,o=this.options,a=this.element;return this.resizing=!0,this._renderProxy(),i=this._num(this.helper.css("left")),s=this._num(this.helper.css("top")),o.containment&&(i+=t(o.containment).scrollLeft()||0,s+=t(o.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:i,top:s},this.size=this._helper?{width:this.helper.width(),height:this.helper.height()}:{width:a.width(),height:a.height()},this.originalSize=this._helper?{width:a.outerWidth(),height:a.outerHeight()}:{width:a.width(),height:a.height()},this.sizeDiff={width:a.outerWidth()-a.width(),height:a.outerHeight()-a.height()},this.originalPosition={left:i,top:s},this.originalMousePosition={left:e.pageX,top:e.pageY},this.aspectRatio="number"==typeof o.aspectRatio?o.aspectRatio:this.originalSize.width/this.originalSize.height||1,n=t(".ui-resizable-"+this.axis).css("cursor"),t("body").css("cursor","auto"===n?this.axis+"-resize":n),this._addClass("ui-resizable-resizing"),this._propagate("start",e),!0},_mouseDrag:function(e){var i,s,n=this.originalMousePosition,o=this.axis,a=e.pageX-n.left||0,r=e.pageY-n.top||0,h=this._change[o];return this._updatePrevProperties(),h?(i=h.apply(this,[e,a,r]),this._updateVirtualBoundaries(e.shiftKey),(this._aspectRatio||e.shiftKey)&&(i=this._updateRatio(i,e)),i=this._respectSize(i,e),this._updateCache(i),this._propagate("resize",e),s=this._applyChanges(),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),t.isEmptyObject(s)||(this._updatePrevProperties(),this._trigger("resize",e,this.ui()),this._applyChanges()),!1):!1},_mouseStop:function(e){this.resizing=!1;var i,s,n,o,a,r,h,l=this.options,c=this;return this._helper&&(i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),n=s&&this._hasScroll(i[0],"left")?0:c.sizeDiff.height,o=s?0:c.sizeDiff.width,a={width:c.helper.width()-o,height:c.helper.height()-n},r=parseFloat(c.element.css("left"))+(c.position.left-c.originalPosition.left)||null,h=parseFloat(c.element.css("top"))+(c.position.top-c.originalPosition.top)||null,l.animate||this.element.css(t.extend(a,{top:h,left:r})),c.helper.height(c.size.height),c.helper.width(c.size.width),this._helper&&!l.animate&&this._proportionallyResize()),t("body").css("cursor","auto"),this._removeClass("ui-resizable-resizing"),this._propagate("stop",e),this._helper&&this.helper.remove(),!1},_updatePrevProperties:function(){this.prevPosition={top:this.position.top,left:this.position.left},this.prevSize={width:this.size.width,height:this.size.height}},_applyChanges:function(){var t={};return this.position.top!==this.prevPosition.top&&(t.top=this.position.top+"px"),this.position.left!==this.prevPosition.left&&(t.left=this.position.left+"px"),this.size.width!==this.prevSize.width&&(t.width=this.size.width+"px"),this.size.height!==this.prevSize.height&&(t.height=this.size.height+"px"),this.helper.css(t),t},_updateVirtualBoundaries:function(t){var e,i,s,n,o,a=this.options;o={minWidth:this._isNumber(a.minWidth)?a.minWidth:0,maxWidth:this._isNumber(a.maxWidth)?a.maxWidth:1/0,minHeight:this._isNumber(a.minHeight)?a.minHeight:0,maxHeight:this._isNumber(a.maxHeight)?a.maxHeight:1/0},(this._aspectRatio||t)&&(e=o.minHeight*this.aspectRatio,s=o.minWidth/this.aspectRatio,i=o.maxHeight*this.aspectRatio,n=o.maxWidth/this.aspectRatio,e>o.minWidth&&(o.minWidth=e),s>o.minHeight&&(o.minHeight=s),o.maxWidth>i&&(o.maxWidth=i),o.maxHeight>n&&(o.maxHeight=n)),this._vBoundaries=o},_updateCache:function(t){this.offset=this.helper.offset(),this._isNumber(t.left)&&(this.position.left=t.left),this._isNumber(t.top)&&(this.position.top=t.top),this._isNumber(t.height)&&(this.size.height=t.height),this._isNumber(t.width)&&(this.size.width=t.width)},_updateRatio:function(t){var e=this.position,i=this.size,s=this.axis;return this._isNumber(t.height)?t.width=t.height*this.aspectRatio:this._isNumber(t.width)&&(t.height=t.width/this.aspectRatio),"sw"===s&&(t.left=e.left+(i.width-t.width),t.top=null),"nw"===s&&(t.top=e.top+(i.height-t.height),t.left=e.left+(i.width-t.width)),t},_respectSize:function(t){var e=this._vBoundaries,i=this.axis,s=this._isNumber(t.width)&&e.maxWidth&&e.maxWidth<t.width,n=this._isNumber(t.height)&&e.maxHeight&&e.maxHeight<t.height,o=this._isNumber(t.width)&&e.minWidth&&e.minWidth>t.width,a=this._isNumber(t.height)&&e.minHeight&&e.minHeight>t.height,r=this.originalPosition.left+this.originalSize.width,h=this.originalPosition.top+this.originalSize.height,l=/sw|nw|w/.test(i),c=/nw|ne|n/.test(i);return o&&(t.width=e.minWidth),a&&(t.height=e.minHeight),s&&(t.width=e.maxWidth),n&&(t.height=e.maxHeight),o&&l&&(t.left=r-e.minWidth),s&&l&&(t.left=r-e.maxWidth),a&&c&&(t.top=h-e.minHeight),n&&c&&(t.top=h-e.maxHeight),t.width||t.height||t.left||!t.top?t.width||t.height||t.top||!t.left||(t.left=null):t.top=null,t},_getPaddingPlusBorderDimensions:function(t){for(var e=0,i=[],s=[t.css("borderTopWidth"),t.css("borderRightWidth"),t.css("borderBottomWidth"),t.css("borderLeftWidth")],n=[t.css("paddingTop"),t.css("paddingRight"),t.css("paddingBottom"),t.css("paddingLeft")];4>e;e++)i[e]=parseFloat(s[e])||0,i[e]+=parseFloat(n[e])||0;return{height:i[0]+i[2],width:i[1]+i[3]}},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var t,e=0,i=this.helper||this.element;this._proportionallyResizeElements.length>e;e++)t=this._proportionallyResizeElements[e],this.outerDimensions||(this.outerDimensions=this._getPaddingPlusBorderDimensions(t)),t.css({height:i.height()-this.outerDimensions.height||0,width:i.width()-this.outerDimensions.width||0})},_renderProxy:function(){var e=this.element,i=this.options;this.elementOffset=e.offset(),this._helper?(this.helper=this.helper||t("<div style='overflow:hidden;'></div>"),this._addClass(this.helper,this._helper),this.helper.css({width:this.element.outerWidth(),height:this.element.outerHeight(),position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++i.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element
+},_change:{e:function(t,e){return{width:this.originalSize.width+e}},w:function(t,e){var i=this.originalSize,s=this.originalPosition;return{left:s.left+e,width:i.width-e}},n:function(t,e,i){var s=this.originalSize,n=this.originalPosition;return{top:n.top+i,height:s.height-i}},s:function(t,e,i){return{height:this.originalSize.height+i}},se:function(e,i,s){return t.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[e,i,s]))},sw:function(e,i,s){return t.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[e,i,s]))},ne:function(e,i,s){return t.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[e,i,s]))},nw:function(e,i,s){return t.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[e,i,s]))}},_propagate:function(e,i){t.ui.plugin.call(this,e,[i,this.ui()]),"resize"!==e&&this._trigger(e,i,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),t.ui.plugin.add("resizable","animate",{stop:function(e){var i=t(this).resizable("instance"),s=i.options,n=i._proportionallyResizeElements,o=n.length&&/textarea/i.test(n[0].nodeName),a=o&&i._hasScroll(n[0],"left")?0:i.sizeDiff.height,r=o?0:i.sizeDiff.width,h={width:i.size.width-r,height:i.size.height-a},l=parseFloat(i.element.css("left"))+(i.position.left-i.originalPosition.left)||null,c=parseFloat(i.element.css("top"))+(i.position.top-i.originalPosition.top)||null;i.element.animate(t.extend(h,c&&l?{top:c,left:l}:{}),{duration:s.animateDuration,easing:s.animateEasing,step:function(){var s={width:parseFloat(i.element.css("width")),height:parseFloat(i.element.css("height")),top:parseFloat(i.element.css("top")),left:parseFloat(i.element.css("left"))};n&&n.length&&t(n[0]).css({width:s.width,height:s.height}),i._updateCache(s),i._propagate("resize",e)}})}}),t.ui.plugin.add("resizable","containment",{start:function(){var e,i,s,n,o,a,r,h=t(this).resizable("instance"),l=h.options,c=h.element,u=l.containment,d=u instanceof t?u.get(0):/parent/.test(u)?c.parent().get(0):u;d&&(h.containerElement=t(d),/document/.test(u)||u===document?(h.containerOffset={left:0,top:0},h.containerPosition={left:0,top:0},h.parentData={element:t(document),left:0,top:0,width:t(document).width(),height:t(document).height()||document.body.parentNode.scrollHeight}):(e=t(d),i=[],t(["Top","Right","Left","Bottom"]).each(function(t,s){i[t]=h._num(e.css("padding"+s))}),h.containerOffset=e.offset(),h.containerPosition=e.position(),h.containerSize={height:e.innerHeight()-i[3],width:e.innerWidth()-i[1]},s=h.containerOffset,n=h.containerSize.height,o=h.containerSize.width,a=h._hasScroll(d,"left")?d.scrollWidth:o,r=h._hasScroll(d)?d.scrollHeight:n,h.parentData={element:d,left:s.left,top:s.top,width:a,height:r}))},resize:function(e){var i,s,n,o,a=t(this).resizable("instance"),r=a.options,h=a.containerOffset,l=a.position,c=a._aspectRatio||e.shiftKey,u={top:0,left:0},d=a.containerElement,p=!0;d[0]!==document&&/static/.test(d.css("position"))&&(u=h),l.left<(a._helper?h.left:0)&&(a.size.width=a.size.width+(a._helper?a.position.left-h.left:a.position.left-u.left),c&&(a.size.height=a.size.width/a.aspectRatio,p=!1),a.position.left=r.helper?h.left:0),l.top<(a._helper?h.top:0)&&(a.size.height=a.size.height+(a._helper?a.position.top-h.top:a.position.top),c&&(a.size.width=a.size.height*a.aspectRatio,p=!1),a.position.top=a._helper?h.top:0),n=a.containerElement.get(0)===a.element.parent().get(0),o=/relative|absolute/.test(a.containerElement.css("position")),n&&o?(a.offset.left=a.parentData.left+a.position.left,a.offset.top=a.parentData.top+a.position.top):(a.offset.left=a.element.offset().left,a.offset.top=a.element.offset().top),i=Math.abs(a.sizeDiff.width+(a._helper?a.offset.left-u.left:a.offset.left-h.left)),s=Math.abs(a.sizeDiff.height+(a._helper?a.offset.top-u.top:a.offset.top-h.top)),i+a.size.width>=a.parentData.width&&(a.size.width=a.parentData.width-i,c&&(a.size.height=a.size.width/a.aspectRatio,p=!1)),s+a.size.height>=a.parentData.height&&(a.size.height=a.parentData.height-s,c&&(a.size.width=a.size.height*a.aspectRatio,p=!1)),p||(a.position.left=a.prevPosition.left,a.position.top=a.prevPosition.top,a.size.width=a.prevSize.width,a.size.height=a.prevSize.height)},stop:function(){var e=t(this).resizable("instance"),i=e.options,s=e.containerOffset,n=e.containerPosition,o=e.containerElement,a=t(e.helper),r=a.offset(),h=a.outerWidth()-e.sizeDiff.width,l=a.outerHeight()-e.sizeDiff.height;e._helper&&!i.animate&&/relative/.test(o.css("position"))&&t(this).css({left:r.left-n.left-s.left,width:h,height:l}),e._helper&&!i.animate&&/static/.test(o.css("position"))&&t(this).css({left:r.left-n.left-s.left,width:h,height:l})}}),t.ui.plugin.add("resizable","alsoResize",{start:function(){var e=t(this).resizable("instance"),i=e.options;t(i.alsoResize).each(function(){var e=t(this);e.data("ui-resizable-alsoresize",{width:parseFloat(e.width()),height:parseFloat(e.height()),left:parseFloat(e.css("left")),top:parseFloat(e.css("top"))})})},resize:function(e,i){var s=t(this).resizable("instance"),n=s.options,o=s.originalSize,a=s.originalPosition,r={height:s.size.height-o.height||0,width:s.size.width-o.width||0,top:s.position.top-a.top||0,left:s.position.left-a.left||0};t(n.alsoResize).each(function(){var e=t(this),s=t(this).data("ui-resizable-alsoresize"),n={},o=e.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];t.each(o,function(t,e){var i=(s[e]||0)+(r[e]||0);i&&i>=0&&(n[e]=i||null)}),e.css(n)})},stop:function(){t(this).removeData("ui-resizable-alsoresize")}}),t.ui.plugin.add("resizable","ghost",{start:function(){var e=t(this).resizable("instance"),i=e.size;e.ghost=e.originalElement.clone(),e.ghost.css({opacity:.25,display:"block",position:"relative",height:i.height,width:i.width,margin:0,left:0,top:0}),e._addClass(e.ghost,"ui-resizable-ghost"),t.uiBackCompat!==!1&&"string"==typeof e.options.ghost&&e.ghost.addClass(this.options.ghost),e.ghost.appendTo(e.helper)},resize:function(){var e=t(this).resizable("instance");e.ghost&&e.ghost.css({position:"relative",height:e.size.height,width:e.size.width})},stop:function(){var e=t(this).resizable("instance");e.ghost&&e.helper&&e.helper.get(0).removeChild(e.ghost.get(0))}}),t.ui.plugin.add("resizable","grid",{resize:function(){var e,i=t(this).resizable("instance"),s=i.options,n=i.size,o=i.originalSize,a=i.originalPosition,r=i.axis,h="number"==typeof s.grid?[s.grid,s.grid]:s.grid,l=h[0]||1,c=h[1]||1,u=Math.round((n.width-o.width)/l)*l,d=Math.round((n.height-o.height)/c)*c,p=o.width+u,f=o.height+d,m=s.maxWidth&&p>s.maxWidth,g=s.maxHeight&&f>s.maxHeight,_=s.minWidth&&s.minWidth>p,v=s.minHeight&&s.minHeight>f;s.grid=h,_&&(p+=l),v&&(f+=c),m&&(p-=l),g&&(f-=c),/^(se|s|e)$/.test(r)?(i.size.width=p,i.size.height=f):/^(ne)$/.test(r)?(i.size.width=p,i.size.height=f,i.position.top=a.top-d):/^(sw)$/.test(r)?(i.size.width=p,i.size.height=f,i.position.left=a.left-u):((0>=f-c||0>=p-l)&&(e=i._getPaddingPlusBorderDimensions(this)),f-c>0?(i.size.height=f,i.position.top=a.top-d):(f=c-e.height,i.size.height=f,i.position.top=a.top+o.height-f),p-l>0?(i.size.width=p,i.position.left=a.left-u):(p=l-e.width,i.size.width=p,i.position.left=a.left+o.width-p))}}),t.ui.resizable});/**
+ * Copyright (c) 2007 Ariel Flesler - aflesler â—‹ gmail • com | https://github.com/flesler
+ * Licensed under MIT
+ * @author Ariel Flesler
+ * @version 2.1.2
+ */
+;(function(f){"use strict";"function"===typeof define&&define.amd?define(["jquery"],f):"undefined"!==typeof module&&module.exports?module.exports=f(require("jquery")):f(jQuery)})(function($){"use strict";function n(a){return!a.nodeName||-1!==$.inArray(a.nodeName.toLowerCase(),["iframe","#document","html","body"])}function h(a){return $.isFunction(a)||$.isPlainObject(a)?a:{top:a,left:a}}var p=$.scrollTo=function(a,d,b){return $(window).scrollTo(a,d,b)};p.defaults={axis:"xy",duration:0,limit:!0};$.fn.scrollTo=function(a,d,b){"object"=== typeof d&&(b=d,d=0);"function"===typeof b&&(b={onAfter:b});"max"===a&&(a=9E9);b=$.extend({},p.defaults,b);d=d||b.duration;var u=b.queue&&1<b.axis.length;u&&(d/=2);b.offset=h(b.offset);b.over=h(b.over);return this.each(function(){function k(a){var k=$.extend({},b,{queue:!0,duration:d,complete:a&&function(){a.call(q,e,b)}});r.animate(f,k)}if(null!==a){var l=n(this),q=l?this.contentWindow||window:this,r=$(q),e=a,f={},t;switch(typeof e){case "number":case "string":if(/^([+-]=?)?\d+(\.\d+)?(px|%)?$/.test(e)){e= h(e);break}e=l?$(e):$(e,q);case "object":if(e.length===0)return;if(e.is||e.style)t=(e=$(e)).offset()}var v=$.isFunction(b.offset)&&b.offset(q,e)||b.offset;$.each(b.axis.split(""),function(a,c){var d="x"===c?"Left":"Top",m=d.toLowerCase(),g="scroll"+d,h=r[g](),n=p.max(q,c);t?(f[g]=t[m]+(l?0:h-r.offset()[m]),b.margin&&(f[g]-=parseInt(e.css("margin"+d),10)||0,f[g]-=parseInt(e.css("border"+d+"Width"),10)||0),f[g]+=v[m]||0,b.over[m]&&(f[g]+=e["x"===c?"width":"height"]()*b.over[m])):(d=e[m],f[g]=d.slice&& "%"===d.slice(-1)?parseFloat(d)/100*n:d);b.limit&&/^\d+$/.test(f[g])&&(f[g]=0>=f[g]?0:Math.min(f[g],n));!a&&1<b.axis.length&&(h===f[g]?f={}:u&&(k(b.onAfterFirst),f={}))});k(b.onAfter)}})};p.max=function(a,d){var b="x"===d?"Width":"Height",h="scroll"+b;if(!n(a))return a[h]-$(a)[b.toLowerCase()]();var b="client"+b,k=a.ownerDocument||a.document,l=k.documentElement,k=k.body;return Math.max(l[h],k[h])-Math.min(l[b],k[b])};$.Tween.propHooks.scrollLeft=$.Tween.propHooks.scrollTop={get:function(a){return $(a.elem)[a.prop]()}, set:function(a){var d=this.get(a);if(a.options.interrupt&&a._last&&a._last!==d)return $(a.elem).stop();var b=Math.round(a.now);d!==b&&($(a.elem)[a.prop](b),a._last=this.get(a))}};return p});
+/*!
+ PowerTip v1.3.1 (2018-04-15)
+ https://stevenbenner.github.io/jquery-powertip/
+ Copyright (c) 2018 Steven Benner (http://stevenbenner.com/).
+ Released under MIT license.
+ https://raw.github.com/stevenbenner/jquery-powertip/master/LICENSE.txt
+*/
+(function(root,factory){if(typeof define==="function"&&define.amd){define(["jquery"],factory)}else if(typeof module==="object"&&module.exports){module.exports=factory(require("jquery"))}else{factory(root.jQuery)}})(this,function($){var $document=$(document),$window=$(window),$body=$("body");var DATA_DISPLAYCONTROLLER="displayController",DATA_HASACTIVEHOVER="hasActiveHover",DATA_FORCEDOPEN="forcedOpen",DATA_HASMOUSEMOVE="hasMouseMove",DATA_MOUSEONTOTIP="mouseOnToPopup",DATA_ORIGINALTITLE="originalTitle",DATA_POWERTIP="powertip",DATA_POWERTIPJQ="powertipjq",DATA_POWERTIPTARGET="powertiptarget",EVENT_NAMESPACE=".powertip",RAD2DEG=180/Math.PI,MOUSE_EVENTS=["click","dblclick","mousedown","mouseup","mousemove","mouseover","mouseout","mouseenter","mouseleave","contextmenu"];var session={tooltips:null,isTipOpen:false,isFixedTipOpen:false,isClosing:false,tipOpenImminent:false,activeHover:null,currentX:0,currentY:0,previousX:0,previousY:0,desyncTimeout:null,closeDelayTimeout:null,mouseTrackingActive:false,delayInProgress:false,windowWidth:0,windowHeight:0,scrollTop:0,scrollLeft:0};var Collision={none:0,top:1,bottom:2,left:4,right:8};$.fn.powerTip=function(opts,arg){var targetElements=this,options,tipController;if(!targetElements.length){return targetElements}if($.type(opts)==="string"&&$.powerTip[opts]){return $.powerTip[opts].call(targetElements,targetElements,arg)}options=$.extend({},$.fn.powerTip.defaults,opts);tipController=new TooltipController(options);initTracking();targetElements.each(function elementSetup(){var $this=$(this),dataPowertip=$this.data(DATA_POWERTIP),dataElem=$this.data(DATA_POWERTIPJQ),dataTarget=$this.data(DATA_POWERTIPTARGET),title=$this.attr("title");if(!dataPowertip&&!dataTarget&&!dataElem&&title){$this.data(DATA_POWERTIP,title);$this.data(DATA_ORIGINALTITLE,title);$this.removeAttr("title")}$this.data(DATA_DISPLAYCONTROLLER,new DisplayController($this,options,tipController))});if(!options.manual){$.each(options.openEvents,function(idx,evt){if($.inArray(evt,options.closeEvents)>-1){targetElements.on(evt+EVENT_NAMESPACE,function elementToggle(event){$.powerTip.toggle(this,event)})}else{targetElements.on(evt+EVENT_NAMESPACE,function elementOpen(event){$.powerTip.show(this,event)})}});$.each(options.closeEvents,function(idx,evt){if($.inArray(evt,options.openEvents)<0){targetElements.on(evt+EVENT_NAMESPACE,function elementClose(event){$.powerTip.hide(this,!isMouseEvent(event))})}});targetElements.on("keydown"+EVENT_NAMESPACE,function elementKeyDown(event){if(event.keyCode===27){$.powerTip.hide(this,true)}})}return targetElements};$.fn.powerTip.defaults={fadeInTime:200,fadeOutTime:100,followMouse:false,popupId:"powerTip",popupClass:null,intentSensitivity:7,intentPollInterval:100,closeDelay:100,placement:"n",smartPlacement:false,offset:10,mouseOnToPopup:false,manual:false,openEvents:["mouseenter","focus"],closeEvents:["mouseleave","blur"]};$.fn.powerTip.smartPlacementLists={n:["n","ne","nw","s"],e:["e","ne","se","w","nw","sw","n","s","e"],s:["s","se","sw","n"],w:["w","nw","sw","e","ne","se","n","s","w"],nw:["nw","w","sw","n","s","se","nw"],ne:["ne","e","se","n","s","sw","ne"],sw:["sw","w","nw","s","n","ne","sw"],se:["se","e","ne","s","n","nw","se"],"nw-alt":["nw-alt","n","ne-alt","sw-alt","s","se-alt","w","e"],"ne-alt":["ne-alt","n","nw-alt","se-alt","s","sw-alt","e","w"],"sw-alt":["sw-alt","s","se-alt","nw-alt","n","ne-alt","w","e"],"se-alt":["se-alt","s","sw-alt","ne-alt","n","nw-alt","e","w"]};$.powerTip={show:function apiShowTip(element,event){if(isMouseEvent(event)){trackMouse(event);session.previousX=event.pageX;session.previousY=event.pageY;$(element).data(DATA_DISPLAYCONTROLLER).show()}else{$(element).first().data(DATA_DISPLAYCONTROLLER).show(true,true)}return element},reposition:function apiResetPosition(element){$(element).first().data(DATA_DISPLAYCONTROLLER).resetPosition();return element},hide:function apiCloseTip(element,immediate){var displayController;immediate=element?immediate:true;if(element){displayController=$(element).first().data(DATA_DISPLAYCONTROLLER)}else if(session.activeHover){displayController=session.activeHover.data(DATA_DISPLAYCONTROLLER)}if(displayController){displayController.hide(immediate)}return element},toggle:function apiToggle(element,event){if(session.activeHover&&session.activeHover.is(element)){$.powerTip.hide(element,!isMouseEvent(event))}else{$.powerTip.show(element,event)}return element}};$.powerTip.showTip=$.powerTip.show;$.powerTip.closeTip=$.powerTip.hide;function CSSCoordinates(){var me=this;me.top="auto";me.left="auto";me.right="auto";me.bottom="auto";me.set=function(property,value){if($.isNumeric(value)){me[property]=Math.round(value)}}}function DisplayController(element,options,tipController){var hoverTimer=null,myCloseDelay=null;function openTooltip(immediate,forceOpen){cancelTimer();if(!element.data(DATA_HASACTIVEHOVER)){if(!immediate){session.tipOpenImminent=true;hoverTimer=setTimeout(function intentDelay(){hoverTimer=null;checkForIntent()},options.intentPollInterval)}else{if(forceOpen){element.data(DATA_FORCEDOPEN,true)}closeAnyDelayed();tipController.showTip(element)}}else{cancelClose()}}function closeTooltip(disableDelay){if(myCloseDelay){myCloseDelay=session.closeDelayTimeout=clearTimeout(myCloseDelay);session.delayInProgress=false}cancelTimer();session.tipOpenImminent=false;if(element.data(DATA_HASACTIVEHOVER)){element.data(DATA_FORCEDOPEN,false);if(!disableDelay){session.delayInProgress=true;session.closeDelayTimeout=setTimeout(function closeDelay(){session.closeDelayTimeout=null;tipController.hideTip(element);session.delayInProgress=false;myCloseDelay=null},options.closeDelay);myCloseDelay=session.closeDelayTimeout}else{tipController.hideTip(element)}}}function checkForIntent(){var xDifference=Math.abs(session.previousX-session.currentX),yDifference=Math.abs(session.previousY-session.currentY),totalDifference=xDifference+yDifference;if(totalDifference<options.intentSensitivity){cancelClose();closeAnyDelayed();tipController.showTip(element)}else{session.previousX=session.currentX;session.previousY=session.currentY;openTooltip()}}function cancelTimer(stopClose){hoverTimer=clearTimeout(hoverTimer);if(session.closeDelayTimeout&&myCloseDelay===session.closeDelayTimeout||stopClose){cancelClose()}}function cancelClose(){session.closeDelayTimeout=clearTimeout(session.closeDelayTimeout);session.delayInProgress=false}function closeAnyDelayed(){if(session.delayInProgress&&session.activeHover&&!session.activeHover.is(element)){session.activeHover.data(DATA_DISPLAYCONTROLLER).hide(true)}}function repositionTooltip(){tipController.resetPosition(element)}this.show=openTooltip;this.hide=closeTooltip;this.cancel=cancelTimer;this.resetPosition=repositionTooltip}function PlacementCalculator(){function computePlacementCoords(element,placement,tipWidth,tipHeight,offset){var placementBase=placement.split("-")[0],coords=new CSSCoordinates,position;if(isSvgElement(element)){position=getSvgPlacement(element,placementBase)}else{position=getHtmlPlacement(element,placementBase)}switch(placement){case"n":coords.set("left",position.left-tipWidth/2);coords.set("bottom",session.windowHeight-position.top+offset);break;case"e":coords.set("left",position.left+offset);coords.set("top",position.top-tipHeight/2);break;case"s":coords.set("left",position.left-tipWidth/2);coords.set("top",position.top+offset);break;case"w":coords.set("top",position.top-tipHeight/2);coords.set("right",session.windowWidth-position.left+offset);break;case"nw":coords.set("bottom",session.windowHeight-position.top+offset);coords.set("right",session.windowWidth-position.left-20);break;case"nw-alt":coords.set("left",position.left);coords.set("bottom",session.windowHeight-position.top+offset);break;case"ne":coords.set("left",position.left-20);coords.set("bottom",session.windowHeight-position.top+offset);break;case"ne-alt":coords.set("bottom",session.windowHeight-position.top+offset);coords.set("right",session.windowWidth-position.left);break;case"sw":coords.set("top",position.top+offset);coords.set("right",session.windowWidth-position.left-20);break;case"sw-alt":coords.set("left",position.left);coords.set("top",position.top+offset);break;case"se":coords.set("left",position.left-20);coords.set("top",position.top+offset);break;case"se-alt":coords.set("top",position.top+offset);coords.set("right",session.windowWidth-position.left);break}return coords}function getHtmlPlacement(element,placement){var objectOffset=element.offset(),objectWidth=element.outerWidth(),objectHeight=element.outerHeight(),left,top;switch(placement){case"n":left=objectOffset.left+objectWidth/2;top=objectOffset.top;break;case"e":left=objectOffset.left+objectWidth;top=objectOffset.top+objectHeight/2;break;case"s":left=objectOffset.left+objectWidth/2;top=objectOffset.top+objectHeight;break;case"w":left=objectOffset.left;top=objectOffset.top+objectHeight/2;break;case"nw":left=objectOffset.left;top=objectOffset.top;break;case"ne":left=objectOffset.left+objectWidth;top=objectOffset.top;break;case"sw":left=objectOffset.left;top=objectOffset.top+objectHeight;break;case"se":left=objectOffset.left+objectWidth;top=objectOffset.top+objectHeight;break}return{top:top,left:left}}function getSvgPlacement(element,placement){var svgElement=element.closest("svg")[0],domElement=element[0],point=svgElement.createSVGPoint(),boundingBox=domElement.getBBox(),matrix=domElement.getScreenCTM(),halfWidth=boundingBox.width/2,halfHeight=boundingBox.height/2,placements=[],placementKeys=["nw","n","ne","e","se","s","sw","w"],coords,rotation,steps,x;function pushPlacement(){placements.push(point.matrixTransform(matrix))}point.x=boundingBox.x;point.y=boundingBox.y;pushPlacement();point.x+=halfWidth;pushPlacement();point.x+=halfWidth;pushPlacement();point.y+=halfHeight;pushPlacement();point.y+=halfHeight;pushPlacement();point.x-=halfWidth;pushPlacement();point.x-=halfWidth;pushPlacement();point.y-=halfHeight;pushPlacement();if(placements[0].y!==placements[1].y||placements[0].x!==placements[7].x){rotation=Math.atan2(matrix.b,matrix.a)*RAD2DEG;steps=Math.ceil((rotation%360-22.5)/45);if(steps<1){steps+=8}while(steps--){placementKeys.push(placementKeys.shift())}}for(x=0;x<placements.length;x++){if(placementKeys[x]===placement){coords=placements[x];break}}return{top:coords.y+session.scrollTop,left:coords.x+session.scrollLeft}}this.compute=computePlacementCoords}function TooltipController(options){var placementCalculator=new PlacementCalculator,tipElement=$("#"+options.popupId);if(tipElement.length===0){tipElement=$("<div/>",{id:options.popupId});if($body.length===0){$body=$("body")}$body.append(tipElement);session.tooltips=session.tooltips?session.tooltips.add(tipElement):tipElement}if(options.followMouse){if(!tipElement.data(DATA_HASMOUSEMOVE)){$document.on("mousemove"+EVENT_NAMESPACE,positionTipOnCursor);$window.on("scroll"+EVENT_NAMESPACE,positionTipOnCursor);tipElement.data(DATA_HASMOUSEMOVE,true)}}function beginShowTip(element){element.data(DATA_HASACTIVEHOVER,true);tipElement.queue(function queueTipInit(next){showTip(element);next()})}function showTip(element){var tipContent;if(!element.data(DATA_HASACTIVEHOVER)){return}if(session.isTipOpen){if(!session.isClosing){hideTip(session.activeHover)}tipElement.delay(100).queue(function queueTipAgain(next){showTip(element);next()});return}element.trigger("powerTipPreRender");tipContent=getTooltipContent(element);if(tipContent){tipElement.empty().append(tipContent)}else{return}element.trigger("powerTipRender");session.activeHover=element;session.isTipOpen=true;tipElement.data(DATA_MOUSEONTOTIP,options.mouseOnToPopup);tipElement.addClass(options.popupClass);if(!options.followMouse||element.data(DATA_FORCEDOPEN)){positionTipOnElement(element);session.isFixedTipOpen=true}else{positionTipOnCursor()}if(!element.data(DATA_FORCEDOPEN)&&!options.followMouse){$document.on("click"+EVENT_NAMESPACE,function documentClick(event){var target=event.target;if(target!==element[0]){if(options.mouseOnToPopup){if(target!==tipElement[0]&&!$.contains(tipElement[0],target)){$.powerTip.hide()}}else{$.powerTip.hide()}}})}if(options.mouseOnToPopup&&!options.manual){tipElement.on("mouseenter"+EVENT_NAMESPACE,function tipMouseEnter(){if(session.activeHover){session.activeHover.data(DATA_DISPLAYCONTROLLER).cancel()}});tipElement.on("mouseleave"+EVENT_NAMESPACE,function tipMouseLeave(){if(session.activeHover){session.activeHover.data(DATA_DISPLAYCONTROLLER).hide()}})}tipElement.fadeIn(options.fadeInTime,function fadeInCallback(){if(!session.desyncTimeout){session.desyncTimeout=setInterval(closeDesyncedTip,500)}element.trigger("powerTipOpen")})}function hideTip(element){session.isClosing=true;session.isTipOpen=false;session.desyncTimeout=clearInterval(session.desyncTimeout);element.data(DATA_HASACTIVEHOVER,false);element.data(DATA_FORCEDOPEN,false);$document.off("click"+EVENT_NAMESPACE);tipElement.off(EVENT_NAMESPACE);tipElement.fadeOut(options.fadeOutTime,function fadeOutCallback(){var coords=new CSSCoordinates;session.activeHover=null;session.isClosing=false;session.isFixedTipOpen=false;tipElement.removeClass();coords.set("top",session.currentY+options.offset);coords.set("left",session.currentX+options.offset);tipElement.css(coords);element.trigger("powerTipClose")})}function positionTipOnCursor(){var tipWidth,tipHeight,coords,collisions,collisionCount;if(!session.isFixedTipOpen&&(session.isTipOpen||session.tipOpenImminent&&tipElement.data(DATA_HASMOUSEMOVE))){tipWidth=tipElement.outerWidth();tipHeight=tipElement.outerHeight();coords=new CSSCoordinates;coords.set("top",session.currentY+options.offset);coords.set("left",session.currentX+options.offset);collisions=getViewportCollisions(coords,tipWidth,tipHeight);if(collisions!==Collision.none){collisionCount=countFlags(collisions);if(collisionCount===1){if(collisions===Collision.right){coords.set("left",session.scrollLeft+session.windowWidth-tipWidth)}else if(collisions===Collision.bottom){coords.set("top",session.scrollTop+session.windowHeight-tipHeight)}}else{coords.set("left",session.currentX-tipWidth-options.offset);coords.set("top",session.currentY-tipHeight-options.offset)}}tipElement.css(coords)}}function positionTipOnElement(element){var priorityList,finalPlacement;if(options.smartPlacement||options.followMouse&&element.data(DATA_FORCEDOPEN)){priorityList=$.fn.powerTip.smartPlacementLists[options.placement];$.each(priorityList,function(idx,pos){var collisions=getViewportCollisions(placeTooltip(element,pos),tipElement.outerWidth(),tipElement.outerHeight());finalPlacement=pos;return collisions!==Collision.none})}else{placeTooltip(element,options.placement);finalPlacement=options.placement}tipElement.removeClass("w nw sw e ne se n s w se-alt sw-alt ne-alt nw-alt");tipElement.addClass(finalPlacement)}function placeTooltip(element,placement){var iterationCount=0,tipWidth,tipHeight,coords=new CSSCoordinates;coords.set("top",0);coords.set("left",0);tipElement.css(coords);do{tipWidth=tipElement.outerWidth();tipHeight=tipElement.outerHeight();coords=placementCalculator.compute(element,placement,tipWidth,tipHeight,options.offset);tipElement.css(coords)}while(++iterationCount<=5&&(tipWidth!==tipElement.outerWidth()||tipHeight!==tipElement.outerHeight()));return coords}function closeDesyncedTip(){var isDesynced=false,hasDesyncableCloseEvent=$.grep(["mouseleave","mouseout","blur","focusout"],function(eventType){return $.inArray(eventType,options.closeEvents)!==-1}).length>0;if(session.isTipOpen&&!session.isClosing&&!session.delayInProgress&&hasDesyncableCloseEvent){if(session.activeHover.data(DATA_HASACTIVEHOVER)===false||session.activeHover.is(":disabled")){isDesynced=true}else if(!isMouseOver(session.activeHover)&&!session.activeHover.is(":focus")&&!session.activeHover.data(DATA_FORCEDOPEN)){if(tipElement.data(DATA_MOUSEONTOTIP)){if(!isMouseOver(tipElement)){isDesynced=true}}else{isDesynced=true}}if(isDesynced){hideTip(session.activeHover)}}}this.showTip=beginShowTip;this.hideTip=hideTip;this.resetPosition=positionTipOnElement}function isSvgElement(element){return Boolean(window.SVGElement&&element[0]instanceof SVGElement)}function isMouseEvent(event){return Boolean(event&&$.inArray(event.type,MOUSE_EVENTS)>-1&&typeof event.pageX==="number")}function initTracking(){if(!session.mouseTrackingActive){session.mouseTrackingActive=true;getViewportDimensions();$(getViewportDimensions);$document.on("mousemove"+EVENT_NAMESPACE,trackMouse);$window.on("resize"+EVENT_NAMESPACE,trackResize);$window.on("scroll"+EVENT_NAMESPACE,trackScroll)}}function getViewportDimensions(){session.scrollLeft=$window.scrollLeft();session.scrollTop=$window.scrollTop();session.windowWidth=$window.width();session.windowHeight=$window.height()}function trackResize(){session.windowWidth=$window.width();session.windowHeight=$window.height()}function trackScroll(){var x=$window.scrollLeft(),y=$window.scrollTop();if(x!==session.scrollLeft){session.currentX+=x-session.scrollLeft;session.scrollLeft=x}if(y!==session.scrollTop){session.currentY+=y-session.scrollTop;session.scrollTop=y}}function trackMouse(event){session.currentX=event.pageX;session.currentY=event.pageY}function isMouseOver(element){var elementPosition=element.offset(),elementBox=element[0].getBoundingClientRect(),elementWidth=elementBox.right-elementBox.left,elementHeight=elementBox.bottom-elementBox.top;return session.currentX>=elementPosition.left&&session.currentX<=elementPosition.left+elementWidth&&session.currentY>=elementPosition.top&&session.currentY<=elementPosition.top+elementHeight}function getTooltipContent(element){var tipText=element.data(DATA_POWERTIP),tipObject=element.data(DATA_POWERTIPJQ),tipTarget=element.data(DATA_POWERTIPTARGET),targetElement,content;if(tipText){if($.isFunction(tipText)){tipText=tipText.call(element[0])}content=tipText}else if(tipObject){if($.isFunction(tipObject)){tipObject=tipObject.call(element[0])}if(tipObject.length>0){content=tipObject.clone(true,true)}}else if(tipTarget){targetElement=$("#"+tipTarget);if(targetElement.length>0){content=targetElement.html()}}return content}function getViewportCollisions(coords,elementWidth,elementHeight){var viewportTop=session.scrollTop,viewportLeft=session.scrollLeft,viewportBottom=viewportTop+session.windowHeight,viewportRight=viewportLeft+session.windowWidth,collisions=Collision.none;if(coords.top<viewportTop||Math.abs(coords.bottom-session.windowHeight)-elementHeight<viewportTop){collisions|=Collision.top}if(coords.top+elementHeight>viewportBottom||Math.abs(coords.bottom-session.windowHeight)>viewportBottom){collisions|=Collision.bottom}if(coords.left<viewportLeft||coords.right+elementWidth>viewportRight){collisions|=Collision.left}if(coords.left+elementWidth>viewportRight||coords.right<viewportLeft){collisions|=Collision.right}return collisions}function countFlags(value){var count=0;while(value){value&=value-1;count++}return count}return $.powerTip});/*!
+ * jQuery UI Touch Punch 0.2.3
+ *
+ * Copyright 2011–2014, Dave Furfero
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ *
+ * Depends:
+ *  jquery.ui.widget.js
+ *  jquery.ui.mouse.js
+ */
+!function(a){function f(a,b){if(!(a.originalEvent.touches.length>1)){a.preventDefault();var c=a.originalEvent.changedTouches[0],d=document.createEvent("MouseEvents");d.initMouseEvent(b,!0,!0,window,1,c.screenX,c.screenY,c.clientX,c.clientY,!1,!1,!1,!1,0,null),a.target.dispatchEvent(d)}}if(a.support.touch="ontouchend"in document,a.support.touch){var e,b=a.ui.mouse.prototype,c=b._mouseInit,d=b._mouseDestroy;b._touchStart=function(a){var b=this;!e&&b._mouseCapture(a.originalEvent.changedTouches[0])&&(e=!0,b._touchMoved=!1,f(a,"mouseover"),f(a,"mousemove"),f(a,"mousedown"))},b._touchMove=function(a){e&&(this._touchMoved=!0,f(a,"mousemove"))},b._touchEnd=function(a){e&&(f(a,"mouseup"),f(a,"mouseout"),this._touchMoved||f(a,"click"),e=!1)},b._mouseInit=function(){var b=this;b.element.bind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),c.call(b)},b._mouseDestroy=function(){var b=this;b.element.unbind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),d.call(b)}}}(jQuery);/*! SmartMenus jQuery Plugin - v1.1.0 - September 17, 2017
+ * http://www.smartmenus.org/
+ * Copyright Vasil Dinkov, Vadikom Web Ltd. http://vadikom.com; Licensed MIT */(function(t){"function"==typeof define&&define.amd?define(["jquery"],t):"object"==typeof module&&"object"==typeof module.exports?module.exports=t(require("jquery")):t(jQuery)})(function($){function initMouseDetection(t){var e=".smartmenus_mouse";if(mouseDetectionEnabled||t)mouseDetectionEnabled&&t&&($(document).off(e),mouseDetectionEnabled=!1);else{var i=!0,s=null,o={mousemove:function(t){var e={x:t.pageX,y:t.pageY,timeStamp:(new Date).getTime()};if(s){var o=Math.abs(s.x-e.x),a=Math.abs(s.y-e.y);if((o>0||a>0)&&2>=o&&2>=a&&300>=e.timeStamp-s.timeStamp&&(mouse=!0,i)){var n=$(t.target).closest("a");n.is("a")&&$.each(menuTrees,function(){return $.contains(this.$root[0],n[0])?(this.itemEnter({currentTarget:n[0]}),!1):void 0}),i=!1}}s=e}};o[touchEvents?"touchstart":"pointerover pointermove pointerout MSPointerOver MSPointerMove MSPointerOut"]=function(t){isTouchEvent(t.originalEvent)&&(mouse=!1)},$(document).on(getEventsNS(o,e)),mouseDetectionEnabled=!0}}function isTouchEvent(t){return!/^(4|mouse)$/.test(t.pointerType)}function getEventsNS(t,e){e||(e="");var i={};for(var s in t)i[s.split(" ").join(e+" ")+e]=t[s];return i}var menuTrees=[],mouse=!1,touchEvents="ontouchstart"in window,mouseDetectionEnabled=!1,requestAnimationFrame=window.requestAnimationFrame||function(t){return setTimeout(t,1e3/60)},cancelAnimationFrame=window.cancelAnimationFrame||function(t){clearTimeout(t)},canAnimate=!!$.fn.animate;return $.SmartMenus=function(t,e){this.$root=$(t),this.opts=e,this.rootId="",this.accessIdPrefix="",this.$subArrow=null,this.activatedItems=[],this.visibleSubMenus=[],this.showTimeout=0,this.hideTimeout=0,this.scrollTimeout=0,this.clickActivated=!1,this.focusActivated=!1,this.zIndexInc=0,this.idInc=0,this.$firstLink=null,this.$firstSub=null,this.disabled=!1,this.$disableOverlay=null,this.$touchScrollingSub=null,this.cssTransforms3d="perspective"in t.style||"webkitPerspective"in t.style,this.wasCollapsible=!1,this.init()},$.extend($.SmartMenus,{hideAll:function(){$.each(menuTrees,function(){this.menuHideAll()})},destroy:function(){for(;menuTrees.length;)menuTrees[0].destroy();initMouseDetection(!0)},prototype:{init:function(t){var e=this;if(!t){menuTrees.push(this),this.rootId=((new Date).getTime()+Math.random()+"").replace(/\D/g,""),this.accessIdPrefix="sm-"+this.rootId+"-",this.$root.hasClass("sm-rtl")&&(this.opts.rightToLeftSubMenus=!0);var i=".smartmenus";this.$root.data("smartmenus",this).attr("data-smartmenus-id",this.rootId).dataSM("level",1).on(getEventsNS({"mouseover focusin":$.proxy(this.rootOver,this),"mouseout focusout":$.proxy(this.rootOut,this),keydown:$.proxy(this.rootKeyDown,this)},i)).on(getEventsNS({mouseenter:$.proxy(this.itemEnter,this),mouseleave:$.proxy(this.itemLeave,this),mousedown:$.proxy(this.itemDown,this),focus:$.proxy(this.itemFocus,this),blur:$.proxy(this.itemBlur,this),click:$.proxy(this.itemClick,this)},i),"a"),i+=this.rootId,this.opts.hideOnClick&&$(document).on(getEventsNS({touchstart:$.proxy(this.docTouchStart,this),touchmove:$.proxy(this.docTouchMove,this),touchend:$.proxy(this.docTouchEnd,this),click:$.proxy(this.docClick,this)},i)),$(window).on(getEventsNS({"resize orientationchange":$.proxy(this.winResize,this)},i)),this.opts.subIndicators&&(this.$subArrow=$("<span/>").addClass("sub-arrow"),this.opts.subIndicatorsText&&this.$subArrow.html(this.opts.subIndicatorsText)),initMouseDetection()}if(this.$firstSub=this.$root.find("ul").each(function(){e.menuInit($(this))}).eq(0),this.$firstLink=this.$root.find("a").eq(0),this.opts.markCurrentItem){var s=/(index|default)\.[^#\?\/]*/i,o=/#.*/,a=window.location.href.replace(s,""),n=a.replace(o,"");this.$root.find("a").each(function(){var t=this.href.replace(s,""),i=$(this);(t==a||t==n)&&(i.addClass("current"),e.opts.markCurrentTree&&i.parentsUntil("[data-smartmenus-id]","ul").each(function(){$(this).dataSM("parent-a").addClass("current")}))})}this.wasCollapsible=this.isCollapsible()},destroy:function(t){if(!t){var e=".smartmenus";this.$root.removeData("smartmenus").removeAttr("data-smartmenus-id").removeDataSM("level").off(e),e+=this.rootId,$(document).off(e),$(window).off(e),this.opts.subIndicators&&(this.$subArrow=null)}this.menuHideAll();var i=this;this.$root.find("ul").each(function(){var t=$(this);t.dataSM("scroll-arrows")&&t.dataSM("scroll-arrows").remove(),t.dataSM("shown-before")&&((i.opts.subMenusMinWidth||i.opts.subMenusMaxWidth)&&t.css({width:"",minWidth:"",maxWidth:""}).removeClass("sm-nowrap"),t.dataSM("scroll-arrows")&&t.dataSM("scroll-arrows").remove(),t.css({zIndex:"",top:"",left:"",marginLeft:"",marginTop:"",display:""})),0==(t.attr("id")||"").indexOf(i.accessIdPrefix)&&t.removeAttr("id")}).removeDataSM("in-mega").removeDataSM("shown-before").removeDataSM("scroll-arrows").removeDataSM("parent-a").removeDataSM("level").removeDataSM("beforefirstshowfired").removeAttr("role").removeAttr("aria-hidden").removeAttr("aria-labelledby").removeAttr("aria-expanded"),this.$root.find("a.has-submenu").each(function(){var t=$(this);0==t.attr("id").indexOf(i.accessIdPrefix)&&t.removeAttr("id")}).removeClass("has-submenu").removeDataSM("sub").removeAttr("aria-haspopup").removeAttr("aria-controls").removeAttr("aria-expanded").closest("li").removeDataSM("sub"),this.opts.subIndicators&&this.$root.find("span.sub-arrow").remove(),this.opts.markCurrentItem&&this.$root.find("a.current").removeClass("current"),t||(this.$root=null,this.$firstLink=null,this.$firstSub=null,this.$disableOverlay&&(this.$disableOverlay.remove(),this.$disableOverlay=null),menuTrees.splice($.inArray(this,menuTrees),1))},disable:function(t){if(!this.disabled){if(this.menuHideAll(),!t&&!this.opts.isPopup&&this.$root.is(":visible")){var e=this.$root.offset();this.$disableOverlay=$('<div class="sm-jquery-disable-overlay"/>').css({position:"absolute",top:e.top,left:e.left,width:this.$root.outerWidth(),height:this.$root.outerHeight(),zIndex:this.getStartZIndex(!0),opacity:0}).appendTo(document.body)}this.disabled=!0}},docClick:function(t){return this.$touchScrollingSub?(this.$touchScrollingSub=null,void 0):((this.visibleSubMenus.length&&!$.contains(this.$root[0],t.target)||$(t.target).closest("a").length)&&this.menuHideAll(),void 0)},docTouchEnd:function(){if(this.lastTouch){if(!(!this.visibleSubMenus.length||void 0!==this.lastTouch.x2&&this.lastTouch.x1!=this.lastTouch.x2||void 0!==this.lastTouch.y2&&this.lastTouch.y1!=this.lastTouch.y2||this.lastTouch.target&&$.contains(this.$root[0],this.lastTouch.target))){this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0);var t=this;this.hideTimeout=setTimeout(function(){t.menuHideAll()},350)}this.lastTouch=null}},docTouchMove:function(t){if(this.lastTouch){var e=t.originalEvent.touches[0];this.lastTouch.x2=e.pageX,this.lastTouch.y2=e.pageY}},docTouchStart:function(t){var e=t.originalEvent.touches[0];this.lastTouch={x1:e.pageX,y1:e.pageY,target:e.target}},enable:function(){this.disabled&&(this.$disableOverlay&&(this.$disableOverlay.remove(),this.$disableOverlay=null),this.disabled=!1)},getClosestMenu:function(t){for(var e=$(t).closest("ul");e.dataSM("in-mega");)e=e.parent().closest("ul");return e[0]||null},getHeight:function(t){return this.getOffset(t,!0)},getOffset:function(t,e){var i;"none"==t.css("display")&&(i={position:t[0].style.position,visibility:t[0].style.visibility},t.css({position:"absolute",visibility:"hidden"}).show());var s=t[0].getBoundingClientRect&&t[0].getBoundingClientRect(),o=s&&(e?s.height||s.bottom-s.top:s.width||s.right-s.left);return o||0===o||(o=e?t[0].offsetHeight:t[0].offsetWidth),i&&t.hide().css(i),o},getStartZIndex:function(t){var e=parseInt(this[t?"$root":"$firstSub"].css("z-index"));return!t&&isNaN(e)&&(e=parseInt(this.$root.css("z-index"))),isNaN(e)?1:e},getTouchPoint:function(t){return t.touches&&t.touches[0]||t.changedTouches&&t.changedTouches[0]||t},getViewport:function(t){var e=t?"Height":"Width",i=document.documentElement["client"+e],s=window["inner"+e];return s&&(i=Math.min(i,s)),i},getViewportHeight:function(){return this.getViewport(!0)},getViewportWidth:function(){return this.getViewport()},getWidth:function(t){return this.getOffset(t)},handleEvents:function(){return!this.disabled&&this.isCSSOn()},handleItemEvents:function(t){return this.handleEvents()&&!this.isLinkInMegaMenu(t)},isCollapsible:function(){return"static"==this.$firstSub.css("position")},isCSSOn:function(){return"inline"!=this.$firstLink.css("display")},isFixed:function(){var t="fixed"==this.$root.css("position");return t||this.$root.parentsUntil("body").each(function(){return"fixed"==$(this).css("position")?(t=!0,!1):void 0}),t},isLinkInMegaMenu:function(t){return $(this.getClosestMenu(t[0])).hasClass("mega-menu")},isTouchMode:function(){return!mouse||this.opts.noMouseOver||this.isCollapsible()},itemActivate:function(t,e){var i=t.closest("ul"),s=i.dataSM("level");if(s>1&&(!this.activatedItems[s-2]||this.activatedItems[s-2][0]!=i.dataSM("parent-a")[0])){var o=this;$(i.parentsUntil("[data-smartmenus-id]","ul").get().reverse()).add(i).each(function(){o.itemActivate($(this).dataSM("parent-a"))})}if((!this.isCollapsible()||e)&&this.menuHideSubMenus(this.activatedItems[s-1]&&this.activatedItems[s-1][0]==t[0]?s:s-1),this.activatedItems[s-1]=t,this.$root.triggerHandler("activate.smapi",t[0])!==!1){var a=t.dataSM("sub");a&&(this.isTouchMode()||!this.opts.showOnClick||this.clickActivated)&&this.menuShow(a)}},itemBlur:function(t){var e=$(t.currentTarget);this.handleItemEvents(e)&&this.$root.triggerHandler("blur.smapi",e[0])},itemClick:function(t){var e=$(t.currentTarget);if(this.handleItemEvents(e)){if(this.$touchScrollingSub&&this.$touchScrollingSub[0]==e.closest("ul")[0])return this.$touchScrollingSub=null,t.stopPropagation(),!1;if(this.$root.triggerHandler("click.smapi",e[0])===!1)return!1;var i=$(t.target).is(".sub-arrow"),s=e.dataSM("sub"),o=s?2==s.dataSM("level"):!1,a=this.isCollapsible(),n=/toggle$/.test(this.opts.collapsibleBehavior),r=/link$/.test(this.opts.collapsibleBehavior),h=/^accordion/.test(this.opts.collapsibleBehavior);if(s&&!s.is(":visible")){if((!r||!a||i)&&(this.opts.showOnClick&&o&&(this.clickActivated=!0),this.itemActivate(e,h),s.is(":visible")))return this.focusActivated=!0,!1}else if(a&&(n||i))return this.itemActivate(e,h),this.menuHide(s),n&&(this.focusActivated=!1),!1;return this.opts.showOnClick&&o||e.hasClass("disabled")||this.$root.triggerHandler("select.smapi",e[0])===!1?!1:void 0}},itemDown:function(t){var e=$(t.currentTarget);this.handleItemEvents(e)&&e.dataSM("mousedown",!0)},itemEnter:function(t){var e=$(t.currentTarget);if(this.handleItemEvents(e)){if(!this.isTouchMode()){this.showTimeout&&(clearTimeout(this.showTimeout),this.showTimeout=0);var i=this;this.showTimeout=setTimeout(function(){i.itemActivate(e)},this.opts.showOnClick&&1==e.closest("ul").dataSM("level")?1:this.opts.showTimeout)}this.$root.triggerHandler("mouseenter.smapi",e[0])}},itemFocus:function(t){var e=$(t.currentTarget);this.handleItemEvents(e)&&(!this.focusActivated||this.isTouchMode()&&e.dataSM("mousedown")||this.activatedItems.length&&this.activatedItems[this.activatedItems.length-1][0]==e[0]||this.itemActivate(e,!0),this.$root.triggerHandler("focus.smapi",e[0]))},itemLeave:function(t){var e=$(t.currentTarget);this.handleItemEvents(e)&&(this.isTouchMode()||(e[0].blur(),this.showTimeout&&(clearTimeout(this.showTimeout),this.showTimeout=0)),e.removeDataSM("mousedown"),this.$root.triggerHandler("mouseleave.smapi",e[0]))},menuHide:function(t){if(this.$root.triggerHandler("beforehide.smapi",t[0])!==!1&&(canAnimate&&t.stop(!0,!0),"none"!=t.css("display"))){var e=function(){t.css("z-index","")};this.isCollapsible()?canAnimate&&this.opts.collapsibleHideFunction?this.opts.collapsibleHideFunction.call(this,t,e):t.hide(this.opts.collapsibleHideDuration,e):canAnimate&&this.opts.hideFunction?this.opts.hideFunction.call(this,t,e):t.hide(this.opts.hideDuration,e),t.dataSM("scroll")&&(this.menuScrollStop(t),t.css({"touch-action":"","-ms-touch-action":"","-webkit-transform":"",transform:""}).off(".smartmenus_scroll").removeDataSM("scroll").dataSM("scroll-arrows").hide()),t.dataSM("parent-a").removeClass("highlighted").attr("aria-expanded","false"),t.attr({"aria-expanded":"false","aria-hidden":"true"});var i=t.dataSM("level");this.activatedItems.splice(i-1,1),this.visibleSubMenus.splice($.inArray(t,this.visibleSubMenus),1),this.$root.triggerHandler("hide.smapi",t[0])}},menuHideAll:function(){this.showTimeout&&(clearTimeout(this.showTimeout),this.showTimeout=0);for(var t=this.opts.isPopup?1:0,e=this.visibleSubMenus.length-1;e>=t;e--)this.menuHide(this.visibleSubMenus[e]);this.opts.isPopup&&(canAnimate&&this.$root.stop(!0,!0),this.$root.is(":visible")&&(canAnimate&&this.opts.hideFunction?this.opts.hideFunction.call(this,this.$root):this.$root.hide(this.opts.hideDuration))),this.activatedItems=[],this.visibleSubMenus=[],this.clickActivated=!1,this.focusActivated=!1,this.zIndexInc=0,this.$root.triggerHandler("hideAll.smapi")},menuHideSubMenus:function(t){for(var e=this.activatedItems.length-1;e>=t;e--){var i=this.activatedItems[e].dataSM("sub");i&&this.menuHide(i)}},menuInit:function(t){if(!t.dataSM("in-mega")){t.hasClass("mega-menu")&&t.find("ul").dataSM("in-mega",!0);for(var e=2,i=t[0];(i=i.parentNode.parentNode)!=this.$root[0];)e++;var s=t.prevAll("a").eq(-1);s.length||(s=t.prevAll().find("a").eq(-1)),s.addClass("has-submenu").dataSM("sub",t),t.dataSM("parent-a",s).dataSM("level",e).parent().dataSM("sub",t);var o=s.attr("id")||this.accessIdPrefix+ ++this.idInc,a=t.attr("id")||this.accessIdPrefix+ ++this.idInc;s.attr({id:o,"aria-haspopup":"true","aria-controls":a,"aria-expanded":"false"}),t.attr({id:a,role:"group","aria-hidden":"true","aria-labelledby":o,"aria-expanded":"false"}),this.opts.subIndicators&&s[this.opts.subIndicatorsPos](this.$subArrow.clone())}},menuPosition:function(t){var e,i,s=t.dataSM("parent-a"),o=s.closest("li"),a=o.parent(),n=t.dataSM("level"),r=this.getWidth(t),h=this.getHeight(t),u=s.offset(),l=u.left,c=u.top,d=this.getWidth(s),m=this.getHeight(s),p=$(window),f=p.scrollLeft(),v=p.scrollTop(),b=this.getViewportWidth(),S=this.getViewportHeight(),g=a.parent().is("[data-sm-horizontal-sub]")||2==n&&!a.hasClass("sm-vertical"),M=this.opts.rightToLeftSubMenus&&!o.is("[data-sm-reverse]")||!this.opts.rightToLeftSubMenus&&o.is("[data-sm-reverse]"),w=2==n?this.opts.mainMenuSubOffsetX:this.opts.subMenusSubOffsetX,T=2==n?this.opts.mainMenuSubOffsetY:this.opts.subMenusSubOffsetY;if(g?(e=M?d-r-w:w,i=this.opts.bottomToTopSubMenus?-h-T:m+T):(e=M?w-r:d-w,i=this.opts.bottomToTopSubMenus?m-T-h:T),this.opts.keepInViewport){var y=l+e,I=c+i;if(M&&f>y?e=g?f-y+e:d-w:!M&&y+r>f+b&&(e=g?f+b-r-y+e:w-r),g||(S>h&&I+h>v+S?i+=v+S-h-I:(h>=S||v>I)&&(i+=v-I)),g&&(I+h>v+S+.49||v>I)||!g&&h>S+.49){var x=this;t.dataSM("scroll-arrows")||t.dataSM("scroll-arrows",$([$('<span class="scroll-up"><span class="scroll-up-arrow"></span></span>')[0],$('<span class="scroll-down"><span class="scroll-down-arrow"></span></span>')[0]]).on({mouseenter:function(){t.dataSM("scroll").up=$(this).hasClass("scroll-up"),x.menuScroll(t)},mouseleave:function(e){x.menuScrollStop(t),x.menuScrollOut(t,e)},"mousewheel DOMMouseScroll":function(t){t.preventDefault()}}).insertAfter(t));var A=".smartmenus_scroll";if(t.dataSM("scroll",{y:this.cssTransforms3d?0:i-m,step:1,itemH:m,subH:h,arrowDownH:this.getHeight(t.dataSM("scroll-arrows").eq(1))}).on(getEventsNS({mouseover:function(e){x.menuScrollOver(t,e)},mouseout:function(e){x.menuScrollOut(t,e)},"mousewheel DOMMouseScroll":function(e){x.menuScrollMousewheel(t,e)}},A)).dataSM("scroll-arrows").css({top:"auto",left:"0",marginLeft:e+(parseInt(t.css("border-left-width"))||0),width:r-(parseInt(t.css("border-left-width"))||0)-(parseInt(t.css("border-right-width"))||0),zIndex:t.css("z-index")}).eq(g&&this.opts.bottomToTopSubMenus?0:1).show(),this.isFixed()){var C={};C[touchEvents?"touchstart touchmove touchend":"pointerdown pointermove pointerup MSPointerDown MSPointerMove MSPointerUp"]=function(e){x.menuScrollTouch(t,e)},t.css({"touch-action":"none","-ms-touch-action":"none"}).on(getEventsNS(C,A))}}}t.css({top:"auto",left:"0",marginLeft:e,marginTop:i-m})},menuScroll:function(t,e,i){var s,o=t.dataSM("scroll"),a=t.dataSM("scroll-arrows"),n=o.up?o.upEnd:o.downEnd;if(!e&&o.momentum){if(o.momentum*=.92,s=o.momentum,.5>s)return this.menuScrollStop(t),void 0}else s=i||(e||!this.opts.scrollAccelerate?this.opts.scrollStep:Math.floor(o.step));var r=t.dataSM("level");if(this.activatedItems[r-1]&&this.activatedItems[r-1].dataSM("sub")&&this.activatedItems[r-1].dataSM("sub").is(":visible")&&this.menuHideSubMenus(r-1),o.y=o.up&&o.y>=n||!o.up&&n>=o.y?o.y:Math.abs(n-o.y)>s?o.y+(o.up?s:-s):n,t.css(this.cssTransforms3d?{"-webkit-transform":"translate3d(0, "+o.y+"px, 0)",transform:"translate3d(0, "+o.y+"px, 0)"}:{marginTop:o.y}),mouse&&(o.up&&o.y>o.downEnd||!o.up&&o.y<o.upEnd)&&a.eq(o.up?1:0).show(),o.y==n)mouse&&a.eq(o.up?0:1).hide(),this.menuScrollStop(t);else if(!e){this.opts.scrollAccelerate&&o.step<this.opts.scrollStep&&(o.step+=.2);var h=this;this.scrollTimeout=requestAnimationFrame(function(){h.menuScroll(t)})}},menuScrollMousewheel:function(t,e){if(this.getClosestMenu(e.target)==t[0]){e=e.originalEvent;var i=(e.wheelDelta||-e.detail)>0;t.dataSM("scroll-arrows").eq(i?0:1).is(":visible")&&(t.dataSM("scroll").up=i,this.menuScroll(t,!0))}e.preventDefault()},menuScrollOut:function(t,e){mouse&&(/^scroll-(up|down)/.test((e.relatedTarget||"").className)||(t[0]==e.relatedTarget||$.contains(t[0],e.relatedTarget))&&this.getClosestMenu(e.relatedTarget)==t[0]||t.dataSM("scroll-arrows").css("visibility","hidden"))},menuScrollOver:function(t,e){if(mouse&&!/^scroll-(up|down)/.test(e.target.className)&&this.getClosestMenu(e.target)==t[0]){this.menuScrollRefreshData(t);var i=t.dataSM("scroll"),s=$(window).scrollTop()-t.dataSM("parent-a").offset().top-i.itemH;t.dataSM("scroll-arrows").eq(0).css("margin-top",s).end().eq(1).css("margin-top",s+this.getViewportHeight()-i.arrowDownH).end().css("visibility","visible")}},menuScrollRefreshData:function(t){var e=t.dataSM("scroll"),i=$(window).scrollTop()-t.dataSM("parent-a").offset().top-e.itemH;this.cssTransforms3d&&(i=-(parseFloat(t.css("margin-top"))-i)),$.extend(e,{upEnd:i,downEnd:i+this.getViewportHeight()-e.subH})},menuScrollStop:function(t){return this.scrollTimeout?(cancelAnimationFrame(this.scrollTimeout),this.scrollTimeout=0,t.dataSM("scroll").step=1,!0):void 0},menuScrollTouch:function(t,e){if(e=e.originalEvent,isTouchEvent(e)){var i=this.getTouchPoint(e);if(this.getClosestMenu(i.target)==t[0]){var s=t.dataSM("scroll");if(/(start|down)$/i.test(e.type))this.menuScrollStop(t)?(e.preventDefault(),this.$touchScrollingSub=t):this.$touchScrollingSub=null,this.menuScrollRefreshData(t),$.extend(s,{touchStartY:i.pageY,touchStartTime:e.timeStamp});else if(/move$/i.test(e.type)){var o=void 0!==s.touchY?s.touchY:s.touchStartY;if(void 0!==o&&o!=i.pageY){this.$touchScrollingSub=t;var a=i.pageY>o;void 0!==s.up&&s.up!=a&&$.extend(s,{touchStartY:i.pageY,touchStartTime:e.timeStamp}),$.extend(s,{up:a,touchY:i.pageY}),this.menuScroll(t,!0,Math.abs(i.pageY-o))}e.preventDefault()}else void 0!==s.touchY&&((s.momentum=15*Math.pow(Math.abs(i.pageY-s.touchStartY)/(e.timeStamp-s.touchStartTime),2))&&(this.menuScrollStop(t),this.menuScroll(t),e.preventDefault()),delete s.touchY)}}},menuShow:function(t){if((t.dataSM("beforefirstshowfired")||(t.dataSM("beforefirstshowfired",!0),this.$root.triggerHandler("beforefirstshow.smapi",t[0])!==!1))&&this.$root.triggerHandler("beforeshow.smapi",t[0])!==!1&&(t.dataSM("shown-before",!0),canAnimate&&t.stop(!0,!0),!t.is(":visible"))){var e=t.dataSM("parent-a"),i=this.isCollapsible();if((this.opts.keepHighlighted||i)&&e.addClass("highlighted"),i)t.removeClass("sm-nowrap").css({zIndex:"",width:"auto",minWidth:"",maxWidth:"",top:"",left:"",marginLeft:"",marginTop:""});else{if(t.css("z-index",this.zIndexInc=(this.zIndexInc||this.getStartZIndex())+1),(this.opts.subMenusMinWidth||this.opts.subMenusMaxWidth)&&(t.css({width:"auto",minWidth:"",maxWidth:""}).addClass("sm-nowrap"),this.opts.subMenusMinWidth&&t.css("min-width",this.opts.subMenusMinWidth),this.opts.subMenusMaxWidth)){var s=this.getWidth(t);t.css("max-width",this.opts.subMenusMaxWidth),s>this.getWidth(t)&&t.removeClass("sm-nowrap").css("width",this.opts.subMenusMaxWidth)}this.menuPosition(t)}var o=function(){t.css("overflow","")};i?canAnimate&&this.opts.collapsibleShowFunction?this.opts.collapsibleShowFunction.call(this,t,o):t.show(this.opts.collapsibleShowDuration,o):canAnimate&&this.opts.showFunction?this.opts.showFunction.call(this,t,o):t.show(this.opts.showDuration,o),e.attr("aria-expanded","true"),t.attr({"aria-expanded":"true","aria-hidden":"false"}),this.visibleSubMenus.push(t),this.$root.triggerHandler("show.smapi",t[0])}},popupHide:function(t){this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0);var e=this;this.hideTimeout=setTimeout(function(){e.menuHideAll()},t?1:this.opts.hideTimeout)},popupShow:function(t,e){if(!this.opts.isPopup)return alert('SmartMenus jQuery Error:\n\nIf you want to show this menu via the "popupShow" method, set the isPopup:true option.'),void 0;if(this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0),this.$root.dataSM("shown-before",!0),canAnimate&&this.$root.stop(!0,!0),!this.$root.is(":visible")){this.$root.css({left:t,top:e});var i=this,s=function(){i.$root.css("overflow","")};canAnimate&&this.opts.showFunction?this.opts.showFunction.call(this,this.$root,s):this.$root.show(this.opts.showDuration,s),this.visibleSubMenus[0]=this.$root}},refresh:function(){this.destroy(!0),this.init(!0)},rootKeyDown:function(t){if(this.handleEvents())switch(t.keyCode){case 27:var e=this.activatedItems[0];if(e){this.menuHideAll(),e[0].focus();var i=e.dataSM("sub");i&&this.menuHide(i)}break;case 32:var s=$(t.target);if(s.is("a")&&this.handleItemEvents(s)){var i=s.dataSM("sub");i&&!i.is(":visible")&&(this.itemClick({currentTarget:t.target}),t.preventDefault())}}},rootOut:function(t){if(this.handleEvents()&&!this.isTouchMode()&&t.target!=this.$root[0]&&(this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0),!this.opts.showOnClick||!this.opts.hideOnClick)){var e=this;this.hideTimeout=setTimeout(function(){e.menuHideAll()},this.opts.hideTimeout)}},rootOver:function(t){this.handleEvents()&&!this.isTouchMode()&&t.target!=this.$root[0]&&this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0)},winResize:function(t){if(this.handleEvents()){if(!("onorientationchange"in window)||"orientationchange"==t.type){var e=this.isCollapsible();this.wasCollapsible&&e||(this.activatedItems.length&&this.activatedItems[this.activatedItems.length-1][0].blur(),this.menuHideAll()),this.wasCollapsible=e}}else if(this.$disableOverlay){var i=this.$root.offset();this.$disableOverlay.css({top:i.top,left:i.left,width:this.$root.outerWidth(),height:this.$root.outerHeight()})}}}}),$.fn.dataSM=function(t,e){return e?this.data(t+"_smartmenus",e):this.data(t+"_smartmenus")},$.fn.removeDataSM=function(t){return this.removeData(t+"_smartmenus")},$.fn.smartmenus=function(options){if("string"==typeof options){var args=arguments,method=options;return Array.prototype.shift.call(args),this.each(function(){var t=$(this).data("smartmenus");t&&t[method]&&t[method].apply(t,args)})}return this.each(function(){var dataOpts=$(this).data("sm-options")||null;if(dataOpts)try{dataOpts=eval("("+dataOpts+")")}catch(e){dataOpts=null,alert('ERROR\n\nSmartMenus jQuery init:\nInvalid "data-sm-options" attribute value syntax.')}new $.SmartMenus(this,$.extend({},$.fn.smartmenus.defaults,options,dataOpts))})},$.fn.smartmenus.defaults={isPopup:!1,mainMenuSubOffsetX:0,mainMenuSubOffsetY:0,subMenusSubOffsetX:0,subMenusSubOffsetY:0,subMenusMinWidth:"10em",subMenusMaxWidth:"20em",subIndicators:!0,subIndicatorsPos:"append",subIndicatorsText:"",scrollStep:30,scrollAccelerate:!0,showTimeout:250,hideTimeout:500,showDuration:0,showFunction:null,hideDuration:0,hideFunction:function(t,e){t.fadeOut(200,e)},collapsibleShowDuration:0,collapsibleShowFunction:function(t,e){t.slideDown(200,e)},collapsibleHideDuration:0,collapsibleHideFunction:function(t,e){t.slideUp(200,e)},showOnClick:!1,hideOnClick:!0,noMouseOver:!1,keepInViewport:!0,keepHighlighted:!0,markCurrentItem:!1,markCurrentTree:!0,rightToLeftSubMenus:!1,bottomToTopSubMenus:!1,collapsibleBehavior:"default"},$});
\ No newline at end of file
diff --git a/third_party/VulkanMemoryAllocator/docs/html/lost_allocations.html b/third_party/VulkanMemoryAllocator/docs/html/lost_allocations.html
new file mode 100644
index 0000000..c4e56ac
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/lost_allocations.html
@@ -0,0 +1,144 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: Lost allocations</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+  <ul>
+<li class="navelem"><a class="el" href="index.html">Vulkan Memory Allocator</a></li>  </ul>
+</div>
+</div><!-- top -->
+<div class="PageDoc"><div class="header">
+  <div class="headertitle">
+<div class="title">Lost allocations </div>  </div>
+</div><!--header-->
+<div class="contents">
+<div class="textblock"><p>If your game oversubscribes video memory, if may work OK in previous-generation graphics APIs (DirectX 9, 10, 11, OpenGL) because resources are automatically paged to system RAM. In Vulkan you can't do it because when you run out of memory, an allocation just fails. If you have more data (e.g. textures) that can fit into VRAM and you don't need it all at once, you may want to upload them to GPU on demand and "push out" ones that are not used for a long time to make room for the new ones, effectively using VRAM (or a cartain memory pool) as a form of cache. Vulkan Memory Allocator can help you with that by supporting a concept of "lost allocations".</p>
+<p>To create an allocation that can become lost, include <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a5f436af6c8fe8540573a6d22627a6fd2">VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT</a> flag in <a class="el" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b" title="Use VmaAllocationCreateFlagBits enum.">VmaAllocationCreateInfo::flags</a>. Before using a buffer or image bound to such allocation in every new frame, you need to query it if it's not lost. To check it, call <a class="el" href="vk__mem__alloc_8h.html#a43d8ba9673c846f049089a5029d5c73a" title="Returns VK_TRUE if allocation is not lost and atomically marks it as used in current frame.">vmaTouchAllocation()</a>. If the allocation is lost, you should not use it or buffer/image bound to it. You mustn't forget to destroy this allocation and this buffer/image. <a class="el" href="vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b" title="Returns current information about specified allocation and atomically marks it as used in current fra...">vmaGetAllocationInfo()</a> can also be used for checking status of the allocation. Allocation is lost when returned <a class="el" href="struct_vma_allocation_info.html#ae0bfb7dfdf79a76ffefc9a94677a2f67" title="Handle to Vulkan memory object.">VmaAllocationInfo::deviceMemory</a> == <code>VK_NULL_HANDLE</code>.</p>
+<p>To create an allocation that can make some other allocations lost to make room for it, use <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a68686d0ce9beb0d4d1b9f2b8b1389a7e">VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT</a> flag. You will usually use both flags <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a68686d0ce9beb0d4d1b9f2b8b1389a7e">VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT</a> and <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a5f436af6c8fe8540573a6d22627a6fd2">VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT</a> at the same time.</p>
+<p>Warning! Current implementation uses quite naive, brute force algorithm, which can make allocation calls that use <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a68686d0ce9beb0d4d1b9f2b8b1389a7e">VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT</a> flag quite slow. A new, more optimal algorithm and data structure to speed this up is planned for the future.</p>
+<p><b>Q: When interleaving creation of new allocations with usage of existing ones, how do you make sure that an allocation won't become lost while it's used in the current frame?</b></p>
+<p>It is ensured because <a class="el" href="vk__mem__alloc_8h.html#a43d8ba9673c846f049089a5029d5c73a" title="Returns VK_TRUE if allocation is not lost and atomically marks it as used in current frame.">vmaTouchAllocation()</a> / <a class="el" href="vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b" title="Returns current information about specified allocation and atomically marks it as used in current fra...">vmaGetAllocationInfo()</a> not only returns allocation status/parameters and checks whether it's not lost, but when it's not, it also atomically marks it as used in the current frame, which makes it impossible to become lost in that frame. It uses lockless algorithm, so it works fast and doesn't involve locking any internal mutex.</p>
+<p><b>Q: What if my allocation may still be in use by the GPU when it's rendering a previous frame while I already submit new frame on the CPU?</b></p>
+<p>You can make sure that allocations "touched" by <a class="el" href="vk__mem__alloc_8h.html#a43d8ba9673c846f049089a5029d5c73a" title="Returns VK_TRUE if allocation is not lost and atomically marks it as used in current frame.">vmaTouchAllocation()</a> / <a class="el" href="vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b" title="Returns current information about specified allocation and atomically marks it as used in current fra...">vmaGetAllocationInfo()</a> will not become lost for a number of additional frames back from the current one by specifying this number as <a class="el" href="struct_vma_allocator_create_info.html#a21ea188dd212b8171cb9ecbed4a2a3a7" title="Maximum number of additional frames that are in use at the same time as current frame.">VmaAllocatorCreateInfo::frameInUseCount</a> (for default memory pool) and <a class="el" href="struct_vma_pool_create_info.html#a9437e43ffbb644dbbf7fc4e50cfad6aa" title="Maximum number of additional frames that are in use at the same time as current frame.">VmaPoolCreateInfo::frameInUseCount</a> (for custom pool).</p>
+<p><b>Q: How do you inform the library when new frame starts?</b></p>
+<p>You need to call function <a class="el" href="vk__mem__alloc_8h.html#ade56bf8dc9f5a5eaddf5f119ed525236" title="Sets index of the current frame.">vmaSetCurrentFrameIndex()</a>.</p>
+<p>Example code:</p>
+<div class="fragment"><div class="line"><span class="keyword">struct </span>MyBuffer</div>
+<div class="line">{</div>
+<div class="line">    VkBuffer m_Buf = <span class="keyword">nullptr</span>;</div>
+<div class="line">    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> m_Alloc = <span class="keyword">nullptr</span>;</div>
+<div class="line"> </div>
+<div class="line">    <span class="comment">// Called when the buffer is really needed in the current frame.</span></div>
+<div class="line">    <span class="keywordtype">void</span> EnsureBuffer();</div>
+<div class="line">};</div>
+<div class="line"> </div>
+<div class="line"><span class="keywordtype">void</span> MyBuffer::EnsureBuffer()</div>
+<div class="line">{</div>
+<div class="line">    <span class="comment">// Buffer has been created.</span></div>
+<div class="line">    <span class="keywordflow">if</span>(m_Buf != VK_NULL_HANDLE)</div>
+<div class="line">    {</div>
+<div class="line">        <span class="comment">// Check if its allocation is not lost + mark it as used in current frame.</span></div>
+<div class="line">        <span class="keywordflow">if</span>(<a class="code" href="vk__mem__alloc_8h.html#a43d8ba9673c846f049089a5029d5c73a">vmaTouchAllocation</a>(allocator, m_Alloc))</div>
+<div class="line">        {</div>
+<div class="line">            <span class="comment">// It&#39;s all OK - safe to use m_Buf.</span></div>
+<div class="line">            <span class="keywordflow">return</span>;</div>
+<div class="line">        }</div>
+<div class="line">    }</div>
+<div class="line"> </div>
+<div class="line">    <span class="comment">// Buffer not yet exists or lost - destroy and recreate it.</span></div>
+<div class="line"> </div>
+<div class="line">    <a class="code" href="vk__mem__alloc_8h.html#a0d9f4e4ba5bf9aab1f1c746387753d77">vmaDestroyBuffer</a>(allocator, m_Buf, m_Alloc);</div>
+<div class="line"> </div>
+<div class="line">    VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };</div>
+<div class="line">    bufCreateInfo.size = 1024;</div>
+<div class="line">    bufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;</div>
+<div class="line"> </div>
+<div class="line">    <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> allocCreateInfo = {};</div>
+<div class="line">    allocCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910">usage</a> = <a class="code" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7">VMA_MEMORY_USAGE_GPU_ONLY</a>;</div>
+<div class="line">    allocCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a> = <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a5f436af6c8fe8540573a6d22627a6fd2">VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT</a> |</div>
+<div class="line">        <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a68686d0ce9beb0d4d1b9f2b8b1389a7e">VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT</a>;</div>
+<div class="line"> </div>
+<div class="line">    <a class="code" href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer</a>(allocator, &amp;bufCreateInfo, &amp;allocCreateInfo, &amp;m_Buf, &amp;m_Alloc, <span class="keyword">nullptr</span>);</div>
+<div class="line">}</div>
+</div><!-- fragment --><p>When using lost allocations, you may see some Vulkan validation layer warnings about overlapping regions of memory bound to different kinds of buffers and images. This is still valid as long as you implement proper handling of lost allocations (like in the example above) and don't use them.</p>
+<p>You can create an allocation that is already in lost state from the beginning using function <a class="el" href="vk__mem__alloc_8h.html#ae5c9657d9e94756269145b01c05d16f1" title="Creates new allocation that is in lost state from the beginning.">vmaCreateLostAllocation()</a>. It may be useful if you need a "dummy" allocation that is not null.</p>
+<p>You can call function <a class="el" href="vk__mem__alloc_8h.html#a736bd6cbda886f36c891727e73bd4024" title="Marks all allocations in given pool as lost if they are not used in current frame or VmaPoolCreateInf...">vmaMakePoolAllocationsLost()</a> to set all eligible allocations in a specified custom pool to lost state. Allocations that have been "touched" in current frame or <a class="el" href="struct_vma_pool_create_info.html#a9437e43ffbb644dbbf7fc4e50cfad6aa" title="Maximum number of additional frames that are in use at the same time as current frame.">VmaPoolCreateInfo::frameInUseCount</a> frames back cannot become lost.</p>
+<p><b>Q: Can I touch allocation that cannot become lost?</b></p>
+<p>Yes, although it has no visible effect. Calls to <a class="el" href="vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b" title="Returns current information about specified allocation and atomically marks it as used in current fra...">vmaGetAllocationInfo()</a> and <a class="el" href="vk__mem__alloc_8h.html#a43d8ba9673c846f049089a5029d5c73a" title="Returns VK_TRUE if allocation is not lost and atomically marks it as used in current frame.">vmaTouchAllocation()</a> update last use frame index also for allocations that cannot become lost, but the only way to observe it is to dump internal allocator state using <a class="el" href="vk__mem__alloc_8h.html#aa4fee7eb5253377599ef4fd38c93c2a0" title="Builds and returns statistics as string in JSON format.">vmaBuildStatsString()</a>. You can use this feature for debugging purposes to explicitly mark allocations that you use in current frame and then analyze JSON dump to see for how long each allocation stays unused. </p>
+</div></div><!-- contents -->
+</div><!-- PageDoc -->
+<div class="ttc" id="avk__mem__alloc_8h_html_a43d8ba9673c846f049089a5029d5c73a"><div class="ttname"><a href="vk__mem__alloc_8h.html#a43d8ba9673c846f049089a5029d5c73a">vmaTouchAllocation</a></div><div class="ttdeci">VkBool32 vmaTouchAllocation(VmaAllocator allocator, VmaAllocation allocation)</div><div class="ttdoc">Returns VK_TRUE if allocation is not lost and atomically marks it as used in current frame.</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ad9889c10c798b040d59c92f257cae597a5f436af6c8fe8540573a6d22627a6fd2"><div class="ttname"><a href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a5f436af6c8fe8540573a6d22627a6fd2">VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT</a></div><div class="ttdeci">@ VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2571</div></div>
+<div class="ttc" id="astruct_vma_allocation_html"><div class="ttname"><a href="struct_vma_allocation.html">VmaAllocation</a></div><div class="ttdoc">Represents single memory allocation.</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7"><div class="ttname"><a href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7">VMA_MEMORY_USAGE_GPU_ONLY</a></div><div class="ttdeci">@ VMA_MEMORY_USAGE_GPU_ONLY</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2481</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ad9889c10c798b040d59c92f257cae597a68686d0ce9beb0d4d1b9f2b8b1389a7e"><div class="ttname"><a href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a68686d0ce9beb0d4d1b9f2b8b1389a7e">VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT</a></div><div class="ttdeci">@ VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2578</div></div>
+<div class="ttc" id="astruct_vma_allocation_create_info_html_accb8b06b1f677d858cb9af20705fa910"><div class="ttname"><a href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910">VmaAllocationCreateInfo::usage</a></div><div class="ttdeci">VmaMemoryUsage usage</div><div class="ttdoc">Intended usage of memory.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2647</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ac72ee55598617e8eecca384e746bab51"><div class="ttname"><a href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer</a></div><div class="ttdeci">VkResult vmaCreateBuffer(VmaAllocator allocator, const VkBufferCreateInfo *pBufferCreateInfo, const VmaAllocationCreateInfo *pAllocationCreateInfo, VkBuffer *pBuffer, VmaAllocation *pAllocation, VmaAllocationInfo *pAllocationInfo)</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a0d9f4e4ba5bf9aab1f1c746387753d77"><div class="ttname"><a href="vk__mem__alloc_8h.html#a0d9f4e4ba5bf9aab1f1c746387753d77">vmaDestroyBuffer</a></div><div class="ttdeci">void vmaDestroyBuffer(VmaAllocator allocator, VkBuffer buffer, VmaAllocation allocation)</div><div class="ttdoc">Destroys Vulkan buffer and frees allocated memory.</div></div>
+<div class="ttc" id="astruct_vma_allocation_create_info_html_add09658ac14fe290ace25470ddd6d41b"><div class="ttname"><a href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">VmaAllocationCreateInfo::flags</a></div><div class="ttdeci">VmaAllocationCreateFlags flags</div><div class="ttdoc">Use VmaAllocationCreateFlagBits enum.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2641</div></div>
+<div class="ttc" id="astruct_vma_allocation_create_info_html"><div class="ttname"><a href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a></div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2638</div></div>
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/memory_mapping.html b/third_party/VulkanMemoryAllocator/docs/html/memory_mapping.html
new file mode 100644
index 0000000..a3f587e
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/memory_mapping.html
@@ -0,0 +1,210 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: Memory mapping</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+  <ul>
+<li class="navelem"><a class="el" href="index.html">Vulkan Memory Allocator</a></li>  </ul>
+</div>
+</div><!-- top -->
+<div class="PageDoc"><div class="header">
+  <div class="headertitle">
+<div class="title">Memory mapping </div>  </div>
+</div><!--header-->
+<div class="contents">
+<div class="textblock"><p>To "map memory" in Vulkan means to obtain a CPU pointer to <code>VkDeviceMemory</code>, to be able to read from it or write to it in CPU code. Mapping is possible only of memory allocated from a memory type that has <code>VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT</code> flag. Functions <code>vkMapMemory()</code>, <code>vkUnmapMemory()</code> are designed for this purpose. You can use them directly with memory allocated by this library, but it is not recommended because of following issue: Mapping the same <code>VkDeviceMemory</code> block multiple times is illegal - only one mapping at a time is allowed. This includes mapping disjoint regions. Mapping is not reference-counted internally by Vulkan. Because of this, Vulkan Memory Allocator provides following facilities:</p>
+<h1><a class="anchor" id="memory_mapping_mapping_functions"></a>
+Mapping functions</h1>
+<p>The library provides following functions for mapping of a specific <a class="el" href="struct_vma_allocation.html" title="Represents single memory allocation.">VmaAllocation</a>: <a class="el" href="vk__mem__alloc_8h.html#ad5bd1243512d099706de88168992f069" title="Maps memory represented by given allocation and returns pointer to it.">vmaMapMemory()</a>, <a class="el" href="vk__mem__alloc_8h.html#a9bc268595cb33f6ec4d519cfce81ff45" title="Unmaps memory represented by given allocation, mapped previously using vmaMapMemory().">vmaUnmapMemory()</a>. They are safer and more convenient to use than standard Vulkan functions. You can map an allocation multiple times simultaneously - mapping is reference-counted internally. You can also map different allocations simultaneously regardless of whether they use the same <code>VkDeviceMemory</code> block. The way it's implemented is that the library always maps entire memory block, not just region of the allocation. For further details, see description of <a class="el" href="vk__mem__alloc_8h.html#ad5bd1243512d099706de88168992f069" title="Maps memory represented by given allocation and returns pointer to it.">vmaMapMemory()</a> function. Example:</p>
+<div class="fragment"><div class="line"><span class="comment">// Having these objects initialized:</span></div>
+<div class="line"> </div>
+<div class="line"><span class="keyword">struct </span>ConstantBuffer</div>
+<div class="line">{</div>
+<div class="line">    ...</div>
+<div class="line">};</div>
+<div class="line">ConstantBuffer constantBufferData;</div>
+<div class="line"> </div>
+<div class="line"><a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator;</div>
+<div class="line">VkBuffer constantBuffer;</div>
+<div class="line"><a class="code" href="struct_vma_allocation.html">VmaAllocation</a> constantBufferAllocation;</div>
+<div class="line"> </div>
+<div class="line"><span class="comment">// You can map and fill your buffer using following code:</span></div>
+<div class="line"> </div>
+<div class="line"><span class="keywordtype">void</span>* mappedData;</div>
+<div class="line"><a class="code" href="vk__mem__alloc_8h.html#ad5bd1243512d099706de88168992f069">vmaMapMemory</a>(allocator, constantBufferAllocation, &amp;mappedData);</div>
+<div class="line">memcpy(mappedData, &amp;constantBufferData, <span class="keyword">sizeof</span>(constantBufferData));</div>
+<div class="line"><a class="code" href="vk__mem__alloc_8h.html#a9bc268595cb33f6ec4d519cfce81ff45">vmaUnmapMemory</a>(allocator, constantBufferAllocation);</div>
+</div><!-- fragment --><p>When mapping, you may see a warning from Vulkan validation layer similar to this one:</p>
+<p><em>Mapping an image with layout VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL can result in undefined behavior if this memory is used by the device. Only GENERAL or PREINITIALIZED should be used.</em></p>
+<p>It happens because the library maps entire <code>VkDeviceMemory</code> block, where different types of images and buffers may end up together, especially on GPUs with unified memory like Intel. You can safely ignore it if you are sure you access only memory of the intended object that you wanted to map.</p>
+<h1><a class="anchor" id="memory_mapping_persistently_mapped_memory"></a>
+Persistently mapped memory</h1>
+<p>Kepping your memory persistently mapped is generally OK in Vulkan. You don't need to unmap it before using its data on the GPU. The library provides a special feature designed for that: Allocations made with <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a11da372cc3a82931c5e5d6146cd9dd1f" title="Set this flag to use a memory that will be persistently mapped and retrieve pointer to it.">VMA_ALLOCATION_CREATE_MAPPED_BIT</a> flag set in <a class="el" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b" title="Use VmaAllocationCreateFlagBits enum.">VmaAllocationCreateInfo::flags</a> stay mapped all the time, so you can just access CPU pointer to it any time without a need to call any "map" or "unmap" function. Example:</p>
+<div class="fragment"><div class="line">VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };</div>
+<div class="line">bufCreateInfo.size = <span class="keyword">sizeof</span>(ConstantBuffer);</div>
+<div class="line">bufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;</div>
+<div class="line"> </div>
+<div class="line"><a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> allocCreateInfo = {};</div>
+<div class="line">allocCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910">usage</a> = <a class="code" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca40bdf4cddeffeb12f43d45ca1286e0a5">VMA_MEMORY_USAGE_CPU_ONLY</a>;</div>
+<div class="line">allocCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a> = <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a11da372cc3a82931c5e5d6146cd9dd1f">VMA_ALLOCATION_CREATE_MAPPED_BIT</a>;</div>
+<div class="line"> </div>
+<div class="line">VkBuffer buf;</div>
+<div class="line"><a class="code" href="struct_vma_allocation.html">VmaAllocation</a> alloc;</div>
+<div class="line"><a class="code" href="struct_vma_allocation_info.html">VmaAllocationInfo</a> allocInfo;</div>
+<div class="line"><a class="code" href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer</a>(allocator, &amp;bufCreateInfo, &amp;allocCreateInfo, &amp;buf, &amp;alloc, &amp;allocInfo);</div>
+<div class="line"> </div>
+<div class="line"><span class="comment">// Buffer is already mapped. You can access its memory.</span></div>
+<div class="line">memcpy(allocInfo.<a class="code" href="struct_vma_allocation_info.html#a5eeffbe2d2f30f53370ff14aefbadbe2">pMappedData</a>, &amp;constantBufferData, <span class="keyword">sizeof</span>(constantBufferData));</div>
+</div><!-- fragment --><p>There are some exceptions though, when you should consider mapping memory only for a short period of time:</p>
+<ul>
+<li>When operating system is Windows 7 or 8.x (Windows 10 is not affected because it uses WDDM2), device is discrete AMD GPU, and memory type is the special 256 MiB pool of <code>DEVICE_LOCAL + HOST_VISIBLE</code> memory (selected when you use <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca9066b52c5a7079bb74a69aaf8b92ff67">VMA_MEMORY_USAGE_CPU_TO_GPU</a>), then whenever a memory block allocated from this memory type stays mapped for the time of any call to <code>vkQueueSubmit()</code> or <code>vkQueuePresentKHR()</code>, this block is migrated by WDDM to system RAM, which degrades performance. It doesn't matter if that particular memory block is actually used by the command buffer being submitted.</li>
+<li>On Mac/MoltenVK there is a known bug - <a href="https://github.com/KhronosGroup/MoltenVK/issues/175">Issue #175</a> which requires unmapping before GPU can see updated texture.</li>
+<li>Keeping many large memory blocks mapped may impact performance or stability of some debugging tools.</li>
+</ul>
+<h1><a class="anchor" id="memory_mapping_cache_control"></a>
+Cache flush and invalidate</h1>
+<p>Memory in Vulkan doesn't need to be unmapped before using it on GPU, but unless a memory types has <code>VK_MEMORY_PROPERTY_HOST_COHERENT_BIT</code> flag set, you need to manually <b>invalidate</b> cache before reading of mapped pointer and <b>flush</b> cache after writing to mapped pointer. Map/unmap operations don't do that automatically. Vulkan provides following functions for this purpose <code>vkFlushMappedMemoryRanges()</code>, <code>vkInvalidateMappedMemoryRanges()</code>, but this library provides more convenient functions that refer to given allocation object: <a class="el" href="vk__mem__alloc_8h.html#abc34ee6f021f459aff885f3758c435de" title="Flushes memory of given allocation.">vmaFlushAllocation()</a>, <a class="el" href="vk__mem__alloc_8h.html#a0d0eb0c1102268fa9a476d12ecbe4006" title="Invalidates memory of given allocation.">vmaInvalidateAllocation()</a>.</p>
+<p>Regions of memory specified for flush/invalidate must be aligned to <code>VkPhysicalDeviceLimits::nonCoherentAtomSize</code>. This is automatically ensured by the library. In any memory type that is <code>HOST_VISIBLE</code> but not <code>HOST_COHERENT</code>, all allocations within blocks are aligned to this value, so their offsets are always multiply of <code>nonCoherentAtomSize</code> and two different allocations never share same "line" of this size.</p>
+<p>Please note that memory allocated with <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca40bdf4cddeffeb12f43d45ca1286e0a5">VMA_MEMORY_USAGE_CPU_ONLY</a> is guaranteed to be <code>HOST_COHERENT</code>.</p>
+<p>Also, Windows drivers from all 3 <b>PC</b> GPU vendors (AMD, Intel, NVIDIA) currently provide <code>HOST_COHERENT</code> flag on all memory types that are <code>HOST_VISIBLE</code>, so on this platform you may not need to bother.</p>
+<h1><a class="anchor" id="memory_mapping_finding_if_memory_mappable"></a>
+Finding out if memory is mappable</h1>
+<p>It may happen that your allocation ends up in memory that is <code>HOST_VISIBLE</code> (available for mapping) despite it wasn't explicitly requested. For example, application may work on integrated graphics with unified memory (like Intel) or allocation from video memory might have failed, so the library chose system memory as fallback.</p>
+<p>You can detect this case and map such allocation to access its memory on CPU directly, instead of launching a transfer operation. In order to do that: inspect <code>allocInfo.memoryType</code>, call <a class="el" href="vk__mem__alloc_8h.html#a8701444752eb5de4464adb5a2b514bca" title="Given Memory Type Index, returns Property Flags of this memory type.">vmaGetMemoryTypeProperties()</a>, and look for <code>VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT</code> flag in properties of that memory type.</p>
+<div class="fragment"><div class="line">VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };</div>
+<div class="line">bufCreateInfo.size = <span class="keyword">sizeof</span>(ConstantBuffer);</div>
+<div class="line">bufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;</div>
+<div class="line"> </div>
+<div class="line"><a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> allocCreateInfo = {};</div>
+<div class="line">allocCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910">usage</a> = <a class="code" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7">VMA_MEMORY_USAGE_GPU_ONLY</a>;</div>
+<div class="line">allocCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#a7fe8d81a1ad10b2a2faacacee5b15d6d">preferredFlags</a> = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;</div>
+<div class="line"> </div>
+<div class="line">VkBuffer buf;</div>
+<div class="line"><a class="code" href="struct_vma_allocation.html">VmaAllocation</a> alloc;</div>
+<div class="line"><a class="code" href="struct_vma_allocation_info.html">VmaAllocationInfo</a> allocInfo;</div>
+<div class="line"><a class="code" href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer</a>(allocator, &amp;bufCreateInfo, &amp;allocCreateInfo, &amp;buf, &amp;alloc, &amp;allocInfo);</div>
+<div class="line"> </div>
+<div class="line">VkMemoryPropertyFlags memFlags;</div>
+<div class="line"><a class="code" href="vk__mem__alloc_8h.html#a8701444752eb5de4464adb5a2b514bca">vmaGetMemoryTypeProperties</a>(allocator, allocInfo.<a class="code" href="struct_vma_allocation_info.html#a7f6b0aa58c135e488e6b40a388dad9d5">memoryType</a>, &amp;memFlags);</div>
+<div class="line"><span class="keywordflow">if</span>((memFlags &amp; VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0)</div>
+<div class="line">{</div>
+<div class="line">    <span class="comment">// Allocation ended up in mappable memory. You can map it and access it directly.</span></div>
+<div class="line">    <span class="keywordtype">void</span>* mappedData;</div>
+<div class="line">    <a class="code" href="vk__mem__alloc_8h.html#ad5bd1243512d099706de88168992f069">vmaMapMemory</a>(allocator, alloc, &amp;mappedData);</div>
+<div class="line">    memcpy(mappedData, &amp;constantBufferData, <span class="keyword">sizeof</span>(constantBufferData));</div>
+<div class="line">    <a class="code" href="vk__mem__alloc_8h.html#a9bc268595cb33f6ec4d519cfce81ff45">vmaUnmapMemory</a>(allocator, alloc);</div>
+<div class="line">}</div>
+<div class="line"><span class="keywordflow">else</span></div>
+<div class="line">{</div>
+<div class="line">    <span class="comment">// Allocation ended up in non-mappable memory.</span></div>
+<div class="line">    <span class="comment">// You need to create CPU-side buffer in VMA_MEMORY_USAGE_CPU_ONLY and make a transfer.</span></div>
+<div class="line">}</div>
+</div><!-- fragment --><p>You can even use <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a11da372cc3a82931c5e5d6146cd9dd1f" title="Set this flag to use a memory that will be persistently mapped and retrieve pointer to it.">VMA_ALLOCATION_CREATE_MAPPED_BIT</a> flag while creating allocations that are not necessarily <code>HOST_VISIBLE</code> (e.g. using <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7">VMA_MEMORY_USAGE_GPU_ONLY</a>). If the allocation ends up in memory type that is <code>HOST_VISIBLE</code>, it will be persistently mapped and you can use it directly. If not, the flag is just ignored. Example:</p>
+<div class="fragment"><div class="line">VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };</div>
+<div class="line">bufCreateInfo.size = <span class="keyword">sizeof</span>(ConstantBuffer);</div>
+<div class="line">bufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;</div>
+<div class="line"> </div>
+<div class="line"><a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> allocCreateInfo = {};</div>
+<div class="line">allocCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910">usage</a> = <a class="code" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7">VMA_MEMORY_USAGE_GPU_ONLY</a>;</div>
+<div class="line">allocCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a> = <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a11da372cc3a82931c5e5d6146cd9dd1f">VMA_ALLOCATION_CREATE_MAPPED_BIT</a>;</div>
+<div class="line"> </div>
+<div class="line">VkBuffer buf;</div>
+<div class="line"><a class="code" href="struct_vma_allocation.html">VmaAllocation</a> alloc;</div>
+<div class="line"><a class="code" href="struct_vma_allocation_info.html">VmaAllocationInfo</a> allocInfo;</div>
+<div class="line"><a class="code" href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer</a>(allocator, &amp;bufCreateInfo, &amp;allocCreateInfo, &amp;buf, &amp;alloc, &amp;allocInfo);</div>
+<div class="line"> </div>
+<div class="line"><span class="keywordflow">if</span>(allocInfo.<a class="code" href="struct_vma_allocation_info.html#adc507656149c04de7ed95d0042ba2a13">pUserData</a> != <span class="keyword">nullptr</span>)</div>
+<div class="line">{</div>
+<div class="line">    <span class="comment">// Allocation ended up in mappable memory.</span></div>
+<div class="line">    <span class="comment">// It&#39;s persistently mapped. You can access it directly.</span></div>
+<div class="line">    memcpy(allocInfo.<a class="code" href="struct_vma_allocation_info.html#a5eeffbe2d2f30f53370ff14aefbadbe2">pMappedData</a>, &amp;constantBufferData, <span class="keyword">sizeof</span>(constantBufferData));</div>
+<div class="line">}</div>
+<div class="line"><span class="keywordflow">else</span></div>
+<div class="line">{</div>
+<div class="line">    <span class="comment">// Allocation ended up in non-mappable memory.</span></div>
+<div class="line">    <span class="comment">// You need to create CPU-side buffer in VMA_MEMORY_USAGE_CPU_ONLY and make a transfer.</span></div>
+<div class="line">}</div>
+</div><!-- fragment --> </div></div><!-- contents -->
+</div><!-- PageDoc -->
+<div class="ttc" id="avk__mem__alloc_8h_html_a9bc268595cb33f6ec4d519cfce81ff45"><div class="ttname"><a href="vk__mem__alloc_8h.html#a9bc268595cb33f6ec4d519cfce81ff45">vmaUnmapMemory</a></div><div class="ttdeci">void vmaUnmapMemory(VmaAllocator allocator, VmaAllocation allocation)</div><div class="ttdoc">Unmaps memory represented by given allocation, mapped previously using vmaMapMemory().</div></div>
+<div class="ttc" id="astruct_vma_allocator_html"><div class="ttname"><a href="struct_vma_allocator.html">VmaAllocator</a></div><div class="ttdoc">Represents main object of this library initialized.</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a8701444752eb5de4464adb5a2b514bca"><div class="ttname"><a href="vk__mem__alloc_8h.html#a8701444752eb5de4464adb5a2b514bca">vmaGetMemoryTypeProperties</a></div><div class="ttdeci">void vmaGetMemoryTypeProperties(VmaAllocator allocator, uint32_t memoryTypeIndex, VkMemoryPropertyFlags *pFlags)</div><div class="ttdoc">Given Memory Type Index, returns Property Flags of this memory type.</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_aa5846affa1e9da3800e3e78fae2305cca40bdf4cddeffeb12f43d45ca1286e0a5"><div class="ttname"><a href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca40bdf4cddeffeb12f43d45ca1286e0a5">VMA_MEMORY_USAGE_CPU_ONLY</a></div><div class="ttdeci">@ VMA_MEMORY_USAGE_CPU_ONLY</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2491</div></div>
+<div class="ttc" id="astruct_vma_allocation_html"><div class="ttname"><a href="struct_vma_allocation.html">VmaAllocation</a></div><div class="ttdoc">Represents single memory allocation.</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7"><div class="ttname"><a href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7">VMA_MEMORY_USAGE_GPU_ONLY</a></div><div class="ttdeci">@ VMA_MEMORY_USAGE_GPU_ONLY</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2481</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ad5bd1243512d099706de88168992f069"><div class="ttname"><a href="vk__mem__alloc_8h.html#ad5bd1243512d099706de88168992f069">vmaMapMemory</a></div><div class="ttdeci">VkResult vmaMapMemory(VmaAllocator allocator, VmaAllocation allocation, void **ppData)</div><div class="ttdoc">Maps memory represented by given allocation and returns pointer to it.</div></div>
+<div class="ttc" id="astruct_vma_allocation_info_html_a5eeffbe2d2f30f53370ff14aefbadbe2"><div class="ttname"><a href="struct_vma_allocation_info.html#a5eeffbe2d2f30f53370ff14aefbadbe2">VmaAllocationInfo::pMappedData</a></div><div class="ttdeci">void * pMappedData</div><div class="ttdoc">Pointer to the beginning of this allocation as mapped data.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3009</div></div>
+<div class="ttc" id="astruct_vma_allocation_create_info_html_accb8b06b1f677d858cb9af20705fa910"><div class="ttname"><a href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910">VmaAllocationCreateInfo::usage</a></div><div class="ttdeci">VmaMemoryUsage usage</div><div class="ttdoc">Intended usage of memory.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2647</div></div>
+<div class="ttc" id="astruct_vma_allocation_info_html_adc507656149c04de7ed95d0042ba2a13"><div class="ttname"><a href="struct_vma_allocation_info.html#adc507656149c04de7ed95d0042ba2a13">VmaAllocationInfo::pUserData</a></div><div class="ttdeci">void * pUserData</div><div class="ttdoc">Custom general-purpose pointer that was passed as VmaAllocationCreateInfo::pUserData or set using vma...</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3014</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ac72ee55598617e8eecca384e746bab51"><div class="ttname"><a href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer</a></div><div class="ttdeci">VkResult vmaCreateBuffer(VmaAllocator allocator, const VkBufferCreateInfo *pBufferCreateInfo, const VmaAllocationCreateInfo *pAllocationCreateInfo, VkBuffer *pBuffer, VmaAllocation *pAllocation, VmaAllocationInfo *pAllocationInfo)</div></div>
+<div class="ttc" id="astruct_vma_allocation_info_html_a7f6b0aa58c135e488e6b40a388dad9d5"><div class="ttname"><a href="struct_vma_allocation_info.html#a7f6b0aa58c135e488e6b40a388dad9d5">VmaAllocationInfo::memoryType</a></div><div class="ttdeci">uint32_t memoryType</div><div class="ttdoc">Memory type index that this allocation was allocated from.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2981</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ad9889c10c798b040d59c92f257cae597a11da372cc3a82931c5e5d6146cd9dd1f"><div class="ttname"><a href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a11da372cc3a82931c5e5d6146cd9dd1f">VMA_ALLOCATION_CREATE_MAPPED_BIT</a></div><div class="ttdeci">@ VMA_ALLOCATION_CREATE_MAPPED_BIT</div><div class="ttdoc">Set this flag to use a memory that will be persistently mapped and retrieve pointer to it.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2558</div></div>
+<div class="ttc" id="astruct_vma_allocation_create_info_html_add09658ac14fe290ace25470ddd6d41b"><div class="ttname"><a href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">VmaAllocationCreateInfo::flags</a></div><div class="ttdeci">VmaAllocationCreateFlags flags</div><div class="ttdoc">Use VmaAllocationCreateFlagBits enum.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2641</div></div>
+<div class="ttc" id="astruct_vma_allocation_create_info_html"><div class="ttname"><a href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a></div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2638</div></div>
+<div class="ttc" id="astruct_vma_allocation_create_info_html_a7fe8d81a1ad10b2a2faacacee5b15d6d"><div class="ttname"><a href="struct_vma_allocation_create_info.html#a7fe8d81a1ad10b2a2faacacee5b15d6d">VmaAllocationCreateInfo::preferredFlags</a></div><div class="ttdeci">VkMemoryPropertyFlags preferredFlags</div><div class="ttdoc">Flags that preferably should be set in a memory type chosen for an allocation.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2657</div></div>
+<div class="ttc" id="astruct_vma_allocation_info_html"><div class="ttname"><a href="struct_vma_allocation_info.html">VmaAllocationInfo</a></div><div class="ttdoc">Parameters of VmaAllocation objects, that can be retrieved using function vmaGetAllocationInfo().</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2976</div></div>
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/menu.js b/third_party/VulkanMemoryAllocator/docs/html/menu.js
new file mode 100644
index 0000000..433c15b
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/menu.js
@@ -0,0 +1,50 @@
+/*
+ @licstart  The following is the entire license notice for the
+ JavaScript code in this file.
+
+ Copyright (C) 1997-2017 by Dimitri van Heesch
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ @licend  The above is the entire license notice
+ for the JavaScript code in this file
+ */
+function initMenu(relPath,searchEnabled,serverSide,searchPage,search) {
+  function makeTree(data,relPath) {
+    var result='';
+    if ('children' in data) {
+      result+='<ul>';
+      for (var i in data.children) {
+        result+='<li><a href="'+relPath+data.children[i].url+'">'+
+                                data.children[i].text+'</a>'+
+                                makeTree(data.children[i],relPath)+'</li>';
+      }
+      result+='</ul>';
+    }
+    return result;
+  }
+
+  $('#main-nav').append(makeTree(menudata,relPath));
+  $('#main-nav').children(':first').addClass('sm sm-dox').attr('id','main-menu');
+  if (searchEnabled) {
+    if (serverSide) {
+      $('#main-menu').append('<li style="float:right"><div id="MSearchBox" class="MSearchBoxInactive"><div class="left"><form id="FSearchBox" action="'+relPath+searchPage+'" method="get"><img id="MSearchSelect" src="'+relPath+'search/mag.png" alt=""/><input type="text" id="MSearchField" name="query" value="'+search+'" size="20" accesskey="S" onfocus="searchBox.OnSearchFieldFocus(true)" onblur="searchBox.OnSearchFieldFocus(false)"></form></div><div class="right"></div></div></li>');
+    } else {
+      $('#main-menu').append('<li style="float:right"><div id="MSearchBox" class="MSearchBoxInactive"><span class="left"><img id="MSearchSelect" src="'+relPath+'search/mag_sel.png" onmouseover="return searchBox.OnSearchSelectShow()" onmouseout="return searchBox.OnSearchSelectHide()" alt=""/><input type="text" id="MSearchField" value="'+search+'" accesskey="S" onfocus="searchBox.OnSearchFieldFocus(true)" onblur="searchBox.OnSearchFieldFocus(false)" onkeyup="searchBox.OnSearchFieldChange(event)"/></span><span class="right"><a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="'+relPath+'search/close.png" alt=""/></a></span></div></li>');
+    }
+  }
+  $('#main-menu').smartmenus();
+}
+/* @license-end */
diff --git a/third_party/VulkanMemoryAllocator/docs/html/menudata.js b/third_party/VulkanMemoryAllocator/docs/html/menudata.js
new file mode 100644
index 0000000..68ce88e
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/menudata.js
@@ -0,0 +1,73 @@
+/*
+@licstart  The following is the entire license notice for the
+JavaScript code in this file.
+
+Copyright (C) 1997-2019 by Dimitri van Heesch
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of version 2 of the GNU General Public License as published by
+the Free Software Foundation
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+@licend  The above is the entire license notice
+for the JavaScript code in this file
+*/
+var menudata={children:[
+{text:"Main Page",url:"index.html"},
+{text:"Related Pages",url:"pages.html"},
+{text:"Classes",url:"annotated.html",children:[
+{text:"Class List",url:"annotated.html"},
+{text:"Class Index",url:"classes.html"},
+{text:"Class Members",url:"functions.html",children:[
+{text:"All",url:"functions.html",children:[
+{text:"a",url:"functions.html#index_a"},
+{text:"b",url:"functions.html#index_b"},
+{text:"c",url:"functions.html#index_c"},
+{text:"d",url:"functions.html#index_d"},
+{text:"f",url:"functions.html#index_f"},
+{text:"i",url:"functions.html#index_i"},
+{text:"m",url:"functions.html#index_m"},
+{text:"o",url:"functions.html#index_o"},
+{text:"p",url:"functions.html#index_p"},
+{text:"r",url:"functions.html#index_r"},
+{text:"s",url:"functions.html#index_s"},
+{text:"t",url:"functions.html#index_t"},
+{text:"u",url:"functions.html#index_u"},
+{text:"v",url:"functions.html#index_v"}]},
+{text:"Variables",url:"functions_vars.html",children:[
+{text:"a",url:"functions_vars.html#index_a"},
+{text:"b",url:"functions_vars.html#index_b"},
+{text:"c",url:"functions_vars.html#index_c"},
+{text:"d",url:"functions_vars.html#index_d"},
+{text:"f",url:"functions_vars.html#index_f"},
+{text:"i",url:"functions_vars.html#index_i"},
+{text:"m",url:"functions_vars.html#index_m"},
+{text:"o",url:"functions_vars.html#index_o"},
+{text:"p",url:"functions_vars.html#index_p"},
+{text:"r",url:"functions_vars.html#index_r"},
+{text:"s",url:"functions_vars.html#index_s"},
+{text:"t",url:"functions_vars.html#index_t"},
+{text:"u",url:"functions_vars.html#index_u"},
+{text:"v",url:"functions_vars.html#index_v"}]}]}]},
+{text:"Files",url:"files.html",children:[
+{text:"File List",url:"files.html"},
+{text:"File Members",url:"globals.html",children:[
+{text:"All",url:"globals.html",children:[
+{text:"n",url:"globals.html#index_n"},
+{text:"p",url:"globals.html#index_p"},
+{text:"v",url:"globals.html#index_v"}]},
+{text:"Functions",url:"globals_func.html",children:[
+{text:"v",url:"globals_func.html#index_v"}]},
+{text:"Typedefs",url:"globals_type.html"},
+{text:"Enumerations",url:"globals_enum.html"},
+{text:"Enumerator",url:"globals_eval.html",children:[
+{text:"v",url:"globals_eval.html#index_v"}]},
+{text:"Macros",url:"globals_defs.html"}]}]}]}
diff --git a/third_party/VulkanMemoryAllocator/docs/html/nav_f.png b/third_party/VulkanMemoryAllocator/docs/html/nav_f.png
new file mode 100644
index 0000000..72a58a5
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/nav_f.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/docs/html/nav_g.png b/third_party/VulkanMemoryAllocator/docs/html/nav_g.png
new file mode 100644
index 0000000..2093a23
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/nav_g.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/docs/html/nav_h.png b/third_party/VulkanMemoryAllocator/docs/html/nav_h.png
new file mode 100644
index 0000000..33389b1
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/nav_h.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/docs/html/open.png b/third_party/VulkanMemoryAllocator/docs/html/open.png
new file mode 100644
index 0000000..30f75c7
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/open.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/docs/html/pages.html b/third_party/VulkanMemoryAllocator/docs/html/pages.html
new file mode 100644
index 0000000..4ba6a9d
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/pages.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: Related Pages</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+  <div class="headertitle">
+<div class="title">Related Pages</div>  </div>
+</div><!--header-->
+<div class="contents">
+<div class="textblock">Here is a list of all related documentation pages:</div><div class="directory">
+<table class="directory">
+<tr id="row_0_" class="even"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><a class="el" href="deprecated.html" target="_self">Deprecated List</a></td><td class="desc"></td></tr>
+</table>
+</div><!-- directory -->
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/quick_start.html b/third_party/VulkanMemoryAllocator/docs/html/quick_start.html
new file mode 100644
index 0000000..cf300ef
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/quick_start.html
@@ -0,0 +1,141 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: Quick start</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+  <ul>
+<li class="navelem"><a class="el" href="index.html">Vulkan Memory Allocator</a></li>  </ul>
+</div>
+</div><!-- top -->
+<div class="PageDoc"><div class="header">
+  <div class="headertitle">
+<div class="title">Quick start </div>  </div>
+</div><!--header-->
+<div class="contents">
+<div class="textblock"><h1><a class="anchor" id="quick_start_project_setup"></a>
+Project setup</h1>
+<p>Vulkan Memory Allocator comes in form of a "stb-style" single header file. You don't need to build it as a separate library project. You can add this file directly to your project and submit it to code repository next to your other source files.</p>
+<p>"Single header" doesn't mean that everything is contained in C/C++ declarations, like it tends to be in case of inline functions or C++ templates. It means that implementation is bundled with interface in a single file and needs to be extracted using preprocessor macro. If you don't do it properly, you will get linker errors.</p>
+<p>To do it properly:</p>
+<ol type="1">
+<li>Include "vk_mem_alloc.h" file in each CPP file where you want to use the library. This includes declarations of all members of the library.</li>
+<li>In exacly one CPP file define following macro before this include. It enables also internal definitions.</li>
+</ol>
+<div class="fragment"><div class="line"><span class="preprocessor">#define VMA_IMPLEMENTATION</span></div>
+<div class="line"><span class="preprocessor">#include &quot;vk_mem_alloc.h&quot;</span></div>
+</div><!-- fragment --><p>It may be a good idea to create dedicated CPP file just for this purpose.</p>
+<p>Note on language: This library is written in C++, but has C-compatible interface. Thus you can include and use <a class="el" href="vk__mem__alloc_8h.html">vk_mem_alloc.h</a> in C or C++ code, but full implementation with <code>VMA_IMPLEMENTATION</code> macro must be compiled as C++, NOT as C.</p>
+<p>Please note that this library includes header <code>&lt;vulkan/vulkan.h&gt;</code>, which in turn includes <code>&lt;windows.h&gt;</code> on Windows. If you need some specific macros defined before including these headers (like <code>WIN32_LEAN_AND_MEAN</code> or <code>WINVER</code> for Windows, <code>VK_USE_PLATFORM_WIN32_KHR</code> for Vulkan), you must define them before every <code>#include</code> of this library.</p>
+<h1><a class="anchor" id="quick_start_initialization"></a>
+Initialization</h1>
+<p>At program startup:</p>
+<ol type="1">
+<li>Initialize Vulkan to have <code>VkPhysicalDevice</code> and <code>VkDevice</code> object.</li>
+<li>Fill <a class="el" href="struct_vma_allocator_create_info.html" title="Description of a Allocator to be created.">VmaAllocatorCreateInfo</a> structure and create <a class="el" href="struct_vma_allocator.html" title="Represents main object of this library initialized.">VmaAllocator</a> object by calling <a class="el" href="vk__mem__alloc_8h.html#a200692051ddb34240248234f5f4c17bb" title="Creates Allocator object.">vmaCreateAllocator()</a>.</li>
+</ol>
+<div class="fragment"><div class="line"><a class="code" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a> allocatorInfo = {};</div>
+<div class="line">allocatorInfo.<a class="code" href="struct_vma_allocator_create_info.html#a08230f04ae6ccf8a78150a9e829a7156">physicalDevice</a> = physicalDevice;</div>
+<div class="line">allocatorInfo.<a class="code" href="struct_vma_allocator_create_info.html#ad924ddd77b04039c88d0c09b0ffcd500">device</a> = device;</div>
+<div class="line"> </div>
+<div class="line"><a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator;</div>
+<div class="line"><a class="code" href="vk__mem__alloc_8h.html#a200692051ddb34240248234f5f4c17bb">vmaCreateAllocator</a>(&amp;allocatorInfo, &amp;allocator);</div>
+</div><!-- fragment --><h1><a class="anchor" id="quick_start_resource_allocation"></a>
+Resource allocation</h1>
+<p>When you want to create a buffer or image:</p>
+<ol type="1">
+<li>Fill <code>VkBufferCreateInfo</code> / <code>VkImageCreateInfo</code> structure.</li>
+<li>Fill <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> structure.</li>
+<li>Call <a class="el" href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer()</a> / <a class="el" href="vk__mem__alloc_8h.html#a02a94f25679275851a53e82eacbcfc73" title="Function similar to vmaCreateBuffer().">vmaCreateImage()</a> to get <code>VkBuffer</code>/<code>VkImage</code> with memory already allocated and bound to it.</li>
+</ol>
+<div class="fragment"><div class="line">VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };</div>
+<div class="line">bufferInfo.size = 65536;</div>
+<div class="line">bufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;</div>
+<div class="line"> </div>
+<div class="line"><a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> allocInfo = {};</div>
+<div class="line">allocInfo.<a class="code" href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910">usage</a> = <a class="code" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7">VMA_MEMORY_USAGE_GPU_ONLY</a>;</div>
+<div class="line"> </div>
+<div class="line">VkBuffer buffer;</div>
+<div class="line"><a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation;</div>
+<div class="line"><a class="code" href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer</a>(allocator, &amp;bufferInfo, &amp;allocInfo, &amp;buffer, &amp;allocation, <span class="keyword">nullptr</span>);</div>
+</div><!-- fragment --><p>Don't forget to destroy your objects when no longer needed:</p>
+<div class="fragment"><div class="line"><a class="code" href="vk__mem__alloc_8h.html#a0d9f4e4ba5bf9aab1f1c746387753d77">vmaDestroyBuffer</a>(allocator, buffer, allocation);</div>
+<div class="line"><a class="code" href="vk__mem__alloc_8h.html#aa8d164061c88f22fb1fd3c8f3534bc1d">vmaDestroyAllocator</a>(allocator);</div>
+</div><!-- fragment --> </div></div><!-- contents -->
+</div><!-- PageDoc -->
+<div class="ttc" id="astruct_vma_allocator_create_info_html_a08230f04ae6ccf8a78150a9e829a7156"><div class="ttname"><a href="struct_vma_allocator_create_info.html#a08230f04ae6ccf8a78150a9e829a7156">VmaAllocatorCreateInfo::physicalDevice</a></div><div class="ttdeci">VkPhysicalDevice physicalDevice</div><div class="ttdoc">Vulkan physical device.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2179</div></div>
+<div class="ttc" id="astruct_vma_allocator_html"><div class="ttname"><a href="struct_vma_allocator.html">VmaAllocator</a></div><div class="ttdoc">Represents main object of this library initialized.</div></div>
+<div class="ttc" id="astruct_vma_allocator_create_info_html"><div class="ttname"><a href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a></div><div class="ttdoc">Description of a Allocator to be created.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2173</div></div>
+<div class="ttc" id="astruct_vma_allocation_html"><div class="ttname"><a href="struct_vma_allocation.html">VmaAllocation</a></div><div class="ttdoc">Represents single memory allocation.</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7"><div class="ttname"><a href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7">VMA_MEMORY_USAGE_GPU_ONLY</a></div><div class="ttdeci">@ VMA_MEMORY_USAGE_GPU_ONLY</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2481</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_aa8d164061c88f22fb1fd3c8f3534bc1d"><div class="ttname"><a href="vk__mem__alloc_8h.html#aa8d164061c88f22fb1fd3c8f3534bc1d">vmaDestroyAllocator</a></div><div class="ttdeci">void vmaDestroyAllocator(VmaAllocator allocator)</div><div class="ttdoc">Destroys allocator object.</div></div>
+<div class="ttc" id="astruct_vma_allocator_create_info_html_ad924ddd77b04039c88d0c09b0ffcd500"><div class="ttname"><a href="struct_vma_allocator_create_info.html#ad924ddd77b04039c88d0c09b0ffcd500">VmaAllocatorCreateInfo::device</a></div><div class="ttdeci">VkDevice device</div><div class="ttdoc">Vulkan device.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2182</div></div>
+<div class="ttc" id="astruct_vma_allocation_create_info_html_accb8b06b1f677d858cb9af20705fa910"><div class="ttname"><a href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910">VmaAllocationCreateInfo::usage</a></div><div class="ttdeci">VmaMemoryUsage usage</div><div class="ttdoc">Intended usage of memory.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2647</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ac72ee55598617e8eecca384e746bab51"><div class="ttname"><a href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer</a></div><div class="ttdeci">VkResult vmaCreateBuffer(VmaAllocator allocator, const VkBufferCreateInfo *pBufferCreateInfo, const VmaAllocationCreateInfo *pAllocationCreateInfo, VkBuffer *pBuffer, VmaAllocation *pAllocation, VmaAllocationInfo *pAllocationInfo)</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a200692051ddb34240248234f5f4c17bb"><div class="ttname"><a href="vk__mem__alloc_8h.html#a200692051ddb34240248234f5f4c17bb">vmaCreateAllocator</a></div><div class="ttdeci">VkResult vmaCreateAllocator(const VmaAllocatorCreateInfo *pCreateInfo, VmaAllocator *pAllocator)</div><div class="ttdoc">Creates Allocator object.</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a0d9f4e4ba5bf9aab1f1c746387753d77"><div class="ttname"><a href="vk__mem__alloc_8h.html#a0d9f4e4ba5bf9aab1f1c746387753d77">vmaDestroyBuffer</a></div><div class="ttdeci">void vmaDestroyBuffer(VmaAllocator allocator, VkBuffer buffer, VmaAllocation allocation)</div><div class="ttdoc">Destroys Vulkan buffer and frees allocated memory.</div></div>
+<div class="ttc" id="astruct_vma_allocation_create_info_html"><div class="ttname"><a href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a></div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2638</div></div>
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/record_and_replay.html b/third_party/VulkanMemoryAllocator/docs/html/record_and_replay.html
new file mode 100644
index 0000000..7be58b4
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/record_and_replay.html
@@ -0,0 +1,102 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: Record and replay</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+  <ul>
+<li class="navelem"><a class="el" href="index.html">Vulkan Memory Allocator</a></li>  </ul>
+</div>
+</div><!-- top -->
+<div class="PageDoc"><div class="header">
+  <div class="headertitle">
+<div class="title">Record and replay </div>  </div>
+</div><!--header-->
+<div class="contents">
+<div class="textblock"><h1><a class="anchor" id="record_and_replay_introduction"></a>
+Introduction</h1>
+<p>While using the library, sequence of calls to its functions together with their parameters can be recorded to a file and later replayed using standalone player application. It can be useful to:</p>
+<ul>
+<li>Test correctness - check if same sequence of calls will not cause crash or failures on a target platform.</li>
+<li>Gather statistics - see number of allocations, peak memory usage, number of calls etc.</li>
+<li>Benchmark performance - see how much time it takes to replay the whole sequence.</li>
+</ul>
+<h1><a class="anchor" id="record_and_replay_usage"></a>
+Usage</h1>
+<p>Recording functionality is disabled by default. To enable it, define following macro before every include of this library:</p>
+<div class="fragment"><div class="line"><span class="preprocessor">#define VMA_RECORDING_ENABLED 1</span></div>
+</div><!-- fragment --><p><b>To record sequence of calls to a file:</b> Fill in <a class="el" href="struct_vma_allocator_create_info.html#ace2aa4877b16a42b0b7673d4e26000ee" title="Parameters for recording of VMA calls. Can be null.">VmaAllocatorCreateInfo::pRecordSettings</a> member while creating <a class="el" href="struct_vma_allocator.html" title="Represents main object of this library initialized.">VmaAllocator</a> object. File is opened and written during whole lifetime of the allocator.</p>
+<p><b>To replay file:</b> Use VmaReplay - standalone command-line program. Precompiled binary can be found in "bin" directory. Its source can be found in "src/VmaReplay" directory. Its project is generated by Premake. Command line syntax is printed when the program is launched without parameters. Basic usage: </p><pre class="fragment">VmaReplay.exe MyRecording.csv
+</pre><p><b>Documentation of file format</b> can be found in file: "docs/Recording file format.md". It's a human-readable, text file in CSV format (Comma Separated Values).</p>
+<h1><a class="anchor" id="record_and_replay_additional_considerations"></a>
+Additional considerations</h1>
+<ul>
+<li>Replaying file that was recorded on a different GPU (with different parameters like <code>bufferImageGranularity</code>, <code>nonCoherentAtomSize</code>, and especially different set of memory heaps and types) may give different performance and memory usage results, as well as issue some warnings and errors.</li>
+<li>Current implementation of recording in VMA, as well as VmaReplay application, is coded and tested only on Windows. Inclusion of recording code is driven by <code>VMA_RECORDING_ENABLED</code> macro. Support for other platforms should be easy to add. Contributions are welcomed. </li>
+</ul>
+</div></div><!-- contents -->
+</div><!-- PageDoc -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/all_0.html b/third_party/VulkanMemoryAllocator/docs/html/search/all_0.html
new file mode 100644
index 0000000..26dd244
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/all_0.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_0.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/all_0.js b/third_party/VulkanMemoryAllocator/docs/html/search/all_0.js
new file mode 100644
index 0000000..6b1115d
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/all_0.js
@@ -0,0 +1,11 @@
+var searchData=
+[
+  ['allocation_0',['allocation',['../struct_vma_defragmentation_pass_move_info.html#ae885c861c2dd8d622e6c19e281d035cc',1,'VmaDefragmentationPassMoveInfo']]],
+  ['allocation_20names_20and_20user_20data_1',['Allocation names and user data',['../allocation_annotation.html',1,'index']]],
+  ['allocationbytes_2',['allocationBytes',['../struct_vma_budget.html#a7e2a6583ebd63e194951c542563804d8',1,'VmaBudget']]],
+  ['allocationcount_3',['allocationCount',['../struct_vma_stat_info.html#a537741e4d5cdddc1c0ab95ec650afaff',1,'VmaStatInfo::allocationCount()'],['../struct_vma_pool_stats.html#ad1924eb54fffa45e9e0e65670c8fe5eb',1,'VmaPoolStats::allocationCount()'],['../struct_vma_defragmentation_info2.html#a3cf86ab32c1da779b4923d301a3056ba',1,'VmaDefragmentationInfo2::allocationCount()']]],
+  ['allocationsizeavg_4',['allocationSizeAvg',['../struct_vma_stat_info.html#a1081a039964e566c672e7a2347f9e599',1,'VmaStatInfo']]],
+  ['allocationsizemax_5',['allocationSizeMax',['../struct_vma_stat_info.html#a17e9733a5ecd76287d4db6e66f71f50c',1,'VmaStatInfo']]],
+  ['allocationsizemin_6',['allocationSizeMin',['../struct_vma_stat_info.html#ade8b40bd3139c04aabd2fc538a356fea',1,'VmaStatInfo']]],
+  ['allocationsmoved_7',['allocationsMoved',['../struct_vma_defragmentation_stats.html#aefeabf130022008eadd75999478af3f9',1,'VmaDefragmentationStats']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/all_1.html b/third_party/VulkanMemoryAllocator/docs/html/search/all_1.html
new file mode 100644
index 0000000..8eb215b
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/all_1.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_1.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/all_1.js b/third_party/VulkanMemoryAllocator/docs/html/search/all_1.js
new file mode 100644
index 0000000..c90e7ad
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/all_1.js
@@ -0,0 +1,9 @@
+var searchData=
+[
+  ['blockbytes_8',['blockBytes',['../struct_vma_budget.html#a58b492901baab685f466199124e514a0',1,'VmaBudget']]],
+  ['blockcount_9',['blockCount',['../struct_vma_stat_info.html#abc4bb7cd611900778464c56e50c970a4',1,'VmaStatInfo::blockCount()'],['../struct_vma_pool_stats.html#aa0b5cb45cef6f18571cefb03b9a230e7',1,'VmaPoolStats::blockCount()']]],
+  ['blocksize_10',['blockSize',['../struct_vma_pool_create_info.html#aa4265160536cdb9be821b7686c16c676',1,'VmaPoolCreateInfo']]],
+  ['budget_11',['budget',['../struct_vma_budget.html#ab82e1d1754c2d210d0bdf90220bc6cdd',1,'VmaBudget']]],
+  ['bytesfreed_12',['bytesFreed',['../struct_vma_defragmentation_stats.html#ab0cb9ac0dbc106c77e384ea676422f28',1,'VmaDefragmentationStats']]],
+  ['bytesmoved_13',['bytesMoved',['../struct_vma_defragmentation_stats.html#a36f9d5df2a10ba2a36b16e126d60572d',1,'VmaDefragmentationStats']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/all_10.html b/third_party/VulkanMemoryAllocator/docs/html/search/all_10.html
new file mode 100644
index 0000000..6fd3a4a
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/all_10.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_10.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/all_10.js b/third_party/VulkanMemoryAllocator/docs/html/search/all_10.js
new file mode 100644
index 0000000..628d913
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/all_10.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['total_75',['total',['../struct_vma_stats.html#a2e8f5b3353f2fefef3c27f29e245a1f9',1,'VmaStats']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/all_11.html b/third_party/VulkanMemoryAllocator/docs/html/search/all_11.html
new file mode 100644
index 0000000..f78343b
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/all_11.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_11.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/all_11.js b/third_party/VulkanMemoryAllocator/docs/html/search/all_11.js
new file mode 100644
index 0000000..c96bee2
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/all_11.js
@@ -0,0 +1,11 @@
+var searchData=
+[
+  ['unusedbytes_76',['unusedBytes',['../struct_vma_stat_info.html#a1859d290aca2cd582d8dc25922092669',1,'VmaStatInfo']]],
+  ['unusedrangecount_77',['unusedRangeCount',['../struct_vma_stat_info.html#ae06129c771bfebfd6468a7f4276502a9',1,'VmaStatInfo::unusedRangeCount()'],['../struct_vma_pool_stats.html#ae4f3546ffa4d1e598b64d8e6134854f4',1,'VmaPoolStats::unusedRangeCount()']]],
+  ['unusedrangesizeavg_78',['unusedRangeSizeAvg',['../struct_vma_stat_info.html#a2f9b3452af90c9768a30b7fb6ae194fc',1,'VmaStatInfo']]],
+  ['unusedrangesizemax_79',['unusedRangeSizeMax',['../struct_vma_stat_info.html#a5ba1a2476c4d39b10f7e2f7ebbb72ac4',1,'VmaStatInfo::unusedRangeSizeMax()'],['../struct_vma_pool_stats.html#ab4c8f52dd42ab01998f60f0b6acc722b',1,'VmaPoolStats::unusedRangeSizeMax()']]],
+  ['unusedrangesizemin_80',['unusedRangeSizeMin',['../struct_vma_stat_info.html#aedeba931324f16589cd2416c0d2dd0d4',1,'VmaStatInfo']]],
+  ['unusedsize_81',['unusedSize',['../struct_vma_pool_stats.html#ad7c54874724fce7b06aba526202d82a8',1,'VmaPoolStats']]],
+  ['usage_82',['usage',['../struct_vma_budget.html#a84dd1ecca8b0110259eb206dbadb11f6',1,'VmaBudget::usage()'],['../struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910',1,'VmaAllocationCreateInfo::usage()']]],
+  ['usedbytes_83',['usedBytes',['../struct_vma_stat_info.html#ab0c6c73837e5a70c749fbd4f6064895a',1,'VmaStatInfo']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/all_12.html b/third_party/VulkanMemoryAllocator/docs/html/search/all_12.html
new file mode 100644
index 0000000..dd9ff1d
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/all_12.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_12.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/all_12.js b/third_party/VulkanMemoryAllocator/docs/html/search/all_12.js
new file mode 100644
index 0000000..ae6f65e
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/all_12.js
@@ -0,0 +1,155 @@
+var searchData=
+[
+  ['vulkan_20memory_20allocator_84',['Vulkan Memory Allocator',['../index.html',1,'']]],
+  ['vk_5famd_5fdevice_5fcoherent_5fmemory_85',['VK_AMD_device_coherent_memory',['../vk_amd_device_coherent_memory.html',1,'index']]],
+  ['vk_5fkhr_5fdedicated_5fallocation_86',['VK_KHR_dedicated_allocation',['../vk_khr_dedicated_allocation.html',1,'index']]],
+  ['vk_5fmem_5falloc_2eh_87',['vk_mem_alloc.h',['../vk__mem__alloc_8h.html',1,'']]],
+  ['vkallocatememory_88',['vkAllocateMemory',['../struct_vma_vulkan_functions.html#a2943bf99dfd784a0e8f599d987e22e6c',1,'VmaVulkanFunctions']]],
+  ['vkbindbuffermemory_89',['vkBindBufferMemory',['../struct_vma_vulkan_functions.html#a94fc4f3a605d9880bb3c0ba2c2fc80b2',1,'VmaVulkanFunctions']]],
+  ['vkbindimagememory_90',['vkBindImageMemory',['../struct_vma_vulkan_functions.html#a1338d96a128a5ade648b8d934907c637',1,'VmaVulkanFunctions']]],
+  ['vkcmdcopybuffer_91',['vkCmdCopyBuffer',['../struct_vma_vulkan_functions.html#ae5c0db8c89a3b82593dc16aa6a49fa3a',1,'VmaVulkanFunctions']]],
+  ['vkcreatebuffer_92',['vkCreateBuffer',['../struct_vma_vulkan_functions.html#ae8084315a25006271a2edfc3a447519f',1,'VmaVulkanFunctions']]],
+  ['vkcreateimage_93',['vkCreateImage',['../struct_vma_vulkan_functions.html#a23ebe70be515b9b5010a1d691200e325',1,'VmaVulkanFunctions']]],
+  ['vkdestroybuffer_94',['vkDestroyBuffer',['../struct_vma_vulkan_functions.html#a7e054606faddb07f0e8556f3ed317d45',1,'VmaVulkanFunctions']]],
+  ['vkdestroyimage_95',['vkDestroyImage',['../struct_vma_vulkan_functions.html#a90b898227039b1dcb3520f6e91f09ffa',1,'VmaVulkanFunctions']]],
+  ['vkflushmappedmemoryranges_96',['vkFlushMappedMemoryRanges',['../struct_vma_vulkan_functions.html#a33c322f4c4ad2810f8a9c97a277572f9',1,'VmaVulkanFunctions']]],
+  ['vkfreememory_97',['vkFreeMemory',['../struct_vma_vulkan_functions.html#a4c658701778564d62034255b5dda91b4',1,'VmaVulkanFunctions']]],
+  ['vkgetbuffermemoryrequirements_98',['vkGetBufferMemoryRequirements',['../struct_vma_vulkan_functions.html#a5b92901df89a4194b0d12f6071d4d143',1,'VmaVulkanFunctions']]],
+  ['vkgetimagememoryrequirements_99',['vkGetImageMemoryRequirements',['../struct_vma_vulkan_functions.html#a475f6f49f8debe4d10800592606d53f4',1,'VmaVulkanFunctions']]],
+  ['vkgetphysicaldevicememoryproperties_100',['vkGetPhysicalDeviceMemoryProperties',['../struct_vma_vulkan_functions.html#a60d25c33bba06bb8592e6875cbaa9830',1,'VmaVulkanFunctions']]],
+  ['vkgetphysicaldeviceproperties_101',['vkGetPhysicalDeviceProperties',['../struct_vma_vulkan_functions.html#a77b7a74082823e865dd6546623468f96',1,'VmaVulkanFunctions']]],
+  ['vkinvalidatemappedmemoryranges_102',['vkInvalidateMappedMemoryRanges',['../struct_vma_vulkan_functions.html#a5c1093bc32386a8060c37c9f282078a1',1,'VmaVulkanFunctions']]],
+  ['vkmapmemory_103',['vkMapMemory',['../struct_vma_vulkan_functions.html#ab5c1f38dea3a2cf00dc9eb4f57218c49',1,'VmaVulkanFunctions']]],
+  ['vkunmapmemory_104',['vkUnmapMemory',['../struct_vma_vulkan_functions.html#acc798589736f0becb317fc2196c1d8b9',1,'VmaVulkanFunctions']]],
+  ['vma_5fallocation_5fcreate_5fcan_5fbecome_5flost_5fbit_105',['VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT',['../vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a5f436af6c8fe8540573a6d22627a6fd2',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocation_5fcreate_5fcan_5fmake_5fother_5flost_5fbit_106',['VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT',['../vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a68686d0ce9beb0d4d1b9f2b8b1389a7e',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocation_5fcreate_5fdedicated_5fmemory_5fbit_107',['VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT',['../vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a3fc311d855c2ff53f1090ef5c722b38f',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocation_5fcreate_5fdont_5fbind_5fbit_108',['VMA_ALLOCATION_CREATE_DONT_BIND_BIT',['../vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a2310568c62208af432724305fe29ccea',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocation_5fcreate_5fflag_5fbits_5fmax_5fenum_109',['VMA_ALLOCATION_CREATE_FLAG_BITS_MAX_ENUM',['../vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597ae5633ec569f4899cf8f29e7385b2f882',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocation_5fcreate_5fmapped_5fbit_110',['VMA_ALLOCATION_CREATE_MAPPED_BIT',['../vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a11da372cc3a82931c5e5d6146cd9dd1f',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocation_5fcreate_5fnever_5fallocate_5fbit_111',['VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT',['../vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a89759603401014eb325eb22a3839f2ff',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocation_5fcreate_5fstrategy_5fbest_5ffit_5fbit_112',['VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT',['../vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a839826775c62319466441f86496f036d',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocation_5fcreate_5fstrategy_5ffirst_5ffit_5fbit_113',['VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT',['../vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a33eb2052674f3ad92386c714a65fb777',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocation_5fcreate_5fstrategy_5fmask_114',['VMA_ALLOCATION_CREATE_STRATEGY_MASK',['../vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a8e16845d81ae3d27c47106d4770d5c7e',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocation_5fcreate_5fstrategy_5fmin_5ffragmentation_5fbit_115',['VMA_ALLOCATION_CREATE_STRATEGY_MIN_FRAGMENTATION_BIT',['../vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a621b704103eb3360230c860acf36e706',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocation_5fcreate_5fstrategy_5fmin_5fmemory_5fbit_116',['VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT',['../vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a8af1210cf591784afa026d94998f735d',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocation_5fcreate_5fstrategy_5fmin_5ftime_5fbit_117',['VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT',['../vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a0729e932b7ea170e3a128cad96c5cf6d',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocation_5fcreate_5fstrategy_5fworst_5ffit_5fbit_118',['VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT',['../vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597ad242a04f802e25fef0b880afe8bb0a62',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocation_5fcreate_5fupper_5faddress_5fbit_119',['VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT',['../vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a42ba3a2d2c7117953210b7c3ef8da0df',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocation_5fcreate_5fuser_5fdata_5fcopy_5fstring_5fbit_120',['VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT',['../vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597aa6f24f821cd6a7c5e4a443f7bf59c520',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocation_5fcreate_5fwithin_5fbudget_5fbit_121',['VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT',['../vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597ab8b1764f3e9022368e440c057783b92d',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocator_5fcreate_5famd_5fdevice_5fcoherent_5fmemory_5fbit_122',['VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT',['../vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca2acce4886d8078552efa38878413970f',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocator_5fcreate_5fbuffer_5fdevice_5faddress_5fbit_123',['VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT',['../vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca5f1b28b0414319d1687e1f2b30ab0089',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocator_5fcreate_5fext_5fmemory_5fbudget_5fbit_124',['VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT',['../vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca4d4687863f7bd4b418c6006dc04400b0',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocator_5fcreate_5fexternally_5fsynchronized_5fbit_125',['VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT',['../vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca4816ddaed324ba110172ca608a20f29d',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocator_5fcreate_5fflag_5fbits_5fmax_5fenum_126',['VMA_ALLOCATOR_CREATE_FLAG_BITS_MAX_ENUM',['../vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7cae4d5ad929caba5f23eb502b13bd5286c',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocator_5fcreate_5fkhr_5fbind_5fmemory2_5fbit_127',['VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT',['../vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca8fb75bf07cd184ab903596295e863dee',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocator_5fcreate_5fkhr_5fdedicated_5fallocation_5fbit_128',['VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT',['../vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7cace7da7cc6e71a625dfa763c55a597878',1,'vk_mem_alloc.h']]],
+  ['vma_5fbind_5fmemory2_129',['VMA_BIND_MEMORY2',['../vk__mem__alloc_8h.html#a88bef97f86d70a34a4c0746e09a2680d',1,'vk_mem_alloc.h']]],
+  ['vma_5fbuffer_5fdevice_5faddress_130',['VMA_BUFFER_DEVICE_ADDRESS',['../vk__mem__alloc_8h.html#a7f9d5e71b70dd1a137c303a8a8262c10',1,'vk_mem_alloc.h']]],
+  ['vma_5fdedicated_5fallocation_131',['VMA_DEDICATED_ALLOCATION',['../vk__mem__alloc_8h.html#af7b860e63b96d11e44ae8587ba06bbf4',1,'vk_mem_alloc.h']]],
+  ['vma_5fdefragmentation_5fflag_5fbits_5fmax_5fenum_132',['VMA_DEFRAGMENTATION_FLAG_BITS_MAX_ENUM',['../vk__mem__alloc_8h.html#a6552a65b71d16f378c6994b3ceaef50cab87ec33154803bfeb5ac2b379f1d6a97',1,'vk_mem_alloc.h']]],
+  ['vma_5fdefragmentation_5fflag_5fincremental_133',['VMA_DEFRAGMENTATION_FLAG_INCREMENTAL',['../vk__mem__alloc_8h.html#a6552a65b71d16f378c6994b3ceaef50ca31af49446af2459284a568ce2f3fdd33',1,'vk_mem_alloc.h']]],
+  ['vma_5fmemory_5fbudget_134',['VMA_MEMORY_BUDGET',['../vk__mem__alloc_8h.html#a05decf1cf4ebf767beba7acca6c1ec3a',1,'vk_mem_alloc.h']]],
+  ['vma_5fmemory_5fusage_5fcpu_5fcopy_135',['VMA_MEMORY_USAGE_CPU_COPY',['../vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca416a444d4d0fc20067c3f76f32ff2500',1,'vk_mem_alloc.h']]],
+  ['vma_5fmemory_5fusage_5fcpu_5fonly_136',['VMA_MEMORY_USAGE_CPU_ONLY',['../vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca40bdf4cddeffeb12f43d45ca1286e0a5',1,'vk_mem_alloc.h']]],
+  ['vma_5fmemory_5fusage_5fcpu_5fto_5fgpu_137',['VMA_MEMORY_USAGE_CPU_TO_GPU',['../vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca9066b52c5a7079bb74a69aaf8b92ff67',1,'vk_mem_alloc.h']]],
+  ['vma_5fmemory_5fusage_5fgpu_5flazily_5fallocated_138',['VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED',['../vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca835333d9072db63a653818030e17614d',1,'vk_mem_alloc.h']]],
+  ['vma_5fmemory_5fusage_5fgpu_5fonly_139',['VMA_MEMORY_USAGE_GPU_ONLY',['../vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7',1,'vk_mem_alloc.h']]],
+  ['vma_5fmemory_5fusage_5fgpu_5fto_5fcpu_140',['VMA_MEMORY_USAGE_GPU_TO_CPU',['../vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca7b586d2fdaf82a463b58f581ed72be27',1,'vk_mem_alloc.h']]],
+  ['vma_5fmemory_5fusage_5fmax_5fenum_141',['VMA_MEMORY_USAGE_MAX_ENUM',['../vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca091e69437ef693e8d0d287f1c719ba6e',1,'vk_mem_alloc.h']]],
+  ['vma_5fmemory_5fusage_5funknown_142',['VMA_MEMORY_USAGE_UNKNOWN',['../vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccaf50d27e34e0925cf3a63db8c839121dd',1,'vk_mem_alloc.h']]],
+  ['vma_5fpool_5fcreate_5falgorithm_5fmask_143',['VMA_POOL_CREATE_ALGORITHM_MASK',['../vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7af4d270f8f42517a0f70037ceb6ac1d9c',1,'vk_mem_alloc.h']]],
+  ['vma_5fpool_5fcreate_5fbuddy_5falgorithm_5fbit_144',['VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT',['../vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a97a0dc38e5161b780594d998d313d35e',1,'vk_mem_alloc.h']]],
+  ['vma_5fpool_5fcreate_5fflag_5fbits_5fmax_5fenum_145',['VMA_POOL_CREATE_FLAG_BITS_MAX_ENUM',['../vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a1c7312bea9ea246846b9054fd6bd6aec',1,'vk_mem_alloc.h']]],
+  ['vma_5fpool_5fcreate_5fignore_5fbuffer_5fimage_5fgranularity_5fbit_146',['VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT',['../vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a9f1a499508a8edb4e8ba40aa0290a3d2',1,'vk_mem_alloc.h']]],
+  ['vma_5fpool_5fcreate_5flinear_5falgorithm_5fbit_147',['VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT',['../vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a13c8a444197c67866be9cb05599fc726',1,'vk_mem_alloc.h']]],
+  ['vma_5frecord_5fflag_5fbits_5fmax_5fenum_148',['VMA_RECORD_FLAG_BITS_MAX_ENUM',['../vk__mem__alloc_8h.html#a4dd2c44642312a147a4e93373a6e64d2a20dd17d69966dbffa054739d6090b85e',1,'vk_mem_alloc.h']]],
+  ['vma_5frecord_5fflush_5fafter_5fcall_5fbit_149',['VMA_RECORD_FLUSH_AFTER_CALL_BIT',['../vk__mem__alloc_8h.html#a4dd2c44642312a147a4e93373a6e64d2a8e7ab322e8732654be627c4ea8f36cc7',1,'vk_mem_alloc.h']]],
+  ['vma_5frecording_5fenabled_150',['VMA_RECORDING_ENABLED',['../vk__mem__alloc_8h.html#a1f0c126759fc96ccb6e2d23c101d770c',1,'vk_mem_alloc.h']]],
+  ['vma_5fstats_5fstring_5fenabled_151',['VMA_STATS_STRING_ENABLED',['../vk__mem__alloc_8h.html#ae25f0d55fd91cb166f002b63244800e1',1,'vk_mem_alloc.h']]],
+  ['vma_5fvulkan_5fversion_152',['VMA_VULKAN_VERSION',['../vk__mem__alloc_8h.html#a1a2407c283893638cc039bb31fcd74b6',1,'vk_mem_alloc.h']]],
+  ['vmaallocatememory_153',['vmaAllocateMemory',['../vk__mem__alloc_8h.html#abf28077dbf82d0908b8acbe8ee8dd9b8',1,'vk_mem_alloc.h']]],
+  ['vmaallocatememoryforbuffer_154',['vmaAllocateMemoryForBuffer',['../vk__mem__alloc_8h.html#a7fdf64415b6c3d83c454f28d2c53df7b',1,'vk_mem_alloc.h']]],
+  ['vmaallocatememoryforimage_155',['vmaAllocateMemoryForImage',['../vk__mem__alloc_8h.html#a0faa3f9e5fb233d29d1e00390650febb',1,'vk_mem_alloc.h']]],
+  ['vmaallocatememorypages_156',['vmaAllocateMemoryPages',['../vk__mem__alloc_8h.html#ad37e82e492b3de38fc3f4cffd9ad0ae1',1,'vk_mem_alloc.h']]],
+  ['vmaallocation_157',['VmaAllocation',['../struct_vma_allocation.html',1,'']]],
+  ['vmaallocationcreateflagbits_158',['VmaAllocationCreateFlagBits',['../vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597',1,'VmaAllocationCreateFlagBits():&#160;vk_mem_alloc.h'],['../vk__mem__alloc_8h.html#a4fceecc301f4064dc808d3cd6c038941',1,'VmaAllocationCreateFlagBits():&#160;vk_mem_alloc.h']]],
+  ['vmaallocationcreateflags_159',['VmaAllocationCreateFlags',['../vk__mem__alloc_8h.html#a5225e5e11f8376f6a31a1791f3d6e817',1,'vk_mem_alloc.h']]],
+  ['vmaallocationcreateinfo_160',['VmaAllocationCreateInfo',['../struct_vma_allocation_create_info.html',1,'VmaAllocationCreateInfo'],['../vk__mem__alloc_8h.html#a3bf110892ea2fb4649fedb68488d026a',1,'VmaAllocationCreateInfo():&#160;vk_mem_alloc.h']]],
+  ['vmaallocationinfo_161',['VmaAllocationInfo',['../struct_vma_allocation_info.html',1,'VmaAllocationInfo'],['../vk__mem__alloc_8h.html#a1cf7774606721026a68aabe3af2e5b50',1,'VmaAllocationInfo():&#160;vk_mem_alloc.h']]],
+  ['vmaallocator_162',['VmaAllocator',['../struct_vma_allocator.html',1,'']]],
+  ['vmaallocatorcreateflagbits_163',['VmaAllocatorCreateFlagBits',['../vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7c',1,'VmaAllocatorCreateFlagBits():&#160;vk_mem_alloc.h'],['../vk__mem__alloc_8h.html#afd73b95e737ee7e76f827cb5472f559f',1,'VmaAllocatorCreateFlagBits():&#160;vk_mem_alloc.h']]],
+  ['vmaallocatorcreateflags_164',['VmaAllocatorCreateFlags',['../vk__mem__alloc_8h.html#acfe6863e160722c2c1bbcf7573fddc4d',1,'vk_mem_alloc.h']]],
+  ['vmaallocatorcreateinfo_165',['VmaAllocatorCreateInfo',['../struct_vma_allocator_create_info.html',1,'VmaAllocatorCreateInfo'],['../vk__mem__alloc_8h.html#aad9652301d33759b83e52d4f3605a14a',1,'VmaAllocatorCreateInfo():&#160;vk_mem_alloc.h']]],
+  ['vmaallocatorinfo_166',['VmaAllocatorInfo',['../struct_vma_allocator_info.html',1,'VmaAllocatorInfo'],['../vk__mem__alloc_8h.html#a1988031b0223fdbd564250fa1edd942c',1,'VmaAllocatorInfo():&#160;vk_mem_alloc.h']]],
+  ['vmabegindefragmentationpass_167',['vmaBeginDefragmentationPass',['../vk__mem__alloc_8h.html#ac0f01545b6262f7d4d128fc8f8e5c77b',1,'vk_mem_alloc.h']]],
+  ['vmabindbuffermemory_168',['vmaBindBufferMemory',['../vk__mem__alloc_8h.html#a6b0929b914b60cf2d45cac4bf3547470',1,'vk_mem_alloc.h']]],
+  ['vmabindbuffermemory2_169',['vmaBindBufferMemory2',['../vk__mem__alloc_8h.html#a927c944f45e0f2941182abb6f608e64a',1,'vk_mem_alloc.h']]],
+  ['vmabindimagememory_170',['vmaBindImageMemory',['../vk__mem__alloc_8h.html#a3d3ca45799923aa5d138e9e5f9eb2da5',1,'vk_mem_alloc.h']]],
+  ['vmabindimagememory2_171',['vmaBindImageMemory2',['../vk__mem__alloc_8h.html#aa8251ee81b0045a443e35b8e8aa021bc',1,'vk_mem_alloc.h']]],
+  ['vmabudget_172',['VmaBudget',['../struct_vma_budget.html',1,'VmaBudget'],['../vk__mem__alloc_8h.html#aa078667e71b1ef24e87a6a30d128381d',1,'VmaBudget():&#160;vk_mem_alloc.h']]],
+  ['vmabuildstatsstring_173',['vmaBuildStatsString',['../vk__mem__alloc_8h.html#aa4fee7eb5253377599ef4fd38c93c2a0',1,'vk_mem_alloc.h']]],
+  ['vmacalculatestats_174',['vmaCalculateStats',['../vk__mem__alloc_8h.html#a333b61c1788cb23559177531e6a93ca3',1,'vk_mem_alloc.h']]],
+  ['vmacheckcorruption_175',['vmaCheckCorruption',['../vk__mem__alloc_8h.html#a49329a7f030dafcf82f7b73334c22e98',1,'vk_mem_alloc.h']]],
+  ['vmacheckpoolcorruption_176',['vmaCheckPoolCorruption',['../vk__mem__alloc_8h.html#ad535935619c7a549bf837e1bb0068f89',1,'vk_mem_alloc.h']]],
+  ['vmacreateallocator_177',['vmaCreateAllocator',['../vk__mem__alloc_8h.html#a200692051ddb34240248234f5f4c17bb',1,'vk_mem_alloc.h']]],
+  ['vmacreatebuffer_178',['vmaCreateBuffer',['../vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51',1,'vk_mem_alloc.h']]],
+  ['vmacreateimage_179',['vmaCreateImage',['../vk__mem__alloc_8h.html#a02a94f25679275851a53e82eacbcfc73',1,'vk_mem_alloc.h']]],
+  ['vmacreatelostallocation_180',['vmaCreateLostAllocation',['../vk__mem__alloc_8h.html#ae5c9657d9e94756269145b01c05d16f1',1,'vk_mem_alloc.h']]],
+  ['vmacreatepool_181',['vmaCreatePool',['../vk__mem__alloc_8h.html#a5c8770ded7c59c8caac6de0c2cb00b50',1,'vk_mem_alloc.h']]],
+  ['vmadefragment_182',['vmaDefragment',['../vk__mem__alloc_8h.html#a6aced90fcc7b39882b6654a740a0b9bb',1,'vk_mem_alloc.h']]],
+  ['vmadefragmentationbegin_183',['vmaDefragmentationBegin',['../vk__mem__alloc_8h.html#a36ba776fd7fd5cb1e9359fdc0d8e6e8a',1,'vk_mem_alloc.h']]],
+  ['vmadefragmentationcontext_184',['VmaDefragmentationContext',['../struct_vma_defragmentation_context.html',1,'']]],
+  ['vmadefragmentationend_185',['vmaDefragmentationEnd',['../vk__mem__alloc_8h.html#a8774e20e91e245aae959ba63efa15dd2',1,'vk_mem_alloc.h']]],
+  ['vmadefragmentationflagbits_186',['VmaDefragmentationFlagBits',['../vk__mem__alloc_8h.html#a6552a65b71d16f378c6994b3ceaef50c',1,'VmaDefragmentationFlagBits():&#160;vk_mem_alloc.h'],['../vk__mem__alloc_8h.html#a13415cc0b443353a7b5abda300b833fc',1,'VmaDefragmentationFlagBits():&#160;vk_mem_alloc.h']]],
+  ['vmadefragmentationflags_187',['VmaDefragmentationFlags',['../vk__mem__alloc_8h.html#a88a77cef37e5d3c4fc9eb328885d048d',1,'vk_mem_alloc.h']]],
+  ['vmadefragmentationinfo_188',['VmaDefragmentationInfo',['../struct_vma_defragmentation_info.html',1,'VmaDefragmentationInfo'],['../vk__mem__alloc_8h.html#a2bf47f96bf92bed2a49461bd9af3acfa',1,'VmaDefragmentationInfo():&#160;vk_mem_alloc.h']]],
+  ['vmadefragmentationinfo2_189',['VmaDefragmentationInfo2',['../struct_vma_defragmentation_info2.html',1,'VmaDefragmentationInfo2'],['../vk__mem__alloc_8h.html#ad6daeffaa670ce6d11a203a6224c9937',1,'VmaDefragmentationInfo2():&#160;vk_mem_alloc.h']]],
+  ['vmadefragmentationpassinfo_190',['VmaDefragmentationPassInfo',['../struct_vma_defragmentation_pass_info.html',1,'VmaDefragmentationPassInfo'],['../vk__mem__alloc_8h.html#a72aebd522242d56abea67b4f47f6549e',1,'VmaDefragmentationPassInfo():&#160;vk_mem_alloc.h']]],
+  ['vmadefragmentationpassmoveinfo_191',['VmaDefragmentationPassMoveInfo',['../struct_vma_defragmentation_pass_move_info.html',1,'VmaDefragmentationPassMoveInfo'],['../vk__mem__alloc_8h.html#ad6799e8e2b1527abfc84d33bc44aeaf5',1,'VmaDefragmentationPassMoveInfo():&#160;vk_mem_alloc.h']]],
+  ['vmadefragmentationstats_192',['VmaDefragmentationStats',['../struct_vma_defragmentation_stats.html',1,'VmaDefragmentationStats'],['../vk__mem__alloc_8h.html#ad94034192259c2e34a4d1c5e27810403',1,'VmaDefragmentationStats():&#160;vk_mem_alloc.h']]],
+  ['vmadestroyallocator_193',['vmaDestroyAllocator',['../vk__mem__alloc_8h.html#aa8d164061c88f22fb1fd3c8f3534bc1d',1,'vk_mem_alloc.h']]],
+  ['vmadestroybuffer_194',['vmaDestroyBuffer',['../vk__mem__alloc_8h.html#a0d9f4e4ba5bf9aab1f1c746387753d77',1,'vk_mem_alloc.h']]],
+  ['vmadestroyimage_195',['vmaDestroyImage',['../vk__mem__alloc_8h.html#ae50d2cb3b4a3bfd4dd40987234e50e7e',1,'vk_mem_alloc.h']]],
+  ['vmadestroypool_196',['vmaDestroyPool',['../vk__mem__alloc_8h.html#a5485779c8f1948238fc4e92232fa65e1',1,'vk_mem_alloc.h']]],
+  ['vmadevicememorycallbacks_197',['VmaDeviceMemoryCallbacks',['../struct_vma_device_memory_callbacks.html',1,'VmaDeviceMemoryCallbacks'],['../vk__mem__alloc_8h.html#a77692d3c8770ea8882d573206bd27b2b',1,'VmaDeviceMemoryCallbacks():&#160;vk_mem_alloc.h']]],
+  ['vmaenddefragmentationpass_198',['vmaEndDefragmentationPass',['../vk__mem__alloc_8h.html#a1b9ffa538bed905af55c747cc48963bd',1,'vk_mem_alloc.h']]],
+  ['vmafindmemorytypeindex_199',['vmaFindMemoryTypeIndex',['../vk__mem__alloc_8h.html#aef15a94b58fbcb0fe706d5720e84a74a',1,'vk_mem_alloc.h']]],
+  ['vmafindmemorytypeindexforbufferinfo_200',['vmaFindMemoryTypeIndexForBufferInfo',['../vk__mem__alloc_8h.html#ae790ab9ffaf7667fb8f62523e6897888',1,'vk_mem_alloc.h']]],
+  ['vmafindmemorytypeindexforimageinfo_201',['vmaFindMemoryTypeIndexForImageInfo',['../vk__mem__alloc_8h.html#a088da83d8eaf3ce9056d9ea0b981d472',1,'vk_mem_alloc.h']]],
+  ['vmaflushallocation_202',['vmaFlushAllocation',['../vk__mem__alloc_8h.html#abc34ee6f021f459aff885f3758c435de',1,'vk_mem_alloc.h']]],
+  ['vmafreememory_203',['vmaFreeMemory',['../vk__mem__alloc_8h.html#a11f0fbc034fa81a4efedd73d61ce7568',1,'vk_mem_alloc.h']]],
+  ['vmafreememorypages_204',['vmaFreeMemoryPages',['../vk__mem__alloc_8h.html#ab9e709de044c5d8476bea77a4e755840',1,'vk_mem_alloc.h']]],
+  ['vmafreestatsstring_205',['vmaFreeStatsString',['../vk__mem__alloc_8h.html#a3104eb30d8122c84dd8541063f145288',1,'vk_mem_alloc.h']]],
+  ['vmagetallocationinfo_206',['vmaGetAllocationInfo',['../vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b',1,'vk_mem_alloc.h']]],
+  ['vmagetallocatorinfo_207',['vmaGetAllocatorInfo',['../vk__mem__alloc_8h.html#afa02231a791b37255720d566a52683e7',1,'vk_mem_alloc.h']]],
+  ['vmagetbudget_208',['vmaGetBudget',['../vk__mem__alloc_8h.html#aec0ed24ebea2d0099eed5f801daaefba',1,'vk_mem_alloc.h']]],
+  ['vmagetmemoryproperties_209',['vmaGetMemoryProperties',['../vk__mem__alloc_8h.html#ab88db292a17974f911182543fda52d19',1,'vk_mem_alloc.h']]],
+  ['vmagetmemorytypeproperties_210',['vmaGetMemoryTypeProperties',['../vk__mem__alloc_8h.html#a8701444752eb5de4464adb5a2b514bca',1,'vk_mem_alloc.h']]],
+  ['vmagetphysicaldeviceproperties_211',['vmaGetPhysicalDeviceProperties',['../vk__mem__alloc_8h.html#aecabf7b6e91ea87d0316fa0a9e014fe0',1,'vk_mem_alloc.h']]],
+  ['vmagetpoolname_212',['vmaGetPoolName',['../vk__mem__alloc_8h.html#af09b4e4eafdbee812e8d73ddf960f030',1,'vk_mem_alloc.h']]],
+  ['vmagetpoolstats_213',['vmaGetPoolStats',['../vk__mem__alloc_8h.html#ae8bf76997b234ef68aad922616df4153',1,'vk_mem_alloc.h']]],
+  ['vmainvalidateallocation_214',['vmaInvalidateAllocation',['../vk__mem__alloc_8h.html#a0d0eb0c1102268fa9a476d12ecbe4006',1,'vk_mem_alloc.h']]],
+  ['vmamakepoolallocationslost_215',['vmaMakePoolAllocationsLost',['../vk__mem__alloc_8h.html#a736bd6cbda886f36c891727e73bd4024',1,'vk_mem_alloc.h']]],
+  ['vmamapmemory_216',['vmaMapMemory',['../vk__mem__alloc_8h.html#ad5bd1243512d099706de88168992f069',1,'vk_mem_alloc.h']]],
+  ['vmamemoryusage_217',['VmaMemoryUsage',['../vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cc',1,'VmaMemoryUsage():&#160;vk_mem_alloc.h'],['../vk__mem__alloc_8h.html#a806e8499dde802e59eb72a1dc811c35f',1,'VmaMemoryUsage():&#160;vk_mem_alloc.h']]],
+  ['vmapool_218',['VmaPool',['../struct_vma_pool.html',1,'']]],
+  ['vmapoolcreateflagbits_219',['VmaPoolCreateFlagBits',['../vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7',1,'VmaPoolCreateFlagBits():&#160;vk_mem_alloc.h'],['../vk__mem__alloc_8h.html#a4d4f2efc2509157a9e4ecd4fd7942303',1,'VmaPoolCreateFlagBits():&#160;vk_mem_alloc.h']]],
+  ['vmapoolcreateflags_220',['VmaPoolCreateFlags',['../vk__mem__alloc_8h.html#a2770e325ea42e087c1b91fdf46d0292a',1,'vk_mem_alloc.h']]],
+  ['vmapoolcreateinfo_221',['VmaPoolCreateInfo',['../struct_vma_pool_create_info.html',1,'VmaPoolCreateInfo'],['../vk__mem__alloc_8h.html#a1017aa83489c0eee8d2163d2bf253f67',1,'VmaPoolCreateInfo():&#160;vk_mem_alloc.h']]],
+  ['vmapoolstats_222',['VmaPoolStats',['../struct_vma_pool_stats.html',1,'VmaPoolStats'],['../vk__mem__alloc_8h.html#a4759a2d9f99c19ba7627553c847132f1',1,'VmaPoolStats():&#160;vk_mem_alloc.h']]],
+  ['vmarecordflagbits_223',['VmaRecordFlagBits',['../vk__mem__alloc_8h.html#a4dd2c44642312a147a4e93373a6e64d2',1,'VmaRecordFlagBits():&#160;vk_mem_alloc.h'],['../vk__mem__alloc_8h.html#acd24d5eb58abff7e1f43cb32a1ba1413',1,'VmaRecordFlagBits():&#160;vk_mem_alloc.h']]],
+  ['vmarecordflags_224',['VmaRecordFlags',['../vk__mem__alloc_8h.html#af3929a1a4547c592fc0b0e55ef452828',1,'vk_mem_alloc.h']]],
+  ['vmarecordsettings_225',['VmaRecordSettings',['../struct_vma_record_settings.html',1,'VmaRecordSettings'],['../vk__mem__alloc_8h.html#a16e21c877101493fce582664cd8754fc',1,'VmaRecordSettings():&#160;vk_mem_alloc.h']]],
+  ['vmaresizeallocation_226',['vmaResizeAllocation',['../vk__mem__alloc_8h.html#a0ff488958ca72b28e545880463cb8696',1,'vk_mem_alloc.h']]],
+  ['vmasetallocationuserdata_227',['vmaSetAllocationUserData',['../vk__mem__alloc_8h.html#af9147d31ffc11d62fc187bde283ed14f',1,'vk_mem_alloc.h']]],
+  ['vmasetcurrentframeindex_228',['vmaSetCurrentFrameIndex',['../vk__mem__alloc_8h.html#ade56bf8dc9f5a5eaddf5f119ed525236',1,'vk_mem_alloc.h']]],
+  ['vmasetpoolname_229',['vmaSetPoolName',['../vk__mem__alloc_8h.html#adbae3a0b4ab078024462fc85c37f3b58',1,'vk_mem_alloc.h']]],
+  ['vmastatinfo_230',['VmaStatInfo',['../struct_vma_stat_info.html',1,'VmaStatInfo'],['../vk__mem__alloc_8h.html#aec5b57e29c97b5d69c6d5654d60df878',1,'VmaStatInfo():&#160;vk_mem_alloc.h']]],
+  ['vmastats_231',['VmaStats',['../struct_vma_stats.html',1,'VmaStats'],['../vk__mem__alloc_8h.html#a21813b2efdf3836767a9058cd8a94034',1,'VmaStats():&#160;vk_mem_alloc.h']]],
+  ['vmatouchallocation_232',['vmaTouchAllocation',['../vk__mem__alloc_8h.html#a43d8ba9673c846f049089a5029d5c73a',1,'vk_mem_alloc.h']]],
+  ['vmaunmapmemory_233',['vmaUnmapMemory',['../vk__mem__alloc_8h.html#a9bc268595cb33f6ec4d519cfce81ff45',1,'vk_mem_alloc.h']]],
+  ['vmavulkanfunctions_234',['VmaVulkanFunctions',['../struct_vma_vulkan_functions.html',1,'VmaVulkanFunctions'],['../vk__mem__alloc_8h.html#abb0a8e3b5040d847571cca6c7f9a8074',1,'VmaVulkanFunctions():&#160;vk_mem_alloc.h']]],
+  ['vulkanapiversion_235',['vulkanApiVersion',['../struct_vma_allocator_create_info.html#ae0ffc55139b54520a6bb704b29ffc285',1,'VmaAllocatorCreateInfo']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/all_2.html b/third_party/VulkanMemoryAllocator/docs/html/search/all_2.html
new file mode 100644
index 0000000..b26d916
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/all_2.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_2.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/all_2.js b/third_party/VulkanMemoryAllocator/docs/html/search/all_2.js
new file mode 100644
index 0000000..ccc0f04
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/all_2.js
@@ -0,0 +1,7 @@
+var searchData=
+[
+  ['choosing_20memory_20type_14',['Choosing memory type',['../choosing_memory_type.html',1,'index']]],
+  ['commandbuffer_15',['commandBuffer',['../struct_vma_defragmentation_info2.html#a7f71f39590c5316771493d2333f9c1bd',1,'VmaDefragmentationInfo2']]],
+  ['configuration_16',['Configuration',['../configuration.html',1,'index']]],
+  ['custom_20memory_20pools_17',['Custom memory pools',['../custom_memory_pools.html',1,'index']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/all_3.html b/third_party/VulkanMemoryAllocator/docs/html/search/all_3.html
new file mode 100644
index 0000000..b61b96f
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/all_3.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_3.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/all_3.js b/third_party/VulkanMemoryAllocator/docs/html/search/all_3.js
new file mode 100644
index 0000000..c58a6e2
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/all_3.js
@@ -0,0 +1,9 @@
+var searchData=
+[
+  ['debugging_20incorrect_20memory_20usage_18',['Debugging incorrect memory usage',['../debugging_memory_usage.html',1,'index']]],
+  ['defragmentation_19',['Defragmentation',['../defragmentation.html',1,'index']]],
+  ['deprecated_20list_20',['Deprecated List',['../deprecated.html',1,'']]],
+  ['device_21',['device',['../struct_vma_allocator_create_info.html#ad924ddd77b04039c88d0c09b0ffcd500',1,'VmaAllocatorCreateInfo::device()'],['../struct_vma_allocator_info.html#a012b4c485bf3b0ea8921352c5ee0c357',1,'VmaAllocatorInfo::device()']]],
+  ['devicememory_22',['deviceMemory',['../struct_vma_allocation_info.html#ae0bfb7dfdf79a76ffefc9a94677a2f67',1,'VmaAllocationInfo']]],
+  ['devicememoryblocksfreed_23',['deviceMemoryBlocksFreed',['../struct_vma_defragmentation_stats.html#a0113f1877904a5d1ee8f409216ff276b',1,'VmaDefragmentationStats']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/all_4.html b/third_party/VulkanMemoryAllocator/docs/html/search/all_4.html
new file mode 100644
index 0000000..06de155
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/all_4.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_4.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/all_4.js b/third_party/VulkanMemoryAllocator/docs/html/search/all_4.js
new file mode 100644
index 0000000..79d75e5
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/all_4.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['enabling_20buffer_20device_20address_24',['Enabling buffer device address',['../enabling_buffer_device_address.html',1,'index']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/all_5.html b/third_party/VulkanMemoryAllocator/docs/html/search/all_5.html
new file mode 100644
index 0000000..2544c4e
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/all_5.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_5.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/all_5.js b/third_party/VulkanMemoryAllocator/docs/html/search/all_5.js
new file mode 100644
index 0000000..09ebae9
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/all_5.js
@@ -0,0 +1,5 @@
+var searchData=
+[
+  ['flags_25',['flags',['../struct_vma_record_settings.html#ad8fdcc92119ae7a8c08c1a564c01d63a',1,'VmaRecordSettings::flags()'],['../struct_vma_allocator_create_info.html#a392ea2ecbaff93f91a7c49f735ad4346',1,'VmaAllocatorCreateInfo::flags()'],['../struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b',1,'VmaAllocationCreateInfo::flags()'],['../struct_vma_pool_create_info.html#a8405139f63d078340ae74513a59f5446',1,'VmaPoolCreateInfo::flags()'],['../struct_vma_defragmentation_info2.html#a53e844ee5633e229cf6daf14b2d9fff9',1,'VmaDefragmentationInfo2::flags()']]],
+  ['frameinusecount_26',['frameInUseCount',['../struct_vma_allocator_create_info.html#a21ea188dd212b8171cb9ecbed4a2a3a7',1,'VmaAllocatorCreateInfo::frameInUseCount()'],['../struct_vma_pool_create_info.html#a9437e43ffbb644dbbf7fc4e50cfad6aa',1,'VmaPoolCreateInfo::frameInUseCount()']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/all_6.html b/third_party/VulkanMemoryAllocator/docs/html/search/all_6.html
new file mode 100644
index 0000000..43f14ea
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/all_6.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_6.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/all_6.js b/third_party/VulkanMemoryAllocator/docs/html/search/all_6.js
new file mode 100644
index 0000000..85d38b9
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/all_6.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['general_20considerations_27',['General considerations',['../general_considerations.html',1,'index']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/all_7.html b/third_party/VulkanMemoryAllocator/docs/html/search/all_7.html
new file mode 100644
index 0000000..af52f82
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/all_7.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_7.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/all_7.js b/third_party/VulkanMemoryAllocator/docs/html/search/all_7.js
new file mode 100644
index 0000000..777be0f
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/all_7.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['instance_28',['instance',['../struct_vma_allocator_create_info.html#a70dd42e29b1df1d1b9b61532ae0b370b',1,'VmaAllocatorCreateInfo::instance()'],['../struct_vma_allocator_info.html#a2ed6a4d2d3fea039d66a13f15d0ce5fe',1,'VmaAllocatorInfo::instance()']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/all_8.html b/third_party/VulkanMemoryAllocator/docs/html/search/all_8.html
new file mode 100644
index 0000000..cf2b5df
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/all_8.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_8.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/all_8.js b/third_party/VulkanMemoryAllocator/docs/html/search/all_8.js
new file mode 100644
index 0000000..8d688d5
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/all_8.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['lost_20allocations_29',['Lost allocations',['../lost_allocations.html',1,'index']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/all_9.html b/third_party/VulkanMemoryAllocator/docs/html/search/all_9.html
new file mode 100644
index 0000000..690785a
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/all_9.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_9.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/all_9.js b/third_party/VulkanMemoryAllocator/docs/html/search/all_9.js
new file mode 100644
index 0000000..d88c966
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/all_9.js
@@ -0,0 +1,18 @@
+var searchData=
+[
+  ['maxallocationstomove_30',['maxAllocationsToMove',['../struct_vma_defragmentation_info.html#aa7c7304e13c71f604c907196c4e28fbc',1,'VmaDefragmentationInfo']]],
+  ['maxblockcount_31',['maxBlockCount',['../struct_vma_pool_create_info.html#ae41142f2834fcdc82baa4883c187b75c',1,'VmaPoolCreateInfo']]],
+  ['maxbytestomove_32',['maxBytesToMove',['../struct_vma_defragmentation_info.html#acb311c940a777270e67e1b81c5ab6a1d',1,'VmaDefragmentationInfo']]],
+  ['maxcpuallocationstomove_33',['maxCpuAllocationsToMove',['../struct_vma_defragmentation_info2.html#a94c2c7223d52878445a8cccce396b671',1,'VmaDefragmentationInfo2']]],
+  ['maxcpubytestomove_34',['maxCpuBytesToMove',['../struct_vma_defragmentation_info2.html#af78e1ea40c22d85137b65f6b384a4d0a',1,'VmaDefragmentationInfo2']]],
+  ['maxgpuallocationstomove_35',['maxGpuAllocationsToMove',['../struct_vma_defragmentation_info2.html#a40d53d33e71ba0b66f844ed63c05a3f6',1,'VmaDefragmentationInfo2']]],
+  ['maxgpubytestomove_36',['maxGpuBytesToMove',['../struct_vma_defragmentation_info2.html#a4ddbc898d0afe1518f863a3763628f08',1,'VmaDefragmentationInfo2']]],
+  ['memory_37',['memory',['../struct_vma_defragmentation_pass_move_info.html#a06eb0c8690aa0d3478a036753492e769',1,'VmaDefragmentationPassMoveInfo']]],
+  ['memory_20mapping_38',['Memory mapping',['../memory_mapping.html',1,'index']]],
+  ['memoryheap_39',['memoryHeap',['../struct_vma_stats.html#a0e6611508c29a187f0fd14ff1a0329c0',1,'VmaStats']]],
+  ['memorytype_40',['memoryType',['../struct_vma_stats.html#a13e3caf754be79352c42408756309331',1,'VmaStats::memoryType()'],['../struct_vma_allocation_info.html#a7f6b0aa58c135e488e6b40a388dad9d5',1,'VmaAllocationInfo::memoryType()']]],
+  ['memorytypebits_41',['memoryTypeBits',['../struct_vma_allocation_create_info.html#a3bf940c0271d85d6ba32a4d820075055',1,'VmaAllocationCreateInfo']]],
+  ['memorytypeindex_42',['memoryTypeIndex',['../struct_vma_pool_create_info.html#a596fa76b685d3f1f688f84a709a5b319',1,'VmaPoolCreateInfo']]],
+  ['minblockcount_43',['minBlockCount',['../struct_vma_pool_create_info.html#ad8006fb803185c0a699d30f3e9a865ae',1,'VmaPoolCreateInfo']]],
+  ['movecount_44',['moveCount',['../struct_vma_defragmentation_pass_info.html#ac1086e657ba995f8d1f4e49b83dcfb6c',1,'VmaDefragmentationPassInfo']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/all_a.html b/third_party/VulkanMemoryAllocator/docs/html/search/all_a.html
new file mode 100644
index 0000000..f2f3d3a
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/all_a.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_a.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/all_a.js b/third_party/VulkanMemoryAllocator/docs/html/search/all_a.js
new file mode 100644
index 0000000..3b32bbf
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/all_a.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['nominmax_45',['NOMINMAX',['../vk__mem__alloc_8h.html#a9f918755b601cf4bffca775992e6fb90',1,'vk_mem_alloc.h']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/all_b.html b/third_party/VulkanMemoryAllocator/docs/html/search/all_b.html
new file mode 100644
index 0000000..14f3403
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/all_b.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_b.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/all_b.js b/third_party/VulkanMemoryAllocator/docs/html/search/all_b.js
new file mode 100644
index 0000000..25ff2bb
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/all_b.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['offset_46',['offset',['../struct_vma_allocation_info.html#a4a3c732388dbdc7a23f9365b00825268',1,'VmaAllocationInfo::offset()'],['../struct_vma_defragmentation_pass_move_info.html#a8ab4508bc03625b0653c880576be96c6',1,'VmaDefragmentationPassMoveInfo::offset()']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/all_c.html b/third_party/VulkanMemoryAllocator/docs/html/search/all_c.html
new file mode 100644
index 0000000..da60ab8
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/all_c.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_c.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/all_c.js b/third_party/VulkanMemoryAllocator/docs/html/search/all_c.js
new file mode 100644
index 0000000..7aff7ee
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/all_c.js
@@ -0,0 +1,24 @@
+var searchData=
+[
+  ['pallocationcallbacks_47',['pAllocationCallbacks',['../struct_vma_allocator_create_info.html#a6e409087e3be55400d0e4ccbe43c608d',1,'VmaAllocatorCreateInfo']]],
+  ['pallocations_48',['pAllocations',['../struct_vma_defragmentation_info2.html#a8943f8d65969ce8e2189a1cdf3205e96',1,'VmaDefragmentationInfo2']]],
+  ['pallocationschanged_49',['pAllocationsChanged',['../struct_vma_defragmentation_info2.html#a76d51a644dc7f5405d0cdd0025ecd0cc',1,'VmaDefragmentationInfo2']]],
+  ['pdevicememorycallbacks_50',['pDeviceMemoryCallbacks',['../struct_vma_allocator_create_info.html#af1380969b5e1ea4c3184a877892d260e',1,'VmaAllocatorCreateInfo']]],
+  ['pfilepath_51',['pFilePath',['../struct_vma_record_settings.html#a6cb1fdbf6bcb610b68f2010dd629e89d',1,'VmaRecordSettings']]],
+  ['pfn_5fvmaallocatedevicememoryfunction_52',['PFN_vmaAllocateDeviceMemoryFunction',['../vk__mem__alloc_8h.html#a7e1ed85f7799600b03ad51a77acc21f3',1,'vk_mem_alloc.h']]],
+  ['pfn_5fvmafreedevicememoryfunction_53',['PFN_vmaFreeDeviceMemoryFunction',['../vk__mem__alloc_8h.html#a154ccaaf53dc2c36378f80f0c4f3679b',1,'vk_mem_alloc.h']]],
+  ['pfnallocate_54',['pfnAllocate',['../struct_vma_device_memory_callbacks.html#a4f17f7b255101e733b44d5633aceabfb',1,'VmaDeviceMemoryCallbacks']]],
+  ['pfnfree_55',['pfnFree',['../struct_vma_device_memory_callbacks.html#abe8a3328bbc916f6f712fdb6b299444c',1,'VmaDeviceMemoryCallbacks']]],
+  ['pheapsizelimit_56',['pHeapSizeLimit',['../struct_vma_allocator_create_info.html#a31c192aa6cbffa33279f6d9f0c47c44b',1,'VmaAllocatorCreateInfo']]],
+  ['physicaldevice_57',['physicalDevice',['../struct_vma_allocator_create_info.html#a08230f04ae6ccf8a78150a9e829a7156',1,'VmaAllocatorCreateInfo::physicalDevice()'],['../struct_vma_allocator_info.html#aba2b703f96e51d567717e1fb2935b47a',1,'VmaAllocatorInfo::physicalDevice()']]],
+  ['pmappeddata_58',['pMappedData',['../struct_vma_allocation_info.html#a5eeffbe2d2f30f53370ff14aefbadbe2',1,'VmaAllocationInfo']]],
+  ['pmoves_59',['pMoves',['../struct_vma_defragmentation_pass_info.html#acbd42d4a3357999da130a95cd99a3792',1,'VmaDefragmentationPassInfo']]],
+  ['pool_60',['pool',['../struct_vma_allocation_create_info.html#a6272c0555cfd1fe28bff1afeb6190150',1,'VmaAllocationCreateInfo']]],
+  ['poolcount_61',['poolCount',['../struct_vma_defragmentation_info2.html#a7e70aa2a1081d849dcc7829b19d3ec9d',1,'VmaDefragmentationInfo2']]],
+  ['ppools_62',['pPools',['../struct_vma_defragmentation_info2.html#a0b3effd57f3fcdeb2ed62210b4ef20e1',1,'VmaDefragmentationInfo2']]],
+  ['precordsettings_63',['pRecordSettings',['../struct_vma_allocator_create_info.html#ace2aa4877b16a42b0b7673d4e26000ee',1,'VmaAllocatorCreateInfo']]],
+  ['preferredflags_64',['preferredFlags',['../struct_vma_allocation_create_info.html#a7fe8d81a1ad10b2a2faacacee5b15d6d',1,'VmaAllocationCreateInfo']]],
+  ['preferredlargeheapblocksize_65',['preferredLargeHeapBlockSize',['../struct_vma_allocator_create_info.html#a8e4714298e3121cdd8b214a1ae7a637a',1,'VmaAllocatorCreateInfo']]],
+  ['puserdata_66',['pUserData',['../struct_vma_device_memory_callbacks.html#a24052de0937ddd54015a2df0363903c6',1,'VmaDeviceMemoryCallbacks::pUserData()'],['../struct_vma_allocation_create_info.html#a8259e85c272683434f4abb4ddddffe19',1,'VmaAllocationCreateInfo::pUserData()'],['../struct_vma_allocation_info.html#adc507656149c04de7ed95d0042ba2a13',1,'VmaAllocationInfo::pUserData()']]],
+  ['pvulkanfunctions_67',['pVulkanFunctions',['../struct_vma_allocator_create_info.html#a3dc197be3227da7338b1643f70db36bd',1,'VmaAllocatorCreateInfo']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/all_d.html b/third_party/VulkanMemoryAllocator/docs/html/search/all_d.html
new file mode 100644
index 0000000..bc376fe
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/all_d.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_d.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/all_d.js b/third_party/VulkanMemoryAllocator/docs/html/search/all_d.js
new file mode 100644
index 0000000..d58e218
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/all_d.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['quick_20start_68',['Quick start',['../quick_start.html',1,'index']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/all_e.html b/third_party/VulkanMemoryAllocator/docs/html/search/all_e.html
new file mode 100644
index 0000000..2e3c74d
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/all_e.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_e.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/all_e.js b/third_party/VulkanMemoryAllocator/docs/html/search/all_e.js
new file mode 100644
index 0000000..09d81d2
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/all_e.js
@@ -0,0 +1,6 @@
+var searchData=
+[
+  ['record_20and_20replay_69',['Record and replay',['../record_and_replay.html',1,'index']]],
+  ['requiredflags_70',['requiredFlags',['../struct_vma_allocation_create_info.html#a9166390303ff42d783305bc31c2b6b90',1,'VmaAllocationCreateInfo']]],
+  ['recommended_20usage_20patterns_71',['Recommended usage patterns',['../usage_patterns.html',1,'index']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/all_f.html b/third_party/VulkanMemoryAllocator/docs/html/search/all_f.html
new file mode 100644
index 0000000..246f8ab
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/all_f.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="all_f.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/all_f.js b/third_party/VulkanMemoryAllocator/docs/html/search/all_f.js
new file mode 100644
index 0000000..20d416e
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/all_f.js
@@ -0,0 +1,6 @@
+var searchData=
+[
+  ['size_72',['size',['../struct_vma_pool_stats.html#a326807b2de2b0931cee4ed9a5f2e420c',1,'VmaPoolStats::size()'],['../struct_vma_allocation_info.html#aac76d113a6a5ccbb09fea00fb25fd18f',1,'VmaAllocationInfo::size()']]],
+  ['statistics_73',['Statistics',['../statistics.html',1,'index']]],
+  ['staying_20within_20budget_74',['Staying within budget',['../staying_within_budget.html',1,'index']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/classes_0.html b/third_party/VulkanMemoryAllocator/docs/html/search/classes_0.html
new file mode 100644
index 0000000..f7e4c14
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/classes_0.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="classes_0.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/classes_0.js b/third_party/VulkanMemoryAllocator/docs/html/search/classes_0.js
new file mode 100644
index 0000000..263ae40
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/classes_0.js
@@ -0,0 +1,24 @@
+var searchData=
+[
+  ['vmaallocation_236',['VmaAllocation',['../struct_vma_allocation.html',1,'']]],
+  ['vmaallocationcreateinfo_237',['VmaAllocationCreateInfo',['../struct_vma_allocation_create_info.html',1,'']]],
+  ['vmaallocationinfo_238',['VmaAllocationInfo',['../struct_vma_allocation_info.html',1,'']]],
+  ['vmaallocator_239',['VmaAllocator',['../struct_vma_allocator.html',1,'']]],
+  ['vmaallocatorcreateinfo_240',['VmaAllocatorCreateInfo',['../struct_vma_allocator_create_info.html',1,'']]],
+  ['vmaallocatorinfo_241',['VmaAllocatorInfo',['../struct_vma_allocator_info.html',1,'']]],
+  ['vmabudget_242',['VmaBudget',['../struct_vma_budget.html',1,'']]],
+  ['vmadefragmentationcontext_243',['VmaDefragmentationContext',['../struct_vma_defragmentation_context.html',1,'']]],
+  ['vmadefragmentationinfo_244',['VmaDefragmentationInfo',['../struct_vma_defragmentation_info.html',1,'']]],
+  ['vmadefragmentationinfo2_245',['VmaDefragmentationInfo2',['../struct_vma_defragmentation_info2.html',1,'']]],
+  ['vmadefragmentationpassinfo_246',['VmaDefragmentationPassInfo',['../struct_vma_defragmentation_pass_info.html',1,'']]],
+  ['vmadefragmentationpassmoveinfo_247',['VmaDefragmentationPassMoveInfo',['../struct_vma_defragmentation_pass_move_info.html',1,'']]],
+  ['vmadefragmentationstats_248',['VmaDefragmentationStats',['../struct_vma_defragmentation_stats.html',1,'']]],
+  ['vmadevicememorycallbacks_249',['VmaDeviceMemoryCallbacks',['../struct_vma_device_memory_callbacks.html',1,'']]],
+  ['vmapool_250',['VmaPool',['../struct_vma_pool.html',1,'']]],
+  ['vmapoolcreateinfo_251',['VmaPoolCreateInfo',['../struct_vma_pool_create_info.html',1,'']]],
+  ['vmapoolstats_252',['VmaPoolStats',['../struct_vma_pool_stats.html',1,'']]],
+  ['vmarecordsettings_253',['VmaRecordSettings',['../struct_vma_record_settings.html',1,'']]],
+  ['vmastatinfo_254',['VmaStatInfo',['../struct_vma_stat_info.html',1,'']]],
+  ['vmastats_255',['VmaStats',['../struct_vma_stats.html',1,'']]],
+  ['vmavulkanfunctions_256',['VmaVulkanFunctions',['../struct_vma_vulkan_functions.html',1,'']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/classes_1.html b/third_party/VulkanMemoryAllocator/docs/html/search/classes_1.html
new file mode 100644
index 0000000..baeb182
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/classes_1.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.16"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="classes_1.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/classes_1.js b/third_party/VulkanMemoryAllocator/docs/html/search/classes_1.js
new file mode 100644
index 0000000..58b1ed2
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/classes_1.js
@@ -0,0 +1,22 @@
+var searchData=
+[
+  ['vmaallocation_232',['VmaAllocation',['../struct_vma_allocation.html',1,'']]],
+  ['vmaallocationinfo_233',['VmaAllocationInfo',['../struct_vma_allocation_info.html',1,'']]],
+  ['vmaallocator_234',['VmaAllocator',['../struct_vma_allocator.html',1,'']]],
+  ['vmaallocatorcreateinfo_235',['VmaAllocatorCreateInfo',['../struct_vma_allocator_create_info.html',1,'']]],
+  ['vmabudget_236',['VmaBudget',['../struct_vma_budget.html',1,'']]],
+  ['vmadefragmentationcontext_237',['VmaDefragmentationContext',['../struct_vma_defragmentation_context.html',1,'']]],
+  ['vmadefragmentationinfo_238',['VmaDefragmentationInfo',['../struct_vma_defragmentation_info.html',1,'']]],
+  ['vmadefragmentationinfo2_239',['VmaDefragmentationInfo2',['../struct_vma_defragmentation_info2.html',1,'']]],
+  ['vmadefragmentationpassinfo_240',['VmaDefragmentationPassInfo',['../struct_vma_defragmentation_pass_info.html',1,'']]],
+  ['vmadefragmentationpassmoveinfo_241',['VmaDefragmentationPassMoveInfo',['../struct_vma_defragmentation_pass_move_info.html',1,'']]],
+  ['vmadefragmentationstats_242',['VmaDefragmentationStats',['../struct_vma_defragmentation_stats.html',1,'']]],
+  ['vmadevicememorycallbacks_243',['VmaDeviceMemoryCallbacks',['../struct_vma_device_memory_callbacks.html',1,'']]],
+  ['vmapool_244',['VmaPool',['../struct_vma_pool.html',1,'']]],
+  ['vmapoolcreateinfo_245',['VmaPoolCreateInfo',['../struct_vma_pool_create_info.html',1,'']]],
+  ['vmapoolstats_246',['VmaPoolStats',['../struct_vma_pool_stats.html',1,'']]],
+  ['vmarecordsettings_247',['VmaRecordSettings',['../struct_vma_record_settings.html',1,'']]],
+  ['vmastatinfo_248',['VmaStatInfo',['../struct_vma_stat_info.html',1,'']]],
+  ['vmastats_249',['VmaStats',['../struct_vma_stats.html',1,'']]],
+  ['vmavulkanfunctions_250',['VmaVulkanFunctions',['../struct_vma_vulkan_functions.html',1,'']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/close.png b/third_party/VulkanMemoryAllocator/docs/html/search/close.png
new file mode 100644
index 0000000..9342d3d
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/close.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/defines_0.html b/third_party/VulkanMemoryAllocator/docs/html/search/defines_0.html
new file mode 100644
index 0000000..2deb369
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/defines_0.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="defines_0.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/defines_0.js b/third_party/VulkanMemoryAllocator/docs/html/search/defines_0.js
new file mode 100644
index 0000000..f9e8d33
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/defines_0.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['nominmax_468',['NOMINMAX',['../vk__mem__alloc_8h.html#a9f918755b601cf4bffca775992e6fb90',1,'vk_mem_alloc.h']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/defines_1.html b/third_party/VulkanMemoryAllocator/docs/html/search/defines_1.html
new file mode 100644
index 0000000..e0d0b6d
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/defines_1.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="defines_1.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/defines_1.js b/third_party/VulkanMemoryAllocator/docs/html/search/defines_1.js
new file mode 100644
index 0000000..9179c5b
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/defines_1.js
@@ -0,0 +1,10 @@
+var searchData=
+[
+  ['vma_5fbind_5fmemory2_469',['VMA_BIND_MEMORY2',['../vk__mem__alloc_8h.html#a88bef97f86d70a34a4c0746e09a2680d',1,'vk_mem_alloc.h']]],
+  ['vma_5fbuffer_5fdevice_5faddress_470',['VMA_BUFFER_DEVICE_ADDRESS',['../vk__mem__alloc_8h.html#a7f9d5e71b70dd1a137c303a8a8262c10',1,'vk_mem_alloc.h']]],
+  ['vma_5fdedicated_5fallocation_471',['VMA_DEDICATED_ALLOCATION',['../vk__mem__alloc_8h.html#af7b860e63b96d11e44ae8587ba06bbf4',1,'vk_mem_alloc.h']]],
+  ['vma_5fmemory_5fbudget_472',['VMA_MEMORY_BUDGET',['../vk__mem__alloc_8h.html#a05decf1cf4ebf767beba7acca6c1ec3a',1,'vk_mem_alloc.h']]],
+  ['vma_5frecording_5fenabled_473',['VMA_RECORDING_ENABLED',['../vk__mem__alloc_8h.html#a1f0c126759fc96ccb6e2d23c101d770c',1,'vk_mem_alloc.h']]],
+  ['vma_5fstats_5fstring_5fenabled_474',['VMA_STATS_STRING_ENABLED',['../vk__mem__alloc_8h.html#ae25f0d55fd91cb166f002b63244800e1',1,'vk_mem_alloc.h']]],
+  ['vma_5fvulkan_5fversion_475',['VMA_VULKAN_VERSION',['../vk__mem__alloc_8h.html#a1a2407c283893638cc039bb31fcd74b6',1,'vk_mem_alloc.h']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/enums_0.html b/third_party/VulkanMemoryAllocator/docs/html/search/enums_0.html
new file mode 100644
index 0000000..9669700
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/enums_0.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="enums_0.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/enums_0.js b/third_party/VulkanMemoryAllocator/docs/html/search/enums_0.js
new file mode 100644
index 0000000..d4fbd21
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/enums_0.js
@@ -0,0 +1,9 @@
+var searchData=
+[
+  ['vmaallocationcreateflagbits_421',['VmaAllocationCreateFlagBits',['../vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597',1,'vk_mem_alloc.h']]],
+  ['vmaallocatorcreateflagbits_422',['VmaAllocatorCreateFlagBits',['../vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7c',1,'vk_mem_alloc.h']]],
+  ['vmadefragmentationflagbits_423',['VmaDefragmentationFlagBits',['../vk__mem__alloc_8h.html#a6552a65b71d16f378c6994b3ceaef50c',1,'vk_mem_alloc.h']]],
+  ['vmamemoryusage_424',['VmaMemoryUsage',['../vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cc',1,'vk_mem_alloc.h']]],
+  ['vmapoolcreateflagbits_425',['VmaPoolCreateFlagBits',['../vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7',1,'vk_mem_alloc.h']]],
+  ['vmarecordflagbits_426',['VmaRecordFlagBits',['../vk__mem__alloc_8h.html#a4dd2c44642312a147a4e93373a6e64d2',1,'vk_mem_alloc.h']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/enumvalues_0.html b/third_party/VulkanMemoryAllocator/docs/html/search/enumvalues_0.html
new file mode 100644
index 0000000..9286248
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/enumvalues_0.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="enumvalues_0.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/enumvalues_0.js b/third_party/VulkanMemoryAllocator/docs/html/search/enumvalues_0.js
new file mode 100644
index 0000000..b3cfcfb
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/enumvalues_0.js
@@ -0,0 +1,44 @@
+var searchData=
+[
+  ['vma_5fallocation_5fcreate_5fcan_5fbecome_5flost_5fbit_427',['VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT',['../vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a5f436af6c8fe8540573a6d22627a6fd2',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocation_5fcreate_5fcan_5fmake_5fother_5flost_5fbit_428',['VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT',['../vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a68686d0ce9beb0d4d1b9f2b8b1389a7e',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocation_5fcreate_5fdedicated_5fmemory_5fbit_429',['VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT',['../vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a3fc311d855c2ff53f1090ef5c722b38f',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocation_5fcreate_5fdont_5fbind_5fbit_430',['VMA_ALLOCATION_CREATE_DONT_BIND_BIT',['../vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a2310568c62208af432724305fe29ccea',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocation_5fcreate_5fflag_5fbits_5fmax_5fenum_431',['VMA_ALLOCATION_CREATE_FLAG_BITS_MAX_ENUM',['../vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597ae5633ec569f4899cf8f29e7385b2f882',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocation_5fcreate_5fmapped_5fbit_432',['VMA_ALLOCATION_CREATE_MAPPED_BIT',['../vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a11da372cc3a82931c5e5d6146cd9dd1f',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocation_5fcreate_5fnever_5fallocate_5fbit_433',['VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT',['../vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a89759603401014eb325eb22a3839f2ff',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocation_5fcreate_5fstrategy_5fbest_5ffit_5fbit_434',['VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT',['../vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a839826775c62319466441f86496f036d',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocation_5fcreate_5fstrategy_5ffirst_5ffit_5fbit_435',['VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT',['../vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a33eb2052674f3ad92386c714a65fb777',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocation_5fcreate_5fstrategy_5fmask_436',['VMA_ALLOCATION_CREATE_STRATEGY_MASK',['../vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a8e16845d81ae3d27c47106d4770d5c7e',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocation_5fcreate_5fstrategy_5fmin_5ffragmentation_5fbit_437',['VMA_ALLOCATION_CREATE_STRATEGY_MIN_FRAGMENTATION_BIT',['../vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a621b704103eb3360230c860acf36e706',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocation_5fcreate_5fstrategy_5fmin_5fmemory_5fbit_438',['VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT',['../vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a8af1210cf591784afa026d94998f735d',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocation_5fcreate_5fstrategy_5fmin_5ftime_5fbit_439',['VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT',['../vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a0729e932b7ea170e3a128cad96c5cf6d',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocation_5fcreate_5fstrategy_5fworst_5ffit_5fbit_440',['VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT',['../vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597ad242a04f802e25fef0b880afe8bb0a62',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocation_5fcreate_5fupper_5faddress_5fbit_441',['VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT',['../vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a42ba3a2d2c7117953210b7c3ef8da0df',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocation_5fcreate_5fuser_5fdata_5fcopy_5fstring_5fbit_442',['VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT',['../vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597aa6f24f821cd6a7c5e4a443f7bf59c520',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocation_5fcreate_5fwithin_5fbudget_5fbit_443',['VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT',['../vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597ab8b1764f3e9022368e440c057783b92d',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocator_5fcreate_5famd_5fdevice_5fcoherent_5fmemory_5fbit_444',['VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT',['../vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca2acce4886d8078552efa38878413970f',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocator_5fcreate_5fbuffer_5fdevice_5faddress_5fbit_445',['VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT',['../vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca5f1b28b0414319d1687e1f2b30ab0089',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocator_5fcreate_5fext_5fmemory_5fbudget_5fbit_446',['VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT',['../vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca4d4687863f7bd4b418c6006dc04400b0',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocator_5fcreate_5fexternally_5fsynchronized_5fbit_447',['VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT',['../vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca4816ddaed324ba110172ca608a20f29d',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocator_5fcreate_5fflag_5fbits_5fmax_5fenum_448',['VMA_ALLOCATOR_CREATE_FLAG_BITS_MAX_ENUM',['../vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7cae4d5ad929caba5f23eb502b13bd5286c',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocator_5fcreate_5fkhr_5fbind_5fmemory2_5fbit_449',['VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT',['../vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca8fb75bf07cd184ab903596295e863dee',1,'vk_mem_alloc.h']]],
+  ['vma_5fallocator_5fcreate_5fkhr_5fdedicated_5fallocation_5fbit_450',['VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT',['../vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7cace7da7cc6e71a625dfa763c55a597878',1,'vk_mem_alloc.h']]],
+  ['vma_5fdefragmentation_5fflag_5fbits_5fmax_5fenum_451',['VMA_DEFRAGMENTATION_FLAG_BITS_MAX_ENUM',['../vk__mem__alloc_8h.html#a6552a65b71d16f378c6994b3ceaef50cab87ec33154803bfeb5ac2b379f1d6a97',1,'vk_mem_alloc.h']]],
+  ['vma_5fdefragmentation_5fflag_5fincremental_452',['VMA_DEFRAGMENTATION_FLAG_INCREMENTAL',['../vk__mem__alloc_8h.html#a6552a65b71d16f378c6994b3ceaef50ca31af49446af2459284a568ce2f3fdd33',1,'vk_mem_alloc.h']]],
+  ['vma_5fmemory_5fusage_5fcpu_5fcopy_453',['VMA_MEMORY_USAGE_CPU_COPY',['../vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca416a444d4d0fc20067c3f76f32ff2500',1,'vk_mem_alloc.h']]],
+  ['vma_5fmemory_5fusage_5fcpu_5fonly_454',['VMA_MEMORY_USAGE_CPU_ONLY',['../vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca40bdf4cddeffeb12f43d45ca1286e0a5',1,'vk_mem_alloc.h']]],
+  ['vma_5fmemory_5fusage_5fcpu_5fto_5fgpu_455',['VMA_MEMORY_USAGE_CPU_TO_GPU',['../vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca9066b52c5a7079bb74a69aaf8b92ff67',1,'vk_mem_alloc.h']]],
+  ['vma_5fmemory_5fusage_5fgpu_5flazily_5fallocated_456',['VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED',['../vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca835333d9072db63a653818030e17614d',1,'vk_mem_alloc.h']]],
+  ['vma_5fmemory_5fusage_5fgpu_5fonly_457',['VMA_MEMORY_USAGE_GPU_ONLY',['../vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7',1,'vk_mem_alloc.h']]],
+  ['vma_5fmemory_5fusage_5fgpu_5fto_5fcpu_458',['VMA_MEMORY_USAGE_GPU_TO_CPU',['../vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca7b586d2fdaf82a463b58f581ed72be27',1,'vk_mem_alloc.h']]],
+  ['vma_5fmemory_5fusage_5fmax_5fenum_459',['VMA_MEMORY_USAGE_MAX_ENUM',['../vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca091e69437ef693e8d0d287f1c719ba6e',1,'vk_mem_alloc.h']]],
+  ['vma_5fmemory_5fusage_5funknown_460',['VMA_MEMORY_USAGE_UNKNOWN',['../vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccaf50d27e34e0925cf3a63db8c839121dd',1,'vk_mem_alloc.h']]],
+  ['vma_5fpool_5fcreate_5falgorithm_5fmask_461',['VMA_POOL_CREATE_ALGORITHM_MASK',['../vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7af4d270f8f42517a0f70037ceb6ac1d9c',1,'vk_mem_alloc.h']]],
+  ['vma_5fpool_5fcreate_5fbuddy_5falgorithm_5fbit_462',['VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT',['../vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a97a0dc38e5161b780594d998d313d35e',1,'vk_mem_alloc.h']]],
+  ['vma_5fpool_5fcreate_5fflag_5fbits_5fmax_5fenum_463',['VMA_POOL_CREATE_FLAG_BITS_MAX_ENUM',['../vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a1c7312bea9ea246846b9054fd6bd6aec',1,'vk_mem_alloc.h']]],
+  ['vma_5fpool_5fcreate_5fignore_5fbuffer_5fimage_5fgranularity_5fbit_464',['VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT',['../vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a9f1a499508a8edb4e8ba40aa0290a3d2',1,'vk_mem_alloc.h']]],
+  ['vma_5fpool_5fcreate_5flinear_5falgorithm_5fbit_465',['VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT',['../vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a13c8a444197c67866be9cb05599fc726',1,'vk_mem_alloc.h']]],
+  ['vma_5frecord_5fflag_5fbits_5fmax_5fenum_466',['VMA_RECORD_FLAG_BITS_MAX_ENUM',['../vk__mem__alloc_8h.html#a4dd2c44642312a147a4e93373a6e64d2a20dd17d69966dbffa054739d6090b85e',1,'vk_mem_alloc.h']]],
+  ['vma_5frecord_5fflush_5fafter_5fcall_5fbit_467',['VMA_RECORD_FLUSH_AFTER_CALL_BIT',['../vk__mem__alloc_8h.html#a4dd2c44642312a147a4e93373a6e64d2a8e7ab322e8732654be627c4ea8f36cc7',1,'vk_mem_alloc.h']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/files_0.html b/third_party/VulkanMemoryAllocator/docs/html/search/files_0.html
new file mode 100644
index 0000000..737608e
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/files_0.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="files_0.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/files_0.js b/third_party/VulkanMemoryAllocator/docs/html/search/files_0.js
new file mode 100644
index 0000000..942faa9
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/files_0.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['vk_5fmem_5falloc_2eh_257',['vk_mem_alloc.h',['../vk__mem__alloc_8h.html',1,'']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/functions_0.html b/third_party/VulkanMemoryAllocator/docs/html/search/functions_0.html
new file mode 100644
index 0000000..e17c711
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/functions_0.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="functions_0.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/functions_0.js b/third_party/VulkanMemoryAllocator/docs/html/search/functions_0.js
new file mode 100644
index 0000000..cb80cff
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/functions_0.js
@@ -0,0 +1,53 @@
+var searchData=
+[
+  ['vmaallocatememory_258',['vmaAllocateMemory',['../vk__mem__alloc_8h.html#abf28077dbf82d0908b8acbe8ee8dd9b8',1,'vk_mem_alloc.h']]],
+  ['vmaallocatememoryforbuffer_259',['vmaAllocateMemoryForBuffer',['../vk__mem__alloc_8h.html#a7fdf64415b6c3d83c454f28d2c53df7b',1,'vk_mem_alloc.h']]],
+  ['vmaallocatememoryforimage_260',['vmaAllocateMemoryForImage',['../vk__mem__alloc_8h.html#a0faa3f9e5fb233d29d1e00390650febb',1,'vk_mem_alloc.h']]],
+  ['vmaallocatememorypages_261',['vmaAllocateMemoryPages',['../vk__mem__alloc_8h.html#ad37e82e492b3de38fc3f4cffd9ad0ae1',1,'vk_mem_alloc.h']]],
+  ['vmabegindefragmentationpass_262',['vmaBeginDefragmentationPass',['../vk__mem__alloc_8h.html#ac0f01545b6262f7d4d128fc8f8e5c77b',1,'vk_mem_alloc.h']]],
+  ['vmabindbuffermemory_263',['vmaBindBufferMemory',['../vk__mem__alloc_8h.html#a6b0929b914b60cf2d45cac4bf3547470',1,'vk_mem_alloc.h']]],
+  ['vmabindbuffermemory2_264',['vmaBindBufferMemory2',['../vk__mem__alloc_8h.html#a927c944f45e0f2941182abb6f608e64a',1,'vk_mem_alloc.h']]],
+  ['vmabindimagememory_265',['vmaBindImageMemory',['../vk__mem__alloc_8h.html#a3d3ca45799923aa5d138e9e5f9eb2da5',1,'vk_mem_alloc.h']]],
+  ['vmabindimagememory2_266',['vmaBindImageMemory2',['../vk__mem__alloc_8h.html#aa8251ee81b0045a443e35b8e8aa021bc',1,'vk_mem_alloc.h']]],
+  ['vmabuildstatsstring_267',['vmaBuildStatsString',['../vk__mem__alloc_8h.html#aa4fee7eb5253377599ef4fd38c93c2a0',1,'vk_mem_alloc.h']]],
+  ['vmacalculatestats_268',['vmaCalculateStats',['../vk__mem__alloc_8h.html#a333b61c1788cb23559177531e6a93ca3',1,'vk_mem_alloc.h']]],
+  ['vmacheckcorruption_269',['vmaCheckCorruption',['../vk__mem__alloc_8h.html#a49329a7f030dafcf82f7b73334c22e98',1,'vk_mem_alloc.h']]],
+  ['vmacheckpoolcorruption_270',['vmaCheckPoolCorruption',['../vk__mem__alloc_8h.html#ad535935619c7a549bf837e1bb0068f89',1,'vk_mem_alloc.h']]],
+  ['vmacreateallocator_271',['vmaCreateAllocator',['../vk__mem__alloc_8h.html#a200692051ddb34240248234f5f4c17bb',1,'vk_mem_alloc.h']]],
+  ['vmacreatebuffer_272',['vmaCreateBuffer',['../vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51',1,'vk_mem_alloc.h']]],
+  ['vmacreateimage_273',['vmaCreateImage',['../vk__mem__alloc_8h.html#a02a94f25679275851a53e82eacbcfc73',1,'vk_mem_alloc.h']]],
+  ['vmacreatelostallocation_274',['vmaCreateLostAllocation',['../vk__mem__alloc_8h.html#ae5c9657d9e94756269145b01c05d16f1',1,'vk_mem_alloc.h']]],
+  ['vmacreatepool_275',['vmaCreatePool',['../vk__mem__alloc_8h.html#a5c8770ded7c59c8caac6de0c2cb00b50',1,'vk_mem_alloc.h']]],
+  ['vmadefragment_276',['vmaDefragment',['../vk__mem__alloc_8h.html#a6aced90fcc7b39882b6654a740a0b9bb',1,'vk_mem_alloc.h']]],
+  ['vmadefragmentationbegin_277',['vmaDefragmentationBegin',['../vk__mem__alloc_8h.html#a36ba776fd7fd5cb1e9359fdc0d8e6e8a',1,'vk_mem_alloc.h']]],
+  ['vmadefragmentationend_278',['vmaDefragmentationEnd',['../vk__mem__alloc_8h.html#a8774e20e91e245aae959ba63efa15dd2',1,'vk_mem_alloc.h']]],
+  ['vmadestroyallocator_279',['vmaDestroyAllocator',['../vk__mem__alloc_8h.html#aa8d164061c88f22fb1fd3c8f3534bc1d',1,'vk_mem_alloc.h']]],
+  ['vmadestroybuffer_280',['vmaDestroyBuffer',['../vk__mem__alloc_8h.html#a0d9f4e4ba5bf9aab1f1c746387753d77',1,'vk_mem_alloc.h']]],
+  ['vmadestroyimage_281',['vmaDestroyImage',['../vk__mem__alloc_8h.html#ae50d2cb3b4a3bfd4dd40987234e50e7e',1,'vk_mem_alloc.h']]],
+  ['vmadestroypool_282',['vmaDestroyPool',['../vk__mem__alloc_8h.html#a5485779c8f1948238fc4e92232fa65e1',1,'vk_mem_alloc.h']]],
+  ['vmaenddefragmentationpass_283',['vmaEndDefragmentationPass',['../vk__mem__alloc_8h.html#a1b9ffa538bed905af55c747cc48963bd',1,'vk_mem_alloc.h']]],
+  ['vmafindmemorytypeindex_284',['vmaFindMemoryTypeIndex',['../vk__mem__alloc_8h.html#aef15a94b58fbcb0fe706d5720e84a74a',1,'vk_mem_alloc.h']]],
+  ['vmafindmemorytypeindexforbufferinfo_285',['vmaFindMemoryTypeIndexForBufferInfo',['../vk__mem__alloc_8h.html#ae790ab9ffaf7667fb8f62523e6897888',1,'vk_mem_alloc.h']]],
+  ['vmafindmemorytypeindexforimageinfo_286',['vmaFindMemoryTypeIndexForImageInfo',['../vk__mem__alloc_8h.html#a088da83d8eaf3ce9056d9ea0b981d472',1,'vk_mem_alloc.h']]],
+  ['vmaflushallocation_287',['vmaFlushAllocation',['../vk__mem__alloc_8h.html#abc34ee6f021f459aff885f3758c435de',1,'vk_mem_alloc.h']]],
+  ['vmafreememory_288',['vmaFreeMemory',['../vk__mem__alloc_8h.html#a11f0fbc034fa81a4efedd73d61ce7568',1,'vk_mem_alloc.h']]],
+  ['vmafreememorypages_289',['vmaFreeMemoryPages',['../vk__mem__alloc_8h.html#ab9e709de044c5d8476bea77a4e755840',1,'vk_mem_alloc.h']]],
+  ['vmafreestatsstring_290',['vmaFreeStatsString',['../vk__mem__alloc_8h.html#a3104eb30d8122c84dd8541063f145288',1,'vk_mem_alloc.h']]],
+  ['vmagetallocationinfo_291',['vmaGetAllocationInfo',['../vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b',1,'vk_mem_alloc.h']]],
+  ['vmagetallocatorinfo_292',['vmaGetAllocatorInfo',['../vk__mem__alloc_8h.html#afa02231a791b37255720d566a52683e7',1,'vk_mem_alloc.h']]],
+  ['vmagetbudget_293',['vmaGetBudget',['../vk__mem__alloc_8h.html#aec0ed24ebea2d0099eed5f801daaefba',1,'vk_mem_alloc.h']]],
+  ['vmagetmemoryproperties_294',['vmaGetMemoryProperties',['../vk__mem__alloc_8h.html#ab88db292a17974f911182543fda52d19',1,'vk_mem_alloc.h']]],
+  ['vmagetmemorytypeproperties_295',['vmaGetMemoryTypeProperties',['../vk__mem__alloc_8h.html#a8701444752eb5de4464adb5a2b514bca',1,'vk_mem_alloc.h']]],
+  ['vmagetphysicaldeviceproperties_296',['vmaGetPhysicalDeviceProperties',['../vk__mem__alloc_8h.html#aecabf7b6e91ea87d0316fa0a9e014fe0',1,'vk_mem_alloc.h']]],
+  ['vmagetpoolname_297',['vmaGetPoolName',['../vk__mem__alloc_8h.html#af09b4e4eafdbee812e8d73ddf960f030',1,'vk_mem_alloc.h']]],
+  ['vmagetpoolstats_298',['vmaGetPoolStats',['../vk__mem__alloc_8h.html#ae8bf76997b234ef68aad922616df4153',1,'vk_mem_alloc.h']]],
+  ['vmainvalidateallocation_299',['vmaInvalidateAllocation',['../vk__mem__alloc_8h.html#a0d0eb0c1102268fa9a476d12ecbe4006',1,'vk_mem_alloc.h']]],
+  ['vmamakepoolallocationslost_300',['vmaMakePoolAllocationsLost',['../vk__mem__alloc_8h.html#a736bd6cbda886f36c891727e73bd4024',1,'vk_mem_alloc.h']]],
+  ['vmamapmemory_301',['vmaMapMemory',['../vk__mem__alloc_8h.html#ad5bd1243512d099706de88168992f069',1,'vk_mem_alloc.h']]],
+  ['vmaresizeallocation_302',['vmaResizeAllocation',['../vk__mem__alloc_8h.html#a0ff488958ca72b28e545880463cb8696',1,'vk_mem_alloc.h']]],
+  ['vmasetallocationuserdata_303',['vmaSetAllocationUserData',['../vk__mem__alloc_8h.html#af9147d31ffc11d62fc187bde283ed14f',1,'vk_mem_alloc.h']]],
+  ['vmasetcurrentframeindex_304',['vmaSetCurrentFrameIndex',['../vk__mem__alloc_8h.html#ade56bf8dc9f5a5eaddf5f119ed525236',1,'vk_mem_alloc.h']]],
+  ['vmasetpoolname_305',['vmaSetPoolName',['../vk__mem__alloc_8h.html#adbae3a0b4ab078024462fc85c37f3b58',1,'vk_mem_alloc.h']]],
+  ['vmatouchallocation_306',['vmaTouchAllocation',['../vk__mem__alloc_8h.html#a43d8ba9673c846f049089a5029d5c73a',1,'vk_mem_alloc.h']]],
+  ['vmaunmapmemory_307',['vmaUnmapMemory',['../vk__mem__alloc_8h.html#a9bc268595cb33f6ec4d519cfce81ff45',1,'vk_mem_alloc.h']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/mag_sel.png b/third_party/VulkanMemoryAllocator/docs/html/search/mag_sel.png
new file mode 100644
index 0000000..39c0ed5
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/mag_sel.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/nomatches.html b/third_party/VulkanMemoryAllocator/docs/html/search/nomatches.html
new file mode 100644
index 0000000..4377320
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/nomatches.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="NoMatches">No Matches</div>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/pages_0.html b/third_party/VulkanMemoryAllocator/docs/html/search/pages_0.html
new file mode 100644
index 0000000..9a6a29a
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/pages_0.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="pages_0.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/pages_0.js b/third_party/VulkanMemoryAllocator/docs/html/search/pages_0.js
new file mode 100644
index 0000000..587a470
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/pages_0.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['allocation_20names_20and_20user_20data_476',['Allocation names and user data',['../allocation_annotation.html',1,'index']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/pages_1.html b/third_party/VulkanMemoryAllocator/docs/html/search/pages_1.html
new file mode 100644
index 0000000..132ee03
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/pages_1.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="pages_1.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/pages_1.js b/third_party/VulkanMemoryAllocator/docs/html/search/pages_1.js
new file mode 100644
index 0000000..cb8e626
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/pages_1.js
@@ -0,0 +1,6 @@
+var searchData=
+[
+  ['choosing_20memory_20type_477',['Choosing memory type',['../choosing_memory_type.html',1,'index']]],
+  ['configuration_478',['Configuration',['../configuration.html',1,'index']]],
+  ['custom_20memory_20pools_479',['Custom memory pools',['../custom_memory_pools.html',1,'index']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/pages_2.html b/third_party/VulkanMemoryAllocator/docs/html/search/pages_2.html
new file mode 100644
index 0000000..6109d47
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/pages_2.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="pages_2.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/pages_2.js b/third_party/VulkanMemoryAllocator/docs/html/search/pages_2.js
new file mode 100644
index 0000000..f5abef5
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/pages_2.js
@@ -0,0 +1,6 @@
+var searchData=
+[
+  ['debugging_20incorrect_20memory_20usage_480',['Debugging incorrect memory usage',['../debugging_memory_usage.html',1,'index']]],
+  ['defragmentation_481',['Defragmentation',['../defragmentation.html',1,'index']]],
+  ['deprecated_20list_482',['Deprecated List',['../deprecated.html',1,'']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/pages_3.html b/third_party/VulkanMemoryAllocator/docs/html/search/pages_3.html
new file mode 100644
index 0000000..54e8ba9
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/pages_3.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="pages_3.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/pages_3.js b/third_party/VulkanMemoryAllocator/docs/html/search/pages_3.js
new file mode 100644
index 0000000..30a0a86
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/pages_3.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['enabling_20buffer_20device_20address_483',['Enabling buffer device address',['../enabling_buffer_device_address.html',1,'index']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/pages_4.html b/third_party/VulkanMemoryAllocator/docs/html/search/pages_4.html
new file mode 100644
index 0000000..1ab6c5a
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/pages_4.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="pages_4.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/pages_4.js b/third_party/VulkanMemoryAllocator/docs/html/search/pages_4.js
new file mode 100644
index 0000000..70f6a63
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/pages_4.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['general_20considerations_484',['General considerations',['../general_considerations.html',1,'index']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/pages_5.html b/third_party/VulkanMemoryAllocator/docs/html/search/pages_5.html
new file mode 100644
index 0000000..b031763
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/pages_5.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="pages_5.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/pages_5.js b/third_party/VulkanMemoryAllocator/docs/html/search/pages_5.js
new file mode 100644
index 0000000..d5fa03c
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/pages_5.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['lost_20allocations_485',['Lost allocations',['../lost_allocations.html',1,'index']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/pages_6.html b/third_party/VulkanMemoryAllocator/docs/html/search/pages_6.html
new file mode 100644
index 0000000..8e6e67d
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/pages_6.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="pages_6.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/pages_6.js b/third_party/VulkanMemoryAllocator/docs/html/search/pages_6.js
new file mode 100644
index 0000000..891dc07
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/pages_6.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['memory_20mapping_486',['Memory mapping',['../memory_mapping.html',1,'index']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/pages_7.html b/third_party/VulkanMemoryAllocator/docs/html/search/pages_7.html
new file mode 100644
index 0000000..f8580ab
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/pages_7.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="pages_7.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/pages_7.js b/third_party/VulkanMemoryAllocator/docs/html/search/pages_7.js
new file mode 100644
index 0000000..e259d4d
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/pages_7.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['quick_20start_487',['Quick start',['../quick_start.html',1,'index']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/pages_8.html b/third_party/VulkanMemoryAllocator/docs/html/search/pages_8.html
new file mode 100644
index 0000000..8a86eef
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/pages_8.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="pages_8.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/pages_8.js b/third_party/VulkanMemoryAllocator/docs/html/search/pages_8.js
new file mode 100644
index 0000000..c536ab1
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/pages_8.js
@@ -0,0 +1,5 @@
+var searchData=
+[
+  ['record_20and_20replay_488',['Record and replay',['../record_and_replay.html',1,'index']]],
+  ['recommended_20usage_20patterns_489',['Recommended usage patterns',['../usage_patterns.html',1,'index']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/pages_9.html b/third_party/VulkanMemoryAllocator/docs/html/search/pages_9.html
new file mode 100644
index 0000000..9bf7ada
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/pages_9.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="pages_9.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/pages_9.js b/third_party/VulkanMemoryAllocator/docs/html/search/pages_9.js
new file mode 100644
index 0000000..2f855b9
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/pages_9.js
@@ -0,0 +1,5 @@
+var searchData=
+[
+  ['statistics_490',['Statistics',['../statistics.html',1,'index']]],
+  ['staying_20within_20budget_491',['Staying within budget',['../staying_within_budget.html',1,'index']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/pages_a.html b/third_party/VulkanMemoryAllocator/docs/html/search/pages_a.html
new file mode 100644
index 0000000..aa82daf
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/pages_a.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="pages_a.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/pages_a.js b/third_party/VulkanMemoryAllocator/docs/html/search/pages_a.js
new file mode 100644
index 0000000..29196aa
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/pages_a.js
@@ -0,0 +1,6 @@
+var searchData=
+[
+  ['vulkan_20memory_20allocator_492',['Vulkan Memory Allocator',['../index.html',1,'']]],
+  ['vk_5famd_5fdevice_5fcoherent_5fmemory_493',['VK_AMD_device_coherent_memory',['../vk_amd_device_coherent_memory.html',1,'index']]],
+  ['vk_5fkhr_5fdedicated_5fallocation_494',['VK_KHR_dedicated_allocation',['../vk_khr_dedicated_allocation.html',1,'index']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/search.css b/third_party/VulkanMemoryAllocator/docs/html/search/search.css
new file mode 100644
index 0000000..3cf9df9
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/search.css
@@ -0,0 +1,271 @@
+/*---------------- Search Box */
+
+#FSearchBox {
+    float: left;
+}
+
+#MSearchBox {
+    white-space : nowrap;
+    float: none;
+    margin-top: 8px;
+    right: 0px;
+    width: 170px;
+    height: 24px;
+    z-index: 102;
+}
+
+#MSearchBox .left
+{
+    display:block;
+    position:absolute;
+    left:10px;
+    width:20px;
+    height:19px;
+    background:url('search_l.png') no-repeat;
+    background-position:right;
+}
+
+#MSearchSelect {
+    display:block;
+    position:absolute;
+    width:20px;
+    height:19px;
+}
+
+.left #MSearchSelect {
+    left:4px;
+}
+
+.right #MSearchSelect {
+    right:5px;
+}
+
+#MSearchField {
+    display:block;
+    position:absolute;
+    height:19px;
+    background:url('search_m.png') repeat-x;
+    border:none;
+    width:115px;
+    margin-left:20px;
+    padding-left:4px;
+    color: #909090;
+    outline: none;
+    font: 9pt Arial, Verdana, sans-serif;
+    -webkit-border-radius: 0px;
+}
+
+#FSearchBox #MSearchField {
+    margin-left:15px;
+}
+
+#MSearchBox .right {
+    display:block;
+    position:absolute;
+    right:10px;
+    top:8px;
+    width:20px;
+    height:19px;
+    background:url('search_r.png') no-repeat;
+    background-position:left;
+}
+
+#MSearchClose {
+    display: none;
+    position: absolute;
+    top: 4px;
+    background : none;
+    border: none;
+    margin: 0px 4px 0px 0px;
+    padding: 0px 0px;
+    outline: none;
+}
+
+.left #MSearchClose {
+    left: 6px;
+}
+
+.right #MSearchClose {
+    right: 2px;
+}
+
+.MSearchBoxActive #MSearchField {
+    color: #000000;
+}
+
+/*---------------- Search filter selection */
+
+#MSearchSelectWindow {
+    display: none;
+    position: absolute;
+    left: 0; top: 0;
+    border: 1px solid #90A5CE;
+    background-color: #F9FAFC;
+    z-index: 10001;
+    padding-top: 4px;
+    padding-bottom: 4px;
+    -moz-border-radius: 4px;
+    -webkit-border-top-left-radius: 4px;
+    -webkit-border-top-right-radius: 4px;
+    -webkit-border-bottom-left-radius: 4px;
+    -webkit-border-bottom-right-radius: 4px;
+    -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
+}
+
+.SelectItem {
+    font: 8pt Arial, Verdana, sans-serif;
+    padding-left:  2px;
+    padding-right: 12px;
+    border: 0px;
+}
+
+span.SelectionMark {
+    margin-right: 4px;
+    font-family: monospace;
+    outline-style: none;
+    text-decoration: none;
+}
+
+a.SelectItem {
+    display: block;
+    outline-style: none;
+    color: #000000; 
+    text-decoration: none;
+    padding-left:   6px;
+    padding-right: 12px;
+}
+
+a.SelectItem:focus,
+a.SelectItem:active {
+    color: #000000; 
+    outline-style: none;
+    text-decoration: none;
+}
+
+a.SelectItem:hover {
+    color: #FFFFFF;
+    background-color: #3D578C;
+    outline-style: none;
+    text-decoration: none;
+    cursor: pointer;
+    display: block;
+}
+
+/*---------------- Search results window */
+
+iframe#MSearchResults {
+    width: 60ex;
+    height: 15em;
+}
+
+#MSearchResultsWindow {
+    display: none;
+    position: absolute;
+    left: 0; top: 0;
+    border: 1px solid #000;
+    background-color: #EEF1F7;
+    z-index:10000;
+}
+
+/* ----------------------------------- */
+
+
+#SRIndex {
+    clear:both; 
+    padding-bottom: 15px;
+}
+
+.SREntry {
+    font-size: 10pt;
+    padding-left: 1ex;
+}
+
+.SRPage .SREntry {
+    font-size: 8pt;
+    padding: 1px 5px;
+}
+
+body.SRPage {
+    margin: 5px 2px;
+}
+
+.SRChildren {
+    padding-left: 3ex; padding-bottom: .5em 
+}
+
+.SRPage .SRChildren {
+    display: none;
+}
+
+.SRSymbol {
+    font-weight: bold; 
+    color: #425E97;
+    font-family: Arial, Verdana, sans-serif;
+    text-decoration: none;
+    outline: none;
+}
+
+a.SRScope {
+    display: block;
+    color: #425E97; 
+    font-family: Arial, Verdana, sans-serif;
+    text-decoration: none;
+    outline: none;
+}
+
+a.SRSymbol:focus, a.SRSymbol:active,
+a.SRScope:focus, a.SRScope:active {
+    text-decoration: underline;
+}
+
+span.SRScope {
+    padding-left: 4px;
+}
+
+.SRPage .SRStatus {
+    padding: 2px 5px;
+    font-size: 8pt;
+    font-style: italic;
+}
+
+.SRResult {
+    display: none;
+}
+
+DIV.searchresults {
+    margin-left: 10px;
+    margin-right: 10px;
+}
+
+/*---------------- External search page results */
+
+.searchresult {
+    background-color: #F0F3F8;
+}
+
+.pages b {
+   color: white;
+   padding: 5px 5px 3px 5px;
+   background-image: url("../tab_a.png");
+   background-repeat: repeat-x;
+   text-shadow: 0 1px 1px #000000;
+}
+
+.pages {
+    line-height: 17px;
+    margin-left: 4px;
+    text-decoration: none;
+}
+
+.hl {
+    font-weight: bold;
+}
+
+#searchresults {
+    margin-bottom: 20px;
+}
+
+.searchpages {
+    margin-top: 10px;
+}
+
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/search.js b/third_party/VulkanMemoryAllocator/docs/html/search/search.js
new file mode 100644
index 0000000..a554ab9
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/search.js
@@ -0,0 +1,814 @@
+/*
+ @licstart  The following is the entire license notice for the
+ JavaScript code in this file.
+
+ Copyright (C) 1997-2017 by Dimitri van Heesch
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ @licend  The above is the entire license notice
+ for the JavaScript code in this file
+ */
+function convertToId(search)
+{
+  var result = '';
+  for (i=0;i<search.length;i++)
+  {
+    var c = search.charAt(i);
+    var cn = c.charCodeAt(0);
+    if (c.match(/[a-z0-9\u0080-\uFFFF]/))
+    {
+      result+=c;
+    }
+    else if (cn<16)
+    {
+      result+="_0"+cn.toString(16);
+    }
+    else
+    {
+      result+="_"+cn.toString(16);
+    }
+  }
+  return result;
+}
+
+function getXPos(item)
+{
+  var x = 0;
+  if (item.offsetWidth)
+  {
+    while (item && item!=document.body)
+    {
+      x   += item.offsetLeft;
+      item = item.offsetParent;
+    }
+  }
+  return x;
+}
+
+function getYPos(item)
+{
+  var y = 0;
+  if (item.offsetWidth)
+  {
+     while (item && item!=document.body)
+     {
+       y   += item.offsetTop;
+       item = item.offsetParent;
+     }
+  }
+  return y;
+}
+
+/* A class handling everything associated with the search panel.
+
+   Parameters:
+   name - The name of the global variable that will be
+          storing this instance.  Is needed to be able to set timeouts.
+   resultPath - path to use for external files
+*/
+function SearchBox(name, resultsPath, inFrame, label)
+{
+  if (!name || !resultsPath) {  alert("Missing parameters to SearchBox."); }
+
+  // ---------- Instance variables
+  this.name                  = name;
+  this.resultsPath           = resultsPath;
+  this.keyTimeout            = 0;
+  this.keyTimeoutLength      = 500;
+  this.closeSelectionTimeout = 300;
+  this.lastSearchValue       = "";
+  this.lastResultsPage       = "";
+  this.hideTimeout           = 0;
+  this.searchIndex           = 0;
+  this.searchActive          = false;
+  this.insideFrame           = inFrame;
+  this.searchLabel           = label;
+
+  // ----------- DOM Elements
+
+  this.DOMSearchField = function()
+  {  return document.getElementById("MSearchField");  }
+
+  this.DOMSearchSelect = function()
+  {  return document.getElementById("MSearchSelect");  }
+
+  this.DOMSearchSelectWindow = function()
+  {  return document.getElementById("MSearchSelectWindow");  }
+
+  this.DOMPopupSearchResults = function()
+  {  return document.getElementById("MSearchResults");  }
+
+  this.DOMPopupSearchResultsWindow = function()
+  {  return document.getElementById("MSearchResultsWindow");  }
+
+  this.DOMSearchClose = function()
+  {  return document.getElementById("MSearchClose"); }
+
+  this.DOMSearchBox = function()
+  {  return document.getElementById("MSearchBox");  }
+
+  // ------------ Event Handlers
+
+  // Called when focus is added or removed from the search field.
+  this.OnSearchFieldFocus = function(isActive)
+  {
+    this.Activate(isActive);
+  }
+
+  this.OnSearchSelectShow = function()
+  {
+    var searchSelectWindow = this.DOMSearchSelectWindow();
+    var searchField        = this.DOMSearchSelect();
+
+    if (this.insideFrame)
+    {
+      var left = getXPos(searchField);
+      var top  = getYPos(searchField);
+      left += searchField.offsetWidth + 6;
+      top += searchField.offsetHeight;
+
+      // show search selection popup
+      searchSelectWindow.style.display='block';
+      left -= searchSelectWindow.offsetWidth;
+      searchSelectWindow.style.left =  left + 'px';
+      searchSelectWindow.style.top  =  top  + 'px';
+    }
+    else
+    {
+      var left = getXPos(searchField);
+      var top  = getYPos(searchField);
+      top += searchField.offsetHeight;
+
+      // show search selection popup
+      searchSelectWindow.style.display='block';
+      searchSelectWindow.style.left =  left + 'px';
+      searchSelectWindow.style.top  =  top  + 'px';
+    }
+
+    // stop selection hide timer
+    if (this.hideTimeout)
+    {
+      clearTimeout(this.hideTimeout);
+      this.hideTimeout=0;
+    }
+    return false; // to avoid "image drag" default event
+  }
+
+  this.OnSearchSelectHide = function()
+  {
+    this.hideTimeout = setTimeout(this.name +".CloseSelectionWindow()",
+                                  this.closeSelectionTimeout);
+  }
+
+  // Called when the content of the search field is changed.
+  this.OnSearchFieldChange = function(evt)
+  {
+    if (this.keyTimeout) // kill running timer
+    {
+      clearTimeout(this.keyTimeout);
+      this.keyTimeout = 0;
+    }
+
+    var e  = (evt) ? evt : window.event; // for IE
+    if (e.keyCode==40 || e.keyCode==13)
+    {
+      if (e.shiftKey==1)
+      {
+        this.OnSearchSelectShow();
+        var win=this.DOMSearchSelectWindow();
+        for (i=0;i<win.childNodes.length;i++)
+        {
+          var child = win.childNodes[i]; // get span within a
+          if (child.className=='SelectItem')
+          {
+            child.focus();
+            return;
+          }
+        }
+        return;
+      }
+      else if (window.frames.MSearchResults.searchResults)
+      {
+        var elem = window.frames.MSearchResults.searchResults.NavNext(0);
+        if (elem) elem.focus();
+      }
+    }
+    else if (e.keyCode==27) // Escape out of the search field
+    {
+      this.DOMSearchField().blur();
+      this.DOMPopupSearchResultsWindow().style.display = 'none';
+      this.DOMSearchClose().style.display = 'none';
+      this.lastSearchValue = '';
+      this.Activate(false);
+      return;
+    }
+
+    // strip whitespaces
+    var searchValue = this.DOMSearchField().value.replace(/ +/g, "");
+
+    if (searchValue != this.lastSearchValue) // search value has changed
+    {
+      if (searchValue != "") // non-empty search
+      {
+        // set timer for search update
+        this.keyTimeout = setTimeout(this.name + '.Search()',
+                                     this.keyTimeoutLength);
+      }
+      else // empty search field
+      {
+        this.DOMPopupSearchResultsWindow().style.display = 'none';
+        this.DOMSearchClose().style.display = 'none';
+        this.lastSearchValue = '';
+      }
+    }
+  }
+
+  this.SelectItemCount = function(id)
+  {
+    var count=0;
+    var win=this.DOMSearchSelectWindow();
+    for (i=0;i<win.childNodes.length;i++)
+    {
+      var child = win.childNodes[i]; // get span within a
+      if (child.className=='SelectItem')
+      {
+        count++;
+      }
+    }
+    return count;
+  }
+
+  this.SelectItemSet = function(id)
+  {
+    var i,j=0;
+    var win=this.DOMSearchSelectWindow();
+    for (i=0;i<win.childNodes.length;i++)
+    {
+      var child = win.childNodes[i]; // get span within a
+      if (child.className=='SelectItem')
+      {
+        var node = child.firstChild;
+        if (j==id)
+        {
+          node.innerHTML='&#8226;';
+        }
+        else
+        {
+          node.innerHTML='&#160;';
+        }
+        j++;
+      }
+    }
+  }
+
+  // Called when an search filter selection is made.
+  // set item with index id as the active item
+  this.OnSelectItem = function(id)
+  {
+    this.searchIndex = id;
+    this.SelectItemSet(id);
+    var searchValue = this.DOMSearchField().value.replace(/ +/g, "");
+    if (searchValue!="" && this.searchActive) // something was found -> do a search
+    {
+      this.Search();
+    }
+  }
+
+  this.OnSearchSelectKey = function(evt)
+  {
+    var e = (evt) ? evt : window.event; // for IE
+    if (e.keyCode==40 && this.searchIndex<this.SelectItemCount()) // Down
+    {
+      this.searchIndex++;
+      this.OnSelectItem(this.searchIndex);
+    }
+    else if (e.keyCode==38 && this.searchIndex>0) // Up
+    {
+      this.searchIndex--;
+      this.OnSelectItem(this.searchIndex);
+    }
+    else if (e.keyCode==13 || e.keyCode==27)
+    {
+      this.OnSelectItem(this.searchIndex);
+      this.CloseSelectionWindow();
+      this.DOMSearchField().focus();
+    }
+    return false;
+  }
+
+  // --------- Actions
+
+  // Closes the results window.
+  this.CloseResultsWindow = function()
+  {
+    this.DOMPopupSearchResultsWindow().style.display = 'none';
+    this.DOMSearchClose().style.display = 'none';
+    this.Activate(false);
+  }
+
+  this.CloseSelectionWindow = function()
+  {
+    this.DOMSearchSelectWindow().style.display = 'none';
+  }
+
+  // Performs a search.
+  this.Search = function()
+  {
+    this.keyTimeout = 0;
+
+    // strip leading whitespace
+    var searchValue = this.DOMSearchField().value.replace(/^ +/, "");
+
+    var code = searchValue.toLowerCase().charCodeAt(0);
+    var idxChar = searchValue.substr(0, 1).toLowerCase();
+    if ( 0xD800 <= code && code <= 0xDBFF && searchValue > 1) // surrogate pair
+    {
+      idxChar = searchValue.substr(0, 2);
+    }
+
+    var resultsPage;
+    var resultsPageWithSearch;
+    var hasResultsPage;
+
+    var idx = indexSectionsWithContent[this.searchIndex].indexOf(idxChar);
+    if (idx!=-1)
+    {
+       var hexCode=idx.toString(16);
+       resultsPage = this.resultsPath + '/' + indexSectionNames[this.searchIndex] + '_' + hexCode + '.html';
+       resultsPageWithSearch = resultsPage+'?'+escape(searchValue);
+       hasResultsPage = true;
+    }
+    else // nothing available for this search term
+    {
+       resultsPage = this.resultsPath + '/nomatches.html';
+       resultsPageWithSearch = resultsPage;
+       hasResultsPage = false;
+    }
+
+    window.frames.MSearchResults.location = resultsPageWithSearch;
+    var domPopupSearchResultsWindow = this.DOMPopupSearchResultsWindow();
+
+    if (domPopupSearchResultsWindow.style.display!='block')
+    {
+       var domSearchBox = this.DOMSearchBox();
+       this.DOMSearchClose().style.display = 'inline';
+       if (this.insideFrame)
+       {
+         var domPopupSearchResults = this.DOMPopupSearchResults();
+         domPopupSearchResultsWindow.style.position = 'relative';
+         domPopupSearchResultsWindow.style.display  = 'block';
+         var width = document.body.clientWidth - 8; // the -8 is for IE :-(
+         domPopupSearchResultsWindow.style.width    = width + 'px';
+         domPopupSearchResults.style.width          = width + 'px';
+       }
+       else
+       {
+         var domPopupSearchResults = this.DOMPopupSearchResults();
+         var left = getXPos(domSearchBox) + 150; // domSearchBox.offsetWidth;
+         var top  = getYPos(domSearchBox) + 20;  // domSearchBox.offsetHeight + 1;
+         domPopupSearchResultsWindow.style.display = 'block';
+         left -= domPopupSearchResults.offsetWidth;
+         domPopupSearchResultsWindow.style.top     = top  + 'px';
+         domPopupSearchResultsWindow.style.left    = left + 'px';
+       }
+    }
+
+    this.lastSearchValue = searchValue;
+    this.lastResultsPage = resultsPage;
+  }
+
+  // -------- Activation Functions
+
+  // Activates or deactivates the search panel, resetting things to
+  // their default values if necessary.
+  this.Activate = function(isActive)
+  {
+    if (isActive || // open it
+        this.DOMPopupSearchResultsWindow().style.display == 'block'
+       )
+    {
+      this.DOMSearchBox().className = 'MSearchBoxActive';
+
+      var searchField = this.DOMSearchField();
+
+      if (searchField.value == this.searchLabel) // clear "Search" term upon entry
+      {
+        searchField.value = '';
+        this.searchActive = true;
+      }
+    }
+    else if (!isActive) // directly remove the panel
+    {
+      this.DOMSearchBox().className = 'MSearchBoxInactive';
+      this.DOMSearchField().value   = this.searchLabel;
+      this.searchActive             = false;
+      this.lastSearchValue          = ''
+      this.lastResultsPage          = '';
+    }
+  }
+}
+
+// -----------------------------------------------------------------------
+
+// The class that handles everything on the search results page.
+function SearchResults(name)
+{
+    // The number of matches from the last run of <Search()>.
+    this.lastMatchCount = 0;
+    this.lastKey = 0;
+    this.repeatOn = false;
+
+    // Toggles the visibility of the passed element ID.
+    this.FindChildElement = function(id)
+    {
+      var parentElement = document.getElementById(id);
+      var element = parentElement.firstChild;
+
+      while (element && element!=parentElement)
+      {
+        if (element.nodeName == 'DIV' && element.className == 'SRChildren')
+        {
+          return element;
+        }
+
+        if (element.nodeName == 'DIV' && element.hasChildNodes())
+        {
+           element = element.firstChild;
+        }
+        else if (element.nextSibling)
+        {
+           element = element.nextSibling;
+        }
+        else
+        {
+          do
+          {
+            element = element.parentNode;
+          }
+          while (element && element!=parentElement && !element.nextSibling);
+
+          if (element && element!=parentElement)
+          {
+            element = element.nextSibling;
+          }
+        }
+      }
+    }
+
+    this.Toggle = function(id)
+    {
+      var element = this.FindChildElement(id);
+      if (element)
+      {
+        if (element.style.display == 'block')
+        {
+          element.style.display = 'none';
+        }
+        else
+        {
+          element.style.display = 'block';
+        }
+      }
+    }
+
+    // Searches for the passed string.  If there is no parameter,
+    // it takes it from the URL query.
+    //
+    // Always returns true, since other documents may try to call it
+    // and that may or may not be possible.
+    this.Search = function(search)
+    {
+      if (!search) // get search word from URL
+      {
+        search = window.location.search;
+        search = search.substring(1);  // Remove the leading '?'
+        search = unescape(search);
+      }
+
+      search = search.replace(/^ +/, ""); // strip leading spaces
+      search = search.replace(/ +$/, ""); // strip trailing spaces
+      search = search.toLowerCase();
+      search = convertToId(search);
+
+      var resultRows = document.getElementsByTagName("div");
+      var matches = 0;
+
+      var i = 0;
+      while (i < resultRows.length)
+      {
+        var row = resultRows.item(i);
+        if (row.className == "SRResult")
+        {
+          var rowMatchName = row.id.toLowerCase();
+          rowMatchName = rowMatchName.replace(/^sr\d*_/, ''); // strip 'sr123_'
+
+          if (search.length<=rowMatchName.length &&
+             rowMatchName.substr(0, search.length)==search)
+          {
+            row.style.display = 'block';
+            matches++;
+          }
+          else
+          {
+            row.style.display = 'none';
+          }
+        }
+        i++;
+      }
+      document.getElementById("Searching").style.display='none';
+      if (matches == 0) // no results
+      {
+        document.getElementById("NoMatches").style.display='block';
+      }
+      else // at least one result
+      {
+        document.getElementById("NoMatches").style.display='none';
+      }
+      this.lastMatchCount = matches;
+      return true;
+    }
+
+    // return the first item with index index or higher that is visible
+    this.NavNext = function(index)
+    {
+      var focusItem;
+      while (1)
+      {
+        var focusName = 'Item'+index;
+        focusItem = document.getElementById(focusName);
+        if (focusItem && focusItem.parentNode.parentNode.style.display=='block')
+        {
+          break;
+        }
+        else if (!focusItem) // last element
+        {
+          break;
+        }
+        focusItem=null;
+        index++;
+      }
+      return focusItem;
+    }
+
+    this.NavPrev = function(index)
+    {
+      var focusItem;
+      while (1)
+      {
+        var focusName = 'Item'+index;
+        focusItem = document.getElementById(focusName);
+        if (focusItem && focusItem.parentNode.parentNode.style.display=='block')
+        {
+          break;
+        }
+        else if (!focusItem) // last element
+        {
+          break;
+        }
+        focusItem=null;
+        index--;
+      }
+      return focusItem;
+    }
+
+    this.ProcessKeys = function(e)
+    {
+      if (e.type == "keydown")
+      {
+        this.repeatOn = false;
+        this.lastKey = e.keyCode;
+      }
+      else if (e.type == "keypress")
+      {
+        if (!this.repeatOn)
+        {
+          if (this.lastKey) this.repeatOn = true;
+          return false; // ignore first keypress after keydown
+        }
+      }
+      else if (e.type == "keyup")
+      {
+        this.lastKey = 0;
+        this.repeatOn = false;
+      }
+      return this.lastKey!=0;
+    }
+
+    this.Nav = function(evt,itemIndex)
+    {
+      var e  = (evt) ? evt : window.event; // for IE
+      if (e.keyCode==13) return true;
+      if (!this.ProcessKeys(e)) return false;
+
+      if (this.lastKey==38) // Up
+      {
+        var newIndex = itemIndex-1;
+        var focusItem = this.NavPrev(newIndex);
+        if (focusItem)
+        {
+          var child = this.FindChildElement(focusItem.parentNode.parentNode.id);
+          if (child && child.style.display == 'block') // children visible
+          {
+            var n=0;
+            var tmpElem;
+            while (1) // search for last child
+            {
+              tmpElem = document.getElementById('Item'+newIndex+'_c'+n);
+              if (tmpElem)
+              {
+                focusItem = tmpElem;
+              }
+              else // found it!
+              {
+                break;
+              }
+              n++;
+            }
+          }
+        }
+        if (focusItem)
+        {
+          focusItem.focus();
+        }
+        else // return focus to search field
+        {
+           parent.document.getElementById("MSearchField").focus();
+        }
+      }
+      else if (this.lastKey==40) // Down
+      {
+        var newIndex = itemIndex+1;
+        var focusItem;
+        var item = document.getElementById('Item'+itemIndex);
+        var elem = this.FindChildElement(item.parentNode.parentNode.id);
+        if (elem && elem.style.display == 'block') // children visible
+        {
+          focusItem = document.getElementById('Item'+itemIndex+'_c0');
+        }
+        if (!focusItem) focusItem = this.NavNext(newIndex);
+        if (focusItem)  focusItem.focus();
+      }
+      else if (this.lastKey==39) // Right
+      {
+        var item = document.getElementById('Item'+itemIndex);
+        var elem = this.FindChildElement(item.parentNode.parentNode.id);
+        if (elem) elem.style.display = 'block';
+      }
+      else if (this.lastKey==37) // Left
+      {
+        var item = document.getElementById('Item'+itemIndex);
+        var elem = this.FindChildElement(item.parentNode.parentNode.id);
+        if (elem) elem.style.display = 'none';
+      }
+      else if (this.lastKey==27) // Escape
+      {
+        parent.searchBox.CloseResultsWindow();
+        parent.document.getElementById("MSearchField").focus();
+      }
+      else if (this.lastKey==13) // Enter
+      {
+        return true;
+      }
+      return false;
+    }
+
+    this.NavChild = function(evt,itemIndex,childIndex)
+    {
+      var e  = (evt) ? evt : window.event; // for IE
+      if (e.keyCode==13) return true;
+      if (!this.ProcessKeys(e)) return false;
+
+      if (this.lastKey==38) // Up
+      {
+        if (childIndex>0)
+        {
+          var newIndex = childIndex-1;
+          document.getElementById('Item'+itemIndex+'_c'+newIndex).focus();
+        }
+        else // already at first child, jump to parent
+        {
+          document.getElementById('Item'+itemIndex).focus();
+        }
+      }
+      else if (this.lastKey==40) // Down
+      {
+        var newIndex = childIndex+1;
+        var elem = document.getElementById('Item'+itemIndex+'_c'+newIndex);
+        if (!elem) // last child, jump to parent next parent
+        {
+          elem = this.NavNext(itemIndex+1);
+        }
+        if (elem)
+        {
+          elem.focus();
+        }
+      }
+      else if (this.lastKey==27) // Escape
+      {
+        parent.searchBox.CloseResultsWindow();
+        parent.document.getElementById("MSearchField").focus();
+      }
+      else if (this.lastKey==13) // Enter
+      {
+        return true;
+      }
+      return false;
+    }
+}
+
+function setKeyActions(elem,action)
+{
+  elem.setAttribute('onkeydown',action);
+  elem.setAttribute('onkeypress',action);
+  elem.setAttribute('onkeyup',action);
+}
+
+function setClassAttr(elem,attr)
+{
+  elem.setAttribute('class',attr);
+  elem.setAttribute('className',attr);
+}
+
+function createResults()
+{
+  var results = document.getElementById("SRResults");
+  for (var e=0; e<searchData.length; e++)
+  {
+    var id = searchData[e][0];
+    var srResult = document.createElement('div');
+    srResult.setAttribute('id','SR_'+id);
+    setClassAttr(srResult,'SRResult');
+    var srEntry = document.createElement('div');
+    setClassAttr(srEntry,'SREntry');
+    var srLink = document.createElement('a');
+    srLink.setAttribute('id','Item'+e);
+    setKeyActions(srLink,'return searchResults.Nav(event,'+e+')');
+    setClassAttr(srLink,'SRSymbol');
+    srLink.innerHTML = searchData[e][1][0];
+    srEntry.appendChild(srLink);
+    if (searchData[e][1].length==2) // single result
+    {
+      srLink.setAttribute('href',searchData[e][1][1][0]);
+      if (searchData[e][1][1][1])
+      {
+       srLink.setAttribute('target','_parent');
+      }
+      var srScope = document.createElement('span');
+      setClassAttr(srScope,'SRScope');
+      srScope.innerHTML = searchData[e][1][1][2];
+      srEntry.appendChild(srScope);
+    }
+    else // multiple results
+    {
+      srLink.setAttribute('href','javascript:searchResults.Toggle("SR_'+id+'")');
+      var srChildren = document.createElement('div');
+      setClassAttr(srChildren,'SRChildren');
+      for (var c=0; c<searchData[e][1].length-1; c++)
+      {
+        var srChild = document.createElement('a');
+        srChild.setAttribute('id','Item'+e+'_c'+c);
+        setKeyActions(srChild,'return searchResults.NavChild(event,'+e+','+c+')');
+        setClassAttr(srChild,'SRScope');
+        srChild.setAttribute('href',searchData[e][1][c+1][0]);
+        if (searchData[e][1][c+1][1])
+        {
+         srChild.setAttribute('target','_parent');
+        }
+        srChild.innerHTML = searchData[e][1][c+1][2];
+        srChildren.appendChild(srChild);
+      }
+      srEntry.appendChild(srChildren);
+    }
+    srResult.appendChild(srEntry);
+    results.appendChild(srResult);
+  }
+}
+
+function init_search()
+{
+  var results = document.getElementById("MSearchSelectWindow");
+  for (var key in indexSectionLabels)
+  {
+    var link = document.createElement('a');
+    link.setAttribute('class','SelectItem');
+    link.setAttribute('onclick','searchBox.OnSelectItem('+key+')');
+    link.href='javascript:void(0)';
+    link.innerHTML='<span class="SelectionMark">&#160;</span>'+indexSectionLabels[key];
+    results.appendChild(link);
+  }
+  searchBox.OnSelectItem(0);
+}
+/* @license-end */
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/search_l.png b/third_party/VulkanMemoryAllocator/docs/html/search/search_l.png
new file mode 100644
index 0000000..fd5f7da
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/search_l.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/search_m.png b/third_party/VulkanMemoryAllocator/docs/html/search/search_m.png
new file mode 100644
index 0000000..b429a16
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/search_m.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/search_r.png b/third_party/VulkanMemoryAllocator/docs/html/search/search_r.png
new file mode 100644
index 0000000..1af5d21
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/search_r.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/searchdata.js b/third_party/VulkanMemoryAllocator/docs/html/search/searchdata.js
new file mode 100644
index 0000000..6a7e9be
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/searchdata.js
@@ -0,0 +1,42 @@
+var indexSectionsWithContent =
+{
+  0: "abcdefgilmnopqrstuv",
+  1: "v",
+  2: "v",
+  3: "v",
+  4: "abcdfimoprstuv",
+  5: "pv",
+  6: "v",
+  7: "v",
+  8: "nv",
+  9: "acdeglmqrsv"
+};
+
+var indexSectionNames =
+{
+  0: "all",
+  1: "classes",
+  2: "files",
+  3: "functions",
+  4: "variables",
+  5: "typedefs",
+  6: "enums",
+  7: "enumvalues",
+  8: "defines",
+  9: "pages"
+};
+
+var indexSectionLabels =
+{
+  0: "All",
+  1: "Classes",
+  2: "Files",
+  3: "Functions",
+  4: "Variables",
+  5: "Typedefs",
+  6: "Enumerations",
+  7: "Enumerator",
+  8: "Macros",
+  9: "Pages"
+};
+
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/typedefs_0.html b/third_party/VulkanMemoryAllocator/docs/html/search/typedefs_0.html
new file mode 100644
index 0000000..376db47
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/typedefs_0.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="typedefs_0.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/typedefs_0.js b/third_party/VulkanMemoryAllocator/docs/html/search/typedefs_0.js
new file mode 100644
index 0000000..cc8b3cd
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/typedefs_0.js
@@ -0,0 +1,5 @@
+var searchData=
+[
+  ['pfn_5fvmaallocatedevicememoryfunction_391',['PFN_vmaAllocateDeviceMemoryFunction',['../vk__mem__alloc_8h.html#a7e1ed85f7799600b03ad51a77acc21f3',1,'vk_mem_alloc.h']]],
+  ['pfn_5fvmafreedevicememoryfunction_392',['PFN_vmaFreeDeviceMemoryFunction',['../vk__mem__alloc_8h.html#a154ccaaf53dc2c36378f80f0c4f3679b',1,'vk_mem_alloc.h']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/typedefs_1.html b/third_party/VulkanMemoryAllocator/docs/html/search/typedefs_1.html
new file mode 100644
index 0000000..9b8bf72
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/typedefs_1.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="typedefs_1.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/typedefs_1.js b/third_party/VulkanMemoryAllocator/docs/html/search/typedefs_1.js
new file mode 100644
index 0000000..039d466
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/typedefs_1.js
@@ -0,0 +1,31 @@
+var searchData=
+[
+  ['vmaallocationcreateflagbits_393',['VmaAllocationCreateFlagBits',['../vk__mem__alloc_8h.html#a4fceecc301f4064dc808d3cd6c038941',1,'vk_mem_alloc.h']]],
+  ['vmaallocationcreateflags_394',['VmaAllocationCreateFlags',['../vk__mem__alloc_8h.html#a5225e5e11f8376f6a31a1791f3d6e817',1,'vk_mem_alloc.h']]],
+  ['vmaallocationcreateinfo_395',['VmaAllocationCreateInfo',['../vk__mem__alloc_8h.html#a3bf110892ea2fb4649fedb68488d026a',1,'vk_mem_alloc.h']]],
+  ['vmaallocationinfo_396',['VmaAllocationInfo',['../vk__mem__alloc_8h.html#a1cf7774606721026a68aabe3af2e5b50',1,'vk_mem_alloc.h']]],
+  ['vmaallocatorcreateflagbits_397',['VmaAllocatorCreateFlagBits',['../vk__mem__alloc_8h.html#afd73b95e737ee7e76f827cb5472f559f',1,'vk_mem_alloc.h']]],
+  ['vmaallocatorcreateflags_398',['VmaAllocatorCreateFlags',['../vk__mem__alloc_8h.html#acfe6863e160722c2c1bbcf7573fddc4d',1,'vk_mem_alloc.h']]],
+  ['vmaallocatorcreateinfo_399',['VmaAllocatorCreateInfo',['../vk__mem__alloc_8h.html#aad9652301d33759b83e52d4f3605a14a',1,'vk_mem_alloc.h']]],
+  ['vmaallocatorinfo_400',['VmaAllocatorInfo',['../vk__mem__alloc_8h.html#a1988031b0223fdbd564250fa1edd942c',1,'vk_mem_alloc.h']]],
+  ['vmabudget_401',['VmaBudget',['../vk__mem__alloc_8h.html#aa078667e71b1ef24e87a6a30d128381d',1,'vk_mem_alloc.h']]],
+  ['vmadefragmentationflagbits_402',['VmaDefragmentationFlagBits',['../vk__mem__alloc_8h.html#a13415cc0b443353a7b5abda300b833fc',1,'vk_mem_alloc.h']]],
+  ['vmadefragmentationflags_403',['VmaDefragmentationFlags',['../vk__mem__alloc_8h.html#a88a77cef37e5d3c4fc9eb328885d048d',1,'vk_mem_alloc.h']]],
+  ['vmadefragmentationinfo_404',['VmaDefragmentationInfo',['../vk__mem__alloc_8h.html#a2bf47f96bf92bed2a49461bd9af3acfa',1,'vk_mem_alloc.h']]],
+  ['vmadefragmentationinfo2_405',['VmaDefragmentationInfo2',['../vk__mem__alloc_8h.html#ad6daeffaa670ce6d11a203a6224c9937',1,'vk_mem_alloc.h']]],
+  ['vmadefragmentationpassinfo_406',['VmaDefragmentationPassInfo',['../vk__mem__alloc_8h.html#a72aebd522242d56abea67b4f47f6549e',1,'vk_mem_alloc.h']]],
+  ['vmadefragmentationpassmoveinfo_407',['VmaDefragmentationPassMoveInfo',['../vk__mem__alloc_8h.html#ad6799e8e2b1527abfc84d33bc44aeaf5',1,'vk_mem_alloc.h']]],
+  ['vmadefragmentationstats_408',['VmaDefragmentationStats',['../vk__mem__alloc_8h.html#ad94034192259c2e34a4d1c5e27810403',1,'vk_mem_alloc.h']]],
+  ['vmadevicememorycallbacks_409',['VmaDeviceMemoryCallbacks',['../vk__mem__alloc_8h.html#a77692d3c8770ea8882d573206bd27b2b',1,'vk_mem_alloc.h']]],
+  ['vmamemoryusage_410',['VmaMemoryUsage',['../vk__mem__alloc_8h.html#a806e8499dde802e59eb72a1dc811c35f',1,'vk_mem_alloc.h']]],
+  ['vmapoolcreateflagbits_411',['VmaPoolCreateFlagBits',['../vk__mem__alloc_8h.html#a4d4f2efc2509157a9e4ecd4fd7942303',1,'vk_mem_alloc.h']]],
+  ['vmapoolcreateflags_412',['VmaPoolCreateFlags',['../vk__mem__alloc_8h.html#a2770e325ea42e087c1b91fdf46d0292a',1,'vk_mem_alloc.h']]],
+  ['vmapoolcreateinfo_413',['VmaPoolCreateInfo',['../vk__mem__alloc_8h.html#a1017aa83489c0eee8d2163d2bf253f67',1,'vk_mem_alloc.h']]],
+  ['vmapoolstats_414',['VmaPoolStats',['../vk__mem__alloc_8h.html#a4759a2d9f99c19ba7627553c847132f1',1,'vk_mem_alloc.h']]],
+  ['vmarecordflagbits_415',['VmaRecordFlagBits',['../vk__mem__alloc_8h.html#acd24d5eb58abff7e1f43cb32a1ba1413',1,'vk_mem_alloc.h']]],
+  ['vmarecordflags_416',['VmaRecordFlags',['../vk__mem__alloc_8h.html#af3929a1a4547c592fc0b0e55ef452828',1,'vk_mem_alloc.h']]],
+  ['vmarecordsettings_417',['VmaRecordSettings',['../vk__mem__alloc_8h.html#a16e21c877101493fce582664cd8754fc',1,'vk_mem_alloc.h']]],
+  ['vmastatinfo_418',['VmaStatInfo',['../vk__mem__alloc_8h.html#aec5b57e29c97b5d69c6d5654d60df878',1,'vk_mem_alloc.h']]],
+  ['vmastats_419',['VmaStats',['../vk__mem__alloc_8h.html#a21813b2efdf3836767a9058cd8a94034',1,'vk_mem_alloc.h']]],
+  ['vmavulkanfunctions_420',['VmaVulkanFunctions',['../vk__mem__alloc_8h.html#abb0a8e3b5040d847571cca6c7f9a8074',1,'vk_mem_alloc.h']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/variables_0.html b/third_party/VulkanMemoryAllocator/docs/html/search/variables_0.html
new file mode 100644
index 0000000..bf3eba5
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/variables_0.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="variables_0.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/variables_0.js b/third_party/VulkanMemoryAllocator/docs/html/search/variables_0.js
new file mode 100644
index 0000000..b202b0a
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/variables_0.js
@@ -0,0 +1,10 @@
+var searchData=
+[
+  ['allocation_308',['allocation',['../struct_vma_defragmentation_pass_move_info.html#ae885c861c2dd8d622e6c19e281d035cc',1,'VmaDefragmentationPassMoveInfo']]],
+  ['allocationbytes_309',['allocationBytes',['../struct_vma_budget.html#a7e2a6583ebd63e194951c542563804d8',1,'VmaBudget']]],
+  ['allocationcount_310',['allocationCount',['../struct_vma_stat_info.html#a537741e4d5cdddc1c0ab95ec650afaff',1,'VmaStatInfo::allocationCount()'],['../struct_vma_pool_stats.html#ad1924eb54fffa45e9e0e65670c8fe5eb',1,'VmaPoolStats::allocationCount()'],['../struct_vma_defragmentation_info2.html#a3cf86ab32c1da779b4923d301a3056ba',1,'VmaDefragmentationInfo2::allocationCount()']]],
+  ['allocationsizeavg_311',['allocationSizeAvg',['../struct_vma_stat_info.html#a1081a039964e566c672e7a2347f9e599',1,'VmaStatInfo']]],
+  ['allocationsizemax_312',['allocationSizeMax',['../struct_vma_stat_info.html#a17e9733a5ecd76287d4db6e66f71f50c',1,'VmaStatInfo']]],
+  ['allocationsizemin_313',['allocationSizeMin',['../struct_vma_stat_info.html#ade8b40bd3139c04aabd2fc538a356fea',1,'VmaStatInfo']]],
+  ['allocationsmoved_314',['allocationsMoved',['../struct_vma_defragmentation_stats.html#aefeabf130022008eadd75999478af3f9',1,'VmaDefragmentationStats']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/variables_1.html b/third_party/VulkanMemoryAllocator/docs/html/search/variables_1.html
new file mode 100644
index 0000000..49fe59a
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/variables_1.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="variables_1.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/variables_1.js b/third_party/VulkanMemoryAllocator/docs/html/search/variables_1.js
new file mode 100644
index 0000000..34e26f9
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/variables_1.js
@@ -0,0 +1,9 @@
+var searchData=
+[
+  ['blockbytes_315',['blockBytes',['../struct_vma_budget.html#a58b492901baab685f466199124e514a0',1,'VmaBudget']]],
+  ['blockcount_316',['blockCount',['../struct_vma_stat_info.html#abc4bb7cd611900778464c56e50c970a4',1,'VmaStatInfo::blockCount()'],['../struct_vma_pool_stats.html#aa0b5cb45cef6f18571cefb03b9a230e7',1,'VmaPoolStats::blockCount()']]],
+  ['blocksize_317',['blockSize',['../struct_vma_pool_create_info.html#aa4265160536cdb9be821b7686c16c676',1,'VmaPoolCreateInfo']]],
+  ['budget_318',['budget',['../struct_vma_budget.html#ab82e1d1754c2d210d0bdf90220bc6cdd',1,'VmaBudget']]],
+  ['bytesfreed_319',['bytesFreed',['../struct_vma_defragmentation_stats.html#ab0cb9ac0dbc106c77e384ea676422f28',1,'VmaDefragmentationStats']]],
+  ['bytesmoved_320',['bytesMoved',['../struct_vma_defragmentation_stats.html#a36f9d5df2a10ba2a36b16e126d60572d',1,'VmaDefragmentationStats']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/variables_2.html b/third_party/VulkanMemoryAllocator/docs/html/search/variables_2.html
new file mode 100644
index 0000000..0c8a18c
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/variables_2.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="variables_2.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/variables_2.js b/third_party/VulkanMemoryAllocator/docs/html/search/variables_2.js
new file mode 100644
index 0000000..f5e708e
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/variables_2.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['commandbuffer_321',['commandBuffer',['../struct_vma_defragmentation_info2.html#a7f71f39590c5316771493d2333f9c1bd',1,'VmaDefragmentationInfo2']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/variables_3.html b/third_party/VulkanMemoryAllocator/docs/html/search/variables_3.html
new file mode 100644
index 0000000..19a31fc
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/variables_3.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="variables_3.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/variables_3.js b/third_party/VulkanMemoryAllocator/docs/html/search/variables_3.js
new file mode 100644
index 0000000..7733ef6
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/variables_3.js
@@ -0,0 +1,6 @@
+var searchData=
+[
+  ['device_322',['device',['../struct_vma_allocator_create_info.html#ad924ddd77b04039c88d0c09b0ffcd500',1,'VmaAllocatorCreateInfo::device()'],['../struct_vma_allocator_info.html#a012b4c485bf3b0ea8921352c5ee0c357',1,'VmaAllocatorInfo::device()']]],
+  ['devicememory_323',['deviceMemory',['../struct_vma_allocation_info.html#ae0bfb7dfdf79a76ffefc9a94677a2f67',1,'VmaAllocationInfo']]],
+  ['devicememoryblocksfreed_324',['deviceMemoryBlocksFreed',['../struct_vma_defragmentation_stats.html#a0113f1877904a5d1ee8f409216ff276b',1,'VmaDefragmentationStats']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/variables_4.html b/third_party/VulkanMemoryAllocator/docs/html/search/variables_4.html
new file mode 100644
index 0000000..bdc37be
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/variables_4.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="variables_4.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/variables_4.js b/third_party/VulkanMemoryAllocator/docs/html/search/variables_4.js
new file mode 100644
index 0000000..1ed97e3
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/variables_4.js
@@ -0,0 +1,5 @@
+var searchData=
+[
+  ['flags_325',['flags',['../struct_vma_record_settings.html#ad8fdcc92119ae7a8c08c1a564c01d63a',1,'VmaRecordSettings::flags()'],['../struct_vma_allocator_create_info.html#a392ea2ecbaff93f91a7c49f735ad4346',1,'VmaAllocatorCreateInfo::flags()'],['../struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b',1,'VmaAllocationCreateInfo::flags()'],['../struct_vma_pool_create_info.html#a8405139f63d078340ae74513a59f5446',1,'VmaPoolCreateInfo::flags()'],['../struct_vma_defragmentation_info2.html#a53e844ee5633e229cf6daf14b2d9fff9',1,'VmaDefragmentationInfo2::flags()']]],
+  ['frameinusecount_326',['frameInUseCount',['../struct_vma_allocator_create_info.html#a21ea188dd212b8171cb9ecbed4a2a3a7',1,'VmaAllocatorCreateInfo::frameInUseCount()'],['../struct_vma_pool_create_info.html#a9437e43ffbb644dbbf7fc4e50cfad6aa',1,'VmaPoolCreateInfo::frameInUseCount()']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/variables_5.html b/third_party/VulkanMemoryAllocator/docs/html/search/variables_5.html
new file mode 100644
index 0000000..6aa2249
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/variables_5.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="variables_5.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/variables_5.js b/third_party/VulkanMemoryAllocator/docs/html/search/variables_5.js
new file mode 100644
index 0000000..cf75a0d
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/variables_5.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['instance_327',['instance',['../struct_vma_allocator_create_info.html#a70dd42e29b1df1d1b9b61532ae0b370b',1,'VmaAllocatorCreateInfo::instance()'],['../struct_vma_allocator_info.html#a2ed6a4d2d3fea039d66a13f15d0ce5fe',1,'VmaAllocatorInfo::instance()']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/variables_6.html b/third_party/VulkanMemoryAllocator/docs/html/search/variables_6.html
new file mode 100644
index 0000000..ce4a906
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/variables_6.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="variables_6.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/variables_6.js b/third_party/VulkanMemoryAllocator/docs/html/search/variables_6.js
new file mode 100644
index 0000000..26fc61c
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/variables_6.js
@@ -0,0 +1,17 @@
+var searchData=
+[
+  ['maxallocationstomove_328',['maxAllocationsToMove',['../struct_vma_defragmentation_info.html#aa7c7304e13c71f604c907196c4e28fbc',1,'VmaDefragmentationInfo']]],
+  ['maxblockcount_329',['maxBlockCount',['../struct_vma_pool_create_info.html#ae41142f2834fcdc82baa4883c187b75c',1,'VmaPoolCreateInfo']]],
+  ['maxbytestomove_330',['maxBytesToMove',['../struct_vma_defragmentation_info.html#acb311c940a777270e67e1b81c5ab6a1d',1,'VmaDefragmentationInfo']]],
+  ['maxcpuallocationstomove_331',['maxCpuAllocationsToMove',['../struct_vma_defragmentation_info2.html#a94c2c7223d52878445a8cccce396b671',1,'VmaDefragmentationInfo2']]],
+  ['maxcpubytestomove_332',['maxCpuBytesToMove',['../struct_vma_defragmentation_info2.html#af78e1ea40c22d85137b65f6b384a4d0a',1,'VmaDefragmentationInfo2']]],
+  ['maxgpuallocationstomove_333',['maxGpuAllocationsToMove',['../struct_vma_defragmentation_info2.html#a40d53d33e71ba0b66f844ed63c05a3f6',1,'VmaDefragmentationInfo2']]],
+  ['maxgpubytestomove_334',['maxGpuBytesToMove',['../struct_vma_defragmentation_info2.html#a4ddbc898d0afe1518f863a3763628f08',1,'VmaDefragmentationInfo2']]],
+  ['memory_335',['memory',['../struct_vma_defragmentation_pass_move_info.html#a06eb0c8690aa0d3478a036753492e769',1,'VmaDefragmentationPassMoveInfo']]],
+  ['memoryheap_336',['memoryHeap',['../struct_vma_stats.html#a0e6611508c29a187f0fd14ff1a0329c0',1,'VmaStats']]],
+  ['memorytype_337',['memoryType',['../struct_vma_stats.html#a13e3caf754be79352c42408756309331',1,'VmaStats::memoryType()'],['../struct_vma_allocation_info.html#a7f6b0aa58c135e488e6b40a388dad9d5',1,'VmaAllocationInfo::memoryType()']]],
+  ['memorytypebits_338',['memoryTypeBits',['../struct_vma_allocation_create_info.html#a3bf940c0271d85d6ba32a4d820075055',1,'VmaAllocationCreateInfo']]],
+  ['memorytypeindex_339',['memoryTypeIndex',['../struct_vma_pool_create_info.html#a596fa76b685d3f1f688f84a709a5b319',1,'VmaPoolCreateInfo']]],
+  ['minblockcount_340',['minBlockCount',['../struct_vma_pool_create_info.html#ad8006fb803185c0a699d30f3e9a865ae',1,'VmaPoolCreateInfo']]],
+  ['movecount_341',['moveCount',['../struct_vma_defragmentation_pass_info.html#ac1086e657ba995f8d1f4e49b83dcfb6c',1,'VmaDefragmentationPassInfo']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/variables_7.html b/third_party/VulkanMemoryAllocator/docs/html/search/variables_7.html
new file mode 100644
index 0000000..39ffd47
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/variables_7.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="variables_7.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/variables_7.js b/third_party/VulkanMemoryAllocator/docs/html/search/variables_7.js
new file mode 100644
index 0000000..2ae2b85
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/variables_7.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['offset_342',['offset',['../struct_vma_allocation_info.html#a4a3c732388dbdc7a23f9365b00825268',1,'VmaAllocationInfo::offset()'],['../struct_vma_defragmentation_pass_move_info.html#a8ab4508bc03625b0653c880576be96c6',1,'VmaDefragmentationPassMoveInfo::offset()']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/variables_8.html b/third_party/VulkanMemoryAllocator/docs/html/search/variables_8.html
new file mode 100644
index 0000000..37a2edd
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/variables_8.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="variables_8.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/variables_8.js b/third_party/VulkanMemoryAllocator/docs/html/search/variables_8.js
new file mode 100644
index 0000000..c9ff9e3
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/variables_8.js
@@ -0,0 +1,22 @@
+var searchData=
+[
+  ['pallocationcallbacks_343',['pAllocationCallbacks',['../struct_vma_allocator_create_info.html#a6e409087e3be55400d0e4ccbe43c608d',1,'VmaAllocatorCreateInfo']]],
+  ['pallocations_344',['pAllocations',['../struct_vma_defragmentation_info2.html#a8943f8d65969ce8e2189a1cdf3205e96',1,'VmaDefragmentationInfo2']]],
+  ['pallocationschanged_345',['pAllocationsChanged',['../struct_vma_defragmentation_info2.html#a76d51a644dc7f5405d0cdd0025ecd0cc',1,'VmaDefragmentationInfo2']]],
+  ['pdevicememorycallbacks_346',['pDeviceMemoryCallbacks',['../struct_vma_allocator_create_info.html#af1380969b5e1ea4c3184a877892d260e',1,'VmaAllocatorCreateInfo']]],
+  ['pfilepath_347',['pFilePath',['../struct_vma_record_settings.html#a6cb1fdbf6bcb610b68f2010dd629e89d',1,'VmaRecordSettings']]],
+  ['pfnallocate_348',['pfnAllocate',['../struct_vma_device_memory_callbacks.html#a4f17f7b255101e733b44d5633aceabfb',1,'VmaDeviceMemoryCallbacks']]],
+  ['pfnfree_349',['pfnFree',['../struct_vma_device_memory_callbacks.html#abe8a3328bbc916f6f712fdb6b299444c',1,'VmaDeviceMemoryCallbacks']]],
+  ['pheapsizelimit_350',['pHeapSizeLimit',['../struct_vma_allocator_create_info.html#a31c192aa6cbffa33279f6d9f0c47c44b',1,'VmaAllocatorCreateInfo']]],
+  ['physicaldevice_351',['physicalDevice',['../struct_vma_allocator_create_info.html#a08230f04ae6ccf8a78150a9e829a7156',1,'VmaAllocatorCreateInfo::physicalDevice()'],['../struct_vma_allocator_info.html#aba2b703f96e51d567717e1fb2935b47a',1,'VmaAllocatorInfo::physicalDevice()']]],
+  ['pmappeddata_352',['pMappedData',['../struct_vma_allocation_info.html#a5eeffbe2d2f30f53370ff14aefbadbe2',1,'VmaAllocationInfo']]],
+  ['pmoves_353',['pMoves',['../struct_vma_defragmentation_pass_info.html#acbd42d4a3357999da130a95cd99a3792',1,'VmaDefragmentationPassInfo']]],
+  ['pool_354',['pool',['../struct_vma_allocation_create_info.html#a6272c0555cfd1fe28bff1afeb6190150',1,'VmaAllocationCreateInfo']]],
+  ['poolcount_355',['poolCount',['../struct_vma_defragmentation_info2.html#a7e70aa2a1081d849dcc7829b19d3ec9d',1,'VmaDefragmentationInfo2']]],
+  ['ppools_356',['pPools',['../struct_vma_defragmentation_info2.html#a0b3effd57f3fcdeb2ed62210b4ef20e1',1,'VmaDefragmentationInfo2']]],
+  ['precordsettings_357',['pRecordSettings',['../struct_vma_allocator_create_info.html#ace2aa4877b16a42b0b7673d4e26000ee',1,'VmaAllocatorCreateInfo']]],
+  ['preferredflags_358',['preferredFlags',['../struct_vma_allocation_create_info.html#a7fe8d81a1ad10b2a2faacacee5b15d6d',1,'VmaAllocationCreateInfo']]],
+  ['preferredlargeheapblocksize_359',['preferredLargeHeapBlockSize',['../struct_vma_allocator_create_info.html#a8e4714298e3121cdd8b214a1ae7a637a',1,'VmaAllocatorCreateInfo']]],
+  ['puserdata_360',['pUserData',['../struct_vma_device_memory_callbacks.html#a24052de0937ddd54015a2df0363903c6',1,'VmaDeviceMemoryCallbacks::pUserData()'],['../struct_vma_allocation_create_info.html#a8259e85c272683434f4abb4ddddffe19',1,'VmaAllocationCreateInfo::pUserData()'],['../struct_vma_allocation_info.html#adc507656149c04de7ed95d0042ba2a13',1,'VmaAllocationInfo::pUserData()']]],
+  ['pvulkanfunctions_361',['pVulkanFunctions',['../struct_vma_allocator_create_info.html#a3dc197be3227da7338b1643f70db36bd',1,'VmaAllocatorCreateInfo']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/variables_9.html b/third_party/VulkanMemoryAllocator/docs/html/search/variables_9.html
new file mode 100644
index 0000000..21e5a4f
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/variables_9.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="variables_9.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/variables_9.js b/third_party/VulkanMemoryAllocator/docs/html/search/variables_9.js
new file mode 100644
index 0000000..e380bb5
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/variables_9.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['requiredflags_362',['requiredFlags',['../struct_vma_allocation_create_info.html#a9166390303ff42d783305bc31c2b6b90',1,'VmaAllocationCreateInfo']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/variables_a.html b/third_party/VulkanMemoryAllocator/docs/html/search/variables_a.html
new file mode 100644
index 0000000..1f65055
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/variables_a.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="variables_a.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/variables_a.js b/third_party/VulkanMemoryAllocator/docs/html/search/variables_a.js
new file mode 100644
index 0000000..224ea91
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/variables_a.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['size_363',['size',['../struct_vma_pool_stats.html#a326807b2de2b0931cee4ed9a5f2e420c',1,'VmaPoolStats::size()'],['../struct_vma_allocation_info.html#aac76d113a6a5ccbb09fea00fb25fd18f',1,'VmaAllocationInfo::size()']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/variables_b.html b/third_party/VulkanMemoryAllocator/docs/html/search/variables_b.html
new file mode 100644
index 0000000..c02d066
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/variables_b.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="variables_b.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/variables_b.js b/third_party/VulkanMemoryAllocator/docs/html/search/variables_b.js
new file mode 100644
index 0000000..449ff4e
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/variables_b.js
@@ -0,0 +1,4 @@
+var searchData=
+[
+  ['total_364',['total',['../struct_vma_stats.html#a2e8f5b3353f2fefef3c27f29e245a1f9',1,'VmaStats']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/variables_c.html b/third_party/VulkanMemoryAllocator/docs/html/search/variables_c.html
new file mode 100644
index 0000000..4b866c6
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/variables_c.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="variables_c.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/variables_c.js b/third_party/VulkanMemoryAllocator/docs/html/search/variables_c.js
new file mode 100644
index 0000000..5d102ba
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/variables_c.js
@@ -0,0 +1,11 @@
+var searchData=
+[
+  ['unusedbytes_365',['unusedBytes',['../struct_vma_stat_info.html#a1859d290aca2cd582d8dc25922092669',1,'VmaStatInfo']]],
+  ['unusedrangecount_366',['unusedRangeCount',['../struct_vma_stat_info.html#ae06129c771bfebfd6468a7f4276502a9',1,'VmaStatInfo::unusedRangeCount()'],['../struct_vma_pool_stats.html#ae4f3546ffa4d1e598b64d8e6134854f4',1,'VmaPoolStats::unusedRangeCount()']]],
+  ['unusedrangesizeavg_367',['unusedRangeSizeAvg',['../struct_vma_stat_info.html#a2f9b3452af90c9768a30b7fb6ae194fc',1,'VmaStatInfo']]],
+  ['unusedrangesizemax_368',['unusedRangeSizeMax',['../struct_vma_stat_info.html#a5ba1a2476c4d39b10f7e2f7ebbb72ac4',1,'VmaStatInfo::unusedRangeSizeMax()'],['../struct_vma_pool_stats.html#ab4c8f52dd42ab01998f60f0b6acc722b',1,'VmaPoolStats::unusedRangeSizeMax()']]],
+  ['unusedrangesizemin_369',['unusedRangeSizeMin',['../struct_vma_stat_info.html#aedeba931324f16589cd2416c0d2dd0d4',1,'VmaStatInfo']]],
+  ['unusedsize_370',['unusedSize',['../struct_vma_pool_stats.html#ad7c54874724fce7b06aba526202d82a8',1,'VmaPoolStats']]],
+  ['usage_371',['usage',['../struct_vma_budget.html#a84dd1ecca8b0110259eb206dbadb11f6',1,'VmaBudget::usage()'],['../struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910',1,'VmaAllocationCreateInfo::usage()']]],
+  ['usedbytes_372',['usedBytes',['../struct_vma_stat_info.html#ab0c6c73837e5a70c749fbd4f6064895a',1,'VmaStatInfo']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/variables_d.html b/third_party/VulkanMemoryAllocator/docs/html/search/variables_d.html
new file mode 100644
index 0000000..84d878b
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/variables_d.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title></title>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<link rel="stylesheet" type="text/css" href="search.css"/>
+<script type="text/javascript" src="variables_d.js"></script>
+<script type="text/javascript" src="search.js"></script>
+</head>
+<body class="SRPage">
+<div id="SRIndex">
+<div class="SRStatus" id="Loading">Loading...</div>
+<div id="SRResults"></div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+createResults();
+/* @license-end */
+--></script>
+<div class="SRStatus" id="Searching">Searching...</div>
+<div class="SRStatus" id="NoMatches">No Matches</div>
+<script type="text/javascript"><!--
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+document.getElementById("Loading").style.display="none";
+document.getElementById("NoMatches").style.display="none";
+var searchResults = new SearchResults("searchResults");
+searchResults.Search();
+/* @license-end */
+--></script>
+</div>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/search/variables_d.js b/third_party/VulkanMemoryAllocator/docs/html/search/variables_d.js
new file mode 100644
index 0000000..3ac2f37
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/search/variables_d.js
@@ -0,0 +1,21 @@
+var searchData=
+[
+  ['vkallocatememory_373',['vkAllocateMemory',['../struct_vma_vulkan_functions.html#a2943bf99dfd784a0e8f599d987e22e6c',1,'VmaVulkanFunctions']]],
+  ['vkbindbuffermemory_374',['vkBindBufferMemory',['../struct_vma_vulkan_functions.html#a94fc4f3a605d9880bb3c0ba2c2fc80b2',1,'VmaVulkanFunctions']]],
+  ['vkbindimagememory_375',['vkBindImageMemory',['../struct_vma_vulkan_functions.html#a1338d96a128a5ade648b8d934907c637',1,'VmaVulkanFunctions']]],
+  ['vkcmdcopybuffer_376',['vkCmdCopyBuffer',['../struct_vma_vulkan_functions.html#ae5c0db8c89a3b82593dc16aa6a49fa3a',1,'VmaVulkanFunctions']]],
+  ['vkcreatebuffer_377',['vkCreateBuffer',['../struct_vma_vulkan_functions.html#ae8084315a25006271a2edfc3a447519f',1,'VmaVulkanFunctions']]],
+  ['vkcreateimage_378',['vkCreateImage',['../struct_vma_vulkan_functions.html#a23ebe70be515b9b5010a1d691200e325',1,'VmaVulkanFunctions']]],
+  ['vkdestroybuffer_379',['vkDestroyBuffer',['../struct_vma_vulkan_functions.html#a7e054606faddb07f0e8556f3ed317d45',1,'VmaVulkanFunctions']]],
+  ['vkdestroyimage_380',['vkDestroyImage',['../struct_vma_vulkan_functions.html#a90b898227039b1dcb3520f6e91f09ffa',1,'VmaVulkanFunctions']]],
+  ['vkflushmappedmemoryranges_381',['vkFlushMappedMemoryRanges',['../struct_vma_vulkan_functions.html#a33c322f4c4ad2810f8a9c97a277572f9',1,'VmaVulkanFunctions']]],
+  ['vkfreememory_382',['vkFreeMemory',['../struct_vma_vulkan_functions.html#a4c658701778564d62034255b5dda91b4',1,'VmaVulkanFunctions']]],
+  ['vkgetbuffermemoryrequirements_383',['vkGetBufferMemoryRequirements',['../struct_vma_vulkan_functions.html#a5b92901df89a4194b0d12f6071d4d143',1,'VmaVulkanFunctions']]],
+  ['vkgetimagememoryrequirements_384',['vkGetImageMemoryRequirements',['../struct_vma_vulkan_functions.html#a475f6f49f8debe4d10800592606d53f4',1,'VmaVulkanFunctions']]],
+  ['vkgetphysicaldevicememoryproperties_385',['vkGetPhysicalDeviceMemoryProperties',['../struct_vma_vulkan_functions.html#a60d25c33bba06bb8592e6875cbaa9830',1,'VmaVulkanFunctions']]],
+  ['vkgetphysicaldeviceproperties_386',['vkGetPhysicalDeviceProperties',['../struct_vma_vulkan_functions.html#a77b7a74082823e865dd6546623468f96',1,'VmaVulkanFunctions']]],
+  ['vkinvalidatemappedmemoryranges_387',['vkInvalidateMappedMemoryRanges',['../struct_vma_vulkan_functions.html#a5c1093bc32386a8060c37c9f282078a1',1,'VmaVulkanFunctions']]],
+  ['vkmapmemory_388',['vkMapMemory',['../struct_vma_vulkan_functions.html#ab5c1f38dea3a2cf00dc9eb4f57218c49',1,'VmaVulkanFunctions']]],
+  ['vkunmapmemory_389',['vkUnmapMemory',['../struct_vma_vulkan_functions.html#acc798589736f0becb317fc2196c1d8b9',1,'VmaVulkanFunctions']]],
+  ['vulkanapiversion_390',['vulkanApiVersion',['../struct_vma_allocator_create_info.html#ae0ffc55139b54520a6bb704b29ffc285',1,'VmaAllocatorCreateInfo']]]
+];
diff --git a/third_party/VulkanMemoryAllocator/docs/html/splitbar.png b/third_party/VulkanMemoryAllocator/docs/html/splitbar.png
new file mode 100644
index 0000000..fe895f2
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/splitbar.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/docs/html/statistics.html b/third_party/VulkanMemoryAllocator/docs/html/statistics.html
new file mode 100644
index 0000000..4ca5b97
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/statistics.html
@@ -0,0 +1,92 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: Statistics</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+  <ul>
+<li class="navelem"><a class="el" href="index.html">Vulkan Memory Allocator</a></li>  </ul>
+</div>
+</div><!-- top -->
+<div class="PageDoc"><div class="header">
+  <div class="headertitle">
+<div class="title">Statistics </div>  </div>
+</div><!--header-->
+<div class="contents">
+<div class="textblock"><p>This library contains functions that return information about its internal state, especially the amount of memory allocated from Vulkan. Please keep in mind that these functions need to traverse all internal data structures to gather these information, so they may be quite time-consuming. Don't call them too often.</p>
+<h1><a class="anchor" id="statistics_numeric_statistics"></a>
+Numeric statistics</h1>
+<p>You can query for overall statistics of the allocator using function <a class="el" href="vk__mem__alloc_8h.html#a333b61c1788cb23559177531e6a93ca3" title="Retrieves statistics from current state of the Allocator.">vmaCalculateStats()</a>. Information are returned using structure <a class="el" href="struct_vma_stats.html" title="General statistics from current state of Allocator.">VmaStats</a>. It contains <a class="el" href="struct_vma_stat_info.html" title="Calculated statistics of memory usage in entire allocator.">VmaStatInfo</a> - number of allocated blocks, number of allocations (occupied ranges in these blocks), number of unused (free) ranges in these blocks, number of bytes used and unused (but still allocated from Vulkan) and other information. They are summed across memory heaps, memory types and total for whole allocator.</p>
+<p>You can query for statistics of a custom pool using function <a class="el" href="vk__mem__alloc_8h.html#ae8bf76997b234ef68aad922616df4153" title="Retrieves statistics of existing VmaPool object.">vmaGetPoolStats()</a>. Information are returned using structure <a class="el" href="struct_vma_pool_stats.html" title="Describes parameter of existing VmaPool.">VmaPoolStats</a>.</p>
+<p>You can query for information about specific allocation using function <a class="el" href="vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b" title="Returns current information about specified allocation and atomically marks it as used in current fra...">vmaGetAllocationInfo()</a>. It fill structure <a class="el" href="struct_vma_allocation_info.html" title="Parameters of VmaAllocation objects, that can be retrieved using function vmaGetAllocationInfo().">VmaAllocationInfo</a>.</p>
+<h1><a class="anchor" id="statistics_json_dump"></a>
+JSON dump</h1>
+<p>You can dump internal state of the allocator to a string in JSON format using function <a class="el" href="vk__mem__alloc_8h.html#aa4fee7eb5253377599ef4fd38c93c2a0" title="Builds and returns statistics as string in JSON format.">vmaBuildStatsString()</a>. The result is guaranteed to be correct JSON. It uses ANSI encoding. Any strings provided by user (see <a class="el" href="allocation_annotation.html#allocation_names">Allocation names</a>) are copied as-is and properly escaped for JSON, so if they use UTF-8, ISO-8859-2 or any other encoding, this JSON string can be treated as using this encoding. It must be freed using function <a class="el" href="vk__mem__alloc_8h.html#a3104eb30d8122c84dd8541063f145288">vmaFreeStatsString()</a>.</p>
+<p>The format of this JSON string is not part of official documentation of the library, but it will not change in backward-incompatible way without increasing library major version number and appropriate mention in changelog.</p>
+<p>The JSON string contains all the data that can be obtained using <a class="el" href="vk__mem__alloc_8h.html#a333b61c1788cb23559177531e6a93ca3" title="Retrieves statistics from current state of the Allocator.">vmaCalculateStats()</a>. It can also contain detailed map of allocated memory blocks and their regions - free and occupied by allocations. This allows e.g. to visualize the memory or assess fragmentation. </p>
+</div></div><!-- contents -->
+</div><!-- PageDoc -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/staying_within_budget.html b/third_party/VulkanMemoryAllocator/docs/html/staying_within_budget.html
new file mode 100644
index 0000000..f9cc2d0
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/staying_within_budget.html
@@ -0,0 +1,106 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: Staying within budget</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+  <ul>
+<li class="navelem"><a class="el" href="index.html">Vulkan Memory Allocator</a></li>  </ul>
+</div>
+</div><!-- top -->
+<div class="PageDoc"><div class="header">
+  <div class="headertitle">
+<div class="title">Staying within budget </div>  </div>
+</div><!--header-->
+<div class="contents">
+<div class="textblock"><p>When developing a graphics-intensive game or program, it is important to avoid allocating more GPU memory than it's physically available. When the memory is over-committed, various bad things can happen, depending on the specific GPU, graphics driver, and operating system:</p>
+<ul>
+<li>It may just work without any problems.</li>
+<li>The application may slow down because some memory blocks are moved to system RAM and the GPU has to access them through PCI Express bus.</li>
+<li>A new allocation may take very long time to complete, even few seconds, and possibly freeze entire system.</li>
+<li>The new allocation may fail with <code>VK_ERROR_OUT_OF_DEVICE_MEMORY</code>.</li>
+<li>It may even result in GPU crash (TDR), observed as <code>VK_ERROR_DEVICE_LOST</code> returned somewhere later.</li>
+</ul>
+<h1><a class="anchor" id="staying_within_budget_querying_for_budget"></a>
+Querying for budget</h1>
+<p>To query for current memory usage and available budget, use function <a class="el" href="vk__mem__alloc_8h.html#aec0ed24ebea2d0099eed5f801daaefba" title="Retrieves information about current memory budget for all memory heaps.">vmaGetBudget()</a>. Returned structure <a class="el" href="struct_vma_budget.html" title="Statistics of current memory usage and available budget, in bytes, for specific memory heap.">VmaBudget</a> contains quantities expressed in bytes, per Vulkan memory heap.</p>
+<p>Please note that this function returns different information and works faster than <a class="el" href="vk__mem__alloc_8h.html#a333b61c1788cb23559177531e6a93ca3" title="Retrieves statistics from current state of the Allocator.">vmaCalculateStats()</a>. <a class="el" href="vk__mem__alloc_8h.html#aec0ed24ebea2d0099eed5f801daaefba" title="Retrieves information about current memory budget for all memory heaps.">vmaGetBudget()</a> can be called every frame or even before every allocation, while <a class="el" href="vk__mem__alloc_8h.html#a333b61c1788cb23559177531e6a93ca3" title="Retrieves statistics from current state of the Allocator.">vmaCalculateStats()</a> is intended to be used rarely, only to obtain statistical information, e.g. for debugging purposes.</p>
+<p>It is recommended to use <b>VK_EXT_memory_budget</b> device extension to obtain information about the budget from Vulkan device. VMA is able to use this extension automatically. When not enabled, the allocator behaves same way, but then it estimates current usage and available budget based on its internal information and Vulkan memory heap sizes, which may be less precise. In order to use this extension:</p>
+<ol type="1">
+<li>Make sure extensions VK_EXT_memory_budget and VK_KHR_get_physical_device_properties2 required by it are available and enable them. Please note that the first is a device extension and the second is instance extension!</li>
+<li>Use flag <a class="el" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca4d4687863f7bd4b418c6006dc04400b0">VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT</a> when creating <a class="el" href="struct_vma_allocator.html" title="Represents main object of this library initialized.">VmaAllocator</a> object.</li>
+<li>Make sure to call <a class="el" href="vk__mem__alloc_8h.html#ade56bf8dc9f5a5eaddf5f119ed525236" title="Sets index of the current frame.">vmaSetCurrentFrameIndex()</a> every frame. Budget is queried from Vulkan inside of it to avoid overhead of querying it with every allocation.</li>
+</ol>
+<h1><a class="anchor" id="staying_within_budget_controlling_memory_usage"></a>
+Controlling memory usage</h1>
+<p>There are many ways in which you can try to stay within the budget.</p>
+<p>First, when making new allocation requires allocating a new memory block, the library tries not to exceed the budget automatically. If a block with default recommended size (e.g. 256 MB) would go over budget, a smaller block is allocated, possibly even dedicated memory for just this resource.</p>
+<p>If the size of the requested resource plus current memory usage is more than the budget, by default the library still tries to create it, leaving it to the Vulkan implementation whether the allocation succeeds or fails. You can change this behavior by using <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597ab8b1764f3e9022368e440c057783b92d">VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT</a> flag. With it, the allocation is not made if it would exceed the budget or if the budget is already exceeded. Some other allocations become lost instead to make room for it, if the mechanism of <a class="el" href="lost_allocations.html">lost allocations</a> is used. If that is not possible, the allocation fails with <code>VK_ERROR_OUT_OF_DEVICE_MEMORY</code>. Example usage pattern may be to pass the <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597ab8b1764f3e9022368e440c057783b92d">VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT</a> flag when creating resources that are not essential for the application (e.g. the texture of a specific object) and not to pass it when creating critically important resources (e.g. render targets).</p>
+<p>Finally, you can also use <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a89759603401014eb325eb22a3839f2ff" title="Set this flag to only try to allocate from existing VkDeviceMemory blocks and never create new such b...">VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT</a> flag to make sure a new allocation is created only when it fits inside one of the existing memory blocks. If it would require to allocate a new block, if fails instead with <code>VK_ERROR_OUT_OF_DEVICE_MEMORY</code>. This also ensures that the function call is very fast because it never goes to Vulkan to obtain a new block.</p>
+<p>Please note that creating <a class="el" href="custom_memory_pools.html">Custom memory pools</a> with <a class="el" href="struct_vma_pool_create_info.html#ad8006fb803185c0a699d30f3e9a865ae" title="Minimum number of blocks to be always allocated in this pool, even if they stay empty.">VmaPoolCreateInfo::minBlockCount</a> set to more than 0 will try to allocate memory blocks without checking whether they fit within budget. </p>
+</div></div><!-- contents -->
+</div><!-- PageDoc -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/struct__-members.html b/third_party/VulkanMemoryAllocator/docs/html/struct__-members.html
new file mode 100644
index 0000000..afd2f73
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/struct__-members.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.16"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: Member List</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.16 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="headertitle">
+<div class="title">_ Member List</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>This is the complete list of members for <a class="el" href="struct__.html">_</a>, including all inherited members.</p>
+<table class="directory">
+  <tr class="even"><td class="entry"><a class="el" href="struct__.html#af6d5d67c61d2394656ca210d0d2b9b40">flags</a></td><td class="entry"><a class="el" href="struct__.html">_</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct__.html#a531171590e30aa2ba2b8a50ee976b9d2">memoryTypeBits</a></td><td class="entry"><a class="el" href="struct__.html">_</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct__.html#ac913e1c322e4782ac6114632a2dfb1e3">pool</a></td><td class="entry"><a class="el" href="struct__.html">_</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct__.html#aeda060f3275a7d0308c4c688a37883cd">preferredFlags</a></td><td class="entry"><a class="el" href="struct__.html">_</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct__.html#a146a1894242756b1be7ac16901ba2bc0">pUserData</a></td><td class="entry"><a class="el" href="struct__.html">_</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct__.html#a9985e0a1c36944cd1eeb38c9acccdd68">requiredFlags</a></td><td class="entry"><a class="el" href="struct__.html">_</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct__.html#a11b2bf964ead1c04f043b9eca68d8807">usage</a></td><td class="entry"><a class="el" href="struct__.html">_</a></td><td class="entry"></td></tr>
+</table></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.16
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/struct__.html b/third_party/VulkanMemoryAllocator/docs/html/struct__.html
new file mode 100644
index 0000000..0823c40
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/struct__.html
@@ -0,0 +1,232 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.16"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: _ Struct Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.16 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="summary">
+<a href="#pub-attribs">Public Attributes</a> &#124;
+<a href="struct__-members.html">List of all members</a>  </div>
+  <div class="headertitle">
+<div class="title">_ Struct Reference</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p><code>#include &lt;<a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a>&gt;</code></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="pub-attribs"></a>
+Public Attributes</h2></td></tr>
+<tr class="memitem:af6d5d67c61d2394656ca210d0d2b9b40"><td class="memItemLeft" align="right" valign="top"><a class="el" href="vk__mem__alloc_8h.html#a5225e5e11f8376f6a31a1791f3d6e817">VmaAllocationCreateFlags</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct__.html#af6d5d67c61d2394656ca210d0d2b9b40">flags</a></td></tr>
+<tr class="memdesc:af6d5d67c61d2394656ca210d0d2b9b40"><td class="mdescLeft">&#160;</td><td class="mdescRight">Use <a class="el" href="vk__mem__alloc_8h.html#abf6bf6748c7a9fe7ce5b7835c0f56af4" title="Flags to be passed as VmaAllocationCreateInfo::flags.">VmaAllocationCreateFlagBits</a> enum.  <a href="struct__.html#af6d5d67c61d2394656ca210d0d2b9b40">More...</a><br /></td></tr>
+<tr class="separator:af6d5d67c61d2394656ca210d0d2b9b40"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a11b2bf964ead1c04f043b9eca68d8807"><td class="memItemLeft" align="right" valign="top"><a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cc">VmaMemoryUsage</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct__.html#a11b2bf964ead1c04f043b9eca68d8807">usage</a></td></tr>
+<tr class="memdesc:a11b2bf964ead1c04f043b9eca68d8807"><td class="mdescLeft">&#160;</td><td class="mdescRight">Intended usage of memory.  <a href="struct__.html#a11b2bf964ead1c04f043b9eca68d8807">More...</a><br /></td></tr>
+<tr class="separator:a11b2bf964ead1c04f043b9eca68d8807"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a9985e0a1c36944cd1eeb38c9acccdd68"><td class="memItemLeft" align="right" valign="top">VkMemoryPropertyFlags&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct__.html#a9985e0a1c36944cd1eeb38c9acccdd68">requiredFlags</a></td></tr>
+<tr class="memdesc:a9985e0a1c36944cd1eeb38c9acccdd68"><td class="mdescLeft">&#160;</td><td class="mdescRight">Flags that must be set in a Memory Type chosen for an allocation.  <a href="struct__.html#a9985e0a1c36944cd1eeb38c9acccdd68">More...</a><br /></td></tr>
+<tr class="separator:a9985e0a1c36944cd1eeb38c9acccdd68"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:aeda060f3275a7d0308c4c688a37883cd"><td class="memItemLeft" align="right" valign="top">VkMemoryPropertyFlags&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct__.html#aeda060f3275a7d0308c4c688a37883cd">preferredFlags</a></td></tr>
+<tr class="memdesc:aeda060f3275a7d0308c4c688a37883cd"><td class="mdescLeft">&#160;</td><td class="mdescRight">Flags that preferably should be set in a memory type chosen for an allocation.  <a href="struct__.html#aeda060f3275a7d0308c4c688a37883cd">More...</a><br /></td></tr>
+<tr class="separator:aeda060f3275a7d0308c4c688a37883cd"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a531171590e30aa2ba2b8a50ee976b9d2"><td class="memItemLeft" align="right" valign="top">uint32_t&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct__.html#a531171590e30aa2ba2b8a50ee976b9d2">memoryTypeBits</a></td></tr>
+<tr class="memdesc:a531171590e30aa2ba2b8a50ee976b9d2"><td class="mdescLeft">&#160;</td><td class="mdescRight">Bitmask containing one bit set for every memory type acceptable for this allocation.  <a href="struct__.html#a531171590e30aa2ba2b8a50ee976b9d2">More...</a><br /></td></tr>
+<tr class="separator:a531171590e30aa2ba2b8a50ee976b9d2"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ac913e1c322e4782ac6114632a2dfb1e3"><td class="memItemLeft" align="right" valign="top"><a class="el" href="struct_vma_pool.html">VmaPool</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct__.html#ac913e1c322e4782ac6114632a2dfb1e3">pool</a></td></tr>
+<tr class="memdesc:ac913e1c322e4782ac6114632a2dfb1e3"><td class="mdescLeft">&#160;</td><td class="mdescRight">Pool that this allocation should be created in.  <a href="struct__.html#ac913e1c322e4782ac6114632a2dfb1e3">More...</a><br /></td></tr>
+<tr class="separator:ac913e1c322e4782ac6114632a2dfb1e3"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a146a1894242756b1be7ac16901ba2bc0"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct__.html#a146a1894242756b1be7ac16901ba2bc0">pUserData</a></td></tr>
+<tr class="memdesc:a146a1894242756b1be7ac16901ba2bc0"><td class="mdescLeft">&#160;</td><td class="mdescRight">Custom general-purpose pointer that will be stored in <a class="el" href="struct_vma_allocation.html" title="Represents single memory allocation.">VmaAllocation</a>, can be read as <a class="el" href="struct_vma_allocation_info.html#adc507656149c04de7ed95d0042ba2a13" title="Custom general-purpose pointer that was passed as VmaAllocationCreateInfo::pUserData or set using vma...">VmaAllocationInfo::pUserData</a> and changed using <a class="el" href="vk__mem__alloc_8h.html#af9147d31ffc11d62fc187bde283ed14f" title="Sets pUserData in given allocation to new value.">vmaSetAllocationUserData()</a>.  <a href="struct__.html#a146a1894242756b1be7ac16901ba2bc0">More...</a><br /></td></tr>
+<tr class="separator:a146a1894242756b1be7ac16901ba2bc0"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<h2 class="groupheader">Member Data Documentation</h2>
+<a id="af6d5d67c61d2394656ca210d0d2b9b40"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#af6d5d67c61d2394656ca210d0d2b9b40">&#9670;&nbsp;</a></span>flags</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname"><a class="el" href="vk__mem__alloc_8h.html#a5225e5e11f8376f6a31a1791f3d6e817">VmaAllocationCreateFlags</a> _::flags</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Use <a class="el" href="vk__mem__alloc_8h.html#abf6bf6748c7a9fe7ce5b7835c0f56af4" title="Flags to be passed as VmaAllocationCreateInfo::flags.">VmaAllocationCreateFlagBits</a> enum. </p>
+
+</div>
+</div>
+<a id="a531171590e30aa2ba2b8a50ee976b9d2"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a531171590e30aa2ba2b8a50ee976b9d2">&#9670;&nbsp;</a></span>memoryTypeBits</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">uint32_t _::memoryTypeBits</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Bitmask containing one bit set for every memory type acceptable for this allocation. </p>
+<p>Value 0 is equivalent to <code>UINT32_MAX</code> - it means any memory type is accepted if it meets other requirements specified by this structure, with no further restrictions on memory type index. <br  />
+If <code>pool</code> is not null, this member is ignored. </p>
+
+</div>
+</div>
+<a id="ac913e1c322e4782ac6114632a2dfb1e3"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ac913e1c322e4782ac6114632a2dfb1e3">&#9670;&nbsp;</a></span>pool</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname"><a class="el" href="struct_vma_pool.html">VmaPool</a> _::pool</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Pool that this allocation should be created in. </p>
+<p>Leave <code>VK_NULL_HANDLE</code> to allocate from default pool. If not null, members: <code>usage</code>, <code>requiredFlags</code>, <code>preferredFlags</code>, <code>memoryTypeBits</code> are ignored. </p>
+
+</div>
+</div>
+<a id="aeda060f3275a7d0308c4c688a37883cd"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#aeda060f3275a7d0308c4c688a37883cd">&#9670;&nbsp;</a></span>preferredFlags</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkMemoryPropertyFlags _::preferredFlags</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Flags that preferably should be set in a memory type chosen for an allocation. </p>
+<p>Set to 0 if no additional flags are prefered. <br  />
+If <code>pool</code> is not null, this member is ignored. </p>
+
+</div>
+</div>
+<a id="a146a1894242756b1be7ac16901ba2bc0"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a146a1894242756b1be7ac16901ba2bc0">&#9670;&nbsp;</a></span>pUserData</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* _::pUserData</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Custom general-purpose pointer that will be stored in <a class="el" href="struct_vma_allocation.html" title="Represents single memory allocation.">VmaAllocation</a>, can be read as <a class="el" href="struct_vma_allocation_info.html#adc507656149c04de7ed95d0042ba2a13" title="Custom general-purpose pointer that was passed as VmaAllocationCreateInfo::pUserData or set using vma...">VmaAllocationInfo::pUserData</a> and changed using <a class="el" href="vk__mem__alloc_8h.html#af9147d31ffc11d62fc187bde283ed14f" title="Sets pUserData in given allocation to new value.">vmaSetAllocationUserData()</a>. </p>
+<p>If <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597aa6f24f821cd6a7c5e4a443f7bf59c520">VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT</a> is used, it must be either null or pointer to a null-terminated string. The string will be then copied to internal buffer, so it doesn't need to be valid after allocation call. </p>
+
+</div>
+</div>
+<a id="a9985e0a1c36944cd1eeb38c9acccdd68"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a9985e0a1c36944cd1eeb38c9acccdd68">&#9670;&nbsp;</a></span>requiredFlags</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkMemoryPropertyFlags _::requiredFlags</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Flags that must be set in a Memory Type chosen for an allocation. </p>
+<p>Leave 0 if you specify memory requirements in other way. <br  />
+If <code>pool</code> is not null, this member is ignored. </p>
+
+</div>
+</div>
+<a id="a11b2bf964ead1c04f043b9eca68d8807"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a11b2bf964ead1c04f043b9eca68d8807">&#9670;&nbsp;</a></span>usage</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname"><a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cc">VmaMemoryUsage</a> _::usage</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Intended usage of memory. </p>
+<p>You can leave <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccaf50d27e34e0925cf3a63db8c839121dd">VMA_MEMORY_USAGE_UNKNOWN</a> if you specify memory requirements in other way. <br  />
+If <code>pool</code> is not null, this member is ignored. </p>
+
+</div>
+</div>
+<hr/>The documentation for this struct was generated from the following file:<ul>
+<li><a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a></li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.16
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/struct_vma_allocation.html b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_allocation.html
new file mode 100644
index 0000000..9679500
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_allocation.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: VmaAllocation Struct Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="headertitle">
+<div class="title">VmaAllocation Struct Reference</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>Represents single memory allocation.  
+ <a href="struct_vma_allocation.html#details">More...</a></p>
+
+<p><code>#include &lt;<a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a>&gt;</code></p>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<div class="textblock"><p>Represents single memory allocation. </p>
+<p>It may be either dedicated block of <code>VkDeviceMemory</code> or a specific region of a bigger block of this type plus unique offset.</p>
+<p>There are multiple ways to create such object. You need to fill structure <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>. For more information see <a class="el" href="choosing_memory_type.html">Choosing memory type</a>.</p>
+<p>Although the library provides convenience functions that create Vulkan buffer or image, allocate memory for it and bind them together, binding of the allocation to a buffer or an image is out of scope of the allocation itself. Allocation object can exist without buffer/image bound, binding can be done manually by the user, and destruction of it can be done independently of destruction of the allocation.</p>
+<p>The object also remembers its size and some other information. To retrieve this information, use function <a class="el" href="vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b" title="Returns current information about specified allocation and atomically marks it as used in current fra...">vmaGetAllocationInfo()</a> and inspect returned structure <a class="el" href="struct_vma_allocation_info.html" title="Parameters of VmaAllocation objects, that can be retrieved using function vmaGetAllocationInfo().">VmaAllocationInfo</a>.</p>
+<p>Some kinds allocations can be in lost state. For more information, see <a class="el" href="lost_allocations.html">Lost allocations</a>. </p>
+</div><hr/>The documentation for this struct was generated from the following file:<ul>
+<li><a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a></li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/struct_vma_allocation_create_info-members.html b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_allocation_create_info-members.html
new file mode 100644
index 0000000..87330a4
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_allocation_create_info-members.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: Member List</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="headertitle">
+<div class="title">VmaAllocationCreateInfo Member List</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>This is the complete list of members for <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>, including all inherited members.</p>
+<table class="directory">
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a></td><td class="entry"><a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_allocation_create_info.html#a3bf940c0271d85d6ba32a4d820075055">memoryTypeBits</a></td><td class="entry"><a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_allocation_create_info.html#a6272c0555cfd1fe28bff1afeb6190150">pool</a></td><td class="entry"><a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_allocation_create_info.html#a7fe8d81a1ad10b2a2faacacee5b15d6d">preferredFlags</a></td><td class="entry"><a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_allocation_create_info.html#a8259e85c272683434f4abb4ddddffe19">pUserData</a></td><td class="entry"><a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_allocation_create_info.html#a9166390303ff42d783305bc31c2b6b90">requiredFlags</a></td><td class="entry"><a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910">usage</a></td><td class="entry"><a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a></td><td class="entry"></td></tr>
+</table></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/struct_vma_allocation_create_info.html b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_allocation_create_info.html
new file mode 100644
index 0000000..0314a43
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_allocation_create_info.html
@@ -0,0 +1,232 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: VmaAllocationCreateInfo Struct Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="summary">
+<a href="#pub-attribs">Public Attributes</a> &#124;
+<a href="struct_vma_allocation_create_info-members.html">List of all members</a>  </div>
+  <div class="headertitle">
+<div class="title">VmaAllocationCreateInfo Struct Reference</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p><code>#include &lt;<a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a>&gt;</code></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="pub-attribs"></a>
+Public Attributes</h2></td></tr>
+<tr class="memitem:add09658ac14fe290ace25470ddd6d41b"><td class="memItemLeft" align="right" valign="top"><a class="el" href="vk__mem__alloc_8h.html#a5225e5e11f8376f6a31a1791f3d6e817">VmaAllocationCreateFlags</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a></td></tr>
+<tr class="memdesc:add09658ac14fe290ace25470ddd6d41b"><td class="mdescLeft">&#160;</td><td class="mdescRight">Use <a class="el" href="vk__mem__alloc_8h.html#a4fceecc301f4064dc808d3cd6c038941" title="Flags to be passed as VmaAllocationCreateInfo::flags.">VmaAllocationCreateFlagBits</a> enum.  <a href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">More...</a><br /></td></tr>
+<tr class="separator:add09658ac14fe290ace25470ddd6d41b"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:accb8b06b1f677d858cb9af20705fa910"><td class="memItemLeft" align="right" valign="top"><a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cc">VmaMemoryUsage</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910">usage</a></td></tr>
+<tr class="memdesc:accb8b06b1f677d858cb9af20705fa910"><td class="mdescLeft">&#160;</td><td class="mdescRight">Intended usage of memory.  <a href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910">More...</a><br /></td></tr>
+<tr class="separator:accb8b06b1f677d858cb9af20705fa910"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a9166390303ff42d783305bc31c2b6b90"><td class="memItemLeft" align="right" valign="top">VkMemoryPropertyFlags&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_allocation_create_info.html#a9166390303ff42d783305bc31c2b6b90">requiredFlags</a></td></tr>
+<tr class="memdesc:a9166390303ff42d783305bc31c2b6b90"><td class="mdescLeft">&#160;</td><td class="mdescRight">Flags that must be set in a Memory Type chosen for an allocation.  <a href="struct_vma_allocation_create_info.html#a9166390303ff42d783305bc31c2b6b90">More...</a><br /></td></tr>
+<tr class="separator:a9166390303ff42d783305bc31c2b6b90"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a7fe8d81a1ad10b2a2faacacee5b15d6d"><td class="memItemLeft" align="right" valign="top">VkMemoryPropertyFlags&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_allocation_create_info.html#a7fe8d81a1ad10b2a2faacacee5b15d6d">preferredFlags</a></td></tr>
+<tr class="memdesc:a7fe8d81a1ad10b2a2faacacee5b15d6d"><td class="mdescLeft">&#160;</td><td class="mdescRight">Flags that preferably should be set in a memory type chosen for an allocation.  <a href="struct_vma_allocation_create_info.html#a7fe8d81a1ad10b2a2faacacee5b15d6d">More...</a><br /></td></tr>
+<tr class="separator:a7fe8d81a1ad10b2a2faacacee5b15d6d"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a3bf940c0271d85d6ba32a4d820075055"><td class="memItemLeft" align="right" valign="top">uint32_t&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_allocation_create_info.html#a3bf940c0271d85d6ba32a4d820075055">memoryTypeBits</a></td></tr>
+<tr class="memdesc:a3bf940c0271d85d6ba32a4d820075055"><td class="mdescLeft">&#160;</td><td class="mdescRight">Bitmask containing one bit set for every memory type acceptable for this allocation.  <a href="struct_vma_allocation_create_info.html#a3bf940c0271d85d6ba32a4d820075055">More...</a><br /></td></tr>
+<tr class="separator:a3bf940c0271d85d6ba32a4d820075055"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a6272c0555cfd1fe28bff1afeb6190150"><td class="memItemLeft" align="right" valign="top"><a class="el" href="struct_vma_pool.html">VmaPool</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_allocation_create_info.html#a6272c0555cfd1fe28bff1afeb6190150">pool</a></td></tr>
+<tr class="memdesc:a6272c0555cfd1fe28bff1afeb6190150"><td class="mdescLeft">&#160;</td><td class="mdescRight">Pool that this allocation should be created in.  <a href="struct_vma_allocation_create_info.html#a6272c0555cfd1fe28bff1afeb6190150">More...</a><br /></td></tr>
+<tr class="separator:a6272c0555cfd1fe28bff1afeb6190150"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a8259e85c272683434f4abb4ddddffe19"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_allocation_create_info.html#a8259e85c272683434f4abb4ddddffe19">pUserData</a></td></tr>
+<tr class="memdesc:a8259e85c272683434f4abb4ddddffe19"><td class="mdescLeft">&#160;</td><td class="mdescRight">Custom general-purpose pointer that will be stored in <a class="el" href="struct_vma_allocation.html" title="Represents single memory allocation.">VmaAllocation</a>, can be read as <a class="el" href="struct_vma_allocation_info.html#adc507656149c04de7ed95d0042ba2a13" title="Custom general-purpose pointer that was passed as VmaAllocationCreateInfo::pUserData or set using vma...">VmaAllocationInfo::pUserData</a> and changed using <a class="el" href="vk__mem__alloc_8h.html#af9147d31ffc11d62fc187bde283ed14f" title="Sets pUserData in given allocation to new value.">vmaSetAllocationUserData()</a>.  <a href="struct_vma_allocation_create_info.html#a8259e85c272683434f4abb4ddddffe19">More...</a><br /></td></tr>
+<tr class="separator:a8259e85c272683434f4abb4ddddffe19"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<h2 class="groupheader">Member Data Documentation</h2>
+<a id="add09658ac14fe290ace25470ddd6d41b"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#add09658ac14fe290ace25470ddd6d41b">&#9670;&nbsp;</a></span>flags</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname"><a class="el" href="vk__mem__alloc_8h.html#a5225e5e11f8376f6a31a1791f3d6e817">VmaAllocationCreateFlags</a> VmaAllocationCreateInfo::flags</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Use <a class="el" href="vk__mem__alloc_8h.html#a4fceecc301f4064dc808d3cd6c038941" title="Flags to be passed as VmaAllocationCreateInfo::flags.">VmaAllocationCreateFlagBits</a> enum. </p>
+
+</div>
+</div>
+<a id="a3bf940c0271d85d6ba32a4d820075055"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a3bf940c0271d85d6ba32a4d820075055">&#9670;&nbsp;</a></span>memoryTypeBits</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">uint32_t VmaAllocationCreateInfo::memoryTypeBits</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Bitmask containing one bit set for every memory type acceptable for this allocation. </p>
+<p>Value 0 is equivalent to <code>UINT32_MAX</code> - it means any memory type is accepted if it meets other requirements specified by this structure, with no further restrictions on memory type index. <br  />
+If <code>pool</code> is not null, this member is ignored. </p>
+
+</div>
+</div>
+<a id="a6272c0555cfd1fe28bff1afeb6190150"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a6272c0555cfd1fe28bff1afeb6190150">&#9670;&nbsp;</a></span>pool</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname"><a class="el" href="struct_vma_pool.html">VmaPool</a> VmaAllocationCreateInfo::pool</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Pool that this allocation should be created in. </p>
+<p>Leave <code>VK_NULL_HANDLE</code> to allocate from default pool. If not null, members: <code>usage</code>, <code>requiredFlags</code>, <code>preferredFlags</code>, <code>memoryTypeBits</code> are ignored. </p>
+
+</div>
+</div>
+<a id="a7fe8d81a1ad10b2a2faacacee5b15d6d"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a7fe8d81a1ad10b2a2faacacee5b15d6d">&#9670;&nbsp;</a></span>preferredFlags</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkMemoryPropertyFlags VmaAllocationCreateInfo::preferredFlags</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Flags that preferably should be set in a memory type chosen for an allocation. </p>
+<p>Set to 0 if no additional flags are prefered. <br  />
+If <code>pool</code> is not null, this member is ignored. </p>
+
+</div>
+</div>
+<a id="a8259e85c272683434f4abb4ddddffe19"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a8259e85c272683434f4abb4ddddffe19">&#9670;&nbsp;</a></span>pUserData</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* VmaAllocationCreateInfo::pUserData</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Custom general-purpose pointer that will be stored in <a class="el" href="struct_vma_allocation.html" title="Represents single memory allocation.">VmaAllocation</a>, can be read as <a class="el" href="struct_vma_allocation_info.html#adc507656149c04de7ed95d0042ba2a13" title="Custom general-purpose pointer that was passed as VmaAllocationCreateInfo::pUserData or set using vma...">VmaAllocationInfo::pUserData</a> and changed using <a class="el" href="vk__mem__alloc_8h.html#af9147d31ffc11d62fc187bde283ed14f" title="Sets pUserData in given allocation to new value.">vmaSetAllocationUserData()</a>. </p>
+<p>If <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597aa6f24f821cd6a7c5e4a443f7bf59c520">VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT</a> is used, it must be either null or pointer to a null-terminated string. The string will be then copied to internal buffer, so it doesn't need to be valid after allocation call. </p>
+
+</div>
+</div>
+<a id="a9166390303ff42d783305bc31c2b6b90"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a9166390303ff42d783305bc31c2b6b90">&#9670;&nbsp;</a></span>requiredFlags</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkMemoryPropertyFlags VmaAllocationCreateInfo::requiredFlags</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Flags that must be set in a Memory Type chosen for an allocation. </p>
+<p>Leave 0 if you specify memory requirements in other way. <br  />
+If <code>pool</code> is not null, this member is ignored. </p>
+
+</div>
+</div>
+<a id="accb8b06b1f677d858cb9af20705fa910"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#accb8b06b1f677d858cb9af20705fa910">&#9670;&nbsp;</a></span>usage</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname"><a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cc">VmaMemoryUsage</a> VmaAllocationCreateInfo::usage</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Intended usage of memory. </p>
+<p>You can leave <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccaf50d27e34e0925cf3a63db8c839121dd">VMA_MEMORY_USAGE_UNKNOWN</a> if you specify memory requirements in other way. <br  />
+If <code>pool</code> is not null, this member is ignored. </p>
+
+</div>
+</div>
+<hr/>The documentation for this struct was generated from the following file:<ul>
+<li><a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a></li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/struct_vma_allocation_info-members.html b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_allocation_info-members.html
new file mode 100644
index 0000000..8e73cbf
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_allocation_info-members.html
@@ -0,0 +1,85 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: Member List</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="headertitle">
+<div class="title">VmaAllocationInfo Member List</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>This is the complete list of members for <a class="el" href="struct_vma_allocation_info.html">VmaAllocationInfo</a>, including all inherited members.</p>
+<table class="directory">
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_allocation_info.html#ae0bfb7dfdf79a76ffefc9a94677a2f67">deviceMemory</a></td><td class="entry"><a class="el" href="struct_vma_allocation_info.html">VmaAllocationInfo</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_allocation_info.html#a7f6b0aa58c135e488e6b40a388dad9d5">memoryType</a></td><td class="entry"><a class="el" href="struct_vma_allocation_info.html">VmaAllocationInfo</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_allocation_info.html#a4a3c732388dbdc7a23f9365b00825268">offset</a></td><td class="entry"><a class="el" href="struct_vma_allocation_info.html">VmaAllocationInfo</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_allocation_info.html#a5eeffbe2d2f30f53370ff14aefbadbe2">pMappedData</a></td><td class="entry"><a class="el" href="struct_vma_allocation_info.html">VmaAllocationInfo</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_allocation_info.html#adc507656149c04de7ed95d0042ba2a13">pUserData</a></td><td class="entry"><a class="el" href="struct_vma_allocation_info.html">VmaAllocationInfo</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_allocation_info.html#aac76d113a6a5ccbb09fea00fb25fd18f">size</a></td><td class="entry"><a class="el" href="struct_vma_allocation_info.html">VmaAllocationInfo</a></td><td class="entry"></td></tr>
+</table></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/struct_vma_allocation_info.html b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_allocation_info.html
new file mode 100644
index 0000000..f7dc799
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_allocation_info.html
@@ -0,0 +1,217 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: VmaAllocationInfo Struct Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="summary">
+<a href="#pub-attribs">Public Attributes</a> &#124;
+<a href="struct_vma_allocation_info-members.html">List of all members</a>  </div>
+  <div class="headertitle">
+<div class="title">VmaAllocationInfo Struct Reference</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>Parameters of <a class="el" href="struct_vma_allocation.html" title="Represents single memory allocation.">VmaAllocation</a> objects, that can be retrieved using function <a class="el" href="vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b" title="Returns current information about specified allocation and atomically marks it as used in current fra...">vmaGetAllocationInfo()</a>.  
+ <a href="struct_vma_allocation_info.html#details">More...</a></p>
+
+<p><code>#include &lt;<a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a>&gt;</code></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="pub-attribs"></a>
+Public Attributes</h2></td></tr>
+<tr class="memitem:a7f6b0aa58c135e488e6b40a388dad9d5"><td class="memItemLeft" align="right" valign="top">uint32_t&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_allocation_info.html#a7f6b0aa58c135e488e6b40a388dad9d5">memoryType</a></td></tr>
+<tr class="memdesc:a7f6b0aa58c135e488e6b40a388dad9d5"><td class="mdescLeft">&#160;</td><td class="mdescRight">Memory type index that this allocation was allocated from.  <a href="struct_vma_allocation_info.html#a7f6b0aa58c135e488e6b40a388dad9d5">More...</a><br /></td></tr>
+<tr class="separator:a7f6b0aa58c135e488e6b40a388dad9d5"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ae0bfb7dfdf79a76ffefc9a94677a2f67"><td class="memItemLeft" align="right" valign="top">VkDeviceMemory&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_allocation_info.html#ae0bfb7dfdf79a76ffefc9a94677a2f67">deviceMemory</a></td></tr>
+<tr class="memdesc:ae0bfb7dfdf79a76ffefc9a94677a2f67"><td class="mdescLeft">&#160;</td><td class="mdescRight">Handle to Vulkan memory object.  <a href="struct_vma_allocation_info.html#ae0bfb7dfdf79a76ffefc9a94677a2f67">More...</a><br /></td></tr>
+<tr class="separator:ae0bfb7dfdf79a76ffefc9a94677a2f67"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a4a3c732388dbdc7a23f9365b00825268"><td class="memItemLeft" align="right" valign="top">VkDeviceSize&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_allocation_info.html#a4a3c732388dbdc7a23f9365b00825268">offset</a></td></tr>
+<tr class="memdesc:a4a3c732388dbdc7a23f9365b00825268"><td class="mdescLeft">&#160;</td><td class="mdescRight">Offset into deviceMemory object to the beginning of this allocation, in bytes. (deviceMemory, offset) pair is unique to this allocation.  <a href="struct_vma_allocation_info.html#a4a3c732388dbdc7a23f9365b00825268">More...</a><br /></td></tr>
+<tr class="separator:a4a3c732388dbdc7a23f9365b00825268"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:aac76d113a6a5ccbb09fea00fb25fd18f"><td class="memItemLeft" align="right" valign="top">VkDeviceSize&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_allocation_info.html#aac76d113a6a5ccbb09fea00fb25fd18f">size</a></td></tr>
+<tr class="memdesc:aac76d113a6a5ccbb09fea00fb25fd18f"><td class="mdescLeft">&#160;</td><td class="mdescRight">Size of this allocation, in bytes.  <a href="struct_vma_allocation_info.html#aac76d113a6a5ccbb09fea00fb25fd18f">More...</a><br /></td></tr>
+<tr class="separator:aac76d113a6a5ccbb09fea00fb25fd18f"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a5eeffbe2d2f30f53370ff14aefbadbe2"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_allocation_info.html#a5eeffbe2d2f30f53370ff14aefbadbe2">pMappedData</a></td></tr>
+<tr class="memdesc:a5eeffbe2d2f30f53370ff14aefbadbe2"><td class="mdescLeft">&#160;</td><td class="mdescRight">Pointer to the beginning of this allocation as mapped data.  <a href="struct_vma_allocation_info.html#a5eeffbe2d2f30f53370ff14aefbadbe2">More...</a><br /></td></tr>
+<tr class="separator:a5eeffbe2d2f30f53370ff14aefbadbe2"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:adc507656149c04de7ed95d0042ba2a13"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_allocation_info.html#adc507656149c04de7ed95d0042ba2a13">pUserData</a></td></tr>
+<tr class="memdesc:adc507656149c04de7ed95d0042ba2a13"><td class="mdescLeft">&#160;</td><td class="mdescRight">Custom general-purpose pointer that was passed as <a class="el" href="struct_vma_allocation_create_info.html#a8259e85c272683434f4abb4ddddffe19" title="Custom general-purpose pointer that will be stored in VmaAllocation, can be read as VmaAllocationInfo...">VmaAllocationCreateInfo::pUserData</a> or set using <a class="el" href="vk__mem__alloc_8h.html#af9147d31ffc11d62fc187bde283ed14f" title="Sets pUserData in given allocation to new value.">vmaSetAllocationUserData()</a>.  <a href="struct_vma_allocation_info.html#adc507656149c04de7ed95d0042ba2a13">More...</a><br /></td></tr>
+<tr class="separator:adc507656149c04de7ed95d0042ba2a13"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<div class="textblock"><p>Parameters of <a class="el" href="struct_vma_allocation.html" title="Represents single memory allocation.">VmaAllocation</a> objects, that can be retrieved using function <a class="el" href="vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b" title="Returns current information about specified allocation and atomically marks it as used in current fra...">vmaGetAllocationInfo()</a>. </p>
+</div><h2 class="groupheader">Member Data Documentation</h2>
+<a id="ae0bfb7dfdf79a76ffefc9a94677a2f67"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ae0bfb7dfdf79a76ffefc9a94677a2f67">&#9670;&nbsp;</a></span>deviceMemory</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkDeviceMemory VmaAllocationInfo::deviceMemory</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Handle to Vulkan memory object. </p>
+<p>Same memory object can be shared by multiple allocations.</p>
+<p>It can change after call to <a class="el" href="vk__mem__alloc_8h.html#a6aced90fcc7b39882b6654a740a0b9bb" title="Deprecated. Compacts memory by moving allocations.">vmaDefragment()</a> if this allocation is passed to the function, or if allocation is lost.</p>
+<p>If the allocation is lost, it is equal to <code>VK_NULL_HANDLE</code>. </p>
+
+</div>
+</div>
+<a id="a7f6b0aa58c135e488e6b40a388dad9d5"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a7f6b0aa58c135e488e6b40a388dad9d5">&#9670;&nbsp;</a></span>memoryType</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">uint32_t VmaAllocationInfo::memoryType</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Memory type index that this allocation was allocated from. </p>
+<p>It never changes. </p>
+
+</div>
+</div>
+<a id="a4a3c732388dbdc7a23f9365b00825268"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a4a3c732388dbdc7a23f9365b00825268">&#9670;&nbsp;</a></span>offset</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkDeviceSize VmaAllocationInfo::offset</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Offset into deviceMemory object to the beginning of this allocation, in bytes. (deviceMemory, offset) pair is unique to this allocation. </p>
+<p>It can change after call to <a class="el" href="vk__mem__alloc_8h.html#a6aced90fcc7b39882b6654a740a0b9bb" title="Deprecated. Compacts memory by moving allocations.">vmaDefragment()</a> if this allocation is passed to the function, or if allocation is lost. </p>
+
+</div>
+</div>
+<a id="a5eeffbe2d2f30f53370ff14aefbadbe2"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a5eeffbe2d2f30f53370ff14aefbadbe2">&#9670;&nbsp;</a></span>pMappedData</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* VmaAllocationInfo::pMappedData</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Pointer to the beginning of this allocation as mapped data. </p>
+<p>If the allocation hasn't been mapped using <a class="el" href="vk__mem__alloc_8h.html#ad5bd1243512d099706de88168992f069" title="Maps memory represented by given allocation and returns pointer to it.">vmaMapMemory()</a> and hasn't been created with <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a11da372cc3a82931c5e5d6146cd9dd1f" title="Set this flag to use a memory that will be persistently mapped and retrieve pointer to it.">VMA_ALLOCATION_CREATE_MAPPED_BIT</a> flag, this value null.</p>
+<p>It can change after call to <a class="el" href="vk__mem__alloc_8h.html#ad5bd1243512d099706de88168992f069" title="Maps memory represented by given allocation and returns pointer to it.">vmaMapMemory()</a>, <a class="el" href="vk__mem__alloc_8h.html#a9bc268595cb33f6ec4d519cfce81ff45" title="Unmaps memory represented by given allocation, mapped previously using vmaMapMemory().">vmaUnmapMemory()</a>. It can also change after call to <a class="el" href="vk__mem__alloc_8h.html#a6aced90fcc7b39882b6654a740a0b9bb" title="Deprecated. Compacts memory by moving allocations.">vmaDefragment()</a> if this allocation is passed to the function. </p>
+
+</div>
+</div>
+<a id="adc507656149c04de7ed95d0042ba2a13"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#adc507656149c04de7ed95d0042ba2a13">&#9670;&nbsp;</a></span>pUserData</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* VmaAllocationInfo::pUserData</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Custom general-purpose pointer that was passed as <a class="el" href="struct_vma_allocation_create_info.html#a8259e85c272683434f4abb4ddddffe19" title="Custom general-purpose pointer that will be stored in VmaAllocation, can be read as VmaAllocationInfo...">VmaAllocationCreateInfo::pUserData</a> or set using <a class="el" href="vk__mem__alloc_8h.html#af9147d31ffc11d62fc187bde283ed14f" title="Sets pUserData in given allocation to new value.">vmaSetAllocationUserData()</a>. </p>
+<p>It can change after call to <a class="el" href="vk__mem__alloc_8h.html#af9147d31ffc11d62fc187bde283ed14f" title="Sets pUserData in given allocation to new value.">vmaSetAllocationUserData()</a> for this allocation. </p>
+
+</div>
+</div>
+<a id="aac76d113a6a5ccbb09fea00fb25fd18f"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#aac76d113a6a5ccbb09fea00fb25fd18f">&#9670;&nbsp;</a></span>size</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkDeviceSize VmaAllocationInfo::size</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Size of this allocation, in bytes. </p>
+<p>It never changes, unless allocation is lost. </p>
+
+</div>
+</div>
+<hr/>The documentation for this struct was generated from the following file:<ul>
+<li><a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a></li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/struct_vma_allocator.html b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_allocator.html
new file mode 100644
index 0000000..412e173
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_allocator.html
@@ -0,0 +1,88 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: VmaAllocator Struct Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="headertitle">
+<div class="title">VmaAllocator Struct Reference</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>Represents main object of this library initialized.  
+ <a href="struct_vma_allocator.html#details">More...</a></p>
+
+<p><code>#include &lt;<a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a>&gt;</code></p>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<div class="textblock"><p>Represents main object of this library initialized. </p>
+<p>Fill structure <a class="el" href="struct_vma_allocator_create_info.html" title="Description of a Allocator to be created.">VmaAllocatorCreateInfo</a> and call function <a class="el" href="vk__mem__alloc_8h.html#a200692051ddb34240248234f5f4c17bb" title="Creates Allocator object.">vmaCreateAllocator()</a> to create it. Call function <a class="el" href="vk__mem__alloc_8h.html#aa8d164061c88f22fb1fd3c8f3534bc1d" title="Destroys allocator object.">vmaDestroyAllocator()</a> to destroy it.</p>
+<p>It is recommended to create just one object of this type per <code>VkDevice</code> object, right after Vulkan is initialized and keep it alive until before Vulkan device is destroyed. </p>
+</div><hr/>The documentation for this struct was generated from the following file:<ul>
+<li><a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a></li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/struct_vma_allocator_create_info-members.html b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_allocator_create_info-members.html
new file mode 100644
index 0000000..b96a87a
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_allocator_create_info-members.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: Member List</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="headertitle">
+<div class="title">VmaAllocatorCreateInfo Member List</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>This is the complete list of members for <a class="el" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a>, including all inherited members.</p>
+<table class="directory">
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html#ad924ddd77b04039c88d0c09b0ffcd500">device</a></td><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html#a392ea2ecbaff93f91a7c49f735ad4346">flags</a></td><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html#a21ea188dd212b8171cb9ecbed4a2a3a7">frameInUseCount</a></td><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html#a70dd42e29b1df1d1b9b61532ae0b370b">instance</a></td><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html#a6e409087e3be55400d0e4ccbe43c608d">pAllocationCallbacks</a></td><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html#af1380969b5e1ea4c3184a877892d260e">pDeviceMemoryCallbacks</a></td><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html#a31c192aa6cbffa33279f6d9f0c47c44b">pHeapSizeLimit</a></td><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html#a08230f04ae6ccf8a78150a9e829a7156">physicalDevice</a></td><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html#ace2aa4877b16a42b0b7673d4e26000ee">pRecordSettings</a></td><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html#a8e4714298e3121cdd8b214a1ae7a637a">preferredLargeHeapBlockSize</a></td><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html#a3dc197be3227da7338b1643f70db36bd">pVulkanFunctions</a></td><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html#ae0ffc55139b54520a6bb704b29ffc285">vulkanApiVersion</a></td><td class="entry"><a class="el" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a></td><td class="entry"></td></tr>
+</table></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/struct_vma_allocator_create_info.html b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_allocator_create_info.html
new file mode 100644
index 0000000..d603593
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_allocator_create_info.html
@@ -0,0 +1,342 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: VmaAllocatorCreateInfo Struct Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="summary">
+<a href="#pub-attribs">Public Attributes</a> &#124;
+<a href="struct_vma_allocator_create_info-members.html">List of all members</a>  </div>
+  <div class="headertitle">
+<div class="title">VmaAllocatorCreateInfo Struct Reference</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>Description of a Allocator to be created.  
+ <a href="struct_vma_allocator_create_info.html#details">More...</a></p>
+
+<p><code>#include &lt;<a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a>&gt;</code></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="pub-attribs"></a>
+Public Attributes</h2></td></tr>
+<tr class="memitem:a392ea2ecbaff93f91a7c49f735ad4346"><td class="memItemLeft" align="right" valign="top"><a class="el" href="vk__mem__alloc_8h.html#acfe6863e160722c2c1bbcf7573fddc4d">VmaAllocatorCreateFlags</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_allocator_create_info.html#a392ea2ecbaff93f91a7c49f735ad4346">flags</a></td></tr>
+<tr class="memdesc:a392ea2ecbaff93f91a7c49f735ad4346"><td class="mdescLeft">&#160;</td><td class="mdescRight">Flags for created allocator. Use <a class="el" href="vk__mem__alloc_8h.html#afd73b95e737ee7e76f827cb5472f559f" title="Flags for created VmaAllocator.">VmaAllocatorCreateFlagBits</a> enum.  <a href="struct_vma_allocator_create_info.html#a392ea2ecbaff93f91a7c49f735ad4346">More...</a><br /></td></tr>
+<tr class="separator:a392ea2ecbaff93f91a7c49f735ad4346"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a08230f04ae6ccf8a78150a9e829a7156"><td class="memItemLeft" align="right" valign="top">VkPhysicalDevice&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_allocator_create_info.html#a08230f04ae6ccf8a78150a9e829a7156">physicalDevice</a></td></tr>
+<tr class="memdesc:a08230f04ae6ccf8a78150a9e829a7156"><td class="mdescLeft">&#160;</td><td class="mdescRight">Vulkan physical device.  <a href="struct_vma_allocator_create_info.html#a08230f04ae6ccf8a78150a9e829a7156">More...</a><br /></td></tr>
+<tr class="separator:a08230f04ae6ccf8a78150a9e829a7156"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ad924ddd77b04039c88d0c09b0ffcd500"><td class="memItemLeft" align="right" valign="top">VkDevice&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_allocator_create_info.html#ad924ddd77b04039c88d0c09b0ffcd500">device</a></td></tr>
+<tr class="memdesc:ad924ddd77b04039c88d0c09b0ffcd500"><td class="mdescLeft">&#160;</td><td class="mdescRight">Vulkan device.  <a href="struct_vma_allocator_create_info.html#ad924ddd77b04039c88d0c09b0ffcd500">More...</a><br /></td></tr>
+<tr class="separator:ad924ddd77b04039c88d0c09b0ffcd500"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a8e4714298e3121cdd8b214a1ae7a637a"><td class="memItemLeft" align="right" valign="top">VkDeviceSize&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_allocator_create_info.html#a8e4714298e3121cdd8b214a1ae7a637a">preferredLargeHeapBlockSize</a></td></tr>
+<tr class="memdesc:a8e4714298e3121cdd8b214a1ae7a637a"><td class="mdescLeft">&#160;</td><td class="mdescRight">Preferred size of a single <code>VkDeviceMemory</code> block to be allocated from large heaps &gt; 1 GiB. Optional.  <a href="struct_vma_allocator_create_info.html#a8e4714298e3121cdd8b214a1ae7a637a">More...</a><br /></td></tr>
+<tr class="separator:a8e4714298e3121cdd8b214a1ae7a637a"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a6e409087e3be55400d0e4ccbe43c608d"><td class="memItemLeft" align="right" valign="top">const VkAllocationCallbacks *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_allocator_create_info.html#a6e409087e3be55400d0e4ccbe43c608d">pAllocationCallbacks</a></td></tr>
+<tr class="memdesc:a6e409087e3be55400d0e4ccbe43c608d"><td class="mdescLeft">&#160;</td><td class="mdescRight">Custom CPU memory allocation callbacks. Optional.  <a href="struct_vma_allocator_create_info.html#a6e409087e3be55400d0e4ccbe43c608d">More...</a><br /></td></tr>
+<tr class="separator:a6e409087e3be55400d0e4ccbe43c608d"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:af1380969b5e1ea4c3184a877892d260e"><td class="memItemLeft" align="right" valign="top">const <a class="el" href="struct_vma_device_memory_callbacks.html">VmaDeviceMemoryCallbacks</a> *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_allocator_create_info.html#af1380969b5e1ea4c3184a877892d260e">pDeviceMemoryCallbacks</a></td></tr>
+<tr class="memdesc:af1380969b5e1ea4c3184a877892d260e"><td class="mdescLeft">&#160;</td><td class="mdescRight">Informative callbacks for <code>vkAllocateMemory</code>, <code>vkFreeMemory</code>. Optional.  <a href="struct_vma_allocator_create_info.html#af1380969b5e1ea4c3184a877892d260e">More...</a><br /></td></tr>
+<tr class="separator:af1380969b5e1ea4c3184a877892d260e"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a21ea188dd212b8171cb9ecbed4a2a3a7"><td class="memItemLeft" align="right" valign="top">uint32_t&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_allocator_create_info.html#a21ea188dd212b8171cb9ecbed4a2a3a7">frameInUseCount</a></td></tr>
+<tr class="memdesc:a21ea188dd212b8171cb9ecbed4a2a3a7"><td class="mdescLeft">&#160;</td><td class="mdescRight">Maximum number of additional frames that are in use at the same time as current frame.  <a href="struct_vma_allocator_create_info.html#a21ea188dd212b8171cb9ecbed4a2a3a7">More...</a><br /></td></tr>
+<tr class="separator:a21ea188dd212b8171cb9ecbed4a2a3a7"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a31c192aa6cbffa33279f6d9f0c47c44b"><td class="memItemLeft" align="right" valign="top">const VkDeviceSize *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_allocator_create_info.html#a31c192aa6cbffa33279f6d9f0c47c44b">pHeapSizeLimit</a></td></tr>
+<tr class="memdesc:a31c192aa6cbffa33279f6d9f0c47c44b"><td class="mdescLeft">&#160;</td><td class="mdescRight">Either null or a pointer to an array of limits on maximum number of bytes that can be allocated out of particular Vulkan memory heap.  <a href="struct_vma_allocator_create_info.html#a31c192aa6cbffa33279f6d9f0c47c44b">More...</a><br /></td></tr>
+<tr class="separator:a31c192aa6cbffa33279f6d9f0c47c44b"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a3dc197be3227da7338b1643f70db36bd"><td class="memItemLeft" align="right" valign="top">const <a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a> *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_allocator_create_info.html#a3dc197be3227da7338b1643f70db36bd">pVulkanFunctions</a></td></tr>
+<tr class="memdesc:a3dc197be3227da7338b1643f70db36bd"><td class="mdescLeft">&#160;</td><td class="mdescRight">Pointers to Vulkan functions. Can be null.  <a href="struct_vma_allocator_create_info.html#a3dc197be3227da7338b1643f70db36bd">More...</a><br /></td></tr>
+<tr class="separator:a3dc197be3227da7338b1643f70db36bd"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ace2aa4877b16a42b0b7673d4e26000ee"><td class="memItemLeft" align="right" valign="top">const <a class="el" href="struct_vma_record_settings.html">VmaRecordSettings</a> *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_allocator_create_info.html#ace2aa4877b16a42b0b7673d4e26000ee">pRecordSettings</a></td></tr>
+<tr class="memdesc:ace2aa4877b16a42b0b7673d4e26000ee"><td class="mdescLeft">&#160;</td><td class="mdescRight">Parameters for recording of VMA calls. Can be null.  <a href="struct_vma_allocator_create_info.html#ace2aa4877b16a42b0b7673d4e26000ee">More...</a><br /></td></tr>
+<tr class="separator:ace2aa4877b16a42b0b7673d4e26000ee"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a70dd42e29b1df1d1b9b61532ae0b370b"><td class="memItemLeft" align="right" valign="top">VkInstance&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_allocator_create_info.html#a70dd42e29b1df1d1b9b61532ae0b370b">instance</a></td></tr>
+<tr class="memdesc:a70dd42e29b1df1d1b9b61532ae0b370b"><td class="mdescLeft">&#160;</td><td class="mdescRight">Handle to Vulkan instance object.  <a href="struct_vma_allocator_create_info.html#a70dd42e29b1df1d1b9b61532ae0b370b">More...</a><br /></td></tr>
+<tr class="separator:a70dd42e29b1df1d1b9b61532ae0b370b"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ae0ffc55139b54520a6bb704b29ffc285"><td class="memItemLeft" align="right" valign="top">uint32_t&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_allocator_create_info.html#ae0ffc55139b54520a6bb704b29ffc285">vulkanApiVersion</a></td></tr>
+<tr class="memdesc:ae0ffc55139b54520a6bb704b29ffc285"><td class="mdescLeft">&#160;</td><td class="mdescRight">Optional. The highest version of Vulkan that the application is designed to use.  <a href="struct_vma_allocator_create_info.html#ae0ffc55139b54520a6bb704b29ffc285">More...</a><br /></td></tr>
+<tr class="separator:ae0ffc55139b54520a6bb704b29ffc285"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<div class="textblock"><p>Description of a Allocator to be created. </p>
+</div><h2 class="groupheader">Member Data Documentation</h2>
+<a id="ad924ddd77b04039c88d0c09b0ffcd500"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ad924ddd77b04039c88d0c09b0ffcd500">&#9670;&nbsp;</a></span>device</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkDevice VmaAllocatorCreateInfo::device</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Vulkan device. </p>
+<p>It must be valid throughout whole lifetime of created allocator. </p>
+
+</div>
+</div>
+<a id="a392ea2ecbaff93f91a7c49f735ad4346"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a392ea2ecbaff93f91a7c49f735ad4346">&#9670;&nbsp;</a></span>flags</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname"><a class="el" href="vk__mem__alloc_8h.html#acfe6863e160722c2c1bbcf7573fddc4d">VmaAllocatorCreateFlags</a> VmaAllocatorCreateInfo::flags</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Flags for created allocator. Use <a class="el" href="vk__mem__alloc_8h.html#afd73b95e737ee7e76f827cb5472f559f" title="Flags for created VmaAllocator.">VmaAllocatorCreateFlagBits</a> enum. </p>
+
+</div>
+</div>
+<a id="a21ea188dd212b8171cb9ecbed4a2a3a7"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a21ea188dd212b8171cb9ecbed4a2a3a7">&#9670;&nbsp;</a></span>frameInUseCount</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">uint32_t VmaAllocatorCreateInfo::frameInUseCount</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Maximum number of additional frames that are in use at the same time as current frame. </p>
+<p>This value is used only when you make allocations with VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT flag. Such allocation cannot become lost if allocation.lastUseFrameIndex &gt;= allocator.currentFrameIndex - frameInUseCount.</p>
+<p>For example, if you double-buffer your command buffers, so resources used for rendering in previous frame may still be in use by the GPU at the moment you allocate resources needed for the current frame, set this value to 1.</p>
+<p>If you want to allow any allocations other than used in the current frame to become lost, set this value to 0. </p>
+
+</div>
+</div>
+<a id="a70dd42e29b1df1d1b9b61532ae0b370b"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a70dd42e29b1df1d1b9b61532ae0b370b">&#9670;&nbsp;</a></span>instance</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkInstance VmaAllocatorCreateInfo::instance</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Handle to Vulkan instance object. </p>
+<p>Starting from version 3.0.0 this member is no longer optional, it must be set! </p>
+
+</div>
+</div>
+<a id="a6e409087e3be55400d0e4ccbe43c608d"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a6e409087e3be55400d0e4ccbe43c608d">&#9670;&nbsp;</a></span>pAllocationCallbacks</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">const VkAllocationCallbacks* VmaAllocatorCreateInfo::pAllocationCallbacks</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Custom CPU memory allocation callbacks. Optional. </p>
+<p>Optional, can be null. When specified, will also be used for all CPU-side memory allocations. </p>
+
+</div>
+</div>
+<a id="af1380969b5e1ea4c3184a877892d260e"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#af1380969b5e1ea4c3184a877892d260e">&#9670;&nbsp;</a></span>pDeviceMemoryCallbacks</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">const <a class="el" href="struct_vma_device_memory_callbacks.html">VmaDeviceMemoryCallbacks</a>* VmaAllocatorCreateInfo::pDeviceMemoryCallbacks</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Informative callbacks for <code>vkAllocateMemory</code>, <code>vkFreeMemory</code>. Optional. </p>
+<p>Optional, can be null. </p>
+
+</div>
+</div>
+<a id="a31c192aa6cbffa33279f6d9f0c47c44b"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a31c192aa6cbffa33279f6d9f0c47c44b">&#9670;&nbsp;</a></span>pHeapSizeLimit</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">const VkDeviceSize* VmaAllocatorCreateInfo::pHeapSizeLimit</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Either null or a pointer to an array of limits on maximum number of bytes that can be allocated out of particular Vulkan memory heap. </p>
+<p>If not NULL, it must be a pointer to an array of <code>VkPhysicalDeviceMemoryProperties::memoryHeapCount</code> elements, defining limit on maximum number of bytes that can be allocated out of particular Vulkan memory heap.</p>
+<p>Any of the elements may be equal to <code>VK_WHOLE_SIZE</code>, which means no limit on that heap. This is also the default in case of <code>pHeapSizeLimit</code> = NULL.</p>
+<p>If there is a limit defined for a heap:</p>
+<ul>
+<li>If user tries to allocate more memory from that heap using this allocator, the allocation fails with <code>VK_ERROR_OUT_OF_DEVICE_MEMORY</code>.</li>
+<li>If the limit is smaller than heap size reported in <code>VkMemoryHeap::size</code>, the value of this limit will be reported instead when using <a class="el" href="vk__mem__alloc_8h.html#ab88db292a17974f911182543fda52d19">vmaGetMemoryProperties()</a>.</li>
+</ul>
+<p>Warning! Using this feature may not be equivalent to installing a GPU with smaller amount of memory, because graphics driver doesn't necessary fail new allocations with <code>VK_ERROR_OUT_OF_DEVICE_MEMORY</code> result when memory capacity is exceeded. It may return success and just silently migrate some device memory blocks to system RAM. This driver behavior can also be controlled using VK_AMD_memory_overallocation_behavior extension. </p>
+
+</div>
+</div>
+<a id="a08230f04ae6ccf8a78150a9e829a7156"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a08230f04ae6ccf8a78150a9e829a7156">&#9670;&nbsp;</a></span>physicalDevice</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkPhysicalDevice VmaAllocatorCreateInfo::physicalDevice</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Vulkan physical device. </p>
+<p>It must be valid throughout whole lifetime of created allocator. </p>
+
+</div>
+</div>
+<a id="ace2aa4877b16a42b0b7673d4e26000ee"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ace2aa4877b16a42b0b7673d4e26000ee">&#9670;&nbsp;</a></span>pRecordSettings</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">const <a class="el" href="struct_vma_record_settings.html">VmaRecordSettings</a>* VmaAllocatorCreateInfo::pRecordSettings</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Parameters for recording of VMA calls. Can be null. </p>
+<p>If not null, it enables recording of calls to VMA functions to a file. If support for recording is not enabled using <code>VMA_RECORDING_ENABLED</code> macro, creation of the allocator object fails with <code>VK_ERROR_FEATURE_NOT_PRESENT</code>. </p>
+
+</div>
+</div>
+<a id="a8e4714298e3121cdd8b214a1ae7a637a"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a8e4714298e3121cdd8b214a1ae7a637a">&#9670;&nbsp;</a></span>preferredLargeHeapBlockSize</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkDeviceSize VmaAllocatorCreateInfo::preferredLargeHeapBlockSize</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Preferred size of a single <code>VkDeviceMemory</code> block to be allocated from large heaps &gt; 1 GiB. Optional. </p>
+<p>Set to 0 to use default, which is currently 256 MiB. </p>
+
+</div>
+</div>
+<a id="a3dc197be3227da7338b1643f70db36bd"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a3dc197be3227da7338b1643f70db36bd">&#9670;&nbsp;</a></span>pVulkanFunctions</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">const <a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a>* VmaAllocatorCreateInfo::pVulkanFunctions</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Pointers to Vulkan functions. Can be null. </p>
+<p>For details see <a class="el" href="configuration.html#config_Vulkan_functions">Pointers to Vulkan functions</a>. </p>
+
+</div>
+</div>
+<a id="ae0ffc55139b54520a6bb704b29ffc285"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ae0ffc55139b54520a6bb704b29ffc285">&#9670;&nbsp;</a></span>vulkanApiVersion</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">uint32_t VmaAllocatorCreateInfo::vulkanApiVersion</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Optional. The highest version of Vulkan that the application is designed to use. </p>
+<p>It must be a value in the format as created by macro <code>VK_MAKE_VERSION</code> or a constant like: <code>VK_API_VERSION_1_1</code>, <code>VK_API_VERSION_1_0</code>. The patch version number specified is ignored. Only the major and minor versions are considered. It must be less or equal (preferably equal) to value as passed to <code>vkCreateInstance</code> as <code>VkApplicationInfo::apiVersion</code>. Only versions 1.0 and 1.1 are supported by the current implementation. Leaving it initialized to zero is equivalent to <code>VK_API_VERSION_1_0</code>. </p>
+
+</div>
+</div>
+<hr/>The documentation for this struct was generated from the following file:<ul>
+<li><a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a></li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/struct_vma_allocator_info-members.html b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_allocator_info-members.html
new file mode 100644
index 0000000..ade98f0
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_allocator_info-members.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: Member List</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="headertitle">
+<div class="title">VmaAllocatorInfo Member List</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>This is the complete list of members for <a class="el" href="struct_vma_allocator_info.html">VmaAllocatorInfo</a>, including all inherited members.</p>
+<table class="directory">
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_allocator_info.html#a012b4c485bf3b0ea8921352c5ee0c357">device</a></td><td class="entry"><a class="el" href="struct_vma_allocator_info.html">VmaAllocatorInfo</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_allocator_info.html#a2ed6a4d2d3fea039d66a13f15d0ce5fe">instance</a></td><td class="entry"><a class="el" href="struct_vma_allocator_info.html">VmaAllocatorInfo</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_allocator_info.html#aba2b703f96e51d567717e1fb2935b47a">physicalDevice</a></td><td class="entry"><a class="el" href="struct_vma_allocator_info.html">VmaAllocatorInfo</a></td><td class="entry"></td></tr>
+</table></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/struct_vma_allocator_info.html b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_allocator_info.html
new file mode 100644
index 0000000..8716975
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_allocator_info.html
@@ -0,0 +1,154 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: VmaAllocatorInfo Struct Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="summary">
+<a href="#pub-attribs">Public Attributes</a> &#124;
+<a href="struct_vma_allocator_info-members.html">List of all members</a>  </div>
+  <div class="headertitle">
+<div class="title">VmaAllocatorInfo Struct Reference</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>Information about existing <a class="el" href="struct_vma_allocator.html" title="Represents main object of this library initialized.">VmaAllocator</a> object.  
+ <a href="struct_vma_allocator_info.html#details">More...</a></p>
+
+<p><code>#include &lt;<a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a>&gt;</code></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="pub-attribs"></a>
+Public Attributes</h2></td></tr>
+<tr class="memitem:a2ed6a4d2d3fea039d66a13f15d0ce5fe"><td class="memItemLeft" align="right" valign="top">VkInstance&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_allocator_info.html#a2ed6a4d2d3fea039d66a13f15d0ce5fe">instance</a></td></tr>
+<tr class="memdesc:a2ed6a4d2d3fea039d66a13f15d0ce5fe"><td class="mdescLeft">&#160;</td><td class="mdescRight">Handle to Vulkan instance object.  <a href="struct_vma_allocator_info.html#a2ed6a4d2d3fea039d66a13f15d0ce5fe">More...</a><br /></td></tr>
+<tr class="separator:a2ed6a4d2d3fea039d66a13f15d0ce5fe"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:aba2b703f96e51d567717e1fb2935b47a"><td class="memItemLeft" align="right" valign="top">VkPhysicalDevice&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_allocator_info.html#aba2b703f96e51d567717e1fb2935b47a">physicalDevice</a></td></tr>
+<tr class="memdesc:aba2b703f96e51d567717e1fb2935b47a"><td class="mdescLeft">&#160;</td><td class="mdescRight">Handle to Vulkan physical device object.  <a href="struct_vma_allocator_info.html#aba2b703f96e51d567717e1fb2935b47a">More...</a><br /></td></tr>
+<tr class="separator:aba2b703f96e51d567717e1fb2935b47a"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a012b4c485bf3b0ea8921352c5ee0c357"><td class="memItemLeft" align="right" valign="top">VkDevice&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_allocator_info.html#a012b4c485bf3b0ea8921352c5ee0c357">device</a></td></tr>
+<tr class="memdesc:a012b4c485bf3b0ea8921352c5ee0c357"><td class="mdescLeft">&#160;</td><td class="mdescRight">Handle to Vulkan device object.  <a href="struct_vma_allocator_info.html#a012b4c485bf3b0ea8921352c5ee0c357">More...</a><br /></td></tr>
+<tr class="separator:a012b4c485bf3b0ea8921352c5ee0c357"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<div class="textblock"><p>Information about existing <a class="el" href="struct_vma_allocator.html" title="Represents main object of this library initialized.">VmaAllocator</a> object. </p>
+</div><h2 class="groupheader">Member Data Documentation</h2>
+<a id="a012b4c485bf3b0ea8921352c5ee0c357"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a012b4c485bf3b0ea8921352c5ee0c357">&#9670;&nbsp;</a></span>device</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkDevice VmaAllocatorInfo::device</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Handle to Vulkan device object. </p>
+<p>This is the same value as has been passed through <a class="el" href="struct_vma_allocator_create_info.html#ad924ddd77b04039c88d0c09b0ffcd500" title="Vulkan device.">VmaAllocatorCreateInfo::device</a>. </p>
+
+</div>
+</div>
+<a id="a2ed6a4d2d3fea039d66a13f15d0ce5fe"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a2ed6a4d2d3fea039d66a13f15d0ce5fe">&#9670;&nbsp;</a></span>instance</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkInstance VmaAllocatorInfo::instance</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Handle to Vulkan instance object. </p>
+<p>This is the same value as has been passed through <a class="el" href="struct_vma_allocator_create_info.html#a70dd42e29b1df1d1b9b61532ae0b370b" title="Handle to Vulkan instance object.">VmaAllocatorCreateInfo::instance</a>. </p>
+
+</div>
+</div>
+<a id="aba2b703f96e51d567717e1fb2935b47a"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#aba2b703f96e51d567717e1fb2935b47a">&#9670;&nbsp;</a></span>physicalDevice</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkPhysicalDevice VmaAllocatorInfo::physicalDevice</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Handle to Vulkan physical device object. </p>
+<p>This is the same value as has been passed through <a class="el" href="struct_vma_allocator_create_info.html#a08230f04ae6ccf8a78150a9e829a7156" title="Vulkan physical device.">VmaAllocatorCreateInfo::physicalDevice</a>. </p>
+
+</div>
+</div>
+<hr/>The documentation for this struct was generated from the following file:<ul>
+<li><a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a></li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/struct_vma_budget-members.html b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_budget-members.html
new file mode 100644
index 0000000..5e34b8b
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_budget-members.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: Member List</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="headertitle">
+<div class="title">VmaBudget Member List</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>This is the complete list of members for <a class="el" href="struct_vma_budget.html">VmaBudget</a>, including all inherited members.</p>
+<table class="directory">
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_budget.html#a7e2a6583ebd63e194951c542563804d8">allocationBytes</a></td><td class="entry"><a class="el" href="struct_vma_budget.html">VmaBudget</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_budget.html#a58b492901baab685f466199124e514a0">blockBytes</a></td><td class="entry"><a class="el" href="struct_vma_budget.html">VmaBudget</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_budget.html#ab82e1d1754c2d210d0bdf90220bc6cdd">budget</a></td><td class="entry"><a class="el" href="struct_vma_budget.html">VmaBudget</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_budget.html#a84dd1ecca8b0110259eb206dbadb11f6">usage</a></td><td class="entry"><a class="el" href="struct_vma_budget.html">VmaBudget</a></td><td class="entry"></td></tr>
+</table></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/struct_vma_budget.html b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_budget.html
new file mode 100644
index 0000000..83f11ec
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_budget.html
@@ -0,0 +1,176 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: VmaBudget Struct Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="summary">
+<a href="#pub-attribs">Public Attributes</a> &#124;
+<a href="struct_vma_budget-members.html">List of all members</a>  </div>
+  <div class="headertitle">
+<div class="title">VmaBudget Struct Reference</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>Statistics of current memory usage and available budget, in bytes, for specific memory heap.  
+ <a href="struct_vma_budget.html#details">More...</a></p>
+
+<p><code>#include &lt;<a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a>&gt;</code></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="pub-attribs"></a>
+Public Attributes</h2></td></tr>
+<tr class="memitem:a58b492901baab685f466199124e514a0"><td class="memItemLeft" align="right" valign="top">VkDeviceSize&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_budget.html#a58b492901baab685f466199124e514a0">blockBytes</a></td></tr>
+<tr class="memdesc:a58b492901baab685f466199124e514a0"><td class="mdescLeft">&#160;</td><td class="mdescRight">Sum size of all <code>VkDeviceMemory</code> blocks allocated from particular heap, in bytes.  <a href="struct_vma_budget.html#a58b492901baab685f466199124e514a0">More...</a><br /></td></tr>
+<tr class="separator:a58b492901baab685f466199124e514a0"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a7e2a6583ebd63e194951c542563804d8"><td class="memItemLeft" align="right" valign="top">VkDeviceSize&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_budget.html#a7e2a6583ebd63e194951c542563804d8">allocationBytes</a></td></tr>
+<tr class="memdesc:a7e2a6583ebd63e194951c542563804d8"><td class="mdescLeft">&#160;</td><td class="mdescRight">Sum size of all allocations created in particular heap, in bytes.  <a href="struct_vma_budget.html#a7e2a6583ebd63e194951c542563804d8">More...</a><br /></td></tr>
+<tr class="separator:a7e2a6583ebd63e194951c542563804d8"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a84dd1ecca8b0110259eb206dbadb11f6"><td class="memItemLeft" align="right" valign="top">VkDeviceSize&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_budget.html#a84dd1ecca8b0110259eb206dbadb11f6">usage</a></td></tr>
+<tr class="memdesc:a84dd1ecca8b0110259eb206dbadb11f6"><td class="mdescLeft">&#160;</td><td class="mdescRight">Estimated current memory usage of the program, in bytes.  <a href="struct_vma_budget.html#a84dd1ecca8b0110259eb206dbadb11f6">More...</a><br /></td></tr>
+<tr class="separator:a84dd1ecca8b0110259eb206dbadb11f6"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ab82e1d1754c2d210d0bdf90220bc6cdd"><td class="memItemLeft" align="right" valign="top">VkDeviceSize&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_budget.html#ab82e1d1754c2d210d0bdf90220bc6cdd">budget</a></td></tr>
+<tr class="memdesc:ab82e1d1754c2d210d0bdf90220bc6cdd"><td class="mdescLeft">&#160;</td><td class="mdescRight">Estimated amount of memory available to the program, in bytes.  <a href="struct_vma_budget.html#ab82e1d1754c2d210d0bdf90220bc6cdd">More...</a><br /></td></tr>
+<tr class="separator:ab82e1d1754c2d210d0bdf90220bc6cdd"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<div class="textblock"><p>Statistics of current memory usage and available budget, in bytes, for specific memory heap. </p>
+</div><h2 class="groupheader">Member Data Documentation</h2>
+<a id="a7e2a6583ebd63e194951c542563804d8"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a7e2a6583ebd63e194951c542563804d8">&#9670;&nbsp;</a></span>allocationBytes</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkDeviceSize VmaBudget::allocationBytes</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Sum size of all allocations created in particular heap, in bytes. </p>
+<p>Usually less or equal than <code>blockBytes</code>. Difference <code>blockBytes - allocationBytes</code> is the amount of memory allocated but unused - available for new allocations or wasted due to fragmentation.</p>
+<p>It might be greater than <code>blockBytes</code> if there are some allocations in lost state, as they account to this value as well. </p>
+
+</div>
+</div>
+<a id="a58b492901baab685f466199124e514a0"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a58b492901baab685f466199124e514a0">&#9670;&nbsp;</a></span>blockBytes</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkDeviceSize VmaBudget::blockBytes</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Sum size of all <code>VkDeviceMemory</code> blocks allocated from particular heap, in bytes. </p>
+
+</div>
+</div>
+<a id="ab82e1d1754c2d210d0bdf90220bc6cdd"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ab82e1d1754c2d210d0bdf90220bc6cdd">&#9670;&nbsp;</a></span>budget</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkDeviceSize VmaBudget::budget</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Estimated amount of memory available to the program, in bytes. </p>
+<p>Fetched from system using <code>VK_EXT_memory_budget</code> extension if enabled.</p>
+<p>It might be different (most probably smaller) than <code>VkMemoryHeap::size[heapIndex]</code> due to factors external to the program, like other programs also consuming system resources. Difference <code>budget - usage</code> is the amount of additional memory that can probably be allocated without problems. Exceeding the budget may result in various problems. </p>
+
+</div>
+</div>
+<a id="a84dd1ecca8b0110259eb206dbadb11f6"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a84dd1ecca8b0110259eb206dbadb11f6">&#9670;&nbsp;</a></span>usage</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkDeviceSize VmaBudget::usage</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Estimated current memory usage of the program, in bytes. </p>
+<p>Fetched from system using <code>VK_EXT_memory_budget</code> extension if enabled.</p>
+<p>It might be different than <code>blockBytes</code> (usually higher) due to additional implicit objects also occupying the memory, like swapchain, pipelines, descriptor heaps, command buffers, or <code>VkDeviceMemory</code> blocks allocated outside of this library, if any. </p>
+
+</div>
+</div>
+<hr/>The documentation for this struct was generated from the following file:<ul>
+<li><a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a></li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/struct_vma_defragmentation_context.html b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_defragmentation_context.html
new file mode 100644
index 0000000..25bcdb8
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_defragmentation_context.html
@@ -0,0 +1,87 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: VmaDefragmentationContext Struct Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="headertitle">
+<div class="title">VmaDefragmentationContext Struct Reference</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>Represents Opaque object that represents started defragmentation process.  
+ <a href="struct_vma_defragmentation_context.html#details">More...</a></p>
+
+<p><code>#include &lt;<a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a>&gt;</code></p>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<div class="textblock"><p>Represents Opaque object that represents started defragmentation process. </p>
+<p>Fill structure <a class="el" href="struct_vma_defragmentation_info2.html" title="Parameters for defragmentation.">VmaDefragmentationInfo2</a> and call function <a class="el" href="vk__mem__alloc_8h.html#a36ba776fd7fd5cb1e9359fdc0d8e6e8a" title="Begins defragmentation process.">vmaDefragmentationBegin()</a> to create it. Call function <a class="el" href="vk__mem__alloc_8h.html#a8774e20e91e245aae959ba63efa15dd2" title="Ends defragmentation process.">vmaDefragmentationEnd()</a> to destroy it. </p>
+</div><hr/>The documentation for this struct was generated from the following file:<ul>
+<li><a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a></li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/struct_vma_defragmentation_info-members.html b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_defragmentation_info-members.html
new file mode 100644
index 0000000..1d3184e
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_defragmentation_info-members.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: Member List</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="headertitle">
+<div class="title">VmaDefragmentationInfo Member List</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>This is the complete list of members for <a class="el" href="struct_vma_defragmentation_info.html">VmaDefragmentationInfo</a>, including all inherited members.</p>
+<table class="directory">
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_defragmentation_info.html#aa7c7304e13c71f604c907196c4e28fbc">maxAllocationsToMove</a></td><td class="entry"><a class="el" href="struct_vma_defragmentation_info.html">VmaDefragmentationInfo</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_defragmentation_info.html#acb311c940a777270e67e1b81c5ab6a1d">maxBytesToMove</a></td><td class="entry"><a class="el" href="struct_vma_defragmentation_info.html">VmaDefragmentationInfo</a></td><td class="entry"></td></tr>
+</table></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/struct_vma_defragmentation_info.html b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_defragmentation_info.html
new file mode 100644
index 0000000..39fc104
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_defragmentation_info.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: VmaDefragmentationInfo Struct Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="summary">
+<a href="#pub-attribs">Public Attributes</a> &#124;
+<a href="struct_vma_defragmentation_info-members.html">List of all members</a>  </div>
+  <div class="headertitle">
+<div class="title">VmaDefragmentationInfo Struct Reference</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>Deprecated. Optional configuration parameters to be passed to function <a class="el" href="vk__mem__alloc_8h.html#a6aced90fcc7b39882b6654a740a0b9bb" title="Deprecated. Compacts memory by moving allocations.">vmaDefragment()</a>.  
+ <a href="struct_vma_defragmentation_info.html#details">More...</a></p>
+
+<p><code>#include &lt;<a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a>&gt;</code></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="pub-attribs"></a>
+Public Attributes</h2></td></tr>
+<tr class="memitem:acb311c940a777270e67e1b81c5ab6a1d"><td class="memItemLeft" align="right" valign="top">VkDeviceSize&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_defragmentation_info.html#acb311c940a777270e67e1b81c5ab6a1d">maxBytesToMove</a></td></tr>
+<tr class="memdesc:acb311c940a777270e67e1b81c5ab6a1d"><td class="mdescLeft">&#160;</td><td class="mdescRight">Maximum total numbers of bytes that can be copied while moving allocations to different places.  <a href="struct_vma_defragmentation_info.html#acb311c940a777270e67e1b81c5ab6a1d">More...</a><br /></td></tr>
+<tr class="separator:acb311c940a777270e67e1b81c5ab6a1d"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:aa7c7304e13c71f604c907196c4e28fbc"><td class="memItemLeft" align="right" valign="top">uint32_t&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_defragmentation_info.html#aa7c7304e13c71f604c907196c4e28fbc">maxAllocationsToMove</a></td></tr>
+<tr class="memdesc:aa7c7304e13c71f604c907196c4e28fbc"><td class="mdescLeft">&#160;</td><td class="mdescRight">Maximum number of allocations that can be moved to different place.  <a href="struct_vma_defragmentation_info.html#aa7c7304e13c71f604c907196c4e28fbc">More...</a><br /></td></tr>
+<tr class="separator:aa7c7304e13c71f604c907196c4e28fbc"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<div class="textblock"><p>Deprecated. Optional configuration parameters to be passed to function <a class="el" href="vk__mem__alloc_8h.html#a6aced90fcc7b39882b6654a740a0b9bb" title="Deprecated. Compacts memory by moving allocations.">vmaDefragment()</a>. </p>
+<dl class="deprecated"><dt><b><a class="el" href="deprecated.html#_deprecated000002">Deprecated:</a></b></dt><dd>This is a part of the old interface. It is recommended to use structure <a class="el" href="struct_vma_defragmentation_info2.html" title="Parameters for defragmentation.">VmaDefragmentationInfo2</a> and function <a class="el" href="vk__mem__alloc_8h.html#a36ba776fd7fd5cb1e9359fdc0d8e6e8a" title="Begins defragmentation process.">vmaDefragmentationBegin()</a> instead. </dd></dl>
+</div><h2 class="groupheader">Member Data Documentation</h2>
+<a id="aa7c7304e13c71f604c907196c4e28fbc"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#aa7c7304e13c71f604c907196c4e28fbc">&#9670;&nbsp;</a></span>maxAllocationsToMove</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">uint32_t VmaDefragmentationInfo::maxAllocationsToMove</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Maximum number of allocations that can be moved to different place. </p>
+<p>Default is <code>UINT32_MAX</code>, which means no limit. </p>
+
+</div>
+</div>
+<a id="acb311c940a777270e67e1b81c5ab6a1d"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#acb311c940a777270e67e1b81c5ab6a1d">&#9670;&nbsp;</a></span>maxBytesToMove</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkDeviceSize VmaDefragmentationInfo::maxBytesToMove</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Maximum total numbers of bytes that can be copied while moving allocations to different places. </p>
+<p>Default is <code>VK_WHOLE_SIZE</code>, which means no limit. </p>
+
+</div>
+</div>
+<hr/>The documentation for this struct was generated from the following file:<ul>
+<li><a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a></li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/struct_vma_defragmentation_info2-members.html b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_defragmentation_info2-members.html
new file mode 100644
index 0000000..baa2e0a
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_defragmentation_info2-members.html
@@ -0,0 +1,90 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: Member List</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="headertitle">
+<div class="title">VmaDefragmentationInfo2 Member List</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>This is the complete list of members for <a class="el" href="struct_vma_defragmentation_info2.html">VmaDefragmentationInfo2</a>, including all inherited members.</p>
+<table class="directory">
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_defragmentation_info2.html#a3cf86ab32c1da779b4923d301a3056ba">allocationCount</a></td><td class="entry"><a class="el" href="struct_vma_defragmentation_info2.html">VmaDefragmentationInfo2</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_defragmentation_info2.html#a7f71f39590c5316771493d2333f9c1bd">commandBuffer</a></td><td class="entry"><a class="el" href="struct_vma_defragmentation_info2.html">VmaDefragmentationInfo2</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_defragmentation_info2.html#a53e844ee5633e229cf6daf14b2d9fff9">flags</a></td><td class="entry"><a class="el" href="struct_vma_defragmentation_info2.html">VmaDefragmentationInfo2</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_defragmentation_info2.html#a94c2c7223d52878445a8cccce396b671">maxCpuAllocationsToMove</a></td><td class="entry"><a class="el" href="struct_vma_defragmentation_info2.html">VmaDefragmentationInfo2</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_defragmentation_info2.html#af78e1ea40c22d85137b65f6b384a4d0a">maxCpuBytesToMove</a></td><td class="entry"><a class="el" href="struct_vma_defragmentation_info2.html">VmaDefragmentationInfo2</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_defragmentation_info2.html#a40d53d33e71ba0b66f844ed63c05a3f6">maxGpuAllocationsToMove</a></td><td class="entry"><a class="el" href="struct_vma_defragmentation_info2.html">VmaDefragmentationInfo2</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_defragmentation_info2.html#a4ddbc898d0afe1518f863a3763628f08">maxGpuBytesToMove</a></td><td class="entry"><a class="el" href="struct_vma_defragmentation_info2.html">VmaDefragmentationInfo2</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_defragmentation_info2.html#a8943f8d65969ce8e2189a1cdf3205e96">pAllocations</a></td><td class="entry"><a class="el" href="struct_vma_defragmentation_info2.html">VmaDefragmentationInfo2</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_defragmentation_info2.html#a76d51a644dc7f5405d0cdd0025ecd0cc">pAllocationsChanged</a></td><td class="entry"><a class="el" href="struct_vma_defragmentation_info2.html">VmaDefragmentationInfo2</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_defragmentation_info2.html#a7e70aa2a1081d849dcc7829b19d3ec9d">poolCount</a></td><td class="entry"><a class="el" href="struct_vma_defragmentation_info2.html">VmaDefragmentationInfo2</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_defragmentation_info2.html#a0b3effd57f3fcdeb2ed62210b4ef20e1">pPools</a></td><td class="entry"><a class="el" href="struct_vma_defragmentation_info2.html">VmaDefragmentationInfo2</a></td><td class="entry"></td></tr>
+</table></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/struct_vma_defragmentation_info2.html b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_defragmentation_info2.html
new file mode 100644
index 0000000..cc17594
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_defragmentation_info2.html
@@ -0,0 +1,315 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: VmaDefragmentationInfo2 Struct Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="summary">
+<a href="#pub-attribs">Public Attributes</a> &#124;
+<a href="struct_vma_defragmentation_info2-members.html">List of all members</a>  </div>
+  <div class="headertitle">
+<div class="title">VmaDefragmentationInfo2 Struct Reference</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>Parameters for defragmentation.  
+ <a href="struct_vma_defragmentation_info2.html#details">More...</a></p>
+
+<p><code>#include &lt;<a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a>&gt;</code></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="pub-attribs"></a>
+Public Attributes</h2></td></tr>
+<tr class="memitem:a53e844ee5633e229cf6daf14b2d9fff9"><td class="memItemLeft" align="right" valign="top"><a class="el" href="vk__mem__alloc_8h.html#a88a77cef37e5d3c4fc9eb328885d048d">VmaDefragmentationFlags</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_defragmentation_info2.html#a53e844ee5633e229cf6daf14b2d9fff9">flags</a></td></tr>
+<tr class="memdesc:a53e844ee5633e229cf6daf14b2d9fff9"><td class="mdescLeft">&#160;</td><td class="mdescRight">Reserved for future use. Should be 0.  <a href="struct_vma_defragmentation_info2.html#a53e844ee5633e229cf6daf14b2d9fff9">More...</a><br /></td></tr>
+<tr class="separator:a53e844ee5633e229cf6daf14b2d9fff9"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a3cf86ab32c1da779b4923d301a3056ba"><td class="memItemLeft" align="right" valign="top">uint32_t&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_defragmentation_info2.html#a3cf86ab32c1da779b4923d301a3056ba">allocationCount</a></td></tr>
+<tr class="memdesc:a3cf86ab32c1da779b4923d301a3056ba"><td class="mdescLeft">&#160;</td><td class="mdescRight">Number of allocations in <code>pAllocations</code> array.  <a href="struct_vma_defragmentation_info2.html#a3cf86ab32c1da779b4923d301a3056ba">More...</a><br /></td></tr>
+<tr class="separator:a3cf86ab32c1da779b4923d301a3056ba"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a8943f8d65969ce8e2189a1cdf3205e96"><td class="memItemLeft" align="right" valign="top"><a class="el" href="struct_vma_allocation.html">VmaAllocation</a> *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_defragmentation_info2.html#a8943f8d65969ce8e2189a1cdf3205e96">pAllocations</a></td></tr>
+<tr class="memdesc:a8943f8d65969ce8e2189a1cdf3205e96"><td class="mdescLeft">&#160;</td><td class="mdescRight">Pointer to array of allocations that can be defragmented.  <a href="struct_vma_defragmentation_info2.html#a8943f8d65969ce8e2189a1cdf3205e96">More...</a><br /></td></tr>
+<tr class="separator:a8943f8d65969ce8e2189a1cdf3205e96"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a76d51a644dc7f5405d0cdd0025ecd0cc"><td class="memItemLeft" align="right" valign="top">VkBool32 *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_defragmentation_info2.html#a76d51a644dc7f5405d0cdd0025ecd0cc">pAllocationsChanged</a></td></tr>
+<tr class="memdesc:a76d51a644dc7f5405d0cdd0025ecd0cc"><td class="mdescLeft">&#160;</td><td class="mdescRight">Optional, output. Pointer to array that will be filled with information whether the allocation at certain index has been changed during defragmentation.  <a href="struct_vma_defragmentation_info2.html#a76d51a644dc7f5405d0cdd0025ecd0cc">More...</a><br /></td></tr>
+<tr class="separator:a76d51a644dc7f5405d0cdd0025ecd0cc"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a7e70aa2a1081d849dcc7829b19d3ec9d"><td class="memItemLeft" align="right" valign="top">uint32_t&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_defragmentation_info2.html#a7e70aa2a1081d849dcc7829b19d3ec9d">poolCount</a></td></tr>
+<tr class="memdesc:a7e70aa2a1081d849dcc7829b19d3ec9d"><td class="mdescLeft">&#160;</td><td class="mdescRight">Numer of pools in <code>pPools</code> array.  <a href="struct_vma_defragmentation_info2.html#a7e70aa2a1081d849dcc7829b19d3ec9d">More...</a><br /></td></tr>
+<tr class="separator:a7e70aa2a1081d849dcc7829b19d3ec9d"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a0b3effd57f3fcdeb2ed62210b4ef20e1"><td class="memItemLeft" align="right" valign="top"><a class="el" href="struct_vma_pool.html">VmaPool</a> *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_defragmentation_info2.html#a0b3effd57f3fcdeb2ed62210b4ef20e1">pPools</a></td></tr>
+<tr class="memdesc:a0b3effd57f3fcdeb2ed62210b4ef20e1"><td class="mdescLeft">&#160;</td><td class="mdescRight">Either null or pointer to array of pools to be defragmented.  <a href="struct_vma_defragmentation_info2.html#a0b3effd57f3fcdeb2ed62210b4ef20e1">More...</a><br /></td></tr>
+<tr class="separator:a0b3effd57f3fcdeb2ed62210b4ef20e1"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:af78e1ea40c22d85137b65f6b384a4d0a"><td class="memItemLeft" align="right" valign="top">VkDeviceSize&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_defragmentation_info2.html#af78e1ea40c22d85137b65f6b384a4d0a">maxCpuBytesToMove</a></td></tr>
+<tr class="memdesc:af78e1ea40c22d85137b65f6b384a4d0a"><td class="mdescLeft">&#160;</td><td class="mdescRight">Maximum total numbers of bytes that can be copied while moving allocations to different places using transfers on CPU side, like <code>memcpy()</code>, <code>memmove()</code>.  <a href="struct_vma_defragmentation_info2.html#af78e1ea40c22d85137b65f6b384a4d0a">More...</a><br /></td></tr>
+<tr class="separator:af78e1ea40c22d85137b65f6b384a4d0a"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a94c2c7223d52878445a8cccce396b671"><td class="memItemLeft" align="right" valign="top">uint32_t&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_defragmentation_info2.html#a94c2c7223d52878445a8cccce396b671">maxCpuAllocationsToMove</a></td></tr>
+<tr class="memdesc:a94c2c7223d52878445a8cccce396b671"><td class="mdescLeft">&#160;</td><td class="mdescRight">Maximum number of allocations that can be moved to a different place using transfers on CPU side, like <code>memcpy()</code>, <code>memmove()</code>.  <a href="struct_vma_defragmentation_info2.html#a94c2c7223d52878445a8cccce396b671">More...</a><br /></td></tr>
+<tr class="separator:a94c2c7223d52878445a8cccce396b671"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a4ddbc898d0afe1518f863a3763628f08"><td class="memItemLeft" align="right" valign="top">VkDeviceSize&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_defragmentation_info2.html#a4ddbc898d0afe1518f863a3763628f08">maxGpuBytesToMove</a></td></tr>
+<tr class="memdesc:a4ddbc898d0afe1518f863a3763628f08"><td class="mdescLeft">&#160;</td><td class="mdescRight">Maximum total numbers of bytes that can be copied while moving allocations to different places using transfers on GPU side, posted to <code>commandBuffer</code>.  <a href="struct_vma_defragmentation_info2.html#a4ddbc898d0afe1518f863a3763628f08">More...</a><br /></td></tr>
+<tr class="separator:a4ddbc898d0afe1518f863a3763628f08"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a40d53d33e71ba0b66f844ed63c05a3f6"><td class="memItemLeft" align="right" valign="top">uint32_t&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_defragmentation_info2.html#a40d53d33e71ba0b66f844ed63c05a3f6">maxGpuAllocationsToMove</a></td></tr>
+<tr class="memdesc:a40d53d33e71ba0b66f844ed63c05a3f6"><td class="mdescLeft">&#160;</td><td class="mdescRight">Maximum number of allocations that can be moved to a different place using transfers on GPU side, posted to <code>commandBuffer</code>.  <a href="struct_vma_defragmentation_info2.html#a40d53d33e71ba0b66f844ed63c05a3f6">More...</a><br /></td></tr>
+<tr class="separator:a40d53d33e71ba0b66f844ed63c05a3f6"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a7f71f39590c5316771493d2333f9c1bd"><td class="memItemLeft" align="right" valign="top">VkCommandBuffer&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_defragmentation_info2.html#a7f71f39590c5316771493d2333f9c1bd">commandBuffer</a></td></tr>
+<tr class="memdesc:a7f71f39590c5316771493d2333f9c1bd"><td class="mdescLeft">&#160;</td><td class="mdescRight">Optional. Command buffer where GPU copy commands will be posted.  <a href="struct_vma_defragmentation_info2.html#a7f71f39590c5316771493d2333f9c1bd">More...</a><br /></td></tr>
+<tr class="separator:a7f71f39590c5316771493d2333f9c1bd"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<div class="textblock"><p>Parameters for defragmentation. </p>
+<p>To be used with function <a class="el" href="vk__mem__alloc_8h.html#a36ba776fd7fd5cb1e9359fdc0d8e6e8a" title="Begins defragmentation process.">vmaDefragmentationBegin()</a>. </p>
+</div><h2 class="groupheader">Member Data Documentation</h2>
+<a id="a3cf86ab32c1da779b4923d301a3056ba"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a3cf86ab32c1da779b4923d301a3056ba">&#9670;&nbsp;</a></span>allocationCount</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">uint32_t VmaDefragmentationInfo2::allocationCount</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Number of allocations in <code>pAllocations</code> array. </p>
+
+</div>
+</div>
+<a id="a7f71f39590c5316771493d2333f9c1bd"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a7f71f39590c5316771493d2333f9c1bd">&#9670;&nbsp;</a></span>commandBuffer</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkCommandBuffer VmaDefragmentationInfo2::commandBuffer</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Optional. Command buffer where GPU copy commands will be posted. </p>
+<p>If not null, it must be a valid command buffer handle that supports Transfer queue type. It must be in the recording state and outside of a render pass instance. You need to submit it and make sure it finished execution before calling <a class="el" href="vk__mem__alloc_8h.html#a8774e20e91e245aae959ba63efa15dd2" title="Ends defragmentation process.">vmaDefragmentationEnd()</a>.</p>
+<p>Passing null means that only CPU defragmentation will be performed. </p>
+
+</div>
+</div>
+<a id="a53e844ee5633e229cf6daf14b2d9fff9"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a53e844ee5633e229cf6daf14b2d9fff9">&#9670;&nbsp;</a></span>flags</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname"><a class="el" href="vk__mem__alloc_8h.html#a88a77cef37e5d3c4fc9eb328885d048d">VmaDefragmentationFlags</a> VmaDefragmentationInfo2::flags</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Reserved for future use. Should be 0. </p>
+
+</div>
+</div>
+<a id="a94c2c7223d52878445a8cccce396b671"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a94c2c7223d52878445a8cccce396b671">&#9670;&nbsp;</a></span>maxCpuAllocationsToMove</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">uint32_t VmaDefragmentationInfo2::maxCpuAllocationsToMove</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Maximum number of allocations that can be moved to a different place using transfers on CPU side, like <code>memcpy()</code>, <code>memmove()</code>. </p>
+<p><code>UINT32_MAX</code> means no limit. </p>
+
+</div>
+</div>
+<a id="af78e1ea40c22d85137b65f6b384a4d0a"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#af78e1ea40c22d85137b65f6b384a4d0a">&#9670;&nbsp;</a></span>maxCpuBytesToMove</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkDeviceSize VmaDefragmentationInfo2::maxCpuBytesToMove</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Maximum total numbers of bytes that can be copied while moving allocations to different places using transfers on CPU side, like <code>memcpy()</code>, <code>memmove()</code>. </p>
+<p><code>VK_WHOLE_SIZE</code> means no limit. </p>
+
+</div>
+</div>
+<a id="a40d53d33e71ba0b66f844ed63c05a3f6"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a40d53d33e71ba0b66f844ed63c05a3f6">&#9670;&nbsp;</a></span>maxGpuAllocationsToMove</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">uint32_t VmaDefragmentationInfo2::maxGpuAllocationsToMove</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Maximum number of allocations that can be moved to a different place using transfers on GPU side, posted to <code>commandBuffer</code>. </p>
+<p><code>UINT32_MAX</code> means no limit. </p>
+
+</div>
+</div>
+<a id="a4ddbc898d0afe1518f863a3763628f08"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a4ddbc898d0afe1518f863a3763628f08">&#9670;&nbsp;</a></span>maxGpuBytesToMove</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkDeviceSize VmaDefragmentationInfo2::maxGpuBytesToMove</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Maximum total numbers of bytes that can be copied while moving allocations to different places using transfers on GPU side, posted to <code>commandBuffer</code>. </p>
+<p><code>VK_WHOLE_SIZE</code> means no limit. </p>
+
+</div>
+</div>
+<a id="a8943f8d65969ce8e2189a1cdf3205e96"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a8943f8d65969ce8e2189a1cdf3205e96">&#9670;&nbsp;</a></span>pAllocations</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname"><a class="el" href="struct_vma_allocation.html">VmaAllocation</a>* VmaDefragmentationInfo2::pAllocations</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Pointer to array of allocations that can be defragmented. </p>
+<p>The array should have <code>allocationCount</code> elements. The array should not contain nulls. Elements in the array should be unique - same allocation cannot occur twice. It is safe to pass allocations that are in the lost state - they are ignored. All allocations not present in this array are considered non-moveable during this defragmentation. </p>
+
+</div>
+</div>
+<a id="a76d51a644dc7f5405d0cdd0025ecd0cc"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a76d51a644dc7f5405d0cdd0025ecd0cc">&#9670;&nbsp;</a></span>pAllocationsChanged</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkBool32* VmaDefragmentationInfo2::pAllocationsChanged</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Optional, output. Pointer to array that will be filled with information whether the allocation at certain index has been changed during defragmentation. </p>
+<p>The array should have <code>allocationCount</code> elements. You can pass null if you are not interested in this information. </p>
+
+</div>
+</div>
+<a id="a7e70aa2a1081d849dcc7829b19d3ec9d"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a7e70aa2a1081d849dcc7829b19d3ec9d">&#9670;&nbsp;</a></span>poolCount</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">uint32_t VmaDefragmentationInfo2::poolCount</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Numer of pools in <code>pPools</code> array. </p>
+
+</div>
+</div>
+<a id="a0b3effd57f3fcdeb2ed62210b4ef20e1"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a0b3effd57f3fcdeb2ed62210b4ef20e1">&#9670;&nbsp;</a></span>pPools</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname"><a class="el" href="struct_vma_pool.html">VmaPool</a>* VmaDefragmentationInfo2::pPools</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Either null or pointer to array of pools to be defragmented. </p>
+<p>All the allocations in the specified pools can be moved during defragmentation and there is no way to check if they were really moved as in <code>pAllocationsChanged</code>, so you must query all the allocations in all these pools for new <code>VkDeviceMemory</code> and offset using <a class="el" href="vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b" title="Returns current information about specified allocation and atomically marks it as used in current fra...">vmaGetAllocationInfo()</a> if you might need to recreate buffers and images bound to them.</p>
+<p>The array should have <code>poolCount</code> elements. The array should not contain nulls. Elements in the array should be unique - same pool cannot occur twice.</p>
+<p>Using this array is equivalent to specifying all allocations from the pools in <code>pAllocations</code>. It might be more efficient. </p>
+
+</div>
+</div>
+<hr/>The documentation for this struct was generated from the following file:<ul>
+<li><a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a></li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/struct_vma_defragmentation_pass_info-members.html b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_defragmentation_pass_info-members.html
new file mode 100644
index 0000000..dac3985
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_defragmentation_pass_info-members.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: Member List</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="headertitle">
+<div class="title">VmaDefragmentationPassInfo Member List</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>This is the complete list of members for <a class="el" href="struct_vma_defragmentation_pass_info.html">VmaDefragmentationPassInfo</a>, including all inherited members.</p>
+<table class="directory">
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_defragmentation_pass_info.html#ac1086e657ba995f8d1f4e49b83dcfb6c">moveCount</a></td><td class="entry"><a class="el" href="struct_vma_defragmentation_pass_info.html">VmaDefragmentationPassInfo</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_defragmentation_pass_info.html#acbd42d4a3357999da130a95cd99a3792">pMoves</a></td><td class="entry"><a class="el" href="struct_vma_defragmentation_pass_info.html">VmaDefragmentationPassInfo</a></td><td class="entry"></td></tr>
+</table></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/struct_vma_defragmentation_pass_info.html b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_defragmentation_pass_info.html
new file mode 100644
index 0000000..9883984
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_defragmentation_pass_info.html
@@ -0,0 +1,127 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: VmaDefragmentationPassInfo Struct Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="summary">
+<a href="#pub-attribs">Public Attributes</a> &#124;
+<a href="struct_vma_defragmentation_pass_info-members.html">List of all members</a>  </div>
+  <div class="headertitle">
+<div class="title">VmaDefragmentationPassInfo Struct Reference</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>Parameters for incremental defragmentation steps.  
+ <a href="struct_vma_defragmentation_pass_info.html#details">More...</a></p>
+
+<p><code>#include &lt;<a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a>&gt;</code></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="pub-attribs"></a>
+Public Attributes</h2></td></tr>
+<tr class="memitem:ac1086e657ba995f8d1f4e49b83dcfb6c"><td class="memItemLeft" align="right" valign="top">uint32_t&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_defragmentation_pass_info.html#ac1086e657ba995f8d1f4e49b83dcfb6c">moveCount</a></td></tr>
+<tr class="separator:ac1086e657ba995f8d1f4e49b83dcfb6c"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:acbd42d4a3357999da130a95cd99a3792"><td class="memItemLeft" align="right" valign="top"><a class="el" href="struct_vma_defragmentation_pass_move_info.html">VmaDefragmentationPassMoveInfo</a> *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_defragmentation_pass_info.html#acbd42d4a3357999da130a95cd99a3792">pMoves</a></td></tr>
+<tr class="separator:acbd42d4a3357999da130a95cd99a3792"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<div class="textblock"><p>Parameters for incremental defragmentation steps. </p>
+<p>To be used with function <a class="el" href="vk__mem__alloc_8h.html#ac0f01545b6262f7d4d128fc8f8e5c77b">vmaBeginDefragmentationPass()</a>. </p>
+</div><h2 class="groupheader">Member Data Documentation</h2>
+<a id="ac1086e657ba995f8d1f4e49b83dcfb6c"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ac1086e657ba995f8d1f4e49b83dcfb6c">&#9670;&nbsp;</a></span>moveCount</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">uint32_t VmaDefragmentationPassInfo::moveCount</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="acbd42d4a3357999da130a95cd99a3792"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#acbd42d4a3357999da130a95cd99a3792">&#9670;&nbsp;</a></span>pMoves</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname"><a class="el" href="struct_vma_defragmentation_pass_move_info.html">VmaDefragmentationPassMoveInfo</a>* VmaDefragmentationPassInfo::pMoves</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<hr/>The documentation for this struct was generated from the following file:<ul>
+<li><a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a></li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/struct_vma_defragmentation_pass_move_info-members.html b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_defragmentation_pass_move_info-members.html
new file mode 100644
index 0000000..d1f6a69
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_defragmentation_pass_move_info-members.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: Member List</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="headertitle">
+<div class="title">VmaDefragmentationPassMoveInfo Member List</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>This is the complete list of members for <a class="el" href="struct_vma_defragmentation_pass_move_info.html">VmaDefragmentationPassMoveInfo</a>, including all inherited members.</p>
+<table class="directory">
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_defragmentation_pass_move_info.html#ae885c861c2dd8d622e6c19e281d035cc">allocation</a></td><td class="entry"><a class="el" href="struct_vma_defragmentation_pass_move_info.html">VmaDefragmentationPassMoveInfo</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_defragmentation_pass_move_info.html#a06eb0c8690aa0d3478a036753492e769">memory</a></td><td class="entry"><a class="el" href="struct_vma_defragmentation_pass_move_info.html">VmaDefragmentationPassMoveInfo</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_defragmentation_pass_move_info.html#a8ab4508bc03625b0653c880576be96c6">offset</a></td><td class="entry"><a class="el" href="struct_vma_defragmentation_pass_move_info.html">VmaDefragmentationPassMoveInfo</a></td><td class="entry"></td></tr>
+</table></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/struct_vma_defragmentation_pass_move_info.html b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_defragmentation_pass_move_info.html
new file mode 100644
index 0000000..b73d936
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_defragmentation_pass_move_info.html
@@ -0,0 +1,137 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: VmaDefragmentationPassMoveInfo Struct Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="summary">
+<a href="#pub-attribs">Public Attributes</a> &#124;
+<a href="struct_vma_defragmentation_pass_move_info-members.html">List of all members</a>  </div>
+  <div class="headertitle">
+<div class="title">VmaDefragmentationPassMoveInfo Struct Reference</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p><code>#include &lt;<a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a>&gt;</code></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="pub-attribs"></a>
+Public Attributes</h2></td></tr>
+<tr class="memitem:ae885c861c2dd8d622e6c19e281d035cc"><td class="memItemLeft" align="right" valign="top"><a class="el" href="struct_vma_allocation.html">VmaAllocation</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_defragmentation_pass_move_info.html#ae885c861c2dd8d622e6c19e281d035cc">allocation</a></td></tr>
+<tr class="separator:ae885c861c2dd8d622e6c19e281d035cc"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a06eb0c8690aa0d3478a036753492e769"><td class="memItemLeft" align="right" valign="top">VkDeviceMemory&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_defragmentation_pass_move_info.html#a06eb0c8690aa0d3478a036753492e769">memory</a></td></tr>
+<tr class="separator:a06eb0c8690aa0d3478a036753492e769"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a8ab4508bc03625b0653c880576be96c6"><td class="memItemLeft" align="right" valign="top">VkDeviceSize&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_defragmentation_pass_move_info.html#a8ab4508bc03625b0653c880576be96c6">offset</a></td></tr>
+<tr class="separator:a8ab4508bc03625b0653c880576be96c6"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<h2 class="groupheader">Member Data Documentation</h2>
+<a id="ae885c861c2dd8d622e6c19e281d035cc"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ae885c861c2dd8d622e6c19e281d035cc">&#9670;&nbsp;</a></span>allocation</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname"><a class="el" href="struct_vma_allocation.html">VmaAllocation</a> VmaDefragmentationPassMoveInfo::allocation</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="a06eb0c8690aa0d3478a036753492e769"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a06eb0c8690aa0d3478a036753492e769">&#9670;&nbsp;</a></span>memory</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkDeviceMemory VmaDefragmentationPassMoveInfo::memory</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="a8ab4508bc03625b0653c880576be96c6"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a8ab4508bc03625b0653c880576be96c6">&#9670;&nbsp;</a></span>offset</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkDeviceSize VmaDefragmentationPassMoveInfo::offset</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<hr/>The documentation for this struct was generated from the following file:<ul>
+<li><a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a></li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/struct_vma_defragmentation_stats-members.html b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_defragmentation_stats-members.html
new file mode 100644
index 0000000..b467d79
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_defragmentation_stats-members.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: Member List</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="headertitle">
+<div class="title">VmaDefragmentationStats Member List</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>This is the complete list of members for <a class="el" href="struct_vma_defragmentation_stats.html">VmaDefragmentationStats</a>, including all inherited members.</p>
+<table class="directory">
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_defragmentation_stats.html#aefeabf130022008eadd75999478af3f9">allocationsMoved</a></td><td class="entry"><a class="el" href="struct_vma_defragmentation_stats.html">VmaDefragmentationStats</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_defragmentation_stats.html#ab0cb9ac0dbc106c77e384ea676422f28">bytesFreed</a></td><td class="entry"><a class="el" href="struct_vma_defragmentation_stats.html">VmaDefragmentationStats</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_defragmentation_stats.html#a36f9d5df2a10ba2a36b16e126d60572d">bytesMoved</a></td><td class="entry"><a class="el" href="struct_vma_defragmentation_stats.html">VmaDefragmentationStats</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_defragmentation_stats.html#a0113f1877904a5d1ee8f409216ff276b">deviceMemoryBlocksFreed</a></td><td class="entry"><a class="el" href="struct_vma_defragmentation_stats.html">VmaDefragmentationStats</a></td><td class="entry"></td></tr>
+</table></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/struct_vma_defragmentation_stats.html b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_defragmentation_stats.html
new file mode 100644
index 0000000..92efa3f
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_defragmentation_stats.html
@@ -0,0 +1,170 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: VmaDefragmentationStats Struct Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="summary">
+<a href="#pub-attribs">Public Attributes</a> &#124;
+<a href="struct_vma_defragmentation_stats-members.html">List of all members</a>  </div>
+  <div class="headertitle">
+<div class="title">VmaDefragmentationStats Struct Reference</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>Statistics returned by function <a class="el" href="vk__mem__alloc_8h.html#a6aced90fcc7b39882b6654a740a0b9bb" title="Deprecated. Compacts memory by moving allocations.">vmaDefragment()</a>.  
+ <a href="struct_vma_defragmentation_stats.html#details">More...</a></p>
+
+<p><code>#include &lt;<a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a>&gt;</code></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="pub-attribs"></a>
+Public Attributes</h2></td></tr>
+<tr class="memitem:a36f9d5df2a10ba2a36b16e126d60572d"><td class="memItemLeft" align="right" valign="top">VkDeviceSize&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_defragmentation_stats.html#a36f9d5df2a10ba2a36b16e126d60572d">bytesMoved</a></td></tr>
+<tr class="memdesc:a36f9d5df2a10ba2a36b16e126d60572d"><td class="mdescLeft">&#160;</td><td class="mdescRight">Total number of bytes that have been copied while moving allocations to different places.  <a href="struct_vma_defragmentation_stats.html#a36f9d5df2a10ba2a36b16e126d60572d">More...</a><br /></td></tr>
+<tr class="separator:a36f9d5df2a10ba2a36b16e126d60572d"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ab0cb9ac0dbc106c77e384ea676422f28"><td class="memItemLeft" align="right" valign="top">VkDeviceSize&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_defragmentation_stats.html#ab0cb9ac0dbc106c77e384ea676422f28">bytesFreed</a></td></tr>
+<tr class="memdesc:ab0cb9ac0dbc106c77e384ea676422f28"><td class="mdescLeft">&#160;</td><td class="mdescRight">Total number of bytes that have been released to the system by freeing empty <code>VkDeviceMemory</code> objects.  <a href="struct_vma_defragmentation_stats.html#ab0cb9ac0dbc106c77e384ea676422f28">More...</a><br /></td></tr>
+<tr class="separator:ab0cb9ac0dbc106c77e384ea676422f28"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:aefeabf130022008eadd75999478af3f9"><td class="memItemLeft" align="right" valign="top">uint32_t&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_defragmentation_stats.html#aefeabf130022008eadd75999478af3f9">allocationsMoved</a></td></tr>
+<tr class="memdesc:aefeabf130022008eadd75999478af3f9"><td class="mdescLeft">&#160;</td><td class="mdescRight">Number of allocations that have been moved to different places.  <a href="struct_vma_defragmentation_stats.html#aefeabf130022008eadd75999478af3f9">More...</a><br /></td></tr>
+<tr class="separator:aefeabf130022008eadd75999478af3f9"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a0113f1877904a5d1ee8f409216ff276b"><td class="memItemLeft" align="right" valign="top">uint32_t&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_defragmentation_stats.html#a0113f1877904a5d1ee8f409216ff276b">deviceMemoryBlocksFreed</a></td></tr>
+<tr class="memdesc:a0113f1877904a5d1ee8f409216ff276b"><td class="mdescLeft">&#160;</td><td class="mdescRight">Number of empty <code>VkDeviceMemory</code> objects that have been released to the system.  <a href="struct_vma_defragmentation_stats.html#a0113f1877904a5d1ee8f409216ff276b">More...</a><br /></td></tr>
+<tr class="separator:a0113f1877904a5d1ee8f409216ff276b"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<div class="textblock"><p>Statistics returned by function <a class="el" href="vk__mem__alloc_8h.html#a6aced90fcc7b39882b6654a740a0b9bb" title="Deprecated. Compacts memory by moving allocations.">vmaDefragment()</a>. </p>
+</div><h2 class="groupheader">Member Data Documentation</h2>
+<a id="aefeabf130022008eadd75999478af3f9"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#aefeabf130022008eadd75999478af3f9">&#9670;&nbsp;</a></span>allocationsMoved</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">uint32_t VmaDefragmentationStats::allocationsMoved</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Number of allocations that have been moved to different places. </p>
+
+</div>
+</div>
+<a id="ab0cb9ac0dbc106c77e384ea676422f28"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ab0cb9ac0dbc106c77e384ea676422f28">&#9670;&nbsp;</a></span>bytesFreed</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkDeviceSize VmaDefragmentationStats::bytesFreed</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Total number of bytes that have been released to the system by freeing empty <code>VkDeviceMemory</code> objects. </p>
+
+</div>
+</div>
+<a id="a36f9d5df2a10ba2a36b16e126d60572d"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a36f9d5df2a10ba2a36b16e126d60572d">&#9670;&nbsp;</a></span>bytesMoved</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkDeviceSize VmaDefragmentationStats::bytesMoved</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Total number of bytes that have been copied while moving allocations to different places. </p>
+
+</div>
+</div>
+<a id="a0113f1877904a5d1ee8f409216ff276b"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a0113f1877904a5d1ee8f409216ff276b">&#9670;&nbsp;</a></span>deviceMemoryBlocksFreed</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">uint32_t VmaDefragmentationStats::deviceMemoryBlocksFreed</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Number of empty <code>VkDeviceMemory</code> objects that have been released to the system. </p>
+
+</div>
+</div>
+<hr/>The documentation for this struct was generated from the following file:<ul>
+<li><a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a></li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/struct_vma_device_memory_callbacks-members.html b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_device_memory_callbacks-members.html
new file mode 100644
index 0000000..5f78791
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_device_memory_callbacks-members.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: Member List</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="headertitle">
+<div class="title">VmaDeviceMemoryCallbacks Member List</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>This is the complete list of members for <a class="el" href="struct_vma_device_memory_callbacks.html">VmaDeviceMemoryCallbacks</a>, including all inherited members.</p>
+<table class="directory">
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_device_memory_callbacks.html#a4f17f7b255101e733b44d5633aceabfb">pfnAllocate</a></td><td class="entry"><a class="el" href="struct_vma_device_memory_callbacks.html">VmaDeviceMemoryCallbacks</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_device_memory_callbacks.html#abe8a3328bbc916f6f712fdb6b299444c">pfnFree</a></td><td class="entry"><a class="el" href="struct_vma_device_memory_callbacks.html">VmaDeviceMemoryCallbacks</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_device_memory_callbacks.html#a24052de0937ddd54015a2df0363903c6">pUserData</a></td><td class="entry"><a class="el" href="struct_vma_device_memory_callbacks.html">VmaDeviceMemoryCallbacks</a></td><td class="entry"></td></tr>
+</table></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/struct_vma_device_memory_callbacks.html b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_device_memory_callbacks.html
new file mode 100644
index 0000000..21d232a
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_device_memory_callbacks.html
@@ -0,0 +1,153 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: VmaDeviceMemoryCallbacks Struct Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="summary">
+<a href="#pub-attribs">Public Attributes</a> &#124;
+<a href="struct_vma_device_memory_callbacks-members.html">List of all members</a>  </div>
+  <div class="headertitle">
+<div class="title">VmaDeviceMemoryCallbacks Struct Reference</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>Set of callbacks that the library will call for <code>vkAllocateMemory</code> and <code>vkFreeMemory</code>.  
+ <a href="struct_vma_device_memory_callbacks.html#details">More...</a></p>
+
+<p><code>#include &lt;<a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a>&gt;</code></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="pub-attribs"></a>
+Public Attributes</h2></td></tr>
+<tr class="memitem:a4f17f7b255101e733b44d5633aceabfb"><td class="memItemLeft" align="right" valign="top"><a class="el" href="vk__mem__alloc_8h.html#a7e1ed85f7799600b03ad51a77acc21f3">PFN_vmaAllocateDeviceMemoryFunction</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_device_memory_callbacks.html#a4f17f7b255101e733b44d5633aceabfb">pfnAllocate</a></td></tr>
+<tr class="memdesc:a4f17f7b255101e733b44d5633aceabfb"><td class="mdescLeft">&#160;</td><td class="mdescRight">Optional, can be null.  <a href="struct_vma_device_memory_callbacks.html#a4f17f7b255101e733b44d5633aceabfb">More...</a><br /></td></tr>
+<tr class="separator:a4f17f7b255101e733b44d5633aceabfb"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:abe8a3328bbc916f6f712fdb6b299444c"><td class="memItemLeft" align="right" valign="top"><a class="el" href="vk__mem__alloc_8h.html#a154ccaaf53dc2c36378f80f0c4f3679b">PFN_vmaFreeDeviceMemoryFunction</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_device_memory_callbacks.html#abe8a3328bbc916f6f712fdb6b299444c">pfnFree</a></td></tr>
+<tr class="memdesc:abe8a3328bbc916f6f712fdb6b299444c"><td class="mdescLeft">&#160;</td><td class="mdescRight">Optional, can be null.  <a href="struct_vma_device_memory_callbacks.html#abe8a3328bbc916f6f712fdb6b299444c">More...</a><br /></td></tr>
+<tr class="separator:abe8a3328bbc916f6f712fdb6b299444c"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a24052de0937ddd54015a2df0363903c6"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_device_memory_callbacks.html#a24052de0937ddd54015a2df0363903c6">pUserData</a></td></tr>
+<tr class="memdesc:a24052de0937ddd54015a2df0363903c6"><td class="mdescLeft">&#160;</td><td class="mdescRight">Optional, can be null.  <a href="struct_vma_device_memory_callbacks.html#a24052de0937ddd54015a2df0363903c6">More...</a><br /></td></tr>
+<tr class="separator:a24052de0937ddd54015a2df0363903c6"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<div class="textblock"><p>Set of callbacks that the library will call for <code>vkAllocateMemory</code> and <code>vkFreeMemory</code>. </p>
+<p>Provided for informative purpose, e.g. to gather statistics about number of allocations or total amount of memory allocated in Vulkan.</p>
+<p>Used in <a class="el" href="struct_vma_allocator_create_info.html#af1380969b5e1ea4c3184a877892d260e" title="Informative callbacks for vkAllocateMemory, vkFreeMemory. Optional.">VmaAllocatorCreateInfo::pDeviceMemoryCallbacks</a>. </p>
+</div><h2 class="groupheader">Member Data Documentation</h2>
+<a id="a4f17f7b255101e733b44d5633aceabfb"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a4f17f7b255101e733b44d5633aceabfb">&#9670;&nbsp;</a></span>pfnAllocate</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname"><a class="el" href="vk__mem__alloc_8h.html#a7e1ed85f7799600b03ad51a77acc21f3">PFN_vmaAllocateDeviceMemoryFunction</a> VmaDeviceMemoryCallbacks::pfnAllocate</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Optional, can be null. </p>
+
+</div>
+</div>
+<a id="abe8a3328bbc916f6f712fdb6b299444c"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#abe8a3328bbc916f6f712fdb6b299444c">&#9670;&nbsp;</a></span>pfnFree</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname"><a class="el" href="vk__mem__alloc_8h.html#a154ccaaf53dc2c36378f80f0c4f3679b">PFN_vmaFreeDeviceMemoryFunction</a> VmaDeviceMemoryCallbacks::pfnFree</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Optional, can be null. </p>
+
+</div>
+</div>
+<a id="a24052de0937ddd54015a2df0363903c6"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a24052de0937ddd54015a2df0363903c6">&#9670;&nbsp;</a></span>pUserData</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void* VmaDeviceMemoryCallbacks::pUserData</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Optional, can be null. </p>
+
+</div>
+</div>
+<hr/>The documentation for this struct was generated from the following file:<ul>
+<li><a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a></li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/struct_vma_pool.html b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_pool.html
new file mode 100644
index 0000000..e1afc02
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_pool.html
@@ -0,0 +1,88 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: VmaPool Struct Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="headertitle">
+<div class="title">VmaPool Struct Reference</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>Represents custom memory pool.  
+ <a href="struct_vma_pool.html#details">More...</a></p>
+
+<p><code>#include &lt;<a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a>&gt;</code></p>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<div class="textblock"><p>Represents custom memory pool. </p>
+<p>Fill structure <a class="el" href="struct_vma_pool_create_info.html" title="Describes parameter of created VmaPool.">VmaPoolCreateInfo</a> and call function <a class="el" href="vk__mem__alloc_8h.html#a5c8770ded7c59c8caac6de0c2cb00b50" title="Allocates Vulkan device memory and creates VmaPool object.">vmaCreatePool()</a> to create it. Call function <a class="el" href="vk__mem__alloc_8h.html#a5485779c8f1948238fc4e92232fa65e1" title="Destroys VmaPool object and frees Vulkan device memory.">vmaDestroyPool()</a> to destroy it.</p>
+<p>For more information see <a class="el" href="choosing_memory_type.html#choosing_memory_type_custom_memory_pools">Custom memory pools</a>. </p>
+</div><hr/>The documentation for this struct was generated from the following file:<ul>
+<li><a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a></li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/struct_vma_pool_create_info-members.html b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_pool_create_info-members.html
new file mode 100644
index 0000000..c2dcafb
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_pool_create_info-members.html
@@ -0,0 +1,85 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: Member List</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="headertitle">
+<div class="title">VmaPoolCreateInfo Member List</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>This is the complete list of members for <a class="el" href="struct_vma_pool_create_info.html">VmaPoolCreateInfo</a>, including all inherited members.</p>
+<table class="directory">
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_pool_create_info.html#aa4265160536cdb9be821b7686c16c676">blockSize</a></td><td class="entry"><a class="el" href="struct_vma_pool_create_info.html">VmaPoolCreateInfo</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_pool_create_info.html#a8405139f63d078340ae74513a59f5446">flags</a></td><td class="entry"><a class="el" href="struct_vma_pool_create_info.html">VmaPoolCreateInfo</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_pool_create_info.html#a9437e43ffbb644dbbf7fc4e50cfad6aa">frameInUseCount</a></td><td class="entry"><a class="el" href="struct_vma_pool_create_info.html">VmaPoolCreateInfo</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_pool_create_info.html#ae41142f2834fcdc82baa4883c187b75c">maxBlockCount</a></td><td class="entry"><a class="el" href="struct_vma_pool_create_info.html">VmaPoolCreateInfo</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_pool_create_info.html#a596fa76b685d3f1f688f84a709a5b319">memoryTypeIndex</a></td><td class="entry"><a class="el" href="struct_vma_pool_create_info.html">VmaPoolCreateInfo</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_pool_create_info.html#ad8006fb803185c0a699d30f3e9a865ae">minBlockCount</a></td><td class="entry"><a class="el" href="struct_vma_pool_create_info.html">VmaPoolCreateInfo</a></td><td class="entry"></td></tr>
+</table></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/struct_vma_pool_create_info.html b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_pool_create_info.html
new file mode 100644
index 0000000..a34ceb1
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_pool_create_info.html
@@ -0,0 +1,216 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: VmaPoolCreateInfo Struct Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="summary">
+<a href="#pub-attribs">Public Attributes</a> &#124;
+<a href="struct_vma_pool_create_info-members.html">List of all members</a>  </div>
+  <div class="headertitle">
+<div class="title">VmaPoolCreateInfo Struct Reference</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>Describes parameter of created <a class="el" href="struct_vma_pool.html" title="Represents custom memory pool.">VmaPool</a>.  
+ <a href="struct_vma_pool_create_info.html#details">More...</a></p>
+
+<p><code>#include &lt;<a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a>&gt;</code></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="pub-attribs"></a>
+Public Attributes</h2></td></tr>
+<tr class="memitem:a596fa76b685d3f1f688f84a709a5b319"><td class="memItemLeft" align="right" valign="top">uint32_t&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_pool_create_info.html#a596fa76b685d3f1f688f84a709a5b319">memoryTypeIndex</a></td></tr>
+<tr class="memdesc:a596fa76b685d3f1f688f84a709a5b319"><td class="mdescLeft">&#160;</td><td class="mdescRight">Vulkan memory type index to allocate this pool from.  <a href="struct_vma_pool_create_info.html#a596fa76b685d3f1f688f84a709a5b319">More...</a><br /></td></tr>
+<tr class="separator:a596fa76b685d3f1f688f84a709a5b319"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a8405139f63d078340ae74513a59f5446"><td class="memItemLeft" align="right" valign="top"><a class="el" href="vk__mem__alloc_8h.html#a2770e325ea42e087c1b91fdf46d0292a">VmaPoolCreateFlags</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_pool_create_info.html#a8405139f63d078340ae74513a59f5446">flags</a></td></tr>
+<tr class="memdesc:a8405139f63d078340ae74513a59f5446"><td class="mdescLeft">&#160;</td><td class="mdescRight">Use combination of <a class="el" href="vk__mem__alloc_8h.html#a4d4f2efc2509157a9e4ecd4fd7942303" title="Flags to be passed as VmaPoolCreateInfo::flags.">VmaPoolCreateFlagBits</a>.  <a href="struct_vma_pool_create_info.html#a8405139f63d078340ae74513a59f5446">More...</a><br /></td></tr>
+<tr class="separator:a8405139f63d078340ae74513a59f5446"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:aa4265160536cdb9be821b7686c16c676"><td class="memItemLeft" align="right" valign="top">VkDeviceSize&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_pool_create_info.html#aa4265160536cdb9be821b7686c16c676">blockSize</a></td></tr>
+<tr class="memdesc:aa4265160536cdb9be821b7686c16c676"><td class="mdescLeft">&#160;</td><td class="mdescRight">Size of a single <code>VkDeviceMemory</code> block to be allocated as part of this pool, in bytes. Optional.  <a href="struct_vma_pool_create_info.html#aa4265160536cdb9be821b7686c16c676">More...</a><br /></td></tr>
+<tr class="separator:aa4265160536cdb9be821b7686c16c676"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ad8006fb803185c0a699d30f3e9a865ae"><td class="memItemLeft" align="right" valign="top">size_t&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_pool_create_info.html#ad8006fb803185c0a699d30f3e9a865ae">minBlockCount</a></td></tr>
+<tr class="memdesc:ad8006fb803185c0a699d30f3e9a865ae"><td class="mdescLeft">&#160;</td><td class="mdescRight">Minimum number of blocks to be always allocated in this pool, even if they stay empty.  <a href="struct_vma_pool_create_info.html#ad8006fb803185c0a699d30f3e9a865ae">More...</a><br /></td></tr>
+<tr class="separator:ad8006fb803185c0a699d30f3e9a865ae"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ae41142f2834fcdc82baa4883c187b75c"><td class="memItemLeft" align="right" valign="top">size_t&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_pool_create_info.html#ae41142f2834fcdc82baa4883c187b75c">maxBlockCount</a></td></tr>
+<tr class="memdesc:ae41142f2834fcdc82baa4883c187b75c"><td class="mdescLeft">&#160;</td><td class="mdescRight">Maximum number of blocks that can be allocated in this pool. Optional.  <a href="struct_vma_pool_create_info.html#ae41142f2834fcdc82baa4883c187b75c">More...</a><br /></td></tr>
+<tr class="separator:ae41142f2834fcdc82baa4883c187b75c"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a9437e43ffbb644dbbf7fc4e50cfad6aa"><td class="memItemLeft" align="right" valign="top">uint32_t&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_pool_create_info.html#a9437e43ffbb644dbbf7fc4e50cfad6aa">frameInUseCount</a></td></tr>
+<tr class="memdesc:a9437e43ffbb644dbbf7fc4e50cfad6aa"><td class="mdescLeft">&#160;</td><td class="mdescRight">Maximum number of additional frames that are in use at the same time as current frame.  <a href="struct_vma_pool_create_info.html#a9437e43ffbb644dbbf7fc4e50cfad6aa">More...</a><br /></td></tr>
+<tr class="separator:a9437e43ffbb644dbbf7fc4e50cfad6aa"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<div class="textblock"><p>Describes parameter of created <a class="el" href="struct_vma_pool.html" title="Represents custom memory pool.">VmaPool</a>. </p>
+</div><h2 class="groupheader">Member Data Documentation</h2>
+<a id="aa4265160536cdb9be821b7686c16c676"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#aa4265160536cdb9be821b7686c16c676">&#9670;&nbsp;</a></span>blockSize</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkDeviceSize VmaPoolCreateInfo::blockSize</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Size of a single <code>VkDeviceMemory</code> block to be allocated as part of this pool, in bytes. Optional. </p>
+<p>Specify nonzero to set explicit, constant size of memory blocks used by this pool.</p>
+<p>Leave 0 to use default and let the library manage block sizes automatically. Sizes of particular blocks may vary. </p>
+
+</div>
+</div>
+<a id="a8405139f63d078340ae74513a59f5446"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a8405139f63d078340ae74513a59f5446">&#9670;&nbsp;</a></span>flags</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname"><a class="el" href="vk__mem__alloc_8h.html#a2770e325ea42e087c1b91fdf46d0292a">VmaPoolCreateFlags</a> VmaPoolCreateInfo::flags</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Use combination of <a class="el" href="vk__mem__alloc_8h.html#a4d4f2efc2509157a9e4ecd4fd7942303" title="Flags to be passed as VmaPoolCreateInfo::flags.">VmaPoolCreateFlagBits</a>. </p>
+
+</div>
+</div>
+<a id="a9437e43ffbb644dbbf7fc4e50cfad6aa"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a9437e43ffbb644dbbf7fc4e50cfad6aa">&#9670;&nbsp;</a></span>frameInUseCount</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">uint32_t VmaPoolCreateInfo::frameInUseCount</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Maximum number of additional frames that are in use at the same time as current frame. </p>
+<p>This value is used only when you make allocations with <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a5f436af6c8fe8540573a6d22627a6fd2">VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT</a> flag. Such allocation cannot become lost if allocation.lastUseFrameIndex &gt;= allocator.currentFrameIndex - frameInUseCount.</p>
+<p>For example, if you double-buffer your command buffers, so resources used for rendering in previous frame may still be in use by the GPU at the moment you allocate resources needed for the current frame, set this value to 1.</p>
+<p>If you want to allow any allocations other than used in the current frame to become lost, set this value to 0. </p>
+
+</div>
+</div>
+<a id="ae41142f2834fcdc82baa4883c187b75c"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ae41142f2834fcdc82baa4883c187b75c">&#9670;&nbsp;</a></span>maxBlockCount</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">size_t VmaPoolCreateInfo::maxBlockCount</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Maximum number of blocks that can be allocated in this pool. Optional. </p>
+<p>Set to 0 to use default, which is <code>SIZE_MAX</code>, which means no limit.</p>
+<p>Set to same value as <a class="el" href="struct_vma_pool_create_info.html#ad8006fb803185c0a699d30f3e9a865ae" title="Minimum number of blocks to be always allocated in this pool, even if they stay empty.">VmaPoolCreateInfo::minBlockCount</a> to have fixed amount of memory allocated throughout whole lifetime of this pool. </p>
+
+</div>
+</div>
+<a id="a596fa76b685d3f1f688f84a709a5b319"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a596fa76b685d3f1f688f84a709a5b319">&#9670;&nbsp;</a></span>memoryTypeIndex</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">uint32_t VmaPoolCreateInfo::memoryTypeIndex</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Vulkan memory type index to allocate this pool from. </p>
+
+</div>
+</div>
+<a id="ad8006fb803185c0a699d30f3e9a865ae"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ad8006fb803185c0a699d30f3e9a865ae">&#9670;&nbsp;</a></span>minBlockCount</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">size_t VmaPoolCreateInfo::minBlockCount</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Minimum number of blocks to be always allocated in this pool, even if they stay empty. </p>
+<p>Set to 0 to have no preallocated blocks and allow the pool be completely empty. </p>
+
+</div>
+</div>
+<hr/>The documentation for this struct was generated from the following file:<ul>
+<li><a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a></li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/struct_vma_pool_stats-members.html b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_pool_stats-members.html
new file mode 100644
index 0000000..979e71d
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_pool_stats-members.html
@@ -0,0 +1,85 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: Member List</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="headertitle">
+<div class="title">VmaPoolStats Member List</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>This is the complete list of members for <a class="el" href="struct_vma_pool_stats.html">VmaPoolStats</a>, including all inherited members.</p>
+<table class="directory">
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_pool_stats.html#ad1924eb54fffa45e9e0e65670c8fe5eb">allocationCount</a></td><td class="entry"><a class="el" href="struct_vma_pool_stats.html">VmaPoolStats</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_pool_stats.html#aa0b5cb45cef6f18571cefb03b9a230e7">blockCount</a></td><td class="entry"><a class="el" href="struct_vma_pool_stats.html">VmaPoolStats</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_pool_stats.html#a326807b2de2b0931cee4ed9a5f2e420c">size</a></td><td class="entry"><a class="el" href="struct_vma_pool_stats.html">VmaPoolStats</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_pool_stats.html#ae4f3546ffa4d1e598b64d8e6134854f4">unusedRangeCount</a></td><td class="entry"><a class="el" href="struct_vma_pool_stats.html">VmaPoolStats</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_pool_stats.html#ab4c8f52dd42ab01998f60f0b6acc722b">unusedRangeSizeMax</a></td><td class="entry"><a class="el" href="struct_vma_pool_stats.html">VmaPoolStats</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_pool_stats.html#ad7c54874724fce7b06aba526202d82a8">unusedSize</a></td><td class="entry"><a class="el" href="struct_vma_pool_stats.html">VmaPoolStats</a></td><td class="entry"></td></tr>
+</table></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/struct_vma_pool_stats.html b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_pool_stats.html
new file mode 100644
index 0000000..7486542
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_pool_stats.html
@@ -0,0 +1,209 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: VmaPoolStats Struct Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="summary">
+<a href="#pub-attribs">Public Attributes</a> &#124;
+<a href="struct_vma_pool_stats-members.html">List of all members</a>  </div>
+  <div class="headertitle">
+<div class="title">VmaPoolStats Struct Reference</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>Describes parameter of existing <a class="el" href="struct_vma_pool.html" title="Represents custom memory pool.">VmaPool</a>.  
+ <a href="struct_vma_pool_stats.html#details">More...</a></p>
+
+<p><code>#include &lt;<a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a>&gt;</code></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="pub-attribs"></a>
+Public Attributes</h2></td></tr>
+<tr class="memitem:a326807b2de2b0931cee4ed9a5f2e420c"><td class="memItemLeft" align="right" valign="top">VkDeviceSize&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_pool_stats.html#a326807b2de2b0931cee4ed9a5f2e420c">size</a></td></tr>
+<tr class="memdesc:a326807b2de2b0931cee4ed9a5f2e420c"><td class="mdescLeft">&#160;</td><td class="mdescRight">Total amount of <code>VkDeviceMemory</code> allocated from Vulkan for this pool, in bytes.  <a href="struct_vma_pool_stats.html#a326807b2de2b0931cee4ed9a5f2e420c">More...</a><br /></td></tr>
+<tr class="separator:a326807b2de2b0931cee4ed9a5f2e420c"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ad7c54874724fce7b06aba526202d82a8"><td class="memItemLeft" align="right" valign="top">VkDeviceSize&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_pool_stats.html#ad7c54874724fce7b06aba526202d82a8">unusedSize</a></td></tr>
+<tr class="memdesc:ad7c54874724fce7b06aba526202d82a8"><td class="mdescLeft">&#160;</td><td class="mdescRight">Total number of bytes in the pool not used by any <a class="el" href="struct_vma_allocation.html" title="Represents single memory allocation.">VmaAllocation</a>.  <a href="struct_vma_pool_stats.html#ad7c54874724fce7b06aba526202d82a8">More...</a><br /></td></tr>
+<tr class="separator:ad7c54874724fce7b06aba526202d82a8"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ad1924eb54fffa45e9e0e65670c8fe5eb"><td class="memItemLeft" align="right" valign="top">size_t&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_pool_stats.html#ad1924eb54fffa45e9e0e65670c8fe5eb">allocationCount</a></td></tr>
+<tr class="memdesc:ad1924eb54fffa45e9e0e65670c8fe5eb"><td class="mdescLeft">&#160;</td><td class="mdescRight">Number of <a class="el" href="struct_vma_allocation.html" title="Represents single memory allocation.">VmaAllocation</a> objects created from this pool that were not destroyed or lost.  <a href="struct_vma_pool_stats.html#ad1924eb54fffa45e9e0e65670c8fe5eb">More...</a><br /></td></tr>
+<tr class="separator:ad1924eb54fffa45e9e0e65670c8fe5eb"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ae4f3546ffa4d1e598b64d8e6134854f4"><td class="memItemLeft" align="right" valign="top">size_t&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_pool_stats.html#ae4f3546ffa4d1e598b64d8e6134854f4">unusedRangeCount</a></td></tr>
+<tr class="memdesc:ae4f3546ffa4d1e598b64d8e6134854f4"><td class="mdescLeft">&#160;</td><td class="mdescRight">Number of continuous memory ranges in the pool not used by any <a class="el" href="struct_vma_allocation.html" title="Represents single memory allocation.">VmaAllocation</a>.  <a href="struct_vma_pool_stats.html#ae4f3546ffa4d1e598b64d8e6134854f4">More...</a><br /></td></tr>
+<tr class="separator:ae4f3546ffa4d1e598b64d8e6134854f4"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ab4c8f52dd42ab01998f60f0b6acc722b"><td class="memItemLeft" align="right" valign="top">VkDeviceSize&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_pool_stats.html#ab4c8f52dd42ab01998f60f0b6acc722b">unusedRangeSizeMax</a></td></tr>
+<tr class="memdesc:ab4c8f52dd42ab01998f60f0b6acc722b"><td class="mdescLeft">&#160;</td><td class="mdescRight">Size of the largest continuous free memory region available for new allocation.  <a href="struct_vma_pool_stats.html#ab4c8f52dd42ab01998f60f0b6acc722b">More...</a><br /></td></tr>
+<tr class="separator:ab4c8f52dd42ab01998f60f0b6acc722b"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:aa0b5cb45cef6f18571cefb03b9a230e7"><td class="memItemLeft" align="right" valign="top">size_t&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_pool_stats.html#aa0b5cb45cef6f18571cefb03b9a230e7">blockCount</a></td></tr>
+<tr class="memdesc:aa0b5cb45cef6f18571cefb03b9a230e7"><td class="mdescLeft">&#160;</td><td class="mdescRight">Number of <code>VkDeviceMemory</code> blocks allocated for this pool.  <a href="struct_vma_pool_stats.html#aa0b5cb45cef6f18571cefb03b9a230e7">More...</a><br /></td></tr>
+<tr class="separator:aa0b5cb45cef6f18571cefb03b9a230e7"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<div class="textblock"><p>Describes parameter of existing <a class="el" href="struct_vma_pool.html" title="Represents custom memory pool.">VmaPool</a>. </p>
+</div><h2 class="groupheader">Member Data Documentation</h2>
+<a id="ad1924eb54fffa45e9e0e65670c8fe5eb"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ad1924eb54fffa45e9e0e65670c8fe5eb">&#9670;&nbsp;</a></span>allocationCount</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">size_t VmaPoolStats::allocationCount</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Number of <a class="el" href="struct_vma_allocation.html" title="Represents single memory allocation.">VmaAllocation</a> objects created from this pool that were not destroyed or lost. </p>
+
+</div>
+</div>
+<a id="aa0b5cb45cef6f18571cefb03b9a230e7"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#aa0b5cb45cef6f18571cefb03b9a230e7">&#9670;&nbsp;</a></span>blockCount</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">size_t VmaPoolStats::blockCount</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Number of <code>VkDeviceMemory</code> blocks allocated for this pool. </p>
+
+</div>
+</div>
+<a id="a326807b2de2b0931cee4ed9a5f2e420c"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a326807b2de2b0931cee4ed9a5f2e420c">&#9670;&nbsp;</a></span>size</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkDeviceSize VmaPoolStats::size</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Total amount of <code>VkDeviceMemory</code> allocated from Vulkan for this pool, in bytes. </p>
+
+</div>
+</div>
+<a id="ae4f3546ffa4d1e598b64d8e6134854f4"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ae4f3546ffa4d1e598b64d8e6134854f4">&#9670;&nbsp;</a></span>unusedRangeCount</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">size_t VmaPoolStats::unusedRangeCount</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Number of continuous memory ranges in the pool not used by any <a class="el" href="struct_vma_allocation.html" title="Represents single memory allocation.">VmaAllocation</a>. </p>
+
+</div>
+</div>
+<a id="ab4c8f52dd42ab01998f60f0b6acc722b"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ab4c8f52dd42ab01998f60f0b6acc722b">&#9670;&nbsp;</a></span>unusedRangeSizeMax</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkDeviceSize VmaPoolStats::unusedRangeSizeMax</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Size of the largest continuous free memory region available for new allocation. </p>
+<p>Making a new allocation of that size is not guaranteed to succeed because of possible additional margin required to respect alignment and buffer/image granularity. </p>
+
+</div>
+</div>
+<a id="ad7c54874724fce7b06aba526202d82a8"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ad7c54874724fce7b06aba526202d82a8">&#9670;&nbsp;</a></span>unusedSize</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkDeviceSize VmaPoolStats::unusedSize</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Total number of bytes in the pool not used by any <a class="el" href="struct_vma_allocation.html" title="Represents single memory allocation.">VmaAllocation</a>. </p>
+
+</div>
+</div>
+<hr/>The documentation for this struct was generated from the following file:<ul>
+<li><a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a></li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/struct_vma_record_settings-members.html b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_record_settings-members.html
new file mode 100644
index 0000000..481c0eb
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_record_settings-members.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: Member List</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="headertitle">
+<div class="title">VmaRecordSettings Member List</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>This is the complete list of members for <a class="el" href="struct_vma_record_settings.html">VmaRecordSettings</a>, including all inherited members.</p>
+<table class="directory">
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_record_settings.html#ad8fdcc92119ae7a8c08c1a564c01d63a">flags</a></td><td class="entry"><a class="el" href="struct_vma_record_settings.html">VmaRecordSettings</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_record_settings.html#a6cb1fdbf6bcb610b68f2010dd629e89d">pFilePath</a></td><td class="entry"><a class="el" href="struct_vma_record_settings.html">VmaRecordSettings</a></td><td class="entry"></td></tr>
+</table></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/struct_vma_record_settings.html b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_record_settings.html
new file mode 100644
index 0000000..c347446
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_record_settings.html
@@ -0,0 +1,133 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: VmaRecordSettings Struct Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="summary">
+<a href="#pub-attribs">Public Attributes</a> &#124;
+<a href="struct_vma_record_settings-members.html">List of all members</a>  </div>
+  <div class="headertitle">
+<div class="title">VmaRecordSettings Struct Reference</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>Parameters for recording calls to VMA functions. To be used in <a class="el" href="struct_vma_allocator_create_info.html#ace2aa4877b16a42b0b7673d4e26000ee" title="Parameters for recording of VMA calls. Can be null.">VmaAllocatorCreateInfo::pRecordSettings</a>.  
+ <a href="struct_vma_record_settings.html#details">More...</a></p>
+
+<p><code>#include &lt;<a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a>&gt;</code></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="pub-attribs"></a>
+Public Attributes</h2></td></tr>
+<tr class="memitem:ad8fdcc92119ae7a8c08c1a564c01d63a"><td class="memItemLeft" align="right" valign="top"><a class="el" href="vk__mem__alloc_8h.html#af3929a1a4547c592fc0b0e55ef452828">VmaRecordFlags</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_record_settings.html#ad8fdcc92119ae7a8c08c1a564c01d63a">flags</a></td></tr>
+<tr class="memdesc:ad8fdcc92119ae7a8c08c1a564c01d63a"><td class="mdescLeft">&#160;</td><td class="mdescRight">Flags for recording. Use <a class="el" href="vk__mem__alloc_8h.html#acd24d5eb58abff7e1f43cb32a1ba1413" title="Flags to be used in VmaRecordSettings::flags.">VmaRecordFlagBits</a> enum.  <a href="struct_vma_record_settings.html#ad8fdcc92119ae7a8c08c1a564c01d63a">More...</a><br /></td></tr>
+<tr class="separator:ad8fdcc92119ae7a8c08c1a564c01d63a"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a6cb1fdbf6bcb610b68f2010dd629e89d"><td class="memItemLeft" align="right" valign="top">const char *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_record_settings.html#a6cb1fdbf6bcb610b68f2010dd629e89d">pFilePath</a></td></tr>
+<tr class="memdesc:a6cb1fdbf6bcb610b68f2010dd629e89d"><td class="mdescLeft">&#160;</td><td class="mdescRight">Path to the file that should be written by the recording.  <a href="struct_vma_record_settings.html#a6cb1fdbf6bcb610b68f2010dd629e89d">More...</a><br /></td></tr>
+<tr class="separator:a6cb1fdbf6bcb610b68f2010dd629e89d"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<div class="textblock"><p>Parameters for recording calls to VMA functions. To be used in <a class="el" href="struct_vma_allocator_create_info.html#ace2aa4877b16a42b0b7673d4e26000ee" title="Parameters for recording of VMA calls. Can be null.">VmaAllocatorCreateInfo::pRecordSettings</a>. </p>
+</div><h2 class="groupheader">Member Data Documentation</h2>
+<a id="ad8fdcc92119ae7a8c08c1a564c01d63a"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ad8fdcc92119ae7a8c08c1a564c01d63a">&#9670;&nbsp;</a></span>flags</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname"><a class="el" href="vk__mem__alloc_8h.html#af3929a1a4547c592fc0b0e55ef452828">VmaRecordFlags</a> VmaRecordSettings::flags</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Flags for recording. Use <a class="el" href="vk__mem__alloc_8h.html#acd24d5eb58abff7e1f43cb32a1ba1413" title="Flags to be used in VmaRecordSettings::flags.">VmaRecordFlagBits</a> enum. </p>
+
+</div>
+</div>
+<a id="a6cb1fdbf6bcb610b68f2010dd629e89d"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a6cb1fdbf6bcb610b68f2010dd629e89d">&#9670;&nbsp;</a></span>pFilePath</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">const char* VmaRecordSettings::pFilePath</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Path to the file that should be written by the recording. </p>
+<p>Suggested extension: "csv". If the file already exists, it will be overwritten. It will be opened for the whole time <a class="el" href="struct_vma_allocator.html" title="Represents main object of this library initialized.">VmaAllocator</a> object is alive. If opening this file fails, creation of the whole allocator object fails. </p>
+
+</div>
+</div>
+<hr/>The documentation for this struct was generated from the following file:<ul>
+<li><a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a></li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/struct_vma_stat_info-members.html b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_stat_info-members.html
new file mode 100644
index 0000000..af90ac6
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_stat_info-members.html
@@ -0,0 +1,90 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: Member List</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="headertitle">
+<div class="title">VmaStatInfo Member List</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>This is the complete list of members for <a class="el" href="struct_vma_stat_info.html">VmaStatInfo</a>, including all inherited members.</p>
+<table class="directory">
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_stat_info.html#a537741e4d5cdddc1c0ab95ec650afaff">allocationCount</a></td><td class="entry"><a class="el" href="struct_vma_stat_info.html">VmaStatInfo</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_stat_info.html#a1081a039964e566c672e7a2347f9e599">allocationSizeAvg</a></td><td class="entry"><a class="el" href="struct_vma_stat_info.html">VmaStatInfo</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_stat_info.html#a17e9733a5ecd76287d4db6e66f71f50c">allocationSizeMax</a></td><td class="entry"><a class="el" href="struct_vma_stat_info.html">VmaStatInfo</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_stat_info.html#ade8b40bd3139c04aabd2fc538a356fea">allocationSizeMin</a></td><td class="entry"><a class="el" href="struct_vma_stat_info.html">VmaStatInfo</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_stat_info.html#abc4bb7cd611900778464c56e50c970a4">blockCount</a></td><td class="entry"><a class="el" href="struct_vma_stat_info.html">VmaStatInfo</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_stat_info.html#a1859d290aca2cd582d8dc25922092669">unusedBytes</a></td><td class="entry"><a class="el" href="struct_vma_stat_info.html">VmaStatInfo</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_stat_info.html#ae06129c771bfebfd6468a7f4276502a9">unusedRangeCount</a></td><td class="entry"><a class="el" href="struct_vma_stat_info.html">VmaStatInfo</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_stat_info.html#a2f9b3452af90c9768a30b7fb6ae194fc">unusedRangeSizeAvg</a></td><td class="entry"><a class="el" href="struct_vma_stat_info.html">VmaStatInfo</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_stat_info.html#a5ba1a2476c4d39b10f7e2f7ebbb72ac4">unusedRangeSizeMax</a></td><td class="entry"><a class="el" href="struct_vma_stat_info.html">VmaStatInfo</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_stat_info.html#aedeba931324f16589cd2416c0d2dd0d4">unusedRangeSizeMin</a></td><td class="entry"><a class="el" href="struct_vma_stat_info.html">VmaStatInfo</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_stat_info.html#ab0c6c73837e5a70c749fbd4f6064895a">usedBytes</a></td><td class="entry"><a class="el" href="struct_vma_stat_info.html">VmaStatInfo</a></td><td class="entry"></td></tr>
+</table></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/struct_vma_stat_info.html b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_stat_info.html
new file mode 100644
index 0000000..d9d4b33
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_stat_info.html
@@ -0,0 +1,285 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: VmaStatInfo Struct Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="summary">
+<a href="#pub-attribs">Public Attributes</a> &#124;
+<a href="struct_vma_stat_info-members.html">List of all members</a>  </div>
+  <div class="headertitle">
+<div class="title">VmaStatInfo Struct Reference</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>Calculated statistics of memory usage in entire allocator.  
+ <a href="struct_vma_stat_info.html#details">More...</a></p>
+
+<p><code>#include &lt;<a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a>&gt;</code></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="pub-attribs"></a>
+Public Attributes</h2></td></tr>
+<tr class="memitem:abc4bb7cd611900778464c56e50c970a4"><td class="memItemLeft" align="right" valign="top">uint32_t&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_stat_info.html#abc4bb7cd611900778464c56e50c970a4">blockCount</a></td></tr>
+<tr class="memdesc:abc4bb7cd611900778464c56e50c970a4"><td class="mdescLeft">&#160;</td><td class="mdescRight">Number of <code>VkDeviceMemory</code> Vulkan memory blocks allocated.  <a href="struct_vma_stat_info.html#abc4bb7cd611900778464c56e50c970a4">More...</a><br /></td></tr>
+<tr class="separator:abc4bb7cd611900778464c56e50c970a4"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a537741e4d5cdddc1c0ab95ec650afaff"><td class="memItemLeft" align="right" valign="top">uint32_t&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_stat_info.html#a537741e4d5cdddc1c0ab95ec650afaff">allocationCount</a></td></tr>
+<tr class="memdesc:a537741e4d5cdddc1c0ab95ec650afaff"><td class="mdescLeft">&#160;</td><td class="mdescRight">Number of <a class="el" href="struct_vma_allocation.html" title="Represents single memory allocation.">VmaAllocation</a> allocation objects allocated.  <a href="struct_vma_stat_info.html#a537741e4d5cdddc1c0ab95ec650afaff">More...</a><br /></td></tr>
+<tr class="separator:a537741e4d5cdddc1c0ab95ec650afaff"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ae06129c771bfebfd6468a7f4276502a9"><td class="memItemLeft" align="right" valign="top">uint32_t&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_stat_info.html#ae06129c771bfebfd6468a7f4276502a9">unusedRangeCount</a></td></tr>
+<tr class="memdesc:ae06129c771bfebfd6468a7f4276502a9"><td class="mdescLeft">&#160;</td><td class="mdescRight">Number of free ranges of memory between allocations.  <a href="struct_vma_stat_info.html#ae06129c771bfebfd6468a7f4276502a9">More...</a><br /></td></tr>
+<tr class="separator:ae06129c771bfebfd6468a7f4276502a9"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ab0c6c73837e5a70c749fbd4f6064895a"><td class="memItemLeft" align="right" valign="top">VkDeviceSize&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_stat_info.html#ab0c6c73837e5a70c749fbd4f6064895a">usedBytes</a></td></tr>
+<tr class="memdesc:ab0c6c73837e5a70c749fbd4f6064895a"><td class="mdescLeft">&#160;</td><td class="mdescRight">Total number of bytes occupied by all allocations.  <a href="struct_vma_stat_info.html#ab0c6c73837e5a70c749fbd4f6064895a">More...</a><br /></td></tr>
+<tr class="separator:ab0c6c73837e5a70c749fbd4f6064895a"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a1859d290aca2cd582d8dc25922092669"><td class="memItemLeft" align="right" valign="top">VkDeviceSize&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_stat_info.html#a1859d290aca2cd582d8dc25922092669">unusedBytes</a></td></tr>
+<tr class="memdesc:a1859d290aca2cd582d8dc25922092669"><td class="mdescLeft">&#160;</td><td class="mdescRight">Total number of bytes occupied by unused ranges.  <a href="struct_vma_stat_info.html#a1859d290aca2cd582d8dc25922092669">More...</a><br /></td></tr>
+<tr class="separator:a1859d290aca2cd582d8dc25922092669"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ade8b40bd3139c04aabd2fc538a356fea"><td class="memItemLeft" align="right" valign="top">VkDeviceSize&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_stat_info.html#ade8b40bd3139c04aabd2fc538a356fea">allocationSizeMin</a></td></tr>
+<tr class="separator:ade8b40bd3139c04aabd2fc538a356fea"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a1081a039964e566c672e7a2347f9e599"><td class="memItemLeft" align="right" valign="top">VkDeviceSize&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_stat_info.html#a1081a039964e566c672e7a2347f9e599">allocationSizeAvg</a></td></tr>
+<tr class="separator:a1081a039964e566c672e7a2347f9e599"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a17e9733a5ecd76287d4db6e66f71f50c"><td class="memItemLeft" align="right" valign="top">VkDeviceSize&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_stat_info.html#a17e9733a5ecd76287d4db6e66f71f50c">allocationSizeMax</a></td></tr>
+<tr class="separator:a17e9733a5ecd76287d4db6e66f71f50c"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:aedeba931324f16589cd2416c0d2dd0d4"><td class="memItemLeft" align="right" valign="top">VkDeviceSize&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_stat_info.html#aedeba931324f16589cd2416c0d2dd0d4">unusedRangeSizeMin</a></td></tr>
+<tr class="separator:aedeba931324f16589cd2416c0d2dd0d4"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a2f9b3452af90c9768a30b7fb6ae194fc"><td class="memItemLeft" align="right" valign="top">VkDeviceSize&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_stat_info.html#a2f9b3452af90c9768a30b7fb6ae194fc">unusedRangeSizeAvg</a></td></tr>
+<tr class="separator:a2f9b3452af90c9768a30b7fb6ae194fc"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a5ba1a2476c4d39b10f7e2f7ebbb72ac4"><td class="memItemLeft" align="right" valign="top">VkDeviceSize&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_stat_info.html#a5ba1a2476c4d39b10f7e2f7ebbb72ac4">unusedRangeSizeMax</a></td></tr>
+<tr class="separator:a5ba1a2476c4d39b10f7e2f7ebbb72ac4"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<div class="textblock"><p>Calculated statistics of memory usage in entire allocator. </p>
+</div><h2 class="groupheader">Member Data Documentation</h2>
+<a id="a537741e4d5cdddc1c0ab95ec650afaff"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a537741e4d5cdddc1c0ab95ec650afaff">&#9670;&nbsp;</a></span>allocationCount</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">uint32_t VmaStatInfo::allocationCount</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Number of <a class="el" href="struct_vma_allocation.html" title="Represents single memory allocation.">VmaAllocation</a> allocation objects allocated. </p>
+
+</div>
+</div>
+<a id="a1081a039964e566c672e7a2347f9e599"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a1081a039964e566c672e7a2347f9e599">&#9670;&nbsp;</a></span>allocationSizeAvg</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkDeviceSize VmaStatInfo::allocationSizeAvg</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="a17e9733a5ecd76287d4db6e66f71f50c"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a17e9733a5ecd76287d4db6e66f71f50c">&#9670;&nbsp;</a></span>allocationSizeMax</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkDeviceSize VmaStatInfo::allocationSizeMax</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="ade8b40bd3139c04aabd2fc538a356fea"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ade8b40bd3139c04aabd2fc538a356fea">&#9670;&nbsp;</a></span>allocationSizeMin</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkDeviceSize VmaStatInfo::allocationSizeMin</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="abc4bb7cd611900778464c56e50c970a4"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#abc4bb7cd611900778464c56e50c970a4">&#9670;&nbsp;</a></span>blockCount</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">uint32_t VmaStatInfo::blockCount</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Number of <code>VkDeviceMemory</code> Vulkan memory blocks allocated. </p>
+
+</div>
+</div>
+<a id="a1859d290aca2cd582d8dc25922092669"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a1859d290aca2cd582d8dc25922092669">&#9670;&nbsp;</a></span>unusedBytes</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkDeviceSize VmaStatInfo::unusedBytes</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Total number of bytes occupied by unused ranges. </p>
+
+</div>
+</div>
+<a id="ae06129c771bfebfd6468a7f4276502a9"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ae06129c771bfebfd6468a7f4276502a9">&#9670;&nbsp;</a></span>unusedRangeCount</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">uint32_t VmaStatInfo::unusedRangeCount</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Number of free ranges of memory between allocations. </p>
+
+</div>
+</div>
+<a id="a2f9b3452af90c9768a30b7fb6ae194fc"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a2f9b3452af90c9768a30b7fb6ae194fc">&#9670;&nbsp;</a></span>unusedRangeSizeAvg</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkDeviceSize VmaStatInfo::unusedRangeSizeAvg</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="a5ba1a2476c4d39b10f7e2f7ebbb72ac4"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a5ba1a2476c4d39b10f7e2f7ebbb72ac4">&#9670;&nbsp;</a></span>unusedRangeSizeMax</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkDeviceSize VmaStatInfo::unusedRangeSizeMax</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="aedeba931324f16589cd2416c0d2dd0d4"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#aedeba931324f16589cd2416c0d2dd0d4">&#9670;&nbsp;</a></span>unusedRangeSizeMin</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkDeviceSize VmaStatInfo::unusedRangeSizeMin</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="ab0c6c73837e5a70c749fbd4f6064895a"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ab0c6c73837e5a70c749fbd4f6064895a">&#9670;&nbsp;</a></span>usedBytes</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkDeviceSize VmaStatInfo::usedBytes</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Total number of bytes occupied by all allocations. </p>
+
+</div>
+</div>
+<hr/>The documentation for this struct was generated from the following file:<ul>
+<li><a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a></li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/struct_vma_stats-members.html b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_stats-members.html
new file mode 100644
index 0000000..21a4477
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_stats-members.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: Member List</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="headertitle">
+<div class="title">VmaStats Member List</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>This is the complete list of members for <a class="el" href="struct_vma_stats.html">VmaStats</a>, including all inherited members.</p>
+<table class="directory">
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_stats.html#a0e6611508c29a187f0fd14ff1a0329c0">memoryHeap</a></td><td class="entry"><a class="el" href="struct_vma_stats.html">VmaStats</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_stats.html#a13e3caf754be79352c42408756309331">memoryType</a></td><td class="entry"><a class="el" href="struct_vma_stats.html">VmaStats</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_stats.html#a2e8f5b3353f2fefef3c27f29e245a1f9">total</a></td><td class="entry"><a class="el" href="struct_vma_stats.html">VmaStats</a></td><td class="entry"></td></tr>
+</table></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/struct_vma_stats.html b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_stats.html
new file mode 100644
index 0000000..a197108
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_stats.html
@@ -0,0 +1,142 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: VmaStats Struct Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="summary">
+<a href="#pub-attribs">Public Attributes</a> &#124;
+<a href="struct_vma_stats-members.html">List of all members</a>  </div>
+  <div class="headertitle">
+<div class="title">VmaStats Struct Reference</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>General statistics from current state of Allocator.  
+ <a href="struct_vma_stats.html#details">More...</a></p>
+
+<p><code>#include &lt;<a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a>&gt;</code></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="pub-attribs"></a>
+Public Attributes</h2></td></tr>
+<tr class="memitem:a13e3caf754be79352c42408756309331"><td class="memItemLeft" align="right" valign="top"><a class="el" href="struct_vma_stat_info.html">VmaStatInfo</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_stats.html#a13e3caf754be79352c42408756309331">memoryType</a> [VK_MAX_MEMORY_TYPES]</td></tr>
+<tr class="separator:a13e3caf754be79352c42408756309331"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a0e6611508c29a187f0fd14ff1a0329c0"><td class="memItemLeft" align="right" valign="top"><a class="el" href="struct_vma_stat_info.html">VmaStatInfo</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_stats.html#a0e6611508c29a187f0fd14ff1a0329c0">memoryHeap</a> [VK_MAX_MEMORY_HEAPS]</td></tr>
+<tr class="separator:a0e6611508c29a187f0fd14ff1a0329c0"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a2e8f5b3353f2fefef3c27f29e245a1f9"><td class="memItemLeft" align="right" valign="top"><a class="el" href="struct_vma_stat_info.html">VmaStatInfo</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_stats.html#a2e8f5b3353f2fefef3c27f29e245a1f9">total</a></td></tr>
+<tr class="separator:a2e8f5b3353f2fefef3c27f29e245a1f9"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<div class="textblock"><p>General statistics from current state of Allocator. </p>
+</div><h2 class="groupheader">Member Data Documentation</h2>
+<a id="a0e6611508c29a187f0fd14ff1a0329c0"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a0e6611508c29a187f0fd14ff1a0329c0">&#9670;&nbsp;</a></span>memoryHeap</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname"><a class="el" href="struct_vma_stat_info.html">VmaStatInfo</a> VmaStats::memoryHeap[VK_MAX_MEMORY_HEAPS]</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="a13e3caf754be79352c42408756309331"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a13e3caf754be79352c42408756309331">&#9670;&nbsp;</a></span>memoryType</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname"><a class="el" href="struct_vma_stat_info.html">VmaStatInfo</a> VmaStats::memoryType[VK_MAX_MEMORY_TYPES]</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="a2e8f5b3353f2fefef3c27f29e245a1f9"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a2e8f5b3353f2fefef3c27f29e245a1f9">&#9670;&nbsp;</a></span>total</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname"><a class="el" href="struct_vma_stat_info.html">VmaStatInfo</a> VmaStats::total</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<hr/>The documentation for this struct was generated from the following file:<ul>
+<li><a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a></li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/struct_vma_vulkan_functions-members.html b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_vulkan_functions-members.html
new file mode 100644
index 0000000..3cddfe6
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_vulkan_functions-members.html
@@ -0,0 +1,96 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: Member List</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="headertitle">
+<div class="title">VmaVulkanFunctions Member List</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>This is the complete list of members for <a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a>, including all inherited members.</p>
+<table class="directory">
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html#a2943bf99dfd784a0e8f599d987e22e6c">vkAllocateMemory</a></td><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html#a94fc4f3a605d9880bb3c0ba2c2fc80b2">vkBindBufferMemory</a></td><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html#a1338d96a128a5ade648b8d934907c637">vkBindImageMemory</a></td><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html#ae5c0db8c89a3b82593dc16aa6a49fa3a">vkCmdCopyBuffer</a></td><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html#ae8084315a25006271a2edfc3a447519f">vkCreateBuffer</a></td><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html#a23ebe70be515b9b5010a1d691200e325">vkCreateImage</a></td><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html#a7e054606faddb07f0e8556f3ed317d45">vkDestroyBuffer</a></td><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html#a90b898227039b1dcb3520f6e91f09ffa">vkDestroyImage</a></td><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html#a33c322f4c4ad2810f8a9c97a277572f9">vkFlushMappedMemoryRanges</a></td><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html#a4c658701778564d62034255b5dda91b4">vkFreeMemory</a></td><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html#a5b92901df89a4194b0d12f6071d4d143">vkGetBufferMemoryRequirements</a></td><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html#a475f6f49f8debe4d10800592606d53f4">vkGetImageMemoryRequirements</a></td><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html#a60d25c33bba06bb8592e6875cbaa9830">vkGetPhysicalDeviceMemoryProperties</a></td><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html#a77b7a74082823e865dd6546623468f96">vkGetPhysicalDeviceProperties</a></td><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html#a5c1093bc32386a8060c37c9f282078a1">vkInvalidateMappedMemoryRanges</a></td><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a></td><td class="entry"></td></tr>
+  <tr><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html#ab5c1f38dea3a2cf00dc9eb4f57218c49">vkMapMemory</a></td><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a></td><td class="entry"></td></tr>
+  <tr class="even"><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html#acc798589736f0becb317fc2196c1d8b9">vkUnmapMemory</a></td><td class="entry"><a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a></td><td class="entry"></td></tr>
+</table></div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/struct_vma_vulkan_functions.html b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_vulkan_functions.html
new file mode 100644
index 0000000..5421985
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/struct_vma_vulkan_functions.html
@@ -0,0 +1,367 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: VmaVulkanFunctions Struct Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="summary">
+<a href="#pub-attribs">Public Attributes</a> &#124;
+<a href="struct_vma_vulkan_functions-members.html">List of all members</a>  </div>
+  <div class="headertitle">
+<div class="title">VmaVulkanFunctions Struct Reference</div>  </div>
+</div><!--header-->
+<div class="contents">
+
+<p>Pointers to some Vulkan functions - a subset used by the library.  
+ <a href="struct_vma_vulkan_functions.html#details">More...</a></p>
+
+<p><code>#include &lt;<a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a>&gt;</code></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="pub-attribs"></a>
+Public Attributes</h2></td></tr>
+<tr class="memitem:a77b7a74082823e865dd6546623468f96"><td class="memItemLeft" align="right" valign="top">PFN_vkGetPhysicalDeviceProperties&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_vulkan_functions.html#a77b7a74082823e865dd6546623468f96">vkGetPhysicalDeviceProperties</a></td></tr>
+<tr class="separator:a77b7a74082823e865dd6546623468f96"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a60d25c33bba06bb8592e6875cbaa9830"><td class="memItemLeft" align="right" valign="top">PFN_vkGetPhysicalDeviceMemoryProperties&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_vulkan_functions.html#a60d25c33bba06bb8592e6875cbaa9830">vkGetPhysicalDeviceMemoryProperties</a></td></tr>
+<tr class="separator:a60d25c33bba06bb8592e6875cbaa9830"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a2943bf99dfd784a0e8f599d987e22e6c"><td class="memItemLeft" align="right" valign="top">PFN_vkAllocateMemory&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_vulkan_functions.html#a2943bf99dfd784a0e8f599d987e22e6c">vkAllocateMemory</a></td></tr>
+<tr class="separator:a2943bf99dfd784a0e8f599d987e22e6c"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a4c658701778564d62034255b5dda91b4"><td class="memItemLeft" align="right" valign="top">PFN_vkFreeMemory&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_vulkan_functions.html#a4c658701778564d62034255b5dda91b4">vkFreeMemory</a></td></tr>
+<tr class="separator:a4c658701778564d62034255b5dda91b4"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ab5c1f38dea3a2cf00dc9eb4f57218c49"><td class="memItemLeft" align="right" valign="top">PFN_vkMapMemory&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_vulkan_functions.html#ab5c1f38dea3a2cf00dc9eb4f57218c49">vkMapMemory</a></td></tr>
+<tr class="separator:ab5c1f38dea3a2cf00dc9eb4f57218c49"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:acc798589736f0becb317fc2196c1d8b9"><td class="memItemLeft" align="right" valign="top">PFN_vkUnmapMemory&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_vulkan_functions.html#acc798589736f0becb317fc2196c1d8b9">vkUnmapMemory</a></td></tr>
+<tr class="separator:acc798589736f0becb317fc2196c1d8b9"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a33c322f4c4ad2810f8a9c97a277572f9"><td class="memItemLeft" align="right" valign="top">PFN_vkFlushMappedMemoryRanges&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_vulkan_functions.html#a33c322f4c4ad2810f8a9c97a277572f9">vkFlushMappedMemoryRanges</a></td></tr>
+<tr class="separator:a33c322f4c4ad2810f8a9c97a277572f9"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a5c1093bc32386a8060c37c9f282078a1"><td class="memItemLeft" align="right" valign="top">PFN_vkInvalidateMappedMemoryRanges&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_vulkan_functions.html#a5c1093bc32386a8060c37c9f282078a1">vkInvalidateMappedMemoryRanges</a></td></tr>
+<tr class="separator:a5c1093bc32386a8060c37c9f282078a1"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a94fc4f3a605d9880bb3c0ba2c2fc80b2"><td class="memItemLeft" align="right" valign="top">PFN_vkBindBufferMemory&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_vulkan_functions.html#a94fc4f3a605d9880bb3c0ba2c2fc80b2">vkBindBufferMemory</a></td></tr>
+<tr class="separator:a94fc4f3a605d9880bb3c0ba2c2fc80b2"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a1338d96a128a5ade648b8d934907c637"><td class="memItemLeft" align="right" valign="top">PFN_vkBindImageMemory&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_vulkan_functions.html#a1338d96a128a5ade648b8d934907c637">vkBindImageMemory</a></td></tr>
+<tr class="separator:a1338d96a128a5ade648b8d934907c637"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a5b92901df89a4194b0d12f6071d4d143"><td class="memItemLeft" align="right" valign="top">PFN_vkGetBufferMemoryRequirements&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_vulkan_functions.html#a5b92901df89a4194b0d12f6071d4d143">vkGetBufferMemoryRequirements</a></td></tr>
+<tr class="separator:a5b92901df89a4194b0d12f6071d4d143"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a475f6f49f8debe4d10800592606d53f4"><td class="memItemLeft" align="right" valign="top">PFN_vkGetImageMemoryRequirements&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_vulkan_functions.html#a475f6f49f8debe4d10800592606d53f4">vkGetImageMemoryRequirements</a></td></tr>
+<tr class="separator:a475f6f49f8debe4d10800592606d53f4"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ae8084315a25006271a2edfc3a447519f"><td class="memItemLeft" align="right" valign="top">PFN_vkCreateBuffer&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_vulkan_functions.html#ae8084315a25006271a2edfc3a447519f">vkCreateBuffer</a></td></tr>
+<tr class="separator:ae8084315a25006271a2edfc3a447519f"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a7e054606faddb07f0e8556f3ed317d45"><td class="memItemLeft" align="right" valign="top">PFN_vkDestroyBuffer&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_vulkan_functions.html#a7e054606faddb07f0e8556f3ed317d45">vkDestroyBuffer</a></td></tr>
+<tr class="separator:a7e054606faddb07f0e8556f3ed317d45"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a23ebe70be515b9b5010a1d691200e325"><td class="memItemLeft" align="right" valign="top">PFN_vkCreateImage&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_vulkan_functions.html#a23ebe70be515b9b5010a1d691200e325">vkCreateImage</a></td></tr>
+<tr class="separator:a23ebe70be515b9b5010a1d691200e325"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a90b898227039b1dcb3520f6e91f09ffa"><td class="memItemLeft" align="right" valign="top">PFN_vkDestroyImage&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_vulkan_functions.html#a90b898227039b1dcb3520f6e91f09ffa">vkDestroyImage</a></td></tr>
+<tr class="separator:a90b898227039b1dcb3520f6e91f09ffa"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ae5c0db8c89a3b82593dc16aa6a49fa3a"><td class="memItemLeft" align="right" valign="top">PFN_vkCmdCopyBuffer&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_vulkan_functions.html#ae5c0db8c89a3b82593dc16aa6a49fa3a">vkCmdCopyBuffer</a></td></tr>
+<tr class="separator:ae5c0db8c89a3b82593dc16aa6a49fa3a"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
+<div class="textblock"><p>Pointers to some Vulkan functions - a subset used by the library. </p>
+<p>Used in <a class="el" href="struct_vma_allocator_create_info.html#a3dc197be3227da7338b1643f70db36bd" title="Pointers to Vulkan functions. Can be null.">VmaAllocatorCreateInfo::pVulkanFunctions</a>. </p>
+</div><h2 class="groupheader">Member Data Documentation</h2>
+<a id="a2943bf99dfd784a0e8f599d987e22e6c"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a2943bf99dfd784a0e8f599d987e22e6c">&#9670;&nbsp;</a></span>vkAllocateMemory</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">PFN_vkAllocateMemory VmaVulkanFunctions::vkAllocateMemory</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="a94fc4f3a605d9880bb3c0ba2c2fc80b2"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a94fc4f3a605d9880bb3c0ba2c2fc80b2">&#9670;&nbsp;</a></span>vkBindBufferMemory</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">PFN_vkBindBufferMemory VmaVulkanFunctions::vkBindBufferMemory</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="a1338d96a128a5ade648b8d934907c637"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a1338d96a128a5ade648b8d934907c637">&#9670;&nbsp;</a></span>vkBindImageMemory</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">PFN_vkBindImageMemory VmaVulkanFunctions::vkBindImageMemory</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="ae5c0db8c89a3b82593dc16aa6a49fa3a"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ae5c0db8c89a3b82593dc16aa6a49fa3a">&#9670;&nbsp;</a></span>vkCmdCopyBuffer</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">PFN_vkCmdCopyBuffer VmaVulkanFunctions::vkCmdCopyBuffer</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="ae8084315a25006271a2edfc3a447519f"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ae8084315a25006271a2edfc3a447519f">&#9670;&nbsp;</a></span>vkCreateBuffer</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">PFN_vkCreateBuffer VmaVulkanFunctions::vkCreateBuffer</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="a23ebe70be515b9b5010a1d691200e325"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a23ebe70be515b9b5010a1d691200e325">&#9670;&nbsp;</a></span>vkCreateImage</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">PFN_vkCreateImage VmaVulkanFunctions::vkCreateImage</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="a7e054606faddb07f0e8556f3ed317d45"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a7e054606faddb07f0e8556f3ed317d45">&#9670;&nbsp;</a></span>vkDestroyBuffer</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">PFN_vkDestroyBuffer VmaVulkanFunctions::vkDestroyBuffer</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="a90b898227039b1dcb3520f6e91f09ffa"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a90b898227039b1dcb3520f6e91f09ffa">&#9670;&nbsp;</a></span>vkDestroyImage</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">PFN_vkDestroyImage VmaVulkanFunctions::vkDestroyImage</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="a33c322f4c4ad2810f8a9c97a277572f9"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a33c322f4c4ad2810f8a9c97a277572f9">&#9670;&nbsp;</a></span>vkFlushMappedMemoryRanges</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">PFN_vkFlushMappedMemoryRanges VmaVulkanFunctions::vkFlushMappedMemoryRanges</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="a4c658701778564d62034255b5dda91b4"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a4c658701778564d62034255b5dda91b4">&#9670;&nbsp;</a></span>vkFreeMemory</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">PFN_vkFreeMemory VmaVulkanFunctions::vkFreeMemory</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="a5b92901df89a4194b0d12f6071d4d143"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a5b92901df89a4194b0d12f6071d4d143">&#9670;&nbsp;</a></span>vkGetBufferMemoryRequirements</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">PFN_vkGetBufferMemoryRequirements VmaVulkanFunctions::vkGetBufferMemoryRequirements</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="a475f6f49f8debe4d10800592606d53f4"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a475f6f49f8debe4d10800592606d53f4">&#9670;&nbsp;</a></span>vkGetImageMemoryRequirements</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">PFN_vkGetImageMemoryRequirements VmaVulkanFunctions::vkGetImageMemoryRequirements</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="a60d25c33bba06bb8592e6875cbaa9830"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a60d25c33bba06bb8592e6875cbaa9830">&#9670;&nbsp;</a></span>vkGetPhysicalDeviceMemoryProperties</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">PFN_vkGetPhysicalDeviceMemoryProperties VmaVulkanFunctions::vkGetPhysicalDeviceMemoryProperties</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="a77b7a74082823e865dd6546623468f96"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a77b7a74082823e865dd6546623468f96">&#9670;&nbsp;</a></span>vkGetPhysicalDeviceProperties</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">PFN_vkGetPhysicalDeviceProperties VmaVulkanFunctions::vkGetPhysicalDeviceProperties</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="a5c1093bc32386a8060c37c9f282078a1"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a5c1093bc32386a8060c37c9f282078a1">&#9670;&nbsp;</a></span>vkInvalidateMappedMemoryRanges</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">PFN_vkInvalidateMappedMemoryRanges VmaVulkanFunctions::vkInvalidateMappedMemoryRanges</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="ab5c1f38dea3a2cf00dc9eb4f57218c49"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ab5c1f38dea3a2cf00dc9eb4f57218c49">&#9670;&nbsp;</a></span>vkMapMemory</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">PFN_vkMapMemory VmaVulkanFunctions::vkMapMemory</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="acc798589736f0becb317fc2196c1d8b9"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#acc798589736f0becb317fc2196c1d8b9">&#9670;&nbsp;</a></span>vkUnmapMemory</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">PFN_vkUnmapMemory VmaVulkanFunctions::vkUnmapMemory</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<hr/>The documentation for this struct was generated from the following file:<ul>
+<li><a class="el" href="vk__mem__alloc_8h_source.html">vk_mem_alloc.h</a></li>
+</ul>
+</div><!-- contents -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/sync_off.png b/third_party/VulkanMemoryAllocator/docs/html/sync_off.png
new file mode 100644
index 0000000..3b443fc
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/sync_off.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/docs/html/sync_on.png b/third_party/VulkanMemoryAllocator/docs/html/sync_on.png
new file mode 100644
index 0000000..e08320f
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/sync_on.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/docs/html/tab_a.png b/third_party/VulkanMemoryAllocator/docs/html/tab_a.png
new file mode 100644
index 0000000..3b725c4
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/tab_a.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/docs/html/tab_b.png b/third_party/VulkanMemoryAllocator/docs/html/tab_b.png
new file mode 100644
index 0000000..e2b4a86
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/tab_b.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/docs/html/tab_h.png b/third_party/VulkanMemoryAllocator/docs/html/tab_h.png
new file mode 100644
index 0000000..fd5cb70
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/tab_h.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/docs/html/tab_s.png b/third_party/VulkanMemoryAllocator/docs/html/tab_s.png
new file mode 100644
index 0000000..ab478c9
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/tab_s.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/docs/html/tabs.css b/third_party/VulkanMemoryAllocator/docs/html/tabs.css
new file mode 100644
index 0000000..85a0cd5
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/tabs.css
@@ -0,0 +1 @@
+.sm{position:relative;z-index:9999}.sm,.sm ul,.sm li{display:block;list-style:none;margin:0;padding:0;line-height:normal;direction:ltr;text-align:left;-webkit-tap-highlight-color:rgba(0,0,0,0)}.sm-rtl,.sm-rtl ul,.sm-rtl li{direction:rtl;text-align:right}.sm>li>h1,.sm>li>h2,.sm>li>h3,.sm>li>h4,.sm>li>h5,.sm>li>h6{margin:0;padding:0}.sm ul{display:none}.sm li,.sm a{position:relative}.sm a{display:block}.sm a.disabled{cursor:not-allowed}.sm:after{content:"\00a0";display:block;height:0;font:0/0 serif;clear:both;visibility:hidden;overflow:hidden}.sm,.sm *,.sm *:before,.sm *:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.sm-dox{background-image:url("tab_b.png")}.sm-dox a,.sm-dox a:focus,.sm-dox a:hover,.sm-dox a:active{padding:0 12px;padding-right:43px;font-family:"Lucida Grande","Geneva","Helvetica",Arial,sans-serif;font-size:13px;font-weight:bold;line-height:36px;text-decoration:none;text-shadow:0 1px 1px rgba(255,255,255,0.9);color:#283a5d;outline:0}.sm-dox a:hover{background-image:url("tab_a.png");background-repeat:repeat-x;color:white;text-shadow:0 1px 1px black}.sm-dox a.current{color:#d23600}.sm-dox a.disabled{color:#bbb}.sm-dox a span.sub-arrow{position:absolute;top:50%;margin-top:-14px;left:auto;right:3px;width:28px;height:28px;overflow:hidden;font:bold 12px/28px monospace!important;text-align:center;text-shadow:none;background:rgba(255,255,255,0.5);-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px}.sm-dox a.highlighted span.sub-arrow:before{display:block;content:'-'}.sm-dox>li:first-child>a,.sm-dox>li:first-child>:not(ul) a{-moz-border-radius:5px 5px 0 0;-webkit-border-radius:5px;border-radius:5px 5px 0 0}.sm-dox>li:last-child>a,.sm-dox>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul{-moz-border-radius:0 0 5px 5px;-webkit-border-radius:0;border-radius:0 0 5px 5px}.sm-dox>li:last-child>a.highlighted,.sm-dox>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a.highlighted{-moz-border-radius:0;-webkit-border-radius:0;border-radius:0}.sm-dox ul{background:rgba(162,162,162,0.1)}.sm-dox ul a,.sm-dox ul a:focus,.sm-dox ul a:hover,.sm-dox ul a:active{font-size:12px;border-left:8px solid transparent;line-height:36px;text-shadow:none;background-color:white;background-image:none}.sm-dox ul a:hover{background-image:url("tab_a.png");background-repeat:repeat-x;color:white;text-shadow:0 1px 1px black}.sm-dox ul ul a,.sm-dox ul ul a:hover,.sm-dox ul ul a:focus,.sm-dox ul ul a:active{border-left:16px solid transparent}.sm-dox ul ul ul a,.sm-dox ul ul ul a:hover,.sm-dox ul ul ul a:focus,.sm-dox ul ul ul a:active{border-left:24px solid transparent}.sm-dox ul ul ul ul a,.sm-dox ul ul ul ul a:hover,.sm-dox ul ul ul ul a:focus,.sm-dox ul ul ul ul a:active{border-left:32px solid transparent}.sm-dox ul ul ul ul ul a,.sm-dox ul ul ul ul ul a:hover,.sm-dox ul ul ul ul ul a:focus,.sm-dox ul ul ul ul ul a:active{border-left:40px solid transparent}@media(min-width:768px){.sm-dox ul{position:absolute;width:12em}.sm-dox li{float:left}.sm-dox.sm-rtl li{float:right}.sm-dox ul li,.sm-dox.sm-rtl ul li,.sm-dox.sm-vertical li{float:none}.sm-dox a{white-space:nowrap}.sm-dox ul a,.sm-dox.sm-vertical a{white-space:normal}.sm-dox .sm-nowrap>li>a,.sm-dox .sm-nowrap>li>:not(ul) a{white-space:nowrap}.sm-dox{padding:0 10px;background-image:url("tab_b.png");line-height:36px}.sm-dox a span.sub-arrow{top:50%;margin-top:-2px;right:12px;width:0;height:0;border-width:4px;border-style:solid dashed dashed dashed;border-color:#283a5d transparent transparent transparent;background:transparent;-moz-border-radius:0;-webkit-border-radius:0;border-radius:0}.sm-dox a,.sm-dox a:focus,.sm-dox a:active,.sm-dox a:hover,.sm-dox a.highlighted{padding:0 12px;background-image:url("tab_s.png");background-repeat:no-repeat;background-position:right;-moz-border-radius:0!important;-webkit-border-radius:0;border-radius:0!important}.sm-dox a:hover{background-image:url("tab_a.png");background-repeat:repeat-x;color:white;text-shadow:0 1px 1px black}.sm-dox a:hover span.sub-arrow{border-color:white transparent transparent transparent}.sm-dox a.has-submenu{padding-right:24px}.sm-dox li{border-top:0}.sm-dox>li>ul:before,.sm-dox>li>ul:after{content:'';position:absolute;top:-18px;left:30px;width:0;height:0;overflow:hidden;border-width:9px;border-style:dashed dashed solid dashed;border-color:transparent transparent #bbb transparent}.sm-dox>li>ul:after{top:-16px;left:31px;border-width:8px;border-color:transparent transparent #fff transparent}.sm-dox ul{border:1px solid #bbb;padding:5px 0;background:#fff;-moz-border-radius:5px!important;-webkit-border-radius:5px;border-radius:5px!important;-moz-box-shadow:0 5px 9px rgba(0,0,0,0.2);-webkit-box-shadow:0 5px 9px rgba(0,0,0,0.2);box-shadow:0 5px 9px rgba(0,0,0,0.2)}.sm-dox ul a span.sub-arrow{right:8px;top:50%;margin-top:-5px;border-width:5px;border-color:transparent transparent transparent #555;border-style:dashed dashed dashed solid}.sm-dox ul a,.sm-dox ul a:hover,.sm-dox ul a:focus,.sm-dox ul a:active,.sm-dox ul a.highlighted{color:#555;background-image:none;border:0!important;color:#555;background-image:none}.sm-dox ul a:hover{background-image:url("tab_a.png");background-repeat:repeat-x;color:white;text-shadow:0 1px 1px black}.sm-dox ul a:hover span.sub-arrow{border-color:transparent transparent transparent white}.sm-dox span.scroll-up,.sm-dox span.scroll-down{position:absolute;display:none;visibility:hidden;overflow:hidden;background:#fff;height:36px}.sm-dox span.scroll-up:hover,.sm-dox span.scroll-down:hover{background:#eee}.sm-dox span.scroll-up:hover span.scroll-up-arrow,.sm-dox span.scroll-up:hover span.scroll-down-arrow{border-color:transparent transparent #d23600 transparent}.sm-dox span.scroll-down:hover span.scroll-down-arrow{border-color:#d23600 transparent transparent transparent}.sm-dox span.scroll-up-arrow,.sm-dox span.scroll-down-arrow{position:absolute;top:0;left:50%;margin-left:-6px;width:0;height:0;overflow:hidden;border-width:6px;border-style:dashed dashed solid dashed;border-color:transparent transparent #555 transparent}.sm-dox span.scroll-down-arrow{top:8px;border-style:solid dashed dashed dashed;border-color:#555 transparent transparent transparent}.sm-dox.sm-rtl a.has-submenu{padding-right:12px;padding-left:24px}.sm-dox.sm-rtl a span.sub-arrow{right:auto;left:12px}.sm-dox.sm-rtl.sm-vertical a.has-submenu{padding:10px 20px}.sm-dox.sm-rtl.sm-vertical a span.sub-arrow{right:auto;left:8px;border-style:dashed solid dashed dashed;border-color:transparent #555 transparent transparent}.sm-dox.sm-rtl>li>ul:before{left:auto;right:30px}.sm-dox.sm-rtl>li>ul:after{left:auto;right:31px}.sm-dox.sm-rtl ul a.has-submenu{padding:10px 20px!important}.sm-dox.sm-rtl ul a span.sub-arrow{right:auto;left:8px;border-style:dashed solid dashed dashed;border-color:transparent #555 transparent transparent}.sm-dox.sm-vertical{padding:10px 0;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px}.sm-dox.sm-vertical a{padding:10px 20px}.sm-dox.sm-vertical a:hover,.sm-dox.sm-vertical a:focus,.sm-dox.sm-vertical a:active,.sm-dox.sm-vertical a.highlighted{background:#fff}.sm-dox.sm-vertical a.disabled{background-image:url("tab_b.png")}.sm-dox.sm-vertical a span.sub-arrow{right:8px;top:50%;margin-top:-5px;border-width:5px;border-style:dashed dashed dashed solid;border-color:transparent transparent transparent #555}.sm-dox.sm-vertical>li>ul:before,.sm-dox.sm-vertical>li>ul:after{display:none}.sm-dox.sm-vertical ul a{padding:10px 20px}.sm-dox.sm-vertical ul a:hover,.sm-dox.sm-vertical ul a:focus,.sm-dox.sm-vertical ul a:active,.sm-dox.sm-vertical ul a.highlighted{background:#eee}.sm-dox.sm-vertical ul a.disabled{background:#fff}}
\ No newline at end of file
diff --git a/third_party/VulkanMemoryAllocator/docs/html/usage_patterns.html b/third_party/VulkanMemoryAllocator/docs/html/usage_patterns.html
new file mode 100644
index 0000000..2efadc5
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/usage_patterns.html
@@ -0,0 +1,137 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: Recommended usage patterns</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+  <ul>
+<li class="navelem"><a class="el" href="index.html">Vulkan Memory Allocator</a></li>  </ul>
+</div>
+</div><!-- top -->
+<div class="PageDoc"><div class="header">
+  <div class="headertitle">
+<div class="title">Recommended usage patterns </div>  </div>
+</div><!--header-->
+<div class="contents">
+<div class="textblock"><p>See also slides from talk: <a href="https://www.gdcvault.com/play/1025458/Advanced-Graphics-Techniques-Tutorial-New">Sawicki, Adam. Advanced Graphics Techniques Tutorial: Memory management in Vulkan and DX12. Game Developers Conference, 2018</a></p>
+<h1><a class="anchor" id="usage_patterns_common_mistakes"></a>
+Common mistakes</h1>
+<p><b>Use of CPU_TO_GPU instead of CPU_ONLY memory</b></p>
+<p><a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca9066b52c5a7079bb74a69aaf8b92ff67">VMA_MEMORY_USAGE_CPU_TO_GPU</a> is recommended only for resources that will be mapped and written by the CPU, as well as read directly by the GPU - like some buffers or textures updated every frame (dynamic). If you create a staging copy of a resource to be written by CPU and then used as a source of transfer to another resource placed in the GPU memory, that staging resource should be created with <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca40bdf4cddeffeb12f43d45ca1286e0a5">VMA_MEMORY_USAGE_CPU_ONLY</a>. Please read the descriptions of these enums carefully for details.</p>
+<p><b>Unnecessary use of custom pools</b></p>
+<p><a class="el" href="custom_memory_pools.html">Custom memory pools</a> may be useful for special purposes - when you want to keep certain type of resources separate e.g. to reserve minimum amount of memory for them, limit maximum amount of memory they can occupy, or make some of them push out the other through the mechanism of <a class="el" href="lost_allocations.html">Lost allocations</a>. For most resources this is not needed and so it is not recommended to create <a class="el" href="struct_vma_pool.html" title="Represents custom memory pool.">VmaPool</a> objects and allocations out of them. Allocating from the default pool is sufficient.</p>
+<h1><a class="anchor" id="usage_patterns_simple"></a>
+Simple patterns</h1>
+<h2><a class="anchor" id="usage_patterns_simple_render_targets"></a>
+Render targets</h2>
+<p><b>When:</b> Any resources that you frequently write and read on GPU, e.g. images used as color attachments (aka "render targets"), depth-stencil attachments, images/buffers used as storage image/buffer (aka "Unordered Access View (UAV)").</p>
+<p><b>What to do:</b> Create them in video memory that is fastest to access from GPU using <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7">VMA_MEMORY_USAGE_GPU_ONLY</a>.</p>
+<p>Consider using <a class="el" href="vk_khr_dedicated_allocation.html">VK_KHR_dedicated_allocation</a> extension and/or manually creating them as dedicated allocations using <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a3fc311d855c2ff53f1090ef5c722b38f" title="Set this flag if the allocation should have its own memory block.">VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT</a>, especially if they are large or if you plan to destroy and recreate them e.g. when display resolution changes. Prefer to create such resources first and all other GPU resources (like textures and vertex buffers) later.</p>
+<h2><a class="anchor" id="usage_patterns_simple_immutable_resources"></a>
+Immutable resources</h2>
+<p><b>When:</b> Any resources that you fill on CPU only once (aka "immutable") or infrequently and then read frequently on GPU, e.g. textures, vertex and index buffers, constant buffers that don't change often.</p>
+<p><b>What to do:</b> Create them in video memory that is fastest to access from GPU using <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7">VMA_MEMORY_USAGE_GPU_ONLY</a>.</p>
+<p>To initialize content of such resource, create a CPU-side (aka "staging") copy of it in system memory - <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca40bdf4cddeffeb12f43d45ca1286e0a5">VMA_MEMORY_USAGE_CPU_ONLY</a>, map it, fill it, and submit a transfer from it to the GPU resource. You can keep the staging copy if you need it for another upload transfer in the future. If you don't, you can destroy it or reuse this buffer for uploading different resource after the transfer finishes.</p>
+<p>Prefer to create just buffers in system memory rather than images, even for uploading textures. Use <code>vkCmdCopyBufferToImage()</code>. Dont use images with <code>VK_IMAGE_TILING_LINEAR</code>.</p>
+<h2><a class="anchor" id="usage_patterns_dynamic_resources"></a>
+Dynamic resources</h2>
+<p><b>When:</b> Any resources that change frequently (aka "dynamic"), e.g. every frame or every draw call, written on CPU, read on GPU.</p>
+<p><b>What to do:</b> Create them using <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca9066b52c5a7079bb74a69aaf8b92ff67">VMA_MEMORY_USAGE_CPU_TO_GPU</a>. You can map it and write to it directly on CPU, as well as read from it on GPU.</p>
+<p>This is a more complex situation. Different solutions are possible, and the best one depends on specific GPU type, but you can use this simple approach for the start. Prefer to write to such resource sequentially (e.g. using <code>memcpy</code>). Don't perform random access or any reads from it on CPU, as it may be very slow.</p>
+<h2><a class="anchor" id="usage_patterns_readback"></a>
+Readback</h2>
+<p><b>When:</b> Resources that contain data written by GPU that you want to read back on CPU, e.g. results of some computations.</p>
+<p><b>What to do:</b> Create them using <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca7b586d2fdaf82a463b58f581ed72be27">VMA_MEMORY_USAGE_GPU_TO_CPU</a>. You can write to them directly on GPU, as well as map and read them on CPU.</p>
+<h1><a class="anchor" id="usage_patterns_advanced"></a>
+Advanced patterns</h1>
+<h2><a class="anchor" id="usage_patterns_integrated_graphics"></a>
+Detecting integrated graphics</h2>
+<p>You can support integrated graphics (like Intel HD Graphics, AMD APU) better by detecting it in Vulkan. To do it, call <code>vkGetPhysicalDeviceProperties()</code>, inspect <code>VkPhysicalDeviceProperties::deviceType</code> and look for <code>VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU</code>. When you find it, you can assume that memory is unified and all memory types are comparably fast to access from GPU, regardless of <code>VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT</code>.</p>
+<p>You can then sum up sizes of all available memory heaps and treat them as useful for your GPU resources, instead of only <code>DEVICE_LOCAL</code> ones. You can also prefer to create your resources in memory types that are <code>HOST_VISIBLE</code> to map them directly instead of submitting explicit transfer (see below).</p>
+<h2><a class="anchor" id="usage_patterns_direct_vs_transfer"></a>
+Direct access versus transfer</h2>
+<p>For resources that you frequently write on CPU and read on GPU, many solutions are possible:</p>
+<ol type="1">
+<li>Create one copy in video memory using <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7">VMA_MEMORY_USAGE_GPU_ONLY</a>, second copy in system memory using <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca40bdf4cddeffeb12f43d45ca1286e0a5">VMA_MEMORY_USAGE_CPU_ONLY</a> and submit explicit tranfer each time.</li>
+<li>Create just single copy using <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca9066b52c5a7079bb74a69aaf8b92ff67">VMA_MEMORY_USAGE_CPU_TO_GPU</a>, map it and fill it on CPU, read it directly on GPU.</li>
+<li>Create just single copy using <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca40bdf4cddeffeb12f43d45ca1286e0a5">VMA_MEMORY_USAGE_CPU_ONLY</a>, map it and fill it on CPU, read it directly on GPU.</li>
+</ol>
+<p>Which solution is the most efficient depends on your resource and especially on the GPU. It is best to measure it and then make the decision. Some general recommendations:</p>
+<ul>
+<li>On integrated graphics use (2) or (3) to avoid unnecesary time and memory overhead related to using a second copy and making transfer.</li>
+<li>For small resources (e.g. constant buffers) use (2). Discrete AMD cards have special 256 MiB pool of video memory that is directly mappable. Even if the resource ends up in system memory, its data may be cached on GPU after first fetch over PCIe bus.</li>
+<li>For larger resources (e.g. textures), decide between (1) and (2). You may want to differentiate NVIDIA and AMD, e.g. by looking for memory type that is both <code>DEVICE_LOCAL</code> and <code>HOST_VISIBLE</code>. When you find it, use (2), otherwise use (1).</li>
+</ul>
+<p>Similarly, for resources that you frequently write on GPU and read on CPU, multiple solutions are possible:</p>
+<ol type="1">
+<li>Create one copy in video memory using <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7">VMA_MEMORY_USAGE_GPU_ONLY</a>, second copy in system memory using <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca7b586d2fdaf82a463b58f581ed72be27">VMA_MEMORY_USAGE_GPU_TO_CPU</a> and submit explicit tranfer each time.</li>
+<li>Create just single copy using <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca7b586d2fdaf82a463b58f581ed72be27">VMA_MEMORY_USAGE_GPU_TO_CPU</a>, write to it directly on GPU, map it and read it on CPU.</li>
+</ol>
+<p>You should take some measurements to decide which option is faster in case of your specific resource.</p>
+<p>If you don't want to specialize your code for specific types of GPUs, you can still make an simple optimization for cases when your resource ends up in mappable memory to use it directly in this case instead of creating CPU-side staging copy. For details see <a class="el" href="memory_mapping.html#memory_mapping_finding_if_memory_mappable">Finding out if memory is mappable</a>. </p>
+</div></div><!-- contents -->
+</div><!-- PageDoc -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/vk__mem__alloc_8h.html b/third_party/VulkanMemoryAllocator/docs/html/vk__mem__alloc_8h.html
new file mode 100644
index 0000000..d8a431a
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/vk__mem__alloc_8h.html
@@ -0,0 +1,3399 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: vk_mem_alloc.h File Reference</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+</div><!-- top -->
+<div class="header">
+  <div class="summary">
+<a href="#nested-classes">Classes</a> &#124;
+<a href="#define-members">Macros</a> &#124;
+<a href="#typedef-members">Typedefs</a> &#124;
+<a href="#enum-members">Enumerations</a> &#124;
+<a href="#func-members">Functions</a>  </div>
+  <div class="headertitle">
+<div class="title">vk_mem_alloc.h File Reference</div>  </div>
+</div><!--header-->
+<div class="contents">
+<div class="textblock"><code>#include &lt;vulkan/vulkan.h&gt;</code><br />
+</div>
+<p><a href="vk__mem__alloc_8h_source.html">Go to the source code of this file.</a></p>
+<table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="nested-classes"></a>
+Classes</h2></td></tr>
+<tr class="memitem:"><td class="memItemLeft" align="right" valign="top">struct &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_device_memory_callbacks.html">VmaDeviceMemoryCallbacks</a></td></tr>
+<tr class="memdesc:"><td class="mdescLeft">&#160;</td><td class="mdescRight">Set of callbacks that the library will call for <code>vkAllocateMemory</code> and <code>vkFreeMemory</code>.  <a href="struct_vma_device_memory_callbacks.html#details">More...</a><br /></td></tr>
+<tr class="separator:"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:"><td class="memItemLeft" align="right" valign="top">struct &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a></td></tr>
+<tr class="memdesc:"><td class="mdescLeft">&#160;</td><td class="mdescRight">Pointers to some Vulkan functions - a subset used by the library.  <a href="struct_vma_vulkan_functions.html#details">More...</a><br /></td></tr>
+<tr class="separator:"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:"><td class="memItemLeft" align="right" valign="top">struct &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_record_settings.html">VmaRecordSettings</a></td></tr>
+<tr class="memdesc:"><td class="mdescLeft">&#160;</td><td class="mdescRight">Parameters for recording calls to VMA functions. To be used in <a class="el" href="struct_vma_allocator_create_info.html#ace2aa4877b16a42b0b7673d4e26000ee" title="Parameters for recording of VMA calls. Can be null.">VmaAllocatorCreateInfo::pRecordSettings</a>.  <a href="struct_vma_record_settings.html#details">More...</a><br /></td></tr>
+<tr class="separator:"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:"><td class="memItemLeft" align="right" valign="top">struct &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a></td></tr>
+<tr class="memdesc:"><td class="mdescLeft">&#160;</td><td class="mdescRight">Description of a Allocator to be created.  <a href="struct_vma_allocator_create_info.html#details">More...</a><br /></td></tr>
+<tr class="separator:"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:"><td class="memItemLeft" align="right" valign="top">struct &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_allocator_info.html">VmaAllocatorInfo</a></td></tr>
+<tr class="memdesc:"><td class="mdescLeft">&#160;</td><td class="mdescRight">Information about existing <a class="el" href="struct_vma_allocator.html" title="Represents main object of this library initialized.">VmaAllocator</a> object.  <a href="struct_vma_allocator_info.html#details">More...</a><br /></td></tr>
+<tr class="separator:"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:"><td class="memItemLeft" align="right" valign="top">struct &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_stat_info.html">VmaStatInfo</a></td></tr>
+<tr class="memdesc:"><td class="mdescLeft">&#160;</td><td class="mdescRight">Calculated statistics of memory usage in entire allocator.  <a href="struct_vma_stat_info.html#details">More...</a><br /></td></tr>
+<tr class="separator:"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:"><td class="memItemLeft" align="right" valign="top">struct &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_stats.html">VmaStats</a></td></tr>
+<tr class="memdesc:"><td class="mdescLeft">&#160;</td><td class="mdescRight">General statistics from current state of Allocator.  <a href="struct_vma_stats.html#details">More...</a><br /></td></tr>
+<tr class="separator:"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:"><td class="memItemLeft" align="right" valign="top">struct &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_budget.html">VmaBudget</a></td></tr>
+<tr class="memdesc:"><td class="mdescLeft">&#160;</td><td class="mdescRight">Statistics of current memory usage and available budget, in bytes, for specific memory heap.  <a href="struct_vma_budget.html#details">More...</a><br /></td></tr>
+<tr class="separator:"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:"><td class="memItemLeft" align="right" valign="top">struct &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a></td></tr>
+<tr class="separator:"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:"><td class="memItemLeft" align="right" valign="top">struct &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_pool_create_info.html">VmaPoolCreateInfo</a></td></tr>
+<tr class="memdesc:"><td class="mdescLeft">&#160;</td><td class="mdescRight">Describes parameter of created <a class="el" href="struct_vma_pool.html" title="Represents custom memory pool.">VmaPool</a>.  <a href="struct_vma_pool_create_info.html#details">More...</a><br /></td></tr>
+<tr class="separator:"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:"><td class="memItemLeft" align="right" valign="top">struct &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_pool_stats.html">VmaPoolStats</a></td></tr>
+<tr class="memdesc:"><td class="mdescLeft">&#160;</td><td class="mdescRight">Describes parameter of existing <a class="el" href="struct_vma_pool.html" title="Represents custom memory pool.">VmaPool</a>.  <a href="struct_vma_pool_stats.html#details">More...</a><br /></td></tr>
+<tr class="separator:"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:"><td class="memItemLeft" align="right" valign="top">struct &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_allocation_info.html">VmaAllocationInfo</a></td></tr>
+<tr class="memdesc:"><td class="mdescLeft">&#160;</td><td class="mdescRight">Parameters of <a class="el" href="struct_vma_allocation.html" title="Represents single memory allocation.">VmaAllocation</a> objects, that can be retrieved using function <a class="el" href="vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b" title="Returns current information about specified allocation and atomically marks it as used in current fra...">vmaGetAllocationInfo()</a>.  <a href="struct_vma_allocation_info.html#details">More...</a><br /></td></tr>
+<tr class="separator:"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:"><td class="memItemLeft" align="right" valign="top">struct &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_defragmentation_info2.html">VmaDefragmentationInfo2</a></td></tr>
+<tr class="memdesc:"><td class="mdescLeft">&#160;</td><td class="mdescRight">Parameters for defragmentation.  <a href="struct_vma_defragmentation_info2.html#details">More...</a><br /></td></tr>
+<tr class="separator:"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:"><td class="memItemLeft" align="right" valign="top">struct &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_defragmentation_pass_move_info.html">VmaDefragmentationPassMoveInfo</a></td></tr>
+<tr class="separator:"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:"><td class="memItemLeft" align="right" valign="top">struct &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_defragmentation_pass_info.html">VmaDefragmentationPassInfo</a></td></tr>
+<tr class="memdesc:"><td class="mdescLeft">&#160;</td><td class="mdescRight">Parameters for incremental defragmentation steps.  <a href="struct_vma_defragmentation_pass_info.html#details">More...</a><br /></td></tr>
+<tr class="separator:"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:"><td class="memItemLeft" align="right" valign="top">struct &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_defragmentation_info.html">VmaDefragmentationInfo</a></td></tr>
+<tr class="memdesc:"><td class="mdescLeft">&#160;</td><td class="mdescRight">Deprecated. Optional configuration parameters to be passed to function <a class="el" href="vk__mem__alloc_8h.html#a6aced90fcc7b39882b6654a740a0b9bb" title="Deprecated. Compacts memory by moving allocations.">vmaDefragment()</a>.  <a href="struct_vma_defragmentation_info.html#details">More...</a><br /></td></tr>
+<tr class="separator:"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:"><td class="memItemLeft" align="right" valign="top">struct &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="struct_vma_defragmentation_stats.html">VmaDefragmentationStats</a></td></tr>
+<tr class="memdesc:"><td class="mdescLeft">&#160;</td><td class="mdescRight">Statistics returned by function <a class="el" href="vk__mem__alloc_8h.html#a6aced90fcc7b39882b6654a740a0b9bb" title="Deprecated. Compacts memory by moving allocations.">vmaDefragment()</a>.  <a href="struct_vma_defragmentation_stats.html#details">More...</a><br /></td></tr>
+<tr class="separator:"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="define-members"></a>
+Macros</h2></td></tr>
+<tr class="memitem:a1f0c126759fc96ccb6e2d23c101d770c"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a1f0c126759fc96ccb6e2d23c101d770c">VMA_RECORDING_ENABLED</a>&#160;&#160;&#160;0</td></tr>
+<tr class="separator:a1f0c126759fc96ccb6e2d23c101d770c"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a9f918755b601cf4bffca775992e6fb90"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a9f918755b601cf4bffca775992e6fb90">NOMINMAX</a></td></tr>
+<tr class="separator:a9f918755b601cf4bffca775992e6fb90"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a1a2407c283893638cc039bb31fcd74b6"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a1a2407c283893638cc039bb31fcd74b6">VMA_VULKAN_VERSION</a>&#160;&#160;&#160;1000000</td></tr>
+<tr class="separator:a1a2407c283893638cc039bb31fcd74b6"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:af7b860e63b96d11e44ae8587ba06bbf4"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#af7b860e63b96d11e44ae8587ba06bbf4">VMA_DEDICATED_ALLOCATION</a>&#160;&#160;&#160;0</td></tr>
+<tr class="separator:af7b860e63b96d11e44ae8587ba06bbf4"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a88bef97f86d70a34a4c0746e09a2680d"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a88bef97f86d70a34a4c0746e09a2680d">VMA_BIND_MEMORY2</a>&#160;&#160;&#160;0</td></tr>
+<tr class="separator:a88bef97f86d70a34a4c0746e09a2680d"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a05decf1cf4ebf767beba7acca6c1ec3a"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a05decf1cf4ebf767beba7acca6c1ec3a">VMA_MEMORY_BUDGET</a>&#160;&#160;&#160;0</td></tr>
+<tr class="separator:a05decf1cf4ebf767beba7acca6c1ec3a"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a7f9d5e71b70dd1a137c303a8a8262c10"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a7f9d5e71b70dd1a137c303a8a8262c10">VMA_BUFFER_DEVICE_ADDRESS</a>&#160;&#160;&#160;0</td></tr>
+<tr class="separator:a7f9d5e71b70dd1a137c303a8a8262c10"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ae25f0d55fd91cb166f002b63244800e1"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#ae25f0d55fd91cb166f002b63244800e1">VMA_STATS_STRING_ENABLED</a>&#160;&#160;&#160;1</td></tr>
+<tr class="separator:ae25f0d55fd91cb166f002b63244800e1"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="typedef-members"></a>
+Typedefs</h2></td></tr>
+<tr class="memitem:a7e1ed85f7799600b03ad51a77acc21f3"><td class="memItemLeft" align="right" valign="top">typedef void(VKAPI_PTR *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a7e1ed85f7799600b03ad51a77acc21f3">PFN_vmaAllocateDeviceMemoryFunction</a>) (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, uint32_t memoryType, VkDeviceMemory memory, VkDeviceSize size, void *pUserData)</td></tr>
+<tr class="memdesc:a7e1ed85f7799600b03ad51a77acc21f3"><td class="mdescLeft">&#160;</td><td class="mdescRight">Callback function called after successful vkAllocateMemory.  <a href="vk__mem__alloc_8h.html#a7e1ed85f7799600b03ad51a77acc21f3">More...</a><br /></td></tr>
+<tr class="separator:a7e1ed85f7799600b03ad51a77acc21f3"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a154ccaaf53dc2c36378f80f0c4f3679b"><td class="memItemLeft" align="right" valign="top">typedef void(VKAPI_PTR *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a154ccaaf53dc2c36378f80f0c4f3679b">PFN_vmaFreeDeviceMemoryFunction</a>) (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, uint32_t memoryType, VkDeviceMemory memory, VkDeviceSize size, void *pUserData)</td></tr>
+<tr class="memdesc:a154ccaaf53dc2c36378f80f0c4f3679b"><td class="mdescLeft">&#160;</td><td class="mdescRight">Callback function called before vkFreeMemory.  <a href="vk__mem__alloc_8h.html#a154ccaaf53dc2c36378f80f0c4f3679b">More...</a><br /></td></tr>
+<tr class="separator:a154ccaaf53dc2c36378f80f0c4f3679b"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a77692d3c8770ea8882d573206bd27b2b"><td class="memItemLeft" align="right" valign="top">typedef struct <a class="el" href="struct_vma_device_memory_callbacks.html">VmaDeviceMemoryCallbacks</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a77692d3c8770ea8882d573206bd27b2b">VmaDeviceMemoryCallbacks</a></td></tr>
+<tr class="memdesc:a77692d3c8770ea8882d573206bd27b2b"><td class="mdescLeft">&#160;</td><td class="mdescRight">Set of callbacks that the library will call for <code>vkAllocateMemory</code> and <code>vkFreeMemory</code>.  <a href="vk__mem__alloc_8h.html#a77692d3c8770ea8882d573206bd27b2b">More...</a><br /></td></tr>
+<tr class="separator:a77692d3c8770ea8882d573206bd27b2b"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:afd73b95e737ee7e76f827cb5472f559f"><td class="memItemLeft" align="right" valign="top">typedef enum <a class="el" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7c">VmaAllocatorCreateFlagBits</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#afd73b95e737ee7e76f827cb5472f559f">VmaAllocatorCreateFlagBits</a></td></tr>
+<tr class="memdesc:afd73b95e737ee7e76f827cb5472f559f"><td class="mdescLeft">&#160;</td><td class="mdescRight">Flags for created <a class="el" href="struct_vma_allocator.html" title="Represents main object of this library initialized.">VmaAllocator</a>.  <a href="vk__mem__alloc_8h.html#afd73b95e737ee7e76f827cb5472f559f">More...</a><br /></td></tr>
+<tr class="separator:afd73b95e737ee7e76f827cb5472f559f"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:acfe6863e160722c2c1bbcf7573fddc4d"><td class="memItemLeft" align="right" valign="top">typedef VkFlags&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#acfe6863e160722c2c1bbcf7573fddc4d">VmaAllocatorCreateFlags</a></td></tr>
+<tr class="separator:acfe6863e160722c2c1bbcf7573fddc4d"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:abb0a8e3b5040d847571cca6c7f9a8074"><td class="memItemLeft" align="right" valign="top">typedef struct <a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#abb0a8e3b5040d847571cca6c7f9a8074">VmaVulkanFunctions</a></td></tr>
+<tr class="memdesc:abb0a8e3b5040d847571cca6c7f9a8074"><td class="mdescLeft">&#160;</td><td class="mdescRight">Pointers to some Vulkan functions - a subset used by the library.  <a href="vk__mem__alloc_8h.html#abb0a8e3b5040d847571cca6c7f9a8074">More...</a><br /></td></tr>
+<tr class="separator:abb0a8e3b5040d847571cca6c7f9a8074"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:acd24d5eb58abff7e1f43cb32a1ba1413"><td class="memItemLeft" align="right" valign="top">typedef enum <a class="el" href="vk__mem__alloc_8h.html#a4dd2c44642312a147a4e93373a6e64d2">VmaRecordFlagBits</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#acd24d5eb58abff7e1f43cb32a1ba1413">VmaRecordFlagBits</a></td></tr>
+<tr class="memdesc:acd24d5eb58abff7e1f43cb32a1ba1413"><td class="mdescLeft">&#160;</td><td class="mdescRight">Flags to be used in <a class="el" href="struct_vma_record_settings.html#ad8fdcc92119ae7a8c08c1a564c01d63a" title="Flags for recording. Use VmaRecordFlagBits enum.">VmaRecordSettings::flags</a>.  <a href="vk__mem__alloc_8h.html#acd24d5eb58abff7e1f43cb32a1ba1413">More...</a><br /></td></tr>
+<tr class="separator:acd24d5eb58abff7e1f43cb32a1ba1413"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:af3929a1a4547c592fc0b0e55ef452828"><td class="memItemLeft" align="right" valign="top">typedef VkFlags&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#af3929a1a4547c592fc0b0e55ef452828">VmaRecordFlags</a></td></tr>
+<tr class="separator:af3929a1a4547c592fc0b0e55ef452828"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a16e21c877101493fce582664cd8754fc"><td class="memItemLeft" align="right" valign="top">typedef struct <a class="el" href="struct_vma_record_settings.html">VmaRecordSettings</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a16e21c877101493fce582664cd8754fc">VmaRecordSettings</a></td></tr>
+<tr class="memdesc:a16e21c877101493fce582664cd8754fc"><td class="mdescLeft">&#160;</td><td class="mdescRight">Parameters for recording calls to VMA functions. To be used in <a class="el" href="struct_vma_allocator_create_info.html#ace2aa4877b16a42b0b7673d4e26000ee" title="Parameters for recording of VMA calls. Can be null.">VmaAllocatorCreateInfo::pRecordSettings</a>.  <a href="vk__mem__alloc_8h.html#a16e21c877101493fce582664cd8754fc">More...</a><br /></td></tr>
+<tr class="separator:a16e21c877101493fce582664cd8754fc"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:aad9652301d33759b83e52d4f3605a14a"><td class="memItemLeft" align="right" valign="top">typedef struct <a class="el" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#aad9652301d33759b83e52d4f3605a14a">VmaAllocatorCreateInfo</a></td></tr>
+<tr class="memdesc:aad9652301d33759b83e52d4f3605a14a"><td class="mdescLeft">&#160;</td><td class="mdescRight">Description of a Allocator to be created.  <a href="vk__mem__alloc_8h.html#aad9652301d33759b83e52d4f3605a14a">More...</a><br /></td></tr>
+<tr class="separator:aad9652301d33759b83e52d4f3605a14a"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a1988031b0223fdbd564250fa1edd942c"><td class="memItemLeft" align="right" valign="top">typedef struct <a class="el" href="struct_vma_allocator_info.html">VmaAllocatorInfo</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a1988031b0223fdbd564250fa1edd942c">VmaAllocatorInfo</a></td></tr>
+<tr class="memdesc:a1988031b0223fdbd564250fa1edd942c"><td class="mdescLeft">&#160;</td><td class="mdescRight">Information about existing <a class="el" href="struct_vma_allocator.html" title="Represents main object of this library initialized.">VmaAllocator</a> object.  <a href="vk__mem__alloc_8h.html#a1988031b0223fdbd564250fa1edd942c">More...</a><br /></td></tr>
+<tr class="separator:a1988031b0223fdbd564250fa1edd942c"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:aec5b57e29c97b5d69c6d5654d60df878"><td class="memItemLeft" align="right" valign="top">typedef struct <a class="el" href="struct_vma_stat_info.html">VmaStatInfo</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#aec5b57e29c97b5d69c6d5654d60df878">VmaStatInfo</a></td></tr>
+<tr class="memdesc:aec5b57e29c97b5d69c6d5654d60df878"><td class="mdescLeft">&#160;</td><td class="mdescRight">Calculated statistics of memory usage in entire allocator.  <a href="vk__mem__alloc_8h.html#aec5b57e29c97b5d69c6d5654d60df878">More...</a><br /></td></tr>
+<tr class="separator:aec5b57e29c97b5d69c6d5654d60df878"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a21813b2efdf3836767a9058cd8a94034"><td class="memItemLeft" align="right" valign="top">typedef struct <a class="el" href="struct_vma_stats.html">VmaStats</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a21813b2efdf3836767a9058cd8a94034">VmaStats</a></td></tr>
+<tr class="memdesc:a21813b2efdf3836767a9058cd8a94034"><td class="mdescLeft">&#160;</td><td class="mdescRight">General statistics from current state of Allocator.  <a href="vk__mem__alloc_8h.html#a21813b2efdf3836767a9058cd8a94034">More...</a><br /></td></tr>
+<tr class="separator:a21813b2efdf3836767a9058cd8a94034"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:aa078667e71b1ef24e87a6a30d128381d"><td class="memItemLeft" align="right" valign="top">typedef struct <a class="el" href="struct_vma_budget.html">VmaBudget</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#aa078667e71b1ef24e87a6a30d128381d">VmaBudget</a></td></tr>
+<tr class="memdesc:aa078667e71b1ef24e87a6a30d128381d"><td class="mdescLeft">&#160;</td><td class="mdescRight">Statistics of current memory usage and available budget, in bytes, for specific memory heap.  <a href="vk__mem__alloc_8h.html#aa078667e71b1ef24e87a6a30d128381d">More...</a><br /></td></tr>
+<tr class="separator:aa078667e71b1ef24e87a6a30d128381d"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a806e8499dde802e59eb72a1dc811c35f"><td class="memItemLeft" align="right" valign="top">typedef enum <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cc">VmaMemoryUsage</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a806e8499dde802e59eb72a1dc811c35f">VmaMemoryUsage</a></td></tr>
+<tr class="separator:a806e8499dde802e59eb72a1dc811c35f"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a4fceecc301f4064dc808d3cd6c038941"><td class="memItemLeft" align="right" valign="top">typedef enum <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597">VmaAllocationCreateFlagBits</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a4fceecc301f4064dc808d3cd6c038941">VmaAllocationCreateFlagBits</a></td></tr>
+<tr class="memdesc:a4fceecc301f4064dc808d3cd6c038941"><td class="mdescLeft">&#160;</td><td class="mdescRight">Flags to be passed as <a class="el" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b" title="Use VmaAllocationCreateFlagBits enum.">VmaAllocationCreateInfo::flags</a>.  <a href="vk__mem__alloc_8h.html#a4fceecc301f4064dc808d3cd6c038941">More...</a><br /></td></tr>
+<tr class="separator:a4fceecc301f4064dc808d3cd6c038941"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a5225e5e11f8376f6a31a1791f3d6e817"><td class="memItemLeft" align="right" valign="top">typedef VkFlags&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a5225e5e11f8376f6a31a1791f3d6e817">VmaAllocationCreateFlags</a></td></tr>
+<tr class="separator:a5225e5e11f8376f6a31a1791f3d6e817"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a3bf110892ea2fb4649fedb68488d026a"><td class="memItemLeft" align="right" valign="top">typedef struct <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a3bf110892ea2fb4649fedb68488d026a">VmaAllocationCreateInfo</a></td></tr>
+<tr class="separator:a3bf110892ea2fb4649fedb68488d026a"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a4d4f2efc2509157a9e4ecd4fd7942303"><td class="memItemLeft" align="right" valign="top">typedef enum <a class="el" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7">VmaPoolCreateFlagBits</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a4d4f2efc2509157a9e4ecd4fd7942303">VmaPoolCreateFlagBits</a></td></tr>
+<tr class="memdesc:a4d4f2efc2509157a9e4ecd4fd7942303"><td class="mdescLeft">&#160;</td><td class="mdescRight">Flags to be passed as <a class="el" href="struct_vma_pool_create_info.html#a8405139f63d078340ae74513a59f5446" title="Use combination of VmaPoolCreateFlagBits.">VmaPoolCreateInfo::flags</a>.  <a href="vk__mem__alloc_8h.html#a4d4f2efc2509157a9e4ecd4fd7942303">More...</a><br /></td></tr>
+<tr class="separator:a4d4f2efc2509157a9e4ecd4fd7942303"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a2770e325ea42e087c1b91fdf46d0292a"><td class="memItemLeft" align="right" valign="top">typedef VkFlags&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a2770e325ea42e087c1b91fdf46d0292a">VmaPoolCreateFlags</a></td></tr>
+<tr class="separator:a2770e325ea42e087c1b91fdf46d0292a"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a1017aa83489c0eee8d2163d2bf253f67"><td class="memItemLeft" align="right" valign="top">typedef struct <a class="el" href="struct_vma_pool_create_info.html">VmaPoolCreateInfo</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a1017aa83489c0eee8d2163d2bf253f67">VmaPoolCreateInfo</a></td></tr>
+<tr class="memdesc:a1017aa83489c0eee8d2163d2bf253f67"><td class="mdescLeft">&#160;</td><td class="mdescRight">Describes parameter of created <a class="el" href="struct_vma_pool.html" title="Represents custom memory pool.">VmaPool</a>.  <a href="vk__mem__alloc_8h.html#a1017aa83489c0eee8d2163d2bf253f67">More...</a><br /></td></tr>
+<tr class="separator:a1017aa83489c0eee8d2163d2bf253f67"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a4759a2d9f99c19ba7627553c847132f1"><td class="memItemLeft" align="right" valign="top">typedef struct <a class="el" href="struct_vma_pool_stats.html">VmaPoolStats</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a4759a2d9f99c19ba7627553c847132f1">VmaPoolStats</a></td></tr>
+<tr class="memdesc:a4759a2d9f99c19ba7627553c847132f1"><td class="mdescLeft">&#160;</td><td class="mdescRight">Describes parameter of existing <a class="el" href="struct_vma_pool.html" title="Represents custom memory pool.">VmaPool</a>.  <a href="vk__mem__alloc_8h.html#a4759a2d9f99c19ba7627553c847132f1">More...</a><br /></td></tr>
+<tr class="separator:a4759a2d9f99c19ba7627553c847132f1"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a1cf7774606721026a68aabe3af2e5b50"><td class="memItemLeft" align="right" valign="top">typedef struct <a class="el" href="struct_vma_allocation_info.html">VmaAllocationInfo</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a1cf7774606721026a68aabe3af2e5b50">VmaAllocationInfo</a></td></tr>
+<tr class="memdesc:a1cf7774606721026a68aabe3af2e5b50"><td class="mdescLeft">&#160;</td><td class="mdescRight">Parameters of <a class="el" href="struct_vma_allocation.html" title="Represents single memory allocation.">VmaAllocation</a> objects, that can be retrieved using function <a class="el" href="vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b" title="Returns current information about specified allocation and atomically marks it as used in current fra...">vmaGetAllocationInfo()</a>.  <a href="vk__mem__alloc_8h.html#a1cf7774606721026a68aabe3af2e5b50">More...</a><br /></td></tr>
+<tr class="separator:a1cf7774606721026a68aabe3af2e5b50"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a13415cc0b443353a7b5abda300b833fc"><td class="memItemLeft" align="right" valign="top">typedef enum <a class="el" href="vk__mem__alloc_8h.html#a6552a65b71d16f378c6994b3ceaef50c">VmaDefragmentationFlagBits</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a13415cc0b443353a7b5abda300b833fc">VmaDefragmentationFlagBits</a></td></tr>
+<tr class="memdesc:a13415cc0b443353a7b5abda300b833fc"><td class="mdescLeft">&#160;</td><td class="mdescRight">Flags to be used in <a class="el" href="vk__mem__alloc_8h.html#a36ba776fd7fd5cb1e9359fdc0d8e6e8a" title="Begins defragmentation process.">vmaDefragmentationBegin()</a>. None at the moment. Reserved for future use.  <a href="vk__mem__alloc_8h.html#a13415cc0b443353a7b5abda300b833fc">More...</a><br /></td></tr>
+<tr class="separator:a13415cc0b443353a7b5abda300b833fc"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a88a77cef37e5d3c4fc9eb328885d048d"><td class="memItemLeft" align="right" valign="top">typedef VkFlags&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a88a77cef37e5d3c4fc9eb328885d048d">VmaDefragmentationFlags</a></td></tr>
+<tr class="separator:a88a77cef37e5d3c4fc9eb328885d048d"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ad6daeffaa670ce6d11a203a6224c9937"><td class="memItemLeft" align="right" valign="top">typedef struct <a class="el" href="struct_vma_defragmentation_info2.html">VmaDefragmentationInfo2</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#ad6daeffaa670ce6d11a203a6224c9937">VmaDefragmentationInfo2</a></td></tr>
+<tr class="memdesc:ad6daeffaa670ce6d11a203a6224c9937"><td class="mdescLeft">&#160;</td><td class="mdescRight">Parameters for defragmentation.  <a href="vk__mem__alloc_8h.html#ad6daeffaa670ce6d11a203a6224c9937">More...</a><br /></td></tr>
+<tr class="separator:ad6daeffaa670ce6d11a203a6224c9937"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ad6799e8e2b1527abfc84d33bc44aeaf5"><td class="memItemLeft" align="right" valign="top">typedef struct <a class="el" href="struct_vma_defragmentation_pass_move_info.html">VmaDefragmentationPassMoveInfo</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#ad6799e8e2b1527abfc84d33bc44aeaf5">VmaDefragmentationPassMoveInfo</a></td></tr>
+<tr class="separator:ad6799e8e2b1527abfc84d33bc44aeaf5"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a72aebd522242d56abea67b4f47f6549e"><td class="memItemLeft" align="right" valign="top">typedef struct <a class="el" href="struct_vma_defragmentation_pass_info.html">VmaDefragmentationPassInfo</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a72aebd522242d56abea67b4f47f6549e">VmaDefragmentationPassInfo</a></td></tr>
+<tr class="memdesc:a72aebd522242d56abea67b4f47f6549e"><td class="mdescLeft">&#160;</td><td class="mdescRight">Parameters for incremental defragmentation steps.  <a href="vk__mem__alloc_8h.html#a72aebd522242d56abea67b4f47f6549e">More...</a><br /></td></tr>
+<tr class="separator:a72aebd522242d56abea67b4f47f6549e"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a2bf47f96bf92bed2a49461bd9af3acfa"><td class="memItemLeft" align="right" valign="top">typedef struct <a class="el" href="struct_vma_defragmentation_info.html">VmaDefragmentationInfo</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a2bf47f96bf92bed2a49461bd9af3acfa">VmaDefragmentationInfo</a></td></tr>
+<tr class="memdesc:a2bf47f96bf92bed2a49461bd9af3acfa"><td class="mdescLeft">&#160;</td><td class="mdescRight">Deprecated. Optional configuration parameters to be passed to function <a class="el" href="vk__mem__alloc_8h.html#a6aced90fcc7b39882b6654a740a0b9bb" title="Deprecated. Compacts memory by moving allocations.">vmaDefragment()</a>.  <a href="vk__mem__alloc_8h.html#a2bf47f96bf92bed2a49461bd9af3acfa">More...</a><br /></td></tr>
+<tr class="separator:a2bf47f96bf92bed2a49461bd9af3acfa"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ad94034192259c2e34a4d1c5e27810403"><td class="memItemLeft" align="right" valign="top">typedef struct <a class="el" href="struct_vma_defragmentation_stats.html">VmaDefragmentationStats</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#ad94034192259c2e34a4d1c5e27810403">VmaDefragmentationStats</a></td></tr>
+<tr class="memdesc:ad94034192259c2e34a4d1c5e27810403"><td class="mdescLeft">&#160;</td><td class="mdescRight">Statistics returned by function <a class="el" href="vk__mem__alloc_8h.html#a6aced90fcc7b39882b6654a740a0b9bb" title="Deprecated. Compacts memory by moving allocations.">vmaDefragment()</a>.  <a href="vk__mem__alloc_8h.html#ad94034192259c2e34a4d1c5e27810403">More...</a><br /></td></tr>
+<tr class="separator:ad94034192259c2e34a4d1c5e27810403"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="enum-members"></a>
+Enumerations</h2></td></tr>
+<tr class="memitem:a4f87c9100d154a65a4ad495f7763cf7c"><td class="memItemLeft" align="right" valign="top">enum &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7c">VmaAllocatorCreateFlagBits</a> { <br />
+&#160;&#160;<a class="el" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca4816ddaed324ba110172ca608a20f29d">VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT</a> = 0x00000001, 
+<a class="el" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7cace7da7cc6e71a625dfa763c55a597878">VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT</a> = 0x00000002, 
+<a class="el" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca8fb75bf07cd184ab903596295e863dee">VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT</a> = 0x00000004, 
+<a class="el" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca4d4687863f7bd4b418c6006dc04400b0">VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT</a> = 0x00000008, 
+<br />
+&#160;&#160;<a class="el" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca2acce4886d8078552efa38878413970f">VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT</a> = 0x00000010, 
+<a class="el" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca5f1b28b0414319d1687e1f2b30ab0089">VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT</a> = 0x00000020, 
+<a class="el" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7cae4d5ad929caba5f23eb502b13bd5286c">VMA_ALLOCATOR_CREATE_FLAG_BITS_MAX_ENUM</a> = 0x7FFFFFFF
+<br />
+ }</td></tr>
+<tr class="memdesc:a4f87c9100d154a65a4ad495f7763cf7c"><td class="mdescLeft">&#160;</td><td class="mdescRight">Flags for created <a class="el" href="struct_vma_allocator.html" title="Represents main object of this library initialized.">VmaAllocator</a>.  <a href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7c">More...</a><br /></td></tr>
+<tr class="separator:a4f87c9100d154a65a4ad495f7763cf7c"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a4dd2c44642312a147a4e93373a6e64d2"><td class="memItemLeft" align="right" valign="top">enum &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a4dd2c44642312a147a4e93373a6e64d2">VmaRecordFlagBits</a> { <a class="el" href="vk__mem__alloc_8h.html#a4dd2c44642312a147a4e93373a6e64d2a8e7ab322e8732654be627c4ea8f36cc7">VMA_RECORD_FLUSH_AFTER_CALL_BIT</a> = 0x00000001, 
+<a class="el" href="vk__mem__alloc_8h.html#a4dd2c44642312a147a4e93373a6e64d2a20dd17d69966dbffa054739d6090b85e">VMA_RECORD_FLAG_BITS_MAX_ENUM</a> = 0x7FFFFFFF
+ }</td></tr>
+<tr class="memdesc:a4dd2c44642312a147a4e93373a6e64d2"><td class="mdescLeft">&#160;</td><td class="mdescRight">Flags to be used in <a class="el" href="struct_vma_record_settings.html#ad8fdcc92119ae7a8c08c1a564c01d63a" title="Flags for recording. Use VmaRecordFlagBits enum.">VmaRecordSettings::flags</a>.  <a href="vk__mem__alloc_8h.html#a4dd2c44642312a147a4e93373a6e64d2">More...</a><br /></td></tr>
+<tr class="separator:a4dd2c44642312a147a4e93373a6e64d2"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:aa5846affa1e9da3800e3e78fae2305cc"><td class="memItemLeft" align="right" valign="top">enum &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cc">VmaMemoryUsage</a> { <br />
+&#160;&#160;<a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccaf50d27e34e0925cf3a63db8c839121dd">VMA_MEMORY_USAGE_UNKNOWN</a> = 0, 
+<a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7">VMA_MEMORY_USAGE_GPU_ONLY</a> = 1, 
+<a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca40bdf4cddeffeb12f43d45ca1286e0a5">VMA_MEMORY_USAGE_CPU_ONLY</a> = 2, 
+<a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca9066b52c5a7079bb74a69aaf8b92ff67">VMA_MEMORY_USAGE_CPU_TO_GPU</a> = 3, 
+<br />
+&#160;&#160;<a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca7b586d2fdaf82a463b58f581ed72be27">VMA_MEMORY_USAGE_GPU_TO_CPU</a> = 4, 
+<a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca416a444d4d0fc20067c3f76f32ff2500">VMA_MEMORY_USAGE_CPU_COPY</a> = 5, 
+<a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca835333d9072db63a653818030e17614d">VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED</a> = 6, 
+<a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca091e69437ef693e8d0d287f1c719ba6e">VMA_MEMORY_USAGE_MAX_ENUM</a> = 0x7FFFFFFF
+<br />
+ }</td></tr>
+<tr class="separator:aa5846affa1e9da3800e3e78fae2305cc"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ad9889c10c798b040d59c92f257cae597"><td class="memItemLeft" align="right" valign="top">enum &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597">VmaAllocationCreateFlagBits</a> { <br />
+&#160;&#160;<a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a3fc311d855c2ff53f1090ef5c722b38f">VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT</a> = 0x00000001, 
+<a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a89759603401014eb325eb22a3839f2ff">VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT</a> = 0x00000002, 
+<a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a11da372cc3a82931c5e5d6146cd9dd1f">VMA_ALLOCATION_CREATE_MAPPED_BIT</a> = 0x00000004, 
+<a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a5f436af6c8fe8540573a6d22627a6fd2">VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT</a> = 0x00000008, 
+<br />
+&#160;&#160;<a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a68686d0ce9beb0d4d1b9f2b8b1389a7e">VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT</a> = 0x00000010, 
+<a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597aa6f24f821cd6a7c5e4a443f7bf59c520">VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT</a> = 0x00000020, 
+<a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a42ba3a2d2c7117953210b7c3ef8da0df">VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT</a> = 0x00000040, 
+<a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a2310568c62208af432724305fe29ccea">VMA_ALLOCATION_CREATE_DONT_BIND_BIT</a> = 0x00000080, 
+<br />
+&#160;&#160;<a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597ab8b1764f3e9022368e440c057783b92d">VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT</a> = 0x00000100, 
+<a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a839826775c62319466441f86496f036d">VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT</a> = 0x00010000, 
+<a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597ad242a04f802e25fef0b880afe8bb0a62">VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT</a> = 0x00020000, 
+<a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a33eb2052674f3ad92386c714a65fb777">VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT</a> = 0x00040000, 
+<br />
+&#160;&#160;<a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a8af1210cf591784afa026d94998f735d">VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT</a> = VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT, 
+<a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a0729e932b7ea170e3a128cad96c5cf6d">VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT</a> = VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT, 
+<a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a621b704103eb3360230c860acf36e706">VMA_ALLOCATION_CREATE_STRATEGY_MIN_FRAGMENTATION_BIT</a> = VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT, 
+<a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a8e16845d81ae3d27c47106d4770d5c7e">VMA_ALLOCATION_CREATE_STRATEGY_MASK</a>, 
+<br />
+&#160;&#160;<a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597ae5633ec569f4899cf8f29e7385b2f882">VMA_ALLOCATION_CREATE_FLAG_BITS_MAX_ENUM</a> = 0x7FFFFFFF
+<br />
+ }</td></tr>
+<tr class="memdesc:ad9889c10c798b040d59c92f257cae597"><td class="mdescLeft">&#160;</td><td class="mdescRight">Flags to be passed as <a class="el" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b" title="Use VmaAllocationCreateFlagBits enum.">VmaAllocationCreateInfo::flags</a>.  <a href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597">More...</a><br /></td></tr>
+<tr class="separator:ad9889c10c798b040d59c92f257cae597"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a9a7c45f9c863695d98c83fa5ac940fe7"><td class="memItemLeft" align="right" valign="top">enum &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7">VmaPoolCreateFlagBits</a> { <br />
+&#160;&#160;<a class="el" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a9f1a499508a8edb4e8ba40aa0290a3d2">VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT</a> = 0x00000002, 
+<a class="el" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a13c8a444197c67866be9cb05599fc726">VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT</a> = 0x00000004, 
+<a class="el" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a97a0dc38e5161b780594d998d313d35e">VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT</a> = 0x00000008, 
+<a class="el" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7af4d270f8f42517a0f70037ceb6ac1d9c">VMA_POOL_CREATE_ALGORITHM_MASK</a>, 
+<br />
+&#160;&#160;<a class="el" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a1c7312bea9ea246846b9054fd6bd6aec">VMA_POOL_CREATE_FLAG_BITS_MAX_ENUM</a> = 0x7FFFFFFF
+<br />
+ }</td></tr>
+<tr class="memdesc:a9a7c45f9c863695d98c83fa5ac940fe7"><td class="mdescLeft">&#160;</td><td class="mdescRight">Flags to be passed as <a class="el" href="struct_vma_pool_create_info.html#a8405139f63d078340ae74513a59f5446" title="Use combination of VmaPoolCreateFlagBits.">VmaPoolCreateInfo::flags</a>.  <a href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7">More...</a><br /></td></tr>
+<tr class="separator:a9a7c45f9c863695d98c83fa5ac940fe7"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a6552a65b71d16f378c6994b3ceaef50c"><td class="memItemLeft" align="right" valign="top">enum &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a6552a65b71d16f378c6994b3ceaef50c">VmaDefragmentationFlagBits</a> { <a class="el" href="vk__mem__alloc_8h.html#a6552a65b71d16f378c6994b3ceaef50ca31af49446af2459284a568ce2f3fdd33">VMA_DEFRAGMENTATION_FLAG_INCREMENTAL</a> = 0x1, 
+<a class="el" href="vk__mem__alloc_8h.html#a6552a65b71d16f378c6994b3ceaef50cab87ec33154803bfeb5ac2b379f1d6a97">VMA_DEFRAGMENTATION_FLAG_BITS_MAX_ENUM</a> = 0x7FFFFFFF
+ }</td></tr>
+<tr class="memdesc:a6552a65b71d16f378c6994b3ceaef50c"><td class="mdescLeft">&#160;</td><td class="mdescRight">Flags to be used in <a class="el" href="vk__mem__alloc_8h.html#a36ba776fd7fd5cb1e9359fdc0d8e6e8a" title="Begins defragmentation process.">vmaDefragmentationBegin()</a>. None at the moment. Reserved for future use.  <a href="vk__mem__alloc_8h.html#a6552a65b71d16f378c6994b3ceaef50c">More...</a><br /></td></tr>
+<tr class="separator:a6552a65b71d16f378c6994b3ceaef50c"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table><table class="memberdecls">
+<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
+Functions</h2></td></tr>
+<tr class="memitem:a200692051ddb34240248234f5f4c17bb"><td class="memItemLeft" align="right" valign="top">VkResult&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a200692051ddb34240248234f5f4c17bb">vmaCreateAllocator</a> (const <a class="el" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a> *pCreateInfo, <a class="el" href="struct_vma_allocator.html">VmaAllocator</a> *pAllocator)</td></tr>
+<tr class="memdesc:a200692051ddb34240248234f5f4c17bb"><td class="mdescLeft">&#160;</td><td class="mdescRight">Creates Allocator object.  <a href="vk__mem__alloc_8h.html#a200692051ddb34240248234f5f4c17bb">More...</a><br /></td></tr>
+<tr class="separator:a200692051ddb34240248234f5f4c17bb"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:aa8d164061c88f22fb1fd3c8f3534bc1d"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#aa8d164061c88f22fb1fd3c8f3534bc1d">vmaDestroyAllocator</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator)</td></tr>
+<tr class="memdesc:aa8d164061c88f22fb1fd3c8f3534bc1d"><td class="mdescLeft">&#160;</td><td class="mdescRight">Destroys allocator object.  <a href="vk__mem__alloc_8h.html#aa8d164061c88f22fb1fd3c8f3534bc1d">More...</a><br /></td></tr>
+<tr class="separator:aa8d164061c88f22fb1fd3c8f3534bc1d"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:afa02231a791b37255720d566a52683e7"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#afa02231a791b37255720d566a52683e7">vmaGetAllocatorInfo</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, <a class="el" href="struct_vma_allocator_info.html">VmaAllocatorInfo</a> *pAllocatorInfo)</td></tr>
+<tr class="memdesc:afa02231a791b37255720d566a52683e7"><td class="mdescLeft">&#160;</td><td class="mdescRight">Returns information about existing <a class="el" href="struct_vma_allocator.html" title="Represents main object of this library initialized.">VmaAllocator</a> object - handle to Vulkan device etc.  <a href="vk__mem__alloc_8h.html#afa02231a791b37255720d566a52683e7">More...</a><br /></td></tr>
+<tr class="separator:afa02231a791b37255720d566a52683e7"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:aecabf7b6e91ea87d0316fa0a9e014fe0"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#aecabf7b6e91ea87d0316fa0a9e014fe0">vmaGetPhysicalDeviceProperties</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, const VkPhysicalDeviceProperties **ppPhysicalDeviceProperties)</td></tr>
+<tr class="separator:aecabf7b6e91ea87d0316fa0a9e014fe0"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ab88db292a17974f911182543fda52d19"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#ab88db292a17974f911182543fda52d19">vmaGetMemoryProperties</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, const VkPhysicalDeviceMemoryProperties **ppPhysicalDeviceMemoryProperties)</td></tr>
+<tr class="separator:ab88db292a17974f911182543fda52d19"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a8701444752eb5de4464adb5a2b514bca"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a8701444752eb5de4464adb5a2b514bca">vmaGetMemoryTypeProperties</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, uint32_t memoryTypeIndex, VkMemoryPropertyFlags *pFlags)</td></tr>
+<tr class="memdesc:a8701444752eb5de4464adb5a2b514bca"><td class="mdescLeft">&#160;</td><td class="mdescRight">Given Memory Type Index, returns Property Flags of this memory type.  <a href="vk__mem__alloc_8h.html#a8701444752eb5de4464adb5a2b514bca">More...</a><br /></td></tr>
+<tr class="separator:a8701444752eb5de4464adb5a2b514bca"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ade56bf8dc9f5a5eaddf5f119ed525236"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#ade56bf8dc9f5a5eaddf5f119ed525236">vmaSetCurrentFrameIndex</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, uint32_t frameIndex)</td></tr>
+<tr class="memdesc:ade56bf8dc9f5a5eaddf5f119ed525236"><td class="mdescLeft">&#160;</td><td class="mdescRight">Sets index of the current frame.  <a href="vk__mem__alloc_8h.html#ade56bf8dc9f5a5eaddf5f119ed525236">More...</a><br /></td></tr>
+<tr class="separator:ade56bf8dc9f5a5eaddf5f119ed525236"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a333b61c1788cb23559177531e6a93ca3"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a333b61c1788cb23559177531e6a93ca3">vmaCalculateStats</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, <a class="el" href="struct_vma_stats.html">VmaStats</a> *pStats)</td></tr>
+<tr class="memdesc:a333b61c1788cb23559177531e6a93ca3"><td class="mdescLeft">&#160;</td><td class="mdescRight">Retrieves statistics from current state of the Allocator.  <a href="vk__mem__alloc_8h.html#a333b61c1788cb23559177531e6a93ca3">More...</a><br /></td></tr>
+<tr class="separator:a333b61c1788cb23559177531e6a93ca3"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:aec0ed24ebea2d0099eed5f801daaefba"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#aec0ed24ebea2d0099eed5f801daaefba">vmaGetBudget</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, <a class="el" href="struct_vma_budget.html">VmaBudget</a> *pBudget)</td></tr>
+<tr class="memdesc:aec0ed24ebea2d0099eed5f801daaefba"><td class="mdescLeft">&#160;</td><td class="mdescRight">Retrieves information about current memory budget for all memory heaps.  <a href="vk__mem__alloc_8h.html#aec0ed24ebea2d0099eed5f801daaefba">More...</a><br /></td></tr>
+<tr class="separator:aec0ed24ebea2d0099eed5f801daaefba"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:aa4fee7eb5253377599ef4fd38c93c2a0"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#aa4fee7eb5253377599ef4fd38c93c2a0">vmaBuildStatsString</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, char **ppStatsString, VkBool32 detailedMap)</td></tr>
+<tr class="memdesc:aa4fee7eb5253377599ef4fd38c93c2a0"><td class="mdescLeft">&#160;</td><td class="mdescRight">Builds and returns statistics as string in JSON format.  <a href="vk__mem__alloc_8h.html#aa4fee7eb5253377599ef4fd38c93c2a0">More...</a><br /></td></tr>
+<tr class="separator:aa4fee7eb5253377599ef4fd38c93c2a0"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a3104eb30d8122c84dd8541063f145288"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a3104eb30d8122c84dd8541063f145288">vmaFreeStatsString</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, char *pStatsString)</td></tr>
+<tr class="separator:a3104eb30d8122c84dd8541063f145288"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:aef15a94b58fbcb0fe706d5720e84a74a"><td class="memItemLeft" align="right" valign="top">VkResult&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#aef15a94b58fbcb0fe706d5720e84a74a">vmaFindMemoryTypeIndex</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, uint32_t memoryTypeBits, const <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> *pAllocationCreateInfo, uint32_t *pMemoryTypeIndex)</td></tr>
+<tr class="memdesc:aef15a94b58fbcb0fe706d5720e84a74a"><td class="mdescLeft">&#160;</td><td class="mdescRight">Helps to find memoryTypeIndex, given memoryTypeBits and <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>.  <a href="vk__mem__alloc_8h.html#aef15a94b58fbcb0fe706d5720e84a74a">More...</a><br /></td></tr>
+<tr class="separator:aef15a94b58fbcb0fe706d5720e84a74a"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ae790ab9ffaf7667fb8f62523e6897888"><td class="memItemLeft" align="right" valign="top">VkResult&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#ae790ab9ffaf7667fb8f62523e6897888">vmaFindMemoryTypeIndexForBufferInfo</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, const VkBufferCreateInfo *pBufferCreateInfo, const <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> *pAllocationCreateInfo, uint32_t *pMemoryTypeIndex)</td></tr>
+<tr class="memdesc:ae790ab9ffaf7667fb8f62523e6897888"><td class="mdescLeft">&#160;</td><td class="mdescRight">Helps to find memoryTypeIndex, given VkBufferCreateInfo and <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>.  <a href="vk__mem__alloc_8h.html#ae790ab9ffaf7667fb8f62523e6897888">More...</a><br /></td></tr>
+<tr class="separator:ae790ab9ffaf7667fb8f62523e6897888"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a088da83d8eaf3ce9056d9ea0b981d472"><td class="memItemLeft" align="right" valign="top">VkResult&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a088da83d8eaf3ce9056d9ea0b981d472">vmaFindMemoryTypeIndexForImageInfo</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, const VkImageCreateInfo *pImageCreateInfo, const <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> *pAllocationCreateInfo, uint32_t *pMemoryTypeIndex)</td></tr>
+<tr class="memdesc:a088da83d8eaf3ce9056d9ea0b981d472"><td class="mdescLeft">&#160;</td><td class="mdescRight">Helps to find memoryTypeIndex, given VkImageCreateInfo and <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>.  <a href="vk__mem__alloc_8h.html#a088da83d8eaf3ce9056d9ea0b981d472">More...</a><br /></td></tr>
+<tr class="separator:a088da83d8eaf3ce9056d9ea0b981d472"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a5c8770ded7c59c8caac6de0c2cb00b50"><td class="memItemLeft" align="right" valign="top">VkResult&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a5c8770ded7c59c8caac6de0c2cb00b50">vmaCreatePool</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, const <a class="el" href="struct_vma_pool_create_info.html">VmaPoolCreateInfo</a> *pCreateInfo, <a class="el" href="struct_vma_pool.html">VmaPool</a> *pPool)</td></tr>
+<tr class="memdesc:a5c8770ded7c59c8caac6de0c2cb00b50"><td class="mdescLeft">&#160;</td><td class="mdescRight">Allocates Vulkan device memory and creates <a class="el" href="struct_vma_pool.html" title="Represents custom memory pool.">VmaPool</a> object.  <a href="vk__mem__alloc_8h.html#a5c8770ded7c59c8caac6de0c2cb00b50">More...</a><br /></td></tr>
+<tr class="separator:a5c8770ded7c59c8caac6de0c2cb00b50"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a5485779c8f1948238fc4e92232fa65e1"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a5485779c8f1948238fc4e92232fa65e1">vmaDestroyPool</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, <a class="el" href="struct_vma_pool.html">VmaPool</a> pool)</td></tr>
+<tr class="memdesc:a5485779c8f1948238fc4e92232fa65e1"><td class="mdescLeft">&#160;</td><td class="mdescRight">Destroys <a class="el" href="struct_vma_pool.html" title="Represents custom memory pool.">VmaPool</a> object and frees Vulkan device memory.  <a href="vk__mem__alloc_8h.html#a5485779c8f1948238fc4e92232fa65e1">More...</a><br /></td></tr>
+<tr class="separator:a5485779c8f1948238fc4e92232fa65e1"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ae8bf76997b234ef68aad922616df4153"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#ae8bf76997b234ef68aad922616df4153">vmaGetPoolStats</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, <a class="el" href="struct_vma_pool.html">VmaPool</a> pool, <a class="el" href="struct_vma_pool_stats.html">VmaPoolStats</a> *pPoolStats)</td></tr>
+<tr class="memdesc:ae8bf76997b234ef68aad922616df4153"><td class="mdescLeft">&#160;</td><td class="mdescRight">Retrieves statistics of existing <a class="el" href="struct_vma_pool.html" title="Represents custom memory pool.">VmaPool</a> object.  <a href="vk__mem__alloc_8h.html#ae8bf76997b234ef68aad922616df4153">More...</a><br /></td></tr>
+<tr class="separator:ae8bf76997b234ef68aad922616df4153"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a736bd6cbda886f36c891727e73bd4024"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a736bd6cbda886f36c891727e73bd4024">vmaMakePoolAllocationsLost</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, <a class="el" href="struct_vma_pool.html">VmaPool</a> pool, size_t *pLostAllocationCount)</td></tr>
+<tr class="memdesc:a736bd6cbda886f36c891727e73bd4024"><td class="mdescLeft">&#160;</td><td class="mdescRight">Marks all allocations in given pool as lost if they are not used in current frame or <a class="el" href="struct_vma_pool_create_info.html#a9437e43ffbb644dbbf7fc4e50cfad6aa" title="Maximum number of additional frames that are in use at the same time as current frame.">VmaPoolCreateInfo::frameInUseCount</a> back from now.  <a href="vk__mem__alloc_8h.html#a736bd6cbda886f36c891727e73bd4024">More...</a><br /></td></tr>
+<tr class="separator:a736bd6cbda886f36c891727e73bd4024"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ad535935619c7a549bf837e1bb0068f89"><td class="memItemLeft" align="right" valign="top">VkResult&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#ad535935619c7a549bf837e1bb0068f89">vmaCheckPoolCorruption</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, <a class="el" href="struct_vma_pool.html">VmaPool</a> pool)</td></tr>
+<tr class="memdesc:ad535935619c7a549bf837e1bb0068f89"><td class="mdescLeft">&#160;</td><td class="mdescRight">Checks magic number in margins around all allocations in given memory pool in search for corruptions.  <a href="vk__mem__alloc_8h.html#ad535935619c7a549bf837e1bb0068f89">More...</a><br /></td></tr>
+<tr class="separator:ad535935619c7a549bf837e1bb0068f89"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:af09b4e4eafdbee812e8d73ddf960f030"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#af09b4e4eafdbee812e8d73ddf960f030">vmaGetPoolName</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, <a class="el" href="struct_vma_pool.html">VmaPool</a> pool, const char **ppName)</td></tr>
+<tr class="memdesc:af09b4e4eafdbee812e8d73ddf960f030"><td class="mdescLeft">&#160;</td><td class="mdescRight">Retrieves name of a custom pool.  <a href="vk__mem__alloc_8h.html#af09b4e4eafdbee812e8d73ddf960f030">More...</a><br /></td></tr>
+<tr class="separator:af09b4e4eafdbee812e8d73ddf960f030"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:adbae3a0b4ab078024462fc85c37f3b58"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#adbae3a0b4ab078024462fc85c37f3b58">vmaSetPoolName</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, <a class="el" href="struct_vma_pool.html">VmaPool</a> pool, const char *pName)</td></tr>
+<tr class="memdesc:adbae3a0b4ab078024462fc85c37f3b58"><td class="mdescLeft">&#160;</td><td class="mdescRight">Sets name of a custom pool.  <a href="vk__mem__alloc_8h.html#adbae3a0b4ab078024462fc85c37f3b58">More...</a><br /></td></tr>
+<tr class="separator:adbae3a0b4ab078024462fc85c37f3b58"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:abf28077dbf82d0908b8acbe8ee8dd9b8"><td class="memItemLeft" align="right" valign="top">VkResult&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#abf28077dbf82d0908b8acbe8ee8dd9b8">vmaAllocateMemory</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, const VkMemoryRequirements *pVkMemoryRequirements, const <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> *pCreateInfo, <a class="el" href="struct_vma_allocation.html">VmaAllocation</a> *pAllocation, <a class="el" href="struct_vma_allocation_info.html">VmaAllocationInfo</a> *pAllocationInfo)</td></tr>
+<tr class="memdesc:abf28077dbf82d0908b8acbe8ee8dd9b8"><td class="mdescLeft">&#160;</td><td class="mdescRight">General purpose memory allocation.  <a href="vk__mem__alloc_8h.html#abf28077dbf82d0908b8acbe8ee8dd9b8">More...</a><br /></td></tr>
+<tr class="separator:abf28077dbf82d0908b8acbe8ee8dd9b8"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ad37e82e492b3de38fc3f4cffd9ad0ae1"><td class="memItemLeft" align="right" valign="top">VkResult&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#ad37e82e492b3de38fc3f4cffd9ad0ae1">vmaAllocateMemoryPages</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, const VkMemoryRequirements *pVkMemoryRequirements, const <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> *pCreateInfo, size_t allocationCount, <a class="el" href="struct_vma_allocation.html">VmaAllocation</a> *pAllocations, <a class="el" href="struct_vma_allocation_info.html">VmaAllocationInfo</a> *pAllocationInfo)</td></tr>
+<tr class="memdesc:ad37e82e492b3de38fc3f4cffd9ad0ae1"><td class="mdescLeft">&#160;</td><td class="mdescRight">General purpose memory allocation for multiple allocation objects at once.  <a href="vk__mem__alloc_8h.html#ad37e82e492b3de38fc3f4cffd9ad0ae1">More...</a><br /></td></tr>
+<tr class="separator:ad37e82e492b3de38fc3f4cffd9ad0ae1"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a7fdf64415b6c3d83c454f28d2c53df7b"><td class="memItemLeft" align="right" valign="top">VkResult&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a7fdf64415b6c3d83c454f28d2c53df7b">vmaAllocateMemoryForBuffer</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, VkBuffer buffer, const <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> *pCreateInfo, <a class="el" href="struct_vma_allocation.html">VmaAllocation</a> *pAllocation, <a class="el" href="struct_vma_allocation_info.html">VmaAllocationInfo</a> *pAllocationInfo)</td></tr>
+<tr class="separator:a7fdf64415b6c3d83c454f28d2c53df7b"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a0faa3f9e5fb233d29d1e00390650febb"><td class="memItemLeft" align="right" valign="top">VkResult&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a0faa3f9e5fb233d29d1e00390650febb">vmaAllocateMemoryForImage</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, VkImage image, const <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> *pCreateInfo, <a class="el" href="struct_vma_allocation.html">VmaAllocation</a> *pAllocation, <a class="el" href="struct_vma_allocation_info.html">VmaAllocationInfo</a> *pAllocationInfo)</td></tr>
+<tr class="memdesc:a0faa3f9e5fb233d29d1e00390650febb"><td class="mdescLeft">&#160;</td><td class="mdescRight">Function similar to <a class="el" href="vk__mem__alloc_8h.html#a7fdf64415b6c3d83c454f28d2c53df7b">vmaAllocateMemoryForBuffer()</a>.  <a href="vk__mem__alloc_8h.html#a0faa3f9e5fb233d29d1e00390650febb">More...</a><br /></td></tr>
+<tr class="separator:a0faa3f9e5fb233d29d1e00390650febb"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a11f0fbc034fa81a4efedd73d61ce7568"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a11f0fbc034fa81a4efedd73d61ce7568">vmaFreeMemory</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, <a class="el" href="struct_vma_allocation.html">VmaAllocation</a> allocation)</td></tr>
+<tr class="memdesc:a11f0fbc034fa81a4efedd73d61ce7568"><td class="mdescLeft">&#160;</td><td class="mdescRight">Frees memory previously allocated using <a class="el" href="vk__mem__alloc_8h.html#abf28077dbf82d0908b8acbe8ee8dd9b8" title="General purpose memory allocation.">vmaAllocateMemory()</a>, <a class="el" href="vk__mem__alloc_8h.html#a7fdf64415b6c3d83c454f28d2c53df7b">vmaAllocateMemoryForBuffer()</a>, or <a class="el" href="vk__mem__alloc_8h.html#a0faa3f9e5fb233d29d1e00390650febb" title="Function similar to vmaAllocateMemoryForBuffer().">vmaAllocateMemoryForImage()</a>.  <a href="vk__mem__alloc_8h.html#a11f0fbc034fa81a4efedd73d61ce7568">More...</a><br /></td></tr>
+<tr class="separator:a11f0fbc034fa81a4efedd73d61ce7568"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ab9e709de044c5d8476bea77a4e755840"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#ab9e709de044c5d8476bea77a4e755840">vmaFreeMemoryPages</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, size_t allocationCount, <a class="el" href="struct_vma_allocation.html">VmaAllocation</a> *pAllocations)</td></tr>
+<tr class="memdesc:ab9e709de044c5d8476bea77a4e755840"><td class="mdescLeft">&#160;</td><td class="mdescRight">Frees memory and destroys multiple allocations.  <a href="vk__mem__alloc_8h.html#ab9e709de044c5d8476bea77a4e755840">More...</a><br /></td></tr>
+<tr class="separator:ab9e709de044c5d8476bea77a4e755840"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a0ff488958ca72b28e545880463cb8696"><td class="memItemLeft" align="right" valign="top">VkResult&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a0ff488958ca72b28e545880463cb8696">vmaResizeAllocation</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, <a class="el" href="struct_vma_allocation.html">VmaAllocation</a> allocation, VkDeviceSize newSize)</td></tr>
+<tr class="memdesc:a0ff488958ca72b28e545880463cb8696"><td class="mdescLeft">&#160;</td><td class="mdescRight">Deprecated.  <a href="vk__mem__alloc_8h.html#a0ff488958ca72b28e545880463cb8696">More...</a><br /></td></tr>
+<tr class="separator:a0ff488958ca72b28e545880463cb8696"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a86dd08aba8633bfa4ad0df2e76481d8b"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b">vmaGetAllocationInfo</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, <a class="el" href="struct_vma_allocation.html">VmaAllocation</a> allocation, <a class="el" href="struct_vma_allocation_info.html">VmaAllocationInfo</a> *pAllocationInfo)</td></tr>
+<tr class="memdesc:a86dd08aba8633bfa4ad0df2e76481d8b"><td class="mdescLeft">&#160;</td><td class="mdescRight">Returns current information about specified allocation and atomically marks it as used in current frame.  <a href="vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b">More...</a><br /></td></tr>
+<tr class="separator:a86dd08aba8633bfa4ad0df2e76481d8b"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a43d8ba9673c846f049089a5029d5c73a"><td class="memItemLeft" align="right" valign="top">VkBool32&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a43d8ba9673c846f049089a5029d5c73a">vmaTouchAllocation</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, <a class="el" href="struct_vma_allocation.html">VmaAllocation</a> allocation)</td></tr>
+<tr class="memdesc:a43d8ba9673c846f049089a5029d5c73a"><td class="mdescLeft">&#160;</td><td class="mdescRight">Returns <code>VK_TRUE</code> if allocation is not lost and atomically marks it as used in current frame.  <a href="vk__mem__alloc_8h.html#a43d8ba9673c846f049089a5029d5c73a">More...</a><br /></td></tr>
+<tr class="separator:a43d8ba9673c846f049089a5029d5c73a"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:af9147d31ffc11d62fc187bde283ed14f"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#af9147d31ffc11d62fc187bde283ed14f">vmaSetAllocationUserData</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, <a class="el" href="struct_vma_allocation.html">VmaAllocation</a> allocation, void *pUserData)</td></tr>
+<tr class="memdesc:af9147d31ffc11d62fc187bde283ed14f"><td class="mdescLeft">&#160;</td><td class="mdescRight">Sets pUserData in given allocation to new value.  <a href="vk__mem__alloc_8h.html#af9147d31ffc11d62fc187bde283ed14f">More...</a><br /></td></tr>
+<tr class="separator:af9147d31ffc11d62fc187bde283ed14f"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ae5c9657d9e94756269145b01c05d16f1"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#ae5c9657d9e94756269145b01c05d16f1">vmaCreateLostAllocation</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, <a class="el" href="struct_vma_allocation.html">VmaAllocation</a> *pAllocation)</td></tr>
+<tr class="memdesc:ae5c9657d9e94756269145b01c05d16f1"><td class="mdescLeft">&#160;</td><td class="mdescRight">Creates new allocation that is in lost state from the beginning.  <a href="vk__mem__alloc_8h.html#ae5c9657d9e94756269145b01c05d16f1">More...</a><br /></td></tr>
+<tr class="separator:ae5c9657d9e94756269145b01c05d16f1"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ad5bd1243512d099706de88168992f069"><td class="memItemLeft" align="right" valign="top">VkResult&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#ad5bd1243512d099706de88168992f069">vmaMapMemory</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, <a class="el" href="struct_vma_allocation.html">VmaAllocation</a> allocation, void **ppData)</td></tr>
+<tr class="memdesc:ad5bd1243512d099706de88168992f069"><td class="mdescLeft">&#160;</td><td class="mdescRight">Maps memory represented by given allocation and returns pointer to it.  <a href="vk__mem__alloc_8h.html#ad5bd1243512d099706de88168992f069">More...</a><br /></td></tr>
+<tr class="separator:ad5bd1243512d099706de88168992f069"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a9bc268595cb33f6ec4d519cfce81ff45"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a9bc268595cb33f6ec4d519cfce81ff45">vmaUnmapMemory</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, <a class="el" href="struct_vma_allocation.html">VmaAllocation</a> allocation)</td></tr>
+<tr class="memdesc:a9bc268595cb33f6ec4d519cfce81ff45"><td class="mdescLeft">&#160;</td><td class="mdescRight">Unmaps memory represented by given allocation, mapped previously using <a class="el" href="vk__mem__alloc_8h.html#ad5bd1243512d099706de88168992f069" title="Maps memory represented by given allocation and returns pointer to it.">vmaMapMemory()</a>.  <a href="vk__mem__alloc_8h.html#a9bc268595cb33f6ec4d519cfce81ff45">More...</a><br /></td></tr>
+<tr class="separator:a9bc268595cb33f6ec4d519cfce81ff45"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:abc34ee6f021f459aff885f3758c435de"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#abc34ee6f021f459aff885f3758c435de">vmaFlushAllocation</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, <a class="el" href="struct_vma_allocation.html">VmaAllocation</a> allocation, VkDeviceSize offset, VkDeviceSize size)</td></tr>
+<tr class="memdesc:abc34ee6f021f459aff885f3758c435de"><td class="mdescLeft">&#160;</td><td class="mdescRight">Flushes memory of given allocation.  <a href="vk__mem__alloc_8h.html#abc34ee6f021f459aff885f3758c435de">More...</a><br /></td></tr>
+<tr class="separator:abc34ee6f021f459aff885f3758c435de"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a0d0eb0c1102268fa9a476d12ecbe4006"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a0d0eb0c1102268fa9a476d12ecbe4006">vmaInvalidateAllocation</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, <a class="el" href="struct_vma_allocation.html">VmaAllocation</a> allocation, VkDeviceSize offset, VkDeviceSize size)</td></tr>
+<tr class="memdesc:a0d0eb0c1102268fa9a476d12ecbe4006"><td class="mdescLeft">&#160;</td><td class="mdescRight">Invalidates memory of given allocation.  <a href="vk__mem__alloc_8h.html#a0d0eb0c1102268fa9a476d12ecbe4006">More...</a><br /></td></tr>
+<tr class="separator:a0d0eb0c1102268fa9a476d12ecbe4006"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a49329a7f030dafcf82f7b73334c22e98"><td class="memItemLeft" align="right" valign="top">VkResult&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a49329a7f030dafcf82f7b73334c22e98">vmaCheckCorruption</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, uint32_t memoryTypeBits)</td></tr>
+<tr class="memdesc:a49329a7f030dafcf82f7b73334c22e98"><td class="mdescLeft">&#160;</td><td class="mdescRight">Checks magic number in margins around all allocations in given memory types (in both default and custom pools) in search for corruptions.  <a href="vk__mem__alloc_8h.html#a49329a7f030dafcf82f7b73334c22e98">More...</a><br /></td></tr>
+<tr class="separator:a49329a7f030dafcf82f7b73334c22e98"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a36ba776fd7fd5cb1e9359fdc0d8e6e8a"><td class="memItemLeft" align="right" valign="top">VkResult&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a36ba776fd7fd5cb1e9359fdc0d8e6e8a">vmaDefragmentationBegin</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, const <a class="el" href="struct_vma_defragmentation_info2.html">VmaDefragmentationInfo2</a> *pInfo, <a class="el" href="struct_vma_defragmentation_stats.html">VmaDefragmentationStats</a> *pStats, <a class="el" href="struct_vma_defragmentation_context.html">VmaDefragmentationContext</a> *pContext)</td></tr>
+<tr class="memdesc:a36ba776fd7fd5cb1e9359fdc0d8e6e8a"><td class="mdescLeft">&#160;</td><td class="mdescRight">Begins defragmentation process.  <a href="vk__mem__alloc_8h.html#a36ba776fd7fd5cb1e9359fdc0d8e6e8a">More...</a><br /></td></tr>
+<tr class="separator:a36ba776fd7fd5cb1e9359fdc0d8e6e8a"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a8774e20e91e245aae959ba63efa15dd2"><td class="memItemLeft" align="right" valign="top">VkResult&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a8774e20e91e245aae959ba63efa15dd2">vmaDefragmentationEnd</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, <a class="el" href="struct_vma_defragmentation_context.html">VmaDefragmentationContext</a> context)</td></tr>
+<tr class="memdesc:a8774e20e91e245aae959ba63efa15dd2"><td class="mdescLeft">&#160;</td><td class="mdescRight">Ends defragmentation process.  <a href="vk__mem__alloc_8h.html#a8774e20e91e245aae959ba63efa15dd2">More...</a><br /></td></tr>
+<tr class="separator:a8774e20e91e245aae959ba63efa15dd2"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ac0f01545b6262f7d4d128fc8f8e5c77b"><td class="memItemLeft" align="right" valign="top">VkResult&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#ac0f01545b6262f7d4d128fc8f8e5c77b">vmaBeginDefragmentationPass</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, <a class="el" href="struct_vma_defragmentation_context.html">VmaDefragmentationContext</a> context, <a class="el" href="struct_vma_defragmentation_pass_info.html">VmaDefragmentationPassInfo</a> *pInfo)</td></tr>
+<tr class="separator:ac0f01545b6262f7d4d128fc8f8e5c77b"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a1b9ffa538bed905af55c747cc48963bd"><td class="memItemLeft" align="right" valign="top">VkResult&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a1b9ffa538bed905af55c747cc48963bd">vmaEndDefragmentationPass</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, <a class="el" href="struct_vma_defragmentation_context.html">VmaDefragmentationContext</a> context)</td></tr>
+<tr class="separator:a1b9ffa538bed905af55c747cc48963bd"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a6aced90fcc7b39882b6654a740a0b9bb"><td class="memItemLeft" align="right" valign="top">VkResult&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a6aced90fcc7b39882b6654a740a0b9bb">vmaDefragment</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, <a class="el" href="struct_vma_allocation.html">VmaAllocation</a> *pAllocations, size_t allocationCount, VkBool32 *pAllocationsChanged, const <a class="el" href="struct_vma_defragmentation_info.html">VmaDefragmentationInfo</a> *pDefragmentationInfo, <a class="el" href="struct_vma_defragmentation_stats.html">VmaDefragmentationStats</a> *pDefragmentationStats)</td></tr>
+<tr class="memdesc:a6aced90fcc7b39882b6654a740a0b9bb"><td class="mdescLeft">&#160;</td><td class="mdescRight">Deprecated. Compacts memory by moving allocations.  <a href="vk__mem__alloc_8h.html#a6aced90fcc7b39882b6654a740a0b9bb">More...</a><br /></td></tr>
+<tr class="separator:a6aced90fcc7b39882b6654a740a0b9bb"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a6b0929b914b60cf2d45cac4bf3547470"><td class="memItemLeft" align="right" valign="top">VkResult&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a6b0929b914b60cf2d45cac4bf3547470">vmaBindBufferMemory</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, <a class="el" href="struct_vma_allocation.html">VmaAllocation</a> allocation, VkBuffer buffer)</td></tr>
+<tr class="memdesc:a6b0929b914b60cf2d45cac4bf3547470"><td class="mdescLeft">&#160;</td><td class="mdescRight">Binds buffer to allocation.  <a href="vk__mem__alloc_8h.html#a6b0929b914b60cf2d45cac4bf3547470">More...</a><br /></td></tr>
+<tr class="separator:a6b0929b914b60cf2d45cac4bf3547470"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a927c944f45e0f2941182abb6f608e64a"><td class="memItemLeft" align="right" valign="top">VkResult&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a927c944f45e0f2941182abb6f608e64a">vmaBindBufferMemory2</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, <a class="el" href="struct_vma_allocation.html">VmaAllocation</a> allocation, VkDeviceSize allocationLocalOffset, VkBuffer buffer, const void *pNext)</td></tr>
+<tr class="memdesc:a927c944f45e0f2941182abb6f608e64a"><td class="mdescLeft">&#160;</td><td class="mdescRight">Binds buffer to allocation with additional parameters.  <a href="vk__mem__alloc_8h.html#a927c944f45e0f2941182abb6f608e64a">More...</a><br /></td></tr>
+<tr class="separator:a927c944f45e0f2941182abb6f608e64a"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a3d3ca45799923aa5d138e9e5f9eb2da5"><td class="memItemLeft" align="right" valign="top">VkResult&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a3d3ca45799923aa5d138e9e5f9eb2da5">vmaBindImageMemory</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, <a class="el" href="struct_vma_allocation.html">VmaAllocation</a> allocation, VkImage image)</td></tr>
+<tr class="memdesc:a3d3ca45799923aa5d138e9e5f9eb2da5"><td class="mdescLeft">&#160;</td><td class="mdescRight">Binds image to allocation.  <a href="vk__mem__alloc_8h.html#a3d3ca45799923aa5d138e9e5f9eb2da5">More...</a><br /></td></tr>
+<tr class="separator:a3d3ca45799923aa5d138e9e5f9eb2da5"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:aa8251ee81b0045a443e35b8e8aa021bc"><td class="memItemLeft" align="right" valign="top">VkResult&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#aa8251ee81b0045a443e35b8e8aa021bc">vmaBindImageMemory2</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, <a class="el" href="struct_vma_allocation.html">VmaAllocation</a> allocation, VkDeviceSize allocationLocalOffset, VkImage image, const void *pNext)</td></tr>
+<tr class="memdesc:aa8251ee81b0045a443e35b8e8aa021bc"><td class="mdescLeft">&#160;</td><td class="mdescRight">Binds image to allocation with additional parameters.  <a href="vk__mem__alloc_8h.html#aa8251ee81b0045a443e35b8e8aa021bc">More...</a><br /></td></tr>
+<tr class="separator:aa8251ee81b0045a443e35b8e8aa021bc"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ac72ee55598617e8eecca384e746bab51"><td class="memItemLeft" align="right" valign="top">VkResult&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, const VkBufferCreateInfo *pBufferCreateInfo, const <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> *pAllocationCreateInfo, VkBuffer *pBuffer, <a class="el" href="struct_vma_allocation.html">VmaAllocation</a> *pAllocation, <a class="el" href="struct_vma_allocation_info.html">VmaAllocationInfo</a> *pAllocationInfo)</td></tr>
+<tr class="separator:ac72ee55598617e8eecca384e746bab51"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a0d9f4e4ba5bf9aab1f1c746387753d77"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a0d9f4e4ba5bf9aab1f1c746387753d77">vmaDestroyBuffer</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, VkBuffer buffer, <a class="el" href="struct_vma_allocation.html">VmaAllocation</a> allocation)</td></tr>
+<tr class="memdesc:a0d9f4e4ba5bf9aab1f1c746387753d77"><td class="mdescLeft">&#160;</td><td class="mdescRight">Destroys Vulkan buffer and frees allocated memory.  <a href="vk__mem__alloc_8h.html#a0d9f4e4ba5bf9aab1f1c746387753d77">More...</a><br /></td></tr>
+<tr class="separator:a0d9f4e4ba5bf9aab1f1c746387753d77"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:a02a94f25679275851a53e82eacbcfc73"><td class="memItemLeft" align="right" valign="top">VkResult&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#a02a94f25679275851a53e82eacbcfc73">vmaCreateImage</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, const VkImageCreateInfo *pImageCreateInfo, const <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> *pAllocationCreateInfo, VkImage *pImage, <a class="el" href="struct_vma_allocation.html">VmaAllocation</a> *pAllocation, <a class="el" href="struct_vma_allocation_info.html">VmaAllocationInfo</a> *pAllocationInfo)</td></tr>
+<tr class="memdesc:a02a94f25679275851a53e82eacbcfc73"><td class="mdescLeft">&#160;</td><td class="mdescRight">Function similar to <a class="el" href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer()</a>.  <a href="vk__mem__alloc_8h.html#a02a94f25679275851a53e82eacbcfc73">More...</a><br /></td></tr>
+<tr class="separator:a02a94f25679275851a53e82eacbcfc73"><td class="memSeparator" colspan="2">&#160;</td></tr>
+<tr class="memitem:ae50d2cb3b4a3bfd4dd40987234e50e7e"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="vk__mem__alloc_8h.html#ae50d2cb3b4a3bfd4dd40987234e50e7e">vmaDestroyImage</a> (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, VkImage image, <a class="el" href="struct_vma_allocation.html">VmaAllocation</a> allocation)</td></tr>
+<tr class="memdesc:ae50d2cb3b4a3bfd4dd40987234e50e7e"><td class="mdescLeft">&#160;</td><td class="mdescRight">Destroys Vulkan image and frees allocated memory.  <a href="vk__mem__alloc_8h.html#ae50d2cb3b4a3bfd4dd40987234e50e7e">More...</a><br /></td></tr>
+<tr class="separator:ae50d2cb3b4a3bfd4dd40987234e50e7e"><td class="memSeparator" colspan="2">&#160;</td></tr>
+</table>
+<h2 class="groupheader">Macro Definition Documentation</h2>
+<a id="a9f918755b601cf4bffca775992e6fb90"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a9f918755b601cf4bffca775992e6fb90">&#9670;&nbsp;</a></span>NOMINMAX</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">#define NOMINMAX</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="a88bef97f86d70a34a4c0746e09a2680d"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a88bef97f86d70a34a4c0746e09a2680d">&#9670;&nbsp;</a></span>VMA_BIND_MEMORY2</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">#define VMA_BIND_MEMORY2&#160;&#160;&#160;0</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="a7f9d5e71b70dd1a137c303a8a8262c10"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a7f9d5e71b70dd1a137c303a8a8262c10">&#9670;&nbsp;</a></span>VMA_BUFFER_DEVICE_ADDRESS</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">#define VMA_BUFFER_DEVICE_ADDRESS&#160;&#160;&#160;0</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="af7b860e63b96d11e44ae8587ba06bbf4"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#af7b860e63b96d11e44ae8587ba06bbf4">&#9670;&nbsp;</a></span>VMA_DEDICATED_ALLOCATION</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">#define VMA_DEDICATED_ALLOCATION&#160;&#160;&#160;0</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="a05decf1cf4ebf767beba7acca6c1ec3a"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a05decf1cf4ebf767beba7acca6c1ec3a">&#9670;&nbsp;</a></span>VMA_MEMORY_BUDGET</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">#define VMA_MEMORY_BUDGET&#160;&#160;&#160;0</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="a1f0c126759fc96ccb6e2d23c101d770c"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a1f0c126759fc96ccb6e2d23c101d770c">&#9670;&nbsp;</a></span>VMA_RECORDING_ENABLED</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">#define VMA_RECORDING_ENABLED&#160;&#160;&#160;0</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="ae25f0d55fd91cb166f002b63244800e1"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ae25f0d55fd91cb166f002b63244800e1">&#9670;&nbsp;</a></span>VMA_STATS_STRING_ENABLED</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">#define VMA_STATS_STRING_ENABLED&#160;&#160;&#160;1</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="a1a2407c283893638cc039bb31fcd74b6"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a1a2407c283893638cc039bb31fcd74b6">&#9670;&nbsp;</a></span>VMA_VULKAN_VERSION</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">#define VMA_VULKAN_VERSION&#160;&#160;&#160;1000000</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<h2 class="groupheader">Typedef Documentation</h2>
+<a id="a7e1ed85f7799600b03ad51a77acc21f3"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a7e1ed85f7799600b03ad51a77acc21f3">&#9670;&nbsp;</a></span>PFN_vmaAllocateDeviceMemoryFunction</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">typedef void(VKAPI_PTR * PFN_vmaAllocateDeviceMemoryFunction) (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, uint32_t memoryType, VkDeviceMemory memory, VkDeviceSize size, void *pUserData)</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Callback function called after successful vkAllocateMemory. </p>
+
+</div>
+</div>
+<a id="a154ccaaf53dc2c36378f80f0c4f3679b"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a154ccaaf53dc2c36378f80f0c4f3679b">&#9670;&nbsp;</a></span>PFN_vmaFreeDeviceMemoryFunction</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">typedef void(VKAPI_PTR * PFN_vmaFreeDeviceMemoryFunction) (<a class="el" href="struct_vma_allocator.html">VmaAllocator</a> allocator, uint32_t memoryType, VkDeviceMemory memory, VkDeviceSize size, void *pUserData)</td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Callback function called before vkFreeMemory. </p>
+
+</div>
+</div>
+<a id="a4fceecc301f4064dc808d3cd6c038941"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a4fceecc301f4064dc808d3cd6c038941">&#9670;&nbsp;</a></span>VmaAllocationCreateFlagBits</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">typedef enum <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597">VmaAllocationCreateFlagBits</a> <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597">VmaAllocationCreateFlagBits</a></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Flags to be passed as <a class="el" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b" title="Use VmaAllocationCreateFlagBits enum.">VmaAllocationCreateInfo::flags</a>. </p>
+
+</div>
+</div>
+<a id="a5225e5e11f8376f6a31a1791f3d6e817"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a5225e5e11f8376f6a31a1791f3d6e817">&#9670;&nbsp;</a></span>VmaAllocationCreateFlags</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">typedef VkFlags <a class="el" href="vk__mem__alloc_8h.html#a5225e5e11f8376f6a31a1791f3d6e817">VmaAllocationCreateFlags</a></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="a3bf110892ea2fb4649fedb68488d026a"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a3bf110892ea2fb4649fedb68488d026a">&#9670;&nbsp;</a></span>VmaAllocationCreateInfo</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">typedef struct <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="a1cf7774606721026a68aabe3af2e5b50"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a1cf7774606721026a68aabe3af2e5b50">&#9670;&nbsp;</a></span>VmaAllocationInfo</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">typedef struct <a class="el" href="struct_vma_allocation_info.html">VmaAllocationInfo</a> <a class="el" href="struct_vma_allocation_info.html">VmaAllocationInfo</a></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Parameters of <a class="el" href="struct_vma_allocation.html" title="Represents single memory allocation.">VmaAllocation</a> objects, that can be retrieved using function <a class="el" href="vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b" title="Returns current information about specified allocation and atomically marks it as used in current fra...">vmaGetAllocationInfo()</a>. </p>
+
+</div>
+</div>
+<a id="afd73b95e737ee7e76f827cb5472f559f"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#afd73b95e737ee7e76f827cb5472f559f">&#9670;&nbsp;</a></span>VmaAllocatorCreateFlagBits</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">typedef enum <a class="el" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7c">VmaAllocatorCreateFlagBits</a> <a class="el" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7c">VmaAllocatorCreateFlagBits</a></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Flags for created <a class="el" href="struct_vma_allocator.html" title="Represents main object of this library initialized.">VmaAllocator</a>. </p>
+
+</div>
+</div>
+<a id="acfe6863e160722c2c1bbcf7573fddc4d"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#acfe6863e160722c2c1bbcf7573fddc4d">&#9670;&nbsp;</a></span>VmaAllocatorCreateFlags</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">typedef VkFlags <a class="el" href="vk__mem__alloc_8h.html#acfe6863e160722c2c1bbcf7573fddc4d">VmaAllocatorCreateFlags</a></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="aad9652301d33759b83e52d4f3605a14a"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#aad9652301d33759b83e52d4f3605a14a">&#9670;&nbsp;</a></span>VmaAllocatorCreateInfo</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">typedef struct <a class="el" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a> <a class="el" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Description of a Allocator to be created. </p>
+
+</div>
+</div>
+<a id="a1988031b0223fdbd564250fa1edd942c"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a1988031b0223fdbd564250fa1edd942c">&#9670;&nbsp;</a></span>VmaAllocatorInfo</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">typedef struct <a class="el" href="struct_vma_allocator_info.html">VmaAllocatorInfo</a> <a class="el" href="struct_vma_allocator_info.html">VmaAllocatorInfo</a></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Information about existing <a class="el" href="struct_vma_allocator.html" title="Represents main object of this library initialized.">VmaAllocator</a> object. </p>
+
+</div>
+</div>
+<a id="aa078667e71b1ef24e87a6a30d128381d"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#aa078667e71b1ef24e87a6a30d128381d">&#9670;&nbsp;</a></span>VmaBudget</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">typedef struct <a class="el" href="struct_vma_budget.html">VmaBudget</a> <a class="el" href="struct_vma_budget.html">VmaBudget</a></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Statistics of current memory usage and available budget, in bytes, for specific memory heap. </p>
+
+</div>
+</div>
+<a id="a13415cc0b443353a7b5abda300b833fc"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a13415cc0b443353a7b5abda300b833fc">&#9670;&nbsp;</a></span>VmaDefragmentationFlagBits</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">typedef enum <a class="el" href="vk__mem__alloc_8h.html#a6552a65b71d16f378c6994b3ceaef50c">VmaDefragmentationFlagBits</a> <a class="el" href="vk__mem__alloc_8h.html#a6552a65b71d16f378c6994b3ceaef50c">VmaDefragmentationFlagBits</a></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Flags to be used in <a class="el" href="vk__mem__alloc_8h.html#a36ba776fd7fd5cb1e9359fdc0d8e6e8a" title="Begins defragmentation process.">vmaDefragmentationBegin()</a>. None at the moment. Reserved for future use. </p>
+
+</div>
+</div>
+<a id="a88a77cef37e5d3c4fc9eb328885d048d"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a88a77cef37e5d3c4fc9eb328885d048d">&#9670;&nbsp;</a></span>VmaDefragmentationFlags</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">typedef VkFlags <a class="el" href="vk__mem__alloc_8h.html#a88a77cef37e5d3c4fc9eb328885d048d">VmaDefragmentationFlags</a></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="a2bf47f96bf92bed2a49461bd9af3acfa"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a2bf47f96bf92bed2a49461bd9af3acfa">&#9670;&nbsp;</a></span>VmaDefragmentationInfo</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">typedef struct <a class="el" href="struct_vma_defragmentation_info.html">VmaDefragmentationInfo</a> <a class="el" href="struct_vma_defragmentation_info.html">VmaDefragmentationInfo</a></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Deprecated. Optional configuration parameters to be passed to function <a class="el" href="vk__mem__alloc_8h.html#a6aced90fcc7b39882b6654a740a0b9bb" title="Deprecated. Compacts memory by moving allocations.">vmaDefragment()</a>. </p>
+<dl class="deprecated"><dt><b><a class="el" href="deprecated.html#_deprecated000002">Deprecated:</a></b></dt><dd>This is a part of the old interface. It is recommended to use structure <a class="el" href="struct_vma_defragmentation_info2.html" title="Parameters for defragmentation.">VmaDefragmentationInfo2</a> and function <a class="el" href="vk__mem__alloc_8h.html#a36ba776fd7fd5cb1e9359fdc0d8e6e8a" title="Begins defragmentation process.">vmaDefragmentationBegin()</a> instead. </dd></dl>
+
+</div>
+</div>
+<a id="ad6daeffaa670ce6d11a203a6224c9937"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ad6daeffaa670ce6d11a203a6224c9937">&#9670;&nbsp;</a></span>VmaDefragmentationInfo2</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">typedef struct <a class="el" href="struct_vma_defragmentation_info2.html">VmaDefragmentationInfo2</a> <a class="el" href="struct_vma_defragmentation_info2.html">VmaDefragmentationInfo2</a></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Parameters for defragmentation. </p>
+<p>To be used with function <a class="el" href="vk__mem__alloc_8h.html#a36ba776fd7fd5cb1e9359fdc0d8e6e8a" title="Begins defragmentation process.">vmaDefragmentationBegin()</a>. </p>
+
+</div>
+</div>
+<a id="a72aebd522242d56abea67b4f47f6549e"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a72aebd522242d56abea67b4f47f6549e">&#9670;&nbsp;</a></span>VmaDefragmentationPassInfo</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">typedef struct <a class="el" href="struct_vma_defragmentation_pass_info.html">VmaDefragmentationPassInfo</a> <a class="el" href="struct_vma_defragmentation_pass_info.html">VmaDefragmentationPassInfo</a></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Parameters for incremental defragmentation steps. </p>
+<p>To be used with function <a class="el" href="vk__mem__alloc_8h.html#ac0f01545b6262f7d4d128fc8f8e5c77b">vmaBeginDefragmentationPass()</a>. </p>
+
+</div>
+</div>
+<a id="ad6799e8e2b1527abfc84d33bc44aeaf5"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ad6799e8e2b1527abfc84d33bc44aeaf5">&#9670;&nbsp;</a></span>VmaDefragmentationPassMoveInfo</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">typedef struct <a class="el" href="struct_vma_defragmentation_pass_move_info.html">VmaDefragmentationPassMoveInfo</a> <a class="el" href="struct_vma_defragmentation_pass_move_info.html">VmaDefragmentationPassMoveInfo</a></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="ad94034192259c2e34a4d1c5e27810403"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ad94034192259c2e34a4d1c5e27810403">&#9670;&nbsp;</a></span>VmaDefragmentationStats</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">typedef struct <a class="el" href="struct_vma_defragmentation_stats.html">VmaDefragmentationStats</a> <a class="el" href="struct_vma_defragmentation_stats.html">VmaDefragmentationStats</a></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Statistics returned by function <a class="el" href="vk__mem__alloc_8h.html#a6aced90fcc7b39882b6654a740a0b9bb" title="Deprecated. Compacts memory by moving allocations.">vmaDefragment()</a>. </p>
+
+</div>
+</div>
+<a id="a77692d3c8770ea8882d573206bd27b2b"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a77692d3c8770ea8882d573206bd27b2b">&#9670;&nbsp;</a></span>VmaDeviceMemoryCallbacks</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">typedef struct <a class="el" href="struct_vma_device_memory_callbacks.html">VmaDeviceMemoryCallbacks</a> <a class="el" href="struct_vma_device_memory_callbacks.html">VmaDeviceMemoryCallbacks</a></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Set of callbacks that the library will call for <code>vkAllocateMemory</code> and <code>vkFreeMemory</code>. </p>
+<p>Provided for informative purpose, e.g. to gather statistics about number of allocations or total amount of memory allocated in Vulkan.</p>
+<p>Used in <a class="el" href="struct_vma_allocator_create_info.html#af1380969b5e1ea4c3184a877892d260e" title="Informative callbacks for vkAllocateMemory, vkFreeMemory. Optional.">VmaAllocatorCreateInfo::pDeviceMemoryCallbacks</a>. </p>
+
+</div>
+</div>
+<a id="a806e8499dde802e59eb72a1dc811c35f"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a806e8499dde802e59eb72a1dc811c35f">&#9670;&nbsp;</a></span>VmaMemoryUsage</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">typedef enum <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cc">VmaMemoryUsage</a> <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cc">VmaMemoryUsage</a></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="a4d4f2efc2509157a9e4ecd4fd7942303"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a4d4f2efc2509157a9e4ecd4fd7942303">&#9670;&nbsp;</a></span>VmaPoolCreateFlagBits</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">typedef enum <a class="el" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7">VmaPoolCreateFlagBits</a> <a class="el" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7">VmaPoolCreateFlagBits</a></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Flags to be passed as <a class="el" href="struct_vma_pool_create_info.html#a8405139f63d078340ae74513a59f5446" title="Use combination of VmaPoolCreateFlagBits.">VmaPoolCreateInfo::flags</a>. </p>
+
+</div>
+</div>
+<a id="a2770e325ea42e087c1b91fdf46d0292a"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a2770e325ea42e087c1b91fdf46d0292a">&#9670;&nbsp;</a></span>VmaPoolCreateFlags</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">typedef VkFlags <a class="el" href="vk__mem__alloc_8h.html#a2770e325ea42e087c1b91fdf46d0292a">VmaPoolCreateFlags</a></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="a1017aa83489c0eee8d2163d2bf253f67"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a1017aa83489c0eee8d2163d2bf253f67">&#9670;&nbsp;</a></span>VmaPoolCreateInfo</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">typedef struct <a class="el" href="struct_vma_pool_create_info.html">VmaPoolCreateInfo</a> <a class="el" href="struct_vma_pool_create_info.html">VmaPoolCreateInfo</a></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Describes parameter of created <a class="el" href="struct_vma_pool.html" title="Represents custom memory pool.">VmaPool</a>. </p>
+
+</div>
+</div>
+<a id="a4759a2d9f99c19ba7627553c847132f1"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a4759a2d9f99c19ba7627553c847132f1">&#9670;&nbsp;</a></span>VmaPoolStats</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">typedef struct <a class="el" href="struct_vma_pool_stats.html">VmaPoolStats</a> <a class="el" href="struct_vma_pool_stats.html">VmaPoolStats</a></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Describes parameter of existing <a class="el" href="struct_vma_pool.html" title="Represents custom memory pool.">VmaPool</a>. </p>
+
+</div>
+</div>
+<a id="acd24d5eb58abff7e1f43cb32a1ba1413"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#acd24d5eb58abff7e1f43cb32a1ba1413">&#9670;&nbsp;</a></span>VmaRecordFlagBits</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">typedef enum <a class="el" href="vk__mem__alloc_8h.html#a4dd2c44642312a147a4e93373a6e64d2">VmaRecordFlagBits</a> <a class="el" href="vk__mem__alloc_8h.html#a4dd2c44642312a147a4e93373a6e64d2">VmaRecordFlagBits</a></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Flags to be used in <a class="el" href="struct_vma_record_settings.html#ad8fdcc92119ae7a8c08c1a564c01d63a" title="Flags for recording. Use VmaRecordFlagBits enum.">VmaRecordSettings::flags</a>. </p>
+
+</div>
+</div>
+<a id="af3929a1a4547c592fc0b0e55ef452828"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#af3929a1a4547c592fc0b0e55ef452828">&#9670;&nbsp;</a></span>VmaRecordFlags</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">typedef VkFlags <a class="el" href="vk__mem__alloc_8h.html#af3929a1a4547c592fc0b0e55ef452828">VmaRecordFlags</a></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="a16e21c877101493fce582664cd8754fc"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a16e21c877101493fce582664cd8754fc">&#9670;&nbsp;</a></span>VmaRecordSettings</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">typedef struct <a class="el" href="struct_vma_record_settings.html">VmaRecordSettings</a> <a class="el" href="struct_vma_record_settings.html">VmaRecordSettings</a></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Parameters for recording calls to VMA functions. To be used in <a class="el" href="struct_vma_allocator_create_info.html#ace2aa4877b16a42b0b7673d4e26000ee" title="Parameters for recording of VMA calls. Can be null.">VmaAllocatorCreateInfo::pRecordSettings</a>. </p>
+
+</div>
+</div>
+<a id="aec5b57e29c97b5d69c6d5654d60df878"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#aec5b57e29c97b5d69c6d5654d60df878">&#9670;&nbsp;</a></span>VmaStatInfo</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">typedef struct <a class="el" href="struct_vma_stat_info.html">VmaStatInfo</a> <a class="el" href="struct_vma_stat_info.html">VmaStatInfo</a></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Calculated statistics of memory usage in entire allocator. </p>
+
+</div>
+</div>
+<a id="a21813b2efdf3836767a9058cd8a94034"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a21813b2efdf3836767a9058cd8a94034">&#9670;&nbsp;</a></span>VmaStats</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">typedef struct <a class="el" href="struct_vma_stats.html">VmaStats</a> <a class="el" href="struct_vma_stats.html">VmaStats</a></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>General statistics from current state of Allocator. </p>
+
+</div>
+</div>
+<a id="abb0a8e3b5040d847571cca6c7f9a8074"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#abb0a8e3b5040d847571cca6c7f9a8074">&#9670;&nbsp;</a></span>VmaVulkanFunctions</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">typedef struct <a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a> <a class="el" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Pointers to some Vulkan functions - a subset used by the library. </p>
+<p>Used in <a class="el" href="struct_vma_allocator_create_info.html#a3dc197be3227da7338b1643f70db36bd" title="Pointers to Vulkan functions. Can be null.">VmaAllocatorCreateInfo::pVulkanFunctions</a>. </p>
+
+</div>
+</div>
+<h2 class="groupheader">Enumeration Type Documentation</h2>
+<a id="ad9889c10c798b040d59c92f257cae597"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ad9889c10c798b040d59c92f257cae597">&#9670;&nbsp;</a></span>VmaAllocationCreateFlagBits</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">enum <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597">VmaAllocationCreateFlagBits</a></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Flags to be passed as <a class="el" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b" title="Use VmaAllocationCreateFlagBits enum.">VmaAllocationCreateInfo::flags</a>. </p>
+<table class="fieldtable">
+<tr><th colspan="2">Enumerator</th></tr><tr><td class="fieldname"><a id="ad9889c10c798b040d59c92f257cae597a3fc311d855c2ff53f1090ef5c722b38f"></a>VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT&#160;</td><td class="fielddoc"><p>Set this flag if the allocation should have its own memory block. </p>
+<p>Use it for special, big resources, like fullscreen images used as attachments.</p>
+<p>You should not use this flag if <a class="el" href="struct_vma_allocation_create_info.html#a6272c0555cfd1fe28bff1afeb6190150" title="Pool that this allocation should be created in.">VmaAllocationCreateInfo::pool</a> is not null. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="ad9889c10c798b040d59c92f257cae597a89759603401014eb325eb22a3839f2ff"></a>VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT&#160;</td><td class="fielddoc"><p>Set this flag to only try to allocate from existing <code>VkDeviceMemory</code> blocks and never create new such block. </p>
+<p>If new allocation cannot be placed in any of the existing blocks, allocation fails with <code>VK_ERROR_OUT_OF_DEVICE_MEMORY</code> error.</p>
+<p>You should not use <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a3fc311d855c2ff53f1090ef5c722b38f" title="Set this flag if the allocation should have its own memory block.">VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT</a> and <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a89759603401014eb325eb22a3839f2ff" title="Set this flag to only try to allocate from existing VkDeviceMemory blocks and never create new such b...">VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT</a> at the same time. It makes no sense.</p>
+<p>If <a class="el" href="struct_vma_allocation_create_info.html#a6272c0555cfd1fe28bff1afeb6190150" title="Pool that this allocation should be created in.">VmaAllocationCreateInfo::pool</a> is not null, this flag is implied and ignored. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="ad9889c10c798b040d59c92f257cae597a11da372cc3a82931c5e5d6146cd9dd1f"></a>VMA_ALLOCATION_CREATE_MAPPED_BIT&#160;</td><td class="fielddoc"><p>Set this flag to use a memory that will be persistently mapped and retrieve pointer to it. </p>
+<p>Pointer to mapped memory will be returned through <a class="el" href="struct_vma_allocation_info.html#a5eeffbe2d2f30f53370ff14aefbadbe2" title="Pointer to the beginning of this allocation as mapped data.">VmaAllocationInfo::pMappedData</a>.</p>
+<p>Is it valid to use this flag for allocation made from memory type that is not <code>HOST_VISIBLE</code>. This flag is then ignored and memory is not mapped. This is useful if you need an allocation that is efficient to use on GPU (<code>DEVICE_LOCAL</code>) and still want to map it directly if possible on platforms that support it (e.g. Intel GPU).</p>
+<p>You should not use this flag together with <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a5f436af6c8fe8540573a6d22627a6fd2">VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT</a>. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="ad9889c10c798b040d59c92f257cae597a5f436af6c8fe8540573a6d22627a6fd2"></a>VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT&#160;</td><td class="fielddoc"><p>Allocation created with this flag can become lost as a result of another allocation with <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a68686d0ce9beb0d4d1b9f2b8b1389a7e">VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT</a> flag, so you must check it before use.</p>
+<p>To check if allocation is not lost, call <a class="el" href="vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b" title="Returns current information about specified allocation and atomically marks it as used in current fra...">vmaGetAllocationInfo()</a> and check if <a class="el" href="struct_vma_allocation_info.html#ae0bfb7dfdf79a76ffefc9a94677a2f67" title="Handle to Vulkan memory object.">VmaAllocationInfo::deviceMemory</a> is not <code>VK_NULL_HANDLE</code>.</p>
+<p>For details about supporting lost allocations, see Lost Allocations chapter of User Guide on Main Page.</p>
+<p>You should not use this flag together with <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a11da372cc3a82931c5e5d6146cd9dd1f" title="Set this flag to use a memory that will be persistently mapped and retrieve pointer to it.">VMA_ALLOCATION_CREATE_MAPPED_BIT</a>. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="ad9889c10c798b040d59c92f257cae597a68686d0ce9beb0d4d1b9f2b8b1389a7e"></a>VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT&#160;</td><td class="fielddoc"><p>While creating allocation using this flag, other allocations that were created with flag <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a5f436af6c8fe8540573a6d22627a6fd2">VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT</a> can become lost.</p>
+<p>For details about supporting lost allocations, see Lost Allocations chapter of User Guide on Main Page. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="ad9889c10c798b040d59c92f257cae597aa6f24f821cd6a7c5e4a443f7bf59c520"></a>VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT&#160;</td><td class="fielddoc"><p>Set this flag to treat <a class="el" href="struct_vma_allocation_create_info.html#a8259e85c272683434f4abb4ddddffe19" title="Custom general-purpose pointer that will be stored in VmaAllocation, can be read as VmaAllocationInfo...">VmaAllocationCreateInfo::pUserData</a> as pointer to a null-terminated string. Instead of copying pointer value, a local copy of the string is made and stored in allocation's <code>pUserData</code>. The string is automatically freed together with the allocation. It is also used in <a class="el" href="vk__mem__alloc_8h.html#aa4fee7eb5253377599ef4fd38c93c2a0" title="Builds and returns statistics as string in JSON format.">vmaBuildStatsString()</a>. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="ad9889c10c798b040d59c92f257cae597a42ba3a2d2c7117953210b7c3ef8da0df"></a>VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT&#160;</td><td class="fielddoc"><p>Allocation will be created from upper stack in a double stack pool.</p>
+<p>This flag is only allowed for custom pools created with <a class="el" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a13c8a444197c67866be9cb05599fc726" title="Enables alternative, linear allocation algorithm in this pool.">VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT</a> flag. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="ad9889c10c798b040d59c92f257cae597a2310568c62208af432724305fe29ccea"></a>VMA_ALLOCATION_CREATE_DONT_BIND_BIT&#160;</td><td class="fielddoc"><p>Create both buffer/image and allocation, but don't bind them together. It is useful when you want to bind yourself to do some more advanced binding, e.g. using some extensions. The flag is meaningful only with functions that bind by default: <a class="el" href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer()</a>, <a class="el" href="vk__mem__alloc_8h.html#a02a94f25679275851a53e82eacbcfc73" title="Function similar to vmaCreateBuffer().">vmaCreateImage()</a>. Otherwise it is ignored. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="ad9889c10c798b040d59c92f257cae597ab8b1764f3e9022368e440c057783b92d"></a>VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT&#160;</td><td class="fielddoc"><p>Create allocation only if additional device memory required for it, if any, won't exceed memory budget. Otherwise return <code>VK_ERROR_OUT_OF_DEVICE_MEMORY</code>. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="ad9889c10c798b040d59c92f257cae597a839826775c62319466441f86496f036d"></a>VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT&#160;</td><td class="fielddoc"><p>Allocation strategy that chooses smallest possible free range for the allocation. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="ad9889c10c798b040d59c92f257cae597ad242a04f802e25fef0b880afe8bb0a62"></a>VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT&#160;</td><td class="fielddoc"><p>Allocation strategy that chooses biggest possible free range for the allocation. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="ad9889c10c798b040d59c92f257cae597a33eb2052674f3ad92386c714a65fb777"></a>VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT&#160;</td><td class="fielddoc"><p>Allocation strategy that chooses first suitable free range for the allocation.</p>
+<p>"First" doesn't necessarily means the one with smallest offset in memory, but rather the one that is easiest and fastest to find. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="ad9889c10c798b040d59c92f257cae597a8af1210cf591784afa026d94998f735d"></a>VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT&#160;</td><td class="fielddoc"><p>Allocation strategy that tries to minimize memory usage. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="ad9889c10c798b040d59c92f257cae597a0729e932b7ea170e3a128cad96c5cf6d"></a>VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT&#160;</td><td class="fielddoc"><p>Allocation strategy that tries to minimize allocation time. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="ad9889c10c798b040d59c92f257cae597a621b704103eb3360230c860acf36e706"></a>VMA_ALLOCATION_CREATE_STRATEGY_MIN_FRAGMENTATION_BIT&#160;</td><td class="fielddoc"><p>Allocation strategy that tries to minimize memory fragmentation. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="ad9889c10c798b040d59c92f257cae597a8e16845d81ae3d27c47106d4770d5c7e"></a>VMA_ALLOCATION_CREATE_STRATEGY_MASK&#160;</td><td class="fielddoc"><p>A bit mask to extract only <code>STRATEGY</code> bits from entire set of flags. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="ad9889c10c798b040d59c92f257cae597ae5633ec569f4899cf8f29e7385b2f882"></a>VMA_ALLOCATION_CREATE_FLAG_BITS_MAX_ENUM&#160;</td><td class="fielddoc"></td></tr>
+</table>
+
+</div>
+</div>
+<a id="a4f87c9100d154a65a4ad495f7763cf7c"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a4f87c9100d154a65a4ad495f7763cf7c">&#9670;&nbsp;</a></span>VmaAllocatorCreateFlagBits</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">enum <a class="el" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7c">VmaAllocatorCreateFlagBits</a></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Flags for created <a class="el" href="struct_vma_allocator.html" title="Represents main object of this library initialized.">VmaAllocator</a>. </p>
+<table class="fieldtable">
+<tr><th colspan="2">Enumerator</th></tr><tr><td class="fieldname"><a id="a4f87c9100d154a65a4ad495f7763cf7ca4816ddaed324ba110172ca608a20f29d"></a>VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT&#160;</td><td class="fielddoc"><p>Allocator and all objects created from it will not be synchronized internally, so you must guarantee they are used from only one thread at a time or synchronized externally by you. </p>
+<p>Using this flag may increase performance because internal mutexes are not used. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="a4f87c9100d154a65a4ad495f7763cf7cace7da7cc6e71a625dfa763c55a597878"></a>VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT&#160;</td><td class="fielddoc"><p>Enables usage of VK_KHR_dedicated_allocation extension. </p>
+<p>The flag works only if <a class="el" href="struct_vma_allocator_create_info.html#ae0ffc55139b54520a6bb704b29ffc285" title="Optional. The highest version of Vulkan that the application is designed to use.">VmaAllocatorCreateInfo::vulkanApiVersion</a> <code>== VK_API_VERSION_1_0</code>. When it's <code>VK_API_VERSION_1_1</code>, the flag is ignored because the extension has been promoted to Vulkan 1.1.</p>
+<p>Using this extenion will automatically allocate dedicated blocks of memory for some buffers and images instead of suballocating place for them out of bigger memory blocks (as if you explicitly used <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a3fc311d855c2ff53f1090ef5c722b38f" title="Set this flag if the allocation should have its own memory block.">VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT</a> flag) when it is recommended by the driver. It may improve performance on some GPUs.</p>
+<p>You may set this flag only if you found out that following device extensions are supported, you enabled them while creating Vulkan device passed as <a class="el" href="struct_vma_allocator_create_info.html#ad924ddd77b04039c88d0c09b0ffcd500" title="Vulkan device.">VmaAllocatorCreateInfo::device</a>, and you want them to be used internally by this library:</p>
+<ul>
+<li>VK_KHR_get_memory_requirements2 (device extension)</li>
+<li>VK_KHR_dedicated_allocation (device extension)</li>
+</ul>
+<p>When this flag is set, you can experience following warnings reported by Vulkan validation layer. You can ignore them.</p>
+<blockquote class="doxtable">
+<p>vkBindBufferMemory(): Binding memory to buffer 0x2d but vkGetBufferMemoryRequirements() has not been called on that buffer. </p>
+</blockquote>
+</td></tr>
+<tr><td class="fieldname"><a id="a4f87c9100d154a65a4ad495f7763cf7ca8fb75bf07cd184ab903596295e863dee"></a>VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT&#160;</td><td class="fielddoc"><p>Enables usage of VK_KHR_bind_memory2 extension.</p>
+<p>The flag works only if <a class="el" href="struct_vma_allocator_create_info.html#ae0ffc55139b54520a6bb704b29ffc285" title="Optional. The highest version of Vulkan that the application is designed to use.">VmaAllocatorCreateInfo::vulkanApiVersion</a> <code>== VK_API_VERSION_1_0</code>. When it's <code>VK_API_VERSION_1_1</code>, the flag is ignored because the extension has been promoted to Vulkan 1.1.</p>
+<p>You may set this flag only if you found out that this device extension is supported, you enabled it while creating Vulkan device passed as <a class="el" href="struct_vma_allocator_create_info.html#ad924ddd77b04039c88d0c09b0ffcd500" title="Vulkan device.">VmaAllocatorCreateInfo::device</a>, and you want it to be used internally by this library.</p>
+<p>The extension provides functions <code>vkBindBufferMemory2KHR</code> and <code>vkBindImageMemory2KHR</code>, which allow to pass a chain of <code>pNext</code> structures while binding. This flag is required if you use <code>pNext</code> parameter in <a class="el" href="vk__mem__alloc_8h.html#a927c944f45e0f2941182abb6f608e64a" title="Binds buffer to allocation with additional parameters.">vmaBindBufferMemory2()</a> or <a class="el" href="vk__mem__alloc_8h.html#aa8251ee81b0045a443e35b8e8aa021bc" title="Binds image to allocation with additional parameters.">vmaBindImageMemory2()</a>. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="a4f87c9100d154a65a4ad495f7763cf7ca4d4687863f7bd4b418c6006dc04400b0"></a>VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT&#160;</td><td class="fielddoc"><p>Enables usage of VK_EXT_memory_budget extension.</p>
+<p>You may set this flag only if you found out that this device extension is supported, you enabled it while creating Vulkan device passed as <a class="el" href="struct_vma_allocator_create_info.html#ad924ddd77b04039c88d0c09b0ffcd500" title="Vulkan device.">VmaAllocatorCreateInfo::device</a>, and you want it to be used internally by this library, along with another instance extension VK_KHR_get_physical_device_properties2, which is required by it (or Vulkan 1.1, where this extension is promoted).</p>
+<p>The extension provides query for current memory usage and budget, which will probably be more accurate than an estimation used by the library otherwise. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="a4f87c9100d154a65a4ad495f7763cf7ca2acce4886d8078552efa38878413970f"></a>VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT&#160;</td><td class="fielddoc"><p>Enables usage of VK_AMD_device_coherent_memory extension.</p>
+<p>You may set this flag only if you:</p>
+<ul>
+<li>found out that this device extension is supported and enabled it while creating Vulkan device passed as <a class="el" href="struct_vma_allocator_create_info.html#ad924ddd77b04039c88d0c09b0ffcd500" title="Vulkan device.">VmaAllocatorCreateInfo::device</a>,</li>
+<li>checked that <code>VkPhysicalDeviceCoherentMemoryFeaturesAMD::deviceCoherentMemory</code> is true and set it while creating the Vulkan device,</li>
+<li>want it to be used internally by this library.</li>
+</ul>
+<p>The extension and accompanying device feature provide access to memory types with <code>VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD</code> and <code>VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD</code> flags. They are useful mostly for writing breadcrumb markers - a common method for debugging GPU crash/hang/TDR.</p>
+<p>When the extension is not enabled, such memory types are still enumerated, but their usage is illegal. To protect from this error, if you don't create the allocator with this flag, it will refuse to allocate any memory or create a custom pool in such memory type, returning <code>VK_ERROR_FEATURE_NOT_PRESENT</code>. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="a4f87c9100d154a65a4ad495f7763cf7ca5f1b28b0414319d1687e1f2b30ab0089"></a>VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT&#160;</td><td class="fielddoc"><p>Enables usage of "buffer device address" feature, which allows you to use function <code>vkGetBufferDeviceAddress*</code> to get raw GPU pointer to a buffer and pass it for usage inside a shader.</p>
+<p>You may set this flag only if you:</p>
+<ol type="1">
+<li>(For Vulkan version &lt; 1.2) Found as available and enabled device extension VK_KHR_buffer_device_address. This extension is promoted to core Vulkan 1.2.</li>
+<li>Found as available and enabled device feature <code>VkPhysicalDeviceBufferDeviceAddressFeatures*::bufferDeviceAddress</code>.</li>
+</ol>
+<p>When this flag is set, you can create buffers with <code>VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT*</code> using VMA. The library automatically adds <code>VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT*</code> to allocated memory blocks wherever it might be needed.</p>
+<p>For more information, see documentation chapter <a class="el" href="enabling_buffer_device_address.html">Enabling buffer device address</a>. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="a4f87c9100d154a65a4ad495f7763cf7cae4d5ad929caba5f23eb502b13bd5286c"></a>VMA_ALLOCATOR_CREATE_FLAG_BITS_MAX_ENUM&#160;</td><td class="fielddoc"></td></tr>
+</table>
+
+</div>
+</div>
+<a id="a6552a65b71d16f378c6994b3ceaef50c"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a6552a65b71d16f378c6994b3ceaef50c">&#9670;&nbsp;</a></span>VmaDefragmentationFlagBits</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">enum <a class="el" href="vk__mem__alloc_8h.html#a6552a65b71d16f378c6994b3ceaef50c">VmaDefragmentationFlagBits</a></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Flags to be used in <a class="el" href="vk__mem__alloc_8h.html#a36ba776fd7fd5cb1e9359fdc0d8e6e8a" title="Begins defragmentation process.">vmaDefragmentationBegin()</a>. None at the moment. Reserved for future use. </p>
+<table class="fieldtable">
+<tr><th colspan="2">Enumerator</th></tr><tr><td class="fieldname"><a id="a6552a65b71d16f378c6994b3ceaef50ca31af49446af2459284a568ce2f3fdd33"></a>VMA_DEFRAGMENTATION_FLAG_INCREMENTAL&#160;</td><td class="fielddoc"></td></tr>
+<tr><td class="fieldname"><a id="a6552a65b71d16f378c6994b3ceaef50cab87ec33154803bfeb5ac2b379f1d6a97"></a>VMA_DEFRAGMENTATION_FLAG_BITS_MAX_ENUM&#160;</td><td class="fielddoc"></td></tr>
+</table>
+
+</div>
+</div>
+<a id="aa5846affa1e9da3800e3e78fae2305cc"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#aa5846affa1e9da3800e3e78fae2305cc">&#9670;&nbsp;</a></span>VmaMemoryUsage</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">enum <a class="el" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cc">VmaMemoryUsage</a></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+<table class="fieldtable">
+<tr><th colspan="2">Enumerator</th></tr><tr><td class="fieldname"><a id="aa5846affa1e9da3800e3e78fae2305ccaf50d27e34e0925cf3a63db8c839121dd"></a>VMA_MEMORY_USAGE_UNKNOWN&#160;</td><td class="fielddoc"><p>No intended memory usage specified. Use other members of <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> to specify your requirements. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7"></a>VMA_MEMORY_USAGE_GPU_ONLY&#160;</td><td class="fielddoc"><p>Memory will be used on device only, so fast access from the device is preferred. It usually means device-local GPU (video) memory. No need to be mappable on host. It is roughly equivalent of <code>D3D12_HEAP_TYPE_DEFAULT</code>.</p>
+<p>Usage:</p>
+<ul>
+<li>Resources written and read by device, e.g. images used as attachments.</li>
+<li>Resources transferred from host once (immutable) or infrequently and read by device multiple times, e.g. textures to be sampled, vertex buffers, uniform (constant) buffers, and majority of other types of resources used on GPU.</li>
+</ul>
+<p>Allocation may still end up in <code>HOST_VISIBLE</code> memory on some implementations. In such case, you are free to map it. You can use <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a11da372cc3a82931c5e5d6146cd9dd1f" title="Set this flag to use a memory that will be persistently mapped and retrieve pointer to it.">VMA_ALLOCATION_CREATE_MAPPED_BIT</a> with this usage type. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="aa5846affa1e9da3800e3e78fae2305cca40bdf4cddeffeb12f43d45ca1286e0a5"></a>VMA_MEMORY_USAGE_CPU_ONLY&#160;</td><td class="fielddoc"><p>Memory will be mappable on host. It usually means CPU (system) memory. Guarantees to be <code>HOST_VISIBLE</code> and <code>HOST_COHERENT</code>. CPU access is typically uncached. Writes may be write-combined. Resources created in this pool may still be accessible to the device, but access to them can be slow. It is roughly equivalent of <code>D3D12_HEAP_TYPE_UPLOAD</code>.</p>
+<p>Usage: Staging copy of resources used as transfer source. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="aa5846affa1e9da3800e3e78fae2305cca9066b52c5a7079bb74a69aaf8b92ff67"></a>VMA_MEMORY_USAGE_CPU_TO_GPU&#160;</td><td class="fielddoc"><p>Memory that is both mappable on host (guarantees to be <code>HOST_VISIBLE</code>) and preferably fast to access by GPU. CPU access is typically uncached. Writes may be write-combined.</p>
+<p>Usage: Resources written frequently by host (dynamic), read by device. E.g. textures, vertex buffers, uniform buffers updated every frame or every draw call. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="aa5846affa1e9da3800e3e78fae2305cca7b586d2fdaf82a463b58f581ed72be27"></a>VMA_MEMORY_USAGE_GPU_TO_CPU&#160;</td><td class="fielddoc"><p>Memory mappable on host (guarantees to be <code>HOST_VISIBLE</code>) and cached. It is roughly equivalent of <code>D3D12_HEAP_TYPE_READBACK</code>.</p>
+<p>Usage:</p>
+<ul>
+<li>Resources written by device, read by host - results of some computations, e.g. screen capture, average scene luminance for HDR tone mapping.</li>
+<li>Any resources read or accessed randomly on host, e.g. CPU-side copy of vertex buffer used as source of transfer, but also used for collision detection. </li>
+</ul>
+</td></tr>
+<tr><td class="fieldname"><a id="aa5846affa1e9da3800e3e78fae2305cca416a444d4d0fc20067c3f76f32ff2500"></a>VMA_MEMORY_USAGE_CPU_COPY&#160;</td><td class="fielddoc"><p>CPU memory - memory that is preferably not <code>DEVICE_LOCAL</code>, but also not guaranteed to be <code>HOST_VISIBLE</code>.</p>
+<p>Usage: Staging copy of resources moved from GPU memory to CPU memory as part of custom paging/residency mechanism, to be moved back to GPU memory when needed. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="aa5846affa1e9da3800e3e78fae2305cca835333d9072db63a653818030e17614d"></a>VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED&#160;</td><td class="fielddoc"><p>Lazily allocated GPU memory having <code>VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT</code>. Exists mostly on mobile platforms. Using it on desktop PC or other GPUs with no such memory type present will fail the allocation.</p>
+<p>Usage: Memory for transient attachment images (color attachments, depth attachments etc.), created with <code>VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT</code>.</p>
+<p>Allocations with this usage are always created as dedicated - it implies <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a3fc311d855c2ff53f1090ef5c722b38f" title="Set this flag if the allocation should have its own memory block.">VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT</a>. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="aa5846affa1e9da3800e3e78fae2305cca091e69437ef693e8d0d287f1c719ba6e"></a>VMA_MEMORY_USAGE_MAX_ENUM&#160;</td><td class="fielddoc"></td></tr>
+</table>
+
+</div>
+</div>
+<a id="a9a7c45f9c863695d98c83fa5ac940fe7"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a9a7c45f9c863695d98c83fa5ac940fe7">&#9670;&nbsp;</a></span>VmaPoolCreateFlagBits</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">enum <a class="el" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7">VmaPoolCreateFlagBits</a></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Flags to be passed as <a class="el" href="struct_vma_pool_create_info.html#a8405139f63d078340ae74513a59f5446" title="Use combination of VmaPoolCreateFlagBits.">VmaPoolCreateInfo::flags</a>. </p>
+<table class="fieldtable">
+<tr><th colspan="2">Enumerator</th></tr><tr><td class="fieldname"><a id="a9a7c45f9c863695d98c83fa5ac940fe7a9f1a499508a8edb4e8ba40aa0290a3d2"></a>VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT&#160;</td><td class="fielddoc"><p>Use this flag if you always allocate only buffers and linear images or only optimal images out of this pool and so Buffer-Image Granularity can be ignored. </p>
+<p>This is an optional optimization flag.</p>
+<p>If you always allocate using <a class="el" href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer()</a>, <a class="el" href="vk__mem__alloc_8h.html#a02a94f25679275851a53e82eacbcfc73" title="Function similar to vmaCreateBuffer().">vmaCreateImage()</a>, <a class="el" href="vk__mem__alloc_8h.html#a7fdf64415b6c3d83c454f28d2c53df7b">vmaAllocateMemoryForBuffer()</a>, then you don't need to use it because allocator knows exact type of your allocations so it can handle Buffer-Image Granularity in the optimal way.</p>
+<p>If you also allocate using <a class="el" href="vk__mem__alloc_8h.html#a0faa3f9e5fb233d29d1e00390650febb" title="Function similar to vmaAllocateMemoryForBuffer().">vmaAllocateMemoryForImage()</a> or <a class="el" href="vk__mem__alloc_8h.html#abf28077dbf82d0908b8acbe8ee8dd9b8" title="General purpose memory allocation.">vmaAllocateMemory()</a>, exact type of such allocations is not known, so allocator must be conservative in handling Buffer-Image Granularity, which can lead to suboptimal allocation (wasted memory). In that case, if you can make sure you always allocate only buffers and linear images or only optimal images out of this pool, use this flag to make allocator disregard Buffer-Image Granularity and so make allocations faster and more optimal. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="a9a7c45f9c863695d98c83fa5ac940fe7a13c8a444197c67866be9cb05599fc726"></a>VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT&#160;</td><td class="fielddoc"><p>Enables alternative, linear allocation algorithm in this pool. </p>
+<p>Specify this flag to enable linear allocation algorithm, which always creates new allocations after last one and doesn't reuse space from allocations freed in between. It trades memory consumption for simplified algorithm and data structure, which has better performance and uses less memory for metadata.</p>
+<p>By using this flag, you can achieve behavior of free-at-once, stack, ring buffer, and double stack. For details, see documentation chapter <a class="el" href="custom_memory_pools.html#linear_algorithm">Linear allocation algorithm</a>.</p>
+<p>When using this flag, you must specify <a class="el" href="struct_vma_pool_create_info.html#ae41142f2834fcdc82baa4883c187b75c" title="Maximum number of blocks that can be allocated in this pool. Optional.">VmaPoolCreateInfo::maxBlockCount</a> == 1 (or 0 for default).</p>
+<p>For more details, see <a class="el" href="custom_memory_pools.html#linear_algorithm">Linear allocation algorithm</a>. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="a9a7c45f9c863695d98c83fa5ac940fe7a97a0dc38e5161b780594d998d313d35e"></a>VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT&#160;</td><td class="fielddoc"><p>Enables alternative, buddy allocation algorithm in this pool. </p>
+<p>It operates on a tree of blocks, each having size that is a power of two and a half of its parent's size. Comparing to default algorithm, this one provides faster allocation and deallocation and decreased external fragmentation, at the expense of more memory wasted (internal fragmentation).</p>
+<p>For more details, see <a class="el" href="custom_memory_pools.html#buddy_algorithm">Buddy allocation algorithm</a>. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="a9a7c45f9c863695d98c83fa5ac940fe7af4d270f8f42517a0f70037ceb6ac1d9c"></a>VMA_POOL_CREATE_ALGORITHM_MASK&#160;</td><td class="fielddoc"><p>Bit mask to extract only <code>ALGORITHM</code> bits from entire set of flags. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="a9a7c45f9c863695d98c83fa5ac940fe7a1c7312bea9ea246846b9054fd6bd6aec"></a>VMA_POOL_CREATE_FLAG_BITS_MAX_ENUM&#160;</td><td class="fielddoc"></td></tr>
+</table>
+
+</div>
+</div>
+<a id="a4dd2c44642312a147a4e93373a6e64d2"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a4dd2c44642312a147a4e93373a6e64d2">&#9670;&nbsp;</a></span>VmaRecordFlagBits</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">enum <a class="el" href="vk__mem__alloc_8h.html#a4dd2c44642312a147a4e93373a6e64d2">VmaRecordFlagBits</a></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Flags to be used in <a class="el" href="struct_vma_record_settings.html#ad8fdcc92119ae7a8c08c1a564c01d63a" title="Flags for recording. Use VmaRecordFlagBits enum.">VmaRecordSettings::flags</a>. </p>
+<table class="fieldtable">
+<tr><th colspan="2">Enumerator</th></tr><tr><td class="fieldname"><a id="a4dd2c44642312a147a4e93373a6e64d2a8e7ab322e8732654be627c4ea8f36cc7"></a>VMA_RECORD_FLUSH_AFTER_CALL_BIT&#160;</td><td class="fielddoc"><p>Enables flush after recording every function call. </p>
+<p>Enable it if you expect your application to crash, which may leave recording file truncated. It may degrade performance though. </p>
+</td></tr>
+<tr><td class="fieldname"><a id="a4dd2c44642312a147a4e93373a6e64d2a20dd17d69966dbffa054739d6090b85e"></a>VMA_RECORD_FLAG_BITS_MAX_ENUM&#160;</td><td class="fielddoc"></td></tr>
+</table>
+
+</div>
+</div>
+<h2 class="groupheader">Function Documentation</h2>
+<a id="abf28077dbf82d0908b8acbe8ee8dd9b8"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#abf28077dbf82d0908b8acbe8ee8dd9b8">&#9670;&nbsp;</a></span>vmaAllocateMemory()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkResult vmaAllocateMemory </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const VkMemoryRequirements *&#160;</td>
+          <td class="paramname"><em>pVkMemoryRequirements</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> *&#160;</td>
+          <td class="paramname"><em>pCreateInfo</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocation.html">VmaAllocation</a> *&#160;</td>
+          <td class="paramname"><em>pAllocation</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocation_info.html">VmaAllocationInfo</a> *&#160;</td>
+          <td class="paramname"><em>pAllocationInfo</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>General purpose memory allocation. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramdir">[out]</td><td class="paramname">pAllocation</td><td>Handle to allocated memory. </td></tr>
+    <tr><td class="paramdir">[out]</td><td class="paramname">pAllocationInfo</td><td>Optional. Information about allocated memory. It can be later fetched using function <a class="el" href="vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b" title="Returns current information about specified allocation and atomically marks it as used in current fra...">vmaGetAllocationInfo()</a>.</td></tr>
+  </table>
+  </dd>
+</dl>
+<p>You should free the memory using <a class="el" href="vk__mem__alloc_8h.html#a11f0fbc034fa81a4efedd73d61ce7568" title="Frees memory previously allocated using vmaAllocateMemory(), vmaAllocateMemoryForBuffer(),...">vmaFreeMemory()</a> or <a class="el" href="vk__mem__alloc_8h.html#ab9e709de044c5d8476bea77a4e755840" title="Frees memory and destroys multiple allocations.">vmaFreeMemoryPages()</a>.</p>
+<p>It is recommended to use <a class="el" href="vk__mem__alloc_8h.html#a7fdf64415b6c3d83c454f28d2c53df7b">vmaAllocateMemoryForBuffer()</a>, <a class="el" href="vk__mem__alloc_8h.html#a0faa3f9e5fb233d29d1e00390650febb" title="Function similar to vmaAllocateMemoryForBuffer().">vmaAllocateMemoryForImage()</a>, <a class="el" href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer()</a>, <a class="el" href="vk__mem__alloc_8h.html#a02a94f25679275851a53e82eacbcfc73" title="Function similar to vmaCreateBuffer().">vmaCreateImage()</a> instead whenever possible. </p>
+
+</div>
+</div>
+<a id="a7fdf64415b6c3d83c454f28d2c53df7b"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a7fdf64415b6c3d83c454f28d2c53df7b">&#9670;&nbsp;</a></span>vmaAllocateMemoryForBuffer()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkResult vmaAllocateMemoryForBuffer </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">VkBuffer&#160;</td>
+          <td class="paramname"><em>buffer</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> *&#160;</td>
+          <td class="paramname"><em>pCreateInfo</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocation.html">VmaAllocation</a> *&#160;</td>
+          <td class="paramname"><em>pAllocation</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocation_info.html">VmaAllocationInfo</a> *&#160;</td>
+          <td class="paramname"><em>pAllocationInfo</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramdir">[out]</td><td class="paramname">pAllocation</td><td>Handle to allocated memory. </td></tr>
+    <tr><td class="paramdir">[out]</td><td class="paramname">pAllocationInfo</td><td>Optional. Information about allocated memory. It can be later fetched using function <a class="el" href="vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b" title="Returns current information about specified allocation and atomically marks it as used in current fra...">vmaGetAllocationInfo()</a>.</td></tr>
+  </table>
+  </dd>
+</dl>
+<p>You should free the memory using <a class="el" href="vk__mem__alloc_8h.html#a11f0fbc034fa81a4efedd73d61ce7568" title="Frees memory previously allocated using vmaAllocateMemory(), vmaAllocateMemoryForBuffer(),...">vmaFreeMemory()</a>. </p>
+
+</div>
+</div>
+<a id="a0faa3f9e5fb233d29d1e00390650febb"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a0faa3f9e5fb233d29d1e00390650febb">&#9670;&nbsp;</a></span>vmaAllocateMemoryForImage()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkResult vmaAllocateMemoryForImage </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">VkImage&#160;</td>
+          <td class="paramname"><em>image</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> *&#160;</td>
+          <td class="paramname"><em>pCreateInfo</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocation.html">VmaAllocation</a> *&#160;</td>
+          <td class="paramname"><em>pAllocation</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocation_info.html">VmaAllocationInfo</a> *&#160;</td>
+          <td class="paramname"><em>pAllocationInfo</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Function similar to <a class="el" href="vk__mem__alloc_8h.html#a7fdf64415b6c3d83c454f28d2c53df7b">vmaAllocateMemoryForBuffer()</a>. </p>
+
+</div>
+</div>
+<a id="ad37e82e492b3de38fc3f4cffd9ad0ae1"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ad37e82e492b3de38fc3f4cffd9ad0ae1">&#9670;&nbsp;</a></span>vmaAllocateMemoryPages()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkResult vmaAllocateMemoryPages </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const VkMemoryRequirements *&#160;</td>
+          <td class="paramname"><em>pVkMemoryRequirements</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> *&#160;</td>
+          <td class="paramname"><em>pCreateInfo</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>allocationCount</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocation.html">VmaAllocation</a> *&#160;</td>
+          <td class="paramname"><em>pAllocations</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocation_info.html">VmaAllocationInfo</a> *&#160;</td>
+          <td class="paramname"><em>pAllocationInfo</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>General purpose memory allocation for multiple allocation objects at once. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramdir"></td><td class="paramname">allocator</td><td>Allocator object. </td></tr>
+    <tr><td class="paramdir"></td><td class="paramname">pVkMemoryRequirements</td><td>Memory requirements for each allocation. </td></tr>
+    <tr><td class="paramdir"></td><td class="paramname">pCreateInfo</td><td>Creation parameters for each alloction. </td></tr>
+    <tr><td class="paramdir"></td><td class="paramname">allocationCount</td><td>Number of allocations to make. </td></tr>
+    <tr><td class="paramdir">[out]</td><td class="paramname">pAllocations</td><td>Pointer to array that will be filled with handles to created allocations. </td></tr>
+    <tr><td class="paramdir">[out]</td><td class="paramname">pAllocationInfo</td><td>Optional. Pointer to array that will be filled with parameters of created allocations.</td></tr>
+  </table>
+  </dd>
+</dl>
+<p>You should free the memory using <a class="el" href="vk__mem__alloc_8h.html#a11f0fbc034fa81a4efedd73d61ce7568" title="Frees memory previously allocated using vmaAllocateMemory(), vmaAllocateMemoryForBuffer(),...">vmaFreeMemory()</a> or <a class="el" href="vk__mem__alloc_8h.html#ab9e709de044c5d8476bea77a4e755840" title="Frees memory and destroys multiple allocations.">vmaFreeMemoryPages()</a>.</p>
+<p>Word "pages" is just a suggestion to use this function to allocate pieces of memory needed for sparse binding. It is just a general purpose allocation function able to make multiple allocations at once. It may be internally optimized to be more efficient than calling <a class="el" href="vk__mem__alloc_8h.html#abf28077dbf82d0908b8acbe8ee8dd9b8" title="General purpose memory allocation.">vmaAllocateMemory()</a> <code>allocationCount</code> times.</p>
+<p>All allocations are made using same parameters. All of them are created out of the same memory pool and type. If any allocation fails, all allocations already made within this function call are also freed, so that when returned result is not <code>VK_SUCCESS</code>, <code>pAllocation</code> array is always entirely filled with <code>VK_NULL_HANDLE</code>. </p>
+
+</div>
+</div>
+<a id="ac0f01545b6262f7d4d128fc8f8e5c77b"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ac0f01545b6262f7d4d128fc8f8e5c77b">&#9670;&nbsp;</a></span>vmaBeginDefragmentationPass()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkResult vmaBeginDefragmentationPass </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_defragmentation_context.html">VmaDefragmentationContext</a>&#160;</td>
+          <td class="paramname"><em>context</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_defragmentation_pass_info.html">VmaDefragmentationPassInfo</a> *&#160;</td>
+          <td class="paramname"><em>pInfo</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="a6b0929b914b60cf2d45cac4bf3547470"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a6b0929b914b60cf2d45cac4bf3547470">&#9670;&nbsp;</a></span>vmaBindBufferMemory()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkResult vmaBindBufferMemory </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocation.html">VmaAllocation</a>&#160;</td>
+          <td class="paramname"><em>allocation</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">VkBuffer&#160;</td>
+          <td class="paramname"><em>buffer</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Binds buffer to allocation. </p>
+<p>Binds specified buffer to region of memory represented by specified allocation. Gets <code>VkDeviceMemory</code> handle and offset from the allocation. If you want to create a buffer, allocate memory for it and bind them together separately, you should use this function for binding instead of standard <code>vkBindBufferMemory()</code>, because it ensures proper synchronization so that when a <code>VkDeviceMemory</code> object is used by multiple allocations, calls to <code>vkBind*Memory()</code> or <code>vkMapMemory()</code> won't happen from multiple threads simultaneously (which is illegal in Vulkan).</p>
+<p>It is recommended to use function <a class="el" href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer()</a> instead of this one. </p>
+
+</div>
+</div>
+<a id="a927c944f45e0f2941182abb6f608e64a"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a927c944f45e0f2941182abb6f608e64a">&#9670;&nbsp;</a></span>vmaBindBufferMemory2()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkResult vmaBindBufferMemory2 </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocation.html">VmaAllocation</a>&#160;</td>
+          <td class="paramname"><em>allocation</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">VkDeviceSize&#160;</td>
+          <td class="paramname"><em>allocationLocalOffset</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">VkBuffer&#160;</td>
+          <td class="paramname"><em>buffer</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const void *&#160;</td>
+          <td class="paramname"><em>pNext</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Binds buffer to allocation with additional parameters. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">allocationLocalOffset</td><td>Additional offset to be added while binding, relative to the beginnig of the <code>allocation</code>. Normally it should be 0. </td></tr>
+    <tr><td class="paramname">pNext</td><td>A chain of structures to be attached to <code>VkBindBufferMemoryInfoKHR</code> structure used internally. Normally it should be null.</td></tr>
+  </table>
+  </dd>
+</dl>
+<p>This function is similar to <a class="el" href="vk__mem__alloc_8h.html#a6b0929b914b60cf2d45cac4bf3547470" title="Binds buffer to allocation.">vmaBindBufferMemory()</a>, but it provides additional parameters.</p>
+<p>If <code>pNext</code> is not null, <a class="el" href="struct_vma_allocator.html" title="Represents main object of this library initialized.">VmaAllocator</a> object must have been created with <a class="el" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca8fb75bf07cd184ab903596295e863dee">VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT</a> flag or with <a class="el" href="struct_vma_allocator_create_info.html#ae0ffc55139b54520a6bb704b29ffc285" title="Optional. The highest version of Vulkan that the application is designed to use.">VmaAllocatorCreateInfo::vulkanApiVersion</a> <code>== VK_API_VERSION_1_1</code>. Otherwise the call fails. </p>
+
+</div>
+</div>
+<a id="a3d3ca45799923aa5d138e9e5f9eb2da5"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a3d3ca45799923aa5d138e9e5f9eb2da5">&#9670;&nbsp;</a></span>vmaBindImageMemory()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkResult vmaBindImageMemory </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocation.html">VmaAllocation</a>&#160;</td>
+          <td class="paramname"><em>allocation</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">VkImage&#160;</td>
+          <td class="paramname"><em>image</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Binds image to allocation. </p>
+<p>Binds specified image to region of memory represented by specified allocation. Gets <code>VkDeviceMemory</code> handle and offset from the allocation. If you want to create an image, allocate memory for it and bind them together separately, you should use this function for binding instead of standard <code>vkBindImageMemory()</code>, because it ensures proper synchronization so that when a <code>VkDeviceMemory</code> object is used by multiple allocations, calls to <code>vkBind*Memory()</code> or <code>vkMapMemory()</code> won't happen from multiple threads simultaneously (which is illegal in Vulkan).</p>
+<p>It is recommended to use function <a class="el" href="vk__mem__alloc_8h.html#a02a94f25679275851a53e82eacbcfc73" title="Function similar to vmaCreateBuffer().">vmaCreateImage()</a> instead of this one. </p>
+
+</div>
+</div>
+<a id="aa8251ee81b0045a443e35b8e8aa021bc"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#aa8251ee81b0045a443e35b8e8aa021bc">&#9670;&nbsp;</a></span>vmaBindImageMemory2()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkResult vmaBindImageMemory2 </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocation.html">VmaAllocation</a>&#160;</td>
+          <td class="paramname"><em>allocation</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">VkDeviceSize&#160;</td>
+          <td class="paramname"><em>allocationLocalOffset</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">VkImage&#160;</td>
+          <td class="paramname"><em>image</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const void *&#160;</td>
+          <td class="paramname"><em>pNext</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Binds image to allocation with additional parameters. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">allocationLocalOffset</td><td>Additional offset to be added while binding, relative to the beginnig of the <code>allocation</code>. Normally it should be 0. </td></tr>
+    <tr><td class="paramname">pNext</td><td>A chain of structures to be attached to <code>VkBindImageMemoryInfoKHR</code> structure used internally. Normally it should be null.</td></tr>
+  </table>
+  </dd>
+</dl>
+<p>This function is similar to <a class="el" href="vk__mem__alloc_8h.html#a3d3ca45799923aa5d138e9e5f9eb2da5" title="Binds image to allocation.">vmaBindImageMemory()</a>, but it provides additional parameters.</p>
+<p>If <code>pNext</code> is not null, <a class="el" href="struct_vma_allocator.html" title="Represents main object of this library initialized.">VmaAllocator</a> object must have been created with <a class="el" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca8fb75bf07cd184ab903596295e863dee">VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT</a> flag or with <a class="el" href="struct_vma_allocator_create_info.html#ae0ffc55139b54520a6bb704b29ffc285" title="Optional. The highest version of Vulkan that the application is designed to use.">VmaAllocatorCreateInfo::vulkanApiVersion</a> <code>== VK_API_VERSION_1_1</code>. Otherwise the call fails. </p>
+
+</div>
+</div>
+<a id="aa4fee7eb5253377599ef4fd38c93c2a0"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#aa4fee7eb5253377599ef4fd38c93c2a0">&#9670;&nbsp;</a></span>vmaBuildStatsString()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void vmaBuildStatsString </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">char **&#160;</td>
+          <td class="paramname"><em>ppStatsString</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">VkBool32&#160;</td>
+          <td class="paramname"><em>detailedMap</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Builds and returns statistics as string in JSON format. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramdir">[out]</td><td class="paramname">ppStatsString</td><td>Must be freed using <a class="el" href="vk__mem__alloc_8h.html#a3104eb30d8122c84dd8541063f145288">vmaFreeStatsString()</a> function. </td></tr>
+  </table>
+  </dd>
+</dl>
+
+</div>
+</div>
+<a id="a333b61c1788cb23559177531e6a93ca3"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a333b61c1788cb23559177531e6a93ca3">&#9670;&nbsp;</a></span>vmaCalculateStats()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void vmaCalculateStats </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_stats.html">VmaStats</a> *&#160;</td>
+          <td class="paramname"><em>pStats</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Retrieves statistics from current state of the Allocator. </p>
+<p>This function is called "calculate" not "get" because it has to traverse all internal data structures, so it may be quite slow. For faster but more brief statistics suitable to be called every frame or every allocation, use <a class="el" href="vk__mem__alloc_8h.html#aec0ed24ebea2d0099eed5f801daaefba" title="Retrieves information about current memory budget for all memory heaps.">vmaGetBudget()</a>.</p>
+<p>Note that when using allocator from multiple threads, returned information may immediately become outdated. </p>
+
+</div>
+</div>
+<a id="a49329a7f030dafcf82f7b73334c22e98"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a49329a7f030dafcf82f7b73334c22e98">&#9670;&nbsp;</a></span>vmaCheckCorruption()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkResult vmaCheckCorruption </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">uint32_t&#160;</td>
+          <td class="paramname"><em>memoryTypeBits</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Checks magic number in margins around all allocations in given memory types (in both default and custom pools) in search for corruptions. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramname">memoryTypeBits</td><td>Bit mask, where each bit set means that a memory type with that index should be checked.</td></tr>
+  </table>
+  </dd>
+</dl>
+<p>Corruption detection is enabled only when <code>VMA_DEBUG_DETECT_CORRUPTION</code> macro is defined to nonzero, <code>VMA_DEBUG_MARGIN</code> is defined to nonzero and only for memory types that are <code>HOST_VISIBLE</code> and <code>HOST_COHERENT</code>. For more information, see <a class="el" href="debugging_memory_usage.html#debugging_memory_usage_corruption_detection">Corruption detection</a>.</p>
+<p>Possible return values:</p>
+<ul>
+<li><code>VK_ERROR_FEATURE_NOT_PRESENT</code> - corruption detection is not enabled for any of specified memory types.</li>
+<li><code>VK_SUCCESS</code> - corruption detection has been performed and succeeded.</li>
+<li><code>VK_ERROR_VALIDATION_FAILED_EXT</code> - corruption detection has been performed and found memory corruptions around one of the allocations. <code>VMA_ASSERT</code> is also fired in that case.</li>
+<li>Other value: Error returned by Vulkan, e.g. memory mapping failure. </li>
+</ul>
+
+</div>
+</div>
+<a id="ad535935619c7a549bf837e1bb0068f89"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ad535935619c7a549bf837e1bb0068f89">&#9670;&nbsp;</a></span>vmaCheckPoolCorruption()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkResult vmaCheckPoolCorruption </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_pool.html">VmaPool</a>&#160;</td>
+          <td class="paramname"><em>pool</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Checks magic number in margins around all allocations in given memory pool in search for corruptions. </p>
+<p>Corruption detection is enabled only when <code>VMA_DEBUG_DETECT_CORRUPTION</code> macro is defined to nonzero, <code>VMA_DEBUG_MARGIN</code> is defined to nonzero and the pool is created in memory type that is <code>HOST_VISIBLE</code> and <code>HOST_COHERENT</code>. For more information, see <a class="el" href="debugging_memory_usage.html#debugging_memory_usage_corruption_detection">Corruption detection</a>.</p>
+<p>Possible return values:</p>
+<ul>
+<li><code>VK_ERROR_FEATURE_NOT_PRESENT</code> - corruption detection is not enabled for specified pool.</li>
+<li><code>VK_SUCCESS</code> - corruption detection has been performed and succeeded.</li>
+<li><code>VK_ERROR_VALIDATION_FAILED_EXT</code> - corruption detection has been performed and found memory corruptions around one of the allocations. <code>VMA_ASSERT</code> is also fired in that case.</li>
+<li>Other value: Error returned by Vulkan, e.g. memory mapping failure. </li>
+</ul>
+
+</div>
+</div>
+<a id="a200692051ddb34240248234f5f4c17bb"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a200692051ddb34240248234f5f4c17bb">&#9670;&nbsp;</a></span>vmaCreateAllocator()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkResult vmaCreateAllocator </td>
+          <td>(</td>
+          <td class="paramtype">const <a class="el" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a> *&#160;</td>
+          <td class="paramname"><em>pCreateInfo</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a> *&#160;</td>
+          <td class="paramname"><em>pAllocator</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Creates Allocator object. </p>
+
+</div>
+</div>
+<a id="ac72ee55598617e8eecca384e746bab51"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ac72ee55598617e8eecca384e746bab51">&#9670;&nbsp;</a></span>vmaCreateBuffer()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkResult vmaCreateBuffer </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const VkBufferCreateInfo *&#160;</td>
+          <td class="paramname"><em>pBufferCreateInfo</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> *&#160;</td>
+          <td class="paramname"><em>pAllocationCreateInfo</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">VkBuffer *&#160;</td>
+          <td class="paramname"><em>pBuffer</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocation.html">VmaAllocation</a> *&#160;</td>
+          <td class="paramname"><em>pAllocation</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocation_info.html">VmaAllocationInfo</a> *&#160;</td>
+          <td class="paramname"><em>pAllocationInfo</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramdir">[out]</td><td class="paramname">pBuffer</td><td>Buffer that was created. </td></tr>
+    <tr><td class="paramdir">[out]</td><td class="paramname">pAllocation</td><td>Allocation that was created. </td></tr>
+    <tr><td class="paramdir">[out]</td><td class="paramname">pAllocationInfo</td><td>Optional. Information about allocated memory. It can be later fetched using function <a class="el" href="vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b" title="Returns current information about specified allocation and atomically marks it as used in current fra...">vmaGetAllocationInfo()</a>.</td></tr>
+  </table>
+  </dd>
+</dl>
+<p>This function automatically:</p>
+<ol type="1">
+<li>Creates buffer.</li>
+<li>Allocates appropriate memory for it.</li>
+<li>Binds the buffer with the memory.</li>
+</ol>
+<p>If any of these operations fail, buffer and allocation are not created, returned value is negative error code, *pBuffer and *pAllocation are null.</p>
+<p>If the function succeeded, you must destroy both buffer and allocation when you no longer need them using either convenience function <a class="el" href="vk__mem__alloc_8h.html#a0d9f4e4ba5bf9aab1f1c746387753d77" title="Destroys Vulkan buffer and frees allocated memory.">vmaDestroyBuffer()</a> or separately, using <code>vkDestroyBuffer()</code> and <a class="el" href="vk__mem__alloc_8h.html#a11f0fbc034fa81a4efedd73d61ce7568" title="Frees memory previously allocated using vmaAllocateMemory(), vmaAllocateMemoryForBuffer(),...">vmaFreeMemory()</a>.</p>
+<p>If VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT flag was used, VK_KHR_dedicated_allocation extension is used internally to query driver whether it requires or prefers the new buffer to have dedicated allocation. If yes, and if dedicated allocation is possible (<a class="el" href="struct_vma_allocation_create_info.html#a6272c0555cfd1fe28bff1afeb6190150" title="Pool that this allocation should be created in.">VmaAllocationCreateInfo::pool</a> is null and VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT is not used), it creates dedicated allocation for this buffer, just like when using VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT. </p>
+
+</div>
+</div>
+<a id="a02a94f25679275851a53e82eacbcfc73"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a02a94f25679275851a53e82eacbcfc73">&#9670;&nbsp;</a></span>vmaCreateImage()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkResult vmaCreateImage </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const VkImageCreateInfo *&#160;</td>
+          <td class="paramname"><em>pImageCreateInfo</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> *&#160;</td>
+          <td class="paramname"><em>pAllocationCreateInfo</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">VkImage *&#160;</td>
+          <td class="paramname"><em>pImage</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocation.html">VmaAllocation</a> *&#160;</td>
+          <td class="paramname"><em>pAllocation</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocation_info.html">VmaAllocationInfo</a> *&#160;</td>
+          <td class="paramname"><em>pAllocationInfo</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Function similar to <a class="el" href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer()</a>. </p>
+
+</div>
+</div>
+<a id="ae5c9657d9e94756269145b01c05d16f1"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ae5c9657d9e94756269145b01c05d16f1">&#9670;&nbsp;</a></span>vmaCreateLostAllocation()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void vmaCreateLostAllocation </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocation.html">VmaAllocation</a> *&#160;</td>
+          <td class="paramname"><em>pAllocation</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Creates new allocation that is in lost state from the beginning. </p>
+<p>It can be useful if you need a dummy, non-null allocation.</p>
+<p>You still need to destroy created object using <a class="el" href="vk__mem__alloc_8h.html#a11f0fbc034fa81a4efedd73d61ce7568" title="Frees memory previously allocated using vmaAllocateMemory(), vmaAllocateMemoryForBuffer(),...">vmaFreeMemory()</a>.</p>
+<p>Returned allocation is not tied to any specific memory pool or memory type and not bound to any image or buffer. It has size = 0. It cannot be turned into a real, non-empty allocation. </p>
+
+</div>
+</div>
+<a id="a5c8770ded7c59c8caac6de0c2cb00b50"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a5c8770ded7c59c8caac6de0c2cb00b50">&#9670;&nbsp;</a></span>vmaCreatePool()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkResult vmaCreatePool </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const <a class="el" href="struct_vma_pool_create_info.html">VmaPoolCreateInfo</a> *&#160;</td>
+          <td class="paramname"><em>pCreateInfo</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_pool.html">VmaPool</a> *&#160;</td>
+          <td class="paramname"><em>pPool</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Allocates Vulkan device memory and creates <a class="el" href="struct_vma_pool.html" title="Represents custom memory pool.">VmaPool</a> object. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramdir"></td><td class="paramname">allocator</td><td>Allocator object. </td></tr>
+    <tr><td class="paramdir"></td><td class="paramname">pCreateInfo</td><td>Parameters of pool to create. </td></tr>
+    <tr><td class="paramdir">[out]</td><td class="paramname">pPool</td><td>Handle to created pool. </td></tr>
+  </table>
+  </dd>
+</dl>
+
+</div>
+</div>
+<a id="a6aced90fcc7b39882b6654a740a0b9bb"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a6aced90fcc7b39882b6654a740a0b9bb">&#9670;&nbsp;</a></span>vmaDefragment()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkResult vmaDefragment </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocation.html">VmaAllocation</a> *&#160;</td>
+          <td class="paramname"><em>pAllocations</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>allocationCount</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">VkBool32 *&#160;</td>
+          <td class="paramname"><em>pAllocationsChanged</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const <a class="el" href="struct_vma_defragmentation_info.html">VmaDefragmentationInfo</a> *&#160;</td>
+          <td class="paramname"><em>pDefragmentationInfo</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_defragmentation_stats.html">VmaDefragmentationStats</a> *&#160;</td>
+          <td class="paramname"><em>pDefragmentationStats</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Deprecated. Compacts memory by moving allocations. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramdir"></td><td class="paramname">pAllocations</td><td>Array of allocations that can be moved during this compation. </td></tr>
+    <tr><td class="paramdir"></td><td class="paramname">allocationCount</td><td>Number of elements in pAllocations and pAllocationsChanged arrays. </td></tr>
+    <tr><td class="paramdir">[out]</td><td class="paramname">pAllocationsChanged</td><td>Array of boolean values that will indicate whether matching allocation in pAllocations array has been moved. This parameter is optional. Pass null if you don't need this information. </td></tr>
+    <tr><td class="paramdir"></td><td class="paramname">pDefragmentationInfo</td><td>Configuration parameters. Optional - pass null to use default values. </td></tr>
+    <tr><td class="paramdir">[out]</td><td class="paramname">pDefragmentationStats</td><td>Statistics returned by the function. Optional - pass null if you don't need this information. </td></tr>
+  </table>
+  </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd><code>VK_SUCCESS</code> if completed, negative error code in case of error.</dd></dl>
+<dl class="deprecated"><dt><b><a class="el" href="deprecated.html#_deprecated000003">Deprecated:</a></b></dt><dd>This is a part of the old interface. It is recommended to use structure <a class="el" href="struct_vma_defragmentation_info2.html" title="Parameters for defragmentation.">VmaDefragmentationInfo2</a> and function <a class="el" href="vk__mem__alloc_8h.html#a36ba776fd7fd5cb1e9359fdc0d8e6e8a" title="Begins defragmentation process.">vmaDefragmentationBegin()</a> instead.</dd></dl>
+<p>This function works by moving allocations to different places (different <code>VkDeviceMemory</code> objects and/or different offsets) in order to optimize memory usage. Only allocations that are in <code>pAllocations</code> array can be moved. All other allocations are considered nonmovable in this call. Basic rules:</p>
+<ul>
+<li>Only allocations made in memory types that have <code>VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT</code> and <code>VK_MEMORY_PROPERTY_HOST_COHERENT_BIT</code> flags can be compacted. You may pass other allocations but it makes no sense - these will never be moved.</li>
+<li>Custom pools created with <a class="el" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a13c8a444197c67866be9cb05599fc726" title="Enables alternative, linear allocation algorithm in this pool.">VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT</a> or <a class="el" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a97a0dc38e5161b780594d998d313d35e" title="Enables alternative, buddy allocation algorithm in this pool.">VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT</a> flag are not defragmented. Allocations passed to this function that come from such pools are ignored.</li>
+<li>Allocations created with <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a3fc311d855c2ff53f1090ef5c722b38f" title="Set this flag if the allocation should have its own memory block.">VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT</a> or created as dedicated allocations for any other reason are also ignored.</li>
+<li>Both allocations made with or without <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a11da372cc3a82931c5e5d6146cd9dd1f" title="Set this flag to use a memory that will be persistently mapped and retrieve pointer to it.">VMA_ALLOCATION_CREATE_MAPPED_BIT</a> flag can be compacted. If not persistently mapped, memory will be mapped temporarily inside this function if needed.</li>
+<li>You must not pass same <a class="el" href="struct_vma_allocation.html" title="Represents single memory allocation.">VmaAllocation</a> object multiple times in <code>pAllocations</code> array.</li>
+</ul>
+<p>The function also frees empty <code>VkDeviceMemory</code> blocks.</p>
+<p>Warning: This function may be time-consuming, so you shouldn't call it too often (like after every resource creation/destruction). You can call it on special occasions (like when reloading a game level or when you just destroyed a lot of objects). Calling it every frame may be OK, but you should measure that on your platform.</p>
+<p>For more information, see <a class="el" href="defragmentation.html">Defragmentation</a> chapter. </p>
+
+</div>
+</div>
+<a id="a36ba776fd7fd5cb1e9359fdc0d8e6e8a"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a36ba776fd7fd5cb1e9359fdc0d8e6e8a">&#9670;&nbsp;</a></span>vmaDefragmentationBegin()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkResult vmaDefragmentationBegin </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const <a class="el" href="struct_vma_defragmentation_info2.html">VmaDefragmentationInfo2</a> *&#160;</td>
+          <td class="paramname"><em>pInfo</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_defragmentation_stats.html">VmaDefragmentationStats</a> *&#160;</td>
+          <td class="paramname"><em>pStats</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_defragmentation_context.html">VmaDefragmentationContext</a> *&#160;</td>
+          <td class="paramname"><em>pContext</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Begins defragmentation process. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramdir"></td><td class="paramname">allocator</td><td>Allocator object. </td></tr>
+    <tr><td class="paramdir"></td><td class="paramname">pInfo</td><td>Structure filled with parameters of defragmentation. </td></tr>
+    <tr><td class="paramdir">[out]</td><td class="paramname">pStats</td><td>Optional. Statistics of defragmentation. You can pass null if you are not interested in this information. </td></tr>
+    <tr><td class="paramdir">[out]</td><td class="paramname">pContext</td><td>Context object that must be passed to <a class="el" href="vk__mem__alloc_8h.html#a8774e20e91e245aae959ba63efa15dd2" title="Ends defragmentation process.">vmaDefragmentationEnd()</a> to finish defragmentation. </td></tr>
+  </table>
+  </dd>
+</dl>
+<dl class="section return"><dt>Returns</dt><dd><code>VK_SUCCESS</code> and <code>*pContext == null</code> if defragmentation finished within this function call. <code>VK_NOT_READY</code> and <code>*pContext != null</code> if defragmentation has been started and you need to call <a class="el" href="vk__mem__alloc_8h.html#a8774e20e91e245aae959ba63efa15dd2" title="Ends defragmentation process.">vmaDefragmentationEnd()</a> to finish it. Negative value in case of error.</dd></dl>
+<p>Use this function instead of old, deprecated <a class="el" href="vk__mem__alloc_8h.html#a6aced90fcc7b39882b6654a740a0b9bb" title="Deprecated. Compacts memory by moving allocations.">vmaDefragment()</a>.</p>
+<p>Warning! Between the call to <a class="el" href="vk__mem__alloc_8h.html#a36ba776fd7fd5cb1e9359fdc0d8e6e8a" title="Begins defragmentation process.">vmaDefragmentationBegin()</a> and <a class="el" href="vk__mem__alloc_8h.html#a8774e20e91e245aae959ba63efa15dd2" title="Ends defragmentation process.">vmaDefragmentationEnd()</a>:</p>
+<ul>
+<li>You should not use any of allocations passed as <code>pInfo-&gt;pAllocations</code> or any allocations that belong to pools passed as <code>pInfo-&gt;pPools</code>, including calling <a class="el" href="vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b" title="Returns current information about specified allocation and atomically marks it as used in current fra...">vmaGetAllocationInfo()</a>, <a class="el" href="vk__mem__alloc_8h.html#a43d8ba9673c846f049089a5029d5c73a" title="Returns VK_TRUE if allocation is not lost and atomically marks it as used in current frame.">vmaTouchAllocation()</a>, or access their data.</li>
+<li>Some mutexes protecting internal data structures may be locked, so trying to make or free any allocations, bind buffers or images, map memory, or launch another simultaneous defragmentation in between may cause stall (when done on another thread) or deadlock (when done on the same thread), unless you are 100% sure that defragmented allocations are in different pools.</li>
+<li>Information returned via <code>pStats</code> and <code>pInfo-&gt;pAllocationsChanged</code> are undefined. They become valid after call to <a class="el" href="vk__mem__alloc_8h.html#a8774e20e91e245aae959ba63efa15dd2" title="Ends defragmentation process.">vmaDefragmentationEnd()</a>.</li>
+<li>If <code>pInfo-&gt;commandBuffer</code> is not null, you must submit that command buffer and make sure it finished execution before calling <a class="el" href="vk__mem__alloc_8h.html#a8774e20e91e245aae959ba63efa15dd2" title="Ends defragmentation process.">vmaDefragmentationEnd()</a>.</li>
+</ul>
+<p>For more information and important limitations regarding defragmentation, see documentation chapter: <a class="el" href="defragmentation.html">Defragmentation</a>. </p>
+
+</div>
+</div>
+<a id="a8774e20e91e245aae959ba63efa15dd2"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a8774e20e91e245aae959ba63efa15dd2">&#9670;&nbsp;</a></span>vmaDefragmentationEnd()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkResult vmaDefragmentationEnd </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_defragmentation_context.html">VmaDefragmentationContext</a>&#160;</td>
+          <td class="paramname"><em>context</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Ends defragmentation process. </p>
+<p>Use this function to finish defragmentation started by <a class="el" href="vk__mem__alloc_8h.html#a36ba776fd7fd5cb1e9359fdc0d8e6e8a" title="Begins defragmentation process.">vmaDefragmentationBegin()</a>. It is safe to pass <code>context == null</code>. The function then does nothing. </p>
+
+</div>
+</div>
+<a id="aa8d164061c88f22fb1fd3c8f3534bc1d"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#aa8d164061c88f22fb1fd3c8f3534bc1d">&#9670;&nbsp;</a></span>vmaDestroyAllocator()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void vmaDestroyAllocator </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em></td><td>)</td>
+          <td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Destroys allocator object. </p>
+
+</div>
+</div>
+<a id="a0d9f4e4ba5bf9aab1f1c746387753d77"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a0d9f4e4ba5bf9aab1f1c746387753d77">&#9670;&nbsp;</a></span>vmaDestroyBuffer()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void vmaDestroyBuffer </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">VkBuffer&#160;</td>
+          <td class="paramname"><em>buffer</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocation.html">VmaAllocation</a>&#160;</td>
+          <td class="paramname"><em>allocation</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Destroys Vulkan buffer and frees allocated memory. </p>
+<p>This is just a convenience function equivalent to:</p>
+<div class="fragment"><div class="line">vkDestroyBuffer(device, buffer, allocationCallbacks);</div>
+<div class="line"><a class="code" href="vk__mem__alloc_8h.html#a11f0fbc034fa81a4efedd73d61ce7568">vmaFreeMemory</a>(allocator, allocation);</div>
+</div><!-- fragment --><p>It it safe to pass null as buffer and/or allocation. </p>
+
+</div>
+</div>
+<a id="ae50d2cb3b4a3bfd4dd40987234e50e7e"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ae50d2cb3b4a3bfd4dd40987234e50e7e">&#9670;&nbsp;</a></span>vmaDestroyImage()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void vmaDestroyImage </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">VkImage&#160;</td>
+          <td class="paramname"><em>image</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocation.html">VmaAllocation</a>&#160;</td>
+          <td class="paramname"><em>allocation</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Destroys Vulkan image and frees allocated memory. </p>
+<p>This is just a convenience function equivalent to:</p>
+<div class="fragment"><div class="line">vkDestroyImage(device, image, allocationCallbacks);</div>
+<div class="line"><a class="code" href="vk__mem__alloc_8h.html#a11f0fbc034fa81a4efedd73d61ce7568">vmaFreeMemory</a>(allocator, allocation);</div>
+</div><!-- fragment --><p>It it safe to pass null as image and/or allocation. </p>
+
+</div>
+</div>
+<a id="a5485779c8f1948238fc4e92232fa65e1"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a5485779c8f1948238fc4e92232fa65e1">&#9670;&nbsp;</a></span>vmaDestroyPool()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void vmaDestroyPool </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_pool.html">VmaPool</a>&#160;</td>
+          <td class="paramname"><em>pool</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Destroys <a class="el" href="struct_vma_pool.html" title="Represents custom memory pool.">VmaPool</a> object and frees Vulkan device memory. </p>
+
+</div>
+</div>
+<a id="a1b9ffa538bed905af55c747cc48963bd"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a1b9ffa538bed905af55c747cc48963bd">&#9670;&nbsp;</a></span>vmaEndDefragmentationPass()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkResult vmaEndDefragmentationPass </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_defragmentation_context.html">VmaDefragmentationContext</a>&#160;</td>
+          <td class="paramname"><em>context</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="aef15a94b58fbcb0fe706d5720e84a74a"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#aef15a94b58fbcb0fe706d5720e84a74a">&#9670;&nbsp;</a></span>vmaFindMemoryTypeIndex()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkResult vmaFindMemoryTypeIndex </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">uint32_t&#160;</td>
+          <td class="paramname"><em>memoryTypeBits</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> *&#160;</td>
+          <td class="paramname"><em>pAllocationCreateInfo</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">uint32_t *&#160;</td>
+          <td class="paramname"><em>pMemoryTypeIndex</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Helps to find memoryTypeIndex, given memoryTypeBits and <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>. </p>
+<p>This algorithm tries to find a memory type that:</p>
+<ul>
+<li>Is allowed by memoryTypeBits.</li>
+<li>Contains all the flags from pAllocationCreateInfo-&gt;requiredFlags.</li>
+<li>Matches intended usage.</li>
+<li>Has as many flags from pAllocationCreateInfo-&gt;preferredFlags as possible.</li>
+</ul>
+<dl class="section return"><dt>Returns</dt><dd>Returns VK_ERROR_FEATURE_NOT_PRESENT if not found. Receiving such result from this function or any other allocating function probably means that your device doesn't support any memory type with requested features for the specific type of resource you want to use it for. Please check parameters of your resource, like image layout (OPTIMAL versus LINEAR) or mip level count. </dd></dl>
+
+</div>
+</div>
+<a id="ae790ab9ffaf7667fb8f62523e6897888"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ae790ab9ffaf7667fb8f62523e6897888">&#9670;&nbsp;</a></span>vmaFindMemoryTypeIndexForBufferInfo()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkResult vmaFindMemoryTypeIndexForBufferInfo </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const VkBufferCreateInfo *&#160;</td>
+          <td class="paramname"><em>pBufferCreateInfo</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> *&#160;</td>
+          <td class="paramname"><em>pAllocationCreateInfo</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">uint32_t *&#160;</td>
+          <td class="paramname"><em>pMemoryTypeIndex</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Helps to find memoryTypeIndex, given VkBufferCreateInfo and <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>. </p>
+<p>It can be useful e.g. to determine value to be used as <a class="el" href="struct_vma_pool_create_info.html#a596fa76b685d3f1f688f84a709a5b319" title="Vulkan memory type index to allocate this pool from.">VmaPoolCreateInfo::memoryTypeIndex</a>. It internally creates a temporary, dummy buffer that never has memory bound. It is just a convenience function, equivalent to calling:</p>
+<ul>
+<li><code>vkCreateBuffer</code></li>
+<li><code>vkGetBufferMemoryRequirements</code></li>
+<li><code>vmaFindMemoryTypeIndex</code></li>
+<li><code>vkDestroyBuffer</code> </li>
+</ul>
+
+</div>
+</div>
+<a id="a088da83d8eaf3ce9056d9ea0b981d472"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a088da83d8eaf3ce9056d9ea0b981d472">&#9670;&nbsp;</a></span>vmaFindMemoryTypeIndexForImageInfo()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkResult vmaFindMemoryTypeIndexForImageInfo </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const VkImageCreateInfo *&#160;</td>
+          <td class="paramname"><em>pImageCreateInfo</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> *&#160;</td>
+          <td class="paramname"><em>pAllocationCreateInfo</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">uint32_t *&#160;</td>
+          <td class="paramname"><em>pMemoryTypeIndex</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Helps to find memoryTypeIndex, given VkImageCreateInfo and <a class="el" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>. </p>
+<p>It can be useful e.g. to determine value to be used as <a class="el" href="struct_vma_pool_create_info.html#a596fa76b685d3f1f688f84a709a5b319" title="Vulkan memory type index to allocate this pool from.">VmaPoolCreateInfo::memoryTypeIndex</a>. It internally creates a temporary, dummy image that never has memory bound. It is just a convenience function, equivalent to calling:</p>
+<ul>
+<li><code>vkCreateImage</code></li>
+<li><code>vkGetImageMemoryRequirements</code></li>
+<li><code>vmaFindMemoryTypeIndex</code></li>
+<li><code>vkDestroyImage</code> </li>
+</ul>
+
+</div>
+</div>
+<a id="abc34ee6f021f459aff885f3758c435de"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#abc34ee6f021f459aff885f3758c435de">&#9670;&nbsp;</a></span>vmaFlushAllocation()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void vmaFlushAllocation </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocation.html">VmaAllocation</a>&#160;</td>
+          <td class="paramname"><em>allocation</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">VkDeviceSize&#160;</td>
+          <td class="paramname"><em>offset</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">VkDeviceSize&#160;</td>
+          <td class="paramname"><em>size</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Flushes memory of given allocation. </p>
+<p>Calls <code>vkFlushMappedMemoryRanges()</code> for memory associated with given range of given allocation. It needs to be called after writing to a mapped memory for memory types that are not <code>HOST_COHERENT</code>. Unmap operation doesn't do that automatically.</p>
+<ul>
+<li><code>offset</code> must be relative to the beginning of allocation.</li>
+<li><code>size</code> can be <code>VK_WHOLE_SIZE</code>. It means all memory from <code>offset</code> the the end of given allocation.</li>
+<li><code>offset</code> and <code>size</code> don't have to be aligned. They are internally rounded down/up to multiply of <code>nonCoherentAtomSize</code>.</li>
+<li>If <code>size</code> is 0, this call is ignored.</li>
+<li>If memory type that the <code>allocation</code> belongs to is not <code>HOST_VISIBLE</code> or it is <code>HOST_COHERENT</code>, this call is ignored.</li>
+</ul>
+<p>Warning! <code>offset</code> and <code>size</code> are relative to the contents of given <code>allocation</code>. If you mean whole allocation, you can pass 0 and <code>VK_WHOLE_SIZE</code>, respectively. Do not pass allocation's offset as <code>offset</code>!!! </p>
+
+</div>
+</div>
+<a id="a11f0fbc034fa81a4efedd73d61ce7568"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a11f0fbc034fa81a4efedd73d61ce7568">&#9670;&nbsp;</a></span>vmaFreeMemory()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void vmaFreeMemory </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocation.html">VmaAllocation</a>&#160;</td>
+          <td class="paramname"><em>allocation</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Frees memory previously allocated using <a class="el" href="vk__mem__alloc_8h.html#abf28077dbf82d0908b8acbe8ee8dd9b8" title="General purpose memory allocation.">vmaAllocateMemory()</a>, <a class="el" href="vk__mem__alloc_8h.html#a7fdf64415b6c3d83c454f28d2c53df7b">vmaAllocateMemoryForBuffer()</a>, or <a class="el" href="vk__mem__alloc_8h.html#a0faa3f9e5fb233d29d1e00390650febb" title="Function similar to vmaAllocateMemoryForBuffer().">vmaAllocateMemoryForImage()</a>. </p>
+<p>Passing <code>VK_NULL_HANDLE</code> as <code>allocation</code> is valid. Such function call is just skipped. </p>
+
+</div>
+</div>
+<a id="ab9e709de044c5d8476bea77a4e755840"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ab9e709de044c5d8476bea77a4e755840">&#9670;&nbsp;</a></span>vmaFreeMemoryPages()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void vmaFreeMemoryPages </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t&#160;</td>
+          <td class="paramname"><em>allocationCount</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocation.html">VmaAllocation</a> *&#160;</td>
+          <td class="paramname"><em>pAllocations</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Frees memory and destroys multiple allocations. </p>
+<p>Word "pages" is just a suggestion to use this function to free pieces of memory used for sparse binding. It is just a general purpose function to free memory and destroy allocations made using e.g. <a class="el" href="vk__mem__alloc_8h.html#abf28077dbf82d0908b8acbe8ee8dd9b8" title="General purpose memory allocation.">vmaAllocateMemory()</a>, <a class="el" href="vk__mem__alloc_8h.html#ad37e82e492b3de38fc3f4cffd9ad0ae1" title="General purpose memory allocation for multiple allocation objects at once.">vmaAllocateMemoryPages()</a> and other functions. It may be internally optimized to be more efficient than calling <a class="el" href="vk__mem__alloc_8h.html#a11f0fbc034fa81a4efedd73d61ce7568" title="Frees memory previously allocated using vmaAllocateMemory(), vmaAllocateMemoryForBuffer(),...">vmaFreeMemory()</a> <code>allocationCount</code> times.</p>
+<p>Allocations in <code>pAllocations</code> array can come from any memory pools and types. Passing <code>VK_NULL_HANDLE</code> as elements of <code>pAllocations</code> array is valid. Such entries are just skipped. </p>
+
+</div>
+</div>
+<a id="a3104eb30d8122c84dd8541063f145288"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a3104eb30d8122c84dd8541063f145288">&#9670;&nbsp;</a></span>vmaFreeStatsString()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void vmaFreeStatsString </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">char *&#160;</td>
+          <td class="paramname"><em>pStatsString</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+</div>
+</div>
+<a id="a86dd08aba8633bfa4ad0df2e76481d8b"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a86dd08aba8633bfa4ad0df2e76481d8b">&#9670;&nbsp;</a></span>vmaGetAllocationInfo()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void vmaGetAllocationInfo </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocation.html">VmaAllocation</a>&#160;</td>
+          <td class="paramname"><em>allocation</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocation_info.html">VmaAllocationInfo</a> *&#160;</td>
+          <td class="paramname"><em>pAllocationInfo</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Returns current information about specified allocation and atomically marks it as used in current frame. </p>
+<p>Current paramters of given allocation are returned in <code>pAllocationInfo</code>.</p>
+<p>This function also atomically "touches" allocation - marks it as used in current frame, just like <a class="el" href="vk__mem__alloc_8h.html#a43d8ba9673c846f049089a5029d5c73a" title="Returns VK_TRUE if allocation is not lost and atomically marks it as used in current frame.">vmaTouchAllocation()</a>. If the allocation is in lost state, <code>pAllocationInfo-&gt;deviceMemory == VK_NULL_HANDLE</code>.</p>
+<p>Although this function uses atomics and doesn't lock any mutex, so it should be quite efficient, you can avoid calling it too often.</p>
+<ul>
+<li>You can retrieve same <a class="el" href="struct_vma_allocation_info.html" title="Parameters of VmaAllocation objects, that can be retrieved using function vmaGetAllocationInfo().">VmaAllocationInfo</a> structure while creating your resource, from function <a class="el" href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer()</a>, <a class="el" href="vk__mem__alloc_8h.html#a02a94f25679275851a53e82eacbcfc73" title="Function similar to vmaCreateBuffer().">vmaCreateImage()</a>. You can remember it if you are sure parameters don't change (e.g. due to defragmentation or allocation becoming lost).</li>
+<li>If you just want to check if allocation is not lost, <a class="el" href="vk__mem__alloc_8h.html#a43d8ba9673c846f049089a5029d5c73a" title="Returns VK_TRUE if allocation is not lost and atomically marks it as used in current frame.">vmaTouchAllocation()</a> will work faster. </li>
+</ul>
+
+</div>
+</div>
+<a id="afa02231a791b37255720d566a52683e7"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#afa02231a791b37255720d566a52683e7">&#9670;&nbsp;</a></span>vmaGetAllocatorInfo()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void vmaGetAllocatorInfo </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator_info.html">VmaAllocatorInfo</a> *&#160;</td>
+          <td class="paramname"><em>pAllocatorInfo</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Returns information about existing <a class="el" href="struct_vma_allocator.html" title="Represents main object of this library initialized.">VmaAllocator</a> object - handle to Vulkan device etc. </p>
+<p>It might be useful if you want to keep just the <a class="el" href="struct_vma_allocator.html" title="Represents main object of this library initialized.">VmaAllocator</a> handle and fetch other required handles to <code>VkPhysicalDevice</code>, <code>VkDevice</code> etc. every time using this function. </p>
+
+</div>
+</div>
+<a id="aec0ed24ebea2d0099eed5f801daaefba"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#aec0ed24ebea2d0099eed5f801daaefba">&#9670;&nbsp;</a></span>vmaGetBudget()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void vmaGetBudget </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_budget.html">VmaBudget</a> *&#160;</td>
+          <td class="paramname"><em>pBudget</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Retrieves information about current memory budget for all memory heaps. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramdir">[out]</td><td class="paramname">pBudget</td><td>Must point to array with number of elements at least equal to number of memory heaps in physical device used.</td></tr>
+  </table>
+  </dd>
+</dl>
+<p>This function is called "get" not "calculate" because it is very fast, suitable to be called every frame or every allocation. For more detailed statistics use <a class="el" href="vk__mem__alloc_8h.html#a333b61c1788cb23559177531e6a93ca3" title="Retrieves statistics from current state of the Allocator.">vmaCalculateStats()</a>.</p>
+<p>Note that when using allocator from multiple threads, returned information may immediately become outdated. </p>
+
+</div>
+</div>
+<a id="ab88db292a17974f911182543fda52d19"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ab88db292a17974f911182543fda52d19">&#9670;&nbsp;</a></span>vmaGetMemoryProperties()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void vmaGetMemoryProperties </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const VkPhysicalDeviceMemoryProperties **&#160;</td>
+          <td class="paramname"><em>ppPhysicalDeviceMemoryProperties</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+<p>PhysicalDeviceMemoryProperties are fetched from physicalDevice by the allocator. You can access it here, without fetching it again on your own. </p>
+
+</div>
+</div>
+<a id="a8701444752eb5de4464adb5a2b514bca"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a8701444752eb5de4464adb5a2b514bca">&#9670;&nbsp;</a></span>vmaGetMemoryTypeProperties()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void vmaGetMemoryTypeProperties </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">uint32_t&#160;</td>
+          <td class="paramname"><em>memoryTypeIndex</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">VkMemoryPropertyFlags *&#160;</td>
+          <td class="paramname"><em>pFlags</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Given Memory Type Index, returns Property Flags of this memory type. </p>
+<p>This is just a convenience function. Same information can be obtained using <a class="el" href="vk__mem__alloc_8h.html#ab88db292a17974f911182543fda52d19">vmaGetMemoryProperties()</a>. </p>
+
+</div>
+</div>
+<a id="aecabf7b6e91ea87d0316fa0a9e014fe0"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#aecabf7b6e91ea87d0316fa0a9e014fe0">&#9670;&nbsp;</a></span>vmaGetPhysicalDeviceProperties()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void vmaGetPhysicalDeviceProperties </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const VkPhysicalDeviceProperties **&#160;</td>
+          <td class="paramname"><em>ppPhysicalDeviceProperties</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+<p>PhysicalDeviceProperties are fetched from physicalDevice by the allocator. You can access it here, without fetching it again on your own. </p>
+
+</div>
+</div>
+<a id="af09b4e4eafdbee812e8d73ddf960f030"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#af09b4e4eafdbee812e8d73ddf960f030">&#9670;&nbsp;</a></span>vmaGetPoolName()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void vmaGetPoolName </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_pool.html">VmaPool</a>&#160;</td>
+          <td class="paramname"><em>pool</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const char **&#160;</td>
+          <td class="paramname"><em>ppName</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Retrieves name of a custom pool. </p>
+<p>After the call <code>ppName</code> is either null or points to an internally-owned null-terminated string containing name of the pool that was previously set. The pointer becomes invalid when the pool is destroyed or its name is changed using <a class="el" href="vk__mem__alloc_8h.html#adbae3a0b4ab078024462fc85c37f3b58" title="Sets name of a custom pool.">vmaSetPoolName()</a>. </p>
+
+</div>
+</div>
+<a id="ae8bf76997b234ef68aad922616df4153"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ae8bf76997b234ef68aad922616df4153">&#9670;&nbsp;</a></span>vmaGetPoolStats()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void vmaGetPoolStats </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_pool.html">VmaPool</a>&#160;</td>
+          <td class="paramname"><em>pool</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_pool_stats.html">VmaPoolStats</a> *&#160;</td>
+          <td class="paramname"><em>pPoolStats</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Retrieves statistics of existing <a class="el" href="struct_vma_pool.html" title="Represents custom memory pool.">VmaPool</a> object. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramdir"></td><td class="paramname">allocator</td><td>Allocator object. </td></tr>
+    <tr><td class="paramdir"></td><td class="paramname">pool</td><td>Pool object. </td></tr>
+    <tr><td class="paramdir">[out]</td><td class="paramname">pPoolStats</td><td>Statistics of specified pool. </td></tr>
+  </table>
+  </dd>
+</dl>
+
+</div>
+</div>
+<a id="a0d0eb0c1102268fa9a476d12ecbe4006"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a0d0eb0c1102268fa9a476d12ecbe4006">&#9670;&nbsp;</a></span>vmaInvalidateAllocation()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void vmaInvalidateAllocation </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocation.html">VmaAllocation</a>&#160;</td>
+          <td class="paramname"><em>allocation</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">VkDeviceSize&#160;</td>
+          <td class="paramname"><em>offset</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">VkDeviceSize&#160;</td>
+          <td class="paramname"><em>size</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Invalidates memory of given allocation. </p>
+<p>Calls <code>vkInvalidateMappedMemoryRanges()</code> for memory associated with given range of given allocation. It needs to be called before reading from a mapped memory for memory types that are not <code>HOST_COHERENT</code>. Map operation doesn't do that automatically.</p>
+<ul>
+<li><code>offset</code> must be relative to the beginning of allocation.</li>
+<li><code>size</code> can be <code>VK_WHOLE_SIZE</code>. It means all memory from <code>offset</code> the the end of given allocation.</li>
+<li><code>offset</code> and <code>size</code> don't have to be aligned. They are internally rounded down/up to multiply of <code>nonCoherentAtomSize</code>.</li>
+<li>If <code>size</code> is 0, this call is ignored.</li>
+<li>If memory type that the <code>allocation</code> belongs to is not <code>HOST_VISIBLE</code> or it is <code>HOST_COHERENT</code>, this call is ignored.</li>
+</ul>
+<p>Warning! <code>offset</code> and <code>size</code> are relative to the contents of given <code>allocation</code>. If you mean whole allocation, you can pass 0 and <code>VK_WHOLE_SIZE</code>, respectively. Do not pass allocation's offset as <code>offset</code>!!! </p>
+
+</div>
+</div>
+<a id="a736bd6cbda886f36c891727e73bd4024"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a736bd6cbda886f36c891727e73bd4024">&#9670;&nbsp;</a></span>vmaMakePoolAllocationsLost()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void vmaMakePoolAllocationsLost </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_pool.html">VmaPool</a>&#160;</td>
+          <td class="paramname"><em>pool</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">size_t *&#160;</td>
+          <td class="paramname"><em>pLostAllocationCount</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Marks all allocations in given pool as lost if they are not used in current frame or <a class="el" href="struct_vma_pool_create_info.html#a9437e43ffbb644dbbf7fc4e50cfad6aa" title="Maximum number of additional frames that are in use at the same time as current frame.">VmaPoolCreateInfo::frameInUseCount</a> back from now. </p>
+<dl class="params"><dt>Parameters</dt><dd>
+  <table class="params">
+    <tr><td class="paramdir"></td><td class="paramname">allocator</td><td>Allocator object. </td></tr>
+    <tr><td class="paramdir"></td><td class="paramname">pool</td><td>Pool. </td></tr>
+    <tr><td class="paramdir">[out]</td><td class="paramname">pLostAllocationCount</td><td>Number of allocations marked as lost. Optional - pass null if you don't need this information. </td></tr>
+  </table>
+  </dd>
+</dl>
+
+</div>
+</div>
+<a id="ad5bd1243512d099706de88168992f069"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ad5bd1243512d099706de88168992f069">&#9670;&nbsp;</a></span>vmaMapMemory()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkResult vmaMapMemory </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocation.html">VmaAllocation</a>&#160;</td>
+          <td class="paramname"><em>allocation</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">void **&#160;</td>
+          <td class="paramname"><em>ppData</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Maps memory represented by given allocation and returns pointer to it. </p>
+<p>Maps memory represented by given allocation to make it accessible to CPU code. When succeeded, <code>*ppData</code> contains pointer to first byte of this memory. If the allocation is part of bigger <code>VkDeviceMemory</code> block, the pointer is correctly offseted to the beginning of region assigned to this particular allocation.</p>
+<p>Mapping is internally reference-counted and synchronized, so despite raw Vulkan function <code>vkMapMemory()</code> cannot be used to map same block of <code>VkDeviceMemory</code> multiple times simultaneously, it is safe to call this function on allocations assigned to the same memory block. Actual Vulkan memory will be mapped on first mapping and unmapped on last unmapping.</p>
+<p>If the function succeeded, you must call <a class="el" href="vk__mem__alloc_8h.html#a9bc268595cb33f6ec4d519cfce81ff45" title="Unmaps memory represented by given allocation, mapped previously using vmaMapMemory().">vmaUnmapMemory()</a> to unmap the allocation when mapping is no longer needed or before freeing the allocation, at the latest.</p>
+<p>It also safe to call this function multiple times on the same allocation. You must call <a class="el" href="vk__mem__alloc_8h.html#a9bc268595cb33f6ec4d519cfce81ff45" title="Unmaps memory represented by given allocation, mapped previously using vmaMapMemory().">vmaUnmapMemory()</a> same number of times as you called <a class="el" href="vk__mem__alloc_8h.html#ad5bd1243512d099706de88168992f069" title="Maps memory represented by given allocation and returns pointer to it.">vmaMapMemory()</a>.</p>
+<p>It is also safe to call this function on allocation created with <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a11da372cc3a82931c5e5d6146cd9dd1f" title="Set this flag to use a memory that will be persistently mapped and retrieve pointer to it.">VMA_ALLOCATION_CREATE_MAPPED_BIT</a> flag. Its memory stays mapped all the time. You must still call <a class="el" href="vk__mem__alloc_8h.html#a9bc268595cb33f6ec4d519cfce81ff45" title="Unmaps memory represented by given allocation, mapped previously using vmaMapMemory().">vmaUnmapMemory()</a> same number of times as you called <a class="el" href="vk__mem__alloc_8h.html#ad5bd1243512d099706de88168992f069" title="Maps memory represented by given allocation and returns pointer to it.">vmaMapMemory()</a>. You must not call <a class="el" href="vk__mem__alloc_8h.html#a9bc268595cb33f6ec4d519cfce81ff45" title="Unmaps memory represented by given allocation, mapped previously using vmaMapMemory().">vmaUnmapMemory()</a> additional time to free the "0-th" mapping made automatically due to <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a11da372cc3a82931c5e5d6146cd9dd1f" title="Set this flag to use a memory that will be persistently mapped and retrieve pointer to it.">VMA_ALLOCATION_CREATE_MAPPED_BIT</a> flag.</p>
+<p>This function fails when used on allocation made in memory type that is not <code>HOST_VISIBLE</code>.</p>
+<p>This function always fails when called for allocation that was created with <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a5f436af6c8fe8540573a6d22627a6fd2">VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT</a> flag. Such allocations cannot be mapped.</p>
+<p>This function doesn't automatically flush or invalidate caches. If the allocation is made from a memory types that is not <code>HOST_COHERENT</code>, you also need to use <a class="el" href="vk__mem__alloc_8h.html#a0d0eb0c1102268fa9a476d12ecbe4006" title="Invalidates memory of given allocation.">vmaInvalidateAllocation()</a> / <a class="el" href="vk__mem__alloc_8h.html#abc34ee6f021f459aff885f3758c435de" title="Flushes memory of given allocation.">vmaFlushAllocation()</a>, as required by Vulkan specification. </p>
+
+</div>
+</div>
+<a id="a0ff488958ca72b28e545880463cb8696"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a0ff488958ca72b28e545880463cb8696">&#9670;&nbsp;</a></span>vmaResizeAllocation()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkResult vmaResizeAllocation </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocation.html">VmaAllocation</a>&#160;</td>
+          <td class="paramname"><em>allocation</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">VkDeviceSize&#160;</td>
+          <td class="paramname"><em>newSize</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Deprecated. </p>
+<dl class="deprecated"><dt><b><a class="el" href="deprecated.html#_deprecated000001">Deprecated:</a></b></dt><dd>In version 2.2.0 it used to try to change allocation's size without moving or reallocating it. In current version it returns <code>VK_SUCCESS</code> only if <code>newSize</code> equals current allocation's size. Otherwise returns <code>VK_ERROR_OUT_OF_POOL_MEMORY</code>, indicating that allocation's size could not be changed. </dd></dl>
+
+</div>
+</div>
+<a id="af9147d31ffc11d62fc187bde283ed14f"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#af9147d31ffc11d62fc187bde283ed14f">&#9670;&nbsp;</a></span>vmaSetAllocationUserData()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void vmaSetAllocationUserData </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocation.html">VmaAllocation</a>&#160;</td>
+          <td class="paramname"><em>allocation</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">void *&#160;</td>
+          <td class="paramname"><em>pUserData</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Sets pUserData in given allocation to new value. </p>
+<p>If the allocation was created with VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT, pUserData must be either null, or pointer to a null-terminated string. The function makes local copy of the string and sets it as allocation's <code>pUserData</code>. String passed as pUserData doesn't need to be valid for whole lifetime of the allocation - you can free it after this call. String previously pointed by allocation's pUserData is freed from memory.</p>
+<p>If the flag was not used, the value of pointer <code>pUserData</code> is just copied to allocation's <code>pUserData</code>. It is opaque, so you can use it however you want - e.g. as a pointer, ordinal number or some handle to you own data. </p>
+
+</div>
+</div>
+<a id="ade56bf8dc9f5a5eaddf5f119ed525236"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#ade56bf8dc9f5a5eaddf5f119ed525236">&#9670;&nbsp;</a></span>vmaSetCurrentFrameIndex()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void vmaSetCurrentFrameIndex </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">uint32_t&#160;</td>
+          <td class="paramname"><em>frameIndex</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Sets index of the current frame. </p>
+<p>This function must be used if you make allocations with <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a5f436af6c8fe8540573a6d22627a6fd2">VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT</a> and <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a68686d0ce9beb0d4d1b9f2b8b1389a7e">VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT</a> flags to inform the allocator when a new frame begins. Allocations queried using <a class="el" href="vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b" title="Returns current information about specified allocation and atomically marks it as used in current fra...">vmaGetAllocationInfo()</a> cannot become lost in the current frame. </p>
+
+</div>
+</div>
+<a id="adbae3a0b4ab078024462fc85c37f3b58"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#adbae3a0b4ab078024462fc85c37f3b58">&#9670;&nbsp;</a></span>vmaSetPoolName()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void vmaSetPoolName </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_pool.html">VmaPool</a>&#160;</td>
+          <td class="paramname"><em>pool</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype">const char *&#160;</td>
+          <td class="paramname"><em>pName</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Sets name of a custom pool. </p>
+<p><code>pName</code> can be either null or pointer to a null-terminated string with new name for the pool. Function makes internal copy of the string, so it can be changed or freed immediately after this call. </p>
+
+</div>
+</div>
+<a id="a43d8ba9673c846f049089a5029d5c73a"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a43d8ba9673c846f049089a5029d5c73a">&#9670;&nbsp;</a></span>vmaTouchAllocation()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">VkBool32 vmaTouchAllocation </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocation.html">VmaAllocation</a>&#160;</td>
+          <td class="paramname"><em>allocation</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Returns <code>VK_TRUE</code> if allocation is not lost and atomically marks it as used in current frame. </p>
+<p>If the allocation has been created with <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a5f436af6c8fe8540573a6d22627a6fd2">VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT</a> flag, this function returns <code>VK_TRUE</code> if it's not in lost state, so it can still be used. It then also atomically "touches" the allocation - marks it as used in current frame, so that you can be sure it won't become lost in current frame or next <code>frameInUseCount</code> frames.</p>
+<p>If the allocation is in lost state, the function returns <code>VK_FALSE</code>. Memory of such allocation, as well as buffer or image bound to it, should not be used. Lost allocation and the buffer/image still need to be destroyed.</p>
+<p>If the allocation has been created without <a class="el" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a5f436af6c8fe8540573a6d22627a6fd2">VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT</a> flag, this function always returns <code>VK_TRUE</code>. </p>
+
+</div>
+</div>
+<a id="a9bc268595cb33f6ec4d519cfce81ff45"></a>
+<h2 class="memtitle"><span class="permalink"><a href="#a9bc268595cb33f6ec4d519cfce81ff45">&#9670;&nbsp;</a></span>vmaUnmapMemory()</h2>
+
+<div class="memitem">
+<div class="memproto">
+      <table class="memname">
+        <tr>
+          <td class="memname">void vmaUnmapMemory </td>
+          <td>(</td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocator.html">VmaAllocator</a>&#160;</td>
+          <td class="paramname"><em>allocator</em>, </td>
+        </tr>
+        <tr>
+          <td class="paramkey"></td>
+          <td></td>
+          <td class="paramtype"><a class="el" href="struct_vma_allocation.html">VmaAllocation</a>&#160;</td>
+          <td class="paramname"><em>allocation</em>&#160;</td>
+        </tr>
+        <tr>
+          <td></td>
+          <td>)</td>
+          <td></td><td></td>
+        </tr>
+      </table>
+</div><div class="memdoc">
+
+<p>Unmaps memory represented by given allocation, mapped previously using <a class="el" href="vk__mem__alloc_8h.html#ad5bd1243512d099706de88168992f069" title="Maps memory represented by given allocation and returns pointer to it.">vmaMapMemory()</a>. </p>
+<p>For details, see description of <a class="el" href="vk__mem__alloc_8h.html#ad5bd1243512d099706de88168992f069" title="Maps memory represented by given allocation and returns pointer to it.">vmaMapMemory()</a>.</p>
+<p>This function doesn't automatically flush or invalidate caches. If the allocation is made from a memory types that is not <code>HOST_COHERENT</code>, you also need to use <a class="el" href="vk__mem__alloc_8h.html#a0d0eb0c1102268fa9a476d12ecbe4006" title="Invalidates memory of given allocation.">vmaInvalidateAllocation()</a> / <a class="el" href="vk__mem__alloc_8h.html#abc34ee6f021f459aff885f3758c435de" title="Flushes memory of given allocation.">vmaFlushAllocation()</a>, as required by Vulkan specification. </p>
+
+</div>
+</div>
+</div><!-- contents -->
+<div class="ttc" id="avk__mem__alloc_8h_html_a11f0fbc034fa81a4efedd73d61ce7568"><div class="ttname"><a href="vk__mem__alloc_8h.html#a11f0fbc034fa81a4efedd73d61ce7568">vmaFreeMemory</a></div><div class="ttdeci">void vmaFreeMemory(VmaAllocator allocator, VmaAllocation allocation)</div><div class="ttdoc">Frees memory previously allocated using vmaAllocateMemory(), vmaAllocateMemoryForBuffer(),...</div></div>
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/vk__mem__alloc_8h_source.html b/third_party/VulkanMemoryAllocator/docs/html/vk__mem__alloc_8h_source.html
new file mode 100644
index 0000000..e3ead23
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/vk__mem__alloc_8h_source.html
@@ -0,0 +1,15780 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: vk_mem_alloc.h Source File</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+</div><!-- top -->
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div class="header">
+  <div class="headertitle">
+<div class="title">vk_mem_alloc.h</div>  </div>
+</div><!--header-->
+<div class="contents">
+<a href="vk__mem__alloc_8h.html">Go to the documentation of this file.</a><div class="fragment"><div class="line"><a name="l00001"></a><span class="lineno">    1</span>&#160;<span class="comment">//</span></div>
+<div class="line"><a name="l00002"></a><span class="lineno">    2</span>&#160;<span class="comment">// Copyright (c) 2017-2020 Advanced Micro Devices, Inc. All rights reserved.</span></div>
+<div class="line"><a name="l00003"></a><span class="lineno">    3</span>&#160;<span class="comment">//</span></div>
+<div class="line"><a name="l00004"></a><span class="lineno">    4</span>&#160;<span class="comment">// Permission is hereby granted, free of charge, to any person obtaining a copy</span></div>
+<div class="line"><a name="l00005"></a><span class="lineno">    5</span>&#160;<span class="comment">// of this software and associated documentation files (the &quot;Software&quot;), to deal</span></div>
+<div class="line"><a name="l00006"></a><span class="lineno">    6</span>&#160;<span class="comment">// in the Software without restriction, including without limitation the rights</span></div>
+<div class="line"><a name="l00007"></a><span class="lineno">    7</span>&#160;<span class="comment">// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell</span></div>
+<div class="line"><a name="l00008"></a><span class="lineno">    8</span>&#160;<span class="comment">// copies of the Software, and to permit persons to whom the Software is</span></div>
+<div class="line"><a name="l00009"></a><span class="lineno">    9</span>&#160;<span class="comment">// furnished to do so, subject to the following conditions:</span></div>
+<div class="line"><a name="l00010"></a><span class="lineno">   10</span>&#160;<span class="comment">//</span></div>
+<div class="line"><a name="l00011"></a><span class="lineno">   11</span>&#160;<span class="comment">// The above copyright notice and this permission notice shall be included in</span></div>
+<div class="line"><a name="l00012"></a><span class="lineno">   12</span>&#160;<span class="comment">// all copies or substantial portions of the Software.</span></div>
+<div class="line"><a name="l00013"></a><span class="lineno">   13</span>&#160;<span class="comment">//</span></div>
+<div class="line"><a name="l00014"></a><span class="lineno">   14</span>&#160;<span class="comment">// THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR</span></div>
+<div class="line"><a name="l00015"></a><span class="lineno">   15</span>&#160;<span class="comment">// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,</span></div>
+<div class="line"><a name="l00016"></a><span class="lineno">   16</span>&#160;<span class="comment">// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE</span></div>
+<div class="line"><a name="l00017"></a><span class="lineno">   17</span>&#160;<span class="comment">// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER</span></div>
+<div class="line"><a name="l00018"></a><span class="lineno">   18</span>&#160;<span class="comment">// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,</span></div>
+<div class="line"><a name="l00019"></a><span class="lineno">   19</span>&#160;<span class="comment">// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN</span></div>
+<div class="line"><a name="l00020"></a><span class="lineno">   20</span>&#160;<span class="comment">// THE SOFTWARE.</span></div>
+<div class="line"><a name="l00021"></a><span class="lineno">   21</span>&#160;<span class="comment">//</span></div>
+<div class="line"><a name="l00022"></a><span class="lineno">   22</span>&#160; </div>
+<div class="line"><a name="l00023"></a><span class="lineno">   23</span>&#160;<span class="preprocessor">#ifndef AMD_VULKAN_MEMORY_ALLOCATOR_H</span></div>
+<div class="line"><a name="l00024"></a><span class="lineno">   24</span>&#160;<span class="preprocessor">#define AMD_VULKAN_MEMORY_ALLOCATOR_H</span></div>
+<div class="line"><a name="l00025"></a><span class="lineno">   25</span>&#160; </div>
+<div class="line"><a name="l00026"></a><span class="lineno">   26</span>&#160;<span class="preprocessor">#ifdef __cplusplus</span></div>
+<div class="line"><a name="l00027"></a><span class="lineno">   27</span>&#160;<span class="keyword">extern</span> <span class="stringliteral">&quot;C&quot;</span> {</div>
+<div class="line"><a name="l00028"></a><span class="lineno">   28</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l00029"></a><span class="lineno">   29</span>&#160; </div>
+<div class="line"><a name="l01889"></a><span class="lineno"> 1889</span>&#160;<span class="comment">/*</span></div>
+<div class="line"><a name="l01890"></a><span class="lineno"> 1890</span>&#160;<span class="comment">Define this macro to 0/1 to disable/enable support for recording functionality,</span></div>
+<div class="line"><a name="l01891"></a><span class="lineno"> 1891</span>&#160;<span class="comment">available through VmaAllocatorCreateInfo::pRecordSettings.</span></div>
+<div class="line"><a name="l01892"></a><span class="lineno"> 1892</span>&#160;<span class="comment">*/</span></div>
+<div class="line"><a name="l01893"></a><span class="lineno"> 1893</span>&#160;<span class="preprocessor">#ifndef VMA_RECORDING_ENABLED</span></div>
+<div class="line"><a name="l01894"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#a1f0c126759fc96ccb6e2d23c101d770c"> 1894</a></span>&#160;<span class="preprocessor">    #define VMA_RECORDING_ENABLED 0</span></div>
+<div class="line"><a name="l01895"></a><span class="lineno"> 1895</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l01896"></a><span class="lineno"> 1896</span>&#160; </div>
+<div class="line"><a name="l01897"></a><span class="lineno"> 1897</span>&#160;<span class="preprocessor">#ifndef NOMINMAX</span></div>
+<div class="line"><a name="l01898"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#a9f918755b601cf4bffca775992e6fb90"> 1898</a></span>&#160;<span class="preprocessor">    #define NOMINMAX // For windows.h</span></div>
+<div class="line"><a name="l01899"></a><span class="lineno"> 1899</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l01900"></a><span class="lineno"> 1900</span>&#160; </div>
+<div class="line"><a name="l01901"></a><span class="lineno"> 1901</span>&#160;<span class="preprocessor">#ifndef VULKAN_H_</span></div>
+<div class="line"><a name="l01902"></a><span class="lineno"> 1902</span>&#160;<span class="preprocessor">    #include &lt;vulkan/vulkan.h&gt;</span></div>
+<div class="line"><a name="l01903"></a><span class="lineno"> 1903</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l01904"></a><span class="lineno"> 1904</span>&#160; </div>
+<div class="line"><a name="l01905"></a><span class="lineno"> 1905</span>&#160;<span class="preprocessor">#if VMA_RECORDING_ENABLED</span></div>
+<div class="line"><a name="l01906"></a><span class="lineno"> 1906</span>&#160;<span class="preprocessor">    #include &lt;windows.h&gt;</span></div>
+<div class="line"><a name="l01907"></a><span class="lineno"> 1907</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l01908"></a><span class="lineno"> 1908</span>&#160; </div>
+<div class="line"><a name="l01909"></a><span class="lineno"> 1909</span>&#160;<span class="comment">// Define this macro to declare maximum supported Vulkan version in format AAABBBCCC,</span></div>
+<div class="line"><a name="l01910"></a><span class="lineno"> 1910</span>&#160;<span class="comment">// where AAA = major, BBB = minor, CCC = patch.</span></div>
+<div class="line"><a name="l01911"></a><span class="lineno"> 1911</span>&#160;<span class="comment">// If you want to use version &gt; 1.0, it still needs to be enabled via VmaAllocatorCreateInfo::vulkanApiVersion.</span></div>
+<div class="line"><a name="l01912"></a><span class="lineno"> 1912</span>&#160;<span class="preprocessor">#if !defined(VMA_VULKAN_VERSION)</span></div>
+<div class="line"><a name="l01913"></a><span class="lineno"> 1913</span>&#160;<span class="preprocessor">    #if defined(VK_VERSION_1_2)</span></div>
+<div class="line"><a name="l01914"></a><span class="lineno"> 1914</span>&#160;<span class="preprocessor">        #define VMA_VULKAN_VERSION 1002000</span></div>
+<div class="line"><a name="l01915"></a><span class="lineno"> 1915</span>&#160;<span class="preprocessor">    #elif defined(VK_VERSION_1_1)</span></div>
+<div class="line"><a name="l01916"></a><span class="lineno"> 1916</span>&#160;<span class="preprocessor">        #define VMA_VULKAN_VERSION 1001000</span></div>
+<div class="line"><a name="l01917"></a><span class="lineno"> 1917</span>&#160;<span class="preprocessor">    #else</span></div>
+<div class="line"><a name="l01918"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#a1a2407c283893638cc039bb31fcd74b6"> 1918</a></span>&#160;<span class="preprocessor">        #define VMA_VULKAN_VERSION 1000000</span></div>
+<div class="line"><a name="l01919"></a><span class="lineno"> 1919</span>&#160;<span class="preprocessor">    #endif</span></div>
+<div class="line"><a name="l01920"></a><span class="lineno"> 1920</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l01921"></a><span class="lineno"> 1921</span>&#160; </div>
+<div class="line"><a name="l01922"></a><span class="lineno"> 1922</span>&#160;<span class="preprocessor">#if !defined(VMA_DEDICATED_ALLOCATION)</span></div>
+<div class="line"><a name="l01923"></a><span class="lineno"> 1923</span>&#160;<span class="preprocessor">    #if VK_KHR_get_memory_requirements2 &amp;&amp; VK_KHR_dedicated_allocation</span></div>
+<div class="line"><a name="l01924"></a><span class="lineno"> 1924</span>&#160;<span class="preprocessor">        #define VMA_DEDICATED_ALLOCATION 1</span></div>
+<div class="line"><a name="l01925"></a><span class="lineno"> 1925</span>&#160;<span class="preprocessor">    #else</span></div>
+<div class="line"><a name="l01926"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#af7b860e63b96d11e44ae8587ba06bbf4"> 1926</a></span>&#160;<span class="preprocessor">        #define VMA_DEDICATED_ALLOCATION 0</span></div>
+<div class="line"><a name="l01927"></a><span class="lineno"> 1927</span>&#160;<span class="preprocessor">    #endif</span></div>
+<div class="line"><a name="l01928"></a><span class="lineno"> 1928</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l01929"></a><span class="lineno"> 1929</span>&#160; </div>
+<div class="line"><a name="l01930"></a><span class="lineno"> 1930</span>&#160;<span class="preprocessor">#if !defined(VMA_BIND_MEMORY2)</span></div>
+<div class="line"><a name="l01931"></a><span class="lineno"> 1931</span>&#160;<span class="preprocessor">    #if VK_KHR_bind_memory2</span></div>
+<div class="line"><a name="l01932"></a><span class="lineno"> 1932</span>&#160;<span class="preprocessor">        #define VMA_BIND_MEMORY2 1</span></div>
+<div class="line"><a name="l01933"></a><span class="lineno"> 1933</span>&#160;<span class="preprocessor">    #else</span></div>
+<div class="line"><a name="l01934"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#a88bef97f86d70a34a4c0746e09a2680d"> 1934</a></span>&#160;<span class="preprocessor">        #define VMA_BIND_MEMORY2 0</span></div>
+<div class="line"><a name="l01935"></a><span class="lineno"> 1935</span>&#160;<span class="preprocessor">    #endif</span></div>
+<div class="line"><a name="l01936"></a><span class="lineno"> 1936</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l01937"></a><span class="lineno"> 1937</span>&#160; </div>
+<div class="line"><a name="l01938"></a><span class="lineno"> 1938</span>&#160;<span class="preprocessor">#if !defined(VMA_MEMORY_BUDGET)</span></div>
+<div class="line"><a name="l01939"></a><span class="lineno"> 1939</span>&#160;<span class="preprocessor">    #if VK_EXT_memory_budget &amp;&amp; (VK_KHR_get_physical_device_properties2 || VMA_VULKAN_VERSION &gt;= 1001000)</span></div>
+<div class="line"><a name="l01940"></a><span class="lineno"> 1940</span>&#160;<span class="preprocessor">        #define VMA_MEMORY_BUDGET 1</span></div>
+<div class="line"><a name="l01941"></a><span class="lineno"> 1941</span>&#160;<span class="preprocessor">    #else</span></div>
+<div class="line"><a name="l01942"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#a05decf1cf4ebf767beba7acca6c1ec3a"> 1942</a></span>&#160;<span class="preprocessor">        #define VMA_MEMORY_BUDGET 0</span></div>
+<div class="line"><a name="l01943"></a><span class="lineno"> 1943</span>&#160;<span class="preprocessor">    #endif</span></div>
+<div class="line"><a name="l01944"></a><span class="lineno"> 1944</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l01945"></a><span class="lineno"> 1945</span>&#160; </div>
+<div class="line"><a name="l01946"></a><span class="lineno"> 1946</span>&#160;<span class="comment">// Defined to 1 when VK_KHR_buffer_device_address device extension or equivalent core Vulkan 1.2 feature is defined in its headers.</span></div>
+<div class="line"><a name="l01947"></a><span class="lineno"> 1947</span>&#160;<span class="preprocessor">#if !defined(VMA_BUFFER_DEVICE_ADDRESS)</span></div>
+<div class="line"><a name="l01948"></a><span class="lineno"> 1948</span>&#160;<span class="preprocessor">    #if VK_KHR_buffer_device_address || VMA_VULKAN_VERSION &gt;= 1002000</span></div>
+<div class="line"><a name="l01949"></a><span class="lineno"> 1949</span>&#160;<span class="preprocessor">        #define VMA_BUFFER_DEVICE_ADDRESS 1</span></div>
+<div class="line"><a name="l01950"></a><span class="lineno"> 1950</span>&#160;<span class="preprocessor">    #else</span></div>
+<div class="line"><a name="l01951"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#a7f9d5e71b70dd1a137c303a8a8262c10"> 1951</a></span>&#160;<span class="preprocessor">        #define VMA_BUFFER_DEVICE_ADDRESS 0</span></div>
+<div class="line"><a name="l01952"></a><span class="lineno"> 1952</span>&#160;<span class="preprocessor">    #endif</span></div>
+<div class="line"><a name="l01953"></a><span class="lineno"> 1953</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l01954"></a><span class="lineno"> 1954</span>&#160; </div>
+<div class="line"><a name="l01955"></a><span class="lineno"> 1955</span>&#160;<span class="comment">// Define these macros to decorate all public functions with additional code,</span></div>
+<div class="line"><a name="l01956"></a><span class="lineno"> 1956</span>&#160;<span class="comment">// before and after returned type, appropriately. This may be useful for</span></div>
+<div class="line"><a name="l01957"></a><span class="lineno"> 1957</span>&#160;<span class="comment">// exporing the functions when compiling VMA as a separate library. Example:</span></div>
+<div class="line"><a name="l01958"></a><span class="lineno"> 1958</span>&#160;<span class="comment">// #define VMA_CALL_PRE  __declspec(dllexport)</span></div>
+<div class="line"><a name="l01959"></a><span class="lineno"> 1959</span>&#160;<span class="comment">// #define VMA_CALL_POST __cdecl</span></div>
+<div class="line"><a name="l01960"></a><span class="lineno"> 1960</span>&#160;<span class="preprocessor">#ifndef VMA_CALL_PRE</span></div>
+<div class="line"><a name="l01961"></a><span class="lineno"> 1961</span>&#160;<span class="preprocessor">    #define VMA_CALL_PRE</span></div>
+<div class="line"><a name="l01962"></a><span class="lineno"> 1962</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l01963"></a><span class="lineno"> 1963</span>&#160;<span class="preprocessor">#ifndef VMA_CALL_POST</span></div>
+<div class="line"><a name="l01964"></a><span class="lineno"> 1964</span>&#160;<span class="preprocessor">    #define VMA_CALL_POST</span></div>
+<div class="line"><a name="l01965"></a><span class="lineno"> 1965</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l01966"></a><span class="lineno"> 1966</span>&#160; </div>
+<div class="line"><a name="l01976"></a><span class="lineno"> 1976</span>&#160;VK_DEFINE_HANDLE(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a>)</div>
+<div class="line"><a name="l01977"></a><span class="lineno"> 1977</span>&#160; </div>
+<div class="line"><a name="l01978"></a><span class="lineno"> 1978</span>&#160;<span class="keyword">typedef</span> void (VKAPI_PTR *<a class="code" href="vk__mem__alloc_8h.html#a7e1ed85f7799600b03ad51a77acc21f3">PFN_vmaAllocateDeviceMemoryFunction</a>)(</div>
+<div class="line"><a name="l01980"></a><span class="lineno"> 1980</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a>      allocator,</div>
+<div class="line"><a name="l01981"></a><span class="lineno"> 1981</span>&#160;    uint32_t          memoryType,</div>
+<div class="line"><a name="l01982"></a><span class="lineno"> 1982</span>&#160;    VkDeviceMemory    memory,</div>
+<div class="line"><a name="l01983"></a><span class="lineno"> 1983</span>&#160;    VkDeviceSize      size,</div>
+<div class="line"><a name="l01984"></a><span class="lineno"> 1984</span>&#160;    <span class="keywordtype">void</span>* pUserData);</div>
+<div class="line"><a name="l01986"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#a154ccaaf53dc2c36378f80f0c4f3679b"> 1986</a></span>&#160;<span class="keyword">typedef</span> void (VKAPI_PTR *<a class="code" href="vk__mem__alloc_8h.html#a154ccaaf53dc2c36378f80f0c4f3679b">PFN_vmaFreeDeviceMemoryFunction</a>)(</div>
+<div class="line"><a name="l01987"></a><span class="lineno"> 1987</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a>      allocator,</div>
+<div class="line"><a name="l01988"></a><span class="lineno"> 1988</span>&#160;    uint32_t          memoryType,</div>
+<div class="line"><a name="l01989"></a><span class="lineno"> 1989</span>&#160;    VkDeviceMemory    memory,</div>
+<div class="line"><a name="l01990"></a><span class="lineno"> 1990</span>&#160;    VkDeviceSize      size,</div>
+<div class="line"><a name="l01991"></a><span class="lineno"> 1991</span>&#160;    <span class="keywordtype">void</span>* pUserData);</div>
+<div class="line"><a name="l01992"></a><span class="lineno"> 1992</span>&#160; </div>
+<div class="line"><a name="l02000"></a><span class="lineno"><a class="line" href="struct_vma_device_memory_callbacks.html"> 2000</a></span>&#160;<span class="keyword">typedef</span> <span class="keyword">struct </span><a class="code" href="struct_vma_device_memory_callbacks.html">VmaDeviceMemoryCallbacks</a> {</div>
+<div class="line"><a name="l02002"></a><span class="lineno"><a class="line" href="struct_vma_device_memory_callbacks.html#a4f17f7b255101e733b44d5633aceabfb"> 2002</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#a7e1ed85f7799600b03ad51a77acc21f3">PFN_vmaAllocateDeviceMemoryFunction</a> <a class="code" href="struct_vma_device_memory_callbacks.html#a4f17f7b255101e733b44d5633aceabfb">pfnAllocate</a>;</div>
+<div class="line"><a name="l02004"></a><span class="lineno"><a class="line" href="struct_vma_device_memory_callbacks.html#abe8a3328bbc916f6f712fdb6b299444c"> 2004</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#a154ccaaf53dc2c36378f80f0c4f3679b">PFN_vmaFreeDeviceMemoryFunction</a> <a class="code" href="struct_vma_device_memory_callbacks.html#abe8a3328bbc916f6f712fdb6b299444c">pfnFree</a>;</div>
+<div class="line"><a name="l02006"></a><span class="lineno"><a class="line" href="struct_vma_device_memory_callbacks.html#a24052de0937ddd54015a2df0363903c6"> 2006</a></span>&#160;    <span class="keywordtype">void</span>* <a class="code" href="struct_vma_device_memory_callbacks.html#a24052de0937ddd54015a2df0363903c6">pUserData</a>;</div>
+<div class="line"><a name="l02007"></a><span class="lineno"> 2007</span>&#160;} <a class="code" href="vk__mem__alloc_8h.html#a77692d3c8770ea8882d573206bd27b2b">VmaDeviceMemoryCallbacks</a>;</div>
+<div class="line"><a name="l02008"></a><span class="lineno"> 2008</span>&#160; </div>
+<div class="line"><a name="l02010"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7c"> 2010</a></span>&#160;<span class="keyword">typedef</span> <span class="keyword">enum</span> <a class="code" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7c">VmaAllocatorCreateFlagBits</a> {</div>
+<div class="line"><a name="l02015"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca4816ddaed324ba110172ca608a20f29d"> 2015</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca4816ddaed324ba110172ca608a20f29d">VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT</a> = 0x00000001,</div>
+<div class="line"><a name="l02040"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7cace7da7cc6e71a625dfa763c55a597878"> 2040</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7cace7da7cc6e71a625dfa763c55a597878">VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT</a> = 0x00000002,</div>
+<div class="line"><a name="l02055"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca8fb75bf07cd184ab903596295e863dee"> 2055</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca8fb75bf07cd184ab903596295e863dee">VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT</a> = 0x00000004,</div>
+<div class="line"><a name="l02067"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca4d4687863f7bd4b418c6006dc04400b0"> 2067</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca4d4687863f7bd4b418c6006dc04400b0">VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT</a> = 0x00000008,</div>
+<div class="line"><a name="l02085"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca2acce4886d8078552efa38878413970f"> 2085</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca2acce4886d8078552efa38878413970f">VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT</a> = 0x00000010,</div>
+<div class="line"><a name="l02103"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca5f1b28b0414319d1687e1f2b30ab0089"> 2103</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca5f1b28b0414319d1687e1f2b30ab0089">VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT</a> = 0x00000020,</div>
+<div class="line"><a name="l02104"></a><span class="lineno"> 2104</span>&#160; </div>
+<div class="line"><a name="l02105"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7cae4d5ad929caba5f23eb502b13bd5286c"> 2105</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7cae4d5ad929caba5f23eb502b13bd5286c">VMA_ALLOCATOR_CREATE_FLAG_BITS_MAX_ENUM</a> = 0x7FFFFFFF</div>
+<div class="line"><a name="l02106"></a><span class="lineno"> 2106</span>&#160;} <a class="code" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7c">VmaAllocatorCreateFlagBits</a>;</div>
+<div class="line"><a name="l02107"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#acfe6863e160722c2c1bbcf7573fddc4d"> 2107</a></span>&#160;<span class="keyword">typedef</span> VkFlags <a class="code" href="vk__mem__alloc_8h.html#acfe6863e160722c2c1bbcf7573fddc4d">VmaAllocatorCreateFlags</a>;</div>
+<div class="line"><a name="l02108"></a><span class="lineno"> 2108</span>&#160; </div>
+<div class="line"><a name="l02113"></a><span class="lineno"><a class="line" href="struct_vma_vulkan_functions.html"> 2113</a></span>&#160;<span class="keyword">typedef</span> <span class="keyword">struct </span><a class="code" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a> {</div>
+<div class="line"><a name="l02114"></a><span class="lineno"><a class="line" href="struct_vma_vulkan_functions.html#a77b7a74082823e865dd6546623468f96"> 2114</a></span>&#160;    PFN_vkGetPhysicalDeviceProperties <a class="code" href="struct_vma_vulkan_functions.html#a77b7a74082823e865dd6546623468f96">vkGetPhysicalDeviceProperties</a>;</div>
+<div class="line"><a name="l02115"></a><span class="lineno"><a class="line" href="struct_vma_vulkan_functions.html#a60d25c33bba06bb8592e6875cbaa9830"> 2115</a></span>&#160;    PFN_vkGetPhysicalDeviceMemoryProperties <a class="code" href="struct_vma_vulkan_functions.html#a60d25c33bba06bb8592e6875cbaa9830">vkGetPhysicalDeviceMemoryProperties</a>;</div>
+<div class="line"><a name="l02116"></a><span class="lineno"><a class="line" href="struct_vma_vulkan_functions.html#a2943bf99dfd784a0e8f599d987e22e6c"> 2116</a></span>&#160;    PFN_vkAllocateMemory <a class="code" href="struct_vma_vulkan_functions.html#a2943bf99dfd784a0e8f599d987e22e6c">vkAllocateMemory</a>;</div>
+<div class="line"><a name="l02117"></a><span class="lineno"><a class="line" href="struct_vma_vulkan_functions.html#a4c658701778564d62034255b5dda91b4"> 2117</a></span>&#160;    PFN_vkFreeMemory <a class="code" href="struct_vma_vulkan_functions.html#a4c658701778564d62034255b5dda91b4">vkFreeMemory</a>;</div>
+<div class="line"><a name="l02118"></a><span class="lineno"><a class="line" href="struct_vma_vulkan_functions.html#ab5c1f38dea3a2cf00dc9eb4f57218c49"> 2118</a></span>&#160;    PFN_vkMapMemory <a class="code" href="struct_vma_vulkan_functions.html#ab5c1f38dea3a2cf00dc9eb4f57218c49">vkMapMemory</a>;</div>
+<div class="line"><a name="l02119"></a><span class="lineno"><a class="line" href="struct_vma_vulkan_functions.html#acc798589736f0becb317fc2196c1d8b9"> 2119</a></span>&#160;    PFN_vkUnmapMemory <a class="code" href="struct_vma_vulkan_functions.html#acc798589736f0becb317fc2196c1d8b9">vkUnmapMemory</a>;</div>
+<div class="line"><a name="l02120"></a><span class="lineno"><a class="line" href="struct_vma_vulkan_functions.html#a33c322f4c4ad2810f8a9c97a277572f9"> 2120</a></span>&#160;    PFN_vkFlushMappedMemoryRanges <a class="code" href="struct_vma_vulkan_functions.html#a33c322f4c4ad2810f8a9c97a277572f9">vkFlushMappedMemoryRanges</a>;</div>
+<div class="line"><a name="l02121"></a><span class="lineno"><a class="line" href="struct_vma_vulkan_functions.html#a5c1093bc32386a8060c37c9f282078a1"> 2121</a></span>&#160;    PFN_vkInvalidateMappedMemoryRanges <a class="code" href="struct_vma_vulkan_functions.html#a5c1093bc32386a8060c37c9f282078a1">vkInvalidateMappedMemoryRanges</a>;</div>
+<div class="line"><a name="l02122"></a><span class="lineno"><a class="line" href="struct_vma_vulkan_functions.html#a94fc4f3a605d9880bb3c0ba2c2fc80b2"> 2122</a></span>&#160;    PFN_vkBindBufferMemory <a class="code" href="struct_vma_vulkan_functions.html#a94fc4f3a605d9880bb3c0ba2c2fc80b2">vkBindBufferMemory</a>;</div>
+<div class="line"><a name="l02123"></a><span class="lineno"><a class="line" href="struct_vma_vulkan_functions.html#a1338d96a128a5ade648b8d934907c637"> 2123</a></span>&#160;    PFN_vkBindImageMemory <a class="code" href="struct_vma_vulkan_functions.html#a1338d96a128a5ade648b8d934907c637">vkBindImageMemory</a>;</div>
+<div class="line"><a name="l02124"></a><span class="lineno"><a class="line" href="struct_vma_vulkan_functions.html#a5b92901df89a4194b0d12f6071d4d143"> 2124</a></span>&#160;    PFN_vkGetBufferMemoryRequirements <a class="code" href="struct_vma_vulkan_functions.html#a5b92901df89a4194b0d12f6071d4d143">vkGetBufferMemoryRequirements</a>;</div>
+<div class="line"><a name="l02125"></a><span class="lineno"><a class="line" href="struct_vma_vulkan_functions.html#a475f6f49f8debe4d10800592606d53f4"> 2125</a></span>&#160;    PFN_vkGetImageMemoryRequirements <a class="code" href="struct_vma_vulkan_functions.html#a475f6f49f8debe4d10800592606d53f4">vkGetImageMemoryRequirements</a>;</div>
+<div class="line"><a name="l02126"></a><span class="lineno"><a class="line" href="struct_vma_vulkan_functions.html#ae8084315a25006271a2edfc3a447519f"> 2126</a></span>&#160;    PFN_vkCreateBuffer <a class="code" href="struct_vma_vulkan_functions.html#ae8084315a25006271a2edfc3a447519f">vkCreateBuffer</a>;</div>
+<div class="line"><a name="l02127"></a><span class="lineno"><a class="line" href="struct_vma_vulkan_functions.html#a7e054606faddb07f0e8556f3ed317d45"> 2127</a></span>&#160;    PFN_vkDestroyBuffer <a class="code" href="struct_vma_vulkan_functions.html#a7e054606faddb07f0e8556f3ed317d45">vkDestroyBuffer</a>;</div>
+<div class="line"><a name="l02128"></a><span class="lineno"><a class="line" href="struct_vma_vulkan_functions.html#a23ebe70be515b9b5010a1d691200e325"> 2128</a></span>&#160;    PFN_vkCreateImage <a class="code" href="struct_vma_vulkan_functions.html#a23ebe70be515b9b5010a1d691200e325">vkCreateImage</a>;</div>
+<div class="line"><a name="l02129"></a><span class="lineno"><a class="line" href="struct_vma_vulkan_functions.html#a90b898227039b1dcb3520f6e91f09ffa"> 2129</a></span>&#160;    PFN_vkDestroyImage <a class="code" href="struct_vma_vulkan_functions.html#a90b898227039b1dcb3520f6e91f09ffa">vkDestroyImage</a>;</div>
+<div class="line"><a name="l02130"></a><span class="lineno"><a class="line" href="struct_vma_vulkan_functions.html#ae5c0db8c89a3b82593dc16aa6a49fa3a"> 2130</a></span>&#160;    PFN_vkCmdCopyBuffer <a class="code" href="struct_vma_vulkan_functions.html#ae5c0db8c89a3b82593dc16aa6a49fa3a">vkCmdCopyBuffer</a>;</div>
+<div class="line"><a name="l02131"></a><span class="lineno"> 2131</span>&#160;<span class="preprocessor">#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION &gt;= 1001000</span></div>
+<div class="line"><a name="l02132"></a><span class="lineno"> 2132</span>&#160;    PFN_vkGetBufferMemoryRequirements2KHR vkGetBufferMemoryRequirements2KHR;</div>
+<div class="line"><a name="l02133"></a><span class="lineno"> 2133</span>&#160;    PFN_vkGetImageMemoryRequirements2KHR vkGetImageMemoryRequirements2KHR;</div>
+<div class="line"><a name="l02134"></a><span class="lineno"> 2134</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l02135"></a><span class="lineno"> 2135</span>&#160;<span class="preprocessor">#if VMA_BIND_MEMORY2 || VMA_VULKAN_VERSION &gt;= 1001000</span></div>
+<div class="line"><a name="l02136"></a><span class="lineno"> 2136</span>&#160;    PFN_vkBindBufferMemory2KHR vkBindBufferMemory2KHR;</div>
+<div class="line"><a name="l02137"></a><span class="lineno"> 2137</span>&#160;    PFN_vkBindImageMemory2KHR vkBindImageMemory2KHR;</div>
+<div class="line"><a name="l02138"></a><span class="lineno"> 2138</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l02139"></a><span class="lineno"> 2139</span>&#160;<span class="preprocessor">#if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION &gt;= 1001000</span></div>
+<div class="line"><a name="l02140"></a><span class="lineno"> 2140</span>&#160;    PFN_vkGetPhysicalDeviceMemoryProperties2KHR vkGetPhysicalDeviceMemoryProperties2KHR;</div>
+<div class="line"><a name="l02141"></a><span class="lineno"> 2141</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l02142"></a><span class="lineno"> 2142</span>&#160;} <a class="code" href="vk__mem__alloc_8h.html#abb0a8e3b5040d847571cca6c7f9a8074">VmaVulkanFunctions</a>;</div>
+<div class="line"><a name="l02143"></a><span class="lineno"> 2143</span>&#160; </div>
+<div class="line"><a name="l02145"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#a4dd2c44642312a147a4e93373a6e64d2"> 2145</a></span>&#160;<span class="keyword">typedef</span> <span class="keyword">enum</span> <a class="code" href="vk__mem__alloc_8h.html#a4dd2c44642312a147a4e93373a6e64d2">VmaRecordFlagBits</a> {</div>
+<div class="line"><a name="l02151"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#a4dd2c44642312a147a4e93373a6e64d2a8e7ab322e8732654be627c4ea8f36cc7"> 2151</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#a4dd2c44642312a147a4e93373a6e64d2a8e7ab322e8732654be627c4ea8f36cc7">VMA_RECORD_FLUSH_AFTER_CALL_BIT</a> = 0x00000001,</div>
+<div class="line"><a name="l02152"></a><span class="lineno"> 2152</span>&#160;    </div>
+<div class="line"><a name="l02153"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#a4dd2c44642312a147a4e93373a6e64d2a20dd17d69966dbffa054739d6090b85e"> 2153</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#a4dd2c44642312a147a4e93373a6e64d2a20dd17d69966dbffa054739d6090b85e">VMA_RECORD_FLAG_BITS_MAX_ENUM</a> = 0x7FFFFFFF</div>
+<div class="line"><a name="l02154"></a><span class="lineno"> 2154</span>&#160;} <a class="code" href="vk__mem__alloc_8h.html#a4dd2c44642312a147a4e93373a6e64d2">VmaRecordFlagBits</a>;</div>
+<div class="line"><a name="l02155"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#af3929a1a4547c592fc0b0e55ef452828"> 2155</a></span>&#160;<span class="keyword">typedef</span> VkFlags <a class="code" href="vk__mem__alloc_8h.html#af3929a1a4547c592fc0b0e55ef452828">VmaRecordFlags</a>;</div>
+<div class="line"><a name="l02156"></a><span class="lineno"> 2156</span>&#160; </div>
+<div class="line"><a name="l02158"></a><span class="lineno"><a class="line" href="struct_vma_record_settings.html"> 2158</a></span>&#160;<span class="keyword">typedef</span> <span class="keyword">struct </span><a class="code" href="struct_vma_record_settings.html">VmaRecordSettings</a></div>
+<div class="line"><a name="l02159"></a><span class="lineno"> 2159</span>&#160;{</div>
+<div class="line"><a name="l02161"></a><span class="lineno"><a class="line" href="struct_vma_record_settings.html#ad8fdcc92119ae7a8c08c1a564c01d63a"> 2161</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#af3929a1a4547c592fc0b0e55ef452828">VmaRecordFlags</a> <a class="code" href="struct_vma_record_settings.html#ad8fdcc92119ae7a8c08c1a564c01d63a">flags</a>;</div>
+<div class="line"><a name="l02169"></a><span class="lineno"><a class="line" href="struct_vma_record_settings.html#a6cb1fdbf6bcb610b68f2010dd629e89d"> 2169</a></span>&#160;    <span class="keyword">const</span> <span class="keywordtype">char</span>* <a class="code" href="struct_vma_record_settings.html#a6cb1fdbf6bcb610b68f2010dd629e89d">pFilePath</a>;</div>
+<div class="line"><a name="l02170"></a><span class="lineno"> 2170</span>&#160;} <a class="code" href="vk__mem__alloc_8h.html#a16e21c877101493fce582664cd8754fc">VmaRecordSettings</a>;</div>
+<div class="line"><a name="l02171"></a><span class="lineno"> 2171</span>&#160; </div>
+<div class="line"><a name="l02173"></a><span class="lineno"><a class="line" href="struct_vma_allocator_create_info.html"> 2173</a></span>&#160;<span class="keyword">typedef</span> <span class="keyword">struct </span><a class="code" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a></div>
+<div class="line"><a name="l02174"></a><span class="lineno"> 2174</span>&#160;{</div>
+<div class="line"><a name="l02176"></a><span class="lineno"><a class="line" href="struct_vma_allocator_create_info.html#a392ea2ecbaff93f91a7c49f735ad4346"> 2176</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#acfe6863e160722c2c1bbcf7573fddc4d">VmaAllocatorCreateFlags</a> <a class="code" href="struct_vma_allocator_create_info.html#a392ea2ecbaff93f91a7c49f735ad4346">flags</a>;</div>
+<div class="line"><a name="l02178"></a><span class="lineno"> 2178</span>&#160; </div>
+<div class="line"><a name="l02179"></a><span class="lineno"><a class="line" href="struct_vma_allocator_create_info.html#a08230f04ae6ccf8a78150a9e829a7156"> 2179</a></span>&#160;    VkPhysicalDevice <a class="code" href="struct_vma_allocator_create_info.html#a08230f04ae6ccf8a78150a9e829a7156">physicalDevice</a>;</div>
+<div class="line"><a name="l02181"></a><span class="lineno"> 2181</span>&#160; </div>
+<div class="line"><a name="l02182"></a><span class="lineno"><a class="line" href="struct_vma_allocator_create_info.html#ad924ddd77b04039c88d0c09b0ffcd500"> 2182</a></span>&#160;    VkDevice <a class="code" href="struct_vma_allocator_create_info.html#ad924ddd77b04039c88d0c09b0ffcd500">device</a>;</div>
+<div class="line"><a name="l02184"></a><span class="lineno"> 2184</span>&#160; </div>
+<div class="line"><a name="l02185"></a><span class="lineno"><a class="line" href="struct_vma_allocator_create_info.html#a8e4714298e3121cdd8b214a1ae7a637a"> 2185</a></span>&#160;    VkDeviceSize <a class="code" href="struct_vma_allocator_create_info.html#a8e4714298e3121cdd8b214a1ae7a637a">preferredLargeHeapBlockSize</a>;</div>
+<div class="line"><a name="l02187"></a><span class="lineno"> 2187</span>&#160; </div>
+<div class="line"><a name="l02188"></a><span class="lineno"><a class="line" href="struct_vma_allocator_create_info.html#a6e409087e3be55400d0e4ccbe43c608d"> 2188</a></span>&#160;    <span class="keyword">const</span> VkAllocationCallbacks* <a class="code" href="struct_vma_allocator_create_info.html#a6e409087e3be55400d0e4ccbe43c608d">pAllocationCallbacks</a>;</div>
+<div class="line"><a name="l02190"></a><span class="lineno"> 2190</span>&#160; </div>
+<div class="line"><a name="l02191"></a><span class="lineno"><a class="line" href="struct_vma_allocator_create_info.html#af1380969b5e1ea4c3184a877892d260e"> 2191</a></span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_device_memory_callbacks.html">VmaDeviceMemoryCallbacks</a>* <a class="code" href="struct_vma_allocator_create_info.html#af1380969b5e1ea4c3184a877892d260e">pDeviceMemoryCallbacks</a>;</div>
+<div class="line"><a name="l02205"></a><span class="lineno"><a class="line" href="struct_vma_allocator_create_info.html#a21ea188dd212b8171cb9ecbed4a2a3a7"> 2205</a></span>&#160;    uint32_t <a class="code" href="struct_vma_allocator_create_info.html#a21ea188dd212b8171cb9ecbed4a2a3a7">frameInUseCount</a>;</div>
+<div class="line"><a name="l02230"></a><span class="lineno"><a class="line" href="struct_vma_allocator_create_info.html#a31c192aa6cbffa33279f6d9f0c47c44b"> 2230</a></span>&#160;    <span class="keyword">const</span> VkDeviceSize* <a class="code" href="struct_vma_allocator_create_info.html#a31c192aa6cbffa33279f6d9f0c47c44b">pHeapSizeLimit</a>;</div>
+<div class="line"><a name="l02235"></a><span class="lineno"><a class="line" href="struct_vma_allocator_create_info.html#a3dc197be3227da7338b1643f70db36bd"> 2235</a></span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a>* <a class="code" href="struct_vma_allocator_create_info.html#a3dc197be3227da7338b1643f70db36bd">pVulkanFunctions</a>;</div>
+<div class="line"><a name="l02242"></a><span class="lineno"><a class="line" href="struct_vma_allocator_create_info.html#ace2aa4877b16a42b0b7673d4e26000ee"> 2242</a></span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_record_settings.html">VmaRecordSettings</a>* <a class="code" href="struct_vma_allocator_create_info.html#ace2aa4877b16a42b0b7673d4e26000ee">pRecordSettings</a>;</div>
+<div class="line"><a name="l02247"></a><span class="lineno"><a class="line" href="struct_vma_allocator_create_info.html#a70dd42e29b1df1d1b9b61532ae0b370b"> 2247</a></span>&#160;    VkInstance <a class="code" href="struct_vma_allocator_create_info.html#a70dd42e29b1df1d1b9b61532ae0b370b">instance</a>;</div>
+<div class="line"><a name="l02256"></a><span class="lineno"><a class="line" href="struct_vma_allocator_create_info.html#ae0ffc55139b54520a6bb704b29ffc285"> 2256</a></span>&#160;    uint32_t <a class="code" href="struct_vma_allocator_create_info.html#ae0ffc55139b54520a6bb704b29ffc285">vulkanApiVersion</a>;</div>
+<div class="line"><a name="l02257"></a><span class="lineno"> 2257</span>&#160;} <a class="code" href="vk__mem__alloc_8h.html#aad9652301d33759b83e52d4f3605a14a">VmaAllocatorCreateInfo</a>;</div>
+<div class="line"><a name="l02258"></a><span class="lineno"> 2258</span>&#160; </div>
+<div class="line"><a name="l02260"></a><span class="lineno"> 2260</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a200692051ddb34240248234f5f4c17bb">vmaCreateAllocator</a>(</div>
+<div class="line"><a name="l02261"></a><span class="lineno"> 2261</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a>* pCreateInfo,</div>
+<div class="line"><a name="l02262"></a><span class="lineno"> 2262</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a>* pAllocator);</div>
+<div class="line"><a name="l02263"></a><span class="lineno"> 2263</span>&#160; </div>
+<div class="line"><a name="l02265"></a><span class="lineno"> 2265</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#aa8d164061c88f22fb1fd3c8f3534bc1d">vmaDestroyAllocator</a>(</div>
+<div class="line"><a name="l02266"></a><span class="lineno"> 2266</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator);</div>
+<div class="line"><a name="l02267"></a><span class="lineno"> 2267</span>&#160; </div>
+<div class="line"><a name="l02270"></a><span class="lineno"><a class="line" href="struct_vma_allocator_info.html"> 2270</a></span>&#160;<span class="keyword">typedef</span> <span class="keyword">struct </span><a class="code" href="struct_vma_allocator_info.html">VmaAllocatorInfo</a></div>
+<div class="line"><a name="l02271"></a><span class="lineno"> 2271</span>&#160;{</div>
+<div class="line"><a name="l02276"></a><span class="lineno"><a class="line" href="struct_vma_allocator_info.html#a2ed6a4d2d3fea039d66a13f15d0ce5fe"> 2276</a></span>&#160;    VkInstance <a class="code" href="struct_vma_allocator_info.html#a2ed6a4d2d3fea039d66a13f15d0ce5fe">instance</a>;</div>
+<div class="line"><a name="l02281"></a><span class="lineno"><a class="line" href="struct_vma_allocator_info.html#aba2b703f96e51d567717e1fb2935b47a"> 2281</a></span>&#160;    VkPhysicalDevice <a class="code" href="struct_vma_allocator_info.html#aba2b703f96e51d567717e1fb2935b47a">physicalDevice</a>;</div>
+<div class="line"><a name="l02286"></a><span class="lineno"><a class="line" href="struct_vma_allocator_info.html#a012b4c485bf3b0ea8921352c5ee0c357"> 2286</a></span>&#160;    VkDevice <a class="code" href="struct_vma_allocator_info.html#a012b4c485bf3b0ea8921352c5ee0c357">device</a>;</div>
+<div class="line"><a name="l02287"></a><span class="lineno"> 2287</span>&#160;} <a class="code" href="vk__mem__alloc_8h.html#a1988031b0223fdbd564250fa1edd942c">VmaAllocatorInfo</a>;</div>
+<div class="line"><a name="l02288"></a><span class="lineno"> 2288</span>&#160; </div>
+<div class="line"><a name="l02294"></a><span class="lineno"> 2294</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#afa02231a791b37255720d566a52683e7">vmaGetAllocatorInfo</a>(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator, <a class="code" href="struct_vma_allocator_info.html">VmaAllocatorInfo</a>* pAllocatorInfo);</div>
+<div class="line"><a name="l02295"></a><span class="lineno"> 2295</span>&#160; </div>
+<div class="line"><a name="l02300"></a><span class="lineno"> 2300</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#aecabf7b6e91ea87d0316fa0a9e014fe0">vmaGetPhysicalDeviceProperties</a>(</div>
+<div class="line"><a name="l02301"></a><span class="lineno"> 2301</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l02302"></a><span class="lineno"> 2302</span>&#160;    <span class="keyword">const</span> VkPhysicalDeviceProperties** ppPhysicalDeviceProperties);</div>
+<div class="line"><a name="l02303"></a><span class="lineno"> 2303</span>&#160; </div>
+<div class="line"><a name="l02308"></a><span class="lineno"> 2308</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#ab88db292a17974f911182543fda52d19">vmaGetMemoryProperties</a>(</div>
+<div class="line"><a name="l02309"></a><span class="lineno"> 2309</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l02310"></a><span class="lineno"> 2310</span>&#160;    <span class="keyword">const</span> VkPhysicalDeviceMemoryProperties** ppPhysicalDeviceMemoryProperties);</div>
+<div class="line"><a name="l02311"></a><span class="lineno"> 2311</span>&#160; </div>
+<div class="line"><a name="l02318"></a><span class="lineno"> 2318</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a8701444752eb5de4464adb5a2b514bca">vmaGetMemoryTypeProperties</a>(</div>
+<div class="line"><a name="l02319"></a><span class="lineno"> 2319</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l02320"></a><span class="lineno"> 2320</span>&#160;    uint32_t memoryTypeIndex,</div>
+<div class="line"><a name="l02321"></a><span class="lineno"> 2321</span>&#160;    VkMemoryPropertyFlags* pFlags);</div>
+<div class="line"><a name="l02322"></a><span class="lineno"> 2322</span>&#160; </div>
+<div class="line"><a name="l02331"></a><span class="lineno"> 2331</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#ade56bf8dc9f5a5eaddf5f119ed525236">vmaSetCurrentFrameIndex</a>(</div>
+<div class="line"><a name="l02332"></a><span class="lineno"> 2332</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l02333"></a><span class="lineno"> 2333</span>&#160;    uint32_t frameIndex);</div>
+<div class="line"><a name="l02334"></a><span class="lineno"> 2334</span>&#160; </div>
+<div class="line"><a name="l02337"></a><span class="lineno"><a class="line" href="struct_vma_stat_info.html"> 2337</a></span>&#160;<span class="keyword">typedef</span> <span class="keyword">struct </span><a class="code" href="struct_vma_stat_info.html">VmaStatInfo</a></div>
+<div class="line"><a name="l02338"></a><span class="lineno"> 2338</span>&#160;{</div>
+<div class="line"><a name="l02340"></a><span class="lineno"><a class="line" href="struct_vma_stat_info.html#abc4bb7cd611900778464c56e50c970a4"> 2340</a></span>&#160;    uint32_t <a class="code" href="struct_vma_stat_info.html#abc4bb7cd611900778464c56e50c970a4">blockCount</a>;</div>
+<div class="line"><a name="l02342"></a><span class="lineno"><a class="line" href="struct_vma_stat_info.html#a537741e4d5cdddc1c0ab95ec650afaff"> 2342</a></span>&#160;    uint32_t <a class="code" href="struct_vma_stat_info.html#a537741e4d5cdddc1c0ab95ec650afaff">allocationCount</a>;</div>
+<div class="line"><a name="l02344"></a><span class="lineno"><a class="line" href="struct_vma_stat_info.html#ae06129c771bfebfd6468a7f4276502a9"> 2344</a></span>&#160;    uint32_t <a class="code" href="struct_vma_stat_info.html#ae06129c771bfebfd6468a7f4276502a9">unusedRangeCount</a>;</div>
+<div class="line"><a name="l02346"></a><span class="lineno"><a class="line" href="struct_vma_stat_info.html#ab0c6c73837e5a70c749fbd4f6064895a"> 2346</a></span>&#160;    VkDeviceSize <a class="code" href="struct_vma_stat_info.html#ab0c6c73837e5a70c749fbd4f6064895a">usedBytes</a>;</div>
+<div class="line"><a name="l02348"></a><span class="lineno"><a class="line" href="struct_vma_stat_info.html#a1859d290aca2cd582d8dc25922092669"> 2348</a></span>&#160;    VkDeviceSize <a class="code" href="struct_vma_stat_info.html#a1859d290aca2cd582d8dc25922092669">unusedBytes</a>;</div>
+<div class="line"><a name="l02349"></a><span class="lineno"><a class="line" href="struct_vma_stat_info.html#ade8b40bd3139c04aabd2fc538a356fea"> 2349</a></span>&#160;    VkDeviceSize <a class="code" href="struct_vma_stat_info.html#ade8b40bd3139c04aabd2fc538a356fea">allocationSizeMin</a>, <a class="code" href="struct_vma_stat_info.html#a1081a039964e566c672e7a2347f9e599">allocationSizeAvg</a>, <a class="code" href="struct_vma_stat_info.html#a17e9733a5ecd76287d4db6e66f71f50c">allocationSizeMax</a>;</div>
+<div class="line"><a name="l02350"></a><span class="lineno"><a class="line" href="struct_vma_stat_info.html#aedeba931324f16589cd2416c0d2dd0d4"> 2350</a></span>&#160;    VkDeviceSize <a class="code" href="struct_vma_stat_info.html#aedeba931324f16589cd2416c0d2dd0d4">unusedRangeSizeMin</a>, <a class="code" href="struct_vma_stat_info.html#a2f9b3452af90c9768a30b7fb6ae194fc">unusedRangeSizeAvg</a>, <a class="code" href="struct_vma_stat_info.html#a5ba1a2476c4d39b10f7e2f7ebbb72ac4">unusedRangeSizeMax</a>;</div>
+<div class="line"><a name="l02351"></a><span class="lineno"> 2351</span>&#160;} <a class="code" href="vk__mem__alloc_8h.html#aec5b57e29c97b5d69c6d5654d60df878">VmaStatInfo</a>;</div>
+<div class="line"><a name="l02352"></a><span class="lineno"> 2352</span>&#160; </div>
+<div class="line"><a name="l02354"></a><span class="lineno"><a class="line" href="struct_vma_stats.html"> 2354</a></span>&#160;<span class="keyword">typedef</span> <span class="keyword">struct </span><a class="code" href="struct_vma_stats.html">VmaStats</a></div>
+<div class="line"><a name="l02355"></a><span class="lineno"> 2355</span>&#160;{</div>
+<div class="line"><a name="l02356"></a><span class="lineno"><a class="line" href="struct_vma_stats.html#a13e3caf754be79352c42408756309331"> 2356</a></span>&#160;    <a class="code" href="struct_vma_stat_info.html">VmaStatInfo</a> <a class="code" href="struct_vma_stats.html#a13e3caf754be79352c42408756309331">memoryType</a>[VK_MAX_MEMORY_TYPES];</div>
+<div class="line"><a name="l02357"></a><span class="lineno"><a class="line" href="struct_vma_stats.html#a0e6611508c29a187f0fd14ff1a0329c0"> 2357</a></span>&#160;    <a class="code" href="struct_vma_stat_info.html">VmaStatInfo</a> <a class="code" href="struct_vma_stats.html#a0e6611508c29a187f0fd14ff1a0329c0">memoryHeap</a>[VK_MAX_MEMORY_HEAPS];</div>
+<div class="line"><a name="l02358"></a><span class="lineno"><a class="line" href="struct_vma_stats.html#a2e8f5b3353f2fefef3c27f29e245a1f9"> 2358</a></span>&#160;    <a class="code" href="struct_vma_stat_info.html">VmaStatInfo</a> <a class="code" href="struct_vma_stats.html#a2e8f5b3353f2fefef3c27f29e245a1f9">total</a>;</div>
+<div class="line"><a name="l02359"></a><span class="lineno"> 2359</span>&#160;} <a class="code" href="vk__mem__alloc_8h.html#a21813b2efdf3836767a9058cd8a94034">VmaStats</a>;</div>
+<div class="line"><a name="l02360"></a><span class="lineno"> 2360</span>&#160; </div>
+<div class="line"><a name="l02370"></a><span class="lineno"> 2370</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a333b61c1788cb23559177531e6a93ca3">vmaCalculateStats</a>(</div>
+<div class="line"><a name="l02371"></a><span class="lineno"> 2371</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l02372"></a><span class="lineno"> 2372</span>&#160;    <a class="code" href="struct_vma_stats.html">VmaStats</a>* pStats);</div>
+<div class="line"><a name="l02373"></a><span class="lineno"> 2373</span>&#160; </div>
+<div class="line"><a name="l02376"></a><span class="lineno"><a class="line" href="struct_vma_budget.html"> 2376</a></span>&#160;<span class="keyword">typedef</span> <span class="keyword">struct </span><a class="code" href="struct_vma_budget.html">VmaBudget</a></div>
+<div class="line"><a name="l02377"></a><span class="lineno"> 2377</span>&#160;{</div>
+<div class="line"><a name="l02380"></a><span class="lineno"><a class="line" href="struct_vma_budget.html#a58b492901baab685f466199124e514a0"> 2380</a></span>&#160;    VkDeviceSize <a class="code" href="struct_vma_budget.html#a58b492901baab685f466199124e514a0">blockBytes</a>;</div>
+<div class="line"><a name="l02381"></a><span class="lineno"> 2381</span>&#160;    </div>
+<div class="line"><a name="l02391"></a><span class="lineno"><a class="line" href="struct_vma_budget.html#a7e2a6583ebd63e194951c542563804d8"> 2391</a></span>&#160;    VkDeviceSize <a class="code" href="struct_vma_budget.html#a7e2a6583ebd63e194951c542563804d8">allocationBytes</a>;</div>
+<div class="line"><a name="l02392"></a><span class="lineno"> 2392</span>&#160;    </div>
+<div class="line"><a name="l02401"></a><span class="lineno"><a class="line" href="struct_vma_budget.html#a84dd1ecca8b0110259eb206dbadb11f6"> 2401</a></span>&#160;    VkDeviceSize <a class="code" href="struct_vma_budget.html#a84dd1ecca8b0110259eb206dbadb11f6">usage</a>;</div>
+<div class="line"><a name="l02402"></a><span class="lineno"> 2402</span>&#160;    </div>
+<div class="line"><a name="l02412"></a><span class="lineno"><a class="line" href="struct_vma_budget.html#ab82e1d1754c2d210d0bdf90220bc6cdd"> 2412</a></span>&#160;    VkDeviceSize <a class="code" href="struct_vma_budget.html#ab82e1d1754c2d210d0bdf90220bc6cdd">budget</a>;</div>
+<div class="line"><a name="l02413"></a><span class="lineno"> 2413</span>&#160;} <a class="code" href="vk__mem__alloc_8h.html#aa078667e71b1ef24e87a6a30d128381d">VmaBudget</a>;</div>
+<div class="line"><a name="l02414"></a><span class="lineno"> 2414</span>&#160; </div>
+<div class="line"><a name="l02425"></a><span class="lineno"> 2425</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#aec0ed24ebea2d0099eed5f801daaefba">vmaGetBudget</a>(</div>
+<div class="line"><a name="l02426"></a><span class="lineno"> 2426</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l02427"></a><span class="lineno"> 2427</span>&#160;    <a class="code" href="struct_vma_budget.html">VmaBudget</a>* pBudget);</div>
+<div class="line"><a name="l02428"></a><span class="lineno"> 2428</span>&#160; </div>
+<div class="line"><a name="l02429"></a><span class="lineno"> 2429</span>&#160;<span class="preprocessor">#ifndef VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l02430"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#ae25f0d55fd91cb166f002b63244800e1"> 2430</a></span>&#160;<span class="preprocessor">#define VMA_STATS_STRING_ENABLED 1</span></div>
+<div class="line"><a name="l02431"></a><span class="lineno"> 2431</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l02432"></a><span class="lineno"> 2432</span>&#160; </div>
+<div class="line"><a name="l02433"></a><span class="lineno"> 2433</span>&#160;<span class="preprocessor">#if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l02434"></a><span class="lineno"> 2434</span>&#160; </div>
+<div class="line"><a name="l02436"></a><span class="lineno"> 2436</span>&#160; </div>
+<div class="line"><a name="l02438"></a><span class="lineno"> 2438</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#aa4fee7eb5253377599ef4fd38c93c2a0">vmaBuildStatsString</a>(</div>
+<div class="line"><a name="l02439"></a><span class="lineno"> 2439</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l02440"></a><span class="lineno"> 2440</span>&#160;    <span class="keywordtype">char</span>** ppStatsString,</div>
+<div class="line"><a name="l02441"></a><span class="lineno"> 2441</span>&#160;    VkBool32 detailedMap);</div>
+<div class="line"><a name="l02442"></a><span class="lineno"> 2442</span>&#160; </div>
+<div class="line"><a name="l02443"></a><span class="lineno"> 2443</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a3104eb30d8122c84dd8541063f145288">vmaFreeStatsString</a>(</div>
+<div class="line"><a name="l02444"></a><span class="lineno"> 2444</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l02445"></a><span class="lineno"> 2445</span>&#160;    <span class="keywordtype">char</span>* pStatsString);</div>
+<div class="line"><a name="l02446"></a><span class="lineno"> 2446</span>&#160; </div>
+<div class="line"><a name="l02447"></a><span class="lineno"> 2447</span>&#160;<span class="preprocessor">#endif // #if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l02448"></a><span class="lineno"> 2448</span>&#160; </div>
+<div class="line"><a name="l02457"></a><span class="lineno"> 2457</span>&#160;VK_DEFINE_HANDLE(<a class="code" href="struct_vma_pool.html">VmaPool</a>)</div>
+<div class="line"><a name="l02458"></a><span class="lineno"> 2458</span>&#160; </div>
+<div class="line"><a name="l02459"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cc"> 2459</a></span>&#160;typedef enum <a class="code" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cc">VmaMemoryUsage</a></div>
+<div class="line"><a name="l02460"></a><span class="lineno"> 2460</span>&#160;{</div>
+<div class="line"><a name="l02464"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccaf50d27e34e0925cf3a63db8c839121dd"> 2464</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccaf50d27e34e0925cf3a63db8c839121dd">VMA_MEMORY_USAGE_UNKNOWN</a> = 0,</div>
+<div class="line"><a name="l02481"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7"> 2481</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7">VMA_MEMORY_USAGE_GPU_ONLY</a> = 1,</div>
+<div class="line"><a name="l02491"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca40bdf4cddeffeb12f43d45ca1286e0a5"> 2491</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca40bdf4cddeffeb12f43d45ca1286e0a5">VMA_MEMORY_USAGE_CPU_ONLY</a> = 2,</div>
+<div class="line"><a name="l02498"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca9066b52c5a7079bb74a69aaf8b92ff67"> 2498</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca9066b52c5a7079bb74a69aaf8b92ff67">VMA_MEMORY_USAGE_CPU_TO_GPU</a> = 3,</div>
+<div class="line"><a name="l02507"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca7b586d2fdaf82a463b58f581ed72be27"> 2507</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca7b586d2fdaf82a463b58f581ed72be27">VMA_MEMORY_USAGE_GPU_TO_CPU</a> = 4,</div>
+<div class="line"><a name="l02513"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca416a444d4d0fc20067c3f76f32ff2500"> 2513</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca416a444d4d0fc20067c3f76f32ff2500">VMA_MEMORY_USAGE_CPU_COPY</a> = 5,</div>
+<div class="line"><a name="l02521"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca835333d9072db63a653818030e17614d"> 2521</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca835333d9072db63a653818030e17614d">VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED</a> = 6,</div>
+<div class="line"><a name="l02522"></a><span class="lineno"> 2522</span>&#160; </div>
+<div class="line"><a name="l02523"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca091e69437ef693e8d0d287f1c719ba6e"> 2523</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca091e69437ef693e8d0d287f1c719ba6e">VMA_MEMORY_USAGE_MAX_ENUM</a> = 0x7FFFFFFF</div>
+<div class="line"><a name="l02524"></a><span class="lineno"> 2524</span>&#160;} <a class="code" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cc">VmaMemoryUsage</a>;</div>
+<div class="line"><a name="l02525"></a><span class="lineno"> 2525</span>&#160; </div>
+<div class="line"><a name="l02527"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597"> 2527</a></span>&#160;<span class="keyword">typedef</span> <span class="keyword">enum</span> <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597">VmaAllocationCreateFlagBits</a> {</div>
+<div class="line"><a name="l02534"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a3fc311d855c2ff53f1090ef5c722b38f"> 2534</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a3fc311d855c2ff53f1090ef5c722b38f">VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT</a> = 0x00000001,</div>
+<div class="line"><a name="l02535"></a><span class="lineno"> 2535</span>&#160; </div>
+<div class="line"><a name="l02545"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a89759603401014eb325eb22a3839f2ff"> 2545</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a89759603401014eb325eb22a3839f2ff">VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT</a> = 0x00000002,</div>
+<div class="line"><a name="l02558"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a11da372cc3a82931c5e5d6146cd9dd1f"> 2558</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a11da372cc3a82931c5e5d6146cd9dd1f">VMA_ALLOCATION_CREATE_MAPPED_BIT</a> = 0x00000004,</div>
+<div class="line"><a name="l02571"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a5f436af6c8fe8540573a6d22627a6fd2"> 2571</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a5f436af6c8fe8540573a6d22627a6fd2">VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT</a> = 0x00000008,</div>
+<div class="line"><a name="l02578"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a68686d0ce9beb0d4d1b9f2b8b1389a7e"> 2578</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a68686d0ce9beb0d4d1b9f2b8b1389a7e">VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT</a> = 0x00000010,</div>
+<div class="line"><a name="l02584"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597aa6f24f821cd6a7c5e4a443f7bf59c520"> 2584</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597aa6f24f821cd6a7c5e4a443f7bf59c520">VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT</a> = 0x00000020,</div>
+<div class="line"><a name="l02589"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a42ba3a2d2c7117953210b7c3ef8da0df"> 2589</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a42ba3a2d2c7117953210b7c3ef8da0df">VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT</a> = 0x00000040,</div>
+<div class="line"><a name="l02595"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a2310568c62208af432724305fe29ccea"> 2595</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a2310568c62208af432724305fe29ccea">VMA_ALLOCATION_CREATE_DONT_BIND_BIT</a> = 0x00000080,</div>
+<div class="line"><a name="l02599"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597ab8b1764f3e9022368e440c057783b92d"> 2599</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597ab8b1764f3e9022368e440c057783b92d">VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT</a> = 0x00000100,</div>
+<div class="line"><a name="l02600"></a><span class="lineno"> 2600</span>&#160; </div>
+<div class="line"><a name="l02604"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a839826775c62319466441f86496f036d"> 2604</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a839826775c62319466441f86496f036d">VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT</a>  = 0x00010000,</div>
+<div class="line"><a name="l02608"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597ad242a04f802e25fef0b880afe8bb0a62"> 2608</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597ad242a04f802e25fef0b880afe8bb0a62">VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT</a> = 0x00020000,</div>
+<div class="line"><a name="l02615"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a33eb2052674f3ad92386c714a65fb777"> 2615</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a33eb2052674f3ad92386c714a65fb777">VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT</a> = 0x00040000,</div>
+<div class="line"><a name="l02616"></a><span class="lineno"> 2616</span>&#160; </div>
+<div class="line"><a name="l02619"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a8af1210cf591784afa026d94998f735d"> 2619</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a8af1210cf591784afa026d94998f735d">VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT</a> = <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a839826775c62319466441f86496f036d">VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT</a>,</div>
+<div class="line"><a name="l02622"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a0729e932b7ea170e3a128cad96c5cf6d"> 2622</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a0729e932b7ea170e3a128cad96c5cf6d">VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT</a> = <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a33eb2052674f3ad92386c714a65fb777">VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT</a>,</div>
+<div class="line"><a name="l02625"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a621b704103eb3360230c860acf36e706"> 2625</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a621b704103eb3360230c860acf36e706">VMA_ALLOCATION_CREATE_STRATEGY_MIN_FRAGMENTATION_BIT</a> = <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597ad242a04f802e25fef0b880afe8bb0a62">VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT</a>,</div>
+<div class="line"><a name="l02626"></a><span class="lineno"> 2626</span>&#160; </div>
+<div class="line"><a name="l02629"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a8e16845d81ae3d27c47106d4770d5c7e"> 2629</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a8e16845d81ae3d27c47106d4770d5c7e">VMA_ALLOCATION_CREATE_STRATEGY_MASK</a> =</div>
+<div class="line"><a name="l02630"></a><span class="lineno"> 2630</span>&#160;        <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a839826775c62319466441f86496f036d">VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT</a> |</div>
+<div class="line"><a name="l02631"></a><span class="lineno"> 2631</span>&#160;        <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597ad242a04f802e25fef0b880afe8bb0a62">VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT</a> |</div>
+<div class="line"><a name="l02632"></a><span class="lineno"> 2632</span>&#160;        <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a33eb2052674f3ad92386c714a65fb777">VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT</a>,</div>
+<div class="line"><a name="l02633"></a><span class="lineno"> 2633</span>&#160; </div>
+<div class="line"><a name="l02634"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597ae5633ec569f4899cf8f29e7385b2f882"> 2634</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597ae5633ec569f4899cf8f29e7385b2f882">VMA_ALLOCATION_CREATE_FLAG_BITS_MAX_ENUM</a> = 0x7FFFFFFF</div>
+<div class="line"><a name="l02635"></a><span class="lineno"> 2635</span>&#160;} <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597">VmaAllocationCreateFlagBits</a>;</div>
+<div class="line"><a name="l02636"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#a5225e5e11f8376f6a31a1791f3d6e817"> 2636</a></span>&#160;<span class="keyword">typedef</span> VkFlags <a class="code" href="vk__mem__alloc_8h.html#a5225e5e11f8376f6a31a1791f3d6e817">VmaAllocationCreateFlags</a>;</div>
+<div class="line"><a name="l02637"></a><span class="lineno"> 2637</span>&#160; </div>
+<div class="line"><a name="l02638"></a><span class="lineno"><a class="line" href="struct_vma_allocation_create_info.html"> 2638</a></span>&#160;<span class="keyword">typedef</span> <span class="keyword">struct </span><a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a></div>
+<div class="line"><a name="l02639"></a><span class="lineno"> 2639</span>&#160;{</div>
+<div class="line"><a name="l02641"></a><span class="lineno"><a class="line" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b"> 2641</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#a5225e5e11f8376f6a31a1791f3d6e817">VmaAllocationCreateFlags</a> <a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a>;</div>
+<div class="line"><a name="l02647"></a><span class="lineno"><a class="line" href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910"> 2647</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cc">VmaMemoryUsage</a> <a class="code" href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910">usage</a>;</div>
+<div class="line"><a name="l02652"></a><span class="lineno"><a class="line" href="struct_vma_allocation_create_info.html#a9166390303ff42d783305bc31c2b6b90"> 2652</a></span>&#160;    VkMemoryPropertyFlags <a class="code" href="struct_vma_allocation_create_info.html#a9166390303ff42d783305bc31c2b6b90">requiredFlags</a>;</div>
+<div class="line"><a name="l02657"></a><span class="lineno"><a class="line" href="struct_vma_allocation_create_info.html#a7fe8d81a1ad10b2a2faacacee5b15d6d"> 2657</a></span>&#160;    VkMemoryPropertyFlags <a class="code" href="struct_vma_allocation_create_info.html#a7fe8d81a1ad10b2a2faacacee5b15d6d">preferredFlags</a>;</div>
+<div class="line"><a name="l02665"></a><span class="lineno"><a class="line" href="struct_vma_allocation_create_info.html#a3bf940c0271d85d6ba32a4d820075055"> 2665</a></span>&#160;    uint32_t <a class="code" href="struct_vma_allocation_create_info.html#a3bf940c0271d85d6ba32a4d820075055">memoryTypeBits</a>;</div>
+<div class="line"><a name="l02671"></a><span class="lineno"><a class="line" href="struct_vma_allocation_create_info.html#a6272c0555cfd1fe28bff1afeb6190150"> 2671</a></span>&#160;    <a class="code" href="struct_vma_pool.html">VmaPool</a> <a class="code" href="struct_vma_allocation_create_info.html#a6272c0555cfd1fe28bff1afeb6190150">pool</a>;</div>
+<div class="line"><a name="l02678"></a><span class="lineno"><a class="line" href="struct_vma_allocation_create_info.html#a8259e85c272683434f4abb4ddddffe19"> 2678</a></span>&#160;    <span class="keywordtype">void</span>* <a class="code" href="struct_vma_allocation_create_info.html#a8259e85c272683434f4abb4ddddffe19">pUserData</a>;</div>
+<div class="line"><a name="l02679"></a><span class="lineno"> 2679</span>&#160;} <a class="code" href="vk__mem__alloc_8h.html#a3bf110892ea2fb4649fedb68488d026a">VmaAllocationCreateInfo</a>;</div>
+<div class="line"><a name="l02680"></a><span class="lineno"> 2680</span>&#160; </div>
+<div class="line"><a name="l02697"></a><span class="lineno"> 2697</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#aef15a94b58fbcb0fe706d5720e84a74a">vmaFindMemoryTypeIndex</a>(</div>
+<div class="line"><a name="l02698"></a><span class="lineno"> 2698</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l02699"></a><span class="lineno"> 2699</span>&#160;    uint32_t memoryTypeBits,</div>
+<div class="line"><a name="l02700"></a><span class="lineno"> 2700</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>* pAllocationCreateInfo,</div>
+<div class="line"><a name="l02701"></a><span class="lineno"> 2701</span>&#160;    uint32_t* pMemoryTypeIndex);</div>
+<div class="line"><a name="l02702"></a><span class="lineno"> 2702</span>&#160; </div>
+<div class="line"><a name="l02715"></a><span class="lineno"> 2715</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#ae790ab9ffaf7667fb8f62523e6897888">vmaFindMemoryTypeIndexForBufferInfo</a>(</div>
+<div class="line"><a name="l02716"></a><span class="lineno"> 2716</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l02717"></a><span class="lineno"> 2717</span>&#160;    <span class="keyword">const</span> VkBufferCreateInfo* pBufferCreateInfo,</div>
+<div class="line"><a name="l02718"></a><span class="lineno"> 2718</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>* pAllocationCreateInfo,</div>
+<div class="line"><a name="l02719"></a><span class="lineno"> 2719</span>&#160;    uint32_t* pMemoryTypeIndex);</div>
+<div class="line"><a name="l02720"></a><span class="lineno"> 2720</span>&#160; </div>
+<div class="line"><a name="l02733"></a><span class="lineno"> 2733</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a088da83d8eaf3ce9056d9ea0b981d472">vmaFindMemoryTypeIndexForImageInfo</a>(</div>
+<div class="line"><a name="l02734"></a><span class="lineno"> 2734</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l02735"></a><span class="lineno"> 2735</span>&#160;    <span class="keyword">const</span> VkImageCreateInfo* pImageCreateInfo,</div>
+<div class="line"><a name="l02736"></a><span class="lineno"> 2736</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>* pAllocationCreateInfo,</div>
+<div class="line"><a name="l02737"></a><span class="lineno"> 2737</span>&#160;    uint32_t* pMemoryTypeIndex);</div>
+<div class="line"><a name="l02738"></a><span class="lineno"> 2738</span>&#160; </div>
+<div class="line"><a name="l02740"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7"> 2740</a></span>&#160;<span class="keyword">typedef</span> <span class="keyword">enum</span> <a class="code" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7">VmaPoolCreateFlagBits</a> {</div>
+<div class="line"><a name="l02758"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a9f1a499508a8edb4e8ba40aa0290a3d2"> 2758</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a9f1a499508a8edb4e8ba40aa0290a3d2">VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT</a> = 0x00000002,</div>
+<div class="line"><a name="l02759"></a><span class="lineno"> 2759</span>&#160; </div>
+<div class="line"><a name="l02775"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a13c8a444197c67866be9cb05599fc726"> 2775</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a13c8a444197c67866be9cb05599fc726">VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT</a> = 0x00000004,</div>
+<div class="line"><a name="l02776"></a><span class="lineno"> 2776</span>&#160; </div>
+<div class="line"><a name="l02786"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a97a0dc38e5161b780594d998d313d35e"> 2786</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a97a0dc38e5161b780594d998d313d35e">VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT</a> = 0x00000008,</div>
+<div class="line"><a name="l02787"></a><span class="lineno"> 2787</span>&#160; </div>
+<div class="line"><a name="l02790"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7af4d270f8f42517a0f70037ceb6ac1d9c"> 2790</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7af4d270f8f42517a0f70037ceb6ac1d9c">VMA_POOL_CREATE_ALGORITHM_MASK</a> =</div>
+<div class="line"><a name="l02791"></a><span class="lineno"> 2791</span>&#160;        <a class="code" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a13c8a444197c67866be9cb05599fc726">VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT</a> |</div>
+<div class="line"><a name="l02792"></a><span class="lineno"> 2792</span>&#160;        <a class="code" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a97a0dc38e5161b780594d998d313d35e">VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT</a>,</div>
+<div class="line"><a name="l02793"></a><span class="lineno"> 2793</span>&#160; </div>
+<div class="line"><a name="l02794"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a1c7312bea9ea246846b9054fd6bd6aec"> 2794</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a1c7312bea9ea246846b9054fd6bd6aec">VMA_POOL_CREATE_FLAG_BITS_MAX_ENUM</a> = 0x7FFFFFFF</div>
+<div class="line"><a name="l02795"></a><span class="lineno"> 2795</span>&#160;} <a class="code" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7">VmaPoolCreateFlagBits</a>;</div>
+<div class="line"><a name="l02796"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#a2770e325ea42e087c1b91fdf46d0292a"> 2796</a></span>&#160;<span class="keyword">typedef</span> VkFlags <a class="code" href="vk__mem__alloc_8h.html#a2770e325ea42e087c1b91fdf46d0292a">VmaPoolCreateFlags</a>;</div>
+<div class="line"><a name="l02797"></a><span class="lineno"> 2797</span>&#160; </div>
+<div class="line"><a name="l02800"></a><span class="lineno"><a class="line" href="struct_vma_pool_create_info.html"> 2800</a></span>&#160;<span class="keyword">typedef</span> <span class="keyword">struct </span><a class="code" href="struct_vma_pool_create_info.html">VmaPoolCreateInfo</a> {</div>
+<div class="line"><a name="l02803"></a><span class="lineno"><a class="line" href="struct_vma_pool_create_info.html#a596fa76b685d3f1f688f84a709a5b319"> 2803</a></span>&#160;    uint32_t <a class="code" href="struct_vma_pool_create_info.html#a596fa76b685d3f1f688f84a709a5b319">memoryTypeIndex</a>;</div>
+<div class="line"><a name="l02806"></a><span class="lineno"><a class="line" href="struct_vma_pool_create_info.html#a8405139f63d078340ae74513a59f5446"> 2806</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#a2770e325ea42e087c1b91fdf46d0292a">VmaPoolCreateFlags</a> <a class="code" href="struct_vma_pool_create_info.html#a8405139f63d078340ae74513a59f5446">flags</a>;</div>
+<div class="line"><a name="l02815"></a><span class="lineno"><a class="line" href="struct_vma_pool_create_info.html#aa4265160536cdb9be821b7686c16c676"> 2815</a></span>&#160;    VkDeviceSize <a class="code" href="struct_vma_pool_create_info.html#aa4265160536cdb9be821b7686c16c676">blockSize</a>;</div>
+<div class="line"><a name="l02820"></a><span class="lineno"><a class="line" href="struct_vma_pool_create_info.html#ad8006fb803185c0a699d30f3e9a865ae"> 2820</a></span>&#160;    <span class="keywordtype">size_t</span> <a class="code" href="struct_vma_pool_create_info.html#ad8006fb803185c0a699d30f3e9a865ae">minBlockCount</a>;</div>
+<div class="line"><a name="l02828"></a><span class="lineno"><a class="line" href="struct_vma_pool_create_info.html#ae41142f2834fcdc82baa4883c187b75c"> 2828</a></span>&#160;    <span class="keywordtype">size_t</span> <a class="code" href="struct_vma_pool_create_info.html#ae41142f2834fcdc82baa4883c187b75c">maxBlockCount</a>;</div>
+<div class="line"><a name="l02842"></a><span class="lineno"><a class="line" href="struct_vma_pool_create_info.html#a9437e43ffbb644dbbf7fc4e50cfad6aa"> 2842</a></span>&#160;    uint32_t <a class="code" href="struct_vma_pool_create_info.html#a9437e43ffbb644dbbf7fc4e50cfad6aa">frameInUseCount</a>;</div>
+<div class="line"><a name="l02843"></a><span class="lineno"> 2843</span>&#160;} <a class="code" href="vk__mem__alloc_8h.html#a1017aa83489c0eee8d2163d2bf253f67">VmaPoolCreateInfo</a>;</div>
+<div class="line"><a name="l02844"></a><span class="lineno"> 2844</span>&#160; </div>
+<div class="line"><a name="l02847"></a><span class="lineno"><a class="line" href="struct_vma_pool_stats.html"> 2847</a></span>&#160;<span class="keyword">typedef</span> <span class="keyword">struct </span><a class="code" href="struct_vma_pool_stats.html">VmaPoolStats</a> {</div>
+<div class="line"><a name="l02850"></a><span class="lineno"><a class="line" href="struct_vma_pool_stats.html#a326807b2de2b0931cee4ed9a5f2e420c"> 2850</a></span>&#160;    VkDeviceSize <a class="code" href="struct_vma_pool_stats.html#a326807b2de2b0931cee4ed9a5f2e420c">size</a>;</div>
+<div class="line"><a name="l02853"></a><span class="lineno"><a class="line" href="struct_vma_pool_stats.html#ad7c54874724fce7b06aba526202d82a8"> 2853</a></span>&#160;    VkDeviceSize <a class="code" href="struct_vma_pool_stats.html#ad7c54874724fce7b06aba526202d82a8">unusedSize</a>;</div>
+<div class="line"><a name="l02856"></a><span class="lineno"><a class="line" href="struct_vma_pool_stats.html#ad1924eb54fffa45e9e0e65670c8fe5eb"> 2856</a></span>&#160;    <span class="keywordtype">size_t</span> <a class="code" href="struct_vma_pool_stats.html#ad1924eb54fffa45e9e0e65670c8fe5eb">allocationCount</a>;</div>
+<div class="line"><a name="l02859"></a><span class="lineno"><a class="line" href="struct_vma_pool_stats.html#ae4f3546ffa4d1e598b64d8e6134854f4"> 2859</a></span>&#160;    <span class="keywordtype">size_t</span> <a class="code" href="struct_vma_pool_stats.html#ae4f3546ffa4d1e598b64d8e6134854f4">unusedRangeCount</a>;</div>
+<div class="line"><a name="l02866"></a><span class="lineno"><a class="line" href="struct_vma_pool_stats.html#ab4c8f52dd42ab01998f60f0b6acc722b"> 2866</a></span>&#160;    VkDeviceSize <a class="code" href="struct_vma_pool_stats.html#ab4c8f52dd42ab01998f60f0b6acc722b">unusedRangeSizeMax</a>;</div>
+<div class="line"><a name="l02869"></a><span class="lineno"><a class="line" href="struct_vma_pool_stats.html#aa0b5cb45cef6f18571cefb03b9a230e7"> 2869</a></span>&#160;    <span class="keywordtype">size_t</span> <a class="code" href="struct_vma_pool_stats.html#aa0b5cb45cef6f18571cefb03b9a230e7">blockCount</a>;</div>
+<div class="line"><a name="l02870"></a><span class="lineno"> 2870</span>&#160;} <a class="code" href="vk__mem__alloc_8h.html#a4759a2d9f99c19ba7627553c847132f1">VmaPoolStats</a>;</div>
+<div class="line"><a name="l02871"></a><span class="lineno"> 2871</span>&#160; </div>
+<div class="line"><a name="l02878"></a><span class="lineno"> 2878</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a5c8770ded7c59c8caac6de0c2cb00b50">vmaCreatePool</a>(</div>
+<div class="line"><a name="l02879"></a><span class="lineno"> 2879</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l02880"></a><span class="lineno"> 2880</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_pool_create_info.html">VmaPoolCreateInfo</a>* pCreateInfo,</div>
+<div class="line"><a name="l02881"></a><span class="lineno"> 2881</span>&#160;    <a class="code" href="struct_vma_pool.html">VmaPool</a>* pPool);</div>
+<div class="line"><a name="l02882"></a><span class="lineno"> 2882</span>&#160; </div>
+<div class="line"><a name="l02885"></a><span class="lineno"> 2885</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a5485779c8f1948238fc4e92232fa65e1">vmaDestroyPool</a>(</div>
+<div class="line"><a name="l02886"></a><span class="lineno"> 2886</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l02887"></a><span class="lineno"> 2887</span>&#160;    <a class="code" href="struct_vma_pool.html">VmaPool</a> pool);</div>
+<div class="line"><a name="l02888"></a><span class="lineno"> 2888</span>&#160; </div>
+<div class="line"><a name="l02895"></a><span class="lineno"> 2895</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#ae8bf76997b234ef68aad922616df4153">vmaGetPoolStats</a>(</div>
+<div class="line"><a name="l02896"></a><span class="lineno"> 2896</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l02897"></a><span class="lineno"> 2897</span>&#160;    <a class="code" href="struct_vma_pool.html">VmaPool</a> pool,</div>
+<div class="line"><a name="l02898"></a><span class="lineno"> 2898</span>&#160;    <a class="code" href="struct_vma_pool_stats.html">VmaPoolStats</a>* pPoolStats);</div>
+<div class="line"><a name="l02899"></a><span class="lineno"> 2899</span>&#160; </div>
+<div class="line"><a name="l02906"></a><span class="lineno"> 2906</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a736bd6cbda886f36c891727e73bd4024">vmaMakePoolAllocationsLost</a>(</div>
+<div class="line"><a name="l02907"></a><span class="lineno"> 2907</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l02908"></a><span class="lineno"> 2908</span>&#160;    <a class="code" href="struct_vma_pool.html">VmaPool</a> pool,</div>
+<div class="line"><a name="l02909"></a><span class="lineno"> 2909</span>&#160;    <span class="keywordtype">size_t</span>* pLostAllocationCount);</div>
+<div class="line"><a name="l02910"></a><span class="lineno"> 2910</span>&#160; </div>
+<div class="line"><a name="l02925"></a><span class="lineno"> 2925</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#ad535935619c7a549bf837e1bb0068f89">vmaCheckPoolCorruption</a>(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator, <a class="code" href="struct_vma_pool.html">VmaPool</a> pool);</div>
+<div class="line"><a name="l02926"></a><span class="lineno"> 2926</span>&#160; </div>
+<div class="line"><a name="l02933"></a><span class="lineno"> 2933</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#af09b4e4eafdbee812e8d73ddf960f030">vmaGetPoolName</a>(</div>
+<div class="line"><a name="l02934"></a><span class="lineno"> 2934</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l02935"></a><span class="lineno"> 2935</span>&#160;    <a class="code" href="struct_vma_pool.html">VmaPool</a> pool,</div>
+<div class="line"><a name="l02936"></a><span class="lineno"> 2936</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">char</span>** ppName);</div>
+<div class="line"><a name="l02937"></a><span class="lineno"> 2937</span>&#160; </div>
+<div class="line"><a name="l02943"></a><span class="lineno"> 2943</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#adbae3a0b4ab078024462fc85c37f3b58">vmaSetPoolName</a>(</div>
+<div class="line"><a name="l02944"></a><span class="lineno"> 2944</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l02945"></a><span class="lineno"> 2945</span>&#160;    <a class="code" href="struct_vma_pool.html">VmaPool</a> pool,</div>
+<div class="line"><a name="l02946"></a><span class="lineno"> 2946</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">char</span>* pName);</div>
+<div class="line"><a name="l02947"></a><span class="lineno"> 2947</span>&#160; </div>
+<div class="line"><a name="l02972"></a><span class="lineno"> 2972</span>&#160;VK_DEFINE_HANDLE(<a class="code" href="struct_vma_allocation.html">VmaAllocation</a>)</div>
+<div class="line"><a name="l02973"></a><span class="lineno"> 2973</span>&#160; </div>
+<div class="line"><a name="l02974"></a><span class="lineno"> 2974</span>&#160; </div>
+<div class="line"><a name="l02976"></a><span class="lineno"><a class="line" href="struct_vma_allocation_info.html"> 2976</a></span>&#160;typedef struct <a class="code" href="struct_vma_allocation_info.html">VmaAllocationInfo</a> {</div>
+<div class="line"><a name="l02981"></a><span class="lineno"><a class="line" href="struct_vma_allocation_info.html#a7f6b0aa58c135e488e6b40a388dad9d5"> 2981</a></span>&#160;    uint32_t <a class="code" href="struct_vma_allocation_info.html#a7f6b0aa58c135e488e6b40a388dad9d5">memoryType</a>;</div>
+<div class="line"><a name="l02990"></a><span class="lineno"><a class="line" href="struct_vma_allocation_info.html#ae0bfb7dfdf79a76ffefc9a94677a2f67"> 2990</a></span>&#160;    VkDeviceMemory <a class="code" href="struct_vma_allocation_info.html#ae0bfb7dfdf79a76ffefc9a94677a2f67">deviceMemory</a>;</div>
+<div class="line"><a name="l02995"></a><span class="lineno"><a class="line" href="struct_vma_allocation_info.html#a4a3c732388dbdc7a23f9365b00825268"> 2995</a></span>&#160;    VkDeviceSize <a class="code" href="struct_vma_allocation_info.html#a4a3c732388dbdc7a23f9365b00825268">offset</a>;</div>
+<div class="line"><a name="l03000"></a><span class="lineno"><a class="line" href="struct_vma_allocation_info.html#aac76d113a6a5ccbb09fea00fb25fd18f"> 3000</a></span>&#160;    VkDeviceSize <a class="code" href="struct_vma_allocation_info.html#aac76d113a6a5ccbb09fea00fb25fd18f">size</a>;</div>
+<div class="line"><a name="l03009"></a><span class="lineno"><a class="line" href="struct_vma_allocation_info.html#a5eeffbe2d2f30f53370ff14aefbadbe2"> 3009</a></span>&#160;    <span class="keywordtype">void</span>* <a class="code" href="struct_vma_allocation_info.html#a5eeffbe2d2f30f53370ff14aefbadbe2">pMappedData</a>;</div>
+<div class="line"><a name="l03014"></a><span class="lineno"><a class="line" href="struct_vma_allocation_info.html#adc507656149c04de7ed95d0042ba2a13"> 3014</a></span>&#160;    <span class="keywordtype">void</span>* <a class="code" href="struct_vma_allocation_info.html#adc507656149c04de7ed95d0042ba2a13">pUserData</a>;</div>
+<div class="line"><a name="l03015"></a><span class="lineno"> 3015</span>&#160;} <a class="code" href="vk__mem__alloc_8h.html#a1cf7774606721026a68aabe3af2e5b50">VmaAllocationInfo</a>;</div>
+<div class="line"><a name="l03016"></a><span class="lineno"> 3016</span>&#160; </div>
+<div class="line"><a name="l03027"></a><span class="lineno"> 3027</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#abf28077dbf82d0908b8acbe8ee8dd9b8">vmaAllocateMemory</a>(</div>
+<div class="line"><a name="l03028"></a><span class="lineno"> 3028</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l03029"></a><span class="lineno"> 3029</span>&#160;    <span class="keyword">const</span> VkMemoryRequirements* pVkMemoryRequirements,</div>
+<div class="line"><a name="l03030"></a><span class="lineno"> 3030</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>* pCreateInfo,</div>
+<div class="line"><a name="l03031"></a><span class="lineno"> 3031</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocation,</div>
+<div class="line"><a name="l03032"></a><span class="lineno"> 3032</span>&#160;    <a class="code" href="struct_vma_allocation_info.html">VmaAllocationInfo</a>* pAllocationInfo);</div>
+<div class="line"><a name="l03033"></a><span class="lineno"> 3033</span>&#160; </div>
+<div class="line"><a name="l03053"></a><span class="lineno"> 3053</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#ad37e82e492b3de38fc3f4cffd9ad0ae1">vmaAllocateMemoryPages</a>(</div>
+<div class="line"><a name="l03054"></a><span class="lineno"> 3054</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l03055"></a><span class="lineno"> 3055</span>&#160;    <span class="keyword">const</span> VkMemoryRequirements* pVkMemoryRequirements,</div>
+<div class="line"><a name="l03056"></a><span class="lineno"> 3056</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>* pCreateInfo,</div>
+<div class="line"><a name="l03057"></a><span class="lineno"> 3057</span>&#160;    <span class="keywordtype">size_t</span> allocationCount,</div>
+<div class="line"><a name="l03058"></a><span class="lineno"> 3058</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocations,</div>
+<div class="line"><a name="l03059"></a><span class="lineno"> 3059</span>&#160;    <a class="code" href="struct_vma_allocation_info.html">VmaAllocationInfo</a>* pAllocationInfo);</div>
+<div class="line"><a name="l03060"></a><span class="lineno"> 3060</span>&#160; </div>
+<div class="line"><a name="l03067"></a><span class="lineno"> 3067</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a7fdf64415b6c3d83c454f28d2c53df7b">vmaAllocateMemoryForBuffer</a>(</div>
+<div class="line"><a name="l03068"></a><span class="lineno"> 3068</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l03069"></a><span class="lineno"> 3069</span>&#160;    VkBuffer buffer,</div>
+<div class="line"><a name="l03070"></a><span class="lineno"> 3070</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>* pCreateInfo,</div>
+<div class="line"><a name="l03071"></a><span class="lineno"> 3071</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocation,</div>
+<div class="line"><a name="l03072"></a><span class="lineno"> 3072</span>&#160;    <a class="code" href="struct_vma_allocation_info.html">VmaAllocationInfo</a>* pAllocationInfo);</div>
+<div class="line"><a name="l03073"></a><span class="lineno"> 3073</span>&#160; </div>
+<div class="line"><a name="l03075"></a><span class="lineno"> 3075</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a0faa3f9e5fb233d29d1e00390650febb">vmaAllocateMemoryForImage</a>(</div>
+<div class="line"><a name="l03076"></a><span class="lineno"> 3076</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l03077"></a><span class="lineno"> 3077</span>&#160;    VkImage image,</div>
+<div class="line"><a name="l03078"></a><span class="lineno"> 3078</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>* pCreateInfo,</div>
+<div class="line"><a name="l03079"></a><span class="lineno"> 3079</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocation,</div>
+<div class="line"><a name="l03080"></a><span class="lineno"> 3080</span>&#160;    <a class="code" href="struct_vma_allocation_info.html">VmaAllocationInfo</a>* pAllocationInfo);</div>
+<div class="line"><a name="l03081"></a><span class="lineno"> 3081</span>&#160; </div>
+<div class="line"><a name="l03086"></a><span class="lineno"> 3086</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a11f0fbc034fa81a4efedd73d61ce7568">vmaFreeMemory</a>(</div>
+<div class="line"><a name="l03087"></a><span class="lineno"> 3087</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l03088"></a><span class="lineno"> 3088</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation);</div>
+<div class="line"><a name="l03089"></a><span class="lineno"> 3089</span>&#160; </div>
+<div class="line"><a name="l03100"></a><span class="lineno"> 3100</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#ab9e709de044c5d8476bea77a4e755840">vmaFreeMemoryPages</a>(</div>
+<div class="line"><a name="l03101"></a><span class="lineno"> 3101</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l03102"></a><span class="lineno"> 3102</span>&#160;    <span class="keywordtype">size_t</span> allocationCount,</div>
+<div class="line"><a name="l03103"></a><span class="lineno"> 3103</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocations);</div>
+<div class="line"><a name="l03104"></a><span class="lineno"> 3104</span>&#160; </div>
+<div class="line"><a name="l03112"></a><span class="lineno"> 3112</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a0ff488958ca72b28e545880463cb8696">vmaResizeAllocation</a>(</div>
+<div class="line"><a name="l03113"></a><span class="lineno"> 3113</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l03114"></a><span class="lineno"> 3114</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation,</div>
+<div class="line"><a name="l03115"></a><span class="lineno"> 3115</span>&#160;    VkDeviceSize newSize);</div>
+<div class="line"><a name="l03116"></a><span class="lineno"> 3116</span>&#160; </div>
+<div class="line"><a name="l03133"></a><span class="lineno"> 3133</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b">vmaGetAllocationInfo</a>(</div>
+<div class="line"><a name="l03134"></a><span class="lineno"> 3134</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l03135"></a><span class="lineno"> 3135</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation,</div>
+<div class="line"><a name="l03136"></a><span class="lineno"> 3136</span>&#160;    <a class="code" href="struct_vma_allocation_info.html">VmaAllocationInfo</a>* pAllocationInfo);</div>
+<div class="line"><a name="l03137"></a><span class="lineno"> 3137</span>&#160; </div>
+<div class="line"><a name="l03152"></a><span class="lineno"> 3152</span>&#160;VMA_CALL_PRE VkBool32 VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a43d8ba9673c846f049089a5029d5c73a">vmaTouchAllocation</a>(</div>
+<div class="line"><a name="l03153"></a><span class="lineno"> 3153</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l03154"></a><span class="lineno"> 3154</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation);</div>
+<div class="line"><a name="l03155"></a><span class="lineno"> 3155</span>&#160; </div>
+<div class="line"><a name="l03169"></a><span class="lineno"> 3169</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#af9147d31ffc11d62fc187bde283ed14f">vmaSetAllocationUserData</a>(</div>
+<div class="line"><a name="l03170"></a><span class="lineno"> 3170</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l03171"></a><span class="lineno"> 3171</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation,</div>
+<div class="line"><a name="l03172"></a><span class="lineno"> 3172</span>&#160;    <span class="keywordtype">void</span>* pUserData);</div>
+<div class="line"><a name="l03173"></a><span class="lineno"> 3173</span>&#160; </div>
+<div class="line"><a name="l03184"></a><span class="lineno"> 3184</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#ae5c9657d9e94756269145b01c05d16f1">vmaCreateLostAllocation</a>(</div>
+<div class="line"><a name="l03185"></a><span class="lineno"> 3185</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l03186"></a><span class="lineno"> 3186</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocation);</div>
+<div class="line"><a name="l03187"></a><span class="lineno"> 3187</span>&#160; </div>
+<div class="line"><a name="l03226"></a><span class="lineno"> 3226</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#ad5bd1243512d099706de88168992f069">vmaMapMemory</a>(</div>
+<div class="line"><a name="l03227"></a><span class="lineno"> 3227</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l03228"></a><span class="lineno"> 3228</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation,</div>
+<div class="line"><a name="l03229"></a><span class="lineno"> 3229</span>&#160;    <span class="keywordtype">void</span>** ppData);</div>
+<div class="line"><a name="l03230"></a><span class="lineno"> 3230</span>&#160; </div>
+<div class="line"><a name="l03239"></a><span class="lineno"> 3239</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a9bc268595cb33f6ec4d519cfce81ff45">vmaUnmapMemory</a>(</div>
+<div class="line"><a name="l03240"></a><span class="lineno"> 3240</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l03241"></a><span class="lineno"> 3241</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation);</div>
+<div class="line"><a name="l03242"></a><span class="lineno"> 3242</span>&#160; </div>
+<div class="line"><a name="l03261"></a><span class="lineno"> 3261</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#abc34ee6f021f459aff885f3758c435de">vmaFlushAllocation</a>(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator, <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation, VkDeviceSize offset, VkDeviceSize size);</div>
+<div class="line"><a name="l03262"></a><span class="lineno"> 3262</span>&#160; </div>
+<div class="line"><a name="l03281"></a><span class="lineno"> 3281</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a0d0eb0c1102268fa9a476d12ecbe4006">vmaInvalidateAllocation</a>(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator, <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation, VkDeviceSize offset, VkDeviceSize size);</div>
+<div class="line"><a name="l03282"></a><span class="lineno"> 3282</span>&#160; </div>
+<div class="line"><a name="l03299"></a><span class="lineno"> 3299</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a49329a7f030dafcf82f7b73334c22e98">vmaCheckCorruption</a>(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator, uint32_t memoryTypeBits);</div>
+<div class="line"><a name="l03300"></a><span class="lineno"> 3300</span>&#160; </div>
+<div class="line"><a name="l03307"></a><span class="lineno"> 3307</span>&#160;VK_DEFINE_HANDLE(<a class="code" href="struct_vma_defragmentation_context.html">VmaDefragmentationContext</a>)</div>
+<div class="line"><a name="l03308"></a><span class="lineno"> 3308</span>&#160; </div>
+<div class="line"><a name="l03309"></a><span class="lineno"> 3309</span>&#160;<span class="keyword">typedef</span> <span class="keyword">enum</span> <a class="code" href="vk__mem__alloc_8h.html#a6552a65b71d16f378c6994b3ceaef50c">VmaDefragmentationFlagBits</a> {</div>
+<div class="line"><a name="l03311"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#a6552a65b71d16f378c6994b3ceaef50ca31af49446af2459284a568ce2f3fdd33"> 3311</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#a6552a65b71d16f378c6994b3ceaef50ca31af49446af2459284a568ce2f3fdd33">VMA_DEFRAGMENTATION_FLAG_INCREMENTAL</a> = 0x1,</div>
+<div class="line"><a name="l03312"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#a6552a65b71d16f378c6994b3ceaef50cab87ec33154803bfeb5ac2b379f1d6a97"> 3312</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#a6552a65b71d16f378c6994b3ceaef50cab87ec33154803bfeb5ac2b379f1d6a97">VMA_DEFRAGMENTATION_FLAG_BITS_MAX_ENUM</a> = 0x7FFFFFFF</div>
+<div class="line"><a name="l03313"></a><span class="lineno"> 3313</span>&#160;} <a class="code" href="vk__mem__alloc_8h.html#a6552a65b71d16f378c6994b3ceaef50c">VmaDefragmentationFlagBits</a>;</div>
+<div class="line"><a name="l03314"></a><span class="lineno"><a class="line" href="vk__mem__alloc_8h.html#a88a77cef37e5d3c4fc9eb328885d048d"> 3314</a></span>&#160;<span class="keyword">typedef</span> VkFlags <a class="code" href="vk__mem__alloc_8h.html#a88a77cef37e5d3c4fc9eb328885d048d">VmaDefragmentationFlags</a>;</div>
+<div class="line"><a name="l03315"></a><span class="lineno"> 3315</span>&#160; </div>
+<div class="line"><a name="l03320"></a><span class="lineno"><a class="line" href="struct_vma_defragmentation_info2.html"> 3320</a></span>&#160;<span class="keyword">typedef</span> <span class="keyword">struct </span><a class="code" href="struct_vma_defragmentation_info2.html">VmaDefragmentationInfo2</a> {</div>
+<div class="line"><a name="l03323"></a><span class="lineno"><a class="line" href="struct_vma_defragmentation_info2.html#a53e844ee5633e229cf6daf14b2d9fff9"> 3323</a></span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#a88a77cef37e5d3c4fc9eb328885d048d">VmaDefragmentationFlags</a> <a class="code" href="struct_vma_defragmentation_info2.html#a53e844ee5633e229cf6daf14b2d9fff9">flags</a>;</div>
+<div class="line"><a name="l03326"></a><span class="lineno"><a class="line" href="struct_vma_defragmentation_info2.html#a3cf86ab32c1da779b4923d301a3056ba"> 3326</a></span>&#160;    uint32_t <a class="code" href="struct_vma_defragmentation_info2.html#a3cf86ab32c1da779b4923d301a3056ba">allocationCount</a>;</div>
+<div class="line"><a name="l03335"></a><span class="lineno"><a class="line" href="struct_vma_defragmentation_info2.html#a8943f8d65969ce8e2189a1cdf3205e96"> 3335</a></span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* <a class="code" href="struct_vma_defragmentation_info2.html#a8943f8d65969ce8e2189a1cdf3205e96">pAllocations</a>;</div>
+<div class="line"><a name="l03341"></a><span class="lineno"><a class="line" href="struct_vma_defragmentation_info2.html#a76d51a644dc7f5405d0cdd0025ecd0cc"> 3341</a></span>&#160;    VkBool32* <a class="code" href="struct_vma_defragmentation_info2.html#a76d51a644dc7f5405d0cdd0025ecd0cc">pAllocationsChanged</a>;</div>
+<div class="line"><a name="l03344"></a><span class="lineno"><a class="line" href="struct_vma_defragmentation_info2.html#a7e70aa2a1081d849dcc7829b19d3ec9d"> 3344</a></span>&#160;    uint32_t <a class="code" href="struct_vma_defragmentation_info2.html#a7e70aa2a1081d849dcc7829b19d3ec9d">poolCount</a>;</div>
+<div class="line"><a name="l03360"></a><span class="lineno"><a class="line" href="struct_vma_defragmentation_info2.html#a0b3effd57f3fcdeb2ed62210b4ef20e1"> 3360</a></span>&#160;    <a class="code" href="struct_vma_pool.html">VmaPool</a>* <a class="code" href="struct_vma_defragmentation_info2.html#a0b3effd57f3fcdeb2ed62210b4ef20e1">pPools</a>;</div>
+<div class="line"><a name="l03365"></a><span class="lineno"><a class="line" href="struct_vma_defragmentation_info2.html#af78e1ea40c22d85137b65f6b384a4d0a"> 3365</a></span>&#160;    VkDeviceSize <a class="code" href="struct_vma_defragmentation_info2.html#af78e1ea40c22d85137b65f6b384a4d0a">maxCpuBytesToMove</a>;</div>
+<div class="line"><a name="l03370"></a><span class="lineno"><a class="line" href="struct_vma_defragmentation_info2.html#a94c2c7223d52878445a8cccce396b671"> 3370</a></span>&#160;    uint32_t <a class="code" href="struct_vma_defragmentation_info2.html#a94c2c7223d52878445a8cccce396b671">maxCpuAllocationsToMove</a>;</div>
+<div class="line"><a name="l03375"></a><span class="lineno"><a class="line" href="struct_vma_defragmentation_info2.html#a4ddbc898d0afe1518f863a3763628f08"> 3375</a></span>&#160;    VkDeviceSize <a class="code" href="struct_vma_defragmentation_info2.html#a4ddbc898d0afe1518f863a3763628f08">maxGpuBytesToMove</a>;</div>
+<div class="line"><a name="l03380"></a><span class="lineno"><a class="line" href="struct_vma_defragmentation_info2.html#a40d53d33e71ba0b66f844ed63c05a3f6"> 3380</a></span>&#160;    uint32_t <a class="code" href="struct_vma_defragmentation_info2.html#a40d53d33e71ba0b66f844ed63c05a3f6">maxGpuAllocationsToMove</a>;</div>
+<div class="line"><a name="l03389"></a><span class="lineno"><a class="line" href="struct_vma_defragmentation_info2.html#a7f71f39590c5316771493d2333f9c1bd"> 3389</a></span>&#160;    VkCommandBuffer <a class="code" href="struct_vma_defragmentation_info2.html#a7f71f39590c5316771493d2333f9c1bd">commandBuffer</a>;</div>
+<div class="line"><a name="l03390"></a><span class="lineno"> 3390</span>&#160;} <a class="code" href="vk__mem__alloc_8h.html#ad6daeffaa670ce6d11a203a6224c9937">VmaDefragmentationInfo2</a>;</div>
+<div class="line"><a name="l03391"></a><span class="lineno"> 3391</span>&#160; </div>
+<div class="line"><a name="l03392"></a><span class="lineno"><a class="line" href="struct_vma_defragmentation_pass_move_info.html"> 3392</a></span>&#160;<span class="keyword">typedef</span> <span class="keyword">struct </span><a class="code" href="struct_vma_defragmentation_pass_move_info.html">VmaDefragmentationPassMoveInfo</a> {</div>
+<div class="line"><a name="l03393"></a><span class="lineno"><a class="line" href="struct_vma_defragmentation_pass_move_info.html#ae885c861c2dd8d622e6c19e281d035cc"> 3393</a></span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> <a class="code" href="struct_vma_defragmentation_pass_move_info.html#ae885c861c2dd8d622e6c19e281d035cc">allocation</a>;</div>
+<div class="line"><a name="l03394"></a><span class="lineno"><a class="line" href="struct_vma_defragmentation_pass_move_info.html#a06eb0c8690aa0d3478a036753492e769"> 3394</a></span>&#160;    VkDeviceMemory <a class="code" href="struct_vma_defragmentation_pass_move_info.html#a06eb0c8690aa0d3478a036753492e769">memory</a>;</div>
+<div class="line"><a name="l03395"></a><span class="lineno"><a class="line" href="struct_vma_defragmentation_pass_move_info.html#a8ab4508bc03625b0653c880576be96c6"> 3395</a></span>&#160;    VkDeviceSize <a class="code" href="struct_vma_defragmentation_pass_move_info.html#a8ab4508bc03625b0653c880576be96c6">offset</a>;</div>
+<div class="line"><a name="l03396"></a><span class="lineno"> 3396</span>&#160;} <a class="code" href="vk__mem__alloc_8h.html#ad6799e8e2b1527abfc84d33bc44aeaf5">VmaDefragmentationPassMoveInfo</a>;</div>
+<div class="line"><a name="l03397"></a><span class="lineno"> 3397</span>&#160; </div>
+<div class="line"><a name="l03402"></a><span class="lineno"><a class="line" href="struct_vma_defragmentation_pass_info.html"> 3402</a></span>&#160;<span class="keyword">typedef</span> <span class="keyword">struct </span><a class="code" href="struct_vma_defragmentation_pass_info.html">VmaDefragmentationPassInfo</a> {</div>
+<div class="line"><a name="l03403"></a><span class="lineno"><a class="line" href="struct_vma_defragmentation_pass_info.html#ac1086e657ba995f8d1f4e49b83dcfb6c"> 3403</a></span>&#160;    uint32_t <a class="code" href="struct_vma_defragmentation_pass_info.html#ac1086e657ba995f8d1f4e49b83dcfb6c">moveCount</a>;</div>
+<div class="line"><a name="l03404"></a><span class="lineno"><a class="line" href="struct_vma_defragmentation_pass_info.html#acbd42d4a3357999da130a95cd99a3792"> 3404</a></span>&#160;    <a class="code" href="struct_vma_defragmentation_pass_move_info.html">VmaDefragmentationPassMoveInfo</a>* <a class="code" href="struct_vma_defragmentation_pass_info.html#acbd42d4a3357999da130a95cd99a3792">pMoves</a>;</div>
+<div class="line"><a name="l03405"></a><span class="lineno"> 3405</span>&#160;} <a class="code" href="vk__mem__alloc_8h.html#a72aebd522242d56abea67b4f47f6549e">VmaDefragmentationPassInfo</a>;</div>
+<div class="line"><a name="l03406"></a><span class="lineno"> 3406</span>&#160; </div>
+<div class="line"><a name="l03411"></a><span class="lineno"><a class="line" href="struct_vma_defragmentation_info.html"> 3411</a></span>&#160;<span class="keyword">typedef</span> <span class="keyword">struct </span><a class="code" href="struct_vma_defragmentation_info.html">VmaDefragmentationInfo</a> {</div>
+<div class="line"><a name="l03416"></a><span class="lineno"><a class="line" href="struct_vma_defragmentation_info.html#acb311c940a777270e67e1b81c5ab6a1d"> 3416</a></span>&#160;    VkDeviceSize <a class="code" href="struct_vma_defragmentation_info.html#acb311c940a777270e67e1b81c5ab6a1d">maxBytesToMove</a>;</div>
+<div class="line"><a name="l03421"></a><span class="lineno"><a class="line" href="struct_vma_defragmentation_info.html#aa7c7304e13c71f604c907196c4e28fbc"> 3421</a></span>&#160;    uint32_t <a class="code" href="struct_vma_defragmentation_info.html#aa7c7304e13c71f604c907196c4e28fbc">maxAllocationsToMove</a>;</div>
+<div class="line"><a name="l03422"></a><span class="lineno"> 3422</span>&#160;} <a class="code" href="vk__mem__alloc_8h.html#a2bf47f96bf92bed2a49461bd9af3acfa">VmaDefragmentationInfo</a>;</div>
+<div class="line"><a name="l03423"></a><span class="lineno"> 3423</span>&#160; </div>
+<div class="line"><a name="l03425"></a><span class="lineno"><a class="line" href="struct_vma_defragmentation_stats.html"> 3425</a></span>&#160;<span class="keyword">typedef</span> <span class="keyword">struct </span><a class="code" href="struct_vma_defragmentation_stats.html">VmaDefragmentationStats</a> {</div>
+<div class="line"><a name="l03427"></a><span class="lineno"><a class="line" href="struct_vma_defragmentation_stats.html#a36f9d5df2a10ba2a36b16e126d60572d"> 3427</a></span>&#160;    VkDeviceSize <a class="code" href="struct_vma_defragmentation_stats.html#a36f9d5df2a10ba2a36b16e126d60572d">bytesMoved</a>;</div>
+<div class="line"><a name="l03429"></a><span class="lineno"><a class="line" href="struct_vma_defragmentation_stats.html#ab0cb9ac0dbc106c77e384ea676422f28"> 3429</a></span>&#160;    VkDeviceSize <a class="code" href="struct_vma_defragmentation_stats.html#ab0cb9ac0dbc106c77e384ea676422f28">bytesFreed</a>;</div>
+<div class="line"><a name="l03431"></a><span class="lineno"><a class="line" href="struct_vma_defragmentation_stats.html#aefeabf130022008eadd75999478af3f9"> 3431</a></span>&#160;    uint32_t <a class="code" href="struct_vma_defragmentation_stats.html#aefeabf130022008eadd75999478af3f9">allocationsMoved</a>;</div>
+<div class="line"><a name="l03433"></a><span class="lineno"><a class="line" href="struct_vma_defragmentation_stats.html#a0113f1877904a5d1ee8f409216ff276b"> 3433</a></span>&#160;    uint32_t <a class="code" href="struct_vma_defragmentation_stats.html#a0113f1877904a5d1ee8f409216ff276b">deviceMemoryBlocksFreed</a>;</div>
+<div class="line"><a name="l03434"></a><span class="lineno"> 3434</span>&#160;} <a class="code" href="vk__mem__alloc_8h.html#ad94034192259c2e34a4d1c5e27810403">VmaDefragmentationStats</a>;</div>
+<div class="line"><a name="l03435"></a><span class="lineno"> 3435</span>&#160; </div>
+<div class="line"><a name="l03465"></a><span class="lineno"> 3465</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a36ba776fd7fd5cb1e9359fdc0d8e6e8a">vmaDefragmentationBegin</a>(</div>
+<div class="line"><a name="l03466"></a><span class="lineno"> 3466</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l03467"></a><span class="lineno"> 3467</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_defragmentation_info2.html">VmaDefragmentationInfo2</a>* pInfo,</div>
+<div class="line"><a name="l03468"></a><span class="lineno"> 3468</span>&#160;    <a class="code" href="struct_vma_defragmentation_stats.html">VmaDefragmentationStats</a>* pStats,</div>
+<div class="line"><a name="l03469"></a><span class="lineno"> 3469</span>&#160;    <a class="code" href="struct_vma_defragmentation_context.html">VmaDefragmentationContext</a> *pContext);</div>
+<div class="line"><a name="l03470"></a><span class="lineno"> 3470</span>&#160; </div>
+<div class="line"><a name="l03476"></a><span class="lineno"> 3476</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a8774e20e91e245aae959ba63efa15dd2">vmaDefragmentationEnd</a>(</div>
+<div class="line"><a name="l03477"></a><span class="lineno"> 3477</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l03478"></a><span class="lineno"> 3478</span>&#160;    <a class="code" href="struct_vma_defragmentation_context.html">VmaDefragmentationContext</a> context);</div>
+<div class="line"><a name="l03479"></a><span class="lineno"> 3479</span>&#160; </div>
+<div class="line"><a name="l03480"></a><span class="lineno"> 3480</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#ac0f01545b6262f7d4d128fc8f8e5c77b">vmaBeginDefragmentationPass</a>(</div>
+<div class="line"><a name="l03481"></a><span class="lineno"> 3481</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l03482"></a><span class="lineno"> 3482</span>&#160;    <a class="code" href="struct_vma_defragmentation_context.html">VmaDefragmentationContext</a> context,</div>
+<div class="line"><a name="l03483"></a><span class="lineno"> 3483</span>&#160;    <a class="code" href="struct_vma_defragmentation_pass_info.html">VmaDefragmentationPassInfo</a>* pInfo</div>
+<div class="line"><a name="l03484"></a><span class="lineno"> 3484</span>&#160;);</div>
+<div class="line"><a name="l03485"></a><span class="lineno"> 3485</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a1b9ffa538bed905af55c747cc48963bd">vmaEndDefragmentationPass</a>(</div>
+<div class="line"><a name="l03486"></a><span class="lineno"> 3486</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l03487"></a><span class="lineno"> 3487</span>&#160;    <a class="code" href="struct_vma_defragmentation_context.html">VmaDefragmentationContext</a> context</div>
+<div class="line"><a name="l03488"></a><span class="lineno"> 3488</span>&#160;);</div>
+<div class="line"><a name="l03489"></a><span class="lineno"> 3489</span>&#160; </div>
+<div class="line"><a name="l03530"></a><span class="lineno"> 3530</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a6aced90fcc7b39882b6654a740a0b9bb">vmaDefragment</a>(</div>
+<div class="line"><a name="l03531"></a><span class="lineno"> 3531</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l03532"></a><span class="lineno"> 3532</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocations,</div>
+<div class="line"><a name="l03533"></a><span class="lineno"> 3533</span>&#160;    <span class="keywordtype">size_t</span> allocationCount,</div>
+<div class="line"><a name="l03534"></a><span class="lineno"> 3534</span>&#160;    VkBool32* pAllocationsChanged,</div>
+<div class="line"><a name="l03535"></a><span class="lineno"> 3535</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_defragmentation_info.html">VmaDefragmentationInfo</a> *pDefragmentationInfo,</div>
+<div class="line"><a name="l03536"></a><span class="lineno"> 3536</span>&#160;    <a class="code" href="struct_vma_defragmentation_stats.html">VmaDefragmentationStats</a>* pDefragmentationStats);</div>
+<div class="line"><a name="l03537"></a><span class="lineno"> 3537</span>&#160; </div>
+<div class="line"><a name="l03550"></a><span class="lineno"> 3550</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a6b0929b914b60cf2d45cac4bf3547470">vmaBindBufferMemory</a>(</div>
+<div class="line"><a name="l03551"></a><span class="lineno"> 3551</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l03552"></a><span class="lineno"> 3552</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation,</div>
+<div class="line"><a name="l03553"></a><span class="lineno"> 3553</span>&#160;    VkBuffer buffer);</div>
+<div class="line"><a name="l03554"></a><span class="lineno"> 3554</span>&#160; </div>
+<div class="line"><a name="l03565"></a><span class="lineno"> 3565</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a927c944f45e0f2941182abb6f608e64a">vmaBindBufferMemory2</a>(</div>
+<div class="line"><a name="l03566"></a><span class="lineno"> 3566</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l03567"></a><span class="lineno"> 3567</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation,</div>
+<div class="line"><a name="l03568"></a><span class="lineno"> 3568</span>&#160;    VkDeviceSize allocationLocalOffset,</div>
+<div class="line"><a name="l03569"></a><span class="lineno"> 3569</span>&#160;    VkBuffer buffer,</div>
+<div class="line"><a name="l03570"></a><span class="lineno"> 3570</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">void</span>* pNext);</div>
+<div class="line"><a name="l03571"></a><span class="lineno"> 3571</span>&#160; </div>
+<div class="line"><a name="l03584"></a><span class="lineno"> 3584</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a3d3ca45799923aa5d138e9e5f9eb2da5">vmaBindImageMemory</a>(</div>
+<div class="line"><a name="l03585"></a><span class="lineno"> 3585</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l03586"></a><span class="lineno"> 3586</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation,</div>
+<div class="line"><a name="l03587"></a><span class="lineno"> 3587</span>&#160;    VkImage image);</div>
+<div class="line"><a name="l03588"></a><span class="lineno"> 3588</span>&#160; </div>
+<div class="line"><a name="l03599"></a><span class="lineno"> 3599</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#aa8251ee81b0045a443e35b8e8aa021bc">vmaBindImageMemory2</a>(</div>
+<div class="line"><a name="l03600"></a><span class="lineno"> 3600</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l03601"></a><span class="lineno"> 3601</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation,</div>
+<div class="line"><a name="l03602"></a><span class="lineno"> 3602</span>&#160;    VkDeviceSize allocationLocalOffset,</div>
+<div class="line"><a name="l03603"></a><span class="lineno"> 3603</span>&#160;    VkImage image,</div>
+<div class="line"><a name="l03604"></a><span class="lineno"> 3604</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">void</span>* pNext);</div>
+<div class="line"><a name="l03605"></a><span class="lineno"> 3605</span>&#160; </div>
+<div class="line"><a name="l03632"></a><span class="lineno"> 3632</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer</a>(</div>
+<div class="line"><a name="l03633"></a><span class="lineno"> 3633</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l03634"></a><span class="lineno"> 3634</span>&#160;    <span class="keyword">const</span> VkBufferCreateInfo* pBufferCreateInfo,</div>
+<div class="line"><a name="l03635"></a><span class="lineno"> 3635</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>* pAllocationCreateInfo,</div>
+<div class="line"><a name="l03636"></a><span class="lineno"> 3636</span>&#160;    VkBuffer* pBuffer,</div>
+<div class="line"><a name="l03637"></a><span class="lineno"> 3637</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocation,</div>
+<div class="line"><a name="l03638"></a><span class="lineno"> 3638</span>&#160;    <a class="code" href="struct_vma_allocation_info.html">VmaAllocationInfo</a>* pAllocationInfo);</div>
+<div class="line"><a name="l03639"></a><span class="lineno"> 3639</span>&#160; </div>
+<div class="line"><a name="l03651"></a><span class="lineno"> 3651</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a0d9f4e4ba5bf9aab1f1c746387753d77">vmaDestroyBuffer</a>(</div>
+<div class="line"><a name="l03652"></a><span class="lineno"> 3652</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l03653"></a><span class="lineno"> 3653</span>&#160;    VkBuffer buffer,</div>
+<div class="line"><a name="l03654"></a><span class="lineno"> 3654</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation);</div>
+<div class="line"><a name="l03655"></a><span class="lineno"> 3655</span>&#160; </div>
+<div class="line"><a name="l03657"></a><span class="lineno"> 3657</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a02a94f25679275851a53e82eacbcfc73">vmaCreateImage</a>(</div>
+<div class="line"><a name="l03658"></a><span class="lineno"> 3658</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l03659"></a><span class="lineno"> 3659</span>&#160;    <span class="keyword">const</span> VkImageCreateInfo* pImageCreateInfo,</div>
+<div class="line"><a name="l03660"></a><span class="lineno"> 3660</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>* pAllocationCreateInfo,</div>
+<div class="line"><a name="l03661"></a><span class="lineno"> 3661</span>&#160;    VkImage* pImage,</div>
+<div class="line"><a name="l03662"></a><span class="lineno"> 3662</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocation,</div>
+<div class="line"><a name="l03663"></a><span class="lineno"> 3663</span>&#160;    <a class="code" href="struct_vma_allocation_info.html">VmaAllocationInfo</a>* pAllocationInfo);</div>
+<div class="line"><a name="l03664"></a><span class="lineno"> 3664</span>&#160; </div>
+<div class="line"><a name="l03676"></a><span class="lineno"> 3676</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#ae50d2cb3b4a3bfd4dd40987234e50e7e">vmaDestroyImage</a>(</div>
+<div class="line"><a name="l03677"></a><span class="lineno"> 3677</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l03678"></a><span class="lineno"> 3678</span>&#160;    VkImage image,</div>
+<div class="line"><a name="l03679"></a><span class="lineno"> 3679</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation);</div>
+<div class="line"><a name="l03680"></a><span class="lineno"> 3680</span>&#160; </div>
+<div class="line"><a name="l03681"></a><span class="lineno"> 3681</span>&#160;<span class="preprocessor">#ifdef __cplusplus</span></div>
+<div class="line"><a name="l03682"></a><span class="lineno"> 3682</span>&#160;}</div>
+<div class="line"><a name="l03683"></a><span class="lineno"> 3683</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l03684"></a><span class="lineno"> 3684</span>&#160; </div>
+<div class="line"><a name="l03685"></a><span class="lineno"> 3685</span>&#160;<span class="preprocessor">#endif // AMD_VULKAN_MEMORY_ALLOCATOR_H</span></div>
+<div class="line"><a name="l03686"></a><span class="lineno"> 3686</span>&#160; </div>
+<div class="line"><a name="l03687"></a><span class="lineno"> 3687</span>&#160;<span class="comment">// For Visual Studio IntelliSense.</span></div>
+<div class="line"><a name="l03688"></a><span class="lineno"> 3688</span>&#160;<span class="preprocessor">#if defined(__cplusplus) &amp;&amp; defined(__INTELLISENSE__)</span></div>
+<div class="line"><a name="l03689"></a><span class="lineno"> 3689</span>&#160;<span class="preprocessor">#define VMA_IMPLEMENTATION</span></div>
+<div class="line"><a name="l03690"></a><span class="lineno"> 3690</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l03691"></a><span class="lineno"> 3691</span>&#160; </div>
+<div class="line"><a name="l03692"></a><span class="lineno"> 3692</span>&#160;<span class="preprocessor">#ifdef VMA_IMPLEMENTATION</span></div>
+<div class="line"><a name="l03693"></a><span class="lineno"> 3693</span>&#160;<span class="preprocessor">#undef VMA_IMPLEMENTATION</span></div>
+<div class="line"><a name="l03694"></a><span class="lineno"> 3694</span>&#160; </div>
+<div class="line"><a name="l03695"></a><span class="lineno"> 3695</span>&#160;<span class="preprocessor">#include &lt;cstdint&gt;</span></div>
+<div class="line"><a name="l03696"></a><span class="lineno"> 3696</span>&#160;<span class="preprocessor">#include &lt;cstdlib&gt;</span></div>
+<div class="line"><a name="l03697"></a><span class="lineno"> 3697</span>&#160;<span class="preprocessor">#include &lt;cstring&gt;</span></div>
+<div class="line"><a name="l03698"></a><span class="lineno"> 3698</span>&#160;<span class="preprocessor">#include &lt;utility&gt;</span></div>
+<div class="line"><a name="l03699"></a><span class="lineno"> 3699</span>&#160; </div>
+<div class="line"><a name="l03700"></a><span class="lineno"> 3700</span>&#160;<span class="comment">/*******************************************************************************</span></div>
+<div class="line"><a name="l03701"></a><span class="lineno"> 3701</span>&#160;<span class="comment">CONFIGURATION SECTION</span></div>
+<div class="line"><a name="l03702"></a><span class="lineno"> 3702</span>&#160;<span class="comment"></span> </div>
+<div class="line"><a name="l03703"></a><span class="lineno"> 3703</span>&#160;<span class="comment">Define some of these macros before each #include of this header or change them</span></div>
+<div class="line"><a name="l03704"></a><span class="lineno"> 3704</span>&#160;<span class="comment">here if you need other then default behavior depending on your environment.</span></div>
+<div class="line"><a name="l03705"></a><span class="lineno"> 3705</span>&#160;<span class="comment">*/</span></div>
+<div class="line"><a name="l03706"></a><span class="lineno"> 3706</span>&#160; </div>
+<div class="line"><a name="l03707"></a><span class="lineno"> 3707</span>&#160;<span class="comment">/*</span></div>
+<div class="line"><a name="l03708"></a><span class="lineno"> 3708</span>&#160;<span class="comment">Define this macro to 1 to make the library fetch pointers to Vulkan functions</span></div>
+<div class="line"><a name="l03709"></a><span class="lineno"> 3709</span>&#160;<span class="comment">internally, like:</span></div>
+<div class="line"><a name="l03710"></a><span class="lineno"> 3710</span>&#160;<span class="comment"></span> </div>
+<div class="line"><a name="l03711"></a><span class="lineno"> 3711</span>&#160;<span class="comment">    vulkanFunctions.vkAllocateMemory = &amp;vkAllocateMemory;</span></div>
+<div class="line"><a name="l03712"></a><span class="lineno"> 3712</span>&#160;<span class="comment">*/</span></div>
+<div class="line"><a name="l03713"></a><span class="lineno"> 3713</span>&#160;<span class="preprocessor">#if !defined(VMA_STATIC_VULKAN_FUNCTIONS) &amp;&amp; !defined(VK_NO_PROTOTYPES)</span></div>
+<div class="line"><a name="l03714"></a><span class="lineno"> 3714</span>&#160;<span class="preprocessor">    #define VMA_STATIC_VULKAN_FUNCTIONS 1</span></div>
+<div class="line"><a name="l03715"></a><span class="lineno"> 3715</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l03716"></a><span class="lineno"> 3716</span>&#160; </div>
+<div class="line"><a name="l03717"></a><span class="lineno"> 3717</span>&#160;<span class="comment">/*</span></div>
+<div class="line"><a name="l03718"></a><span class="lineno"> 3718</span>&#160;<span class="comment">Define this macro to 1 to make the library fetch pointers to Vulkan functions</span></div>
+<div class="line"><a name="l03719"></a><span class="lineno"> 3719</span>&#160;<span class="comment">internally, like:</span></div>
+<div class="line"><a name="l03720"></a><span class="lineno"> 3720</span>&#160;<span class="comment"></span> </div>
+<div class="line"><a name="l03721"></a><span class="lineno"> 3721</span>&#160;<span class="comment">    vulkanFunctions.vkAllocateMemory = (PFN_vkAllocateMemory)vkGetDeviceProcAddr(m_hDevice, vkAllocateMemory);</span></div>
+<div class="line"><a name="l03722"></a><span class="lineno"> 3722</span>&#160;<span class="comment">*/</span></div>
+<div class="line"><a name="l03723"></a><span class="lineno"> 3723</span>&#160;<span class="preprocessor">#if !defined(VMA_DYNAMIC_VULKAN_FUNCTIONS)</span></div>
+<div class="line"><a name="l03724"></a><span class="lineno"> 3724</span>&#160;<span class="preprocessor">    #define VMA_DYNAMIC_VULKAN_FUNCTIONS 1</span></div>
+<div class="line"><a name="l03725"></a><span class="lineno"> 3725</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l03726"></a><span class="lineno"> 3726</span>&#160; </div>
+<div class="line"><a name="l03727"></a><span class="lineno"> 3727</span>&#160;<span class="comment">// Define this macro to 1 to make the library use STL containers instead of its own implementation.</span></div>
+<div class="line"><a name="l03728"></a><span class="lineno"> 3728</span>&#160;<span class="comment">//#define VMA_USE_STL_CONTAINERS 1</span></div>
+<div class="line"><a name="l03729"></a><span class="lineno"> 3729</span>&#160; </div>
+<div class="line"><a name="l03730"></a><span class="lineno"> 3730</span>&#160;<span class="comment">/* Set this macro to 1 to make the library including and using STL containers:</span></div>
+<div class="line"><a name="l03731"></a><span class="lineno"> 3731</span>&#160;<span class="comment">std::pair, std::vector, std::list, std::unordered_map.</span></div>
+<div class="line"><a name="l03732"></a><span class="lineno"> 3732</span>&#160;<span class="comment"></span> </div>
+<div class="line"><a name="l03733"></a><span class="lineno"> 3733</span>&#160;<span class="comment">Set it to 0 or undefined to make the library using its own implementation of</span></div>
+<div class="line"><a name="l03734"></a><span class="lineno"> 3734</span>&#160;<span class="comment">the containers.</span></div>
+<div class="line"><a name="l03735"></a><span class="lineno"> 3735</span>&#160;<span class="comment">*/</span></div>
+<div class="line"><a name="l03736"></a><span class="lineno"> 3736</span>&#160;<span class="preprocessor">#if VMA_USE_STL_CONTAINERS</span></div>
+<div class="line"><a name="l03737"></a><span class="lineno"> 3737</span>&#160;<span class="preprocessor">   #define VMA_USE_STL_VECTOR 1</span></div>
+<div class="line"><a name="l03738"></a><span class="lineno"> 3738</span>&#160;<span class="preprocessor">   #define VMA_USE_STL_UNORDERED_MAP 1</span></div>
+<div class="line"><a name="l03739"></a><span class="lineno"> 3739</span>&#160;<span class="preprocessor">   #define VMA_USE_STL_LIST 1</span></div>
+<div class="line"><a name="l03740"></a><span class="lineno"> 3740</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l03741"></a><span class="lineno"> 3741</span>&#160; </div>
+<div class="line"><a name="l03742"></a><span class="lineno"> 3742</span>&#160;<span class="preprocessor">#ifndef VMA_USE_STL_SHARED_MUTEX</span></div>
+<div class="line"><a name="l03743"></a><span class="lineno"> 3743</span>&#160;    <span class="comment">// Compiler conforms to C++17.</span></div>
+<div class="line"><a name="l03744"></a><span class="lineno"> 3744</span>&#160;<span class="preprocessor">    #if __cplusplus &gt;= 201703L</span></div>
+<div class="line"><a name="l03745"></a><span class="lineno"> 3745</span>&#160;<span class="preprocessor">        #define VMA_USE_STL_SHARED_MUTEX 1</span></div>
+<div class="line"><a name="l03746"></a><span class="lineno"> 3746</span>&#160;    <span class="comment">// Visual studio defines __cplusplus properly only when passed additional parameter: /Zc:__cplusplus</span></div>
+<div class="line"><a name="l03747"></a><span class="lineno"> 3747</span>&#160;    <span class="comment">// Otherwise it&#39;s always 199711L, despite shared_mutex works since Visual Studio 2015 Update 2.</span></div>
+<div class="line"><a name="l03748"></a><span class="lineno"> 3748</span>&#160;    <span class="comment">// See: https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/</span></div>
+<div class="line"><a name="l03749"></a><span class="lineno"> 3749</span>&#160;<span class="preprocessor">    #elif defined(_MSC_FULL_VER) &amp;&amp; _MSC_FULL_VER &gt;= 190023918 &amp;&amp; __cplusplus == 199711L &amp;&amp; _MSVC_LANG &gt;= 201703L</span></div>
+<div class="line"><a name="l03750"></a><span class="lineno"> 3750</span>&#160;<span class="preprocessor">        #define VMA_USE_STL_SHARED_MUTEX 1</span></div>
+<div class="line"><a name="l03751"></a><span class="lineno"> 3751</span>&#160;<span class="preprocessor">    #else</span></div>
+<div class="line"><a name="l03752"></a><span class="lineno"> 3752</span>&#160;<span class="preprocessor">        #define VMA_USE_STL_SHARED_MUTEX 0</span></div>
+<div class="line"><a name="l03753"></a><span class="lineno"> 3753</span>&#160;<span class="preprocessor">    #endif</span></div>
+<div class="line"><a name="l03754"></a><span class="lineno"> 3754</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l03755"></a><span class="lineno"> 3755</span>&#160; </div>
+<div class="line"><a name="l03756"></a><span class="lineno"> 3756</span>&#160;<span class="comment">/*</span></div>
+<div class="line"><a name="l03757"></a><span class="lineno"> 3757</span>&#160;<span class="comment">THESE INCLUDES ARE NOT ENABLED BY DEFAULT.</span></div>
+<div class="line"><a name="l03758"></a><span class="lineno"> 3758</span>&#160;<span class="comment">Library has its own container implementation.</span></div>
+<div class="line"><a name="l03759"></a><span class="lineno"> 3759</span>&#160;<span class="comment">*/</span></div>
+<div class="line"><a name="l03760"></a><span class="lineno"> 3760</span>&#160;<span class="preprocessor">#if VMA_USE_STL_VECTOR</span></div>
+<div class="line"><a name="l03761"></a><span class="lineno"> 3761</span>&#160;<span class="preprocessor">   #include &lt;vector&gt;</span></div>
+<div class="line"><a name="l03762"></a><span class="lineno"> 3762</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l03763"></a><span class="lineno"> 3763</span>&#160; </div>
+<div class="line"><a name="l03764"></a><span class="lineno"> 3764</span>&#160;<span class="preprocessor">#if VMA_USE_STL_UNORDERED_MAP</span></div>
+<div class="line"><a name="l03765"></a><span class="lineno"> 3765</span>&#160;<span class="preprocessor">   #include &lt;unordered_map&gt;</span></div>
+<div class="line"><a name="l03766"></a><span class="lineno"> 3766</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l03767"></a><span class="lineno"> 3767</span>&#160; </div>
+<div class="line"><a name="l03768"></a><span class="lineno"> 3768</span>&#160;<span class="preprocessor">#if VMA_USE_STL_LIST</span></div>
+<div class="line"><a name="l03769"></a><span class="lineno"> 3769</span>&#160;<span class="preprocessor">   #include &lt;list&gt;</span></div>
+<div class="line"><a name="l03770"></a><span class="lineno"> 3770</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l03771"></a><span class="lineno"> 3771</span>&#160; </div>
+<div class="line"><a name="l03772"></a><span class="lineno"> 3772</span>&#160;<span class="comment">/*</span></div>
+<div class="line"><a name="l03773"></a><span class="lineno"> 3773</span>&#160;<span class="comment">Following headers are used in this CONFIGURATION section only, so feel free to</span></div>
+<div class="line"><a name="l03774"></a><span class="lineno"> 3774</span>&#160;<span class="comment">remove them if not needed.</span></div>
+<div class="line"><a name="l03775"></a><span class="lineno"> 3775</span>&#160;<span class="comment">*/</span></div>
+<div class="line"><a name="l03776"></a><span class="lineno"> 3776</span>&#160;<span class="preprocessor">#include &lt;cassert&gt;</span> <span class="comment">// for assert</span></div>
+<div class="line"><a name="l03777"></a><span class="lineno"> 3777</span>&#160;<span class="preprocessor">#include &lt;algorithm&gt;</span> <span class="comment">// for min, max</span></div>
+<div class="line"><a name="l03778"></a><span class="lineno"> 3778</span>&#160;<span class="preprocessor">#include &lt;mutex&gt;</span></div>
+<div class="line"><a name="l03779"></a><span class="lineno"> 3779</span>&#160; </div>
+<div class="line"><a name="l03780"></a><span class="lineno"> 3780</span>&#160;<span class="preprocessor">#ifndef VMA_NULL</span></div>
+<div class="line"><a name="l03781"></a><span class="lineno"> 3781</span>&#160;   <span class="comment">// Value used as null pointer. Define it to e.g.: nullptr, NULL, 0, (void*)0.</span></div>
+<div class="line"><a name="l03782"></a><span class="lineno"> 3782</span>&#160;<span class="preprocessor">   #define VMA_NULL   nullptr</span></div>
+<div class="line"><a name="l03783"></a><span class="lineno"> 3783</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l03784"></a><span class="lineno"> 3784</span>&#160; </div>
+<div class="line"><a name="l03785"></a><span class="lineno"> 3785</span>&#160;<span class="preprocessor">#if defined(__ANDROID_API__) &amp;&amp; (__ANDROID_API__ &lt; 16)</span></div>
+<div class="line"><a name="l03786"></a><span class="lineno"> 3786</span>&#160;<span class="preprocessor">#include &lt;cstdlib&gt;</span></div>
+<div class="line"><a name="l03787"></a><span class="lineno"> 3787</span>&#160;<span class="keywordtype">void</span> *aligned_alloc(<span class="keywordtype">size_t</span> alignment, <span class="keywordtype">size_t</span> size)</div>
+<div class="line"><a name="l03788"></a><span class="lineno"> 3788</span>&#160;{</div>
+<div class="line"><a name="l03789"></a><span class="lineno"> 3789</span>&#160;    <span class="comment">// alignment must be &gt;= sizeof(void*)</span></div>
+<div class="line"><a name="l03790"></a><span class="lineno"> 3790</span>&#160;    <span class="keywordflow">if</span>(alignment &lt; <span class="keyword">sizeof</span>(<span class="keywordtype">void</span>*))</div>
+<div class="line"><a name="l03791"></a><span class="lineno"> 3791</span>&#160;    {</div>
+<div class="line"><a name="l03792"></a><span class="lineno"> 3792</span>&#160;        alignment = <span class="keyword">sizeof</span>(<span class="keywordtype">void</span>*);</div>
+<div class="line"><a name="l03793"></a><span class="lineno"> 3793</span>&#160;    }</div>
+<div class="line"><a name="l03794"></a><span class="lineno"> 3794</span>&#160; </div>
+<div class="line"><a name="l03795"></a><span class="lineno"> 3795</span>&#160;    <span class="keywordflow">return</span> memalign(alignment, size);</div>
+<div class="line"><a name="l03796"></a><span class="lineno"> 3796</span>&#160;}</div>
+<div class="line"><a name="l03797"></a><span class="lineno"> 3797</span>&#160;<span class="preprocessor">#elif defined(__APPLE__) || defined(__ANDROID__) || (defined(__linux__) &amp;&amp; defined(__GLIBCXX__) &amp;&amp; !defined(_GLIBCXX_HAVE_ALIGNED_ALLOC))</span></div>
+<div class="line"><a name="l03798"></a><span class="lineno"> 3798</span>&#160;<span class="preprocessor">#include &lt;cstdlib&gt;</span></div>
+<div class="line"><a name="l03799"></a><span class="lineno"> 3799</span>&#160;<span class="keywordtype">void</span> *aligned_alloc(<span class="keywordtype">size_t</span> alignment, <span class="keywordtype">size_t</span> size)</div>
+<div class="line"><a name="l03800"></a><span class="lineno"> 3800</span>&#160;{</div>
+<div class="line"><a name="l03801"></a><span class="lineno"> 3801</span>&#160;    <span class="comment">// alignment must be &gt;= sizeof(void*)</span></div>
+<div class="line"><a name="l03802"></a><span class="lineno"> 3802</span>&#160;    <span class="keywordflow">if</span>(alignment &lt; <span class="keyword">sizeof</span>(<span class="keywordtype">void</span>*))</div>
+<div class="line"><a name="l03803"></a><span class="lineno"> 3803</span>&#160;    {</div>
+<div class="line"><a name="l03804"></a><span class="lineno"> 3804</span>&#160;        alignment = <span class="keyword">sizeof</span>(<span class="keywordtype">void</span>*);</div>
+<div class="line"><a name="l03805"></a><span class="lineno"> 3805</span>&#160;    }</div>
+<div class="line"><a name="l03806"></a><span class="lineno"> 3806</span>&#160; </div>
+<div class="line"><a name="l03807"></a><span class="lineno"> 3807</span>&#160;    <span class="keywordtype">void</span> *pointer;</div>
+<div class="line"><a name="l03808"></a><span class="lineno"> 3808</span>&#160;    <span class="keywordflow">if</span>(posix_memalign(&amp;pointer, alignment, size) == 0)</div>
+<div class="line"><a name="l03809"></a><span class="lineno"> 3809</span>&#160;        <span class="keywordflow">return</span> pointer;</div>
+<div class="line"><a name="l03810"></a><span class="lineno"> 3810</span>&#160;    <span class="keywordflow">return</span> VMA_NULL;</div>
+<div class="line"><a name="l03811"></a><span class="lineno"> 3811</span>&#160;}</div>
+<div class="line"><a name="l03812"></a><span class="lineno"> 3812</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l03813"></a><span class="lineno"> 3813</span>&#160; </div>
+<div class="line"><a name="l03814"></a><span class="lineno"> 3814</span>&#160;<span class="comment">// If your compiler is not compatible with C++11 and definition of</span></div>
+<div class="line"><a name="l03815"></a><span class="lineno"> 3815</span>&#160;<span class="comment">// aligned_alloc() function is missing, uncommeting following line may help:</span></div>
+<div class="line"><a name="l03816"></a><span class="lineno"> 3816</span>&#160; </div>
+<div class="line"><a name="l03817"></a><span class="lineno"> 3817</span>&#160;<span class="comment">//#include &lt;malloc.h&gt;</span></div>
+<div class="line"><a name="l03818"></a><span class="lineno"> 3818</span>&#160; </div>
+<div class="line"><a name="l03819"></a><span class="lineno"> 3819</span>&#160;<span class="comment">// Normal assert to check for programmer&#39;s errors, especially in Debug configuration.</span></div>
+<div class="line"><a name="l03820"></a><span class="lineno"> 3820</span>&#160;<span class="preprocessor">#ifndef VMA_ASSERT</span></div>
+<div class="line"><a name="l03821"></a><span class="lineno"> 3821</span>&#160;<span class="preprocessor">   #ifdef NDEBUG</span></div>
+<div class="line"><a name="l03822"></a><span class="lineno"> 3822</span>&#160;<span class="preprocessor">       #define VMA_ASSERT(expr)</span></div>
+<div class="line"><a name="l03823"></a><span class="lineno"> 3823</span>&#160;<span class="preprocessor">   #else</span></div>
+<div class="line"><a name="l03824"></a><span class="lineno"> 3824</span>&#160;<span class="preprocessor">       #define VMA_ASSERT(expr)         assert(expr)</span></div>
+<div class="line"><a name="l03825"></a><span class="lineno"> 3825</span>&#160;<span class="preprocessor">   #endif</span></div>
+<div class="line"><a name="l03826"></a><span class="lineno"> 3826</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l03827"></a><span class="lineno"> 3827</span>&#160; </div>
+<div class="line"><a name="l03828"></a><span class="lineno"> 3828</span>&#160;<span class="comment">// Assert that will be called very often, like inside data structures e.g. operator[].</span></div>
+<div class="line"><a name="l03829"></a><span class="lineno"> 3829</span>&#160;<span class="comment">// Making it non-empty can make program slow.</span></div>
+<div class="line"><a name="l03830"></a><span class="lineno"> 3830</span>&#160;<span class="preprocessor">#ifndef VMA_HEAVY_ASSERT</span></div>
+<div class="line"><a name="l03831"></a><span class="lineno"> 3831</span>&#160;<span class="preprocessor">   #ifdef NDEBUG</span></div>
+<div class="line"><a name="l03832"></a><span class="lineno"> 3832</span>&#160;<span class="preprocessor">       #define VMA_HEAVY_ASSERT(expr)</span></div>
+<div class="line"><a name="l03833"></a><span class="lineno"> 3833</span>&#160;<span class="preprocessor">   #else</span></div>
+<div class="line"><a name="l03834"></a><span class="lineno"> 3834</span>&#160;<span class="preprocessor">       #define VMA_HEAVY_ASSERT(expr)   //VMA_ASSERT(expr)</span></div>
+<div class="line"><a name="l03835"></a><span class="lineno"> 3835</span>&#160;<span class="preprocessor">   #endif</span></div>
+<div class="line"><a name="l03836"></a><span class="lineno"> 3836</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l03837"></a><span class="lineno"> 3837</span>&#160; </div>
+<div class="line"><a name="l03838"></a><span class="lineno"> 3838</span>&#160;<span class="preprocessor">#ifndef VMA_ALIGN_OF</span></div>
+<div class="line"><a name="l03839"></a><span class="lineno"> 3839</span>&#160;<span class="preprocessor">   #define VMA_ALIGN_OF(type)       (__alignof(type))</span></div>
+<div class="line"><a name="l03840"></a><span class="lineno"> 3840</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l03841"></a><span class="lineno"> 3841</span>&#160; </div>
+<div class="line"><a name="l03842"></a><span class="lineno"> 3842</span>&#160;<span class="preprocessor">#ifndef VMA_SYSTEM_ALIGNED_MALLOC</span></div>
+<div class="line"><a name="l03843"></a><span class="lineno"> 3843</span>&#160;<span class="preprocessor">   #if defined(_WIN32)</span></div>
+<div class="line"><a name="l03844"></a><span class="lineno"> 3844</span>&#160;<span class="preprocessor">       #define VMA_SYSTEM_ALIGNED_MALLOC(size, alignment)   (_aligned_malloc((size), (alignment)))</span></div>
+<div class="line"><a name="l03845"></a><span class="lineno"> 3845</span>&#160;<span class="preprocessor">   #else</span></div>
+<div class="line"><a name="l03846"></a><span class="lineno"> 3846</span>&#160;<span class="preprocessor">       #define VMA_SYSTEM_ALIGNED_MALLOC(size, alignment)   (aligned_alloc((alignment), (size) ))</span></div>
+<div class="line"><a name="l03847"></a><span class="lineno"> 3847</span>&#160;<span class="preprocessor">   #endif</span></div>
+<div class="line"><a name="l03848"></a><span class="lineno"> 3848</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l03849"></a><span class="lineno"> 3849</span>&#160; </div>
+<div class="line"><a name="l03850"></a><span class="lineno"> 3850</span>&#160;<span class="preprocessor">#ifndef VMA_SYSTEM_FREE</span></div>
+<div class="line"><a name="l03851"></a><span class="lineno"> 3851</span>&#160;<span class="preprocessor">   #if defined(_WIN32)</span></div>
+<div class="line"><a name="l03852"></a><span class="lineno"> 3852</span>&#160;<span class="preprocessor">       #define VMA_SYSTEM_FREE(ptr)   _aligned_free(ptr)</span></div>
+<div class="line"><a name="l03853"></a><span class="lineno"> 3853</span>&#160;<span class="preprocessor">   #else</span></div>
+<div class="line"><a name="l03854"></a><span class="lineno"> 3854</span>&#160;<span class="preprocessor">       #define VMA_SYSTEM_FREE(ptr)   free(ptr)</span></div>
+<div class="line"><a name="l03855"></a><span class="lineno"> 3855</span>&#160;<span class="preprocessor">   #endif</span></div>
+<div class="line"><a name="l03856"></a><span class="lineno"> 3856</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l03857"></a><span class="lineno"> 3857</span>&#160; </div>
+<div class="line"><a name="l03858"></a><span class="lineno"> 3858</span>&#160;<span class="preprocessor">#ifndef VMA_MIN</span></div>
+<div class="line"><a name="l03859"></a><span class="lineno"> 3859</span>&#160;<span class="preprocessor">   #define VMA_MIN(v1, v2)    (std::min((v1), (v2)))</span></div>
+<div class="line"><a name="l03860"></a><span class="lineno"> 3860</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l03861"></a><span class="lineno"> 3861</span>&#160; </div>
+<div class="line"><a name="l03862"></a><span class="lineno"> 3862</span>&#160;<span class="preprocessor">#ifndef VMA_MAX</span></div>
+<div class="line"><a name="l03863"></a><span class="lineno"> 3863</span>&#160;<span class="preprocessor">   #define VMA_MAX(v1, v2)    (std::max((v1), (v2)))</span></div>
+<div class="line"><a name="l03864"></a><span class="lineno"> 3864</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l03865"></a><span class="lineno"> 3865</span>&#160; </div>
+<div class="line"><a name="l03866"></a><span class="lineno"> 3866</span>&#160;<span class="preprocessor">#ifndef VMA_SWAP</span></div>
+<div class="line"><a name="l03867"></a><span class="lineno"> 3867</span>&#160;<span class="preprocessor">   #define VMA_SWAP(v1, v2)   std::swap((v1), (v2))</span></div>
+<div class="line"><a name="l03868"></a><span class="lineno"> 3868</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l03869"></a><span class="lineno"> 3869</span>&#160; </div>
+<div class="line"><a name="l03870"></a><span class="lineno"> 3870</span>&#160;<span class="preprocessor">#ifndef VMA_SORT</span></div>
+<div class="line"><a name="l03871"></a><span class="lineno"> 3871</span>&#160;<span class="preprocessor">   #define VMA_SORT(beg, end, cmp)  std::sort(beg, end, cmp)</span></div>
+<div class="line"><a name="l03872"></a><span class="lineno"> 3872</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l03873"></a><span class="lineno"> 3873</span>&#160; </div>
+<div class="line"><a name="l03874"></a><span class="lineno"> 3874</span>&#160;<span class="preprocessor">#ifndef VMA_DEBUG_LOG</span></div>
+<div class="line"><a name="l03875"></a><span class="lineno"> 3875</span>&#160;<span class="preprocessor">   #define VMA_DEBUG_LOG(format, ...)</span></div>
+<div class="line"><a name="l03876"></a><span class="lineno"> 3876</span>&#160;   <span class="comment">/*</span></div>
+<div class="line"><a name="l03877"></a><span class="lineno"> 3877</span>&#160;<span class="comment">   #define VMA_DEBUG_LOG(format, ...) do { \</span></div>
+<div class="line"><a name="l03878"></a><span class="lineno"> 3878</span>&#160;<span class="comment">       printf(format, __VA_ARGS__); \</span></div>
+<div class="line"><a name="l03879"></a><span class="lineno"> 3879</span>&#160;<span class="comment">       printf(&quot;\n&quot;); \</span></div>
+<div class="line"><a name="l03880"></a><span class="lineno"> 3880</span>&#160;<span class="comment">   } while(false)</span></div>
+<div class="line"><a name="l03881"></a><span class="lineno"> 3881</span>&#160;<span class="comment">   */</span></div>
+<div class="line"><a name="l03882"></a><span class="lineno"> 3882</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l03883"></a><span class="lineno"> 3883</span>&#160; </div>
+<div class="line"><a name="l03884"></a><span class="lineno"> 3884</span>&#160;<span class="comment">// Define this macro to 1 to enable functions: vmaBuildStatsString, vmaFreeStatsString.</span></div>
+<div class="line"><a name="l03885"></a><span class="lineno"> 3885</span>&#160;<span class="preprocessor">#if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l03886"></a><span class="lineno"> 3886</span>&#160;    <span class="keyword">static</span> <span class="keyword">inline</span> <span class="keywordtype">void</span> VmaUint32ToStr(<span class="keywordtype">char</span>* outStr, <span class="keywordtype">size_t</span> strLen, uint32_t num)</div>
+<div class="line"><a name="l03887"></a><span class="lineno"> 3887</span>&#160;    {</div>
+<div class="line"><a name="l03888"></a><span class="lineno"> 3888</span>&#160;        snprintf(outStr, strLen, <span class="stringliteral">&quot;%u&quot;</span>, <span class="keyword">static_cast&lt;</span><span class="keywordtype">unsigned</span> <span class="keywordtype">int</span><span class="keyword">&gt;</span>(num));</div>
+<div class="line"><a name="l03889"></a><span class="lineno"> 3889</span>&#160;    }</div>
+<div class="line"><a name="l03890"></a><span class="lineno"> 3890</span>&#160;    <span class="keyword">static</span> <span class="keyword">inline</span> <span class="keywordtype">void</span> VmaUint64ToStr(<span class="keywordtype">char</span>* outStr, <span class="keywordtype">size_t</span> strLen, uint64_t num)</div>
+<div class="line"><a name="l03891"></a><span class="lineno"> 3891</span>&#160;    {</div>
+<div class="line"><a name="l03892"></a><span class="lineno"> 3892</span>&#160;        snprintf(outStr, strLen, <span class="stringliteral">&quot;%llu&quot;</span>, <span class="keyword">static_cast&lt;</span><span class="keywordtype">unsigned</span> <span class="keywordtype">long</span> <span class="keywordtype">long</span><span class="keyword">&gt;</span>(num));</div>
+<div class="line"><a name="l03893"></a><span class="lineno"> 3893</span>&#160;    }</div>
+<div class="line"><a name="l03894"></a><span class="lineno"> 3894</span>&#160;    <span class="keyword">static</span> <span class="keyword">inline</span> <span class="keywordtype">void</span> VmaPtrToStr(<span class="keywordtype">char</span>* outStr, <span class="keywordtype">size_t</span> strLen, <span class="keyword">const</span> <span class="keywordtype">void</span>* ptr)</div>
+<div class="line"><a name="l03895"></a><span class="lineno"> 3895</span>&#160;    {</div>
+<div class="line"><a name="l03896"></a><span class="lineno"> 3896</span>&#160;        snprintf(outStr, strLen, <span class="stringliteral">&quot;%p&quot;</span>, ptr);</div>
+<div class="line"><a name="l03897"></a><span class="lineno"> 3897</span>&#160;    }</div>
+<div class="line"><a name="l03898"></a><span class="lineno"> 3898</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l03899"></a><span class="lineno"> 3899</span>&#160; </div>
+<div class="line"><a name="l03900"></a><span class="lineno"> 3900</span>&#160;<span class="preprocessor">#ifndef VMA_MUTEX</span></div>
+<div class="line"><a name="l03901"></a><span class="lineno"> 3901</span>&#160;    <span class="keyword">class </span>VmaMutex</div>
+<div class="line"><a name="l03902"></a><span class="lineno"> 3902</span>&#160;    {</div>
+<div class="line"><a name="l03903"></a><span class="lineno"> 3903</span>&#160;    <span class="keyword">public</span>:</div>
+<div class="line"><a name="l03904"></a><span class="lineno"> 3904</span>&#160;        <span class="keywordtype">void</span> Lock() { m_Mutex.lock(); }</div>
+<div class="line"><a name="l03905"></a><span class="lineno"> 3905</span>&#160;        <span class="keywordtype">void</span> Unlock() { m_Mutex.unlock(); }</div>
+<div class="line"><a name="l03906"></a><span class="lineno"> 3906</span>&#160;        <span class="keywordtype">bool</span> TryLock() { <span class="keywordflow">return</span> m_Mutex.try_lock(); }</div>
+<div class="line"><a name="l03907"></a><span class="lineno"> 3907</span>&#160;    <span class="keyword">private</span>:</div>
+<div class="line"><a name="l03908"></a><span class="lineno"> 3908</span>&#160;        std::mutex m_Mutex;</div>
+<div class="line"><a name="l03909"></a><span class="lineno"> 3909</span>&#160;    };</div>
+<div class="line"><a name="l03910"></a><span class="lineno"> 3910</span>&#160;<span class="preprocessor">    #define VMA_MUTEX VmaMutex</span></div>
+<div class="line"><a name="l03911"></a><span class="lineno"> 3911</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l03912"></a><span class="lineno"> 3912</span>&#160; </div>
+<div class="line"><a name="l03913"></a><span class="lineno"> 3913</span>&#160;<span class="comment">// Read-write mutex, where &quot;read&quot; is shared access, &quot;write&quot; is exclusive access.</span></div>
+<div class="line"><a name="l03914"></a><span class="lineno"> 3914</span>&#160;<span class="preprocessor">#ifndef VMA_RW_MUTEX</span></div>
+<div class="line"><a name="l03915"></a><span class="lineno"> 3915</span>&#160;<span class="preprocessor">    #if VMA_USE_STL_SHARED_MUTEX</span></div>
+<div class="line"><a name="l03916"></a><span class="lineno"> 3916</span>&#160;        <span class="comment">// Use std::shared_mutex from C++17.</span></div>
+<div class="line"><a name="l03917"></a><span class="lineno"> 3917</span>&#160;<span class="preprocessor">        #include &lt;shared_mutex&gt;</span></div>
+<div class="line"><a name="l03918"></a><span class="lineno"> 3918</span>&#160;        <span class="keyword">class </span>VmaRWMutex</div>
+<div class="line"><a name="l03919"></a><span class="lineno"> 3919</span>&#160;        {</div>
+<div class="line"><a name="l03920"></a><span class="lineno"> 3920</span>&#160;        <span class="keyword">public</span>:</div>
+<div class="line"><a name="l03921"></a><span class="lineno"> 3921</span>&#160;            <span class="keywordtype">void</span> LockRead() { m_Mutex.lock_shared(); }</div>
+<div class="line"><a name="l03922"></a><span class="lineno"> 3922</span>&#160;            <span class="keywordtype">void</span> UnlockRead() { m_Mutex.unlock_shared(); }</div>
+<div class="line"><a name="l03923"></a><span class="lineno"> 3923</span>&#160;            <span class="keywordtype">bool</span> TryLockRead() { <span class="keywordflow">return</span> m_Mutex.try_lock_shared(); }</div>
+<div class="line"><a name="l03924"></a><span class="lineno"> 3924</span>&#160;            <span class="keywordtype">void</span> LockWrite() { m_Mutex.lock(); }</div>
+<div class="line"><a name="l03925"></a><span class="lineno"> 3925</span>&#160;            <span class="keywordtype">void</span> UnlockWrite() { m_Mutex.unlock(); }</div>
+<div class="line"><a name="l03926"></a><span class="lineno"> 3926</span>&#160;            <span class="keywordtype">bool</span> TryLockWrite() { <span class="keywordflow">return</span> m_Mutex.try_lock(); }</div>
+<div class="line"><a name="l03927"></a><span class="lineno"> 3927</span>&#160;        <span class="keyword">private</span>:</div>
+<div class="line"><a name="l03928"></a><span class="lineno"> 3928</span>&#160;            std::shared_mutex m_Mutex;</div>
+<div class="line"><a name="l03929"></a><span class="lineno"> 3929</span>&#160;        };</div>
+<div class="line"><a name="l03930"></a><span class="lineno"> 3930</span>&#160;<span class="preprocessor">        #define VMA_RW_MUTEX VmaRWMutex</span></div>
+<div class="line"><a name="l03931"></a><span class="lineno"> 3931</span>&#160;<span class="preprocessor">    #elif defined(_WIN32) &amp;&amp; defined(WINVER) &amp;&amp; WINVER &gt;= 0x0600</span></div>
+<div class="line"><a name="l03932"></a><span class="lineno"> 3932</span>&#160;        <span class="comment">// Use SRWLOCK from WinAPI.</span></div>
+<div class="line"><a name="l03933"></a><span class="lineno"> 3933</span>&#160;        <span class="comment">// Minimum supported client = Windows Vista, server = Windows Server 2008.</span></div>
+<div class="line"><a name="l03934"></a><span class="lineno"> 3934</span>&#160;        <span class="keyword">class </span>VmaRWMutex</div>
+<div class="line"><a name="l03935"></a><span class="lineno"> 3935</span>&#160;        {</div>
+<div class="line"><a name="l03936"></a><span class="lineno"> 3936</span>&#160;        <span class="keyword">public</span>:</div>
+<div class="line"><a name="l03937"></a><span class="lineno"> 3937</span>&#160;            VmaRWMutex() { InitializeSRWLock(&amp;m_Lock); }</div>
+<div class="line"><a name="l03938"></a><span class="lineno"> 3938</span>&#160;            <span class="keywordtype">void</span> LockRead() { AcquireSRWLockShared(&amp;m_Lock); }</div>
+<div class="line"><a name="l03939"></a><span class="lineno"> 3939</span>&#160;            <span class="keywordtype">void</span> UnlockRead() { ReleaseSRWLockShared(&amp;m_Lock); }</div>
+<div class="line"><a name="l03940"></a><span class="lineno"> 3940</span>&#160;            <span class="keywordtype">bool</span> TryLockRead() { <span class="keywordflow">return</span> TryAcquireSRWLockShared(&amp;m_Lock) != FALSE; }</div>
+<div class="line"><a name="l03941"></a><span class="lineno"> 3941</span>&#160;            <span class="keywordtype">void</span> LockWrite() { AcquireSRWLockExclusive(&amp;m_Lock); }</div>
+<div class="line"><a name="l03942"></a><span class="lineno"> 3942</span>&#160;            <span class="keywordtype">void</span> UnlockWrite() { ReleaseSRWLockExclusive(&amp;m_Lock); }</div>
+<div class="line"><a name="l03943"></a><span class="lineno"> 3943</span>&#160;            <span class="keywordtype">bool</span> TryLockWrite() { <span class="keywordflow">return</span> TryAcquireSRWLockExclusive(&amp;m_Lock) != FALSE; }</div>
+<div class="line"><a name="l03944"></a><span class="lineno"> 3944</span>&#160;        <span class="keyword">private</span>:</div>
+<div class="line"><a name="l03945"></a><span class="lineno"> 3945</span>&#160;            SRWLOCK m_Lock;</div>
+<div class="line"><a name="l03946"></a><span class="lineno"> 3946</span>&#160;        };</div>
+<div class="line"><a name="l03947"></a><span class="lineno"> 3947</span>&#160;<span class="preprocessor">        #define VMA_RW_MUTEX VmaRWMutex</span></div>
+<div class="line"><a name="l03948"></a><span class="lineno"> 3948</span>&#160;<span class="preprocessor">    #else</span></div>
+<div class="line"><a name="l03949"></a><span class="lineno"> 3949</span>&#160;        <span class="comment">// Less efficient fallback: Use normal mutex.</span></div>
+<div class="line"><a name="l03950"></a><span class="lineno"> 3950</span>&#160;        <span class="keyword">class </span>VmaRWMutex</div>
+<div class="line"><a name="l03951"></a><span class="lineno"> 3951</span>&#160;        {</div>
+<div class="line"><a name="l03952"></a><span class="lineno"> 3952</span>&#160;        <span class="keyword">public</span>:</div>
+<div class="line"><a name="l03953"></a><span class="lineno"> 3953</span>&#160;            <span class="keywordtype">void</span> LockRead() { m_Mutex.Lock(); }</div>
+<div class="line"><a name="l03954"></a><span class="lineno"> 3954</span>&#160;            <span class="keywordtype">void</span> UnlockRead() { m_Mutex.Unlock(); }</div>
+<div class="line"><a name="l03955"></a><span class="lineno"> 3955</span>&#160;            <span class="keywordtype">bool</span> TryLockRead() { <span class="keywordflow">return</span> m_Mutex.TryLock(); }</div>
+<div class="line"><a name="l03956"></a><span class="lineno"> 3956</span>&#160;            <span class="keywordtype">void</span> LockWrite() { m_Mutex.Lock(); }</div>
+<div class="line"><a name="l03957"></a><span class="lineno"> 3957</span>&#160;            <span class="keywordtype">void</span> UnlockWrite() { m_Mutex.Unlock(); }</div>
+<div class="line"><a name="l03958"></a><span class="lineno"> 3958</span>&#160;            <span class="keywordtype">bool</span> TryLockWrite() { <span class="keywordflow">return</span> m_Mutex.TryLock(); }</div>
+<div class="line"><a name="l03959"></a><span class="lineno"> 3959</span>&#160;        <span class="keyword">private</span>:</div>
+<div class="line"><a name="l03960"></a><span class="lineno"> 3960</span>&#160;            VMA_MUTEX m_Mutex;</div>
+<div class="line"><a name="l03961"></a><span class="lineno"> 3961</span>&#160;        };</div>
+<div class="line"><a name="l03962"></a><span class="lineno"> 3962</span>&#160;<span class="preprocessor">        #define VMA_RW_MUTEX VmaRWMutex</span></div>
+<div class="line"><a name="l03963"></a><span class="lineno"> 3963</span>&#160;<span class="preprocessor">    #endif // #if VMA_USE_STL_SHARED_MUTEX</span></div>
+<div class="line"><a name="l03964"></a><span class="lineno"> 3964</span>&#160;<span class="preprocessor">#endif // #ifndef VMA_RW_MUTEX</span></div>
+<div class="line"><a name="l03965"></a><span class="lineno"> 3965</span>&#160; </div>
+<div class="line"><a name="l03966"></a><span class="lineno"> 3966</span>&#160;<span class="comment">/*</span></div>
+<div class="line"><a name="l03967"></a><span class="lineno"> 3967</span>&#160;<span class="comment">If providing your own implementation, you need to implement a subset of std::atomic.</span></div>
+<div class="line"><a name="l03968"></a><span class="lineno"> 3968</span>&#160;<span class="comment">*/</span></div>
+<div class="line"><a name="l03969"></a><span class="lineno"> 3969</span>&#160;<span class="preprocessor">#ifndef VMA_ATOMIC_UINT32</span></div>
+<div class="line"><a name="l03970"></a><span class="lineno"> 3970</span>&#160;<span class="preprocessor">    #include &lt;atomic&gt;</span></div>
+<div class="line"><a name="l03971"></a><span class="lineno"> 3971</span>&#160;<span class="preprocessor">    #define VMA_ATOMIC_UINT32 std::atomic&lt;uint32_t&gt;</span></div>
+<div class="line"><a name="l03972"></a><span class="lineno"> 3972</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l03973"></a><span class="lineno"> 3973</span>&#160; </div>
+<div class="line"><a name="l03974"></a><span class="lineno"> 3974</span>&#160;<span class="preprocessor">#ifndef VMA_ATOMIC_UINT64</span></div>
+<div class="line"><a name="l03975"></a><span class="lineno"> 3975</span>&#160;<span class="preprocessor">    #include &lt;atomic&gt;</span></div>
+<div class="line"><a name="l03976"></a><span class="lineno"> 3976</span>&#160;<span class="preprocessor">    #define VMA_ATOMIC_UINT64 std::atomic&lt;uint64_t&gt;</span></div>
+<div class="line"><a name="l03977"></a><span class="lineno"> 3977</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l03978"></a><span class="lineno"> 3978</span>&#160; </div>
+<div class="line"><a name="l03979"></a><span class="lineno"> 3979</span>&#160;<span class="preprocessor">#ifndef VMA_DEBUG_ALWAYS_DEDICATED_MEMORY</span></div>
+<div class="line"><a name="l03980"></a><span class="lineno"> 3980</span>&#160; </div>
+<div class="line"><a name="l03984"></a><span class="lineno"> 3984</span>&#160;<span class="preprocessor">    #define VMA_DEBUG_ALWAYS_DEDICATED_MEMORY (0)</span></div>
+<div class="line"><a name="l03985"></a><span class="lineno"> 3985</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l03986"></a><span class="lineno"> 3986</span>&#160; </div>
+<div class="line"><a name="l03987"></a><span class="lineno"> 3987</span>&#160;<span class="preprocessor">#ifndef VMA_DEBUG_ALIGNMENT</span></div>
+<div class="line"><a name="l03988"></a><span class="lineno"> 3988</span>&#160; </div>
+<div class="line"><a name="l03992"></a><span class="lineno"> 3992</span>&#160;<span class="preprocessor">    #define VMA_DEBUG_ALIGNMENT (1)</span></div>
+<div class="line"><a name="l03993"></a><span class="lineno"> 3993</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l03994"></a><span class="lineno"> 3994</span>&#160; </div>
+<div class="line"><a name="l03995"></a><span class="lineno"> 3995</span>&#160;<span class="preprocessor">#ifndef VMA_DEBUG_MARGIN</span></div>
+<div class="line"><a name="l03996"></a><span class="lineno"> 3996</span>&#160; </div>
+<div class="line"><a name="l04000"></a><span class="lineno"> 4000</span>&#160;<span class="preprocessor">    #define VMA_DEBUG_MARGIN (0)</span></div>
+<div class="line"><a name="l04001"></a><span class="lineno"> 4001</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l04002"></a><span class="lineno"> 4002</span>&#160; </div>
+<div class="line"><a name="l04003"></a><span class="lineno"> 4003</span>&#160;<span class="preprocessor">#ifndef VMA_DEBUG_INITIALIZE_ALLOCATIONS</span></div>
+<div class="line"><a name="l04004"></a><span class="lineno"> 4004</span>&#160; </div>
+<div class="line"><a name="l04008"></a><span class="lineno"> 4008</span>&#160;<span class="preprocessor">    #define VMA_DEBUG_INITIALIZE_ALLOCATIONS (0)</span></div>
+<div class="line"><a name="l04009"></a><span class="lineno"> 4009</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l04010"></a><span class="lineno"> 4010</span>&#160; </div>
+<div class="line"><a name="l04011"></a><span class="lineno"> 4011</span>&#160;<span class="preprocessor">#ifndef VMA_DEBUG_DETECT_CORRUPTION</span></div>
+<div class="line"><a name="l04012"></a><span class="lineno"> 4012</span>&#160; </div>
+<div class="line"><a name="l04017"></a><span class="lineno"> 4017</span>&#160;<span class="preprocessor">    #define VMA_DEBUG_DETECT_CORRUPTION (0)</span></div>
+<div class="line"><a name="l04018"></a><span class="lineno"> 4018</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l04019"></a><span class="lineno"> 4019</span>&#160; </div>
+<div class="line"><a name="l04020"></a><span class="lineno"> 4020</span>&#160;<span class="preprocessor">#ifndef VMA_DEBUG_GLOBAL_MUTEX</span></div>
+<div class="line"><a name="l04021"></a><span class="lineno"> 4021</span>&#160; </div>
+<div class="line"><a name="l04025"></a><span class="lineno"> 4025</span>&#160;<span class="preprocessor">    #define VMA_DEBUG_GLOBAL_MUTEX (0)</span></div>
+<div class="line"><a name="l04026"></a><span class="lineno"> 4026</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l04027"></a><span class="lineno"> 4027</span>&#160; </div>
+<div class="line"><a name="l04028"></a><span class="lineno"> 4028</span>&#160;<span class="preprocessor">#ifndef VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY</span></div>
+<div class="line"><a name="l04029"></a><span class="lineno"> 4029</span>&#160; </div>
+<div class="line"><a name="l04033"></a><span class="lineno"> 4033</span>&#160;<span class="preprocessor">    #define VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY (1)</span></div>
+<div class="line"><a name="l04034"></a><span class="lineno"> 4034</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l04035"></a><span class="lineno"> 4035</span>&#160; </div>
+<div class="line"><a name="l04036"></a><span class="lineno"> 4036</span>&#160;<span class="preprocessor">#ifndef VMA_SMALL_HEAP_MAX_SIZE</span></div>
+<div class="line"><a name="l04037"></a><span class="lineno"> 4037</span>&#160;<span class="preprocessor">   #define VMA_SMALL_HEAP_MAX_SIZE (1024ull * 1024 * 1024)</span></div>
+<div class="line"><a name="l04039"></a><span class="lineno"> 4039</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l04040"></a><span class="lineno"> 4040</span>&#160; </div>
+<div class="line"><a name="l04041"></a><span class="lineno"> 4041</span>&#160;<span class="preprocessor">#ifndef VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE</span></div>
+<div class="line"><a name="l04042"></a><span class="lineno"> 4042</span>&#160;<span class="preprocessor">   #define VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE (256ull * 1024 * 1024)</span></div>
+<div class="line"><a name="l04044"></a><span class="lineno"> 4044</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l04045"></a><span class="lineno"> 4045</span>&#160; </div>
+<div class="line"><a name="l04046"></a><span class="lineno"> 4046</span>&#160;<span class="preprocessor">#ifndef VMA_CLASS_NO_COPY</span></div>
+<div class="line"><a name="l04047"></a><span class="lineno"> 4047</span>&#160;<span class="preprocessor">    #define VMA_CLASS_NO_COPY(className) \</span></div>
+<div class="line"><a name="l04048"></a><span class="lineno"> 4048</span>&#160;<span class="preprocessor">        private: \</span></div>
+<div class="line"><a name="l04049"></a><span class="lineno"> 4049</span>&#160;<span class="preprocessor">            className(const className&amp;) = delete; \</span></div>
+<div class="line"><a name="l04050"></a><span class="lineno"> 4050</span>&#160;<span class="preprocessor">            className&amp; operator=(const className&amp;) = delete;</span></div>
+<div class="line"><a name="l04051"></a><span class="lineno"> 4051</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l04052"></a><span class="lineno"> 4052</span>&#160; </div>
+<div class="line"><a name="l04053"></a><span class="lineno"> 4053</span>&#160;<span class="keyword">static</span> <span class="keyword">const</span> uint32_t VMA_FRAME_INDEX_LOST = UINT32_MAX;</div>
+<div class="line"><a name="l04054"></a><span class="lineno"> 4054</span>&#160; </div>
+<div class="line"><a name="l04055"></a><span class="lineno"> 4055</span>&#160;<span class="comment">// Decimal 2139416166, float NaN, little-endian binary 66 E6 84 7F.</span></div>
+<div class="line"><a name="l04056"></a><span class="lineno"> 4056</span>&#160;<span class="keyword">static</span> <span class="keyword">const</span> uint32_t VMA_CORRUPTION_DETECTION_MAGIC_VALUE = 0x7F84E666;</div>
+<div class="line"><a name="l04057"></a><span class="lineno"> 4057</span>&#160; </div>
+<div class="line"><a name="l04058"></a><span class="lineno"> 4058</span>&#160;<span class="keyword">static</span> <span class="keyword">const</span> uint8_t VMA_ALLOCATION_FILL_PATTERN_CREATED   = 0xDC;</div>
+<div class="line"><a name="l04059"></a><span class="lineno"> 4059</span>&#160;<span class="keyword">static</span> <span class="keyword">const</span> uint8_t VMA_ALLOCATION_FILL_PATTERN_DESTROYED = 0xEF;</div>
+<div class="line"><a name="l04060"></a><span class="lineno"> 4060</span>&#160; </div>
+<div class="line"><a name="l04061"></a><span class="lineno"> 4061</span>&#160;<span class="comment">/*******************************************************************************</span></div>
+<div class="line"><a name="l04062"></a><span class="lineno"> 4062</span>&#160;<span class="comment">END OF CONFIGURATION</span></div>
+<div class="line"><a name="l04063"></a><span class="lineno"> 4063</span>&#160;<span class="comment">*/</span></div>
+<div class="line"><a name="l04064"></a><span class="lineno"> 4064</span>&#160; </div>
+<div class="line"><a name="l04065"></a><span class="lineno"> 4065</span>&#160;<span class="comment">// # Copy of some Vulkan definitions so we don&#39;t need to check their existence just to handle few constants.</span></div>
+<div class="line"><a name="l04066"></a><span class="lineno"> 4066</span>&#160; </div>
+<div class="line"><a name="l04067"></a><span class="lineno"> 4067</span>&#160;<span class="keyword">static</span> <span class="keyword">const</span> uint32_t VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD_COPY = 0x00000040;</div>
+<div class="line"><a name="l04068"></a><span class="lineno"> 4068</span>&#160;<span class="keyword">static</span> <span class="keyword">const</span> uint32_t VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD_COPY = 0x00000080;</div>
+<div class="line"><a name="l04069"></a><span class="lineno"> 4069</span>&#160;<span class="keyword">static</span> <span class="keyword">const</span> uint32_t VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_COPY = 0x00020000;</div>
+<div class="line"><a name="l04070"></a><span class="lineno"> 4070</span>&#160; </div>
+<div class="line"><a name="l04071"></a><span class="lineno"> 4071</span>&#160;<span class="keyword">static</span> <span class="keyword">const</span> uint32_t VMA_ALLOCATION_INTERNAL_STRATEGY_MIN_OFFSET = 0x10000000u;</div>
+<div class="line"><a name="l04072"></a><span class="lineno"> 4072</span>&#160; </div>
+<div class="line"><a name="l04073"></a><span class="lineno"> 4073</span>&#160;<span class="keyword">static</span> VkAllocationCallbacks VmaEmptyAllocationCallbacks = {</div>
+<div class="line"><a name="l04074"></a><span class="lineno"> 4074</span>&#160;    VMA_NULL, VMA_NULL, VMA_NULL, VMA_NULL, VMA_NULL, VMA_NULL };</div>
+<div class="line"><a name="l04075"></a><span class="lineno"> 4075</span>&#160; </div>
+<div class="line"><a name="l04076"></a><span class="lineno"> 4076</span>&#160;<span class="comment">// Returns number of bits set to 1 in (v).</span></div>
+<div class="line"><a name="l04077"></a><span class="lineno"> 4077</span>&#160;<span class="keyword">static</span> <span class="keyword">inline</span> uint32_t VmaCountBitsSet(uint32_t v)</div>
+<div class="line"><a name="l04078"></a><span class="lineno"> 4078</span>&#160;{</div>
+<div class="line"><a name="l04079"></a><span class="lineno"> 4079</span>&#160;    uint32_t c = v - ((v &gt;&gt; 1) &amp; 0x55555555);</div>
+<div class="line"><a name="l04080"></a><span class="lineno"> 4080</span>&#160;    c = ((c &gt;&gt;  2) &amp; 0x33333333) + (c &amp; 0x33333333);</div>
+<div class="line"><a name="l04081"></a><span class="lineno"> 4081</span>&#160;    c = ((c &gt;&gt;  4) + c) &amp; 0x0F0F0F0F;</div>
+<div class="line"><a name="l04082"></a><span class="lineno"> 4082</span>&#160;    c = ((c &gt;&gt;  8) + c) &amp; 0x00FF00FF;</div>
+<div class="line"><a name="l04083"></a><span class="lineno"> 4083</span>&#160;    c = ((c &gt;&gt; 16) + c) &amp; 0x0000FFFF;</div>
+<div class="line"><a name="l04084"></a><span class="lineno"> 4084</span>&#160;    <span class="keywordflow">return</span> c;</div>
+<div class="line"><a name="l04085"></a><span class="lineno"> 4085</span>&#160;}</div>
+<div class="line"><a name="l04086"></a><span class="lineno"> 4086</span>&#160; </div>
+<div class="line"><a name="l04087"></a><span class="lineno"> 4087</span>&#160;<span class="comment">// Aligns given value up to nearest multiply of align value. For example: VmaAlignUp(11, 8) = 16.</span></div>
+<div class="line"><a name="l04088"></a><span class="lineno"> 4088</span>&#160;<span class="comment">// Use types like uint32_t, uint64_t as T.</span></div>
+<div class="line"><a name="l04089"></a><span class="lineno"> 4089</span>&#160;<span class="keyword">template</span> &lt;<span class="keyword">typename</span> T&gt;</div>
+<div class="line"><a name="l04090"></a><span class="lineno"> 4090</span>&#160;<span class="keyword">static</span> <span class="keyword">inline</span> T VmaAlignUp(T val, T align)</div>
+<div class="line"><a name="l04091"></a><span class="lineno"> 4091</span>&#160;{</div>
+<div class="line"><a name="l04092"></a><span class="lineno"> 4092</span>&#160;    <span class="keywordflow">return</span> (val + align - 1) / align * align;</div>
+<div class="line"><a name="l04093"></a><span class="lineno"> 4093</span>&#160;}</div>
+<div class="line"><a name="l04094"></a><span class="lineno"> 4094</span>&#160;<span class="comment">// Aligns given value down to nearest multiply of align value. For example: VmaAlignUp(11, 8) = 8.</span></div>
+<div class="line"><a name="l04095"></a><span class="lineno"> 4095</span>&#160;<span class="comment">// Use types like uint32_t, uint64_t as T.</span></div>
+<div class="line"><a name="l04096"></a><span class="lineno"> 4096</span>&#160;<span class="keyword">template</span> &lt;<span class="keyword">typename</span> T&gt;</div>
+<div class="line"><a name="l04097"></a><span class="lineno"> 4097</span>&#160;<span class="keyword">static</span> <span class="keyword">inline</span> T VmaAlignDown(T val, T align)</div>
+<div class="line"><a name="l04098"></a><span class="lineno"> 4098</span>&#160;{</div>
+<div class="line"><a name="l04099"></a><span class="lineno"> 4099</span>&#160;    <span class="keywordflow">return</span> val / align * align;</div>
+<div class="line"><a name="l04100"></a><span class="lineno"> 4100</span>&#160;}</div>
+<div class="line"><a name="l04101"></a><span class="lineno"> 4101</span>&#160; </div>
+<div class="line"><a name="l04102"></a><span class="lineno"> 4102</span>&#160;<span class="comment">// Division with mathematical rounding to nearest number.</span></div>
+<div class="line"><a name="l04103"></a><span class="lineno"> 4103</span>&#160;<span class="keyword">template</span> &lt;<span class="keyword">typename</span> T&gt;</div>
+<div class="line"><a name="l04104"></a><span class="lineno"> 4104</span>&#160;<span class="keyword">static</span> <span class="keyword">inline</span> T VmaRoundDiv(T x, T y)</div>
+<div class="line"><a name="l04105"></a><span class="lineno"> 4105</span>&#160;{</div>
+<div class="line"><a name="l04106"></a><span class="lineno"> 4106</span>&#160;    <span class="keywordflow">return</span> (x + (y / (T)2)) / y;</div>
+<div class="line"><a name="l04107"></a><span class="lineno"> 4107</span>&#160;}</div>
+<div class="line"><a name="l04108"></a><span class="lineno"> 4108</span>&#160; </div>
+<div class="line"><a name="l04109"></a><span class="lineno"> 4109</span>&#160;<span class="comment">/*</span></div>
+<div class="line"><a name="l04110"></a><span class="lineno"> 4110</span>&#160;<span class="comment">Returns true if given number is a power of two.</span></div>
+<div class="line"><a name="l04111"></a><span class="lineno"> 4111</span>&#160;<span class="comment">T must be unsigned integer number or signed integer but always nonnegative.</span></div>
+<div class="line"><a name="l04112"></a><span class="lineno"> 4112</span>&#160;<span class="comment">For 0 returns true.</span></div>
+<div class="line"><a name="l04113"></a><span class="lineno"> 4113</span>&#160;<span class="comment">*/</span></div>
+<div class="line"><a name="l04114"></a><span class="lineno"> 4114</span>&#160;<span class="keyword">template</span> &lt;<span class="keyword">typename</span> T&gt;</div>
+<div class="line"><a name="l04115"></a><span class="lineno"> 4115</span>&#160;<span class="keyword">inline</span> <span class="keywordtype">bool</span> VmaIsPow2(T x)</div>
+<div class="line"><a name="l04116"></a><span class="lineno"> 4116</span>&#160;{</div>
+<div class="line"><a name="l04117"></a><span class="lineno"> 4117</span>&#160;    <span class="keywordflow">return</span> (x &amp; (x-1)) == 0;</div>
+<div class="line"><a name="l04118"></a><span class="lineno"> 4118</span>&#160;}</div>
+<div class="line"><a name="l04119"></a><span class="lineno"> 4119</span>&#160; </div>
+<div class="line"><a name="l04120"></a><span class="lineno"> 4120</span>&#160;<span class="comment">// Returns smallest power of 2 greater or equal to v.</span></div>
+<div class="line"><a name="l04121"></a><span class="lineno"> 4121</span>&#160;<span class="keyword">static</span> <span class="keyword">inline</span> uint32_t VmaNextPow2(uint32_t v)</div>
+<div class="line"><a name="l04122"></a><span class="lineno"> 4122</span>&#160;{</div>
+<div class="line"><a name="l04123"></a><span class="lineno"> 4123</span>&#160;    v--;</div>
+<div class="line"><a name="l04124"></a><span class="lineno"> 4124</span>&#160;    v |= v &gt;&gt; 1;</div>
+<div class="line"><a name="l04125"></a><span class="lineno"> 4125</span>&#160;    v |= v &gt;&gt; 2;</div>
+<div class="line"><a name="l04126"></a><span class="lineno"> 4126</span>&#160;    v |= v &gt;&gt; 4;</div>
+<div class="line"><a name="l04127"></a><span class="lineno"> 4127</span>&#160;    v |= v &gt;&gt; 8;</div>
+<div class="line"><a name="l04128"></a><span class="lineno"> 4128</span>&#160;    v |= v &gt;&gt; 16;</div>
+<div class="line"><a name="l04129"></a><span class="lineno"> 4129</span>&#160;    v++;</div>
+<div class="line"><a name="l04130"></a><span class="lineno"> 4130</span>&#160;    <span class="keywordflow">return</span> v;</div>
+<div class="line"><a name="l04131"></a><span class="lineno"> 4131</span>&#160;}</div>
+<div class="line"><a name="l04132"></a><span class="lineno"> 4132</span>&#160;<span class="keyword">static</span> <span class="keyword">inline</span> uint64_t VmaNextPow2(uint64_t v)</div>
+<div class="line"><a name="l04133"></a><span class="lineno"> 4133</span>&#160;{</div>
+<div class="line"><a name="l04134"></a><span class="lineno"> 4134</span>&#160;    v--;</div>
+<div class="line"><a name="l04135"></a><span class="lineno"> 4135</span>&#160;    v |= v &gt;&gt; 1;</div>
+<div class="line"><a name="l04136"></a><span class="lineno"> 4136</span>&#160;    v |= v &gt;&gt; 2;</div>
+<div class="line"><a name="l04137"></a><span class="lineno"> 4137</span>&#160;    v |= v &gt;&gt; 4;</div>
+<div class="line"><a name="l04138"></a><span class="lineno"> 4138</span>&#160;    v |= v &gt;&gt; 8;</div>
+<div class="line"><a name="l04139"></a><span class="lineno"> 4139</span>&#160;    v |= v &gt;&gt; 16;</div>
+<div class="line"><a name="l04140"></a><span class="lineno"> 4140</span>&#160;    v |= v &gt;&gt; 32;</div>
+<div class="line"><a name="l04141"></a><span class="lineno"> 4141</span>&#160;    v++;</div>
+<div class="line"><a name="l04142"></a><span class="lineno"> 4142</span>&#160;    <span class="keywordflow">return</span> v;</div>
+<div class="line"><a name="l04143"></a><span class="lineno"> 4143</span>&#160;}</div>
+<div class="line"><a name="l04144"></a><span class="lineno"> 4144</span>&#160; </div>
+<div class="line"><a name="l04145"></a><span class="lineno"> 4145</span>&#160;<span class="comment">// Returns largest power of 2 less or equal to v.</span></div>
+<div class="line"><a name="l04146"></a><span class="lineno"> 4146</span>&#160;<span class="keyword">static</span> <span class="keyword">inline</span> uint32_t VmaPrevPow2(uint32_t v)</div>
+<div class="line"><a name="l04147"></a><span class="lineno"> 4147</span>&#160;{</div>
+<div class="line"><a name="l04148"></a><span class="lineno"> 4148</span>&#160;    v |= v &gt;&gt; 1;</div>
+<div class="line"><a name="l04149"></a><span class="lineno"> 4149</span>&#160;    v |= v &gt;&gt; 2;</div>
+<div class="line"><a name="l04150"></a><span class="lineno"> 4150</span>&#160;    v |= v &gt;&gt; 4;</div>
+<div class="line"><a name="l04151"></a><span class="lineno"> 4151</span>&#160;    v |= v &gt;&gt; 8;</div>
+<div class="line"><a name="l04152"></a><span class="lineno"> 4152</span>&#160;    v |= v &gt;&gt; 16;</div>
+<div class="line"><a name="l04153"></a><span class="lineno"> 4153</span>&#160;    v = v ^ (v &gt;&gt; 1);</div>
+<div class="line"><a name="l04154"></a><span class="lineno"> 4154</span>&#160;    <span class="keywordflow">return</span> v;</div>
+<div class="line"><a name="l04155"></a><span class="lineno"> 4155</span>&#160;}</div>
+<div class="line"><a name="l04156"></a><span class="lineno"> 4156</span>&#160;<span class="keyword">static</span> <span class="keyword">inline</span> uint64_t VmaPrevPow2(uint64_t v)</div>
+<div class="line"><a name="l04157"></a><span class="lineno"> 4157</span>&#160;{</div>
+<div class="line"><a name="l04158"></a><span class="lineno"> 4158</span>&#160;    v |= v &gt;&gt; 1;</div>
+<div class="line"><a name="l04159"></a><span class="lineno"> 4159</span>&#160;    v |= v &gt;&gt; 2;</div>
+<div class="line"><a name="l04160"></a><span class="lineno"> 4160</span>&#160;    v |= v &gt;&gt; 4;</div>
+<div class="line"><a name="l04161"></a><span class="lineno"> 4161</span>&#160;    v |= v &gt;&gt; 8;</div>
+<div class="line"><a name="l04162"></a><span class="lineno"> 4162</span>&#160;    v |= v &gt;&gt; 16;</div>
+<div class="line"><a name="l04163"></a><span class="lineno"> 4163</span>&#160;    v |= v &gt;&gt; 32;</div>
+<div class="line"><a name="l04164"></a><span class="lineno"> 4164</span>&#160;    v = v ^ (v &gt;&gt; 1);</div>
+<div class="line"><a name="l04165"></a><span class="lineno"> 4165</span>&#160;    <span class="keywordflow">return</span> v;</div>
+<div class="line"><a name="l04166"></a><span class="lineno"> 4166</span>&#160;}</div>
+<div class="line"><a name="l04167"></a><span class="lineno"> 4167</span>&#160; </div>
+<div class="line"><a name="l04168"></a><span class="lineno"> 4168</span>&#160;<span class="keyword">static</span> <span class="keyword">inline</span> <span class="keywordtype">bool</span> VmaStrIsEmpty(<span class="keyword">const</span> <span class="keywordtype">char</span>* pStr)</div>
+<div class="line"><a name="l04169"></a><span class="lineno"> 4169</span>&#160;{</div>
+<div class="line"><a name="l04170"></a><span class="lineno"> 4170</span>&#160;    <span class="keywordflow">return</span> pStr == VMA_NULL || *pStr == <span class="charliteral">&#39;\0&#39;</span>;</div>
+<div class="line"><a name="l04171"></a><span class="lineno"> 4171</span>&#160;}</div>
+<div class="line"><a name="l04172"></a><span class="lineno"> 4172</span>&#160; </div>
+<div class="line"><a name="l04173"></a><span class="lineno"> 4173</span>&#160;<span class="preprocessor">#if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l04174"></a><span class="lineno"> 4174</span>&#160; </div>
+<div class="line"><a name="l04175"></a><span class="lineno"> 4175</span>&#160;<span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">char</span>* VmaAlgorithmToStr(uint32_t algorithm)</div>
+<div class="line"><a name="l04176"></a><span class="lineno"> 4176</span>&#160;{</div>
+<div class="line"><a name="l04177"></a><span class="lineno"> 4177</span>&#160;    <span class="keywordflow">switch</span>(algorithm)</div>
+<div class="line"><a name="l04178"></a><span class="lineno"> 4178</span>&#160;    {</div>
+<div class="line"><a name="l04179"></a><span class="lineno"> 4179</span>&#160;    <span class="keywordflow">case</span> <a class="code" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a13c8a444197c67866be9cb05599fc726">VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT</a>:</div>
+<div class="line"><a name="l04180"></a><span class="lineno"> 4180</span>&#160;        <span class="keywordflow">return</span> <span class="stringliteral">&quot;Linear&quot;</span>;</div>
+<div class="line"><a name="l04181"></a><span class="lineno"> 4181</span>&#160;    <span class="keywordflow">case</span> <a class="code" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a97a0dc38e5161b780594d998d313d35e">VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT</a>:</div>
+<div class="line"><a name="l04182"></a><span class="lineno"> 4182</span>&#160;        <span class="keywordflow">return</span> <span class="stringliteral">&quot;Buddy&quot;</span>;</div>
+<div class="line"><a name="l04183"></a><span class="lineno"> 4183</span>&#160;    <span class="keywordflow">case</span> 0:</div>
+<div class="line"><a name="l04184"></a><span class="lineno"> 4184</span>&#160;        <span class="keywordflow">return</span> <span class="stringliteral">&quot;Default&quot;</span>;</div>
+<div class="line"><a name="l04185"></a><span class="lineno"> 4185</span>&#160;    <span class="keywordflow">default</span>:</div>
+<div class="line"><a name="l04186"></a><span class="lineno"> 4186</span>&#160;        VMA_ASSERT(0);</div>
+<div class="line"><a name="l04187"></a><span class="lineno"> 4187</span>&#160;        <span class="keywordflow">return</span> <span class="stringliteral">&quot;&quot;</span>;</div>
+<div class="line"><a name="l04188"></a><span class="lineno"> 4188</span>&#160;    }</div>
+<div class="line"><a name="l04189"></a><span class="lineno"> 4189</span>&#160;}</div>
+<div class="line"><a name="l04190"></a><span class="lineno"> 4190</span>&#160; </div>
+<div class="line"><a name="l04191"></a><span class="lineno"> 4191</span>&#160;<span class="preprocessor">#endif // #if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l04192"></a><span class="lineno"> 4192</span>&#160; </div>
+<div class="line"><a name="l04193"></a><span class="lineno"> 4193</span>&#160;<span class="preprocessor">#ifndef VMA_SORT</span></div>
+<div class="line"><a name="l04194"></a><span class="lineno"> 4194</span>&#160; </div>
+<div class="line"><a name="l04195"></a><span class="lineno"> 4195</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> Iterator, <span class="keyword">typename</span> Compare&gt;</div>
+<div class="line"><a name="l04196"></a><span class="lineno"> 4196</span>&#160;Iterator VmaQuickSortPartition(Iterator beg, Iterator end, Compare cmp)</div>
+<div class="line"><a name="l04197"></a><span class="lineno"> 4197</span>&#160;{</div>
+<div class="line"><a name="l04198"></a><span class="lineno"> 4198</span>&#160;    Iterator centerValue = end; --centerValue;</div>
+<div class="line"><a name="l04199"></a><span class="lineno"> 4199</span>&#160;    Iterator insertIndex = beg;</div>
+<div class="line"><a name="l04200"></a><span class="lineno"> 4200</span>&#160;    <span class="keywordflow">for</span>(Iterator memTypeIndex = beg; memTypeIndex &lt; centerValue; ++memTypeIndex)</div>
+<div class="line"><a name="l04201"></a><span class="lineno"> 4201</span>&#160;    {</div>
+<div class="line"><a name="l04202"></a><span class="lineno"> 4202</span>&#160;        <span class="keywordflow">if</span>(cmp(*memTypeIndex, *centerValue))</div>
+<div class="line"><a name="l04203"></a><span class="lineno"> 4203</span>&#160;        {</div>
+<div class="line"><a name="l04204"></a><span class="lineno"> 4204</span>&#160;            <span class="keywordflow">if</span>(insertIndex != memTypeIndex)</div>
+<div class="line"><a name="l04205"></a><span class="lineno"> 4205</span>&#160;            {</div>
+<div class="line"><a name="l04206"></a><span class="lineno"> 4206</span>&#160;                VMA_SWAP(*memTypeIndex, *insertIndex);</div>
+<div class="line"><a name="l04207"></a><span class="lineno"> 4207</span>&#160;            }</div>
+<div class="line"><a name="l04208"></a><span class="lineno"> 4208</span>&#160;            ++insertIndex;</div>
+<div class="line"><a name="l04209"></a><span class="lineno"> 4209</span>&#160;        }</div>
+<div class="line"><a name="l04210"></a><span class="lineno"> 4210</span>&#160;    }</div>
+<div class="line"><a name="l04211"></a><span class="lineno"> 4211</span>&#160;    <span class="keywordflow">if</span>(insertIndex != centerValue)</div>
+<div class="line"><a name="l04212"></a><span class="lineno"> 4212</span>&#160;    {</div>
+<div class="line"><a name="l04213"></a><span class="lineno"> 4213</span>&#160;        VMA_SWAP(*insertIndex, *centerValue);</div>
+<div class="line"><a name="l04214"></a><span class="lineno"> 4214</span>&#160;    }</div>
+<div class="line"><a name="l04215"></a><span class="lineno"> 4215</span>&#160;    <span class="keywordflow">return</span> insertIndex;</div>
+<div class="line"><a name="l04216"></a><span class="lineno"> 4216</span>&#160;}</div>
+<div class="line"><a name="l04217"></a><span class="lineno"> 4217</span>&#160; </div>
+<div class="line"><a name="l04218"></a><span class="lineno"> 4218</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> Iterator, <span class="keyword">typename</span> Compare&gt;</div>
+<div class="line"><a name="l04219"></a><span class="lineno"> 4219</span>&#160;<span class="keywordtype">void</span> VmaQuickSort(Iterator beg, Iterator end, Compare cmp)</div>
+<div class="line"><a name="l04220"></a><span class="lineno"> 4220</span>&#160;{</div>
+<div class="line"><a name="l04221"></a><span class="lineno"> 4221</span>&#160;    <span class="keywordflow">if</span>(beg &lt; end)</div>
+<div class="line"><a name="l04222"></a><span class="lineno"> 4222</span>&#160;    {</div>
+<div class="line"><a name="l04223"></a><span class="lineno"> 4223</span>&#160;        Iterator it = VmaQuickSortPartition&lt;Iterator, Compare&gt;(beg, end, cmp);</div>
+<div class="line"><a name="l04224"></a><span class="lineno"> 4224</span>&#160;        VmaQuickSort&lt;Iterator, Compare&gt;(beg, it, cmp);</div>
+<div class="line"><a name="l04225"></a><span class="lineno"> 4225</span>&#160;        VmaQuickSort&lt;Iterator, Compare&gt;(it + 1, end, cmp);</div>
+<div class="line"><a name="l04226"></a><span class="lineno"> 4226</span>&#160;    }</div>
+<div class="line"><a name="l04227"></a><span class="lineno"> 4227</span>&#160;}</div>
+<div class="line"><a name="l04228"></a><span class="lineno"> 4228</span>&#160; </div>
+<div class="line"><a name="l04229"></a><span class="lineno"> 4229</span>&#160;<span class="preprocessor">#define VMA_SORT(beg, end, cmp) VmaQuickSort(beg, end, cmp)</span></div>
+<div class="line"><a name="l04230"></a><span class="lineno"> 4230</span>&#160; </div>
+<div class="line"><a name="l04231"></a><span class="lineno"> 4231</span>&#160;<span class="preprocessor">#endif // #ifndef VMA_SORT</span></div>
+<div class="line"><a name="l04232"></a><span class="lineno"> 4232</span>&#160; </div>
+<div class="line"><a name="l04233"></a><span class="lineno"> 4233</span>&#160;<span class="comment">/*</span></div>
+<div class="line"><a name="l04234"></a><span class="lineno"> 4234</span>&#160;<span class="comment">Returns true if two memory blocks occupy overlapping pages.</span></div>
+<div class="line"><a name="l04235"></a><span class="lineno"> 4235</span>&#160;<span class="comment">ResourceA must be in less memory offset than ResourceB.</span></div>
+<div class="line"><a name="l04236"></a><span class="lineno"> 4236</span>&#160;<span class="comment"></span> </div>
+<div class="line"><a name="l04237"></a><span class="lineno"> 4237</span>&#160;<span class="comment">Algorithm is based on &quot;Vulkan 1.0.39 - A Specification (with all registered Vulkan extensions)&quot;</span></div>
+<div class="line"><a name="l04238"></a><span class="lineno"> 4238</span>&#160;<span class="comment">chapter 11.6 &quot;Resource Memory Association&quot;, paragraph &quot;Buffer-Image Granularity&quot;.</span></div>
+<div class="line"><a name="l04239"></a><span class="lineno"> 4239</span>&#160;<span class="comment">*/</span></div>
+<div class="line"><a name="l04240"></a><span class="lineno"> 4240</span>&#160;<span class="keyword">static</span> <span class="keyword">inline</span> <span class="keywordtype">bool</span> VmaBlocksOnSamePage(</div>
+<div class="line"><a name="l04241"></a><span class="lineno"> 4241</span>&#160;    VkDeviceSize resourceAOffset,</div>
+<div class="line"><a name="l04242"></a><span class="lineno"> 4242</span>&#160;    VkDeviceSize resourceASize,</div>
+<div class="line"><a name="l04243"></a><span class="lineno"> 4243</span>&#160;    VkDeviceSize resourceBOffset,</div>
+<div class="line"><a name="l04244"></a><span class="lineno"> 4244</span>&#160;    VkDeviceSize pageSize)</div>
+<div class="line"><a name="l04245"></a><span class="lineno"> 4245</span>&#160;{</div>
+<div class="line"><a name="l04246"></a><span class="lineno"> 4246</span>&#160;    VMA_ASSERT(resourceAOffset + resourceASize &lt;= resourceBOffset &amp;&amp; resourceASize &gt; 0 &amp;&amp; pageSize &gt; 0);</div>
+<div class="line"><a name="l04247"></a><span class="lineno"> 4247</span>&#160;    VkDeviceSize resourceAEnd = resourceAOffset + resourceASize - 1;</div>
+<div class="line"><a name="l04248"></a><span class="lineno"> 4248</span>&#160;    VkDeviceSize resourceAEndPage = resourceAEnd &amp; ~(pageSize - 1);</div>
+<div class="line"><a name="l04249"></a><span class="lineno"> 4249</span>&#160;    VkDeviceSize resourceBStart = resourceBOffset;</div>
+<div class="line"><a name="l04250"></a><span class="lineno"> 4250</span>&#160;    VkDeviceSize resourceBStartPage = resourceBStart &amp; ~(pageSize - 1);</div>
+<div class="line"><a name="l04251"></a><span class="lineno"> 4251</span>&#160;    <span class="keywordflow">return</span> resourceAEndPage == resourceBStartPage;</div>
+<div class="line"><a name="l04252"></a><span class="lineno"> 4252</span>&#160;}</div>
+<div class="line"><a name="l04253"></a><span class="lineno"> 4253</span>&#160; </div>
+<div class="line"><a name="l04254"></a><span class="lineno"> 4254</span>&#160;<span class="keyword">enum</span> VmaSuballocationType</div>
+<div class="line"><a name="l04255"></a><span class="lineno"> 4255</span>&#160;{</div>
+<div class="line"><a name="l04256"></a><span class="lineno"> 4256</span>&#160;    VMA_SUBALLOCATION_TYPE_FREE = 0,</div>
+<div class="line"><a name="l04257"></a><span class="lineno"> 4257</span>&#160;    VMA_SUBALLOCATION_TYPE_UNKNOWN = 1,</div>
+<div class="line"><a name="l04258"></a><span class="lineno"> 4258</span>&#160;    VMA_SUBALLOCATION_TYPE_BUFFER = 2,</div>
+<div class="line"><a name="l04259"></a><span class="lineno"> 4259</span>&#160;    VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN = 3,</div>
+<div class="line"><a name="l04260"></a><span class="lineno"> 4260</span>&#160;    VMA_SUBALLOCATION_TYPE_IMAGE_LINEAR = 4,</div>
+<div class="line"><a name="l04261"></a><span class="lineno"> 4261</span>&#160;    VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL = 5,</div>
+<div class="line"><a name="l04262"></a><span class="lineno"> 4262</span>&#160;    VMA_SUBALLOCATION_TYPE_MAX_ENUM = 0x7FFFFFFF</div>
+<div class="line"><a name="l04263"></a><span class="lineno"> 4263</span>&#160;};</div>
+<div class="line"><a name="l04264"></a><span class="lineno"> 4264</span>&#160; </div>
+<div class="line"><a name="l04265"></a><span class="lineno"> 4265</span>&#160;<span class="comment">/*</span></div>
+<div class="line"><a name="l04266"></a><span class="lineno"> 4266</span>&#160;<span class="comment">Returns true if given suballocation types could conflict and must respect</span></div>
+<div class="line"><a name="l04267"></a><span class="lineno"> 4267</span>&#160;<span class="comment">VkPhysicalDeviceLimits::bufferImageGranularity. They conflict if one is buffer</span></div>
+<div class="line"><a name="l04268"></a><span class="lineno"> 4268</span>&#160;<span class="comment">or linear image and another one is optimal image. If type is unknown, behave</span></div>
+<div class="line"><a name="l04269"></a><span class="lineno"> 4269</span>&#160;<span class="comment">conservatively.</span></div>
+<div class="line"><a name="l04270"></a><span class="lineno"> 4270</span>&#160;<span class="comment">*/</span></div>
+<div class="line"><a name="l04271"></a><span class="lineno"> 4271</span>&#160;<span class="keyword">static</span> <span class="keyword">inline</span> <span class="keywordtype">bool</span> VmaIsBufferImageGranularityConflict(</div>
+<div class="line"><a name="l04272"></a><span class="lineno"> 4272</span>&#160;    VmaSuballocationType suballocType1,</div>
+<div class="line"><a name="l04273"></a><span class="lineno"> 4273</span>&#160;    VmaSuballocationType suballocType2)</div>
+<div class="line"><a name="l04274"></a><span class="lineno"> 4274</span>&#160;{</div>
+<div class="line"><a name="l04275"></a><span class="lineno"> 4275</span>&#160;    <span class="keywordflow">if</span>(suballocType1 &gt; suballocType2)</div>
+<div class="line"><a name="l04276"></a><span class="lineno"> 4276</span>&#160;    {</div>
+<div class="line"><a name="l04277"></a><span class="lineno"> 4277</span>&#160;        VMA_SWAP(suballocType1, suballocType2);</div>
+<div class="line"><a name="l04278"></a><span class="lineno"> 4278</span>&#160;    }</div>
+<div class="line"><a name="l04279"></a><span class="lineno"> 4279</span>&#160;    </div>
+<div class="line"><a name="l04280"></a><span class="lineno"> 4280</span>&#160;    <span class="keywordflow">switch</span>(suballocType1)</div>
+<div class="line"><a name="l04281"></a><span class="lineno"> 4281</span>&#160;    {</div>
+<div class="line"><a name="l04282"></a><span class="lineno"> 4282</span>&#160;    <span class="keywordflow">case</span> VMA_SUBALLOCATION_TYPE_FREE:</div>
+<div class="line"><a name="l04283"></a><span class="lineno"> 4283</span>&#160;        <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l04284"></a><span class="lineno"> 4284</span>&#160;    <span class="keywordflow">case</span> VMA_SUBALLOCATION_TYPE_UNKNOWN:</div>
+<div class="line"><a name="l04285"></a><span class="lineno"> 4285</span>&#160;        <span class="keywordflow">return</span> <span class="keyword">true</span>;</div>
+<div class="line"><a name="l04286"></a><span class="lineno"> 4286</span>&#160;    <span class="keywordflow">case</span> VMA_SUBALLOCATION_TYPE_BUFFER:</div>
+<div class="line"><a name="l04287"></a><span class="lineno"> 4287</span>&#160;        <span class="keywordflow">return</span></div>
+<div class="line"><a name="l04288"></a><span class="lineno"> 4288</span>&#160;            suballocType2 == VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN ||</div>
+<div class="line"><a name="l04289"></a><span class="lineno"> 4289</span>&#160;            suballocType2 == VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL;</div>
+<div class="line"><a name="l04290"></a><span class="lineno"> 4290</span>&#160;    <span class="keywordflow">case</span> VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN:</div>
+<div class="line"><a name="l04291"></a><span class="lineno"> 4291</span>&#160;        <span class="keywordflow">return</span></div>
+<div class="line"><a name="l04292"></a><span class="lineno"> 4292</span>&#160;            suballocType2 == VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN ||</div>
+<div class="line"><a name="l04293"></a><span class="lineno"> 4293</span>&#160;            suballocType2 == VMA_SUBALLOCATION_TYPE_IMAGE_LINEAR ||</div>
+<div class="line"><a name="l04294"></a><span class="lineno"> 4294</span>&#160;            suballocType2 == VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL;</div>
+<div class="line"><a name="l04295"></a><span class="lineno"> 4295</span>&#160;    <span class="keywordflow">case</span> VMA_SUBALLOCATION_TYPE_IMAGE_LINEAR:</div>
+<div class="line"><a name="l04296"></a><span class="lineno"> 4296</span>&#160;        <span class="keywordflow">return</span></div>
+<div class="line"><a name="l04297"></a><span class="lineno"> 4297</span>&#160;            suballocType2 == VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL;</div>
+<div class="line"><a name="l04298"></a><span class="lineno"> 4298</span>&#160;    <span class="keywordflow">case</span> VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL:</div>
+<div class="line"><a name="l04299"></a><span class="lineno"> 4299</span>&#160;        <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l04300"></a><span class="lineno"> 4300</span>&#160;    <span class="keywordflow">default</span>:</div>
+<div class="line"><a name="l04301"></a><span class="lineno"> 4301</span>&#160;        VMA_ASSERT(0);</div>
+<div class="line"><a name="l04302"></a><span class="lineno"> 4302</span>&#160;        <span class="keywordflow">return</span> <span class="keyword">true</span>;</div>
+<div class="line"><a name="l04303"></a><span class="lineno"> 4303</span>&#160;    }</div>
+<div class="line"><a name="l04304"></a><span class="lineno"> 4304</span>&#160;}</div>
+<div class="line"><a name="l04305"></a><span class="lineno"> 4305</span>&#160; </div>
+<div class="line"><a name="l04306"></a><span class="lineno"> 4306</span>&#160;<span class="keyword">static</span> <span class="keywordtype">void</span> VmaWriteMagicValue(<span class="keywordtype">void</span>* pData, VkDeviceSize offset)</div>
+<div class="line"><a name="l04307"></a><span class="lineno"> 4307</span>&#160;{</div>
+<div class="line"><a name="l04308"></a><span class="lineno"> 4308</span>&#160;<span class="preprocessor">#if VMA_DEBUG_MARGIN &gt; 0 &amp;&amp; VMA_DEBUG_DETECT_CORRUPTION</span></div>
+<div class="line"><a name="l04309"></a><span class="lineno"> 4309</span>&#160;    uint32_t* pDst = (uint32_t*)((<span class="keywordtype">char</span>*)pData + offset);</div>
+<div class="line"><a name="l04310"></a><span class="lineno"> 4310</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">size_t</span> numberCount = VMA_DEBUG_MARGIN / <span class="keyword">sizeof</span>(uint32_t);</div>
+<div class="line"><a name="l04311"></a><span class="lineno"> 4311</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = 0; i &lt; numberCount; ++i, ++pDst)</div>
+<div class="line"><a name="l04312"></a><span class="lineno"> 4312</span>&#160;    {</div>
+<div class="line"><a name="l04313"></a><span class="lineno"> 4313</span>&#160;        *pDst = VMA_CORRUPTION_DETECTION_MAGIC_VALUE;</div>
+<div class="line"><a name="l04314"></a><span class="lineno"> 4314</span>&#160;    }</div>
+<div class="line"><a name="l04315"></a><span class="lineno"> 4315</span>&#160;<span class="preprocessor">#else</span></div>
+<div class="line"><a name="l04316"></a><span class="lineno"> 4316</span>&#160;    <span class="comment">// no-op</span></div>
+<div class="line"><a name="l04317"></a><span class="lineno"> 4317</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l04318"></a><span class="lineno"> 4318</span>&#160;}</div>
+<div class="line"><a name="l04319"></a><span class="lineno"> 4319</span>&#160; </div>
+<div class="line"><a name="l04320"></a><span class="lineno"> 4320</span>&#160;<span class="keyword">static</span> <span class="keywordtype">bool</span> VmaValidateMagicValue(<span class="keyword">const</span> <span class="keywordtype">void</span>* pData, VkDeviceSize offset)</div>
+<div class="line"><a name="l04321"></a><span class="lineno"> 4321</span>&#160;{</div>
+<div class="line"><a name="l04322"></a><span class="lineno"> 4322</span>&#160;<span class="preprocessor">#if VMA_DEBUG_MARGIN &gt; 0 &amp;&amp; VMA_DEBUG_DETECT_CORRUPTION</span></div>
+<div class="line"><a name="l04323"></a><span class="lineno"> 4323</span>&#160;    <span class="keyword">const</span> uint32_t* pSrc = (<span class="keyword">const</span> uint32_t*)((<span class="keyword">const</span> <span class="keywordtype">char</span>*)pData + offset);</div>
+<div class="line"><a name="l04324"></a><span class="lineno"> 4324</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">size_t</span> numberCount = VMA_DEBUG_MARGIN / <span class="keyword">sizeof</span>(uint32_t);</div>
+<div class="line"><a name="l04325"></a><span class="lineno"> 4325</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = 0; i &lt; numberCount; ++i, ++pSrc)</div>
+<div class="line"><a name="l04326"></a><span class="lineno"> 4326</span>&#160;    {</div>
+<div class="line"><a name="l04327"></a><span class="lineno"> 4327</span>&#160;        <span class="keywordflow">if</span>(*pSrc != VMA_CORRUPTION_DETECTION_MAGIC_VALUE)</div>
+<div class="line"><a name="l04328"></a><span class="lineno"> 4328</span>&#160;        {</div>
+<div class="line"><a name="l04329"></a><span class="lineno"> 4329</span>&#160;            <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l04330"></a><span class="lineno"> 4330</span>&#160;        }</div>
+<div class="line"><a name="l04331"></a><span class="lineno"> 4331</span>&#160;    }</div>
+<div class="line"><a name="l04332"></a><span class="lineno"> 4332</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l04333"></a><span class="lineno"> 4333</span>&#160;    <span class="keywordflow">return</span> <span class="keyword">true</span>;</div>
+<div class="line"><a name="l04334"></a><span class="lineno"> 4334</span>&#160;}</div>
+<div class="line"><a name="l04335"></a><span class="lineno"> 4335</span>&#160; </div>
+<div class="line"><a name="l04336"></a><span class="lineno"> 4336</span>&#160;<span class="comment">/*</span></div>
+<div class="line"><a name="l04337"></a><span class="lineno"> 4337</span>&#160;<span class="comment">Fills structure with parameters of an example buffer to be used for transfers</span></div>
+<div class="line"><a name="l04338"></a><span class="lineno"> 4338</span>&#160;<span class="comment">during GPU memory defragmentation.</span></div>
+<div class="line"><a name="l04339"></a><span class="lineno"> 4339</span>&#160;<span class="comment">*/</span></div>
+<div class="line"><a name="l04340"></a><span class="lineno"> 4340</span>&#160;<span class="keyword">static</span> <span class="keywordtype">void</span> VmaFillGpuDefragmentationBufferCreateInfo(VkBufferCreateInfo&amp; outBufCreateInfo)</div>
+<div class="line"><a name="l04341"></a><span class="lineno"> 4341</span>&#160;{</div>
+<div class="line"><a name="l04342"></a><span class="lineno"> 4342</span>&#160;    memset(&amp;outBufCreateInfo, 0, <span class="keyword">sizeof</span>(outBufCreateInfo));</div>
+<div class="line"><a name="l04343"></a><span class="lineno"> 4343</span>&#160;    outBufCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;</div>
+<div class="line"><a name="l04344"></a><span class="lineno"> 4344</span>&#160;    outBufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;</div>
+<div class="line"><a name="l04345"></a><span class="lineno"> 4345</span>&#160;    outBufCreateInfo.size = (VkDeviceSize)VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE; <span class="comment">// Example size.</span></div>
+<div class="line"><a name="l04346"></a><span class="lineno"> 4346</span>&#160;}</div>
+<div class="line"><a name="l04347"></a><span class="lineno"> 4347</span>&#160; </div>
+<div class="line"><a name="l04348"></a><span class="lineno"> 4348</span>&#160;<span class="comment">// Helper RAII class to lock a mutex in constructor and unlock it in destructor (at the end of scope).</span></div>
+<div class="line"><a name="l04349"></a><span class="lineno"> 4349</span>&#160;<span class="keyword">struct </span>VmaMutexLock</div>
+<div class="line"><a name="l04350"></a><span class="lineno"> 4350</span>&#160;{</div>
+<div class="line"><a name="l04351"></a><span class="lineno"> 4351</span>&#160;    VMA_CLASS_NO_COPY(VmaMutexLock)</div>
+<div class="line"><a name="l04352"></a><span class="lineno"> 4352</span>&#160;<span class="keyword">public</span>:</div>
+<div class="line"><a name="l04353"></a><span class="lineno"> 4353</span>&#160;    VmaMutexLock(VMA_MUTEX&amp; mutex, <span class="keywordtype">bool</span> useMutex = <span class="keyword">true</span>) :</div>
+<div class="line"><a name="l04354"></a><span class="lineno"> 4354</span>&#160;        m_pMutex(useMutex ? &amp;mutex : VMA_NULL)</div>
+<div class="line"><a name="l04355"></a><span class="lineno"> 4355</span>&#160;    { <span class="keywordflow">if</span>(m_pMutex) { m_pMutex-&gt;Lock(); } }</div>
+<div class="line"><a name="l04356"></a><span class="lineno"> 4356</span>&#160;    ~VmaMutexLock()</div>
+<div class="line"><a name="l04357"></a><span class="lineno"> 4357</span>&#160;    { <span class="keywordflow">if</span>(m_pMutex) { m_pMutex-&gt;Unlock(); } }</div>
+<div class="line"><a name="l04358"></a><span class="lineno"> 4358</span>&#160;<span class="keyword">private</span>:</div>
+<div class="line"><a name="l04359"></a><span class="lineno"> 4359</span>&#160;    VMA_MUTEX* m_pMutex;</div>
+<div class="line"><a name="l04360"></a><span class="lineno"> 4360</span>&#160;};</div>
+<div class="line"><a name="l04361"></a><span class="lineno"> 4361</span>&#160; </div>
+<div class="line"><a name="l04362"></a><span class="lineno"> 4362</span>&#160;<span class="comment">// Helper RAII class to lock a RW mutex in constructor and unlock it in destructor (at the end of scope), for reading.</span></div>
+<div class="line"><a name="l04363"></a><span class="lineno"> 4363</span>&#160;<span class="keyword">struct </span>VmaMutexLockRead</div>
+<div class="line"><a name="l04364"></a><span class="lineno"> 4364</span>&#160;{</div>
+<div class="line"><a name="l04365"></a><span class="lineno"> 4365</span>&#160;    VMA_CLASS_NO_COPY(VmaMutexLockRead)</div>
+<div class="line"><a name="l04366"></a><span class="lineno"> 4366</span>&#160;<span class="keyword">public</span>:</div>
+<div class="line"><a name="l04367"></a><span class="lineno"> 4367</span>&#160;    VmaMutexLockRead(VMA_RW_MUTEX&amp; mutex, <span class="keywordtype">bool</span> useMutex) :</div>
+<div class="line"><a name="l04368"></a><span class="lineno"> 4368</span>&#160;        m_pMutex(useMutex ? &amp;mutex : VMA_NULL)</div>
+<div class="line"><a name="l04369"></a><span class="lineno"> 4369</span>&#160;    { <span class="keywordflow">if</span>(m_pMutex) { m_pMutex-&gt;LockRead(); } }</div>
+<div class="line"><a name="l04370"></a><span class="lineno"> 4370</span>&#160;    ~VmaMutexLockRead() { <span class="keywordflow">if</span>(m_pMutex) { m_pMutex-&gt;UnlockRead(); } }</div>
+<div class="line"><a name="l04371"></a><span class="lineno"> 4371</span>&#160;<span class="keyword">private</span>:</div>
+<div class="line"><a name="l04372"></a><span class="lineno"> 4372</span>&#160;    VMA_RW_MUTEX* m_pMutex;</div>
+<div class="line"><a name="l04373"></a><span class="lineno"> 4373</span>&#160;};</div>
+<div class="line"><a name="l04374"></a><span class="lineno"> 4374</span>&#160; </div>
+<div class="line"><a name="l04375"></a><span class="lineno"> 4375</span>&#160;<span class="comment">// Helper RAII class to lock a RW mutex in constructor and unlock it in destructor (at the end of scope), for writing.</span></div>
+<div class="line"><a name="l04376"></a><span class="lineno"> 4376</span>&#160;<span class="keyword">struct </span>VmaMutexLockWrite</div>
+<div class="line"><a name="l04377"></a><span class="lineno"> 4377</span>&#160;{</div>
+<div class="line"><a name="l04378"></a><span class="lineno"> 4378</span>&#160;    VMA_CLASS_NO_COPY(VmaMutexLockWrite)</div>
+<div class="line"><a name="l04379"></a><span class="lineno"> 4379</span>&#160;<span class="keyword">public</span>:</div>
+<div class="line"><a name="l04380"></a><span class="lineno"> 4380</span>&#160;    VmaMutexLockWrite(VMA_RW_MUTEX&amp; mutex, <span class="keywordtype">bool</span> useMutex) :</div>
+<div class="line"><a name="l04381"></a><span class="lineno"> 4381</span>&#160;        m_pMutex(useMutex ? &amp;mutex : VMA_NULL)</div>
+<div class="line"><a name="l04382"></a><span class="lineno"> 4382</span>&#160;    { <span class="keywordflow">if</span>(m_pMutex) { m_pMutex-&gt;LockWrite(); } }</div>
+<div class="line"><a name="l04383"></a><span class="lineno"> 4383</span>&#160;    ~VmaMutexLockWrite() { <span class="keywordflow">if</span>(m_pMutex) { m_pMutex-&gt;UnlockWrite(); } }</div>
+<div class="line"><a name="l04384"></a><span class="lineno"> 4384</span>&#160;<span class="keyword">private</span>:</div>
+<div class="line"><a name="l04385"></a><span class="lineno"> 4385</span>&#160;    VMA_RW_MUTEX* m_pMutex;</div>
+<div class="line"><a name="l04386"></a><span class="lineno"> 4386</span>&#160;};</div>
+<div class="line"><a name="l04387"></a><span class="lineno"> 4387</span>&#160; </div>
+<div class="line"><a name="l04388"></a><span class="lineno"> 4388</span>&#160;<span class="preprocessor">#if VMA_DEBUG_GLOBAL_MUTEX</span></div>
+<div class="line"><a name="l04389"></a><span class="lineno"> 4389</span>&#160;    <span class="keyword">static</span> VMA_MUTEX gDebugGlobalMutex;</div>
+<div class="line"><a name="l04390"></a><span class="lineno"> 4390</span>&#160;<span class="preprocessor">    #define VMA_DEBUG_GLOBAL_MUTEX_LOCK VmaMutexLock debugGlobalMutexLock(gDebugGlobalMutex, true);</span></div>
+<div class="line"><a name="l04391"></a><span class="lineno"> 4391</span>&#160;<span class="preprocessor">#else</span></div>
+<div class="line"><a name="l04392"></a><span class="lineno"> 4392</span>&#160;<span class="preprocessor">    #define VMA_DEBUG_GLOBAL_MUTEX_LOCK</span></div>
+<div class="line"><a name="l04393"></a><span class="lineno"> 4393</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l04394"></a><span class="lineno"> 4394</span>&#160; </div>
+<div class="line"><a name="l04395"></a><span class="lineno"> 4395</span>&#160;<span class="comment">// Minimum size of a free suballocation to register it in the free suballocation collection.</span></div>
+<div class="line"><a name="l04396"></a><span class="lineno"> 4396</span>&#160;<span class="keyword">static</span> <span class="keyword">const</span> VkDeviceSize VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER = 16;</div>
+<div class="line"><a name="l04397"></a><span class="lineno"> 4397</span>&#160; </div>
+<div class="line"><a name="l04398"></a><span class="lineno"> 4398</span>&#160;<span class="comment">/*</span></div>
+<div class="line"><a name="l04399"></a><span class="lineno"> 4399</span>&#160;<span class="comment">Performs binary search and returns iterator to first element that is greater or</span></div>
+<div class="line"><a name="l04400"></a><span class="lineno"> 4400</span>&#160;<span class="comment">equal to (key), according to comparison (cmp).</span></div>
+<div class="line"><a name="l04401"></a><span class="lineno"> 4401</span>&#160;<span class="comment"></span> </div>
+<div class="line"><a name="l04402"></a><span class="lineno"> 4402</span>&#160;<span class="comment">Cmp should return true if first argument is less than second argument.</span></div>
+<div class="line"><a name="l04403"></a><span class="lineno"> 4403</span>&#160;<span class="comment"></span> </div>
+<div class="line"><a name="l04404"></a><span class="lineno"> 4404</span>&#160;<span class="comment">Returned value is the found element, if present in the collection or place where</span></div>
+<div class="line"><a name="l04405"></a><span class="lineno"> 4405</span>&#160;<span class="comment">new element with value (key) should be inserted.</span></div>
+<div class="line"><a name="l04406"></a><span class="lineno"> 4406</span>&#160;<span class="comment">*/</span></div>
+<div class="line"><a name="l04407"></a><span class="lineno"> 4407</span>&#160;<span class="keyword">template</span> &lt;<span class="keyword">typename</span> CmpLess, <span class="keyword">typename</span> IterT, <span class="keyword">typename</span> KeyT&gt;</div>
+<div class="line"><a name="l04408"></a><span class="lineno"> 4408</span>&#160;<span class="keyword">static</span> IterT VmaBinaryFindFirstNotLess(IterT beg, IterT end, <span class="keyword">const</span> KeyT &amp;key, <span class="keyword">const</span> CmpLess&amp; cmp)</div>
+<div class="line"><a name="l04409"></a><span class="lineno"> 4409</span>&#160;{</div>
+<div class="line"><a name="l04410"></a><span class="lineno"> 4410</span>&#160;    <span class="keywordtype">size_t</span> down = 0, up = (end - beg);</div>
+<div class="line"><a name="l04411"></a><span class="lineno"> 4411</span>&#160;    <span class="keywordflow">while</span>(down &lt; up)</div>
+<div class="line"><a name="l04412"></a><span class="lineno"> 4412</span>&#160;    {</div>
+<div class="line"><a name="l04413"></a><span class="lineno"> 4413</span>&#160;        <span class="keyword">const</span> <span class="keywordtype">size_t</span> mid = (down + up) / 2;</div>
+<div class="line"><a name="l04414"></a><span class="lineno"> 4414</span>&#160;        <span class="keywordflow">if</span>(cmp(*(beg+mid), key))</div>
+<div class="line"><a name="l04415"></a><span class="lineno"> 4415</span>&#160;        {</div>
+<div class="line"><a name="l04416"></a><span class="lineno"> 4416</span>&#160;            down = mid + 1;</div>
+<div class="line"><a name="l04417"></a><span class="lineno"> 4417</span>&#160;        }</div>
+<div class="line"><a name="l04418"></a><span class="lineno"> 4418</span>&#160;        <span class="keywordflow">else</span></div>
+<div class="line"><a name="l04419"></a><span class="lineno"> 4419</span>&#160;        {</div>
+<div class="line"><a name="l04420"></a><span class="lineno"> 4420</span>&#160;            up = mid;</div>
+<div class="line"><a name="l04421"></a><span class="lineno"> 4421</span>&#160;        }</div>
+<div class="line"><a name="l04422"></a><span class="lineno"> 4422</span>&#160;    }</div>
+<div class="line"><a name="l04423"></a><span class="lineno"> 4423</span>&#160;    <span class="keywordflow">return</span> beg + down;</div>
+<div class="line"><a name="l04424"></a><span class="lineno"> 4424</span>&#160;}</div>
+<div class="line"><a name="l04425"></a><span class="lineno"> 4425</span>&#160; </div>
+<div class="line"><a name="l04426"></a><span class="lineno"> 4426</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> CmpLess, <span class="keyword">typename</span> IterT, <span class="keyword">typename</span> KeyT&gt;</div>
+<div class="line"><a name="l04427"></a><span class="lineno"> 4427</span>&#160;IterT VmaBinaryFindSorted(<span class="keyword">const</span> IterT&amp; beg, <span class="keyword">const</span> IterT&amp; end, <span class="keyword">const</span> KeyT&amp; value, <span class="keyword">const</span> CmpLess&amp; cmp)</div>
+<div class="line"><a name="l04428"></a><span class="lineno"> 4428</span>&#160;{</div>
+<div class="line"><a name="l04429"></a><span class="lineno"> 4429</span>&#160;    IterT it = VmaBinaryFindFirstNotLess&lt;CmpLess, IterT, KeyT&gt;(</div>
+<div class="line"><a name="l04430"></a><span class="lineno"> 4430</span>&#160;        beg, end, value, cmp);</div>
+<div class="line"><a name="l04431"></a><span class="lineno"> 4431</span>&#160;    <span class="keywordflow">if</span>(it == end ||</div>
+<div class="line"><a name="l04432"></a><span class="lineno"> 4432</span>&#160;        (!cmp(*it, value) &amp;&amp; !cmp(value, *it)))</div>
+<div class="line"><a name="l04433"></a><span class="lineno"> 4433</span>&#160;    {</div>
+<div class="line"><a name="l04434"></a><span class="lineno"> 4434</span>&#160;        <span class="keywordflow">return</span> it;</div>
+<div class="line"><a name="l04435"></a><span class="lineno"> 4435</span>&#160;    }</div>
+<div class="line"><a name="l04436"></a><span class="lineno"> 4436</span>&#160;    <span class="keywordflow">return</span> end;</div>
+<div class="line"><a name="l04437"></a><span class="lineno"> 4437</span>&#160;}</div>
+<div class="line"><a name="l04438"></a><span class="lineno"> 4438</span>&#160; </div>
+<div class="line"><a name="l04439"></a><span class="lineno"> 4439</span>&#160;<span class="comment">/*</span></div>
+<div class="line"><a name="l04440"></a><span class="lineno"> 4440</span>&#160;<span class="comment">Returns true if all pointers in the array are not-null and unique.</span></div>
+<div class="line"><a name="l04441"></a><span class="lineno"> 4441</span>&#160;<span class="comment">Warning! O(n^2) complexity. Use only inside VMA_HEAVY_ASSERT.</span></div>
+<div class="line"><a name="l04442"></a><span class="lineno"> 4442</span>&#160;<span class="comment">T must be pointer type, e.g. VmaAllocation, VmaPool.</span></div>
+<div class="line"><a name="l04443"></a><span class="lineno"> 4443</span>&#160;<span class="comment">*/</span></div>
+<div class="line"><a name="l04444"></a><span class="lineno"> 4444</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</div>
+<div class="line"><a name="l04445"></a><span class="lineno"> 4445</span>&#160;<span class="keyword">static</span> <span class="keywordtype">bool</span> VmaValidatePointerArray(uint32_t count, <span class="keyword">const</span> T* arr)</div>
+<div class="line"><a name="l04446"></a><span class="lineno"> 4446</span>&#160;{</div>
+<div class="line"><a name="l04447"></a><span class="lineno"> 4447</span>&#160;    <span class="keywordflow">for</span>(uint32_t i = 0; i &lt; count; ++i)</div>
+<div class="line"><a name="l04448"></a><span class="lineno"> 4448</span>&#160;    {</div>
+<div class="line"><a name="l04449"></a><span class="lineno"> 4449</span>&#160;        <span class="keyword">const</span> T iPtr = arr[i];</div>
+<div class="line"><a name="l04450"></a><span class="lineno"> 4450</span>&#160;        <span class="keywordflow">if</span>(iPtr == VMA_NULL)</div>
+<div class="line"><a name="l04451"></a><span class="lineno"> 4451</span>&#160;        {</div>
+<div class="line"><a name="l04452"></a><span class="lineno"> 4452</span>&#160;            <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l04453"></a><span class="lineno"> 4453</span>&#160;        }</div>
+<div class="line"><a name="l04454"></a><span class="lineno"> 4454</span>&#160;        <span class="keywordflow">for</span>(uint32_t j = i + 1; j &lt; count; ++j)</div>
+<div class="line"><a name="l04455"></a><span class="lineno"> 4455</span>&#160;        {</div>
+<div class="line"><a name="l04456"></a><span class="lineno"> 4456</span>&#160;            <span class="keywordflow">if</span>(iPtr == arr[j])</div>
+<div class="line"><a name="l04457"></a><span class="lineno"> 4457</span>&#160;            {</div>
+<div class="line"><a name="l04458"></a><span class="lineno"> 4458</span>&#160;                <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l04459"></a><span class="lineno"> 4459</span>&#160;            }</div>
+<div class="line"><a name="l04460"></a><span class="lineno"> 4460</span>&#160;        }</div>
+<div class="line"><a name="l04461"></a><span class="lineno"> 4461</span>&#160;    }</div>
+<div class="line"><a name="l04462"></a><span class="lineno"> 4462</span>&#160;    <span class="keywordflow">return</span> <span class="keyword">true</span>;</div>
+<div class="line"><a name="l04463"></a><span class="lineno"> 4463</span>&#160;}</div>
+<div class="line"><a name="l04464"></a><span class="lineno"> 4464</span>&#160; </div>
+<div class="line"><a name="l04465"></a><span class="lineno"> 4465</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> MainT, <span class="keyword">typename</span> NewT&gt;</div>
+<div class="line"><a name="l04466"></a><span class="lineno"> 4466</span>&#160;<span class="keyword">static</span> <span class="keyword">inline</span> <span class="keywordtype">void</span> VmaPnextChainPushFront(MainT* mainStruct, NewT* newStruct)</div>
+<div class="line"><a name="l04467"></a><span class="lineno"> 4467</span>&#160;{</div>
+<div class="line"><a name="l04468"></a><span class="lineno"> 4468</span>&#160;    newStruct-&gt;pNext = mainStruct-&gt;pNext;</div>
+<div class="line"><a name="l04469"></a><span class="lineno"> 4469</span>&#160;    mainStruct-&gt;pNext = newStruct;</div>
+<div class="line"><a name="l04470"></a><span class="lineno"> 4470</span>&#160;}</div>
+<div class="line"><a name="l04471"></a><span class="lineno"> 4471</span>&#160; </div>
+<div class="line"><a name="l04473"></a><span class="lineno"> 4473</span>&#160;<span class="comment">// Memory allocation</span></div>
+<div class="line"><a name="l04474"></a><span class="lineno"> 4474</span>&#160; </div>
+<div class="line"><a name="l04475"></a><span class="lineno"> 4475</span>&#160;<span class="keyword">static</span> <span class="keywordtype">void</span>* VmaMalloc(<span class="keyword">const</span> VkAllocationCallbacks* pAllocationCallbacks, <span class="keywordtype">size_t</span> size, <span class="keywordtype">size_t</span> alignment)</div>
+<div class="line"><a name="l04476"></a><span class="lineno"> 4476</span>&#160;{</div>
+<div class="line"><a name="l04477"></a><span class="lineno"> 4477</span>&#160;    <span class="keywordflow">if</span>((pAllocationCallbacks != VMA_NULL) &amp;&amp;</div>
+<div class="line"><a name="l04478"></a><span class="lineno"> 4478</span>&#160;        (pAllocationCallbacks-&gt;pfnAllocation != VMA_NULL))</div>
+<div class="line"><a name="l04479"></a><span class="lineno"> 4479</span>&#160;    {</div>
+<div class="line"><a name="l04480"></a><span class="lineno"> 4480</span>&#160;        <span class="keywordflow">return</span> (*pAllocationCallbacks-&gt;pfnAllocation)(</div>
+<div class="line"><a name="l04481"></a><span class="lineno"> 4481</span>&#160;            pAllocationCallbacks-&gt;pUserData,</div>
+<div class="line"><a name="l04482"></a><span class="lineno"> 4482</span>&#160;            size,</div>
+<div class="line"><a name="l04483"></a><span class="lineno"> 4483</span>&#160;            alignment,</div>
+<div class="line"><a name="l04484"></a><span class="lineno"> 4484</span>&#160;            VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);</div>
+<div class="line"><a name="l04485"></a><span class="lineno"> 4485</span>&#160;    }</div>
+<div class="line"><a name="l04486"></a><span class="lineno"> 4486</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l04487"></a><span class="lineno"> 4487</span>&#160;    {</div>
+<div class="line"><a name="l04488"></a><span class="lineno"> 4488</span>&#160;        <span class="keywordflow">return</span> VMA_SYSTEM_ALIGNED_MALLOC(size, alignment);</div>
+<div class="line"><a name="l04489"></a><span class="lineno"> 4489</span>&#160;    }</div>
+<div class="line"><a name="l04490"></a><span class="lineno"> 4490</span>&#160;}</div>
+<div class="line"><a name="l04491"></a><span class="lineno"> 4491</span>&#160; </div>
+<div class="line"><a name="l04492"></a><span class="lineno"> 4492</span>&#160;<span class="keyword">static</span> <span class="keywordtype">void</span> VmaFree(<span class="keyword">const</span> VkAllocationCallbacks* pAllocationCallbacks, <span class="keywordtype">void</span>* ptr)</div>
+<div class="line"><a name="l04493"></a><span class="lineno"> 4493</span>&#160;{</div>
+<div class="line"><a name="l04494"></a><span class="lineno"> 4494</span>&#160;    <span class="keywordflow">if</span>((pAllocationCallbacks != VMA_NULL) &amp;&amp;</div>
+<div class="line"><a name="l04495"></a><span class="lineno"> 4495</span>&#160;        (pAllocationCallbacks-&gt;pfnFree != VMA_NULL))</div>
+<div class="line"><a name="l04496"></a><span class="lineno"> 4496</span>&#160;    {</div>
+<div class="line"><a name="l04497"></a><span class="lineno"> 4497</span>&#160;        (*pAllocationCallbacks-&gt;pfnFree)(pAllocationCallbacks-&gt;pUserData, ptr);</div>
+<div class="line"><a name="l04498"></a><span class="lineno"> 4498</span>&#160;    }</div>
+<div class="line"><a name="l04499"></a><span class="lineno"> 4499</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l04500"></a><span class="lineno"> 4500</span>&#160;    {</div>
+<div class="line"><a name="l04501"></a><span class="lineno"> 4501</span>&#160;        VMA_SYSTEM_FREE(ptr);</div>
+<div class="line"><a name="l04502"></a><span class="lineno"> 4502</span>&#160;    }</div>
+<div class="line"><a name="l04503"></a><span class="lineno"> 4503</span>&#160;}</div>
+<div class="line"><a name="l04504"></a><span class="lineno"> 4504</span>&#160; </div>
+<div class="line"><a name="l04505"></a><span class="lineno"> 4505</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</div>
+<div class="line"><a name="l04506"></a><span class="lineno"> 4506</span>&#160;<span class="keyword">static</span> T* VmaAllocate(<span class="keyword">const</span> VkAllocationCallbacks* pAllocationCallbacks)</div>
+<div class="line"><a name="l04507"></a><span class="lineno"> 4507</span>&#160;{</div>
+<div class="line"><a name="l04508"></a><span class="lineno"> 4508</span>&#160;    <span class="keywordflow">return</span> (T*)VmaMalloc(pAllocationCallbacks, <span class="keyword">sizeof</span>(T), VMA_ALIGN_OF(T));</div>
+<div class="line"><a name="l04509"></a><span class="lineno"> 4509</span>&#160;}</div>
+<div class="line"><a name="l04510"></a><span class="lineno"> 4510</span>&#160; </div>
+<div class="line"><a name="l04511"></a><span class="lineno"> 4511</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</div>
+<div class="line"><a name="l04512"></a><span class="lineno"> 4512</span>&#160;<span class="keyword">static</span> T* VmaAllocateArray(<span class="keyword">const</span> VkAllocationCallbacks* pAllocationCallbacks, <span class="keywordtype">size_t</span> count)</div>
+<div class="line"><a name="l04513"></a><span class="lineno"> 4513</span>&#160;{</div>
+<div class="line"><a name="l04514"></a><span class="lineno"> 4514</span>&#160;    <span class="keywordflow">return</span> (T*)VmaMalloc(pAllocationCallbacks, <span class="keyword">sizeof</span>(T) * count, VMA_ALIGN_OF(T));</div>
+<div class="line"><a name="l04515"></a><span class="lineno"> 4515</span>&#160;}</div>
+<div class="line"><a name="l04516"></a><span class="lineno"> 4516</span>&#160; </div>
+<div class="line"><a name="l04517"></a><span class="lineno"> 4517</span>&#160;<span class="preprocessor">#define vma_new(allocator, type)   new(VmaAllocate&lt;type&gt;(allocator))(type)</span></div>
+<div class="line"><a name="l04518"></a><span class="lineno"> 4518</span>&#160; </div>
+<div class="line"><a name="l04519"></a><span class="lineno"> 4519</span>&#160;<span class="preprocessor">#define vma_new_array(allocator, type, count)   new(VmaAllocateArray&lt;type&gt;((allocator), (count)))(type)</span></div>
+<div class="line"><a name="l04520"></a><span class="lineno"> 4520</span>&#160; </div>
+<div class="line"><a name="l04521"></a><span class="lineno"> 4521</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</div>
+<div class="line"><a name="l04522"></a><span class="lineno"> 4522</span>&#160;<span class="keyword">static</span> <span class="keywordtype">void</span> vma_delete(<span class="keyword">const</span> VkAllocationCallbacks* pAllocationCallbacks, T* ptr)</div>
+<div class="line"><a name="l04523"></a><span class="lineno"> 4523</span>&#160;{</div>
+<div class="line"><a name="l04524"></a><span class="lineno"> 4524</span>&#160;    ptr-&gt;~T();</div>
+<div class="line"><a name="l04525"></a><span class="lineno"> 4525</span>&#160;    VmaFree(pAllocationCallbacks, ptr);</div>
+<div class="line"><a name="l04526"></a><span class="lineno"> 4526</span>&#160;}</div>
+<div class="line"><a name="l04527"></a><span class="lineno"> 4527</span>&#160; </div>
+<div class="line"><a name="l04528"></a><span class="lineno"> 4528</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</div>
+<div class="line"><a name="l04529"></a><span class="lineno"> 4529</span>&#160;<span class="keyword">static</span> <span class="keywordtype">void</span> vma_delete_array(<span class="keyword">const</span> VkAllocationCallbacks* pAllocationCallbacks, T* ptr, <span class="keywordtype">size_t</span> count)</div>
+<div class="line"><a name="l04530"></a><span class="lineno"> 4530</span>&#160;{</div>
+<div class="line"><a name="l04531"></a><span class="lineno"> 4531</span>&#160;    <span class="keywordflow">if</span>(ptr != VMA_NULL)</div>
+<div class="line"><a name="l04532"></a><span class="lineno"> 4532</span>&#160;    {</div>
+<div class="line"><a name="l04533"></a><span class="lineno"> 4533</span>&#160;        <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = count; i--; )</div>
+<div class="line"><a name="l04534"></a><span class="lineno"> 4534</span>&#160;        {</div>
+<div class="line"><a name="l04535"></a><span class="lineno"> 4535</span>&#160;            ptr[i].~T();</div>
+<div class="line"><a name="l04536"></a><span class="lineno"> 4536</span>&#160;        }</div>
+<div class="line"><a name="l04537"></a><span class="lineno"> 4537</span>&#160;        VmaFree(pAllocationCallbacks, ptr);</div>
+<div class="line"><a name="l04538"></a><span class="lineno"> 4538</span>&#160;    }</div>
+<div class="line"><a name="l04539"></a><span class="lineno"> 4539</span>&#160;}</div>
+<div class="line"><a name="l04540"></a><span class="lineno"> 4540</span>&#160; </div>
+<div class="line"><a name="l04541"></a><span class="lineno"> 4541</span>&#160;<span class="keyword">static</span> <span class="keywordtype">char</span>* VmaCreateStringCopy(<span class="keyword">const</span> VkAllocationCallbacks* allocs, <span class="keyword">const</span> <span class="keywordtype">char</span>* srcStr)</div>
+<div class="line"><a name="l04542"></a><span class="lineno"> 4542</span>&#160;{</div>
+<div class="line"><a name="l04543"></a><span class="lineno"> 4543</span>&#160;    <span class="keywordflow">if</span>(srcStr != VMA_NULL)</div>
+<div class="line"><a name="l04544"></a><span class="lineno"> 4544</span>&#160;    {</div>
+<div class="line"><a name="l04545"></a><span class="lineno"> 4545</span>&#160;        <span class="keyword">const</span> <span class="keywordtype">size_t</span> len = strlen(srcStr);</div>
+<div class="line"><a name="l04546"></a><span class="lineno"> 4546</span>&#160;        <span class="keywordtype">char</span>* <span class="keyword">const</span> result = vma_new_array(allocs, <span class="keywordtype">char</span>, len + 1);</div>
+<div class="line"><a name="l04547"></a><span class="lineno"> 4547</span>&#160;        memcpy(result, srcStr, len + 1);</div>
+<div class="line"><a name="l04548"></a><span class="lineno"> 4548</span>&#160;        <span class="keywordflow">return</span> result;</div>
+<div class="line"><a name="l04549"></a><span class="lineno"> 4549</span>&#160;    }</div>
+<div class="line"><a name="l04550"></a><span class="lineno"> 4550</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l04551"></a><span class="lineno"> 4551</span>&#160;    {</div>
+<div class="line"><a name="l04552"></a><span class="lineno"> 4552</span>&#160;        <span class="keywordflow">return</span> VMA_NULL;</div>
+<div class="line"><a name="l04553"></a><span class="lineno"> 4553</span>&#160;    }</div>
+<div class="line"><a name="l04554"></a><span class="lineno"> 4554</span>&#160;}</div>
+<div class="line"><a name="l04555"></a><span class="lineno"> 4555</span>&#160; </div>
+<div class="line"><a name="l04556"></a><span class="lineno"> 4556</span>&#160;<span class="keyword">static</span> <span class="keywordtype">void</span> VmaFreeString(<span class="keyword">const</span> VkAllocationCallbacks* allocs, <span class="keywordtype">char</span>* str)</div>
+<div class="line"><a name="l04557"></a><span class="lineno"> 4557</span>&#160;{</div>
+<div class="line"><a name="l04558"></a><span class="lineno"> 4558</span>&#160;    <span class="keywordflow">if</span>(str != VMA_NULL)</div>
+<div class="line"><a name="l04559"></a><span class="lineno"> 4559</span>&#160;    {</div>
+<div class="line"><a name="l04560"></a><span class="lineno"> 4560</span>&#160;        <span class="keyword">const</span> <span class="keywordtype">size_t</span> len = strlen(str);</div>
+<div class="line"><a name="l04561"></a><span class="lineno"> 4561</span>&#160;        vma_delete_array(allocs, str, len + 1);</div>
+<div class="line"><a name="l04562"></a><span class="lineno"> 4562</span>&#160;    }</div>
+<div class="line"><a name="l04563"></a><span class="lineno"> 4563</span>&#160;}</div>
+<div class="line"><a name="l04564"></a><span class="lineno"> 4564</span>&#160; </div>
+<div class="line"><a name="l04565"></a><span class="lineno"> 4565</span>&#160;<span class="comment">// STL-compatible allocator.</span></div>
+<div class="line"><a name="l04566"></a><span class="lineno"> 4566</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</div>
+<div class="line"><a name="l04567"></a><span class="lineno"> 4567</span>&#160;<span class="keyword">class </span>VmaStlAllocator</div>
+<div class="line"><a name="l04568"></a><span class="lineno"> 4568</span>&#160;{</div>
+<div class="line"><a name="l04569"></a><span class="lineno"> 4569</span>&#160;<span class="keyword">public</span>:</div>
+<div class="line"><a name="l04570"></a><span class="lineno"> 4570</span>&#160;    <span class="keyword">const</span> VkAllocationCallbacks* <span class="keyword">const</span> m_pCallbacks;</div>
+<div class="line"><a name="l04571"></a><span class="lineno"> 4571</span>&#160;    <span class="keyword">typedef</span> T value_type;</div>
+<div class="line"><a name="l04572"></a><span class="lineno"> 4572</span>&#160;    </div>
+<div class="line"><a name="l04573"></a><span class="lineno"> 4573</span>&#160;    VmaStlAllocator(<span class="keyword">const</span> VkAllocationCallbacks* pCallbacks) : m_pCallbacks(pCallbacks) { }</div>
+<div class="line"><a name="l04574"></a><span class="lineno"> 4574</span>&#160;    <span class="keyword">template</span>&lt;<span class="keyword">typename</span> U&gt; VmaStlAllocator(<span class="keyword">const</span> VmaStlAllocator&lt;U&gt;&amp; src) : m_pCallbacks(src.m_pCallbacks) { }</div>
+<div class="line"><a name="l04575"></a><span class="lineno"> 4575</span>&#160; </div>
+<div class="line"><a name="l04576"></a><span class="lineno"> 4576</span>&#160;    T* allocate(<span class="keywordtype">size_t</span> n) { <span class="keywordflow">return</span> VmaAllocateArray&lt;T&gt;(m_pCallbacks, n); }</div>
+<div class="line"><a name="l04577"></a><span class="lineno"> 4577</span>&#160;    <span class="keywordtype">void</span> deallocate(T* p, <span class="keywordtype">size_t</span> n) { VmaFree(m_pCallbacks, p); }</div>
+<div class="line"><a name="l04578"></a><span class="lineno"> 4578</span>&#160; </div>
+<div class="line"><a name="l04579"></a><span class="lineno"> 4579</span>&#160;    <span class="keyword">template</span>&lt;<span class="keyword">typename</span> U&gt;</div>
+<div class="line"><a name="l04580"></a><span class="lineno"> 4580</span>&#160;    <span class="keywordtype">bool</span> operator==(<span class="keyword">const</span> VmaStlAllocator&lt;U&gt;&amp; rhs)<span class="keyword"> const</span></div>
+<div class="line"><a name="l04581"></a><span class="lineno"> 4581</span>&#160;<span class="keyword">    </span>{</div>
+<div class="line"><a name="l04582"></a><span class="lineno"> 4582</span>&#160;        <span class="keywordflow">return</span> m_pCallbacks == rhs.m_pCallbacks;</div>
+<div class="line"><a name="l04583"></a><span class="lineno"> 4583</span>&#160;    }</div>
+<div class="line"><a name="l04584"></a><span class="lineno"> 4584</span>&#160;    <span class="keyword">template</span>&lt;<span class="keyword">typename</span> U&gt;</div>
+<div class="line"><a name="l04585"></a><span class="lineno"> 4585</span>&#160;    <span class="keywordtype">bool</span> operator!=(<span class="keyword">const</span> VmaStlAllocator&lt;U&gt;&amp; rhs)<span class="keyword"> const</span></div>
+<div class="line"><a name="l04586"></a><span class="lineno"> 4586</span>&#160;<span class="keyword">    </span>{</div>
+<div class="line"><a name="l04587"></a><span class="lineno"> 4587</span>&#160;        <span class="keywordflow">return</span> m_pCallbacks != rhs.m_pCallbacks;</div>
+<div class="line"><a name="l04588"></a><span class="lineno"> 4588</span>&#160;    }</div>
+<div class="line"><a name="l04589"></a><span class="lineno"> 4589</span>&#160; </div>
+<div class="line"><a name="l04590"></a><span class="lineno"> 4590</span>&#160;    VmaStlAllocator&amp; operator=(<span class="keyword">const</span> VmaStlAllocator&amp; x) = <span class="keyword">delete</span>;</div>
+<div class="line"><a name="l04591"></a><span class="lineno"> 4591</span>&#160;};</div>
+<div class="line"><a name="l04592"></a><span class="lineno"> 4592</span>&#160; </div>
+<div class="line"><a name="l04593"></a><span class="lineno"> 4593</span>&#160;<span class="preprocessor">#if VMA_USE_STL_VECTOR</span></div>
+<div class="line"><a name="l04594"></a><span class="lineno"> 4594</span>&#160; </div>
+<div class="line"><a name="l04595"></a><span class="lineno"> 4595</span>&#160;<span class="preprocessor">#define VmaVector std::vector</span></div>
+<div class="line"><a name="l04596"></a><span class="lineno"> 4596</span>&#160; </div>
+<div class="line"><a name="l04597"></a><span class="lineno"> 4597</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> T, <span class="keyword">typename</span> allocatorT&gt;</div>
+<div class="line"><a name="l04598"></a><span class="lineno"> 4598</span>&#160;<span class="keyword">static</span> <span class="keywordtype">void</span> VmaVectorInsert(std::vector&lt;T, allocatorT&gt;&amp; vec, <span class="keywordtype">size_t</span> index, <span class="keyword">const</span> T&amp; item)</div>
+<div class="line"><a name="l04599"></a><span class="lineno"> 4599</span>&#160;{</div>
+<div class="line"><a name="l04600"></a><span class="lineno"> 4600</span>&#160;    vec.insert(vec.begin() + index, item);</div>
+<div class="line"><a name="l04601"></a><span class="lineno"> 4601</span>&#160;}</div>
+<div class="line"><a name="l04602"></a><span class="lineno"> 4602</span>&#160; </div>
+<div class="line"><a name="l04603"></a><span class="lineno"> 4603</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> T, <span class="keyword">typename</span> allocatorT&gt;</div>
+<div class="line"><a name="l04604"></a><span class="lineno"> 4604</span>&#160;<span class="keyword">static</span> <span class="keywordtype">void</span> VmaVectorRemove(std::vector&lt;T, allocatorT&gt;&amp; vec, <span class="keywordtype">size_t</span> index)</div>
+<div class="line"><a name="l04605"></a><span class="lineno"> 4605</span>&#160;{</div>
+<div class="line"><a name="l04606"></a><span class="lineno"> 4606</span>&#160;    vec.erase(vec.begin() + index);</div>
+<div class="line"><a name="l04607"></a><span class="lineno"> 4607</span>&#160;}</div>
+<div class="line"><a name="l04608"></a><span class="lineno"> 4608</span>&#160; </div>
+<div class="line"><a name="l04609"></a><span class="lineno"> 4609</span>&#160;<span class="preprocessor">#else // #if VMA_USE_STL_VECTOR</span></div>
+<div class="line"><a name="l04610"></a><span class="lineno"> 4610</span>&#160; </div>
+<div class="line"><a name="l04611"></a><span class="lineno"> 4611</span>&#160;<span class="comment">/* Class with interface compatible with subset of std::vector.</span></div>
+<div class="line"><a name="l04612"></a><span class="lineno"> 4612</span>&#160;<span class="comment">T must be POD because constructors and destructors are not called and memcpy is</span></div>
+<div class="line"><a name="l04613"></a><span class="lineno"> 4613</span>&#160;<span class="comment">used for these objects. */</span></div>
+<div class="line"><a name="l04614"></a><span class="lineno"> 4614</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> T, <span class="keyword">typename</span> AllocatorT&gt;</div>
+<div class="line"><a name="l04615"></a><span class="lineno"> 4615</span>&#160;<span class="keyword">class </span>VmaVector</div>
+<div class="line"><a name="l04616"></a><span class="lineno"> 4616</span>&#160;{</div>
+<div class="line"><a name="l04617"></a><span class="lineno"> 4617</span>&#160;<span class="keyword">public</span>:</div>
+<div class="line"><a name="l04618"></a><span class="lineno"> 4618</span>&#160;    <span class="keyword">typedef</span> T value_type;</div>
+<div class="line"><a name="l04619"></a><span class="lineno"> 4619</span>&#160; </div>
+<div class="line"><a name="l04620"></a><span class="lineno"> 4620</span>&#160;    VmaVector(<span class="keyword">const</span> AllocatorT&amp; allocator) :</div>
+<div class="line"><a name="l04621"></a><span class="lineno"> 4621</span>&#160;        m_Allocator(allocator),</div>
+<div class="line"><a name="l04622"></a><span class="lineno"> 4622</span>&#160;        m_pArray(VMA_NULL),</div>
+<div class="line"><a name="l04623"></a><span class="lineno"> 4623</span>&#160;        m_Count(0),</div>
+<div class="line"><a name="l04624"></a><span class="lineno"> 4624</span>&#160;        m_Capacity(0)</div>
+<div class="line"><a name="l04625"></a><span class="lineno"> 4625</span>&#160;    {</div>
+<div class="line"><a name="l04626"></a><span class="lineno"> 4626</span>&#160;    }</div>
+<div class="line"><a name="l04627"></a><span class="lineno"> 4627</span>&#160; </div>
+<div class="line"><a name="l04628"></a><span class="lineno"> 4628</span>&#160;    VmaVector(<span class="keywordtype">size_t</span> count, <span class="keyword">const</span> AllocatorT&amp; allocator) :</div>
+<div class="line"><a name="l04629"></a><span class="lineno"> 4629</span>&#160;        m_Allocator(allocator),</div>
+<div class="line"><a name="l04630"></a><span class="lineno"> 4630</span>&#160;        m_pArray(count ? (T*)VmaAllocateArray&lt;T&gt;(allocator.m_pCallbacks, count) : VMA_NULL),</div>
+<div class="line"><a name="l04631"></a><span class="lineno"> 4631</span>&#160;        m_Count(count),</div>
+<div class="line"><a name="l04632"></a><span class="lineno"> 4632</span>&#160;        m_Capacity(count)</div>
+<div class="line"><a name="l04633"></a><span class="lineno"> 4633</span>&#160;    {</div>
+<div class="line"><a name="l04634"></a><span class="lineno"> 4634</span>&#160;    }</div>
+<div class="line"><a name="l04635"></a><span class="lineno"> 4635</span>&#160;    </div>
+<div class="line"><a name="l04636"></a><span class="lineno"> 4636</span>&#160;    <span class="comment">// This version of the constructor is here for compatibility with pre-C++14 std::vector.</span></div>
+<div class="line"><a name="l04637"></a><span class="lineno"> 4637</span>&#160;    <span class="comment">// value is unused.</span></div>
+<div class="line"><a name="l04638"></a><span class="lineno"> 4638</span>&#160;    VmaVector(<span class="keywordtype">size_t</span> count, <span class="keyword">const</span> T&amp; value, <span class="keyword">const</span> AllocatorT&amp; allocator)</div>
+<div class="line"><a name="l04639"></a><span class="lineno"> 4639</span>&#160;        : VmaVector(count, allocator) {}</div>
+<div class="line"><a name="l04640"></a><span class="lineno"> 4640</span>&#160;    </div>
+<div class="line"><a name="l04641"></a><span class="lineno"> 4641</span>&#160;    VmaVector(<span class="keyword">const</span> VmaVector&lt;T, AllocatorT&gt;&amp; src) :</div>
+<div class="line"><a name="l04642"></a><span class="lineno"> 4642</span>&#160;        m_Allocator(src.m_Allocator),</div>
+<div class="line"><a name="l04643"></a><span class="lineno"> 4643</span>&#160;        m_pArray(src.m_Count ? (T*)VmaAllocateArray&lt;T&gt;(src.m_Allocator.m_pCallbacks, src.m_Count) : VMA_NULL),</div>
+<div class="line"><a name="l04644"></a><span class="lineno"> 4644</span>&#160;        m_Count(src.m_Count),</div>
+<div class="line"><a name="l04645"></a><span class="lineno"> 4645</span>&#160;        m_Capacity(src.m_Count)</div>
+<div class="line"><a name="l04646"></a><span class="lineno"> 4646</span>&#160;    {</div>
+<div class="line"><a name="l04647"></a><span class="lineno"> 4647</span>&#160;        <span class="keywordflow">if</span>(m_Count != 0)</div>
+<div class="line"><a name="l04648"></a><span class="lineno"> 4648</span>&#160;        {</div>
+<div class="line"><a name="l04649"></a><span class="lineno"> 4649</span>&#160;            memcpy(m_pArray, src.m_pArray, m_Count * <span class="keyword">sizeof</span>(T));</div>
+<div class="line"><a name="l04650"></a><span class="lineno"> 4650</span>&#160;        }</div>
+<div class="line"><a name="l04651"></a><span class="lineno"> 4651</span>&#160;    }</div>
+<div class="line"><a name="l04652"></a><span class="lineno"> 4652</span>&#160;    </div>
+<div class="line"><a name="l04653"></a><span class="lineno"> 4653</span>&#160;    ~VmaVector()</div>
+<div class="line"><a name="l04654"></a><span class="lineno"> 4654</span>&#160;    {</div>
+<div class="line"><a name="l04655"></a><span class="lineno"> 4655</span>&#160;        VmaFree(m_Allocator.m_pCallbacks, m_pArray);</div>
+<div class="line"><a name="l04656"></a><span class="lineno"> 4656</span>&#160;    }</div>
+<div class="line"><a name="l04657"></a><span class="lineno"> 4657</span>&#160; </div>
+<div class="line"><a name="l04658"></a><span class="lineno"> 4658</span>&#160;    VmaVector&amp; operator=(<span class="keyword">const</span> VmaVector&lt;T, AllocatorT&gt;&amp; rhs)</div>
+<div class="line"><a name="l04659"></a><span class="lineno"> 4659</span>&#160;    {</div>
+<div class="line"><a name="l04660"></a><span class="lineno"> 4660</span>&#160;        <span class="keywordflow">if</span>(&amp;rhs != <span class="keyword">this</span>)</div>
+<div class="line"><a name="l04661"></a><span class="lineno"> 4661</span>&#160;        {</div>
+<div class="line"><a name="l04662"></a><span class="lineno"> 4662</span>&#160;            resize(rhs.m_Count);</div>
+<div class="line"><a name="l04663"></a><span class="lineno"> 4663</span>&#160;            <span class="keywordflow">if</span>(m_Count != 0)</div>
+<div class="line"><a name="l04664"></a><span class="lineno"> 4664</span>&#160;            {</div>
+<div class="line"><a name="l04665"></a><span class="lineno"> 4665</span>&#160;                memcpy(m_pArray, rhs.m_pArray, m_Count * <span class="keyword">sizeof</span>(T));</div>
+<div class="line"><a name="l04666"></a><span class="lineno"> 4666</span>&#160;            }</div>
+<div class="line"><a name="l04667"></a><span class="lineno"> 4667</span>&#160;        }</div>
+<div class="line"><a name="l04668"></a><span class="lineno"> 4668</span>&#160;        <span class="keywordflow">return</span> *<span class="keyword">this</span>;</div>
+<div class="line"><a name="l04669"></a><span class="lineno"> 4669</span>&#160;    }</div>
+<div class="line"><a name="l04670"></a><span class="lineno"> 4670</span>&#160;    </div>
+<div class="line"><a name="l04671"></a><span class="lineno"> 4671</span>&#160;    <span class="keywordtype">bool</span> empty()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_Count == 0; }</div>
+<div class="line"><a name="l04672"></a><span class="lineno"> 4672</span>&#160;    <span class="keywordtype">size_t</span> size()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_Count; }</div>
+<div class="line"><a name="l04673"></a><span class="lineno"> 4673</span>&#160;    T* data() { <span class="keywordflow">return</span> m_pArray; }</div>
+<div class="line"><a name="l04674"></a><span class="lineno"> 4674</span>&#160;    <span class="keyword">const</span> T* data()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_pArray; }</div>
+<div class="line"><a name="l04675"></a><span class="lineno"> 4675</span>&#160;    </div>
+<div class="line"><a name="l04676"></a><span class="lineno"> 4676</span>&#160;    T&amp; operator[](<span class="keywordtype">size_t</span> index)</div>
+<div class="line"><a name="l04677"></a><span class="lineno"> 4677</span>&#160;    {</div>
+<div class="line"><a name="l04678"></a><span class="lineno"> 4678</span>&#160;        VMA_HEAVY_ASSERT(index &lt; m_Count);</div>
+<div class="line"><a name="l04679"></a><span class="lineno"> 4679</span>&#160;        <span class="keywordflow">return</span> m_pArray[index];</div>
+<div class="line"><a name="l04680"></a><span class="lineno"> 4680</span>&#160;    }</div>
+<div class="line"><a name="l04681"></a><span class="lineno"> 4681</span>&#160;    <span class="keyword">const</span> T&amp; operator[](<span class="keywordtype">size_t</span> index)<span class="keyword"> const</span></div>
+<div class="line"><a name="l04682"></a><span class="lineno"> 4682</span>&#160;<span class="keyword">    </span>{</div>
+<div class="line"><a name="l04683"></a><span class="lineno"> 4683</span>&#160;        VMA_HEAVY_ASSERT(index &lt; m_Count);</div>
+<div class="line"><a name="l04684"></a><span class="lineno"> 4684</span>&#160;        <span class="keywordflow">return</span> m_pArray[index];</div>
+<div class="line"><a name="l04685"></a><span class="lineno"> 4685</span>&#160;    }</div>
+<div class="line"><a name="l04686"></a><span class="lineno"> 4686</span>&#160; </div>
+<div class="line"><a name="l04687"></a><span class="lineno"> 4687</span>&#160;    T&amp; front()</div>
+<div class="line"><a name="l04688"></a><span class="lineno"> 4688</span>&#160;    {</div>
+<div class="line"><a name="l04689"></a><span class="lineno"> 4689</span>&#160;        VMA_HEAVY_ASSERT(m_Count &gt; 0);</div>
+<div class="line"><a name="l04690"></a><span class="lineno"> 4690</span>&#160;        <span class="keywordflow">return</span> m_pArray[0];</div>
+<div class="line"><a name="l04691"></a><span class="lineno"> 4691</span>&#160;    }</div>
+<div class="line"><a name="l04692"></a><span class="lineno"> 4692</span>&#160;    <span class="keyword">const</span> T&amp; front()<span class="keyword"> const</span></div>
+<div class="line"><a name="l04693"></a><span class="lineno"> 4693</span>&#160;<span class="keyword">    </span>{</div>
+<div class="line"><a name="l04694"></a><span class="lineno"> 4694</span>&#160;        VMA_HEAVY_ASSERT(m_Count &gt; 0);</div>
+<div class="line"><a name="l04695"></a><span class="lineno"> 4695</span>&#160;        <span class="keywordflow">return</span> m_pArray[0];</div>
+<div class="line"><a name="l04696"></a><span class="lineno"> 4696</span>&#160;    }</div>
+<div class="line"><a name="l04697"></a><span class="lineno"> 4697</span>&#160;    T&amp; back()</div>
+<div class="line"><a name="l04698"></a><span class="lineno"> 4698</span>&#160;    {</div>
+<div class="line"><a name="l04699"></a><span class="lineno"> 4699</span>&#160;        VMA_HEAVY_ASSERT(m_Count &gt; 0);</div>
+<div class="line"><a name="l04700"></a><span class="lineno"> 4700</span>&#160;        <span class="keywordflow">return</span> m_pArray[m_Count - 1];</div>
+<div class="line"><a name="l04701"></a><span class="lineno"> 4701</span>&#160;    }</div>
+<div class="line"><a name="l04702"></a><span class="lineno"> 4702</span>&#160;    <span class="keyword">const</span> T&amp; back()<span class="keyword"> const</span></div>
+<div class="line"><a name="l04703"></a><span class="lineno"> 4703</span>&#160;<span class="keyword">    </span>{</div>
+<div class="line"><a name="l04704"></a><span class="lineno"> 4704</span>&#160;        VMA_HEAVY_ASSERT(m_Count &gt; 0);</div>
+<div class="line"><a name="l04705"></a><span class="lineno"> 4705</span>&#160;        <span class="keywordflow">return</span> m_pArray[m_Count - 1];</div>
+<div class="line"><a name="l04706"></a><span class="lineno"> 4706</span>&#160;    }</div>
+<div class="line"><a name="l04707"></a><span class="lineno"> 4707</span>&#160; </div>
+<div class="line"><a name="l04708"></a><span class="lineno"> 4708</span>&#160;    <span class="keywordtype">void</span> reserve(<span class="keywordtype">size_t</span> newCapacity, <span class="keywordtype">bool</span> freeMemory = <span class="keyword">false</span>)</div>
+<div class="line"><a name="l04709"></a><span class="lineno"> 4709</span>&#160;    {</div>
+<div class="line"><a name="l04710"></a><span class="lineno"> 4710</span>&#160;        newCapacity = VMA_MAX(newCapacity, m_Count);</div>
+<div class="line"><a name="l04711"></a><span class="lineno"> 4711</span>&#160;        </div>
+<div class="line"><a name="l04712"></a><span class="lineno"> 4712</span>&#160;        <span class="keywordflow">if</span>((newCapacity &lt; m_Capacity) &amp;&amp; !freeMemory)</div>
+<div class="line"><a name="l04713"></a><span class="lineno"> 4713</span>&#160;        {</div>
+<div class="line"><a name="l04714"></a><span class="lineno"> 4714</span>&#160;            newCapacity = m_Capacity;</div>
+<div class="line"><a name="l04715"></a><span class="lineno"> 4715</span>&#160;        }</div>
+<div class="line"><a name="l04716"></a><span class="lineno"> 4716</span>&#160;        </div>
+<div class="line"><a name="l04717"></a><span class="lineno"> 4717</span>&#160;        <span class="keywordflow">if</span>(newCapacity != m_Capacity)</div>
+<div class="line"><a name="l04718"></a><span class="lineno"> 4718</span>&#160;        {</div>
+<div class="line"><a name="l04719"></a><span class="lineno"> 4719</span>&#160;            T* <span class="keyword">const</span> newArray = newCapacity ? VmaAllocateArray&lt;T&gt;(m_Allocator, newCapacity) : VMA_NULL;</div>
+<div class="line"><a name="l04720"></a><span class="lineno"> 4720</span>&#160;            <span class="keywordflow">if</span>(m_Count != 0)</div>
+<div class="line"><a name="l04721"></a><span class="lineno"> 4721</span>&#160;            {</div>
+<div class="line"><a name="l04722"></a><span class="lineno"> 4722</span>&#160;                memcpy(newArray, m_pArray, m_Count * <span class="keyword">sizeof</span>(T));</div>
+<div class="line"><a name="l04723"></a><span class="lineno"> 4723</span>&#160;            }</div>
+<div class="line"><a name="l04724"></a><span class="lineno"> 4724</span>&#160;            VmaFree(m_Allocator.m_pCallbacks, m_pArray);</div>
+<div class="line"><a name="l04725"></a><span class="lineno"> 4725</span>&#160;            m_Capacity = newCapacity;</div>
+<div class="line"><a name="l04726"></a><span class="lineno"> 4726</span>&#160;            m_pArray = newArray;</div>
+<div class="line"><a name="l04727"></a><span class="lineno"> 4727</span>&#160;        }</div>
+<div class="line"><a name="l04728"></a><span class="lineno"> 4728</span>&#160;    }</div>
+<div class="line"><a name="l04729"></a><span class="lineno"> 4729</span>&#160; </div>
+<div class="line"><a name="l04730"></a><span class="lineno"> 4730</span>&#160;    <span class="keywordtype">void</span> resize(<span class="keywordtype">size_t</span> newCount, <span class="keywordtype">bool</span> freeMemory = <span class="keyword">false</span>)</div>
+<div class="line"><a name="l04731"></a><span class="lineno"> 4731</span>&#160;    {</div>
+<div class="line"><a name="l04732"></a><span class="lineno"> 4732</span>&#160;        <span class="keywordtype">size_t</span> newCapacity = m_Capacity;</div>
+<div class="line"><a name="l04733"></a><span class="lineno"> 4733</span>&#160;        <span class="keywordflow">if</span>(newCount &gt; m_Capacity)</div>
+<div class="line"><a name="l04734"></a><span class="lineno"> 4734</span>&#160;        {</div>
+<div class="line"><a name="l04735"></a><span class="lineno"> 4735</span>&#160;            newCapacity = VMA_MAX(newCount, VMA_MAX(m_Capacity * 3 / 2, (<span class="keywordtype">size_t</span>)8));</div>
+<div class="line"><a name="l04736"></a><span class="lineno"> 4736</span>&#160;        }</div>
+<div class="line"><a name="l04737"></a><span class="lineno"> 4737</span>&#160;        <span class="keywordflow">else</span> <span class="keywordflow">if</span>(freeMemory)</div>
+<div class="line"><a name="l04738"></a><span class="lineno"> 4738</span>&#160;        {</div>
+<div class="line"><a name="l04739"></a><span class="lineno"> 4739</span>&#160;            newCapacity = newCount;</div>
+<div class="line"><a name="l04740"></a><span class="lineno"> 4740</span>&#160;        }</div>
+<div class="line"><a name="l04741"></a><span class="lineno"> 4741</span>&#160; </div>
+<div class="line"><a name="l04742"></a><span class="lineno"> 4742</span>&#160;        <span class="keywordflow">if</span>(newCapacity != m_Capacity)</div>
+<div class="line"><a name="l04743"></a><span class="lineno"> 4743</span>&#160;        {</div>
+<div class="line"><a name="l04744"></a><span class="lineno"> 4744</span>&#160;            T* <span class="keyword">const</span> newArray = newCapacity ? VmaAllocateArray&lt;T&gt;(m_Allocator.m_pCallbacks, newCapacity) : VMA_NULL;</div>
+<div class="line"><a name="l04745"></a><span class="lineno"> 4745</span>&#160;            <span class="keyword">const</span> <span class="keywordtype">size_t</span> elementsToCopy = VMA_MIN(m_Count, newCount);</div>
+<div class="line"><a name="l04746"></a><span class="lineno"> 4746</span>&#160;            <span class="keywordflow">if</span>(elementsToCopy != 0)</div>
+<div class="line"><a name="l04747"></a><span class="lineno"> 4747</span>&#160;            {</div>
+<div class="line"><a name="l04748"></a><span class="lineno"> 4748</span>&#160;                memcpy(newArray, m_pArray, elementsToCopy * <span class="keyword">sizeof</span>(T));</div>
+<div class="line"><a name="l04749"></a><span class="lineno"> 4749</span>&#160;            }</div>
+<div class="line"><a name="l04750"></a><span class="lineno"> 4750</span>&#160;            VmaFree(m_Allocator.m_pCallbacks, m_pArray);</div>
+<div class="line"><a name="l04751"></a><span class="lineno"> 4751</span>&#160;            m_Capacity = newCapacity;</div>
+<div class="line"><a name="l04752"></a><span class="lineno"> 4752</span>&#160;            m_pArray = newArray;</div>
+<div class="line"><a name="l04753"></a><span class="lineno"> 4753</span>&#160;        }</div>
+<div class="line"><a name="l04754"></a><span class="lineno"> 4754</span>&#160; </div>
+<div class="line"><a name="l04755"></a><span class="lineno"> 4755</span>&#160;        m_Count = newCount;</div>
+<div class="line"><a name="l04756"></a><span class="lineno"> 4756</span>&#160;    }</div>
+<div class="line"><a name="l04757"></a><span class="lineno"> 4757</span>&#160; </div>
+<div class="line"><a name="l04758"></a><span class="lineno"> 4758</span>&#160;    <span class="keywordtype">void</span> clear(<span class="keywordtype">bool</span> freeMemory = <span class="keyword">false</span>)</div>
+<div class="line"><a name="l04759"></a><span class="lineno"> 4759</span>&#160;    {</div>
+<div class="line"><a name="l04760"></a><span class="lineno"> 4760</span>&#160;        resize(0, freeMemory);</div>
+<div class="line"><a name="l04761"></a><span class="lineno"> 4761</span>&#160;    }</div>
+<div class="line"><a name="l04762"></a><span class="lineno"> 4762</span>&#160; </div>
+<div class="line"><a name="l04763"></a><span class="lineno"> 4763</span>&#160;    <span class="keywordtype">void</span> insert(<span class="keywordtype">size_t</span> index, <span class="keyword">const</span> T&amp; src)</div>
+<div class="line"><a name="l04764"></a><span class="lineno"> 4764</span>&#160;    {</div>
+<div class="line"><a name="l04765"></a><span class="lineno"> 4765</span>&#160;        VMA_HEAVY_ASSERT(index &lt;= m_Count);</div>
+<div class="line"><a name="l04766"></a><span class="lineno"> 4766</span>&#160;        <span class="keyword">const</span> <span class="keywordtype">size_t</span> oldCount = size();</div>
+<div class="line"><a name="l04767"></a><span class="lineno"> 4767</span>&#160;        resize(oldCount + 1);</div>
+<div class="line"><a name="l04768"></a><span class="lineno"> 4768</span>&#160;        <span class="keywordflow">if</span>(index &lt; oldCount)</div>
+<div class="line"><a name="l04769"></a><span class="lineno"> 4769</span>&#160;        {</div>
+<div class="line"><a name="l04770"></a><span class="lineno"> 4770</span>&#160;            memmove(m_pArray + (index + 1), m_pArray + index, (oldCount - index) * <span class="keyword">sizeof</span>(T));</div>
+<div class="line"><a name="l04771"></a><span class="lineno"> 4771</span>&#160;        }</div>
+<div class="line"><a name="l04772"></a><span class="lineno"> 4772</span>&#160;        m_pArray[index] = src;</div>
+<div class="line"><a name="l04773"></a><span class="lineno"> 4773</span>&#160;    }</div>
+<div class="line"><a name="l04774"></a><span class="lineno"> 4774</span>&#160; </div>
+<div class="line"><a name="l04775"></a><span class="lineno"> 4775</span>&#160;    <span class="keywordtype">void</span> remove(<span class="keywordtype">size_t</span> index)</div>
+<div class="line"><a name="l04776"></a><span class="lineno"> 4776</span>&#160;    {</div>
+<div class="line"><a name="l04777"></a><span class="lineno"> 4777</span>&#160;        VMA_HEAVY_ASSERT(index &lt; m_Count);</div>
+<div class="line"><a name="l04778"></a><span class="lineno"> 4778</span>&#160;        <span class="keyword">const</span> <span class="keywordtype">size_t</span> oldCount = size();</div>
+<div class="line"><a name="l04779"></a><span class="lineno"> 4779</span>&#160;        <span class="keywordflow">if</span>(index &lt; oldCount - 1)</div>
+<div class="line"><a name="l04780"></a><span class="lineno"> 4780</span>&#160;        {</div>
+<div class="line"><a name="l04781"></a><span class="lineno"> 4781</span>&#160;            memmove(m_pArray + index, m_pArray + (index + 1), (oldCount - index - 1) * <span class="keyword">sizeof</span>(T));</div>
+<div class="line"><a name="l04782"></a><span class="lineno"> 4782</span>&#160;        }</div>
+<div class="line"><a name="l04783"></a><span class="lineno"> 4783</span>&#160;        resize(oldCount - 1);</div>
+<div class="line"><a name="l04784"></a><span class="lineno"> 4784</span>&#160;    }</div>
+<div class="line"><a name="l04785"></a><span class="lineno"> 4785</span>&#160; </div>
+<div class="line"><a name="l04786"></a><span class="lineno"> 4786</span>&#160;    <span class="keywordtype">void</span> push_back(<span class="keyword">const</span> T&amp; src)</div>
+<div class="line"><a name="l04787"></a><span class="lineno"> 4787</span>&#160;    {</div>
+<div class="line"><a name="l04788"></a><span class="lineno"> 4788</span>&#160;        <span class="keyword">const</span> <span class="keywordtype">size_t</span> newIndex = size();</div>
+<div class="line"><a name="l04789"></a><span class="lineno"> 4789</span>&#160;        resize(newIndex + 1);</div>
+<div class="line"><a name="l04790"></a><span class="lineno"> 4790</span>&#160;        m_pArray[newIndex] = src;</div>
+<div class="line"><a name="l04791"></a><span class="lineno"> 4791</span>&#160;    }</div>
+<div class="line"><a name="l04792"></a><span class="lineno"> 4792</span>&#160; </div>
+<div class="line"><a name="l04793"></a><span class="lineno"> 4793</span>&#160;    <span class="keywordtype">void</span> pop_back()</div>
+<div class="line"><a name="l04794"></a><span class="lineno"> 4794</span>&#160;    {</div>
+<div class="line"><a name="l04795"></a><span class="lineno"> 4795</span>&#160;        VMA_HEAVY_ASSERT(m_Count &gt; 0);</div>
+<div class="line"><a name="l04796"></a><span class="lineno"> 4796</span>&#160;        resize(size() - 1);</div>
+<div class="line"><a name="l04797"></a><span class="lineno"> 4797</span>&#160;    }</div>
+<div class="line"><a name="l04798"></a><span class="lineno"> 4798</span>&#160; </div>
+<div class="line"><a name="l04799"></a><span class="lineno"> 4799</span>&#160;    <span class="keywordtype">void</span> push_front(<span class="keyword">const</span> T&amp; src)</div>
+<div class="line"><a name="l04800"></a><span class="lineno"> 4800</span>&#160;    {</div>
+<div class="line"><a name="l04801"></a><span class="lineno"> 4801</span>&#160;        insert(0, src);</div>
+<div class="line"><a name="l04802"></a><span class="lineno"> 4802</span>&#160;    }</div>
+<div class="line"><a name="l04803"></a><span class="lineno"> 4803</span>&#160; </div>
+<div class="line"><a name="l04804"></a><span class="lineno"> 4804</span>&#160;    <span class="keywordtype">void</span> pop_front()</div>
+<div class="line"><a name="l04805"></a><span class="lineno"> 4805</span>&#160;    {</div>
+<div class="line"><a name="l04806"></a><span class="lineno"> 4806</span>&#160;        VMA_HEAVY_ASSERT(m_Count &gt; 0);</div>
+<div class="line"><a name="l04807"></a><span class="lineno"> 4807</span>&#160;        remove(0);</div>
+<div class="line"><a name="l04808"></a><span class="lineno"> 4808</span>&#160;    }</div>
+<div class="line"><a name="l04809"></a><span class="lineno"> 4809</span>&#160; </div>
+<div class="line"><a name="l04810"></a><span class="lineno"> 4810</span>&#160;    <span class="keyword">typedef</span> T* iterator;</div>
+<div class="line"><a name="l04811"></a><span class="lineno"> 4811</span>&#160; </div>
+<div class="line"><a name="l04812"></a><span class="lineno"> 4812</span>&#160;    iterator begin() { <span class="keywordflow">return</span> m_pArray; }</div>
+<div class="line"><a name="l04813"></a><span class="lineno"> 4813</span>&#160;    iterator end() { <span class="keywordflow">return</span> m_pArray + m_Count; }</div>
+<div class="line"><a name="l04814"></a><span class="lineno"> 4814</span>&#160; </div>
+<div class="line"><a name="l04815"></a><span class="lineno"> 4815</span>&#160;<span class="keyword">private</span>:</div>
+<div class="line"><a name="l04816"></a><span class="lineno"> 4816</span>&#160;    AllocatorT m_Allocator;</div>
+<div class="line"><a name="l04817"></a><span class="lineno"> 4817</span>&#160;    T* m_pArray;</div>
+<div class="line"><a name="l04818"></a><span class="lineno"> 4818</span>&#160;    <span class="keywordtype">size_t</span> m_Count;</div>
+<div class="line"><a name="l04819"></a><span class="lineno"> 4819</span>&#160;    <span class="keywordtype">size_t</span> m_Capacity;</div>
+<div class="line"><a name="l04820"></a><span class="lineno"> 4820</span>&#160;};</div>
+<div class="line"><a name="l04821"></a><span class="lineno"> 4821</span>&#160; </div>
+<div class="line"><a name="l04822"></a><span class="lineno"> 4822</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> T, <span class="keyword">typename</span> allocatorT&gt;</div>
+<div class="line"><a name="l04823"></a><span class="lineno"> 4823</span>&#160;<span class="keyword">static</span> <span class="keywordtype">void</span> VmaVectorInsert(VmaVector&lt;T, allocatorT&gt;&amp; vec, <span class="keywordtype">size_t</span> index, <span class="keyword">const</span> T&amp; item)</div>
+<div class="line"><a name="l04824"></a><span class="lineno"> 4824</span>&#160;{</div>
+<div class="line"><a name="l04825"></a><span class="lineno"> 4825</span>&#160;    vec.insert(index, item);</div>
+<div class="line"><a name="l04826"></a><span class="lineno"> 4826</span>&#160;}</div>
+<div class="line"><a name="l04827"></a><span class="lineno"> 4827</span>&#160; </div>
+<div class="line"><a name="l04828"></a><span class="lineno"> 4828</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> T, <span class="keyword">typename</span> allocatorT&gt;</div>
+<div class="line"><a name="l04829"></a><span class="lineno"> 4829</span>&#160;<span class="keyword">static</span> <span class="keywordtype">void</span> VmaVectorRemove(VmaVector&lt;T, allocatorT&gt;&amp; vec, <span class="keywordtype">size_t</span> index)</div>
+<div class="line"><a name="l04830"></a><span class="lineno"> 4830</span>&#160;{</div>
+<div class="line"><a name="l04831"></a><span class="lineno"> 4831</span>&#160;    vec.remove(index);</div>
+<div class="line"><a name="l04832"></a><span class="lineno"> 4832</span>&#160;}</div>
+<div class="line"><a name="l04833"></a><span class="lineno"> 4833</span>&#160; </div>
+<div class="line"><a name="l04834"></a><span class="lineno"> 4834</span>&#160;<span class="preprocessor">#endif // #if VMA_USE_STL_VECTOR</span></div>
+<div class="line"><a name="l04835"></a><span class="lineno"> 4835</span>&#160; </div>
+<div class="line"><a name="l04836"></a><span class="lineno"> 4836</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> CmpLess, <span class="keyword">typename</span> VectorT&gt;</div>
+<div class="line"><a name="l04837"></a><span class="lineno"> 4837</span>&#160;<span class="keywordtype">size_t</span> VmaVectorInsertSorted(VectorT&amp; vector, <span class="keyword">const</span> <span class="keyword">typename</span> VectorT::value_type&amp; value)</div>
+<div class="line"><a name="l04838"></a><span class="lineno"> 4838</span>&#160;{</div>
+<div class="line"><a name="l04839"></a><span class="lineno"> 4839</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">size_t</span> indexToInsert = VmaBinaryFindFirstNotLess(</div>
+<div class="line"><a name="l04840"></a><span class="lineno"> 4840</span>&#160;        vector.data(),</div>
+<div class="line"><a name="l04841"></a><span class="lineno"> 4841</span>&#160;        vector.data() + vector.size(),</div>
+<div class="line"><a name="l04842"></a><span class="lineno"> 4842</span>&#160;        value,</div>
+<div class="line"><a name="l04843"></a><span class="lineno"> 4843</span>&#160;        CmpLess()) - vector.data();</div>
+<div class="line"><a name="l04844"></a><span class="lineno"> 4844</span>&#160;    VmaVectorInsert(vector, indexToInsert, value);</div>
+<div class="line"><a name="l04845"></a><span class="lineno"> 4845</span>&#160;    <span class="keywordflow">return</span> indexToInsert;</div>
+<div class="line"><a name="l04846"></a><span class="lineno"> 4846</span>&#160;}</div>
+<div class="line"><a name="l04847"></a><span class="lineno"> 4847</span>&#160; </div>
+<div class="line"><a name="l04848"></a><span class="lineno"> 4848</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> CmpLess, <span class="keyword">typename</span> VectorT&gt;</div>
+<div class="line"><a name="l04849"></a><span class="lineno"> 4849</span>&#160;<span class="keywordtype">bool</span> VmaVectorRemoveSorted(VectorT&amp; vector, <span class="keyword">const</span> <span class="keyword">typename</span> VectorT::value_type&amp; value)</div>
+<div class="line"><a name="l04850"></a><span class="lineno"> 4850</span>&#160;{</div>
+<div class="line"><a name="l04851"></a><span class="lineno"> 4851</span>&#160;    CmpLess comparator;</div>
+<div class="line"><a name="l04852"></a><span class="lineno"> 4852</span>&#160;    <span class="keyword">typename</span> VectorT::iterator it = VmaBinaryFindFirstNotLess(</div>
+<div class="line"><a name="l04853"></a><span class="lineno"> 4853</span>&#160;        vector.begin(),</div>
+<div class="line"><a name="l04854"></a><span class="lineno"> 4854</span>&#160;        vector.end(),</div>
+<div class="line"><a name="l04855"></a><span class="lineno"> 4855</span>&#160;        value,</div>
+<div class="line"><a name="l04856"></a><span class="lineno"> 4856</span>&#160;        comparator);</div>
+<div class="line"><a name="l04857"></a><span class="lineno"> 4857</span>&#160;    <span class="keywordflow">if</span>((it != vector.end()) &amp;&amp; !comparator(*it, value) &amp;&amp; !comparator(value, *it))</div>
+<div class="line"><a name="l04858"></a><span class="lineno"> 4858</span>&#160;    {</div>
+<div class="line"><a name="l04859"></a><span class="lineno"> 4859</span>&#160;        <span class="keywordtype">size_t</span> indexToRemove = it - vector.begin();</div>
+<div class="line"><a name="l04860"></a><span class="lineno"> 4860</span>&#160;        VmaVectorRemove(vector, indexToRemove);</div>
+<div class="line"><a name="l04861"></a><span class="lineno"> 4861</span>&#160;        <span class="keywordflow">return</span> <span class="keyword">true</span>;</div>
+<div class="line"><a name="l04862"></a><span class="lineno"> 4862</span>&#160;    }</div>
+<div class="line"><a name="l04863"></a><span class="lineno"> 4863</span>&#160;    <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l04864"></a><span class="lineno"> 4864</span>&#160;}</div>
+<div class="line"><a name="l04865"></a><span class="lineno"> 4865</span>&#160; </div>
+<div class="line"><a name="l04867"></a><span class="lineno"> 4867</span>&#160;<span class="comment">// class VmaPoolAllocator</span></div>
+<div class="line"><a name="l04868"></a><span class="lineno"> 4868</span>&#160; </div>
+<div class="line"><a name="l04869"></a><span class="lineno"> 4869</span>&#160;<span class="comment">/*</span></div>
+<div class="line"><a name="l04870"></a><span class="lineno"> 4870</span>&#160;<span class="comment">Allocator for objects of type T using a list of arrays (pools) to speed up</span></div>
+<div class="line"><a name="l04871"></a><span class="lineno"> 4871</span>&#160;<span class="comment">allocation. Number of elements that can be allocated is not bounded because</span></div>
+<div class="line"><a name="l04872"></a><span class="lineno"> 4872</span>&#160;<span class="comment">allocator can create multiple blocks.</span></div>
+<div class="line"><a name="l04873"></a><span class="lineno"> 4873</span>&#160;<span class="comment">*/</span></div>
+<div class="line"><a name="l04874"></a><span class="lineno"> 4874</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</div>
+<div class="line"><a name="l04875"></a><span class="lineno"> 4875</span>&#160;<span class="keyword">class </span>VmaPoolAllocator</div>
+<div class="line"><a name="l04876"></a><span class="lineno"> 4876</span>&#160;{</div>
+<div class="line"><a name="l04877"></a><span class="lineno"> 4877</span>&#160;    VMA_CLASS_NO_COPY(VmaPoolAllocator)</div>
+<div class="line"><a name="l04878"></a><span class="lineno"> 4878</span>&#160;<span class="keyword">public</span>:</div>
+<div class="line"><a name="l04879"></a><span class="lineno"> 4879</span>&#160;    VmaPoolAllocator(<span class="keyword">const</span> VkAllocationCallbacks* pAllocationCallbacks, uint32_t firstBlockCapacity);</div>
+<div class="line"><a name="l04880"></a><span class="lineno"> 4880</span>&#160;    ~VmaPoolAllocator();</div>
+<div class="line"><a name="l04881"></a><span class="lineno"> 4881</span>&#160;    <span class="keyword">template</span>&lt;<span class="keyword">typename</span>... Types&gt; T* Alloc(Types... args);</div>
+<div class="line"><a name="l04882"></a><span class="lineno"> 4882</span>&#160;    <span class="keywordtype">void</span> Free(T* ptr);</div>
+<div class="line"><a name="l04883"></a><span class="lineno"> 4883</span>&#160; </div>
+<div class="line"><a name="l04884"></a><span class="lineno"> 4884</span>&#160;<span class="keyword">private</span>:</div>
+<div class="line"><a name="l04885"></a><span class="lineno"> 4885</span>&#160;    <span class="keyword">union </span>Item</div>
+<div class="line"><a name="l04886"></a><span class="lineno"> 4886</span>&#160;    {</div>
+<div class="line"><a name="l04887"></a><span class="lineno"> 4887</span>&#160;        uint32_t NextFreeIndex;</div>
+<div class="line"><a name="l04888"></a><span class="lineno"> 4888</span>&#160;        <span class="keyword">alignas</span>(T) <span class="keywordtype">char</span> Value[<span class="keyword">sizeof</span>(T)];</div>
+<div class="line"><a name="l04889"></a><span class="lineno"> 4889</span>&#160;    };</div>
+<div class="line"><a name="l04890"></a><span class="lineno"> 4890</span>&#160; </div>
+<div class="line"><a name="l04891"></a><span class="lineno"> 4891</span>&#160;    <span class="keyword">struct </span>ItemBlock</div>
+<div class="line"><a name="l04892"></a><span class="lineno"> 4892</span>&#160;    {</div>
+<div class="line"><a name="l04893"></a><span class="lineno"> 4893</span>&#160;        Item* pItems;</div>
+<div class="line"><a name="l04894"></a><span class="lineno"> 4894</span>&#160;        uint32_t Capacity;</div>
+<div class="line"><a name="l04895"></a><span class="lineno"> 4895</span>&#160;        uint32_t FirstFreeIndex;</div>
+<div class="line"><a name="l04896"></a><span class="lineno"> 4896</span>&#160;    };</div>
+<div class="line"><a name="l04897"></a><span class="lineno"> 4897</span>&#160;    </div>
+<div class="line"><a name="l04898"></a><span class="lineno"> 4898</span>&#160;    <span class="keyword">const</span> VkAllocationCallbacks* m_pAllocationCallbacks;</div>
+<div class="line"><a name="l04899"></a><span class="lineno"> 4899</span>&#160;    <span class="keyword">const</span> uint32_t m_FirstBlockCapacity;</div>
+<div class="line"><a name="l04900"></a><span class="lineno"> 4900</span>&#160;    VmaVector&lt; ItemBlock, VmaStlAllocator&lt;ItemBlock&gt; &gt; m_ItemBlocks;</div>
+<div class="line"><a name="l04901"></a><span class="lineno"> 4901</span>&#160; </div>
+<div class="line"><a name="l04902"></a><span class="lineno"> 4902</span>&#160;    ItemBlock&amp; CreateNewBlock();</div>
+<div class="line"><a name="l04903"></a><span class="lineno"> 4903</span>&#160;};</div>
+<div class="line"><a name="l04904"></a><span class="lineno"> 4904</span>&#160; </div>
+<div class="line"><a name="l04905"></a><span class="lineno"> 4905</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</div>
+<div class="line"><a name="l04906"></a><span class="lineno"> 4906</span>&#160;VmaPoolAllocator&lt;T&gt;::VmaPoolAllocator(<span class="keyword">const</span> VkAllocationCallbacks* pAllocationCallbacks, uint32_t firstBlockCapacity) :</div>
+<div class="line"><a name="l04907"></a><span class="lineno"> 4907</span>&#160;    m_pAllocationCallbacks(pAllocationCallbacks),</div>
+<div class="line"><a name="l04908"></a><span class="lineno"> 4908</span>&#160;    m_FirstBlockCapacity(firstBlockCapacity),</div>
+<div class="line"><a name="l04909"></a><span class="lineno"> 4909</span>&#160;    m_ItemBlocks(VmaStlAllocator&lt;ItemBlock&gt;(pAllocationCallbacks))</div>
+<div class="line"><a name="l04910"></a><span class="lineno"> 4910</span>&#160;{</div>
+<div class="line"><a name="l04911"></a><span class="lineno"> 4911</span>&#160;    VMA_ASSERT(m_FirstBlockCapacity &gt; 1);</div>
+<div class="line"><a name="l04912"></a><span class="lineno"> 4912</span>&#160;}</div>
+<div class="line"><a name="l04913"></a><span class="lineno"> 4913</span>&#160; </div>
+<div class="line"><a name="l04914"></a><span class="lineno"> 4914</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</div>
+<div class="line"><a name="l04915"></a><span class="lineno"> 4915</span>&#160;VmaPoolAllocator&lt;T&gt;::~VmaPoolAllocator()</div>
+<div class="line"><a name="l04916"></a><span class="lineno"> 4916</span>&#160;{</div>
+<div class="line"><a name="l04917"></a><span class="lineno"> 4917</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = m_ItemBlocks.size(); i--; )</div>
+<div class="line"><a name="l04918"></a><span class="lineno"> 4918</span>&#160;        vma_delete_array(m_pAllocationCallbacks, m_ItemBlocks[i].pItems, m_ItemBlocks[i].Capacity);</div>
+<div class="line"><a name="l04919"></a><span class="lineno"> 4919</span>&#160;    m_ItemBlocks.clear();</div>
+<div class="line"><a name="l04920"></a><span class="lineno"> 4920</span>&#160;}</div>
+<div class="line"><a name="l04921"></a><span class="lineno"> 4921</span>&#160; </div>
+<div class="line"><a name="l04922"></a><span class="lineno"> 4922</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</div>
+<div class="line"><a name="l04923"></a><span class="lineno"> 4923</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span>... Types&gt; T* VmaPoolAllocator&lt;T&gt;::Alloc(Types... args)</div>
+<div class="line"><a name="l04924"></a><span class="lineno"> 4924</span>&#160;{</div>
+<div class="line"><a name="l04925"></a><span class="lineno"> 4925</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = m_ItemBlocks.size(); i--; )</div>
+<div class="line"><a name="l04926"></a><span class="lineno"> 4926</span>&#160;    {</div>
+<div class="line"><a name="l04927"></a><span class="lineno"> 4927</span>&#160;        ItemBlock&amp; block = m_ItemBlocks[i];</div>
+<div class="line"><a name="l04928"></a><span class="lineno"> 4928</span>&#160;        <span class="comment">// This block has some free items: Use first one.</span></div>
+<div class="line"><a name="l04929"></a><span class="lineno"> 4929</span>&#160;        <span class="keywordflow">if</span>(block.FirstFreeIndex != UINT32_MAX)</div>
+<div class="line"><a name="l04930"></a><span class="lineno"> 4930</span>&#160;        {</div>
+<div class="line"><a name="l04931"></a><span class="lineno"> 4931</span>&#160;            Item* <span class="keyword">const</span> pItem = &amp;block.pItems[block.FirstFreeIndex];</div>
+<div class="line"><a name="l04932"></a><span class="lineno"> 4932</span>&#160;            block.FirstFreeIndex = pItem-&gt;NextFreeIndex;</div>
+<div class="line"><a name="l04933"></a><span class="lineno"> 4933</span>&#160;            T* result = (T*)&amp;pItem-&gt;Value;</div>
+<div class="line"><a name="l04934"></a><span class="lineno"> 4934</span>&#160;            <span class="keyword">new</span>(result)T(std::forward&lt;Types&gt;(args)...); <span class="comment">// Explicit constructor call.</span></div>
+<div class="line"><a name="l04935"></a><span class="lineno"> 4935</span>&#160;            <span class="keywordflow">return</span> result;</div>
+<div class="line"><a name="l04936"></a><span class="lineno"> 4936</span>&#160;        }</div>
+<div class="line"><a name="l04937"></a><span class="lineno"> 4937</span>&#160;    }</div>
+<div class="line"><a name="l04938"></a><span class="lineno"> 4938</span>&#160; </div>
+<div class="line"><a name="l04939"></a><span class="lineno"> 4939</span>&#160;    <span class="comment">// No block has free item: Create new one and use it.</span></div>
+<div class="line"><a name="l04940"></a><span class="lineno"> 4940</span>&#160;    ItemBlock&amp; newBlock = CreateNewBlock();</div>
+<div class="line"><a name="l04941"></a><span class="lineno"> 4941</span>&#160;    Item* <span class="keyword">const</span> pItem = &amp;newBlock.pItems[0];</div>
+<div class="line"><a name="l04942"></a><span class="lineno"> 4942</span>&#160;    newBlock.FirstFreeIndex = pItem-&gt;NextFreeIndex;</div>
+<div class="line"><a name="l04943"></a><span class="lineno"> 4943</span>&#160;    T* result = (T*)&amp;pItem-&gt;Value;</div>
+<div class="line"><a name="l04944"></a><span class="lineno"> 4944</span>&#160;    <span class="keyword">new</span>(result)T(std::forward&lt;Types&gt;(args)...); <span class="comment">// Explicit constructor call.</span></div>
+<div class="line"><a name="l04945"></a><span class="lineno"> 4945</span>&#160;    <span class="keywordflow">return</span> result;</div>
+<div class="line"><a name="l04946"></a><span class="lineno"> 4946</span>&#160;}</div>
+<div class="line"><a name="l04947"></a><span class="lineno"> 4947</span>&#160; </div>
+<div class="line"><a name="l04948"></a><span class="lineno"> 4948</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</div>
+<div class="line"><a name="l04949"></a><span class="lineno"> 4949</span>&#160;<span class="keywordtype">void</span> VmaPoolAllocator&lt;T&gt;::Free(T* ptr)</div>
+<div class="line"><a name="l04950"></a><span class="lineno"> 4950</span>&#160;{</div>
+<div class="line"><a name="l04951"></a><span class="lineno"> 4951</span>&#160;    <span class="comment">// Search all memory blocks to find ptr.</span></div>
+<div class="line"><a name="l04952"></a><span class="lineno"> 4952</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = m_ItemBlocks.size(); i--; )</div>
+<div class="line"><a name="l04953"></a><span class="lineno"> 4953</span>&#160;    {</div>
+<div class="line"><a name="l04954"></a><span class="lineno"> 4954</span>&#160;        ItemBlock&amp; block = m_ItemBlocks[i];</div>
+<div class="line"><a name="l04955"></a><span class="lineno"> 4955</span>&#160;        </div>
+<div class="line"><a name="l04956"></a><span class="lineno"> 4956</span>&#160;        <span class="comment">// Casting to union.</span></div>
+<div class="line"><a name="l04957"></a><span class="lineno"> 4957</span>&#160;        Item* pItemPtr;</div>
+<div class="line"><a name="l04958"></a><span class="lineno"> 4958</span>&#160;        memcpy(&amp;pItemPtr, &amp;ptr, <span class="keyword">sizeof</span>(pItemPtr));</div>
+<div class="line"><a name="l04959"></a><span class="lineno"> 4959</span>&#160;        </div>
+<div class="line"><a name="l04960"></a><span class="lineno"> 4960</span>&#160;        <span class="comment">// Check if pItemPtr is in address range of this block.</span></div>
+<div class="line"><a name="l04961"></a><span class="lineno"> 4961</span>&#160;        <span class="keywordflow">if</span>((pItemPtr &gt;= block.pItems) &amp;&amp; (pItemPtr &lt; block.pItems + block.Capacity))</div>
+<div class="line"><a name="l04962"></a><span class="lineno"> 4962</span>&#160;        {</div>
+<div class="line"><a name="l04963"></a><span class="lineno"> 4963</span>&#160;            ptr-&gt;~T(); <span class="comment">// Explicit destructor call.</span></div>
+<div class="line"><a name="l04964"></a><span class="lineno"> 4964</span>&#160;            <span class="keyword">const</span> uint32_t index = <span class="keyword">static_cast&lt;</span>uint32_t<span class="keyword">&gt;</span>(pItemPtr - block.pItems);</div>
+<div class="line"><a name="l04965"></a><span class="lineno"> 4965</span>&#160;            pItemPtr-&gt;NextFreeIndex = block.FirstFreeIndex;</div>
+<div class="line"><a name="l04966"></a><span class="lineno"> 4966</span>&#160;            block.FirstFreeIndex = index;</div>
+<div class="line"><a name="l04967"></a><span class="lineno"> 4967</span>&#160;            <span class="keywordflow">return</span>;</div>
+<div class="line"><a name="l04968"></a><span class="lineno"> 4968</span>&#160;        }</div>
+<div class="line"><a name="l04969"></a><span class="lineno"> 4969</span>&#160;    }</div>
+<div class="line"><a name="l04970"></a><span class="lineno"> 4970</span>&#160;    VMA_ASSERT(0 &amp;&amp; <span class="stringliteral">&quot;Pointer doesn&#39;t belong to this memory pool.&quot;</span>);</div>
+<div class="line"><a name="l04971"></a><span class="lineno"> 4971</span>&#160;}</div>
+<div class="line"><a name="l04972"></a><span class="lineno"> 4972</span>&#160; </div>
+<div class="line"><a name="l04973"></a><span class="lineno"> 4973</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</div>
+<div class="line"><a name="l04974"></a><span class="lineno"> 4974</span>&#160;<span class="keyword">typename</span> VmaPoolAllocator&lt;T&gt;::ItemBlock&amp; VmaPoolAllocator&lt;T&gt;::CreateNewBlock()</div>
+<div class="line"><a name="l04975"></a><span class="lineno"> 4975</span>&#160;{</div>
+<div class="line"><a name="l04976"></a><span class="lineno"> 4976</span>&#160;    <span class="keyword">const</span> uint32_t newBlockCapacity = m_ItemBlocks.empty() ?</div>
+<div class="line"><a name="l04977"></a><span class="lineno"> 4977</span>&#160;        m_FirstBlockCapacity : m_ItemBlocks.back().Capacity * 3 / 2;</div>
+<div class="line"><a name="l04978"></a><span class="lineno"> 4978</span>&#160; </div>
+<div class="line"><a name="l04979"></a><span class="lineno"> 4979</span>&#160;    <span class="keyword">const</span> ItemBlock newBlock = {</div>
+<div class="line"><a name="l04980"></a><span class="lineno"> 4980</span>&#160;        vma_new_array(m_pAllocationCallbacks, Item, newBlockCapacity),</div>
+<div class="line"><a name="l04981"></a><span class="lineno"> 4981</span>&#160;        newBlockCapacity,</div>
+<div class="line"><a name="l04982"></a><span class="lineno"> 4982</span>&#160;        0 };</div>
+<div class="line"><a name="l04983"></a><span class="lineno"> 4983</span>&#160; </div>
+<div class="line"><a name="l04984"></a><span class="lineno"> 4984</span>&#160;    m_ItemBlocks.push_back(newBlock);</div>
+<div class="line"><a name="l04985"></a><span class="lineno"> 4985</span>&#160; </div>
+<div class="line"><a name="l04986"></a><span class="lineno"> 4986</span>&#160;    <span class="comment">// Setup singly-linked list of all free items in this block.</span></div>
+<div class="line"><a name="l04987"></a><span class="lineno"> 4987</span>&#160;    <span class="keywordflow">for</span>(uint32_t i = 0; i &lt; newBlockCapacity - 1; ++i)</div>
+<div class="line"><a name="l04988"></a><span class="lineno"> 4988</span>&#160;        newBlock.pItems[i].NextFreeIndex = i + 1;</div>
+<div class="line"><a name="l04989"></a><span class="lineno"> 4989</span>&#160;    newBlock.pItems[newBlockCapacity - 1].NextFreeIndex = UINT32_MAX;</div>
+<div class="line"><a name="l04990"></a><span class="lineno"> 4990</span>&#160;    <span class="keywordflow">return</span> m_ItemBlocks.back();</div>
+<div class="line"><a name="l04991"></a><span class="lineno"> 4991</span>&#160;}</div>
+<div class="line"><a name="l04992"></a><span class="lineno"> 4992</span>&#160; </div>
+<div class="line"><a name="l04994"></a><span class="lineno"> 4994</span>&#160;<span class="comment">// class VmaRawList, VmaList</span></div>
+<div class="line"><a name="l04995"></a><span class="lineno"> 4995</span>&#160; </div>
+<div class="line"><a name="l04996"></a><span class="lineno"> 4996</span>&#160;<span class="preprocessor">#if VMA_USE_STL_LIST</span></div>
+<div class="line"><a name="l04997"></a><span class="lineno"> 4997</span>&#160; </div>
+<div class="line"><a name="l04998"></a><span class="lineno"> 4998</span>&#160;<span class="preprocessor">#define VmaList std::list</span></div>
+<div class="line"><a name="l04999"></a><span class="lineno"> 4999</span>&#160; </div>
+<div class="line"><a name="l05000"></a><span class="lineno"> 5000</span>&#160;<span class="preprocessor">#else // #if VMA_USE_STL_LIST</span></div>
+<div class="line"><a name="l05001"></a><span class="lineno"> 5001</span>&#160; </div>
+<div class="line"><a name="l05002"></a><span class="lineno"> 5002</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</div>
+<div class="line"><a name="l05003"></a><span class="lineno"> 5003</span>&#160;<span class="keyword">struct </span>VmaListItem</div>
+<div class="line"><a name="l05004"></a><span class="lineno"> 5004</span>&#160;{</div>
+<div class="line"><a name="l05005"></a><span class="lineno"> 5005</span>&#160;    VmaListItem* pPrev;</div>
+<div class="line"><a name="l05006"></a><span class="lineno"> 5006</span>&#160;    VmaListItem* pNext;</div>
+<div class="line"><a name="l05007"></a><span class="lineno"> 5007</span>&#160;    T Value;</div>
+<div class="line"><a name="l05008"></a><span class="lineno"> 5008</span>&#160;};</div>
+<div class="line"><a name="l05009"></a><span class="lineno"> 5009</span>&#160; </div>
+<div class="line"><a name="l05010"></a><span class="lineno"> 5010</span>&#160;<span class="comment">// Doubly linked list.</span></div>
+<div class="line"><a name="l05011"></a><span class="lineno"> 5011</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</div>
+<div class="line"><a name="l05012"></a><span class="lineno"> 5012</span>&#160;<span class="keyword">class </span>VmaRawList</div>
+<div class="line"><a name="l05013"></a><span class="lineno"> 5013</span>&#160;{</div>
+<div class="line"><a name="l05014"></a><span class="lineno"> 5014</span>&#160;    VMA_CLASS_NO_COPY(VmaRawList)</div>
+<div class="line"><a name="l05015"></a><span class="lineno"> 5015</span>&#160;<span class="keyword">public</span>:</div>
+<div class="line"><a name="l05016"></a><span class="lineno"> 5016</span>&#160;    <span class="keyword">typedef</span> VmaListItem&lt;T&gt; ItemType;</div>
+<div class="line"><a name="l05017"></a><span class="lineno"> 5017</span>&#160; </div>
+<div class="line"><a name="l05018"></a><span class="lineno"> 5018</span>&#160;    VmaRawList(<span class="keyword">const</span> VkAllocationCallbacks* pAllocationCallbacks);</div>
+<div class="line"><a name="l05019"></a><span class="lineno"> 5019</span>&#160;    ~VmaRawList();</div>
+<div class="line"><a name="l05020"></a><span class="lineno"> 5020</span>&#160;    <span class="keywordtype">void</span> Clear();</div>
+<div class="line"><a name="l05021"></a><span class="lineno"> 5021</span>&#160; </div>
+<div class="line"><a name="l05022"></a><span class="lineno"> 5022</span>&#160;    <span class="keywordtype">size_t</span> GetCount()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_Count; }</div>
+<div class="line"><a name="l05023"></a><span class="lineno"> 5023</span>&#160;    <span class="keywordtype">bool</span> IsEmpty()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_Count == 0; }</div>
+<div class="line"><a name="l05024"></a><span class="lineno"> 5024</span>&#160; </div>
+<div class="line"><a name="l05025"></a><span class="lineno"> 5025</span>&#160;    ItemType* Front() { <span class="keywordflow">return</span> m_pFront; }</div>
+<div class="line"><a name="l05026"></a><span class="lineno"> 5026</span>&#160;    <span class="keyword">const</span> ItemType* Front()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_pFront; }</div>
+<div class="line"><a name="l05027"></a><span class="lineno"> 5027</span>&#160;    ItemType* Back() { <span class="keywordflow">return</span> m_pBack; }</div>
+<div class="line"><a name="l05028"></a><span class="lineno"> 5028</span>&#160;    <span class="keyword">const</span> ItemType* Back()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_pBack; }</div>
+<div class="line"><a name="l05029"></a><span class="lineno"> 5029</span>&#160; </div>
+<div class="line"><a name="l05030"></a><span class="lineno"> 5030</span>&#160;    ItemType* PushBack();</div>
+<div class="line"><a name="l05031"></a><span class="lineno"> 5031</span>&#160;    ItemType* PushFront();</div>
+<div class="line"><a name="l05032"></a><span class="lineno"> 5032</span>&#160;    ItemType* PushBack(<span class="keyword">const</span> T&amp; value);</div>
+<div class="line"><a name="l05033"></a><span class="lineno"> 5033</span>&#160;    ItemType* PushFront(<span class="keyword">const</span> T&amp; value);</div>
+<div class="line"><a name="l05034"></a><span class="lineno"> 5034</span>&#160;    <span class="keywordtype">void</span> PopBack();</div>
+<div class="line"><a name="l05035"></a><span class="lineno"> 5035</span>&#160;    <span class="keywordtype">void</span> PopFront();</div>
+<div class="line"><a name="l05036"></a><span class="lineno"> 5036</span>&#160;    </div>
+<div class="line"><a name="l05037"></a><span class="lineno"> 5037</span>&#160;    <span class="comment">// Item can be null - it means PushBack.</span></div>
+<div class="line"><a name="l05038"></a><span class="lineno"> 5038</span>&#160;    ItemType* InsertBefore(ItemType* pItem);</div>
+<div class="line"><a name="l05039"></a><span class="lineno"> 5039</span>&#160;    <span class="comment">// Item can be null - it means PushFront.</span></div>
+<div class="line"><a name="l05040"></a><span class="lineno"> 5040</span>&#160;    ItemType* InsertAfter(ItemType* pItem);</div>
+<div class="line"><a name="l05041"></a><span class="lineno"> 5041</span>&#160; </div>
+<div class="line"><a name="l05042"></a><span class="lineno"> 5042</span>&#160;    ItemType* InsertBefore(ItemType* pItem, <span class="keyword">const</span> T&amp; value);</div>
+<div class="line"><a name="l05043"></a><span class="lineno"> 5043</span>&#160;    ItemType* InsertAfter(ItemType* pItem, <span class="keyword">const</span> T&amp; value);</div>
+<div class="line"><a name="l05044"></a><span class="lineno"> 5044</span>&#160; </div>
+<div class="line"><a name="l05045"></a><span class="lineno"> 5045</span>&#160;    <span class="keywordtype">void</span> Remove(ItemType* pItem);</div>
+<div class="line"><a name="l05046"></a><span class="lineno"> 5046</span>&#160; </div>
+<div class="line"><a name="l05047"></a><span class="lineno"> 5047</span>&#160;<span class="keyword">private</span>:</div>
+<div class="line"><a name="l05048"></a><span class="lineno"> 5048</span>&#160;    <span class="keyword">const</span> VkAllocationCallbacks* <span class="keyword">const</span> m_pAllocationCallbacks;</div>
+<div class="line"><a name="l05049"></a><span class="lineno"> 5049</span>&#160;    VmaPoolAllocator&lt;ItemType&gt; m_ItemAllocator;</div>
+<div class="line"><a name="l05050"></a><span class="lineno"> 5050</span>&#160;    ItemType* m_pFront;</div>
+<div class="line"><a name="l05051"></a><span class="lineno"> 5051</span>&#160;    ItemType* m_pBack;</div>
+<div class="line"><a name="l05052"></a><span class="lineno"> 5052</span>&#160;    <span class="keywordtype">size_t</span> m_Count;</div>
+<div class="line"><a name="l05053"></a><span class="lineno"> 5053</span>&#160;};</div>
+<div class="line"><a name="l05054"></a><span class="lineno"> 5054</span>&#160; </div>
+<div class="line"><a name="l05055"></a><span class="lineno"> 5055</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</div>
+<div class="line"><a name="l05056"></a><span class="lineno"> 5056</span>&#160;VmaRawList&lt;T&gt;::VmaRawList(<span class="keyword">const</span> VkAllocationCallbacks* pAllocationCallbacks) :</div>
+<div class="line"><a name="l05057"></a><span class="lineno"> 5057</span>&#160;    m_pAllocationCallbacks(pAllocationCallbacks),</div>
+<div class="line"><a name="l05058"></a><span class="lineno"> 5058</span>&#160;    m_ItemAllocator(pAllocationCallbacks, 128),</div>
+<div class="line"><a name="l05059"></a><span class="lineno"> 5059</span>&#160;    m_pFront(VMA_NULL),</div>
+<div class="line"><a name="l05060"></a><span class="lineno"> 5060</span>&#160;    m_pBack(VMA_NULL),</div>
+<div class="line"><a name="l05061"></a><span class="lineno"> 5061</span>&#160;    m_Count(0)</div>
+<div class="line"><a name="l05062"></a><span class="lineno"> 5062</span>&#160;{</div>
+<div class="line"><a name="l05063"></a><span class="lineno"> 5063</span>&#160;}</div>
+<div class="line"><a name="l05064"></a><span class="lineno"> 5064</span>&#160; </div>
+<div class="line"><a name="l05065"></a><span class="lineno"> 5065</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</div>
+<div class="line"><a name="l05066"></a><span class="lineno"> 5066</span>&#160;VmaRawList&lt;T&gt;::~VmaRawList()</div>
+<div class="line"><a name="l05067"></a><span class="lineno"> 5067</span>&#160;{</div>
+<div class="line"><a name="l05068"></a><span class="lineno"> 5068</span>&#160;    <span class="comment">// Intentionally not calling Clear, because that would be unnecessary</span></div>
+<div class="line"><a name="l05069"></a><span class="lineno"> 5069</span>&#160;    <span class="comment">// computations to return all items to m_ItemAllocator as free.</span></div>
+<div class="line"><a name="l05070"></a><span class="lineno"> 5070</span>&#160;}</div>
+<div class="line"><a name="l05071"></a><span class="lineno"> 5071</span>&#160; </div>
+<div class="line"><a name="l05072"></a><span class="lineno"> 5072</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</div>
+<div class="line"><a name="l05073"></a><span class="lineno"> 5073</span>&#160;<span class="keywordtype">void</span> VmaRawList&lt;T&gt;::Clear()</div>
+<div class="line"><a name="l05074"></a><span class="lineno"> 5074</span>&#160;{</div>
+<div class="line"><a name="l05075"></a><span class="lineno"> 5075</span>&#160;    <span class="keywordflow">if</span>(IsEmpty() == <span class="keyword">false</span>)</div>
+<div class="line"><a name="l05076"></a><span class="lineno"> 5076</span>&#160;    {</div>
+<div class="line"><a name="l05077"></a><span class="lineno"> 5077</span>&#160;        ItemType* pItem = m_pBack;</div>
+<div class="line"><a name="l05078"></a><span class="lineno"> 5078</span>&#160;        <span class="keywordflow">while</span>(pItem != VMA_NULL)</div>
+<div class="line"><a name="l05079"></a><span class="lineno"> 5079</span>&#160;        {</div>
+<div class="line"><a name="l05080"></a><span class="lineno"> 5080</span>&#160;            ItemType* <span class="keyword">const</span> pPrevItem = pItem-&gt;pPrev;</div>
+<div class="line"><a name="l05081"></a><span class="lineno"> 5081</span>&#160;            m_ItemAllocator.Free(pItem);</div>
+<div class="line"><a name="l05082"></a><span class="lineno"> 5082</span>&#160;            pItem = pPrevItem;</div>
+<div class="line"><a name="l05083"></a><span class="lineno"> 5083</span>&#160;        }</div>
+<div class="line"><a name="l05084"></a><span class="lineno"> 5084</span>&#160;        m_pFront = VMA_NULL;</div>
+<div class="line"><a name="l05085"></a><span class="lineno"> 5085</span>&#160;        m_pBack = VMA_NULL;</div>
+<div class="line"><a name="l05086"></a><span class="lineno"> 5086</span>&#160;        m_Count = 0;</div>
+<div class="line"><a name="l05087"></a><span class="lineno"> 5087</span>&#160;    }</div>
+<div class="line"><a name="l05088"></a><span class="lineno"> 5088</span>&#160;}</div>
+<div class="line"><a name="l05089"></a><span class="lineno"> 5089</span>&#160; </div>
+<div class="line"><a name="l05090"></a><span class="lineno"> 5090</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</div>
+<div class="line"><a name="l05091"></a><span class="lineno"> 5091</span>&#160;VmaListItem&lt;T&gt;* VmaRawList&lt;T&gt;::PushBack()</div>
+<div class="line"><a name="l05092"></a><span class="lineno"> 5092</span>&#160;{</div>
+<div class="line"><a name="l05093"></a><span class="lineno"> 5093</span>&#160;    ItemType* <span class="keyword">const</span> pNewItem = m_ItemAllocator.Alloc();</div>
+<div class="line"><a name="l05094"></a><span class="lineno"> 5094</span>&#160;    pNewItem-&gt;pNext = VMA_NULL;</div>
+<div class="line"><a name="l05095"></a><span class="lineno"> 5095</span>&#160;    <span class="keywordflow">if</span>(IsEmpty())</div>
+<div class="line"><a name="l05096"></a><span class="lineno"> 5096</span>&#160;    {</div>
+<div class="line"><a name="l05097"></a><span class="lineno"> 5097</span>&#160;        pNewItem-&gt;pPrev = VMA_NULL;</div>
+<div class="line"><a name="l05098"></a><span class="lineno"> 5098</span>&#160;        m_pFront = pNewItem;</div>
+<div class="line"><a name="l05099"></a><span class="lineno"> 5099</span>&#160;        m_pBack = pNewItem;</div>
+<div class="line"><a name="l05100"></a><span class="lineno"> 5100</span>&#160;        m_Count = 1;</div>
+<div class="line"><a name="l05101"></a><span class="lineno"> 5101</span>&#160;    }</div>
+<div class="line"><a name="l05102"></a><span class="lineno"> 5102</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l05103"></a><span class="lineno"> 5103</span>&#160;    {</div>
+<div class="line"><a name="l05104"></a><span class="lineno"> 5104</span>&#160;        pNewItem-&gt;pPrev = m_pBack;</div>
+<div class="line"><a name="l05105"></a><span class="lineno"> 5105</span>&#160;        m_pBack-&gt;pNext = pNewItem;</div>
+<div class="line"><a name="l05106"></a><span class="lineno"> 5106</span>&#160;        m_pBack = pNewItem;</div>
+<div class="line"><a name="l05107"></a><span class="lineno"> 5107</span>&#160;        ++m_Count;</div>
+<div class="line"><a name="l05108"></a><span class="lineno"> 5108</span>&#160;    }</div>
+<div class="line"><a name="l05109"></a><span class="lineno"> 5109</span>&#160;    <span class="keywordflow">return</span> pNewItem;</div>
+<div class="line"><a name="l05110"></a><span class="lineno"> 5110</span>&#160;}</div>
+<div class="line"><a name="l05111"></a><span class="lineno"> 5111</span>&#160; </div>
+<div class="line"><a name="l05112"></a><span class="lineno"> 5112</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</div>
+<div class="line"><a name="l05113"></a><span class="lineno"> 5113</span>&#160;VmaListItem&lt;T&gt;* VmaRawList&lt;T&gt;::PushFront()</div>
+<div class="line"><a name="l05114"></a><span class="lineno"> 5114</span>&#160;{</div>
+<div class="line"><a name="l05115"></a><span class="lineno"> 5115</span>&#160;    ItemType* <span class="keyword">const</span> pNewItem = m_ItemAllocator.Alloc();</div>
+<div class="line"><a name="l05116"></a><span class="lineno"> 5116</span>&#160;    pNewItem-&gt;pPrev = VMA_NULL;</div>
+<div class="line"><a name="l05117"></a><span class="lineno"> 5117</span>&#160;    <span class="keywordflow">if</span>(IsEmpty())</div>
+<div class="line"><a name="l05118"></a><span class="lineno"> 5118</span>&#160;    {</div>
+<div class="line"><a name="l05119"></a><span class="lineno"> 5119</span>&#160;        pNewItem-&gt;pNext = VMA_NULL;</div>
+<div class="line"><a name="l05120"></a><span class="lineno"> 5120</span>&#160;        m_pFront = pNewItem;</div>
+<div class="line"><a name="l05121"></a><span class="lineno"> 5121</span>&#160;        m_pBack = pNewItem;</div>
+<div class="line"><a name="l05122"></a><span class="lineno"> 5122</span>&#160;        m_Count = 1;</div>
+<div class="line"><a name="l05123"></a><span class="lineno"> 5123</span>&#160;    }</div>
+<div class="line"><a name="l05124"></a><span class="lineno"> 5124</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l05125"></a><span class="lineno"> 5125</span>&#160;    {</div>
+<div class="line"><a name="l05126"></a><span class="lineno"> 5126</span>&#160;        pNewItem-&gt;pNext = m_pFront;</div>
+<div class="line"><a name="l05127"></a><span class="lineno"> 5127</span>&#160;        m_pFront-&gt;pPrev = pNewItem;</div>
+<div class="line"><a name="l05128"></a><span class="lineno"> 5128</span>&#160;        m_pFront = pNewItem;</div>
+<div class="line"><a name="l05129"></a><span class="lineno"> 5129</span>&#160;        ++m_Count;</div>
+<div class="line"><a name="l05130"></a><span class="lineno"> 5130</span>&#160;    }</div>
+<div class="line"><a name="l05131"></a><span class="lineno"> 5131</span>&#160;    <span class="keywordflow">return</span> pNewItem;</div>
+<div class="line"><a name="l05132"></a><span class="lineno"> 5132</span>&#160;}</div>
+<div class="line"><a name="l05133"></a><span class="lineno"> 5133</span>&#160; </div>
+<div class="line"><a name="l05134"></a><span class="lineno"> 5134</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</div>
+<div class="line"><a name="l05135"></a><span class="lineno"> 5135</span>&#160;VmaListItem&lt;T&gt;* VmaRawList&lt;T&gt;::PushBack(<span class="keyword">const</span> T&amp; value)</div>
+<div class="line"><a name="l05136"></a><span class="lineno"> 5136</span>&#160;{</div>
+<div class="line"><a name="l05137"></a><span class="lineno"> 5137</span>&#160;    ItemType* <span class="keyword">const</span> pNewItem = PushBack();</div>
+<div class="line"><a name="l05138"></a><span class="lineno"> 5138</span>&#160;    pNewItem-&gt;Value = value;</div>
+<div class="line"><a name="l05139"></a><span class="lineno"> 5139</span>&#160;    <span class="keywordflow">return</span> pNewItem;</div>
+<div class="line"><a name="l05140"></a><span class="lineno"> 5140</span>&#160;}</div>
+<div class="line"><a name="l05141"></a><span class="lineno"> 5141</span>&#160; </div>
+<div class="line"><a name="l05142"></a><span class="lineno"> 5142</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</div>
+<div class="line"><a name="l05143"></a><span class="lineno"> 5143</span>&#160;VmaListItem&lt;T&gt;* VmaRawList&lt;T&gt;::PushFront(<span class="keyword">const</span> T&amp; value)</div>
+<div class="line"><a name="l05144"></a><span class="lineno"> 5144</span>&#160;{</div>
+<div class="line"><a name="l05145"></a><span class="lineno"> 5145</span>&#160;    ItemType* <span class="keyword">const</span> pNewItem = PushFront();</div>
+<div class="line"><a name="l05146"></a><span class="lineno"> 5146</span>&#160;    pNewItem-&gt;Value = value;</div>
+<div class="line"><a name="l05147"></a><span class="lineno"> 5147</span>&#160;    <span class="keywordflow">return</span> pNewItem;</div>
+<div class="line"><a name="l05148"></a><span class="lineno"> 5148</span>&#160;}</div>
+<div class="line"><a name="l05149"></a><span class="lineno"> 5149</span>&#160; </div>
+<div class="line"><a name="l05150"></a><span class="lineno"> 5150</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</div>
+<div class="line"><a name="l05151"></a><span class="lineno"> 5151</span>&#160;<span class="keywordtype">void</span> VmaRawList&lt;T&gt;::PopBack()</div>
+<div class="line"><a name="l05152"></a><span class="lineno"> 5152</span>&#160;{</div>
+<div class="line"><a name="l05153"></a><span class="lineno"> 5153</span>&#160;    VMA_HEAVY_ASSERT(m_Count &gt; 0);</div>
+<div class="line"><a name="l05154"></a><span class="lineno"> 5154</span>&#160;    ItemType* <span class="keyword">const</span> pBackItem = m_pBack;</div>
+<div class="line"><a name="l05155"></a><span class="lineno"> 5155</span>&#160;    ItemType* <span class="keyword">const</span> pPrevItem = pBackItem-&gt;pPrev;</div>
+<div class="line"><a name="l05156"></a><span class="lineno"> 5156</span>&#160;    <span class="keywordflow">if</span>(pPrevItem != VMA_NULL)</div>
+<div class="line"><a name="l05157"></a><span class="lineno"> 5157</span>&#160;    {</div>
+<div class="line"><a name="l05158"></a><span class="lineno"> 5158</span>&#160;        pPrevItem-&gt;pNext = VMA_NULL;</div>
+<div class="line"><a name="l05159"></a><span class="lineno"> 5159</span>&#160;    }</div>
+<div class="line"><a name="l05160"></a><span class="lineno"> 5160</span>&#160;    m_pBack = pPrevItem;</div>
+<div class="line"><a name="l05161"></a><span class="lineno"> 5161</span>&#160;    m_ItemAllocator.Free(pBackItem);</div>
+<div class="line"><a name="l05162"></a><span class="lineno"> 5162</span>&#160;    --m_Count;</div>
+<div class="line"><a name="l05163"></a><span class="lineno"> 5163</span>&#160;}</div>
+<div class="line"><a name="l05164"></a><span class="lineno"> 5164</span>&#160; </div>
+<div class="line"><a name="l05165"></a><span class="lineno"> 5165</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</div>
+<div class="line"><a name="l05166"></a><span class="lineno"> 5166</span>&#160;<span class="keywordtype">void</span> VmaRawList&lt;T&gt;::PopFront()</div>
+<div class="line"><a name="l05167"></a><span class="lineno"> 5167</span>&#160;{</div>
+<div class="line"><a name="l05168"></a><span class="lineno"> 5168</span>&#160;    VMA_HEAVY_ASSERT(m_Count &gt; 0);</div>
+<div class="line"><a name="l05169"></a><span class="lineno"> 5169</span>&#160;    ItemType* <span class="keyword">const</span> pFrontItem = m_pFront;</div>
+<div class="line"><a name="l05170"></a><span class="lineno"> 5170</span>&#160;    ItemType* <span class="keyword">const</span> pNextItem = pFrontItem-&gt;pNext;</div>
+<div class="line"><a name="l05171"></a><span class="lineno"> 5171</span>&#160;    <span class="keywordflow">if</span>(pNextItem != VMA_NULL)</div>
+<div class="line"><a name="l05172"></a><span class="lineno"> 5172</span>&#160;    {</div>
+<div class="line"><a name="l05173"></a><span class="lineno"> 5173</span>&#160;        pNextItem-&gt;pPrev = VMA_NULL;</div>
+<div class="line"><a name="l05174"></a><span class="lineno"> 5174</span>&#160;    }</div>
+<div class="line"><a name="l05175"></a><span class="lineno"> 5175</span>&#160;    m_pFront = pNextItem;</div>
+<div class="line"><a name="l05176"></a><span class="lineno"> 5176</span>&#160;    m_ItemAllocator.Free(pFrontItem);</div>
+<div class="line"><a name="l05177"></a><span class="lineno"> 5177</span>&#160;    --m_Count;</div>
+<div class="line"><a name="l05178"></a><span class="lineno"> 5178</span>&#160;}</div>
+<div class="line"><a name="l05179"></a><span class="lineno"> 5179</span>&#160; </div>
+<div class="line"><a name="l05180"></a><span class="lineno"> 5180</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</div>
+<div class="line"><a name="l05181"></a><span class="lineno"> 5181</span>&#160;<span class="keywordtype">void</span> VmaRawList&lt;T&gt;::Remove(ItemType* pItem)</div>
+<div class="line"><a name="l05182"></a><span class="lineno"> 5182</span>&#160;{</div>
+<div class="line"><a name="l05183"></a><span class="lineno"> 5183</span>&#160;    VMA_HEAVY_ASSERT(pItem != VMA_NULL);</div>
+<div class="line"><a name="l05184"></a><span class="lineno"> 5184</span>&#160;    VMA_HEAVY_ASSERT(m_Count &gt; 0);</div>
+<div class="line"><a name="l05185"></a><span class="lineno"> 5185</span>&#160; </div>
+<div class="line"><a name="l05186"></a><span class="lineno"> 5186</span>&#160;    <span class="keywordflow">if</span>(pItem-&gt;pPrev != VMA_NULL)</div>
+<div class="line"><a name="l05187"></a><span class="lineno"> 5187</span>&#160;    {</div>
+<div class="line"><a name="l05188"></a><span class="lineno"> 5188</span>&#160;        pItem-&gt;pPrev-&gt;pNext = pItem-&gt;pNext;</div>
+<div class="line"><a name="l05189"></a><span class="lineno"> 5189</span>&#160;    }</div>
+<div class="line"><a name="l05190"></a><span class="lineno"> 5190</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l05191"></a><span class="lineno"> 5191</span>&#160;    {</div>
+<div class="line"><a name="l05192"></a><span class="lineno"> 5192</span>&#160;        VMA_HEAVY_ASSERT(m_pFront == pItem);</div>
+<div class="line"><a name="l05193"></a><span class="lineno"> 5193</span>&#160;        m_pFront = pItem-&gt;pNext;</div>
+<div class="line"><a name="l05194"></a><span class="lineno"> 5194</span>&#160;    }</div>
+<div class="line"><a name="l05195"></a><span class="lineno"> 5195</span>&#160; </div>
+<div class="line"><a name="l05196"></a><span class="lineno"> 5196</span>&#160;    <span class="keywordflow">if</span>(pItem-&gt;pNext != VMA_NULL)</div>
+<div class="line"><a name="l05197"></a><span class="lineno"> 5197</span>&#160;    {</div>
+<div class="line"><a name="l05198"></a><span class="lineno"> 5198</span>&#160;        pItem-&gt;pNext-&gt;pPrev = pItem-&gt;pPrev;</div>
+<div class="line"><a name="l05199"></a><span class="lineno"> 5199</span>&#160;    }</div>
+<div class="line"><a name="l05200"></a><span class="lineno"> 5200</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l05201"></a><span class="lineno"> 5201</span>&#160;    {</div>
+<div class="line"><a name="l05202"></a><span class="lineno"> 5202</span>&#160;        VMA_HEAVY_ASSERT(m_pBack == pItem);</div>
+<div class="line"><a name="l05203"></a><span class="lineno"> 5203</span>&#160;        m_pBack = pItem-&gt;pPrev;</div>
+<div class="line"><a name="l05204"></a><span class="lineno"> 5204</span>&#160;    }</div>
+<div class="line"><a name="l05205"></a><span class="lineno"> 5205</span>&#160; </div>
+<div class="line"><a name="l05206"></a><span class="lineno"> 5206</span>&#160;    m_ItemAllocator.Free(pItem);</div>
+<div class="line"><a name="l05207"></a><span class="lineno"> 5207</span>&#160;    --m_Count;</div>
+<div class="line"><a name="l05208"></a><span class="lineno"> 5208</span>&#160;}</div>
+<div class="line"><a name="l05209"></a><span class="lineno"> 5209</span>&#160; </div>
+<div class="line"><a name="l05210"></a><span class="lineno"> 5210</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</div>
+<div class="line"><a name="l05211"></a><span class="lineno"> 5211</span>&#160;VmaListItem&lt;T&gt;* VmaRawList&lt;T&gt;::InsertBefore(ItemType* pItem)</div>
+<div class="line"><a name="l05212"></a><span class="lineno"> 5212</span>&#160;{</div>
+<div class="line"><a name="l05213"></a><span class="lineno"> 5213</span>&#160;    <span class="keywordflow">if</span>(pItem != VMA_NULL)</div>
+<div class="line"><a name="l05214"></a><span class="lineno"> 5214</span>&#160;    {</div>
+<div class="line"><a name="l05215"></a><span class="lineno"> 5215</span>&#160;        ItemType* <span class="keyword">const</span> prevItem = pItem-&gt;pPrev;</div>
+<div class="line"><a name="l05216"></a><span class="lineno"> 5216</span>&#160;        ItemType* <span class="keyword">const</span> newItem = m_ItemAllocator.Alloc();</div>
+<div class="line"><a name="l05217"></a><span class="lineno"> 5217</span>&#160;        newItem-&gt;pPrev = prevItem;</div>
+<div class="line"><a name="l05218"></a><span class="lineno"> 5218</span>&#160;        newItem-&gt;pNext = pItem;</div>
+<div class="line"><a name="l05219"></a><span class="lineno"> 5219</span>&#160;        pItem-&gt;pPrev = newItem;</div>
+<div class="line"><a name="l05220"></a><span class="lineno"> 5220</span>&#160;        <span class="keywordflow">if</span>(prevItem != VMA_NULL)</div>
+<div class="line"><a name="l05221"></a><span class="lineno"> 5221</span>&#160;        {</div>
+<div class="line"><a name="l05222"></a><span class="lineno"> 5222</span>&#160;            prevItem-&gt;pNext = newItem;</div>
+<div class="line"><a name="l05223"></a><span class="lineno"> 5223</span>&#160;        }</div>
+<div class="line"><a name="l05224"></a><span class="lineno"> 5224</span>&#160;        <span class="keywordflow">else</span></div>
+<div class="line"><a name="l05225"></a><span class="lineno"> 5225</span>&#160;        {</div>
+<div class="line"><a name="l05226"></a><span class="lineno"> 5226</span>&#160;            VMA_HEAVY_ASSERT(m_pFront == pItem);</div>
+<div class="line"><a name="l05227"></a><span class="lineno"> 5227</span>&#160;            m_pFront = newItem;</div>
+<div class="line"><a name="l05228"></a><span class="lineno"> 5228</span>&#160;        }</div>
+<div class="line"><a name="l05229"></a><span class="lineno"> 5229</span>&#160;        ++m_Count;</div>
+<div class="line"><a name="l05230"></a><span class="lineno"> 5230</span>&#160;        <span class="keywordflow">return</span> newItem;</div>
+<div class="line"><a name="l05231"></a><span class="lineno"> 5231</span>&#160;    }</div>
+<div class="line"><a name="l05232"></a><span class="lineno"> 5232</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l05233"></a><span class="lineno"> 5233</span>&#160;        <span class="keywordflow">return</span> PushBack();</div>
+<div class="line"><a name="l05234"></a><span class="lineno"> 5234</span>&#160;}</div>
+<div class="line"><a name="l05235"></a><span class="lineno"> 5235</span>&#160; </div>
+<div class="line"><a name="l05236"></a><span class="lineno"> 5236</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</div>
+<div class="line"><a name="l05237"></a><span class="lineno"> 5237</span>&#160;VmaListItem&lt;T&gt;* VmaRawList&lt;T&gt;::InsertAfter(ItemType* pItem)</div>
+<div class="line"><a name="l05238"></a><span class="lineno"> 5238</span>&#160;{</div>
+<div class="line"><a name="l05239"></a><span class="lineno"> 5239</span>&#160;    <span class="keywordflow">if</span>(pItem != VMA_NULL)</div>
+<div class="line"><a name="l05240"></a><span class="lineno"> 5240</span>&#160;    {</div>
+<div class="line"><a name="l05241"></a><span class="lineno"> 5241</span>&#160;        ItemType* <span class="keyword">const</span> nextItem = pItem-&gt;pNext;</div>
+<div class="line"><a name="l05242"></a><span class="lineno"> 5242</span>&#160;        ItemType* <span class="keyword">const</span> newItem = m_ItemAllocator.Alloc();</div>
+<div class="line"><a name="l05243"></a><span class="lineno"> 5243</span>&#160;        newItem-&gt;pNext = nextItem;</div>
+<div class="line"><a name="l05244"></a><span class="lineno"> 5244</span>&#160;        newItem-&gt;pPrev = pItem;</div>
+<div class="line"><a name="l05245"></a><span class="lineno"> 5245</span>&#160;        pItem-&gt;pNext = newItem;</div>
+<div class="line"><a name="l05246"></a><span class="lineno"> 5246</span>&#160;        <span class="keywordflow">if</span>(nextItem != VMA_NULL)</div>
+<div class="line"><a name="l05247"></a><span class="lineno"> 5247</span>&#160;        {</div>
+<div class="line"><a name="l05248"></a><span class="lineno"> 5248</span>&#160;            nextItem-&gt;pPrev = newItem;</div>
+<div class="line"><a name="l05249"></a><span class="lineno"> 5249</span>&#160;        }</div>
+<div class="line"><a name="l05250"></a><span class="lineno"> 5250</span>&#160;        <span class="keywordflow">else</span></div>
+<div class="line"><a name="l05251"></a><span class="lineno"> 5251</span>&#160;        {</div>
+<div class="line"><a name="l05252"></a><span class="lineno"> 5252</span>&#160;            VMA_HEAVY_ASSERT(m_pBack == pItem);</div>
+<div class="line"><a name="l05253"></a><span class="lineno"> 5253</span>&#160;            m_pBack = newItem;</div>
+<div class="line"><a name="l05254"></a><span class="lineno"> 5254</span>&#160;        }</div>
+<div class="line"><a name="l05255"></a><span class="lineno"> 5255</span>&#160;        ++m_Count;</div>
+<div class="line"><a name="l05256"></a><span class="lineno"> 5256</span>&#160;        <span class="keywordflow">return</span> newItem;</div>
+<div class="line"><a name="l05257"></a><span class="lineno"> 5257</span>&#160;    }</div>
+<div class="line"><a name="l05258"></a><span class="lineno"> 5258</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l05259"></a><span class="lineno"> 5259</span>&#160;        <span class="keywordflow">return</span> PushFront();</div>
+<div class="line"><a name="l05260"></a><span class="lineno"> 5260</span>&#160;}</div>
+<div class="line"><a name="l05261"></a><span class="lineno"> 5261</span>&#160; </div>
+<div class="line"><a name="l05262"></a><span class="lineno"> 5262</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</div>
+<div class="line"><a name="l05263"></a><span class="lineno"> 5263</span>&#160;VmaListItem&lt;T&gt;* VmaRawList&lt;T&gt;::InsertBefore(ItemType* pItem, <span class="keyword">const</span> T&amp; value)</div>
+<div class="line"><a name="l05264"></a><span class="lineno"> 5264</span>&#160;{</div>
+<div class="line"><a name="l05265"></a><span class="lineno"> 5265</span>&#160;    ItemType* <span class="keyword">const</span> newItem = InsertBefore(pItem);</div>
+<div class="line"><a name="l05266"></a><span class="lineno"> 5266</span>&#160;    newItem-&gt;Value = value;</div>
+<div class="line"><a name="l05267"></a><span class="lineno"> 5267</span>&#160;    <span class="keywordflow">return</span> newItem;</div>
+<div class="line"><a name="l05268"></a><span class="lineno"> 5268</span>&#160;}</div>
+<div class="line"><a name="l05269"></a><span class="lineno"> 5269</span>&#160; </div>
+<div class="line"><a name="l05270"></a><span class="lineno"> 5270</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</div>
+<div class="line"><a name="l05271"></a><span class="lineno"> 5271</span>&#160;VmaListItem&lt;T&gt;* VmaRawList&lt;T&gt;::InsertAfter(ItemType* pItem, <span class="keyword">const</span> T&amp; value)</div>
+<div class="line"><a name="l05272"></a><span class="lineno"> 5272</span>&#160;{</div>
+<div class="line"><a name="l05273"></a><span class="lineno"> 5273</span>&#160;    ItemType* <span class="keyword">const</span> newItem = InsertAfter(pItem);</div>
+<div class="line"><a name="l05274"></a><span class="lineno"> 5274</span>&#160;    newItem-&gt;Value = value;</div>
+<div class="line"><a name="l05275"></a><span class="lineno"> 5275</span>&#160;    <span class="keywordflow">return</span> newItem;</div>
+<div class="line"><a name="l05276"></a><span class="lineno"> 5276</span>&#160;}</div>
+<div class="line"><a name="l05277"></a><span class="lineno"> 5277</span>&#160; </div>
+<div class="line"><a name="l05278"></a><span class="lineno"> 5278</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> T, <span class="keyword">typename</span> AllocatorT&gt;</div>
+<div class="line"><a name="l05279"></a><span class="lineno"> 5279</span>&#160;<span class="keyword">class </span>VmaList</div>
+<div class="line"><a name="l05280"></a><span class="lineno"> 5280</span>&#160;{</div>
+<div class="line"><a name="l05281"></a><span class="lineno"> 5281</span>&#160;    VMA_CLASS_NO_COPY(VmaList)</div>
+<div class="line"><a name="l05282"></a><span class="lineno"> 5282</span>&#160;<span class="keyword">public</span>:</div>
+<div class="line"><a name="l05283"></a><span class="lineno"> 5283</span>&#160;    <span class="keyword">class </span>iterator</div>
+<div class="line"><a name="l05284"></a><span class="lineno"> 5284</span>&#160;    {</div>
+<div class="line"><a name="l05285"></a><span class="lineno"> 5285</span>&#160;    <span class="keyword">public</span>:</div>
+<div class="line"><a name="l05286"></a><span class="lineno"> 5286</span>&#160;        iterator() :</div>
+<div class="line"><a name="l05287"></a><span class="lineno"> 5287</span>&#160;            m_pList(VMA_NULL),</div>
+<div class="line"><a name="l05288"></a><span class="lineno"> 5288</span>&#160;            m_pItem(VMA_NULL)</div>
+<div class="line"><a name="l05289"></a><span class="lineno"> 5289</span>&#160;        {</div>
+<div class="line"><a name="l05290"></a><span class="lineno"> 5290</span>&#160;        }</div>
+<div class="line"><a name="l05291"></a><span class="lineno"> 5291</span>&#160; </div>
+<div class="line"><a name="l05292"></a><span class="lineno"> 5292</span>&#160;        T&amp; operator*()<span class="keyword"> const</span></div>
+<div class="line"><a name="l05293"></a><span class="lineno"> 5293</span>&#160;<span class="keyword">        </span>{</div>
+<div class="line"><a name="l05294"></a><span class="lineno"> 5294</span>&#160;            VMA_HEAVY_ASSERT(m_pItem != VMA_NULL);</div>
+<div class="line"><a name="l05295"></a><span class="lineno"> 5295</span>&#160;            <span class="keywordflow">return</span> m_pItem-&gt;Value;</div>
+<div class="line"><a name="l05296"></a><span class="lineno"> 5296</span>&#160;        }</div>
+<div class="line"><a name="l05297"></a><span class="lineno"> 5297</span>&#160;        T* operator-&gt;()<span class="keyword"> const</span></div>
+<div class="line"><a name="l05298"></a><span class="lineno"> 5298</span>&#160;<span class="keyword">        </span>{</div>
+<div class="line"><a name="l05299"></a><span class="lineno"> 5299</span>&#160;            VMA_HEAVY_ASSERT(m_pItem != VMA_NULL);</div>
+<div class="line"><a name="l05300"></a><span class="lineno"> 5300</span>&#160;            <span class="keywordflow">return</span> &amp;m_pItem-&gt;Value;</div>
+<div class="line"><a name="l05301"></a><span class="lineno"> 5301</span>&#160;        }</div>
+<div class="line"><a name="l05302"></a><span class="lineno"> 5302</span>&#160; </div>
+<div class="line"><a name="l05303"></a><span class="lineno"> 5303</span>&#160;        iterator&amp; operator++()</div>
+<div class="line"><a name="l05304"></a><span class="lineno"> 5304</span>&#160;        {</div>
+<div class="line"><a name="l05305"></a><span class="lineno"> 5305</span>&#160;            VMA_HEAVY_ASSERT(m_pItem != VMA_NULL);</div>
+<div class="line"><a name="l05306"></a><span class="lineno"> 5306</span>&#160;            m_pItem = m_pItem-&gt;pNext;</div>
+<div class="line"><a name="l05307"></a><span class="lineno"> 5307</span>&#160;            <span class="keywordflow">return</span> *<span class="keyword">this</span>;</div>
+<div class="line"><a name="l05308"></a><span class="lineno"> 5308</span>&#160;        }</div>
+<div class="line"><a name="l05309"></a><span class="lineno"> 5309</span>&#160;        iterator&amp; operator--()</div>
+<div class="line"><a name="l05310"></a><span class="lineno"> 5310</span>&#160;        {</div>
+<div class="line"><a name="l05311"></a><span class="lineno"> 5311</span>&#160;            <span class="keywordflow">if</span>(m_pItem != VMA_NULL)</div>
+<div class="line"><a name="l05312"></a><span class="lineno"> 5312</span>&#160;            {</div>
+<div class="line"><a name="l05313"></a><span class="lineno"> 5313</span>&#160;                m_pItem = m_pItem-&gt;pPrev;</div>
+<div class="line"><a name="l05314"></a><span class="lineno"> 5314</span>&#160;            }</div>
+<div class="line"><a name="l05315"></a><span class="lineno"> 5315</span>&#160;            <span class="keywordflow">else</span></div>
+<div class="line"><a name="l05316"></a><span class="lineno"> 5316</span>&#160;            {</div>
+<div class="line"><a name="l05317"></a><span class="lineno"> 5317</span>&#160;                VMA_HEAVY_ASSERT(!m_pList-&gt;IsEmpty());</div>
+<div class="line"><a name="l05318"></a><span class="lineno"> 5318</span>&#160;                m_pItem = m_pList-&gt;Back();</div>
+<div class="line"><a name="l05319"></a><span class="lineno"> 5319</span>&#160;            }</div>
+<div class="line"><a name="l05320"></a><span class="lineno"> 5320</span>&#160;            <span class="keywordflow">return</span> *<span class="keyword">this</span>;</div>
+<div class="line"><a name="l05321"></a><span class="lineno"> 5321</span>&#160;        }</div>
+<div class="line"><a name="l05322"></a><span class="lineno"> 5322</span>&#160; </div>
+<div class="line"><a name="l05323"></a><span class="lineno"> 5323</span>&#160;        iterator operator++(<span class="keywordtype">int</span>)</div>
+<div class="line"><a name="l05324"></a><span class="lineno"> 5324</span>&#160;        {</div>
+<div class="line"><a name="l05325"></a><span class="lineno"> 5325</span>&#160;            iterator result = *<span class="keyword">this</span>;</div>
+<div class="line"><a name="l05326"></a><span class="lineno"> 5326</span>&#160;            ++*<span class="keyword">this</span>;</div>
+<div class="line"><a name="l05327"></a><span class="lineno"> 5327</span>&#160;            <span class="keywordflow">return</span> result;</div>
+<div class="line"><a name="l05328"></a><span class="lineno"> 5328</span>&#160;        }</div>
+<div class="line"><a name="l05329"></a><span class="lineno"> 5329</span>&#160;        iterator operator--(<span class="keywordtype">int</span>)</div>
+<div class="line"><a name="l05330"></a><span class="lineno"> 5330</span>&#160;        {</div>
+<div class="line"><a name="l05331"></a><span class="lineno"> 5331</span>&#160;            iterator result = *<span class="keyword">this</span>;</div>
+<div class="line"><a name="l05332"></a><span class="lineno"> 5332</span>&#160;            --*<span class="keyword">this</span>;</div>
+<div class="line"><a name="l05333"></a><span class="lineno"> 5333</span>&#160;            <span class="keywordflow">return</span> result;</div>
+<div class="line"><a name="l05334"></a><span class="lineno"> 5334</span>&#160;        }</div>
+<div class="line"><a name="l05335"></a><span class="lineno"> 5335</span>&#160; </div>
+<div class="line"><a name="l05336"></a><span class="lineno"> 5336</span>&#160;        <span class="keywordtype">bool</span> operator==(<span class="keyword">const</span> iterator&amp; rhs)<span class="keyword"> const</span></div>
+<div class="line"><a name="l05337"></a><span class="lineno"> 5337</span>&#160;<span class="keyword">        </span>{</div>
+<div class="line"><a name="l05338"></a><span class="lineno"> 5338</span>&#160;            VMA_HEAVY_ASSERT(m_pList == rhs.m_pList);</div>
+<div class="line"><a name="l05339"></a><span class="lineno"> 5339</span>&#160;            <span class="keywordflow">return</span> m_pItem == rhs.m_pItem;</div>
+<div class="line"><a name="l05340"></a><span class="lineno"> 5340</span>&#160;        }</div>
+<div class="line"><a name="l05341"></a><span class="lineno"> 5341</span>&#160;        <span class="keywordtype">bool</span> operator!=(<span class="keyword">const</span> iterator&amp; rhs)<span class="keyword"> const</span></div>
+<div class="line"><a name="l05342"></a><span class="lineno"> 5342</span>&#160;<span class="keyword">        </span>{</div>
+<div class="line"><a name="l05343"></a><span class="lineno"> 5343</span>&#160;            VMA_HEAVY_ASSERT(m_pList == rhs.m_pList);</div>
+<div class="line"><a name="l05344"></a><span class="lineno"> 5344</span>&#160;            <span class="keywordflow">return</span> m_pItem != rhs.m_pItem;</div>
+<div class="line"><a name="l05345"></a><span class="lineno"> 5345</span>&#160;        }</div>
+<div class="line"><a name="l05346"></a><span class="lineno"> 5346</span>&#160;        </div>
+<div class="line"><a name="l05347"></a><span class="lineno"> 5347</span>&#160;    <span class="keyword">private</span>:</div>
+<div class="line"><a name="l05348"></a><span class="lineno"> 5348</span>&#160;        VmaRawList&lt;T&gt;* m_pList;</div>
+<div class="line"><a name="l05349"></a><span class="lineno"> 5349</span>&#160;        VmaListItem&lt;T&gt;* m_pItem;</div>
+<div class="line"><a name="l05350"></a><span class="lineno"> 5350</span>&#160; </div>
+<div class="line"><a name="l05351"></a><span class="lineno"> 5351</span>&#160;        iterator(VmaRawList&lt;T&gt;* pList, VmaListItem&lt;T&gt;* pItem) :</div>
+<div class="line"><a name="l05352"></a><span class="lineno"> 5352</span>&#160;            m_pList(pList),</div>
+<div class="line"><a name="l05353"></a><span class="lineno"> 5353</span>&#160;            m_pItem(pItem)</div>
+<div class="line"><a name="l05354"></a><span class="lineno"> 5354</span>&#160;        {</div>
+<div class="line"><a name="l05355"></a><span class="lineno"> 5355</span>&#160;        }</div>
+<div class="line"><a name="l05356"></a><span class="lineno"> 5356</span>&#160; </div>
+<div class="line"><a name="l05357"></a><span class="lineno"> 5357</span>&#160;        <span class="keyword">friend</span> <span class="keyword">class </span>VmaList&lt;T, AllocatorT&gt;;</div>
+<div class="line"><a name="l05358"></a><span class="lineno"> 5358</span>&#160;    };</div>
+<div class="line"><a name="l05359"></a><span class="lineno"> 5359</span>&#160; </div>
+<div class="line"><a name="l05360"></a><span class="lineno"> 5360</span>&#160;    <span class="keyword">class </span>const_iterator</div>
+<div class="line"><a name="l05361"></a><span class="lineno"> 5361</span>&#160;    {</div>
+<div class="line"><a name="l05362"></a><span class="lineno"> 5362</span>&#160;    <span class="keyword">public</span>:</div>
+<div class="line"><a name="l05363"></a><span class="lineno"> 5363</span>&#160;        const_iterator() :</div>
+<div class="line"><a name="l05364"></a><span class="lineno"> 5364</span>&#160;            m_pList(VMA_NULL),</div>
+<div class="line"><a name="l05365"></a><span class="lineno"> 5365</span>&#160;            m_pItem(VMA_NULL)</div>
+<div class="line"><a name="l05366"></a><span class="lineno"> 5366</span>&#160;        {</div>
+<div class="line"><a name="l05367"></a><span class="lineno"> 5367</span>&#160;        }</div>
+<div class="line"><a name="l05368"></a><span class="lineno"> 5368</span>&#160; </div>
+<div class="line"><a name="l05369"></a><span class="lineno"> 5369</span>&#160;        const_iterator(<span class="keyword">const</span> iterator&amp; src) :</div>
+<div class="line"><a name="l05370"></a><span class="lineno"> 5370</span>&#160;            m_pList(src.m_pList),</div>
+<div class="line"><a name="l05371"></a><span class="lineno"> 5371</span>&#160;            m_pItem(src.m_pItem)</div>
+<div class="line"><a name="l05372"></a><span class="lineno"> 5372</span>&#160;        {</div>
+<div class="line"><a name="l05373"></a><span class="lineno"> 5373</span>&#160;        }</div>
+<div class="line"><a name="l05374"></a><span class="lineno"> 5374</span>&#160;        </div>
+<div class="line"><a name="l05375"></a><span class="lineno"> 5375</span>&#160;        <span class="keyword">const</span> T&amp; operator*()<span class="keyword"> const</span></div>
+<div class="line"><a name="l05376"></a><span class="lineno"> 5376</span>&#160;<span class="keyword">        </span>{</div>
+<div class="line"><a name="l05377"></a><span class="lineno"> 5377</span>&#160;            VMA_HEAVY_ASSERT(m_pItem != VMA_NULL);</div>
+<div class="line"><a name="l05378"></a><span class="lineno"> 5378</span>&#160;            <span class="keywordflow">return</span> m_pItem-&gt;Value;</div>
+<div class="line"><a name="l05379"></a><span class="lineno"> 5379</span>&#160;        }</div>
+<div class="line"><a name="l05380"></a><span class="lineno"> 5380</span>&#160;        <span class="keyword">const</span> T* operator-&gt;()<span class="keyword"> const</span></div>
+<div class="line"><a name="l05381"></a><span class="lineno"> 5381</span>&#160;<span class="keyword">        </span>{</div>
+<div class="line"><a name="l05382"></a><span class="lineno"> 5382</span>&#160;            VMA_HEAVY_ASSERT(m_pItem != VMA_NULL);</div>
+<div class="line"><a name="l05383"></a><span class="lineno"> 5383</span>&#160;            <span class="keywordflow">return</span> &amp;m_pItem-&gt;Value;</div>
+<div class="line"><a name="l05384"></a><span class="lineno"> 5384</span>&#160;        }</div>
+<div class="line"><a name="l05385"></a><span class="lineno"> 5385</span>&#160; </div>
+<div class="line"><a name="l05386"></a><span class="lineno"> 5386</span>&#160;        const_iterator&amp; operator++()</div>
+<div class="line"><a name="l05387"></a><span class="lineno"> 5387</span>&#160;        {</div>
+<div class="line"><a name="l05388"></a><span class="lineno"> 5388</span>&#160;            VMA_HEAVY_ASSERT(m_pItem != VMA_NULL);</div>
+<div class="line"><a name="l05389"></a><span class="lineno"> 5389</span>&#160;            m_pItem = m_pItem-&gt;pNext;</div>
+<div class="line"><a name="l05390"></a><span class="lineno"> 5390</span>&#160;            <span class="keywordflow">return</span> *<span class="keyword">this</span>;</div>
+<div class="line"><a name="l05391"></a><span class="lineno"> 5391</span>&#160;        }</div>
+<div class="line"><a name="l05392"></a><span class="lineno"> 5392</span>&#160;        const_iterator&amp; operator--()</div>
+<div class="line"><a name="l05393"></a><span class="lineno"> 5393</span>&#160;        {</div>
+<div class="line"><a name="l05394"></a><span class="lineno"> 5394</span>&#160;            <span class="keywordflow">if</span>(m_pItem != VMA_NULL)</div>
+<div class="line"><a name="l05395"></a><span class="lineno"> 5395</span>&#160;            {</div>
+<div class="line"><a name="l05396"></a><span class="lineno"> 5396</span>&#160;                m_pItem = m_pItem-&gt;pPrev;</div>
+<div class="line"><a name="l05397"></a><span class="lineno"> 5397</span>&#160;            }</div>
+<div class="line"><a name="l05398"></a><span class="lineno"> 5398</span>&#160;            <span class="keywordflow">else</span></div>
+<div class="line"><a name="l05399"></a><span class="lineno"> 5399</span>&#160;            {</div>
+<div class="line"><a name="l05400"></a><span class="lineno"> 5400</span>&#160;                VMA_HEAVY_ASSERT(!m_pList-&gt;IsEmpty());</div>
+<div class="line"><a name="l05401"></a><span class="lineno"> 5401</span>&#160;                m_pItem = m_pList-&gt;Back();</div>
+<div class="line"><a name="l05402"></a><span class="lineno"> 5402</span>&#160;            }</div>
+<div class="line"><a name="l05403"></a><span class="lineno"> 5403</span>&#160;            <span class="keywordflow">return</span> *<span class="keyword">this</span>;</div>
+<div class="line"><a name="l05404"></a><span class="lineno"> 5404</span>&#160;        }</div>
+<div class="line"><a name="l05405"></a><span class="lineno"> 5405</span>&#160; </div>
+<div class="line"><a name="l05406"></a><span class="lineno"> 5406</span>&#160;        const_iterator operator++(<span class="keywordtype">int</span>)</div>
+<div class="line"><a name="l05407"></a><span class="lineno"> 5407</span>&#160;        {</div>
+<div class="line"><a name="l05408"></a><span class="lineno"> 5408</span>&#160;            const_iterator result = *<span class="keyword">this</span>;</div>
+<div class="line"><a name="l05409"></a><span class="lineno"> 5409</span>&#160;            ++*<span class="keyword">this</span>;</div>
+<div class="line"><a name="l05410"></a><span class="lineno"> 5410</span>&#160;            <span class="keywordflow">return</span> result;</div>
+<div class="line"><a name="l05411"></a><span class="lineno"> 5411</span>&#160;        }</div>
+<div class="line"><a name="l05412"></a><span class="lineno"> 5412</span>&#160;        const_iterator operator--(<span class="keywordtype">int</span>)</div>
+<div class="line"><a name="l05413"></a><span class="lineno"> 5413</span>&#160;        {</div>
+<div class="line"><a name="l05414"></a><span class="lineno"> 5414</span>&#160;            const_iterator result = *<span class="keyword">this</span>;</div>
+<div class="line"><a name="l05415"></a><span class="lineno"> 5415</span>&#160;            --*<span class="keyword">this</span>;</div>
+<div class="line"><a name="l05416"></a><span class="lineno"> 5416</span>&#160;            <span class="keywordflow">return</span> result;</div>
+<div class="line"><a name="l05417"></a><span class="lineno"> 5417</span>&#160;        }</div>
+<div class="line"><a name="l05418"></a><span class="lineno"> 5418</span>&#160; </div>
+<div class="line"><a name="l05419"></a><span class="lineno"> 5419</span>&#160;        <span class="keywordtype">bool</span> operator==(<span class="keyword">const</span> const_iterator&amp; rhs)<span class="keyword"> const</span></div>
+<div class="line"><a name="l05420"></a><span class="lineno"> 5420</span>&#160;<span class="keyword">        </span>{</div>
+<div class="line"><a name="l05421"></a><span class="lineno"> 5421</span>&#160;            VMA_HEAVY_ASSERT(m_pList == rhs.m_pList);</div>
+<div class="line"><a name="l05422"></a><span class="lineno"> 5422</span>&#160;            <span class="keywordflow">return</span> m_pItem == rhs.m_pItem;</div>
+<div class="line"><a name="l05423"></a><span class="lineno"> 5423</span>&#160;        }</div>
+<div class="line"><a name="l05424"></a><span class="lineno"> 5424</span>&#160;        <span class="keywordtype">bool</span> operator!=(<span class="keyword">const</span> const_iterator&amp; rhs)<span class="keyword"> const</span></div>
+<div class="line"><a name="l05425"></a><span class="lineno"> 5425</span>&#160;<span class="keyword">        </span>{</div>
+<div class="line"><a name="l05426"></a><span class="lineno"> 5426</span>&#160;            VMA_HEAVY_ASSERT(m_pList == rhs.m_pList);</div>
+<div class="line"><a name="l05427"></a><span class="lineno"> 5427</span>&#160;            <span class="keywordflow">return</span> m_pItem != rhs.m_pItem;</div>
+<div class="line"><a name="l05428"></a><span class="lineno"> 5428</span>&#160;        }</div>
+<div class="line"><a name="l05429"></a><span class="lineno"> 5429</span>&#160;        </div>
+<div class="line"><a name="l05430"></a><span class="lineno"> 5430</span>&#160;    <span class="keyword">private</span>:</div>
+<div class="line"><a name="l05431"></a><span class="lineno"> 5431</span>&#160;        const_iterator(<span class="keyword">const</span> VmaRawList&lt;T&gt;* pList, <span class="keyword">const</span> VmaListItem&lt;T&gt;* pItem) :</div>
+<div class="line"><a name="l05432"></a><span class="lineno"> 5432</span>&#160;            m_pList(pList),</div>
+<div class="line"><a name="l05433"></a><span class="lineno"> 5433</span>&#160;            m_pItem(pItem)</div>
+<div class="line"><a name="l05434"></a><span class="lineno"> 5434</span>&#160;        {</div>
+<div class="line"><a name="l05435"></a><span class="lineno"> 5435</span>&#160;        }</div>
+<div class="line"><a name="l05436"></a><span class="lineno"> 5436</span>&#160; </div>
+<div class="line"><a name="l05437"></a><span class="lineno"> 5437</span>&#160;        <span class="keyword">const</span> VmaRawList&lt;T&gt;* m_pList;</div>
+<div class="line"><a name="l05438"></a><span class="lineno"> 5438</span>&#160;        <span class="keyword">const</span> VmaListItem&lt;T&gt;* m_pItem;</div>
+<div class="line"><a name="l05439"></a><span class="lineno"> 5439</span>&#160; </div>
+<div class="line"><a name="l05440"></a><span class="lineno"> 5440</span>&#160;        <span class="keyword">friend</span> <span class="keyword">class </span>VmaList&lt;T, AllocatorT&gt;;</div>
+<div class="line"><a name="l05441"></a><span class="lineno"> 5441</span>&#160;    };</div>
+<div class="line"><a name="l05442"></a><span class="lineno"> 5442</span>&#160; </div>
+<div class="line"><a name="l05443"></a><span class="lineno"> 5443</span>&#160;    VmaList(<span class="keyword">const</span> AllocatorT&amp; allocator) : m_RawList(allocator.m_pCallbacks) { }</div>
+<div class="line"><a name="l05444"></a><span class="lineno"> 5444</span>&#160; </div>
+<div class="line"><a name="l05445"></a><span class="lineno"> 5445</span>&#160;    <span class="keywordtype">bool</span> empty()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_RawList.IsEmpty(); }</div>
+<div class="line"><a name="l05446"></a><span class="lineno"> 5446</span>&#160;    <span class="keywordtype">size_t</span> size()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_RawList.GetCount(); }</div>
+<div class="line"><a name="l05447"></a><span class="lineno"> 5447</span>&#160; </div>
+<div class="line"><a name="l05448"></a><span class="lineno"> 5448</span>&#160;    iterator begin() { <span class="keywordflow">return</span> iterator(&amp;m_RawList, m_RawList.Front()); }</div>
+<div class="line"><a name="l05449"></a><span class="lineno"> 5449</span>&#160;    iterator end() { <span class="keywordflow">return</span> iterator(&amp;m_RawList, VMA_NULL); }</div>
+<div class="line"><a name="l05450"></a><span class="lineno"> 5450</span>&#160; </div>
+<div class="line"><a name="l05451"></a><span class="lineno"> 5451</span>&#160;    const_iterator cbegin()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> const_iterator(&amp;m_RawList, m_RawList.Front()); }</div>
+<div class="line"><a name="l05452"></a><span class="lineno"> 5452</span>&#160;    const_iterator cend()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> const_iterator(&amp;m_RawList, VMA_NULL); }</div>
+<div class="line"><a name="l05453"></a><span class="lineno"> 5453</span>&#160; </div>
+<div class="line"><a name="l05454"></a><span class="lineno"> 5454</span>&#160;    <span class="keywordtype">void</span> clear() { m_RawList.Clear(); }</div>
+<div class="line"><a name="l05455"></a><span class="lineno"> 5455</span>&#160;    <span class="keywordtype">void</span> push_back(<span class="keyword">const</span> T&amp; value) { m_RawList.PushBack(value); }</div>
+<div class="line"><a name="l05456"></a><span class="lineno"> 5456</span>&#160;    <span class="keywordtype">void</span> erase(iterator it) { m_RawList.Remove(it.m_pItem); }</div>
+<div class="line"><a name="l05457"></a><span class="lineno"> 5457</span>&#160;    iterator insert(iterator it, <span class="keyword">const</span> T&amp; value) { <span class="keywordflow">return</span> iterator(&amp;m_RawList, m_RawList.InsertBefore(it.m_pItem, value)); }</div>
+<div class="line"><a name="l05458"></a><span class="lineno"> 5458</span>&#160; </div>
+<div class="line"><a name="l05459"></a><span class="lineno"> 5459</span>&#160;<span class="keyword">private</span>:</div>
+<div class="line"><a name="l05460"></a><span class="lineno"> 5460</span>&#160;    VmaRawList&lt;T&gt; m_RawList;</div>
+<div class="line"><a name="l05461"></a><span class="lineno"> 5461</span>&#160;};</div>
+<div class="line"><a name="l05462"></a><span class="lineno"> 5462</span>&#160; </div>
+<div class="line"><a name="l05463"></a><span class="lineno"> 5463</span>&#160;<span class="preprocessor">#endif // #if VMA_USE_STL_LIST</span></div>
+<div class="line"><a name="l05464"></a><span class="lineno"> 5464</span>&#160; </div>
+<div class="line"><a name="l05466"></a><span class="lineno"> 5466</span>&#160;<span class="comment">// class VmaMap</span></div>
+<div class="line"><a name="l05467"></a><span class="lineno"> 5467</span>&#160; </div>
+<div class="line"><a name="l05468"></a><span class="lineno"> 5468</span>&#160;<span class="comment">// Unused in this version.</span></div>
+<div class="line"><a name="l05469"></a><span class="lineno"> 5469</span>&#160;<span class="preprocessor">#if 0</span></div>
+<div class="line"><a name="l05470"></a><span class="lineno"> 5470</span>&#160; </div>
+<div class="line"><a name="l05471"></a><span class="lineno"> 5471</span>&#160;<span class="preprocessor">#if VMA_USE_STL_UNORDERED_MAP</span></div>
+<div class="line"><a name="l05472"></a><span class="lineno"> 5472</span>&#160; </div>
+<div class="line"><a name="l05473"></a><span class="lineno"> 5473</span>&#160;<span class="preprocessor">#define VmaPair std::pair</span></div>
+<div class="line"><a name="l05474"></a><span class="lineno"> 5474</span>&#160; </div>
+<div class="line"><a name="l05475"></a><span class="lineno"> 5475</span>&#160;<span class="preprocessor">#define VMA_MAP_TYPE(KeyT, ValueT) \</span></div>
+<div class="line"><a name="l05476"></a><span class="lineno"> 5476</span>&#160;<span class="preprocessor">    std::unordered_map&lt; KeyT, ValueT, std::hash&lt;KeyT&gt;, std::equal_to&lt;KeyT&gt;, VmaStlAllocator&lt; std::pair&lt;KeyT, ValueT&gt; &gt; &gt;</span></div>
+<div class="line"><a name="l05477"></a><span class="lineno"> 5477</span>&#160; </div>
+<div class="line"><a name="l05478"></a><span class="lineno"> 5478</span>&#160;<span class="preprocessor">#else // #if VMA_USE_STL_UNORDERED_MAP</span></div>
+<div class="line"><a name="l05479"></a><span class="lineno"> 5479</span>&#160; </div>
+<div class="line"><a name="l05480"></a><span class="lineno"> 5480</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> T1, <span class="keyword">typename</span> T2&gt;</div>
+<div class="line"><a name="l05481"></a><span class="lineno"> 5481</span>&#160;<span class="keyword">struct </span>VmaPair</div>
+<div class="line"><a name="l05482"></a><span class="lineno"> 5482</span>&#160;{</div>
+<div class="line"><a name="l05483"></a><span class="lineno"> 5483</span>&#160;    T1 first;</div>
+<div class="line"><a name="l05484"></a><span class="lineno"> 5484</span>&#160;    T2 second;</div>
+<div class="line"><a name="l05485"></a><span class="lineno"> 5485</span>&#160; </div>
+<div class="line"><a name="l05486"></a><span class="lineno"> 5486</span>&#160;    VmaPair() : first(), second() { }</div>
+<div class="line"><a name="l05487"></a><span class="lineno"> 5487</span>&#160;    VmaPair(<span class="keyword">const</span> T1&amp; firstSrc, <span class="keyword">const</span> T2&amp; secondSrc) : first(firstSrc), second(secondSrc) { }</div>
+<div class="line"><a name="l05488"></a><span class="lineno"> 5488</span>&#160;};</div>
+<div class="line"><a name="l05489"></a><span class="lineno"> 5489</span>&#160; </div>
+<div class="line"><a name="l05490"></a><span class="lineno"> 5490</span>&#160;<span class="comment">/* Class compatible with subset of interface of std::unordered_map.</span></div>
+<div class="line"><a name="l05491"></a><span class="lineno"> 5491</span>&#160;<span class="comment">KeyT, ValueT must be POD because they will be stored in VmaVector.</span></div>
+<div class="line"><a name="l05492"></a><span class="lineno"> 5492</span>&#160;<span class="comment">*/</span></div>
+<div class="line"><a name="l05493"></a><span class="lineno"> 5493</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> KeyT, <span class="keyword">typename</span> ValueT&gt;</div>
+<div class="line"><a name="l05494"></a><span class="lineno"> 5494</span>&#160;<span class="keyword">class </span>VmaMap</div>
+<div class="line"><a name="l05495"></a><span class="lineno"> 5495</span>&#160;{</div>
+<div class="line"><a name="l05496"></a><span class="lineno"> 5496</span>&#160;<span class="keyword">public</span>:</div>
+<div class="line"><a name="l05497"></a><span class="lineno"> 5497</span>&#160;    <span class="keyword">typedef</span> VmaPair&lt;KeyT, ValueT&gt; PairType;</div>
+<div class="line"><a name="l05498"></a><span class="lineno"> 5498</span>&#160;    <span class="keyword">typedef</span> PairType* iterator;</div>
+<div class="line"><a name="l05499"></a><span class="lineno"> 5499</span>&#160; </div>
+<div class="line"><a name="l05500"></a><span class="lineno"> 5500</span>&#160;    VmaMap(<span class="keyword">const</span> VmaStlAllocator&lt;PairType&gt;&amp; allocator) : m_Vector(allocator) { }</div>
+<div class="line"><a name="l05501"></a><span class="lineno"> 5501</span>&#160; </div>
+<div class="line"><a name="l05502"></a><span class="lineno"> 5502</span>&#160;    iterator begin() { <span class="keywordflow">return</span> m_Vector.begin(); }</div>
+<div class="line"><a name="l05503"></a><span class="lineno"> 5503</span>&#160;    iterator end() { <span class="keywordflow">return</span> m_Vector.end(); }</div>
+<div class="line"><a name="l05504"></a><span class="lineno"> 5504</span>&#160; </div>
+<div class="line"><a name="l05505"></a><span class="lineno"> 5505</span>&#160;    <span class="keywordtype">void</span> insert(<span class="keyword">const</span> PairType&amp; pair);</div>
+<div class="line"><a name="l05506"></a><span class="lineno"> 5506</span>&#160;    iterator find(<span class="keyword">const</span> KeyT&amp; key);</div>
+<div class="line"><a name="l05507"></a><span class="lineno"> 5507</span>&#160;    <span class="keywordtype">void</span> erase(iterator it);</div>
+<div class="line"><a name="l05508"></a><span class="lineno"> 5508</span>&#160;    </div>
+<div class="line"><a name="l05509"></a><span class="lineno"> 5509</span>&#160;<span class="keyword">private</span>:</div>
+<div class="line"><a name="l05510"></a><span class="lineno"> 5510</span>&#160;    VmaVector&lt; PairType, VmaStlAllocator&lt;PairType&gt; &gt; m_Vector;</div>
+<div class="line"><a name="l05511"></a><span class="lineno"> 5511</span>&#160;};</div>
+<div class="line"><a name="l05512"></a><span class="lineno"> 5512</span>&#160; </div>
+<div class="line"><a name="l05513"></a><span class="lineno"> 5513</span>&#160;<span class="preprocessor">#define VMA_MAP_TYPE(KeyT, ValueT) VmaMap&lt;KeyT, ValueT&gt;</span></div>
+<div class="line"><a name="l05514"></a><span class="lineno"> 5514</span>&#160; </div>
+<div class="line"><a name="l05515"></a><span class="lineno"> 5515</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> FirstT, <span class="keyword">typename</span> SecondT&gt;</div>
+<div class="line"><a name="l05516"></a><span class="lineno"> 5516</span>&#160;<span class="keyword">struct </span>VmaPairFirstLess</div>
+<div class="line"><a name="l05517"></a><span class="lineno"> 5517</span>&#160;{</div>
+<div class="line"><a name="l05518"></a><span class="lineno"> 5518</span>&#160;    <span class="keywordtype">bool</span> operator()(<span class="keyword">const</span> VmaPair&lt;FirstT, SecondT&gt;&amp; lhs, <span class="keyword">const</span> VmaPair&lt;FirstT, SecondT&gt;&amp; rhs)<span class="keyword"> const</span></div>
+<div class="line"><a name="l05519"></a><span class="lineno"> 5519</span>&#160;<span class="keyword">    </span>{</div>
+<div class="line"><a name="l05520"></a><span class="lineno"> 5520</span>&#160;        <span class="keywordflow">return</span> lhs.first &lt; rhs.first;</div>
+<div class="line"><a name="l05521"></a><span class="lineno"> 5521</span>&#160;    }</div>
+<div class="line"><a name="l05522"></a><span class="lineno"> 5522</span>&#160;    <span class="keywordtype">bool</span> operator()(<span class="keyword">const</span> VmaPair&lt;FirstT, SecondT&gt;&amp; lhs, <span class="keyword">const</span> FirstT&amp; rhsFirst)<span class="keyword"> const</span></div>
+<div class="line"><a name="l05523"></a><span class="lineno"> 5523</span>&#160;<span class="keyword">    </span>{</div>
+<div class="line"><a name="l05524"></a><span class="lineno"> 5524</span>&#160;        <span class="keywordflow">return</span> lhs.first &lt; rhsFirst;</div>
+<div class="line"><a name="l05525"></a><span class="lineno"> 5525</span>&#160;    }</div>
+<div class="line"><a name="l05526"></a><span class="lineno"> 5526</span>&#160;};</div>
+<div class="line"><a name="l05527"></a><span class="lineno"> 5527</span>&#160; </div>
+<div class="line"><a name="l05528"></a><span class="lineno"> 5528</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> KeyT, <span class="keyword">typename</span> ValueT&gt;</div>
+<div class="line"><a name="l05529"></a><span class="lineno"> 5529</span>&#160;<span class="keywordtype">void</span> VmaMap&lt;KeyT, ValueT&gt;::insert(<span class="keyword">const</span> PairType&amp; pair)</div>
+<div class="line"><a name="l05530"></a><span class="lineno"> 5530</span>&#160;{</div>
+<div class="line"><a name="l05531"></a><span class="lineno"> 5531</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">size_t</span> indexToInsert = VmaBinaryFindFirstNotLess(</div>
+<div class="line"><a name="l05532"></a><span class="lineno"> 5532</span>&#160;        m_Vector.data(),</div>
+<div class="line"><a name="l05533"></a><span class="lineno"> 5533</span>&#160;        m_Vector.data() + m_Vector.size(),</div>
+<div class="line"><a name="l05534"></a><span class="lineno"> 5534</span>&#160;        pair,</div>
+<div class="line"><a name="l05535"></a><span class="lineno"> 5535</span>&#160;        VmaPairFirstLess&lt;KeyT, ValueT&gt;()) - m_Vector.data();</div>
+<div class="line"><a name="l05536"></a><span class="lineno"> 5536</span>&#160;    VmaVectorInsert(m_Vector, indexToInsert, pair);</div>
+<div class="line"><a name="l05537"></a><span class="lineno"> 5537</span>&#160;}</div>
+<div class="line"><a name="l05538"></a><span class="lineno"> 5538</span>&#160; </div>
+<div class="line"><a name="l05539"></a><span class="lineno"> 5539</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> KeyT, <span class="keyword">typename</span> ValueT&gt;</div>
+<div class="line"><a name="l05540"></a><span class="lineno"> 5540</span>&#160;VmaPair&lt;KeyT, ValueT&gt;* VmaMap&lt;KeyT, ValueT&gt;::find(<span class="keyword">const</span> KeyT&amp; key)</div>
+<div class="line"><a name="l05541"></a><span class="lineno"> 5541</span>&#160;{</div>
+<div class="line"><a name="l05542"></a><span class="lineno"> 5542</span>&#160;    PairType* it = VmaBinaryFindFirstNotLess(</div>
+<div class="line"><a name="l05543"></a><span class="lineno"> 5543</span>&#160;        m_Vector.data(),</div>
+<div class="line"><a name="l05544"></a><span class="lineno"> 5544</span>&#160;        m_Vector.data() + m_Vector.size(),</div>
+<div class="line"><a name="l05545"></a><span class="lineno"> 5545</span>&#160;        key,</div>
+<div class="line"><a name="l05546"></a><span class="lineno"> 5546</span>&#160;        VmaPairFirstLess&lt;KeyT, ValueT&gt;());</div>
+<div class="line"><a name="l05547"></a><span class="lineno"> 5547</span>&#160;    <span class="keywordflow">if</span>((it != m_Vector.end()) &amp;&amp; (it-&gt;first == key))</div>
+<div class="line"><a name="l05548"></a><span class="lineno"> 5548</span>&#160;    {</div>
+<div class="line"><a name="l05549"></a><span class="lineno"> 5549</span>&#160;        <span class="keywordflow">return</span> it;</div>
+<div class="line"><a name="l05550"></a><span class="lineno"> 5550</span>&#160;    }</div>
+<div class="line"><a name="l05551"></a><span class="lineno"> 5551</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l05552"></a><span class="lineno"> 5552</span>&#160;    {</div>
+<div class="line"><a name="l05553"></a><span class="lineno"> 5553</span>&#160;        <span class="keywordflow">return</span> m_Vector.end();</div>
+<div class="line"><a name="l05554"></a><span class="lineno"> 5554</span>&#160;    }</div>
+<div class="line"><a name="l05555"></a><span class="lineno"> 5555</span>&#160;}</div>
+<div class="line"><a name="l05556"></a><span class="lineno"> 5556</span>&#160; </div>
+<div class="line"><a name="l05557"></a><span class="lineno"> 5557</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> KeyT, <span class="keyword">typename</span> ValueT&gt;</div>
+<div class="line"><a name="l05558"></a><span class="lineno"> 5558</span>&#160;<span class="keywordtype">void</span> VmaMap&lt;KeyT, ValueT&gt;::erase(iterator it)</div>
+<div class="line"><a name="l05559"></a><span class="lineno"> 5559</span>&#160;{</div>
+<div class="line"><a name="l05560"></a><span class="lineno"> 5560</span>&#160;    VmaVectorRemove(m_Vector, it - m_Vector.begin());</div>
+<div class="line"><a name="l05561"></a><span class="lineno"> 5561</span>&#160;}</div>
+<div class="line"><a name="l05562"></a><span class="lineno"> 5562</span>&#160; </div>
+<div class="line"><a name="l05563"></a><span class="lineno"> 5563</span>&#160;<span class="preprocessor">#endif // #if VMA_USE_STL_UNORDERED_MAP</span></div>
+<div class="line"><a name="l05564"></a><span class="lineno"> 5564</span>&#160; </div>
+<div class="line"><a name="l05565"></a><span class="lineno"> 5565</span>&#160;<span class="preprocessor">#endif // #if 0</span></div>
+<div class="line"><a name="l05566"></a><span class="lineno"> 5566</span>&#160; </div>
+<div class="line"><a name="l05568"></a><span class="lineno"> 5568</span>&#160; </div>
+<div class="line"><a name="l05569"></a><span class="lineno"> 5569</span>&#160;<span class="keyword">class </span>VmaDeviceMemoryBlock;</div>
+<div class="line"><a name="l05570"></a><span class="lineno"> 5570</span>&#160; </div>
+<div class="line"><a name="l05571"></a><span class="lineno"> 5571</span>&#160;<span class="keyword">enum</span> VMA_CACHE_OPERATION { VMA_CACHE_FLUSH, VMA_CACHE_INVALIDATE };</div>
+<div class="line"><a name="l05572"></a><span class="lineno"> 5572</span>&#160; </div>
+<div class="line"><a name="l05573"></a><span class="lineno"> 5573</span>&#160;<span class="keyword">struct </span>VmaAllocation_T</div>
+<div class="line"><a name="l05574"></a><span class="lineno"> 5574</span>&#160;{</div>
+<div class="line"><a name="l05575"></a><span class="lineno"> 5575</span>&#160;<span class="keyword">private</span>:</div>
+<div class="line"><a name="l05576"></a><span class="lineno"> 5576</span>&#160;    <span class="keyword">static</span> <span class="keyword">const</span> uint8_t MAP_COUNT_FLAG_PERSISTENT_MAP = 0x80;</div>
+<div class="line"><a name="l05577"></a><span class="lineno"> 5577</span>&#160; </div>
+<div class="line"><a name="l05578"></a><span class="lineno"> 5578</span>&#160;    <span class="keyword">enum</span> FLAGS</div>
+<div class="line"><a name="l05579"></a><span class="lineno"> 5579</span>&#160;    {</div>
+<div class="line"><a name="l05580"></a><span class="lineno"> 5580</span>&#160;        FLAG_USER_DATA_STRING = 0x01,</div>
+<div class="line"><a name="l05581"></a><span class="lineno"> 5581</span>&#160;    };</div>
+<div class="line"><a name="l05582"></a><span class="lineno"> 5582</span>&#160; </div>
+<div class="line"><a name="l05583"></a><span class="lineno"> 5583</span>&#160;<span class="keyword">public</span>:</div>
+<div class="line"><a name="l05584"></a><span class="lineno"> 5584</span>&#160;    <span class="keyword">enum</span> ALLOCATION_TYPE</div>
+<div class="line"><a name="l05585"></a><span class="lineno"> 5585</span>&#160;    {</div>
+<div class="line"><a name="l05586"></a><span class="lineno"> 5586</span>&#160;        ALLOCATION_TYPE_NONE,</div>
+<div class="line"><a name="l05587"></a><span class="lineno"> 5587</span>&#160;        ALLOCATION_TYPE_BLOCK,</div>
+<div class="line"><a name="l05588"></a><span class="lineno"> 5588</span>&#160;        ALLOCATION_TYPE_DEDICATED,</div>
+<div class="line"><a name="l05589"></a><span class="lineno"> 5589</span>&#160;    };</div>
+<div class="line"><a name="l05590"></a><span class="lineno"> 5590</span>&#160; </div>
+<div class="line"><a name="l05591"></a><span class="lineno"> 5591</span>&#160;    <span class="comment">/*</span></div>
+<div class="line"><a name="l05592"></a><span class="lineno"> 5592</span>&#160;<span class="comment">    This struct is allocated using VmaPoolAllocator.</span></div>
+<div class="line"><a name="l05593"></a><span class="lineno"> 5593</span>&#160;<span class="comment">    */</span></div>
+<div class="line"><a name="l05594"></a><span class="lineno"> 5594</span>&#160; </div>
+<div class="line"><a name="l05595"></a><span class="lineno"> 5595</span>&#160;    VmaAllocation_T(uint32_t currentFrameIndex, <span class="keywordtype">bool</span> userDataString) :</div>
+<div class="line"><a name="l05596"></a><span class="lineno"> 5596</span>&#160;        m_Alignment{1},</div>
+<div class="line"><a name="l05597"></a><span class="lineno"> 5597</span>&#160;        m_Size{0},</div>
+<div class="line"><a name="l05598"></a><span class="lineno"> 5598</span>&#160;        m_pUserData{VMA_NULL},</div>
+<div class="line"><a name="l05599"></a><span class="lineno"> 5599</span>&#160;        m_LastUseFrameIndex{currentFrameIndex},</div>
+<div class="line"><a name="l05600"></a><span class="lineno"> 5600</span>&#160;        m_MemoryTypeIndex{0},</div>
+<div class="line"><a name="l05601"></a><span class="lineno"> 5601</span>&#160;        m_Type{(uint8_t)ALLOCATION_TYPE_NONE},</div>
+<div class="line"><a name="l05602"></a><span class="lineno"> 5602</span>&#160;        m_SuballocationType{(uint8_t)VMA_SUBALLOCATION_TYPE_UNKNOWN},</div>
+<div class="line"><a name="l05603"></a><span class="lineno"> 5603</span>&#160;        m_MapCount{0},</div>
+<div class="line"><a name="l05604"></a><span class="lineno"> 5604</span>&#160;        m_Flags{userDataString ? (uint8_t)FLAG_USER_DATA_STRING : (uint8_t)0}</div>
+<div class="line"><a name="l05605"></a><span class="lineno"> 5605</span>&#160;    {</div>
+<div class="line"><a name="l05606"></a><span class="lineno"> 5606</span>&#160;<span class="preprocessor">#if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l05607"></a><span class="lineno"> 5607</span>&#160;        m_CreationFrameIndex = currentFrameIndex;</div>
+<div class="line"><a name="l05608"></a><span class="lineno"> 5608</span>&#160;        m_BufferImageUsage = 0;</div>
+<div class="line"><a name="l05609"></a><span class="lineno"> 5609</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l05610"></a><span class="lineno"> 5610</span>&#160;    }</div>
+<div class="line"><a name="l05611"></a><span class="lineno"> 5611</span>&#160; </div>
+<div class="line"><a name="l05612"></a><span class="lineno"> 5612</span>&#160;    ~VmaAllocation_T()</div>
+<div class="line"><a name="l05613"></a><span class="lineno"> 5613</span>&#160;    {</div>
+<div class="line"><a name="l05614"></a><span class="lineno"> 5614</span>&#160;        VMA_ASSERT((m_MapCount &amp; ~MAP_COUNT_FLAG_PERSISTENT_MAP) == 0 &amp;&amp; <span class="stringliteral">&quot;Allocation was not unmapped before destruction.&quot;</span>);</div>
+<div class="line"><a name="l05615"></a><span class="lineno"> 5615</span>&#160; </div>
+<div class="line"><a name="l05616"></a><span class="lineno"> 5616</span>&#160;        <span class="comment">// Check if owned string was freed.</span></div>
+<div class="line"><a name="l05617"></a><span class="lineno"> 5617</span>&#160;        VMA_ASSERT(m_pUserData == VMA_NULL);</div>
+<div class="line"><a name="l05618"></a><span class="lineno"> 5618</span>&#160;    }</div>
+<div class="line"><a name="l05619"></a><span class="lineno"> 5619</span>&#160; </div>
+<div class="line"><a name="l05620"></a><span class="lineno"> 5620</span>&#160;    <span class="keywordtype">void</span> InitBlockAllocation(</div>
+<div class="line"><a name="l05621"></a><span class="lineno"> 5621</span>&#160;        VmaDeviceMemoryBlock* block,</div>
+<div class="line"><a name="l05622"></a><span class="lineno"> 5622</span>&#160;        VkDeviceSize offset,</div>
+<div class="line"><a name="l05623"></a><span class="lineno"> 5623</span>&#160;        VkDeviceSize alignment,</div>
+<div class="line"><a name="l05624"></a><span class="lineno"> 5624</span>&#160;        VkDeviceSize size,</div>
+<div class="line"><a name="l05625"></a><span class="lineno"> 5625</span>&#160;        uint32_t memoryTypeIndex,</div>
+<div class="line"><a name="l05626"></a><span class="lineno"> 5626</span>&#160;        VmaSuballocationType suballocationType,</div>
+<div class="line"><a name="l05627"></a><span class="lineno"> 5627</span>&#160;        <span class="keywordtype">bool</span> mapped,</div>
+<div class="line"><a name="l05628"></a><span class="lineno"> 5628</span>&#160;        <span class="keywordtype">bool</span> canBecomeLost)</div>
+<div class="line"><a name="l05629"></a><span class="lineno"> 5629</span>&#160;    {</div>
+<div class="line"><a name="l05630"></a><span class="lineno"> 5630</span>&#160;        VMA_ASSERT(m_Type == ALLOCATION_TYPE_NONE);</div>
+<div class="line"><a name="l05631"></a><span class="lineno"> 5631</span>&#160;        VMA_ASSERT(block != VMA_NULL);</div>
+<div class="line"><a name="l05632"></a><span class="lineno"> 5632</span>&#160;        m_Type = (uint8_t)ALLOCATION_TYPE_BLOCK;</div>
+<div class="line"><a name="l05633"></a><span class="lineno"> 5633</span>&#160;        m_Alignment = alignment;</div>
+<div class="line"><a name="l05634"></a><span class="lineno"> 5634</span>&#160;        m_Size = size;</div>
+<div class="line"><a name="l05635"></a><span class="lineno"> 5635</span>&#160;        m_MemoryTypeIndex = memoryTypeIndex;</div>
+<div class="line"><a name="l05636"></a><span class="lineno"> 5636</span>&#160;        m_MapCount = mapped ? MAP_COUNT_FLAG_PERSISTENT_MAP : 0;</div>
+<div class="line"><a name="l05637"></a><span class="lineno"> 5637</span>&#160;        m_SuballocationType = (uint8_t)suballocationType;</div>
+<div class="line"><a name="l05638"></a><span class="lineno"> 5638</span>&#160;        m_BlockAllocation.m_Block = block;</div>
+<div class="line"><a name="l05639"></a><span class="lineno"> 5639</span>&#160;        m_BlockAllocation.m_Offset = offset;</div>
+<div class="line"><a name="l05640"></a><span class="lineno"> 5640</span>&#160;        m_BlockAllocation.m_CanBecomeLost = canBecomeLost;</div>
+<div class="line"><a name="l05641"></a><span class="lineno"> 5641</span>&#160;    }</div>
+<div class="line"><a name="l05642"></a><span class="lineno"> 5642</span>&#160; </div>
+<div class="line"><a name="l05643"></a><span class="lineno"> 5643</span>&#160;    <span class="keywordtype">void</span> InitLost()</div>
+<div class="line"><a name="l05644"></a><span class="lineno"> 5644</span>&#160;    {</div>
+<div class="line"><a name="l05645"></a><span class="lineno"> 5645</span>&#160;        VMA_ASSERT(m_Type == ALLOCATION_TYPE_NONE);</div>
+<div class="line"><a name="l05646"></a><span class="lineno"> 5646</span>&#160;        VMA_ASSERT(m_LastUseFrameIndex.load() == VMA_FRAME_INDEX_LOST);</div>
+<div class="line"><a name="l05647"></a><span class="lineno"> 5647</span>&#160;        m_Type = (uint8_t)ALLOCATION_TYPE_BLOCK;</div>
+<div class="line"><a name="l05648"></a><span class="lineno"> 5648</span>&#160;        m_MemoryTypeIndex = 0;</div>
+<div class="line"><a name="l05649"></a><span class="lineno"> 5649</span>&#160;        m_BlockAllocation.m_Block = VMA_NULL;</div>
+<div class="line"><a name="l05650"></a><span class="lineno"> 5650</span>&#160;        m_BlockAllocation.m_Offset = 0;</div>
+<div class="line"><a name="l05651"></a><span class="lineno"> 5651</span>&#160;        m_BlockAllocation.m_CanBecomeLost = <span class="keyword">true</span>;</div>
+<div class="line"><a name="l05652"></a><span class="lineno"> 5652</span>&#160;    }</div>
+<div class="line"><a name="l05653"></a><span class="lineno"> 5653</span>&#160; </div>
+<div class="line"><a name="l05654"></a><span class="lineno"> 5654</span>&#160;    <span class="keywordtype">void</span> ChangeBlockAllocation(</div>
+<div class="line"><a name="l05655"></a><span class="lineno"> 5655</span>&#160;        <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator,</div>
+<div class="line"><a name="l05656"></a><span class="lineno"> 5656</span>&#160;        VmaDeviceMemoryBlock* block,</div>
+<div class="line"><a name="l05657"></a><span class="lineno"> 5657</span>&#160;        VkDeviceSize offset); </div>
+<div class="line"><a name="l05658"></a><span class="lineno"> 5658</span>&#160; </div>
+<div class="line"><a name="l05659"></a><span class="lineno"> 5659</span>&#160;    <span class="keywordtype">void</span> ChangeOffset(VkDeviceSize newOffset);</div>
+<div class="line"><a name="l05660"></a><span class="lineno"> 5660</span>&#160; </div>
+<div class="line"><a name="l05661"></a><span class="lineno"> 5661</span>&#160;    <span class="comment">// pMappedData not null means allocation is created with MAPPED flag.</span></div>
+<div class="line"><a name="l05662"></a><span class="lineno"> 5662</span>&#160;    <span class="keywordtype">void</span> InitDedicatedAllocation(</div>
+<div class="line"><a name="l05663"></a><span class="lineno"> 5663</span>&#160;        uint32_t memoryTypeIndex,</div>
+<div class="line"><a name="l05664"></a><span class="lineno"> 5664</span>&#160;        VkDeviceMemory hMemory,</div>
+<div class="line"><a name="l05665"></a><span class="lineno"> 5665</span>&#160;        VmaSuballocationType suballocationType,</div>
+<div class="line"><a name="l05666"></a><span class="lineno"> 5666</span>&#160;        <span class="keywordtype">void</span>* pMappedData,</div>
+<div class="line"><a name="l05667"></a><span class="lineno"> 5667</span>&#160;        VkDeviceSize size)</div>
+<div class="line"><a name="l05668"></a><span class="lineno"> 5668</span>&#160;    {</div>
+<div class="line"><a name="l05669"></a><span class="lineno"> 5669</span>&#160;        VMA_ASSERT(m_Type == ALLOCATION_TYPE_NONE);</div>
+<div class="line"><a name="l05670"></a><span class="lineno"> 5670</span>&#160;        VMA_ASSERT(hMemory != VK_NULL_HANDLE);</div>
+<div class="line"><a name="l05671"></a><span class="lineno"> 5671</span>&#160;        m_Type = (uint8_t)ALLOCATION_TYPE_DEDICATED;</div>
+<div class="line"><a name="l05672"></a><span class="lineno"> 5672</span>&#160;        m_Alignment = 0;</div>
+<div class="line"><a name="l05673"></a><span class="lineno"> 5673</span>&#160;        m_Size = size;</div>
+<div class="line"><a name="l05674"></a><span class="lineno"> 5674</span>&#160;        m_MemoryTypeIndex = memoryTypeIndex;</div>
+<div class="line"><a name="l05675"></a><span class="lineno"> 5675</span>&#160;        m_SuballocationType = (uint8_t)suballocationType;</div>
+<div class="line"><a name="l05676"></a><span class="lineno"> 5676</span>&#160;        m_MapCount = (pMappedData != VMA_NULL) ? MAP_COUNT_FLAG_PERSISTENT_MAP : 0;</div>
+<div class="line"><a name="l05677"></a><span class="lineno"> 5677</span>&#160;        m_DedicatedAllocation.m_hMemory = hMemory;</div>
+<div class="line"><a name="l05678"></a><span class="lineno"> 5678</span>&#160;        m_DedicatedAllocation.m_pMappedData = pMappedData;</div>
+<div class="line"><a name="l05679"></a><span class="lineno"> 5679</span>&#160;    }</div>
+<div class="line"><a name="l05680"></a><span class="lineno"> 5680</span>&#160; </div>
+<div class="line"><a name="l05681"></a><span class="lineno"> 5681</span>&#160;    ALLOCATION_TYPE GetType()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> (ALLOCATION_TYPE)m_Type; }</div>
+<div class="line"><a name="l05682"></a><span class="lineno"> 5682</span>&#160;    VkDeviceSize GetAlignment()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_Alignment; }</div>
+<div class="line"><a name="l05683"></a><span class="lineno"> 5683</span>&#160;    VkDeviceSize GetSize()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_Size; }</div>
+<div class="line"><a name="l05684"></a><span class="lineno"> 5684</span>&#160;    <span class="keywordtype">bool</span> IsUserDataString()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> (m_Flags &amp; FLAG_USER_DATA_STRING) != 0; }</div>
+<div class="line"><a name="l05685"></a><span class="lineno"> 5685</span>&#160;    <span class="keywordtype">void</span>* GetUserData()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_pUserData; }</div>
+<div class="line"><a name="l05686"></a><span class="lineno"> 5686</span>&#160;    <span class="keywordtype">void</span> SetUserData(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator, <span class="keywordtype">void</span>* pUserData);</div>
+<div class="line"><a name="l05687"></a><span class="lineno"> 5687</span>&#160;    VmaSuballocationType GetSuballocationType()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> (VmaSuballocationType)m_SuballocationType; }</div>
+<div class="line"><a name="l05688"></a><span class="lineno"> 5688</span>&#160; </div>
+<div class="line"><a name="l05689"></a><span class="lineno"> 5689</span>&#160;    VmaDeviceMemoryBlock* GetBlock()<span class="keyword"> const</span></div>
+<div class="line"><a name="l05690"></a><span class="lineno"> 5690</span>&#160;<span class="keyword">    </span>{</div>
+<div class="line"><a name="l05691"></a><span class="lineno"> 5691</span>&#160;        VMA_ASSERT(m_Type == ALLOCATION_TYPE_BLOCK);</div>
+<div class="line"><a name="l05692"></a><span class="lineno"> 5692</span>&#160;        <span class="keywordflow">return</span> m_BlockAllocation.m_Block;</div>
+<div class="line"><a name="l05693"></a><span class="lineno"> 5693</span>&#160;    }</div>
+<div class="line"><a name="l05694"></a><span class="lineno"> 5694</span>&#160;    VkDeviceSize GetOffset() <span class="keyword">const</span>;</div>
+<div class="line"><a name="l05695"></a><span class="lineno"> 5695</span>&#160;    VkDeviceMemory GetMemory() <span class="keyword">const</span>;</div>
+<div class="line"><a name="l05696"></a><span class="lineno"> 5696</span>&#160;    uint32_t GetMemoryTypeIndex()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_MemoryTypeIndex; }</div>
+<div class="line"><a name="l05697"></a><span class="lineno"> 5697</span>&#160;    <span class="keywordtype">bool</span> IsPersistentMap()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> (m_MapCount &amp; MAP_COUNT_FLAG_PERSISTENT_MAP) != 0; }</div>
+<div class="line"><a name="l05698"></a><span class="lineno"> 5698</span>&#160;    <span class="keywordtype">void</span>* GetMappedData() <span class="keyword">const</span>;</div>
+<div class="line"><a name="l05699"></a><span class="lineno"> 5699</span>&#160;    <span class="keywordtype">bool</span> CanBecomeLost() <span class="keyword">const</span>;</div>
+<div class="line"><a name="l05700"></a><span class="lineno"> 5700</span>&#160;    </div>
+<div class="line"><a name="l05701"></a><span class="lineno"> 5701</span>&#160;    uint32_t GetLastUseFrameIndex()<span class="keyword"> const</span></div>
+<div class="line"><a name="l05702"></a><span class="lineno"> 5702</span>&#160;<span class="keyword">    </span>{</div>
+<div class="line"><a name="l05703"></a><span class="lineno"> 5703</span>&#160;        <span class="keywordflow">return</span> m_LastUseFrameIndex.load();</div>
+<div class="line"><a name="l05704"></a><span class="lineno"> 5704</span>&#160;    }</div>
+<div class="line"><a name="l05705"></a><span class="lineno"> 5705</span>&#160;    <span class="keywordtype">bool</span> CompareExchangeLastUseFrameIndex(uint32_t&amp; expected, uint32_t desired)</div>
+<div class="line"><a name="l05706"></a><span class="lineno"> 5706</span>&#160;    {</div>
+<div class="line"><a name="l05707"></a><span class="lineno"> 5707</span>&#160;        <span class="keywordflow">return</span> m_LastUseFrameIndex.compare_exchange_weak(expected, desired);</div>
+<div class="line"><a name="l05708"></a><span class="lineno"> 5708</span>&#160;    }</div>
+<div class="line"><a name="l05709"></a><span class="lineno"> 5709</span>&#160;    <span class="comment">/*</span></div>
+<div class="line"><a name="l05710"></a><span class="lineno"> 5710</span>&#160;<span class="comment">    - If hAllocation.LastUseFrameIndex + frameInUseCount &lt; allocator.CurrentFrameIndex,</span></div>
+<div class="line"><a name="l05711"></a><span class="lineno"> 5711</span>&#160;<span class="comment">      makes it lost by setting LastUseFrameIndex = VMA_FRAME_INDEX_LOST and returns true.</span></div>
+<div class="line"><a name="l05712"></a><span class="lineno"> 5712</span>&#160;<span class="comment">    - Else, returns false.</span></div>
+<div class="line"><a name="l05713"></a><span class="lineno"> 5713</span>&#160;<span class="comment">    </span></div>
+<div class="line"><a name="l05714"></a><span class="lineno"> 5714</span>&#160;<span class="comment">    If hAllocation is already lost, assert - you should not call it then.</span></div>
+<div class="line"><a name="l05715"></a><span class="lineno"> 5715</span>&#160;<span class="comment">    If hAllocation was not created with CAN_BECOME_LOST_BIT, assert.</span></div>
+<div class="line"><a name="l05716"></a><span class="lineno"> 5716</span>&#160;<span class="comment">    */</span></div>
+<div class="line"><a name="l05717"></a><span class="lineno"> 5717</span>&#160;    <span class="keywordtype">bool</span> MakeLost(uint32_t currentFrameIndex, uint32_t frameInUseCount);</div>
+<div class="line"><a name="l05718"></a><span class="lineno"> 5718</span>&#160; </div>
+<div class="line"><a name="l05719"></a><span class="lineno"> 5719</span>&#160;    <span class="keywordtype">void</span> DedicatedAllocCalcStatsInfo(<a class="code" href="struct_vma_stat_info.html">VmaStatInfo</a>&amp; outInfo)</div>
+<div class="line"><a name="l05720"></a><span class="lineno"> 5720</span>&#160;    {</div>
+<div class="line"><a name="l05721"></a><span class="lineno"> 5721</span>&#160;        VMA_ASSERT(m_Type == ALLOCATION_TYPE_DEDICATED);</div>
+<div class="line"><a name="l05722"></a><span class="lineno"> 5722</span>&#160;        outInfo.<a class="code" href="struct_vma_stat_info.html#abc4bb7cd611900778464c56e50c970a4">blockCount</a> = 1;</div>
+<div class="line"><a name="l05723"></a><span class="lineno"> 5723</span>&#160;        outInfo.<a class="code" href="struct_vma_stat_info.html#a537741e4d5cdddc1c0ab95ec650afaff">allocationCount</a> = 1;</div>
+<div class="line"><a name="l05724"></a><span class="lineno"> 5724</span>&#160;        outInfo.<a class="code" href="struct_vma_stat_info.html#ae06129c771bfebfd6468a7f4276502a9">unusedRangeCount</a> = 0;</div>
+<div class="line"><a name="l05725"></a><span class="lineno"> 5725</span>&#160;        outInfo.<a class="code" href="struct_vma_stat_info.html#ab0c6c73837e5a70c749fbd4f6064895a">usedBytes</a> = m_Size;</div>
+<div class="line"><a name="l05726"></a><span class="lineno"> 5726</span>&#160;        outInfo.<a class="code" href="struct_vma_stat_info.html#a1859d290aca2cd582d8dc25922092669">unusedBytes</a> = 0;</div>
+<div class="line"><a name="l05727"></a><span class="lineno"> 5727</span>&#160;        outInfo.<a class="code" href="struct_vma_stat_info.html#ade8b40bd3139c04aabd2fc538a356fea">allocationSizeMin</a> = outInfo.<a class="code" href="struct_vma_stat_info.html#a17e9733a5ecd76287d4db6e66f71f50c">allocationSizeMax</a> = m_Size;</div>
+<div class="line"><a name="l05728"></a><span class="lineno"> 5728</span>&#160;        outInfo.<a class="code" href="struct_vma_stat_info.html#aedeba931324f16589cd2416c0d2dd0d4">unusedRangeSizeMin</a> = UINT64_MAX;</div>
+<div class="line"><a name="l05729"></a><span class="lineno"> 5729</span>&#160;        outInfo.<a class="code" href="struct_vma_stat_info.html#a5ba1a2476c4d39b10f7e2f7ebbb72ac4">unusedRangeSizeMax</a> = 0;</div>
+<div class="line"><a name="l05730"></a><span class="lineno"> 5730</span>&#160;    }</div>
+<div class="line"><a name="l05731"></a><span class="lineno"> 5731</span>&#160; </div>
+<div class="line"><a name="l05732"></a><span class="lineno"> 5732</span>&#160;    <span class="keywordtype">void</span> BlockAllocMap();</div>
+<div class="line"><a name="l05733"></a><span class="lineno"> 5733</span>&#160;    <span class="keywordtype">void</span> BlockAllocUnmap();</div>
+<div class="line"><a name="l05734"></a><span class="lineno"> 5734</span>&#160;    VkResult DedicatedAllocMap(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator, <span class="keywordtype">void</span>** ppData);</div>
+<div class="line"><a name="l05735"></a><span class="lineno"> 5735</span>&#160;    <span class="keywordtype">void</span> DedicatedAllocUnmap(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator);</div>
+<div class="line"><a name="l05736"></a><span class="lineno"> 5736</span>&#160; </div>
+<div class="line"><a name="l05737"></a><span class="lineno"> 5737</span>&#160;<span class="preprocessor">#if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l05738"></a><span class="lineno"> 5738</span>&#160;    uint32_t GetCreationFrameIndex()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_CreationFrameIndex; }</div>
+<div class="line"><a name="l05739"></a><span class="lineno"> 5739</span>&#160;    uint32_t GetBufferImageUsage()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_BufferImageUsage; }</div>
+<div class="line"><a name="l05740"></a><span class="lineno"> 5740</span>&#160; </div>
+<div class="line"><a name="l05741"></a><span class="lineno"> 5741</span>&#160;    <span class="keywordtype">void</span> InitBufferImageUsage(uint32_t bufferImageUsage)</div>
+<div class="line"><a name="l05742"></a><span class="lineno"> 5742</span>&#160;    {</div>
+<div class="line"><a name="l05743"></a><span class="lineno"> 5743</span>&#160;        VMA_ASSERT(m_BufferImageUsage == 0);</div>
+<div class="line"><a name="l05744"></a><span class="lineno"> 5744</span>&#160;        m_BufferImageUsage = bufferImageUsage;</div>
+<div class="line"><a name="l05745"></a><span class="lineno"> 5745</span>&#160;    }</div>
+<div class="line"><a name="l05746"></a><span class="lineno"> 5746</span>&#160; </div>
+<div class="line"><a name="l05747"></a><span class="lineno"> 5747</span>&#160;    <span class="keywordtype">void</span> PrintParameters(<span class="keyword">class</span> VmaJsonWriter&amp; json) <span class="keyword">const</span>;</div>
+<div class="line"><a name="l05748"></a><span class="lineno"> 5748</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l05749"></a><span class="lineno"> 5749</span>&#160; </div>
+<div class="line"><a name="l05750"></a><span class="lineno"> 5750</span>&#160;<span class="keyword">private</span>:</div>
+<div class="line"><a name="l05751"></a><span class="lineno"> 5751</span>&#160;    VkDeviceSize m_Alignment;</div>
+<div class="line"><a name="l05752"></a><span class="lineno"> 5752</span>&#160;    VkDeviceSize m_Size;</div>
+<div class="line"><a name="l05753"></a><span class="lineno"> 5753</span>&#160;    <span class="keywordtype">void</span>* m_pUserData;</div>
+<div class="line"><a name="l05754"></a><span class="lineno"> 5754</span>&#160;    VMA_ATOMIC_UINT32 m_LastUseFrameIndex;</div>
+<div class="line"><a name="l05755"></a><span class="lineno"> 5755</span>&#160;    uint32_t m_MemoryTypeIndex;</div>
+<div class="line"><a name="l05756"></a><span class="lineno"> 5756</span>&#160;    uint8_t m_Type; <span class="comment">// ALLOCATION_TYPE</span></div>
+<div class="line"><a name="l05757"></a><span class="lineno"> 5757</span>&#160;    uint8_t m_SuballocationType; <span class="comment">// VmaSuballocationType</span></div>
+<div class="line"><a name="l05758"></a><span class="lineno"> 5758</span>&#160;    <span class="comment">// Bit 0x80 is set when allocation was created with VMA_ALLOCATION_CREATE_MAPPED_BIT.</span></div>
+<div class="line"><a name="l05759"></a><span class="lineno"> 5759</span>&#160;    <span class="comment">// Bits with mask 0x7F are reference counter for vmaMapMemory()/vmaUnmapMemory().</span></div>
+<div class="line"><a name="l05760"></a><span class="lineno"> 5760</span>&#160;    uint8_t m_MapCount;</div>
+<div class="line"><a name="l05761"></a><span class="lineno"> 5761</span>&#160;    uint8_t m_Flags; <span class="comment">// enum FLAGS</span></div>
+<div class="line"><a name="l05762"></a><span class="lineno"> 5762</span>&#160; </div>
+<div class="line"><a name="l05763"></a><span class="lineno"> 5763</span>&#160;    <span class="comment">// Allocation out of VmaDeviceMemoryBlock.</span></div>
+<div class="line"><a name="l05764"></a><span class="lineno"> 5764</span>&#160;    <span class="keyword">struct </span>BlockAllocation</div>
+<div class="line"><a name="l05765"></a><span class="lineno"> 5765</span>&#160;    {</div>
+<div class="line"><a name="l05766"></a><span class="lineno"> 5766</span>&#160;        VmaDeviceMemoryBlock* m_Block;</div>
+<div class="line"><a name="l05767"></a><span class="lineno"> 5767</span>&#160;        VkDeviceSize m_Offset;</div>
+<div class="line"><a name="l05768"></a><span class="lineno"> 5768</span>&#160;        <span class="keywordtype">bool</span> m_CanBecomeLost;</div>
+<div class="line"><a name="l05769"></a><span class="lineno"> 5769</span>&#160;    };</div>
+<div class="line"><a name="l05770"></a><span class="lineno"> 5770</span>&#160; </div>
+<div class="line"><a name="l05771"></a><span class="lineno"> 5771</span>&#160;    <span class="comment">// Allocation for an object that has its own private VkDeviceMemory.</span></div>
+<div class="line"><a name="l05772"></a><span class="lineno"> 5772</span>&#160;    <span class="keyword">struct </span>DedicatedAllocation</div>
+<div class="line"><a name="l05773"></a><span class="lineno"> 5773</span>&#160;    {</div>
+<div class="line"><a name="l05774"></a><span class="lineno"> 5774</span>&#160;        VkDeviceMemory m_hMemory;</div>
+<div class="line"><a name="l05775"></a><span class="lineno"> 5775</span>&#160;        <span class="keywordtype">void</span>* m_pMappedData; <span class="comment">// Not null means memory is mapped.</span></div>
+<div class="line"><a name="l05776"></a><span class="lineno"> 5776</span>&#160;    };</div>
+<div class="line"><a name="l05777"></a><span class="lineno"> 5777</span>&#160; </div>
+<div class="line"><a name="l05778"></a><span class="lineno"> 5778</span>&#160;    <span class="keyword">union</span></div>
+<div class="line"><a name="l05779"></a><span class="lineno"> 5779</span>&#160;    {</div>
+<div class="line"><a name="l05780"></a><span class="lineno"> 5780</span>&#160;        <span class="comment">// Allocation out of VmaDeviceMemoryBlock.</span></div>
+<div class="line"><a name="l05781"></a><span class="lineno"> 5781</span>&#160;        BlockAllocation m_BlockAllocation;</div>
+<div class="line"><a name="l05782"></a><span class="lineno"> 5782</span>&#160;        <span class="comment">// Allocation for an object that has its own private VkDeviceMemory.</span></div>
+<div class="line"><a name="l05783"></a><span class="lineno"> 5783</span>&#160;        DedicatedAllocation m_DedicatedAllocation;</div>
+<div class="line"><a name="l05784"></a><span class="lineno"> 5784</span>&#160;    };</div>
+<div class="line"><a name="l05785"></a><span class="lineno"> 5785</span>&#160; </div>
+<div class="line"><a name="l05786"></a><span class="lineno"> 5786</span>&#160;<span class="preprocessor">#if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l05787"></a><span class="lineno"> 5787</span>&#160;    uint32_t m_CreationFrameIndex;</div>
+<div class="line"><a name="l05788"></a><span class="lineno"> 5788</span>&#160;    uint32_t m_BufferImageUsage; <span class="comment">// 0 if unknown.</span></div>
+<div class="line"><a name="l05789"></a><span class="lineno"> 5789</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l05790"></a><span class="lineno"> 5790</span>&#160; </div>
+<div class="line"><a name="l05791"></a><span class="lineno"> 5791</span>&#160;    <span class="keywordtype">void</span> FreeUserDataString(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator);</div>
+<div class="line"><a name="l05792"></a><span class="lineno"> 5792</span>&#160;};</div>
+<div class="line"><a name="l05793"></a><span class="lineno"> 5793</span>&#160; </div>
+<div class="line"><a name="l05794"></a><span class="lineno"> 5794</span>&#160;<span class="comment">/*</span></div>
+<div class="line"><a name="l05795"></a><span class="lineno"> 5795</span>&#160;<span class="comment">Represents a region of VmaDeviceMemoryBlock that is either assigned and returned as</span></div>
+<div class="line"><a name="l05796"></a><span class="lineno"> 5796</span>&#160;<span class="comment">allocated memory block or free.</span></div>
+<div class="line"><a name="l05797"></a><span class="lineno"> 5797</span>&#160;<span class="comment">*/</span></div>
+<div class="line"><a name="l05798"></a><span class="lineno"> 5798</span>&#160;<span class="keyword">struct </span>VmaSuballocation</div>
+<div class="line"><a name="l05799"></a><span class="lineno"> 5799</span>&#160;{</div>
+<div class="line"><a name="l05800"></a><span class="lineno"> 5800</span>&#160;    VkDeviceSize offset;</div>
+<div class="line"><a name="l05801"></a><span class="lineno"> 5801</span>&#160;    VkDeviceSize size;</div>
+<div class="line"><a name="l05802"></a><span class="lineno"> 5802</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAllocation;</div>
+<div class="line"><a name="l05803"></a><span class="lineno"> 5803</span>&#160;    VmaSuballocationType type;</div>
+<div class="line"><a name="l05804"></a><span class="lineno"> 5804</span>&#160;};</div>
+<div class="line"><a name="l05805"></a><span class="lineno"> 5805</span>&#160; </div>
+<div class="line"><a name="l05806"></a><span class="lineno"> 5806</span>&#160;<span class="comment">// Comparator for offsets.</span></div>
+<div class="line"><a name="l05807"></a><span class="lineno"> 5807</span>&#160;<span class="keyword">struct </span>VmaSuballocationOffsetLess</div>
+<div class="line"><a name="l05808"></a><span class="lineno"> 5808</span>&#160;{</div>
+<div class="line"><a name="l05809"></a><span class="lineno"> 5809</span>&#160;    <span class="keywordtype">bool</span> operator()(<span class="keyword">const</span> VmaSuballocation&amp; lhs, <span class="keyword">const</span> VmaSuballocation&amp; rhs)<span class="keyword"> const</span></div>
+<div class="line"><a name="l05810"></a><span class="lineno"> 5810</span>&#160;<span class="keyword">    </span>{</div>
+<div class="line"><a name="l05811"></a><span class="lineno"> 5811</span>&#160;        <span class="keywordflow">return</span> lhs.offset &lt; rhs.offset;</div>
+<div class="line"><a name="l05812"></a><span class="lineno"> 5812</span>&#160;    }</div>
+<div class="line"><a name="l05813"></a><span class="lineno"> 5813</span>&#160;};</div>
+<div class="line"><a name="l05814"></a><span class="lineno"> 5814</span>&#160;<span class="keyword">struct </span>VmaSuballocationOffsetGreater</div>
+<div class="line"><a name="l05815"></a><span class="lineno"> 5815</span>&#160;{</div>
+<div class="line"><a name="l05816"></a><span class="lineno"> 5816</span>&#160;    <span class="keywordtype">bool</span> operator()(<span class="keyword">const</span> VmaSuballocation&amp; lhs, <span class="keyword">const</span> VmaSuballocation&amp; rhs)<span class="keyword"> const</span></div>
+<div class="line"><a name="l05817"></a><span class="lineno"> 5817</span>&#160;<span class="keyword">    </span>{</div>
+<div class="line"><a name="l05818"></a><span class="lineno"> 5818</span>&#160;        <span class="keywordflow">return</span> lhs.offset &gt; rhs.offset;</div>
+<div class="line"><a name="l05819"></a><span class="lineno"> 5819</span>&#160;    }</div>
+<div class="line"><a name="l05820"></a><span class="lineno"> 5820</span>&#160;};</div>
+<div class="line"><a name="l05821"></a><span class="lineno"> 5821</span>&#160; </div>
+<div class="line"><a name="l05822"></a><span class="lineno"> 5822</span>&#160;<span class="keyword">typedef</span> VmaList&lt; VmaSuballocation, VmaStlAllocator&lt;VmaSuballocation&gt; &gt; VmaSuballocationList;</div>
+<div class="line"><a name="l05823"></a><span class="lineno"> 5823</span>&#160; </div>
+<div class="line"><a name="l05824"></a><span class="lineno"> 5824</span>&#160;<span class="comment">// Cost of one additional allocation lost, as equivalent in bytes.</span></div>
+<div class="line"><a name="l05825"></a><span class="lineno"> 5825</span>&#160;<span class="keyword">static</span> <span class="keyword">const</span> VkDeviceSize VMA_LOST_ALLOCATION_COST = 1048576;</div>
+<div class="line"><a name="l05826"></a><span class="lineno"> 5826</span>&#160; </div>
+<div class="line"><a name="l05827"></a><span class="lineno"> 5827</span>&#160;<span class="keyword">enum class</span> VmaAllocationRequestType</div>
+<div class="line"><a name="l05828"></a><span class="lineno"> 5828</span>&#160;{</div>
+<div class="line"><a name="l05829"></a><span class="lineno"> 5829</span>&#160;    Normal,</div>
+<div class="line"><a name="l05830"></a><span class="lineno"> 5830</span>&#160;    <span class="comment">// Used by &quot;Linear&quot; algorithm.</span></div>
+<div class="line"><a name="l05831"></a><span class="lineno"> 5831</span>&#160;    UpperAddress,</div>
+<div class="line"><a name="l05832"></a><span class="lineno"> 5832</span>&#160;    EndOf1st,</div>
+<div class="line"><a name="l05833"></a><span class="lineno"> 5833</span>&#160;    EndOf2nd,</div>
+<div class="line"><a name="l05834"></a><span class="lineno"> 5834</span>&#160;};</div>
+<div class="line"><a name="l05835"></a><span class="lineno"> 5835</span>&#160; </div>
+<div class="line"><a name="l05836"></a><span class="lineno"> 5836</span>&#160;<span class="comment">/*</span></div>
+<div class="line"><a name="l05837"></a><span class="lineno"> 5837</span>&#160;<span class="comment">Parameters of planned allocation inside a VmaDeviceMemoryBlock.</span></div>
+<div class="line"><a name="l05838"></a><span class="lineno"> 5838</span>&#160;<span class="comment"></span> </div>
+<div class="line"><a name="l05839"></a><span class="lineno"> 5839</span>&#160;<span class="comment">If canMakeOtherLost was false:</span></div>
+<div class="line"><a name="l05840"></a><span class="lineno"> 5840</span>&#160;<span class="comment">- item points to a FREE suballocation.</span></div>
+<div class="line"><a name="l05841"></a><span class="lineno"> 5841</span>&#160;<span class="comment">- itemsToMakeLostCount is 0.</span></div>
+<div class="line"><a name="l05842"></a><span class="lineno"> 5842</span>&#160;<span class="comment"></span> </div>
+<div class="line"><a name="l05843"></a><span class="lineno"> 5843</span>&#160;<span class="comment">If canMakeOtherLost was true:</span></div>
+<div class="line"><a name="l05844"></a><span class="lineno"> 5844</span>&#160;<span class="comment">- item points to first of sequence of suballocations, which are either FREE,</span></div>
+<div class="line"><a name="l05845"></a><span class="lineno"> 5845</span>&#160;<span class="comment">  or point to VmaAllocations that can become lost.</span></div>
+<div class="line"><a name="l05846"></a><span class="lineno"> 5846</span>&#160;<span class="comment">- itemsToMakeLostCount is the number of VmaAllocations that need to be made lost for</span></div>
+<div class="line"><a name="l05847"></a><span class="lineno"> 5847</span>&#160;<span class="comment">  the requested allocation to succeed.</span></div>
+<div class="line"><a name="l05848"></a><span class="lineno"> 5848</span>&#160;<span class="comment">*/</span></div>
+<div class="line"><a name="l05849"></a><span class="lineno"> 5849</span>&#160;<span class="keyword">struct </span>VmaAllocationRequest</div>
+<div class="line"><a name="l05850"></a><span class="lineno"> 5850</span>&#160;{</div>
+<div class="line"><a name="l05851"></a><span class="lineno"> 5851</span>&#160;    VkDeviceSize offset;</div>
+<div class="line"><a name="l05852"></a><span class="lineno"> 5852</span>&#160;    VkDeviceSize sumFreeSize; <span class="comment">// Sum size of free items that overlap with proposed allocation.</span></div>
+<div class="line"><a name="l05853"></a><span class="lineno"> 5853</span>&#160;    VkDeviceSize sumItemSize; <span class="comment">// Sum size of items to make lost that overlap with proposed allocation.</span></div>
+<div class="line"><a name="l05854"></a><span class="lineno"> 5854</span>&#160;    VmaSuballocationList::iterator item;</div>
+<div class="line"><a name="l05855"></a><span class="lineno"> 5855</span>&#160;    <span class="keywordtype">size_t</span> itemsToMakeLostCount;</div>
+<div class="line"><a name="l05856"></a><span class="lineno"> 5856</span>&#160;    <span class="keywordtype">void</span>* customData;</div>
+<div class="line"><a name="l05857"></a><span class="lineno"> 5857</span>&#160;    VmaAllocationRequestType type;</div>
+<div class="line"><a name="l05858"></a><span class="lineno"> 5858</span>&#160; </div>
+<div class="line"><a name="l05859"></a><span class="lineno"> 5859</span>&#160;    VkDeviceSize CalcCost()<span class="keyword"> const</span></div>
+<div class="line"><a name="l05860"></a><span class="lineno"> 5860</span>&#160;<span class="keyword">    </span>{</div>
+<div class="line"><a name="l05861"></a><span class="lineno"> 5861</span>&#160;        <span class="keywordflow">return</span> sumItemSize + itemsToMakeLostCount * VMA_LOST_ALLOCATION_COST;</div>
+<div class="line"><a name="l05862"></a><span class="lineno"> 5862</span>&#160;    }</div>
+<div class="line"><a name="l05863"></a><span class="lineno"> 5863</span>&#160;};</div>
+<div class="line"><a name="l05864"></a><span class="lineno"> 5864</span>&#160; </div>
+<div class="line"><a name="l05865"></a><span class="lineno"> 5865</span>&#160;<span class="comment">/*</span></div>
+<div class="line"><a name="l05866"></a><span class="lineno"> 5866</span>&#160;<span class="comment">Data structure used for bookkeeping of allocations and unused ranges of memory</span></div>
+<div class="line"><a name="l05867"></a><span class="lineno"> 5867</span>&#160;<span class="comment">in a single VkDeviceMemory block.</span></div>
+<div class="line"><a name="l05868"></a><span class="lineno"> 5868</span>&#160;<span class="comment">*/</span></div>
+<div class="line"><a name="l05869"></a><span class="lineno"> 5869</span>&#160;<span class="keyword">class </span>VmaBlockMetadata</div>
+<div class="line"><a name="l05870"></a><span class="lineno"> 5870</span>&#160;{</div>
+<div class="line"><a name="l05871"></a><span class="lineno"> 5871</span>&#160;<span class="keyword">public</span>:</div>
+<div class="line"><a name="l05872"></a><span class="lineno"> 5872</span>&#160;    VmaBlockMetadata(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator);</div>
+<div class="line"><a name="l05873"></a><span class="lineno"> 5873</span>&#160;    <span class="keyword">virtual</span> ~VmaBlockMetadata() { }</div>
+<div class="line"><a name="l05874"></a><span class="lineno"> 5874</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">void</span> Init(VkDeviceSize size) { m_Size = size; }</div>
+<div class="line"><a name="l05875"></a><span class="lineno"> 5875</span>&#160; </div>
+<div class="line"><a name="l05876"></a><span class="lineno"> 5876</span>&#160;    <span class="comment">// Validates all data structures inside this object. If not valid, returns false.</span></div>
+<div class="line"><a name="l05877"></a><span class="lineno"> 5877</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">bool</span> Validate() <span class="keyword">const</span> = 0;</div>
+<div class="line"><a name="l05878"></a><span class="lineno"> 5878</span>&#160;    VkDeviceSize GetSize()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_Size; }</div>
+<div class="line"><a name="l05879"></a><span class="lineno"> 5879</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">size_t</span> GetAllocationCount() <span class="keyword">const</span> = 0;</div>
+<div class="line"><a name="l05880"></a><span class="lineno"> 5880</span>&#160;    <span class="keyword">virtual</span> VkDeviceSize GetSumFreeSize() <span class="keyword">const</span> = 0;</div>
+<div class="line"><a name="l05881"></a><span class="lineno"> 5881</span>&#160;    <span class="keyword">virtual</span> VkDeviceSize GetUnusedRangeSizeMax() <span class="keyword">const</span> = 0;</div>
+<div class="line"><a name="l05882"></a><span class="lineno"> 5882</span>&#160;    <span class="comment">// Returns true if this block is empty - contains only single free suballocation.</span></div>
+<div class="line"><a name="l05883"></a><span class="lineno"> 5883</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">bool</span> IsEmpty() <span class="keyword">const</span> = 0;</div>
+<div class="line"><a name="l05884"></a><span class="lineno"> 5884</span>&#160; </div>
+<div class="line"><a name="l05885"></a><span class="lineno"> 5885</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">void</span> CalcAllocationStatInfo(<a class="code" href="struct_vma_stat_info.html">VmaStatInfo</a>&amp; outInfo) <span class="keyword">const</span> = 0;</div>
+<div class="line"><a name="l05886"></a><span class="lineno"> 5886</span>&#160;    <span class="comment">// Shouldn&#39;t modify blockCount.</span></div>
+<div class="line"><a name="l05887"></a><span class="lineno"> 5887</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">void</span> AddPoolStats(<a class="code" href="struct_vma_pool_stats.html">VmaPoolStats</a>&amp; inoutStats) <span class="keyword">const</span> = 0;</div>
+<div class="line"><a name="l05888"></a><span class="lineno"> 5888</span>&#160; </div>
+<div class="line"><a name="l05889"></a><span class="lineno"> 5889</span>&#160;<span class="preprocessor">#if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l05890"></a><span class="lineno"> 5890</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">void</span> PrintDetailedMap(<span class="keyword">class</span> VmaJsonWriter&amp; json) <span class="keyword">const</span> = 0;</div>
+<div class="line"><a name="l05891"></a><span class="lineno"> 5891</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l05892"></a><span class="lineno"> 5892</span>&#160; </div>
+<div class="line"><a name="l05893"></a><span class="lineno"> 5893</span>&#160;    <span class="comment">// Tries to find a place for suballocation with given parameters inside this block.</span></div>
+<div class="line"><a name="l05894"></a><span class="lineno"> 5894</span>&#160;    <span class="comment">// If succeeded, fills pAllocationRequest and returns true.</span></div>
+<div class="line"><a name="l05895"></a><span class="lineno"> 5895</span>&#160;    <span class="comment">// If failed, returns false.</span></div>
+<div class="line"><a name="l05896"></a><span class="lineno"> 5896</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">bool</span> CreateAllocationRequest(</div>
+<div class="line"><a name="l05897"></a><span class="lineno"> 5897</span>&#160;        uint32_t currentFrameIndex,</div>
+<div class="line"><a name="l05898"></a><span class="lineno"> 5898</span>&#160;        uint32_t frameInUseCount,</div>
+<div class="line"><a name="l05899"></a><span class="lineno"> 5899</span>&#160;        VkDeviceSize bufferImageGranularity,</div>
+<div class="line"><a name="l05900"></a><span class="lineno"> 5900</span>&#160;        VkDeviceSize allocSize,</div>
+<div class="line"><a name="l05901"></a><span class="lineno"> 5901</span>&#160;        VkDeviceSize allocAlignment,</div>
+<div class="line"><a name="l05902"></a><span class="lineno"> 5902</span>&#160;        <span class="keywordtype">bool</span> upperAddress,</div>
+<div class="line"><a name="l05903"></a><span class="lineno"> 5903</span>&#160;        VmaSuballocationType allocType,</div>
+<div class="line"><a name="l05904"></a><span class="lineno"> 5904</span>&#160;        <span class="keywordtype">bool</span> canMakeOtherLost,</div>
+<div class="line"><a name="l05905"></a><span class="lineno"> 5905</span>&#160;        <span class="comment">// Always one of VMA_ALLOCATION_CREATE_STRATEGY_* or VMA_ALLOCATION_INTERNAL_STRATEGY_* flags.</span></div>
+<div class="line"><a name="l05906"></a><span class="lineno"> 5906</span>&#160;        uint32_t strategy,</div>
+<div class="line"><a name="l05907"></a><span class="lineno"> 5907</span>&#160;        VmaAllocationRequest* pAllocationRequest) = 0;</div>
+<div class="line"><a name="l05908"></a><span class="lineno"> 5908</span>&#160; </div>
+<div class="line"><a name="l05909"></a><span class="lineno"> 5909</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">bool</span> MakeRequestedAllocationsLost(</div>
+<div class="line"><a name="l05910"></a><span class="lineno"> 5910</span>&#160;        uint32_t currentFrameIndex,</div>
+<div class="line"><a name="l05911"></a><span class="lineno"> 5911</span>&#160;        uint32_t frameInUseCount,</div>
+<div class="line"><a name="l05912"></a><span class="lineno"> 5912</span>&#160;        VmaAllocationRequest* pAllocationRequest) = 0;</div>
+<div class="line"><a name="l05913"></a><span class="lineno"> 5913</span>&#160; </div>
+<div class="line"><a name="l05914"></a><span class="lineno"> 5914</span>&#160;    <span class="keyword">virtual</span> uint32_t MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount) = 0;</div>
+<div class="line"><a name="l05915"></a><span class="lineno"> 5915</span>&#160; </div>
+<div class="line"><a name="l05916"></a><span class="lineno"> 5916</span>&#160;    <span class="keyword">virtual</span> VkResult CheckCorruption(<span class="keyword">const</span> <span class="keywordtype">void</span>* pBlockData) = 0;</div>
+<div class="line"><a name="l05917"></a><span class="lineno"> 5917</span>&#160; </div>
+<div class="line"><a name="l05918"></a><span class="lineno"> 5918</span>&#160;    <span class="comment">// Makes actual allocation based on request. Request must already be checked and valid.</span></div>
+<div class="line"><a name="l05919"></a><span class="lineno"> 5919</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">void</span> Alloc(</div>
+<div class="line"><a name="l05920"></a><span class="lineno"> 5920</span>&#160;        <span class="keyword">const</span> VmaAllocationRequest&amp; request,</div>
+<div class="line"><a name="l05921"></a><span class="lineno"> 5921</span>&#160;        VmaSuballocationType type,</div>
+<div class="line"><a name="l05922"></a><span class="lineno"> 5922</span>&#160;        VkDeviceSize allocSize,</div>
+<div class="line"><a name="l05923"></a><span class="lineno"> 5923</span>&#160;        <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAllocation) = 0;</div>
+<div class="line"><a name="l05924"></a><span class="lineno"> 5924</span>&#160; </div>
+<div class="line"><a name="l05925"></a><span class="lineno"> 5925</span>&#160;    <span class="comment">// Frees suballocation assigned to given memory region.</span></div>
+<div class="line"><a name="l05926"></a><span class="lineno"> 5926</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">void</span> Free(<span class="keyword">const</span> <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation) = 0;</div>
+<div class="line"><a name="l05927"></a><span class="lineno"> 5927</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">void</span> FreeAtOffset(VkDeviceSize offset) = 0;</div>
+<div class="line"><a name="l05928"></a><span class="lineno"> 5928</span>&#160; </div>
+<div class="line"><a name="l05929"></a><span class="lineno"> 5929</span>&#160;<span class="keyword">protected</span>:</div>
+<div class="line"><a name="l05930"></a><span class="lineno"> 5930</span>&#160;    <span class="keyword">const</span> VkAllocationCallbacks* GetAllocationCallbacks()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_pAllocationCallbacks; }</div>
+<div class="line"><a name="l05931"></a><span class="lineno"> 5931</span>&#160; </div>
+<div class="line"><a name="l05932"></a><span class="lineno"> 5932</span>&#160;<span class="preprocessor">#if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l05933"></a><span class="lineno"> 5933</span>&#160;    <span class="keywordtype">void</span> PrintDetailedMap_Begin(<span class="keyword">class</span> VmaJsonWriter&amp; json,</div>
+<div class="line"><a name="l05934"></a><span class="lineno"> 5934</span>&#160;        VkDeviceSize unusedBytes,</div>
+<div class="line"><a name="l05935"></a><span class="lineno"> 5935</span>&#160;        <span class="keywordtype">size_t</span> allocationCount,</div>
+<div class="line"><a name="l05936"></a><span class="lineno"> 5936</span>&#160;        <span class="keywordtype">size_t</span> unusedRangeCount) <span class="keyword">const</span>;</div>
+<div class="line"><a name="l05937"></a><span class="lineno"> 5937</span>&#160;    <span class="keywordtype">void</span> PrintDetailedMap_Allocation(<span class="keyword">class</span> VmaJsonWriter&amp; json,</div>
+<div class="line"><a name="l05938"></a><span class="lineno"> 5938</span>&#160;        VkDeviceSize offset,</div>
+<div class="line"><a name="l05939"></a><span class="lineno"> 5939</span>&#160;        <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAllocation) <span class="keyword">const</span>;</div>
+<div class="line"><a name="l05940"></a><span class="lineno"> 5940</span>&#160;    <span class="keywordtype">void</span> PrintDetailedMap_UnusedRange(<span class="keyword">class</span> VmaJsonWriter&amp; json,</div>
+<div class="line"><a name="l05941"></a><span class="lineno"> 5941</span>&#160;        VkDeviceSize offset,</div>
+<div class="line"><a name="l05942"></a><span class="lineno"> 5942</span>&#160;        VkDeviceSize size) <span class="keyword">const</span>;</div>
+<div class="line"><a name="l05943"></a><span class="lineno"> 5943</span>&#160;    <span class="keywordtype">void</span> PrintDetailedMap_End(<span class="keyword">class</span> VmaJsonWriter&amp; json) <span class="keyword">const</span>;</div>
+<div class="line"><a name="l05944"></a><span class="lineno"> 5944</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l05945"></a><span class="lineno"> 5945</span>&#160; </div>
+<div class="line"><a name="l05946"></a><span class="lineno"> 5946</span>&#160;<span class="keyword">private</span>:</div>
+<div class="line"><a name="l05947"></a><span class="lineno"> 5947</span>&#160;    VkDeviceSize m_Size;</div>
+<div class="line"><a name="l05948"></a><span class="lineno"> 5948</span>&#160;    <span class="keyword">const</span> VkAllocationCallbacks* m_pAllocationCallbacks;</div>
+<div class="line"><a name="l05949"></a><span class="lineno"> 5949</span>&#160;};</div>
+<div class="line"><a name="l05950"></a><span class="lineno"> 5950</span>&#160; </div>
+<div class="line"><a name="l05951"></a><span class="lineno"> 5951</span>&#160;<span class="preprocessor">#define VMA_VALIDATE(cond) do { if(!(cond)) { \</span></div>
+<div class="line"><a name="l05952"></a><span class="lineno"> 5952</span>&#160;<span class="preprocessor">        VMA_ASSERT(0 &amp;&amp; &quot;Validation failed: &quot; #cond); \</span></div>
+<div class="line"><a name="l05953"></a><span class="lineno"> 5953</span>&#160;<span class="preprocessor">        return false; \</span></div>
+<div class="line"><a name="l05954"></a><span class="lineno"> 5954</span>&#160;<span class="preprocessor">    } } while(false)</span></div>
+<div class="line"><a name="l05955"></a><span class="lineno"> 5955</span>&#160; </div>
+<div class="line"><a name="l05956"></a><span class="lineno"> 5956</span>&#160;<span class="keyword">class </span>VmaBlockMetadata_Generic : <span class="keyword">public</span> VmaBlockMetadata</div>
+<div class="line"><a name="l05957"></a><span class="lineno"> 5957</span>&#160;{</div>
+<div class="line"><a name="l05958"></a><span class="lineno"> 5958</span>&#160;    VMA_CLASS_NO_COPY(VmaBlockMetadata_Generic)</div>
+<div class="line"><a name="l05959"></a><span class="lineno"> 5959</span>&#160;<span class="keyword">public</span>:</div>
+<div class="line"><a name="l05960"></a><span class="lineno"> 5960</span>&#160;    VmaBlockMetadata_Generic(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator);</div>
+<div class="line"><a name="l05961"></a><span class="lineno"> 5961</span>&#160;    <span class="keyword">virtual</span> ~VmaBlockMetadata_Generic();</div>
+<div class="line"><a name="l05962"></a><span class="lineno"> 5962</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">void</span> Init(VkDeviceSize size);</div>
+<div class="line"><a name="l05963"></a><span class="lineno"> 5963</span>&#160; </div>
+<div class="line"><a name="l05964"></a><span class="lineno"> 5964</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">bool</span> Validate() <span class="keyword">const</span>;</div>
+<div class="line"><a name="l05965"></a><span class="lineno"> 5965</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">size_t</span> GetAllocationCount()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_Suballocations.size() - m_FreeCount; }</div>
+<div class="line"><a name="l05966"></a><span class="lineno"> 5966</span>&#160;    <span class="keyword">virtual</span> VkDeviceSize GetSumFreeSize()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_SumFreeSize; }</div>
+<div class="line"><a name="l05967"></a><span class="lineno"> 5967</span>&#160;    <span class="keyword">virtual</span> VkDeviceSize GetUnusedRangeSizeMax() <span class="keyword">const</span>;</div>
+<div class="line"><a name="l05968"></a><span class="lineno"> 5968</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">bool</span> IsEmpty() <span class="keyword">const</span>;</div>
+<div class="line"><a name="l05969"></a><span class="lineno"> 5969</span>&#160; </div>
+<div class="line"><a name="l05970"></a><span class="lineno"> 5970</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">void</span> CalcAllocationStatInfo(<a class="code" href="struct_vma_stat_info.html">VmaStatInfo</a>&amp; outInfo) <span class="keyword">const</span>;</div>
+<div class="line"><a name="l05971"></a><span class="lineno"> 5971</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">void</span> AddPoolStats(<a class="code" href="struct_vma_pool_stats.html">VmaPoolStats</a>&amp; inoutStats) <span class="keyword">const</span>;</div>
+<div class="line"><a name="l05972"></a><span class="lineno"> 5972</span>&#160; </div>
+<div class="line"><a name="l05973"></a><span class="lineno"> 5973</span>&#160;<span class="preprocessor">#if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l05974"></a><span class="lineno"> 5974</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">void</span> PrintDetailedMap(<span class="keyword">class</span> VmaJsonWriter&amp; json) <span class="keyword">const</span>;</div>
+<div class="line"><a name="l05975"></a><span class="lineno"> 5975</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l05976"></a><span class="lineno"> 5976</span>&#160; </div>
+<div class="line"><a name="l05977"></a><span class="lineno"> 5977</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">bool</span> CreateAllocationRequest(</div>
+<div class="line"><a name="l05978"></a><span class="lineno"> 5978</span>&#160;        uint32_t currentFrameIndex,</div>
+<div class="line"><a name="l05979"></a><span class="lineno"> 5979</span>&#160;        uint32_t frameInUseCount,</div>
+<div class="line"><a name="l05980"></a><span class="lineno"> 5980</span>&#160;        VkDeviceSize bufferImageGranularity,</div>
+<div class="line"><a name="l05981"></a><span class="lineno"> 5981</span>&#160;        VkDeviceSize allocSize,</div>
+<div class="line"><a name="l05982"></a><span class="lineno"> 5982</span>&#160;        VkDeviceSize allocAlignment,</div>
+<div class="line"><a name="l05983"></a><span class="lineno"> 5983</span>&#160;        <span class="keywordtype">bool</span> upperAddress,</div>
+<div class="line"><a name="l05984"></a><span class="lineno"> 5984</span>&#160;        VmaSuballocationType allocType,</div>
+<div class="line"><a name="l05985"></a><span class="lineno"> 5985</span>&#160;        <span class="keywordtype">bool</span> canMakeOtherLost,</div>
+<div class="line"><a name="l05986"></a><span class="lineno"> 5986</span>&#160;        uint32_t strategy,</div>
+<div class="line"><a name="l05987"></a><span class="lineno"> 5987</span>&#160;        VmaAllocationRequest* pAllocationRequest);</div>
+<div class="line"><a name="l05988"></a><span class="lineno"> 5988</span>&#160; </div>
+<div class="line"><a name="l05989"></a><span class="lineno"> 5989</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">bool</span> MakeRequestedAllocationsLost(</div>
+<div class="line"><a name="l05990"></a><span class="lineno"> 5990</span>&#160;        uint32_t currentFrameIndex,</div>
+<div class="line"><a name="l05991"></a><span class="lineno"> 5991</span>&#160;        uint32_t frameInUseCount,</div>
+<div class="line"><a name="l05992"></a><span class="lineno"> 5992</span>&#160;        VmaAllocationRequest* pAllocationRequest);</div>
+<div class="line"><a name="l05993"></a><span class="lineno"> 5993</span>&#160; </div>
+<div class="line"><a name="l05994"></a><span class="lineno"> 5994</span>&#160;    <span class="keyword">virtual</span> uint32_t MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount);</div>
+<div class="line"><a name="l05995"></a><span class="lineno"> 5995</span>&#160; </div>
+<div class="line"><a name="l05996"></a><span class="lineno"> 5996</span>&#160;    <span class="keyword">virtual</span> VkResult CheckCorruption(<span class="keyword">const</span> <span class="keywordtype">void</span>* pBlockData);</div>
+<div class="line"><a name="l05997"></a><span class="lineno"> 5997</span>&#160; </div>
+<div class="line"><a name="l05998"></a><span class="lineno"> 5998</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">void</span> Alloc(</div>
+<div class="line"><a name="l05999"></a><span class="lineno"> 5999</span>&#160;        <span class="keyword">const</span> VmaAllocationRequest&amp; request,</div>
+<div class="line"><a name="l06000"></a><span class="lineno"> 6000</span>&#160;        VmaSuballocationType type,</div>
+<div class="line"><a name="l06001"></a><span class="lineno"> 6001</span>&#160;        VkDeviceSize allocSize,</div>
+<div class="line"><a name="l06002"></a><span class="lineno"> 6002</span>&#160;        <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAllocation);</div>
+<div class="line"><a name="l06003"></a><span class="lineno"> 6003</span>&#160; </div>
+<div class="line"><a name="l06004"></a><span class="lineno"> 6004</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">void</span> Free(<span class="keyword">const</span> <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation);</div>
+<div class="line"><a name="l06005"></a><span class="lineno"> 6005</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">void</span> FreeAtOffset(VkDeviceSize offset);</div>
+<div class="line"><a name="l06006"></a><span class="lineno"> 6006</span>&#160; </div>
+<div class="line"><a name="l06008"></a><span class="lineno"> 6008</span>&#160;    <span class="comment">// For defragmentation</span></div>
+<div class="line"><a name="l06009"></a><span class="lineno"> 6009</span>&#160;    </div>
+<div class="line"><a name="l06010"></a><span class="lineno"> 6010</span>&#160;    <span class="keywordtype">bool</span> IsBufferImageGranularityConflictPossible(</div>
+<div class="line"><a name="l06011"></a><span class="lineno"> 6011</span>&#160;        VkDeviceSize bufferImageGranularity,</div>
+<div class="line"><a name="l06012"></a><span class="lineno"> 6012</span>&#160;        VmaSuballocationType&amp; inOutPrevSuballocType) <span class="keyword">const</span>;</div>
+<div class="line"><a name="l06013"></a><span class="lineno"> 6013</span>&#160; </div>
+<div class="line"><a name="l06014"></a><span class="lineno"> 6014</span>&#160;<span class="keyword">private</span>:</div>
+<div class="line"><a name="l06015"></a><span class="lineno"> 6015</span>&#160;    <span class="keyword">friend</span> <span class="keyword">class </span>VmaDefragmentationAlgorithm_Generic;</div>
+<div class="line"><a name="l06016"></a><span class="lineno"> 6016</span>&#160;    <span class="keyword">friend</span> <span class="keyword">class </span>VmaDefragmentationAlgorithm_Fast;</div>
+<div class="line"><a name="l06017"></a><span class="lineno"> 6017</span>&#160; </div>
+<div class="line"><a name="l06018"></a><span class="lineno"> 6018</span>&#160;    uint32_t m_FreeCount;</div>
+<div class="line"><a name="l06019"></a><span class="lineno"> 6019</span>&#160;    VkDeviceSize m_SumFreeSize;</div>
+<div class="line"><a name="l06020"></a><span class="lineno"> 6020</span>&#160;    VmaSuballocationList m_Suballocations;</div>
+<div class="line"><a name="l06021"></a><span class="lineno"> 6021</span>&#160;    <span class="comment">// Suballocations that are free and have size greater than certain threshold.</span></div>
+<div class="line"><a name="l06022"></a><span class="lineno"> 6022</span>&#160;    <span class="comment">// Sorted by size, ascending.</span></div>
+<div class="line"><a name="l06023"></a><span class="lineno"> 6023</span>&#160;    VmaVector&lt; VmaSuballocationList::iterator, VmaStlAllocator&lt; VmaSuballocationList::iterator &gt; &gt; m_FreeSuballocationsBySize;</div>
+<div class="line"><a name="l06024"></a><span class="lineno"> 6024</span>&#160; </div>
+<div class="line"><a name="l06025"></a><span class="lineno"> 6025</span>&#160;    <span class="keywordtype">bool</span> ValidateFreeSuballocationList() <span class="keyword">const</span>;</div>
+<div class="line"><a name="l06026"></a><span class="lineno"> 6026</span>&#160; </div>
+<div class="line"><a name="l06027"></a><span class="lineno"> 6027</span>&#160;    <span class="comment">// Checks if requested suballocation with given parameters can be placed in given pFreeSuballocItem.</span></div>
+<div class="line"><a name="l06028"></a><span class="lineno"> 6028</span>&#160;    <span class="comment">// If yes, fills pOffset and returns true. If no, returns false.</span></div>
+<div class="line"><a name="l06029"></a><span class="lineno"> 6029</span>&#160;    <span class="keywordtype">bool</span> CheckAllocation(</div>
+<div class="line"><a name="l06030"></a><span class="lineno"> 6030</span>&#160;        uint32_t currentFrameIndex,</div>
+<div class="line"><a name="l06031"></a><span class="lineno"> 6031</span>&#160;        uint32_t frameInUseCount,</div>
+<div class="line"><a name="l06032"></a><span class="lineno"> 6032</span>&#160;        VkDeviceSize bufferImageGranularity,</div>
+<div class="line"><a name="l06033"></a><span class="lineno"> 6033</span>&#160;        VkDeviceSize allocSize,</div>
+<div class="line"><a name="l06034"></a><span class="lineno"> 6034</span>&#160;        VkDeviceSize allocAlignment,</div>
+<div class="line"><a name="l06035"></a><span class="lineno"> 6035</span>&#160;        VmaSuballocationType allocType,</div>
+<div class="line"><a name="l06036"></a><span class="lineno"> 6036</span>&#160;        VmaSuballocationList::const_iterator suballocItem,</div>
+<div class="line"><a name="l06037"></a><span class="lineno"> 6037</span>&#160;        <span class="keywordtype">bool</span> canMakeOtherLost,</div>
+<div class="line"><a name="l06038"></a><span class="lineno"> 6038</span>&#160;        VkDeviceSize* pOffset,</div>
+<div class="line"><a name="l06039"></a><span class="lineno"> 6039</span>&#160;        <span class="keywordtype">size_t</span>* itemsToMakeLostCount,</div>
+<div class="line"><a name="l06040"></a><span class="lineno"> 6040</span>&#160;        VkDeviceSize* pSumFreeSize,</div>
+<div class="line"><a name="l06041"></a><span class="lineno"> 6041</span>&#160;        VkDeviceSize* pSumItemSize) <span class="keyword">const</span>;</div>
+<div class="line"><a name="l06042"></a><span class="lineno"> 6042</span>&#160;    <span class="comment">// Given free suballocation, it merges it with following one, which must also be free.</span></div>
+<div class="line"><a name="l06043"></a><span class="lineno"> 6043</span>&#160;    <span class="keywordtype">void</span> MergeFreeWithNext(VmaSuballocationList::iterator item);</div>
+<div class="line"><a name="l06044"></a><span class="lineno"> 6044</span>&#160;    <span class="comment">// Releases given suballocation, making it free.</span></div>
+<div class="line"><a name="l06045"></a><span class="lineno"> 6045</span>&#160;    <span class="comment">// Merges it with adjacent free suballocations if applicable.</span></div>
+<div class="line"><a name="l06046"></a><span class="lineno"> 6046</span>&#160;    <span class="comment">// Returns iterator to new free suballocation at this place.</span></div>
+<div class="line"><a name="l06047"></a><span class="lineno"> 6047</span>&#160;    VmaSuballocationList::iterator FreeSuballocation(VmaSuballocationList::iterator suballocItem);</div>
+<div class="line"><a name="l06048"></a><span class="lineno"> 6048</span>&#160;    <span class="comment">// Given free suballocation, it inserts it into sorted list of</span></div>
+<div class="line"><a name="l06049"></a><span class="lineno"> 6049</span>&#160;    <span class="comment">// m_FreeSuballocationsBySize if it&#39;s suitable.</span></div>
+<div class="line"><a name="l06050"></a><span class="lineno"> 6050</span>&#160;    <span class="keywordtype">void</span> RegisterFreeSuballocation(VmaSuballocationList::iterator item);</div>
+<div class="line"><a name="l06051"></a><span class="lineno"> 6051</span>&#160;    <span class="comment">// Given free suballocation, it removes it from sorted list of</span></div>
+<div class="line"><a name="l06052"></a><span class="lineno"> 6052</span>&#160;    <span class="comment">// m_FreeSuballocationsBySize if it&#39;s suitable.</span></div>
+<div class="line"><a name="l06053"></a><span class="lineno"> 6053</span>&#160;    <span class="keywordtype">void</span> UnregisterFreeSuballocation(VmaSuballocationList::iterator item);</div>
+<div class="line"><a name="l06054"></a><span class="lineno"> 6054</span>&#160;};</div>
+<div class="line"><a name="l06055"></a><span class="lineno"> 6055</span>&#160; </div>
+<div class="line"><a name="l06056"></a><span class="lineno"> 6056</span>&#160;<span class="comment">/*</span></div>
+<div class="line"><a name="l06057"></a><span class="lineno"> 6057</span>&#160;<span class="comment">Allocations and their references in internal data structure look like this:</span></div>
+<div class="line"><a name="l06058"></a><span class="lineno"> 6058</span>&#160;<span class="comment"></span> </div>
+<div class="line"><a name="l06059"></a><span class="lineno"> 6059</span>&#160;<span class="comment">if(m_2ndVectorMode == SECOND_VECTOR_EMPTY):</span></div>
+<div class="line"><a name="l06060"></a><span class="lineno"> 6060</span>&#160;<span class="comment"></span> </div>
+<div class="line"><a name="l06061"></a><span class="lineno"> 6061</span>&#160;<span class="comment">        0 +-------+</span></div>
+<div class="line"><a name="l06062"></a><span class="lineno"> 6062</span>&#160;<span class="comment">          |       |</span></div>
+<div class="line"><a name="l06063"></a><span class="lineno"> 6063</span>&#160;<span class="comment">          |       |</span></div>
+<div class="line"><a name="l06064"></a><span class="lineno"> 6064</span>&#160;<span class="comment">          |       |</span></div>
+<div class="line"><a name="l06065"></a><span class="lineno"> 6065</span>&#160;<span class="comment">          +-------+</span></div>
+<div class="line"><a name="l06066"></a><span class="lineno"> 6066</span>&#160;<span class="comment">          | Alloc |  1st[m_1stNullItemsBeginCount]</span></div>
+<div class="line"><a name="l06067"></a><span class="lineno"> 6067</span>&#160;<span class="comment">          +-------+</span></div>
+<div class="line"><a name="l06068"></a><span class="lineno"> 6068</span>&#160;<span class="comment">          | Alloc |  1st[m_1stNullItemsBeginCount + 1]</span></div>
+<div class="line"><a name="l06069"></a><span class="lineno"> 6069</span>&#160;<span class="comment">          +-------+</span></div>
+<div class="line"><a name="l06070"></a><span class="lineno"> 6070</span>&#160;<span class="comment">          |  ...  |</span></div>
+<div class="line"><a name="l06071"></a><span class="lineno"> 6071</span>&#160;<span class="comment">          +-------+</span></div>
+<div class="line"><a name="l06072"></a><span class="lineno"> 6072</span>&#160;<span class="comment">          | Alloc |  1st[1st.size() - 1]</span></div>
+<div class="line"><a name="l06073"></a><span class="lineno"> 6073</span>&#160;<span class="comment">          +-------+</span></div>
+<div class="line"><a name="l06074"></a><span class="lineno"> 6074</span>&#160;<span class="comment">          |       |</span></div>
+<div class="line"><a name="l06075"></a><span class="lineno"> 6075</span>&#160;<span class="comment">          |       |</span></div>
+<div class="line"><a name="l06076"></a><span class="lineno"> 6076</span>&#160;<span class="comment">          |       |</span></div>
+<div class="line"><a name="l06077"></a><span class="lineno"> 6077</span>&#160;<span class="comment">GetSize() +-------+</span></div>
+<div class="line"><a name="l06078"></a><span class="lineno"> 6078</span>&#160;<span class="comment"></span> </div>
+<div class="line"><a name="l06079"></a><span class="lineno"> 6079</span>&#160;<span class="comment">if(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER):</span></div>
+<div class="line"><a name="l06080"></a><span class="lineno"> 6080</span>&#160;<span class="comment"></span> </div>
+<div class="line"><a name="l06081"></a><span class="lineno"> 6081</span>&#160;<span class="comment">        0 +-------+</span></div>
+<div class="line"><a name="l06082"></a><span class="lineno"> 6082</span>&#160;<span class="comment">          | Alloc |  2nd[0]</span></div>
+<div class="line"><a name="l06083"></a><span class="lineno"> 6083</span>&#160;<span class="comment">          +-------+</span></div>
+<div class="line"><a name="l06084"></a><span class="lineno"> 6084</span>&#160;<span class="comment">          | Alloc |  2nd[1]</span></div>
+<div class="line"><a name="l06085"></a><span class="lineno"> 6085</span>&#160;<span class="comment">          +-------+</span></div>
+<div class="line"><a name="l06086"></a><span class="lineno"> 6086</span>&#160;<span class="comment">          |  ...  |</span></div>
+<div class="line"><a name="l06087"></a><span class="lineno"> 6087</span>&#160;<span class="comment">          +-------+</span></div>
+<div class="line"><a name="l06088"></a><span class="lineno"> 6088</span>&#160;<span class="comment">          | Alloc |  2nd[2nd.size() - 1]</span></div>
+<div class="line"><a name="l06089"></a><span class="lineno"> 6089</span>&#160;<span class="comment">          +-------+</span></div>
+<div class="line"><a name="l06090"></a><span class="lineno"> 6090</span>&#160;<span class="comment">          |       |</span></div>
+<div class="line"><a name="l06091"></a><span class="lineno"> 6091</span>&#160;<span class="comment">          |       |</span></div>
+<div class="line"><a name="l06092"></a><span class="lineno"> 6092</span>&#160;<span class="comment">          |       |</span></div>
+<div class="line"><a name="l06093"></a><span class="lineno"> 6093</span>&#160;<span class="comment">          +-------+</span></div>
+<div class="line"><a name="l06094"></a><span class="lineno"> 6094</span>&#160;<span class="comment">          | Alloc |  1st[m_1stNullItemsBeginCount]</span></div>
+<div class="line"><a name="l06095"></a><span class="lineno"> 6095</span>&#160;<span class="comment">          +-------+</span></div>
+<div class="line"><a name="l06096"></a><span class="lineno"> 6096</span>&#160;<span class="comment">          | Alloc |  1st[m_1stNullItemsBeginCount + 1]</span></div>
+<div class="line"><a name="l06097"></a><span class="lineno"> 6097</span>&#160;<span class="comment">          +-------+</span></div>
+<div class="line"><a name="l06098"></a><span class="lineno"> 6098</span>&#160;<span class="comment">          |  ...  |</span></div>
+<div class="line"><a name="l06099"></a><span class="lineno"> 6099</span>&#160;<span class="comment">          +-------+</span></div>
+<div class="line"><a name="l06100"></a><span class="lineno"> 6100</span>&#160;<span class="comment">          | Alloc |  1st[1st.size() - 1]</span></div>
+<div class="line"><a name="l06101"></a><span class="lineno"> 6101</span>&#160;<span class="comment">          +-------+</span></div>
+<div class="line"><a name="l06102"></a><span class="lineno"> 6102</span>&#160;<span class="comment">          |       |</span></div>
+<div class="line"><a name="l06103"></a><span class="lineno"> 6103</span>&#160;<span class="comment">GetSize() +-------+</span></div>
+<div class="line"><a name="l06104"></a><span class="lineno"> 6104</span>&#160;<span class="comment"></span> </div>
+<div class="line"><a name="l06105"></a><span class="lineno"> 6105</span>&#160;<span class="comment">if(m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK):</span></div>
+<div class="line"><a name="l06106"></a><span class="lineno"> 6106</span>&#160;<span class="comment"></span> </div>
+<div class="line"><a name="l06107"></a><span class="lineno"> 6107</span>&#160;<span class="comment">        0 +-------+</span></div>
+<div class="line"><a name="l06108"></a><span class="lineno"> 6108</span>&#160;<span class="comment">          |       |</span></div>
+<div class="line"><a name="l06109"></a><span class="lineno"> 6109</span>&#160;<span class="comment">          |       |</span></div>
+<div class="line"><a name="l06110"></a><span class="lineno"> 6110</span>&#160;<span class="comment">          |       |</span></div>
+<div class="line"><a name="l06111"></a><span class="lineno"> 6111</span>&#160;<span class="comment">          +-------+</span></div>
+<div class="line"><a name="l06112"></a><span class="lineno"> 6112</span>&#160;<span class="comment">          | Alloc |  1st[m_1stNullItemsBeginCount]</span></div>
+<div class="line"><a name="l06113"></a><span class="lineno"> 6113</span>&#160;<span class="comment">          +-------+</span></div>
+<div class="line"><a name="l06114"></a><span class="lineno"> 6114</span>&#160;<span class="comment">          | Alloc |  1st[m_1stNullItemsBeginCount + 1]</span></div>
+<div class="line"><a name="l06115"></a><span class="lineno"> 6115</span>&#160;<span class="comment">          +-------+</span></div>
+<div class="line"><a name="l06116"></a><span class="lineno"> 6116</span>&#160;<span class="comment">          |  ...  |</span></div>
+<div class="line"><a name="l06117"></a><span class="lineno"> 6117</span>&#160;<span class="comment">          +-------+</span></div>
+<div class="line"><a name="l06118"></a><span class="lineno"> 6118</span>&#160;<span class="comment">          | Alloc |  1st[1st.size() - 1]</span></div>
+<div class="line"><a name="l06119"></a><span class="lineno"> 6119</span>&#160;<span class="comment">          +-------+</span></div>
+<div class="line"><a name="l06120"></a><span class="lineno"> 6120</span>&#160;<span class="comment">          |       |</span></div>
+<div class="line"><a name="l06121"></a><span class="lineno"> 6121</span>&#160;<span class="comment">          |       |</span></div>
+<div class="line"><a name="l06122"></a><span class="lineno"> 6122</span>&#160;<span class="comment">          |       |</span></div>
+<div class="line"><a name="l06123"></a><span class="lineno"> 6123</span>&#160;<span class="comment">          +-------+</span></div>
+<div class="line"><a name="l06124"></a><span class="lineno"> 6124</span>&#160;<span class="comment">          | Alloc |  2nd[2nd.size() - 1]</span></div>
+<div class="line"><a name="l06125"></a><span class="lineno"> 6125</span>&#160;<span class="comment">          +-------+</span></div>
+<div class="line"><a name="l06126"></a><span class="lineno"> 6126</span>&#160;<span class="comment">          |  ...  |</span></div>
+<div class="line"><a name="l06127"></a><span class="lineno"> 6127</span>&#160;<span class="comment">          +-------+</span></div>
+<div class="line"><a name="l06128"></a><span class="lineno"> 6128</span>&#160;<span class="comment">          | Alloc |  2nd[1]</span></div>
+<div class="line"><a name="l06129"></a><span class="lineno"> 6129</span>&#160;<span class="comment">          +-------+</span></div>
+<div class="line"><a name="l06130"></a><span class="lineno"> 6130</span>&#160;<span class="comment">          | Alloc |  2nd[0]</span></div>
+<div class="line"><a name="l06131"></a><span class="lineno"> 6131</span>&#160;<span class="comment">GetSize() +-------+</span></div>
+<div class="line"><a name="l06132"></a><span class="lineno"> 6132</span>&#160;<span class="comment"></span> </div>
+<div class="line"><a name="l06133"></a><span class="lineno"> 6133</span>&#160;<span class="comment">*/</span></div>
+<div class="line"><a name="l06134"></a><span class="lineno"> 6134</span>&#160;<span class="keyword">class </span>VmaBlockMetadata_Linear : <span class="keyword">public</span> VmaBlockMetadata</div>
+<div class="line"><a name="l06135"></a><span class="lineno"> 6135</span>&#160;{</div>
+<div class="line"><a name="l06136"></a><span class="lineno"> 6136</span>&#160;    VMA_CLASS_NO_COPY(VmaBlockMetadata_Linear)</div>
+<div class="line"><a name="l06137"></a><span class="lineno"> 6137</span>&#160;<span class="keyword">public</span>:</div>
+<div class="line"><a name="l06138"></a><span class="lineno"> 6138</span>&#160;    VmaBlockMetadata_Linear(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator);</div>
+<div class="line"><a name="l06139"></a><span class="lineno"> 6139</span>&#160;    <span class="keyword">virtual</span> ~VmaBlockMetadata_Linear();</div>
+<div class="line"><a name="l06140"></a><span class="lineno"> 6140</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">void</span> Init(VkDeviceSize size);</div>
+<div class="line"><a name="l06141"></a><span class="lineno"> 6141</span>&#160; </div>
+<div class="line"><a name="l06142"></a><span class="lineno"> 6142</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">bool</span> Validate() <span class="keyword">const</span>;</div>
+<div class="line"><a name="l06143"></a><span class="lineno"> 6143</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">size_t</span> GetAllocationCount() <span class="keyword">const</span>;</div>
+<div class="line"><a name="l06144"></a><span class="lineno"> 6144</span>&#160;    <span class="keyword">virtual</span> VkDeviceSize GetSumFreeSize()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_SumFreeSize; }</div>
+<div class="line"><a name="l06145"></a><span class="lineno"> 6145</span>&#160;    <span class="keyword">virtual</span> VkDeviceSize GetUnusedRangeSizeMax() <span class="keyword">const</span>;</div>
+<div class="line"><a name="l06146"></a><span class="lineno"> 6146</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">bool</span> IsEmpty()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> GetAllocationCount() == 0; }</div>
+<div class="line"><a name="l06147"></a><span class="lineno"> 6147</span>&#160; </div>
+<div class="line"><a name="l06148"></a><span class="lineno"> 6148</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">void</span> CalcAllocationStatInfo(<a class="code" href="struct_vma_stat_info.html">VmaStatInfo</a>&amp; outInfo) <span class="keyword">const</span>;</div>
+<div class="line"><a name="l06149"></a><span class="lineno"> 6149</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">void</span> AddPoolStats(<a class="code" href="struct_vma_pool_stats.html">VmaPoolStats</a>&amp; inoutStats) <span class="keyword">const</span>;</div>
+<div class="line"><a name="l06150"></a><span class="lineno"> 6150</span>&#160; </div>
+<div class="line"><a name="l06151"></a><span class="lineno"> 6151</span>&#160;<span class="preprocessor">#if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l06152"></a><span class="lineno"> 6152</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">void</span> PrintDetailedMap(<span class="keyword">class</span> VmaJsonWriter&amp; json) <span class="keyword">const</span>;</div>
+<div class="line"><a name="l06153"></a><span class="lineno"> 6153</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l06154"></a><span class="lineno"> 6154</span>&#160; </div>
+<div class="line"><a name="l06155"></a><span class="lineno"> 6155</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">bool</span> CreateAllocationRequest(</div>
+<div class="line"><a name="l06156"></a><span class="lineno"> 6156</span>&#160;        uint32_t currentFrameIndex,</div>
+<div class="line"><a name="l06157"></a><span class="lineno"> 6157</span>&#160;        uint32_t frameInUseCount,</div>
+<div class="line"><a name="l06158"></a><span class="lineno"> 6158</span>&#160;        VkDeviceSize bufferImageGranularity,</div>
+<div class="line"><a name="l06159"></a><span class="lineno"> 6159</span>&#160;        VkDeviceSize allocSize,</div>
+<div class="line"><a name="l06160"></a><span class="lineno"> 6160</span>&#160;        VkDeviceSize allocAlignment,</div>
+<div class="line"><a name="l06161"></a><span class="lineno"> 6161</span>&#160;        <span class="keywordtype">bool</span> upperAddress,</div>
+<div class="line"><a name="l06162"></a><span class="lineno"> 6162</span>&#160;        VmaSuballocationType allocType,</div>
+<div class="line"><a name="l06163"></a><span class="lineno"> 6163</span>&#160;        <span class="keywordtype">bool</span> canMakeOtherLost,</div>
+<div class="line"><a name="l06164"></a><span class="lineno"> 6164</span>&#160;        uint32_t strategy,</div>
+<div class="line"><a name="l06165"></a><span class="lineno"> 6165</span>&#160;        VmaAllocationRequest* pAllocationRequest);</div>
+<div class="line"><a name="l06166"></a><span class="lineno"> 6166</span>&#160; </div>
+<div class="line"><a name="l06167"></a><span class="lineno"> 6167</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">bool</span> MakeRequestedAllocationsLost(</div>
+<div class="line"><a name="l06168"></a><span class="lineno"> 6168</span>&#160;        uint32_t currentFrameIndex,</div>
+<div class="line"><a name="l06169"></a><span class="lineno"> 6169</span>&#160;        uint32_t frameInUseCount,</div>
+<div class="line"><a name="l06170"></a><span class="lineno"> 6170</span>&#160;        VmaAllocationRequest* pAllocationRequest);</div>
+<div class="line"><a name="l06171"></a><span class="lineno"> 6171</span>&#160; </div>
+<div class="line"><a name="l06172"></a><span class="lineno"> 6172</span>&#160;    <span class="keyword">virtual</span> uint32_t MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount);</div>
+<div class="line"><a name="l06173"></a><span class="lineno"> 6173</span>&#160; </div>
+<div class="line"><a name="l06174"></a><span class="lineno"> 6174</span>&#160;    <span class="keyword">virtual</span> VkResult CheckCorruption(<span class="keyword">const</span> <span class="keywordtype">void</span>* pBlockData);</div>
+<div class="line"><a name="l06175"></a><span class="lineno"> 6175</span>&#160; </div>
+<div class="line"><a name="l06176"></a><span class="lineno"> 6176</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">void</span> Alloc(</div>
+<div class="line"><a name="l06177"></a><span class="lineno"> 6177</span>&#160;        <span class="keyword">const</span> VmaAllocationRequest&amp; request,</div>
+<div class="line"><a name="l06178"></a><span class="lineno"> 6178</span>&#160;        VmaSuballocationType type,</div>
+<div class="line"><a name="l06179"></a><span class="lineno"> 6179</span>&#160;        VkDeviceSize allocSize,</div>
+<div class="line"><a name="l06180"></a><span class="lineno"> 6180</span>&#160;        <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAllocation);</div>
+<div class="line"><a name="l06181"></a><span class="lineno"> 6181</span>&#160; </div>
+<div class="line"><a name="l06182"></a><span class="lineno"> 6182</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">void</span> Free(<span class="keyword">const</span> <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation);</div>
+<div class="line"><a name="l06183"></a><span class="lineno"> 6183</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">void</span> FreeAtOffset(VkDeviceSize offset);</div>
+<div class="line"><a name="l06184"></a><span class="lineno"> 6184</span>&#160; </div>
+<div class="line"><a name="l06185"></a><span class="lineno"> 6185</span>&#160;<span class="keyword">private</span>:</div>
+<div class="line"><a name="l06186"></a><span class="lineno"> 6186</span>&#160;    <span class="comment">/*</span></div>
+<div class="line"><a name="l06187"></a><span class="lineno"> 6187</span>&#160;<span class="comment">    There are two suballocation vectors, used in ping-pong way.</span></div>
+<div class="line"><a name="l06188"></a><span class="lineno"> 6188</span>&#160;<span class="comment">    The one with index m_1stVectorIndex is called 1st.</span></div>
+<div class="line"><a name="l06189"></a><span class="lineno"> 6189</span>&#160;<span class="comment">    The one with index (m_1stVectorIndex ^ 1) is called 2nd.</span></div>
+<div class="line"><a name="l06190"></a><span class="lineno"> 6190</span>&#160;<span class="comment">    2nd can be non-empty only when 1st is not empty.</span></div>
+<div class="line"><a name="l06191"></a><span class="lineno"> 6191</span>&#160;<span class="comment">    When 2nd is not empty, m_2ndVectorMode indicates its mode of operation.</span></div>
+<div class="line"><a name="l06192"></a><span class="lineno"> 6192</span>&#160;<span class="comment">    */</span></div>
+<div class="line"><a name="l06193"></a><span class="lineno"> 6193</span>&#160;    <span class="keyword">typedef</span> VmaVector&lt; VmaSuballocation, VmaStlAllocator&lt;VmaSuballocation&gt; &gt; SuballocationVectorType;</div>
+<div class="line"><a name="l06194"></a><span class="lineno"> 6194</span>&#160; </div>
+<div class="line"><a name="l06195"></a><span class="lineno"> 6195</span>&#160;    <span class="keyword">enum</span> SECOND_VECTOR_MODE</div>
+<div class="line"><a name="l06196"></a><span class="lineno"> 6196</span>&#160;    {</div>
+<div class="line"><a name="l06197"></a><span class="lineno"> 6197</span>&#160;        SECOND_VECTOR_EMPTY,</div>
+<div class="line"><a name="l06198"></a><span class="lineno"> 6198</span>&#160;        <span class="comment">/*</span></div>
+<div class="line"><a name="l06199"></a><span class="lineno"> 6199</span>&#160;<span class="comment">        Suballocations in 2nd vector are created later than the ones in 1st, but they</span></div>
+<div class="line"><a name="l06200"></a><span class="lineno"> 6200</span>&#160;<span class="comment">        all have smaller offset.</span></div>
+<div class="line"><a name="l06201"></a><span class="lineno"> 6201</span>&#160;<span class="comment">        */</span></div>
+<div class="line"><a name="l06202"></a><span class="lineno"> 6202</span>&#160;        SECOND_VECTOR_RING_BUFFER,</div>
+<div class="line"><a name="l06203"></a><span class="lineno"> 6203</span>&#160;        <span class="comment">/*</span></div>
+<div class="line"><a name="l06204"></a><span class="lineno"> 6204</span>&#160;<span class="comment">        Suballocations in 2nd vector are upper side of double stack.</span></div>
+<div class="line"><a name="l06205"></a><span class="lineno"> 6205</span>&#160;<span class="comment">        They all have offsets higher than those in 1st vector.</span></div>
+<div class="line"><a name="l06206"></a><span class="lineno"> 6206</span>&#160;<span class="comment">        Top of this stack means smaller offsets, but higher indices in this vector.</span></div>
+<div class="line"><a name="l06207"></a><span class="lineno"> 6207</span>&#160;<span class="comment">        */</span></div>
+<div class="line"><a name="l06208"></a><span class="lineno"> 6208</span>&#160;        SECOND_VECTOR_DOUBLE_STACK,</div>
+<div class="line"><a name="l06209"></a><span class="lineno"> 6209</span>&#160;    };</div>
+<div class="line"><a name="l06210"></a><span class="lineno"> 6210</span>&#160; </div>
+<div class="line"><a name="l06211"></a><span class="lineno"> 6211</span>&#160;    VkDeviceSize m_SumFreeSize;</div>
+<div class="line"><a name="l06212"></a><span class="lineno"> 6212</span>&#160;    SuballocationVectorType m_Suballocations0, m_Suballocations1;</div>
+<div class="line"><a name="l06213"></a><span class="lineno"> 6213</span>&#160;    uint32_t m_1stVectorIndex;</div>
+<div class="line"><a name="l06214"></a><span class="lineno"> 6214</span>&#160;    SECOND_VECTOR_MODE m_2ndVectorMode;</div>
+<div class="line"><a name="l06215"></a><span class="lineno"> 6215</span>&#160; </div>
+<div class="line"><a name="l06216"></a><span class="lineno"> 6216</span>&#160;    SuballocationVectorType&amp; AccessSuballocations1st() { <span class="keywordflow">return</span> m_1stVectorIndex ? m_Suballocations1 : m_Suballocations0; }</div>
+<div class="line"><a name="l06217"></a><span class="lineno"> 6217</span>&#160;    SuballocationVectorType&amp; AccessSuballocations2nd() { <span class="keywordflow">return</span> m_1stVectorIndex ? m_Suballocations0 : m_Suballocations1; }</div>
+<div class="line"><a name="l06218"></a><span class="lineno"> 6218</span>&#160;    <span class="keyword">const</span> SuballocationVectorType&amp; AccessSuballocations1st()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_1stVectorIndex ? m_Suballocations1 : m_Suballocations0; }</div>
+<div class="line"><a name="l06219"></a><span class="lineno"> 6219</span>&#160;    <span class="keyword">const</span> SuballocationVectorType&amp; AccessSuballocations2nd()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_1stVectorIndex ? m_Suballocations0 : m_Suballocations1; }</div>
+<div class="line"><a name="l06220"></a><span class="lineno"> 6220</span>&#160;    </div>
+<div class="line"><a name="l06221"></a><span class="lineno"> 6221</span>&#160;    <span class="comment">// Number of items in 1st vector with hAllocation = null at the beginning.</span></div>
+<div class="line"><a name="l06222"></a><span class="lineno"> 6222</span>&#160;    <span class="keywordtype">size_t</span> m_1stNullItemsBeginCount;</div>
+<div class="line"><a name="l06223"></a><span class="lineno"> 6223</span>&#160;    <span class="comment">// Number of other items in 1st vector with hAllocation = null somewhere in the middle.</span></div>
+<div class="line"><a name="l06224"></a><span class="lineno"> 6224</span>&#160;    <span class="keywordtype">size_t</span> m_1stNullItemsMiddleCount;</div>
+<div class="line"><a name="l06225"></a><span class="lineno"> 6225</span>&#160;    <span class="comment">// Number of items in 2nd vector with hAllocation = null.</span></div>
+<div class="line"><a name="l06226"></a><span class="lineno"> 6226</span>&#160;    <span class="keywordtype">size_t</span> m_2ndNullItemsCount;</div>
+<div class="line"><a name="l06227"></a><span class="lineno"> 6227</span>&#160; </div>
+<div class="line"><a name="l06228"></a><span class="lineno"> 6228</span>&#160;    <span class="keywordtype">bool</span> ShouldCompact1st() <span class="keyword">const</span>;</div>
+<div class="line"><a name="l06229"></a><span class="lineno"> 6229</span>&#160;    <span class="keywordtype">void</span> CleanupAfterFree();</div>
+<div class="line"><a name="l06230"></a><span class="lineno"> 6230</span>&#160; </div>
+<div class="line"><a name="l06231"></a><span class="lineno"> 6231</span>&#160;    <span class="keywordtype">bool</span> CreateAllocationRequest_LowerAddress(</div>
+<div class="line"><a name="l06232"></a><span class="lineno"> 6232</span>&#160;        uint32_t currentFrameIndex,</div>
+<div class="line"><a name="l06233"></a><span class="lineno"> 6233</span>&#160;        uint32_t frameInUseCount,</div>
+<div class="line"><a name="l06234"></a><span class="lineno"> 6234</span>&#160;        VkDeviceSize bufferImageGranularity,</div>
+<div class="line"><a name="l06235"></a><span class="lineno"> 6235</span>&#160;        VkDeviceSize allocSize,</div>
+<div class="line"><a name="l06236"></a><span class="lineno"> 6236</span>&#160;        VkDeviceSize allocAlignment,</div>
+<div class="line"><a name="l06237"></a><span class="lineno"> 6237</span>&#160;        VmaSuballocationType allocType,</div>
+<div class="line"><a name="l06238"></a><span class="lineno"> 6238</span>&#160;        <span class="keywordtype">bool</span> canMakeOtherLost,</div>
+<div class="line"><a name="l06239"></a><span class="lineno"> 6239</span>&#160;        uint32_t strategy,</div>
+<div class="line"><a name="l06240"></a><span class="lineno"> 6240</span>&#160;        VmaAllocationRequest* pAllocationRequest);</div>
+<div class="line"><a name="l06241"></a><span class="lineno"> 6241</span>&#160;    <span class="keywordtype">bool</span> CreateAllocationRequest_UpperAddress(</div>
+<div class="line"><a name="l06242"></a><span class="lineno"> 6242</span>&#160;        uint32_t currentFrameIndex,</div>
+<div class="line"><a name="l06243"></a><span class="lineno"> 6243</span>&#160;        uint32_t frameInUseCount,</div>
+<div class="line"><a name="l06244"></a><span class="lineno"> 6244</span>&#160;        VkDeviceSize bufferImageGranularity,</div>
+<div class="line"><a name="l06245"></a><span class="lineno"> 6245</span>&#160;        VkDeviceSize allocSize,</div>
+<div class="line"><a name="l06246"></a><span class="lineno"> 6246</span>&#160;        VkDeviceSize allocAlignment,</div>
+<div class="line"><a name="l06247"></a><span class="lineno"> 6247</span>&#160;        VmaSuballocationType allocType,</div>
+<div class="line"><a name="l06248"></a><span class="lineno"> 6248</span>&#160;        <span class="keywordtype">bool</span> canMakeOtherLost,</div>
+<div class="line"><a name="l06249"></a><span class="lineno"> 6249</span>&#160;        uint32_t strategy,</div>
+<div class="line"><a name="l06250"></a><span class="lineno"> 6250</span>&#160;        VmaAllocationRequest* pAllocationRequest);</div>
+<div class="line"><a name="l06251"></a><span class="lineno"> 6251</span>&#160;};</div>
+<div class="line"><a name="l06252"></a><span class="lineno"> 6252</span>&#160; </div>
+<div class="line"><a name="l06253"></a><span class="lineno"> 6253</span>&#160;<span class="comment">/*</span></div>
+<div class="line"><a name="l06254"></a><span class="lineno"> 6254</span>&#160;<span class="comment">- GetSize() is the original size of allocated memory block.</span></div>
+<div class="line"><a name="l06255"></a><span class="lineno"> 6255</span>&#160;<span class="comment">- m_UsableSize is this size aligned down to a power of two.</span></div>
+<div class="line"><a name="l06256"></a><span class="lineno"> 6256</span>&#160;<span class="comment">  All allocations and calculations happen relative to m_UsableSize.</span></div>
+<div class="line"><a name="l06257"></a><span class="lineno"> 6257</span>&#160;<span class="comment">- GetUnusableSize() is the difference between them.</span></div>
+<div class="line"><a name="l06258"></a><span class="lineno"> 6258</span>&#160;<span class="comment">  It is repoted as separate, unused range, not available for allocations.</span></div>
+<div class="line"><a name="l06259"></a><span class="lineno"> 6259</span>&#160;<span class="comment"></span> </div>
+<div class="line"><a name="l06260"></a><span class="lineno"> 6260</span>&#160;<span class="comment">Node at level 0 has size = m_UsableSize.</span></div>
+<div class="line"><a name="l06261"></a><span class="lineno"> 6261</span>&#160;<span class="comment">Each next level contains nodes with size 2 times smaller than current level.</span></div>
+<div class="line"><a name="l06262"></a><span class="lineno"> 6262</span>&#160;<span class="comment">m_LevelCount is the maximum number of levels to use in the current object.</span></div>
+<div class="line"><a name="l06263"></a><span class="lineno"> 6263</span>&#160;<span class="comment">*/</span></div>
+<div class="line"><a name="l06264"></a><span class="lineno"> 6264</span>&#160;<span class="keyword">class </span>VmaBlockMetadata_Buddy : <span class="keyword">public</span> VmaBlockMetadata</div>
+<div class="line"><a name="l06265"></a><span class="lineno"> 6265</span>&#160;{</div>
+<div class="line"><a name="l06266"></a><span class="lineno"> 6266</span>&#160;    VMA_CLASS_NO_COPY(VmaBlockMetadata_Buddy)</div>
+<div class="line"><a name="l06267"></a><span class="lineno"> 6267</span>&#160;<span class="keyword">public</span>:</div>
+<div class="line"><a name="l06268"></a><span class="lineno"> 6268</span>&#160;    VmaBlockMetadata_Buddy(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator);</div>
+<div class="line"><a name="l06269"></a><span class="lineno"> 6269</span>&#160;    <span class="keyword">virtual</span> ~VmaBlockMetadata_Buddy();</div>
+<div class="line"><a name="l06270"></a><span class="lineno"> 6270</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">void</span> Init(VkDeviceSize size);</div>
+<div class="line"><a name="l06271"></a><span class="lineno"> 6271</span>&#160; </div>
+<div class="line"><a name="l06272"></a><span class="lineno"> 6272</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">bool</span> Validate() <span class="keyword">const</span>;</div>
+<div class="line"><a name="l06273"></a><span class="lineno"> 6273</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">size_t</span> GetAllocationCount()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_AllocationCount; }</div>
+<div class="line"><a name="l06274"></a><span class="lineno"> 6274</span>&#160;    <span class="keyword">virtual</span> VkDeviceSize GetSumFreeSize()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_SumFreeSize + GetUnusableSize(); }</div>
+<div class="line"><a name="l06275"></a><span class="lineno"> 6275</span>&#160;    <span class="keyword">virtual</span> VkDeviceSize GetUnusedRangeSizeMax() <span class="keyword">const</span>;</div>
+<div class="line"><a name="l06276"></a><span class="lineno"> 6276</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">bool</span> IsEmpty()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_Root-&gt;type == Node::TYPE_FREE; }</div>
+<div class="line"><a name="l06277"></a><span class="lineno"> 6277</span>&#160; </div>
+<div class="line"><a name="l06278"></a><span class="lineno"> 6278</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">void</span> CalcAllocationStatInfo(<a class="code" href="struct_vma_stat_info.html">VmaStatInfo</a>&amp; outInfo) <span class="keyword">const</span>;</div>
+<div class="line"><a name="l06279"></a><span class="lineno"> 6279</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">void</span> AddPoolStats(<a class="code" href="struct_vma_pool_stats.html">VmaPoolStats</a>&amp; inoutStats) <span class="keyword">const</span>;</div>
+<div class="line"><a name="l06280"></a><span class="lineno"> 6280</span>&#160; </div>
+<div class="line"><a name="l06281"></a><span class="lineno"> 6281</span>&#160;<span class="preprocessor">#if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l06282"></a><span class="lineno"> 6282</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">void</span> PrintDetailedMap(<span class="keyword">class</span> VmaJsonWriter&amp; json) <span class="keyword">const</span>;</div>
+<div class="line"><a name="l06283"></a><span class="lineno"> 6283</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l06284"></a><span class="lineno"> 6284</span>&#160; </div>
+<div class="line"><a name="l06285"></a><span class="lineno"> 6285</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">bool</span> CreateAllocationRequest(</div>
+<div class="line"><a name="l06286"></a><span class="lineno"> 6286</span>&#160;        uint32_t currentFrameIndex,</div>
+<div class="line"><a name="l06287"></a><span class="lineno"> 6287</span>&#160;        uint32_t frameInUseCount,</div>
+<div class="line"><a name="l06288"></a><span class="lineno"> 6288</span>&#160;        VkDeviceSize bufferImageGranularity,</div>
+<div class="line"><a name="l06289"></a><span class="lineno"> 6289</span>&#160;        VkDeviceSize allocSize,</div>
+<div class="line"><a name="l06290"></a><span class="lineno"> 6290</span>&#160;        VkDeviceSize allocAlignment,</div>
+<div class="line"><a name="l06291"></a><span class="lineno"> 6291</span>&#160;        <span class="keywordtype">bool</span> upperAddress,</div>
+<div class="line"><a name="l06292"></a><span class="lineno"> 6292</span>&#160;        VmaSuballocationType allocType,</div>
+<div class="line"><a name="l06293"></a><span class="lineno"> 6293</span>&#160;        <span class="keywordtype">bool</span> canMakeOtherLost,</div>
+<div class="line"><a name="l06294"></a><span class="lineno"> 6294</span>&#160;        uint32_t strategy,</div>
+<div class="line"><a name="l06295"></a><span class="lineno"> 6295</span>&#160;        VmaAllocationRequest* pAllocationRequest);</div>
+<div class="line"><a name="l06296"></a><span class="lineno"> 6296</span>&#160; </div>
+<div class="line"><a name="l06297"></a><span class="lineno"> 6297</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">bool</span> MakeRequestedAllocationsLost(</div>
+<div class="line"><a name="l06298"></a><span class="lineno"> 6298</span>&#160;        uint32_t currentFrameIndex,</div>
+<div class="line"><a name="l06299"></a><span class="lineno"> 6299</span>&#160;        uint32_t frameInUseCount,</div>
+<div class="line"><a name="l06300"></a><span class="lineno"> 6300</span>&#160;        VmaAllocationRequest* pAllocationRequest);</div>
+<div class="line"><a name="l06301"></a><span class="lineno"> 6301</span>&#160; </div>
+<div class="line"><a name="l06302"></a><span class="lineno"> 6302</span>&#160;    <span class="keyword">virtual</span> uint32_t MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount);</div>
+<div class="line"><a name="l06303"></a><span class="lineno"> 6303</span>&#160; </div>
+<div class="line"><a name="l06304"></a><span class="lineno"> 6304</span>&#160;    <span class="keyword">virtual</span> VkResult CheckCorruption(<span class="keyword">const</span> <span class="keywordtype">void</span>* pBlockData) { <span class="keywordflow">return</span> VK_ERROR_FEATURE_NOT_PRESENT; }</div>
+<div class="line"><a name="l06305"></a><span class="lineno"> 6305</span>&#160; </div>
+<div class="line"><a name="l06306"></a><span class="lineno"> 6306</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">void</span> Alloc(</div>
+<div class="line"><a name="l06307"></a><span class="lineno"> 6307</span>&#160;        <span class="keyword">const</span> VmaAllocationRequest&amp; request,</div>
+<div class="line"><a name="l06308"></a><span class="lineno"> 6308</span>&#160;        VmaSuballocationType type,</div>
+<div class="line"><a name="l06309"></a><span class="lineno"> 6309</span>&#160;        VkDeviceSize allocSize,</div>
+<div class="line"><a name="l06310"></a><span class="lineno"> 6310</span>&#160;        <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAllocation);</div>
+<div class="line"><a name="l06311"></a><span class="lineno"> 6311</span>&#160; </div>
+<div class="line"><a name="l06312"></a><span class="lineno"> 6312</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">void</span> Free(<span class="keyword">const</span> <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation) { FreeAtOffset(allocation, allocation-&gt;GetOffset()); }</div>
+<div class="line"><a name="l06313"></a><span class="lineno"> 6313</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">void</span> FreeAtOffset(VkDeviceSize offset) { FreeAtOffset(VMA_NULL, offset); }</div>
+<div class="line"><a name="l06314"></a><span class="lineno"> 6314</span>&#160; </div>
+<div class="line"><a name="l06315"></a><span class="lineno"> 6315</span>&#160;<span class="keyword">private</span>:</div>
+<div class="line"><a name="l06316"></a><span class="lineno"> 6316</span>&#160;    <span class="keyword">static</span> <span class="keyword">const</span> VkDeviceSize MIN_NODE_SIZE = 32;</div>
+<div class="line"><a name="l06317"></a><span class="lineno"> 6317</span>&#160;    <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">size_t</span> MAX_LEVELS = 30;</div>
+<div class="line"><a name="l06318"></a><span class="lineno"> 6318</span>&#160; </div>
+<div class="line"><a name="l06319"></a><span class="lineno"> 6319</span>&#160;    <span class="keyword">struct </span>ValidationContext</div>
+<div class="line"><a name="l06320"></a><span class="lineno"> 6320</span>&#160;    {</div>
+<div class="line"><a name="l06321"></a><span class="lineno"> 6321</span>&#160;        <span class="keywordtype">size_t</span> calculatedAllocationCount;</div>
+<div class="line"><a name="l06322"></a><span class="lineno"> 6322</span>&#160;        <span class="keywordtype">size_t</span> calculatedFreeCount;</div>
+<div class="line"><a name="l06323"></a><span class="lineno"> 6323</span>&#160;        VkDeviceSize calculatedSumFreeSize;</div>
+<div class="line"><a name="l06324"></a><span class="lineno"> 6324</span>&#160; </div>
+<div class="line"><a name="l06325"></a><span class="lineno"> 6325</span>&#160;        ValidationContext() :</div>
+<div class="line"><a name="l06326"></a><span class="lineno"> 6326</span>&#160;            calculatedAllocationCount(0),</div>
+<div class="line"><a name="l06327"></a><span class="lineno"> 6327</span>&#160;            calculatedFreeCount(0),</div>
+<div class="line"><a name="l06328"></a><span class="lineno"> 6328</span>&#160;            calculatedSumFreeSize(0) { }</div>
+<div class="line"><a name="l06329"></a><span class="lineno"> 6329</span>&#160;    };</div>
+<div class="line"><a name="l06330"></a><span class="lineno"> 6330</span>&#160; </div>
+<div class="line"><a name="l06331"></a><span class="lineno"> 6331</span>&#160;    <span class="keyword">struct </span>Node</div>
+<div class="line"><a name="l06332"></a><span class="lineno"> 6332</span>&#160;    {</div>
+<div class="line"><a name="l06333"></a><span class="lineno"> 6333</span>&#160;        VkDeviceSize offset;</div>
+<div class="line"><a name="l06334"></a><span class="lineno"> 6334</span>&#160;        <span class="keyword">enum</span> TYPE</div>
+<div class="line"><a name="l06335"></a><span class="lineno"> 6335</span>&#160;        {</div>
+<div class="line"><a name="l06336"></a><span class="lineno"> 6336</span>&#160;            TYPE_FREE,</div>
+<div class="line"><a name="l06337"></a><span class="lineno"> 6337</span>&#160;            TYPE_ALLOCATION,</div>
+<div class="line"><a name="l06338"></a><span class="lineno"> 6338</span>&#160;            TYPE_SPLIT,</div>
+<div class="line"><a name="l06339"></a><span class="lineno"> 6339</span>&#160;            TYPE_COUNT</div>
+<div class="line"><a name="l06340"></a><span class="lineno"> 6340</span>&#160;        } type;</div>
+<div class="line"><a name="l06341"></a><span class="lineno"> 6341</span>&#160;        Node* parent;</div>
+<div class="line"><a name="l06342"></a><span class="lineno"> 6342</span>&#160;        Node* buddy;</div>
+<div class="line"><a name="l06343"></a><span class="lineno"> 6343</span>&#160; </div>
+<div class="line"><a name="l06344"></a><span class="lineno"> 6344</span>&#160;        <span class="keyword">union</span></div>
+<div class="line"><a name="l06345"></a><span class="lineno"> 6345</span>&#160;        {</div>
+<div class="line"><a name="l06346"></a><span class="lineno"> 6346</span>&#160;            <span class="keyword">struct</span></div>
+<div class="line"><a name="l06347"></a><span class="lineno"> 6347</span>&#160;            {</div>
+<div class="line"><a name="l06348"></a><span class="lineno"> 6348</span>&#160;                Node* prev;</div>
+<div class="line"><a name="l06349"></a><span class="lineno"> 6349</span>&#160;                Node* next;</div>
+<div class="line"><a name="l06350"></a><span class="lineno"> 6350</span>&#160;            } free;</div>
+<div class="line"><a name="l06351"></a><span class="lineno"> 6351</span>&#160;            <span class="keyword">struct</span></div>
+<div class="line"><a name="l06352"></a><span class="lineno"> 6352</span>&#160;            {</div>
+<div class="line"><a name="l06353"></a><span class="lineno"> 6353</span>&#160;                <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> alloc;</div>
+<div class="line"><a name="l06354"></a><span class="lineno"> 6354</span>&#160;            } allocation;</div>
+<div class="line"><a name="l06355"></a><span class="lineno"> 6355</span>&#160;            <span class="keyword">struct</span></div>
+<div class="line"><a name="l06356"></a><span class="lineno"> 6356</span>&#160;            {</div>
+<div class="line"><a name="l06357"></a><span class="lineno"> 6357</span>&#160;                Node* leftChild;</div>
+<div class="line"><a name="l06358"></a><span class="lineno"> 6358</span>&#160;            } split;</div>
+<div class="line"><a name="l06359"></a><span class="lineno"> 6359</span>&#160;        };</div>
+<div class="line"><a name="l06360"></a><span class="lineno"> 6360</span>&#160;    };</div>
+<div class="line"><a name="l06361"></a><span class="lineno"> 6361</span>&#160; </div>
+<div class="line"><a name="l06362"></a><span class="lineno"> 6362</span>&#160;    <span class="comment">// Size of the memory block aligned down to a power of two.</span></div>
+<div class="line"><a name="l06363"></a><span class="lineno"> 6363</span>&#160;    VkDeviceSize m_UsableSize;</div>
+<div class="line"><a name="l06364"></a><span class="lineno"> 6364</span>&#160;    uint32_t m_LevelCount;</div>
+<div class="line"><a name="l06365"></a><span class="lineno"> 6365</span>&#160; </div>
+<div class="line"><a name="l06366"></a><span class="lineno"> 6366</span>&#160;    Node* m_Root;</div>
+<div class="line"><a name="l06367"></a><span class="lineno"> 6367</span>&#160;    <span class="keyword">struct </span>{</div>
+<div class="line"><a name="l06368"></a><span class="lineno"> 6368</span>&#160;        Node* front;</div>
+<div class="line"><a name="l06369"></a><span class="lineno"> 6369</span>&#160;        Node* back;</div>
+<div class="line"><a name="l06370"></a><span class="lineno"> 6370</span>&#160;    } m_FreeList[MAX_LEVELS];</div>
+<div class="line"><a name="l06371"></a><span class="lineno"> 6371</span>&#160;    <span class="comment">// Number of nodes in the tree with type == TYPE_ALLOCATION.</span></div>
+<div class="line"><a name="l06372"></a><span class="lineno"> 6372</span>&#160;    <span class="keywordtype">size_t</span> m_AllocationCount;</div>
+<div class="line"><a name="l06373"></a><span class="lineno"> 6373</span>&#160;    <span class="comment">// Number of nodes in the tree with type == TYPE_FREE.</span></div>
+<div class="line"><a name="l06374"></a><span class="lineno"> 6374</span>&#160;    <span class="keywordtype">size_t</span> m_FreeCount;</div>
+<div class="line"><a name="l06375"></a><span class="lineno"> 6375</span>&#160;    <span class="comment">// This includes space wasted due to internal fragmentation. Doesn&#39;t include unusable size.</span></div>
+<div class="line"><a name="l06376"></a><span class="lineno"> 6376</span>&#160;    VkDeviceSize m_SumFreeSize;</div>
+<div class="line"><a name="l06377"></a><span class="lineno"> 6377</span>&#160; </div>
+<div class="line"><a name="l06378"></a><span class="lineno"> 6378</span>&#160;    VkDeviceSize GetUnusableSize()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> GetSize() - m_UsableSize; }</div>
+<div class="line"><a name="l06379"></a><span class="lineno"> 6379</span>&#160;    <span class="keywordtype">void</span> DeleteNode(Node* node);</div>
+<div class="line"><a name="l06380"></a><span class="lineno"> 6380</span>&#160;    <span class="keywordtype">bool</span> ValidateNode(ValidationContext&amp; ctx, <span class="keyword">const</span> Node* parent, <span class="keyword">const</span> Node* curr, uint32_t level, VkDeviceSize levelNodeSize) <span class="keyword">const</span>;</div>
+<div class="line"><a name="l06381"></a><span class="lineno"> 6381</span>&#160;    uint32_t AllocSizeToLevel(VkDeviceSize allocSize) <span class="keyword">const</span>;</div>
+<div class="line"><a name="l06382"></a><span class="lineno"> 6382</span>&#160;    <span class="keyword">inline</span> VkDeviceSize LevelToNodeSize(uint32_t level)<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_UsableSize &gt;&gt; level; }</div>
+<div class="line"><a name="l06383"></a><span class="lineno"> 6383</span>&#160;    <span class="comment">// Alloc passed just for validation. Can be null.</span></div>
+<div class="line"><a name="l06384"></a><span class="lineno"> 6384</span>&#160;    <span class="keywordtype">void</span> FreeAtOffset(<a class="code" href="struct_vma_allocation.html">VmaAllocation</a> alloc, VkDeviceSize offset);</div>
+<div class="line"><a name="l06385"></a><span class="lineno"> 6385</span>&#160;    <span class="keywordtype">void</span> CalcAllocationStatInfoNode(<a class="code" href="struct_vma_stat_info.html">VmaStatInfo</a>&amp; outInfo, <span class="keyword">const</span> Node* node, VkDeviceSize levelNodeSize) <span class="keyword">const</span>;</div>
+<div class="line"><a name="l06386"></a><span class="lineno"> 6386</span>&#160;    <span class="comment">// Adds node to the front of FreeList at given level.</span></div>
+<div class="line"><a name="l06387"></a><span class="lineno"> 6387</span>&#160;    <span class="comment">// node-&gt;type must be FREE.</span></div>
+<div class="line"><a name="l06388"></a><span class="lineno"> 6388</span>&#160;    <span class="comment">// node-&gt;free.prev, next can be undefined.</span></div>
+<div class="line"><a name="l06389"></a><span class="lineno"> 6389</span>&#160;    <span class="keywordtype">void</span> AddToFreeListFront(uint32_t level, Node* node);</div>
+<div class="line"><a name="l06390"></a><span class="lineno"> 6390</span>&#160;    <span class="comment">// Removes node from FreeList at given level.</span></div>
+<div class="line"><a name="l06391"></a><span class="lineno"> 6391</span>&#160;    <span class="comment">// node-&gt;type must be FREE.</span></div>
+<div class="line"><a name="l06392"></a><span class="lineno"> 6392</span>&#160;    <span class="comment">// node-&gt;free.prev, next stay untouched.</span></div>
+<div class="line"><a name="l06393"></a><span class="lineno"> 6393</span>&#160;    <span class="keywordtype">void</span> RemoveFromFreeList(uint32_t level, Node* node);</div>
+<div class="line"><a name="l06394"></a><span class="lineno"> 6394</span>&#160; </div>
+<div class="line"><a name="l06395"></a><span class="lineno"> 6395</span>&#160;<span class="preprocessor">#if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l06396"></a><span class="lineno"> 6396</span>&#160;    <span class="keywordtype">void</span> PrintDetailedMapNode(<span class="keyword">class</span> VmaJsonWriter&amp; json, <span class="keyword">const</span> Node* node, VkDeviceSize levelNodeSize) <span class="keyword">const</span>;</div>
+<div class="line"><a name="l06397"></a><span class="lineno"> 6397</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l06398"></a><span class="lineno"> 6398</span>&#160;};</div>
+<div class="line"><a name="l06399"></a><span class="lineno"> 6399</span>&#160; </div>
+<div class="line"><a name="l06400"></a><span class="lineno"> 6400</span>&#160;<span class="comment">/*</span></div>
+<div class="line"><a name="l06401"></a><span class="lineno"> 6401</span>&#160;<span class="comment">Represents a single block of device memory (`VkDeviceMemory`) with all the</span></div>
+<div class="line"><a name="l06402"></a><span class="lineno"> 6402</span>&#160;<span class="comment">data about its regions (aka suballocations, #VmaAllocation), assigned and free.</span></div>
+<div class="line"><a name="l06403"></a><span class="lineno"> 6403</span>&#160;<span class="comment"></span> </div>
+<div class="line"><a name="l06404"></a><span class="lineno"> 6404</span>&#160;<span class="comment">Thread-safety: This class must be externally synchronized.</span></div>
+<div class="line"><a name="l06405"></a><span class="lineno"> 6405</span>&#160;<span class="comment">*/</span></div>
+<div class="line"><a name="l06406"></a><span class="lineno"> 6406</span>&#160;<span class="keyword">class </span>VmaDeviceMemoryBlock</div>
+<div class="line"><a name="l06407"></a><span class="lineno"> 6407</span>&#160;{</div>
+<div class="line"><a name="l06408"></a><span class="lineno"> 6408</span>&#160;    VMA_CLASS_NO_COPY(VmaDeviceMemoryBlock)</div>
+<div class="line"><a name="l06409"></a><span class="lineno"> 6409</span>&#160;<span class="keyword">public</span>:</div>
+<div class="line"><a name="l06410"></a><span class="lineno"> 6410</span>&#160;    VmaBlockMetadata* m_pMetadata;</div>
+<div class="line"><a name="l06411"></a><span class="lineno"> 6411</span>&#160; </div>
+<div class="line"><a name="l06412"></a><span class="lineno"> 6412</span>&#160;    VmaDeviceMemoryBlock(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator);</div>
+<div class="line"><a name="l06413"></a><span class="lineno"> 6413</span>&#160; </div>
+<div class="line"><a name="l06414"></a><span class="lineno"> 6414</span>&#160;    ~VmaDeviceMemoryBlock()</div>
+<div class="line"><a name="l06415"></a><span class="lineno"> 6415</span>&#160;    {</div>
+<div class="line"><a name="l06416"></a><span class="lineno"> 6416</span>&#160;        VMA_ASSERT(m_MapCount == 0 &amp;&amp; <span class="stringliteral">&quot;VkDeviceMemory block is being destroyed while it is still mapped.&quot;</span>);</div>
+<div class="line"><a name="l06417"></a><span class="lineno"> 6417</span>&#160;        VMA_ASSERT(m_hMemory == VK_NULL_HANDLE);</div>
+<div class="line"><a name="l06418"></a><span class="lineno"> 6418</span>&#160;    }</div>
+<div class="line"><a name="l06419"></a><span class="lineno"> 6419</span>&#160; </div>
+<div class="line"><a name="l06420"></a><span class="lineno"> 6420</span>&#160;    <span class="comment">// Always call after construction.</span></div>
+<div class="line"><a name="l06421"></a><span class="lineno"> 6421</span>&#160;    <span class="keywordtype">void</span> Init(</div>
+<div class="line"><a name="l06422"></a><span class="lineno"> 6422</span>&#160;        <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator,</div>
+<div class="line"><a name="l06423"></a><span class="lineno"> 6423</span>&#160;        <a class="code" href="struct_vma_pool.html">VmaPool</a> hParentPool,</div>
+<div class="line"><a name="l06424"></a><span class="lineno"> 6424</span>&#160;        uint32_t newMemoryTypeIndex,</div>
+<div class="line"><a name="l06425"></a><span class="lineno"> 6425</span>&#160;        VkDeviceMemory newMemory,</div>
+<div class="line"><a name="l06426"></a><span class="lineno"> 6426</span>&#160;        VkDeviceSize newSize,</div>
+<div class="line"><a name="l06427"></a><span class="lineno"> 6427</span>&#160;        uint32_t <span class="keywordtype">id</span>,</div>
+<div class="line"><a name="l06428"></a><span class="lineno"> 6428</span>&#160;        uint32_t algorithm);</div>
+<div class="line"><a name="l06429"></a><span class="lineno"> 6429</span>&#160;    <span class="comment">// Always call before destruction.</span></div>
+<div class="line"><a name="l06430"></a><span class="lineno"> 6430</span>&#160;    <span class="keywordtype">void</span> Destroy(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator);</div>
+<div class="line"><a name="l06431"></a><span class="lineno"> 6431</span>&#160;    </div>
+<div class="line"><a name="l06432"></a><span class="lineno"> 6432</span>&#160;    <a class="code" href="struct_vma_pool.html">VmaPool</a> GetParentPool()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_hParentPool; }</div>
+<div class="line"><a name="l06433"></a><span class="lineno"> 6433</span>&#160;    VkDeviceMemory GetDeviceMemory()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_hMemory; }</div>
+<div class="line"><a name="l06434"></a><span class="lineno"> 6434</span>&#160;    uint32_t GetMemoryTypeIndex()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_MemoryTypeIndex; }</div>
+<div class="line"><a name="l06435"></a><span class="lineno"> 6435</span>&#160;    uint32_t GetId()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_Id; }</div>
+<div class="line"><a name="l06436"></a><span class="lineno"> 6436</span>&#160;    <span class="keywordtype">void</span>* GetMappedData()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_pMappedData; }</div>
+<div class="line"><a name="l06437"></a><span class="lineno"> 6437</span>&#160; </div>
+<div class="line"><a name="l06438"></a><span class="lineno"> 6438</span>&#160;    <span class="comment">// Validates all data structures inside this object. If not valid, returns false.</span></div>
+<div class="line"><a name="l06439"></a><span class="lineno"> 6439</span>&#160;    <span class="keywordtype">bool</span> Validate() <span class="keyword">const</span>;</div>
+<div class="line"><a name="l06440"></a><span class="lineno"> 6440</span>&#160; </div>
+<div class="line"><a name="l06441"></a><span class="lineno"> 6441</span>&#160;    VkResult CheckCorruption(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator);</div>
+<div class="line"><a name="l06442"></a><span class="lineno"> 6442</span>&#160; </div>
+<div class="line"><a name="l06443"></a><span class="lineno"> 6443</span>&#160;    <span class="comment">// ppData can be null.</span></div>
+<div class="line"><a name="l06444"></a><span class="lineno"> 6444</span>&#160;    VkResult Map(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator, uint32_t count, <span class="keywordtype">void</span>** ppData);</div>
+<div class="line"><a name="l06445"></a><span class="lineno"> 6445</span>&#160;    <span class="keywordtype">void</span> Unmap(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator, uint32_t count);</div>
+<div class="line"><a name="l06446"></a><span class="lineno"> 6446</span>&#160; </div>
+<div class="line"><a name="l06447"></a><span class="lineno"> 6447</span>&#160;    VkResult WriteMagicValueAroundAllocation(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator, VkDeviceSize allocOffset, VkDeviceSize allocSize);</div>
+<div class="line"><a name="l06448"></a><span class="lineno"> 6448</span>&#160;    VkResult ValidateMagicValueAroundAllocation(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator, VkDeviceSize allocOffset, VkDeviceSize allocSize);</div>
+<div class="line"><a name="l06449"></a><span class="lineno"> 6449</span>&#160; </div>
+<div class="line"><a name="l06450"></a><span class="lineno"> 6450</span>&#160;    VkResult BindBufferMemory(</div>
+<div class="line"><a name="l06451"></a><span class="lineno"> 6451</span>&#160;        <span class="keyword">const</span> <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator,</div>
+<div class="line"><a name="l06452"></a><span class="lineno"> 6452</span>&#160;        <span class="keyword">const</span> <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAllocation,</div>
+<div class="line"><a name="l06453"></a><span class="lineno"> 6453</span>&#160;        VkDeviceSize allocationLocalOffset,</div>
+<div class="line"><a name="l06454"></a><span class="lineno"> 6454</span>&#160;        VkBuffer hBuffer,</div>
+<div class="line"><a name="l06455"></a><span class="lineno"> 6455</span>&#160;        <span class="keyword">const</span> <span class="keywordtype">void</span>* pNext);</div>
+<div class="line"><a name="l06456"></a><span class="lineno"> 6456</span>&#160;    VkResult BindImageMemory(</div>
+<div class="line"><a name="l06457"></a><span class="lineno"> 6457</span>&#160;        <span class="keyword">const</span> <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator,</div>
+<div class="line"><a name="l06458"></a><span class="lineno"> 6458</span>&#160;        <span class="keyword">const</span> <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAllocation,</div>
+<div class="line"><a name="l06459"></a><span class="lineno"> 6459</span>&#160;        VkDeviceSize allocationLocalOffset,</div>
+<div class="line"><a name="l06460"></a><span class="lineno"> 6460</span>&#160;        VkImage hImage,</div>
+<div class="line"><a name="l06461"></a><span class="lineno"> 6461</span>&#160;        <span class="keyword">const</span> <span class="keywordtype">void</span>* pNext);</div>
+<div class="line"><a name="l06462"></a><span class="lineno"> 6462</span>&#160; </div>
+<div class="line"><a name="l06463"></a><span class="lineno"> 6463</span>&#160;<span class="keyword">private</span>:</div>
+<div class="line"><a name="l06464"></a><span class="lineno"> 6464</span>&#160;    <a class="code" href="struct_vma_pool.html">VmaPool</a> m_hParentPool; <span class="comment">// VK_NULL_HANDLE if not belongs to custom pool.</span></div>
+<div class="line"><a name="l06465"></a><span class="lineno"> 6465</span>&#160;    uint32_t m_MemoryTypeIndex;</div>
+<div class="line"><a name="l06466"></a><span class="lineno"> 6466</span>&#160;    uint32_t m_Id;</div>
+<div class="line"><a name="l06467"></a><span class="lineno"> 6467</span>&#160;    VkDeviceMemory m_hMemory;</div>
+<div class="line"><a name="l06468"></a><span class="lineno"> 6468</span>&#160; </div>
+<div class="line"><a name="l06469"></a><span class="lineno"> 6469</span>&#160;    <span class="comment">/*</span></div>
+<div class="line"><a name="l06470"></a><span class="lineno"> 6470</span>&#160;<span class="comment">    Protects access to m_hMemory so it&#39;s not used by multiple threads simultaneously, e.g. vkMapMemory, vkBindBufferMemory.</span></div>
+<div class="line"><a name="l06471"></a><span class="lineno"> 6471</span>&#160;<span class="comment">    Also protects m_MapCount, m_pMappedData.</span></div>
+<div class="line"><a name="l06472"></a><span class="lineno"> 6472</span>&#160;<span class="comment">    Allocations, deallocations, any change in m_pMetadata is protected by parent&#39;s VmaBlockVector::m_Mutex.</span></div>
+<div class="line"><a name="l06473"></a><span class="lineno"> 6473</span>&#160;<span class="comment">    */</span></div>
+<div class="line"><a name="l06474"></a><span class="lineno"> 6474</span>&#160;    VMA_MUTEX m_Mutex;</div>
+<div class="line"><a name="l06475"></a><span class="lineno"> 6475</span>&#160;    uint32_t m_MapCount;</div>
+<div class="line"><a name="l06476"></a><span class="lineno"> 6476</span>&#160;    <span class="keywordtype">void</span>* m_pMappedData;</div>
+<div class="line"><a name="l06477"></a><span class="lineno"> 6477</span>&#160;};</div>
+<div class="line"><a name="l06478"></a><span class="lineno"> 6478</span>&#160; </div>
+<div class="line"><a name="l06479"></a><span class="lineno"> 6479</span>&#160;<span class="keyword">struct </span>VmaPointerLess</div>
+<div class="line"><a name="l06480"></a><span class="lineno"> 6480</span>&#160;{</div>
+<div class="line"><a name="l06481"></a><span class="lineno"> 6481</span>&#160;    <span class="keywordtype">bool</span> operator()(<span class="keyword">const</span> <span class="keywordtype">void</span>* lhs, <span class="keyword">const</span> <span class="keywordtype">void</span>* rhs)<span class="keyword"> const</span></div>
+<div class="line"><a name="l06482"></a><span class="lineno"> 6482</span>&#160;<span class="keyword">    </span>{</div>
+<div class="line"><a name="l06483"></a><span class="lineno"> 6483</span>&#160;        <span class="keywordflow">return</span> lhs &lt; rhs;</div>
+<div class="line"><a name="l06484"></a><span class="lineno"> 6484</span>&#160;    }</div>
+<div class="line"><a name="l06485"></a><span class="lineno"> 6485</span>&#160;};</div>
+<div class="line"><a name="l06486"></a><span class="lineno"> 6486</span>&#160; </div>
+<div class="line"><a name="l06487"></a><span class="lineno"> 6487</span>&#160;<span class="keyword">struct </span>VmaDefragmentationMove</div>
+<div class="line"><a name="l06488"></a><span class="lineno"> 6488</span>&#160;{</div>
+<div class="line"><a name="l06489"></a><span class="lineno"> 6489</span>&#160;    <span class="keywordtype">size_t</span> srcBlockIndex;</div>
+<div class="line"><a name="l06490"></a><span class="lineno"> 6490</span>&#160;    <span class="keywordtype">size_t</span> dstBlockIndex;</div>
+<div class="line"><a name="l06491"></a><span class="lineno"> 6491</span>&#160;    VkDeviceSize srcOffset;</div>
+<div class="line"><a name="l06492"></a><span class="lineno"> 6492</span>&#160;    VkDeviceSize dstOffset;</div>
+<div class="line"><a name="l06493"></a><span class="lineno"> 6493</span>&#160;    VkDeviceSize size;</div>
+<div class="line"><a name="l06494"></a><span class="lineno"> 6494</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAllocation;</div>
+<div class="line"><a name="l06495"></a><span class="lineno"> 6495</span>&#160;    VmaDeviceMemoryBlock* pSrcBlock;</div>
+<div class="line"><a name="l06496"></a><span class="lineno"> 6496</span>&#160;    VmaDeviceMemoryBlock* pDstBlock;</div>
+<div class="line"><a name="l06497"></a><span class="lineno"> 6497</span>&#160;};</div>
+<div class="line"><a name="l06498"></a><span class="lineno"> 6498</span>&#160; </div>
+<div class="line"><a name="l06499"></a><span class="lineno"> 6499</span>&#160;<span class="keyword">class </span>VmaDefragmentationAlgorithm;</div>
+<div class="line"><a name="l06500"></a><span class="lineno"> 6500</span>&#160; </div>
+<div class="line"><a name="l06501"></a><span class="lineno"> 6501</span>&#160;<span class="comment">/*</span></div>
+<div class="line"><a name="l06502"></a><span class="lineno"> 6502</span>&#160;<span class="comment">Sequence of VmaDeviceMemoryBlock. Represents memory blocks allocated for a specific</span></div>
+<div class="line"><a name="l06503"></a><span class="lineno"> 6503</span>&#160;<span class="comment">Vulkan memory type.</span></div>
+<div class="line"><a name="l06504"></a><span class="lineno"> 6504</span>&#160;<span class="comment"></span> </div>
+<div class="line"><a name="l06505"></a><span class="lineno"> 6505</span>&#160;<span class="comment">Synchronized internally with a mutex.</span></div>
+<div class="line"><a name="l06506"></a><span class="lineno"> 6506</span>&#160;<span class="comment">*/</span></div>
+<div class="line"><a name="l06507"></a><span class="lineno"> 6507</span>&#160;<span class="keyword">struct </span>VmaBlockVector</div>
+<div class="line"><a name="l06508"></a><span class="lineno"> 6508</span>&#160;{</div>
+<div class="line"><a name="l06509"></a><span class="lineno"> 6509</span>&#160;    VMA_CLASS_NO_COPY(VmaBlockVector)</div>
+<div class="line"><a name="l06510"></a><span class="lineno"> 6510</span>&#160;<span class="keyword">public</span>:</div>
+<div class="line"><a name="l06511"></a><span class="lineno"> 6511</span>&#160;    VmaBlockVector(</div>
+<div class="line"><a name="l06512"></a><span class="lineno"> 6512</span>&#160;        <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator,</div>
+<div class="line"><a name="l06513"></a><span class="lineno"> 6513</span>&#160;        <a class="code" href="struct_vma_pool.html">VmaPool</a> hParentPool,</div>
+<div class="line"><a name="l06514"></a><span class="lineno"> 6514</span>&#160;        uint32_t memoryTypeIndex,</div>
+<div class="line"><a name="l06515"></a><span class="lineno"> 6515</span>&#160;        VkDeviceSize preferredBlockSize,</div>
+<div class="line"><a name="l06516"></a><span class="lineno"> 6516</span>&#160;        <span class="keywordtype">size_t</span> minBlockCount,</div>
+<div class="line"><a name="l06517"></a><span class="lineno"> 6517</span>&#160;        <span class="keywordtype">size_t</span> maxBlockCount,</div>
+<div class="line"><a name="l06518"></a><span class="lineno"> 6518</span>&#160;        VkDeviceSize bufferImageGranularity,</div>
+<div class="line"><a name="l06519"></a><span class="lineno"> 6519</span>&#160;        uint32_t frameInUseCount,</div>
+<div class="line"><a name="l06520"></a><span class="lineno"> 6520</span>&#160;        <span class="keywordtype">bool</span> explicitBlockSize,</div>
+<div class="line"><a name="l06521"></a><span class="lineno"> 6521</span>&#160;        uint32_t algorithm);</div>
+<div class="line"><a name="l06522"></a><span class="lineno"> 6522</span>&#160;    ~VmaBlockVector();</div>
+<div class="line"><a name="l06523"></a><span class="lineno"> 6523</span>&#160; </div>
+<div class="line"><a name="l06524"></a><span class="lineno"> 6524</span>&#160;    VkResult CreateMinBlocks();</div>
+<div class="line"><a name="l06525"></a><span class="lineno"> 6525</span>&#160; </div>
+<div class="line"><a name="l06526"></a><span class="lineno"> 6526</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> GetAllocator()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_hAllocator; }</div>
+<div class="line"><a name="l06527"></a><span class="lineno"> 6527</span>&#160;    <a class="code" href="struct_vma_pool.html">VmaPool</a> GetParentPool()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_hParentPool; }</div>
+<div class="line"><a name="l06528"></a><span class="lineno"> 6528</span>&#160;    <span class="keywordtype">bool</span> IsCustomPool()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_hParentPool != VMA_NULL; }</div>
+<div class="line"><a name="l06529"></a><span class="lineno"> 6529</span>&#160;    uint32_t GetMemoryTypeIndex()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_MemoryTypeIndex; }</div>
+<div class="line"><a name="l06530"></a><span class="lineno"> 6530</span>&#160;    VkDeviceSize GetPreferredBlockSize()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_PreferredBlockSize; }</div>
+<div class="line"><a name="l06531"></a><span class="lineno"> 6531</span>&#160;    VkDeviceSize GetBufferImageGranularity()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_BufferImageGranularity; }</div>
+<div class="line"><a name="l06532"></a><span class="lineno"> 6532</span>&#160;    uint32_t GetFrameInUseCount()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_FrameInUseCount; }</div>
+<div class="line"><a name="l06533"></a><span class="lineno"> 6533</span>&#160;    uint32_t GetAlgorithm()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_Algorithm; }</div>
+<div class="line"><a name="l06534"></a><span class="lineno"> 6534</span>&#160; </div>
+<div class="line"><a name="l06535"></a><span class="lineno"> 6535</span>&#160;    <span class="keywordtype">void</span> GetPoolStats(<a class="code" href="struct_vma_pool_stats.html">VmaPoolStats</a>* pStats);</div>
+<div class="line"><a name="l06536"></a><span class="lineno"> 6536</span>&#160; </div>
+<div class="line"><a name="l06537"></a><span class="lineno"> 6537</span>&#160;    <span class="keywordtype">bool</span> IsEmpty();</div>
+<div class="line"><a name="l06538"></a><span class="lineno"> 6538</span>&#160;    <span class="keywordtype">bool</span> IsCorruptionDetectionEnabled() <span class="keyword">const</span>;</div>
+<div class="line"><a name="l06539"></a><span class="lineno"> 6539</span>&#160; </div>
+<div class="line"><a name="l06540"></a><span class="lineno"> 6540</span>&#160;    VkResult Allocate(</div>
+<div class="line"><a name="l06541"></a><span class="lineno"> 6541</span>&#160;        uint32_t currentFrameIndex,</div>
+<div class="line"><a name="l06542"></a><span class="lineno"> 6542</span>&#160;        VkDeviceSize size,</div>
+<div class="line"><a name="l06543"></a><span class="lineno"> 6543</span>&#160;        VkDeviceSize alignment,</div>
+<div class="line"><a name="l06544"></a><span class="lineno"> 6544</span>&#160;        <span class="keyword">const</span> <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>&amp; createInfo,</div>
+<div class="line"><a name="l06545"></a><span class="lineno"> 6545</span>&#160;        VmaSuballocationType suballocType,</div>
+<div class="line"><a name="l06546"></a><span class="lineno"> 6546</span>&#160;        <span class="keywordtype">size_t</span> allocationCount,</div>
+<div class="line"><a name="l06547"></a><span class="lineno"> 6547</span>&#160;        <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocations);</div>
+<div class="line"><a name="l06548"></a><span class="lineno"> 6548</span>&#160; </div>
+<div class="line"><a name="l06549"></a><span class="lineno"> 6549</span>&#160;    <span class="keywordtype">void</span> Free(<span class="keyword">const</span> <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAllocation);</div>
+<div class="line"><a name="l06550"></a><span class="lineno"> 6550</span>&#160; </div>
+<div class="line"><a name="l06551"></a><span class="lineno"> 6551</span>&#160;    <span class="comment">// Adds statistics of this BlockVector to pStats.</span></div>
+<div class="line"><a name="l06552"></a><span class="lineno"> 6552</span>&#160;    <span class="keywordtype">void</span> AddStats(<a class="code" href="struct_vma_stats.html">VmaStats</a>* pStats);</div>
+<div class="line"><a name="l06553"></a><span class="lineno"> 6553</span>&#160; </div>
+<div class="line"><a name="l06554"></a><span class="lineno"> 6554</span>&#160;<span class="preprocessor">#if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l06555"></a><span class="lineno"> 6555</span>&#160;    <span class="keywordtype">void</span> PrintDetailedMap(<span class="keyword">class</span> VmaJsonWriter&amp; json);</div>
+<div class="line"><a name="l06556"></a><span class="lineno"> 6556</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l06557"></a><span class="lineno"> 6557</span>&#160; </div>
+<div class="line"><a name="l06558"></a><span class="lineno"> 6558</span>&#160;    <span class="keywordtype">void</span> MakePoolAllocationsLost(</div>
+<div class="line"><a name="l06559"></a><span class="lineno"> 6559</span>&#160;        uint32_t currentFrameIndex,</div>
+<div class="line"><a name="l06560"></a><span class="lineno"> 6560</span>&#160;        <span class="keywordtype">size_t</span>* pLostAllocationCount);</div>
+<div class="line"><a name="l06561"></a><span class="lineno"> 6561</span>&#160;    VkResult CheckCorruption();</div>
+<div class="line"><a name="l06562"></a><span class="lineno"> 6562</span>&#160; </div>
+<div class="line"><a name="l06563"></a><span class="lineno"> 6563</span>&#160;    <span class="comment">// Saves results in pCtx-&gt;res.</span></div>
+<div class="line"><a name="l06564"></a><span class="lineno"> 6564</span>&#160;    <span class="keywordtype">void</span> Defragment(</div>
+<div class="line"><a name="l06565"></a><span class="lineno"> 6565</span>&#160;        <span class="keyword">class</span> VmaBlockVectorDefragmentationContext* pCtx,</div>
+<div class="line"><a name="l06566"></a><span class="lineno"> 6566</span>&#160;        <a class="code" href="struct_vma_defragmentation_stats.html">VmaDefragmentationStats</a>* pStats, <a class="code" href="vk__mem__alloc_8h.html#a88a77cef37e5d3c4fc9eb328885d048d">VmaDefragmentationFlags</a> flags,</div>
+<div class="line"><a name="l06567"></a><span class="lineno"> 6567</span>&#160;        VkDeviceSize&amp; maxCpuBytesToMove, uint32_t&amp; maxCpuAllocationsToMove,</div>
+<div class="line"><a name="l06568"></a><span class="lineno"> 6568</span>&#160;        VkDeviceSize&amp; maxGpuBytesToMove, uint32_t&amp; maxGpuAllocationsToMove,</div>
+<div class="line"><a name="l06569"></a><span class="lineno"> 6569</span>&#160;        VkCommandBuffer commandBuffer);</div>
+<div class="line"><a name="l06570"></a><span class="lineno"> 6570</span>&#160;    <span class="keywordtype">void</span> DefragmentationEnd(</div>
+<div class="line"><a name="l06571"></a><span class="lineno"> 6571</span>&#160;        <span class="keyword">class</span> VmaBlockVectorDefragmentationContext* pCtx,</div>
+<div class="line"><a name="l06572"></a><span class="lineno"> 6572</span>&#160;        uint32_t flags,</div>
+<div class="line"><a name="l06573"></a><span class="lineno"> 6573</span>&#160;        <a class="code" href="struct_vma_defragmentation_stats.html">VmaDefragmentationStats</a>* pStats);</div>
+<div class="line"><a name="l06574"></a><span class="lineno"> 6574</span>&#160; </div>
+<div class="line"><a name="l06575"></a><span class="lineno"> 6575</span>&#160;    uint32_t ProcessDefragmentations(</div>
+<div class="line"><a name="l06576"></a><span class="lineno"> 6576</span>&#160;        <span class="keyword">class</span> VmaBlockVectorDefragmentationContext *pCtx,</div>
+<div class="line"><a name="l06577"></a><span class="lineno"> 6577</span>&#160;        <a class="code" href="struct_vma_defragmentation_pass_move_info.html">VmaDefragmentationPassMoveInfo</a>* pMove, uint32_t maxMoves);</div>
+<div class="line"><a name="l06578"></a><span class="lineno"> 6578</span>&#160; </div>
+<div class="line"><a name="l06579"></a><span class="lineno"> 6579</span>&#160;    <span class="keywordtype">void</span> CommitDefragmentations(</div>
+<div class="line"><a name="l06580"></a><span class="lineno"> 6580</span>&#160;        <span class="keyword">class</span> VmaBlockVectorDefragmentationContext *pCtx,</div>
+<div class="line"><a name="l06581"></a><span class="lineno"> 6581</span>&#160;        <a class="code" href="struct_vma_defragmentation_stats.html">VmaDefragmentationStats</a>* pStats);</div>
+<div class="line"><a name="l06582"></a><span class="lineno"> 6582</span>&#160; </div>
+<div class="line"><a name="l06584"></a><span class="lineno"> 6584</span>&#160;    <span class="comment">// To be used only while the m_Mutex is locked. Used during defragmentation.</span></div>
+<div class="line"><a name="l06585"></a><span class="lineno"> 6585</span>&#160; </div>
+<div class="line"><a name="l06586"></a><span class="lineno"> 6586</span>&#160;    <span class="keywordtype">size_t</span> GetBlockCount()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_Blocks.size(); }</div>
+<div class="line"><a name="l06587"></a><span class="lineno"> 6587</span>&#160;    VmaDeviceMemoryBlock* GetBlock(<span class="keywordtype">size_t</span> index)<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_Blocks[index]; }</div>
+<div class="line"><a name="l06588"></a><span class="lineno"> 6588</span>&#160;    <span class="keywordtype">size_t</span> CalcAllocationCount() <span class="keyword">const</span>;</div>
+<div class="line"><a name="l06589"></a><span class="lineno"> 6589</span>&#160;    <span class="keywordtype">bool</span> IsBufferImageGranularityConflictPossible() <span class="keyword">const</span>;</div>
+<div class="line"><a name="l06590"></a><span class="lineno"> 6590</span>&#160; </div>
+<div class="line"><a name="l06591"></a><span class="lineno"> 6591</span>&#160;<span class="keyword">private</span>:</div>
+<div class="line"><a name="l06592"></a><span class="lineno"> 6592</span>&#160;    <span class="keyword">friend</span> <span class="keyword">class </span>VmaDefragmentationAlgorithm_Generic;</div>
+<div class="line"><a name="l06593"></a><span class="lineno"> 6593</span>&#160; </div>
+<div class="line"><a name="l06594"></a><span class="lineno"> 6594</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> m_hAllocator;</div>
+<div class="line"><a name="l06595"></a><span class="lineno"> 6595</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_pool.html">VmaPool</a> m_hParentPool;</div>
+<div class="line"><a name="l06596"></a><span class="lineno"> 6596</span>&#160;    <span class="keyword">const</span> uint32_t m_MemoryTypeIndex;</div>
+<div class="line"><a name="l06597"></a><span class="lineno"> 6597</span>&#160;    <span class="keyword">const</span> VkDeviceSize m_PreferredBlockSize;</div>
+<div class="line"><a name="l06598"></a><span class="lineno"> 6598</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">size_t</span> m_MinBlockCount;</div>
+<div class="line"><a name="l06599"></a><span class="lineno"> 6599</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">size_t</span> m_MaxBlockCount;</div>
+<div class="line"><a name="l06600"></a><span class="lineno"> 6600</span>&#160;    <span class="keyword">const</span> VkDeviceSize m_BufferImageGranularity;</div>
+<div class="line"><a name="l06601"></a><span class="lineno"> 6601</span>&#160;    <span class="keyword">const</span> uint32_t m_FrameInUseCount;</div>
+<div class="line"><a name="l06602"></a><span class="lineno"> 6602</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">bool</span> m_ExplicitBlockSize;</div>
+<div class="line"><a name="l06603"></a><span class="lineno"> 6603</span>&#160;    <span class="keyword">const</span> uint32_t m_Algorithm;</div>
+<div class="line"><a name="l06604"></a><span class="lineno"> 6604</span>&#160;    VMA_RW_MUTEX m_Mutex;</div>
+<div class="line"><a name="l06605"></a><span class="lineno"> 6605</span>&#160; </div>
+<div class="line"><a name="l06606"></a><span class="lineno"> 6606</span>&#160;    <span class="comment">/* There can be at most one allocation that is completely empty (except when minBlockCount &gt; 0) -</span></div>
+<div class="line"><a name="l06607"></a><span class="lineno"> 6607</span>&#160;<span class="comment">    a hysteresis to avoid pessimistic case of alternating creation and destruction of a VkDeviceMemory. */</span></div>
+<div class="line"><a name="l06608"></a><span class="lineno"> 6608</span>&#160;    <span class="keywordtype">bool</span> m_HasEmptyBlock;</div>
+<div class="line"><a name="l06609"></a><span class="lineno"> 6609</span>&#160;    <span class="comment">// Incrementally sorted by sumFreeSize, ascending.</span></div>
+<div class="line"><a name="l06610"></a><span class="lineno"> 6610</span>&#160;    VmaVector&lt; VmaDeviceMemoryBlock*, VmaStlAllocator&lt;VmaDeviceMemoryBlock*&gt; &gt; m_Blocks;</div>
+<div class="line"><a name="l06611"></a><span class="lineno"> 6611</span>&#160;    uint32_t m_NextBlockId;</div>
+<div class="line"><a name="l06612"></a><span class="lineno"> 6612</span>&#160; </div>
+<div class="line"><a name="l06613"></a><span class="lineno"> 6613</span>&#160;    VkDeviceSize CalcMaxBlockSize() <span class="keyword">const</span>;</div>
+<div class="line"><a name="l06614"></a><span class="lineno"> 6614</span>&#160; </div>
+<div class="line"><a name="l06615"></a><span class="lineno"> 6615</span>&#160;    <span class="comment">// Finds and removes given block from vector.</span></div>
+<div class="line"><a name="l06616"></a><span class="lineno"> 6616</span>&#160;    <span class="keywordtype">void</span> Remove(VmaDeviceMemoryBlock* pBlock);</div>
+<div class="line"><a name="l06617"></a><span class="lineno"> 6617</span>&#160; </div>
+<div class="line"><a name="l06618"></a><span class="lineno"> 6618</span>&#160;    <span class="comment">// Performs single step in sorting m_Blocks. They may not be fully sorted</span></div>
+<div class="line"><a name="l06619"></a><span class="lineno"> 6619</span>&#160;    <span class="comment">// after this call.</span></div>
+<div class="line"><a name="l06620"></a><span class="lineno"> 6620</span>&#160;    <span class="keywordtype">void</span> IncrementallySortBlocks();</div>
+<div class="line"><a name="l06621"></a><span class="lineno"> 6621</span>&#160; </div>
+<div class="line"><a name="l06622"></a><span class="lineno"> 6622</span>&#160;    VkResult AllocatePage(</div>
+<div class="line"><a name="l06623"></a><span class="lineno"> 6623</span>&#160;        uint32_t currentFrameIndex,</div>
+<div class="line"><a name="l06624"></a><span class="lineno"> 6624</span>&#160;        VkDeviceSize size,</div>
+<div class="line"><a name="l06625"></a><span class="lineno"> 6625</span>&#160;        VkDeviceSize alignment,</div>
+<div class="line"><a name="l06626"></a><span class="lineno"> 6626</span>&#160;        <span class="keyword">const</span> <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>&amp; createInfo,</div>
+<div class="line"><a name="l06627"></a><span class="lineno"> 6627</span>&#160;        VmaSuballocationType suballocType,</div>
+<div class="line"><a name="l06628"></a><span class="lineno"> 6628</span>&#160;        <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocation);</div>
+<div class="line"><a name="l06629"></a><span class="lineno"> 6629</span>&#160; </div>
+<div class="line"><a name="l06630"></a><span class="lineno"> 6630</span>&#160;    <span class="comment">// To be used only without CAN_MAKE_OTHER_LOST flag.</span></div>
+<div class="line"><a name="l06631"></a><span class="lineno"> 6631</span>&#160;    VkResult AllocateFromBlock(</div>
+<div class="line"><a name="l06632"></a><span class="lineno"> 6632</span>&#160;        VmaDeviceMemoryBlock* pBlock,</div>
+<div class="line"><a name="l06633"></a><span class="lineno"> 6633</span>&#160;        uint32_t currentFrameIndex,</div>
+<div class="line"><a name="l06634"></a><span class="lineno"> 6634</span>&#160;        VkDeviceSize size,</div>
+<div class="line"><a name="l06635"></a><span class="lineno"> 6635</span>&#160;        VkDeviceSize alignment,</div>
+<div class="line"><a name="l06636"></a><span class="lineno"> 6636</span>&#160;        <a class="code" href="vk__mem__alloc_8h.html#a5225e5e11f8376f6a31a1791f3d6e817">VmaAllocationCreateFlags</a> allocFlags,</div>
+<div class="line"><a name="l06637"></a><span class="lineno"> 6637</span>&#160;        <span class="keywordtype">void</span>* pUserData,</div>
+<div class="line"><a name="l06638"></a><span class="lineno"> 6638</span>&#160;        VmaSuballocationType suballocType,</div>
+<div class="line"><a name="l06639"></a><span class="lineno"> 6639</span>&#160;        uint32_t strategy,</div>
+<div class="line"><a name="l06640"></a><span class="lineno"> 6640</span>&#160;        <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocation);</div>
+<div class="line"><a name="l06641"></a><span class="lineno"> 6641</span>&#160; </div>
+<div class="line"><a name="l06642"></a><span class="lineno"> 6642</span>&#160;    VkResult CreateBlock(VkDeviceSize blockSize, <span class="keywordtype">size_t</span>* pNewBlockIndex);</div>
+<div class="line"><a name="l06643"></a><span class="lineno"> 6643</span>&#160; </div>
+<div class="line"><a name="l06644"></a><span class="lineno"> 6644</span>&#160;    <span class="comment">// Saves result to pCtx-&gt;res.</span></div>
+<div class="line"><a name="l06645"></a><span class="lineno"> 6645</span>&#160;    <span class="keywordtype">void</span> ApplyDefragmentationMovesCpu(</div>
+<div class="line"><a name="l06646"></a><span class="lineno"> 6646</span>&#160;        <span class="keyword">class</span> VmaBlockVectorDefragmentationContext* pDefragCtx,</div>
+<div class="line"><a name="l06647"></a><span class="lineno"> 6647</span>&#160;        <span class="keyword">const</span> VmaVector&lt; VmaDefragmentationMove, VmaStlAllocator&lt;VmaDefragmentationMove&gt; &gt;&amp; moves);</div>
+<div class="line"><a name="l06648"></a><span class="lineno"> 6648</span>&#160;    <span class="comment">// Saves result to pCtx-&gt;res.</span></div>
+<div class="line"><a name="l06649"></a><span class="lineno"> 6649</span>&#160;    <span class="keywordtype">void</span> ApplyDefragmentationMovesGpu(</div>
+<div class="line"><a name="l06650"></a><span class="lineno"> 6650</span>&#160;        <span class="keyword">class</span> VmaBlockVectorDefragmentationContext* pDefragCtx,</div>
+<div class="line"><a name="l06651"></a><span class="lineno"> 6651</span>&#160;        VmaVector&lt; VmaDefragmentationMove, VmaStlAllocator&lt;VmaDefragmentationMove&gt; &gt;&amp; moves,</div>
+<div class="line"><a name="l06652"></a><span class="lineno"> 6652</span>&#160;        VkCommandBuffer commandBuffer);</div>
+<div class="line"><a name="l06653"></a><span class="lineno"> 6653</span>&#160; </div>
+<div class="line"><a name="l06654"></a><span class="lineno"> 6654</span>&#160;    <span class="comment">/*</span></div>
+<div class="line"><a name="l06655"></a><span class="lineno"> 6655</span>&#160;<span class="comment">    Used during defragmentation. pDefragmentationStats is optional. It&#39;s in/out</span></div>
+<div class="line"><a name="l06656"></a><span class="lineno"> 6656</span>&#160;<span class="comment">    - updated with new data.</span></div>
+<div class="line"><a name="l06657"></a><span class="lineno"> 6657</span>&#160;<span class="comment">    */</span></div>
+<div class="line"><a name="l06658"></a><span class="lineno"> 6658</span>&#160;    <span class="keywordtype">void</span> FreeEmptyBlocks(<a class="code" href="struct_vma_defragmentation_stats.html">VmaDefragmentationStats</a>* pDefragmentationStats);</div>
+<div class="line"><a name="l06659"></a><span class="lineno"> 6659</span>&#160; </div>
+<div class="line"><a name="l06660"></a><span class="lineno"> 6660</span>&#160;    <span class="keywordtype">void</span> UpdateHasEmptyBlock();</div>
+<div class="line"><a name="l06661"></a><span class="lineno"> 6661</span>&#160;};</div>
+<div class="line"><a name="l06662"></a><span class="lineno"> 6662</span>&#160; </div>
+<div class="line"><a name="l06663"></a><span class="lineno"> 6663</span>&#160;<span class="keyword">struct </span>VmaPool_T</div>
+<div class="line"><a name="l06664"></a><span class="lineno"> 6664</span>&#160;{</div>
+<div class="line"><a name="l06665"></a><span class="lineno"> 6665</span>&#160;    VMA_CLASS_NO_COPY(VmaPool_T)</div>
+<div class="line"><a name="l06666"></a><span class="lineno"> 6666</span>&#160;<span class="keyword">public</span>:</div>
+<div class="line"><a name="l06667"></a><span class="lineno"> 6667</span>&#160;    VmaBlockVector m_BlockVector;</div>
+<div class="line"><a name="l06668"></a><span class="lineno"> 6668</span>&#160; </div>
+<div class="line"><a name="l06669"></a><span class="lineno"> 6669</span>&#160;    VmaPool_T(</div>
+<div class="line"><a name="l06670"></a><span class="lineno"> 6670</span>&#160;        <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator,</div>
+<div class="line"><a name="l06671"></a><span class="lineno"> 6671</span>&#160;        <span class="keyword">const</span> <a class="code" href="struct_vma_pool_create_info.html">VmaPoolCreateInfo</a>&amp; createInfo,</div>
+<div class="line"><a name="l06672"></a><span class="lineno"> 6672</span>&#160;        VkDeviceSize preferredBlockSize);</div>
+<div class="line"><a name="l06673"></a><span class="lineno"> 6673</span>&#160;    ~VmaPool_T();</div>
+<div class="line"><a name="l06674"></a><span class="lineno"> 6674</span>&#160; </div>
+<div class="line"><a name="l06675"></a><span class="lineno"> 6675</span>&#160;    uint32_t GetId()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_Id; }</div>
+<div class="line"><a name="l06676"></a><span class="lineno"> 6676</span>&#160;    <span class="keywordtype">void</span> SetId(uint32_t <span class="keywordtype">id</span>) { VMA_ASSERT(m_Id == 0); m_Id = id; }</div>
+<div class="line"><a name="l06677"></a><span class="lineno"> 6677</span>&#160; </div>
+<div class="line"><a name="l06678"></a><span class="lineno"> 6678</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">char</span>* GetName()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_Name; }</div>
+<div class="line"><a name="l06679"></a><span class="lineno"> 6679</span>&#160;    <span class="keywordtype">void</span> SetName(<span class="keyword">const</span> <span class="keywordtype">char</span>* pName);</div>
+<div class="line"><a name="l06680"></a><span class="lineno"> 6680</span>&#160; </div>
+<div class="line"><a name="l06681"></a><span class="lineno"> 6681</span>&#160;<span class="preprocessor">#if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l06682"></a><span class="lineno"> 6682</span>&#160;    <span class="comment">//void PrintDetailedMap(class VmaStringBuilder&amp; sb);</span></div>
+<div class="line"><a name="l06683"></a><span class="lineno"> 6683</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l06684"></a><span class="lineno"> 6684</span>&#160; </div>
+<div class="line"><a name="l06685"></a><span class="lineno"> 6685</span>&#160;<span class="keyword">private</span>:</div>
+<div class="line"><a name="l06686"></a><span class="lineno"> 6686</span>&#160;    uint32_t m_Id;</div>
+<div class="line"><a name="l06687"></a><span class="lineno"> 6687</span>&#160;    <span class="keywordtype">char</span>* m_Name;</div>
+<div class="line"><a name="l06688"></a><span class="lineno"> 6688</span>&#160;};</div>
+<div class="line"><a name="l06689"></a><span class="lineno"> 6689</span>&#160; </div>
+<div class="line"><a name="l06690"></a><span class="lineno"> 6690</span>&#160;<span class="comment">/*</span></div>
+<div class="line"><a name="l06691"></a><span class="lineno"> 6691</span>&#160;<span class="comment">Performs defragmentation:</span></div>
+<div class="line"><a name="l06692"></a><span class="lineno"> 6692</span>&#160;<span class="comment"></span> </div>
+<div class="line"><a name="l06693"></a><span class="lineno"> 6693</span>&#160;<span class="comment">- Updates `pBlockVector-&gt;m_pMetadata`.</span></div>
+<div class="line"><a name="l06694"></a><span class="lineno"> 6694</span>&#160;<span class="comment">- Updates allocations by calling ChangeBlockAllocation() or ChangeOffset().</span></div>
+<div class="line"><a name="l06695"></a><span class="lineno"> 6695</span>&#160;<span class="comment">- Does not move actual data, only returns requested moves as `moves`.</span></div>
+<div class="line"><a name="l06696"></a><span class="lineno"> 6696</span>&#160;<span class="comment">*/</span></div>
+<div class="line"><a name="l06697"></a><span class="lineno"> 6697</span>&#160;<span class="keyword">class </span>VmaDefragmentationAlgorithm</div>
+<div class="line"><a name="l06698"></a><span class="lineno"> 6698</span>&#160;{</div>
+<div class="line"><a name="l06699"></a><span class="lineno"> 6699</span>&#160;    VMA_CLASS_NO_COPY(VmaDefragmentationAlgorithm)</div>
+<div class="line"><a name="l06700"></a><span class="lineno"> 6700</span>&#160;<span class="keyword">public</span>:</div>
+<div class="line"><a name="l06701"></a><span class="lineno"> 6701</span>&#160;    VmaDefragmentationAlgorithm(</div>
+<div class="line"><a name="l06702"></a><span class="lineno"> 6702</span>&#160;        <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator,</div>
+<div class="line"><a name="l06703"></a><span class="lineno"> 6703</span>&#160;        VmaBlockVector* pBlockVector,</div>
+<div class="line"><a name="l06704"></a><span class="lineno"> 6704</span>&#160;        uint32_t currentFrameIndex) :</div>
+<div class="line"><a name="l06705"></a><span class="lineno"> 6705</span>&#160;        m_hAllocator(hAllocator),</div>
+<div class="line"><a name="l06706"></a><span class="lineno"> 6706</span>&#160;        m_pBlockVector(pBlockVector),</div>
+<div class="line"><a name="l06707"></a><span class="lineno"> 6707</span>&#160;        m_CurrentFrameIndex(currentFrameIndex)</div>
+<div class="line"><a name="l06708"></a><span class="lineno"> 6708</span>&#160;    {</div>
+<div class="line"><a name="l06709"></a><span class="lineno"> 6709</span>&#160;    }</div>
+<div class="line"><a name="l06710"></a><span class="lineno"> 6710</span>&#160;    <span class="keyword">virtual</span> ~VmaDefragmentationAlgorithm()</div>
+<div class="line"><a name="l06711"></a><span class="lineno"> 6711</span>&#160;    {</div>
+<div class="line"><a name="l06712"></a><span class="lineno"> 6712</span>&#160;    }</div>
+<div class="line"><a name="l06713"></a><span class="lineno"> 6713</span>&#160; </div>
+<div class="line"><a name="l06714"></a><span class="lineno"> 6714</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">void</span> AddAllocation(<a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAlloc, VkBool32* pChanged) = 0;</div>
+<div class="line"><a name="l06715"></a><span class="lineno"> 6715</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">void</span> AddAll() = 0;</div>
+<div class="line"><a name="l06716"></a><span class="lineno"> 6716</span>&#160; </div>
+<div class="line"><a name="l06717"></a><span class="lineno"> 6717</span>&#160;    <span class="keyword">virtual</span> VkResult Defragment(</div>
+<div class="line"><a name="l06718"></a><span class="lineno"> 6718</span>&#160;        VmaVector&lt; VmaDefragmentationMove, VmaStlAllocator&lt;VmaDefragmentationMove&gt; &gt;&amp; moves,</div>
+<div class="line"><a name="l06719"></a><span class="lineno"> 6719</span>&#160;        VkDeviceSize maxBytesToMove,</div>
+<div class="line"><a name="l06720"></a><span class="lineno"> 6720</span>&#160;        uint32_t maxAllocationsToMove,</div>
+<div class="line"><a name="l06721"></a><span class="lineno"> 6721</span>&#160;        <a class="code" href="vk__mem__alloc_8h.html#a88a77cef37e5d3c4fc9eb328885d048d">VmaDefragmentationFlags</a> flags) = 0;</div>
+<div class="line"><a name="l06722"></a><span class="lineno"> 6722</span>&#160; </div>
+<div class="line"><a name="l06723"></a><span class="lineno"> 6723</span>&#160;    <span class="keyword">virtual</span> VkDeviceSize GetBytesMoved() <span class="keyword">const</span> = 0;</div>
+<div class="line"><a name="l06724"></a><span class="lineno"> 6724</span>&#160;    <span class="keyword">virtual</span> uint32_t GetAllocationsMoved() <span class="keyword">const</span> = 0;</div>
+<div class="line"><a name="l06725"></a><span class="lineno"> 6725</span>&#160; </div>
+<div class="line"><a name="l06726"></a><span class="lineno"> 6726</span>&#160;<span class="keyword">protected</span>:</div>
+<div class="line"><a name="l06727"></a><span class="lineno"> 6727</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> <span class="keyword">const</span> m_hAllocator;</div>
+<div class="line"><a name="l06728"></a><span class="lineno"> 6728</span>&#160;    VmaBlockVector* <span class="keyword">const</span> m_pBlockVector;</div>
+<div class="line"><a name="l06729"></a><span class="lineno"> 6729</span>&#160;    <span class="keyword">const</span> uint32_t m_CurrentFrameIndex;</div>
+<div class="line"><a name="l06730"></a><span class="lineno"> 6730</span>&#160; </div>
+<div class="line"><a name="l06731"></a><span class="lineno"> 6731</span>&#160;    <span class="keyword">struct </span>AllocationInfo</div>
+<div class="line"><a name="l06732"></a><span class="lineno"> 6732</span>&#160;    {</div>
+<div class="line"><a name="l06733"></a><span class="lineno"> 6733</span>&#160;        <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> m_hAllocation;</div>
+<div class="line"><a name="l06734"></a><span class="lineno"> 6734</span>&#160;        VkBool32* m_pChanged;</div>
+<div class="line"><a name="l06735"></a><span class="lineno"> 6735</span>&#160; </div>
+<div class="line"><a name="l06736"></a><span class="lineno"> 6736</span>&#160;        AllocationInfo() :</div>
+<div class="line"><a name="l06737"></a><span class="lineno"> 6737</span>&#160;            m_hAllocation(VK_NULL_HANDLE),</div>
+<div class="line"><a name="l06738"></a><span class="lineno"> 6738</span>&#160;            m_pChanged(VMA_NULL)</div>
+<div class="line"><a name="l06739"></a><span class="lineno"> 6739</span>&#160;        {</div>
+<div class="line"><a name="l06740"></a><span class="lineno"> 6740</span>&#160;        }</div>
+<div class="line"><a name="l06741"></a><span class="lineno"> 6741</span>&#160;        AllocationInfo(<a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAlloc, VkBool32* pChanged) :</div>
+<div class="line"><a name="l06742"></a><span class="lineno"> 6742</span>&#160;            m_hAllocation(hAlloc),</div>
+<div class="line"><a name="l06743"></a><span class="lineno"> 6743</span>&#160;            m_pChanged(pChanged)</div>
+<div class="line"><a name="l06744"></a><span class="lineno"> 6744</span>&#160;        {</div>
+<div class="line"><a name="l06745"></a><span class="lineno"> 6745</span>&#160;        }</div>
+<div class="line"><a name="l06746"></a><span class="lineno"> 6746</span>&#160;    };</div>
+<div class="line"><a name="l06747"></a><span class="lineno"> 6747</span>&#160;};</div>
+<div class="line"><a name="l06748"></a><span class="lineno"> 6748</span>&#160; </div>
+<div class="line"><a name="l06749"></a><span class="lineno"> 6749</span>&#160;<span class="keyword">class </span>VmaDefragmentationAlgorithm_Generic : <span class="keyword">public</span> VmaDefragmentationAlgorithm</div>
+<div class="line"><a name="l06750"></a><span class="lineno"> 6750</span>&#160;{</div>
+<div class="line"><a name="l06751"></a><span class="lineno"> 6751</span>&#160;    VMA_CLASS_NO_COPY(VmaDefragmentationAlgorithm_Generic)</div>
+<div class="line"><a name="l06752"></a><span class="lineno"> 6752</span>&#160;<span class="keyword">public</span>:</div>
+<div class="line"><a name="l06753"></a><span class="lineno"> 6753</span>&#160;    VmaDefragmentationAlgorithm_Generic(</div>
+<div class="line"><a name="l06754"></a><span class="lineno"> 6754</span>&#160;        <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator,</div>
+<div class="line"><a name="l06755"></a><span class="lineno"> 6755</span>&#160;        VmaBlockVector* pBlockVector,</div>
+<div class="line"><a name="l06756"></a><span class="lineno"> 6756</span>&#160;        uint32_t currentFrameIndex,</div>
+<div class="line"><a name="l06757"></a><span class="lineno"> 6757</span>&#160;        <span class="keywordtype">bool</span> overlappingMoveSupported);</div>
+<div class="line"><a name="l06758"></a><span class="lineno"> 6758</span>&#160;    <span class="keyword">virtual</span> ~VmaDefragmentationAlgorithm_Generic();</div>
+<div class="line"><a name="l06759"></a><span class="lineno"> 6759</span>&#160; </div>
+<div class="line"><a name="l06760"></a><span class="lineno"> 6760</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">void</span> AddAllocation(<a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAlloc, VkBool32* pChanged);</div>
+<div class="line"><a name="l06761"></a><span class="lineno"> 6761</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">void</span> AddAll() { m_AllAllocations = <span class="keyword">true</span>; }</div>
+<div class="line"><a name="l06762"></a><span class="lineno"> 6762</span>&#160; </div>
+<div class="line"><a name="l06763"></a><span class="lineno"> 6763</span>&#160;    <span class="keyword">virtual</span> VkResult Defragment(</div>
+<div class="line"><a name="l06764"></a><span class="lineno"> 6764</span>&#160;        VmaVector&lt; VmaDefragmentationMove, VmaStlAllocator&lt;VmaDefragmentationMove&gt; &gt;&amp; moves,</div>
+<div class="line"><a name="l06765"></a><span class="lineno"> 6765</span>&#160;        VkDeviceSize maxBytesToMove,</div>
+<div class="line"><a name="l06766"></a><span class="lineno"> 6766</span>&#160;        uint32_t maxAllocationsToMove,</div>
+<div class="line"><a name="l06767"></a><span class="lineno"> 6767</span>&#160;        <a class="code" href="vk__mem__alloc_8h.html#a88a77cef37e5d3c4fc9eb328885d048d">VmaDefragmentationFlags</a> flags);</div>
+<div class="line"><a name="l06768"></a><span class="lineno"> 6768</span>&#160; </div>
+<div class="line"><a name="l06769"></a><span class="lineno"> 6769</span>&#160;    <span class="keyword">virtual</span> VkDeviceSize GetBytesMoved()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_BytesMoved; }</div>
+<div class="line"><a name="l06770"></a><span class="lineno"> 6770</span>&#160;    <span class="keyword">virtual</span> uint32_t GetAllocationsMoved()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_AllocationsMoved; }</div>
+<div class="line"><a name="l06771"></a><span class="lineno"> 6771</span>&#160; </div>
+<div class="line"><a name="l06772"></a><span class="lineno"> 6772</span>&#160;<span class="keyword">private</span>:</div>
+<div class="line"><a name="l06773"></a><span class="lineno"> 6773</span>&#160;    uint32_t m_AllocationCount;</div>
+<div class="line"><a name="l06774"></a><span class="lineno"> 6774</span>&#160;    <span class="keywordtype">bool</span> m_AllAllocations;</div>
+<div class="line"><a name="l06775"></a><span class="lineno"> 6775</span>&#160; </div>
+<div class="line"><a name="l06776"></a><span class="lineno"> 6776</span>&#160;    VkDeviceSize m_BytesMoved;</div>
+<div class="line"><a name="l06777"></a><span class="lineno"> 6777</span>&#160;    uint32_t m_AllocationsMoved;</div>
+<div class="line"><a name="l06778"></a><span class="lineno"> 6778</span>&#160; </div>
+<div class="line"><a name="l06779"></a><span class="lineno"> 6779</span>&#160;    <span class="keyword">struct </span>AllocationInfoSizeGreater</div>
+<div class="line"><a name="l06780"></a><span class="lineno"> 6780</span>&#160;    {</div>
+<div class="line"><a name="l06781"></a><span class="lineno"> 6781</span>&#160;        <span class="keywordtype">bool</span> operator()(<span class="keyword">const</span> AllocationInfo&amp; lhs, <span class="keyword">const</span> AllocationInfo&amp; rhs)<span class="keyword"> const</span></div>
+<div class="line"><a name="l06782"></a><span class="lineno"> 6782</span>&#160;<span class="keyword">        </span>{</div>
+<div class="line"><a name="l06783"></a><span class="lineno"> 6783</span>&#160;            <span class="keywordflow">return</span> lhs.m_hAllocation-&gt;GetSize() &gt; rhs.m_hAllocation-&gt;GetSize();</div>
+<div class="line"><a name="l06784"></a><span class="lineno"> 6784</span>&#160;        }</div>
+<div class="line"><a name="l06785"></a><span class="lineno"> 6785</span>&#160;    };</div>
+<div class="line"><a name="l06786"></a><span class="lineno"> 6786</span>&#160; </div>
+<div class="line"><a name="l06787"></a><span class="lineno"> 6787</span>&#160;    <span class="keyword">struct </span>AllocationInfoOffsetGreater</div>
+<div class="line"><a name="l06788"></a><span class="lineno"> 6788</span>&#160;    {</div>
+<div class="line"><a name="l06789"></a><span class="lineno"> 6789</span>&#160;        <span class="keywordtype">bool</span> operator()(<span class="keyword">const</span> AllocationInfo&amp; lhs, <span class="keyword">const</span> AllocationInfo&amp; rhs)<span class="keyword"> const</span></div>
+<div class="line"><a name="l06790"></a><span class="lineno"> 6790</span>&#160;<span class="keyword">        </span>{</div>
+<div class="line"><a name="l06791"></a><span class="lineno"> 6791</span>&#160;            <span class="keywordflow">return</span> lhs.m_hAllocation-&gt;GetOffset() &gt; rhs.m_hAllocation-&gt;GetOffset();</div>
+<div class="line"><a name="l06792"></a><span class="lineno"> 6792</span>&#160;        }</div>
+<div class="line"><a name="l06793"></a><span class="lineno"> 6793</span>&#160;    };</div>
+<div class="line"><a name="l06794"></a><span class="lineno"> 6794</span>&#160; </div>
+<div class="line"><a name="l06795"></a><span class="lineno"> 6795</span>&#160;    <span class="keyword">struct </span>BlockInfo</div>
+<div class="line"><a name="l06796"></a><span class="lineno"> 6796</span>&#160;    {</div>
+<div class="line"><a name="l06797"></a><span class="lineno"> 6797</span>&#160;        <span class="keywordtype">size_t</span> m_OriginalBlockIndex;</div>
+<div class="line"><a name="l06798"></a><span class="lineno"> 6798</span>&#160;        VmaDeviceMemoryBlock* m_pBlock;</div>
+<div class="line"><a name="l06799"></a><span class="lineno"> 6799</span>&#160;        <span class="keywordtype">bool</span> m_HasNonMovableAllocations;</div>
+<div class="line"><a name="l06800"></a><span class="lineno"> 6800</span>&#160;        VmaVector&lt; AllocationInfo, VmaStlAllocator&lt;AllocationInfo&gt; &gt; m_Allocations;</div>
+<div class="line"><a name="l06801"></a><span class="lineno"> 6801</span>&#160; </div>
+<div class="line"><a name="l06802"></a><span class="lineno"> 6802</span>&#160;        BlockInfo(<span class="keyword">const</span> VkAllocationCallbacks* pAllocationCallbacks) :</div>
+<div class="line"><a name="l06803"></a><span class="lineno"> 6803</span>&#160;            m_OriginalBlockIndex(SIZE_MAX),</div>
+<div class="line"><a name="l06804"></a><span class="lineno"> 6804</span>&#160;            m_pBlock(VMA_NULL),</div>
+<div class="line"><a name="l06805"></a><span class="lineno"> 6805</span>&#160;            m_HasNonMovableAllocations(true),</div>
+<div class="line"><a name="l06806"></a><span class="lineno"> 6806</span>&#160;            m_Allocations(pAllocationCallbacks)</div>
+<div class="line"><a name="l06807"></a><span class="lineno"> 6807</span>&#160;        {</div>
+<div class="line"><a name="l06808"></a><span class="lineno"> 6808</span>&#160;        }</div>
+<div class="line"><a name="l06809"></a><span class="lineno"> 6809</span>&#160; </div>
+<div class="line"><a name="l06810"></a><span class="lineno"> 6810</span>&#160;        <span class="keywordtype">void</span> CalcHasNonMovableAllocations()</div>
+<div class="line"><a name="l06811"></a><span class="lineno"> 6811</span>&#160;        {</div>
+<div class="line"><a name="l06812"></a><span class="lineno"> 6812</span>&#160;            <span class="keyword">const</span> <span class="keywordtype">size_t</span> blockAllocCount = m_pBlock-&gt;m_pMetadata-&gt;GetAllocationCount();</div>
+<div class="line"><a name="l06813"></a><span class="lineno"> 6813</span>&#160;            <span class="keyword">const</span> <span class="keywordtype">size_t</span> defragmentAllocCount = m_Allocations.size();</div>
+<div class="line"><a name="l06814"></a><span class="lineno"> 6814</span>&#160;            m_HasNonMovableAllocations = blockAllocCount != defragmentAllocCount;</div>
+<div class="line"><a name="l06815"></a><span class="lineno"> 6815</span>&#160;        }</div>
+<div class="line"><a name="l06816"></a><span class="lineno"> 6816</span>&#160; </div>
+<div class="line"><a name="l06817"></a><span class="lineno"> 6817</span>&#160;        <span class="keywordtype">void</span> SortAllocationsBySizeDescending()</div>
+<div class="line"><a name="l06818"></a><span class="lineno"> 6818</span>&#160;        {</div>
+<div class="line"><a name="l06819"></a><span class="lineno"> 6819</span>&#160;            VMA_SORT(m_Allocations.begin(), m_Allocations.end(), AllocationInfoSizeGreater());</div>
+<div class="line"><a name="l06820"></a><span class="lineno"> 6820</span>&#160;        }</div>
+<div class="line"><a name="l06821"></a><span class="lineno"> 6821</span>&#160; </div>
+<div class="line"><a name="l06822"></a><span class="lineno"> 6822</span>&#160;        <span class="keywordtype">void</span> SortAllocationsByOffsetDescending()</div>
+<div class="line"><a name="l06823"></a><span class="lineno"> 6823</span>&#160;        {</div>
+<div class="line"><a name="l06824"></a><span class="lineno"> 6824</span>&#160;            VMA_SORT(m_Allocations.begin(), m_Allocations.end(), AllocationInfoOffsetGreater());</div>
+<div class="line"><a name="l06825"></a><span class="lineno"> 6825</span>&#160;        }</div>
+<div class="line"><a name="l06826"></a><span class="lineno"> 6826</span>&#160;    };</div>
+<div class="line"><a name="l06827"></a><span class="lineno"> 6827</span>&#160; </div>
+<div class="line"><a name="l06828"></a><span class="lineno"> 6828</span>&#160;    <span class="keyword">struct </span>BlockPointerLess</div>
+<div class="line"><a name="l06829"></a><span class="lineno"> 6829</span>&#160;    {</div>
+<div class="line"><a name="l06830"></a><span class="lineno"> 6830</span>&#160;        <span class="keywordtype">bool</span> operator()(<span class="keyword">const</span> BlockInfo* pLhsBlockInfo, <span class="keyword">const</span> VmaDeviceMemoryBlock* pRhsBlock)<span class="keyword"> const</span></div>
+<div class="line"><a name="l06831"></a><span class="lineno"> 6831</span>&#160;<span class="keyword">        </span>{</div>
+<div class="line"><a name="l06832"></a><span class="lineno"> 6832</span>&#160;            <span class="keywordflow">return</span> pLhsBlockInfo-&gt;m_pBlock &lt; pRhsBlock;</div>
+<div class="line"><a name="l06833"></a><span class="lineno"> 6833</span>&#160;        }</div>
+<div class="line"><a name="l06834"></a><span class="lineno"> 6834</span>&#160;        <span class="keywordtype">bool</span> operator()(<span class="keyword">const</span> BlockInfo* pLhsBlockInfo, <span class="keyword">const</span> BlockInfo* pRhsBlockInfo)<span class="keyword"> const</span></div>
+<div class="line"><a name="l06835"></a><span class="lineno"> 6835</span>&#160;<span class="keyword">        </span>{</div>
+<div class="line"><a name="l06836"></a><span class="lineno"> 6836</span>&#160;            <span class="keywordflow">return</span> pLhsBlockInfo-&gt;m_pBlock &lt; pRhsBlockInfo-&gt;m_pBlock;</div>
+<div class="line"><a name="l06837"></a><span class="lineno"> 6837</span>&#160;        }</div>
+<div class="line"><a name="l06838"></a><span class="lineno"> 6838</span>&#160;    };</div>
+<div class="line"><a name="l06839"></a><span class="lineno"> 6839</span>&#160; </div>
+<div class="line"><a name="l06840"></a><span class="lineno"> 6840</span>&#160;    <span class="comment">// 1. Blocks with some non-movable allocations go first.</span></div>
+<div class="line"><a name="l06841"></a><span class="lineno"> 6841</span>&#160;    <span class="comment">// 2. Blocks with smaller sumFreeSize go first.</span></div>
+<div class="line"><a name="l06842"></a><span class="lineno"> 6842</span>&#160;    <span class="keyword">struct </span>BlockInfoCompareMoveDestination</div>
+<div class="line"><a name="l06843"></a><span class="lineno"> 6843</span>&#160;    {</div>
+<div class="line"><a name="l06844"></a><span class="lineno"> 6844</span>&#160;        <span class="keywordtype">bool</span> operator()(<span class="keyword">const</span> BlockInfo* pLhsBlockInfo, <span class="keyword">const</span> BlockInfo* pRhsBlockInfo)<span class="keyword"> const</span></div>
+<div class="line"><a name="l06845"></a><span class="lineno"> 6845</span>&#160;<span class="keyword">        </span>{</div>
+<div class="line"><a name="l06846"></a><span class="lineno"> 6846</span>&#160;            <span class="keywordflow">if</span>(pLhsBlockInfo-&gt;m_HasNonMovableAllocations &amp;&amp; !pRhsBlockInfo-&gt;m_HasNonMovableAllocations)</div>
+<div class="line"><a name="l06847"></a><span class="lineno"> 6847</span>&#160;            {</div>
+<div class="line"><a name="l06848"></a><span class="lineno"> 6848</span>&#160;                <span class="keywordflow">return</span> <span class="keyword">true</span>;</div>
+<div class="line"><a name="l06849"></a><span class="lineno"> 6849</span>&#160;            }</div>
+<div class="line"><a name="l06850"></a><span class="lineno"> 6850</span>&#160;            <span class="keywordflow">if</span>(!pLhsBlockInfo-&gt;m_HasNonMovableAllocations &amp;&amp; pRhsBlockInfo-&gt;m_HasNonMovableAllocations)</div>
+<div class="line"><a name="l06851"></a><span class="lineno"> 6851</span>&#160;            {</div>
+<div class="line"><a name="l06852"></a><span class="lineno"> 6852</span>&#160;                <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l06853"></a><span class="lineno"> 6853</span>&#160;            }</div>
+<div class="line"><a name="l06854"></a><span class="lineno"> 6854</span>&#160;            <span class="keywordflow">if</span>(pLhsBlockInfo-&gt;m_pBlock-&gt;m_pMetadata-&gt;GetSumFreeSize() &lt; pRhsBlockInfo-&gt;m_pBlock-&gt;m_pMetadata-&gt;GetSumFreeSize())</div>
+<div class="line"><a name="l06855"></a><span class="lineno"> 6855</span>&#160;            {</div>
+<div class="line"><a name="l06856"></a><span class="lineno"> 6856</span>&#160;                <span class="keywordflow">return</span> <span class="keyword">true</span>;</div>
+<div class="line"><a name="l06857"></a><span class="lineno"> 6857</span>&#160;            }</div>
+<div class="line"><a name="l06858"></a><span class="lineno"> 6858</span>&#160;            <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l06859"></a><span class="lineno"> 6859</span>&#160;        }</div>
+<div class="line"><a name="l06860"></a><span class="lineno"> 6860</span>&#160;    };</div>
+<div class="line"><a name="l06861"></a><span class="lineno"> 6861</span>&#160; </div>
+<div class="line"><a name="l06862"></a><span class="lineno"> 6862</span>&#160;    <span class="keyword">typedef</span> VmaVector&lt; BlockInfo*, VmaStlAllocator&lt;BlockInfo*&gt; &gt; BlockInfoVector;</div>
+<div class="line"><a name="l06863"></a><span class="lineno"> 6863</span>&#160;    BlockInfoVector m_Blocks;</div>
+<div class="line"><a name="l06864"></a><span class="lineno"> 6864</span>&#160; </div>
+<div class="line"><a name="l06865"></a><span class="lineno"> 6865</span>&#160;    VkResult DefragmentRound(</div>
+<div class="line"><a name="l06866"></a><span class="lineno"> 6866</span>&#160;        VmaVector&lt; VmaDefragmentationMove, VmaStlAllocator&lt;VmaDefragmentationMove&gt; &gt;&amp; moves,</div>
+<div class="line"><a name="l06867"></a><span class="lineno"> 6867</span>&#160;        VkDeviceSize maxBytesToMove,</div>
+<div class="line"><a name="l06868"></a><span class="lineno"> 6868</span>&#160;        uint32_t maxAllocationsToMove,</div>
+<div class="line"><a name="l06869"></a><span class="lineno"> 6869</span>&#160;        <span class="keywordtype">bool</span> freeOldAllocations);</div>
+<div class="line"><a name="l06870"></a><span class="lineno"> 6870</span>&#160; </div>
+<div class="line"><a name="l06871"></a><span class="lineno"> 6871</span>&#160;    <span class="keywordtype">size_t</span> CalcBlocksWithNonMovableCount() <span class="keyword">const</span>;</div>
+<div class="line"><a name="l06872"></a><span class="lineno"> 6872</span>&#160; </div>
+<div class="line"><a name="l06873"></a><span class="lineno"> 6873</span>&#160;    <span class="keyword">static</span> <span class="keywordtype">bool</span> MoveMakesSense(</div>
+<div class="line"><a name="l06874"></a><span class="lineno"> 6874</span>&#160;        <span class="keywordtype">size_t</span> dstBlockIndex, VkDeviceSize dstOffset,</div>
+<div class="line"><a name="l06875"></a><span class="lineno"> 6875</span>&#160;        <span class="keywordtype">size_t</span> srcBlockIndex, VkDeviceSize srcOffset);</div>
+<div class="line"><a name="l06876"></a><span class="lineno"> 6876</span>&#160;};</div>
+<div class="line"><a name="l06877"></a><span class="lineno"> 6877</span>&#160; </div>
+<div class="line"><a name="l06878"></a><span class="lineno"> 6878</span>&#160;<span class="keyword">class </span>VmaDefragmentationAlgorithm_Fast : <span class="keyword">public</span> VmaDefragmentationAlgorithm</div>
+<div class="line"><a name="l06879"></a><span class="lineno"> 6879</span>&#160;{</div>
+<div class="line"><a name="l06880"></a><span class="lineno"> 6880</span>&#160;    VMA_CLASS_NO_COPY(VmaDefragmentationAlgorithm_Fast)</div>
+<div class="line"><a name="l06881"></a><span class="lineno"> 6881</span>&#160;<span class="keyword">public</span>:</div>
+<div class="line"><a name="l06882"></a><span class="lineno"> 6882</span>&#160;    VmaDefragmentationAlgorithm_Fast(</div>
+<div class="line"><a name="l06883"></a><span class="lineno"> 6883</span>&#160;        <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator,</div>
+<div class="line"><a name="l06884"></a><span class="lineno"> 6884</span>&#160;        VmaBlockVector* pBlockVector,</div>
+<div class="line"><a name="l06885"></a><span class="lineno"> 6885</span>&#160;        uint32_t currentFrameIndex,</div>
+<div class="line"><a name="l06886"></a><span class="lineno"> 6886</span>&#160;        <span class="keywordtype">bool</span> overlappingMoveSupported);</div>
+<div class="line"><a name="l06887"></a><span class="lineno"> 6887</span>&#160;    <span class="keyword">virtual</span> ~VmaDefragmentationAlgorithm_Fast();</div>
+<div class="line"><a name="l06888"></a><span class="lineno"> 6888</span>&#160; </div>
+<div class="line"><a name="l06889"></a><span class="lineno"> 6889</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">void</span> AddAllocation(<a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAlloc, VkBool32* pChanged) { ++m_AllocationCount; }</div>
+<div class="line"><a name="l06890"></a><span class="lineno"> 6890</span>&#160;    <span class="keyword">virtual</span> <span class="keywordtype">void</span> AddAll() { m_AllAllocations = <span class="keyword">true</span>; }</div>
+<div class="line"><a name="l06891"></a><span class="lineno"> 6891</span>&#160; </div>
+<div class="line"><a name="l06892"></a><span class="lineno"> 6892</span>&#160;    <span class="keyword">virtual</span> VkResult Defragment(</div>
+<div class="line"><a name="l06893"></a><span class="lineno"> 6893</span>&#160;        VmaVector&lt; VmaDefragmentationMove, VmaStlAllocator&lt;VmaDefragmentationMove&gt; &gt;&amp; moves,</div>
+<div class="line"><a name="l06894"></a><span class="lineno"> 6894</span>&#160;        VkDeviceSize maxBytesToMove,</div>
+<div class="line"><a name="l06895"></a><span class="lineno"> 6895</span>&#160;        uint32_t maxAllocationsToMove,</div>
+<div class="line"><a name="l06896"></a><span class="lineno"> 6896</span>&#160;        <a class="code" href="vk__mem__alloc_8h.html#a88a77cef37e5d3c4fc9eb328885d048d">VmaDefragmentationFlags</a> flags);</div>
+<div class="line"><a name="l06897"></a><span class="lineno"> 6897</span>&#160; </div>
+<div class="line"><a name="l06898"></a><span class="lineno"> 6898</span>&#160;    <span class="keyword">virtual</span> VkDeviceSize GetBytesMoved()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_BytesMoved; }</div>
+<div class="line"><a name="l06899"></a><span class="lineno"> 6899</span>&#160;    <span class="keyword">virtual</span> uint32_t GetAllocationsMoved()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_AllocationsMoved; }</div>
+<div class="line"><a name="l06900"></a><span class="lineno"> 6900</span>&#160; </div>
+<div class="line"><a name="l06901"></a><span class="lineno"> 6901</span>&#160;<span class="keyword">private</span>:</div>
+<div class="line"><a name="l06902"></a><span class="lineno"> 6902</span>&#160;    <span class="keyword">struct </span>BlockInfo</div>
+<div class="line"><a name="l06903"></a><span class="lineno"> 6903</span>&#160;    {</div>
+<div class="line"><a name="l06904"></a><span class="lineno"> 6904</span>&#160;        <span class="keywordtype">size_t</span> origBlockIndex;</div>
+<div class="line"><a name="l06905"></a><span class="lineno"> 6905</span>&#160;    };</div>
+<div class="line"><a name="l06906"></a><span class="lineno"> 6906</span>&#160; </div>
+<div class="line"><a name="l06907"></a><span class="lineno"> 6907</span>&#160;    <span class="keyword">class </span>FreeSpaceDatabase</div>
+<div class="line"><a name="l06908"></a><span class="lineno"> 6908</span>&#160;    {</div>
+<div class="line"><a name="l06909"></a><span class="lineno"> 6909</span>&#160;    <span class="keyword">public</span>:</div>
+<div class="line"><a name="l06910"></a><span class="lineno"> 6910</span>&#160;        FreeSpaceDatabase()</div>
+<div class="line"><a name="l06911"></a><span class="lineno"> 6911</span>&#160;        {</div>
+<div class="line"><a name="l06912"></a><span class="lineno"> 6912</span>&#160;            FreeSpace s = {};</div>
+<div class="line"><a name="l06913"></a><span class="lineno"> 6913</span>&#160;            s.blockInfoIndex = SIZE_MAX;</div>
+<div class="line"><a name="l06914"></a><span class="lineno"> 6914</span>&#160;            <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = 0; i &lt; MAX_COUNT; ++i)</div>
+<div class="line"><a name="l06915"></a><span class="lineno"> 6915</span>&#160;            {</div>
+<div class="line"><a name="l06916"></a><span class="lineno"> 6916</span>&#160;                m_FreeSpaces[i] = s;</div>
+<div class="line"><a name="l06917"></a><span class="lineno"> 6917</span>&#160;            }</div>
+<div class="line"><a name="l06918"></a><span class="lineno"> 6918</span>&#160;        }</div>
+<div class="line"><a name="l06919"></a><span class="lineno"> 6919</span>&#160; </div>
+<div class="line"><a name="l06920"></a><span class="lineno"> 6920</span>&#160;        <span class="keywordtype">void</span> Register(<span class="keywordtype">size_t</span> blockInfoIndex, VkDeviceSize offset, VkDeviceSize size)</div>
+<div class="line"><a name="l06921"></a><span class="lineno"> 6921</span>&#160;        {</div>
+<div class="line"><a name="l06922"></a><span class="lineno"> 6922</span>&#160;            <span class="keywordflow">if</span>(size &lt; VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER)</div>
+<div class="line"><a name="l06923"></a><span class="lineno"> 6923</span>&#160;            {</div>
+<div class="line"><a name="l06924"></a><span class="lineno"> 6924</span>&#160;                <span class="keywordflow">return</span>;</div>
+<div class="line"><a name="l06925"></a><span class="lineno"> 6925</span>&#160;            }</div>
+<div class="line"><a name="l06926"></a><span class="lineno"> 6926</span>&#160; </div>
+<div class="line"><a name="l06927"></a><span class="lineno"> 6927</span>&#160;            <span class="comment">// Find first invalid or the smallest structure.</span></div>
+<div class="line"><a name="l06928"></a><span class="lineno"> 6928</span>&#160;            <span class="keywordtype">size_t</span> bestIndex = SIZE_MAX;</div>
+<div class="line"><a name="l06929"></a><span class="lineno"> 6929</span>&#160;            <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = 0; i &lt; MAX_COUNT; ++i)</div>
+<div class="line"><a name="l06930"></a><span class="lineno"> 6930</span>&#160;            {</div>
+<div class="line"><a name="l06931"></a><span class="lineno"> 6931</span>&#160;                <span class="comment">// Empty structure.</span></div>
+<div class="line"><a name="l06932"></a><span class="lineno"> 6932</span>&#160;                <span class="keywordflow">if</span>(m_FreeSpaces[i].blockInfoIndex == SIZE_MAX)</div>
+<div class="line"><a name="l06933"></a><span class="lineno"> 6933</span>&#160;                {</div>
+<div class="line"><a name="l06934"></a><span class="lineno"> 6934</span>&#160;                    bestIndex = i;</div>
+<div class="line"><a name="l06935"></a><span class="lineno"> 6935</span>&#160;                    <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l06936"></a><span class="lineno"> 6936</span>&#160;                }</div>
+<div class="line"><a name="l06937"></a><span class="lineno"> 6937</span>&#160;                <span class="keywordflow">if</span>(m_FreeSpaces[i].size &lt; size &amp;&amp;</div>
+<div class="line"><a name="l06938"></a><span class="lineno"> 6938</span>&#160;                    (bestIndex == SIZE_MAX || m_FreeSpaces[bestIndex].size &gt; m_FreeSpaces[i].size))</div>
+<div class="line"><a name="l06939"></a><span class="lineno"> 6939</span>&#160;                {</div>
+<div class="line"><a name="l06940"></a><span class="lineno"> 6940</span>&#160;                    bestIndex = i;</div>
+<div class="line"><a name="l06941"></a><span class="lineno"> 6941</span>&#160;                }</div>
+<div class="line"><a name="l06942"></a><span class="lineno"> 6942</span>&#160;            }</div>
+<div class="line"><a name="l06943"></a><span class="lineno"> 6943</span>&#160; </div>
+<div class="line"><a name="l06944"></a><span class="lineno"> 6944</span>&#160;            <span class="keywordflow">if</span>(bestIndex != SIZE_MAX)</div>
+<div class="line"><a name="l06945"></a><span class="lineno"> 6945</span>&#160;            {</div>
+<div class="line"><a name="l06946"></a><span class="lineno"> 6946</span>&#160;                m_FreeSpaces[bestIndex].blockInfoIndex = blockInfoIndex;</div>
+<div class="line"><a name="l06947"></a><span class="lineno"> 6947</span>&#160;                m_FreeSpaces[bestIndex].offset = offset;</div>
+<div class="line"><a name="l06948"></a><span class="lineno"> 6948</span>&#160;                m_FreeSpaces[bestIndex].size = size;</div>
+<div class="line"><a name="l06949"></a><span class="lineno"> 6949</span>&#160;            }</div>
+<div class="line"><a name="l06950"></a><span class="lineno"> 6950</span>&#160;        }</div>
+<div class="line"><a name="l06951"></a><span class="lineno"> 6951</span>&#160; </div>
+<div class="line"><a name="l06952"></a><span class="lineno"> 6952</span>&#160;        <span class="keywordtype">bool</span> Fetch(VkDeviceSize alignment, VkDeviceSize size,</div>
+<div class="line"><a name="l06953"></a><span class="lineno"> 6953</span>&#160;            <span class="keywordtype">size_t</span>&amp; outBlockInfoIndex, VkDeviceSize&amp; outDstOffset)</div>
+<div class="line"><a name="l06954"></a><span class="lineno"> 6954</span>&#160;        {</div>
+<div class="line"><a name="l06955"></a><span class="lineno"> 6955</span>&#160;            <span class="keywordtype">size_t</span> bestIndex = SIZE_MAX;</div>
+<div class="line"><a name="l06956"></a><span class="lineno"> 6956</span>&#160;            VkDeviceSize bestFreeSpaceAfter = 0;</div>
+<div class="line"><a name="l06957"></a><span class="lineno"> 6957</span>&#160;            <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = 0; i &lt; MAX_COUNT; ++i)</div>
+<div class="line"><a name="l06958"></a><span class="lineno"> 6958</span>&#160;            {</div>
+<div class="line"><a name="l06959"></a><span class="lineno"> 6959</span>&#160;                <span class="comment">// Structure is valid.</span></div>
+<div class="line"><a name="l06960"></a><span class="lineno"> 6960</span>&#160;                <span class="keywordflow">if</span>(m_FreeSpaces[i].blockInfoIndex != SIZE_MAX)</div>
+<div class="line"><a name="l06961"></a><span class="lineno"> 6961</span>&#160;                {</div>
+<div class="line"><a name="l06962"></a><span class="lineno"> 6962</span>&#160;                    <span class="keyword">const</span> VkDeviceSize dstOffset = VmaAlignUp(m_FreeSpaces[i].offset, alignment);</div>
+<div class="line"><a name="l06963"></a><span class="lineno"> 6963</span>&#160;                    <span class="comment">// Allocation fits into this structure.</span></div>
+<div class="line"><a name="l06964"></a><span class="lineno"> 6964</span>&#160;                    <span class="keywordflow">if</span>(dstOffset + size &lt;= m_FreeSpaces[i].offset + m_FreeSpaces[i].size)</div>
+<div class="line"><a name="l06965"></a><span class="lineno"> 6965</span>&#160;                    {</div>
+<div class="line"><a name="l06966"></a><span class="lineno"> 6966</span>&#160;                        <span class="keyword">const</span> VkDeviceSize freeSpaceAfter = (m_FreeSpaces[i].offset + m_FreeSpaces[i].size) -</div>
+<div class="line"><a name="l06967"></a><span class="lineno"> 6967</span>&#160;                            (dstOffset + size);</div>
+<div class="line"><a name="l06968"></a><span class="lineno"> 6968</span>&#160;                        <span class="keywordflow">if</span>(bestIndex == SIZE_MAX || freeSpaceAfter &gt; bestFreeSpaceAfter)</div>
+<div class="line"><a name="l06969"></a><span class="lineno"> 6969</span>&#160;                        {</div>
+<div class="line"><a name="l06970"></a><span class="lineno"> 6970</span>&#160;                            bestIndex = i;</div>
+<div class="line"><a name="l06971"></a><span class="lineno"> 6971</span>&#160;                            bestFreeSpaceAfter = freeSpaceAfter;</div>
+<div class="line"><a name="l06972"></a><span class="lineno"> 6972</span>&#160;                        }</div>
+<div class="line"><a name="l06973"></a><span class="lineno"> 6973</span>&#160;                    }</div>
+<div class="line"><a name="l06974"></a><span class="lineno"> 6974</span>&#160;                }</div>
+<div class="line"><a name="l06975"></a><span class="lineno"> 6975</span>&#160;            }</div>
+<div class="line"><a name="l06976"></a><span class="lineno"> 6976</span>&#160;            </div>
+<div class="line"><a name="l06977"></a><span class="lineno"> 6977</span>&#160;            <span class="keywordflow">if</span>(bestIndex != SIZE_MAX)</div>
+<div class="line"><a name="l06978"></a><span class="lineno"> 6978</span>&#160;            {</div>
+<div class="line"><a name="l06979"></a><span class="lineno"> 6979</span>&#160;                outBlockInfoIndex = m_FreeSpaces[bestIndex].blockInfoIndex;</div>
+<div class="line"><a name="l06980"></a><span class="lineno"> 6980</span>&#160;                outDstOffset = VmaAlignUp(m_FreeSpaces[bestIndex].offset, alignment);</div>
+<div class="line"><a name="l06981"></a><span class="lineno"> 6981</span>&#160; </div>
+<div class="line"><a name="l06982"></a><span class="lineno"> 6982</span>&#160;                <span class="keywordflow">if</span>(bestFreeSpaceAfter &gt;= VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER)</div>
+<div class="line"><a name="l06983"></a><span class="lineno"> 6983</span>&#160;                {</div>
+<div class="line"><a name="l06984"></a><span class="lineno"> 6984</span>&#160;                    <span class="comment">// Leave this structure for remaining empty space.</span></div>
+<div class="line"><a name="l06985"></a><span class="lineno"> 6985</span>&#160;                    <span class="keyword">const</span> VkDeviceSize alignmentPlusSize = (outDstOffset - m_FreeSpaces[bestIndex].offset) + size;</div>
+<div class="line"><a name="l06986"></a><span class="lineno"> 6986</span>&#160;                    m_FreeSpaces[bestIndex].offset += alignmentPlusSize;</div>
+<div class="line"><a name="l06987"></a><span class="lineno"> 6987</span>&#160;                    m_FreeSpaces[bestIndex].size -= alignmentPlusSize;</div>
+<div class="line"><a name="l06988"></a><span class="lineno"> 6988</span>&#160;                }</div>
+<div class="line"><a name="l06989"></a><span class="lineno"> 6989</span>&#160;                <span class="keywordflow">else</span></div>
+<div class="line"><a name="l06990"></a><span class="lineno"> 6990</span>&#160;                {</div>
+<div class="line"><a name="l06991"></a><span class="lineno"> 6991</span>&#160;                    <span class="comment">// This structure becomes invalid.</span></div>
+<div class="line"><a name="l06992"></a><span class="lineno"> 6992</span>&#160;                    m_FreeSpaces[bestIndex].blockInfoIndex = SIZE_MAX;</div>
+<div class="line"><a name="l06993"></a><span class="lineno"> 6993</span>&#160;                }</div>
+<div class="line"><a name="l06994"></a><span class="lineno"> 6994</span>&#160; </div>
+<div class="line"><a name="l06995"></a><span class="lineno"> 6995</span>&#160;                <span class="keywordflow">return</span> <span class="keyword">true</span>;</div>
+<div class="line"><a name="l06996"></a><span class="lineno"> 6996</span>&#160;            }</div>
+<div class="line"><a name="l06997"></a><span class="lineno"> 6997</span>&#160; </div>
+<div class="line"><a name="l06998"></a><span class="lineno"> 6998</span>&#160;            <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l06999"></a><span class="lineno"> 6999</span>&#160;        }</div>
+<div class="line"><a name="l07000"></a><span class="lineno"> 7000</span>&#160; </div>
+<div class="line"><a name="l07001"></a><span class="lineno"> 7001</span>&#160;    <span class="keyword">private</span>:</div>
+<div class="line"><a name="l07002"></a><span class="lineno"> 7002</span>&#160;        <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">size_t</span> MAX_COUNT = 4;</div>
+<div class="line"><a name="l07003"></a><span class="lineno"> 7003</span>&#160; </div>
+<div class="line"><a name="l07004"></a><span class="lineno"> 7004</span>&#160;        <span class="keyword">struct </span>FreeSpace</div>
+<div class="line"><a name="l07005"></a><span class="lineno"> 7005</span>&#160;        {</div>
+<div class="line"><a name="l07006"></a><span class="lineno"> 7006</span>&#160;            <span class="keywordtype">size_t</span> blockInfoIndex; <span class="comment">// SIZE_MAX means this structure is invalid.</span></div>
+<div class="line"><a name="l07007"></a><span class="lineno"> 7007</span>&#160;            VkDeviceSize offset;</div>
+<div class="line"><a name="l07008"></a><span class="lineno"> 7008</span>&#160;            VkDeviceSize size;</div>
+<div class="line"><a name="l07009"></a><span class="lineno"> 7009</span>&#160;        } m_FreeSpaces[MAX_COUNT];</div>
+<div class="line"><a name="l07010"></a><span class="lineno"> 7010</span>&#160;    };</div>
+<div class="line"><a name="l07011"></a><span class="lineno"> 7011</span>&#160; </div>
+<div class="line"><a name="l07012"></a><span class="lineno"> 7012</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">bool</span> m_OverlappingMoveSupported;</div>
+<div class="line"><a name="l07013"></a><span class="lineno"> 7013</span>&#160; </div>
+<div class="line"><a name="l07014"></a><span class="lineno"> 7014</span>&#160;    uint32_t m_AllocationCount;</div>
+<div class="line"><a name="l07015"></a><span class="lineno"> 7015</span>&#160;    <span class="keywordtype">bool</span> m_AllAllocations;</div>
+<div class="line"><a name="l07016"></a><span class="lineno"> 7016</span>&#160; </div>
+<div class="line"><a name="l07017"></a><span class="lineno"> 7017</span>&#160;    VkDeviceSize m_BytesMoved;</div>
+<div class="line"><a name="l07018"></a><span class="lineno"> 7018</span>&#160;    uint32_t m_AllocationsMoved;</div>
+<div class="line"><a name="l07019"></a><span class="lineno"> 7019</span>&#160; </div>
+<div class="line"><a name="l07020"></a><span class="lineno"> 7020</span>&#160;    VmaVector&lt; BlockInfo, VmaStlAllocator&lt;BlockInfo&gt; &gt; m_BlockInfos;</div>
+<div class="line"><a name="l07021"></a><span class="lineno"> 7021</span>&#160; </div>
+<div class="line"><a name="l07022"></a><span class="lineno"> 7022</span>&#160;    <span class="keywordtype">void</span> PreprocessMetadata();</div>
+<div class="line"><a name="l07023"></a><span class="lineno"> 7023</span>&#160;    <span class="keywordtype">void</span> PostprocessMetadata();</div>
+<div class="line"><a name="l07024"></a><span class="lineno"> 7024</span>&#160;    <span class="keywordtype">void</span> InsertSuballoc(VmaBlockMetadata_Generic* pMetadata, <span class="keyword">const</span> VmaSuballocation&amp; suballoc);</div>
+<div class="line"><a name="l07025"></a><span class="lineno"> 7025</span>&#160;};</div>
+<div class="line"><a name="l07026"></a><span class="lineno"> 7026</span>&#160; </div>
+<div class="line"><a name="l07027"></a><span class="lineno"> 7027</span>&#160;<span class="keyword">struct </span>VmaBlockDefragmentationContext</div>
+<div class="line"><a name="l07028"></a><span class="lineno"> 7028</span>&#160;{</div>
+<div class="line"><a name="l07029"></a><span class="lineno"> 7029</span>&#160;    <span class="keyword">enum</span> BLOCK_FLAG</div>
+<div class="line"><a name="l07030"></a><span class="lineno"> 7030</span>&#160;    {</div>
+<div class="line"><a name="l07031"></a><span class="lineno"> 7031</span>&#160;        BLOCK_FLAG_USED = 0x00000001,</div>
+<div class="line"><a name="l07032"></a><span class="lineno"> 7032</span>&#160;    };</div>
+<div class="line"><a name="l07033"></a><span class="lineno"> 7033</span>&#160;    uint32_t flags;</div>
+<div class="line"><a name="l07034"></a><span class="lineno"> 7034</span>&#160;    VkBuffer hBuffer;</div>
+<div class="line"><a name="l07035"></a><span class="lineno"> 7035</span>&#160;};</div>
+<div class="line"><a name="l07036"></a><span class="lineno"> 7036</span>&#160; </div>
+<div class="line"><a name="l07037"></a><span class="lineno"> 7037</span>&#160;<span class="keyword">class </span>VmaBlockVectorDefragmentationContext</div>
+<div class="line"><a name="l07038"></a><span class="lineno"> 7038</span>&#160;{</div>
+<div class="line"><a name="l07039"></a><span class="lineno"> 7039</span>&#160;    VMA_CLASS_NO_COPY(VmaBlockVectorDefragmentationContext)</div>
+<div class="line"><a name="l07040"></a><span class="lineno"> 7040</span>&#160;<span class="keyword">public</span>:</div>
+<div class="line"><a name="l07041"></a><span class="lineno"> 7041</span>&#160;    VkResult res;</div>
+<div class="line"><a name="l07042"></a><span class="lineno"> 7042</span>&#160;    <span class="keywordtype">bool</span> mutexLocked;</div>
+<div class="line"><a name="l07043"></a><span class="lineno"> 7043</span>&#160;    VmaVector&lt; VmaBlockDefragmentationContext, VmaStlAllocator&lt;VmaBlockDefragmentationContext&gt; &gt; blockContexts;</div>
+<div class="line"><a name="l07044"></a><span class="lineno"> 7044</span>&#160;    VmaVector&lt; VmaDefragmentationMove, VmaStlAllocator&lt;VmaDefragmentationMove&gt; &gt; defragmentationMoves;</div>
+<div class="line"><a name="l07045"></a><span class="lineno"> 7045</span>&#160;    uint32_t defragmentationMovesProcessed;</div>
+<div class="line"><a name="l07046"></a><span class="lineno"> 7046</span>&#160;    uint32_t defragmentationMovesCommitted;</div>
+<div class="line"><a name="l07047"></a><span class="lineno"> 7047</span>&#160;    <span class="keywordtype">bool</span> hasDefragmentationPlan;</div>
+<div class="line"><a name="l07048"></a><span class="lineno"> 7048</span>&#160; </div>
+<div class="line"><a name="l07049"></a><span class="lineno"> 7049</span>&#160;    VmaBlockVectorDefragmentationContext(</div>
+<div class="line"><a name="l07050"></a><span class="lineno"> 7050</span>&#160;        <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator,</div>
+<div class="line"><a name="l07051"></a><span class="lineno"> 7051</span>&#160;        <a class="code" href="struct_vma_pool.html">VmaPool</a> hCustomPool, <span class="comment">// Optional.</span></div>
+<div class="line"><a name="l07052"></a><span class="lineno"> 7052</span>&#160;        VmaBlockVector* pBlockVector,</div>
+<div class="line"><a name="l07053"></a><span class="lineno"> 7053</span>&#160;        uint32_t currFrameIndex);</div>
+<div class="line"><a name="l07054"></a><span class="lineno"> 7054</span>&#160;    ~VmaBlockVectorDefragmentationContext();</div>
+<div class="line"><a name="l07055"></a><span class="lineno"> 7055</span>&#160; </div>
+<div class="line"><a name="l07056"></a><span class="lineno"> 7056</span>&#160;    <a class="code" href="struct_vma_pool.html">VmaPool</a> GetCustomPool()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_hCustomPool; }</div>
+<div class="line"><a name="l07057"></a><span class="lineno"> 7057</span>&#160;    VmaBlockVector* GetBlockVector()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_pBlockVector; }</div>
+<div class="line"><a name="l07058"></a><span class="lineno"> 7058</span>&#160;    VmaDefragmentationAlgorithm* GetAlgorithm()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_pAlgorithm; }</div>
+<div class="line"><a name="l07059"></a><span class="lineno"> 7059</span>&#160; </div>
+<div class="line"><a name="l07060"></a><span class="lineno"> 7060</span>&#160;    <span class="keywordtype">void</span> AddAllocation(<a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAlloc, VkBool32* pChanged);</div>
+<div class="line"><a name="l07061"></a><span class="lineno"> 7061</span>&#160;    <span class="keywordtype">void</span> AddAll() { m_AllAllocations = <span class="keyword">true</span>; }</div>
+<div class="line"><a name="l07062"></a><span class="lineno"> 7062</span>&#160; </div>
+<div class="line"><a name="l07063"></a><span class="lineno"> 7063</span>&#160;    <span class="keywordtype">void</span> Begin(<span class="keywordtype">bool</span> overlappingMoveSupported, <a class="code" href="vk__mem__alloc_8h.html#a88a77cef37e5d3c4fc9eb328885d048d">VmaDefragmentationFlags</a> flags);</div>
+<div class="line"><a name="l07064"></a><span class="lineno"> 7064</span>&#160; </div>
+<div class="line"><a name="l07065"></a><span class="lineno"> 7065</span>&#160;<span class="keyword">private</span>:</div>
+<div class="line"><a name="l07066"></a><span class="lineno"> 7066</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> m_hAllocator;</div>
+<div class="line"><a name="l07067"></a><span class="lineno"> 7067</span>&#160;    <span class="comment">// Null if not from custom pool.</span></div>
+<div class="line"><a name="l07068"></a><span class="lineno"> 7068</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_pool.html">VmaPool</a> m_hCustomPool;</div>
+<div class="line"><a name="l07069"></a><span class="lineno"> 7069</span>&#160;    <span class="comment">// Redundant, for convenience not to fetch from m_hCustomPool-&gt;m_BlockVector or m_hAllocator-&gt;m_pBlockVectors.</span></div>
+<div class="line"><a name="l07070"></a><span class="lineno"> 7070</span>&#160;    VmaBlockVector* <span class="keyword">const</span> m_pBlockVector;</div>
+<div class="line"><a name="l07071"></a><span class="lineno"> 7071</span>&#160;    <span class="keyword">const</span> uint32_t m_CurrFrameIndex;</div>
+<div class="line"><a name="l07072"></a><span class="lineno"> 7072</span>&#160;    <span class="comment">// Owner of this object.</span></div>
+<div class="line"><a name="l07073"></a><span class="lineno"> 7073</span>&#160;    VmaDefragmentationAlgorithm* m_pAlgorithm;</div>
+<div class="line"><a name="l07074"></a><span class="lineno"> 7074</span>&#160; </div>
+<div class="line"><a name="l07075"></a><span class="lineno"> 7075</span>&#160;    <span class="keyword">struct </span>AllocInfo</div>
+<div class="line"><a name="l07076"></a><span class="lineno"> 7076</span>&#160;    {</div>
+<div class="line"><a name="l07077"></a><span class="lineno"> 7077</span>&#160;        <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAlloc;</div>
+<div class="line"><a name="l07078"></a><span class="lineno"> 7078</span>&#160;        VkBool32* pChanged;</div>
+<div class="line"><a name="l07079"></a><span class="lineno"> 7079</span>&#160;    };</div>
+<div class="line"><a name="l07080"></a><span class="lineno"> 7080</span>&#160;    <span class="comment">// Used between constructor and Begin.</span></div>
+<div class="line"><a name="l07081"></a><span class="lineno"> 7081</span>&#160;    VmaVector&lt; AllocInfo, VmaStlAllocator&lt;AllocInfo&gt; &gt; m_Allocations;</div>
+<div class="line"><a name="l07082"></a><span class="lineno"> 7082</span>&#160;    <span class="keywordtype">bool</span> m_AllAllocations;</div>
+<div class="line"><a name="l07083"></a><span class="lineno"> 7083</span>&#160;};</div>
+<div class="line"><a name="l07084"></a><span class="lineno"> 7084</span>&#160; </div>
+<div class="line"><a name="l07085"></a><span class="lineno"> 7085</span>&#160;<span class="keyword">struct </span>VmaDefragmentationContext_T</div>
+<div class="line"><a name="l07086"></a><span class="lineno"> 7086</span>&#160;{</div>
+<div class="line"><a name="l07087"></a><span class="lineno"> 7087</span>&#160;<span class="keyword">private</span>:</div>
+<div class="line"><a name="l07088"></a><span class="lineno"> 7088</span>&#160;    VMA_CLASS_NO_COPY(VmaDefragmentationContext_T)</div>
+<div class="line"><a name="l07089"></a><span class="lineno"> 7089</span>&#160;<span class="keyword">public</span>:</div>
+<div class="line"><a name="l07090"></a><span class="lineno"> 7090</span>&#160;    VmaDefragmentationContext_T(</div>
+<div class="line"><a name="l07091"></a><span class="lineno"> 7091</span>&#160;        <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator,</div>
+<div class="line"><a name="l07092"></a><span class="lineno"> 7092</span>&#160;        uint32_t currFrameIndex,</div>
+<div class="line"><a name="l07093"></a><span class="lineno"> 7093</span>&#160;        uint32_t flags,</div>
+<div class="line"><a name="l07094"></a><span class="lineno"> 7094</span>&#160;        <a class="code" href="struct_vma_defragmentation_stats.html">VmaDefragmentationStats</a>* pStats);</div>
+<div class="line"><a name="l07095"></a><span class="lineno"> 7095</span>&#160;    ~VmaDefragmentationContext_T();</div>
+<div class="line"><a name="l07096"></a><span class="lineno"> 7096</span>&#160; </div>
+<div class="line"><a name="l07097"></a><span class="lineno"> 7097</span>&#160;    <span class="keywordtype">void</span> AddPools(uint32_t poolCount, <a class="code" href="struct_vma_pool.html">VmaPool</a>* pPools);</div>
+<div class="line"><a name="l07098"></a><span class="lineno"> 7098</span>&#160;    <span class="keywordtype">void</span> AddAllocations(</div>
+<div class="line"><a name="l07099"></a><span class="lineno"> 7099</span>&#160;        uint32_t allocationCount,</div>
+<div class="line"><a name="l07100"></a><span class="lineno"> 7100</span>&#160;        <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocations,</div>
+<div class="line"><a name="l07101"></a><span class="lineno"> 7101</span>&#160;        VkBool32* pAllocationsChanged);</div>
+<div class="line"><a name="l07102"></a><span class="lineno"> 7102</span>&#160; </div>
+<div class="line"><a name="l07103"></a><span class="lineno"> 7103</span>&#160;    <span class="comment">/*</span></div>
+<div class="line"><a name="l07104"></a><span class="lineno"> 7104</span>&#160;<span class="comment">    Returns:</span></div>
+<div class="line"><a name="l07105"></a><span class="lineno"> 7105</span>&#160;<span class="comment">    - `VK_SUCCESS` if succeeded and object can be destroyed immediately.</span></div>
+<div class="line"><a name="l07106"></a><span class="lineno"> 7106</span>&#160;<span class="comment">    - `VK_NOT_READY` if succeeded but the object must remain alive until vmaDefragmentationEnd().</span></div>
+<div class="line"><a name="l07107"></a><span class="lineno"> 7107</span>&#160;<span class="comment">    - Negative value if error occured and object can be destroyed immediately.</span></div>
+<div class="line"><a name="l07108"></a><span class="lineno"> 7108</span>&#160;<span class="comment">    */</span></div>
+<div class="line"><a name="l07109"></a><span class="lineno"> 7109</span>&#160;    VkResult Defragment(</div>
+<div class="line"><a name="l07110"></a><span class="lineno"> 7110</span>&#160;        VkDeviceSize maxCpuBytesToMove, uint32_t maxCpuAllocationsToMove,</div>
+<div class="line"><a name="l07111"></a><span class="lineno"> 7111</span>&#160;        VkDeviceSize maxGpuBytesToMove, uint32_t maxGpuAllocationsToMove,</div>
+<div class="line"><a name="l07112"></a><span class="lineno"> 7112</span>&#160;        VkCommandBuffer commandBuffer, <a class="code" href="struct_vma_defragmentation_stats.html">VmaDefragmentationStats</a>* pStats, <a class="code" href="vk__mem__alloc_8h.html#a88a77cef37e5d3c4fc9eb328885d048d">VmaDefragmentationFlags</a> flags);</div>
+<div class="line"><a name="l07113"></a><span class="lineno"> 7113</span>&#160; </div>
+<div class="line"><a name="l07114"></a><span class="lineno"> 7114</span>&#160;    VkResult DefragmentPassBegin(<a class="code" href="struct_vma_defragmentation_pass_info.html">VmaDefragmentationPassInfo</a>* pInfo);</div>
+<div class="line"><a name="l07115"></a><span class="lineno"> 7115</span>&#160;    VkResult DefragmentPassEnd();</div>
+<div class="line"><a name="l07116"></a><span class="lineno"> 7116</span>&#160; </div>
+<div class="line"><a name="l07117"></a><span class="lineno"> 7117</span>&#160;<span class="keyword">private</span>:</div>
+<div class="line"><a name="l07118"></a><span class="lineno"> 7118</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> m_hAllocator;</div>
+<div class="line"><a name="l07119"></a><span class="lineno"> 7119</span>&#160;    <span class="keyword">const</span> uint32_t m_CurrFrameIndex;</div>
+<div class="line"><a name="l07120"></a><span class="lineno"> 7120</span>&#160;    <span class="keyword">const</span> uint32_t m_Flags;</div>
+<div class="line"><a name="l07121"></a><span class="lineno"> 7121</span>&#160;    <a class="code" href="struct_vma_defragmentation_stats.html">VmaDefragmentationStats</a>* <span class="keyword">const</span> m_pStats;</div>
+<div class="line"><a name="l07122"></a><span class="lineno"> 7122</span>&#160; </div>
+<div class="line"><a name="l07123"></a><span class="lineno"> 7123</span>&#160;    VkDeviceSize m_MaxCpuBytesToMove;</div>
+<div class="line"><a name="l07124"></a><span class="lineno"> 7124</span>&#160;    uint32_t m_MaxCpuAllocationsToMove;</div>
+<div class="line"><a name="l07125"></a><span class="lineno"> 7125</span>&#160;    VkDeviceSize m_MaxGpuBytesToMove;</div>
+<div class="line"><a name="l07126"></a><span class="lineno"> 7126</span>&#160;    uint32_t m_MaxGpuAllocationsToMove;</div>
+<div class="line"><a name="l07127"></a><span class="lineno"> 7127</span>&#160; </div>
+<div class="line"><a name="l07128"></a><span class="lineno"> 7128</span>&#160;    <span class="comment">// Owner of these objects.</span></div>
+<div class="line"><a name="l07129"></a><span class="lineno"> 7129</span>&#160;    VmaBlockVectorDefragmentationContext* m_DefaultPoolContexts[VK_MAX_MEMORY_TYPES];</div>
+<div class="line"><a name="l07130"></a><span class="lineno"> 7130</span>&#160;    <span class="comment">// Owner of these objects.</span></div>
+<div class="line"><a name="l07131"></a><span class="lineno"> 7131</span>&#160;    VmaVector&lt; VmaBlockVectorDefragmentationContext*, VmaStlAllocator&lt;VmaBlockVectorDefragmentationContext*&gt; &gt; m_CustomPoolContexts;</div>
+<div class="line"><a name="l07132"></a><span class="lineno"> 7132</span>&#160;};</div>
+<div class="line"><a name="l07133"></a><span class="lineno"> 7133</span>&#160; </div>
+<div class="line"><a name="l07134"></a><span class="lineno"> 7134</span>&#160;<span class="preprocessor">#if VMA_RECORDING_ENABLED</span></div>
+<div class="line"><a name="l07135"></a><span class="lineno"> 7135</span>&#160; </div>
+<div class="line"><a name="l07136"></a><span class="lineno"> 7136</span>&#160;<span class="keyword">class </span>VmaRecorder</div>
+<div class="line"><a name="l07137"></a><span class="lineno"> 7137</span>&#160;{</div>
+<div class="line"><a name="l07138"></a><span class="lineno"> 7138</span>&#160;<span class="keyword">public</span>:</div>
+<div class="line"><a name="l07139"></a><span class="lineno"> 7139</span>&#160;    VmaRecorder();</div>
+<div class="line"><a name="l07140"></a><span class="lineno"> 7140</span>&#160;    VkResult Init(<span class="keyword">const</span> <a class="code" href="struct_vma_record_settings.html">VmaRecordSettings</a>&amp; settings, <span class="keywordtype">bool</span> useMutex);</div>
+<div class="line"><a name="l07141"></a><span class="lineno"> 7141</span>&#160;    <span class="keywordtype">void</span> WriteConfiguration(</div>
+<div class="line"><a name="l07142"></a><span class="lineno"> 7142</span>&#160;        <span class="keyword">const</span> VkPhysicalDeviceProperties&amp; devProps,</div>
+<div class="line"><a name="l07143"></a><span class="lineno"> 7143</span>&#160;        <span class="keyword">const</span> VkPhysicalDeviceMemoryProperties&amp; memProps,</div>
+<div class="line"><a name="l07144"></a><span class="lineno"> 7144</span>&#160;        uint32_t vulkanApiVersion,</div>
+<div class="line"><a name="l07145"></a><span class="lineno"> 7145</span>&#160;        <span class="keywordtype">bool</span> dedicatedAllocationExtensionEnabled,</div>
+<div class="line"><a name="l07146"></a><span class="lineno"> 7146</span>&#160;        <span class="keywordtype">bool</span> bindMemory2ExtensionEnabled,</div>
+<div class="line"><a name="l07147"></a><span class="lineno"> 7147</span>&#160;        <span class="keywordtype">bool</span> memoryBudgetExtensionEnabled,</div>
+<div class="line"><a name="l07148"></a><span class="lineno"> 7148</span>&#160;        <span class="keywordtype">bool</span> deviceCoherentMemoryExtensionEnabled);</div>
+<div class="line"><a name="l07149"></a><span class="lineno"> 7149</span>&#160;    ~VmaRecorder();</div>
+<div class="line"><a name="l07150"></a><span class="lineno"> 7150</span>&#160; </div>
+<div class="line"><a name="l07151"></a><span class="lineno"> 7151</span>&#160;    <span class="keywordtype">void</span> RecordCreateAllocator(uint32_t frameIndex);</div>
+<div class="line"><a name="l07152"></a><span class="lineno"> 7152</span>&#160;    <span class="keywordtype">void</span> RecordDestroyAllocator(uint32_t frameIndex);</div>
+<div class="line"><a name="l07153"></a><span class="lineno"> 7153</span>&#160;    <span class="keywordtype">void</span> RecordCreatePool(uint32_t frameIndex,</div>
+<div class="line"><a name="l07154"></a><span class="lineno"> 7154</span>&#160;        <span class="keyword">const</span> <a class="code" href="struct_vma_pool_create_info.html">VmaPoolCreateInfo</a>&amp; createInfo,</div>
+<div class="line"><a name="l07155"></a><span class="lineno"> 7155</span>&#160;        <a class="code" href="struct_vma_pool.html">VmaPool</a> pool);</div>
+<div class="line"><a name="l07156"></a><span class="lineno"> 7156</span>&#160;    <span class="keywordtype">void</span> RecordDestroyPool(uint32_t frameIndex, <a class="code" href="struct_vma_pool.html">VmaPool</a> pool);</div>
+<div class="line"><a name="l07157"></a><span class="lineno"> 7157</span>&#160;    <span class="keywordtype">void</span> RecordAllocateMemory(uint32_t frameIndex,</div>
+<div class="line"><a name="l07158"></a><span class="lineno"> 7158</span>&#160;        <span class="keyword">const</span> VkMemoryRequirements&amp; vkMemReq,</div>
+<div class="line"><a name="l07159"></a><span class="lineno"> 7159</span>&#160;        <span class="keyword">const</span> <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>&amp; createInfo,</div>
+<div class="line"><a name="l07160"></a><span class="lineno"> 7160</span>&#160;        <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation);</div>
+<div class="line"><a name="l07161"></a><span class="lineno"> 7161</span>&#160;    <span class="keywordtype">void</span> RecordAllocateMemoryPages(uint32_t frameIndex,</div>
+<div class="line"><a name="l07162"></a><span class="lineno"> 7162</span>&#160;        <span class="keyword">const</span> VkMemoryRequirements&amp; vkMemReq,</div>
+<div class="line"><a name="l07163"></a><span class="lineno"> 7163</span>&#160;        <span class="keyword">const</span> <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>&amp; createInfo,</div>
+<div class="line"><a name="l07164"></a><span class="lineno"> 7164</span>&#160;        uint64_t allocationCount,</div>
+<div class="line"><a name="l07165"></a><span class="lineno"> 7165</span>&#160;        <span class="keyword">const</span> <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocations);</div>
+<div class="line"><a name="l07166"></a><span class="lineno"> 7166</span>&#160;    <span class="keywordtype">void</span> RecordAllocateMemoryForBuffer(uint32_t frameIndex,</div>
+<div class="line"><a name="l07167"></a><span class="lineno"> 7167</span>&#160;        <span class="keyword">const</span> VkMemoryRequirements&amp; vkMemReq,</div>
+<div class="line"><a name="l07168"></a><span class="lineno"> 7168</span>&#160;        <span class="keywordtype">bool</span> requiresDedicatedAllocation,</div>
+<div class="line"><a name="l07169"></a><span class="lineno"> 7169</span>&#160;        <span class="keywordtype">bool</span> prefersDedicatedAllocation,</div>
+<div class="line"><a name="l07170"></a><span class="lineno"> 7170</span>&#160;        <span class="keyword">const</span> <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>&amp; createInfo,</div>
+<div class="line"><a name="l07171"></a><span class="lineno"> 7171</span>&#160;        <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation);</div>
+<div class="line"><a name="l07172"></a><span class="lineno"> 7172</span>&#160;    <span class="keywordtype">void</span> RecordAllocateMemoryForImage(uint32_t frameIndex,</div>
+<div class="line"><a name="l07173"></a><span class="lineno"> 7173</span>&#160;        <span class="keyword">const</span> VkMemoryRequirements&amp; vkMemReq,</div>
+<div class="line"><a name="l07174"></a><span class="lineno"> 7174</span>&#160;        <span class="keywordtype">bool</span> requiresDedicatedAllocation,</div>
+<div class="line"><a name="l07175"></a><span class="lineno"> 7175</span>&#160;        <span class="keywordtype">bool</span> prefersDedicatedAllocation,</div>
+<div class="line"><a name="l07176"></a><span class="lineno"> 7176</span>&#160;        <span class="keyword">const</span> <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>&amp; createInfo,</div>
+<div class="line"><a name="l07177"></a><span class="lineno"> 7177</span>&#160;        <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation);</div>
+<div class="line"><a name="l07178"></a><span class="lineno"> 7178</span>&#160;    <span class="keywordtype">void</span> RecordFreeMemory(uint32_t frameIndex,</div>
+<div class="line"><a name="l07179"></a><span class="lineno"> 7179</span>&#160;        <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation);</div>
+<div class="line"><a name="l07180"></a><span class="lineno"> 7180</span>&#160;    <span class="keywordtype">void</span> RecordFreeMemoryPages(uint32_t frameIndex,</div>
+<div class="line"><a name="l07181"></a><span class="lineno"> 7181</span>&#160;        uint64_t allocationCount,</div>
+<div class="line"><a name="l07182"></a><span class="lineno"> 7182</span>&#160;        <span class="keyword">const</span> <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocations);</div>
+<div class="line"><a name="l07183"></a><span class="lineno"> 7183</span>&#160;    <span class="keywordtype">void</span> RecordSetAllocationUserData(uint32_t frameIndex,</div>
+<div class="line"><a name="l07184"></a><span class="lineno"> 7184</span>&#160;        <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation,</div>
+<div class="line"><a name="l07185"></a><span class="lineno"> 7185</span>&#160;        <span class="keyword">const</span> <span class="keywordtype">void</span>* pUserData);</div>
+<div class="line"><a name="l07186"></a><span class="lineno"> 7186</span>&#160;    <span class="keywordtype">void</span> RecordCreateLostAllocation(uint32_t frameIndex,</div>
+<div class="line"><a name="l07187"></a><span class="lineno"> 7187</span>&#160;        <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation);</div>
+<div class="line"><a name="l07188"></a><span class="lineno"> 7188</span>&#160;    <span class="keywordtype">void</span> RecordMapMemory(uint32_t frameIndex,</div>
+<div class="line"><a name="l07189"></a><span class="lineno"> 7189</span>&#160;        <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation);</div>
+<div class="line"><a name="l07190"></a><span class="lineno"> 7190</span>&#160;    <span class="keywordtype">void</span> RecordUnmapMemory(uint32_t frameIndex,</div>
+<div class="line"><a name="l07191"></a><span class="lineno"> 7191</span>&#160;        <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation);</div>
+<div class="line"><a name="l07192"></a><span class="lineno"> 7192</span>&#160;    <span class="keywordtype">void</span> RecordFlushAllocation(uint32_t frameIndex,</div>
+<div class="line"><a name="l07193"></a><span class="lineno"> 7193</span>&#160;        <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation, VkDeviceSize offset, VkDeviceSize size);</div>
+<div class="line"><a name="l07194"></a><span class="lineno"> 7194</span>&#160;    <span class="keywordtype">void</span> RecordInvalidateAllocation(uint32_t frameIndex,</div>
+<div class="line"><a name="l07195"></a><span class="lineno"> 7195</span>&#160;        <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation, VkDeviceSize offset, VkDeviceSize size);</div>
+<div class="line"><a name="l07196"></a><span class="lineno"> 7196</span>&#160;    <span class="keywordtype">void</span> RecordCreateBuffer(uint32_t frameIndex,</div>
+<div class="line"><a name="l07197"></a><span class="lineno"> 7197</span>&#160;        <span class="keyword">const</span> VkBufferCreateInfo&amp; bufCreateInfo,</div>
+<div class="line"><a name="l07198"></a><span class="lineno"> 7198</span>&#160;        <span class="keyword">const</span> <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>&amp; allocCreateInfo,</div>
+<div class="line"><a name="l07199"></a><span class="lineno"> 7199</span>&#160;        <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation);</div>
+<div class="line"><a name="l07200"></a><span class="lineno"> 7200</span>&#160;    <span class="keywordtype">void</span> RecordCreateImage(uint32_t frameIndex,</div>
+<div class="line"><a name="l07201"></a><span class="lineno"> 7201</span>&#160;        <span class="keyword">const</span> VkImageCreateInfo&amp; imageCreateInfo,</div>
+<div class="line"><a name="l07202"></a><span class="lineno"> 7202</span>&#160;        <span class="keyword">const</span> <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>&amp; allocCreateInfo,</div>
+<div class="line"><a name="l07203"></a><span class="lineno"> 7203</span>&#160;        <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation);</div>
+<div class="line"><a name="l07204"></a><span class="lineno"> 7204</span>&#160;    <span class="keywordtype">void</span> RecordDestroyBuffer(uint32_t frameIndex,</div>
+<div class="line"><a name="l07205"></a><span class="lineno"> 7205</span>&#160;        <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation);</div>
+<div class="line"><a name="l07206"></a><span class="lineno"> 7206</span>&#160;    <span class="keywordtype">void</span> RecordDestroyImage(uint32_t frameIndex,</div>
+<div class="line"><a name="l07207"></a><span class="lineno"> 7207</span>&#160;        <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation);</div>
+<div class="line"><a name="l07208"></a><span class="lineno"> 7208</span>&#160;    <span class="keywordtype">void</span> RecordTouchAllocation(uint32_t frameIndex,</div>
+<div class="line"><a name="l07209"></a><span class="lineno"> 7209</span>&#160;        <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation);</div>
+<div class="line"><a name="l07210"></a><span class="lineno"> 7210</span>&#160;    <span class="keywordtype">void</span> RecordGetAllocationInfo(uint32_t frameIndex,</div>
+<div class="line"><a name="l07211"></a><span class="lineno"> 7211</span>&#160;        <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation);</div>
+<div class="line"><a name="l07212"></a><span class="lineno"> 7212</span>&#160;    <span class="keywordtype">void</span> RecordMakePoolAllocationsLost(uint32_t frameIndex,</div>
+<div class="line"><a name="l07213"></a><span class="lineno"> 7213</span>&#160;        <a class="code" href="struct_vma_pool.html">VmaPool</a> pool);</div>
+<div class="line"><a name="l07214"></a><span class="lineno"> 7214</span>&#160;    <span class="keywordtype">void</span> RecordDefragmentationBegin(uint32_t frameIndex,</div>
+<div class="line"><a name="l07215"></a><span class="lineno"> 7215</span>&#160;        <span class="keyword">const</span> <a class="code" href="struct_vma_defragmentation_info2.html">VmaDefragmentationInfo2</a>&amp; info,</div>
+<div class="line"><a name="l07216"></a><span class="lineno"> 7216</span>&#160;        <a class="code" href="struct_vma_defragmentation_context.html">VmaDefragmentationContext</a> ctx);</div>
+<div class="line"><a name="l07217"></a><span class="lineno"> 7217</span>&#160;    <span class="keywordtype">void</span> RecordDefragmentationEnd(uint32_t frameIndex,</div>
+<div class="line"><a name="l07218"></a><span class="lineno"> 7218</span>&#160;        <a class="code" href="struct_vma_defragmentation_context.html">VmaDefragmentationContext</a> ctx);</div>
+<div class="line"><a name="l07219"></a><span class="lineno"> 7219</span>&#160;    <span class="keywordtype">void</span> RecordSetPoolName(uint32_t frameIndex,</div>
+<div class="line"><a name="l07220"></a><span class="lineno"> 7220</span>&#160;        <a class="code" href="struct_vma_pool.html">VmaPool</a> pool,</div>
+<div class="line"><a name="l07221"></a><span class="lineno"> 7221</span>&#160;        <span class="keyword">const</span> <span class="keywordtype">char</span>* name);</div>
+<div class="line"><a name="l07222"></a><span class="lineno"> 7222</span>&#160; </div>
+<div class="line"><a name="l07223"></a><span class="lineno"> 7223</span>&#160;<span class="keyword">private</span>:</div>
+<div class="line"><a name="l07224"></a><span class="lineno"> 7224</span>&#160;    <span class="keyword">struct </span>CallParams</div>
+<div class="line"><a name="l07225"></a><span class="lineno"> 7225</span>&#160;    {</div>
+<div class="line"><a name="l07226"></a><span class="lineno"> 7226</span>&#160;        uint32_t threadId;</div>
+<div class="line"><a name="l07227"></a><span class="lineno"> 7227</span>&#160;        <span class="keywordtype">double</span> time;</div>
+<div class="line"><a name="l07228"></a><span class="lineno"> 7228</span>&#160;    };</div>
+<div class="line"><a name="l07229"></a><span class="lineno"> 7229</span>&#160; </div>
+<div class="line"><a name="l07230"></a><span class="lineno"> 7230</span>&#160;    <span class="keyword">class </span>UserDataString</div>
+<div class="line"><a name="l07231"></a><span class="lineno"> 7231</span>&#160;    {</div>
+<div class="line"><a name="l07232"></a><span class="lineno"> 7232</span>&#160;    <span class="keyword">public</span>:</div>
+<div class="line"><a name="l07233"></a><span class="lineno"> 7233</span>&#160;        UserDataString(<a class="code" href="vk__mem__alloc_8h.html#a5225e5e11f8376f6a31a1791f3d6e817">VmaAllocationCreateFlags</a> allocFlags, <span class="keyword">const</span> <span class="keywordtype">void</span>* pUserData);</div>
+<div class="line"><a name="l07234"></a><span class="lineno"> 7234</span>&#160;        <span class="keyword">const</span> <span class="keywordtype">char</span>* GetString()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_Str; }</div>
+<div class="line"><a name="l07235"></a><span class="lineno"> 7235</span>&#160; </div>
+<div class="line"><a name="l07236"></a><span class="lineno"> 7236</span>&#160;    <span class="keyword">private</span>:</div>
+<div class="line"><a name="l07237"></a><span class="lineno"> 7237</span>&#160;        <span class="keywordtype">char</span> m_PtrStr[17];</div>
+<div class="line"><a name="l07238"></a><span class="lineno"> 7238</span>&#160;        <span class="keyword">const</span> <span class="keywordtype">char</span>* m_Str;</div>
+<div class="line"><a name="l07239"></a><span class="lineno"> 7239</span>&#160;    };</div>
+<div class="line"><a name="l07240"></a><span class="lineno"> 7240</span>&#160; </div>
+<div class="line"><a name="l07241"></a><span class="lineno"> 7241</span>&#160;    <span class="keywordtype">bool</span> m_UseMutex;</div>
+<div class="line"><a name="l07242"></a><span class="lineno"> 7242</span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#af3929a1a4547c592fc0b0e55ef452828">VmaRecordFlags</a> m_Flags;</div>
+<div class="line"><a name="l07243"></a><span class="lineno"> 7243</span>&#160;    FILE* m_File;</div>
+<div class="line"><a name="l07244"></a><span class="lineno"> 7244</span>&#160;    VMA_MUTEX m_FileMutex;</div>
+<div class="line"><a name="l07245"></a><span class="lineno"> 7245</span>&#160;    int64_t m_Freq;</div>
+<div class="line"><a name="l07246"></a><span class="lineno"> 7246</span>&#160;    int64_t m_StartCounter;</div>
+<div class="line"><a name="l07247"></a><span class="lineno"> 7247</span>&#160; </div>
+<div class="line"><a name="l07248"></a><span class="lineno"> 7248</span>&#160;    <span class="keywordtype">void</span> GetBasicParams(CallParams&amp; outParams);</div>
+<div class="line"><a name="l07249"></a><span class="lineno"> 7249</span>&#160; </div>
+<div class="line"><a name="l07250"></a><span class="lineno"> 7250</span>&#160;    <span class="comment">// T must be a pointer type, e.g. VmaAllocation, VmaPool.</span></div>
+<div class="line"><a name="l07251"></a><span class="lineno"> 7251</span>&#160;    <span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</div>
+<div class="line"><a name="l07252"></a><span class="lineno"> 7252</span>&#160;    <span class="keywordtype">void</span> PrintPointerList(uint64_t count, <span class="keyword">const</span> T* pItems)</div>
+<div class="line"><a name="l07253"></a><span class="lineno"> 7253</span>&#160;    {</div>
+<div class="line"><a name="l07254"></a><span class="lineno"> 7254</span>&#160;        <span class="keywordflow">if</span>(count)</div>
+<div class="line"><a name="l07255"></a><span class="lineno"> 7255</span>&#160;        {</div>
+<div class="line"><a name="l07256"></a><span class="lineno"> 7256</span>&#160;            fprintf(m_File, <span class="stringliteral">&quot;%p&quot;</span>, pItems[0]);</div>
+<div class="line"><a name="l07257"></a><span class="lineno"> 7257</span>&#160;            <span class="keywordflow">for</span>(uint64_t i = 1; i &lt; count; ++i)</div>
+<div class="line"><a name="l07258"></a><span class="lineno"> 7258</span>&#160;            {</div>
+<div class="line"><a name="l07259"></a><span class="lineno"> 7259</span>&#160;                fprintf(m_File, <span class="stringliteral">&quot; %p&quot;</span>, pItems[i]);</div>
+<div class="line"><a name="l07260"></a><span class="lineno"> 7260</span>&#160;            }</div>
+<div class="line"><a name="l07261"></a><span class="lineno"> 7261</span>&#160;        }</div>
+<div class="line"><a name="l07262"></a><span class="lineno"> 7262</span>&#160;    }</div>
+<div class="line"><a name="l07263"></a><span class="lineno"> 7263</span>&#160; </div>
+<div class="line"><a name="l07264"></a><span class="lineno"> 7264</span>&#160;    <span class="keywordtype">void</span> PrintPointerList(uint64_t count, <span class="keyword">const</span> <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pItems);</div>
+<div class="line"><a name="l07265"></a><span class="lineno"> 7265</span>&#160;    <span class="keywordtype">void</span> Flush();</div>
+<div class="line"><a name="l07266"></a><span class="lineno"> 7266</span>&#160;};</div>
+<div class="line"><a name="l07267"></a><span class="lineno"> 7267</span>&#160; </div>
+<div class="line"><a name="l07268"></a><span class="lineno"> 7268</span>&#160;<span class="preprocessor">#endif // #if VMA_RECORDING_ENABLED</span></div>
+<div class="line"><a name="l07269"></a><span class="lineno"> 7269</span>&#160; </div>
+<div class="line"><a name="l07270"></a><span class="lineno"> 7270</span>&#160;<span class="comment">/*</span></div>
+<div class="line"><a name="l07271"></a><span class="lineno"> 7271</span>&#160;<span class="comment">Thread-safe wrapper over VmaPoolAllocator free list, for allocation of VmaAllocation_T objects.</span></div>
+<div class="line"><a name="l07272"></a><span class="lineno"> 7272</span>&#160;<span class="comment">*/</span></div>
+<div class="line"><a name="l07273"></a><span class="lineno"> 7273</span>&#160;<span class="keyword">class </span>VmaAllocationObjectAllocator</div>
+<div class="line"><a name="l07274"></a><span class="lineno"> 7274</span>&#160;{</div>
+<div class="line"><a name="l07275"></a><span class="lineno"> 7275</span>&#160;    VMA_CLASS_NO_COPY(VmaAllocationObjectAllocator)</div>
+<div class="line"><a name="l07276"></a><span class="lineno"> 7276</span>&#160;<span class="keyword">public</span>:</div>
+<div class="line"><a name="l07277"></a><span class="lineno"> 7277</span>&#160;    VmaAllocationObjectAllocator(<span class="keyword">const</span> VkAllocationCallbacks* pAllocationCallbacks);</div>
+<div class="line"><a name="l07278"></a><span class="lineno"> 7278</span>&#160; </div>
+<div class="line"><a name="l07279"></a><span class="lineno"> 7279</span>&#160;    <span class="keyword">template</span>&lt;<span class="keyword">typename</span>... Types&gt; <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> Allocate(Types... args);</div>
+<div class="line"><a name="l07280"></a><span class="lineno"> 7280</span>&#160;    <span class="keywordtype">void</span> Free(<a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAlloc);</div>
+<div class="line"><a name="l07281"></a><span class="lineno"> 7281</span>&#160; </div>
+<div class="line"><a name="l07282"></a><span class="lineno"> 7282</span>&#160;<span class="keyword">private</span>:</div>
+<div class="line"><a name="l07283"></a><span class="lineno"> 7283</span>&#160;    VMA_MUTEX m_Mutex;</div>
+<div class="line"><a name="l07284"></a><span class="lineno"> 7284</span>&#160;    VmaPoolAllocator&lt;VmaAllocation_T&gt; m_Allocator;</div>
+<div class="line"><a name="l07285"></a><span class="lineno"> 7285</span>&#160;};</div>
+<div class="line"><a name="l07286"></a><span class="lineno"> 7286</span>&#160; </div>
+<div class="line"><a name="l07287"></a><span class="lineno"> 7287</span>&#160;<span class="keyword">struct </span>VmaCurrentBudgetData</div>
+<div class="line"><a name="l07288"></a><span class="lineno"> 7288</span>&#160;{</div>
+<div class="line"><a name="l07289"></a><span class="lineno"> 7289</span>&#160;    VMA_ATOMIC_UINT64 m_BlockBytes[VK_MAX_MEMORY_HEAPS];</div>
+<div class="line"><a name="l07290"></a><span class="lineno"> 7290</span>&#160;    VMA_ATOMIC_UINT64 m_AllocationBytes[VK_MAX_MEMORY_HEAPS];</div>
+<div class="line"><a name="l07291"></a><span class="lineno"> 7291</span>&#160; </div>
+<div class="line"><a name="l07292"></a><span class="lineno"> 7292</span>&#160;<span class="preprocessor">#if VMA_MEMORY_BUDGET</span></div>
+<div class="line"><a name="l07293"></a><span class="lineno"> 7293</span>&#160;    VMA_ATOMIC_UINT32 m_OperationsSinceBudgetFetch;</div>
+<div class="line"><a name="l07294"></a><span class="lineno"> 7294</span>&#160;    VMA_RW_MUTEX m_BudgetMutex;</div>
+<div class="line"><a name="l07295"></a><span class="lineno"> 7295</span>&#160;    uint64_t m_VulkanUsage[VK_MAX_MEMORY_HEAPS];</div>
+<div class="line"><a name="l07296"></a><span class="lineno"> 7296</span>&#160;    uint64_t m_VulkanBudget[VK_MAX_MEMORY_HEAPS];</div>
+<div class="line"><a name="l07297"></a><span class="lineno"> 7297</span>&#160;    uint64_t m_BlockBytesAtBudgetFetch[VK_MAX_MEMORY_HEAPS];</div>
+<div class="line"><a name="l07298"></a><span class="lineno"> 7298</span>&#160;<span class="preprocessor">#endif // #if VMA_MEMORY_BUDGET</span></div>
+<div class="line"><a name="l07299"></a><span class="lineno"> 7299</span>&#160; </div>
+<div class="line"><a name="l07300"></a><span class="lineno"> 7300</span>&#160;    VmaCurrentBudgetData()</div>
+<div class="line"><a name="l07301"></a><span class="lineno"> 7301</span>&#160;    {</div>
+<div class="line"><a name="l07302"></a><span class="lineno"> 7302</span>&#160;        <span class="keywordflow">for</span>(uint32_t heapIndex = 0; heapIndex &lt; VK_MAX_MEMORY_HEAPS; ++heapIndex)</div>
+<div class="line"><a name="l07303"></a><span class="lineno"> 7303</span>&#160;        {</div>
+<div class="line"><a name="l07304"></a><span class="lineno"> 7304</span>&#160;            m_BlockBytes[heapIndex] = 0;</div>
+<div class="line"><a name="l07305"></a><span class="lineno"> 7305</span>&#160;            m_AllocationBytes[heapIndex] = 0;</div>
+<div class="line"><a name="l07306"></a><span class="lineno"> 7306</span>&#160;<span class="preprocessor">#if VMA_MEMORY_BUDGET</span></div>
+<div class="line"><a name="l07307"></a><span class="lineno"> 7307</span>&#160;            m_VulkanUsage[heapIndex] = 0;</div>
+<div class="line"><a name="l07308"></a><span class="lineno"> 7308</span>&#160;            m_VulkanBudget[heapIndex] = 0;</div>
+<div class="line"><a name="l07309"></a><span class="lineno"> 7309</span>&#160;            m_BlockBytesAtBudgetFetch[heapIndex] = 0;</div>
+<div class="line"><a name="l07310"></a><span class="lineno"> 7310</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l07311"></a><span class="lineno"> 7311</span>&#160;        }</div>
+<div class="line"><a name="l07312"></a><span class="lineno"> 7312</span>&#160; </div>
+<div class="line"><a name="l07313"></a><span class="lineno"> 7313</span>&#160;<span class="preprocessor">#if VMA_MEMORY_BUDGET</span></div>
+<div class="line"><a name="l07314"></a><span class="lineno"> 7314</span>&#160;        m_OperationsSinceBudgetFetch = 0;</div>
+<div class="line"><a name="l07315"></a><span class="lineno"> 7315</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l07316"></a><span class="lineno"> 7316</span>&#160;    }</div>
+<div class="line"><a name="l07317"></a><span class="lineno"> 7317</span>&#160; </div>
+<div class="line"><a name="l07318"></a><span class="lineno"> 7318</span>&#160;    <span class="keywordtype">void</span> AddAllocation(uint32_t heapIndex, VkDeviceSize allocationSize)</div>
+<div class="line"><a name="l07319"></a><span class="lineno"> 7319</span>&#160;    {</div>
+<div class="line"><a name="l07320"></a><span class="lineno"> 7320</span>&#160;        m_AllocationBytes[heapIndex] += allocationSize;</div>
+<div class="line"><a name="l07321"></a><span class="lineno"> 7321</span>&#160;<span class="preprocessor">#if VMA_MEMORY_BUDGET</span></div>
+<div class="line"><a name="l07322"></a><span class="lineno"> 7322</span>&#160;        ++m_OperationsSinceBudgetFetch;</div>
+<div class="line"><a name="l07323"></a><span class="lineno"> 7323</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l07324"></a><span class="lineno"> 7324</span>&#160;    }</div>
+<div class="line"><a name="l07325"></a><span class="lineno"> 7325</span>&#160; </div>
+<div class="line"><a name="l07326"></a><span class="lineno"> 7326</span>&#160;    <span class="keywordtype">void</span> RemoveAllocation(uint32_t heapIndex, VkDeviceSize allocationSize)</div>
+<div class="line"><a name="l07327"></a><span class="lineno"> 7327</span>&#160;    {</div>
+<div class="line"><a name="l07328"></a><span class="lineno"> 7328</span>&#160;        VMA_ASSERT(m_AllocationBytes[heapIndex] &gt;= allocationSize); <span class="comment">// DELME</span></div>
+<div class="line"><a name="l07329"></a><span class="lineno"> 7329</span>&#160;        m_AllocationBytes[heapIndex] -= allocationSize;</div>
+<div class="line"><a name="l07330"></a><span class="lineno"> 7330</span>&#160;<span class="preprocessor">#if VMA_MEMORY_BUDGET</span></div>
+<div class="line"><a name="l07331"></a><span class="lineno"> 7331</span>&#160;        ++m_OperationsSinceBudgetFetch;</div>
+<div class="line"><a name="l07332"></a><span class="lineno"> 7332</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l07333"></a><span class="lineno"> 7333</span>&#160;    }</div>
+<div class="line"><a name="l07334"></a><span class="lineno"> 7334</span>&#160;};</div>
+<div class="line"><a name="l07335"></a><span class="lineno"> 7335</span>&#160; </div>
+<div class="line"><a name="l07336"></a><span class="lineno"> 7336</span>&#160;<span class="comment">// Main allocator object.</span></div>
+<div class="line"><a name="l07337"></a><span class="lineno"> 7337</span>&#160;<span class="keyword">struct </span>VmaAllocator_T</div>
+<div class="line"><a name="l07338"></a><span class="lineno"> 7338</span>&#160;{</div>
+<div class="line"><a name="l07339"></a><span class="lineno"> 7339</span>&#160;    VMA_CLASS_NO_COPY(VmaAllocator_T)</div>
+<div class="line"><a name="l07340"></a><span class="lineno"> 7340</span>&#160;<span class="keyword">public</span>:</div>
+<div class="line"><a name="l07341"></a><span class="lineno"> 7341</span>&#160;    <span class="keywordtype">bool</span> m_UseMutex;</div>
+<div class="line"><a name="l07342"></a><span class="lineno"> 7342</span>&#160;    uint32_t m_VulkanApiVersion;</div>
+<div class="line"><a name="l07343"></a><span class="lineno"> 7343</span>&#160;    <span class="keywordtype">bool</span> m_UseKhrDedicatedAllocation; <span class="comment">// Can be set only if m_VulkanApiVersion &lt; VK_MAKE_VERSION(1, 1, 0).</span></div>
+<div class="line"><a name="l07344"></a><span class="lineno"> 7344</span>&#160;    <span class="keywordtype">bool</span> m_UseKhrBindMemory2; <span class="comment">// Can be set only if m_VulkanApiVersion &lt; VK_MAKE_VERSION(1, 1, 0).</span></div>
+<div class="line"><a name="l07345"></a><span class="lineno"> 7345</span>&#160;    <span class="keywordtype">bool</span> m_UseExtMemoryBudget;</div>
+<div class="line"><a name="l07346"></a><span class="lineno"> 7346</span>&#160;    <span class="keywordtype">bool</span> m_UseAmdDeviceCoherentMemory;</div>
+<div class="line"><a name="l07347"></a><span class="lineno"> 7347</span>&#160;    <span class="keywordtype">bool</span> m_UseKhrBufferDeviceAddress;</div>
+<div class="line"><a name="l07348"></a><span class="lineno"> 7348</span>&#160;    VkDevice m_hDevice;</div>
+<div class="line"><a name="l07349"></a><span class="lineno"> 7349</span>&#160;    VkInstance m_hInstance;</div>
+<div class="line"><a name="l07350"></a><span class="lineno"> 7350</span>&#160;    <span class="keywordtype">bool</span> m_AllocationCallbacksSpecified;</div>
+<div class="line"><a name="l07351"></a><span class="lineno"> 7351</span>&#160;    VkAllocationCallbacks m_AllocationCallbacks;</div>
+<div class="line"><a name="l07352"></a><span class="lineno"> 7352</span>&#160;    <a class="code" href="struct_vma_device_memory_callbacks.html">VmaDeviceMemoryCallbacks</a> m_DeviceMemoryCallbacks;</div>
+<div class="line"><a name="l07353"></a><span class="lineno"> 7353</span>&#160;    VmaAllocationObjectAllocator m_AllocationObjectAllocator;</div>
+<div class="line"><a name="l07354"></a><span class="lineno"> 7354</span>&#160;    </div>
+<div class="line"><a name="l07355"></a><span class="lineno"> 7355</span>&#160;    <span class="comment">// Each bit (1 &lt;&lt; i) is set if HeapSizeLimit is enabled for that heap, so cannot allocate more than the heap size.</span></div>
+<div class="line"><a name="l07356"></a><span class="lineno"> 7356</span>&#160;    uint32_t m_HeapSizeLimitMask;</div>
+<div class="line"><a name="l07357"></a><span class="lineno"> 7357</span>&#160; </div>
+<div class="line"><a name="l07358"></a><span class="lineno"> 7358</span>&#160;    VkPhysicalDeviceProperties m_PhysicalDeviceProperties;</div>
+<div class="line"><a name="l07359"></a><span class="lineno"> 7359</span>&#160;    VkPhysicalDeviceMemoryProperties m_MemProps;</div>
+<div class="line"><a name="l07360"></a><span class="lineno"> 7360</span>&#160; </div>
+<div class="line"><a name="l07361"></a><span class="lineno"> 7361</span>&#160;    <span class="comment">// Default pools.</span></div>
+<div class="line"><a name="l07362"></a><span class="lineno"> 7362</span>&#160;    VmaBlockVector* m_pBlockVectors[VK_MAX_MEMORY_TYPES];</div>
+<div class="line"><a name="l07363"></a><span class="lineno"> 7363</span>&#160; </div>
+<div class="line"><a name="l07364"></a><span class="lineno"> 7364</span>&#160;    <span class="comment">// Each vector is sorted by memory (handle value).</span></div>
+<div class="line"><a name="l07365"></a><span class="lineno"> 7365</span>&#160;    <span class="keyword">typedef</span> VmaVector&lt; VmaAllocation, VmaStlAllocator&lt;VmaAllocation&gt; &gt; AllocationVectorType;</div>
+<div class="line"><a name="l07366"></a><span class="lineno"> 7366</span>&#160;    AllocationVectorType* m_pDedicatedAllocations[VK_MAX_MEMORY_TYPES];</div>
+<div class="line"><a name="l07367"></a><span class="lineno"> 7367</span>&#160;    VMA_RW_MUTEX m_DedicatedAllocationsMutex[VK_MAX_MEMORY_TYPES];</div>
+<div class="line"><a name="l07368"></a><span class="lineno"> 7368</span>&#160; </div>
+<div class="line"><a name="l07369"></a><span class="lineno"> 7369</span>&#160;    VmaCurrentBudgetData m_Budget;</div>
+<div class="line"><a name="l07370"></a><span class="lineno"> 7370</span>&#160; </div>
+<div class="line"><a name="l07371"></a><span class="lineno"> 7371</span>&#160;    VmaAllocator_T(<span class="keyword">const</span> <a class="code" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a>* pCreateInfo);</div>
+<div class="line"><a name="l07372"></a><span class="lineno"> 7372</span>&#160;    VkResult Init(<span class="keyword">const</span> <a class="code" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a>* pCreateInfo);</div>
+<div class="line"><a name="l07373"></a><span class="lineno"> 7373</span>&#160;    ~VmaAllocator_T();</div>
+<div class="line"><a name="l07374"></a><span class="lineno"> 7374</span>&#160; </div>
+<div class="line"><a name="l07375"></a><span class="lineno"> 7375</span>&#160;    <span class="keyword">const</span> VkAllocationCallbacks* GetAllocationCallbacks()<span class="keyword"> const</span></div>
+<div class="line"><a name="l07376"></a><span class="lineno"> 7376</span>&#160;<span class="keyword">    </span>{</div>
+<div class="line"><a name="l07377"></a><span class="lineno"> 7377</span>&#160;        <span class="keywordflow">return</span> m_AllocationCallbacksSpecified ? &amp;m_AllocationCallbacks : 0;</div>
+<div class="line"><a name="l07378"></a><span class="lineno"> 7378</span>&#160;    }</div>
+<div class="line"><a name="l07379"></a><span class="lineno"> 7379</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a>&amp; GetVulkanFunctions()<span class="keyword"> const</span></div>
+<div class="line"><a name="l07380"></a><span class="lineno"> 7380</span>&#160;<span class="keyword">    </span>{</div>
+<div class="line"><a name="l07381"></a><span class="lineno"> 7381</span>&#160;        <span class="keywordflow">return</span> m_VulkanFunctions;</div>
+<div class="line"><a name="l07382"></a><span class="lineno"> 7382</span>&#160;    }</div>
+<div class="line"><a name="l07383"></a><span class="lineno"> 7383</span>&#160; </div>
+<div class="line"><a name="l07384"></a><span class="lineno"> 7384</span>&#160;    VkPhysicalDevice GetPhysicalDevice()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_PhysicalDevice; }</div>
+<div class="line"><a name="l07385"></a><span class="lineno"> 7385</span>&#160; </div>
+<div class="line"><a name="l07386"></a><span class="lineno"> 7386</span>&#160;    VkDeviceSize GetBufferImageGranularity()<span class="keyword"> const</span></div>
+<div class="line"><a name="l07387"></a><span class="lineno"> 7387</span>&#160;<span class="keyword">    </span>{</div>
+<div class="line"><a name="l07388"></a><span class="lineno"> 7388</span>&#160;        <span class="keywordflow">return</span> VMA_MAX(</div>
+<div class="line"><a name="l07389"></a><span class="lineno"> 7389</span>&#160;            <span class="keyword">static_cast&lt;</span>VkDeviceSize<span class="keyword">&gt;</span>(VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY),</div>
+<div class="line"><a name="l07390"></a><span class="lineno"> 7390</span>&#160;            m_PhysicalDeviceProperties.limits.bufferImageGranularity);</div>
+<div class="line"><a name="l07391"></a><span class="lineno"> 7391</span>&#160;    }</div>
+<div class="line"><a name="l07392"></a><span class="lineno"> 7392</span>&#160; </div>
+<div class="line"><a name="l07393"></a><span class="lineno"> 7393</span>&#160;    uint32_t GetMemoryHeapCount()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_MemProps.memoryHeapCount; }</div>
+<div class="line"><a name="l07394"></a><span class="lineno"> 7394</span>&#160;    uint32_t GetMemoryTypeCount()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_MemProps.memoryTypeCount; }</div>
+<div class="line"><a name="l07395"></a><span class="lineno"> 7395</span>&#160; </div>
+<div class="line"><a name="l07396"></a><span class="lineno"> 7396</span>&#160;    uint32_t MemoryTypeIndexToHeapIndex(uint32_t memTypeIndex)<span class="keyword"> const</span></div>
+<div class="line"><a name="l07397"></a><span class="lineno"> 7397</span>&#160;<span class="keyword">    </span>{</div>
+<div class="line"><a name="l07398"></a><span class="lineno"> 7398</span>&#160;        VMA_ASSERT(memTypeIndex &lt; m_MemProps.memoryTypeCount);</div>
+<div class="line"><a name="l07399"></a><span class="lineno"> 7399</span>&#160;        <span class="keywordflow">return</span> m_MemProps.memoryTypes[memTypeIndex].heapIndex;</div>
+<div class="line"><a name="l07400"></a><span class="lineno"> 7400</span>&#160;    }</div>
+<div class="line"><a name="l07401"></a><span class="lineno"> 7401</span>&#160;    <span class="comment">// True when specific memory type is HOST_VISIBLE but not HOST_COHERENT.</span></div>
+<div class="line"><a name="l07402"></a><span class="lineno"> 7402</span>&#160;    <span class="keywordtype">bool</span> IsMemoryTypeNonCoherent(uint32_t memTypeIndex)<span class="keyword"> const</span></div>
+<div class="line"><a name="l07403"></a><span class="lineno"> 7403</span>&#160;<span class="keyword">    </span>{</div>
+<div class="line"><a name="l07404"></a><span class="lineno"> 7404</span>&#160;        <span class="keywordflow">return</span> (m_MemProps.memoryTypes[memTypeIndex].propertyFlags &amp; (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) ==</div>
+<div class="line"><a name="l07405"></a><span class="lineno"> 7405</span>&#160;            VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;</div>
+<div class="line"><a name="l07406"></a><span class="lineno"> 7406</span>&#160;    }</div>
+<div class="line"><a name="l07407"></a><span class="lineno"> 7407</span>&#160;    <span class="comment">// Minimum alignment for all allocations in specific memory type.</span></div>
+<div class="line"><a name="l07408"></a><span class="lineno"> 7408</span>&#160;    VkDeviceSize GetMemoryTypeMinAlignment(uint32_t memTypeIndex)<span class="keyword"> const</span></div>
+<div class="line"><a name="l07409"></a><span class="lineno"> 7409</span>&#160;<span class="keyword">    </span>{</div>
+<div class="line"><a name="l07410"></a><span class="lineno"> 7410</span>&#160;        <span class="keywordflow">return</span> IsMemoryTypeNonCoherent(memTypeIndex) ?</div>
+<div class="line"><a name="l07411"></a><span class="lineno"> 7411</span>&#160;            VMA_MAX((VkDeviceSize)VMA_DEBUG_ALIGNMENT, m_PhysicalDeviceProperties.limits.nonCoherentAtomSize) :</div>
+<div class="line"><a name="l07412"></a><span class="lineno"> 7412</span>&#160;            (VkDeviceSize)VMA_DEBUG_ALIGNMENT;</div>
+<div class="line"><a name="l07413"></a><span class="lineno"> 7413</span>&#160;    }</div>
+<div class="line"><a name="l07414"></a><span class="lineno"> 7414</span>&#160; </div>
+<div class="line"><a name="l07415"></a><span class="lineno"> 7415</span>&#160;    <span class="keywordtype">bool</span> IsIntegratedGpu()<span class="keyword"> const</span></div>
+<div class="line"><a name="l07416"></a><span class="lineno"> 7416</span>&#160;<span class="keyword">    </span>{</div>
+<div class="line"><a name="l07417"></a><span class="lineno"> 7417</span>&#160;        <span class="keywordflow">return</span> m_PhysicalDeviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;</div>
+<div class="line"><a name="l07418"></a><span class="lineno"> 7418</span>&#160;    }</div>
+<div class="line"><a name="l07419"></a><span class="lineno"> 7419</span>&#160; </div>
+<div class="line"><a name="l07420"></a><span class="lineno"> 7420</span>&#160;    uint32_t GetGlobalMemoryTypeBits()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_GlobalMemoryTypeBits; }</div>
+<div class="line"><a name="l07421"></a><span class="lineno"> 7421</span>&#160; </div>
+<div class="line"><a name="l07422"></a><span class="lineno"> 7422</span>&#160;<span class="preprocessor">#if VMA_RECORDING_ENABLED</span></div>
+<div class="line"><a name="l07423"></a><span class="lineno"> 7423</span>&#160;    VmaRecorder* GetRecorder()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_pRecorder; }</div>
+<div class="line"><a name="l07424"></a><span class="lineno"> 7424</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l07425"></a><span class="lineno"> 7425</span>&#160; </div>
+<div class="line"><a name="l07426"></a><span class="lineno"> 7426</span>&#160;    <span class="keywordtype">void</span> GetBufferMemoryRequirements(</div>
+<div class="line"><a name="l07427"></a><span class="lineno"> 7427</span>&#160;        VkBuffer hBuffer,</div>
+<div class="line"><a name="l07428"></a><span class="lineno"> 7428</span>&#160;        VkMemoryRequirements&amp; memReq,</div>
+<div class="line"><a name="l07429"></a><span class="lineno"> 7429</span>&#160;        <span class="keywordtype">bool</span>&amp; requiresDedicatedAllocation,</div>
+<div class="line"><a name="l07430"></a><span class="lineno"> 7430</span>&#160;        <span class="keywordtype">bool</span>&amp; prefersDedicatedAllocation) <span class="keyword">const</span>;</div>
+<div class="line"><a name="l07431"></a><span class="lineno"> 7431</span>&#160;    <span class="keywordtype">void</span> GetImageMemoryRequirements(</div>
+<div class="line"><a name="l07432"></a><span class="lineno"> 7432</span>&#160;        VkImage hImage,</div>
+<div class="line"><a name="l07433"></a><span class="lineno"> 7433</span>&#160;        VkMemoryRequirements&amp; memReq,</div>
+<div class="line"><a name="l07434"></a><span class="lineno"> 7434</span>&#160;        <span class="keywordtype">bool</span>&amp; requiresDedicatedAllocation,</div>
+<div class="line"><a name="l07435"></a><span class="lineno"> 7435</span>&#160;        <span class="keywordtype">bool</span>&amp; prefersDedicatedAllocation) <span class="keyword">const</span>;</div>
+<div class="line"><a name="l07436"></a><span class="lineno"> 7436</span>&#160; </div>
+<div class="line"><a name="l07437"></a><span class="lineno"> 7437</span>&#160;    <span class="comment">// Main allocation function.</span></div>
+<div class="line"><a name="l07438"></a><span class="lineno"> 7438</span>&#160;    VkResult AllocateMemory(</div>
+<div class="line"><a name="l07439"></a><span class="lineno"> 7439</span>&#160;        <span class="keyword">const</span> VkMemoryRequirements&amp; vkMemReq,</div>
+<div class="line"><a name="l07440"></a><span class="lineno"> 7440</span>&#160;        <span class="keywordtype">bool</span> requiresDedicatedAllocation,</div>
+<div class="line"><a name="l07441"></a><span class="lineno"> 7441</span>&#160;        <span class="keywordtype">bool</span> prefersDedicatedAllocation,</div>
+<div class="line"><a name="l07442"></a><span class="lineno"> 7442</span>&#160;        VkBuffer dedicatedBuffer,</div>
+<div class="line"><a name="l07443"></a><span class="lineno"> 7443</span>&#160;        VkBufferUsageFlags dedicatedBufferUsage, <span class="comment">// UINT32_MAX when unknown.</span></div>
+<div class="line"><a name="l07444"></a><span class="lineno"> 7444</span>&#160;        VkImage dedicatedImage,</div>
+<div class="line"><a name="l07445"></a><span class="lineno"> 7445</span>&#160;        <span class="keyword">const</span> <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>&amp; createInfo,</div>
+<div class="line"><a name="l07446"></a><span class="lineno"> 7446</span>&#160;        VmaSuballocationType suballocType,</div>
+<div class="line"><a name="l07447"></a><span class="lineno"> 7447</span>&#160;        <span class="keywordtype">size_t</span> allocationCount,</div>
+<div class="line"><a name="l07448"></a><span class="lineno"> 7448</span>&#160;        <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocations);</div>
+<div class="line"><a name="l07449"></a><span class="lineno"> 7449</span>&#160; </div>
+<div class="line"><a name="l07450"></a><span class="lineno"> 7450</span>&#160;    <span class="comment">// Main deallocation function.</span></div>
+<div class="line"><a name="l07451"></a><span class="lineno"> 7451</span>&#160;    <span class="keywordtype">void</span> FreeMemory(</div>
+<div class="line"><a name="l07452"></a><span class="lineno"> 7452</span>&#160;        <span class="keywordtype">size_t</span> allocationCount,</div>
+<div class="line"><a name="l07453"></a><span class="lineno"> 7453</span>&#160;        <span class="keyword">const</span> <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocations);</div>
+<div class="line"><a name="l07454"></a><span class="lineno"> 7454</span>&#160; </div>
+<div class="line"><a name="l07455"></a><span class="lineno"> 7455</span>&#160;    VkResult ResizeAllocation(</div>
+<div class="line"><a name="l07456"></a><span class="lineno"> 7456</span>&#160;        <span class="keyword">const</span> <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> alloc,</div>
+<div class="line"><a name="l07457"></a><span class="lineno"> 7457</span>&#160;        VkDeviceSize newSize);</div>
+<div class="line"><a name="l07458"></a><span class="lineno"> 7458</span>&#160; </div>
+<div class="line"><a name="l07459"></a><span class="lineno"> 7459</span>&#160;    <span class="keywordtype">void</span> CalculateStats(<a class="code" href="struct_vma_stats.html">VmaStats</a>* pStats);</div>
+<div class="line"><a name="l07460"></a><span class="lineno"> 7460</span>&#160; </div>
+<div class="line"><a name="l07461"></a><span class="lineno"> 7461</span>&#160;    <span class="keywordtype">void</span> GetBudget(</div>
+<div class="line"><a name="l07462"></a><span class="lineno"> 7462</span>&#160;        <a class="code" href="struct_vma_budget.html">VmaBudget</a>* outBudget, uint32_t firstHeap, uint32_t heapCount);</div>
+<div class="line"><a name="l07463"></a><span class="lineno"> 7463</span>&#160; </div>
+<div class="line"><a name="l07464"></a><span class="lineno"> 7464</span>&#160;<span class="preprocessor">#if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l07465"></a><span class="lineno"> 7465</span>&#160;    <span class="keywordtype">void</span> PrintDetailedMap(<span class="keyword">class</span> VmaJsonWriter&amp; json);</div>
+<div class="line"><a name="l07466"></a><span class="lineno"> 7466</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l07467"></a><span class="lineno"> 7467</span>&#160; </div>
+<div class="line"><a name="l07468"></a><span class="lineno"> 7468</span>&#160;    VkResult DefragmentationBegin(</div>
+<div class="line"><a name="l07469"></a><span class="lineno"> 7469</span>&#160;        <span class="keyword">const</span> <a class="code" href="struct_vma_defragmentation_info2.html">VmaDefragmentationInfo2</a>&amp; info,</div>
+<div class="line"><a name="l07470"></a><span class="lineno"> 7470</span>&#160;        <a class="code" href="struct_vma_defragmentation_stats.html">VmaDefragmentationStats</a>* pStats,</div>
+<div class="line"><a name="l07471"></a><span class="lineno"> 7471</span>&#160;        <a class="code" href="struct_vma_defragmentation_context.html">VmaDefragmentationContext</a>* pContext);</div>
+<div class="line"><a name="l07472"></a><span class="lineno"> 7472</span>&#160;    VkResult DefragmentationEnd(</div>
+<div class="line"><a name="l07473"></a><span class="lineno"> 7473</span>&#160;        <a class="code" href="struct_vma_defragmentation_context.html">VmaDefragmentationContext</a> context);</div>
+<div class="line"><a name="l07474"></a><span class="lineno"> 7474</span>&#160; </div>
+<div class="line"><a name="l07475"></a><span class="lineno"> 7475</span>&#160;    VkResult DefragmentationPassBegin(</div>
+<div class="line"><a name="l07476"></a><span class="lineno"> 7476</span>&#160;        <a class="code" href="struct_vma_defragmentation_pass_info.html">VmaDefragmentationPassInfo</a>* pInfo,</div>
+<div class="line"><a name="l07477"></a><span class="lineno"> 7477</span>&#160;        <a class="code" href="struct_vma_defragmentation_context.html">VmaDefragmentationContext</a> context);</div>
+<div class="line"><a name="l07478"></a><span class="lineno"> 7478</span>&#160;    VkResult DefragmentationPassEnd(</div>
+<div class="line"><a name="l07479"></a><span class="lineno"> 7479</span>&#160;        <a class="code" href="struct_vma_defragmentation_context.html">VmaDefragmentationContext</a> context);</div>
+<div class="line"><a name="l07480"></a><span class="lineno"> 7480</span>&#160; </div>
+<div class="line"><a name="l07481"></a><span class="lineno"> 7481</span>&#160;    <span class="keywordtype">void</span> GetAllocationInfo(<a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAllocation, <a class="code" href="struct_vma_allocation_info.html">VmaAllocationInfo</a>* pAllocationInfo);</div>
+<div class="line"><a name="l07482"></a><span class="lineno"> 7482</span>&#160;    <span class="keywordtype">bool</span> TouchAllocation(<a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAllocation);</div>
+<div class="line"><a name="l07483"></a><span class="lineno"> 7483</span>&#160; </div>
+<div class="line"><a name="l07484"></a><span class="lineno"> 7484</span>&#160;    VkResult CreatePool(<span class="keyword">const</span> <a class="code" href="struct_vma_pool_create_info.html">VmaPoolCreateInfo</a>* pCreateInfo, <a class="code" href="struct_vma_pool.html">VmaPool</a>* pPool);</div>
+<div class="line"><a name="l07485"></a><span class="lineno"> 7485</span>&#160;    <span class="keywordtype">void</span> DestroyPool(<a class="code" href="struct_vma_pool.html">VmaPool</a> pool);</div>
+<div class="line"><a name="l07486"></a><span class="lineno"> 7486</span>&#160;    <span class="keywordtype">void</span> GetPoolStats(<a class="code" href="struct_vma_pool.html">VmaPool</a> pool, <a class="code" href="struct_vma_pool_stats.html">VmaPoolStats</a>* pPoolStats);</div>
+<div class="line"><a name="l07487"></a><span class="lineno"> 7487</span>&#160; </div>
+<div class="line"><a name="l07488"></a><span class="lineno"> 7488</span>&#160;    <span class="keywordtype">void</span> SetCurrentFrameIndex(uint32_t frameIndex);</div>
+<div class="line"><a name="l07489"></a><span class="lineno"> 7489</span>&#160;    uint32_t GetCurrentFrameIndex()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_CurrentFrameIndex.load(); }</div>
+<div class="line"><a name="l07490"></a><span class="lineno"> 7490</span>&#160; </div>
+<div class="line"><a name="l07491"></a><span class="lineno"> 7491</span>&#160;    <span class="keywordtype">void</span> MakePoolAllocationsLost(</div>
+<div class="line"><a name="l07492"></a><span class="lineno"> 7492</span>&#160;        <a class="code" href="struct_vma_pool.html">VmaPool</a> hPool,</div>
+<div class="line"><a name="l07493"></a><span class="lineno"> 7493</span>&#160;        <span class="keywordtype">size_t</span>* pLostAllocationCount);</div>
+<div class="line"><a name="l07494"></a><span class="lineno"> 7494</span>&#160;    VkResult CheckPoolCorruption(<a class="code" href="struct_vma_pool.html">VmaPool</a> hPool);</div>
+<div class="line"><a name="l07495"></a><span class="lineno"> 7495</span>&#160;    VkResult CheckCorruption(uint32_t memoryTypeBits);</div>
+<div class="line"><a name="l07496"></a><span class="lineno"> 7496</span>&#160; </div>
+<div class="line"><a name="l07497"></a><span class="lineno"> 7497</span>&#160;    <span class="keywordtype">void</span> CreateLostAllocation(<a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocation);</div>
+<div class="line"><a name="l07498"></a><span class="lineno"> 7498</span>&#160; </div>
+<div class="line"><a name="l07499"></a><span class="lineno"> 7499</span>&#160;    <span class="comment">// Call to Vulkan function vkAllocateMemory with accompanying bookkeeping.</span></div>
+<div class="line"><a name="l07500"></a><span class="lineno"> 7500</span>&#160;    VkResult AllocateVulkanMemory(<span class="keyword">const</span> VkMemoryAllocateInfo* pAllocateInfo, VkDeviceMemory* pMemory);</div>
+<div class="line"><a name="l07501"></a><span class="lineno"> 7501</span>&#160;    <span class="comment">// Call to Vulkan function vkFreeMemory with accompanying bookkeeping.</span></div>
+<div class="line"><a name="l07502"></a><span class="lineno"> 7502</span>&#160;    <span class="keywordtype">void</span> FreeVulkanMemory(uint32_t memoryType, VkDeviceSize size, VkDeviceMemory hMemory);</div>
+<div class="line"><a name="l07503"></a><span class="lineno"> 7503</span>&#160;    <span class="comment">// Call to Vulkan function vkBindBufferMemory or vkBindBufferMemory2KHR.</span></div>
+<div class="line"><a name="l07504"></a><span class="lineno"> 7504</span>&#160;    VkResult BindVulkanBuffer(</div>
+<div class="line"><a name="l07505"></a><span class="lineno"> 7505</span>&#160;        VkDeviceMemory memory,</div>
+<div class="line"><a name="l07506"></a><span class="lineno"> 7506</span>&#160;        VkDeviceSize memoryOffset,</div>
+<div class="line"><a name="l07507"></a><span class="lineno"> 7507</span>&#160;        VkBuffer buffer,</div>
+<div class="line"><a name="l07508"></a><span class="lineno"> 7508</span>&#160;        <span class="keyword">const</span> <span class="keywordtype">void</span>* pNext);</div>
+<div class="line"><a name="l07509"></a><span class="lineno"> 7509</span>&#160;    <span class="comment">// Call to Vulkan function vkBindImageMemory or vkBindImageMemory2KHR.</span></div>
+<div class="line"><a name="l07510"></a><span class="lineno"> 7510</span>&#160;    VkResult BindVulkanImage(</div>
+<div class="line"><a name="l07511"></a><span class="lineno"> 7511</span>&#160;        VkDeviceMemory memory,</div>
+<div class="line"><a name="l07512"></a><span class="lineno"> 7512</span>&#160;        VkDeviceSize memoryOffset,</div>
+<div class="line"><a name="l07513"></a><span class="lineno"> 7513</span>&#160;        VkImage image,</div>
+<div class="line"><a name="l07514"></a><span class="lineno"> 7514</span>&#160;        <span class="keyword">const</span> <span class="keywordtype">void</span>* pNext);</div>
+<div class="line"><a name="l07515"></a><span class="lineno"> 7515</span>&#160; </div>
+<div class="line"><a name="l07516"></a><span class="lineno"> 7516</span>&#160;    VkResult Map(<a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAllocation, <span class="keywordtype">void</span>** ppData);</div>
+<div class="line"><a name="l07517"></a><span class="lineno"> 7517</span>&#160;    <span class="keywordtype">void</span> Unmap(<a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAllocation);</div>
+<div class="line"><a name="l07518"></a><span class="lineno"> 7518</span>&#160; </div>
+<div class="line"><a name="l07519"></a><span class="lineno"> 7519</span>&#160;    VkResult BindBufferMemory(</div>
+<div class="line"><a name="l07520"></a><span class="lineno"> 7520</span>&#160;        <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAllocation,</div>
+<div class="line"><a name="l07521"></a><span class="lineno"> 7521</span>&#160;        VkDeviceSize allocationLocalOffset,</div>
+<div class="line"><a name="l07522"></a><span class="lineno"> 7522</span>&#160;        VkBuffer hBuffer,</div>
+<div class="line"><a name="l07523"></a><span class="lineno"> 7523</span>&#160;        <span class="keyword">const</span> <span class="keywordtype">void</span>* pNext);</div>
+<div class="line"><a name="l07524"></a><span class="lineno"> 7524</span>&#160;    VkResult BindImageMemory(</div>
+<div class="line"><a name="l07525"></a><span class="lineno"> 7525</span>&#160;        <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAllocation,</div>
+<div class="line"><a name="l07526"></a><span class="lineno"> 7526</span>&#160;        VkDeviceSize allocationLocalOffset,</div>
+<div class="line"><a name="l07527"></a><span class="lineno"> 7527</span>&#160;        VkImage hImage,</div>
+<div class="line"><a name="l07528"></a><span class="lineno"> 7528</span>&#160;        <span class="keyword">const</span> <span class="keywordtype">void</span>* pNext);</div>
+<div class="line"><a name="l07529"></a><span class="lineno"> 7529</span>&#160; </div>
+<div class="line"><a name="l07530"></a><span class="lineno"> 7530</span>&#160;    <span class="keywordtype">void</span> FlushOrInvalidateAllocation(</div>
+<div class="line"><a name="l07531"></a><span class="lineno"> 7531</span>&#160;        <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAllocation,</div>
+<div class="line"><a name="l07532"></a><span class="lineno"> 7532</span>&#160;        VkDeviceSize offset, VkDeviceSize size,</div>
+<div class="line"><a name="l07533"></a><span class="lineno"> 7533</span>&#160;        VMA_CACHE_OPERATION op);</div>
+<div class="line"><a name="l07534"></a><span class="lineno"> 7534</span>&#160; </div>
+<div class="line"><a name="l07535"></a><span class="lineno"> 7535</span>&#160;    <span class="keywordtype">void</span> FillAllocation(<span class="keyword">const</span> <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAllocation, uint8_t pattern);</div>
+<div class="line"><a name="l07536"></a><span class="lineno"> 7536</span>&#160; </div>
+<div class="line"><a name="l07537"></a><span class="lineno"> 7537</span>&#160;    <span class="comment">/*</span></div>
+<div class="line"><a name="l07538"></a><span class="lineno"> 7538</span>&#160;<span class="comment">    Returns bit mask of memory types that can support defragmentation on GPU as</span></div>
+<div class="line"><a name="l07539"></a><span class="lineno"> 7539</span>&#160;<span class="comment">    they support creation of required buffer for copy operations.</span></div>
+<div class="line"><a name="l07540"></a><span class="lineno"> 7540</span>&#160;<span class="comment">    */</span></div>
+<div class="line"><a name="l07541"></a><span class="lineno"> 7541</span>&#160;    uint32_t GetGpuDefragmentationMemoryTypeBits();</div>
+<div class="line"><a name="l07542"></a><span class="lineno"> 7542</span>&#160; </div>
+<div class="line"><a name="l07543"></a><span class="lineno"> 7543</span>&#160;<span class="keyword">private</span>:</div>
+<div class="line"><a name="l07544"></a><span class="lineno"> 7544</span>&#160;    VkDeviceSize m_PreferredLargeHeapBlockSize;</div>
+<div class="line"><a name="l07545"></a><span class="lineno"> 7545</span>&#160; </div>
+<div class="line"><a name="l07546"></a><span class="lineno"> 7546</span>&#160;    VkPhysicalDevice m_PhysicalDevice;</div>
+<div class="line"><a name="l07547"></a><span class="lineno"> 7547</span>&#160;    VMA_ATOMIC_UINT32 m_CurrentFrameIndex;</div>
+<div class="line"><a name="l07548"></a><span class="lineno"> 7548</span>&#160;    VMA_ATOMIC_UINT32 m_GpuDefragmentationMemoryTypeBits; <span class="comment">// UINT32_MAX means uninitialized.</span></div>
+<div class="line"><a name="l07549"></a><span class="lineno"> 7549</span>&#160;    </div>
+<div class="line"><a name="l07550"></a><span class="lineno"> 7550</span>&#160;    VMA_RW_MUTEX m_PoolsMutex;</div>
+<div class="line"><a name="l07551"></a><span class="lineno"> 7551</span>&#160;    <span class="comment">// Protected by m_PoolsMutex. Sorted by pointer value.</span></div>
+<div class="line"><a name="l07552"></a><span class="lineno"> 7552</span>&#160;    VmaVector&lt;VmaPool, VmaStlAllocator&lt;VmaPool&gt; &gt; m_Pools;</div>
+<div class="line"><a name="l07553"></a><span class="lineno"> 7553</span>&#160;    uint32_t m_NextPoolId;</div>
+<div class="line"><a name="l07554"></a><span class="lineno"> 7554</span>&#160; </div>
+<div class="line"><a name="l07555"></a><span class="lineno"> 7555</span>&#160;    <a class="code" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a> m_VulkanFunctions;</div>
+<div class="line"><a name="l07556"></a><span class="lineno"> 7556</span>&#160; </div>
+<div class="line"><a name="l07557"></a><span class="lineno"> 7557</span>&#160;    <span class="comment">// Global bit mask AND-ed with any memoryTypeBits to disallow certain memory types.</span></div>
+<div class="line"><a name="l07558"></a><span class="lineno"> 7558</span>&#160;    uint32_t m_GlobalMemoryTypeBits;</div>
+<div class="line"><a name="l07559"></a><span class="lineno"> 7559</span>&#160; </div>
+<div class="line"><a name="l07560"></a><span class="lineno"> 7560</span>&#160;<span class="preprocessor">#if VMA_RECORDING_ENABLED</span></div>
+<div class="line"><a name="l07561"></a><span class="lineno"> 7561</span>&#160;    VmaRecorder* m_pRecorder;</div>
+<div class="line"><a name="l07562"></a><span class="lineno"> 7562</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l07563"></a><span class="lineno"> 7563</span>&#160; </div>
+<div class="line"><a name="l07564"></a><span class="lineno"> 7564</span>&#160;    <span class="keywordtype">void</span> ImportVulkanFunctions(<span class="keyword">const</span> <a class="code" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a>* pVulkanFunctions);</div>
+<div class="line"><a name="l07565"></a><span class="lineno"> 7565</span>&#160;    <span class="keywordtype">void</span> ImportVulkanFunctions_Static();</div>
+<div class="line"><a name="l07566"></a><span class="lineno"> 7566</span>&#160;    <span class="keywordtype">void</span> ImportVulkanFunctions_Custom(<span class="keyword">const</span> <a class="code" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a>* pVulkanFunctions);</div>
+<div class="line"><a name="l07567"></a><span class="lineno"> 7567</span>&#160;    <span class="keywordtype">void</span> ImportVulkanFunctions_Dynamic();</div>
+<div class="line"><a name="l07568"></a><span class="lineno"> 7568</span>&#160;    <span class="keywordtype">void</span> ValidateVulkanFunctions();</div>
+<div class="line"><a name="l07569"></a><span class="lineno"> 7569</span>&#160; </div>
+<div class="line"><a name="l07570"></a><span class="lineno"> 7570</span>&#160;    VkDeviceSize CalcPreferredBlockSize(uint32_t memTypeIndex);</div>
+<div class="line"><a name="l07571"></a><span class="lineno"> 7571</span>&#160; </div>
+<div class="line"><a name="l07572"></a><span class="lineno"> 7572</span>&#160;    VkResult AllocateMemoryOfType(</div>
+<div class="line"><a name="l07573"></a><span class="lineno"> 7573</span>&#160;        VkDeviceSize size,</div>
+<div class="line"><a name="l07574"></a><span class="lineno"> 7574</span>&#160;        VkDeviceSize alignment,</div>
+<div class="line"><a name="l07575"></a><span class="lineno"> 7575</span>&#160;        <span class="keywordtype">bool</span> dedicatedAllocation,</div>
+<div class="line"><a name="l07576"></a><span class="lineno"> 7576</span>&#160;        VkBuffer dedicatedBuffer,</div>
+<div class="line"><a name="l07577"></a><span class="lineno"> 7577</span>&#160;        VkBufferUsageFlags dedicatedBufferUsage,</div>
+<div class="line"><a name="l07578"></a><span class="lineno"> 7578</span>&#160;        VkImage dedicatedImage,</div>
+<div class="line"><a name="l07579"></a><span class="lineno"> 7579</span>&#160;        <span class="keyword">const</span> <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>&amp; createInfo,</div>
+<div class="line"><a name="l07580"></a><span class="lineno"> 7580</span>&#160;        uint32_t memTypeIndex,</div>
+<div class="line"><a name="l07581"></a><span class="lineno"> 7581</span>&#160;        VmaSuballocationType suballocType,</div>
+<div class="line"><a name="l07582"></a><span class="lineno"> 7582</span>&#160;        <span class="keywordtype">size_t</span> allocationCount,</div>
+<div class="line"><a name="l07583"></a><span class="lineno"> 7583</span>&#160;        <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocations);</div>
+<div class="line"><a name="l07584"></a><span class="lineno"> 7584</span>&#160; </div>
+<div class="line"><a name="l07585"></a><span class="lineno"> 7585</span>&#160;    <span class="comment">// Helper function only to be used inside AllocateDedicatedMemory.</span></div>
+<div class="line"><a name="l07586"></a><span class="lineno"> 7586</span>&#160;    VkResult AllocateDedicatedMemoryPage(</div>
+<div class="line"><a name="l07587"></a><span class="lineno"> 7587</span>&#160;        VkDeviceSize size,</div>
+<div class="line"><a name="l07588"></a><span class="lineno"> 7588</span>&#160;        VmaSuballocationType suballocType,</div>
+<div class="line"><a name="l07589"></a><span class="lineno"> 7589</span>&#160;        uint32_t memTypeIndex,</div>
+<div class="line"><a name="l07590"></a><span class="lineno"> 7590</span>&#160;        <span class="keyword">const</span> VkMemoryAllocateInfo&amp; allocInfo,</div>
+<div class="line"><a name="l07591"></a><span class="lineno"> 7591</span>&#160;        <span class="keywordtype">bool</span> map,</div>
+<div class="line"><a name="l07592"></a><span class="lineno"> 7592</span>&#160;        <span class="keywordtype">bool</span> isUserDataString,</div>
+<div class="line"><a name="l07593"></a><span class="lineno"> 7593</span>&#160;        <span class="keywordtype">void</span>* pUserData,</div>
+<div class="line"><a name="l07594"></a><span class="lineno"> 7594</span>&#160;        <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocation);</div>
+<div class="line"><a name="l07595"></a><span class="lineno"> 7595</span>&#160; </div>
+<div class="line"><a name="l07596"></a><span class="lineno"> 7596</span>&#160;    <span class="comment">// Allocates and registers new VkDeviceMemory specifically for dedicated allocations.</span></div>
+<div class="line"><a name="l07597"></a><span class="lineno"> 7597</span>&#160;    VkResult AllocateDedicatedMemory(</div>
+<div class="line"><a name="l07598"></a><span class="lineno"> 7598</span>&#160;        VkDeviceSize size,</div>
+<div class="line"><a name="l07599"></a><span class="lineno"> 7599</span>&#160;        VmaSuballocationType suballocType,</div>
+<div class="line"><a name="l07600"></a><span class="lineno"> 7600</span>&#160;        uint32_t memTypeIndex,</div>
+<div class="line"><a name="l07601"></a><span class="lineno"> 7601</span>&#160;        <span class="keywordtype">bool</span> withinBudget,</div>
+<div class="line"><a name="l07602"></a><span class="lineno"> 7602</span>&#160;        <span class="keywordtype">bool</span> map,</div>
+<div class="line"><a name="l07603"></a><span class="lineno"> 7603</span>&#160;        <span class="keywordtype">bool</span> isUserDataString,</div>
+<div class="line"><a name="l07604"></a><span class="lineno"> 7604</span>&#160;        <span class="keywordtype">void</span>* pUserData,</div>
+<div class="line"><a name="l07605"></a><span class="lineno"> 7605</span>&#160;        VkBuffer dedicatedBuffer,</div>
+<div class="line"><a name="l07606"></a><span class="lineno"> 7606</span>&#160;        VkBufferUsageFlags dedicatedBufferUsage,</div>
+<div class="line"><a name="l07607"></a><span class="lineno"> 7607</span>&#160;        VkImage dedicatedImage,</div>
+<div class="line"><a name="l07608"></a><span class="lineno"> 7608</span>&#160;        <span class="keywordtype">size_t</span> allocationCount,</div>
+<div class="line"><a name="l07609"></a><span class="lineno"> 7609</span>&#160;        <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocations);</div>
+<div class="line"><a name="l07610"></a><span class="lineno"> 7610</span>&#160; </div>
+<div class="line"><a name="l07611"></a><span class="lineno"> 7611</span>&#160;    <span class="keywordtype">void</span> FreeDedicatedMemory(<span class="keyword">const</span> <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation);</div>
+<div class="line"><a name="l07612"></a><span class="lineno"> 7612</span>&#160; </div>
+<div class="line"><a name="l07613"></a><span class="lineno"> 7613</span>&#160;    <span class="comment">/*</span></div>
+<div class="line"><a name="l07614"></a><span class="lineno"> 7614</span>&#160;<span class="comment">    Calculates and returns bit mask of memory types that can support defragmentation</span></div>
+<div class="line"><a name="l07615"></a><span class="lineno"> 7615</span>&#160;<span class="comment">    on GPU as they support creation of required buffer for copy operations.</span></div>
+<div class="line"><a name="l07616"></a><span class="lineno"> 7616</span>&#160;<span class="comment">    */</span></div>
+<div class="line"><a name="l07617"></a><span class="lineno"> 7617</span>&#160;    uint32_t CalculateGpuDefragmentationMemoryTypeBits() <span class="keyword">const</span>;</div>
+<div class="line"><a name="l07618"></a><span class="lineno"> 7618</span>&#160; </div>
+<div class="line"><a name="l07619"></a><span class="lineno"> 7619</span>&#160;    uint32_t CalculateGlobalMemoryTypeBits() <span class="keyword">const</span>;</div>
+<div class="line"><a name="l07620"></a><span class="lineno"> 7620</span>&#160; </div>
+<div class="line"><a name="l07621"></a><span class="lineno"> 7621</span>&#160;<span class="preprocessor">#if VMA_MEMORY_BUDGET</span></div>
+<div class="line"><a name="l07622"></a><span class="lineno"> 7622</span>&#160;    <span class="keywordtype">void</span> UpdateVulkanBudget();</div>
+<div class="line"><a name="l07623"></a><span class="lineno"> 7623</span>&#160;<span class="preprocessor">#endif // #if VMA_MEMORY_BUDGET</span></div>
+<div class="line"><a name="l07624"></a><span class="lineno"> 7624</span>&#160;};</div>
+<div class="line"><a name="l07625"></a><span class="lineno"> 7625</span>&#160; </div>
+<div class="line"><a name="l07627"></a><span class="lineno"> 7627</span>&#160;<span class="comment">// Memory allocation #2 after VmaAllocator_T definition</span></div>
+<div class="line"><a name="l07628"></a><span class="lineno"> 7628</span>&#160; </div>
+<div class="line"><a name="l07629"></a><span class="lineno"> 7629</span>&#160;<span class="keyword">static</span> <span class="keywordtype">void</span>* VmaMalloc(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator, <span class="keywordtype">size_t</span> size, <span class="keywordtype">size_t</span> alignment)</div>
+<div class="line"><a name="l07630"></a><span class="lineno"> 7630</span>&#160;{</div>
+<div class="line"><a name="l07631"></a><span class="lineno"> 7631</span>&#160;    <span class="keywordflow">return</span> VmaMalloc(&amp;hAllocator-&gt;m_AllocationCallbacks, size, alignment);</div>
+<div class="line"><a name="l07632"></a><span class="lineno"> 7632</span>&#160;}</div>
+<div class="line"><a name="l07633"></a><span class="lineno"> 7633</span>&#160; </div>
+<div class="line"><a name="l07634"></a><span class="lineno"> 7634</span>&#160;<span class="keyword">static</span> <span class="keywordtype">void</span> VmaFree(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator, <span class="keywordtype">void</span>* ptr)</div>
+<div class="line"><a name="l07635"></a><span class="lineno"> 7635</span>&#160;{</div>
+<div class="line"><a name="l07636"></a><span class="lineno"> 7636</span>&#160;    VmaFree(&amp;hAllocator-&gt;m_AllocationCallbacks, ptr);</div>
+<div class="line"><a name="l07637"></a><span class="lineno"> 7637</span>&#160;}</div>
+<div class="line"><a name="l07638"></a><span class="lineno"> 7638</span>&#160; </div>
+<div class="line"><a name="l07639"></a><span class="lineno"> 7639</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</div>
+<div class="line"><a name="l07640"></a><span class="lineno"> 7640</span>&#160;<span class="keyword">static</span> T* VmaAllocate(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator)</div>
+<div class="line"><a name="l07641"></a><span class="lineno"> 7641</span>&#160;{</div>
+<div class="line"><a name="l07642"></a><span class="lineno"> 7642</span>&#160;    <span class="keywordflow">return</span> (T*)VmaMalloc(hAllocator, <span class="keyword">sizeof</span>(T), VMA_ALIGN_OF(T));</div>
+<div class="line"><a name="l07643"></a><span class="lineno"> 7643</span>&#160;}</div>
+<div class="line"><a name="l07644"></a><span class="lineno"> 7644</span>&#160; </div>
+<div class="line"><a name="l07645"></a><span class="lineno"> 7645</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</div>
+<div class="line"><a name="l07646"></a><span class="lineno"> 7646</span>&#160;<span class="keyword">static</span> T* VmaAllocateArray(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator, <span class="keywordtype">size_t</span> count)</div>
+<div class="line"><a name="l07647"></a><span class="lineno"> 7647</span>&#160;{</div>
+<div class="line"><a name="l07648"></a><span class="lineno"> 7648</span>&#160;    <span class="keywordflow">return</span> (T*)VmaMalloc(hAllocator, <span class="keyword">sizeof</span>(T) * count, VMA_ALIGN_OF(T));</div>
+<div class="line"><a name="l07649"></a><span class="lineno"> 7649</span>&#160;}</div>
+<div class="line"><a name="l07650"></a><span class="lineno"> 7650</span>&#160; </div>
+<div class="line"><a name="l07651"></a><span class="lineno"> 7651</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</div>
+<div class="line"><a name="l07652"></a><span class="lineno"> 7652</span>&#160;<span class="keyword">static</span> <span class="keywordtype">void</span> vma_delete(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator, T* ptr)</div>
+<div class="line"><a name="l07653"></a><span class="lineno"> 7653</span>&#160;{</div>
+<div class="line"><a name="l07654"></a><span class="lineno"> 7654</span>&#160;    <span class="keywordflow">if</span>(ptr != VMA_NULL)</div>
+<div class="line"><a name="l07655"></a><span class="lineno"> 7655</span>&#160;    {</div>
+<div class="line"><a name="l07656"></a><span class="lineno"> 7656</span>&#160;        ptr-&gt;~T();</div>
+<div class="line"><a name="l07657"></a><span class="lineno"> 7657</span>&#160;        VmaFree(hAllocator, ptr);</div>
+<div class="line"><a name="l07658"></a><span class="lineno"> 7658</span>&#160;    }</div>
+<div class="line"><a name="l07659"></a><span class="lineno"> 7659</span>&#160;}</div>
+<div class="line"><a name="l07660"></a><span class="lineno"> 7660</span>&#160; </div>
+<div class="line"><a name="l07661"></a><span class="lineno"> 7661</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</div>
+<div class="line"><a name="l07662"></a><span class="lineno"> 7662</span>&#160;<span class="keyword">static</span> <span class="keywordtype">void</span> vma_delete_array(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator, T* ptr, <span class="keywordtype">size_t</span> count)</div>
+<div class="line"><a name="l07663"></a><span class="lineno"> 7663</span>&#160;{</div>
+<div class="line"><a name="l07664"></a><span class="lineno"> 7664</span>&#160;    <span class="keywordflow">if</span>(ptr != VMA_NULL)</div>
+<div class="line"><a name="l07665"></a><span class="lineno"> 7665</span>&#160;    {</div>
+<div class="line"><a name="l07666"></a><span class="lineno"> 7666</span>&#160;        <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = count; i--; )</div>
+<div class="line"><a name="l07667"></a><span class="lineno"> 7667</span>&#160;            ptr[i].~T();</div>
+<div class="line"><a name="l07668"></a><span class="lineno"> 7668</span>&#160;        VmaFree(hAllocator, ptr);</div>
+<div class="line"><a name="l07669"></a><span class="lineno"> 7669</span>&#160;    }</div>
+<div class="line"><a name="l07670"></a><span class="lineno"> 7670</span>&#160;}</div>
+<div class="line"><a name="l07671"></a><span class="lineno"> 7671</span>&#160; </div>
+<div class="line"><a name="l07673"></a><span class="lineno"> 7673</span>&#160;<span class="comment">// VmaStringBuilder</span></div>
+<div class="line"><a name="l07674"></a><span class="lineno"> 7674</span>&#160; </div>
+<div class="line"><a name="l07675"></a><span class="lineno"> 7675</span>&#160;<span class="preprocessor">#if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l07676"></a><span class="lineno"> 7676</span>&#160; </div>
+<div class="line"><a name="l07677"></a><span class="lineno"> 7677</span>&#160;<span class="keyword">class </span>VmaStringBuilder</div>
+<div class="line"><a name="l07678"></a><span class="lineno"> 7678</span>&#160;{</div>
+<div class="line"><a name="l07679"></a><span class="lineno"> 7679</span>&#160;<span class="keyword">public</span>:</div>
+<div class="line"><a name="l07680"></a><span class="lineno"> 7680</span>&#160;    VmaStringBuilder(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> alloc) : m_Data(VmaStlAllocator&lt;char&gt;(alloc-&gt;GetAllocationCallbacks())) { }</div>
+<div class="line"><a name="l07681"></a><span class="lineno"> 7681</span>&#160;    <span class="keywordtype">size_t</span> GetLength()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_Data.size(); }</div>
+<div class="line"><a name="l07682"></a><span class="lineno"> 7682</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">char</span>* GetData()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> m_Data.data(); }</div>
+<div class="line"><a name="l07683"></a><span class="lineno"> 7683</span>&#160; </div>
+<div class="line"><a name="l07684"></a><span class="lineno"> 7684</span>&#160;    <span class="keywordtype">void</span> Add(<span class="keywordtype">char</span> ch) { m_Data.push_back(ch); }</div>
+<div class="line"><a name="l07685"></a><span class="lineno"> 7685</span>&#160;    <span class="keywordtype">void</span> Add(<span class="keyword">const</span> <span class="keywordtype">char</span>* pStr);</div>
+<div class="line"><a name="l07686"></a><span class="lineno"> 7686</span>&#160;    <span class="keywordtype">void</span> AddNewLine() { Add(<span class="charliteral">&#39;\n&#39;</span>); }</div>
+<div class="line"><a name="l07687"></a><span class="lineno"> 7687</span>&#160;    <span class="keywordtype">void</span> AddNumber(uint32_t num);</div>
+<div class="line"><a name="l07688"></a><span class="lineno"> 7688</span>&#160;    <span class="keywordtype">void</span> AddNumber(uint64_t num);</div>
+<div class="line"><a name="l07689"></a><span class="lineno"> 7689</span>&#160;    <span class="keywordtype">void</span> AddPointer(<span class="keyword">const</span> <span class="keywordtype">void</span>* ptr);</div>
+<div class="line"><a name="l07690"></a><span class="lineno"> 7690</span>&#160; </div>
+<div class="line"><a name="l07691"></a><span class="lineno"> 7691</span>&#160;<span class="keyword">private</span>:</div>
+<div class="line"><a name="l07692"></a><span class="lineno"> 7692</span>&#160;    VmaVector&lt; char, VmaStlAllocator&lt;char&gt; &gt; m_Data;</div>
+<div class="line"><a name="l07693"></a><span class="lineno"> 7693</span>&#160;};</div>
+<div class="line"><a name="l07694"></a><span class="lineno"> 7694</span>&#160; </div>
+<div class="line"><a name="l07695"></a><span class="lineno"> 7695</span>&#160;<span class="keywordtype">void</span> VmaStringBuilder::Add(<span class="keyword">const</span> <span class="keywordtype">char</span>* pStr)</div>
+<div class="line"><a name="l07696"></a><span class="lineno"> 7696</span>&#160;{</div>
+<div class="line"><a name="l07697"></a><span class="lineno"> 7697</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">size_t</span> strLen = strlen(pStr);</div>
+<div class="line"><a name="l07698"></a><span class="lineno"> 7698</span>&#160;    <span class="keywordflow">if</span>(strLen &gt; 0)</div>
+<div class="line"><a name="l07699"></a><span class="lineno"> 7699</span>&#160;    {</div>
+<div class="line"><a name="l07700"></a><span class="lineno"> 7700</span>&#160;        <span class="keyword">const</span> <span class="keywordtype">size_t</span> oldCount = m_Data.size();</div>
+<div class="line"><a name="l07701"></a><span class="lineno"> 7701</span>&#160;        m_Data.resize(oldCount + strLen);</div>
+<div class="line"><a name="l07702"></a><span class="lineno"> 7702</span>&#160;        memcpy(m_Data.data() + oldCount, pStr, strLen);</div>
+<div class="line"><a name="l07703"></a><span class="lineno"> 7703</span>&#160;    }</div>
+<div class="line"><a name="l07704"></a><span class="lineno"> 7704</span>&#160;}</div>
+<div class="line"><a name="l07705"></a><span class="lineno"> 7705</span>&#160; </div>
+<div class="line"><a name="l07706"></a><span class="lineno"> 7706</span>&#160;<span class="keywordtype">void</span> VmaStringBuilder::AddNumber(uint32_t num)</div>
+<div class="line"><a name="l07707"></a><span class="lineno"> 7707</span>&#160;{</div>
+<div class="line"><a name="l07708"></a><span class="lineno"> 7708</span>&#160;    <span class="keywordtype">char</span> buf[11];</div>
+<div class="line"><a name="l07709"></a><span class="lineno"> 7709</span>&#160;    buf[10] = <span class="charliteral">&#39;\0&#39;</span>;</div>
+<div class="line"><a name="l07710"></a><span class="lineno"> 7710</span>&#160;    <span class="keywordtype">char</span> *p = &amp;buf[10];</div>
+<div class="line"><a name="l07711"></a><span class="lineno"> 7711</span>&#160;    <span class="keywordflow">do</span></div>
+<div class="line"><a name="l07712"></a><span class="lineno"> 7712</span>&#160;    {</div>
+<div class="line"><a name="l07713"></a><span class="lineno"> 7713</span>&#160;        *--p = <span class="charliteral">&#39;0&#39;</span> + (num % 10);</div>
+<div class="line"><a name="l07714"></a><span class="lineno"> 7714</span>&#160;        num /= 10;</div>
+<div class="line"><a name="l07715"></a><span class="lineno"> 7715</span>&#160;    }</div>
+<div class="line"><a name="l07716"></a><span class="lineno"> 7716</span>&#160;    <span class="keywordflow">while</span>(num);</div>
+<div class="line"><a name="l07717"></a><span class="lineno"> 7717</span>&#160;    Add(p);</div>
+<div class="line"><a name="l07718"></a><span class="lineno"> 7718</span>&#160;}</div>
+<div class="line"><a name="l07719"></a><span class="lineno"> 7719</span>&#160; </div>
+<div class="line"><a name="l07720"></a><span class="lineno"> 7720</span>&#160;<span class="keywordtype">void</span> VmaStringBuilder::AddNumber(uint64_t num)</div>
+<div class="line"><a name="l07721"></a><span class="lineno"> 7721</span>&#160;{</div>
+<div class="line"><a name="l07722"></a><span class="lineno"> 7722</span>&#160;    <span class="keywordtype">char</span> buf[21];</div>
+<div class="line"><a name="l07723"></a><span class="lineno"> 7723</span>&#160;    buf[20] = <span class="charliteral">&#39;\0&#39;</span>;</div>
+<div class="line"><a name="l07724"></a><span class="lineno"> 7724</span>&#160;    <span class="keywordtype">char</span> *p = &amp;buf[20];</div>
+<div class="line"><a name="l07725"></a><span class="lineno"> 7725</span>&#160;    <span class="keywordflow">do</span></div>
+<div class="line"><a name="l07726"></a><span class="lineno"> 7726</span>&#160;    {</div>
+<div class="line"><a name="l07727"></a><span class="lineno"> 7727</span>&#160;        *--p = <span class="charliteral">&#39;0&#39;</span> + (num % 10);</div>
+<div class="line"><a name="l07728"></a><span class="lineno"> 7728</span>&#160;        num /= 10;</div>
+<div class="line"><a name="l07729"></a><span class="lineno"> 7729</span>&#160;    }</div>
+<div class="line"><a name="l07730"></a><span class="lineno"> 7730</span>&#160;    <span class="keywordflow">while</span>(num);</div>
+<div class="line"><a name="l07731"></a><span class="lineno"> 7731</span>&#160;    Add(p);</div>
+<div class="line"><a name="l07732"></a><span class="lineno"> 7732</span>&#160;}</div>
+<div class="line"><a name="l07733"></a><span class="lineno"> 7733</span>&#160; </div>
+<div class="line"><a name="l07734"></a><span class="lineno"> 7734</span>&#160;<span class="keywordtype">void</span> VmaStringBuilder::AddPointer(<span class="keyword">const</span> <span class="keywordtype">void</span>* ptr)</div>
+<div class="line"><a name="l07735"></a><span class="lineno"> 7735</span>&#160;{</div>
+<div class="line"><a name="l07736"></a><span class="lineno"> 7736</span>&#160;    <span class="keywordtype">char</span> buf[21];</div>
+<div class="line"><a name="l07737"></a><span class="lineno"> 7737</span>&#160;    VmaPtrToStr(buf, <span class="keyword">sizeof</span>(buf), ptr);</div>
+<div class="line"><a name="l07738"></a><span class="lineno"> 7738</span>&#160;    Add(buf);</div>
+<div class="line"><a name="l07739"></a><span class="lineno"> 7739</span>&#160;}</div>
+<div class="line"><a name="l07740"></a><span class="lineno"> 7740</span>&#160; </div>
+<div class="line"><a name="l07741"></a><span class="lineno"> 7741</span>&#160;<span class="preprocessor">#endif // #if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l07742"></a><span class="lineno"> 7742</span>&#160; </div>
+<div class="line"><a name="l07744"></a><span class="lineno"> 7744</span>&#160;<span class="comment">// VmaJsonWriter</span></div>
+<div class="line"><a name="l07745"></a><span class="lineno"> 7745</span>&#160; </div>
+<div class="line"><a name="l07746"></a><span class="lineno"> 7746</span>&#160;<span class="preprocessor">#if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l07747"></a><span class="lineno"> 7747</span>&#160; </div>
+<div class="line"><a name="l07748"></a><span class="lineno"> 7748</span>&#160;<span class="keyword">class </span>VmaJsonWriter</div>
+<div class="line"><a name="l07749"></a><span class="lineno"> 7749</span>&#160;{</div>
+<div class="line"><a name="l07750"></a><span class="lineno"> 7750</span>&#160;    VMA_CLASS_NO_COPY(VmaJsonWriter)</div>
+<div class="line"><a name="l07751"></a><span class="lineno"> 7751</span>&#160;<span class="keyword">public</span>:</div>
+<div class="line"><a name="l07752"></a><span class="lineno"> 7752</span>&#160;    VmaJsonWriter(<span class="keyword">const</span> VkAllocationCallbacks* pAllocationCallbacks, VmaStringBuilder&amp; sb);</div>
+<div class="line"><a name="l07753"></a><span class="lineno"> 7753</span>&#160;    ~VmaJsonWriter();</div>
+<div class="line"><a name="l07754"></a><span class="lineno"> 7754</span>&#160; </div>
+<div class="line"><a name="l07755"></a><span class="lineno"> 7755</span>&#160;    <span class="keywordtype">void</span> BeginObject(<span class="keywordtype">bool</span> singleLine = <span class="keyword">false</span>);</div>
+<div class="line"><a name="l07756"></a><span class="lineno"> 7756</span>&#160;    <span class="keywordtype">void</span> EndObject();</div>
+<div class="line"><a name="l07757"></a><span class="lineno"> 7757</span>&#160;    </div>
+<div class="line"><a name="l07758"></a><span class="lineno"> 7758</span>&#160;    <span class="keywordtype">void</span> BeginArray(<span class="keywordtype">bool</span> singleLine = <span class="keyword">false</span>);</div>
+<div class="line"><a name="l07759"></a><span class="lineno"> 7759</span>&#160;    <span class="keywordtype">void</span> EndArray();</div>
+<div class="line"><a name="l07760"></a><span class="lineno"> 7760</span>&#160;    </div>
+<div class="line"><a name="l07761"></a><span class="lineno"> 7761</span>&#160;    <span class="keywordtype">void</span> WriteString(<span class="keyword">const</span> <span class="keywordtype">char</span>* pStr);</div>
+<div class="line"><a name="l07762"></a><span class="lineno"> 7762</span>&#160;    <span class="keywordtype">void</span> BeginString(<span class="keyword">const</span> <span class="keywordtype">char</span>* pStr = VMA_NULL);</div>
+<div class="line"><a name="l07763"></a><span class="lineno"> 7763</span>&#160;    <span class="keywordtype">void</span> ContinueString(<span class="keyword">const</span> <span class="keywordtype">char</span>* pStr);</div>
+<div class="line"><a name="l07764"></a><span class="lineno"> 7764</span>&#160;    <span class="keywordtype">void</span> ContinueString(uint32_t n);</div>
+<div class="line"><a name="l07765"></a><span class="lineno"> 7765</span>&#160;    <span class="keywordtype">void</span> ContinueString(uint64_t n);</div>
+<div class="line"><a name="l07766"></a><span class="lineno"> 7766</span>&#160;    <span class="keywordtype">void</span> ContinueString_Pointer(<span class="keyword">const</span> <span class="keywordtype">void</span>* ptr);</div>
+<div class="line"><a name="l07767"></a><span class="lineno"> 7767</span>&#160;    <span class="keywordtype">void</span> EndString(<span class="keyword">const</span> <span class="keywordtype">char</span>* pStr = VMA_NULL);</div>
+<div class="line"><a name="l07768"></a><span class="lineno"> 7768</span>&#160;    </div>
+<div class="line"><a name="l07769"></a><span class="lineno"> 7769</span>&#160;    <span class="keywordtype">void</span> WriteNumber(uint32_t n);</div>
+<div class="line"><a name="l07770"></a><span class="lineno"> 7770</span>&#160;    <span class="keywordtype">void</span> WriteNumber(uint64_t n);</div>
+<div class="line"><a name="l07771"></a><span class="lineno"> 7771</span>&#160;    <span class="keywordtype">void</span> WriteBool(<span class="keywordtype">bool</span> b);</div>
+<div class="line"><a name="l07772"></a><span class="lineno"> 7772</span>&#160;    <span class="keywordtype">void</span> WriteNull();</div>
+<div class="line"><a name="l07773"></a><span class="lineno"> 7773</span>&#160; </div>
+<div class="line"><a name="l07774"></a><span class="lineno"> 7774</span>&#160;<span class="keyword">private</span>:</div>
+<div class="line"><a name="l07775"></a><span class="lineno"> 7775</span>&#160;    <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">char</span>* <span class="keyword">const</span> INDENT;</div>
+<div class="line"><a name="l07776"></a><span class="lineno"> 7776</span>&#160; </div>
+<div class="line"><a name="l07777"></a><span class="lineno"> 7777</span>&#160;    <span class="keyword">enum</span> COLLECTION_TYPE</div>
+<div class="line"><a name="l07778"></a><span class="lineno"> 7778</span>&#160;    {</div>
+<div class="line"><a name="l07779"></a><span class="lineno"> 7779</span>&#160;        COLLECTION_TYPE_OBJECT,</div>
+<div class="line"><a name="l07780"></a><span class="lineno"> 7780</span>&#160;        COLLECTION_TYPE_ARRAY,</div>
+<div class="line"><a name="l07781"></a><span class="lineno"> 7781</span>&#160;    };</div>
+<div class="line"><a name="l07782"></a><span class="lineno"> 7782</span>&#160;    <span class="keyword">struct </span>StackItem</div>
+<div class="line"><a name="l07783"></a><span class="lineno"> 7783</span>&#160;    {</div>
+<div class="line"><a name="l07784"></a><span class="lineno"> 7784</span>&#160;        COLLECTION_TYPE type;</div>
+<div class="line"><a name="l07785"></a><span class="lineno"> 7785</span>&#160;        uint32_t valueCount;</div>
+<div class="line"><a name="l07786"></a><span class="lineno"> 7786</span>&#160;        <span class="keywordtype">bool</span> singleLineMode;</div>
+<div class="line"><a name="l07787"></a><span class="lineno"> 7787</span>&#160;    };</div>
+<div class="line"><a name="l07788"></a><span class="lineno"> 7788</span>&#160; </div>
+<div class="line"><a name="l07789"></a><span class="lineno"> 7789</span>&#160;    VmaStringBuilder&amp; m_SB;</div>
+<div class="line"><a name="l07790"></a><span class="lineno"> 7790</span>&#160;    VmaVector&lt; StackItem, VmaStlAllocator&lt;StackItem&gt; &gt; m_Stack;</div>
+<div class="line"><a name="l07791"></a><span class="lineno"> 7791</span>&#160;    <span class="keywordtype">bool</span> m_InsideString;</div>
+<div class="line"><a name="l07792"></a><span class="lineno"> 7792</span>&#160; </div>
+<div class="line"><a name="l07793"></a><span class="lineno"> 7793</span>&#160;    <span class="keywordtype">void</span> BeginValue(<span class="keywordtype">bool</span> isString);</div>
+<div class="line"><a name="l07794"></a><span class="lineno"> 7794</span>&#160;    <span class="keywordtype">void</span> WriteIndent(<span class="keywordtype">bool</span> oneLess = <span class="keyword">false</span>);</div>
+<div class="line"><a name="l07795"></a><span class="lineno"> 7795</span>&#160;};</div>
+<div class="line"><a name="l07796"></a><span class="lineno"> 7796</span>&#160; </div>
+<div class="line"><a name="l07797"></a><span class="lineno"> 7797</span>&#160;<span class="keyword">const</span> <span class="keywordtype">char</span>* <span class="keyword">const</span> VmaJsonWriter::INDENT = <span class="stringliteral">&quot;  &quot;</span>;</div>
+<div class="line"><a name="l07798"></a><span class="lineno"> 7798</span>&#160; </div>
+<div class="line"><a name="l07799"></a><span class="lineno"> 7799</span>&#160;VmaJsonWriter::VmaJsonWriter(<span class="keyword">const</span> VkAllocationCallbacks* pAllocationCallbacks, VmaStringBuilder&amp; sb) :</div>
+<div class="line"><a name="l07800"></a><span class="lineno"> 7800</span>&#160;    m_SB(sb),</div>
+<div class="line"><a name="l07801"></a><span class="lineno"> 7801</span>&#160;    m_Stack(VmaStlAllocator&lt;StackItem&gt;(pAllocationCallbacks)),</div>
+<div class="line"><a name="l07802"></a><span class="lineno"> 7802</span>&#160;    m_InsideString(false)</div>
+<div class="line"><a name="l07803"></a><span class="lineno"> 7803</span>&#160;{</div>
+<div class="line"><a name="l07804"></a><span class="lineno"> 7804</span>&#160;}</div>
+<div class="line"><a name="l07805"></a><span class="lineno"> 7805</span>&#160; </div>
+<div class="line"><a name="l07806"></a><span class="lineno"> 7806</span>&#160;VmaJsonWriter::~VmaJsonWriter()</div>
+<div class="line"><a name="l07807"></a><span class="lineno"> 7807</span>&#160;{</div>
+<div class="line"><a name="l07808"></a><span class="lineno"> 7808</span>&#160;    VMA_ASSERT(!m_InsideString);</div>
+<div class="line"><a name="l07809"></a><span class="lineno"> 7809</span>&#160;    VMA_ASSERT(m_Stack.empty());</div>
+<div class="line"><a name="l07810"></a><span class="lineno"> 7810</span>&#160;}</div>
+<div class="line"><a name="l07811"></a><span class="lineno"> 7811</span>&#160; </div>
+<div class="line"><a name="l07812"></a><span class="lineno"> 7812</span>&#160;<span class="keywordtype">void</span> VmaJsonWriter::BeginObject(<span class="keywordtype">bool</span> singleLine)</div>
+<div class="line"><a name="l07813"></a><span class="lineno"> 7813</span>&#160;{</div>
+<div class="line"><a name="l07814"></a><span class="lineno"> 7814</span>&#160;    VMA_ASSERT(!m_InsideString);</div>
+<div class="line"><a name="l07815"></a><span class="lineno"> 7815</span>&#160; </div>
+<div class="line"><a name="l07816"></a><span class="lineno"> 7816</span>&#160;    BeginValue(<span class="keyword">false</span>);</div>
+<div class="line"><a name="l07817"></a><span class="lineno"> 7817</span>&#160;    m_SB.Add(<span class="charliteral">&#39;{&#39;</span>);</div>
+<div class="line"><a name="l07818"></a><span class="lineno"> 7818</span>&#160; </div>
+<div class="line"><a name="l07819"></a><span class="lineno"> 7819</span>&#160;    StackItem item;</div>
+<div class="line"><a name="l07820"></a><span class="lineno"> 7820</span>&#160;    item.type = COLLECTION_TYPE_OBJECT;</div>
+<div class="line"><a name="l07821"></a><span class="lineno"> 7821</span>&#160;    item.valueCount = 0;</div>
+<div class="line"><a name="l07822"></a><span class="lineno"> 7822</span>&#160;    item.singleLineMode = singleLine;</div>
+<div class="line"><a name="l07823"></a><span class="lineno"> 7823</span>&#160;    m_Stack.push_back(item);</div>
+<div class="line"><a name="l07824"></a><span class="lineno"> 7824</span>&#160;}</div>
+<div class="line"><a name="l07825"></a><span class="lineno"> 7825</span>&#160; </div>
+<div class="line"><a name="l07826"></a><span class="lineno"> 7826</span>&#160;<span class="keywordtype">void</span> VmaJsonWriter::EndObject()</div>
+<div class="line"><a name="l07827"></a><span class="lineno"> 7827</span>&#160;{</div>
+<div class="line"><a name="l07828"></a><span class="lineno"> 7828</span>&#160;    VMA_ASSERT(!m_InsideString);</div>
+<div class="line"><a name="l07829"></a><span class="lineno"> 7829</span>&#160; </div>
+<div class="line"><a name="l07830"></a><span class="lineno"> 7830</span>&#160;    WriteIndent(<span class="keyword">true</span>);</div>
+<div class="line"><a name="l07831"></a><span class="lineno"> 7831</span>&#160;    m_SB.Add(<span class="charliteral">&#39;}&#39;</span>);</div>
+<div class="line"><a name="l07832"></a><span class="lineno"> 7832</span>&#160; </div>
+<div class="line"><a name="l07833"></a><span class="lineno"> 7833</span>&#160;    VMA_ASSERT(!m_Stack.empty() &amp;&amp; m_Stack.back().type == COLLECTION_TYPE_OBJECT);</div>
+<div class="line"><a name="l07834"></a><span class="lineno"> 7834</span>&#160;    m_Stack.pop_back();</div>
+<div class="line"><a name="l07835"></a><span class="lineno"> 7835</span>&#160;}</div>
+<div class="line"><a name="l07836"></a><span class="lineno"> 7836</span>&#160; </div>
+<div class="line"><a name="l07837"></a><span class="lineno"> 7837</span>&#160;<span class="keywordtype">void</span> VmaJsonWriter::BeginArray(<span class="keywordtype">bool</span> singleLine)</div>
+<div class="line"><a name="l07838"></a><span class="lineno"> 7838</span>&#160;{</div>
+<div class="line"><a name="l07839"></a><span class="lineno"> 7839</span>&#160;    VMA_ASSERT(!m_InsideString);</div>
+<div class="line"><a name="l07840"></a><span class="lineno"> 7840</span>&#160; </div>
+<div class="line"><a name="l07841"></a><span class="lineno"> 7841</span>&#160;    BeginValue(<span class="keyword">false</span>);</div>
+<div class="line"><a name="l07842"></a><span class="lineno"> 7842</span>&#160;    m_SB.Add(<span class="charliteral">&#39;[&#39;</span>);</div>
+<div class="line"><a name="l07843"></a><span class="lineno"> 7843</span>&#160; </div>
+<div class="line"><a name="l07844"></a><span class="lineno"> 7844</span>&#160;    StackItem item;</div>
+<div class="line"><a name="l07845"></a><span class="lineno"> 7845</span>&#160;    item.type = COLLECTION_TYPE_ARRAY;</div>
+<div class="line"><a name="l07846"></a><span class="lineno"> 7846</span>&#160;    item.valueCount = 0;</div>
+<div class="line"><a name="l07847"></a><span class="lineno"> 7847</span>&#160;    item.singleLineMode = singleLine;</div>
+<div class="line"><a name="l07848"></a><span class="lineno"> 7848</span>&#160;    m_Stack.push_back(item);</div>
+<div class="line"><a name="l07849"></a><span class="lineno"> 7849</span>&#160;}</div>
+<div class="line"><a name="l07850"></a><span class="lineno"> 7850</span>&#160; </div>
+<div class="line"><a name="l07851"></a><span class="lineno"> 7851</span>&#160;<span class="keywordtype">void</span> VmaJsonWriter::EndArray()</div>
+<div class="line"><a name="l07852"></a><span class="lineno"> 7852</span>&#160;{</div>
+<div class="line"><a name="l07853"></a><span class="lineno"> 7853</span>&#160;    VMA_ASSERT(!m_InsideString);</div>
+<div class="line"><a name="l07854"></a><span class="lineno"> 7854</span>&#160; </div>
+<div class="line"><a name="l07855"></a><span class="lineno"> 7855</span>&#160;    WriteIndent(<span class="keyword">true</span>);</div>
+<div class="line"><a name="l07856"></a><span class="lineno"> 7856</span>&#160;    m_SB.Add(<span class="charliteral">&#39;]&#39;</span>);</div>
+<div class="line"><a name="l07857"></a><span class="lineno"> 7857</span>&#160; </div>
+<div class="line"><a name="l07858"></a><span class="lineno"> 7858</span>&#160;    VMA_ASSERT(!m_Stack.empty() &amp;&amp; m_Stack.back().type == COLLECTION_TYPE_ARRAY);</div>
+<div class="line"><a name="l07859"></a><span class="lineno"> 7859</span>&#160;    m_Stack.pop_back();</div>
+<div class="line"><a name="l07860"></a><span class="lineno"> 7860</span>&#160;}</div>
+<div class="line"><a name="l07861"></a><span class="lineno"> 7861</span>&#160; </div>
+<div class="line"><a name="l07862"></a><span class="lineno"> 7862</span>&#160;<span class="keywordtype">void</span> VmaJsonWriter::WriteString(<span class="keyword">const</span> <span class="keywordtype">char</span>* pStr)</div>
+<div class="line"><a name="l07863"></a><span class="lineno"> 7863</span>&#160;{</div>
+<div class="line"><a name="l07864"></a><span class="lineno"> 7864</span>&#160;    BeginString(pStr);</div>
+<div class="line"><a name="l07865"></a><span class="lineno"> 7865</span>&#160;    EndString();</div>
+<div class="line"><a name="l07866"></a><span class="lineno"> 7866</span>&#160;}</div>
+<div class="line"><a name="l07867"></a><span class="lineno"> 7867</span>&#160; </div>
+<div class="line"><a name="l07868"></a><span class="lineno"> 7868</span>&#160;<span class="keywordtype">void</span> VmaJsonWriter::BeginString(<span class="keyword">const</span> <span class="keywordtype">char</span>* pStr)</div>
+<div class="line"><a name="l07869"></a><span class="lineno"> 7869</span>&#160;{</div>
+<div class="line"><a name="l07870"></a><span class="lineno"> 7870</span>&#160;    VMA_ASSERT(!m_InsideString);</div>
+<div class="line"><a name="l07871"></a><span class="lineno"> 7871</span>&#160; </div>
+<div class="line"><a name="l07872"></a><span class="lineno"> 7872</span>&#160;    BeginValue(<span class="keyword">true</span>);</div>
+<div class="line"><a name="l07873"></a><span class="lineno"> 7873</span>&#160;    m_SB.Add(<span class="charliteral">&#39;&quot;&#39;</span>);</div>
+<div class="line"><a name="l07874"></a><span class="lineno"> 7874</span>&#160;    m_InsideString = <span class="keyword">true</span>;</div>
+<div class="line"><a name="l07875"></a><span class="lineno"> 7875</span>&#160;    <span class="keywordflow">if</span>(pStr != VMA_NULL &amp;&amp; pStr[0] != <span class="charliteral">&#39;\0&#39;</span>)</div>
+<div class="line"><a name="l07876"></a><span class="lineno"> 7876</span>&#160;    {</div>
+<div class="line"><a name="l07877"></a><span class="lineno"> 7877</span>&#160;        ContinueString(pStr);</div>
+<div class="line"><a name="l07878"></a><span class="lineno"> 7878</span>&#160;    }</div>
+<div class="line"><a name="l07879"></a><span class="lineno"> 7879</span>&#160;}</div>
+<div class="line"><a name="l07880"></a><span class="lineno"> 7880</span>&#160; </div>
+<div class="line"><a name="l07881"></a><span class="lineno"> 7881</span>&#160;<span class="keywordtype">void</span> VmaJsonWriter::ContinueString(<span class="keyword">const</span> <span class="keywordtype">char</span>* pStr)</div>
+<div class="line"><a name="l07882"></a><span class="lineno"> 7882</span>&#160;{</div>
+<div class="line"><a name="l07883"></a><span class="lineno"> 7883</span>&#160;    VMA_ASSERT(m_InsideString);</div>
+<div class="line"><a name="l07884"></a><span class="lineno"> 7884</span>&#160; </div>
+<div class="line"><a name="l07885"></a><span class="lineno"> 7885</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">size_t</span> strLen = strlen(pStr);</div>
+<div class="line"><a name="l07886"></a><span class="lineno"> 7886</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = 0; i &lt; strLen; ++i)</div>
+<div class="line"><a name="l07887"></a><span class="lineno"> 7887</span>&#160;    {</div>
+<div class="line"><a name="l07888"></a><span class="lineno"> 7888</span>&#160;        <span class="keywordtype">char</span> ch = pStr[i];</div>
+<div class="line"><a name="l07889"></a><span class="lineno"> 7889</span>&#160;        <span class="keywordflow">if</span>(ch == <span class="charliteral">&#39;\\&#39;</span>)</div>
+<div class="line"><a name="l07890"></a><span class="lineno"> 7890</span>&#160;        {</div>
+<div class="line"><a name="l07891"></a><span class="lineno"> 7891</span>&#160;            m_SB.Add(<span class="stringliteral">&quot;\\\\&quot;</span>);</div>
+<div class="line"><a name="l07892"></a><span class="lineno"> 7892</span>&#160;        }</div>
+<div class="line"><a name="l07893"></a><span class="lineno"> 7893</span>&#160;        <span class="keywordflow">else</span> <span class="keywordflow">if</span>(ch == <span class="charliteral">&#39;&quot;&#39;</span>)</div>
+<div class="line"><a name="l07894"></a><span class="lineno"> 7894</span>&#160;        {</div>
+<div class="line"><a name="l07895"></a><span class="lineno"> 7895</span>&#160;            m_SB.Add(<span class="stringliteral">&quot;\\\&quot;&quot;</span>);</div>
+<div class="line"><a name="l07896"></a><span class="lineno"> 7896</span>&#160;        }</div>
+<div class="line"><a name="l07897"></a><span class="lineno"> 7897</span>&#160;        <span class="keywordflow">else</span> <span class="keywordflow">if</span>(ch &gt;= 32)</div>
+<div class="line"><a name="l07898"></a><span class="lineno"> 7898</span>&#160;        {</div>
+<div class="line"><a name="l07899"></a><span class="lineno"> 7899</span>&#160;            m_SB.Add(ch);</div>
+<div class="line"><a name="l07900"></a><span class="lineno"> 7900</span>&#160;        }</div>
+<div class="line"><a name="l07901"></a><span class="lineno"> 7901</span>&#160;        <span class="keywordflow">else</span> <span class="keywordflow">switch</span>(ch)</div>
+<div class="line"><a name="l07902"></a><span class="lineno"> 7902</span>&#160;        {</div>
+<div class="line"><a name="l07903"></a><span class="lineno"> 7903</span>&#160;        <span class="keywordflow">case</span> <span class="charliteral">&#39;\b&#39;</span>:</div>
+<div class="line"><a name="l07904"></a><span class="lineno"> 7904</span>&#160;            m_SB.Add(<span class="stringliteral">&quot;\\b&quot;</span>);</div>
+<div class="line"><a name="l07905"></a><span class="lineno"> 7905</span>&#160;            <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l07906"></a><span class="lineno"> 7906</span>&#160;        <span class="keywordflow">case</span> <span class="charliteral">&#39;\f&#39;</span>:</div>
+<div class="line"><a name="l07907"></a><span class="lineno"> 7907</span>&#160;            m_SB.Add(<span class="stringliteral">&quot;\\f&quot;</span>);</div>
+<div class="line"><a name="l07908"></a><span class="lineno"> 7908</span>&#160;            <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l07909"></a><span class="lineno"> 7909</span>&#160;        <span class="keywordflow">case</span> <span class="charliteral">&#39;\n&#39;</span>:</div>
+<div class="line"><a name="l07910"></a><span class="lineno"> 7910</span>&#160;            m_SB.Add(<span class="stringliteral">&quot;\\n&quot;</span>);</div>
+<div class="line"><a name="l07911"></a><span class="lineno"> 7911</span>&#160;            <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l07912"></a><span class="lineno"> 7912</span>&#160;        <span class="keywordflow">case</span> <span class="charliteral">&#39;\r&#39;</span>:</div>
+<div class="line"><a name="l07913"></a><span class="lineno"> 7913</span>&#160;            m_SB.Add(<span class="stringliteral">&quot;\\r&quot;</span>);</div>
+<div class="line"><a name="l07914"></a><span class="lineno"> 7914</span>&#160;            <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l07915"></a><span class="lineno"> 7915</span>&#160;        <span class="keywordflow">case</span> <span class="charliteral">&#39;\t&#39;</span>:</div>
+<div class="line"><a name="l07916"></a><span class="lineno"> 7916</span>&#160;            m_SB.Add(<span class="stringliteral">&quot;\\t&quot;</span>);</div>
+<div class="line"><a name="l07917"></a><span class="lineno"> 7917</span>&#160;            <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l07918"></a><span class="lineno"> 7918</span>&#160;        <span class="keywordflow">default</span>:</div>
+<div class="line"><a name="l07919"></a><span class="lineno"> 7919</span>&#160;            VMA_ASSERT(0 &amp;&amp; <span class="stringliteral">&quot;Character not currently supported.&quot;</span>);</div>
+<div class="line"><a name="l07920"></a><span class="lineno"> 7920</span>&#160;            <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l07921"></a><span class="lineno"> 7921</span>&#160;        }</div>
+<div class="line"><a name="l07922"></a><span class="lineno"> 7922</span>&#160;    }</div>
+<div class="line"><a name="l07923"></a><span class="lineno"> 7923</span>&#160;}</div>
+<div class="line"><a name="l07924"></a><span class="lineno"> 7924</span>&#160; </div>
+<div class="line"><a name="l07925"></a><span class="lineno"> 7925</span>&#160;<span class="keywordtype">void</span> VmaJsonWriter::ContinueString(uint32_t n)</div>
+<div class="line"><a name="l07926"></a><span class="lineno"> 7926</span>&#160;{</div>
+<div class="line"><a name="l07927"></a><span class="lineno"> 7927</span>&#160;    VMA_ASSERT(m_InsideString);</div>
+<div class="line"><a name="l07928"></a><span class="lineno"> 7928</span>&#160;    m_SB.AddNumber(n);</div>
+<div class="line"><a name="l07929"></a><span class="lineno"> 7929</span>&#160;}</div>
+<div class="line"><a name="l07930"></a><span class="lineno"> 7930</span>&#160; </div>
+<div class="line"><a name="l07931"></a><span class="lineno"> 7931</span>&#160;<span class="keywordtype">void</span> VmaJsonWriter::ContinueString(uint64_t n)</div>
+<div class="line"><a name="l07932"></a><span class="lineno"> 7932</span>&#160;{</div>
+<div class="line"><a name="l07933"></a><span class="lineno"> 7933</span>&#160;    VMA_ASSERT(m_InsideString);</div>
+<div class="line"><a name="l07934"></a><span class="lineno"> 7934</span>&#160;    m_SB.AddNumber(n);</div>
+<div class="line"><a name="l07935"></a><span class="lineno"> 7935</span>&#160;}</div>
+<div class="line"><a name="l07936"></a><span class="lineno"> 7936</span>&#160; </div>
+<div class="line"><a name="l07937"></a><span class="lineno"> 7937</span>&#160;<span class="keywordtype">void</span> VmaJsonWriter::ContinueString_Pointer(<span class="keyword">const</span> <span class="keywordtype">void</span>* ptr)</div>
+<div class="line"><a name="l07938"></a><span class="lineno"> 7938</span>&#160;{</div>
+<div class="line"><a name="l07939"></a><span class="lineno"> 7939</span>&#160;    VMA_ASSERT(m_InsideString);</div>
+<div class="line"><a name="l07940"></a><span class="lineno"> 7940</span>&#160;    m_SB.AddPointer(ptr);</div>
+<div class="line"><a name="l07941"></a><span class="lineno"> 7941</span>&#160;}</div>
+<div class="line"><a name="l07942"></a><span class="lineno"> 7942</span>&#160; </div>
+<div class="line"><a name="l07943"></a><span class="lineno"> 7943</span>&#160;<span class="keywordtype">void</span> VmaJsonWriter::EndString(<span class="keyword">const</span> <span class="keywordtype">char</span>* pStr)</div>
+<div class="line"><a name="l07944"></a><span class="lineno"> 7944</span>&#160;{</div>
+<div class="line"><a name="l07945"></a><span class="lineno"> 7945</span>&#160;    VMA_ASSERT(m_InsideString);</div>
+<div class="line"><a name="l07946"></a><span class="lineno"> 7946</span>&#160;    <span class="keywordflow">if</span>(pStr != VMA_NULL &amp;&amp; pStr[0] != <span class="charliteral">&#39;\0&#39;</span>)</div>
+<div class="line"><a name="l07947"></a><span class="lineno"> 7947</span>&#160;    {</div>
+<div class="line"><a name="l07948"></a><span class="lineno"> 7948</span>&#160;        ContinueString(pStr);</div>
+<div class="line"><a name="l07949"></a><span class="lineno"> 7949</span>&#160;    }</div>
+<div class="line"><a name="l07950"></a><span class="lineno"> 7950</span>&#160;    m_SB.Add(<span class="charliteral">&#39;&quot;&#39;</span>);</div>
+<div class="line"><a name="l07951"></a><span class="lineno"> 7951</span>&#160;    m_InsideString = <span class="keyword">false</span>;</div>
+<div class="line"><a name="l07952"></a><span class="lineno"> 7952</span>&#160;}</div>
+<div class="line"><a name="l07953"></a><span class="lineno"> 7953</span>&#160; </div>
+<div class="line"><a name="l07954"></a><span class="lineno"> 7954</span>&#160;<span class="keywordtype">void</span> VmaJsonWriter::WriteNumber(uint32_t n)</div>
+<div class="line"><a name="l07955"></a><span class="lineno"> 7955</span>&#160;{</div>
+<div class="line"><a name="l07956"></a><span class="lineno"> 7956</span>&#160;    VMA_ASSERT(!m_InsideString);</div>
+<div class="line"><a name="l07957"></a><span class="lineno"> 7957</span>&#160;    BeginValue(<span class="keyword">false</span>);</div>
+<div class="line"><a name="l07958"></a><span class="lineno"> 7958</span>&#160;    m_SB.AddNumber(n);</div>
+<div class="line"><a name="l07959"></a><span class="lineno"> 7959</span>&#160;}</div>
+<div class="line"><a name="l07960"></a><span class="lineno"> 7960</span>&#160; </div>
+<div class="line"><a name="l07961"></a><span class="lineno"> 7961</span>&#160;<span class="keywordtype">void</span> VmaJsonWriter::WriteNumber(uint64_t n)</div>
+<div class="line"><a name="l07962"></a><span class="lineno"> 7962</span>&#160;{</div>
+<div class="line"><a name="l07963"></a><span class="lineno"> 7963</span>&#160;    VMA_ASSERT(!m_InsideString);</div>
+<div class="line"><a name="l07964"></a><span class="lineno"> 7964</span>&#160;    BeginValue(<span class="keyword">false</span>);</div>
+<div class="line"><a name="l07965"></a><span class="lineno"> 7965</span>&#160;    m_SB.AddNumber(n);</div>
+<div class="line"><a name="l07966"></a><span class="lineno"> 7966</span>&#160;}</div>
+<div class="line"><a name="l07967"></a><span class="lineno"> 7967</span>&#160; </div>
+<div class="line"><a name="l07968"></a><span class="lineno"> 7968</span>&#160;<span class="keywordtype">void</span> VmaJsonWriter::WriteBool(<span class="keywordtype">bool</span> b)</div>
+<div class="line"><a name="l07969"></a><span class="lineno"> 7969</span>&#160;{</div>
+<div class="line"><a name="l07970"></a><span class="lineno"> 7970</span>&#160;    VMA_ASSERT(!m_InsideString);</div>
+<div class="line"><a name="l07971"></a><span class="lineno"> 7971</span>&#160;    BeginValue(<span class="keyword">false</span>);</div>
+<div class="line"><a name="l07972"></a><span class="lineno"> 7972</span>&#160;    m_SB.Add(b ? <span class="stringliteral">&quot;true&quot;</span> : <span class="stringliteral">&quot;false&quot;</span>);</div>
+<div class="line"><a name="l07973"></a><span class="lineno"> 7973</span>&#160;}</div>
+<div class="line"><a name="l07974"></a><span class="lineno"> 7974</span>&#160; </div>
+<div class="line"><a name="l07975"></a><span class="lineno"> 7975</span>&#160;<span class="keywordtype">void</span> VmaJsonWriter::WriteNull()</div>
+<div class="line"><a name="l07976"></a><span class="lineno"> 7976</span>&#160;{</div>
+<div class="line"><a name="l07977"></a><span class="lineno"> 7977</span>&#160;    VMA_ASSERT(!m_InsideString);</div>
+<div class="line"><a name="l07978"></a><span class="lineno"> 7978</span>&#160;    BeginValue(<span class="keyword">false</span>);</div>
+<div class="line"><a name="l07979"></a><span class="lineno"> 7979</span>&#160;    m_SB.Add(<span class="stringliteral">&quot;null&quot;</span>);</div>
+<div class="line"><a name="l07980"></a><span class="lineno"> 7980</span>&#160;}</div>
+<div class="line"><a name="l07981"></a><span class="lineno"> 7981</span>&#160; </div>
+<div class="line"><a name="l07982"></a><span class="lineno"> 7982</span>&#160;<span class="keywordtype">void</span> VmaJsonWriter::BeginValue(<span class="keywordtype">bool</span> isString)</div>
+<div class="line"><a name="l07983"></a><span class="lineno"> 7983</span>&#160;{</div>
+<div class="line"><a name="l07984"></a><span class="lineno"> 7984</span>&#160;    <span class="keywordflow">if</span>(!m_Stack.empty())</div>
+<div class="line"><a name="l07985"></a><span class="lineno"> 7985</span>&#160;    {</div>
+<div class="line"><a name="l07986"></a><span class="lineno"> 7986</span>&#160;        StackItem&amp; currItem = m_Stack.back();</div>
+<div class="line"><a name="l07987"></a><span class="lineno"> 7987</span>&#160;        <span class="keywordflow">if</span>(currItem.type == COLLECTION_TYPE_OBJECT &amp;&amp;</div>
+<div class="line"><a name="l07988"></a><span class="lineno"> 7988</span>&#160;            currItem.valueCount % 2 == 0)</div>
+<div class="line"><a name="l07989"></a><span class="lineno"> 7989</span>&#160;        {</div>
+<div class="line"><a name="l07990"></a><span class="lineno"> 7990</span>&#160;            VMA_ASSERT(isString);</div>
+<div class="line"><a name="l07991"></a><span class="lineno"> 7991</span>&#160;        }</div>
+<div class="line"><a name="l07992"></a><span class="lineno"> 7992</span>&#160; </div>
+<div class="line"><a name="l07993"></a><span class="lineno"> 7993</span>&#160;        <span class="keywordflow">if</span>(currItem.type == COLLECTION_TYPE_OBJECT &amp;&amp;</div>
+<div class="line"><a name="l07994"></a><span class="lineno"> 7994</span>&#160;            currItem.valueCount % 2 != 0)</div>
+<div class="line"><a name="l07995"></a><span class="lineno"> 7995</span>&#160;        {</div>
+<div class="line"><a name="l07996"></a><span class="lineno"> 7996</span>&#160;            m_SB.Add(<span class="stringliteral">&quot;: &quot;</span>);</div>
+<div class="line"><a name="l07997"></a><span class="lineno"> 7997</span>&#160;        }</div>
+<div class="line"><a name="l07998"></a><span class="lineno"> 7998</span>&#160;        <span class="keywordflow">else</span> <span class="keywordflow">if</span>(currItem.valueCount &gt; 0)</div>
+<div class="line"><a name="l07999"></a><span class="lineno"> 7999</span>&#160;        {</div>
+<div class="line"><a name="l08000"></a><span class="lineno"> 8000</span>&#160;            m_SB.Add(<span class="stringliteral">&quot;, &quot;</span>);</div>
+<div class="line"><a name="l08001"></a><span class="lineno"> 8001</span>&#160;            WriteIndent();</div>
+<div class="line"><a name="l08002"></a><span class="lineno"> 8002</span>&#160;        }</div>
+<div class="line"><a name="l08003"></a><span class="lineno"> 8003</span>&#160;        <span class="keywordflow">else</span></div>
+<div class="line"><a name="l08004"></a><span class="lineno"> 8004</span>&#160;        {</div>
+<div class="line"><a name="l08005"></a><span class="lineno"> 8005</span>&#160;            WriteIndent();</div>
+<div class="line"><a name="l08006"></a><span class="lineno"> 8006</span>&#160;        }</div>
+<div class="line"><a name="l08007"></a><span class="lineno"> 8007</span>&#160;        ++currItem.valueCount;</div>
+<div class="line"><a name="l08008"></a><span class="lineno"> 8008</span>&#160;    }</div>
+<div class="line"><a name="l08009"></a><span class="lineno"> 8009</span>&#160;}</div>
+<div class="line"><a name="l08010"></a><span class="lineno"> 8010</span>&#160; </div>
+<div class="line"><a name="l08011"></a><span class="lineno"> 8011</span>&#160;<span class="keywordtype">void</span> VmaJsonWriter::WriteIndent(<span class="keywordtype">bool</span> oneLess)</div>
+<div class="line"><a name="l08012"></a><span class="lineno"> 8012</span>&#160;{</div>
+<div class="line"><a name="l08013"></a><span class="lineno"> 8013</span>&#160;    <span class="keywordflow">if</span>(!m_Stack.empty() &amp;&amp; !m_Stack.back().singleLineMode)</div>
+<div class="line"><a name="l08014"></a><span class="lineno"> 8014</span>&#160;    {</div>
+<div class="line"><a name="l08015"></a><span class="lineno"> 8015</span>&#160;        m_SB.AddNewLine();</div>
+<div class="line"><a name="l08016"></a><span class="lineno"> 8016</span>&#160;        </div>
+<div class="line"><a name="l08017"></a><span class="lineno"> 8017</span>&#160;        <span class="keywordtype">size_t</span> count = m_Stack.size();</div>
+<div class="line"><a name="l08018"></a><span class="lineno"> 8018</span>&#160;        <span class="keywordflow">if</span>(count &gt; 0 &amp;&amp; oneLess)</div>
+<div class="line"><a name="l08019"></a><span class="lineno"> 8019</span>&#160;        {</div>
+<div class="line"><a name="l08020"></a><span class="lineno"> 8020</span>&#160;            --count;</div>
+<div class="line"><a name="l08021"></a><span class="lineno"> 8021</span>&#160;        }</div>
+<div class="line"><a name="l08022"></a><span class="lineno"> 8022</span>&#160;        <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = 0; i &lt; count; ++i)</div>
+<div class="line"><a name="l08023"></a><span class="lineno"> 8023</span>&#160;        {</div>
+<div class="line"><a name="l08024"></a><span class="lineno"> 8024</span>&#160;            m_SB.Add(INDENT);</div>
+<div class="line"><a name="l08025"></a><span class="lineno"> 8025</span>&#160;        }</div>
+<div class="line"><a name="l08026"></a><span class="lineno"> 8026</span>&#160;    }</div>
+<div class="line"><a name="l08027"></a><span class="lineno"> 8027</span>&#160;}</div>
+<div class="line"><a name="l08028"></a><span class="lineno"> 8028</span>&#160; </div>
+<div class="line"><a name="l08029"></a><span class="lineno"> 8029</span>&#160;<span class="preprocessor">#endif // #if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l08030"></a><span class="lineno"> 8030</span>&#160; </div>
+<div class="line"><a name="l08032"></a><span class="lineno"> 8032</span>&#160; </div>
+<div class="line"><a name="l08033"></a><span class="lineno"> 8033</span>&#160;<span class="keywordtype">void</span> VmaAllocation_T::SetUserData(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator, <span class="keywordtype">void</span>* pUserData)</div>
+<div class="line"><a name="l08034"></a><span class="lineno"> 8034</span>&#160;{</div>
+<div class="line"><a name="l08035"></a><span class="lineno"> 8035</span>&#160;    <span class="keywordflow">if</span>(IsUserDataString())</div>
+<div class="line"><a name="l08036"></a><span class="lineno"> 8036</span>&#160;    {</div>
+<div class="line"><a name="l08037"></a><span class="lineno"> 8037</span>&#160;        VMA_ASSERT(pUserData == VMA_NULL || pUserData != m_pUserData);</div>
+<div class="line"><a name="l08038"></a><span class="lineno"> 8038</span>&#160; </div>
+<div class="line"><a name="l08039"></a><span class="lineno"> 8039</span>&#160;        FreeUserDataString(hAllocator);</div>
+<div class="line"><a name="l08040"></a><span class="lineno"> 8040</span>&#160; </div>
+<div class="line"><a name="l08041"></a><span class="lineno"> 8041</span>&#160;        <span class="keywordflow">if</span>(pUserData != VMA_NULL)</div>
+<div class="line"><a name="l08042"></a><span class="lineno"> 8042</span>&#160;        {</div>
+<div class="line"><a name="l08043"></a><span class="lineno"> 8043</span>&#160;            m_pUserData = VmaCreateStringCopy(hAllocator-&gt;GetAllocationCallbacks(), (<span class="keyword">const</span> <span class="keywordtype">char</span>*)pUserData);</div>
+<div class="line"><a name="l08044"></a><span class="lineno"> 8044</span>&#160;        }</div>
+<div class="line"><a name="l08045"></a><span class="lineno"> 8045</span>&#160;    }</div>
+<div class="line"><a name="l08046"></a><span class="lineno"> 8046</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l08047"></a><span class="lineno"> 8047</span>&#160;    {</div>
+<div class="line"><a name="l08048"></a><span class="lineno"> 8048</span>&#160;        m_pUserData = pUserData;</div>
+<div class="line"><a name="l08049"></a><span class="lineno"> 8049</span>&#160;    }</div>
+<div class="line"><a name="l08050"></a><span class="lineno"> 8050</span>&#160;}</div>
+<div class="line"><a name="l08051"></a><span class="lineno"> 8051</span>&#160; </div>
+<div class="line"><a name="l08052"></a><span class="lineno"> 8052</span>&#160;<span class="keywordtype">void</span> VmaAllocation_T::ChangeBlockAllocation(</div>
+<div class="line"><a name="l08053"></a><span class="lineno"> 8053</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator,</div>
+<div class="line"><a name="l08054"></a><span class="lineno"> 8054</span>&#160;    VmaDeviceMemoryBlock* block,</div>
+<div class="line"><a name="l08055"></a><span class="lineno"> 8055</span>&#160;    VkDeviceSize offset)</div>
+<div class="line"><a name="l08056"></a><span class="lineno"> 8056</span>&#160;{</div>
+<div class="line"><a name="l08057"></a><span class="lineno"> 8057</span>&#160;    VMA_ASSERT(block != VMA_NULL);</div>
+<div class="line"><a name="l08058"></a><span class="lineno"> 8058</span>&#160;    VMA_ASSERT(m_Type == ALLOCATION_TYPE_BLOCK);</div>
+<div class="line"><a name="l08059"></a><span class="lineno"> 8059</span>&#160; </div>
+<div class="line"><a name="l08060"></a><span class="lineno"> 8060</span>&#160;    <span class="comment">// Move mapping reference counter from old block to new block.</span></div>
+<div class="line"><a name="l08061"></a><span class="lineno"> 8061</span>&#160;    <span class="keywordflow">if</span>(block != m_BlockAllocation.m_Block)</div>
+<div class="line"><a name="l08062"></a><span class="lineno"> 8062</span>&#160;    {</div>
+<div class="line"><a name="l08063"></a><span class="lineno"> 8063</span>&#160;        uint32_t mapRefCount = m_MapCount &amp; ~MAP_COUNT_FLAG_PERSISTENT_MAP;</div>
+<div class="line"><a name="l08064"></a><span class="lineno"> 8064</span>&#160;        <span class="keywordflow">if</span>(IsPersistentMap())</div>
+<div class="line"><a name="l08065"></a><span class="lineno"> 8065</span>&#160;            ++mapRefCount;</div>
+<div class="line"><a name="l08066"></a><span class="lineno"> 8066</span>&#160;        m_BlockAllocation.m_Block-&gt;Unmap(hAllocator, mapRefCount);</div>
+<div class="line"><a name="l08067"></a><span class="lineno"> 8067</span>&#160;        block-&gt;Map(hAllocator, mapRefCount, VMA_NULL);</div>
+<div class="line"><a name="l08068"></a><span class="lineno"> 8068</span>&#160;    }</div>
+<div class="line"><a name="l08069"></a><span class="lineno"> 8069</span>&#160; </div>
+<div class="line"><a name="l08070"></a><span class="lineno"> 8070</span>&#160;    m_BlockAllocation.m_Block = block;</div>
+<div class="line"><a name="l08071"></a><span class="lineno"> 8071</span>&#160;    m_BlockAllocation.m_Offset = offset;</div>
+<div class="line"><a name="l08072"></a><span class="lineno"> 8072</span>&#160;}</div>
+<div class="line"><a name="l08073"></a><span class="lineno"> 8073</span>&#160; </div>
+<div class="line"><a name="l08074"></a><span class="lineno"> 8074</span>&#160;<span class="keywordtype">void</span> VmaAllocation_T::ChangeOffset(VkDeviceSize newOffset)</div>
+<div class="line"><a name="l08075"></a><span class="lineno"> 8075</span>&#160;{</div>
+<div class="line"><a name="l08076"></a><span class="lineno"> 8076</span>&#160;    VMA_ASSERT(m_Type == ALLOCATION_TYPE_BLOCK);</div>
+<div class="line"><a name="l08077"></a><span class="lineno"> 8077</span>&#160;    m_BlockAllocation.m_Offset = newOffset;</div>
+<div class="line"><a name="l08078"></a><span class="lineno"> 8078</span>&#160;}</div>
+<div class="line"><a name="l08079"></a><span class="lineno"> 8079</span>&#160; </div>
+<div class="line"><a name="l08080"></a><span class="lineno"> 8080</span>&#160;VkDeviceSize VmaAllocation_T::GetOffset()<span class="keyword"> const</span></div>
+<div class="line"><a name="l08081"></a><span class="lineno"> 8081</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l08082"></a><span class="lineno"> 8082</span>&#160;    <span class="keywordflow">switch</span>(m_Type)</div>
+<div class="line"><a name="l08083"></a><span class="lineno"> 8083</span>&#160;    {</div>
+<div class="line"><a name="l08084"></a><span class="lineno"> 8084</span>&#160;    <span class="keywordflow">case</span> ALLOCATION_TYPE_BLOCK:</div>
+<div class="line"><a name="l08085"></a><span class="lineno"> 8085</span>&#160;        <span class="keywordflow">return</span> m_BlockAllocation.m_Offset;</div>
+<div class="line"><a name="l08086"></a><span class="lineno"> 8086</span>&#160;    <span class="keywordflow">case</span> ALLOCATION_TYPE_DEDICATED:</div>
+<div class="line"><a name="l08087"></a><span class="lineno"> 8087</span>&#160;        <span class="keywordflow">return</span> 0;</div>
+<div class="line"><a name="l08088"></a><span class="lineno"> 8088</span>&#160;    <span class="keywordflow">default</span>:</div>
+<div class="line"><a name="l08089"></a><span class="lineno"> 8089</span>&#160;        VMA_ASSERT(0);</div>
+<div class="line"><a name="l08090"></a><span class="lineno"> 8090</span>&#160;        <span class="keywordflow">return</span> 0;</div>
+<div class="line"><a name="l08091"></a><span class="lineno"> 8091</span>&#160;    }</div>
+<div class="line"><a name="l08092"></a><span class="lineno"> 8092</span>&#160;}</div>
+<div class="line"><a name="l08093"></a><span class="lineno"> 8093</span>&#160; </div>
+<div class="line"><a name="l08094"></a><span class="lineno"> 8094</span>&#160;VkDeviceMemory VmaAllocation_T::GetMemory()<span class="keyword"> const</span></div>
+<div class="line"><a name="l08095"></a><span class="lineno"> 8095</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l08096"></a><span class="lineno"> 8096</span>&#160;    <span class="keywordflow">switch</span>(m_Type)</div>
+<div class="line"><a name="l08097"></a><span class="lineno"> 8097</span>&#160;    {</div>
+<div class="line"><a name="l08098"></a><span class="lineno"> 8098</span>&#160;    <span class="keywordflow">case</span> ALLOCATION_TYPE_BLOCK:</div>
+<div class="line"><a name="l08099"></a><span class="lineno"> 8099</span>&#160;        <span class="keywordflow">return</span> m_BlockAllocation.m_Block-&gt;GetDeviceMemory();</div>
+<div class="line"><a name="l08100"></a><span class="lineno"> 8100</span>&#160;    <span class="keywordflow">case</span> ALLOCATION_TYPE_DEDICATED:</div>
+<div class="line"><a name="l08101"></a><span class="lineno"> 8101</span>&#160;        <span class="keywordflow">return</span> m_DedicatedAllocation.m_hMemory;</div>
+<div class="line"><a name="l08102"></a><span class="lineno"> 8102</span>&#160;    <span class="keywordflow">default</span>:</div>
+<div class="line"><a name="l08103"></a><span class="lineno"> 8103</span>&#160;        VMA_ASSERT(0);</div>
+<div class="line"><a name="l08104"></a><span class="lineno"> 8104</span>&#160;        <span class="keywordflow">return</span> VK_NULL_HANDLE;</div>
+<div class="line"><a name="l08105"></a><span class="lineno"> 8105</span>&#160;    }</div>
+<div class="line"><a name="l08106"></a><span class="lineno"> 8106</span>&#160;}</div>
+<div class="line"><a name="l08107"></a><span class="lineno"> 8107</span>&#160; </div>
+<div class="line"><a name="l08108"></a><span class="lineno"> 8108</span>&#160;<span class="keywordtype">void</span>* VmaAllocation_T::GetMappedData()<span class="keyword"> const</span></div>
+<div class="line"><a name="l08109"></a><span class="lineno"> 8109</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l08110"></a><span class="lineno"> 8110</span>&#160;    <span class="keywordflow">switch</span>(m_Type)</div>
+<div class="line"><a name="l08111"></a><span class="lineno"> 8111</span>&#160;    {</div>
+<div class="line"><a name="l08112"></a><span class="lineno"> 8112</span>&#160;    <span class="keywordflow">case</span> ALLOCATION_TYPE_BLOCK:</div>
+<div class="line"><a name="l08113"></a><span class="lineno"> 8113</span>&#160;        <span class="keywordflow">if</span>(m_MapCount != 0)</div>
+<div class="line"><a name="l08114"></a><span class="lineno"> 8114</span>&#160;        {</div>
+<div class="line"><a name="l08115"></a><span class="lineno"> 8115</span>&#160;            <span class="keywordtype">void</span>* pBlockData = m_BlockAllocation.m_Block-&gt;GetMappedData();</div>
+<div class="line"><a name="l08116"></a><span class="lineno"> 8116</span>&#160;            VMA_ASSERT(pBlockData != VMA_NULL);</div>
+<div class="line"><a name="l08117"></a><span class="lineno"> 8117</span>&#160;            <span class="keywordflow">return</span> (<span class="keywordtype">char</span>*)pBlockData + m_BlockAllocation.m_Offset;</div>
+<div class="line"><a name="l08118"></a><span class="lineno"> 8118</span>&#160;        }</div>
+<div class="line"><a name="l08119"></a><span class="lineno"> 8119</span>&#160;        <span class="keywordflow">else</span></div>
+<div class="line"><a name="l08120"></a><span class="lineno"> 8120</span>&#160;        {</div>
+<div class="line"><a name="l08121"></a><span class="lineno"> 8121</span>&#160;            <span class="keywordflow">return</span> VMA_NULL;</div>
+<div class="line"><a name="l08122"></a><span class="lineno"> 8122</span>&#160;        }</div>
+<div class="line"><a name="l08123"></a><span class="lineno"> 8123</span>&#160;        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l08124"></a><span class="lineno"> 8124</span>&#160;    <span class="keywordflow">case</span> ALLOCATION_TYPE_DEDICATED:</div>
+<div class="line"><a name="l08125"></a><span class="lineno"> 8125</span>&#160;        VMA_ASSERT((m_DedicatedAllocation.m_pMappedData != VMA_NULL) == (m_MapCount != 0));</div>
+<div class="line"><a name="l08126"></a><span class="lineno"> 8126</span>&#160;        <span class="keywordflow">return</span> m_DedicatedAllocation.m_pMappedData;</div>
+<div class="line"><a name="l08127"></a><span class="lineno"> 8127</span>&#160;    <span class="keywordflow">default</span>:</div>
+<div class="line"><a name="l08128"></a><span class="lineno"> 8128</span>&#160;        VMA_ASSERT(0);</div>
+<div class="line"><a name="l08129"></a><span class="lineno"> 8129</span>&#160;        <span class="keywordflow">return</span> VMA_NULL;</div>
+<div class="line"><a name="l08130"></a><span class="lineno"> 8130</span>&#160;    }</div>
+<div class="line"><a name="l08131"></a><span class="lineno"> 8131</span>&#160;}</div>
+<div class="line"><a name="l08132"></a><span class="lineno"> 8132</span>&#160; </div>
+<div class="line"><a name="l08133"></a><span class="lineno"> 8133</span>&#160;<span class="keywordtype">bool</span> VmaAllocation_T::CanBecomeLost()<span class="keyword"> const</span></div>
+<div class="line"><a name="l08134"></a><span class="lineno"> 8134</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l08135"></a><span class="lineno"> 8135</span>&#160;    <span class="keywordflow">switch</span>(m_Type)</div>
+<div class="line"><a name="l08136"></a><span class="lineno"> 8136</span>&#160;    {</div>
+<div class="line"><a name="l08137"></a><span class="lineno"> 8137</span>&#160;    <span class="keywordflow">case</span> ALLOCATION_TYPE_BLOCK:</div>
+<div class="line"><a name="l08138"></a><span class="lineno"> 8138</span>&#160;        <span class="keywordflow">return</span> m_BlockAllocation.m_CanBecomeLost;</div>
+<div class="line"><a name="l08139"></a><span class="lineno"> 8139</span>&#160;    <span class="keywordflow">case</span> ALLOCATION_TYPE_DEDICATED:</div>
+<div class="line"><a name="l08140"></a><span class="lineno"> 8140</span>&#160;        <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l08141"></a><span class="lineno"> 8141</span>&#160;    <span class="keywordflow">default</span>:</div>
+<div class="line"><a name="l08142"></a><span class="lineno"> 8142</span>&#160;        VMA_ASSERT(0);</div>
+<div class="line"><a name="l08143"></a><span class="lineno"> 8143</span>&#160;        <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l08144"></a><span class="lineno"> 8144</span>&#160;    }</div>
+<div class="line"><a name="l08145"></a><span class="lineno"> 8145</span>&#160;}</div>
+<div class="line"><a name="l08146"></a><span class="lineno"> 8146</span>&#160; </div>
+<div class="line"><a name="l08147"></a><span class="lineno"> 8147</span>&#160;<span class="keywordtype">bool</span> VmaAllocation_T::MakeLost(uint32_t currentFrameIndex, uint32_t frameInUseCount)</div>
+<div class="line"><a name="l08148"></a><span class="lineno"> 8148</span>&#160;{</div>
+<div class="line"><a name="l08149"></a><span class="lineno"> 8149</span>&#160;    VMA_ASSERT(CanBecomeLost());</div>
+<div class="line"><a name="l08150"></a><span class="lineno"> 8150</span>&#160; </div>
+<div class="line"><a name="l08151"></a><span class="lineno"> 8151</span>&#160;    <span class="comment">/*</span></div>
+<div class="line"><a name="l08152"></a><span class="lineno"> 8152</span>&#160;<span class="comment">    Warning: This is a carefully designed algorithm.</span></div>
+<div class="line"><a name="l08153"></a><span class="lineno"> 8153</span>&#160;<span class="comment">    Do not modify unless you really know what you&#39;re doing :)</span></div>
+<div class="line"><a name="l08154"></a><span class="lineno"> 8154</span>&#160;<span class="comment">    */</span></div>
+<div class="line"><a name="l08155"></a><span class="lineno"> 8155</span>&#160;    uint32_t localLastUseFrameIndex = GetLastUseFrameIndex();</div>
+<div class="line"><a name="l08156"></a><span class="lineno"> 8156</span>&#160;    <span class="keywordflow">for</span>(;;)</div>
+<div class="line"><a name="l08157"></a><span class="lineno"> 8157</span>&#160;    {</div>
+<div class="line"><a name="l08158"></a><span class="lineno"> 8158</span>&#160;        <span class="keywordflow">if</span>(localLastUseFrameIndex == VMA_FRAME_INDEX_LOST)</div>
+<div class="line"><a name="l08159"></a><span class="lineno"> 8159</span>&#160;        {</div>
+<div class="line"><a name="l08160"></a><span class="lineno"> 8160</span>&#160;            VMA_ASSERT(0);</div>
+<div class="line"><a name="l08161"></a><span class="lineno"> 8161</span>&#160;            <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l08162"></a><span class="lineno"> 8162</span>&#160;        }</div>
+<div class="line"><a name="l08163"></a><span class="lineno"> 8163</span>&#160;        <span class="keywordflow">else</span> <span class="keywordflow">if</span>(localLastUseFrameIndex + frameInUseCount &gt;= currentFrameIndex)</div>
+<div class="line"><a name="l08164"></a><span class="lineno"> 8164</span>&#160;        {</div>
+<div class="line"><a name="l08165"></a><span class="lineno"> 8165</span>&#160;            <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l08166"></a><span class="lineno"> 8166</span>&#160;        }</div>
+<div class="line"><a name="l08167"></a><span class="lineno"> 8167</span>&#160;        <span class="keywordflow">else</span> <span class="comment">// Last use time earlier than current time.</span></div>
+<div class="line"><a name="l08168"></a><span class="lineno"> 8168</span>&#160;        {</div>
+<div class="line"><a name="l08169"></a><span class="lineno"> 8169</span>&#160;            <span class="keywordflow">if</span>(CompareExchangeLastUseFrameIndex(localLastUseFrameIndex, VMA_FRAME_INDEX_LOST))</div>
+<div class="line"><a name="l08170"></a><span class="lineno"> 8170</span>&#160;            {</div>
+<div class="line"><a name="l08171"></a><span class="lineno"> 8171</span>&#160;                <span class="comment">// Setting hAllocation.LastUseFrameIndex atomic to VMA_FRAME_INDEX_LOST is enough to mark it as LOST.</span></div>
+<div class="line"><a name="l08172"></a><span class="lineno"> 8172</span>&#160;                <span class="comment">// Calling code just needs to unregister this allocation in owning VmaDeviceMemoryBlock.</span></div>
+<div class="line"><a name="l08173"></a><span class="lineno"> 8173</span>&#160;                <span class="keywordflow">return</span> <span class="keyword">true</span>;</div>
+<div class="line"><a name="l08174"></a><span class="lineno"> 8174</span>&#160;            }</div>
+<div class="line"><a name="l08175"></a><span class="lineno"> 8175</span>&#160;        }</div>
+<div class="line"><a name="l08176"></a><span class="lineno"> 8176</span>&#160;    }</div>
+<div class="line"><a name="l08177"></a><span class="lineno"> 8177</span>&#160;}</div>
+<div class="line"><a name="l08178"></a><span class="lineno"> 8178</span>&#160; </div>
+<div class="line"><a name="l08179"></a><span class="lineno"> 8179</span>&#160;<span class="preprocessor">#if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l08180"></a><span class="lineno"> 8180</span>&#160; </div>
+<div class="line"><a name="l08181"></a><span class="lineno"> 8181</span>&#160;<span class="comment">// Correspond to values of enum VmaSuballocationType.</span></div>
+<div class="line"><a name="l08182"></a><span class="lineno"> 8182</span>&#160;<span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">char</span>* VMA_SUBALLOCATION_TYPE_NAMES[] = {</div>
+<div class="line"><a name="l08183"></a><span class="lineno"> 8183</span>&#160;    <span class="stringliteral">&quot;FREE&quot;</span>,</div>
+<div class="line"><a name="l08184"></a><span class="lineno"> 8184</span>&#160;    <span class="stringliteral">&quot;UNKNOWN&quot;</span>,</div>
+<div class="line"><a name="l08185"></a><span class="lineno"> 8185</span>&#160;    <span class="stringliteral">&quot;BUFFER&quot;</span>,</div>
+<div class="line"><a name="l08186"></a><span class="lineno"> 8186</span>&#160;    <span class="stringliteral">&quot;IMAGE_UNKNOWN&quot;</span>,</div>
+<div class="line"><a name="l08187"></a><span class="lineno"> 8187</span>&#160;    <span class="stringliteral">&quot;IMAGE_LINEAR&quot;</span>,</div>
+<div class="line"><a name="l08188"></a><span class="lineno"> 8188</span>&#160;    <span class="stringliteral">&quot;IMAGE_OPTIMAL&quot;</span>,</div>
+<div class="line"><a name="l08189"></a><span class="lineno"> 8189</span>&#160;};</div>
+<div class="line"><a name="l08190"></a><span class="lineno"> 8190</span>&#160; </div>
+<div class="line"><a name="l08191"></a><span class="lineno"> 8191</span>&#160;<span class="keywordtype">void</span> VmaAllocation_T::PrintParameters(<span class="keyword">class</span> VmaJsonWriter&amp; json)<span class="keyword"> const</span></div>
+<div class="line"><a name="l08192"></a><span class="lineno"> 8192</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l08193"></a><span class="lineno"> 8193</span>&#160;    json.WriteString(<span class="stringliteral">&quot;Type&quot;</span>);</div>
+<div class="line"><a name="l08194"></a><span class="lineno"> 8194</span>&#160;    json.WriteString(VMA_SUBALLOCATION_TYPE_NAMES[m_SuballocationType]);</div>
+<div class="line"><a name="l08195"></a><span class="lineno"> 8195</span>&#160; </div>
+<div class="line"><a name="l08196"></a><span class="lineno"> 8196</span>&#160;    json.WriteString(<span class="stringliteral">&quot;Size&quot;</span>);</div>
+<div class="line"><a name="l08197"></a><span class="lineno"> 8197</span>&#160;    json.WriteNumber(m_Size);</div>
+<div class="line"><a name="l08198"></a><span class="lineno"> 8198</span>&#160; </div>
+<div class="line"><a name="l08199"></a><span class="lineno"> 8199</span>&#160;    <span class="keywordflow">if</span>(m_pUserData != VMA_NULL)</div>
+<div class="line"><a name="l08200"></a><span class="lineno"> 8200</span>&#160;    {</div>
+<div class="line"><a name="l08201"></a><span class="lineno"> 8201</span>&#160;        json.WriteString(<span class="stringliteral">&quot;UserData&quot;</span>);</div>
+<div class="line"><a name="l08202"></a><span class="lineno"> 8202</span>&#160;        <span class="keywordflow">if</span>(IsUserDataString())</div>
+<div class="line"><a name="l08203"></a><span class="lineno"> 8203</span>&#160;        {</div>
+<div class="line"><a name="l08204"></a><span class="lineno"> 8204</span>&#160;            json.WriteString((<span class="keyword">const</span> <span class="keywordtype">char</span>*)m_pUserData);</div>
+<div class="line"><a name="l08205"></a><span class="lineno"> 8205</span>&#160;        }</div>
+<div class="line"><a name="l08206"></a><span class="lineno"> 8206</span>&#160;        <span class="keywordflow">else</span></div>
+<div class="line"><a name="l08207"></a><span class="lineno"> 8207</span>&#160;        {</div>
+<div class="line"><a name="l08208"></a><span class="lineno"> 8208</span>&#160;            json.BeginString();</div>
+<div class="line"><a name="l08209"></a><span class="lineno"> 8209</span>&#160;            json.ContinueString_Pointer(m_pUserData);</div>
+<div class="line"><a name="l08210"></a><span class="lineno"> 8210</span>&#160;            json.EndString();</div>
+<div class="line"><a name="l08211"></a><span class="lineno"> 8211</span>&#160;        }</div>
+<div class="line"><a name="l08212"></a><span class="lineno"> 8212</span>&#160;    }</div>
+<div class="line"><a name="l08213"></a><span class="lineno"> 8213</span>&#160; </div>
+<div class="line"><a name="l08214"></a><span class="lineno"> 8214</span>&#160;    json.WriteString(<span class="stringliteral">&quot;CreationFrameIndex&quot;</span>);</div>
+<div class="line"><a name="l08215"></a><span class="lineno"> 8215</span>&#160;    json.WriteNumber(m_CreationFrameIndex);</div>
+<div class="line"><a name="l08216"></a><span class="lineno"> 8216</span>&#160; </div>
+<div class="line"><a name="l08217"></a><span class="lineno"> 8217</span>&#160;    json.WriteString(<span class="stringliteral">&quot;LastUseFrameIndex&quot;</span>);</div>
+<div class="line"><a name="l08218"></a><span class="lineno"> 8218</span>&#160;    json.WriteNumber(GetLastUseFrameIndex());</div>
+<div class="line"><a name="l08219"></a><span class="lineno"> 8219</span>&#160; </div>
+<div class="line"><a name="l08220"></a><span class="lineno"> 8220</span>&#160;    <span class="keywordflow">if</span>(m_BufferImageUsage != 0)</div>
+<div class="line"><a name="l08221"></a><span class="lineno"> 8221</span>&#160;    {</div>
+<div class="line"><a name="l08222"></a><span class="lineno"> 8222</span>&#160;        json.WriteString(<span class="stringliteral">&quot;Usage&quot;</span>);</div>
+<div class="line"><a name="l08223"></a><span class="lineno"> 8223</span>&#160;        json.WriteNumber(m_BufferImageUsage);</div>
+<div class="line"><a name="l08224"></a><span class="lineno"> 8224</span>&#160;    }</div>
+<div class="line"><a name="l08225"></a><span class="lineno"> 8225</span>&#160;}</div>
+<div class="line"><a name="l08226"></a><span class="lineno"> 8226</span>&#160; </div>
+<div class="line"><a name="l08227"></a><span class="lineno"> 8227</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l08228"></a><span class="lineno"> 8228</span>&#160; </div>
+<div class="line"><a name="l08229"></a><span class="lineno"> 8229</span>&#160;<span class="keywordtype">void</span> VmaAllocation_T::FreeUserDataString(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator)</div>
+<div class="line"><a name="l08230"></a><span class="lineno"> 8230</span>&#160;{</div>
+<div class="line"><a name="l08231"></a><span class="lineno"> 8231</span>&#160;    VMA_ASSERT(IsUserDataString());</div>
+<div class="line"><a name="l08232"></a><span class="lineno"> 8232</span>&#160;    VmaFreeString(hAllocator-&gt;GetAllocationCallbacks(), (<span class="keywordtype">char</span>*)m_pUserData);</div>
+<div class="line"><a name="l08233"></a><span class="lineno"> 8233</span>&#160;    m_pUserData = VMA_NULL;</div>
+<div class="line"><a name="l08234"></a><span class="lineno"> 8234</span>&#160;}</div>
+<div class="line"><a name="l08235"></a><span class="lineno"> 8235</span>&#160; </div>
+<div class="line"><a name="l08236"></a><span class="lineno"> 8236</span>&#160;<span class="keywordtype">void</span> VmaAllocation_T::BlockAllocMap()</div>
+<div class="line"><a name="l08237"></a><span class="lineno"> 8237</span>&#160;{</div>
+<div class="line"><a name="l08238"></a><span class="lineno"> 8238</span>&#160;    VMA_ASSERT(GetType() == ALLOCATION_TYPE_BLOCK);</div>
+<div class="line"><a name="l08239"></a><span class="lineno"> 8239</span>&#160; </div>
+<div class="line"><a name="l08240"></a><span class="lineno"> 8240</span>&#160;    <span class="keywordflow">if</span>((m_MapCount &amp; ~MAP_COUNT_FLAG_PERSISTENT_MAP) &lt; 0x7F)</div>
+<div class="line"><a name="l08241"></a><span class="lineno"> 8241</span>&#160;    {</div>
+<div class="line"><a name="l08242"></a><span class="lineno"> 8242</span>&#160;        ++m_MapCount;</div>
+<div class="line"><a name="l08243"></a><span class="lineno"> 8243</span>&#160;    }</div>
+<div class="line"><a name="l08244"></a><span class="lineno"> 8244</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l08245"></a><span class="lineno"> 8245</span>&#160;    {</div>
+<div class="line"><a name="l08246"></a><span class="lineno"> 8246</span>&#160;        VMA_ASSERT(0 &amp;&amp; <span class="stringliteral">&quot;Allocation mapped too many times simultaneously.&quot;</span>);</div>
+<div class="line"><a name="l08247"></a><span class="lineno"> 8247</span>&#160;    }</div>
+<div class="line"><a name="l08248"></a><span class="lineno"> 8248</span>&#160;}</div>
+<div class="line"><a name="l08249"></a><span class="lineno"> 8249</span>&#160; </div>
+<div class="line"><a name="l08250"></a><span class="lineno"> 8250</span>&#160;<span class="keywordtype">void</span> VmaAllocation_T::BlockAllocUnmap()</div>
+<div class="line"><a name="l08251"></a><span class="lineno"> 8251</span>&#160;{</div>
+<div class="line"><a name="l08252"></a><span class="lineno"> 8252</span>&#160;    VMA_ASSERT(GetType() == ALLOCATION_TYPE_BLOCK);</div>
+<div class="line"><a name="l08253"></a><span class="lineno"> 8253</span>&#160; </div>
+<div class="line"><a name="l08254"></a><span class="lineno"> 8254</span>&#160;    <span class="keywordflow">if</span>((m_MapCount &amp; ~MAP_COUNT_FLAG_PERSISTENT_MAP) != 0)</div>
+<div class="line"><a name="l08255"></a><span class="lineno"> 8255</span>&#160;    {</div>
+<div class="line"><a name="l08256"></a><span class="lineno"> 8256</span>&#160;        --m_MapCount;</div>
+<div class="line"><a name="l08257"></a><span class="lineno"> 8257</span>&#160;    }</div>
+<div class="line"><a name="l08258"></a><span class="lineno"> 8258</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l08259"></a><span class="lineno"> 8259</span>&#160;    {</div>
+<div class="line"><a name="l08260"></a><span class="lineno"> 8260</span>&#160;        VMA_ASSERT(0 &amp;&amp; <span class="stringliteral">&quot;Unmapping allocation not previously mapped.&quot;</span>);</div>
+<div class="line"><a name="l08261"></a><span class="lineno"> 8261</span>&#160;    }</div>
+<div class="line"><a name="l08262"></a><span class="lineno"> 8262</span>&#160;}</div>
+<div class="line"><a name="l08263"></a><span class="lineno"> 8263</span>&#160; </div>
+<div class="line"><a name="l08264"></a><span class="lineno"> 8264</span>&#160;VkResult VmaAllocation_T::DedicatedAllocMap(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator, <span class="keywordtype">void</span>** ppData)</div>
+<div class="line"><a name="l08265"></a><span class="lineno"> 8265</span>&#160;{</div>
+<div class="line"><a name="l08266"></a><span class="lineno"> 8266</span>&#160;    VMA_ASSERT(GetType() == ALLOCATION_TYPE_DEDICATED);</div>
+<div class="line"><a name="l08267"></a><span class="lineno"> 8267</span>&#160; </div>
+<div class="line"><a name="l08268"></a><span class="lineno"> 8268</span>&#160;    <span class="keywordflow">if</span>(m_MapCount != 0)</div>
+<div class="line"><a name="l08269"></a><span class="lineno"> 8269</span>&#160;    {</div>
+<div class="line"><a name="l08270"></a><span class="lineno"> 8270</span>&#160;        <span class="keywordflow">if</span>((m_MapCount &amp; ~MAP_COUNT_FLAG_PERSISTENT_MAP) &lt; 0x7F)</div>
+<div class="line"><a name="l08271"></a><span class="lineno"> 8271</span>&#160;        {</div>
+<div class="line"><a name="l08272"></a><span class="lineno"> 8272</span>&#160;            VMA_ASSERT(m_DedicatedAllocation.m_pMappedData != VMA_NULL);</div>
+<div class="line"><a name="l08273"></a><span class="lineno"> 8273</span>&#160;            *ppData = m_DedicatedAllocation.m_pMappedData;</div>
+<div class="line"><a name="l08274"></a><span class="lineno"> 8274</span>&#160;            ++m_MapCount;</div>
+<div class="line"><a name="l08275"></a><span class="lineno"> 8275</span>&#160;            <span class="keywordflow">return</span> VK_SUCCESS;</div>
+<div class="line"><a name="l08276"></a><span class="lineno"> 8276</span>&#160;        }</div>
+<div class="line"><a name="l08277"></a><span class="lineno"> 8277</span>&#160;        <span class="keywordflow">else</span></div>
+<div class="line"><a name="l08278"></a><span class="lineno"> 8278</span>&#160;        {</div>
+<div class="line"><a name="l08279"></a><span class="lineno"> 8279</span>&#160;            VMA_ASSERT(0 &amp;&amp; <span class="stringliteral">&quot;Dedicated allocation mapped too many times simultaneously.&quot;</span>);</div>
+<div class="line"><a name="l08280"></a><span class="lineno"> 8280</span>&#160;            <span class="keywordflow">return</span> VK_ERROR_MEMORY_MAP_FAILED;</div>
+<div class="line"><a name="l08281"></a><span class="lineno"> 8281</span>&#160;        }</div>
+<div class="line"><a name="l08282"></a><span class="lineno"> 8282</span>&#160;    }</div>
+<div class="line"><a name="l08283"></a><span class="lineno"> 8283</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l08284"></a><span class="lineno"> 8284</span>&#160;    {</div>
+<div class="line"><a name="l08285"></a><span class="lineno"> 8285</span>&#160;        VkResult result = (*hAllocator-&gt;GetVulkanFunctions().vkMapMemory)(</div>
+<div class="line"><a name="l08286"></a><span class="lineno"> 8286</span>&#160;            hAllocator-&gt;m_hDevice,</div>
+<div class="line"><a name="l08287"></a><span class="lineno"> 8287</span>&#160;            m_DedicatedAllocation.m_hMemory,</div>
+<div class="line"><a name="l08288"></a><span class="lineno"> 8288</span>&#160;            0, <span class="comment">// offset</span></div>
+<div class="line"><a name="l08289"></a><span class="lineno"> 8289</span>&#160;            VK_WHOLE_SIZE,</div>
+<div class="line"><a name="l08290"></a><span class="lineno"> 8290</span>&#160;            0, <span class="comment">// flags</span></div>
+<div class="line"><a name="l08291"></a><span class="lineno"> 8291</span>&#160;            ppData);</div>
+<div class="line"><a name="l08292"></a><span class="lineno"> 8292</span>&#160;        <span class="keywordflow">if</span>(result == VK_SUCCESS)</div>
+<div class="line"><a name="l08293"></a><span class="lineno"> 8293</span>&#160;        {</div>
+<div class="line"><a name="l08294"></a><span class="lineno"> 8294</span>&#160;            m_DedicatedAllocation.m_pMappedData = *ppData;</div>
+<div class="line"><a name="l08295"></a><span class="lineno"> 8295</span>&#160;            m_MapCount = 1;</div>
+<div class="line"><a name="l08296"></a><span class="lineno"> 8296</span>&#160;        }</div>
+<div class="line"><a name="l08297"></a><span class="lineno"> 8297</span>&#160;        <span class="keywordflow">return</span> result;</div>
+<div class="line"><a name="l08298"></a><span class="lineno"> 8298</span>&#160;    }</div>
+<div class="line"><a name="l08299"></a><span class="lineno"> 8299</span>&#160;}</div>
+<div class="line"><a name="l08300"></a><span class="lineno"> 8300</span>&#160; </div>
+<div class="line"><a name="l08301"></a><span class="lineno"> 8301</span>&#160;<span class="keywordtype">void</span> VmaAllocation_T::DedicatedAllocUnmap(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator)</div>
+<div class="line"><a name="l08302"></a><span class="lineno"> 8302</span>&#160;{</div>
+<div class="line"><a name="l08303"></a><span class="lineno"> 8303</span>&#160;    VMA_ASSERT(GetType() == ALLOCATION_TYPE_DEDICATED);</div>
+<div class="line"><a name="l08304"></a><span class="lineno"> 8304</span>&#160; </div>
+<div class="line"><a name="l08305"></a><span class="lineno"> 8305</span>&#160;    <span class="keywordflow">if</span>((m_MapCount &amp; ~MAP_COUNT_FLAG_PERSISTENT_MAP) != 0)</div>
+<div class="line"><a name="l08306"></a><span class="lineno"> 8306</span>&#160;    {</div>
+<div class="line"><a name="l08307"></a><span class="lineno"> 8307</span>&#160;        --m_MapCount;</div>
+<div class="line"><a name="l08308"></a><span class="lineno"> 8308</span>&#160;        <span class="keywordflow">if</span>(m_MapCount == 0)</div>
+<div class="line"><a name="l08309"></a><span class="lineno"> 8309</span>&#160;        {</div>
+<div class="line"><a name="l08310"></a><span class="lineno"> 8310</span>&#160;            m_DedicatedAllocation.m_pMappedData = VMA_NULL;</div>
+<div class="line"><a name="l08311"></a><span class="lineno"> 8311</span>&#160;            (*hAllocator-&gt;GetVulkanFunctions().vkUnmapMemory)(</div>
+<div class="line"><a name="l08312"></a><span class="lineno"> 8312</span>&#160;                hAllocator-&gt;m_hDevice,</div>
+<div class="line"><a name="l08313"></a><span class="lineno"> 8313</span>&#160;                m_DedicatedAllocation.m_hMemory);</div>
+<div class="line"><a name="l08314"></a><span class="lineno"> 8314</span>&#160;        }</div>
+<div class="line"><a name="l08315"></a><span class="lineno"> 8315</span>&#160;    }</div>
+<div class="line"><a name="l08316"></a><span class="lineno"> 8316</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l08317"></a><span class="lineno"> 8317</span>&#160;    {</div>
+<div class="line"><a name="l08318"></a><span class="lineno"> 8318</span>&#160;        VMA_ASSERT(0 &amp;&amp; <span class="stringliteral">&quot;Unmapping dedicated allocation not previously mapped.&quot;</span>);</div>
+<div class="line"><a name="l08319"></a><span class="lineno"> 8319</span>&#160;    }</div>
+<div class="line"><a name="l08320"></a><span class="lineno"> 8320</span>&#160;}</div>
+<div class="line"><a name="l08321"></a><span class="lineno"> 8321</span>&#160; </div>
+<div class="line"><a name="l08322"></a><span class="lineno"> 8322</span>&#160;<span class="preprocessor">#if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l08323"></a><span class="lineno"> 8323</span>&#160; </div>
+<div class="line"><a name="l08324"></a><span class="lineno"> 8324</span>&#160;<span class="keyword">static</span> <span class="keywordtype">void</span> VmaPrintStatInfo(VmaJsonWriter&amp; json, <span class="keyword">const</span> <a class="code" href="struct_vma_stat_info.html">VmaStatInfo</a>&amp; stat)</div>
+<div class="line"><a name="l08325"></a><span class="lineno"> 8325</span>&#160;{</div>
+<div class="line"><a name="l08326"></a><span class="lineno"> 8326</span>&#160;    json.BeginObject();</div>
+<div class="line"><a name="l08327"></a><span class="lineno"> 8327</span>&#160; </div>
+<div class="line"><a name="l08328"></a><span class="lineno"> 8328</span>&#160;    json.WriteString(<span class="stringliteral">&quot;Blocks&quot;</span>);</div>
+<div class="line"><a name="l08329"></a><span class="lineno"> 8329</span>&#160;    json.WriteNumber(stat.<a class="code" href="struct_vma_stat_info.html#abc4bb7cd611900778464c56e50c970a4">blockCount</a>);</div>
+<div class="line"><a name="l08330"></a><span class="lineno"> 8330</span>&#160; </div>
+<div class="line"><a name="l08331"></a><span class="lineno"> 8331</span>&#160;    json.WriteString(<span class="stringliteral">&quot;Allocations&quot;</span>);</div>
+<div class="line"><a name="l08332"></a><span class="lineno"> 8332</span>&#160;    json.WriteNumber(stat.<a class="code" href="struct_vma_stat_info.html#a537741e4d5cdddc1c0ab95ec650afaff">allocationCount</a>);</div>
+<div class="line"><a name="l08333"></a><span class="lineno"> 8333</span>&#160; </div>
+<div class="line"><a name="l08334"></a><span class="lineno"> 8334</span>&#160;    json.WriteString(<span class="stringliteral">&quot;UnusedRanges&quot;</span>);</div>
+<div class="line"><a name="l08335"></a><span class="lineno"> 8335</span>&#160;    json.WriteNumber(stat.<a class="code" href="struct_vma_stat_info.html#ae06129c771bfebfd6468a7f4276502a9">unusedRangeCount</a>);</div>
+<div class="line"><a name="l08336"></a><span class="lineno"> 8336</span>&#160; </div>
+<div class="line"><a name="l08337"></a><span class="lineno"> 8337</span>&#160;    json.WriteString(<span class="stringliteral">&quot;UsedBytes&quot;</span>);</div>
+<div class="line"><a name="l08338"></a><span class="lineno"> 8338</span>&#160;    json.WriteNumber(stat.<a class="code" href="struct_vma_stat_info.html#ab0c6c73837e5a70c749fbd4f6064895a">usedBytes</a>);</div>
+<div class="line"><a name="l08339"></a><span class="lineno"> 8339</span>&#160; </div>
+<div class="line"><a name="l08340"></a><span class="lineno"> 8340</span>&#160;    json.WriteString(<span class="stringliteral">&quot;UnusedBytes&quot;</span>);</div>
+<div class="line"><a name="l08341"></a><span class="lineno"> 8341</span>&#160;    json.WriteNumber(stat.<a class="code" href="struct_vma_stat_info.html#a1859d290aca2cd582d8dc25922092669">unusedBytes</a>);</div>
+<div class="line"><a name="l08342"></a><span class="lineno"> 8342</span>&#160; </div>
+<div class="line"><a name="l08343"></a><span class="lineno"> 8343</span>&#160;    <span class="keywordflow">if</span>(stat.<a class="code" href="struct_vma_stat_info.html#a537741e4d5cdddc1c0ab95ec650afaff">allocationCount</a> &gt; 1)</div>
+<div class="line"><a name="l08344"></a><span class="lineno"> 8344</span>&#160;    {</div>
+<div class="line"><a name="l08345"></a><span class="lineno"> 8345</span>&#160;        json.WriteString(<span class="stringliteral">&quot;AllocationSize&quot;</span>);</div>
+<div class="line"><a name="l08346"></a><span class="lineno"> 8346</span>&#160;        json.BeginObject(<span class="keyword">true</span>);</div>
+<div class="line"><a name="l08347"></a><span class="lineno"> 8347</span>&#160;        json.WriteString(<span class="stringliteral">&quot;Min&quot;</span>);</div>
+<div class="line"><a name="l08348"></a><span class="lineno"> 8348</span>&#160;        json.WriteNumber(stat.<a class="code" href="struct_vma_stat_info.html#ade8b40bd3139c04aabd2fc538a356fea">allocationSizeMin</a>);</div>
+<div class="line"><a name="l08349"></a><span class="lineno"> 8349</span>&#160;        json.WriteString(<span class="stringliteral">&quot;Avg&quot;</span>);</div>
+<div class="line"><a name="l08350"></a><span class="lineno"> 8350</span>&#160;        json.WriteNumber(stat.<a class="code" href="struct_vma_stat_info.html#a1081a039964e566c672e7a2347f9e599">allocationSizeAvg</a>);</div>
+<div class="line"><a name="l08351"></a><span class="lineno"> 8351</span>&#160;        json.WriteString(<span class="stringliteral">&quot;Max&quot;</span>);</div>
+<div class="line"><a name="l08352"></a><span class="lineno"> 8352</span>&#160;        json.WriteNumber(stat.<a class="code" href="struct_vma_stat_info.html#a17e9733a5ecd76287d4db6e66f71f50c">allocationSizeMax</a>);</div>
+<div class="line"><a name="l08353"></a><span class="lineno"> 8353</span>&#160;        json.EndObject();</div>
+<div class="line"><a name="l08354"></a><span class="lineno"> 8354</span>&#160;    }</div>
+<div class="line"><a name="l08355"></a><span class="lineno"> 8355</span>&#160; </div>
+<div class="line"><a name="l08356"></a><span class="lineno"> 8356</span>&#160;    <span class="keywordflow">if</span>(stat.<a class="code" href="struct_vma_stat_info.html#ae06129c771bfebfd6468a7f4276502a9">unusedRangeCount</a> &gt; 1)</div>
+<div class="line"><a name="l08357"></a><span class="lineno"> 8357</span>&#160;    {</div>
+<div class="line"><a name="l08358"></a><span class="lineno"> 8358</span>&#160;        json.WriteString(<span class="stringliteral">&quot;UnusedRangeSize&quot;</span>);</div>
+<div class="line"><a name="l08359"></a><span class="lineno"> 8359</span>&#160;        json.BeginObject(<span class="keyword">true</span>);</div>
+<div class="line"><a name="l08360"></a><span class="lineno"> 8360</span>&#160;        json.WriteString(<span class="stringliteral">&quot;Min&quot;</span>);</div>
+<div class="line"><a name="l08361"></a><span class="lineno"> 8361</span>&#160;        json.WriteNumber(stat.<a class="code" href="struct_vma_stat_info.html#aedeba931324f16589cd2416c0d2dd0d4">unusedRangeSizeMin</a>);</div>
+<div class="line"><a name="l08362"></a><span class="lineno"> 8362</span>&#160;        json.WriteString(<span class="stringliteral">&quot;Avg&quot;</span>);</div>
+<div class="line"><a name="l08363"></a><span class="lineno"> 8363</span>&#160;        json.WriteNumber(stat.<a class="code" href="struct_vma_stat_info.html#a2f9b3452af90c9768a30b7fb6ae194fc">unusedRangeSizeAvg</a>);</div>
+<div class="line"><a name="l08364"></a><span class="lineno"> 8364</span>&#160;        json.WriteString(<span class="stringliteral">&quot;Max&quot;</span>);</div>
+<div class="line"><a name="l08365"></a><span class="lineno"> 8365</span>&#160;        json.WriteNumber(stat.<a class="code" href="struct_vma_stat_info.html#a5ba1a2476c4d39b10f7e2f7ebbb72ac4">unusedRangeSizeMax</a>);</div>
+<div class="line"><a name="l08366"></a><span class="lineno"> 8366</span>&#160;        json.EndObject();</div>
+<div class="line"><a name="l08367"></a><span class="lineno"> 8367</span>&#160;    }</div>
+<div class="line"><a name="l08368"></a><span class="lineno"> 8368</span>&#160; </div>
+<div class="line"><a name="l08369"></a><span class="lineno"> 8369</span>&#160;    json.EndObject();</div>
+<div class="line"><a name="l08370"></a><span class="lineno"> 8370</span>&#160;}</div>
+<div class="line"><a name="l08371"></a><span class="lineno"> 8371</span>&#160; </div>
+<div class="line"><a name="l08372"></a><span class="lineno"> 8372</span>&#160;<span class="preprocessor">#endif // #if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l08373"></a><span class="lineno"> 8373</span>&#160; </div>
+<div class="line"><a name="l08374"></a><span class="lineno"> 8374</span>&#160;<span class="keyword">struct </span>VmaSuballocationItemSizeLess</div>
+<div class="line"><a name="l08375"></a><span class="lineno"> 8375</span>&#160;{</div>
+<div class="line"><a name="l08376"></a><span class="lineno"> 8376</span>&#160;    <span class="keywordtype">bool</span> operator()(</div>
+<div class="line"><a name="l08377"></a><span class="lineno"> 8377</span>&#160;        <span class="keyword">const</span> VmaSuballocationList::iterator lhs,</div>
+<div class="line"><a name="l08378"></a><span class="lineno"> 8378</span>&#160;        <span class="keyword">const</span> VmaSuballocationList::iterator rhs)<span class="keyword"> const</span></div>
+<div class="line"><a name="l08379"></a><span class="lineno"> 8379</span>&#160;<span class="keyword">    </span>{</div>
+<div class="line"><a name="l08380"></a><span class="lineno"> 8380</span>&#160;        <span class="keywordflow">return</span> lhs-&gt;size &lt; rhs-&gt;size;</div>
+<div class="line"><a name="l08381"></a><span class="lineno"> 8381</span>&#160;    }</div>
+<div class="line"><a name="l08382"></a><span class="lineno"> 8382</span>&#160;    <span class="keywordtype">bool</span> operator()(</div>
+<div class="line"><a name="l08383"></a><span class="lineno"> 8383</span>&#160;        <span class="keyword">const</span> VmaSuballocationList::iterator lhs,</div>
+<div class="line"><a name="l08384"></a><span class="lineno"> 8384</span>&#160;        VkDeviceSize rhsSize)<span class="keyword"> const</span></div>
+<div class="line"><a name="l08385"></a><span class="lineno"> 8385</span>&#160;<span class="keyword">    </span>{</div>
+<div class="line"><a name="l08386"></a><span class="lineno"> 8386</span>&#160;        <span class="keywordflow">return</span> lhs-&gt;size &lt; rhsSize;</div>
+<div class="line"><a name="l08387"></a><span class="lineno"> 8387</span>&#160;    }</div>
+<div class="line"><a name="l08388"></a><span class="lineno"> 8388</span>&#160;};</div>
+<div class="line"><a name="l08389"></a><span class="lineno"> 8389</span>&#160; </div>
+<div class="line"><a name="l08390"></a><span class="lineno"> 8390</span>&#160; </div>
+<div class="line"><a name="l08392"></a><span class="lineno"> 8392</span>&#160;<span class="comment">// class VmaBlockMetadata</span></div>
+<div class="line"><a name="l08393"></a><span class="lineno"> 8393</span>&#160; </div>
+<div class="line"><a name="l08394"></a><span class="lineno"> 8394</span>&#160;VmaBlockMetadata::VmaBlockMetadata(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator) :</div>
+<div class="line"><a name="l08395"></a><span class="lineno"> 8395</span>&#160;    m_Size(0),</div>
+<div class="line"><a name="l08396"></a><span class="lineno"> 8396</span>&#160;    m_pAllocationCallbacks(hAllocator-&gt;GetAllocationCallbacks())</div>
+<div class="line"><a name="l08397"></a><span class="lineno"> 8397</span>&#160;{</div>
+<div class="line"><a name="l08398"></a><span class="lineno"> 8398</span>&#160;}</div>
+<div class="line"><a name="l08399"></a><span class="lineno"> 8399</span>&#160; </div>
+<div class="line"><a name="l08400"></a><span class="lineno"> 8400</span>&#160;<span class="preprocessor">#if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l08401"></a><span class="lineno"> 8401</span>&#160; </div>
+<div class="line"><a name="l08402"></a><span class="lineno"> 8402</span>&#160;<span class="keywordtype">void</span> VmaBlockMetadata::PrintDetailedMap_Begin(<span class="keyword">class</span> VmaJsonWriter&amp; json,</div>
+<div class="line"><a name="l08403"></a><span class="lineno"> 8403</span>&#160;    VkDeviceSize unusedBytes,</div>
+<div class="line"><a name="l08404"></a><span class="lineno"> 8404</span>&#160;    <span class="keywordtype">size_t</span> allocationCount,</div>
+<div class="line"><a name="l08405"></a><span class="lineno"> 8405</span>&#160;    <span class="keywordtype">size_t</span> unusedRangeCount)<span class="keyword"> const</span></div>
+<div class="line"><a name="l08406"></a><span class="lineno"> 8406</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l08407"></a><span class="lineno"> 8407</span>&#160;    json.BeginObject();</div>
+<div class="line"><a name="l08408"></a><span class="lineno"> 8408</span>&#160; </div>
+<div class="line"><a name="l08409"></a><span class="lineno"> 8409</span>&#160;    json.WriteString(<span class="stringliteral">&quot;TotalBytes&quot;</span>);</div>
+<div class="line"><a name="l08410"></a><span class="lineno"> 8410</span>&#160;    json.WriteNumber(GetSize());</div>
+<div class="line"><a name="l08411"></a><span class="lineno"> 8411</span>&#160; </div>
+<div class="line"><a name="l08412"></a><span class="lineno"> 8412</span>&#160;    json.WriteString(<span class="stringliteral">&quot;UnusedBytes&quot;</span>);</div>
+<div class="line"><a name="l08413"></a><span class="lineno"> 8413</span>&#160;    json.WriteNumber(unusedBytes);</div>
+<div class="line"><a name="l08414"></a><span class="lineno"> 8414</span>&#160; </div>
+<div class="line"><a name="l08415"></a><span class="lineno"> 8415</span>&#160;    json.WriteString(<span class="stringliteral">&quot;Allocations&quot;</span>);</div>
+<div class="line"><a name="l08416"></a><span class="lineno"> 8416</span>&#160;    json.WriteNumber((uint64_t)allocationCount);</div>
+<div class="line"><a name="l08417"></a><span class="lineno"> 8417</span>&#160; </div>
+<div class="line"><a name="l08418"></a><span class="lineno"> 8418</span>&#160;    json.WriteString(<span class="stringliteral">&quot;UnusedRanges&quot;</span>);</div>
+<div class="line"><a name="l08419"></a><span class="lineno"> 8419</span>&#160;    json.WriteNumber((uint64_t)unusedRangeCount);</div>
+<div class="line"><a name="l08420"></a><span class="lineno"> 8420</span>&#160; </div>
+<div class="line"><a name="l08421"></a><span class="lineno"> 8421</span>&#160;    json.WriteString(<span class="stringliteral">&quot;Suballocations&quot;</span>);</div>
+<div class="line"><a name="l08422"></a><span class="lineno"> 8422</span>&#160;    json.BeginArray();</div>
+<div class="line"><a name="l08423"></a><span class="lineno"> 8423</span>&#160;}</div>
+<div class="line"><a name="l08424"></a><span class="lineno"> 8424</span>&#160; </div>
+<div class="line"><a name="l08425"></a><span class="lineno"> 8425</span>&#160;<span class="keywordtype">void</span> VmaBlockMetadata::PrintDetailedMap_Allocation(<span class="keyword">class</span> VmaJsonWriter&amp; json,</div>
+<div class="line"><a name="l08426"></a><span class="lineno"> 8426</span>&#160;    VkDeviceSize offset,</div>
+<div class="line"><a name="l08427"></a><span class="lineno"> 8427</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAllocation)<span class="keyword"> const</span></div>
+<div class="line"><a name="l08428"></a><span class="lineno"> 8428</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l08429"></a><span class="lineno"> 8429</span>&#160;    json.BeginObject(<span class="keyword">true</span>);</div>
+<div class="line"><a name="l08430"></a><span class="lineno"> 8430</span>&#160;        </div>
+<div class="line"><a name="l08431"></a><span class="lineno"> 8431</span>&#160;    json.WriteString(<span class="stringliteral">&quot;Offset&quot;</span>);</div>
+<div class="line"><a name="l08432"></a><span class="lineno"> 8432</span>&#160;    json.WriteNumber(offset);</div>
+<div class="line"><a name="l08433"></a><span class="lineno"> 8433</span>&#160; </div>
+<div class="line"><a name="l08434"></a><span class="lineno"> 8434</span>&#160;    hAllocation-&gt;PrintParameters(json);</div>
+<div class="line"><a name="l08435"></a><span class="lineno"> 8435</span>&#160; </div>
+<div class="line"><a name="l08436"></a><span class="lineno"> 8436</span>&#160;    json.EndObject();</div>
+<div class="line"><a name="l08437"></a><span class="lineno"> 8437</span>&#160;}</div>
+<div class="line"><a name="l08438"></a><span class="lineno"> 8438</span>&#160; </div>
+<div class="line"><a name="l08439"></a><span class="lineno"> 8439</span>&#160;<span class="keywordtype">void</span> VmaBlockMetadata::PrintDetailedMap_UnusedRange(<span class="keyword">class</span> VmaJsonWriter&amp; json,</div>
+<div class="line"><a name="l08440"></a><span class="lineno"> 8440</span>&#160;    VkDeviceSize offset,</div>
+<div class="line"><a name="l08441"></a><span class="lineno"> 8441</span>&#160;    VkDeviceSize size)<span class="keyword"> const</span></div>
+<div class="line"><a name="l08442"></a><span class="lineno"> 8442</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l08443"></a><span class="lineno"> 8443</span>&#160;    json.BeginObject(<span class="keyword">true</span>);</div>
+<div class="line"><a name="l08444"></a><span class="lineno"> 8444</span>&#160;        </div>
+<div class="line"><a name="l08445"></a><span class="lineno"> 8445</span>&#160;    json.WriteString(<span class="stringliteral">&quot;Offset&quot;</span>);</div>
+<div class="line"><a name="l08446"></a><span class="lineno"> 8446</span>&#160;    json.WriteNumber(offset);</div>
+<div class="line"><a name="l08447"></a><span class="lineno"> 8447</span>&#160; </div>
+<div class="line"><a name="l08448"></a><span class="lineno"> 8448</span>&#160;    json.WriteString(<span class="stringliteral">&quot;Type&quot;</span>);</div>
+<div class="line"><a name="l08449"></a><span class="lineno"> 8449</span>&#160;    json.WriteString(VMA_SUBALLOCATION_TYPE_NAMES[VMA_SUBALLOCATION_TYPE_FREE]);</div>
+<div class="line"><a name="l08450"></a><span class="lineno"> 8450</span>&#160; </div>
+<div class="line"><a name="l08451"></a><span class="lineno"> 8451</span>&#160;    json.WriteString(<span class="stringliteral">&quot;Size&quot;</span>);</div>
+<div class="line"><a name="l08452"></a><span class="lineno"> 8452</span>&#160;    json.WriteNumber(size);</div>
+<div class="line"><a name="l08453"></a><span class="lineno"> 8453</span>&#160; </div>
+<div class="line"><a name="l08454"></a><span class="lineno"> 8454</span>&#160;    json.EndObject();</div>
+<div class="line"><a name="l08455"></a><span class="lineno"> 8455</span>&#160;}</div>
+<div class="line"><a name="l08456"></a><span class="lineno"> 8456</span>&#160; </div>
+<div class="line"><a name="l08457"></a><span class="lineno"> 8457</span>&#160;<span class="keywordtype">void</span> VmaBlockMetadata::PrintDetailedMap_End(<span class="keyword">class</span> VmaJsonWriter&amp; json)<span class="keyword"> const</span></div>
+<div class="line"><a name="l08458"></a><span class="lineno"> 8458</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l08459"></a><span class="lineno"> 8459</span>&#160;    json.EndArray();</div>
+<div class="line"><a name="l08460"></a><span class="lineno"> 8460</span>&#160;    json.EndObject();</div>
+<div class="line"><a name="l08461"></a><span class="lineno"> 8461</span>&#160;}</div>
+<div class="line"><a name="l08462"></a><span class="lineno"> 8462</span>&#160; </div>
+<div class="line"><a name="l08463"></a><span class="lineno"> 8463</span>&#160;<span class="preprocessor">#endif // #if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l08464"></a><span class="lineno"> 8464</span>&#160; </div>
+<div class="line"><a name="l08466"></a><span class="lineno"> 8466</span>&#160;<span class="comment">// class VmaBlockMetadata_Generic</span></div>
+<div class="line"><a name="l08467"></a><span class="lineno"> 8467</span>&#160; </div>
+<div class="line"><a name="l08468"></a><span class="lineno"> 8468</span>&#160;VmaBlockMetadata_Generic::VmaBlockMetadata_Generic(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator) :</div>
+<div class="line"><a name="l08469"></a><span class="lineno"> 8469</span>&#160;    VmaBlockMetadata(hAllocator),</div>
+<div class="line"><a name="l08470"></a><span class="lineno"> 8470</span>&#160;    m_FreeCount(0),</div>
+<div class="line"><a name="l08471"></a><span class="lineno"> 8471</span>&#160;    m_SumFreeSize(0),</div>
+<div class="line"><a name="l08472"></a><span class="lineno"> 8472</span>&#160;    m_Suballocations(VmaStlAllocator&lt;VmaSuballocation&gt;(hAllocator-&gt;GetAllocationCallbacks())),</div>
+<div class="line"><a name="l08473"></a><span class="lineno"> 8473</span>&#160;    m_FreeSuballocationsBySize(VmaStlAllocator&lt;VmaSuballocationList::iterator&gt;(hAllocator-&gt;GetAllocationCallbacks()))</div>
+<div class="line"><a name="l08474"></a><span class="lineno"> 8474</span>&#160;{</div>
+<div class="line"><a name="l08475"></a><span class="lineno"> 8475</span>&#160;}</div>
+<div class="line"><a name="l08476"></a><span class="lineno"> 8476</span>&#160; </div>
+<div class="line"><a name="l08477"></a><span class="lineno"> 8477</span>&#160;VmaBlockMetadata_Generic::~VmaBlockMetadata_Generic()</div>
+<div class="line"><a name="l08478"></a><span class="lineno"> 8478</span>&#160;{</div>
+<div class="line"><a name="l08479"></a><span class="lineno"> 8479</span>&#160;}</div>
+<div class="line"><a name="l08480"></a><span class="lineno"> 8480</span>&#160; </div>
+<div class="line"><a name="l08481"></a><span class="lineno"> 8481</span>&#160;<span class="keywordtype">void</span> VmaBlockMetadata_Generic::Init(VkDeviceSize size)</div>
+<div class="line"><a name="l08482"></a><span class="lineno"> 8482</span>&#160;{</div>
+<div class="line"><a name="l08483"></a><span class="lineno"> 8483</span>&#160;    VmaBlockMetadata::Init(size);</div>
+<div class="line"><a name="l08484"></a><span class="lineno"> 8484</span>&#160; </div>
+<div class="line"><a name="l08485"></a><span class="lineno"> 8485</span>&#160;    m_FreeCount = 1;</div>
+<div class="line"><a name="l08486"></a><span class="lineno"> 8486</span>&#160;    m_SumFreeSize = size;</div>
+<div class="line"><a name="l08487"></a><span class="lineno"> 8487</span>&#160; </div>
+<div class="line"><a name="l08488"></a><span class="lineno"> 8488</span>&#160;    VmaSuballocation suballoc = {};</div>
+<div class="line"><a name="l08489"></a><span class="lineno"> 8489</span>&#160;    suballoc.offset = 0;</div>
+<div class="line"><a name="l08490"></a><span class="lineno"> 8490</span>&#160;    suballoc.size = size;</div>
+<div class="line"><a name="l08491"></a><span class="lineno"> 8491</span>&#160;    suballoc.type = VMA_SUBALLOCATION_TYPE_FREE;</div>
+<div class="line"><a name="l08492"></a><span class="lineno"> 8492</span>&#160;    suballoc.hAllocation = VK_NULL_HANDLE;</div>
+<div class="line"><a name="l08493"></a><span class="lineno"> 8493</span>&#160; </div>
+<div class="line"><a name="l08494"></a><span class="lineno"> 8494</span>&#160;    VMA_ASSERT(size &gt; VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER);</div>
+<div class="line"><a name="l08495"></a><span class="lineno"> 8495</span>&#160;    m_Suballocations.push_back(suballoc);</div>
+<div class="line"><a name="l08496"></a><span class="lineno"> 8496</span>&#160;    VmaSuballocationList::iterator suballocItem = m_Suballocations.end();</div>
+<div class="line"><a name="l08497"></a><span class="lineno"> 8497</span>&#160;    --suballocItem;</div>
+<div class="line"><a name="l08498"></a><span class="lineno"> 8498</span>&#160;    m_FreeSuballocationsBySize.push_back(suballocItem);</div>
+<div class="line"><a name="l08499"></a><span class="lineno"> 8499</span>&#160;}</div>
+<div class="line"><a name="l08500"></a><span class="lineno"> 8500</span>&#160; </div>
+<div class="line"><a name="l08501"></a><span class="lineno"> 8501</span>&#160;<span class="keywordtype">bool</span> VmaBlockMetadata_Generic::Validate()<span class="keyword"> const</span></div>
+<div class="line"><a name="l08502"></a><span class="lineno"> 8502</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l08503"></a><span class="lineno"> 8503</span>&#160;    VMA_VALIDATE(!m_Suballocations.empty());</div>
+<div class="line"><a name="l08504"></a><span class="lineno"> 8504</span>&#160;    </div>
+<div class="line"><a name="l08505"></a><span class="lineno"> 8505</span>&#160;    <span class="comment">// Expected offset of new suballocation as calculated from previous ones.</span></div>
+<div class="line"><a name="l08506"></a><span class="lineno"> 8506</span>&#160;    VkDeviceSize calculatedOffset = 0;</div>
+<div class="line"><a name="l08507"></a><span class="lineno"> 8507</span>&#160;    <span class="comment">// Expected number of free suballocations as calculated from traversing their list.</span></div>
+<div class="line"><a name="l08508"></a><span class="lineno"> 8508</span>&#160;    uint32_t calculatedFreeCount = 0;</div>
+<div class="line"><a name="l08509"></a><span class="lineno"> 8509</span>&#160;    <span class="comment">// Expected sum size of free suballocations as calculated from traversing their list.</span></div>
+<div class="line"><a name="l08510"></a><span class="lineno"> 8510</span>&#160;    VkDeviceSize calculatedSumFreeSize = 0;</div>
+<div class="line"><a name="l08511"></a><span class="lineno"> 8511</span>&#160;    <span class="comment">// Expected number of free suballocations that should be registered in</span></div>
+<div class="line"><a name="l08512"></a><span class="lineno"> 8512</span>&#160;    <span class="comment">// m_FreeSuballocationsBySize calculated from traversing their list.</span></div>
+<div class="line"><a name="l08513"></a><span class="lineno"> 8513</span>&#160;    <span class="keywordtype">size_t</span> freeSuballocationsToRegister = 0;</div>
+<div class="line"><a name="l08514"></a><span class="lineno"> 8514</span>&#160;    <span class="comment">// True if previous visited suballocation was free.</span></div>
+<div class="line"><a name="l08515"></a><span class="lineno"> 8515</span>&#160;    <span class="keywordtype">bool</span> prevFree = <span class="keyword">false</span>;</div>
+<div class="line"><a name="l08516"></a><span class="lineno"> 8516</span>&#160; </div>
+<div class="line"><a name="l08517"></a><span class="lineno"> 8517</span>&#160;    <span class="keywordflow">for</span>(VmaSuballocationList::const_iterator suballocItem = m_Suballocations.cbegin();</div>
+<div class="line"><a name="l08518"></a><span class="lineno"> 8518</span>&#160;        suballocItem != m_Suballocations.cend();</div>
+<div class="line"><a name="l08519"></a><span class="lineno"> 8519</span>&#160;        ++suballocItem)</div>
+<div class="line"><a name="l08520"></a><span class="lineno"> 8520</span>&#160;    {</div>
+<div class="line"><a name="l08521"></a><span class="lineno"> 8521</span>&#160;        <span class="keyword">const</span> VmaSuballocation&amp; subAlloc = *suballocItem;</div>
+<div class="line"><a name="l08522"></a><span class="lineno"> 8522</span>&#160;        </div>
+<div class="line"><a name="l08523"></a><span class="lineno"> 8523</span>&#160;        <span class="comment">// Actual offset of this suballocation doesn&#39;t match expected one.</span></div>
+<div class="line"><a name="l08524"></a><span class="lineno"> 8524</span>&#160;        VMA_VALIDATE(subAlloc.offset == calculatedOffset);</div>
+<div class="line"><a name="l08525"></a><span class="lineno"> 8525</span>&#160; </div>
+<div class="line"><a name="l08526"></a><span class="lineno"> 8526</span>&#160;        <span class="keyword">const</span> <span class="keywordtype">bool</span> currFree = (subAlloc.type == VMA_SUBALLOCATION_TYPE_FREE);</div>
+<div class="line"><a name="l08527"></a><span class="lineno"> 8527</span>&#160;        <span class="comment">// Two adjacent free suballocations are invalid. They should be merged.</span></div>
+<div class="line"><a name="l08528"></a><span class="lineno"> 8528</span>&#160;        VMA_VALIDATE(!prevFree || !currFree);</div>
+<div class="line"><a name="l08529"></a><span class="lineno"> 8529</span>&#160; </div>
+<div class="line"><a name="l08530"></a><span class="lineno"> 8530</span>&#160;        VMA_VALIDATE(currFree == (subAlloc.hAllocation == VK_NULL_HANDLE));</div>
+<div class="line"><a name="l08531"></a><span class="lineno"> 8531</span>&#160; </div>
+<div class="line"><a name="l08532"></a><span class="lineno"> 8532</span>&#160;        <span class="keywordflow">if</span>(currFree)</div>
+<div class="line"><a name="l08533"></a><span class="lineno"> 8533</span>&#160;        {</div>
+<div class="line"><a name="l08534"></a><span class="lineno"> 8534</span>&#160;            calculatedSumFreeSize += subAlloc.size;</div>
+<div class="line"><a name="l08535"></a><span class="lineno"> 8535</span>&#160;            ++calculatedFreeCount;</div>
+<div class="line"><a name="l08536"></a><span class="lineno"> 8536</span>&#160;            <span class="keywordflow">if</span>(subAlloc.size &gt;= VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER)</div>
+<div class="line"><a name="l08537"></a><span class="lineno"> 8537</span>&#160;            {</div>
+<div class="line"><a name="l08538"></a><span class="lineno"> 8538</span>&#160;                ++freeSuballocationsToRegister;</div>
+<div class="line"><a name="l08539"></a><span class="lineno"> 8539</span>&#160;            }</div>
+<div class="line"><a name="l08540"></a><span class="lineno"> 8540</span>&#160; </div>
+<div class="line"><a name="l08541"></a><span class="lineno"> 8541</span>&#160;            <span class="comment">// Margin required between allocations - every free space must be at least that large.</span></div>
+<div class="line"><a name="l08542"></a><span class="lineno"> 8542</span>&#160;            VMA_VALIDATE(subAlloc.size &gt;= VMA_DEBUG_MARGIN);</div>
+<div class="line"><a name="l08543"></a><span class="lineno"> 8543</span>&#160;        }</div>
+<div class="line"><a name="l08544"></a><span class="lineno"> 8544</span>&#160;        <span class="keywordflow">else</span></div>
+<div class="line"><a name="l08545"></a><span class="lineno"> 8545</span>&#160;        {</div>
+<div class="line"><a name="l08546"></a><span class="lineno"> 8546</span>&#160;            VMA_VALIDATE(subAlloc.hAllocation-&gt;GetOffset() == subAlloc.offset);</div>
+<div class="line"><a name="l08547"></a><span class="lineno"> 8547</span>&#160;            VMA_VALIDATE(subAlloc.hAllocation-&gt;GetSize() == subAlloc.size);</div>
+<div class="line"><a name="l08548"></a><span class="lineno"> 8548</span>&#160; </div>
+<div class="line"><a name="l08549"></a><span class="lineno"> 8549</span>&#160;            <span class="comment">// Margin required between allocations - previous allocation must be free.</span></div>
+<div class="line"><a name="l08550"></a><span class="lineno"> 8550</span>&#160;            VMA_VALIDATE(VMA_DEBUG_MARGIN == 0 || prevFree);</div>
+<div class="line"><a name="l08551"></a><span class="lineno"> 8551</span>&#160;        }</div>
+<div class="line"><a name="l08552"></a><span class="lineno"> 8552</span>&#160; </div>
+<div class="line"><a name="l08553"></a><span class="lineno"> 8553</span>&#160;        calculatedOffset += subAlloc.size;</div>
+<div class="line"><a name="l08554"></a><span class="lineno"> 8554</span>&#160;        prevFree = currFree;</div>
+<div class="line"><a name="l08555"></a><span class="lineno"> 8555</span>&#160;    }</div>
+<div class="line"><a name="l08556"></a><span class="lineno"> 8556</span>&#160; </div>
+<div class="line"><a name="l08557"></a><span class="lineno"> 8557</span>&#160;    <span class="comment">// Number of free suballocations registered in m_FreeSuballocationsBySize doesn&#39;t</span></div>
+<div class="line"><a name="l08558"></a><span class="lineno"> 8558</span>&#160;    <span class="comment">// match expected one.</span></div>
+<div class="line"><a name="l08559"></a><span class="lineno"> 8559</span>&#160;    VMA_VALIDATE(m_FreeSuballocationsBySize.size() == freeSuballocationsToRegister);</div>
+<div class="line"><a name="l08560"></a><span class="lineno"> 8560</span>&#160; </div>
+<div class="line"><a name="l08561"></a><span class="lineno"> 8561</span>&#160;    VkDeviceSize lastSize = 0;</div>
+<div class="line"><a name="l08562"></a><span class="lineno"> 8562</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = 0; i &lt; m_FreeSuballocationsBySize.size(); ++i)</div>
+<div class="line"><a name="l08563"></a><span class="lineno"> 8563</span>&#160;    {</div>
+<div class="line"><a name="l08564"></a><span class="lineno"> 8564</span>&#160;        VmaSuballocationList::iterator suballocItem = m_FreeSuballocationsBySize[i];</div>
+<div class="line"><a name="l08565"></a><span class="lineno"> 8565</span>&#160;        </div>
+<div class="line"><a name="l08566"></a><span class="lineno"> 8566</span>&#160;        <span class="comment">// Only free suballocations can be registered in m_FreeSuballocationsBySize.</span></div>
+<div class="line"><a name="l08567"></a><span class="lineno"> 8567</span>&#160;        VMA_VALIDATE(suballocItem-&gt;type == VMA_SUBALLOCATION_TYPE_FREE);</div>
+<div class="line"><a name="l08568"></a><span class="lineno"> 8568</span>&#160;        <span class="comment">// They must be sorted by size ascending.</span></div>
+<div class="line"><a name="l08569"></a><span class="lineno"> 8569</span>&#160;        VMA_VALIDATE(suballocItem-&gt;size &gt;= lastSize);</div>
+<div class="line"><a name="l08570"></a><span class="lineno"> 8570</span>&#160; </div>
+<div class="line"><a name="l08571"></a><span class="lineno"> 8571</span>&#160;        lastSize = suballocItem-&gt;size;</div>
+<div class="line"><a name="l08572"></a><span class="lineno"> 8572</span>&#160;    }</div>
+<div class="line"><a name="l08573"></a><span class="lineno"> 8573</span>&#160; </div>
+<div class="line"><a name="l08574"></a><span class="lineno"> 8574</span>&#160;    <span class="comment">// Check if totals match calculacted values.</span></div>
+<div class="line"><a name="l08575"></a><span class="lineno"> 8575</span>&#160;    VMA_VALIDATE(ValidateFreeSuballocationList());</div>
+<div class="line"><a name="l08576"></a><span class="lineno"> 8576</span>&#160;    VMA_VALIDATE(calculatedOffset == GetSize());</div>
+<div class="line"><a name="l08577"></a><span class="lineno"> 8577</span>&#160;    VMA_VALIDATE(calculatedSumFreeSize == m_SumFreeSize);</div>
+<div class="line"><a name="l08578"></a><span class="lineno"> 8578</span>&#160;    VMA_VALIDATE(calculatedFreeCount == m_FreeCount);</div>
+<div class="line"><a name="l08579"></a><span class="lineno"> 8579</span>&#160; </div>
+<div class="line"><a name="l08580"></a><span class="lineno"> 8580</span>&#160;    <span class="keywordflow">return</span> <span class="keyword">true</span>;</div>
+<div class="line"><a name="l08581"></a><span class="lineno"> 8581</span>&#160;}</div>
+<div class="line"><a name="l08582"></a><span class="lineno"> 8582</span>&#160; </div>
+<div class="line"><a name="l08583"></a><span class="lineno"> 8583</span>&#160;VkDeviceSize VmaBlockMetadata_Generic::GetUnusedRangeSizeMax()<span class="keyword"> const</span></div>
+<div class="line"><a name="l08584"></a><span class="lineno"> 8584</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l08585"></a><span class="lineno"> 8585</span>&#160;    <span class="keywordflow">if</span>(!m_FreeSuballocationsBySize.empty())</div>
+<div class="line"><a name="l08586"></a><span class="lineno"> 8586</span>&#160;    {</div>
+<div class="line"><a name="l08587"></a><span class="lineno"> 8587</span>&#160;        <span class="keywordflow">return</span> m_FreeSuballocationsBySize.back()-&gt;size;</div>
+<div class="line"><a name="l08588"></a><span class="lineno"> 8588</span>&#160;    }</div>
+<div class="line"><a name="l08589"></a><span class="lineno"> 8589</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l08590"></a><span class="lineno"> 8590</span>&#160;    {</div>
+<div class="line"><a name="l08591"></a><span class="lineno"> 8591</span>&#160;        <span class="keywordflow">return</span> 0;</div>
+<div class="line"><a name="l08592"></a><span class="lineno"> 8592</span>&#160;    }</div>
+<div class="line"><a name="l08593"></a><span class="lineno"> 8593</span>&#160;}</div>
+<div class="line"><a name="l08594"></a><span class="lineno"> 8594</span>&#160; </div>
+<div class="line"><a name="l08595"></a><span class="lineno"> 8595</span>&#160;<span class="keywordtype">bool</span> VmaBlockMetadata_Generic::IsEmpty()<span class="keyword"> const</span></div>
+<div class="line"><a name="l08596"></a><span class="lineno"> 8596</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l08597"></a><span class="lineno"> 8597</span>&#160;    <span class="keywordflow">return</span> (m_Suballocations.size() == 1) &amp;&amp; (m_FreeCount == 1);</div>
+<div class="line"><a name="l08598"></a><span class="lineno"> 8598</span>&#160;}</div>
+<div class="line"><a name="l08599"></a><span class="lineno"> 8599</span>&#160; </div>
+<div class="line"><a name="l08600"></a><span class="lineno"> 8600</span>&#160;<span class="keywordtype">void</span> VmaBlockMetadata_Generic::CalcAllocationStatInfo(<a class="code" href="struct_vma_stat_info.html">VmaStatInfo</a>&amp; outInfo)<span class="keyword"> const</span></div>
+<div class="line"><a name="l08601"></a><span class="lineno"> 8601</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l08602"></a><span class="lineno"> 8602</span>&#160;    outInfo.<a class="code" href="struct_vma_stat_info.html#abc4bb7cd611900778464c56e50c970a4">blockCount</a> = 1;</div>
+<div class="line"><a name="l08603"></a><span class="lineno"> 8603</span>&#160; </div>
+<div class="line"><a name="l08604"></a><span class="lineno"> 8604</span>&#160;    <span class="keyword">const</span> uint32_t rangeCount = (uint32_t)m_Suballocations.size();</div>
+<div class="line"><a name="l08605"></a><span class="lineno"> 8605</span>&#160;    outInfo.<a class="code" href="struct_vma_stat_info.html#a537741e4d5cdddc1c0ab95ec650afaff">allocationCount</a> = rangeCount - m_FreeCount;</div>
+<div class="line"><a name="l08606"></a><span class="lineno"> 8606</span>&#160;    outInfo.<a class="code" href="struct_vma_stat_info.html#ae06129c771bfebfd6468a7f4276502a9">unusedRangeCount</a> = m_FreeCount;</div>
+<div class="line"><a name="l08607"></a><span class="lineno"> 8607</span>&#160;    </div>
+<div class="line"><a name="l08608"></a><span class="lineno"> 8608</span>&#160;    outInfo.<a class="code" href="struct_vma_stat_info.html#a1859d290aca2cd582d8dc25922092669">unusedBytes</a> = m_SumFreeSize;</div>
+<div class="line"><a name="l08609"></a><span class="lineno"> 8609</span>&#160;    outInfo.<a class="code" href="struct_vma_stat_info.html#ab0c6c73837e5a70c749fbd4f6064895a">usedBytes</a> = GetSize() - outInfo.<a class="code" href="struct_vma_stat_info.html#a1859d290aca2cd582d8dc25922092669">unusedBytes</a>;</div>
+<div class="line"><a name="l08610"></a><span class="lineno"> 8610</span>&#160; </div>
+<div class="line"><a name="l08611"></a><span class="lineno"> 8611</span>&#160;    outInfo.<a class="code" href="struct_vma_stat_info.html#ade8b40bd3139c04aabd2fc538a356fea">allocationSizeMin</a> = UINT64_MAX;</div>
+<div class="line"><a name="l08612"></a><span class="lineno"> 8612</span>&#160;    outInfo.<a class="code" href="struct_vma_stat_info.html#a17e9733a5ecd76287d4db6e66f71f50c">allocationSizeMax</a> = 0;</div>
+<div class="line"><a name="l08613"></a><span class="lineno"> 8613</span>&#160;    outInfo.<a class="code" href="struct_vma_stat_info.html#aedeba931324f16589cd2416c0d2dd0d4">unusedRangeSizeMin</a> = UINT64_MAX;</div>
+<div class="line"><a name="l08614"></a><span class="lineno"> 8614</span>&#160;    outInfo.<a class="code" href="struct_vma_stat_info.html#a5ba1a2476c4d39b10f7e2f7ebbb72ac4">unusedRangeSizeMax</a> = 0;</div>
+<div class="line"><a name="l08615"></a><span class="lineno"> 8615</span>&#160; </div>
+<div class="line"><a name="l08616"></a><span class="lineno"> 8616</span>&#160;    <span class="keywordflow">for</span>(VmaSuballocationList::const_iterator suballocItem = m_Suballocations.cbegin();</div>
+<div class="line"><a name="l08617"></a><span class="lineno"> 8617</span>&#160;        suballocItem != m_Suballocations.cend();</div>
+<div class="line"><a name="l08618"></a><span class="lineno"> 8618</span>&#160;        ++suballocItem)</div>
+<div class="line"><a name="l08619"></a><span class="lineno"> 8619</span>&#160;    {</div>
+<div class="line"><a name="l08620"></a><span class="lineno"> 8620</span>&#160;        <span class="keyword">const</span> VmaSuballocation&amp; suballoc = *suballocItem;</div>
+<div class="line"><a name="l08621"></a><span class="lineno"> 8621</span>&#160;        <span class="keywordflow">if</span>(suballoc.type != VMA_SUBALLOCATION_TYPE_FREE)</div>
+<div class="line"><a name="l08622"></a><span class="lineno"> 8622</span>&#160;        {</div>
+<div class="line"><a name="l08623"></a><span class="lineno"> 8623</span>&#160;            outInfo.<a class="code" href="struct_vma_stat_info.html#ade8b40bd3139c04aabd2fc538a356fea">allocationSizeMin</a> = VMA_MIN(outInfo.<a class="code" href="struct_vma_stat_info.html#ade8b40bd3139c04aabd2fc538a356fea">allocationSizeMin</a>, suballoc.size);</div>
+<div class="line"><a name="l08624"></a><span class="lineno"> 8624</span>&#160;            outInfo.<a class="code" href="struct_vma_stat_info.html#a17e9733a5ecd76287d4db6e66f71f50c">allocationSizeMax</a> = VMA_MAX(outInfo.<a class="code" href="struct_vma_stat_info.html#a17e9733a5ecd76287d4db6e66f71f50c">allocationSizeMax</a>, suballoc.size);</div>
+<div class="line"><a name="l08625"></a><span class="lineno"> 8625</span>&#160;        }</div>
+<div class="line"><a name="l08626"></a><span class="lineno"> 8626</span>&#160;        <span class="keywordflow">else</span></div>
+<div class="line"><a name="l08627"></a><span class="lineno"> 8627</span>&#160;        {</div>
+<div class="line"><a name="l08628"></a><span class="lineno"> 8628</span>&#160;            outInfo.<a class="code" href="struct_vma_stat_info.html#aedeba931324f16589cd2416c0d2dd0d4">unusedRangeSizeMin</a> = VMA_MIN(outInfo.<a class="code" href="struct_vma_stat_info.html#aedeba931324f16589cd2416c0d2dd0d4">unusedRangeSizeMin</a>, suballoc.size);</div>
+<div class="line"><a name="l08629"></a><span class="lineno"> 8629</span>&#160;            outInfo.<a class="code" href="struct_vma_stat_info.html#a5ba1a2476c4d39b10f7e2f7ebbb72ac4">unusedRangeSizeMax</a> = VMA_MAX(outInfo.<a class="code" href="struct_vma_stat_info.html#a5ba1a2476c4d39b10f7e2f7ebbb72ac4">unusedRangeSizeMax</a>, suballoc.size);</div>
+<div class="line"><a name="l08630"></a><span class="lineno"> 8630</span>&#160;        }</div>
+<div class="line"><a name="l08631"></a><span class="lineno"> 8631</span>&#160;    }</div>
+<div class="line"><a name="l08632"></a><span class="lineno"> 8632</span>&#160;}</div>
+<div class="line"><a name="l08633"></a><span class="lineno"> 8633</span>&#160; </div>
+<div class="line"><a name="l08634"></a><span class="lineno"> 8634</span>&#160;<span class="keywordtype">void</span> VmaBlockMetadata_Generic::AddPoolStats(<a class="code" href="struct_vma_pool_stats.html">VmaPoolStats</a>&amp; inoutStats)<span class="keyword"> const</span></div>
+<div class="line"><a name="l08635"></a><span class="lineno"> 8635</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l08636"></a><span class="lineno"> 8636</span>&#160;    <span class="keyword">const</span> uint32_t rangeCount = (uint32_t)m_Suballocations.size();</div>
+<div class="line"><a name="l08637"></a><span class="lineno"> 8637</span>&#160; </div>
+<div class="line"><a name="l08638"></a><span class="lineno"> 8638</span>&#160;    inoutStats.<a class="code" href="struct_vma_pool_stats.html#a326807b2de2b0931cee4ed9a5f2e420c">size</a> += GetSize();</div>
+<div class="line"><a name="l08639"></a><span class="lineno"> 8639</span>&#160;    inoutStats.<a class="code" href="struct_vma_pool_stats.html#ad7c54874724fce7b06aba526202d82a8">unusedSize</a> += m_SumFreeSize;</div>
+<div class="line"><a name="l08640"></a><span class="lineno"> 8640</span>&#160;    inoutStats.<a class="code" href="struct_vma_pool_stats.html#ad1924eb54fffa45e9e0e65670c8fe5eb">allocationCount</a> += rangeCount - m_FreeCount;</div>
+<div class="line"><a name="l08641"></a><span class="lineno"> 8641</span>&#160;    inoutStats.<a class="code" href="struct_vma_pool_stats.html#ae4f3546ffa4d1e598b64d8e6134854f4">unusedRangeCount</a> += m_FreeCount;</div>
+<div class="line"><a name="l08642"></a><span class="lineno"> 8642</span>&#160;    inoutStats.<a class="code" href="struct_vma_pool_stats.html#ab4c8f52dd42ab01998f60f0b6acc722b">unusedRangeSizeMax</a> = VMA_MAX(inoutStats.<a class="code" href="struct_vma_pool_stats.html#ab4c8f52dd42ab01998f60f0b6acc722b">unusedRangeSizeMax</a>, GetUnusedRangeSizeMax());</div>
+<div class="line"><a name="l08643"></a><span class="lineno"> 8643</span>&#160;}</div>
+<div class="line"><a name="l08644"></a><span class="lineno"> 8644</span>&#160; </div>
+<div class="line"><a name="l08645"></a><span class="lineno"> 8645</span>&#160;<span class="preprocessor">#if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l08646"></a><span class="lineno"> 8646</span>&#160; </div>
+<div class="line"><a name="l08647"></a><span class="lineno"> 8647</span>&#160;<span class="keywordtype">void</span> VmaBlockMetadata_Generic::PrintDetailedMap(<span class="keyword">class</span> VmaJsonWriter&amp; json)<span class="keyword"> const</span></div>
+<div class="line"><a name="l08648"></a><span class="lineno"> 8648</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l08649"></a><span class="lineno"> 8649</span>&#160;    PrintDetailedMap_Begin(json,</div>
+<div class="line"><a name="l08650"></a><span class="lineno"> 8650</span>&#160;        m_SumFreeSize, <span class="comment">// unusedBytes</span></div>
+<div class="line"><a name="l08651"></a><span class="lineno"> 8651</span>&#160;        m_Suballocations.size() - (<span class="keywordtype">size_t</span>)m_FreeCount, <span class="comment">// allocationCount</span></div>
+<div class="line"><a name="l08652"></a><span class="lineno"> 8652</span>&#160;        m_FreeCount); <span class="comment">// unusedRangeCount</span></div>
+<div class="line"><a name="l08653"></a><span class="lineno"> 8653</span>&#160; </div>
+<div class="line"><a name="l08654"></a><span class="lineno"> 8654</span>&#160;    <span class="keywordtype">size_t</span> i = 0;</div>
+<div class="line"><a name="l08655"></a><span class="lineno"> 8655</span>&#160;    <span class="keywordflow">for</span>(VmaSuballocationList::const_iterator suballocItem = m_Suballocations.cbegin();</div>
+<div class="line"><a name="l08656"></a><span class="lineno"> 8656</span>&#160;        suballocItem != m_Suballocations.cend();</div>
+<div class="line"><a name="l08657"></a><span class="lineno"> 8657</span>&#160;        ++suballocItem, ++i)</div>
+<div class="line"><a name="l08658"></a><span class="lineno"> 8658</span>&#160;    {</div>
+<div class="line"><a name="l08659"></a><span class="lineno"> 8659</span>&#160;        <span class="keywordflow">if</span>(suballocItem-&gt;type == VMA_SUBALLOCATION_TYPE_FREE)</div>
+<div class="line"><a name="l08660"></a><span class="lineno"> 8660</span>&#160;        {</div>
+<div class="line"><a name="l08661"></a><span class="lineno"> 8661</span>&#160;            PrintDetailedMap_UnusedRange(json, suballocItem-&gt;offset, suballocItem-&gt;size);</div>
+<div class="line"><a name="l08662"></a><span class="lineno"> 8662</span>&#160;        }</div>
+<div class="line"><a name="l08663"></a><span class="lineno"> 8663</span>&#160;        <span class="keywordflow">else</span></div>
+<div class="line"><a name="l08664"></a><span class="lineno"> 8664</span>&#160;        {</div>
+<div class="line"><a name="l08665"></a><span class="lineno"> 8665</span>&#160;            PrintDetailedMap_Allocation(json, suballocItem-&gt;offset, suballocItem-&gt;hAllocation);</div>
+<div class="line"><a name="l08666"></a><span class="lineno"> 8666</span>&#160;        }</div>
+<div class="line"><a name="l08667"></a><span class="lineno"> 8667</span>&#160;    }</div>
+<div class="line"><a name="l08668"></a><span class="lineno"> 8668</span>&#160; </div>
+<div class="line"><a name="l08669"></a><span class="lineno"> 8669</span>&#160;    PrintDetailedMap_End(json);</div>
+<div class="line"><a name="l08670"></a><span class="lineno"> 8670</span>&#160;}</div>
+<div class="line"><a name="l08671"></a><span class="lineno"> 8671</span>&#160; </div>
+<div class="line"><a name="l08672"></a><span class="lineno"> 8672</span>&#160;<span class="preprocessor">#endif // #if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l08673"></a><span class="lineno"> 8673</span>&#160; </div>
+<div class="line"><a name="l08674"></a><span class="lineno"> 8674</span>&#160;<span class="keywordtype">bool</span> VmaBlockMetadata_Generic::CreateAllocationRequest(</div>
+<div class="line"><a name="l08675"></a><span class="lineno"> 8675</span>&#160;    uint32_t currentFrameIndex,</div>
+<div class="line"><a name="l08676"></a><span class="lineno"> 8676</span>&#160;    uint32_t frameInUseCount,</div>
+<div class="line"><a name="l08677"></a><span class="lineno"> 8677</span>&#160;    VkDeviceSize bufferImageGranularity,</div>
+<div class="line"><a name="l08678"></a><span class="lineno"> 8678</span>&#160;    VkDeviceSize allocSize,</div>
+<div class="line"><a name="l08679"></a><span class="lineno"> 8679</span>&#160;    VkDeviceSize allocAlignment,</div>
+<div class="line"><a name="l08680"></a><span class="lineno"> 8680</span>&#160;    <span class="keywordtype">bool</span> upperAddress,</div>
+<div class="line"><a name="l08681"></a><span class="lineno"> 8681</span>&#160;    VmaSuballocationType allocType,</div>
+<div class="line"><a name="l08682"></a><span class="lineno"> 8682</span>&#160;    <span class="keywordtype">bool</span> canMakeOtherLost,</div>
+<div class="line"><a name="l08683"></a><span class="lineno"> 8683</span>&#160;    uint32_t strategy,</div>
+<div class="line"><a name="l08684"></a><span class="lineno"> 8684</span>&#160;    VmaAllocationRequest* pAllocationRequest)</div>
+<div class="line"><a name="l08685"></a><span class="lineno"> 8685</span>&#160;{</div>
+<div class="line"><a name="l08686"></a><span class="lineno"> 8686</span>&#160;    VMA_ASSERT(allocSize &gt; 0);</div>
+<div class="line"><a name="l08687"></a><span class="lineno"> 8687</span>&#160;    VMA_ASSERT(!upperAddress);</div>
+<div class="line"><a name="l08688"></a><span class="lineno"> 8688</span>&#160;    VMA_ASSERT(allocType != VMA_SUBALLOCATION_TYPE_FREE);</div>
+<div class="line"><a name="l08689"></a><span class="lineno"> 8689</span>&#160;    VMA_ASSERT(pAllocationRequest != VMA_NULL);</div>
+<div class="line"><a name="l08690"></a><span class="lineno"> 8690</span>&#160;    VMA_HEAVY_ASSERT(Validate());</div>
+<div class="line"><a name="l08691"></a><span class="lineno"> 8691</span>&#160; </div>
+<div class="line"><a name="l08692"></a><span class="lineno"> 8692</span>&#160;    pAllocationRequest-&gt;type = VmaAllocationRequestType::Normal;</div>
+<div class="line"><a name="l08693"></a><span class="lineno"> 8693</span>&#160; </div>
+<div class="line"><a name="l08694"></a><span class="lineno"> 8694</span>&#160;    <span class="comment">// There is not enough total free space in this block to fullfill the request: Early return.</span></div>
+<div class="line"><a name="l08695"></a><span class="lineno"> 8695</span>&#160;    <span class="keywordflow">if</span>(canMakeOtherLost == <span class="keyword">false</span> &amp;&amp;</div>
+<div class="line"><a name="l08696"></a><span class="lineno"> 8696</span>&#160;        m_SumFreeSize &lt; allocSize + 2 * VMA_DEBUG_MARGIN)</div>
+<div class="line"><a name="l08697"></a><span class="lineno"> 8697</span>&#160;    {</div>
+<div class="line"><a name="l08698"></a><span class="lineno"> 8698</span>&#160;        <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l08699"></a><span class="lineno"> 8699</span>&#160;    }</div>
+<div class="line"><a name="l08700"></a><span class="lineno"> 8700</span>&#160; </div>
+<div class="line"><a name="l08701"></a><span class="lineno"> 8701</span>&#160;    <span class="comment">// New algorithm, efficiently searching freeSuballocationsBySize.</span></div>
+<div class="line"><a name="l08702"></a><span class="lineno"> 8702</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">size_t</span> freeSuballocCount = m_FreeSuballocationsBySize.size();</div>
+<div class="line"><a name="l08703"></a><span class="lineno"> 8703</span>&#160;    <span class="keywordflow">if</span>(freeSuballocCount &gt; 0)</div>
+<div class="line"><a name="l08704"></a><span class="lineno"> 8704</span>&#160;    {</div>
+<div class="line"><a name="l08705"></a><span class="lineno"> 8705</span>&#160;        <span class="keywordflow">if</span>(strategy == <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a839826775c62319466441f86496f036d">VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT</a>)</div>
+<div class="line"><a name="l08706"></a><span class="lineno"> 8706</span>&#160;        {</div>
+<div class="line"><a name="l08707"></a><span class="lineno"> 8707</span>&#160;            <span class="comment">// Find first free suballocation with size not less than allocSize + 2 * VMA_DEBUG_MARGIN.</span></div>
+<div class="line"><a name="l08708"></a><span class="lineno"> 8708</span>&#160;            VmaSuballocationList::iterator* <span class="keyword">const</span> it = VmaBinaryFindFirstNotLess(</div>
+<div class="line"><a name="l08709"></a><span class="lineno"> 8709</span>&#160;                m_FreeSuballocationsBySize.data(),</div>
+<div class="line"><a name="l08710"></a><span class="lineno"> 8710</span>&#160;                m_FreeSuballocationsBySize.data() + freeSuballocCount,</div>
+<div class="line"><a name="l08711"></a><span class="lineno"> 8711</span>&#160;                allocSize + 2 * VMA_DEBUG_MARGIN,</div>
+<div class="line"><a name="l08712"></a><span class="lineno"> 8712</span>&#160;                VmaSuballocationItemSizeLess());</div>
+<div class="line"><a name="l08713"></a><span class="lineno"> 8713</span>&#160;            <span class="keywordtype">size_t</span> index = it - m_FreeSuballocationsBySize.data();</div>
+<div class="line"><a name="l08714"></a><span class="lineno"> 8714</span>&#160;            <span class="keywordflow">for</span>(; index &lt; freeSuballocCount; ++index)</div>
+<div class="line"><a name="l08715"></a><span class="lineno"> 8715</span>&#160;            {</div>
+<div class="line"><a name="l08716"></a><span class="lineno"> 8716</span>&#160;                <span class="keywordflow">if</span>(CheckAllocation(</div>
+<div class="line"><a name="l08717"></a><span class="lineno"> 8717</span>&#160;                    currentFrameIndex,</div>
+<div class="line"><a name="l08718"></a><span class="lineno"> 8718</span>&#160;                    frameInUseCount,</div>
+<div class="line"><a name="l08719"></a><span class="lineno"> 8719</span>&#160;                    bufferImageGranularity,</div>
+<div class="line"><a name="l08720"></a><span class="lineno"> 8720</span>&#160;                    allocSize,</div>
+<div class="line"><a name="l08721"></a><span class="lineno"> 8721</span>&#160;                    allocAlignment,</div>
+<div class="line"><a name="l08722"></a><span class="lineno"> 8722</span>&#160;                    allocType,</div>
+<div class="line"><a name="l08723"></a><span class="lineno"> 8723</span>&#160;                    m_FreeSuballocationsBySize[index],</div>
+<div class="line"><a name="l08724"></a><span class="lineno"> 8724</span>&#160;                    <span class="keyword">false</span>, <span class="comment">// canMakeOtherLost</span></div>
+<div class="line"><a name="l08725"></a><span class="lineno"> 8725</span>&#160;                    &amp;pAllocationRequest-&gt;offset,</div>
+<div class="line"><a name="l08726"></a><span class="lineno"> 8726</span>&#160;                    &amp;pAllocationRequest-&gt;itemsToMakeLostCount,</div>
+<div class="line"><a name="l08727"></a><span class="lineno"> 8727</span>&#160;                    &amp;pAllocationRequest-&gt;sumFreeSize,</div>
+<div class="line"><a name="l08728"></a><span class="lineno"> 8728</span>&#160;                    &amp;pAllocationRequest-&gt;sumItemSize))</div>
+<div class="line"><a name="l08729"></a><span class="lineno"> 8729</span>&#160;                {</div>
+<div class="line"><a name="l08730"></a><span class="lineno"> 8730</span>&#160;                    pAllocationRequest-&gt;item = m_FreeSuballocationsBySize[index];</div>
+<div class="line"><a name="l08731"></a><span class="lineno"> 8731</span>&#160;                    <span class="keywordflow">return</span> <span class="keyword">true</span>;</div>
+<div class="line"><a name="l08732"></a><span class="lineno"> 8732</span>&#160;                }</div>
+<div class="line"><a name="l08733"></a><span class="lineno"> 8733</span>&#160;            }</div>
+<div class="line"><a name="l08734"></a><span class="lineno"> 8734</span>&#160;        }</div>
+<div class="line"><a name="l08735"></a><span class="lineno"> 8735</span>&#160;        <span class="keywordflow">else</span> <span class="keywordflow">if</span>(strategy == VMA_ALLOCATION_INTERNAL_STRATEGY_MIN_OFFSET)</div>
+<div class="line"><a name="l08736"></a><span class="lineno"> 8736</span>&#160;        {</div>
+<div class="line"><a name="l08737"></a><span class="lineno"> 8737</span>&#160;            <span class="keywordflow">for</span>(VmaSuballocationList::iterator it = m_Suballocations.begin();</div>
+<div class="line"><a name="l08738"></a><span class="lineno"> 8738</span>&#160;                it != m_Suballocations.end();</div>
+<div class="line"><a name="l08739"></a><span class="lineno"> 8739</span>&#160;                ++it)</div>
+<div class="line"><a name="l08740"></a><span class="lineno"> 8740</span>&#160;            {</div>
+<div class="line"><a name="l08741"></a><span class="lineno"> 8741</span>&#160;                <span class="keywordflow">if</span>(it-&gt;type == VMA_SUBALLOCATION_TYPE_FREE &amp;&amp; CheckAllocation(</div>
+<div class="line"><a name="l08742"></a><span class="lineno"> 8742</span>&#160;                    currentFrameIndex,</div>
+<div class="line"><a name="l08743"></a><span class="lineno"> 8743</span>&#160;                    frameInUseCount,</div>
+<div class="line"><a name="l08744"></a><span class="lineno"> 8744</span>&#160;                    bufferImageGranularity,</div>
+<div class="line"><a name="l08745"></a><span class="lineno"> 8745</span>&#160;                    allocSize,</div>
+<div class="line"><a name="l08746"></a><span class="lineno"> 8746</span>&#160;                    allocAlignment,</div>
+<div class="line"><a name="l08747"></a><span class="lineno"> 8747</span>&#160;                    allocType,</div>
+<div class="line"><a name="l08748"></a><span class="lineno"> 8748</span>&#160;                    it,</div>
+<div class="line"><a name="l08749"></a><span class="lineno"> 8749</span>&#160;                    <span class="keyword">false</span>, <span class="comment">// canMakeOtherLost</span></div>
+<div class="line"><a name="l08750"></a><span class="lineno"> 8750</span>&#160;                    &amp;pAllocationRequest-&gt;offset,</div>
+<div class="line"><a name="l08751"></a><span class="lineno"> 8751</span>&#160;                    &amp;pAllocationRequest-&gt;itemsToMakeLostCount,</div>
+<div class="line"><a name="l08752"></a><span class="lineno"> 8752</span>&#160;                    &amp;pAllocationRequest-&gt;sumFreeSize,</div>
+<div class="line"><a name="l08753"></a><span class="lineno"> 8753</span>&#160;                    &amp;pAllocationRequest-&gt;sumItemSize))</div>
+<div class="line"><a name="l08754"></a><span class="lineno"> 8754</span>&#160;                {</div>
+<div class="line"><a name="l08755"></a><span class="lineno"> 8755</span>&#160;                    pAllocationRequest-&gt;item = it;</div>
+<div class="line"><a name="l08756"></a><span class="lineno"> 8756</span>&#160;                    <span class="keywordflow">return</span> <span class="keyword">true</span>;</div>
+<div class="line"><a name="l08757"></a><span class="lineno"> 8757</span>&#160;                }</div>
+<div class="line"><a name="l08758"></a><span class="lineno"> 8758</span>&#160;            }</div>
+<div class="line"><a name="l08759"></a><span class="lineno"> 8759</span>&#160;        }</div>
+<div class="line"><a name="l08760"></a><span class="lineno"> 8760</span>&#160;        <span class="keywordflow">else</span> <span class="comment">// WORST_FIT, FIRST_FIT</span></div>
+<div class="line"><a name="l08761"></a><span class="lineno"> 8761</span>&#160;        {</div>
+<div class="line"><a name="l08762"></a><span class="lineno"> 8762</span>&#160;            <span class="comment">// Search staring from biggest suballocations.</span></div>
+<div class="line"><a name="l08763"></a><span class="lineno"> 8763</span>&#160;            <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> index = freeSuballocCount; index--; )</div>
+<div class="line"><a name="l08764"></a><span class="lineno"> 8764</span>&#160;            {</div>
+<div class="line"><a name="l08765"></a><span class="lineno"> 8765</span>&#160;                <span class="keywordflow">if</span>(CheckAllocation(</div>
+<div class="line"><a name="l08766"></a><span class="lineno"> 8766</span>&#160;                    currentFrameIndex,</div>
+<div class="line"><a name="l08767"></a><span class="lineno"> 8767</span>&#160;                    frameInUseCount,</div>
+<div class="line"><a name="l08768"></a><span class="lineno"> 8768</span>&#160;                    bufferImageGranularity,</div>
+<div class="line"><a name="l08769"></a><span class="lineno"> 8769</span>&#160;                    allocSize,</div>
+<div class="line"><a name="l08770"></a><span class="lineno"> 8770</span>&#160;                    allocAlignment,</div>
+<div class="line"><a name="l08771"></a><span class="lineno"> 8771</span>&#160;                    allocType,</div>
+<div class="line"><a name="l08772"></a><span class="lineno"> 8772</span>&#160;                    m_FreeSuballocationsBySize[index],</div>
+<div class="line"><a name="l08773"></a><span class="lineno"> 8773</span>&#160;                    <span class="keyword">false</span>, <span class="comment">// canMakeOtherLost</span></div>
+<div class="line"><a name="l08774"></a><span class="lineno"> 8774</span>&#160;                    &amp;pAllocationRequest-&gt;offset,</div>
+<div class="line"><a name="l08775"></a><span class="lineno"> 8775</span>&#160;                    &amp;pAllocationRequest-&gt;itemsToMakeLostCount,</div>
+<div class="line"><a name="l08776"></a><span class="lineno"> 8776</span>&#160;                    &amp;pAllocationRequest-&gt;sumFreeSize,</div>
+<div class="line"><a name="l08777"></a><span class="lineno"> 8777</span>&#160;                    &amp;pAllocationRequest-&gt;sumItemSize))</div>
+<div class="line"><a name="l08778"></a><span class="lineno"> 8778</span>&#160;                {</div>
+<div class="line"><a name="l08779"></a><span class="lineno"> 8779</span>&#160;                    pAllocationRequest-&gt;item = m_FreeSuballocationsBySize[index];</div>
+<div class="line"><a name="l08780"></a><span class="lineno"> 8780</span>&#160;                    <span class="keywordflow">return</span> <span class="keyword">true</span>;</div>
+<div class="line"><a name="l08781"></a><span class="lineno"> 8781</span>&#160;                }</div>
+<div class="line"><a name="l08782"></a><span class="lineno"> 8782</span>&#160;            }</div>
+<div class="line"><a name="l08783"></a><span class="lineno"> 8783</span>&#160;        }</div>
+<div class="line"><a name="l08784"></a><span class="lineno"> 8784</span>&#160;    }</div>
+<div class="line"><a name="l08785"></a><span class="lineno"> 8785</span>&#160; </div>
+<div class="line"><a name="l08786"></a><span class="lineno"> 8786</span>&#160;    <span class="keywordflow">if</span>(canMakeOtherLost)</div>
+<div class="line"><a name="l08787"></a><span class="lineno"> 8787</span>&#160;    {</div>
+<div class="line"><a name="l08788"></a><span class="lineno"> 8788</span>&#160;        <span class="comment">// Brute-force algorithm. TODO: Come up with something better.</span></div>
+<div class="line"><a name="l08789"></a><span class="lineno"> 8789</span>&#160; </div>
+<div class="line"><a name="l08790"></a><span class="lineno"> 8790</span>&#160;        <span class="keywordtype">bool</span> found = <span class="keyword">false</span>;</div>
+<div class="line"><a name="l08791"></a><span class="lineno"> 8791</span>&#160;        VmaAllocationRequest tmpAllocRequest = {};</div>
+<div class="line"><a name="l08792"></a><span class="lineno"> 8792</span>&#160;        tmpAllocRequest.type = VmaAllocationRequestType::Normal;</div>
+<div class="line"><a name="l08793"></a><span class="lineno"> 8793</span>&#160;        <span class="keywordflow">for</span>(VmaSuballocationList::iterator suballocIt = m_Suballocations.begin();</div>
+<div class="line"><a name="l08794"></a><span class="lineno"> 8794</span>&#160;            suballocIt != m_Suballocations.end();</div>
+<div class="line"><a name="l08795"></a><span class="lineno"> 8795</span>&#160;            ++suballocIt)</div>
+<div class="line"><a name="l08796"></a><span class="lineno"> 8796</span>&#160;        {</div>
+<div class="line"><a name="l08797"></a><span class="lineno"> 8797</span>&#160;            <span class="keywordflow">if</span>(suballocIt-&gt;type == VMA_SUBALLOCATION_TYPE_FREE ||</div>
+<div class="line"><a name="l08798"></a><span class="lineno"> 8798</span>&#160;                suballocIt-&gt;hAllocation-&gt;CanBecomeLost())</div>
+<div class="line"><a name="l08799"></a><span class="lineno"> 8799</span>&#160;            {</div>
+<div class="line"><a name="l08800"></a><span class="lineno"> 8800</span>&#160;                <span class="keywordflow">if</span>(CheckAllocation(</div>
+<div class="line"><a name="l08801"></a><span class="lineno"> 8801</span>&#160;                    currentFrameIndex,</div>
+<div class="line"><a name="l08802"></a><span class="lineno"> 8802</span>&#160;                    frameInUseCount,</div>
+<div class="line"><a name="l08803"></a><span class="lineno"> 8803</span>&#160;                    bufferImageGranularity,</div>
+<div class="line"><a name="l08804"></a><span class="lineno"> 8804</span>&#160;                    allocSize,</div>
+<div class="line"><a name="l08805"></a><span class="lineno"> 8805</span>&#160;                    allocAlignment,</div>
+<div class="line"><a name="l08806"></a><span class="lineno"> 8806</span>&#160;                    allocType,</div>
+<div class="line"><a name="l08807"></a><span class="lineno"> 8807</span>&#160;                    suballocIt,</div>
+<div class="line"><a name="l08808"></a><span class="lineno"> 8808</span>&#160;                    canMakeOtherLost,</div>
+<div class="line"><a name="l08809"></a><span class="lineno"> 8809</span>&#160;                    &amp;tmpAllocRequest.offset,</div>
+<div class="line"><a name="l08810"></a><span class="lineno"> 8810</span>&#160;                    &amp;tmpAllocRequest.itemsToMakeLostCount,</div>
+<div class="line"><a name="l08811"></a><span class="lineno"> 8811</span>&#160;                    &amp;tmpAllocRequest.sumFreeSize,</div>
+<div class="line"><a name="l08812"></a><span class="lineno"> 8812</span>&#160;                    &amp;tmpAllocRequest.sumItemSize))</div>
+<div class="line"><a name="l08813"></a><span class="lineno"> 8813</span>&#160;                {</div>
+<div class="line"><a name="l08814"></a><span class="lineno"> 8814</span>&#160;                    <span class="keywordflow">if</span>(strategy == <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a33eb2052674f3ad92386c714a65fb777">VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT</a>)</div>
+<div class="line"><a name="l08815"></a><span class="lineno"> 8815</span>&#160;                    {</div>
+<div class="line"><a name="l08816"></a><span class="lineno"> 8816</span>&#160;                        *pAllocationRequest = tmpAllocRequest;</div>
+<div class="line"><a name="l08817"></a><span class="lineno"> 8817</span>&#160;                        pAllocationRequest-&gt;item = suballocIt;</div>
+<div class="line"><a name="l08818"></a><span class="lineno"> 8818</span>&#160;                        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l08819"></a><span class="lineno"> 8819</span>&#160;                    }</div>
+<div class="line"><a name="l08820"></a><span class="lineno"> 8820</span>&#160;                    <span class="keywordflow">if</span>(!found || tmpAllocRequest.CalcCost() &lt; pAllocationRequest-&gt;CalcCost())</div>
+<div class="line"><a name="l08821"></a><span class="lineno"> 8821</span>&#160;                    {</div>
+<div class="line"><a name="l08822"></a><span class="lineno"> 8822</span>&#160;                        *pAllocationRequest = tmpAllocRequest;</div>
+<div class="line"><a name="l08823"></a><span class="lineno"> 8823</span>&#160;                        pAllocationRequest-&gt;item = suballocIt;</div>
+<div class="line"><a name="l08824"></a><span class="lineno"> 8824</span>&#160;                        found = <span class="keyword">true</span>;</div>
+<div class="line"><a name="l08825"></a><span class="lineno"> 8825</span>&#160;                    }</div>
+<div class="line"><a name="l08826"></a><span class="lineno"> 8826</span>&#160;                }</div>
+<div class="line"><a name="l08827"></a><span class="lineno"> 8827</span>&#160;            }</div>
+<div class="line"><a name="l08828"></a><span class="lineno"> 8828</span>&#160;        }</div>
+<div class="line"><a name="l08829"></a><span class="lineno"> 8829</span>&#160; </div>
+<div class="line"><a name="l08830"></a><span class="lineno"> 8830</span>&#160;        <span class="keywordflow">return</span> found;</div>
+<div class="line"><a name="l08831"></a><span class="lineno"> 8831</span>&#160;    }</div>
+<div class="line"><a name="l08832"></a><span class="lineno"> 8832</span>&#160; </div>
+<div class="line"><a name="l08833"></a><span class="lineno"> 8833</span>&#160;    <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l08834"></a><span class="lineno"> 8834</span>&#160;}</div>
+<div class="line"><a name="l08835"></a><span class="lineno"> 8835</span>&#160; </div>
+<div class="line"><a name="l08836"></a><span class="lineno"> 8836</span>&#160;<span class="keywordtype">bool</span> VmaBlockMetadata_Generic::MakeRequestedAllocationsLost(</div>
+<div class="line"><a name="l08837"></a><span class="lineno"> 8837</span>&#160;    uint32_t currentFrameIndex,</div>
+<div class="line"><a name="l08838"></a><span class="lineno"> 8838</span>&#160;    uint32_t frameInUseCount,</div>
+<div class="line"><a name="l08839"></a><span class="lineno"> 8839</span>&#160;    VmaAllocationRequest* pAllocationRequest)</div>
+<div class="line"><a name="l08840"></a><span class="lineno"> 8840</span>&#160;{</div>
+<div class="line"><a name="l08841"></a><span class="lineno"> 8841</span>&#160;    VMA_ASSERT(pAllocationRequest &amp;&amp; pAllocationRequest-&gt;type == VmaAllocationRequestType::Normal);</div>
+<div class="line"><a name="l08842"></a><span class="lineno"> 8842</span>&#160; </div>
+<div class="line"><a name="l08843"></a><span class="lineno"> 8843</span>&#160;    <span class="keywordflow">while</span>(pAllocationRequest-&gt;itemsToMakeLostCount &gt; 0)</div>
+<div class="line"><a name="l08844"></a><span class="lineno"> 8844</span>&#160;    {</div>
+<div class="line"><a name="l08845"></a><span class="lineno"> 8845</span>&#160;        <span class="keywordflow">if</span>(pAllocationRequest-&gt;item-&gt;type == VMA_SUBALLOCATION_TYPE_FREE)</div>
+<div class="line"><a name="l08846"></a><span class="lineno"> 8846</span>&#160;        {</div>
+<div class="line"><a name="l08847"></a><span class="lineno"> 8847</span>&#160;            ++pAllocationRequest-&gt;item;</div>
+<div class="line"><a name="l08848"></a><span class="lineno"> 8848</span>&#160;        }</div>
+<div class="line"><a name="l08849"></a><span class="lineno"> 8849</span>&#160;        VMA_ASSERT(pAllocationRequest-&gt;item != m_Suballocations.end());</div>
+<div class="line"><a name="l08850"></a><span class="lineno"> 8850</span>&#160;        VMA_ASSERT(pAllocationRequest-&gt;item-&gt;hAllocation != VK_NULL_HANDLE);</div>
+<div class="line"><a name="l08851"></a><span class="lineno"> 8851</span>&#160;        VMA_ASSERT(pAllocationRequest-&gt;item-&gt;hAllocation-&gt;CanBecomeLost());</div>
+<div class="line"><a name="l08852"></a><span class="lineno"> 8852</span>&#160;        <span class="keywordflow">if</span>(pAllocationRequest-&gt;item-&gt;hAllocation-&gt;MakeLost(currentFrameIndex, frameInUseCount))</div>
+<div class="line"><a name="l08853"></a><span class="lineno"> 8853</span>&#160;        {</div>
+<div class="line"><a name="l08854"></a><span class="lineno"> 8854</span>&#160;            pAllocationRequest-&gt;item = FreeSuballocation(pAllocationRequest-&gt;item);</div>
+<div class="line"><a name="l08855"></a><span class="lineno"> 8855</span>&#160;            --pAllocationRequest-&gt;itemsToMakeLostCount;</div>
+<div class="line"><a name="l08856"></a><span class="lineno"> 8856</span>&#160;        }</div>
+<div class="line"><a name="l08857"></a><span class="lineno"> 8857</span>&#160;        <span class="keywordflow">else</span></div>
+<div class="line"><a name="l08858"></a><span class="lineno"> 8858</span>&#160;        {</div>
+<div class="line"><a name="l08859"></a><span class="lineno"> 8859</span>&#160;            <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l08860"></a><span class="lineno"> 8860</span>&#160;        }</div>
+<div class="line"><a name="l08861"></a><span class="lineno"> 8861</span>&#160;    }</div>
+<div class="line"><a name="l08862"></a><span class="lineno"> 8862</span>&#160; </div>
+<div class="line"><a name="l08863"></a><span class="lineno"> 8863</span>&#160;    VMA_HEAVY_ASSERT(Validate());</div>
+<div class="line"><a name="l08864"></a><span class="lineno"> 8864</span>&#160;    VMA_ASSERT(pAllocationRequest-&gt;item != m_Suballocations.end());</div>
+<div class="line"><a name="l08865"></a><span class="lineno"> 8865</span>&#160;    VMA_ASSERT(pAllocationRequest-&gt;item-&gt;type == VMA_SUBALLOCATION_TYPE_FREE);</div>
+<div class="line"><a name="l08866"></a><span class="lineno"> 8866</span>&#160;    </div>
+<div class="line"><a name="l08867"></a><span class="lineno"> 8867</span>&#160;    <span class="keywordflow">return</span> <span class="keyword">true</span>;</div>
+<div class="line"><a name="l08868"></a><span class="lineno"> 8868</span>&#160;}</div>
+<div class="line"><a name="l08869"></a><span class="lineno"> 8869</span>&#160; </div>
+<div class="line"><a name="l08870"></a><span class="lineno"> 8870</span>&#160;uint32_t VmaBlockMetadata_Generic::MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount)</div>
+<div class="line"><a name="l08871"></a><span class="lineno"> 8871</span>&#160;{</div>
+<div class="line"><a name="l08872"></a><span class="lineno"> 8872</span>&#160;    uint32_t lostAllocationCount = 0;</div>
+<div class="line"><a name="l08873"></a><span class="lineno"> 8873</span>&#160;    <span class="keywordflow">for</span>(VmaSuballocationList::iterator it = m_Suballocations.begin();</div>
+<div class="line"><a name="l08874"></a><span class="lineno"> 8874</span>&#160;        it != m_Suballocations.end();</div>
+<div class="line"><a name="l08875"></a><span class="lineno"> 8875</span>&#160;        ++it)</div>
+<div class="line"><a name="l08876"></a><span class="lineno"> 8876</span>&#160;    {</div>
+<div class="line"><a name="l08877"></a><span class="lineno"> 8877</span>&#160;        <span class="keywordflow">if</span>(it-&gt;type != VMA_SUBALLOCATION_TYPE_FREE &amp;&amp;</div>
+<div class="line"><a name="l08878"></a><span class="lineno"> 8878</span>&#160;            it-&gt;hAllocation-&gt;CanBecomeLost() &amp;&amp;</div>
+<div class="line"><a name="l08879"></a><span class="lineno"> 8879</span>&#160;            it-&gt;hAllocation-&gt;MakeLost(currentFrameIndex, frameInUseCount))</div>
+<div class="line"><a name="l08880"></a><span class="lineno"> 8880</span>&#160;        {</div>
+<div class="line"><a name="l08881"></a><span class="lineno"> 8881</span>&#160;            it = FreeSuballocation(it);</div>
+<div class="line"><a name="l08882"></a><span class="lineno"> 8882</span>&#160;            ++lostAllocationCount;</div>
+<div class="line"><a name="l08883"></a><span class="lineno"> 8883</span>&#160;        }</div>
+<div class="line"><a name="l08884"></a><span class="lineno"> 8884</span>&#160;    }</div>
+<div class="line"><a name="l08885"></a><span class="lineno"> 8885</span>&#160;    <span class="keywordflow">return</span> lostAllocationCount;</div>
+<div class="line"><a name="l08886"></a><span class="lineno"> 8886</span>&#160;}</div>
+<div class="line"><a name="l08887"></a><span class="lineno"> 8887</span>&#160; </div>
+<div class="line"><a name="l08888"></a><span class="lineno"> 8888</span>&#160;VkResult VmaBlockMetadata_Generic::CheckCorruption(<span class="keyword">const</span> <span class="keywordtype">void</span>* pBlockData)</div>
+<div class="line"><a name="l08889"></a><span class="lineno"> 8889</span>&#160;{</div>
+<div class="line"><a name="l08890"></a><span class="lineno"> 8890</span>&#160;    <span class="keywordflow">for</span>(VmaSuballocationList::iterator it = m_Suballocations.begin();</div>
+<div class="line"><a name="l08891"></a><span class="lineno"> 8891</span>&#160;        it != m_Suballocations.end();</div>
+<div class="line"><a name="l08892"></a><span class="lineno"> 8892</span>&#160;        ++it)</div>
+<div class="line"><a name="l08893"></a><span class="lineno"> 8893</span>&#160;    {</div>
+<div class="line"><a name="l08894"></a><span class="lineno"> 8894</span>&#160;        <span class="keywordflow">if</span>(it-&gt;type != VMA_SUBALLOCATION_TYPE_FREE)</div>
+<div class="line"><a name="l08895"></a><span class="lineno"> 8895</span>&#160;        {</div>
+<div class="line"><a name="l08896"></a><span class="lineno"> 8896</span>&#160;            <span class="keywordflow">if</span>(!VmaValidateMagicValue(pBlockData, it-&gt;offset - VMA_DEBUG_MARGIN))</div>
+<div class="line"><a name="l08897"></a><span class="lineno"> 8897</span>&#160;            {</div>
+<div class="line"><a name="l08898"></a><span class="lineno"> 8898</span>&#160;                VMA_ASSERT(0 &amp;&amp; <span class="stringliteral">&quot;MEMORY CORRUPTION DETECTED BEFORE VALIDATED ALLOCATION!&quot;</span>);</div>
+<div class="line"><a name="l08899"></a><span class="lineno"> 8899</span>&#160;                <span class="keywordflow">return</span> VK_ERROR_VALIDATION_FAILED_EXT;</div>
+<div class="line"><a name="l08900"></a><span class="lineno"> 8900</span>&#160;            }</div>
+<div class="line"><a name="l08901"></a><span class="lineno"> 8901</span>&#160;            <span class="keywordflow">if</span>(!VmaValidateMagicValue(pBlockData, it-&gt;offset + it-&gt;size))</div>
+<div class="line"><a name="l08902"></a><span class="lineno"> 8902</span>&#160;            {</div>
+<div class="line"><a name="l08903"></a><span class="lineno"> 8903</span>&#160;                VMA_ASSERT(0 &amp;&amp; <span class="stringliteral">&quot;MEMORY CORRUPTION DETECTED AFTER VALIDATED ALLOCATION!&quot;</span>);</div>
+<div class="line"><a name="l08904"></a><span class="lineno"> 8904</span>&#160;                <span class="keywordflow">return</span> VK_ERROR_VALIDATION_FAILED_EXT;</div>
+<div class="line"><a name="l08905"></a><span class="lineno"> 8905</span>&#160;            }</div>
+<div class="line"><a name="l08906"></a><span class="lineno"> 8906</span>&#160;        }</div>
+<div class="line"><a name="l08907"></a><span class="lineno"> 8907</span>&#160;    }</div>
+<div class="line"><a name="l08908"></a><span class="lineno"> 8908</span>&#160; </div>
+<div class="line"><a name="l08909"></a><span class="lineno"> 8909</span>&#160;    <span class="keywordflow">return</span> VK_SUCCESS;</div>
+<div class="line"><a name="l08910"></a><span class="lineno"> 8910</span>&#160;}</div>
+<div class="line"><a name="l08911"></a><span class="lineno"> 8911</span>&#160; </div>
+<div class="line"><a name="l08912"></a><span class="lineno"> 8912</span>&#160;<span class="keywordtype">void</span> VmaBlockMetadata_Generic::Alloc(</div>
+<div class="line"><a name="l08913"></a><span class="lineno"> 8913</span>&#160;    <span class="keyword">const</span> VmaAllocationRequest&amp; request,</div>
+<div class="line"><a name="l08914"></a><span class="lineno"> 8914</span>&#160;    VmaSuballocationType type,</div>
+<div class="line"><a name="l08915"></a><span class="lineno"> 8915</span>&#160;    VkDeviceSize allocSize,</div>
+<div class="line"><a name="l08916"></a><span class="lineno"> 8916</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAllocation)</div>
+<div class="line"><a name="l08917"></a><span class="lineno"> 8917</span>&#160;{</div>
+<div class="line"><a name="l08918"></a><span class="lineno"> 8918</span>&#160;    VMA_ASSERT(request.type == VmaAllocationRequestType::Normal);</div>
+<div class="line"><a name="l08919"></a><span class="lineno"> 8919</span>&#160;    VMA_ASSERT(request.item != m_Suballocations.end());</div>
+<div class="line"><a name="l08920"></a><span class="lineno"> 8920</span>&#160;    VmaSuballocation&amp; suballoc = *request.item;</div>
+<div class="line"><a name="l08921"></a><span class="lineno"> 8921</span>&#160;    <span class="comment">// Given suballocation is a free block.</span></div>
+<div class="line"><a name="l08922"></a><span class="lineno"> 8922</span>&#160;    VMA_ASSERT(suballoc.type == VMA_SUBALLOCATION_TYPE_FREE);</div>
+<div class="line"><a name="l08923"></a><span class="lineno"> 8923</span>&#160;    <span class="comment">// Given offset is inside this suballocation.</span></div>
+<div class="line"><a name="l08924"></a><span class="lineno"> 8924</span>&#160;    VMA_ASSERT(request.offset &gt;= suballoc.offset);</div>
+<div class="line"><a name="l08925"></a><span class="lineno"> 8925</span>&#160;    <span class="keyword">const</span> VkDeviceSize paddingBegin = request.offset - suballoc.offset;</div>
+<div class="line"><a name="l08926"></a><span class="lineno"> 8926</span>&#160;    VMA_ASSERT(suballoc.size &gt;= paddingBegin + allocSize);</div>
+<div class="line"><a name="l08927"></a><span class="lineno"> 8927</span>&#160;    <span class="keyword">const</span> VkDeviceSize paddingEnd = suballoc.size - paddingBegin - allocSize;</div>
+<div class="line"><a name="l08928"></a><span class="lineno"> 8928</span>&#160; </div>
+<div class="line"><a name="l08929"></a><span class="lineno"> 8929</span>&#160;    <span class="comment">// Unregister this free suballocation from m_FreeSuballocationsBySize and update</span></div>
+<div class="line"><a name="l08930"></a><span class="lineno"> 8930</span>&#160;    <span class="comment">// it to become used.</span></div>
+<div class="line"><a name="l08931"></a><span class="lineno"> 8931</span>&#160;    UnregisterFreeSuballocation(request.item);</div>
+<div class="line"><a name="l08932"></a><span class="lineno"> 8932</span>&#160; </div>
+<div class="line"><a name="l08933"></a><span class="lineno"> 8933</span>&#160;    suballoc.offset = request.offset;</div>
+<div class="line"><a name="l08934"></a><span class="lineno"> 8934</span>&#160;    suballoc.size = allocSize;</div>
+<div class="line"><a name="l08935"></a><span class="lineno"> 8935</span>&#160;    suballoc.type = type;</div>
+<div class="line"><a name="l08936"></a><span class="lineno"> 8936</span>&#160;    suballoc.hAllocation = hAllocation;</div>
+<div class="line"><a name="l08937"></a><span class="lineno"> 8937</span>&#160; </div>
+<div class="line"><a name="l08938"></a><span class="lineno"> 8938</span>&#160;    <span class="comment">// If there are any free bytes remaining at the end, insert new free suballocation after current one.</span></div>
+<div class="line"><a name="l08939"></a><span class="lineno"> 8939</span>&#160;    <span class="keywordflow">if</span>(paddingEnd)</div>
+<div class="line"><a name="l08940"></a><span class="lineno"> 8940</span>&#160;    {</div>
+<div class="line"><a name="l08941"></a><span class="lineno"> 8941</span>&#160;        VmaSuballocation paddingSuballoc = {};</div>
+<div class="line"><a name="l08942"></a><span class="lineno"> 8942</span>&#160;        paddingSuballoc.offset = request.offset + allocSize;</div>
+<div class="line"><a name="l08943"></a><span class="lineno"> 8943</span>&#160;        paddingSuballoc.size = paddingEnd;</div>
+<div class="line"><a name="l08944"></a><span class="lineno"> 8944</span>&#160;        paddingSuballoc.type = VMA_SUBALLOCATION_TYPE_FREE;</div>
+<div class="line"><a name="l08945"></a><span class="lineno"> 8945</span>&#160;        VmaSuballocationList::iterator next = request.item;</div>
+<div class="line"><a name="l08946"></a><span class="lineno"> 8946</span>&#160;        ++next;</div>
+<div class="line"><a name="l08947"></a><span class="lineno"> 8947</span>&#160;        <span class="keyword">const</span> VmaSuballocationList::iterator paddingEndItem =</div>
+<div class="line"><a name="l08948"></a><span class="lineno"> 8948</span>&#160;            m_Suballocations.insert(next, paddingSuballoc);</div>
+<div class="line"><a name="l08949"></a><span class="lineno"> 8949</span>&#160;        RegisterFreeSuballocation(paddingEndItem);</div>
+<div class="line"><a name="l08950"></a><span class="lineno"> 8950</span>&#160;    }</div>
+<div class="line"><a name="l08951"></a><span class="lineno"> 8951</span>&#160; </div>
+<div class="line"><a name="l08952"></a><span class="lineno"> 8952</span>&#160;    <span class="comment">// If there are any free bytes remaining at the beginning, insert new free suballocation before current one.</span></div>
+<div class="line"><a name="l08953"></a><span class="lineno"> 8953</span>&#160;    <span class="keywordflow">if</span>(paddingBegin)</div>
+<div class="line"><a name="l08954"></a><span class="lineno"> 8954</span>&#160;    {</div>
+<div class="line"><a name="l08955"></a><span class="lineno"> 8955</span>&#160;        VmaSuballocation paddingSuballoc = {};</div>
+<div class="line"><a name="l08956"></a><span class="lineno"> 8956</span>&#160;        paddingSuballoc.offset = request.offset - paddingBegin;</div>
+<div class="line"><a name="l08957"></a><span class="lineno"> 8957</span>&#160;        paddingSuballoc.size = paddingBegin;</div>
+<div class="line"><a name="l08958"></a><span class="lineno"> 8958</span>&#160;        paddingSuballoc.type = VMA_SUBALLOCATION_TYPE_FREE;</div>
+<div class="line"><a name="l08959"></a><span class="lineno"> 8959</span>&#160;        <span class="keyword">const</span> VmaSuballocationList::iterator paddingBeginItem =</div>
+<div class="line"><a name="l08960"></a><span class="lineno"> 8960</span>&#160;            m_Suballocations.insert(request.item, paddingSuballoc);</div>
+<div class="line"><a name="l08961"></a><span class="lineno"> 8961</span>&#160;        RegisterFreeSuballocation(paddingBeginItem);</div>
+<div class="line"><a name="l08962"></a><span class="lineno"> 8962</span>&#160;    }</div>
+<div class="line"><a name="l08963"></a><span class="lineno"> 8963</span>&#160; </div>
+<div class="line"><a name="l08964"></a><span class="lineno"> 8964</span>&#160;    <span class="comment">// Update totals.</span></div>
+<div class="line"><a name="l08965"></a><span class="lineno"> 8965</span>&#160;    m_FreeCount = m_FreeCount - 1;</div>
+<div class="line"><a name="l08966"></a><span class="lineno"> 8966</span>&#160;    <span class="keywordflow">if</span>(paddingBegin &gt; 0)</div>
+<div class="line"><a name="l08967"></a><span class="lineno"> 8967</span>&#160;    {</div>
+<div class="line"><a name="l08968"></a><span class="lineno"> 8968</span>&#160;        ++m_FreeCount;</div>
+<div class="line"><a name="l08969"></a><span class="lineno"> 8969</span>&#160;    }</div>
+<div class="line"><a name="l08970"></a><span class="lineno"> 8970</span>&#160;    <span class="keywordflow">if</span>(paddingEnd &gt; 0)</div>
+<div class="line"><a name="l08971"></a><span class="lineno"> 8971</span>&#160;    {</div>
+<div class="line"><a name="l08972"></a><span class="lineno"> 8972</span>&#160;        ++m_FreeCount;</div>
+<div class="line"><a name="l08973"></a><span class="lineno"> 8973</span>&#160;    }</div>
+<div class="line"><a name="l08974"></a><span class="lineno"> 8974</span>&#160;    m_SumFreeSize -= allocSize;</div>
+<div class="line"><a name="l08975"></a><span class="lineno"> 8975</span>&#160;}</div>
+<div class="line"><a name="l08976"></a><span class="lineno"> 8976</span>&#160; </div>
+<div class="line"><a name="l08977"></a><span class="lineno"> 8977</span>&#160;<span class="keywordtype">void</span> VmaBlockMetadata_Generic::Free(<span class="keyword">const</span> <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation)</div>
+<div class="line"><a name="l08978"></a><span class="lineno"> 8978</span>&#160;{</div>
+<div class="line"><a name="l08979"></a><span class="lineno"> 8979</span>&#160;    <span class="keywordflow">for</span>(VmaSuballocationList::iterator suballocItem = m_Suballocations.begin();</div>
+<div class="line"><a name="l08980"></a><span class="lineno"> 8980</span>&#160;        suballocItem != m_Suballocations.end();</div>
+<div class="line"><a name="l08981"></a><span class="lineno"> 8981</span>&#160;        ++suballocItem)</div>
+<div class="line"><a name="l08982"></a><span class="lineno"> 8982</span>&#160;    {</div>
+<div class="line"><a name="l08983"></a><span class="lineno"> 8983</span>&#160;        VmaSuballocation&amp; suballoc = *suballocItem;</div>
+<div class="line"><a name="l08984"></a><span class="lineno"> 8984</span>&#160;        <span class="keywordflow">if</span>(suballoc.hAllocation == allocation)</div>
+<div class="line"><a name="l08985"></a><span class="lineno"> 8985</span>&#160;        {</div>
+<div class="line"><a name="l08986"></a><span class="lineno"> 8986</span>&#160;            FreeSuballocation(suballocItem);</div>
+<div class="line"><a name="l08987"></a><span class="lineno"> 8987</span>&#160;            VMA_HEAVY_ASSERT(Validate());</div>
+<div class="line"><a name="l08988"></a><span class="lineno"> 8988</span>&#160;            <span class="keywordflow">return</span>;</div>
+<div class="line"><a name="l08989"></a><span class="lineno"> 8989</span>&#160;        }</div>
+<div class="line"><a name="l08990"></a><span class="lineno"> 8990</span>&#160;    }</div>
+<div class="line"><a name="l08991"></a><span class="lineno"> 8991</span>&#160;    VMA_ASSERT(0 &amp;&amp; <span class="stringliteral">&quot;Not found!&quot;</span>);</div>
+<div class="line"><a name="l08992"></a><span class="lineno"> 8992</span>&#160;}</div>
+<div class="line"><a name="l08993"></a><span class="lineno"> 8993</span>&#160; </div>
+<div class="line"><a name="l08994"></a><span class="lineno"> 8994</span>&#160;<span class="keywordtype">void</span> VmaBlockMetadata_Generic::FreeAtOffset(VkDeviceSize offset)</div>
+<div class="line"><a name="l08995"></a><span class="lineno"> 8995</span>&#160;{</div>
+<div class="line"><a name="l08996"></a><span class="lineno"> 8996</span>&#160;    <span class="keywordflow">for</span>(VmaSuballocationList::iterator suballocItem = m_Suballocations.begin();</div>
+<div class="line"><a name="l08997"></a><span class="lineno"> 8997</span>&#160;        suballocItem != m_Suballocations.end();</div>
+<div class="line"><a name="l08998"></a><span class="lineno"> 8998</span>&#160;        ++suballocItem)</div>
+<div class="line"><a name="l08999"></a><span class="lineno"> 8999</span>&#160;    {</div>
+<div class="line"><a name="l09000"></a><span class="lineno"> 9000</span>&#160;        VmaSuballocation&amp; suballoc = *suballocItem;</div>
+<div class="line"><a name="l09001"></a><span class="lineno"> 9001</span>&#160;        <span class="keywordflow">if</span>(suballoc.offset == offset)</div>
+<div class="line"><a name="l09002"></a><span class="lineno"> 9002</span>&#160;        {</div>
+<div class="line"><a name="l09003"></a><span class="lineno"> 9003</span>&#160;            FreeSuballocation(suballocItem);</div>
+<div class="line"><a name="l09004"></a><span class="lineno"> 9004</span>&#160;            <span class="keywordflow">return</span>;</div>
+<div class="line"><a name="l09005"></a><span class="lineno"> 9005</span>&#160;        }</div>
+<div class="line"><a name="l09006"></a><span class="lineno"> 9006</span>&#160;    }</div>
+<div class="line"><a name="l09007"></a><span class="lineno"> 9007</span>&#160;    VMA_ASSERT(0 &amp;&amp; <span class="stringliteral">&quot;Not found!&quot;</span>);</div>
+<div class="line"><a name="l09008"></a><span class="lineno"> 9008</span>&#160;}</div>
+<div class="line"><a name="l09009"></a><span class="lineno"> 9009</span>&#160; </div>
+<div class="line"><a name="l09010"></a><span class="lineno"> 9010</span>&#160;<span class="keywordtype">bool</span> VmaBlockMetadata_Generic::ValidateFreeSuballocationList()<span class="keyword"> const</span></div>
+<div class="line"><a name="l09011"></a><span class="lineno"> 9011</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l09012"></a><span class="lineno"> 9012</span>&#160;    VkDeviceSize lastSize = 0;</div>
+<div class="line"><a name="l09013"></a><span class="lineno"> 9013</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = 0, count = m_FreeSuballocationsBySize.size(); i &lt; count; ++i)</div>
+<div class="line"><a name="l09014"></a><span class="lineno"> 9014</span>&#160;    {</div>
+<div class="line"><a name="l09015"></a><span class="lineno"> 9015</span>&#160;        <span class="keyword">const</span> VmaSuballocationList::iterator it = m_FreeSuballocationsBySize[i];</div>
+<div class="line"><a name="l09016"></a><span class="lineno"> 9016</span>&#160; </div>
+<div class="line"><a name="l09017"></a><span class="lineno"> 9017</span>&#160;        VMA_VALIDATE(it-&gt;type == VMA_SUBALLOCATION_TYPE_FREE);</div>
+<div class="line"><a name="l09018"></a><span class="lineno"> 9018</span>&#160;        VMA_VALIDATE(it-&gt;size &gt;= VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER);</div>
+<div class="line"><a name="l09019"></a><span class="lineno"> 9019</span>&#160;        VMA_VALIDATE(it-&gt;size &gt;= lastSize);</div>
+<div class="line"><a name="l09020"></a><span class="lineno"> 9020</span>&#160;        lastSize = it-&gt;size;</div>
+<div class="line"><a name="l09021"></a><span class="lineno"> 9021</span>&#160;    }</div>
+<div class="line"><a name="l09022"></a><span class="lineno"> 9022</span>&#160;    <span class="keywordflow">return</span> <span class="keyword">true</span>;</div>
+<div class="line"><a name="l09023"></a><span class="lineno"> 9023</span>&#160;}</div>
+<div class="line"><a name="l09024"></a><span class="lineno"> 9024</span>&#160; </div>
+<div class="line"><a name="l09025"></a><span class="lineno"> 9025</span>&#160;<span class="keywordtype">bool</span> VmaBlockMetadata_Generic::CheckAllocation(</div>
+<div class="line"><a name="l09026"></a><span class="lineno"> 9026</span>&#160;    uint32_t currentFrameIndex,</div>
+<div class="line"><a name="l09027"></a><span class="lineno"> 9027</span>&#160;    uint32_t frameInUseCount,</div>
+<div class="line"><a name="l09028"></a><span class="lineno"> 9028</span>&#160;    VkDeviceSize bufferImageGranularity,</div>
+<div class="line"><a name="l09029"></a><span class="lineno"> 9029</span>&#160;    VkDeviceSize allocSize,</div>
+<div class="line"><a name="l09030"></a><span class="lineno"> 9030</span>&#160;    VkDeviceSize allocAlignment,</div>
+<div class="line"><a name="l09031"></a><span class="lineno"> 9031</span>&#160;    VmaSuballocationType allocType,</div>
+<div class="line"><a name="l09032"></a><span class="lineno"> 9032</span>&#160;    VmaSuballocationList::const_iterator suballocItem,</div>
+<div class="line"><a name="l09033"></a><span class="lineno"> 9033</span>&#160;    <span class="keywordtype">bool</span> canMakeOtherLost,</div>
+<div class="line"><a name="l09034"></a><span class="lineno"> 9034</span>&#160;    VkDeviceSize* pOffset,</div>
+<div class="line"><a name="l09035"></a><span class="lineno"> 9035</span>&#160;    <span class="keywordtype">size_t</span>* itemsToMakeLostCount,</div>
+<div class="line"><a name="l09036"></a><span class="lineno"> 9036</span>&#160;    VkDeviceSize* pSumFreeSize,</div>
+<div class="line"><a name="l09037"></a><span class="lineno"> 9037</span>&#160;    VkDeviceSize* pSumItemSize)<span class="keyword"> const</span></div>
+<div class="line"><a name="l09038"></a><span class="lineno"> 9038</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l09039"></a><span class="lineno"> 9039</span>&#160;    VMA_ASSERT(allocSize &gt; 0);</div>
+<div class="line"><a name="l09040"></a><span class="lineno"> 9040</span>&#160;    VMA_ASSERT(allocType != VMA_SUBALLOCATION_TYPE_FREE);</div>
+<div class="line"><a name="l09041"></a><span class="lineno"> 9041</span>&#160;    VMA_ASSERT(suballocItem != m_Suballocations.cend());</div>
+<div class="line"><a name="l09042"></a><span class="lineno"> 9042</span>&#160;    VMA_ASSERT(pOffset != VMA_NULL);</div>
+<div class="line"><a name="l09043"></a><span class="lineno"> 9043</span>&#160;    </div>
+<div class="line"><a name="l09044"></a><span class="lineno"> 9044</span>&#160;    *itemsToMakeLostCount = 0;</div>
+<div class="line"><a name="l09045"></a><span class="lineno"> 9045</span>&#160;    *pSumFreeSize = 0;</div>
+<div class="line"><a name="l09046"></a><span class="lineno"> 9046</span>&#160;    *pSumItemSize = 0;</div>
+<div class="line"><a name="l09047"></a><span class="lineno"> 9047</span>&#160; </div>
+<div class="line"><a name="l09048"></a><span class="lineno"> 9048</span>&#160;    <span class="keywordflow">if</span>(canMakeOtherLost)</div>
+<div class="line"><a name="l09049"></a><span class="lineno"> 9049</span>&#160;    {</div>
+<div class="line"><a name="l09050"></a><span class="lineno"> 9050</span>&#160;        <span class="keywordflow">if</span>(suballocItem-&gt;type == VMA_SUBALLOCATION_TYPE_FREE)</div>
+<div class="line"><a name="l09051"></a><span class="lineno"> 9051</span>&#160;        {</div>
+<div class="line"><a name="l09052"></a><span class="lineno"> 9052</span>&#160;            *pSumFreeSize = suballocItem-&gt;size;</div>
+<div class="line"><a name="l09053"></a><span class="lineno"> 9053</span>&#160;        }</div>
+<div class="line"><a name="l09054"></a><span class="lineno"> 9054</span>&#160;        <span class="keywordflow">else</span></div>
+<div class="line"><a name="l09055"></a><span class="lineno"> 9055</span>&#160;        {</div>
+<div class="line"><a name="l09056"></a><span class="lineno"> 9056</span>&#160;            <span class="keywordflow">if</span>(suballocItem-&gt;hAllocation-&gt;CanBecomeLost() &amp;&amp;</div>
+<div class="line"><a name="l09057"></a><span class="lineno"> 9057</span>&#160;                suballocItem-&gt;hAllocation-&gt;GetLastUseFrameIndex() + frameInUseCount &lt; currentFrameIndex)</div>
+<div class="line"><a name="l09058"></a><span class="lineno"> 9058</span>&#160;            {</div>
+<div class="line"><a name="l09059"></a><span class="lineno"> 9059</span>&#160;                ++*itemsToMakeLostCount;</div>
+<div class="line"><a name="l09060"></a><span class="lineno"> 9060</span>&#160;                *pSumItemSize = suballocItem-&gt;size;</div>
+<div class="line"><a name="l09061"></a><span class="lineno"> 9061</span>&#160;            }</div>
+<div class="line"><a name="l09062"></a><span class="lineno"> 9062</span>&#160;            <span class="keywordflow">else</span></div>
+<div class="line"><a name="l09063"></a><span class="lineno"> 9063</span>&#160;            {</div>
+<div class="line"><a name="l09064"></a><span class="lineno"> 9064</span>&#160;                <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l09065"></a><span class="lineno"> 9065</span>&#160;            }</div>
+<div class="line"><a name="l09066"></a><span class="lineno"> 9066</span>&#160;        }</div>
+<div class="line"><a name="l09067"></a><span class="lineno"> 9067</span>&#160; </div>
+<div class="line"><a name="l09068"></a><span class="lineno"> 9068</span>&#160;        <span class="comment">// Remaining size is too small for this request: Early return.</span></div>
+<div class="line"><a name="l09069"></a><span class="lineno"> 9069</span>&#160;        <span class="keywordflow">if</span>(GetSize() - suballocItem-&gt;offset &lt; allocSize)</div>
+<div class="line"><a name="l09070"></a><span class="lineno"> 9070</span>&#160;        {</div>
+<div class="line"><a name="l09071"></a><span class="lineno"> 9071</span>&#160;            <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l09072"></a><span class="lineno"> 9072</span>&#160;        }</div>
+<div class="line"><a name="l09073"></a><span class="lineno"> 9073</span>&#160; </div>
+<div class="line"><a name="l09074"></a><span class="lineno"> 9074</span>&#160;        <span class="comment">// Start from offset equal to beginning of this suballocation.</span></div>
+<div class="line"><a name="l09075"></a><span class="lineno"> 9075</span>&#160;        *pOffset = suballocItem-&gt;offset;</div>
+<div class="line"><a name="l09076"></a><span class="lineno"> 9076</span>&#160;    </div>
+<div class="line"><a name="l09077"></a><span class="lineno"> 9077</span>&#160;        <span class="comment">// Apply VMA_DEBUG_MARGIN at the beginning.</span></div>
+<div class="line"><a name="l09078"></a><span class="lineno"> 9078</span>&#160;        <span class="keywordflow">if</span>(VMA_DEBUG_MARGIN &gt; 0)</div>
+<div class="line"><a name="l09079"></a><span class="lineno"> 9079</span>&#160;        {</div>
+<div class="line"><a name="l09080"></a><span class="lineno"> 9080</span>&#160;            *pOffset += VMA_DEBUG_MARGIN;</div>
+<div class="line"><a name="l09081"></a><span class="lineno"> 9081</span>&#160;        }</div>
+<div class="line"><a name="l09082"></a><span class="lineno"> 9082</span>&#160;    </div>
+<div class="line"><a name="l09083"></a><span class="lineno"> 9083</span>&#160;        <span class="comment">// Apply alignment.</span></div>
+<div class="line"><a name="l09084"></a><span class="lineno"> 9084</span>&#160;        *pOffset = VmaAlignUp(*pOffset, allocAlignment);</div>
+<div class="line"><a name="l09085"></a><span class="lineno"> 9085</span>&#160; </div>
+<div class="line"><a name="l09086"></a><span class="lineno"> 9086</span>&#160;        <span class="comment">// Check previous suballocations for BufferImageGranularity conflicts.</span></div>
+<div class="line"><a name="l09087"></a><span class="lineno"> 9087</span>&#160;        <span class="comment">// Make bigger alignment if necessary.</span></div>
+<div class="line"><a name="l09088"></a><span class="lineno"> 9088</span>&#160;        <span class="keywordflow">if</span>(bufferImageGranularity &gt; 1)</div>
+<div class="line"><a name="l09089"></a><span class="lineno"> 9089</span>&#160;        {</div>
+<div class="line"><a name="l09090"></a><span class="lineno"> 9090</span>&#160;            <span class="keywordtype">bool</span> bufferImageGranularityConflict = <span class="keyword">false</span>;</div>
+<div class="line"><a name="l09091"></a><span class="lineno"> 9091</span>&#160;            VmaSuballocationList::const_iterator prevSuballocItem = suballocItem;</div>
+<div class="line"><a name="l09092"></a><span class="lineno"> 9092</span>&#160;            <span class="keywordflow">while</span>(prevSuballocItem != m_Suballocations.cbegin())</div>
+<div class="line"><a name="l09093"></a><span class="lineno"> 9093</span>&#160;            {</div>
+<div class="line"><a name="l09094"></a><span class="lineno"> 9094</span>&#160;                --prevSuballocItem;</div>
+<div class="line"><a name="l09095"></a><span class="lineno"> 9095</span>&#160;                <span class="keyword">const</span> VmaSuballocation&amp; prevSuballoc = *prevSuballocItem;</div>
+<div class="line"><a name="l09096"></a><span class="lineno"> 9096</span>&#160;                <span class="keywordflow">if</span>(VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, *pOffset, bufferImageGranularity))</div>
+<div class="line"><a name="l09097"></a><span class="lineno"> 9097</span>&#160;                {</div>
+<div class="line"><a name="l09098"></a><span class="lineno"> 9098</span>&#160;                    <span class="keywordflow">if</span>(VmaIsBufferImageGranularityConflict(prevSuballoc.type, allocType))</div>
+<div class="line"><a name="l09099"></a><span class="lineno"> 9099</span>&#160;                    {</div>
+<div class="line"><a name="l09100"></a><span class="lineno"> 9100</span>&#160;                        bufferImageGranularityConflict = <span class="keyword">true</span>;</div>
+<div class="line"><a name="l09101"></a><span class="lineno"> 9101</span>&#160;                        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l09102"></a><span class="lineno"> 9102</span>&#160;                    }</div>
+<div class="line"><a name="l09103"></a><span class="lineno"> 9103</span>&#160;                }</div>
+<div class="line"><a name="l09104"></a><span class="lineno"> 9104</span>&#160;                <span class="keywordflow">else</span></div>
+<div class="line"><a name="l09105"></a><span class="lineno"> 9105</span>&#160;                    <span class="comment">// Already on previous page.</span></div>
+<div class="line"><a name="l09106"></a><span class="lineno"> 9106</span>&#160;                    <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l09107"></a><span class="lineno"> 9107</span>&#160;            }</div>
+<div class="line"><a name="l09108"></a><span class="lineno"> 9108</span>&#160;            <span class="keywordflow">if</span>(bufferImageGranularityConflict)</div>
+<div class="line"><a name="l09109"></a><span class="lineno"> 9109</span>&#160;            {</div>
+<div class="line"><a name="l09110"></a><span class="lineno"> 9110</span>&#160;                *pOffset = VmaAlignUp(*pOffset, bufferImageGranularity);</div>
+<div class="line"><a name="l09111"></a><span class="lineno"> 9111</span>&#160;            }</div>
+<div class="line"><a name="l09112"></a><span class="lineno"> 9112</span>&#160;        }</div>
+<div class="line"><a name="l09113"></a><span class="lineno"> 9113</span>&#160;    </div>
+<div class="line"><a name="l09114"></a><span class="lineno"> 9114</span>&#160;        <span class="comment">// Now that we have final *pOffset, check if we are past suballocItem.</span></div>
+<div class="line"><a name="l09115"></a><span class="lineno"> 9115</span>&#160;        <span class="comment">// If yes, return false - this function should be called for another suballocItem as starting point.</span></div>
+<div class="line"><a name="l09116"></a><span class="lineno"> 9116</span>&#160;        <span class="keywordflow">if</span>(*pOffset &gt;= suballocItem-&gt;offset + suballocItem-&gt;size)</div>
+<div class="line"><a name="l09117"></a><span class="lineno"> 9117</span>&#160;        {</div>
+<div class="line"><a name="l09118"></a><span class="lineno"> 9118</span>&#160;            <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l09119"></a><span class="lineno"> 9119</span>&#160;        }</div>
+<div class="line"><a name="l09120"></a><span class="lineno"> 9120</span>&#160;    </div>
+<div class="line"><a name="l09121"></a><span class="lineno"> 9121</span>&#160;        <span class="comment">// Calculate padding at the beginning based on current offset.</span></div>
+<div class="line"><a name="l09122"></a><span class="lineno"> 9122</span>&#160;        <span class="keyword">const</span> VkDeviceSize paddingBegin = *pOffset - suballocItem-&gt;offset;</div>
+<div class="line"><a name="l09123"></a><span class="lineno"> 9123</span>&#160; </div>
+<div class="line"><a name="l09124"></a><span class="lineno"> 9124</span>&#160;        <span class="comment">// Calculate required margin at the end.</span></div>
+<div class="line"><a name="l09125"></a><span class="lineno"> 9125</span>&#160;        <span class="keyword">const</span> VkDeviceSize requiredEndMargin = VMA_DEBUG_MARGIN;</div>
+<div class="line"><a name="l09126"></a><span class="lineno"> 9126</span>&#160; </div>
+<div class="line"><a name="l09127"></a><span class="lineno"> 9127</span>&#160;        <span class="keyword">const</span> VkDeviceSize totalSize = paddingBegin + allocSize + requiredEndMargin;</div>
+<div class="line"><a name="l09128"></a><span class="lineno"> 9128</span>&#160;        <span class="comment">// Another early return check.</span></div>
+<div class="line"><a name="l09129"></a><span class="lineno"> 9129</span>&#160;        <span class="keywordflow">if</span>(suballocItem-&gt;offset + totalSize &gt; GetSize())</div>
+<div class="line"><a name="l09130"></a><span class="lineno"> 9130</span>&#160;        {</div>
+<div class="line"><a name="l09131"></a><span class="lineno"> 9131</span>&#160;            <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l09132"></a><span class="lineno"> 9132</span>&#160;        }</div>
+<div class="line"><a name="l09133"></a><span class="lineno"> 9133</span>&#160; </div>
+<div class="line"><a name="l09134"></a><span class="lineno"> 9134</span>&#160;        <span class="comment">// Advance lastSuballocItem until desired size is reached.</span></div>
+<div class="line"><a name="l09135"></a><span class="lineno"> 9135</span>&#160;        <span class="comment">// Update itemsToMakeLostCount.</span></div>
+<div class="line"><a name="l09136"></a><span class="lineno"> 9136</span>&#160;        VmaSuballocationList::const_iterator lastSuballocItem = suballocItem;</div>
+<div class="line"><a name="l09137"></a><span class="lineno"> 9137</span>&#160;        <span class="keywordflow">if</span>(totalSize &gt; suballocItem-&gt;size)</div>
+<div class="line"><a name="l09138"></a><span class="lineno"> 9138</span>&#160;        {</div>
+<div class="line"><a name="l09139"></a><span class="lineno"> 9139</span>&#160;            VkDeviceSize remainingSize = totalSize - suballocItem-&gt;size;</div>
+<div class="line"><a name="l09140"></a><span class="lineno"> 9140</span>&#160;            <span class="keywordflow">while</span>(remainingSize &gt; 0)</div>
+<div class="line"><a name="l09141"></a><span class="lineno"> 9141</span>&#160;            {</div>
+<div class="line"><a name="l09142"></a><span class="lineno"> 9142</span>&#160;                ++lastSuballocItem;</div>
+<div class="line"><a name="l09143"></a><span class="lineno"> 9143</span>&#160;                <span class="keywordflow">if</span>(lastSuballocItem == m_Suballocations.cend())</div>
+<div class="line"><a name="l09144"></a><span class="lineno"> 9144</span>&#160;                {</div>
+<div class="line"><a name="l09145"></a><span class="lineno"> 9145</span>&#160;                    <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l09146"></a><span class="lineno"> 9146</span>&#160;                }</div>
+<div class="line"><a name="l09147"></a><span class="lineno"> 9147</span>&#160;                <span class="keywordflow">if</span>(lastSuballocItem-&gt;type == VMA_SUBALLOCATION_TYPE_FREE)</div>
+<div class="line"><a name="l09148"></a><span class="lineno"> 9148</span>&#160;                {</div>
+<div class="line"><a name="l09149"></a><span class="lineno"> 9149</span>&#160;                    *pSumFreeSize += lastSuballocItem-&gt;size;</div>
+<div class="line"><a name="l09150"></a><span class="lineno"> 9150</span>&#160;                }</div>
+<div class="line"><a name="l09151"></a><span class="lineno"> 9151</span>&#160;                <span class="keywordflow">else</span></div>
+<div class="line"><a name="l09152"></a><span class="lineno"> 9152</span>&#160;                {</div>
+<div class="line"><a name="l09153"></a><span class="lineno"> 9153</span>&#160;                    VMA_ASSERT(lastSuballocItem-&gt;hAllocation != VK_NULL_HANDLE);</div>
+<div class="line"><a name="l09154"></a><span class="lineno"> 9154</span>&#160;                    <span class="keywordflow">if</span>(lastSuballocItem-&gt;hAllocation-&gt;CanBecomeLost() &amp;&amp;</div>
+<div class="line"><a name="l09155"></a><span class="lineno"> 9155</span>&#160;                        lastSuballocItem-&gt;hAllocation-&gt;GetLastUseFrameIndex() + frameInUseCount &lt; currentFrameIndex)</div>
+<div class="line"><a name="l09156"></a><span class="lineno"> 9156</span>&#160;                    {</div>
+<div class="line"><a name="l09157"></a><span class="lineno"> 9157</span>&#160;                        ++*itemsToMakeLostCount;</div>
+<div class="line"><a name="l09158"></a><span class="lineno"> 9158</span>&#160;                        *pSumItemSize += lastSuballocItem-&gt;size;</div>
+<div class="line"><a name="l09159"></a><span class="lineno"> 9159</span>&#160;                    }</div>
+<div class="line"><a name="l09160"></a><span class="lineno"> 9160</span>&#160;                    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l09161"></a><span class="lineno"> 9161</span>&#160;                    {</div>
+<div class="line"><a name="l09162"></a><span class="lineno"> 9162</span>&#160;                        <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l09163"></a><span class="lineno"> 9163</span>&#160;                    }</div>
+<div class="line"><a name="l09164"></a><span class="lineno"> 9164</span>&#160;                }</div>
+<div class="line"><a name="l09165"></a><span class="lineno"> 9165</span>&#160;                remainingSize = (lastSuballocItem-&gt;size &lt; remainingSize) ?</div>
+<div class="line"><a name="l09166"></a><span class="lineno"> 9166</span>&#160;                    remainingSize - lastSuballocItem-&gt;size : 0;</div>
+<div class="line"><a name="l09167"></a><span class="lineno"> 9167</span>&#160;            }</div>
+<div class="line"><a name="l09168"></a><span class="lineno"> 9168</span>&#160;        }</div>
+<div class="line"><a name="l09169"></a><span class="lineno"> 9169</span>&#160; </div>
+<div class="line"><a name="l09170"></a><span class="lineno"> 9170</span>&#160;        <span class="comment">// Check next suballocations for BufferImageGranularity conflicts.</span></div>
+<div class="line"><a name="l09171"></a><span class="lineno"> 9171</span>&#160;        <span class="comment">// If conflict exists, we must mark more allocations lost or fail.</span></div>
+<div class="line"><a name="l09172"></a><span class="lineno"> 9172</span>&#160;        <span class="keywordflow">if</span>(bufferImageGranularity &gt; 1)</div>
+<div class="line"><a name="l09173"></a><span class="lineno"> 9173</span>&#160;        {</div>
+<div class="line"><a name="l09174"></a><span class="lineno"> 9174</span>&#160;            VmaSuballocationList::const_iterator nextSuballocItem = lastSuballocItem;</div>
+<div class="line"><a name="l09175"></a><span class="lineno"> 9175</span>&#160;            ++nextSuballocItem;</div>
+<div class="line"><a name="l09176"></a><span class="lineno"> 9176</span>&#160;            <span class="keywordflow">while</span>(nextSuballocItem != m_Suballocations.cend())</div>
+<div class="line"><a name="l09177"></a><span class="lineno"> 9177</span>&#160;            {</div>
+<div class="line"><a name="l09178"></a><span class="lineno"> 9178</span>&#160;                <span class="keyword">const</span> VmaSuballocation&amp; nextSuballoc = *nextSuballocItem;</div>
+<div class="line"><a name="l09179"></a><span class="lineno"> 9179</span>&#160;                <span class="keywordflow">if</span>(VmaBlocksOnSamePage(*pOffset, allocSize, nextSuballoc.offset, bufferImageGranularity))</div>
+<div class="line"><a name="l09180"></a><span class="lineno"> 9180</span>&#160;                {</div>
+<div class="line"><a name="l09181"></a><span class="lineno"> 9181</span>&#160;                    <span class="keywordflow">if</span>(VmaIsBufferImageGranularityConflict(allocType, nextSuballoc.type))</div>
+<div class="line"><a name="l09182"></a><span class="lineno"> 9182</span>&#160;                    {</div>
+<div class="line"><a name="l09183"></a><span class="lineno"> 9183</span>&#160;                        VMA_ASSERT(nextSuballoc.hAllocation != VK_NULL_HANDLE);</div>
+<div class="line"><a name="l09184"></a><span class="lineno"> 9184</span>&#160;                        <span class="keywordflow">if</span>(nextSuballoc.hAllocation-&gt;CanBecomeLost() &amp;&amp;</div>
+<div class="line"><a name="l09185"></a><span class="lineno"> 9185</span>&#160;                            nextSuballoc.hAllocation-&gt;GetLastUseFrameIndex() + frameInUseCount &lt; currentFrameIndex)</div>
+<div class="line"><a name="l09186"></a><span class="lineno"> 9186</span>&#160;                        {</div>
+<div class="line"><a name="l09187"></a><span class="lineno"> 9187</span>&#160;                            ++*itemsToMakeLostCount;</div>
+<div class="line"><a name="l09188"></a><span class="lineno"> 9188</span>&#160;                        }</div>
+<div class="line"><a name="l09189"></a><span class="lineno"> 9189</span>&#160;                        <span class="keywordflow">else</span></div>
+<div class="line"><a name="l09190"></a><span class="lineno"> 9190</span>&#160;                        {</div>
+<div class="line"><a name="l09191"></a><span class="lineno"> 9191</span>&#160;                            <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l09192"></a><span class="lineno"> 9192</span>&#160;                        }</div>
+<div class="line"><a name="l09193"></a><span class="lineno"> 9193</span>&#160;                    }</div>
+<div class="line"><a name="l09194"></a><span class="lineno"> 9194</span>&#160;                }</div>
+<div class="line"><a name="l09195"></a><span class="lineno"> 9195</span>&#160;                <span class="keywordflow">else</span></div>
+<div class="line"><a name="l09196"></a><span class="lineno"> 9196</span>&#160;                {</div>
+<div class="line"><a name="l09197"></a><span class="lineno"> 9197</span>&#160;                    <span class="comment">// Already on next page.</span></div>
+<div class="line"><a name="l09198"></a><span class="lineno"> 9198</span>&#160;                    <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l09199"></a><span class="lineno"> 9199</span>&#160;                }</div>
+<div class="line"><a name="l09200"></a><span class="lineno"> 9200</span>&#160;                ++nextSuballocItem;</div>
+<div class="line"><a name="l09201"></a><span class="lineno"> 9201</span>&#160;            }</div>
+<div class="line"><a name="l09202"></a><span class="lineno"> 9202</span>&#160;        }</div>
+<div class="line"><a name="l09203"></a><span class="lineno"> 9203</span>&#160;    }</div>
+<div class="line"><a name="l09204"></a><span class="lineno"> 9204</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l09205"></a><span class="lineno"> 9205</span>&#160;    {</div>
+<div class="line"><a name="l09206"></a><span class="lineno"> 9206</span>&#160;        <span class="keyword">const</span> VmaSuballocation&amp; suballoc = *suballocItem;</div>
+<div class="line"><a name="l09207"></a><span class="lineno"> 9207</span>&#160;        VMA_ASSERT(suballoc.type == VMA_SUBALLOCATION_TYPE_FREE);</div>
+<div class="line"><a name="l09208"></a><span class="lineno"> 9208</span>&#160; </div>
+<div class="line"><a name="l09209"></a><span class="lineno"> 9209</span>&#160;        *pSumFreeSize = suballoc.size;</div>
+<div class="line"><a name="l09210"></a><span class="lineno"> 9210</span>&#160; </div>
+<div class="line"><a name="l09211"></a><span class="lineno"> 9211</span>&#160;        <span class="comment">// Size of this suballocation is too small for this request: Early return.</span></div>
+<div class="line"><a name="l09212"></a><span class="lineno"> 9212</span>&#160;        <span class="keywordflow">if</span>(suballoc.size &lt; allocSize)</div>
+<div class="line"><a name="l09213"></a><span class="lineno"> 9213</span>&#160;        {</div>
+<div class="line"><a name="l09214"></a><span class="lineno"> 9214</span>&#160;            <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l09215"></a><span class="lineno"> 9215</span>&#160;        }</div>
+<div class="line"><a name="l09216"></a><span class="lineno"> 9216</span>&#160; </div>
+<div class="line"><a name="l09217"></a><span class="lineno"> 9217</span>&#160;        <span class="comment">// Start from offset equal to beginning of this suballocation.</span></div>
+<div class="line"><a name="l09218"></a><span class="lineno"> 9218</span>&#160;        *pOffset = suballoc.offset;</div>
+<div class="line"><a name="l09219"></a><span class="lineno"> 9219</span>&#160;    </div>
+<div class="line"><a name="l09220"></a><span class="lineno"> 9220</span>&#160;        <span class="comment">// Apply VMA_DEBUG_MARGIN at the beginning.</span></div>
+<div class="line"><a name="l09221"></a><span class="lineno"> 9221</span>&#160;        <span class="keywordflow">if</span>(VMA_DEBUG_MARGIN &gt; 0)</div>
+<div class="line"><a name="l09222"></a><span class="lineno"> 9222</span>&#160;        {</div>
+<div class="line"><a name="l09223"></a><span class="lineno"> 9223</span>&#160;            *pOffset += VMA_DEBUG_MARGIN;</div>
+<div class="line"><a name="l09224"></a><span class="lineno"> 9224</span>&#160;        }</div>
+<div class="line"><a name="l09225"></a><span class="lineno"> 9225</span>&#160;    </div>
+<div class="line"><a name="l09226"></a><span class="lineno"> 9226</span>&#160;        <span class="comment">// Apply alignment.</span></div>
+<div class="line"><a name="l09227"></a><span class="lineno"> 9227</span>&#160;        *pOffset = VmaAlignUp(*pOffset, allocAlignment);</div>
+<div class="line"><a name="l09228"></a><span class="lineno"> 9228</span>&#160;    </div>
+<div class="line"><a name="l09229"></a><span class="lineno"> 9229</span>&#160;        <span class="comment">// Check previous suballocations for BufferImageGranularity conflicts.</span></div>
+<div class="line"><a name="l09230"></a><span class="lineno"> 9230</span>&#160;        <span class="comment">// Make bigger alignment if necessary.</span></div>
+<div class="line"><a name="l09231"></a><span class="lineno"> 9231</span>&#160;        <span class="keywordflow">if</span>(bufferImageGranularity &gt; 1)</div>
+<div class="line"><a name="l09232"></a><span class="lineno"> 9232</span>&#160;        {</div>
+<div class="line"><a name="l09233"></a><span class="lineno"> 9233</span>&#160;            <span class="keywordtype">bool</span> bufferImageGranularityConflict = <span class="keyword">false</span>;</div>
+<div class="line"><a name="l09234"></a><span class="lineno"> 9234</span>&#160;            VmaSuballocationList::const_iterator prevSuballocItem = suballocItem;</div>
+<div class="line"><a name="l09235"></a><span class="lineno"> 9235</span>&#160;            <span class="keywordflow">while</span>(prevSuballocItem != m_Suballocations.cbegin())</div>
+<div class="line"><a name="l09236"></a><span class="lineno"> 9236</span>&#160;            {</div>
+<div class="line"><a name="l09237"></a><span class="lineno"> 9237</span>&#160;                --prevSuballocItem;</div>
+<div class="line"><a name="l09238"></a><span class="lineno"> 9238</span>&#160;                <span class="keyword">const</span> VmaSuballocation&amp; prevSuballoc = *prevSuballocItem;</div>
+<div class="line"><a name="l09239"></a><span class="lineno"> 9239</span>&#160;                <span class="keywordflow">if</span>(VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, *pOffset, bufferImageGranularity))</div>
+<div class="line"><a name="l09240"></a><span class="lineno"> 9240</span>&#160;                {</div>
+<div class="line"><a name="l09241"></a><span class="lineno"> 9241</span>&#160;                    <span class="keywordflow">if</span>(VmaIsBufferImageGranularityConflict(prevSuballoc.type, allocType))</div>
+<div class="line"><a name="l09242"></a><span class="lineno"> 9242</span>&#160;                    {</div>
+<div class="line"><a name="l09243"></a><span class="lineno"> 9243</span>&#160;                        bufferImageGranularityConflict = <span class="keyword">true</span>;</div>
+<div class="line"><a name="l09244"></a><span class="lineno"> 9244</span>&#160;                        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l09245"></a><span class="lineno"> 9245</span>&#160;                    }</div>
+<div class="line"><a name="l09246"></a><span class="lineno"> 9246</span>&#160;                }</div>
+<div class="line"><a name="l09247"></a><span class="lineno"> 9247</span>&#160;                <span class="keywordflow">else</span></div>
+<div class="line"><a name="l09248"></a><span class="lineno"> 9248</span>&#160;                    <span class="comment">// Already on previous page.</span></div>
+<div class="line"><a name="l09249"></a><span class="lineno"> 9249</span>&#160;                    <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l09250"></a><span class="lineno"> 9250</span>&#160;            }</div>
+<div class="line"><a name="l09251"></a><span class="lineno"> 9251</span>&#160;            <span class="keywordflow">if</span>(bufferImageGranularityConflict)</div>
+<div class="line"><a name="l09252"></a><span class="lineno"> 9252</span>&#160;            {</div>
+<div class="line"><a name="l09253"></a><span class="lineno"> 9253</span>&#160;                *pOffset = VmaAlignUp(*pOffset, bufferImageGranularity);</div>
+<div class="line"><a name="l09254"></a><span class="lineno"> 9254</span>&#160;            }</div>
+<div class="line"><a name="l09255"></a><span class="lineno"> 9255</span>&#160;        }</div>
+<div class="line"><a name="l09256"></a><span class="lineno"> 9256</span>&#160;    </div>
+<div class="line"><a name="l09257"></a><span class="lineno"> 9257</span>&#160;        <span class="comment">// Calculate padding at the beginning based on current offset.</span></div>
+<div class="line"><a name="l09258"></a><span class="lineno"> 9258</span>&#160;        <span class="keyword">const</span> VkDeviceSize paddingBegin = *pOffset - suballoc.offset;</div>
+<div class="line"><a name="l09259"></a><span class="lineno"> 9259</span>&#160; </div>
+<div class="line"><a name="l09260"></a><span class="lineno"> 9260</span>&#160;        <span class="comment">// Calculate required margin at the end.</span></div>
+<div class="line"><a name="l09261"></a><span class="lineno"> 9261</span>&#160;        <span class="keyword">const</span> VkDeviceSize requiredEndMargin = VMA_DEBUG_MARGIN;</div>
+<div class="line"><a name="l09262"></a><span class="lineno"> 9262</span>&#160; </div>
+<div class="line"><a name="l09263"></a><span class="lineno"> 9263</span>&#160;        <span class="comment">// Fail if requested size plus margin before and after is bigger than size of this suballocation.</span></div>
+<div class="line"><a name="l09264"></a><span class="lineno"> 9264</span>&#160;        <span class="keywordflow">if</span>(paddingBegin + allocSize + requiredEndMargin &gt; suballoc.size)</div>
+<div class="line"><a name="l09265"></a><span class="lineno"> 9265</span>&#160;        {</div>
+<div class="line"><a name="l09266"></a><span class="lineno"> 9266</span>&#160;            <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l09267"></a><span class="lineno"> 9267</span>&#160;        }</div>
+<div class="line"><a name="l09268"></a><span class="lineno"> 9268</span>&#160; </div>
+<div class="line"><a name="l09269"></a><span class="lineno"> 9269</span>&#160;        <span class="comment">// Check next suballocations for BufferImageGranularity conflicts.</span></div>
+<div class="line"><a name="l09270"></a><span class="lineno"> 9270</span>&#160;        <span class="comment">// If conflict exists, allocation cannot be made here.</span></div>
+<div class="line"><a name="l09271"></a><span class="lineno"> 9271</span>&#160;        <span class="keywordflow">if</span>(bufferImageGranularity &gt; 1)</div>
+<div class="line"><a name="l09272"></a><span class="lineno"> 9272</span>&#160;        {</div>
+<div class="line"><a name="l09273"></a><span class="lineno"> 9273</span>&#160;            VmaSuballocationList::const_iterator nextSuballocItem = suballocItem;</div>
+<div class="line"><a name="l09274"></a><span class="lineno"> 9274</span>&#160;            ++nextSuballocItem;</div>
+<div class="line"><a name="l09275"></a><span class="lineno"> 9275</span>&#160;            <span class="keywordflow">while</span>(nextSuballocItem != m_Suballocations.cend())</div>
+<div class="line"><a name="l09276"></a><span class="lineno"> 9276</span>&#160;            {</div>
+<div class="line"><a name="l09277"></a><span class="lineno"> 9277</span>&#160;                <span class="keyword">const</span> VmaSuballocation&amp; nextSuballoc = *nextSuballocItem;</div>
+<div class="line"><a name="l09278"></a><span class="lineno"> 9278</span>&#160;                <span class="keywordflow">if</span>(VmaBlocksOnSamePage(*pOffset, allocSize, nextSuballoc.offset, bufferImageGranularity))</div>
+<div class="line"><a name="l09279"></a><span class="lineno"> 9279</span>&#160;                {</div>
+<div class="line"><a name="l09280"></a><span class="lineno"> 9280</span>&#160;                    <span class="keywordflow">if</span>(VmaIsBufferImageGranularityConflict(allocType, nextSuballoc.type))</div>
+<div class="line"><a name="l09281"></a><span class="lineno"> 9281</span>&#160;                    {</div>
+<div class="line"><a name="l09282"></a><span class="lineno"> 9282</span>&#160;                        <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l09283"></a><span class="lineno"> 9283</span>&#160;                    }</div>
+<div class="line"><a name="l09284"></a><span class="lineno"> 9284</span>&#160;                }</div>
+<div class="line"><a name="l09285"></a><span class="lineno"> 9285</span>&#160;                <span class="keywordflow">else</span></div>
+<div class="line"><a name="l09286"></a><span class="lineno"> 9286</span>&#160;                {</div>
+<div class="line"><a name="l09287"></a><span class="lineno"> 9287</span>&#160;                    <span class="comment">// Already on next page.</span></div>
+<div class="line"><a name="l09288"></a><span class="lineno"> 9288</span>&#160;                    <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l09289"></a><span class="lineno"> 9289</span>&#160;                }</div>
+<div class="line"><a name="l09290"></a><span class="lineno"> 9290</span>&#160;                ++nextSuballocItem;</div>
+<div class="line"><a name="l09291"></a><span class="lineno"> 9291</span>&#160;            }</div>
+<div class="line"><a name="l09292"></a><span class="lineno"> 9292</span>&#160;        }</div>
+<div class="line"><a name="l09293"></a><span class="lineno"> 9293</span>&#160;    }</div>
+<div class="line"><a name="l09294"></a><span class="lineno"> 9294</span>&#160; </div>
+<div class="line"><a name="l09295"></a><span class="lineno"> 9295</span>&#160;    <span class="comment">// All tests passed: Success. pOffset is already filled.</span></div>
+<div class="line"><a name="l09296"></a><span class="lineno"> 9296</span>&#160;    <span class="keywordflow">return</span> <span class="keyword">true</span>;</div>
+<div class="line"><a name="l09297"></a><span class="lineno"> 9297</span>&#160;}</div>
+<div class="line"><a name="l09298"></a><span class="lineno"> 9298</span>&#160; </div>
+<div class="line"><a name="l09299"></a><span class="lineno"> 9299</span>&#160;<span class="keywordtype">void</span> VmaBlockMetadata_Generic::MergeFreeWithNext(VmaSuballocationList::iterator item)</div>
+<div class="line"><a name="l09300"></a><span class="lineno"> 9300</span>&#160;{</div>
+<div class="line"><a name="l09301"></a><span class="lineno"> 9301</span>&#160;    VMA_ASSERT(item != m_Suballocations.end());</div>
+<div class="line"><a name="l09302"></a><span class="lineno"> 9302</span>&#160;    VMA_ASSERT(item-&gt;type == VMA_SUBALLOCATION_TYPE_FREE);</div>
+<div class="line"><a name="l09303"></a><span class="lineno"> 9303</span>&#160;    </div>
+<div class="line"><a name="l09304"></a><span class="lineno"> 9304</span>&#160;    VmaSuballocationList::iterator nextItem = item;</div>
+<div class="line"><a name="l09305"></a><span class="lineno"> 9305</span>&#160;    ++nextItem;</div>
+<div class="line"><a name="l09306"></a><span class="lineno"> 9306</span>&#160;    VMA_ASSERT(nextItem != m_Suballocations.end());</div>
+<div class="line"><a name="l09307"></a><span class="lineno"> 9307</span>&#160;    VMA_ASSERT(nextItem-&gt;type == VMA_SUBALLOCATION_TYPE_FREE);</div>
+<div class="line"><a name="l09308"></a><span class="lineno"> 9308</span>&#160; </div>
+<div class="line"><a name="l09309"></a><span class="lineno"> 9309</span>&#160;    item-&gt;size += nextItem-&gt;size;</div>
+<div class="line"><a name="l09310"></a><span class="lineno"> 9310</span>&#160;    --m_FreeCount;</div>
+<div class="line"><a name="l09311"></a><span class="lineno"> 9311</span>&#160;    m_Suballocations.erase(nextItem);</div>
+<div class="line"><a name="l09312"></a><span class="lineno"> 9312</span>&#160;}</div>
+<div class="line"><a name="l09313"></a><span class="lineno"> 9313</span>&#160; </div>
+<div class="line"><a name="l09314"></a><span class="lineno"> 9314</span>&#160;VmaSuballocationList::iterator VmaBlockMetadata_Generic::FreeSuballocation(VmaSuballocationList::iterator suballocItem)</div>
+<div class="line"><a name="l09315"></a><span class="lineno"> 9315</span>&#160;{</div>
+<div class="line"><a name="l09316"></a><span class="lineno"> 9316</span>&#160;    <span class="comment">// Change this suballocation to be marked as free.</span></div>
+<div class="line"><a name="l09317"></a><span class="lineno"> 9317</span>&#160;    VmaSuballocation&amp; suballoc = *suballocItem;</div>
+<div class="line"><a name="l09318"></a><span class="lineno"> 9318</span>&#160;    suballoc.type = VMA_SUBALLOCATION_TYPE_FREE;</div>
+<div class="line"><a name="l09319"></a><span class="lineno"> 9319</span>&#160;    suballoc.hAllocation = VK_NULL_HANDLE;</div>
+<div class="line"><a name="l09320"></a><span class="lineno"> 9320</span>&#160;    </div>
+<div class="line"><a name="l09321"></a><span class="lineno"> 9321</span>&#160;    <span class="comment">// Update totals.</span></div>
+<div class="line"><a name="l09322"></a><span class="lineno"> 9322</span>&#160;    ++m_FreeCount;</div>
+<div class="line"><a name="l09323"></a><span class="lineno"> 9323</span>&#160;    m_SumFreeSize += suballoc.size;</div>
+<div class="line"><a name="l09324"></a><span class="lineno"> 9324</span>&#160; </div>
+<div class="line"><a name="l09325"></a><span class="lineno"> 9325</span>&#160;    <span class="comment">// Merge with previous and/or next suballocation if it&#39;s also free.</span></div>
+<div class="line"><a name="l09326"></a><span class="lineno"> 9326</span>&#160;    <span class="keywordtype">bool</span> mergeWithNext = <span class="keyword">false</span>;</div>
+<div class="line"><a name="l09327"></a><span class="lineno"> 9327</span>&#160;    <span class="keywordtype">bool</span> mergeWithPrev = <span class="keyword">false</span>;</div>
+<div class="line"><a name="l09328"></a><span class="lineno"> 9328</span>&#160;    </div>
+<div class="line"><a name="l09329"></a><span class="lineno"> 9329</span>&#160;    VmaSuballocationList::iterator nextItem = suballocItem;</div>
+<div class="line"><a name="l09330"></a><span class="lineno"> 9330</span>&#160;    ++nextItem;</div>
+<div class="line"><a name="l09331"></a><span class="lineno"> 9331</span>&#160;    <span class="keywordflow">if</span>((nextItem != m_Suballocations.end()) &amp;&amp; (nextItem-&gt;type == VMA_SUBALLOCATION_TYPE_FREE))</div>
+<div class="line"><a name="l09332"></a><span class="lineno"> 9332</span>&#160;    {</div>
+<div class="line"><a name="l09333"></a><span class="lineno"> 9333</span>&#160;        mergeWithNext = <span class="keyword">true</span>;</div>
+<div class="line"><a name="l09334"></a><span class="lineno"> 9334</span>&#160;    }</div>
+<div class="line"><a name="l09335"></a><span class="lineno"> 9335</span>&#160; </div>
+<div class="line"><a name="l09336"></a><span class="lineno"> 9336</span>&#160;    VmaSuballocationList::iterator prevItem = suballocItem;</div>
+<div class="line"><a name="l09337"></a><span class="lineno"> 9337</span>&#160;    <span class="keywordflow">if</span>(suballocItem != m_Suballocations.begin())</div>
+<div class="line"><a name="l09338"></a><span class="lineno"> 9338</span>&#160;    {</div>
+<div class="line"><a name="l09339"></a><span class="lineno"> 9339</span>&#160;        --prevItem;</div>
+<div class="line"><a name="l09340"></a><span class="lineno"> 9340</span>&#160;        <span class="keywordflow">if</span>(prevItem-&gt;type == VMA_SUBALLOCATION_TYPE_FREE)</div>
+<div class="line"><a name="l09341"></a><span class="lineno"> 9341</span>&#160;        {</div>
+<div class="line"><a name="l09342"></a><span class="lineno"> 9342</span>&#160;            mergeWithPrev = <span class="keyword">true</span>;</div>
+<div class="line"><a name="l09343"></a><span class="lineno"> 9343</span>&#160;        }</div>
+<div class="line"><a name="l09344"></a><span class="lineno"> 9344</span>&#160;    }</div>
+<div class="line"><a name="l09345"></a><span class="lineno"> 9345</span>&#160; </div>
+<div class="line"><a name="l09346"></a><span class="lineno"> 9346</span>&#160;    <span class="keywordflow">if</span>(mergeWithNext)</div>
+<div class="line"><a name="l09347"></a><span class="lineno"> 9347</span>&#160;    {</div>
+<div class="line"><a name="l09348"></a><span class="lineno"> 9348</span>&#160;        UnregisterFreeSuballocation(nextItem);</div>
+<div class="line"><a name="l09349"></a><span class="lineno"> 9349</span>&#160;        MergeFreeWithNext(suballocItem);</div>
+<div class="line"><a name="l09350"></a><span class="lineno"> 9350</span>&#160;    }</div>
+<div class="line"><a name="l09351"></a><span class="lineno"> 9351</span>&#160; </div>
+<div class="line"><a name="l09352"></a><span class="lineno"> 9352</span>&#160;    <span class="keywordflow">if</span>(mergeWithPrev)</div>
+<div class="line"><a name="l09353"></a><span class="lineno"> 9353</span>&#160;    {</div>
+<div class="line"><a name="l09354"></a><span class="lineno"> 9354</span>&#160;        UnregisterFreeSuballocation(prevItem);</div>
+<div class="line"><a name="l09355"></a><span class="lineno"> 9355</span>&#160;        MergeFreeWithNext(prevItem);</div>
+<div class="line"><a name="l09356"></a><span class="lineno"> 9356</span>&#160;        RegisterFreeSuballocation(prevItem);</div>
+<div class="line"><a name="l09357"></a><span class="lineno"> 9357</span>&#160;        <span class="keywordflow">return</span> prevItem;</div>
+<div class="line"><a name="l09358"></a><span class="lineno"> 9358</span>&#160;    }</div>
+<div class="line"><a name="l09359"></a><span class="lineno"> 9359</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l09360"></a><span class="lineno"> 9360</span>&#160;    {</div>
+<div class="line"><a name="l09361"></a><span class="lineno"> 9361</span>&#160;        RegisterFreeSuballocation(suballocItem);</div>
+<div class="line"><a name="l09362"></a><span class="lineno"> 9362</span>&#160;        <span class="keywordflow">return</span> suballocItem;</div>
+<div class="line"><a name="l09363"></a><span class="lineno"> 9363</span>&#160;    }</div>
+<div class="line"><a name="l09364"></a><span class="lineno"> 9364</span>&#160;}</div>
+<div class="line"><a name="l09365"></a><span class="lineno"> 9365</span>&#160; </div>
+<div class="line"><a name="l09366"></a><span class="lineno"> 9366</span>&#160;<span class="keywordtype">void</span> VmaBlockMetadata_Generic::RegisterFreeSuballocation(VmaSuballocationList::iterator item)</div>
+<div class="line"><a name="l09367"></a><span class="lineno"> 9367</span>&#160;{</div>
+<div class="line"><a name="l09368"></a><span class="lineno"> 9368</span>&#160;    VMA_ASSERT(item-&gt;type == VMA_SUBALLOCATION_TYPE_FREE);</div>
+<div class="line"><a name="l09369"></a><span class="lineno"> 9369</span>&#160;    VMA_ASSERT(item-&gt;size &gt; 0);</div>
+<div class="line"><a name="l09370"></a><span class="lineno"> 9370</span>&#160; </div>
+<div class="line"><a name="l09371"></a><span class="lineno"> 9371</span>&#160;    <span class="comment">// You may want to enable this validation at the beginning or at the end of</span></div>
+<div class="line"><a name="l09372"></a><span class="lineno"> 9372</span>&#160;    <span class="comment">// this function, depending on what do you want to check.</span></div>
+<div class="line"><a name="l09373"></a><span class="lineno"> 9373</span>&#160;    VMA_HEAVY_ASSERT(ValidateFreeSuballocationList());</div>
+<div class="line"><a name="l09374"></a><span class="lineno"> 9374</span>&#160; </div>
+<div class="line"><a name="l09375"></a><span class="lineno"> 9375</span>&#160;    <span class="keywordflow">if</span>(item-&gt;size &gt;= VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER)</div>
+<div class="line"><a name="l09376"></a><span class="lineno"> 9376</span>&#160;    {</div>
+<div class="line"><a name="l09377"></a><span class="lineno"> 9377</span>&#160;        <span class="keywordflow">if</span>(m_FreeSuballocationsBySize.empty())</div>
+<div class="line"><a name="l09378"></a><span class="lineno"> 9378</span>&#160;        {</div>
+<div class="line"><a name="l09379"></a><span class="lineno"> 9379</span>&#160;            m_FreeSuballocationsBySize.push_back(item);</div>
+<div class="line"><a name="l09380"></a><span class="lineno"> 9380</span>&#160;        }</div>
+<div class="line"><a name="l09381"></a><span class="lineno"> 9381</span>&#160;        <span class="keywordflow">else</span></div>
+<div class="line"><a name="l09382"></a><span class="lineno"> 9382</span>&#160;        {</div>
+<div class="line"><a name="l09383"></a><span class="lineno"> 9383</span>&#160;            VmaVectorInsertSorted&lt;VmaSuballocationItemSizeLess&gt;(m_FreeSuballocationsBySize, item);</div>
+<div class="line"><a name="l09384"></a><span class="lineno"> 9384</span>&#160;        }</div>
+<div class="line"><a name="l09385"></a><span class="lineno"> 9385</span>&#160;    }</div>
+<div class="line"><a name="l09386"></a><span class="lineno"> 9386</span>&#160; </div>
+<div class="line"><a name="l09387"></a><span class="lineno"> 9387</span>&#160;    <span class="comment">//VMA_HEAVY_ASSERT(ValidateFreeSuballocationList());</span></div>
+<div class="line"><a name="l09388"></a><span class="lineno"> 9388</span>&#160;}</div>
+<div class="line"><a name="l09389"></a><span class="lineno"> 9389</span>&#160; </div>
+<div class="line"><a name="l09390"></a><span class="lineno"> 9390</span>&#160; </div>
+<div class="line"><a name="l09391"></a><span class="lineno"> 9391</span>&#160;<span class="keywordtype">void</span> VmaBlockMetadata_Generic::UnregisterFreeSuballocation(VmaSuballocationList::iterator item)</div>
+<div class="line"><a name="l09392"></a><span class="lineno"> 9392</span>&#160;{</div>
+<div class="line"><a name="l09393"></a><span class="lineno"> 9393</span>&#160;    VMA_ASSERT(item-&gt;type == VMA_SUBALLOCATION_TYPE_FREE);</div>
+<div class="line"><a name="l09394"></a><span class="lineno"> 9394</span>&#160;    VMA_ASSERT(item-&gt;size &gt; 0);</div>
+<div class="line"><a name="l09395"></a><span class="lineno"> 9395</span>&#160; </div>
+<div class="line"><a name="l09396"></a><span class="lineno"> 9396</span>&#160;    <span class="comment">// You may want to enable this validation at the beginning or at the end of</span></div>
+<div class="line"><a name="l09397"></a><span class="lineno"> 9397</span>&#160;    <span class="comment">// this function, depending on what do you want to check.</span></div>
+<div class="line"><a name="l09398"></a><span class="lineno"> 9398</span>&#160;    VMA_HEAVY_ASSERT(ValidateFreeSuballocationList());</div>
+<div class="line"><a name="l09399"></a><span class="lineno"> 9399</span>&#160; </div>
+<div class="line"><a name="l09400"></a><span class="lineno"> 9400</span>&#160;    <span class="keywordflow">if</span>(item-&gt;size &gt;= VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER)</div>
+<div class="line"><a name="l09401"></a><span class="lineno"> 9401</span>&#160;    {</div>
+<div class="line"><a name="l09402"></a><span class="lineno"> 9402</span>&#160;        VmaSuballocationList::iterator* <span class="keyword">const</span> it = VmaBinaryFindFirstNotLess(</div>
+<div class="line"><a name="l09403"></a><span class="lineno"> 9403</span>&#160;            m_FreeSuballocationsBySize.data(),</div>
+<div class="line"><a name="l09404"></a><span class="lineno"> 9404</span>&#160;            m_FreeSuballocationsBySize.data() + m_FreeSuballocationsBySize.size(),</div>
+<div class="line"><a name="l09405"></a><span class="lineno"> 9405</span>&#160;            item,</div>
+<div class="line"><a name="l09406"></a><span class="lineno"> 9406</span>&#160;            VmaSuballocationItemSizeLess());</div>
+<div class="line"><a name="l09407"></a><span class="lineno"> 9407</span>&#160;        <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> index = it - m_FreeSuballocationsBySize.data();</div>
+<div class="line"><a name="l09408"></a><span class="lineno"> 9408</span>&#160;            index &lt; m_FreeSuballocationsBySize.size();</div>
+<div class="line"><a name="l09409"></a><span class="lineno"> 9409</span>&#160;            ++index)</div>
+<div class="line"><a name="l09410"></a><span class="lineno"> 9410</span>&#160;        {</div>
+<div class="line"><a name="l09411"></a><span class="lineno"> 9411</span>&#160;            <span class="keywordflow">if</span>(m_FreeSuballocationsBySize[index] == item)</div>
+<div class="line"><a name="l09412"></a><span class="lineno"> 9412</span>&#160;            {</div>
+<div class="line"><a name="l09413"></a><span class="lineno"> 9413</span>&#160;                VmaVectorRemove(m_FreeSuballocationsBySize, index);</div>
+<div class="line"><a name="l09414"></a><span class="lineno"> 9414</span>&#160;                <span class="keywordflow">return</span>;</div>
+<div class="line"><a name="l09415"></a><span class="lineno"> 9415</span>&#160;            }</div>
+<div class="line"><a name="l09416"></a><span class="lineno"> 9416</span>&#160;            VMA_ASSERT((m_FreeSuballocationsBySize[index]-&gt;size == item-&gt;size) &amp;&amp; <span class="stringliteral">&quot;Not found.&quot;</span>);</div>
+<div class="line"><a name="l09417"></a><span class="lineno"> 9417</span>&#160;        }</div>
+<div class="line"><a name="l09418"></a><span class="lineno"> 9418</span>&#160;        VMA_ASSERT(0 &amp;&amp; <span class="stringliteral">&quot;Not found.&quot;</span>);</div>
+<div class="line"><a name="l09419"></a><span class="lineno"> 9419</span>&#160;    }</div>
+<div class="line"><a name="l09420"></a><span class="lineno"> 9420</span>&#160; </div>
+<div class="line"><a name="l09421"></a><span class="lineno"> 9421</span>&#160;    <span class="comment">//VMA_HEAVY_ASSERT(ValidateFreeSuballocationList());</span></div>
+<div class="line"><a name="l09422"></a><span class="lineno"> 9422</span>&#160;}</div>
+<div class="line"><a name="l09423"></a><span class="lineno"> 9423</span>&#160; </div>
+<div class="line"><a name="l09424"></a><span class="lineno"> 9424</span>&#160;<span class="keywordtype">bool</span> VmaBlockMetadata_Generic::IsBufferImageGranularityConflictPossible(</div>
+<div class="line"><a name="l09425"></a><span class="lineno"> 9425</span>&#160;    VkDeviceSize bufferImageGranularity,</div>
+<div class="line"><a name="l09426"></a><span class="lineno"> 9426</span>&#160;    VmaSuballocationType&amp; inOutPrevSuballocType)<span class="keyword"> const</span></div>
+<div class="line"><a name="l09427"></a><span class="lineno"> 9427</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l09428"></a><span class="lineno"> 9428</span>&#160;    <span class="keywordflow">if</span>(bufferImageGranularity == 1 || IsEmpty())</div>
+<div class="line"><a name="l09429"></a><span class="lineno"> 9429</span>&#160;    {</div>
+<div class="line"><a name="l09430"></a><span class="lineno"> 9430</span>&#160;        <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l09431"></a><span class="lineno"> 9431</span>&#160;    }</div>
+<div class="line"><a name="l09432"></a><span class="lineno"> 9432</span>&#160; </div>
+<div class="line"><a name="l09433"></a><span class="lineno"> 9433</span>&#160;    VkDeviceSize minAlignment = VK_WHOLE_SIZE;</div>
+<div class="line"><a name="l09434"></a><span class="lineno"> 9434</span>&#160;    <span class="keywordtype">bool</span> typeConflictFound = <span class="keyword">false</span>;</div>
+<div class="line"><a name="l09435"></a><span class="lineno"> 9435</span>&#160;    <span class="keywordflow">for</span>(VmaSuballocationList::const_iterator it = m_Suballocations.cbegin();</div>
+<div class="line"><a name="l09436"></a><span class="lineno"> 9436</span>&#160;        it != m_Suballocations.cend();</div>
+<div class="line"><a name="l09437"></a><span class="lineno"> 9437</span>&#160;        ++it)</div>
+<div class="line"><a name="l09438"></a><span class="lineno"> 9438</span>&#160;    {</div>
+<div class="line"><a name="l09439"></a><span class="lineno"> 9439</span>&#160;        <span class="keyword">const</span> VmaSuballocationType suballocType = it-&gt;type;</div>
+<div class="line"><a name="l09440"></a><span class="lineno"> 9440</span>&#160;        <span class="keywordflow">if</span>(suballocType != VMA_SUBALLOCATION_TYPE_FREE)</div>
+<div class="line"><a name="l09441"></a><span class="lineno"> 9441</span>&#160;        {</div>
+<div class="line"><a name="l09442"></a><span class="lineno"> 9442</span>&#160;            minAlignment = VMA_MIN(minAlignment, it-&gt;hAllocation-&gt;GetAlignment());</div>
+<div class="line"><a name="l09443"></a><span class="lineno"> 9443</span>&#160;            <span class="keywordflow">if</span>(VmaIsBufferImageGranularityConflict(inOutPrevSuballocType, suballocType))</div>
+<div class="line"><a name="l09444"></a><span class="lineno"> 9444</span>&#160;            {</div>
+<div class="line"><a name="l09445"></a><span class="lineno"> 9445</span>&#160;                typeConflictFound = <span class="keyword">true</span>;</div>
+<div class="line"><a name="l09446"></a><span class="lineno"> 9446</span>&#160;            }</div>
+<div class="line"><a name="l09447"></a><span class="lineno"> 9447</span>&#160;            inOutPrevSuballocType = suballocType;</div>
+<div class="line"><a name="l09448"></a><span class="lineno"> 9448</span>&#160;        }</div>
+<div class="line"><a name="l09449"></a><span class="lineno"> 9449</span>&#160;    }</div>
+<div class="line"><a name="l09450"></a><span class="lineno"> 9450</span>&#160; </div>
+<div class="line"><a name="l09451"></a><span class="lineno"> 9451</span>&#160;    <span class="keywordflow">return</span> typeConflictFound || minAlignment &gt;= bufferImageGranularity;</div>
+<div class="line"><a name="l09452"></a><span class="lineno"> 9452</span>&#160;}</div>
+<div class="line"><a name="l09453"></a><span class="lineno"> 9453</span>&#160; </div>
+<div class="line"><a name="l09455"></a><span class="lineno"> 9455</span>&#160;<span class="comment">// class VmaBlockMetadata_Linear</span></div>
+<div class="line"><a name="l09456"></a><span class="lineno"> 9456</span>&#160; </div>
+<div class="line"><a name="l09457"></a><span class="lineno"> 9457</span>&#160;VmaBlockMetadata_Linear::VmaBlockMetadata_Linear(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator) :</div>
+<div class="line"><a name="l09458"></a><span class="lineno"> 9458</span>&#160;    VmaBlockMetadata(hAllocator),</div>
+<div class="line"><a name="l09459"></a><span class="lineno"> 9459</span>&#160;    m_SumFreeSize(0),</div>
+<div class="line"><a name="l09460"></a><span class="lineno"> 9460</span>&#160;    m_Suballocations0(VmaStlAllocator&lt;VmaSuballocation&gt;(hAllocator-&gt;GetAllocationCallbacks())),</div>
+<div class="line"><a name="l09461"></a><span class="lineno"> 9461</span>&#160;    m_Suballocations1(VmaStlAllocator&lt;VmaSuballocation&gt;(hAllocator-&gt;GetAllocationCallbacks())),</div>
+<div class="line"><a name="l09462"></a><span class="lineno"> 9462</span>&#160;    m_1stVectorIndex(0),</div>
+<div class="line"><a name="l09463"></a><span class="lineno"> 9463</span>&#160;    m_2ndVectorMode(SECOND_VECTOR_EMPTY),</div>
+<div class="line"><a name="l09464"></a><span class="lineno"> 9464</span>&#160;    m_1stNullItemsBeginCount(0),</div>
+<div class="line"><a name="l09465"></a><span class="lineno"> 9465</span>&#160;    m_1stNullItemsMiddleCount(0),</div>
+<div class="line"><a name="l09466"></a><span class="lineno"> 9466</span>&#160;    m_2ndNullItemsCount(0)</div>
+<div class="line"><a name="l09467"></a><span class="lineno"> 9467</span>&#160;{</div>
+<div class="line"><a name="l09468"></a><span class="lineno"> 9468</span>&#160;}</div>
+<div class="line"><a name="l09469"></a><span class="lineno"> 9469</span>&#160; </div>
+<div class="line"><a name="l09470"></a><span class="lineno"> 9470</span>&#160;VmaBlockMetadata_Linear::~VmaBlockMetadata_Linear()</div>
+<div class="line"><a name="l09471"></a><span class="lineno"> 9471</span>&#160;{</div>
+<div class="line"><a name="l09472"></a><span class="lineno"> 9472</span>&#160;}</div>
+<div class="line"><a name="l09473"></a><span class="lineno"> 9473</span>&#160; </div>
+<div class="line"><a name="l09474"></a><span class="lineno"> 9474</span>&#160;<span class="keywordtype">void</span> VmaBlockMetadata_Linear::Init(VkDeviceSize size)</div>
+<div class="line"><a name="l09475"></a><span class="lineno"> 9475</span>&#160;{</div>
+<div class="line"><a name="l09476"></a><span class="lineno"> 9476</span>&#160;    VmaBlockMetadata::Init(size);</div>
+<div class="line"><a name="l09477"></a><span class="lineno"> 9477</span>&#160;    m_SumFreeSize = size;</div>
+<div class="line"><a name="l09478"></a><span class="lineno"> 9478</span>&#160;}</div>
+<div class="line"><a name="l09479"></a><span class="lineno"> 9479</span>&#160; </div>
+<div class="line"><a name="l09480"></a><span class="lineno"> 9480</span>&#160;<span class="keywordtype">bool</span> VmaBlockMetadata_Linear::Validate()<span class="keyword"> const</span></div>
+<div class="line"><a name="l09481"></a><span class="lineno"> 9481</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l09482"></a><span class="lineno"> 9482</span>&#160;    <span class="keyword">const</span> SuballocationVectorType&amp; suballocations1st = AccessSuballocations1st();</div>
+<div class="line"><a name="l09483"></a><span class="lineno"> 9483</span>&#160;    <span class="keyword">const</span> SuballocationVectorType&amp; suballocations2nd = AccessSuballocations2nd();</div>
+<div class="line"><a name="l09484"></a><span class="lineno"> 9484</span>&#160; </div>
+<div class="line"><a name="l09485"></a><span class="lineno"> 9485</span>&#160;    VMA_VALIDATE(suballocations2nd.empty() == (m_2ndVectorMode == SECOND_VECTOR_EMPTY));</div>
+<div class="line"><a name="l09486"></a><span class="lineno"> 9486</span>&#160;    VMA_VALIDATE(!suballocations1st.empty() ||</div>
+<div class="line"><a name="l09487"></a><span class="lineno"> 9487</span>&#160;        suballocations2nd.empty() ||</div>
+<div class="line"><a name="l09488"></a><span class="lineno"> 9488</span>&#160;        m_2ndVectorMode != SECOND_VECTOR_RING_BUFFER);</div>
+<div class="line"><a name="l09489"></a><span class="lineno"> 9489</span>&#160; </div>
+<div class="line"><a name="l09490"></a><span class="lineno"> 9490</span>&#160;    <span class="keywordflow">if</span>(!suballocations1st.empty())</div>
+<div class="line"><a name="l09491"></a><span class="lineno"> 9491</span>&#160;    {</div>
+<div class="line"><a name="l09492"></a><span class="lineno"> 9492</span>&#160;        <span class="comment">// Null item at the beginning should be accounted into m_1stNullItemsBeginCount.</span></div>
+<div class="line"><a name="l09493"></a><span class="lineno"> 9493</span>&#160;        VMA_VALIDATE(suballocations1st[m_1stNullItemsBeginCount].hAllocation != VK_NULL_HANDLE);</div>
+<div class="line"><a name="l09494"></a><span class="lineno"> 9494</span>&#160;        <span class="comment">// Null item at the end should be just pop_back().</span></div>
+<div class="line"><a name="l09495"></a><span class="lineno"> 9495</span>&#160;        VMA_VALIDATE(suballocations1st.back().hAllocation != VK_NULL_HANDLE);</div>
+<div class="line"><a name="l09496"></a><span class="lineno"> 9496</span>&#160;    }</div>
+<div class="line"><a name="l09497"></a><span class="lineno"> 9497</span>&#160;    <span class="keywordflow">if</span>(!suballocations2nd.empty())</div>
+<div class="line"><a name="l09498"></a><span class="lineno"> 9498</span>&#160;    {</div>
+<div class="line"><a name="l09499"></a><span class="lineno"> 9499</span>&#160;        <span class="comment">// Null item at the end should be just pop_back().</span></div>
+<div class="line"><a name="l09500"></a><span class="lineno"> 9500</span>&#160;        VMA_VALIDATE(suballocations2nd.back().hAllocation != VK_NULL_HANDLE);</div>
+<div class="line"><a name="l09501"></a><span class="lineno"> 9501</span>&#160;    }</div>
+<div class="line"><a name="l09502"></a><span class="lineno"> 9502</span>&#160; </div>
+<div class="line"><a name="l09503"></a><span class="lineno"> 9503</span>&#160;    VMA_VALIDATE(m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount &lt;= suballocations1st.size());</div>
+<div class="line"><a name="l09504"></a><span class="lineno"> 9504</span>&#160;    VMA_VALIDATE(m_2ndNullItemsCount &lt;= suballocations2nd.size());</div>
+<div class="line"><a name="l09505"></a><span class="lineno"> 9505</span>&#160; </div>
+<div class="line"><a name="l09506"></a><span class="lineno"> 9506</span>&#160;    VkDeviceSize sumUsedSize = 0;</div>
+<div class="line"><a name="l09507"></a><span class="lineno"> 9507</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">size_t</span> suballoc1stCount = suballocations1st.size();</div>
+<div class="line"><a name="l09508"></a><span class="lineno"> 9508</span>&#160;    VkDeviceSize offset = VMA_DEBUG_MARGIN;</div>
+<div class="line"><a name="l09509"></a><span class="lineno"> 9509</span>&#160; </div>
+<div class="line"><a name="l09510"></a><span class="lineno"> 9510</span>&#160;    <span class="keywordflow">if</span>(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)</div>
+<div class="line"><a name="l09511"></a><span class="lineno"> 9511</span>&#160;    {</div>
+<div class="line"><a name="l09512"></a><span class="lineno"> 9512</span>&#160;        <span class="keyword">const</span> <span class="keywordtype">size_t</span> suballoc2ndCount = suballocations2nd.size();</div>
+<div class="line"><a name="l09513"></a><span class="lineno"> 9513</span>&#160;        <span class="keywordtype">size_t</span> nullItem2ndCount = 0;</div>
+<div class="line"><a name="l09514"></a><span class="lineno"> 9514</span>&#160;        <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = 0; i &lt; suballoc2ndCount; ++i)</div>
+<div class="line"><a name="l09515"></a><span class="lineno"> 9515</span>&#160;        {</div>
+<div class="line"><a name="l09516"></a><span class="lineno"> 9516</span>&#160;            <span class="keyword">const</span> VmaSuballocation&amp; suballoc = suballocations2nd[i];</div>
+<div class="line"><a name="l09517"></a><span class="lineno"> 9517</span>&#160;            <span class="keyword">const</span> <span class="keywordtype">bool</span> currFree = (suballoc.type == VMA_SUBALLOCATION_TYPE_FREE);</div>
+<div class="line"><a name="l09518"></a><span class="lineno"> 9518</span>&#160; </div>
+<div class="line"><a name="l09519"></a><span class="lineno"> 9519</span>&#160;            VMA_VALIDATE(currFree == (suballoc.hAllocation == VK_NULL_HANDLE));</div>
+<div class="line"><a name="l09520"></a><span class="lineno"> 9520</span>&#160;            VMA_VALIDATE(suballoc.offset &gt;= offset);</div>
+<div class="line"><a name="l09521"></a><span class="lineno"> 9521</span>&#160; </div>
+<div class="line"><a name="l09522"></a><span class="lineno"> 9522</span>&#160;            <span class="keywordflow">if</span>(!currFree)</div>
+<div class="line"><a name="l09523"></a><span class="lineno"> 9523</span>&#160;            {</div>
+<div class="line"><a name="l09524"></a><span class="lineno"> 9524</span>&#160;                VMA_VALIDATE(suballoc.hAllocation-&gt;GetOffset() == suballoc.offset);</div>
+<div class="line"><a name="l09525"></a><span class="lineno"> 9525</span>&#160;                VMA_VALIDATE(suballoc.hAllocation-&gt;GetSize() == suballoc.size);</div>
+<div class="line"><a name="l09526"></a><span class="lineno"> 9526</span>&#160;                sumUsedSize += suballoc.size;</div>
+<div class="line"><a name="l09527"></a><span class="lineno"> 9527</span>&#160;            }</div>
+<div class="line"><a name="l09528"></a><span class="lineno"> 9528</span>&#160;            <span class="keywordflow">else</span></div>
+<div class="line"><a name="l09529"></a><span class="lineno"> 9529</span>&#160;            {</div>
+<div class="line"><a name="l09530"></a><span class="lineno"> 9530</span>&#160;                ++nullItem2ndCount;</div>
+<div class="line"><a name="l09531"></a><span class="lineno"> 9531</span>&#160;            }</div>
+<div class="line"><a name="l09532"></a><span class="lineno"> 9532</span>&#160; </div>
+<div class="line"><a name="l09533"></a><span class="lineno"> 9533</span>&#160;            offset = suballoc.offset + suballoc.size + VMA_DEBUG_MARGIN;</div>
+<div class="line"><a name="l09534"></a><span class="lineno"> 9534</span>&#160;        }</div>
+<div class="line"><a name="l09535"></a><span class="lineno"> 9535</span>&#160; </div>
+<div class="line"><a name="l09536"></a><span class="lineno"> 9536</span>&#160;        VMA_VALIDATE(nullItem2ndCount == m_2ndNullItemsCount);</div>
+<div class="line"><a name="l09537"></a><span class="lineno"> 9537</span>&#160;    }</div>
+<div class="line"><a name="l09538"></a><span class="lineno"> 9538</span>&#160; </div>
+<div class="line"><a name="l09539"></a><span class="lineno"> 9539</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = 0; i &lt; m_1stNullItemsBeginCount; ++i)</div>
+<div class="line"><a name="l09540"></a><span class="lineno"> 9540</span>&#160;    {</div>
+<div class="line"><a name="l09541"></a><span class="lineno"> 9541</span>&#160;        <span class="keyword">const</span> VmaSuballocation&amp; suballoc = suballocations1st[i];</div>
+<div class="line"><a name="l09542"></a><span class="lineno"> 9542</span>&#160;        VMA_VALIDATE(suballoc.type == VMA_SUBALLOCATION_TYPE_FREE &amp;&amp;</div>
+<div class="line"><a name="l09543"></a><span class="lineno"> 9543</span>&#160;            suballoc.hAllocation == VK_NULL_HANDLE);</div>
+<div class="line"><a name="l09544"></a><span class="lineno"> 9544</span>&#160;    }</div>
+<div class="line"><a name="l09545"></a><span class="lineno"> 9545</span>&#160; </div>
+<div class="line"><a name="l09546"></a><span class="lineno"> 9546</span>&#160;    <span class="keywordtype">size_t</span> nullItem1stCount = m_1stNullItemsBeginCount;</div>
+<div class="line"><a name="l09547"></a><span class="lineno"> 9547</span>&#160; </div>
+<div class="line"><a name="l09548"></a><span class="lineno"> 9548</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = m_1stNullItemsBeginCount; i &lt; suballoc1stCount; ++i)</div>
+<div class="line"><a name="l09549"></a><span class="lineno"> 9549</span>&#160;    {</div>
+<div class="line"><a name="l09550"></a><span class="lineno"> 9550</span>&#160;        <span class="keyword">const</span> VmaSuballocation&amp; suballoc = suballocations1st[i];</div>
+<div class="line"><a name="l09551"></a><span class="lineno"> 9551</span>&#160;        <span class="keyword">const</span> <span class="keywordtype">bool</span> currFree = (suballoc.type == VMA_SUBALLOCATION_TYPE_FREE);</div>
+<div class="line"><a name="l09552"></a><span class="lineno"> 9552</span>&#160; </div>
+<div class="line"><a name="l09553"></a><span class="lineno"> 9553</span>&#160;        VMA_VALIDATE(currFree == (suballoc.hAllocation == VK_NULL_HANDLE));</div>
+<div class="line"><a name="l09554"></a><span class="lineno"> 9554</span>&#160;        VMA_VALIDATE(suballoc.offset &gt;= offset);</div>
+<div class="line"><a name="l09555"></a><span class="lineno"> 9555</span>&#160;        VMA_VALIDATE(i &gt;= m_1stNullItemsBeginCount || currFree);</div>
+<div class="line"><a name="l09556"></a><span class="lineno"> 9556</span>&#160; </div>
+<div class="line"><a name="l09557"></a><span class="lineno"> 9557</span>&#160;        <span class="keywordflow">if</span>(!currFree)</div>
+<div class="line"><a name="l09558"></a><span class="lineno"> 9558</span>&#160;        {</div>
+<div class="line"><a name="l09559"></a><span class="lineno"> 9559</span>&#160;            VMA_VALIDATE(suballoc.hAllocation-&gt;GetOffset() == suballoc.offset);</div>
+<div class="line"><a name="l09560"></a><span class="lineno"> 9560</span>&#160;            VMA_VALIDATE(suballoc.hAllocation-&gt;GetSize() == suballoc.size);</div>
+<div class="line"><a name="l09561"></a><span class="lineno"> 9561</span>&#160;            sumUsedSize += suballoc.size;</div>
+<div class="line"><a name="l09562"></a><span class="lineno"> 9562</span>&#160;        }</div>
+<div class="line"><a name="l09563"></a><span class="lineno"> 9563</span>&#160;        <span class="keywordflow">else</span></div>
+<div class="line"><a name="l09564"></a><span class="lineno"> 9564</span>&#160;        {</div>
+<div class="line"><a name="l09565"></a><span class="lineno"> 9565</span>&#160;            ++nullItem1stCount;</div>
+<div class="line"><a name="l09566"></a><span class="lineno"> 9566</span>&#160;        }</div>
+<div class="line"><a name="l09567"></a><span class="lineno"> 9567</span>&#160; </div>
+<div class="line"><a name="l09568"></a><span class="lineno"> 9568</span>&#160;        offset = suballoc.offset + suballoc.size + VMA_DEBUG_MARGIN;</div>
+<div class="line"><a name="l09569"></a><span class="lineno"> 9569</span>&#160;    }</div>
+<div class="line"><a name="l09570"></a><span class="lineno"> 9570</span>&#160;    VMA_VALIDATE(nullItem1stCount == m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount);</div>
+<div class="line"><a name="l09571"></a><span class="lineno"> 9571</span>&#160; </div>
+<div class="line"><a name="l09572"></a><span class="lineno"> 9572</span>&#160;    <span class="keywordflow">if</span>(m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)</div>
+<div class="line"><a name="l09573"></a><span class="lineno"> 9573</span>&#160;    {</div>
+<div class="line"><a name="l09574"></a><span class="lineno"> 9574</span>&#160;        <span class="keyword">const</span> <span class="keywordtype">size_t</span> suballoc2ndCount = suballocations2nd.size();</div>
+<div class="line"><a name="l09575"></a><span class="lineno"> 9575</span>&#160;        <span class="keywordtype">size_t</span> nullItem2ndCount = 0;</div>
+<div class="line"><a name="l09576"></a><span class="lineno"> 9576</span>&#160;        <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = suballoc2ndCount; i--; )</div>
+<div class="line"><a name="l09577"></a><span class="lineno"> 9577</span>&#160;        {</div>
+<div class="line"><a name="l09578"></a><span class="lineno"> 9578</span>&#160;            <span class="keyword">const</span> VmaSuballocation&amp; suballoc = suballocations2nd[i];</div>
+<div class="line"><a name="l09579"></a><span class="lineno"> 9579</span>&#160;            <span class="keyword">const</span> <span class="keywordtype">bool</span> currFree = (suballoc.type == VMA_SUBALLOCATION_TYPE_FREE);</div>
+<div class="line"><a name="l09580"></a><span class="lineno"> 9580</span>&#160; </div>
+<div class="line"><a name="l09581"></a><span class="lineno"> 9581</span>&#160;            VMA_VALIDATE(currFree == (suballoc.hAllocation == VK_NULL_HANDLE));</div>
+<div class="line"><a name="l09582"></a><span class="lineno"> 9582</span>&#160;            VMA_VALIDATE(suballoc.offset &gt;= offset);</div>
+<div class="line"><a name="l09583"></a><span class="lineno"> 9583</span>&#160; </div>
+<div class="line"><a name="l09584"></a><span class="lineno"> 9584</span>&#160;            <span class="keywordflow">if</span>(!currFree)</div>
+<div class="line"><a name="l09585"></a><span class="lineno"> 9585</span>&#160;            {</div>
+<div class="line"><a name="l09586"></a><span class="lineno"> 9586</span>&#160;                VMA_VALIDATE(suballoc.hAllocation-&gt;GetOffset() == suballoc.offset);</div>
+<div class="line"><a name="l09587"></a><span class="lineno"> 9587</span>&#160;                VMA_VALIDATE(suballoc.hAllocation-&gt;GetSize() == suballoc.size);</div>
+<div class="line"><a name="l09588"></a><span class="lineno"> 9588</span>&#160;                sumUsedSize += suballoc.size;</div>
+<div class="line"><a name="l09589"></a><span class="lineno"> 9589</span>&#160;            }</div>
+<div class="line"><a name="l09590"></a><span class="lineno"> 9590</span>&#160;            <span class="keywordflow">else</span></div>
+<div class="line"><a name="l09591"></a><span class="lineno"> 9591</span>&#160;            {</div>
+<div class="line"><a name="l09592"></a><span class="lineno"> 9592</span>&#160;                ++nullItem2ndCount;</div>
+<div class="line"><a name="l09593"></a><span class="lineno"> 9593</span>&#160;            }</div>
+<div class="line"><a name="l09594"></a><span class="lineno"> 9594</span>&#160; </div>
+<div class="line"><a name="l09595"></a><span class="lineno"> 9595</span>&#160;            offset = suballoc.offset + suballoc.size + VMA_DEBUG_MARGIN;</div>
+<div class="line"><a name="l09596"></a><span class="lineno"> 9596</span>&#160;        }</div>
+<div class="line"><a name="l09597"></a><span class="lineno"> 9597</span>&#160; </div>
+<div class="line"><a name="l09598"></a><span class="lineno"> 9598</span>&#160;        VMA_VALIDATE(nullItem2ndCount == m_2ndNullItemsCount);</div>
+<div class="line"><a name="l09599"></a><span class="lineno"> 9599</span>&#160;    }</div>
+<div class="line"><a name="l09600"></a><span class="lineno"> 9600</span>&#160; </div>
+<div class="line"><a name="l09601"></a><span class="lineno"> 9601</span>&#160;    VMA_VALIDATE(offset &lt;= GetSize());</div>
+<div class="line"><a name="l09602"></a><span class="lineno"> 9602</span>&#160;    VMA_VALIDATE(m_SumFreeSize == GetSize() - sumUsedSize);</div>
+<div class="line"><a name="l09603"></a><span class="lineno"> 9603</span>&#160; </div>
+<div class="line"><a name="l09604"></a><span class="lineno"> 9604</span>&#160;    <span class="keywordflow">return</span> <span class="keyword">true</span>;</div>
+<div class="line"><a name="l09605"></a><span class="lineno"> 9605</span>&#160;}</div>
+<div class="line"><a name="l09606"></a><span class="lineno"> 9606</span>&#160; </div>
+<div class="line"><a name="l09607"></a><span class="lineno"> 9607</span>&#160;<span class="keywordtype">size_t</span> VmaBlockMetadata_Linear::GetAllocationCount()<span class="keyword"> const</span></div>
+<div class="line"><a name="l09608"></a><span class="lineno"> 9608</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l09609"></a><span class="lineno"> 9609</span>&#160;    <span class="keywordflow">return</span> AccessSuballocations1st().size() - (m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount) +</div>
+<div class="line"><a name="l09610"></a><span class="lineno"> 9610</span>&#160;        AccessSuballocations2nd().size() - m_2ndNullItemsCount;</div>
+<div class="line"><a name="l09611"></a><span class="lineno"> 9611</span>&#160;}</div>
+<div class="line"><a name="l09612"></a><span class="lineno"> 9612</span>&#160; </div>
+<div class="line"><a name="l09613"></a><span class="lineno"> 9613</span>&#160;VkDeviceSize VmaBlockMetadata_Linear::GetUnusedRangeSizeMax()<span class="keyword"> const</span></div>
+<div class="line"><a name="l09614"></a><span class="lineno"> 9614</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l09615"></a><span class="lineno"> 9615</span>&#160;    <span class="keyword">const</span> VkDeviceSize size = GetSize();</div>
+<div class="line"><a name="l09616"></a><span class="lineno"> 9616</span>&#160; </div>
+<div class="line"><a name="l09617"></a><span class="lineno"> 9617</span>&#160;    <span class="comment">/*</span></div>
+<div class="line"><a name="l09618"></a><span class="lineno"> 9618</span>&#160;<span class="comment">    We don&#39;t consider gaps inside allocation vectors with freed allocations because</span></div>
+<div class="line"><a name="l09619"></a><span class="lineno"> 9619</span>&#160;<span class="comment">    they are not suitable for reuse in linear allocator. We consider only space that</span></div>
+<div class="line"><a name="l09620"></a><span class="lineno"> 9620</span>&#160;<span class="comment">    is available for new allocations.</span></div>
+<div class="line"><a name="l09621"></a><span class="lineno"> 9621</span>&#160;<span class="comment">    */</span></div>
+<div class="line"><a name="l09622"></a><span class="lineno"> 9622</span>&#160;    <span class="keywordflow">if</span>(IsEmpty())</div>
+<div class="line"><a name="l09623"></a><span class="lineno"> 9623</span>&#160;    {</div>
+<div class="line"><a name="l09624"></a><span class="lineno"> 9624</span>&#160;        <span class="keywordflow">return</span> size;</div>
+<div class="line"><a name="l09625"></a><span class="lineno"> 9625</span>&#160;    }</div>
+<div class="line"><a name="l09626"></a><span class="lineno"> 9626</span>&#160;    </div>
+<div class="line"><a name="l09627"></a><span class="lineno"> 9627</span>&#160;    <span class="keyword">const</span> SuballocationVectorType&amp; suballocations1st = AccessSuballocations1st();</div>
+<div class="line"><a name="l09628"></a><span class="lineno"> 9628</span>&#160; </div>
+<div class="line"><a name="l09629"></a><span class="lineno"> 9629</span>&#160;    <span class="keywordflow">switch</span>(m_2ndVectorMode)</div>
+<div class="line"><a name="l09630"></a><span class="lineno"> 9630</span>&#160;    {</div>
+<div class="line"><a name="l09631"></a><span class="lineno"> 9631</span>&#160;    <span class="keywordflow">case</span> SECOND_VECTOR_EMPTY:</div>
+<div class="line"><a name="l09632"></a><span class="lineno"> 9632</span>&#160;        <span class="comment">/*</span></div>
+<div class="line"><a name="l09633"></a><span class="lineno"> 9633</span>&#160;<span class="comment">        Available space is after end of 1st, as well as before beginning of 1st (which</span></div>
+<div class="line"><a name="l09634"></a><span class="lineno"> 9634</span>&#160;<span class="comment">        whould make it a ring buffer).</span></div>
+<div class="line"><a name="l09635"></a><span class="lineno"> 9635</span>&#160;<span class="comment">        */</span></div>
+<div class="line"><a name="l09636"></a><span class="lineno"> 9636</span>&#160;        {</div>
+<div class="line"><a name="l09637"></a><span class="lineno"> 9637</span>&#160;            <span class="keyword">const</span> <span class="keywordtype">size_t</span> suballocations1stCount = suballocations1st.size();</div>
+<div class="line"><a name="l09638"></a><span class="lineno"> 9638</span>&#160;            VMA_ASSERT(suballocations1stCount &gt; m_1stNullItemsBeginCount);</div>
+<div class="line"><a name="l09639"></a><span class="lineno"> 9639</span>&#160;            <span class="keyword">const</span> VmaSuballocation&amp; firstSuballoc = suballocations1st[m_1stNullItemsBeginCount];</div>
+<div class="line"><a name="l09640"></a><span class="lineno"> 9640</span>&#160;            <span class="keyword">const</span> VmaSuballocation&amp; lastSuballoc  = suballocations1st[suballocations1stCount - 1];</div>
+<div class="line"><a name="l09641"></a><span class="lineno"> 9641</span>&#160;            <span class="keywordflow">return</span> VMA_MAX(</div>
+<div class="line"><a name="l09642"></a><span class="lineno"> 9642</span>&#160;                firstSuballoc.offset,</div>
+<div class="line"><a name="l09643"></a><span class="lineno"> 9643</span>&#160;                size - (lastSuballoc.offset + lastSuballoc.size));</div>
+<div class="line"><a name="l09644"></a><span class="lineno"> 9644</span>&#160;        }</div>
+<div class="line"><a name="l09645"></a><span class="lineno"> 9645</span>&#160;        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l09646"></a><span class="lineno"> 9646</span>&#160; </div>
+<div class="line"><a name="l09647"></a><span class="lineno"> 9647</span>&#160;    <span class="keywordflow">case</span> SECOND_VECTOR_RING_BUFFER:</div>
+<div class="line"><a name="l09648"></a><span class="lineno"> 9648</span>&#160;        <span class="comment">/*</span></div>
+<div class="line"><a name="l09649"></a><span class="lineno"> 9649</span>&#160;<span class="comment">        Available space is only between end of 2nd and beginning of 1st.</span></div>
+<div class="line"><a name="l09650"></a><span class="lineno"> 9650</span>&#160;<span class="comment">        */</span></div>
+<div class="line"><a name="l09651"></a><span class="lineno"> 9651</span>&#160;        {</div>
+<div class="line"><a name="l09652"></a><span class="lineno"> 9652</span>&#160;            <span class="keyword">const</span> SuballocationVectorType&amp; suballocations2nd = AccessSuballocations2nd();</div>
+<div class="line"><a name="l09653"></a><span class="lineno"> 9653</span>&#160;            <span class="keyword">const</span> VmaSuballocation&amp; lastSuballoc2nd = suballocations2nd.back();</div>
+<div class="line"><a name="l09654"></a><span class="lineno"> 9654</span>&#160;            <span class="keyword">const</span> VmaSuballocation&amp; firstSuballoc1st = suballocations1st[m_1stNullItemsBeginCount];</div>
+<div class="line"><a name="l09655"></a><span class="lineno"> 9655</span>&#160;            <span class="keywordflow">return</span> firstSuballoc1st.offset - (lastSuballoc2nd.offset + lastSuballoc2nd.size);</div>
+<div class="line"><a name="l09656"></a><span class="lineno"> 9656</span>&#160;        }</div>
+<div class="line"><a name="l09657"></a><span class="lineno"> 9657</span>&#160;        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l09658"></a><span class="lineno"> 9658</span>&#160; </div>
+<div class="line"><a name="l09659"></a><span class="lineno"> 9659</span>&#160;    <span class="keywordflow">case</span> SECOND_VECTOR_DOUBLE_STACK:</div>
+<div class="line"><a name="l09660"></a><span class="lineno"> 9660</span>&#160;        <span class="comment">/*</span></div>
+<div class="line"><a name="l09661"></a><span class="lineno"> 9661</span>&#160;<span class="comment">        Available space is only between end of 1st and top of 2nd.</span></div>
+<div class="line"><a name="l09662"></a><span class="lineno"> 9662</span>&#160;<span class="comment">        */</span></div>
+<div class="line"><a name="l09663"></a><span class="lineno"> 9663</span>&#160;        {</div>
+<div class="line"><a name="l09664"></a><span class="lineno"> 9664</span>&#160;            <span class="keyword">const</span> SuballocationVectorType&amp; suballocations2nd = AccessSuballocations2nd();</div>
+<div class="line"><a name="l09665"></a><span class="lineno"> 9665</span>&#160;            <span class="keyword">const</span> VmaSuballocation&amp; topSuballoc2nd = suballocations2nd.back();</div>
+<div class="line"><a name="l09666"></a><span class="lineno"> 9666</span>&#160;            <span class="keyword">const</span> VmaSuballocation&amp; lastSuballoc1st = suballocations1st.back();</div>
+<div class="line"><a name="l09667"></a><span class="lineno"> 9667</span>&#160;            <span class="keywordflow">return</span> topSuballoc2nd.offset - (lastSuballoc1st.offset + lastSuballoc1st.size);</div>
+<div class="line"><a name="l09668"></a><span class="lineno"> 9668</span>&#160;        }</div>
+<div class="line"><a name="l09669"></a><span class="lineno"> 9669</span>&#160;        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l09670"></a><span class="lineno"> 9670</span>&#160; </div>
+<div class="line"><a name="l09671"></a><span class="lineno"> 9671</span>&#160;    <span class="keywordflow">default</span>:</div>
+<div class="line"><a name="l09672"></a><span class="lineno"> 9672</span>&#160;        VMA_ASSERT(0);</div>
+<div class="line"><a name="l09673"></a><span class="lineno"> 9673</span>&#160;        <span class="keywordflow">return</span> 0;</div>
+<div class="line"><a name="l09674"></a><span class="lineno"> 9674</span>&#160;    }</div>
+<div class="line"><a name="l09675"></a><span class="lineno"> 9675</span>&#160;}</div>
+<div class="line"><a name="l09676"></a><span class="lineno"> 9676</span>&#160; </div>
+<div class="line"><a name="l09677"></a><span class="lineno"> 9677</span>&#160;<span class="keywordtype">void</span> VmaBlockMetadata_Linear::CalcAllocationStatInfo(<a class="code" href="struct_vma_stat_info.html">VmaStatInfo</a>&amp; outInfo)<span class="keyword"> const</span></div>
+<div class="line"><a name="l09678"></a><span class="lineno"> 9678</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l09679"></a><span class="lineno"> 9679</span>&#160;    <span class="keyword">const</span> VkDeviceSize size = GetSize();</div>
+<div class="line"><a name="l09680"></a><span class="lineno"> 9680</span>&#160;    <span class="keyword">const</span> SuballocationVectorType&amp; suballocations1st = AccessSuballocations1st();</div>
+<div class="line"><a name="l09681"></a><span class="lineno"> 9681</span>&#160;    <span class="keyword">const</span> SuballocationVectorType&amp; suballocations2nd = AccessSuballocations2nd();</div>
+<div class="line"><a name="l09682"></a><span class="lineno"> 9682</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">size_t</span> suballoc1stCount = suballocations1st.size();</div>
+<div class="line"><a name="l09683"></a><span class="lineno"> 9683</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">size_t</span> suballoc2ndCount = suballocations2nd.size();</div>
+<div class="line"><a name="l09684"></a><span class="lineno"> 9684</span>&#160; </div>
+<div class="line"><a name="l09685"></a><span class="lineno"> 9685</span>&#160;    outInfo.<a class="code" href="struct_vma_stat_info.html#abc4bb7cd611900778464c56e50c970a4">blockCount</a> = 1;</div>
+<div class="line"><a name="l09686"></a><span class="lineno"> 9686</span>&#160;    outInfo.<a class="code" href="struct_vma_stat_info.html#a537741e4d5cdddc1c0ab95ec650afaff">allocationCount</a> = (uint32_t)GetAllocationCount();</div>
+<div class="line"><a name="l09687"></a><span class="lineno"> 9687</span>&#160;    outInfo.<a class="code" href="struct_vma_stat_info.html#ae06129c771bfebfd6468a7f4276502a9">unusedRangeCount</a> = 0;</div>
+<div class="line"><a name="l09688"></a><span class="lineno"> 9688</span>&#160;    outInfo.<a class="code" href="struct_vma_stat_info.html#ab0c6c73837e5a70c749fbd4f6064895a">usedBytes</a> = 0;</div>
+<div class="line"><a name="l09689"></a><span class="lineno"> 9689</span>&#160;    outInfo.<a class="code" href="struct_vma_stat_info.html#ade8b40bd3139c04aabd2fc538a356fea">allocationSizeMin</a> = UINT64_MAX;</div>
+<div class="line"><a name="l09690"></a><span class="lineno"> 9690</span>&#160;    outInfo.<a class="code" href="struct_vma_stat_info.html#a17e9733a5ecd76287d4db6e66f71f50c">allocationSizeMax</a> = 0;</div>
+<div class="line"><a name="l09691"></a><span class="lineno"> 9691</span>&#160;    outInfo.<a class="code" href="struct_vma_stat_info.html#aedeba931324f16589cd2416c0d2dd0d4">unusedRangeSizeMin</a> = UINT64_MAX;</div>
+<div class="line"><a name="l09692"></a><span class="lineno"> 9692</span>&#160;    outInfo.<a class="code" href="struct_vma_stat_info.html#a5ba1a2476c4d39b10f7e2f7ebbb72ac4">unusedRangeSizeMax</a> = 0;</div>
+<div class="line"><a name="l09693"></a><span class="lineno"> 9693</span>&#160; </div>
+<div class="line"><a name="l09694"></a><span class="lineno"> 9694</span>&#160;    VkDeviceSize lastOffset = 0;</div>
+<div class="line"><a name="l09695"></a><span class="lineno"> 9695</span>&#160; </div>
+<div class="line"><a name="l09696"></a><span class="lineno"> 9696</span>&#160;    <span class="keywordflow">if</span>(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)</div>
+<div class="line"><a name="l09697"></a><span class="lineno"> 9697</span>&#160;    {</div>
+<div class="line"><a name="l09698"></a><span class="lineno"> 9698</span>&#160;        <span class="keyword">const</span> VkDeviceSize freeSpace2ndTo1stEnd = suballocations1st[m_1stNullItemsBeginCount].offset;</div>
+<div class="line"><a name="l09699"></a><span class="lineno"> 9699</span>&#160;        <span class="keywordtype">size_t</span> nextAlloc2ndIndex = 0;</div>
+<div class="line"><a name="l09700"></a><span class="lineno"> 9700</span>&#160;        <span class="keywordflow">while</span>(lastOffset &lt; freeSpace2ndTo1stEnd)</div>
+<div class="line"><a name="l09701"></a><span class="lineno"> 9701</span>&#160;        {</div>
+<div class="line"><a name="l09702"></a><span class="lineno"> 9702</span>&#160;            <span class="comment">// Find next non-null allocation or move nextAllocIndex to the end.</span></div>
+<div class="line"><a name="l09703"></a><span class="lineno"> 9703</span>&#160;            <span class="keywordflow">while</span>(nextAlloc2ndIndex &lt; suballoc2ndCount &amp;&amp;</div>
+<div class="line"><a name="l09704"></a><span class="lineno"> 9704</span>&#160;                suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE)</div>
+<div class="line"><a name="l09705"></a><span class="lineno"> 9705</span>&#160;            {</div>
+<div class="line"><a name="l09706"></a><span class="lineno"> 9706</span>&#160;                ++nextAlloc2ndIndex;</div>
+<div class="line"><a name="l09707"></a><span class="lineno"> 9707</span>&#160;            }</div>
+<div class="line"><a name="l09708"></a><span class="lineno"> 9708</span>&#160; </div>
+<div class="line"><a name="l09709"></a><span class="lineno"> 9709</span>&#160;            <span class="comment">// Found non-null allocation.</span></div>
+<div class="line"><a name="l09710"></a><span class="lineno"> 9710</span>&#160;            <span class="keywordflow">if</span>(nextAlloc2ndIndex &lt; suballoc2ndCount)</div>
+<div class="line"><a name="l09711"></a><span class="lineno"> 9711</span>&#160;            {</div>
+<div class="line"><a name="l09712"></a><span class="lineno"> 9712</span>&#160;                <span class="keyword">const</span> VmaSuballocation&amp; suballoc = suballocations2nd[nextAlloc2ndIndex];</div>
+<div class="line"><a name="l09713"></a><span class="lineno"> 9713</span>&#160;            </div>
+<div class="line"><a name="l09714"></a><span class="lineno"> 9714</span>&#160;                <span class="comment">// 1. Process free space before this allocation.</span></div>
+<div class="line"><a name="l09715"></a><span class="lineno"> 9715</span>&#160;                <span class="keywordflow">if</span>(lastOffset &lt; suballoc.offset)</div>
+<div class="line"><a name="l09716"></a><span class="lineno"> 9716</span>&#160;                {</div>
+<div class="line"><a name="l09717"></a><span class="lineno"> 9717</span>&#160;                    <span class="comment">// There is free space from lastOffset to suballoc.offset.</span></div>
+<div class="line"><a name="l09718"></a><span class="lineno"> 9718</span>&#160;                    <span class="keyword">const</span> VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;</div>
+<div class="line"><a name="l09719"></a><span class="lineno"> 9719</span>&#160;                    ++outInfo.<a class="code" href="struct_vma_stat_info.html#ae06129c771bfebfd6468a7f4276502a9">unusedRangeCount</a>;</div>
+<div class="line"><a name="l09720"></a><span class="lineno"> 9720</span>&#160;                    outInfo.<a class="code" href="struct_vma_stat_info.html#a1859d290aca2cd582d8dc25922092669">unusedBytes</a> += unusedRangeSize;</div>
+<div class="line"><a name="l09721"></a><span class="lineno"> 9721</span>&#160;                    outInfo.<a class="code" href="struct_vma_stat_info.html#aedeba931324f16589cd2416c0d2dd0d4">unusedRangeSizeMin</a> = VMA_MIN(outInfo.<a class="code" href="struct_vma_stat_info.html#aedeba931324f16589cd2416c0d2dd0d4">unusedRangeSizeMin</a>, unusedRangeSize);</div>
+<div class="line"><a name="l09722"></a><span class="lineno"> 9722</span>&#160;                    outInfo.<a class="code" href="struct_vma_stat_info.html#a5ba1a2476c4d39b10f7e2f7ebbb72ac4">unusedRangeSizeMax</a> = VMA_MIN(outInfo.<a class="code" href="struct_vma_stat_info.html#a5ba1a2476c4d39b10f7e2f7ebbb72ac4">unusedRangeSizeMax</a>, unusedRangeSize);</div>
+<div class="line"><a name="l09723"></a><span class="lineno"> 9723</span>&#160;                }</div>
+<div class="line"><a name="l09724"></a><span class="lineno"> 9724</span>&#160;            </div>
+<div class="line"><a name="l09725"></a><span class="lineno"> 9725</span>&#160;                <span class="comment">// 2. Process this allocation.</span></div>
+<div class="line"><a name="l09726"></a><span class="lineno"> 9726</span>&#160;                <span class="comment">// There is allocation with suballoc.offset, suballoc.size.</span></div>
+<div class="line"><a name="l09727"></a><span class="lineno"> 9727</span>&#160;                outInfo.<a class="code" href="struct_vma_stat_info.html#ab0c6c73837e5a70c749fbd4f6064895a">usedBytes</a> += suballoc.size;</div>
+<div class="line"><a name="l09728"></a><span class="lineno"> 9728</span>&#160;                outInfo.<a class="code" href="struct_vma_stat_info.html#ade8b40bd3139c04aabd2fc538a356fea">allocationSizeMin</a> = VMA_MIN(outInfo.<a class="code" href="struct_vma_stat_info.html#ade8b40bd3139c04aabd2fc538a356fea">allocationSizeMin</a>, suballoc.size);</div>
+<div class="line"><a name="l09729"></a><span class="lineno"> 9729</span>&#160;                outInfo.<a class="code" href="struct_vma_stat_info.html#a17e9733a5ecd76287d4db6e66f71f50c">allocationSizeMax</a> = VMA_MIN(outInfo.<a class="code" href="struct_vma_stat_info.html#a17e9733a5ecd76287d4db6e66f71f50c">allocationSizeMax</a>, suballoc.size);</div>
+<div class="line"><a name="l09730"></a><span class="lineno"> 9730</span>&#160;            </div>
+<div class="line"><a name="l09731"></a><span class="lineno"> 9731</span>&#160;                <span class="comment">// 3. Prepare for next iteration.</span></div>
+<div class="line"><a name="l09732"></a><span class="lineno"> 9732</span>&#160;                lastOffset = suballoc.offset + suballoc.size;</div>
+<div class="line"><a name="l09733"></a><span class="lineno"> 9733</span>&#160;                ++nextAlloc2ndIndex;</div>
+<div class="line"><a name="l09734"></a><span class="lineno"> 9734</span>&#160;            }</div>
+<div class="line"><a name="l09735"></a><span class="lineno"> 9735</span>&#160;            <span class="comment">// We are at the end.</span></div>
+<div class="line"><a name="l09736"></a><span class="lineno"> 9736</span>&#160;            <span class="keywordflow">else</span></div>
+<div class="line"><a name="l09737"></a><span class="lineno"> 9737</span>&#160;            {</div>
+<div class="line"><a name="l09738"></a><span class="lineno"> 9738</span>&#160;                <span class="comment">// There is free space from lastOffset to freeSpace2ndTo1stEnd.</span></div>
+<div class="line"><a name="l09739"></a><span class="lineno"> 9739</span>&#160;                <span class="keywordflow">if</span>(lastOffset &lt; freeSpace2ndTo1stEnd)</div>
+<div class="line"><a name="l09740"></a><span class="lineno"> 9740</span>&#160;                {</div>
+<div class="line"><a name="l09741"></a><span class="lineno"> 9741</span>&#160;                    <span class="keyword">const</span> VkDeviceSize unusedRangeSize = freeSpace2ndTo1stEnd - lastOffset;</div>
+<div class="line"><a name="l09742"></a><span class="lineno"> 9742</span>&#160;                    ++outInfo.<a class="code" href="struct_vma_stat_info.html#ae06129c771bfebfd6468a7f4276502a9">unusedRangeCount</a>;</div>
+<div class="line"><a name="l09743"></a><span class="lineno"> 9743</span>&#160;                    outInfo.<a class="code" href="struct_vma_stat_info.html#a1859d290aca2cd582d8dc25922092669">unusedBytes</a> += unusedRangeSize;</div>
+<div class="line"><a name="l09744"></a><span class="lineno"> 9744</span>&#160;                    outInfo.<a class="code" href="struct_vma_stat_info.html#aedeba931324f16589cd2416c0d2dd0d4">unusedRangeSizeMin</a> = VMA_MIN(outInfo.<a class="code" href="struct_vma_stat_info.html#aedeba931324f16589cd2416c0d2dd0d4">unusedRangeSizeMin</a>, unusedRangeSize);</div>
+<div class="line"><a name="l09745"></a><span class="lineno"> 9745</span>&#160;                    outInfo.<a class="code" href="struct_vma_stat_info.html#a5ba1a2476c4d39b10f7e2f7ebbb72ac4">unusedRangeSizeMax</a> = VMA_MIN(outInfo.<a class="code" href="struct_vma_stat_info.html#a5ba1a2476c4d39b10f7e2f7ebbb72ac4">unusedRangeSizeMax</a>, unusedRangeSize);</div>
+<div class="line"><a name="l09746"></a><span class="lineno"> 9746</span>&#160;               }</div>
+<div class="line"><a name="l09747"></a><span class="lineno"> 9747</span>&#160; </div>
+<div class="line"><a name="l09748"></a><span class="lineno"> 9748</span>&#160;                <span class="comment">// End of loop.</span></div>
+<div class="line"><a name="l09749"></a><span class="lineno"> 9749</span>&#160;                lastOffset = freeSpace2ndTo1stEnd;</div>
+<div class="line"><a name="l09750"></a><span class="lineno"> 9750</span>&#160;            }</div>
+<div class="line"><a name="l09751"></a><span class="lineno"> 9751</span>&#160;        }</div>
+<div class="line"><a name="l09752"></a><span class="lineno"> 9752</span>&#160;    }</div>
+<div class="line"><a name="l09753"></a><span class="lineno"> 9753</span>&#160; </div>
+<div class="line"><a name="l09754"></a><span class="lineno"> 9754</span>&#160;    <span class="keywordtype">size_t</span> nextAlloc1stIndex = m_1stNullItemsBeginCount;</div>
+<div class="line"><a name="l09755"></a><span class="lineno"> 9755</span>&#160;    <span class="keyword">const</span> VkDeviceSize freeSpace1stTo2ndEnd =</div>
+<div class="line"><a name="l09756"></a><span class="lineno"> 9756</span>&#160;        m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK ? suballocations2nd.back().offset : size;</div>
+<div class="line"><a name="l09757"></a><span class="lineno"> 9757</span>&#160;    <span class="keywordflow">while</span>(lastOffset &lt; freeSpace1stTo2ndEnd)</div>
+<div class="line"><a name="l09758"></a><span class="lineno"> 9758</span>&#160;    {</div>
+<div class="line"><a name="l09759"></a><span class="lineno"> 9759</span>&#160;        <span class="comment">// Find next non-null allocation or move nextAllocIndex to the end.</span></div>
+<div class="line"><a name="l09760"></a><span class="lineno"> 9760</span>&#160;        <span class="keywordflow">while</span>(nextAlloc1stIndex &lt; suballoc1stCount &amp;&amp;</div>
+<div class="line"><a name="l09761"></a><span class="lineno"> 9761</span>&#160;            suballocations1st[nextAlloc1stIndex].hAllocation == VK_NULL_HANDLE)</div>
+<div class="line"><a name="l09762"></a><span class="lineno"> 9762</span>&#160;        {</div>
+<div class="line"><a name="l09763"></a><span class="lineno"> 9763</span>&#160;            ++nextAlloc1stIndex;</div>
+<div class="line"><a name="l09764"></a><span class="lineno"> 9764</span>&#160;        }</div>
+<div class="line"><a name="l09765"></a><span class="lineno"> 9765</span>&#160; </div>
+<div class="line"><a name="l09766"></a><span class="lineno"> 9766</span>&#160;        <span class="comment">// Found non-null allocation.</span></div>
+<div class="line"><a name="l09767"></a><span class="lineno"> 9767</span>&#160;        <span class="keywordflow">if</span>(nextAlloc1stIndex &lt; suballoc1stCount)</div>
+<div class="line"><a name="l09768"></a><span class="lineno"> 9768</span>&#160;        {</div>
+<div class="line"><a name="l09769"></a><span class="lineno"> 9769</span>&#160;            <span class="keyword">const</span> VmaSuballocation&amp; suballoc = suballocations1st[nextAlloc1stIndex];</div>
+<div class="line"><a name="l09770"></a><span class="lineno"> 9770</span>&#160;            </div>
+<div class="line"><a name="l09771"></a><span class="lineno"> 9771</span>&#160;            <span class="comment">// 1. Process free space before this allocation.</span></div>
+<div class="line"><a name="l09772"></a><span class="lineno"> 9772</span>&#160;            <span class="keywordflow">if</span>(lastOffset &lt; suballoc.offset)</div>
+<div class="line"><a name="l09773"></a><span class="lineno"> 9773</span>&#160;            {</div>
+<div class="line"><a name="l09774"></a><span class="lineno"> 9774</span>&#160;                <span class="comment">// There is free space from lastOffset to suballoc.offset.</span></div>
+<div class="line"><a name="l09775"></a><span class="lineno"> 9775</span>&#160;                <span class="keyword">const</span> VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;</div>
+<div class="line"><a name="l09776"></a><span class="lineno"> 9776</span>&#160;                ++outInfo.<a class="code" href="struct_vma_stat_info.html#ae06129c771bfebfd6468a7f4276502a9">unusedRangeCount</a>;</div>
+<div class="line"><a name="l09777"></a><span class="lineno"> 9777</span>&#160;                outInfo.<a class="code" href="struct_vma_stat_info.html#a1859d290aca2cd582d8dc25922092669">unusedBytes</a> += unusedRangeSize;</div>
+<div class="line"><a name="l09778"></a><span class="lineno"> 9778</span>&#160;                outInfo.<a class="code" href="struct_vma_stat_info.html#aedeba931324f16589cd2416c0d2dd0d4">unusedRangeSizeMin</a> = VMA_MIN(outInfo.<a class="code" href="struct_vma_stat_info.html#aedeba931324f16589cd2416c0d2dd0d4">unusedRangeSizeMin</a>, unusedRangeSize);</div>
+<div class="line"><a name="l09779"></a><span class="lineno"> 9779</span>&#160;                outInfo.<a class="code" href="struct_vma_stat_info.html#a5ba1a2476c4d39b10f7e2f7ebbb72ac4">unusedRangeSizeMax</a> = VMA_MIN(outInfo.<a class="code" href="struct_vma_stat_info.html#a5ba1a2476c4d39b10f7e2f7ebbb72ac4">unusedRangeSizeMax</a>, unusedRangeSize);</div>
+<div class="line"><a name="l09780"></a><span class="lineno"> 9780</span>&#160;            }</div>
+<div class="line"><a name="l09781"></a><span class="lineno"> 9781</span>&#160;            </div>
+<div class="line"><a name="l09782"></a><span class="lineno"> 9782</span>&#160;            <span class="comment">// 2. Process this allocation.</span></div>
+<div class="line"><a name="l09783"></a><span class="lineno"> 9783</span>&#160;            <span class="comment">// There is allocation with suballoc.offset, suballoc.size.</span></div>
+<div class="line"><a name="l09784"></a><span class="lineno"> 9784</span>&#160;            outInfo.<a class="code" href="struct_vma_stat_info.html#ab0c6c73837e5a70c749fbd4f6064895a">usedBytes</a> += suballoc.size;</div>
+<div class="line"><a name="l09785"></a><span class="lineno"> 9785</span>&#160;            outInfo.<a class="code" href="struct_vma_stat_info.html#ade8b40bd3139c04aabd2fc538a356fea">allocationSizeMin</a> = VMA_MIN(outInfo.<a class="code" href="struct_vma_stat_info.html#ade8b40bd3139c04aabd2fc538a356fea">allocationSizeMin</a>, suballoc.size);</div>
+<div class="line"><a name="l09786"></a><span class="lineno"> 9786</span>&#160;            outInfo.<a class="code" href="struct_vma_stat_info.html#a17e9733a5ecd76287d4db6e66f71f50c">allocationSizeMax</a> = VMA_MIN(outInfo.<a class="code" href="struct_vma_stat_info.html#a17e9733a5ecd76287d4db6e66f71f50c">allocationSizeMax</a>, suballoc.size);</div>
+<div class="line"><a name="l09787"></a><span class="lineno"> 9787</span>&#160;            </div>
+<div class="line"><a name="l09788"></a><span class="lineno"> 9788</span>&#160;            <span class="comment">// 3. Prepare for next iteration.</span></div>
+<div class="line"><a name="l09789"></a><span class="lineno"> 9789</span>&#160;            lastOffset = suballoc.offset + suballoc.size;</div>
+<div class="line"><a name="l09790"></a><span class="lineno"> 9790</span>&#160;            ++nextAlloc1stIndex;</div>
+<div class="line"><a name="l09791"></a><span class="lineno"> 9791</span>&#160;        }</div>
+<div class="line"><a name="l09792"></a><span class="lineno"> 9792</span>&#160;        <span class="comment">// We are at the end.</span></div>
+<div class="line"><a name="l09793"></a><span class="lineno"> 9793</span>&#160;        <span class="keywordflow">else</span></div>
+<div class="line"><a name="l09794"></a><span class="lineno"> 9794</span>&#160;        {</div>
+<div class="line"><a name="l09795"></a><span class="lineno"> 9795</span>&#160;            <span class="comment">// There is free space from lastOffset to freeSpace1stTo2ndEnd.</span></div>
+<div class="line"><a name="l09796"></a><span class="lineno"> 9796</span>&#160;            <span class="keywordflow">if</span>(lastOffset &lt; freeSpace1stTo2ndEnd)</div>
+<div class="line"><a name="l09797"></a><span class="lineno"> 9797</span>&#160;            {</div>
+<div class="line"><a name="l09798"></a><span class="lineno"> 9798</span>&#160;                <span class="keyword">const</span> VkDeviceSize unusedRangeSize = freeSpace1stTo2ndEnd - lastOffset;</div>
+<div class="line"><a name="l09799"></a><span class="lineno"> 9799</span>&#160;                ++outInfo.<a class="code" href="struct_vma_stat_info.html#ae06129c771bfebfd6468a7f4276502a9">unusedRangeCount</a>;</div>
+<div class="line"><a name="l09800"></a><span class="lineno"> 9800</span>&#160;                outInfo.<a class="code" href="struct_vma_stat_info.html#a1859d290aca2cd582d8dc25922092669">unusedBytes</a> += unusedRangeSize;</div>
+<div class="line"><a name="l09801"></a><span class="lineno"> 9801</span>&#160;                outInfo.<a class="code" href="struct_vma_stat_info.html#aedeba931324f16589cd2416c0d2dd0d4">unusedRangeSizeMin</a> = VMA_MIN(outInfo.<a class="code" href="struct_vma_stat_info.html#aedeba931324f16589cd2416c0d2dd0d4">unusedRangeSizeMin</a>, unusedRangeSize);</div>
+<div class="line"><a name="l09802"></a><span class="lineno"> 9802</span>&#160;                outInfo.<a class="code" href="struct_vma_stat_info.html#a5ba1a2476c4d39b10f7e2f7ebbb72ac4">unusedRangeSizeMax</a> = VMA_MIN(outInfo.<a class="code" href="struct_vma_stat_info.html#a5ba1a2476c4d39b10f7e2f7ebbb72ac4">unusedRangeSizeMax</a>, unusedRangeSize);</div>
+<div class="line"><a name="l09803"></a><span class="lineno"> 9803</span>&#160;           }</div>
+<div class="line"><a name="l09804"></a><span class="lineno"> 9804</span>&#160; </div>
+<div class="line"><a name="l09805"></a><span class="lineno"> 9805</span>&#160;            <span class="comment">// End of loop.</span></div>
+<div class="line"><a name="l09806"></a><span class="lineno"> 9806</span>&#160;            lastOffset = freeSpace1stTo2ndEnd;</div>
+<div class="line"><a name="l09807"></a><span class="lineno"> 9807</span>&#160;        }</div>
+<div class="line"><a name="l09808"></a><span class="lineno"> 9808</span>&#160;    }</div>
+<div class="line"><a name="l09809"></a><span class="lineno"> 9809</span>&#160; </div>
+<div class="line"><a name="l09810"></a><span class="lineno"> 9810</span>&#160;    <span class="keywordflow">if</span>(m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)</div>
+<div class="line"><a name="l09811"></a><span class="lineno"> 9811</span>&#160;    {</div>
+<div class="line"><a name="l09812"></a><span class="lineno"> 9812</span>&#160;        <span class="keywordtype">size_t</span> nextAlloc2ndIndex = suballocations2nd.size() - 1;</div>
+<div class="line"><a name="l09813"></a><span class="lineno"> 9813</span>&#160;        <span class="keywordflow">while</span>(lastOffset &lt; size)</div>
+<div class="line"><a name="l09814"></a><span class="lineno"> 9814</span>&#160;        {</div>
+<div class="line"><a name="l09815"></a><span class="lineno"> 9815</span>&#160;            <span class="comment">// Find next non-null allocation or move nextAllocIndex to the end.</span></div>
+<div class="line"><a name="l09816"></a><span class="lineno"> 9816</span>&#160;            <span class="keywordflow">while</span>(nextAlloc2ndIndex != SIZE_MAX &amp;&amp;</div>
+<div class="line"><a name="l09817"></a><span class="lineno"> 9817</span>&#160;                suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE)</div>
+<div class="line"><a name="l09818"></a><span class="lineno"> 9818</span>&#160;            {</div>
+<div class="line"><a name="l09819"></a><span class="lineno"> 9819</span>&#160;                --nextAlloc2ndIndex;</div>
+<div class="line"><a name="l09820"></a><span class="lineno"> 9820</span>&#160;            }</div>
+<div class="line"><a name="l09821"></a><span class="lineno"> 9821</span>&#160; </div>
+<div class="line"><a name="l09822"></a><span class="lineno"> 9822</span>&#160;            <span class="comment">// Found non-null allocation.</span></div>
+<div class="line"><a name="l09823"></a><span class="lineno"> 9823</span>&#160;            <span class="keywordflow">if</span>(nextAlloc2ndIndex != SIZE_MAX)</div>
+<div class="line"><a name="l09824"></a><span class="lineno"> 9824</span>&#160;            {</div>
+<div class="line"><a name="l09825"></a><span class="lineno"> 9825</span>&#160;                <span class="keyword">const</span> VmaSuballocation&amp; suballoc = suballocations2nd[nextAlloc2ndIndex];</div>
+<div class="line"><a name="l09826"></a><span class="lineno"> 9826</span>&#160;            </div>
+<div class="line"><a name="l09827"></a><span class="lineno"> 9827</span>&#160;                <span class="comment">// 1. Process free space before this allocation.</span></div>
+<div class="line"><a name="l09828"></a><span class="lineno"> 9828</span>&#160;                <span class="keywordflow">if</span>(lastOffset &lt; suballoc.offset)</div>
+<div class="line"><a name="l09829"></a><span class="lineno"> 9829</span>&#160;                {</div>
+<div class="line"><a name="l09830"></a><span class="lineno"> 9830</span>&#160;                    <span class="comment">// There is free space from lastOffset to suballoc.offset.</span></div>
+<div class="line"><a name="l09831"></a><span class="lineno"> 9831</span>&#160;                    <span class="keyword">const</span> VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;</div>
+<div class="line"><a name="l09832"></a><span class="lineno"> 9832</span>&#160;                    ++outInfo.<a class="code" href="struct_vma_stat_info.html#ae06129c771bfebfd6468a7f4276502a9">unusedRangeCount</a>;</div>
+<div class="line"><a name="l09833"></a><span class="lineno"> 9833</span>&#160;                    outInfo.<a class="code" href="struct_vma_stat_info.html#a1859d290aca2cd582d8dc25922092669">unusedBytes</a> += unusedRangeSize;</div>
+<div class="line"><a name="l09834"></a><span class="lineno"> 9834</span>&#160;                    outInfo.<a class="code" href="struct_vma_stat_info.html#aedeba931324f16589cd2416c0d2dd0d4">unusedRangeSizeMin</a> = VMA_MIN(outInfo.<a class="code" href="struct_vma_stat_info.html#aedeba931324f16589cd2416c0d2dd0d4">unusedRangeSizeMin</a>, unusedRangeSize);</div>
+<div class="line"><a name="l09835"></a><span class="lineno"> 9835</span>&#160;                    outInfo.<a class="code" href="struct_vma_stat_info.html#a5ba1a2476c4d39b10f7e2f7ebbb72ac4">unusedRangeSizeMax</a> = VMA_MIN(outInfo.<a class="code" href="struct_vma_stat_info.html#a5ba1a2476c4d39b10f7e2f7ebbb72ac4">unusedRangeSizeMax</a>, unusedRangeSize);</div>
+<div class="line"><a name="l09836"></a><span class="lineno"> 9836</span>&#160;                }</div>
+<div class="line"><a name="l09837"></a><span class="lineno"> 9837</span>&#160;            </div>
+<div class="line"><a name="l09838"></a><span class="lineno"> 9838</span>&#160;                <span class="comment">// 2. Process this allocation.</span></div>
+<div class="line"><a name="l09839"></a><span class="lineno"> 9839</span>&#160;                <span class="comment">// There is allocation with suballoc.offset, suballoc.size.</span></div>
+<div class="line"><a name="l09840"></a><span class="lineno"> 9840</span>&#160;                outInfo.<a class="code" href="struct_vma_stat_info.html#ab0c6c73837e5a70c749fbd4f6064895a">usedBytes</a> += suballoc.size;</div>
+<div class="line"><a name="l09841"></a><span class="lineno"> 9841</span>&#160;                outInfo.<a class="code" href="struct_vma_stat_info.html#ade8b40bd3139c04aabd2fc538a356fea">allocationSizeMin</a> = VMA_MIN(outInfo.<a class="code" href="struct_vma_stat_info.html#ade8b40bd3139c04aabd2fc538a356fea">allocationSizeMin</a>, suballoc.size);</div>
+<div class="line"><a name="l09842"></a><span class="lineno"> 9842</span>&#160;                outInfo.<a class="code" href="struct_vma_stat_info.html#a17e9733a5ecd76287d4db6e66f71f50c">allocationSizeMax</a> = VMA_MIN(outInfo.<a class="code" href="struct_vma_stat_info.html#a17e9733a5ecd76287d4db6e66f71f50c">allocationSizeMax</a>, suballoc.size);</div>
+<div class="line"><a name="l09843"></a><span class="lineno"> 9843</span>&#160;            </div>
+<div class="line"><a name="l09844"></a><span class="lineno"> 9844</span>&#160;                <span class="comment">// 3. Prepare for next iteration.</span></div>
+<div class="line"><a name="l09845"></a><span class="lineno"> 9845</span>&#160;                lastOffset = suballoc.offset + suballoc.size;</div>
+<div class="line"><a name="l09846"></a><span class="lineno"> 9846</span>&#160;                --nextAlloc2ndIndex;</div>
+<div class="line"><a name="l09847"></a><span class="lineno"> 9847</span>&#160;            }</div>
+<div class="line"><a name="l09848"></a><span class="lineno"> 9848</span>&#160;            <span class="comment">// We are at the end.</span></div>
+<div class="line"><a name="l09849"></a><span class="lineno"> 9849</span>&#160;            <span class="keywordflow">else</span></div>
+<div class="line"><a name="l09850"></a><span class="lineno"> 9850</span>&#160;            {</div>
+<div class="line"><a name="l09851"></a><span class="lineno"> 9851</span>&#160;                <span class="comment">// There is free space from lastOffset to size.</span></div>
+<div class="line"><a name="l09852"></a><span class="lineno"> 9852</span>&#160;                <span class="keywordflow">if</span>(lastOffset &lt; size)</div>
+<div class="line"><a name="l09853"></a><span class="lineno"> 9853</span>&#160;                {</div>
+<div class="line"><a name="l09854"></a><span class="lineno"> 9854</span>&#160;                    <span class="keyword">const</span> VkDeviceSize unusedRangeSize = size - lastOffset;</div>
+<div class="line"><a name="l09855"></a><span class="lineno"> 9855</span>&#160;                    ++outInfo.<a class="code" href="struct_vma_stat_info.html#ae06129c771bfebfd6468a7f4276502a9">unusedRangeCount</a>;</div>
+<div class="line"><a name="l09856"></a><span class="lineno"> 9856</span>&#160;                    outInfo.<a class="code" href="struct_vma_stat_info.html#a1859d290aca2cd582d8dc25922092669">unusedBytes</a> += unusedRangeSize;</div>
+<div class="line"><a name="l09857"></a><span class="lineno"> 9857</span>&#160;                    outInfo.<a class="code" href="struct_vma_stat_info.html#aedeba931324f16589cd2416c0d2dd0d4">unusedRangeSizeMin</a> = VMA_MIN(outInfo.<a class="code" href="struct_vma_stat_info.html#aedeba931324f16589cd2416c0d2dd0d4">unusedRangeSizeMin</a>, unusedRangeSize);</div>
+<div class="line"><a name="l09858"></a><span class="lineno"> 9858</span>&#160;                    outInfo.<a class="code" href="struct_vma_stat_info.html#a5ba1a2476c4d39b10f7e2f7ebbb72ac4">unusedRangeSizeMax</a> = VMA_MIN(outInfo.<a class="code" href="struct_vma_stat_info.html#a5ba1a2476c4d39b10f7e2f7ebbb72ac4">unusedRangeSizeMax</a>, unusedRangeSize);</div>
+<div class="line"><a name="l09859"></a><span class="lineno"> 9859</span>&#160;               }</div>
+<div class="line"><a name="l09860"></a><span class="lineno"> 9860</span>&#160; </div>
+<div class="line"><a name="l09861"></a><span class="lineno"> 9861</span>&#160;                <span class="comment">// End of loop.</span></div>
+<div class="line"><a name="l09862"></a><span class="lineno"> 9862</span>&#160;                lastOffset = size;</div>
+<div class="line"><a name="l09863"></a><span class="lineno"> 9863</span>&#160;            }</div>
+<div class="line"><a name="l09864"></a><span class="lineno"> 9864</span>&#160;        }</div>
+<div class="line"><a name="l09865"></a><span class="lineno"> 9865</span>&#160;    }</div>
+<div class="line"><a name="l09866"></a><span class="lineno"> 9866</span>&#160; </div>
+<div class="line"><a name="l09867"></a><span class="lineno"> 9867</span>&#160;    outInfo.<a class="code" href="struct_vma_stat_info.html#a1859d290aca2cd582d8dc25922092669">unusedBytes</a> = size - outInfo.<a class="code" href="struct_vma_stat_info.html#ab0c6c73837e5a70c749fbd4f6064895a">usedBytes</a>;</div>
+<div class="line"><a name="l09868"></a><span class="lineno"> 9868</span>&#160;}</div>
+<div class="line"><a name="l09869"></a><span class="lineno"> 9869</span>&#160; </div>
+<div class="line"><a name="l09870"></a><span class="lineno"> 9870</span>&#160;<span class="keywordtype">void</span> VmaBlockMetadata_Linear::AddPoolStats(<a class="code" href="struct_vma_pool_stats.html">VmaPoolStats</a>&amp; inoutStats)<span class="keyword"> const</span></div>
+<div class="line"><a name="l09871"></a><span class="lineno"> 9871</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l09872"></a><span class="lineno"> 9872</span>&#160;    <span class="keyword">const</span> SuballocationVectorType&amp; suballocations1st = AccessSuballocations1st();</div>
+<div class="line"><a name="l09873"></a><span class="lineno"> 9873</span>&#160;    <span class="keyword">const</span> SuballocationVectorType&amp; suballocations2nd = AccessSuballocations2nd();</div>
+<div class="line"><a name="l09874"></a><span class="lineno"> 9874</span>&#160;    <span class="keyword">const</span> VkDeviceSize size = GetSize();</div>
+<div class="line"><a name="l09875"></a><span class="lineno"> 9875</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">size_t</span> suballoc1stCount = suballocations1st.size();</div>
+<div class="line"><a name="l09876"></a><span class="lineno"> 9876</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">size_t</span> suballoc2ndCount = suballocations2nd.size();</div>
+<div class="line"><a name="l09877"></a><span class="lineno"> 9877</span>&#160; </div>
+<div class="line"><a name="l09878"></a><span class="lineno"> 9878</span>&#160;    inoutStats.<a class="code" href="struct_vma_pool_stats.html#a326807b2de2b0931cee4ed9a5f2e420c">size</a> += size;</div>
+<div class="line"><a name="l09879"></a><span class="lineno"> 9879</span>&#160; </div>
+<div class="line"><a name="l09880"></a><span class="lineno"> 9880</span>&#160;    VkDeviceSize lastOffset = 0;</div>
+<div class="line"><a name="l09881"></a><span class="lineno"> 9881</span>&#160; </div>
+<div class="line"><a name="l09882"></a><span class="lineno"> 9882</span>&#160;    <span class="keywordflow">if</span>(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)</div>
+<div class="line"><a name="l09883"></a><span class="lineno"> 9883</span>&#160;    {</div>
+<div class="line"><a name="l09884"></a><span class="lineno"> 9884</span>&#160;        <span class="keyword">const</span> VkDeviceSize freeSpace2ndTo1stEnd = suballocations1st[m_1stNullItemsBeginCount].offset;</div>
+<div class="line"><a name="l09885"></a><span class="lineno"> 9885</span>&#160;        <span class="keywordtype">size_t</span> nextAlloc2ndIndex = m_1stNullItemsBeginCount;</div>
+<div class="line"><a name="l09886"></a><span class="lineno"> 9886</span>&#160;        <span class="keywordflow">while</span>(lastOffset &lt; freeSpace2ndTo1stEnd)</div>
+<div class="line"><a name="l09887"></a><span class="lineno"> 9887</span>&#160;        {</div>
+<div class="line"><a name="l09888"></a><span class="lineno"> 9888</span>&#160;            <span class="comment">// Find next non-null allocation or move nextAlloc2ndIndex to the end.</span></div>
+<div class="line"><a name="l09889"></a><span class="lineno"> 9889</span>&#160;            <span class="keywordflow">while</span>(nextAlloc2ndIndex &lt; suballoc2ndCount &amp;&amp;</div>
+<div class="line"><a name="l09890"></a><span class="lineno"> 9890</span>&#160;                suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE)</div>
+<div class="line"><a name="l09891"></a><span class="lineno"> 9891</span>&#160;            {</div>
+<div class="line"><a name="l09892"></a><span class="lineno"> 9892</span>&#160;                ++nextAlloc2ndIndex;</div>
+<div class="line"><a name="l09893"></a><span class="lineno"> 9893</span>&#160;            }</div>
+<div class="line"><a name="l09894"></a><span class="lineno"> 9894</span>&#160; </div>
+<div class="line"><a name="l09895"></a><span class="lineno"> 9895</span>&#160;            <span class="comment">// Found non-null allocation.</span></div>
+<div class="line"><a name="l09896"></a><span class="lineno"> 9896</span>&#160;            <span class="keywordflow">if</span>(nextAlloc2ndIndex &lt; suballoc2ndCount)</div>
+<div class="line"><a name="l09897"></a><span class="lineno"> 9897</span>&#160;            {</div>
+<div class="line"><a name="l09898"></a><span class="lineno"> 9898</span>&#160;                <span class="keyword">const</span> VmaSuballocation&amp; suballoc = suballocations2nd[nextAlloc2ndIndex];</div>
+<div class="line"><a name="l09899"></a><span class="lineno"> 9899</span>&#160;            </div>
+<div class="line"><a name="l09900"></a><span class="lineno"> 9900</span>&#160;                <span class="comment">// 1. Process free space before this allocation.</span></div>
+<div class="line"><a name="l09901"></a><span class="lineno"> 9901</span>&#160;                <span class="keywordflow">if</span>(lastOffset &lt; suballoc.offset)</div>
+<div class="line"><a name="l09902"></a><span class="lineno"> 9902</span>&#160;                {</div>
+<div class="line"><a name="l09903"></a><span class="lineno"> 9903</span>&#160;                    <span class="comment">// There is free space from lastOffset to suballoc.offset.</span></div>
+<div class="line"><a name="l09904"></a><span class="lineno"> 9904</span>&#160;                    <span class="keyword">const</span> VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;</div>
+<div class="line"><a name="l09905"></a><span class="lineno"> 9905</span>&#160;                    inoutStats.<a class="code" href="struct_vma_pool_stats.html#ad7c54874724fce7b06aba526202d82a8">unusedSize</a> += unusedRangeSize;</div>
+<div class="line"><a name="l09906"></a><span class="lineno"> 9906</span>&#160;                    ++inoutStats.<a class="code" href="struct_vma_pool_stats.html#ae4f3546ffa4d1e598b64d8e6134854f4">unusedRangeCount</a>;</div>
+<div class="line"><a name="l09907"></a><span class="lineno"> 9907</span>&#160;                    inoutStats.<a class="code" href="struct_vma_pool_stats.html#ab4c8f52dd42ab01998f60f0b6acc722b">unusedRangeSizeMax</a> = VMA_MAX(inoutStats.<a class="code" href="struct_vma_pool_stats.html#ab4c8f52dd42ab01998f60f0b6acc722b">unusedRangeSizeMax</a>, unusedRangeSize);</div>
+<div class="line"><a name="l09908"></a><span class="lineno"> 9908</span>&#160;                }</div>
+<div class="line"><a name="l09909"></a><span class="lineno"> 9909</span>&#160;            </div>
+<div class="line"><a name="l09910"></a><span class="lineno"> 9910</span>&#160;                <span class="comment">// 2. Process this allocation.</span></div>
+<div class="line"><a name="l09911"></a><span class="lineno"> 9911</span>&#160;                <span class="comment">// There is allocation with suballoc.offset, suballoc.size.</span></div>
+<div class="line"><a name="l09912"></a><span class="lineno"> 9912</span>&#160;                ++inoutStats.<a class="code" href="struct_vma_pool_stats.html#ad1924eb54fffa45e9e0e65670c8fe5eb">allocationCount</a>;</div>
+<div class="line"><a name="l09913"></a><span class="lineno"> 9913</span>&#160;            </div>
+<div class="line"><a name="l09914"></a><span class="lineno"> 9914</span>&#160;                <span class="comment">// 3. Prepare for next iteration.</span></div>
+<div class="line"><a name="l09915"></a><span class="lineno"> 9915</span>&#160;                lastOffset = suballoc.offset + suballoc.size;</div>
+<div class="line"><a name="l09916"></a><span class="lineno"> 9916</span>&#160;                ++nextAlloc2ndIndex;</div>
+<div class="line"><a name="l09917"></a><span class="lineno"> 9917</span>&#160;            }</div>
+<div class="line"><a name="l09918"></a><span class="lineno"> 9918</span>&#160;            <span class="comment">// We are at the end.</span></div>
+<div class="line"><a name="l09919"></a><span class="lineno"> 9919</span>&#160;            <span class="keywordflow">else</span></div>
+<div class="line"><a name="l09920"></a><span class="lineno"> 9920</span>&#160;            {</div>
+<div class="line"><a name="l09921"></a><span class="lineno"> 9921</span>&#160;                <span class="keywordflow">if</span>(lastOffset &lt; freeSpace2ndTo1stEnd)</div>
+<div class="line"><a name="l09922"></a><span class="lineno"> 9922</span>&#160;                {</div>
+<div class="line"><a name="l09923"></a><span class="lineno"> 9923</span>&#160;                    <span class="comment">// There is free space from lastOffset to freeSpace2ndTo1stEnd.</span></div>
+<div class="line"><a name="l09924"></a><span class="lineno"> 9924</span>&#160;                    <span class="keyword">const</span> VkDeviceSize unusedRangeSize = freeSpace2ndTo1stEnd - lastOffset;</div>
+<div class="line"><a name="l09925"></a><span class="lineno"> 9925</span>&#160;                    inoutStats.<a class="code" href="struct_vma_pool_stats.html#ad7c54874724fce7b06aba526202d82a8">unusedSize</a> += unusedRangeSize;</div>
+<div class="line"><a name="l09926"></a><span class="lineno"> 9926</span>&#160;                    ++inoutStats.<a class="code" href="struct_vma_pool_stats.html#ae4f3546ffa4d1e598b64d8e6134854f4">unusedRangeCount</a>;</div>
+<div class="line"><a name="l09927"></a><span class="lineno"> 9927</span>&#160;                    inoutStats.<a class="code" href="struct_vma_pool_stats.html#ab4c8f52dd42ab01998f60f0b6acc722b">unusedRangeSizeMax</a> = VMA_MAX(inoutStats.<a class="code" href="struct_vma_pool_stats.html#ab4c8f52dd42ab01998f60f0b6acc722b">unusedRangeSizeMax</a>, unusedRangeSize);</div>
+<div class="line"><a name="l09928"></a><span class="lineno"> 9928</span>&#160;                }</div>
+<div class="line"><a name="l09929"></a><span class="lineno"> 9929</span>&#160; </div>
+<div class="line"><a name="l09930"></a><span class="lineno"> 9930</span>&#160;                <span class="comment">// End of loop.</span></div>
+<div class="line"><a name="l09931"></a><span class="lineno"> 9931</span>&#160;                lastOffset = freeSpace2ndTo1stEnd;</div>
+<div class="line"><a name="l09932"></a><span class="lineno"> 9932</span>&#160;            }</div>
+<div class="line"><a name="l09933"></a><span class="lineno"> 9933</span>&#160;        }</div>
+<div class="line"><a name="l09934"></a><span class="lineno"> 9934</span>&#160;    }</div>
+<div class="line"><a name="l09935"></a><span class="lineno"> 9935</span>&#160; </div>
+<div class="line"><a name="l09936"></a><span class="lineno"> 9936</span>&#160;    <span class="keywordtype">size_t</span> nextAlloc1stIndex = m_1stNullItemsBeginCount;</div>
+<div class="line"><a name="l09937"></a><span class="lineno"> 9937</span>&#160;    <span class="keyword">const</span> VkDeviceSize freeSpace1stTo2ndEnd =</div>
+<div class="line"><a name="l09938"></a><span class="lineno"> 9938</span>&#160;        m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK ? suballocations2nd.back().offset : size;</div>
+<div class="line"><a name="l09939"></a><span class="lineno"> 9939</span>&#160;    <span class="keywordflow">while</span>(lastOffset &lt; freeSpace1stTo2ndEnd)</div>
+<div class="line"><a name="l09940"></a><span class="lineno"> 9940</span>&#160;    {</div>
+<div class="line"><a name="l09941"></a><span class="lineno"> 9941</span>&#160;        <span class="comment">// Find next non-null allocation or move nextAllocIndex to the end.</span></div>
+<div class="line"><a name="l09942"></a><span class="lineno"> 9942</span>&#160;        <span class="keywordflow">while</span>(nextAlloc1stIndex &lt; suballoc1stCount &amp;&amp;</div>
+<div class="line"><a name="l09943"></a><span class="lineno"> 9943</span>&#160;            suballocations1st[nextAlloc1stIndex].hAllocation == VK_NULL_HANDLE)</div>
+<div class="line"><a name="l09944"></a><span class="lineno"> 9944</span>&#160;        {</div>
+<div class="line"><a name="l09945"></a><span class="lineno"> 9945</span>&#160;            ++nextAlloc1stIndex;</div>
+<div class="line"><a name="l09946"></a><span class="lineno"> 9946</span>&#160;        }</div>
+<div class="line"><a name="l09947"></a><span class="lineno"> 9947</span>&#160; </div>
+<div class="line"><a name="l09948"></a><span class="lineno"> 9948</span>&#160;        <span class="comment">// Found non-null allocation.</span></div>
+<div class="line"><a name="l09949"></a><span class="lineno"> 9949</span>&#160;        <span class="keywordflow">if</span>(nextAlloc1stIndex &lt; suballoc1stCount)</div>
+<div class="line"><a name="l09950"></a><span class="lineno"> 9950</span>&#160;        {</div>
+<div class="line"><a name="l09951"></a><span class="lineno"> 9951</span>&#160;            <span class="keyword">const</span> VmaSuballocation&amp; suballoc = suballocations1st[nextAlloc1stIndex];</div>
+<div class="line"><a name="l09952"></a><span class="lineno"> 9952</span>&#160;            </div>
+<div class="line"><a name="l09953"></a><span class="lineno"> 9953</span>&#160;            <span class="comment">// 1. Process free space before this allocation.</span></div>
+<div class="line"><a name="l09954"></a><span class="lineno"> 9954</span>&#160;            <span class="keywordflow">if</span>(lastOffset &lt; suballoc.offset)</div>
+<div class="line"><a name="l09955"></a><span class="lineno"> 9955</span>&#160;            {</div>
+<div class="line"><a name="l09956"></a><span class="lineno"> 9956</span>&#160;                <span class="comment">// There is free space from lastOffset to suballoc.offset.</span></div>
+<div class="line"><a name="l09957"></a><span class="lineno"> 9957</span>&#160;                <span class="keyword">const</span> VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;</div>
+<div class="line"><a name="l09958"></a><span class="lineno"> 9958</span>&#160;                inoutStats.<a class="code" href="struct_vma_pool_stats.html#ad7c54874724fce7b06aba526202d82a8">unusedSize</a> += unusedRangeSize;</div>
+<div class="line"><a name="l09959"></a><span class="lineno"> 9959</span>&#160;                ++inoutStats.<a class="code" href="struct_vma_pool_stats.html#ae4f3546ffa4d1e598b64d8e6134854f4">unusedRangeCount</a>;</div>
+<div class="line"><a name="l09960"></a><span class="lineno"> 9960</span>&#160;                inoutStats.<a class="code" href="struct_vma_pool_stats.html#ab4c8f52dd42ab01998f60f0b6acc722b">unusedRangeSizeMax</a> = VMA_MAX(inoutStats.<a class="code" href="struct_vma_pool_stats.html#ab4c8f52dd42ab01998f60f0b6acc722b">unusedRangeSizeMax</a>, unusedRangeSize);</div>
+<div class="line"><a name="l09961"></a><span class="lineno"> 9961</span>&#160;            }</div>
+<div class="line"><a name="l09962"></a><span class="lineno"> 9962</span>&#160;            </div>
+<div class="line"><a name="l09963"></a><span class="lineno"> 9963</span>&#160;            <span class="comment">// 2. Process this allocation.</span></div>
+<div class="line"><a name="l09964"></a><span class="lineno"> 9964</span>&#160;            <span class="comment">// There is allocation with suballoc.offset, suballoc.size.</span></div>
+<div class="line"><a name="l09965"></a><span class="lineno"> 9965</span>&#160;            ++inoutStats.<a class="code" href="struct_vma_pool_stats.html#ad1924eb54fffa45e9e0e65670c8fe5eb">allocationCount</a>;</div>
+<div class="line"><a name="l09966"></a><span class="lineno"> 9966</span>&#160;            </div>
+<div class="line"><a name="l09967"></a><span class="lineno"> 9967</span>&#160;            <span class="comment">// 3. Prepare for next iteration.</span></div>
+<div class="line"><a name="l09968"></a><span class="lineno"> 9968</span>&#160;            lastOffset = suballoc.offset + suballoc.size;</div>
+<div class="line"><a name="l09969"></a><span class="lineno"> 9969</span>&#160;            ++nextAlloc1stIndex;</div>
+<div class="line"><a name="l09970"></a><span class="lineno"> 9970</span>&#160;        }</div>
+<div class="line"><a name="l09971"></a><span class="lineno"> 9971</span>&#160;        <span class="comment">// We are at the end.</span></div>
+<div class="line"><a name="l09972"></a><span class="lineno"> 9972</span>&#160;        <span class="keywordflow">else</span></div>
+<div class="line"><a name="l09973"></a><span class="lineno"> 9973</span>&#160;        {</div>
+<div class="line"><a name="l09974"></a><span class="lineno"> 9974</span>&#160;            <span class="keywordflow">if</span>(lastOffset &lt; freeSpace1stTo2ndEnd)</div>
+<div class="line"><a name="l09975"></a><span class="lineno"> 9975</span>&#160;            {</div>
+<div class="line"><a name="l09976"></a><span class="lineno"> 9976</span>&#160;                <span class="comment">// There is free space from lastOffset to freeSpace1stTo2ndEnd.</span></div>
+<div class="line"><a name="l09977"></a><span class="lineno"> 9977</span>&#160;                <span class="keyword">const</span> VkDeviceSize unusedRangeSize = freeSpace1stTo2ndEnd - lastOffset;</div>
+<div class="line"><a name="l09978"></a><span class="lineno"> 9978</span>&#160;                inoutStats.<a class="code" href="struct_vma_pool_stats.html#ad7c54874724fce7b06aba526202d82a8">unusedSize</a> += unusedRangeSize;</div>
+<div class="line"><a name="l09979"></a><span class="lineno"> 9979</span>&#160;                ++inoutStats.<a class="code" href="struct_vma_pool_stats.html#ae4f3546ffa4d1e598b64d8e6134854f4">unusedRangeCount</a>;</div>
+<div class="line"><a name="l09980"></a><span class="lineno"> 9980</span>&#160;                inoutStats.<a class="code" href="struct_vma_pool_stats.html#ab4c8f52dd42ab01998f60f0b6acc722b">unusedRangeSizeMax</a> = VMA_MAX(inoutStats.<a class="code" href="struct_vma_pool_stats.html#ab4c8f52dd42ab01998f60f0b6acc722b">unusedRangeSizeMax</a>, unusedRangeSize);</div>
+<div class="line"><a name="l09981"></a><span class="lineno"> 9981</span>&#160;            }</div>
+<div class="line"><a name="l09982"></a><span class="lineno"> 9982</span>&#160; </div>
+<div class="line"><a name="l09983"></a><span class="lineno"> 9983</span>&#160;            <span class="comment">// End of loop.</span></div>
+<div class="line"><a name="l09984"></a><span class="lineno"> 9984</span>&#160;            lastOffset = freeSpace1stTo2ndEnd;</div>
+<div class="line"><a name="l09985"></a><span class="lineno"> 9985</span>&#160;        }</div>
+<div class="line"><a name="l09986"></a><span class="lineno"> 9986</span>&#160;    }</div>
+<div class="line"><a name="l09987"></a><span class="lineno"> 9987</span>&#160; </div>
+<div class="line"><a name="l09988"></a><span class="lineno"> 9988</span>&#160;    <span class="keywordflow">if</span>(m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)</div>
+<div class="line"><a name="l09989"></a><span class="lineno"> 9989</span>&#160;    {</div>
+<div class="line"><a name="l09990"></a><span class="lineno"> 9990</span>&#160;        <span class="keywordtype">size_t</span> nextAlloc2ndIndex = suballocations2nd.size() - 1;</div>
+<div class="line"><a name="l09991"></a><span class="lineno"> 9991</span>&#160;        <span class="keywordflow">while</span>(lastOffset &lt; size)</div>
+<div class="line"><a name="l09992"></a><span class="lineno"> 9992</span>&#160;        {</div>
+<div class="line"><a name="l09993"></a><span class="lineno"> 9993</span>&#160;            <span class="comment">// Find next non-null allocation or move nextAlloc2ndIndex to the end.</span></div>
+<div class="line"><a name="l09994"></a><span class="lineno"> 9994</span>&#160;            <span class="keywordflow">while</span>(nextAlloc2ndIndex != SIZE_MAX &amp;&amp;</div>
+<div class="line"><a name="l09995"></a><span class="lineno"> 9995</span>&#160;                suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE)</div>
+<div class="line"><a name="l09996"></a><span class="lineno"> 9996</span>&#160;            {</div>
+<div class="line"><a name="l09997"></a><span class="lineno"> 9997</span>&#160;                --nextAlloc2ndIndex;</div>
+<div class="line"><a name="l09998"></a><span class="lineno"> 9998</span>&#160;            }</div>
+<div class="line"><a name="l09999"></a><span class="lineno"> 9999</span>&#160; </div>
+<div class="line"><a name="l10000"></a><span class="lineno">10000</span>&#160;            <span class="comment">// Found non-null allocation.</span></div>
+<div class="line"><a name="l10001"></a><span class="lineno">10001</span>&#160;            <span class="keywordflow">if</span>(nextAlloc2ndIndex != SIZE_MAX)</div>
+<div class="line"><a name="l10002"></a><span class="lineno">10002</span>&#160;            {</div>
+<div class="line"><a name="l10003"></a><span class="lineno">10003</span>&#160;                <span class="keyword">const</span> VmaSuballocation&amp; suballoc = suballocations2nd[nextAlloc2ndIndex];</div>
+<div class="line"><a name="l10004"></a><span class="lineno">10004</span>&#160;            </div>
+<div class="line"><a name="l10005"></a><span class="lineno">10005</span>&#160;                <span class="comment">// 1. Process free space before this allocation.</span></div>
+<div class="line"><a name="l10006"></a><span class="lineno">10006</span>&#160;                <span class="keywordflow">if</span>(lastOffset &lt; suballoc.offset)</div>
+<div class="line"><a name="l10007"></a><span class="lineno">10007</span>&#160;                {</div>
+<div class="line"><a name="l10008"></a><span class="lineno">10008</span>&#160;                    <span class="comment">// There is free space from lastOffset to suballoc.offset.</span></div>
+<div class="line"><a name="l10009"></a><span class="lineno">10009</span>&#160;                    <span class="keyword">const</span> VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;</div>
+<div class="line"><a name="l10010"></a><span class="lineno">10010</span>&#160;                    inoutStats.<a class="code" href="struct_vma_pool_stats.html#ad7c54874724fce7b06aba526202d82a8">unusedSize</a> += unusedRangeSize;</div>
+<div class="line"><a name="l10011"></a><span class="lineno">10011</span>&#160;                    ++inoutStats.<a class="code" href="struct_vma_pool_stats.html#ae4f3546ffa4d1e598b64d8e6134854f4">unusedRangeCount</a>;</div>
+<div class="line"><a name="l10012"></a><span class="lineno">10012</span>&#160;                    inoutStats.<a class="code" href="struct_vma_pool_stats.html#ab4c8f52dd42ab01998f60f0b6acc722b">unusedRangeSizeMax</a> = VMA_MAX(inoutStats.<a class="code" href="struct_vma_pool_stats.html#ab4c8f52dd42ab01998f60f0b6acc722b">unusedRangeSizeMax</a>, unusedRangeSize);</div>
+<div class="line"><a name="l10013"></a><span class="lineno">10013</span>&#160;                }</div>
+<div class="line"><a name="l10014"></a><span class="lineno">10014</span>&#160;            </div>
+<div class="line"><a name="l10015"></a><span class="lineno">10015</span>&#160;                <span class="comment">// 2. Process this allocation.</span></div>
+<div class="line"><a name="l10016"></a><span class="lineno">10016</span>&#160;                <span class="comment">// There is allocation with suballoc.offset, suballoc.size.</span></div>
+<div class="line"><a name="l10017"></a><span class="lineno">10017</span>&#160;                ++inoutStats.<a class="code" href="struct_vma_pool_stats.html#ad1924eb54fffa45e9e0e65670c8fe5eb">allocationCount</a>;</div>
+<div class="line"><a name="l10018"></a><span class="lineno">10018</span>&#160;            </div>
+<div class="line"><a name="l10019"></a><span class="lineno">10019</span>&#160;                <span class="comment">// 3. Prepare for next iteration.</span></div>
+<div class="line"><a name="l10020"></a><span class="lineno">10020</span>&#160;                lastOffset = suballoc.offset + suballoc.size;</div>
+<div class="line"><a name="l10021"></a><span class="lineno">10021</span>&#160;                --nextAlloc2ndIndex;</div>
+<div class="line"><a name="l10022"></a><span class="lineno">10022</span>&#160;            }</div>
+<div class="line"><a name="l10023"></a><span class="lineno">10023</span>&#160;            <span class="comment">// We are at the end.</span></div>
+<div class="line"><a name="l10024"></a><span class="lineno">10024</span>&#160;            <span class="keywordflow">else</span></div>
+<div class="line"><a name="l10025"></a><span class="lineno">10025</span>&#160;            {</div>
+<div class="line"><a name="l10026"></a><span class="lineno">10026</span>&#160;                <span class="keywordflow">if</span>(lastOffset &lt; size)</div>
+<div class="line"><a name="l10027"></a><span class="lineno">10027</span>&#160;                {</div>
+<div class="line"><a name="l10028"></a><span class="lineno">10028</span>&#160;                    <span class="comment">// There is free space from lastOffset to size.</span></div>
+<div class="line"><a name="l10029"></a><span class="lineno">10029</span>&#160;                    <span class="keyword">const</span> VkDeviceSize unusedRangeSize = size - lastOffset;</div>
+<div class="line"><a name="l10030"></a><span class="lineno">10030</span>&#160;                    inoutStats.<a class="code" href="struct_vma_pool_stats.html#ad7c54874724fce7b06aba526202d82a8">unusedSize</a> += unusedRangeSize;</div>
+<div class="line"><a name="l10031"></a><span class="lineno">10031</span>&#160;                    ++inoutStats.<a class="code" href="struct_vma_pool_stats.html#ae4f3546ffa4d1e598b64d8e6134854f4">unusedRangeCount</a>;</div>
+<div class="line"><a name="l10032"></a><span class="lineno">10032</span>&#160;                    inoutStats.<a class="code" href="struct_vma_pool_stats.html#ab4c8f52dd42ab01998f60f0b6acc722b">unusedRangeSizeMax</a> = VMA_MAX(inoutStats.<a class="code" href="struct_vma_pool_stats.html#ab4c8f52dd42ab01998f60f0b6acc722b">unusedRangeSizeMax</a>, unusedRangeSize);</div>
+<div class="line"><a name="l10033"></a><span class="lineno">10033</span>&#160;                }</div>
+<div class="line"><a name="l10034"></a><span class="lineno">10034</span>&#160; </div>
+<div class="line"><a name="l10035"></a><span class="lineno">10035</span>&#160;                <span class="comment">// End of loop.</span></div>
+<div class="line"><a name="l10036"></a><span class="lineno">10036</span>&#160;                lastOffset = size;</div>
+<div class="line"><a name="l10037"></a><span class="lineno">10037</span>&#160;            }</div>
+<div class="line"><a name="l10038"></a><span class="lineno">10038</span>&#160;        }</div>
+<div class="line"><a name="l10039"></a><span class="lineno">10039</span>&#160;    }</div>
+<div class="line"><a name="l10040"></a><span class="lineno">10040</span>&#160;}</div>
+<div class="line"><a name="l10041"></a><span class="lineno">10041</span>&#160; </div>
+<div class="line"><a name="l10042"></a><span class="lineno">10042</span>&#160;<span class="preprocessor">#if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l10043"></a><span class="lineno">10043</span>&#160;<span class="keywordtype">void</span> VmaBlockMetadata_Linear::PrintDetailedMap(<span class="keyword">class</span> VmaJsonWriter&amp; json)<span class="keyword"> const</span></div>
+<div class="line"><a name="l10044"></a><span class="lineno">10044</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l10045"></a><span class="lineno">10045</span>&#160;    <span class="keyword">const</span> VkDeviceSize size = GetSize();</div>
+<div class="line"><a name="l10046"></a><span class="lineno">10046</span>&#160;    <span class="keyword">const</span> SuballocationVectorType&amp; suballocations1st = AccessSuballocations1st();</div>
+<div class="line"><a name="l10047"></a><span class="lineno">10047</span>&#160;    <span class="keyword">const</span> SuballocationVectorType&amp; suballocations2nd = AccessSuballocations2nd();</div>
+<div class="line"><a name="l10048"></a><span class="lineno">10048</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">size_t</span> suballoc1stCount = suballocations1st.size();</div>
+<div class="line"><a name="l10049"></a><span class="lineno">10049</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">size_t</span> suballoc2ndCount = suballocations2nd.size();</div>
+<div class="line"><a name="l10050"></a><span class="lineno">10050</span>&#160; </div>
+<div class="line"><a name="l10051"></a><span class="lineno">10051</span>&#160;    <span class="comment">// FIRST PASS</span></div>
+<div class="line"><a name="l10052"></a><span class="lineno">10052</span>&#160; </div>
+<div class="line"><a name="l10053"></a><span class="lineno">10053</span>&#160;    <span class="keywordtype">size_t</span> unusedRangeCount = 0;</div>
+<div class="line"><a name="l10054"></a><span class="lineno">10054</span>&#160;    VkDeviceSize usedBytes = 0;</div>
+<div class="line"><a name="l10055"></a><span class="lineno">10055</span>&#160; </div>
+<div class="line"><a name="l10056"></a><span class="lineno">10056</span>&#160;    VkDeviceSize lastOffset = 0;</div>
+<div class="line"><a name="l10057"></a><span class="lineno">10057</span>&#160; </div>
+<div class="line"><a name="l10058"></a><span class="lineno">10058</span>&#160;    <span class="keywordtype">size_t</span> alloc2ndCount = 0;</div>
+<div class="line"><a name="l10059"></a><span class="lineno">10059</span>&#160;    <span class="keywordflow">if</span>(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)</div>
+<div class="line"><a name="l10060"></a><span class="lineno">10060</span>&#160;    {</div>
+<div class="line"><a name="l10061"></a><span class="lineno">10061</span>&#160;        <span class="keyword">const</span> VkDeviceSize freeSpace2ndTo1stEnd = suballocations1st[m_1stNullItemsBeginCount].offset;</div>
+<div class="line"><a name="l10062"></a><span class="lineno">10062</span>&#160;        <span class="keywordtype">size_t</span> nextAlloc2ndIndex = 0;</div>
+<div class="line"><a name="l10063"></a><span class="lineno">10063</span>&#160;        <span class="keywordflow">while</span>(lastOffset &lt; freeSpace2ndTo1stEnd)</div>
+<div class="line"><a name="l10064"></a><span class="lineno">10064</span>&#160;        {</div>
+<div class="line"><a name="l10065"></a><span class="lineno">10065</span>&#160;            <span class="comment">// Find next non-null allocation or move nextAlloc2ndIndex to the end.</span></div>
+<div class="line"><a name="l10066"></a><span class="lineno">10066</span>&#160;            <span class="keywordflow">while</span>(nextAlloc2ndIndex &lt; suballoc2ndCount &amp;&amp;</div>
+<div class="line"><a name="l10067"></a><span class="lineno">10067</span>&#160;                suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE)</div>
+<div class="line"><a name="l10068"></a><span class="lineno">10068</span>&#160;            {</div>
+<div class="line"><a name="l10069"></a><span class="lineno">10069</span>&#160;                ++nextAlloc2ndIndex;</div>
+<div class="line"><a name="l10070"></a><span class="lineno">10070</span>&#160;            }</div>
+<div class="line"><a name="l10071"></a><span class="lineno">10071</span>&#160; </div>
+<div class="line"><a name="l10072"></a><span class="lineno">10072</span>&#160;            <span class="comment">// Found non-null allocation.</span></div>
+<div class="line"><a name="l10073"></a><span class="lineno">10073</span>&#160;            <span class="keywordflow">if</span>(nextAlloc2ndIndex &lt; suballoc2ndCount)</div>
+<div class="line"><a name="l10074"></a><span class="lineno">10074</span>&#160;            {</div>
+<div class="line"><a name="l10075"></a><span class="lineno">10075</span>&#160;                <span class="keyword">const</span> VmaSuballocation&amp; suballoc = suballocations2nd[nextAlloc2ndIndex];</div>
+<div class="line"><a name="l10076"></a><span class="lineno">10076</span>&#160;            </div>
+<div class="line"><a name="l10077"></a><span class="lineno">10077</span>&#160;                <span class="comment">// 1. Process free space before this allocation.</span></div>
+<div class="line"><a name="l10078"></a><span class="lineno">10078</span>&#160;                <span class="keywordflow">if</span>(lastOffset &lt; suballoc.offset)</div>
+<div class="line"><a name="l10079"></a><span class="lineno">10079</span>&#160;                {</div>
+<div class="line"><a name="l10080"></a><span class="lineno">10080</span>&#160;                    <span class="comment">// There is free space from lastOffset to suballoc.offset.</span></div>
+<div class="line"><a name="l10081"></a><span class="lineno">10081</span>&#160;                    ++unusedRangeCount;</div>
+<div class="line"><a name="l10082"></a><span class="lineno">10082</span>&#160;                }</div>
+<div class="line"><a name="l10083"></a><span class="lineno">10083</span>&#160;            </div>
+<div class="line"><a name="l10084"></a><span class="lineno">10084</span>&#160;                <span class="comment">// 2. Process this allocation.</span></div>
+<div class="line"><a name="l10085"></a><span class="lineno">10085</span>&#160;                <span class="comment">// There is allocation with suballoc.offset, suballoc.size.</span></div>
+<div class="line"><a name="l10086"></a><span class="lineno">10086</span>&#160;                ++alloc2ndCount;</div>
+<div class="line"><a name="l10087"></a><span class="lineno">10087</span>&#160;                usedBytes += suballoc.size;</div>
+<div class="line"><a name="l10088"></a><span class="lineno">10088</span>&#160;            </div>
+<div class="line"><a name="l10089"></a><span class="lineno">10089</span>&#160;                <span class="comment">// 3. Prepare for next iteration.</span></div>
+<div class="line"><a name="l10090"></a><span class="lineno">10090</span>&#160;                lastOffset = suballoc.offset + suballoc.size;</div>
+<div class="line"><a name="l10091"></a><span class="lineno">10091</span>&#160;                ++nextAlloc2ndIndex;</div>
+<div class="line"><a name="l10092"></a><span class="lineno">10092</span>&#160;            }</div>
+<div class="line"><a name="l10093"></a><span class="lineno">10093</span>&#160;            <span class="comment">// We are at the end.</span></div>
+<div class="line"><a name="l10094"></a><span class="lineno">10094</span>&#160;            <span class="keywordflow">else</span></div>
+<div class="line"><a name="l10095"></a><span class="lineno">10095</span>&#160;            {</div>
+<div class="line"><a name="l10096"></a><span class="lineno">10096</span>&#160;                <span class="keywordflow">if</span>(lastOffset &lt; freeSpace2ndTo1stEnd)</div>
+<div class="line"><a name="l10097"></a><span class="lineno">10097</span>&#160;                {</div>
+<div class="line"><a name="l10098"></a><span class="lineno">10098</span>&#160;                    <span class="comment">// There is free space from lastOffset to freeSpace2ndTo1stEnd.</span></div>
+<div class="line"><a name="l10099"></a><span class="lineno">10099</span>&#160;                    ++unusedRangeCount;</div>
+<div class="line"><a name="l10100"></a><span class="lineno">10100</span>&#160;                }</div>
+<div class="line"><a name="l10101"></a><span class="lineno">10101</span>&#160; </div>
+<div class="line"><a name="l10102"></a><span class="lineno">10102</span>&#160;                <span class="comment">// End of loop.</span></div>
+<div class="line"><a name="l10103"></a><span class="lineno">10103</span>&#160;                lastOffset = freeSpace2ndTo1stEnd;</div>
+<div class="line"><a name="l10104"></a><span class="lineno">10104</span>&#160;            }</div>
+<div class="line"><a name="l10105"></a><span class="lineno">10105</span>&#160;        }</div>
+<div class="line"><a name="l10106"></a><span class="lineno">10106</span>&#160;    }</div>
+<div class="line"><a name="l10107"></a><span class="lineno">10107</span>&#160; </div>
+<div class="line"><a name="l10108"></a><span class="lineno">10108</span>&#160;    <span class="keywordtype">size_t</span> nextAlloc1stIndex = m_1stNullItemsBeginCount;</div>
+<div class="line"><a name="l10109"></a><span class="lineno">10109</span>&#160;    <span class="keywordtype">size_t</span> alloc1stCount = 0;</div>
+<div class="line"><a name="l10110"></a><span class="lineno">10110</span>&#160;    <span class="keyword">const</span> VkDeviceSize freeSpace1stTo2ndEnd =</div>
+<div class="line"><a name="l10111"></a><span class="lineno">10111</span>&#160;        m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK ? suballocations2nd.back().offset : size;</div>
+<div class="line"><a name="l10112"></a><span class="lineno">10112</span>&#160;    <span class="keywordflow">while</span>(lastOffset &lt; freeSpace1stTo2ndEnd)</div>
+<div class="line"><a name="l10113"></a><span class="lineno">10113</span>&#160;    {</div>
+<div class="line"><a name="l10114"></a><span class="lineno">10114</span>&#160;        <span class="comment">// Find next non-null allocation or move nextAllocIndex to the end.</span></div>
+<div class="line"><a name="l10115"></a><span class="lineno">10115</span>&#160;        <span class="keywordflow">while</span>(nextAlloc1stIndex &lt; suballoc1stCount &amp;&amp;</div>
+<div class="line"><a name="l10116"></a><span class="lineno">10116</span>&#160;            suballocations1st[nextAlloc1stIndex].hAllocation == VK_NULL_HANDLE)</div>
+<div class="line"><a name="l10117"></a><span class="lineno">10117</span>&#160;        {</div>
+<div class="line"><a name="l10118"></a><span class="lineno">10118</span>&#160;            ++nextAlloc1stIndex;</div>
+<div class="line"><a name="l10119"></a><span class="lineno">10119</span>&#160;        }</div>
+<div class="line"><a name="l10120"></a><span class="lineno">10120</span>&#160; </div>
+<div class="line"><a name="l10121"></a><span class="lineno">10121</span>&#160;        <span class="comment">// Found non-null allocation.</span></div>
+<div class="line"><a name="l10122"></a><span class="lineno">10122</span>&#160;        <span class="keywordflow">if</span>(nextAlloc1stIndex &lt; suballoc1stCount)</div>
+<div class="line"><a name="l10123"></a><span class="lineno">10123</span>&#160;        {</div>
+<div class="line"><a name="l10124"></a><span class="lineno">10124</span>&#160;            <span class="keyword">const</span> VmaSuballocation&amp; suballoc = suballocations1st[nextAlloc1stIndex];</div>
+<div class="line"><a name="l10125"></a><span class="lineno">10125</span>&#160;            </div>
+<div class="line"><a name="l10126"></a><span class="lineno">10126</span>&#160;            <span class="comment">// 1. Process free space before this allocation.</span></div>
+<div class="line"><a name="l10127"></a><span class="lineno">10127</span>&#160;            <span class="keywordflow">if</span>(lastOffset &lt; suballoc.offset)</div>
+<div class="line"><a name="l10128"></a><span class="lineno">10128</span>&#160;            {</div>
+<div class="line"><a name="l10129"></a><span class="lineno">10129</span>&#160;                <span class="comment">// There is free space from lastOffset to suballoc.offset.</span></div>
+<div class="line"><a name="l10130"></a><span class="lineno">10130</span>&#160;                ++unusedRangeCount;</div>
+<div class="line"><a name="l10131"></a><span class="lineno">10131</span>&#160;            }</div>
+<div class="line"><a name="l10132"></a><span class="lineno">10132</span>&#160;            </div>
+<div class="line"><a name="l10133"></a><span class="lineno">10133</span>&#160;            <span class="comment">// 2. Process this allocation.</span></div>
+<div class="line"><a name="l10134"></a><span class="lineno">10134</span>&#160;            <span class="comment">// There is allocation with suballoc.offset, suballoc.size.</span></div>
+<div class="line"><a name="l10135"></a><span class="lineno">10135</span>&#160;            ++alloc1stCount;</div>
+<div class="line"><a name="l10136"></a><span class="lineno">10136</span>&#160;            usedBytes += suballoc.size;</div>
+<div class="line"><a name="l10137"></a><span class="lineno">10137</span>&#160;            </div>
+<div class="line"><a name="l10138"></a><span class="lineno">10138</span>&#160;            <span class="comment">// 3. Prepare for next iteration.</span></div>
+<div class="line"><a name="l10139"></a><span class="lineno">10139</span>&#160;            lastOffset = suballoc.offset + suballoc.size;</div>
+<div class="line"><a name="l10140"></a><span class="lineno">10140</span>&#160;            ++nextAlloc1stIndex;</div>
+<div class="line"><a name="l10141"></a><span class="lineno">10141</span>&#160;        }</div>
+<div class="line"><a name="l10142"></a><span class="lineno">10142</span>&#160;        <span class="comment">// We are at the end.</span></div>
+<div class="line"><a name="l10143"></a><span class="lineno">10143</span>&#160;        <span class="keywordflow">else</span></div>
+<div class="line"><a name="l10144"></a><span class="lineno">10144</span>&#160;        {</div>
+<div class="line"><a name="l10145"></a><span class="lineno">10145</span>&#160;            <span class="keywordflow">if</span>(lastOffset &lt; size)</div>
+<div class="line"><a name="l10146"></a><span class="lineno">10146</span>&#160;            {</div>
+<div class="line"><a name="l10147"></a><span class="lineno">10147</span>&#160;                <span class="comment">// There is free space from lastOffset to freeSpace1stTo2ndEnd.</span></div>
+<div class="line"><a name="l10148"></a><span class="lineno">10148</span>&#160;                ++unusedRangeCount;</div>
+<div class="line"><a name="l10149"></a><span class="lineno">10149</span>&#160;            }</div>
+<div class="line"><a name="l10150"></a><span class="lineno">10150</span>&#160; </div>
+<div class="line"><a name="l10151"></a><span class="lineno">10151</span>&#160;            <span class="comment">// End of loop.</span></div>
+<div class="line"><a name="l10152"></a><span class="lineno">10152</span>&#160;            lastOffset = freeSpace1stTo2ndEnd;</div>
+<div class="line"><a name="l10153"></a><span class="lineno">10153</span>&#160;        }</div>
+<div class="line"><a name="l10154"></a><span class="lineno">10154</span>&#160;    }</div>
+<div class="line"><a name="l10155"></a><span class="lineno">10155</span>&#160; </div>
+<div class="line"><a name="l10156"></a><span class="lineno">10156</span>&#160;    <span class="keywordflow">if</span>(m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)</div>
+<div class="line"><a name="l10157"></a><span class="lineno">10157</span>&#160;    {</div>
+<div class="line"><a name="l10158"></a><span class="lineno">10158</span>&#160;        <span class="keywordtype">size_t</span> nextAlloc2ndIndex = suballocations2nd.size() - 1;</div>
+<div class="line"><a name="l10159"></a><span class="lineno">10159</span>&#160;        <span class="keywordflow">while</span>(lastOffset &lt; size)</div>
+<div class="line"><a name="l10160"></a><span class="lineno">10160</span>&#160;        {</div>
+<div class="line"><a name="l10161"></a><span class="lineno">10161</span>&#160;            <span class="comment">// Find next non-null allocation or move nextAlloc2ndIndex to the end.</span></div>
+<div class="line"><a name="l10162"></a><span class="lineno">10162</span>&#160;            <span class="keywordflow">while</span>(nextAlloc2ndIndex != SIZE_MAX &amp;&amp;</div>
+<div class="line"><a name="l10163"></a><span class="lineno">10163</span>&#160;                suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE)</div>
+<div class="line"><a name="l10164"></a><span class="lineno">10164</span>&#160;            {</div>
+<div class="line"><a name="l10165"></a><span class="lineno">10165</span>&#160;                --nextAlloc2ndIndex;</div>
+<div class="line"><a name="l10166"></a><span class="lineno">10166</span>&#160;            }</div>
+<div class="line"><a name="l10167"></a><span class="lineno">10167</span>&#160; </div>
+<div class="line"><a name="l10168"></a><span class="lineno">10168</span>&#160;            <span class="comment">// Found non-null allocation.</span></div>
+<div class="line"><a name="l10169"></a><span class="lineno">10169</span>&#160;            <span class="keywordflow">if</span>(nextAlloc2ndIndex != SIZE_MAX)</div>
+<div class="line"><a name="l10170"></a><span class="lineno">10170</span>&#160;            {</div>
+<div class="line"><a name="l10171"></a><span class="lineno">10171</span>&#160;                <span class="keyword">const</span> VmaSuballocation&amp; suballoc = suballocations2nd[nextAlloc2ndIndex];</div>
+<div class="line"><a name="l10172"></a><span class="lineno">10172</span>&#160;            </div>
+<div class="line"><a name="l10173"></a><span class="lineno">10173</span>&#160;                <span class="comment">// 1. Process free space before this allocation.</span></div>
+<div class="line"><a name="l10174"></a><span class="lineno">10174</span>&#160;                <span class="keywordflow">if</span>(lastOffset &lt; suballoc.offset)</div>
+<div class="line"><a name="l10175"></a><span class="lineno">10175</span>&#160;                {</div>
+<div class="line"><a name="l10176"></a><span class="lineno">10176</span>&#160;                    <span class="comment">// There is free space from lastOffset to suballoc.offset.</span></div>
+<div class="line"><a name="l10177"></a><span class="lineno">10177</span>&#160;                    ++unusedRangeCount;</div>
+<div class="line"><a name="l10178"></a><span class="lineno">10178</span>&#160;                }</div>
+<div class="line"><a name="l10179"></a><span class="lineno">10179</span>&#160;            </div>
+<div class="line"><a name="l10180"></a><span class="lineno">10180</span>&#160;                <span class="comment">// 2. Process this allocation.</span></div>
+<div class="line"><a name="l10181"></a><span class="lineno">10181</span>&#160;                <span class="comment">// There is allocation with suballoc.offset, suballoc.size.</span></div>
+<div class="line"><a name="l10182"></a><span class="lineno">10182</span>&#160;                ++alloc2ndCount;</div>
+<div class="line"><a name="l10183"></a><span class="lineno">10183</span>&#160;                usedBytes += suballoc.size;</div>
+<div class="line"><a name="l10184"></a><span class="lineno">10184</span>&#160;            </div>
+<div class="line"><a name="l10185"></a><span class="lineno">10185</span>&#160;                <span class="comment">// 3. Prepare for next iteration.</span></div>
+<div class="line"><a name="l10186"></a><span class="lineno">10186</span>&#160;                lastOffset = suballoc.offset + suballoc.size;</div>
+<div class="line"><a name="l10187"></a><span class="lineno">10187</span>&#160;                --nextAlloc2ndIndex;</div>
+<div class="line"><a name="l10188"></a><span class="lineno">10188</span>&#160;            }</div>
+<div class="line"><a name="l10189"></a><span class="lineno">10189</span>&#160;            <span class="comment">// We are at the end.</span></div>
+<div class="line"><a name="l10190"></a><span class="lineno">10190</span>&#160;            <span class="keywordflow">else</span></div>
+<div class="line"><a name="l10191"></a><span class="lineno">10191</span>&#160;            {</div>
+<div class="line"><a name="l10192"></a><span class="lineno">10192</span>&#160;                <span class="keywordflow">if</span>(lastOffset &lt; size)</div>
+<div class="line"><a name="l10193"></a><span class="lineno">10193</span>&#160;                {</div>
+<div class="line"><a name="l10194"></a><span class="lineno">10194</span>&#160;                    <span class="comment">// There is free space from lastOffset to size.</span></div>
+<div class="line"><a name="l10195"></a><span class="lineno">10195</span>&#160;                    ++unusedRangeCount;</div>
+<div class="line"><a name="l10196"></a><span class="lineno">10196</span>&#160;                }</div>
+<div class="line"><a name="l10197"></a><span class="lineno">10197</span>&#160; </div>
+<div class="line"><a name="l10198"></a><span class="lineno">10198</span>&#160;                <span class="comment">// End of loop.</span></div>
+<div class="line"><a name="l10199"></a><span class="lineno">10199</span>&#160;                lastOffset = size;</div>
+<div class="line"><a name="l10200"></a><span class="lineno">10200</span>&#160;            }</div>
+<div class="line"><a name="l10201"></a><span class="lineno">10201</span>&#160;        }</div>
+<div class="line"><a name="l10202"></a><span class="lineno">10202</span>&#160;    }</div>
+<div class="line"><a name="l10203"></a><span class="lineno">10203</span>&#160; </div>
+<div class="line"><a name="l10204"></a><span class="lineno">10204</span>&#160;    <span class="keyword">const</span> VkDeviceSize unusedBytes = size - usedBytes;</div>
+<div class="line"><a name="l10205"></a><span class="lineno">10205</span>&#160;    PrintDetailedMap_Begin(json, unusedBytes, alloc1stCount + alloc2ndCount, unusedRangeCount);</div>
+<div class="line"><a name="l10206"></a><span class="lineno">10206</span>&#160; </div>
+<div class="line"><a name="l10207"></a><span class="lineno">10207</span>&#160;    <span class="comment">// SECOND PASS</span></div>
+<div class="line"><a name="l10208"></a><span class="lineno">10208</span>&#160;    lastOffset = 0;</div>
+<div class="line"><a name="l10209"></a><span class="lineno">10209</span>&#160; </div>
+<div class="line"><a name="l10210"></a><span class="lineno">10210</span>&#160;    <span class="keywordflow">if</span>(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)</div>
+<div class="line"><a name="l10211"></a><span class="lineno">10211</span>&#160;    {</div>
+<div class="line"><a name="l10212"></a><span class="lineno">10212</span>&#160;        <span class="keyword">const</span> VkDeviceSize freeSpace2ndTo1stEnd = suballocations1st[m_1stNullItemsBeginCount].offset;</div>
+<div class="line"><a name="l10213"></a><span class="lineno">10213</span>&#160;        <span class="keywordtype">size_t</span> nextAlloc2ndIndex = 0;</div>
+<div class="line"><a name="l10214"></a><span class="lineno">10214</span>&#160;        <span class="keywordflow">while</span>(lastOffset &lt; freeSpace2ndTo1stEnd)</div>
+<div class="line"><a name="l10215"></a><span class="lineno">10215</span>&#160;        {</div>
+<div class="line"><a name="l10216"></a><span class="lineno">10216</span>&#160;            <span class="comment">// Find next non-null allocation or move nextAlloc2ndIndex to the end.</span></div>
+<div class="line"><a name="l10217"></a><span class="lineno">10217</span>&#160;            <span class="keywordflow">while</span>(nextAlloc2ndIndex &lt; suballoc2ndCount &amp;&amp;</div>
+<div class="line"><a name="l10218"></a><span class="lineno">10218</span>&#160;                suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE)</div>
+<div class="line"><a name="l10219"></a><span class="lineno">10219</span>&#160;            {</div>
+<div class="line"><a name="l10220"></a><span class="lineno">10220</span>&#160;                ++nextAlloc2ndIndex;</div>
+<div class="line"><a name="l10221"></a><span class="lineno">10221</span>&#160;            }</div>
+<div class="line"><a name="l10222"></a><span class="lineno">10222</span>&#160; </div>
+<div class="line"><a name="l10223"></a><span class="lineno">10223</span>&#160;            <span class="comment">// Found non-null allocation.</span></div>
+<div class="line"><a name="l10224"></a><span class="lineno">10224</span>&#160;            <span class="keywordflow">if</span>(nextAlloc2ndIndex &lt; suballoc2ndCount)</div>
+<div class="line"><a name="l10225"></a><span class="lineno">10225</span>&#160;            {</div>
+<div class="line"><a name="l10226"></a><span class="lineno">10226</span>&#160;                <span class="keyword">const</span> VmaSuballocation&amp; suballoc = suballocations2nd[nextAlloc2ndIndex];</div>
+<div class="line"><a name="l10227"></a><span class="lineno">10227</span>&#160;            </div>
+<div class="line"><a name="l10228"></a><span class="lineno">10228</span>&#160;                <span class="comment">// 1. Process free space before this allocation.</span></div>
+<div class="line"><a name="l10229"></a><span class="lineno">10229</span>&#160;                <span class="keywordflow">if</span>(lastOffset &lt; suballoc.offset)</div>
+<div class="line"><a name="l10230"></a><span class="lineno">10230</span>&#160;                {</div>
+<div class="line"><a name="l10231"></a><span class="lineno">10231</span>&#160;                    <span class="comment">// There is free space from lastOffset to suballoc.offset.</span></div>
+<div class="line"><a name="l10232"></a><span class="lineno">10232</span>&#160;                    <span class="keyword">const</span> VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;</div>
+<div class="line"><a name="l10233"></a><span class="lineno">10233</span>&#160;                    PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize);</div>
+<div class="line"><a name="l10234"></a><span class="lineno">10234</span>&#160;                }</div>
+<div class="line"><a name="l10235"></a><span class="lineno">10235</span>&#160;            </div>
+<div class="line"><a name="l10236"></a><span class="lineno">10236</span>&#160;                <span class="comment">// 2. Process this allocation.</span></div>
+<div class="line"><a name="l10237"></a><span class="lineno">10237</span>&#160;                <span class="comment">// There is allocation with suballoc.offset, suballoc.size.</span></div>
+<div class="line"><a name="l10238"></a><span class="lineno">10238</span>&#160;                PrintDetailedMap_Allocation(json, suballoc.offset, suballoc.hAllocation);</div>
+<div class="line"><a name="l10239"></a><span class="lineno">10239</span>&#160;            </div>
+<div class="line"><a name="l10240"></a><span class="lineno">10240</span>&#160;                <span class="comment">// 3. Prepare for next iteration.</span></div>
+<div class="line"><a name="l10241"></a><span class="lineno">10241</span>&#160;                lastOffset = suballoc.offset + suballoc.size;</div>
+<div class="line"><a name="l10242"></a><span class="lineno">10242</span>&#160;                ++nextAlloc2ndIndex;</div>
+<div class="line"><a name="l10243"></a><span class="lineno">10243</span>&#160;            }</div>
+<div class="line"><a name="l10244"></a><span class="lineno">10244</span>&#160;            <span class="comment">// We are at the end.</span></div>
+<div class="line"><a name="l10245"></a><span class="lineno">10245</span>&#160;            <span class="keywordflow">else</span></div>
+<div class="line"><a name="l10246"></a><span class="lineno">10246</span>&#160;            {</div>
+<div class="line"><a name="l10247"></a><span class="lineno">10247</span>&#160;                <span class="keywordflow">if</span>(lastOffset &lt; freeSpace2ndTo1stEnd)</div>
+<div class="line"><a name="l10248"></a><span class="lineno">10248</span>&#160;                {</div>
+<div class="line"><a name="l10249"></a><span class="lineno">10249</span>&#160;                    <span class="comment">// There is free space from lastOffset to freeSpace2ndTo1stEnd.</span></div>
+<div class="line"><a name="l10250"></a><span class="lineno">10250</span>&#160;                    <span class="keyword">const</span> VkDeviceSize unusedRangeSize = freeSpace2ndTo1stEnd - lastOffset;</div>
+<div class="line"><a name="l10251"></a><span class="lineno">10251</span>&#160;                    PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize);</div>
+<div class="line"><a name="l10252"></a><span class="lineno">10252</span>&#160;                }</div>
+<div class="line"><a name="l10253"></a><span class="lineno">10253</span>&#160; </div>
+<div class="line"><a name="l10254"></a><span class="lineno">10254</span>&#160;                <span class="comment">// End of loop.</span></div>
+<div class="line"><a name="l10255"></a><span class="lineno">10255</span>&#160;                lastOffset = freeSpace2ndTo1stEnd;</div>
+<div class="line"><a name="l10256"></a><span class="lineno">10256</span>&#160;            }</div>
+<div class="line"><a name="l10257"></a><span class="lineno">10257</span>&#160;        }</div>
+<div class="line"><a name="l10258"></a><span class="lineno">10258</span>&#160;    }</div>
+<div class="line"><a name="l10259"></a><span class="lineno">10259</span>&#160; </div>
+<div class="line"><a name="l10260"></a><span class="lineno">10260</span>&#160;    nextAlloc1stIndex = m_1stNullItemsBeginCount;</div>
+<div class="line"><a name="l10261"></a><span class="lineno">10261</span>&#160;    <span class="keywordflow">while</span>(lastOffset &lt; freeSpace1stTo2ndEnd)</div>
+<div class="line"><a name="l10262"></a><span class="lineno">10262</span>&#160;    {</div>
+<div class="line"><a name="l10263"></a><span class="lineno">10263</span>&#160;        <span class="comment">// Find next non-null allocation or move nextAllocIndex to the end.</span></div>
+<div class="line"><a name="l10264"></a><span class="lineno">10264</span>&#160;        <span class="keywordflow">while</span>(nextAlloc1stIndex &lt; suballoc1stCount &amp;&amp;</div>
+<div class="line"><a name="l10265"></a><span class="lineno">10265</span>&#160;            suballocations1st[nextAlloc1stIndex].hAllocation == VK_NULL_HANDLE)</div>
+<div class="line"><a name="l10266"></a><span class="lineno">10266</span>&#160;        {</div>
+<div class="line"><a name="l10267"></a><span class="lineno">10267</span>&#160;            ++nextAlloc1stIndex;</div>
+<div class="line"><a name="l10268"></a><span class="lineno">10268</span>&#160;        }</div>
+<div class="line"><a name="l10269"></a><span class="lineno">10269</span>&#160; </div>
+<div class="line"><a name="l10270"></a><span class="lineno">10270</span>&#160;        <span class="comment">// Found non-null allocation.</span></div>
+<div class="line"><a name="l10271"></a><span class="lineno">10271</span>&#160;        <span class="keywordflow">if</span>(nextAlloc1stIndex &lt; suballoc1stCount)</div>
+<div class="line"><a name="l10272"></a><span class="lineno">10272</span>&#160;        {</div>
+<div class="line"><a name="l10273"></a><span class="lineno">10273</span>&#160;            <span class="keyword">const</span> VmaSuballocation&amp; suballoc = suballocations1st[nextAlloc1stIndex];</div>
+<div class="line"><a name="l10274"></a><span class="lineno">10274</span>&#160;            </div>
+<div class="line"><a name="l10275"></a><span class="lineno">10275</span>&#160;            <span class="comment">// 1. Process free space before this allocation.</span></div>
+<div class="line"><a name="l10276"></a><span class="lineno">10276</span>&#160;            <span class="keywordflow">if</span>(lastOffset &lt; suballoc.offset)</div>
+<div class="line"><a name="l10277"></a><span class="lineno">10277</span>&#160;            {</div>
+<div class="line"><a name="l10278"></a><span class="lineno">10278</span>&#160;                <span class="comment">// There is free space from lastOffset to suballoc.offset.</span></div>
+<div class="line"><a name="l10279"></a><span class="lineno">10279</span>&#160;                <span class="keyword">const</span> VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;</div>
+<div class="line"><a name="l10280"></a><span class="lineno">10280</span>&#160;                PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize);</div>
+<div class="line"><a name="l10281"></a><span class="lineno">10281</span>&#160;            }</div>
+<div class="line"><a name="l10282"></a><span class="lineno">10282</span>&#160;            </div>
+<div class="line"><a name="l10283"></a><span class="lineno">10283</span>&#160;            <span class="comment">// 2. Process this allocation.</span></div>
+<div class="line"><a name="l10284"></a><span class="lineno">10284</span>&#160;            <span class="comment">// There is allocation with suballoc.offset, suballoc.size.</span></div>
+<div class="line"><a name="l10285"></a><span class="lineno">10285</span>&#160;            PrintDetailedMap_Allocation(json, suballoc.offset, suballoc.hAllocation);</div>
+<div class="line"><a name="l10286"></a><span class="lineno">10286</span>&#160;            </div>
+<div class="line"><a name="l10287"></a><span class="lineno">10287</span>&#160;            <span class="comment">// 3. Prepare for next iteration.</span></div>
+<div class="line"><a name="l10288"></a><span class="lineno">10288</span>&#160;            lastOffset = suballoc.offset + suballoc.size;</div>
+<div class="line"><a name="l10289"></a><span class="lineno">10289</span>&#160;            ++nextAlloc1stIndex;</div>
+<div class="line"><a name="l10290"></a><span class="lineno">10290</span>&#160;        }</div>
+<div class="line"><a name="l10291"></a><span class="lineno">10291</span>&#160;        <span class="comment">// We are at the end.</span></div>
+<div class="line"><a name="l10292"></a><span class="lineno">10292</span>&#160;        <span class="keywordflow">else</span></div>
+<div class="line"><a name="l10293"></a><span class="lineno">10293</span>&#160;        {</div>
+<div class="line"><a name="l10294"></a><span class="lineno">10294</span>&#160;            <span class="keywordflow">if</span>(lastOffset &lt; freeSpace1stTo2ndEnd)</div>
+<div class="line"><a name="l10295"></a><span class="lineno">10295</span>&#160;            {</div>
+<div class="line"><a name="l10296"></a><span class="lineno">10296</span>&#160;                <span class="comment">// There is free space from lastOffset to freeSpace1stTo2ndEnd.</span></div>
+<div class="line"><a name="l10297"></a><span class="lineno">10297</span>&#160;                <span class="keyword">const</span> VkDeviceSize unusedRangeSize = freeSpace1stTo2ndEnd - lastOffset;</div>
+<div class="line"><a name="l10298"></a><span class="lineno">10298</span>&#160;                PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize);</div>
+<div class="line"><a name="l10299"></a><span class="lineno">10299</span>&#160;            }</div>
+<div class="line"><a name="l10300"></a><span class="lineno">10300</span>&#160; </div>
+<div class="line"><a name="l10301"></a><span class="lineno">10301</span>&#160;            <span class="comment">// End of loop.</span></div>
+<div class="line"><a name="l10302"></a><span class="lineno">10302</span>&#160;            lastOffset = freeSpace1stTo2ndEnd;</div>
+<div class="line"><a name="l10303"></a><span class="lineno">10303</span>&#160;        }</div>
+<div class="line"><a name="l10304"></a><span class="lineno">10304</span>&#160;    }</div>
+<div class="line"><a name="l10305"></a><span class="lineno">10305</span>&#160; </div>
+<div class="line"><a name="l10306"></a><span class="lineno">10306</span>&#160;    <span class="keywordflow">if</span>(m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)</div>
+<div class="line"><a name="l10307"></a><span class="lineno">10307</span>&#160;    {</div>
+<div class="line"><a name="l10308"></a><span class="lineno">10308</span>&#160;        <span class="keywordtype">size_t</span> nextAlloc2ndIndex = suballocations2nd.size() - 1;</div>
+<div class="line"><a name="l10309"></a><span class="lineno">10309</span>&#160;        <span class="keywordflow">while</span>(lastOffset &lt; size)</div>
+<div class="line"><a name="l10310"></a><span class="lineno">10310</span>&#160;        {</div>
+<div class="line"><a name="l10311"></a><span class="lineno">10311</span>&#160;            <span class="comment">// Find next non-null allocation or move nextAlloc2ndIndex to the end.</span></div>
+<div class="line"><a name="l10312"></a><span class="lineno">10312</span>&#160;            <span class="keywordflow">while</span>(nextAlloc2ndIndex != SIZE_MAX &amp;&amp;</div>
+<div class="line"><a name="l10313"></a><span class="lineno">10313</span>&#160;                suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE)</div>
+<div class="line"><a name="l10314"></a><span class="lineno">10314</span>&#160;            {</div>
+<div class="line"><a name="l10315"></a><span class="lineno">10315</span>&#160;                --nextAlloc2ndIndex;</div>
+<div class="line"><a name="l10316"></a><span class="lineno">10316</span>&#160;            }</div>
+<div class="line"><a name="l10317"></a><span class="lineno">10317</span>&#160; </div>
+<div class="line"><a name="l10318"></a><span class="lineno">10318</span>&#160;            <span class="comment">// Found non-null allocation.</span></div>
+<div class="line"><a name="l10319"></a><span class="lineno">10319</span>&#160;            <span class="keywordflow">if</span>(nextAlloc2ndIndex != SIZE_MAX)</div>
+<div class="line"><a name="l10320"></a><span class="lineno">10320</span>&#160;            {</div>
+<div class="line"><a name="l10321"></a><span class="lineno">10321</span>&#160;                <span class="keyword">const</span> VmaSuballocation&amp; suballoc = suballocations2nd[nextAlloc2ndIndex];</div>
+<div class="line"><a name="l10322"></a><span class="lineno">10322</span>&#160;            </div>
+<div class="line"><a name="l10323"></a><span class="lineno">10323</span>&#160;                <span class="comment">// 1. Process free space before this allocation.</span></div>
+<div class="line"><a name="l10324"></a><span class="lineno">10324</span>&#160;                <span class="keywordflow">if</span>(lastOffset &lt; suballoc.offset)</div>
+<div class="line"><a name="l10325"></a><span class="lineno">10325</span>&#160;                {</div>
+<div class="line"><a name="l10326"></a><span class="lineno">10326</span>&#160;                    <span class="comment">// There is free space from lastOffset to suballoc.offset.</span></div>
+<div class="line"><a name="l10327"></a><span class="lineno">10327</span>&#160;                    <span class="keyword">const</span> VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;</div>
+<div class="line"><a name="l10328"></a><span class="lineno">10328</span>&#160;                    PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize);</div>
+<div class="line"><a name="l10329"></a><span class="lineno">10329</span>&#160;                }</div>
+<div class="line"><a name="l10330"></a><span class="lineno">10330</span>&#160;            </div>
+<div class="line"><a name="l10331"></a><span class="lineno">10331</span>&#160;                <span class="comment">// 2. Process this allocation.</span></div>
+<div class="line"><a name="l10332"></a><span class="lineno">10332</span>&#160;                <span class="comment">// There is allocation with suballoc.offset, suballoc.size.</span></div>
+<div class="line"><a name="l10333"></a><span class="lineno">10333</span>&#160;                PrintDetailedMap_Allocation(json, suballoc.offset, suballoc.hAllocation);</div>
+<div class="line"><a name="l10334"></a><span class="lineno">10334</span>&#160;            </div>
+<div class="line"><a name="l10335"></a><span class="lineno">10335</span>&#160;                <span class="comment">// 3. Prepare for next iteration.</span></div>
+<div class="line"><a name="l10336"></a><span class="lineno">10336</span>&#160;                lastOffset = suballoc.offset + suballoc.size;</div>
+<div class="line"><a name="l10337"></a><span class="lineno">10337</span>&#160;                --nextAlloc2ndIndex;</div>
+<div class="line"><a name="l10338"></a><span class="lineno">10338</span>&#160;            }</div>
+<div class="line"><a name="l10339"></a><span class="lineno">10339</span>&#160;            <span class="comment">// We are at the end.</span></div>
+<div class="line"><a name="l10340"></a><span class="lineno">10340</span>&#160;            <span class="keywordflow">else</span></div>
+<div class="line"><a name="l10341"></a><span class="lineno">10341</span>&#160;            {</div>
+<div class="line"><a name="l10342"></a><span class="lineno">10342</span>&#160;                <span class="keywordflow">if</span>(lastOffset &lt; size)</div>
+<div class="line"><a name="l10343"></a><span class="lineno">10343</span>&#160;                {</div>
+<div class="line"><a name="l10344"></a><span class="lineno">10344</span>&#160;                    <span class="comment">// There is free space from lastOffset to size.</span></div>
+<div class="line"><a name="l10345"></a><span class="lineno">10345</span>&#160;                    <span class="keyword">const</span> VkDeviceSize unusedRangeSize = size - lastOffset;</div>
+<div class="line"><a name="l10346"></a><span class="lineno">10346</span>&#160;                    PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize);</div>
+<div class="line"><a name="l10347"></a><span class="lineno">10347</span>&#160;                }</div>
+<div class="line"><a name="l10348"></a><span class="lineno">10348</span>&#160; </div>
+<div class="line"><a name="l10349"></a><span class="lineno">10349</span>&#160;                <span class="comment">// End of loop.</span></div>
+<div class="line"><a name="l10350"></a><span class="lineno">10350</span>&#160;                lastOffset = size;</div>
+<div class="line"><a name="l10351"></a><span class="lineno">10351</span>&#160;            }</div>
+<div class="line"><a name="l10352"></a><span class="lineno">10352</span>&#160;        }</div>
+<div class="line"><a name="l10353"></a><span class="lineno">10353</span>&#160;    }</div>
+<div class="line"><a name="l10354"></a><span class="lineno">10354</span>&#160; </div>
+<div class="line"><a name="l10355"></a><span class="lineno">10355</span>&#160;    PrintDetailedMap_End(json);</div>
+<div class="line"><a name="l10356"></a><span class="lineno">10356</span>&#160;}</div>
+<div class="line"><a name="l10357"></a><span class="lineno">10357</span>&#160;<span class="preprocessor">#endif // #if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l10358"></a><span class="lineno">10358</span>&#160; </div>
+<div class="line"><a name="l10359"></a><span class="lineno">10359</span>&#160;<span class="keywordtype">bool</span> VmaBlockMetadata_Linear::CreateAllocationRequest(</div>
+<div class="line"><a name="l10360"></a><span class="lineno">10360</span>&#160;    uint32_t currentFrameIndex,</div>
+<div class="line"><a name="l10361"></a><span class="lineno">10361</span>&#160;    uint32_t frameInUseCount,</div>
+<div class="line"><a name="l10362"></a><span class="lineno">10362</span>&#160;    VkDeviceSize bufferImageGranularity,</div>
+<div class="line"><a name="l10363"></a><span class="lineno">10363</span>&#160;    VkDeviceSize allocSize,</div>
+<div class="line"><a name="l10364"></a><span class="lineno">10364</span>&#160;    VkDeviceSize allocAlignment,</div>
+<div class="line"><a name="l10365"></a><span class="lineno">10365</span>&#160;    <span class="keywordtype">bool</span> upperAddress,</div>
+<div class="line"><a name="l10366"></a><span class="lineno">10366</span>&#160;    VmaSuballocationType allocType,</div>
+<div class="line"><a name="l10367"></a><span class="lineno">10367</span>&#160;    <span class="keywordtype">bool</span> canMakeOtherLost,</div>
+<div class="line"><a name="l10368"></a><span class="lineno">10368</span>&#160;    uint32_t strategy,</div>
+<div class="line"><a name="l10369"></a><span class="lineno">10369</span>&#160;    VmaAllocationRequest* pAllocationRequest)</div>
+<div class="line"><a name="l10370"></a><span class="lineno">10370</span>&#160;{</div>
+<div class="line"><a name="l10371"></a><span class="lineno">10371</span>&#160;    VMA_ASSERT(allocSize &gt; 0);</div>
+<div class="line"><a name="l10372"></a><span class="lineno">10372</span>&#160;    VMA_ASSERT(allocType != VMA_SUBALLOCATION_TYPE_FREE);</div>
+<div class="line"><a name="l10373"></a><span class="lineno">10373</span>&#160;    VMA_ASSERT(pAllocationRequest != VMA_NULL);</div>
+<div class="line"><a name="l10374"></a><span class="lineno">10374</span>&#160;    VMA_HEAVY_ASSERT(Validate());</div>
+<div class="line"><a name="l10375"></a><span class="lineno">10375</span>&#160;    <span class="keywordflow">return</span> upperAddress ?</div>
+<div class="line"><a name="l10376"></a><span class="lineno">10376</span>&#160;        CreateAllocationRequest_UpperAddress(</div>
+<div class="line"><a name="l10377"></a><span class="lineno">10377</span>&#160;            currentFrameIndex, frameInUseCount, bufferImageGranularity,</div>
+<div class="line"><a name="l10378"></a><span class="lineno">10378</span>&#160;            allocSize, allocAlignment, allocType, canMakeOtherLost, strategy, pAllocationRequest) :</div>
+<div class="line"><a name="l10379"></a><span class="lineno">10379</span>&#160;        CreateAllocationRequest_LowerAddress(</div>
+<div class="line"><a name="l10380"></a><span class="lineno">10380</span>&#160;            currentFrameIndex, frameInUseCount, bufferImageGranularity,</div>
+<div class="line"><a name="l10381"></a><span class="lineno">10381</span>&#160;            allocSize, allocAlignment, allocType, canMakeOtherLost, strategy, pAllocationRequest);</div>
+<div class="line"><a name="l10382"></a><span class="lineno">10382</span>&#160;}</div>
+<div class="line"><a name="l10383"></a><span class="lineno">10383</span>&#160; </div>
+<div class="line"><a name="l10384"></a><span class="lineno">10384</span>&#160;<span class="keywordtype">bool</span> VmaBlockMetadata_Linear::CreateAllocationRequest_UpperAddress(</div>
+<div class="line"><a name="l10385"></a><span class="lineno">10385</span>&#160;    uint32_t currentFrameIndex,</div>
+<div class="line"><a name="l10386"></a><span class="lineno">10386</span>&#160;    uint32_t frameInUseCount,</div>
+<div class="line"><a name="l10387"></a><span class="lineno">10387</span>&#160;    VkDeviceSize bufferImageGranularity,</div>
+<div class="line"><a name="l10388"></a><span class="lineno">10388</span>&#160;    VkDeviceSize allocSize,</div>
+<div class="line"><a name="l10389"></a><span class="lineno">10389</span>&#160;    VkDeviceSize allocAlignment,</div>
+<div class="line"><a name="l10390"></a><span class="lineno">10390</span>&#160;    VmaSuballocationType allocType,</div>
+<div class="line"><a name="l10391"></a><span class="lineno">10391</span>&#160;    <span class="keywordtype">bool</span> canMakeOtherLost,</div>
+<div class="line"><a name="l10392"></a><span class="lineno">10392</span>&#160;    uint32_t strategy,</div>
+<div class="line"><a name="l10393"></a><span class="lineno">10393</span>&#160;    VmaAllocationRequest* pAllocationRequest)</div>
+<div class="line"><a name="l10394"></a><span class="lineno">10394</span>&#160;{</div>
+<div class="line"><a name="l10395"></a><span class="lineno">10395</span>&#160;    <span class="keyword">const</span> VkDeviceSize size = GetSize();</div>
+<div class="line"><a name="l10396"></a><span class="lineno">10396</span>&#160;    SuballocationVectorType&amp; suballocations1st = AccessSuballocations1st();</div>
+<div class="line"><a name="l10397"></a><span class="lineno">10397</span>&#160;    SuballocationVectorType&amp; suballocations2nd = AccessSuballocations2nd();</div>
+<div class="line"><a name="l10398"></a><span class="lineno">10398</span>&#160; </div>
+<div class="line"><a name="l10399"></a><span class="lineno">10399</span>&#160;    <span class="keywordflow">if</span>(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)</div>
+<div class="line"><a name="l10400"></a><span class="lineno">10400</span>&#160;    {</div>
+<div class="line"><a name="l10401"></a><span class="lineno">10401</span>&#160;        VMA_ASSERT(0 &amp;&amp; <span class="stringliteral">&quot;Trying to use pool with linear algorithm as double stack, while it is already being used as ring buffer.&quot;</span>);</div>
+<div class="line"><a name="l10402"></a><span class="lineno">10402</span>&#160;        <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l10403"></a><span class="lineno">10403</span>&#160;    }</div>
+<div class="line"><a name="l10404"></a><span class="lineno">10404</span>&#160; </div>
+<div class="line"><a name="l10405"></a><span class="lineno">10405</span>&#160;    <span class="comment">// Try to allocate before 2nd.back(), or end of block if 2nd.empty().</span></div>
+<div class="line"><a name="l10406"></a><span class="lineno">10406</span>&#160;    <span class="keywordflow">if</span>(allocSize &gt; size)</div>
+<div class="line"><a name="l10407"></a><span class="lineno">10407</span>&#160;    {</div>
+<div class="line"><a name="l10408"></a><span class="lineno">10408</span>&#160;        <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l10409"></a><span class="lineno">10409</span>&#160;    }</div>
+<div class="line"><a name="l10410"></a><span class="lineno">10410</span>&#160;    VkDeviceSize resultBaseOffset = size - allocSize;</div>
+<div class="line"><a name="l10411"></a><span class="lineno">10411</span>&#160;    <span class="keywordflow">if</span>(!suballocations2nd.empty())</div>
+<div class="line"><a name="l10412"></a><span class="lineno">10412</span>&#160;    {</div>
+<div class="line"><a name="l10413"></a><span class="lineno">10413</span>&#160;        <span class="keyword">const</span> VmaSuballocation&amp; lastSuballoc = suballocations2nd.back();</div>
+<div class="line"><a name="l10414"></a><span class="lineno">10414</span>&#160;        resultBaseOffset = lastSuballoc.offset - allocSize;</div>
+<div class="line"><a name="l10415"></a><span class="lineno">10415</span>&#160;        <span class="keywordflow">if</span>(allocSize &gt; lastSuballoc.offset)</div>
+<div class="line"><a name="l10416"></a><span class="lineno">10416</span>&#160;        {</div>
+<div class="line"><a name="l10417"></a><span class="lineno">10417</span>&#160;            <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l10418"></a><span class="lineno">10418</span>&#160;        }</div>
+<div class="line"><a name="l10419"></a><span class="lineno">10419</span>&#160;    }</div>
+<div class="line"><a name="l10420"></a><span class="lineno">10420</span>&#160; </div>
+<div class="line"><a name="l10421"></a><span class="lineno">10421</span>&#160;    <span class="comment">// Start from offset equal to end of free space.</span></div>
+<div class="line"><a name="l10422"></a><span class="lineno">10422</span>&#160;    VkDeviceSize resultOffset = resultBaseOffset;</div>
+<div class="line"><a name="l10423"></a><span class="lineno">10423</span>&#160; </div>
+<div class="line"><a name="l10424"></a><span class="lineno">10424</span>&#160;    <span class="comment">// Apply VMA_DEBUG_MARGIN at the end.</span></div>
+<div class="line"><a name="l10425"></a><span class="lineno">10425</span>&#160;    <span class="keywordflow">if</span>(VMA_DEBUG_MARGIN &gt; 0)</div>
+<div class="line"><a name="l10426"></a><span class="lineno">10426</span>&#160;    {</div>
+<div class="line"><a name="l10427"></a><span class="lineno">10427</span>&#160;        <span class="keywordflow">if</span>(resultOffset &lt; VMA_DEBUG_MARGIN)</div>
+<div class="line"><a name="l10428"></a><span class="lineno">10428</span>&#160;        {</div>
+<div class="line"><a name="l10429"></a><span class="lineno">10429</span>&#160;            <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l10430"></a><span class="lineno">10430</span>&#160;        }</div>
+<div class="line"><a name="l10431"></a><span class="lineno">10431</span>&#160;        resultOffset -= VMA_DEBUG_MARGIN;</div>
+<div class="line"><a name="l10432"></a><span class="lineno">10432</span>&#160;    }</div>
+<div class="line"><a name="l10433"></a><span class="lineno">10433</span>&#160; </div>
+<div class="line"><a name="l10434"></a><span class="lineno">10434</span>&#160;    <span class="comment">// Apply alignment.</span></div>
+<div class="line"><a name="l10435"></a><span class="lineno">10435</span>&#160;    resultOffset = VmaAlignDown(resultOffset, allocAlignment);</div>
+<div class="line"><a name="l10436"></a><span class="lineno">10436</span>&#160; </div>
+<div class="line"><a name="l10437"></a><span class="lineno">10437</span>&#160;    <span class="comment">// Check next suballocations from 2nd for BufferImageGranularity conflicts.</span></div>
+<div class="line"><a name="l10438"></a><span class="lineno">10438</span>&#160;    <span class="comment">// Make bigger alignment if necessary.</span></div>
+<div class="line"><a name="l10439"></a><span class="lineno">10439</span>&#160;    <span class="keywordflow">if</span>(bufferImageGranularity &gt; 1 &amp;&amp; !suballocations2nd.empty())</div>
+<div class="line"><a name="l10440"></a><span class="lineno">10440</span>&#160;    {</div>
+<div class="line"><a name="l10441"></a><span class="lineno">10441</span>&#160;        <span class="keywordtype">bool</span> bufferImageGranularityConflict = <span class="keyword">false</span>;</div>
+<div class="line"><a name="l10442"></a><span class="lineno">10442</span>&#160;        <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> nextSuballocIndex = suballocations2nd.size(); nextSuballocIndex--; )</div>
+<div class="line"><a name="l10443"></a><span class="lineno">10443</span>&#160;        {</div>
+<div class="line"><a name="l10444"></a><span class="lineno">10444</span>&#160;            <span class="keyword">const</span> VmaSuballocation&amp; nextSuballoc = suballocations2nd[nextSuballocIndex];</div>
+<div class="line"><a name="l10445"></a><span class="lineno">10445</span>&#160;            <span class="keywordflow">if</span>(VmaBlocksOnSamePage(resultOffset, allocSize, nextSuballoc.offset, bufferImageGranularity))</div>
+<div class="line"><a name="l10446"></a><span class="lineno">10446</span>&#160;            {</div>
+<div class="line"><a name="l10447"></a><span class="lineno">10447</span>&#160;                <span class="keywordflow">if</span>(VmaIsBufferImageGranularityConflict(nextSuballoc.type, allocType))</div>
+<div class="line"><a name="l10448"></a><span class="lineno">10448</span>&#160;                {</div>
+<div class="line"><a name="l10449"></a><span class="lineno">10449</span>&#160;                    bufferImageGranularityConflict = <span class="keyword">true</span>;</div>
+<div class="line"><a name="l10450"></a><span class="lineno">10450</span>&#160;                    <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l10451"></a><span class="lineno">10451</span>&#160;                }</div>
+<div class="line"><a name="l10452"></a><span class="lineno">10452</span>&#160;            }</div>
+<div class="line"><a name="l10453"></a><span class="lineno">10453</span>&#160;            <span class="keywordflow">else</span></div>
+<div class="line"><a name="l10454"></a><span class="lineno">10454</span>&#160;                <span class="comment">// Already on previous page.</span></div>
+<div class="line"><a name="l10455"></a><span class="lineno">10455</span>&#160;                <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l10456"></a><span class="lineno">10456</span>&#160;        }</div>
+<div class="line"><a name="l10457"></a><span class="lineno">10457</span>&#160;        <span class="keywordflow">if</span>(bufferImageGranularityConflict)</div>
+<div class="line"><a name="l10458"></a><span class="lineno">10458</span>&#160;        {</div>
+<div class="line"><a name="l10459"></a><span class="lineno">10459</span>&#160;            resultOffset = VmaAlignDown(resultOffset, bufferImageGranularity);</div>
+<div class="line"><a name="l10460"></a><span class="lineno">10460</span>&#160;        }</div>
+<div class="line"><a name="l10461"></a><span class="lineno">10461</span>&#160;    }</div>
+<div class="line"><a name="l10462"></a><span class="lineno">10462</span>&#160; </div>
+<div class="line"><a name="l10463"></a><span class="lineno">10463</span>&#160;    <span class="comment">// There is enough free space.</span></div>
+<div class="line"><a name="l10464"></a><span class="lineno">10464</span>&#160;    <span class="keyword">const</span> VkDeviceSize endOf1st = !suballocations1st.empty() ?</div>
+<div class="line"><a name="l10465"></a><span class="lineno">10465</span>&#160;        suballocations1st.back().offset + suballocations1st.back().size :</div>
+<div class="line"><a name="l10466"></a><span class="lineno">10466</span>&#160;        0;</div>
+<div class="line"><a name="l10467"></a><span class="lineno">10467</span>&#160;    <span class="keywordflow">if</span>(endOf1st + VMA_DEBUG_MARGIN &lt;= resultOffset)</div>
+<div class="line"><a name="l10468"></a><span class="lineno">10468</span>&#160;    {</div>
+<div class="line"><a name="l10469"></a><span class="lineno">10469</span>&#160;        <span class="comment">// Check previous suballocations for BufferImageGranularity conflicts.</span></div>
+<div class="line"><a name="l10470"></a><span class="lineno">10470</span>&#160;        <span class="comment">// If conflict exists, allocation cannot be made here.</span></div>
+<div class="line"><a name="l10471"></a><span class="lineno">10471</span>&#160;        <span class="keywordflow">if</span>(bufferImageGranularity &gt; 1)</div>
+<div class="line"><a name="l10472"></a><span class="lineno">10472</span>&#160;        {</div>
+<div class="line"><a name="l10473"></a><span class="lineno">10473</span>&#160;            <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> prevSuballocIndex = suballocations1st.size(); prevSuballocIndex--; )</div>
+<div class="line"><a name="l10474"></a><span class="lineno">10474</span>&#160;            {</div>
+<div class="line"><a name="l10475"></a><span class="lineno">10475</span>&#160;                <span class="keyword">const</span> VmaSuballocation&amp; prevSuballoc = suballocations1st[prevSuballocIndex];</div>
+<div class="line"><a name="l10476"></a><span class="lineno">10476</span>&#160;                <span class="keywordflow">if</span>(VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, resultOffset, bufferImageGranularity))</div>
+<div class="line"><a name="l10477"></a><span class="lineno">10477</span>&#160;                {</div>
+<div class="line"><a name="l10478"></a><span class="lineno">10478</span>&#160;                    <span class="keywordflow">if</span>(VmaIsBufferImageGranularityConflict(allocType, prevSuballoc.type))</div>
+<div class="line"><a name="l10479"></a><span class="lineno">10479</span>&#160;                    {</div>
+<div class="line"><a name="l10480"></a><span class="lineno">10480</span>&#160;                        <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l10481"></a><span class="lineno">10481</span>&#160;                    }</div>
+<div class="line"><a name="l10482"></a><span class="lineno">10482</span>&#160;                }</div>
+<div class="line"><a name="l10483"></a><span class="lineno">10483</span>&#160;                <span class="keywordflow">else</span></div>
+<div class="line"><a name="l10484"></a><span class="lineno">10484</span>&#160;                {</div>
+<div class="line"><a name="l10485"></a><span class="lineno">10485</span>&#160;                    <span class="comment">// Already on next page.</span></div>
+<div class="line"><a name="l10486"></a><span class="lineno">10486</span>&#160;                    <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l10487"></a><span class="lineno">10487</span>&#160;                }</div>
+<div class="line"><a name="l10488"></a><span class="lineno">10488</span>&#160;            }</div>
+<div class="line"><a name="l10489"></a><span class="lineno">10489</span>&#160;        }</div>
+<div class="line"><a name="l10490"></a><span class="lineno">10490</span>&#160; </div>
+<div class="line"><a name="l10491"></a><span class="lineno">10491</span>&#160;        <span class="comment">// All tests passed: Success.</span></div>
+<div class="line"><a name="l10492"></a><span class="lineno">10492</span>&#160;        pAllocationRequest-&gt;offset = resultOffset;</div>
+<div class="line"><a name="l10493"></a><span class="lineno">10493</span>&#160;        pAllocationRequest-&gt;sumFreeSize = resultBaseOffset + allocSize - endOf1st;</div>
+<div class="line"><a name="l10494"></a><span class="lineno">10494</span>&#160;        pAllocationRequest-&gt;sumItemSize = 0;</div>
+<div class="line"><a name="l10495"></a><span class="lineno">10495</span>&#160;        <span class="comment">// pAllocationRequest-&gt;item unused.</span></div>
+<div class="line"><a name="l10496"></a><span class="lineno">10496</span>&#160;        pAllocationRequest-&gt;itemsToMakeLostCount = 0;</div>
+<div class="line"><a name="l10497"></a><span class="lineno">10497</span>&#160;        pAllocationRequest-&gt;type = VmaAllocationRequestType::UpperAddress;</div>
+<div class="line"><a name="l10498"></a><span class="lineno">10498</span>&#160;        <span class="keywordflow">return</span> <span class="keyword">true</span>;</div>
+<div class="line"><a name="l10499"></a><span class="lineno">10499</span>&#160;    }</div>
+<div class="line"><a name="l10500"></a><span class="lineno">10500</span>&#160; </div>
+<div class="line"><a name="l10501"></a><span class="lineno">10501</span>&#160;    <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l10502"></a><span class="lineno">10502</span>&#160;}</div>
+<div class="line"><a name="l10503"></a><span class="lineno">10503</span>&#160; </div>
+<div class="line"><a name="l10504"></a><span class="lineno">10504</span>&#160;<span class="keywordtype">bool</span> VmaBlockMetadata_Linear::CreateAllocationRequest_LowerAddress(</div>
+<div class="line"><a name="l10505"></a><span class="lineno">10505</span>&#160;    uint32_t currentFrameIndex,</div>
+<div class="line"><a name="l10506"></a><span class="lineno">10506</span>&#160;    uint32_t frameInUseCount,</div>
+<div class="line"><a name="l10507"></a><span class="lineno">10507</span>&#160;    VkDeviceSize bufferImageGranularity,</div>
+<div class="line"><a name="l10508"></a><span class="lineno">10508</span>&#160;    VkDeviceSize allocSize,</div>
+<div class="line"><a name="l10509"></a><span class="lineno">10509</span>&#160;    VkDeviceSize allocAlignment,</div>
+<div class="line"><a name="l10510"></a><span class="lineno">10510</span>&#160;    VmaSuballocationType allocType,</div>
+<div class="line"><a name="l10511"></a><span class="lineno">10511</span>&#160;    <span class="keywordtype">bool</span> canMakeOtherLost,</div>
+<div class="line"><a name="l10512"></a><span class="lineno">10512</span>&#160;    uint32_t strategy,</div>
+<div class="line"><a name="l10513"></a><span class="lineno">10513</span>&#160;    VmaAllocationRequest* pAllocationRequest)</div>
+<div class="line"><a name="l10514"></a><span class="lineno">10514</span>&#160;{</div>
+<div class="line"><a name="l10515"></a><span class="lineno">10515</span>&#160;    <span class="keyword">const</span> VkDeviceSize size = GetSize();</div>
+<div class="line"><a name="l10516"></a><span class="lineno">10516</span>&#160;    SuballocationVectorType&amp; suballocations1st = AccessSuballocations1st();</div>
+<div class="line"><a name="l10517"></a><span class="lineno">10517</span>&#160;    SuballocationVectorType&amp; suballocations2nd = AccessSuballocations2nd();</div>
+<div class="line"><a name="l10518"></a><span class="lineno">10518</span>&#160; </div>
+<div class="line"><a name="l10519"></a><span class="lineno">10519</span>&#160;    <span class="keywordflow">if</span>(m_2ndVectorMode == SECOND_VECTOR_EMPTY || m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)</div>
+<div class="line"><a name="l10520"></a><span class="lineno">10520</span>&#160;    {</div>
+<div class="line"><a name="l10521"></a><span class="lineno">10521</span>&#160;        <span class="comment">// Try to allocate at the end of 1st vector.</span></div>
+<div class="line"><a name="l10522"></a><span class="lineno">10522</span>&#160; </div>
+<div class="line"><a name="l10523"></a><span class="lineno">10523</span>&#160;        VkDeviceSize resultBaseOffset = 0;</div>
+<div class="line"><a name="l10524"></a><span class="lineno">10524</span>&#160;        <span class="keywordflow">if</span>(!suballocations1st.empty())</div>
+<div class="line"><a name="l10525"></a><span class="lineno">10525</span>&#160;        {</div>
+<div class="line"><a name="l10526"></a><span class="lineno">10526</span>&#160;            <span class="keyword">const</span> VmaSuballocation&amp; lastSuballoc = suballocations1st.back();</div>
+<div class="line"><a name="l10527"></a><span class="lineno">10527</span>&#160;            resultBaseOffset = lastSuballoc.offset + lastSuballoc.size;</div>
+<div class="line"><a name="l10528"></a><span class="lineno">10528</span>&#160;        }</div>
+<div class="line"><a name="l10529"></a><span class="lineno">10529</span>&#160; </div>
+<div class="line"><a name="l10530"></a><span class="lineno">10530</span>&#160;        <span class="comment">// Start from offset equal to beginning of free space.</span></div>
+<div class="line"><a name="l10531"></a><span class="lineno">10531</span>&#160;        VkDeviceSize resultOffset = resultBaseOffset;</div>
+<div class="line"><a name="l10532"></a><span class="lineno">10532</span>&#160; </div>
+<div class="line"><a name="l10533"></a><span class="lineno">10533</span>&#160;        <span class="comment">// Apply VMA_DEBUG_MARGIN at the beginning.</span></div>
+<div class="line"><a name="l10534"></a><span class="lineno">10534</span>&#160;        <span class="keywordflow">if</span>(VMA_DEBUG_MARGIN &gt; 0)</div>
+<div class="line"><a name="l10535"></a><span class="lineno">10535</span>&#160;        {</div>
+<div class="line"><a name="l10536"></a><span class="lineno">10536</span>&#160;            resultOffset += VMA_DEBUG_MARGIN;</div>
+<div class="line"><a name="l10537"></a><span class="lineno">10537</span>&#160;        }</div>
+<div class="line"><a name="l10538"></a><span class="lineno">10538</span>&#160; </div>
+<div class="line"><a name="l10539"></a><span class="lineno">10539</span>&#160;        <span class="comment">// Apply alignment.</span></div>
+<div class="line"><a name="l10540"></a><span class="lineno">10540</span>&#160;        resultOffset = VmaAlignUp(resultOffset, allocAlignment);</div>
+<div class="line"><a name="l10541"></a><span class="lineno">10541</span>&#160; </div>
+<div class="line"><a name="l10542"></a><span class="lineno">10542</span>&#160;        <span class="comment">// Check previous suballocations for BufferImageGranularity conflicts.</span></div>
+<div class="line"><a name="l10543"></a><span class="lineno">10543</span>&#160;        <span class="comment">// Make bigger alignment if necessary.</span></div>
+<div class="line"><a name="l10544"></a><span class="lineno">10544</span>&#160;        <span class="keywordflow">if</span>(bufferImageGranularity &gt; 1 &amp;&amp; !suballocations1st.empty())</div>
+<div class="line"><a name="l10545"></a><span class="lineno">10545</span>&#160;        {</div>
+<div class="line"><a name="l10546"></a><span class="lineno">10546</span>&#160;            <span class="keywordtype">bool</span> bufferImageGranularityConflict = <span class="keyword">false</span>;</div>
+<div class="line"><a name="l10547"></a><span class="lineno">10547</span>&#160;            <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> prevSuballocIndex = suballocations1st.size(); prevSuballocIndex--; )</div>
+<div class="line"><a name="l10548"></a><span class="lineno">10548</span>&#160;            {</div>
+<div class="line"><a name="l10549"></a><span class="lineno">10549</span>&#160;                <span class="keyword">const</span> VmaSuballocation&amp; prevSuballoc = suballocations1st[prevSuballocIndex];</div>
+<div class="line"><a name="l10550"></a><span class="lineno">10550</span>&#160;                <span class="keywordflow">if</span>(VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, resultOffset, bufferImageGranularity))</div>
+<div class="line"><a name="l10551"></a><span class="lineno">10551</span>&#160;                {</div>
+<div class="line"><a name="l10552"></a><span class="lineno">10552</span>&#160;                    <span class="keywordflow">if</span>(VmaIsBufferImageGranularityConflict(prevSuballoc.type, allocType))</div>
+<div class="line"><a name="l10553"></a><span class="lineno">10553</span>&#160;                    {</div>
+<div class="line"><a name="l10554"></a><span class="lineno">10554</span>&#160;                        bufferImageGranularityConflict = <span class="keyword">true</span>;</div>
+<div class="line"><a name="l10555"></a><span class="lineno">10555</span>&#160;                        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l10556"></a><span class="lineno">10556</span>&#160;                    }</div>
+<div class="line"><a name="l10557"></a><span class="lineno">10557</span>&#160;                }</div>
+<div class="line"><a name="l10558"></a><span class="lineno">10558</span>&#160;                <span class="keywordflow">else</span></div>
+<div class="line"><a name="l10559"></a><span class="lineno">10559</span>&#160;                    <span class="comment">// Already on previous page.</span></div>
+<div class="line"><a name="l10560"></a><span class="lineno">10560</span>&#160;                    <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l10561"></a><span class="lineno">10561</span>&#160;            }</div>
+<div class="line"><a name="l10562"></a><span class="lineno">10562</span>&#160;            <span class="keywordflow">if</span>(bufferImageGranularityConflict)</div>
+<div class="line"><a name="l10563"></a><span class="lineno">10563</span>&#160;            {</div>
+<div class="line"><a name="l10564"></a><span class="lineno">10564</span>&#160;                resultOffset = VmaAlignUp(resultOffset, bufferImageGranularity);</div>
+<div class="line"><a name="l10565"></a><span class="lineno">10565</span>&#160;            }</div>
+<div class="line"><a name="l10566"></a><span class="lineno">10566</span>&#160;        }</div>
+<div class="line"><a name="l10567"></a><span class="lineno">10567</span>&#160; </div>
+<div class="line"><a name="l10568"></a><span class="lineno">10568</span>&#160;        <span class="keyword">const</span> VkDeviceSize freeSpaceEnd = m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK ?</div>
+<div class="line"><a name="l10569"></a><span class="lineno">10569</span>&#160;            suballocations2nd.back().offset : size;</div>
+<div class="line"><a name="l10570"></a><span class="lineno">10570</span>&#160; </div>
+<div class="line"><a name="l10571"></a><span class="lineno">10571</span>&#160;        <span class="comment">// There is enough free space at the end after alignment.</span></div>
+<div class="line"><a name="l10572"></a><span class="lineno">10572</span>&#160;        <span class="keywordflow">if</span>(resultOffset + allocSize + VMA_DEBUG_MARGIN &lt;= freeSpaceEnd)</div>
+<div class="line"><a name="l10573"></a><span class="lineno">10573</span>&#160;        {</div>
+<div class="line"><a name="l10574"></a><span class="lineno">10574</span>&#160;            <span class="comment">// Check next suballocations for BufferImageGranularity conflicts.</span></div>
+<div class="line"><a name="l10575"></a><span class="lineno">10575</span>&#160;            <span class="comment">// If conflict exists, allocation cannot be made here.</span></div>
+<div class="line"><a name="l10576"></a><span class="lineno">10576</span>&#160;            <span class="keywordflow">if</span>(bufferImageGranularity &gt; 1 &amp;&amp; m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)</div>
+<div class="line"><a name="l10577"></a><span class="lineno">10577</span>&#160;            {</div>
+<div class="line"><a name="l10578"></a><span class="lineno">10578</span>&#160;                <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> nextSuballocIndex = suballocations2nd.size(); nextSuballocIndex--; )</div>
+<div class="line"><a name="l10579"></a><span class="lineno">10579</span>&#160;                {</div>
+<div class="line"><a name="l10580"></a><span class="lineno">10580</span>&#160;                    <span class="keyword">const</span> VmaSuballocation&amp; nextSuballoc = suballocations2nd[nextSuballocIndex];</div>
+<div class="line"><a name="l10581"></a><span class="lineno">10581</span>&#160;                    <span class="keywordflow">if</span>(VmaBlocksOnSamePage(resultOffset, allocSize, nextSuballoc.offset, bufferImageGranularity))</div>
+<div class="line"><a name="l10582"></a><span class="lineno">10582</span>&#160;                    {</div>
+<div class="line"><a name="l10583"></a><span class="lineno">10583</span>&#160;                        <span class="keywordflow">if</span>(VmaIsBufferImageGranularityConflict(allocType, nextSuballoc.type))</div>
+<div class="line"><a name="l10584"></a><span class="lineno">10584</span>&#160;                        {</div>
+<div class="line"><a name="l10585"></a><span class="lineno">10585</span>&#160;                            <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l10586"></a><span class="lineno">10586</span>&#160;                        }</div>
+<div class="line"><a name="l10587"></a><span class="lineno">10587</span>&#160;                    }</div>
+<div class="line"><a name="l10588"></a><span class="lineno">10588</span>&#160;                    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l10589"></a><span class="lineno">10589</span>&#160;                    {</div>
+<div class="line"><a name="l10590"></a><span class="lineno">10590</span>&#160;                        <span class="comment">// Already on previous page.</span></div>
+<div class="line"><a name="l10591"></a><span class="lineno">10591</span>&#160;                        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l10592"></a><span class="lineno">10592</span>&#160;                    }</div>
+<div class="line"><a name="l10593"></a><span class="lineno">10593</span>&#160;                }</div>
+<div class="line"><a name="l10594"></a><span class="lineno">10594</span>&#160;            }</div>
+<div class="line"><a name="l10595"></a><span class="lineno">10595</span>&#160; </div>
+<div class="line"><a name="l10596"></a><span class="lineno">10596</span>&#160;            <span class="comment">// All tests passed: Success.</span></div>
+<div class="line"><a name="l10597"></a><span class="lineno">10597</span>&#160;            pAllocationRequest-&gt;offset = resultOffset;</div>
+<div class="line"><a name="l10598"></a><span class="lineno">10598</span>&#160;            pAllocationRequest-&gt;sumFreeSize = freeSpaceEnd - resultBaseOffset;</div>
+<div class="line"><a name="l10599"></a><span class="lineno">10599</span>&#160;            pAllocationRequest-&gt;sumItemSize = 0;</div>
+<div class="line"><a name="l10600"></a><span class="lineno">10600</span>&#160;            <span class="comment">// pAllocationRequest-&gt;item, customData unused.</span></div>
+<div class="line"><a name="l10601"></a><span class="lineno">10601</span>&#160;            pAllocationRequest-&gt;type = VmaAllocationRequestType::EndOf1st;</div>
+<div class="line"><a name="l10602"></a><span class="lineno">10602</span>&#160;            pAllocationRequest-&gt;itemsToMakeLostCount = 0;</div>
+<div class="line"><a name="l10603"></a><span class="lineno">10603</span>&#160;            <span class="keywordflow">return</span> <span class="keyword">true</span>;</div>
+<div class="line"><a name="l10604"></a><span class="lineno">10604</span>&#160;        }</div>
+<div class="line"><a name="l10605"></a><span class="lineno">10605</span>&#160;    }</div>
+<div class="line"><a name="l10606"></a><span class="lineno">10606</span>&#160; </div>
+<div class="line"><a name="l10607"></a><span class="lineno">10607</span>&#160;    <span class="comment">// Wrap-around to end of 2nd vector. Try to allocate there, watching for the</span></div>
+<div class="line"><a name="l10608"></a><span class="lineno">10608</span>&#160;    <span class="comment">// beginning of 1st vector as the end of free space.</span></div>
+<div class="line"><a name="l10609"></a><span class="lineno">10609</span>&#160;    <span class="keywordflow">if</span>(m_2ndVectorMode == SECOND_VECTOR_EMPTY || m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)</div>
+<div class="line"><a name="l10610"></a><span class="lineno">10610</span>&#160;    {</div>
+<div class="line"><a name="l10611"></a><span class="lineno">10611</span>&#160;        VMA_ASSERT(!suballocations1st.empty());</div>
+<div class="line"><a name="l10612"></a><span class="lineno">10612</span>&#160; </div>
+<div class="line"><a name="l10613"></a><span class="lineno">10613</span>&#160;        VkDeviceSize resultBaseOffset = 0;</div>
+<div class="line"><a name="l10614"></a><span class="lineno">10614</span>&#160;        <span class="keywordflow">if</span>(!suballocations2nd.empty())</div>
+<div class="line"><a name="l10615"></a><span class="lineno">10615</span>&#160;        {</div>
+<div class="line"><a name="l10616"></a><span class="lineno">10616</span>&#160;            <span class="keyword">const</span> VmaSuballocation&amp; lastSuballoc = suballocations2nd.back();</div>
+<div class="line"><a name="l10617"></a><span class="lineno">10617</span>&#160;            resultBaseOffset = lastSuballoc.offset + lastSuballoc.size;</div>
+<div class="line"><a name="l10618"></a><span class="lineno">10618</span>&#160;        }</div>
+<div class="line"><a name="l10619"></a><span class="lineno">10619</span>&#160; </div>
+<div class="line"><a name="l10620"></a><span class="lineno">10620</span>&#160;        <span class="comment">// Start from offset equal to beginning of free space.</span></div>
+<div class="line"><a name="l10621"></a><span class="lineno">10621</span>&#160;        VkDeviceSize resultOffset = resultBaseOffset;</div>
+<div class="line"><a name="l10622"></a><span class="lineno">10622</span>&#160; </div>
+<div class="line"><a name="l10623"></a><span class="lineno">10623</span>&#160;        <span class="comment">// Apply VMA_DEBUG_MARGIN at the beginning.</span></div>
+<div class="line"><a name="l10624"></a><span class="lineno">10624</span>&#160;        <span class="keywordflow">if</span>(VMA_DEBUG_MARGIN &gt; 0)</div>
+<div class="line"><a name="l10625"></a><span class="lineno">10625</span>&#160;        {</div>
+<div class="line"><a name="l10626"></a><span class="lineno">10626</span>&#160;            resultOffset += VMA_DEBUG_MARGIN;</div>
+<div class="line"><a name="l10627"></a><span class="lineno">10627</span>&#160;        }</div>
+<div class="line"><a name="l10628"></a><span class="lineno">10628</span>&#160; </div>
+<div class="line"><a name="l10629"></a><span class="lineno">10629</span>&#160;        <span class="comment">// Apply alignment.</span></div>
+<div class="line"><a name="l10630"></a><span class="lineno">10630</span>&#160;        resultOffset = VmaAlignUp(resultOffset, allocAlignment);</div>
+<div class="line"><a name="l10631"></a><span class="lineno">10631</span>&#160; </div>
+<div class="line"><a name="l10632"></a><span class="lineno">10632</span>&#160;        <span class="comment">// Check previous suballocations for BufferImageGranularity conflicts.</span></div>
+<div class="line"><a name="l10633"></a><span class="lineno">10633</span>&#160;        <span class="comment">// Make bigger alignment if necessary.</span></div>
+<div class="line"><a name="l10634"></a><span class="lineno">10634</span>&#160;        <span class="keywordflow">if</span>(bufferImageGranularity &gt; 1 &amp;&amp; !suballocations2nd.empty())</div>
+<div class="line"><a name="l10635"></a><span class="lineno">10635</span>&#160;        {</div>
+<div class="line"><a name="l10636"></a><span class="lineno">10636</span>&#160;            <span class="keywordtype">bool</span> bufferImageGranularityConflict = <span class="keyword">false</span>;</div>
+<div class="line"><a name="l10637"></a><span class="lineno">10637</span>&#160;            <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> prevSuballocIndex = suballocations2nd.size(); prevSuballocIndex--; )</div>
+<div class="line"><a name="l10638"></a><span class="lineno">10638</span>&#160;            {</div>
+<div class="line"><a name="l10639"></a><span class="lineno">10639</span>&#160;                <span class="keyword">const</span> VmaSuballocation&amp; prevSuballoc = suballocations2nd[prevSuballocIndex];</div>
+<div class="line"><a name="l10640"></a><span class="lineno">10640</span>&#160;                <span class="keywordflow">if</span>(VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, resultOffset, bufferImageGranularity))</div>
+<div class="line"><a name="l10641"></a><span class="lineno">10641</span>&#160;                {</div>
+<div class="line"><a name="l10642"></a><span class="lineno">10642</span>&#160;                    <span class="keywordflow">if</span>(VmaIsBufferImageGranularityConflict(prevSuballoc.type, allocType))</div>
+<div class="line"><a name="l10643"></a><span class="lineno">10643</span>&#160;                    {</div>
+<div class="line"><a name="l10644"></a><span class="lineno">10644</span>&#160;                        bufferImageGranularityConflict = <span class="keyword">true</span>;</div>
+<div class="line"><a name="l10645"></a><span class="lineno">10645</span>&#160;                        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l10646"></a><span class="lineno">10646</span>&#160;                    }</div>
+<div class="line"><a name="l10647"></a><span class="lineno">10647</span>&#160;                }</div>
+<div class="line"><a name="l10648"></a><span class="lineno">10648</span>&#160;                <span class="keywordflow">else</span></div>
+<div class="line"><a name="l10649"></a><span class="lineno">10649</span>&#160;                    <span class="comment">// Already on previous page.</span></div>
+<div class="line"><a name="l10650"></a><span class="lineno">10650</span>&#160;                    <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l10651"></a><span class="lineno">10651</span>&#160;            }</div>
+<div class="line"><a name="l10652"></a><span class="lineno">10652</span>&#160;            <span class="keywordflow">if</span>(bufferImageGranularityConflict)</div>
+<div class="line"><a name="l10653"></a><span class="lineno">10653</span>&#160;            {</div>
+<div class="line"><a name="l10654"></a><span class="lineno">10654</span>&#160;                resultOffset = VmaAlignUp(resultOffset, bufferImageGranularity);</div>
+<div class="line"><a name="l10655"></a><span class="lineno">10655</span>&#160;            }</div>
+<div class="line"><a name="l10656"></a><span class="lineno">10656</span>&#160;        }</div>
+<div class="line"><a name="l10657"></a><span class="lineno">10657</span>&#160; </div>
+<div class="line"><a name="l10658"></a><span class="lineno">10658</span>&#160;        pAllocationRequest-&gt;itemsToMakeLostCount = 0;</div>
+<div class="line"><a name="l10659"></a><span class="lineno">10659</span>&#160;        pAllocationRequest-&gt;sumItemSize = 0;</div>
+<div class="line"><a name="l10660"></a><span class="lineno">10660</span>&#160;        <span class="keywordtype">size_t</span> index1st = m_1stNullItemsBeginCount;</div>
+<div class="line"><a name="l10661"></a><span class="lineno">10661</span>&#160; </div>
+<div class="line"><a name="l10662"></a><span class="lineno">10662</span>&#160;        <span class="keywordflow">if</span>(canMakeOtherLost)</div>
+<div class="line"><a name="l10663"></a><span class="lineno">10663</span>&#160;        {</div>
+<div class="line"><a name="l10664"></a><span class="lineno">10664</span>&#160;            <span class="keywordflow">while</span>(index1st &lt; suballocations1st.size() &amp;&amp;</div>
+<div class="line"><a name="l10665"></a><span class="lineno">10665</span>&#160;                resultOffset + allocSize + VMA_DEBUG_MARGIN &gt; suballocations1st[index1st].offset)</div>
+<div class="line"><a name="l10666"></a><span class="lineno">10666</span>&#160;            {</div>
+<div class="line"><a name="l10667"></a><span class="lineno">10667</span>&#160;                <span class="comment">// Next colliding allocation at the beginning of 1st vector found. Try to make it lost.</span></div>
+<div class="line"><a name="l10668"></a><span class="lineno">10668</span>&#160;                <span class="keyword">const</span> VmaSuballocation&amp; suballoc = suballocations1st[index1st];</div>
+<div class="line"><a name="l10669"></a><span class="lineno">10669</span>&#160;                <span class="keywordflow">if</span>(suballoc.type == VMA_SUBALLOCATION_TYPE_FREE)</div>
+<div class="line"><a name="l10670"></a><span class="lineno">10670</span>&#160;                {</div>
+<div class="line"><a name="l10671"></a><span class="lineno">10671</span>&#160;                    <span class="comment">// No problem.</span></div>
+<div class="line"><a name="l10672"></a><span class="lineno">10672</span>&#160;                }</div>
+<div class="line"><a name="l10673"></a><span class="lineno">10673</span>&#160;                <span class="keywordflow">else</span></div>
+<div class="line"><a name="l10674"></a><span class="lineno">10674</span>&#160;                {</div>
+<div class="line"><a name="l10675"></a><span class="lineno">10675</span>&#160;                    VMA_ASSERT(suballoc.hAllocation != VK_NULL_HANDLE);</div>
+<div class="line"><a name="l10676"></a><span class="lineno">10676</span>&#160;                    <span class="keywordflow">if</span>(suballoc.hAllocation-&gt;CanBecomeLost() &amp;&amp;</div>
+<div class="line"><a name="l10677"></a><span class="lineno">10677</span>&#160;                        suballoc.hAllocation-&gt;GetLastUseFrameIndex() + frameInUseCount &lt; currentFrameIndex)</div>
+<div class="line"><a name="l10678"></a><span class="lineno">10678</span>&#160;                    {</div>
+<div class="line"><a name="l10679"></a><span class="lineno">10679</span>&#160;                        ++pAllocationRequest-&gt;itemsToMakeLostCount;</div>
+<div class="line"><a name="l10680"></a><span class="lineno">10680</span>&#160;                        pAllocationRequest-&gt;sumItemSize += suballoc.size;</div>
+<div class="line"><a name="l10681"></a><span class="lineno">10681</span>&#160;                    }</div>
+<div class="line"><a name="l10682"></a><span class="lineno">10682</span>&#160;                    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l10683"></a><span class="lineno">10683</span>&#160;                    {</div>
+<div class="line"><a name="l10684"></a><span class="lineno">10684</span>&#160;                        <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l10685"></a><span class="lineno">10685</span>&#160;                    }</div>
+<div class="line"><a name="l10686"></a><span class="lineno">10686</span>&#160;                }</div>
+<div class="line"><a name="l10687"></a><span class="lineno">10687</span>&#160;                ++index1st;</div>
+<div class="line"><a name="l10688"></a><span class="lineno">10688</span>&#160;            }</div>
+<div class="line"><a name="l10689"></a><span class="lineno">10689</span>&#160; </div>
+<div class="line"><a name="l10690"></a><span class="lineno">10690</span>&#160;            <span class="comment">// Check next suballocations for BufferImageGranularity conflicts.</span></div>
+<div class="line"><a name="l10691"></a><span class="lineno">10691</span>&#160;            <span class="comment">// If conflict exists, we must mark more allocations lost or fail.</span></div>
+<div class="line"><a name="l10692"></a><span class="lineno">10692</span>&#160;            <span class="keywordflow">if</span>(bufferImageGranularity &gt; 1)</div>
+<div class="line"><a name="l10693"></a><span class="lineno">10693</span>&#160;            {</div>
+<div class="line"><a name="l10694"></a><span class="lineno">10694</span>&#160;                <span class="keywordflow">while</span>(index1st &lt; suballocations1st.size())</div>
+<div class="line"><a name="l10695"></a><span class="lineno">10695</span>&#160;                {</div>
+<div class="line"><a name="l10696"></a><span class="lineno">10696</span>&#160;                    <span class="keyword">const</span> VmaSuballocation&amp; suballoc = suballocations1st[index1st];</div>
+<div class="line"><a name="l10697"></a><span class="lineno">10697</span>&#160;                    <span class="keywordflow">if</span>(VmaBlocksOnSamePage(resultOffset, allocSize, suballoc.offset, bufferImageGranularity))</div>
+<div class="line"><a name="l10698"></a><span class="lineno">10698</span>&#160;                    {</div>
+<div class="line"><a name="l10699"></a><span class="lineno">10699</span>&#160;                        <span class="keywordflow">if</span>(suballoc.hAllocation != VK_NULL_HANDLE)</div>
+<div class="line"><a name="l10700"></a><span class="lineno">10700</span>&#160;                        {</div>
+<div class="line"><a name="l10701"></a><span class="lineno">10701</span>&#160;                            <span class="comment">// Not checking actual VmaIsBufferImageGranularityConflict(allocType, suballoc.type).</span></div>
+<div class="line"><a name="l10702"></a><span class="lineno">10702</span>&#160;                            <span class="keywordflow">if</span>(suballoc.hAllocation-&gt;CanBecomeLost() &amp;&amp;</div>
+<div class="line"><a name="l10703"></a><span class="lineno">10703</span>&#160;                                suballoc.hAllocation-&gt;GetLastUseFrameIndex() + frameInUseCount &lt; currentFrameIndex)</div>
+<div class="line"><a name="l10704"></a><span class="lineno">10704</span>&#160;                            {</div>
+<div class="line"><a name="l10705"></a><span class="lineno">10705</span>&#160;                                ++pAllocationRequest-&gt;itemsToMakeLostCount;</div>
+<div class="line"><a name="l10706"></a><span class="lineno">10706</span>&#160;                                pAllocationRequest-&gt;sumItemSize += suballoc.size;</div>
+<div class="line"><a name="l10707"></a><span class="lineno">10707</span>&#160;                            }</div>
+<div class="line"><a name="l10708"></a><span class="lineno">10708</span>&#160;                            <span class="keywordflow">else</span></div>
+<div class="line"><a name="l10709"></a><span class="lineno">10709</span>&#160;                            {</div>
+<div class="line"><a name="l10710"></a><span class="lineno">10710</span>&#160;                                <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l10711"></a><span class="lineno">10711</span>&#160;                            }</div>
+<div class="line"><a name="l10712"></a><span class="lineno">10712</span>&#160;                        }</div>
+<div class="line"><a name="l10713"></a><span class="lineno">10713</span>&#160;                    }</div>
+<div class="line"><a name="l10714"></a><span class="lineno">10714</span>&#160;                    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l10715"></a><span class="lineno">10715</span>&#160;                    {</div>
+<div class="line"><a name="l10716"></a><span class="lineno">10716</span>&#160;                        <span class="comment">// Already on next page.</span></div>
+<div class="line"><a name="l10717"></a><span class="lineno">10717</span>&#160;                        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l10718"></a><span class="lineno">10718</span>&#160;                    }</div>
+<div class="line"><a name="l10719"></a><span class="lineno">10719</span>&#160;                    ++index1st;</div>
+<div class="line"><a name="l10720"></a><span class="lineno">10720</span>&#160;                }</div>
+<div class="line"><a name="l10721"></a><span class="lineno">10721</span>&#160;            }</div>
+<div class="line"><a name="l10722"></a><span class="lineno">10722</span>&#160; </div>
+<div class="line"><a name="l10723"></a><span class="lineno">10723</span>&#160;            <span class="comment">// Special case: There is not enough room at the end for this allocation, even after making all from the 1st lost.</span></div>
+<div class="line"><a name="l10724"></a><span class="lineno">10724</span>&#160;            <span class="keywordflow">if</span>(index1st == suballocations1st.size() &amp;&amp;</div>
+<div class="line"><a name="l10725"></a><span class="lineno">10725</span>&#160;                resultOffset + allocSize + VMA_DEBUG_MARGIN &gt; size)</div>
+<div class="line"><a name="l10726"></a><span class="lineno">10726</span>&#160;            {</div>
+<div class="line"><a name="l10727"></a><span class="lineno">10727</span>&#160;                <span class="comment">// TODO: This is a known bug that it&#39;s not yet implemented and the allocation is failing.</span></div>
+<div class="line"><a name="l10728"></a><span class="lineno">10728</span>&#160;                VMA_DEBUG_LOG(<span class="stringliteral">&quot;Unsupported special case in custom pool with linear allocation algorithm used as ring buffer with allocations that can be lost.&quot;</span>);</div>
+<div class="line"><a name="l10729"></a><span class="lineno">10729</span>&#160;            }</div>
+<div class="line"><a name="l10730"></a><span class="lineno">10730</span>&#160;        }</div>
+<div class="line"><a name="l10731"></a><span class="lineno">10731</span>&#160; </div>
+<div class="line"><a name="l10732"></a><span class="lineno">10732</span>&#160;        <span class="comment">// There is enough free space at the end after alignment.</span></div>
+<div class="line"><a name="l10733"></a><span class="lineno">10733</span>&#160;        <span class="keywordflow">if</span>((index1st == suballocations1st.size() &amp;&amp; resultOffset + allocSize + VMA_DEBUG_MARGIN &lt;= size) ||</div>
+<div class="line"><a name="l10734"></a><span class="lineno">10734</span>&#160;            (index1st &lt; suballocations1st.size() &amp;&amp; resultOffset + allocSize + VMA_DEBUG_MARGIN &lt;= suballocations1st[index1st].offset))</div>
+<div class="line"><a name="l10735"></a><span class="lineno">10735</span>&#160;        {</div>
+<div class="line"><a name="l10736"></a><span class="lineno">10736</span>&#160;            <span class="comment">// Check next suballocations for BufferImageGranularity conflicts.</span></div>
+<div class="line"><a name="l10737"></a><span class="lineno">10737</span>&#160;            <span class="comment">// If conflict exists, allocation cannot be made here.</span></div>
+<div class="line"><a name="l10738"></a><span class="lineno">10738</span>&#160;            <span class="keywordflow">if</span>(bufferImageGranularity &gt; 1)</div>
+<div class="line"><a name="l10739"></a><span class="lineno">10739</span>&#160;            {</div>
+<div class="line"><a name="l10740"></a><span class="lineno">10740</span>&#160;                <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> nextSuballocIndex = index1st;</div>
+<div class="line"><a name="l10741"></a><span class="lineno">10741</span>&#160;                    nextSuballocIndex &lt; suballocations1st.size();</div>
+<div class="line"><a name="l10742"></a><span class="lineno">10742</span>&#160;                    nextSuballocIndex++)</div>
+<div class="line"><a name="l10743"></a><span class="lineno">10743</span>&#160;                {</div>
+<div class="line"><a name="l10744"></a><span class="lineno">10744</span>&#160;                    <span class="keyword">const</span> VmaSuballocation&amp; nextSuballoc = suballocations1st[nextSuballocIndex];</div>
+<div class="line"><a name="l10745"></a><span class="lineno">10745</span>&#160;                    <span class="keywordflow">if</span>(VmaBlocksOnSamePage(resultOffset, allocSize, nextSuballoc.offset, bufferImageGranularity))</div>
+<div class="line"><a name="l10746"></a><span class="lineno">10746</span>&#160;                    {</div>
+<div class="line"><a name="l10747"></a><span class="lineno">10747</span>&#160;                        <span class="keywordflow">if</span>(VmaIsBufferImageGranularityConflict(allocType, nextSuballoc.type))</div>
+<div class="line"><a name="l10748"></a><span class="lineno">10748</span>&#160;                        {</div>
+<div class="line"><a name="l10749"></a><span class="lineno">10749</span>&#160;                            <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l10750"></a><span class="lineno">10750</span>&#160;                        }</div>
+<div class="line"><a name="l10751"></a><span class="lineno">10751</span>&#160;                    }</div>
+<div class="line"><a name="l10752"></a><span class="lineno">10752</span>&#160;                    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l10753"></a><span class="lineno">10753</span>&#160;                    {</div>
+<div class="line"><a name="l10754"></a><span class="lineno">10754</span>&#160;                        <span class="comment">// Already on next page.</span></div>
+<div class="line"><a name="l10755"></a><span class="lineno">10755</span>&#160;                        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l10756"></a><span class="lineno">10756</span>&#160;                    }</div>
+<div class="line"><a name="l10757"></a><span class="lineno">10757</span>&#160;                }</div>
+<div class="line"><a name="l10758"></a><span class="lineno">10758</span>&#160;            }</div>
+<div class="line"><a name="l10759"></a><span class="lineno">10759</span>&#160; </div>
+<div class="line"><a name="l10760"></a><span class="lineno">10760</span>&#160;            <span class="comment">// All tests passed: Success.</span></div>
+<div class="line"><a name="l10761"></a><span class="lineno">10761</span>&#160;            pAllocationRequest-&gt;offset = resultOffset;</div>
+<div class="line"><a name="l10762"></a><span class="lineno">10762</span>&#160;            pAllocationRequest-&gt;sumFreeSize =</div>
+<div class="line"><a name="l10763"></a><span class="lineno">10763</span>&#160;                (index1st &lt; suballocations1st.size() ? suballocations1st[index1st].offset : size)</div>
+<div class="line"><a name="l10764"></a><span class="lineno">10764</span>&#160;                - resultBaseOffset</div>
+<div class="line"><a name="l10765"></a><span class="lineno">10765</span>&#160;                - pAllocationRequest-&gt;sumItemSize;</div>
+<div class="line"><a name="l10766"></a><span class="lineno">10766</span>&#160;            pAllocationRequest-&gt;type = VmaAllocationRequestType::EndOf2nd;</div>
+<div class="line"><a name="l10767"></a><span class="lineno">10767</span>&#160;            <span class="comment">// pAllocationRequest-&gt;item, customData unused.</span></div>
+<div class="line"><a name="l10768"></a><span class="lineno">10768</span>&#160;            <span class="keywordflow">return</span> <span class="keyword">true</span>;</div>
+<div class="line"><a name="l10769"></a><span class="lineno">10769</span>&#160;        }</div>
+<div class="line"><a name="l10770"></a><span class="lineno">10770</span>&#160;    }</div>
+<div class="line"><a name="l10771"></a><span class="lineno">10771</span>&#160; </div>
+<div class="line"><a name="l10772"></a><span class="lineno">10772</span>&#160;    <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l10773"></a><span class="lineno">10773</span>&#160;}</div>
+<div class="line"><a name="l10774"></a><span class="lineno">10774</span>&#160; </div>
+<div class="line"><a name="l10775"></a><span class="lineno">10775</span>&#160;<span class="keywordtype">bool</span> VmaBlockMetadata_Linear::MakeRequestedAllocationsLost(</div>
+<div class="line"><a name="l10776"></a><span class="lineno">10776</span>&#160;    uint32_t currentFrameIndex,</div>
+<div class="line"><a name="l10777"></a><span class="lineno">10777</span>&#160;    uint32_t frameInUseCount,</div>
+<div class="line"><a name="l10778"></a><span class="lineno">10778</span>&#160;    VmaAllocationRequest* pAllocationRequest)</div>
+<div class="line"><a name="l10779"></a><span class="lineno">10779</span>&#160;{</div>
+<div class="line"><a name="l10780"></a><span class="lineno">10780</span>&#160;    <span class="keywordflow">if</span>(pAllocationRequest-&gt;itemsToMakeLostCount == 0)</div>
+<div class="line"><a name="l10781"></a><span class="lineno">10781</span>&#160;    {</div>
+<div class="line"><a name="l10782"></a><span class="lineno">10782</span>&#160;        <span class="keywordflow">return</span> <span class="keyword">true</span>;</div>
+<div class="line"><a name="l10783"></a><span class="lineno">10783</span>&#160;    }</div>
+<div class="line"><a name="l10784"></a><span class="lineno">10784</span>&#160; </div>
+<div class="line"><a name="l10785"></a><span class="lineno">10785</span>&#160;    VMA_ASSERT(m_2ndVectorMode == SECOND_VECTOR_EMPTY || m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER);</div>
+<div class="line"><a name="l10786"></a><span class="lineno">10786</span>&#160;    </div>
+<div class="line"><a name="l10787"></a><span class="lineno">10787</span>&#160;    <span class="comment">// We always start from 1st.</span></div>
+<div class="line"><a name="l10788"></a><span class="lineno">10788</span>&#160;    SuballocationVectorType* suballocations = &amp;AccessSuballocations1st();</div>
+<div class="line"><a name="l10789"></a><span class="lineno">10789</span>&#160;    <span class="keywordtype">size_t</span> index = m_1stNullItemsBeginCount;</div>
+<div class="line"><a name="l10790"></a><span class="lineno">10790</span>&#160;    <span class="keywordtype">size_t</span> madeLostCount = 0;</div>
+<div class="line"><a name="l10791"></a><span class="lineno">10791</span>&#160;    <span class="keywordflow">while</span>(madeLostCount &lt; pAllocationRequest-&gt;itemsToMakeLostCount)</div>
+<div class="line"><a name="l10792"></a><span class="lineno">10792</span>&#160;    {</div>
+<div class="line"><a name="l10793"></a><span class="lineno">10793</span>&#160;        <span class="keywordflow">if</span>(index == suballocations-&gt;size())</div>
+<div class="line"><a name="l10794"></a><span class="lineno">10794</span>&#160;        {</div>
+<div class="line"><a name="l10795"></a><span class="lineno">10795</span>&#160;            index = 0;</div>
+<div class="line"><a name="l10796"></a><span class="lineno">10796</span>&#160;            <span class="comment">// If we get to the end of 1st, we wrap around to beginning of 2nd of 1st.</span></div>
+<div class="line"><a name="l10797"></a><span class="lineno">10797</span>&#160;            <span class="keywordflow">if</span>(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)</div>
+<div class="line"><a name="l10798"></a><span class="lineno">10798</span>&#160;            {</div>
+<div class="line"><a name="l10799"></a><span class="lineno">10799</span>&#160;                suballocations = &amp;AccessSuballocations2nd();</div>
+<div class="line"><a name="l10800"></a><span class="lineno">10800</span>&#160;            }</div>
+<div class="line"><a name="l10801"></a><span class="lineno">10801</span>&#160;            <span class="comment">// else: m_2ndVectorMode == SECOND_VECTOR_EMPTY:</span></div>
+<div class="line"><a name="l10802"></a><span class="lineno">10802</span>&#160;            <span class="comment">// suballocations continues pointing at AccessSuballocations1st().</span></div>
+<div class="line"><a name="l10803"></a><span class="lineno">10803</span>&#160;            VMA_ASSERT(!suballocations-&gt;empty());</div>
+<div class="line"><a name="l10804"></a><span class="lineno">10804</span>&#160;        }</div>
+<div class="line"><a name="l10805"></a><span class="lineno">10805</span>&#160;        VmaSuballocation&amp; suballoc = (*suballocations)[index];</div>
+<div class="line"><a name="l10806"></a><span class="lineno">10806</span>&#160;        <span class="keywordflow">if</span>(suballoc.type != VMA_SUBALLOCATION_TYPE_FREE)</div>
+<div class="line"><a name="l10807"></a><span class="lineno">10807</span>&#160;        {</div>
+<div class="line"><a name="l10808"></a><span class="lineno">10808</span>&#160;            VMA_ASSERT(suballoc.hAllocation != VK_NULL_HANDLE);</div>
+<div class="line"><a name="l10809"></a><span class="lineno">10809</span>&#160;            VMA_ASSERT(suballoc.hAllocation-&gt;CanBecomeLost());</div>
+<div class="line"><a name="l10810"></a><span class="lineno">10810</span>&#160;            <span class="keywordflow">if</span>(suballoc.hAllocation-&gt;MakeLost(currentFrameIndex, frameInUseCount))</div>
+<div class="line"><a name="l10811"></a><span class="lineno">10811</span>&#160;            {</div>
+<div class="line"><a name="l10812"></a><span class="lineno">10812</span>&#160;                suballoc.type = VMA_SUBALLOCATION_TYPE_FREE;</div>
+<div class="line"><a name="l10813"></a><span class="lineno">10813</span>&#160;                suballoc.hAllocation = VK_NULL_HANDLE;</div>
+<div class="line"><a name="l10814"></a><span class="lineno">10814</span>&#160;                m_SumFreeSize += suballoc.size;</div>
+<div class="line"><a name="l10815"></a><span class="lineno">10815</span>&#160;                <span class="keywordflow">if</span>(suballocations == &amp;AccessSuballocations1st())</div>
+<div class="line"><a name="l10816"></a><span class="lineno">10816</span>&#160;                {</div>
+<div class="line"><a name="l10817"></a><span class="lineno">10817</span>&#160;                    ++m_1stNullItemsMiddleCount;</div>
+<div class="line"><a name="l10818"></a><span class="lineno">10818</span>&#160;                }</div>
+<div class="line"><a name="l10819"></a><span class="lineno">10819</span>&#160;                <span class="keywordflow">else</span></div>
+<div class="line"><a name="l10820"></a><span class="lineno">10820</span>&#160;                {</div>
+<div class="line"><a name="l10821"></a><span class="lineno">10821</span>&#160;                    ++m_2ndNullItemsCount;</div>
+<div class="line"><a name="l10822"></a><span class="lineno">10822</span>&#160;                }</div>
+<div class="line"><a name="l10823"></a><span class="lineno">10823</span>&#160;                ++madeLostCount;</div>
+<div class="line"><a name="l10824"></a><span class="lineno">10824</span>&#160;            }</div>
+<div class="line"><a name="l10825"></a><span class="lineno">10825</span>&#160;            <span class="keywordflow">else</span></div>
+<div class="line"><a name="l10826"></a><span class="lineno">10826</span>&#160;            {</div>
+<div class="line"><a name="l10827"></a><span class="lineno">10827</span>&#160;                <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l10828"></a><span class="lineno">10828</span>&#160;            }</div>
+<div class="line"><a name="l10829"></a><span class="lineno">10829</span>&#160;        }</div>
+<div class="line"><a name="l10830"></a><span class="lineno">10830</span>&#160;        ++index;</div>
+<div class="line"><a name="l10831"></a><span class="lineno">10831</span>&#160;    }</div>
+<div class="line"><a name="l10832"></a><span class="lineno">10832</span>&#160; </div>
+<div class="line"><a name="l10833"></a><span class="lineno">10833</span>&#160;    CleanupAfterFree();</div>
+<div class="line"><a name="l10834"></a><span class="lineno">10834</span>&#160;    <span class="comment">//VMA_HEAVY_ASSERT(Validate()); // Already called by ClanupAfterFree().</span></div>
+<div class="line"><a name="l10835"></a><span class="lineno">10835</span>&#160;    </div>
+<div class="line"><a name="l10836"></a><span class="lineno">10836</span>&#160;    <span class="keywordflow">return</span> <span class="keyword">true</span>;</div>
+<div class="line"><a name="l10837"></a><span class="lineno">10837</span>&#160;}</div>
+<div class="line"><a name="l10838"></a><span class="lineno">10838</span>&#160; </div>
+<div class="line"><a name="l10839"></a><span class="lineno">10839</span>&#160;uint32_t VmaBlockMetadata_Linear::MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount)</div>
+<div class="line"><a name="l10840"></a><span class="lineno">10840</span>&#160;{</div>
+<div class="line"><a name="l10841"></a><span class="lineno">10841</span>&#160;    uint32_t lostAllocationCount = 0;</div>
+<div class="line"><a name="l10842"></a><span class="lineno">10842</span>&#160;    </div>
+<div class="line"><a name="l10843"></a><span class="lineno">10843</span>&#160;    SuballocationVectorType&amp; suballocations1st = AccessSuballocations1st();</div>
+<div class="line"><a name="l10844"></a><span class="lineno">10844</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = m_1stNullItemsBeginCount, count = suballocations1st.size(); i &lt; count; ++i)</div>
+<div class="line"><a name="l10845"></a><span class="lineno">10845</span>&#160;    {</div>
+<div class="line"><a name="l10846"></a><span class="lineno">10846</span>&#160;        VmaSuballocation&amp; suballoc = suballocations1st[i];</div>
+<div class="line"><a name="l10847"></a><span class="lineno">10847</span>&#160;        <span class="keywordflow">if</span>(suballoc.type != VMA_SUBALLOCATION_TYPE_FREE &amp;&amp;</div>
+<div class="line"><a name="l10848"></a><span class="lineno">10848</span>&#160;            suballoc.hAllocation-&gt;CanBecomeLost() &amp;&amp;</div>
+<div class="line"><a name="l10849"></a><span class="lineno">10849</span>&#160;            suballoc.hAllocation-&gt;MakeLost(currentFrameIndex, frameInUseCount))</div>
+<div class="line"><a name="l10850"></a><span class="lineno">10850</span>&#160;        {</div>
+<div class="line"><a name="l10851"></a><span class="lineno">10851</span>&#160;            suballoc.type = VMA_SUBALLOCATION_TYPE_FREE;</div>
+<div class="line"><a name="l10852"></a><span class="lineno">10852</span>&#160;            suballoc.hAllocation = VK_NULL_HANDLE;</div>
+<div class="line"><a name="l10853"></a><span class="lineno">10853</span>&#160;            ++m_1stNullItemsMiddleCount;</div>
+<div class="line"><a name="l10854"></a><span class="lineno">10854</span>&#160;            m_SumFreeSize += suballoc.size;</div>
+<div class="line"><a name="l10855"></a><span class="lineno">10855</span>&#160;            ++lostAllocationCount;</div>
+<div class="line"><a name="l10856"></a><span class="lineno">10856</span>&#160;        }</div>
+<div class="line"><a name="l10857"></a><span class="lineno">10857</span>&#160;    }</div>
+<div class="line"><a name="l10858"></a><span class="lineno">10858</span>&#160; </div>
+<div class="line"><a name="l10859"></a><span class="lineno">10859</span>&#160;    SuballocationVectorType&amp; suballocations2nd = AccessSuballocations2nd();</div>
+<div class="line"><a name="l10860"></a><span class="lineno">10860</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = 0, count = suballocations2nd.size(); i &lt; count; ++i)</div>
+<div class="line"><a name="l10861"></a><span class="lineno">10861</span>&#160;    {</div>
+<div class="line"><a name="l10862"></a><span class="lineno">10862</span>&#160;        VmaSuballocation&amp; suballoc = suballocations2nd[i];</div>
+<div class="line"><a name="l10863"></a><span class="lineno">10863</span>&#160;        <span class="keywordflow">if</span>(suballoc.type != VMA_SUBALLOCATION_TYPE_FREE &amp;&amp;</div>
+<div class="line"><a name="l10864"></a><span class="lineno">10864</span>&#160;            suballoc.hAllocation-&gt;CanBecomeLost() &amp;&amp;</div>
+<div class="line"><a name="l10865"></a><span class="lineno">10865</span>&#160;            suballoc.hAllocation-&gt;MakeLost(currentFrameIndex, frameInUseCount))</div>
+<div class="line"><a name="l10866"></a><span class="lineno">10866</span>&#160;        {</div>
+<div class="line"><a name="l10867"></a><span class="lineno">10867</span>&#160;            suballoc.type = VMA_SUBALLOCATION_TYPE_FREE;</div>
+<div class="line"><a name="l10868"></a><span class="lineno">10868</span>&#160;            suballoc.hAllocation = VK_NULL_HANDLE;</div>
+<div class="line"><a name="l10869"></a><span class="lineno">10869</span>&#160;            ++m_2ndNullItemsCount;</div>
+<div class="line"><a name="l10870"></a><span class="lineno">10870</span>&#160;            m_SumFreeSize += suballoc.size;</div>
+<div class="line"><a name="l10871"></a><span class="lineno">10871</span>&#160;            ++lostAllocationCount;</div>
+<div class="line"><a name="l10872"></a><span class="lineno">10872</span>&#160;        }</div>
+<div class="line"><a name="l10873"></a><span class="lineno">10873</span>&#160;    }</div>
+<div class="line"><a name="l10874"></a><span class="lineno">10874</span>&#160; </div>
+<div class="line"><a name="l10875"></a><span class="lineno">10875</span>&#160;    <span class="keywordflow">if</span>(lostAllocationCount)</div>
+<div class="line"><a name="l10876"></a><span class="lineno">10876</span>&#160;    {</div>
+<div class="line"><a name="l10877"></a><span class="lineno">10877</span>&#160;        CleanupAfterFree();</div>
+<div class="line"><a name="l10878"></a><span class="lineno">10878</span>&#160;    }</div>
+<div class="line"><a name="l10879"></a><span class="lineno">10879</span>&#160; </div>
+<div class="line"><a name="l10880"></a><span class="lineno">10880</span>&#160;    <span class="keywordflow">return</span> lostAllocationCount;</div>
+<div class="line"><a name="l10881"></a><span class="lineno">10881</span>&#160;}</div>
+<div class="line"><a name="l10882"></a><span class="lineno">10882</span>&#160; </div>
+<div class="line"><a name="l10883"></a><span class="lineno">10883</span>&#160;VkResult VmaBlockMetadata_Linear::CheckCorruption(<span class="keyword">const</span> <span class="keywordtype">void</span>* pBlockData)</div>
+<div class="line"><a name="l10884"></a><span class="lineno">10884</span>&#160;{</div>
+<div class="line"><a name="l10885"></a><span class="lineno">10885</span>&#160;    SuballocationVectorType&amp; suballocations1st = AccessSuballocations1st();</div>
+<div class="line"><a name="l10886"></a><span class="lineno">10886</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = m_1stNullItemsBeginCount, count = suballocations1st.size(); i &lt; count; ++i)</div>
+<div class="line"><a name="l10887"></a><span class="lineno">10887</span>&#160;    {</div>
+<div class="line"><a name="l10888"></a><span class="lineno">10888</span>&#160;        <span class="keyword">const</span> VmaSuballocation&amp; suballoc = suballocations1st[i];</div>
+<div class="line"><a name="l10889"></a><span class="lineno">10889</span>&#160;        <span class="keywordflow">if</span>(suballoc.type != VMA_SUBALLOCATION_TYPE_FREE)</div>
+<div class="line"><a name="l10890"></a><span class="lineno">10890</span>&#160;        {</div>
+<div class="line"><a name="l10891"></a><span class="lineno">10891</span>&#160;            <span class="keywordflow">if</span>(!VmaValidateMagicValue(pBlockData, suballoc.offset - VMA_DEBUG_MARGIN))</div>
+<div class="line"><a name="l10892"></a><span class="lineno">10892</span>&#160;            {</div>
+<div class="line"><a name="l10893"></a><span class="lineno">10893</span>&#160;                VMA_ASSERT(0 &amp;&amp; <span class="stringliteral">&quot;MEMORY CORRUPTION DETECTED BEFORE VALIDATED ALLOCATION!&quot;</span>);</div>
+<div class="line"><a name="l10894"></a><span class="lineno">10894</span>&#160;                <span class="keywordflow">return</span> VK_ERROR_VALIDATION_FAILED_EXT;</div>
+<div class="line"><a name="l10895"></a><span class="lineno">10895</span>&#160;            }</div>
+<div class="line"><a name="l10896"></a><span class="lineno">10896</span>&#160;            <span class="keywordflow">if</span>(!VmaValidateMagicValue(pBlockData, suballoc.offset + suballoc.size))</div>
+<div class="line"><a name="l10897"></a><span class="lineno">10897</span>&#160;            {</div>
+<div class="line"><a name="l10898"></a><span class="lineno">10898</span>&#160;                VMA_ASSERT(0 &amp;&amp; <span class="stringliteral">&quot;MEMORY CORRUPTION DETECTED AFTER VALIDATED ALLOCATION!&quot;</span>);</div>
+<div class="line"><a name="l10899"></a><span class="lineno">10899</span>&#160;                <span class="keywordflow">return</span> VK_ERROR_VALIDATION_FAILED_EXT;</div>
+<div class="line"><a name="l10900"></a><span class="lineno">10900</span>&#160;            }</div>
+<div class="line"><a name="l10901"></a><span class="lineno">10901</span>&#160;        }</div>
+<div class="line"><a name="l10902"></a><span class="lineno">10902</span>&#160;    }</div>
+<div class="line"><a name="l10903"></a><span class="lineno">10903</span>&#160; </div>
+<div class="line"><a name="l10904"></a><span class="lineno">10904</span>&#160;    SuballocationVectorType&amp; suballocations2nd = AccessSuballocations2nd();</div>
+<div class="line"><a name="l10905"></a><span class="lineno">10905</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = 0, count = suballocations2nd.size(); i &lt; count; ++i)</div>
+<div class="line"><a name="l10906"></a><span class="lineno">10906</span>&#160;    {</div>
+<div class="line"><a name="l10907"></a><span class="lineno">10907</span>&#160;        <span class="keyword">const</span> VmaSuballocation&amp; suballoc = suballocations2nd[i];</div>
+<div class="line"><a name="l10908"></a><span class="lineno">10908</span>&#160;        <span class="keywordflow">if</span>(suballoc.type != VMA_SUBALLOCATION_TYPE_FREE)</div>
+<div class="line"><a name="l10909"></a><span class="lineno">10909</span>&#160;        {</div>
+<div class="line"><a name="l10910"></a><span class="lineno">10910</span>&#160;            <span class="keywordflow">if</span>(!VmaValidateMagicValue(pBlockData, suballoc.offset - VMA_DEBUG_MARGIN))</div>
+<div class="line"><a name="l10911"></a><span class="lineno">10911</span>&#160;            {</div>
+<div class="line"><a name="l10912"></a><span class="lineno">10912</span>&#160;                VMA_ASSERT(0 &amp;&amp; <span class="stringliteral">&quot;MEMORY CORRUPTION DETECTED BEFORE VALIDATED ALLOCATION!&quot;</span>);</div>
+<div class="line"><a name="l10913"></a><span class="lineno">10913</span>&#160;                <span class="keywordflow">return</span> VK_ERROR_VALIDATION_FAILED_EXT;</div>
+<div class="line"><a name="l10914"></a><span class="lineno">10914</span>&#160;            }</div>
+<div class="line"><a name="l10915"></a><span class="lineno">10915</span>&#160;            <span class="keywordflow">if</span>(!VmaValidateMagicValue(pBlockData, suballoc.offset + suballoc.size))</div>
+<div class="line"><a name="l10916"></a><span class="lineno">10916</span>&#160;            {</div>
+<div class="line"><a name="l10917"></a><span class="lineno">10917</span>&#160;                VMA_ASSERT(0 &amp;&amp; <span class="stringliteral">&quot;MEMORY CORRUPTION DETECTED AFTER VALIDATED ALLOCATION!&quot;</span>);</div>
+<div class="line"><a name="l10918"></a><span class="lineno">10918</span>&#160;                <span class="keywordflow">return</span> VK_ERROR_VALIDATION_FAILED_EXT;</div>
+<div class="line"><a name="l10919"></a><span class="lineno">10919</span>&#160;            }</div>
+<div class="line"><a name="l10920"></a><span class="lineno">10920</span>&#160;        }</div>
+<div class="line"><a name="l10921"></a><span class="lineno">10921</span>&#160;    }</div>
+<div class="line"><a name="l10922"></a><span class="lineno">10922</span>&#160; </div>
+<div class="line"><a name="l10923"></a><span class="lineno">10923</span>&#160;    <span class="keywordflow">return</span> VK_SUCCESS;</div>
+<div class="line"><a name="l10924"></a><span class="lineno">10924</span>&#160;}</div>
+<div class="line"><a name="l10925"></a><span class="lineno">10925</span>&#160; </div>
+<div class="line"><a name="l10926"></a><span class="lineno">10926</span>&#160;<span class="keywordtype">void</span> VmaBlockMetadata_Linear::Alloc(</div>
+<div class="line"><a name="l10927"></a><span class="lineno">10927</span>&#160;    <span class="keyword">const</span> VmaAllocationRequest&amp; request,</div>
+<div class="line"><a name="l10928"></a><span class="lineno">10928</span>&#160;    VmaSuballocationType type,</div>
+<div class="line"><a name="l10929"></a><span class="lineno">10929</span>&#160;    VkDeviceSize allocSize,</div>
+<div class="line"><a name="l10930"></a><span class="lineno">10930</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAllocation)</div>
+<div class="line"><a name="l10931"></a><span class="lineno">10931</span>&#160;{</div>
+<div class="line"><a name="l10932"></a><span class="lineno">10932</span>&#160;    <span class="keyword">const</span> VmaSuballocation newSuballoc = { request.offset, allocSize, hAllocation, type };</div>
+<div class="line"><a name="l10933"></a><span class="lineno">10933</span>&#160; </div>
+<div class="line"><a name="l10934"></a><span class="lineno">10934</span>&#160;    <span class="keywordflow">switch</span>(request.type)</div>
+<div class="line"><a name="l10935"></a><span class="lineno">10935</span>&#160;    {</div>
+<div class="line"><a name="l10936"></a><span class="lineno">10936</span>&#160;    <span class="keywordflow">case</span> VmaAllocationRequestType::UpperAddress:</div>
+<div class="line"><a name="l10937"></a><span class="lineno">10937</span>&#160;        {</div>
+<div class="line"><a name="l10938"></a><span class="lineno">10938</span>&#160;            VMA_ASSERT(m_2ndVectorMode != SECOND_VECTOR_RING_BUFFER &amp;&amp;</div>
+<div class="line"><a name="l10939"></a><span class="lineno">10939</span>&#160;                <span class="stringliteral">&quot;CRITICAL ERROR: Trying to use linear allocator as double stack while it was already used as ring buffer.&quot;</span>);</div>
+<div class="line"><a name="l10940"></a><span class="lineno">10940</span>&#160;            SuballocationVectorType&amp; suballocations2nd = AccessSuballocations2nd();</div>
+<div class="line"><a name="l10941"></a><span class="lineno">10941</span>&#160;            suballocations2nd.push_back(newSuballoc);</div>
+<div class="line"><a name="l10942"></a><span class="lineno">10942</span>&#160;            m_2ndVectorMode = SECOND_VECTOR_DOUBLE_STACK;</div>
+<div class="line"><a name="l10943"></a><span class="lineno">10943</span>&#160;        }</div>
+<div class="line"><a name="l10944"></a><span class="lineno">10944</span>&#160;        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l10945"></a><span class="lineno">10945</span>&#160;    <span class="keywordflow">case</span> VmaAllocationRequestType::EndOf1st:</div>
+<div class="line"><a name="l10946"></a><span class="lineno">10946</span>&#160;        {</div>
+<div class="line"><a name="l10947"></a><span class="lineno">10947</span>&#160;            SuballocationVectorType&amp; suballocations1st = AccessSuballocations1st();</div>
+<div class="line"><a name="l10948"></a><span class="lineno">10948</span>&#160; </div>
+<div class="line"><a name="l10949"></a><span class="lineno">10949</span>&#160;            VMA_ASSERT(suballocations1st.empty() ||</div>
+<div class="line"><a name="l10950"></a><span class="lineno">10950</span>&#160;                request.offset &gt;= suballocations1st.back().offset + suballocations1st.back().size);</div>
+<div class="line"><a name="l10951"></a><span class="lineno">10951</span>&#160;            <span class="comment">// Check if it fits before the end of the block.</span></div>
+<div class="line"><a name="l10952"></a><span class="lineno">10952</span>&#160;            VMA_ASSERT(request.offset + allocSize &lt;= GetSize());</div>
+<div class="line"><a name="l10953"></a><span class="lineno">10953</span>&#160; </div>
+<div class="line"><a name="l10954"></a><span class="lineno">10954</span>&#160;            suballocations1st.push_back(newSuballoc);</div>
+<div class="line"><a name="l10955"></a><span class="lineno">10955</span>&#160;        }</div>
+<div class="line"><a name="l10956"></a><span class="lineno">10956</span>&#160;        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l10957"></a><span class="lineno">10957</span>&#160;    <span class="keywordflow">case</span> VmaAllocationRequestType::EndOf2nd:</div>
+<div class="line"><a name="l10958"></a><span class="lineno">10958</span>&#160;        {</div>
+<div class="line"><a name="l10959"></a><span class="lineno">10959</span>&#160;            SuballocationVectorType&amp; suballocations1st = AccessSuballocations1st();</div>
+<div class="line"><a name="l10960"></a><span class="lineno">10960</span>&#160;            <span class="comment">// New allocation at the end of 2-part ring buffer, so before first allocation from 1st vector.</span></div>
+<div class="line"><a name="l10961"></a><span class="lineno">10961</span>&#160;            VMA_ASSERT(!suballocations1st.empty() &amp;&amp;</div>
+<div class="line"><a name="l10962"></a><span class="lineno">10962</span>&#160;                request.offset + allocSize &lt;= suballocations1st[m_1stNullItemsBeginCount].offset);</div>
+<div class="line"><a name="l10963"></a><span class="lineno">10963</span>&#160;            SuballocationVectorType&amp; suballocations2nd = AccessSuballocations2nd();</div>
+<div class="line"><a name="l10964"></a><span class="lineno">10964</span>&#160; </div>
+<div class="line"><a name="l10965"></a><span class="lineno">10965</span>&#160;            <span class="keywordflow">switch</span>(m_2ndVectorMode)</div>
+<div class="line"><a name="l10966"></a><span class="lineno">10966</span>&#160;            {</div>
+<div class="line"><a name="l10967"></a><span class="lineno">10967</span>&#160;            <span class="keywordflow">case</span> SECOND_VECTOR_EMPTY:</div>
+<div class="line"><a name="l10968"></a><span class="lineno">10968</span>&#160;                <span class="comment">// First allocation from second part ring buffer.</span></div>
+<div class="line"><a name="l10969"></a><span class="lineno">10969</span>&#160;                VMA_ASSERT(suballocations2nd.empty());</div>
+<div class="line"><a name="l10970"></a><span class="lineno">10970</span>&#160;                m_2ndVectorMode = SECOND_VECTOR_RING_BUFFER;</div>
+<div class="line"><a name="l10971"></a><span class="lineno">10971</span>&#160;                <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l10972"></a><span class="lineno">10972</span>&#160;            <span class="keywordflow">case</span> SECOND_VECTOR_RING_BUFFER:</div>
+<div class="line"><a name="l10973"></a><span class="lineno">10973</span>&#160;                <span class="comment">// 2-part ring buffer is already started.</span></div>
+<div class="line"><a name="l10974"></a><span class="lineno">10974</span>&#160;                VMA_ASSERT(!suballocations2nd.empty());</div>
+<div class="line"><a name="l10975"></a><span class="lineno">10975</span>&#160;                <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l10976"></a><span class="lineno">10976</span>&#160;            <span class="keywordflow">case</span> SECOND_VECTOR_DOUBLE_STACK:</div>
+<div class="line"><a name="l10977"></a><span class="lineno">10977</span>&#160;                VMA_ASSERT(0 &amp;&amp; <span class="stringliteral">&quot;CRITICAL ERROR: Trying to use linear allocator as ring buffer while it was already used as double stack.&quot;</span>);</div>
+<div class="line"><a name="l10978"></a><span class="lineno">10978</span>&#160;                <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l10979"></a><span class="lineno">10979</span>&#160;            <span class="keywordflow">default</span>:</div>
+<div class="line"><a name="l10980"></a><span class="lineno">10980</span>&#160;                VMA_ASSERT(0);</div>
+<div class="line"><a name="l10981"></a><span class="lineno">10981</span>&#160;            }</div>
+<div class="line"><a name="l10982"></a><span class="lineno">10982</span>&#160; </div>
+<div class="line"><a name="l10983"></a><span class="lineno">10983</span>&#160;            suballocations2nd.push_back(newSuballoc);</div>
+<div class="line"><a name="l10984"></a><span class="lineno">10984</span>&#160;        }</div>
+<div class="line"><a name="l10985"></a><span class="lineno">10985</span>&#160;        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l10986"></a><span class="lineno">10986</span>&#160;    <span class="keywordflow">default</span>:</div>
+<div class="line"><a name="l10987"></a><span class="lineno">10987</span>&#160;        VMA_ASSERT(0 &amp;&amp; <span class="stringliteral">&quot;CRITICAL INTERNAL ERROR.&quot;</span>);</div>
+<div class="line"><a name="l10988"></a><span class="lineno">10988</span>&#160;    }</div>
+<div class="line"><a name="l10989"></a><span class="lineno">10989</span>&#160; </div>
+<div class="line"><a name="l10990"></a><span class="lineno">10990</span>&#160;    m_SumFreeSize -= newSuballoc.size;</div>
+<div class="line"><a name="l10991"></a><span class="lineno">10991</span>&#160;}</div>
+<div class="line"><a name="l10992"></a><span class="lineno">10992</span>&#160; </div>
+<div class="line"><a name="l10993"></a><span class="lineno">10993</span>&#160;<span class="keywordtype">void</span> VmaBlockMetadata_Linear::Free(<span class="keyword">const</span> <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation)</div>
+<div class="line"><a name="l10994"></a><span class="lineno">10994</span>&#160;{</div>
+<div class="line"><a name="l10995"></a><span class="lineno">10995</span>&#160;    FreeAtOffset(allocation-&gt;GetOffset());</div>
+<div class="line"><a name="l10996"></a><span class="lineno">10996</span>&#160;}</div>
+<div class="line"><a name="l10997"></a><span class="lineno">10997</span>&#160; </div>
+<div class="line"><a name="l10998"></a><span class="lineno">10998</span>&#160;<span class="keywordtype">void</span> VmaBlockMetadata_Linear::FreeAtOffset(VkDeviceSize offset)</div>
+<div class="line"><a name="l10999"></a><span class="lineno">10999</span>&#160;{</div>
+<div class="line"><a name="l11000"></a><span class="lineno">11000</span>&#160;    SuballocationVectorType&amp; suballocations1st = AccessSuballocations1st();</div>
+<div class="line"><a name="l11001"></a><span class="lineno">11001</span>&#160;    SuballocationVectorType&amp; suballocations2nd = AccessSuballocations2nd();</div>
+<div class="line"><a name="l11002"></a><span class="lineno">11002</span>&#160; </div>
+<div class="line"><a name="l11003"></a><span class="lineno">11003</span>&#160;    <span class="keywordflow">if</span>(!suballocations1st.empty())</div>
+<div class="line"><a name="l11004"></a><span class="lineno">11004</span>&#160;    {</div>
+<div class="line"><a name="l11005"></a><span class="lineno">11005</span>&#160;        <span class="comment">// First allocation: Mark it as next empty at the beginning.</span></div>
+<div class="line"><a name="l11006"></a><span class="lineno">11006</span>&#160;        VmaSuballocation&amp; firstSuballoc = suballocations1st[m_1stNullItemsBeginCount];</div>
+<div class="line"><a name="l11007"></a><span class="lineno">11007</span>&#160;        <span class="keywordflow">if</span>(firstSuballoc.offset == offset)</div>
+<div class="line"><a name="l11008"></a><span class="lineno">11008</span>&#160;        {</div>
+<div class="line"><a name="l11009"></a><span class="lineno">11009</span>&#160;            firstSuballoc.type = VMA_SUBALLOCATION_TYPE_FREE;</div>
+<div class="line"><a name="l11010"></a><span class="lineno">11010</span>&#160;            firstSuballoc.hAllocation = VK_NULL_HANDLE;</div>
+<div class="line"><a name="l11011"></a><span class="lineno">11011</span>&#160;            m_SumFreeSize += firstSuballoc.size;</div>
+<div class="line"><a name="l11012"></a><span class="lineno">11012</span>&#160;            ++m_1stNullItemsBeginCount;</div>
+<div class="line"><a name="l11013"></a><span class="lineno">11013</span>&#160;            CleanupAfterFree();</div>
+<div class="line"><a name="l11014"></a><span class="lineno">11014</span>&#160;            <span class="keywordflow">return</span>;</div>
+<div class="line"><a name="l11015"></a><span class="lineno">11015</span>&#160;        }</div>
+<div class="line"><a name="l11016"></a><span class="lineno">11016</span>&#160;    }</div>
+<div class="line"><a name="l11017"></a><span class="lineno">11017</span>&#160; </div>
+<div class="line"><a name="l11018"></a><span class="lineno">11018</span>&#160;    <span class="comment">// Last allocation in 2-part ring buffer or top of upper stack (same logic).</span></div>
+<div class="line"><a name="l11019"></a><span class="lineno">11019</span>&#160;    <span class="keywordflow">if</span>(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER ||</div>
+<div class="line"><a name="l11020"></a><span class="lineno">11020</span>&#160;        m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)</div>
+<div class="line"><a name="l11021"></a><span class="lineno">11021</span>&#160;    {</div>
+<div class="line"><a name="l11022"></a><span class="lineno">11022</span>&#160;        VmaSuballocation&amp; lastSuballoc = suballocations2nd.back();</div>
+<div class="line"><a name="l11023"></a><span class="lineno">11023</span>&#160;        <span class="keywordflow">if</span>(lastSuballoc.offset == offset)</div>
+<div class="line"><a name="l11024"></a><span class="lineno">11024</span>&#160;        {</div>
+<div class="line"><a name="l11025"></a><span class="lineno">11025</span>&#160;            m_SumFreeSize += lastSuballoc.size;</div>
+<div class="line"><a name="l11026"></a><span class="lineno">11026</span>&#160;            suballocations2nd.pop_back();</div>
+<div class="line"><a name="l11027"></a><span class="lineno">11027</span>&#160;            CleanupAfterFree();</div>
+<div class="line"><a name="l11028"></a><span class="lineno">11028</span>&#160;            <span class="keywordflow">return</span>;</div>
+<div class="line"><a name="l11029"></a><span class="lineno">11029</span>&#160;        }</div>
+<div class="line"><a name="l11030"></a><span class="lineno">11030</span>&#160;    }</div>
+<div class="line"><a name="l11031"></a><span class="lineno">11031</span>&#160;    <span class="comment">// Last allocation in 1st vector.</span></div>
+<div class="line"><a name="l11032"></a><span class="lineno">11032</span>&#160;    <span class="keywordflow">else</span> <span class="keywordflow">if</span>(m_2ndVectorMode == SECOND_VECTOR_EMPTY)</div>
+<div class="line"><a name="l11033"></a><span class="lineno">11033</span>&#160;    {</div>
+<div class="line"><a name="l11034"></a><span class="lineno">11034</span>&#160;        VmaSuballocation&amp; lastSuballoc = suballocations1st.back();</div>
+<div class="line"><a name="l11035"></a><span class="lineno">11035</span>&#160;        <span class="keywordflow">if</span>(lastSuballoc.offset == offset)</div>
+<div class="line"><a name="l11036"></a><span class="lineno">11036</span>&#160;        {</div>
+<div class="line"><a name="l11037"></a><span class="lineno">11037</span>&#160;            m_SumFreeSize += lastSuballoc.size;</div>
+<div class="line"><a name="l11038"></a><span class="lineno">11038</span>&#160;            suballocations1st.pop_back();</div>
+<div class="line"><a name="l11039"></a><span class="lineno">11039</span>&#160;            CleanupAfterFree();</div>
+<div class="line"><a name="l11040"></a><span class="lineno">11040</span>&#160;            <span class="keywordflow">return</span>;</div>
+<div class="line"><a name="l11041"></a><span class="lineno">11041</span>&#160;        }</div>
+<div class="line"><a name="l11042"></a><span class="lineno">11042</span>&#160;    }</div>
+<div class="line"><a name="l11043"></a><span class="lineno">11043</span>&#160; </div>
+<div class="line"><a name="l11044"></a><span class="lineno">11044</span>&#160;    <span class="comment">// Item from the middle of 1st vector.</span></div>
+<div class="line"><a name="l11045"></a><span class="lineno">11045</span>&#160;    {</div>
+<div class="line"><a name="l11046"></a><span class="lineno">11046</span>&#160;        VmaSuballocation refSuballoc;</div>
+<div class="line"><a name="l11047"></a><span class="lineno">11047</span>&#160;        refSuballoc.offset = offset;</div>
+<div class="line"><a name="l11048"></a><span class="lineno">11048</span>&#160;        <span class="comment">// Rest of members stays uninitialized intentionally for better performance.</span></div>
+<div class="line"><a name="l11049"></a><span class="lineno">11049</span>&#160;        SuballocationVectorType::iterator it = VmaBinaryFindSorted(</div>
+<div class="line"><a name="l11050"></a><span class="lineno">11050</span>&#160;            suballocations1st.begin() + m_1stNullItemsBeginCount,</div>
+<div class="line"><a name="l11051"></a><span class="lineno">11051</span>&#160;            suballocations1st.end(),</div>
+<div class="line"><a name="l11052"></a><span class="lineno">11052</span>&#160;            refSuballoc,</div>
+<div class="line"><a name="l11053"></a><span class="lineno">11053</span>&#160;            VmaSuballocationOffsetLess());</div>
+<div class="line"><a name="l11054"></a><span class="lineno">11054</span>&#160;        <span class="keywordflow">if</span>(it != suballocations1st.end())</div>
+<div class="line"><a name="l11055"></a><span class="lineno">11055</span>&#160;        {</div>
+<div class="line"><a name="l11056"></a><span class="lineno">11056</span>&#160;            it-&gt;type = VMA_SUBALLOCATION_TYPE_FREE;</div>
+<div class="line"><a name="l11057"></a><span class="lineno">11057</span>&#160;            it-&gt;hAllocation = VK_NULL_HANDLE;</div>
+<div class="line"><a name="l11058"></a><span class="lineno">11058</span>&#160;            ++m_1stNullItemsMiddleCount;</div>
+<div class="line"><a name="l11059"></a><span class="lineno">11059</span>&#160;            m_SumFreeSize += it-&gt;size;</div>
+<div class="line"><a name="l11060"></a><span class="lineno">11060</span>&#160;            CleanupAfterFree();</div>
+<div class="line"><a name="l11061"></a><span class="lineno">11061</span>&#160;            <span class="keywordflow">return</span>;</div>
+<div class="line"><a name="l11062"></a><span class="lineno">11062</span>&#160;        }</div>
+<div class="line"><a name="l11063"></a><span class="lineno">11063</span>&#160;    }</div>
+<div class="line"><a name="l11064"></a><span class="lineno">11064</span>&#160; </div>
+<div class="line"><a name="l11065"></a><span class="lineno">11065</span>&#160;    <span class="keywordflow">if</span>(m_2ndVectorMode != SECOND_VECTOR_EMPTY)</div>
+<div class="line"><a name="l11066"></a><span class="lineno">11066</span>&#160;    {</div>
+<div class="line"><a name="l11067"></a><span class="lineno">11067</span>&#160;        <span class="comment">// Item from the middle of 2nd vector.</span></div>
+<div class="line"><a name="l11068"></a><span class="lineno">11068</span>&#160;        VmaSuballocation refSuballoc;</div>
+<div class="line"><a name="l11069"></a><span class="lineno">11069</span>&#160;        refSuballoc.offset = offset;</div>
+<div class="line"><a name="l11070"></a><span class="lineno">11070</span>&#160;        <span class="comment">// Rest of members stays uninitialized intentionally for better performance.</span></div>
+<div class="line"><a name="l11071"></a><span class="lineno">11071</span>&#160;        SuballocationVectorType::iterator it = m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER ?</div>
+<div class="line"><a name="l11072"></a><span class="lineno">11072</span>&#160;            VmaBinaryFindSorted(suballocations2nd.begin(), suballocations2nd.end(), refSuballoc, VmaSuballocationOffsetLess()) :</div>
+<div class="line"><a name="l11073"></a><span class="lineno">11073</span>&#160;            VmaBinaryFindSorted(suballocations2nd.begin(), suballocations2nd.end(), refSuballoc, VmaSuballocationOffsetGreater());</div>
+<div class="line"><a name="l11074"></a><span class="lineno">11074</span>&#160;        <span class="keywordflow">if</span>(it != suballocations2nd.end())</div>
+<div class="line"><a name="l11075"></a><span class="lineno">11075</span>&#160;        {</div>
+<div class="line"><a name="l11076"></a><span class="lineno">11076</span>&#160;            it-&gt;type = VMA_SUBALLOCATION_TYPE_FREE;</div>
+<div class="line"><a name="l11077"></a><span class="lineno">11077</span>&#160;            it-&gt;hAllocation = VK_NULL_HANDLE;</div>
+<div class="line"><a name="l11078"></a><span class="lineno">11078</span>&#160;            ++m_2ndNullItemsCount;</div>
+<div class="line"><a name="l11079"></a><span class="lineno">11079</span>&#160;            m_SumFreeSize += it-&gt;size;</div>
+<div class="line"><a name="l11080"></a><span class="lineno">11080</span>&#160;            CleanupAfterFree();</div>
+<div class="line"><a name="l11081"></a><span class="lineno">11081</span>&#160;            <span class="keywordflow">return</span>;</div>
+<div class="line"><a name="l11082"></a><span class="lineno">11082</span>&#160;        }</div>
+<div class="line"><a name="l11083"></a><span class="lineno">11083</span>&#160;    }</div>
+<div class="line"><a name="l11084"></a><span class="lineno">11084</span>&#160; </div>
+<div class="line"><a name="l11085"></a><span class="lineno">11085</span>&#160;    VMA_ASSERT(0 &amp;&amp; <span class="stringliteral">&quot;Allocation to free not found in linear allocator!&quot;</span>);</div>
+<div class="line"><a name="l11086"></a><span class="lineno">11086</span>&#160;}</div>
+<div class="line"><a name="l11087"></a><span class="lineno">11087</span>&#160; </div>
+<div class="line"><a name="l11088"></a><span class="lineno">11088</span>&#160;<span class="keywordtype">bool</span> VmaBlockMetadata_Linear::ShouldCompact1st()<span class="keyword"> const</span></div>
+<div class="line"><a name="l11089"></a><span class="lineno">11089</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l11090"></a><span class="lineno">11090</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">size_t</span> nullItemCount = m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount;</div>
+<div class="line"><a name="l11091"></a><span class="lineno">11091</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">size_t</span> suballocCount = AccessSuballocations1st().size();</div>
+<div class="line"><a name="l11092"></a><span class="lineno">11092</span>&#160;    <span class="keywordflow">return</span> suballocCount &gt; 32 &amp;&amp; nullItemCount * 2 &gt;= (suballocCount - nullItemCount) * 3;</div>
+<div class="line"><a name="l11093"></a><span class="lineno">11093</span>&#160;}</div>
+<div class="line"><a name="l11094"></a><span class="lineno">11094</span>&#160; </div>
+<div class="line"><a name="l11095"></a><span class="lineno">11095</span>&#160;<span class="keywordtype">void</span> VmaBlockMetadata_Linear::CleanupAfterFree()</div>
+<div class="line"><a name="l11096"></a><span class="lineno">11096</span>&#160;{</div>
+<div class="line"><a name="l11097"></a><span class="lineno">11097</span>&#160;    SuballocationVectorType&amp; suballocations1st = AccessSuballocations1st();</div>
+<div class="line"><a name="l11098"></a><span class="lineno">11098</span>&#160;    SuballocationVectorType&amp; suballocations2nd = AccessSuballocations2nd();</div>
+<div class="line"><a name="l11099"></a><span class="lineno">11099</span>&#160; </div>
+<div class="line"><a name="l11100"></a><span class="lineno">11100</span>&#160;    <span class="keywordflow">if</span>(IsEmpty())</div>
+<div class="line"><a name="l11101"></a><span class="lineno">11101</span>&#160;    {</div>
+<div class="line"><a name="l11102"></a><span class="lineno">11102</span>&#160;        suballocations1st.clear();</div>
+<div class="line"><a name="l11103"></a><span class="lineno">11103</span>&#160;        suballocations2nd.clear();</div>
+<div class="line"><a name="l11104"></a><span class="lineno">11104</span>&#160;        m_1stNullItemsBeginCount = 0;</div>
+<div class="line"><a name="l11105"></a><span class="lineno">11105</span>&#160;        m_1stNullItemsMiddleCount = 0;</div>
+<div class="line"><a name="l11106"></a><span class="lineno">11106</span>&#160;        m_2ndNullItemsCount = 0;</div>
+<div class="line"><a name="l11107"></a><span class="lineno">11107</span>&#160;        m_2ndVectorMode = SECOND_VECTOR_EMPTY;</div>
+<div class="line"><a name="l11108"></a><span class="lineno">11108</span>&#160;    }</div>
+<div class="line"><a name="l11109"></a><span class="lineno">11109</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l11110"></a><span class="lineno">11110</span>&#160;    {</div>
+<div class="line"><a name="l11111"></a><span class="lineno">11111</span>&#160;        <span class="keyword">const</span> <span class="keywordtype">size_t</span> suballoc1stCount = suballocations1st.size();</div>
+<div class="line"><a name="l11112"></a><span class="lineno">11112</span>&#160;        <span class="keyword">const</span> <span class="keywordtype">size_t</span> nullItem1stCount = m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount;</div>
+<div class="line"><a name="l11113"></a><span class="lineno">11113</span>&#160;        VMA_ASSERT(nullItem1stCount &lt;= suballoc1stCount);</div>
+<div class="line"><a name="l11114"></a><span class="lineno">11114</span>&#160; </div>
+<div class="line"><a name="l11115"></a><span class="lineno">11115</span>&#160;        <span class="comment">// Find more null items at the beginning of 1st vector.</span></div>
+<div class="line"><a name="l11116"></a><span class="lineno">11116</span>&#160;        <span class="keywordflow">while</span>(m_1stNullItemsBeginCount &lt; suballoc1stCount &amp;&amp;</div>
+<div class="line"><a name="l11117"></a><span class="lineno">11117</span>&#160;            suballocations1st[m_1stNullItemsBeginCount].hAllocation == VK_NULL_HANDLE)</div>
+<div class="line"><a name="l11118"></a><span class="lineno">11118</span>&#160;        {</div>
+<div class="line"><a name="l11119"></a><span class="lineno">11119</span>&#160;            ++m_1stNullItemsBeginCount;</div>
+<div class="line"><a name="l11120"></a><span class="lineno">11120</span>&#160;            --m_1stNullItemsMiddleCount;</div>
+<div class="line"><a name="l11121"></a><span class="lineno">11121</span>&#160;        }</div>
+<div class="line"><a name="l11122"></a><span class="lineno">11122</span>&#160; </div>
+<div class="line"><a name="l11123"></a><span class="lineno">11123</span>&#160;        <span class="comment">// Find more null items at the end of 1st vector.</span></div>
+<div class="line"><a name="l11124"></a><span class="lineno">11124</span>&#160;        <span class="keywordflow">while</span>(m_1stNullItemsMiddleCount &gt; 0 &amp;&amp;</div>
+<div class="line"><a name="l11125"></a><span class="lineno">11125</span>&#160;            suballocations1st.back().hAllocation == VK_NULL_HANDLE)</div>
+<div class="line"><a name="l11126"></a><span class="lineno">11126</span>&#160;        {</div>
+<div class="line"><a name="l11127"></a><span class="lineno">11127</span>&#160;            --m_1stNullItemsMiddleCount;</div>
+<div class="line"><a name="l11128"></a><span class="lineno">11128</span>&#160;            suballocations1st.pop_back();</div>
+<div class="line"><a name="l11129"></a><span class="lineno">11129</span>&#160;        }</div>
+<div class="line"><a name="l11130"></a><span class="lineno">11130</span>&#160; </div>
+<div class="line"><a name="l11131"></a><span class="lineno">11131</span>&#160;        <span class="comment">// Find more null items at the end of 2nd vector.</span></div>
+<div class="line"><a name="l11132"></a><span class="lineno">11132</span>&#160;        <span class="keywordflow">while</span>(m_2ndNullItemsCount &gt; 0 &amp;&amp;</div>
+<div class="line"><a name="l11133"></a><span class="lineno">11133</span>&#160;            suballocations2nd.back().hAllocation == VK_NULL_HANDLE)</div>
+<div class="line"><a name="l11134"></a><span class="lineno">11134</span>&#160;        {</div>
+<div class="line"><a name="l11135"></a><span class="lineno">11135</span>&#160;            --m_2ndNullItemsCount;</div>
+<div class="line"><a name="l11136"></a><span class="lineno">11136</span>&#160;            suballocations2nd.pop_back();</div>
+<div class="line"><a name="l11137"></a><span class="lineno">11137</span>&#160;        }</div>
+<div class="line"><a name="l11138"></a><span class="lineno">11138</span>&#160; </div>
+<div class="line"><a name="l11139"></a><span class="lineno">11139</span>&#160;        <span class="comment">// Find more null items at the beginning of 2nd vector.</span></div>
+<div class="line"><a name="l11140"></a><span class="lineno">11140</span>&#160;        <span class="keywordflow">while</span>(m_2ndNullItemsCount &gt; 0 &amp;&amp;</div>
+<div class="line"><a name="l11141"></a><span class="lineno">11141</span>&#160;            suballocations2nd[0].hAllocation == VK_NULL_HANDLE)</div>
+<div class="line"><a name="l11142"></a><span class="lineno">11142</span>&#160;        {</div>
+<div class="line"><a name="l11143"></a><span class="lineno">11143</span>&#160;            --m_2ndNullItemsCount;</div>
+<div class="line"><a name="l11144"></a><span class="lineno">11144</span>&#160;            VmaVectorRemove(suballocations2nd, 0);</div>
+<div class="line"><a name="l11145"></a><span class="lineno">11145</span>&#160;        }</div>
+<div class="line"><a name="l11146"></a><span class="lineno">11146</span>&#160; </div>
+<div class="line"><a name="l11147"></a><span class="lineno">11147</span>&#160;        <span class="keywordflow">if</span>(ShouldCompact1st())</div>
+<div class="line"><a name="l11148"></a><span class="lineno">11148</span>&#160;        {</div>
+<div class="line"><a name="l11149"></a><span class="lineno">11149</span>&#160;            <span class="keyword">const</span> <span class="keywordtype">size_t</span> nonNullItemCount = suballoc1stCount - nullItem1stCount;</div>
+<div class="line"><a name="l11150"></a><span class="lineno">11150</span>&#160;            <span class="keywordtype">size_t</span> srcIndex = m_1stNullItemsBeginCount;</div>
+<div class="line"><a name="l11151"></a><span class="lineno">11151</span>&#160;            <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> dstIndex = 0; dstIndex &lt; nonNullItemCount; ++dstIndex)</div>
+<div class="line"><a name="l11152"></a><span class="lineno">11152</span>&#160;            {</div>
+<div class="line"><a name="l11153"></a><span class="lineno">11153</span>&#160;                <span class="keywordflow">while</span>(suballocations1st[srcIndex].hAllocation == VK_NULL_HANDLE)</div>
+<div class="line"><a name="l11154"></a><span class="lineno">11154</span>&#160;                {</div>
+<div class="line"><a name="l11155"></a><span class="lineno">11155</span>&#160;                    ++srcIndex;</div>
+<div class="line"><a name="l11156"></a><span class="lineno">11156</span>&#160;                }</div>
+<div class="line"><a name="l11157"></a><span class="lineno">11157</span>&#160;                <span class="keywordflow">if</span>(dstIndex != srcIndex)</div>
+<div class="line"><a name="l11158"></a><span class="lineno">11158</span>&#160;                {</div>
+<div class="line"><a name="l11159"></a><span class="lineno">11159</span>&#160;                    suballocations1st[dstIndex] = suballocations1st[srcIndex];</div>
+<div class="line"><a name="l11160"></a><span class="lineno">11160</span>&#160;                }</div>
+<div class="line"><a name="l11161"></a><span class="lineno">11161</span>&#160;                ++srcIndex;</div>
+<div class="line"><a name="l11162"></a><span class="lineno">11162</span>&#160;            }</div>
+<div class="line"><a name="l11163"></a><span class="lineno">11163</span>&#160;            suballocations1st.resize(nonNullItemCount);</div>
+<div class="line"><a name="l11164"></a><span class="lineno">11164</span>&#160;            m_1stNullItemsBeginCount = 0;</div>
+<div class="line"><a name="l11165"></a><span class="lineno">11165</span>&#160;            m_1stNullItemsMiddleCount = 0;</div>
+<div class="line"><a name="l11166"></a><span class="lineno">11166</span>&#160;        }</div>
+<div class="line"><a name="l11167"></a><span class="lineno">11167</span>&#160; </div>
+<div class="line"><a name="l11168"></a><span class="lineno">11168</span>&#160;        <span class="comment">// 2nd vector became empty.</span></div>
+<div class="line"><a name="l11169"></a><span class="lineno">11169</span>&#160;        <span class="keywordflow">if</span>(suballocations2nd.empty())</div>
+<div class="line"><a name="l11170"></a><span class="lineno">11170</span>&#160;        {</div>
+<div class="line"><a name="l11171"></a><span class="lineno">11171</span>&#160;            m_2ndVectorMode = SECOND_VECTOR_EMPTY;</div>
+<div class="line"><a name="l11172"></a><span class="lineno">11172</span>&#160;        }</div>
+<div class="line"><a name="l11173"></a><span class="lineno">11173</span>&#160; </div>
+<div class="line"><a name="l11174"></a><span class="lineno">11174</span>&#160;        <span class="comment">// 1st vector became empty.</span></div>
+<div class="line"><a name="l11175"></a><span class="lineno">11175</span>&#160;        <span class="keywordflow">if</span>(suballocations1st.size() - m_1stNullItemsBeginCount == 0)</div>
+<div class="line"><a name="l11176"></a><span class="lineno">11176</span>&#160;        {</div>
+<div class="line"><a name="l11177"></a><span class="lineno">11177</span>&#160;            suballocations1st.clear();</div>
+<div class="line"><a name="l11178"></a><span class="lineno">11178</span>&#160;            m_1stNullItemsBeginCount = 0;</div>
+<div class="line"><a name="l11179"></a><span class="lineno">11179</span>&#160; </div>
+<div class="line"><a name="l11180"></a><span class="lineno">11180</span>&#160;            <span class="keywordflow">if</span>(!suballocations2nd.empty() &amp;&amp; m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)</div>
+<div class="line"><a name="l11181"></a><span class="lineno">11181</span>&#160;            {</div>
+<div class="line"><a name="l11182"></a><span class="lineno">11182</span>&#160;                <span class="comment">// Swap 1st with 2nd. Now 2nd is empty.</span></div>
+<div class="line"><a name="l11183"></a><span class="lineno">11183</span>&#160;                m_2ndVectorMode = SECOND_VECTOR_EMPTY;</div>
+<div class="line"><a name="l11184"></a><span class="lineno">11184</span>&#160;                m_1stNullItemsMiddleCount = m_2ndNullItemsCount;</div>
+<div class="line"><a name="l11185"></a><span class="lineno">11185</span>&#160;                <span class="keywordflow">while</span>(m_1stNullItemsBeginCount &lt; suballocations2nd.size() &amp;&amp;</div>
+<div class="line"><a name="l11186"></a><span class="lineno">11186</span>&#160;                    suballocations2nd[m_1stNullItemsBeginCount].hAllocation == VK_NULL_HANDLE)</div>
+<div class="line"><a name="l11187"></a><span class="lineno">11187</span>&#160;                {</div>
+<div class="line"><a name="l11188"></a><span class="lineno">11188</span>&#160;                    ++m_1stNullItemsBeginCount;</div>
+<div class="line"><a name="l11189"></a><span class="lineno">11189</span>&#160;                    --m_1stNullItemsMiddleCount;</div>
+<div class="line"><a name="l11190"></a><span class="lineno">11190</span>&#160;                }</div>
+<div class="line"><a name="l11191"></a><span class="lineno">11191</span>&#160;                m_2ndNullItemsCount = 0;</div>
+<div class="line"><a name="l11192"></a><span class="lineno">11192</span>&#160;                m_1stVectorIndex ^= 1;</div>
+<div class="line"><a name="l11193"></a><span class="lineno">11193</span>&#160;            }</div>
+<div class="line"><a name="l11194"></a><span class="lineno">11194</span>&#160;        }</div>
+<div class="line"><a name="l11195"></a><span class="lineno">11195</span>&#160;    }</div>
+<div class="line"><a name="l11196"></a><span class="lineno">11196</span>&#160; </div>
+<div class="line"><a name="l11197"></a><span class="lineno">11197</span>&#160;    VMA_HEAVY_ASSERT(Validate());</div>
+<div class="line"><a name="l11198"></a><span class="lineno">11198</span>&#160;}</div>
+<div class="line"><a name="l11199"></a><span class="lineno">11199</span>&#160; </div>
+<div class="line"><a name="l11200"></a><span class="lineno">11200</span>&#160; </div>
+<div class="line"><a name="l11202"></a><span class="lineno">11202</span>&#160;<span class="comment">// class VmaBlockMetadata_Buddy</span></div>
+<div class="line"><a name="l11203"></a><span class="lineno">11203</span>&#160; </div>
+<div class="line"><a name="l11204"></a><span class="lineno">11204</span>&#160;VmaBlockMetadata_Buddy::VmaBlockMetadata_Buddy(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator) :</div>
+<div class="line"><a name="l11205"></a><span class="lineno">11205</span>&#160;    VmaBlockMetadata(hAllocator),</div>
+<div class="line"><a name="l11206"></a><span class="lineno">11206</span>&#160;    m_Root(VMA_NULL),</div>
+<div class="line"><a name="l11207"></a><span class="lineno">11207</span>&#160;    m_AllocationCount(0),</div>
+<div class="line"><a name="l11208"></a><span class="lineno">11208</span>&#160;    m_FreeCount(1),</div>
+<div class="line"><a name="l11209"></a><span class="lineno">11209</span>&#160;    m_SumFreeSize(0)</div>
+<div class="line"><a name="l11210"></a><span class="lineno">11210</span>&#160;{</div>
+<div class="line"><a name="l11211"></a><span class="lineno">11211</span>&#160;    memset(m_FreeList, 0, <span class="keyword">sizeof</span>(m_FreeList));</div>
+<div class="line"><a name="l11212"></a><span class="lineno">11212</span>&#160;}</div>
+<div class="line"><a name="l11213"></a><span class="lineno">11213</span>&#160; </div>
+<div class="line"><a name="l11214"></a><span class="lineno">11214</span>&#160;VmaBlockMetadata_Buddy::~VmaBlockMetadata_Buddy()</div>
+<div class="line"><a name="l11215"></a><span class="lineno">11215</span>&#160;{</div>
+<div class="line"><a name="l11216"></a><span class="lineno">11216</span>&#160;    DeleteNode(m_Root);</div>
+<div class="line"><a name="l11217"></a><span class="lineno">11217</span>&#160;}</div>
+<div class="line"><a name="l11218"></a><span class="lineno">11218</span>&#160; </div>
+<div class="line"><a name="l11219"></a><span class="lineno">11219</span>&#160;<span class="keywordtype">void</span> VmaBlockMetadata_Buddy::Init(VkDeviceSize size)</div>
+<div class="line"><a name="l11220"></a><span class="lineno">11220</span>&#160;{</div>
+<div class="line"><a name="l11221"></a><span class="lineno">11221</span>&#160;    VmaBlockMetadata::Init(size);</div>
+<div class="line"><a name="l11222"></a><span class="lineno">11222</span>&#160; </div>
+<div class="line"><a name="l11223"></a><span class="lineno">11223</span>&#160;    m_UsableSize = VmaPrevPow2(size);</div>
+<div class="line"><a name="l11224"></a><span class="lineno">11224</span>&#160;    m_SumFreeSize = m_UsableSize;</div>
+<div class="line"><a name="l11225"></a><span class="lineno">11225</span>&#160; </div>
+<div class="line"><a name="l11226"></a><span class="lineno">11226</span>&#160;    <span class="comment">// Calculate m_LevelCount.</span></div>
+<div class="line"><a name="l11227"></a><span class="lineno">11227</span>&#160;    m_LevelCount = 1;</div>
+<div class="line"><a name="l11228"></a><span class="lineno">11228</span>&#160;    <span class="keywordflow">while</span>(m_LevelCount &lt; MAX_LEVELS &amp;&amp;</div>
+<div class="line"><a name="l11229"></a><span class="lineno">11229</span>&#160;        LevelToNodeSize(m_LevelCount) &gt;= MIN_NODE_SIZE)</div>
+<div class="line"><a name="l11230"></a><span class="lineno">11230</span>&#160;    {</div>
+<div class="line"><a name="l11231"></a><span class="lineno">11231</span>&#160;        ++m_LevelCount;</div>
+<div class="line"><a name="l11232"></a><span class="lineno">11232</span>&#160;    }</div>
+<div class="line"><a name="l11233"></a><span class="lineno">11233</span>&#160; </div>
+<div class="line"><a name="l11234"></a><span class="lineno">11234</span>&#160;    Node* rootNode = vma_new(GetAllocationCallbacks(), Node)();</div>
+<div class="line"><a name="l11235"></a><span class="lineno">11235</span>&#160;    rootNode-&gt;offset = 0;</div>
+<div class="line"><a name="l11236"></a><span class="lineno">11236</span>&#160;    rootNode-&gt;type = Node::TYPE_FREE;</div>
+<div class="line"><a name="l11237"></a><span class="lineno">11237</span>&#160;    rootNode-&gt;parent = VMA_NULL;</div>
+<div class="line"><a name="l11238"></a><span class="lineno">11238</span>&#160;    rootNode-&gt;buddy = VMA_NULL;</div>
+<div class="line"><a name="l11239"></a><span class="lineno">11239</span>&#160; </div>
+<div class="line"><a name="l11240"></a><span class="lineno">11240</span>&#160;    m_Root = rootNode;</div>
+<div class="line"><a name="l11241"></a><span class="lineno">11241</span>&#160;    AddToFreeListFront(0, rootNode);</div>
+<div class="line"><a name="l11242"></a><span class="lineno">11242</span>&#160;}</div>
+<div class="line"><a name="l11243"></a><span class="lineno">11243</span>&#160; </div>
+<div class="line"><a name="l11244"></a><span class="lineno">11244</span>&#160;<span class="keywordtype">bool</span> VmaBlockMetadata_Buddy::Validate()<span class="keyword"> const</span></div>
+<div class="line"><a name="l11245"></a><span class="lineno">11245</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l11246"></a><span class="lineno">11246</span>&#160;    <span class="comment">// Validate tree.</span></div>
+<div class="line"><a name="l11247"></a><span class="lineno">11247</span>&#160;    ValidationContext ctx;</div>
+<div class="line"><a name="l11248"></a><span class="lineno">11248</span>&#160;    <span class="keywordflow">if</span>(!ValidateNode(ctx, VMA_NULL, m_Root, 0, LevelToNodeSize(0)))</div>
+<div class="line"><a name="l11249"></a><span class="lineno">11249</span>&#160;    {</div>
+<div class="line"><a name="l11250"></a><span class="lineno">11250</span>&#160;        VMA_VALIDATE(<span class="keyword">false</span> &amp;&amp; <span class="stringliteral">&quot;ValidateNode failed.&quot;</span>);</div>
+<div class="line"><a name="l11251"></a><span class="lineno">11251</span>&#160;    }</div>
+<div class="line"><a name="l11252"></a><span class="lineno">11252</span>&#160;    VMA_VALIDATE(m_AllocationCount == ctx.calculatedAllocationCount);</div>
+<div class="line"><a name="l11253"></a><span class="lineno">11253</span>&#160;    VMA_VALIDATE(m_SumFreeSize == ctx.calculatedSumFreeSize);</div>
+<div class="line"><a name="l11254"></a><span class="lineno">11254</span>&#160; </div>
+<div class="line"><a name="l11255"></a><span class="lineno">11255</span>&#160;    <span class="comment">// Validate free node lists.</span></div>
+<div class="line"><a name="l11256"></a><span class="lineno">11256</span>&#160;    <span class="keywordflow">for</span>(uint32_t level = 0; level &lt; m_LevelCount; ++level)</div>
+<div class="line"><a name="l11257"></a><span class="lineno">11257</span>&#160;    {</div>
+<div class="line"><a name="l11258"></a><span class="lineno">11258</span>&#160;        VMA_VALIDATE(m_FreeList[level].front == VMA_NULL ||</div>
+<div class="line"><a name="l11259"></a><span class="lineno">11259</span>&#160;            m_FreeList[level].front-&gt;free.prev == VMA_NULL);</div>
+<div class="line"><a name="l11260"></a><span class="lineno">11260</span>&#160; </div>
+<div class="line"><a name="l11261"></a><span class="lineno">11261</span>&#160;        <span class="keywordflow">for</span>(Node* node = m_FreeList[level].front;</div>
+<div class="line"><a name="l11262"></a><span class="lineno">11262</span>&#160;            node != VMA_NULL;</div>
+<div class="line"><a name="l11263"></a><span class="lineno">11263</span>&#160;            node = node-&gt;free.next)</div>
+<div class="line"><a name="l11264"></a><span class="lineno">11264</span>&#160;        {</div>
+<div class="line"><a name="l11265"></a><span class="lineno">11265</span>&#160;            VMA_VALIDATE(node-&gt;type == Node::TYPE_FREE);</div>
+<div class="line"><a name="l11266"></a><span class="lineno">11266</span>&#160;            </div>
+<div class="line"><a name="l11267"></a><span class="lineno">11267</span>&#160;            <span class="keywordflow">if</span>(node-&gt;free.next == VMA_NULL)</div>
+<div class="line"><a name="l11268"></a><span class="lineno">11268</span>&#160;            {</div>
+<div class="line"><a name="l11269"></a><span class="lineno">11269</span>&#160;                VMA_VALIDATE(m_FreeList[level].back == node);</div>
+<div class="line"><a name="l11270"></a><span class="lineno">11270</span>&#160;            }</div>
+<div class="line"><a name="l11271"></a><span class="lineno">11271</span>&#160;            <span class="keywordflow">else</span></div>
+<div class="line"><a name="l11272"></a><span class="lineno">11272</span>&#160;            {</div>
+<div class="line"><a name="l11273"></a><span class="lineno">11273</span>&#160;                VMA_VALIDATE(node-&gt;free.next-&gt;free.prev == node);</div>
+<div class="line"><a name="l11274"></a><span class="lineno">11274</span>&#160;            }</div>
+<div class="line"><a name="l11275"></a><span class="lineno">11275</span>&#160;        }</div>
+<div class="line"><a name="l11276"></a><span class="lineno">11276</span>&#160;    }</div>
+<div class="line"><a name="l11277"></a><span class="lineno">11277</span>&#160; </div>
+<div class="line"><a name="l11278"></a><span class="lineno">11278</span>&#160;    <span class="comment">// Validate that free lists ar higher levels are empty.</span></div>
+<div class="line"><a name="l11279"></a><span class="lineno">11279</span>&#160;    <span class="keywordflow">for</span>(uint32_t level = m_LevelCount; level &lt; MAX_LEVELS; ++level)</div>
+<div class="line"><a name="l11280"></a><span class="lineno">11280</span>&#160;    {</div>
+<div class="line"><a name="l11281"></a><span class="lineno">11281</span>&#160;        VMA_VALIDATE(m_FreeList[level].front == VMA_NULL &amp;&amp; m_FreeList[level].back == VMA_NULL);</div>
+<div class="line"><a name="l11282"></a><span class="lineno">11282</span>&#160;    }</div>
+<div class="line"><a name="l11283"></a><span class="lineno">11283</span>&#160; </div>
+<div class="line"><a name="l11284"></a><span class="lineno">11284</span>&#160;    <span class="keywordflow">return</span> <span class="keyword">true</span>;</div>
+<div class="line"><a name="l11285"></a><span class="lineno">11285</span>&#160;}</div>
+<div class="line"><a name="l11286"></a><span class="lineno">11286</span>&#160; </div>
+<div class="line"><a name="l11287"></a><span class="lineno">11287</span>&#160;VkDeviceSize VmaBlockMetadata_Buddy::GetUnusedRangeSizeMax()<span class="keyword"> const</span></div>
+<div class="line"><a name="l11288"></a><span class="lineno">11288</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l11289"></a><span class="lineno">11289</span>&#160;    <span class="keywordflow">for</span>(uint32_t level = 0; level &lt; m_LevelCount; ++level)</div>
+<div class="line"><a name="l11290"></a><span class="lineno">11290</span>&#160;    {</div>
+<div class="line"><a name="l11291"></a><span class="lineno">11291</span>&#160;        <span class="keywordflow">if</span>(m_FreeList[level].front != VMA_NULL)</div>
+<div class="line"><a name="l11292"></a><span class="lineno">11292</span>&#160;        {</div>
+<div class="line"><a name="l11293"></a><span class="lineno">11293</span>&#160;            <span class="keywordflow">return</span> LevelToNodeSize(level);</div>
+<div class="line"><a name="l11294"></a><span class="lineno">11294</span>&#160;        }</div>
+<div class="line"><a name="l11295"></a><span class="lineno">11295</span>&#160;    }</div>
+<div class="line"><a name="l11296"></a><span class="lineno">11296</span>&#160;    <span class="keywordflow">return</span> 0;</div>
+<div class="line"><a name="l11297"></a><span class="lineno">11297</span>&#160;}</div>
+<div class="line"><a name="l11298"></a><span class="lineno">11298</span>&#160; </div>
+<div class="line"><a name="l11299"></a><span class="lineno">11299</span>&#160;<span class="keywordtype">void</span> VmaBlockMetadata_Buddy::CalcAllocationStatInfo(<a class="code" href="struct_vma_stat_info.html">VmaStatInfo</a>&amp; outInfo)<span class="keyword"> const</span></div>
+<div class="line"><a name="l11300"></a><span class="lineno">11300</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l11301"></a><span class="lineno">11301</span>&#160;    <span class="keyword">const</span> VkDeviceSize unusableSize = GetUnusableSize();</div>
+<div class="line"><a name="l11302"></a><span class="lineno">11302</span>&#160; </div>
+<div class="line"><a name="l11303"></a><span class="lineno">11303</span>&#160;    outInfo.<a class="code" href="struct_vma_stat_info.html#abc4bb7cd611900778464c56e50c970a4">blockCount</a> = 1;</div>
+<div class="line"><a name="l11304"></a><span class="lineno">11304</span>&#160; </div>
+<div class="line"><a name="l11305"></a><span class="lineno">11305</span>&#160;    outInfo.<a class="code" href="struct_vma_stat_info.html#a537741e4d5cdddc1c0ab95ec650afaff">allocationCount</a> = outInfo.<a class="code" href="struct_vma_stat_info.html#ae06129c771bfebfd6468a7f4276502a9">unusedRangeCount</a> = 0;</div>
+<div class="line"><a name="l11306"></a><span class="lineno">11306</span>&#160;    outInfo.<a class="code" href="struct_vma_stat_info.html#ab0c6c73837e5a70c749fbd4f6064895a">usedBytes</a> = outInfo.<a class="code" href="struct_vma_stat_info.html#a1859d290aca2cd582d8dc25922092669">unusedBytes</a> = 0;</div>
+<div class="line"><a name="l11307"></a><span class="lineno">11307</span>&#160; </div>
+<div class="line"><a name="l11308"></a><span class="lineno">11308</span>&#160;    outInfo.<a class="code" href="struct_vma_stat_info.html#a17e9733a5ecd76287d4db6e66f71f50c">allocationSizeMax</a> = outInfo.<a class="code" href="struct_vma_stat_info.html#a5ba1a2476c4d39b10f7e2f7ebbb72ac4">unusedRangeSizeMax</a> = 0;</div>
+<div class="line"><a name="l11309"></a><span class="lineno">11309</span>&#160;    outInfo.<a class="code" href="struct_vma_stat_info.html#ade8b40bd3139c04aabd2fc538a356fea">allocationSizeMin</a> = outInfo.<a class="code" href="struct_vma_stat_info.html#aedeba931324f16589cd2416c0d2dd0d4">unusedRangeSizeMin</a> = UINT64_MAX;</div>
+<div class="line"><a name="l11310"></a><span class="lineno">11310</span>&#160;    outInfo.<a class="code" href="struct_vma_stat_info.html#a1081a039964e566c672e7a2347f9e599">allocationSizeAvg</a> = outInfo.<a class="code" href="struct_vma_stat_info.html#a2f9b3452af90c9768a30b7fb6ae194fc">unusedRangeSizeAvg</a> = 0; <span class="comment">// Unused.</span></div>
+<div class="line"><a name="l11311"></a><span class="lineno">11311</span>&#160; </div>
+<div class="line"><a name="l11312"></a><span class="lineno">11312</span>&#160;    CalcAllocationStatInfoNode(outInfo, m_Root, LevelToNodeSize(0));</div>
+<div class="line"><a name="l11313"></a><span class="lineno">11313</span>&#160; </div>
+<div class="line"><a name="l11314"></a><span class="lineno">11314</span>&#160;    <span class="keywordflow">if</span>(unusableSize &gt; 0)</div>
+<div class="line"><a name="l11315"></a><span class="lineno">11315</span>&#160;    {</div>
+<div class="line"><a name="l11316"></a><span class="lineno">11316</span>&#160;        ++outInfo.<a class="code" href="struct_vma_stat_info.html#ae06129c771bfebfd6468a7f4276502a9">unusedRangeCount</a>;</div>
+<div class="line"><a name="l11317"></a><span class="lineno">11317</span>&#160;        outInfo.<a class="code" href="struct_vma_stat_info.html#a1859d290aca2cd582d8dc25922092669">unusedBytes</a> += unusableSize;</div>
+<div class="line"><a name="l11318"></a><span class="lineno">11318</span>&#160;        outInfo.<a class="code" href="struct_vma_stat_info.html#a5ba1a2476c4d39b10f7e2f7ebbb72ac4">unusedRangeSizeMax</a> = VMA_MAX(outInfo.<a class="code" href="struct_vma_stat_info.html#a5ba1a2476c4d39b10f7e2f7ebbb72ac4">unusedRangeSizeMax</a>, unusableSize);</div>
+<div class="line"><a name="l11319"></a><span class="lineno">11319</span>&#160;        outInfo.<a class="code" href="struct_vma_stat_info.html#aedeba931324f16589cd2416c0d2dd0d4">unusedRangeSizeMin</a> = VMA_MIN(outInfo.<a class="code" href="struct_vma_stat_info.html#aedeba931324f16589cd2416c0d2dd0d4">unusedRangeSizeMin</a>, unusableSize);</div>
+<div class="line"><a name="l11320"></a><span class="lineno">11320</span>&#160;    }</div>
+<div class="line"><a name="l11321"></a><span class="lineno">11321</span>&#160;}</div>
+<div class="line"><a name="l11322"></a><span class="lineno">11322</span>&#160; </div>
+<div class="line"><a name="l11323"></a><span class="lineno">11323</span>&#160;<span class="keywordtype">void</span> VmaBlockMetadata_Buddy::AddPoolStats(<a class="code" href="struct_vma_pool_stats.html">VmaPoolStats</a>&amp; inoutStats)<span class="keyword"> const</span></div>
+<div class="line"><a name="l11324"></a><span class="lineno">11324</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l11325"></a><span class="lineno">11325</span>&#160;    <span class="keyword">const</span> VkDeviceSize unusableSize = GetUnusableSize();</div>
+<div class="line"><a name="l11326"></a><span class="lineno">11326</span>&#160; </div>
+<div class="line"><a name="l11327"></a><span class="lineno">11327</span>&#160;    inoutStats.<a class="code" href="struct_vma_pool_stats.html#a326807b2de2b0931cee4ed9a5f2e420c">size</a> += GetSize();</div>
+<div class="line"><a name="l11328"></a><span class="lineno">11328</span>&#160;    inoutStats.<a class="code" href="struct_vma_pool_stats.html#ad7c54874724fce7b06aba526202d82a8">unusedSize</a> += m_SumFreeSize + unusableSize;</div>
+<div class="line"><a name="l11329"></a><span class="lineno">11329</span>&#160;    inoutStats.<a class="code" href="struct_vma_pool_stats.html#ad1924eb54fffa45e9e0e65670c8fe5eb">allocationCount</a> += m_AllocationCount;</div>
+<div class="line"><a name="l11330"></a><span class="lineno">11330</span>&#160;    inoutStats.<a class="code" href="struct_vma_pool_stats.html#ae4f3546ffa4d1e598b64d8e6134854f4">unusedRangeCount</a> += m_FreeCount;</div>
+<div class="line"><a name="l11331"></a><span class="lineno">11331</span>&#160;    inoutStats.<a class="code" href="struct_vma_pool_stats.html#ab4c8f52dd42ab01998f60f0b6acc722b">unusedRangeSizeMax</a> = VMA_MAX(inoutStats.<a class="code" href="struct_vma_pool_stats.html#ab4c8f52dd42ab01998f60f0b6acc722b">unusedRangeSizeMax</a>, GetUnusedRangeSizeMax());</div>
+<div class="line"><a name="l11332"></a><span class="lineno">11332</span>&#160; </div>
+<div class="line"><a name="l11333"></a><span class="lineno">11333</span>&#160;    <span class="keywordflow">if</span>(unusableSize &gt; 0)</div>
+<div class="line"><a name="l11334"></a><span class="lineno">11334</span>&#160;    {</div>
+<div class="line"><a name="l11335"></a><span class="lineno">11335</span>&#160;        ++inoutStats.<a class="code" href="struct_vma_pool_stats.html#ae4f3546ffa4d1e598b64d8e6134854f4">unusedRangeCount</a>;</div>
+<div class="line"><a name="l11336"></a><span class="lineno">11336</span>&#160;        <span class="comment">// Not updating inoutStats.unusedRangeSizeMax with unusableSize because this space is not available for allocations.</span></div>
+<div class="line"><a name="l11337"></a><span class="lineno">11337</span>&#160;    }</div>
+<div class="line"><a name="l11338"></a><span class="lineno">11338</span>&#160;}</div>
+<div class="line"><a name="l11339"></a><span class="lineno">11339</span>&#160; </div>
+<div class="line"><a name="l11340"></a><span class="lineno">11340</span>&#160;<span class="preprocessor">#if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l11341"></a><span class="lineno">11341</span>&#160; </div>
+<div class="line"><a name="l11342"></a><span class="lineno">11342</span>&#160;<span class="keywordtype">void</span> VmaBlockMetadata_Buddy::PrintDetailedMap(<span class="keyword">class</span> VmaJsonWriter&amp; json)<span class="keyword"> const</span></div>
+<div class="line"><a name="l11343"></a><span class="lineno">11343</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l11344"></a><span class="lineno">11344</span>&#160;    <span class="comment">// TODO optimize</span></div>
+<div class="line"><a name="l11345"></a><span class="lineno">11345</span>&#160;    <a class="code" href="struct_vma_stat_info.html">VmaStatInfo</a> stat;</div>
+<div class="line"><a name="l11346"></a><span class="lineno">11346</span>&#160;    CalcAllocationStatInfo(stat);</div>
+<div class="line"><a name="l11347"></a><span class="lineno">11347</span>&#160; </div>
+<div class="line"><a name="l11348"></a><span class="lineno">11348</span>&#160;    PrintDetailedMap_Begin(</div>
+<div class="line"><a name="l11349"></a><span class="lineno">11349</span>&#160;        json,</div>
+<div class="line"><a name="l11350"></a><span class="lineno">11350</span>&#160;        stat.<a class="code" href="struct_vma_stat_info.html#a1859d290aca2cd582d8dc25922092669">unusedBytes</a>,</div>
+<div class="line"><a name="l11351"></a><span class="lineno">11351</span>&#160;        stat.<a class="code" href="struct_vma_stat_info.html#a537741e4d5cdddc1c0ab95ec650afaff">allocationCount</a>,</div>
+<div class="line"><a name="l11352"></a><span class="lineno">11352</span>&#160;        stat.<a class="code" href="struct_vma_stat_info.html#ae06129c771bfebfd6468a7f4276502a9">unusedRangeCount</a>);</div>
+<div class="line"><a name="l11353"></a><span class="lineno">11353</span>&#160; </div>
+<div class="line"><a name="l11354"></a><span class="lineno">11354</span>&#160;    PrintDetailedMapNode(json, m_Root, LevelToNodeSize(0));</div>
+<div class="line"><a name="l11355"></a><span class="lineno">11355</span>&#160; </div>
+<div class="line"><a name="l11356"></a><span class="lineno">11356</span>&#160;    <span class="keyword">const</span> VkDeviceSize unusableSize = GetUnusableSize();</div>
+<div class="line"><a name="l11357"></a><span class="lineno">11357</span>&#160;    <span class="keywordflow">if</span>(unusableSize &gt; 0)</div>
+<div class="line"><a name="l11358"></a><span class="lineno">11358</span>&#160;    {</div>
+<div class="line"><a name="l11359"></a><span class="lineno">11359</span>&#160;        PrintDetailedMap_UnusedRange(json,</div>
+<div class="line"><a name="l11360"></a><span class="lineno">11360</span>&#160;            m_UsableSize, <span class="comment">// offset</span></div>
+<div class="line"><a name="l11361"></a><span class="lineno">11361</span>&#160;            unusableSize); <span class="comment">// size</span></div>
+<div class="line"><a name="l11362"></a><span class="lineno">11362</span>&#160;    }</div>
+<div class="line"><a name="l11363"></a><span class="lineno">11363</span>&#160; </div>
+<div class="line"><a name="l11364"></a><span class="lineno">11364</span>&#160;    PrintDetailedMap_End(json);</div>
+<div class="line"><a name="l11365"></a><span class="lineno">11365</span>&#160;}</div>
+<div class="line"><a name="l11366"></a><span class="lineno">11366</span>&#160; </div>
+<div class="line"><a name="l11367"></a><span class="lineno">11367</span>&#160;<span class="preprocessor">#endif // #if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l11368"></a><span class="lineno">11368</span>&#160; </div>
+<div class="line"><a name="l11369"></a><span class="lineno">11369</span>&#160;<span class="keywordtype">bool</span> VmaBlockMetadata_Buddy::CreateAllocationRequest(</div>
+<div class="line"><a name="l11370"></a><span class="lineno">11370</span>&#160;    uint32_t currentFrameIndex,</div>
+<div class="line"><a name="l11371"></a><span class="lineno">11371</span>&#160;    uint32_t frameInUseCount,</div>
+<div class="line"><a name="l11372"></a><span class="lineno">11372</span>&#160;    VkDeviceSize bufferImageGranularity,</div>
+<div class="line"><a name="l11373"></a><span class="lineno">11373</span>&#160;    VkDeviceSize allocSize,</div>
+<div class="line"><a name="l11374"></a><span class="lineno">11374</span>&#160;    VkDeviceSize allocAlignment,</div>
+<div class="line"><a name="l11375"></a><span class="lineno">11375</span>&#160;    <span class="keywordtype">bool</span> upperAddress,</div>
+<div class="line"><a name="l11376"></a><span class="lineno">11376</span>&#160;    VmaSuballocationType allocType,</div>
+<div class="line"><a name="l11377"></a><span class="lineno">11377</span>&#160;    <span class="keywordtype">bool</span> canMakeOtherLost,</div>
+<div class="line"><a name="l11378"></a><span class="lineno">11378</span>&#160;    uint32_t strategy,</div>
+<div class="line"><a name="l11379"></a><span class="lineno">11379</span>&#160;    VmaAllocationRequest* pAllocationRequest)</div>
+<div class="line"><a name="l11380"></a><span class="lineno">11380</span>&#160;{</div>
+<div class="line"><a name="l11381"></a><span class="lineno">11381</span>&#160;    VMA_ASSERT(!upperAddress &amp;&amp; <span class="stringliteral">&quot;VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT can be used only with linear algorithm.&quot;</span>);</div>
+<div class="line"><a name="l11382"></a><span class="lineno">11382</span>&#160; </div>
+<div class="line"><a name="l11383"></a><span class="lineno">11383</span>&#160;    <span class="comment">// Simple way to respect bufferImageGranularity. May be optimized some day.</span></div>
+<div class="line"><a name="l11384"></a><span class="lineno">11384</span>&#160;    <span class="comment">// Whenever it might be an OPTIMAL image...</span></div>
+<div class="line"><a name="l11385"></a><span class="lineno">11385</span>&#160;    <span class="keywordflow">if</span>(allocType == VMA_SUBALLOCATION_TYPE_UNKNOWN ||</div>
+<div class="line"><a name="l11386"></a><span class="lineno">11386</span>&#160;        allocType == VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN ||</div>
+<div class="line"><a name="l11387"></a><span class="lineno">11387</span>&#160;        allocType == VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL)</div>
+<div class="line"><a name="l11388"></a><span class="lineno">11388</span>&#160;    {</div>
+<div class="line"><a name="l11389"></a><span class="lineno">11389</span>&#160;        allocAlignment = VMA_MAX(allocAlignment, bufferImageGranularity);</div>
+<div class="line"><a name="l11390"></a><span class="lineno">11390</span>&#160;        allocSize = VMA_MAX(allocSize, bufferImageGranularity);</div>
+<div class="line"><a name="l11391"></a><span class="lineno">11391</span>&#160;    }</div>
+<div class="line"><a name="l11392"></a><span class="lineno">11392</span>&#160; </div>
+<div class="line"><a name="l11393"></a><span class="lineno">11393</span>&#160;    <span class="keywordflow">if</span>(allocSize &gt; m_UsableSize)</div>
+<div class="line"><a name="l11394"></a><span class="lineno">11394</span>&#160;    {</div>
+<div class="line"><a name="l11395"></a><span class="lineno">11395</span>&#160;        <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l11396"></a><span class="lineno">11396</span>&#160;    }</div>
+<div class="line"><a name="l11397"></a><span class="lineno">11397</span>&#160; </div>
+<div class="line"><a name="l11398"></a><span class="lineno">11398</span>&#160;    <span class="keyword">const</span> uint32_t targetLevel = AllocSizeToLevel(allocSize);</div>
+<div class="line"><a name="l11399"></a><span class="lineno">11399</span>&#160;    <span class="keywordflow">for</span>(uint32_t level = targetLevel + 1; level--; )</div>
+<div class="line"><a name="l11400"></a><span class="lineno">11400</span>&#160;    {</div>
+<div class="line"><a name="l11401"></a><span class="lineno">11401</span>&#160;        <span class="keywordflow">for</span>(Node* freeNode = m_FreeList[level].front;</div>
+<div class="line"><a name="l11402"></a><span class="lineno">11402</span>&#160;            freeNode != VMA_NULL;</div>
+<div class="line"><a name="l11403"></a><span class="lineno">11403</span>&#160;            freeNode = freeNode-&gt;free.next)</div>
+<div class="line"><a name="l11404"></a><span class="lineno">11404</span>&#160;        {</div>
+<div class="line"><a name="l11405"></a><span class="lineno">11405</span>&#160;            <span class="keywordflow">if</span>(freeNode-&gt;offset % allocAlignment == 0)</div>
+<div class="line"><a name="l11406"></a><span class="lineno">11406</span>&#160;            {</div>
+<div class="line"><a name="l11407"></a><span class="lineno">11407</span>&#160;                pAllocationRequest-&gt;type = VmaAllocationRequestType::Normal;</div>
+<div class="line"><a name="l11408"></a><span class="lineno">11408</span>&#160;                pAllocationRequest-&gt;offset = freeNode-&gt;offset;</div>
+<div class="line"><a name="l11409"></a><span class="lineno">11409</span>&#160;                pAllocationRequest-&gt;sumFreeSize = LevelToNodeSize(level);</div>
+<div class="line"><a name="l11410"></a><span class="lineno">11410</span>&#160;                pAllocationRequest-&gt;sumItemSize = 0;</div>
+<div class="line"><a name="l11411"></a><span class="lineno">11411</span>&#160;                pAllocationRequest-&gt;itemsToMakeLostCount = 0;</div>
+<div class="line"><a name="l11412"></a><span class="lineno">11412</span>&#160;                pAllocationRequest-&gt;customData = (<span class="keywordtype">void</span>*)(uintptr_t)level;</div>
+<div class="line"><a name="l11413"></a><span class="lineno">11413</span>&#160;                <span class="keywordflow">return</span> <span class="keyword">true</span>;</div>
+<div class="line"><a name="l11414"></a><span class="lineno">11414</span>&#160;            }</div>
+<div class="line"><a name="l11415"></a><span class="lineno">11415</span>&#160;        }</div>
+<div class="line"><a name="l11416"></a><span class="lineno">11416</span>&#160;    }</div>
+<div class="line"><a name="l11417"></a><span class="lineno">11417</span>&#160; </div>
+<div class="line"><a name="l11418"></a><span class="lineno">11418</span>&#160;    <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l11419"></a><span class="lineno">11419</span>&#160;}</div>
+<div class="line"><a name="l11420"></a><span class="lineno">11420</span>&#160; </div>
+<div class="line"><a name="l11421"></a><span class="lineno">11421</span>&#160;<span class="keywordtype">bool</span> VmaBlockMetadata_Buddy::MakeRequestedAllocationsLost(</div>
+<div class="line"><a name="l11422"></a><span class="lineno">11422</span>&#160;    uint32_t currentFrameIndex,</div>
+<div class="line"><a name="l11423"></a><span class="lineno">11423</span>&#160;    uint32_t frameInUseCount,</div>
+<div class="line"><a name="l11424"></a><span class="lineno">11424</span>&#160;    VmaAllocationRequest* pAllocationRequest)</div>
+<div class="line"><a name="l11425"></a><span class="lineno">11425</span>&#160;{</div>
+<div class="line"><a name="l11426"></a><span class="lineno">11426</span>&#160;    <span class="comment">/*</span></div>
+<div class="line"><a name="l11427"></a><span class="lineno">11427</span>&#160;<span class="comment">    Lost allocations are not supported in buddy allocator at the moment.</span></div>
+<div class="line"><a name="l11428"></a><span class="lineno">11428</span>&#160;<span class="comment">    Support might be added in the future.</span></div>
+<div class="line"><a name="l11429"></a><span class="lineno">11429</span>&#160;<span class="comment">    */</span></div>
+<div class="line"><a name="l11430"></a><span class="lineno">11430</span>&#160;    <span class="keywordflow">return</span> pAllocationRequest-&gt;itemsToMakeLostCount == 0;</div>
+<div class="line"><a name="l11431"></a><span class="lineno">11431</span>&#160;}</div>
+<div class="line"><a name="l11432"></a><span class="lineno">11432</span>&#160; </div>
+<div class="line"><a name="l11433"></a><span class="lineno">11433</span>&#160;uint32_t VmaBlockMetadata_Buddy::MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount)</div>
+<div class="line"><a name="l11434"></a><span class="lineno">11434</span>&#160;{</div>
+<div class="line"><a name="l11435"></a><span class="lineno">11435</span>&#160;    <span class="comment">/*</span></div>
+<div class="line"><a name="l11436"></a><span class="lineno">11436</span>&#160;<span class="comment">    Lost allocations are not supported in buddy allocator at the moment.</span></div>
+<div class="line"><a name="l11437"></a><span class="lineno">11437</span>&#160;<span class="comment">    Support might be added in the future.</span></div>
+<div class="line"><a name="l11438"></a><span class="lineno">11438</span>&#160;<span class="comment">    */</span></div>
+<div class="line"><a name="l11439"></a><span class="lineno">11439</span>&#160;    <span class="keywordflow">return</span> 0;</div>
+<div class="line"><a name="l11440"></a><span class="lineno">11440</span>&#160;}</div>
+<div class="line"><a name="l11441"></a><span class="lineno">11441</span>&#160; </div>
+<div class="line"><a name="l11442"></a><span class="lineno">11442</span>&#160;<span class="keywordtype">void</span> VmaBlockMetadata_Buddy::Alloc(</div>
+<div class="line"><a name="l11443"></a><span class="lineno">11443</span>&#160;    <span class="keyword">const</span> VmaAllocationRequest&amp; request,</div>
+<div class="line"><a name="l11444"></a><span class="lineno">11444</span>&#160;    VmaSuballocationType type,</div>
+<div class="line"><a name="l11445"></a><span class="lineno">11445</span>&#160;    VkDeviceSize allocSize,</div>
+<div class="line"><a name="l11446"></a><span class="lineno">11446</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAllocation)</div>
+<div class="line"><a name="l11447"></a><span class="lineno">11447</span>&#160;{</div>
+<div class="line"><a name="l11448"></a><span class="lineno">11448</span>&#160;    VMA_ASSERT(request.type == VmaAllocationRequestType::Normal);</div>
+<div class="line"><a name="l11449"></a><span class="lineno">11449</span>&#160; </div>
+<div class="line"><a name="l11450"></a><span class="lineno">11450</span>&#160;    <span class="keyword">const</span> uint32_t targetLevel = AllocSizeToLevel(allocSize);</div>
+<div class="line"><a name="l11451"></a><span class="lineno">11451</span>&#160;    uint32_t currLevel = (uint32_t)(uintptr_t)request.customData;</div>
+<div class="line"><a name="l11452"></a><span class="lineno">11452</span>&#160;    </div>
+<div class="line"><a name="l11453"></a><span class="lineno">11453</span>&#160;    Node* currNode = m_FreeList[currLevel].front;</div>
+<div class="line"><a name="l11454"></a><span class="lineno">11454</span>&#160;    VMA_ASSERT(currNode != VMA_NULL &amp;&amp; currNode-&gt;type == Node::TYPE_FREE);</div>
+<div class="line"><a name="l11455"></a><span class="lineno">11455</span>&#160;    <span class="keywordflow">while</span>(currNode-&gt;offset != request.offset)</div>
+<div class="line"><a name="l11456"></a><span class="lineno">11456</span>&#160;    {</div>
+<div class="line"><a name="l11457"></a><span class="lineno">11457</span>&#160;        currNode = currNode-&gt;free.next;</div>
+<div class="line"><a name="l11458"></a><span class="lineno">11458</span>&#160;        VMA_ASSERT(currNode != VMA_NULL &amp;&amp; currNode-&gt;type == Node::TYPE_FREE);</div>
+<div class="line"><a name="l11459"></a><span class="lineno">11459</span>&#160;    }</div>
+<div class="line"><a name="l11460"></a><span class="lineno">11460</span>&#160;    </div>
+<div class="line"><a name="l11461"></a><span class="lineno">11461</span>&#160;    <span class="comment">// Go down, splitting free nodes.</span></div>
+<div class="line"><a name="l11462"></a><span class="lineno">11462</span>&#160;    <span class="keywordflow">while</span>(currLevel &lt; targetLevel)</div>
+<div class="line"><a name="l11463"></a><span class="lineno">11463</span>&#160;    {</div>
+<div class="line"><a name="l11464"></a><span class="lineno">11464</span>&#160;        <span class="comment">// currNode is already first free node at currLevel.</span></div>
+<div class="line"><a name="l11465"></a><span class="lineno">11465</span>&#160;        <span class="comment">// Remove it from list of free nodes at this currLevel.</span></div>
+<div class="line"><a name="l11466"></a><span class="lineno">11466</span>&#160;        RemoveFromFreeList(currLevel, currNode);</div>
+<div class="line"><a name="l11467"></a><span class="lineno">11467</span>&#160;         </div>
+<div class="line"><a name="l11468"></a><span class="lineno">11468</span>&#160;        <span class="keyword">const</span> uint32_t childrenLevel = currLevel + 1;</div>
+<div class="line"><a name="l11469"></a><span class="lineno">11469</span>&#160; </div>
+<div class="line"><a name="l11470"></a><span class="lineno">11470</span>&#160;        <span class="comment">// Create two free sub-nodes.</span></div>
+<div class="line"><a name="l11471"></a><span class="lineno">11471</span>&#160;        Node* leftChild = vma_new(GetAllocationCallbacks(), Node)();</div>
+<div class="line"><a name="l11472"></a><span class="lineno">11472</span>&#160;        Node* rightChild = vma_new(GetAllocationCallbacks(), Node)();</div>
+<div class="line"><a name="l11473"></a><span class="lineno">11473</span>&#160; </div>
+<div class="line"><a name="l11474"></a><span class="lineno">11474</span>&#160;        leftChild-&gt;offset = currNode-&gt;offset;</div>
+<div class="line"><a name="l11475"></a><span class="lineno">11475</span>&#160;        leftChild-&gt;type = Node::TYPE_FREE;</div>
+<div class="line"><a name="l11476"></a><span class="lineno">11476</span>&#160;        leftChild-&gt;parent = currNode;</div>
+<div class="line"><a name="l11477"></a><span class="lineno">11477</span>&#160;        leftChild-&gt;buddy = rightChild;</div>
+<div class="line"><a name="l11478"></a><span class="lineno">11478</span>&#160; </div>
+<div class="line"><a name="l11479"></a><span class="lineno">11479</span>&#160;        rightChild-&gt;offset = currNode-&gt;offset + LevelToNodeSize(childrenLevel);</div>
+<div class="line"><a name="l11480"></a><span class="lineno">11480</span>&#160;        rightChild-&gt;type = Node::TYPE_FREE;</div>
+<div class="line"><a name="l11481"></a><span class="lineno">11481</span>&#160;        rightChild-&gt;parent = currNode;</div>
+<div class="line"><a name="l11482"></a><span class="lineno">11482</span>&#160;        rightChild-&gt;buddy = leftChild;</div>
+<div class="line"><a name="l11483"></a><span class="lineno">11483</span>&#160; </div>
+<div class="line"><a name="l11484"></a><span class="lineno">11484</span>&#160;        <span class="comment">// Convert current currNode to split type.</span></div>
+<div class="line"><a name="l11485"></a><span class="lineno">11485</span>&#160;        currNode-&gt;type = Node::TYPE_SPLIT;</div>
+<div class="line"><a name="l11486"></a><span class="lineno">11486</span>&#160;        currNode-&gt;split.leftChild = leftChild;</div>
+<div class="line"><a name="l11487"></a><span class="lineno">11487</span>&#160; </div>
+<div class="line"><a name="l11488"></a><span class="lineno">11488</span>&#160;        <span class="comment">// Add child nodes to free list. Order is important!</span></div>
+<div class="line"><a name="l11489"></a><span class="lineno">11489</span>&#160;        AddToFreeListFront(childrenLevel, rightChild);</div>
+<div class="line"><a name="l11490"></a><span class="lineno">11490</span>&#160;        AddToFreeListFront(childrenLevel, leftChild);</div>
+<div class="line"><a name="l11491"></a><span class="lineno">11491</span>&#160; </div>
+<div class="line"><a name="l11492"></a><span class="lineno">11492</span>&#160;        ++m_FreeCount;</div>
+<div class="line"><a name="l11493"></a><span class="lineno">11493</span>&#160;        <span class="comment">//m_SumFreeSize -= LevelToNodeSize(currLevel) % 2; // Useful only when level node sizes can be non power of 2.</span></div>
+<div class="line"><a name="l11494"></a><span class="lineno">11494</span>&#160;        ++currLevel;</div>
+<div class="line"><a name="l11495"></a><span class="lineno">11495</span>&#160;        currNode = m_FreeList[currLevel].front;</div>
+<div class="line"><a name="l11496"></a><span class="lineno">11496</span>&#160; </div>
+<div class="line"><a name="l11497"></a><span class="lineno">11497</span>&#160;        <span class="comment">/*</span></div>
+<div class="line"><a name="l11498"></a><span class="lineno">11498</span>&#160;<span class="comment">        We can be sure that currNode, as left child of node previously split,</span></div>
+<div class="line"><a name="l11499"></a><span class="lineno">11499</span>&#160;<span class="comment">        also fullfills the alignment requirement.</span></div>
+<div class="line"><a name="l11500"></a><span class="lineno">11500</span>&#160;<span class="comment">        */</span></div>
+<div class="line"><a name="l11501"></a><span class="lineno">11501</span>&#160;    }</div>
+<div class="line"><a name="l11502"></a><span class="lineno">11502</span>&#160; </div>
+<div class="line"><a name="l11503"></a><span class="lineno">11503</span>&#160;    <span class="comment">// Remove from free list.</span></div>
+<div class="line"><a name="l11504"></a><span class="lineno">11504</span>&#160;    VMA_ASSERT(currLevel == targetLevel &amp;&amp;</div>
+<div class="line"><a name="l11505"></a><span class="lineno">11505</span>&#160;        currNode != VMA_NULL &amp;&amp;</div>
+<div class="line"><a name="l11506"></a><span class="lineno">11506</span>&#160;        currNode-&gt;type == Node::TYPE_FREE);</div>
+<div class="line"><a name="l11507"></a><span class="lineno">11507</span>&#160;    RemoveFromFreeList(currLevel, currNode);</div>
+<div class="line"><a name="l11508"></a><span class="lineno">11508</span>&#160; </div>
+<div class="line"><a name="l11509"></a><span class="lineno">11509</span>&#160;    <span class="comment">// Convert to allocation node.</span></div>
+<div class="line"><a name="l11510"></a><span class="lineno">11510</span>&#160;    currNode-&gt;type = Node::TYPE_ALLOCATION;</div>
+<div class="line"><a name="l11511"></a><span class="lineno">11511</span>&#160;    currNode-&gt;allocation.alloc = hAllocation;</div>
+<div class="line"><a name="l11512"></a><span class="lineno">11512</span>&#160; </div>
+<div class="line"><a name="l11513"></a><span class="lineno">11513</span>&#160;    ++m_AllocationCount;</div>
+<div class="line"><a name="l11514"></a><span class="lineno">11514</span>&#160;    --m_FreeCount;</div>
+<div class="line"><a name="l11515"></a><span class="lineno">11515</span>&#160;    m_SumFreeSize -= allocSize;</div>
+<div class="line"><a name="l11516"></a><span class="lineno">11516</span>&#160;}</div>
+<div class="line"><a name="l11517"></a><span class="lineno">11517</span>&#160; </div>
+<div class="line"><a name="l11518"></a><span class="lineno">11518</span>&#160;<span class="keywordtype">void</span> VmaBlockMetadata_Buddy::DeleteNode(Node* node)</div>
+<div class="line"><a name="l11519"></a><span class="lineno">11519</span>&#160;{</div>
+<div class="line"><a name="l11520"></a><span class="lineno">11520</span>&#160;    <span class="keywordflow">if</span>(node-&gt;type == Node::TYPE_SPLIT)</div>
+<div class="line"><a name="l11521"></a><span class="lineno">11521</span>&#160;    {</div>
+<div class="line"><a name="l11522"></a><span class="lineno">11522</span>&#160;        DeleteNode(node-&gt;split.leftChild-&gt;buddy);</div>
+<div class="line"><a name="l11523"></a><span class="lineno">11523</span>&#160;        DeleteNode(node-&gt;split.leftChild);</div>
+<div class="line"><a name="l11524"></a><span class="lineno">11524</span>&#160;    }</div>
+<div class="line"><a name="l11525"></a><span class="lineno">11525</span>&#160; </div>
+<div class="line"><a name="l11526"></a><span class="lineno">11526</span>&#160;    vma_delete(GetAllocationCallbacks(), node);</div>
+<div class="line"><a name="l11527"></a><span class="lineno">11527</span>&#160;}</div>
+<div class="line"><a name="l11528"></a><span class="lineno">11528</span>&#160; </div>
+<div class="line"><a name="l11529"></a><span class="lineno">11529</span>&#160;<span class="keywordtype">bool</span> VmaBlockMetadata_Buddy::ValidateNode(ValidationContext&amp; ctx, <span class="keyword">const</span> Node* parent, <span class="keyword">const</span> Node* curr, uint32_t level, VkDeviceSize levelNodeSize)<span class="keyword"> const</span></div>
+<div class="line"><a name="l11530"></a><span class="lineno">11530</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l11531"></a><span class="lineno">11531</span>&#160;    VMA_VALIDATE(level &lt; m_LevelCount);</div>
+<div class="line"><a name="l11532"></a><span class="lineno">11532</span>&#160;    VMA_VALIDATE(curr-&gt;parent == parent);</div>
+<div class="line"><a name="l11533"></a><span class="lineno">11533</span>&#160;    VMA_VALIDATE((curr-&gt;buddy == VMA_NULL) == (parent == VMA_NULL));</div>
+<div class="line"><a name="l11534"></a><span class="lineno">11534</span>&#160;    VMA_VALIDATE(curr-&gt;buddy == VMA_NULL || curr-&gt;buddy-&gt;buddy == curr);</div>
+<div class="line"><a name="l11535"></a><span class="lineno">11535</span>&#160;    <span class="keywordflow">switch</span>(curr-&gt;type)</div>
+<div class="line"><a name="l11536"></a><span class="lineno">11536</span>&#160;    {</div>
+<div class="line"><a name="l11537"></a><span class="lineno">11537</span>&#160;    <span class="keywordflow">case</span> Node::TYPE_FREE:</div>
+<div class="line"><a name="l11538"></a><span class="lineno">11538</span>&#160;        <span class="comment">// curr-&gt;free.prev, next are validated separately.</span></div>
+<div class="line"><a name="l11539"></a><span class="lineno">11539</span>&#160;        ctx.calculatedSumFreeSize += levelNodeSize;</div>
+<div class="line"><a name="l11540"></a><span class="lineno">11540</span>&#160;        ++ctx.calculatedFreeCount;</div>
+<div class="line"><a name="l11541"></a><span class="lineno">11541</span>&#160;        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l11542"></a><span class="lineno">11542</span>&#160;    <span class="keywordflow">case</span> Node::TYPE_ALLOCATION:</div>
+<div class="line"><a name="l11543"></a><span class="lineno">11543</span>&#160;        ++ctx.calculatedAllocationCount;</div>
+<div class="line"><a name="l11544"></a><span class="lineno">11544</span>&#160;        ctx.calculatedSumFreeSize += levelNodeSize - curr-&gt;allocation.alloc-&gt;GetSize();</div>
+<div class="line"><a name="l11545"></a><span class="lineno">11545</span>&#160;        VMA_VALIDATE(curr-&gt;allocation.alloc != VK_NULL_HANDLE);</div>
+<div class="line"><a name="l11546"></a><span class="lineno">11546</span>&#160;        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l11547"></a><span class="lineno">11547</span>&#160;    <span class="keywordflow">case</span> Node::TYPE_SPLIT:</div>
+<div class="line"><a name="l11548"></a><span class="lineno">11548</span>&#160;        {</div>
+<div class="line"><a name="l11549"></a><span class="lineno">11549</span>&#160;            <span class="keyword">const</span> uint32_t childrenLevel = level + 1;</div>
+<div class="line"><a name="l11550"></a><span class="lineno">11550</span>&#160;            <span class="keyword">const</span> VkDeviceSize childrenLevelNodeSize = levelNodeSize / 2;</div>
+<div class="line"><a name="l11551"></a><span class="lineno">11551</span>&#160;            <span class="keyword">const</span> Node* <span class="keyword">const</span> leftChild = curr-&gt;split.leftChild;</div>
+<div class="line"><a name="l11552"></a><span class="lineno">11552</span>&#160;            VMA_VALIDATE(leftChild != VMA_NULL);</div>
+<div class="line"><a name="l11553"></a><span class="lineno">11553</span>&#160;            VMA_VALIDATE(leftChild-&gt;offset == curr-&gt;offset);</div>
+<div class="line"><a name="l11554"></a><span class="lineno">11554</span>&#160;            <span class="keywordflow">if</span>(!ValidateNode(ctx, curr, leftChild, childrenLevel, childrenLevelNodeSize))</div>
+<div class="line"><a name="l11555"></a><span class="lineno">11555</span>&#160;            {</div>
+<div class="line"><a name="l11556"></a><span class="lineno">11556</span>&#160;                VMA_VALIDATE(<span class="keyword">false</span> &amp;&amp; <span class="stringliteral">&quot;ValidateNode for left child failed.&quot;</span>);</div>
+<div class="line"><a name="l11557"></a><span class="lineno">11557</span>&#160;            }</div>
+<div class="line"><a name="l11558"></a><span class="lineno">11558</span>&#160;            <span class="keyword">const</span> Node* <span class="keyword">const</span> rightChild = leftChild-&gt;buddy;</div>
+<div class="line"><a name="l11559"></a><span class="lineno">11559</span>&#160;            VMA_VALIDATE(rightChild-&gt;offset == curr-&gt;offset + childrenLevelNodeSize);</div>
+<div class="line"><a name="l11560"></a><span class="lineno">11560</span>&#160;            <span class="keywordflow">if</span>(!ValidateNode(ctx, curr, rightChild, childrenLevel, childrenLevelNodeSize))</div>
+<div class="line"><a name="l11561"></a><span class="lineno">11561</span>&#160;            {</div>
+<div class="line"><a name="l11562"></a><span class="lineno">11562</span>&#160;                VMA_VALIDATE(<span class="keyword">false</span> &amp;&amp; <span class="stringliteral">&quot;ValidateNode for right child failed.&quot;</span>);</div>
+<div class="line"><a name="l11563"></a><span class="lineno">11563</span>&#160;            }</div>
+<div class="line"><a name="l11564"></a><span class="lineno">11564</span>&#160;        }</div>
+<div class="line"><a name="l11565"></a><span class="lineno">11565</span>&#160;        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l11566"></a><span class="lineno">11566</span>&#160;    <span class="keywordflow">default</span>:</div>
+<div class="line"><a name="l11567"></a><span class="lineno">11567</span>&#160;        <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l11568"></a><span class="lineno">11568</span>&#160;    }</div>
+<div class="line"><a name="l11569"></a><span class="lineno">11569</span>&#160; </div>
+<div class="line"><a name="l11570"></a><span class="lineno">11570</span>&#160;    <span class="keywordflow">return</span> <span class="keyword">true</span>;</div>
+<div class="line"><a name="l11571"></a><span class="lineno">11571</span>&#160;}</div>
+<div class="line"><a name="l11572"></a><span class="lineno">11572</span>&#160; </div>
+<div class="line"><a name="l11573"></a><span class="lineno">11573</span>&#160;uint32_t VmaBlockMetadata_Buddy::AllocSizeToLevel(VkDeviceSize allocSize)<span class="keyword"> const</span></div>
+<div class="line"><a name="l11574"></a><span class="lineno">11574</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l11575"></a><span class="lineno">11575</span>&#160;    <span class="comment">// I know this could be optimized somehow e.g. by using std::log2p1 from C++20.</span></div>
+<div class="line"><a name="l11576"></a><span class="lineno">11576</span>&#160;    uint32_t level = 0;</div>
+<div class="line"><a name="l11577"></a><span class="lineno">11577</span>&#160;    VkDeviceSize currLevelNodeSize = m_UsableSize;</div>
+<div class="line"><a name="l11578"></a><span class="lineno">11578</span>&#160;    VkDeviceSize nextLevelNodeSize = currLevelNodeSize &gt;&gt; 1;</div>
+<div class="line"><a name="l11579"></a><span class="lineno">11579</span>&#160;    <span class="keywordflow">while</span>(allocSize &lt;= nextLevelNodeSize &amp;&amp; level + 1 &lt; m_LevelCount)</div>
+<div class="line"><a name="l11580"></a><span class="lineno">11580</span>&#160;    {</div>
+<div class="line"><a name="l11581"></a><span class="lineno">11581</span>&#160;        ++level;</div>
+<div class="line"><a name="l11582"></a><span class="lineno">11582</span>&#160;        currLevelNodeSize = nextLevelNodeSize;</div>
+<div class="line"><a name="l11583"></a><span class="lineno">11583</span>&#160;        nextLevelNodeSize = currLevelNodeSize &gt;&gt; 1;</div>
+<div class="line"><a name="l11584"></a><span class="lineno">11584</span>&#160;    }</div>
+<div class="line"><a name="l11585"></a><span class="lineno">11585</span>&#160;    <span class="keywordflow">return</span> level;</div>
+<div class="line"><a name="l11586"></a><span class="lineno">11586</span>&#160;}</div>
+<div class="line"><a name="l11587"></a><span class="lineno">11587</span>&#160; </div>
+<div class="line"><a name="l11588"></a><span class="lineno">11588</span>&#160;<span class="keywordtype">void</span> VmaBlockMetadata_Buddy::FreeAtOffset(<a class="code" href="struct_vma_allocation.html">VmaAllocation</a> alloc, VkDeviceSize offset)</div>
+<div class="line"><a name="l11589"></a><span class="lineno">11589</span>&#160;{</div>
+<div class="line"><a name="l11590"></a><span class="lineno">11590</span>&#160;    <span class="comment">// Find node and level.</span></div>
+<div class="line"><a name="l11591"></a><span class="lineno">11591</span>&#160;    Node* node = m_Root;</div>
+<div class="line"><a name="l11592"></a><span class="lineno">11592</span>&#160;    VkDeviceSize nodeOffset = 0;</div>
+<div class="line"><a name="l11593"></a><span class="lineno">11593</span>&#160;    uint32_t level = 0;</div>
+<div class="line"><a name="l11594"></a><span class="lineno">11594</span>&#160;    VkDeviceSize levelNodeSize = LevelToNodeSize(0);</div>
+<div class="line"><a name="l11595"></a><span class="lineno">11595</span>&#160;    <span class="keywordflow">while</span>(node-&gt;type == Node::TYPE_SPLIT)</div>
+<div class="line"><a name="l11596"></a><span class="lineno">11596</span>&#160;    {</div>
+<div class="line"><a name="l11597"></a><span class="lineno">11597</span>&#160;        <span class="keyword">const</span> VkDeviceSize nextLevelSize = levelNodeSize &gt;&gt; 1;</div>
+<div class="line"><a name="l11598"></a><span class="lineno">11598</span>&#160;        <span class="keywordflow">if</span>(offset &lt; nodeOffset + nextLevelSize)</div>
+<div class="line"><a name="l11599"></a><span class="lineno">11599</span>&#160;        {</div>
+<div class="line"><a name="l11600"></a><span class="lineno">11600</span>&#160;            node = node-&gt;split.leftChild;</div>
+<div class="line"><a name="l11601"></a><span class="lineno">11601</span>&#160;        }</div>
+<div class="line"><a name="l11602"></a><span class="lineno">11602</span>&#160;        <span class="keywordflow">else</span></div>
+<div class="line"><a name="l11603"></a><span class="lineno">11603</span>&#160;        {</div>
+<div class="line"><a name="l11604"></a><span class="lineno">11604</span>&#160;            node = node-&gt;split.leftChild-&gt;buddy;</div>
+<div class="line"><a name="l11605"></a><span class="lineno">11605</span>&#160;            nodeOffset += nextLevelSize;</div>
+<div class="line"><a name="l11606"></a><span class="lineno">11606</span>&#160;        }</div>
+<div class="line"><a name="l11607"></a><span class="lineno">11607</span>&#160;        ++level;</div>
+<div class="line"><a name="l11608"></a><span class="lineno">11608</span>&#160;        levelNodeSize = nextLevelSize;</div>
+<div class="line"><a name="l11609"></a><span class="lineno">11609</span>&#160;    }</div>
+<div class="line"><a name="l11610"></a><span class="lineno">11610</span>&#160; </div>
+<div class="line"><a name="l11611"></a><span class="lineno">11611</span>&#160;    VMA_ASSERT(node != VMA_NULL &amp;&amp; node-&gt;type == Node::TYPE_ALLOCATION);</div>
+<div class="line"><a name="l11612"></a><span class="lineno">11612</span>&#160;    VMA_ASSERT(alloc == VK_NULL_HANDLE || node-&gt;allocation.alloc == alloc);</div>
+<div class="line"><a name="l11613"></a><span class="lineno">11613</span>&#160; </div>
+<div class="line"><a name="l11614"></a><span class="lineno">11614</span>&#160;    ++m_FreeCount;</div>
+<div class="line"><a name="l11615"></a><span class="lineno">11615</span>&#160;    --m_AllocationCount;</div>
+<div class="line"><a name="l11616"></a><span class="lineno">11616</span>&#160;    m_SumFreeSize += alloc-&gt;GetSize();</div>
+<div class="line"><a name="l11617"></a><span class="lineno">11617</span>&#160; </div>
+<div class="line"><a name="l11618"></a><span class="lineno">11618</span>&#160;    node-&gt;type = Node::TYPE_FREE;</div>
+<div class="line"><a name="l11619"></a><span class="lineno">11619</span>&#160; </div>
+<div class="line"><a name="l11620"></a><span class="lineno">11620</span>&#160;    <span class="comment">// Join free nodes if possible.</span></div>
+<div class="line"><a name="l11621"></a><span class="lineno">11621</span>&#160;    <span class="keywordflow">while</span>(level &gt; 0 &amp;&amp; node-&gt;buddy-&gt;type == Node::TYPE_FREE)</div>
+<div class="line"><a name="l11622"></a><span class="lineno">11622</span>&#160;    {</div>
+<div class="line"><a name="l11623"></a><span class="lineno">11623</span>&#160;        RemoveFromFreeList(level, node-&gt;buddy);</div>
+<div class="line"><a name="l11624"></a><span class="lineno">11624</span>&#160;        Node* <span class="keyword">const</span> parent = node-&gt;parent;</div>
+<div class="line"><a name="l11625"></a><span class="lineno">11625</span>&#160; </div>
+<div class="line"><a name="l11626"></a><span class="lineno">11626</span>&#160;        vma_delete(GetAllocationCallbacks(), node-&gt;buddy);</div>
+<div class="line"><a name="l11627"></a><span class="lineno">11627</span>&#160;        vma_delete(GetAllocationCallbacks(), node);</div>
+<div class="line"><a name="l11628"></a><span class="lineno">11628</span>&#160;        parent-&gt;type = Node::TYPE_FREE;</div>
+<div class="line"><a name="l11629"></a><span class="lineno">11629</span>&#160;        </div>
+<div class="line"><a name="l11630"></a><span class="lineno">11630</span>&#160;        node = parent;</div>
+<div class="line"><a name="l11631"></a><span class="lineno">11631</span>&#160;        --level;</div>
+<div class="line"><a name="l11632"></a><span class="lineno">11632</span>&#160;        <span class="comment">//m_SumFreeSize += LevelToNodeSize(level) % 2; // Useful only when level node sizes can be non power of 2.</span></div>
+<div class="line"><a name="l11633"></a><span class="lineno">11633</span>&#160;        --m_FreeCount;</div>
+<div class="line"><a name="l11634"></a><span class="lineno">11634</span>&#160;    }</div>
+<div class="line"><a name="l11635"></a><span class="lineno">11635</span>&#160; </div>
+<div class="line"><a name="l11636"></a><span class="lineno">11636</span>&#160;    AddToFreeListFront(level, node);</div>
+<div class="line"><a name="l11637"></a><span class="lineno">11637</span>&#160;}</div>
+<div class="line"><a name="l11638"></a><span class="lineno">11638</span>&#160; </div>
+<div class="line"><a name="l11639"></a><span class="lineno">11639</span>&#160;<span class="keywordtype">void</span> VmaBlockMetadata_Buddy::CalcAllocationStatInfoNode(<a class="code" href="struct_vma_stat_info.html">VmaStatInfo</a>&amp; outInfo, <span class="keyword">const</span> Node* node, VkDeviceSize levelNodeSize)<span class="keyword"> const</span></div>
+<div class="line"><a name="l11640"></a><span class="lineno">11640</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l11641"></a><span class="lineno">11641</span>&#160;    <span class="keywordflow">switch</span>(node-&gt;type)</div>
+<div class="line"><a name="l11642"></a><span class="lineno">11642</span>&#160;    {</div>
+<div class="line"><a name="l11643"></a><span class="lineno">11643</span>&#160;    <span class="keywordflow">case</span> Node::TYPE_FREE:</div>
+<div class="line"><a name="l11644"></a><span class="lineno">11644</span>&#160;        ++outInfo.<a class="code" href="struct_vma_stat_info.html#ae06129c771bfebfd6468a7f4276502a9">unusedRangeCount</a>;</div>
+<div class="line"><a name="l11645"></a><span class="lineno">11645</span>&#160;        outInfo.<a class="code" href="struct_vma_stat_info.html#a1859d290aca2cd582d8dc25922092669">unusedBytes</a> += levelNodeSize;</div>
+<div class="line"><a name="l11646"></a><span class="lineno">11646</span>&#160;        outInfo.<a class="code" href="struct_vma_stat_info.html#a5ba1a2476c4d39b10f7e2f7ebbb72ac4">unusedRangeSizeMax</a> = VMA_MAX(outInfo.<a class="code" href="struct_vma_stat_info.html#a5ba1a2476c4d39b10f7e2f7ebbb72ac4">unusedRangeSizeMax</a>, levelNodeSize);</div>
+<div class="line"><a name="l11647"></a><span class="lineno">11647</span>&#160;        outInfo.<a class="code" href="struct_vma_stat_info.html#aedeba931324f16589cd2416c0d2dd0d4">unusedRangeSizeMin</a> = VMA_MAX(outInfo.<a class="code" href="struct_vma_stat_info.html#aedeba931324f16589cd2416c0d2dd0d4">unusedRangeSizeMin</a>, levelNodeSize);</div>
+<div class="line"><a name="l11648"></a><span class="lineno">11648</span>&#160;        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l11649"></a><span class="lineno">11649</span>&#160;    <span class="keywordflow">case</span> Node::TYPE_ALLOCATION:</div>
+<div class="line"><a name="l11650"></a><span class="lineno">11650</span>&#160;        {</div>
+<div class="line"><a name="l11651"></a><span class="lineno">11651</span>&#160;            <span class="keyword">const</span> VkDeviceSize allocSize = node-&gt;allocation.alloc-&gt;GetSize();</div>
+<div class="line"><a name="l11652"></a><span class="lineno">11652</span>&#160;            ++outInfo.<a class="code" href="struct_vma_stat_info.html#a537741e4d5cdddc1c0ab95ec650afaff">allocationCount</a>;</div>
+<div class="line"><a name="l11653"></a><span class="lineno">11653</span>&#160;            outInfo.<a class="code" href="struct_vma_stat_info.html#ab0c6c73837e5a70c749fbd4f6064895a">usedBytes</a> += allocSize;</div>
+<div class="line"><a name="l11654"></a><span class="lineno">11654</span>&#160;            outInfo.<a class="code" href="struct_vma_stat_info.html#a17e9733a5ecd76287d4db6e66f71f50c">allocationSizeMax</a> = VMA_MAX(outInfo.<a class="code" href="struct_vma_stat_info.html#a17e9733a5ecd76287d4db6e66f71f50c">allocationSizeMax</a>, allocSize);</div>
+<div class="line"><a name="l11655"></a><span class="lineno">11655</span>&#160;            outInfo.<a class="code" href="struct_vma_stat_info.html#ade8b40bd3139c04aabd2fc538a356fea">allocationSizeMin</a> = VMA_MAX(outInfo.<a class="code" href="struct_vma_stat_info.html#ade8b40bd3139c04aabd2fc538a356fea">allocationSizeMin</a>, allocSize);</div>
+<div class="line"><a name="l11656"></a><span class="lineno">11656</span>&#160; </div>
+<div class="line"><a name="l11657"></a><span class="lineno">11657</span>&#160;            <span class="keyword">const</span> VkDeviceSize unusedRangeSize = levelNodeSize - allocSize;</div>
+<div class="line"><a name="l11658"></a><span class="lineno">11658</span>&#160;            <span class="keywordflow">if</span>(unusedRangeSize &gt; 0)</div>
+<div class="line"><a name="l11659"></a><span class="lineno">11659</span>&#160;            {</div>
+<div class="line"><a name="l11660"></a><span class="lineno">11660</span>&#160;                ++outInfo.<a class="code" href="struct_vma_stat_info.html#ae06129c771bfebfd6468a7f4276502a9">unusedRangeCount</a>;</div>
+<div class="line"><a name="l11661"></a><span class="lineno">11661</span>&#160;                outInfo.<a class="code" href="struct_vma_stat_info.html#a1859d290aca2cd582d8dc25922092669">unusedBytes</a> += unusedRangeSize;</div>
+<div class="line"><a name="l11662"></a><span class="lineno">11662</span>&#160;                outInfo.<a class="code" href="struct_vma_stat_info.html#a5ba1a2476c4d39b10f7e2f7ebbb72ac4">unusedRangeSizeMax</a> = VMA_MAX(outInfo.<a class="code" href="struct_vma_stat_info.html#a5ba1a2476c4d39b10f7e2f7ebbb72ac4">unusedRangeSizeMax</a>, unusedRangeSize);</div>
+<div class="line"><a name="l11663"></a><span class="lineno">11663</span>&#160;                outInfo.<a class="code" href="struct_vma_stat_info.html#aedeba931324f16589cd2416c0d2dd0d4">unusedRangeSizeMin</a> = VMA_MAX(outInfo.<a class="code" href="struct_vma_stat_info.html#aedeba931324f16589cd2416c0d2dd0d4">unusedRangeSizeMin</a>, unusedRangeSize);</div>
+<div class="line"><a name="l11664"></a><span class="lineno">11664</span>&#160;            }</div>
+<div class="line"><a name="l11665"></a><span class="lineno">11665</span>&#160;        }</div>
+<div class="line"><a name="l11666"></a><span class="lineno">11666</span>&#160;        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l11667"></a><span class="lineno">11667</span>&#160;    <span class="keywordflow">case</span> Node::TYPE_SPLIT:</div>
+<div class="line"><a name="l11668"></a><span class="lineno">11668</span>&#160;        {</div>
+<div class="line"><a name="l11669"></a><span class="lineno">11669</span>&#160;            <span class="keyword">const</span> VkDeviceSize childrenNodeSize = levelNodeSize / 2;</div>
+<div class="line"><a name="l11670"></a><span class="lineno">11670</span>&#160;            <span class="keyword">const</span> Node* <span class="keyword">const</span> leftChild = node-&gt;split.leftChild;</div>
+<div class="line"><a name="l11671"></a><span class="lineno">11671</span>&#160;            CalcAllocationStatInfoNode(outInfo, leftChild, childrenNodeSize);</div>
+<div class="line"><a name="l11672"></a><span class="lineno">11672</span>&#160;            <span class="keyword">const</span> Node* <span class="keyword">const</span> rightChild = leftChild-&gt;buddy;</div>
+<div class="line"><a name="l11673"></a><span class="lineno">11673</span>&#160;            CalcAllocationStatInfoNode(outInfo, rightChild, childrenNodeSize);</div>
+<div class="line"><a name="l11674"></a><span class="lineno">11674</span>&#160;        }</div>
+<div class="line"><a name="l11675"></a><span class="lineno">11675</span>&#160;        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l11676"></a><span class="lineno">11676</span>&#160;    <span class="keywordflow">default</span>:</div>
+<div class="line"><a name="l11677"></a><span class="lineno">11677</span>&#160;        VMA_ASSERT(0);</div>
+<div class="line"><a name="l11678"></a><span class="lineno">11678</span>&#160;    }</div>
+<div class="line"><a name="l11679"></a><span class="lineno">11679</span>&#160;}</div>
+<div class="line"><a name="l11680"></a><span class="lineno">11680</span>&#160; </div>
+<div class="line"><a name="l11681"></a><span class="lineno">11681</span>&#160;<span class="keywordtype">void</span> VmaBlockMetadata_Buddy::AddToFreeListFront(uint32_t level, Node* node)</div>
+<div class="line"><a name="l11682"></a><span class="lineno">11682</span>&#160;{</div>
+<div class="line"><a name="l11683"></a><span class="lineno">11683</span>&#160;    VMA_ASSERT(node-&gt;type == Node::TYPE_FREE);</div>
+<div class="line"><a name="l11684"></a><span class="lineno">11684</span>&#160; </div>
+<div class="line"><a name="l11685"></a><span class="lineno">11685</span>&#160;    <span class="comment">// List is empty.</span></div>
+<div class="line"><a name="l11686"></a><span class="lineno">11686</span>&#160;    Node* <span class="keyword">const</span> frontNode = m_FreeList[level].front;</div>
+<div class="line"><a name="l11687"></a><span class="lineno">11687</span>&#160;    <span class="keywordflow">if</span>(frontNode == VMA_NULL)</div>
+<div class="line"><a name="l11688"></a><span class="lineno">11688</span>&#160;    {</div>
+<div class="line"><a name="l11689"></a><span class="lineno">11689</span>&#160;        VMA_ASSERT(m_FreeList[level].back == VMA_NULL);</div>
+<div class="line"><a name="l11690"></a><span class="lineno">11690</span>&#160;        node-&gt;free.prev = node-&gt;free.next = VMA_NULL;</div>
+<div class="line"><a name="l11691"></a><span class="lineno">11691</span>&#160;        m_FreeList[level].front = m_FreeList[level].back = node;</div>
+<div class="line"><a name="l11692"></a><span class="lineno">11692</span>&#160;    }</div>
+<div class="line"><a name="l11693"></a><span class="lineno">11693</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l11694"></a><span class="lineno">11694</span>&#160;    {</div>
+<div class="line"><a name="l11695"></a><span class="lineno">11695</span>&#160;        VMA_ASSERT(frontNode-&gt;free.prev == VMA_NULL);</div>
+<div class="line"><a name="l11696"></a><span class="lineno">11696</span>&#160;        node-&gt;free.prev = VMA_NULL;</div>
+<div class="line"><a name="l11697"></a><span class="lineno">11697</span>&#160;        node-&gt;free.next = frontNode;</div>
+<div class="line"><a name="l11698"></a><span class="lineno">11698</span>&#160;        frontNode-&gt;free.prev = node;</div>
+<div class="line"><a name="l11699"></a><span class="lineno">11699</span>&#160;        m_FreeList[level].front = node;</div>
+<div class="line"><a name="l11700"></a><span class="lineno">11700</span>&#160;    }</div>
+<div class="line"><a name="l11701"></a><span class="lineno">11701</span>&#160;}</div>
+<div class="line"><a name="l11702"></a><span class="lineno">11702</span>&#160; </div>
+<div class="line"><a name="l11703"></a><span class="lineno">11703</span>&#160;<span class="keywordtype">void</span> VmaBlockMetadata_Buddy::RemoveFromFreeList(uint32_t level, Node* node)</div>
+<div class="line"><a name="l11704"></a><span class="lineno">11704</span>&#160;{</div>
+<div class="line"><a name="l11705"></a><span class="lineno">11705</span>&#160;    VMA_ASSERT(m_FreeList[level].front != VMA_NULL);</div>
+<div class="line"><a name="l11706"></a><span class="lineno">11706</span>&#160; </div>
+<div class="line"><a name="l11707"></a><span class="lineno">11707</span>&#160;    <span class="comment">// It is at the front.</span></div>
+<div class="line"><a name="l11708"></a><span class="lineno">11708</span>&#160;    <span class="keywordflow">if</span>(node-&gt;free.prev == VMA_NULL)</div>
+<div class="line"><a name="l11709"></a><span class="lineno">11709</span>&#160;    {</div>
+<div class="line"><a name="l11710"></a><span class="lineno">11710</span>&#160;        VMA_ASSERT(m_FreeList[level].front == node);</div>
+<div class="line"><a name="l11711"></a><span class="lineno">11711</span>&#160;        m_FreeList[level].front = node-&gt;free.next;</div>
+<div class="line"><a name="l11712"></a><span class="lineno">11712</span>&#160;    }</div>
+<div class="line"><a name="l11713"></a><span class="lineno">11713</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l11714"></a><span class="lineno">11714</span>&#160;    {</div>
+<div class="line"><a name="l11715"></a><span class="lineno">11715</span>&#160;        Node* <span class="keyword">const</span> prevFreeNode = node-&gt;free.prev;</div>
+<div class="line"><a name="l11716"></a><span class="lineno">11716</span>&#160;        VMA_ASSERT(prevFreeNode-&gt;free.next == node);</div>
+<div class="line"><a name="l11717"></a><span class="lineno">11717</span>&#160;        prevFreeNode-&gt;free.next = node-&gt;free.next;</div>
+<div class="line"><a name="l11718"></a><span class="lineno">11718</span>&#160;    }</div>
+<div class="line"><a name="l11719"></a><span class="lineno">11719</span>&#160; </div>
+<div class="line"><a name="l11720"></a><span class="lineno">11720</span>&#160;    <span class="comment">// It is at the back.</span></div>
+<div class="line"><a name="l11721"></a><span class="lineno">11721</span>&#160;    <span class="keywordflow">if</span>(node-&gt;free.next == VMA_NULL)</div>
+<div class="line"><a name="l11722"></a><span class="lineno">11722</span>&#160;    {</div>
+<div class="line"><a name="l11723"></a><span class="lineno">11723</span>&#160;        VMA_ASSERT(m_FreeList[level].back == node);</div>
+<div class="line"><a name="l11724"></a><span class="lineno">11724</span>&#160;        m_FreeList[level].back = node-&gt;free.prev;</div>
+<div class="line"><a name="l11725"></a><span class="lineno">11725</span>&#160;    }</div>
+<div class="line"><a name="l11726"></a><span class="lineno">11726</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l11727"></a><span class="lineno">11727</span>&#160;    {</div>
+<div class="line"><a name="l11728"></a><span class="lineno">11728</span>&#160;        Node* <span class="keyword">const</span> nextFreeNode = node-&gt;free.next;</div>
+<div class="line"><a name="l11729"></a><span class="lineno">11729</span>&#160;        VMA_ASSERT(nextFreeNode-&gt;free.prev == node);</div>
+<div class="line"><a name="l11730"></a><span class="lineno">11730</span>&#160;        nextFreeNode-&gt;free.prev = node-&gt;free.prev;</div>
+<div class="line"><a name="l11731"></a><span class="lineno">11731</span>&#160;    }</div>
+<div class="line"><a name="l11732"></a><span class="lineno">11732</span>&#160;}</div>
+<div class="line"><a name="l11733"></a><span class="lineno">11733</span>&#160; </div>
+<div class="line"><a name="l11734"></a><span class="lineno">11734</span>&#160;<span class="preprocessor">#if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l11735"></a><span class="lineno">11735</span>&#160;<span class="keywordtype">void</span> VmaBlockMetadata_Buddy::PrintDetailedMapNode(<span class="keyword">class</span> VmaJsonWriter&amp; json, <span class="keyword">const</span> Node* node, VkDeviceSize levelNodeSize)<span class="keyword"> const</span></div>
+<div class="line"><a name="l11736"></a><span class="lineno">11736</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l11737"></a><span class="lineno">11737</span>&#160;    <span class="keywordflow">switch</span>(node-&gt;type)</div>
+<div class="line"><a name="l11738"></a><span class="lineno">11738</span>&#160;    {</div>
+<div class="line"><a name="l11739"></a><span class="lineno">11739</span>&#160;    <span class="keywordflow">case</span> Node::TYPE_FREE:</div>
+<div class="line"><a name="l11740"></a><span class="lineno">11740</span>&#160;        PrintDetailedMap_UnusedRange(json, node-&gt;offset, levelNodeSize);</div>
+<div class="line"><a name="l11741"></a><span class="lineno">11741</span>&#160;        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l11742"></a><span class="lineno">11742</span>&#160;    <span class="keywordflow">case</span> Node::TYPE_ALLOCATION:</div>
+<div class="line"><a name="l11743"></a><span class="lineno">11743</span>&#160;        {   </div>
+<div class="line"><a name="l11744"></a><span class="lineno">11744</span>&#160;            PrintDetailedMap_Allocation(json, node-&gt;offset, node-&gt;allocation.alloc);</div>
+<div class="line"><a name="l11745"></a><span class="lineno">11745</span>&#160;            <span class="keyword">const</span> VkDeviceSize allocSize = node-&gt;allocation.alloc-&gt;GetSize();</div>
+<div class="line"><a name="l11746"></a><span class="lineno">11746</span>&#160;            <span class="keywordflow">if</span>(allocSize &lt; levelNodeSize)</div>
+<div class="line"><a name="l11747"></a><span class="lineno">11747</span>&#160;            {</div>
+<div class="line"><a name="l11748"></a><span class="lineno">11748</span>&#160;                PrintDetailedMap_UnusedRange(json, node-&gt;offset + allocSize, levelNodeSize - allocSize);</div>
+<div class="line"><a name="l11749"></a><span class="lineno">11749</span>&#160;            }</div>
+<div class="line"><a name="l11750"></a><span class="lineno">11750</span>&#160;        }</div>
+<div class="line"><a name="l11751"></a><span class="lineno">11751</span>&#160;        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l11752"></a><span class="lineno">11752</span>&#160;    <span class="keywordflow">case</span> Node::TYPE_SPLIT:</div>
+<div class="line"><a name="l11753"></a><span class="lineno">11753</span>&#160;        {</div>
+<div class="line"><a name="l11754"></a><span class="lineno">11754</span>&#160;            <span class="keyword">const</span> VkDeviceSize childrenNodeSize = levelNodeSize / 2;</div>
+<div class="line"><a name="l11755"></a><span class="lineno">11755</span>&#160;            <span class="keyword">const</span> Node* <span class="keyword">const</span> leftChild = node-&gt;split.leftChild;</div>
+<div class="line"><a name="l11756"></a><span class="lineno">11756</span>&#160;            PrintDetailedMapNode(json, leftChild, childrenNodeSize);</div>
+<div class="line"><a name="l11757"></a><span class="lineno">11757</span>&#160;            <span class="keyword">const</span> Node* <span class="keyword">const</span> rightChild = leftChild-&gt;buddy;</div>
+<div class="line"><a name="l11758"></a><span class="lineno">11758</span>&#160;            PrintDetailedMapNode(json, rightChild, childrenNodeSize);</div>
+<div class="line"><a name="l11759"></a><span class="lineno">11759</span>&#160;        }</div>
+<div class="line"><a name="l11760"></a><span class="lineno">11760</span>&#160;        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l11761"></a><span class="lineno">11761</span>&#160;    <span class="keywordflow">default</span>:</div>
+<div class="line"><a name="l11762"></a><span class="lineno">11762</span>&#160;        VMA_ASSERT(0);</div>
+<div class="line"><a name="l11763"></a><span class="lineno">11763</span>&#160;    }</div>
+<div class="line"><a name="l11764"></a><span class="lineno">11764</span>&#160;}</div>
+<div class="line"><a name="l11765"></a><span class="lineno">11765</span>&#160;<span class="preprocessor">#endif // #if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l11766"></a><span class="lineno">11766</span>&#160; </div>
+<div class="line"><a name="l11767"></a><span class="lineno">11767</span>&#160; </div>
+<div class="line"><a name="l11769"></a><span class="lineno">11769</span>&#160;<span class="comment">// class VmaDeviceMemoryBlock</span></div>
+<div class="line"><a name="l11770"></a><span class="lineno">11770</span>&#160; </div>
+<div class="line"><a name="l11771"></a><span class="lineno">11771</span>&#160;VmaDeviceMemoryBlock::VmaDeviceMemoryBlock(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator) :</div>
+<div class="line"><a name="l11772"></a><span class="lineno">11772</span>&#160;    m_pMetadata(VMA_NULL),</div>
+<div class="line"><a name="l11773"></a><span class="lineno">11773</span>&#160;    m_MemoryTypeIndex(UINT32_MAX),</div>
+<div class="line"><a name="l11774"></a><span class="lineno">11774</span>&#160;    m_Id(0),</div>
+<div class="line"><a name="l11775"></a><span class="lineno">11775</span>&#160;    m_hMemory(VK_NULL_HANDLE),</div>
+<div class="line"><a name="l11776"></a><span class="lineno">11776</span>&#160;    m_MapCount(0),</div>
+<div class="line"><a name="l11777"></a><span class="lineno">11777</span>&#160;    m_pMappedData(VMA_NULL)</div>
+<div class="line"><a name="l11778"></a><span class="lineno">11778</span>&#160;{</div>
+<div class="line"><a name="l11779"></a><span class="lineno">11779</span>&#160;}</div>
+<div class="line"><a name="l11780"></a><span class="lineno">11780</span>&#160; </div>
+<div class="line"><a name="l11781"></a><span class="lineno">11781</span>&#160;<span class="keywordtype">void</span> VmaDeviceMemoryBlock::Init(</div>
+<div class="line"><a name="l11782"></a><span class="lineno">11782</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator,</div>
+<div class="line"><a name="l11783"></a><span class="lineno">11783</span>&#160;    <a class="code" href="struct_vma_pool.html">VmaPool</a> hParentPool,</div>
+<div class="line"><a name="l11784"></a><span class="lineno">11784</span>&#160;    uint32_t newMemoryTypeIndex,</div>
+<div class="line"><a name="l11785"></a><span class="lineno">11785</span>&#160;    VkDeviceMemory newMemory,</div>
+<div class="line"><a name="l11786"></a><span class="lineno">11786</span>&#160;    VkDeviceSize newSize,</div>
+<div class="line"><a name="l11787"></a><span class="lineno">11787</span>&#160;    uint32_t <span class="keywordtype">id</span>,</div>
+<div class="line"><a name="l11788"></a><span class="lineno">11788</span>&#160;    uint32_t algorithm)</div>
+<div class="line"><a name="l11789"></a><span class="lineno">11789</span>&#160;{</div>
+<div class="line"><a name="l11790"></a><span class="lineno">11790</span>&#160;    VMA_ASSERT(m_hMemory == VK_NULL_HANDLE);</div>
+<div class="line"><a name="l11791"></a><span class="lineno">11791</span>&#160; </div>
+<div class="line"><a name="l11792"></a><span class="lineno">11792</span>&#160;    m_hParentPool = hParentPool;</div>
+<div class="line"><a name="l11793"></a><span class="lineno">11793</span>&#160;    m_MemoryTypeIndex = newMemoryTypeIndex;</div>
+<div class="line"><a name="l11794"></a><span class="lineno">11794</span>&#160;    m_Id = id;</div>
+<div class="line"><a name="l11795"></a><span class="lineno">11795</span>&#160;    m_hMemory = newMemory;</div>
+<div class="line"><a name="l11796"></a><span class="lineno">11796</span>&#160; </div>
+<div class="line"><a name="l11797"></a><span class="lineno">11797</span>&#160;    <span class="keywordflow">switch</span>(algorithm)</div>
+<div class="line"><a name="l11798"></a><span class="lineno">11798</span>&#160;    {</div>
+<div class="line"><a name="l11799"></a><span class="lineno">11799</span>&#160;    <span class="keywordflow">case</span> <a class="code" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a13c8a444197c67866be9cb05599fc726">VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT</a>:</div>
+<div class="line"><a name="l11800"></a><span class="lineno">11800</span>&#160;        m_pMetadata = vma_new(hAllocator, VmaBlockMetadata_Linear)(hAllocator);</div>
+<div class="line"><a name="l11801"></a><span class="lineno">11801</span>&#160;        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l11802"></a><span class="lineno">11802</span>&#160;    <span class="keywordflow">case</span> <a class="code" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a97a0dc38e5161b780594d998d313d35e">VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT</a>:</div>
+<div class="line"><a name="l11803"></a><span class="lineno">11803</span>&#160;        m_pMetadata = vma_new(hAllocator, VmaBlockMetadata_Buddy)(hAllocator);</div>
+<div class="line"><a name="l11804"></a><span class="lineno">11804</span>&#160;        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l11805"></a><span class="lineno">11805</span>&#160;    <span class="keywordflow">default</span>:</div>
+<div class="line"><a name="l11806"></a><span class="lineno">11806</span>&#160;        VMA_ASSERT(0);</div>
+<div class="line"><a name="l11807"></a><span class="lineno">11807</span>&#160;        <span class="comment">// Fall-through.</span></div>
+<div class="line"><a name="l11808"></a><span class="lineno">11808</span>&#160;    <span class="keywordflow">case</span> 0:</div>
+<div class="line"><a name="l11809"></a><span class="lineno">11809</span>&#160;        m_pMetadata = vma_new(hAllocator, VmaBlockMetadata_Generic)(hAllocator);</div>
+<div class="line"><a name="l11810"></a><span class="lineno">11810</span>&#160;    }</div>
+<div class="line"><a name="l11811"></a><span class="lineno">11811</span>&#160;    m_pMetadata-&gt;Init(newSize);</div>
+<div class="line"><a name="l11812"></a><span class="lineno">11812</span>&#160;}</div>
+<div class="line"><a name="l11813"></a><span class="lineno">11813</span>&#160; </div>
+<div class="line"><a name="l11814"></a><span class="lineno">11814</span>&#160;<span class="keywordtype">void</span> VmaDeviceMemoryBlock::Destroy(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator)</div>
+<div class="line"><a name="l11815"></a><span class="lineno">11815</span>&#160;{</div>
+<div class="line"><a name="l11816"></a><span class="lineno">11816</span>&#160;    <span class="comment">// This is the most important assert in the entire library.</span></div>
+<div class="line"><a name="l11817"></a><span class="lineno">11817</span>&#160;    <span class="comment">// Hitting it means you have some memory leak - unreleased VmaAllocation objects.</span></div>
+<div class="line"><a name="l11818"></a><span class="lineno">11818</span>&#160;    VMA_ASSERT(m_pMetadata-&gt;IsEmpty() &amp;&amp; <span class="stringliteral">&quot;Some allocations were not freed before destruction of this memory block!&quot;</span>);</div>
+<div class="line"><a name="l11819"></a><span class="lineno">11819</span>&#160; </div>
+<div class="line"><a name="l11820"></a><span class="lineno">11820</span>&#160;    VMA_ASSERT(m_hMemory != VK_NULL_HANDLE);</div>
+<div class="line"><a name="l11821"></a><span class="lineno">11821</span>&#160;    allocator-&gt;FreeVulkanMemory(m_MemoryTypeIndex, m_pMetadata-&gt;GetSize(), m_hMemory);</div>
+<div class="line"><a name="l11822"></a><span class="lineno">11822</span>&#160;    m_hMemory = VK_NULL_HANDLE;</div>
+<div class="line"><a name="l11823"></a><span class="lineno">11823</span>&#160; </div>
+<div class="line"><a name="l11824"></a><span class="lineno">11824</span>&#160;    vma_delete(allocator, m_pMetadata);</div>
+<div class="line"><a name="l11825"></a><span class="lineno">11825</span>&#160;    m_pMetadata = VMA_NULL;</div>
+<div class="line"><a name="l11826"></a><span class="lineno">11826</span>&#160;}</div>
+<div class="line"><a name="l11827"></a><span class="lineno">11827</span>&#160; </div>
+<div class="line"><a name="l11828"></a><span class="lineno">11828</span>&#160;<span class="keywordtype">bool</span> VmaDeviceMemoryBlock::Validate()<span class="keyword"> const</span></div>
+<div class="line"><a name="l11829"></a><span class="lineno">11829</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l11830"></a><span class="lineno">11830</span>&#160;    VMA_VALIDATE((m_hMemory != VK_NULL_HANDLE) &amp;&amp;</div>
+<div class="line"><a name="l11831"></a><span class="lineno">11831</span>&#160;        (m_pMetadata-&gt;GetSize() != 0));</div>
+<div class="line"><a name="l11832"></a><span class="lineno">11832</span>&#160;    </div>
+<div class="line"><a name="l11833"></a><span class="lineno">11833</span>&#160;    <span class="keywordflow">return</span> m_pMetadata-&gt;Validate();</div>
+<div class="line"><a name="l11834"></a><span class="lineno">11834</span>&#160;}</div>
+<div class="line"><a name="l11835"></a><span class="lineno">11835</span>&#160; </div>
+<div class="line"><a name="l11836"></a><span class="lineno">11836</span>&#160;VkResult VmaDeviceMemoryBlock::CheckCorruption(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator)</div>
+<div class="line"><a name="l11837"></a><span class="lineno">11837</span>&#160;{</div>
+<div class="line"><a name="l11838"></a><span class="lineno">11838</span>&#160;    <span class="keywordtype">void</span>* pData = <span class="keyword">nullptr</span>;</div>
+<div class="line"><a name="l11839"></a><span class="lineno">11839</span>&#160;    VkResult res = Map(hAllocator, 1, &amp;pData);</div>
+<div class="line"><a name="l11840"></a><span class="lineno">11840</span>&#160;    <span class="keywordflow">if</span>(res != VK_SUCCESS)</div>
+<div class="line"><a name="l11841"></a><span class="lineno">11841</span>&#160;    {</div>
+<div class="line"><a name="l11842"></a><span class="lineno">11842</span>&#160;        <span class="keywordflow">return</span> res;</div>
+<div class="line"><a name="l11843"></a><span class="lineno">11843</span>&#160;    }</div>
+<div class="line"><a name="l11844"></a><span class="lineno">11844</span>&#160; </div>
+<div class="line"><a name="l11845"></a><span class="lineno">11845</span>&#160;    res = m_pMetadata-&gt;CheckCorruption(pData);</div>
+<div class="line"><a name="l11846"></a><span class="lineno">11846</span>&#160; </div>
+<div class="line"><a name="l11847"></a><span class="lineno">11847</span>&#160;    Unmap(hAllocator, 1);</div>
+<div class="line"><a name="l11848"></a><span class="lineno">11848</span>&#160; </div>
+<div class="line"><a name="l11849"></a><span class="lineno">11849</span>&#160;    <span class="keywordflow">return</span> res;</div>
+<div class="line"><a name="l11850"></a><span class="lineno">11850</span>&#160;}</div>
+<div class="line"><a name="l11851"></a><span class="lineno">11851</span>&#160; </div>
+<div class="line"><a name="l11852"></a><span class="lineno">11852</span>&#160;VkResult VmaDeviceMemoryBlock::Map(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator, uint32_t count, <span class="keywordtype">void</span>** ppData)</div>
+<div class="line"><a name="l11853"></a><span class="lineno">11853</span>&#160;{</div>
+<div class="line"><a name="l11854"></a><span class="lineno">11854</span>&#160;    <span class="keywordflow">if</span>(count == 0)</div>
+<div class="line"><a name="l11855"></a><span class="lineno">11855</span>&#160;    {</div>
+<div class="line"><a name="l11856"></a><span class="lineno">11856</span>&#160;        <span class="keywordflow">return</span> VK_SUCCESS;</div>
+<div class="line"><a name="l11857"></a><span class="lineno">11857</span>&#160;    }</div>
+<div class="line"><a name="l11858"></a><span class="lineno">11858</span>&#160; </div>
+<div class="line"><a name="l11859"></a><span class="lineno">11859</span>&#160;    VmaMutexLock lock(m_Mutex, hAllocator-&gt;m_UseMutex);</div>
+<div class="line"><a name="l11860"></a><span class="lineno">11860</span>&#160;    <span class="keywordflow">if</span>(m_MapCount != 0)</div>
+<div class="line"><a name="l11861"></a><span class="lineno">11861</span>&#160;    {</div>
+<div class="line"><a name="l11862"></a><span class="lineno">11862</span>&#160;        m_MapCount += count;</div>
+<div class="line"><a name="l11863"></a><span class="lineno">11863</span>&#160;        VMA_ASSERT(m_pMappedData != VMA_NULL);</div>
+<div class="line"><a name="l11864"></a><span class="lineno">11864</span>&#160;        <span class="keywordflow">if</span>(ppData != VMA_NULL)</div>
+<div class="line"><a name="l11865"></a><span class="lineno">11865</span>&#160;        {</div>
+<div class="line"><a name="l11866"></a><span class="lineno">11866</span>&#160;            *ppData = m_pMappedData;</div>
+<div class="line"><a name="l11867"></a><span class="lineno">11867</span>&#160;        }</div>
+<div class="line"><a name="l11868"></a><span class="lineno">11868</span>&#160;        <span class="keywordflow">return</span> VK_SUCCESS;</div>
+<div class="line"><a name="l11869"></a><span class="lineno">11869</span>&#160;    }</div>
+<div class="line"><a name="l11870"></a><span class="lineno">11870</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l11871"></a><span class="lineno">11871</span>&#160;    {</div>
+<div class="line"><a name="l11872"></a><span class="lineno">11872</span>&#160;        VkResult result = (*hAllocator-&gt;GetVulkanFunctions().vkMapMemory)(</div>
+<div class="line"><a name="l11873"></a><span class="lineno">11873</span>&#160;            hAllocator-&gt;m_hDevice,</div>
+<div class="line"><a name="l11874"></a><span class="lineno">11874</span>&#160;            m_hMemory,</div>
+<div class="line"><a name="l11875"></a><span class="lineno">11875</span>&#160;            0, <span class="comment">// offset</span></div>
+<div class="line"><a name="l11876"></a><span class="lineno">11876</span>&#160;            VK_WHOLE_SIZE,</div>
+<div class="line"><a name="l11877"></a><span class="lineno">11877</span>&#160;            0, <span class="comment">// flags</span></div>
+<div class="line"><a name="l11878"></a><span class="lineno">11878</span>&#160;            &amp;m_pMappedData);</div>
+<div class="line"><a name="l11879"></a><span class="lineno">11879</span>&#160;        <span class="keywordflow">if</span>(result == VK_SUCCESS)</div>
+<div class="line"><a name="l11880"></a><span class="lineno">11880</span>&#160;        {</div>
+<div class="line"><a name="l11881"></a><span class="lineno">11881</span>&#160;            <span class="keywordflow">if</span>(ppData != VMA_NULL)</div>
+<div class="line"><a name="l11882"></a><span class="lineno">11882</span>&#160;            {</div>
+<div class="line"><a name="l11883"></a><span class="lineno">11883</span>&#160;                *ppData = m_pMappedData;</div>
+<div class="line"><a name="l11884"></a><span class="lineno">11884</span>&#160;            }</div>
+<div class="line"><a name="l11885"></a><span class="lineno">11885</span>&#160;            m_MapCount = count;</div>
+<div class="line"><a name="l11886"></a><span class="lineno">11886</span>&#160;        }</div>
+<div class="line"><a name="l11887"></a><span class="lineno">11887</span>&#160;        <span class="keywordflow">return</span> result;</div>
+<div class="line"><a name="l11888"></a><span class="lineno">11888</span>&#160;    }</div>
+<div class="line"><a name="l11889"></a><span class="lineno">11889</span>&#160;}</div>
+<div class="line"><a name="l11890"></a><span class="lineno">11890</span>&#160; </div>
+<div class="line"><a name="l11891"></a><span class="lineno">11891</span>&#160;<span class="keywordtype">void</span> VmaDeviceMemoryBlock::Unmap(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator, uint32_t count)</div>
+<div class="line"><a name="l11892"></a><span class="lineno">11892</span>&#160;{</div>
+<div class="line"><a name="l11893"></a><span class="lineno">11893</span>&#160;    <span class="keywordflow">if</span>(count == 0)</div>
+<div class="line"><a name="l11894"></a><span class="lineno">11894</span>&#160;    {</div>
+<div class="line"><a name="l11895"></a><span class="lineno">11895</span>&#160;        <span class="keywordflow">return</span>;</div>
+<div class="line"><a name="l11896"></a><span class="lineno">11896</span>&#160;    }</div>
+<div class="line"><a name="l11897"></a><span class="lineno">11897</span>&#160; </div>
+<div class="line"><a name="l11898"></a><span class="lineno">11898</span>&#160;    VmaMutexLock lock(m_Mutex, hAllocator-&gt;m_UseMutex);</div>
+<div class="line"><a name="l11899"></a><span class="lineno">11899</span>&#160;    <span class="keywordflow">if</span>(m_MapCount &gt;= count)</div>
+<div class="line"><a name="l11900"></a><span class="lineno">11900</span>&#160;    {</div>
+<div class="line"><a name="l11901"></a><span class="lineno">11901</span>&#160;        m_MapCount -= count;</div>
+<div class="line"><a name="l11902"></a><span class="lineno">11902</span>&#160;        <span class="keywordflow">if</span>(m_MapCount == 0)</div>
+<div class="line"><a name="l11903"></a><span class="lineno">11903</span>&#160;        {</div>
+<div class="line"><a name="l11904"></a><span class="lineno">11904</span>&#160;            m_pMappedData = VMA_NULL;</div>
+<div class="line"><a name="l11905"></a><span class="lineno">11905</span>&#160;            (*hAllocator-&gt;GetVulkanFunctions().vkUnmapMemory)(hAllocator-&gt;m_hDevice, m_hMemory);</div>
+<div class="line"><a name="l11906"></a><span class="lineno">11906</span>&#160;        }</div>
+<div class="line"><a name="l11907"></a><span class="lineno">11907</span>&#160;    }</div>
+<div class="line"><a name="l11908"></a><span class="lineno">11908</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l11909"></a><span class="lineno">11909</span>&#160;    {</div>
+<div class="line"><a name="l11910"></a><span class="lineno">11910</span>&#160;        VMA_ASSERT(0 &amp;&amp; <span class="stringliteral">&quot;VkDeviceMemory block is being unmapped while it was not previously mapped.&quot;</span>);</div>
+<div class="line"><a name="l11911"></a><span class="lineno">11911</span>&#160;    }</div>
+<div class="line"><a name="l11912"></a><span class="lineno">11912</span>&#160;}</div>
+<div class="line"><a name="l11913"></a><span class="lineno">11913</span>&#160; </div>
+<div class="line"><a name="l11914"></a><span class="lineno">11914</span>&#160;VkResult VmaDeviceMemoryBlock::WriteMagicValueAroundAllocation(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator, VkDeviceSize allocOffset, VkDeviceSize allocSize)</div>
+<div class="line"><a name="l11915"></a><span class="lineno">11915</span>&#160;{</div>
+<div class="line"><a name="l11916"></a><span class="lineno">11916</span>&#160;    VMA_ASSERT(VMA_DEBUG_MARGIN &gt; 0 &amp;&amp; VMA_DEBUG_MARGIN % 4 == 0 &amp;&amp; VMA_DEBUG_DETECT_CORRUPTION);</div>
+<div class="line"><a name="l11917"></a><span class="lineno">11917</span>&#160;    VMA_ASSERT(allocOffset &gt;= VMA_DEBUG_MARGIN);</div>
+<div class="line"><a name="l11918"></a><span class="lineno">11918</span>&#160; </div>
+<div class="line"><a name="l11919"></a><span class="lineno">11919</span>&#160;    <span class="keywordtype">void</span>* pData;</div>
+<div class="line"><a name="l11920"></a><span class="lineno">11920</span>&#160;    VkResult res = Map(hAllocator, 1, &amp;pData);</div>
+<div class="line"><a name="l11921"></a><span class="lineno">11921</span>&#160;    <span class="keywordflow">if</span>(res != VK_SUCCESS)</div>
+<div class="line"><a name="l11922"></a><span class="lineno">11922</span>&#160;    {</div>
+<div class="line"><a name="l11923"></a><span class="lineno">11923</span>&#160;        <span class="keywordflow">return</span> res;</div>
+<div class="line"><a name="l11924"></a><span class="lineno">11924</span>&#160;    }</div>
+<div class="line"><a name="l11925"></a><span class="lineno">11925</span>&#160; </div>
+<div class="line"><a name="l11926"></a><span class="lineno">11926</span>&#160;    VmaWriteMagicValue(pData, allocOffset - VMA_DEBUG_MARGIN);</div>
+<div class="line"><a name="l11927"></a><span class="lineno">11927</span>&#160;    VmaWriteMagicValue(pData, allocOffset + allocSize);</div>
+<div class="line"><a name="l11928"></a><span class="lineno">11928</span>&#160; </div>
+<div class="line"><a name="l11929"></a><span class="lineno">11929</span>&#160;    Unmap(hAllocator, 1);</div>
+<div class="line"><a name="l11930"></a><span class="lineno">11930</span>&#160; </div>
+<div class="line"><a name="l11931"></a><span class="lineno">11931</span>&#160;    <span class="keywordflow">return</span> VK_SUCCESS;</div>
+<div class="line"><a name="l11932"></a><span class="lineno">11932</span>&#160;}</div>
+<div class="line"><a name="l11933"></a><span class="lineno">11933</span>&#160; </div>
+<div class="line"><a name="l11934"></a><span class="lineno">11934</span>&#160;VkResult VmaDeviceMemoryBlock::ValidateMagicValueAroundAllocation(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator, VkDeviceSize allocOffset, VkDeviceSize allocSize)</div>
+<div class="line"><a name="l11935"></a><span class="lineno">11935</span>&#160;{</div>
+<div class="line"><a name="l11936"></a><span class="lineno">11936</span>&#160;    VMA_ASSERT(VMA_DEBUG_MARGIN &gt; 0 &amp;&amp; VMA_DEBUG_MARGIN % 4 == 0 &amp;&amp; VMA_DEBUG_DETECT_CORRUPTION);</div>
+<div class="line"><a name="l11937"></a><span class="lineno">11937</span>&#160;    VMA_ASSERT(allocOffset &gt;= VMA_DEBUG_MARGIN);</div>
+<div class="line"><a name="l11938"></a><span class="lineno">11938</span>&#160; </div>
+<div class="line"><a name="l11939"></a><span class="lineno">11939</span>&#160;    <span class="keywordtype">void</span>* pData;</div>
+<div class="line"><a name="l11940"></a><span class="lineno">11940</span>&#160;    VkResult res = Map(hAllocator, 1, &amp;pData);</div>
+<div class="line"><a name="l11941"></a><span class="lineno">11941</span>&#160;    <span class="keywordflow">if</span>(res != VK_SUCCESS)</div>
+<div class="line"><a name="l11942"></a><span class="lineno">11942</span>&#160;    {</div>
+<div class="line"><a name="l11943"></a><span class="lineno">11943</span>&#160;        <span class="keywordflow">return</span> res;</div>
+<div class="line"><a name="l11944"></a><span class="lineno">11944</span>&#160;    }</div>
+<div class="line"><a name="l11945"></a><span class="lineno">11945</span>&#160; </div>
+<div class="line"><a name="l11946"></a><span class="lineno">11946</span>&#160;    <span class="keywordflow">if</span>(!VmaValidateMagicValue(pData, allocOffset - VMA_DEBUG_MARGIN))</div>
+<div class="line"><a name="l11947"></a><span class="lineno">11947</span>&#160;    {</div>
+<div class="line"><a name="l11948"></a><span class="lineno">11948</span>&#160;        VMA_ASSERT(0 &amp;&amp; <span class="stringliteral">&quot;MEMORY CORRUPTION DETECTED BEFORE FREED ALLOCATION!&quot;</span>);</div>
+<div class="line"><a name="l11949"></a><span class="lineno">11949</span>&#160;    }</div>
+<div class="line"><a name="l11950"></a><span class="lineno">11950</span>&#160;    <span class="keywordflow">else</span> <span class="keywordflow">if</span>(!VmaValidateMagicValue(pData, allocOffset + allocSize))</div>
+<div class="line"><a name="l11951"></a><span class="lineno">11951</span>&#160;    {</div>
+<div class="line"><a name="l11952"></a><span class="lineno">11952</span>&#160;        VMA_ASSERT(0 &amp;&amp; <span class="stringliteral">&quot;MEMORY CORRUPTION DETECTED AFTER FREED ALLOCATION!&quot;</span>);</div>
+<div class="line"><a name="l11953"></a><span class="lineno">11953</span>&#160;    }</div>
+<div class="line"><a name="l11954"></a><span class="lineno">11954</span>&#160; </div>
+<div class="line"><a name="l11955"></a><span class="lineno">11955</span>&#160;    Unmap(hAllocator, 1);</div>
+<div class="line"><a name="l11956"></a><span class="lineno">11956</span>&#160; </div>
+<div class="line"><a name="l11957"></a><span class="lineno">11957</span>&#160;    <span class="keywordflow">return</span> VK_SUCCESS;</div>
+<div class="line"><a name="l11958"></a><span class="lineno">11958</span>&#160;}</div>
+<div class="line"><a name="l11959"></a><span class="lineno">11959</span>&#160; </div>
+<div class="line"><a name="l11960"></a><span class="lineno">11960</span>&#160;VkResult VmaDeviceMemoryBlock::BindBufferMemory(</div>
+<div class="line"><a name="l11961"></a><span class="lineno">11961</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator,</div>
+<div class="line"><a name="l11962"></a><span class="lineno">11962</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAllocation,</div>
+<div class="line"><a name="l11963"></a><span class="lineno">11963</span>&#160;    VkDeviceSize allocationLocalOffset,</div>
+<div class="line"><a name="l11964"></a><span class="lineno">11964</span>&#160;    VkBuffer hBuffer,</div>
+<div class="line"><a name="l11965"></a><span class="lineno">11965</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">void</span>* pNext)</div>
+<div class="line"><a name="l11966"></a><span class="lineno">11966</span>&#160;{</div>
+<div class="line"><a name="l11967"></a><span class="lineno">11967</span>&#160;    VMA_ASSERT(hAllocation-&gt;GetType() == VmaAllocation_T::ALLOCATION_TYPE_BLOCK &amp;&amp;</div>
+<div class="line"><a name="l11968"></a><span class="lineno">11968</span>&#160;        hAllocation-&gt;GetBlock() == <span class="keyword">this</span>);</div>
+<div class="line"><a name="l11969"></a><span class="lineno">11969</span>&#160;    VMA_ASSERT(allocationLocalOffset &lt; hAllocation-&gt;GetSize() &amp;&amp;</div>
+<div class="line"><a name="l11970"></a><span class="lineno">11970</span>&#160;        <span class="stringliteral">&quot;Invalid allocationLocalOffset. Did you forget that this offset is relative to the beginning of the allocation, not the whole memory block?&quot;</span>);</div>
+<div class="line"><a name="l11971"></a><span class="lineno">11971</span>&#160;    <span class="keyword">const</span> VkDeviceSize memoryOffset = hAllocation-&gt;GetOffset() + allocationLocalOffset;</div>
+<div class="line"><a name="l11972"></a><span class="lineno">11972</span>&#160;    <span class="comment">// This lock is important so that we don&#39;t call vkBind... and/or vkMap... simultaneously on the same VkDeviceMemory from multiple threads.</span></div>
+<div class="line"><a name="l11973"></a><span class="lineno">11973</span>&#160;    VmaMutexLock lock(m_Mutex, hAllocator-&gt;m_UseMutex);</div>
+<div class="line"><a name="l11974"></a><span class="lineno">11974</span>&#160;    <span class="keywordflow">return</span> hAllocator-&gt;BindVulkanBuffer(m_hMemory, memoryOffset, hBuffer, pNext);</div>
+<div class="line"><a name="l11975"></a><span class="lineno">11975</span>&#160;}</div>
+<div class="line"><a name="l11976"></a><span class="lineno">11976</span>&#160; </div>
+<div class="line"><a name="l11977"></a><span class="lineno">11977</span>&#160;VkResult VmaDeviceMemoryBlock::BindImageMemory(</div>
+<div class="line"><a name="l11978"></a><span class="lineno">11978</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator,</div>
+<div class="line"><a name="l11979"></a><span class="lineno">11979</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAllocation,</div>
+<div class="line"><a name="l11980"></a><span class="lineno">11980</span>&#160;    VkDeviceSize allocationLocalOffset,</div>
+<div class="line"><a name="l11981"></a><span class="lineno">11981</span>&#160;    VkImage hImage,</div>
+<div class="line"><a name="l11982"></a><span class="lineno">11982</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">void</span>* pNext)</div>
+<div class="line"><a name="l11983"></a><span class="lineno">11983</span>&#160;{</div>
+<div class="line"><a name="l11984"></a><span class="lineno">11984</span>&#160;    VMA_ASSERT(hAllocation-&gt;GetType() == VmaAllocation_T::ALLOCATION_TYPE_BLOCK &amp;&amp;</div>
+<div class="line"><a name="l11985"></a><span class="lineno">11985</span>&#160;        hAllocation-&gt;GetBlock() == <span class="keyword">this</span>);</div>
+<div class="line"><a name="l11986"></a><span class="lineno">11986</span>&#160;    VMA_ASSERT(allocationLocalOffset &lt; hAllocation-&gt;GetSize() &amp;&amp;</div>
+<div class="line"><a name="l11987"></a><span class="lineno">11987</span>&#160;        <span class="stringliteral">&quot;Invalid allocationLocalOffset. Did you forget that this offset is relative to the beginning of the allocation, not the whole memory block?&quot;</span>);</div>
+<div class="line"><a name="l11988"></a><span class="lineno">11988</span>&#160;    <span class="keyword">const</span> VkDeviceSize memoryOffset = hAllocation-&gt;GetOffset() + allocationLocalOffset;</div>
+<div class="line"><a name="l11989"></a><span class="lineno">11989</span>&#160;    <span class="comment">// This lock is important so that we don&#39;t call vkBind... and/or vkMap... simultaneously on the same VkDeviceMemory from multiple threads.</span></div>
+<div class="line"><a name="l11990"></a><span class="lineno">11990</span>&#160;    VmaMutexLock lock(m_Mutex, hAllocator-&gt;m_UseMutex);</div>
+<div class="line"><a name="l11991"></a><span class="lineno">11991</span>&#160;    <span class="keywordflow">return</span> hAllocator-&gt;BindVulkanImage(m_hMemory, memoryOffset, hImage, pNext);</div>
+<div class="line"><a name="l11992"></a><span class="lineno">11992</span>&#160;}</div>
+<div class="line"><a name="l11993"></a><span class="lineno">11993</span>&#160; </div>
+<div class="line"><a name="l11994"></a><span class="lineno">11994</span>&#160;<span class="keyword">static</span> <span class="keywordtype">void</span> InitStatInfo(<a class="code" href="struct_vma_stat_info.html">VmaStatInfo</a>&amp; outInfo)</div>
+<div class="line"><a name="l11995"></a><span class="lineno">11995</span>&#160;{</div>
+<div class="line"><a name="l11996"></a><span class="lineno">11996</span>&#160;    memset(&amp;outInfo, 0, <span class="keyword">sizeof</span>(outInfo));</div>
+<div class="line"><a name="l11997"></a><span class="lineno">11997</span>&#160;    outInfo.<a class="code" href="struct_vma_stat_info.html#ade8b40bd3139c04aabd2fc538a356fea">allocationSizeMin</a> = UINT64_MAX;</div>
+<div class="line"><a name="l11998"></a><span class="lineno">11998</span>&#160;    outInfo.<a class="code" href="struct_vma_stat_info.html#aedeba931324f16589cd2416c0d2dd0d4">unusedRangeSizeMin</a> = UINT64_MAX;</div>
+<div class="line"><a name="l11999"></a><span class="lineno">11999</span>&#160;}</div>
+<div class="line"><a name="l12000"></a><span class="lineno">12000</span>&#160; </div>
+<div class="line"><a name="l12001"></a><span class="lineno">12001</span>&#160;<span class="comment">// Adds statistics srcInfo into inoutInfo, like: inoutInfo += srcInfo.</span></div>
+<div class="line"><a name="l12002"></a><span class="lineno">12002</span>&#160;<span class="keyword">static</span> <span class="keywordtype">void</span> VmaAddStatInfo(<a class="code" href="struct_vma_stat_info.html">VmaStatInfo</a>&amp; inoutInfo, <span class="keyword">const</span> <a class="code" href="struct_vma_stat_info.html">VmaStatInfo</a>&amp; srcInfo)</div>
+<div class="line"><a name="l12003"></a><span class="lineno">12003</span>&#160;{</div>
+<div class="line"><a name="l12004"></a><span class="lineno">12004</span>&#160;    inoutInfo.<a class="code" href="struct_vma_stat_info.html#abc4bb7cd611900778464c56e50c970a4">blockCount</a> += srcInfo.<a class="code" href="struct_vma_stat_info.html#abc4bb7cd611900778464c56e50c970a4">blockCount</a>;</div>
+<div class="line"><a name="l12005"></a><span class="lineno">12005</span>&#160;    inoutInfo.<a class="code" href="struct_vma_stat_info.html#a537741e4d5cdddc1c0ab95ec650afaff">allocationCount</a> += srcInfo.<a class="code" href="struct_vma_stat_info.html#a537741e4d5cdddc1c0ab95ec650afaff">allocationCount</a>;</div>
+<div class="line"><a name="l12006"></a><span class="lineno">12006</span>&#160;    inoutInfo.<a class="code" href="struct_vma_stat_info.html#ae06129c771bfebfd6468a7f4276502a9">unusedRangeCount</a> += srcInfo.<a class="code" href="struct_vma_stat_info.html#ae06129c771bfebfd6468a7f4276502a9">unusedRangeCount</a>;</div>
+<div class="line"><a name="l12007"></a><span class="lineno">12007</span>&#160;    inoutInfo.<a class="code" href="struct_vma_stat_info.html#ab0c6c73837e5a70c749fbd4f6064895a">usedBytes</a> += srcInfo.<a class="code" href="struct_vma_stat_info.html#ab0c6c73837e5a70c749fbd4f6064895a">usedBytes</a>;</div>
+<div class="line"><a name="l12008"></a><span class="lineno">12008</span>&#160;    inoutInfo.<a class="code" href="struct_vma_stat_info.html#a1859d290aca2cd582d8dc25922092669">unusedBytes</a> += srcInfo.<a class="code" href="struct_vma_stat_info.html#a1859d290aca2cd582d8dc25922092669">unusedBytes</a>;</div>
+<div class="line"><a name="l12009"></a><span class="lineno">12009</span>&#160;    inoutInfo.<a class="code" href="struct_vma_stat_info.html#ade8b40bd3139c04aabd2fc538a356fea">allocationSizeMin</a> = VMA_MIN(inoutInfo.<a class="code" href="struct_vma_stat_info.html#ade8b40bd3139c04aabd2fc538a356fea">allocationSizeMin</a>, srcInfo.<a class="code" href="struct_vma_stat_info.html#ade8b40bd3139c04aabd2fc538a356fea">allocationSizeMin</a>);</div>
+<div class="line"><a name="l12010"></a><span class="lineno">12010</span>&#160;    inoutInfo.<a class="code" href="struct_vma_stat_info.html#a17e9733a5ecd76287d4db6e66f71f50c">allocationSizeMax</a> = VMA_MAX(inoutInfo.<a class="code" href="struct_vma_stat_info.html#a17e9733a5ecd76287d4db6e66f71f50c">allocationSizeMax</a>, srcInfo.<a class="code" href="struct_vma_stat_info.html#a17e9733a5ecd76287d4db6e66f71f50c">allocationSizeMax</a>);</div>
+<div class="line"><a name="l12011"></a><span class="lineno">12011</span>&#160;    inoutInfo.<a class="code" href="struct_vma_stat_info.html#aedeba931324f16589cd2416c0d2dd0d4">unusedRangeSizeMin</a> = VMA_MIN(inoutInfo.<a class="code" href="struct_vma_stat_info.html#aedeba931324f16589cd2416c0d2dd0d4">unusedRangeSizeMin</a>, srcInfo.<a class="code" href="struct_vma_stat_info.html#aedeba931324f16589cd2416c0d2dd0d4">unusedRangeSizeMin</a>);</div>
+<div class="line"><a name="l12012"></a><span class="lineno">12012</span>&#160;    inoutInfo.<a class="code" href="struct_vma_stat_info.html#a5ba1a2476c4d39b10f7e2f7ebbb72ac4">unusedRangeSizeMax</a> = VMA_MAX(inoutInfo.<a class="code" href="struct_vma_stat_info.html#a5ba1a2476c4d39b10f7e2f7ebbb72ac4">unusedRangeSizeMax</a>, srcInfo.<a class="code" href="struct_vma_stat_info.html#a5ba1a2476c4d39b10f7e2f7ebbb72ac4">unusedRangeSizeMax</a>);</div>
+<div class="line"><a name="l12013"></a><span class="lineno">12013</span>&#160;}</div>
+<div class="line"><a name="l12014"></a><span class="lineno">12014</span>&#160; </div>
+<div class="line"><a name="l12015"></a><span class="lineno">12015</span>&#160;<span class="keyword">static</span> <span class="keywordtype">void</span> VmaPostprocessCalcStatInfo(<a class="code" href="struct_vma_stat_info.html">VmaStatInfo</a>&amp; inoutInfo)</div>
+<div class="line"><a name="l12016"></a><span class="lineno">12016</span>&#160;{</div>
+<div class="line"><a name="l12017"></a><span class="lineno">12017</span>&#160;    inoutInfo.<a class="code" href="struct_vma_stat_info.html#a1081a039964e566c672e7a2347f9e599">allocationSizeAvg</a> = (inoutInfo.<a class="code" href="struct_vma_stat_info.html#a537741e4d5cdddc1c0ab95ec650afaff">allocationCount</a> &gt; 0) ?</div>
+<div class="line"><a name="l12018"></a><span class="lineno">12018</span>&#160;        VmaRoundDiv&lt;VkDeviceSize&gt;(inoutInfo.<a class="code" href="struct_vma_stat_info.html#ab0c6c73837e5a70c749fbd4f6064895a">usedBytes</a>, inoutInfo.<a class="code" href="struct_vma_stat_info.html#a537741e4d5cdddc1c0ab95ec650afaff">allocationCount</a>) : 0;</div>
+<div class="line"><a name="l12019"></a><span class="lineno">12019</span>&#160;    inoutInfo.<a class="code" href="struct_vma_stat_info.html#a2f9b3452af90c9768a30b7fb6ae194fc">unusedRangeSizeAvg</a> = (inoutInfo.<a class="code" href="struct_vma_stat_info.html#ae06129c771bfebfd6468a7f4276502a9">unusedRangeCount</a> &gt; 0) ?</div>
+<div class="line"><a name="l12020"></a><span class="lineno">12020</span>&#160;        VmaRoundDiv&lt;VkDeviceSize&gt;(inoutInfo.<a class="code" href="struct_vma_stat_info.html#a1859d290aca2cd582d8dc25922092669">unusedBytes</a>, inoutInfo.<a class="code" href="struct_vma_stat_info.html#ae06129c771bfebfd6468a7f4276502a9">unusedRangeCount</a>) : 0;</div>
+<div class="line"><a name="l12021"></a><span class="lineno">12021</span>&#160;}</div>
+<div class="line"><a name="l12022"></a><span class="lineno">12022</span>&#160; </div>
+<div class="line"><a name="l12023"></a><span class="lineno">12023</span>&#160;VmaPool_T::VmaPool_T(</div>
+<div class="line"><a name="l12024"></a><span class="lineno">12024</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator,</div>
+<div class="line"><a name="l12025"></a><span class="lineno">12025</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_pool_create_info.html">VmaPoolCreateInfo</a>&amp; createInfo,</div>
+<div class="line"><a name="l12026"></a><span class="lineno">12026</span>&#160;    VkDeviceSize preferredBlockSize) :</div>
+<div class="line"><a name="l12027"></a><span class="lineno">12027</span>&#160;    m_BlockVector(</div>
+<div class="line"><a name="l12028"></a><span class="lineno">12028</span>&#160;        hAllocator,</div>
+<div class="line"><a name="l12029"></a><span class="lineno">12029</span>&#160;        this, <span class="comment">// hParentPool</span></div>
+<div class="line"><a name="l12030"></a><span class="lineno">12030</span>&#160;        createInfo.memoryTypeIndex,</div>
+<div class="line"><a name="l12031"></a><span class="lineno">12031</span>&#160;        createInfo.blockSize != 0 ? createInfo.blockSize : preferredBlockSize,</div>
+<div class="line"><a name="l12032"></a><span class="lineno">12032</span>&#160;        createInfo.minBlockCount,</div>
+<div class="line"><a name="l12033"></a><span class="lineno">12033</span>&#160;        createInfo.maxBlockCount,</div>
+<div class="line"><a name="l12034"></a><span class="lineno">12034</span>&#160;        (createInfo.flags &amp; <a class="code" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a9f1a499508a8edb4e8ba40aa0290a3d2">VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT</a>) != 0 ? 1 : hAllocator-&gt;GetBufferImageGranularity(),</div>
+<div class="line"><a name="l12035"></a><span class="lineno">12035</span>&#160;        createInfo.frameInUseCount,</div>
+<div class="line"><a name="l12036"></a><span class="lineno">12036</span>&#160;        createInfo.blockSize != 0, <span class="comment">// explicitBlockSize</span></div>
+<div class="line"><a name="l12037"></a><span class="lineno">12037</span>&#160;        createInfo.flags &amp; <a class="code" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7af4d270f8f42517a0f70037ceb6ac1d9c">VMA_POOL_CREATE_ALGORITHM_MASK</a>), <span class="comment">// algorithm</span></div>
+<div class="line"><a name="l12038"></a><span class="lineno">12038</span>&#160;    m_Id(0),</div>
+<div class="line"><a name="l12039"></a><span class="lineno">12039</span>&#160;    m_Name(VMA_NULL)</div>
+<div class="line"><a name="l12040"></a><span class="lineno">12040</span>&#160;{</div>
+<div class="line"><a name="l12041"></a><span class="lineno">12041</span>&#160;}</div>
+<div class="line"><a name="l12042"></a><span class="lineno">12042</span>&#160; </div>
+<div class="line"><a name="l12043"></a><span class="lineno">12043</span>&#160;VmaPool_T::~VmaPool_T()</div>
+<div class="line"><a name="l12044"></a><span class="lineno">12044</span>&#160;{</div>
+<div class="line"><a name="l12045"></a><span class="lineno">12045</span>&#160;}</div>
+<div class="line"><a name="l12046"></a><span class="lineno">12046</span>&#160; </div>
+<div class="line"><a name="l12047"></a><span class="lineno">12047</span>&#160;<span class="keywordtype">void</span> VmaPool_T::SetName(<span class="keyword">const</span> <span class="keywordtype">char</span>* pName)</div>
+<div class="line"><a name="l12048"></a><span class="lineno">12048</span>&#160;{</div>
+<div class="line"><a name="l12049"></a><span class="lineno">12049</span>&#160;    <span class="keyword">const</span> VkAllocationCallbacks* allocs = m_BlockVector.GetAllocator()-&gt;GetAllocationCallbacks();</div>
+<div class="line"><a name="l12050"></a><span class="lineno">12050</span>&#160;    VmaFreeString(allocs, m_Name);</div>
+<div class="line"><a name="l12051"></a><span class="lineno">12051</span>&#160;    </div>
+<div class="line"><a name="l12052"></a><span class="lineno">12052</span>&#160;    <span class="keywordflow">if</span>(pName != VMA_NULL)</div>
+<div class="line"><a name="l12053"></a><span class="lineno">12053</span>&#160;    {</div>
+<div class="line"><a name="l12054"></a><span class="lineno">12054</span>&#160;        m_Name = VmaCreateStringCopy(allocs, pName);</div>
+<div class="line"><a name="l12055"></a><span class="lineno">12055</span>&#160;    }</div>
+<div class="line"><a name="l12056"></a><span class="lineno">12056</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l12057"></a><span class="lineno">12057</span>&#160;    {</div>
+<div class="line"><a name="l12058"></a><span class="lineno">12058</span>&#160;        m_Name = VMA_NULL;</div>
+<div class="line"><a name="l12059"></a><span class="lineno">12059</span>&#160;    }</div>
+<div class="line"><a name="l12060"></a><span class="lineno">12060</span>&#160;}</div>
+<div class="line"><a name="l12061"></a><span class="lineno">12061</span>&#160; </div>
+<div class="line"><a name="l12062"></a><span class="lineno">12062</span>&#160;<span class="preprocessor">#if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l12063"></a><span class="lineno">12063</span>&#160; </div>
+<div class="line"><a name="l12064"></a><span class="lineno">12064</span>&#160;<span class="preprocessor">#endif // #if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l12065"></a><span class="lineno">12065</span>&#160; </div>
+<div class="line"><a name="l12066"></a><span class="lineno">12066</span>&#160;VmaBlockVector::VmaBlockVector(</div>
+<div class="line"><a name="l12067"></a><span class="lineno">12067</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator,</div>
+<div class="line"><a name="l12068"></a><span class="lineno">12068</span>&#160;    <a class="code" href="struct_vma_pool.html">VmaPool</a> hParentPool,</div>
+<div class="line"><a name="l12069"></a><span class="lineno">12069</span>&#160;    uint32_t memoryTypeIndex,</div>
+<div class="line"><a name="l12070"></a><span class="lineno">12070</span>&#160;    VkDeviceSize preferredBlockSize,</div>
+<div class="line"><a name="l12071"></a><span class="lineno">12071</span>&#160;    <span class="keywordtype">size_t</span> minBlockCount,</div>
+<div class="line"><a name="l12072"></a><span class="lineno">12072</span>&#160;    <span class="keywordtype">size_t</span> maxBlockCount,</div>
+<div class="line"><a name="l12073"></a><span class="lineno">12073</span>&#160;    VkDeviceSize bufferImageGranularity,</div>
+<div class="line"><a name="l12074"></a><span class="lineno">12074</span>&#160;    uint32_t frameInUseCount,</div>
+<div class="line"><a name="l12075"></a><span class="lineno">12075</span>&#160;    <span class="keywordtype">bool</span> explicitBlockSize,</div>
+<div class="line"><a name="l12076"></a><span class="lineno">12076</span>&#160;    uint32_t algorithm) :</div>
+<div class="line"><a name="l12077"></a><span class="lineno">12077</span>&#160;    m_hAllocator(hAllocator),</div>
+<div class="line"><a name="l12078"></a><span class="lineno">12078</span>&#160;    m_hParentPool(hParentPool),</div>
+<div class="line"><a name="l12079"></a><span class="lineno">12079</span>&#160;    m_MemoryTypeIndex(memoryTypeIndex),</div>
+<div class="line"><a name="l12080"></a><span class="lineno">12080</span>&#160;    m_PreferredBlockSize(preferredBlockSize),</div>
+<div class="line"><a name="l12081"></a><span class="lineno">12081</span>&#160;    m_MinBlockCount(minBlockCount),</div>
+<div class="line"><a name="l12082"></a><span class="lineno">12082</span>&#160;    m_MaxBlockCount(maxBlockCount),</div>
+<div class="line"><a name="l12083"></a><span class="lineno">12083</span>&#160;    m_BufferImageGranularity(bufferImageGranularity),</div>
+<div class="line"><a name="l12084"></a><span class="lineno">12084</span>&#160;    m_FrameInUseCount(frameInUseCount),</div>
+<div class="line"><a name="l12085"></a><span class="lineno">12085</span>&#160;    m_ExplicitBlockSize(explicitBlockSize),</div>
+<div class="line"><a name="l12086"></a><span class="lineno">12086</span>&#160;    m_Algorithm(algorithm),</div>
+<div class="line"><a name="l12087"></a><span class="lineno">12087</span>&#160;    m_HasEmptyBlock(false),</div>
+<div class="line"><a name="l12088"></a><span class="lineno">12088</span>&#160;    m_Blocks(VmaStlAllocator&lt;VmaDeviceMemoryBlock*&gt;(hAllocator-&gt;GetAllocationCallbacks())),</div>
+<div class="line"><a name="l12089"></a><span class="lineno">12089</span>&#160;    m_NextBlockId(0)</div>
+<div class="line"><a name="l12090"></a><span class="lineno">12090</span>&#160;{</div>
+<div class="line"><a name="l12091"></a><span class="lineno">12091</span>&#160;}</div>
+<div class="line"><a name="l12092"></a><span class="lineno">12092</span>&#160; </div>
+<div class="line"><a name="l12093"></a><span class="lineno">12093</span>&#160;VmaBlockVector::~VmaBlockVector()</div>
+<div class="line"><a name="l12094"></a><span class="lineno">12094</span>&#160;{</div>
+<div class="line"><a name="l12095"></a><span class="lineno">12095</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = m_Blocks.size(); i--; )</div>
+<div class="line"><a name="l12096"></a><span class="lineno">12096</span>&#160;    {</div>
+<div class="line"><a name="l12097"></a><span class="lineno">12097</span>&#160;        m_Blocks[i]-&gt;Destroy(m_hAllocator);</div>
+<div class="line"><a name="l12098"></a><span class="lineno">12098</span>&#160;        vma_delete(m_hAllocator, m_Blocks[i]);</div>
+<div class="line"><a name="l12099"></a><span class="lineno">12099</span>&#160;    }</div>
+<div class="line"><a name="l12100"></a><span class="lineno">12100</span>&#160;}</div>
+<div class="line"><a name="l12101"></a><span class="lineno">12101</span>&#160; </div>
+<div class="line"><a name="l12102"></a><span class="lineno">12102</span>&#160;VkResult VmaBlockVector::CreateMinBlocks()</div>
+<div class="line"><a name="l12103"></a><span class="lineno">12103</span>&#160;{</div>
+<div class="line"><a name="l12104"></a><span class="lineno">12104</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = 0; i &lt; m_MinBlockCount; ++i)</div>
+<div class="line"><a name="l12105"></a><span class="lineno">12105</span>&#160;    {</div>
+<div class="line"><a name="l12106"></a><span class="lineno">12106</span>&#160;        VkResult res = CreateBlock(m_PreferredBlockSize, VMA_NULL);</div>
+<div class="line"><a name="l12107"></a><span class="lineno">12107</span>&#160;        <span class="keywordflow">if</span>(res != VK_SUCCESS)</div>
+<div class="line"><a name="l12108"></a><span class="lineno">12108</span>&#160;        {</div>
+<div class="line"><a name="l12109"></a><span class="lineno">12109</span>&#160;            <span class="keywordflow">return</span> res;</div>
+<div class="line"><a name="l12110"></a><span class="lineno">12110</span>&#160;        }</div>
+<div class="line"><a name="l12111"></a><span class="lineno">12111</span>&#160;    }</div>
+<div class="line"><a name="l12112"></a><span class="lineno">12112</span>&#160;    <span class="keywordflow">return</span> VK_SUCCESS;</div>
+<div class="line"><a name="l12113"></a><span class="lineno">12113</span>&#160;}</div>
+<div class="line"><a name="l12114"></a><span class="lineno">12114</span>&#160; </div>
+<div class="line"><a name="l12115"></a><span class="lineno">12115</span>&#160;<span class="keywordtype">void</span> VmaBlockVector::GetPoolStats(<a class="code" href="struct_vma_pool_stats.html">VmaPoolStats</a>* pStats)</div>
+<div class="line"><a name="l12116"></a><span class="lineno">12116</span>&#160;{</div>
+<div class="line"><a name="l12117"></a><span class="lineno">12117</span>&#160;    VmaMutexLockRead lock(m_Mutex, m_hAllocator-&gt;m_UseMutex);</div>
+<div class="line"><a name="l12118"></a><span class="lineno">12118</span>&#160; </div>
+<div class="line"><a name="l12119"></a><span class="lineno">12119</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">size_t</span> blockCount = m_Blocks.size();</div>
+<div class="line"><a name="l12120"></a><span class="lineno">12120</span>&#160; </div>
+<div class="line"><a name="l12121"></a><span class="lineno">12121</span>&#160;    pStats-&gt;<a class="code" href="struct_vma_pool_stats.html#a326807b2de2b0931cee4ed9a5f2e420c">size</a> = 0;</div>
+<div class="line"><a name="l12122"></a><span class="lineno">12122</span>&#160;    pStats-&gt;<a class="code" href="struct_vma_pool_stats.html#ad7c54874724fce7b06aba526202d82a8">unusedSize</a> = 0;</div>
+<div class="line"><a name="l12123"></a><span class="lineno">12123</span>&#160;    pStats-&gt;<a class="code" href="struct_vma_pool_stats.html#ad1924eb54fffa45e9e0e65670c8fe5eb">allocationCount</a> = 0;</div>
+<div class="line"><a name="l12124"></a><span class="lineno">12124</span>&#160;    pStats-&gt;<a class="code" href="struct_vma_pool_stats.html#ae4f3546ffa4d1e598b64d8e6134854f4">unusedRangeCount</a> = 0;</div>
+<div class="line"><a name="l12125"></a><span class="lineno">12125</span>&#160;    pStats-&gt;<a class="code" href="struct_vma_pool_stats.html#ab4c8f52dd42ab01998f60f0b6acc722b">unusedRangeSizeMax</a> = 0;</div>
+<div class="line"><a name="l12126"></a><span class="lineno">12126</span>&#160;    pStats-&gt;<a class="code" href="struct_vma_pool_stats.html#aa0b5cb45cef6f18571cefb03b9a230e7">blockCount</a> = blockCount;</div>
+<div class="line"><a name="l12127"></a><span class="lineno">12127</span>&#160; </div>
+<div class="line"><a name="l12128"></a><span class="lineno">12128</span>&#160;    <span class="keywordflow">for</span>(uint32_t blockIndex = 0; blockIndex &lt; blockCount; ++blockIndex)</div>
+<div class="line"><a name="l12129"></a><span class="lineno">12129</span>&#160;    {</div>
+<div class="line"><a name="l12130"></a><span class="lineno">12130</span>&#160;        <span class="keyword">const</span> VmaDeviceMemoryBlock* <span class="keyword">const</span> pBlock = m_Blocks[blockIndex];</div>
+<div class="line"><a name="l12131"></a><span class="lineno">12131</span>&#160;        VMA_ASSERT(pBlock);</div>
+<div class="line"><a name="l12132"></a><span class="lineno">12132</span>&#160;        VMA_HEAVY_ASSERT(pBlock-&gt;Validate());</div>
+<div class="line"><a name="l12133"></a><span class="lineno">12133</span>&#160;        pBlock-&gt;m_pMetadata-&gt;AddPoolStats(*pStats);</div>
+<div class="line"><a name="l12134"></a><span class="lineno">12134</span>&#160;    }</div>
+<div class="line"><a name="l12135"></a><span class="lineno">12135</span>&#160;}</div>
+<div class="line"><a name="l12136"></a><span class="lineno">12136</span>&#160; </div>
+<div class="line"><a name="l12137"></a><span class="lineno">12137</span>&#160;<span class="keywordtype">bool</span> VmaBlockVector::IsEmpty()</div>
+<div class="line"><a name="l12138"></a><span class="lineno">12138</span>&#160;{</div>
+<div class="line"><a name="l12139"></a><span class="lineno">12139</span>&#160;    VmaMutexLockRead lock(m_Mutex, m_hAllocator-&gt;m_UseMutex);</div>
+<div class="line"><a name="l12140"></a><span class="lineno">12140</span>&#160;    <span class="keywordflow">return</span> m_Blocks.empty();</div>
+<div class="line"><a name="l12141"></a><span class="lineno">12141</span>&#160;}</div>
+<div class="line"><a name="l12142"></a><span class="lineno">12142</span>&#160; </div>
+<div class="line"><a name="l12143"></a><span class="lineno">12143</span>&#160;<span class="keywordtype">bool</span> VmaBlockVector::IsCorruptionDetectionEnabled()<span class="keyword"> const</span></div>
+<div class="line"><a name="l12144"></a><span class="lineno">12144</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l12145"></a><span class="lineno">12145</span>&#160;    <span class="keyword">const</span> uint32_t requiredMemFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;</div>
+<div class="line"><a name="l12146"></a><span class="lineno">12146</span>&#160;    <span class="keywordflow">return</span> (VMA_DEBUG_DETECT_CORRUPTION != 0) &amp;&amp;</div>
+<div class="line"><a name="l12147"></a><span class="lineno">12147</span>&#160;        (VMA_DEBUG_MARGIN &gt; 0) &amp;&amp;</div>
+<div class="line"><a name="l12148"></a><span class="lineno">12148</span>&#160;        (m_Algorithm == 0 || m_Algorithm == <a class="code" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a13c8a444197c67866be9cb05599fc726">VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT</a>) &amp;&amp;</div>
+<div class="line"><a name="l12149"></a><span class="lineno">12149</span>&#160;        (m_hAllocator-&gt;m_MemProps.memoryTypes[m_MemoryTypeIndex].propertyFlags &amp; requiredMemFlags) == requiredMemFlags;</div>
+<div class="line"><a name="l12150"></a><span class="lineno">12150</span>&#160;}</div>
+<div class="line"><a name="l12151"></a><span class="lineno">12151</span>&#160; </div>
+<div class="line"><a name="l12152"></a><span class="lineno">12152</span>&#160;<span class="keyword">static</span> <span class="keyword">const</span> uint32_t VMA_ALLOCATION_TRY_COUNT = 32;</div>
+<div class="line"><a name="l12153"></a><span class="lineno">12153</span>&#160; </div>
+<div class="line"><a name="l12154"></a><span class="lineno">12154</span>&#160;VkResult VmaBlockVector::Allocate(</div>
+<div class="line"><a name="l12155"></a><span class="lineno">12155</span>&#160;    uint32_t currentFrameIndex,</div>
+<div class="line"><a name="l12156"></a><span class="lineno">12156</span>&#160;    VkDeviceSize size,</div>
+<div class="line"><a name="l12157"></a><span class="lineno">12157</span>&#160;    VkDeviceSize alignment,</div>
+<div class="line"><a name="l12158"></a><span class="lineno">12158</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>&amp; createInfo,</div>
+<div class="line"><a name="l12159"></a><span class="lineno">12159</span>&#160;    VmaSuballocationType suballocType,</div>
+<div class="line"><a name="l12160"></a><span class="lineno">12160</span>&#160;    <span class="keywordtype">size_t</span> allocationCount,</div>
+<div class="line"><a name="l12161"></a><span class="lineno">12161</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocations)</div>
+<div class="line"><a name="l12162"></a><span class="lineno">12162</span>&#160;{</div>
+<div class="line"><a name="l12163"></a><span class="lineno">12163</span>&#160;    <span class="keywordtype">size_t</span> allocIndex;</div>
+<div class="line"><a name="l12164"></a><span class="lineno">12164</span>&#160;    VkResult res = VK_SUCCESS;</div>
+<div class="line"><a name="l12165"></a><span class="lineno">12165</span>&#160; </div>
+<div class="line"><a name="l12166"></a><span class="lineno">12166</span>&#160;    <span class="keywordflow">if</span>(IsCorruptionDetectionEnabled())</div>
+<div class="line"><a name="l12167"></a><span class="lineno">12167</span>&#160;    {</div>
+<div class="line"><a name="l12168"></a><span class="lineno">12168</span>&#160;        size = VmaAlignUp&lt;VkDeviceSize&gt;(size, <span class="keyword">sizeof</span>(VMA_CORRUPTION_DETECTION_MAGIC_VALUE));</div>
+<div class="line"><a name="l12169"></a><span class="lineno">12169</span>&#160;        alignment = VmaAlignUp&lt;VkDeviceSize&gt;(alignment, <span class="keyword">sizeof</span>(VMA_CORRUPTION_DETECTION_MAGIC_VALUE));</div>
+<div class="line"><a name="l12170"></a><span class="lineno">12170</span>&#160;    }</div>
+<div class="line"><a name="l12171"></a><span class="lineno">12171</span>&#160; </div>
+<div class="line"><a name="l12172"></a><span class="lineno">12172</span>&#160;    {</div>
+<div class="line"><a name="l12173"></a><span class="lineno">12173</span>&#160;        VmaMutexLockWrite lock(m_Mutex, m_hAllocator-&gt;m_UseMutex);</div>
+<div class="line"><a name="l12174"></a><span class="lineno">12174</span>&#160;        <span class="keywordflow">for</span>(allocIndex = 0; allocIndex &lt; allocationCount; ++allocIndex)</div>
+<div class="line"><a name="l12175"></a><span class="lineno">12175</span>&#160;        {</div>
+<div class="line"><a name="l12176"></a><span class="lineno">12176</span>&#160;            res = AllocatePage(</div>
+<div class="line"><a name="l12177"></a><span class="lineno">12177</span>&#160;                currentFrameIndex,</div>
+<div class="line"><a name="l12178"></a><span class="lineno">12178</span>&#160;                size,</div>
+<div class="line"><a name="l12179"></a><span class="lineno">12179</span>&#160;                alignment,</div>
+<div class="line"><a name="l12180"></a><span class="lineno">12180</span>&#160;                createInfo,</div>
+<div class="line"><a name="l12181"></a><span class="lineno">12181</span>&#160;                suballocType,</div>
+<div class="line"><a name="l12182"></a><span class="lineno">12182</span>&#160;                pAllocations + allocIndex);</div>
+<div class="line"><a name="l12183"></a><span class="lineno">12183</span>&#160;            <span class="keywordflow">if</span>(res != VK_SUCCESS)</div>
+<div class="line"><a name="l12184"></a><span class="lineno">12184</span>&#160;            {</div>
+<div class="line"><a name="l12185"></a><span class="lineno">12185</span>&#160;                <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l12186"></a><span class="lineno">12186</span>&#160;            }</div>
+<div class="line"><a name="l12187"></a><span class="lineno">12187</span>&#160;        }</div>
+<div class="line"><a name="l12188"></a><span class="lineno">12188</span>&#160;    }</div>
+<div class="line"><a name="l12189"></a><span class="lineno">12189</span>&#160; </div>
+<div class="line"><a name="l12190"></a><span class="lineno">12190</span>&#160;    <span class="keywordflow">if</span>(res != VK_SUCCESS)</div>
+<div class="line"><a name="l12191"></a><span class="lineno">12191</span>&#160;    {</div>
+<div class="line"><a name="l12192"></a><span class="lineno">12192</span>&#160;        <span class="comment">// Free all already created allocations.</span></div>
+<div class="line"><a name="l12193"></a><span class="lineno">12193</span>&#160;        <span class="keywordflow">while</span>(allocIndex--)</div>
+<div class="line"><a name="l12194"></a><span class="lineno">12194</span>&#160;        {</div>
+<div class="line"><a name="l12195"></a><span class="lineno">12195</span>&#160;            Free(pAllocations[allocIndex]);</div>
+<div class="line"><a name="l12196"></a><span class="lineno">12196</span>&#160;        }</div>
+<div class="line"><a name="l12197"></a><span class="lineno">12197</span>&#160;        memset(pAllocations, 0, <span class="keyword">sizeof</span>(<a class="code" href="struct_vma_allocation.html">VmaAllocation</a>) * allocationCount);</div>
+<div class="line"><a name="l12198"></a><span class="lineno">12198</span>&#160;    }</div>
+<div class="line"><a name="l12199"></a><span class="lineno">12199</span>&#160; </div>
+<div class="line"><a name="l12200"></a><span class="lineno">12200</span>&#160;    <span class="keywordflow">return</span> res;</div>
+<div class="line"><a name="l12201"></a><span class="lineno">12201</span>&#160;}</div>
+<div class="line"><a name="l12202"></a><span class="lineno">12202</span>&#160; </div>
+<div class="line"><a name="l12203"></a><span class="lineno">12203</span>&#160;VkResult VmaBlockVector::AllocatePage(</div>
+<div class="line"><a name="l12204"></a><span class="lineno">12204</span>&#160;    uint32_t currentFrameIndex,</div>
+<div class="line"><a name="l12205"></a><span class="lineno">12205</span>&#160;    VkDeviceSize size,</div>
+<div class="line"><a name="l12206"></a><span class="lineno">12206</span>&#160;    VkDeviceSize alignment,</div>
+<div class="line"><a name="l12207"></a><span class="lineno">12207</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>&amp; createInfo,</div>
+<div class="line"><a name="l12208"></a><span class="lineno">12208</span>&#160;    VmaSuballocationType suballocType,</div>
+<div class="line"><a name="l12209"></a><span class="lineno">12209</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocation)</div>
+<div class="line"><a name="l12210"></a><span class="lineno">12210</span>&#160;{</div>
+<div class="line"><a name="l12211"></a><span class="lineno">12211</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">bool</span> isUpperAddress = (createInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a> &amp; <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a42ba3a2d2c7117953210b7c3ef8da0df">VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT</a>) != 0;</div>
+<div class="line"><a name="l12212"></a><span class="lineno">12212</span>&#160;    <span class="keywordtype">bool</span> canMakeOtherLost = (createInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a> &amp; <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a68686d0ce9beb0d4d1b9f2b8b1389a7e">VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT</a>) != 0;</div>
+<div class="line"><a name="l12213"></a><span class="lineno">12213</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">bool</span> mapped = (createInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a> &amp; <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a11da372cc3a82931c5e5d6146cd9dd1f">VMA_ALLOCATION_CREATE_MAPPED_BIT</a>) != 0;</div>
+<div class="line"><a name="l12214"></a><span class="lineno">12214</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">bool</span> isUserDataString = (createInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a> &amp; <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597aa6f24f821cd6a7c5e4a443f7bf59c520">VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT</a>) != 0;</div>
+<div class="line"><a name="l12215"></a><span class="lineno">12215</span>&#160;    </div>
+<div class="line"><a name="l12216"></a><span class="lineno">12216</span>&#160;    VkDeviceSize freeMemory;</div>
+<div class="line"><a name="l12217"></a><span class="lineno">12217</span>&#160;    {</div>
+<div class="line"><a name="l12218"></a><span class="lineno">12218</span>&#160;        <span class="keyword">const</span> uint32_t heapIndex = m_hAllocator-&gt;MemoryTypeIndexToHeapIndex(m_MemoryTypeIndex);</div>
+<div class="line"><a name="l12219"></a><span class="lineno">12219</span>&#160;        <a class="code" href="struct_vma_budget.html">VmaBudget</a> heapBudget = {};</div>
+<div class="line"><a name="l12220"></a><span class="lineno">12220</span>&#160;        m_hAllocator-&gt;GetBudget(&amp;heapBudget, heapIndex, 1);</div>
+<div class="line"><a name="l12221"></a><span class="lineno">12221</span>&#160;        freeMemory = (heapBudget.<a class="code" href="struct_vma_budget.html#a84dd1ecca8b0110259eb206dbadb11f6">usage</a> &lt; heapBudget.<a class="code" href="struct_vma_budget.html#ab82e1d1754c2d210d0bdf90220bc6cdd">budget</a>) ? (heapBudget.<a class="code" href="struct_vma_budget.html#ab82e1d1754c2d210d0bdf90220bc6cdd">budget</a> - heapBudget.<a class="code" href="struct_vma_budget.html#a84dd1ecca8b0110259eb206dbadb11f6">usage</a>) : 0;</div>
+<div class="line"><a name="l12222"></a><span class="lineno">12222</span>&#160;    }</div>
+<div class="line"><a name="l12223"></a><span class="lineno">12223</span>&#160;    </div>
+<div class="line"><a name="l12224"></a><span class="lineno">12224</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">bool</span> canFallbackToDedicated = !IsCustomPool();</div>
+<div class="line"><a name="l12225"></a><span class="lineno">12225</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">bool</span> canCreateNewBlock =</div>
+<div class="line"><a name="l12226"></a><span class="lineno">12226</span>&#160;        ((createInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a> &amp; <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a89759603401014eb325eb22a3839f2ff">VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT</a>) == 0) &amp;&amp;</div>
+<div class="line"><a name="l12227"></a><span class="lineno">12227</span>&#160;        (m_Blocks.size() &lt; m_MaxBlockCount) &amp;&amp;</div>
+<div class="line"><a name="l12228"></a><span class="lineno">12228</span>&#160;        (freeMemory &gt;= size || !canFallbackToDedicated);</div>
+<div class="line"><a name="l12229"></a><span class="lineno">12229</span>&#160;    uint32_t strategy = createInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a> &amp; <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a8e16845d81ae3d27c47106d4770d5c7e">VMA_ALLOCATION_CREATE_STRATEGY_MASK</a>;</div>
+<div class="line"><a name="l12230"></a><span class="lineno">12230</span>&#160; </div>
+<div class="line"><a name="l12231"></a><span class="lineno">12231</span>&#160;    <span class="comment">// If linearAlgorithm is used, canMakeOtherLost is available only when used as ring buffer.</span></div>
+<div class="line"><a name="l12232"></a><span class="lineno">12232</span>&#160;    <span class="comment">// Which in turn is available only when maxBlockCount = 1.</span></div>
+<div class="line"><a name="l12233"></a><span class="lineno">12233</span>&#160;    <span class="keywordflow">if</span>(m_Algorithm == <a class="code" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a13c8a444197c67866be9cb05599fc726">VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT</a> &amp;&amp; m_MaxBlockCount &gt; 1)</div>
+<div class="line"><a name="l12234"></a><span class="lineno">12234</span>&#160;    {</div>
+<div class="line"><a name="l12235"></a><span class="lineno">12235</span>&#160;        canMakeOtherLost = <span class="keyword">false</span>;</div>
+<div class="line"><a name="l12236"></a><span class="lineno">12236</span>&#160;    }</div>
+<div class="line"><a name="l12237"></a><span class="lineno">12237</span>&#160; </div>
+<div class="line"><a name="l12238"></a><span class="lineno">12238</span>&#160;    <span class="comment">// Upper address can only be used with linear allocator and within single memory block.</span></div>
+<div class="line"><a name="l12239"></a><span class="lineno">12239</span>&#160;    <span class="keywordflow">if</span>(isUpperAddress &amp;&amp;</div>
+<div class="line"><a name="l12240"></a><span class="lineno">12240</span>&#160;        (m_Algorithm != <a class="code" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a13c8a444197c67866be9cb05599fc726">VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT</a> || m_MaxBlockCount &gt; 1))</div>
+<div class="line"><a name="l12241"></a><span class="lineno">12241</span>&#160;    {</div>
+<div class="line"><a name="l12242"></a><span class="lineno">12242</span>&#160;        <span class="keywordflow">return</span> VK_ERROR_FEATURE_NOT_PRESENT;</div>
+<div class="line"><a name="l12243"></a><span class="lineno">12243</span>&#160;    }</div>
+<div class="line"><a name="l12244"></a><span class="lineno">12244</span>&#160; </div>
+<div class="line"><a name="l12245"></a><span class="lineno">12245</span>&#160;    <span class="comment">// Validate strategy.</span></div>
+<div class="line"><a name="l12246"></a><span class="lineno">12246</span>&#160;    <span class="keywordflow">switch</span>(strategy)</div>
+<div class="line"><a name="l12247"></a><span class="lineno">12247</span>&#160;    {</div>
+<div class="line"><a name="l12248"></a><span class="lineno">12248</span>&#160;    <span class="keywordflow">case</span> 0:</div>
+<div class="line"><a name="l12249"></a><span class="lineno">12249</span>&#160;        strategy = <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a839826775c62319466441f86496f036d">VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT</a>;</div>
+<div class="line"><a name="l12250"></a><span class="lineno">12250</span>&#160;        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l12251"></a><span class="lineno">12251</span>&#160;    <span class="keywordflow">case</span> <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a839826775c62319466441f86496f036d">VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT</a>:</div>
+<div class="line"><a name="l12252"></a><span class="lineno">12252</span>&#160;    <span class="keywordflow">case</span> <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597ad242a04f802e25fef0b880afe8bb0a62">VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT</a>:</div>
+<div class="line"><a name="l12253"></a><span class="lineno">12253</span>&#160;    <span class="keywordflow">case</span> <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a33eb2052674f3ad92386c714a65fb777">VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT</a>:</div>
+<div class="line"><a name="l12254"></a><span class="lineno">12254</span>&#160;        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l12255"></a><span class="lineno">12255</span>&#160;    <span class="keywordflow">default</span>:</div>
+<div class="line"><a name="l12256"></a><span class="lineno">12256</span>&#160;        <span class="keywordflow">return</span> VK_ERROR_FEATURE_NOT_PRESENT;</div>
+<div class="line"><a name="l12257"></a><span class="lineno">12257</span>&#160;    }</div>
+<div class="line"><a name="l12258"></a><span class="lineno">12258</span>&#160; </div>
+<div class="line"><a name="l12259"></a><span class="lineno">12259</span>&#160;    <span class="comment">// Early reject: requested allocation size is larger that maximum block size for this block vector.</span></div>
+<div class="line"><a name="l12260"></a><span class="lineno">12260</span>&#160;    <span class="keywordflow">if</span>(size + 2 * VMA_DEBUG_MARGIN &gt; m_PreferredBlockSize)</div>
+<div class="line"><a name="l12261"></a><span class="lineno">12261</span>&#160;    {</div>
+<div class="line"><a name="l12262"></a><span class="lineno">12262</span>&#160;        <span class="keywordflow">return</span> VK_ERROR_OUT_OF_DEVICE_MEMORY;</div>
+<div class="line"><a name="l12263"></a><span class="lineno">12263</span>&#160;    }</div>
+<div class="line"><a name="l12264"></a><span class="lineno">12264</span>&#160; </div>
+<div class="line"><a name="l12265"></a><span class="lineno">12265</span>&#160;    <span class="comment">/*</span></div>
+<div class="line"><a name="l12266"></a><span class="lineno">12266</span>&#160;<span class="comment">    Under certain condition, this whole section can be skipped for optimization, so</span></div>
+<div class="line"><a name="l12267"></a><span class="lineno">12267</span>&#160;<span class="comment">    we move on directly to trying to allocate with canMakeOtherLost. That&#39;s the case</span></div>
+<div class="line"><a name="l12268"></a><span class="lineno">12268</span>&#160;<span class="comment">    e.g. for custom pools with linear algorithm.</span></div>
+<div class="line"><a name="l12269"></a><span class="lineno">12269</span>&#160;<span class="comment">    */</span></div>
+<div class="line"><a name="l12270"></a><span class="lineno">12270</span>&#160;    <span class="keywordflow">if</span>(!canMakeOtherLost || canCreateNewBlock)</div>
+<div class="line"><a name="l12271"></a><span class="lineno">12271</span>&#160;    {</div>
+<div class="line"><a name="l12272"></a><span class="lineno">12272</span>&#160;        <span class="comment">// 1. Search existing allocations. Try to allocate without making other allocations lost.</span></div>
+<div class="line"><a name="l12273"></a><span class="lineno">12273</span>&#160;        <a class="code" href="vk__mem__alloc_8h.html#a5225e5e11f8376f6a31a1791f3d6e817">VmaAllocationCreateFlags</a> allocFlagsCopy = createInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a>;</div>
+<div class="line"><a name="l12274"></a><span class="lineno">12274</span>&#160;        allocFlagsCopy &amp;= ~<a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a68686d0ce9beb0d4d1b9f2b8b1389a7e">VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT</a>;</div>
+<div class="line"><a name="l12275"></a><span class="lineno">12275</span>&#160; </div>
+<div class="line"><a name="l12276"></a><span class="lineno">12276</span>&#160;        <span class="keywordflow">if</span>(m_Algorithm == <a class="code" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a13c8a444197c67866be9cb05599fc726">VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT</a>)</div>
+<div class="line"><a name="l12277"></a><span class="lineno">12277</span>&#160;        {</div>
+<div class="line"><a name="l12278"></a><span class="lineno">12278</span>&#160;            <span class="comment">// Use only last block.</span></div>
+<div class="line"><a name="l12279"></a><span class="lineno">12279</span>&#160;            <span class="keywordflow">if</span>(!m_Blocks.empty())</div>
+<div class="line"><a name="l12280"></a><span class="lineno">12280</span>&#160;            {</div>
+<div class="line"><a name="l12281"></a><span class="lineno">12281</span>&#160;                VmaDeviceMemoryBlock* <span class="keyword">const</span> pCurrBlock = m_Blocks.back();</div>
+<div class="line"><a name="l12282"></a><span class="lineno">12282</span>&#160;                VMA_ASSERT(pCurrBlock);</div>
+<div class="line"><a name="l12283"></a><span class="lineno">12283</span>&#160;                VkResult res = AllocateFromBlock(</div>
+<div class="line"><a name="l12284"></a><span class="lineno">12284</span>&#160;                    pCurrBlock,</div>
+<div class="line"><a name="l12285"></a><span class="lineno">12285</span>&#160;                    currentFrameIndex,</div>
+<div class="line"><a name="l12286"></a><span class="lineno">12286</span>&#160;                    size,</div>
+<div class="line"><a name="l12287"></a><span class="lineno">12287</span>&#160;                    alignment,</div>
+<div class="line"><a name="l12288"></a><span class="lineno">12288</span>&#160;                    allocFlagsCopy,</div>
+<div class="line"><a name="l12289"></a><span class="lineno">12289</span>&#160;                    createInfo.<a class="code" href="struct_vma_allocation_create_info.html#a8259e85c272683434f4abb4ddddffe19">pUserData</a>,</div>
+<div class="line"><a name="l12290"></a><span class="lineno">12290</span>&#160;                    suballocType,</div>
+<div class="line"><a name="l12291"></a><span class="lineno">12291</span>&#160;                    strategy,</div>
+<div class="line"><a name="l12292"></a><span class="lineno">12292</span>&#160;                    pAllocation);</div>
+<div class="line"><a name="l12293"></a><span class="lineno">12293</span>&#160;                <span class="keywordflow">if</span>(res == VK_SUCCESS)</div>
+<div class="line"><a name="l12294"></a><span class="lineno">12294</span>&#160;                {</div>
+<div class="line"><a name="l12295"></a><span class="lineno">12295</span>&#160;                    VMA_DEBUG_LOG(<span class="stringliteral">&quot;    Returned from last block #%u&quot;</span>, pCurrBlock-&gt;GetId());</div>
+<div class="line"><a name="l12296"></a><span class="lineno">12296</span>&#160;                    <span class="keywordflow">return</span> VK_SUCCESS;</div>
+<div class="line"><a name="l12297"></a><span class="lineno">12297</span>&#160;                }</div>
+<div class="line"><a name="l12298"></a><span class="lineno">12298</span>&#160;            }</div>
+<div class="line"><a name="l12299"></a><span class="lineno">12299</span>&#160;        }</div>
+<div class="line"><a name="l12300"></a><span class="lineno">12300</span>&#160;        <span class="keywordflow">else</span></div>
+<div class="line"><a name="l12301"></a><span class="lineno">12301</span>&#160;        {</div>
+<div class="line"><a name="l12302"></a><span class="lineno">12302</span>&#160;            <span class="keywordflow">if</span>(strategy == <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a839826775c62319466441f86496f036d">VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT</a>)</div>
+<div class="line"><a name="l12303"></a><span class="lineno">12303</span>&#160;            {</div>
+<div class="line"><a name="l12304"></a><span class="lineno">12304</span>&#160;                <span class="comment">// Forward order in m_Blocks - prefer blocks with smallest amount of free space.</span></div>
+<div class="line"><a name="l12305"></a><span class="lineno">12305</span>&#160;                <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> blockIndex = 0; blockIndex &lt; m_Blocks.size(); ++blockIndex )</div>
+<div class="line"><a name="l12306"></a><span class="lineno">12306</span>&#160;                {</div>
+<div class="line"><a name="l12307"></a><span class="lineno">12307</span>&#160;                    VmaDeviceMemoryBlock* <span class="keyword">const</span> pCurrBlock = m_Blocks[blockIndex];</div>
+<div class="line"><a name="l12308"></a><span class="lineno">12308</span>&#160;                    VMA_ASSERT(pCurrBlock);</div>
+<div class="line"><a name="l12309"></a><span class="lineno">12309</span>&#160;                    VkResult res = AllocateFromBlock(</div>
+<div class="line"><a name="l12310"></a><span class="lineno">12310</span>&#160;                        pCurrBlock,</div>
+<div class="line"><a name="l12311"></a><span class="lineno">12311</span>&#160;                        currentFrameIndex,</div>
+<div class="line"><a name="l12312"></a><span class="lineno">12312</span>&#160;                        size,</div>
+<div class="line"><a name="l12313"></a><span class="lineno">12313</span>&#160;                        alignment,</div>
+<div class="line"><a name="l12314"></a><span class="lineno">12314</span>&#160;                        allocFlagsCopy,</div>
+<div class="line"><a name="l12315"></a><span class="lineno">12315</span>&#160;                        createInfo.<a class="code" href="struct_vma_allocation_create_info.html#a8259e85c272683434f4abb4ddddffe19">pUserData</a>,</div>
+<div class="line"><a name="l12316"></a><span class="lineno">12316</span>&#160;                        suballocType,</div>
+<div class="line"><a name="l12317"></a><span class="lineno">12317</span>&#160;                        strategy,</div>
+<div class="line"><a name="l12318"></a><span class="lineno">12318</span>&#160;                        pAllocation);</div>
+<div class="line"><a name="l12319"></a><span class="lineno">12319</span>&#160;                    <span class="keywordflow">if</span>(res == VK_SUCCESS)</div>
+<div class="line"><a name="l12320"></a><span class="lineno">12320</span>&#160;                    {</div>
+<div class="line"><a name="l12321"></a><span class="lineno">12321</span>&#160;                        VMA_DEBUG_LOG(<span class="stringliteral">&quot;    Returned from existing block #%u&quot;</span>, pCurrBlock-&gt;GetId());</div>
+<div class="line"><a name="l12322"></a><span class="lineno">12322</span>&#160;                        <span class="keywordflow">return</span> VK_SUCCESS;</div>
+<div class="line"><a name="l12323"></a><span class="lineno">12323</span>&#160;                    }</div>
+<div class="line"><a name="l12324"></a><span class="lineno">12324</span>&#160;                }</div>
+<div class="line"><a name="l12325"></a><span class="lineno">12325</span>&#160;            }</div>
+<div class="line"><a name="l12326"></a><span class="lineno">12326</span>&#160;            <span class="keywordflow">else</span> <span class="comment">// WORST_FIT, FIRST_FIT</span></div>
+<div class="line"><a name="l12327"></a><span class="lineno">12327</span>&#160;            {</div>
+<div class="line"><a name="l12328"></a><span class="lineno">12328</span>&#160;                <span class="comment">// Backward order in m_Blocks - prefer blocks with largest amount of free space.</span></div>
+<div class="line"><a name="l12329"></a><span class="lineno">12329</span>&#160;                <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> blockIndex = m_Blocks.size(); blockIndex--; )</div>
+<div class="line"><a name="l12330"></a><span class="lineno">12330</span>&#160;                {</div>
+<div class="line"><a name="l12331"></a><span class="lineno">12331</span>&#160;                    VmaDeviceMemoryBlock* <span class="keyword">const</span> pCurrBlock = m_Blocks[blockIndex];</div>
+<div class="line"><a name="l12332"></a><span class="lineno">12332</span>&#160;                    VMA_ASSERT(pCurrBlock);</div>
+<div class="line"><a name="l12333"></a><span class="lineno">12333</span>&#160;                    VkResult res = AllocateFromBlock(</div>
+<div class="line"><a name="l12334"></a><span class="lineno">12334</span>&#160;                        pCurrBlock,</div>
+<div class="line"><a name="l12335"></a><span class="lineno">12335</span>&#160;                        currentFrameIndex,</div>
+<div class="line"><a name="l12336"></a><span class="lineno">12336</span>&#160;                        size,</div>
+<div class="line"><a name="l12337"></a><span class="lineno">12337</span>&#160;                        alignment,</div>
+<div class="line"><a name="l12338"></a><span class="lineno">12338</span>&#160;                        allocFlagsCopy,</div>
+<div class="line"><a name="l12339"></a><span class="lineno">12339</span>&#160;                        createInfo.<a class="code" href="struct_vma_allocation_create_info.html#a8259e85c272683434f4abb4ddddffe19">pUserData</a>,</div>
+<div class="line"><a name="l12340"></a><span class="lineno">12340</span>&#160;                        suballocType,</div>
+<div class="line"><a name="l12341"></a><span class="lineno">12341</span>&#160;                        strategy,</div>
+<div class="line"><a name="l12342"></a><span class="lineno">12342</span>&#160;                        pAllocation);</div>
+<div class="line"><a name="l12343"></a><span class="lineno">12343</span>&#160;                    <span class="keywordflow">if</span>(res == VK_SUCCESS)</div>
+<div class="line"><a name="l12344"></a><span class="lineno">12344</span>&#160;                    {</div>
+<div class="line"><a name="l12345"></a><span class="lineno">12345</span>&#160;                        VMA_DEBUG_LOG(<span class="stringliteral">&quot;    Returned from existing block #%u&quot;</span>, pCurrBlock-&gt;GetId());</div>
+<div class="line"><a name="l12346"></a><span class="lineno">12346</span>&#160;                        <span class="keywordflow">return</span> VK_SUCCESS;</div>
+<div class="line"><a name="l12347"></a><span class="lineno">12347</span>&#160;                    }</div>
+<div class="line"><a name="l12348"></a><span class="lineno">12348</span>&#160;                }</div>
+<div class="line"><a name="l12349"></a><span class="lineno">12349</span>&#160;            }</div>
+<div class="line"><a name="l12350"></a><span class="lineno">12350</span>&#160;        }</div>
+<div class="line"><a name="l12351"></a><span class="lineno">12351</span>&#160; </div>
+<div class="line"><a name="l12352"></a><span class="lineno">12352</span>&#160;        <span class="comment">// 2. Try to create new block.</span></div>
+<div class="line"><a name="l12353"></a><span class="lineno">12353</span>&#160;        <span class="keywordflow">if</span>(canCreateNewBlock)</div>
+<div class="line"><a name="l12354"></a><span class="lineno">12354</span>&#160;        {</div>
+<div class="line"><a name="l12355"></a><span class="lineno">12355</span>&#160;            <span class="comment">// Calculate optimal size for new block.</span></div>
+<div class="line"><a name="l12356"></a><span class="lineno">12356</span>&#160;            VkDeviceSize newBlockSize = m_PreferredBlockSize;</div>
+<div class="line"><a name="l12357"></a><span class="lineno">12357</span>&#160;            uint32_t newBlockSizeShift = 0;</div>
+<div class="line"><a name="l12358"></a><span class="lineno">12358</span>&#160;            <span class="keyword">const</span> uint32_t NEW_BLOCK_SIZE_SHIFT_MAX = 3;</div>
+<div class="line"><a name="l12359"></a><span class="lineno">12359</span>&#160; </div>
+<div class="line"><a name="l12360"></a><span class="lineno">12360</span>&#160;            <span class="keywordflow">if</span>(!m_ExplicitBlockSize)</div>
+<div class="line"><a name="l12361"></a><span class="lineno">12361</span>&#160;            {</div>
+<div class="line"><a name="l12362"></a><span class="lineno">12362</span>&#160;                <span class="comment">// Allocate 1/8, 1/4, 1/2 as first blocks.</span></div>
+<div class="line"><a name="l12363"></a><span class="lineno">12363</span>&#160;                <span class="keyword">const</span> VkDeviceSize maxExistingBlockSize = CalcMaxBlockSize();</div>
+<div class="line"><a name="l12364"></a><span class="lineno">12364</span>&#160;                <span class="keywordflow">for</span>(uint32_t i = 0; i &lt; NEW_BLOCK_SIZE_SHIFT_MAX; ++i)</div>
+<div class="line"><a name="l12365"></a><span class="lineno">12365</span>&#160;                {</div>
+<div class="line"><a name="l12366"></a><span class="lineno">12366</span>&#160;                    <span class="keyword">const</span> VkDeviceSize smallerNewBlockSize = newBlockSize / 2;</div>
+<div class="line"><a name="l12367"></a><span class="lineno">12367</span>&#160;                    <span class="keywordflow">if</span>(smallerNewBlockSize &gt; maxExistingBlockSize &amp;&amp; smallerNewBlockSize &gt;= size * 2)</div>
+<div class="line"><a name="l12368"></a><span class="lineno">12368</span>&#160;                    {</div>
+<div class="line"><a name="l12369"></a><span class="lineno">12369</span>&#160;                        newBlockSize = smallerNewBlockSize;</div>
+<div class="line"><a name="l12370"></a><span class="lineno">12370</span>&#160;                        ++newBlockSizeShift;</div>
+<div class="line"><a name="l12371"></a><span class="lineno">12371</span>&#160;                    }</div>
+<div class="line"><a name="l12372"></a><span class="lineno">12372</span>&#160;                    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l12373"></a><span class="lineno">12373</span>&#160;                    {</div>
+<div class="line"><a name="l12374"></a><span class="lineno">12374</span>&#160;                        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l12375"></a><span class="lineno">12375</span>&#160;                    }</div>
+<div class="line"><a name="l12376"></a><span class="lineno">12376</span>&#160;                }</div>
+<div class="line"><a name="l12377"></a><span class="lineno">12377</span>&#160;            }</div>
+<div class="line"><a name="l12378"></a><span class="lineno">12378</span>&#160; </div>
+<div class="line"><a name="l12379"></a><span class="lineno">12379</span>&#160;            <span class="keywordtype">size_t</span> newBlockIndex = 0;</div>
+<div class="line"><a name="l12380"></a><span class="lineno">12380</span>&#160;            VkResult res = (newBlockSize &lt;= freeMemory || !canFallbackToDedicated) ?</div>
+<div class="line"><a name="l12381"></a><span class="lineno">12381</span>&#160;                CreateBlock(newBlockSize, &amp;newBlockIndex) : VK_ERROR_OUT_OF_DEVICE_MEMORY;</div>
+<div class="line"><a name="l12382"></a><span class="lineno">12382</span>&#160;            <span class="comment">// Allocation of this size failed? Try 1/2, 1/4, 1/8 of m_PreferredBlockSize.</span></div>
+<div class="line"><a name="l12383"></a><span class="lineno">12383</span>&#160;            <span class="keywordflow">if</span>(!m_ExplicitBlockSize)</div>
+<div class="line"><a name="l12384"></a><span class="lineno">12384</span>&#160;            {</div>
+<div class="line"><a name="l12385"></a><span class="lineno">12385</span>&#160;                <span class="keywordflow">while</span>(res &lt; 0 &amp;&amp; newBlockSizeShift &lt; NEW_BLOCK_SIZE_SHIFT_MAX)</div>
+<div class="line"><a name="l12386"></a><span class="lineno">12386</span>&#160;                {</div>
+<div class="line"><a name="l12387"></a><span class="lineno">12387</span>&#160;                    <span class="keyword">const</span> VkDeviceSize smallerNewBlockSize = newBlockSize / 2;</div>
+<div class="line"><a name="l12388"></a><span class="lineno">12388</span>&#160;                    <span class="keywordflow">if</span>(smallerNewBlockSize &gt;= size)</div>
+<div class="line"><a name="l12389"></a><span class="lineno">12389</span>&#160;                    {</div>
+<div class="line"><a name="l12390"></a><span class="lineno">12390</span>&#160;                        newBlockSize = smallerNewBlockSize;</div>
+<div class="line"><a name="l12391"></a><span class="lineno">12391</span>&#160;                        ++newBlockSizeShift;</div>
+<div class="line"><a name="l12392"></a><span class="lineno">12392</span>&#160;                        res = (newBlockSize &lt;= freeMemory || !canFallbackToDedicated) ?</div>
+<div class="line"><a name="l12393"></a><span class="lineno">12393</span>&#160;                            CreateBlock(newBlockSize, &amp;newBlockIndex) : VK_ERROR_OUT_OF_DEVICE_MEMORY;</div>
+<div class="line"><a name="l12394"></a><span class="lineno">12394</span>&#160;                    }</div>
+<div class="line"><a name="l12395"></a><span class="lineno">12395</span>&#160;                    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l12396"></a><span class="lineno">12396</span>&#160;                    {</div>
+<div class="line"><a name="l12397"></a><span class="lineno">12397</span>&#160;                        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l12398"></a><span class="lineno">12398</span>&#160;                    }</div>
+<div class="line"><a name="l12399"></a><span class="lineno">12399</span>&#160;                }</div>
+<div class="line"><a name="l12400"></a><span class="lineno">12400</span>&#160;            }</div>
+<div class="line"><a name="l12401"></a><span class="lineno">12401</span>&#160; </div>
+<div class="line"><a name="l12402"></a><span class="lineno">12402</span>&#160;            <span class="keywordflow">if</span>(res == VK_SUCCESS)</div>
+<div class="line"><a name="l12403"></a><span class="lineno">12403</span>&#160;            {</div>
+<div class="line"><a name="l12404"></a><span class="lineno">12404</span>&#160;                VmaDeviceMemoryBlock* <span class="keyword">const</span> pBlock = m_Blocks[newBlockIndex];</div>
+<div class="line"><a name="l12405"></a><span class="lineno">12405</span>&#160;                VMA_ASSERT(pBlock-&gt;m_pMetadata-&gt;GetSize() &gt;= size);</div>
+<div class="line"><a name="l12406"></a><span class="lineno">12406</span>&#160; </div>
+<div class="line"><a name="l12407"></a><span class="lineno">12407</span>&#160;                res = AllocateFromBlock(</div>
+<div class="line"><a name="l12408"></a><span class="lineno">12408</span>&#160;                    pBlock,</div>
+<div class="line"><a name="l12409"></a><span class="lineno">12409</span>&#160;                    currentFrameIndex,</div>
+<div class="line"><a name="l12410"></a><span class="lineno">12410</span>&#160;                    size,</div>
+<div class="line"><a name="l12411"></a><span class="lineno">12411</span>&#160;                    alignment,</div>
+<div class="line"><a name="l12412"></a><span class="lineno">12412</span>&#160;                    allocFlagsCopy,</div>
+<div class="line"><a name="l12413"></a><span class="lineno">12413</span>&#160;                    createInfo.<a class="code" href="struct_vma_allocation_create_info.html#a8259e85c272683434f4abb4ddddffe19">pUserData</a>,</div>
+<div class="line"><a name="l12414"></a><span class="lineno">12414</span>&#160;                    suballocType,</div>
+<div class="line"><a name="l12415"></a><span class="lineno">12415</span>&#160;                    strategy,</div>
+<div class="line"><a name="l12416"></a><span class="lineno">12416</span>&#160;                    pAllocation);</div>
+<div class="line"><a name="l12417"></a><span class="lineno">12417</span>&#160;                <span class="keywordflow">if</span>(res == VK_SUCCESS)</div>
+<div class="line"><a name="l12418"></a><span class="lineno">12418</span>&#160;                {</div>
+<div class="line"><a name="l12419"></a><span class="lineno">12419</span>&#160;                    VMA_DEBUG_LOG(<span class="stringliteral">&quot;    Created new block #%u Size=%llu&quot;</span>, pBlock-&gt;GetId(), newBlockSize);</div>
+<div class="line"><a name="l12420"></a><span class="lineno">12420</span>&#160;                    <span class="keywordflow">return</span> VK_SUCCESS;</div>
+<div class="line"><a name="l12421"></a><span class="lineno">12421</span>&#160;                }</div>
+<div class="line"><a name="l12422"></a><span class="lineno">12422</span>&#160;                <span class="keywordflow">else</span></div>
+<div class="line"><a name="l12423"></a><span class="lineno">12423</span>&#160;                {</div>
+<div class="line"><a name="l12424"></a><span class="lineno">12424</span>&#160;                    <span class="comment">// Allocation from new block failed, possibly due to VMA_DEBUG_MARGIN or alignment.</span></div>
+<div class="line"><a name="l12425"></a><span class="lineno">12425</span>&#160;                    <span class="keywordflow">return</span> VK_ERROR_OUT_OF_DEVICE_MEMORY;</div>
+<div class="line"><a name="l12426"></a><span class="lineno">12426</span>&#160;                }</div>
+<div class="line"><a name="l12427"></a><span class="lineno">12427</span>&#160;            }</div>
+<div class="line"><a name="l12428"></a><span class="lineno">12428</span>&#160;        }</div>
+<div class="line"><a name="l12429"></a><span class="lineno">12429</span>&#160;    }</div>
+<div class="line"><a name="l12430"></a><span class="lineno">12430</span>&#160; </div>
+<div class="line"><a name="l12431"></a><span class="lineno">12431</span>&#160;    <span class="comment">// 3. Try to allocate from existing blocks with making other allocations lost.</span></div>
+<div class="line"><a name="l12432"></a><span class="lineno">12432</span>&#160;    <span class="keywordflow">if</span>(canMakeOtherLost)</div>
+<div class="line"><a name="l12433"></a><span class="lineno">12433</span>&#160;    {</div>
+<div class="line"><a name="l12434"></a><span class="lineno">12434</span>&#160;        uint32_t tryIndex = 0;</div>
+<div class="line"><a name="l12435"></a><span class="lineno">12435</span>&#160;        <span class="keywordflow">for</span>(; tryIndex &lt; VMA_ALLOCATION_TRY_COUNT; ++tryIndex)</div>
+<div class="line"><a name="l12436"></a><span class="lineno">12436</span>&#160;        {</div>
+<div class="line"><a name="l12437"></a><span class="lineno">12437</span>&#160;            VmaDeviceMemoryBlock* pBestRequestBlock = VMA_NULL;</div>
+<div class="line"><a name="l12438"></a><span class="lineno">12438</span>&#160;            VmaAllocationRequest bestRequest = {};</div>
+<div class="line"><a name="l12439"></a><span class="lineno">12439</span>&#160;            VkDeviceSize bestRequestCost = VK_WHOLE_SIZE;</div>
+<div class="line"><a name="l12440"></a><span class="lineno">12440</span>&#160; </div>
+<div class="line"><a name="l12441"></a><span class="lineno">12441</span>&#160;            <span class="comment">// 1. Search existing allocations.</span></div>
+<div class="line"><a name="l12442"></a><span class="lineno">12442</span>&#160;            <span class="keywordflow">if</span>(strategy == <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a839826775c62319466441f86496f036d">VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT</a>)</div>
+<div class="line"><a name="l12443"></a><span class="lineno">12443</span>&#160;            {</div>
+<div class="line"><a name="l12444"></a><span class="lineno">12444</span>&#160;                <span class="comment">// Forward order in m_Blocks - prefer blocks with smallest amount of free space.</span></div>
+<div class="line"><a name="l12445"></a><span class="lineno">12445</span>&#160;                <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> blockIndex = 0; blockIndex &lt; m_Blocks.size(); ++blockIndex )</div>
+<div class="line"><a name="l12446"></a><span class="lineno">12446</span>&#160;                {</div>
+<div class="line"><a name="l12447"></a><span class="lineno">12447</span>&#160;                    VmaDeviceMemoryBlock* <span class="keyword">const</span> pCurrBlock = m_Blocks[blockIndex];</div>
+<div class="line"><a name="l12448"></a><span class="lineno">12448</span>&#160;                    VMA_ASSERT(pCurrBlock);</div>
+<div class="line"><a name="l12449"></a><span class="lineno">12449</span>&#160;                    VmaAllocationRequest currRequest = {};</div>
+<div class="line"><a name="l12450"></a><span class="lineno">12450</span>&#160;                    <span class="keywordflow">if</span>(pCurrBlock-&gt;m_pMetadata-&gt;CreateAllocationRequest(</div>
+<div class="line"><a name="l12451"></a><span class="lineno">12451</span>&#160;                        currentFrameIndex,</div>
+<div class="line"><a name="l12452"></a><span class="lineno">12452</span>&#160;                        m_FrameInUseCount,</div>
+<div class="line"><a name="l12453"></a><span class="lineno">12453</span>&#160;                        m_BufferImageGranularity,</div>
+<div class="line"><a name="l12454"></a><span class="lineno">12454</span>&#160;                        size,</div>
+<div class="line"><a name="l12455"></a><span class="lineno">12455</span>&#160;                        alignment,</div>
+<div class="line"><a name="l12456"></a><span class="lineno">12456</span>&#160;                        (createInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a> &amp; <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a42ba3a2d2c7117953210b7c3ef8da0df">VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT</a>) != 0,</div>
+<div class="line"><a name="l12457"></a><span class="lineno">12457</span>&#160;                        suballocType,</div>
+<div class="line"><a name="l12458"></a><span class="lineno">12458</span>&#160;                        canMakeOtherLost,</div>
+<div class="line"><a name="l12459"></a><span class="lineno">12459</span>&#160;                        strategy,</div>
+<div class="line"><a name="l12460"></a><span class="lineno">12460</span>&#160;                        &amp;currRequest))</div>
+<div class="line"><a name="l12461"></a><span class="lineno">12461</span>&#160;                    {</div>
+<div class="line"><a name="l12462"></a><span class="lineno">12462</span>&#160;                        <span class="keyword">const</span> VkDeviceSize currRequestCost = currRequest.CalcCost();</div>
+<div class="line"><a name="l12463"></a><span class="lineno">12463</span>&#160;                        <span class="keywordflow">if</span>(pBestRequestBlock == VMA_NULL ||</div>
+<div class="line"><a name="l12464"></a><span class="lineno">12464</span>&#160;                            currRequestCost &lt; bestRequestCost)</div>
+<div class="line"><a name="l12465"></a><span class="lineno">12465</span>&#160;                        {</div>
+<div class="line"><a name="l12466"></a><span class="lineno">12466</span>&#160;                            pBestRequestBlock = pCurrBlock;</div>
+<div class="line"><a name="l12467"></a><span class="lineno">12467</span>&#160;                            bestRequest = currRequest;</div>
+<div class="line"><a name="l12468"></a><span class="lineno">12468</span>&#160;                            bestRequestCost = currRequestCost;</div>
+<div class="line"><a name="l12469"></a><span class="lineno">12469</span>&#160; </div>
+<div class="line"><a name="l12470"></a><span class="lineno">12470</span>&#160;                            <span class="keywordflow">if</span>(bestRequestCost == 0)</div>
+<div class="line"><a name="l12471"></a><span class="lineno">12471</span>&#160;                            {</div>
+<div class="line"><a name="l12472"></a><span class="lineno">12472</span>&#160;                                <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l12473"></a><span class="lineno">12473</span>&#160;                            }</div>
+<div class="line"><a name="l12474"></a><span class="lineno">12474</span>&#160;                        }</div>
+<div class="line"><a name="l12475"></a><span class="lineno">12475</span>&#160;                    }</div>
+<div class="line"><a name="l12476"></a><span class="lineno">12476</span>&#160;                }</div>
+<div class="line"><a name="l12477"></a><span class="lineno">12477</span>&#160;            }</div>
+<div class="line"><a name="l12478"></a><span class="lineno">12478</span>&#160;            <span class="keywordflow">else</span> <span class="comment">// WORST_FIT, FIRST_FIT</span></div>
+<div class="line"><a name="l12479"></a><span class="lineno">12479</span>&#160;            {</div>
+<div class="line"><a name="l12480"></a><span class="lineno">12480</span>&#160;                <span class="comment">// Backward order in m_Blocks - prefer blocks with largest amount of free space.</span></div>
+<div class="line"><a name="l12481"></a><span class="lineno">12481</span>&#160;                <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> blockIndex = m_Blocks.size(); blockIndex--; )</div>
+<div class="line"><a name="l12482"></a><span class="lineno">12482</span>&#160;                {</div>
+<div class="line"><a name="l12483"></a><span class="lineno">12483</span>&#160;                    VmaDeviceMemoryBlock* <span class="keyword">const</span> pCurrBlock = m_Blocks[blockIndex];</div>
+<div class="line"><a name="l12484"></a><span class="lineno">12484</span>&#160;                    VMA_ASSERT(pCurrBlock);</div>
+<div class="line"><a name="l12485"></a><span class="lineno">12485</span>&#160;                    VmaAllocationRequest currRequest = {};</div>
+<div class="line"><a name="l12486"></a><span class="lineno">12486</span>&#160;                    <span class="keywordflow">if</span>(pCurrBlock-&gt;m_pMetadata-&gt;CreateAllocationRequest(</div>
+<div class="line"><a name="l12487"></a><span class="lineno">12487</span>&#160;                        currentFrameIndex,</div>
+<div class="line"><a name="l12488"></a><span class="lineno">12488</span>&#160;                        m_FrameInUseCount,</div>
+<div class="line"><a name="l12489"></a><span class="lineno">12489</span>&#160;                        m_BufferImageGranularity,</div>
+<div class="line"><a name="l12490"></a><span class="lineno">12490</span>&#160;                        size,</div>
+<div class="line"><a name="l12491"></a><span class="lineno">12491</span>&#160;                        alignment,</div>
+<div class="line"><a name="l12492"></a><span class="lineno">12492</span>&#160;                        (createInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a> &amp; <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a42ba3a2d2c7117953210b7c3ef8da0df">VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT</a>) != 0,</div>
+<div class="line"><a name="l12493"></a><span class="lineno">12493</span>&#160;                        suballocType,</div>
+<div class="line"><a name="l12494"></a><span class="lineno">12494</span>&#160;                        canMakeOtherLost,</div>
+<div class="line"><a name="l12495"></a><span class="lineno">12495</span>&#160;                        strategy,</div>
+<div class="line"><a name="l12496"></a><span class="lineno">12496</span>&#160;                        &amp;currRequest))</div>
+<div class="line"><a name="l12497"></a><span class="lineno">12497</span>&#160;                    {</div>
+<div class="line"><a name="l12498"></a><span class="lineno">12498</span>&#160;                        <span class="keyword">const</span> VkDeviceSize currRequestCost = currRequest.CalcCost();</div>
+<div class="line"><a name="l12499"></a><span class="lineno">12499</span>&#160;                        <span class="keywordflow">if</span>(pBestRequestBlock == VMA_NULL ||</div>
+<div class="line"><a name="l12500"></a><span class="lineno">12500</span>&#160;                            currRequestCost &lt; bestRequestCost ||</div>
+<div class="line"><a name="l12501"></a><span class="lineno">12501</span>&#160;                            strategy == <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a33eb2052674f3ad92386c714a65fb777">VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT</a>)</div>
+<div class="line"><a name="l12502"></a><span class="lineno">12502</span>&#160;                        {</div>
+<div class="line"><a name="l12503"></a><span class="lineno">12503</span>&#160;                            pBestRequestBlock = pCurrBlock;</div>
+<div class="line"><a name="l12504"></a><span class="lineno">12504</span>&#160;                            bestRequest = currRequest;</div>
+<div class="line"><a name="l12505"></a><span class="lineno">12505</span>&#160;                            bestRequestCost = currRequestCost;</div>
+<div class="line"><a name="l12506"></a><span class="lineno">12506</span>&#160; </div>
+<div class="line"><a name="l12507"></a><span class="lineno">12507</span>&#160;                            <span class="keywordflow">if</span>(bestRequestCost == 0 ||</div>
+<div class="line"><a name="l12508"></a><span class="lineno">12508</span>&#160;                                strategy == <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a33eb2052674f3ad92386c714a65fb777">VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT</a>)</div>
+<div class="line"><a name="l12509"></a><span class="lineno">12509</span>&#160;                            {</div>
+<div class="line"><a name="l12510"></a><span class="lineno">12510</span>&#160;                                <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l12511"></a><span class="lineno">12511</span>&#160;                            }</div>
+<div class="line"><a name="l12512"></a><span class="lineno">12512</span>&#160;                        }</div>
+<div class="line"><a name="l12513"></a><span class="lineno">12513</span>&#160;                    }</div>
+<div class="line"><a name="l12514"></a><span class="lineno">12514</span>&#160;                }</div>
+<div class="line"><a name="l12515"></a><span class="lineno">12515</span>&#160;            }</div>
+<div class="line"><a name="l12516"></a><span class="lineno">12516</span>&#160; </div>
+<div class="line"><a name="l12517"></a><span class="lineno">12517</span>&#160;            <span class="keywordflow">if</span>(pBestRequestBlock != VMA_NULL)</div>
+<div class="line"><a name="l12518"></a><span class="lineno">12518</span>&#160;            {</div>
+<div class="line"><a name="l12519"></a><span class="lineno">12519</span>&#160;                <span class="keywordflow">if</span>(mapped)</div>
+<div class="line"><a name="l12520"></a><span class="lineno">12520</span>&#160;                {</div>
+<div class="line"><a name="l12521"></a><span class="lineno">12521</span>&#160;                    VkResult res = pBestRequestBlock-&gt;Map(m_hAllocator, 1, VMA_NULL);</div>
+<div class="line"><a name="l12522"></a><span class="lineno">12522</span>&#160;                    <span class="keywordflow">if</span>(res != VK_SUCCESS)</div>
+<div class="line"><a name="l12523"></a><span class="lineno">12523</span>&#160;                    {</div>
+<div class="line"><a name="l12524"></a><span class="lineno">12524</span>&#160;                        <span class="keywordflow">return</span> res;</div>
+<div class="line"><a name="l12525"></a><span class="lineno">12525</span>&#160;                    }</div>
+<div class="line"><a name="l12526"></a><span class="lineno">12526</span>&#160;                }</div>
+<div class="line"><a name="l12527"></a><span class="lineno">12527</span>&#160; </div>
+<div class="line"><a name="l12528"></a><span class="lineno">12528</span>&#160;                <span class="keywordflow">if</span>(pBestRequestBlock-&gt;m_pMetadata-&gt;MakeRequestedAllocationsLost(</div>
+<div class="line"><a name="l12529"></a><span class="lineno">12529</span>&#160;                    currentFrameIndex,</div>
+<div class="line"><a name="l12530"></a><span class="lineno">12530</span>&#160;                    m_FrameInUseCount,</div>
+<div class="line"><a name="l12531"></a><span class="lineno">12531</span>&#160;                    &amp;bestRequest))</div>
+<div class="line"><a name="l12532"></a><span class="lineno">12532</span>&#160;                {</div>
+<div class="line"><a name="l12533"></a><span class="lineno">12533</span>&#160;                    <span class="comment">// Allocate from this pBlock.</span></div>
+<div class="line"><a name="l12534"></a><span class="lineno">12534</span>&#160;                    *pAllocation = m_hAllocator-&gt;m_AllocationObjectAllocator.Allocate(currentFrameIndex, isUserDataString);</div>
+<div class="line"><a name="l12535"></a><span class="lineno">12535</span>&#160;                    pBestRequestBlock-&gt;m_pMetadata-&gt;Alloc(bestRequest, suballocType, size, *pAllocation);</div>
+<div class="line"><a name="l12536"></a><span class="lineno">12536</span>&#160;                    UpdateHasEmptyBlock();</div>
+<div class="line"><a name="l12537"></a><span class="lineno">12537</span>&#160;                    (*pAllocation)-&gt;InitBlockAllocation(</div>
+<div class="line"><a name="l12538"></a><span class="lineno">12538</span>&#160;                        pBestRequestBlock,</div>
+<div class="line"><a name="l12539"></a><span class="lineno">12539</span>&#160;                        bestRequest.offset,</div>
+<div class="line"><a name="l12540"></a><span class="lineno">12540</span>&#160;                        alignment,</div>
+<div class="line"><a name="l12541"></a><span class="lineno">12541</span>&#160;                        size,</div>
+<div class="line"><a name="l12542"></a><span class="lineno">12542</span>&#160;                        m_MemoryTypeIndex,</div>
+<div class="line"><a name="l12543"></a><span class="lineno">12543</span>&#160;                        suballocType,</div>
+<div class="line"><a name="l12544"></a><span class="lineno">12544</span>&#160;                        mapped,</div>
+<div class="line"><a name="l12545"></a><span class="lineno">12545</span>&#160;                        (createInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a> &amp; <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a5f436af6c8fe8540573a6d22627a6fd2">VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT</a>) != 0);</div>
+<div class="line"><a name="l12546"></a><span class="lineno">12546</span>&#160;                    VMA_HEAVY_ASSERT(pBestRequestBlock-&gt;Validate());</div>
+<div class="line"><a name="l12547"></a><span class="lineno">12547</span>&#160;                    VMA_DEBUG_LOG(<span class="stringliteral">&quot;    Returned from existing block&quot;</span>);</div>
+<div class="line"><a name="l12548"></a><span class="lineno">12548</span>&#160;                    (*pAllocation)-&gt;SetUserData(m_hAllocator, createInfo.<a class="code" href="struct_vma_allocation_create_info.html#a8259e85c272683434f4abb4ddddffe19">pUserData</a>);</div>
+<div class="line"><a name="l12549"></a><span class="lineno">12549</span>&#160;                    m_hAllocator-&gt;m_Budget.AddAllocation(m_hAllocator-&gt;MemoryTypeIndexToHeapIndex(m_MemoryTypeIndex), size);</div>
+<div class="line"><a name="l12550"></a><span class="lineno">12550</span>&#160;                    <span class="keywordflow">if</span>(VMA_DEBUG_INITIALIZE_ALLOCATIONS)</div>
+<div class="line"><a name="l12551"></a><span class="lineno">12551</span>&#160;                    {</div>
+<div class="line"><a name="l12552"></a><span class="lineno">12552</span>&#160;                        m_hAllocator-&gt;FillAllocation(*pAllocation, VMA_ALLOCATION_FILL_PATTERN_CREATED);</div>
+<div class="line"><a name="l12553"></a><span class="lineno">12553</span>&#160;                    }</div>
+<div class="line"><a name="l12554"></a><span class="lineno">12554</span>&#160;                    <span class="keywordflow">if</span>(IsCorruptionDetectionEnabled())</div>
+<div class="line"><a name="l12555"></a><span class="lineno">12555</span>&#160;                    {</div>
+<div class="line"><a name="l12556"></a><span class="lineno">12556</span>&#160;                        VkResult res = pBestRequestBlock-&gt;WriteMagicValueAroundAllocation(m_hAllocator, bestRequest.offset, size);</div>
+<div class="line"><a name="l12557"></a><span class="lineno">12557</span>&#160;                        VMA_ASSERT(res == VK_SUCCESS &amp;&amp; <span class="stringliteral">&quot;Couldn&#39;t map block memory to write magic value.&quot;</span>);</div>
+<div class="line"><a name="l12558"></a><span class="lineno">12558</span>&#160;                    }</div>
+<div class="line"><a name="l12559"></a><span class="lineno">12559</span>&#160;                    <span class="keywordflow">return</span> VK_SUCCESS;</div>
+<div class="line"><a name="l12560"></a><span class="lineno">12560</span>&#160;                }</div>
+<div class="line"><a name="l12561"></a><span class="lineno">12561</span>&#160;                <span class="comment">// else: Some allocations must have been touched while we are here. Next try.</span></div>
+<div class="line"><a name="l12562"></a><span class="lineno">12562</span>&#160;            }</div>
+<div class="line"><a name="l12563"></a><span class="lineno">12563</span>&#160;            <span class="keywordflow">else</span></div>
+<div class="line"><a name="l12564"></a><span class="lineno">12564</span>&#160;            {</div>
+<div class="line"><a name="l12565"></a><span class="lineno">12565</span>&#160;                <span class="comment">// Could not find place in any of the blocks - break outer loop.</span></div>
+<div class="line"><a name="l12566"></a><span class="lineno">12566</span>&#160;                <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l12567"></a><span class="lineno">12567</span>&#160;            }</div>
+<div class="line"><a name="l12568"></a><span class="lineno">12568</span>&#160;        }</div>
+<div class="line"><a name="l12569"></a><span class="lineno">12569</span>&#160;        <span class="comment">/* Maximum number of tries exceeded - a very unlike event when many other</span></div>
+<div class="line"><a name="l12570"></a><span class="lineno">12570</span>&#160;<span class="comment">        threads are simultaneously touching allocations making it impossible to make</span></div>
+<div class="line"><a name="l12571"></a><span class="lineno">12571</span>&#160;<span class="comment">        lost at the same time as we try to allocate. */</span></div>
+<div class="line"><a name="l12572"></a><span class="lineno">12572</span>&#160;        <span class="keywordflow">if</span>(tryIndex == VMA_ALLOCATION_TRY_COUNT)</div>
+<div class="line"><a name="l12573"></a><span class="lineno">12573</span>&#160;        {</div>
+<div class="line"><a name="l12574"></a><span class="lineno">12574</span>&#160;            <span class="keywordflow">return</span> VK_ERROR_TOO_MANY_OBJECTS;</div>
+<div class="line"><a name="l12575"></a><span class="lineno">12575</span>&#160;        }</div>
+<div class="line"><a name="l12576"></a><span class="lineno">12576</span>&#160;    }</div>
+<div class="line"><a name="l12577"></a><span class="lineno">12577</span>&#160; </div>
+<div class="line"><a name="l12578"></a><span class="lineno">12578</span>&#160;    <span class="keywordflow">return</span> VK_ERROR_OUT_OF_DEVICE_MEMORY;</div>
+<div class="line"><a name="l12579"></a><span class="lineno">12579</span>&#160;}</div>
+<div class="line"><a name="l12580"></a><span class="lineno">12580</span>&#160; </div>
+<div class="line"><a name="l12581"></a><span class="lineno">12581</span>&#160;<span class="keywordtype">void</span> VmaBlockVector::Free(</div>
+<div class="line"><a name="l12582"></a><span class="lineno">12582</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAllocation)</div>
+<div class="line"><a name="l12583"></a><span class="lineno">12583</span>&#160;{</div>
+<div class="line"><a name="l12584"></a><span class="lineno">12584</span>&#160;    VmaDeviceMemoryBlock* pBlockToDelete = VMA_NULL;</div>
+<div class="line"><a name="l12585"></a><span class="lineno">12585</span>&#160; </div>
+<div class="line"><a name="l12586"></a><span class="lineno">12586</span>&#160;    <span class="keywordtype">bool</span> budgetExceeded = <span class="keyword">false</span>;</div>
+<div class="line"><a name="l12587"></a><span class="lineno">12587</span>&#160;    {</div>
+<div class="line"><a name="l12588"></a><span class="lineno">12588</span>&#160;        <span class="keyword">const</span> uint32_t heapIndex = m_hAllocator-&gt;MemoryTypeIndexToHeapIndex(m_MemoryTypeIndex);</div>
+<div class="line"><a name="l12589"></a><span class="lineno">12589</span>&#160;        <a class="code" href="struct_vma_budget.html">VmaBudget</a> heapBudget = {};</div>
+<div class="line"><a name="l12590"></a><span class="lineno">12590</span>&#160;        m_hAllocator-&gt;GetBudget(&amp;heapBudget, heapIndex, 1);</div>
+<div class="line"><a name="l12591"></a><span class="lineno">12591</span>&#160;        budgetExceeded = heapBudget.<a class="code" href="struct_vma_budget.html#a84dd1ecca8b0110259eb206dbadb11f6">usage</a> &gt;= heapBudget.<a class="code" href="struct_vma_budget.html#ab82e1d1754c2d210d0bdf90220bc6cdd">budget</a>;</div>
+<div class="line"><a name="l12592"></a><span class="lineno">12592</span>&#160;    }</div>
+<div class="line"><a name="l12593"></a><span class="lineno">12593</span>&#160; </div>
+<div class="line"><a name="l12594"></a><span class="lineno">12594</span>&#160;    <span class="comment">// Scope for lock.</span></div>
+<div class="line"><a name="l12595"></a><span class="lineno">12595</span>&#160;    {</div>
+<div class="line"><a name="l12596"></a><span class="lineno">12596</span>&#160;        VmaMutexLockWrite lock(m_Mutex, m_hAllocator-&gt;m_UseMutex);</div>
+<div class="line"><a name="l12597"></a><span class="lineno">12597</span>&#160; </div>
+<div class="line"><a name="l12598"></a><span class="lineno">12598</span>&#160;        VmaDeviceMemoryBlock* pBlock = hAllocation-&gt;GetBlock();</div>
+<div class="line"><a name="l12599"></a><span class="lineno">12599</span>&#160; </div>
+<div class="line"><a name="l12600"></a><span class="lineno">12600</span>&#160;        <span class="keywordflow">if</span>(IsCorruptionDetectionEnabled())</div>
+<div class="line"><a name="l12601"></a><span class="lineno">12601</span>&#160;        {</div>
+<div class="line"><a name="l12602"></a><span class="lineno">12602</span>&#160;            VkResult res = pBlock-&gt;ValidateMagicValueAroundAllocation(m_hAllocator, hAllocation-&gt;GetOffset(), hAllocation-&gt;GetSize());</div>
+<div class="line"><a name="l12603"></a><span class="lineno">12603</span>&#160;            VMA_ASSERT(res == VK_SUCCESS &amp;&amp; <span class="stringliteral">&quot;Couldn&#39;t map block memory to validate magic value.&quot;</span>);</div>
+<div class="line"><a name="l12604"></a><span class="lineno">12604</span>&#160;        }</div>
+<div class="line"><a name="l12605"></a><span class="lineno">12605</span>&#160; </div>
+<div class="line"><a name="l12606"></a><span class="lineno">12606</span>&#160;        <span class="keywordflow">if</span>(hAllocation-&gt;IsPersistentMap())</div>
+<div class="line"><a name="l12607"></a><span class="lineno">12607</span>&#160;        {</div>
+<div class="line"><a name="l12608"></a><span class="lineno">12608</span>&#160;            pBlock-&gt;Unmap(m_hAllocator, 1);</div>
+<div class="line"><a name="l12609"></a><span class="lineno">12609</span>&#160;        }</div>
+<div class="line"><a name="l12610"></a><span class="lineno">12610</span>&#160; </div>
+<div class="line"><a name="l12611"></a><span class="lineno">12611</span>&#160;        pBlock-&gt;m_pMetadata-&gt;Free(hAllocation);</div>
+<div class="line"><a name="l12612"></a><span class="lineno">12612</span>&#160;        VMA_HEAVY_ASSERT(pBlock-&gt;Validate());</div>
+<div class="line"><a name="l12613"></a><span class="lineno">12613</span>&#160; </div>
+<div class="line"><a name="l12614"></a><span class="lineno">12614</span>&#160;        VMA_DEBUG_LOG(<span class="stringliteral">&quot;  Freed from MemoryTypeIndex=%u&quot;</span>, m_MemoryTypeIndex);</div>
+<div class="line"><a name="l12615"></a><span class="lineno">12615</span>&#160; </div>
+<div class="line"><a name="l12616"></a><span class="lineno">12616</span>&#160;        <span class="keyword">const</span> <span class="keywordtype">bool</span> canDeleteBlock = m_Blocks.size() &gt; m_MinBlockCount;</div>
+<div class="line"><a name="l12617"></a><span class="lineno">12617</span>&#160;        <span class="comment">// pBlock became empty after this deallocation.</span></div>
+<div class="line"><a name="l12618"></a><span class="lineno">12618</span>&#160;        <span class="keywordflow">if</span>(pBlock-&gt;m_pMetadata-&gt;IsEmpty())</div>
+<div class="line"><a name="l12619"></a><span class="lineno">12619</span>&#160;        {</div>
+<div class="line"><a name="l12620"></a><span class="lineno">12620</span>&#160;            <span class="comment">// Already has empty block. We don&#39;t want to have two, so delete this one.</span></div>
+<div class="line"><a name="l12621"></a><span class="lineno">12621</span>&#160;            <span class="keywordflow">if</span>((m_HasEmptyBlock || budgetExceeded) &amp;&amp; canDeleteBlock)</div>
+<div class="line"><a name="l12622"></a><span class="lineno">12622</span>&#160;            {</div>
+<div class="line"><a name="l12623"></a><span class="lineno">12623</span>&#160;                pBlockToDelete = pBlock;</div>
+<div class="line"><a name="l12624"></a><span class="lineno">12624</span>&#160;                Remove(pBlock);</div>
+<div class="line"><a name="l12625"></a><span class="lineno">12625</span>&#160;            }</div>
+<div class="line"><a name="l12626"></a><span class="lineno">12626</span>&#160;            <span class="comment">// else: We now have an empty block - leave it.</span></div>
+<div class="line"><a name="l12627"></a><span class="lineno">12627</span>&#160;        }</div>
+<div class="line"><a name="l12628"></a><span class="lineno">12628</span>&#160;        <span class="comment">// pBlock didn&#39;t become empty, but we have another empty block - find and free that one.</span></div>
+<div class="line"><a name="l12629"></a><span class="lineno">12629</span>&#160;        <span class="comment">// (This is optional, heuristics.)</span></div>
+<div class="line"><a name="l12630"></a><span class="lineno">12630</span>&#160;        <span class="keywordflow">else</span> <span class="keywordflow">if</span>(m_HasEmptyBlock &amp;&amp; canDeleteBlock)</div>
+<div class="line"><a name="l12631"></a><span class="lineno">12631</span>&#160;        {</div>
+<div class="line"><a name="l12632"></a><span class="lineno">12632</span>&#160;            VmaDeviceMemoryBlock* pLastBlock = m_Blocks.back();</div>
+<div class="line"><a name="l12633"></a><span class="lineno">12633</span>&#160;            <span class="keywordflow">if</span>(pLastBlock-&gt;m_pMetadata-&gt;IsEmpty())</div>
+<div class="line"><a name="l12634"></a><span class="lineno">12634</span>&#160;            {</div>
+<div class="line"><a name="l12635"></a><span class="lineno">12635</span>&#160;                pBlockToDelete = pLastBlock;</div>
+<div class="line"><a name="l12636"></a><span class="lineno">12636</span>&#160;                m_Blocks.pop_back();</div>
+<div class="line"><a name="l12637"></a><span class="lineno">12637</span>&#160;            }</div>
+<div class="line"><a name="l12638"></a><span class="lineno">12638</span>&#160;        }</div>
+<div class="line"><a name="l12639"></a><span class="lineno">12639</span>&#160; </div>
+<div class="line"><a name="l12640"></a><span class="lineno">12640</span>&#160;        UpdateHasEmptyBlock();</div>
+<div class="line"><a name="l12641"></a><span class="lineno">12641</span>&#160;        IncrementallySortBlocks();</div>
+<div class="line"><a name="l12642"></a><span class="lineno">12642</span>&#160;    }</div>
+<div class="line"><a name="l12643"></a><span class="lineno">12643</span>&#160; </div>
+<div class="line"><a name="l12644"></a><span class="lineno">12644</span>&#160;    <span class="comment">// Destruction of a free block. Deferred until this point, outside of mutex</span></div>
+<div class="line"><a name="l12645"></a><span class="lineno">12645</span>&#160;    <span class="comment">// lock, for performance reason.</span></div>
+<div class="line"><a name="l12646"></a><span class="lineno">12646</span>&#160;    <span class="keywordflow">if</span>(pBlockToDelete != VMA_NULL)</div>
+<div class="line"><a name="l12647"></a><span class="lineno">12647</span>&#160;    {</div>
+<div class="line"><a name="l12648"></a><span class="lineno">12648</span>&#160;        VMA_DEBUG_LOG(<span class="stringliteral">&quot;    Deleted empty block&quot;</span>);</div>
+<div class="line"><a name="l12649"></a><span class="lineno">12649</span>&#160;        pBlockToDelete-&gt;Destroy(m_hAllocator);</div>
+<div class="line"><a name="l12650"></a><span class="lineno">12650</span>&#160;        vma_delete(m_hAllocator, pBlockToDelete);</div>
+<div class="line"><a name="l12651"></a><span class="lineno">12651</span>&#160;    }</div>
+<div class="line"><a name="l12652"></a><span class="lineno">12652</span>&#160;}</div>
+<div class="line"><a name="l12653"></a><span class="lineno">12653</span>&#160; </div>
+<div class="line"><a name="l12654"></a><span class="lineno">12654</span>&#160;VkDeviceSize VmaBlockVector::CalcMaxBlockSize()<span class="keyword"> const</span></div>
+<div class="line"><a name="l12655"></a><span class="lineno">12655</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l12656"></a><span class="lineno">12656</span>&#160;    VkDeviceSize result = 0;</div>
+<div class="line"><a name="l12657"></a><span class="lineno">12657</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = m_Blocks.size(); i--; )</div>
+<div class="line"><a name="l12658"></a><span class="lineno">12658</span>&#160;    {</div>
+<div class="line"><a name="l12659"></a><span class="lineno">12659</span>&#160;        result = VMA_MAX(result, m_Blocks[i]-&gt;m_pMetadata-&gt;GetSize());</div>
+<div class="line"><a name="l12660"></a><span class="lineno">12660</span>&#160;        <span class="keywordflow">if</span>(result &gt;= m_PreferredBlockSize)</div>
+<div class="line"><a name="l12661"></a><span class="lineno">12661</span>&#160;        {</div>
+<div class="line"><a name="l12662"></a><span class="lineno">12662</span>&#160;            <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l12663"></a><span class="lineno">12663</span>&#160;        }</div>
+<div class="line"><a name="l12664"></a><span class="lineno">12664</span>&#160;    }</div>
+<div class="line"><a name="l12665"></a><span class="lineno">12665</span>&#160;    <span class="keywordflow">return</span> result;</div>
+<div class="line"><a name="l12666"></a><span class="lineno">12666</span>&#160;}</div>
+<div class="line"><a name="l12667"></a><span class="lineno">12667</span>&#160; </div>
+<div class="line"><a name="l12668"></a><span class="lineno">12668</span>&#160;<span class="keywordtype">void</span> VmaBlockVector::Remove(VmaDeviceMemoryBlock* pBlock)</div>
+<div class="line"><a name="l12669"></a><span class="lineno">12669</span>&#160;{</div>
+<div class="line"><a name="l12670"></a><span class="lineno">12670</span>&#160;    <span class="keywordflow">for</span>(uint32_t blockIndex = 0; blockIndex &lt; m_Blocks.size(); ++blockIndex)</div>
+<div class="line"><a name="l12671"></a><span class="lineno">12671</span>&#160;    {</div>
+<div class="line"><a name="l12672"></a><span class="lineno">12672</span>&#160;        <span class="keywordflow">if</span>(m_Blocks[blockIndex] == pBlock)</div>
+<div class="line"><a name="l12673"></a><span class="lineno">12673</span>&#160;        {</div>
+<div class="line"><a name="l12674"></a><span class="lineno">12674</span>&#160;            VmaVectorRemove(m_Blocks, blockIndex);</div>
+<div class="line"><a name="l12675"></a><span class="lineno">12675</span>&#160;            <span class="keywordflow">return</span>;</div>
+<div class="line"><a name="l12676"></a><span class="lineno">12676</span>&#160;        }</div>
+<div class="line"><a name="l12677"></a><span class="lineno">12677</span>&#160;    }</div>
+<div class="line"><a name="l12678"></a><span class="lineno">12678</span>&#160;    VMA_ASSERT(0);</div>
+<div class="line"><a name="l12679"></a><span class="lineno">12679</span>&#160;}</div>
+<div class="line"><a name="l12680"></a><span class="lineno">12680</span>&#160; </div>
+<div class="line"><a name="l12681"></a><span class="lineno">12681</span>&#160;<span class="keywordtype">void</span> VmaBlockVector::IncrementallySortBlocks()</div>
+<div class="line"><a name="l12682"></a><span class="lineno">12682</span>&#160;{</div>
+<div class="line"><a name="l12683"></a><span class="lineno">12683</span>&#160;    <span class="keywordflow">if</span>(m_Algorithm != <a class="code" href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a13c8a444197c67866be9cb05599fc726">VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT</a>)</div>
+<div class="line"><a name="l12684"></a><span class="lineno">12684</span>&#160;    {</div>
+<div class="line"><a name="l12685"></a><span class="lineno">12685</span>&#160;        <span class="comment">// Bubble sort only until first swap.</span></div>
+<div class="line"><a name="l12686"></a><span class="lineno">12686</span>&#160;        <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = 1; i &lt; m_Blocks.size(); ++i)</div>
+<div class="line"><a name="l12687"></a><span class="lineno">12687</span>&#160;        {</div>
+<div class="line"><a name="l12688"></a><span class="lineno">12688</span>&#160;            <span class="keywordflow">if</span>(m_Blocks[i - 1]-&gt;m_pMetadata-&gt;GetSumFreeSize() &gt; m_Blocks[i]-&gt;m_pMetadata-&gt;GetSumFreeSize())</div>
+<div class="line"><a name="l12689"></a><span class="lineno">12689</span>&#160;            {</div>
+<div class="line"><a name="l12690"></a><span class="lineno">12690</span>&#160;                VMA_SWAP(m_Blocks[i - 1], m_Blocks[i]);</div>
+<div class="line"><a name="l12691"></a><span class="lineno">12691</span>&#160;                <span class="keywordflow">return</span>;</div>
+<div class="line"><a name="l12692"></a><span class="lineno">12692</span>&#160;            }</div>
+<div class="line"><a name="l12693"></a><span class="lineno">12693</span>&#160;        }</div>
+<div class="line"><a name="l12694"></a><span class="lineno">12694</span>&#160;    }</div>
+<div class="line"><a name="l12695"></a><span class="lineno">12695</span>&#160;}</div>
+<div class="line"><a name="l12696"></a><span class="lineno">12696</span>&#160; </div>
+<div class="line"><a name="l12697"></a><span class="lineno">12697</span>&#160;VkResult VmaBlockVector::AllocateFromBlock(</div>
+<div class="line"><a name="l12698"></a><span class="lineno">12698</span>&#160;    VmaDeviceMemoryBlock* pBlock,</div>
+<div class="line"><a name="l12699"></a><span class="lineno">12699</span>&#160;    uint32_t currentFrameIndex,</div>
+<div class="line"><a name="l12700"></a><span class="lineno">12700</span>&#160;    VkDeviceSize size,</div>
+<div class="line"><a name="l12701"></a><span class="lineno">12701</span>&#160;    VkDeviceSize alignment,</div>
+<div class="line"><a name="l12702"></a><span class="lineno">12702</span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#a5225e5e11f8376f6a31a1791f3d6e817">VmaAllocationCreateFlags</a> allocFlags,</div>
+<div class="line"><a name="l12703"></a><span class="lineno">12703</span>&#160;    <span class="keywordtype">void</span>* pUserData,</div>
+<div class="line"><a name="l12704"></a><span class="lineno">12704</span>&#160;    VmaSuballocationType suballocType,</div>
+<div class="line"><a name="l12705"></a><span class="lineno">12705</span>&#160;    uint32_t strategy,</div>
+<div class="line"><a name="l12706"></a><span class="lineno">12706</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocation)</div>
+<div class="line"><a name="l12707"></a><span class="lineno">12707</span>&#160;{</div>
+<div class="line"><a name="l12708"></a><span class="lineno">12708</span>&#160;    VMA_ASSERT((allocFlags &amp; <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a68686d0ce9beb0d4d1b9f2b8b1389a7e">VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT</a>) == 0);</div>
+<div class="line"><a name="l12709"></a><span class="lineno">12709</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">bool</span> isUpperAddress = (allocFlags &amp; <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a42ba3a2d2c7117953210b7c3ef8da0df">VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT</a>) != 0;</div>
+<div class="line"><a name="l12710"></a><span class="lineno">12710</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">bool</span> mapped = (allocFlags &amp; <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a11da372cc3a82931c5e5d6146cd9dd1f">VMA_ALLOCATION_CREATE_MAPPED_BIT</a>) != 0;</div>
+<div class="line"><a name="l12711"></a><span class="lineno">12711</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">bool</span> isUserDataString = (allocFlags &amp; <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597aa6f24f821cd6a7c5e4a443f7bf59c520">VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT</a>) != 0;</div>
+<div class="line"><a name="l12712"></a><span class="lineno">12712</span>&#160; </div>
+<div class="line"><a name="l12713"></a><span class="lineno">12713</span>&#160;    VmaAllocationRequest currRequest = {};</div>
+<div class="line"><a name="l12714"></a><span class="lineno">12714</span>&#160;    <span class="keywordflow">if</span>(pBlock-&gt;m_pMetadata-&gt;CreateAllocationRequest(</div>
+<div class="line"><a name="l12715"></a><span class="lineno">12715</span>&#160;        currentFrameIndex,</div>
+<div class="line"><a name="l12716"></a><span class="lineno">12716</span>&#160;        m_FrameInUseCount,</div>
+<div class="line"><a name="l12717"></a><span class="lineno">12717</span>&#160;        m_BufferImageGranularity,</div>
+<div class="line"><a name="l12718"></a><span class="lineno">12718</span>&#160;        size,</div>
+<div class="line"><a name="l12719"></a><span class="lineno">12719</span>&#160;        alignment,</div>
+<div class="line"><a name="l12720"></a><span class="lineno">12720</span>&#160;        isUpperAddress,</div>
+<div class="line"><a name="l12721"></a><span class="lineno">12721</span>&#160;        suballocType,</div>
+<div class="line"><a name="l12722"></a><span class="lineno">12722</span>&#160;        <span class="keyword">false</span>, <span class="comment">// canMakeOtherLost</span></div>
+<div class="line"><a name="l12723"></a><span class="lineno">12723</span>&#160;        strategy,</div>
+<div class="line"><a name="l12724"></a><span class="lineno">12724</span>&#160;        &amp;currRequest))</div>
+<div class="line"><a name="l12725"></a><span class="lineno">12725</span>&#160;    {</div>
+<div class="line"><a name="l12726"></a><span class="lineno">12726</span>&#160;        <span class="comment">// Allocate from pCurrBlock.</span></div>
+<div class="line"><a name="l12727"></a><span class="lineno">12727</span>&#160;        VMA_ASSERT(currRequest.itemsToMakeLostCount == 0);</div>
+<div class="line"><a name="l12728"></a><span class="lineno">12728</span>&#160; </div>
+<div class="line"><a name="l12729"></a><span class="lineno">12729</span>&#160;        <span class="keywordflow">if</span>(mapped)</div>
+<div class="line"><a name="l12730"></a><span class="lineno">12730</span>&#160;        {</div>
+<div class="line"><a name="l12731"></a><span class="lineno">12731</span>&#160;            VkResult res = pBlock-&gt;Map(m_hAllocator, 1, VMA_NULL);</div>
+<div class="line"><a name="l12732"></a><span class="lineno">12732</span>&#160;            <span class="keywordflow">if</span>(res != VK_SUCCESS)</div>
+<div class="line"><a name="l12733"></a><span class="lineno">12733</span>&#160;            {</div>
+<div class="line"><a name="l12734"></a><span class="lineno">12734</span>&#160;                <span class="keywordflow">return</span> res;</div>
+<div class="line"><a name="l12735"></a><span class="lineno">12735</span>&#160;            }</div>
+<div class="line"><a name="l12736"></a><span class="lineno">12736</span>&#160;        }</div>
+<div class="line"><a name="l12737"></a><span class="lineno">12737</span>&#160;            </div>
+<div class="line"><a name="l12738"></a><span class="lineno">12738</span>&#160;        *pAllocation = m_hAllocator-&gt;m_AllocationObjectAllocator.Allocate(currentFrameIndex, isUserDataString);</div>
+<div class="line"><a name="l12739"></a><span class="lineno">12739</span>&#160;        pBlock-&gt;m_pMetadata-&gt;Alloc(currRequest, suballocType, size, *pAllocation);</div>
+<div class="line"><a name="l12740"></a><span class="lineno">12740</span>&#160;        UpdateHasEmptyBlock();</div>
+<div class="line"><a name="l12741"></a><span class="lineno">12741</span>&#160;        (*pAllocation)-&gt;InitBlockAllocation(</div>
+<div class="line"><a name="l12742"></a><span class="lineno">12742</span>&#160;            pBlock,</div>
+<div class="line"><a name="l12743"></a><span class="lineno">12743</span>&#160;            currRequest.offset,</div>
+<div class="line"><a name="l12744"></a><span class="lineno">12744</span>&#160;            alignment,</div>
+<div class="line"><a name="l12745"></a><span class="lineno">12745</span>&#160;            size,</div>
+<div class="line"><a name="l12746"></a><span class="lineno">12746</span>&#160;            m_MemoryTypeIndex,</div>
+<div class="line"><a name="l12747"></a><span class="lineno">12747</span>&#160;            suballocType,</div>
+<div class="line"><a name="l12748"></a><span class="lineno">12748</span>&#160;            mapped,</div>
+<div class="line"><a name="l12749"></a><span class="lineno">12749</span>&#160;            (allocFlags &amp; <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a5f436af6c8fe8540573a6d22627a6fd2">VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT</a>) != 0);</div>
+<div class="line"><a name="l12750"></a><span class="lineno">12750</span>&#160;        VMA_HEAVY_ASSERT(pBlock-&gt;Validate());</div>
+<div class="line"><a name="l12751"></a><span class="lineno">12751</span>&#160;        (*pAllocation)-&gt;SetUserData(m_hAllocator, pUserData);</div>
+<div class="line"><a name="l12752"></a><span class="lineno">12752</span>&#160;        m_hAllocator-&gt;m_Budget.AddAllocation(m_hAllocator-&gt;MemoryTypeIndexToHeapIndex(m_MemoryTypeIndex), size);</div>
+<div class="line"><a name="l12753"></a><span class="lineno">12753</span>&#160;        <span class="keywordflow">if</span>(VMA_DEBUG_INITIALIZE_ALLOCATIONS)</div>
+<div class="line"><a name="l12754"></a><span class="lineno">12754</span>&#160;        {</div>
+<div class="line"><a name="l12755"></a><span class="lineno">12755</span>&#160;            m_hAllocator-&gt;FillAllocation(*pAllocation, VMA_ALLOCATION_FILL_PATTERN_CREATED);</div>
+<div class="line"><a name="l12756"></a><span class="lineno">12756</span>&#160;        }</div>
+<div class="line"><a name="l12757"></a><span class="lineno">12757</span>&#160;        <span class="keywordflow">if</span>(IsCorruptionDetectionEnabled())</div>
+<div class="line"><a name="l12758"></a><span class="lineno">12758</span>&#160;        {</div>
+<div class="line"><a name="l12759"></a><span class="lineno">12759</span>&#160;            VkResult res = pBlock-&gt;WriteMagicValueAroundAllocation(m_hAllocator, currRequest.offset, size);</div>
+<div class="line"><a name="l12760"></a><span class="lineno">12760</span>&#160;            VMA_ASSERT(res == VK_SUCCESS &amp;&amp; <span class="stringliteral">&quot;Couldn&#39;t map block memory to write magic value.&quot;</span>);</div>
+<div class="line"><a name="l12761"></a><span class="lineno">12761</span>&#160;        }</div>
+<div class="line"><a name="l12762"></a><span class="lineno">12762</span>&#160;        <span class="keywordflow">return</span> VK_SUCCESS;</div>
+<div class="line"><a name="l12763"></a><span class="lineno">12763</span>&#160;    }</div>
+<div class="line"><a name="l12764"></a><span class="lineno">12764</span>&#160;    <span class="keywordflow">return</span> VK_ERROR_OUT_OF_DEVICE_MEMORY;</div>
+<div class="line"><a name="l12765"></a><span class="lineno">12765</span>&#160;}</div>
+<div class="line"><a name="l12766"></a><span class="lineno">12766</span>&#160; </div>
+<div class="line"><a name="l12767"></a><span class="lineno">12767</span>&#160;VkResult VmaBlockVector::CreateBlock(VkDeviceSize blockSize, <span class="keywordtype">size_t</span>* pNewBlockIndex)</div>
+<div class="line"><a name="l12768"></a><span class="lineno">12768</span>&#160;{</div>
+<div class="line"><a name="l12769"></a><span class="lineno">12769</span>&#160;    VkMemoryAllocateInfo allocInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };</div>
+<div class="line"><a name="l12770"></a><span class="lineno">12770</span>&#160;    allocInfo.memoryTypeIndex = m_MemoryTypeIndex;</div>
+<div class="line"><a name="l12771"></a><span class="lineno">12771</span>&#160;    allocInfo.allocationSize = blockSize;</div>
+<div class="line"><a name="l12772"></a><span class="lineno">12772</span>&#160; </div>
+<div class="line"><a name="l12773"></a><span class="lineno">12773</span>&#160;<span class="preprocessor">#if VMA_BUFFER_DEVICE_ADDRESS</span></div>
+<div class="line"><a name="l12774"></a><span class="lineno">12774</span>&#160;    <span class="comment">// Every standalone block can potentially contain a buffer with VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT - always enable the feature.</span></div>
+<div class="line"><a name="l12775"></a><span class="lineno">12775</span>&#160;    VkMemoryAllocateFlagsInfoKHR allocFlagsInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO_KHR };</div>
+<div class="line"><a name="l12776"></a><span class="lineno">12776</span>&#160;    <span class="keywordflow">if</span>(m_hAllocator-&gt;m_UseKhrBufferDeviceAddress)</div>
+<div class="line"><a name="l12777"></a><span class="lineno">12777</span>&#160;    {</div>
+<div class="line"><a name="l12778"></a><span class="lineno">12778</span>&#160;        allocFlagsInfo.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR;</div>
+<div class="line"><a name="l12779"></a><span class="lineno">12779</span>&#160;        VmaPnextChainPushFront(&amp;allocInfo, &amp;allocFlagsInfo);</div>
+<div class="line"><a name="l12780"></a><span class="lineno">12780</span>&#160;    }</div>
+<div class="line"><a name="l12781"></a><span class="lineno">12781</span>&#160;<span class="preprocessor">#endif // #if VMA_BUFFER_DEVICE_ADDRESS</span></div>
+<div class="line"><a name="l12782"></a><span class="lineno">12782</span>&#160; </div>
+<div class="line"><a name="l12783"></a><span class="lineno">12783</span>&#160;    VkDeviceMemory mem = VK_NULL_HANDLE;</div>
+<div class="line"><a name="l12784"></a><span class="lineno">12784</span>&#160;    VkResult res = m_hAllocator-&gt;AllocateVulkanMemory(&amp;allocInfo, &amp;mem);</div>
+<div class="line"><a name="l12785"></a><span class="lineno">12785</span>&#160;    <span class="keywordflow">if</span>(res &lt; 0)</div>
+<div class="line"><a name="l12786"></a><span class="lineno">12786</span>&#160;    {</div>
+<div class="line"><a name="l12787"></a><span class="lineno">12787</span>&#160;        <span class="keywordflow">return</span> res;</div>
+<div class="line"><a name="l12788"></a><span class="lineno">12788</span>&#160;    }</div>
+<div class="line"><a name="l12789"></a><span class="lineno">12789</span>&#160; </div>
+<div class="line"><a name="l12790"></a><span class="lineno">12790</span>&#160;    <span class="comment">// New VkDeviceMemory successfully created.</span></div>
+<div class="line"><a name="l12791"></a><span class="lineno">12791</span>&#160; </div>
+<div class="line"><a name="l12792"></a><span class="lineno">12792</span>&#160;    <span class="comment">// Create new Allocation for it.</span></div>
+<div class="line"><a name="l12793"></a><span class="lineno">12793</span>&#160;    VmaDeviceMemoryBlock* <span class="keyword">const</span> pBlock = vma_new(m_hAllocator, VmaDeviceMemoryBlock)(m_hAllocator);</div>
+<div class="line"><a name="l12794"></a><span class="lineno">12794</span>&#160;    pBlock-&gt;Init(</div>
+<div class="line"><a name="l12795"></a><span class="lineno">12795</span>&#160;        m_hAllocator,</div>
+<div class="line"><a name="l12796"></a><span class="lineno">12796</span>&#160;        m_hParentPool,</div>
+<div class="line"><a name="l12797"></a><span class="lineno">12797</span>&#160;        m_MemoryTypeIndex,</div>
+<div class="line"><a name="l12798"></a><span class="lineno">12798</span>&#160;        mem,</div>
+<div class="line"><a name="l12799"></a><span class="lineno">12799</span>&#160;        allocInfo.allocationSize,</div>
+<div class="line"><a name="l12800"></a><span class="lineno">12800</span>&#160;        m_NextBlockId++,</div>
+<div class="line"><a name="l12801"></a><span class="lineno">12801</span>&#160;        m_Algorithm);</div>
+<div class="line"><a name="l12802"></a><span class="lineno">12802</span>&#160; </div>
+<div class="line"><a name="l12803"></a><span class="lineno">12803</span>&#160;    m_Blocks.push_back(pBlock);</div>
+<div class="line"><a name="l12804"></a><span class="lineno">12804</span>&#160;    <span class="keywordflow">if</span>(pNewBlockIndex != VMA_NULL)</div>
+<div class="line"><a name="l12805"></a><span class="lineno">12805</span>&#160;    {</div>
+<div class="line"><a name="l12806"></a><span class="lineno">12806</span>&#160;        *pNewBlockIndex = m_Blocks.size() - 1;</div>
+<div class="line"><a name="l12807"></a><span class="lineno">12807</span>&#160;    }</div>
+<div class="line"><a name="l12808"></a><span class="lineno">12808</span>&#160; </div>
+<div class="line"><a name="l12809"></a><span class="lineno">12809</span>&#160;    <span class="keywordflow">return</span> VK_SUCCESS;</div>
+<div class="line"><a name="l12810"></a><span class="lineno">12810</span>&#160;}</div>
+<div class="line"><a name="l12811"></a><span class="lineno">12811</span>&#160; </div>
+<div class="line"><a name="l12812"></a><span class="lineno">12812</span>&#160;<span class="keywordtype">void</span> VmaBlockVector::ApplyDefragmentationMovesCpu(</div>
+<div class="line"><a name="l12813"></a><span class="lineno">12813</span>&#160;    <span class="keyword">class</span> VmaBlockVectorDefragmentationContext* pDefragCtx,</div>
+<div class="line"><a name="l12814"></a><span class="lineno">12814</span>&#160;    <span class="keyword">const</span> VmaVector&lt; VmaDefragmentationMove, VmaStlAllocator&lt;VmaDefragmentationMove&gt; &gt;&amp; moves)</div>
+<div class="line"><a name="l12815"></a><span class="lineno">12815</span>&#160;{</div>
+<div class="line"><a name="l12816"></a><span class="lineno">12816</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">size_t</span> blockCount = m_Blocks.size();</div>
+<div class="line"><a name="l12817"></a><span class="lineno">12817</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">bool</span> isNonCoherent = m_hAllocator-&gt;IsMemoryTypeNonCoherent(m_MemoryTypeIndex);</div>
+<div class="line"><a name="l12818"></a><span class="lineno">12818</span>&#160; </div>
+<div class="line"><a name="l12819"></a><span class="lineno">12819</span>&#160;    <span class="keyword">enum</span> BLOCK_FLAG</div>
+<div class="line"><a name="l12820"></a><span class="lineno">12820</span>&#160;    {</div>
+<div class="line"><a name="l12821"></a><span class="lineno">12821</span>&#160;        BLOCK_FLAG_USED = 0x00000001,</div>
+<div class="line"><a name="l12822"></a><span class="lineno">12822</span>&#160;        BLOCK_FLAG_MAPPED_FOR_DEFRAGMENTATION = 0x00000002,</div>
+<div class="line"><a name="l12823"></a><span class="lineno">12823</span>&#160;    };</div>
+<div class="line"><a name="l12824"></a><span class="lineno">12824</span>&#160; </div>
+<div class="line"><a name="l12825"></a><span class="lineno">12825</span>&#160;    <span class="keyword">struct </span>BlockInfo</div>
+<div class="line"><a name="l12826"></a><span class="lineno">12826</span>&#160;    {</div>
+<div class="line"><a name="l12827"></a><span class="lineno">12827</span>&#160;        uint32_t flags;</div>
+<div class="line"><a name="l12828"></a><span class="lineno">12828</span>&#160;        <span class="keywordtype">void</span>* pMappedData;</div>
+<div class="line"><a name="l12829"></a><span class="lineno">12829</span>&#160;    };</div>
+<div class="line"><a name="l12830"></a><span class="lineno">12830</span>&#160;    VmaVector&lt; BlockInfo, VmaStlAllocator&lt;BlockInfo&gt; &gt;</div>
+<div class="line"><a name="l12831"></a><span class="lineno">12831</span>&#160;        blockInfo(blockCount, BlockInfo(), VmaStlAllocator&lt;BlockInfo&gt;(m_hAllocator-&gt;GetAllocationCallbacks()));</div>
+<div class="line"><a name="l12832"></a><span class="lineno">12832</span>&#160;    memset(blockInfo.data(), 0, blockCount * <span class="keyword">sizeof</span>(BlockInfo));</div>
+<div class="line"><a name="l12833"></a><span class="lineno">12833</span>&#160; </div>
+<div class="line"><a name="l12834"></a><span class="lineno">12834</span>&#160;    <span class="comment">// Go over all moves. Mark blocks that are used with BLOCK_FLAG_USED.</span></div>
+<div class="line"><a name="l12835"></a><span class="lineno">12835</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">size_t</span> moveCount = moves.size();</div>
+<div class="line"><a name="l12836"></a><span class="lineno">12836</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> moveIndex = 0; moveIndex &lt; moveCount; ++moveIndex)</div>
+<div class="line"><a name="l12837"></a><span class="lineno">12837</span>&#160;    {</div>
+<div class="line"><a name="l12838"></a><span class="lineno">12838</span>&#160;        <span class="keyword">const</span> VmaDefragmentationMove&amp; move = moves[moveIndex];</div>
+<div class="line"><a name="l12839"></a><span class="lineno">12839</span>&#160;        blockInfo[move.srcBlockIndex].flags |= BLOCK_FLAG_USED;</div>
+<div class="line"><a name="l12840"></a><span class="lineno">12840</span>&#160;        blockInfo[move.dstBlockIndex].flags |= BLOCK_FLAG_USED;</div>
+<div class="line"><a name="l12841"></a><span class="lineno">12841</span>&#160;    }</div>
+<div class="line"><a name="l12842"></a><span class="lineno">12842</span>&#160; </div>
+<div class="line"><a name="l12843"></a><span class="lineno">12843</span>&#160;    VMA_ASSERT(pDefragCtx-&gt;res == VK_SUCCESS);</div>
+<div class="line"><a name="l12844"></a><span class="lineno">12844</span>&#160; </div>
+<div class="line"><a name="l12845"></a><span class="lineno">12845</span>&#160;    <span class="comment">// Go over all blocks. Get mapped pointer or map if necessary.</span></div>
+<div class="line"><a name="l12846"></a><span class="lineno">12846</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> blockIndex = 0; pDefragCtx-&gt;res == VK_SUCCESS &amp;&amp; blockIndex &lt; blockCount; ++blockIndex)</div>
+<div class="line"><a name="l12847"></a><span class="lineno">12847</span>&#160;    {</div>
+<div class="line"><a name="l12848"></a><span class="lineno">12848</span>&#160;        BlockInfo&amp; currBlockInfo = blockInfo[blockIndex];</div>
+<div class="line"><a name="l12849"></a><span class="lineno">12849</span>&#160;        VmaDeviceMemoryBlock* pBlock = m_Blocks[blockIndex];</div>
+<div class="line"><a name="l12850"></a><span class="lineno">12850</span>&#160;        <span class="keywordflow">if</span>((currBlockInfo.flags &amp; BLOCK_FLAG_USED) != 0)</div>
+<div class="line"><a name="l12851"></a><span class="lineno">12851</span>&#160;        {</div>
+<div class="line"><a name="l12852"></a><span class="lineno">12852</span>&#160;            currBlockInfo.pMappedData = pBlock-&gt;GetMappedData();</div>
+<div class="line"><a name="l12853"></a><span class="lineno">12853</span>&#160;            <span class="comment">// It is not originally mapped - map it.</span></div>
+<div class="line"><a name="l12854"></a><span class="lineno">12854</span>&#160;            <span class="keywordflow">if</span>(currBlockInfo.pMappedData == VMA_NULL)</div>
+<div class="line"><a name="l12855"></a><span class="lineno">12855</span>&#160;            {</div>
+<div class="line"><a name="l12856"></a><span class="lineno">12856</span>&#160;                pDefragCtx-&gt;res = pBlock-&gt;Map(m_hAllocator, 1, &amp;currBlockInfo.pMappedData);</div>
+<div class="line"><a name="l12857"></a><span class="lineno">12857</span>&#160;                <span class="keywordflow">if</span>(pDefragCtx-&gt;res == VK_SUCCESS)</div>
+<div class="line"><a name="l12858"></a><span class="lineno">12858</span>&#160;                {</div>
+<div class="line"><a name="l12859"></a><span class="lineno">12859</span>&#160;                    currBlockInfo.flags |= BLOCK_FLAG_MAPPED_FOR_DEFRAGMENTATION;</div>
+<div class="line"><a name="l12860"></a><span class="lineno">12860</span>&#160;                }</div>
+<div class="line"><a name="l12861"></a><span class="lineno">12861</span>&#160;            }</div>
+<div class="line"><a name="l12862"></a><span class="lineno">12862</span>&#160;        }</div>
+<div class="line"><a name="l12863"></a><span class="lineno">12863</span>&#160;    }</div>
+<div class="line"><a name="l12864"></a><span class="lineno">12864</span>&#160; </div>
+<div class="line"><a name="l12865"></a><span class="lineno">12865</span>&#160;    <span class="comment">// Go over all moves. Do actual data transfer.</span></div>
+<div class="line"><a name="l12866"></a><span class="lineno">12866</span>&#160;    <span class="keywordflow">if</span>(pDefragCtx-&gt;res == VK_SUCCESS)</div>
+<div class="line"><a name="l12867"></a><span class="lineno">12867</span>&#160;    {</div>
+<div class="line"><a name="l12868"></a><span class="lineno">12868</span>&#160;        <span class="keyword">const</span> VkDeviceSize nonCoherentAtomSize = m_hAllocator-&gt;m_PhysicalDeviceProperties.limits.nonCoherentAtomSize;</div>
+<div class="line"><a name="l12869"></a><span class="lineno">12869</span>&#160;        VkMappedMemoryRange memRange = { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE };</div>
+<div class="line"><a name="l12870"></a><span class="lineno">12870</span>&#160; </div>
+<div class="line"><a name="l12871"></a><span class="lineno">12871</span>&#160;        <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> moveIndex = 0; moveIndex &lt; moveCount; ++moveIndex)</div>
+<div class="line"><a name="l12872"></a><span class="lineno">12872</span>&#160;        {</div>
+<div class="line"><a name="l12873"></a><span class="lineno">12873</span>&#160;            <span class="keyword">const</span> VmaDefragmentationMove&amp; move = moves[moveIndex];</div>
+<div class="line"><a name="l12874"></a><span class="lineno">12874</span>&#160; </div>
+<div class="line"><a name="l12875"></a><span class="lineno">12875</span>&#160;            <span class="keyword">const</span> BlockInfo&amp; srcBlockInfo = blockInfo[move.srcBlockIndex];</div>
+<div class="line"><a name="l12876"></a><span class="lineno">12876</span>&#160;            <span class="keyword">const</span> BlockInfo&amp; dstBlockInfo = blockInfo[move.dstBlockIndex];</div>
+<div class="line"><a name="l12877"></a><span class="lineno">12877</span>&#160; </div>
+<div class="line"><a name="l12878"></a><span class="lineno">12878</span>&#160;            VMA_ASSERT(srcBlockInfo.pMappedData &amp;&amp; dstBlockInfo.pMappedData);</div>
+<div class="line"><a name="l12879"></a><span class="lineno">12879</span>&#160; </div>
+<div class="line"><a name="l12880"></a><span class="lineno">12880</span>&#160;            <span class="comment">// Invalidate source.</span></div>
+<div class="line"><a name="l12881"></a><span class="lineno">12881</span>&#160;            <span class="keywordflow">if</span>(isNonCoherent)</div>
+<div class="line"><a name="l12882"></a><span class="lineno">12882</span>&#160;            {</div>
+<div class="line"><a name="l12883"></a><span class="lineno">12883</span>&#160;                VmaDeviceMemoryBlock* <span class="keyword">const</span> pSrcBlock = m_Blocks[move.srcBlockIndex];</div>
+<div class="line"><a name="l12884"></a><span class="lineno">12884</span>&#160;                memRange.memory = pSrcBlock-&gt;GetDeviceMemory();</div>
+<div class="line"><a name="l12885"></a><span class="lineno">12885</span>&#160;                memRange.offset = VmaAlignDown(move.srcOffset, nonCoherentAtomSize);</div>
+<div class="line"><a name="l12886"></a><span class="lineno">12886</span>&#160;                memRange.size = VMA_MIN(</div>
+<div class="line"><a name="l12887"></a><span class="lineno">12887</span>&#160;                    VmaAlignUp(move.size + (move.srcOffset - memRange.offset), nonCoherentAtomSize),</div>
+<div class="line"><a name="l12888"></a><span class="lineno">12888</span>&#160;                    pSrcBlock-&gt;m_pMetadata-&gt;GetSize() - memRange.offset);</div>
+<div class="line"><a name="l12889"></a><span class="lineno">12889</span>&#160;                (*m_hAllocator-&gt;GetVulkanFunctions().vkInvalidateMappedMemoryRanges)(m_hAllocator-&gt;m_hDevice, 1, &amp;memRange);</div>
+<div class="line"><a name="l12890"></a><span class="lineno">12890</span>&#160;            }</div>
+<div class="line"><a name="l12891"></a><span class="lineno">12891</span>&#160; </div>
+<div class="line"><a name="l12892"></a><span class="lineno">12892</span>&#160;            <span class="comment">// THE PLACE WHERE ACTUAL DATA COPY HAPPENS.</span></div>
+<div class="line"><a name="l12893"></a><span class="lineno">12893</span>&#160;            memmove(</div>
+<div class="line"><a name="l12894"></a><span class="lineno">12894</span>&#160;                <span class="keyword">reinterpret_cast&lt;</span><span class="keywordtype">char</span>*<span class="keyword">&gt;</span>(dstBlockInfo.pMappedData) + move.dstOffset,</div>
+<div class="line"><a name="l12895"></a><span class="lineno">12895</span>&#160;                <span class="keyword">reinterpret_cast&lt;</span><span class="keywordtype">char</span>*<span class="keyword">&gt;</span>(srcBlockInfo.pMappedData) + move.srcOffset,</div>
+<div class="line"><a name="l12896"></a><span class="lineno">12896</span>&#160;                <span class="keyword">static_cast&lt;</span><span class="keywordtype">size_t</span><span class="keyword">&gt;</span>(move.size));</div>
+<div class="line"><a name="l12897"></a><span class="lineno">12897</span>&#160; </div>
+<div class="line"><a name="l12898"></a><span class="lineno">12898</span>&#160;            <span class="keywordflow">if</span>(IsCorruptionDetectionEnabled())</div>
+<div class="line"><a name="l12899"></a><span class="lineno">12899</span>&#160;            {</div>
+<div class="line"><a name="l12900"></a><span class="lineno">12900</span>&#160;                VmaWriteMagicValue(dstBlockInfo.pMappedData, move.dstOffset - VMA_DEBUG_MARGIN);</div>
+<div class="line"><a name="l12901"></a><span class="lineno">12901</span>&#160;                VmaWriteMagicValue(dstBlockInfo.pMappedData, move.dstOffset + move.size);</div>
+<div class="line"><a name="l12902"></a><span class="lineno">12902</span>&#160;            }</div>
+<div class="line"><a name="l12903"></a><span class="lineno">12903</span>&#160; </div>
+<div class="line"><a name="l12904"></a><span class="lineno">12904</span>&#160;            <span class="comment">// Flush destination.</span></div>
+<div class="line"><a name="l12905"></a><span class="lineno">12905</span>&#160;            <span class="keywordflow">if</span>(isNonCoherent)</div>
+<div class="line"><a name="l12906"></a><span class="lineno">12906</span>&#160;            {</div>
+<div class="line"><a name="l12907"></a><span class="lineno">12907</span>&#160;                VmaDeviceMemoryBlock* <span class="keyword">const</span> pDstBlock = m_Blocks[move.dstBlockIndex];</div>
+<div class="line"><a name="l12908"></a><span class="lineno">12908</span>&#160;                memRange.memory = pDstBlock-&gt;GetDeviceMemory();</div>
+<div class="line"><a name="l12909"></a><span class="lineno">12909</span>&#160;                memRange.offset = VmaAlignDown(move.dstOffset, nonCoherentAtomSize);</div>
+<div class="line"><a name="l12910"></a><span class="lineno">12910</span>&#160;                memRange.size = VMA_MIN(</div>
+<div class="line"><a name="l12911"></a><span class="lineno">12911</span>&#160;                    VmaAlignUp(move.size + (move.dstOffset - memRange.offset), nonCoherentAtomSize),</div>
+<div class="line"><a name="l12912"></a><span class="lineno">12912</span>&#160;                    pDstBlock-&gt;m_pMetadata-&gt;GetSize() - memRange.offset);</div>
+<div class="line"><a name="l12913"></a><span class="lineno">12913</span>&#160;                (*m_hAllocator-&gt;GetVulkanFunctions().vkFlushMappedMemoryRanges)(m_hAllocator-&gt;m_hDevice, 1, &amp;memRange);</div>
+<div class="line"><a name="l12914"></a><span class="lineno">12914</span>&#160;            }</div>
+<div class="line"><a name="l12915"></a><span class="lineno">12915</span>&#160;        }</div>
+<div class="line"><a name="l12916"></a><span class="lineno">12916</span>&#160;    }</div>
+<div class="line"><a name="l12917"></a><span class="lineno">12917</span>&#160; </div>
+<div class="line"><a name="l12918"></a><span class="lineno">12918</span>&#160;    <span class="comment">// Go over all blocks in reverse order. Unmap those that were mapped just for defragmentation.</span></div>
+<div class="line"><a name="l12919"></a><span class="lineno">12919</span>&#160;    <span class="comment">// Regardless of pCtx-&gt;res == VK_SUCCESS.</span></div>
+<div class="line"><a name="l12920"></a><span class="lineno">12920</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> blockIndex = blockCount; blockIndex--; )</div>
+<div class="line"><a name="l12921"></a><span class="lineno">12921</span>&#160;    {</div>
+<div class="line"><a name="l12922"></a><span class="lineno">12922</span>&#160;        <span class="keyword">const</span> BlockInfo&amp; currBlockInfo = blockInfo[blockIndex];</div>
+<div class="line"><a name="l12923"></a><span class="lineno">12923</span>&#160;        <span class="keywordflow">if</span>((currBlockInfo.flags &amp; BLOCK_FLAG_MAPPED_FOR_DEFRAGMENTATION) != 0)</div>
+<div class="line"><a name="l12924"></a><span class="lineno">12924</span>&#160;        {</div>
+<div class="line"><a name="l12925"></a><span class="lineno">12925</span>&#160;            VmaDeviceMemoryBlock* pBlock = m_Blocks[blockIndex];</div>
+<div class="line"><a name="l12926"></a><span class="lineno">12926</span>&#160;            pBlock-&gt;Unmap(m_hAllocator, 1);</div>
+<div class="line"><a name="l12927"></a><span class="lineno">12927</span>&#160;        }</div>
+<div class="line"><a name="l12928"></a><span class="lineno">12928</span>&#160;    }</div>
+<div class="line"><a name="l12929"></a><span class="lineno">12929</span>&#160;}</div>
+<div class="line"><a name="l12930"></a><span class="lineno">12930</span>&#160; </div>
+<div class="line"><a name="l12931"></a><span class="lineno">12931</span>&#160;<span class="keywordtype">void</span> VmaBlockVector::ApplyDefragmentationMovesGpu(</div>
+<div class="line"><a name="l12932"></a><span class="lineno">12932</span>&#160;    <span class="keyword">class</span> VmaBlockVectorDefragmentationContext* pDefragCtx,</div>
+<div class="line"><a name="l12933"></a><span class="lineno">12933</span>&#160;    VmaVector&lt; VmaDefragmentationMove, VmaStlAllocator&lt;VmaDefragmentationMove&gt; &gt;&amp; moves,</div>
+<div class="line"><a name="l12934"></a><span class="lineno">12934</span>&#160;    VkCommandBuffer commandBuffer)</div>
+<div class="line"><a name="l12935"></a><span class="lineno">12935</span>&#160;{</div>
+<div class="line"><a name="l12936"></a><span class="lineno">12936</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">size_t</span> blockCount = m_Blocks.size();</div>
+<div class="line"><a name="l12937"></a><span class="lineno">12937</span>&#160; </div>
+<div class="line"><a name="l12938"></a><span class="lineno">12938</span>&#160;    pDefragCtx-&gt;blockContexts.resize(blockCount);</div>
+<div class="line"><a name="l12939"></a><span class="lineno">12939</span>&#160;    memset(pDefragCtx-&gt;blockContexts.data(), 0, blockCount * <span class="keyword">sizeof</span>(VmaBlockDefragmentationContext));</div>
+<div class="line"><a name="l12940"></a><span class="lineno">12940</span>&#160; </div>
+<div class="line"><a name="l12941"></a><span class="lineno">12941</span>&#160;    <span class="comment">// Go over all moves. Mark blocks that are used with BLOCK_FLAG_USED.</span></div>
+<div class="line"><a name="l12942"></a><span class="lineno">12942</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">size_t</span> moveCount = moves.size();</div>
+<div class="line"><a name="l12943"></a><span class="lineno">12943</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> moveIndex = 0; moveIndex &lt; moveCount; ++moveIndex)</div>
+<div class="line"><a name="l12944"></a><span class="lineno">12944</span>&#160;    {</div>
+<div class="line"><a name="l12945"></a><span class="lineno">12945</span>&#160;        <span class="keyword">const</span> VmaDefragmentationMove&amp; move = moves[moveIndex];</div>
+<div class="line"><a name="l12946"></a><span class="lineno">12946</span>&#160; </div>
+<div class="line"><a name="l12947"></a><span class="lineno">12947</span>&#160;        <span class="comment">//if(move.type == VMA_ALLOCATION_TYPE_UNKNOWN)</span></div>
+<div class="line"><a name="l12948"></a><span class="lineno">12948</span>&#160;        {</div>
+<div class="line"><a name="l12949"></a><span class="lineno">12949</span>&#160;            <span class="comment">// Old school move still require us to map the whole block</span></div>
+<div class="line"><a name="l12950"></a><span class="lineno">12950</span>&#160;            pDefragCtx-&gt;blockContexts[move.srcBlockIndex].flags |= VmaBlockDefragmentationContext::BLOCK_FLAG_USED;</div>
+<div class="line"><a name="l12951"></a><span class="lineno">12951</span>&#160;            pDefragCtx-&gt;blockContexts[move.dstBlockIndex].flags |= VmaBlockDefragmentationContext::BLOCK_FLAG_USED;</div>
+<div class="line"><a name="l12952"></a><span class="lineno">12952</span>&#160;        }</div>
+<div class="line"><a name="l12953"></a><span class="lineno">12953</span>&#160;    }</div>
+<div class="line"><a name="l12954"></a><span class="lineno">12954</span>&#160; </div>
+<div class="line"><a name="l12955"></a><span class="lineno">12955</span>&#160;    VMA_ASSERT(pDefragCtx-&gt;res == VK_SUCCESS);</div>
+<div class="line"><a name="l12956"></a><span class="lineno">12956</span>&#160; </div>
+<div class="line"><a name="l12957"></a><span class="lineno">12957</span>&#160;    <span class="comment">// Go over all blocks. Create and bind buffer for whole block if necessary.</span></div>
+<div class="line"><a name="l12958"></a><span class="lineno">12958</span>&#160;    {</div>
+<div class="line"><a name="l12959"></a><span class="lineno">12959</span>&#160;        VkBufferCreateInfo bufCreateInfo;</div>
+<div class="line"><a name="l12960"></a><span class="lineno">12960</span>&#160;        VmaFillGpuDefragmentationBufferCreateInfo(bufCreateInfo);</div>
+<div class="line"><a name="l12961"></a><span class="lineno">12961</span>&#160; </div>
+<div class="line"><a name="l12962"></a><span class="lineno">12962</span>&#160;        <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> blockIndex = 0; pDefragCtx-&gt;res == VK_SUCCESS &amp;&amp; blockIndex &lt; blockCount; ++blockIndex)</div>
+<div class="line"><a name="l12963"></a><span class="lineno">12963</span>&#160;        {</div>
+<div class="line"><a name="l12964"></a><span class="lineno">12964</span>&#160;            VmaBlockDefragmentationContext&amp; currBlockCtx = pDefragCtx-&gt;blockContexts[blockIndex];</div>
+<div class="line"><a name="l12965"></a><span class="lineno">12965</span>&#160;            VmaDeviceMemoryBlock* pBlock = m_Blocks[blockIndex];</div>
+<div class="line"><a name="l12966"></a><span class="lineno">12966</span>&#160;            <span class="keywordflow">if</span>((currBlockCtx.flags &amp; VmaBlockDefragmentationContext::BLOCK_FLAG_USED) != 0)</div>
+<div class="line"><a name="l12967"></a><span class="lineno">12967</span>&#160;            {</div>
+<div class="line"><a name="l12968"></a><span class="lineno">12968</span>&#160;                bufCreateInfo.size = pBlock-&gt;m_pMetadata-&gt;GetSize();</div>
+<div class="line"><a name="l12969"></a><span class="lineno">12969</span>&#160;                pDefragCtx-&gt;res = (*m_hAllocator-&gt;GetVulkanFunctions().vkCreateBuffer)(</div>
+<div class="line"><a name="l12970"></a><span class="lineno">12970</span>&#160;                    m_hAllocator-&gt;m_hDevice, &amp;bufCreateInfo, m_hAllocator-&gt;GetAllocationCallbacks(), &amp;currBlockCtx.hBuffer);</div>
+<div class="line"><a name="l12971"></a><span class="lineno">12971</span>&#160;                <span class="keywordflow">if</span>(pDefragCtx-&gt;res == VK_SUCCESS)</div>
+<div class="line"><a name="l12972"></a><span class="lineno">12972</span>&#160;                {</div>
+<div class="line"><a name="l12973"></a><span class="lineno">12973</span>&#160;                    pDefragCtx-&gt;res = (*m_hAllocator-&gt;GetVulkanFunctions().vkBindBufferMemory)(</div>
+<div class="line"><a name="l12974"></a><span class="lineno">12974</span>&#160;                        m_hAllocator-&gt;m_hDevice, currBlockCtx.hBuffer, pBlock-&gt;GetDeviceMemory(), 0);</div>
+<div class="line"><a name="l12975"></a><span class="lineno">12975</span>&#160;                }</div>
+<div class="line"><a name="l12976"></a><span class="lineno">12976</span>&#160;            }</div>
+<div class="line"><a name="l12977"></a><span class="lineno">12977</span>&#160;        }</div>
+<div class="line"><a name="l12978"></a><span class="lineno">12978</span>&#160;    }</div>
+<div class="line"><a name="l12979"></a><span class="lineno">12979</span>&#160; </div>
+<div class="line"><a name="l12980"></a><span class="lineno">12980</span>&#160;    <span class="comment">// Go over all moves. Post data transfer commands to command buffer.</span></div>
+<div class="line"><a name="l12981"></a><span class="lineno">12981</span>&#160;    <span class="keywordflow">if</span>(pDefragCtx-&gt;res == VK_SUCCESS)</div>
+<div class="line"><a name="l12982"></a><span class="lineno">12982</span>&#160;    {</div>
+<div class="line"><a name="l12983"></a><span class="lineno">12983</span>&#160;        <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> moveIndex = 0; moveIndex &lt; moveCount; ++moveIndex)</div>
+<div class="line"><a name="l12984"></a><span class="lineno">12984</span>&#160;        {</div>
+<div class="line"><a name="l12985"></a><span class="lineno">12985</span>&#160;            <span class="keyword">const</span> VmaDefragmentationMove&amp; move = moves[moveIndex];</div>
+<div class="line"><a name="l12986"></a><span class="lineno">12986</span>&#160; </div>
+<div class="line"><a name="l12987"></a><span class="lineno">12987</span>&#160;            <span class="keyword">const</span> VmaBlockDefragmentationContext&amp; srcBlockCtx = pDefragCtx-&gt;blockContexts[move.srcBlockIndex];</div>
+<div class="line"><a name="l12988"></a><span class="lineno">12988</span>&#160;            <span class="keyword">const</span> VmaBlockDefragmentationContext&amp; dstBlockCtx = pDefragCtx-&gt;blockContexts[move.dstBlockIndex];</div>
+<div class="line"><a name="l12989"></a><span class="lineno">12989</span>&#160; </div>
+<div class="line"><a name="l12990"></a><span class="lineno">12990</span>&#160;            VMA_ASSERT(srcBlockCtx.hBuffer &amp;&amp; dstBlockCtx.hBuffer);</div>
+<div class="line"><a name="l12991"></a><span class="lineno">12991</span>&#160; </div>
+<div class="line"><a name="l12992"></a><span class="lineno">12992</span>&#160;            VkBufferCopy region = {</div>
+<div class="line"><a name="l12993"></a><span class="lineno">12993</span>&#160;                move.srcOffset,</div>
+<div class="line"><a name="l12994"></a><span class="lineno">12994</span>&#160;                move.dstOffset,</div>
+<div class="line"><a name="l12995"></a><span class="lineno">12995</span>&#160;                move.size };</div>
+<div class="line"><a name="l12996"></a><span class="lineno">12996</span>&#160;            (*m_hAllocator-&gt;GetVulkanFunctions().vkCmdCopyBuffer)(</div>
+<div class="line"><a name="l12997"></a><span class="lineno">12997</span>&#160;                commandBuffer, srcBlockCtx.hBuffer, dstBlockCtx.hBuffer, 1, &amp;region);</div>
+<div class="line"><a name="l12998"></a><span class="lineno">12998</span>&#160;        }</div>
+<div class="line"><a name="l12999"></a><span class="lineno">12999</span>&#160;    }</div>
+<div class="line"><a name="l13000"></a><span class="lineno">13000</span>&#160; </div>
+<div class="line"><a name="l13001"></a><span class="lineno">13001</span>&#160;    <span class="comment">// Save buffers to defrag context for later destruction.</span></div>
+<div class="line"><a name="l13002"></a><span class="lineno">13002</span>&#160;    <span class="keywordflow">if</span>(pDefragCtx-&gt;res == VK_SUCCESS &amp;&amp; moveCount &gt; 0)</div>
+<div class="line"><a name="l13003"></a><span class="lineno">13003</span>&#160;    {</div>
+<div class="line"><a name="l13004"></a><span class="lineno">13004</span>&#160;        pDefragCtx-&gt;res = VK_NOT_READY;</div>
+<div class="line"><a name="l13005"></a><span class="lineno">13005</span>&#160;    }</div>
+<div class="line"><a name="l13006"></a><span class="lineno">13006</span>&#160;}</div>
+<div class="line"><a name="l13007"></a><span class="lineno">13007</span>&#160; </div>
+<div class="line"><a name="l13008"></a><span class="lineno">13008</span>&#160;<span class="keywordtype">void</span> VmaBlockVector::FreeEmptyBlocks(<a class="code" href="struct_vma_defragmentation_stats.html">VmaDefragmentationStats</a>* pDefragmentationStats)</div>
+<div class="line"><a name="l13009"></a><span class="lineno">13009</span>&#160;{</div>
+<div class="line"><a name="l13010"></a><span class="lineno">13010</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> blockIndex = m_Blocks.size(); blockIndex--; )</div>
+<div class="line"><a name="l13011"></a><span class="lineno">13011</span>&#160;    {</div>
+<div class="line"><a name="l13012"></a><span class="lineno">13012</span>&#160;        VmaDeviceMemoryBlock* pBlock = m_Blocks[blockIndex];</div>
+<div class="line"><a name="l13013"></a><span class="lineno">13013</span>&#160;        <span class="keywordflow">if</span>(pBlock-&gt;m_pMetadata-&gt;IsEmpty())</div>
+<div class="line"><a name="l13014"></a><span class="lineno">13014</span>&#160;        {</div>
+<div class="line"><a name="l13015"></a><span class="lineno">13015</span>&#160;            <span class="keywordflow">if</span>(m_Blocks.size() &gt; m_MinBlockCount)</div>
+<div class="line"><a name="l13016"></a><span class="lineno">13016</span>&#160;            {</div>
+<div class="line"><a name="l13017"></a><span class="lineno">13017</span>&#160;                <span class="keywordflow">if</span>(pDefragmentationStats != VMA_NULL)</div>
+<div class="line"><a name="l13018"></a><span class="lineno">13018</span>&#160;                {</div>
+<div class="line"><a name="l13019"></a><span class="lineno">13019</span>&#160;                    ++pDefragmentationStats-&gt;<a class="code" href="struct_vma_defragmentation_stats.html#a0113f1877904a5d1ee8f409216ff276b">deviceMemoryBlocksFreed</a>;</div>
+<div class="line"><a name="l13020"></a><span class="lineno">13020</span>&#160;                    pDefragmentationStats-&gt;<a class="code" href="struct_vma_defragmentation_stats.html#ab0cb9ac0dbc106c77e384ea676422f28">bytesFreed</a> += pBlock-&gt;m_pMetadata-&gt;GetSize();</div>
+<div class="line"><a name="l13021"></a><span class="lineno">13021</span>&#160;                }</div>
+<div class="line"><a name="l13022"></a><span class="lineno">13022</span>&#160; </div>
+<div class="line"><a name="l13023"></a><span class="lineno">13023</span>&#160;                VmaVectorRemove(m_Blocks, blockIndex);</div>
+<div class="line"><a name="l13024"></a><span class="lineno">13024</span>&#160;                pBlock-&gt;Destroy(m_hAllocator);</div>
+<div class="line"><a name="l13025"></a><span class="lineno">13025</span>&#160;                vma_delete(m_hAllocator, pBlock);</div>
+<div class="line"><a name="l13026"></a><span class="lineno">13026</span>&#160;            }</div>
+<div class="line"><a name="l13027"></a><span class="lineno">13027</span>&#160;            <span class="keywordflow">else</span></div>
+<div class="line"><a name="l13028"></a><span class="lineno">13028</span>&#160;            {</div>
+<div class="line"><a name="l13029"></a><span class="lineno">13029</span>&#160;                <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l13030"></a><span class="lineno">13030</span>&#160;            }</div>
+<div class="line"><a name="l13031"></a><span class="lineno">13031</span>&#160;        }</div>
+<div class="line"><a name="l13032"></a><span class="lineno">13032</span>&#160;    }</div>
+<div class="line"><a name="l13033"></a><span class="lineno">13033</span>&#160;    UpdateHasEmptyBlock();</div>
+<div class="line"><a name="l13034"></a><span class="lineno">13034</span>&#160;}</div>
+<div class="line"><a name="l13035"></a><span class="lineno">13035</span>&#160; </div>
+<div class="line"><a name="l13036"></a><span class="lineno">13036</span>&#160;<span class="keywordtype">void</span> VmaBlockVector::UpdateHasEmptyBlock()</div>
+<div class="line"><a name="l13037"></a><span class="lineno">13037</span>&#160;{</div>
+<div class="line"><a name="l13038"></a><span class="lineno">13038</span>&#160;    m_HasEmptyBlock = <span class="keyword">false</span>;</div>
+<div class="line"><a name="l13039"></a><span class="lineno">13039</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> index = 0, count = m_Blocks.size(); index &lt; count; ++index)</div>
+<div class="line"><a name="l13040"></a><span class="lineno">13040</span>&#160;    {</div>
+<div class="line"><a name="l13041"></a><span class="lineno">13041</span>&#160;        VmaDeviceMemoryBlock* <span class="keyword">const</span> pBlock = m_Blocks[index];</div>
+<div class="line"><a name="l13042"></a><span class="lineno">13042</span>&#160;        <span class="keywordflow">if</span>(pBlock-&gt;m_pMetadata-&gt;IsEmpty())</div>
+<div class="line"><a name="l13043"></a><span class="lineno">13043</span>&#160;        {</div>
+<div class="line"><a name="l13044"></a><span class="lineno">13044</span>&#160;            m_HasEmptyBlock = <span class="keyword">true</span>;</div>
+<div class="line"><a name="l13045"></a><span class="lineno">13045</span>&#160;            <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l13046"></a><span class="lineno">13046</span>&#160;        }</div>
+<div class="line"><a name="l13047"></a><span class="lineno">13047</span>&#160;    }</div>
+<div class="line"><a name="l13048"></a><span class="lineno">13048</span>&#160;}</div>
+<div class="line"><a name="l13049"></a><span class="lineno">13049</span>&#160; </div>
+<div class="line"><a name="l13050"></a><span class="lineno">13050</span>&#160;<span class="preprocessor">#if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l13051"></a><span class="lineno">13051</span>&#160; </div>
+<div class="line"><a name="l13052"></a><span class="lineno">13052</span>&#160;<span class="keywordtype">void</span> VmaBlockVector::PrintDetailedMap(<span class="keyword">class</span> VmaJsonWriter&amp; json)</div>
+<div class="line"><a name="l13053"></a><span class="lineno">13053</span>&#160;{</div>
+<div class="line"><a name="l13054"></a><span class="lineno">13054</span>&#160;    VmaMutexLockRead lock(m_Mutex, m_hAllocator-&gt;m_UseMutex);</div>
+<div class="line"><a name="l13055"></a><span class="lineno">13055</span>&#160; </div>
+<div class="line"><a name="l13056"></a><span class="lineno">13056</span>&#160;    json.BeginObject();</div>
+<div class="line"><a name="l13057"></a><span class="lineno">13057</span>&#160; </div>
+<div class="line"><a name="l13058"></a><span class="lineno">13058</span>&#160;    <span class="keywordflow">if</span>(IsCustomPool())</div>
+<div class="line"><a name="l13059"></a><span class="lineno">13059</span>&#160;    {</div>
+<div class="line"><a name="l13060"></a><span class="lineno">13060</span>&#160;        <span class="keyword">const</span> <span class="keywordtype">char</span>* poolName = m_hParentPool-&gt;GetName();</div>
+<div class="line"><a name="l13061"></a><span class="lineno">13061</span>&#160;        <span class="keywordflow">if</span>(poolName != VMA_NULL &amp;&amp; poolName[0] != <span class="charliteral">&#39;\0&#39;</span>)</div>
+<div class="line"><a name="l13062"></a><span class="lineno">13062</span>&#160;        {</div>
+<div class="line"><a name="l13063"></a><span class="lineno">13063</span>&#160;            json.WriteString(<span class="stringliteral">&quot;Name&quot;</span>);</div>
+<div class="line"><a name="l13064"></a><span class="lineno">13064</span>&#160;            json.WriteString(poolName);</div>
+<div class="line"><a name="l13065"></a><span class="lineno">13065</span>&#160;        }</div>
+<div class="line"><a name="l13066"></a><span class="lineno">13066</span>&#160; </div>
+<div class="line"><a name="l13067"></a><span class="lineno">13067</span>&#160;        json.WriteString(<span class="stringliteral">&quot;MemoryTypeIndex&quot;</span>);</div>
+<div class="line"><a name="l13068"></a><span class="lineno">13068</span>&#160;        json.WriteNumber(m_MemoryTypeIndex);</div>
+<div class="line"><a name="l13069"></a><span class="lineno">13069</span>&#160; </div>
+<div class="line"><a name="l13070"></a><span class="lineno">13070</span>&#160;        json.WriteString(<span class="stringliteral">&quot;BlockSize&quot;</span>);</div>
+<div class="line"><a name="l13071"></a><span class="lineno">13071</span>&#160;        json.WriteNumber(m_PreferredBlockSize);</div>
+<div class="line"><a name="l13072"></a><span class="lineno">13072</span>&#160; </div>
+<div class="line"><a name="l13073"></a><span class="lineno">13073</span>&#160;        json.WriteString(<span class="stringliteral">&quot;BlockCount&quot;</span>);</div>
+<div class="line"><a name="l13074"></a><span class="lineno">13074</span>&#160;        json.BeginObject(<span class="keyword">true</span>);</div>
+<div class="line"><a name="l13075"></a><span class="lineno">13075</span>&#160;        <span class="keywordflow">if</span>(m_MinBlockCount &gt; 0)</div>
+<div class="line"><a name="l13076"></a><span class="lineno">13076</span>&#160;        {</div>
+<div class="line"><a name="l13077"></a><span class="lineno">13077</span>&#160;            json.WriteString(<span class="stringliteral">&quot;Min&quot;</span>);</div>
+<div class="line"><a name="l13078"></a><span class="lineno">13078</span>&#160;            json.WriteNumber((uint64_t)m_MinBlockCount);</div>
+<div class="line"><a name="l13079"></a><span class="lineno">13079</span>&#160;        }</div>
+<div class="line"><a name="l13080"></a><span class="lineno">13080</span>&#160;        <span class="keywordflow">if</span>(m_MaxBlockCount &lt; SIZE_MAX)</div>
+<div class="line"><a name="l13081"></a><span class="lineno">13081</span>&#160;        {</div>
+<div class="line"><a name="l13082"></a><span class="lineno">13082</span>&#160;            json.WriteString(<span class="stringliteral">&quot;Max&quot;</span>);</div>
+<div class="line"><a name="l13083"></a><span class="lineno">13083</span>&#160;            json.WriteNumber((uint64_t)m_MaxBlockCount);</div>
+<div class="line"><a name="l13084"></a><span class="lineno">13084</span>&#160;        }</div>
+<div class="line"><a name="l13085"></a><span class="lineno">13085</span>&#160;        json.WriteString(<span class="stringliteral">&quot;Cur&quot;</span>);</div>
+<div class="line"><a name="l13086"></a><span class="lineno">13086</span>&#160;        json.WriteNumber((uint64_t)m_Blocks.size());</div>
+<div class="line"><a name="l13087"></a><span class="lineno">13087</span>&#160;        json.EndObject();</div>
+<div class="line"><a name="l13088"></a><span class="lineno">13088</span>&#160; </div>
+<div class="line"><a name="l13089"></a><span class="lineno">13089</span>&#160;        <span class="keywordflow">if</span>(m_FrameInUseCount &gt; 0)</div>
+<div class="line"><a name="l13090"></a><span class="lineno">13090</span>&#160;        {</div>
+<div class="line"><a name="l13091"></a><span class="lineno">13091</span>&#160;            json.WriteString(<span class="stringliteral">&quot;FrameInUseCount&quot;</span>);</div>
+<div class="line"><a name="l13092"></a><span class="lineno">13092</span>&#160;            json.WriteNumber(m_FrameInUseCount);</div>
+<div class="line"><a name="l13093"></a><span class="lineno">13093</span>&#160;        }</div>
+<div class="line"><a name="l13094"></a><span class="lineno">13094</span>&#160; </div>
+<div class="line"><a name="l13095"></a><span class="lineno">13095</span>&#160;        <span class="keywordflow">if</span>(m_Algorithm != 0)</div>
+<div class="line"><a name="l13096"></a><span class="lineno">13096</span>&#160;        {</div>
+<div class="line"><a name="l13097"></a><span class="lineno">13097</span>&#160;            json.WriteString(<span class="stringliteral">&quot;Algorithm&quot;</span>);</div>
+<div class="line"><a name="l13098"></a><span class="lineno">13098</span>&#160;            json.WriteString(VmaAlgorithmToStr(m_Algorithm));</div>
+<div class="line"><a name="l13099"></a><span class="lineno">13099</span>&#160;        }</div>
+<div class="line"><a name="l13100"></a><span class="lineno">13100</span>&#160;    }</div>
+<div class="line"><a name="l13101"></a><span class="lineno">13101</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l13102"></a><span class="lineno">13102</span>&#160;    {</div>
+<div class="line"><a name="l13103"></a><span class="lineno">13103</span>&#160;        json.WriteString(<span class="stringliteral">&quot;PreferredBlockSize&quot;</span>);</div>
+<div class="line"><a name="l13104"></a><span class="lineno">13104</span>&#160;        json.WriteNumber(m_PreferredBlockSize);</div>
+<div class="line"><a name="l13105"></a><span class="lineno">13105</span>&#160;    }</div>
+<div class="line"><a name="l13106"></a><span class="lineno">13106</span>&#160; </div>
+<div class="line"><a name="l13107"></a><span class="lineno">13107</span>&#160;    json.WriteString(<span class="stringliteral">&quot;Blocks&quot;</span>);</div>
+<div class="line"><a name="l13108"></a><span class="lineno">13108</span>&#160;    json.BeginObject();</div>
+<div class="line"><a name="l13109"></a><span class="lineno">13109</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = 0; i &lt; m_Blocks.size(); ++i)</div>
+<div class="line"><a name="l13110"></a><span class="lineno">13110</span>&#160;    {</div>
+<div class="line"><a name="l13111"></a><span class="lineno">13111</span>&#160;        json.BeginString();</div>
+<div class="line"><a name="l13112"></a><span class="lineno">13112</span>&#160;        json.ContinueString(m_Blocks[i]-&gt;GetId());</div>
+<div class="line"><a name="l13113"></a><span class="lineno">13113</span>&#160;        json.EndString();</div>
+<div class="line"><a name="l13114"></a><span class="lineno">13114</span>&#160; </div>
+<div class="line"><a name="l13115"></a><span class="lineno">13115</span>&#160;        m_Blocks[i]-&gt;m_pMetadata-&gt;PrintDetailedMap(json);</div>
+<div class="line"><a name="l13116"></a><span class="lineno">13116</span>&#160;    }</div>
+<div class="line"><a name="l13117"></a><span class="lineno">13117</span>&#160;    json.EndObject();</div>
+<div class="line"><a name="l13118"></a><span class="lineno">13118</span>&#160; </div>
+<div class="line"><a name="l13119"></a><span class="lineno">13119</span>&#160;    json.EndObject();</div>
+<div class="line"><a name="l13120"></a><span class="lineno">13120</span>&#160;}</div>
+<div class="line"><a name="l13121"></a><span class="lineno">13121</span>&#160; </div>
+<div class="line"><a name="l13122"></a><span class="lineno">13122</span>&#160;<span class="preprocessor">#endif // #if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l13123"></a><span class="lineno">13123</span>&#160; </div>
+<div class="line"><a name="l13124"></a><span class="lineno">13124</span>&#160;<span class="keywordtype">void</span> VmaBlockVector::Defragment(</div>
+<div class="line"><a name="l13125"></a><span class="lineno">13125</span>&#160;    <span class="keyword">class</span> VmaBlockVectorDefragmentationContext* pCtx,</div>
+<div class="line"><a name="l13126"></a><span class="lineno">13126</span>&#160;    <a class="code" href="struct_vma_defragmentation_stats.html">VmaDefragmentationStats</a>* pStats, <a class="code" href="vk__mem__alloc_8h.html#a88a77cef37e5d3c4fc9eb328885d048d">VmaDefragmentationFlags</a> flags,</div>
+<div class="line"><a name="l13127"></a><span class="lineno">13127</span>&#160;    VkDeviceSize&amp; maxCpuBytesToMove, uint32_t&amp; maxCpuAllocationsToMove,</div>
+<div class="line"><a name="l13128"></a><span class="lineno">13128</span>&#160;    VkDeviceSize&amp; maxGpuBytesToMove, uint32_t&amp; maxGpuAllocationsToMove,</div>
+<div class="line"><a name="l13129"></a><span class="lineno">13129</span>&#160;    VkCommandBuffer commandBuffer)</div>
+<div class="line"><a name="l13130"></a><span class="lineno">13130</span>&#160;{</div>
+<div class="line"><a name="l13131"></a><span class="lineno">13131</span>&#160;    pCtx-&gt;res = VK_SUCCESS;</div>
+<div class="line"><a name="l13132"></a><span class="lineno">13132</span>&#160;    </div>
+<div class="line"><a name="l13133"></a><span class="lineno">13133</span>&#160;    <span class="keyword">const</span> VkMemoryPropertyFlags memPropFlags =</div>
+<div class="line"><a name="l13134"></a><span class="lineno">13134</span>&#160;        m_hAllocator-&gt;m_MemProps.memoryTypes[m_MemoryTypeIndex].propertyFlags;</div>
+<div class="line"><a name="l13135"></a><span class="lineno">13135</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">bool</span> isHostVisible = (memPropFlags &amp; VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0;</div>
+<div class="line"><a name="l13136"></a><span class="lineno">13136</span>&#160; </div>
+<div class="line"><a name="l13137"></a><span class="lineno">13137</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">bool</span> canDefragmentOnCpu = maxCpuBytesToMove &gt; 0 &amp;&amp; maxCpuAllocationsToMove &gt; 0 &amp;&amp;</div>
+<div class="line"><a name="l13138"></a><span class="lineno">13138</span>&#160;        isHostVisible;</div>
+<div class="line"><a name="l13139"></a><span class="lineno">13139</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">bool</span> canDefragmentOnGpu = maxGpuBytesToMove &gt; 0 &amp;&amp; maxGpuAllocationsToMove &gt; 0 &amp;&amp;</div>
+<div class="line"><a name="l13140"></a><span class="lineno">13140</span>&#160;        !IsCorruptionDetectionEnabled() &amp;&amp;</div>
+<div class="line"><a name="l13141"></a><span class="lineno">13141</span>&#160;        ((1u &lt;&lt; m_MemoryTypeIndex) &amp; m_hAllocator-&gt;GetGpuDefragmentationMemoryTypeBits()) != 0;</div>
+<div class="line"><a name="l13142"></a><span class="lineno">13142</span>&#160; </div>
+<div class="line"><a name="l13143"></a><span class="lineno">13143</span>&#160;    <span class="comment">// There are options to defragment this memory type.</span></div>
+<div class="line"><a name="l13144"></a><span class="lineno">13144</span>&#160;    <span class="keywordflow">if</span>(canDefragmentOnCpu || canDefragmentOnGpu)</div>
+<div class="line"><a name="l13145"></a><span class="lineno">13145</span>&#160;    {</div>
+<div class="line"><a name="l13146"></a><span class="lineno">13146</span>&#160;        <span class="keywordtype">bool</span> defragmentOnGpu;</div>
+<div class="line"><a name="l13147"></a><span class="lineno">13147</span>&#160;        <span class="comment">// There is only one option to defragment this memory type.</span></div>
+<div class="line"><a name="l13148"></a><span class="lineno">13148</span>&#160;        <span class="keywordflow">if</span>(canDefragmentOnGpu != canDefragmentOnCpu)</div>
+<div class="line"><a name="l13149"></a><span class="lineno">13149</span>&#160;        {</div>
+<div class="line"><a name="l13150"></a><span class="lineno">13150</span>&#160;            defragmentOnGpu = canDefragmentOnGpu;</div>
+<div class="line"><a name="l13151"></a><span class="lineno">13151</span>&#160;        }</div>
+<div class="line"><a name="l13152"></a><span class="lineno">13152</span>&#160;        <span class="comment">// Both options are available: Heuristics to choose the best one.</span></div>
+<div class="line"><a name="l13153"></a><span class="lineno">13153</span>&#160;        <span class="keywordflow">else</span></div>
+<div class="line"><a name="l13154"></a><span class="lineno">13154</span>&#160;        {</div>
+<div class="line"><a name="l13155"></a><span class="lineno">13155</span>&#160;            defragmentOnGpu = (memPropFlags &amp; VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) != 0 ||</div>
+<div class="line"><a name="l13156"></a><span class="lineno">13156</span>&#160;                m_hAllocator-&gt;IsIntegratedGpu();</div>
+<div class="line"><a name="l13157"></a><span class="lineno">13157</span>&#160;        }</div>
+<div class="line"><a name="l13158"></a><span class="lineno">13158</span>&#160; </div>
+<div class="line"><a name="l13159"></a><span class="lineno">13159</span>&#160;        <span class="keywordtype">bool</span> overlappingMoveSupported = !defragmentOnGpu;</div>
+<div class="line"><a name="l13160"></a><span class="lineno">13160</span>&#160; </div>
+<div class="line"><a name="l13161"></a><span class="lineno">13161</span>&#160;        <span class="keywordflow">if</span>(m_hAllocator-&gt;m_UseMutex)</div>
+<div class="line"><a name="l13162"></a><span class="lineno">13162</span>&#160;        {</div>
+<div class="line"><a name="l13163"></a><span class="lineno">13163</span>&#160;            <span class="keywordflow">if</span>(flags &amp; <a class="code" href="vk__mem__alloc_8h.html#a6552a65b71d16f378c6994b3ceaef50ca31af49446af2459284a568ce2f3fdd33">VMA_DEFRAGMENTATION_FLAG_INCREMENTAL</a>)</div>
+<div class="line"><a name="l13164"></a><span class="lineno">13164</span>&#160;            {</div>
+<div class="line"><a name="l13165"></a><span class="lineno">13165</span>&#160;                <span class="keywordflow">if</span>(!m_Mutex.TryLockWrite())</div>
+<div class="line"><a name="l13166"></a><span class="lineno">13166</span>&#160;                {</div>
+<div class="line"><a name="l13167"></a><span class="lineno">13167</span>&#160;                    pCtx-&gt;res = VK_ERROR_INITIALIZATION_FAILED;</div>
+<div class="line"><a name="l13168"></a><span class="lineno">13168</span>&#160;                    <span class="keywordflow">return</span>;</div>
+<div class="line"><a name="l13169"></a><span class="lineno">13169</span>&#160;                }</div>
+<div class="line"><a name="l13170"></a><span class="lineno">13170</span>&#160;            }</div>
+<div class="line"><a name="l13171"></a><span class="lineno">13171</span>&#160;            <span class="keywordflow">else</span></div>
+<div class="line"><a name="l13172"></a><span class="lineno">13172</span>&#160;            {</div>
+<div class="line"><a name="l13173"></a><span class="lineno">13173</span>&#160;                m_Mutex.LockWrite();</div>
+<div class="line"><a name="l13174"></a><span class="lineno">13174</span>&#160;                pCtx-&gt;mutexLocked = <span class="keyword">true</span>;</div>
+<div class="line"><a name="l13175"></a><span class="lineno">13175</span>&#160;            }</div>
+<div class="line"><a name="l13176"></a><span class="lineno">13176</span>&#160;        }</div>
+<div class="line"><a name="l13177"></a><span class="lineno">13177</span>&#160; </div>
+<div class="line"><a name="l13178"></a><span class="lineno">13178</span>&#160;        pCtx-&gt;Begin(overlappingMoveSupported, flags);</div>
+<div class="line"><a name="l13179"></a><span class="lineno">13179</span>&#160; </div>
+<div class="line"><a name="l13180"></a><span class="lineno">13180</span>&#160;        <span class="comment">// Defragment.</span></div>
+<div class="line"><a name="l13181"></a><span class="lineno">13181</span>&#160; </div>
+<div class="line"><a name="l13182"></a><span class="lineno">13182</span>&#160;        <span class="keyword">const</span> VkDeviceSize maxBytesToMove = defragmentOnGpu ? maxGpuBytesToMove : maxCpuBytesToMove;</div>
+<div class="line"><a name="l13183"></a><span class="lineno">13183</span>&#160;        <span class="keyword">const</span> uint32_t maxAllocationsToMove = defragmentOnGpu ? maxGpuAllocationsToMove : maxCpuAllocationsToMove;</div>
+<div class="line"><a name="l13184"></a><span class="lineno">13184</span>&#160;        pCtx-&gt;res = pCtx-&gt;GetAlgorithm()-&gt;Defragment(pCtx-&gt;defragmentationMoves, maxBytesToMove, maxAllocationsToMove, flags);</div>
+<div class="line"><a name="l13185"></a><span class="lineno">13185</span>&#160; </div>
+<div class="line"><a name="l13186"></a><span class="lineno">13186</span>&#160;        <span class="comment">// Accumulate statistics.</span></div>
+<div class="line"><a name="l13187"></a><span class="lineno">13187</span>&#160;        <span class="keywordflow">if</span>(pStats != VMA_NULL)</div>
+<div class="line"><a name="l13188"></a><span class="lineno">13188</span>&#160;        {</div>
+<div class="line"><a name="l13189"></a><span class="lineno">13189</span>&#160;            <span class="keyword">const</span> VkDeviceSize bytesMoved = pCtx-&gt;GetAlgorithm()-&gt;GetBytesMoved();</div>
+<div class="line"><a name="l13190"></a><span class="lineno">13190</span>&#160;            <span class="keyword">const</span> uint32_t allocationsMoved = pCtx-&gt;GetAlgorithm()-&gt;GetAllocationsMoved();</div>
+<div class="line"><a name="l13191"></a><span class="lineno">13191</span>&#160;            pStats-&gt;<a class="code" href="struct_vma_defragmentation_stats.html#a36f9d5df2a10ba2a36b16e126d60572d">bytesMoved</a> += bytesMoved;</div>
+<div class="line"><a name="l13192"></a><span class="lineno">13192</span>&#160;            pStats-&gt;<a class="code" href="struct_vma_defragmentation_stats.html#aefeabf130022008eadd75999478af3f9">allocationsMoved</a> += allocationsMoved;</div>
+<div class="line"><a name="l13193"></a><span class="lineno">13193</span>&#160;            VMA_ASSERT(bytesMoved &lt;= maxBytesToMove);</div>
+<div class="line"><a name="l13194"></a><span class="lineno">13194</span>&#160;            VMA_ASSERT(allocationsMoved &lt;= maxAllocationsToMove);</div>
+<div class="line"><a name="l13195"></a><span class="lineno">13195</span>&#160;            <span class="keywordflow">if</span>(defragmentOnGpu)</div>
+<div class="line"><a name="l13196"></a><span class="lineno">13196</span>&#160;            {</div>
+<div class="line"><a name="l13197"></a><span class="lineno">13197</span>&#160;                maxGpuBytesToMove -= bytesMoved;</div>
+<div class="line"><a name="l13198"></a><span class="lineno">13198</span>&#160;                maxGpuAllocationsToMove -= allocationsMoved;</div>
+<div class="line"><a name="l13199"></a><span class="lineno">13199</span>&#160;            }</div>
+<div class="line"><a name="l13200"></a><span class="lineno">13200</span>&#160;            <span class="keywordflow">else</span></div>
+<div class="line"><a name="l13201"></a><span class="lineno">13201</span>&#160;            {</div>
+<div class="line"><a name="l13202"></a><span class="lineno">13202</span>&#160;                maxCpuBytesToMove -= bytesMoved;</div>
+<div class="line"><a name="l13203"></a><span class="lineno">13203</span>&#160;                maxCpuAllocationsToMove -= allocationsMoved;</div>
+<div class="line"><a name="l13204"></a><span class="lineno">13204</span>&#160;            }</div>
+<div class="line"><a name="l13205"></a><span class="lineno">13205</span>&#160;        }</div>
+<div class="line"><a name="l13206"></a><span class="lineno">13206</span>&#160; </div>
+<div class="line"><a name="l13207"></a><span class="lineno">13207</span>&#160;        <span class="keywordflow">if</span>(flags &amp; <a class="code" href="vk__mem__alloc_8h.html#a6552a65b71d16f378c6994b3ceaef50ca31af49446af2459284a568ce2f3fdd33">VMA_DEFRAGMENTATION_FLAG_INCREMENTAL</a>)</div>
+<div class="line"><a name="l13208"></a><span class="lineno">13208</span>&#160;        {</div>
+<div class="line"><a name="l13209"></a><span class="lineno">13209</span>&#160;            <span class="keywordflow">if</span>(m_hAllocator-&gt;m_UseMutex)</div>
+<div class="line"><a name="l13210"></a><span class="lineno">13210</span>&#160;                m_Mutex.UnlockWrite();</div>
+<div class="line"><a name="l13211"></a><span class="lineno">13211</span>&#160;            </div>
+<div class="line"><a name="l13212"></a><span class="lineno">13212</span>&#160;            <span class="keywordflow">if</span>(pCtx-&gt;res &gt;= VK_SUCCESS &amp;&amp; !pCtx-&gt;defragmentationMoves.empty())</div>
+<div class="line"><a name="l13213"></a><span class="lineno">13213</span>&#160;                pCtx-&gt;res = VK_NOT_READY;</div>
+<div class="line"><a name="l13214"></a><span class="lineno">13214</span>&#160; </div>
+<div class="line"><a name="l13215"></a><span class="lineno">13215</span>&#160;            <span class="keywordflow">return</span>;</div>
+<div class="line"><a name="l13216"></a><span class="lineno">13216</span>&#160;        }</div>
+<div class="line"><a name="l13217"></a><span class="lineno">13217</span>&#160;    </div>
+<div class="line"><a name="l13218"></a><span class="lineno">13218</span>&#160;        <span class="keywordflow">if</span>(pCtx-&gt;res &gt;= VK_SUCCESS)</div>
+<div class="line"><a name="l13219"></a><span class="lineno">13219</span>&#160;        {</div>
+<div class="line"><a name="l13220"></a><span class="lineno">13220</span>&#160;            <span class="keywordflow">if</span>(defragmentOnGpu)</div>
+<div class="line"><a name="l13221"></a><span class="lineno">13221</span>&#160;            {</div>
+<div class="line"><a name="l13222"></a><span class="lineno">13222</span>&#160;                ApplyDefragmentationMovesGpu(pCtx, pCtx-&gt;defragmentationMoves, commandBuffer);</div>
+<div class="line"><a name="l13223"></a><span class="lineno">13223</span>&#160;            }</div>
+<div class="line"><a name="l13224"></a><span class="lineno">13224</span>&#160;            <span class="keywordflow">else</span></div>
+<div class="line"><a name="l13225"></a><span class="lineno">13225</span>&#160;            {</div>
+<div class="line"><a name="l13226"></a><span class="lineno">13226</span>&#160;                ApplyDefragmentationMovesCpu(pCtx, pCtx-&gt;defragmentationMoves);</div>
+<div class="line"><a name="l13227"></a><span class="lineno">13227</span>&#160;            }</div>
+<div class="line"><a name="l13228"></a><span class="lineno">13228</span>&#160;        }</div>
+<div class="line"><a name="l13229"></a><span class="lineno">13229</span>&#160;    }</div>
+<div class="line"><a name="l13230"></a><span class="lineno">13230</span>&#160;}</div>
+<div class="line"><a name="l13231"></a><span class="lineno">13231</span>&#160; </div>
+<div class="line"><a name="l13232"></a><span class="lineno">13232</span>&#160;<span class="keywordtype">void</span> VmaBlockVector::DefragmentationEnd(</div>
+<div class="line"><a name="l13233"></a><span class="lineno">13233</span>&#160;    <span class="keyword">class</span> VmaBlockVectorDefragmentationContext* pCtx,</div>
+<div class="line"><a name="l13234"></a><span class="lineno">13234</span>&#160;    uint32_t flags,</div>
+<div class="line"><a name="l13235"></a><span class="lineno">13235</span>&#160;    <a class="code" href="struct_vma_defragmentation_stats.html">VmaDefragmentationStats</a>* pStats)</div>
+<div class="line"><a name="l13236"></a><span class="lineno">13236</span>&#160;{</div>
+<div class="line"><a name="l13237"></a><span class="lineno">13237</span>&#160;    <span class="keywordflow">if</span>(flags &amp; <a class="code" href="vk__mem__alloc_8h.html#a6552a65b71d16f378c6994b3ceaef50ca31af49446af2459284a568ce2f3fdd33">VMA_DEFRAGMENTATION_FLAG_INCREMENTAL</a> &amp;&amp; m_hAllocator-&gt;m_UseMutex)</div>
+<div class="line"><a name="l13238"></a><span class="lineno">13238</span>&#160;    {</div>
+<div class="line"><a name="l13239"></a><span class="lineno">13239</span>&#160;        VMA_ASSERT(pCtx-&gt;mutexLocked == <span class="keyword">false</span>);</div>
+<div class="line"><a name="l13240"></a><span class="lineno">13240</span>&#160; </div>
+<div class="line"><a name="l13241"></a><span class="lineno">13241</span>&#160;        <span class="comment">// Incremental defragmentation doesn&#39;t hold the lock, so when we enter here we don&#39;t actually have any</span></div>
+<div class="line"><a name="l13242"></a><span class="lineno">13242</span>&#160;        <span class="comment">// lock protecting us. Since we mutate state here, we have to take the lock out now</span></div>
+<div class="line"><a name="l13243"></a><span class="lineno">13243</span>&#160;        m_Mutex.LockWrite();</div>
+<div class="line"><a name="l13244"></a><span class="lineno">13244</span>&#160;        pCtx-&gt;mutexLocked = <span class="keyword">true</span>;</div>
+<div class="line"><a name="l13245"></a><span class="lineno">13245</span>&#160;    }</div>
+<div class="line"><a name="l13246"></a><span class="lineno">13246</span>&#160; </div>
+<div class="line"><a name="l13247"></a><span class="lineno">13247</span>&#160;    <span class="comment">// If the mutex isn&#39;t locked we didn&#39;t do any work and there is nothing to delete.</span></div>
+<div class="line"><a name="l13248"></a><span class="lineno">13248</span>&#160;    <span class="keywordflow">if</span>(pCtx-&gt;mutexLocked || !m_hAllocator-&gt;m_UseMutex)</div>
+<div class="line"><a name="l13249"></a><span class="lineno">13249</span>&#160;    {</div>
+<div class="line"><a name="l13250"></a><span class="lineno">13250</span>&#160;        <span class="comment">// Destroy buffers.</span></div>
+<div class="line"><a name="l13251"></a><span class="lineno">13251</span>&#160;        <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> blockIndex = pCtx-&gt;blockContexts.size(); blockIndex--;)</div>
+<div class="line"><a name="l13252"></a><span class="lineno">13252</span>&#160;        {</div>
+<div class="line"><a name="l13253"></a><span class="lineno">13253</span>&#160;            VmaBlockDefragmentationContext &amp;blockCtx = pCtx-&gt;blockContexts[blockIndex];</div>
+<div class="line"><a name="l13254"></a><span class="lineno">13254</span>&#160;            <span class="keywordflow">if</span>(blockCtx.hBuffer)</div>
+<div class="line"><a name="l13255"></a><span class="lineno">13255</span>&#160;            {</div>
+<div class="line"><a name="l13256"></a><span class="lineno">13256</span>&#160;                (*m_hAllocator-&gt;GetVulkanFunctions().vkDestroyBuffer)(m_hAllocator-&gt;m_hDevice, blockCtx.hBuffer, m_hAllocator-&gt;GetAllocationCallbacks());</div>
+<div class="line"><a name="l13257"></a><span class="lineno">13257</span>&#160;            }</div>
+<div class="line"><a name="l13258"></a><span class="lineno">13258</span>&#160;        }</div>
+<div class="line"><a name="l13259"></a><span class="lineno">13259</span>&#160; </div>
+<div class="line"><a name="l13260"></a><span class="lineno">13260</span>&#160;        <span class="keywordflow">if</span>(pCtx-&gt;res &gt;= VK_SUCCESS)</div>
+<div class="line"><a name="l13261"></a><span class="lineno">13261</span>&#160;        {</div>
+<div class="line"><a name="l13262"></a><span class="lineno">13262</span>&#160;            FreeEmptyBlocks(pStats);</div>
+<div class="line"><a name="l13263"></a><span class="lineno">13263</span>&#160;        }</div>
+<div class="line"><a name="l13264"></a><span class="lineno">13264</span>&#160;    }</div>
+<div class="line"><a name="l13265"></a><span class="lineno">13265</span>&#160; </div>
+<div class="line"><a name="l13266"></a><span class="lineno">13266</span>&#160;    <span class="keywordflow">if</span>(pCtx-&gt;mutexLocked)</div>
+<div class="line"><a name="l13267"></a><span class="lineno">13267</span>&#160;    {</div>
+<div class="line"><a name="l13268"></a><span class="lineno">13268</span>&#160;        VMA_ASSERT(m_hAllocator-&gt;m_UseMutex);</div>
+<div class="line"><a name="l13269"></a><span class="lineno">13269</span>&#160;        m_Mutex.UnlockWrite();</div>
+<div class="line"><a name="l13270"></a><span class="lineno">13270</span>&#160;    }</div>
+<div class="line"><a name="l13271"></a><span class="lineno">13271</span>&#160;}</div>
+<div class="line"><a name="l13272"></a><span class="lineno">13272</span>&#160; </div>
+<div class="line"><a name="l13273"></a><span class="lineno">13273</span>&#160;uint32_t VmaBlockVector::ProcessDefragmentations(</div>
+<div class="line"><a name="l13274"></a><span class="lineno">13274</span>&#160;    <span class="keyword">class</span> VmaBlockVectorDefragmentationContext *pCtx,</div>
+<div class="line"><a name="l13275"></a><span class="lineno">13275</span>&#160;    <a class="code" href="struct_vma_defragmentation_pass_move_info.html">VmaDefragmentationPassMoveInfo</a>* pMove, uint32_t maxMoves)</div>
+<div class="line"><a name="l13276"></a><span class="lineno">13276</span>&#160;{</div>
+<div class="line"><a name="l13277"></a><span class="lineno">13277</span>&#160;    VmaMutexLockWrite lock(m_Mutex, m_hAllocator-&gt;m_UseMutex);</div>
+<div class="line"><a name="l13278"></a><span class="lineno">13278</span>&#160;    </div>
+<div class="line"><a name="l13279"></a><span class="lineno">13279</span>&#160;    <span class="keyword">const</span> uint32_t moveCount = std::min(uint32_t(pCtx-&gt;defragmentationMoves.size()) - pCtx-&gt;defragmentationMovesProcessed, maxMoves);</div>
+<div class="line"><a name="l13280"></a><span class="lineno">13280</span>&#160; </div>
+<div class="line"><a name="l13281"></a><span class="lineno">13281</span>&#160;    <span class="keywordflow">for</span>(uint32_t i = 0; i &lt; moveCount; ++ i)</div>
+<div class="line"><a name="l13282"></a><span class="lineno">13282</span>&#160;    {</div>
+<div class="line"><a name="l13283"></a><span class="lineno">13283</span>&#160;        VmaDefragmentationMove&amp; move = pCtx-&gt;defragmentationMoves[pCtx-&gt;defragmentationMovesProcessed + i];</div>
+<div class="line"><a name="l13284"></a><span class="lineno">13284</span>&#160; </div>
+<div class="line"><a name="l13285"></a><span class="lineno">13285</span>&#160;        pMove-&gt;<a class="code" href="struct_vma_defragmentation_pass_move_info.html#ae885c861c2dd8d622e6c19e281d035cc">allocation</a> = move.hAllocation;</div>
+<div class="line"><a name="l13286"></a><span class="lineno">13286</span>&#160;        pMove-&gt;<a class="code" href="struct_vma_defragmentation_pass_move_info.html#a06eb0c8690aa0d3478a036753492e769">memory</a> = move.pDstBlock-&gt;GetDeviceMemory();</div>
+<div class="line"><a name="l13287"></a><span class="lineno">13287</span>&#160;        pMove-&gt;<a class="code" href="struct_vma_defragmentation_pass_move_info.html#a8ab4508bc03625b0653c880576be96c6">offset</a> = move.dstOffset;</div>
+<div class="line"><a name="l13288"></a><span class="lineno">13288</span>&#160; </div>
+<div class="line"><a name="l13289"></a><span class="lineno">13289</span>&#160;        ++ pMove;</div>
+<div class="line"><a name="l13290"></a><span class="lineno">13290</span>&#160;    }</div>
+<div class="line"><a name="l13291"></a><span class="lineno">13291</span>&#160; </div>
+<div class="line"><a name="l13292"></a><span class="lineno">13292</span>&#160;    pCtx-&gt;defragmentationMovesProcessed += moveCount;</div>
+<div class="line"><a name="l13293"></a><span class="lineno">13293</span>&#160; </div>
+<div class="line"><a name="l13294"></a><span class="lineno">13294</span>&#160;    <span class="keywordflow">return</span> moveCount;</div>
+<div class="line"><a name="l13295"></a><span class="lineno">13295</span>&#160;}</div>
+<div class="line"><a name="l13296"></a><span class="lineno">13296</span>&#160; </div>
+<div class="line"><a name="l13297"></a><span class="lineno">13297</span>&#160;<span class="keywordtype">void</span> VmaBlockVector::CommitDefragmentations(</div>
+<div class="line"><a name="l13298"></a><span class="lineno">13298</span>&#160;    <span class="keyword">class</span> VmaBlockVectorDefragmentationContext *pCtx,</div>
+<div class="line"><a name="l13299"></a><span class="lineno">13299</span>&#160;    <a class="code" href="struct_vma_defragmentation_stats.html">VmaDefragmentationStats</a>* pStats)</div>
+<div class="line"><a name="l13300"></a><span class="lineno">13300</span>&#160;{</div>
+<div class="line"><a name="l13301"></a><span class="lineno">13301</span>&#160;    VmaMutexLockWrite lock(m_Mutex, m_hAllocator-&gt;m_UseMutex);</div>
+<div class="line"><a name="l13302"></a><span class="lineno">13302</span>&#160;    </div>
+<div class="line"><a name="l13303"></a><span class="lineno">13303</span>&#160;    <span class="keywordflow">for</span>(uint32_t i = pCtx-&gt;defragmentationMovesCommitted; i &lt; pCtx-&gt;defragmentationMovesProcessed; ++ i)</div>
+<div class="line"><a name="l13304"></a><span class="lineno">13304</span>&#160;    {</div>
+<div class="line"><a name="l13305"></a><span class="lineno">13305</span>&#160;        <span class="keyword">const</span> VmaDefragmentationMove &amp;move = pCtx-&gt;defragmentationMoves[i];</div>
+<div class="line"><a name="l13306"></a><span class="lineno">13306</span>&#160; </div>
+<div class="line"><a name="l13307"></a><span class="lineno">13307</span>&#160;        move.pSrcBlock-&gt;m_pMetadata-&gt;FreeAtOffset(move.srcOffset);</div>
+<div class="line"><a name="l13308"></a><span class="lineno">13308</span>&#160;        move.hAllocation-&gt;ChangeBlockAllocation(m_hAllocator, move.pDstBlock, move.dstOffset);</div>
+<div class="line"><a name="l13309"></a><span class="lineno">13309</span>&#160;    }</div>
+<div class="line"><a name="l13310"></a><span class="lineno">13310</span>&#160; </div>
+<div class="line"><a name="l13311"></a><span class="lineno">13311</span>&#160;    pCtx-&gt;defragmentationMovesCommitted = pCtx-&gt;defragmentationMovesProcessed;</div>
+<div class="line"><a name="l13312"></a><span class="lineno">13312</span>&#160;    FreeEmptyBlocks(pStats);</div>
+<div class="line"><a name="l13313"></a><span class="lineno">13313</span>&#160;}</div>
+<div class="line"><a name="l13314"></a><span class="lineno">13314</span>&#160; </div>
+<div class="line"><a name="l13315"></a><span class="lineno">13315</span>&#160;<span class="keywordtype">size_t</span> VmaBlockVector::CalcAllocationCount()<span class="keyword"> const</span></div>
+<div class="line"><a name="l13316"></a><span class="lineno">13316</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l13317"></a><span class="lineno">13317</span>&#160;    <span class="keywordtype">size_t</span> result = 0;</div>
+<div class="line"><a name="l13318"></a><span class="lineno">13318</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = 0; i &lt; m_Blocks.size(); ++i)</div>
+<div class="line"><a name="l13319"></a><span class="lineno">13319</span>&#160;    {</div>
+<div class="line"><a name="l13320"></a><span class="lineno">13320</span>&#160;        result += m_Blocks[i]-&gt;m_pMetadata-&gt;GetAllocationCount();</div>
+<div class="line"><a name="l13321"></a><span class="lineno">13321</span>&#160;    }</div>
+<div class="line"><a name="l13322"></a><span class="lineno">13322</span>&#160;    <span class="keywordflow">return</span> result;</div>
+<div class="line"><a name="l13323"></a><span class="lineno">13323</span>&#160;}</div>
+<div class="line"><a name="l13324"></a><span class="lineno">13324</span>&#160; </div>
+<div class="line"><a name="l13325"></a><span class="lineno">13325</span>&#160;<span class="keywordtype">bool</span> VmaBlockVector::IsBufferImageGranularityConflictPossible()<span class="keyword"> const</span></div>
+<div class="line"><a name="l13326"></a><span class="lineno">13326</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l13327"></a><span class="lineno">13327</span>&#160;    <span class="keywordflow">if</span>(m_BufferImageGranularity == 1)</div>
+<div class="line"><a name="l13328"></a><span class="lineno">13328</span>&#160;    {</div>
+<div class="line"><a name="l13329"></a><span class="lineno">13329</span>&#160;        <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l13330"></a><span class="lineno">13330</span>&#160;    }</div>
+<div class="line"><a name="l13331"></a><span class="lineno">13331</span>&#160;    VmaSuballocationType lastSuballocType = VMA_SUBALLOCATION_TYPE_FREE;</div>
+<div class="line"><a name="l13332"></a><span class="lineno">13332</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = 0, count = m_Blocks.size(); i &lt; count; ++i)</div>
+<div class="line"><a name="l13333"></a><span class="lineno">13333</span>&#160;    {</div>
+<div class="line"><a name="l13334"></a><span class="lineno">13334</span>&#160;        VmaDeviceMemoryBlock* <span class="keyword">const</span> pBlock = m_Blocks[i];</div>
+<div class="line"><a name="l13335"></a><span class="lineno">13335</span>&#160;        VMA_ASSERT(m_Algorithm == 0);</div>
+<div class="line"><a name="l13336"></a><span class="lineno">13336</span>&#160;        VmaBlockMetadata_Generic* <span class="keyword">const</span> pMetadata = (VmaBlockMetadata_Generic*)pBlock-&gt;m_pMetadata;</div>
+<div class="line"><a name="l13337"></a><span class="lineno">13337</span>&#160;        <span class="keywordflow">if</span>(pMetadata-&gt;IsBufferImageGranularityConflictPossible(m_BufferImageGranularity, lastSuballocType))</div>
+<div class="line"><a name="l13338"></a><span class="lineno">13338</span>&#160;        {</div>
+<div class="line"><a name="l13339"></a><span class="lineno">13339</span>&#160;            <span class="keywordflow">return</span> <span class="keyword">true</span>;</div>
+<div class="line"><a name="l13340"></a><span class="lineno">13340</span>&#160;        }</div>
+<div class="line"><a name="l13341"></a><span class="lineno">13341</span>&#160;    }</div>
+<div class="line"><a name="l13342"></a><span class="lineno">13342</span>&#160;    <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l13343"></a><span class="lineno">13343</span>&#160;}</div>
+<div class="line"><a name="l13344"></a><span class="lineno">13344</span>&#160; </div>
+<div class="line"><a name="l13345"></a><span class="lineno">13345</span>&#160;<span class="keywordtype">void</span> VmaBlockVector::MakePoolAllocationsLost(</div>
+<div class="line"><a name="l13346"></a><span class="lineno">13346</span>&#160;    uint32_t currentFrameIndex,</div>
+<div class="line"><a name="l13347"></a><span class="lineno">13347</span>&#160;    <span class="keywordtype">size_t</span>* pLostAllocationCount)</div>
+<div class="line"><a name="l13348"></a><span class="lineno">13348</span>&#160;{</div>
+<div class="line"><a name="l13349"></a><span class="lineno">13349</span>&#160;    VmaMutexLockWrite lock(m_Mutex, m_hAllocator-&gt;m_UseMutex);</div>
+<div class="line"><a name="l13350"></a><span class="lineno">13350</span>&#160;    <span class="keywordtype">size_t</span> lostAllocationCount = 0;</div>
+<div class="line"><a name="l13351"></a><span class="lineno">13351</span>&#160;    <span class="keywordflow">for</span>(uint32_t blockIndex = 0; blockIndex &lt; m_Blocks.size(); ++blockIndex)</div>
+<div class="line"><a name="l13352"></a><span class="lineno">13352</span>&#160;    {</div>
+<div class="line"><a name="l13353"></a><span class="lineno">13353</span>&#160;        VmaDeviceMemoryBlock* <span class="keyword">const</span> pBlock = m_Blocks[blockIndex];</div>
+<div class="line"><a name="l13354"></a><span class="lineno">13354</span>&#160;        VMA_ASSERT(pBlock);</div>
+<div class="line"><a name="l13355"></a><span class="lineno">13355</span>&#160;        lostAllocationCount += pBlock-&gt;m_pMetadata-&gt;MakeAllocationsLost(currentFrameIndex, m_FrameInUseCount);</div>
+<div class="line"><a name="l13356"></a><span class="lineno">13356</span>&#160;    }</div>
+<div class="line"><a name="l13357"></a><span class="lineno">13357</span>&#160;    <span class="keywordflow">if</span>(pLostAllocationCount != VMA_NULL)</div>
+<div class="line"><a name="l13358"></a><span class="lineno">13358</span>&#160;    {</div>
+<div class="line"><a name="l13359"></a><span class="lineno">13359</span>&#160;        *pLostAllocationCount = lostAllocationCount;</div>
+<div class="line"><a name="l13360"></a><span class="lineno">13360</span>&#160;    }</div>
+<div class="line"><a name="l13361"></a><span class="lineno">13361</span>&#160;}</div>
+<div class="line"><a name="l13362"></a><span class="lineno">13362</span>&#160; </div>
+<div class="line"><a name="l13363"></a><span class="lineno">13363</span>&#160;VkResult VmaBlockVector::CheckCorruption()</div>
+<div class="line"><a name="l13364"></a><span class="lineno">13364</span>&#160;{</div>
+<div class="line"><a name="l13365"></a><span class="lineno">13365</span>&#160;    <span class="keywordflow">if</span>(!IsCorruptionDetectionEnabled())</div>
+<div class="line"><a name="l13366"></a><span class="lineno">13366</span>&#160;    {</div>
+<div class="line"><a name="l13367"></a><span class="lineno">13367</span>&#160;        <span class="keywordflow">return</span> VK_ERROR_FEATURE_NOT_PRESENT;</div>
+<div class="line"><a name="l13368"></a><span class="lineno">13368</span>&#160;    }</div>
+<div class="line"><a name="l13369"></a><span class="lineno">13369</span>&#160; </div>
+<div class="line"><a name="l13370"></a><span class="lineno">13370</span>&#160;    VmaMutexLockRead lock(m_Mutex, m_hAllocator-&gt;m_UseMutex);</div>
+<div class="line"><a name="l13371"></a><span class="lineno">13371</span>&#160;    <span class="keywordflow">for</span>(uint32_t blockIndex = 0; blockIndex &lt; m_Blocks.size(); ++blockIndex)</div>
+<div class="line"><a name="l13372"></a><span class="lineno">13372</span>&#160;    {</div>
+<div class="line"><a name="l13373"></a><span class="lineno">13373</span>&#160;        VmaDeviceMemoryBlock* <span class="keyword">const</span> pBlock = m_Blocks[blockIndex];</div>
+<div class="line"><a name="l13374"></a><span class="lineno">13374</span>&#160;        VMA_ASSERT(pBlock);</div>
+<div class="line"><a name="l13375"></a><span class="lineno">13375</span>&#160;        VkResult res = pBlock-&gt;CheckCorruption(m_hAllocator);</div>
+<div class="line"><a name="l13376"></a><span class="lineno">13376</span>&#160;        <span class="keywordflow">if</span>(res != VK_SUCCESS)</div>
+<div class="line"><a name="l13377"></a><span class="lineno">13377</span>&#160;        {</div>
+<div class="line"><a name="l13378"></a><span class="lineno">13378</span>&#160;            <span class="keywordflow">return</span> res;</div>
+<div class="line"><a name="l13379"></a><span class="lineno">13379</span>&#160;        }</div>
+<div class="line"><a name="l13380"></a><span class="lineno">13380</span>&#160;    }</div>
+<div class="line"><a name="l13381"></a><span class="lineno">13381</span>&#160;    <span class="keywordflow">return</span> VK_SUCCESS;</div>
+<div class="line"><a name="l13382"></a><span class="lineno">13382</span>&#160;}</div>
+<div class="line"><a name="l13383"></a><span class="lineno">13383</span>&#160; </div>
+<div class="line"><a name="l13384"></a><span class="lineno">13384</span>&#160;<span class="keywordtype">void</span> VmaBlockVector::AddStats(<a class="code" href="struct_vma_stats.html">VmaStats</a>* pStats)</div>
+<div class="line"><a name="l13385"></a><span class="lineno">13385</span>&#160;{</div>
+<div class="line"><a name="l13386"></a><span class="lineno">13386</span>&#160;    <span class="keyword">const</span> uint32_t memTypeIndex = m_MemoryTypeIndex;</div>
+<div class="line"><a name="l13387"></a><span class="lineno">13387</span>&#160;    <span class="keyword">const</span> uint32_t memHeapIndex = m_hAllocator-&gt;MemoryTypeIndexToHeapIndex(memTypeIndex);</div>
+<div class="line"><a name="l13388"></a><span class="lineno">13388</span>&#160; </div>
+<div class="line"><a name="l13389"></a><span class="lineno">13389</span>&#160;    VmaMutexLockRead lock(m_Mutex, m_hAllocator-&gt;m_UseMutex);</div>
+<div class="line"><a name="l13390"></a><span class="lineno">13390</span>&#160; </div>
+<div class="line"><a name="l13391"></a><span class="lineno">13391</span>&#160;    <span class="keywordflow">for</span>(uint32_t blockIndex = 0; blockIndex &lt; m_Blocks.size(); ++blockIndex)</div>
+<div class="line"><a name="l13392"></a><span class="lineno">13392</span>&#160;    {</div>
+<div class="line"><a name="l13393"></a><span class="lineno">13393</span>&#160;        <span class="keyword">const</span> VmaDeviceMemoryBlock* <span class="keyword">const</span> pBlock = m_Blocks[blockIndex];</div>
+<div class="line"><a name="l13394"></a><span class="lineno">13394</span>&#160;        VMA_ASSERT(pBlock);</div>
+<div class="line"><a name="l13395"></a><span class="lineno">13395</span>&#160;        VMA_HEAVY_ASSERT(pBlock-&gt;Validate());</div>
+<div class="line"><a name="l13396"></a><span class="lineno">13396</span>&#160;        <a class="code" href="struct_vma_stat_info.html">VmaStatInfo</a> allocationStatInfo;</div>
+<div class="line"><a name="l13397"></a><span class="lineno">13397</span>&#160;        pBlock-&gt;m_pMetadata-&gt;CalcAllocationStatInfo(allocationStatInfo);</div>
+<div class="line"><a name="l13398"></a><span class="lineno">13398</span>&#160;        VmaAddStatInfo(pStats-&gt;<a class="code" href="struct_vma_stats.html#a2e8f5b3353f2fefef3c27f29e245a1f9">total</a>, allocationStatInfo);</div>
+<div class="line"><a name="l13399"></a><span class="lineno">13399</span>&#160;        VmaAddStatInfo(pStats-&gt;<a class="code" href="struct_vma_stats.html#a13e3caf754be79352c42408756309331">memoryType</a>[memTypeIndex], allocationStatInfo);</div>
+<div class="line"><a name="l13400"></a><span class="lineno">13400</span>&#160;        VmaAddStatInfo(pStats-&gt;<a class="code" href="struct_vma_stats.html#a0e6611508c29a187f0fd14ff1a0329c0">memoryHeap</a>[memHeapIndex], allocationStatInfo);</div>
+<div class="line"><a name="l13401"></a><span class="lineno">13401</span>&#160;    }</div>
+<div class="line"><a name="l13402"></a><span class="lineno">13402</span>&#160;}</div>
+<div class="line"><a name="l13403"></a><span class="lineno">13403</span>&#160; </div>
+<div class="line"><a name="l13405"></a><span class="lineno">13405</span>&#160;<span class="comment">// VmaDefragmentationAlgorithm_Generic members definition</span></div>
+<div class="line"><a name="l13406"></a><span class="lineno">13406</span>&#160; </div>
+<div class="line"><a name="l13407"></a><span class="lineno">13407</span>&#160;VmaDefragmentationAlgorithm_Generic::VmaDefragmentationAlgorithm_Generic(</div>
+<div class="line"><a name="l13408"></a><span class="lineno">13408</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator,</div>
+<div class="line"><a name="l13409"></a><span class="lineno">13409</span>&#160;    VmaBlockVector* pBlockVector,</div>
+<div class="line"><a name="l13410"></a><span class="lineno">13410</span>&#160;    uint32_t currentFrameIndex,</div>
+<div class="line"><a name="l13411"></a><span class="lineno">13411</span>&#160;    <span class="keywordtype">bool</span> overlappingMoveSupported) :</div>
+<div class="line"><a name="l13412"></a><span class="lineno">13412</span>&#160;    VmaDefragmentationAlgorithm(hAllocator, pBlockVector, currentFrameIndex),</div>
+<div class="line"><a name="l13413"></a><span class="lineno">13413</span>&#160;    m_AllocationCount(0),</div>
+<div class="line"><a name="l13414"></a><span class="lineno">13414</span>&#160;    m_AllAllocations(false),</div>
+<div class="line"><a name="l13415"></a><span class="lineno">13415</span>&#160;    m_BytesMoved(0),</div>
+<div class="line"><a name="l13416"></a><span class="lineno">13416</span>&#160;    m_AllocationsMoved(0),</div>
+<div class="line"><a name="l13417"></a><span class="lineno">13417</span>&#160;    m_Blocks(VmaStlAllocator&lt;BlockInfo*&gt;(hAllocator-&gt;GetAllocationCallbacks()))</div>
+<div class="line"><a name="l13418"></a><span class="lineno">13418</span>&#160;{</div>
+<div class="line"><a name="l13419"></a><span class="lineno">13419</span>&#160;    <span class="comment">// Create block info for each block.</span></div>
+<div class="line"><a name="l13420"></a><span class="lineno">13420</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">size_t</span> blockCount = m_pBlockVector-&gt;m_Blocks.size();</div>
+<div class="line"><a name="l13421"></a><span class="lineno">13421</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> blockIndex = 0; blockIndex &lt; blockCount; ++blockIndex)</div>
+<div class="line"><a name="l13422"></a><span class="lineno">13422</span>&#160;    {</div>
+<div class="line"><a name="l13423"></a><span class="lineno">13423</span>&#160;        BlockInfo* pBlockInfo = vma_new(m_hAllocator, BlockInfo)(m_hAllocator-&gt;GetAllocationCallbacks());</div>
+<div class="line"><a name="l13424"></a><span class="lineno">13424</span>&#160;        pBlockInfo-&gt;m_OriginalBlockIndex = blockIndex;</div>
+<div class="line"><a name="l13425"></a><span class="lineno">13425</span>&#160;        pBlockInfo-&gt;m_pBlock = m_pBlockVector-&gt;m_Blocks[blockIndex];</div>
+<div class="line"><a name="l13426"></a><span class="lineno">13426</span>&#160;        m_Blocks.push_back(pBlockInfo);</div>
+<div class="line"><a name="l13427"></a><span class="lineno">13427</span>&#160;    }</div>
+<div class="line"><a name="l13428"></a><span class="lineno">13428</span>&#160; </div>
+<div class="line"><a name="l13429"></a><span class="lineno">13429</span>&#160;    <span class="comment">// Sort them by m_pBlock pointer value.</span></div>
+<div class="line"><a name="l13430"></a><span class="lineno">13430</span>&#160;    VMA_SORT(m_Blocks.begin(), m_Blocks.end(), BlockPointerLess());</div>
+<div class="line"><a name="l13431"></a><span class="lineno">13431</span>&#160;}</div>
+<div class="line"><a name="l13432"></a><span class="lineno">13432</span>&#160; </div>
+<div class="line"><a name="l13433"></a><span class="lineno">13433</span>&#160;VmaDefragmentationAlgorithm_Generic::~VmaDefragmentationAlgorithm_Generic()</div>
+<div class="line"><a name="l13434"></a><span class="lineno">13434</span>&#160;{</div>
+<div class="line"><a name="l13435"></a><span class="lineno">13435</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = m_Blocks.size(); i--; )</div>
+<div class="line"><a name="l13436"></a><span class="lineno">13436</span>&#160;    {</div>
+<div class="line"><a name="l13437"></a><span class="lineno">13437</span>&#160;        vma_delete(m_hAllocator, m_Blocks[i]);</div>
+<div class="line"><a name="l13438"></a><span class="lineno">13438</span>&#160;    }</div>
+<div class="line"><a name="l13439"></a><span class="lineno">13439</span>&#160;}</div>
+<div class="line"><a name="l13440"></a><span class="lineno">13440</span>&#160; </div>
+<div class="line"><a name="l13441"></a><span class="lineno">13441</span>&#160;<span class="keywordtype">void</span> VmaDefragmentationAlgorithm_Generic::AddAllocation(<a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAlloc, VkBool32* pChanged)</div>
+<div class="line"><a name="l13442"></a><span class="lineno">13442</span>&#160;{</div>
+<div class="line"><a name="l13443"></a><span class="lineno">13443</span>&#160;    <span class="comment">// Now as we are inside VmaBlockVector::m_Mutex, we can make final check if this allocation was not lost.</span></div>
+<div class="line"><a name="l13444"></a><span class="lineno">13444</span>&#160;    <span class="keywordflow">if</span>(hAlloc-&gt;GetLastUseFrameIndex() != VMA_FRAME_INDEX_LOST)</div>
+<div class="line"><a name="l13445"></a><span class="lineno">13445</span>&#160;    {</div>
+<div class="line"><a name="l13446"></a><span class="lineno">13446</span>&#160;        VmaDeviceMemoryBlock* pBlock = hAlloc-&gt;GetBlock();</div>
+<div class="line"><a name="l13447"></a><span class="lineno">13447</span>&#160;        BlockInfoVector::iterator it = VmaBinaryFindFirstNotLess(m_Blocks.begin(), m_Blocks.end(), pBlock, BlockPointerLess());</div>
+<div class="line"><a name="l13448"></a><span class="lineno">13448</span>&#160;        <span class="keywordflow">if</span>(it != m_Blocks.end() &amp;&amp; (*it)-&gt;m_pBlock == pBlock)</div>
+<div class="line"><a name="l13449"></a><span class="lineno">13449</span>&#160;        {</div>
+<div class="line"><a name="l13450"></a><span class="lineno">13450</span>&#160;            AllocationInfo allocInfo = AllocationInfo(hAlloc, pChanged);</div>
+<div class="line"><a name="l13451"></a><span class="lineno">13451</span>&#160;            (*it)-&gt;m_Allocations.push_back(allocInfo);</div>
+<div class="line"><a name="l13452"></a><span class="lineno">13452</span>&#160;        }</div>
+<div class="line"><a name="l13453"></a><span class="lineno">13453</span>&#160;        <span class="keywordflow">else</span></div>
+<div class="line"><a name="l13454"></a><span class="lineno">13454</span>&#160;        {</div>
+<div class="line"><a name="l13455"></a><span class="lineno">13455</span>&#160;            VMA_ASSERT(0);</div>
+<div class="line"><a name="l13456"></a><span class="lineno">13456</span>&#160;        }</div>
+<div class="line"><a name="l13457"></a><span class="lineno">13457</span>&#160; </div>
+<div class="line"><a name="l13458"></a><span class="lineno">13458</span>&#160;        ++m_AllocationCount;</div>
+<div class="line"><a name="l13459"></a><span class="lineno">13459</span>&#160;    }</div>
+<div class="line"><a name="l13460"></a><span class="lineno">13460</span>&#160;}</div>
+<div class="line"><a name="l13461"></a><span class="lineno">13461</span>&#160; </div>
+<div class="line"><a name="l13462"></a><span class="lineno">13462</span>&#160;VkResult VmaDefragmentationAlgorithm_Generic::DefragmentRound(</div>
+<div class="line"><a name="l13463"></a><span class="lineno">13463</span>&#160;    VmaVector&lt; VmaDefragmentationMove, VmaStlAllocator&lt;VmaDefragmentationMove&gt; &gt;&amp; moves,</div>
+<div class="line"><a name="l13464"></a><span class="lineno">13464</span>&#160;    VkDeviceSize maxBytesToMove,</div>
+<div class="line"><a name="l13465"></a><span class="lineno">13465</span>&#160;    uint32_t maxAllocationsToMove,</div>
+<div class="line"><a name="l13466"></a><span class="lineno">13466</span>&#160;    <span class="keywordtype">bool</span> freeOldAllocations)</div>
+<div class="line"><a name="l13467"></a><span class="lineno">13467</span>&#160;{</div>
+<div class="line"><a name="l13468"></a><span class="lineno">13468</span>&#160;    <span class="keywordflow">if</span>(m_Blocks.empty())</div>
+<div class="line"><a name="l13469"></a><span class="lineno">13469</span>&#160;    {</div>
+<div class="line"><a name="l13470"></a><span class="lineno">13470</span>&#160;        <span class="keywordflow">return</span> VK_SUCCESS;</div>
+<div class="line"><a name="l13471"></a><span class="lineno">13471</span>&#160;    }</div>
+<div class="line"><a name="l13472"></a><span class="lineno">13472</span>&#160; </div>
+<div class="line"><a name="l13473"></a><span class="lineno">13473</span>&#160;    <span class="comment">// This is a choice based on research.</span></div>
+<div class="line"><a name="l13474"></a><span class="lineno">13474</span>&#160;    <span class="comment">// Option 1:</span></div>
+<div class="line"><a name="l13475"></a><span class="lineno">13475</span>&#160;    uint32_t strategy = <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a0729e932b7ea170e3a128cad96c5cf6d">VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT</a>;</div>
+<div class="line"><a name="l13476"></a><span class="lineno">13476</span>&#160;    <span class="comment">// Option 2:</span></div>
+<div class="line"><a name="l13477"></a><span class="lineno">13477</span>&#160;    <span class="comment">//uint32_t strategy = VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT;</span></div>
+<div class="line"><a name="l13478"></a><span class="lineno">13478</span>&#160;    <span class="comment">// Option 3:</span></div>
+<div class="line"><a name="l13479"></a><span class="lineno">13479</span>&#160;    <span class="comment">//uint32_t strategy = VMA_ALLOCATION_CREATE_STRATEGY_MIN_FRAGMENTATION_BIT;</span></div>
+<div class="line"><a name="l13480"></a><span class="lineno">13480</span>&#160; </div>
+<div class="line"><a name="l13481"></a><span class="lineno">13481</span>&#160;    <span class="keywordtype">size_t</span> srcBlockMinIndex = 0;</div>
+<div class="line"><a name="l13482"></a><span class="lineno">13482</span>&#160;    <span class="comment">// When FAST_ALGORITHM, move allocations from only last out of blocks that contain non-movable allocations.</span></div>
+<div class="line"><a name="l13483"></a><span class="lineno">13483</span>&#160;    <span class="comment">/*</span></div>
+<div class="line"><a name="l13484"></a><span class="lineno">13484</span>&#160;<span class="comment">    if(m_AlgorithmFlags &amp; VMA_DEFRAGMENTATION_FAST_ALGORITHM_BIT)</span></div>
+<div class="line"><a name="l13485"></a><span class="lineno">13485</span>&#160;<span class="comment">    {</span></div>
+<div class="line"><a name="l13486"></a><span class="lineno">13486</span>&#160;<span class="comment">        const size_t blocksWithNonMovableCount = CalcBlocksWithNonMovableCount();</span></div>
+<div class="line"><a name="l13487"></a><span class="lineno">13487</span>&#160;<span class="comment">        if(blocksWithNonMovableCount &gt; 0)</span></div>
+<div class="line"><a name="l13488"></a><span class="lineno">13488</span>&#160;<span class="comment">        {</span></div>
+<div class="line"><a name="l13489"></a><span class="lineno">13489</span>&#160;<span class="comment">            srcBlockMinIndex = blocksWithNonMovableCount - 1;</span></div>
+<div class="line"><a name="l13490"></a><span class="lineno">13490</span>&#160;<span class="comment">        }</span></div>
+<div class="line"><a name="l13491"></a><span class="lineno">13491</span>&#160;<span class="comment">    }</span></div>
+<div class="line"><a name="l13492"></a><span class="lineno">13492</span>&#160;<span class="comment">    */</span></div>
+<div class="line"><a name="l13493"></a><span class="lineno">13493</span>&#160; </div>
+<div class="line"><a name="l13494"></a><span class="lineno">13494</span>&#160;    <span class="keywordtype">size_t</span> srcBlockIndex = m_Blocks.size() - 1;</div>
+<div class="line"><a name="l13495"></a><span class="lineno">13495</span>&#160;    <span class="keywordtype">size_t</span> srcAllocIndex = SIZE_MAX;</div>
+<div class="line"><a name="l13496"></a><span class="lineno">13496</span>&#160;    <span class="keywordflow">for</span>(;;)</div>
+<div class="line"><a name="l13497"></a><span class="lineno">13497</span>&#160;    {</div>
+<div class="line"><a name="l13498"></a><span class="lineno">13498</span>&#160;        <span class="comment">// 1. Find next allocation to move.</span></div>
+<div class="line"><a name="l13499"></a><span class="lineno">13499</span>&#160;        <span class="comment">// 1.1. Start from last to first m_Blocks - they are sorted from most &quot;destination&quot; to most &quot;source&quot;.</span></div>
+<div class="line"><a name="l13500"></a><span class="lineno">13500</span>&#160;        <span class="comment">// 1.2. Then start from last to first m_Allocations.</span></div>
+<div class="line"><a name="l13501"></a><span class="lineno">13501</span>&#160;        <span class="keywordflow">while</span>(srcAllocIndex &gt;= m_Blocks[srcBlockIndex]-&gt;m_Allocations.size())</div>
+<div class="line"><a name="l13502"></a><span class="lineno">13502</span>&#160;        {</div>
+<div class="line"><a name="l13503"></a><span class="lineno">13503</span>&#160;            <span class="keywordflow">if</span>(m_Blocks[srcBlockIndex]-&gt;m_Allocations.empty())</div>
+<div class="line"><a name="l13504"></a><span class="lineno">13504</span>&#160;            {</div>
+<div class="line"><a name="l13505"></a><span class="lineno">13505</span>&#160;                <span class="comment">// Finished: no more allocations to process.</span></div>
+<div class="line"><a name="l13506"></a><span class="lineno">13506</span>&#160;                <span class="keywordflow">if</span>(srcBlockIndex == srcBlockMinIndex)</div>
+<div class="line"><a name="l13507"></a><span class="lineno">13507</span>&#160;                {</div>
+<div class="line"><a name="l13508"></a><span class="lineno">13508</span>&#160;                    <span class="keywordflow">return</span> VK_SUCCESS;</div>
+<div class="line"><a name="l13509"></a><span class="lineno">13509</span>&#160;                }</div>
+<div class="line"><a name="l13510"></a><span class="lineno">13510</span>&#160;                <span class="keywordflow">else</span></div>
+<div class="line"><a name="l13511"></a><span class="lineno">13511</span>&#160;                {</div>
+<div class="line"><a name="l13512"></a><span class="lineno">13512</span>&#160;                    --srcBlockIndex;</div>
+<div class="line"><a name="l13513"></a><span class="lineno">13513</span>&#160;                    srcAllocIndex = SIZE_MAX;</div>
+<div class="line"><a name="l13514"></a><span class="lineno">13514</span>&#160;                }</div>
+<div class="line"><a name="l13515"></a><span class="lineno">13515</span>&#160;            }</div>
+<div class="line"><a name="l13516"></a><span class="lineno">13516</span>&#160;            <span class="keywordflow">else</span></div>
+<div class="line"><a name="l13517"></a><span class="lineno">13517</span>&#160;            {</div>
+<div class="line"><a name="l13518"></a><span class="lineno">13518</span>&#160;                srcAllocIndex = m_Blocks[srcBlockIndex]-&gt;m_Allocations.size() - 1;</div>
+<div class="line"><a name="l13519"></a><span class="lineno">13519</span>&#160;            }</div>
+<div class="line"><a name="l13520"></a><span class="lineno">13520</span>&#160;        }</div>
+<div class="line"><a name="l13521"></a><span class="lineno">13521</span>&#160;        </div>
+<div class="line"><a name="l13522"></a><span class="lineno">13522</span>&#160;        BlockInfo* pSrcBlockInfo = m_Blocks[srcBlockIndex];</div>
+<div class="line"><a name="l13523"></a><span class="lineno">13523</span>&#160;        AllocationInfo&amp; allocInfo = pSrcBlockInfo-&gt;m_Allocations[srcAllocIndex];</div>
+<div class="line"><a name="l13524"></a><span class="lineno">13524</span>&#160; </div>
+<div class="line"><a name="l13525"></a><span class="lineno">13525</span>&#160;        <span class="keyword">const</span> VkDeviceSize size = allocInfo.m_hAllocation-&gt;GetSize();</div>
+<div class="line"><a name="l13526"></a><span class="lineno">13526</span>&#160;        <span class="keyword">const</span> VkDeviceSize srcOffset = allocInfo.m_hAllocation-&gt;GetOffset();</div>
+<div class="line"><a name="l13527"></a><span class="lineno">13527</span>&#160;        <span class="keyword">const</span> VkDeviceSize alignment = allocInfo.m_hAllocation-&gt;GetAlignment();</div>
+<div class="line"><a name="l13528"></a><span class="lineno">13528</span>&#160;        <span class="keyword">const</span> VmaSuballocationType suballocType = allocInfo.m_hAllocation-&gt;GetSuballocationType();</div>
+<div class="line"><a name="l13529"></a><span class="lineno">13529</span>&#160; </div>
+<div class="line"><a name="l13530"></a><span class="lineno">13530</span>&#160;        <span class="comment">// 2. Try to find new place for this allocation in preceding or current block.</span></div>
+<div class="line"><a name="l13531"></a><span class="lineno">13531</span>&#160;        <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> dstBlockIndex = 0; dstBlockIndex &lt;= srcBlockIndex; ++dstBlockIndex)</div>
+<div class="line"><a name="l13532"></a><span class="lineno">13532</span>&#160;        {</div>
+<div class="line"><a name="l13533"></a><span class="lineno">13533</span>&#160;            BlockInfo* pDstBlockInfo = m_Blocks[dstBlockIndex];</div>
+<div class="line"><a name="l13534"></a><span class="lineno">13534</span>&#160;            VmaAllocationRequest dstAllocRequest;</div>
+<div class="line"><a name="l13535"></a><span class="lineno">13535</span>&#160;            <span class="keywordflow">if</span>(pDstBlockInfo-&gt;m_pBlock-&gt;m_pMetadata-&gt;CreateAllocationRequest(</div>
+<div class="line"><a name="l13536"></a><span class="lineno">13536</span>&#160;                m_CurrentFrameIndex,</div>
+<div class="line"><a name="l13537"></a><span class="lineno">13537</span>&#160;                m_pBlockVector-&gt;GetFrameInUseCount(),</div>
+<div class="line"><a name="l13538"></a><span class="lineno">13538</span>&#160;                m_pBlockVector-&gt;GetBufferImageGranularity(),</div>
+<div class="line"><a name="l13539"></a><span class="lineno">13539</span>&#160;                size,</div>
+<div class="line"><a name="l13540"></a><span class="lineno">13540</span>&#160;                alignment,</div>
+<div class="line"><a name="l13541"></a><span class="lineno">13541</span>&#160;                <span class="keyword">false</span>, <span class="comment">// upperAddress</span></div>
+<div class="line"><a name="l13542"></a><span class="lineno">13542</span>&#160;                suballocType,</div>
+<div class="line"><a name="l13543"></a><span class="lineno">13543</span>&#160;                <span class="keyword">false</span>, <span class="comment">// canMakeOtherLost</span></div>
+<div class="line"><a name="l13544"></a><span class="lineno">13544</span>&#160;                strategy,</div>
+<div class="line"><a name="l13545"></a><span class="lineno">13545</span>&#160;                &amp;dstAllocRequest) &amp;&amp;</div>
+<div class="line"><a name="l13546"></a><span class="lineno">13546</span>&#160;            MoveMakesSense(</div>
+<div class="line"><a name="l13547"></a><span class="lineno">13547</span>&#160;                dstBlockIndex, dstAllocRequest.offset, srcBlockIndex, srcOffset))</div>
+<div class="line"><a name="l13548"></a><span class="lineno">13548</span>&#160;            {</div>
+<div class="line"><a name="l13549"></a><span class="lineno">13549</span>&#160;                VMA_ASSERT(dstAllocRequest.itemsToMakeLostCount == 0);</div>
+<div class="line"><a name="l13550"></a><span class="lineno">13550</span>&#160; </div>
+<div class="line"><a name="l13551"></a><span class="lineno">13551</span>&#160;                <span class="comment">// Reached limit on number of allocations or bytes to move.</span></div>
+<div class="line"><a name="l13552"></a><span class="lineno">13552</span>&#160;                <span class="keywordflow">if</span>((m_AllocationsMoved + 1 &gt; maxAllocationsToMove) ||</div>
+<div class="line"><a name="l13553"></a><span class="lineno">13553</span>&#160;                    (m_BytesMoved + size &gt; maxBytesToMove))</div>
+<div class="line"><a name="l13554"></a><span class="lineno">13554</span>&#160;                {</div>
+<div class="line"><a name="l13555"></a><span class="lineno">13555</span>&#160;                    <span class="keywordflow">return</span> VK_SUCCESS;</div>
+<div class="line"><a name="l13556"></a><span class="lineno">13556</span>&#160;                }</div>
+<div class="line"><a name="l13557"></a><span class="lineno">13557</span>&#160; </div>
+<div class="line"><a name="l13558"></a><span class="lineno">13558</span>&#160;                VmaDefragmentationMove move = {};</div>
+<div class="line"><a name="l13559"></a><span class="lineno">13559</span>&#160;                move.srcBlockIndex = pSrcBlockInfo-&gt;m_OriginalBlockIndex;</div>
+<div class="line"><a name="l13560"></a><span class="lineno">13560</span>&#160;                move.dstBlockIndex = pDstBlockInfo-&gt;m_OriginalBlockIndex;</div>
+<div class="line"><a name="l13561"></a><span class="lineno">13561</span>&#160;                move.srcOffset = srcOffset;</div>
+<div class="line"><a name="l13562"></a><span class="lineno">13562</span>&#160;                move.dstOffset = dstAllocRequest.offset;</div>
+<div class="line"><a name="l13563"></a><span class="lineno">13563</span>&#160;                move.size = size;</div>
+<div class="line"><a name="l13564"></a><span class="lineno">13564</span>&#160;                move.hAllocation = allocInfo.m_hAllocation;</div>
+<div class="line"><a name="l13565"></a><span class="lineno">13565</span>&#160;                move.pSrcBlock = pSrcBlockInfo-&gt;m_pBlock;</div>
+<div class="line"><a name="l13566"></a><span class="lineno">13566</span>&#160;                move.pDstBlock = pDstBlockInfo-&gt;m_pBlock;</div>
+<div class="line"><a name="l13567"></a><span class="lineno">13567</span>&#160; </div>
+<div class="line"><a name="l13568"></a><span class="lineno">13568</span>&#160;                moves.push_back(move);</div>
+<div class="line"><a name="l13569"></a><span class="lineno">13569</span>&#160; </div>
+<div class="line"><a name="l13570"></a><span class="lineno">13570</span>&#160;                pDstBlockInfo-&gt;m_pBlock-&gt;m_pMetadata-&gt;Alloc(</div>
+<div class="line"><a name="l13571"></a><span class="lineno">13571</span>&#160;                    dstAllocRequest,</div>
+<div class="line"><a name="l13572"></a><span class="lineno">13572</span>&#160;                    suballocType,</div>
+<div class="line"><a name="l13573"></a><span class="lineno">13573</span>&#160;                    size,</div>
+<div class="line"><a name="l13574"></a><span class="lineno">13574</span>&#160;                    allocInfo.m_hAllocation);</div>
+<div class="line"><a name="l13575"></a><span class="lineno">13575</span>&#160; </div>
+<div class="line"><a name="l13576"></a><span class="lineno">13576</span>&#160;                <span class="keywordflow">if</span>(freeOldAllocations)</div>
+<div class="line"><a name="l13577"></a><span class="lineno">13577</span>&#160;                {</div>
+<div class="line"><a name="l13578"></a><span class="lineno">13578</span>&#160;                    pSrcBlockInfo-&gt;m_pBlock-&gt;m_pMetadata-&gt;FreeAtOffset(srcOffset);</div>
+<div class="line"><a name="l13579"></a><span class="lineno">13579</span>&#160;                    allocInfo.m_hAllocation-&gt;ChangeBlockAllocation(m_hAllocator, pDstBlockInfo-&gt;m_pBlock, dstAllocRequest.offset);</div>
+<div class="line"><a name="l13580"></a><span class="lineno">13580</span>&#160;                }</div>
+<div class="line"><a name="l13581"></a><span class="lineno">13581</span>&#160;                </div>
+<div class="line"><a name="l13582"></a><span class="lineno">13582</span>&#160;                <span class="keywordflow">if</span>(allocInfo.m_pChanged != VMA_NULL)</div>
+<div class="line"><a name="l13583"></a><span class="lineno">13583</span>&#160;                {</div>
+<div class="line"><a name="l13584"></a><span class="lineno">13584</span>&#160;                    *allocInfo.m_pChanged = VK_TRUE;</div>
+<div class="line"><a name="l13585"></a><span class="lineno">13585</span>&#160;                }</div>
+<div class="line"><a name="l13586"></a><span class="lineno">13586</span>&#160; </div>
+<div class="line"><a name="l13587"></a><span class="lineno">13587</span>&#160;                ++m_AllocationsMoved;</div>
+<div class="line"><a name="l13588"></a><span class="lineno">13588</span>&#160;                m_BytesMoved += size;</div>
+<div class="line"><a name="l13589"></a><span class="lineno">13589</span>&#160; </div>
+<div class="line"><a name="l13590"></a><span class="lineno">13590</span>&#160;                VmaVectorRemove(pSrcBlockInfo-&gt;m_Allocations, srcAllocIndex);</div>
+<div class="line"><a name="l13591"></a><span class="lineno">13591</span>&#160; </div>
+<div class="line"><a name="l13592"></a><span class="lineno">13592</span>&#160;                <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l13593"></a><span class="lineno">13593</span>&#160;            }</div>
+<div class="line"><a name="l13594"></a><span class="lineno">13594</span>&#160;        }</div>
+<div class="line"><a name="l13595"></a><span class="lineno">13595</span>&#160; </div>
+<div class="line"><a name="l13596"></a><span class="lineno">13596</span>&#160;        <span class="comment">// If not processed, this allocInfo remains in pBlockInfo-&gt;m_Allocations for next round.</span></div>
+<div class="line"><a name="l13597"></a><span class="lineno">13597</span>&#160; </div>
+<div class="line"><a name="l13598"></a><span class="lineno">13598</span>&#160;        <span class="keywordflow">if</span>(srcAllocIndex &gt; 0)</div>
+<div class="line"><a name="l13599"></a><span class="lineno">13599</span>&#160;        {</div>
+<div class="line"><a name="l13600"></a><span class="lineno">13600</span>&#160;            --srcAllocIndex;</div>
+<div class="line"><a name="l13601"></a><span class="lineno">13601</span>&#160;        }</div>
+<div class="line"><a name="l13602"></a><span class="lineno">13602</span>&#160;        <span class="keywordflow">else</span></div>
+<div class="line"><a name="l13603"></a><span class="lineno">13603</span>&#160;        {</div>
+<div class="line"><a name="l13604"></a><span class="lineno">13604</span>&#160;            <span class="keywordflow">if</span>(srcBlockIndex &gt; 0)</div>
+<div class="line"><a name="l13605"></a><span class="lineno">13605</span>&#160;            {</div>
+<div class="line"><a name="l13606"></a><span class="lineno">13606</span>&#160;                --srcBlockIndex;</div>
+<div class="line"><a name="l13607"></a><span class="lineno">13607</span>&#160;                srcAllocIndex = SIZE_MAX;</div>
+<div class="line"><a name="l13608"></a><span class="lineno">13608</span>&#160;            }</div>
+<div class="line"><a name="l13609"></a><span class="lineno">13609</span>&#160;            <span class="keywordflow">else</span></div>
+<div class="line"><a name="l13610"></a><span class="lineno">13610</span>&#160;            {</div>
+<div class="line"><a name="l13611"></a><span class="lineno">13611</span>&#160;                <span class="keywordflow">return</span> VK_SUCCESS;</div>
+<div class="line"><a name="l13612"></a><span class="lineno">13612</span>&#160;            }</div>
+<div class="line"><a name="l13613"></a><span class="lineno">13613</span>&#160;        }</div>
+<div class="line"><a name="l13614"></a><span class="lineno">13614</span>&#160;    }</div>
+<div class="line"><a name="l13615"></a><span class="lineno">13615</span>&#160;}</div>
+<div class="line"><a name="l13616"></a><span class="lineno">13616</span>&#160; </div>
+<div class="line"><a name="l13617"></a><span class="lineno">13617</span>&#160;<span class="keywordtype">size_t</span> VmaDefragmentationAlgorithm_Generic::CalcBlocksWithNonMovableCount()<span class="keyword"> const</span></div>
+<div class="line"><a name="l13618"></a><span class="lineno">13618</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l13619"></a><span class="lineno">13619</span>&#160;    <span class="keywordtype">size_t</span> result = 0;</div>
+<div class="line"><a name="l13620"></a><span class="lineno">13620</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = 0; i &lt; m_Blocks.size(); ++i)</div>
+<div class="line"><a name="l13621"></a><span class="lineno">13621</span>&#160;    {</div>
+<div class="line"><a name="l13622"></a><span class="lineno">13622</span>&#160;        <span class="keywordflow">if</span>(m_Blocks[i]-&gt;m_HasNonMovableAllocations)</div>
+<div class="line"><a name="l13623"></a><span class="lineno">13623</span>&#160;        {</div>
+<div class="line"><a name="l13624"></a><span class="lineno">13624</span>&#160;            ++result;</div>
+<div class="line"><a name="l13625"></a><span class="lineno">13625</span>&#160;        }</div>
+<div class="line"><a name="l13626"></a><span class="lineno">13626</span>&#160;    }</div>
+<div class="line"><a name="l13627"></a><span class="lineno">13627</span>&#160;    <span class="keywordflow">return</span> result;</div>
+<div class="line"><a name="l13628"></a><span class="lineno">13628</span>&#160;}</div>
+<div class="line"><a name="l13629"></a><span class="lineno">13629</span>&#160; </div>
+<div class="line"><a name="l13630"></a><span class="lineno">13630</span>&#160;VkResult VmaDefragmentationAlgorithm_Generic::Defragment(</div>
+<div class="line"><a name="l13631"></a><span class="lineno">13631</span>&#160;    VmaVector&lt; VmaDefragmentationMove, VmaStlAllocator&lt;VmaDefragmentationMove&gt; &gt;&amp; moves,</div>
+<div class="line"><a name="l13632"></a><span class="lineno">13632</span>&#160;    VkDeviceSize maxBytesToMove,</div>
+<div class="line"><a name="l13633"></a><span class="lineno">13633</span>&#160;    uint32_t maxAllocationsToMove,</div>
+<div class="line"><a name="l13634"></a><span class="lineno">13634</span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#a88a77cef37e5d3c4fc9eb328885d048d">VmaDefragmentationFlags</a> flags)</div>
+<div class="line"><a name="l13635"></a><span class="lineno">13635</span>&#160;{</div>
+<div class="line"><a name="l13636"></a><span class="lineno">13636</span>&#160;    <span class="keywordflow">if</span>(!m_AllAllocations &amp;&amp; m_AllocationCount == 0)</div>
+<div class="line"><a name="l13637"></a><span class="lineno">13637</span>&#160;    {</div>
+<div class="line"><a name="l13638"></a><span class="lineno">13638</span>&#160;        <span class="keywordflow">return</span> VK_SUCCESS;</div>
+<div class="line"><a name="l13639"></a><span class="lineno">13639</span>&#160;    }</div>
+<div class="line"><a name="l13640"></a><span class="lineno">13640</span>&#160; </div>
+<div class="line"><a name="l13641"></a><span class="lineno">13641</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">size_t</span> blockCount = m_Blocks.size();</div>
+<div class="line"><a name="l13642"></a><span class="lineno">13642</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> blockIndex = 0; blockIndex &lt; blockCount; ++blockIndex)</div>
+<div class="line"><a name="l13643"></a><span class="lineno">13643</span>&#160;    {</div>
+<div class="line"><a name="l13644"></a><span class="lineno">13644</span>&#160;        BlockInfo* pBlockInfo = m_Blocks[blockIndex];</div>
+<div class="line"><a name="l13645"></a><span class="lineno">13645</span>&#160; </div>
+<div class="line"><a name="l13646"></a><span class="lineno">13646</span>&#160;        <span class="keywordflow">if</span>(m_AllAllocations)</div>
+<div class="line"><a name="l13647"></a><span class="lineno">13647</span>&#160;        {</div>
+<div class="line"><a name="l13648"></a><span class="lineno">13648</span>&#160;            VmaBlockMetadata_Generic* pMetadata = (VmaBlockMetadata_Generic*)pBlockInfo-&gt;m_pBlock-&gt;m_pMetadata;</div>
+<div class="line"><a name="l13649"></a><span class="lineno">13649</span>&#160;            <span class="keywordflow">for</span>(VmaSuballocationList::const_iterator it = pMetadata-&gt;m_Suballocations.begin();</div>
+<div class="line"><a name="l13650"></a><span class="lineno">13650</span>&#160;                it != pMetadata-&gt;m_Suballocations.end();</div>
+<div class="line"><a name="l13651"></a><span class="lineno">13651</span>&#160;                ++it)</div>
+<div class="line"><a name="l13652"></a><span class="lineno">13652</span>&#160;            {</div>
+<div class="line"><a name="l13653"></a><span class="lineno">13653</span>&#160;                <span class="keywordflow">if</span>(it-&gt;type != VMA_SUBALLOCATION_TYPE_FREE)</div>
+<div class="line"><a name="l13654"></a><span class="lineno">13654</span>&#160;                {</div>
+<div class="line"><a name="l13655"></a><span class="lineno">13655</span>&#160;                    AllocationInfo allocInfo = AllocationInfo(it-&gt;hAllocation, VMA_NULL);</div>
+<div class="line"><a name="l13656"></a><span class="lineno">13656</span>&#160;                    pBlockInfo-&gt;m_Allocations.push_back(allocInfo);</div>
+<div class="line"><a name="l13657"></a><span class="lineno">13657</span>&#160;                }</div>
+<div class="line"><a name="l13658"></a><span class="lineno">13658</span>&#160;            }</div>
+<div class="line"><a name="l13659"></a><span class="lineno">13659</span>&#160;        }</div>
+<div class="line"><a name="l13660"></a><span class="lineno">13660</span>&#160; </div>
+<div class="line"><a name="l13661"></a><span class="lineno">13661</span>&#160;        pBlockInfo-&gt;CalcHasNonMovableAllocations();</div>
+<div class="line"><a name="l13662"></a><span class="lineno">13662</span>&#160;        </div>
+<div class="line"><a name="l13663"></a><span class="lineno">13663</span>&#160;        <span class="comment">// This is a choice based on research.</span></div>
+<div class="line"><a name="l13664"></a><span class="lineno">13664</span>&#160;        <span class="comment">// Option 1:</span></div>
+<div class="line"><a name="l13665"></a><span class="lineno">13665</span>&#160;        pBlockInfo-&gt;SortAllocationsByOffsetDescending();</div>
+<div class="line"><a name="l13666"></a><span class="lineno">13666</span>&#160;        <span class="comment">// Option 2:</span></div>
+<div class="line"><a name="l13667"></a><span class="lineno">13667</span>&#160;        <span class="comment">//pBlockInfo-&gt;SortAllocationsBySizeDescending();</span></div>
+<div class="line"><a name="l13668"></a><span class="lineno">13668</span>&#160;    }</div>
+<div class="line"><a name="l13669"></a><span class="lineno">13669</span>&#160; </div>
+<div class="line"><a name="l13670"></a><span class="lineno">13670</span>&#160;    <span class="comment">// Sort m_Blocks this time by the main criterium, from most &quot;destination&quot; to most &quot;source&quot; blocks.</span></div>
+<div class="line"><a name="l13671"></a><span class="lineno">13671</span>&#160;    VMA_SORT(m_Blocks.begin(), m_Blocks.end(), BlockInfoCompareMoveDestination());</div>
+<div class="line"><a name="l13672"></a><span class="lineno">13672</span>&#160; </div>
+<div class="line"><a name="l13673"></a><span class="lineno">13673</span>&#160;    <span class="comment">// This is a choice based on research.</span></div>
+<div class="line"><a name="l13674"></a><span class="lineno">13674</span>&#160;    <span class="keyword">const</span> uint32_t roundCount = 2;</div>
+<div class="line"><a name="l13675"></a><span class="lineno">13675</span>&#160; </div>
+<div class="line"><a name="l13676"></a><span class="lineno">13676</span>&#160;    <span class="comment">// Execute defragmentation rounds (the main part).</span></div>
+<div class="line"><a name="l13677"></a><span class="lineno">13677</span>&#160;    VkResult result = VK_SUCCESS;</div>
+<div class="line"><a name="l13678"></a><span class="lineno">13678</span>&#160;    <span class="keywordflow">for</span>(uint32_t round = 0; (round &lt; roundCount) &amp;&amp; (result == VK_SUCCESS); ++round)</div>
+<div class="line"><a name="l13679"></a><span class="lineno">13679</span>&#160;    {</div>
+<div class="line"><a name="l13680"></a><span class="lineno">13680</span>&#160;        result = DefragmentRound(moves, maxBytesToMove, maxAllocationsToMove, !(flags &amp; <a class="code" href="vk__mem__alloc_8h.html#a6552a65b71d16f378c6994b3ceaef50ca31af49446af2459284a568ce2f3fdd33">VMA_DEFRAGMENTATION_FLAG_INCREMENTAL</a>));</div>
+<div class="line"><a name="l13681"></a><span class="lineno">13681</span>&#160;    }</div>
+<div class="line"><a name="l13682"></a><span class="lineno">13682</span>&#160; </div>
+<div class="line"><a name="l13683"></a><span class="lineno">13683</span>&#160;    <span class="keywordflow">return</span> result;</div>
+<div class="line"><a name="l13684"></a><span class="lineno">13684</span>&#160;}</div>
+<div class="line"><a name="l13685"></a><span class="lineno">13685</span>&#160; </div>
+<div class="line"><a name="l13686"></a><span class="lineno">13686</span>&#160;<span class="keywordtype">bool</span> VmaDefragmentationAlgorithm_Generic::MoveMakesSense(</div>
+<div class="line"><a name="l13687"></a><span class="lineno">13687</span>&#160;        <span class="keywordtype">size_t</span> dstBlockIndex, VkDeviceSize dstOffset,</div>
+<div class="line"><a name="l13688"></a><span class="lineno">13688</span>&#160;        <span class="keywordtype">size_t</span> srcBlockIndex, VkDeviceSize srcOffset)</div>
+<div class="line"><a name="l13689"></a><span class="lineno">13689</span>&#160;{</div>
+<div class="line"><a name="l13690"></a><span class="lineno">13690</span>&#160;    <span class="keywordflow">if</span>(dstBlockIndex &lt; srcBlockIndex)</div>
+<div class="line"><a name="l13691"></a><span class="lineno">13691</span>&#160;    {</div>
+<div class="line"><a name="l13692"></a><span class="lineno">13692</span>&#160;        <span class="keywordflow">return</span> <span class="keyword">true</span>;</div>
+<div class="line"><a name="l13693"></a><span class="lineno">13693</span>&#160;    }</div>
+<div class="line"><a name="l13694"></a><span class="lineno">13694</span>&#160;    <span class="keywordflow">if</span>(dstBlockIndex &gt; srcBlockIndex)</div>
+<div class="line"><a name="l13695"></a><span class="lineno">13695</span>&#160;    {</div>
+<div class="line"><a name="l13696"></a><span class="lineno">13696</span>&#160;        <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l13697"></a><span class="lineno">13697</span>&#160;    }</div>
+<div class="line"><a name="l13698"></a><span class="lineno">13698</span>&#160;    <span class="keywordflow">if</span>(dstOffset &lt; srcOffset)</div>
+<div class="line"><a name="l13699"></a><span class="lineno">13699</span>&#160;    {</div>
+<div class="line"><a name="l13700"></a><span class="lineno">13700</span>&#160;        <span class="keywordflow">return</span> <span class="keyword">true</span>;</div>
+<div class="line"><a name="l13701"></a><span class="lineno">13701</span>&#160;    }</div>
+<div class="line"><a name="l13702"></a><span class="lineno">13702</span>&#160;    <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l13703"></a><span class="lineno">13703</span>&#160;}</div>
+<div class="line"><a name="l13704"></a><span class="lineno">13704</span>&#160; </div>
+<div class="line"><a name="l13706"></a><span class="lineno">13706</span>&#160;<span class="comment">// VmaDefragmentationAlgorithm_Fast</span></div>
+<div class="line"><a name="l13707"></a><span class="lineno">13707</span>&#160; </div>
+<div class="line"><a name="l13708"></a><span class="lineno">13708</span>&#160;VmaDefragmentationAlgorithm_Fast::VmaDefragmentationAlgorithm_Fast(</div>
+<div class="line"><a name="l13709"></a><span class="lineno">13709</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator,</div>
+<div class="line"><a name="l13710"></a><span class="lineno">13710</span>&#160;    VmaBlockVector* pBlockVector,</div>
+<div class="line"><a name="l13711"></a><span class="lineno">13711</span>&#160;    uint32_t currentFrameIndex,</div>
+<div class="line"><a name="l13712"></a><span class="lineno">13712</span>&#160;    <span class="keywordtype">bool</span> overlappingMoveSupported) :</div>
+<div class="line"><a name="l13713"></a><span class="lineno">13713</span>&#160;    VmaDefragmentationAlgorithm(hAllocator, pBlockVector, currentFrameIndex),</div>
+<div class="line"><a name="l13714"></a><span class="lineno">13714</span>&#160;    m_OverlappingMoveSupported(overlappingMoveSupported),</div>
+<div class="line"><a name="l13715"></a><span class="lineno">13715</span>&#160;    m_AllocationCount(0),</div>
+<div class="line"><a name="l13716"></a><span class="lineno">13716</span>&#160;    m_AllAllocations(false),</div>
+<div class="line"><a name="l13717"></a><span class="lineno">13717</span>&#160;    m_BytesMoved(0),</div>
+<div class="line"><a name="l13718"></a><span class="lineno">13718</span>&#160;    m_AllocationsMoved(0),</div>
+<div class="line"><a name="l13719"></a><span class="lineno">13719</span>&#160;    m_BlockInfos(VmaStlAllocator&lt;BlockInfo&gt;(hAllocator-&gt;GetAllocationCallbacks()))</div>
+<div class="line"><a name="l13720"></a><span class="lineno">13720</span>&#160;{</div>
+<div class="line"><a name="l13721"></a><span class="lineno">13721</span>&#160;    VMA_ASSERT(VMA_DEBUG_MARGIN == 0);</div>
+<div class="line"><a name="l13722"></a><span class="lineno">13722</span>&#160; </div>
+<div class="line"><a name="l13723"></a><span class="lineno">13723</span>&#160;}</div>
+<div class="line"><a name="l13724"></a><span class="lineno">13724</span>&#160; </div>
+<div class="line"><a name="l13725"></a><span class="lineno">13725</span>&#160;VmaDefragmentationAlgorithm_Fast::~VmaDefragmentationAlgorithm_Fast()</div>
+<div class="line"><a name="l13726"></a><span class="lineno">13726</span>&#160;{</div>
+<div class="line"><a name="l13727"></a><span class="lineno">13727</span>&#160;}</div>
+<div class="line"><a name="l13728"></a><span class="lineno">13728</span>&#160; </div>
+<div class="line"><a name="l13729"></a><span class="lineno">13729</span>&#160;VkResult VmaDefragmentationAlgorithm_Fast::Defragment(</div>
+<div class="line"><a name="l13730"></a><span class="lineno">13730</span>&#160;    VmaVector&lt; VmaDefragmentationMove, VmaStlAllocator&lt;VmaDefragmentationMove&gt; &gt;&amp; moves,</div>
+<div class="line"><a name="l13731"></a><span class="lineno">13731</span>&#160;    VkDeviceSize maxBytesToMove,</div>
+<div class="line"><a name="l13732"></a><span class="lineno">13732</span>&#160;    uint32_t maxAllocationsToMove,</div>
+<div class="line"><a name="l13733"></a><span class="lineno">13733</span>&#160;    <a class="code" href="vk__mem__alloc_8h.html#a88a77cef37e5d3c4fc9eb328885d048d">VmaDefragmentationFlags</a> flags)</div>
+<div class="line"><a name="l13734"></a><span class="lineno">13734</span>&#160;{</div>
+<div class="line"><a name="l13735"></a><span class="lineno">13735</span>&#160;    VMA_ASSERT(m_AllAllocations || m_pBlockVector-&gt;CalcAllocationCount() == m_AllocationCount);</div>
+<div class="line"><a name="l13736"></a><span class="lineno">13736</span>&#160; </div>
+<div class="line"><a name="l13737"></a><span class="lineno">13737</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">size_t</span> blockCount = m_pBlockVector-&gt;GetBlockCount();</div>
+<div class="line"><a name="l13738"></a><span class="lineno">13738</span>&#160;    <span class="keywordflow">if</span>(blockCount == 0 || maxBytesToMove == 0 || maxAllocationsToMove == 0)</div>
+<div class="line"><a name="l13739"></a><span class="lineno">13739</span>&#160;    {</div>
+<div class="line"><a name="l13740"></a><span class="lineno">13740</span>&#160;        <span class="keywordflow">return</span> VK_SUCCESS;</div>
+<div class="line"><a name="l13741"></a><span class="lineno">13741</span>&#160;    }</div>
+<div class="line"><a name="l13742"></a><span class="lineno">13742</span>&#160; </div>
+<div class="line"><a name="l13743"></a><span class="lineno">13743</span>&#160;    PreprocessMetadata();</div>
+<div class="line"><a name="l13744"></a><span class="lineno">13744</span>&#160; </div>
+<div class="line"><a name="l13745"></a><span class="lineno">13745</span>&#160;    <span class="comment">// Sort blocks in order from most destination.</span></div>
+<div class="line"><a name="l13746"></a><span class="lineno">13746</span>&#160; </div>
+<div class="line"><a name="l13747"></a><span class="lineno">13747</span>&#160;    m_BlockInfos.resize(blockCount);</div>
+<div class="line"><a name="l13748"></a><span class="lineno">13748</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = 0; i &lt; blockCount; ++i)</div>
+<div class="line"><a name="l13749"></a><span class="lineno">13749</span>&#160;    {</div>
+<div class="line"><a name="l13750"></a><span class="lineno">13750</span>&#160;        m_BlockInfos[i].origBlockIndex = i;</div>
+<div class="line"><a name="l13751"></a><span class="lineno">13751</span>&#160;    }</div>
+<div class="line"><a name="l13752"></a><span class="lineno">13752</span>&#160; </div>
+<div class="line"><a name="l13753"></a><span class="lineno">13753</span>&#160;    VMA_SORT(m_BlockInfos.begin(), m_BlockInfos.end(), [<span class="keyword">this</span>](<span class="keyword">const</span> BlockInfo&amp; lhs, <span class="keyword">const</span> BlockInfo&amp; rhs) -&gt; <span class="keywordtype">bool</span> {</div>
+<div class="line"><a name="l13754"></a><span class="lineno">13754</span>&#160;        return m_pBlockVector-&gt;GetBlock(lhs.origBlockIndex)-&gt;m_pMetadata-&gt;GetSumFreeSize() &lt;</div>
+<div class="line"><a name="l13755"></a><span class="lineno">13755</span>&#160;            m_pBlockVector-&gt;GetBlock(rhs.origBlockIndex)-&gt;m_pMetadata-&gt;GetSumFreeSize();</div>
+<div class="line"><a name="l13756"></a><span class="lineno">13756</span>&#160;    });</div>
+<div class="line"><a name="l13757"></a><span class="lineno">13757</span>&#160; </div>
+<div class="line"><a name="l13758"></a><span class="lineno">13758</span>&#160;    <span class="comment">// THE MAIN ALGORITHM</span></div>
+<div class="line"><a name="l13759"></a><span class="lineno">13759</span>&#160; </div>
+<div class="line"><a name="l13760"></a><span class="lineno">13760</span>&#160;    FreeSpaceDatabase freeSpaceDb;</div>
+<div class="line"><a name="l13761"></a><span class="lineno">13761</span>&#160; </div>
+<div class="line"><a name="l13762"></a><span class="lineno">13762</span>&#160;    <span class="keywordtype">size_t</span> dstBlockInfoIndex = 0;</div>
+<div class="line"><a name="l13763"></a><span class="lineno">13763</span>&#160;    <span class="keywordtype">size_t</span> dstOrigBlockIndex = m_BlockInfos[dstBlockInfoIndex].origBlockIndex;</div>
+<div class="line"><a name="l13764"></a><span class="lineno">13764</span>&#160;    VmaDeviceMemoryBlock* pDstBlock = m_pBlockVector-&gt;GetBlock(dstOrigBlockIndex);</div>
+<div class="line"><a name="l13765"></a><span class="lineno">13765</span>&#160;    VmaBlockMetadata_Generic* pDstMetadata = (VmaBlockMetadata_Generic*)pDstBlock-&gt;m_pMetadata;</div>
+<div class="line"><a name="l13766"></a><span class="lineno">13766</span>&#160;    VkDeviceSize dstBlockSize = pDstMetadata-&gt;GetSize();</div>
+<div class="line"><a name="l13767"></a><span class="lineno">13767</span>&#160;    VkDeviceSize dstOffset = 0;</div>
+<div class="line"><a name="l13768"></a><span class="lineno">13768</span>&#160; </div>
+<div class="line"><a name="l13769"></a><span class="lineno">13769</span>&#160;    <span class="keywordtype">bool</span> end = <span class="keyword">false</span>;</div>
+<div class="line"><a name="l13770"></a><span class="lineno">13770</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> srcBlockInfoIndex = 0; !end &amp;&amp; srcBlockInfoIndex &lt; blockCount; ++srcBlockInfoIndex)</div>
+<div class="line"><a name="l13771"></a><span class="lineno">13771</span>&#160;    {</div>
+<div class="line"><a name="l13772"></a><span class="lineno">13772</span>&#160;        <span class="keyword">const</span> <span class="keywordtype">size_t</span> srcOrigBlockIndex = m_BlockInfos[srcBlockInfoIndex].origBlockIndex;</div>
+<div class="line"><a name="l13773"></a><span class="lineno">13773</span>&#160;        VmaDeviceMemoryBlock* <span class="keyword">const</span> pSrcBlock = m_pBlockVector-&gt;GetBlock(srcOrigBlockIndex);</div>
+<div class="line"><a name="l13774"></a><span class="lineno">13774</span>&#160;        VmaBlockMetadata_Generic* <span class="keyword">const</span> pSrcMetadata = (VmaBlockMetadata_Generic*)pSrcBlock-&gt;m_pMetadata;</div>
+<div class="line"><a name="l13775"></a><span class="lineno">13775</span>&#160;        <span class="keywordflow">for</span>(VmaSuballocationList::iterator srcSuballocIt = pSrcMetadata-&gt;m_Suballocations.begin();</div>
+<div class="line"><a name="l13776"></a><span class="lineno">13776</span>&#160;            !end &amp;&amp; srcSuballocIt != pSrcMetadata-&gt;m_Suballocations.end(); )</div>
+<div class="line"><a name="l13777"></a><span class="lineno">13777</span>&#160;        {</div>
+<div class="line"><a name="l13778"></a><span class="lineno">13778</span>&#160;            VmaAllocation_T* <span class="keyword">const</span> pAlloc = srcSuballocIt-&gt;hAllocation;</div>
+<div class="line"><a name="l13779"></a><span class="lineno">13779</span>&#160;            <span class="keyword">const</span> VkDeviceSize srcAllocAlignment = pAlloc-&gt;GetAlignment();</div>
+<div class="line"><a name="l13780"></a><span class="lineno">13780</span>&#160;            <span class="keyword">const</span> VkDeviceSize srcAllocSize = srcSuballocIt-&gt;size;</div>
+<div class="line"><a name="l13781"></a><span class="lineno">13781</span>&#160;            <span class="keywordflow">if</span>(m_AllocationsMoved == maxAllocationsToMove ||</div>
+<div class="line"><a name="l13782"></a><span class="lineno">13782</span>&#160;                m_BytesMoved + srcAllocSize &gt; maxBytesToMove)</div>
+<div class="line"><a name="l13783"></a><span class="lineno">13783</span>&#160;            {</div>
+<div class="line"><a name="l13784"></a><span class="lineno">13784</span>&#160;                end = <span class="keyword">true</span>;</div>
+<div class="line"><a name="l13785"></a><span class="lineno">13785</span>&#160;                <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l13786"></a><span class="lineno">13786</span>&#160;            }</div>
+<div class="line"><a name="l13787"></a><span class="lineno">13787</span>&#160;            <span class="keyword">const</span> VkDeviceSize srcAllocOffset = srcSuballocIt-&gt;offset;</div>
+<div class="line"><a name="l13788"></a><span class="lineno">13788</span>&#160; </div>
+<div class="line"><a name="l13789"></a><span class="lineno">13789</span>&#160;            VmaDefragmentationMove move = {};</div>
+<div class="line"><a name="l13790"></a><span class="lineno">13790</span>&#160;            <span class="comment">// Try to place it in one of free spaces from the database.</span></div>
+<div class="line"><a name="l13791"></a><span class="lineno">13791</span>&#160;            <span class="keywordtype">size_t</span> freeSpaceInfoIndex;</div>
+<div class="line"><a name="l13792"></a><span class="lineno">13792</span>&#160;            VkDeviceSize dstAllocOffset;</div>
+<div class="line"><a name="l13793"></a><span class="lineno">13793</span>&#160;            <span class="keywordflow">if</span>(freeSpaceDb.Fetch(srcAllocAlignment, srcAllocSize,</div>
+<div class="line"><a name="l13794"></a><span class="lineno">13794</span>&#160;                freeSpaceInfoIndex, dstAllocOffset))</div>
+<div class="line"><a name="l13795"></a><span class="lineno">13795</span>&#160;            {</div>
+<div class="line"><a name="l13796"></a><span class="lineno">13796</span>&#160;                <span class="keywordtype">size_t</span> freeSpaceOrigBlockIndex = m_BlockInfos[freeSpaceInfoIndex].origBlockIndex;</div>
+<div class="line"><a name="l13797"></a><span class="lineno">13797</span>&#160;                VmaDeviceMemoryBlock* pFreeSpaceBlock = m_pBlockVector-&gt;GetBlock(freeSpaceOrigBlockIndex);</div>
+<div class="line"><a name="l13798"></a><span class="lineno">13798</span>&#160;                VmaBlockMetadata_Generic* pFreeSpaceMetadata = (VmaBlockMetadata_Generic*)pFreeSpaceBlock-&gt;m_pMetadata;</div>
+<div class="line"><a name="l13799"></a><span class="lineno">13799</span>&#160; </div>
+<div class="line"><a name="l13800"></a><span class="lineno">13800</span>&#160;                <span class="comment">// Same block</span></div>
+<div class="line"><a name="l13801"></a><span class="lineno">13801</span>&#160;                <span class="keywordflow">if</span>(freeSpaceInfoIndex == srcBlockInfoIndex)</div>
+<div class="line"><a name="l13802"></a><span class="lineno">13802</span>&#160;                {</div>
+<div class="line"><a name="l13803"></a><span class="lineno">13803</span>&#160;                    VMA_ASSERT(dstAllocOffset &lt;= srcAllocOffset);</div>
+<div class="line"><a name="l13804"></a><span class="lineno">13804</span>&#160; </div>
+<div class="line"><a name="l13805"></a><span class="lineno">13805</span>&#160;                    <span class="comment">// MOVE OPTION 1: Move the allocation inside the same block by decreasing offset.</span></div>
+<div class="line"><a name="l13806"></a><span class="lineno">13806</span>&#160; </div>
+<div class="line"><a name="l13807"></a><span class="lineno">13807</span>&#160;                    VmaSuballocation suballoc = *srcSuballocIt;</div>
+<div class="line"><a name="l13808"></a><span class="lineno">13808</span>&#160;                    suballoc.offset = dstAllocOffset;</div>
+<div class="line"><a name="l13809"></a><span class="lineno">13809</span>&#160;                    suballoc.hAllocation-&gt;ChangeOffset(dstAllocOffset);</div>
+<div class="line"><a name="l13810"></a><span class="lineno">13810</span>&#160;                    m_BytesMoved += srcAllocSize;</div>
+<div class="line"><a name="l13811"></a><span class="lineno">13811</span>&#160;                    ++m_AllocationsMoved;</div>
+<div class="line"><a name="l13812"></a><span class="lineno">13812</span>&#160;                    </div>
+<div class="line"><a name="l13813"></a><span class="lineno">13813</span>&#160;                    VmaSuballocationList::iterator nextSuballocIt = srcSuballocIt;</div>
+<div class="line"><a name="l13814"></a><span class="lineno">13814</span>&#160;                    ++nextSuballocIt;</div>
+<div class="line"><a name="l13815"></a><span class="lineno">13815</span>&#160;                    pSrcMetadata-&gt;m_Suballocations.erase(srcSuballocIt);</div>
+<div class="line"><a name="l13816"></a><span class="lineno">13816</span>&#160;                    srcSuballocIt = nextSuballocIt;</div>
+<div class="line"><a name="l13817"></a><span class="lineno">13817</span>&#160; </div>
+<div class="line"><a name="l13818"></a><span class="lineno">13818</span>&#160;                    InsertSuballoc(pFreeSpaceMetadata, suballoc);</div>
+<div class="line"><a name="l13819"></a><span class="lineno">13819</span>&#160; </div>
+<div class="line"><a name="l13820"></a><span class="lineno">13820</span>&#160;                    move.srcBlockIndex = srcOrigBlockIndex;</div>
+<div class="line"><a name="l13821"></a><span class="lineno">13821</span>&#160;                    move.dstBlockIndex = freeSpaceOrigBlockIndex;</div>
+<div class="line"><a name="l13822"></a><span class="lineno">13822</span>&#160;                    move.srcOffset = srcAllocOffset;</div>
+<div class="line"><a name="l13823"></a><span class="lineno">13823</span>&#160;                    move.dstOffset = dstAllocOffset;</div>
+<div class="line"><a name="l13824"></a><span class="lineno">13824</span>&#160;                    move.size = srcAllocSize;</div>
+<div class="line"><a name="l13825"></a><span class="lineno">13825</span>&#160;                    </div>
+<div class="line"><a name="l13826"></a><span class="lineno">13826</span>&#160;                    moves.push_back(move);</div>
+<div class="line"><a name="l13827"></a><span class="lineno">13827</span>&#160;                }</div>
+<div class="line"><a name="l13828"></a><span class="lineno">13828</span>&#160;                <span class="comment">// Different block</span></div>
+<div class="line"><a name="l13829"></a><span class="lineno">13829</span>&#160;                <span class="keywordflow">else</span></div>
+<div class="line"><a name="l13830"></a><span class="lineno">13830</span>&#160;                {</div>
+<div class="line"><a name="l13831"></a><span class="lineno">13831</span>&#160;                    <span class="comment">// MOVE OPTION 2: Move the allocation to a different block.</span></div>
+<div class="line"><a name="l13832"></a><span class="lineno">13832</span>&#160; </div>
+<div class="line"><a name="l13833"></a><span class="lineno">13833</span>&#160;                    VMA_ASSERT(freeSpaceInfoIndex &lt; srcBlockInfoIndex);</div>
+<div class="line"><a name="l13834"></a><span class="lineno">13834</span>&#160; </div>
+<div class="line"><a name="l13835"></a><span class="lineno">13835</span>&#160;                    VmaSuballocation suballoc = *srcSuballocIt;</div>
+<div class="line"><a name="l13836"></a><span class="lineno">13836</span>&#160;                    suballoc.offset = dstAllocOffset;</div>
+<div class="line"><a name="l13837"></a><span class="lineno">13837</span>&#160;                    suballoc.hAllocation-&gt;ChangeBlockAllocation(m_hAllocator, pFreeSpaceBlock, dstAllocOffset);</div>
+<div class="line"><a name="l13838"></a><span class="lineno">13838</span>&#160;                    m_BytesMoved += srcAllocSize;</div>
+<div class="line"><a name="l13839"></a><span class="lineno">13839</span>&#160;                    ++m_AllocationsMoved;</div>
+<div class="line"><a name="l13840"></a><span class="lineno">13840</span>&#160; </div>
+<div class="line"><a name="l13841"></a><span class="lineno">13841</span>&#160;                    VmaSuballocationList::iterator nextSuballocIt = srcSuballocIt;</div>
+<div class="line"><a name="l13842"></a><span class="lineno">13842</span>&#160;                    ++nextSuballocIt;</div>
+<div class="line"><a name="l13843"></a><span class="lineno">13843</span>&#160;                    pSrcMetadata-&gt;m_Suballocations.erase(srcSuballocIt);</div>
+<div class="line"><a name="l13844"></a><span class="lineno">13844</span>&#160;                    srcSuballocIt = nextSuballocIt;</div>
+<div class="line"><a name="l13845"></a><span class="lineno">13845</span>&#160; </div>
+<div class="line"><a name="l13846"></a><span class="lineno">13846</span>&#160;                    InsertSuballoc(pFreeSpaceMetadata, suballoc);</div>
+<div class="line"><a name="l13847"></a><span class="lineno">13847</span>&#160; </div>
+<div class="line"><a name="l13848"></a><span class="lineno">13848</span>&#160;                    move.srcBlockIndex = srcOrigBlockIndex;</div>
+<div class="line"><a name="l13849"></a><span class="lineno">13849</span>&#160;                    move.dstBlockIndex = freeSpaceOrigBlockIndex;</div>
+<div class="line"><a name="l13850"></a><span class="lineno">13850</span>&#160;                    move.srcOffset = srcAllocOffset;</div>
+<div class="line"><a name="l13851"></a><span class="lineno">13851</span>&#160;                    move.dstOffset = dstAllocOffset;</div>
+<div class="line"><a name="l13852"></a><span class="lineno">13852</span>&#160;                    move.size = srcAllocSize;</div>
+<div class="line"><a name="l13853"></a><span class="lineno">13853</span>&#160;                    </div>
+<div class="line"><a name="l13854"></a><span class="lineno">13854</span>&#160;                    moves.push_back(move);</div>
+<div class="line"><a name="l13855"></a><span class="lineno">13855</span>&#160;                }</div>
+<div class="line"><a name="l13856"></a><span class="lineno">13856</span>&#160;            }</div>
+<div class="line"><a name="l13857"></a><span class="lineno">13857</span>&#160;            <span class="keywordflow">else</span></div>
+<div class="line"><a name="l13858"></a><span class="lineno">13858</span>&#160;            {</div>
+<div class="line"><a name="l13859"></a><span class="lineno">13859</span>&#160;                dstAllocOffset = VmaAlignUp(dstOffset, srcAllocAlignment);</div>
+<div class="line"><a name="l13860"></a><span class="lineno">13860</span>&#160; </div>
+<div class="line"><a name="l13861"></a><span class="lineno">13861</span>&#160;                <span class="comment">// If the allocation doesn&#39;t fit before the end of dstBlock, forward to next block.</span></div>
+<div class="line"><a name="l13862"></a><span class="lineno">13862</span>&#160;                <span class="keywordflow">while</span>(dstBlockInfoIndex &lt; srcBlockInfoIndex &amp;&amp;</div>
+<div class="line"><a name="l13863"></a><span class="lineno">13863</span>&#160;                    dstAllocOffset + srcAllocSize &gt; dstBlockSize)</div>
+<div class="line"><a name="l13864"></a><span class="lineno">13864</span>&#160;                {</div>
+<div class="line"><a name="l13865"></a><span class="lineno">13865</span>&#160;                    <span class="comment">// But before that, register remaining free space at the end of dst block.</span></div>
+<div class="line"><a name="l13866"></a><span class="lineno">13866</span>&#160;                    freeSpaceDb.Register(dstBlockInfoIndex, dstOffset, dstBlockSize - dstOffset);</div>
+<div class="line"><a name="l13867"></a><span class="lineno">13867</span>&#160; </div>
+<div class="line"><a name="l13868"></a><span class="lineno">13868</span>&#160;                    ++dstBlockInfoIndex;</div>
+<div class="line"><a name="l13869"></a><span class="lineno">13869</span>&#160;                    dstOrigBlockIndex = m_BlockInfos[dstBlockInfoIndex].origBlockIndex;</div>
+<div class="line"><a name="l13870"></a><span class="lineno">13870</span>&#160;                    pDstBlock = m_pBlockVector-&gt;GetBlock(dstOrigBlockIndex);</div>
+<div class="line"><a name="l13871"></a><span class="lineno">13871</span>&#160;                    pDstMetadata = (VmaBlockMetadata_Generic*)pDstBlock-&gt;m_pMetadata;</div>
+<div class="line"><a name="l13872"></a><span class="lineno">13872</span>&#160;                    dstBlockSize = pDstMetadata-&gt;GetSize();</div>
+<div class="line"><a name="l13873"></a><span class="lineno">13873</span>&#160;                    dstOffset = 0;</div>
+<div class="line"><a name="l13874"></a><span class="lineno">13874</span>&#160;                    dstAllocOffset = 0;</div>
+<div class="line"><a name="l13875"></a><span class="lineno">13875</span>&#160;                }</div>
+<div class="line"><a name="l13876"></a><span class="lineno">13876</span>&#160; </div>
+<div class="line"><a name="l13877"></a><span class="lineno">13877</span>&#160;                <span class="comment">// Same block</span></div>
+<div class="line"><a name="l13878"></a><span class="lineno">13878</span>&#160;                <span class="keywordflow">if</span>(dstBlockInfoIndex == srcBlockInfoIndex)</div>
+<div class="line"><a name="l13879"></a><span class="lineno">13879</span>&#160;                {</div>
+<div class="line"><a name="l13880"></a><span class="lineno">13880</span>&#160;                    VMA_ASSERT(dstAllocOffset &lt;= srcAllocOffset);</div>
+<div class="line"><a name="l13881"></a><span class="lineno">13881</span>&#160; </div>
+<div class="line"><a name="l13882"></a><span class="lineno">13882</span>&#160;                    <span class="keyword">const</span> <span class="keywordtype">bool</span> overlap = dstAllocOffset + srcAllocSize &gt; srcAllocOffset;</div>
+<div class="line"><a name="l13883"></a><span class="lineno">13883</span>&#160; </div>
+<div class="line"><a name="l13884"></a><span class="lineno">13884</span>&#160;                    <span class="keywordtype">bool</span> skipOver = overlap;</div>
+<div class="line"><a name="l13885"></a><span class="lineno">13885</span>&#160;                    <span class="keywordflow">if</span>(overlap &amp;&amp; m_OverlappingMoveSupported &amp;&amp; dstAllocOffset &lt; srcAllocOffset)</div>
+<div class="line"><a name="l13886"></a><span class="lineno">13886</span>&#160;                    {</div>
+<div class="line"><a name="l13887"></a><span class="lineno">13887</span>&#160;                        <span class="comment">// If destination and source place overlap, skip if it would move it</span></div>
+<div class="line"><a name="l13888"></a><span class="lineno">13888</span>&#160;                        <span class="comment">// by only &lt; 1/64 of its size.</span></div>
+<div class="line"><a name="l13889"></a><span class="lineno">13889</span>&#160;                        skipOver = (srcAllocOffset - dstAllocOffset) * 64 &lt; srcAllocSize;</div>
+<div class="line"><a name="l13890"></a><span class="lineno">13890</span>&#160;                    }</div>
+<div class="line"><a name="l13891"></a><span class="lineno">13891</span>&#160; </div>
+<div class="line"><a name="l13892"></a><span class="lineno">13892</span>&#160;                    <span class="keywordflow">if</span>(skipOver)</div>
+<div class="line"><a name="l13893"></a><span class="lineno">13893</span>&#160;                    {</div>
+<div class="line"><a name="l13894"></a><span class="lineno">13894</span>&#160;                        freeSpaceDb.Register(dstBlockInfoIndex, dstOffset, srcAllocOffset - dstOffset);</div>
+<div class="line"><a name="l13895"></a><span class="lineno">13895</span>&#160; </div>
+<div class="line"><a name="l13896"></a><span class="lineno">13896</span>&#160;                        dstOffset = srcAllocOffset + srcAllocSize;</div>
+<div class="line"><a name="l13897"></a><span class="lineno">13897</span>&#160;                        ++srcSuballocIt;</div>
+<div class="line"><a name="l13898"></a><span class="lineno">13898</span>&#160;                    }</div>
+<div class="line"><a name="l13899"></a><span class="lineno">13899</span>&#160;                    <span class="comment">// MOVE OPTION 1: Move the allocation inside the same block by decreasing offset.</span></div>
+<div class="line"><a name="l13900"></a><span class="lineno">13900</span>&#160;                    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l13901"></a><span class="lineno">13901</span>&#160;                    {</div>
+<div class="line"><a name="l13902"></a><span class="lineno">13902</span>&#160;                        srcSuballocIt-&gt;offset = dstAllocOffset;</div>
+<div class="line"><a name="l13903"></a><span class="lineno">13903</span>&#160;                        srcSuballocIt-&gt;hAllocation-&gt;ChangeOffset(dstAllocOffset);</div>
+<div class="line"><a name="l13904"></a><span class="lineno">13904</span>&#160;                        dstOffset = dstAllocOffset + srcAllocSize;</div>
+<div class="line"><a name="l13905"></a><span class="lineno">13905</span>&#160;                        m_BytesMoved += srcAllocSize;</div>
+<div class="line"><a name="l13906"></a><span class="lineno">13906</span>&#160;                        ++m_AllocationsMoved;</div>
+<div class="line"><a name="l13907"></a><span class="lineno">13907</span>&#160;                        ++srcSuballocIt;</div>
+<div class="line"><a name="l13908"></a><span class="lineno">13908</span>&#160;                        </div>
+<div class="line"><a name="l13909"></a><span class="lineno">13909</span>&#160;                        move.srcBlockIndex = srcOrigBlockIndex;</div>
+<div class="line"><a name="l13910"></a><span class="lineno">13910</span>&#160;                        move.dstBlockIndex = dstOrigBlockIndex;</div>
+<div class="line"><a name="l13911"></a><span class="lineno">13911</span>&#160;                        move.srcOffset = srcAllocOffset;</div>
+<div class="line"><a name="l13912"></a><span class="lineno">13912</span>&#160;                        move.dstOffset = dstAllocOffset;</div>
+<div class="line"><a name="l13913"></a><span class="lineno">13913</span>&#160;                        move.size = srcAllocSize;</div>
+<div class="line"><a name="l13914"></a><span class="lineno">13914</span>&#160;                        </div>
+<div class="line"><a name="l13915"></a><span class="lineno">13915</span>&#160;                        moves.push_back(move);</div>
+<div class="line"><a name="l13916"></a><span class="lineno">13916</span>&#160;                    }</div>
+<div class="line"><a name="l13917"></a><span class="lineno">13917</span>&#160;                }</div>
+<div class="line"><a name="l13918"></a><span class="lineno">13918</span>&#160;                <span class="comment">// Different block</span></div>
+<div class="line"><a name="l13919"></a><span class="lineno">13919</span>&#160;                <span class="keywordflow">else</span></div>
+<div class="line"><a name="l13920"></a><span class="lineno">13920</span>&#160;                {</div>
+<div class="line"><a name="l13921"></a><span class="lineno">13921</span>&#160;                    <span class="comment">// MOVE OPTION 2: Move the allocation to a different block.</span></div>
+<div class="line"><a name="l13922"></a><span class="lineno">13922</span>&#160; </div>
+<div class="line"><a name="l13923"></a><span class="lineno">13923</span>&#160;                    VMA_ASSERT(dstBlockInfoIndex &lt; srcBlockInfoIndex);</div>
+<div class="line"><a name="l13924"></a><span class="lineno">13924</span>&#160;                    VMA_ASSERT(dstAllocOffset + srcAllocSize &lt;= dstBlockSize);</div>
+<div class="line"><a name="l13925"></a><span class="lineno">13925</span>&#160; </div>
+<div class="line"><a name="l13926"></a><span class="lineno">13926</span>&#160;                    VmaSuballocation suballoc = *srcSuballocIt;</div>
+<div class="line"><a name="l13927"></a><span class="lineno">13927</span>&#160;                    suballoc.offset = dstAllocOffset;</div>
+<div class="line"><a name="l13928"></a><span class="lineno">13928</span>&#160;                    suballoc.hAllocation-&gt;ChangeBlockAllocation(m_hAllocator, pDstBlock, dstAllocOffset);</div>
+<div class="line"><a name="l13929"></a><span class="lineno">13929</span>&#160;                    dstOffset = dstAllocOffset + srcAllocSize;</div>
+<div class="line"><a name="l13930"></a><span class="lineno">13930</span>&#160;                    m_BytesMoved += srcAllocSize;</div>
+<div class="line"><a name="l13931"></a><span class="lineno">13931</span>&#160;                    ++m_AllocationsMoved;</div>
+<div class="line"><a name="l13932"></a><span class="lineno">13932</span>&#160; </div>
+<div class="line"><a name="l13933"></a><span class="lineno">13933</span>&#160;                    VmaSuballocationList::iterator nextSuballocIt = srcSuballocIt;</div>
+<div class="line"><a name="l13934"></a><span class="lineno">13934</span>&#160;                    ++nextSuballocIt;</div>
+<div class="line"><a name="l13935"></a><span class="lineno">13935</span>&#160;                    pSrcMetadata-&gt;m_Suballocations.erase(srcSuballocIt);</div>
+<div class="line"><a name="l13936"></a><span class="lineno">13936</span>&#160;                    srcSuballocIt = nextSuballocIt;</div>
+<div class="line"><a name="l13937"></a><span class="lineno">13937</span>&#160; </div>
+<div class="line"><a name="l13938"></a><span class="lineno">13938</span>&#160;                    pDstMetadata-&gt;m_Suballocations.push_back(suballoc);</div>
+<div class="line"><a name="l13939"></a><span class="lineno">13939</span>&#160; </div>
+<div class="line"><a name="l13940"></a><span class="lineno">13940</span>&#160;                    move.srcBlockIndex = srcOrigBlockIndex;</div>
+<div class="line"><a name="l13941"></a><span class="lineno">13941</span>&#160;                    move.dstBlockIndex = dstOrigBlockIndex;</div>
+<div class="line"><a name="l13942"></a><span class="lineno">13942</span>&#160;                    move.srcOffset = srcAllocOffset;</div>
+<div class="line"><a name="l13943"></a><span class="lineno">13943</span>&#160;                    move.dstOffset = dstAllocOffset;</div>
+<div class="line"><a name="l13944"></a><span class="lineno">13944</span>&#160;                    move.size = srcAllocSize;</div>
+<div class="line"><a name="l13945"></a><span class="lineno">13945</span>&#160;                    </div>
+<div class="line"><a name="l13946"></a><span class="lineno">13946</span>&#160;                    moves.push_back(move);</div>
+<div class="line"><a name="l13947"></a><span class="lineno">13947</span>&#160;                }</div>
+<div class="line"><a name="l13948"></a><span class="lineno">13948</span>&#160;            }</div>
+<div class="line"><a name="l13949"></a><span class="lineno">13949</span>&#160;        }</div>
+<div class="line"><a name="l13950"></a><span class="lineno">13950</span>&#160;    }</div>
+<div class="line"><a name="l13951"></a><span class="lineno">13951</span>&#160; </div>
+<div class="line"><a name="l13952"></a><span class="lineno">13952</span>&#160;    m_BlockInfos.clear();</div>
+<div class="line"><a name="l13953"></a><span class="lineno">13953</span>&#160;    </div>
+<div class="line"><a name="l13954"></a><span class="lineno">13954</span>&#160;    PostprocessMetadata();</div>
+<div class="line"><a name="l13955"></a><span class="lineno">13955</span>&#160; </div>
+<div class="line"><a name="l13956"></a><span class="lineno">13956</span>&#160;    <span class="keywordflow">return</span> VK_SUCCESS;</div>
+<div class="line"><a name="l13957"></a><span class="lineno">13957</span>&#160;}</div>
+<div class="line"><a name="l13958"></a><span class="lineno">13958</span>&#160; </div>
+<div class="line"><a name="l13959"></a><span class="lineno">13959</span>&#160;<span class="keywordtype">void</span> VmaDefragmentationAlgorithm_Fast::PreprocessMetadata()</div>
+<div class="line"><a name="l13960"></a><span class="lineno">13960</span>&#160;{</div>
+<div class="line"><a name="l13961"></a><span class="lineno">13961</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">size_t</span> blockCount = m_pBlockVector-&gt;GetBlockCount();</div>
+<div class="line"><a name="l13962"></a><span class="lineno">13962</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> blockIndex = 0; blockIndex &lt; blockCount; ++blockIndex)</div>
+<div class="line"><a name="l13963"></a><span class="lineno">13963</span>&#160;    {</div>
+<div class="line"><a name="l13964"></a><span class="lineno">13964</span>&#160;        VmaBlockMetadata_Generic* <span class="keyword">const</span> pMetadata =</div>
+<div class="line"><a name="l13965"></a><span class="lineno">13965</span>&#160;            (VmaBlockMetadata_Generic*)m_pBlockVector-&gt;GetBlock(blockIndex)-&gt;m_pMetadata;</div>
+<div class="line"><a name="l13966"></a><span class="lineno">13966</span>&#160;        pMetadata-&gt;m_FreeCount = 0;</div>
+<div class="line"><a name="l13967"></a><span class="lineno">13967</span>&#160;        pMetadata-&gt;m_SumFreeSize = pMetadata-&gt;GetSize();</div>
+<div class="line"><a name="l13968"></a><span class="lineno">13968</span>&#160;        pMetadata-&gt;m_FreeSuballocationsBySize.clear();</div>
+<div class="line"><a name="l13969"></a><span class="lineno">13969</span>&#160;        <span class="keywordflow">for</span>(VmaSuballocationList::iterator it = pMetadata-&gt;m_Suballocations.begin();</div>
+<div class="line"><a name="l13970"></a><span class="lineno">13970</span>&#160;            it != pMetadata-&gt;m_Suballocations.end(); )</div>
+<div class="line"><a name="l13971"></a><span class="lineno">13971</span>&#160;        {</div>
+<div class="line"><a name="l13972"></a><span class="lineno">13972</span>&#160;            <span class="keywordflow">if</span>(it-&gt;type == VMA_SUBALLOCATION_TYPE_FREE)</div>
+<div class="line"><a name="l13973"></a><span class="lineno">13973</span>&#160;            {</div>
+<div class="line"><a name="l13974"></a><span class="lineno">13974</span>&#160;                VmaSuballocationList::iterator nextIt = it;</div>
+<div class="line"><a name="l13975"></a><span class="lineno">13975</span>&#160;                ++nextIt;</div>
+<div class="line"><a name="l13976"></a><span class="lineno">13976</span>&#160;                pMetadata-&gt;m_Suballocations.erase(it);</div>
+<div class="line"><a name="l13977"></a><span class="lineno">13977</span>&#160;                it = nextIt;</div>
+<div class="line"><a name="l13978"></a><span class="lineno">13978</span>&#160;            }</div>
+<div class="line"><a name="l13979"></a><span class="lineno">13979</span>&#160;            <span class="keywordflow">else</span></div>
+<div class="line"><a name="l13980"></a><span class="lineno">13980</span>&#160;            {</div>
+<div class="line"><a name="l13981"></a><span class="lineno">13981</span>&#160;                ++it;</div>
+<div class="line"><a name="l13982"></a><span class="lineno">13982</span>&#160;            }</div>
+<div class="line"><a name="l13983"></a><span class="lineno">13983</span>&#160;        }</div>
+<div class="line"><a name="l13984"></a><span class="lineno">13984</span>&#160;    }</div>
+<div class="line"><a name="l13985"></a><span class="lineno">13985</span>&#160;}</div>
+<div class="line"><a name="l13986"></a><span class="lineno">13986</span>&#160; </div>
+<div class="line"><a name="l13987"></a><span class="lineno">13987</span>&#160;<span class="keywordtype">void</span> VmaDefragmentationAlgorithm_Fast::PostprocessMetadata()</div>
+<div class="line"><a name="l13988"></a><span class="lineno">13988</span>&#160;{</div>
+<div class="line"><a name="l13989"></a><span class="lineno">13989</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">size_t</span> blockCount = m_pBlockVector-&gt;GetBlockCount();</div>
+<div class="line"><a name="l13990"></a><span class="lineno">13990</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> blockIndex = 0; blockIndex &lt; blockCount; ++blockIndex)</div>
+<div class="line"><a name="l13991"></a><span class="lineno">13991</span>&#160;    {</div>
+<div class="line"><a name="l13992"></a><span class="lineno">13992</span>&#160;        VmaBlockMetadata_Generic* <span class="keyword">const</span> pMetadata =</div>
+<div class="line"><a name="l13993"></a><span class="lineno">13993</span>&#160;            (VmaBlockMetadata_Generic*)m_pBlockVector-&gt;GetBlock(blockIndex)-&gt;m_pMetadata;</div>
+<div class="line"><a name="l13994"></a><span class="lineno">13994</span>&#160;        <span class="keyword">const</span> VkDeviceSize blockSize = pMetadata-&gt;GetSize();</div>
+<div class="line"><a name="l13995"></a><span class="lineno">13995</span>&#160;        </div>
+<div class="line"><a name="l13996"></a><span class="lineno">13996</span>&#160;        <span class="comment">// No allocations in this block - entire area is free.</span></div>
+<div class="line"><a name="l13997"></a><span class="lineno">13997</span>&#160;        <span class="keywordflow">if</span>(pMetadata-&gt;m_Suballocations.empty())</div>
+<div class="line"><a name="l13998"></a><span class="lineno">13998</span>&#160;        {</div>
+<div class="line"><a name="l13999"></a><span class="lineno">13999</span>&#160;            pMetadata-&gt;m_FreeCount = 1;</div>
+<div class="line"><a name="l14000"></a><span class="lineno">14000</span>&#160;            <span class="comment">//pMetadata-&gt;m_SumFreeSize is already set to blockSize.</span></div>
+<div class="line"><a name="l14001"></a><span class="lineno">14001</span>&#160;            VmaSuballocation suballoc = {</div>
+<div class="line"><a name="l14002"></a><span class="lineno">14002</span>&#160;                0, <span class="comment">// offset</span></div>
+<div class="line"><a name="l14003"></a><span class="lineno">14003</span>&#160;                blockSize, <span class="comment">// size</span></div>
+<div class="line"><a name="l14004"></a><span class="lineno">14004</span>&#160;                VMA_NULL, <span class="comment">// hAllocation</span></div>
+<div class="line"><a name="l14005"></a><span class="lineno">14005</span>&#160;                VMA_SUBALLOCATION_TYPE_FREE };</div>
+<div class="line"><a name="l14006"></a><span class="lineno">14006</span>&#160;            pMetadata-&gt;m_Suballocations.push_back(suballoc);</div>
+<div class="line"><a name="l14007"></a><span class="lineno">14007</span>&#160;            pMetadata-&gt;RegisterFreeSuballocation(pMetadata-&gt;m_Suballocations.begin());</div>
+<div class="line"><a name="l14008"></a><span class="lineno">14008</span>&#160;        }</div>
+<div class="line"><a name="l14009"></a><span class="lineno">14009</span>&#160;        <span class="comment">// There are some allocations in this block.</span></div>
+<div class="line"><a name="l14010"></a><span class="lineno">14010</span>&#160;        <span class="keywordflow">else</span></div>
+<div class="line"><a name="l14011"></a><span class="lineno">14011</span>&#160;        {</div>
+<div class="line"><a name="l14012"></a><span class="lineno">14012</span>&#160;            VkDeviceSize offset = 0;</div>
+<div class="line"><a name="l14013"></a><span class="lineno">14013</span>&#160;            VmaSuballocationList::iterator it;</div>
+<div class="line"><a name="l14014"></a><span class="lineno">14014</span>&#160;            <span class="keywordflow">for</span>(it = pMetadata-&gt;m_Suballocations.begin();</div>
+<div class="line"><a name="l14015"></a><span class="lineno">14015</span>&#160;                it != pMetadata-&gt;m_Suballocations.end();</div>
+<div class="line"><a name="l14016"></a><span class="lineno">14016</span>&#160;                ++it)</div>
+<div class="line"><a name="l14017"></a><span class="lineno">14017</span>&#160;            {</div>
+<div class="line"><a name="l14018"></a><span class="lineno">14018</span>&#160;                VMA_ASSERT(it-&gt;type != VMA_SUBALLOCATION_TYPE_FREE);</div>
+<div class="line"><a name="l14019"></a><span class="lineno">14019</span>&#160;                VMA_ASSERT(it-&gt;offset &gt;= offset);</div>
+<div class="line"><a name="l14020"></a><span class="lineno">14020</span>&#160; </div>
+<div class="line"><a name="l14021"></a><span class="lineno">14021</span>&#160;                <span class="comment">// Need to insert preceding free space.</span></div>
+<div class="line"><a name="l14022"></a><span class="lineno">14022</span>&#160;                <span class="keywordflow">if</span>(it-&gt;offset &gt; offset)</div>
+<div class="line"><a name="l14023"></a><span class="lineno">14023</span>&#160;                {</div>
+<div class="line"><a name="l14024"></a><span class="lineno">14024</span>&#160;                    ++pMetadata-&gt;m_FreeCount;</div>
+<div class="line"><a name="l14025"></a><span class="lineno">14025</span>&#160;                    <span class="keyword">const</span> VkDeviceSize freeSize = it-&gt;offset - offset;</div>
+<div class="line"><a name="l14026"></a><span class="lineno">14026</span>&#160;                    VmaSuballocation suballoc = {</div>
+<div class="line"><a name="l14027"></a><span class="lineno">14027</span>&#160;                        offset, <span class="comment">// offset</span></div>
+<div class="line"><a name="l14028"></a><span class="lineno">14028</span>&#160;                        freeSize, <span class="comment">// size</span></div>
+<div class="line"><a name="l14029"></a><span class="lineno">14029</span>&#160;                        VMA_NULL, <span class="comment">// hAllocation</span></div>
+<div class="line"><a name="l14030"></a><span class="lineno">14030</span>&#160;                        VMA_SUBALLOCATION_TYPE_FREE };</div>
+<div class="line"><a name="l14031"></a><span class="lineno">14031</span>&#160;                    VmaSuballocationList::iterator precedingFreeIt = pMetadata-&gt;m_Suballocations.insert(it, suballoc);</div>
+<div class="line"><a name="l14032"></a><span class="lineno">14032</span>&#160;                    <span class="keywordflow">if</span>(freeSize &gt;= VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER)</div>
+<div class="line"><a name="l14033"></a><span class="lineno">14033</span>&#160;                    {</div>
+<div class="line"><a name="l14034"></a><span class="lineno">14034</span>&#160;                        pMetadata-&gt;m_FreeSuballocationsBySize.push_back(precedingFreeIt);</div>
+<div class="line"><a name="l14035"></a><span class="lineno">14035</span>&#160;                    }</div>
+<div class="line"><a name="l14036"></a><span class="lineno">14036</span>&#160;                }</div>
+<div class="line"><a name="l14037"></a><span class="lineno">14037</span>&#160; </div>
+<div class="line"><a name="l14038"></a><span class="lineno">14038</span>&#160;                pMetadata-&gt;m_SumFreeSize -= it-&gt;size;</div>
+<div class="line"><a name="l14039"></a><span class="lineno">14039</span>&#160;                offset = it-&gt;offset + it-&gt;size;</div>
+<div class="line"><a name="l14040"></a><span class="lineno">14040</span>&#160;            }</div>
+<div class="line"><a name="l14041"></a><span class="lineno">14041</span>&#160; </div>
+<div class="line"><a name="l14042"></a><span class="lineno">14042</span>&#160;            <span class="comment">// Need to insert trailing free space.</span></div>
+<div class="line"><a name="l14043"></a><span class="lineno">14043</span>&#160;            <span class="keywordflow">if</span>(offset &lt; blockSize)</div>
+<div class="line"><a name="l14044"></a><span class="lineno">14044</span>&#160;            {</div>
+<div class="line"><a name="l14045"></a><span class="lineno">14045</span>&#160;                ++pMetadata-&gt;m_FreeCount;</div>
+<div class="line"><a name="l14046"></a><span class="lineno">14046</span>&#160;                <span class="keyword">const</span> VkDeviceSize freeSize = blockSize - offset;</div>
+<div class="line"><a name="l14047"></a><span class="lineno">14047</span>&#160;                VmaSuballocation suballoc = {</div>
+<div class="line"><a name="l14048"></a><span class="lineno">14048</span>&#160;                    offset, <span class="comment">// offset</span></div>
+<div class="line"><a name="l14049"></a><span class="lineno">14049</span>&#160;                    freeSize, <span class="comment">// size</span></div>
+<div class="line"><a name="l14050"></a><span class="lineno">14050</span>&#160;                    VMA_NULL, <span class="comment">// hAllocation</span></div>
+<div class="line"><a name="l14051"></a><span class="lineno">14051</span>&#160;                    VMA_SUBALLOCATION_TYPE_FREE };</div>
+<div class="line"><a name="l14052"></a><span class="lineno">14052</span>&#160;                VMA_ASSERT(it == pMetadata-&gt;m_Suballocations.end());</div>
+<div class="line"><a name="l14053"></a><span class="lineno">14053</span>&#160;                VmaSuballocationList::iterator trailingFreeIt = pMetadata-&gt;m_Suballocations.insert(it, suballoc);</div>
+<div class="line"><a name="l14054"></a><span class="lineno">14054</span>&#160;                <span class="keywordflow">if</span>(freeSize &gt; VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER)</div>
+<div class="line"><a name="l14055"></a><span class="lineno">14055</span>&#160;                {</div>
+<div class="line"><a name="l14056"></a><span class="lineno">14056</span>&#160;                    pMetadata-&gt;m_FreeSuballocationsBySize.push_back(trailingFreeIt);</div>
+<div class="line"><a name="l14057"></a><span class="lineno">14057</span>&#160;                }</div>
+<div class="line"><a name="l14058"></a><span class="lineno">14058</span>&#160;            }</div>
+<div class="line"><a name="l14059"></a><span class="lineno">14059</span>&#160; </div>
+<div class="line"><a name="l14060"></a><span class="lineno">14060</span>&#160;            VMA_SORT(</div>
+<div class="line"><a name="l14061"></a><span class="lineno">14061</span>&#160;                pMetadata-&gt;m_FreeSuballocationsBySize.begin(),</div>
+<div class="line"><a name="l14062"></a><span class="lineno">14062</span>&#160;                pMetadata-&gt;m_FreeSuballocationsBySize.end(),</div>
+<div class="line"><a name="l14063"></a><span class="lineno">14063</span>&#160;                VmaSuballocationItemSizeLess());</div>
+<div class="line"><a name="l14064"></a><span class="lineno">14064</span>&#160;        }</div>
+<div class="line"><a name="l14065"></a><span class="lineno">14065</span>&#160; </div>
+<div class="line"><a name="l14066"></a><span class="lineno">14066</span>&#160;        VMA_HEAVY_ASSERT(pMetadata-&gt;Validate());</div>
+<div class="line"><a name="l14067"></a><span class="lineno">14067</span>&#160;    }</div>
+<div class="line"><a name="l14068"></a><span class="lineno">14068</span>&#160;}</div>
+<div class="line"><a name="l14069"></a><span class="lineno">14069</span>&#160; </div>
+<div class="line"><a name="l14070"></a><span class="lineno">14070</span>&#160;<span class="keywordtype">void</span> VmaDefragmentationAlgorithm_Fast::InsertSuballoc(VmaBlockMetadata_Generic* pMetadata, <span class="keyword">const</span> VmaSuballocation&amp; suballoc)</div>
+<div class="line"><a name="l14071"></a><span class="lineno">14071</span>&#160;{</div>
+<div class="line"><a name="l14072"></a><span class="lineno">14072</span>&#160;    <span class="comment">// TODO: Optimize somehow. Remember iterator instead of searching for it linearly.</span></div>
+<div class="line"><a name="l14073"></a><span class="lineno">14073</span>&#160;    VmaSuballocationList::iterator it = pMetadata-&gt;m_Suballocations.begin();</div>
+<div class="line"><a name="l14074"></a><span class="lineno">14074</span>&#160;    <span class="keywordflow">while</span>(it != pMetadata-&gt;m_Suballocations.end())</div>
+<div class="line"><a name="l14075"></a><span class="lineno">14075</span>&#160;    {</div>
+<div class="line"><a name="l14076"></a><span class="lineno">14076</span>&#160;        <span class="keywordflow">if</span>(it-&gt;offset &lt; suballoc.offset)</div>
+<div class="line"><a name="l14077"></a><span class="lineno">14077</span>&#160;        {</div>
+<div class="line"><a name="l14078"></a><span class="lineno">14078</span>&#160;            ++it;</div>
+<div class="line"><a name="l14079"></a><span class="lineno">14079</span>&#160;        }</div>
+<div class="line"><a name="l14080"></a><span class="lineno">14080</span>&#160;    }</div>
+<div class="line"><a name="l14081"></a><span class="lineno">14081</span>&#160;    pMetadata-&gt;m_Suballocations.insert(it, suballoc);</div>
+<div class="line"><a name="l14082"></a><span class="lineno">14082</span>&#160;}</div>
+<div class="line"><a name="l14083"></a><span class="lineno">14083</span>&#160; </div>
+<div class="line"><a name="l14085"></a><span class="lineno">14085</span>&#160;<span class="comment">// VmaBlockVectorDefragmentationContext</span></div>
+<div class="line"><a name="l14086"></a><span class="lineno">14086</span>&#160; </div>
+<div class="line"><a name="l14087"></a><span class="lineno">14087</span>&#160;VmaBlockVectorDefragmentationContext::VmaBlockVectorDefragmentationContext(</div>
+<div class="line"><a name="l14088"></a><span class="lineno">14088</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator,</div>
+<div class="line"><a name="l14089"></a><span class="lineno">14089</span>&#160;    <a class="code" href="struct_vma_pool.html">VmaPool</a> hCustomPool,</div>
+<div class="line"><a name="l14090"></a><span class="lineno">14090</span>&#160;    VmaBlockVector* pBlockVector,</div>
+<div class="line"><a name="l14091"></a><span class="lineno">14091</span>&#160;    uint32_t currFrameIndex) :</div>
+<div class="line"><a name="l14092"></a><span class="lineno">14092</span>&#160;    res(VK_SUCCESS),</div>
+<div class="line"><a name="l14093"></a><span class="lineno">14093</span>&#160;    mutexLocked(false),</div>
+<div class="line"><a name="l14094"></a><span class="lineno">14094</span>&#160;    blockContexts(VmaStlAllocator&lt;VmaBlockDefragmentationContext&gt;(hAllocator-&gt;GetAllocationCallbacks())),</div>
+<div class="line"><a name="l14095"></a><span class="lineno">14095</span>&#160;    defragmentationMoves(VmaStlAllocator&lt;VmaDefragmentationMove&gt;(hAllocator-&gt;GetAllocationCallbacks())),</div>
+<div class="line"><a name="l14096"></a><span class="lineno">14096</span>&#160;    defragmentationMovesProcessed(0),</div>
+<div class="line"><a name="l14097"></a><span class="lineno">14097</span>&#160;    defragmentationMovesCommitted(0),</div>
+<div class="line"><a name="l14098"></a><span class="lineno">14098</span>&#160;    hasDefragmentationPlan(0),</div>
+<div class="line"><a name="l14099"></a><span class="lineno">14099</span>&#160;    m_hAllocator(hAllocator),</div>
+<div class="line"><a name="l14100"></a><span class="lineno">14100</span>&#160;    m_hCustomPool(hCustomPool),</div>
+<div class="line"><a name="l14101"></a><span class="lineno">14101</span>&#160;    m_pBlockVector(pBlockVector),</div>
+<div class="line"><a name="l14102"></a><span class="lineno">14102</span>&#160;    m_CurrFrameIndex(currFrameIndex),</div>
+<div class="line"><a name="l14103"></a><span class="lineno">14103</span>&#160;    m_pAlgorithm(VMA_NULL),</div>
+<div class="line"><a name="l14104"></a><span class="lineno">14104</span>&#160;    m_Allocations(VmaStlAllocator&lt;AllocInfo&gt;(hAllocator-&gt;GetAllocationCallbacks())),</div>
+<div class="line"><a name="l14105"></a><span class="lineno">14105</span>&#160;    m_AllAllocations(false)</div>
+<div class="line"><a name="l14106"></a><span class="lineno">14106</span>&#160;{</div>
+<div class="line"><a name="l14107"></a><span class="lineno">14107</span>&#160;}</div>
+<div class="line"><a name="l14108"></a><span class="lineno">14108</span>&#160; </div>
+<div class="line"><a name="l14109"></a><span class="lineno">14109</span>&#160;VmaBlockVectorDefragmentationContext::~VmaBlockVectorDefragmentationContext()</div>
+<div class="line"><a name="l14110"></a><span class="lineno">14110</span>&#160;{</div>
+<div class="line"><a name="l14111"></a><span class="lineno">14111</span>&#160;    vma_delete(m_hAllocator, m_pAlgorithm);</div>
+<div class="line"><a name="l14112"></a><span class="lineno">14112</span>&#160;}</div>
+<div class="line"><a name="l14113"></a><span class="lineno">14113</span>&#160; </div>
+<div class="line"><a name="l14114"></a><span class="lineno">14114</span>&#160;<span class="keywordtype">void</span> VmaBlockVectorDefragmentationContext::AddAllocation(<a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAlloc, VkBool32* pChanged)</div>
+<div class="line"><a name="l14115"></a><span class="lineno">14115</span>&#160;{</div>
+<div class="line"><a name="l14116"></a><span class="lineno">14116</span>&#160;    AllocInfo info = { hAlloc, pChanged };</div>
+<div class="line"><a name="l14117"></a><span class="lineno">14117</span>&#160;    m_Allocations.push_back(info);</div>
+<div class="line"><a name="l14118"></a><span class="lineno">14118</span>&#160;}</div>
+<div class="line"><a name="l14119"></a><span class="lineno">14119</span>&#160; </div>
+<div class="line"><a name="l14120"></a><span class="lineno">14120</span>&#160;<span class="keywordtype">void</span> VmaBlockVectorDefragmentationContext::Begin(<span class="keywordtype">bool</span> overlappingMoveSupported, <a class="code" href="vk__mem__alloc_8h.html#a88a77cef37e5d3c4fc9eb328885d048d">VmaDefragmentationFlags</a> flags)</div>
+<div class="line"><a name="l14121"></a><span class="lineno">14121</span>&#160;{</div>
+<div class="line"><a name="l14122"></a><span class="lineno">14122</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">bool</span> allAllocations = m_AllAllocations ||</div>
+<div class="line"><a name="l14123"></a><span class="lineno">14123</span>&#160;        m_Allocations.size() == m_pBlockVector-&gt;CalcAllocationCount();</div>
+<div class="line"><a name="l14124"></a><span class="lineno">14124</span>&#160; </div>
+<div class="line"><a name="l14125"></a><span class="lineno">14125</span>&#160;<span class="comment">    /********************************</span></div>
+<div class="line"><a name="l14126"></a><span class="lineno">14126</span>&#160;<span class="comment">    HERE IS THE CHOICE OF DEFRAGMENTATION ALGORITHM.</span></div>
+<div class="line"><a name="l14127"></a><span class="lineno">14127</span>&#160;<span class="comment">    ********************************/</span></div>
+<div class="line"><a name="l14128"></a><span class="lineno">14128</span>&#160; </div>
+<div class="line"><a name="l14129"></a><span class="lineno">14129</span>&#160;    <span class="comment">/*</span></div>
+<div class="line"><a name="l14130"></a><span class="lineno">14130</span>&#160;<span class="comment">    Fast algorithm is supported only when certain criteria are met:</span></div>
+<div class="line"><a name="l14131"></a><span class="lineno">14131</span>&#160;<span class="comment">    - VMA_DEBUG_MARGIN is 0.</span></div>
+<div class="line"><a name="l14132"></a><span class="lineno">14132</span>&#160;<span class="comment">    - All allocations in this block vector are moveable.</span></div>
+<div class="line"><a name="l14133"></a><span class="lineno">14133</span>&#160;<span class="comment">    - There is no possibility of image/buffer granularity conflict.</span></div>
+<div class="line"><a name="l14134"></a><span class="lineno">14134</span>&#160;<span class="comment">    - The defragmentation is not incremental</span></div>
+<div class="line"><a name="l14135"></a><span class="lineno">14135</span>&#160;<span class="comment">    */</span></div>
+<div class="line"><a name="l14136"></a><span class="lineno">14136</span>&#160;    <span class="keywordflow">if</span>(VMA_DEBUG_MARGIN == 0 &amp;&amp;</div>
+<div class="line"><a name="l14137"></a><span class="lineno">14137</span>&#160;        allAllocations &amp;&amp;</div>
+<div class="line"><a name="l14138"></a><span class="lineno">14138</span>&#160;        !m_pBlockVector-&gt;IsBufferImageGranularityConflictPossible() &amp;&amp;</div>
+<div class="line"><a name="l14139"></a><span class="lineno">14139</span>&#160;        !(flags &amp; <a class="code" href="vk__mem__alloc_8h.html#a6552a65b71d16f378c6994b3ceaef50ca31af49446af2459284a568ce2f3fdd33">VMA_DEFRAGMENTATION_FLAG_INCREMENTAL</a>))</div>
+<div class="line"><a name="l14140"></a><span class="lineno">14140</span>&#160;    {</div>
+<div class="line"><a name="l14141"></a><span class="lineno">14141</span>&#160;        m_pAlgorithm = vma_new(m_hAllocator, VmaDefragmentationAlgorithm_Fast)(</div>
+<div class="line"><a name="l14142"></a><span class="lineno">14142</span>&#160;            m_hAllocator, m_pBlockVector, m_CurrFrameIndex, overlappingMoveSupported);</div>
+<div class="line"><a name="l14143"></a><span class="lineno">14143</span>&#160;    }</div>
+<div class="line"><a name="l14144"></a><span class="lineno">14144</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l14145"></a><span class="lineno">14145</span>&#160;    {</div>
+<div class="line"><a name="l14146"></a><span class="lineno">14146</span>&#160;        m_pAlgorithm = vma_new(m_hAllocator, VmaDefragmentationAlgorithm_Generic)(</div>
+<div class="line"><a name="l14147"></a><span class="lineno">14147</span>&#160;            m_hAllocator, m_pBlockVector, m_CurrFrameIndex, overlappingMoveSupported);</div>
+<div class="line"><a name="l14148"></a><span class="lineno">14148</span>&#160;    }</div>
+<div class="line"><a name="l14149"></a><span class="lineno">14149</span>&#160; </div>
+<div class="line"><a name="l14150"></a><span class="lineno">14150</span>&#160;    <span class="keywordflow">if</span>(allAllocations)</div>
+<div class="line"><a name="l14151"></a><span class="lineno">14151</span>&#160;    {</div>
+<div class="line"><a name="l14152"></a><span class="lineno">14152</span>&#160;        m_pAlgorithm-&gt;AddAll();</div>
+<div class="line"><a name="l14153"></a><span class="lineno">14153</span>&#160;    }</div>
+<div class="line"><a name="l14154"></a><span class="lineno">14154</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l14155"></a><span class="lineno">14155</span>&#160;    {</div>
+<div class="line"><a name="l14156"></a><span class="lineno">14156</span>&#160;        <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = 0, count = m_Allocations.size(); i &lt; count; ++i)</div>
+<div class="line"><a name="l14157"></a><span class="lineno">14157</span>&#160;        {</div>
+<div class="line"><a name="l14158"></a><span class="lineno">14158</span>&#160;            m_pAlgorithm-&gt;AddAllocation(m_Allocations[i].hAlloc, m_Allocations[i].pChanged);</div>
+<div class="line"><a name="l14159"></a><span class="lineno">14159</span>&#160;        }</div>
+<div class="line"><a name="l14160"></a><span class="lineno">14160</span>&#160;    }</div>
+<div class="line"><a name="l14161"></a><span class="lineno">14161</span>&#160;}</div>
+<div class="line"><a name="l14162"></a><span class="lineno">14162</span>&#160; </div>
+<div class="line"><a name="l14164"></a><span class="lineno">14164</span>&#160;<span class="comment">// VmaDefragmentationContext</span></div>
+<div class="line"><a name="l14165"></a><span class="lineno">14165</span>&#160; </div>
+<div class="line"><a name="l14166"></a><span class="lineno">14166</span>&#160;VmaDefragmentationContext_T::VmaDefragmentationContext_T(</div>
+<div class="line"><a name="l14167"></a><span class="lineno">14167</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> hAllocator,</div>
+<div class="line"><a name="l14168"></a><span class="lineno">14168</span>&#160;    uint32_t currFrameIndex,</div>
+<div class="line"><a name="l14169"></a><span class="lineno">14169</span>&#160;    uint32_t flags,</div>
+<div class="line"><a name="l14170"></a><span class="lineno">14170</span>&#160;    <a class="code" href="struct_vma_defragmentation_stats.html">VmaDefragmentationStats</a>* pStats) :</div>
+<div class="line"><a name="l14171"></a><span class="lineno">14171</span>&#160;    m_hAllocator(hAllocator),</div>
+<div class="line"><a name="l14172"></a><span class="lineno">14172</span>&#160;    m_CurrFrameIndex(currFrameIndex),</div>
+<div class="line"><a name="l14173"></a><span class="lineno">14173</span>&#160;    m_Flags(flags),</div>
+<div class="line"><a name="l14174"></a><span class="lineno">14174</span>&#160;    m_pStats(pStats),</div>
+<div class="line"><a name="l14175"></a><span class="lineno">14175</span>&#160;    m_CustomPoolContexts(VmaStlAllocator&lt;VmaBlockVectorDefragmentationContext*&gt;(hAllocator-&gt;GetAllocationCallbacks()))</div>
+<div class="line"><a name="l14176"></a><span class="lineno">14176</span>&#160;{</div>
+<div class="line"><a name="l14177"></a><span class="lineno">14177</span>&#160;    memset(m_DefaultPoolContexts, 0, <span class="keyword">sizeof</span>(m_DefaultPoolContexts));</div>
+<div class="line"><a name="l14178"></a><span class="lineno">14178</span>&#160;}</div>
+<div class="line"><a name="l14179"></a><span class="lineno">14179</span>&#160; </div>
+<div class="line"><a name="l14180"></a><span class="lineno">14180</span>&#160;VmaDefragmentationContext_T::~VmaDefragmentationContext_T()</div>
+<div class="line"><a name="l14181"></a><span class="lineno">14181</span>&#160;{</div>
+<div class="line"><a name="l14182"></a><span class="lineno">14182</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = m_CustomPoolContexts.size(); i--; )</div>
+<div class="line"><a name="l14183"></a><span class="lineno">14183</span>&#160;    {</div>
+<div class="line"><a name="l14184"></a><span class="lineno">14184</span>&#160;        VmaBlockVectorDefragmentationContext* pBlockVectorCtx = m_CustomPoolContexts[i];</div>
+<div class="line"><a name="l14185"></a><span class="lineno">14185</span>&#160;        pBlockVectorCtx-&gt;GetBlockVector()-&gt;DefragmentationEnd(pBlockVectorCtx, m_Flags, m_pStats);</div>
+<div class="line"><a name="l14186"></a><span class="lineno">14186</span>&#160;        vma_delete(m_hAllocator, pBlockVectorCtx);</div>
+<div class="line"><a name="l14187"></a><span class="lineno">14187</span>&#160;    }</div>
+<div class="line"><a name="l14188"></a><span class="lineno">14188</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = m_hAllocator-&gt;m_MemProps.memoryTypeCount; i--; )</div>
+<div class="line"><a name="l14189"></a><span class="lineno">14189</span>&#160;    {</div>
+<div class="line"><a name="l14190"></a><span class="lineno">14190</span>&#160;        VmaBlockVectorDefragmentationContext* pBlockVectorCtx = m_DefaultPoolContexts[i];</div>
+<div class="line"><a name="l14191"></a><span class="lineno">14191</span>&#160;        <span class="keywordflow">if</span>(pBlockVectorCtx)</div>
+<div class="line"><a name="l14192"></a><span class="lineno">14192</span>&#160;        {</div>
+<div class="line"><a name="l14193"></a><span class="lineno">14193</span>&#160;            pBlockVectorCtx-&gt;GetBlockVector()-&gt;DefragmentationEnd(pBlockVectorCtx, m_Flags, m_pStats);</div>
+<div class="line"><a name="l14194"></a><span class="lineno">14194</span>&#160;            vma_delete(m_hAllocator, pBlockVectorCtx);</div>
+<div class="line"><a name="l14195"></a><span class="lineno">14195</span>&#160;        }</div>
+<div class="line"><a name="l14196"></a><span class="lineno">14196</span>&#160;    }</div>
+<div class="line"><a name="l14197"></a><span class="lineno">14197</span>&#160;}</div>
+<div class="line"><a name="l14198"></a><span class="lineno">14198</span>&#160; </div>
+<div class="line"><a name="l14199"></a><span class="lineno">14199</span>&#160;<span class="keywordtype">void</span> VmaDefragmentationContext_T::AddPools(uint32_t poolCount, <a class="code" href="struct_vma_pool.html">VmaPool</a>* pPools)</div>
+<div class="line"><a name="l14200"></a><span class="lineno">14200</span>&#160;{</div>
+<div class="line"><a name="l14201"></a><span class="lineno">14201</span>&#160;    <span class="keywordflow">for</span>(uint32_t poolIndex = 0; poolIndex &lt; poolCount; ++poolIndex)</div>
+<div class="line"><a name="l14202"></a><span class="lineno">14202</span>&#160;    {</div>
+<div class="line"><a name="l14203"></a><span class="lineno">14203</span>&#160;        <a class="code" href="struct_vma_pool.html">VmaPool</a> pool = pPools[poolIndex];</div>
+<div class="line"><a name="l14204"></a><span class="lineno">14204</span>&#160;        VMA_ASSERT(pool);</div>
+<div class="line"><a name="l14205"></a><span class="lineno">14205</span>&#160;        <span class="comment">// Pools with algorithm other than default are not defragmented.</span></div>
+<div class="line"><a name="l14206"></a><span class="lineno">14206</span>&#160;        <span class="keywordflow">if</span>(pool-&gt;m_BlockVector.GetAlgorithm() == 0)</div>
+<div class="line"><a name="l14207"></a><span class="lineno">14207</span>&#160;        {</div>
+<div class="line"><a name="l14208"></a><span class="lineno">14208</span>&#160;            VmaBlockVectorDefragmentationContext* pBlockVectorDefragCtx = VMA_NULL;</div>
+<div class="line"><a name="l14209"></a><span class="lineno">14209</span>&#160;            </div>
+<div class="line"><a name="l14210"></a><span class="lineno">14210</span>&#160;            <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = m_CustomPoolContexts.size(); i--; )</div>
+<div class="line"><a name="l14211"></a><span class="lineno">14211</span>&#160;            {</div>
+<div class="line"><a name="l14212"></a><span class="lineno">14212</span>&#160;                <span class="keywordflow">if</span>(m_CustomPoolContexts[i]-&gt;GetCustomPool() == pool)</div>
+<div class="line"><a name="l14213"></a><span class="lineno">14213</span>&#160;                {</div>
+<div class="line"><a name="l14214"></a><span class="lineno">14214</span>&#160;                    pBlockVectorDefragCtx = m_CustomPoolContexts[i];</div>
+<div class="line"><a name="l14215"></a><span class="lineno">14215</span>&#160;                    <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l14216"></a><span class="lineno">14216</span>&#160;                }</div>
+<div class="line"><a name="l14217"></a><span class="lineno">14217</span>&#160;            }</div>
+<div class="line"><a name="l14218"></a><span class="lineno">14218</span>&#160;            </div>
+<div class="line"><a name="l14219"></a><span class="lineno">14219</span>&#160;            <span class="keywordflow">if</span>(!pBlockVectorDefragCtx)</div>
+<div class="line"><a name="l14220"></a><span class="lineno">14220</span>&#160;            {</div>
+<div class="line"><a name="l14221"></a><span class="lineno">14221</span>&#160;                pBlockVectorDefragCtx = vma_new(m_hAllocator, VmaBlockVectorDefragmentationContext)(</div>
+<div class="line"><a name="l14222"></a><span class="lineno">14222</span>&#160;                    m_hAllocator,</div>
+<div class="line"><a name="l14223"></a><span class="lineno">14223</span>&#160;                    pool,</div>
+<div class="line"><a name="l14224"></a><span class="lineno">14224</span>&#160;                    &amp;pool-&gt;m_BlockVector,</div>
+<div class="line"><a name="l14225"></a><span class="lineno">14225</span>&#160;                    m_CurrFrameIndex);</div>
+<div class="line"><a name="l14226"></a><span class="lineno">14226</span>&#160;                m_CustomPoolContexts.push_back(pBlockVectorDefragCtx);</div>
+<div class="line"><a name="l14227"></a><span class="lineno">14227</span>&#160;            }</div>
+<div class="line"><a name="l14228"></a><span class="lineno">14228</span>&#160; </div>
+<div class="line"><a name="l14229"></a><span class="lineno">14229</span>&#160;            pBlockVectorDefragCtx-&gt;AddAll();</div>
+<div class="line"><a name="l14230"></a><span class="lineno">14230</span>&#160;        }</div>
+<div class="line"><a name="l14231"></a><span class="lineno">14231</span>&#160;    }</div>
+<div class="line"><a name="l14232"></a><span class="lineno">14232</span>&#160;}</div>
+<div class="line"><a name="l14233"></a><span class="lineno">14233</span>&#160; </div>
+<div class="line"><a name="l14234"></a><span class="lineno">14234</span>&#160;<span class="keywordtype">void</span> VmaDefragmentationContext_T::AddAllocations(</div>
+<div class="line"><a name="l14235"></a><span class="lineno">14235</span>&#160;    uint32_t allocationCount,</div>
+<div class="line"><a name="l14236"></a><span class="lineno">14236</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocations,</div>
+<div class="line"><a name="l14237"></a><span class="lineno">14237</span>&#160;    VkBool32* pAllocationsChanged)</div>
+<div class="line"><a name="l14238"></a><span class="lineno">14238</span>&#160;{</div>
+<div class="line"><a name="l14239"></a><span class="lineno">14239</span>&#160;    <span class="comment">// Dispatch pAllocations among defragmentators. Create them when necessary.</span></div>
+<div class="line"><a name="l14240"></a><span class="lineno">14240</span>&#160;    <span class="keywordflow">for</span>(uint32_t allocIndex = 0; allocIndex &lt; allocationCount; ++allocIndex)</div>
+<div class="line"><a name="l14241"></a><span class="lineno">14241</span>&#160;    {</div>
+<div class="line"><a name="l14242"></a><span class="lineno">14242</span>&#160;        <span class="keyword">const</span> <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAlloc = pAllocations[allocIndex];</div>
+<div class="line"><a name="l14243"></a><span class="lineno">14243</span>&#160;        VMA_ASSERT(hAlloc);</div>
+<div class="line"><a name="l14244"></a><span class="lineno">14244</span>&#160;        <span class="comment">// DedicatedAlloc cannot be defragmented.</span></div>
+<div class="line"><a name="l14245"></a><span class="lineno">14245</span>&#160;        <span class="keywordflow">if</span>((hAlloc-&gt;GetType() == VmaAllocation_T::ALLOCATION_TYPE_BLOCK) &amp;&amp;</div>
+<div class="line"><a name="l14246"></a><span class="lineno">14246</span>&#160;            <span class="comment">// Lost allocation cannot be defragmented.</span></div>
+<div class="line"><a name="l14247"></a><span class="lineno">14247</span>&#160;            (hAlloc-&gt;GetLastUseFrameIndex() != VMA_FRAME_INDEX_LOST))</div>
+<div class="line"><a name="l14248"></a><span class="lineno">14248</span>&#160;        {</div>
+<div class="line"><a name="l14249"></a><span class="lineno">14249</span>&#160;            VmaBlockVectorDefragmentationContext* pBlockVectorDefragCtx = VMA_NULL;</div>
+<div class="line"><a name="l14250"></a><span class="lineno">14250</span>&#160; </div>
+<div class="line"><a name="l14251"></a><span class="lineno">14251</span>&#160;            <span class="keyword">const</span> <a class="code" href="struct_vma_pool.html">VmaPool</a> hAllocPool = hAlloc-&gt;GetBlock()-&gt;GetParentPool();</div>
+<div class="line"><a name="l14252"></a><span class="lineno">14252</span>&#160;            <span class="comment">// This allocation belongs to custom pool.</span></div>
+<div class="line"><a name="l14253"></a><span class="lineno">14253</span>&#160;            <span class="keywordflow">if</span>(hAllocPool != VK_NULL_HANDLE)</div>
+<div class="line"><a name="l14254"></a><span class="lineno">14254</span>&#160;            {</div>
+<div class="line"><a name="l14255"></a><span class="lineno">14255</span>&#160;                <span class="comment">// Pools with algorithm other than default are not defragmented.</span></div>
+<div class="line"><a name="l14256"></a><span class="lineno">14256</span>&#160;                <span class="keywordflow">if</span>(hAllocPool-&gt;m_BlockVector.GetAlgorithm() == 0)</div>
+<div class="line"><a name="l14257"></a><span class="lineno">14257</span>&#160;                {</div>
+<div class="line"><a name="l14258"></a><span class="lineno">14258</span>&#160;                    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = m_CustomPoolContexts.size(); i--; )</div>
+<div class="line"><a name="l14259"></a><span class="lineno">14259</span>&#160;                    {</div>
+<div class="line"><a name="l14260"></a><span class="lineno">14260</span>&#160;                        <span class="keywordflow">if</span>(m_CustomPoolContexts[i]-&gt;GetCustomPool() == hAllocPool)</div>
+<div class="line"><a name="l14261"></a><span class="lineno">14261</span>&#160;                        {</div>
+<div class="line"><a name="l14262"></a><span class="lineno">14262</span>&#160;                            pBlockVectorDefragCtx = m_CustomPoolContexts[i];</div>
+<div class="line"><a name="l14263"></a><span class="lineno">14263</span>&#160;                            <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l14264"></a><span class="lineno">14264</span>&#160;                        }</div>
+<div class="line"><a name="l14265"></a><span class="lineno">14265</span>&#160;                    }</div>
+<div class="line"><a name="l14266"></a><span class="lineno">14266</span>&#160;                    <span class="keywordflow">if</span>(!pBlockVectorDefragCtx)</div>
+<div class="line"><a name="l14267"></a><span class="lineno">14267</span>&#160;                    {</div>
+<div class="line"><a name="l14268"></a><span class="lineno">14268</span>&#160;                        pBlockVectorDefragCtx = vma_new(m_hAllocator, VmaBlockVectorDefragmentationContext)(</div>
+<div class="line"><a name="l14269"></a><span class="lineno">14269</span>&#160;                            m_hAllocator,</div>
+<div class="line"><a name="l14270"></a><span class="lineno">14270</span>&#160;                            hAllocPool,</div>
+<div class="line"><a name="l14271"></a><span class="lineno">14271</span>&#160;                            &amp;hAllocPool-&gt;m_BlockVector,</div>
+<div class="line"><a name="l14272"></a><span class="lineno">14272</span>&#160;                            m_CurrFrameIndex);</div>
+<div class="line"><a name="l14273"></a><span class="lineno">14273</span>&#160;                        m_CustomPoolContexts.push_back(pBlockVectorDefragCtx);</div>
+<div class="line"><a name="l14274"></a><span class="lineno">14274</span>&#160;                    }</div>
+<div class="line"><a name="l14275"></a><span class="lineno">14275</span>&#160;                }</div>
+<div class="line"><a name="l14276"></a><span class="lineno">14276</span>&#160;            }</div>
+<div class="line"><a name="l14277"></a><span class="lineno">14277</span>&#160;            <span class="comment">// This allocation belongs to default pool.</span></div>
+<div class="line"><a name="l14278"></a><span class="lineno">14278</span>&#160;            <span class="keywordflow">else</span></div>
+<div class="line"><a name="l14279"></a><span class="lineno">14279</span>&#160;            {</div>
+<div class="line"><a name="l14280"></a><span class="lineno">14280</span>&#160;                <span class="keyword">const</span> uint32_t memTypeIndex = hAlloc-&gt;GetMemoryTypeIndex();</div>
+<div class="line"><a name="l14281"></a><span class="lineno">14281</span>&#160;                pBlockVectorDefragCtx = m_DefaultPoolContexts[memTypeIndex];</div>
+<div class="line"><a name="l14282"></a><span class="lineno">14282</span>&#160;                <span class="keywordflow">if</span>(!pBlockVectorDefragCtx)</div>
+<div class="line"><a name="l14283"></a><span class="lineno">14283</span>&#160;                {</div>
+<div class="line"><a name="l14284"></a><span class="lineno">14284</span>&#160;                    pBlockVectorDefragCtx = vma_new(m_hAllocator, VmaBlockVectorDefragmentationContext)(</div>
+<div class="line"><a name="l14285"></a><span class="lineno">14285</span>&#160;                        m_hAllocator,</div>
+<div class="line"><a name="l14286"></a><span class="lineno">14286</span>&#160;                        VMA_NULL, <span class="comment">// hCustomPool</span></div>
+<div class="line"><a name="l14287"></a><span class="lineno">14287</span>&#160;                        m_hAllocator-&gt;m_pBlockVectors[memTypeIndex],</div>
+<div class="line"><a name="l14288"></a><span class="lineno">14288</span>&#160;                        m_CurrFrameIndex);</div>
+<div class="line"><a name="l14289"></a><span class="lineno">14289</span>&#160;                    m_DefaultPoolContexts[memTypeIndex] = pBlockVectorDefragCtx;</div>
+<div class="line"><a name="l14290"></a><span class="lineno">14290</span>&#160;                }</div>
+<div class="line"><a name="l14291"></a><span class="lineno">14291</span>&#160;            }</div>
+<div class="line"><a name="l14292"></a><span class="lineno">14292</span>&#160; </div>
+<div class="line"><a name="l14293"></a><span class="lineno">14293</span>&#160;            <span class="keywordflow">if</span>(pBlockVectorDefragCtx)</div>
+<div class="line"><a name="l14294"></a><span class="lineno">14294</span>&#160;            {</div>
+<div class="line"><a name="l14295"></a><span class="lineno">14295</span>&#160;                VkBool32* <span class="keyword">const</span> pChanged = (pAllocationsChanged != VMA_NULL) ?</div>
+<div class="line"><a name="l14296"></a><span class="lineno">14296</span>&#160;                    &amp;pAllocationsChanged[allocIndex] : VMA_NULL;</div>
+<div class="line"><a name="l14297"></a><span class="lineno">14297</span>&#160;                pBlockVectorDefragCtx-&gt;AddAllocation(hAlloc, pChanged);</div>
+<div class="line"><a name="l14298"></a><span class="lineno">14298</span>&#160;            }</div>
+<div class="line"><a name="l14299"></a><span class="lineno">14299</span>&#160;        }</div>
+<div class="line"><a name="l14300"></a><span class="lineno">14300</span>&#160;    }</div>
+<div class="line"><a name="l14301"></a><span class="lineno">14301</span>&#160;}</div>
+<div class="line"><a name="l14302"></a><span class="lineno">14302</span>&#160; </div>
+<div class="line"><a name="l14303"></a><span class="lineno">14303</span>&#160;VkResult VmaDefragmentationContext_T::Defragment(</div>
+<div class="line"><a name="l14304"></a><span class="lineno">14304</span>&#160;    VkDeviceSize maxCpuBytesToMove, uint32_t maxCpuAllocationsToMove,</div>
+<div class="line"><a name="l14305"></a><span class="lineno">14305</span>&#160;    VkDeviceSize maxGpuBytesToMove, uint32_t maxGpuAllocationsToMove,</div>
+<div class="line"><a name="l14306"></a><span class="lineno">14306</span>&#160;    VkCommandBuffer commandBuffer, <a class="code" href="struct_vma_defragmentation_stats.html">VmaDefragmentationStats</a>* pStats, <a class="code" href="vk__mem__alloc_8h.html#a88a77cef37e5d3c4fc9eb328885d048d">VmaDefragmentationFlags</a> flags)</div>
+<div class="line"><a name="l14307"></a><span class="lineno">14307</span>&#160;{</div>
+<div class="line"><a name="l14308"></a><span class="lineno">14308</span>&#160;    <span class="keywordflow">if</span>(pStats)</div>
+<div class="line"><a name="l14309"></a><span class="lineno">14309</span>&#160;    {</div>
+<div class="line"><a name="l14310"></a><span class="lineno">14310</span>&#160;        memset(pStats, 0, <span class="keyword">sizeof</span>(<a class="code" href="struct_vma_defragmentation_stats.html">VmaDefragmentationStats</a>));</div>
+<div class="line"><a name="l14311"></a><span class="lineno">14311</span>&#160;    }</div>
+<div class="line"><a name="l14312"></a><span class="lineno">14312</span>&#160; </div>
+<div class="line"><a name="l14313"></a><span class="lineno">14313</span>&#160;    <span class="keywordflow">if</span>(flags &amp; <a class="code" href="vk__mem__alloc_8h.html#a6552a65b71d16f378c6994b3ceaef50ca31af49446af2459284a568ce2f3fdd33">VMA_DEFRAGMENTATION_FLAG_INCREMENTAL</a>)</div>
+<div class="line"><a name="l14314"></a><span class="lineno">14314</span>&#160;    {</div>
+<div class="line"><a name="l14315"></a><span class="lineno">14315</span>&#160;        <span class="comment">// For incremental defragmetnations, we just earmark how much we can move</span></div>
+<div class="line"><a name="l14316"></a><span class="lineno">14316</span>&#160;        <span class="comment">// The real meat is in the defragmentation steps</span></div>
+<div class="line"><a name="l14317"></a><span class="lineno">14317</span>&#160;        m_MaxCpuBytesToMove = maxCpuBytesToMove;</div>
+<div class="line"><a name="l14318"></a><span class="lineno">14318</span>&#160;        m_MaxCpuAllocationsToMove = maxCpuAllocationsToMove;</div>
+<div class="line"><a name="l14319"></a><span class="lineno">14319</span>&#160; </div>
+<div class="line"><a name="l14320"></a><span class="lineno">14320</span>&#160;        m_MaxGpuBytesToMove = maxGpuBytesToMove;</div>
+<div class="line"><a name="l14321"></a><span class="lineno">14321</span>&#160;        m_MaxGpuAllocationsToMove = maxGpuAllocationsToMove;</div>
+<div class="line"><a name="l14322"></a><span class="lineno">14322</span>&#160; </div>
+<div class="line"><a name="l14323"></a><span class="lineno">14323</span>&#160;        <span class="keywordflow">if</span>(m_MaxCpuBytesToMove == 0 &amp;&amp; m_MaxCpuAllocationsToMove == 0 &amp;&amp;</div>
+<div class="line"><a name="l14324"></a><span class="lineno">14324</span>&#160;            m_MaxGpuBytesToMove == 0 &amp;&amp; m_MaxGpuAllocationsToMove == 0)</div>
+<div class="line"><a name="l14325"></a><span class="lineno">14325</span>&#160;            <span class="keywordflow">return</span> VK_SUCCESS;</div>
+<div class="line"><a name="l14326"></a><span class="lineno">14326</span>&#160; </div>
+<div class="line"><a name="l14327"></a><span class="lineno">14327</span>&#160;        <span class="keywordflow">return</span> VK_NOT_READY;</div>
+<div class="line"><a name="l14328"></a><span class="lineno">14328</span>&#160;    }</div>
+<div class="line"><a name="l14329"></a><span class="lineno">14329</span>&#160; </div>
+<div class="line"><a name="l14330"></a><span class="lineno">14330</span>&#160;    <span class="keywordflow">if</span>(commandBuffer == VK_NULL_HANDLE)</div>
+<div class="line"><a name="l14331"></a><span class="lineno">14331</span>&#160;    {</div>
+<div class="line"><a name="l14332"></a><span class="lineno">14332</span>&#160;        maxGpuBytesToMove = 0;</div>
+<div class="line"><a name="l14333"></a><span class="lineno">14333</span>&#160;        maxGpuAllocationsToMove = 0;</div>
+<div class="line"><a name="l14334"></a><span class="lineno">14334</span>&#160;    }</div>
+<div class="line"><a name="l14335"></a><span class="lineno">14335</span>&#160; </div>
+<div class="line"><a name="l14336"></a><span class="lineno">14336</span>&#160;    VkResult res = VK_SUCCESS;</div>
+<div class="line"><a name="l14337"></a><span class="lineno">14337</span>&#160; </div>
+<div class="line"><a name="l14338"></a><span class="lineno">14338</span>&#160;    <span class="comment">// Process default pools.</span></div>
+<div class="line"><a name="l14339"></a><span class="lineno">14339</span>&#160;    <span class="keywordflow">for</span>(uint32_t memTypeIndex = 0;</div>
+<div class="line"><a name="l14340"></a><span class="lineno">14340</span>&#160;        memTypeIndex &lt; m_hAllocator-&gt;GetMemoryTypeCount() &amp;&amp; res &gt;= VK_SUCCESS;</div>
+<div class="line"><a name="l14341"></a><span class="lineno">14341</span>&#160;        ++memTypeIndex)</div>
+<div class="line"><a name="l14342"></a><span class="lineno">14342</span>&#160;    {</div>
+<div class="line"><a name="l14343"></a><span class="lineno">14343</span>&#160;        VmaBlockVectorDefragmentationContext* pBlockVectorCtx = m_DefaultPoolContexts[memTypeIndex];</div>
+<div class="line"><a name="l14344"></a><span class="lineno">14344</span>&#160;        <span class="keywordflow">if</span>(pBlockVectorCtx)</div>
+<div class="line"><a name="l14345"></a><span class="lineno">14345</span>&#160;        {</div>
+<div class="line"><a name="l14346"></a><span class="lineno">14346</span>&#160;            VMA_ASSERT(pBlockVectorCtx-&gt;GetBlockVector());</div>
+<div class="line"><a name="l14347"></a><span class="lineno">14347</span>&#160;            pBlockVectorCtx-&gt;GetBlockVector()-&gt;Defragment(</div>
+<div class="line"><a name="l14348"></a><span class="lineno">14348</span>&#160;                pBlockVectorCtx,</div>
+<div class="line"><a name="l14349"></a><span class="lineno">14349</span>&#160;                pStats, flags,</div>
+<div class="line"><a name="l14350"></a><span class="lineno">14350</span>&#160;                maxCpuBytesToMove, maxCpuAllocationsToMove,</div>
+<div class="line"><a name="l14351"></a><span class="lineno">14351</span>&#160;                maxGpuBytesToMove, maxGpuAllocationsToMove,</div>
+<div class="line"><a name="l14352"></a><span class="lineno">14352</span>&#160;                commandBuffer);</div>
+<div class="line"><a name="l14353"></a><span class="lineno">14353</span>&#160;            <span class="keywordflow">if</span>(pBlockVectorCtx-&gt;res != VK_SUCCESS)</div>
+<div class="line"><a name="l14354"></a><span class="lineno">14354</span>&#160;            {</div>
+<div class="line"><a name="l14355"></a><span class="lineno">14355</span>&#160;                res = pBlockVectorCtx-&gt;res;</div>
+<div class="line"><a name="l14356"></a><span class="lineno">14356</span>&#160;            }</div>
+<div class="line"><a name="l14357"></a><span class="lineno">14357</span>&#160;        }</div>
+<div class="line"><a name="l14358"></a><span class="lineno">14358</span>&#160;    }</div>
+<div class="line"><a name="l14359"></a><span class="lineno">14359</span>&#160; </div>
+<div class="line"><a name="l14360"></a><span class="lineno">14360</span>&#160;    <span class="comment">// Process custom pools.</span></div>
+<div class="line"><a name="l14361"></a><span class="lineno">14361</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> customCtxIndex = 0, customCtxCount = m_CustomPoolContexts.size();</div>
+<div class="line"><a name="l14362"></a><span class="lineno">14362</span>&#160;        customCtxIndex &lt; customCtxCount &amp;&amp; res &gt;= VK_SUCCESS;</div>
+<div class="line"><a name="l14363"></a><span class="lineno">14363</span>&#160;        ++customCtxIndex)</div>
+<div class="line"><a name="l14364"></a><span class="lineno">14364</span>&#160;    {</div>
+<div class="line"><a name="l14365"></a><span class="lineno">14365</span>&#160;        VmaBlockVectorDefragmentationContext* pBlockVectorCtx = m_CustomPoolContexts[customCtxIndex];</div>
+<div class="line"><a name="l14366"></a><span class="lineno">14366</span>&#160;        VMA_ASSERT(pBlockVectorCtx &amp;&amp; pBlockVectorCtx-&gt;GetBlockVector());</div>
+<div class="line"><a name="l14367"></a><span class="lineno">14367</span>&#160;        pBlockVectorCtx-&gt;GetBlockVector()-&gt;Defragment(</div>
+<div class="line"><a name="l14368"></a><span class="lineno">14368</span>&#160;            pBlockVectorCtx,</div>
+<div class="line"><a name="l14369"></a><span class="lineno">14369</span>&#160;            pStats, flags,</div>
+<div class="line"><a name="l14370"></a><span class="lineno">14370</span>&#160;            maxCpuBytesToMove, maxCpuAllocationsToMove,</div>
+<div class="line"><a name="l14371"></a><span class="lineno">14371</span>&#160;            maxGpuBytesToMove, maxGpuAllocationsToMove,</div>
+<div class="line"><a name="l14372"></a><span class="lineno">14372</span>&#160;            commandBuffer);</div>
+<div class="line"><a name="l14373"></a><span class="lineno">14373</span>&#160;        <span class="keywordflow">if</span>(pBlockVectorCtx-&gt;res != VK_SUCCESS)</div>
+<div class="line"><a name="l14374"></a><span class="lineno">14374</span>&#160;        {</div>
+<div class="line"><a name="l14375"></a><span class="lineno">14375</span>&#160;            res = pBlockVectorCtx-&gt;res;</div>
+<div class="line"><a name="l14376"></a><span class="lineno">14376</span>&#160;        }</div>
+<div class="line"><a name="l14377"></a><span class="lineno">14377</span>&#160;    }</div>
+<div class="line"><a name="l14378"></a><span class="lineno">14378</span>&#160; </div>
+<div class="line"><a name="l14379"></a><span class="lineno">14379</span>&#160;    <span class="keywordflow">return</span> res;</div>
+<div class="line"><a name="l14380"></a><span class="lineno">14380</span>&#160;}</div>
+<div class="line"><a name="l14381"></a><span class="lineno">14381</span>&#160; </div>
+<div class="line"><a name="l14382"></a><span class="lineno">14382</span>&#160;VkResult VmaDefragmentationContext_T::DefragmentPassBegin(<a class="code" href="struct_vma_defragmentation_pass_info.html">VmaDefragmentationPassInfo</a>* pInfo)</div>
+<div class="line"><a name="l14383"></a><span class="lineno">14383</span>&#160;{</div>
+<div class="line"><a name="l14384"></a><span class="lineno">14384</span>&#160;    <a class="code" href="struct_vma_defragmentation_pass_move_info.html">VmaDefragmentationPassMoveInfo</a>* pCurrentMove = pInfo-&gt;<a class="code" href="struct_vma_defragmentation_pass_info.html#acbd42d4a3357999da130a95cd99a3792">pMoves</a>;</div>
+<div class="line"><a name="l14385"></a><span class="lineno">14385</span>&#160;    uint32_t movesLeft = pInfo-&gt;<a class="code" href="struct_vma_defragmentation_pass_info.html#ac1086e657ba995f8d1f4e49b83dcfb6c">moveCount</a>;</div>
+<div class="line"><a name="l14386"></a><span class="lineno">14386</span>&#160; </div>
+<div class="line"><a name="l14387"></a><span class="lineno">14387</span>&#160;    <span class="comment">// Process default pools.</span></div>
+<div class="line"><a name="l14388"></a><span class="lineno">14388</span>&#160;    <span class="keywordflow">for</span>(uint32_t memTypeIndex = 0;</div>
+<div class="line"><a name="l14389"></a><span class="lineno">14389</span>&#160;        memTypeIndex &lt; m_hAllocator-&gt;GetMemoryTypeCount();</div>
+<div class="line"><a name="l14390"></a><span class="lineno">14390</span>&#160;        ++memTypeIndex)</div>
+<div class="line"><a name="l14391"></a><span class="lineno">14391</span>&#160;    {</div>
+<div class="line"><a name="l14392"></a><span class="lineno">14392</span>&#160;        VmaBlockVectorDefragmentationContext *pBlockVectorCtx = m_DefaultPoolContexts[memTypeIndex];</div>
+<div class="line"><a name="l14393"></a><span class="lineno">14393</span>&#160;        <span class="keywordflow">if</span>(pBlockVectorCtx)</div>
+<div class="line"><a name="l14394"></a><span class="lineno">14394</span>&#160;        {</div>
+<div class="line"><a name="l14395"></a><span class="lineno">14395</span>&#160;            VMA_ASSERT(pBlockVectorCtx-&gt;GetBlockVector());</div>
+<div class="line"><a name="l14396"></a><span class="lineno">14396</span>&#160; </div>
+<div class="line"><a name="l14397"></a><span class="lineno">14397</span>&#160;            <span class="keywordflow">if</span>(!pBlockVectorCtx-&gt;hasDefragmentationPlan)</div>
+<div class="line"><a name="l14398"></a><span class="lineno">14398</span>&#160;            {</div>
+<div class="line"><a name="l14399"></a><span class="lineno">14399</span>&#160;                pBlockVectorCtx-&gt;GetBlockVector()-&gt;Defragment(</div>
+<div class="line"><a name="l14400"></a><span class="lineno">14400</span>&#160;                    pBlockVectorCtx,</div>
+<div class="line"><a name="l14401"></a><span class="lineno">14401</span>&#160;                    m_pStats, m_Flags,</div>
+<div class="line"><a name="l14402"></a><span class="lineno">14402</span>&#160;                    m_MaxCpuBytesToMove, m_MaxCpuAllocationsToMove,</div>
+<div class="line"><a name="l14403"></a><span class="lineno">14403</span>&#160;                    m_MaxGpuBytesToMove, m_MaxGpuAllocationsToMove,</div>
+<div class="line"><a name="l14404"></a><span class="lineno">14404</span>&#160;                    VK_NULL_HANDLE);</div>
+<div class="line"><a name="l14405"></a><span class="lineno">14405</span>&#160; </div>
+<div class="line"><a name="l14406"></a><span class="lineno">14406</span>&#160;                <span class="keywordflow">if</span>(pBlockVectorCtx-&gt;res &lt; VK_SUCCESS)</div>
+<div class="line"><a name="l14407"></a><span class="lineno">14407</span>&#160;                    <span class="keywordflow">continue</span>;</div>
+<div class="line"><a name="l14408"></a><span class="lineno">14408</span>&#160; </div>
+<div class="line"><a name="l14409"></a><span class="lineno">14409</span>&#160;                pBlockVectorCtx-&gt;hasDefragmentationPlan = <span class="keyword">true</span>;</div>
+<div class="line"><a name="l14410"></a><span class="lineno">14410</span>&#160;            }</div>
+<div class="line"><a name="l14411"></a><span class="lineno">14411</span>&#160; </div>
+<div class="line"><a name="l14412"></a><span class="lineno">14412</span>&#160;            <span class="keyword">const</span> uint32_t processed = pBlockVectorCtx-&gt;GetBlockVector()-&gt;ProcessDefragmentations(</div>
+<div class="line"><a name="l14413"></a><span class="lineno">14413</span>&#160;                pBlockVectorCtx,</div>
+<div class="line"><a name="l14414"></a><span class="lineno">14414</span>&#160;                pCurrentMove, movesLeft);</div>
+<div class="line"><a name="l14415"></a><span class="lineno">14415</span>&#160; </div>
+<div class="line"><a name="l14416"></a><span class="lineno">14416</span>&#160;            movesLeft -= processed;</div>
+<div class="line"><a name="l14417"></a><span class="lineno">14417</span>&#160;            pCurrentMove += processed;</div>
+<div class="line"><a name="l14418"></a><span class="lineno">14418</span>&#160;        }</div>
+<div class="line"><a name="l14419"></a><span class="lineno">14419</span>&#160;    }</div>
+<div class="line"><a name="l14420"></a><span class="lineno">14420</span>&#160; </div>
+<div class="line"><a name="l14421"></a><span class="lineno">14421</span>&#160;    <span class="comment">// Process custom pools.</span></div>
+<div class="line"><a name="l14422"></a><span class="lineno">14422</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> customCtxIndex = 0, customCtxCount = m_CustomPoolContexts.size();</div>
+<div class="line"><a name="l14423"></a><span class="lineno">14423</span>&#160;        customCtxIndex &lt; customCtxCount;</div>
+<div class="line"><a name="l14424"></a><span class="lineno">14424</span>&#160;        ++customCtxIndex)</div>
+<div class="line"><a name="l14425"></a><span class="lineno">14425</span>&#160;    {</div>
+<div class="line"><a name="l14426"></a><span class="lineno">14426</span>&#160;        VmaBlockVectorDefragmentationContext *pBlockVectorCtx = m_CustomPoolContexts[customCtxIndex];</div>
+<div class="line"><a name="l14427"></a><span class="lineno">14427</span>&#160;        VMA_ASSERT(pBlockVectorCtx &amp;&amp; pBlockVectorCtx-&gt;GetBlockVector());</div>
+<div class="line"><a name="l14428"></a><span class="lineno">14428</span>&#160; </div>
+<div class="line"><a name="l14429"></a><span class="lineno">14429</span>&#160;        <span class="keywordflow">if</span>(!pBlockVectorCtx-&gt;hasDefragmentationPlan)</div>
+<div class="line"><a name="l14430"></a><span class="lineno">14430</span>&#160;        {</div>
+<div class="line"><a name="l14431"></a><span class="lineno">14431</span>&#160;            pBlockVectorCtx-&gt;GetBlockVector()-&gt;Defragment(</div>
+<div class="line"><a name="l14432"></a><span class="lineno">14432</span>&#160;                pBlockVectorCtx,</div>
+<div class="line"><a name="l14433"></a><span class="lineno">14433</span>&#160;                m_pStats, m_Flags,</div>
+<div class="line"><a name="l14434"></a><span class="lineno">14434</span>&#160;                m_MaxCpuBytesToMove, m_MaxCpuAllocationsToMove,</div>
+<div class="line"><a name="l14435"></a><span class="lineno">14435</span>&#160;                m_MaxGpuBytesToMove, m_MaxGpuAllocationsToMove,</div>
+<div class="line"><a name="l14436"></a><span class="lineno">14436</span>&#160;                VK_NULL_HANDLE);</div>
+<div class="line"><a name="l14437"></a><span class="lineno">14437</span>&#160; </div>
+<div class="line"><a name="l14438"></a><span class="lineno">14438</span>&#160;            <span class="keywordflow">if</span>(pBlockVectorCtx-&gt;res &lt; VK_SUCCESS)</div>
+<div class="line"><a name="l14439"></a><span class="lineno">14439</span>&#160;                <span class="keywordflow">continue</span>;</div>
+<div class="line"><a name="l14440"></a><span class="lineno">14440</span>&#160; </div>
+<div class="line"><a name="l14441"></a><span class="lineno">14441</span>&#160;            pBlockVectorCtx-&gt;hasDefragmentationPlan = <span class="keyword">true</span>;</div>
+<div class="line"><a name="l14442"></a><span class="lineno">14442</span>&#160;        }</div>
+<div class="line"><a name="l14443"></a><span class="lineno">14443</span>&#160; </div>
+<div class="line"><a name="l14444"></a><span class="lineno">14444</span>&#160;        <span class="keyword">const</span> uint32_t processed = pBlockVectorCtx-&gt;GetBlockVector()-&gt;ProcessDefragmentations(</div>
+<div class="line"><a name="l14445"></a><span class="lineno">14445</span>&#160;            pBlockVectorCtx,</div>
+<div class="line"><a name="l14446"></a><span class="lineno">14446</span>&#160;            pCurrentMove, movesLeft);</div>
+<div class="line"><a name="l14447"></a><span class="lineno">14447</span>&#160; </div>
+<div class="line"><a name="l14448"></a><span class="lineno">14448</span>&#160;        movesLeft -= processed;</div>
+<div class="line"><a name="l14449"></a><span class="lineno">14449</span>&#160;        pCurrentMove += processed;</div>
+<div class="line"><a name="l14450"></a><span class="lineno">14450</span>&#160;    }</div>
+<div class="line"><a name="l14451"></a><span class="lineno">14451</span>&#160; </div>
+<div class="line"><a name="l14452"></a><span class="lineno">14452</span>&#160;    pInfo-&gt;<a class="code" href="struct_vma_defragmentation_pass_info.html#ac1086e657ba995f8d1f4e49b83dcfb6c">moveCount</a> = pInfo-&gt;<a class="code" href="struct_vma_defragmentation_pass_info.html#ac1086e657ba995f8d1f4e49b83dcfb6c">moveCount</a> - movesLeft;</div>
+<div class="line"><a name="l14453"></a><span class="lineno">14453</span>&#160; </div>
+<div class="line"><a name="l14454"></a><span class="lineno">14454</span>&#160;    <span class="keywordflow">return</span> VK_SUCCESS;</div>
+<div class="line"><a name="l14455"></a><span class="lineno">14455</span>&#160;}</div>
+<div class="line"><a name="l14456"></a><span class="lineno">14456</span>&#160;VkResult VmaDefragmentationContext_T::DefragmentPassEnd()</div>
+<div class="line"><a name="l14457"></a><span class="lineno">14457</span>&#160;{</div>
+<div class="line"><a name="l14458"></a><span class="lineno">14458</span>&#160;    VkResult res = VK_SUCCESS;</div>
+<div class="line"><a name="l14459"></a><span class="lineno">14459</span>&#160; </div>
+<div class="line"><a name="l14460"></a><span class="lineno">14460</span>&#160;    <span class="comment">// Process default pools.</span></div>
+<div class="line"><a name="l14461"></a><span class="lineno">14461</span>&#160;    <span class="keywordflow">for</span>(uint32_t memTypeIndex = 0;</div>
+<div class="line"><a name="l14462"></a><span class="lineno">14462</span>&#160;        memTypeIndex &lt; m_hAllocator-&gt;GetMemoryTypeCount();</div>
+<div class="line"><a name="l14463"></a><span class="lineno">14463</span>&#160;        ++memTypeIndex)</div>
+<div class="line"><a name="l14464"></a><span class="lineno">14464</span>&#160;    {</div>
+<div class="line"><a name="l14465"></a><span class="lineno">14465</span>&#160;        VmaBlockVectorDefragmentationContext *pBlockVectorCtx = m_DefaultPoolContexts[memTypeIndex];</div>
+<div class="line"><a name="l14466"></a><span class="lineno">14466</span>&#160;        <span class="keywordflow">if</span>(pBlockVectorCtx)</div>
+<div class="line"><a name="l14467"></a><span class="lineno">14467</span>&#160;        {</div>
+<div class="line"><a name="l14468"></a><span class="lineno">14468</span>&#160;            VMA_ASSERT(pBlockVectorCtx-&gt;GetBlockVector());</div>
+<div class="line"><a name="l14469"></a><span class="lineno">14469</span>&#160; </div>
+<div class="line"><a name="l14470"></a><span class="lineno">14470</span>&#160;            <span class="keywordflow">if</span>(!pBlockVectorCtx-&gt;hasDefragmentationPlan)</div>
+<div class="line"><a name="l14471"></a><span class="lineno">14471</span>&#160;            {</div>
+<div class="line"><a name="l14472"></a><span class="lineno">14472</span>&#160;                res = VK_NOT_READY;</div>
+<div class="line"><a name="l14473"></a><span class="lineno">14473</span>&#160;                <span class="keywordflow">continue</span>;</div>
+<div class="line"><a name="l14474"></a><span class="lineno">14474</span>&#160;            }</div>
+<div class="line"><a name="l14475"></a><span class="lineno">14475</span>&#160; </div>
+<div class="line"><a name="l14476"></a><span class="lineno">14476</span>&#160;            pBlockVectorCtx-&gt;GetBlockVector()-&gt;CommitDefragmentations(</div>
+<div class="line"><a name="l14477"></a><span class="lineno">14477</span>&#160;                pBlockVectorCtx, m_pStats);</div>
+<div class="line"><a name="l14478"></a><span class="lineno">14478</span>&#160; </div>
+<div class="line"><a name="l14479"></a><span class="lineno">14479</span>&#160;            <span class="keywordflow">if</span>(pBlockVectorCtx-&gt;defragmentationMoves.size() != pBlockVectorCtx-&gt;defragmentationMovesCommitted)</div>
+<div class="line"><a name="l14480"></a><span class="lineno">14480</span>&#160;                res = VK_NOT_READY;</div>
+<div class="line"><a name="l14481"></a><span class="lineno">14481</span>&#160;        }</div>
+<div class="line"><a name="l14482"></a><span class="lineno">14482</span>&#160;    }</div>
+<div class="line"><a name="l14483"></a><span class="lineno">14483</span>&#160; </div>
+<div class="line"><a name="l14484"></a><span class="lineno">14484</span>&#160;    <span class="comment">// Process custom pools.</span></div>
+<div class="line"><a name="l14485"></a><span class="lineno">14485</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> customCtxIndex = 0, customCtxCount = m_CustomPoolContexts.size();</div>
+<div class="line"><a name="l14486"></a><span class="lineno">14486</span>&#160;        customCtxIndex &lt; customCtxCount;</div>
+<div class="line"><a name="l14487"></a><span class="lineno">14487</span>&#160;        ++customCtxIndex)</div>
+<div class="line"><a name="l14488"></a><span class="lineno">14488</span>&#160;    {</div>
+<div class="line"><a name="l14489"></a><span class="lineno">14489</span>&#160;        VmaBlockVectorDefragmentationContext *pBlockVectorCtx = m_CustomPoolContexts[customCtxIndex];</div>
+<div class="line"><a name="l14490"></a><span class="lineno">14490</span>&#160;        VMA_ASSERT(pBlockVectorCtx &amp;&amp; pBlockVectorCtx-&gt;GetBlockVector());</div>
+<div class="line"><a name="l14491"></a><span class="lineno">14491</span>&#160; </div>
+<div class="line"><a name="l14492"></a><span class="lineno">14492</span>&#160;        <span class="keywordflow">if</span>(!pBlockVectorCtx-&gt;hasDefragmentationPlan)</div>
+<div class="line"><a name="l14493"></a><span class="lineno">14493</span>&#160;        {</div>
+<div class="line"><a name="l14494"></a><span class="lineno">14494</span>&#160;            res = VK_NOT_READY;</div>
+<div class="line"><a name="l14495"></a><span class="lineno">14495</span>&#160;            <span class="keywordflow">continue</span>;</div>
+<div class="line"><a name="l14496"></a><span class="lineno">14496</span>&#160;        }</div>
+<div class="line"><a name="l14497"></a><span class="lineno">14497</span>&#160; </div>
+<div class="line"><a name="l14498"></a><span class="lineno">14498</span>&#160;        pBlockVectorCtx-&gt;GetBlockVector()-&gt;CommitDefragmentations(</div>
+<div class="line"><a name="l14499"></a><span class="lineno">14499</span>&#160;            pBlockVectorCtx, m_pStats);</div>
+<div class="line"><a name="l14500"></a><span class="lineno">14500</span>&#160; </div>
+<div class="line"><a name="l14501"></a><span class="lineno">14501</span>&#160;        <span class="keywordflow">if</span>(pBlockVectorCtx-&gt;defragmentationMoves.size() != pBlockVectorCtx-&gt;defragmentationMovesCommitted)</div>
+<div class="line"><a name="l14502"></a><span class="lineno">14502</span>&#160;            res = VK_NOT_READY;</div>
+<div class="line"><a name="l14503"></a><span class="lineno">14503</span>&#160;    }</div>
+<div class="line"><a name="l14504"></a><span class="lineno">14504</span>&#160; </div>
+<div class="line"><a name="l14505"></a><span class="lineno">14505</span>&#160;    <span class="keywordflow">return</span> res;</div>
+<div class="line"><a name="l14506"></a><span class="lineno">14506</span>&#160;}</div>
+<div class="line"><a name="l14507"></a><span class="lineno">14507</span>&#160; </div>
+<div class="line"><a name="l14509"></a><span class="lineno">14509</span>&#160;<span class="comment">// VmaRecorder</span></div>
+<div class="line"><a name="l14510"></a><span class="lineno">14510</span>&#160; </div>
+<div class="line"><a name="l14511"></a><span class="lineno">14511</span>&#160;<span class="preprocessor">#if VMA_RECORDING_ENABLED</span></div>
+<div class="line"><a name="l14512"></a><span class="lineno">14512</span>&#160; </div>
+<div class="line"><a name="l14513"></a><span class="lineno">14513</span>&#160;VmaRecorder::VmaRecorder() :</div>
+<div class="line"><a name="l14514"></a><span class="lineno">14514</span>&#160;    m_UseMutex(true),</div>
+<div class="line"><a name="l14515"></a><span class="lineno">14515</span>&#160;    m_Flags(0),</div>
+<div class="line"><a name="l14516"></a><span class="lineno">14516</span>&#160;    m_File(VMA_NULL),</div>
+<div class="line"><a name="l14517"></a><span class="lineno">14517</span>&#160;    m_Freq(INT64_MAX),</div>
+<div class="line"><a name="l14518"></a><span class="lineno">14518</span>&#160;    m_StartCounter(INT64_MAX)</div>
+<div class="line"><a name="l14519"></a><span class="lineno">14519</span>&#160;{</div>
+<div class="line"><a name="l14520"></a><span class="lineno">14520</span>&#160;}</div>
+<div class="line"><a name="l14521"></a><span class="lineno">14521</span>&#160; </div>
+<div class="line"><a name="l14522"></a><span class="lineno">14522</span>&#160;VkResult VmaRecorder::Init(<span class="keyword">const</span> <a class="code" href="struct_vma_record_settings.html">VmaRecordSettings</a>&amp; settings, <span class="keywordtype">bool</span> useMutex)</div>
+<div class="line"><a name="l14523"></a><span class="lineno">14523</span>&#160;{</div>
+<div class="line"><a name="l14524"></a><span class="lineno">14524</span>&#160;    m_UseMutex = useMutex;</div>
+<div class="line"><a name="l14525"></a><span class="lineno">14525</span>&#160;    m_Flags = settings.<a class="code" href="struct_vma_record_settings.html#ad8fdcc92119ae7a8c08c1a564c01d63a">flags</a>;</div>
+<div class="line"><a name="l14526"></a><span class="lineno">14526</span>&#160; </div>
+<div class="line"><a name="l14527"></a><span class="lineno">14527</span>&#160;    QueryPerformanceFrequency((LARGE_INTEGER*)&amp;m_Freq);</div>
+<div class="line"><a name="l14528"></a><span class="lineno">14528</span>&#160;    QueryPerformanceCounter((LARGE_INTEGER*)&amp;m_StartCounter);</div>
+<div class="line"><a name="l14529"></a><span class="lineno">14529</span>&#160; </div>
+<div class="line"><a name="l14530"></a><span class="lineno">14530</span>&#160;    <span class="comment">// Open file for writing.</span></div>
+<div class="line"><a name="l14531"></a><span class="lineno">14531</span>&#160;    errno_t err = fopen_s(&amp;m_File, settings.<a class="code" href="struct_vma_record_settings.html#a6cb1fdbf6bcb610b68f2010dd629e89d">pFilePath</a>, <span class="stringliteral">&quot;wb&quot;</span>);</div>
+<div class="line"><a name="l14532"></a><span class="lineno">14532</span>&#160;    <span class="keywordflow">if</span>(err != 0)</div>
+<div class="line"><a name="l14533"></a><span class="lineno">14533</span>&#160;    {</div>
+<div class="line"><a name="l14534"></a><span class="lineno">14534</span>&#160;        <span class="keywordflow">return</span> VK_ERROR_INITIALIZATION_FAILED;</div>
+<div class="line"><a name="l14535"></a><span class="lineno">14535</span>&#160;    }</div>
+<div class="line"><a name="l14536"></a><span class="lineno">14536</span>&#160; </div>
+<div class="line"><a name="l14537"></a><span class="lineno">14537</span>&#160;    <span class="comment">// Write header.</span></div>
+<div class="line"><a name="l14538"></a><span class="lineno">14538</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;%s\n&quot;</span>, <span class="stringliteral">&quot;Vulkan Memory Allocator,Calls recording&quot;</span>);</div>
+<div class="line"><a name="l14539"></a><span class="lineno">14539</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;%s\n&quot;</span>, <span class="stringliteral">&quot;1,8&quot;</span>);</div>
+<div class="line"><a name="l14540"></a><span class="lineno">14540</span>&#160; </div>
+<div class="line"><a name="l14541"></a><span class="lineno">14541</span>&#160;    <span class="keywordflow">return</span> VK_SUCCESS;</div>
+<div class="line"><a name="l14542"></a><span class="lineno">14542</span>&#160;}</div>
+<div class="line"><a name="l14543"></a><span class="lineno">14543</span>&#160; </div>
+<div class="line"><a name="l14544"></a><span class="lineno">14544</span>&#160;VmaRecorder::~VmaRecorder()</div>
+<div class="line"><a name="l14545"></a><span class="lineno">14545</span>&#160;{</div>
+<div class="line"><a name="l14546"></a><span class="lineno">14546</span>&#160;    <span class="keywordflow">if</span>(m_File != VMA_NULL)</div>
+<div class="line"><a name="l14547"></a><span class="lineno">14547</span>&#160;    {</div>
+<div class="line"><a name="l14548"></a><span class="lineno">14548</span>&#160;        fclose(m_File);</div>
+<div class="line"><a name="l14549"></a><span class="lineno">14549</span>&#160;    }</div>
+<div class="line"><a name="l14550"></a><span class="lineno">14550</span>&#160;}</div>
+<div class="line"><a name="l14551"></a><span class="lineno">14551</span>&#160; </div>
+<div class="line"><a name="l14552"></a><span class="lineno">14552</span>&#160;<span class="keywordtype">void</span> VmaRecorder::RecordCreateAllocator(uint32_t frameIndex)</div>
+<div class="line"><a name="l14553"></a><span class="lineno">14553</span>&#160;{</div>
+<div class="line"><a name="l14554"></a><span class="lineno">14554</span>&#160;    CallParams callParams;</div>
+<div class="line"><a name="l14555"></a><span class="lineno">14555</span>&#160;    GetBasicParams(callParams);</div>
+<div class="line"><a name="l14556"></a><span class="lineno">14556</span>&#160; </div>
+<div class="line"><a name="l14557"></a><span class="lineno">14557</span>&#160;    VmaMutexLock lock(m_FileMutex, m_UseMutex);</div>
+<div class="line"><a name="l14558"></a><span class="lineno">14558</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;%u,%.3f,%u,vmaCreateAllocator\n&quot;</span>, callParams.threadId, callParams.time, frameIndex);</div>
+<div class="line"><a name="l14559"></a><span class="lineno">14559</span>&#160;    Flush();</div>
+<div class="line"><a name="l14560"></a><span class="lineno">14560</span>&#160;}</div>
+<div class="line"><a name="l14561"></a><span class="lineno">14561</span>&#160; </div>
+<div class="line"><a name="l14562"></a><span class="lineno">14562</span>&#160;<span class="keywordtype">void</span> VmaRecorder::RecordDestroyAllocator(uint32_t frameIndex)</div>
+<div class="line"><a name="l14563"></a><span class="lineno">14563</span>&#160;{</div>
+<div class="line"><a name="l14564"></a><span class="lineno">14564</span>&#160;    CallParams callParams;</div>
+<div class="line"><a name="l14565"></a><span class="lineno">14565</span>&#160;    GetBasicParams(callParams);</div>
+<div class="line"><a name="l14566"></a><span class="lineno">14566</span>&#160; </div>
+<div class="line"><a name="l14567"></a><span class="lineno">14567</span>&#160;    VmaMutexLock lock(m_FileMutex, m_UseMutex);</div>
+<div class="line"><a name="l14568"></a><span class="lineno">14568</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;%u,%.3f,%u,vmaDestroyAllocator\n&quot;</span>, callParams.threadId, callParams.time, frameIndex);</div>
+<div class="line"><a name="l14569"></a><span class="lineno">14569</span>&#160;    Flush();</div>
+<div class="line"><a name="l14570"></a><span class="lineno">14570</span>&#160;}</div>
+<div class="line"><a name="l14571"></a><span class="lineno">14571</span>&#160; </div>
+<div class="line"><a name="l14572"></a><span class="lineno">14572</span>&#160;<span class="keywordtype">void</span> VmaRecorder::RecordCreatePool(uint32_t frameIndex, <span class="keyword">const</span> <a class="code" href="struct_vma_pool_create_info.html">VmaPoolCreateInfo</a>&amp; createInfo, <a class="code" href="struct_vma_pool.html">VmaPool</a> pool)</div>
+<div class="line"><a name="l14573"></a><span class="lineno">14573</span>&#160;{</div>
+<div class="line"><a name="l14574"></a><span class="lineno">14574</span>&#160;    CallParams callParams;</div>
+<div class="line"><a name="l14575"></a><span class="lineno">14575</span>&#160;    GetBasicParams(callParams);</div>
+<div class="line"><a name="l14576"></a><span class="lineno">14576</span>&#160; </div>
+<div class="line"><a name="l14577"></a><span class="lineno">14577</span>&#160;    VmaMutexLock lock(m_FileMutex, m_UseMutex);</div>
+<div class="line"><a name="l14578"></a><span class="lineno">14578</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;%u,%.3f,%u,vmaCreatePool,%u,%u,%llu,%llu,%llu,%u,%p\n&quot;</span>, callParams.threadId, callParams.time, frameIndex,</div>
+<div class="line"><a name="l14579"></a><span class="lineno">14579</span>&#160;        createInfo.<a class="code" href="struct_vma_pool_create_info.html#a596fa76b685d3f1f688f84a709a5b319">memoryTypeIndex</a>,</div>
+<div class="line"><a name="l14580"></a><span class="lineno">14580</span>&#160;        createInfo.<a class="code" href="struct_vma_pool_create_info.html#a8405139f63d078340ae74513a59f5446">flags</a>,</div>
+<div class="line"><a name="l14581"></a><span class="lineno">14581</span>&#160;        createInfo.<a class="code" href="struct_vma_pool_create_info.html#aa4265160536cdb9be821b7686c16c676">blockSize</a>,</div>
+<div class="line"><a name="l14582"></a><span class="lineno">14582</span>&#160;        (uint64_t)createInfo.<a class="code" href="struct_vma_pool_create_info.html#ad8006fb803185c0a699d30f3e9a865ae">minBlockCount</a>,</div>
+<div class="line"><a name="l14583"></a><span class="lineno">14583</span>&#160;        (uint64_t)createInfo.<a class="code" href="struct_vma_pool_create_info.html#ae41142f2834fcdc82baa4883c187b75c">maxBlockCount</a>,</div>
+<div class="line"><a name="l14584"></a><span class="lineno">14584</span>&#160;        createInfo.<a class="code" href="struct_vma_pool_create_info.html#a9437e43ffbb644dbbf7fc4e50cfad6aa">frameInUseCount</a>,</div>
+<div class="line"><a name="l14585"></a><span class="lineno">14585</span>&#160;        pool);</div>
+<div class="line"><a name="l14586"></a><span class="lineno">14586</span>&#160;    Flush();</div>
+<div class="line"><a name="l14587"></a><span class="lineno">14587</span>&#160;}</div>
+<div class="line"><a name="l14588"></a><span class="lineno">14588</span>&#160; </div>
+<div class="line"><a name="l14589"></a><span class="lineno">14589</span>&#160;<span class="keywordtype">void</span> VmaRecorder::RecordDestroyPool(uint32_t frameIndex, <a class="code" href="struct_vma_pool.html">VmaPool</a> pool)</div>
+<div class="line"><a name="l14590"></a><span class="lineno">14590</span>&#160;{</div>
+<div class="line"><a name="l14591"></a><span class="lineno">14591</span>&#160;    CallParams callParams;</div>
+<div class="line"><a name="l14592"></a><span class="lineno">14592</span>&#160;    GetBasicParams(callParams);</div>
+<div class="line"><a name="l14593"></a><span class="lineno">14593</span>&#160; </div>
+<div class="line"><a name="l14594"></a><span class="lineno">14594</span>&#160;    VmaMutexLock lock(m_FileMutex, m_UseMutex);</div>
+<div class="line"><a name="l14595"></a><span class="lineno">14595</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;%u,%.3f,%u,vmaDestroyPool,%p\n&quot;</span>, callParams.threadId, callParams.time, frameIndex,</div>
+<div class="line"><a name="l14596"></a><span class="lineno">14596</span>&#160;        pool);</div>
+<div class="line"><a name="l14597"></a><span class="lineno">14597</span>&#160;    Flush();</div>
+<div class="line"><a name="l14598"></a><span class="lineno">14598</span>&#160;}</div>
+<div class="line"><a name="l14599"></a><span class="lineno">14599</span>&#160; </div>
+<div class="line"><a name="l14600"></a><span class="lineno">14600</span>&#160;<span class="keywordtype">void</span> VmaRecorder::RecordAllocateMemory(uint32_t frameIndex,</div>
+<div class="line"><a name="l14601"></a><span class="lineno">14601</span>&#160;        <span class="keyword">const</span> VkMemoryRequirements&amp; vkMemReq,</div>
+<div class="line"><a name="l14602"></a><span class="lineno">14602</span>&#160;        <span class="keyword">const</span> <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>&amp; createInfo,</div>
+<div class="line"><a name="l14603"></a><span class="lineno">14603</span>&#160;        <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation)</div>
+<div class="line"><a name="l14604"></a><span class="lineno">14604</span>&#160;{</div>
+<div class="line"><a name="l14605"></a><span class="lineno">14605</span>&#160;    CallParams callParams;</div>
+<div class="line"><a name="l14606"></a><span class="lineno">14606</span>&#160;    GetBasicParams(callParams);</div>
+<div class="line"><a name="l14607"></a><span class="lineno">14607</span>&#160; </div>
+<div class="line"><a name="l14608"></a><span class="lineno">14608</span>&#160;    VmaMutexLock lock(m_FileMutex, m_UseMutex);</div>
+<div class="line"><a name="l14609"></a><span class="lineno">14609</span>&#160;    UserDataString userDataStr(createInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a>, createInfo.<a class="code" href="struct_vma_allocation_create_info.html#a8259e85c272683434f4abb4ddddffe19">pUserData</a>);</div>
+<div class="line"><a name="l14610"></a><span class="lineno">14610</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;%u,%.3f,%u,vmaAllocateMemory,%llu,%llu,%u,%u,%u,%u,%u,%u,%p,%p,%s\n&quot;</span>, callParams.threadId, callParams.time, frameIndex,</div>
+<div class="line"><a name="l14611"></a><span class="lineno">14611</span>&#160;        vkMemReq.size,</div>
+<div class="line"><a name="l14612"></a><span class="lineno">14612</span>&#160;        vkMemReq.alignment,</div>
+<div class="line"><a name="l14613"></a><span class="lineno">14613</span>&#160;        vkMemReq.memoryTypeBits,</div>
+<div class="line"><a name="l14614"></a><span class="lineno">14614</span>&#160;        createInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a>,</div>
+<div class="line"><a name="l14615"></a><span class="lineno">14615</span>&#160;        createInfo.<a class="code" href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910">usage</a>,</div>
+<div class="line"><a name="l14616"></a><span class="lineno">14616</span>&#160;        createInfo.<a class="code" href="struct_vma_allocation_create_info.html#a9166390303ff42d783305bc31c2b6b90">requiredFlags</a>,</div>
+<div class="line"><a name="l14617"></a><span class="lineno">14617</span>&#160;        createInfo.<a class="code" href="struct_vma_allocation_create_info.html#a7fe8d81a1ad10b2a2faacacee5b15d6d">preferredFlags</a>,</div>
+<div class="line"><a name="l14618"></a><span class="lineno">14618</span>&#160;        createInfo.<a class="code" href="struct_vma_allocation_create_info.html#a3bf940c0271d85d6ba32a4d820075055">memoryTypeBits</a>,</div>
+<div class="line"><a name="l14619"></a><span class="lineno">14619</span>&#160;        createInfo.<a class="code" href="struct_vma_allocation_create_info.html#a6272c0555cfd1fe28bff1afeb6190150">pool</a>,</div>
+<div class="line"><a name="l14620"></a><span class="lineno">14620</span>&#160;        allocation,</div>
+<div class="line"><a name="l14621"></a><span class="lineno">14621</span>&#160;        userDataStr.GetString());</div>
+<div class="line"><a name="l14622"></a><span class="lineno">14622</span>&#160;    Flush();</div>
+<div class="line"><a name="l14623"></a><span class="lineno">14623</span>&#160;}</div>
+<div class="line"><a name="l14624"></a><span class="lineno">14624</span>&#160; </div>
+<div class="line"><a name="l14625"></a><span class="lineno">14625</span>&#160;<span class="keywordtype">void</span> VmaRecorder::RecordAllocateMemoryPages(uint32_t frameIndex,</div>
+<div class="line"><a name="l14626"></a><span class="lineno">14626</span>&#160;    <span class="keyword">const</span> VkMemoryRequirements&amp; vkMemReq,</div>
+<div class="line"><a name="l14627"></a><span class="lineno">14627</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>&amp; createInfo,</div>
+<div class="line"><a name="l14628"></a><span class="lineno">14628</span>&#160;    uint64_t allocationCount,</div>
+<div class="line"><a name="l14629"></a><span class="lineno">14629</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocations)</div>
+<div class="line"><a name="l14630"></a><span class="lineno">14630</span>&#160;{</div>
+<div class="line"><a name="l14631"></a><span class="lineno">14631</span>&#160;    CallParams callParams;</div>
+<div class="line"><a name="l14632"></a><span class="lineno">14632</span>&#160;    GetBasicParams(callParams);</div>
+<div class="line"><a name="l14633"></a><span class="lineno">14633</span>&#160; </div>
+<div class="line"><a name="l14634"></a><span class="lineno">14634</span>&#160;    VmaMutexLock lock(m_FileMutex, m_UseMutex);</div>
+<div class="line"><a name="l14635"></a><span class="lineno">14635</span>&#160;    UserDataString userDataStr(createInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a>, createInfo.<a class="code" href="struct_vma_allocation_create_info.html#a8259e85c272683434f4abb4ddddffe19">pUserData</a>);</div>
+<div class="line"><a name="l14636"></a><span class="lineno">14636</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;%u,%.3f,%u,vmaAllocateMemoryPages,%llu,%llu,%u,%u,%u,%u,%u,%u,%p,&quot;</span>, callParams.threadId, callParams.time, frameIndex,</div>
+<div class="line"><a name="l14637"></a><span class="lineno">14637</span>&#160;        vkMemReq.size,</div>
+<div class="line"><a name="l14638"></a><span class="lineno">14638</span>&#160;        vkMemReq.alignment,</div>
+<div class="line"><a name="l14639"></a><span class="lineno">14639</span>&#160;        vkMemReq.memoryTypeBits,</div>
+<div class="line"><a name="l14640"></a><span class="lineno">14640</span>&#160;        createInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a>,</div>
+<div class="line"><a name="l14641"></a><span class="lineno">14641</span>&#160;        createInfo.<a class="code" href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910">usage</a>,</div>
+<div class="line"><a name="l14642"></a><span class="lineno">14642</span>&#160;        createInfo.<a class="code" href="struct_vma_allocation_create_info.html#a9166390303ff42d783305bc31c2b6b90">requiredFlags</a>,</div>
+<div class="line"><a name="l14643"></a><span class="lineno">14643</span>&#160;        createInfo.<a class="code" href="struct_vma_allocation_create_info.html#a7fe8d81a1ad10b2a2faacacee5b15d6d">preferredFlags</a>,</div>
+<div class="line"><a name="l14644"></a><span class="lineno">14644</span>&#160;        createInfo.<a class="code" href="struct_vma_allocation_create_info.html#a3bf940c0271d85d6ba32a4d820075055">memoryTypeBits</a>,</div>
+<div class="line"><a name="l14645"></a><span class="lineno">14645</span>&#160;        createInfo.<a class="code" href="struct_vma_allocation_create_info.html#a6272c0555cfd1fe28bff1afeb6190150">pool</a>);</div>
+<div class="line"><a name="l14646"></a><span class="lineno">14646</span>&#160;    PrintPointerList(allocationCount, pAllocations);</div>
+<div class="line"><a name="l14647"></a><span class="lineno">14647</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;,%s\n&quot;</span>, userDataStr.GetString());</div>
+<div class="line"><a name="l14648"></a><span class="lineno">14648</span>&#160;    Flush();</div>
+<div class="line"><a name="l14649"></a><span class="lineno">14649</span>&#160;}</div>
+<div class="line"><a name="l14650"></a><span class="lineno">14650</span>&#160; </div>
+<div class="line"><a name="l14651"></a><span class="lineno">14651</span>&#160;<span class="keywordtype">void</span> VmaRecorder::RecordAllocateMemoryForBuffer(uint32_t frameIndex,</div>
+<div class="line"><a name="l14652"></a><span class="lineno">14652</span>&#160;    <span class="keyword">const</span> VkMemoryRequirements&amp; vkMemReq,</div>
+<div class="line"><a name="l14653"></a><span class="lineno">14653</span>&#160;    <span class="keywordtype">bool</span> requiresDedicatedAllocation,</div>
+<div class="line"><a name="l14654"></a><span class="lineno">14654</span>&#160;    <span class="keywordtype">bool</span> prefersDedicatedAllocation,</div>
+<div class="line"><a name="l14655"></a><span class="lineno">14655</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>&amp; createInfo,</div>
+<div class="line"><a name="l14656"></a><span class="lineno">14656</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation)</div>
+<div class="line"><a name="l14657"></a><span class="lineno">14657</span>&#160;{</div>
+<div class="line"><a name="l14658"></a><span class="lineno">14658</span>&#160;    CallParams callParams;</div>
+<div class="line"><a name="l14659"></a><span class="lineno">14659</span>&#160;    GetBasicParams(callParams);</div>
+<div class="line"><a name="l14660"></a><span class="lineno">14660</span>&#160; </div>
+<div class="line"><a name="l14661"></a><span class="lineno">14661</span>&#160;    VmaMutexLock lock(m_FileMutex, m_UseMutex);</div>
+<div class="line"><a name="l14662"></a><span class="lineno">14662</span>&#160;    UserDataString userDataStr(createInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a>, createInfo.<a class="code" href="struct_vma_allocation_create_info.html#a8259e85c272683434f4abb4ddddffe19">pUserData</a>);</div>
+<div class="line"><a name="l14663"></a><span class="lineno">14663</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;%u,%.3f,%u,vmaAllocateMemoryForBuffer,%llu,%llu,%u,%u,%u,%u,%u,%u,%u,%u,%p,%p,%s\n&quot;</span>, callParams.threadId, callParams.time, frameIndex,</div>
+<div class="line"><a name="l14664"></a><span class="lineno">14664</span>&#160;        vkMemReq.size,</div>
+<div class="line"><a name="l14665"></a><span class="lineno">14665</span>&#160;        vkMemReq.alignment,</div>
+<div class="line"><a name="l14666"></a><span class="lineno">14666</span>&#160;        vkMemReq.memoryTypeBits,</div>
+<div class="line"><a name="l14667"></a><span class="lineno">14667</span>&#160;        requiresDedicatedAllocation ? 1 : 0,</div>
+<div class="line"><a name="l14668"></a><span class="lineno">14668</span>&#160;        prefersDedicatedAllocation ? 1 : 0,</div>
+<div class="line"><a name="l14669"></a><span class="lineno">14669</span>&#160;        createInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a>,</div>
+<div class="line"><a name="l14670"></a><span class="lineno">14670</span>&#160;        createInfo.<a class="code" href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910">usage</a>,</div>
+<div class="line"><a name="l14671"></a><span class="lineno">14671</span>&#160;        createInfo.<a class="code" href="struct_vma_allocation_create_info.html#a9166390303ff42d783305bc31c2b6b90">requiredFlags</a>,</div>
+<div class="line"><a name="l14672"></a><span class="lineno">14672</span>&#160;        createInfo.<a class="code" href="struct_vma_allocation_create_info.html#a7fe8d81a1ad10b2a2faacacee5b15d6d">preferredFlags</a>,</div>
+<div class="line"><a name="l14673"></a><span class="lineno">14673</span>&#160;        createInfo.<a class="code" href="struct_vma_allocation_create_info.html#a3bf940c0271d85d6ba32a4d820075055">memoryTypeBits</a>,</div>
+<div class="line"><a name="l14674"></a><span class="lineno">14674</span>&#160;        createInfo.<a class="code" href="struct_vma_allocation_create_info.html#a6272c0555cfd1fe28bff1afeb6190150">pool</a>,</div>
+<div class="line"><a name="l14675"></a><span class="lineno">14675</span>&#160;        allocation,</div>
+<div class="line"><a name="l14676"></a><span class="lineno">14676</span>&#160;        userDataStr.GetString());</div>
+<div class="line"><a name="l14677"></a><span class="lineno">14677</span>&#160;    Flush();</div>
+<div class="line"><a name="l14678"></a><span class="lineno">14678</span>&#160;}</div>
+<div class="line"><a name="l14679"></a><span class="lineno">14679</span>&#160; </div>
+<div class="line"><a name="l14680"></a><span class="lineno">14680</span>&#160;<span class="keywordtype">void</span> VmaRecorder::RecordAllocateMemoryForImage(uint32_t frameIndex,</div>
+<div class="line"><a name="l14681"></a><span class="lineno">14681</span>&#160;    <span class="keyword">const</span> VkMemoryRequirements&amp; vkMemReq,</div>
+<div class="line"><a name="l14682"></a><span class="lineno">14682</span>&#160;    <span class="keywordtype">bool</span> requiresDedicatedAllocation,</div>
+<div class="line"><a name="l14683"></a><span class="lineno">14683</span>&#160;    <span class="keywordtype">bool</span> prefersDedicatedAllocation,</div>
+<div class="line"><a name="l14684"></a><span class="lineno">14684</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>&amp; createInfo,</div>
+<div class="line"><a name="l14685"></a><span class="lineno">14685</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation)</div>
+<div class="line"><a name="l14686"></a><span class="lineno">14686</span>&#160;{</div>
+<div class="line"><a name="l14687"></a><span class="lineno">14687</span>&#160;    CallParams callParams;</div>
+<div class="line"><a name="l14688"></a><span class="lineno">14688</span>&#160;    GetBasicParams(callParams);</div>
+<div class="line"><a name="l14689"></a><span class="lineno">14689</span>&#160; </div>
+<div class="line"><a name="l14690"></a><span class="lineno">14690</span>&#160;    VmaMutexLock lock(m_FileMutex, m_UseMutex);</div>
+<div class="line"><a name="l14691"></a><span class="lineno">14691</span>&#160;    UserDataString userDataStr(createInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a>, createInfo.<a class="code" href="struct_vma_allocation_create_info.html#a8259e85c272683434f4abb4ddddffe19">pUserData</a>);</div>
+<div class="line"><a name="l14692"></a><span class="lineno">14692</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;%u,%.3f,%u,vmaAllocateMemoryForImage,%llu,%llu,%u,%u,%u,%u,%u,%u,%u,%u,%p,%p,%s\n&quot;</span>, callParams.threadId, callParams.time, frameIndex,</div>
+<div class="line"><a name="l14693"></a><span class="lineno">14693</span>&#160;        vkMemReq.size,</div>
+<div class="line"><a name="l14694"></a><span class="lineno">14694</span>&#160;        vkMemReq.alignment,</div>
+<div class="line"><a name="l14695"></a><span class="lineno">14695</span>&#160;        vkMemReq.memoryTypeBits,</div>
+<div class="line"><a name="l14696"></a><span class="lineno">14696</span>&#160;        requiresDedicatedAllocation ? 1 : 0,</div>
+<div class="line"><a name="l14697"></a><span class="lineno">14697</span>&#160;        prefersDedicatedAllocation ? 1 : 0,</div>
+<div class="line"><a name="l14698"></a><span class="lineno">14698</span>&#160;        createInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a>,</div>
+<div class="line"><a name="l14699"></a><span class="lineno">14699</span>&#160;        createInfo.<a class="code" href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910">usage</a>,</div>
+<div class="line"><a name="l14700"></a><span class="lineno">14700</span>&#160;        createInfo.<a class="code" href="struct_vma_allocation_create_info.html#a9166390303ff42d783305bc31c2b6b90">requiredFlags</a>,</div>
+<div class="line"><a name="l14701"></a><span class="lineno">14701</span>&#160;        createInfo.<a class="code" href="struct_vma_allocation_create_info.html#a7fe8d81a1ad10b2a2faacacee5b15d6d">preferredFlags</a>,</div>
+<div class="line"><a name="l14702"></a><span class="lineno">14702</span>&#160;        createInfo.<a class="code" href="struct_vma_allocation_create_info.html#a3bf940c0271d85d6ba32a4d820075055">memoryTypeBits</a>,</div>
+<div class="line"><a name="l14703"></a><span class="lineno">14703</span>&#160;        createInfo.<a class="code" href="struct_vma_allocation_create_info.html#a6272c0555cfd1fe28bff1afeb6190150">pool</a>,</div>
+<div class="line"><a name="l14704"></a><span class="lineno">14704</span>&#160;        allocation,</div>
+<div class="line"><a name="l14705"></a><span class="lineno">14705</span>&#160;        userDataStr.GetString());</div>
+<div class="line"><a name="l14706"></a><span class="lineno">14706</span>&#160;    Flush();</div>
+<div class="line"><a name="l14707"></a><span class="lineno">14707</span>&#160;}</div>
+<div class="line"><a name="l14708"></a><span class="lineno">14708</span>&#160; </div>
+<div class="line"><a name="l14709"></a><span class="lineno">14709</span>&#160;<span class="keywordtype">void</span> VmaRecorder::RecordFreeMemory(uint32_t frameIndex,</div>
+<div class="line"><a name="l14710"></a><span class="lineno">14710</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation)</div>
+<div class="line"><a name="l14711"></a><span class="lineno">14711</span>&#160;{</div>
+<div class="line"><a name="l14712"></a><span class="lineno">14712</span>&#160;    CallParams callParams;</div>
+<div class="line"><a name="l14713"></a><span class="lineno">14713</span>&#160;    GetBasicParams(callParams);</div>
+<div class="line"><a name="l14714"></a><span class="lineno">14714</span>&#160; </div>
+<div class="line"><a name="l14715"></a><span class="lineno">14715</span>&#160;    VmaMutexLock lock(m_FileMutex, m_UseMutex);</div>
+<div class="line"><a name="l14716"></a><span class="lineno">14716</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;%u,%.3f,%u,vmaFreeMemory,%p\n&quot;</span>, callParams.threadId, callParams.time, frameIndex,</div>
+<div class="line"><a name="l14717"></a><span class="lineno">14717</span>&#160;        allocation);</div>
+<div class="line"><a name="l14718"></a><span class="lineno">14718</span>&#160;    Flush();</div>
+<div class="line"><a name="l14719"></a><span class="lineno">14719</span>&#160;}</div>
+<div class="line"><a name="l14720"></a><span class="lineno">14720</span>&#160; </div>
+<div class="line"><a name="l14721"></a><span class="lineno">14721</span>&#160;<span class="keywordtype">void</span> VmaRecorder::RecordFreeMemoryPages(uint32_t frameIndex,</div>
+<div class="line"><a name="l14722"></a><span class="lineno">14722</span>&#160;    uint64_t allocationCount,</div>
+<div class="line"><a name="l14723"></a><span class="lineno">14723</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocations)</div>
+<div class="line"><a name="l14724"></a><span class="lineno">14724</span>&#160;{</div>
+<div class="line"><a name="l14725"></a><span class="lineno">14725</span>&#160;    CallParams callParams;</div>
+<div class="line"><a name="l14726"></a><span class="lineno">14726</span>&#160;    GetBasicParams(callParams);</div>
+<div class="line"><a name="l14727"></a><span class="lineno">14727</span>&#160; </div>
+<div class="line"><a name="l14728"></a><span class="lineno">14728</span>&#160;    VmaMutexLock lock(m_FileMutex, m_UseMutex);</div>
+<div class="line"><a name="l14729"></a><span class="lineno">14729</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;%u,%.3f,%u,vmaFreeMemoryPages,&quot;</span>, callParams.threadId, callParams.time, frameIndex);</div>
+<div class="line"><a name="l14730"></a><span class="lineno">14730</span>&#160;    PrintPointerList(allocationCount, pAllocations);</div>
+<div class="line"><a name="l14731"></a><span class="lineno">14731</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;\n&quot;</span>);</div>
+<div class="line"><a name="l14732"></a><span class="lineno">14732</span>&#160;    Flush();</div>
+<div class="line"><a name="l14733"></a><span class="lineno">14733</span>&#160;}</div>
+<div class="line"><a name="l14734"></a><span class="lineno">14734</span>&#160; </div>
+<div class="line"><a name="l14735"></a><span class="lineno">14735</span>&#160;<span class="keywordtype">void</span> VmaRecorder::RecordSetAllocationUserData(uint32_t frameIndex,</div>
+<div class="line"><a name="l14736"></a><span class="lineno">14736</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation,</div>
+<div class="line"><a name="l14737"></a><span class="lineno">14737</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">void</span>* pUserData)</div>
+<div class="line"><a name="l14738"></a><span class="lineno">14738</span>&#160;{</div>
+<div class="line"><a name="l14739"></a><span class="lineno">14739</span>&#160;    CallParams callParams;</div>
+<div class="line"><a name="l14740"></a><span class="lineno">14740</span>&#160;    GetBasicParams(callParams);</div>
+<div class="line"><a name="l14741"></a><span class="lineno">14741</span>&#160; </div>
+<div class="line"><a name="l14742"></a><span class="lineno">14742</span>&#160;    VmaMutexLock lock(m_FileMutex, m_UseMutex);</div>
+<div class="line"><a name="l14743"></a><span class="lineno">14743</span>&#160;    UserDataString userDataStr(</div>
+<div class="line"><a name="l14744"></a><span class="lineno">14744</span>&#160;        allocation-&gt;IsUserDataString() ? <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597aa6f24f821cd6a7c5e4a443f7bf59c520">VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT</a> : 0,</div>
+<div class="line"><a name="l14745"></a><span class="lineno">14745</span>&#160;        pUserData);</div>
+<div class="line"><a name="l14746"></a><span class="lineno">14746</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;%u,%.3f,%u,vmaSetAllocationUserData,%p,%s\n&quot;</span>, callParams.threadId, callParams.time, frameIndex,</div>
+<div class="line"><a name="l14747"></a><span class="lineno">14747</span>&#160;        allocation,</div>
+<div class="line"><a name="l14748"></a><span class="lineno">14748</span>&#160;        userDataStr.GetString());</div>
+<div class="line"><a name="l14749"></a><span class="lineno">14749</span>&#160;    Flush();</div>
+<div class="line"><a name="l14750"></a><span class="lineno">14750</span>&#160;}</div>
+<div class="line"><a name="l14751"></a><span class="lineno">14751</span>&#160; </div>
+<div class="line"><a name="l14752"></a><span class="lineno">14752</span>&#160;<span class="keywordtype">void</span> VmaRecorder::RecordCreateLostAllocation(uint32_t frameIndex,</div>
+<div class="line"><a name="l14753"></a><span class="lineno">14753</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation)</div>
+<div class="line"><a name="l14754"></a><span class="lineno">14754</span>&#160;{</div>
+<div class="line"><a name="l14755"></a><span class="lineno">14755</span>&#160;    CallParams callParams;</div>
+<div class="line"><a name="l14756"></a><span class="lineno">14756</span>&#160;    GetBasicParams(callParams);</div>
+<div class="line"><a name="l14757"></a><span class="lineno">14757</span>&#160; </div>
+<div class="line"><a name="l14758"></a><span class="lineno">14758</span>&#160;    VmaMutexLock lock(m_FileMutex, m_UseMutex);</div>
+<div class="line"><a name="l14759"></a><span class="lineno">14759</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;%u,%.3f,%u,vmaCreateLostAllocation,%p\n&quot;</span>, callParams.threadId, callParams.time, frameIndex,</div>
+<div class="line"><a name="l14760"></a><span class="lineno">14760</span>&#160;        allocation);</div>
+<div class="line"><a name="l14761"></a><span class="lineno">14761</span>&#160;    Flush();</div>
+<div class="line"><a name="l14762"></a><span class="lineno">14762</span>&#160;}</div>
+<div class="line"><a name="l14763"></a><span class="lineno">14763</span>&#160; </div>
+<div class="line"><a name="l14764"></a><span class="lineno">14764</span>&#160;<span class="keywordtype">void</span> VmaRecorder::RecordMapMemory(uint32_t frameIndex,</div>
+<div class="line"><a name="l14765"></a><span class="lineno">14765</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation)</div>
+<div class="line"><a name="l14766"></a><span class="lineno">14766</span>&#160;{</div>
+<div class="line"><a name="l14767"></a><span class="lineno">14767</span>&#160;    CallParams callParams;</div>
+<div class="line"><a name="l14768"></a><span class="lineno">14768</span>&#160;    GetBasicParams(callParams);</div>
+<div class="line"><a name="l14769"></a><span class="lineno">14769</span>&#160; </div>
+<div class="line"><a name="l14770"></a><span class="lineno">14770</span>&#160;    VmaMutexLock lock(m_FileMutex, m_UseMutex);</div>
+<div class="line"><a name="l14771"></a><span class="lineno">14771</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;%u,%.3f,%u,vmaMapMemory,%p\n&quot;</span>, callParams.threadId, callParams.time, frameIndex,</div>
+<div class="line"><a name="l14772"></a><span class="lineno">14772</span>&#160;        allocation);</div>
+<div class="line"><a name="l14773"></a><span class="lineno">14773</span>&#160;    Flush();</div>
+<div class="line"><a name="l14774"></a><span class="lineno">14774</span>&#160;}</div>
+<div class="line"><a name="l14775"></a><span class="lineno">14775</span>&#160; </div>
+<div class="line"><a name="l14776"></a><span class="lineno">14776</span>&#160;<span class="keywordtype">void</span> VmaRecorder::RecordUnmapMemory(uint32_t frameIndex,</div>
+<div class="line"><a name="l14777"></a><span class="lineno">14777</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation)</div>
+<div class="line"><a name="l14778"></a><span class="lineno">14778</span>&#160;{</div>
+<div class="line"><a name="l14779"></a><span class="lineno">14779</span>&#160;    CallParams callParams;</div>
+<div class="line"><a name="l14780"></a><span class="lineno">14780</span>&#160;    GetBasicParams(callParams);</div>
+<div class="line"><a name="l14781"></a><span class="lineno">14781</span>&#160; </div>
+<div class="line"><a name="l14782"></a><span class="lineno">14782</span>&#160;    VmaMutexLock lock(m_FileMutex, m_UseMutex);</div>
+<div class="line"><a name="l14783"></a><span class="lineno">14783</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;%u,%.3f,%u,vmaUnmapMemory,%p\n&quot;</span>, callParams.threadId, callParams.time, frameIndex,</div>
+<div class="line"><a name="l14784"></a><span class="lineno">14784</span>&#160;        allocation);</div>
+<div class="line"><a name="l14785"></a><span class="lineno">14785</span>&#160;    Flush();</div>
+<div class="line"><a name="l14786"></a><span class="lineno">14786</span>&#160;}</div>
+<div class="line"><a name="l14787"></a><span class="lineno">14787</span>&#160; </div>
+<div class="line"><a name="l14788"></a><span class="lineno">14788</span>&#160;<span class="keywordtype">void</span> VmaRecorder::RecordFlushAllocation(uint32_t frameIndex,</div>
+<div class="line"><a name="l14789"></a><span class="lineno">14789</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation, VkDeviceSize offset, VkDeviceSize size)</div>
+<div class="line"><a name="l14790"></a><span class="lineno">14790</span>&#160;{</div>
+<div class="line"><a name="l14791"></a><span class="lineno">14791</span>&#160;    CallParams callParams;</div>
+<div class="line"><a name="l14792"></a><span class="lineno">14792</span>&#160;    GetBasicParams(callParams);</div>
+<div class="line"><a name="l14793"></a><span class="lineno">14793</span>&#160; </div>
+<div class="line"><a name="l14794"></a><span class="lineno">14794</span>&#160;    VmaMutexLock lock(m_FileMutex, m_UseMutex);</div>
+<div class="line"><a name="l14795"></a><span class="lineno">14795</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;%u,%.3f,%u,vmaFlushAllocation,%p,%llu,%llu\n&quot;</span>, callParams.threadId, callParams.time, frameIndex,</div>
+<div class="line"><a name="l14796"></a><span class="lineno">14796</span>&#160;        allocation,</div>
+<div class="line"><a name="l14797"></a><span class="lineno">14797</span>&#160;        offset,</div>
+<div class="line"><a name="l14798"></a><span class="lineno">14798</span>&#160;        size);</div>
+<div class="line"><a name="l14799"></a><span class="lineno">14799</span>&#160;    Flush();</div>
+<div class="line"><a name="l14800"></a><span class="lineno">14800</span>&#160;}</div>
+<div class="line"><a name="l14801"></a><span class="lineno">14801</span>&#160; </div>
+<div class="line"><a name="l14802"></a><span class="lineno">14802</span>&#160;<span class="keywordtype">void</span> VmaRecorder::RecordInvalidateAllocation(uint32_t frameIndex,</div>
+<div class="line"><a name="l14803"></a><span class="lineno">14803</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation, VkDeviceSize offset, VkDeviceSize size)</div>
+<div class="line"><a name="l14804"></a><span class="lineno">14804</span>&#160;{</div>
+<div class="line"><a name="l14805"></a><span class="lineno">14805</span>&#160;    CallParams callParams;</div>
+<div class="line"><a name="l14806"></a><span class="lineno">14806</span>&#160;    GetBasicParams(callParams);</div>
+<div class="line"><a name="l14807"></a><span class="lineno">14807</span>&#160; </div>
+<div class="line"><a name="l14808"></a><span class="lineno">14808</span>&#160;    VmaMutexLock lock(m_FileMutex, m_UseMutex);</div>
+<div class="line"><a name="l14809"></a><span class="lineno">14809</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;%u,%.3f,%u,vmaInvalidateAllocation,%p,%llu,%llu\n&quot;</span>, callParams.threadId, callParams.time, frameIndex,</div>
+<div class="line"><a name="l14810"></a><span class="lineno">14810</span>&#160;        allocation,</div>
+<div class="line"><a name="l14811"></a><span class="lineno">14811</span>&#160;        offset,</div>
+<div class="line"><a name="l14812"></a><span class="lineno">14812</span>&#160;        size);</div>
+<div class="line"><a name="l14813"></a><span class="lineno">14813</span>&#160;    Flush();</div>
+<div class="line"><a name="l14814"></a><span class="lineno">14814</span>&#160;}</div>
+<div class="line"><a name="l14815"></a><span class="lineno">14815</span>&#160; </div>
+<div class="line"><a name="l14816"></a><span class="lineno">14816</span>&#160;<span class="keywordtype">void</span> VmaRecorder::RecordCreateBuffer(uint32_t frameIndex,</div>
+<div class="line"><a name="l14817"></a><span class="lineno">14817</span>&#160;    <span class="keyword">const</span> VkBufferCreateInfo&amp; bufCreateInfo,</div>
+<div class="line"><a name="l14818"></a><span class="lineno">14818</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>&amp; allocCreateInfo,</div>
+<div class="line"><a name="l14819"></a><span class="lineno">14819</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation)</div>
+<div class="line"><a name="l14820"></a><span class="lineno">14820</span>&#160;{</div>
+<div class="line"><a name="l14821"></a><span class="lineno">14821</span>&#160;    CallParams callParams;</div>
+<div class="line"><a name="l14822"></a><span class="lineno">14822</span>&#160;    GetBasicParams(callParams);</div>
+<div class="line"><a name="l14823"></a><span class="lineno">14823</span>&#160; </div>
+<div class="line"><a name="l14824"></a><span class="lineno">14824</span>&#160;    VmaMutexLock lock(m_FileMutex, m_UseMutex);</div>
+<div class="line"><a name="l14825"></a><span class="lineno">14825</span>&#160;    UserDataString userDataStr(allocCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a>, allocCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#a8259e85c272683434f4abb4ddddffe19">pUserData</a>);</div>
+<div class="line"><a name="l14826"></a><span class="lineno">14826</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;%u,%.3f,%u,vmaCreateBuffer,%u,%llu,%u,%u,%u,%u,%u,%u,%u,%p,%p,%s\n&quot;</span>, callParams.threadId, callParams.time, frameIndex,</div>
+<div class="line"><a name="l14827"></a><span class="lineno">14827</span>&#160;        bufCreateInfo.flags,</div>
+<div class="line"><a name="l14828"></a><span class="lineno">14828</span>&#160;        bufCreateInfo.size,</div>
+<div class="line"><a name="l14829"></a><span class="lineno">14829</span>&#160;        bufCreateInfo.usage,</div>
+<div class="line"><a name="l14830"></a><span class="lineno">14830</span>&#160;        bufCreateInfo.sharingMode,</div>
+<div class="line"><a name="l14831"></a><span class="lineno">14831</span>&#160;        allocCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a>,</div>
+<div class="line"><a name="l14832"></a><span class="lineno">14832</span>&#160;        allocCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910">usage</a>,</div>
+<div class="line"><a name="l14833"></a><span class="lineno">14833</span>&#160;        allocCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#a9166390303ff42d783305bc31c2b6b90">requiredFlags</a>,</div>
+<div class="line"><a name="l14834"></a><span class="lineno">14834</span>&#160;        allocCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#a7fe8d81a1ad10b2a2faacacee5b15d6d">preferredFlags</a>,</div>
+<div class="line"><a name="l14835"></a><span class="lineno">14835</span>&#160;        allocCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#a3bf940c0271d85d6ba32a4d820075055">memoryTypeBits</a>,</div>
+<div class="line"><a name="l14836"></a><span class="lineno">14836</span>&#160;        allocCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#a6272c0555cfd1fe28bff1afeb6190150">pool</a>,</div>
+<div class="line"><a name="l14837"></a><span class="lineno">14837</span>&#160;        allocation,</div>
+<div class="line"><a name="l14838"></a><span class="lineno">14838</span>&#160;        userDataStr.GetString());</div>
+<div class="line"><a name="l14839"></a><span class="lineno">14839</span>&#160;    Flush();</div>
+<div class="line"><a name="l14840"></a><span class="lineno">14840</span>&#160;}</div>
+<div class="line"><a name="l14841"></a><span class="lineno">14841</span>&#160; </div>
+<div class="line"><a name="l14842"></a><span class="lineno">14842</span>&#160;<span class="keywordtype">void</span> VmaRecorder::RecordCreateImage(uint32_t frameIndex,</div>
+<div class="line"><a name="l14843"></a><span class="lineno">14843</span>&#160;    <span class="keyword">const</span> VkImageCreateInfo&amp; imageCreateInfo,</div>
+<div class="line"><a name="l14844"></a><span class="lineno">14844</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>&amp; allocCreateInfo,</div>
+<div class="line"><a name="l14845"></a><span class="lineno">14845</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation)</div>
+<div class="line"><a name="l14846"></a><span class="lineno">14846</span>&#160;{</div>
+<div class="line"><a name="l14847"></a><span class="lineno">14847</span>&#160;    CallParams callParams;</div>
+<div class="line"><a name="l14848"></a><span class="lineno">14848</span>&#160;    GetBasicParams(callParams);</div>
+<div class="line"><a name="l14849"></a><span class="lineno">14849</span>&#160; </div>
+<div class="line"><a name="l14850"></a><span class="lineno">14850</span>&#160;    VmaMutexLock lock(m_FileMutex, m_UseMutex);</div>
+<div class="line"><a name="l14851"></a><span class="lineno">14851</span>&#160;    UserDataString userDataStr(allocCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a>, allocCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#a8259e85c272683434f4abb4ddddffe19">pUserData</a>);</div>
+<div class="line"><a name="l14852"></a><span class="lineno">14852</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;%u,%.3f,%u,vmaCreateImage,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%p,%p,%s\n&quot;</span>, callParams.threadId, callParams.time, frameIndex,</div>
+<div class="line"><a name="l14853"></a><span class="lineno">14853</span>&#160;        imageCreateInfo.flags,</div>
+<div class="line"><a name="l14854"></a><span class="lineno">14854</span>&#160;        imageCreateInfo.imageType,</div>
+<div class="line"><a name="l14855"></a><span class="lineno">14855</span>&#160;        imageCreateInfo.format,</div>
+<div class="line"><a name="l14856"></a><span class="lineno">14856</span>&#160;        imageCreateInfo.extent.width,</div>
+<div class="line"><a name="l14857"></a><span class="lineno">14857</span>&#160;        imageCreateInfo.extent.height,</div>
+<div class="line"><a name="l14858"></a><span class="lineno">14858</span>&#160;        imageCreateInfo.extent.depth,</div>
+<div class="line"><a name="l14859"></a><span class="lineno">14859</span>&#160;        imageCreateInfo.mipLevels,</div>
+<div class="line"><a name="l14860"></a><span class="lineno">14860</span>&#160;        imageCreateInfo.arrayLayers,</div>
+<div class="line"><a name="l14861"></a><span class="lineno">14861</span>&#160;        imageCreateInfo.samples,</div>
+<div class="line"><a name="l14862"></a><span class="lineno">14862</span>&#160;        imageCreateInfo.tiling,</div>
+<div class="line"><a name="l14863"></a><span class="lineno">14863</span>&#160;        imageCreateInfo.usage,</div>
+<div class="line"><a name="l14864"></a><span class="lineno">14864</span>&#160;        imageCreateInfo.sharingMode,</div>
+<div class="line"><a name="l14865"></a><span class="lineno">14865</span>&#160;        imageCreateInfo.initialLayout,</div>
+<div class="line"><a name="l14866"></a><span class="lineno">14866</span>&#160;        allocCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a>,</div>
+<div class="line"><a name="l14867"></a><span class="lineno">14867</span>&#160;        allocCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910">usage</a>,</div>
+<div class="line"><a name="l14868"></a><span class="lineno">14868</span>&#160;        allocCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#a9166390303ff42d783305bc31c2b6b90">requiredFlags</a>,</div>
+<div class="line"><a name="l14869"></a><span class="lineno">14869</span>&#160;        allocCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#a7fe8d81a1ad10b2a2faacacee5b15d6d">preferredFlags</a>,</div>
+<div class="line"><a name="l14870"></a><span class="lineno">14870</span>&#160;        allocCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#a3bf940c0271d85d6ba32a4d820075055">memoryTypeBits</a>,</div>
+<div class="line"><a name="l14871"></a><span class="lineno">14871</span>&#160;        allocCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#a6272c0555cfd1fe28bff1afeb6190150">pool</a>,</div>
+<div class="line"><a name="l14872"></a><span class="lineno">14872</span>&#160;        allocation,</div>
+<div class="line"><a name="l14873"></a><span class="lineno">14873</span>&#160;        userDataStr.GetString());</div>
+<div class="line"><a name="l14874"></a><span class="lineno">14874</span>&#160;    Flush();</div>
+<div class="line"><a name="l14875"></a><span class="lineno">14875</span>&#160;}</div>
+<div class="line"><a name="l14876"></a><span class="lineno">14876</span>&#160; </div>
+<div class="line"><a name="l14877"></a><span class="lineno">14877</span>&#160;<span class="keywordtype">void</span> VmaRecorder::RecordDestroyBuffer(uint32_t frameIndex,</div>
+<div class="line"><a name="l14878"></a><span class="lineno">14878</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation)</div>
+<div class="line"><a name="l14879"></a><span class="lineno">14879</span>&#160;{</div>
+<div class="line"><a name="l14880"></a><span class="lineno">14880</span>&#160;    CallParams callParams;</div>
+<div class="line"><a name="l14881"></a><span class="lineno">14881</span>&#160;    GetBasicParams(callParams);</div>
+<div class="line"><a name="l14882"></a><span class="lineno">14882</span>&#160; </div>
+<div class="line"><a name="l14883"></a><span class="lineno">14883</span>&#160;    VmaMutexLock lock(m_FileMutex, m_UseMutex);</div>
+<div class="line"><a name="l14884"></a><span class="lineno">14884</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;%u,%.3f,%u,vmaDestroyBuffer,%p\n&quot;</span>, callParams.threadId, callParams.time, frameIndex,</div>
+<div class="line"><a name="l14885"></a><span class="lineno">14885</span>&#160;        allocation);</div>
+<div class="line"><a name="l14886"></a><span class="lineno">14886</span>&#160;    Flush();</div>
+<div class="line"><a name="l14887"></a><span class="lineno">14887</span>&#160;}</div>
+<div class="line"><a name="l14888"></a><span class="lineno">14888</span>&#160; </div>
+<div class="line"><a name="l14889"></a><span class="lineno">14889</span>&#160;<span class="keywordtype">void</span> VmaRecorder::RecordDestroyImage(uint32_t frameIndex,</div>
+<div class="line"><a name="l14890"></a><span class="lineno">14890</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation)</div>
+<div class="line"><a name="l14891"></a><span class="lineno">14891</span>&#160;{</div>
+<div class="line"><a name="l14892"></a><span class="lineno">14892</span>&#160;    CallParams callParams;</div>
+<div class="line"><a name="l14893"></a><span class="lineno">14893</span>&#160;    GetBasicParams(callParams);</div>
+<div class="line"><a name="l14894"></a><span class="lineno">14894</span>&#160; </div>
+<div class="line"><a name="l14895"></a><span class="lineno">14895</span>&#160;    VmaMutexLock lock(m_FileMutex, m_UseMutex);</div>
+<div class="line"><a name="l14896"></a><span class="lineno">14896</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;%u,%.3f,%u,vmaDestroyImage,%p\n&quot;</span>, callParams.threadId, callParams.time, frameIndex,</div>
+<div class="line"><a name="l14897"></a><span class="lineno">14897</span>&#160;        allocation);</div>
+<div class="line"><a name="l14898"></a><span class="lineno">14898</span>&#160;    Flush();</div>
+<div class="line"><a name="l14899"></a><span class="lineno">14899</span>&#160;}</div>
+<div class="line"><a name="l14900"></a><span class="lineno">14900</span>&#160; </div>
+<div class="line"><a name="l14901"></a><span class="lineno">14901</span>&#160;<span class="keywordtype">void</span> VmaRecorder::RecordTouchAllocation(uint32_t frameIndex,</div>
+<div class="line"><a name="l14902"></a><span class="lineno">14902</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation)</div>
+<div class="line"><a name="l14903"></a><span class="lineno">14903</span>&#160;{</div>
+<div class="line"><a name="l14904"></a><span class="lineno">14904</span>&#160;    CallParams callParams;</div>
+<div class="line"><a name="l14905"></a><span class="lineno">14905</span>&#160;    GetBasicParams(callParams);</div>
+<div class="line"><a name="l14906"></a><span class="lineno">14906</span>&#160; </div>
+<div class="line"><a name="l14907"></a><span class="lineno">14907</span>&#160;    VmaMutexLock lock(m_FileMutex, m_UseMutex);</div>
+<div class="line"><a name="l14908"></a><span class="lineno">14908</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;%u,%.3f,%u,vmaTouchAllocation,%p\n&quot;</span>, callParams.threadId, callParams.time, frameIndex,</div>
+<div class="line"><a name="l14909"></a><span class="lineno">14909</span>&#160;        allocation);</div>
+<div class="line"><a name="l14910"></a><span class="lineno">14910</span>&#160;    Flush();</div>
+<div class="line"><a name="l14911"></a><span class="lineno">14911</span>&#160;}</div>
+<div class="line"><a name="l14912"></a><span class="lineno">14912</span>&#160; </div>
+<div class="line"><a name="l14913"></a><span class="lineno">14913</span>&#160;<span class="keywordtype">void</span> VmaRecorder::RecordGetAllocationInfo(uint32_t frameIndex,</div>
+<div class="line"><a name="l14914"></a><span class="lineno">14914</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation)</div>
+<div class="line"><a name="l14915"></a><span class="lineno">14915</span>&#160;{</div>
+<div class="line"><a name="l14916"></a><span class="lineno">14916</span>&#160;    CallParams callParams;</div>
+<div class="line"><a name="l14917"></a><span class="lineno">14917</span>&#160;    GetBasicParams(callParams);</div>
+<div class="line"><a name="l14918"></a><span class="lineno">14918</span>&#160; </div>
+<div class="line"><a name="l14919"></a><span class="lineno">14919</span>&#160;    VmaMutexLock lock(m_FileMutex, m_UseMutex);</div>
+<div class="line"><a name="l14920"></a><span class="lineno">14920</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;%u,%.3f,%u,vmaGetAllocationInfo,%p\n&quot;</span>, callParams.threadId, callParams.time, frameIndex,</div>
+<div class="line"><a name="l14921"></a><span class="lineno">14921</span>&#160;        allocation);</div>
+<div class="line"><a name="l14922"></a><span class="lineno">14922</span>&#160;    Flush();</div>
+<div class="line"><a name="l14923"></a><span class="lineno">14923</span>&#160;}</div>
+<div class="line"><a name="l14924"></a><span class="lineno">14924</span>&#160; </div>
+<div class="line"><a name="l14925"></a><span class="lineno">14925</span>&#160;<span class="keywordtype">void</span> VmaRecorder::RecordMakePoolAllocationsLost(uint32_t frameIndex,</div>
+<div class="line"><a name="l14926"></a><span class="lineno">14926</span>&#160;    <a class="code" href="struct_vma_pool.html">VmaPool</a> pool)</div>
+<div class="line"><a name="l14927"></a><span class="lineno">14927</span>&#160;{</div>
+<div class="line"><a name="l14928"></a><span class="lineno">14928</span>&#160;    CallParams callParams;</div>
+<div class="line"><a name="l14929"></a><span class="lineno">14929</span>&#160;    GetBasicParams(callParams);</div>
+<div class="line"><a name="l14930"></a><span class="lineno">14930</span>&#160; </div>
+<div class="line"><a name="l14931"></a><span class="lineno">14931</span>&#160;    VmaMutexLock lock(m_FileMutex, m_UseMutex);</div>
+<div class="line"><a name="l14932"></a><span class="lineno">14932</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;%u,%.3f,%u,vmaMakePoolAllocationsLost,%p\n&quot;</span>, callParams.threadId, callParams.time, frameIndex,</div>
+<div class="line"><a name="l14933"></a><span class="lineno">14933</span>&#160;        pool);</div>
+<div class="line"><a name="l14934"></a><span class="lineno">14934</span>&#160;    Flush();</div>
+<div class="line"><a name="l14935"></a><span class="lineno">14935</span>&#160;}</div>
+<div class="line"><a name="l14936"></a><span class="lineno">14936</span>&#160; </div>
+<div class="line"><a name="l14937"></a><span class="lineno">14937</span>&#160;<span class="keywordtype">void</span> VmaRecorder::RecordDefragmentationBegin(uint32_t frameIndex,</div>
+<div class="line"><a name="l14938"></a><span class="lineno">14938</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_defragmentation_info2.html">VmaDefragmentationInfo2</a>&amp; info,</div>
+<div class="line"><a name="l14939"></a><span class="lineno">14939</span>&#160;    <a class="code" href="struct_vma_defragmentation_context.html">VmaDefragmentationContext</a> ctx)</div>
+<div class="line"><a name="l14940"></a><span class="lineno">14940</span>&#160;{</div>
+<div class="line"><a name="l14941"></a><span class="lineno">14941</span>&#160;    CallParams callParams;</div>
+<div class="line"><a name="l14942"></a><span class="lineno">14942</span>&#160;    GetBasicParams(callParams);</div>
+<div class="line"><a name="l14943"></a><span class="lineno">14943</span>&#160; </div>
+<div class="line"><a name="l14944"></a><span class="lineno">14944</span>&#160;    VmaMutexLock lock(m_FileMutex, m_UseMutex);</div>
+<div class="line"><a name="l14945"></a><span class="lineno">14945</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;%u,%.3f,%u,vmaDefragmentationBegin,%u,&quot;</span>, callParams.threadId, callParams.time, frameIndex,</div>
+<div class="line"><a name="l14946"></a><span class="lineno">14946</span>&#160;        info.<a class="code" href="struct_vma_defragmentation_info2.html#a53e844ee5633e229cf6daf14b2d9fff9">flags</a>);</div>
+<div class="line"><a name="l14947"></a><span class="lineno">14947</span>&#160;    PrintPointerList(info.<a class="code" href="struct_vma_defragmentation_info2.html#a3cf86ab32c1da779b4923d301a3056ba">allocationCount</a>, info.<a class="code" href="struct_vma_defragmentation_info2.html#a8943f8d65969ce8e2189a1cdf3205e96">pAllocations</a>);</div>
+<div class="line"><a name="l14948"></a><span class="lineno">14948</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;,&quot;</span>);</div>
+<div class="line"><a name="l14949"></a><span class="lineno">14949</span>&#160;    PrintPointerList(info.<a class="code" href="struct_vma_defragmentation_info2.html#a7e70aa2a1081d849dcc7829b19d3ec9d">poolCount</a>, info.<a class="code" href="struct_vma_defragmentation_info2.html#a0b3effd57f3fcdeb2ed62210b4ef20e1">pPools</a>);</div>
+<div class="line"><a name="l14950"></a><span class="lineno">14950</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;,%llu,%u,%llu,%u,%p,%p\n&quot;</span>,</div>
+<div class="line"><a name="l14951"></a><span class="lineno">14951</span>&#160;        info.<a class="code" href="struct_vma_defragmentation_info2.html#af78e1ea40c22d85137b65f6b384a4d0a">maxCpuBytesToMove</a>,</div>
+<div class="line"><a name="l14952"></a><span class="lineno">14952</span>&#160;        info.<a class="code" href="struct_vma_defragmentation_info2.html#a94c2c7223d52878445a8cccce396b671">maxCpuAllocationsToMove</a>,</div>
+<div class="line"><a name="l14953"></a><span class="lineno">14953</span>&#160;        info.<a class="code" href="struct_vma_defragmentation_info2.html#a4ddbc898d0afe1518f863a3763628f08">maxGpuBytesToMove</a>,</div>
+<div class="line"><a name="l14954"></a><span class="lineno">14954</span>&#160;        info.<a class="code" href="struct_vma_defragmentation_info2.html#a40d53d33e71ba0b66f844ed63c05a3f6">maxGpuAllocationsToMove</a>,</div>
+<div class="line"><a name="l14955"></a><span class="lineno">14955</span>&#160;        info.<a class="code" href="struct_vma_defragmentation_info2.html#a7f71f39590c5316771493d2333f9c1bd">commandBuffer</a>,</div>
+<div class="line"><a name="l14956"></a><span class="lineno">14956</span>&#160;        ctx);</div>
+<div class="line"><a name="l14957"></a><span class="lineno">14957</span>&#160;    Flush();</div>
+<div class="line"><a name="l14958"></a><span class="lineno">14958</span>&#160;}</div>
+<div class="line"><a name="l14959"></a><span class="lineno">14959</span>&#160; </div>
+<div class="line"><a name="l14960"></a><span class="lineno">14960</span>&#160;<span class="keywordtype">void</span> VmaRecorder::RecordDefragmentationEnd(uint32_t frameIndex,</div>
+<div class="line"><a name="l14961"></a><span class="lineno">14961</span>&#160;    <a class="code" href="struct_vma_defragmentation_context.html">VmaDefragmentationContext</a> ctx)</div>
+<div class="line"><a name="l14962"></a><span class="lineno">14962</span>&#160;{</div>
+<div class="line"><a name="l14963"></a><span class="lineno">14963</span>&#160;    CallParams callParams;</div>
+<div class="line"><a name="l14964"></a><span class="lineno">14964</span>&#160;    GetBasicParams(callParams);</div>
+<div class="line"><a name="l14965"></a><span class="lineno">14965</span>&#160; </div>
+<div class="line"><a name="l14966"></a><span class="lineno">14966</span>&#160;    VmaMutexLock lock(m_FileMutex, m_UseMutex);</div>
+<div class="line"><a name="l14967"></a><span class="lineno">14967</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;%u,%.3f,%u,vmaDefragmentationEnd,%p\n&quot;</span>, callParams.threadId, callParams.time, frameIndex,</div>
+<div class="line"><a name="l14968"></a><span class="lineno">14968</span>&#160;        ctx);</div>
+<div class="line"><a name="l14969"></a><span class="lineno">14969</span>&#160;    Flush();</div>
+<div class="line"><a name="l14970"></a><span class="lineno">14970</span>&#160;}</div>
+<div class="line"><a name="l14971"></a><span class="lineno">14971</span>&#160; </div>
+<div class="line"><a name="l14972"></a><span class="lineno">14972</span>&#160;<span class="keywordtype">void</span> VmaRecorder::RecordSetPoolName(uint32_t frameIndex,</div>
+<div class="line"><a name="l14973"></a><span class="lineno">14973</span>&#160;    <a class="code" href="struct_vma_pool.html">VmaPool</a> pool,</div>
+<div class="line"><a name="l14974"></a><span class="lineno">14974</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">char</span>* name)</div>
+<div class="line"><a name="l14975"></a><span class="lineno">14975</span>&#160;{</div>
+<div class="line"><a name="l14976"></a><span class="lineno">14976</span>&#160;    CallParams callParams;</div>
+<div class="line"><a name="l14977"></a><span class="lineno">14977</span>&#160;    GetBasicParams(callParams);</div>
+<div class="line"><a name="l14978"></a><span class="lineno">14978</span>&#160; </div>
+<div class="line"><a name="l14979"></a><span class="lineno">14979</span>&#160;    VmaMutexLock lock(m_FileMutex, m_UseMutex);</div>
+<div class="line"><a name="l14980"></a><span class="lineno">14980</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;%u,%.3f,%u,vmaSetPoolName,%p,%s\n&quot;</span>, callParams.threadId, callParams.time, frameIndex,</div>
+<div class="line"><a name="l14981"></a><span class="lineno">14981</span>&#160;        pool, name != VMA_NULL ? name : <span class="stringliteral">&quot;&quot;</span>);</div>
+<div class="line"><a name="l14982"></a><span class="lineno">14982</span>&#160;    Flush();</div>
+<div class="line"><a name="l14983"></a><span class="lineno">14983</span>&#160;}</div>
+<div class="line"><a name="l14984"></a><span class="lineno">14984</span>&#160; </div>
+<div class="line"><a name="l14985"></a><span class="lineno">14985</span>&#160;VmaRecorder::UserDataString::UserDataString(<a class="code" href="vk__mem__alloc_8h.html#a5225e5e11f8376f6a31a1791f3d6e817">VmaAllocationCreateFlags</a> allocFlags, <span class="keyword">const</span> <span class="keywordtype">void</span>* pUserData)</div>
+<div class="line"><a name="l14986"></a><span class="lineno">14986</span>&#160;{</div>
+<div class="line"><a name="l14987"></a><span class="lineno">14987</span>&#160;    <span class="keywordflow">if</span>(pUserData != VMA_NULL)</div>
+<div class="line"><a name="l14988"></a><span class="lineno">14988</span>&#160;    {</div>
+<div class="line"><a name="l14989"></a><span class="lineno">14989</span>&#160;        <span class="keywordflow">if</span>((allocFlags &amp; <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597aa6f24f821cd6a7c5e4a443f7bf59c520">VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT</a>) != 0)</div>
+<div class="line"><a name="l14990"></a><span class="lineno">14990</span>&#160;        {</div>
+<div class="line"><a name="l14991"></a><span class="lineno">14991</span>&#160;            m_Str = (<span class="keyword">const</span> <span class="keywordtype">char</span>*)pUserData;</div>
+<div class="line"><a name="l14992"></a><span class="lineno">14992</span>&#160;        }</div>
+<div class="line"><a name="l14993"></a><span class="lineno">14993</span>&#160;        <span class="keywordflow">else</span></div>
+<div class="line"><a name="l14994"></a><span class="lineno">14994</span>&#160;        {</div>
+<div class="line"><a name="l14995"></a><span class="lineno">14995</span>&#160;            sprintf_s(m_PtrStr, <span class="stringliteral">&quot;%p&quot;</span>, pUserData);</div>
+<div class="line"><a name="l14996"></a><span class="lineno">14996</span>&#160;            m_Str = m_PtrStr;</div>
+<div class="line"><a name="l14997"></a><span class="lineno">14997</span>&#160;        }</div>
+<div class="line"><a name="l14998"></a><span class="lineno">14998</span>&#160;    }</div>
+<div class="line"><a name="l14999"></a><span class="lineno">14999</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l15000"></a><span class="lineno">15000</span>&#160;    {</div>
+<div class="line"><a name="l15001"></a><span class="lineno">15001</span>&#160;        m_Str = <span class="stringliteral">&quot;&quot;</span>;</div>
+<div class="line"><a name="l15002"></a><span class="lineno">15002</span>&#160;    }</div>
+<div class="line"><a name="l15003"></a><span class="lineno">15003</span>&#160;}</div>
+<div class="line"><a name="l15004"></a><span class="lineno">15004</span>&#160; </div>
+<div class="line"><a name="l15005"></a><span class="lineno">15005</span>&#160;<span class="keywordtype">void</span> VmaRecorder::WriteConfiguration(</div>
+<div class="line"><a name="l15006"></a><span class="lineno">15006</span>&#160;    <span class="keyword">const</span> VkPhysicalDeviceProperties&amp; devProps,</div>
+<div class="line"><a name="l15007"></a><span class="lineno">15007</span>&#160;    <span class="keyword">const</span> VkPhysicalDeviceMemoryProperties&amp; memProps,</div>
+<div class="line"><a name="l15008"></a><span class="lineno">15008</span>&#160;    uint32_t vulkanApiVersion,</div>
+<div class="line"><a name="l15009"></a><span class="lineno">15009</span>&#160;    <span class="keywordtype">bool</span> dedicatedAllocationExtensionEnabled,</div>
+<div class="line"><a name="l15010"></a><span class="lineno">15010</span>&#160;    <span class="keywordtype">bool</span> bindMemory2ExtensionEnabled,</div>
+<div class="line"><a name="l15011"></a><span class="lineno">15011</span>&#160;    <span class="keywordtype">bool</span> memoryBudgetExtensionEnabled,</div>
+<div class="line"><a name="l15012"></a><span class="lineno">15012</span>&#160;    <span class="keywordtype">bool</span> deviceCoherentMemoryExtensionEnabled)</div>
+<div class="line"><a name="l15013"></a><span class="lineno">15013</span>&#160;{</div>
+<div class="line"><a name="l15014"></a><span class="lineno">15014</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;Config,Begin\n&quot;</span>);</div>
+<div class="line"><a name="l15015"></a><span class="lineno">15015</span>&#160; </div>
+<div class="line"><a name="l15016"></a><span class="lineno">15016</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;VulkanApiVersion,%u,%u\n&quot;</span>, VK_VERSION_MAJOR(vulkanApiVersion), VK_VERSION_MINOR(vulkanApiVersion));</div>
+<div class="line"><a name="l15017"></a><span class="lineno">15017</span>&#160; </div>
+<div class="line"><a name="l15018"></a><span class="lineno">15018</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;PhysicalDevice,apiVersion,%u\n&quot;</span>, devProps.apiVersion);</div>
+<div class="line"><a name="l15019"></a><span class="lineno">15019</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;PhysicalDevice,driverVersion,%u\n&quot;</span>, devProps.driverVersion);</div>
+<div class="line"><a name="l15020"></a><span class="lineno">15020</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;PhysicalDevice,vendorID,%u\n&quot;</span>, devProps.vendorID);</div>
+<div class="line"><a name="l15021"></a><span class="lineno">15021</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;PhysicalDevice,deviceID,%u\n&quot;</span>, devProps.deviceID);</div>
+<div class="line"><a name="l15022"></a><span class="lineno">15022</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;PhysicalDevice,deviceType,%u\n&quot;</span>, devProps.deviceType);</div>
+<div class="line"><a name="l15023"></a><span class="lineno">15023</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;PhysicalDevice,deviceName,%s\n&quot;</span>, devProps.deviceName);</div>
+<div class="line"><a name="l15024"></a><span class="lineno">15024</span>&#160; </div>
+<div class="line"><a name="l15025"></a><span class="lineno">15025</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;PhysicalDeviceLimits,maxMemoryAllocationCount,%u\n&quot;</span>, devProps.limits.maxMemoryAllocationCount);</div>
+<div class="line"><a name="l15026"></a><span class="lineno">15026</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;PhysicalDeviceLimits,bufferImageGranularity,%llu\n&quot;</span>, devProps.limits.bufferImageGranularity);</div>
+<div class="line"><a name="l15027"></a><span class="lineno">15027</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;PhysicalDeviceLimits,nonCoherentAtomSize,%llu\n&quot;</span>, devProps.limits.nonCoherentAtomSize);</div>
+<div class="line"><a name="l15028"></a><span class="lineno">15028</span>&#160; </div>
+<div class="line"><a name="l15029"></a><span class="lineno">15029</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;PhysicalDeviceMemory,HeapCount,%u\n&quot;</span>, memProps.memoryHeapCount);</div>
+<div class="line"><a name="l15030"></a><span class="lineno">15030</span>&#160;    <span class="keywordflow">for</span>(uint32_t i = 0; i &lt; memProps.memoryHeapCount; ++i)</div>
+<div class="line"><a name="l15031"></a><span class="lineno">15031</span>&#160;    {</div>
+<div class="line"><a name="l15032"></a><span class="lineno">15032</span>&#160;        fprintf(m_File, <span class="stringliteral">&quot;PhysicalDeviceMemory,Heap,%u,size,%llu\n&quot;</span>, i, memProps.memoryHeaps[i].size);</div>
+<div class="line"><a name="l15033"></a><span class="lineno">15033</span>&#160;        fprintf(m_File, <span class="stringliteral">&quot;PhysicalDeviceMemory,Heap,%u,flags,%u\n&quot;</span>, i, memProps.memoryHeaps[i].flags);</div>
+<div class="line"><a name="l15034"></a><span class="lineno">15034</span>&#160;    }</div>
+<div class="line"><a name="l15035"></a><span class="lineno">15035</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;PhysicalDeviceMemory,TypeCount,%u\n&quot;</span>, memProps.memoryTypeCount);</div>
+<div class="line"><a name="l15036"></a><span class="lineno">15036</span>&#160;    <span class="keywordflow">for</span>(uint32_t i = 0; i &lt; memProps.memoryTypeCount; ++i)</div>
+<div class="line"><a name="l15037"></a><span class="lineno">15037</span>&#160;    {</div>
+<div class="line"><a name="l15038"></a><span class="lineno">15038</span>&#160;        fprintf(m_File, <span class="stringliteral">&quot;PhysicalDeviceMemory,Type,%u,heapIndex,%u\n&quot;</span>, i, memProps.memoryTypes[i].heapIndex);</div>
+<div class="line"><a name="l15039"></a><span class="lineno">15039</span>&#160;        fprintf(m_File, <span class="stringliteral">&quot;PhysicalDeviceMemory,Type,%u,propertyFlags,%u\n&quot;</span>, i, memProps.memoryTypes[i].propertyFlags);</div>
+<div class="line"><a name="l15040"></a><span class="lineno">15040</span>&#160;    }</div>
+<div class="line"><a name="l15041"></a><span class="lineno">15041</span>&#160; </div>
+<div class="line"><a name="l15042"></a><span class="lineno">15042</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;Extension,VK_KHR_dedicated_allocation,%u\n&quot;</span>, dedicatedAllocationExtensionEnabled ? 1 : 0);</div>
+<div class="line"><a name="l15043"></a><span class="lineno">15043</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;Extension,VK_KHR_bind_memory2,%u\n&quot;</span>, bindMemory2ExtensionEnabled ? 1 : 0);</div>
+<div class="line"><a name="l15044"></a><span class="lineno">15044</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;Extension,VK_EXT_memory_budget,%u\n&quot;</span>, memoryBudgetExtensionEnabled ? 1 : 0);</div>
+<div class="line"><a name="l15045"></a><span class="lineno">15045</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;Extension,VK_AMD_device_coherent_memory,%u\n&quot;</span>, deviceCoherentMemoryExtensionEnabled ? 1 : 0);</div>
+<div class="line"><a name="l15046"></a><span class="lineno">15046</span>&#160; </div>
+<div class="line"><a name="l15047"></a><span class="lineno">15047</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;Macro,VMA_DEBUG_ALWAYS_DEDICATED_MEMORY,%u\n&quot;</span>, VMA_DEBUG_ALWAYS_DEDICATED_MEMORY ? 1 : 0);</div>
+<div class="line"><a name="l15048"></a><span class="lineno">15048</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;Macro,VMA_DEBUG_ALIGNMENT,%llu\n&quot;</span>, (VkDeviceSize)VMA_DEBUG_ALIGNMENT);</div>
+<div class="line"><a name="l15049"></a><span class="lineno">15049</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;Macro,VMA_DEBUG_MARGIN,%llu\n&quot;</span>, (VkDeviceSize)VMA_DEBUG_MARGIN);</div>
+<div class="line"><a name="l15050"></a><span class="lineno">15050</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;Macro,VMA_DEBUG_INITIALIZE_ALLOCATIONS,%u\n&quot;</span>, VMA_DEBUG_INITIALIZE_ALLOCATIONS ? 1 : 0);</div>
+<div class="line"><a name="l15051"></a><span class="lineno">15051</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;Macro,VMA_DEBUG_DETECT_CORRUPTION,%u\n&quot;</span>, VMA_DEBUG_DETECT_CORRUPTION ? 1 : 0);</div>
+<div class="line"><a name="l15052"></a><span class="lineno">15052</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;Macro,VMA_DEBUG_GLOBAL_MUTEX,%u\n&quot;</span>, VMA_DEBUG_GLOBAL_MUTEX ? 1 : 0);</div>
+<div class="line"><a name="l15053"></a><span class="lineno">15053</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;Macro,VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY,%llu\n&quot;</span>, (VkDeviceSize)VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY);</div>
+<div class="line"><a name="l15054"></a><span class="lineno">15054</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;Macro,VMA_SMALL_HEAP_MAX_SIZE,%llu\n&quot;</span>, (VkDeviceSize)VMA_SMALL_HEAP_MAX_SIZE);</div>
+<div class="line"><a name="l15055"></a><span class="lineno">15055</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;Macro,VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE,%llu\n&quot;</span>, (VkDeviceSize)VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE);</div>
+<div class="line"><a name="l15056"></a><span class="lineno">15056</span>&#160; </div>
+<div class="line"><a name="l15057"></a><span class="lineno">15057</span>&#160;    fprintf(m_File, <span class="stringliteral">&quot;Config,End\n&quot;</span>);</div>
+<div class="line"><a name="l15058"></a><span class="lineno">15058</span>&#160;}</div>
+<div class="line"><a name="l15059"></a><span class="lineno">15059</span>&#160; </div>
+<div class="line"><a name="l15060"></a><span class="lineno">15060</span>&#160;<span class="keywordtype">void</span> VmaRecorder::GetBasicParams(CallParams&amp; outParams)</div>
+<div class="line"><a name="l15061"></a><span class="lineno">15061</span>&#160;{</div>
+<div class="line"><a name="l15062"></a><span class="lineno">15062</span>&#160;    outParams.threadId = GetCurrentThreadId();</div>
+<div class="line"><a name="l15063"></a><span class="lineno">15063</span>&#160; </div>
+<div class="line"><a name="l15064"></a><span class="lineno">15064</span>&#160;    LARGE_INTEGER counter;</div>
+<div class="line"><a name="l15065"></a><span class="lineno">15065</span>&#160;    QueryPerformanceCounter(&amp;counter);</div>
+<div class="line"><a name="l15066"></a><span class="lineno">15066</span>&#160;    outParams.time = (double)(counter.QuadPart - m_StartCounter) / (double)m_Freq;</div>
+<div class="line"><a name="l15067"></a><span class="lineno">15067</span>&#160;}</div>
+<div class="line"><a name="l15068"></a><span class="lineno">15068</span>&#160; </div>
+<div class="line"><a name="l15069"></a><span class="lineno">15069</span>&#160;<span class="keywordtype">void</span> VmaRecorder::PrintPointerList(uint64_t count, <span class="keyword">const</span> <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pItems)</div>
+<div class="line"><a name="l15070"></a><span class="lineno">15070</span>&#160;{</div>
+<div class="line"><a name="l15071"></a><span class="lineno">15071</span>&#160;    <span class="keywordflow">if</span>(count)</div>
+<div class="line"><a name="l15072"></a><span class="lineno">15072</span>&#160;    {</div>
+<div class="line"><a name="l15073"></a><span class="lineno">15073</span>&#160;        fprintf(m_File, <span class="stringliteral">&quot;%p&quot;</span>, pItems[0]);</div>
+<div class="line"><a name="l15074"></a><span class="lineno">15074</span>&#160;        <span class="keywordflow">for</span>(uint64_t i = 1; i &lt; count; ++i)</div>
+<div class="line"><a name="l15075"></a><span class="lineno">15075</span>&#160;        {</div>
+<div class="line"><a name="l15076"></a><span class="lineno">15076</span>&#160;            fprintf(m_File, <span class="stringliteral">&quot; %p&quot;</span>, pItems[i]);</div>
+<div class="line"><a name="l15077"></a><span class="lineno">15077</span>&#160;        }</div>
+<div class="line"><a name="l15078"></a><span class="lineno">15078</span>&#160;    }</div>
+<div class="line"><a name="l15079"></a><span class="lineno">15079</span>&#160;}</div>
+<div class="line"><a name="l15080"></a><span class="lineno">15080</span>&#160; </div>
+<div class="line"><a name="l15081"></a><span class="lineno">15081</span>&#160;<span class="keywordtype">void</span> VmaRecorder::Flush()</div>
+<div class="line"><a name="l15082"></a><span class="lineno">15082</span>&#160;{</div>
+<div class="line"><a name="l15083"></a><span class="lineno">15083</span>&#160;    <span class="keywordflow">if</span>((m_Flags &amp; <a class="code" href="vk__mem__alloc_8h.html#a4dd2c44642312a147a4e93373a6e64d2a8e7ab322e8732654be627c4ea8f36cc7">VMA_RECORD_FLUSH_AFTER_CALL_BIT</a>) != 0)</div>
+<div class="line"><a name="l15084"></a><span class="lineno">15084</span>&#160;    {</div>
+<div class="line"><a name="l15085"></a><span class="lineno">15085</span>&#160;        fflush(m_File);</div>
+<div class="line"><a name="l15086"></a><span class="lineno">15086</span>&#160;    }</div>
+<div class="line"><a name="l15087"></a><span class="lineno">15087</span>&#160;}</div>
+<div class="line"><a name="l15088"></a><span class="lineno">15088</span>&#160; </div>
+<div class="line"><a name="l15089"></a><span class="lineno">15089</span>&#160;<span class="preprocessor">#endif // #if VMA_RECORDING_ENABLED</span></div>
+<div class="line"><a name="l15090"></a><span class="lineno">15090</span>&#160; </div>
+<div class="line"><a name="l15092"></a><span class="lineno">15092</span>&#160;<span class="comment">// VmaAllocationObjectAllocator</span></div>
+<div class="line"><a name="l15093"></a><span class="lineno">15093</span>&#160; </div>
+<div class="line"><a name="l15094"></a><span class="lineno">15094</span>&#160;VmaAllocationObjectAllocator::VmaAllocationObjectAllocator(<span class="keyword">const</span> VkAllocationCallbacks* pAllocationCallbacks) :</div>
+<div class="line"><a name="l15095"></a><span class="lineno">15095</span>&#160;    m_Allocator(pAllocationCallbacks, 1024)</div>
+<div class="line"><a name="l15096"></a><span class="lineno">15096</span>&#160;{</div>
+<div class="line"><a name="l15097"></a><span class="lineno">15097</span>&#160;}</div>
+<div class="line"><a name="l15098"></a><span class="lineno">15098</span>&#160; </div>
+<div class="line"><a name="l15099"></a><span class="lineno">15099</span>&#160;<span class="keyword">template</span>&lt;<span class="keyword">typename</span>... Types&gt; <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> VmaAllocationObjectAllocator::Allocate(Types... args)</div>
+<div class="line"><a name="l15100"></a><span class="lineno">15100</span>&#160;{</div>
+<div class="line"><a name="l15101"></a><span class="lineno">15101</span>&#160;    VmaMutexLock mutexLock(m_Mutex);</div>
+<div class="line"><a name="l15102"></a><span class="lineno">15102</span>&#160;    <span class="keywordflow">return</span> m_Allocator.Alloc&lt;Types...&gt;(std::forward&lt;Types&gt;(args)...);</div>
+<div class="line"><a name="l15103"></a><span class="lineno">15103</span>&#160;}</div>
+<div class="line"><a name="l15104"></a><span class="lineno">15104</span>&#160; </div>
+<div class="line"><a name="l15105"></a><span class="lineno">15105</span>&#160;<span class="keywordtype">void</span> VmaAllocationObjectAllocator::Free(<a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAlloc)</div>
+<div class="line"><a name="l15106"></a><span class="lineno">15106</span>&#160;{</div>
+<div class="line"><a name="l15107"></a><span class="lineno">15107</span>&#160;    VmaMutexLock mutexLock(m_Mutex);</div>
+<div class="line"><a name="l15108"></a><span class="lineno">15108</span>&#160;    m_Allocator.Free(hAlloc);</div>
+<div class="line"><a name="l15109"></a><span class="lineno">15109</span>&#160;}</div>
+<div class="line"><a name="l15110"></a><span class="lineno">15110</span>&#160; </div>
+<div class="line"><a name="l15112"></a><span class="lineno">15112</span>&#160;<span class="comment">// VmaAllocator_T</span></div>
+<div class="line"><a name="l15113"></a><span class="lineno">15113</span>&#160; </div>
+<div class="line"><a name="l15114"></a><span class="lineno">15114</span>&#160;VmaAllocator_T::VmaAllocator_T(<span class="keyword">const</span> <a class="code" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a>* pCreateInfo) :</div>
+<div class="line"><a name="l15115"></a><span class="lineno">15115</span>&#160;    m_UseMutex((pCreateInfo-&gt;flags &amp; <a class="code" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca4816ddaed324ba110172ca608a20f29d">VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT</a>) == 0),</div>
+<div class="line"><a name="l15116"></a><span class="lineno">15116</span>&#160;    m_VulkanApiVersion(pCreateInfo-&gt;vulkanApiVersion != 0 ? pCreateInfo-&gt;vulkanApiVersion : VK_API_VERSION_1_0),</div>
+<div class="line"><a name="l15117"></a><span class="lineno">15117</span>&#160;    m_UseKhrDedicatedAllocation((pCreateInfo-&gt;flags &amp; <a class="code" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7cace7da7cc6e71a625dfa763c55a597878">VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT</a>) != 0),</div>
+<div class="line"><a name="l15118"></a><span class="lineno">15118</span>&#160;    m_UseKhrBindMemory2((pCreateInfo-&gt;flags &amp; <a class="code" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca8fb75bf07cd184ab903596295e863dee">VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT</a>) != 0),</div>
+<div class="line"><a name="l15119"></a><span class="lineno">15119</span>&#160;    m_UseExtMemoryBudget((pCreateInfo-&gt;flags &amp; <a class="code" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca4d4687863f7bd4b418c6006dc04400b0">VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT</a>) != 0),</div>
+<div class="line"><a name="l15120"></a><span class="lineno">15120</span>&#160;    m_UseAmdDeviceCoherentMemory((pCreateInfo-&gt;flags &amp; <a class="code" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca2acce4886d8078552efa38878413970f">VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT</a>) != 0),</div>
+<div class="line"><a name="l15121"></a><span class="lineno">15121</span>&#160;    m_UseKhrBufferDeviceAddress((pCreateInfo-&gt;flags &amp; <a class="code" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca5f1b28b0414319d1687e1f2b30ab0089">VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT</a>) != 0),</div>
+<div class="line"><a name="l15122"></a><span class="lineno">15122</span>&#160;    m_hDevice(pCreateInfo-&gt;device),</div>
+<div class="line"><a name="l15123"></a><span class="lineno">15123</span>&#160;    m_hInstance(pCreateInfo-&gt;instance),</div>
+<div class="line"><a name="l15124"></a><span class="lineno">15124</span>&#160;    m_AllocationCallbacksSpecified(pCreateInfo-&gt;pAllocationCallbacks != VMA_NULL),</div>
+<div class="line"><a name="l15125"></a><span class="lineno">15125</span>&#160;    m_AllocationCallbacks(pCreateInfo-&gt;pAllocationCallbacks ?</div>
+<div class="line"><a name="l15126"></a><span class="lineno">15126</span>&#160;        *pCreateInfo-&gt;pAllocationCallbacks : VmaEmptyAllocationCallbacks),</div>
+<div class="line"><a name="l15127"></a><span class="lineno">15127</span>&#160;    m_AllocationObjectAllocator(&amp;m_AllocationCallbacks),</div>
+<div class="line"><a name="l15128"></a><span class="lineno">15128</span>&#160;    m_HeapSizeLimitMask(0),</div>
+<div class="line"><a name="l15129"></a><span class="lineno">15129</span>&#160;    m_PreferredLargeHeapBlockSize(0),</div>
+<div class="line"><a name="l15130"></a><span class="lineno">15130</span>&#160;    m_PhysicalDevice(pCreateInfo-&gt;physicalDevice),</div>
+<div class="line"><a name="l15131"></a><span class="lineno">15131</span>&#160;    m_CurrentFrameIndex(0),</div>
+<div class="line"><a name="l15132"></a><span class="lineno">15132</span>&#160;    m_GpuDefragmentationMemoryTypeBits(UINT32_MAX),</div>
+<div class="line"><a name="l15133"></a><span class="lineno">15133</span>&#160;    m_Pools(VmaStlAllocator&lt;<a class="code" href="struct_vma_pool.html">VmaPool</a>&gt;(GetAllocationCallbacks())),</div>
+<div class="line"><a name="l15134"></a><span class="lineno">15134</span>&#160;    m_NextPoolId(0),</div>
+<div class="line"><a name="l15135"></a><span class="lineno">15135</span>&#160;    m_GlobalMemoryTypeBits(UINT32_MAX)</div>
+<div class="line"><a name="l15136"></a><span class="lineno">15136</span>&#160;#if <a class="code" href="vk__mem__alloc_8h.html#a1f0c126759fc96ccb6e2d23c101d770c">VMA_RECORDING_ENABLED</a></div>
+<div class="line"><a name="l15137"></a><span class="lineno">15137</span>&#160;    ,m_pRecorder(VMA_NULL)</div>
+<div class="line"><a name="l15138"></a><span class="lineno">15138</span>&#160;#endif</div>
+<div class="line"><a name="l15139"></a><span class="lineno">15139</span>&#160;{</div>
+<div class="line"><a name="l15140"></a><span class="lineno">15140</span>&#160;    <span class="keywordflow">if</span>(m_VulkanApiVersion &gt;= VK_MAKE_VERSION(1, 1, 0))</div>
+<div class="line"><a name="l15141"></a><span class="lineno">15141</span>&#160;    {</div>
+<div class="line"><a name="l15142"></a><span class="lineno">15142</span>&#160;        m_UseKhrDedicatedAllocation = <span class="keyword">false</span>;</div>
+<div class="line"><a name="l15143"></a><span class="lineno">15143</span>&#160;        m_UseKhrBindMemory2 = <span class="keyword">false</span>;</div>
+<div class="line"><a name="l15144"></a><span class="lineno">15144</span>&#160;    }</div>
+<div class="line"><a name="l15145"></a><span class="lineno">15145</span>&#160; </div>
+<div class="line"><a name="l15146"></a><span class="lineno">15146</span>&#160;    <span class="keywordflow">if</span>(VMA_DEBUG_DETECT_CORRUPTION)</div>
+<div class="line"><a name="l15147"></a><span class="lineno">15147</span>&#160;    {</div>
+<div class="line"><a name="l15148"></a><span class="lineno">15148</span>&#160;        <span class="comment">// Needs to be multiply of uint32_t size because we are going to write VMA_CORRUPTION_DETECTION_MAGIC_VALUE to it.</span></div>
+<div class="line"><a name="l15149"></a><span class="lineno">15149</span>&#160;        VMA_ASSERT(VMA_DEBUG_MARGIN % <span class="keyword">sizeof</span>(uint32_t) == 0);</div>
+<div class="line"><a name="l15150"></a><span class="lineno">15150</span>&#160;    }</div>
+<div class="line"><a name="l15151"></a><span class="lineno">15151</span>&#160; </div>
+<div class="line"><a name="l15152"></a><span class="lineno">15152</span>&#160;    VMA_ASSERT(pCreateInfo-&gt;<a class="code" href="struct_vma_allocator_create_info.html#a08230f04ae6ccf8a78150a9e829a7156">physicalDevice</a> &amp;&amp; pCreateInfo-&gt;<a class="code" href="struct_vma_allocator_create_info.html#ad924ddd77b04039c88d0c09b0ffcd500">device</a> &amp;&amp; pCreateInfo-&gt;<a class="code" href="struct_vma_allocator_create_info.html#a70dd42e29b1df1d1b9b61532ae0b370b">instance</a>);</div>
+<div class="line"><a name="l15153"></a><span class="lineno">15153</span>&#160; </div>
+<div class="line"><a name="l15154"></a><span class="lineno">15154</span>&#160;    <span class="keywordflow">if</span>(m_VulkanApiVersion &lt; VK_MAKE_VERSION(1, 1, 0))</div>
+<div class="line"><a name="l15155"></a><span class="lineno">15155</span>&#160;    {</div>
+<div class="line"><a name="l15156"></a><span class="lineno">15156</span>&#160;<span class="preprocessor">#if !(VMA_DEDICATED_ALLOCATION)</span></div>
+<div class="line"><a name="l15157"></a><span class="lineno">15157</span>&#160;        <span class="keywordflow">if</span>((pCreateInfo-&gt;<a class="code" href="struct_vma_allocator_create_info.html#a392ea2ecbaff93f91a7c49f735ad4346">flags</a> &amp; <a class="code" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7cace7da7cc6e71a625dfa763c55a597878">VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT</a>) != 0)</div>
+<div class="line"><a name="l15158"></a><span class="lineno">15158</span>&#160;        {</div>
+<div class="line"><a name="l15159"></a><span class="lineno">15159</span>&#160;            VMA_ASSERT(0 &amp;&amp; <span class="stringliteral">&quot;VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT set but required extensions are disabled by preprocessor macros.&quot;</span>);</div>
+<div class="line"><a name="l15160"></a><span class="lineno">15160</span>&#160;        }</div>
+<div class="line"><a name="l15161"></a><span class="lineno">15161</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l15162"></a><span class="lineno">15162</span>&#160;<span class="preprocessor">#if !(VMA_BIND_MEMORY2)</span></div>
+<div class="line"><a name="l15163"></a><span class="lineno">15163</span>&#160;        <span class="keywordflow">if</span>((pCreateInfo-&gt;<a class="code" href="struct_vma_allocator_create_info.html#a392ea2ecbaff93f91a7c49f735ad4346">flags</a> &amp; <a class="code" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca8fb75bf07cd184ab903596295e863dee">VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT</a>) != 0)</div>
+<div class="line"><a name="l15164"></a><span class="lineno">15164</span>&#160;        {</div>
+<div class="line"><a name="l15165"></a><span class="lineno">15165</span>&#160;            VMA_ASSERT(0 &amp;&amp; <span class="stringliteral">&quot;VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT set but required extension is disabled by preprocessor macros.&quot;</span>);</div>
+<div class="line"><a name="l15166"></a><span class="lineno">15166</span>&#160;        }</div>
+<div class="line"><a name="l15167"></a><span class="lineno">15167</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l15168"></a><span class="lineno">15168</span>&#160;    }</div>
+<div class="line"><a name="l15169"></a><span class="lineno">15169</span>&#160;<span class="preprocessor">#if !(VMA_MEMORY_BUDGET)</span></div>
+<div class="line"><a name="l15170"></a><span class="lineno">15170</span>&#160;    <span class="keywordflow">if</span>((pCreateInfo-&gt;<a class="code" href="struct_vma_allocator_create_info.html#a392ea2ecbaff93f91a7c49f735ad4346">flags</a> &amp; <a class="code" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca4d4687863f7bd4b418c6006dc04400b0">VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT</a>) != 0)</div>
+<div class="line"><a name="l15171"></a><span class="lineno">15171</span>&#160;    {</div>
+<div class="line"><a name="l15172"></a><span class="lineno">15172</span>&#160;        VMA_ASSERT(0 &amp;&amp; <span class="stringliteral">&quot;VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT set but required extension is disabled by preprocessor macros.&quot;</span>);</div>
+<div class="line"><a name="l15173"></a><span class="lineno">15173</span>&#160;    }</div>
+<div class="line"><a name="l15174"></a><span class="lineno">15174</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l15175"></a><span class="lineno">15175</span>&#160;<span class="preprocessor">#if !(VMA_BUFFER_DEVICE_ADDRESS)</span></div>
+<div class="line"><a name="l15176"></a><span class="lineno">15176</span>&#160;    <span class="keywordflow">if</span>(m_UseKhrBufferDeviceAddress)</div>
+<div class="line"><a name="l15177"></a><span class="lineno">15177</span>&#160;    {</div>
+<div class="line"><a name="l15178"></a><span class="lineno">15178</span>&#160;        VMA_ASSERT(0 &amp;&amp; <span class="stringliteral">&quot;VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT is set but required extension or Vulkan 1.2 is not available in your Vulkan header or its support in VMA has been disabled by a preprocessor macro.&quot;</span>);</div>
+<div class="line"><a name="l15179"></a><span class="lineno">15179</span>&#160;    }</div>
+<div class="line"><a name="l15180"></a><span class="lineno">15180</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l15181"></a><span class="lineno">15181</span>&#160;<span class="preprocessor">#if VMA_VULKAN_VERSION &lt; 1002000</span></div>
+<div class="line"><a name="l15182"></a><span class="lineno">15182</span>&#160;    <span class="keywordflow">if</span>(m_VulkanApiVersion &gt;= VK_MAKE_VERSION(1, 2, 0))</div>
+<div class="line"><a name="l15183"></a><span class="lineno">15183</span>&#160;    {</div>
+<div class="line"><a name="l15184"></a><span class="lineno">15184</span>&#160;        VMA_ASSERT(0 &amp;&amp; <span class="stringliteral">&quot;vulkanApiVersion &gt;= VK_API_VERSION_1_2 but required Vulkan version is disabled by preprocessor macros.&quot;</span>);</div>
+<div class="line"><a name="l15185"></a><span class="lineno">15185</span>&#160;    }</div>
+<div class="line"><a name="l15186"></a><span class="lineno">15186</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l15187"></a><span class="lineno">15187</span>&#160;<span class="preprocessor">#if VMA_VULKAN_VERSION &lt; 1001000</span></div>
+<div class="line"><a name="l15188"></a><span class="lineno">15188</span>&#160;    <span class="keywordflow">if</span>(m_VulkanApiVersion &gt;= VK_MAKE_VERSION(1, 1, 0))</div>
+<div class="line"><a name="l15189"></a><span class="lineno">15189</span>&#160;    {</div>
+<div class="line"><a name="l15190"></a><span class="lineno">15190</span>&#160;        VMA_ASSERT(0 &amp;&amp; <span class="stringliteral">&quot;vulkanApiVersion &gt;= VK_API_VERSION_1_1 but required Vulkan version is disabled by preprocessor macros.&quot;</span>);</div>
+<div class="line"><a name="l15191"></a><span class="lineno">15191</span>&#160;    }</div>
+<div class="line"><a name="l15192"></a><span class="lineno">15192</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l15193"></a><span class="lineno">15193</span>&#160; </div>
+<div class="line"><a name="l15194"></a><span class="lineno">15194</span>&#160;    memset(&amp;m_DeviceMemoryCallbacks, 0 ,<span class="keyword">sizeof</span>(m_DeviceMemoryCallbacks));</div>
+<div class="line"><a name="l15195"></a><span class="lineno">15195</span>&#160;    memset(&amp;m_PhysicalDeviceProperties, 0, <span class="keyword">sizeof</span>(m_PhysicalDeviceProperties));</div>
+<div class="line"><a name="l15196"></a><span class="lineno">15196</span>&#160;    memset(&amp;m_MemProps, 0, <span class="keyword">sizeof</span>(m_MemProps));</div>
+<div class="line"><a name="l15197"></a><span class="lineno">15197</span>&#160;        </div>
+<div class="line"><a name="l15198"></a><span class="lineno">15198</span>&#160;    memset(&amp;m_pBlockVectors, 0, <span class="keyword">sizeof</span>(m_pBlockVectors));</div>
+<div class="line"><a name="l15199"></a><span class="lineno">15199</span>&#160;    memset(&amp;m_pDedicatedAllocations, 0, <span class="keyword">sizeof</span>(m_pDedicatedAllocations));</div>
+<div class="line"><a name="l15200"></a><span class="lineno">15200</span>&#160;    memset(&amp;m_VulkanFunctions, 0, <span class="keyword">sizeof</span>(m_VulkanFunctions));</div>
+<div class="line"><a name="l15201"></a><span class="lineno">15201</span>&#160; </div>
+<div class="line"><a name="l15202"></a><span class="lineno">15202</span>&#160;    <span class="keywordflow">if</span>(pCreateInfo-&gt;<a class="code" href="struct_vma_allocator_create_info.html#af1380969b5e1ea4c3184a877892d260e">pDeviceMemoryCallbacks</a> != VMA_NULL)</div>
+<div class="line"><a name="l15203"></a><span class="lineno">15203</span>&#160;    {</div>
+<div class="line"><a name="l15204"></a><span class="lineno">15204</span>&#160;        m_DeviceMemoryCallbacks.<a class="code" href="struct_vma_device_memory_callbacks.html#a24052de0937ddd54015a2df0363903c6">pUserData</a> = pCreateInfo-&gt;<a class="code" href="struct_vma_allocator_create_info.html#af1380969b5e1ea4c3184a877892d260e">pDeviceMemoryCallbacks</a>-&gt;<a class="code" href="struct_vma_device_memory_callbacks.html#a24052de0937ddd54015a2df0363903c6">pUserData</a>;</div>
+<div class="line"><a name="l15205"></a><span class="lineno">15205</span>&#160;        m_DeviceMemoryCallbacks.<a class="code" href="struct_vma_device_memory_callbacks.html#a4f17f7b255101e733b44d5633aceabfb">pfnAllocate</a> = pCreateInfo-&gt;<a class="code" href="struct_vma_allocator_create_info.html#af1380969b5e1ea4c3184a877892d260e">pDeviceMemoryCallbacks</a>-&gt;<a class="code" href="struct_vma_device_memory_callbacks.html#a4f17f7b255101e733b44d5633aceabfb">pfnAllocate</a>;</div>
+<div class="line"><a name="l15206"></a><span class="lineno">15206</span>&#160;        m_DeviceMemoryCallbacks.<a class="code" href="struct_vma_device_memory_callbacks.html#abe8a3328bbc916f6f712fdb6b299444c">pfnFree</a> = pCreateInfo-&gt;<a class="code" href="struct_vma_allocator_create_info.html#af1380969b5e1ea4c3184a877892d260e">pDeviceMemoryCallbacks</a>-&gt;<a class="code" href="struct_vma_device_memory_callbacks.html#abe8a3328bbc916f6f712fdb6b299444c">pfnFree</a>;</div>
+<div class="line"><a name="l15207"></a><span class="lineno">15207</span>&#160;    }</div>
+<div class="line"><a name="l15208"></a><span class="lineno">15208</span>&#160; </div>
+<div class="line"><a name="l15209"></a><span class="lineno">15209</span>&#160;    ImportVulkanFunctions(pCreateInfo-&gt;<a class="code" href="struct_vma_allocator_create_info.html#a3dc197be3227da7338b1643f70db36bd">pVulkanFunctions</a>);</div>
+<div class="line"><a name="l15210"></a><span class="lineno">15210</span>&#160; </div>
+<div class="line"><a name="l15211"></a><span class="lineno">15211</span>&#160;    (*m_VulkanFunctions.vkGetPhysicalDeviceProperties)(m_PhysicalDevice, &amp;m_PhysicalDeviceProperties);</div>
+<div class="line"><a name="l15212"></a><span class="lineno">15212</span>&#160;    (*m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties)(m_PhysicalDevice, &amp;m_MemProps);</div>
+<div class="line"><a name="l15213"></a><span class="lineno">15213</span>&#160; </div>
+<div class="line"><a name="l15214"></a><span class="lineno">15214</span>&#160;    VMA_ASSERT(VmaIsPow2(VMA_DEBUG_ALIGNMENT));</div>
+<div class="line"><a name="l15215"></a><span class="lineno">15215</span>&#160;    VMA_ASSERT(VmaIsPow2(VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY));</div>
+<div class="line"><a name="l15216"></a><span class="lineno">15216</span>&#160;    VMA_ASSERT(VmaIsPow2(m_PhysicalDeviceProperties.limits.bufferImageGranularity));</div>
+<div class="line"><a name="l15217"></a><span class="lineno">15217</span>&#160;    VMA_ASSERT(VmaIsPow2(m_PhysicalDeviceProperties.limits.nonCoherentAtomSize));</div>
+<div class="line"><a name="l15218"></a><span class="lineno">15218</span>&#160; </div>
+<div class="line"><a name="l15219"></a><span class="lineno">15219</span>&#160;    m_PreferredLargeHeapBlockSize = (pCreateInfo-&gt;<a class="code" href="struct_vma_allocator_create_info.html#a8e4714298e3121cdd8b214a1ae7a637a">preferredLargeHeapBlockSize</a> != 0) ?</div>
+<div class="line"><a name="l15220"></a><span class="lineno">15220</span>&#160;        pCreateInfo-&gt;<a class="code" href="struct_vma_allocator_create_info.html#a8e4714298e3121cdd8b214a1ae7a637a">preferredLargeHeapBlockSize</a> : <span class="keyword">static_cast&lt;</span>VkDeviceSize<span class="keyword">&gt;</span>(VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE);</div>
+<div class="line"><a name="l15221"></a><span class="lineno">15221</span>&#160; </div>
+<div class="line"><a name="l15222"></a><span class="lineno">15222</span>&#160;    m_GlobalMemoryTypeBits = CalculateGlobalMemoryTypeBits();</div>
+<div class="line"><a name="l15223"></a><span class="lineno">15223</span>&#160; </div>
+<div class="line"><a name="l15224"></a><span class="lineno">15224</span>&#160;    <span class="keywordflow">if</span>(pCreateInfo-&gt;<a class="code" href="struct_vma_allocator_create_info.html#a31c192aa6cbffa33279f6d9f0c47c44b">pHeapSizeLimit</a> != VMA_NULL)</div>
+<div class="line"><a name="l15225"></a><span class="lineno">15225</span>&#160;    {</div>
+<div class="line"><a name="l15226"></a><span class="lineno">15226</span>&#160;        <span class="keywordflow">for</span>(uint32_t heapIndex = 0; heapIndex &lt; GetMemoryHeapCount(); ++heapIndex)</div>
+<div class="line"><a name="l15227"></a><span class="lineno">15227</span>&#160;        {</div>
+<div class="line"><a name="l15228"></a><span class="lineno">15228</span>&#160;            <span class="keyword">const</span> VkDeviceSize limit = pCreateInfo-&gt;<a class="code" href="struct_vma_allocator_create_info.html#a31c192aa6cbffa33279f6d9f0c47c44b">pHeapSizeLimit</a>[heapIndex];</div>
+<div class="line"><a name="l15229"></a><span class="lineno">15229</span>&#160;            <span class="keywordflow">if</span>(limit != VK_WHOLE_SIZE)</div>
+<div class="line"><a name="l15230"></a><span class="lineno">15230</span>&#160;            {</div>
+<div class="line"><a name="l15231"></a><span class="lineno">15231</span>&#160;                m_HeapSizeLimitMask |= 1u &lt;&lt; heapIndex;</div>
+<div class="line"><a name="l15232"></a><span class="lineno">15232</span>&#160;                <span class="keywordflow">if</span>(limit &lt; m_MemProps.memoryHeaps[heapIndex].size)</div>
+<div class="line"><a name="l15233"></a><span class="lineno">15233</span>&#160;                {</div>
+<div class="line"><a name="l15234"></a><span class="lineno">15234</span>&#160;                    m_MemProps.memoryHeaps[heapIndex].size = limit;</div>
+<div class="line"><a name="l15235"></a><span class="lineno">15235</span>&#160;                }</div>
+<div class="line"><a name="l15236"></a><span class="lineno">15236</span>&#160;            }</div>
+<div class="line"><a name="l15237"></a><span class="lineno">15237</span>&#160;        }</div>
+<div class="line"><a name="l15238"></a><span class="lineno">15238</span>&#160;    }</div>
+<div class="line"><a name="l15239"></a><span class="lineno">15239</span>&#160; </div>
+<div class="line"><a name="l15240"></a><span class="lineno">15240</span>&#160;    <span class="keywordflow">for</span>(uint32_t memTypeIndex = 0; memTypeIndex &lt; GetMemoryTypeCount(); ++memTypeIndex)</div>
+<div class="line"><a name="l15241"></a><span class="lineno">15241</span>&#160;    {</div>
+<div class="line"><a name="l15242"></a><span class="lineno">15242</span>&#160;        <span class="keyword">const</span> VkDeviceSize preferredBlockSize = CalcPreferredBlockSize(memTypeIndex);</div>
+<div class="line"><a name="l15243"></a><span class="lineno">15243</span>&#160; </div>
+<div class="line"><a name="l15244"></a><span class="lineno">15244</span>&#160;        m_pBlockVectors[memTypeIndex] = vma_new(<span class="keyword">this</span>, VmaBlockVector)(</div>
+<div class="line"><a name="l15245"></a><span class="lineno">15245</span>&#160;            <span class="keyword">this</span>,</div>
+<div class="line"><a name="l15246"></a><span class="lineno">15246</span>&#160;            VK_NULL_HANDLE, <span class="comment">// hParentPool</span></div>
+<div class="line"><a name="l15247"></a><span class="lineno">15247</span>&#160;            memTypeIndex,</div>
+<div class="line"><a name="l15248"></a><span class="lineno">15248</span>&#160;            preferredBlockSize,</div>
+<div class="line"><a name="l15249"></a><span class="lineno">15249</span>&#160;            0,</div>
+<div class="line"><a name="l15250"></a><span class="lineno">15250</span>&#160;            SIZE_MAX,</div>
+<div class="line"><a name="l15251"></a><span class="lineno">15251</span>&#160;            GetBufferImageGranularity(),</div>
+<div class="line"><a name="l15252"></a><span class="lineno">15252</span>&#160;            pCreateInfo-&gt;<a class="code" href="struct_vma_allocator_create_info.html#a21ea188dd212b8171cb9ecbed4a2a3a7">frameInUseCount</a>,</div>
+<div class="line"><a name="l15253"></a><span class="lineno">15253</span>&#160;            <span class="keyword">false</span>, <span class="comment">// explicitBlockSize</span></div>
+<div class="line"><a name="l15254"></a><span class="lineno">15254</span>&#160;            <span class="keyword">false</span>); <span class="comment">// linearAlgorithm</span></div>
+<div class="line"><a name="l15255"></a><span class="lineno">15255</span>&#160;        <span class="comment">// No need to call m_pBlockVectors[memTypeIndex][blockVectorTypeIndex]-&gt;CreateMinBlocks here,</span></div>
+<div class="line"><a name="l15256"></a><span class="lineno">15256</span>&#160;        <span class="comment">// becase minBlockCount is 0.</span></div>
+<div class="line"><a name="l15257"></a><span class="lineno">15257</span>&#160;        m_pDedicatedAllocations[memTypeIndex] = vma_new(<span class="keyword">this</span>, AllocationVectorType)(VmaStlAllocator&lt;VmaAllocation&gt;(GetAllocationCallbacks()));</div>
+<div class="line"><a name="l15258"></a><span class="lineno">15258</span>&#160; </div>
+<div class="line"><a name="l15259"></a><span class="lineno">15259</span>&#160;    }</div>
+<div class="line"><a name="l15260"></a><span class="lineno">15260</span>&#160;}</div>
+<div class="line"><a name="l15261"></a><span class="lineno">15261</span>&#160; </div>
+<div class="line"><a name="l15262"></a><span class="lineno">15262</span>&#160;VkResult VmaAllocator_T::Init(<span class="keyword">const</span> <a class="code" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a>* pCreateInfo)</div>
+<div class="line"><a name="l15263"></a><span class="lineno">15263</span>&#160;{</div>
+<div class="line"><a name="l15264"></a><span class="lineno">15264</span>&#160;    VkResult res = VK_SUCCESS;</div>
+<div class="line"><a name="l15265"></a><span class="lineno">15265</span>&#160; </div>
+<div class="line"><a name="l15266"></a><span class="lineno">15266</span>&#160;    <span class="keywordflow">if</span>(pCreateInfo-&gt;<a class="code" href="struct_vma_allocator_create_info.html#ace2aa4877b16a42b0b7673d4e26000ee">pRecordSettings</a> != VMA_NULL &amp;&amp;</div>
+<div class="line"><a name="l15267"></a><span class="lineno">15267</span>&#160;        !VmaStrIsEmpty(pCreateInfo-&gt;<a class="code" href="struct_vma_allocator_create_info.html#ace2aa4877b16a42b0b7673d4e26000ee">pRecordSettings</a>-&gt;<a class="code" href="struct_vma_record_settings.html#a6cb1fdbf6bcb610b68f2010dd629e89d">pFilePath</a>))</div>
+<div class="line"><a name="l15268"></a><span class="lineno">15268</span>&#160;    {</div>
+<div class="line"><a name="l15269"></a><span class="lineno">15269</span>&#160;<span class="preprocessor">#if VMA_RECORDING_ENABLED</span></div>
+<div class="line"><a name="l15270"></a><span class="lineno">15270</span>&#160;        m_pRecorder = vma_new(<span class="keyword">this</span>, VmaRecorder)();</div>
+<div class="line"><a name="l15271"></a><span class="lineno">15271</span>&#160;        res = m_pRecorder-&gt;Init(*pCreateInfo-&gt;<a class="code" href="struct_vma_allocator_create_info.html#ace2aa4877b16a42b0b7673d4e26000ee">pRecordSettings</a>, m_UseMutex);</div>
+<div class="line"><a name="l15272"></a><span class="lineno">15272</span>&#160;        <span class="keywordflow">if</span>(res != VK_SUCCESS)</div>
+<div class="line"><a name="l15273"></a><span class="lineno">15273</span>&#160;        {</div>
+<div class="line"><a name="l15274"></a><span class="lineno">15274</span>&#160;            <span class="keywordflow">return</span> res;</div>
+<div class="line"><a name="l15275"></a><span class="lineno">15275</span>&#160;        }</div>
+<div class="line"><a name="l15276"></a><span class="lineno">15276</span>&#160;        m_pRecorder-&gt;WriteConfiguration(</div>
+<div class="line"><a name="l15277"></a><span class="lineno">15277</span>&#160;            m_PhysicalDeviceProperties,</div>
+<div class="line"><a name="l15278"></a><span class="lineno">15278</span>&#160;            m_MemProps,</div>
+<div class="line"><a name="l15279"></a><span class="lineno">15279</span>&#160;            m_VulkanApiVersion,</div>
+<div class="line"><a name="l15280"></a><span class="lineno">15280</span>&#160;            m_UseKhrDedicatedAllocation,</div>
+<div class="line"><a name="l15281"></a><span class="lineno">15281</span>&#160;            m_UseKhrBindMemory2,</div>
+<div class="line"><a name="l15282"></a><span class="lineno">15282</span>&#160;            m_UseExtMemoryBudget,</div>
+<div class="line"><a name="l15283"></a><span class="lineno">15283</span>&#160;            m_UseAmdDeviceCoherentMemory);</div>
+<div class="line"><a name="l15284"></a><span class="lineno">15284</span>&#160;        m_pRecorder-&gt;RecordCreateAllocator(GetCurrentFrameIndex());</div>
+<div class="line"><a name="l15285"></a><span class="lineno">15285</span>&#160;<span class="preprocessor">#else</span></div>
+<div class="line"><a name="l15286"></a><span class="lineno">15286</span>&#160;        VMA_ASSERT(0 &amp;&amp; <span class="stringliteral">&quot;VmaAllocatorCreateInfo::pRecordSettings used, but not supported due to VMA_RECORDING_ENABLED not defined to 1.&quot;</span>);</div>
+<div class="line"><a name="l15287"></a><span class="lineno">15287</span>&#160;        <span class="keywordflow">return</span> VK_ERROR_FEATURE_NOT_PRESENT;</div>
+<div class="line"><a name="l15288"></a><span class="lineno">15288</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l15289"></a><span class="lineno">15289</span>&#160;    }</div>
+<div class="line"><a name="l15290"></a><span class="lineno">15290</span>&#160; </div>
+<div class="line"><a name="l15291"></a><span class="lineno">15291</span>&#160;<span class="preprocessor">#if VMA_MEMORY_BUDGET</span></div>
+<div class="line"><a name="l15292"></a><span class="lineno">15292</span>&#160;    <span class="keywordflow">if</span>(m_UseExtMemoryBudget)</div>
+<div class="line"><a name="l15293"></a><span class="lineno">15293</span>&#160;    {</div>
+<div class="line"><a name="l15294"></a><span class="lineno">15294</span>&#160;        UpdateVulkanBudget();</div>
+<div class="line"><a name="l15295"></a><span class="lineno">15295</span>&#160;    }</div>
+<div class="line"><a name="l15296"></a><span class="lineno">15296</span>&#160;<span class="preprocessor">#endif // #if VMA_MEMORY_BUDGET</span></div>
+<div class="line"><a name="l15297"></a><span class="lineno">15297</span>&#160; </div>
+<div class="line"><a name="l15298"></a><span class="lineno">15298</span>&#160;    <span class="keywordflow">return</span> res;</div>
+<div class="line"><a name="l15299"></a><span class="lineno">15299</span>&#160;}</div>
+<div class="line"><a name="l15300"></a><span class="lineno">15300</span>&#160; </div>
+<div class="line"><a name="l15301"></a><span class="lineno">15301</span>&#160;VmaAllocator_T::~VmaAllocator_T()</div>
+<div class="line"><a name="l15302"></a><span class="lineno">15302</span>&#160;{</div>
+<div class="line"><a name="l15303"></a><span class="lineno">15303</span>&#160;<span class="preprocessor">#if VMA_RECORDING_ENABLED</span></div>
+<div class="line"><a name="l15304"></a><span class="lineno">15304</span>&#160;    <span class="keywordflow">if</span>(m_pRecorder != VMA_NULL)</div>
+<div class="line"><a name="l15305"></a><span class="lineno">15305</span>&#160;    {</div>
+<div class="line"><a name="l15306"></a><span class="lineno">15306</span>&#160;        m_pRecorder-&gt;RecordDestroyAllocator(GetCurrentFrameIndex());</div>
+<div class="line"><a name="l15307"></a><span class="lineno">15307</span>&#160;        vma_delete(<span class="keyword">this</span>, m_pRecorder);</div>
+<div class="line"><a name="l15308"></a><span class="lineno">15308</span>&#160;    }</div>
+<div class="line"><a name="l15309"></a><span class="lineno">15309</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l15310"></a><span class="lineno">15310</span>&#160;    </div>
+<div class="line"><a name="l15311"></a><span class="lineno">15311</span>&#160;    VMA_ASSERT(m_Pools.empty());</div>
+<div class="line"><a name="l15312"></a><span class="lineno">15312</span>&#160; </div>
+<div class="line"><a name="l15313"></a><span class="lineno">15313</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = GetMemoryTypeCount(); i--; )</div>
+<div class="line"><a name="l15314"></a><span class="lineno">15314</span>&#160;    {</div>
+<div class="line"><a name="l15315"></a><span class="lineno">15315</span>&#160;        <span class="keywordflow">if</span>(m_pDedicatedAllocations[i] != VMA_NULL &amp;&amp; !m_pDedicatedAllocations[i]-&gt;empty())</div>
+<div class="line"><a name="l15316"></a><span class="lineno">15316</span>&#160;        {</div>
+<div class="line"><a name="l15317"></a><span class="lineno">15317</span>&#160;            VMA_ASSERT(0 &amp;&amp; <span class="stringliteral">&quot;Unfreed dedicated allocations found.&quot;</span>);</div>
+<div class="line"><a name="l15318"></a><span class="lineno">15318</span>&#160;        }</div>
+<div class="line"><a name="l15319"></a><span class="lineno">15319</span>&#160; </div>
+<div class="line"><a name="l15320"></a><span class="lineno">15320</span>&#160;        vma_delete(<span class="keyword">this</span>, m_pDedicatedAllocations[i]);</div>
+<div class="line"><a name="l15321"></a><span class="lineno">15321</span>&#160;        vma_delete(<span class="keyword">this</span>, m_pBlockVectors[i]);</div>
+<div class="line"><a name="l15322"></a><span class="lineno">15322</span>&#160;    }</div>
+<div class="line"><a name="l15323"></a><span class="lineno">15323</span>&#160;}</div>
+<div class="line"><a name="l15324"></a><span class="lineno">15324</span>&#160; </div>
+<div class="line"><a name="l15325"></a><span class="lineno">15325</span>&#160;<span class="keywordtype">void</span> VmaAllocator_T::ImportVulkanFunctions(<span class="keyword">const</span> <a class="code" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a>* pVulkanFunctions)</div>
+<div class="line"><a name="l15326"></a><span class="lineno">15326</span>&#160;{</div>
+<div class="line"><a name="l15327"></a><span class="lineno">15327</span>&#160;<span class="preprocessor">#if VMA_STATIC_VULKAN_FUNCTIONS == 1</span></div>
+<div class="line"><a name="l15328"></a><span class="lineno">15328</span>&#160;    ImportVulkanFunctions_Static();</div>
+<div class="line"><a name="l15329"></a><span class="lineno">15329</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l15330"></a><span class="lineno">15330</span>&#160; </div>
+<div class="line"><a name="l15331"></a><span class="lineno">15331</span>&#160;    <span class="keywordflow">if</span>(pVulkanFunctions != VMA_NULL)</div>
+<div class="line"><a name="l15332"></a><span class="lineno">15332</span>&#160;    {</div>
+<div class="line"><a name="l15333"></a><span class="lineno">15333</span>&#160;        ImportVulkanFunctions_Custom(pVulkanFunctions);</div>
+<div class="line"><a name="l15334"></a><span class="lineno">15334</span>&#160;    }</div>
+<div class="line"><a name="l15335"></a><span class="lineno">15335</span>&#160; </div>
+<div class="line"><a name="l15336"></a><span class="lineno">15336</span>&#160;<span class="preprocessor">#if VMA_DYNAMIC_VULKAN_FUNCTIONS == 1</span></div>
+<div class="line"><a name="l15337"></a><span class="lineno">15337</span>&#160;    ImportVulkanFunctions_Dynamic();</div>
+<div class="line"><a name="l15338"></a><span class="lineno">15338</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l15339"></a><span class="lineno">15339</span>&#160; </div>
+<div class="line"><a name="l15340"></a><span class="lineno">15340</span>&#160;    ValidateVulkanFunctions();</div>
+<div class="line"><a name="l15341"></a><span class="lineno">15341</span>&#160;}</div>
+<div class="line"><a name="l15342"></a><span class="lineno">15342</span>&#160; </div>
+<div class="line"><a name="l15343"></a><span class="lineno">15343</span>&#160;<span class="preprocessor">#if VMA_STATIC_VULKAN_FUNCTIONS == 1</span></div>
+<div class="line"><a name="l15344"></a><span class="lineno">15344</span>&#160; </div>
+<div class="line"><a name="l15345"></a><span class="lineno">15345</span>&#160;<span class="keywordtype">void</span> VmaAllocator_T::ImportVulkanFunctions_Static()</div>
+<div class="line"><a name="l15346"></a><span class="lineno">15346</span>&#160;{</div>
+<div class="line"><a name="l15347"></a><span class="lineno">15347</span>&#160;    <span class="comment">// Vulkan 1.0</span></div>
+<div class="line"><a name="l15348"></a><span class="lineno">15348</span>&#160;    m_VulkanFunctions.vkGetPhysicalDeviceProperties = (PFN_vkGetPhysicalDeviceProperties)vkGetPhysicalDeviceProperties;</div>
+<div class="line"><a name="l15349"></a><span class="lineno">15349</span>&#160;    m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties = (PFN_vkGetPhysicalDeviceMemoryProperties)vkGetPhysicalDeviceMemoryProperties;</div>
+<div class="line"><a name="l15350"></a><span class="lineno">15350</span>&#160;    m_VulkanFunctions.vkAllocateMemory = (PFN_vkAllocateMemory)vkAllocateMemory;</div>
+<div class="line"><a name="l15351"></a><span class="lineno">15351</span>&#160;    m_VulkanFunctions.vkFreeMemory = (PFN_vkFreeMemory)vkFreeMemory;</div>
+<div class="line"><a name="l15352"></a><span class="lineno">15352</span>&#160;    m_VulkanFunctions.vkMapMemory = (PFN_vkMapMemory)vkMapMemory;</div>
+<div class="line"><a name="l15353"></a><span class="lineno">15353</span>&#160;    m_VulkanFunctions.vkUnmapMemory = (PFN_vkUnmapMemory)vkUnmapMemory;</div>
+<div class="line"><a name="l15354"></a><span class="lineno">15354</span>&#160;    m_VulkanFunctions.vkFlushMappedMemoryRanges = (PFN_vkFlushMappedMemoryRanges)vkFlushMappedMemoryRanges;</div>
+<div class="line"><a name="l15355"></a><span class="lineno">15355</span>&#160;    m_VulkanFunctions.vkInvalidateMappedMemoryRanges = (PFN_vkInvalidateMappedMemoryRanges)vkInvalidateMappedMemoryRanges;</div>
+<div class="line"><a name="l15356"></a><span class="lineno">15356</span>&#160;    m_VulkanFunctions.vkBindBufferMemory = (PFN_vkBindBufferMemory)vkBindBufferMemory;</div>
+<div class="line"><a name="l15357"></a><span class="lineno">15357</span>&#160;    m_VulkanFunctions.vkBindImageMemory = (PFN_vkBindImageMemory)vkBindImageMemory;</div>
+<div class="line"><a name="l15358"></a><span class="lineno">15358</span>&#160;    m_VulkanFunctions.vkGetBufferMemoryRequirements = (PFN_vkGetBufferMemoryRequirements)vkGetBufferMemoryRequirements;</div>
+<div class="line"><a name="l15359"></a><span class="lineno">15359</span>&#160;    m_VulkanFunctions.vkGetImageMemoryRequirements = (PFN_vkGetImageMemoryRequirements)vkGetImageMemoryRequirements;</div>
+<div class="line"><a name="l15360"></a><span class="lineno">15360</span>&#160;    m_VulkanFunctions.vkCreateBuffer = (PFN_vkCreateBuffer)vkCreateBuffer;</div>
+<div class="line"><a name="l15361"></a><span class="lineno">15361</span>&#160;    m_VulkanFunctions.vkDestroyBuffer = (PFN_vkDestroyBuffer)vkDestroyBuffer;</div>
+<div class="line"><a name="l15362"></a><span class="lineno">15362</span>&#160;    m_VulkanFunctions.vkCreateImage = (PFN_vkCreateImage)vkCreateImage;</div>
+<div class="line"><a name="l15363"></a><span class="lineno">15363</span>&#160;    m_VulkanFunctions.vkDestroyImage = (PFN_vkDestroyImage)vkDestroyImage;</div>
+<div class="line"><a name="l15364"></a><span class="lineno">15364</span>&#160;    m_VulkanFunctions.vkCmdCopyBuffer = (PFN_vkCmdCopyBuffer)vkCmdCopyBuffer;</div>
+<div class="line"><a name="l15365"></a><span class="lineno">15365</span>&#160; </div>
+<div class="line"><a name="l15366"></a><span class="lineno">15366</span>&#160;    <span class="comment">// Vulkan 1.1</span></div>
+<div class="line"><a name="l15367"></a><span class="lineno">15367</span>&#160;<span class="preprocessor">#if VMA_VULKAN_VERSION &gt;= 1001000</span></div>
+<div class="line"><a name="l15368"></a><span class="lineno">15368</span>&#160;    <span class="keywordflow">if</span>(m_VulkanApiVersion &gt;= VK_MAKE_VERSION(1, 1, 0))</div>
+<div class="line"><a name="l15369"></a><span class="lineno">15369</span>&#160;    {</div>
+<div class="line"><a name="l15370"></a><span class="lineno">15370</span>&#160;        m_VulkanFunctions.vkGetBufferMemoryRequirements2KHR = (PFN_vkGetBufferMemoryRequirements2)vkGetBufferMemoryRequirements2;</div>
+<div class="line"><a name="l15371"></a><span class="lineno">15371</span>&#160;        m_VulkanFunctions.vkGetImageMemoryRequirements2KHR = (PFN_vkGetImageMemoryRequirements2)vkGetImageMemoryRequirements2;</div>
+<div class="line"><a name="l15372"></a><span class="lineno">15372</span>&#160;        m_VulkanFunctions.vkBindBufferMemory2KHR = (PFN_vkBindBufferMemory2)vkBindBufferMemory2;</div>
+<div class="line"><a name="l15373"></a><span class="lineno">15373</span>&#160;        m_VulkanFunctions.vkBindImageMemory2KHR = (PFN_vkBindImageMemory2)vkBindImageMemory2;</div>
+<div class="line"><a name="l15374"></a><span class="lineno">15374</span>&#160;        m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties2KHR = (PFN_vkGetPhysicalDeviceMemoryProperties2)vkGetPhysicalDeviceMemoryProperties2;</div>
+<div class="line"><a name="l15375"></a><span class="lineno">15375</span>&#160;    }</div>
+<div class="line"><a name="l15376"></a><span class="lineno">15376</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l15377"></a><span class="lineno">15377</span>&#160;}</div>
+<div class="line"><a name="l15378"></a><span class="lineno">15378</span>&#160; </div>
+<div class="line"><a name="l15379"></a><span class="lineno">15379</span>&#160;<span class="preprocessor">#endif // #if VMA_STATIC_VULKAN_FUNCTIONS == 1</span></div>
+<div class="line"><a name="l15380"></a><span class="lineno">15380</span>&#160; </div>
+<div class="line"><a name="l15381"></a><span class="lineno">15381</span>&#160;<span class="keywordtype">void</span> VmaAllocator_T::ImportVulkanFunctions_Custom(<span class="keyword">const</span> <a class="code" href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a>* pVulkanFunctions)</div>
+<div class="line"><a name="l15382"></a><span class="lineno">15382</span>&#160;{</div>
+<div class="line"><a name="l15383"></a><span class="lineno">15383</span>&#160;    VMA_ASSERT(pVulkanFunctions != VMA_NULL);</div>
+<div class="line"><a name="l15384"></a><span class="lineno">15384</span>&#160; </div>
+<div class="line"><a name="l15385"></a><span class="lineno">15385</span>&#160;<span class="preprocessor">#define VMA_COPY_IF_NOT_NULL(funcName) \</span></div>
+<div class="line"><a name="l15386"></a><span class="lineno">15386</span>&#160;<span class="preprocessor">    if(pVulkanFunctions-&gt;funcName != VMA_NULL) m_VulkanFunctions.funcName = pVulkanFunctions-&gt;funcName;</span></div>
+<div class="line"><a name="l15387"></a><span class="lineno">15387</span>&#160; </div>
+<div class="line"><a name="l15388"></a><span class="lineno">15388</span>&#160;    VMA_COPY_IF_NOT_NULL(vkGetPhysicalDeviceProperties);</div>
+<div class="line"><a name="l15389"></a><span class="lineno">15389</span>&#160;    VMA_COPY_IF_NOT_NULL(vkGetPhysicalDeviceMemoryProperties);</div>
+<div class="line"><a name="l15390"></a><span class="lineno">15390</span>&#160;    VMA_COPY_IF_NOT_NULL(vkAllocateMemory);</div>
+<div class="line"><a name="l15391"></a><span class="lineno">15391</span>&#160;    VMA_COPY_IF_NOT_NULL(vkFreeMemory);</div>
+<div class="line"><a name="l15392"></a><span class="lineno">15392</span>&#160;    VMA_COPY_IF_NOT_NULL(vkMapMemory);</div>
+<div class="line"><a name="l15393"></a><span class="lineno">15393</span>&#160;    VMA_COPY_IF_NOT_NULL(vkUnmapMemory);</div>
+<div class="line"><a name="l15394"></a><span class="lineno">15394</span>&#160;    VMA_COPY_IF_NOT_NULL(vkFlushMappedMemoryRanges);</div>
+<div class="line"><a name="l15395"></a><span class="lineno">15395</span>&#160;    VMA_COPY_IF_NOT_NULL(vkInvalidateMappedMemoryRanges);</div>
+<div class="line"><a name="l15396"></a><span class="lineno">15396</span>&#160;    VMA_COPY_IF_NOT_NULL(vkBindBufferMemory);</div>
+<div class="line"><a name="l15397"></a><span class="lineno">15397</span>&#160;    VMA_COPY_IF_NOT_NULL(vkBindImageMemory);</div>
+<div class="line"><a name="l15398"></a><span class="lineno">15398</span>&#160;    VMA_COPY_IF_NOT_NULL(vkGetBufferMemoryRequirements);</div>
+<div class="line"><a name="l15399"></a><span class="lineno">15399</span>&#160;    VMA_COPY_IF_NOT_NULL(vkGetImageMemoryRequirements);</div>
+<div class="line"><a name="l15400"></a><span class="lineno">15400</span>&#160;    VMA_COPY_IF_NOT_NULL(vkCreateBuffer);</div>
+<div class="line"><a name="l15401"></a><span class="lineno">15401</span>&#160;    VMA_COPY_IF_NOT_NULL(vkDestroyBuffer);</div>
+<div class="line"><a name="l15402"></a><span class="lineno">15402</span>&#160;    VMA_COPY_IF_NOT_NULL(vkCreateImage);</div>
+<div class="line"><a name="l15403"></a><span class="lineno">15403</span>&#160;    VMA_COPY_IF_NOT_NULL(vkDestroyImage);</div>
+<div class="line"><a name="l15404"></a><span class="lineno">15404</span>&#160;    VMA_COPY_IF_NOT_NULL(vkCmdCopyBuffer);</div>
+<div class="line"><a name="l15405"></a><span class="lineno">15405</span>&#160; </div>
+<div class="line"><a name="l15406"></a><span class="lineno">15406</span>&#160;<span class="preprocessor">#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION &gt;= 1001000</span></div>
+<div class="line"><a name="l15407"></a><span class="lineno">15407</span>&#160;    VMA_COPY_IF_NOT_NULL(vkGetBufferMemoryRequirements2KHR);</div>
+<div class="line"><a name="l15408"></a><span class="lineno">15408</span>&#160;    VMA_COPY_IF_NOT_NULL(vkGetImageMemoryRequirements2KHR);</div>
+<div class="line"><a name="l15409"></a><span class="lineno">15409</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l15410"></a><span class="lineno">15410</span>&#160; </div>
+<div class="line"><a name="l15411"></a><span class="lineno">15411</span>&#160;<span class="preprocessor">#if VMA_BIND_MEMORY2 || VMA_VULKAN_VERSION &gt;= 1001000</span></div>
+<div class="line"><a name="l15412"></a><span class="lineno">15412</span>&#160;    VMA_COPY_IF_NOT_NULL(vkBindBufferMemory2KHR);</div>
+<div class="line"><a name="l15413"></a><span class="lineno">15413</span>&#160;    VMA_COPY_IF_NOT_NULL(vkBindImageMemory2KHR);</div>
+<div class="line"><a name="l15414"></a><span class="lineno">15414</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l15415"></a><span class="lineno">15415</span>&#160; </div>
+<div class="line"><a name="l15416"></a><span class="lineno">15416</span>&#160;<span class="preprocessor">#if VMA_MEMORY_BUDGET</span></div>
+<div class="line"><a name="l15417"></a><span class="lineno">15417</span>&#160;    VMA_COPY_IF_NOT_NULL(vkGetPhysicalDeviceMemoryProperties2KHR);</div>
+<div class="line"><a name="l15418"></a><span class="lineno">15418</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l15419"></a><span class="lineno">15419</span>&#160; </div>
+<div class="line"><a name="l15420"></a><span class="lineno">15420</span>&#160;<span class="preprocessor">#undef VMA_COPY_IF_NOT_NULL</span></div>
+<div class="line"><a name="l15421"></a><span class="lineno">15421</span>&#160;}</div>
+<div class="line"><a name="l15422"></a><span class="lineno">15422</span>&#160; </div>
+<div class="line"><a name="l15423"></a><span class="lineno">15423</span>&#160;<span class="keywordtype">void</span> VmaAllocator_T::ImportVulkanFunctions_Dynamic()</div>
+<div class="line"><a name="l15424"></a><span class="lineno">15424</span>&#160;{</div>
+<div class="line"><a name="l15425"></a><span class="lineno">15425</span>&#160;<span class="preprocessor">#define VMA_FETCH_INSTANCE_FUNC(memberName, functionPointerType, functionNameString) \</span></div>
+<div class="line"><a name="l15426"></a><span class="lineno">15426</span>&#160;<span class="preprocessor">    if(m_VulkanFunctions.memberName == VMA_NULL) \</span></div>
+<div class="line"><a name="l15427"></a><span class="lineno">15427</span>&#160;<span class="preprocessor">        m_VulkanFunctions.memberName = \</span></div>
+<div class="line"><a name="l15428"></a><span class="lineno">15428</span>&#160;<span class="preprocessor">            (functionPointerType)vkGetInstanceProcAddr(m_hInstance, functionNameString);</span></div>
+<div class="line"><a name="l15429"></a><span class="lineno">15429</span>&#160;<span class="preprocessor">#define VMA_FETCH_DEVICE_FUNC(memberName, functionPointerType, functionNameString) \</span></div>
+<div class="line"><a name="l15430"></a><span class="lineno">15430</span>&#160;<span class="preprocessor">    if(m_VulkanFunctions.memberName == VMA_NULL) \</span></div>
+<div class="line"><a name="l15431"></a><span class="lineno">15431</span>&#160;<span class="preprocessor">        m_VulkanFunctions.memberName = \</span></div>
+<div class="line"><a name="l15432"></a><span class="lineno">15432</span>&#160;<span class="preprocessor">            (functionPointerType)vkGetDeviceProcAddr(m_hDevice, functionNameString);</span></div>
+<div class="line"><a name="l15433"></a><span class="lineno">15433</span>&#160; </div>
+<div class="line"><a name="l15434"></a><span class="lineno">15434</span>&#160;    VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceProperties, PFN_vkGetPhysicalDeviceProperties, <span class="stringliteral">&quot;vkGetPhysicalDeviceProperties&quot;</span>);</div>
+<div class="line"><a name="l15435"></a><span class="lineno">15435</span>&#160;    VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties, PFN_vkGetPhysicalDeviceMemoryProperties, <span class="stringliteral">&quot;vkGetPhysicalDeviceMemoryProperties&quot;</span>);</div>
+<div class="line"><a name="l15436"></a><span class="lineno">15436</span>&#160;    VMA_FETCH_DEVICE_FUNC(vkAllocateMemory, PFN_vkAllocateMemory, <span class="stringliteral">&quot;vkAllocateMemory&quot;</span>);</div>
+<div class="line"><a name="l15437"></a><span class="lineno">15437</span>&#160;    VMA_FETCH_DEVICE_FUNC(vkFreeMemory, PFN_vkFreeMemory, <span class="stringliteral">&quot;vkFreeMemory&quot;</span>);</div>
+<div class="line"><a name="l15438"></a><span class="lineno">15438</span>&#160;    VMA_FETCH_DEVICE_FUNC(vkMapMemory, PFN_vkMapMemory, <span class="stringliteral">&quot;vkMapMemory&quot;</span>);</div>
+<div class="line"><a name="l15439"></a><span class="lineno">15439</span>&#160;    VMA_FETCH_DEVICE_FUNC(vkUnmapMemory, PFN_vkUnmapMemory, <span class="stringliteral">&quot;vkUnmapMemory&quot;</span>);</div>
+<div class="line"><a name="l15440"></a><span class="lineno">15440</span>&#160;    VMA_FETCH_DEVICE_FUNC(vkFlushMappedMemoryRanges, PFN_vkFlushMappedMemoryRanges, <span class="stringliteral">&quot;vkFlushMappedMemoryRanges&quot;</span>);</div>
+<div class="line"><a name="l15441"></a><span class="lineno">15441</span>&#160;    VMA_FETCH_DEVICE_FUNC(vkInvalidateMappedMemoryRanges, PFN_vkInvalidateMappedMemoryRanges, <span class="stringliteral">&quot;vkInvalidateMappedMemoryRanges&quot;</span>);</div>
+<div class="line"><a name="l15442"></a><span class="lineno">15442</span>&#160;    VMA_FETCH_DEVICE_FUNC(vkBindBufferMemory, PFN_vkBindBufferMemory, <span class="stringliteral">&quot;vkBindBufferMemory&quot;</span>);</div>
+<div class="line"><a name="l15443"></a><span class="lineno">15443</span>&#160;    VMA_FETCH_DEVICE_FUNC(vkBindImageMemory, PFN_vkBindImageMemory, <span class="stringliteral">&quot;vkBindImageMemory&quot;</span>);</div>
+<div class="line"><a name="l15444"></a><span class="lineno">15444</span>&#160;    VMA_FETCH_DEVICE_FUNC(vkGetBufferMemoryRequirements, PFN_vkGetBufferMemoryRequirements, <span class="stringliteral">&quot;vkGetBufferMemoryRequirements&quot;</span>);</div>
+<div class="line"><a name="l15445"></a><span class="lineno">15445</span>&#160;    VMA_FETCH_DEVICE_FUNC(vkGetImageMemoryRequirements, PFN_vkGetImageMemoryRequirements, <span class="stringliteral">&quot;vkGetImageMemoryRequirements&quot;</span>);</div>
+<div class="line"><a name="l15446"></a><span class="lineno">15446</span>&#160;    VMA_FETCH_DEVICE_FUNC(vkCreateBuffer, PFN_vkCreateBuffer, <span class="stringliteral">&quot;vkCreateBuffer&quot;</span>);</div>
+<div class="line"><a name="l15447"></a><span class="lineno">15447</span>&#160;    VMA_FETCH_DEVICE_FUNC(vkDestroyBuffer, PFN_vkDestroyBuffer, <span class="stringliteral">&quot;vkDestroyBuffer&quot;</span>);</div>
+<div class="line"><a name="l15448"></a><span class="lineno">15448</span>&#160;    VMA_FETCH_DEVICE_FUNC(vkCreateImage, PFN_vkCreateImage, <span class="stringliteral">&quot;vkCreateImage&quot;</span>);</div>
+<div class="line"><a name="l15449"></a><span class="lineno">15449</span>&#160;    VMA_FETCH_DEVICE_FUNC(vkDestroyImage, PFN_vkDestroyImage, <span class="stringliteral">&quot;vkDestroyImage&quot;</span>);</div>
+<div class="line"><a name="l15450"></a><span class="lineno">15450</span>&#160;    VMA_FETCH_DEVICE_FUNC(vkCmdCopyBuffer, PFN_vkCmdCopyBuffer, <span class="stringliteral">&quot;vkCmdCopyBuffer&quot;</span>);</div>
+<div class="line"><a name="l15451"></a><span class="lineno">15451</span>&#160; </div>
+<div class="line"><a name="l15452"></a><span class="lineno">15452</span>&#160;<span class="preprocessor">#if VMA_DEDICATED_ALLOCATION</span></div>
+<div class="line"><a name="l15453"></a><span class="lineno">15453</span>&#160;    <span class="keywordflow">if</span>(m_UseKhrDedicatedAllocation)</div>
+<div class="line"><a name="l15454"></a><span class="lineno">15454</span>&#160;    {</div>
+<div class="line"><a name="l15455"></a><span class="lineno">15455</span>&#160;        VMA_FETCH_DEVICE_FUNC(vkGetBufferMemoryRequirements2KHR, PFN_vkGetBufferMemoryRequirements2KHR, <span class="stringliteral">&quot;vkGetBufferMemoryRequirements2KHR&quot;</span>);</div>
+<div class="line"><a name="l15456"></a><span class="lineno">15456</span>&#160;        VMA_FETCH_DEVICE_FUNC(vkGetImageMemoryRequirements2KHR, PFN_vkGetImageMemoryRequirements2KHR, <span class="stringliteral">&quot;vkGetImageMemoryRequirements2KHR&quot;</span>);</div>
+<div class="line"><a name="l15457"></a><span class="lineno">15457</span>&#160;    }</div>
+<div class="line"><a name="l15458"></a><span class="lineno">15458</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l15459"></a><span class="lineno">15459</span>&#160; </div>
+<div class="line"><a name="l15460"></a><span class="lineno">15460</span>&#160;<span class="preprocessor">#if VMA_BIND_MEMORY2</span></div>
+<div class="line"><a name="l15461"></a><span class="lineno">15461</span>&#160;    <span class="keywordflow">if</span>(m_UseKhrBindMemory2)</div>
+<div class="line"><a name="l15462"></a><span class="lineno">15462</span>&#160;    {</div>
+<div class="line"><a name="l15463"></a><span class="lineno">15463</span>&#160;        VMA_FETCH_DEVICE_FUNC(vkBindBufferMemory2KHR, PFN_vkBindBufferMemory2KHR, <span class="stringliteral">&quot;vkBindBufferMemory2KHR&quot;</span>);</div>
+<div class="line"><a name="l15464"></a><span class="lineno">15464</span>&#160;        VMA_FETCH_DEVICE_FUNC(vkBindImageMemory2KHR, PFN_vkBindImageMemory2KHR, <span class="stringliteral">&quot;vkBindImageMemory2KHR&quot;</span>);</div>
+<div class="line"><a name="l15465"></a><span class="lineno">15465</span>&#160;    }</div>
+<div class="line"><a name="l15466"></a><span class="lineno">15466</span>&#160;<span class="preprocessor">#endif // #if VMA_BIND_MEMORY2</span></div>
+<div class="line"><a name="l15467"></a><span class="lineno">15467</span>&#160; </div>
+<div class="line"><a name="l15468"></a><span class="lineno">15468</span>&#160;<span class="preprocessor">#if VMA_MEMORY_BUDGET</span></div>
+<div class="line"><a name="l15469"></a><span class="lineno">15469</span>&#160;    <span class="keywordflow">if</span>(m_UseExtMemoryBudget &amp;&amp; m_VulkanApiVersion &lt; VK_MAKE_VERSION(1, 1, 0))</div>
+<div class="line"><a name="l15470"></a><span class="lineno">15470</span>&#160;    {</div>
+<div class="line"><a name="l15471"></a><span class="lineno">15471</span>&#160;        VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2KHR, <span class="stringliteral">&quot;vkGetPhysicalDeviceMemoryProperties2KHR&quot;</span>);</div>
+<div class="line"><a name="l15472"></a><span class="lineno">15472</span>&#160;    }</div>
+<div class="line"><a name="l15473"></a><span class="lineno">15473</span>&#160;<span class="preprocessor">#endif // #if VMA_MEMORY_BUDGET</span></div>
+<div class="line"><a name="l15474"></a><span class="lineno">15474</span>&#160; </div>
+<div class="line"><a name="l15475"></a><span class="lineno">15475</span>&#160;<span class="preprocessor">#undef VMA_FETCH_DEVICE_FUNC</span></div>
+<div class="line"><a name="l15476"></a><span class="lineno">15476</span>&#160;<span class="preprocessor">#undef VMA_FETCH_INSTANCE_FUNC</span></div>
+<div class="line"><a name="l15477"></a><span class="lineno">15477</span>&#160;}</div>
+<div class="line"><a name="l15478"></a><span class="lineno">15478</span>&#160; </div>
+<div class="line"><a name="l15479"></a><span class="lineno">15479</span>&#160;<span class="keywordtype">void</span> VmaAllocator_T::ValidateVulkanFunctions()</div>
+<div class="line"><a name="l15480"></a><span class="lineno">15480</span>&#160;{</div>
+<div class="line"><a name="l15481"></a><span class="lineno">15481</span>&#160;    VMA_ASSERT(m_VulkanFunctions.vkGetPhysicalDeviceProperties != VMA_NULL);</div>
+<div class="line"><a name="l15482"></a><span class="lineno">15482</span>&#160;    VMA_ASSERT(m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties != VMA_NULL);</div>
+<div class="line"><a name="l15483"></a><span class="lineno">15483</span>&#160;    VMA_ASSERT(m_VulkanFunctions.vkAllocateMemory != VMA_NULL);</div>
+<div class="line"><a name="l15484"></a><span class="lineno">15484</span>&#160;    VMA_ASSERT(m_VulkanFunctions.vkFreeMemory != VMA_NULL);</div>
+<div class="line"><a name="l15485"></a><span class="lineno">15485</span>&#160;    VMA_ASSERT(m_VulkanFunctions.vkMapMemory != VMA_NULL);</div>
+<div class="line"><a name="l15486"></a><span class="lineno">15486</span>&#160;    VMA_ASSERT(m_VulkanFunctions.vkUnmapMemory != VMA_NULL);</div>
+<div class="line"><a name="l15487"></a><span class="lineno">15487</span>&#160;    VMA_ASSERT(m_VulkanFunctions.vkFlushMappedMemoryRanges != VMA_NULL);</div>
+<div class="line"><a name="l15488"></a><span class="lineno">15488</span>&#160;    VMA_ASSERT(m_VulkanFunctions.vkInvalidateMappedMemoryRanges != VMA_NULL);</div>
+<div class="line"><a name="l15489"></a><span class="lineno">15489</span>&#160;    VMA_ASSERT(m_VulkanFunctions.vkBindBufferMemory != VMA_NULL);</div>
+<div class="line"><a name="l15490"></a><span class="lineno">15490</span>&#160;    VMA_ASSERT(m_VulkanFunctions.vkBindImageMemory != VMA_NULL);</div>
+<div class="line"><a name="l15491"></a><span class="lineno">15491</span>&#160;    VMA_ASSERT(m_VulkanFunctions.vkGetBufferMemoryRequirements != VMA_NULL);</div>
+<div class="line"><a name="l15492"></a><span class="lineno">15492</span>&#160;    VMA_ASSERT(m_VulkanFunctions.vkGetImageMemoryRequirements != VMA_NULL);</div>
+<div class="line"><a name="l15493"></a><span class="lineno">15493</span>&#160;    VMA_ASSERT(m_VulkanFunctions.vkCreateBuffer != VMA_NULL);</div>
+<div class="line"><a name="l15494"></a><span class="lineno">15494</span>&#160;    VMA_ASSERT(m_VulkanFunctions.vkDestroyBuffer != VMA_NULL);</div>
+<div class="line"><a name="l15495"></a><span class="lineno">15495</span>&#160;    VMA_ASSERT(m_VulkanFunctions.vkCreateImage != VMA_NULL);</div>
+<div class="line"><a name="l15496"></a><span class="lineno">15496</span>&#160;    VMA_ASSERT(m_VulkanFunctions.vkDestroyImage != VMA_NULL);</div>
+<div class="line"><a name="l15497"></a><span class="lineno">15497</span>&#160;    VMA_ASSERT(m_VulkanFunctions.vkCmdCopyBuffer != VMA_NULL);</div>
+<div class="line"><a name="l15498"></a><span class="lineno">15498</span>&#160; </div>
+<div class="line"><a name="l15499"></a><span class="lineno">15499</span>&#160;<span class="preprocessor">#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION &gt;= 1001000</span></div>
+<div class="line"><a name="l15500"></a><span class="lineno">15500</span>&#160;    <span class="keywordflow">if</span>(m_VulkanApiVersion &gt;= VK_MAKE_VERSION(1, 1, 0) || m_UseKhrDedicatedAllocation)</div>
+<div class="line"><a name="l15501"></a><span class="lineno">15501</span>&#160;    {</div>
+<div class="line"><a name="l15502"></a><span class="lineno">15502</span>&#160;        VMA_ASSERT(m_VulkanFunctions.vkGetBufferMemoryRequirements2KHR != VMA_NULL);</div>
+<div class="line"><a name="l15503"></a><span class="lineno">15503</span>&#160;        VMA_ASSERT(m_VulkanFunctions.vkGetImageMemoryRequirements2KHR != VMA_NULL);</div>
+<div class="line"><a name="l15504"></a><span class="lineno">15504</span>&#160;    }</div>
+<div class="line"><a name="l15505"></a><span class="lineno">15505</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l15506"></a><span class="lineno">15506</span>&#160; </div>
+<div class="line"><a name="l15507"></a><span class="lineno">15507</span>&#160;<span class="preprocessor">#if VMA_BIND_MEMORY2 || VMA_VULKAN_VERSION &gt;= 1001000</span></div>
+<div class="line"><a name="l15508"></a><span class="lineno">15508</span>&#160;    <span class="keywordflow">if</span>(m_VulkanApiVersion &gt;= VK_MAKE_VERSION(1, 1, 0) || m_UseKhrBindMemory2)</div>
+<div class="line"><a name="l15509"></a><span class="lineno">15509</span>&#160;    {</div>
+<div class="line"><a name="l15510"></a><span class="lineno">15510</span>&#160;        VMA_ASSERT(m_VulkanFunctions.vkBindBufferMemory2KHR != VMA_NULL);</div>
+<div class="line"><a name="l15511"></a><span class="lineno">15511</span>&#160;        VMA_ASSERT(m_VulkanFunctions.vkBindImageMemory2KHR != VMA_NULL);</div>
+<div class="line"><a name="l15512"></a><span class="lineno">15512</span>&#160;    }</div>
+<div class="line"><a name="l15513"></a><span class="lineno">15513</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l15514"></a><span class="lineno">15514</span>&#160; </div>
+<div class="line"><a name="l15515"></a><span class="lineno">15515</span>&#160;<span class="preprocessor">#if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION &gt;= 1001000</span></div>
+<div class="line"><a name="l15516"></a><span class="lineno">15516</span>&#160;    <span class="keywordflow">if</span>(m_UseExtMemoryBudget || m_VulkanApiVersion &gt;= VK_MAKE_VERSION(1, 1, 0))</div>
+<div class="line"><a name="l15517"></a><span class="lineno">15517</span>&#160;    {</div>
+<div class="line"><a name="l15518"></a><span class="lineno">15518</span>&#160;        VMA_ASSERT(m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties2KHR != VMA_NULL);</div>
+<div class="line"><a name="l15519"></a><span class="lineno">15519</span>&#160;    }</div>
+<div class="line"><a name="l15520"></a><span class="lineno">15520</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l15521"></a><span class="lineno">15521</span>&#160;}</div>
+<div class="line"><a name="l15522"></a><span class="lineno">15522</span>&#160; </div>
+<div class="line"><a name="l15523"></a><span class="lineno">15523</span>&#160;VkDeviceSize VmaAllocator_T::CalcPreferredBlockSize(uint32_t memTypeIndex)</div>
+<div class="line"><a name="l15524"></a><span class="lineno">15524</span>&#160;{</div>
+<div class="line"><a name="l15525"></a><span class="lineno">15525</span>&#160;    <span class="keyword">const</span> uint32_t heapIndex = MemoryTypeIndexToHeapIndex(memTypeIndex);</div>
+<div class="line"><a name="l15526"></a><span class="lineno">15526</span>&#160;    <span class="keyword">const</span> VkDeviceSize heapSize = m_MemProps.memoryHeaps[heapIndex].size;</div>
+<div class="line"><a name="l15527"></a><span class="lineno">15527</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">bool</span> isSmallHeap = heapSize &lt;= VMA_SMALL_HEAP_MAX_SIZE;</div>
+<div class="line"><a name="l15528"></a><span class="lineno">15528</span>&#160;    <span class="keywordflow">return</span> VmaAlignUp(isSmallHeap ? (heapSize / 8) : m_PreferredLargeHeapBlockSize, (VkDeviceSize)32);</div>
+<div class="line"><a name="l15529"></a><span class="lineno">15529</span>&#160;}</div>
+<div class="line"><a name="l15530"></a><span class="lineno">15530</span>&#160; </div>
+<div class="line"><a name="l15531"></a><span class="lineno">15531</span>&#160;VkResult VmaAllocator_T::AllocateMemoryOfType(</div>
+<div class="line"><a name="l15532"></a><span class="lineno">15532</span>&#160;    VkDeviceSize size,</div>
+<div class="line"><a name="l15533"></a><span class="lineno">15533</span>&#160;    VkDeviceSize alignment,</div>
+<div class="line"><a name="l15534"></a><span class="lineno">15534</span>&#160;    <span class="keywordtype">bool</span> dedicatedAllocation,</div>
+<div class="line"><a name="l15535"></a><span class="lineno">15535</span>&#160;    VkBuffer dedicatedBuffer,</div>
+<div class="line"><a name="l15536"></a><span class="lineno">15536</span>&#160;    VkBufferUsageFlags dedicatedBufferUsage,</div>
+<div class="line"><a name="l15537"></a><span class="lineno">15537</span>&#160;    VkImage dedicatedImage,</div>
+<div class="line"><a name="l15538"></a><span class="lineno">15538</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>&amp; createInfo,</div>
+<div class="line"><a name="l15539"></a><span class="lineno">15539</span>&#160;    uint32_t memTypeIndex,</div>
+<div class="line"><a name="l15540"></a><span class="lineno">15540</span>&#160;    VmaSuballocationType suballocType,</div>
+<div class="line"><a name="l15541"></a><span class="lineno">15541</span>&#160;    <span class="keywordtype">size_t</span> allocationCount,</div>
+<div class="line"><a name="l15542"></a><span class="lineno">15542</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocations)</div>
+<div class="line"><a name="l15543"></a><span class="lineno">15543</span>&#160;{</div>
+<div class="line"><a name="l15544"></a><span class="lineno">15544</span>&#160;    VMA_ASSERT(pAllocations != VMA_NULL);</div>
+<div class="line"><a name="l15545"></a><span class="lineno">15545</span>&#160;    VMA_DEBUG_LOG(<span class="stringliteral">&quot;  AllocateMemory: MemoryTypeIndex=%u, AllocationCount=%zu, Size=%llu&quot;</span>, memTypeIndex, allocationCount, size);</div>
+<div class="line"><a name="l15546"></a><span class="lineno">15546</span>&#160; </div>
+<div class="line"><a name="l15547"></a><span class="lineno">15547</span>&#160;    <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> finalCreateInfo = createInfo;</div>
+<div class="line"><a name="l15548"></a><span class="lineno">15548</span>&#160; </div>
+<div class="line"><a name="l15549"></a><span class="lineno">15549</span>&#160;    <span class="comment">// If memory type is not HOST_VISIBLE, disable MAPPED.</span></div>
+<div class="line"><a name="l15550"></a><span class="lineno">15550</span>&#160;    <span class="keywordflow">if</span>((finalCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a> &amp; <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a11da372cc3a82931c5e5d6146cd9dd1f">VMA_ALLOCATION_CREATE_MAPPED_BIT</a>) != 0 &amp;&amp;</div>
+<div class="line"><a name="l15551"></a><span class="lineno">15551</span>&#160;        (m_MemProps.memoryTypes[memTypeIndex].propertyFlags &amp; VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0)</div>
+<div class="line"><a name="l15552"></a><span class="lineno">15552</span>&#160;    {</div>
+<div class="line"><a name="l15553"></a><span class="lineno">15553</span>&#160;        finalCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a> &amp;= ~<a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a11da372cc3a82931c5e5d6146cd9dd1f">VMA_ALLOCATION_CREATE_MAPPED_BIT</a>;</div>
+<div class="line"><a name="l15554"></a><span class="lineno">15554</span>&#160;    }</div>
+<div class="line"><a name="l15555"></a><span class="lineno">15555</span>&#160;    <span class="comment">// If memory is lazily allocated, it should be always dedicated.</span></div>
+<div class="line"><a name="l15556"></a><span class="lineno">15556</span>&#160;    <span class="keywordflow">if</span>(finalCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910">usage</a> == <a class="code" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca835333d9072db63a653818030e17614d">VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED</a>)</div>
+<div class="line"><a name="l15557"></a><span class="lineno">15557</span>&#160;    {</div>
+<div class="line"><a name="l15558"></a><span class="lineno">15558</span>&#160;        finalCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a> |= <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a3fc311d855c2ff53f1090ef5c722b38f">VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT</a>;</div>
+<div class="line"><a name="l15559"></a><span class="lineno">15559</span>&#160;    }</div>
+<div class="line"><a name="l15560"></a><span class="lineno">15560</span>&#160; </div>
+<div class="line"><a name="l15561"></a><span class="lineno">15561</span>&#160;    VmaBlockVector* <span class="keyword">const</span> blockVector = m_pBlockVectors[memTypeIndex];</div>
+<div class="line"><a name="l15562"></a><span class="lineno">15562</span>&#160;    VMA_ASSERT(blockVector);</div>
+<div class="line"><a name="l15563"></a><span class="lineno">15563</span>&#160; </div>
+<div class="line"><a name="l15564"></a><span class="lineno">15564</span>&#160;    <span class="keyword">const</span> VkDeviceSize preferredBlockSize = blockVector-&gt;GetPreferredBlockSize();</div>
+<div class="line"><a name="l15565"></a><span class="lineno">15565</span>&#160;    <span class="keywordtype">bool</span> preferDedicatedMemory =</div>
+<div class="line"><a name="l15566"></a><span class="lineno">15566</span>&#160;        VMA_DEBUG_ALWAYS_DEDICATED_MEMORY ||</div>
+<div class="line"><a name="l15567"></a><span class="lineno">15567</span>&#160;        dedicatedAllocation ||</div>
+<div class="line"><a name="l15568"></a><span class="lineno">15568</span>&#160;        <span class="comment">// Heuristics: Allocate dedicated memory if requested size if greater than half of preferred block size.</span></div>
+<div class="line"><a name="l15569"></a><span class="lineno">15569</span>&#160;        size &gt; preferredBlockSize / 2;</div>
+<div class="line"><a name="l15570"></a><span class="lineno">15570</span>&#160; </div>
+<div class="line"><a name="l15571"></a><span class="lineno">15571</span>&#160;    <span class="keywordflow">if</span>(preferDedicatedMemory &amp;&amp;</div>
+<div class="line"><a name="l15572"></a><span class="lineno">15572</span>&#160;        (finalCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a> &amp; <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a89759603401014eb325eb22a3839f2ff">VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT</a>) == 0 &amp;&amp;</div>
+<div class="line"><a name="l15573"></a><span class="lineno">15573</span>&#160;        finalCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#a6272c0555cfd1fe28bff1afeb6190150">pool</a> == VK_NULL_HANDLE)</div>
+<div class="line"><a name="l15574"></a><span class="lineno">15574</span>&#160;    {</div>
+<div class="line"><a name="l15575"></a><span class="lineno">15575</span>&#160;        finalCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a> |= <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a3fc311d855c2ff53f1090ef5c722b38f">VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT</a>;</div>
+<div class="line"><a name="l15576"></a><span class="lineno">15576</span>&#160;    }</div>
+<div class="line"><a name="l15577"></a><span class="lineno">15577</span>&#160; </div>
+<div class="line"><a name="l15578"></a><span class="lineno">15578</span>&#160;    <span class="keywordflow">if</span>((finalCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a> &amp; <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a3fc311d855c2ff53f1090ef5c722b38f">VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT</a>) != 0)</div>
+<div class="line"><a name="l15579"></a><span class="lineno">15579</span>&#160;    {</div>
+<div class="line"><a name="l15580"></a><span class="lineno">15580</span>&#160;        <span class="keywordflow">if</span>((finalCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a> &amp; <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a89759603401014eb325eb22a3839f2ff">VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT</a>) != 0)</div>
+<div class="line"><a name="l15581"></a><span class="lineno">15581</span>&#160;        {</div>
+<div class="line"><a name="l15582"></a><span class="lineno">15582</span>&#160;            <span class="keywordflow">return</span> VK_ERROR_OUT_OF_DEVICE_MEMORY;</div>
+<div class="line"><a name="l15583"></a><span class="lineno">15583</span>&#160;        }</div>
+<div class="line"><a name="l15584"></a><span class="lineno">15584</span>&#160;        <span class="keywordflow">else</span></div>
+<div class="line"><a name="l15585"></a><span class="lineno">15585</span>&#160;        {</div>
+<div class="line"><a name="l15586"></a><span class="lineno">15586</span>&#160;            <span class="keywordflow">return</span> AllocateDedicatedMemory(</div>
+<div class="line"><a name="l15587"></a><span class="lineno">15587</span>&#160;                size,</div>
+<div class="line"><a name="l15588"></a><span class="lineno">15588</span>&#160;                suballocType,</div>
+<div class="line"><a name="l15589"></a><span class="lineno">15589</span>&#160;                memTypeIndex,</div>
+<div class="line"><a name="l15590"></a><span class="lineno">15590</span>&#160;                (finalCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a> &amp; <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597ab8b1764f3e9022368e440c057783b92d">VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT</a>) != 0,</div>
+<div class="line"><a name="l15591"></a><span class="lineno">15591</span>&#160;                (finalCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a> &amp; <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a11da372cc3a82931c5e5d6146cd9dd1f">VMA_ALLOCATION_CREATE_MAPPED_BIT</a>) != 0,</div>
+<div class="line"><a name="l15592"></a><span class="lineno">15592</span>&#160;                (finalCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a> &amp; <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597aa6f24f821cd6a7c5e4a443f7bf59c520">VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT</a>) != 0,</div>
+<div class="line"><a name="l15593"></a><span class="lineno">15593</span>&#160;                finalCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#a8259e85c272683434f4abb4ddddffe19">pUserData</a>,</div>
+<div class="line"><a name="l15594"></a><span class="lineno">15594</span>&#160;                dedicatedBuffer,</div>
+<div class="line"><a name="l15595"></a><span class="lineno">15595</span>&#160;                dedicatedBufferUsage,</div>
+<div class="line"><a name="l15596"></a><span class="lineno">15596</span>&#160;                dedicatedImage,</div>
+<div class="line"><a name="l15597"></a><span class="lineno">15597</span>&#160;                allocationCount,</div>
+<div class="line"><a name="l15598"></a><span class="lineno">15598</span>&#160;                pAllocations);</div>
+<div class="line"><a name="l15599"></a><span class="lineno">15599</span>&#160;        }</div>
+<div class="line"><a name="l15600"></a><span class="lineno">15600</span>&#160;    }</div>
+<div class="line"><a name="l15601"></a><span class="lineno">15601</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l15602"></a><span class="lineno">15602</span>&#160;    {</div>
+<div class="line"><a name="l15603"></a><span class="lineno">15603</span>&#160;        VkResult res = blockVector-&gt;Allocate(</div>
+<div class="line"><a name="l15604"></a><span class="lineno">15604</span>&#160;            m_CurrentFrameIndex.load(),</div>
+<div class="line"><a name="l15605"></a><span class="lineno">15605</span>&#160;            size,</div>
+<div class="line"><a name="l15606"></a><span class="lineno">15606</span>&#160;            alignment,</div>
+<div class="line"><a name="l15607"></a><span class="lineno">15607</span>&#160;            finalCreateInfo,</div>
+<div class="line"><a name="l15608"></a><span class="lineno">15608</span>&#160;            suballocType,</div>
+<div class="line"><a name="l15609"></a><span class="lineno">15609</span>&#160;            allocationCount,</div>
+<div class="line"><a name="l15610"></a><span class="lineno">15610</span>&#160;            pAllocations);</div>
+<div class="line"><a name="l15611"></a><span class="lineno">15611</span>&#160;        <span class="keywordflow">if</span>(res == VK_SUCCESS)</div>
+<div class="line"><a name="l15612"></a><span class="lineno">15612</span>&#160;        {</div>
+<div class="line"><a name="l15613"></a><span class="lineno">15613</span>&#160;            <span class="keywordflow">return</span> res;</div>
+<div class="line"><a name="l15614"></a><span class="lineno">15614</span>&#160;        }</div>
+<div class="line"><a name="l15615"></a><span class="lineno">15615</span>&#160; </div>
+<div class="line"><a name="l15616"></a><span class="lineno">15616</span>&#160;        <span class="comment">// 5. Try dedicated memory.</span></div>
+<div class="line"><a name="l15617"></a><span class="lineno">15617</span>&#160;        <span class="keywordflow">if</span>((finalCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a> &amp; <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a89759603401014eb325eb22a3839f2ff">VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT</a>) != 0)</div>
+<div class="line"><a name="l15618"></a><span class="lineno">15618</span>&#160;        {</div>
+<div class="line"><a name="l15619"></a><span class="lineno">15619</span>&#160;            <span class="keywordflow">return</span> VK_ERROR_OUT_OF_DEVICE_MEMORY;</div>
+<div class="line"><a name="l15620"></a><span class="lineno">15620</span>&#160;        }</div>
+<div class="line"><a name="l15621"></a><span class="lineno">15621</span>&#160;        <span class="keywordflow">else</span></div>
+<div class="line"><a name="l15622"></a><span class="lineno">15622</span>&#160;        {</div>
+<div class="line"><a name="l15623"></a><span class="lineno">15623</span>&#160;            res = AllocateDedicatedMemory(</div>
+<div class="line"><a name="l15624"></a><span class="lineno">15624</span>&#160;                size,</div>
+<div class="line"><a name="l15625"></a><span class="lineno">15625</span>&#160;                suballocType,</div>
+<div class="line"><a name="l15626"></a><span class="lineno">15626</span>&#160;                memTypeIndex,</div>
+<div class="line"><a name="l15627"></a><span class="lineno">15627</span>&#160;                (finalCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a> &amp; <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597ab8b1764f3e9022368e440c057783b92d">VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT</a>) != 0,</div>
+<div class="line"><a name="l15628"></a><span class="lineno">15628</span>&#160;                (finalCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a> &amp; <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a11da372cc3a82931c5e5d6146cd9dd1f">VMA_ALLOCATION_CREATE_MAPPED_BIT</a>) != 0,</div>
+<div class="line"><a name="l15629"></a><span class="lineno">15629</span>&#160;                (finalCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a> &amp; <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597aa6f24f821cd6a7c5e4a443f7bf59c520">VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT</a>) != 0,</div>
+<div class="line"><a name="l15630"></a><span class="lineno">15630</span>&#160;                finalCreateInfo.<a class="code" href="struct_vma_allocation_create_info.html#a8259e85c272683434f4abb4ddddffe19">pUserData</a>,</div>
+<div class="line"><a name="l15631"></a><span class="lineno">15631</span>&#160;                dedicatedBuffer,</div>
+<div class="line"><a name="l15632"></a><span class="lineno">15632</span>&#160;                dedicatedBufferUsage,</div>
+<div class="line"><a name="l15633"></a><span class="lineno">15633</span>&#160;                dedicatedImage,</div>
+<div class="line"><a name="l15634"></a><span class="lineno">15634</span>&#160;                allocationCount,</div>
+<div class="line"><a name="l15635"></a><span class="lineno">15635</span>&#160;                pAllocations);</div>
+<div class="line"><a name="l15636"></a><span class="lineno">15636</span>&#160;            <span class="keywordflow">if</span>(res == VK_SUCCESS)</div>
+<div class="line"><a name="l15637"></a><span class="lineno">15637</span>&#160;            {</div>
+<div class="line"><a name="l15638"></a><span class="lineno">15638</span>&#160;                <span class="comment">// Succeeded: AllocateDedicatedMemory function already filld pMemory, nothing more to do here.</span></div>
+<div class="line"><a name="l15639"></a><span class="lineno">15639</span>&#160;                VMA_DEBUG_LOG(<span class="stringliteral">&quot;    Allocated as DedicatedMemory&quot;</span>);</div>
+<div class="line"><a name="l15640"></a><span class="lineno">15640</span>&#160;                <span class="keywordflow">return</span> VK_SUCCESS;</div>
+<div class="line"><a name="l15641"></a><span class="lineno">15641</span>&#160;            }</div>
+<div class="line"><a name="l15642"></a><span class="lineno">15642</span>&#160;            <span class="keywordflow">else</span></div>
+<div class="line"><a name="l15643"></a><span class="lineno">15643</span>&#160;            {</div>
+<div class="line"><a name="l15644"></a><span class="lineno">15644</span>&#160;                <span class="comment">// Everything failed: Return error code.</span></div>
+<div class="line"><a name="l15645"></a><span class="lineno">15645</span>&#160;                VMA_DEBUG_LOG(<span class="stringliteral">&quot;    vkAllocateMemory FAILED&quot;</span>);</div>
+<div class="line"><a name="l15646"></a><span class="lineno">15646</span>&#160;                <span class="keywordflow">return</span> res;</div>
+<div class="line"><a name="l15647"></a><span class="lineno">15647</span>&#160;            }</div>
+<div class="line"><a name="l15648"></a><span class="lineno">15648</span>&#160;        }</div>
+<div class="line"><a name="l15649"></a><span class="lineno">15649</span>&#160;    }</div>
+<div class="line"><a name="l15650"></a><span class="lineno">15650</span>&#160;}</div>
+<div class="line"><a name="l15651"></a><span class="lineno">15651</span>&#160; </div>
+<div class="line"><a name="l15652"></a><span class="lineno">15652</span>&#160;VkResult VmaAllocator_T::AllocateDedicatedMemory(</div>
+<div class="line"><a name="l15653"></a><span class="lineno">15653</span>&#160;    VkDeviceSize size,</div>
+<div class="line"><a name="l15654"></a><span class="lineno">15654</span>&#160;    VmaSuballocationType suballocType,</div>
+<div class="line"><a name="l15655"></a><span class="lineno">15655</span>&#160;    uint32_t memTypeIndex,</div>
+<div class="line"><a name="l15656"></a><span class="lineno">15656</span>&#160;    <span class="keywordtype">bool</span> withinBudget,</div>
+<div class="line"><a name="l15657"></a><span class="lineno">15657</span>&#160;    <span class="keywordtype">bool</span> map,</div>
+<div class="line"><a name="l15658"></a><span class="lineno">15658</span>&#160;    <span class="keywordtype">bool</span> isUserDataString,</div>
+<div class="line"><a name="l15659"></a><span class="lineno">15659</span>&#160;    <span class="keywordtype">void</span>* pUserData,</div>
+<div class="line"><a name="l15660"></a><span class="lineno">15660</span>&#160;    VkBuffer dedicatedBuffer,</div>
+<div class="line"><a name="l15661"></a><span class="lineno">15661</span>&#160;    VkBufferUsageFlags dedicatedBufferUsage,</div>
+<div class="line"><a name="l15662"></a><span class="lineno">15662</span>&#160;    VkImage dedicatedImage,</div>
+<div class="line"><a name="l15663"></a><span class="lineno">15663</span>&#160;    <span class="keywordtype">size_t</span> allocationCount,</div>
+<div class="line"><a name="l15664"></a><span class="lineno">15664</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocations)</div>
+<div class="line"><a name="l15665"></a><span class="lineno">15665</span>&#160;{</div>
+<div class="line"><a name="l15666"></a><span class="lineno">15666</span>&#160;    VMA_ASSERT(allocationCount &gt; 0 &amp;&amp; pAllocations);</div>
+<div class="line"><a name="l15667"></a><span class="lineno">15667</span>&#160; </div>
+<div class="line"><a name="l15668"></a><span class="lineno">15668</span>&#160;    <span class="keywordflow">if</span>(withinBudget)</div>
+<div class="line"><a name="l15669"></a><span class="lineno">15669</span>&#160;    {</div>
+<div class="line"><a name="l15670"></a><span class="lineno">15670</span>&#160;        <span class="keyword">const</span> uint32_t heapIndex = MemoryTypeIndexToHeapIndex(memTypeIndex);</div>
+<div class="line"><a name="l15671"></a><span class="lineno">15671</span>&#160;        <a class="code" href="struct_vma_budget.html">VmaBudget</a> heapBudget = {};</div>
+<div class="line"><a name="l15672"></a><span class="lineno">15672</span>&#160;        GetBudget(&amp;heapBudget, heapIndex, 1);</div>
+<div class="line"><a name="l15673"></a><span class="lineno">15673</span>&#160;        <span class="keywordflow">if</span>(heapBudget.<a class="code" href="struct_vma_budget.html#a84dd1ecca8b0110259eb206dbadb11f6">usage</a> + size * allocationCount &gt; heapBudget.<a class="code" href="struct_vma_budget.html#ab82e1d1754c2d210d0bdf90220bc6cdd">budget</a>)</div>
+<div class="line"><a name="l15674"></a><span class="lineno">15674</span>&#160;        {</div>
+<div class="line"><a name="l15675"></a><span class="lineno">15675</span>&#160;            <span class="keywordflow">return</span> VK_ERROR_OUT_OF_DEVICE_MEMORY;</div>
+<div class="line"><a name="l15676"></a><span class="lineno">15676</span>&#160;        }</div>
+<div class="line"><a name="l15677"></a><span class="lineno">15677</span>&#160;    }</div>
+<div class="line"><a name="l15678"></a><span class="lineno">15678</span>&#160; </div>
+<div class="line"><a name="l15679"></a><span class="lineno">15679</span>&#160;    VkMemoryAllocateInfo allocInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };</div>
+<div class="line"><a name="l15680"></a><span class="lineno">15680</span>&#160;    allocInfo.memoryTypeIndex = memTypeIndex;</div>
+<div class="line"><a name="l15681"></a><span class="lineno">15681</span>&#160;    allocInfo.allocationSize = size;</div>
+<div class="line"><a name="l15682"></a><span class="lineno">15682</span>&#160; </div>
+<div class="line"><a name="l15683"></a><span class="lineno">15683</span>&#160;<span class="preprocessor">#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION &gt;= 1001000</span></div>
+<div class="line"><a name="l15684"></a><span class="lineno">15684</span>&#160;    VkMemoryDedicatedAllocateInfoKHR dedicatedAllocInfo = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR };</div>
+<div class="line"><a name="l15685"></a><span class="lineno">15685</span>&#160;    <span class="keywordflow">if</span>(m_UseKhrDedicatedAllocation || m_VulkanApiVersion &gt;= VK_MAKE_VERSION(1, 1, 0))</div>
+<div class="line"><a name="l15686"></a><span class="lineno">15686</span>&#160;    {</div>
+<div class="line"><a name="l15687"></a><span class="lineno">15687</span>&#160;        <span class="keywordflow">if</span>(dedicatedBuffer != VK_NULL_HANDLE)</div>
+<div class="line"><a name="l15688"></a><span class="lineno">15688</span>&#160;        {</div>
+<div class="line"><a name="l15689"></a><span class="lineno">15689</span>&#160;            VMA_ASSERT(dedicatedImage == VK_NULL_HANDLE);</div>
+<div class="line"><a name="l15690"></a><span class="lineno">15690</span>&#160;            dedicatedAllocInfo.buffer = dedicatedBuffer;</div>
+<div class="line"><a name="l15691"></a><span class="lineno">15691</span>&#160;            VmaPnextChainPushFront(&amp;allocInfo, &amp;dedicatedAllocInfo);</div>
+<div class="line"><a name="l15692"></a><span class="lineno">15692</span>&#160;        }</div>
+<div class="line"><a name="l15693"></a><span class="lineno">15693</span>&#160;        <span class="keywordflow">else</span> <span class="keywordflow">if</span>(dedicatedImage != VK_NULL_HANDLE)</div>
+<div class="line"><a name="l15694"></a><span class="lineno">15694</span>&#160;        {</div>
+<div class="line"><a name="l15695"></a><span class="lineno">15695</span>&#160;            dedicatedAllocInfo.image = dedicatedImage;</div>
+<div class="line"><a name="l15696"></a><span class="lineno">15696</span>&#160;            VmaPnextChainPushFront(&amp;allocInfo, &amp;dedicatedAllocInfo);</div>
+<div class="line"><a name="l15697"></a><span class="lineno">15697</span>&#160;        }</div>
+<div class="line"><a name="l15698"></a><span class="lineno">15698</span>&#160;    }</div>
+<div class="line"><a name="l15699"></a><span class="lineno">15699</span>&#160;<span class="preprocessor">#endif // #if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION &gt;= 1001000</span></div>
+<div class="line"><a name="l15700"></a><span class="lineno">15700</span>&#160; </div>
+<div class="line"><a name="l15701"></a><span class="lineno">15701</span>&#160;<span class="preprocessor">#if VMA_BUFFER_DEVICE_ADDRESS</span></div>
+<div class="line"><a name="l15702"></a><span class="lineno">15702</span>&#160;    VkMemoryAllocateFlagsInfoKHR allocFlagsInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO_KHR };</div>
+<div class="line"><a name="l15703"></a><span class="lineno">15703</span>&#160;    <span class="keywordflow">if</span>(m_UseKhrBufferDeviceAddress)</div>
+<div class="line"><a name="l15704"></a><span class="lineno">15704</span>&#160;    {</div>
+<div class="line"><a name="l15705"></a><span class="lineno">15705</span>&#160;        <span class="keywordtype">bool</span> canContainBufferWithDeviceAddress = <span class="keyword">true</span>;</div>
+<div class="line"><a name="l15706"></a><span class="lineno">15706</span>&#160;        <span class="keywordflow">if</span>(dedicatedBuffer != VK_NULL_HANDLE)</div>
+<div class="line"><a name="l15707"></a><span class="lineno">15707</span>&#160;        {</div>
+<div class="line"><a name="l15708"></a><span class="lineno">15708</span>&#160;            canContainBufferWithDeviceAddress = dedicatedBufferUsage == UINT32_MAX || <span class="comment">// Usage flags unknown</span></div>
+<div class="line"><a name="l15709"></a><span class="lineno">15709</span>&#160;                (dedicatedBufferUsage &amp; VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_EXT) != 0;</div>
+<div class="line"><a name="l15710"></a><span class="lineno">15710</span>&#160;        }</div>
+<div class="line"><a name="l15711"></a><span class="lineno">15711</span>&#160;        <span class="keywordflow">else</span> <span class="keywordflow">if</span>(dedicatedImage != VK_NULL_HANDLE)</div>
+<div class="line"><a name="l15712"></a><span class="lineno">15712</span>&#160;        {</div>
+<div class="line"><a name="l15713"></a><span class="lineno">15713</span>&#160;            canContainBufferWithDeviceAddress = <span class="keyword">false</span>;</div>
+<div class="line"><a name="l15714"></a><span class="lineno">15714</span>&#160;        }</div>
+<div class="line"><a name="l15715"></a><span class="lineno">15715</span>&#160;        <span class="keywordflow">if</span>(canContainBufferWithDeviceAddress)</div>
+<div class="line"><a name="l15716"></a><span class="lineno">15716</span>&#160;        {</div>
+<div class="line"><a name="l15717"></a><span class="lineno">15717</span>&#160;            allocFlagsInfo.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR;</div>
+<div class="line"><a name="l15718"></a><span class="lineno">15718</span>&#160;            VmaPnextChainPushFront(&amp;allocInfo, &amp;allocFlagsInfo);</div>
+<div class="line"><a name="l15719"></a><span class="lineno">15719</span>&#160;        }</div>
+<div class="line"><a name="l15720"></a><span class="lineno">15720</span>&#160;    }</div>
+<div class="line"><a name="l15721"></a><span class="lineno">15721</span>&#160;<span class="preprocessor">#endif // #if VMA_BUFFER_DEVICE_ADDRESS</span></div>
+<div class="line"><a name="l15722"></a><span class="lineno">15722</span>&#160; </div>
+<div class="line"><a name="l15723"></a><span class="lineno">15723</span>&#160;    <span class="keywordtype">size_t</span> allocIndex;</div>
+<div class="line"><a name="l15724"></a><span class="lineno">15724</span>&#160;    VkResult res = VK_SUCCESS;</div>
+<div class="line"><a name="l15725"></a><span class="lineno">15725</span>&#160;    <span class="keywordflow">for</span>(allocIndex = 0; allocIndex &lt; allocationCount; ++allocIndex)</div>
+<div class="line"><a name="l15726"></a><span class="lineno">15726</span>&#160;    {</div>
+<div class="line"><a name="l15727"></a><span class="lineno">15727</span>&#160;        res = AllocateDedicatedMemoryPage(</div>
+<div class="line"><a name="l15728"></a><span class="lineno">15728</span>&#160;            size,</div>
+<div class="line"><a name="l15729"></a><span class="lineno">15729</span>&#160;            suballocType,</div>
+<div class="line"><a name="l15730"></a><span class="lineno">15730</span>&#160;            memTypeIndex,</div>
+<div class="line"><a name="l15731"></a><span class="lineno">15731</span>&#160;            allocInfo,</div>
+<div class="line"><a name="l15732"></a><span class="lineno">15732</span>&#160;            map,</div>
+<div class="line"><a name="l15733"></a><span class="lineno">15733</span>&#160;            isUserDataString,</div>
+<div class="line"><a name="l15734"></a><span class="lineno">15734</span>&#160;            pUserData,</div>
+<div class="line"><a name="l15735"></a><span class="lineno">15735</span>&#160;            pAllocations + allocIndex);</div>
+<div class="line"><a name="l15736"></a><span class="lineno">15736</span>&#160;        <span class="keywordflow">if</span>(res != VK_SUCCESS)</div>
+<div class="line"><a name="l15737"></a><span class="lineno">15737</span>&#160;        {</div>
+<div class="line"><a name="l15738"></a><span class="lineno">15738</span>&#160;            <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l15739"></a><span class="lineno">15739</span>&#160;        }</div>
+<div class="line"><a name="l15740"></a><span class="lineno">15740</span>&#160;    }</div>
+<div class="line"><a name="l15741"></a><span class="lineno">15741</span>&#160; </div>
+<div class="line"><a name="l15742"></a><span class="lineno">15742</span>&#160;    <span class="keywordflow">if</span>(res == VK_SUCCESS)</div>
+<div class="line"><a name="l15743"></a><span class="lineno">15743</span>&#160;    {</div>
+<div class="line"><a name="l15744"></a><span class="lineno">15744</span>&#160;        <span class="comment">// Register them in m_pDedicatedAllocations.</span></div>
+<div class="line"><a name="l15745"></a><span class="lineno">15745</span>&#160;        {</div>
+<div class="line"><a name="l15746"></a><span class="lineno">15746</span>&#160;            VmaMutexLockWrite lock(m_DedicatedAllocationsMutex[memTypeIndex], m_UseMutex);</div>
+<div class="line"><a name="l15747"></a><span class="lineno">15747</span>&#160;            AllocationVectorType* pDedicatedAllocations = m_pDedicatedAllocations[memTypeIndex];</div>
+<div class="line"><a name="l15748"></a><span class="lineno">15748</span>&#160;            VMA_ASSERT(pDedicatedAllocations);</div>
+<div class="line"><a name="l15749"></a><span class="lineno">15749</span>&#160;            <span class="keywordflow">for</span>(allocIndex = 0; allocIndex &lt; allocationCount; ++allocIndex)</div>
+<div class="line"><a name="l15750"></a><span class="lineno">15750</span>&#160;            {</div>
+<div class="line"><a name="l15751"></a><span class="lineno">15751</span>&#160;                VmaVectorInsertSorted&lt;VmaPointerLess&gt;(*pDedicatedAllocations, pAllocations[allocIndex]);</div>
+<div class="line"><a name="l15752"></a><span class="lineno">15752</span>&#160;            }</div>
+<div class="line"><a name="l15753"></a><span class="lineno">15753</span>&#160;        }</div>
+<div class="line"><a name="l15754"></a><span class="lineno">15754</span>&#160; </div>
+<div class="line"><a name="l15755"></a><span class="lineno">15755</span>&#160;        VMA_DEBUG_LOG(<span class="stringliteral">&quot;    Allocated DedicatedMemory Count=%zu, MemoryTypeIndex=#%u&quot;</span>, allocationCount, memTypeIndex);</div>
+<div class="line"><a name="l15756"></a><span class="lineno">15756</span>&#160;    }</div>
+<div class="line"><a name="l15757"></a><span class="lineno">15757</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l15758"></a><span class="lineno">15758</span>&#160;    {</div>
+<div class="line"><a name="l15759"></a><span class="lineno">15759</span>&#160;        <span class="comment">// Free all already created allocations.</span></div>
+<div class="line"><a name="l15760"></a><span class="lineno">15760</span>&#160;        <span class="keywordflow">while</span>(allocIndex--)</div>
+<div class="line"><a name="l15761"></a><span class="lineno">15761</span>&#160;        {</div>
+<div class="line"><a name="l15762"></a><span class="lineno">15762</span>&#160;            <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> currAlloc = pAllocations[allocIndex];</div>
+<div class="line"><a name="l15763"></a><span class="lineno">15763</span>&#160;            VkDeviceMemory hMemory = currAlloc-&gt;GetMemory();</div>
+<div class="line"><a name="l15764"></a><span class="lineno">15764</span>&#160;    </div>
+<div class="line"><a name="l15765"></a><span class="lineno">15765</span>&#160;            <span class="comment">/*</span></div>
+<div class="line"><a name="l15766"></a><span class="lineno">15766</span>&#160;<span class="comment">            There is no need to call this, because Vulkan spec allows to skip vkUnmapMemory</span></div>
+<div class="line"><a name="l15767"></a><span class="lineno">15767</span>&#160;<span class="comment">            before vkFreeMemory.</span></div>
+<div class="line"><a name="l15768"></a><span class="lineno">15768</span>&#160;<span class="comment"></span> </div>
+<div class="line"><a name="l15769"></a><span class="lineno">15769</span>&#160;<span class="comment">            if(currAlloc-&gt;GetMappedData() != VMA_NULL)</span></div>
+<div class="line"><a name="l15770"></a><span class="lineno">15770</span>&#160;<span class="comment">            {</span></div>
+<div class="line"><a name="l15771"></a><span class="lineno">15771</span>&#160;<span class="comment">                (*m_VulkanFunctions.vkUnmapMemory)(m_hDevice, hMemory);</span></div>
+<div class="line"><a name="l15772"></a><span class="lineno">15772</span>&#160;<span class="comment">            }</span></div>
+<div class="line"><a name="l15773"></a><span class="lineno">15773</span>&#160;<span class="comment">            */</span></div>
+<div class="line"><a name="l15774"></a><span class="lineno">15774</span>&#160;    </div>
+<div class="line"><a name="l15775"></a><span class="lineno">15775</span>&#160;            FreeVulkanMemory(memTypeIndex, currAlloc-&gt;GetSize(), hMemory);</div>
+<div class="line"><a name="l15776"></a><span class="lineno">15776</span>&#160;            m_Budget.RemoveAllocation(MemoryTypeIndexToHeapIndex(memTypeIndex), currAlloc-&gt;GetSize());</div>
+<div class="line"><a name="l15777"></a><span class="lineno">15777</span>&#160;            currAlloc-&gt;SetUserData(<span class="keyword">this</span>, VMA_NULL);</div>
+<div class="line"><a name="l15778"></a><span class="lineno">15778</span>&#160;            m_AllocationObjectAllocator.Free(currAlloc);</div>
+<div class="line"><a name="l15779"></a><span class="lineno">15779</span>&#160;        }</div>
+<div class="line"><a name="l15780"></a><span class="lineno">15780</span>&#160; </div>
+<div class="line"><a name="l15781"></a><span class="lineno">15781</span>&#160;        memset(pAllocations, 0, <span class="keyword">sizeof</span>(<a class="code" href="struct_vma_allocation.html">VmaAllocation</a>) * allocationCount);</div>
+<div class="line"><a name="l15782"></a><span class="lineno">15782</span>&#160;    }</div>
+<div class="line"><a name="l15783"></a><span class="lineno">15783</span>&#160; </div>
+<div class="line"><a name="l15784"></a><span class="lineno">15784</span>&#160;    <span class="keywordflow">return</span> res;</div>
+<div class="line"><a name="l15785"></a><span class="lineno">15785</span>&#160;}</div>
+<div class="line"><a name="l15786"></a><span class="lineno">15786</span>&#160; </div>
+<div class="line"><a name="l15787"></a><span class="lineno">15787</span>&#160;VkResult VmaAllocator_T::AllocateDedicatedMemoryPage(</div>
+<div class="line"><a name="l15788"></a><span class="lineno">15788</span>&#160;    VkDeviceSize size,</div>
+<div class="line"><a name="l15789"></a><span class="lineno">15789</span>&#160;    VmaSuballocationType suballocType,</div>
+<div class="line"><a name="l15790"></a><span class="lineno">15790</span>&#160;    uint32_t memTypeIndex,</div>
+<div class="line"><a name="l15791"></a><span class="lineno">15791</span>&#160;    <span class="keyword">const</span> VkMemoryAllocateInfo&amp; allocInfo,</div>
+<div class="line"><a name="l15792"></a><span class="lineno">15792</span>&#160;    <span class="keywordtype">bool</span> map,</div>
+<div class="line"><a name="l15793"></a><span class="lineno">15793</span>&#160;    <span class="keywordtype">bool</span> isUserDataString,</div>
+<div class="line"><a name="l15794"></a><span class="lineno">15794</span>&#160;    <span class="keywordtype">void</span>* pUserData,</div>
+<div class="line"><a name="l15795"></a><span class="lineno">15795</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocation)</div>
+<div class="line"><a name="l15796"></a><span class="lineno">15796</span>&#160;{</div>
+<div class="line"><a name="l15797"></a><span class="lineno">15797</span>&#160;    VkDeviceMemory hMemory = VK_NULL_HANDLE;</div>
+<div class="line"><a name="l15798"></a><span class="lineno">15798</span>&#160;    VkResult res = AllocateVulkanMemory(&amp;allocInfo, &amp;hMemory);</div>
+<div class="line"><a name="l15799"></a><span class="lineno">15799</span>&#160;    <span class="keywordflow">if</span>(res &lt; 0)</div>
+<div class="line"><a name="l15800"></a><span class="lineno">15800</span>&#160;    {</div>
+<div class="line"><a name="l15801"></a><span class="lineno">15801</span>&#160;        VMA_DEBUG_LOG(<span class="stringliteral">&quot;    vkAllocateMemory FAILED&quot;</span>);</div>
+<div class="line"><a name="l15802"></a><span class="lineno">15802</span>&#160;        <span class="keywordflow">return</span> res;</div>
+<div class="line"><a name="l15803"></a><span class="lineno">15803</span>&#160;    }</div>
+<div class="line"><a name="l15804"></a><span class="lineno">15804</span>&#160; </div>
+<div class="line"><a name="l15805"></a><span class="lineno">15805</span>&#160;    <span class="keywordtype">void</span>* pMappedData = VMA_NULL;</div>
+<div class="line"><a name="l15806"></a><span class="lineno">15806</span>&#160;    <span class="keywordflow">if</span>(map)</div>
+<div class="line"><a name="l15807"></a><span class="lineno">15807</span>&#160;    {</div>
+<div class="line"><a name="l15808"></a><span class="lineno">15808</span>&#160;        res = (*m_VulkanFunctions.vkMapMemory)(</div>
+<div class="line"><a name="l15809"></a><span class="lineno">15809</span>&#160;            m_hDevice,</div>
+<div class="line"><a name="l15810"></a><span class="lineno">15810</span>&#160;            hMemory,</div>
+<div class="line"><a name="l15811"></a><span class="lineno">15811</span>&#160;            0,</div>
+<div class="line"><a name="l15812"></a><span class="lineno">15812</span>&#160;            VK_WHOLE_SIZE,</div>
+<div class="line"><a name="l15813"></a><span class="lineno">15813</span>&#160;            0,</div>
+<div class="line"><a name="l15814"></a><span class="lineno">15814</span>&#160;            &amp;pMappedData);</div>
+<div class="line"><a name="l15815"></a><span class="lineno">15815</span>&#160;        <span class="keywordflow">if</span>(res &lt; 0)</div>
+<div class="line"><a name="l15816"></a><span class="lineno">15816</span>&#160;        {</div>
+<div class="line"><a name="l15817"></a><span class="lineno">15817</span>&#160;            VMA_DEBUG_LOG(<span class="stringliteral">&quot;    vkMapMemory FAILED&quot;</span>);</div>
+<div class="line"><a name="l15818"></a><span class="lineno">15818</span>&#160;            FreeVulkanMemory(memTypeIndex, size, hMemory);</div>
+<div class="line"><a name="l15819"></a><span class="lineno">15819</span>&#160;            <span class="keywordflow">return</span> res;</div>
+<div class="line"><a name="l15820"></a><span class="lineno">15820</span>&#160;        }</div>
+<div class="line"><a name="l15821"></a><span class="lineno">15821</span>&#160;    }</div>
+<div class="line"><a name="l15822"></a><span class="lineno">15822</span>&#160; </div>
+<div class="line"><a name="l15823"></a><span class="lineno">15823</span>&#160;    *pAllocation = m_AllocationObjectAllocator.Allocate(m_CurrentFrameIndex.load(), isUserDataString);</div>
+<div class="line"><a name="l15824"></a><span class="lineno">15824</span>&#160;    (*pAllocation)-&gt;InitDedicatedAllocation(memTypeIndex, hMemory, suballocType, pMappedData, size);</div>
+<div class="line"><a name="l15825"></a><span class="lineno">15825</span>&#160;    (*pAllocation)-&gt;SetUserData(<span class="keyword">this</span>, pUserData);</div>
+<div class="line"><a name="l15826"></a><span class="lineno">15826</span>&#160;    m_Budget.AddAllocation(MemoryTypeIndexToHeapIndex(memTypeIndex), size);</div>
+<div class="line"><a name="l15827"></a><span class="lineno">15827</span>&#160;    <span class="keywordflow">if</span>(VMA_DEBUG_INITIALIZE_ALLOCATIONS)</div>
+<div class="line"><a name="l15828"></a><span class="lineno">15828</span>&#160;    {</div>
+<div class="line"><a name="l15829"></a><span class="lineno">15829</span>&#160;        FillAllocation(*pAllocation, VMA_ALLOCATION_FILL_PATTERN_CREATED);</div>
+<div class="line"><a name="l15830"></a><span class="lineno">15830</span>&#160;    }</div>
+<div class="line"><a name="l15831"></a><span class="lineno">15831</span>&#160; </div>
+<div class="line"><a name="l15832"></a><span class="lineno">15832</span>&#160;    <span class="keywordflow">return</span> VK_SUCCESS;</div>
+<div class="line"><a name="l15833"></a><span class="lineno">15833</span>&#160;}</div>
+<div class="line"><a name="l15834"></a><span class="lineno">15834</span>&#160; </div>
+<div class="line"><a name="l15835"></a><span class="lineno">15835</span>&#160;<span class="keywordtype">void</span> VmaAllocator_T::GetBufferMemoryRequirements(</div>
+<div class="line"><a name="l15836"></a><span class="lineno">15836</span>&#160;    VkBuffer hBuffer,</div>
+<div class="line"><a name="l15837"></a><span class="lineno">15837</span>&#160;    VkMemoryRequirements&amp; memReq,</div>
+<div class="line"><a name="l15838"></a><span class="lineno">15838</span>&#160;    <span class="keywordtype">bool</span>&amp; requiresDedicatedAllocation,</div>
+<div class="line"><a name="l15839"></a><span class="lineno">15839</span>&#160;    <span class="keywordtype">bool</span>&amp; prefersDedicatedAllocation)<span class="keyword"> const</span></div>
+<div class="line"><a name="l15840"></a><span class="lineno">15840</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l15841"></a><span class="lineno">15841</span>&#160;<span class="preprocessor">#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION &gt;= 1001000</span></div>
+<div class="line"><a name="l15842"></a><span class="lineno">15842</span>&#160;    <span class="keywordflow">if</span>(m_UseKhrDedicatedAllocation || m_VulkanApiVersion &gt;= VK_MAKE_VERSION(1, 1, 0))</div>
+<div class="line"><a name="l15843"></a><span class="lineno">15843</span>&#160;    {</div>
+<div class="line"><a name="l15844"></a><span class="lineno">15844</span>&#160;        VkBufferMemoryRequirementsInfo2KHR memReqInfo = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR };</div>
+<div class="line"><a name="l15845"></a><span class="lineno">15845</span>&#160;        memReqInfo.buffer = hBuffer;</div>
+<div class="line"><a name="l15846"></a><span class="lineno">15846</span>&#160; </div>
+<div class="line"><a name="l15847"></a><span class="lineno">15847</span>&#160;        VkMemoryDedicatedRequirementsKHR memDedicatedReq = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR };</div>
+<div class="line"><a name="l15848"></a><span class="lineno">15848</span>&#160; </div>
+<div class="line"><a name="l15849"></a><span class="lineno">15849</span>&#160;        VkMemoryRequirements2KHR memReq2 = { VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR };</div>
+<div class="line"><a name="l15850"></a><span class="lineno">15850</span>&#160;        VmaPnextChainPushFront(&amp;memReq2, &amp;memDedicatedReq);</div>
+<div class="line"><a name="l15851"></a><span class="lineno">15851</span>&#160; </div>
+<div class="line"><a name="l15852"></a><span class="lineno">15852</span>&#160;        (*m_VulkanFunctions.vkGetBufferMemoryRequirements2KHR)(m_hDevice, &amp;memReqInfo, &amp;memReq2);</div>
+<div class="line"><a name="l15853"></a><span class="lineno">15853</span>&#160; </div>
+<div class="line"><a name="l15854"></a><span class="lineno">15854</span>&#160;        memReq = memReq2.memoryRequirements;</div>
+<div class="line"><a name="l15855"></a><span class="lineno">15855</span>&#160;        requiresDedicatedAllocation = (memDedicatedReq.requiresDedicatedAllocation != VK_FALSE);</div>
+<div class="line"><a name="l15856"></a><span class="lineno">15856</span>&#160;        prefersDedicatedAllocation  = (memDedicatedReq.prefersDedicatedAllocation  != VK_FALSE);</div>
+<div class="line"><a name="l15857"></a><span class="lineno">15857</span>&#160;    }</div>
+<div class="line"><a name="l15858"></a><span class="lineno">15858</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l15859"></a><span class="lineno">15859</span>&#160;<span class="preprocessor">#endif // #if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION &gt;= 1001000</span></div>
+<div class="line"><a name="l15860"></a><span class="lineno">15860</span>&#160;    {</div>
+<div class="line"><a name="l15861"></a><span class="lineno">15861</span>&#160;        (*m_VulkanFunctions.vkGetBufferMemoryRequirements)(m_hDevice, hBuffer, &amp;memReq);</div>
+<div class="line"><a name="l15862"></a><span class="lineno">15862</span>&#160;        requiresDedicatedAllocation = <span class="keyword">false</span>;</div>
+<div class="line"><a name="l15863"></a><span class="lineno">15863</span>&#160;        prefersDedicatedAllocation  = <span class="keyword">false</span>;</div>
+<div class="line"><a name="l15864"></a><span class="lineno">15864</span>&#160;    }</div>
+<div class="line"><a name="l15865"></a><span class="lineno">15865</span>&#160;}</div>
+<div class="line"><a name="l15866"></a><span class="lineno">15866</span>&#160; </div>
+<div class="line"><a name="l15867"></a><span class="lineno">15867</span>&#160;<span class="keywordtype">void</span> VmaAllocator_T::GetImageMemoryRequirements(</div>
+<div class="line"><a name="l15868"></a><span class="lineno">15868</span>&#160;    VkImage hImage,</div>
+<div class="line"><a name="l15869"></a><span class="lineno">15869</span>&#160;    VkMemoryRequirements&amp; memReq,</div>
+<div class="line"><a name="l15870"></a><span class="lineno">15870</span>&#160;    <span class="keywordtype">bool</span>&amp; requiresDedicatedAllocation,</div>
+<div class="line"><a name="l15871"></a><span class="lineno">15871</span>&#160;    <span class="keywordtype">bool</span>&amp; prefersDedicatedAllocation)<span class="keyword"> const</span></div>
+<div class="line"><a name="l15872"></a><span class="lineno">15872</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l15873"></a><span class="lineno">15873</span>&#160;<span class="preprocessor">#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION &gt;= 1001000</span></div>
+<div class="line"><a name="l15874"></a><span class="lineno">15874</span>&#160;    <span class="keywordflow">if</span>(m_UseKhrDedicatedAllocation || m_VulkanApiVersion &gt;= VK_MAKE_VERSION(1, 1, 0))</div>
+<div class="line"><a name="l15875"></a><span class="lineno">15875</span>&#160;    {</div>
+<div class="line"><a name="l15876"></a><span class="lineno">15876</span>&#160;        VkImageMemoryRequirementsInfo2KHR memReqInfo = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR };</div>
+<div class="line"><a name="l15877"></a><span class="lineno">15877</span>&#160;        memReqInfo.image = hImage;</div>
+<div class="line"><a name="l15878"></a><span class="lineno">15878</span>&#160; </div>
+<div class="line"><a name="l15879"></a><span class="lineno">15879</span>&#160;        VkMemoryDedicatedRequirementsKHR memDedicatedReq = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR };</div>
+<div class="line"><a name="l15880"></a><span class="lineno">15880</span>&#160; </div>
+<div class="line"><a name="l15881"></a><span class="lineno">15881</span>&#160;        VkMemoryRequirements2KHR memReq2 = { VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR };</div>
+<div class="line"><a name="l15882"></a><span class="lineno">15882</span>&#160;        VmaPnextChainPushFront(&amp;memReq2, &amp;memDedicatedReq);</div>
+<div class="line"><a name="l15883"></a><span class="lineno">15883</span>&#160; </div>
+<div class="line"><a name="l15884"></a><span class="lineno">15884</span>&#160;        (*m_VulkanFunctions.vkGetImageMemoryRequirements2KHR)(m_hDevice, &amp;memReqInfo, &amp;memReq2);</div>
+<div class="line"><a name="l15885"></a><span class="lineno">15885</span>&#160; </div>
+<div class="line"><a name="l15886"></a><span class="lineno">15886</span>&#160;        memReq = memReq2.memoryRequirements;</div>
+<div class="line"><a name="l15887"></a><span class="lineno">15887</span>&#160;        requiresDedicatedAllocation = (memDedicatedReq.requiresDedicatedAllocation != VK_FALSE);</div>
+<div class="line"><a name="l15888"></a><span class="lineno">15888</span>&#160;        prefersDedicatedAllocation  = (memDedicatedReq.prefersDedicatedAllocation  != VK_FALSE);</div>
+<div class="line"><a name="l15889"></a><span class="lineno">15889</span>&#160;    }</div>
+<div class="line"><a name="l15890"></a><span class="lineno">15890</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l15891"></a><span class="lineno">15891</span>&#160;<span class="preprocessor">#endif // #if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION &gt;= 1001000</span></div>
+<div class="line"><a name="l15892"></a><span class="lineno">15892</span>&#160;    {</div>
+<div class="line"><a name="l15893"></a><span class="lineno">15893</span>&#160;        (*m_VulkanFunctions.vkGetImageMemoryRequirements)(m_hDevice, hImage, &amp;memReq);</div>
+<div class="line"><a name="l15894"></a><span class="lineno">15894</span>&#160;        requiresDedicatedAllocation = <span class="keyword">false</span>;</div>
+<div class="line"><a name="l15895"></a><span class="lineno">15895</span>&#160;        prefersDedicatedAllocation  = <span class="keyword">false</span>;</div>
+<div class="line"><a name="l15896"></a><span class="lineno">15896</span>&#160;    }</div>
+<div class="line"><a name="l15897"></a><span class="lineno">15897</span>&#160;}</div>
+<div class="line"><a name="l15898"></a><span class="lineno">15898</span>&#160; </div>
+<div class="line"><a name="l15899"></a><span class="lineno">15899</span>&#160;VkResult VmaAllocator_T::AllocateMemory(</div>
+<div class="line"><a name="l15900"></a><span class="lineno">15900</span>&#160;    <span class="keyword">const</span> VkMemoryRequirements&amp; vkMemReq,</div>
+<div class="line"><a name="l15901"></a><span class="lineno">15901</span>&#160;    <span class="keywordtype">bool</span> requiresDedicatedAllocation,</div>
+<div class="line"><a name="l15902"></a><span class="lineno">15902</span>&#160;    <span class="keywordtype">bool</span> prefersDedicatedAllocation,</div>
+<div class="line"><a name="l15903"></a><span class="lineno">15903</span>&#160;    VkBuffer dedicatedBuffer,</div>
+<div class="line"><a name="l15904"></a><span class="lineno">15904</span>&#160;    VkBufferUsageFlags dedicatedBufferUsage,</div>
+<div class="line"><a name="l15905"></a><span class="lineno">15905</span>&#160;    VkImage dedicatedImage,</div>
+<div class="line"><a name="l15906"></a><span class="lineno">15906</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>&amp; createInfo,</div>
+<div class="line"><a name="l15907"></a><span class="lineno">15907</span>&#160;    VmaSuballocationType suballocType,</div>
+<div class="line"><a name="l15908"></a><span class="lineno">15908</span>&#160;    <span class="keywordtype">size_t</span> allocationCount,</div>
+<div class="line"><a name="l15909"></a><span class="lineno">15909</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocations)</div>
+<div class="line"><a name="l15910"></a><span class="lineno">15910</span>&#160;{</div>
+<div class="line"><a name="l15911"></a><span class="lineno">15911</span>&#160;    memset(pAllocations, 0, <span class="keyword">sizeof</span>(<a class="code" href="struct_vma_allocation.html">VmaAllocation</a>) * allocationCount);</div>
+<div class="line"><a name="l15912"></a><span class="lineno">15912</span>&#160; </div>
+<div class="line"><a name="l15913"></a><span class="lineno">15913</span>&#160;    VMA_ASSERT(VmaIsPow2(vkMemReq.alignment));</div>
+<div class="line"><a name="l15914"></a><span class="lineno">15914</span>&#160; </div>
+<div class="line"><a name="l15915"></a><span class="lineno">15915</span>&#160;    <span class="keywordflow">if</span>(vkMemReq.size == 0)</div>
+<div class="line"><a name="l15916"></a><span class="lineno">15916</span>&#160;    {</div>
+<div class="line"><a name="l15917"></a><span class="lineno">15917</span>&#160;        <span class="keywordflow">return</span> VK_ERROR_VALIDATION_FAILED_EXT;</div>
+<div class="line"><a name="l15918"></a><span class="lineno">15918</span>&#160;    }</div>
+<div class="line"><a name="l15919"></a><span class="lineno">15919</span>&#160;    <span class="keywordflow">if</span>((createInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a> &amp; <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a3fc311d855c2ff53f1090ef5c722b38f">VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT</a>) != 0 &amp;&amp;</div>
+<div class="line"><a name="l15920"></a><span class="lineno">15920</span>&#160;        (createInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a> &amp; <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a89759603401014eb325eb22a3839f2ff">VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT</a>) != 0)</div>
+<div class="line"><a name="l15921"></a><span class="lineno">15921</span>&#160;    {</div>
+<div class="line"><a name="l15922"></a><span class="lineno">15922</span>&#160;        VMA_ASSERT(0 &amp;&amp; <span class="stringliteral">&quot;Specifying VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT together with VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT makes no sense.&quot;</span>);</div>
+<div class="line"><a name="l15923"></a><span class="lineno">15923</span>&#160;        <span class="keywordflow">return</span> VK_ERROR_OUT_OF_DEVICE_MEMORY;</div>
+<div class="line"><a name="l15924"></a><span class="lineno">15924</span>&#160;    }</div>
+<div class="line"><a name="l15925"></a><span class="lineno">15925</span>&#160;    <span class="keywordflow">if</span>((createInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a> &amp; <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a11da372cc3a82931c5e5d6146cd9dd1f">VMA_ALLOCATION_CREATE_MAPPED_BIT</a>) != 0 &amp;&amp;</div>
+<div class="line"><a name="l15926"></a><span class="lineno">15926</span>&#160;        (createInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a> &amp; <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a5f436af6c8fe8540573a6d22627a6fd2">VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT</a>) != 0)</div>
+<div class="line"><a name="l15927"></a><span class="lineno">15927</span>&#160;    {</div>
+<div class="line"><a name="l15928"></a><span class="lineno">15928</span>&#160;        VMA_ASSERT(0 &amp;&amp; <span class="stringliteral">&quot;Specifying VMA_ALLOCATION_CREATE_MAPPED_BIT together with VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT is invalid.&quot;</span>);</div>
+<div class="line"><a name="l15929"></a><span class="lineno">15929</span>&#160;        <span class="keywordflow">return</span> VK_ERROR_OUT_OF_DEVICE_MEMORY;</div>
+<div class="line"><a name="l15930"></a><span class="lineno">15930</span>&#160;    }</div>
+<div class="line"><a name="l15931"></a><span class="lineno">15931</span>&#160;    <span class="keywordflow">if</span>(requiresDedicatedAllocation)</div>
+<div class="line"><a name="l15932"></a><span class="lineno">15932</span>&#160;    {</div>
+<div class="line"><a name="l15933"></a><span class="lineno">15933</span>&#160;        <span class="keywordflow">if</span>((createInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a> &amp; <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a89759603401014eb325eb22a3839f2ff">VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT</a>) != 0)</div>
+<div class="line"><a name="l15934"></a><span class="lineno">15934</span>&#160;        {</div>
+<div class="line"><a name="l15935"></a><span class="lineno">15935</span>&#160;            VMA_ASSERT(0 &amp;&amp; <span class="stringliteral">&quot;VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT specified while dedicated allocation is required.&quot;</span>);</div>
+<div class="line"><a name="l15936"></a><span class="lineno">15936</span>&#160;            <span class="keywordflow">return</span> VK_ERROR_OUT_OF_DEVICE_MEMORY;</div>
+<div class="line"><a name="l15937"></a><span class="lineno">15937</span>&#160;        }</div>
+<div class="line"><a name="l15938"></a><span class="lineno">15938</span>&#160;        <span class="keywordflow">if</span>(createInfo.<a class="code" href="struct_vma_allocation_create_info.html#a6272c0555cfd1fe28bff1afeb6190150">pool</a> != VK_NULL_HANDLE)</div>
+<div class="line"><a name="l15939"></a><span class="lineno">15939</span>&#160;        {</div>
+<div class="line"><a name="l15940"></a><span class="lineno">15940</span>&#160;            VMA_ASSERT(0 &amp;&amp; <span class="stringliteral">&quot;Pool specified while dedicated allocation is required.&quot;</span>);</div>
+<div class="line"><a name="l15941"></a><span class="lineno">15941</span>&#160;            <span class="keywordflow">return</span> VK_ERROR_OUT_OF_DEVICE_MEMORY;</div>
+<div class="line"><a name="l15942"></a><span class="lineno">15942</span>&#160;        }</div>
+<div class="line"><a name="l15943"></a><span class="lineno">15943</span>&#160;    }</div>
+<div class="line"><a name="l15944"></a><span class="lineno">15944</span>&#160;    <span class="keywordflow">if</span>((createInfo.<a class="code" href="struct_vma_allocation_create_info.html#a6272c0555cfd1fe28bff1afeb6190150">pool</a> != VK_NULL_HANDLE) &amp;&amp;</div>
+<div class="line"><a name="l15945"></a><span class="lineno">15945</span>&#160;        ((createInfo.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a> &amp; (<a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a3fc311d855c2ff53f1090ef5c722b38f">VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT</a>)) != 0))</div>
+<div class="line"><a name="l15946"></a><span class="lineno">15946</span>&#160;    {</div>
+<div class="line"><a name="l15947"></a><span class="lineno">15947</span>&#160;        VMA_ASSERT(0 &amp;&amp; <span class="stringliteral">&quot;Specifying VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT when pool != null is invalid.&quot;</span>);</div>
+<div class="line"><a name="l15948"></a><span class="lineno">15948</span>&#160;        <span class="keywordflow">return</span> VK_ERROR_OUT_OF_DEVICE_MEMORY;</div>
+<div class="line"><a name="l15949"></a><span class="lineno">15949</span>&#160;    }</div>
+<div class="line"><a name="l15950"></a><span class="lineno">15950</span>&#160; </div>
+<div class="line"><a name="l15951"></a><span class="lineno">15951</span>&#160;    <span class="keywordflow">if</span>(createInfo.<a class="code" href="struct_vma_allocation_create_info.html#a6272c0555cfd1fe28bff1afeb6190150">pool</a> != VK_NULL_HANDLE)</div>
+<div class="line"><a name="l15952"></a><span class="lineno">15952</span>&#160;    {</div>
+<div class="line"><a name="l15953"></a><span class="lineno">15953</span>&#160;        <span class="keyword">const</span> VkDeviceSize alignmentForPool = VMA_MAX(</div>
+<div class="line"><a name="l15954"></a><span class="lineno">15954</span>&#160;            vkMemReq.alignment,</div>
+<div class="line"><a name="l15955"></a><span class="lineno">15955</span>&#160;            GetMemoryTypeMinAlignment(createInfo.<a class="code" href="struct_vma_allocation_create_info.html#a6272c0555cfd1fe28bff1afeb6190150">pool</a>-&gt;m_BlockVector.GetMemoryTypeIndex()));</div>
+<div class="line"><a name="l15956"></a><span class="lineno">15956</span>&#160; </div>
+<div class="line"><a name="l15957"></a><span class="lineno">15957</span>&#160;        <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a> createInfoForPool = createInfo;</div>
+<div class="line"><a name="l15958"></a><span class="lineno">15958</span>&#160;        <span class="comment">// If memory type is not HOST_VISIBLE, disable MAPPED.</span></div>
+<div class="line"><a name="l15959"></a><span class="lineno">15959</span>&#160;        <span class="keywordflow">if</span>((createInfoForPool.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a> &amp; <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a11da372cc3a82931c5e5d6146cd9dd1f">VMA_ALLOCATION_CREATE_MAPPED_BIT</a>) != 0 &amp;&amp;</div>
+<div class="line"><a name="l15960"></a><span class="lineno">15960</span>&#160;            (m_MemProps.memoryTypes[createInfo.<a class="code" href="struct_vma_allocation_create_info.html#a6272c0555cfd1fe28bff1afeb6190150">pool</a>-&gt;m_BlockVector.GetMemoryTypeIndex()].propertyFlags &amp; VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0)</div>
+<div class="line"><a name="l15961"></a><span class="lineno">15961</span>&#160;        {</div>
+<div class="line"><a name="l15962"></a><span class="lineno">15962</span>&#160;            createInfoForPool.<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a> &amp;= ~<a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a11da372cc3a82931c5e5d6146cd9dd1f">VMA_ALLOCATION_CREATE_MAPPED_BIT</a>;</div>
+<div class="line"><a name="l15963"></a><span class="lineno">15963</span>&#160;        }</div>
+<div class="line"><a name="l15964"></a><span class="lineno">15964</span>&#160; </div>
+<div class="line"><a name="l15965"></a><span class="lineno">15965</span>&#160;        <span class="keywordflow">return</span> createInfo.<a class="code" href="struct_vma_allocation_create_info.html#a6272c0555cfd1fe28bff1afeb6190150">pool</a>-&gt;m_BlockVector.Allocate(</div>
+<div class="line"><a name="l15966"></a><span class="lineno">15966</span>&#160;            m_CurrentFrameIndex.load(),</div>
+<div class="line"><a name="l15967"></a><span class="lineno">15967</span>&#160;            vkMemReq.size,</div>
+<div class="line"><a name="l15968"></a><span class="lineno">15968</span>&#160;            alignmentForPool,</div>
+<div class="line"><a name="l15969"></a><span class="lineno">15969</span>&#160;            createInfoForPool,</div>
+<div class="line"><a name="l15970"></a><span class="lineno">15970</span>&#160;            suballocType,</div>
+<div class="line"><a name="l15971"></a><span class="lineno">15971</span>&#160;            allocationCount,</div>
+<div class="line"><a name="l15972"></a><span class="lineno">15972</span>&#160;            pAllocations);</div>
+<div class="line"><a name="l15973"></a><span class="lineno">15973</span>&#160;    }</div>
+<div class="line"><a name="l15974"></a><span class="lineno">15974</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l15975"></a><span class="lineno">15975</span>&#160;    {</div>
+<div class="line"><a name="l15976"></a><span class="lineno">15976</span>&#160;        <span class="comment">// Bit mask of memory Vulkan types acceptable for this allocation.</span></div>
+<div class="line"><a name="l15977"></a><span class="lineno">15977</span>&#160;        uint32_t memoryTypeBits = vkMemReq.memoryTypeBits;</div>
+<div class="line"><a name="l15978"></a><span class="lineno">15978</span>&#160;        uint32_t memTypeIndex = UINT32_MAX;</div>
+<div class="line"><a name="l15979"></a><span class="lineno">15979</span>&#160;        VkResult res = <a class="code" href="vk__mem__alloc_8h.html#aef15a94b58fbcb0fe706d5720e84a74a">vmaFindMemoryTypeIndex</a>(<span class="keyword">this</span>, memoryTypeBits, &amp;createInfo, &amp;memTypeIndex);</div>
+<div class="line"><a name="l15980"></a><span class="lineno">15980</span>&#160;        <span class="keywordflow">if</span>(res == VK_SUCCESS)</div>
+<div class="line"><a name="l15981"></a><span class="lineno">15981</span>&#160;        {</div>
+<div class="line"><a name="l15982"></a><span class="lineno">15982</span>&#160;            VkDeviceSize alignmentForMemType = VMA_MAX(</div>
+<div class="line"><a name="l15983"></a><span class="lineno">15983</span>&#160;                vkMemReq.alignment,</div>
+<div class="line"><a name="l15984"></a><span class="lineno">15984</span>&#160;                GetMemoryTypeMinAlignment(memTypeIndex));</div>
+<div class="line"><a name="l15985"></a><span class="lineno">15985</span>&#160; </div>
+<div class="line"><a name="l15986"></a><span class="lineno">15986</span>&#160;            res = AllocateMemoryOfType(</div>
+<div class="line"><a name="l15987"></a><span class="lineno">15987</span>&#160;                vkMemReq.size,</div>
+<div class="line"><a name="l15988"></a><span class="lineno">15988</span>&#160;                alignmentForMemType,</div>
+<div class="line"><a name="l15989"></a><span class="lineno">15989</span>&#160;                requiresDedicatedAllocation || prefersDedicatedAllocation,</div>
+<div class="line"><a name="l15990"></a><span class="lineno">15990</span>&#160;                dedicatedBuffer,</div>
+<div class="line"><a name="l15991"></a><span class="lineno">15991</span>&#160;                dedicatedBufferUsage,</div>
+<div class="line"><a name="l15992"></a><span class="lineno">15992</span>&#160;                dedicatedImage,</div>
+<div class="line"><a name="l15993"></a><span class="lineno">15993</span>&#160;                createInfo,</div>
+<div class="line"><a name="l15994"></a><span class="lineno">15994</span>&#160;                memTypeIndex,</div>
+<div class="line"><a name="l15995"></a><span class="lineno">15995</span>&#160;                suballocType,</div>
+<div class="line"><a name="l15996"></a><span class="lineno">15996</span>&#160;                allocationCount,</div>
+<div class="line"><a name="l15997"></a><span class="lineno">15997</span>&#160;                pAllocations);</div>
+<div class="line"><a name="l15998"></a><span class="lineno">15998</span>&#160;            <span class="comment">// Succeeded on first try.</span></div>
+<div class="line"><a name="l15999"></a><span class="lineno">15999</span>&#160;            <span class="keywordflow">if</span>(res == VK_SUCCESS)</div>
+<div class="line"><a name="l16000"></a><span class="lineno">16000</span>&#160;            {</div>
+<div class="line"><a name="l16001"></a><span class="lineno">16001</span>&#160;                <span class="keywordflow">return</span> res;</div>
+<div class="line"><a name="l16002"></a><span class="lineno">16002</span>&#160;            }</div>
+<div class="line"><a name="l16003"></a><span class="lineno">16003</span>&#160;            <span class="comment">// Allocation from this memory type failed. Try other compatible memory types.</span></div>
+<div class="line"><a name="l16004"></a><span class="lineno">16004</span>&#160;            <span class="keywordflow">else</span></div>
+<div class="line"><a name="l16005"></a><span class="lineno">16005</span>&#160;            {</div>
+<div class="line"><a name="l16006"></a><span class="lineno">16006</span>&#160;                <span class="keywordflow">for</span>(;;)</div>
+<div class="line"><a name="l16007"></a><span class="lineno">16007</span>&#160;                {</div>
+<div class="line"><a name="l16008"></a><span class="lineno">16008</span>&#160;                    <span class="comment">// Remove old memTypeIndex from list of possibilities.</span></div>
+<div class="line"><a name="l16009"></a><span class="lineno">16009</span>&#160;                    memoryTypeBits &amp;= ~(1u &lt;&lt; memTypeIndex);</div>
+<div class="line"><a name="l16010"></a><span class="lineno">16010</span>&#160;                    <span class="comment">// Find alternative memTypeIndex.</span></div>
+<div class="line"><a name="l16011"></a><span class="lineno">16011</span>&#160;                    res = <a class="code" href="vk__mem__alloc_8h.html#aef15a94b58fbcb0fe706d5720e84a74a">vmaFindMemoryTypeIndex</a>(<span class="keyword">this</span>, memoryTypeBits, &amp;createInfo, &amp;memTypeIndex);</div>
+<div class="line"><a name="l16012"></a><span class="lineno">16012</span>&#160;                    <span class="keywordflow">if</span>(res == VK_SUCCESS)</div>
+<div class="line"><a name="l16013"></a><span class="lineno">16013</span>&#160;                    {</div>
+<div class="line"><a name="l16014"></a><span class="lineno">16014</span>&#160;                        alignmentForMemType = VMA_MAX(</div>
+<div class="line"><a name="l16015"></a><span class="lineno">16015</span>&#160;                            vkMemReq.alignment,</div>
+<div class="line"><a name="l16016"></a><span class="lineno">16016</span>&#160;                            GetMemoryTypeMinAlignment(memTypeIndex));</div>
+<div class="line"><a name="l16017"></a><span class="lineno">16017</span>&#160;                        </div>
+<div class="line"><a name="l16018"></a><span class="lineno">16018</span>&#160;                        res = AllocateMemoryOfType(</div>
+<div class="line"><a name="l16019"></a><span class="lineno">16019</span>&#160;                            vkMemReq.size,</div>
+<div class="line"><a name="l16020"></a><span class="lineno">16020</span>&#160;                            alignmentForMemType,</div>
+<div class="line"><a name="l16021"></a><span class="lineno">16021</span>&#160;                            requiresDedicatedAllocation || prefersDedicatedAllocation,</div>
+<div class="line"><a name="l16022"></a><span class="lineno">16022</span>&#160;                            dedicatedBuffer,</div>
+<div class="line"><a name="l16023"></a><span class="lineno">16023</span>&#160;                            dedicatedBufferUsage,</div>
+<div class="line"><a name="l16024"></a><span class="lineno">16024</span>&#160;                            dedicatedImage,</div>
+<div class="line"><a name="l16025"></a><span class="lineno">16025</span>&#160;                            createInfo,</div>
+<div class="line"><a name="l16026"></a><span class="lineno">16026</span>&#160;                            memTypeIndex,</div>
+<div class="line"><a name="l16027"></a><span class="lineno">16027</span>&#160;                            suballocType,</div>
+<div class="line"><a name="l16028"></a><span class="lineno">16028</span>&#160;                            allocationCount,</div>
+<div class="line"><a name="l16029"></a><span class="lineno">16029</span>&#160;                            pAllocations);</div>
+<div class="line"><a name="l16030"></a><span class="lineno">16030</span>&#160;                        <span class="comment">// Allocation from this alternative memory type succeeded.</span></div>
+<div class="line"><a name="l16031"></a><span class="lineno">16031</span>&#160;                        <span class="keywordflow">if</span>(res == VK_SUCCESS)</div>
+<div class="line"><a name="l16032"></a><span class="lineno">16032</span>&#160;                        {</div>
+<div class="line"><a name="l16033"></a><span class="lineno">16033</span>&#160;                            <span class="keywordflow">return</span> res;</div>
+<div class="line"><a name="l16034"></a><span class="lineno">16034</span>&#160;                        }</div>
+<div class="line"><a name="l16035"></a><span class="lineno">16035</span>&#160;                        <span class="comment">// else: Allocation from this memory type failed. Try next one - next loop iteration.</span></div>
+<div class="line"><a name="l16036"></a><span class="lineno">16036</span>&#160;                    }</div>
+<div class="line"><a name="l16037"></a><span class="lineno">16037</span>&#160;                    <span class="comment">// No other matching memory type index could be found.</span></div>
+<div class="line"><a name="l16038"></a><span class="lineno">16038</span>&#160;                    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l16039"></a><span class="lineno">16039</span>&#160;                    {</div>
+<div class="line"><a name="l16040"></a><span class="lineno">16040</span>&#160;                        <span class="comment">// Not returning res, which is VK_ERROR_FEATURE_NOT_PRESENT, because we already failed to allocate once.</span></div>
+<div class="line"><a name="l16041"></a><span class="lineno">16041</span>&#160;                        <span class="keywordflow">return</span> VK_ERROR_OUT_OF_DEVICE_MEMORY;</div>
+<div class="line"><a name="l16042"></a><span class="lineno">16042</span>&#160;                    }</div>
+<div class="line"><a name="l16043"></a><span class="lineno">16043</span>&#160;                }</div>
+<div class="line"><a name="l16044"></a><span class="lineno">16044</span>&#160;            }</div>
+<div class="line"><a name="l16045"></a><span class="lineno">16045</span>&#160;        }</div>
+<div class="line"><a name="l16046"></a><span class="lineno">16046</span>&#160;        <span class="comment">// Can&#39;t find any single memory type maching requirements. res is VK_ERROR_FEATURE_NOT_PRESENT.</span></div>
+<div class="line"><a name="l16047"></a><span class="lineno">16047</span>&#160;        <span class="keywordflow">else</span></div>
+<div class="line"><a name="l16048"></a><span class="lineno">16048</span>&#160;            <span class="keywordflow">return</span> res;</div>
+<div class="line"><a name="l16049"></a><span class="lineno">16049</span>&#160;    }</div>
+<div class="line"><a name="l16050"></a><span class="lineno">16050</span>&#160;}</div>
+<div class="line"><a name="l16051"></a><span class="lineno">16051</span>&#160; </div>
+<div class="line"><a name="l16052"></a><span class="lineno">16052</span>&#160;<span class="keywordtype">void</span> VmaAllocator_T::FreeMemory(</div>
+<div class="line"><a name="l16053"></a><span class="lineno">16053</span>&#160;    <span class="keywordtype">size_t</span> allocationCount,</div>
+<div class="line"><a name="l16054"></a><span class="lineno">16054</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocations)</div>
+<div class="line"><a name="l16055"></a><span class="lineno">16055</span>&#160;{</div>
+<div class="line"><a name="l16056"></a><span class="lineno">16056</span>&#160;    VMA_ASSERT(pAllocations);</div>
+<div class="line"><a name="l16057"></a><span class="lineno">16057</span>&#160; </div>
+<div class="line"><a name="l16058"></a><span class="lineno">16058</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> allocIndex = allocationCount; allocIndex--; )</div>
+<div class="line"><a name="l16059"></a><span class="lineno">16059</span>&#160;    {</div>
+<div class="line"><a name="l16060"></a><span class="lineno">16060</span>&#160;        <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation = pAllocations[allocIndex];</div>
+<div class="line"><a name="l16061"></a><span class="lineno">16061</span>&#160; </div>
+<div class="line"><a name="l16062"></a><span class="lineno">16062</span>&#160;        <span class="keywordflow">if</span>(allocation != VK_NULL_HANDLE)</div>
+<div class="line"><a name="l16063"></a><span class="lineno">16063</span>&#160;        {</div>
+<div class="line"><a name="l16064"></a><span class="lineno">16064</span>&#160;            <span class="keywordflow">if</span>(TouchAllocation(allocation))</div>
+<div class="line"><a name="l16065"></a><span class="lineno">16065</span>&#160;            {</div>
+<div class="line"><a name="l16066"></a><span class="lineno">16066</span>&#160;                <span class="keywordflow">if</span>(VMA_DEBUG_INITIALIZE_ALLOCATIONS)</div>
+<div class="line"><a name="l16067"></a><span class="lineno">16067</span>&#160;                {</div>
+<div class="line"><a name="l16068"></a><span class="lineno">16068</span>&#160;                    FillAllocation(allocation, VMA_ALLOCATION_FILL_PATTERN_DESTROYED);</div>
+<div class="line"><a name="l16069"></a><span class="lineno">16069</span>&#160;                }</div>
+<div class="line"><a name="l16070"></a><span class="lineno">16070</span>&#160; </div>
+<div class="line"><a name="l16071"></a><span class="lineno">16071</span>&#160;                <span class="keywordflow">switch</span>(allocation-&gt;GetType())</div>
+<div class="line"><a name="l16072"></a><span class="lineno">16072</span>&#160;                {</div>
+<div class="line"><a name="l16073"></a><span class="lineno">16073</span>&#160;                <span class="keywordflow">case</span> VmaAllocation_T::ALLOCATION_TYPE_BLOCK:</div>
+<div class="line"><a name="l16074"></a><span class="lineno">16074</span>&#160;                    {</div>
+<div class="line"><a name="l16075"></a><span class="lineno">16075</span>&#160;                        VmaBlockVector* pBlockVector = VMA_NULL;</div>
+<div class="line"><a name="l16076"></a><span class="lineno">16076</span>&#160;                        <a class="code" href="struct_vma_pool.html">VmaPool</a> hPool = allocation-&gt;GetBlock()-&gt;GetParentPool();</div>
+<div class="line"><a name="l16077"></a><span class="lineno">16077</span>&#160;                        <span class="keywordflow">if</span>(hPool != VK_NULL_HANDLE)</div>
+<div class="line"><a name="l16078"></a><span class="lineno">16078</span>&#160;                        {</div>
+<div class="line"><a name="l16079"></a><span class="lineno">16079</span>&#160;                            pBlockVector = &amp;hPool-&gt;m_BlockVector;</div>
+<div class="line"><a name="l16080"></a><span class="lineno">16080</span>&#160;                        }</div>
+<div class="line"><a name="l16081"></a><span class="lineno">16081</span>&#160;                        <span class="keywordflow">else</span></div>
+<div class="line"><a name="l16082"></a><span class="lineno">16082</span>&#160;                        {</div>
+<div class="line"><a name="l16083"></a><span class="lineno">16083</span>&#160;                            <span class="keyword">const</span> uint32_t memTypeIndex = allocation-&gt;GetMemoryTypeIndex();</div>
+<div class="line"><a name="l16084"></a><span class="lineno">16084</span>&#160;                            pBlockVector = m_pBlockVectors[memTypeIndex];</div>
+<div class="line"><a name="l16085"></a><span class="lineno">16085</span>&#160;                        }</div>
+<div class="line"><a name="l16086"></a><span class="lineno">16086</span>&#160;                        pBlockVector-&gt;Free(allocation);</div>
+<div class="line"><a name="l16087"></a><span class="lineno">16087</span>&#160;                    }</div>
+<div class="line"><a name="l16088"></a><span class="lineno">16088</span>&#160;                    <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l16089"></a><span class="lineno">16089</span>&#160;                <span class="keywordflow">case</span> VmaAllocation_T::ALLOCATION_TYPE_DEDICATED:</div>
+<div class="line"><a name="l16090"></a><span class="lineno">16090</span>&#160;                    FreeDedicatedMemory(allocation);</div>
+<div class="line"><a name="l16091"></a><span class="lineno">16091</span>&#160;                    <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l16092"></a><span class="lineno">16092</span>&#160;                <span class="keywordflow">default</span>:</div>
+<div class="line"><a name="l16093"></a><span class="lineno">16093</span>&#160;                    VMA_ASSERT(0);</div>
+<div class="line"><a name="l16094"></a><span class="lineno">16094</span>&#160;                }</div>
+<div class="line"><a name="l16095"></a><span class="lineno">16095</span>&#160;            }</div>
+<div class="line"><a name="l16096"></a><span class="lineno">16096</span>&#160; </div>
+<div class="line"><a name="l16097"></a><span class="lineno">16097</span>&#160;            <span class="comment">// Do this regardless of whether the allocation is lost. Lost allocations still account to Budget.AllocationBytes.</span></div>
+<div class="line"><a name="l16098"></a><span class="lineno">16098</span>&#160;            m_Budget.RemoveAllocation(MemoryTypeIndexToHeapIndex(allocation-&gt;GetMemoryTypeIndex()), allocation-&gt;GetSize());</div>
+<div class="line"><a name="l16099"></a><span class="lineno">16099</span>&#160;            allocation-&gt;SetUserData(<span class="keyword">this</span>, VMA_NULL);</div>
+<div class="line"><a name="l16100"></a><span class="lineno">16100</span>&#160;            m_AllocationObjectAllocator.Free(allocation);</div>
+<div class="line"><a name="l16101"></a><span class="lineno">16101</span>&#160;        }</div>
+<div class="line"><a name="l16102"></a><span class="lineno">16102</span>&#160;    }</div>
+<div class="line"><a name="l16103"></a><span class="lineno">16103</span>&#160;}</div>
+<div class="line"><a name="l16104"></a><span class="lineno">16104</span>&#160; </div>
+<div class="line"><a name="l16105"></a><span class="lineno">16105</span>&#160;VkResult VmaAllocator_T::ResizeAllocation(</div>
+<div class="line"><a name="l16106"></a><span class="lineno">16106</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> alloc,</div>
+<div class="line"><a name="l16107"></a><span class="lineno">16107</span>&#160;    VkDeviceSize newSize)</div>
+<div class="line"><a name="l16108"></a><span class="lineno">16108</span>&#160;{</div>
+<div class="line"><a name="l16109"></a><span class="lineno">16109</span>&#160;    <span class="comment">// This function is deprecated and so it does nothing. It&#39;s left for backward compatibility.</span></div>
+<div class="line"><a name="l16110"></a><span class="lineno">16110</span>&#160;    <span class="keywordflow">if</span>(newSize == 0 || alloc-&gt;GetLastUseFrameIndex() == VMA_FRAME_INDEX_LOST)</div>
+<div class="line"><a name="l16111"></a><span class="lineno">16111</span>&#160;    {</div>
+<div class="line"><a name="l16112"></a><span class="lineno">16112</span>&#160;        <span class="keywordflow">return</span> VK_ERROR_VALIDATION_FAILED_EXT;</div>
+<div class="line"><a name="l16113"></a><span class="lineno">16113</span>&#160;    }</div>
+<div class="line"><a name="l16114"></a><span class="lineno">16114</span>&#160;    <span class="keywordflow">if</span>(newSize == alloc-&gt;GetSize())</div>
+<div class="line"><a name="l16115"></a><span class="lineno">16115</span>&#160;    {</div>
+<div class="line"><a name="l16116"></a><span class="lineno">16116</span>&#160;        <span class="keywordflow">return</span> VK_SUCCESS;</div>
+<div class="line"><a name="l16117"></a><span class="lineno">16117</span>&#160;    }</div>
+<div class="line"><a name="l16118"></a><span class="lineno">16118</span>&#160;    <span class="keywordflow">return</span> VK_ERROR_OUT_OF_POOL_MEMORY;</div>
+<div class="line"><a name="l16119"></a><span class="lineno">16119</span>&#160;}</div>
+<div class="line"><a name="l16120"></a><span class="lineno">16120</span>&#160; </div>
+<div class="line"><a name="l16121"></a><span class="lineno">16121</span>&#160;<span class="keywordtype">void</span> VmaAllocator_T::CalculateStats(<a class="code" href="struct_vma_stats.html">VmaStats</a>* pStats)</div>
+<div class="line"><a name="l16122"></a><span class="lineno">16122</span>&#160;{</div>
+<div class="line"><a name="l16123"></a><span class="lineno">16123</span>&#160;    <span class="comment">// Initialize.</span></div>
+<div class="line"><a name="l16124"></a><span class="lineno">16124</span>&#160;    InitStatInfo(pStats-&gt;<a class="code" href="struct_vma_stats.html#a2e8f5b3353f2fefef3c27f29e245a1f9">total</a>);</div>
+<div class="line"><a name="l16125"></a><span class="lineno">16125</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = 0; i &lt; VK_MAX_MEMORY_TYPES; ++i)</div>
+<div class="line"><a name="l16126"></a><span class="lineno">16126</span>&#160;        InitStatInfo(pStats-&gt;<a class="code" href="struct_vma_stats.html#a13e3caf754be79352c42408756309331">memoryType</a>[i]);</div>
+<div class="line"><a name="l16127"></a><span class="lineno">16127</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = 0; i &lt; VK_MAX_MEMORY_HEAPS; ++i)</div>
+<div class="line"><a name="l16128"></a><span class="lineno">16128</span>&#160;        InitStatInfo(pStats-&gt;<a class="code" href="struct_vma_stats.html#a0e6611508c29a187f0fd14ff1a0329c0">memoryHeap</a>[i]);</div>
+<div class="line"><a name="l16129"></a><span class="lineno">16129</span>&#160;    </div>
+<div class="line"><a name="l16130"></a><span class="lineno">16130</span>&#160;    <span class="comment">// Process default pools.</span></div>
+<div class="line"><a name="l16131"></a><span class="lineno">16131</span>&#160;    <span class="keywordflow">for</span>(uint32_t memTypeIndex = 0; memTypeIndex &lt; GetMemoryTypeCount(); ++memTypeIndex)</div>
+<div class="line"><a name="l16132"></a><span class="lineno">16132</span>&#160;    {</div>
+<div class="line"><a name="l16133"></a><span class="lineno">16133</span>&#160;        VmaBlockVector* <span class="keyword">const</span> pBlockVector = m_pBlockVectors[memTypeIndex];</div>
+<div class="line"><a name="l16134"></a><span class="lineno">16134</span>&#160;        VMA_ASSERT(pBlockVector);</div>
+<div class="line"><a name="l16135"></a><span class="lineno">16135</span>&#160;        pBlockVector-&gt;AddStats(pStats);</div>
+<div class="line"><a name="l16136"></a><span class="lineno">16136</span>&#160;    }</div>
+<div class="line"><a name="l16137"></a><span class="lineno">16137</span>&#160; </div>
+<div class="line"><a name="l16138"></a><span class="lineno">16138</span>&#160;    <span class="comment">// Process custom pools.</span></div>
+<div class="line"><a name="l16139"></a><span class="lineno">16139</span>&#160;    {</div>
+<div class="line"><a name="l16140"></a><span class="lineno">16140</span>&#160;        VmaMutexLockRead lock(m_PoolsMutex, m_UseMutex);</div>
+<div class="line"><a name="l16141"></a><span class="lineno">16141</span>&#160;        <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> poolIndex = 0, poolCount = m_Pools.size(); poolIndex &lt; poolCount; ++poolIndex)</div>
+<div class="line"><a name="l16142"></a><span class="lineno">16142</span>&#160;        {</div>
+<div class="line"><a name="l16143"></a><span class="lineno">16143</span>&#160;            m_Pools[poolIndex]-&gt;m_BlockVector.AddStats(pStats);</div>
+<div class="line"><a name="l16144"></a><span class="lineno">16144</span>&#160;        }</div>
+<div class="line"><a name="l16145"></a><span class="lineno">16145</span>&#160;    }</div>
+<div class="line"><a name="l16146"></a><span class="lineno">16146</span>&#160; </div>
+<div class="line"><a name="l16147"></a><span class="lineno">16147</span>&#160;    <span class="comment">// Process dedicated allocations.</span></div>
+<div class="line"><a name="l16148"></a><span class="lineno">16148</span>&#160;    <span class="keywordflow">for</span>(uint32_t memTypeIndex = 0; memTypeIndex &lt; GetMemoryTypeCount(); ++memTypeIndex)</div>
+<div class="line"><a name="l16149"></a><span class="lineno">16149</span>&#160;    {</div>
+<div class="line"><a name="l16150"></a><span class="lineno">16150</span>&#160;        <span class="keyword">const</span> uint32_t memHeapIndex = MemoryTypeIndexToHeapIndex(memTypeIndex);</div>
+<div class="line"><a name="l16151"></a><span class="lineno">16151</span>&#160;        VmaMutexLockRead dedicatedAllocationsLock(m_DedicatedAllocationsMutex[memTypeIndex], m_UseMutex);</div>
+<div class="line"><a name="l16152"></a><span class="lineno">16152</span>&#160;        AllocationVectorType* <span class="keyword">const</span> pDedicatedAllocVector = m_pDedicatedAllocations[memTypeIndex];</div>
+<div class="line"><a name="l16153"></a><span class="lineno">16153</span>&#160;        VMA_ASSERT(pDedicatedAllocVector);</div>
+<div class="line"><a name="l16154"></a><span class="lineno">16154</span>&#160;        <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> allocIndex = 0, allocCount = pDedicatedAllocVector-&gt;size(); allocIndex &lt; allocCount; ++allocIndex)</div>
+<div class="line"><a name="l16155"></a><span class="lineno">16155</span>&#160;        {</div>
+<div class="line"><a name="l16156"></a><span class="lineno">16156</span>&#160;            <a class="code" href="struct_vma_stat_info.html">VmaStatInfo</a> allocationStatInfo;</div>
+<div class="line"><a name="l16157"></a><span class="lineno">16157</span>&#160;            (*pDedicatedAllocVector)[allocIndex]-&gt;DedicatedAllocCalcStatsInfo(allocationStatInfo);</div>
+<div class="line"><a name="l16158"></a><span class="lineno">16158</span>&#160;            VmaAddStatInfo(pStats-&gt;<a class="code" href="struct_vma_stats.html#a2e8f5b3353f2fefef3c27f29e245a1f9">total</a>, allocationStatInfo);</div>
+<div class="line"><a name="l16159"></a><span class="lineno">16159</span>&#160;            VmaAddStatInfo(pStats-&gt;<a class="code" href="struct_vma_stats.html#a13e3caf754be79352c42408756309331">memoryType</a>[memTypeIndex], allocationStatInfo);</div>
+<div class="line"><a name="l16160"></a><span class="lineno">16160</span>&#160;            VmaAddStatInfo(pStats-&gt;<a class="code" href="struct_vma_stats.html#a0e6611508c29a187f0fd14ff1a0329c0">memoryHeap</a>[memHeapIndex], allocationStatInfo);</div>
+<div class="line"><a name="l16161"></a><span class="lineno">16161</span>&#160;        }</div>
+<div class="line"><a name="l16162"></a><span class="lineno">16162</span>&#160;    }</div>
+<div class="line"><a name="l16163"></a><span class="lineno">16163</span>&#160; </div>
+<div class="line"><a name="l16164"></a><span class="lineno">16164</span>&#160;    <span class="comment">// Postprocess.</span></div>
+<div class="line"><a name="l16165"></a><span class="lineno">16165</span>&#160;    VmaPostprocessCalcStatInfo(pStats-&gt;<a class="code" href="struct_vma_stats.html#a2e8f5b3353f2fefef3c27f29e245a1f9">total</a>);</div>
+<div class="line"><a name="l16166"></a><span class="lineno">16166</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = 0; i &lt; GetMemoryTypeCount(); ++i)</div>
+<div class="line"><a name="l16167"></a><span class="lineno">16167</span>&#160;        VmaPostprocessCalcStatInfo(pStats-&gt;<a class="code" href="struct_vma_stats.html#a13e3caf754be79352c42408756309331">memoryType</a>[i]);</div>
+<div class="line"><a name="l16168"></a><span class="lineno">16168</span>&#160;    <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = 0; i &lt; GetMemoryHeapCount(); ++i)</div>
+<div class="line"><a name="l16169"></a><span class="lineno">16169</span>&#160;        VmaPostprocessCalcStatInfo(pStats-&gt;<a class="code" href="struct_vma_stats.html#a0e6611508c29a187f0fd14ff1a0329c0">memoryHeap</a>[i]);</div>
+<div class="line"><a name="l16170"></a><span class="lineno">16170</span>&#160;}</div>
+<div class="line"><a name="l16171"></a><span class="lineno">16171</span>&#160; </div>
+<div class="line"><a name="l16172"></a><span class="lineno">16172</span>&#160;<span class="keywordtype">void</span> VmaAllocator_T::GetBudget(<a class="code" href="struct_vma_budget.html">VmaBudget</a>* outBudget, uint32_t firstHeap, uint32_t heapCount)</div>
+<div class="line"><a name="l16173"></a><span class="lineno">16173</span>&#160;{</div>
+<div class="line"><a name="l16174"></a><span class="lineno">16174</span>&#160;<span class="preprocessor">#if VMA_MEMORY_BUDGET</span></div>
+<div class="line"><a name="l16175"></a><span class="lineno">16175</span>&#160;    <span class="keywordflow">if</span>(m_UseExtMemoryBudget)</div>
+<div class="line"><a name="l16176"></a><span class="lineno">16176</span>&#160;    {</div>
+<div class="line"><a name="l16177"></a><span class="lineno">16177</span>&#160;        <span class="keywordflow">if</span>(m_Budget.m_OperationsSinceBudgetFetch &lt; 30)</div>
+<div class="line"><a name="l16178"></a><span class="lineno">16178</span>&#160;        {</div>
+<div class="line"><a name="l16179"></a><span class="lineno">16179</span>&#160;            VmaMutexLockRead lockRead(m_Budget.m_BudgetMutex, m_UseMutex);</div>
+<div class="line"><a name="l16180"></a><span class="lineno">16180</span>&#160;            <span class="keywordflow">for</span>(uint32_t i = 0; i &lt; heapCount; ++i, ++outBudget)</div>
+<div class="line"><a name="l16181"></a><span class="lineno">16181</span>&#160;            {</div>
+<div class="line"><a name="l16182"></a><span class="lineno">16182</span>&#160;                <span class="keyword">const</span> uint32_t heapIndex = firstHeap + i;</div>
+<div class="line"><a name="l16183"></a><span class="lineno">16183</span>&#160; </div>
+<div class="line"><a name="l16184"></a><span class="lineno">16184</span>&#160;                outBudget-&gt;<a class="code" href="struct_vma_budget.html#a58b492901baab685f466199124e514a0">blockBytes</a> = m_Budget.m_BlockBytes[heapIndex];</div>
+<div class="line"><a name="l16185"></a><span class="lineno">16185</span>&#160;                outBudget-&gt;<a class="code" href="struct_vma_budget.html#a7e2a6583ebd63e194951c542563804d8">allocationBytes</a> = m_Budget.m_AllocationBytes[heapIndex];</div>
+<div class="line"><a name="l16186"></a><span class="lineno">16186</span>&#160; </div>
+<div class="line"><a name="l16187"></a><span class="lineno">16187</span>&#160;                <span class="keywordflow">if</span>(m_Budget.m_VulkanUsage[heapIndex] + outBudget-&gt;<a class="code" href="struct_vma_budget.html#a58b492901baab685f466199124e514a0">blockBytes</a> &gt; m_Budget.m_BlockBytesAtBudgetFetch[heapIndex])</div>
+<div class="line"><a name="l16188"></a><span class="lineno">16188</span>&#160;                {</div>
+<div class="line"><a name="l16189"></a><span class="lineno">16189</span>&#160;                    outBudget-&gt;<a class="code" href="struct_vma_budget.html#a84dd1ecca8b0110259eb206dbadb11f6">usage</a> = m_Budget.m_VulkanUsage[heapIndex] +</div>
+<div class="line"><a name="l16190"></a><span class="lineno">16190</span>&#160;                        outBudget-&gt;<a class="code" href="struct_vma_budget.html#a58b492901baab685f466199124e514a0">blockBytes</a> - m_Budget.m_BlockBytesAtBudgetFetch[heapIndex];</div>
+<div class="line"><a name="l16191"></a><span class="lineno">16191</span>&#160;                }</div>
+<div class="line"><a name="l16192"></a><span class="lineno">16192</span>&#160;                <span class="keywordflow">else</span></div>
+<div class="line"><a name="l16193"></a><span class="lineno">16193</span>&#160;                {</div>
+<div class="line"><a name="l16194"></a><span class="lineno">16194</span>&#160;                    outBudget-&gt;<a class="code" href="struct_vma_budget.html#a84dd1ecca8b0110259eb206dbadb11f6">usage</a> = 0;</div>
+<div class="line"><a name="l16195"></a><span class="lineno">16195</span>&#160;                }</div>
+<div class="line"><a name="l16196"></a><span class="lineno">16196</span>&#160; </div>
+<div class="line"><a name="l16197"></a><span class="lineno">16197</span>&#160;                <span class="comment">// Have to take MIN with heap size because explicit HeapSizeLimit is included in it.</span></div>
+<div class="line"><a name="l16198"></a><span class="lineno">16198</span>&#160;                outBudget-&gt;<a class="code" href="struct_vma_budget.html#ab82e1d1754c2d210d0bdf90220bc6cdd">budget</a> = VMA_MIN(</div>
+<div class="line"><a name="l16199"></a><span class="lineno">16199</span>&#160;                    m_Budget.m_VulkanBudget[heapIndex], m_MemProps.memoryHeaps[heapIndex].size);</div>
+<div class="line"><a name="l16200"></a><span class="lineno">16200</span>&#160;            }</div>
+<div class="line"><a name="l16201"></a><span class="lineno">16201</span>&#160;        }</div>
+<div class="line"><a name="l16202"></a><span class="lineno">16202</span>&#160;        <span class="keywordflow">else</span></div>
+<div class="line"><a name="l16203"></a><span class="lineno">16203</span>&#160;        {</div>
+<div class="line"><a name="l16204"></a><span class="lineno">16204</span>&#160;            UpdateVulkanBudget(); <span class="comment">// Outside of mutex lock</span></div>
+<div class="line"><a name="l16205"></a><span class="lineno">16205</span>&#160;            GetBudget(outBudget, firstHeap, heapCount); <span class="comment">// Recursion</span></div>
+<div class="line"><a name="l16206"></a><span class="lineno">16206</span>&#160;        }</div>
+<div class="line"><a name="l16207"></a><span class="lineno">16207</span>&#160;    }</div>
+<div class="line"><a name="l16208"></a><span class="lineno">16208</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l16209"></a><span class="lineno">16209</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l16210"></a><span class="lineno">16210</span>&#160;    {</div>
+<div class="line"><a name="l16211"></a><span class="lineno">16211</span>&#160;        <span class="keywordflow">for</span>(uint32_t i = 0; i &lt; heapCount; ++i, ++outBudget)</div>
+<div class="line"><a name="l16212"></a><span class="lineno">16212</span>&#160;        {</div>
+<div class="line"><a name="l16213"></a><span class="lineno">16213</span>&#160;            <span class="keyword">const</span> uint32_t heapIndex = firstHeap + i;</div>
+<div class="line"><a name="l16214"></a><span class="lineno">16214</span>&#160; </div>
+<div class="line"><a name="l16215"></a><span class="lineno">16215</span>&#160;            outBudget-&gt;<a class="code" href="struct_vma_budget.html#a58b492901baab685f466199124e514a0">blockBytes</a> = m_Budget.m_BlockBytes[heapIndex];</div>
+<div class="line"><a name="l16216"></a><span class="lineno">16216</span>&#160;            outBudget-&gt;<a class="code" href="struct_vma_budget.html#a7e2a6583ebd63e194951c542563804d8">allocationBytes</a> = m_Budget.m_AllocationBytes[heapIndex];</div>
+<div class="line"><a name="l16217"></a><span class="lineno">16217</span>&#160; </div>
+<div class="line"><a name="l16218"></a><span class="lineno">16218</span>&#160;            outBudget-&gt;<a class="code" href="struct_vma_budget.html#a84dd1ecca8b0110259eb206dbadb11f6">usage</a> = outBudget-&gt;<a class="code" href="struct_vma_budget.html#a58b492901baab685f466199124e514a0">blockBytes</a>;</div>
+<div class="line"><a name="l16219"></a><span class="lineno">16219</span>&#160;            outBudget-&gt;<a class="code" href="struct_vma_budget.html#ab82e1d1754c2d210d0bdf90220bc6cdd">budget</a> = m_MemProps.memoryHeaps[heapIndex].size * 8 / 10; <span class="comment">// 80% heuristics.</span></div>
+<div class="line"><a name="l16220"></a><span class="lineno">16220</span>&#160;        }</div>
+<div class="line"><a name="l16221"></a><span class="lineno">16221</span>&#160;    }</div>
+<div class="line"><a name="l16222"></a><span class="lineno">16222</span>&#160;}</div>
+<div class="line"><a name="l16223"></a><span class="lineno">16223</span>&#160; </div>
+<div class="line"><a name="l16224"></a><span class="lineno">16224</span>&#160;<span class="keyword">static</span> <span class="keyword">const</span> uint32_t VMA_VENDOR_ID_AMD = 4098;</div>
+<div class="line"><a name="l16225"></a><span class="lineno">16225</span>&#160; </div>
+<div class="line"><a name="l16226"></a><span class="lineno">16226</span>&#160;VkResult VmaAllocator_T::DefragmentationBegin(</div>
+<div class="line"><a name="l16227"></a><span class="lineno">16227</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_defragmentation_info2.html">VmaDefragmentationInfo2</a>&amp; info,</div>
+<div class="line"><a name="l16228"></a><span class="lineno">16228</span>&#160;    <a class="code" href="struct_vma_defragmentation_stats.html">VmaDefragmentationStats</a>* pStats,</div>
+<div class="line"><a name="l16229"></a><span class="lineno">16229</span>&#160;    <a class="code" href="struct_vma_defragmentation_context.html">VmaDefragmentationContext</a>* pContext)</div>
+<div class="line"><a name="l16230"></a><span class="lineno">16230</span>&#160;{</div>
+<div class="line"><a name="l16231"></a><span class="lineno">16231</span>&#160;    <span class="keywordflow">if</span>(info.<a class="code" href="struct_vma_defragmentation_info2.html#a76d51a644dc7f5405d0cdd0025ecd0cc">pAllocationsChanged</a> != VMA_NULL)</div>
+<div class="line"><a name="l16232"></a><span class="lineno">16232</span>&#160;    {</div>
+<div class="line"><a name="l16233"></a><span class="lineno">16233</span>&#160;        memset(info.<a class="code" href="struct_vma_defragmentation_info2.html#a76d51a644dc7f5405d0cdd0025ecd0cc">pAllocationsChanged</a>, 0, info.<a class="code" href="struct_vma_defragmentation_info2.html#a3cf86ab32c1da779b4923d301a3056ba">allocationCount</a> * <span class="keyword">sizeof</span>(VkBool32));</div>
+<div class="line"><a name="l16234"></a><span class="lineno">16234</span>&#160;    }</div>
+<div class="line"><a name="l16235"></a><span class="lineno">16235</span>&#160; </div>
+<div class="line"><a name="l16236"></a><span class="lineno">16236</span>&#160;    *pContext = vma_new(<span class="keyword">this</span>, VmaDefragmentationContext_T)(</div>
+<div class="line"><a name="l16237"></a><span class="lineno">16237</span>&#160;        <span class="keyword">this</span>, m_CurrentFrameIndex.load(), info.<a class="code" href="struct_vma_defragmentation_info2.html#a53e844ee5633e229cf6daf14b2d9fff9">flags</a>, pStats);</div>
+<div class="line"><a name="l16238"></a><span class="lineno">16238</span>&#160; </div>
+<div class="line"><a name="l16239"></a><span class="lineno">16239</span>&#160;    (*pContext)-&gt;AddPools(info.<a class="code" href="struct_vma_defragmentation_info2.html#a7e70aa2a1081d849dcc7829b19d3ec9d">poolCount</a>, info.<a class="code" href="struct_vma_defragmentation_info2.html#a0b3effd57f3fcdeb2ed62210b4ef20e1">pPools</a>);</div>
+<div class="line"><a name="l16240"></a><span class="lineno">16240</span>&#160;    (*pContext)-&gt;AddAllocations(</div>
+<div class="line"><a name="l16241"></a><span class="lineno">16241</span>&#160;        info.<a class="code" href="struct_vma_defragmentation_info2.html#a3cf86ab32c1da779b4923d301a3056ba">allocationCount</a>, info.<a class="code" href="struct_vma_defragmentation_info2.html#a8943f8d65969ce8e2189a1cdf3205e96">pAllocations</a>, info.<a class="code" href="struct_vma_defragmentation_info2.html#a76d51a644dc7f5405d0cdd0025ecd0cc">pAllocationsChanged</a>);</div>
+<div class="line"><a name="l16242"></a><span class="lineno">16242</span>&#160; </div>
+<div class="line"><a name="l16243"></a><span class="lineno">16243</span>&#160;    VkResult res = (*pContext)-&gt;Defragment(</div>
+<div class="line"><a name="l16244"></a><span class="lineno">16244</span>&#160;        info.<a class="code" href="struct_vma_defragmentation_info2.html#af78e1ea40c22d85137b65f6b384a4d0a">maxCpuBytesToMove</a>, info.<a class="code" href="struct_vma_defragmentation_info2.html#a94c2c7223d52878445a8cccce396b671">maxCpuAllocationsToMove</a>,</div>
+<div class="line"><a name="l16245"></a><span class="lineno">16245</span>&#160;        info.<a class="code" href="struct_vma_defragmentation_info2.html#a4ddbc898d0afe1518f863a3763628f08">maxGpuBytesToMove</a>, info.<a class="code" href="struct_vma_defragmentation_info2.html#a40d53d33e71ba0b66f844ed63c05a3f6">maxGpuAllocationsToMove</a>,</div>
+<div class="line"><a name="l16246"></a><span class="lineno">16246</span>&#160;        info.<a class="code" href="struct_vma_defragmentation_info2.html#a7f71f39590c5316771493d2333f9c1bd">commandBuffer</a>, pStats, info.<a class="code" href="struct_vma_defragmentation_info2.html#a53e844ee5633e229cf6daf14b2d9fff9">flags</a>);</div>
+<div class="line"><a name="l16247"></a><span class="lineno">16247</span>&#160; </div>
+<div class="line"><a name="l16248"></a><span class="lineno">16248</span>&#160;    <span class="keywordflow">if</span>(res != VK_NOT_READY)</div>
+<div class="line"><a name="l16249"></a><span class="lineno">16249</span>&#160;    {</div>
+<div class="line"><a name="l16250"></a><span class="lineno">16250</span>&#160;        vma_delete(<span class="keyword">this</span>, *pContext);</div>
+<div class="line"><a name="l16251"></a><span class="lineno">16251</span>&#160;        *pContext = VMA_NULL;</div>
+<div class="line"><a name="l16252"></a><span class="lineno">16252</span>&#160;    }</div>
+<div class="line"><a name="l16253"></a><span class="lineno">16253</span>&#160; </div>
+<div class="line"><a name="l16254"></a><span class="lineno">16254</span>&#160;    <span class="keywordflow">return</span> res;</div>
+<div class="line"><a name="l16255"></a><span class="lineno">16255</span>&#160;}</div>
+<div class="line"><a name="l16256"></a><span class="lineno">16256</span>&#160; </div>
+<div class="line"><a name="l16257"></a><span class="lineno">16257</span>&#160;VkResult VmaAllocator_T::DefragmentationEnd(</div>
+<div class="line"><a name="l16258"></a><span class="lineno">16258</span>&#160;    <a class="code" href="struct_vma_defragmentation_context.html">VmaDefragmentationContext</a> context)</div>
+<div class="line"><a name="l16259"></a><span class="lineno">16259</span>&#160;{</div>
+<div class="line"><a name="l16260"></a><span class="lineno">16260</span>&#160;    vma_delete(<span class="keyword">this</span>, context);</div>
+<div class="line"><a name="l16261"></a><span class="lineno">16261</span>&#160;    <span class="keywordflow">return</span> VK_SUCCESS;</div>
+<div class="line"><a name="l16262"></a><span class="lineno">16262</span>&#160;}</div>
+<div class="line"><a name="l16263"></a><span class="lineno">16263</span>&#160; </div>
+<div class="line"><a name="l16264"></a><span class="lineno">16264</span>&#160;VkResult VmaAllocator_T::DefragmentationPassBegin(</div>
+<div class="line"><a name="l16265"></a><span class="lineno">16265</span>&#160;    <a class="code" href="struct_vma_defragmentation_pass_info.html">VmaDefragmentationPassInfo</a>* pInfo,</div>
+<div class="line"><a name="l16266"></a><span class="lineno">16266</span>&#160;    <a class="code" href="struct_vma_defragmentation_context.html">VmaDefragmentationContext</a> context)</div>
+<div class="line"><a name="l16267"></a><span class="lineno">16267</span>&#160;{</div>
+<div class="line"><a name="l16268"></a><span class="lineno">16268</span>&#160;    <span class="keywordflow">return</span> context-&gt;DefragmentPassBegin(pInfo);</div>
+<div class="line"><a name="l16269"></a><span class="lineno">16269</span>&#160;}</div>
+<div class="line"><a name="l16270"></a><span class="lineno">16270</span>&#160;VkResult VmaAllocator_T::DefragmentationPassEnd(</div>
+<div class="line"><a name="l16271"></a><span class="lineno">16271</span>&#160;    <a class="code" href="struct_vma_defragmentation_context.html">VmaDefragmentationContext</a> context)</div>
+<div class="line"><a name="l16272"></a><span class="lineno">16272</span>&#160;{</div>
+<div class="line"><a name="l16273"></a><span class="lineno">16273</span>&#160;    <span class="keywordflow">return</span> context-&gt;DefragmentPassEnd();</div>
+<div class="line"><a name="l16274"></a><span class="lineno">16274</span>&#160;    </div>
+<div class="line"><a name="l16275"></a><span class="lineno">16275</span>&#160;}</div>
+<div class="line"><a name="l16276"></a><span class="lineno">16276</span>&#160; </div>
+<div class="line"><a name="l16277"></a><span class="lineno">16277</span>&#160;<span class="keywordtype">void</span> VmaAllocator_T::GetAllocationInfo(<a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAllocation, <a class="code" href="struct_vma_allocation_info.html">VmaAllocationInfo</a>* pAllocationInfo)</div>
+<div class="line"><a name="l16278"></a><span class="lineno">16278</span>&#160;{</div>
+<div class="line"><a name="l16279"></a><span class="lineno">16279</span>&#160;    <span class="keywordflow">if</span>(hAllocation-&gt;CanBecomeLost())</div>
+<div class="line"><a name="l16280"></a><span class="lineno">16280</span>&#160;    {</div>
+<div class="line"><a name="l16281"></a><span class="lineno">16281</span>&#160;        <span class="comment">/*</span></div>
+<div class="line"><a name="l16282"></a><span class="lineno">16282</span>&#160;<span class="comment">        Warning: This is a carefully designed algorithm.</span></div>
+<div class="line"><a name="l16283"></a><span class="lineno">16283</span>&#160;<span class="comment">        Do not modify unless you really know what you&#39;re doing :)</span></div>
+<div class="line"><a name="l16284"></a><span class="lineno">16284</span>&#160;<span class="comment">        */</span></div>
+<div class="line"><a name="l16285"></a><span class="lineno">16285</span>&#160;        <span class="keyword">const</span> uint32_t localCurrFrameIndex = m_CurrentFrameIndex.load();</div>
+<div class="line"><a name="l16286"></a><span class="lineno">16286</span>&#160;        uint32_t localLastUseFrameIndex = hAllocation-&gt;GetLastUseFrameIndex();</div>
+<div class="line"><a name="l16287"></a><span class="lineno">16287</span>&#160;        <span class="keywordflow">for</span>(;;)</div>
+<div class="line"><a name="l16288"></a><span class="lineno">16288</span>&#160;        {</div>
+<div class="line"><a name="l16289"></a><span class="lineno">16289</span>&#160;            <span class="keywordflow">if</span>(localLastUseFrameIndex == VMA_FRAME_INDEX_LOST)</div>
+<div class="line"><a name="l16290"></a><span class="lineno">16290</span>&#160;            {</div>
+<div class="line"><a name="l16291"></a><span class="lineno">16291</span>&#160;                pAllocationInfo-&gt;<a class="code" href="struct_vma_allocation_info.html#a7f6b0aa58c135e488e6b40a388dad9d5">memoryType</a> = UINT32_MAX;</div>
+<div class="line"><a name="l16292"></a><span class="lineno">16292</span>&#160;                pAllocationInfo-&gt;<a class="code" href="struct_vma_allocation_info.html#ae0bfb7dfdf79a76ffefc9a94677a2f67">deviceMemory</a> = VK_NULL_HANDLE;</div>
+<div class="line"><a name="l16293"></a><span class="lineno">16293</span>&#160;                pAllocationInfo-&gt;<a class="code" href="struct_vma_allocation_info.html#a4a3c732388dbdc7a23f9365b00825268">offset</a> = 0;</div>
+<div class="line"><a name="l16294"></a><span class="lineno">16294</span>&#160;                pAllocationInfo-&gt;<a class="code" href="struct_vma_allocation_info.html#aac76d113a6a5ccbb09fea00fb25fd18f">size</a> = hAllocation-&gt;GetSize();</div>
+<div class="line"><a name="l16295"></a><span class="lineno">16295</span>&#160;                pAllocationInfo-&gt;<a class="code" href="struct_vma_allocation_info.html#a5eeffbe2d2f30f53370ff14aefbadbe2">pMappedData</a> = VMA_NULL;</div>
+<div class="line"><a name="l16296"></a><span class="lineno">16296</span>&#160;                pAllocationInfo-&gt;<a class="code" href="struct_vma_allocation_info.html#adc507656149c04de7ed95d0042ba2a13">pUserData</a> = hAllocation-&gt;GetUserData();</div>
+<div class="line"><a name="l16297"></a><span class="lineno">16297</span>&#160;                <span class="keywordflow">return</span>;</div>
+<div class="line"><a name="l16298"></a><span class="lineno">16298</span>&#160;            }</div>
+<div class="line"><a name="l16299"></a><span class="lineno">16299</span>&#160;            <span class="keywordflow">else</span> <span class="keywordflow">if</span>(localLastUseFrameIndex == localCurrFrameIndex)</div>
+<div class="line"><a name="l16300"></a><span class="lineno">16300</span>&#160;            {</div>
+<div class="line"><a name="l16301"></a><span class="lineno">16301</span>&#160;                pAllocationInfo-&gt;<a class="code" href="struct_vma_allocation_info.html#a7f6b0aa58c135e488e6b40a388dad9d5">memoryType</a> = hAllocation-&gt;GetMemoryTypeIndex();</div>
+<div class="line"><a name="l16302"></a><span class="lineno">16302</span>&#160;                pAllocationInfo-&gt;<a class="code" href="struct_vma_allocation_info.html#ae0bfb7dfdf79a76ffefc9a94677a2f67">deviceMemory</a> = hAllocation-&gt;GetMemory();</div>
+<div class="line"><a name="l16303"></a><span class="lineno">16303</span>&#160;                pAllocationInfo-&gt;<a class="code" href="struct_vma_allocation_info.html#a4a3c732388dbdc7a23f9365b00825268">offset</a> = hAllocation-&gt;GetOffset();</div>
+<div class="line"><a name="l16304"></a><span class="lineno">16304</span>&#160;                pAllocationInfo-&gt;<a class="code" href="struct_vma_allocation_info.html#aac76d113a6a5ccbb09fea00fb25fd18f">size</a> = hAllocation-&gt;GetSize();</div>
+<div class="line"><a name="l16305"></a><span class="lineno">16305</span>&#160;                pAllocationInfo-&gt;<a class="code" href="struct_vma_allocation_info.html#a5eeffbe2d2f30f53370ff14aefbadbe2">pMappedData</a> = VMA_NULL;</div>
+<div class="line"><a name="l16306"></a><span class="lineno">16306</span>&#160;                pAllocationInfo-&gt;<a class="code" href="struct_vma_allocation_info.html#adc507656149c04de7ed95d0042ba2a13">pUserData</a> = hAllocation-&gt;GetUserData();</div>
+<div class="line"><a name="l16307"></a><span class="lineno">16307</span>&#160;                <span class="keywordflow">return</span>;</div>
+<div class="line"><a name="l16308"></a><span class="lineno">16308</span>&#160;            }</div>
+<div class="line"><a name="l16309"></a><span class="lineno">16309</span>&#160;            <span class="keywordflow">else</span> <span class="comment">// Last use time earlier than current time.</span></div>
+<div class="line"><a name="l16310"></a><span class="lineno">16310</span>&#160;            {</div>
+<div class="line"><a name="l16311"></a><span class="lineno">16311</span>&#160;                <span class="keywordflow">if</span>(hAllocation-&gt;CompareExchangeLastUseFrameIndex(localLastUseFrameIndex, localCurrFrameIndex))</div>
+<div class="line"><a name="l16312"></a><span class="lineno">16312</span>&#160;                {</div>
+<div class="line"><a name="l16313"></a><span class="lineno">16313</span>&#160;                    localLastUseFrameIndex = localCurrFrameIndex;</div>
+<div class="line"><a name="l16314"></a><span class="lineno">16314</span>&#160;                }</div>
+<div class="line"><a name="l16315"></a><span class="lineno">16315</span>&#160;            }</div>
+<div class="line"><a name="l16316"></a><span class="lineno">16316</span>&#160;        }</div>
+<div class="line"><a name="l16317"></a><span class="lineno">16317</span>&#160;    }</div>
+<div class="line"><a name="l16318"></a><span class="lineno">16318</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l16319"></a><span class="lineno">16319</span>&#160;    {</div>
+<div class="line"><a name="l16320"></a><span class="lineno">16320</span>&#160;<span class="preprocessor">#if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l16321"></a><span class="lineno">16321</span>&#160;        uint32_t localCurrFrameIndex = m_CurrentFrameIndex.load();</div>
+<div class="line"><a name="l16322"></a><span class="lineno">16322</span>&#160;        uint32_t localLastUseFrameIndex = hAllocation-&gt;GetLastUseFrameIndex();</div>
+<div class="line"><a name="l16323"></a><span class="lineno">16323</span>&#160;        <span class="keywordflow">for</span>(;;)</div>
+<div class="line"><a name="l16324"></a><span class="lineno">16324</span>&#160;        {</div>
+<div class="line"><a name="l16325"></a><span class="lineno">16325</span>&#160;            VMA_ASSERT(localLastUseFrameIndex != VMA_FRAME_INDEX_LOST);</div>
+<div class="line"><a name="l16326"></a><span class="lineno">16326</span>&#160;            <span class="keywordflow">if</span>(localLastUseFrameIndex == localCurrFrameIndex)</div>
+<div class="line"><a name="l16327"></a><span class="lineno">16327</span>&#160;            {</div>
+<div class="line"><a name="l16328"></a><span class="lineno">16328</span>&#160;                <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l16329"></a><span class="lineno">16329</span>&#160;            }</div>
+<div class="line"><a name="l16330"></a><span class="lineno">16330</span>&#160;            <span class="keywordflow">else</span> <span class="comment">// Last use time earlier than current time.</span></div>
+<div class="line"><a name="l16331"></a><span class="lineno">16331</span>&#160;            {</div>
+<div class="line"><a name="l16332"></a><span class="lineno">16332</span>&#160;                <span class="keywordflow">if</span>(hAllocation-&gt;CompareExchangeLastUseFrameIndex(localLastUseFrameIndex, localCurrFrameIndex))</div>
+<div class="line"><a name="l16333"></a><span class="lineno">16333</span>&#160;                {</div>
+<div class="line"><a name="l16334"></a><span class="lineno">16334</span>&#160;                    localLastUseFrameIndex = localCurrFrameIndex;</div>
+<div class="line"><a name="l16335"></a><span class="lineno">16335</span>&#160;                }</div>
+<div class="line"><a name="l16336"></a><span class="lineno">16336</span>&#160;            }</div>
+<div class="line"><a name="l16337"></a><span class="lineno">16337</span>&#160;        }</div>
+<div class="line"><a name="l16338"></a><span class="lineno">16338</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l16339"></a><span class="lineno">16339</span>&#160; </div>
+<div class="line"><a name="l16340"></a><span class="lineno">16340</span>&#160;        pAllocationInfo-&gt;<a class="code" href="struct_vma_allocation_info.html#a7f6b0aa58c135e488e6b40a388dad9d5">memoryType</a> = hAllocation-&gt;GetMemoryTypeIndex();</div>
+<div class="line"><a name="l16341"></a><span class="lineno">16341</span>&#160;        pAllocationInfo-&gt;<a class="code" href="struct_vma_allocation_info.html#ae0bfb7dfdf79a76ffefc9a94677a2f67">deviceMemory</a> = hAllocation-&gt;GetMemory();</div>
+<div class="line"><a name="l16342"></a><span class="lineno">16342</span>&#160;        pAllocationInfo-&gt;<a class="code" href="struct_vma_allocation_info.html#a4a3c732388dbdc7a23f9365b00825268">offset</a> = hAllocation-&gt;GetOffset();</div>
+<div class="line"><a name="l16343"></a><span class="lineno">16343</span>&#160;        pAllocationInfo-&gt;<a class="code" href="struct_vma_allocation_info.html#aac76d113a6a5ccbb09fea00fb25fd18f">size</a> = hAllocation-&gt;GetSize();</div>
+<div class="line"><a name="l16344"></a><span class="lineno">16344</span>&#160;        pAllocationInfo-&gt;<a class="code" href="struct_vma_allocation_info.html#a5eeffbe2d2f30f53370ff14aefbadbe2">pMappedData</a> = hAllocation-&gt;GetMappedData();</div>
+<div class="line"><a name="l16345"></a><span class="lineno">16345</span>&#160;        pAllocationInfo-&gt;<a class="code" href="struct_vma_allocation_info.html#adc507656149c04de7ed95d0042ba2a13">pUserData</a> = hAllocation-&gt;GetUserData();</div>
+<div class="line"><a name="l16346"></a><span class="lineno">16346</span>&#160;    }</div>
+<div class="line"><a name="l16347"></a><span class="lineno">16347</span>&#160;}</div>
+<div class="line"><a name="l16348"></a><span class="lineno">16348</span>&#160; </div>
+<div class="line"><a name="l16349"></a><span class="lineno">16349</span>&#160;<span class="keywordtype">bool</span> VmaAllocator_T::TouchAllocation(<a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAllocation)</div>
+<div class="line"><a name="l16350"></a><span class="lineno">16350</span>&#160;{</div>
+<div class="line"><a name="l16351"></a><span class="lineno">16351</span>&#160;    <span class="comment">// This is a stripped-down version of VmaAllocator_T::GetAllocationInfo.</span></div>
+<div class="line"><a name="l16352"></a><span class="lineno">16352</span>&#160;    <span class="keywordflow">if</span>(hAllocation-&gt;CanBecomeLost())</div>
+<div class="line"><a name="l16353"></a><span class="lineno">16353</span>&#160;    {</div>
+<div class="line"><a name="l16354"></a><span class="lineno">16354</span>&#160;        uint32_t localCurrFrameIndex = m_CurrentFrameIndex.load();</div>
+<div class="line"><a name="l16355"></a><span class="lineno">16355</span>&#160;        uint32_t localLastUseFrameIndex = hAllocation-&gt;GetLastUseFrameIndex();</div>
+<div class="line"><a name="l16356"></a><span class="lineno">16356</span>&#160;        <span class="keywordflow">for</span>(;;)</div>
+<div class="line"><a name="l16357"></a><span class="lineno">16357</span>&#160;        {</div>
+<div class="line"><a name="l16358"></a><span class="lineno">16358</span>&#160;            <span class="keywordflow">if</span>(localLastUseFrameIndex == VMA_FRAME_INDEX_LOST)</div>
+<div class="line"><a name="l16359"></a><span class="lineno">16359</span>&#160;            {</div>
+<div class="line"><a name="l16360"></a><span class="lineno">16360</span>&#160;                <span class="keywordflow">return</span> <span class="keyword">false</span>;</div>
+<div class="line"><a name="l16361"></a><span class="lineno">16361</span>&#160;            }</div>
+<div class="line"><a name="l16362"></a><span class="lineno">16362</span>&#160;            <span class="keywordflow">else</span> <span class="keywordflow">if</span>(localLastUseFrameIndex == localCurrFrameIndex)</div>
+<div class="line"><a name="l16363"></a><span class="lineno">16363</span>&#160;            {</div>
+<div class="line"><a name="l16364"></a><span class="lineno">16364</span>&#160;                <span class="keywordflow">return</span> <span class="keyword">true</span>;</div>
+<div class="line"><a name="l16365"></a><span class="lineno">16365</span>&#160;            }</div>
+<div class="line"><a name="l16366"></a><span class="lineno">16366</span>&#160;            <span class="keywordflow">else</span> <span class="comment">// Last use time earlier than current time.</span></div>
+<div class="line"><a name="l16367"></a><span class="lineno">16367</span>&#160;            {</div>
+<div class="line"><a name="l16368"></a><span class="lineno">16368</span>&#160;                <span class="keywordflow">if</span>(hAllocation-&gt;CompareExchangeLastUseFrameIndex(localLastUseFrameIndex, localCurrFrameIndex))</div>
+<div class="line"><a name="l16369"></a><span class="lineno">16369</span>&#160;                {</div>
+<div class="line"><a name="l16370"></a><span class="lineno">16370</span>&#160;                    localLastUseFrameIndex = localCurrFrameIndex;</div>
+<div class="line"><a name="l16371"></a><span class="lineno">16371</span>&#160;                }</div>
+<div class="line"><a name="l16372"></a><span class="lineno">16372</span>&#160;            }</div>
+<div class="line"><a name="l16373"></a><span class="lineno">16373</span>&#160;        }</div>
+<div class="line"><a name="l16374"></a><span class="lineno">16374</span>&#160;    }</div>
+<div class="line"><a name="l16375"></a><span class="lineno">16375</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l16376"></a><span class="lineno">16376</span>&#160;    {</div>
+<div class="line"><a name="l16377"></a><span class="lineno">16377</span>&#160;<span class="preprocessor">#if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l16378"></a><span class="lineno">16378</span>&#160;        uint32_t localCurrFrameIndex = m_CurrentFrameIndex.load();</div>
+<div class="line"><a name="l16379"></a><span class="lineno">16379</span>&#160;        uint32_t localLastUseFrameIndex = hAllocation-&gt;GetLastUseFrameIndex();</div>
+<div class="line"><a name="l16380"></a><span class="lineno">16380</span>&#160;        <span class="keywordflow">for</span>(;;)</div>
+<div class="line"><a name="l16381"></a><span class="lineno">16381</span>&#160;        {</div>
+<div class="line"><a name="l16382"></a><span class="lineno">16382</span>&#160;            VMA_ASSERT(localLastUseFrameIndex != VMA_FRAME_INDEX_LOST);</div>
+<div class="line"><a name="l16383"></a><span class="lineno">16383</span>&#160;            <span class="keywordflow">if</span>(localLastUseFrameIndex == localCurrFrameIndex)</div>
+<div class="line"><a name="l16384"></a><span class="lineno">16384</span>&#160;            {</div>
+<div class="line"><a name="l16385"></a><span class="lineno">16385</span>&#160;                <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l16386"></a><span class="lineno">16386</span>&#160;            }</div>
+<div class="line"><a name="l16387"></a><span class="lineno">16387</span>&#160;            <span class="keywordflow">else</span> <span class="comment">// Last use time earlier than current time.</span></div>
+<div class="line"><a name="l16388"></a><span class="lineno">16388</span>&#160;            {</div>
+<div class="line"><a name="l16389"></a><span class="lineno">16389</span>&#160;                <span class="keywordflow">if</span>(hAllocation-&gt;CompareExchangeLastUseFrameIndex(localLastUseFrameIndex, localCurrFrameIndex))</div>
+<div class="line"><a name="l16390"></a><span class="lineno">16390</span>&#160;                {</div>
+<div class="line"><a name="l16391"></a><span class="lineno">16391</span>&#160;                    localLastUseFrameIndex = localCurrFrameIndex;</div>
+<div class="line"><a name="l16392"></a><span class="lineno">16392</span>&#160;                }</div>
+<div class="line"><a name="l16393"></a><span class="lineno">16393</span>&#160;            }</div>
+<div class="line"><a name="l16394"></a><span class="lineno">16394</span>&#160;        }</div>
+<div class="line"><a name="l16395"></a><span class="lineno">16395</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l16396"></a><span class="lineno">16396</span>&#160; </div>
+<div class="line"><a name="l16397"></a><span class="lineno">16397</span>&#160;        <span class="keywordflow">return</span> <span class="keyword">true</span>;</div>
+<div class="line"><a name="l16398"></a><span class="lineno">16398</span>&#160;    }</div>
+<div class="line"><a name="l16399"></a><span class="lineno">16399</span>&#160;}</div>
+<div class="line"><a name="l16400"></a><span class="lineno">16400</span>&#160; </div>
+<div class="line"><a name="l16401"></a><span class="lineno">16401</span>&#160;VkResult VmaAllocator_T::CreatePool(<span class="keyword">const</span> <a class="code" href="struct_vma_pool_create_info.html">VmaPoolCreateInfo</a>* pCreateInfo, <a class="code" href="struct_vma_pool.html">VmaPool</a>* pPool)</div>
+<div class="line"><a name="l16402"></a><span class="lineno">16402</span>&#160;{</div>
+<div class="line"><a name="l16403"></a><span class="lineno">16403</span>&#160;    VMA_DEBUG_LOG(<span class="stringliteral">&quot;  CreatePool: MemoryTypeIndex=%u, flags=%u&quot;</span>, pCreateInfo-&gt;<a class="code" href="struct_vma_pool_create_info.html#a596fa76b685d3f1f688f84a709a5b319">memoryTypeIndex</a>, pCreateInfo-&gt;<a class="code" href="struct_vma_pool_create_info.html#a8405139f63d078340ae74513a59f5446">flags</a>);</div>
+<div class="line"><a name="l16404"></a><span class="lineno">16404</span>&#160; </div>
+<div class="line"><a name="l16405"></a><span class="lineno">16405</span>&#160;    <a class="code" href="struct_vma_pool_create_info.html">VmaPoolCreateInfo</a> newCreateInfo = *pCreateInfo;</div>
+<div class="line"><a name="l16406"></a><span class="lineno">16406</span>&#160; </div>
+<div class="line"><a name="l16407"></a><span class="lineno">16407</span>&#160;    <span class="keywordflow">if</span>(newCreateInfo.<a class="code" href="struct_vma_pool_create_info.html#ae41142f2834fcdc82baa4883c187b75c">maxBlockCount</a> == 0)</div>
+<div class="line"><a name="l16408"></a><span class="lineno">16408</span>&#160;    {</div>
+<div class="line"><a name="l16409"></a><span class="lineno">16409</span>&#160;        newCreateInfo.<a class="code" href="struct_vma_pool_create_info.html#ae41142f2834fcdc82baa4883c187b75c">maxBlockCount</a> = SIZE_MAX;</div>
+<div class="line"><a name="l16410"></a><span class="lineno">16410</span>&#160;    }</div>
+<div class="line"><a name="l16411"></a><span class="lineno">16411</span>&#160;    <span class="keywordflow">if</span>(newCreateInfo.<a class="code" href="struct_vma_pool_create_info.html#ad8006fb803185c0a699d30f3e9a865ae">minBlockCount</a> &gt; newCreateInfo.<a class="code" href="struct_vma_pool_create_info.html#ae41142f2834fcdc82baa4883c187b75c">maxBlockCount</a>)</div>
+<div class="line"><a name="l16412"></a><span class="lineno">16412</span>&#160;    {</div>
+<div class="line"><a name="l16413"></a><span class="lineno">16413</span>&#160;        <span class="keywordflow">return</span> VK_ERROR_INITIALIZATION_FAILED;</div>
+<div class="line"><a name="l16414"></a><span class="lineno">16414</span>&#160;    }</div>
+<div class="line"><a name="l16415"></a><span class="lineno">16415</span>&#160;    <span class="comment">// Memory type index out of range or forbidden.</span></div>
+<div class="line"><a name="l16416"></a><span class="lineno">16416</span>&#160;    <span class="keywordflow">if</span>(pCreateInfo-&gt;<a class="code" href="struct_vma_pool_create_info.html#a596fa76b685d3f1f688f84a709a5b319">memoryTypeIndex</a> &gt;= GetMemoryTypeCount() ||</div>
+<div class="line"><a name="l16417"></a><span class="lineno">16417</span>&#160;        ((1u &lt;&lt; pCreateInfo-&gt;<a class="code" href="struct_vma_pool_create_info.html#a596fa76b685d3f1f688f84a709a5b319">memoryTypeIndex</a>) &amp; m_GlobalMemoryTypeBits) == 0)</div>
+<div class="line"><a name="l16418"></a><span class="lineno">16418</span>&#160;    {</div>
+<div class="line"><a name="l16419"></a><span class="lineno">16419</span>&#160;        <span class="keywordflow">return</span> VK_ERROR_FEATURE_NOT_PRESENT;</div>
+<div class="line"><a name="l16420"></a><span class="lineno">16420</span>&#160;    }</div>
+<div class="line"><a name="l16421"></a><span class="lineno">16421</span>&#160; </div>
+<div class="line"><a name="l16422"></a><span class="lineno">16422</span>&#160;    <span class="keyword">const</span> VkDeviceSize preferredBlockSize = CalcPreferredBlockSize(newCreateInfo.<a class="code" href="struct_vma_pool_create_info.html#a596fa76b685d3f1f688f84a709a5b319">memoryTypeIndex</a>);</div>
+<div class="line"><a name="l16423"></a><span class="lineno">16423</span>&#160; </div>
+<div class="line"><a name="l16424"></a><span class="lineno">16424</span>&#160;    *pPool = vma_new(<span class="keyword">this</span>, VmaPool_T)(<span class="keyword">this</span>, newCreateInfo, preferredBlockSize);</div>
+<div class="line"><a name="l16425"></a><span class="lineno">16425</span>&#160; </div>
+<div class="line"><a name="l16426"></a><span class="lineno">16426</span>&#160;    VkResult res = (*pPool)-&gt;m_BlockVector.CreateMinBlocks();</div>
+<div class="line"><a name="l16427"></a><span class="lineno">16427</span>&#160;    <span class="keywordflow">if</span>(res != VK_SUCCESS)</div>
+<div class="line"><a name="l16428"></a><span class="lineno">16428</span>&#160;    {</div>
+<div class="line"><a name="l16429"></a><span class="lineno">16429</span>&#160;        vma_delete(<span class="keyword">this</span>, *pPool);</div>
+<div class="line"><a name="l16430"></a><span class="lineno">16430</span>&#160;        *pPool = VMA_NULL;</div>
+<div class="line"><a name="l16431"></a><span class="lineno">16431</span>&#160;        <span class="keywordflow">return</span> res;</div>
+<div class="line"><a name="l16432"></a><span class="lineno">16432</span>&#160;    }</div>
+<div class="line"><a name="l16433"></a><span class="lineno">16433</span>&#160; </div>
+<div class="line"><a name="l16434"></a><span class="lineno">16434</span>&#160;    <span class="comment">// Add to m_Pools.</span></div>
+<div class="line"><a name="l16435"></a><span class="lineno">16435</span>&#160;    {</div>
+<div class="line"><a name="l16436"></a><span class="lineno">16436</span>&#160;        VmaMutexLockWrite lock(m_PoolsMutex, m_UseMutex);</div>
+<div class="line"><a name="l16437"></a><span class="lineno">16437</span>&#160;        (*pPool)-&gt;SetId(m_NextPoolId++);</div>
+<div class="line"><a name="l16438"></a><span class="lineno">16438</span>&#160;        VmaVectorInsertSorted&lt;VmaPointerLess&gt;(m_Pools, *pPool);</div>
+<div class="line"><a name="l16439"></a><span class="lineno">16439</span>&#160;    }</div>
+<div class="line"><a name="l16440"></a><span class="lineno">16440</span>&#160; </div>
+<div class="line"><a name="l16441"></a><span class="lineno">16441</span>&#160;    <span class="keywordflow">return</span> VK_SUCCESS;</div>
+<div class="line"><a name="l16442"></a><span class="lineno">16442</span>&#160;}</div>
+<div class="line"><a name="l16443"></a><span class="lineno">16443</span>&#160; </div>
+<div class="line"><a name="l16444"></a><span class="lineno">16444</span>&#160;<span class="keywordtype">void</span> VmaAllocator_T::DestroyPool(<a class="code" href="struct_vma_pool.html">VmaPool</a> pool)</div>
+<div class="line"><a name="l16445"></a><span class="lineno">16445</span>&#160;{</div>
+<div class="line"><a name="l16446"></a><span class="lineno">16446</span>&#160;    <span class="comment">// Remove from m_Pools.</span></div>
+<div class="line"><a name="l16447"></a><span class="lineno">16447</span>&#160;    {</div>
+<div class="line"><a name="l16448"></a><span class="lineno">16448</span>&#160;        VmaMutexLockWrite lock(m_PoolsMutex, m_UseMutex);</div>
+<div class="line"><a name="l16449"></a><span class="lineno">16449</span>&#160;        <span class="keywordtype">bool</span> success = VmaVectorRemoveSorted&lt;VmaPointerLess&gt;(m_Pools, pool);</div>
+<div class="line"><a name="l16450"></a><span class="lineno">16450</span>&#160;        VMA_ASSERT(success &amp;&amp; <span class="stringliteral">&quot;Pool not found in Allocator.&quot;</span>);</div>
+<div class="line"><a name="l16451"></a><span class="lineno">16451</span>&#160;    }</div>
+<div class="line"><a name="l16452"></a><span class="lineno">16452</span>&#160; </div>
+<div class="line"><a name="l16453"></a><span class="lineno">16453</span>&#160;    vma_delete(<span class="keyword">this</span>, pool);</div>
+<div class="line"><a name="l16454"></a><span class="lineno">16454</span>&#160;}</div>
+<div class="line"><a name="l16455"></a><span class="lineno">16455</span>&#160; </div>
+<div class="line"><a name="l16456"></a><span class="lineno">16456</span>&#160;<span class="keywordtype">void</span> VmaAllocator_T::GetPoolStats(<a class="code" href="struct_vma_pool.html">VmaPool</a> pool, <a class="code" href="struct_vma_pool_stats.html">VmaPoolStats</a>* pPoolStats)</div>
+<div class="line"><a name="l16457"></a><span class="lineno">16457</span>&#160;{</div>
+<div class="line"><a name="l16458"></a><span class="lineno">16458</span>&#160;    pool-&gt;m_BlockVector.GetPoolStats(pPoolStats);</div>
+<div class="line"><a name="l16459"></a><span class="lineno">16459</span>&#160;}</div>
+<div class="line"><a name="l16460"></a><span class="lineno">16460</span>&#160; </div>
+<div class="line"><a name="l16461"></a><span class="lineno">16461</span>&#160;<span class="keywordtype">void</span> VmaAllocator_T::SetCurrentFrameIndex(uint32_t frameIndex)</div>
+<div class="line"><a name="l16462"></a><span class="lineno">16462</span>&#160;{</div>
+<div class="line"><a name="l16463"></a><span class="lineno">16463</span>&#160;    m_CurrentFrameIndex.store(frameIndex);</div>
+<div class="line"><a name="l16464"></a><span class="lineno">16464</span>&#160; </div>
+<div class="line"><a name="l16465"></a><span class="lineno">16465</span>&#160;<span class="preprocessor">#if VMA_MEMORY_BUDGET</span></div>
+<div class="line"><a name="l16466"></a><span class="lineno">16466</span>&#160;    <span class="keywordflow">if</span>(m_UseExtMemoryBudget)</div>
+<div class="line"><a name="l16467"></a><span class="lineno">16467</span>&#160;    {</div>
+<div class="line"><a name="l16468"></a><span class="lineno">16468</span>&#160;        UpdateVulkanBudget();</div>
+<div class="line"><a name="l16469"></a><span class="lineno">16469</span>&#160;    }</div>
+<div class="line"><a name="l16470"></a><span class="lineno">16470</span>&#160;<span class="preprocessor">#endif // #if VMA_MEMORY_BUDGET</span></div>
+<div class="line"><a name="l16471"></a><span class="lineno">16471</span>&#160;}</div>
+<div class="line"><a name="l16472"></a><span class="lineno">16472</span>&#160; </div>
+<div class="line"><a name="l16473"></a><span class="lineno">16473</span>&#160;<span class="keywordtype">void</span> VmaAllocator_T::MakePoolAllocationsLost(</div>
+<div class="line"><a name="l16474"></a><span class="lineno">16474</span>&#160;    <a class="code" href="struct_vma_pool.html">VmaPool</a> hPool,</div>
+<div class="line"><a name="l16475"></a><span class="lineno">16475</span>&#160;    <span class="keywordtype">size_t</span>* pLostAllocationCount)</div>
+<div class="line"><a name="l16476"></a><span class="lineno">16476</span>&#160;{</div>
+<div class="line"><a name="l16477"></a><span class="lineno">16477</span>&#160;    hPool-&gt;m_BlockVector.MakePoolAllocationsLost(</div>
+<div class="line"><a name="l16478"></a><span class="lineno">16478</span>&#160;        m_CurrentFrameIndex.load(),</div>
+<div class="line"><a name="l16479"></a><span class="lineno">16479</span>&#160;        pLostAllocationCount);</div>
+<div class="line"><a name="l16480"></a><span class="lineno">16480</span>&#160;}</div>
+<div class="line"><a name="l16481"></a><span class="lineno">16481</span>&#160; </div>
+<div class="line"><a name="l16482"></a><span class="lineno">16482</span>&#160;VkResult VmaAllocator_T::CheckPoolCorruption(<a class="code" href="struct_vma_pool.html">VmaPool</a> hPool)</div>
+<div class="line"><a name="l16483"></a><span class="lineno">16483</span>&#160;{</div>
+<div class="line"><a name="l16484"></a><span class="lineno">16484</span>&#160;    <span class="keywordflow">return</span> hPool-&gt;m_BlockVector.CheckCorruption();</div>
+<div class="line"><a name="l16485"></a><span class="lineno">16485</span>&#160;}</div>
+<div class="line"><a name="l16486"></a><span class="lineno">16486</span>&#160; </div>
+<div class="line"><a name="l16487"></a><span class="lineno">16487</span>&#160;VkResult VmaAllocator_T::CheckCorruption(uint32_t memoryTypeBits)</div>
+<div class="line"><a name="l16488"></a><span class="lineno">16488</span>&#160;{</div>
+<div class="line"><a name="l16489"></a><span class="lineno">16489</span>&#160;    VkResult finalRes = VK_ERROR_FEATURE_NOT_PRESENT;</div>
+<div class="line"><a name="l16490"></a><span class="lineno">16490</span>&#160; </div>
+<div class="line"><a name="l16491"></a><span class="lineno">16491</span>&#160;    <span class="comment">// Process default pools.</span></div>
+<div class="line"><a name="l16492"></a><span class="lineno">16492</span>&#160;    <span class="keywordflow">for</span>(uint32_t memTypeIndex = 0; memTypeIndex &lt; GetMemoryTypeCount(); ++memTypeIndex)</div>
+<div class="line"><a name="l16493"></a><span class="lineno">16493</span>&#160;    {</div>
+<div class="line"><a name="l16494"></a><span class="lineno">16494</span>&#160;        <span class="keywordflow">if</span>(((1u &lt;&lt; memTypeIndex) &amp; memoryTypeBits) != 0)</div>
+<div class="line"><a name="l16495"></a><span class="lineno">16495</span>&#160;        {</div>
+<div class="line"><a name="l16496"></a><span class="lineno">16496</span>&#160;            VmaBlockVector* <span class="keyword">const</span> pBlockVector = m_pBlockVectors[memTypeIndex];</div>
+<div class="line"><a name="l16497"></a><span class="lineno">16497</span>&#160;            VMA_ASSERT(pBlockVector);</div>
+<div class="line"><a name="l16498"></a><span class="lineno">16498</span>&#160;            VkResult localRes = pBlockVector-&gt;CheckCorruption();</div>
+<div class="line"><a name="l16499"></a><span class="lineno">16499</span>&#160;            <span class="keywordflow">switch</span>(localRes)</div>
+<div class="line"><a name="l16500"></a><span class="lineno">16500</span>&#160;            {</div>
+<div class="line"><a name="l16501"></a><span class="lineno">16501</span>&#160;            <span class="keywordflow">case</span> VK_ERROR_FEATURE_NOT_PRESENT:</div>
+<div class="line"><a name="l16502"></a><span class="lineno">16502</span>&#160;                <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l16503"></a><span class="lineno">16503</span>&#160;            <span class="keywordflow">case</span> VK_SUCCESS:</div>
+<div class="line"><a name="l16504"></a><span class="lineno">16504</span>&#160;                finalRes = VK_SUCCESS;</div>
+<div class="line"><a name="l16505"></a><span class="lineno">16505</span>&#160;                <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l16506"></a><span class="lineno">16506</span>&#160;            <span class="keywordflow">default</span>:</div>
+<div class="line"><a name="l16507"></a><span class="lineno">16507</span>&#160;                <span class="keywordflow">return</span> localRes;</div>
+<div class="line"><a name="l16508"></a><span class="lineno">16508</span>&#160;            }</div>
+<div class="line"><a name="l16509"></a><span class="lineno">16509</span>&#160;        }</div>
+<div class="line"><a name="l16510"></a><span class="lineno">16510</span>&#160;    }</div>
+<div class="line"><a name="l16511"></a><span class="lineno">16511</span>&#160; </div>
+<div class="line"><a name="l16512"></a><span class="lineno">16512</span>&#160;    <span class="comment">// Process custom pools.</span></div>
+<div class="line"><a name="l16513"></a><span class="lineno">16513</span>&#160;    {</div>
+<div class="line"><a name="l16514"></a><span class="lineno">16514</span>&#160;        VmaMutexLockRead lock(m_PoolsMutex, m_UseMutex);</div>
+<div class="line"><a name="l16515"></a><span class="lineno">16515</span>&#160;        <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> poolIndex = 0, poolCount = m_Pools.size(); poolIndex &lt; poolCount; ++poolIndex)</div>
+<div class="line"><a name="l16516"></a><span class="lineno">16516</span>&#160;        {</div>
+<div class="line"><a name="l16517"></a><span class="lineno">16517</span>&#160;            <span class="keywordflow">if</span>(((1u &lt;&lt; m_Pools[poolIndex]-&gt;m_BlockVector.GetMemoryTypeIndex()) &amp; memoryTypeBits) != 0)</div>
+<div class="line"><a name="l16518"></a><span class="lineno">16518</span>&#160;            {</div>
+<div class="line"><a name="l16519"></a><span class="lineno">16519</span>&#160;                VkResult localRes = m_Pools[poolIndex]-&gt;m_BlockVector.CheckCorruption();</div>
+<div class="line"><a name="l16520"></a><span class="lineno">16520</span>&#160;                <span class="keywordflow">switch</span>(localRes)</div>
+<div class="line"><a name="l16521"></a><span class="lineno">16521</span>&#160;                {</div>
+<div class="line"><a name="l16522"></a><span class="lineno">16522</span>&#160;                <span class="keywordflow">case</span> VK_ERROR_FEATURE_NOT_PRESENT:</div>
+<div class="line"><a name="l16523"></a><span class="lineno">16523</span>&#160;                    <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l16524"></a><span class="lineno">16524</span>&#160;                <span class="keywordflow">case</span> VK_SUCCESS:</div>
+<div class="line"><a name="l16525"></a><span class="lineno">16525</span>&#160;                    finalRes = VK_SUCCESS;</div>
+<div class="line"><a name="l16526"></a><span class="lineno">16526</span>&#160;                    <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l16527"></a><span class="lineno">16527</span>&#160;                <span class="keywordflow">default</span>:</div>
+<div class="line"><a name="l16528"></a><span class="lineno">16528</span>&#160;                    <span class="keywordflow">return</span> localRes;</div>
+<div class="line"><a name="l16529"></a><span class="lineno">16529</span>&#160;                }</div>
+<div class="line"><a name="l16530"></a><span class="lineno">16530</span>&#160;            }</div>
+<div class="line"><a name="l16531"></a><span class="lineno">16531</span>&#160;        }</div>
+<div class="line"><a name="l16532"></a><span class="lineno">16532</span>&#160;    }</div>
+<div class="line"><a name="l16533"></a><span class="lineno">16533</span>&#160; </div>
+<div class="line"><a name="l16534"></a><span class="lineno">16534</span>&#160;    <span class="keywordflow">return</span> finalRes;</div>
+<div class="line"><a name="l16535"></a><span class="lineno">16535</span>&#160;}</div>
+<div class="line"><a name="l16536"></a><span class="lineno">16536</span>&#160; </div>
+<div class="line"><a name="l16537"></a><span class="lineno">16537</span>&#160;<span class="keywordtype">void</span> VmaAllocator_T::CreateLostAllocation(<a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocation)</div>
+<div class="line"><a name="l16538"></a><span class="lineno">16538</span>&#160;{</div>
+<div class="line"><a name="l16539"></a><span class="lineno">16539</span>&#160;    *pAllocation = m_AllocationObjectAllocator.Allocate(VMA_FRAME_INDEX_LOST, <span class="keyword">false</span>);</div>
+<div class="line"><a name="l16540"></a><span class="lineno">16540</span>&#160;    (*pAllocation)-&gt;InitLost();</div>
+<div class="line"><a name="l16541"></a><span class="lineno">16541</span>&#160;}</div>
+<div class="line"><a name="l16542"></a><span class="lineno">16542</span>&#160; </div>
+<div class="line"><a name="l16543"></a><span class="lineno">16543</span>&#160;VkResult VmaAllocator_T::AllocateVulkanMemory(<span class="keyword">const</span> VkMemoryAllocateInfo* pAllocateInfo, VkDeviceMemory* pMemory)</div>
+<div class="line"><a name="l16544"></a><span class="lineno">16544</span>&#160;{</div>
+<div class="line"><a name="l16545"></a><span class="lineno">16545</span>&#160;    <span class="keyword">const</span> uint32_t heapIndex = MemoryTypeIndexToHeapIndex(pAllocateInfo-&gt;memoryTypeIndex);</div>
+<div class="line"><a name="l16546"></a><span class="lineno">16546</span>&#160; </div>
+<div class="line"><a name="l16547"></a><span class="lineno">16547</span>&#160;    <span class="comment">// HeapSizeLimit is in effect for this heap.</span></div>
+<div class="line"><a name="l16548"></a><span class="lineno">16548</span>&#160;    <span class="keywordflow">if</span>((m_HeapSizeLimitMask &amp; (1u &lt;&lt; heapIndex)) != 0)</div>
+<div class="line"><a name="l16549"></a><span class="lineno">16549</span>&#160;    {</div>
+<div class="line"><a name="l16550"></a><span class="lineno">16550</span>&#160;        <span class="keyword">const</span> VkDeviceSize heapSize = m_MemProps.memoryHeaps[heapIndex].size;</div>
+<div class="line"><a name="l16551"></a><span class="lineno">16551</span>&#160;        VkDeviceSize blockBytes = m_Budget.m_BlockBytes[heapIndex];</div>
+<div class="line"><a name="l16552"></a><span class="lineno">16552</span>&#160;        <span class="keywordflow">for</span>(;;)</div>
+<div class="line"><a name="l16553"></a><span class="lineno">16553</span>&#160;        {</div>
+<div class="line"><a name="l16554"></a><span class="lineno">16554</span>&#160;            <span class="keyword">const</span> VkDeviceSize blockBytesAfterAllocation = blockBytes + pAllocateInfo-&gt;allocationSize;</div>
+<div class="line"><a name="l16555"></a><span class="lineno">16555</span>&#160;            <span class="keywordflow">if</span>(blockBytesAfterAllocation &gt; heapSize)</div>
+<div class="line"><a name="l16556"></a><span class="lineno">16556</span>&#160;            {</div>
+<div class="line"><a name="l16557"></a><span class="lineno">16557</span>&#160;                <span class="keywordflow">return</span> VK_ERROR_OUT_OF_DEVICE_MEMORY;</div>
+<div class="line"><a name="l16558"></a><span class="lineno">16558</span>&#160;            }</div>
+<div class="line"><a name="l16559"></a><span class="lineno">16559</span>&#160;            <span class="keywordflow">if</span>(m_Budget.m_BlockBytes[heapIndex].compare_exchange_strong(blockBytes, blockBytesAfterAllocation))</div>
+<div class="line"><a name="l16560"></a><span class="lineno">16560</span>&#160;            {</div>
+<div class="line"><a name="l16561"></a><span class="lineno">16561</span>&#160;                <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l16562"></a><span class="lineno">16562</span>&#160;            }</div>
+<div class="line"><a name="l16563"></a><span class="lineno">16563</span>&#160;        }</div>
+<div class="line"><a name="l16564"></a><span class="lineno">16564</span>&#160;    }</div>
+<div class="line"><a name="l16565"></a><span class="lineno">16565</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l16566"></a><span class="lineno">16566</span>&#160;    {</div>
+<div class="line"><a name="l16567"></a><span class="lineno">16567</span>&#160;        m_Budget.m_BlockBytes[heapIndex] += pAllocateInfo-&gt;allocationSize;</div>
+<div class="line"><a name="l16568"></a><span class="lineno">16568</span>&#160;    }</div>
+<div class="line"><a name="l16569"></a><span class="lineno">16569</span>&#160; </div>
+<div class="line"><a name="l16570"></a><span class="lineno">16570</span>&#160;    <span class="comment">// VULKAN CALL vkAllocateMemory.</span></div>
+<div class="line"><a name="l16571"></a><span class="lineno">16571</span>&#160;    VkResult res = (*m_VulkanFunctions.vkAllocateMemory)(m_hDevice, pAllocateInfo, GetAllocationCallbacks(), pMemory);</div>
+<div class="line"><a name="l16572"></a><span class="lineno">16572</span>&#160; </div>
+<div class="line"><a name="l16573"></a><span class="lineno">16573</span>&#160;    <span class="keywordflow">if</span>(res == VK_SUCCESS)</div>
+<div class="line"><a name="l16574"></a><span class="lineno">16574</span>&#160;    {</div>
+<div class="line"><a name="l16575"></a><span class="lineno">16575</span>&#160;<span class="preprocessor">#if VMA_MEMORY_BUDGET</span></div>
+<div class="line"><a name="l16576"></a><span class="lineno">16576</span>&#160;        ++m_Budget.m_OperationsSinceBudgetFetch;</div>
+<div class="line"><a name="l16577"></a><span class="lineno">16577</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l16578"></a><span class="lineno">16578</span>&#160; </div>
+<div class="line"><a name="l16579"></a><span class="lineno">16579</span>&#160;        <span class="comment">// Informative callback.</span></div>
+<div class="line"><a name="l16580"></a><span class="lineno">16580</span>&#160;        <span class="keywordflow">if</span>(m_DeviceMemoryCallbacks.<a class="code" href="struct_vma_device_memory_callbacks.html#a4f17f7b255101e733b44d5633aceabfb">pfnAllocate</a> != VMA_NULL)</div>
+<div class="line"><a name="l16581"></a><span class="lineno">16581</span>&#160;        {</div>
+<div class="line"><a name="l16582"></a><span class="lineno">16582</span>&#160;            (*m_DeviceMemoryCallbacks.<a class="code" href="struct_vma_device_memory_callbacks.html#a4f17f7b255101e733b44d5633aceabfb">pfnAllocate</a>)(<span class="keyword">this</span>, pAllocateInfo-&gt;memoryTypeIndex, *pMemory, pAllocateInfo-&gt;allocationSize, m_DeviceMemoryCallbacks.<a class="code" href="struct_vma_device_memory_callbacks.html#a24052de0937ddd54015a2df0363903c6">pUserData</a>);</div>
+<div class="line"><a name="l16583"></a><span class="lineno">16583</span>&#160;        }</div>
+<div class="line"><a name="l16584"></a><span class="lineno">16584</span>&#160;    }</div>
+<div class="line"><a name="l16585"></a><span class="lineno">16585</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l16586"></a><span class="lineno">16586</span>&#160;    {</div>
+<div class="line"><a name="l16587"></a><span class="lineno">16587</span>&#160;        m_Budget.m_BlockBytes[heapIndex] -= pAllocateInfo-&gt;allocationSize;</div>
+<div class="line"><a name="l16588"></a><span class="lineno">16588</span>&#160;    }</div>
+<div class="line"><a name="l16589"></a><span class="lineno">16589</span>&#160; </div>
+<div class="line"><a name="l16590"></a><span class="lineno">16590</span>&#160;    <span class="keywordflow">return</span> res;</div>
+<div class="line"><a name="l16591"></a><span class="lineno">16591</span>&#160;}</div>
+<div class="line"><a name="l16592"></a><span class="lineno">16592</span>&#160; </div>
+<div class="line"><a name="l16593"></a><span class="lineno">16593</span>&#160;<span class="keywordtype">void</span> VmaAllocator_T::FreeVulkanMemory(uint32_t memoryType, VkDeviceSize size, VkDeviceMemory hMemory)</div>
+<div class="line"><a name="l16594"></a><span class="lineno">16594</span>&#160;{</div>
+<div class="line"><a name="l16595"></a><span class="lineno">16595</span>&#160;    <span class="comment">// Informative callback.</span></div>
+<div class="line"><a name="l16596"></a><span class="lineno">16596</span>&#160;    <span class="keywordflow">if</span>(m_DeviceMemoryCallbacks.<a class="code" href="struct_vma_device_memory_callbacks.html#abe8a3328bbc916f6f712fdb6b299444c">pfnFree</a> != VMA_NULL)</div>
+<div class="line"><a name="l16597"></a><span class="lineno">16597</span>&#160;    {</div>
+<div class="line"><a name="l16598"></a><span class="lineno">16598</span>&#160;        (*m_DeviceMemoryCallbacks.<a class="code" href="struct_vma_device_memory_callbacks.html#abe8a3328bbc916f6f712fdb6b299444c">pfnFree</a>)(<span class="keyword">this</span>, memoryType, hMemory, size, m_DeviceMemoryCallbacks.<a class="code" href="struct_vma_device_memory_callbacks.html#a24052de0937ddd54015a2df0363903c6">pUserData</a>);</div>
+<div class="line"><a name="l16599"></a><span class="lineno">16599</span>&#160;    }</div>
+<div class="line"><a name="l16600"></a><span class="lineno">16600</span>&#160; </div>
+<div class="line"><a name="l16601"></a><span class="lineno">16601</span>&#160;    <span class="comment">// VULKAN CALL vkFreeMemory.</span></div>
+<div class="line"><a name="l16602"></a><span class="lineno">16602</span>&#160;    (*m_VulkanFunctions.vkFreeMemory)(m_hDevice, hMemory, GetAllocationCallbacks());</div>
+<div class="line"><a name="l16603"></a><span class="lineno">16603</span>&#160; </div>
+<div class="line"><a name="l16604"></a><span class="lineno">16604</span>&#160;    m_Budget.m_BlockBytes[MemoryTypeIndexToHeapIndex(memoryType)] -= size;</div>
+<div class="line"><a name="l16605"></a><span class="lineno">16605</span>&#160;}</div>
+<div class="line"><a name="l16606"></a><span class="lineno">16606</span>&#160; </div>
+<div class="line"><a name="l16607"></a><span class="lineno">16607</span>&#160;VkResult VmaAllocator_T::BindVulkanBuffer(</div>
+<div class="line"><a name="l16608"></a><span class="lineno">16608</span>&#160;    VkDeviceMemory memory,</div>
+<div class="line"><a name="l16609"></a><span class="lineno">16609</span>&#160;    VkDeviceSize memoryOffset,</div>
+<div class="line"><a name="l16610"></a><span class="lineno">16610</span>&#160;    VkBuffer buffer,</div>
+<div class="line"><a name="l16611"></a><span class="lineno">16611</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">void</span>* pNext)</div>
+<div class="line"><a name="l16612"></a><span class="lineno">16612</span>&#160;{</div>
+<div class="line"><a name="l16613"></a><span class="lineno">16613</span>&#160;    <span class="keywordflow">if</span>(pNext != VMA_NULL)</div>
+<div class="line"><a name="l16614"></a><span class="lineno">16614</span>&#160;    {</div>
+<div class="line"><a name="l16615"></a><span class="lineno">16615</span>&#160;<span class="preprocessor">#if VMA_VULKAN_VERSION &gt;= 1001000 || VMA_BIND_MEMORY2</span></div>
+<div class="line"><a name="l16616"></a><span class="lineno">16616</span>&#160;        <span class="keywordflow">if</span>((m_UseKhrBindMemory2 || m_VulkanApiVersion &gt;= VK_MAKE_VERSION(1, 1, 0)) &amp;&amp;</div>
+<div class="line"><a name="l16617"></a><span class="lineno">16617</span>&#160;            m_VulkanFunctions.vkBindBufferMemory2KHR != VMA_NULL)</div>
+<div class="line"><a name="l16618"></a><span class="lineno">16618</span>&#160;        {</div>
+<div class="line"><a name="l16619"></a><span class="lineno">16619</span>&#160;            VkBindBufferMemoryInfoKHR bindBufferMemoryInfo = { VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO_KHR };</div>
+<div class="line"><a name="l16620"></a><span class="lineno">16620</span>&#160;            bindBufferMemoryInfo.pNext = pNext;</div>
+<div class="line"><a name="l16621"></a><span class="lineno">16621</span>&#160;            bindBufferMemoryInfo.buffer = buffer;</div>
+<div class="line"><a name="l16622"></a><span class="lineno">16622</span>&#160;            bindBufferMemoryInfo.memory = memory;</div>
+<div class="line"><a name="l16623"></a><span class="lineno">16623</span>&#160;            bindBufferMemoryInfo.memoryOffset = memoryOffset;</div>
+<div class="line"><a name="l16624"></a><span class="lineno">16624</span>&#160;            <span class="keywordflow">return</span> (*m_VulkanFunctions.vkBindBufferMemory2KHR)(m_hDevice, 1, &amp;bindBufferMemoryInfo);</div>
+<div class="line"><a name="l16625"></a><span class="lineno">16625</span>&#160;        }</div>
+<div class="line"><a name="l16626"></a><span class="lineno">16626</span>&#160;        <span class="keywordflow">else</span></div>
+<div class="line"><a name="l16627"></a><span class="lineno">16627</span>&#160;<span class="preprocessor">#endif // #if VMA_VULKAN_VERSION &gt;= 1001000 || VMA_BIND_MEMORY2</span></div>
+<div class="line"><a name="l16628"></a><span class="lineno">16628</span>&#160;        {</div>
+<div class="line"><a name="l16629"></a><span class="lineno">16629</span>&#160;            <span class="keywordflow">return</span> VK_ERROR_EXTENSION_NOT_PRESENT;</div>
+<div class="line"><a name="l16630"></a><span class="lineno">16630</span>&#160;        }</div>
+<div class="line"><a name="l16631"></a><span class="lineno">16631</span>&#160;    }</div>
+<div class="line"><a name="l16632"></a><span class="lineno">16632</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l16633"></a><span class="lineno">16633</span>&#160;    {</div>
+<div class="line"><a name="l16634"></a><span class="lineno">16634</span>&#160;        <span class="keywordflow">return</span> (*m_VulkanFunctions.vkBindBufferMemory)(m_hDevice, buffer, memory, memoryOffset);</div>
+<div class="line"><a name="l16635"></a><span class="lineno">16635</span>&#160;    }</div>
+<div class="line"><a name="l16636"></a><span class="lineno">16636</span>&#160;}</div>
+<div class="line"><a name="l16637"></a><span class="lineno">16637</span>&#160; </div>
+<div class="line"><a name="l16638"></a><span class="lineno">16638</span>&#160;VkResult VmaAllocator_T::BindVulkanImage(</div>
+<div class="line"><a name="l16639"></a><span class="lineno">16639</span>&#160;    VkDeviceMemory memory,</div>
+<div class="line"><a name="l16640"></a><span class="lineno">16640</span>&#160;    VkDeviceSize memoryOffset,</div>
+<div class="line"><a name="l16641"></a><span class="lineno">16641</span>&#160;    VkImage image,</div>
+<div class="line"><a name="l16642"></a><span class="lineno">16642</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">void</span>* pNext)</div>
+<div class="line"><a name="l16643"></a><span class="lineno">16643</span>&#160;{</div>
+<div class="line"><a name="l16644"></a><span class="lineno">16644</span>&#160;    <span class="keywordflow">if</span>(pNext != VMA_NULL)</div>
+<div class="line"><a name="l16645"></a><span class="lineno">16645</span>&#160;    {</div>
+<div class="line"><a name="l16646"></a><span class="lineno">16646</span>&#160;<span class="preprocessor">#if VMA_VULKAN_VERSION &gt;= 1001000 || VMA_BIND_MEMORY2</span></div>
+<div class="line"><a name="l16647"></a><span class="lineno">16647</span>&#160;        <span class="keywordflow">if</span>((m_UseKhrBindMemory2 || m_VulkanApiVersion &gt;= VK_MAKE_VERSION(1, 1, 0)) &amp;&amp;</div>
+<div class="line"><a name="l16648"></a><span class="lineno">16648</span>&#160;            m_VulkanFunctions.vkBindImageMemory2KHR != VMA_NULL)</div>
+<div class="line"><a name="l16649"></a><span class="lineno">16649</span>&#160;        {</div>
+<div class="line"><a name="l16650"></a><span class="lineno">16650</span>&#160;            VkBindImageMemoryInfoKHR bindBufferMemoryInfo = { VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO_KHR };</div>
+<div class="line"><a name="l16651"></a><span class="lineno">16651</span>&#160;            bindBufferMemoryInfo.pNext = pNext;</div>
+<div class="line"><a name="l16652"></a><span class="lineno">16652</span>&#160;            bindBufferMemoryInfo.image = image;</div>
+<div class="line"><a name="l16653"></a><span class="lineno">16653</span>&#160;            bindBufferMemoryInfo.memory = memory;</div>
+<div class="line"><a name="l16654"></a><span class="lineno">16654</span>&#160;            bindBufferMemoryInfo.memoryOffset = memoryOffset;</div>
+<div class="line"><a name="l16655"></a><span class="lineno">16655</span>&#160;            <span class="keywordflow">return</span> (*m_VulkanFunctions.vkBindImageMemory2KHR)(m_hDevice, 1, &amp;bindBufferMemoryInfo);</div>
+<div class="line"><a name="l16656"></a><span class="lineno">16656</span>&#160;        }</div>
+<div class="line"><a name="l16657"></a><span class="lineno">16657</span>&#160;        <span class="keywordflow">else</span></div>
+<div class="line"><a name="l16658"></a><span class="lineno">16658</span>&#160;<span class="preprocessor">#endif // #if VMA_BIND_MEMORY2</span></div>
+<div class="line"><a name="l16659"></a><span class="lineno">16659</span>&#160;        {</div>
+<div class="line"><a name="l16660"></a><span class="lineno">16660</span>&#160;            <span class="keywordflow">return</span> VK_ERROR_EXTENSION_NOT_PRESENT;</div>
+<div class="line"><a name="l16661"></a><span class="lineno">16661</span>&#160;        }</div>
+<div class="line"><a name="l16662"></a><span class="lineno">16662</span>&#160;    }</div>
+<div class="line"><a name="l16663"></a><span class="lineno">16663</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l16664"></a><span class="lineno">16664</span>&#160;    {</div>
+<div class="line"><a name="l16665"></a><span class="lineno">16665</span>&#160;        <span class="keywordflow">return</span> (*m_VulkanFunctions.vkBindImageMemory)(m_hDevice, image, memory, memoryOffset);</div>
+<div class="line"><a name="l16666"></a><span class="lineno">16666</span>&#160;    }</div>
+<div class="line"><a name="l16667"></a><span class="lineno">16667</span>&#160;}</div>
+<div class="line"><a name="l16668"></a><span class="lineno">16668</span>&#160; </div>
+<div class="line"><a name="l16669"></a><span class="lineno">16669</span>&#160;VkResult VmaAllocator_T::Map(<a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAllocation, <span class="keywordtype">void</span>** ppData)</div>
+<div class="line"><a name="l16670"></a><span class="lineno">16670</span>&#160;{</div>
+<div class="line"><a name="l16671"></a><span class="lineno">16671</span>&#160;    <span class="keywordflow">if</span>(hAllocation-&gt;CanBecomeLost())</div>
+<div class="line"><a name="l16672"></a><span class="lineno">16672</span>&#160;    {</div>
+<div class="line"><a name="l16673"></a><span class="lineno">16673</span>&#160;        <span class="keywordflow">return</span> VK_ERROR_MEMORY_MAP_FAILED;</div>
+<div class="line"><a name="l16674"></a><span class="lineno">16674</span>&#160;    }</div>
+<div class="line"><a name="l16675"></a><span class="lineno">16675</span>&#160; </div>
+<div class="line"><a name="l16676"></a><span class="lineno">16676</span>&#160;    <span class="keywordflow">switch</span>(hAllocation-&gt;GetType())</div>
+<div class="line"><a name="l16677"></a><span class="lineno">16677</span>&#160;    {</div>
+<div class="line"><a name="l16678"></a><span class="lineno">16678</span>&#160;    <span class="keywordflow">case</span> VmaAllocation_T::ALLOCATION_TYPE_BLOCK:</div>
+<div class="line"><a name="l16679"></a><span class="lineno">16679</span>&#160;        {</div>
+<div class="line"><a name="l16680"></a><span class="lineno">16680</span>&#160;            VmaDeviceMemoryBlock* <span class="keyword">const</span> pBlock = hAllocation-&gt;GetBlock();</div>
+<div class="line"><a name="l16681"></a><span class="lineno">16681</span>&#160;            <span class="keywordtype">char</span> *pBytes = VMA_NULL;</div>
+<div class="line"><a name="l16682"></a><span class="lineno">16682</span>&#160;            VkResult res = pBlock-&gt;Map(<span class="keyword">this</span>, 1, (<span class="keywordtype">void</span>**)&amp;pBytes);</div>
+<div class="line"><a name="l16683"></a><span class="lineno">16683</span>&#160;            <span class="keywordflow">if</span>(res == VK_SUCCESS)</div>
+<div class="line"><a name="l16684"></a><span class="lineno">16684</span>&#160;            {</div>
+<div class="line"><a name="l16685"></a><span class="lineno">16685</span>&#160;                *ppData = pBytes + (ptrdiff_t)hAllocation-&gt;GetOffset();</div>
+<div class="line"><a name="l16686"></a><span class="lineno">16686</span>&#160;                hAllocation-&gt;BlockAllocMap();</div>
+<div class="line"><a name="l16687"></a><span class="lineno">16687</span>&#160;            }</div>
+<div class="line"><a name="l16688"></a><span class="lineno">16688</span>&#160;            <span class="keywordflow">return</span> res;</div>
+<div class="line"><a name="l16689"></a><span class="lineno">16689</span>&#160;        }</div>
+<div class="line"><a name="l16690"></a><span class="lineno">16690</span>&#160;    <span class="keywordflow">case</span> VmaAllocation_T::ALLOCATION_TYPE_DEDICATED:</div>
+<div class="line"><a name="l16691"></a><span class="lineno">16691</span>&#160;        <span class="keywordflow">return</span> hAllocation-&gt;DedicatedAllocMap(<span class="keyword">this</span>, ppData);</div>
+<div class="line"><a name="l16692"></a><span class="lineno">16692</span>&#160;    <span class="keywordflow">default</span>:</div>
+<div class="line"><a name="l16693"></a><span class="lineno">16693</span>&#160;        VMA_ASSERT(0);</div>
+<div class="line"><a name="l16694"></a><span class="lineno">16694</span>&#160;        <span class="keywordflow">return</span> VK_ERROR_MEMORY_MAP_FAILED;</div>
+<div class="line"><a name="l16695"></a><span class="lineno">16695</span>&#160;    }</div>
+<div class="line"><a name="l16696"></a><span class="lineno">16696</span>&#160;}</div>
+<div class="line"><a name="l16697"></a><span class="lineno">16697</span>&#160; </div>
+<div class="line"><a name="l16698"></a><span class="lineno">16698</span>&#160;<span class="keywordtype">void</span> VmaAllocator_T::Unmap(<a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAllocation)</div>
+<div class="line"><a name="l16699"></a><span class="lineno">16699</span>&#160;{</div>
+<div class="line"><a name="l16700"></a><span class="lineno">16700</span>&#160;    <span class="keywordflow">switch</span>(hAllocation-&gt;GetType())</div>
+<div class="line"><a name="l16701"></a><span class="lineno">16701</span>&#160;    {</div>
+<div class="line"><a name="l16702"></a><span class="lineno">16702</span>&#160;    <span class="keywordflow">case</span> VmaAllocation_T::ALLOCATION_TYPE_BLOCK:</div>
+<div class="line"><a name="l16703"></a><span class="lineno">16703</span>&#160;        {</div>
+<div class="line"><a name="l16704"></a><span class="lineno">16704</span>&#160;            VmaDeviceMemoryBlock* <span class="keyword">const</span> pBlock = hAllocation-&gt;GetBlock();</div>
+<div class="line"><a name="l16705"></a><span class="lineno">16705</span>&#160;            hAllocation-&gt;BlockAllocUnmap();</div>
+<div class="line"><a name="l16706"></a><span class="lineno">16706</span>&#160;            pBlock-&gt;Unmap(<span class="keyword">this</span>, 1);</div>
+<div class="line"><a name="l16707"></a><span class="lineno">16707</span>&#160;        }</div>
+<div class="line"><a name="l16708"></a><span class="lineno">16708</span>&#160;        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l16709"></a><span class="lineno">16709</span>&#160;    <span class="keywordflow">case</span> VmaAllocation_T::ALLOCATION_TYPE_DEDICATED:</div>
+<div class="line"><a name="l16710"></a><span class="lineno">16710</span>&#160;        hAllocation-&gt;DedicatedAllocUnmap(<span class="keyword">this</span>);</div>
+<div class="line"><a name="l16711"></a><span class="lineno">16711</span>&#160;        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l16712"></a><span class="lineno">16712</span>&#160;    <span class="keywordflow">default</span>:</div>
+<div class="line"><a name="l16713"></a><span class="lineno">16713</span>&#160;        VMA_ASSERT(0);</div>
+<div class="line"><a name="l16714"></a><span class="lineno">16714</span>&#160;    }</div>
+<div class="line"><a name="l16715"></a><span class="lineno">16715</span>&#160;}</div>
+<div class="line"><a name="l16716"></a><span class="lineno">16716</span>&#160; </div>
+<div class="line"><a name="l16717"></a><span class="lineno">16717</span>&#160;VkResult VmaAllocator_T::BindBufferMemory(</div>
+<div class="line"><a name="l16718"></a><span class="lineno">16718</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAllocation,</div>
+<div class="line"><a name="l16719"></a><span class="lineno">16719</span>&#160;    VkDeviceSize allocationLocalOffset,</div>
+<div class="line"><a name="l16720"></a><span class="lineno">16720</span>&#160;    VkBuffer hBuffer,</div>
+<div class="line"><a name="l16721"></a><span class="lineno">16721</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">void</span>* pNext)</div>
+<div class="line"><a name="l16722"></a><span class="lineno">16722</span>&#160;{</div>
+<div class="line"><a name="l16723"></a><span class="lineno">16723</span>&#160;    VkResult res = VK_SUCCESS;</div>
+<div class="line"><a name="l16724"></a><span class="lineno">16724</span>&#160;    <span class="keywordflow">switch</span>(hAllocation-&gt;GetType())</div>
+<div class="line"><a name="l16725"></a><span class="lineno">16725</span>&#160;    {</div>
+<div class="line"><a name="l16726"></a><span class="lineno">16726</span>&#160;    <span class="keywordflow">case</span> VmaAllocation_T::ALLOCATION_TYPE_DEDICATED:</div>
+<div class="line"><a name="l16727"></a><span class="lineno">16727</span>&#160;        res = BindVulkanBuffer(hAllocation-&gt;GetMemory(), allocationLocalOffset, hBuffer, pNext);</div>
+<div class="line"><a name="l16728"></a><span class="lineno">16728</span>&#160;        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l16729"></a><span class="lineno">16729</span>&#160;    <span class="keywordflow">case</span> VmaAllocation_T::ALLOCATION_TYPE_BLOCK:</div>
+<div class="line"><a name="l16730"></a><span class="lineno">16730</span>&#160;    {</div>
+<div class="line"><a name="l16731"></a><span class="lineno">16731</span>&#160;        VmaDeviceMemoryBlock* <span class="keyword">const</span> pBlock = hAllocation-&gt;GetBlock();</div>
+<div class="line"><a name="l16732"></a><span class="lineno">16732</span>&#160;        VMA_ASSERT(pBlock &amp;&amp; <span class="stringliteral">&quot;Binding buffer to allocation that doesn&#39;t belong to any block. Is the allocation lost?&quot;</span>);</div>
+<div class="line"><a name="l16733"></a><span class="lineno">16733</span>&#160;        res = pBlock-&gt;BindBufferMemory(<span class="keyword">this</span>, hAllocation, allocationLocalOffset, hBuffer, pNext);</div>
+<div class="line"><a name="l16734"></a><span class="lineno">16734</span>&#160;        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l16735"></a><span class="lineno">16735</span>&#160;    }</div>
+<div class="line"><a name="l16736"></a><span class="lineno">16736</span>&#160;    <span class="keywordflow">default</span>:</div>
+<div class="line"><a name="l16737"></a><span class="lineno">16737</span>&#160;        VMA_ASSERT(0);</div>
+<div class="line"><a name="l16738"></a><span class="lineno">16738</span>&#160;    }</div>
+<div class="line"><a name="l16739"></a><span class="lineno">16739</span>&#160;    <span class="keywordflow">return</span> res;</div>
+<div class="line"><a name="l16740"></a><span class="lineno">16740</span>&#160;}</div>
+<div class="line"><a name="l16741"></a><span class="lineno">16741</span>&#160; </div>
+<div class="line"><a name="l16742"></a><span class="lineno">16742</span>&#160;VkResult VmaAllocator_T::BindImageMemory(</div>
+<div class="line"><a name="l16743"></a><span class="lineno">16743</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAllocation,</div>
+<div class="line"><a name="l16744"></a><span class="lineno">16744</span>&#160;    VkDeviceSize allocationLocalOffset,</div>
+<div class="line"><a name="l16745"></a><span class="lineno">16745</span>&#160;    VkImage hImage,</div>
+<div class="line"><a name="l16746"></a><span class="lineno">16746</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">void</span>* pNext)</div>
+<div class="line"><a name="l16747"></a><span class="lineno">16747</span>&#160;{</div>
+<div class="line"><a name="l16748"></a><span class="lineno">16748</span>&#160;    VkResult res = VK_SUCCESS;</div>
+<div class="line"><a name="l16749"></a><span class="lineno">16749</span>&#160;    <span class="keywordflow">switch</span>(hAllocation-&gt;GetType())</div>
+<div class="line"><a name="l16750"></a><span class="lineno">16750</span>&#160;    {</div>
+<div class="line"><a name="l16751"></a><span class="lineno">16751</span>&#160;    <span class="keywordflow">case</span> VmaAllocation_T::ALLOCATION_TYPE_DEDICATED:</div>
+<div class="line"><a name="l16752"></a><span class="lineno">16752</span>&#160;        res = BindVulkanImage(hAllocation-&gt;GetMemory(), allocationLocalOffset, hImage, pNext);</div>
+<div class="line"><a name="l16753"></a><span class="lineno">16753</span>&#160;        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l16754"></a><span class="lineno">16754</span>&#160;    <span class="keywordflow">case</span> VmaAllocation_T::ALLOCATION_TYPE_BLOCK:</div>
+<div class="line"><a name="l16755"></a><span class="lineno">16755</span>&#160;    {</div>
+<div class="line"><a name="l16756"></a><span class="lineno">16756</span>&#160;        VmaDeviceMemoryBlock* pBlock = hAllocation-&gt;GetBlock();</div>
+<div class="line"><a name="l16757"></a><span class="lineno">16757</span>&#160;        VMA_ASSERT(pBlock &amp;&amp; <span class="stringliteral">&quot;Binding image to allocation that doesn&#39;t belong to any block. Is the allocation lost?&quot;</span>);</div>
+<div class="line"><a name="l16758"></a><span class="lineno">16758</span>&#160;        res = pBlock-&gt;BindImageMemory(<span class="keyword">this</span>, hAllocation, allocationLocalOffset, hImage, pNext);</div>
+<div class="line"><a name="l16759"></a><span class="lineno">16759</span>&#160;        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l16760"></a><span class="lineno">16760</span>&#160;    }</div>
+<div class="line"><a name="l16761"></a><span class="lineno">16761</span>&#160;    <span class="keywordflow">default</span>:</div>
+<div class="line"><a name="l16762"></a><span class="lineno">16762</span>&#160;        VMA_ASSERT(0);</div>
+<div class="line"><a name="l16763"></a><span class="lineno">16763</span>&#160;    }</div>
+<div class="line"><a name="l16764"></a><span class="lineno">16764</span>&#160;    <span class="keywordflow">return</span> res;</div>
+<div class="line"><a name="l16765"></a><span class="lineno">16765</span>&#160;}</div>
+<div class="line"><a name="l16766"></a><span class="lineno">16766</span>&#160; </div>
+<div class="line"><a name="l16767"></a><span class="lineno">16767</span>&#160;<span class="keywordtype">void</span> VmaAllocator_T::FlushOrInvalidateAllocation(</div>
+<div class="line"><a name="l16768"></a><span class="lineno">16768</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAllocation,</div>
+<div class="line"><a name="l16769"></a><span class="lineno">16769</span>&#160;    VkDeviceSize offset, VkDeviceSize size,</div>
+<div class="line"><a name="l16770"></a><span class="lineno">16770</span>&#160;    VMA_CACHE_OPERATION op)</div>
+<div class="line"><a name="l16771"></a><span class="lineno">16771</span>&#160;{</div>
+<div class="line"><a name="l16772"></a><span class="lineno">16772</span>&#160;    <span class="keyword">const</span> uint32_t memTypeIndex = hAllocation-&gt;GetMemoryTypeIndex();</div>
+<div class="line"><a name="l16773"></a><span class="lineno">16773</span>&#160;    <span class="keywordflow">if</span>(size &gt; 0 &amp;&amp; IsMemoryTypeNonCoherent(memTypeIndex))</div>
+<div class="line"><a name="l16774"></a><span class="lineno">16774</span>&#160;    {</div>
+<div class="line"><a name="l16775"></a><span class="lineno">16775</span>&#160;        <span class="keyword">const</span> VkDeviceSize allocationSize = hAllocation-&gt;GetSize();</div>
+<div class="line"><a name="l16776"></a><span class="lineno">16776</span>&#160;        VMA_ASSERT(offset &lt;= allocationSize);</div>
+<div class="line"><a name="l16777"></a><span class="lineno">16777</span>&#160; </div>
+<div class="line"><a name="l16778"></a><span class="lineno">16778</span>&#160;        <span class="keyword">const</span> VkDeviceSize nonCoherentAtomSize = m_PhysicalDeviceProperties.limits.nonCoherentAtomSize;</div>
+<div class="line"><a name="l16779"></a><span class="lineno">16779</span>&#160; </div>
+<div class="line"><a name="l16780"></a><span class="lineno">16780</span>&#160;        VkMappedMemoryRange memRange = { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE };</div>
+<div class="line"><a name="l16781"></a><span class="lineno">16781</span>&#160;        memRange.memory = hAllocation-&gt;GetMemory();</div>
+<div class="line"><a name="l16782"></a><span class="lineno">16782</span>&#160;        </div>
+<div class="line"><a name="l16783"></a><span class="lineno">16783</span>&#160;        <span class="keywordflow">switch</span>(hAllocation-&gt;GetType())</div>
+<div class="line"><a name="l16784"></a><span class="lineno">16784</span>&#160;        {</div>
+<div class="line"><a name="l16785"></a><span class="lineno">16785</span>&#160;        <span class="keywordflow">case</span> VmaAllocation_T::ALLOCATION_TYPE_DEDICATED:</div>
+<div class="line"><a name="l16786"></a><span class="lineno">16786</span>&#160;            memRange.offset = VmaAlignDown(offset, nonCoherentAtomSize);</div>
+<div class="line"><a name="l16787"></a><span class="lineno">16787</span>&#160;            <span class="keywordflow">if</span>(size == VK_WHOLE_SIZE)</div>
+<div class="line"><a name="l16788"></a><span class="lineno">16788</span>&#160;            {</div>
+<div class="line"><a name="l16789"></a><span class="lineno">16789</span>&#160;                memRange.size = allocationSize - memRange.offset;</div>
+<div class="line"><a name="l16790"></a><span class="lineno">16790</span>&#160;            }</div>
+<div class="line"><a name="l16791"></a><span class="lineno">16791</span>&#160;            <span class="keywordflow">else</span></div>
+<div class="line"><a name="l16792"></a><span class="lineno">16792</span>&#160;            {</div>
+<div class="line"><a name="l16793"></a><span class="lineno">16793</span>&#160;                VMA_ASSERT(offset + size &lt;= allocationSize);</div>
+<div class="line"><a name="l16794"></a><span class="lineno">16794</span>&#160;                memRange.size = VMA_MIN(</div>
+<div class="line"><a name="l16795"></a><span class="lineno">16795</span>&#160;                    VmaAlignUp(size + (offset - memRange.offset), nonCoherentAtomSize),</div>
+<div class="line"><a name="l16796"></a><span class="lineno">16796</span>&#160;                    allocationSize - memRange.offset);</div>
+<div class="line"><a name="l16797"></a><span class="lineno">16797</span>&#160;            }</div>
+<div class="line"><a name="l16798"></a><span class="lineno">16798</span>&#160;            <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l16799"></a><span class="lineno">16799</span>&#160; </div>
+<div class="line"><a name="l16800"></a><span class="lineno">16800</span>&#160;        <span class="keywordflow">case</span> VmaAllocation_T::ALLOCATION_TYPE_BLOCK:</div>
+<div class="line"><a name="l16801"></a><span class="lineno">16801</span>&#160;        {</div>
+<div class="line"><a name="l16802"></a><span class="lineno">16802</span>&#160;            <span class="comment">// 1. Still within this allocation.</span></div>
+<div class="line"><a name="l16803"></a><span class="lineno">16803</span>&#160;            memRange.offset = VmaAlignDown(offset, nonCoherentAtomSize);</div>
+<div class="line"><a name="l16804"></a><span class="lineno">16804</span>&#160;            <span class="keywordflow">if</span>(size == VK_WHOLE_SIZE)</div>
+<div class="line"><a name="l16805"></a><span class="lineno">16805</span>&#160;            {</div>
+<div class="line"><a name="l16806"></a><span class="lineno">16806</span>&#160;                size = allocationSize - offset;</div>
+<div class="line"><a name="l16807"></a><span class="lineno">16807</span>&#160;            }</div>
+<div class="line"><a name="l16808"></a><span class="lineno">16808</span>&#160;            <span class="keywordflow">else</span></div>
+<div class="line"><a name="l16809"></a><span class="lineno">16809</span>&#160;            {</div>
+<div class="line"><a name="l16810"></a><span class="lineno">16810</span>&#160;                VMA_ASSERT(offset + size &lt;= allocationSize);</div>
+<div class="line"><a name="l16811"></a><span class="lineno">16811</span>&#160;            }</div>
+<div class="line"><a name="l16812"></a><span class="lineno">16812</span>&#160;            memRange.size = VmaAlignUp(size + (offset - memRange.offset), nonCoherentAtomSize);</div>
+<div class="line"><a name="l16813"></a><span class="lineno">16813</span>&#160; </div>
+<div class="line"><a name="l16814"></a><span class="lineno">16814</span>&#160;            <span class="comment">// 2. Adjust to whole block.</span></div>
+<div class="line"><a name="l16815"></a><span class="lineno">16815</span>&#160;            <span class="keyword">const</span> VkDeviceSize allocationOffset = hAllocation-&gt;GetOffset();</div>
+<div class="line"><a name="l16816"></a><span class="lineno">16816</span>&#160;            VMA_ASSERT(allocationOffset % nonCoherentAtomSize == 0);</div>
+<div class="line"><a name="l16817"></a><span class="lineno">16817</span>&#160;            <span class="keyword">const</span> VkDeviceSize blockSize = hAllocation-&gt;GetBlock()-&gt;m_pMetadata-&gt;GetSize();</div>
+<div class="line"><a name="l16818"></a><span class="lineno">16818</span>&#160;            memRange.offset += allocationOffset;</div>
+<div class="line"><a name="l16819"></a><span class="lineno">16819</span>&#160;            memRange.size = VMA_MIN(memRange.size, blockSize - memRange.offset);</div>
+<div class="line"><a name="l16820"></a><span class="lineno">16820</span>&#160;            </div>
+<div class="line"><a name="l16821"></a><span class="lineno">16821</span>&#160;            <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l16822"></a><span class="lineno">16822</span>&#160;        }</div>
+<div class="line"><a name="l16823"></a><span class="lineno">16823</span>&#160;        </div>
+<div class="line"><a name="l16824"></a><span class="lineno">16824</span>&#160;        <span class="keywordflow">default</span>:</div>
+<div class="line"><a name="l16825"></a><span class="lineno">16825</span>&#160;            VMA_ASSERT(0);</div>
+<div class="line"><a name="l16826"></a><span class="lineno">16826</span>&#160;        }</div>
+<div class="line"><a name="l16827"></a><span class="lineno">16827</span>&#160; </div>
+<div class="line"><a name="l16828"></a><span class="lineno">16828</span>&#160;        <span class="keywordflow">switch</span>(op)</div>
+<div class="line"><a name="l16829"></a><span class="lineno">16829</span>&#160;        {</div>
+<div class="line"><a name="l16830"></a><span class="lineno">16830</span>&#160;        <span class="keywordflow">case</span> VMA_CACHE_FLUSH:</div>
+<div class="line"><a name="l16831"></a><span class="lineno">16831</span>&#160;            (*GetVulkanFunctions().vkFlushMappedMemoryRanges)(m_hDevice, 1, &amp;memRange);</div>
+<div class="line"><a name="l16832"></a><span class="lineno">16832</span>&#160;            <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l16833"></a><span class="lineno">16833</span>&#160;        <span class="keywordflow">case</span> VMA_CACHE_INVALIDATE:</div>
+<div class="line"><a name="l16834"></a><span class="lineno">16834</span>&#160;            (*GetVulkanFunctions().vkInvalidateMappedMemoryRanges)(m_hDevice, 1, &amp;memRange);</div>
+<div class="line"><a name="l16835"></a><span class="lineno">16835</span>&#160;            <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l16836"></a><span class="lineno">16836</span>&#160;        <span class="keywordflow">default</span>:</div>
+<div class="line"><a name="l16837"></a><span class="lineno">16837</span>&#160;            VMA_ASSERT(0);</div>
+<div class="line"><a name="l16838"></a><span class="lineno">16838</span>&#160;        }</div>
+<div class="line"><a name="l16839"></a><span class="lineno">16839</span>&#160;    }</div>
+<div class="line"><a name="l16840"></a><span class="lineno">16840</span>&#160;    <span class="comment">// else: Just ignore this call.</span></div>
+<div class="line"><a name="l16841"></a><span class="lineno">16841</span>&#160;}</div>
+<div class="line"><a name="l16842"></a><span class="lineno">16842</span>&#160; </div>
+<div class="line"><a name="l16843"></a><span class="lineno">16843</span>&#160;<span class="keywordtype">void</span> VmaAllocator_T::FreeDedicatedMemory(<span class="keyword">const</span> <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation)</div>
+<div class="line"><a name="l16844"></a><span class="lineno">16844</span>&#160;{</div>
+<div class="line"><a name="l16845"></a><span class="lineno">16845</span>&#160;    VMA_ASSERT(allocation &amp;&amp; allocation-&gt;GetType() == VmaAllocation_T::ALLOCATION_TYPE_DEDICATED);</div>
+<div class="line"><a name="l16846"></a><span class="lineno">16846</span>&#160; </div>
+<div class="line"><a name="l16847"></a><span class="lineno">16847</span>&#160;    <span class="keyword">const</span> uint32_t memTypeIndex = allocation-&gt;GetMemoryTypeIndex();</div>
+<div class="line"><a name="l16848"></a><span class="lineno">16848</span>&#160;    {</div>
+<div class="line"><a name="l16849"></a><span class="lineno">16849</span>&#160;        VmaMutexLockWrite lock(m_DedicatedAllocationsMutex[memTypeIndex], m_UseMutex);</div>
+<div class="line"><a name="l16850"></a><span class="lineno">16850</span>&#160;        AllocationVectorType* <span class="keyword">const</span> pDedicatedAllocations = m_pDedicatedAllocations[memTypeIndex];</div>
+<div class="line"><a name="l16851"></a><span class="lineno">16851</span>&#160;        VMA_ASSERT(pDedicatedAllocations);</div>
+<div class="line"><a name="l16852"></a><span class="lineno">16852</span>&#160;        <span class="keywordtype">bool</span> success = VmaVectorRemoveSorted&lt;VmaPointerLess&gt;(*pDedicatedAllocations, allocation);</div>
+<div class="line"><a name="l16853"></a><span class="lineno">16853</span>&#160;        VMA_ASSERT(success);</div>
+<div class="line"><a name="l16854"></a><span class="lineno">16854</span>&#160;    }</div>
+<div class="line"><a name="l16855"></a><span class="lineno">16855</span>&#160; </div>
+<div class="line"><a name="l16856"></a><span class="lineno">16856</span>&#160;    VkDeviceMemory hMemory = allocation-&gt;GetMemory();</div>
+<div class="line"><a name="l16857"></a><span class="lineno">16857</span>&#160;    </div>
+<div class="line"><a name="l16858"></a><span class="lineno">16858</span>&#160;    <span class="comment">/*</span></div>
+<div class="line"><a name="l16859"></a><span class="lineno">16859</span>&#160;<span class="comment">    There is no need to call this, because Vulkan spec allows to skip vkUnmapMemory</span></div>
+<div class="line"><a name="l16860"></a><span class="lineno">16860</span>&#160;<span class="comment">    before vkFreeMemory.</span></div>
+<div class="line"><a name="l16861"></a><span class="lineno">16861</span>&#160;<span class="comment"></span> </div>
+<div class="line"><a name="l16862"></a><span class="lineno">16862</span>&#160;<span class="comment">    if(allocation-&gt;GetMappedData() != VMA_NULL)</span></div>
+<div class="line"><a name="l16863"></a><span class="lineno">16863</span>&#160;<span class="comment">    {</span></div>
+<div class="line"><a name="l16864"></a><span class="lineno">16864</span>&#160;<span class="comment">        (*m_VulkanFunctions.vkUnmapMemory)(m_hDevice, hMemory);</span></div>
+<div class="line"><a name="l16865"></a><span class="lineno">16865</span>&#160;<span class="comment">    }</span></div>
+<div class="line"><a name="l16866"></a><span class="lineno">16866</span>&#160;<span class="comment">    */</span></div>
+<div class="line"><a name="l16867"></a><span class="lineno">16867</span>&#160;    </div>
+<div class="line"><a name="l16868"></a><span class="lineno">16868</span>&#160;    FreeVulkanMemory(memTypeIndex, allocation-&gt;GetSize(), hMemory);</div>
+<div class="line"><a name="l16869"></a><span class="lineno">16869</span>&#160; </div>
+<div class="line"><a name="l16870"></a><span class="lineno">16870</span>&#160;    VMA_DEBUG_LOG(<span class="stringliteral">&quot;    Freed DedicatedMemory MemoryTypeIndex=%u&quot;</span>, memTypeIndex);</div>
+<div class="line"><a name="l16871"></a><span class="lineno">16871</span>&#160;}</div>
+<div class="line"><a name="l16872"></a><span class="lineno">16872</span>&#160; </div>
+<div class="line"><a name="l16873"></a><span class="lineno">16873</span>&#160;uint32_t VmaAllocator_T::CalculateGpuDefragmentationMemoryTypeBits()<span class="keyword"> const</span></div>
+<div class="line"><a name="l16874"></a><span class="lineno">16874</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l16875"></a><span class="lineno">16875</span>&#160;    VkBufferCreateInfo dummyBufCreateInfo;</div>
+<div class="line"><a name="l16876"></a><span class="lineno">16876</span>&#160;    VmaFillGpuDefragmentationBufferCreateInfo(dummyBufCreateInfo);</div>
+<div class="line"><a name="l16877"></a><span class="lineno">16877</span>&#160; </div>
+<div class="line"><a name="l16878"></a><span class="lineno">16878</span>&#160;    uint32_t memoryTypeBits = 0;</div>
+<div class="line"><a name="l16879"></a><span class="lineno">16879</span>&#160; </div>
+<div class="line"><a name="l16880"></a><span class="lineno">16880</span>&#160;    <span class="comment">// Create buffer.</span></div>
+<div class="line"><a name="l16881"></a><span class="lineno">16881</span>&#160;    VkBuffer buf = VK_NULL_HANDLE;</div>
+<div class="line"><a name="l16882"></a><span class="lineno">16882</span>&#160;    VkResult res = (*GetVulkanFunctions().vkCreateBuffer)(</div>
+<div class="line"><a name="l16883"></a><span class="lineno">16883</span>&#160;        m_hDevice, &amp;dummyBufCreateInfo, GetAllocationCallbacks(), &amp;buf);</div>
+<div class="line"><a name="l16884"></a><span class="lineno">16884</span>&#160;    <span class="keywordflow">if</span>(res == VK_SUCCESS)</div>
+<div class="line"><a name="l16885"></a><span class="lineno">16885</span>&#160;    {</div>
+<div class="line"><a name="l16886"></a><span class="lineno">16886</span>&#160;        <span class="comment">// Query for supported memory types.</span></div>
+<div class="line"><a name="l16887"></a><span class="lineno">16887</span>&#160;        VkMemoryRequirements memReq;</div>
+<div class="line"><a name="l16888"></a><span class="lineno">16888</span>&#160;        (*GetVulkanFunctions().vkGetBufferMemoryRequirements)(m_hDevice, buf, &amp;memReq);</div>
+<div class="line"><a name="l16889"></a><span class="lineno">16889</span>&#160;        memoryTypeBits = memReq.memoryTypeBits;</div>
+<div class="line"><a name="l16890"></a><span class="lineno">16890</span>&#160; </div>
+<div class="line"><a name="l16891"></a><span class="lineno">16891</span>&#160;        <span class="comment">// Destroy buffer.</span></div>
+<div class="line"><a name="l16892"></a><span class="lineno">16892</span>&#160;        (*GetVulkanFunctions().vkDestroyBuffer)(m_hDevice, buf, GetAllocationCallbacks());</div>
+<div class="line"><a name="l16893"></a><span class="lineno">16893</span>&#160;    }</div>
+<div class="line"><a name="l16894"></a><span class="lineno">16894</span>&#160; </div>
+<div class="line"><a name="l16895"></a><span class="lineno">16895</span>&#160;    <span class="keywordflow">return</span> memoryTypeBits;</div>
+<div class="line"><a name="l16896"></a><span class="lineno">16896</span>&#160;}</div>
+<div class="line"><a name="l16897"></a><span class="lineno">16897</span>&#160; </div>
+<div class="line"><a name="l16898"></a><span class="lineno">16898</span>&#160;uint32_t VmaAllocator_T::CalculateGlobalMemoryTypeBits()<span class="keyword"> const</span></div>
+<div class="line"><a name="l16899"></a><span class="lineno">16899</span>&#160;<span class="keyword"></span>{</div>
+<div class="line"><a name="l16900"></a><span class="lineno">16900</span>&#160;    <span class="comment">// Make sure memory information is already fetched.</span></div>
+<div class="line"><a name="l16901"></a><span class="lineno">16901</span>&#160;    VMA_ASSERT(GetMemoryTypeCount() &gt; 0);</div>
+<div class="line"><a name="l16902"></a><span class="lineno">16902</span>&#160; </div>
+<div class="line"><a name="l16903"></a><span class="lineno">16903</span>&#160;    uint32_t memoryTypeBits = UINT32_MAX;</div>
+<div class="line"><a name="l16904"></a><span class="lineno">16904</span>&#160; </div>
+<div class="line"><a name="l16905"></a><span class="lineno">16905</span>&#160;    <span class="keywordflow">if</span>(!m_UseAmdDeviceCoherentMemory)</div>
+<div class="line"><a name="l16906"></a><span class="lineno">16906</span>&#160;    {</div>
+<div class="line"><a name="l16907"></a><span class="lineno">16907</span>&#160;        <span class="comment">// Exclude memory types that have VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD.</span></div>
+<div class="line"><a name="l16908"></a><span class="lineno">16908</span>&#160;        <span class="keywordflow">for</span>(uint32_t memTypeIndex = 0; memTypeIndex &lt; GetMemoryTypeCount(); ++memTypeIndex)</div>
+<div class="line"><a name="l16909"></a><span class="lineno">16909</span>&#160;        {</div>
+<div class="line"><a name="l16910"></a><span class="lineno">16910</span>&#160;            <span class="keywordflow">if</span>((m_MemProps.memoryTypes[memTypeIndex].propertyFlags &amp; VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD_COPY) != 0)</div>
+<div class="line"><a name="l16911"></a><span class="lineno">16911</span>&#160;            {</div>
+<div class="line"><a name="l16912"></a><span class="lineno">16912</span>&#160;                memoryTypeBits &amp;= ~(1u &lt;&lt; memTypeIndex);</div>
+<div class="line"><a name="l16913"></a><span class="lineno">16913</span>&#160;            }</div>
+<div class="line"><a name="l16914"></a><span class="lineno">16914</span>&#160;        }</div>
+<div class="line"><a name="l16915"></a><span class="lineno">16915</span>&#160;    }</div>
+<div class="line"><a name="l16916"></a><span class="lineno">16916</span>&#160; </div>
+<div class="line"><a name="l16917"></a><span class="lineno">16917</span>&#160;    <span class="keywordflow">return</span> memoryTypeBits;</div>
+<div class="line"><a name="l16918"></a><span class="lineno">16918</span>&#160;}</div>
+<div class="line"><a name="l16919"></a><span class="lineno">16919</span>&#160; </div>
+<div class="line"><a name="l16920"></a><span class="lineno">16920</span>&#160;<span class="preprocessor">#if VMA_MEMORY_BUDGET</span></div>
+<div class="line"><a name="l16921"></a><span class="lineno">16921</span>&#160; </div>
+<div class="line"><a name="l16922"></a><span class="lineno">16922</span>&#160;<span class="keywordtype">void</span> VmaAllocator_T::UpdateVulkanBudget()</div>
+<div class="line"><a name="l16923"></a><span class="lineno">16923</span>&#160;{</div>
+<div class="line"><a name="l16924"></a><span class="lineno">16924</span>&#160;    VMA_ASSERT(m_UseExtMemoryBudget);</div>
+<div class="line"><a name="l16925"></a><span class="lineno">16925</span>&#160; </div>
+<div class="line"><a name="l16926"></a><span class="lineno">16926</span>&#160;    VkPhysicalDeviceMemoryProperties2KHR memProps = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR };</div>
+<div class="line"><a name="l16927"></a><span class="lineno">16927</span>&#160; </div>
+<div class="line"><a name="l16928"></a><span class="lineno">16928</span>&#160;    VkPhysicalDeviceMemoryBudgetPropertiesEXT budgetProps = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT };</div>
+<div class="line"><a name="l16929"></a><span class="lineno">16929</span>&#160;    VmaPnextChainPushFront(&amp;memProps, &amp;budgetProps);</div>
+<div class="line"><a name="l16930"></a><span class="lineno">16930</span>&#160; </div>
+<div class="line"><a name="l16931"></a><span class="lineno">16931</span>&#160;    GetVulkanFunctions().vkGetPhysicalDeviceMemoryProperties2KHR(m_PhysicalDevice, &amp;memProps);</div>
+<div class="line"><a name="l16932"></a><span class="lineno">16932</span>&#160; </div>
+<div class="line"><a name="l16933"></a><span class="lineno">16933</span>&#160;    {</div>
+<div class="line"><a name="l16934"></a><span class="lineno">16934</span>&#160;        VmaMutexLockWrite lockWrite(m_Budget.m_BudgetMutex, m_UseMutex);</div>
+<div class="line"><a name="l16935"></a><span class="lineno">16935</span>&#160; </div>
+<div class="line"><a name="l16936"></a><span class="lineno">16936</span>&#160;        <span class="keywordflow">for</span>(uint32_t heapIndex = 0; heapIndex &lt; GetMemoryHeapCount(); ++heapIndex)</div>
+<div class="line"><a name="l16937"></a><span class="lineno">16937</span>&#160;        {</div>
+<div class="line"><a name="l16938"></a><span class="lineno">16938</span>&#160;            m_Budget.m_VulkanUsage[heapIndex] = budgetProps.heapUsage[heapIndex];</div>
+<div class="line"><a name="l16939"></a><span class="lineno">16939</span>&#160;            m_Budget.m_VulkanBudget[heapIndex] = budgetProps.heapBudget[heapIndex];</div>
+<div class="line"><a name="l16940"></a><span class="lineno">16940</span>&#160;            m_Budget.m_BlockBytesAtBudgetFetch[heapIndex] = m_Budget.m_BlockBytes[heapIndex].load();</div>
+<div class="line"><a name="l16941"></a><span class="lineno">16941</span>&#160; </div>
+<div class="line"><a name="l16942"></a><span class="lineno">16942</span>&#160;            <span class="comment">// Some bugged drivers return the budget incorrectly, e.g. 0 or much bigger than heap size.</span></div>
+<div class="line"><a name="l16943"></a><span class="lineno">16943</span>&#160;            <span class="keywordflow">if</span>(m_Budget.m_VulkanBudget[heapIndex] == 0)</div>
+<div class="line"><a name="l16944"></a><span class="lineno">16944</span>&#160;            {</div>
+<div class="line"><a name="l16945"></a><span class="lineno">16945</span>&#160;                m_Budget.m_VulkanBudget[heapIndex] = m_MemProps.memoryHeaps[heapIndex].size * 8 / 10; <span class="comment">// 80% heuristics.</span></div>
+<div class="line"><a name="l16946"></a><span class="lineno">16946</span>&#160;            }</div>
+<div class="line"><a name="l16947"></a><span class="lineno">16947</span>&#160;            <span class="keywordflow">else</span> <span class="keywordflow">if</span>(m_Budget.m_VulkanBudget[heapIndex] &gt; m_MemProps.memoryHeaps[heapIndex].size)</div>
+<div class="line"><a name="l16948"></a><span class="lineno">16948</span>&#160;            {</div>
+<div class="line"><a name="l16949"></a><span class="lineno">16949</span>&#160;                m_Budget.m_VulkanBudget[heapIndex] = m_MemProps.memoryHeaps[heapIndex].size;</div>
+<div class="line"><a name="l16950"></a><span class="lineno">16950</span>&#160;            }</div>
+<div class="line"><a name="l16951"></a><span class="lineno">16951</span>&#160;            <span class="keywordflow">if</span>(m_Budget.m_VulkanUsage[heapIndex] == 0 &amp;&amp; m_Budget.m_BlockBytesAtBudgetFetch[heapIndex] &gt; 0)</div>
+<div class="line"><a name="l16952"></a><span class="lineno">16952</span>&#160;            {</div>
+<div class="line"><a name="l16953"></a><span class="lineno">16953</span>&#160;                m_Budget.m_VulkanUsage[heapIndex] = m_Budget.m_BlockBytesAtBudgetFetch[heapIndex];</div>
+<div class="line"><a name="l16954"></a><span class="lineno">16954</span>&#160;            }</div>
+<div class="line"><a name="l16955"></a><span class="lineno">16955</span>&#160;        }</div>
+<div class="line"><a name="l16956"></a><span class="lineno">16956</span>&#160;        m_Budget.m_OperationsSinceBudgetFetch = 0;</div>
+<div class="line"><a name="l16957"></a><span class="lineno">16957</span>&#160;    }</div>
+<div class="line"><a name="l16958"></a><span class="lineno">16958</span>&#160;}</div>
+<div class="line"><a name="l16959"></a><span class="lineno">16959</span>&#160; </div>
+<div class="line"><a name="l16960"></a><span class="lineno">16960</span>&#160;<span class="preprocessor">#endif // #if VMA_MEMORY_BUDGET</span></div>
+<div class="line"><a name="l16961"></a><span class="lineno">16961</span>&#160; </div>
+<div class="line"><a name="l16962"></a><span class="lineno">16962</span>&#160;<span class="keywordtype">void</span> VmaAllocator_T::FillAllocation(<span class="keyword">const</span> <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAllocation, uint8_t pattern)</div>
+<div class="line"><a name="l16963"></a><span class="lineno">16963</span>&#160;{</div>
+<div class="line"><a name="l16964"></a><span class="lineno">16964</span>&#160;    <span class="keywordflow">if</span>(VMA_DEBUG_INITIALIZE_ALLOCATIONS &amp;&amp;</div>
+<div class="line"><a name="l16965"></a><span class="lineno">16965</span>&#160;        !hAllocation-&gt;CanBecomeLost() &amp;&amp;</div>
+<div class="line"><a name="l16966"></a><span class="lineno">16966</span>&#160;        (m_MemProps.memoryTypes[hAllocation-&gt;GetMemoryTypeIndex()].propertyFlags &amp; VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0)</div>
+<div class="line"><a name="l16967"></a><span class="lineno">16967</span>&#160;    {</div>
+<div class="line"><a name="l16968"></a><span class="lineno">16968</span>&#160;        <span class="keywordtype">void</span>* pData = VMA_NULL;</div>
+<div class="line"><a name="l16969"></a><span class="lineno">16969</span>&#160;        VkResult res = Map(hAllocation, &amp;pData);</div>
+<div class="line"><a name="l16970"></a><span class="lineno">16970</span>&#160;        <span class="keywordflow">if</span>(res == VK_SUCCESS)</div>
+<div class="line"><a name="l16971"></a><span class="lineno">16971</span>&#160;        {</div>
+<div class="line"><a name="l16972"></a><span class="lineno">16972</span>&#160;            memset(pData, (<span class="keywordtype">int</span>)pattern, (<span class="keywordtype">size_t</span>)hAllocation-&gt;GetSize());</div>
+<div class="line"><a name="l16973"></a><span class="lineno">16973</span>&#160;            FlushOrInvalidateAllocation(hAllocation, 0, VK_WHOLE_SIZE, VMA_CACHE_FLUSH);</div>
+<div class="line"><a name="l16974"></a><span class="lineno">16974</span>&#160;            Unmap(hAllocation);</div>
+<div class="line"><a name="l16975"></a><span class="lineno">16975</span>&#160;        }</div>
+<div class="line"><a name="l16976"></a><span class="lineno">16976</span>&#160;        <span class="keywordflow">else</span></div>
+<div class="line"><a name="l16977"></a><span class="lineno">16977</span>&#160;        {</div>
+<div class="line"><a name="l16978"></a><span class="lineno">16978</span>&#160;            VMA_ASSERT(0 &amp;&amp; <span class="stringliteral">&quot;VMA_DEBUG_INITIALIZE_ALLOCATIONS is enabled, but couldn&#39;t map memory to fill allocation.&quot;</span>);</div>
+<div class="line"><a name="l16979"></a><span class="lineno">16979</span>&#160;        }</div>
+<div class="line"><a name="l16980"></a><span class="lineno">16980</span>&#160;    }</div>
+<div class="line"><a name="l16981"></a><span class="lineno">16981</span>&#160;}</div>
+<div class="line"><a name="l16982"></a><span class="lineno">16982</span>&#160; </div>
+<div class="line"><a name="l16983"></a><span class="lineno">16983</span>&#160;uint32_t VmaAllocator_T::GetGpuDefragmentationMemoryTypeBits()</div>
+<div class="line"><a name="l16984"></a><span class="lineno">16984</span>&#160;{</div>
+<div class="line"><a name="l16985"></a><span class="lineno">16985</span>&#160;    uint32_t memoryTypeBits = m_GpuDefragmentationMemoryTypeBits.load();</div>
+<div class="line"><a name="l16986"></a><span class="lineno">16986</span>&#160;    <span class="keywordflow">if</span>(memoryTypeBits == UINT32_MAX)</div>
+<div class="line"><a name="l16987"></a><span class="lineno">16987</span>&#160;    {</div>
+<div class="line"><a name="l16988"></a><span class="lineno">16988</span>&#160;        memoryTypeBits = CalculateGpuDefragmentationMemoryTypeBits();</div>
+<div class="line"><a name="l16989"></a><span class="lineno">16989</span>&#160;        m_GpuDefragmentationMemoryTypeBits.store(memoryTypeBits);</div>
+<div class="line"><a name="l16990"></a><span class="lineno">16990</span>&#160;    }</div>
+<div class="line"><a name="l16991"></a><span class="lineno">16991</span>&#160;    <span class="keywordflow">return</span> memoryTypeBits;</div>
+<div class="line"><a name="l16992"></a><span class="lineno">16992</span>&#160;}</div>
+<div class="line"><a name="l16993"></a><span class="lineno">16993</span>&#160; </div>
+<div class="line"><a name="l16994"></a><span class="lineno">16994</span>&#160;<span class="preprocessor">#if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l16995"></a><span class="lineno">16995</span>&#160; </div>
+<div class="line"><a name="l16996"></a><span class="lineno">16996</span>&#160;<span class="keywordtype">void</span> VmaAllocator_T::PrintDetailedMap(VmaJsonWriter&amp; json)</div>
+<div class="line"><a name="l16997"></a><span class="lineno">16997</span>&#160;{</div>
+<div class="line"><a name="l16998"></a><span class="lineno">16998</span>&#160;    <span class="keywordtype">bool</span> dedicatedAllocationsStarted = <span class="keyword">false</span>;</div>
+<div class="line"><a name="l16999"></a><span class="lineno">16999</span>&#160;    <span class="keywordflow">for</span>(uint32_t memTypeIndex = 0; memTypeIndex &lt; GetMemoryTypeCount(); ++memTypeIndex)</div>
+<div class="line"><a name="l17000"></a><span class="lineno">17000</span>&#160;    {</div>
+<div class="line"><a name="l17001"></a><span class="lineno">17001</span>&#160;        VmaMutexLockRead dedicatedAllocationsLock(m_DedicatedAllocationsMutex[memTypeIndex], m_UseMutex);</div>
+<div class="line"><a name="l17002"></a><span class="lineno">17002</span>&#160;        AllocationVectorType* <span class="keyword">const</span> pDedicatedAllocVector = m_pDedicatedAllocations[memTypeIndex];</div>
+<div class="line"><a name="l17003"></a><span class="lineno">17003</span>&#160;        VMA_ASSERT(pDedicatedAllocVector);</div>
+<div class="line"><a name="l17004"></a><span class="lineno">17004</span>&#160;        <span class="keywordflow">if</span>(pDedicatedAllocVector-&gt;empty() == <span class="keyword">false</span>)</div>
+<div class="line"><a name="l17005"></a><span class="lineno">17005</span>&#160;        {</div>
+<div class="line"><a name="l17006"></a><span class="lineno">17006</span>&#160;            <span class="keywordflow">if</span>(dedicatedAllocationsStarted == <span class="keyword">false</span>)</div>
+<div class="line"><a name="l17007"></a><span class="lineno">17007</span>&#160;            {</div>
+<div class="line"><a name="l17008"></a><span class="lineno">17008</span>&#160;                dedicatedAllocationsStarted = <span class="keyword">true</span>;</div>
+<div class="line"><a name="l17009"></a><span class="lineno">17009</span>&#160;                json.WriteString(<span class="stringliteral">&quot;DedicatedAllocations&quot;</span>);</div>
+<div class="line"><a name="l17010"></a><span class="lineno">17010</span>&#160;                json.BeginObject();</div>
+<div class="line"><a name="l17011"></a><span class="lineno">17011</span>&#160;            }</div>
+<div class="line"><a name="l17012"></a><span class="lineno">17012</span>&#160; </div>
+<div class="line"><a name="l17013"></a><span class="lineno">17013</span>&#160;            json.BeginString(<span class="stringliteral">&quot;Type &quot;</span>);</div>
+<div class="line"><a name="l17014"></a><span class="lineno">17014</span>&#160;            json.ContinueString(memTypeIndex);</div>
+<div class="line"><a name="l17015"></a><span class="lineno">17015</span>&#160;            json.EndString();</div>
+<div class="line"><a name="l17016"></a><span class="lineno">17016</span>&#160;                </div>
+<div class="line"><a name="l17017"></a><span class="lineno">17017</span>&#160;            json.BeginArray();</div>
+<div class="line"><a name="l17018"></a><span class="lineno">17018</span>&#160; </div>
+<div class="line"><a name="l17019"></a><span class="lineno">17019</span>&#160;            <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = 0; i &lt; pDedicatedAllocVector-&gt;size(); ++i)</div>
+<div class="line"><a name="l17020"></a><span class="lineno">17020</span>&#160;            {</div>
+<div class="line"><a name="l17021"></a><span class="lineno">17021</span>&#160;                json.BeginObject(<span class="keyword">true</span>);</div>
+<div class="line"><a name="l17022"></a><span class="lineno">17022</span>&#160;                <span class="keyword">const</span> <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> hAlloc = (*pDedicatedAllocVector)[i];</div>
+<div class="line"><a name="l17023"></a><span class="lineno">17023</span>&#160;                hAlloc-&gt;PrintParameters(json);</div>
+<div class="line"><a name="l17024"></a><span class="lineno">17024</span>&#160;                json.EndObject();</div>
+<div class="line"><a name="l17025"></a><span class="lineno">17025</span>&#160;            }</div>
+<div class="line"><a name="l17026"></a><span class="lineno">17026</span>&#160; </div>
+<div class="line"><a name="l17027"></a><span class="lineno">17027</span>&#160;            json.EndArray();</div>
+<div class="line"><a name="l17028"></a><span class="lineno">17028</span>&#160;        }</div>
+<div class="line"><a name="l17029"></a><span class="lineno">17029</span>&#160;    }</div>
+<div class="line"><a name="l17030"></a><span class="lineno">17030</span>&#160;    <span class="keywordflow">if</span>(dedicatedAllocationsStarted)</div>
+<div class="line"><a name="l17031"></a><span class="lineno">17031</span>&#160;    {</div>
+<div class="line"><a name="l17032"></a><span class="lineno">17032</span>&#160;        json.EndObject();</div>
+<div class="line"><a name="l17033"></a><span class="lineno">17033</span>&#160;    }</div>
+<div class="line"><a name="l17034"></a><span class="lineno">17034</span>&#160; </div>
+<div class="line"><a name="l17035"></a><span class="lineno">17035</span>&#160;    {</div>
+<div class="line"><a name="l17036"></a><span class="lineno">17036</span>&#160;        <span class="keywordtype">bool</span> allocationsStarted = <span class="keyword">false</span>;</div>
+<div class="line"><a name="l17037"></a><span class="lineno">17037</span>&#160;        <span class="keywordflow">for</span>(uint32_t memTypeIndex = 0; memTypeIndex &lt; GetMemoryTypeCount(); ++memTypeIndex)</div>
+<div class="line"><a name="l17038"></a><span class="lineno">17038</span>&#160;        {</div>
+<div class="line"><a name="l17039"></a><span class="lineno">17039</span>&#160;            <span class="keywordflow">if</span>(m_pBlockVectors[memTypeIndex]-&gt;IsEmpty() == <span class="keyword">false</span>)</div>
+<div class="line"><a name="l17040"></a><span class="lineno">17040</span>&#160;            {</div>
+<div class="line"><a name="l17041"></a><span class="lineno">17041</span>&#160;                <span class="keywordflow">if</span>(allocationsStarted == <span class="keyword">false</span>)</div>
+<div class="line"><a name="l17042"></a><span class="lineno">17042</span>&#160;                {</div>
+<div class="line"><a name="l17043"></a><span class="lineno">17043</span>&#160;                    allocationsStarted = <span class="keyword">true</span>;</div>
+<div class="line"><a name="l17044"></a><span class="lineno">17044</span>&#160;                    json.WriteString(<span class="stringliteral">&quot;DefaultPools&quot;</span>);</div>
+<div class="line"><a name="l17045"></a><span class="lineno">17045</span>&#160;                    json.BeginObject();</div>
+<div class="line"><a name="l17046"></a><span class="lineno">17046</span>&#160;                }</div>
+<div class="line"><a name="l17047"></a><span class="lineno">17047</span>&#160; </div>
+<div class="line"><a name="l17048"></a><span class="lineno">17048</span>&#160;                json.BeginString(<span class="stringliteral">&quot;Type &quot;</span>);</div>
+<div class="line"><a name="l17049"></a><span class="lineno">17049</span>&#160;                json.ContinueString(memTypeIndex);</div>
+<div class="line"><a name="l17050"></a><span class="lineno">17050</span>&#160;                json.EndString();</div>
+<div class="line"><a name="l17051"></a><span class="lineno">17051</span>&#160; </div>
+<div class="line"><a name="l17052"></a><span class="lineno">17052</span>&#160;                m_pBlockVectors[memTypeIndex]-&gt;PrintDetailedMap(json);</div>
+<div class="line"><a name="l17053"></a><span class="lineno">17053</span>&#160;            }</div>
+<div class="line"><a name="l17054"></a><span class="lineno">17054</span>&#160;        }</div>
+<div class="line"><a name="l17055"></a><span class="lineno">17055</span>&#160;        <span class="keywordflow">if</span>(allocationsStarted)</div>
+<div class="line"><a name="l17056"></a><span class="lineno">17056</span>&#160;        {</div>
+<div class="line"><a name="l17057"></a><span class="lineno">17057</span>&#160;            json.EndObject();</div>
+<div class="line"><a name="l17058"></a><span class="lineno">17058</span>&#160;        }</div>
+<div class="line"><a name="l17059"></a><span class="lineno">17059</span>&#160;    }</div>
+<div class="line"><a name="l17060"></a><span class="lineno">17060</span>&#160; </div>
+<div class="line"><a name="l17061"></a><span class="lineno">17061</span>&#160;    <span class="comment">// Custom pools</span></div>
+<div class="line"><a name="l17062"></a><span class="lineno">17062</span>&#160;    {</div>
+<div class="line"><a name="l17063"></a><span class="lineno">17063</span>&#160;        VmaMutexLockRead lock(m_PoolsMutex, m_UseMutex);</div>
+<div class="line"><a name="l17064"></a><span class="lineno">17064</span>&#160;        <span class="keyword">const</span> <span class="keywordtype">size_t</span> poolCount = m_Pools.size();</div>
+<div class="line"><a name="l17065"></a><span class="lineno">17065</span>&#160;        <span class="keywordflow">if</span>(poolCount &gt; 0)</div>
+<div class="line"><a name="l17066"></a><span class="lineno">17066</span>&#160;        {</div>
+<div class="line"><a name="l17067"></a><span class="lineno">17067</span>&#160;            json.WriteString(<span class="stringliteral">&quot;Pools&quot;</span>);</div>
+<div class="line"><a name="l17068"></a><span class="lineno">17068</span>&#160;            json.BeginObject();</div>
+<div class="line"><a name="l17069"></a><span class="lineno">17069</span>&#160;            <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> poolIndex = 0; poolIndex &lt; poolCount; ++poolIndex)</div>
+<div class="line"><a name="l17070"></a><span class="lineno">17070</span>&#160;            {</div>
+<div class="line"><a name="l17071"></a><span class="lineno">17071</span>&#160;                json.BeginString();</div>
+<div class="line"><a name="l17072"></a><span class="lineno">17072</span>&#160;                json.ContinueString(m_Pools[poolIndex]-&gt;GetId());</div>
+<div class="line"><a name="l17073"></a><span class="lineno">17073</span>&#160;                json.EndString();</div>
+<div class="line"><a name="l17074"></a><span class="lineno">17074</span>&#160; </div>
+<div class="line"><a name="l17075"></a><span class="lineno">17075</span>&#160;                m_Pools[poolIndex]-&gt;m_BlockVector.PrintDetailedMap(json);</div>
+<div class="line"><a name="l17076"></a><span class="lineno">17076</span>&#160;            }</div>
+<div class="line"><a name="l17077"></a><span class="lineno">17077</span>&#160;            json.EndObject();</div>
+<div class="line"><a name="l17078"></a><span class="lineno">17078</span>&#160;        }</div>
+<div class="line"><a name="l17079"></a><span class="lineno">17079</span>&#160;    }</div>
+<div class="line"><a name="l17080"></a><span class="lineno">17080</span>&#160;}</div>
+<div class="line"><a name="l17081"></a><span class="lineno">17081</span>&#160; </div>
+<div class="line"><a name="l17082"></a><span class="lineno">17082</span>&#160;<span class="preprocessor">#endif // #if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l17083"></a><span class="lineno">17083</span>&#160; </div>
+<div class="line"><a name="l17085"></a><span class="lineno">17085</span>&#160;<span class="comment">// Public interface</span></div>
+<div class="line"><a name="l17086"></a><span class="lineno">17086</span>&#160; </div>
+<div class="line"><a name="l17087"></a><span class="lineno">17087</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a200692051ddb34240248234f5f4c17bb">vmaCreateAllocator</a>(</div>
+<div class="line"><a name="l17088"></a><span class="lineno">17088</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a>* pCreateInfo,</div>
+<div class="line"><a name="l17089"></a><span class="lineno">17089</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a>* pAllocator)</div>
+<div class="line"><a name="l17090"></a><span class="lineno">17090</span>&#160;{</div>
+<div class="line"><a name="l17091"></a><span class="lineno">17091</span>&#160;    VMA_ASSERT(pCreateInfo &amp;&amp; pAllocator);</div>
+<div class="line"><a name="l17092"></a><span class="lineno">17092</span>&#160;    VMA_ASSERT(pCreateInfo-&gt;<a class="code" href="struct_vma_allocator_create_info.html#ae0ffc55139b54520a6bb704b29ffc285">vulkanApiVersion</a> == 0 ||</div>
+<div class="line"><a name="l17093"></a><span class="lineno">17093</span>&#160;        (VK_VERSION_MAJOR(pCreateInfo-&gt;<a class="code" href="struct_vma_allocator_create_info.html#ae0ffc55139b54520a6bb704b29ffc285">vulkanApiVersion</a>) == 1 &amp;&amp; VK_VERSION_MINOR(pCreateInfo-&gt;<a class="code" href="struct_vma_allocator_create_info.html#ae0ffc55139b54520a6bb704b29ffc285">vulkanApiVersion</a>) &lt;= 2));</div>
+<div class="line"><a name="l17094"></a><span class="lineno">17094</span>&#160;    VMA_DEBUG_LOG(<span class="stringliteral">&quot;vmaCreateAllocator&quot;</span>);</div>
+<div class="line"><a name="l17095"></a><span class="lineno">17095</span>&#160;    *pAllocator = vma_new(pCreateInfo-&gt;<a class="code" href="struct_vma_allocator_create_info.html#a6e409087e3be55400d0e4ccbe43c608d">pAllocationCallbacks</a>, VmaAllocator_T)(pCreateInfo);</div>
+<div class="line"><a name="l17096"></a><span class="lineno">17096</span>&#160;    <span class="keywordflow">return</span> (*pAllocator)-&gt;Init(pCreateInfo);</div>
+<div class="line"><a name="l17097"></a><span class="lineno">17097</span>&#160;}</div>
+<div class="line"><a name="l17098"></a><span class="lineno">17098</span>&#160; </div>
+<div class="line"><a name="l17099"></a><span class="lineno">17099</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#aa8d164061c88f22fb1fd3c8f3534bc1d">vmaDestroyAllocator</a>(</div>
+<div class="line"><a name="l17100"></a><span class="lineno">17100</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator)</div>
+<div class="line"><a name="l17101"></a><span class="lineno">17101</span>&#160;{</div>
+<div class="line"><a name="l17102"></a><span class="lineno">17102</span>&#160;    <span class="keywordflow">if</span>(allocator != VK_NULL_HANDLE)</div>
+<div class="line"><a name="l17103"></a><span class="lineno">17103</span>&#160;    {</div>
+<div class="line"><a name="l17104"></a><span class="lineno">17104</span>&#160;        VMA_DEBUG_LOG(<span class="stringliteral">&quot;vmaDestroyAllocator&quot;</span>);</div>
+<div class="line"><a name="l17105"></a><span class="lineno">17105</span>&#160;        VkAllocationCallbacks allocationCallbacks = allocator-&gt;m_AllocationCallbacks;</div>
+<div class="line"><a name="l17106"></a><span class="lineno">17106</span>&#160;        vma_delete(&amp;allocationCallbacks, allocator);</div>
+<div class="line"><a name="l17107"></a><span class="lineno">17107</span>&#160;    }</div>
+<div class="line"><a name="l17108"></a><span class="lineno">17108</span>&#160;}</div>
+<div class="line"><a name="l17109"></a><span class="lineno">17109</span>&#160; </div>
+<div class="line"><a name="l17110"></a><span class="lineno">17110</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#afa02231a791b37255720d566a52683e7">vmaGetAllocatorInfo</a>(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator, <a class="code" href="struct_vma_allocator_info.html">VmaAllocatorInfo</a>* pAllocatorInfo)</div>
+<div class="line"><a name="l17111"></a><span class="lineno">17111</span>&#160;{</div>
+<div class="line"><a name="l17112"></a><span class="lineno">17112</span>&#160;    VMA_ASSERT(allocator &amp;&amp; pAllocatorInfo);</div>
+<div class="line"><a name="l17113"></a><span class="lineno">17113</span>&#160;    pAllocatorInfo-&gt;<a class="code" href="struct_vma_allocator_info.html#a2ed6a4d2d3fea039d66a13f15d0ce5fe">instance</a> = allocator-&gt;m_hInstance;</div>
+<div class="line"><a name="l17114"></a><span class="lineno">17114</span>&#160;    pAllocatorInfo-&gt;<a class="code" href="struct_vma_allocator_info.html#aba2b703f96e51d567717e1fb2935b47a">physicalDevice</a> = allocator-&gt;GetPhysicalDevice();</div>
+<div class="line"><a name="l17115"></a><span class="lineno">17115</span>&#160;    pAllocatorInfo-&gt;<a class="code" href="struct_vma_allocator_info.html#a012b4c485bf3b0ea8921352c5ee0c357">device</a> = allocator-&gt;m_hDevice;</div>
+<div class="line"><a name="l17116"></a><span class="lineno">17116</span>&#160;}</div>
+<div class="line"><a name="l17117"></a><span class="lineno">17117</span>&#160; </div>
+<div class="line"><a name="l17118"></a><span class="lineno">17118</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#aecabf7b6e91ea87d0316fa0a9e014fe0">vmaGetPhysicalDeviceProperties</a>(</div>
+<div class="line"><a name="l17119"></a><span class="lineno">17119</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l17120"></a><span class="lineno">17120</span>&#160;    <span class="keyword">const</span> VkPhysicalDeviceProperties **ppPhysicalDeviceProperties)</div>
+<div class="line"><a name="l17121"></a><span class="lineno">17121</span>&#160;{</div>
+<div class="line"><a name="l17122"></a><span class="lineno">17122</span>&#160;    VMA_ASSERT(allocator &amp;&amp; ppPhysicalDeviceProperties);</div>
+<div class="line"><a name="l17123"></a><span class="lineno">17123</span>&#160;    *ppPhysicalDeviceProperties = &amp;allocator-&gt;m_PhysicalDeviceProperties;</div>
+<div class="line"><a name="l17124"></a><span class="lineno">17124</span>&#160;}</div>
+<div class="line"><a name="l17125"></a><span class="lineno">17125</span>&#160; </div>
+<div class="line"><a name="l17126"></a><span class="lineno">17126</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#ab88db292a17974f911182543fda52d19">vmaGetMemoryProperties</a>(</div>
+<div class="line"><a name="l17127"></a><span class="lineno">17127</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l17128"></a><span class="lineno">17128</span>&#160;    <span class="keyword">const</span> VkPhysicalDeviceMemoryProperties** ppPhysicalDeviceMemoryProperties)</div>
+<div class="line"><a name="l17129"></a><span class="lineno">17129</span>&#160;{</div>
+<div class="line"><a name="l17130"></a><span class="lineno">17130</span>&#160;    VMA_ASSERT(allocator &amp;&amp; ppPhysicalDeviceMemoryProperties);</div>
+<div class="line"><a name="l17131"></a><span class="lineno">17131</span>&#160;    *ppPhysicalDeviceMemoryProperties = &amp;allocator-&gt;m_MemProps;</div>
+<div class="line"><a name="l17132"></a><span class="lineno">17132</span>&#160;}</div>
+<div class="line"><a name="l17133"></a><span class="lineno">17133</span>&#160; </div>
+<div class="line"><a name="l17134"></a><span class="lineno">17134</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a8701444752eb5de4464adb5a2b514bca">vmaGetMemoryTypeProperties</a>(</div>
+<div class="line"><a name="l17135"></a><span class="lineno">17135</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l17136"></a><span class="lineno">17136</span>&#160;    uint32_t memoryTypeIndex,</div>
+<div class="line"><a name="l17137"></a><span class="lineno">17137</span>&#160;    VkMemoryPropertyFlags* pFlags)</div>
+<div class="line"><a name="l17138"></a><span class="lineno">17138</span>&#160;{</div>
+<div class="line"><a name="l17139"></a><span class="lineno">17139</span>&#160;    VMA_ASSERT(allocator &amp;&amp; pFlags);</div>
+<div class="line"><a name="l17140"></a><span class="lineno">17140</span>&#160;    VMA_ASSERT(memoryTypeIndex &lt; allocator-&gt;GetMemoryTypeCount());</div>
+<div class="line"><a name="l17141"></a><span class="lineno">17141</span>&#160;    *pFlags = allocator-&gt;m_MemProps.memoryTypes[memoryTypeIndex].propertyFlags;</div>
+<div class="line"><a name="l17142"></a><span class="lineno">17142</span>&#160;}</div>
+<div class="line"><a name="l17143"></a><span class="lineno">17143</span>&#160; </div>
+<div class="line"><a name="l17144"></a><span class="lineno">17144</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#ade56bf8dc9f5a5eaddf5f119ed525236">vmaSetCurrentFrameIndex</a>(</div>
+<div class="line"><a name="l17145"></a><span class="lineno">17145</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l17146"></a><span class="lineno">17146</span>&#160;    uint32_t frameIndex)</div>
+<div class="line"><a name="l17147"></a><span class="lineno">17147</span>&#160;{</div>
+<div class="line"><a name="l17148"></a><span class="lineno">17148</span>&#160;    VMA_ASSERT(allocator);</div>
+<div class="line"><a name="l17149"></a><span class="lineno">17149</span>&#160;    VMA_ASSERT(frameIndex != VMA_FRAME_INDEX_LOST);</div>
+<div class="line"><a name="l17150"></a><span class="lineno">17150</span>&#160; </div>
+<div class="line"><a name="l17151"></a><span class="lineno">17151</span>&#160;    VMA_DEBUG_GLOBAL_MUTEX_LOCK</div>
+<div class="line"><a name="l17152"></a><span class="lineno">17152</span>&#160; </div>
+<div class="line"><a name="l17153"></a><span class="lineno">17153</span>&#160;    allocator-&gt;SetCurrentFrameIndex(frameIndex);</div>
+<div class="line"><a name="l17154"></a><span class="lineno">17154</span>&#160;}</div>
+<div class="line"><a name="l17155"></a><span class="lineno">17155</span>&#160; </div>
+<div class="line"><a name="l17156"></a><span class="lineno">17156</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a333b61c1788cb23559177531e6a93ca3">vmaCalculateStats</a>(</div>
+<div class="line"><a name="l17157"></a><span class="lineno">17157</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l17158"></a><span class="lineno">17158</span>&#160;    <a class="code" href="struct_vma_stats.html">VmaStats</a>* pStats)</div>
+<div class="line"><a name="l17159"></a><span class="lineno">17159</span>&#160;{</div>
+<div class="line"><a name="l17160"></a><span class="lineno">17160</span>&#160;    VMA_ASSERT(allocator &amp;&amp; pStats);</div>
+<div class="line"><a name="l17161"></a><span class="lineno">17161</span>&#160;    VMA_DEBUG_GLOBAL_MUTEX_LOCK</div>
+<div class="line"><a name="l17162"></a><span class="lineno">17162</span>&#160;    allocator-&gt;CalculateStats(pStats);</div>
+<div class="line"><a name="l17163"></a><span class="lineno">17163</span>&#160;}</div>
+<div class="line"><a name="l17164"></a><span class="lineno">17164</span>&#160; </div>
+<div class="line"><a name="l17165"></a><span class="lineno">17165</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#aec0ed24ebea2d0099eed5f801daaefba">vmaGetBudget</a>(</div>
+<div class="line"><a name="l17166"></a><span class="lineno">17166</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l17167"></a><span class="lineno">17167</span>&#160;    <a class="code" href="struct_vma_budget.html">VmaBudget</a>* pBudget)</div>
+<div class="line"><a name="l17168"></a><span class="lineno">17168</span>&#160;{</div>
+<div class="line"><a name="l17169"></a><span class="lineno">17169</span>&#160;    VMA_ASSERT(allocator &amp;&amp; pBudget);</div>
+<div class="line"><a name="l17170"></a><span class="lineno">17170</span>&#160;    VMA_DEBUG_GLOBAL_MUTEX_LOCK</div>
+<div class="line"><a name="l17171"></a><span class="lineno">17171</span>&#160;    allocator-&gt;GetBudget(pBudget, 0, allocator-&gt;GetMemoryHeapCount());</div>
+<div class="line"><a name="l17172"></a><span class="lineno">17172</span>&#160;}</div>
+<div class="line"><a name="l17173"></a><span class="lineno">17173</span>&#160; </div>
+<div class="line"><a name="l17174"></a><span class="lineno">17174</span>&#160;<span class="preprocessor">#if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l17175"></a><span class="lineno">17175</span>&#160; </div>
+<div class="line"><a name="l17176"></a><span class="lineno">17176</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#aa4fee7eb5253377599ef4fd38c93c2a0">vmaBuildStatsString</a>(</div>
+<div class="line"><a name="l17177"></a><span class="lineno">17177</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l17178"></a><span class="lineno">17178</span>&#160;    <span class="keywordtype">char</span>** ppStatsString,</div>
+<div class="line"><a name="l17179"></a><span class="lineno">17179</span>&#160;    VkBool32 detailedMap)</div>
+<div class="line"><a name="l17180"></a><span class="lineno">17180</span>&#160;{</div>
+<div class="line"><a name="l17181"></a><span class="lineno">17181</span>&#160;    VMA_ASSERT(allocator &amp;&amp; ppStatsString);</div>
+<div class="line"><a name="l17182"></a><span class="lineno">17182</span>&#160;    VMA_DEBUG_GLOBAL_MUTEX_LOCK</div>
+<div class="line"><a name="l17183"></a><span class="lineno">17183</span>&#160; </div>
+<div class="line"><a name="l17184"></a><span class="lineno">17184</span>&#160;    VmaStringBuilder sb(allocator);</div>
+<div class="line"><a name="l17185"></a><span class="lineno">17185</span>&#160;    {</div>
+<div class="line"><a name="l17186"></a><span class="lineno">17186</span>&#160;        VmaJsonWriter json(allocator-&gt;GetAllocationCallbacks(), sb);</div>
+<div class="line"><a name="l17187"></a><span class="lineno">17187</span>&#160;        json.BeginObject();</div>
+<div class="line"><a name="l17188"></a><span class="lineno">17188</span>&#160; </div>
+<div class="line"><a name="l17189"></a><span class="lineno">17189</span>&#160;        <a class="code" href="struct_vma_budget.html">VmaBudget</a> budget[VK_MAX_MEMORY_HEAPS];</div>
+<div class="line"><a name="l17190"></a><span class="lineno">17190</span>&#160;        allocator-&gt;GetBudget(budget, 0, allocator-&gt;GetMemoryHeapCount());</div>
+<div class="line"><a name="l17191"></a><span class="lineno">17191</span>&#160; </div>
+<div class="line"><a name="l17192"></a><span class="lineno">17192</span>&#160;        <a class="code" href="struct_vma_stats.html">VmaStats</a> stats;</div>
+<div class="line"><a name="l17193"></a><span class="lineno">17193</span>&#160;        allocator-&gt;CalculateStats(&amp;stats);</div>
+<div class="line"><a name="l17194"></a><span class="lineno">17194</span>&#160; </div>
+<div class="line"><a name="l17195"></a><span class="lineno">17195</span>&#160;        json.WriteString(<span class="stringliteral">&quot;Total&quot;</span>);</div>
+<div class="line"><a name="l17196"></a><span class="lineno">17196</span>&#160;        VmaPrintStatInfo(json, stats.<a class="code" href="struct_vma_stats.html#a2e8f5b3353f2fefef3c27f29e245a1f9">total</a>);</div>
+<div class="line"><a name="l17197"></a><span class="lineno">17197</span>&#160;    </div>
+<div class="line"><a name="l17198"></a><span class="lineno">17198</span>&#160;        <span class="keywordflow">for</span>(uint32_t heapIndex = 0; heapIndex &lt; allocator-&gt;GetMemoryHeapCount(); ++heapIndex)</div>
+<div class="line"><a name="l17199"></a><span class="lineno">17199</span>&#160;        {</div>
+<div class="line"><a name="l17200"></a><span class="lineno">17200</span>&#160;            json.BeginString(<span class="stringliteral">&quot;Heap &quot;</span>);</div>
+<div class="line"><a name="l17201"></a><span class="lineno">17201</span>&#160;            json.ContinueString(heapIndex);</div>
+<div class="line"><a name="l17202"></a><span class="lineno">17202</span>&#160;            json.EndString();</div>
+<div class="line"><a name="l17203"></a><span class="lineno">17203</span>&#160;            json.BeginObject();</div>
+<div class="line"><a name="l17204"></a><span class="lineno">17204</span>&#160; </div>
+<div class="line"><a name="l17205"></a><span class="lineno">17205</span>&#160;            json.WriteString(<span class="stringliteral">&quot;Size&quot;</span>);</div>
+<div class="line"><a name="l17206"></a><span class="lineno">17206</span>&#160;            json.WriteNumber(allocator-&gt;m_MemProps.memoryHeaps[heapIndex].size);</div>
+<div class="line"><a name="l17207"></a><span class="lineno">17207</span>&#160; </div>
+<div class="line"><a name="l17208"></a><span class="lineno">17208</span>&#160;            json.WriteString(<span class="stringliteral">&quot;Flags&quot;</span>);</div>
+<div class="line"><a name="l17209"></a><span class="lineno">17209</span>&#160;            json.BeginArray(<span class="keyword">true</span>);</div>
+<div class="line"><a name="l17210"></a><span class="lineno">17210</span>&#160;            <span class="keywordflow">if</span>((allocator-&gt;m_MemProps.memoryHeaps[heapIndex].flags &amp; VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) != 0)</div>
+<div class="line"><a name="l17211"></a><span class="lineno">17211</span>&#160;            {</div>
+<div class="line"><a name="l17212"></a><span class="lineno">17212</span>&#160;                json.WriteString(<span class="stringliteral">&quot;DEVICE_LOCAL&quot;</span>);</div>
+<div class="line"><a name="l17213"></a><span class="lineno">17213</span>&#160;            }</div>
+<div class="line"><a name="l17214"></a><span class="lineno">17214</span>&#160;            json.EndArray();</div>
+<div class="line"><a name="l17215"></a><span class="lineno">17215</span>&#160; </div>
+<div class="line"><a name="l17216"></a><span class="lineno">17216</span>&#160;            json.WriteString(<span class="stringliteral">&quot;Budget&quot;</span>);</div>
+<div class="line"><a name="l17217"></a><span class="lineno">17217</span>&#160;            json.BeginObject();</div>
+<div class="line"><a name="l17218"></a><span class="lineno">17218</span>&#160;            {</div>
+<div class="line"><a name="l17219"></a><span class="lineno">17219</span>&#160;                json.WriteString(<span class="stringliteral">&quot;BlockBytes&quot;</span>);</div>
+<div class="line"><a name="l17220"></a><span class="lineno">17220</span>&#160;                json.WriteNumber(budget[heapIndex].blockBytes);</div>
+<div class="line"><a name="l17221"></a><span class="lineno">17221</span>&#160;                json.WriteString(<span class="stringliteral">&quot;AllocationBytes&quot;</span>);</div>
+<div class="line"><a name="l17222"></a><span class="lineno">17222</span>&#160;                json.WriteNumber(budget[heapIndex].allocationBytes);</div>
+<div class="line"><a name="l17223"></a><span class="lineno">17223</span>&#160;                json.WriteString(<span class="stringliteral">&quot;Usage&quot;</span>);</div>
+<div class="line"><a name="l17224"></a><span class="lineno">17224</span>&#160;                json.WriteNumber(budget[heapIndex].usage);</div>
+<div class="line"><a name="l17225"></a><span class="lineno">17225</span>&#160;                json.WriteString(<span class="stringliteral">&quot;Budget&quot;</span>);</div>
+<div class="line"><a name="l17226"></a><span class="lineno">17226</span>&#160;                json.WriteNumber(budget[heapIndex].budget);</div>
+<div class="line"><a name="l17227"></a><span class="lineno">17227</span>&#160;            }</div>
+<div class="line"><a name="l17228"></a><span class="lineno">17228</span>&#160;            json.EndObject();</div>
+<div class="line"><a name="l17229"></a><span class="lineno">17229</span>&#160; </div>
+<div class="line"><a name="l17230"></a><span class="lineno">17230</span>&#160;            <span class="keywordflow">if</span>(stats.<a class="code" href="struct_vma_stats.html#a0e6611508c29a187f0fd14ff1a0329c0">memoryHeap</a>[heapIndex].<a class="code" href="struct_vma_stat_info.html#abc4bb7cd611900778464c56e50c970a4">blockCount</a> &gt; 0)</div>
+<div class="line"><a name="l17231"></a><span class="lineno">17231</span>&#160;            {</div>
+<div class="line"><a name="l17232"></a><span class="lineno">17232</span>&#160;                json.WriteString(<span class="stringliteral">&quot;Stats&quot;</span>);</div>
+<div class="line"><a name="l17233"></a><span class="lineno">17233</span>&#160;                VmaPrintStatInfo(json, stats.<a class="code" href="struct_vma_stats.html#a0e6611508c29a187f0fd14ff1a0329c0">memoryHeap</a>[heapIndex]);</div>
+<div class="line"><a name="l17234"></a><span class="lineno">17234</span>&#160;            }</div>
+<div class="line"><a name="l17235"></a><span class="lineno">17235</span>&#160; </div>
+<div class="line"><a name="l17236"></a><span class="lineno">17236</span>&#160;            <span class="keywordflow">for</span>(uint32_t typeIndex = 0; typeIndex &lt; allocator-&gt;GetMemoryTypeCount(); ++typeIndex)</div>
+<div class="line"><a name="l17237"></a><span class="lineno">17237</span>&#160;            {</div>
+<div class="line"><a name="l17238"></a><span class="lineno">17238</span>&#160;                <span class="keywordflow">if</span>(allocator-&gt;MemoryTypeIndexToHeapIndex(typeIndex) == heapIndex)</div>
+<div class="line"><a name="l17239"></a><span class="lineno">17239</span>&#160;                {</div>
+<div class="line"><a name="l17240"></a><span class="lineno">17240</span>&#160;                    json.BeginString(<span class="stringliteral">&quot;Type &quot;</span>);</div>
+<div class="line"><a name="l17241"></a><span class="lineno">17241</span>&#160;                    json.ContinueString(typeIndex);</div>
+<div class="line"><a name="l17242"></a><span class="lineno">17242</span>&#160;                    json.EndString();</div>
+<div class="line"><a name="l17243"></a><span class="lineno">17243</span>&#160; </div>
+<div class="line"><a name="l17244"></a><span class="lineno">17244</span>&#160;                    json.BeginObject();</div>
+<div class="line"><a name="l17245"></a><span class="lineno">17245</span>&#160; </div>
+<div class="line"><a name="l17246"></a><span class="lineno">17246</span>&#160;                    json.WriteString(<span class="stringliteral">&quot;Flags&quot;</span>);</div>
+<div class="line"><a name="l17247"></a><span class="lineno">17247</span>&#160;                    json.BeginArray(<span class="keyword">true</span>);</div>
+<div class="line"><a name="l17248"></a><span class="lineno">17248</span>&#160;                    VkMemoryPropertyFlags flags = allocator-&gt;m_MemProps.memoryTypes[typeIndex].propertyFlags;</div>
+<div class="line"><a name="l17249"></a><span class="lineno">17249</span>&#160;                    <span class="keywordflow">if</span>((flags &amp; VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) != 0)</div>
+<div class="line"><a name="l17250"></a><span class="lineno">17250</span>&#160;                    {</div>
+<div class="line"><a name="l17251"></a><span class="lineno">17251</span>&#160;                        json.WriteString(<span class="stringliteral">&quot;DEVICE_LOCAL&quot;</span>);</div>
+<div class="line"><a name="l17252"></a><span class="lineno">17252</span>&#160;                    }</div>
+<div class="line"><a name="l17253"></a><span class="lineno">17253</span>&#160;                    <span class="keywordflow">if</span>((flags &amp; VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0)</div>
+<div class="line"><a name="l17254"></a><span class="lineno">17254</span>&#160;                    {</div>
+<div class="line"><a name="l17255"></a><span class="lineno">17255</span>&#160;                        json.WriteString(<span class="stringliteral">&quot;HOST_VISIBLE&quot;</span>);</div>
+<div class="line"><a name="l17256"></a><span class="lineno">17256</span>&#160;                    }</div>
+<div class="line"><a name="l17257"></a><span class="lineno">17257</span>&#160;                    <span class="keywordflow">if</span>((flags &amp; VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) != 0)</div>
+<div class="line"><a name="l17258"></a><span class="lineno">17258</span>&#160;                    {</div>
+<div class="line"><a name="l17259"></a><span class="lineno">17259</span>&#160;                        json.WriteString(<span class="stringliteral">&quot;HOST_COHERENT&quot;</span>);</div>
+<div class="line"><a name="l17260"></a><span class="lineno">17260</span>&#160;                    }</div>
+<div class="line"><a name="l17261"></a><span class="lineno">17261</span>&#160;                    <span class="keywordflow">if</span>((flags &amp; VK_MEMORY_PROPERTY_HOST_CACHED_BIT) != 0)</div>
+<div class="line"><a name="l17262"></a><span class="lineno">17262</span>&#160;                    {</div>
+<div class="line"><a name="l17263"></a><span class="lineno">17263</span>&#160;                        json.WriteString(<span class="stringliteral">&quot;HOST_CACHED&quot;</span>);</div>
+<div class="line"><a name="l17264"></a><span class="lineno">17264</span>&#160;                    }</div>
+<div class="line"><a name="l17265"></a><span class="lineno">17265</span>&#160;                    <span class="keywordflow">if</span>((flags &amp; VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) != 0)</div>
+<div class="line"><a name="l17266"></a><span class="lineno">17266</span>&#160;                    {</div>
+<div class="line"><a name="l17267"></a><span class="lineno">17267</span>&#160;                        json.WriteString(<span class="stringliteral">&quot;LAZILY_ALLOCATED&quot;</span>);</div>
+<div class="line"><a name="l17268"></a><span class="lineno">17268</span>&#160;                    }</div>
+<div class="line"><a name="l17269"></a><span class="lineno">17269</span>&#160;                    <span class="keywordflow">if</span>((flags &amp; VK_MEMORY_PROPERTY_PROTECTED_BIT) != 0)</div>
+<div class="line"><a name="l17270"></a><span class="lineno">17270</span>&#160;                    {</div>
+<div class="line"><a name="l17271"></a><span class="lineno">17271</span>&#160;                        json.WriteString(<span class="stringliteral">&quot; PROTECTED&quot;</span>);</div>
+<div class="line"><a name="l17272"></a><span class="lineno">17272</span>&#160;                    }</div>
+<div class="line"><a name="l17273"></a><span class="lineno">17273</span>&#160;                    <span class="keywordflow">if</span>((flags &amp; VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD_COPY) != 0)</div>
+<div class="line"><a name="l17274"></a><span class="lineno">17274</span>&#160;                    {</div>
+<div class="line"><a name="l17275"></a><span class="lineno">17275</span>&#160;                        json.WriteString(<span class="stringliteral">&quot; DEVICE_COHERENT&quot;</span>);</div>
+<div class="line"><a name="l17276"></a><span class="lineno">17276</span>&#160;                    }</div>
+<div class="line"><a name="l17277"></a><span class="lineno">17277</span>&#160;                    <span class="keywordflow">if</span>((flags &amp; VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD_COPY) != 0)</div>
+<div class="line"><a name="l17278"></a><span class="lineno">17278</span>&#160;                    {</div>
+<div class="line"><a name="l17279"></a><span class="lineno">17279</span>&#160;                        json.WriteString(<span class="stringliteral">&quot; DEVICE_UNCACHED&quot;</span>);</div>
+<div class="line"><a name="l17280"></a><span class="lineno">17280</span>&#160;                    }</div>
+<div class="line"><a name="l17281"></a><span class="lineno">17281</span>&#160;                    json.EndArray();</div>
+<div class="line"><a name="l17282"></a><span class="lineno">17282</span>&#160; </div>
+<div class="line"><a name="l17283"></a><span class="lineno">17283</span>&#160;                    <span class="keywordflow">if</span>(stats.<a class="code" href="struct_vma_stats.html#a13e3caf754be79352c42408756309331">memoryType</a>[typeIndex].<a class="code" href="struct_vma_stat_info.html#abc4bb7cd611900778464c56e50c970a4">blockCount</a> &gt; 0)</div>
+<div class="line"><a name="l17284"></a><span class="lineno">17284</span>&#160;                    {</div>
+<div class="line"><a name="l17285"></a><span class="lineno">17285</span>&#160;                        json.WriteString(<span class="stringliteral">&quot;Stats&quot;</span>);</div>
+<div class="line"><a name="l17286"></a><span class="lineno">17286</span>&#160;                        VmaPrintStatInfo(json, stats.<a class="code" href="struct_vma_stats.html#a13e3caf754be79352c42408756309331">memoryType</a>[typeIndex]);</div>
+<div class="line"><a name="l17287"></a><span class="lineno">17287</span>&#160;                    }</div>
+<div class="line"><a name="l17288"></a><span class="lineno">17288</span>&#160; </div>
+<div class="line"><a name="l17289"></a><span class="lineno">17289</span>&#160;                    json.EndObject();</div>
+<div class="line"><a name="l17290"></a><span class="lineno">17290</span>&#160;                }</div>
+<div class="line"><a name="l17291"></a><span class="lineno">17291</span>&#160;            }</div>
+<div class="line"><a name="l17292"></a><span class="lineno">17292</span>&#160; </div>
+<div class="line"><a name="l17293"></a><span class="lineno">17293</span>&#160;            json.EndObject();</div>
+<div class="line"><a name="l17294"></a><span class="lineno">17294</span>&#160;        }</div>
+<div class="line"><a name="l17295"></a><span class="lineno">17295</span>&#160;        <span class="keywordflow">if</span>(detailedMap == VK_TRUE)</div>
+<div class="line"><a name="l17296"></a><span class="lineno">17296</span>&#160;        {</div>
+<div class="line"><a name="l17297"></a><span class="lineno">17297</span>&#160;            allocator-&gt;PrintDetailedMap(json);</div>
+<div class="line"><a name="l17298"></a><span class="lineno">17298</span>&#160;        }</div>
+<div class="line"><a name="l17299"></a><span class="lineno">17299</span>&#160; </div>
+<div class="line"><a name="l17300"></a><span class="lineno">17300</span>&#160;        json.EndObject();</div>
+<div class="line"><a name="l17301"></a><span class="lineno">17301</span>&#160;    }</div>
+<div class="line"><a name="l17302"></a><span class="lineno">17302</span>&#160; </div>
+<div class="line"><a name="l17303"></a><span class="lineno">17303</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">size_t</span> len = sb.GetLength();</div>
+<div class="line"><a name="l17304"></a><span class="lineno">17304</span>&#160;    <span class="keywordtype">char</span>* <span class="keyword">const</span> pChars = vma_new_array(allocator, <span class="keywordtype">char</span>, len + 1);</div>
+<div class="line"><a name="l17305"></a><span class="lineno">17305</span>&#160;    <span class="keywordflow">if</span>(len &gt; 0)</div>
+<div class="line"><a name="l17306"></a><span class="lineno">17306</span>&#160;    {</div>
+<div class="line"><a name="l17307"></a><span class="lineno">17307</span>&#160;        memcpy(pChars, sb.GetData(), len);</div>
+<div class="line"><a name="l17308"></a><span class="lineno">17308</span>&#160;    }</div>
+<div class="line"><a name="l17309"></a><span class="lineno">17309</span>&#160;    pChars[len] = <span class="charliteral">&#39;\0&#39;</span>;</div>
+<div class="line"><a name="l17310"></a><span class="lineno">17310</span>&#160;    *ppStatsString = pChars;</div>
+<div class="line"><a name="l17311"></a><span class="lineno">17311</span>&#160;}</div>
+<div class="line"><a name="l17312"></a><span class="lineno">17312</span>&#160; </div>
+<div class="line"><a name="l17313"></a><span class="lineno">17313</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a3104eb30d8122c84dd8541063f145288">vmaFreeStatsString</a>(</div>
+<div class="line"><a name="l17314"></a><span class="lineno">17314</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l17315"></a><span class="lineno">17315</span>&#160;    <span class="keywordtype">char</span>* pStatsString)</div>
+<div class="line"><a name="l17316"></a><span class="lineno">17316</span>&#160;{</div>
+<div class="line"><a name="l17317"></a><span class="lineno">17317</span>&#160;    <span class="keywordflow">if</span>(pStatsString != VMA_NULL)</div>
+<div class="line"><a name="l17318"></a><span class="lineno">17318</span>&#160;    {</div>
+<div class="line"><a name="l17319"></a><span class="lineno">17319</span>&#160;        VMA_ASSERT(allocator);</div>
+<div class="line"><a name="l17320"></a><span class="lineno">17320</span>&#160;        <span class="keywordtype">size_t</span> len = strlen(pStatsString);</div>
+<div class="line"><a name="l17321"></a><span class="lineno">17321</span>&#160;        vma_delete_array(allocator, pStatsString, len + 1);</div>
+<div class="line"><a name="l17322"></a><span class="lineno">17322</span>&#160;    }</div>
+<div class="line"><a name="l17323"></a><span class="lineno">17323</span>&#160;}</div>
+<div class="line"><a name="l17324"></a><span class="lineno">17324</span>&#160; </div>
+<div class="line"><a name="l17325"></a><span class="lineno">17325</span>&#160;<span class="preprocessor">#endif // #if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l17326"></a><span class="lineno">17326</span>&#160; </div>
+<div class="line"><a name="l17327"></a><span class="lineno">17327</span>&#160;<span class="comment">/*</span></div>
+<div class="line"><a name="l17328"></a><span class="lineno">17328</span>&#160;<span class="comment">This function is not protected by any mutex because it just reads immutable data.</span></div>
+<div class="line"><a name="l17329"></a><span class="lineno">17329</span>&#160;<span class="comment">*/</span></div>
+<div class="line"><a name="l17330"></a><span class="lineno">17330</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#aef15a94b58fbcb0fe706d5720e84a74a">vmaFindMemoryTypeIndex</a>(</div>
+<div class="line"><a name="l17331"></a><span class="lineno">17331</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l17332"></a><span class="lineno">17332</span>&#160;    uint32_t memoryTypeBits,</div>
+<div class="line"><a name="l17333"></a><span class="lineno">17333</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>* pAllocationCreateInfo,</div>
+<div class="line"><a name="l17334"></a><span class="lineno">17334</span>&#160;    uint32_t* pMemoryTypeIndex)</div>
+<div class="line"><a name="l17335"></a><span class="lineno">17335</span>&#160;{</div>
+<div class="line"><a name="l17336"></a><span class="lineno">17336</span>&#160;    VMA_ASSERT(allocator != VK_NULL_HANDLE);</div>
+<div class="line"><a name="l17337"></a><span class="lineno">17337</span>&#160;    VMA_ASSERT(pAllocationCreateInfo != VMA_NULL);</div>
+<div class="line"><a name="l17338"></a><span class="lineno">17338</span>&#160;    VMA_ASSERT(pMemoryTypeIndex != VMA_NULL);</div>
+<div class="line"><a name="l17339"></a><span class="lineno">17339</span>&#160; </div>
+<div class="line"><a name="l17340"></a><span class="lineno">17340</span>&#160;    memoryTypeBits &amp;= allocator-&gt;GetGlobalMemoryTypeBits();</div>
+<div class="line"><a name="l17341"></a><span class="lineno">17341</span>&#160; </div>
+<div class="line"><a name="l17342"></a><span class="lineno">17342</span>&#160;    <span class="keywordflow">if</span>(pAllocationCreateInfo-&gt;<a class="code" href="struct_vma_allocation_create_info.html#a3bf940c0271d85d6ba32a4d820075055">memoryTypeBits</a> != 0)</div>
+<div class="line"><a name="l17343"></a><span class="lineno">17343</span>&#160;    {</div>
+<div class="line"><a name="l17344"></a><span class="lineno">17344</span>&#160;        memoryTypeBits &amp;= pAllocationCreateInfo-&gt;<a class="code" href="struct_vma_allocation_create_info.html#a3bf940c0271d85d6ba32a4d820075055">memoryTypeBits</a>;</div>
+<div class="line"><a name="l17345"></a><span class="lineno">17345</span>&#160;    }</div>
+<div class="line"><a name="l17346"></a><span class="lineno">17346</span>&#160;    </div>
+<div class="line"><a name="l17347"></a><span class="lineno">17347</span>&#160;    uint32_t requiredFlags = pAllocationCreateInfo-&gt;<a class="code" href="struct_vma_allocation_create_info.html#a9166390303ff42d783305bc31c2b6b90">requiredFlags</a>;</div>
+<div class="line"><a name="l17348"></a><span class="lineno">17348</span>&#160;    uint32_t preferredFlags = pAllocationCreateInfo-&gt;<a class="code" href="struct_vma_allocation_create_info.html#a7fe8d81a1ad10b2a2faacacee5b15d6d">preferredFlags</a>;</div>
+<div class="line"><a name="l17349"></a><span class="lineno">17349</span>&#160;    uint32_t notPreferredFlags = 0;</div>
+<div class="line"><a name="l17350"></a><span class="lineno">17350</span>&#160; </div>
+<div class="line"><a name="l17351"></a><span class="lineno">17351</span>&#160;    <span class="comment">// Convert usage to requiredFlags and preferredFlags.</span></div>
+<div class="line"><a name="l17352"></a><span class="lineno">17352</span>&#160;    <span class="keywordflow">switch</span>(pAllocationCreateInfo-&gt;<a class="code" href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910">usage</a>)</div>
+<div class="line"><a name="l17353"></a><span class="lineno">17353</span>&#160;    {</div>
+<div class="line"><a name="l17354"></a><span class="lineno">17354</span>&#160;    <span class="keywordflow">case</span> <a class="code" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccaf50d27e34e0925cf3a63db8c839121dd">VMA_MEMORY_USAGE_UNKNOWN</a>:</div>
+<div class="line"><a name="l17355"></a><span class="lineno">17355</span>&#160;        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l17356"></a><span class="lineno">17356</span>&#160;    <span class="keywordflow">case</span> <a class="code" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7">VMA_MEMORY_USAGE_GPU_ONLY</a>:</div>
+<div class="line"><a name="l17357"></a><span class="lineno">17357</span>&#160;        <span class="keywordflow">if</span>(!allocator-&gt;IsIntegratedGpu() || (preferredFlags &amp; VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0)</div>
+<div class="line"><a name="l17358"></a><span class="lineno">17358</span>&#160;        {</div>
+<div class="line"><a name="l17359"></a><span class="lineno">17359</span>&#160;            preferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;</div>
+<div class="line"><a name="l17360"></a><span class="lineno">17360</span>&#160;        }</div>
+<div class="line"><a name="l17361"></a><span class="lineno">17361</span>&#160;        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l17362"></a><span class="lineno">17362</span>&#160;    <span class="keywordflow">case</span> <a class="code" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca40bdf4cddeffeb12f43d45ca1286e0a5">VMA_MEMORY_USAGE_CPU_ONLY</a>:</div>
+<div class="line"><a name="l17363"></a><span class="lineno">17363</span>&#160;        requiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;</div>
+<div class="line"><a name="l17364"></a><span class="lineno">17364</span>&#160;        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l17365"></a><span class="lineno">17365</span>&#160;    <span class="keywordflow">case</span> <a class="code" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca9066b52c5a7079bb74a69aaf8b92ff67">VMA_MEMORY_USAGE_CPU_TO_GPU</a>:</div>
+<div class="line"><a name="l17366"></a><span class="lineno">17366</span>&#160;        requiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;</div>
+<div class="line"><a name="l17367"></a><span class="lineno">17367</span>&#160;        <span class="keywordflow">if</span>(!allocator-&gt;IsIntegratedGpu() || (preferredFlags &amp; VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0)</div>
+<div class="line"><a name="l17368"></a><span class="lineno">17368</span>&#160;        {</div>
+<div class="line"><a name="l17369"></a><span class="lineno">17369</span>&#160;            preferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;</div>
+<div class="line"><a name="l17370"></a><span class="lineno">17370</span>&#160;        }</div>
+<div class="line"><a name="l17371"></a><span class="lineno">17371</span>&#160;        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l17372"></a><span class="lineno">17372</span>&#160;    <span class="keywordflow">case</span> <a class="code" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca7b586d2fdaf82a463b58f581ed72be27">VMA_MEMORY_USAGE_GPU_TO_CPU</a>:</div>
+<div class="line"><a name="l17373"></a><span class="lineno">17373</span>&#160;        requiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;</div>
+<div class="line"><a name="l17374"></a><span class="lineno">17374</span>&#160;        preferredFlags |= VK_MEMORY_PROPERTY_HOST_CACHED_BIT;</div>
+<div class="line"><a name="l17375"></a><span class="lineno">17375</span>&#160;        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l17376"></a><span class="lineno">17376</span>&#160;    <span class="keywordflow">case</span> <a class="code" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca416a444d4d0fc20067c3f76f32ff2500">VMA_MEMORY_USAGE_CPU_COPY</a>:</div>
+<div class="line"><a name="l17377"></a><span class="lineno">17377</span>&#160;        notPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;</div>
+<div class="line"><a name="l17378"></a><span class="lineno">17378</span>&#160;        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l17379"></a><span class="lineno">17379</span>&#160;    <span class="keywordflow">case</span> <a class="code" href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca835333d9072db63a653818030e17614d">VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED</a>:</div>
+<div class="line"><a name="l17380"></a><span class="lineno">17380</span>&#160;        requiredFlags |= VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT;</div>
+<div class="line"><a name="l17381"></a><span class="lineno">17381</span>&#160;        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l17382"></a><span class="lineno">17382</span>&#160;    <span class="keywordflow">default</span>:</div>
+<div class="line"><a name="l17383"></a><span class="lineno">17383</span>&#160;        VMA_ASSERT(0);</div>
+<div class="line"><a name="l17384"></a><span class="lineno">17384</span>&#160;        <span class="keywordflow">break</span>;</div>
+<div class="line"><a name="l17385"></a><span class="lineno">17385</span>&#160;    }</div>
+<div class="line"><a name="l17386"></a><span class="lineno">17386</span>&#160; </div>
+<div class="line"><a name="l17387"></a><span class="lineno">17387</span>&#160;    <span class="comment">// Avoid DEVICE_COHERENT unless explicitly requested.</span></div>
+<div class="line"><a name="l17388"></a><span class="lineno">17388</span>&#160;    <span class="keywordflow">if</span>(((pAllocationCreateInfo-&gt;<a class="code" href="struct_vma_allocation_create_info.html#a9166390303ff42d783305bc31c2b6b90">requiredFlags</a> | pAllocationCreateInfo-&gt;<a class="code" href="struct_vma_allocation_create_info.html#a7fe8d81a1ad10b2a2faacacee5b15d6d">preferredFlags</a>) &amp;</div>
+<div class="line"><a name="l17389"></a><span class="lineno">17389</span>&#160;        (VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD_COPY | VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD_COPY)) == 0)</div>
+<div class="line"><a name="l17390"></a><span class="lineno">17390</span>&#160;    {</div>
+<div class="line"><a name="l17391"></a><span class="lineno">17391</span>&#160;        notPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD_COPY;</div>
+<div class="line"><a name="l17392"></a><span class="lineno">17392</span>&#160;    }</div>
+<div class="line"><a name="l17393"></a><span class="lineno">17393</span>&#160; </div>
+<div class="line"><a name="l17394"></a><span class="lineno">17394</span>&#160;    *pMemoryTypeIndex = UINT32_MAX;</div>
+<div class="line"><a name="l17395"></a><span class="lineno">17395</span>&#160;    uint32_t minCost = UINT32_MAX;</div>
+<div class="line"><a name="l17396"></a><span class="lineno">17396</span>&#160;    <span class="keywordflow">for</span>(uint32_t memTypeIndex = 0, memTypeBit = 1;</div>
+<div class="line"><a name="l17397"></a><span class="lineno">17397</span>&#160;        memTypeIndex &lt; allocator-&gt;GetMemoryTypeCount();</div>
+<div class="line"><a name="l17398"></a><span class="lineno">17398</span>&#160;        ++memTypeIndex, memTypeBit &lt;&lt;= 1)</div>
+<div class="line"><a name="l17399"></a><span class="lineno">17399</span>&#160;    {</div>
+<div class="line"><a name="l17400"></a><span class="lineno">17400</span>&#160;        <span class="comment">// This memory type is acceptable according to memoryTypeBits bitmask.</span></div>
+<div class="line"><a name="l17401"></a><span class="lineno">17401</span>&#160;        <span class="keywordflow">if</span>((memTypeBit &amp; memoryTypeBits) != 0)</div>
+<div class="line"><a name="l17402"></a><span class="lineno">17402</span>&#160;        {</div>
+<div class="line"><a name="l17403"></a><span class="lineno">17403</span>&#160;            <span class="keyword">const</span> VkMemoryPropertyFlags currFlags =</div>
+<div class="line"><a name="l17404"></a><span class="lineno">17404</span>&#160;                allocator-&gt;m_MemProps.memoryTypes[memTypeIndex].propertyFlags;</div>
+<div class="line"><a name="l17405"></a><span class="lineno">17405</span>&#160;            <span class="comment">// This memory type contains requiredFlags.</span></div>
+<div class="line"><a name="l17406"></a><span class="lineno">17406</span>&#160;            <span class="keywordflow">if</span>((requiredFlags &amp; ~currFlags) == 0)</div>
+<div class="line"><a name="l17407"></a><span class="lineno">17407</span>&#160;            {</div>
+<div class="line"><a name="l17408"></a><span class="lineno">17408</span>&#160;                <span class="comment">// Calculate cost as number of bits from preferredFlags not present in this memory type.</span></div>
+<div class="line"><a name="l17409"></a><span class="lineno">17409</span>&#160;                uint32_t currCost = VmaCountBitsSet(preferredFlags &amp; ~currFlags) +</div>
+<div class="line"><a name="l17410"></a><span class="lineno">17410</span>&#160;                    VmaCountBitsSet(currFlags &amp; notPreferredFlags);</div>
+<div class="line"><a name="l17411"></a><span class="lineno">17411</span>&#160;                <span class="comment">// Remember memory type with lowest cost.</span></div>
+<div class="line"><a name="l17412"></a><span class="lineno">17412</span>&#160;                <span class="keywordflow">if</span>(currCost &lt; minCost)</div>
+<div class="line"><a name="l17413"></a><span class="lineno">17413</span>&#160;                {</div>
+<div class="line"><a name="l17414"></a><span class="lineno">17414</span>&#160;                    *pMemoryTypeIndex = memTypeIndex;</div>
+<div class="line"><a name="l17415"></a><span class="lineno">17415</span>&#160;                    <span class="keywordflow">if</span>(currCost == 0)</div>
+<div class="line"><a name="l17416"></a><span class="lineno">17416</span>&#160;                    {</div>
+<div class="line"><a name="l17417"></a><span class="lineno">17417</span>&#160;                        <span class="keywordflow">return</span> VK_SUCCESS;</div>
+<div class="line"><a name="l17418"></a><span class="lineno">17418</span>&#160;                    }</div>
+<div class="line"><a name="l17419"></a><span class="lineno">17419</span>&#160;                    minCost = currCost;</div>
+<div class="line"><a name="l17420"></a><span class="lineno">17420</span>&#160;                }</div>
+<div class="line"><a name="l17421"></a><span class="lineno">17421</span>&#160;            }</div>
+<div class="line"><a name="l17422"></a><span class="lineno">17422</span>&#160;        }</div>
+<div class="line"><a name="l17423"></a><span class="lineno">17423</span>&#160;    }</div>
+<div class="line"><a name="l17424"></a><span class="lineno">17424</span>&#160;    <span class="keywordflow">return</span> (*pMemoryTypeIndex != UINT32_MAX) ? VK_SUCCESS : VK_ERROR_FEATURE_NOT_PRESENT;</div>
+<div class="line"><a name="l17425"></a><span class="lineno">17425</span>&#160;}</div>
+<div class="line"><a name="l17426"></a><span class="lineno">17426</span>&#160; </div>
+<div class="line"><a name="l17427"></a><span class="lineno">17427</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#ae790ab9ffaf7667fb8f62523e6897888">vmaFindMemoryTypeIndexForBufferInfo</a>(</div>
+<div class="line"><a name="l17428"></a><span class="lineno">17428</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l17429"></a><span class="lineno">17429</span>&#160;    <span class="keyword">const</span> VkBufferCreateInfo* pBufferCreateInfo,</div>
+<div class="line"><a name="l17430"></a><span class="lineno">17430</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>* pAllocationCreateInfo,</div>
+<div class="line"><a name="l17431"></a><span class="lineno">17431</span>&#160;    uint32_t* pMemoryTypeIndex)</div>
+<div class="line"><a name="l17432"></a><span class="lineno">17432</span>&#160;{</div>
+<div class="line"><a name="l17433"></a><span class="lineno">17433</span>&#160;    VMA_ASSERT(allocator != VK_NULL_HANDLE);</div>
+<div class="line"><a name="l17434"></a><span class="lineno">17434</span>&#160;    VMA_ASSERT(pBufferCreateInfo != VMA_NULL);</div>
+<div class="line"><a name="l17435"></a><span class="lineno">17435</span>&#160;    VMA_ASSERT(pAllocationCreateInfo != VMA_NULL);</div>
+<div class="line"><a name="l17436"></a><span class="lineno">17436</span>&#160;    VMA_ASSERT(pMemoryTypeIndex != VMA_NULL);</div>
+<div class="line"><a name="l17437"></a><span class="lineno">17437</span>&#160; </div>
+<div class="line"><a name="l17438"></a><span class="lineno">17438</span>&#160;    <span class="keyword">const</span> VkDevice hDev = allocator-&gt;m_hDevice;</div>
+<div class="line"><a name="l17439"></a><span class="lineno">17439</span>&#160;    VkBuffer hBuffer = VK_NULL_HANDLE;</div>
+<div class="line"><a name="l17440"></a><span class="lineno">17440</span>&#160;    VkResult res = allocator-&gt;GetVulkanFunctions().vkCreateBuffer(</div>
+<div class="line"><a name="l17441"></a><span class="lineno">17441</span>&#160;        hDev, pBufferCreateInfo, allocator-&gt;GetAllocationCallbacks(), &amp;hBuffer);</div>
+<div class="line"><a name="l17442"></a><span class="lineno">17442</span>&#160;    <span class="keywordflow">if</span>(res == VK_SUCCESS)</div>
+<div class="line"><a name="l17443"></a><span class="lineno">17443</span>&#160;    {</div>
+<div class="line"><a name="l17444"></a><span class="lineno">17444</span>&#160;        VkMemoryRequirements memReq = {};</div>
+<div class="line"><a name="l17445"></a><span class="lineno">17445</span>&#160;        allocator-&gt;GetVulkanFunctions().vkGetBufferMemoryRequirements(</div>
+<div class="line"><a name="l17446"></a><span class="lineno">17446</span>&#160;            hDev, hBuffer, &amp;memReq);</div>
+<div class="line"><a name="l17447"></a><span class="lineno">17447</span>&#160; </div>
+<div class="line"><a name="l17448"></a><span class="lineno">17448</span>&#160;        res = <a class="code" href="vk__mem__alloc_8h.html#aef15a94b58fbcb0fe706d5720e84a74a">vmaFindMemoryTypeIndex</a>(</div>
+<div class="line"><a name="l17449"></a><span class="lineno">17449</span>&#160;            allocator,</div>
+<div class="line"><a name="l17450"></a><span class="lineno">17450</span>&#160;            memReq.memoryTypeBits,</div>
+<div class="line"><a name="l17451"></a><span class="lineno">17451</span>&#160;            pAllocationCreateInfo,</div>
+<div class="line"><a name="l17452"></a><span class="lineno">17452</span>&#160;            pMemoryTypeIndex);</div>
+<div class="line"><a name="l17453"></a><span class="lineno">17453</span>&#160; </div>
+<div class="line"><a name="l17454"></a><span class="lineno">17454</span>&#160;        allocator-&gt;GetVulkanFunctions().vkDestroyBuffer(</div>
+<div class="line"><a name="l17455"></a><span class="lineno">17455</span>&#160;            hDev, hBuffer, allocator-&gt;GetAllocationCallbacks());</div>
+<div class="line"><a name="l17456"></a><span class="lineno">17456</span>&#160;    }</div>
+<div class="line"><a name="l17457"></a><span class="lineno">17457</span>&#160;    <span class="keywordflow">return</span> res;</div>
+<div class="line"><a name="l17458"></a><span class="lineno">17458</span>&#160;}</div>
+<div class="line"><a name="l17459"></a><span class="lineno">17459</span>&#160; </div>
+<div class="line"><a name="l17460"></a><span class="lineno">17460</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a088da83d8eaf3ce9056d9ea0b981d472">vmaFindMemoryTypeIndexForImageInfo</a>(</div>
+<div class="line"><a name="l17461"></a><span class="lineno">17461</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l17462"></a><span class="lineno">17462</span>&#160;    <span class="keyword">const</span> VkImageCreateInfo* pImageCreateInfo,</div>
+<div class="line"><a name="l17463"></a><span class="lineno">17463</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>* pAllocationCreateInfo,</div>
+<div class="line"><a name="l17464"></a><span class="lineno">17464</span>&#160;    uint32_t* pMemoryTypeIndex)</div>
+<div class="line"><a name="l17465"></a><span class="lineno">17465</span>&#160;{</div>
+<div class="line"><a name="l17466"></a><span class="lineno">17466</span>&#160;    VMA_ASSERT(allocator != VK_NULL_HANDLE);</div>
+<div class="line"><a name="l17467"></a><span class="lineno">17467</span>&#160;    VMA_ASSERT(pImageCreateInfo != VMA_NULL);</div>
+<div class="line"><a name="l17468"></a><span class="lineno">17468</span>&#160;    VMA_ASSERT(pAllocationCreateInfo != VMA_NULL);</div>
+<div class="line"><a name="l17469"></a><span class="lineno">17469</span>&#160;    VMA_ASSERT(pMemoryTypeIndex != VMA_NULL);</div>
+<div class="line"><a name="l17470"></a><span class="lineno">17470</span>&#160; </div>
+<div class="line"><a name="l17471"></a><span class="lineno">17471</span>&#160;    <span class="keyword">const</span> VkDevice hDev = allocator-&gt;m_hDevice;</div>
+<div class="line"><a name="l17472"></a><span class="lineno">17472</span>&#160;    VkImage hImage = VK_NULL_HANDLE;</div>
+<div class="line"><a name="l17473"></a><span class="lineno">17473</span>&#160;    VkResult res = allocator-&gt;GetVulkanFunctions().vkCreateImage(</div>
+<div class="line"><a name="l17474"></a><span class="lineno">17474</span>&#160;        hDev, pImageCreateInfo, allocator-&gt;GetAllocationCallbacks(), &amp;hImage);</div>
+<div class="line"><a name="l17475"></a><span class="lineno">17475</span>&#160;    <span class="keywordflow">if</span>(res == VK_SUCCESS)</div>
+<div class="line"><a name="l17476"></a><span class="lineno">17476</span>&#160;    {</div>
+<div class="line"><a name="l17477"></a><span class="lineno">17477</span>&#160;        VkMemoryRequirements memReq = {};</div>
+<div class="line"><a name="l17478"></a><span class="lineno">17478</span>&#160;        allocator-&gt;GetVulkanFunctions().vkGetImageMemoryRequirements(</div>
+<div class="line"><a name="l17479"></a><span class="lineno">17479</span>&#160;            hDev, hImage, &amp;memReq);</div>
+<div class="line"><a name="l17480"></a><span class="lineno">17480</span>&#160; </div>
+<div class="line"><a name="l17481"></a><span class="lineno">17481</span>&#160;        res = <a class="code" href="vk__mem__alloc_8h.html#aef15a94b58fbcb0fe706d5720e84a74a">vmaFindMemoryTypeIndex</a>(</div>
+<div class="line"><a name="l17482"></a><span class="lineno">17482</span>&#160;            allocator,</div>
+<div class="line"><a name="l17483"></a><span class="lineno">17483</span>&#160;            memReq.memoryTypeBits,</div>
+<div class="line"><a name="l17484"></a><span class="lineno">17484</span>&#160;            pAllocationCreateInfo,</div>
+<div class="line"><a name="l17485"></a><span class="lineno">17485</span>&#160;            pMemoryTypeIndex);</div>
+<div class="line"><a name="l17486"></a><span class="lineno">17486</span>&#160; </div>
+<div class="line"><a name="l17487"></a><span class="lineno">17487</span>&#160;        allocator-&gt;GetVulkanFunctions().vkDestroyImage(</div>
+<div class="line"><a name="l17488"></a><span class="lineno">17488</span>&#160;            hDev, hImage, allocator-&gt;GetAllocationCallbacks());</div>
+<div class="line"><a name="l17489"></a><span class="lineno">17489</span>&#160;    }</div>
+<div class="line"><a name="l17490"></a><span class="lineno">17490</span>&#160;    <span class="keywordflow">return</span> res;</div>
+<div class="line"><a name="l17491"></a><span class="lineno">17491</span>&#160;}</div>
+<div class="line"><a name="l17492"></a><span class="lineno">17492</span>&#160; </div>
+<div class="line"><a name="l17493"></a><span class="lineno">17493</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a5c8770ded7c59c8caac6de0c2cb00b50">vmaCreatePool</a>(</div>
+<div class="line"><a name="l17494"></a><span class="lineno">17494</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l17495"></a><span class="lineno">17495</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_pool_create_info.html">VmaPoolCreateInfo</a>* pCreateInfo,</div>
+<div class="line"><a name="l17496"></a><span class="lineno">17496</span>&#160;    <a class="code" href="struct_vma_pool.html">VmaPool</a>* pPool)</div>
+<div class="line"><a name="l17497"></a><span class="lineno">17497</span>&#160;{</div>
+<div class="line"><a name="l17498"></a><span class="lineno">17498</span>&#160;    VMA_ASSERT(allocator &amp;&amp; pCreateInfo &amp;&amp; pPool);</div>
+<div class="line"><a name="l17499"></a><span class="lineno">17499</span>&#160;    </div>
+<div class="line"><a name="l17500"></a><span class="lineno">17500</span>&#160;    VMA_DEBUG_LOG(<span class="stringliteral">&quot;vmaCreatePool&quot;</span>);</div>
+<div class="line"><a name="l17501"></a><span class="lineno">17501</span>&#160;    </div>
+<div class="line"><a name="l17502"></a><span class="lineno">17502</span>&#160;    VMA_DEBUG_GLOBAL_MUTEX_LOCK</div>
+<div class="line"><a name="l17503"></a><span class="lineno">17503</span>&#160;    </div>
+<div class="line"><a name="l17504"></a><span class="lineno">17504</span>&#160;    VkResult res = allocator-&gt;CreatePool(pCreateInfo, pPool);</div>
+<div class="line"><a name="l17505"></a><span class="lineno">17505</span>&#160;    </div>
+<div class="line"><a name="l17506"></a><span class="lineno">17506</span>&#160;<span class="preprocessor">#if VMA_RECORDING_ENABLED</span></div>
+<div class="line"><a name="l17507"></a><span class="lineno">17507</span>&#160;    <span class="keywordflow">if</span>(allocator-&gt;GetRecorder() != VMA_NULL)</div>
+<div class="line"><a name="l17508"></a><span class="lineno">17508</span>&#160;    {</div>
+<div class="line"><a name="l17509"></a><span class="lineno">17509</span>&#160;        allocator-&gt;GetRecorder()-&gt;RecordCreatePool(allocator-&gt;GetCurrentFrameIndex(), *pCreateInfo, *pPool);</div>
+<div class="line"><a name="l17510"></a><span class="lineno">17510</span>&#160;    }</div>
+<div class="line"><a name="l17511"></a><span class="lineno">17511</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l17512"></a><span class="lineno">17512</span>&#160;    </div>
+<div class="line"><a name="l17513"></a><span class="lineno">17513</span>&#160;    <span class="keywordflow">return</span> res;</div>
+<div class="line"><a name="l17514"></a><span class="lineno">17514</span>&#160;}</div>
+<div class="line"><a name="l17515"></a><span class="lineno">17515</span>&#160; </div>
+<div class="line"><a name="l17516"></a><span class="lineno">17516</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a5485779c8f1948238fc4e92232fa65e1">vmaDestroyPool</a>(</div>
+<div class="line"><a name="l17517"></a><span class="lineno">17517</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l17518"></a><span class="lineno">17518</span>&#160;    <a class="code" href="struct_vma_pool.html">VmaPool</a> pool)</div>
+<div class="line"><a name="l17519"></a><span class="lineno">17519</span>&#160;{</div>
+<div class="line"><a name="l17520"></a><span class="lineno">17520</span>&#160;    VMA_ASSERT(allocator);</div>
+<div class="line"><a name="l17521"></a><span class="lineno">17521</span>&#160;    </div>
+<div class="line"><a name="l17522"></a><span class="lineno">17522</span>&#160;    <span class="keywordflow">if</span>(pool == VK_NULL_HANDLE)</div>
+<div class="line"><a name="l17523"></a><span class="lineno">17523</span>&#160;    {</div>
+<div class="line"><a name="l17524"></a><span class="lineno">17524</span>&#160;        <span class="keywordflow">return</span>;</div>
+<div class="line"><a name="l17525"></a><span class="lineno">17525</span>&#160;    }</div>
+<div class="line"><a name="l17526"></a><span class="lineno">17526</span>&#160;    </div>
+<div class="line"><a name="l17527"></a><span class="lineno">17527</span>&#160;    VMA_DEBUG_LOG(<span class="stringliteral">&quot;vmaDestroyPool&quot;</span>);</div>
+<div class="line"><a name="l17528"></a><span class="lineno">17528</span>&#160;    </div>
+<div class="line"><a name="l17529"></a><span class="lineno">17529</span>&#160;    VMA_DEBUG_GLOBAL_MUTEX_LOCK</div>
+<div class="line"><a name="l17530"></a><span class="lineno">17530</span>&#160;    </div>
+<div class="line"><a name="l17531"></a><span class="lineno">17531</span>&#160;<span class="preprocessor">#if VMA_RECORDING_ENABLED</span></div>
+<div class="line"><a name="l17532"></a><span class="lineno">17532</span>&#160;    <span class="keywordflow">if</span>(allocator-&gt;GetRecorder() != VMA_NULL)</div>
+<div class="line"><a name="l17533"></a><span class="lineno">17533</span>&#160;    {</div>
+<div class="line"><a name="l17534"></a><span class="lineno">17534</span>&#160;        allocator-&gt;GetRecorder()-&gt;RecordDestroyPool(allocator-&gt;GetCurrentFrameIndex(), pool);</div>
+<div class="line"><a name="l17535"></a><span class="lineno">17535</span>&#160;    }</div>
+<div class="line"><a name="l17536"></a><span class="lineno">17536</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l17537"></a><span class="lineno">17537</span>&#160; </div>
+<div class="line"><a name="l17538"></a><span class="lineno">17538</span>&#160;    allocator-&gt;DestroyPool(pool);</div>
+<div class="line"><a name="l17539"></a><span class="lineno">17539</span>&#160;}</div>
+<div class="line"><a name="l17540"></a><span class="lineno">17540</span>&#160; </div>
+<div class="line"><a name="l17541"></a><span class="lineno">17541</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#ae8bf76997b234ef68aad922616df4153">vmaGetPoolStats</a>(</div>
+<div class="line"><a name="l17542"></a><span class="lineno">17542</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l17543"></a><span class="lineno">17543</span>&#160;    <a class="code" href="struct_vma_pool.html">VmaPool</a> pool,</div>
+<div class="line"><a name="l17544"></a><span class="lineno">17544</span>&#160;    <a class="code" href="struct_vma_pool_stats.html">VmaPoolStats</a>* pPoolStats)</div>
+<div class="line"><a name="l17545"></a><span class="lineno">17545</span>&#160;{</div>
+<div class="line"><a name="l17546"></a><span class="lineno">17546</span>&#160;    VMA_ASSERT(allocator &amp;&amp; pool &amp;&amp; pPoolStats);</div>
+<div class="line"><a name="l17547"></a><span class="lineno">17547</span>&#160; </div>
+<div class="line"><a name="l17548"></a><span class="lineno">17548</span>&#160;    VMA_DEBUG_GLOBAL_MUTEX_LOCK</div>
+<div class="line"><a name="l17549"></a><span class="lineno">17549</span>&#160; </div>
+<div class="line"><a name="l17550"></a><span class="lineno">17550</span>&#160;    allocator-&gt;GetPoolStats(pool, pPoolStats);</div>
+<div class="line"><a name="l17551"></a><span class="lineno">17551</span>&#160;}</div>
+<div class="line"><a name="l17552"></a><span class="lineno">17552</span>&#160; </div>
+<div class="line"><a name="l17553"></a><span class="lineno">17553</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a736bd6cbda886f36c891727e73bd4024">vmaMakePoolAllocationsLost</a>(</div>
+<div class="line"><a name="l17554"></a><span class="lineno">17554</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l17555"></a><span class="lineno">17555</span>&#160;    <a class="code" href="struct_vma_pool.html">VmaPool</a> pool,</div>
+<div class="line"><a name="l17556"></a><span class="lineno">17556</span>&#160;    <span class="keywordtype">size_t</span>* pLostAllocationCount)</div>
+<div class="line"><a name="l17557"></a><span class="lineno">17557</span>&#160;{</div>
+<div class="line"><a name="l17558"></a><span class="lineno">17558</span>&#160;    VMA_ASSERT(allocator &amp;&amp; pool);</div>
+<div class="line"><a name="l17559"></a><span class="lineno">17559</span>&#160; </div>
+<div class="line"><a name="l17560"></a><span class="lineno">17560</span>&#160;    VMA_DEBUG_GLOBAL_MUTEX_LOCK</div>
+<div class="line"><a name="l17561"></a><span class="lineno">17561</span>&#160; </div>
+<div class="line"><a name="l17562"></a><span class="lineno">17562</span>&#160;<span class="preprocessor">#if VMA_RECORDING_ENABLED</span></div>
+<div class="line"><a name="l17563"></a><span class="lineno">17563</span>&#160;    <span class="keywordflow">if</span>(allocator-&gt;GetRecorder() != VMA_NULL)</div>
+<div class="line"><a name="l17564"></a><span class="lineno">17564</span>&#160;    {</div>
+<div class="line"><a name="l17565"></a><span class="lineno">17565</span>&#160;        allocator-&gt;GetRecorder()-&gt;RecordMakePoolAllocationsLost(allocator-&gt;GetCurrentFrameIndex(), pool);</div>
+<div class="line"><a name="l17566"></a><span class="lineno">17566</span>&#160;    }</div>
+<div class="line"><a name="l17567"></a><span class="lineno">17567</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l17568"></a><span class="lineno">17568</span>&#160; </div>
+<div class="line"><a name="l17569"></a><span class="lineno">17569</span>&#160;    allocator-&gt;MakePoolAllocationsLost(pool, pLostAllocationCount);</div>
+<div class="line"><a name="l17570"></a><span class="lineno">17570</span>&#160;}</div>
+<div class="line"><a name="l17571"></a><span class="lineno">17571</span>&#160; </div>
+<div class="line"><a name="l17572"></a><span class="lineno">17572</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#ad535935619c7a549bf837e1bb0068f89">vmaCheckPoolCorruption</a>(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator, <a class="code" href="struct_vma_pool.html">VmaPool</a> pool)</div>
+<div class="line"><a name="l17573"></a><span class="lineno">17573</span>&#160;{</div>
+<div class="line"><a name="l17574"></a><span class="lineno">17574</span>&#160;    VMA_ASSERT(allocator &amp;&amp; pool);</div>
+<div class="line"><a name="l17575"></a><span class="lineno">17575</span>&#160; </div>
+<div class="line"><a name="l17576"></a><span class="lineno">17576</span>&#160;    VMA_DEBUG_GLOBAL_MUTEX_LOCK</div>
+<div class="line"><a name="l17577"></a><span class="lineno">17577</span>&#160; </div>
+<div class="line"><a name="l17578"></a><span class="lineno">17578</span>&#160;    VMA_DEBUG_LOG(<span class="stringliteral">&quot;vmaCheckPoolCorruption&quot;</span>);</div>
+<div class="line"><a name="l17579"></a><span class="lineno">17579</span>&#160; </div>
+<div class="line"><a name="l17580"></a><span class="lineno">17580</span>&#160;    <span class="keywordflow">return</span> allocator-&gt;CheckPoolCorruption(pool);</div>
+<div class="line"><a name="l17581"></a><span class="lineno">17581</span>&#160;}</div>
+<div class="line"><a name="l17582"></a><span class="lineno">17582</span>&#160; </div>
+<div class="line"><a name="l17583"></a><span class="lineno">17583</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#af09b4e4eafdbee812e8d73ddf960f030">vmaGetPoolName</a>(</div>
+<div class="line"><a name="l17584"></a><span class="lineno">17584</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l17585"></a><span class="lineno">17585</span>&#160;    <a class="code" href="struct_vma_pool.html">VmaPool</a> pool,</div>
+<div class="line"><a name="l17586"></a><span class="lineno">17586</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">char</span>** ppName)</div>
+<div class="line"><a name="l17587"></a><span class="lineno">17587</span>&#160;{</div>
+<div class="line"><a name="l17588"></a><span class="lineno">17588</span>&#160;    VMA_ASSERT(allocator &amp;&amp; pool);</div>
+<div class="line"><a name="l17589"></a><span class="lineno">17589</span>&#160;    </div>
+<div class="line"><a name="l17590"></a><span class="lineno">17590</span>&#160;    VMA_DEBUG_LOG(<span class="stringliteral">&quot;vmaGetPoolName&quot;</span>);</div>
+<div class="line"><a name="l17591"></a><span class="lineno">17591</span>&#160; </div>
+<div class="line"><a name="l17592"></a><span class="lineno">17592</span>&#160;    VMA_DEBUG_GLOBAL_MUTEX_LOCK</div>
+<div class="line"><a name="l17593"></a><span class="lineno">17593</span>&#160; </div>
+<div class="line"><a name="l17594"></a><span class="lineno">17594</span>&#160;    *ppName = pool-&gt;GetName();</div>
+<div class="line"><a name="l17595"></a><span class="lineno">17595</span>&#160;}</div>
+<div class="line"><a name="l17596"></a><span class="lineno">17596</span>&#160; </div>
+<div class="line"><a name="l17597"></a><span class="lineno">17597</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#adbae3a0b4ab078024462fc85c37f3b58">vmaSetPoolName</a>(</div>
+<div class="line"><a name="l17598"></a><span class="lineno">17598</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l17599"></a><span class="lineno">17599</span>&#160;    <a class="code" href="struct_vma_pool.html">VmaPool</a> pool,</div>
+<div class="line"><a name="l17600"></a><span class="lineno">17600</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">char</span>* pName)</div>
+<div class="line"><a name="l17601"></a><span class="lineno">17601</span>&#160;{</div>
+<div class="line"><a name="l17602"></a><span class="lineno">17602</span>&#160;    VMA_ASSERT(allocator &amp;&amp; pool);</div>
+<div class="line"><a name="l17603"></a><span class="lineno">17603</span>&#160; </div>
+<div class="line"><a name="l17604"></a><span class="lineno">17604</span>&#160;    VMA_DEBUG_LOG(<span class="stringliteral">&quot;vmaSetPoolName&quot;</span>);</div>
+<div class="line"><a name="l17605"></a><span class="lineno">17605</span>&#160; </div>
+<div class="line"><a name="l17606"></a><span class="lineno">17606</span>&#160;    VMA_DEBUG_GLOBAL_MUTEX_LOCK</div>
+<div class="line"><a name="l17607"></a><span class="lineno">17607</span>&#160; </div>
+<div class="line"><a name="l17608"></a><span class="lineno">17608</span>&#160;    pool-&gt;SetName(pName);</div>
+<div class="line"><a name="l17609"></a><span class="lineno">17609</span>&#160; </div>
+<div class="line"><a name="l17610"></a><span class="lineno">17610</span>&#160;<span class="preprocessor">#if VMA_RECORDING_ENABLED</span></div>
+<div class="line"><a name="l17611"></a><span class="lineno">17611</span>&#160;    <span class="keywordflow">if</span>(allocator-&gt;GetRecorder() != VMA_NULL)</div>
+<div class="line"><a name="l17612"></a><span class="lineno">17612</span>&#160;    {</div>
+<div class="line"><a name="l17613"></a><span class="lineno">17613</span>&#160;        allocator-&gt;GetRecorder()-&gt;RecordSetPoolName(allocator-&gt;GetCurrentFrameIndex(), pool, pName);</div>
+<div class="line"><a name="l17614"></a><span class="lineno">17614</span>&#160;    }</div>
+<div class="line"><a name="l17615"></a><span class="lineno">17615</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l17616"></a><span class="lineno">17616</span>&#160;}</div>
+<div class="line"><a name="l17617"></a><span class="lineno">17617</span>&#160; </div>
+<div class="line"><a name="l17618"></a><span class="lineno">17618</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#abf28077dbf82d0908b8acbe8ee8dd9b8">vmaAllocateMemory</a>(</div>
+<div class="line"><a name="l17619"></a><span class="lineno">17619</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l17620"></a><span class="lineno">17620</span>&#160;    <span class="keyword">const</span> VkMemoryRequirements* pVkMemoryRequirements,</div>
+<div class="line"><a name="l17621"></a><span class="lineno">17621</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>* pCreateInfo,</div>
+<div class="line"><a name="l17622"></a><span class="lineno">17622</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocation,</div>
+<div class="line"><a name="l17623"></a><span class="lineno">17623</span>&#160;    <a class="code" href="struct_vma_allocation_info.html">VmaAllocationInfo</a>* pAllocationInfo)</div>
+<div class="line"><a name="l17624"></a><span class="lineno">17624</span>&#160;{</div>
+<div class="line"><a name="l17625"></a><span class="lineno">17625</span>&#160;    VMA_ASSERT(allocator &amp;&amp; pVkMemoryRequirements &amp;&amp; pCreateInfo &amp;&amp; pAllocation);</div>
+<div class="line"><a name="l17626"></a><span class="lineno">17626</span>&#160; </div>
+<div class="line"><a name="l17627"></a><span class="lineno">17627</span>&#160;    VMA_DEBUG_LOG(<span class="stringliteral">&quot;vmaAllocateMemory&quot;</span>);</div>
+<div class="line"><a name="l17628"></a><span class="lineno">17628</span>&#160; </div>
+<div class="line"><a name="l17629"></a><span class="lineno">17629</span>&#160;    VMA_DEBUG_GLOBAL_MUTEX_LOCK</div>
+<div class="line"><a name="l17630"></a><span class="lineno">17630</span>&#160; </div>
+<div class="line"><a name="l17631"></a><span class="lineno">17631</span>&#160;    VkResult result = allocator-&gt;AllocateMemory(</div>
+<div class="line"><a name="l17632"></a><span class="lineno">17632</span>&#160;        *pVkMemoryRequirements,</div>
+<div class="line"><a name="l17633"></a><span class="lineno">17633</span>&#160;        <span class="keyword">false</span>, <span class="comment">// requiresDedicatedAllocation</span></div>
+<div class="line"><a name="l17634"></a><span class="lineno">17634</span>&#160;        <span class="keyword">false</span>, <span class="comment">// prefersDedicatedAllocation</span></div>
+<div class="line"><a name="l17635"></a><span class="lineno">17635</span>&#160;        VK_NULL_HANDLE, <span class="comment">// dedicatedBuffer</span></div>
+<div class="line"><a name="l17636"></a><span class="lineno">17636</span>&#160;        UINT32_MAX, <span class="comment">// dedicatedBufferUsage</span></div>
+<div class="line"><a name="l17637"></a><span class="lineno">17637</span>&#160;        VK_NULL_HANDLE, <span class="comment">// dedicatedImage</span></div>
+<div class="line"><a name="l17638"></a><span class="lineno">17638</span>&#160;        *pCreateInfo,</div>
+<div class="line"><a name="l17639"></a><span class="lineno">17639</span>&#160;        VMA_SUBALLOCATION_TYPE_UNKNOWN,</div>
+<div class="line"><a name="l17640"></a><span class="lineno">17640</span>&#160;        1, <span class="comment">// allocationCount</span></div>
+<div class="line"><a name="l17641"></a><span class="lineno">17641</span>&#160;        pAllocation);</div>
+<div class="line"><a name="l17642"></a><span class="lineno">17642</span>&#160; </div>
+<div class="line"><a name="l17643"></a><span class="lineno">17643</span>&#160;<span class="preprocessor">#if VMA_RECORDING_ENABLED</span></div>
+<div class="line"><a name="l17644"></a><span class="lineno">17644</span>&#160;    <span class="keywordflow">if</span>(allocator-&gt;GetRecorder() != VMA_NULL)</div>
+<div class="line"><a name="l17645"></a><span class="lineno">17645</span>&#160;    {</div>
+<div class="line"><a name="l17646"></a><span class="lineno">17646</span>&#160;        allocator-&gt;GetRecorder()-&gt;RecordAllocateMemory(</div>
+<div class="line"><a name="l17647"></a><span class="lineno">17647</span>&#160;            allocator-&gt;GetCurrentFrameIndex(),</div>
+<div class="line"><a name="l17648"></a><span class="lineno">17648</span>&#160;            *pVkMemoryRequirements,</div>
+<div class="line"><a name="l17649"></a><span class="lineno">17649</span>&#160;            *pCreateInfo,</div>
+<div class="line"><a name="l17650"></a><span class="lineno">17650</span>&#160;            *pAllocation);</div>
+<div class="line"><a name="l17651"></a><span class="lineno">17651</span>&#160;    }</div>
+<div class="line"><a name="l17652"></a><span class="lineno">17652</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l17653"></a><span class="lineno">17653</span>&#160;        </div>
+<div class="line"><a name="l17654"></a><span class="lineno">17654</span>&#160;    <span class="keywordflow">if</span>(pAllocationInfo != VMA_NULL &amp;&amp; result == VK_SUCCESS)</div>
+<div class="line"><a name="l17655"></a><span class="lineno">17655</span>&#160;    {</div>
+<div class="line"><a name="l17656"></a><span class="lineno">17656</span>&#160;        allocator-&gt;GetAllocationInfo(*pAllocation, pAllocationInfo);</div>
+<div class="line"><a name="l17657"></a><span class="lineno">17657</span>&#160;    }</div>
+<div class="line"><a name="l17658"></a><span class="lineno">17658</span>&#160; </div>
+<div class="line"><a name="l17659"></a><span class="lineno">17659</span>&#160;    <span class="keywordflow">return</span> result;</div>
+<div class="line"><a name="l17660"></a><span class="lineno">17660</span>&#160;}</div>
+<div class="line"><a name="l17661"></a><span class="lineno">17661</span>&#160; </div>
+<div class="line"><a name="l17662"></a><span class="lineno">17662</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#ad37e82e492b3de38fc3f4cffd9ad0ae1">vmaAllocateMemoryPages</a>(</div>
+<div class="line"><a name="l17663"></a><span class="lineno">17663</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l17664"></a><span class="lineno">17664</span>&#160;    <span class="keyword">const</span> VkMemoryRequirements* pVkMemoryRequirements,</div>
+<div class="line"><a name="l17665"></a><span class="lineno">17665</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>* pCreateInfo,</div>
+<div class="line"><a name="l17666"></a><span class="lineno">17666</span>&#160;    <span class="keywordtype">size_t</span> allocationCount,</div>
+<div class="line"><a name="l17667"></a><span class="lineno">17667</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocations,</div>
+<div class="line"><a name="l17668"></a><span class="lineno">17668</span>&#160;    <a class="code" href="struct_vma_allocation_info.html">VmaAllocationInfo</a>* pAllocationInfo)</div>
+<div class="line"><a name="l17669"></a><span class="lineno">17669</span>&#160;{</div>
+<div class="line"><a name="l17670"></a><span class="lineno">17670</span>&#160;    <span class="keywordflow">if</span>(allocationCount == 0)</div>
+<div class="line"><a name="l17671"></a><span class="lineno">17671</span>&#160;    {</div>
+<div class="line"><a name="l17672"></a><span class="lineno">17672</span>&#160;        <span class="keywordflow">return</span> VK_SUCCESS;</div>
+<div class="line"><a name="l17673"></a><span class="lineno">17673</span>&#160;    }</div>
+<div class="line"><a name="l17674"></a><span class="lineno">17674</span>&#160; </div>
+<div class="line"><a name="l17675"></a><span class="lineno">17675</span>&#160;    VMA_ASSERT(allocator &amp;&amp; pVkMemoryRequirements &amp;&amp; pCreateInfo &amp;&amp; pAllocations);</div>
+<div class="line"><a name="l17676"></a><span class="lineno">17676</span>&#160; </div>
+<div class="line"><a name="l17677"></a><span class="lineno">17677</span>&#160;    VMA_DEBUG_LOG(<span class="stringliteral">&quot;vmaAllocateMemoryPages&quot;</span>);</div>
+<div class="line"><a name="l17678"></a><span class="lineno">17678</span>&#160; </div>
+<div class="line"><a name="l17679"></a><span class="lineno">17679</span>&#160;    VMA_DEBUG_GLOBAL_MUTEX_LOCK</div>
+<div class="line"><a name="l17680"></a><span class="lineno">17680</span>&#160; </div>
+<div class="line"><a name="l17681"></a><span class="lineno">17681</span>&#160;    VkResult result = allocator-&gt;AllocateMemory(</div>
+<div class="line"><a name="l17682"></a><span class="lineno">17682</span>&#160;        *pVkMemoryRequirements,</div>
+<div class="line"><a name="l17683"></a><span class="lineno">17683</span>&#160;        <span class="keyword">false</span>, <span class="comment">// requiresDedicatedAllocation</span></div>
+<div class="line"><a name="l17684"></a><span class="lineno">17684</span>&#160;        <span class="keyword">false</span>, <span class="comment">// prefersDedicatedAllocation</span></div>
+<div class="line"><a name="l17685"></a><span class="lineno">17685</span>&#160;        VK_NULL_HANDLE, <span class="comment">// dedicatedBuffer</span></div>
+<div class="line"><a name="l17686"></a><span class="lineno">17686</span>&#160;        UINT32_MAX, <span class="comment">// dedicatedBufferUsage</span></div>
+<div class="line"><a name="l17687"></a><span class="lineno">17687</span>&#160;        VK_NULL_HANDLE, <span class="comment">// dedicatedImage</span></div>
+<div class="line"><a name="l17688"></a><span class="lineno">17688</span>&#160;        *pCreateInfo,</div>
+<div class="line"><a name="l17689"></a><span class="lineno">17689</span>&#160;        VMA_SUBALLOCATION_TYPE_UNKNOWN,</div>
+<div class="line"><a name="l17690"></a><span class="lineno">17690</span>&#160;        allocationCount,</div>
+<div class="line"><a name="l17691"></a><span class="lineno">17691</span>&#160;        pAllocations);</div>
+<div class="line"><a name="l17692"></a><span class="lineno">17692</span>&#160; </div>
+<div class="line"><a name="l17693"></a><span class="lineno">17693</span>&#160;<span class="preprocessor">#if VMA_RECORDING_ENABLED</span></div>
+<div class="line"><a name="l17694"></a><span class="lineno">17694</span>&#160;    <span class="keywordflow">if</span>(allocator-&gt;GetRecorder() != VMA_NULL)</div>
+<div class="line"><a name="l17695"></a><span class="lineno">17695</span>&#160;    {</div>
+<div class="line"><a name="l17696"></a><span class="lineno">17696</span>&#160;        allocator-&gt;GetRecorder()-&gt;RecordAllocateMemoryPages(</div>
+<div class="line"><a name="l17697"></a><span class="lineno">17697</span>&#160;            allocator-&gt;GetCurrentFrameIndex(),</div>
+<div class="line"><a name="l17698"></a><span class="lineno">17698</span>&#160;            *pVkMemoryRequirements,</div>
+<div class="line"><a name="l17699"></a><span class="lineno">17699</span>&#160;            *pCreateInfo,</div>
+<div class="line"><a name="l17700"></a><span class="lineno">17700</span>&#160;            (uint64_t)allocationCount,</div>
+<div class="line"><a name="l17701"></a><span class="lineno">17701</span>&#160;            pAllocations);</div>
+<div class="line"><a name="l17702"></a><span class="lineno">17702</span>&#160;    }</div>
+<div class="line"><a name="l17703"></a><span class="lineno">17703</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l17704"></a><span class="lineno">17704</span>&#160;        </div>
+<div class="line"><a name="l17705"></a><span class="lineno">17705</span>&#160;    <span class="keywordflow">if</span>(pAllocationInfo != VMA_NULL &amp;&amp; result == VK_SUCCESS)</div>
+<div class="line"><a name="l17706"></a><span class="lineno">17706</span>&#160;    {</div>
+<div class="line"><a name="l17707"></a><span class="lineno">17707</span>&#160;        <span class="keywordflow">for</span>(<span class="keywordtype">size_t</span> i = 0; i &lt; allocationCount; ++i)</div>
+<div class="line"><a name="l17708"></a><span class="lineno">17708</span>&#160;        {</div>
+<div class="line"><a name="l17709"></a><span class="lineno">17709</span>&#160;            allocator-&gt;GetAllocationInfo(pAllocations[i], pAllocationInfo + i);</div>
+<div class="line"><a name="l17710"></a><span class="lineno">17710</span>&#160;        }</div>
+<div class="line"><a name="l17711"></a><span class="lineno">17711</span>&#160;    }</div>
+<div class="line"><a name="l17712"></a><span class="lineno">17712</span>&#160; </div>
+<div class="line"><a name="l17713"></a><span class="lineno">17713</span>&#160;    <span class="keywordflow">return</span> result;</div>
+<div class="line"><a name="l17714"></a><span class="lineno">17714</span>&#160;}</div>
+<div class="line"><a name="l17715"></a><span class="lineno">17715</span>&#160; </div>
+<div class="line"><a name="l17716"></a><span class="lineno">17716</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a7fdf64415b6c3d83c454f28d2c53df7b">vmaAllocateMemoryForBuffer</a>(</div>
+<div class="line"><a name="l17717"></a><span class="lineno">17717</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l17718"></a><span class="lineno">17718</span>&#160;    VkBuffer buffer,</div>
+<div class="line"><a name="l17719"></a><span class="lineno">17719</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>* pCreateInfo,</div>
+<div class="line"><a name="l17720"></a><span class="lineno">17720</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocation,</div>
+<div class="line"><a name="l17721"></a><span class="lineno">17721</span>&#160;    <a class="code" href="struct_vma_allocation_info.html">VmaAllocationInfo</a>* pAllocationInfo)</div>
+<div class="line"><a name="l17722"></a><span class="lineno">17722</span>&#160;{</div>
+<div class="line"><a name="l17723"></a><span class="lineno">17723</span>&#160;    VMA_ASSERT(allocator &amp;&amp; buffer != VK_NULL_HANDLE &amp;&amp; pCreateInfo &amp;&amp; pAllocation);</div>
+<div class="line"><a name="l17724"></a><span class="lineno">17724</span>&#160; </div>
+<div class="line"><a name="l17725"></a><span class="lineno">17725</span>&#160;    VMA_DEBUG_LOG(<span class="stringliteral">&quot;vmaAllocateMemoryForBuffer&quot;</span>);</div>
+<div class="line"><a name="l17726"></a><span class="lineno">17726</span>&#160; </div>
+<div class="line"><a name="l17727"></a><span class="lineno">17727</span>&#160;    VMA_DEBUG_GLOBAL_MUTEX_LOCK</div>
+<div class="line"><a name="l17728"></a><span class="lineno">17728</span>&#160; </div>
+<div class="line"><a name="l17729"></a><span class="lineno">17729</span>&#160;    VkMemoryRequirements vkMemReq = {};</div>
+<div class="line"><a name="l17730"></a><span class="lineno">17730</span>&#160;    <span class="keywordtype">bool</span> requiresDedicatedAllocation = <span class="keyword">false</span>;</div>
+<div class="line"><a name="l17731"></a><span class="lineno">17731</span>&#160;    <span class="keywordtype">bool</span> prefersDedicatedAllocation = <span class="keyword">false</span>;</div>
+<div class="line"><a name="l17732"></a><span class="lineno">17732</span>&#160;    allocator-&gt;GetBufferMemoryRequirements(buffer, vkMemReq,</div>
+<div class="line"><a name="l17733"></a><span class="lineno">17733</span>&#160;        requiresDedicatedAllocation,</div>
+<div class="line"><a name="l17734"></a><span class="lineno">17734</span>&#160;        prefersDedicatedAllocation);</div>
+<div class="line"><a name="l17735"></a><span class="lineno">17735</span>&#160; </div>
+<div class="line"><a name="l17736"></a><span class="lineno">17736</span>&#160;    VkResult result = allocator-&gt;AllocateMemory(</div>
+<div class="line"><a name="l17737"></a><span class="lineno">17737</span>&#160;        vkMemReq,</div>
+<div class="line"><a name="l17738"></a><span class="lineno">17738</span>&#160;        requiresDedicatedAllocation,</div>
+<div class="line"><a name="l17739"></a><span class="lineno">17739</span>&#160;        prefersDedicatedAllocation,</div>
+<div class="line"><a name="l17740"></a><span class="lineno">17740</span>&#160;        buffer, <span class="comment">// dedicatedBuffer</span></div>
+<div class="line"><a name="l17741"></a><span class="lineno">17741</span>&#160;        UINT32_MAX, <span class="comment">// dedicatedBufferUsage</span></div>
+<div class="line"><a name="l17742"></a><span class="lineno">17742</span>&#160;        VK_NULL_HANDLE, <span class="comment">// dedicatedImage</span></div>
+<div class="line"><a name="l17743"></a><span class="lineno">17743</span>&#160;        *pCreateInfo,</div>
+<div class="line"><a name="l17744"></a><span class="lineno">17744</span>&#160;        VMA_SUBALLOCATION_TYPE_BUFFER,</div>
+<div class="line"><a name="l17745"></a><span class="lineno">17745</span>&#160;        1, <span class="comment">// allocationCount</span></div>
+<div class="line"><a name="l17746"></a><span class="lineno">17746</span>&#160;        pAllocation);</div>
+<div class="line"><a name="l17747"></a><span class="lineno">17747</span>&#160; </div>
+<div class="line"><a name="l17748"></a><span class="lineno">17748</span>&#160;<span class="preprocessor">#if VMA_RECORDING_ENABLED</span></div>
+<div class="line"><a name="l17749"></a><span class="lineno">17749</span>&#160;    <span class="keywordflow">if</span>(allocator-&gt;GetRecorder() != VMA_NULL)</div>
+<div class="line"><a name="l17750"></a><span class="lineno">17750</span>&#160;    {</div>
+<div class="line"><a name="l17751"></a><span class="lineno">17751</span>&#160;        allocator-&gt;GetRecorder()-&gt;RecordAllocateMemoryForBuffer(</div>
+<div class="line"><a name="l17752"></a><span class="lineno">17752</span>&#160;            allocator-&gt;GetCurrentFrameIndex(),</div>
+<div class="line"><a name="l17753"></a><span class="lineno">17753</span>&#160;            vkMemReq,</div>
+<div class="line"><a name="l17754"></a><span class="lineno">17754</span>&#160;            requiresDedicatedAllocation,</div>
+<div class="line"><a name="l17755"></a><span class="lineno">17755</span>&#160;            prefersDedicatedAllocation,</div>
+<div class="line"><a name="l17756"></a><span class="lineno">17756</span>&#160;            *pCreateInfo,</div>
+<div class="line"><a name="l17757"></a><span class="lineno">17757</span>&#160;            *pAllocation);</div>
+<div class="line"><a name="l17758"></a><span class="lineno">17758</span>&#160;    }</div>
+<div class="line"><a name="l17759"></a><span class="lineno">17759</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l17760"></a><span class="lineno">17760</span>&#160; </div>
+<div class="line"><a name="l17761"></a><span class="lineno">17761</span>&#160;    <span class="keywordflow">if</span>(pAllocationInfo &amp;&amp; result == VK_SUCCESS)</div>
+<div class="line"><a name="l17762"></a><span class="lineno">17762</span>&#160;    {</div>
+<div class="line"><a name="l17763"></a><span class="lineno">17763</span>&#160;        allocator-&gt;GetAllocationInfo(*pAllocation, pAllocationInfo);</div>
+<div class="line"><a name="l17764"></a><span class="lineno">17764</span>&#160;    }</div>
+<div class="line"><a name="l17765"></a><span class="lineno">17765</span>&#160; </div>
+<div class="line"><a name="l17766"></a><span class="lineno">17766</span>&#160;    <span class="keywordflow">return</span> result;</div>
+<div class="line"><a name="l17767"></a><span class="lineno">17767</span>&#160;}</div>
+<div class="line"><a name="l17768"></a><span class="lineno">17768</span>&#160; </div>
+<div class="line"><a name="l17769"></a><span class="lineno">17769</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a0faa3f9e5fb233d29d1e00390650febb">vmaAllocateMemoryForImage</a>(</div>
+<div class="line"><a name="l17770"></a><span class="lineno">17770</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l17771"></a><span class="lineno">17771</span>&#160;    VkImage image,</div>
+<div class="line"><a name="l17772"></a><span class="lineno">17772</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>* pCreateInfo,</div>
+<div class="line"><a name="l17773"></a><span class="lineno">17773</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocation,</div>
+<div class="line"><a name="l17774"></a><span class="lineno">17774</span>&#160;    <a class="code" href="struct_vma_allocation_info.html">VmaAllocationInfo</a>* pAllocationInfo)</div>
+<div class="line"><a name="l17775"></a><span class="lineno">17775</span>&#160;{</div>
+<div class="line"><a name="l17776"></a><span class="lineno">17776</span>&#160;    VMA_ASSERT(allocator &amp;&amp; image != VK_NULL_HANDLE &amp;&amp; pCreateInfo &amp;&amp; pAllocation);</div>
+<div class="line"><a name="l17777"></a><span class="lineno">17777</span>&#160; </div>
+<div class="line"><a name="l17778"></a><span class="lineno">17778</span>&#160;    VMA_DEBUG_LOG(<span class="stringliteral">&quot;vmaAllocateMemoryForImage&quot;</span>);</div>
+<div class="line"><a name="l17779"></a><span class="lineno">17779</span>&#160; </div>
+<div class="line"><a name="l17780"></a><span class="lineno">17780</span>&#160;    VMA_DEBUG_GLOBAL_MUTEX_LOCK</div>
+<div class="line"><a name="l17781"></a><span class="lineno">17781</span>&#160; </div>
+<div class="line"><a name="l17782"></a><span class="lineno">17782</span>&#160;    VkMemoryRequirements vkMemReq = {};</div>
+<div class="line"><a name="l17783"></a><span class="lineno">17783</span>&#160;    <span class="keywordtype">bool</span> requiresDedicatedAllocation = <span class="keyword">false</span>;</div>
+<div class="line"><a name="l17784"></a><span class="lineno">17784</span>&#160;    <span class="keywordtype">bool</span> prefersDedicatedAllocation  = <span class="keyword">false</span>;</div>
+<div class="line"><a name="l17785"></a><span class="lineno">17785</span>&#160;    allocator-&gt;GetImageMemoryRequirements(image, vkMemReq,</div>
+<div class="line"><a name="l17786"></a><span class="lineno">17786</span>&#160;        requiresDedicatedAllocation, prefersDedicatedAllocation);</div>
+<div class="line"><a name="l17787"></a><span class="lineno">17787</span>&#160; </div>
+<div class="line"><a name="l17788"></a><span class="lineno">17788</span>&#160;    VkResult result = allocator-&gt;AllocateMemory(</div>
+<div class="line"><a name="l17789"></a><span class="lineno">17789</span>&#160;        vkMemReq,</div>
+<div class="line"><a name="l17790"></a><span class="lineno">17790</span>&#160;        requiresDedicatedAllocation,</div>
+<div class="line"><a name="l17791"></a><span class="lineno">17791</span>&#160;        prefersDedicatedAllocation,</div>
+<div class="line"><a name="l17792"></a><span class="lineno">17792</span>&#160;        VK_NULL_HANDLE, <span class="comment">// dedicatedBuffer</span></div>
+<div class="line"><a name="l17793"></a><span class="lineno">17793</span>&#160;        UINT32_MAX, <span class="comment">// dedicatedBufferUsage</span></div>
+<div class="line"><a name="l17794"></a><span class="lineno">17794</span>&#160;        image, <span class="comment">// dedicatedImage</span></div>
+<div class="line"><a name="l17795"></a><span class="lineno">17795</span>&#160;        *pCreateInfo,</div>
+<div class="line"><a name="l17796"></a><span class="lineno">17796</span>&#160;        VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN,</div>
+<div class="line"><a name="l17797"></a><span class="lineno">17797</span>&#160;        1, <span class="comment">// allocationCount</span></div>
+<div class="line"><a name="l17798"></a><span class="lineno">17798</span>&#160;        pAllocation);</div>
+<div class="line"><a name="l17799"></a><span class="lineno">17799</span>&#160; </div>
+<div class="line"><a name="l17800"></a><span class="lineno">17800</span>&#160;<span class="preprocessor">#if VMA_RECORDING_ENABLED</span></div>
+<div class="line"><a name="l17801"></a><span class="lineno">17801</span>&#160;    <span class="keywordflow">if</span>(allocator-&gt;GetRecorder() != VMA_NULL)</div>
+<div class="line"><a name="l17802"></a><span class="lineno">17802</span>&#160;    {</div>
+<div class="line"><a name="l17803"></a><span class="lineno">17803</span>&#160;        allocator-&gt;GetRecorder()-&gt;RecordAllocateMemoryForImage(</div>
+<div class="line"><a name="l17804"></a><span class="lineno">17804</span>&#160;            allocator-&gt;GetCurrentFrameIndex(),</div>
+<div class="line"><a name="l17805"></a><span class="lineno">17805</span>&#160;            vkMemReq,</div>
+<div class="line"><a name="l17806"></a><span class="lineno">17806</span>&#160;            requiresDedicatedAllocation,</div>
+<div class="line"><a name="l17807"></a><span class="lineno">17807</span>&#160;            prefersDedicatedAllocation,</div>
+<div class="line"><a name="l17808"></a><span class="lineno">17808</span>&#160;            *pCreateInfo,</div>
+<div class="line"><a name="l17809"></a><span class="lineno">17809</span>&#160;            *pAllocation);</div>
+<div class="line"><a name="l17810"></a><span class="lineno">17810</span>&#160;    }</div>
+<div class="line"><a name="l17811"></a><span class="lineno">17811</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l17812"></a><span class="lineno">17812</span>&#160; </div>
+<div class="line"><a name="l17813"></a><span class="lineno">17813</span>&#160;    <span class="keywordflow">if</span>(pAllocationInfo &amp;&amp; result == VK_SUCCESS)</div>
+<div class="line"><a name="l17814"></a><span class="lineno">17814</span>&#160;    {</div>
+<div class="line"><a name="l17815"></a><span class="lineno">17815</span>&#160;        allocator-&gt;GetAllocationInfo(*pAllocation, pAllocationInfo);</div>
+<div class="line"><a name="l17816"></a><span class="lineno">17816</span>&#160;    }</div>
+<div class="line"><a name="l17817"></a><span class="lineno">17817</span>&#160; </div>
+<div class="line"><a name="l17818"></a><span class="lineno">17818</span>&#160;    <span class="keywordflow">return</span> result;</div>
+<div class="line"><a name="l17819"></a><span class="lineno">17819</span>&#160;}</div>
+<div class="line"><a name="l17820"></a><span class="lineno">17820</span>&#160; </div>
+<div class="line"><a name="l17821"></a><span class="lineno">17821</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a11f0fbc034fa81a4efedd73d61ce7568">vmaFreeMemory</a>(</div>
+<div class="line"><a name="l17822"></a><span class="lineno">17822</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l17823"></a><span class="lineno">17823</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation)</div>
+<div class="line"><a name="l17824"></a><span class="lineno">17824</span>&#160;{</div>
+<div class="line"><a name="l17825"></a><span class="lineno">17825</span>&#160;    VMA_ASSERT(allocator);</div>
+<div class="line"><a name="l17826"></a><span class="lineno">17826</span>&#160;    </div>
+<div class="line"><a name="l17827"></a><span class="lineno">17827</span>&#160;    <span class="keywordflow">if</span>(allocation == VK_NULL_HANDLE)</div>
+<div class="line"><a name="l17828"></a><span class="lineno">17828</span>&#160;    {</div>
+<div class="line"><a name="l17829"></a><span class="lineno">17829</span>&#160;        <span class="keywordflow">return</span>;</div>
+<div class="line"><a name="l17830"></a><span class="lineno">17830</span>&#160;    }</div>
+<div class="line"><a name="l17831"></a><span class="lineno">17831</span>&#160;    </div>
+<div class="line"><a name="l17832"></a><span class="lineno">17832</span>&#160;    VMA_DEBUG_LOG(<span class="stringliteral">&quot;vmaFreeMemory&quot;</span>);</div>
+<div class="line"><a name="l17833"></a><span class="lineno">17833</span>&#160;    </div>
+<div class="line"><a name="l17834"></a><span class="lineno">17834</span>&#160;    VMA_DEBUG_GLOBAL_MUTEX_LOCK</div>
+<div class="line"><a name="l17835"></a><span class="lineno">17835</span>&#160; </div>
+<div class="line"><a name="l17836"></a><span class="lineno">17836</span>&#160;<span class="preprocessor">#if VMA_RECORDING_ENABLED</span></div>
+<div class="line"><a name="l17837"></a><span class="lineno">17837</span>&#160;    <span class="keywordflow">if</span>(allocator-&gt;GetRecorder() != VMA_NULL)</div>
+<div class="line"><a name="l17838"></a><span class="lineno">17838</span>&#160;    {</div>
+<div class="line"><a name="l17839"></a><span class="lineno">17839</span>&#160;        allocator-&gt;GetRecorder()-&gt;RecordFreeMemory(</div>
+<div class="line"><a name="l17840"></a><span class="lineno">17840</span>&#160;            allocator-&gt;GetCurrentFrameIndex(),</div>
+<div class="line"><a name="l17841"></a><span class="lineno">17841</span>&#160;            allocation);</div>
+<div class="line"><a name="l17842"></a><span class="lineno">17842</span>&#160;    }</div>
+<div class="line"><a name="l17843"></a><span class="lineno">17843</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l17844"></a><span class="lineno">17844</span>&#160;    </div>
+<div class="line"><a name="l17845"></a><span class="lineno">17845</span>&#160;    allocator-&gt;FreeMemory(</div>
+<div class="line"><a name="l17846"></a><span class="lineno">17846</span>&#160;        1, <span class="comment">// allocationCount</span></div>
+<div class="line"><a name="l17847"></a><span class="lineno">17847</span>&#160;        &amp;allocation);</div>
+<div class="line"><a name="l17848"></a><span class="lineno">17848</span>&#160;}</div>
+<div class="line"><a name="l17849"></a><span class="lineno">17849</span>&#160; </div>
+<div class="line"><a name="l17850"></a><span class="lineno">17850</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#ab9e709de044c5d8476bea77a4e755840">vmaFreeMemoryPages</a>(</div>
+<div class="line"><a name="l17851"></a><span class="lineno">17851</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l17852"></a><span class="lineno">17852</span>&#160;    <span class="keywordtype">size_t</span> allocationCount,</div>
+<div class="line"><a name="l17853"></a><span class="lineno">17853</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocations)</div>
+<div class="line"><a name="l17854"></a><span class="lineno">17854</span>&#160;{</div>
+<div class="line"><a name="l17855"></a><span class="lineno">17855</span>&#160;    <span class="keywordflow">if</span>(allocationCount == 0)</div>
+<div class="line"><a name="l17856"></a><span class="lineno">17856</span>&#160;    {</div>
+<div class="line"><a name="l17857"></a><span class="lineno">17857</span>&#160;        <span class="keywordflow">return</span>;</div>
+<div class="line"><a name="l17858"></a><span class="lineno">17858</span>&#160;    }</div>
+<div class="line"><a name="l17859"></a><span class="lineno">17859</span>&#160; </div>
+<div class="line"><a name="l17860"></a><span class="lineno">17860</span>&#160;    VMA_ASSERT(allocator);</div>
+<div class="line"><a name="l17861"></a><span class="lineno">17861</span>&#160;    </div>
+<div class="line"><a name="l17862"></a><span class="lineno">17862</span>&#160;    VMA_DEBUG_LOG(<span class="stringliteral">&quot;vmaFreeMemoryPages&quot;</span>);</div>
+<div class="line"><a name="l17863"></a><span class="lineno">17863</span>&#160;    </div>
+<div class="line"><a name="l17864"></a><span class="lineno">17864</span>&#160;    VMA_DEBUG_GLOBAL_MUTEX_LOCK</div>
+<div class="line"><a name="l17865"></a><span class="lineno">17865</span>&#160; </div>
+<div class="line"><a name="l17866"></a><span class="lineno">17866</span>&#160;<span class="preprocessor">#if VMA_RECORDING_ENABLED</span></div>
+<div class="line"><a name="l17867"></a><span class="lineno">17867</span>&#160;    <span class="keywordflow">if</span>(allocator-&gt;GetRecorder() != VMA_NULL)</div>
+<div class="line"><a name="l17868"></a><span class="lineno">17868</span>&#160;    {</div>
+<div class="line"><a name="l17869"></a><span class="lineno">17869</span>&#160;        allocator-&gt;GetRecorder()-&gt;RecordFreeMemoryPages(</div>
+<div class="line"><a name="l17870"></a><span class="lineno">17870</span>&#160;            allocator-&gt;GetCurrentFrameIndex(),</div>
+<div class="line"><a name="l17871"></a><span class="lineno">17871</span>&#160;            (uint64_t)allocationCount,</div>
+<div class="line"><a name="l17872"></a><span class="lineno">17872</span>&#160;            pAllocations);</div>
+<div class="line"><a name="l17873"></a><span class="lineno">17873</span>&#160;    }</div>
+<div class="line"><a name="l17874"></a><span class="lineno">17874</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l17875"></a><span class="lineno">17875</span>&#160;    </div>
+<div class="line"><a name="l17876"></a><span class="lineno">17876</span>&#160;    allocator-&gt;FreeMemory(allocationCount, pAllocations);</div>
+<div class="line"><a name="l17877"></a><span class="lineno">17877</span>&#160;}</div>
+<div class="line"><a name="l17878"></a><span class="lineno">17878</span>&#160; </div>
+<div class="line"><a name="l17879"></a><span class="lineno">17879</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a0ff488958ca72b28e545880463cb8696">vmaResizeAllocation</a>(</div>
+<div class="line"><a name="l17880"></a><span class="lineno">17880</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l17881"></a><span class="lineno">17881</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation,</div>
+<div class="line"><a name="l17882"></a><span class="lineno">17882</span>&#160;    VkDeviceSize newSize)</div>
+<div class="line"><a name="l17883"></a><span class="lineno">17883</span>&#160;{</div>
+<div class="line"><a name="l17884"></a><span class="lineno">17884</span>&#160;    VMA_ASSERT(allocator &amp;&amp; allocation);</div>
+<div class="line"><a name="l17885"></a><span class="lineno">17885</span>&#160;    </div>
+<div class="line"><a name="l17886"></a><span class="lineno">17886</span>&#160;    VMA_DEBUG_LOG(<span class="stringliteral">&quot;vmaResizeAllocation&quot;</span>);</div>
+<div class="line"><a name="l17887"></a><span class="lineno">17887</span>&#160;    </div>
+<div class="line"><a name="l17888"></a><span class="lineno">17888</span>&#160;    VMA_DEBUG_GLOBAL_MUTEX_LOCK</div>
+<div class="line"><a name="l17889"></a><span class="lineno">17889</span>&#160; </div>
+<div class="line"><a name="l17890"></a><span class="lineno">17890</span>&#160;    <span class="keywordflow">return</span> allocator-&gt;ResizeAllocation(allocation, newSize);</div>
+<div class="line"><a name="l17891"></a><span class="lineno">17891</span>&#160;}</div>
+<div class="line"><a name="l17892"></a><span class="lineno">17892</span>&#160; </div>
+<div class="line"><a name="l17893"></a><span class="lineno">17893</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b">vmaGetAllocationInfo</a>(</div>
+<div class="line"><a name="l17894"></a><span class="lineno">17894</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l17895"></a><span class="lineno">17895</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation,</div>
+<div class="line"><a name="l17896"></a><span class="lineno">17896</span>&#160;    <a class="code" href="struct_vma_allocation_info.html">VmaAllocationInfo</a>* pAllocationInfo)</div>
+<div class="line"><a name="l17897"></a><span class="lineno">17897</span>&#160;{</div>
+<div class="line"><a name="l17898"></a><span class="lineno">17898</span>&#160;    VMA_ASSERT(allocator &amp;&amp; allocation &amp;&amp; pAllocationInfo);</div>
+<div class="line"><a name="l17899"></a><span class="lineno">17899</span>&#160; </div>
+<div class="line"><a name="l17900"></a><span class="lineno">17900</span>&#160;    VMA_DEBUG_GLOBAL_MUTEX_LOCK</div>
+<div class="line"><a name="l17901"></a><span class="lineno">17901</span>&#160; </div>
+<div class="line"><a name="l17902"></a><span class="lineno">17902</span>&#160;<span class="preprocessor">#if VMA_RECORDING_ENABLED</span></div>
+<div class="line"><a name="l17903"></a><span class="lineno">17903</span>&#160;    <span class="keywordflow">if</span>(allocator-&gt;GetRecorder() != VMA_NULL)</div>
+<div class="line"><a name="l17904"></a><span class="lineno">17904</span>&#160;    {</div>
+<div class="line"><a name="l17905"></a><span class="lineno">17905</span>&#160;        allocator-&gt;GetRecorder()-&gt;RecordGetAllocationInfo(</div>
+<div class="line"><a name="l17906"></a><span class="lineno">17906</span>&#160;            allocator-&gt;GetCurrentFrameIndex(),</div>
+<div class="line"><a name="l17907"></a><span class="lineno">17907</span>&#160;            allocation);</div>
+<div class="line"><a name="l17908"></a><span class="lineno">17908</span>&#160;    }</div>
+<div class="line"><a name="l17909"></a><span class="lineno">17909</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l17910"></a><span class="lineno">17910</span>&#160; </div>
+<div class="line"><a name="l17911"></a><span class="lineno">17911</span>&#160;    allocator-&gt;GetAllocationInfo(allocation, pAllocationInfo);</div>
+<div class="line"><a name="l17912"></a><span class="lineno">17912</span>&#160;}</div>
+<div class="line"><a name="l17913"></a><span class="lineno">17913</span>&#160; </div>
+<div class="line"><a name="l17914"></a><span class="lineno">17914</span>&#160;VMA_CALL_PRE VkBool32 VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a43d8ba9673c846f049089a5029d5c73a">vmaTouchAllocation</a>(</div>
+<div class="line"><a name="l17915"></a><span class="lineno">17915</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l17916"></a><span class="lineno">17916</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation)</div>
+<div class="line"><a name="l17917"></a><span class="lineno">17917</span>&#160;{</div>
+<div class="line"><a name="l17918"></a><span class="lineno">17918</span>&#160;    VMA_ASSERT(allocator &amp;&amp; allocation);</div>
+<div class="line"><a name="l17919"></a><span class="lineno">17919</span>&#160; </div>
+<div class="line"><a name="l17920"></a><span class="lineno">17920</span>&#160;    VMA_DEBUG_GLOBAL_MUTEX_LOCK</div>
+<div class="line"><a name="l17921"></a><span class="lineno">17921</span>&#160; </div>
+<div class="line"><a name="l17922"></a><span class="lineno">17922</span>&#160;<span class="preprocessor">#if VMA_RECORDING_ENABLED</span></div>
+<div class="line"><a name="l17923"></a><span class="lineno">17923</span>&#160;    <span class="keywordflow">if</span>(allocator-&gt;GetRecorder() != VMA_NULL)</div>
+<div class="line"><a name="l17924"></a><span class="lineno">17924</span>&#160;    {</div>
+<div class="line"><a name="l17925"></a><span class="lineno">17925</span>&#160;        allocator-&gt;GetRecorder()-&gt;RecordTouchAllocation(</div>
+<div class="line"><a name="l17926"></a><span class="lineno">17926</span>&#160;            allocator-&gt;GetCurrentFrameIndex(),</div>
+<div class="line"><a name="l17927"></a><span class="lineno">17927</span>&#160;            allocation);</div>
+<div class="line"><a name="l17928"></a><span class="lineno">17928</span>&#160;    }</div>
+<div class="line"><a name="l17929"></a><span class="lineno">17929</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l17930"></a><span class="lineno">17930</span>&#160; </div>
+<div class="line"><a name="l17931"></a><span class="lineno">17931</span>&#160;    <span class="keywordflow">return</span> allocator-&gt;TouchAllocation(allocation);</div>
+<div class="line"><a name="l17932"></a><span class="lineno">17932</span>&#160;}</div>
+<div class="line"><a name="l17933"></a><span class="lineno">17933</span>&#160; </div>
+<div class="line"><a name="l17934"></a><span class="lineno">17934</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#af9147d31ffc11d62fc187bde283ed14f">vmaSetAllocationUserData</a>(</div>
+<div class="line"><a name="l17935"></a><span class="lineno">17935</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l17936"></a><span class="lineno">17936</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation,</div>
+<div class="line"><a name="l17937"></a><span class="lineno">17937</span>&#160;    <span class="keywordtype">void</span>* pUserData)</div>
+<div class="line"><a name="l17938"></a><span class="lineno">17938</span>&#160;{</div>
+<div class="line"><a name="l17939"></a><span class="lineno">17939</span>&#160;    VMA_ASSERT(allocator &amp;&amp; allocation);</div>
+<div class="line"><a name="l17940"></a><span class="lineno">17940</span>&#160; </div>
+<div class="line"><a name="l17941"></a><span class="lineno">17941</span>&#160;    VMA_DEBUG_GLOBAL_MUTEX_LOCK</div>
+<div class="line"><a name="l17942"></a><span class="lineno">17942</span>&#160; </div>
+<div class="line"><a name="l17943"></a><span class="lineno">17943</span>&#160;    allocation-&gt;SetUserData(allocator, pUserData);</div>
+<div class="line"><a name="l17944"></a><span class="lineno">17944</span>&#160; </div>
+<div class="line"><a name="l17945"></a><span class="lineno">17945</span>&#160;<span class="preprocessor">#if VMA_RECORDING_ENABLED</span></div>
+<div class="line"><a name="l17946"></a><span class="lineno">17946</span>&#160;    <span class="keywordflow">if</span>(allocator-&gt;GetRecorder() != VMA_NULL)</div>
+<div class="line"><a name="l17947"></a><span class="lineno">17947</span>&#160;    {</div>
+<div class="line"><a name="l17948"></a><span class="lineno">17948</span>&#160;        allocator-&gt;GetRecorder()-&gt;RecordSetAllocationUserData(</div>
+<div class="line"><a name="l17949"></a><span class="lineno">17949</span>&#160;            allocator-&gt;GetCurrentFrameIndex(),</div>
+<div class="line"><a name="l17950"></a><span class="lineno">17950</span>&#160;            allocation,</div>
+<div class="line"><a name="l17951"></a><span class="lineno">17951</span>&#160;            pUserData);</div>
+<div class="line"><a name="l17952"></a><span class="lineno">17952</span>&#160;    }</div>
+<div class="line"><a name="l17953"></a><span class="lineno">17953</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l17954"></a><span class="lineno">17954</span>&#160;}</div>
+<div class="line"><a name="l17955"></a><span class="lineno">17955</span>&#160; </div>
+<div class="line"><a name="l17956"></a><span class="lineno">17956</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#ae5c9657d9e94756269145b01c05d16f1">vmaCreateLostAllocation</a>(</div>
+<div class="line"><a name="l17957"></a><span class="lineno">17957</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l17958"></a><span class="lineno">17958</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocation)</div>
+<div class="line"><a name="l17959"></a><span class="lineno">17959</span>&#160;{</div>
+<div class="line"><a name="l17960"></a><span class="lineno">17960</span>&#160;    VMA_ASSERT(allocator &amp;&amp; pAllocation);</div>
+<div class="line"><a name="l17961"></a><span class="lineno">17961</span>&#160; </div>
+<div class="line"><a name="l17962"></a><span class="lineno">17962</span>&#160;    VMA_DEBUG_GLOBAL_MUTEX_LOCK;</div>
+<div class="line"><a name="l17963"></a><span class="lineno">17963</span>&#160; </div>
+<div class="line"><a name="l17964"></a><span class="lineno">17964</span>&#160;    allocator-&gt;CreateLostAllocation(pAllocation);</div>
+<div class="line"><a name="l17965"></a><span class="lineno">17965</span>&#160; </div>
+<div class="line"><a name="l17966"></a><span class="lineno">17966</span>&#160;<span class="preprocessor">#if VMA_RECORDING_ENABLED</span></div>
+<div class="line"><a name="l17967"></a><span class="lineno">17967</span>&#160;    <span class="keywordflow">if</span>(allocator-&gt;GetRecorder() != VMA_NULL)</div>
+<div class="line"><a name="l17968"></a><span class="lineno">17968</span>&#160;    {</div>
+<div class="line"><a name="l17969"></a><span class="lineno">17969</span>&#160;        allocator-&gt;GetRecorder()-&gt;RecordCreateLostAllocation(</div>
+<div class="line"><a name="l17970"></a><span class="lineno">17970</span>&#160;            allocator-&gt;GetCurrentFrameIndex(),</div>
+<div class="line"><a name="l17971"></a><span class="lineno">17971</span>&#160;            *pAllocation);</div>
+<div class="line"><a name="l17972"></a><span class="lineno">17972</span>&#160;    }</div>
+<div class="line"><a name="l17973"></a><span class="lineno">17973</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l17974"></a><span class="lineno">17974</span>&#160;}</div>
+<div class="line"><a name="l17975"></a><span class="lineno">17975</span>&#160; </div>
+<div class="line"><a name="l17976"></a><span class="lineno">17976</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#ad5bd1243512d099706de88168992f069">vmaMapMemory</a>(</div>
+<div class="line"><a name="l17977"></a><span class="lineno">17977</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l17978"></a><span class="lineno">17978</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation,</div>
+<div class="line"><a name="l17979"></a><span class="lineno">17979</span>&#160;    <span class="keywordtype">void</span>** ppData)</div>
+<div class="line"><a name="l17980"></a><span class="lineno">17980</span>&#160;{</div>
+<div class="line"><a name="l17981"></a><span class="lineno">17981</span>&#160;    VMA_ASSERT(allocator &amp;&amp; allocation &amp;&amp; ppData);</div>
+<div class="line"><a name="l17982"></a><span class="lineno">17982</span>&#160; </div>
+<div class="line"><a name="l17983"></a><span class="lineno">17983</span>&#160;    VMA_DEBUG_GLOBAL_MUTEX_LOCK</div>
+<div class="line"><a name="l17984"></a><span class="lineno">17984</span>&#160; </div>
+<div class="line"><a name="l17985"></a><span class="lineno">17985</span>&#160;    VkResult res = allocator-&gt;Map(allocation, ppData);</div>
+<div class="line"><a name="l17986"></a><span class="lineno">17986</span>&#160; </div>
+<div class="line"><a name="l17987"></a><span class="lineno">17987</span>&#160;<span class="preprocessor">#if VMA_RECORDING_ENABLED</span></div>
+<div class="line"><a name="l17988"></a><span class="lineno">17988</span>&#160;    <span class="keywordflow">if</span>(allocator-&gt;GetRecorder() != VMA_NULL)</div>
+<div class="line"><a name="l17989"></a><span class="lineno">17989</span>&#160;    {</div>
+<div class="line"><a name="l17990"></a><span class="lineno">17990</span>&#160;        allocator-&gt;GetRecorder()-&gt;RecordMapMemory(</div>
+<div class="line"><a name="l17991"></a><span class="lineno">17991</span>&#160;            allocator-&gt;GetCurrentFrameIndex(),</div>
+<div class="line"><a name="l17992"></a><span class="lineno">17992</span>&#160;            allocation);</div>
+<div class="line"><a name="l17993"></a><span class="lineno">17993</span>&#160;    }</div>
+<div class="line"><a name="l17994"></a><span class="lineno">17994</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l17995"></a><span class="lineno">17995</span>&#160; </div>
+<div class="line"><a name="l17996"></a><span class="lineno">17996</span>&#160;    <span class="keywordflow">return</span> res;</div>
+<div class="line"><a name="l17997"></a><span class="lineno">17997</span>&#160;}</div>
+<div class="line"><a name="l17998"></a><span class="lineno">17998</span>&#160; </div>
+<div class="line"><a name="l17999"></a><span class="lineno">17999</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a9bc268595cb33f6ec4d519cfce81ff45">vmaUnmapMemory</a>(</div>
+<div class="line"><a name="l18000"></a><span class="lineno">18000</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l18001"></a><span class="lineno">18001</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation)</div>
+<div class="line"><a name="l18002"></a><span class="lineno">18002</span>&#160;{</div>
+<div class="line"><a name="l18003"></a><span class="lineno">18003</span>&#160;    VMA_ASSERT(allocator &amp;&amp; allocation);</div>
+<div class="line"><a name="l18004"></a><span class="lineno">18004</span>&#160; </div>
+<div class="line"><a name="l18005"></a><span class="lineno">18005</span>&#160;    VMA_DEBUG_GLOBAL_MUTEX_LOCK</div>
+<div class="line"><a name="l18006"></a><span class="lineno">18006</span>&#160; </div>
+<div class="line"><a name="l18007"></a><span class="lineno">18007</span>&#160;<span class="preprocessor">#if VMA_RECORDING_ENABLED</span></div>
+<div class="line"><a name="l18008"></a><span class="lineno">18008</span>&#160;    <span class="keywordflow">if</span>(allocator-&gt;GetRecorder() != VMA_NULL)</div>
+<div class="line"><a name="l18009"></a><span class="lineno">18009</span>&#160;    {</div>
+<div class="line"><a name="l18010"></a><span class="lineno">18010</span>&#160;        allocator-&gt;GetRecorder()-&gt;RecordUnmapMemory(</div>
+<div class="line"><a name="l18011"></a><span class="lineno">18011</span>&#160;            allocator-&gt;GetCurrentFrameIndex(),</div>
+<div class="line"><a name="l18012"></a><span class="lineno">18012</span>&#160;            allocation);</div>
+<div class="line"><a name="l18013"></a><span class="lineno">18013</span>&#160;    }</div>
+<div class="line"><a name="l18014"></a><span class="lineno">18014</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l18015"></a><span class="lineno">18015</span>&#160; </div>
+<div class="line"><a name="l18016"></a><span class="lineno">18016</span>&#160;    allocator-&gt;Unmap(allocation);</div>
+<div class="line"><a name="l18017"></a><span class="lineno">18017</span>&#160;}</div>
+<div class="line"><a name="l18018"></a><span class="lineno">18018</span>&#160; </div>
+<div class="line"><a name="l18019"></a><span class="lineno">18019</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#abc34ee6f021f459aff885f3758c435de">vmaFlushAllocation</a>(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator, <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation, VkDeviceSize offset, VkDeviceSize size)</div>
+<div class="line"><a name="l18020"></a><span class="lineno">18020</span>&#160;{</div>
+<div class="line"><a name="l18021"></a><span class="lineno">18021</span>&#160;    VMA_ASSERT(allocator &amp;&amp; allocation);</div>
+<div class="line"><a name="l18022"></a><span class="lineno">18022</span>&#160; </div>
+<div class="line"><a name="l18023"></a><span class="lineno">18023</span>&#160;    VMA_DEBUG_LOG(<span class="stringliteral">&quot;vmaFlushAllocation&quot;</span>);</div>
+<div class="line"><a name="l18024"></a><span class="lineno">18024</span>&#160; </div>
+<div class="line"><a name="l18025"></a><span class="lineno">18025</span>&#160;    VMA_DEBUG_GLOBAL_MUTEX_LOCK</div>
+<div class="line"><a name="l18026"></a><span class="lineno">18026</span>&#160; </div>
+<div class="line"><a name="l18027"></a><span class="lineno">18027</span>&#160;    allocator-&gt;FlushOrInvalidateAllocation(allocation, offset, size, VMA_CACHE_FLUSH);</div>
+<div class="line"><a name="l18028"></a><span class="lineno">18028</span>&#160; </div>
+<div class="line"><a name="l18029"></a><span class="lineno">18029</span>&#160;<span class="preprocessor">#if VMA_RECORDING_ENABLED</span></div>
+<div class="line"><a name="l18030"></a><span class="lineno">18030</span>&#160;    <span class="keywordflow">if</span>(allocator-&gt;GetRecorder() != VMA_NULL)</div>
+<div class="line"><a name="l18031"></a><span class="lineno">18031</span>&#160;    {</div>
+<div class="line"><a name="l18032"></a><span class="lineno">18032</span>&#160;        allocator-&gt;GetRecorder()-&gt;RecordFlushAllocation(</div>
+<div class="line"><a name="l18033"></a><span class="lineno">18033</span>&#160;            allocator-&gt;GetCurrentFrameIndex(),</div>
+<div class="line"><a name="l18034"></a><span class="lineno">18034</span>&#160;            allocation, offset, size);</div>
+<div class="line"><a name="l18035"></a><span class="lineno">18035</span>&#160;    }</div>
+<div class="line"><a name="l18036"></a><span class="lineno">18036</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l18037"></a><span class="lineno">18037</span>&#160;}</div>
+<div class="line"><a name="l18038"></a><span class="lineno">18038</span>&#160; </div>
+<div class="line"><a name="l18039"></a><span class="lineno">18039</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a0d0eb0c1102268fa9a476d12ecbe4006">vmaInvalidateAllocation</a>(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator, <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation, VkDeviceSize offset, VkDeviceSize size)</div>
+<div class="line"><a name="l18040"></a><span class="lineno">18040</span>&#160;{</div>
+<div class="line"><a name="l18041"></a><span class="lineno">18041</span>&#160;    VMA_ASSERT(allocator &amp;&amp; allocation);</div>
+<div class="line"><a name="l18042"></a><span class="lineno">18042</span>&#160; </div>
+<div class="line"><a name="l18043"></a><span class="lineno">18043</span>&#160;    VMA_DEBUG_LOG(<span class="stringliteral">&quot;vmaInvalidateAllocation&quot;</span>);</div>
+<div class="line"><a name="l18044"></a><span class="lineno">18044</span>&#160; </div>
+<div class="line"><a name="l18045"></a><span class="lineno">18045</span>&#160;    VMA_DEBUG_GLOBAL_MUTEX_LOCK</div>
+<div class="line"><a name="l18046"></a><span class="lineno">18046</span>&#160; </div>
+<div class="line"><a name="l18047"></a><span class="lineno">18047</span>&#160;    allocator-&gt;FlushOrInvalidateAllocation(allocation, offset, size, VMA_CACHE_INVALIDATE);</div>
+<div class="line"><a name="l18048"></a><span class="lineno">18048</span>&#160; </div>
+<div class="line"><a name="l18049"></a><span class="lineno">18049</span>&#160;<span class="preprocessor">#if VMA_RECORDING_ENABLED</span></div>
+<div class="line"><a name="l18050"></a><span class="lineno">18050</span>&#160;    <span class="keywordflow">if</span>(allocator-&gt;GetRecorder() != VMA_NULL)</div>
+<div class="line"><a name="l18051"></a><span class="lineno">18051</span>&#160;    {</div>
+<div class="line"><a name="l18052"></a><span class="lineno">18052</span>&#160;        allocator-&gt;GetRecorder()-&gt;RecordInvalidateAllocation(</div>
+<div class="line"><a name="l18053"></a><span class="lineno">18053</span>&#160;            allocator-&gt;GetCurrentFrameIndex(),</div>
+<div class="line"><a name="l18054"></a><span class="lineno">18054</span>&#160;            allocation, offset, size);</div>
+<div class="line"><a name="l18055"></a><span class="lineno">18055</span>&#160;    }</div>
+<div class="line"><a name="l18056"></a><span class="lineno">18056</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l18057"></a><span class="lineno">18057</span>&#160;}</div>
+<div class="line"><a name="l18058"></a><span class="lineno">18058</span>&#160; </div>
+<div class="line"><a name="l18059"></a><span class="lineno">18059</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a49329a7f030dafcf82f7b73334c22e98">vmaCheckCorruption</a>(<a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator, uint32_t memoryTypeBits)</div>
+<div class="line"><a name="l18060"></a><span class="lineno">18060</span>&#160;{</div>
+<div class="line"><a name="l18061"></a><span class="lineno">18061</span>&#160;    VMA_ASSERT(allocator);</div>
+<div class="line"><a name="l18062"></a><span class="lineno">18062</span>&#160; </div>
+<div class="line"><a name="l18063"></a><span class="lineno">18063</span>&#160;    VMA_DEBUG_LOG(<span class="stringliteral">&quot;vmaCheckCorruption&quot;</span>);</div>
+<div class="line"><a name="l18064"></a><span class="lineno">18064</span>&#160; </div>
+<div class="line"><a name="l18065"></a><span class="lineno">18065</span>&#160;    VMA_DEBUG_GLOBAL_MUTEX_LOCK</div>
+<div class="line"><a name="l18066"></a><span class="lineno">18066</span>&#160; </div>
+<div class="line"><a name="l18067"></a><span class="lineno">18067</span>&#160;    <span class="keywordflow">return</span> allocator-&gt;CheckCorruption(memoryTypeBits);</div>
+<div class="line"><a name="l18068"></a><span class="lineno">18068</span>&#160;}</div>
+<div class="line"><a name="l18069"></a><span class="lineno">18069</span>&#160; </div>
+<div class="line"><a name="l18070"></a><span class="lineno">18070</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a6aced90fcc7b39882b6654a740a0b9bb">vmaDefragment</a>(</div>
+<div class="line"><a name="l18071"></a><span class="lineno">18071</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l18072"></a><span class="lineno">18072</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocations,</div>
+<div class="line"><a name="l18073"></a><span class="lineno">18073</span>&#160;    <span class="keywordtype">size_t</span> allocationCount,</div>
+<div class="line"><a name="l18074"></a><span class="lineno">18074</span>&#160;    VkBool32* pAllocationsChanged,</div>
+<div class="line"><a name="l18075"></a><span class="lineno">18075</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_defragmentation_info.html">VmaDefragmentationInfo</a> *pDefragmentationInfo,</div>
+<div class="line"><a name="l18076"></a><span class="lineno">18076</span>&#160;    <a class="code" href="struct_vma_defragmentation_stats.html">VmaDefragmentationStats</a>* pDefragmentationStats)</div>
+<div class="line"><a name="l18077"></a><span class="lineno">18077</span>&#160;{</div>
+<div class="line"><a name="l18078"></a><span class="lineno">18078</span>&#160;    <span class="comment">// Deprecated interface, reimplemented using new one.</span></div>
+<div class="line"><a name="l18079"></a><span class="lineno">18079</span>&#160; </div>
+<div class="line"><a name="l18080"></a><span class="lineno">18080</span>&#160;    <a class="code" href="struct_vma_defragmentation_info2.html">VmaDefragmentationInfo2</a> info2 = {};</div>
+<div class="line"><a name="l18081"></a><span class="lineno">18081</span>&#160;    info2.<a class="code" href="struct_vma_defragmentation_info2.html#a3cf86ab32c1da779b4923d301a3056ba">allocationCount</a> = (uint32_t)allocationCount;</div>
+<div class="line"><a name="l18082"></a><span class="lineno">18082</span>&#160;    info2.<a class="code" href="struct_vma_defragmentation_info2.html#a8943f8d65969ce8e2189a1cdf3205e96">pAllocations</a> = pAllocations;</div>
+<div class="line"><a name="l18083"></a><span class="lineno">18083</span>&#160;    info2.<a class="code" href="struct_vma_defragmentation_info2.html#a76d51a644dc7f5405d0cdd0025ecd0cc">pAllocationsChanged</a> = pAllocationsChanged;</div>
+<div class="line"><a name="l18084"></a><span class="lineno">18084</span>&#160;    <span class="keywordflow">if</span>(pDefragmentationInfo != VMA_NULL)</div>
+<div class="line"><a name="l18085"></a><span class="lineno">18085</span>&#160;    {</div>
+<div class="line"><a name="l18086"></a><span class="lineno">18086</span>&#160;        info2.<a class="code" href="struct_vma_defragmentation_info2.html#a94c2c7223d52878445a8cccce396b671">maxCpuAllocationsToMove</a> = pDefragmentationInfo-&gt;<a class="code" href="struct_vma_defragmentation_info.html#aa7c7304e13c71f604c907196c4e28fbc">maxAllocationsToMove</a>;</div>
+<div class="line"><a name="l18087"></a><span class="lineno">18087</span>&#160;        info2.<a class="code" href="struct_vma_defragmentation_info2.html#af78e1ea40c22d85137b65f6b384a4d0a">maxCpuBytesToMove</a> = pDefragmentationInfo-&gt;<a class="code" href="struct_vma_defragmentation_info.html#acb311c940a777270e67e1b81c5ab6a1d">maxBytesToMove</a>;</div>
+<div class="line"><a name="l18088"></a><span class="lineno">18088</span>&#160;    }</div>
+<div class="line"><a name="l18089"></a><span class="lineno">18089</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l18090"></a><span class="lineno">18090</span>&#160;    {</div>
+<div class="line"><a name="l18091"></a><span class="lineno">18091</span>&#160;        info2.<a class="code" href="struct_vma_defragmentation_info2.html#a94c2c7223d52878445a8cccce396b671">maxCpuAllocationsToMove</a> = UINT32_MAX;</div>
+<div class="line"><a name="l18092"></a><span class="lineno">18092</span>&#160;        info2.<a class="code" href="struct_vma_defragmentation_info2.html#af78e1ea40c22d85137b65f6b384a4d0a">maxCpuBytesToMove</a> = VK_WHOLE_SIZE;</div>
+<div class="line"><a name="l18093"></a><span class="lineno">18093</span>&#160;    }</div>
+<div class="line"><a name="l18094"></a><span class="lineno">18094</span>&#160;    <span class="comment">// info2.flags, maxGpuAllocationsToMove, maxGpuBytesToMove, commandBuffer deliberately left zero.</span></div>
+<div class="line"><a name="l18095"></a><span class="lineno">18095</span>&#160; </div>
+<div class="line"><a name="l18096"></a><span class="lineno">18096</span>&#160;    <a class="code" href="struct_vma_defragmentation_context.html">VmaDefragmentationContext</a> ctx;</div>
+<div class="line"><a name="l18097"></a><span class="lineno">18097</span>&#160;    VkResult res = <a class="code" href="vk__mem__alloc_8h.html#a36ba776fd7fd5cb1e9359fdc0d8e6e8a">vmaDefragmentationBegin</a>(allocator, &amp;info2, pDefragmentationStats, &amp;ctx);</div>
+<div class="line"><a name="l18098"></a><span class="lineno">18098</span>&#160;    <span class="keywordflow">if</span>(res == VK_NOT_READY)</div>
+<div class="line"><a name="l18099"></a><span class="lineno">18099</span>&#160;    {</div>
+<div class="line"><a name="l18100"></a><span class="lineno">18100</span>&#160;        res = <a class="code" href="vk__mem__alloc_8h.html#a8774e20e91e245aae959ba63efa15dd2">vmaDefragmentationEnd</a>( allocator, ctx);</div>
+<div class="line"><a name="l18101"></a><span class="lineno">18101</span>&#160;    }</div>
+<div class="line"><a name="l18102"></a><span class="lineno">18102</span>&#160;    <span class="keywordflow">return</span> res;</div>
+<div class="line"><a name="l18103"></a><span class="lineno">18103</span>&#160;}</div>
+<div class="line"><a name="l18104"></a><span class="lineno">18104</span>&#160; </div>
+<div class="line"><a name="l18105"></a><span class="lineno">18105</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a36ba776fd7fd5cb1e9359fdc0d8e6e8a">vmaDefragmentationBegin</a>(</div>
+<div class="line"><a name="l18106"></a><span class="lineno">18106</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l18107"></a><span class="lineno">18107</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_defragmentation_info2.html">VmaDefragmentationInfo2</a>* pInfo,</div>
+<div class="line"><a name="l18108"></a><span class="lineno">18108</span>&#160;    <a class="code" href="struct_vma_defragmentation_stats.html">VmaDefragmentationStats</a>* pStats,</div>
+<div class="line"><a name="l18109"></a><span class="lineno">18109</span>&#160;    <a class="code" href="struct_vma_defragmentation_context.html">VmaDefragmentationContext</a> *pContext)</div>
+<div class="line"><a name="l18110"></a><span class="lineno">18110</span>&#160;{</div>
+<div class="line"><a name="l18111"></a><span class="lineno">18111</span>&#160;    VMA_ASSERT(allocator &amp;&amp; pInfo &amp;&amp; pContext);</div>
+<div class="line"><a name="l18112"></a><span class="lineno">18112</span>&#160; </div>
+<div class="line"><a name="l18113"></a><span class="lineno">18113</span>&#160;    <span class="comment">// Degenerate case: Nothing to defragment.</span></div>
+<div class="line"><a name="l18114"></a><span class="lineno">18114</span>&#160;    <span class="keywordflow">if</span>(pInfo-&gt;<a class="code" href="struct_vma_defragmentation_info2.html#a3cf86ab32c1da779b4923d301a3056ba">allocationCount</a> == 0 &amp;&amp; pInfo-&gt;<a class="code" href="struct_vma_defragmentation_info2.html#a7e70aa2a1081d849dcc7829b19d3ec9d">poolCount</a> == 0)</div>
+<div class="line"><a name="l18115"></a><span class="lineno">18115</span>&#160;    {</div>
+<div class="line"><a name="l18116"></a><span class="lineno">18116</span>&#160;        <span class="keywordflow">return</span> VK_SUCCESS;</div>
+<div class="line"><a name="l18117"></a><span class="lineno">18117</span>&#160;    }</div>
+<div class="line"><a name="l18118"></a><span class="lineno">18118</span>&#160; </div>
+<div class="line"><a name="l18119"></a><span class="lineno">18119</span>&#160;    VMA_ASSERT(pInfo-&gt;<a class="code" href="struct_vma_defragmentation_info2.html#a3cf86ab32c1da779b4923d301a3056ba">allocationCount</a> == 0 || pInfo-&gt;<a class="code" href="struct_vma_defragmentation_info2.html#a8943f8d65969ce8e2189a1cdf3205e96">pAllocations</a> != VMA_NULL);</div>
+<div class="line"><a name="l18120"></a><span class="lineno">18120</span>&#160;    VMA_ASSERT(pInfo-&gt;<a class="code" href="struct_vma_defragmentation_info2.html#a7e70aa2a1081d849dcc7829b19d3ec9d">poolCount</a> == 0 || pInfo-&gt;<a class="code" href="struct_vma_defragmentation_info2.html#a0b3effd57f3fcdeb2ed62210b4ef20e1">pPools</a> != VMA_NULL);</div>
+<div class="line"><a name="l18121"></a><span class="lineno">18121</span>&#160;    VMA_HEAVY_ASSERT(VmaValidatePointerArray(pInfo-&gt;<a class="code" href="struct_vma_defragmentation_info2.html#a3cf86ab32c1da779b4923d301a3056ba">allocationCount</a>, pInfo-&gt;<a class="code" href="struct_vma_defragmentation_info2.html#a8943f8d65969ce8e2189a1cdf3205e96">pAllocations</a>));</div>
+<div class="line"><a name="l18122"></a><span class="lineno">18122</span>&#160;    VMA_HEAVY_ASSERT(VmaValidatePointerArray(pInfo-&gt;<a class="code" href="struct_vma_defragmentation_info2.html#a7e70aa2a1081d849dcc7829b19d3ec9d">poolCount</a>, pInfo-&gt;<a class="code" href="struct_vma_defragmentation_info2.html#a0b3effd57f3fcdeb2ed62210b4ef20e1">pPools</a>));</div>
+<div class="line"><a name="l18123"></a><span class="lineno">18123</span>&#160; </div>
+<div class="line"><a name="l18124"></a><span class="lineno">18124</span>&#160;    VMA_DEBUG_LOG(<span class="stringliteral">&quot;vmaDefragmentationBegin&quot;</span>);</div>
+<div class="line"><a name="l18125"></a><span class="lineno">18125</span>&#160; </div>
+<div class="line"><a name="l18126"></a><span class="lineno">18126</span>&#160;    VMA_DEBUG_GLOBAL_MUTEX_LOCK</div>
+<div class="line"><a name="l18127"></a><span class="lineno">18127</span>&#160; </div>
+<div class="line"><a name="l18128"></a><span class="lineno">18128</span>&#160;    VkResult res = allocator-&gt;DefragmentationBegin(*pInfo, pStats, pContext);</div>
+<div class="line"><a name="l18129"></a><span class="lineno">18129</span>&#160; </div>
+<div class="line"><a name="l18130"></a><span class="lineno">18130</span>&#160;<span class="preprocessor">#if VMA_RECORDING_ENABLED</span></div>
+<div class="line"><a name="l18131"></a><span class="lineno">18131</span>&#160;    <span class="keywordflow">if</span>(allocator-&gt;GetRecorder() != VMA_NULL)</div>
+<div class="line"><a name="l18132"></a><span class="lineno">18132</span>&#160;    {</div>
+<div class="line"><a name="l18133"></a><span class="lineno">18133</span>&#160;        allocator-&gt;GetRecorder()-&gt;RecordDefragmentationBegin(</div>
+<div class="line"><a name="l18134"></a><span class="lineno">18134</span>&#160;            allocator-&gt;GetCurrentFrameIndex(), *pInfo, *pContext);</div>
+<div class="line"><a name="l18135"></a><span class="lineno">18135</span>&#160;    }</div>
+<div class="line"><a name="l18136"></a><span class="lineno">18136</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l18137"></a><span class="lineno">18137</span>&#160; </div>
+<div class="line"><a name="l18138"></a><span class="lineno">18138</span>&#160;    <span class="keywordflow">return</span> res;</div>
+<div class="line"><a name="l18139"></a><span class="lineno">18139</span>&#160;}</div>
+<div class="line"><a name="l18140"></a><span class="lineno">18140</span>&#160; </div>
+<div class="line"><a name="l18141"></a><span class="lineno">18141</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a8774e20e91e245aae959ba63efa15dd2">vmaDefragmentationEnd</a>(</div>
+<div class="line"><a name="l18142"></a><span class="lineno">18142</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l18143"></a><span class="lineno">18143</span>&#160;    <a class="code" href="struct_vma_defragmentation_context.html">VmaDefragmentationContext</a> context)</div>
+<div class="line"><a name="l18144"></a><span class="lineno">18144</span>&#160;{</div>
+<div class="line"><a name="l18145"></a><span class="lineno">18145</span>&#160;    VMA_ASSERT(allocator);</div>
+<div class="line"><a name="l18146"></a><span class="lineno">18146</span>&#160; </div>
+<div class="line"><a name="l18147"></a><span class="lineno">18147</span>&#160;    VMA_DEBUG_LOG(<span class="stringliteral">&quot;vmaDefragmentationEnd&quot;</span>);</div>
+<div class="line"><a name="l18148"></a><span class="lineno">18148</span>&#160; </div>
+<div class="line"><a name="l18149"></a><span class="lineno">18149</span>&#160;    <span class="keywordflow">if</span>(context != VK_NULL_HANDLE)</div>
+<div class="line"><a name="l18150"></a><span class="lineno">18150</span>&#160;    {</div>
+<div class="line"><a name="l18151"></a><span class="lineno">18151</span>&#160;        VMA_DEBUG_GLOBAL_MUTEX_LOCK</div>
+<div class="line"><a name="l18152"></a><span class="lineno">18152</span>&#160; </div>
+<div class="line"><a name="l18153"></a><span class="lineno">18153</span>&#160;<span class="preprocessor">#if VMA_RECORDING_ENABLED</span></div>
+<div class="line"><a name="l18154"></a><span class="lineno">18154</span>&#160;        <span class="keywordflow">if</span>(allocator-&gt;GetRecorder() != VMA_NULL)</div>
+<div class="line"><a name="l18155"></a><span class="lineno">18155</span>&#160;        {</div>
+<div class="line"><a name="l18156"></a><span class="lineno">18156</span>&#160;            allocator-&gt;GetRecorder()-&gt;RecordDefragmentationEnd(</div>
+<div class="line"><a name="l18157"></a><span class="lineno">18157</span>&#160;                allocator-&gt;GetCurrentFrameIndex(), context);</div>
+<div class="line"><a name="l18158"></a><span class="lineno">18158</span>&#160;        }</div>
+<div class="line"><a name="l18159"></a><span class="lineno">18159</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l18160"></a><span class="lineno">18160</span>&#160; </div>
+<div class="line"><a name="l18161"></a><span class="lineno">18161</span>&#160;        <span class="keywordflow">return</span> allocator-&gt;DefragmentationEnd(context);</div>
+<div class="line"><a name="l18162"></a><span class="lineno">18162</span>&#160;    }</div>
+<div class="line"><a name="l18163"></a><span class="lineno">18163</span>&#160;    <span class="keywordflow">else</span></div>
+<div class="line"><a name="l18164"></a><span class="lineno">18164</span>&#160;    {</div>
+<div class="line"><a name="l18165"></a><span class="lineno">18165</span>&#160;        <span class="keywordflow">return</span> VK_SUCCESS;</div>
+<div class="line"><a name="l18166"></a><span class="lineno">18166</span>&#160;    }</div>
+<div class="line"><a name="l18167"></a><span class="lineno">18167</span>&#160;}</div>
+<div class="line"><a name="l18168"></a><span class="lineno">18168</span>&#160; </div>
+<div class="line"><a name="l18169"></a><span class="lineno">18169</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#ac0f01545b6262f7d4d128fc8f8e5c77b">vmaBeginDefragmentationPass</a>(</div>
+<div class="line"><a name="l18170"></a><span class="lineno">18170</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l18171"></a><span class="lineno">18171</span>&#160;    <a class="code" href="struct_vma_defragmentation_context.html">VmaDefragmentationContext</a> context,</div>
+<div class="line"><a name="l18172"></a><span class="lineno">18172</span>&#160;    <a class="code" href="struct_vma_defragmentation_pass_info.html">VmaDefragmentationPassInfo</a>* pInfo</div>
+<div class="line"><a name="l18173"></a><span class="lineno">18173</span>&#160;    )</div>
+<div class="line"><a name="l18174"></a><span class="lineno">18174</span>&#160;{</div>
+<div class="line"><a name="l18175"></a><span class="lineno">18175</span>&#160;    VMA_ASSERT(allocator);</div>
+<div class="line"><a name="l18176"></a><span class="lineno">18176</span>&#160;    VMA_ASSERT(pInfo);</div>
+<div class="line"><a name="l18177"></a><span class="lineno">18177</span>&#160;    VMA_HEAVY_ASSERT(VmaValidatePointerArray(pInfo-&gt;<a class="code" href="struct_vma_defragmentation_pass_info.html#ac1086e657ba995f8d1f4e49b83dcfb6c">moveCount</a>, pInfo-&gt;<a class="code" href="struct_vma_defragmentation_pass_info.html#acbd42d4a3357999da130a95cd99a3792">pMoves</a>));</div>
+<div class="line"><a name="l18178"></a><span class="lineno">18178</span>&#160; </div>
+<div class="line"><a name="l18179"></a><span class="lineno">18179</span>&#160;    VMA_DEBUG_LOG(<span class="stringliteral">&quot;vmaBeginDefragmentationPass&quot;</span>);</div>
+<div class="line"><a name="l18180"></a><span class="lineno">18180</span>&#160; </div>
+<div class="line"><a name="l18181"></a><span class="lineno">18181</span>&#160;    VMA_DEBUG_GLOBAL_MUTEX_LOCK</div>
+<div class="line"><a name="l18182"></a><span class="lineno">18182</span>&#160; </div>
+<div class="line"><a name="l18183"></a><span class="lineno">18183</span>&#160;    <span class="keywordflow">if</span>(context == VK_NULL_HANDLE)</div>
+<div class="line"><a name="l18184"></a><span class="lineno">18184</span>&#160;    {</div>
+<div class="line"><a name="l18185"></a><span class="lineno">18185</span>&#160;        pInfo-&gt;<a class="code" href="struct_vma_defragmentation_pass_info.html#ac1086e657ba995f8d1f4e49b83dcfb6c">moveCount</a> = 0;</div>
+<div class="line"><a name="l18186"></a><span class="lineno">18186</span>&#160;        <span class="keywordflow">return</span> VK_SUCCESS;</div>
+<div class="line"><a name="l18187"></a><span class="lineno">18187</span>&#160;    }</div>
+<div class="line"><a name="l18188"></a><span class="lineno">18188</span>&#160; </div>
+<div class="line"><a name="l18189"></a><span class="lineno">18189</span>&#160;    <span class="keywordflow">return</span> allocator-&gt;DefragmentationPassBegin(pInfo, context);</div>
+<div class="line"><a name="l18190"></a><span class="lineno">18190</span>&#160;}</div>
+<div class="line"><a name="l18191"></a><span class="lineno">18191</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a1b9ffa538bed905af55c747cc48963bd">vmaEndDefragmentationPass</a>(</div>
+<div class="line"><a name="l18192"></a><span class="lineno">18192</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l18193"></a><span class="lineno">18193</span>&#160;    <a class="code" href="struct_vma_defragmentation_context.html">VmaDefragmentationContext</a> context)</div>
+<div class="line"><a name="l18194"></a><span class="lineno">18194</span>&#160;{</div>
+<div class="line"><a name="l18195"></a><span class="lineno">18195</span>&#160;    VMA_ASSERT(allocator);</div>
+<div class="line"><a name="l18196"></a><span class="lineno">18196</span>&#160; </div>
+<div class="line"><a name="l18197"></a><span class="lineno">18197</span>&#160;    VMA_DEBUG_LOG(<span class="stringliteral">&quot;vmaEndDefragmentationPass&quot;</span>);</div>
+<div class="line"><a name="l18198"></a><span class="lineno">18198</span>&#160;    VMA_DEBUG_GLOBAL_MUTEX_LOCK</div>
+<div class="line"><a name="l18199"></a><span class="lineno">18199</span>&#160; </div>
+<div class="line"><a name="l18200"></a><span class="lineno">18200</span>&#160;    <span class="keywordflow">if</span>(context == VK_NULL_HANDLE)</div>
+<div class="line"><a name="l18201"></a><span class="lineno">18201</span>&#160;        <span class="keywordflow">return</span> VK_SUCCESS;</div>
+<div class="line"><a name="l18202"></a><span class="lineno">18202</span>&#160; </div>
+<div class="line"><a name="l18203"></a><span class="lineno">18203</span>&#160;    <span class="keywordflow">return</span> allocator-&gt;DefragmentationPassEnd(context);</div>
+<div class="line"><a name="l18204"></a><span class="lineno">18204</span>&#160;}</div>
+<div class="line"><a name="l18205"></a><span class="lineno">18205</span>&#160; </div>
+<div class="line"><a name="l18206"></a><span class="lineno">18206</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a6b0929b914b60cf2d45cac4bf3547470">vmaBindBufferMemory</a>(</div>
+<div class="line"><a name="l18207"></a><span class="lineno">18207</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l18208"></a><span class="lineno">18208</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation,</div>
+<div class="line"><a name="l18209"></a><span class="lineno">18209</span>&#160;    VkBuffer buffer)</div>
+<div class="line"><a name="l18210"></a><span class="lineno">18210</span>&#160;{</div>
+<div class="line"><a name="l18211"></a><span class="lineno">18211</span>&#160;    VMA_ASSERT(allocator &amp;&amp; allocation &amp;&amp; buffer);</div>
+<div class="line"><a name="l18212"></a><span class="lineno">18212</span>&#160; </div>
+<div class="line"><a name="l18213"></a><span class="lineno">18213</span>&#160;    VMA_DEBUG_LOG(<span class="stringliteral">&quot;vmaBindBufferMemory&quot;</span>);</div>
+<div class="line"><a name="l18214"></a><span class="lineno">18214</span>&#160; </div>
+<div class="line"><a name="l18215"></a><span class="lineno">18215</span>&#160;    VMA_DEBUG_GLOBAL_MUTEX_LOCK</div>
+<div class="line"><a name="l18216"></a><span class="lineno">18216</span>&#160; </div>
+<div class="line"><a name="l18217"></a><span class="lineno">18217</span>&#160;    <span class="keywordflow">return</span> allocator-&gt;BindBufferMemory(allocation, 0, buffer, VMA_NULL);</div>
+<div class="line"><a name="l18218"></a><span class="lineno">18218</span>&#160;}</div>
+<div class="line"><a name="l18219"></a><span class="lineno">18219</span>&#160; </div>
+<div class="line"><a name="l18220"></a><span class="lineno">18220</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a927c944f45e0f2941182abb6f608e64a">vmaBindBufferMemory2</a>(</div>
+<div class="line"><a name="l18221"></a><span class="lineno">18221</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l18222"></a><span class="lineno">18222</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation,</div>
+<div class="line"><a name="l18223"></a><span class="lineno">18223</span>&#160;    VkDeviceSize allocationLocalOffset,</div>
+<div class="line"><a name="l18224"></a><span class="lineno">18224</span>&#160;    VkBuffer buffer,</div>
+<div class="line"><a name="l18225"></a><span class="lineno">18225</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">void</span>* pNext)</div>
+<div class="line"><a name="l18226"></a><span class="lineno">18226</span>&#160;{</div>
+<div class="line"><a name="l18227"></a><span class="lineno">18227</span>&#160;    VMA_ASSERT(allocator &amp;&amp; allocation &amp;&amp; buffer);</div>
+<div class="line"><a name="l18228"></a><span class="lineno">18228</span>&#160; </div>
+<div class="line"><a name="l18229"></a><span class="lineno">18229</span>&#160;    VMA_DEBUG_LOG(<span class="stringliteral">&quot;vmaBindBufferMemory2&quot;</span>);</div>
+<div class="line"><a name="l18230"></a><span class="lineno">18230</span>&#160; </div>
+<div class="line"><a name="l18231"></a><span class="lineno">18231</span>&#160;    VMA_DEBUG_GLOBAL_MUTEX_LOCK</div>
+<div class="line"><a name="l18232"></a><span class="lineno">18232</span>&#160; </div>
+<div class="line"><a name="l18233"></a><span class="lineno">18233</span>&#160;    <span class="keywordflow">return</span> allocator-&gt;BindBufferMemory(allocation, allocationLocalOffset, buffer, pNext);</div>
+<div class="line"><a name="l18234"></a><span class="lineno">18234</span>&#160;}</div>
+<div class="line"><a name="l18235"></a><span class="lineno">18235</span>&#160; </div>
+<div class="line"><a name="l18236"></a><span class="lineno">18236</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a3d3ca45799923aa5d138e9e5f9eb2da5">vmaBindImageMemory</a>(</div>
+<div class="line"><a name="l18237"></a><span class="lineno">18237</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l18238"></a><span class="lineno">18238</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation,</div>
+<div class="line"><a name="l18239"></a><span class="lineno">18239</span>&#160;    VkImage image)</div>
+<div class="line"><a name="l18240"></a><span class="lineno">18240</span>&#160;{</div>
+<div class="line"><a name="l18241"></a><span class="lineno">18241</span>&#160;    VMA_ASSERT(allocator &amp;&amp; allocation &amp;&amp; image);</div>
+<div class="line"><a name="l18242"></a><span class="lineno">18242</span>&#160; </div>
+<div class="line"><a name="l18243"></a><span class="lineno">18243</span>&#160;    VMA_DEBUG_LOG(<span class="stringliteral">&quot;vmaBindImageMemory&quot;</span>);</div>
+<div class="line"><a name="l18244"></a><span class="lineno">18244</span>&#160; </div>
+<div class="line"><a name="l18245"></a><span class="lineno">18245</span>&#160;    VMA_DEBUG_GLOBAL_MUTEX_LOCK</div>
+<div class="line"><a name="l18246"></a><span class="lineno">18246</span>&#160; </div>
+<div class="line"><a name="l18247"></a><span class="lineno">18247</span>&#160;    <span class="keywordflow">return</span> allocator-&gt;BindImageMemory(allocation, 0, image, VMA_NULL);</div>
+<div class="line"><a name="l18248"></a><span class="lineno">18248</span>&#160;}</div>
+<div class="line"><a name="l18249"></a><span class="lineno">18249</span>&#160; </div>
+<div class="line"><a name="l18250"></a><span class="lineno">18250</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#aa8251ee81b0045a443e35b8e8aa021bc">vmaBindImageMemory2</a>(</div>
+<div class="line"><a name="l18251"></a><span class="lineno">18251</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l18252"></a><span class="lineno">18252</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation,</div>
+<div class="line"><a name="l18253"></a><span class="lineno">18253</span>&#160;    VkDeviceSize allocationLocalOffset,</div>
+<div class="line"><a name="l18254"></a><span class="lineno">18254</span>&#160;    VkImage image,</div>
+<div class="line"><a name="l18255"></a><span class="lineno">18255</span>&#160;    <span class="keyword">const</span> <span class="keywordtype">void</span>* pNext)</div>
+<div class="line"><a name="l18256"></a><span class="lineno">18256</span>&#160;{</div>
+<div class="line"><a name="l18257"></a><span class="lineno">18257</span>&#160;    VMA_ASSERT(allocator &amp;&amp; allocation &amp;&amp; image);</div>
+<div class="line"><a name="l18258"></a><span class="lineno">18258</span>&#160; </div>
+<div class="line"><a name="l18259"></a><span class="lineno">18259</span>&#160;    VMA_DEBUG_LOG(<span class="stringliteral">&quot;vmaBindImageMemory2&quot;</span>);</div>
+<div class="line"><a name="l18260"></a><span class="lineno">18260</span>&#160; </div>
+<div class="line"><a name="l18261"></a><span class="lineno">18261</span>&#160;    VMA_DEBUG_GLOBAL_MUTEX_LOCK</div>
+<div class="line"><a name="l18262"></a><span class="lineno">18262</span>&#160; </div>
+<div class="line"><a name="l18263"></a><span class="lineno">18263</span>&#160;        <span class="keywordflow">return</span> allocator-&gt;BindImageMemory(allocation, allocationLocalOffset, image, pNext);</div>
+<div class="line"><a name="l18264"></a><span class="lineno">18264</span>&#160;}</div>
+<div class="line"><a name="l18265"></a><span class="lineno">18265</span>&#160; </div>
+<div class="line"><a name="l18266"></a><span class="lineno">18266</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer</a>(</div>
+<div class="line"><a name="l18267"></a><span class="lineno">18267</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l18268"></a><span class="lineno">18268</span>&#160;    <span class="keyword">const</span> VkBufferCreateInfo* pBufferCreateInfo,</div>
+<div class="line"><a name="l18269"></a><span class="lineno">18269</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>* pAllocationCreateInfo,</div>
+<div class="line"><a name="l18270"></a><span class="lineno">18270</span>&#160;    VkBuffer* pBuffer,</div>
+<div class="line"><a name="l18271"></a><span class="lineno">18271</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocation,</div>
+<div class="line"><a name="l18272"></a><span class="lineno">18272</span>&#160;    <a class="code" href="struct_vma_allocation_info.html">VmaAllocationInfo</a>* pAllocationInfo)</div>
+<div class="line"><a name="l18273"></a><span class="lineno">18273</span>&#160;{</div>
+<div class="line"><a name="l18274"></a><span class="lineno">18274</span>&#160;    VMA_ASSERT(allocator &amp;&amp; pBufferCreateInfo &amp;&amp; pAllocationCreateInfo &amp;&amp; pBuffer &amp;&amp; pAllocation);</div>
+<div class="line"><a name="l18275"></a><span class="lineno">18275</span>&#160; </div>
+<div class="line"><a name="l18276"></a><span class="lineno">18276</span>&#160;    <span class="keywordflow">if</span>(pBufferCreateInfo-&gt;size == 0)</div>
+<div class="line"><a name="l18277"></a><span class="lineno">18277</span>&#160;    {</div>
+<div class="line"><a name="l18278"></a><span class="lineno">18278</span>&#160;        <span class="keywordflow">return</span> VK_ERROR_VALIDATION_FAILED_EXT;</div>
+<div class="line"><a name="l18279"></a><span class="lineno">18279</span>&#160;    }</div>
+<div class="line"><a name="l18280"></a><span class="lineno">18280</span>&#160;    <span class="keywordflow">if</span>((pBufferCreateInfo-&gt;usage &amp; VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_COPY) != 0 &amp;&amp;</div>
+<div class="line"><a name="l18281"></a><span class="lineno">18281</span>&#160;        !allocator-&gt;m_UseKhrBufferDeviceAddress)</div>
+<div class="line"><a name="l18282"></a><span class="lineno">18282</span>&#160;    {</div>
+<div class="line"><a name="l18283"></a><span class="lineno">18283</span>&#160;        VMA_ASSERT(0 &amp;&amp; <span class="stringliteral">&quot;Creating a buffer with VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT is not valid if VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT was not used.&quot;</span>);</div>
+<div class="line"><a name="l18284"></a><span class="lineno">18284</span>&#160;        <span class="keywordflow">return</span> VK_ERROR_VALIDATION_FAILED_EXT;</div>
+<div class="line"><a name="l18285"></a><span class="lineno">18285</span>&#160;    }</div>
+<div class="line"><a name="l18286"></a><span class="lineno">18286</span>&#160;    </div>
+<div class="line"><a name="l18287"></a><span class="lineno">18287</span>&#160;    VMA_DEBUG_LOG(<span class="stringliteral">&quot;vmaCreateBuffer&quot;</span>);</div>
+<div class="line"><a name="l18288"></a><span class="lineno">18288</span>&#160;    </div>
+<div class="line"><a name="l18289"></a><span class="lineno">18289</span>&#160;    VMA_DEBUG_GLOBAL_MUTEX_LOCK</div>
+<div class="line"><a name="l18290"></a><span class="lineno">18290</span>&#160; </div>
+<div class="line"><a name="l18291"></a><span class="lineno">18291</span>&#160;    *pBuffer = VK_NULL_HANDLE;</div>
+<div class="line"><a name="l18292"></a><span class="lineno">18292</span>&#160;    *pAllocation = VK_NULL_HANDLE;</div>
+<div class="line"><a name="l18293"></a><span class="lineno">18293</span>&#160; </div>
+<div class="line"><a name="l18294"></a><span class="lineno">18294</span>&#160;    <span class="comment">// 1. Create VkBuffer.</span></div>
+<div class="line"><a name="l18295"></a><span class="lineno">18295</span>&#160;    VkResult res = (*allocator-&gt;GetVulkanFunctions().vkCreateBuffer)(</div>
+<div class="line"><a name="l18296"></a><span class="lineno">18296</span>&#160;        allocator-&gt;m_hDevice,</div>
+<div class="line"><a name="l18297"></a><span class="lineno">18297</span>&#160;        pBufferCreateInfo,</div>
+<div class="line"><a name="l18298"></a><span class="lineno">18298</span>&#160;        allocator-&gt;GetAllocationCallbacks(),</div>
+<div class="line"><a name="l18299"></a><span class="lineno">18299</span>&#160;        pBuffer);</div>
+<div class="line"><a name="l18300"></a><span class="lineno">18300</span>&#160;    <span class="keywordflow">if</span>(res &gt;= 0)</div>
+<div class="line"><a name="l18301"></a><span class="lineno">18301</span>&#160;    {</div>
+<div class="line"><a name="l18302"></a><span class="lineno">18302</span>&#160;        <span class="comment">// 2. vkGetBufferMemoryRequirements.</span></div>
+<div class="line"><a name="l18303"></a><span class="lineno">18303</span>&#160;        VkMemoryRequirements vkMemReq = {};</div>
+<div class="line"><a name="l18304"></a><span class="lineno">18304</span>&#160;        <span class="keywordtype">bool</span> requiresDedicatedAllocation = <span class="keyword">false</span>;</div>
+<div class="line"><a name="l18305"></a><span class="lineno">18305</span>&#160;        <span class="keywordtype">bool</span> prefersDedicatedAllocation  = <span class="keyword">false</span>;</div>
+<div class="line"><a name="l18306"></a><span class="lineno">18306</span>&#160;        allocator-&gt;GetBufferMemoryRequirements(*pBuffer, vkMemReq,</div>
+<div class="line"><a name="l18307"></a><span class="lineno">18307</span>&#160;            requiresDedicatedAllocation, prefersDedicatedAllocation);</div>
+<div class="line"><a name="l18308"></a><span class="lineno">18308</span>&#160; </div>
+<div class="line"><a name="l18309"></a><span class="lineno">18309</span>&#160;        <span class="comment">// 3. Allocate memory using allocator.</span></div>
+<div class="line"><a name="l18310"></a><span class="lineno">18310</span>&#160;        res = allocator-&gt;AllocateMemory(</div>
+<div class="line"><a name="l18311"></a><span class="lineno">18311</span>&#160;            vkMemReq,</div>
+<div class="line"><a name="l18312"></a><span class="lineno">18312</span>&#160;            requiresDedicatedAllocation,</div>
+<div class="line"><a name="l18313"></a><span class="lineno">18313</span>&#160;            prefersDedicatedAllocation,</div>
+<div class="line"><a name="l18314"></a><span class="lineno">18314</span>&#160;            *pBuffer, <span class="comment">// dedicatedBuffer</span></div>
+<div class="line"><a name="l18315"></a><span class="lineno">18315</span>&#160;            pBufferCreateInfo-&gt;usage, <span class="comment">// dedicatedBufferUsage</span></div>
+<div class="line"><a name="l18316"></a><span class="lineno">18316</span>&#160;            VK_NULL_HANDLE, <span class="comment">// dedicatedImage</span></div>
+<div class="line"><a name="l18317"></a><span class="lineno">18317</span>&#160;            *pAllocationCreateInfo,</div>
+<div class="line"><a name="l18318"></a><span class="lineno">18318</span>&#160;            VMA_SUBALLOCATION_TYPE_BUFFER,</div>
+<div class="line"><a name="l18319"></a><span class="lineno">18319</span>&#160;            1, <span class="comment">// allocationCount</span></div>
+<div class="line"><a name="l18320"></a><span class="lineno">18320</span>&#160;            pAllocation);</div>
+<div class="line"><a name="l18321"></a><span class="lineno">18321</span>&#160; </div>
+<div class="line"><a name="l18322"></a><span class="lineno">18322</span>&#160;<span class="preprocessor">#if VMA_RECORDING_ENABLED</span></div>
+<div class="line"><a name="l18323"></a><span class="lineno">18323</span>&#160;        <span class="keywordflow">if</span>(allocator-&gt;GetRecorder() != VMA_NULL)</div>
+<div class="line"><a name="l18324"></a><span class="lineno">18324</span>&#160;        {</div>
+<div class="line"><a name="l18325"></a><span class="lineno">18325</span>&#160;            allocator-&gt;GetRecorder()-&gt;RecordCreateBuffer(</div>
+<div class="line"><a name="l18326"></a><span class="lineno">18326</span>&#160;                allocator-&gt;GetCurrentFrameIndex(),</div>
+<div class="line"><a name="l18327"></a><span class="lineno">18327</span>&#160;                *pBufferCreateInfo,</div>
+<div class="line"><a name="l18328"></a><span class="lineno">18328</span>&#160;                *pAllocationCreateInfo,</div>
+<div class="line"><a name="l18329"></a><span class="lineno">18329</span>&#160;                *pAllocation);</div>
+<div class="line"><a name="l18330"></a><span class="lineno">18330</span>&#160;        }</div>
+<div class="line"><a name="l18331"></a><span class="lineno">18331</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l18332"></a><span class="lineno">18332</span>&#160; </div>
+<div class="line"><a name="l18333"></a><span class="lineno">18333</span>&#160;        <span class="keywordflow">if</span>(res &gt;= 0)</div>
+<div class="line"><a name="l18334"></a><span class="lineno">18334</span>&#160;        {</div>
+<div class="line"><a name="l18335"></a><span class="lineno">18335</span>&#160;            <span class="comment">// 3. Bind buffer with memory.</span></div>
+<div class="line"><a name="l18336"></a><span class="lineno">18336</span>&#160;            <span class="keywordflow">if</span>((pAllocationCreateInfo-&gt;<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a> &amp; <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a2310568c62208af432724305fe29ccea">VMA_ALLOCATION_CREATE_DONT_BIND_BIT</a>) == 0)</div>
+<div class="line"><a name="l18337"></a><span class="lineno">18337</span>&#160;            {</div>
+<div class="line"><a name="l18338"></a><span class="lineno">18338</span>&#160;                res = allocator-&gt;BindBufferMemory(*pAllocation, 0, *pBuffer, VMA_NULL);</div>
+<div class="line"><a name="l18339"></a><span class="lineno">18339</span>&#160;            }</div>
+<div class="line"><a name="l18340"></a><span class="lineno">18340</span>&#160;            <span class="keywordflow">if</span>(res &gt;= 0)</div>
+<div class="line"><a name="l18341"></a><span class="lineno">18341</span>&#160;            {</div>
+<div class="line"><a name="l18342"></a><span class="lineno">18342</span>&#160;                <span class="comment">// All steps succeeded.</span></div>
+<div class="line"><a name="l18343"></a><span class="lineno">18343</span>&#160;<span class="preprocessor">                #if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l18344"></a><span class="lineno">18344</span>&#160;                    (*pAllocation)-&gt;InitBufferImageUsage(pBufferCreateInfo-&gt;usage);</div>
+<div class="line"><a name="l18345"></a><span class="lineno">18345</span>&#160;<span class="preprocessor">                #endif</span></div>
+<div class="line"><a name="l18346"></a><span class="lineno">18346</span>&#160;                <span class="keywordflow">if</span>(pAllocationInfo != VMA_NULL)</div>
+<div class="line"><a name="l18347"></a><span class="lineno">18347</span>&#160;                {</div>
+<div class="line"><a name="l18348"></a><span class="lineno">18348</span>&#160;                    allocator-&gt;GetAllocationInfo(*pAllocation, pAllocationInfo);</div>
+<div class="line"><a name="l18349"></a><span class="lineno">18349</span>&#160;                }</div>
+<div class="line"><a name="l18350"></a><span class="lineno">18350</span>&#160; </div>
+<div class="line"><a name="l18351"></a><span class="lineno">18351</span>&#160;                <span class="keywordflow">return</span> VK_SUCCESS;</div>
+<div class="line"><a name="l18352"></a><span class="lineno">18352</span>&#160;            }</div>
+<div class="line"><a name="l18353"></a><span class="lineno">18353</span>&#160;            allocator-&gt;FreeMemory(</div>
+<div class="line"><a name="l18354"></a><span class="lineno">18354</span>&#160;                1, <span class="comment">// allocationCount</span></div>
+<div class="line"><a name="l18355"></a><span class="lineno">18355</span>&#160;                pAllocation);</div>
+<div class="line"><a name="l18356"></a><span class="lineno">18356</span>&#160;            *pAllocation = VK_NULL_HANDLE;</div>
+<div class="line"><a name="l18357"></a><span class="lineno">18357</span>&#160;            (*allocator-&gt;GetVulkanFunctions().vkDestroyBuffer)(allocator-&gt;m_hDevice, *pBuffer, allocator-&gt;GetAllocationCallbacks());</div>
+<div class="line"><a name="l18358"></a><span class="lineno">18358</span>&#160;            *pBuffer = VK_NULL_HANDLE;</div>
+<div class="line"><a name="l18359"></a><span class="lineno">18359</span>&#160;            <span class="keywordflow">return</span> res;</div>
+<div class="line"><a name="l18360"></a><span class="lineno">18360</span>&#160;        }</div>
+<div class="line"><a name="l18361"></a><span class="lineno">18361</span>&#160;        (*allocator-&gt;GetVulkanFunctions().vkDestroyBuffer)(allocator-&gt;m_hDevice, *pBuffer, allocator-&gt;GetAllocationCallbacks());</div>
+<div class="line"><a name="l18362"></a><span class="lineno">18362</span>&#160;        *pBuffer = VK_NULL_HANDLE;</div>
+<div class="line"><a name="l18363"></a><span class="lineno">18363</span>&#160;        <span class="keywordflow">return</span> res;</div>
+<div class="line"><a name="l18364"></a><span class="lineno">18364</span>&#160;    }</div>
+<div class="line"><a name="l18365"></a><span class="lineno">18365</span>&#160;    <span class="keywordflow">return</span> res;</div>
+<div class="line"><a name="l18366"></a><span class="lineno">18366</span>&#160;}</div>
+<div class="line"><a name="l18367"></a><span class="lineno">18367</span>&#160; </div>
+<div class="line"><a name="l18368"></a><span class="lineno">18368</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a0d9f4e4ba5bf9aab1f1c746387753d77">vmaDestroyBuffer</a>(</div>
+<div class="line"><a name="l18369"></a><span class="lineno">18369</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l18370"></a><span class="lineno">18370</span>&#160;    VkBuffer buffer,</div>
+<div class="line"><a name="l18371"></a><span class="lineno">18371</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation)</div>
+<div class="line"><a name="l18372"></a><span class="lineno">18372</span>&#160;{</div>
+<div class="line"><a name="l18373"></a><span class="lineno">18373</span>&#160;    VMA_ASSERT(allocator);</div>
+<div class="line"><a name="l18374"></a><span class="lineno">18374</span>&#160; </div>
+<div class="line"><a name="l18375"></a><span class="lineno">18375</span>&#160;    <span class="keywordflow">if</span>(buffer == VK_NULL_HANDLE &amp;&amp; allocation == VK_NULL_HANDLE)</div>
+<div class="line"><a name="l18376"></a><span class="lineno">18376</span>&#160;    {</div>
+<div class="line"><a name="l18377"></a><span class="lineno">18377</span>&#160;        <span class="keywordflow">return</span>;</div>
+<div class="line"><a name="l18378"></a><span class="lineno">18378</span>&#160;    }</div>
+<div class="line"><a name="l18379"></a><span class="lineno">18379</span>&#160; </div>
+<div class="line"><a name="l18380"></a><span class="lineno">18380</span>&#160;    VMA_DEBUG_LOG(<span class="stringliteral">&quot;vmaDestroyBuffer&quot;</span>);</div>
+<div class="line"><a name="l18381"></a><span class="lineno">18381</span>&#160; </div>
+<div class="line"><a name="l18382"></a><span class="lineno">18382</span>&#160;    VMA_DEBUG_GLOBAL_MUTEX_LOCK</div>
+<div class="line"><a name="l18383"></a><span class="lineno">18383</span>&#160; </div>
+<div class="line"><a name="l18384"></a><span class="lineno">18384</span>&#160;<span class="preprocessor">#if VMA_RECORDING_ENABLED</span></div>
+<div class="line"><a name="l18385"></a><span class="lineno">18385</span>&#160;    <span class="keywordflow">if</span>(allocator-&gt;GetRecorder() != VMA_NULL)</div>
+<div class="line"><a name="l18386"></a><span class="lineno">18386</span>&#160;    {</div>
+<div class="line"><a name="l18387"></a><span class="lineno">18387</span>&#160;        allocator-&gt;GetRecorder()-&gt;RecordDestroyBuffer(</div>
+<div class="line"><a name="l18388"></a><span class="lineno">18388</span>&#160;            allocator-&gt;GetCurrentFrameIndex(),</div>
+<div class="line"><a name="l18389"></a><span class="lineno">18389</span>&#160;            allocation);</div>
+<div class="line"><a name="l18390"></a><span class="lineno">18390</span>&#160;    }</div>
+<div class="line"><a name="l18391"></a><span class="lineno">18391</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l18392"></a><span class="lineno">18392</span>&#160; </div>
+<div class="line"><a name="l18393"></a><span class="lineno">18393</span>&#160;    <span class="keywordflow">if</span>(buffer != VK_NULL_HANDLE)</div>
+<div class="line"><a name="l18394"></a><span class="lineno">18394</span>&#160;    {</div>
+<div class="line"><a name="l18395"></a><span class="lineno">18395</span>&#160;        (*allocator-&gt;GetVulkanFunctions().vkDestroyBuffer)(allocator-&gt;m_hDevice, buffer, allocator-&gt;GetAllocationCallbacks());</div>
+<div class="line"><a name="l18396"></a><span class="lineno">18396</span>&#160;    }</div>
+<div class="line"><a name="l18397"></a><span class="lineno">18397</span>&#160; </div>
+<div class="line"><a name="l18398"></a><span class="lineno">18398</span>&#160;    <span class="keywordflow">if</span>(allocation != VK_NULL_HANDLE)</div>
+<div class="line"><a name="l18399"></a><span class="lineno">18399</span>&#160;    {</div>
+<div class="line"><a name="l18400"></a><span class="lineno">18400</span>&#160;        allocator-&gt;FreeMemory(</div>
+<div class="line"><a name="l18401"></a><span class="lineno">18401</span>&#160;            1, <span class="comment">// allocationCount</span></div>
+<div class="line"><a name="l18402"></a><span class="lineno">18402</span>&#160;            &amp;allocation);</div>
+<div class="line"><a name="l18403"></a><span class="lineno">18403</span>&#160;    }</div>
+<div class="line"><a name="l18404"></a><span class="lineno">18404</span>&#160;}</div>
+<div class="line"><a name="l18405"></a><span class="lineno">18405</span>&#160; </div>
+<div class="line"><a name="l18406"></a><span class="lineno">18406</span>&#160;VMA_CALL_PRE VkResult VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#a02a94f25679275851a53e82eacbcfc73">vmaCreateImage</a>(</div>
+<div class="line"><a name="l18407"></a><span class="lineno">18407</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l18408"></a><span class="lineno">18408</span>&#160;    <span class="keyword">const</span> VkImageCreateInfo* pImageCreateInfo,</div>
+<div class="line"><a name="l18409"></a><span class="lineno">18409</span>&#160;    <span class="keyword">const</span> <a class="code" href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a>* pAllocationCreateInfo,</div>
+<div class="line"><a name="l18410"></a><span class="lineno">18410</span>&#160;    VkImage* pImage,</div>
+<div class="line"><a name="l18411"></a><span class="lineno">18411</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a>* pAllocation,</div>
+<div class="line"><a name="l18412"></a><span class="lineno">18412</span>&#160;    <a class="code" href="struct_vma_allocation_info.html">VmaAllocationInfo</a>* pAllocationInfo)</div>
+<div class="line"><a name="l18413"></a><span class="lineno">18413</span>&#160;{</div>
+<div class="line"><a name="l18414"></a><span class="lineno">18414</span>&#160;    VMA_ASSERT(allocator &amp;&amp; pImageCreateInfo &amp;&amp; pAllocationCreateInfo &amp;&amp; pImage &amp;&amp; pAllocation);</div>
+<div class="line"><a name="l18415"></a><span class="lineno">18415</span>&#160; </div>
+<div class="line"><a name="l18416"></a><span class="lineno">18416</span>&#160;    <span class="keywordflow">if</span>(pImageCreateInfo-&gt;extent.width == 0 ||</div>
+<div class="line"><a name="l18417"></a><span class="lineno">18417</span>&#160;        pImageCreateInfo-&gt;extent.height == 0 ||</div>
+<div class="line"><a name="l18418"></a><span class="lineno">18418</span>&#160;        pImageCreateInfo-&gt;extent.depth == 0 ||</div>
+<div class="line"><a name="l18419"></a><span class="lineno">18419</span>&#160;        pImageCreateInfo-&gt;mipLevels == 0 ||</div>
+<div class="line"><a name="l18420"></a><span class="lineno">18420</span>&#160;        pImageCreateInfo-&gt;arrayLayers == 0)</div>
+<div class="line"><a name="l18421"></a><span class="lineno">18421</span>&#160;    {</div>
+<div class="line"><a name="l18422"></a><span class="lineno">18422</span>&#160;        <span class="keywordflow">return</span> VK_ERROR_VALIDATION_FAILED_EXT;</div>
+<div class="line"><a name="l18423"></a><span class="lineno">18423</span>&#160;    }</div>
+<div class="line"><a name="l18424"></a><span class="lineno">18424</span>&#160; </div>
+<div class="line"><a name="l18425"></a><span class="lineno">18425</span>&#160;    VMA_DEBUG_LOG(<span class="stringliteral">&quot;vmaCreateImage&quot;</span>);</div>
+<div class="line"><a name="l18426"></a><span class="lineno">18426</span>&#160; </div>
+<div class="line"><a name="l18427"></a><span class="lineno">18427</span>&#160;    VMA_DEBUG_GLOBAL_MUTEX_LOCK</div>
+<div class="line"><a name="l18428"></a><span class="lineno">18428</span>&#160; </div>
+<div class="line"><a name="l18429"></a><span class="lineno">18429</span>&#160;    *pImage = VK_NULL_HANDLE;</div>
+<div class="line"><a name="l18430"></a><span class="lineno">18430</span>&#160;    *pAllocation = VK_NULL_HANDLE;</div>
+<div class="line"><a name="l18431"></a><span class="lineno">18431</span>&#160; </div>
+<div class="line"><a name="l18432"></a><span class="lineno">18432</span>&#160;    <span class="comment">// 1. Create VkImage.</span></div>
+<div class="line"><a name="l18433"></a><span class="lineno">18433</span>&#160;    VkResult res = (*allocator-&gt;GetVulkanFunctions().vkCreateImage)(</div>
+<div class="line"><a name="l18434"></a><span class="lineno">18434</span>&#160;        allocator-&gt;m_hDevice,</div>
+<div class="line"><a name="l18435"></a><span class="lineno">18435</span>&#160;        pImageCreateInfo,</div>
+<div class="line"><a name="l18436"></a><span class="lineno">18436</span>&#160;        allocator-&gt;GetAllocationCallbacks(),</div>
+<div class="line"><a name="l18437"></a><span class="lineno">18437</span>&#160;        pImage);</div>
+<div class="line"><a name="l18438"></a><span class="lineno">18438</span>&#160;    <span class="keywordflow">if</span>(res &gt;= 0)</div>
+<div class="line"><a name="l18439"></a><span class="lineno">18439</span>&#160;    {</div>
+<div class="line"><a name="l18440"></a><span class="lineno">18440</span>&#160;        VmaSuballocationType suballocType = pImageCreateInfo-&gt;tiling == VK_IMAGE_TILING_OPTIMAL ?</div>
+<div class="line"><a name="l18441"></a><span class="lineno">18441</span>&#160;            VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL :</div>
+<div class="line"><a name="l18442"></a><span class="lineno">18442</span>&#160;            VMA_SUBALLOCATION_TYPE_IMAGE_LINEAR;</div>
+<div class="line"><a name="l18443"></a><span class="lineno">18443</span>&#160;        </div>
+<div class="line"><a name="l18444"></a><span class="lineno">18444</span>&#160;        <span class="comment">// 2. Allocate memory using allocator.</span></div>
+<div class="line"><a name="l18445"></a><span class="lineno">18445</span>&#160;        VkMemoryRequirements vkMemReq = {};</div>
+<div class="line"><a name="l18446"></a><span class="lineno">18446</span>&#160;        <span class="keywordtype">bool</span> requiresDedicatedAllocation = <span class="keyword">false</span>;</div>
+<div class="line"><a name="l18447"></a><span class="lineno">18447</span>&#160;        <span class="keywordtype">bool</span> prefersDedicatedAllocation  = <span class="keyword">false</span>;</div>
+<div class="line"><a name="l18448"></a><span class="lineno">18448</span>&#160;        allocator-&gt;GetImageMemoryRequirements(*pImage, vkMemReq,</div>
+<div class="line"><a name="l18449"></a><span class="lineno">18449</span>&#160;            requiresDedicatedAllocation, prefersDedicatedAllocation);</div>
+<div class="line"><a name="l18450"></a><span class="lineno">18450</span>&#160; </div>
+<div class="line"><a name="l18451"></a><span class="lineno">18451</span>&#160;        res = allocator-&gt;AllocateMemory(</div>
+<div class="line"><a name="l18452"></a><span class="lineno">18452</span>&#160;            vkMemReq,</div>
+<div class="line"><a name="l18453"></a><span class="lineno">18453</span>&#160;            requiresDedicatedAllocation,</div>
+<div class="line"><a name="l18454"></a><span class="lineno">18454</span>&#160;            prefersDedicatedAllocation,</div>
+<div class="line"><a name="l18455"></a><span class="lineno">18455</span>&#160;            VK_NULL_HANDLE, <span class="comment">// dedicatedBuffer</span></div>
+<div class="line"><a name="l18456"></a><span class="lineno">18456</span>&#160;            UINT32_MAX, <span class="comment">// dedicatedBufferUsage</span></div>
+<div class="line"><a name="l18457"></a><span class="lineno">18457</span>&#160;            *pImage, <span class="comment">// dedicatedImage</span></div>
+<div class="line"><a name="l18458"></a><span class="lineno">18458</span>&#160;            *pAllocationCreateInfo,</div>
+<div class="line"><a name="l18459"></a><span class="lineno">18459</span>&#160;            suballocType,</div>
+<div class="line"><a name="l18460"></a><span class="lineno">18460</span>&#160;            1, <span class="comment">// allocationCount</span></div>
+<div class="line"><a name="l18461"></a><span class="lineno">18461</span>&#160;            pAllocation);</div>
+<div class="line"><a name="l18462"></a><span class="lineno">18462</span>&#160; </div>
+<div class="line"><a name="l18463"></a><span class="lineno">18463</span>&#160;<span class="preprocessor">#if VMA_RECORDING_ENABLED</span></div>
+<div class="line"><a name="l18464"></a><span class="lineno">18464</span>&#160;        <span class="keywordflow">if</span>(allocator-&gt;GetRecorder() != VMA_NULL)</div>
+<div class="line"><a name="l18465"></a><span class="lineno">18465</span>&#160;        {</div>
+<div class="line"><a name="l18466"></a><span class="lineno">18466</span>&#160;            allocator-&gt;GetRecorder()-&gt;RecordCreateImage(</div>
+<div class="line"><a name="l18467"></a><span class="lineno">18467</span>&#160;                allocator-&gt;GetCurrentFrameIndex(),</div>
+<div class="line"><a name="l18468"></a><span class="lineno">18468</span>&#160;                *pImageCreateInfo,</div>
+<div class="line"><a name="l18469"></a><span class="lineno">18469</span>&#160;                *pAllocationCreateInfo,</div>
+<div class="line"><a name="l18470"></a><span class="lineno">18470</span>&#160;                *pAllocation);</div>
+<div class="line"><a name="l18471"></a><span class="lineno">18471</span>&#160;        }</div>
+<div class="line"><a name="l18472"></a><span class="lineno">18472</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l18473"></a><span class="lineno">18473</span>&#160; </div>
+<div class="line"><a name="l18474"></a><span class="lineno">18474</span>&#160;        <span class="keywordflow">if</span>(res &gt;= 0)</div>
+<div class="line"><a name="l18475"></a><span class="lineno">18475</span>&#160;        {</div>
+<div class="line"><a name="l18476"></a><span class="lineno">18476</span>&#160;            <span class="comment">// 3. Bind image with memory.</span></div>
+<div class="line"><a name="l18477"></a><span class="lineno">18477</span>&#160;            <span class="keywordflow">if</span>((pAllocationCreateInfo-&gt;<a class="code" href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">flags</a> &amp; <a class="code" href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a2310568c62208af432724305fe29ccea">VMA_ALLOCATION_CREATE_DONT_BIND_BIT</a>) == 0)</div>
+<div class="line"><a name="l18478"></a><span class="lineno">18478</span>&#160;            {</div>
+<div class="line"><a name="l18479"></a><span class="lineno">18479</span>&#160;                res = allocator-&gt;BindImageMemory(*pAllocation, 0, *pImage, VMA_NULL);</div>
+<div class="line"><a name="l18480"></a><span class="lineno">18480</span>&#160;            }</div>
+<div class="line"><a name="l18481"></a><span class="lineno">18481</span>&#160;            <span class="keywordflow">if</span>(res &gt;= 0)</div>
+<div class="line"><a name="l18482"></a><span class="lineno">18482</span>&#160;            {</div>
+<div class="line"><a name="l18483"></a><span class="lineno">18483</span>&#160;                <span class="comment">// All steps succeeded.</span></div>
+<div class="line"><a name="l18484"></a><span class="lineno">18484</span>&#160;<span class="preprocessor">                #if VMA_STATS_STRING_ENABLED</span></div>
+<div class="line"><a name="l18485"></a><span class="lineno">18485</span>&#160;                    (*pAllocation)-&gt;InitBufferImageUsage(pImageCreateInfo-&gt;usage);</div>
+<div class="line"><a name="l18486"></a><span class="lineno">18486</span>&#160;<span class="preprocessor">                #endif</span></div>
+<div class="line"><a name="l18487"></a><span class="lineno">18487</span>&#160;                <span class="keywordflow">if</span>(pAllocationInfo != VMA_NULL)</div>
+<div class="line"><a name="l18488"></a><span class="lineno">18488</span>&#160;                {</div>
+<div class="line"><a name="l18489"></a><span class="lineno">18489</span>&#160;                    allocator-&gt;GetAllocationInfo(*pAllocation, pAllocationInfo);</div>
+<div class="line"><a name="l18490"></a><span class="lineno">18490</span>&#160;                }</div>
+<div class="line"><a name="l18491"></a><span class="lineno">18491</span>&#160; </div>
+<div class="line"><a name="l18492"></a><span class="lineno">18492</span>&#160;                <span class="keywordflow">return</span> VK_SUCCESS;</div>
+<div class="line"><a name="l18493"></a><span class="lineno">18493</span>&#160;            }</div>
+<div class="line"><a name="l18494"></a><span class="lineno">18494</span>&#160;            allocator-&gt;FreeMemory(</div>
+<div class="line"><a name="l18495"></a><span class="lineno">18495</span>&#160;                1, <span class="comment">// allocationCount</span></div>
+<div class="line"><a name="l18496"></a><span class="lineno">18496</span>&#160;                pAllocation);</div>
+<div class="line"><a name="l18497"></a><span class="lineno">18497</span>&#160;            *pAllocation = VK_NULL_HANDLE;</div>
+<div class="line"><a name="l18498"></a><span class="lineno">18498</span>&#160;            (*allocator-&gt;GetVulkanFunctions().vkDestroyImage)(allocator-&gt;m_hDevice, *pImage, allocator-&gt;GetAllocationCallbacks());</div>
+<div class="line"><a name="l18499"></a><span class="lineno">18499</span>&#160;            *pImage = VK_NULL_HANDLE;</div>
+<div class="line"><a name="l18500"></a><span class="lineno">18500</span>&#160;            <span class="keywordflow">return</span> res;</div>
+<div class="line"><a name="l18501"></a><span class="lineno">18501</span>&#160;        }</div>
+<div class="line"><a name="l18502"></a><span class="lineno">18502</span>&#160;        (*allocator-&gt;GetVulkanFunctions().vkDestroyImage)(allocator-&gt;m_hDevice, *pImage, allocator-&gt;GetAllocationCallbacks());</div>
+<div class="line"><a name="l18503"></a><span class="lineno">18503</span>&#160;        *pImage = VK_NULL_HANDLE;</div>
+<div class="line"><a name="l18504"></a><span class="lineno">18504</span>&#160;        <span class="keywordflow">return</span> res;</div>
+<div class="line"><a name="l18505"></a><span class="lineno">18505</span>&#160;    }</div>
+<div class="line"><a name="l18506"></a><span class="lineno">18506</span>&#160;    <span class="keywordflow">return</span> res;</div>
+<div class="line"><a name="l18507"></a><span class="lineno">18507</span>&#160;}</div>
+<div class="line"><a name="l18508"></a><span class="lineno">18508</span>&#160; </div>
+<div class="line"><a name="l18509"></a><span class="lineno">18509</span>&#160;VMA_CALL_PRE <span class="keywordtype">void</span> VMA_CALL_POST <a class="code" href="vk__mem__alloc_8h.html#ae50d2cb3b4a3bfd4dd40987234e50e7e">vmaDestroyImage</a>(</div>
+<div class="line"><a name="l18510"></a><span class="lineno">18510</span>&#160;    <a class="code" href="struct_vma_allocator.html">VmaAllocator</a> allocator,</div>
+<div class="line"><a name="l18511"></a><span class="lineno">18511</span>&#160;    VkImage image,</div>
+<div class="line"><a name="l18512"></a><span class="lineno">18512</span>&#160;    <a class="code" href="struct_vma_allocation.html">VmaAllocation</a> allocation)</div>
+<div class="line"><a name="l18513"></a><span class="lineno">18513</span>&#160;{</div>
+<div class="line"><a name="l18514"></a><span class="lineno">18514</span>&#160;    VMA_ASSERT(allocator);</div>
+<div class="line"><a name="l18515"></a><span class="lineno">18515</span>&#160; </div>
+<div class="line"><a name="l18516"></a><span class="lineno">18516</span>&#160;    <span class="keywordflow">if</span>(image == VK_NULL_HANDLE &amp;&amp; allocation == VK_NULL_HANDLE)</div>
+<div class="line"><a name="l18517"></a><span class="lineno">18517</span>&#160;    {</div>
+<div class="line"><a name="l18518"></a><span class="lineno">18518</span>&#160;        <span class="keywordflow">return</span>;</div>
+<div class="line"><a name="l18519"></a><span class="lineno">18519</span>&#160;    }</div>
+<div class="line"><a name="l18520"></a><span class="lineno">18520</span>&#160; </div>
+<div class="line"><a name="l18521"></a><span class="lineno">18521</span>&#160;    VMA_DEBUG_LOG(<span class="stringliteral">&quot;vmaDestroyImage&quot;</span>);</div>
+<div class="line"><a name="l18522"></a><span class="lineno">18522</span>&#160; </div>
+<div class="line"><a name="l18523"></a><span class="lineno">18523</span>&#160;    VMA_DEBUG_GLOBAL_MUTEX_LOCK</div>
+<div class="line"><a name="l18524"></a><span class="lineno">18524</span>&#160; </div>
+<div class="line"><a name="l18525"></a><span class="lineno">18525</span>&#160;<span class="preprocessor">#if VMA_RECORDING_ENABLED</span></div>
+<div class="line"><a name="l18526"></a><span class="lineno">18526</span>&#160;    <span class="keywordflow">if</span>(allocator-&gt;GetRecorder() != VMA_NULL)</div>
+<div class="line"><a name="l18527"></a><span class="lineno">18527</span>&#160;    {</div>
+<div class="line"><a name="l18528"></a><span class="lineno">18528</span>&#160;        allocator-&gt;GetRecorder()-&gt;RecordDestroyImage(</div>
+<div class="line"><a name="l18529"></a><span class="lineno">18529</span>&#160;            allocator-&gt;GetCurrentFrameIndex(),</div>
+<div class="line"><a name="l18530"></a><span class="lineno">18530</span>&#160;            allocation);</div>
+<div class="line"><a name="l18531"></a><span class="lineno">18531</span>&#160;    }</div>
+<div class="line"><a name="l18532"></a><span class="lineno">18532</span>&#160;<span class="preprocessor">#endif</span></div>
+<div class="line"><a name="l18533"></a><span class="lineno">18533</span>&#160; </div>
+<div class="line"><a name="l18534"></a><span class="lineno">18534</span>&#160;    <span class="keywordflow">if</span>(image != VK_NULL_HANDLE)</div>
+<div class="line"><a name="l18535"></a><span class="lineno">18535</span>&#160;    {</div>
+<div class="line"><a name="l18536"></a><span class="lineno">18536</span>&#160;        (*allocator-&gt;GetVulkanFunctions().vkDestroyImage)(allocator-&gt;m_hDevice, image, allocator-&gt;GetAllocationCallbacks());</div>
+<div class="line"><a name="l18537"></a><span class="lineno">18537</span>&#160;    }</div>
+<div class="line"><a name="l18538"></a><span class="lineno">18538</span>&#160;    <span class="keywordflow">if</span>(allocation != VK_NULL_HANDLE)</div>
+<div class="line"><a name="l18539"></a><span class="lineno">18539</span>&#160;    {</div>
+<div class="line"><a name="l18540"></a><span class="lineno">18540</span>&#160;        allocator-&gt;FreeMemory(</div>
+<div class="line"><a name="l18541"></a><span class="lineno">18541</span>&#160;            1, <span class="comment">// allocationCount</span></div>
+<div class="line"><a name="l18542"></a><span class="lineno">18542</span>&#160;            &amp;allocation);</div>
+<div class="line"><a name="l18543"></a><span class="lineno">18543</span>&#160;    }</div>
+<div class="line"><a name="l18544"></a><span class="lineno">18544</span>&#160;}</div>
+<div class="line"><a name="l18545"></a><span class="lineno">18545</span>&#160; </div>
+<div class="line"><a name="l18546"></a><span class="lineno">18546</span>&#160;<span class="preprocessor">#endif // #ifdef VMA_IMPLEMENTATION</span></div>
+</div><!-- fragment --></div><!-- contents -->
+<div class="ttc" id="avk__mem__alloc_8h_html_a21813b2efdf3836767a9058cd8a94034"><div class="ttname"><a href="vk__mem__alloc_8h.html#a21813b2efdf3836767a9058cd8a94034">VmaStats</a></div><div class="ttdeci">struct VmaStats VmaStats</div><div class="ttdoc">General statistics from current state of Allocator.</div></div>
+<div class="ttc" id="astruct_vma_record_settings_html"><div class="ttname"><a href="struct_vma_record_settings.html">VmaRecordSettings</a></div><div class="ttdoc">Parameters for recording calls to VMA functions. To be used in VmaAllocatorCreateInfo::pRecordSetting...</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2158</div></div>
+<div class="ttc" id="astruct_vma_vulkan_functions_html_a2943bf99dfd784a0e8f599d987e22e6c"><div class="ttname"><a href="struct_vma_vulkan_functions.html#a2943bf99dfd784a0e8f599d987e22e6c">VmaVulkanFunctions::vkAllocateMemory</a></div><div class="ttdeci">PFN_vkAllocateMemory vkAllocateMemory</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2116</div></div>
+<div class="ttc" id="astruct_vma_device_memory_callbacks_html_abe8a3328bbc916f6f712fdb6b299444c"><div class="ttname"><a href="struct_vma_device_memory_callbacks.html#abe8a3328bbc916f6f712fdb6b299444c">VmaDeviceMemoryCallbacks::pfnFree</a></div><div class="ttdeci">PFN_vmaFreeDeviceMemoryFunction pfnFree</div><div class="ttdoc">Optional, can be null.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2004</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a4dd2c44642312a147a4e93373a6e64d2a20dd17d69966dbffa054739d6090b85e"><div class="ttname"><a href="vk__mem__alloc_8h.html#a4dd2c44642312a147a4e93373a6e64d2a20dd17d69966dbffa054739d6090b85e">VMA_RECORD_FLAG_BITS_MAX_ENUM</a></div><div class="ttdeci">@ VMA_RECORD_FLAG_BITS_MAX_ENUM</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2153</div></div>
+<div class="ttc" id="astruct_vma_vulkan_functions_html_a77b7a74082823e865dd6546623468f96"><div class="ttname"><a href="struct_vma_vulkan_functions.html#a77b7a74082823e865dd6546623468f96">VmaVulkanFunctions::vkGetPhysicalDeviceProperties</a></div><div class="ttdeci">PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2114</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a11f0fbc034fa81a4efedd73d61ce7568"><div class="ttname"><a href="vk__mem__alloc_8h.html#a11f0fbc034fa81a4efedd73d61ce7568">vmaFreeMemory</a></div><div class="ttdeci">void vmaFreeMemory(VmaAllocator allocator, VmaAllocation allocation)</div><div class="ttdoc">Frees memory previously allocated using vmaAllocateMemory(), vmaAllocateMemoryForBuffer(),...</div></div>
+<div class="ttc" id="astruct_vma_allocator_create_info_html_a08230f04ae6ccf8a78150a9e829a7156"><div class="ttname"><a href="struct_vma_allocator_create_info.html#a08230f04ae6ccf8a78150a9e829a7156">VmaAllocatorCreateInfo::physicalDevice</a></div><div class="ttdeci">VkPhysicalDevice physicalDevice</div><div class="ttdoc">Vulkan physical device.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2179</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a9a7c45f9c863695d98c83fa5ac940fe7a13c8a444197c67866be9cb05599fc726"><div class="ttname"><a href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a13c8a444197c67866be9cb05599fc726">VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT</a></div><div class="ttdeci">@ VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT</div><div class="ttdoc">Enables alternative, linear allocation algorithm in this pool.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2775</div></div>
+<div class="ttc" id="astruct_vma_defragmentation_info2_html_a3cf86ab32c1da779b4923d301a3056ba"><div class="ttname"><a href="struct_vma_defragmentation_info2.html#a3cf86ab32c1da779b4923d301a3056ba">VmaDefragmentationInfo2::allocationCount</a></div><div class="ttdeci">uint32_t allocationCount</div><div class="ttdoc">Number of allocations in pAllocations array.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3326</div></div>
+<div class="ttc" id="astruct_vma_allocator_create_info_html_a21ea188dd212b8171cb9ecbed4a2a3a7"><div class="ttname"><a href="struct_vma_allocator_create_info.html#a21ea188dd212b8171cb9ecbed4a2a3a7">VmaAllocatorCreateInfo::frameInUseCount</a></div><div class="ttdeci">uint32_t frameInUseCount</div><div class="ttdoc">Maximum number of additional frames that are in use at the same time as current frame.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2205</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a4f87c9100d154a65a4ad495f7763cf7ca4d4687863f7bd4b418c6006dc04400b0"><div class="ttname"><a href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca4d4687863f7bd4b418c6006dc04400b0">VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT</a></div><div class="ttdeci">@ VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2067</div></div>
+<div class="ttc" id="astruct_vma_budget_html"><div class="ttname"><a href="struct_vma_budget.html">VmaBudget</a></div><div class="ttdoc">Statistics of current memory usage and available budget, in bytes, for specific memory heap.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2376</div></div>
+<div class="ttc" id="astruct_vma_defragmentation_pass_move_info_html_a06eb0c8690aa0d3478a036753492e769"><div class="ttname"><a href="struct_vma_defragmentation_pass_move_info.html#a06eb0c8690aa0d3478a036753492e769">VmaDefragmentationPassMoveInfo::memory</a></div><div class="ttdeci">VkDeviceMemory memory</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3394</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a0d0eb0c1102268fa9a476d12ecbe4006"><div class="ttname"><a href="vk__mem__alloc_8h.html#a0d0eb0c1102268fa9a476d12ecbe4006">vmaInvalidateAllocation</a></div><div class="ttdeci">void vmaInvalidateAllocation(VmaAllocator allocator, VmaAllocation allocation, VkDeviceSize offset, VkDeviceSize size)</div><div class="ttdoc">Invalidates memory of given allocation.</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_aa5846affa1e9da3800e3e78fae2305cca835333d9072db63a653818030e17614d"><div class="ttname"><a href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca835333d9072db63a653818030e17614d">VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED</a></div><div class="ttdeci">@ VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2521</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a2bf47f96bf92bed2a49461bd9af3acfa"><div class="ttname"><a href="vk__mem__alloc_8h.html#a2bf47f96bf92bed2a49461bd9af3acfa">VmaDefragmentationInfo</a></div><div class="ttdeci">struct VmaDefragmentationInfo VmaDefragmentationInfo</div><div class="ttdoc">Deprecated. Optional configuration parameters to be passed to function vmaDefragment().</div></div>
+<div class="ttc" id="astruct_vma_pool_stats_html"><div class="ttname"><a href="struct_vma_pool_stats.html">VmaPoolStats</a></div><div class="ttdoc">Describes parameter of existing VmaPool.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2847</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ad9889c10c798b040d59c92f257cae597a839826775c62319466441f86496f036d"><div class="ttname"><a href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a839826775c62319466441f86496f036d">VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT</a></div><div class="ttdeci">@ VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2604</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a4f87c9100d154a65a4ad495f7763cf7ca4816ddaed324ba110172ca608a20f29d"><div class="ttname"><a href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca4816ddaed324ba110172ca608a20f29d">VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT</a></div><div class="ttdeci">@ VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT</div><div class="ttdoc">Allocator and all objects created from it will not be synchronized internally, so you must guarantee ...</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2015</div></div>
+<div class="ttc" id="astruct_vma_pool_stats_html_ad7c54874724fce7b06aba526202d82a8"><div class="ttname"><a href="struct_vma_pool_stats.html#ad7c54874724fce7b06aba526202d82a8">VmaPoolStats::unusedSize</a></div><div class="ttdeci">VkDeviceSize unusedSize</div><div class="ttdoc">Total number of bytes in the pool not used by any VmaAllocation.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2853</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ad9889c10c798b040d59c92f257cae597aa6f24f821cd6a7c5e4a443f7bf59c520"><div class="ttname"><a href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597aa6f24f821cd6a7c5e4a443f7bf59c520">VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT</a></div><div class="ttdeci">@ VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2584</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a4dd2c44642312a147a4e93373a6e64d2"><div class="ttname"><a href="vk__mem__alloc_8h.html#a4dd2c44642312a147a4e93373a6e64d2">VmaRecordFlagBits</a></div><div class="ttdeci">VmaRecordFlagBits</div><div class="ttdoc">Flags to be used in VmaRecordSettings::flags.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2145</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_adbae3a0b4ab078024462fc85c37f3b58"><div class="ttname"><a href="vk__mem__alloc_8h.html#adbae3a0b4ab078024462fc85c37f3b58">vmaSetPoolName</a></div><div class="ttdeci">void vmaSetPoolName(VmaAllocator allocator, VmaPool pool, const char *pName)</div><div class="ttdoc">Sets name of a custom pool.</div></div>
+<div class="ttc" id="astruct_vma_device_memory_callbacks_html"><div class="ttname"><a href="struct_vma_device_memory_callbacks.html">VmaDeviceMemoryCallbacks</a></div><div class="ttdoc">Set of callbacks that the library will call for vkAllocateMemory and vkFreeMemory.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2000</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a43d8ba9673c846f049089a5029d5c73a"><div class="ttname"><a href="vk__mem__alloc_8h.html#a43d8ba9673c846f049089a5029d5c73a">vmaTouchAllocation</a></div><div class="ttdeci">VkBool32 vmaTouchAllocation(VmaAllocator allocator, VmaAllocation allocation)</div><div class="ttdoc">Returns VK_TRUE if allocation is not lost and atomically marks it as used in current frame.</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ad9889c10c798b040d59c92f257cae597a5f436af6c8fe8540573a6d22627a6fd2"><div class="ttname"><a href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a5f436af6c8fe8540573a6d22627a6fd2">VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT</a></div><div class="ttdeci">@ VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2571</div></div>
+<div class="ttc" id="astruct_vma_allocator_create_info_html_a8e4714298e3121cdd8b214a1ae7a637a"><div class="ttname"><a href="struct_vma_allocator_create_info.html#a8e4714298e3121cdd8b214a1ae7a637a">VmaAllocatorCreateInfo::preferredLargeHeapBlockSize</a></div><div class="ttdeci">VkDeviceSize preferredLargeHeapBlockSize</div><div class="ttdoc">Preferred size of a single VkDeviceMemory block to be allocated from large heaps &gt; 1 GiB....</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2185</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a4dd2c44642312a147a4e93373a6e64d2a8e7ab322e8732654be627c4ea8f36cc7"><div class="ttname"><a href="vk__mem__alloc_8h.html#a4dd2c44642312a147a4e93373a6e64d2a8e7ab322e8732654be627c4ea8f36cc7">VMA_RECORD_FLUSH_AFTER_CALL_BIT</a></div><div class="ttdeci">@ VMA_RECORD_FLUSH_AFTER_CALL_BIT</div><div class="ttdoc">Enables flush after recording every function call.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2151</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a3bf110892ea2fb4649fedb68488d026a"><div class="ttname"><a href="vk__mem__alloc_8h.html#a3bf110892ea2fb4649fedb68488d026a">VmaAllocationCreateInfo</a></div><div class="ttdeci">struct VmaAllocationCreateInfo VmaAllocationCreateInfo</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a0ff488958ca72b28e545880463cb8696"><div class="ttname"><a href="vk__mem__alloc_8h.html#a0ff488958ca72b28e545880463cb8696">vmaResizeAllocation</a></div><div class="ttdeci">VkResult vmaResizeAllocation(VmaAllocator allocator, VmaAllocation allocation, VkDeviceSize newSize)</div><div class="ttdoc">Deprecated.</div></div>
+<div class="ttc" id="astruct_vma_vulkan_functions_html_acc798589736f0becb317fc2196c1d8b9"><div class="ttname"><a href="struct_vma_vulkan_functions.html#acc798589736f0becb317fc2196c1d8b9">VmaVulkanFunctions::vkUnmapMemory</a></div><div class="ttdeci">PFN_vkUnmapMemory vkUnmapMemory</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2119</div></div>
+<div class="ttc" id="astruct_vma_allocation_info_html_ae0bfb7dfdf79a76ffefc9a94677a2f67"><div class="ttname"><a href="struct_vma_allocation_info.html#ae0bfb7dfdf79a76ffefc9a94677a2f67">VmaAllocationInfo::deviceMemory</a></div><div class="ttdeci">VkDeviceMemory deviceMemory</div><div class="ttdoc">Handle to Vulkan memory object.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2990</div></div>
+<div class="ttc" id="astruct_vma_stat_info_html_ae06129c771bfebfd6468a7f4276502a9"><div class="ttname"><a href="struct_vma_stat_info.html#ae06129c771bfebfd6468a7f4276502a9">VmaStatInfo::unusedRangeCount</a></div><div class="ttdeci">uint32_t unusedRangeCount</div><div class="ttdoc">Number of free ranges of memory between allocations.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2344</div></div>
+<div class="ttc" id="astruct_vma_allocation_create_info_html_a8259e85c272683434f4abb4ddddffe19"><div class="ttname"><a href="struct_vma_allocation_create_info.html#a8259e85c272683434f4abb4ddddffe19">VmaAllocationCreateInfo::pUserData</a></div><div class="ttdeci">void * pUserData</div><div class="ttdoc">Custom general-purpose pointer that will be stored in VmaAllocation, can be read as VmaAllocationInfo...</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2678</div></div>
+<div class="ttc" id="astruct_vma_stat_info_html_a5ba1a2476c4d39b10f7e2f7ebbb72ac4"><div class="ttname"><a href="struct_vma_stat_info.html#a5ba1a2476c4d39b10f7e2f7ebbb72ac4">VmaStatInfo::unusedRangeSizeMax</a></div><div class="ttdeci">VkDeviceSize unusedRangeSizeMax</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2350</div></div>
+<div class="ttc" id="astruct_vma_vulkan_functions_html_ab5c1f38dea3a2cf00dc9eb4f57218c49"><div class="ttname"><a href="struct_vma_vulkan_functions.html#ab5c1f38dea3a2cf00dc9eb4f57218c49">VmaVulkanFunctions::vkMapMemory</a></div><div class="ttdeci">PFN_vkMapMemory vkMapMemory</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2118</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a1f0c126759fc96ccb6e2d23c101d770c"><div class="ttname"><a href="vk__mem__alloc_8h.html#a1f0c126759fc96ccb6e2d23c101d770c">VMA_RECORDING_ENABLED</a></div><div class="ttdeci">#define VMA_RECORDING_ENABLED</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:1894</div></div>
+<div class="ttc" id="astruct_vma_defragmentation_pass_move_info_html_a8ab4508bc03625b0653c880576be96c6"><div class="ttname"><a href="struct_vma_defragmentation_pass_move_info.html#a8ab4508bc03625b0653c880576be96c6">VmaDefragmentationPassMoveInfo::offset</a></div><div class="ttdeci">VkDeviceSize offset</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3395</div></div>
+<div class="ttc" id="astruct_vma_defragmentation_pass_info_html_acbd42d4a3357999da130a95cd99a3792"><div class="ttname"><a href="struct_vma_defragmentation_pass_info.html#acbd42d4a3357999da130a95cd99a3792">VmaDefragmentationPassInfo::pMoves</a></div><div class="ttdeci">VmaDefragmentationPassMoveInfo * pMoves</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3404</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ad9889c10c798b040d59c92f257cae597a33eb2052674f3ad92386c714a65fb777"><div class="ttname"><a href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a33eb2052674f3ad92386c714a65fb777">VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT</a></div><div class="ttdeci">@ VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2615</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a9bc268595cb33f6ec4d519cfce81ff45"><div class="ttname"><a href="vk__mem__alloc_8h.html#a9bc268595cb33f6ec4d519cfce81ff45">vmaUnmapMemory</a></div><div class="ttdeci">void vmaUnmapMemory(VmaAllocator allocator, VmaAllocation allocation)</div><div class="ttdoc">Unmaps memory represented by given allocation, mapped previously using vmaMapMemory().</div></div>
+<div class="ttc" id="astruct_vma_allocator_info_html_a2ed6a4d2d3fea039d66a13f15d0ce5fe"><div class="ttname"><a href="struct_vma_allocator_info.html#a2ed6a4d2d3fea039d66a13f15d0ce5fe">VmaAllocatorInfo::instance</a></div><div class="ttdeci">VkInstance instance</div><div class="ttdoc">Handle to Vulkan instance object.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2276</div></div>
+<div class="ttc" id="astruct_vma_budget_html_a84dd1ecca8b0110259eb206dbadb11f6"><div class="ttname"><a href="struct_vma_budget.html#a84dd1ecca8b0110259eb206dbadb11f6">VmaBudget::usage</a></div><div class="ttdeci">VkDeviceSize usage</div><div class="ttdoc">Estimated current memory usage of the program, in bytes.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2401</div></div>
+<div class="ttc" id="astruct_vma_allocator_html"><div class="ttname"><a href="struct_vma_allocator.html">VmaAllocator</a></div><div class="ttdoc">Represents main object of this library initialized.</div></div>
+<div class="ttc" id="astruct_vma_vulkan_functions_html_ae5c0db8c89a3b82593dc16aa6a49fa3a"><div class="ttname"><a href="struct_vma_vulkan_functions.html#ae5c0db8c89a3b82593dc16aa6a49fa3a">VmaVulkanFunctions::vkCmdCopyBuffer</a></div><div class="ttdeci">PFN_vkCmdCopyBuffer vkCmdCopyBuffer</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2130</div></div>
+<div class="ttc" id="astruct_vma_allocator_create_info_html"><div class="ttname"><a href="struct_vma_allocator_create_info.html">VmaAllocatorCreateInfo</a></div><div class="ttdoc">Description of a Allocator to be created.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2173</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ad9889c10c798b040d59c92f257cae597a89759603401014eb325eb22a3839f2ff"><div class="ttname"><a href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a89759603401014eb325eb22a3839f2ff">VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT</a></div><div class="ttdeci">@ VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT</div><div class="ttdoc">Set this flag to only try to allocate from existing VkDeviceMemory blocks and never create new such b...</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2545</div></div>
+<div class="ttc" id="astruct_vma_allocator_info_html_a012b4c485bf3b0ea8921352c5ee0c357"><div class="ttname"><a href="struct_vma_allocator_info.html#a012b4c485bf3b0ea8921352c5ee0c357">VmaAllocatorInfo::device</a></div><div class="ttdeci">VkDevice device</div><div class="ttdoc">Handle to Vulkan device object.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2286</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a6552a65b71d16f378c6994b3ceaef50cab87ec33154803bfeb5ac2b379f1d6a97"><div class="ttname"><a href="vk__mem__alloc_8h.html#a6552a65b71d16f378c6994b3ceaef50cab87ec33154803bfeb5ac2b379f1d6a97">VMA_DEFRAGMENTATION_FLAG_BITS_MAX_ENUM</a></div><div class="ttdeci">@ VMA_DEFRAGMENTATION_FLAG_BITS_MAX_ENUM</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3312</div></div>
+<div class="ttc" id="astruct_vma_pool_stats_html_ab4c8f52dd42ab01998f60f0b6acc722b"><div class="ttname"><a href="struct_vma_pool_stats.html#ab4c8f52dd42ab01998f60f0b6acc722b">VmaPoolStats::unusedRangeSizeMax</a></div><div class="ttdeci">VkDeviceSize unusedRangeSizeMax</div><div class="ttdoc">Size of the largest continuous free memory region available for new allocation.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2866</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ad9889c10c798b040d59c92f257cae597ad242a04f802e25fef0b880afe8bb0a62"><div class="ttname"><a href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597ad242a04f802e25fef0b880afe8bb0a62">VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT</a></div><div class="ttdeci">@ VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2608</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a4f87c9100d154a65a4ad495f7763cf7cace7da7cc6e71a625dfa763c55a597878"><div class="ttname"><a href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7cace7da7cc6e71a625dfa763c55a597878">VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT</a></div><div class="ttdeci">@ VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT</div><div class="ttdoc">Enables usage of VK_KHR_dedicated_allocation extension.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2040</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ade56bf8dc9f5a5eaddf5f119ed525236"><div class="ttname"><a href="vk__mem__alloc_8h.html#ade56bf8dc9f5a5eaddf5f119ed525236">vmaSetCurrentFrameIndex</a></div><div class="ttdeci">void vmaSetCurrentFrameIndex(VmaAllocator allocator, uint32_t frameIndex)</div><div class="ttdoc">Sets index of the current frame.</div></div>
+<div class="ttc" id="astruct_vma_defragmentation_info_html_aa7c7304e13c71f604c907196c4e28fbc"><div class="ttname"><a href="struct_vma_defragmentation_info.html#aa7c7304e13c71f604c907196c4e28fbc">VmaDefragmentationInfo::maxAllocationsToMove</a></div><div class="ttdeci">uint32_t maxAllocationsToMove</div><div class="ttdoc">Maximum number of allocations that can be moved to different place.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3421</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ad9889c10c798b040d59c92f257cae597ab8b1764f3e9022368e440c057783b92d"><div class="ttname"><a href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597ab8b1764f3e9022368e440c057783b92d">VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT</a></div><div class="ttdeci">@ VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2599</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_aa5846affa1e9da3800e3e78fae2305cc"><div class="ttname"><a href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cc">VmaMemoryUsage</a></div><div class="ttdeci">VmaMemoryUsage</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2459</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a8701444752eb5de4464adb5a2b514bca"><div class="ttname"><a href="vk__mem__alloc_8h.html#a8701444752eb5de4464adb5a2b514bca">vmaGetMemoryTypeProperties</a></div><div class="ttdeci">void vmaGetMemoryTypeProperties(VmaAllocator allocator, uint32_t memoryTypeIndex, VkMemoryPropertyFlags *pFlags)</div><div class="ttdoc">Given Memory Type Index, returns Property Flags of this memory type.</div></div>
+<div class="ttc" id="astruct_vma_stat_info_html_abc4bb7cd611900778464c56e50c970a4"><div class="ttname"><a href="struct_vma_stat_info.html#abc4bb7cd611900778464c56e50c970a4">VmaStatInfo::blockCount</a></div><div class="ttdeci">uint32_t blockCount</div><div class="ttdoc">Number of VkDeviceMemory Vulkan memory blocks allocated.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2340</div></div>
+<div class="ttc" id="astruct_vma_pool_create_info_html_a596fa76b685d3f1f688f84a709a5b319"><div class="ttname"><a href="struct_vma_pool_create_info.html#a596fa76b685d3f1f688f84a709a5b319">VmaPoolCreateInfo::memoryTypeIndex</a></div><div class="ttdeci">uint32_t memoryTypeIndex</div><div class="ttdoc">Vulkan memory type index to allocate this pool from.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2803</div></div>
+<div class="ttc" id="astruct_vma_pool_create_info_html_aa4265160536cdb9be821b7686c16c676"><div class="ttname"><a href="struct_vma_pool_create_info.html#aa4265160536cdb9be821b7686c16c676">VmaPoolCreateInfo::blockSize</a></div><div class="ttdeci">VkDeviceSize blockSize</div><div class="ttdoc">Size of a single VkDeviceMemory block to be allocated as part of this pool, in bytes....</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2815</div></div>
+<div class="ttc" id="astruct_vma_defragmentation_info2_html_a7e70aa2a1081d849dcc7829b19d3ec9d"><div class="ttname"><a href="struct_vma_defragmentation_info2.html#a7e70aa2a1081d849dcc7829b19d3ec9d">VmaDefragmentationInfo2::poolCount</a></div><div class="ttdeci">uint32_t poolCount</div><div class="ttdoc">Numer of pools in pPools array.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3344</div></div>
+<div class="ttc" id="astruct_vma_defragmentation_pass_move_info_html"><div class="ttname"><a href="struct_vma_defragmentation_pass_move_info.html">VmaDefragmentationPassMoveInfo</a></div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3392</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_aa4fee7eb5253377599ef4fd38c93c2a0"><div class="ttname"><a href="vk__mem__alloc_8h.html#aa4fee7eb5253377599ef4fd38c93c2a0">vmaBuildStatsString</a></div><div class="ttdeci">void vmaBuildStatsString(VmaAllocator allocator, char **ppStatsString, VkBool32 detailedMap)</div><div class="ttdoc">Builds and returns statistics as string in JSON format.</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a86dd08aba8633bfa4ad0df2e76481d8b"><div class="ttname"><a href="vk__mem__alloc_8h.html#a86dd08aba8633bfa4ad0df2e76481d8b">vmaGetAllocationInfo</a></div><div class="ttdeci">void vmaGetAllocationInfo(VmaAllocator allocator, VmaAllocation allocation, VmaAllocationInfo *pAllocationInfo)</div><div class="ttdoc">Returns current information about specified allocation and atomically marks it as used in current fra...</div></div>
+<div class="ttc" id="astruct_vma_pool_stats_html_ad1924eb54fffa45e9e0e65670c8fe5eb"><div class="ttname"><a href="struct_vma_pool_stats.html#ad1924eb54fffa45e9e0e65670c8fe5eb">VmaPoolStats::allocationCount</a></div><div class="ttdeci">size_t allocationCount</div><div class="ttdoc">Number of VmaAllocation objects created from this pool that were not destroyed or lost.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2856</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_acfe6863e160722c2c1bbcf7573fddc4d"><div class="ttname"><a href="vk__mem__alloc_8h.html#acfe6863e160722c2c1bbcf7573fddc4d">VmaAllocatorCreateFlags</a></div><div class="ttdeci">VkFlags VmaAllocatorCreateFlags</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2107</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a3104eb30d8122c84dd8541063f145288"><div class="ttname"><a href="vk__mem__alloc_8h.html#a3104eb30d8122c84dd8541063f145288">vmaFreeStatsString</a></div><div class="ttdeci">void vmaFreeStatsString(VmaAllocator allocator, char *pStatsString)</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a7fdf64415b6c3d83c454f28d2c53df7b"><div class="ttname"><a href="vk__mem__alloc_8h.html#a7fdf64415b6c3d83c454f28d2c53df7b">vmaAllocateMemoryForBuffer</a></div><div class="ttdeci">VkResult vmaAllocateMemoryForBuffer(VmaAllocator allocator, VkBuffer buffer, const VmaAllocationCreateInfo *pCreateInfo, VmaAllocation *pAllocation, VmaAllocationInfo *pAllocationInfo)</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_abb0a8e3b5040d847571cca6c7f9a8074"><div class="ttname"><a href="vk__mem__alloc_8h.html#abb0a8e3b5040d847571cca6c7f9a8074">VmaVulkanFunctions</a></div><div class="ttdeci">struct VmaVulkanFunctions VmaVulkanFunctions</div><div class="ttdoc">Pointers to some Vulkan functions - a subset used by the library.</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a4f87c9100d154a65a4ad495f7763cf7cae4d5ad929caba5f23eb502b13bd5286c"><div class="ttname"><a href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7cae4d5ad929caba5f23eb502b13bd5286c">VMA_ALLOCATOR_CREATE_FLAG_BITS_MAX_ENUM</a></div><div class="ttdeci">@ VMA_ALLOCATOR_CREATE_FLAG_BITS_MAX_ENUM</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2105</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a6552a65b71d16f378c6994b3ceaef50c"><div class="ttname"><a href="vk__mem__alloc_8h.html#a6552a65b71d16f378c6994b3ceaef50c">VmaDefragmentationFlagBits</a></div><div class="ttdeci">VmaDefragmentationFlagBits</div><div class="ttdoc">Flags to be used in vmaDefragmentationBegin(). None at the moment. Reserved for future use.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3310</div></div>
+<div class="ttc" id="astruct_vma_allocation_info_html_a4a3c732388dbdc7a23f9365b00825268"><div class="ttname"><a href="struct_vma_allocation_info.html#a4a3c732388dbdc7a23f9365b00825268">VmaAllocationInfo::offset</a></div><div class="ttdeci">VkDeviceSize offset</div><div class="ttdoc">Offset into deviceMemory object to the beginning of this allocation, in bytes. (deviceMemory,...</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2995</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ad9889c10c798b040d59c92f257cae597"><div class="ttname"><a href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597">VmaAllocationCreateFlagBits</a></div><div class="ttdeci">VmaAllocationCreateFlagBits</div><div class="ttdoc">Flags to be passed as VmaAllocationCreateInfo::flags.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2527</div></div>
+<div class="ttc" id="astruct_vma_vulkan_functions_html_a60d25c33bba06bb8592e6875cbaa9830"><div class="ttname"><a href="struct_vma_vulkan_functions.html#a60d25c33bba06bb8592e6875cbaa9830">VmaVulkanFunctions::vkGetPhysicalDeviceMemoryProperties</a></div><div class="ttdeci">PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2115</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a2770e325ea42e087c1b91fdf46d0292a"><div class="ttname"><a href="vk__mem__alloc_8h.html#a2770e325ea42e087c1b91fdf46d0292a">VmaPoolCreateFlags</a></div><div class="ttdeci">VkFlags VmaPoolCreateFlags</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2796</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ae5c9657d9e94756269145b01c05d16f1"><div class="ttname"><a href="vk__mem__alloc_8h.html#ae5c9657d9e94756269145b01c05d16f1">vmaCreateLostAllocation</a></div><div class="ttdeci">void vmaCreateLostAllocation(VmaAllocator allocator, VmaAllocation *pAllocation)</div><div class="ttdoc">Creates new allocation that is in lost state from the beginning.</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a77692d3c8770ea8882d573206bd27b2b"><div class="ttname"><a href="vk__mem__alloc_8h.html#a77692d3c8770ea8882d573206bd27b2b">VmaDeviceMemoryCallbacks</a></div><div class="ttdeci">struct VmaDeviceMemoryCallbacks VmaDeviceMemoryCallbacks</div><div class="ttdoc">Set of callbacks that the library will call for vkAllocateMemory and vkFreeMemory.</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_aecabf7b6e91ea87d0316fa0a9e014fe0"><div class="ttname"><a href="vk__mem__alloc_8h.html#aecabf7b6e91ea87d0316fa0a9e014fe0">vmaGetPhysicalDeviceProperties</a></div><div class="ttdeci">void vmaGetPhysicalDeviceProperties(VmaAllocator allocator, const VkPhysicalDeviceProperties **ppPhysicalDeviceProperties)</div></div>
+<div class="ttc" id="astruct_vma_allocation_create_info_html_a6272c0555cfd1fe28bff1afeb6190150"><div class="ttname"><a href="struct_vma_allocation_create_info.html#a6272c0555cfd1fe28bff1afeb6190150">VmaAllocationCreateInfo::pool</a></div><div class="ttdeci">VmaPool pool</div><div class="ttdoc">Pool that this allocation should be created in.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2671</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ab88db292a17974f911182543fda52d19"><div class="ttname"><a href="vk__mem__alloc_8h.html#ab88db292a17974f911182543fda52d19">vmaGetMemoryProperties</a></div><div class="ttdeci">void vmaGetMemoryProperties(VmaAllocator allocator, const VkPhysicalDeviceMemoryProperties **ppPhysicalDeviceMemoryProperties)</div></div>
+<div class="ttc" id="astruct_vma_stats_html_a2e8f5b3353f2fefef3c27f29e245a1f9"><div class="ttname"><a href="struct_vma_stats.html#a2e8f5b3353f2fefef3c27f29e245a1f9">VmaStats::total</a></div><div class="ttdeci">VmaStatInfo total</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2358</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ad9889c10c798b040d59c92f257cae597a3fc311d855c2ff53f1090ef5c722b38f"><div class="ttname"><a href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a3fc311d855c2ff53f1090ef5c722b38f">VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT</a></div><div class="ttdeci">@ VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT</div><div class="ttdoc">Set this flag if the allocation should have its own memory block.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2534</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a8774e20e91e245aae959ba63efa15dd2"><div class="ttname"><a href="vk__mem__alloc_8h.html#a8774e20e91e245aae959ba63efa15dd2">vmaDefragmentationEnd</a></div><div class="ttdeci">VkResult vmaDefragmentationEnd(VmaAllocator allocator, VmaDefragmentationContext context)</div><div class="ttdoc">Ends defragmentation process.</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a4f87c9100d154a65a4ad495f7763cf7ca8fb75bf07cd184ab903596295e863dee"><div class="ttname"><a href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca8fb75bf07cd184ab903596295e863dee">VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT</a></div><div class="ttdeci">@ VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2055</div></div>
+<div class="ttc" id="astruct_vma_defragmentation_info2_html_a53e844ee5633e229cf6daf14b2d9fff9"><div class="ttname"><a href="struct_vma_defragmentation_info2.html#a53e844ee5633e229cf6daf14b2d9fff9">VmaDefragmentationInfo2::flags</a></div><div class="ttdeci">VmaDefragmentationFlags flags</div><div class="ttdoc">Reserved for future use. Should be 0.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3323</div></div>
+<div class="ttc" id="astruct_vma_vulkan_functions_html_a1338d96a128a5ade648b8d934907c637"><div class="ttname"><a href="struct_vma_vulkan_functions.html#a1338d96a128a5ade648b8d934907c637">VmaVulkanFunctions::vkBindImageMemory</a></div><div class="ttdeci">PFN_vkBindImageMemory vkBindImageMemory</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2123</div></div>
+<div class="ttc" id="astruct_vma_defragmentation_info2_html_a4ddbc898d0afe1518f863a3763628f08"><div class="ttname"><a href="struct_vma_defragmentation_info2.html#a4ddbc898d0afe1518f863a3763628f08">VmaDefragmentationInfo2::maxGpuBytesToMove</a></div><div class="ttdeci">VkDeviceSize maxGpuBytesToMove</div><div class="ttdoc">Maximum total numbers of bytes that can be copied while moving allocations to different places using ...</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3375</div></div>
+<div class="ttc" id="astruct_vma_defragmentation_stats_html"><div class="ttname"><a href="struct_vma_defragmentation_stats.html">VmaDefragmentationStats</a></div><div class="ttdoc">Statistics returned by function vmaDefragment().</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3425</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a5485779c8f1948238fc4e92232fa65e1"><div class="ttname"><a href="vk__mem__alloc_8h.html#a5485779c8f1948238fc4e92232fa65e1">vmaDestroyPool</a></div><div class="ttdeci">void vmaDestroyPool(VmaAllocator allocator, VmaPool pool)</div><div class="ttdoc">Destroys VmaPool object and frees Vulkan device memory.</div></div>
+<div class="ttc" id="astruct_vma_pool_stats_html_a326807b2de2b0931cee4ed9a5f2e420c"><div class="ttname"><a href="struct_vma_pool_stats.html#a326807b2de2b0931cee4ed9a5f2e420c">VmaPoolStats::size</a></div><div class="ttdeci">VkDeviceSize size</div><div class="ttdoc">Total amount of VkDeviceMemory allocated from Vulkan for this pool, in bytes.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2850</div></div>
+<div class="ttc" id="astruct_vma_vulkan_functions_html_a4c658701778564d62034255b5dda91b4"><div class="ttname"><a href="struct_vma_vulkan_functions.html#a4c658701778564d62034255b5dda91b4">VmaVulkanFunctions::vkFreeMemory</a></div><div class="ttdeci">PFN_vkFreeMemory vkFreeMemory</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2117</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_af3929a1a4547c592fc0b0e55ef452828"><div class="ttname"><a href="vk__mem__alloc_8h.html#af3929a1a4547c592fc0b0e55ef452828">VmaRecordFlags</a></div><div class="ttdeci">VkFlags VmaRecordFlags</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2155</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_aa5846affa1e9da3800e3e78fae2305cca40bdf4cddeffeb12f43d45ca1286e0a5"><div class="ttname"><a href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca40bdf4cddeffeb12f43d45ca1286e0a5">VMA_MEMORY_USAGE_CPU_ONLY</a></div><div class="ttdeci">@ VMA_MEMORY_USAGE_CPU_ONLY</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2491</div></div>
+<div class="ttc" id="astruct_vma_defragmentation_info2_html_a0b3effd57f3fcdeb2ed62210b4ef20e1"><div class="ttname"><a href="struct_vma_defragmentation_info2.html#a0b3effd57f3fcdeb2ed62210b4ef20e1">VmaDefragmentationInfo2::pPools</a></div><div class="ttdeci">VmaPool * pPools</div><div class="ttdoc">Either null or pointer to array of pools to be defragmented.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3360</div></div>
+<div class="ttc" id="astruct_vma_allocation_html"><div class="ttname"><a href="struct_vma_allocation.html">VmaAllocation</a></div><div class="ttdoc">Represents single memory allocation.</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_aa5846affa1e9da3800e3e78fae2305cca416a444d4d0fc20067c3f76f32ff2500"><div class="ttname"><a href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca416a444d4d0fc20067c3f76f32ff2500">VMA_MEMORY_USAGE_CPU_COPY</a></div><div class="ttdeci">@ VMA_MEMORY_USAGE_CPU_COPY</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2513</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_af9147d31ffc11d62fc187bde283ed14f"><div class="ttname"><a href="vk__mem__alloc_8h.html#af9147d31ffc11d62fc187bde283ed14f">vmaSetAllocationUserData</a></div><div class="ttdeci">void vmaSetAllocationUserData(VmaAllocator allocator, VmaAllocation allocation, void *pUserData)</div><div class="ttdoc">Sets pUserData in given allocation to new value.</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a6552a65b71d16f378c6994b3ceaef50ca31af49446af2459284a568ce2f3fdd33"><div class="ttname"><a href="vk__mem__alloc_8h.html#a6552a65b71d16f378c6994b3ceaef50ca31af49446af2459284a568ce2f3fdd33">VMA_DEFRAGMENTATION_FLAG_INCREMENTAL</a></div><div class="ttdeci">@ VMA_DEFRAGMENTATION_FLAG_INCREMENTAL</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3311</div></div>
+<div class="ttc" id="astruct_vma_allocator_create_info_html_ace2aa4877b16a42b0b7673d4e26000ee"><div class="ttname"><a href="struct_vma_allocator_create_info.html#ace2aa4877b16a42b0b7673d4e26000ee">VmaAllocatorCreateInfo::pRecordSettings</a></div><div class="ttdeci">const VmaRecordSettings * pRecordSettings</div><div class="ttdoc">Parameters for recording of VMA calls. Can be null.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2242</div></div>
+<div class="ttc" id="astruct_vma_vulkan_functions_html_a94fc4f3a605d9880bb3c0ba2c2fc80b2"><div class="ttname"><a href="struct_vma_vulkan_functions.html#a94fc4f3a605d9880bb3c0ba2c2fc80b2">VmaVulkanFunctions::vkBindBufferMemory</a></div><div class="ttdeci">PFN_vkBindBufferMemory vkBindBufferMemory</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2122</div></div>
+<div class="ttc" id="astruct_vma_vulkan_functions_html_a5b92901df89a4194b0d12f6071d4d143"><div class="ttname"><a href="struct_vma_vulkan_functions.html#a5b92901df89a4194b0d12f6071d4d143">VmaVulkanFunctions::vkGetBufferMemoryRequirements</a></div><div class="ttdeci">PFN_vkGetBufferMemoryRequirements vkGetBufferMemoryRequirements</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2124</div></div>
+<div class="ttc" id="astruct_vma_defragmentation_info2_html_a7f71f39590c5316771493d2333f9c1bd"><div class="ttname"><a href="struct_vma_defragmentation_info2.html#a7f71f39590c5316771493d2333f9c1bd">VmaDefragmentationInfo2::commandBuffer</a></div><div class="ttdeci">VkCommandBuffer commandBuffer</div><div class="ttdoc">Optional. Command buffer where GPU copy commands will be posted.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3389</div></div>
+<div class="ttc" id="astruct_vma_stats_html"><div class="ttname"><a href="struct_vma_stats.html">VmaStats</a></div><div class="ttdoc">General statistics from current state of Allocator.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2354</div></div>
+<div class="ttc" id="astruct_vma_pool_create_info_html_ad8006fb803185c0a699d30f3e9a865ae"><div class="ttname"><a href="struct_vma_pool_create_info.html#ad8006fb803185c0a699d30f3e9a865ae">VmaPoolCreateInfo::minBlockCount</a></div><div class="ttdeci">size_t minBlockCount</div><div class="ttdoc">Minimum number of blocks to be always allocated in this pool, even if they stay empty.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2820</div></div>
+<div class="ttc" id="astruct_vma_allocator_create_info_html_ae0ffc55139b54520a6bb704b29ffc285"><div class="ttname"><a href="struct_vma_allocator_create_info.html#ae0ffc55139b54520a6bb704b29ffc285">VmaAllocatorCreateInfo::vulkanApiVersion</a></div><div class="ttdeci">uint32_t vulkanApiVersion</div><div class="ttdoc">Optional. The highest version of Vulkan that the application is designed to use.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2256</div></div>
+<div class="ttc" id="astruct_vma_stat_info_html"><div class="ttname"><a href="struct_vma_stat_info.html">VmaStatInfo</a></div><div class="ttdoc">Calculated statistics of memory usage in entire allocator.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2337</div></div>
+<div class="ttc" id="astruct_vma_defragmentation_stats_html_ab0cb9ac0dbc106c77e384ea676422f28"><div class="ttname"><a href="struct_vma_defragmentation_stats.html#ab0cb9ac0dbc106c77e384ea676422f28">VmaDefragmentationStats::bytesFreed</a></div><div class="ttdeci">VkDeviceSize bytesFreed</div><div class="ttdoc">Total number of bytes that have been released to the system by freeing empty VkDeviceMemory objects.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3429</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ab9e709de044c5d8476bea77a4e755840"><div class="ttname"><a href="vk__mem__alloc_8h.html#ab9e709de044c5d8476bea77a4e755840">vmaFreeMemoryPages</a></div><div class="ttdeci">void vmaFreeMemoryPages(VmaAllocator allocator, size_t allocationCount, VmaAllocation *pAllocations)</div><div class="ttdoc">Frees memory and destroys multiple allocations.</div></div>
+<div class="ttc" id="astruct_vma_defragmentation_pass_info_html_ac1086e657ba995f8d1f4e49b83dcfb6c"><div class="ttname"><a href="struct_vma_defragmentation_pass_info.html#ac1086e657ba995f8d1f4e49b83dcfb6c">VmaDefragmentationPassInfo::moveCount</a></div><div class="ttdeci">uint32_t moveCount</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3403</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7"><div class="ttname"><a href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccac6b5dc1432d88647aa4cd456246eadf7">VMA_MEMORY_USAGE_GPU_ONLY</a></div><div class="ttdeci">@ VMA_MEMORY_USAGE_GPU_ONLY</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2481</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ac0f01545b6262f7d4d128fc8f8e5c77b"><div class="ttname"><a href="vk__mem__alloc_8h.html#ac0f01545b6262f7d4d128fc8f8e5c77b">vmaBeginDefragmentationPass</a></div><div class="ttdeci">VkResult vmaBeginDefragmentationPass(VmaAllocator allocator, VmaDefragmentationContext context, VmaDefragmentationPassInfo *pInfo)</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_aef15a94b58fbcb0fe706d5720e84a74a"><div class="ttname"><a href="vk__mem__alloc_8h.html#aef15a94b58fbcb0fe706d5720e84a74a">vmaFindMemoryTypeIndex</a></div><div class="ttdeci">VkResult vmaFindMemoryTypeIndex(VmaAllocator allocator, uint32_t memoryTypeBits, const VmaAllocationCreateInfo *pAllocationCreateInfo, uint32_t *pMemoryTypeIndex)</div><div class="ttdoc">Helps to find memoryTypeIndex, given memoryTypeBits and VmaAllocationCreateInfo.</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a5c8770ded7c59c8caac6de0c2cb00b50"><div class="ttname"><a href="vk__mem__alloc_8h.html#a5c8770ded7c59c8caac6de0c2cb00b50">vmaCreatePool</a></div><div class="ttdeci">VkResult vmaCreatePool(VmaAllocator allocator, const VmaPoolCreateInfo *pCreateInfo, VmaPool *pPool)</div><div class="ttdoc">Allocates Vulkan device memory and creates VmaPool object.</div></div>
+<div class="ttc" id="astruct_vma_stat_info_html_a1859d290aca2cd582d8dc25922092669"><div class="ttname"><a href="struct_vma_stat_info.html#a1859d290aca2cd582d8dc25922092669">VmaStatInfo::unusedBytes</a></div><div class="ttdeci">VkDeviceSize unusedBytes</div><div class="ttdoc">Total number of bytes occupied by unused ranges.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2348</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a4f87c9100d154a65a4ad495f7763cf7ca5f1b28b0414319d1687e1f2b30ab0089"><div class="ttname"><a href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca5f1b28b0414319d1687e1f2b30ab0089">VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT</a></div><div class="ttdeci">@ VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2103</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ad37e82e492b3de38fc3f4cffd9ad0ae1"><div class="ttname"><a href="vk__mem__alloc_8h.html#ad37e82e492b3de38fc3f4cffd9ad0ae1">vmaAllocateMemoryPages</a></div><div class="ttdeci">VkResult vmaAllocateMemoryPages(VmaAllocator allocator, const VkMemoryRequirements *pVkMemoryRequirements, const VmaAllocationCreateInfo *pCreateInfo, size_t allocationCount, VmaAllocation *pAllocations, VmaAllocationInfo *pAllocationInfo)</div><div class="ttdoc">General purpose memory allocation for multiple allocation objects at once.</div></div>
+<div class="ttc" id="astruct_vma_stat_info_html_ab0c6c73837e5a70c749fbd4f6064895a"><div class="ttname"><a href="struct_vma_stat_info.html#ab0c6c73837e5a70c749fbd4f6064895a">VmaStatInfo::usedBytes</a></div><div class="ttdeci">VkDeviceSize usedBytes</div><div class="ttdoc">Total number of bytes occupied by all allocations.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2346</div></div>
+<div class="ttc" id="astruct_vma_allocator_create_info_html_a6e409087e3be55400d0e4ccbe43c608d"><div class="ttname"><a href="struct_vma_allocator_create_info.html#a6e409087e3be55400d0e4ccbe43c608d">VmaAllocatorCreateInfo::pAllocationCallbacks</a></div><div class="ttdeci">const VkAllocationCallbacks * pAllocationCallbacks</div><div class="ttdoc">Custom CPU memory allocation callbacks. Optional.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2188</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a4f87c9100d154a65a4ad495f7763cf7c"><div class="ttname"><a href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7c">VmaAllocatorCreateFlagBits</a></div><div class="ttdeci">VmaAllocatorCreateFlagBits</div><div class="ttdoc">Flags for created VmaAllocator.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2010</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a0faa3f9e5fb233d29d1e00390650febb"><div class="ttname"><a href="vk__mem__alloc_8h.html#a0faa3f9e5fb233d29d1e00390650febb">vmaAllocateMemoryForImage</a></div><div class="ttdeci">VkResult vmaAllocateMemoryForImage(VmaAllocator allocator, VkImage image, const VmaAllocationCreateInfo *pCreateInfo, VmaAllocation *pAllocation, VmaAllocationInfo *pAllocationInfo)</div><div class="ttdoc">Function similar to vmaAllocateMemoryForBuffer().</div></div>
+<div class="ttc" id="astruct_vma_pool_create_info_html_ae41142f2834fcdc82baa4883c187b75c"><div class="ttname"><a href="struct_vma_pool_create_info.html#ae41142f2834fcdc82baa4883c187b75c">VmaPoolCreateInfo::maxBlockCount</a></div><div class="ttdeci">size_t maxBlockCount</div><div class="ttdoc">Maximum number of blocks that can be allocated in this pool. Optional.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2828</div></div>
+<div class="ttc" id="astruct_vma_pool_create_info_html"><div class="ttname"><a href="struct_vma_pool_create_info.html">VmaPoolCreateInfo</a></div><div class="ttdoc">Describes parameter of created VmaPool.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2800</div></div>
+<div class="ttc" id="astruct_vma_device_memory_callbacks_html_a4f17f7b255101e733b44d5633aceabfb"><div class="ttname"><a href="struct_vma_device_memory_callbacks.html#a4f17f7b255101e733b44d5633aceabfb">VmaDeviceMemoryCallbacks::pfnAllocate</a></div><div class="ttdeci">PFN_vmaAllocateDeviceMemoryFunction pfnAllocate</div><div class="ttdoc">Optional, can be null.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2002</div></div>
+<div class="ttc" id="astruct_vma_pool_html"><div class="ttname"><a href="struct_vma_pool.html">VmaPool</a></div><div class="ttdoc">Represents custom memory pool.</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_aa5846affa1e9da3800e3e78fae2305cca7b586d2fdaf82a463b58f581ed72be27"><div class="ttname"><a href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca7b586d2fdaf82a463b58f581ed72be27">VMA_MEMORY_USAGE_GPU_TO_CPU</a></div><div class="ttdeci">@ VMA_MEMORY_USAGE_GPU_TO_CPU</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2507</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ad9889c10c798b040d59c92f257cae597a68686d0ce9beb0d4d1b9f2b8b1389a7e"><div class="ttname"><a href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a68686d0ce9beb0d4d1b9f2b8b1389a7e">VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT</a></div><div class="ttdeci">@ VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2578</div></div>
+<div class="ttc" id="astruct_vma_pool_create_info_html_a8405139f63d078340ae74513a59f5446"><div class="ttname"><a href="struct_vma_pool_create_info.html#a8405139f63d078340ae74513a59f5446">VmaPoolCreateInfo::flags</a></div><div class="ttdeci">VmaPoolCreateFlags flags</div><div class="ttdoc">Use combination of VmaPoolCreateFlagBits.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2806</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_aa5846affa1e9da3800e3e78fae2305cca091e69437ef693e8d0d287f1c719ba6e"><div class="ttname"><a href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca091e69437ef693e8d0d287f1c719ba6e">VMA_MEMORY_USAGE_MAX_ENUM</a></div><div class="ttdeci">@ VMA_MEMORY_USAGE_MAX_ENUM</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2523</div></div>
+<div class="ttc" id="astruct_vma_stat_info_html_a537741e4d5cdddc1c0ab95ec650afaff"><div class="ttname"><a href="struct_vma_stat_info.html#a537741e4d5cdddc1c0ab95ec650afaff">VmaStatInfo::allocationCount</a></div><div class="ttdeci">uint32_t allocationCount</div><div class="ttdoc">Number of VmaAllocation allocation objects allocated.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2342</div></div>
+<div class="ttc" id="astruct_vma_vulkan_functions_html_a5c1093bc32386a8060c37c9f282078a1"><div class="ttname"><a href="struct_vma_vulkan_functions.html#a5c1093bc32386a8060c37c9f282078a1">VmaVulkanFunctions::vkInvalidateMappedMemoryRanges</a></div><div class="ttdeci">PFN_vkInvalidateMappedMemoryRanges vkInvalidateMappedMemoryRanges</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2121</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_abf28077dbf82d0908b8acbe8ee8dd9b8"><div class="ttname"><a href="vk__mem__alloc_8h.html#abf28077dbf82d0908b8acbe8ee8dd9b8">vmaAllocateMemory</a></div><div class="ttdeci">VkResult vmaAllocateMemory(VmaAllocator allocator, const VkMemoryRequirements *pVkMemoryRequirements, const VmaAllocationCreateInfo *pCreateInfo, VmaAllocation *pAllocation, VmaAllocationInfo *pAllocationInfo)</div><div class="ttdoc">General purpose memory allocation.</div></div>
+<div class="ttc" id="astruct_vma_defragmentation_info2_html"><div class="ttname"><a href="struct_vma_defragmentation_info2.html">VmaDefragmentationInfo2</a></div><div class="ttdoc">Parameters for defragmentation.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3320</div></div>
+<div class="ttc" id="astruct_vma_defragmentation_info_html_acb311c940a777270e67e1b81c5ab6a1d"><div class="ttname"><a href="struct_vma_defragmentation_info.html#acb311c940a777270e67e1b81c5ab6a1d">VmaDefragmentationInfo::maxBytesToMove</a></div><div class="ttdeci">VkDeviceSize maxBytesToMove</div><div class="ttdoc">Maximum total numbers of bytes that can be copied while moving allocations to different places.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3416</div></div>
+<div class="ttc" id="astruct_vma_budget_html_a58b492901baab685f466199124e514a0"><div class="ttname"><a href="struct_vma_budget.html#a58b492901baab685f466199124e514a0">VmaBudget::blockBytes</a></div><div class="ttdeci">VkDeviceSize blockBytes</div><div class="ttdoc">Sum size of all VkDeviceMemory blocks allocated from particular heap, in bytes.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2380</div></div>
+<div class="ttc" id="astruct_vma_allocator_info_html"><div class="ttname"><a href="struct_vma_allocator_info.html">VmaAllocatorInfo</a></div><div class="ttdoc">Information about existing VmaAllocator object.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2270</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a9a7c45f9c863695d98c83fa5ac940fe7a1c7312bea9ea246846b9054fd6bd6aec"><div class="ttname"><a href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a1c7312bea9ea246846b9054fd6bd6aec">VMA_POOL_CREATE_FLAG_BITS_MAX_ENUM</a></div><div class="ttdeci">@ VMA_POOL_CREATE_FLAG_BITS_MAX_ENUM</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2794</div></div>
+<div class="ttc" id="astruct_vma_allocation_create_info_html_a9166390303ff42d783305bc31c2b6b90"><div class="ttname"><a href="struct_vma_allocation_create_info.html#a9166390303ff42d783305bc31c2b6b90">VmaAllocationCreateInfo::requiredFlags</a></div><div class="ttdeci">VkMemoryPropertyFlags requiredFlags</div><div class="ttdoc">Flags that must be set in a Memory Type chosen for an allocation.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2652</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ad9889c10c798b040d59c92f257cae597a621b704103eb3360230c860acf36e706"><div class="ttname"><a href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a621b704103eb3360230c860acf36e706">VMA_ALLOCATION_CREATE_STRATEGY_MIN_FRAGMENTATION_BIT</a></div><div class="ttdeci">@ VMA_ALLOCATION_CREATE_STRATEGY_MIN_FRAGMENTATION_BIT</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2625</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_aec5b57e29c97b5d69c6d5654d60df878"><div class="ttname"><a href="vk__mem__alloc_8h.html#aec5b57e29c97b5d69c6d5654d60df878">VmaStatInfo</a></div><div class="ttdeci">struct VmaStatInfo VmaStatInfo</div><div class="ttdoc">Calculated statistics of memory usage in entire allocator.</div></div>
+<div class="ttc" id="astruct_vma_stat_info_html_a1081a039964e566c672e7a2347f9e599"><div class="ttname"><a href="struct_vma_stat_info.html#a1081a039964e566c672e7a2347f9e599">VmaStatInfo::allocationSizeAvg</a></div><div class="ttdeci">VkDeviceSize allocationSizeAvg</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2349</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_aa8d164061c88f22fb1fd3c8f3534bc1d"><div class="ttname"><a href="vk__mem__alloc_8h.html#aa8d164061c88f22fb1fd3c8f3534bc1d">vmaDestroyAllocator</a></div><div class="ttdeci">void vmaDestroyAllocator(VmaAllocator allocator)</div><div class="ttdoc">Destroys allocator object.</div></div>
+<div class="ttc" id="astruct_vma_allocator_create_info_html_af1380969b5e1ea4c3184a877892d260e"><div class="ttname"><a href="struct_vma_allocator_create_info.html#af1380969b5e1ea4c3184a877892d260e">VmaAllocatorCreateInfo::pDeviceMemoryCallbacks</a></div><div class="ttdeci">const VmaDeviceMemoryCallbacks * pDeviceMemoryCallbacks</div><div class="ttdoc">Informative callbacks for vkAllocateMemory, vkFreeMemory. Optional.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2191</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ad9889c10c798b040d59c92f257cae597a8e16845d81ae3d27c47106d4770d5c7e"><div class="ttname"><a href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a8e16845d81ae3d27c47106d4770d5c7e">VMA_ALLOCATION_CREATE_STRATEGY_MASK</a></div><div class="ttdeci">@ VMA_ALLOCATION_CREATE_STRATEGY_MASK</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2629</div></div>
+<div class="ttc" id="astruct_vma_allocator_create_info_html_ad924ddd77b04039c88d0c09b0ffcd500"><div class="ttname"><a href="struct_vma_allocator_create_info.html#ad924ddd77b04039c88d0c09b0ffcd500">VmaAllocatorCreateInfo::device</a></div><div class="ttdeci">VkDevice device</div><div class="ttdoc">Vulkan device.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2182</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a088da83d8eaf3ce9056d9ea0b981d472"><div class="ttname"><a href="vk__mem__alloc_8h.html#a088da83d8eaf3ce9056d9ea0b981d472">vmaFindMemoryTypeIndexForImageInfo</a></div><div class="ttdeci">VkResult vmaFindMemoryTypeIndexForImageInfo(VmaAllocator allocator, const VkImageCreateInfo *pImageCreateInfo, const VmaAllocationCreateInfo *pAllocationCreateInfo, uint32_t *pMemoryTypeIndex)</div><div class="ttdoc">Helps to find memoryTypeIndex, given VkImageCreateInfo and VmaAllocationCreateInfo.</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ad5bd1243512d099706de88168992f069"><div class="ttname"><a href="vk__mem__alloc_8h.html#ad5bd1243512d099706de88168992f069">vmaMapMemory</a></div><div class="ttdeci">VkResult vmaMapMemory(VmaAllocator allocator, VmaAllocation allocation, void **ppData)</div><div class="ttdoc">Maps memory represented by given allocation and returns pointer to it.</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a6b0929b914b60cf2d45cac4bf3547470"><div class="ttname"><a href="vk__mem__alloc_8h.html#a6b0929b914b60cf2d45cac4bf3547470">vmaBindBufferMemory</a></div><div class="ttdeci">VkResult vmaBindBufferMemory(VmaAllocator allocator, VmaAllocation allocation, VkBuffer buffer)</div><div class="ttdoc">Binds buffer to allocation.</div></div>
+<div class="ttc" id="astruct_vma_allocator_create_info_html_a31c192aa6cbffa33279f6d9f0c47c44b"><div class="ttname"><a href="struct_vma_allocator_create_info.html#a31c192aa6cbffa33279f6d9f0c47c44b">VmaAllocatorCreateInfo::pHeapSizeLimit</a></div><div class="ttdeci">const VkDeviceSize * pHeapSizeLimit</div><div class="ttdoc">Either null or a pointer to an array of limits on maximum number of bytes that can be allocated out o...</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2230</div></div>
+<div class="ttc" id="astruct_vma_defragmentation_pass_move_info_html_ae885c861c2dd8d622e6c19e281d035cc"><div class="ttname"><a href="struct_vma_defragmentation_pass_move_info.html#ae885c861c2dd8d622e6c19e281d035cc">VmaDefragmentationPassMoveInfo::allocation</a></div><div class="ttdeci">VmaAllocation allocation</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3393</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a02a94f25679275851a53e82eacbcfc73"><div class="ttname"><a href="vk__mem__alloc_8h.html#a02a94f25679275851a53e82eacbcfc73">vmaCreateImage</a></div><div class="ttdeci">VkResult vmaCreateImage(VmaAllocator allocator, const VkImageCreateInfo *pImageCreateInfo, const VmaAllocationCreateInfo *pAllocationCreateInfo, VkImage *pImage, VmaAllocation *pAllocation, VmaAllocationInfo *pAllocationInfo)</div><div class="ttdoc">Function similar to vmaCreateBuffer().</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ae790ab9ffaf7667fb8f62523e6897888"><div class="ttname"><a href="vk__mem__alloc_8h.html#ae790ab9ffaf7667fb8f62523e6897888">vmaFindMemoryTypeIndexForBufferInfo</a></div><div class="ttdeci">VkResult vmaFindMemoryTypeIndexForBufferInfo(VmaAllocator allocator, const VkBufferCreateInfo *pBufferCreateInfo, const VmaAllocationCreateInfo *pAllocationCreateInfo, uint32_t *pMemoryTypeIndex)</div><div class="ttdoc">Helps to find memoryTypeIndex, given VkBufferCreateInfo and VmaAllocationCreateInfo.</div></div>
+<div class="ttc" id="astruct_vma_budget_html_ab82e1d1754c2d210d0bdf90220bc6cdd"><div class="ttname"><a href="struct_vma_budget.html#ab82e1d1754c2d210d0bdf90220bc6cdd">VmaBudget::budget</a></div><div class="ttdeci">VkDeviceSize budget</div><div class="ttdoc">Estimated amount of memory available to the program, in bytes.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2412</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a4759a2d9f99c19ba7627553c847132f1"><div class="ttname"><a href="vk__mem__alloc_8h.html#a4759a2d9f99c19ba7627553c847132f1">VmaPoolStats</a></div><div class="ttdeci">struct VmaPoolStats VmaPoolStats</div><div class="ttdoc">Describes parameter of existing VmaPool.</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a72aebd522242d56abea67b4f47f6549e"><div class="ttname"><a href="vk__mem__alloc_8h.html#a72aebd522242d56abea67b4f47f6549e">VmaDefragmentationPassInfo</a></div><div class="ttdeci">struct VmaDefragmentationPassInfo VmaDefragmentationPassInfo</div><div class="ttdoc">Parameters for incremental defragmentation steps.</div></div>
+<div class="ttc" id="astruct_vma_vulkan_functions_html"><div class="ttname"><a href="struct_vma_vulkan_functions.html">VmaVulkanFunctions</a></div><div class="ttdoc">Pointers to some Vulkan functions - a subset used by the library.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2113</div></div>
+<div class="ttc" id="astruct_vma_allocation_info_html_a5eeffbe2d2f30f53370ff14aefbadbe2"><div class="ttname"><a href="struct_vma_allocation_info.html#a5eeffbe2d2f30f53370ff14aefbadbe2">VmaAllocationInfo::pMappedData</a></div><div class="ttdeci">void * pMappedData</div><div class="ttdoc">Pointer to the beginning of this allocation as mapped data.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3009</div></div>
+<div class="ttc" id="astruct_vma_allocator_create_info_html_a392ea2ecbaff93f91a7c49f735ad4346"><div class="ttname"><a href="struct_vma_allocator_create_info.html#a392ea2ecbaff93f91a7c49f735ad4346">VmaAllocatorCreateInfo::flags</a></div><div class="ttdeci">VmaAllocatorCreateFlags flags</div><div class="ttdoc">Flags for created allocator. Use VmaAllocatorCreateFlagBits enum.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2176</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a88a77cef37e5d3c4fc9eb328885d048d"><div class="ttname"><a href="vk__mem__alloc_8h.html#a88a77cef37e5d3c4fc9eb328885d048d">VmaDefragmentationFlags</a></div><div class="ttdeci">VkFlags VmaDefragmentationFlags</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3314</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ae8bf76997b234ef68aad922616df4153"><div class="ttname"><a href="vk__mem__alloc_8h.html#ae8bf76997b234ef68aad922616df4153">vmaGetPoolStats</a></div><div class="ttdeci">void vmaGetPoolStats(VmaAllocator allocator, VmaPool pool, VmaPoolStats *pPoolStats)</div><div class="ttdoc">Retrieves statistics of existing VmaPool object.</div></div>
+<div class="ttc" id="astruct_vma_vulkan_functions_html_a23ebe70be515b9b5010a1d691200e325"><div class="ttname"><a href="struct_vma_vulkan_functions.html#a23ebe70be515b9b5010a1d691200e325">VmaVulkanFunctions::vkCreateImage</a></div><div class="ttdeci">PFN_vkCreateImage vkCreateImage</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2128</div></div>
+<div class="ttc" id="astruct_vma_device_memory_callbacks_html_a24052de0937ddd54015a2df0363903c6"><div class="ttname"><a href="struct_vma_device_memory_callbacks.html#a24052de0937ddd54015a2df0363903c6">VmaDeviceMemoryCallbacks::pUserData</a></div><div class="ttdeci">void * pUserData</div><div class="ttdoc">Optional, can be null.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2006</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a16e21c877101493fce582664cd8754fc"><div class="ttname"><a href="vk__mem__alloc_8h.html#a16e21c877101493fce582664cd8754fc">VmaRecordSettings</a></div><div class="ttdeci">struct VmaRecordSettings VmaRecordSettings</div><div class="ttdoc">Parameters for recording calls to VMA functions. To be used in VmaAllocatorCreateInfo::pRecordSetting...</div></div>
+<div class="ttc" id="astruct_vma_stat_info_html_a2f9b3452af90c9768a30b7fb6ae194fc"><div class="ttname"><a href="struct_vma_stat_info.html#a2f9b3452af90c9768a30b7fb6ae194fc">VmaStatInfo::unusedRangeSizeAvg</a></div><div class="ttdeci">VkDeviceSize unusedRangeSizeAvg</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2350</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_aa5846affa1e9da3800e3e78fae2305cca9066b52c5a7079bb74a69aaf8b92ff67"><div class="ttname"><a href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305cca9066b52c5a7079bb74a69aaf8b92ff67">VMA_MEMORY_USAGE_CPU_TO_GPU</a></div><div class="ttdeci">@ VMA_MEMORY_USAGE_CPU_TO_GPU</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2498</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ad9889c10c798b040d59c92f257cae597a0729e932b7ea170e3a128cad96c5cf6d"><div class="ttname"><a href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a0729e932b7ea170e3a128cad96c5cf6d">VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT</a></div><div class="ttdeci">@ VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2622</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ad9889c10c798b040d59c92f257cae597a8af1210cf591784afa026d94998f735d"><div class="ttname"><a href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a8af1210cf591784afa026d94998f735d">VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT</a></div><div class="ttdeci">@ VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2619</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a4f87c9100d154a65a4ad495f7763cf7ca2acce4886d8078552efa38878413970f"><div class="ttname"><a href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca2acce4886d8078552efa38878413970f">VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT</a></div><div class="ttdeci">@ VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2085</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ad94034192259c2e34a4d1c5e27810403"><div class="ttname"><a href="vk__mem__alloc_8h.html#ad94034192259c2e34a4d1c5e27810403">VmaDefragmentationStats</a></div><div class="ttdeci">struct VmaDefragmentationStats VmaDefragmentationStats</div><div class="ttdoc">Statistics returned by function vmaDefragment().</div></div>
+<div class="ttc" id="astruct_vma_allocation_create_info_html_accb8b06b1f677d858cb9af20705fa910"><div class="ttname"><a href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910">VmaAllocationCreateInfo::usage</a></div><div class="ttdeci">VmaMemoryUsage usage</div><div class="ttdoc">Intended usage of memory.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2647</div></div>
+<div class="ttc" id="astruct_vma_stat_info_html_ade8b40bd3139c04aabd2fc538a356fea"><div class="ttname"><a href="struct_vma_stat_info.html#ade8b40bd3139c04aabd2fc538a356fea">VmaStatInfo::allocationSizeMin</a></div><div class="ttdeci">VkDeviceSize allocationSizeMin</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2349</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a927c944f45e0f2941182abb6f608e64a"><div class="ttname"><a href="vk__mem__alloc_8h.html#a927c944f45e0f2941182abb6f608e64a">vmaBindBufferMemory2</a></div><div class="ttdeci">VkResult vmaBindBufferMemory2(VmaAllocator allocator, VmaAllocation allocation, VkDeviceSize allocationLocalOffset, VkBuffer buffer, const void *pNext)</div><div class="ttdoc">Binds buffer to allocation with additional parameters.</div></div>
+<div class="ttc" id="astruct_vma_allocation_info_html_aac76d113a6a5ccbb09fea00fb25fd18f"><div class="ttname"><a href="struct_vma_allocation_info.html#aac76d113a6a5ccbb09fea00fb25fd18f">VmaAllocationInfo::size</a></div><div class="ttdeci">VkDeviceSize size</div><div class="ttdoc">Size of this allocation, in bytes.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3000</div></div>
+<div class="ttc" id="astruct_vma_record_settings_html_ad8fdcc92119ae7a8c08c1a564c01d63a"><div class="ttname"><a href="struct_vma_record_settings.html#ad8fdcc92119ae7a8c08c1a564c01d63a">VmaRecordSettings::flags</a></div><div class="ttdeci">VmaRecordFlags flags</div><div class="ttdoc">Flags for recording. Use VmaRecordFlagBits enum.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2161</div></div>
+<div class="ttc" id="astruct_vma_vulkan_functions_html_a33c322f4c4ad2810f8a9c97a277572f9"><div class="ttname"><a href="struct_vma_vulkan_functions.html#a33c322f4c4ad2810f8a9c97a277572f9">VmaVulkanFunctions::vkFlushMappedMemoryRanges</a></div><div class="ttdeci">PFN_vkFlushMappedMemoryRanges vkFlushMappedMemoryRanges</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2120</div></div>
+<div class="ttc" id="astruct_vma_allocation_info_html_adc507656149c04de7ed95d0042ba2a13"><div class="ttname"><a href="struct_vma_allocation_info.html#adc507656149c04de7ed95d0042ba2a13">VmaAllocationInfo::pUserData</a></div><div class="ttdeci">void * pUserData</div><div class="ttdoc">Custom general-purpose pointer that was passed as VmaAllocationCreateInfo::pUserData or set using vma...</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3014</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a736bd6cbda886f36c891727e73bd4024"><div class="ttname"><a href="vk__mem__alloc_8h.html#a736bd6cbda886f36c891727e73bd4024">vmaMakePoolAllocationsLost</a></div><div class="ttdeci">void vmaMakePoolAllocationsLost(VmaAllocator allocator, VmaPool pool, size_t *pLostAllocationCount)</div><div class="ttdoc">Marks all allocations in given pool as lost if they are not used in current frame or VmaPoolCreateInf...</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a9a7c45f9c863695d98c83fa5ac940fe7a9f1a499508a8edb4e8ba40aa0290a3d2"><div class="ttname"><a href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a9f1a499508a8edb4e8ba40aa0290a3d2">VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT</a></div><div class="ttdeci">@ VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT</div><div class="ttdoc">Use this flag if you always allocate only buffers and linear images or only optimal images out of thi...</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2758</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ac72ee55598617e8eecca384e746bab51"><div class="ttname"><a href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer</a></div><div class="ttdeci">VkResult vmaCreateBuffer(VmaAllocator allocator, const VkBufferCreateInfo *pBufferCreateInfo, const VmaAllocationCreateInfo *pAllocationCreateInfo, VkBuffer *pBuffer, VmaAllocation *pAllocation, VmaAllocationInfo *pAllocationInfo)</div></div>
+<div class="ttc" id="astruct_vma_stats_html_a0e6611508c29a187f0fd14ff1a0329c0"><div class="ttname"><a href="struct_vma_stats.html#a0e6611508c29a187f0fd14ff1a0329c0">VmaStats::memoryHeap</a></div><div class="ttdeci">VmaStatInfo memoryHeap[VK_MAX_MEMORY_HEAPS]</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2357</div></div>
+<div class="ttc" id="astruct_vma_allocator_create_info_html_a3dc197be3227da7338b1643f70db36bd"><div class="ttname"><a href="struct_vma_allocator_create_info.html#a3dc197be3227da7338b1643f70db36bd">VmaAllocatorCreateInfo::pVulkanFunctions</a></div><div class="ttdeci">const VmaVulkanFunctions * pVulkanFunctions</div><div class="ttdoc">Pointers to Vulkan functions. Can be null.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2235</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_aad9652301d33759b83e52d4f3605a14a"><div class="ttname"><a href="vk__mem__alloc_8h.html#aad9652301d33759b83e52d4f3605a14a">VmaAllocatorCreateInfo</a></div><div class="ttdeci">struct VmaAllocatorCreateInfo VmaAllocatorCreateInfo</div><div class="ttdoc">Description of a Allocator to be created.</div></div>
+<div class="ttc" id="astruct_vma_pool_stats_html_aa0b5cb45cef6f18571cefb03b9a230e7"><div class="ttname"><a href="struct_vma_pool_stats.html#aa0b5cb45cef6f18571cefb03b9a230e7">VmaPoolStats::blockCount</a></div><div class="ttdeci">size_t blockCount</div><div class="ttdoc">Number of VkDeviceMemory blocks allocated for this pool.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2869</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a200692051ddb34240248234f5f4c17bb"><div class="ttname"><a href="vk__mem__alloc_8h.html#a200692051ddb34240248234f5f4c17bb">vmaCreateAllocator</a></div><div class="ttdeci">VkResult vmaCreateAllocator(const VmaAllocatorCreateInfo *pCreateInfo, VmaAllocator *pAllocator)</div><div class="ttdoc">Creates Allocator object.</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a6aced90fcc7b39882b6654a740a0b9bb"><div class="ttname"><a href="vk__mem__alloc_8h.html#a6aced90fcc7b39882b6654a740a0b9bb">vmaDefragment</a></div><div class="ttdeci">VkResult vmaDefragment(VmaAllocator allocator, VmaAllocation *pAllocations, size_t allocationCount, VkBool32 *pAllocationsChanged, const VmaDefragmentationInfo *pDefragmentationInfo, VmaDefragmentationStats *pDefragmentationStats)</div><div class="ttdoc">Deprecated. Compacts memory by moving allocations.</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a49329a7f030dafcf82f7b73334c22e98"><div class="ttname"><a href="vk__mem__alloc_8h.html#a49329a7f030dafcf82f7b73334c22e98">vmaCheckCorruption</a></div><div class="ttdeci">VkResult vmaCheckCorruption(VmaAllocator allocator, uint32_t memoryTypeBits)</div><div class="ttdoc">Checks magic number in margins around all allocations in given memory types (in both default and cust...</div></div>
+<div class="ttc" id="astruct_vma_defragmentation_pass_info_html"><div class="ttname"><a href="struct_vma_defragmentation_pass_info.html">VmaDefragmentationPassInfo</a></div><div class="ttdoc">Parameters for incremental defragmentation steps.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3402</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a5225e5e11f8376f6a31a1791f3d6e817"><div class="ttname"><a href="vk__mem__alloc_8h.html#a5225e5e11f8376f6a31a1791f3d6e817">VmaAllocationCreateFlags</a></div><div class="ttdeci">VkFlags VmaAllocationCreateFlags</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2636</div></div>
+<div class="ttc" id="astruct_vma_stats_html_a13e3caf754be79352c42408756309331"><div class="ttname"><a href="struct_vma_stats.html#a13e3caf754be79352c42408756309331">VmaStats::memoryType</a></div><div class="ttdeci">VmaStatInfo memoryType[VK_MAX_MEMORY_TYPES]</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2356</div></div>
+<div class="ttc" id="astruct_vma_allocator_create_info_html_a70dd42e29b1df1d1b9b61532ae0b370b"><div class="ttname"><a href="struct_vma_allocator_create_info.html#a70dd42e29b1df1d1b9b61532ae0b370b">VmaAllocatorCreateInfo::instance</a></div><div class="ttdeci">VkInstance instance</div><div class="ttdoc">Handle to Vulkan instance object.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2247</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_abc34ee6f021f459aff885f3758c435de"><div class="ttname"><a href="vk__mem__alloc_8h.html#abc34ee6f021f459aff885f3758c435de">vmaFlushAllocation</a></div><div class="ttdeci">void vmaFlushAllocation(VmaAllocator allocator, VmaAllocation allocation, VkDeviceSize offset, VkDeviceSize size)</div><div class="ttdoc">Flushes memory of given allocation.</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_aa5846affa1e9da3800e3e78fae2305ccaf50d27e34e0925cf3a63db8c839121dd"><div class="ttname"><a href="vk__mem__alloc_8h.html#aa5846affa1e9da3800e3e78fae2305ccaf50d27e34e0925cf3a63db8c839121dd">VMA_MEMORY_USAGE_UNKNOWN</a></div><div class="ttdeci">@ VMA_MEMORY_USAGE_UNKNOWN</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2464</div></div>
+<div class="ttc" id="astruct_vma_defragmentation_info2_html_a40d53d33e71ba0b66f844ed63c05a3f6"><div class="ttname"><a href="struct_vma_defragmentation_info2.html#a40d53d33e71ba0b66f844ed63c05a3f6">VmaDefragmentationInfo2::maxGpuAllocationsToMove</a></div><div class="ttdeci">uint32_t maxGpuAllocationsToMove</div><div class="ttdoc">Maximum number of allocations that can be moved to a different place using transfers on GPU side,...</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3380</div></div>
+<div class="ttc" id="astruct_vma_vulkan_functions_html_a7e054606faddb07f0e8556f3ed317d45"><div class="ttname"><a href="struct_vma_vulkan_functions.html#a7e054606faddb07f0e8556f3ed317d45">VmaVulkanFunctions::vkDestroyBuffer</a></div><div class="ttdeci">PFN_vkDestroyBuffer vkDestroyBuffer</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2127</div></div>
+<div class="ttc" id="astruct_vma_pool_create_info_html_a9437e43ffbb644dbbf7fc4e50cfad6aa"><div class="ttname"><a href="struct_vma_pool_create_info.html#a9437e43ffbb644dbbf7fc4e50cfad6aa">VmaPoolCreateInfo::frameInUseCount</a></div><div class="ttdeci">uint32_t frameInUseCount</div><div class="ttdoc">Maximum number of additional frames that are in use at the same time as current frame.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2842</div></div>
+<div class="ttc" id="astruct_vma_vulkan_functions_html_a90b898227039b1dcb3520f6e91f09ffa"><div class="ttname"><a href="struct_vma_vulkan_functions.html#a90b898227039b1dcb3520f6e91f09ffa">VmaVulkanFunctions::vkDestroyImage</a></div><div class="ttdeci">PFN_vkDestroyImage vkDestroyImage</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2129</div></div>
+<div class="ttc" id="astruct_vma_defragmentation_info2_html_af78e1ea40c22d85137b65f6b384a4d0a"><div class="ttname"><a href="struct_vma_defragmentation_info2.html#af78e1ea40c22d85137b65f6b384a4d0a">VmaDefragmentationInfo2::maxCpuBytesToMove</a></div><div class="ttdeci">VkDeviceSize maxCpuBytesToMove</div><div class="ttdoc">Maximum total numbers of bytes that can be copied while moving allocations to different places using ...</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3365</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a1017aa83489c0eee8d2163d2bf253f67"><div class="ttname"><a href="vk__mem__alloc_8h.html#a1017aa83489c0eee8d2163d2bf253f67">VmaPoolCreateInfo</a></div><div class="ttdeci">struct VmaPoolCreateInfo VmaPoolCreateInfo</div><div class="ttdoc">Describes parameter of created VmaPool.</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_af09b4e4eafdbee812e8d73ddf960f030"><div class="ttname"><a href="vk__mem__alloc_8h.html#af09b4e4eafdbee812e8d73ddf960f030">vmaGetPoolName</a></div><div class="ttdeci">void vmaGetPoolName(VmaAllocator allocator, VmaPool pool, const char **ppName)</div><div class="ttdoc">Retrieves name of a custom pool.</div></div>
+<div class="ttc" id="astruct_vma_allocation_info_html_a7f6b0aa58c135e488e6b40a388dad9d5"><div class="ttname"><a href="struct_vma_allocation_info.html#a7f6b0aa58c135e488e6b40a388dad9d5">VmaAllocationInfo::memoryType</a></div><div class="ttdeci">uint32_t memoryType</div><div class="ttdoc">Memory type index that this allocation was allocated from.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2981</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ae50d2cb3b4a3bfd4dd40987234e50e7e"><div class="ttname"><a href="vk__mem__alloc_8h.html#ae50d2cb3b4a3bfd4dd40987234e50e7e">vmaDestroyImage</a></div><div class="ttdeci">void vmaDestroyImage(VmaAllocator allocator, VkImage image, VmaAllocation allocation)</div><div class="ttdoc">Destroys Vulkan image and frees allocated memory.</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ad9889c10c798b040d59c92f257cae597a11da372cc3a82931c5e5d6146cd9dd1f"><div class="ttname"><a href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a11da372cc3a82931c5e5d6146cd9dd1f">VMA_ALLOCATION_CREATE_MAPPED_BIT</a></div><div class="ttdeci">@ VMA_ALLOCATION_CREATE_MAPPED_BIT</div><div class="ttdoc">Set this flag to use a memory that will be persistently mapped and retrieve pointer to it.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2558</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a333b61c1788cb23559177531e6a93ca3"><div class="ttname"><a href="vk__mem__alloc_8h.html#a333b61c1788cb23559177531e6a93ca3">vmaCalculateStats</a></div><div class="ttdeci">void vmaCalculateStats(VmaAllocator allocator, VmaStats *pStats)</div><div class="ttdoc">Retrieves statistics from current state of the Allocator.</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a0d9f4e4ba5bf9aab1f1c746387753d77"><div class="ttname"><a href="vk__mem__alloc_8h.html#a0d9f4e4ba5bf9aab1f1c746387753d77">vmaDestroyBuffer</a></div><div class="ttdeci">void vmaDestroyBuffer(VmaAllocator allocator, VkBuffer buffer, VmaAllocation allocation)</div><div class="ttdoc">Destroys Vulkan buffer and frees allocated memory.</div></div>
+<div class="ttc" id="astruct_vma_vulkan_functions_html_ae8084315a25006271a2edfc3a447519f"><div class="ttname"><a href="struct_vma_vulkan_functions.html#ae8084315a25006271a2edfc3a447519f">VmaVulkanFunctions::vkCreateBuffer</a></div><div class="ttdeci">PFN_vkCreateBuffer vkCreateBuffer</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2126</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a7e1ed85f7799600b03ad51a77acc21f3"><div class="ttname"><a href="vk__mem__alloc_8h.html#a7e1ed85f7799600b03ad51a77acc21f3">PFN_vmaAllocateDeviceMemoryFunction</a></div><div class="ttdeci">void(VKAPI_PTR * PFN_vmaAllocateDeviceMemoryFunction)(VmaAllocator allocator, uint32_t memoryType, VkDeviceMemory memory, VkDeviceSize size, void *pUserData)</div><div class="ttdoc">Callback function called after successful vkAllocateMemory.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:1979</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_afa02231a791b37255720d566a52683e7"><div class="ttname"><a href="vk__mem__alloc_8h.html#afa02231a791b37255720d566a52683e7">vmaGetAllocatorInfo</a></div><div class="ttdeci">void vmaGetAllocatorInfo(VmaAllocator allocator, VmaAllocatorInfo *pAllocatorInfo)</div><div class="ttdoc">Returns information about existing VmaAllocator object - handle to Vulkan device etc.</div></div>
+<div class="ttc" id="astruct_vma_pool_stats_html_ae4f3546ffa4d1e598b64d8e6134854f4"><div class="ttname"><a href="struct_vma_pool_stats.html#ae4f3546ffa4d1e598b64d8e6134854f4">VmaPoolStats::unusedRangeCount</a></div><div class="ttdeci">size_t unusedRangeCount</div><div class="ttdoc">Number of continuous memory ranges in the pool not used by any VmaAllocation.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2859</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a9a7c45f9c863695d98c83fa5ac940fe7"><div class="ttname"><a href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7">VmaPoolCreateFlagBits</a></div><div class="ttdeci">VmaPoolCreateFlagBits</div><div class="ttdoc">Flags to be passed as VmaPoolCreateInfo::flags.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2740</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a1cf7774606721026a68aabe3af2e5b50"><div class="ttname"><a href="vk__mem__alloc_8h.html#a1cf7774606721026a68aabe3af2e5b50">VmaAllocationInfo</a></div><div class="ttdeci">struct VmaAllocationInfo VmaAllocationInfo</div><div class="ttdoc">Parameters of VmaAllocation objects, that can be retrieved using function vmaGetAllocationInfo().</div></div>
+<div class="ttc" id="astruct_vma_defragmentation_stats_html_a36f9d5df2a10ba2a36b16e126d60572d"><div class="ttname"><a href="struct_vma_defragmentation_stats.html#a36f9d5df2a10ba2a36b16e126d60572d">VmaDefragmentationStats::bytesMoved</a></div><div class="ttdeci">VkDeviceSize bytesMoved</div><div class="ttdoc">Total number of bytes that have been copied while moving allocations to different places.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3427</div></div>
+<div class="ttc" id="astruct_vma_stat_info_html_aedeba931324f16589cd2416c0d2dd0d4"><div class="ttname"><a href="struct_vma_stat_info.html#aedeba931324f16589cd2416c0d2dd0d4">VmaStatInfo::unusedRangeSizeMin</a></div><div class="ttdeci">VkDeviceSize unusedRangeSizeMin</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2350</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ad9889c10c798b040d59c92f257cae597a42ba3a2d2c7117953210b7c3ef8da0df"><div class="ttname"><a href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a42ba3a2d2c7117953210b7c3ef8da0df">VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT</a></div><div class="ttdeci">@ VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2589</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ad535935619c7a549bf837e1bb0068f89"><div class="ttname"><a href="vk__mem__alloc_8h.html#ad535935619c7a549bf837e1bb0068f89">vmaCheckPoolCorruption</a></div><div class="ttdeci">VkResult vmaCheckPoolCorruption(VmaAllocator allocator, VmaPool pool)</div><div class="ttdoc">Checks magic number in margins around all allocations in given memory pool in search for corruptions.</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a3d3ca45799923aa5d138e9e5f9eb2da5"><div class="ttname"><a href="vk__mem__alloc_8h.html#a3d3ca45799923aa5d138e9e5f9eb2da5">vmaBindImageMemory</a></div><div class="ttdeci">VkResult vmaBindImageMemory(VmaAllocator allocator, VmaAllocation allocation, VkImage image)</div><div class="ttdoc">Binds image to allocation.</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a154ccaaf53dc2c36378f80f0c4f3679b"><div class="ttname"><a href="vk__mem__alloc_8h.html#a154ccaaf53dc2c36378f80f0c4f3679b">PFN_vmaFreeDeviceMemoryFunction</a></div><div class="ttdeci">void(VKAPI_PTR * PFN_vmaFreeDeviceMemoryFunction)(VmaAllocator allocator, uint32_t memoryType, VkDeviceMemory memory, VkDeviceSize size, void *pUserData)</div><div class="ttdoc">Callback function called before vkFreeMemory.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:1986</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ad6799e8e2b1527abfc84d33bc44aeaf5"><div class="ttname"><a href="vk__mem__alloc_8h.html#ad6799e8e2b1527abfc84d33bc44aeaf5">VmaDefragmentationPassMoveInfo</a></div><div class="ttdeci">struct VmaDefragmentationPassMoveInfo VmaDefragmentationPassMoveInfo</div></div>
+<div class="ttc" id="astruct_vma_allocation_create_info_html_add09658ac14fe290ace25470ddd6d41b"><div class="ttname"><a href="struct_vma_allocation_create_info.html#add09658ac14fe290ace25470ddd6d41b">VmaAllocationCreateInfo::flags</a></div><div class="ttdeci">VmaAllocationCreateFlags flags</div><div class="ttdoc">Use VmaAllocationCreateFlagBits enum.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2641</div></div>
+<div class="ttc" id="astruct_vma_vulkan_functions_html_a475f6f49f8debe4d10800592606d53f4"><div class="ttname"><a href="struct_vma_vulkan_functions.html#a475f6f49f8debe4d10800592606d53f4">VmaVulkanFunctions::vkGetImageMemoryRequirements</a></div><div class="ttdeci">PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2125</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_aec0ed24ebea2d0099eed5f801daaefba"><div class="ttname"><a href="vk__mem__alloc_8h.html#aec0ed24ebea2d0099eed5f801daaefba">vmaGetBudget</a></div><div class="ttdeci">void vmaGetBudget(VmaAllocator allocator, VmaBudget *pBudget)</div><div class="ttdoc">Retrieves information about current memory budget for all memory heaps.</div></div>
+<div class="ttc" id="astruct_vma_allocation_create_info_html"><div class="ttname"><a href="struct_vma_allocation_create_info.html">VmaAllocationCreateInfo</a></div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2638</div></div>
+<div class="ttc" id="astruct_vma_allocation_create_info_html_a7fe8d81a1ad10b2a2faacacee5b15d6d"><div class="ttname"><a href="struct_vma_allocation_create_info.html#a7fe8d81a1ad10b2a2faacacee5b15d6d">VmaAllocationCreateInfo::preferredFlags</a></div><div class="ttdeci">VkMemoryPropertyFlags preferredFlags</div><div class="ttdoc">Flags that preferably should be set in a memory type chosen for an allocation.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2657</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a36ba776fd7fd5cb1e9359fdc0d8e6e8a"><div class="ttname"><a href="vk__mem__alloc_8h.html#a36ba776fd7fd5cb1e9359fdc0d8e6e8a">vmaDefragmentationBegin</a></div><div class="ttdeci">VkResult vmaDefragmentationBegin(VmaAllocator allocator, const VmaDefragmentationInfo2 *pInfo, VmaDefragmentationStats *pStats, VmaDefragmentationContext *pContext)</div><div class="ttdoc">Begins defragmentation process.</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_aa8251ee81b0045a443e35b8e8aa021bc"><div class="ttname"><a href="vk__mem__alloc_8h.html#aa8251ee81b0045a443e35b8e8aa021bc">vmaBindImageMemory2</a></div><div class="ttdeci">VkResult vmaBindImageMemory2(VmaAllocator allocator, VmaAllocation allocation, VkDeviceSize allocationLocalOffset, VkImage image, const void *pNext)</div><div class="ttdoc">Binds image to allocation with additional parameters.</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_aa078667e71b1ef24e87a6a30d128381d"><div class="ttname"><a href="vk__mem__alloc_8h.html#aa078667e71b1ef24e87a6a30d128381d">VmaBudget</a></div><div class="ttdeci">struct VmaBudget VmaBudget</div><div class="ttdoc">Statistics of current memory usage and available budget, in bytes, for specific memory heap.</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a1b9ffa538bed905af55c747cc48963bd"><div class="ttname"><a href="vk__mem__alloc_8h.html#a1b9ffa538bed905af55c747cc48963bd">vmaEndDefragmentationPass</a></div><div class="ttdeci">VkResult vmaEndDefragmentationPass(VmaAllocator allocator, VmaDefragmentationContext context)</div></div>
+<div class="ttc" id="astruct_vma_defragmentation_info2_html_a76d51a644dc7f5405d0cdd0025ecd0cc"><div class="ttname"><a href="struct_vma_defragmentation_info2.html#a76d51a644dc7f5405d0cdd0025ecd0cc">VmaDefragmentationInfo2::pAllocationsChanged</a></div><div class="ttdeci">VkBool32 * pAllocationsChanged</div><div class="ttdoc">Optional, output. Pointer to array that will be filled with information whether the allocation at cer...</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3341</div></div>
+<div class="ttc" id="astruct_vma_defragmentation_stats_html_aefeabf130022008eadd75999478af3f9"><div class="ttname"><a href="struct_vma_defragmentation_stats.html#aefeabf130022008eadd75999478af3f9">VmaDefragmentationStats::allocationsMoved</a></div><div class="ttdeci">uint32_t allocationsMoved</div><div class="ttdoc">Number of allocations that have been moved to different places.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3431</div></div>
+<div class="ttc" id="astruct_vma_allocation_create_info_html_a3bf940c0271d85d6ba32a4d820075055"><div class="ttname"><a href="struct_vma_allocation_create_info.html#a3bf940c0271d85d6ba32a4d820075055">VmaAllocationCreateInfo::memoryTypeBits</a></div><div class="ttdeci">uint32_t memoryTypeBits</div><div class="ttdoc">Bitmask containing one bit set for every memory type acceptable for this allocation.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2665</div></div>
+<div class="ttc" id="astruct_vma_allocator_info_html_aba2b703f96e51d567717e1fb2935b47a"><div class="ttname"><a href="struct_vma_allocator_info.html#aba2b703f96e51d567717e1fb2935b47a">VmaAllocatorInfo::physicalDevice</a></div><div class="ttdeci">VkPhysicalDevice physicalDevice</div><div class="ttdoc">Handle to Vulkan physical device object.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2281</div></div>
+<div class="ttc" id="astruct_vma_defragmentation_stats_html_a0113f1877904a5d1ee8f409216ff276b"><div class="ttname"><a href="struct_vma_defragmentation_stats.html#a0113f1877904a5d1ee8f409216ff276b">VmaDefragmentationStats::deviceMemoryBlocksFreed</a></div><div class="ttdeci">uint32_t deviceMemoryBlocksFreed</div><div class="ttdoc">Number of empty VkDeviceMemory objects that have been released to the system.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3433</div></div>
+<div class="ttc" id="astruct_vma_record_settings_html_a6cb1fdbf6bcb610b68f2010dd629e89d"><div class="ttname"><a href="struct_vma_record_settings.html#a6cb1fdbf6bcb610b68f2010dd629e89d">VmaRecordSettings::pFilePath</a></div><div class="ttdeci">const char * pFilePath</div><div class="ttdoc">Path to the file that should be written by the recording.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2169</div></div>
+<div class="ttc" id="astruct_vma_stat_info_html_a17e9733a5ecd76287d4db6e66f71f50c"><div class="ttname"><a href="struct_vma_stat_info.html#a17e9733a5ecd76287d4db6e66f71f50c">VmaStatInfo::allocationSizeMax</a></div><div class="ttdeci">VkDeviceSize allocationSizeMax</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2349</div></div>
+<div class="ttc" id="astruct_vma_allocation_info_html"><div class="ttname"><a href="struct_vma_allocation_info.html">VmaAllocationInfo</a></div><div class="ttdoc">Parameters of VmaAllocation objects, that can be retrieved using function vmaGetAllocationInfo().</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2976</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a9a7c45f9c863695d98c83fa5ac940fe7a97a0dc38e5161b780594d998d313d35e"><div class="ttname"><a href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7a97a0dc38e5161b780594d998d313d35e">VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT</a></div><div class="ttdeci">@ VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT</div><div class="ttdoc">Enables alternative, buddy allocation algorithm in this pool.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2786</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a1988031b0223fdbd564250fa1edd942c"><div class="ttname"><a href="vk__mem__alloc_8h.html#a1988031b0223fdbd564250fa1edd942c">VmaAllocatorInfo</a></div><div class="ttdeci">struct VmaAllocatorInfo VmaAllocatorInfo</div><div class="ttdoc">Information about existing VmaAllocator object.</div></div>
+<div class="ttc" id="astruct_vma_budget_html_a7e2a6583ebd63e194951c542563804d8"><div class="ttname"><a href="struct_vma_budget.html#a7e2a6583ebd63e194951c542563804d8">VmaBudget::allocationBytes</a></div><div class="ttdeci">VkDeviceSize allocationBytes</div><div class="ttdoc">Sum size of all allocations created in particular heap, in bytes.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2391</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ad9889c10c798b040d59c92f257cae597ae5633ec569f4899cf8f29e7385b2f882"><div class="ttname"><a href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597ae5633ec569f4899cf8f29e7385b2f882">VMA_ALLOCATION_CREATE_FLAG_BITS_MAX_ENUM</a></div><div class="ttdeci">@ VMA_ALLOCATION_CREATE_FLAG_BITS_MAX_ENUM</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2634</div></div>
+<div class="ttc" id="astruct_vma_defragmentation_context_html"><div class="ttname"><a href="struct_vma_defragmentation_context.html">VmaDefragmentationContext</a></div><div class="ttdoc">Represents Opaque object that represents started defragmentation process.</div></div>
+<div class="ttc" id="astruct_vma_defragmentation_info2_html_a8943f8d65969ce8e2189a1cdf3205e96"><div class="ttname"><a href="struct_vma_defragmentation_info2.html#a8943f8d65969ce8e2189a1cdf3205e96">VmaDefragmentationInfo2::pAllocations</a></div><div class="ttdeci">VmaAllocation * pAllocations</div><div class="ttdoc">Pointer to array of allocations that can be defragmented.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3335</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a9a7c45f9c863695d98c83fa5ac940fe7af4d270f8f42517a0f70037ceb6ac1d9c"><div class="ttname"><a href="vk__mem__alloc_8h.html#a9a7c45f9c863695d98c83fa5ac940fe7af4d270f8f42517a0f70037ceb6ac1d9c">VMA_POOL_CREATE_ALGORITHM_MASK</a></div><div class="ttdeci">@ VMA_POOL_CREATE_ALGORITHM_MASK</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2790</div></div>
+<div class="ttc" id="astruct_vma_defragmentation_info2_html_a94c2c7223d52878445a8cccce396b671"><div class="ttname"><a href="struct_vma_defragmentation_info2.html#a94c2c7223d52878445a8cccce396b671">VmaDefragmentationInfo2::maxCpuAllocationsToMove</a></div><div class="ttdeci">uint32_t maxCpuAllocationsToMove</div><div class="ttdoc">Maximum number of allocations that can be moved to a different place using transfers on CPU side,...</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3370</div></div>
+<div class="ttc" id="astruct_vma_defragmentation_info_html"><div class="ttname"><a href="struct_vma_defragmentation_info.html">VmaDefragmentationInfo</a></div><div class="ttdoc">Deprecated. Optional configuration parameters to be passed to function vmaDefragment().</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:3411</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ad9889c10c798b040d59c92f257cae597a2310568c62208af432724305fe29ccea"><div class="ttname"><a href="vk__mem__alloc_8h.html#ad9889c10c798b040d59c92f257cae597a2310568c62208af432724305fe29ccea">VMA_ALLOCATION_CREATE_DONT_BIND_BIT</a></div><div class="ttdeci">@ VMA_ALLOCATION_CREATE_DONT_BIND_BIT</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2595</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_ad6daeffaa670ce6d11a203a6224c9937"><div class="ttname"><a href="vk__mem__alloc_8h.html#ad6daeffaa670ce6d11a203a6224c9937">VmaDefragmentationInfo2</a></div><div class="ttdeci">struct VmaDefragmentationInfo2 VmaDefragmentationInfo2</div><div class="ttdoc">Parameters for defragmentation.</div></div>
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/vk_amd_device_coherent_memory.html b/third_party/VulkanMemoryAllocator/docs/html/vk_amd_device_coherent_memory.html
new file mode 100644
index 0000000..fa2fb04
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/vk_amd_device_coherent_memory.html
@@ -0,0 +1,102 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: VK_AMD_device_coherent_memory</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+  <ul>
+<li class="navelem"><a class="el" href="index.html">Vulkan Memory Allocator</a></li>  </ul>
+</div>
+</div><!-- top -->
+<div class="PageDoc"><div class="header">
+  <div class="headertitle">
+<div class="title">VK_AMD_device_coherent_memory </div>  </div>
+</div><!--header-->
+<div class="contents">
+<div class="textblock"><p>VK_AMD_device_coherent_memory is a device extension that enables access to additional memory types with <code>VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD</code> and <code>VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD</code> flag. It is useful mostly for allocation of buffers intended for writing "breadcrumb markers" in between passes or draw calls, which in turn are useful for debugging GPU crash/hang/TDR cases.</p>
+<p>When the extension is available but has not been enabled, Vulkan physical device still exposes those memory types, but their usage is forbidden. VMA automatically takes care of that - it returns <code>VK_ERROR_FEATURE_NOT_PRESENT</code> when an attempt to allocate memory of such type is made.</p>
+<p>If you want to use this extension in connection with VMA, follow these steps:</p>
+<h1><a class="anchor" id="vk_amd_device_coherent_memory_initialization"></a>
+Initialization</h1>
+<p>1) Call <code>vkEnumerateDeviceExtensionProperties</code> for the physical device. Check if the extension is supported - if returned array of <code>VkExtensionProperties</code> contains "VK_AMD_device_coherent_memory".</p>
+<p>2) Call <code>vkGetPhysicalDeviceFeatures2</code> for the physical device instead of old <code>vkGetPhysicalDeviceFeatures</code>. Attach additional structure <code>VkPhysicalDeviceCoherentMemoryFeaturesAMD</code> to <code>VkPhysicalDeviceFeatures2::pNext</code> to be returned. Check if the device feature is really supported - check if <code>VkPhysicalDeviceCoherentMemoryFeaturesAMD::deviceCoherentMemory</code> is true.</p>
+<p>3) While creating device with <code>vkCreateDevice</code>, enable this extension - add "VK_AMD_device_coherent_memory" to the list passed as <code>VkDeviceCreateInfo::ppEnabledExtensionNames</code>.</p>
+<p>4) While creating the device, also don't set <code>VkDeviceCreateInfo::pEnabledFeatures</code>. Fill in <code>VkPhysicalDeviceFeatures2</code> structure instead and pass it as <code>VkDeviceCreateInfo::pNext</code>. Enable this device feature - attach additional structure <code>VkPhysicalDeviceCoherentMemoryFeaturesAMD</code> to <code>VkPhysicalDeviceFeatures2::pNext</code> and set its member <code>deviceCoherentMemory</code> to <code>VK_TRUE</code>.</p>
+<p>5) While creating <a class="el" href="struct_vma_allocator.html" title="Represents main object of this library initialized.">VmaAllocator</a> with <a class="el" href="vk__mem__alloc_8h.html#a200692051ddb34240248234f5f4c17bb" title="Creates Allocator object.">vmaCreateAllocator()</a> inform VMA that you have enabled this extension and feature - add <a class="el" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7ca2acce4886d8078552efa38878413970f">VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT</a> to <a class="el" href="struct_vma_allocator_create_info.html#a392ea2ecbaff93f91a7c49f735ad4346" title="Flags for created allocator. Use VmaAllocatorCreateFlagBits enum.">VmaAllocatorCreateInfo::flags</a>.</p>
+<h1><a class="anchor" id="vk_amd_device_coherent_memory_usage"></a>
+Usage</h1>
+<p>After following steps described above, you can create VMA allocations and custom pools out of the special <code>DEVICE_COHERENT</code> and <code>DEVICE_UNCACHED</code> memory types on eligible devices. There are multiple ways to do it, for example:</p>
+<ul>
+<li>You can request or prefer to allocate out of such memory types by adding <code>VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD</code> to <a class="el" href="struct_vma_allocation_create_info.html#a9166390303ff42d783305bc31c2b6b90" title="Flags that must be set in a Memory Type chosen for an allocation.">VmaAllocationCreateInfo::requiredFlags</a> or <a class="el" href="struct_vma_allocation_create_info.html#a7fe8d81a1ad10b2a2faacacee5b15d6d" title="Flags that preferably should be set in a memory type chosen for an allocation.">VmaAllocationCreateInfo::preferredFlags</a>. Those flags can be freely mixed with other ways of <a class="el" href="choosing_memory_type.html">Choosing memory type</a>, like setting <a class="el" href="struct_vma_allocation_create_info.html#accb8b06b1f677d858cb9af20705fa910" title="Intended usage of memory.">VmaAllocationCreateInfo::usage</a>.</li>
+<li>If you manually found memory type index to use for this purpose, force allocation from this specific index by setting <a class="el" href="struct_vma_allocation_create_info.html#a3bf940c0271d85d6ba32a4d820075055" title="Bitmask containing one bit set for every memory type acceptable for this allocation.">VmaAllocationCreateInfo::memoryTypeBits</a> <code>= 1u &lt;&lt; index</code>.</li>
+</ul>
+<h1><a class="anchor" id="vk_amd_device_coherent_memory_more_information"></a>
+More information</h1>
+<p>To learn more about this extension, see <a href="https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/chap44.html#VK_AMD_device_coherent_memory">VK_AMD_device_coherent_memory in Vulkan specification</a></p>
+<p>Example use of this extension can be found in the code of the sample and test suite accompanying this library. </p>
+</div></div><!-- contents -->
+</div><!-- PageDoc -->
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/docs/html/vk_khr_dedicated_allocation.html b/third_party/VulkanMemoryAllocator/docs/html/vk_khr_dedicated_allocation.html
new file mode 100644
index 0000000..a7c2237
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/docs/html/vk_khr_dedicated_allocation.html
@@ -0,0 +1,104 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen 1.8.17"/>
+<meta name="viewport" content="width=device-width, initial-scale=1"/>
+<title>Vulkan Memory Allocator: VK_KHR_dedicated_allocation</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="dynsections.js"></script>
+<link href="search/search.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="search/searchdata.js"></script>
+<script type="text/javascript" src="search/search.js"></script>
+<link href="doxygen.css" rel="stylesheet" type="text/css" />
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+  <td id="projectalign" style="padding-left: 0.5em;">
+   <div id="projectname">Vulkan Memory Allocator
+   </div>
+  </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<!-- end header part -->
+<!-- Generated by Doxygen 1.8.17 -->
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+var searchBox = new SearchBox("searchBox", "search",false,'Search');
+/* @license-end */
+</script>
+<script type="text/javascript" src="menudata.js"></script>
+<script type="text/javascript" src="menu.js"></script>
+<script type="text/javascript">
+/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
+$(function() {
+  initMenu('',true,false,'search.php','Search');
+  $(document).ready(function() { init_search(); });
+});
+/* @license-end */</script>
+<div id="main-nav"></div>
+<!-- window showing the filter options -->
+<div id="MSearchSelectWindow"
+     onmouseover="return searchBox.OnSearchSelectShow()"
+     onmouseout="return searchBox.OnSearchSelectHide()"
+     onkeydown="return searchBox.OnSearchSelectKey(event)">
+</div>
+
+<!-- iframe showing the search results (closed by default) -->
+<div id="MSearchResultsWindow">
+<iframe src="javascript:void(0)" frameborder="0" 
+        name="MSearchResults" id="MSearchResults">
+</iframe>
+</div>
+
+<div id="nav-path" class="navpath">
+  <ul>
+<li class="navelem"><a class="el" href="index.html">Vulkan Memory Allocator</a></li>  </ul>
+</div>
+</div><!-- top -->
+<div class="PageDoc"><div class="header">
+  <div class="headertitle">
+<div class="title">VK_KHR_dedicated_allocation </div>  </div>
+</div><!--header-->
+<div class="contents">
+<div class="textblock"><p>VK_KHR_dedicated_allocation is a Vulkan extension which can be used to improve performance on some GPUs. It augments Vulkan API with possibility to query driver whether it prefers particular buffer or image to have its own, dedicated allocation (separate <code>VkDeviceMemory</code> block) for better efficiency - to be able to do some internal optimizations.</p>
+<p>The extension is supported by this library. It will be used automatically when enabled. To enable it:</p>
+<p>1 . When creating Vulkan device, check if following 2 device extensions are supported (call <code>vkEnumerateDeviceExtensionProperties()</code>). If yes, enable them (fill <code>VkDeviceCreateInfo::ppEnabledExtensionNames</code>).</p>
+<ul>
+<li>VK_KHR_get_memory_requirements2</li>
+<li>VK_KHR_dedicated_allocation</li>
+</ul>
+<p>If you enabled these extensions:</p>
+<p>2 . Use <a class="el" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7cace7da7cc6e71a625dfa763c55a597878" title="Enables usage of VK_KHR_dedicated_allocation extension.">VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT</a> flag when creating your <a class="el" href="struct_vma_allocator.html" title="Represents main object of this library initialized.">VmaAllocator</a>`to inform the library that you enabled required extensions and you want the library to use them.</p>
+<div class="fragment"><div class="line">allocatorInfo.<a class="code" href="struct_vma_allocator_create_info.html#a392ea2ecbaff93f91a7c49f735ad4346">flags</a> |= <a class="code" href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7cace7da7cc6e71a625dfa763c55a597878">VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT</a>;</div>
+<div class="line"> </div>
+<div class="line"><a class="code" href="vk__mem__alloc_8h.html#a200692051ddb34240248234f5f4c17bb">vmaCreateAllocator</a>(&amp;allocatorInfo, &amp;allocator);</div>
+</div><!-- fragment --><p>That's all. The extension will be automatically used whenever you create a buffer using <a class="el" href="vk__mem__alloc_8h.html#ac72ee55598617e8eecca384e746bab51">vmaCreateBuffer()</a> or image using <a class="el" href="vk__mem__alloc_8h.html#a02a94f25679275851a53e82eacbcfc73" title="Function similar to vmaCreateBuffer().">vmaCreateImage()</a>.</p>
+<p>When using the extension together with Vulkan Validation Layer, you will receive warnings like this: </p><pre class="fragment">vkBindBufferMemory(): Binding memory to buffer 0x33 but vkGetBufferMemoryRequirements() has not been called on that buffer.
+</pre><p>It is OK, you should just ignore it. It happens because you use function <code>vkGetBufferMemoryRequirements2KHR()</code> instead of standard <code>vkGetBufferMemoryRequirements()</code>, while the validation layer seems to be unaware of it.</p>
+<p>To learn more about this extension, see:</p>
+<ul>
+<li><a href="https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/chap44.html#VK_KHR_dedicated_allocation">VK_KHR_dedicated_allocation in Vulkan specification</a></li>
+<li><a href="http://asawicki.info/articles/VK_KHR_dedicated_allocation.php5">VK_KHR_dedicated_allocation unofficial manual</a> </li>
+</ul>
+</div></div><!-- contents -->
+</div><!-- PageDoc -->
+<div class="ttc" id="avk__mem__alloc_8h_html_a4f87c9100d154a65a4ad495f7763cf7cace7da7cc6e71a625dfa763c55a597878"><div class="ttname"><a href="vk__mem__alloc_8h.html#a4f87c9100d154a65a4ad495f7763cf7cace7da7cc6e71a625dfa763c55a597878">VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT</a></div><div class="ttdeci">@ VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT</div><div class="ttdoc">Enables usage of VK_KHR_dedicated_allocation extension.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2040</div></div>
+<div class="ttc" id="astruct_vma_allocator_create_info_html_a392ea2ecbaff93f91a7c49f735ad4346"><div class="ttname"><a href="struct_vma_allocator_create_info.html#a392ea2ecbaff93f91a7c49f735ad4346">VmaAllocatorCreateInfo::flags</a></div><div class="ttdeci">VmaAllocatorCreateFlags flags</div><div class="ttdoc">Flags for created allocator. Use VmaAllocatorCreateFlagBits enum.</div><div class="ttdef"><b>Definition:</b> vk_mem_alloc.h:2176</div></div>
+<div class="ttc" id="avk__mem__alloc_8h_html_a200692051ddb34240248234f5f4c17bb"><div class="ttname"><a href="vk__mem__alloc_8h.html#a200692051ddb34240248234f5f4c17bb">vmaCreateAllocator</a></div><div class="ttdeci">VkResult vmaCreateAllocator(const VmaAllocatorCreateInfo *pCreateInfo, VmaAllocator *pAllocator)</div><div class="ttdoc">Creates Allocator object.</div></div>
+<!-- start footer part -->
+<hr class="footer"/><address class="footer"><small>
+Generated by &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="doxygen.png" alt="doxygen"/>
+</a> 1.8.17
+</small></address>
+</body>
+</html>
diff --git a/third_party/VulkanMemoryAllocator/media/Thumbnail.png b/third_party/VulkanMemoryAllocator/media/Thumbnail.png
new file mode 100644
index 0000000..22027bd
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/media/Thumbnail.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/premake/LICENSE.txt b/third_party/VulkanMemoryAllocator/premake/LICENSE.txt
new file mode 100644
index 0000000..e7611e6
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/premake/LICENSE.txt
@@ -0,0 +1,27 @@
+Copyright (c) 2003-2016 Jason Perkins and individual contributors.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+  1. Redistributions of source code must retain the above copyright notice,
+     this list of conditions and the following disclaimer.
+
+  2. Redistributions in binary form must reproduce the above copyright notice,
+     this list of conditions and the following disclaimer in the documentation
+     and/or other materials provided with the distribution.
+
+  3. Neither the name of Premake nor the names of its contributors may be
+     used to endorse or promote products derived from this software without
+     specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/third_party/VulkanMemoryAllocator/premake/premake5.exe b/third_party/VulkanMemoryAllocator/premake/premake5.exe
new file mode 100644
index 0000000..9048d51
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/premake/premake5.exe
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/premake/premake5.lua b/third_party/VulkanMemoryAllocator/premake/premake5.lua
new file mode 100644
index 0000000..80de8e2
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/premake/premake5.lua
@@ -0,0 +1,99 @@
+-- _ACTION is a premake global variable and for our usage will be vs2012, vs2013, etc.
+-- Strip "vs" from this string to make a suffix for solution and project files.
+_SUFFIX = _ACTION
+
+workspace "VulkanSample"
+configurations { "Debug", "Release" }
+platforms { "x64", "Linux-x64" }
+location "../build"
+filename ("VulkanSample_" .. _SUFFIX)
+startproject "VulkanSample"
+
+filter "platforms:x64"
+system "Windows"
+architecture "x64"
+includedirs { "$(VULKAN_SDK)/Include" }
+libdirs { "$(VULKAN_SDK)/Lib" }
+
+filter "platforms:Linux-x64"
+system "Linux"
+architecture "x64"
+includedirs { "$(VULKAN_SDK)/include" }
+libdirs { "$(VULKAN_SDK)/lib" }
+
+
+project "VulkanSample"
+kind "ConsoleApp"
+language "C++"
+location "../build"
+filename ("VulkanSample_" .. _SUFFIX)
+targetdir "../bin"
+objdir "../build/Desktop_%{_SUFFIX}/%{cfg.platform}/%{cfg.buildcfg}"
+floatingpoint "Fast"
+files { "../src/*.h", "../src/*.cpp" }
+flags { "NoPCH", "FatalWarnings" }
+characterset "Unicode"
+
+filter "configurations:Debug"
+defines { "_DEBUG", "DEBUG" }
+flags { }
+targetsuffix ("_Debug_" .. _SUFFIX)
+
+filter "configurations:Release"
+defines { "NDEBUG" }
+optimize "On"
+flags { "LinkTimeOptimization" }
+targetsuffix ("_Release_" .. _SUFFIX)
+
+filter { "platforms:x64" }
+defines { "WIN32", "_CONSOLE", "PROFILE", "_WINDOWS", "_WIN32_WINNT=0x0601" }
+links { "vulkan-1" }
+
+filter { "platforms:Linux-x64" }
+buildoptions { "-std=c++0x" }
+links { "vulkan" }
+
+filter { "configurations:Debug", "platforms:x64" }
+buildoptions { "/MDd" }
+
+filter { "configurations:Release", "platforms:Windows-x64" }
+buildoptions { "/MD" }
+
+
+project "VmaReplay"
+removeplatforms { "Linux-x64" }
+kind "ConsoleApp"
+language "C++"
+location "../build"
+filename ("VmaReplay_" .. _SUFFIX)
+targetdir "../bin"
+objdir "../build/Desktop_%{_SUFFIX}/%{cfg.platform}/%{cfg.buildcfg}"
+floatingpoint "Fast"
+files { "../src/VmaReplay/*.h", "../src/VmaReplay/*.cpp" }
+flags { "NoPCH", "FatalWarnings" }
+characterset "Default"
+
+filter "configurations:Debug"
+defines { "_DEBUG", "DEBUG" }
+flags { }
+targetsuffix ("_Debug_" .. _SUFFIX)
+
+filter "configurations:Release"
+defines { "NDEBUG" }
+optimize "On"
+flags { "LinkTimeOptimization" }
+targetsuffix ("_Release_" .. _SUFFIX)
+
+filter { "platforms:x64" }
+defines { "WIN32", "_CONSOLE", "PROFILE", "_WINDOWS", "_WIN32_WINNT=0x0601" }
+links { "vulkan-1" }
+
+filter { "platforms:Linux-x64" }
+buildoptions { "-std=c++0x" }
+links { "vulkan" }
+
+filter { "configurations:Debug", "platforms:x64" }
+buildoptions { "/MDd" }
+
+filter { "configurations:Release", "platforms:Windows-x64" }
+buildoptions { "/MD" }
diff --git a/third_party/VulkanMemoryAllocator/src/Common.cpp b/third_party/VulkanMemoryAllocator/src/Common.cpp
new file mode 100644
index 0000000..5ef7928
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/src/Common.cpp
@@ -0,0 +1,180 @@
+//
+// Copyright (c) 2017-2020 Advanced Micro Devices, Inc. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#include "Common.h"
+
+#ifdef _WIN32
+
+void ReadFile(std::vector<char>& out, const char* fileName)
+{
+    std::ifstream file(fileName, std::ios::ate | std::ios::binary);
+    assert(file.is_open());
+    size_t fileSize = (size_t)file.tellg();
+    if(fileSize > 0)
+    {
+        out.resize(fileSize);
+        file.seekg(0);
+        file.read(out.data(), fileSize);
+    }
+    else
+        out.clear();
+}
+
+void SetConsoleColor(CONSOLE_COLOR color)
+{
+    WORD attr = 0;
+    switch(color)
+    {
+    case CONSOLE_COLOR::INFO:
+        attr = FOREGROUND_INTENSITY;;
+        break;
+    case CONSOLE_COLOR::NORMAL:
+        attr = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
+        break;
+    case CONSOLE_COLOR::WARNING:
+        attr = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY;
+        break;
+    case CONSOLE_COLOR::ERROR_:
+        attr = FOREGROUND_RED | FOREGROUND_INTENSITY;
+        break;
+    default:
+        assert(0);
+    }
+
+    HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
+    SetConsoleTextAttribute(out, attr);
+}
+
+void PrintMessage(CONSOLE_COLOR color, const char* msg)
+{
+    if(color != CONSOLE_COLOR::NORMAL)
+        SetConsoleColor(color);
+    
+    printf("%s\n", msg);
+    
+    if (color != CONSOLE_COLOR::NORMAL)
+        SetConsoleColor(CONSOLE_COLOR::NORMAL);
+}
+
+void PrintMessage(CONSOLE_COLOR color, const wchar_t* msg)
+{
+    if(color != CONSOLE_COLOR::NORMAL)
+        SetConsoleColor(color);
+    
+    wprintf(L"%s\n", msg);
+    
+    if (color != CONSOLE_COLOR::NORMAL)
+        SetConsoleColor(CONSOLE_COLOR::NORMAL);
+}
+
+static const size_t CONSOLE_SMALL_BUF_SIZE = 256;
+
+void PrintMessageV(CONSOLE_COLOR color, const char* format, va_list argList)
+{
+	size_t dstLen = (size_t)::_vscprintf(format, argList);
+	if(dstLen)
+	{
+		bool useSmallBuf = dstLen < CONSOLE_SMALL_BUF_SIZE;
+		char smallBuf[CONSOLE_SMALL_BUF_SIZE];
+		std::vector<char> bigBuf(useSmallBuf ? 0 : dstLen + 1);
+		char* bufPtr = useSmallBuf ? smallBuf : bigBuf.data();
+		::vsprintf_s(bufPtr, dstLen + 1, format, argList);
+		PrintMessage(color, bufPtr);
+	}
+}
+
+void PrintMessageV(CONSOLE_COLOR color, const wchar_t* format, va_list argList)
+{
+	size_t dstLen = (size_t)::_vcwprintf(format, argList);
+	if(dstLen)
+	{
+		bool useSmallBuf = dstLen < CONSOLE_SMALL_BUF_SIZE;
+		wchar_t smallBuf[CONSOLE_SMALL_BUF_SIZE];
+		std::vector<wchar_t> bigBuf(useSmallBuf ? 0 : dstLen + 1);
+		wchar_t* bufPtr = useSmallBuf ? smallBuf : bigBuf.data();
+		::vswprintf_s(bufPtr, dstLen + 1, format, argList);
+		PrintMessage(color, bufPtr);
+	}
+}
+
+void PrintMessageF(CONSOLE_COLOR color, const char* format, ...)
+{
+	va_list argList;
+	va_start(argList, format);
+	PrintMessageV(color, format, argList);
+	va_end(argList);
+}
+
+void PrintMessageF(CONSOLE_COLOR color, const wchar_t* format, ...)
+{
+	va_list argList;
+	va_start(argList, format);
+	PrintMessageV(color, format, argList);
+	va_end(argList);
+}
+
+void PrintWarningF(const char* format, ...)
+{
+	va_list argList;
+	va_start(argList, format);
+	PrintMessageV(CONSOLE_COLOR::WARNING, format, argList);
+	va_end(argList);
+}
+
+void PrintWarningF(const wchar_t* format, ...)
+{
+	va_list argList;
+	va_start(argList, format);
+	PrintMessageV(CONSOLE_COLOR::WARNING, format, argList);
+	va_end(argList);
+}
+
+void PrintErrorF(const char* format, ...)
+{
+	va_list argList;
+	va_start(argList, format);
+	PrintMessageV(CONSOLE_COLOR::WARNING, format, argList);
+	va_end(argList);
+}
+
+void PrintErrorF(const wchar_t* format, ...)
+{
+	va_list argList;
+	va_start(argList, format);
+	PrintMessageV(CONSOLE_COLOR::WARNING, format, argList);
+	va_end(argList);
+}
+
+void SaveFile(const wchar_t* filePath, const void* data, size_t dataSize)
+{
+    FILE* f = nullptr;
+    _wfopen_s(&f, filePath, L"wb");
+    if(f)
+    {
+        fwrite(data, 1, dataSize, f);
+        fclose(f);
+    }
+    else
+        assert(0);
+}
+
+#endif // #ifdef _WIN32
diff --git a/third_party/VulkanMemoryAllocator/src/Common.h b/third_party/VulkanMemoryAllocator/src/Common.h
new file mode 100644
index 0000000..3d4f3b1
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/src/Common.h
@@ -0,0 +1,328 @@
+//
+// Copyright (c) 2017-2020 Advanced Micro Devices, Inc. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include "VmaUsage.h"
+
+#ifdef _WIN32
+
+#include <iostream>
+#include <fstream>
+#include <vector>
+#include <memory>
+#include <algorithm>
+#include <numeric>
+#include <array>
+#include <type_traits>
+#include <utility>
+#include <chrono>
+#include <string>
+#include <exception>
+
+#include <cassert>
+#include <cstdlib>
+#include <cstdio>
+#include <cstdarg>
+
+typedef std::chrono::high_resolution_clock::time_point time_point;
+typedef std::chrono::high_resolution_clock::duration duration;
+
+#ifdef _DEBUG
+    #define TEST(expr) do { \
+            if(!(expr)) { \
+                assert(0 && #expr); \
+            } \
+        } while(0)
+#else
+    #define TEST(expr) do { \
+            if(!(expr)) { \
+                throw std::runtime_error("TEST FAILED: " #expr); \
+            } \
+        } while(0)
+#endif
+
+#define ERR_GUARD_VULKAN(expr) TEST((expr) >= 0)
+
+extern VkInstance g_hVulkanInstance;
+extern VkPhysicalDevice g_hPhysicalDevice;
+extern VkDevice g_hDevice;
+extern VkInstance g_hVulkanInstance;
+extern VmaAllocator g_hAllocator;
+extern bool g_MemoryAliasingWarningEnabled;
+extern bool VK_AMD_device_coherent_memory_enabled;
+
+void SetAllocatorCreateInfo(VmaAllocatorCreateInfo& outInfo);
+
+inline float ToFloatSeconds(duration d)
+{
+    return std::chrono::duration_cast<std::chrono::duration<float>>(d).count();
+}
+
+template <typename T>
+inline T ceil_div(T x, T y)
+{
+    return (x+y-1) / y;
+}
+template <typename T>
+inline T round_div(T x, T y)
+{
+    return (x+y/(T)2) / y;
+}
+
+template <typename T>
+static inline T align_up(T val, T align)
+{
+    return (val + align - 1) / align * align;
+}
+
+static const float PI = 3.14159265358979323846264338327950288419716939937510582f;
+
+template<typename MainT, typename NewT>
+inline void PnextChainPushFront(MainT* mainStruct, NewT* newStruct)
+{
+    newStruct->pNext = mainStruct->pNext;
+    mainStruct->pNext = newStruct;
+}
+template<typename MainT, typename NewT>
+inline void PnextChainPushBack(MainT* mainStruct, NewT* newStruct)
+{
+    struct VkAnyStruct
+    {
+        VkStructureType sType;
+        void* pNext;
+    };
+    VkAnyStruct* lastStruct = (VkAnyStruct*)mainStruct;
+    while(lastStruct->pNext != nullptr)
+    {
+        lastStruct = (VkAnyStruct*)lastStruct->pNext;
+    }
+    newStruct->pNext = nullptr;
+    lastStruct->pNext = newStruct;
+}
+
+struct vec3
+{
+    float x, y, z;
+
+    vec3() { }
+    vec3(float x, float y, float z) : x(x), y(y), z(z) { }
+
+    float& operator[](uint32_t index) { return *(&x + index); }
+    const float& operator[](uint32_t index) const { return *(&x + index); }
+
+    vec3 operator+(const vec3& rhs) const { return vec3(x + rhs.x, y + rhs.y, z + rhs.z); }
+    vec3 operator-(const vec3& rhs) const { return vec3(x - rhs.x, y - rhs.y, z - rhs.z); }
+    vec3 operator*(float s) const { return vec3(x * s, y * s, z * s); }
+
+    vec3 Normalized() const
+    {
+        return (*this) * (1.f / sqrt(x * x + y * y + z * z));
+    }
+};
+
+inline float Dot(const vec3& lhs, const vec3& rhs)
+{
+    return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z;
+}
+inline vec3 Cross(const vec3& lhs, const vec3& rhs)
+{
+    return vec3(
+        lhs.y * rhs.z - lhs.z * rhs.y,
+	    lhs.z * rhs.x - lhs.x * rhs.z,
+	    lhs.x * rhs.y - lhs.y * rhs.x);
+}
+
+struct vec4
+{
+    float x, y, z, w;
+
+    vec4() { }
+    vec4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) { }
+    vec4(const vec3& v, float w) : x(v.x), y(v.y), z(v.z), w(w) { }
+
+    float& operator[](uint32_t index) { return *(&x + index); }
+    const float& operator[](uint32_t index) const { return *(&x + index); }
+};
+
+struct mat4
+{
+    union
+    {
+        struct
+        {
+            float _11, _12, _13, _14;
+            float _21, _22, _23, _24;
+            float _31, _32, _33, _34;
+            float _41, _42, _43, _44;
+        };
+        float m[4][4]; // [row][column]
+    };
+
+    mat4() { }
+
+    mat4(
+        float _11, float _12, float _13, float _14,
+        float _21, float _22, float _23, float _24,
+        float _31, float _32, float _33, float _34,
+        float _41, float _42, float _43, float _44) :
+        _11(_11), _12(_12), _13(_13), _14(_14),
+        _21(_21), _22(_22), _23(_23), _24(_24),
+        _31(_31), _32(_32), _33(_33), _34(_34),
+        _41(_41), _42(_42), _43(_43), _44(_44)
+    {
+    }
+
+    mat4(
+        const vec4& row1,
+        const vec4& row2,
+        const vec4& row3,
+        const vec4& row4) :
+        _11(row1.x), _12(row1.y), _13(row1.z), _14(row1.w),
+        _21(row2.x), _22(row2.y), _23(row2.z), _24(row2.w),
+        _31(row3.x), _32(row3.y), _33(row3.z), _34(row3.w),
+        _41(row4.x), _42(row4.y), _43(row4.z), _44(row4.w)
+    {
+    }
+
+    mat4 operator*(const mat4 &rhs) const
+    {
+        return mat4(
+            _11 * rhs._11 + _12 * rhs._21 + _13 * rhs._31 + _14 * rhs._41,
+            _11 * rhs._12 + _12 * rhs._22 + _13 * rhs._32 + _14 * rhs._42,
+            _11 * rhs._13 + _12 * rhs._23 + _13 * rhs._33 + _14 * rhs._43,
+            _11 * rhs._14 + _12 * rhs._24 + _13 * rhs._34 + _14 * rhs._44,
+
+            _21 * rhs._11 + _22 * rhs._21 + _23 * rhs._31 + _24 * rhs._41,
+            _21 * rhs._12 + _22 * rhs._22 + _23 * rhs._32 + _24 * rhs._42,
+            _21 * rhs._13 + _22 * rhs._23 + _23 * rhs._33 + _24 * rhs._43,
+            _21 * rhs._14 + _22 * rhs._24 + _23 * rhs._34 + _24 * rhs._44,
+
+            _31 * rhs._11 + _32 * rhs._21 + _33 * rhs._31 + _34 * rhs._41,
+            _31 * rhs._12 + _32 * rhs._22 + _33 * rhs._32 + _34 * rhs._42,
+            _31 * rhs._13 + _32 * rhs._23 + _33 * rhs._33 + _34 * rhs._43,
+            _31 * rhs._14 + _32 * rhs._24 + _33 * rhs._34 + _34 * rhs._44,
+
+            _41 * rhs._11 + _42 * rhs._21 + _43 * rhs._31 + _44 * rhs._41,
+            _41 * rhs._12 + _42 * rhs._22 + _43 * rhs._32 + _44 * rhs._42,
+            _41 * rhs._13 + _42 * rhs._23 + _43 * rhs._33 + _44 * rhs._43,
+            _41 * rhs._14 + _42 * rhs._24 + _43 * rhs._34 + _44 * rhs._44);
+    }
+
+    static mat4 RotationY(float angle)
+    {
+        const float s = sin(angle), c = cos(angle);
+        return mat4(
+            c,   0.f, -s,  0.f,
+            0.f, 1.f, 0.f, 0.f,
+            s,   0.f, c,   0.f,
+            0.f, 0.f, 0.f, 1.f);
+    }
+
+    static mat4 Perspective(float fovY, float aspectRatio, float zNear, float zFar)
+    {
+        float yScale = 1.0f / tan(fovY * 0.5f);
+        float xScale = yScale / aspectRatio;
+        return mat4(
+            xScale, 0.0f, 0.0f, 0.0f,
+            0.0f, yScale, 0.0f, 0.0f,
+            0.0f, 0.0f, zFar / (zFar - zNear), 1.0f,
+            0.0f, 0.0f, -zNear * zFar / (zFar - zNear), 0.0f);
+    }
+
+    static mat4 LookAt(vec3 at, vec3 eye, vec3 up)
+    {
+        vec3 zAxis = (at - eye).Normalized();
+        vec3 xAxis = Cross(up, zAxis).Normalized();
+        vec3 yAxis = Cross(zAxis, xAxis);
+        return mat4(
+            xAxis.x, yAxis.x, zAxis.x, 0.0f,
+            xAxis.y, yAxis.y, zAxis.y, 0.0f,
+            xAxis.z, yAxis.z, zAxis.z, 0.0f,
+            -Dot(xAxis, eye), -Dot(yAxis, eye), -Dot(zAxis, eye), 1.0f);
+    }
+};
+
+class RandomNumberGenerator
+{
+public:
+    RandomNumberGenerator() : m_Value{GetTickCount()} {}
+    RandomNumberGenerator(uint32_t seed) : m_Value{seed} { }
+    void Seed(uint32_t seed) { m_Value = seed; }
+    uint32_t Generate() { return GenerateFast() ^ (GenerateFast() >> 7); }
+
+private:
+    uint32_t m_Value;
+    uint32_t GenerateFast() { return m_Value = (m_Value * 196314165 + 907633515); }
+};
+
+// Wrapper for RandomNumberGenerator compatible with STL "UniformRandomNumberGenerator" idea.
+struct MyUniformRandomNumberGenerator
+{
+    typedef uint32_t result_type;
+    MyUniformRandomNumberGenerator(RandomNumberGenerator& gen) : m_Gen(gen) { }
+    static uint32_t min() { return 0; }
+    static uint32_t max() { return UINT32_MAX; }
+    uint32_t operator()() { return m_Gen.Generate(); }
+
+private:
+    RandomNumberGenerator& m_Gen;
+};
+
+void ReadFile(std::vector<char>& out, const char* fileName);
+
+enum class CONSOLE_COLOR
+{
+    INFO,
+    NORMAL,
+    WARNING,
+    ERROR_,
+    COUNT
+};
+
+void SetConsoleColor(CONSOLE_COLOR color);
+
+void PrintMessage(CONSOLE_COLOR color, const char* msg);
+void PrintMessage(CONSOLE_COLOR color, const wchar_t* msg);
+
+inline void Print(const char* msg) { PrintMessage(CONSOLE_COLOR::NORMAL, msg); }
+inline void Print(const wchar_t* msg) { PrintMessage(CONSOLE_COLOR::NORMAL, msg); }
+inline void PrintWarning(const char* msg) { PrintMessage(CONSOLE_COLOR::WARNING, msg); }
+inline void PrintWarning(const wchar_t* msg) { PrintMessage(CONSOLE_COLOR::WARNING, msg); }
+inline void PrintError(const char* msg) { PrintMessage(CONSOLE_COLOR::ERROR_, msg); }
+inline void PrintError(const wchar_t* msg) { PrintMessage(CONSOLE_COLOR::ERROR_, msg); }
+
+void PrintMessageV(CONSOLE_COLOR color, const char* format, va_list argList);
+void PrintMessageV(CONSOLE_COLOR color, const wchar_t* format, va_list argList);
+void PrintMessageF(CONSOLE_COLOR color, const char* format, ...);
+void PrintMessageF(CONSOLE_COLOR color, const wchar_t* format, ...);
+void PrintWarningF(const char* format, ...);
+void PrintWarningF(const wchar_t* format, ...);
+void PrintErrorF(const char* format, ...);
+void PrintErrorF(const wchar_t* format, ...);
+
+void SaveFile(const wchar_t* filePath, const void* data, size_t dataSize);
+
+#endif // #ifdef _WIN32
+
+#endif
diff --git a/third_party/VulkanMemoryAllocator/src/Doxyfile b/third_party/VulkanMemoryAllocator/src/Doxyfile
new file mode 100644
index 0000000..e4c5914
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/src/Doxyfile
@@ -0,0 +1,2566 @@
+# Doxyfile 1.8.16
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the configuration
+# file that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# https://www.gnu.org/software/libiconv/ for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME           = "Vulkan Memory Allocator"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER         =
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF          =
+
+# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
+# in the documentation. The maximum height of the logo should not exceed 55
+# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
+# the logo to the output directory.
+
+PROJECT_LOGO           =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = ../docs
+
+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS         = NO
+
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES    = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE        = English
+
+# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all generated output in the proper direction.
+# Possible values are: None, LTR, RTL and Context.
+# The default value is: None.
+
+OUTPUT_TEXT_DIRECTION  = None
+
+# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF       = "The $name class" \
+                         "The $name widget" \
+                         "The $name file" \
+                         is \
+                         provides \
+                         specifies \
+                         contains \
+                         represents \
+                         a \
+                         an \
+                         the
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES        = YES
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH        =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH    =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF      = NO
+
+# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line
+# such as
+# /***************
+# as being the beginning of a Javadoc-style comment "banner". If set to NO, the
+# Javadoc-style will behave just like regular comments and it will not be
+# interpreted by doxygen.
+# The default value is: NO.
+
+JAVADOC_BANNER         = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF           = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
+# page for each member. If set to NO, the documentation of a member will be part
+# of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE               = 4
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines (in the resulting output). You can put ^^ in the value part of an
+# alias to insert a newline as if a physical newline was in the original file.
+# When you need a literal { or } or , in the value part of an alias you have to
+# escape them by means of a backslash (\), this can lead to conflicts with the
+# commands \{ and \} for these it is advised to use the version @{ and @} or use
+# a double escape (\\{ and \\})
+
+ALIASES                =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
+
+TCL_SUBST              =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C  = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice
+# sources only. Doxygen will then generate output that is more tailored for that
+# language. For instance, namespaces will be presented as modules, types will be
+# separated into more groups, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_SLICE  = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice,
+# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
+# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
+# tries to guess whether the code is fixed or free formatted code, this is the
+# default for Fortran type files), VHDL, tcl. For instance to make doxygen treat
+# .inc files as Fortran files (default is PHP), and .f files as C (default is
+# Fortran), use: inc=Fortran f=C.
+#
+# Note: For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
+
+EXTENSION_MAPPING      =
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See https://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT       = YES
+
+# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
+# to that level are automatically included in the table of contents, even if
+# they do not have an id attribute.
+# Note: This feature currently applies only to Markdown headings.
+# Minimum value: 0, maximum value: 99, default value: 5.
+# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
+
+TOC_INCLUDE_HEADINGS   = 0
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT       = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# If one adds a struct or class to a group and this option is enabled, then also
+# any nested class or struct is added to the same group. By default this option
+# is disabled and one has to add nested compounds explicitly via \ingroup.
+# The default value is: NO.
+
+GROUP_NESTED_COMPOUNDS = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING            = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS  = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE      = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL            = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual
+# methods of a class will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIV_VIRTUAL   = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC         = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO,
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. If set to YES, local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO, only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES   = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO, these classes will be included in the various overviews. This option
+# has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO, these declarations will be
+# included in the documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO, these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES, upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# (including Cygwin) ands Mac users are advised to set this option to NO.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES       = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES, the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
+# append additional text to a page's title, such as Class Reference. If set to
+# YES the compound reference will be hidden.
+# The default value is: NO.
+
+HIDE_COMPOUND_REFERENCE= NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC  = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES   = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING  = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
+# list. This list is created by putting \todo commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
+# list. This list is created by putting \test commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS       =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES, the
+# list will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES        = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER    =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE            =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. See also \cite for info how to create references.
+
+CITE_BIB_FILES         =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS               = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR      = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO, doxygen will only warn about wrong or incomplete
+# parameter documentation, but not about the absence of documentation. If
+# EXTRACT_ALL is set to YES then this flag will automatically be disabled.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC       = NO
+
+# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
+# a warning is encountered.
+# The default value is: NO.
+
+WARN_AS_ERROR          = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
+WARN_LOGFILE           =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
+# Note: If this tag is empty the current directory is searched.
+
+INPUT                  = vk_mem_alloc.h
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: https://www.gnu.org/software/libiconv/) for the list of
+# possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# read by doxygen.
+#
+# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
+# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
+# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
+# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
+# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice.
+
+FILE_PATTERNS          = *.c \
+                         *.cc \
+                         *.cxx \
+                         *.cpp \
+                         *.c++ \
+                         *.java \
+                         *.ii \
+                         *.ixx \
+                         *.ipp \
+                         *.i++ \
+                         *.inl \
+                         *.idl \
+                         *.ddl \
+                         *.odl \
+                         *.h \
+                         *.hh \
+                         *.hxx \
+                         *.hpp \
+                         *.h++ \
+                         *.cs \
+                         *.d \
+                         *.php \
+                         *.php4 \
+                         *.php5 \
+                         *.phtml \
+                         *.inc \
+                         *.m \
+                         *.markdown \
+                         *.md \
+                         *.mm \
+                         *.dox \
+                         *.py \
+                         *.pyw \
+                         *.f90 \
+                         *.f95 \
+                         *.f03 \
+                         *.f08 \
+                         *.f \
+                         *.for \
+                         *.tcl \
+                         *.vhd \
+                         *.vhdl \
+                         *.ucf \
+                         *.qsf
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE              = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE                =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS        =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH           =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS       = *
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH             =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
+
+INPUT_FILTER           =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
+
+FILTER_PATTERNS        =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES    = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# entity all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION    = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS        = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see https://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS       = YES
+
+# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
+# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
+# cost of reduced performance. This can be particularly helpful with template
+# rich C++ code for which doxygen's built-in parser lacks the necessary type
+# information.
+# Note: The availability of this option depends on whether or not doxygen was
+# generated with the -Duse_libclang=ON option for CMake.
+# The default value is: NO.
+
+CLANG_ASSISTED_PARSING = NO
+
+# If clang assisted parsing is enabled you can provide the compiler with command
+# line options that you would normally use when invoking the compiler. Note that
+# the include paths will already be set by doxygen for the files and directories
+# specified with INPUT and INCLUDE_PATH.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+
+CLANG_OPTIONS          =
+
+# If clang assisted parsing is enabled you can provide the clang parser with the
+# path to the compilation database (see:
+# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) used when the files
+# were built. This is equivalent to specifying the "-p" option to a clang tool,
+# such as clang-check. These options will then be passed to the parser.
+# Note: The availability of this option depends on whether or not doxygen was
+# generated with the -Duse_libclang=ON option for CMake.
+
+CLANG_DATABASE_PATH    =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX     = YES
+
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX          =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER            =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER            =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET        =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefore more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list). For an example see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET  =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES       =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the style sheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE    = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT    = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA  = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to YES can help to show when doxygen was last run and thus if the
+# documentation is up to date.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP         = NO
+
+# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
+# documentation will contain a main index with vertical navigation menus that
+# are dynamically created via Javascript. If disabled, the navigation index will
+# consists of multiple levels of tabs that are statically embedded in every HTML
+# page. Disable this option to support browsers that do not have Javascript,
+# like the Qt help browser.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_MENUS     = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS  = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: https://developer.apple.com/xcode/), introduced with OSX
+# 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
+# genXcode/_index.html for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET        = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME  = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP      = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE               =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler (hhc.exe). If non-empty,
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION           =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated
+# (YES) or that it should be included in the master .chm file (NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI           = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING     =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated
+# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND             = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP           = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE               =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE          = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER     = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME   =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS  =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS  =
+
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION           =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP   = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID         = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX          = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW      = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH         = 250
+
+# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW    = NO
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE       = 10
+
+# Use the FORMULA_TRANSPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT    = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# https://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX            = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT         = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from https://www.mathjax.org before deployment.
+# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS     =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE       =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE           = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH    = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: https://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH        = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: https://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL       =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE        = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID     =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS  =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when not enabling USE_PDFLATEX the default is latex when enabling
+# USE_PDFLATEX the default is pdflatex and when in the later case latex is
+# chosen this is overwritten by pdflatex. For specific output languages the
+# default can have been set differently, this depends on the implementation of
+# the output language.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# Note: This tag is used in the Makefile / make.bat.
+# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file
+# (.tex).
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to
+# generate index for LaTeX. In case there is no backslash (\) as first character
+# it will be automatically added in the LaTeX code.
+# Note: This tag is used in the generated output file (.tex).
+# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.
+# The default value is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_MAKEINDEX_CMD    = makeindex
+
+# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE             = a4
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. The package can be specified just
+# by its name or with the correct syntax as to be used with the LaTeX
+# \usepackage command. To get the times font for instance you can specify :
+# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
+# To use the option intlimits with the amsmath package you can specify:
+# EXTRA_PACKAGES=[intlimits]{amsmath}
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES         =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
+# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
+# string, for the replacement values of the other commands the user is referred
+# to HTML_HEADER.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER           =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER           =
+
+# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# LaTeX style sheets that are included after the standard style sheets created
+# by doxygen. Using this option one can overrule certain style aspects. Doxygen
+# will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_STYLESHEET =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES      =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS         = YES
+
+# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES, to get a
+# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE        = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES     = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE      = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE        = plain
+
+# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_TIMESTAMP        = NO
+
+# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute)
+# path from which the emoji images will be read. If a relative path is entered,
+# it will be relative to the LATEX_OUTPUT directory. If left blank the
+# LATEX_OUTPUT directory will be used.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EMOJI_DIRECTORY  =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# configuration file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE    =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's configuration file. A template extensions file can be
+# generated using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE    =
+
+# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
+# with syntax highlighting in the RTF output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_SOURCE_CODE        = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION          = .3
+
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR             =
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT             = xml
+
+# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING     = YES
+
+# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include
+# namespace members in file scope as well, matching the HTML output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_NS_MEMB_FILE_SCOPE = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK       = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT         = docbook
+
+# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
+# program listings (including syntax highlighting and cross-referencing
+# information) to the DOCBOOK output. Note that enabling this will significantly
+# increase the size of the DOCBOOK output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_PROGRAMLISTING = NO
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
+# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures
+# the structure of the code including all documentation. Note that this feature
+# is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO, the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
+# in the source code. If set to NO, only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION        = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF     = YES
+
+# If the SEARCH_INCLUDES tag is set to YES, the include files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH           =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS  =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED             = VMA_CALL_PRE= VMA_CALL_POST=
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED      =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have a unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES               =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE       =
+
+# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
+# the class index. If set to NO, only the inherited external classes will be
+# listed.
+# The default value is: NO.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS        = YES
+
+# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES         = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
+
+CLASS_DIAGRAMS         = YES
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH               =
+
+# If set to YES the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
+
+HAVE_DOT               = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS        = 0
+
+# When you want a differently looking font in the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME           = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE           = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH           =
+
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK               = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LIMIT_NUM_FIELDS   = 10
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH          = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command. Disabling a call graph can be
+# accomplished by means of the command \hidecallgraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH             = NO
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command. Disabling a caller graph can be
+# accomplished by means of the command \hidecallergraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH           = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. For an explanation of the image formats see the section
+# output formats in the documentation of the dot tool (Graphviz (see:
+# http://www.graphviz.org/)).
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,
+# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
+# png:gdiplus:gdiplus.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT       = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG        = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH               =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS           =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS           =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS           =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file. If left blank, it is assumed
+# PlantUML is not used or called during a preprocessing step. Doxygen will
+# generate a warning when it encounters a \startuml command in this case and
+# will not generate output for the diagram.
+
+PLANTUML_JAR_PATH      =
+
+# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
+# configuration file for plantuml.
+
+PLANTUML_CFG_FILE      =
+
+# When using plantuml, the specified paths are searched for files specified by
+# the !include statement in a plantuml block.
+
+PLANTUML_INCLUDE_PATH  =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES    = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT        = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_CLEANUP            = YES
diff --git a/third_party/VulkanMemoryAllocator/src/Shaders/CompileShaders.bat b/third_party/VulkanMemoryAllocator/src/Shaders/CompileShaders.bat
new file mode 100644
index 0000000..4256499
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/src/Shaders/CompileShaders.bat
@@ -0,0 +1,4 @@
+%VULKAN_SDK%/Bin32/glslangValidator.exe -V -o ../../bin/Shader.vert.spv Shader.vert
+%VULKAN_SDK%/Bin32/glslangValidator.exe -V -o ../../bin/Shader.frag.spv Shader.frag
+%VULKAN_SDK%/Bin32/glslangValidator.exe -V -o ../../bin/SparseBindingTest.comp.spv SparseBindingTest.comp
+pause
diff --git a/third_party/VulkanMemoryAllocator/src/Shaders/Shader.frag b/third_party/VulkanMemoryAllocator/src/Shaders/Shader.frag
new file mode 100644
index 0000000..6c32d89
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/src/Shaders/Shader.frag
@@ -0,0 +1,37 @@
+//
+// Copyright (c) 2017-2020 Advanced Micro Devices, Inc. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#version 450
+#extension GL_ARB_separate_shader_objects : enable
+
+layout(location = 0) in vec3 inColor;
+layout(location = 1) in vec2 inTexCoord;
+
+layout(location = 0) out vec4 outColor;
+
+layout(binding = 1) uniform sampler2D texSampler;
+
+void main()
+{
+    outColor = texture(texSampler, inTexCoord);
+    outColor.rgb *= inColor;
+}
diff --git a/third_party/VulkanMemoryAllocator/src/Shaders/Shader.vert b/third_party/VulkanMemoryAllocator/src/Shaders/Shader.vert
new file mode 100644
index 0000000..8349579
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/src/Shaders/Shader.vert
@@ -0,0 +1,42 @@
+//
+// Copyright (c) 2017-2020 Advanced Micro Devices, Inc. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#version 450
+#extension GL_ARB_separate_shader_objects : enable
+
+layout(push_constant) uniform UniformBufferObject
+{
+    mat4 ModelViewProj;
+} ubo;
+
+layout(location = 0) in vec3 inPosition;
+layout(location = 1) in vec3 inColor;
+layout(location = 2) in vec2 inTexCoord;
+
+layout(location = 0) out vec3 outColor;
+layout(location = 1) out vec2 outTexCoord;
+
+void main() {
+    gl_Position = ubo.ModelViewProj * vec4(inPosition, 1.0);
+    outColor = inColor;
+    outTexCoord = inTexCoord;
+}
diff --git a/third_party/VulkanMemoryAllocator/src/Shaders/SparseBindingTest.comp b/third_party/VulkanMemoryAllocator/src/Shaders/SparseBindingTest.comp
new file mode 100644
index 0000000..102637d
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/src/Shaders/SparseBindingTest.comp
@@ -0,0 +1,44 @@
+//
+// Copyright (c) 2018-2020 Advanced Micro Devices, Inc. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#version 450
+#extension GL_ARB_separate_shader_objects : enable
+
+layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
+
+layout(binding=0) uniform sampler2D img;
+layout(binding=1) buffer buf
+{
+	uint bufValues[];
+};
+
+void main()
+{
+	ivec2 xy = ivec2(bufValues[gl_GlobalInvocationID.x * 3],
+		bufValues[gl_GlobalInvocationID.x * 3 + 1]);
+	vec4 color = texture(img, xy);
+	bufValues[gl_GlobalInvocationID.x * 3 + 2] =
+		uint(color.r * 255.0) << 24 |
+		uint(color.g * 255.0) << 16 |
+		uint(color.b * 255.0) <<  8 |
+		uint(color.a * 255.0);
+}
diff --git a/third_party/VulkanMemoryAllocator/src/SparseBindingTest.cpp b/third_party/VulkanMemoryAllocator/src/SparseBindingTest.cpp
new file mode 100644
index 0000000..4562cf4
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/src/SparseBindingTest.cpp
@@ -0,0 +1,593 @@
+//
+// Copyright (c) 2017-2020 Advanced Micro Devices, Inc. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#include "Common.h"
+#include "SparseBindingTest.h"
+
+#ifdef _WIN32
+
+////////////////////////////////////////////////////////////////////////////////
+// External imports
+
+extern VkDevice g_hDevice;
+extern VmaAllocator g_hAllocator;
+extern uint32_t g_FrameIndex;
+extern bool g_SparseBindingEnabled;
+extern VkQueue g_hSparseBindingQueue;
+extern VkFence g_ImmediateFence;
+extern VkCommandBuffer g_hTemporaryCommandBuffer;
+
+void BeginSingleTimeCommands();
+void EndSingleTimeCommands();
+void SaveAllocatorStatsToFile(const wchar_t* filePath);
+void LoadShader(std::vector<char>& out, const char* fileName);
+
+////////////////////////////////////////////////////////////////////////////////
+// Class definitions
+
+static uint32_t CalculateMipMapCount(uint32_t width, uint32_t height, uint32_t depth)
+{
+    uint32_t mipMapCount = 1;
+    while(width > 1 || height > 1 || depth > 1)
+    {
+        ++mipMapCount;
+        width  /= 2;
+        height /= 2;
+        depth  /= 2;
+    }
+    return mipMapCount;
+}
+
+class BaseImage
+{
+public:
+    virtual void Init(RandomNumberGenerator& rand) = 0;
+    virtual ~BaseImage();
+
+    const VkImageCreateInfo& GetCreateInfo() const { return m_CreateInfo; }
+
+    void TestContent(RandomNumberGenerator& rand);
+
+protected:
+    VkImageCreateInfo m_CreateInfo = {};
+    VkImage m_Image = VK_NULL_HANDLE;
+
+    void FillImageCreateInfo(RandomNumberGenerator& rand);
+    void UploadContent();
+    void ValidateContent(RandomNumberGenerator& rand);
+};
+
+class TraditionalImage : public BaseImage
+{
+public:
+    virtual void Init(RandomNumberGenerator& rand);
+    virtual ~TraditionalImage();
+
+private:
+    VmaAllocation m_Allocation = VK_NULL_HANDLE;
+};
+
+class SparseBindingImage : public BaseImage
+{
+public:
+    virtual void Init(RandomNumberGenerator& rand);
+    virtual ~SparseBindingImage();
+
+private:
+    std::vector<VmaAllocation> m_Allocations;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// class BaseImage
+
+BaseImage::~BaseImage()
+{
+    if(m_Image)
+    {
+        vkDestroyImage(g_hDevice, m_Image, nullptr);
+    }
+}
+
+void BaseImage::TestContent(RandomNumberGenerator& rand)
+{
+    printf("Validating content of %u x %u texture...\n",
+        m_CreateInfo.extent.width, m_CreateInfo.extent.height);
+    UploadContent();
+    ValidateContent(rand);
+}
+
+void BaseImage::FillImageCreateInfo(RandomNumberGenerator& rand)
+{
+    constexpr uint32_t imageSizeMin = 8;
+    constexpr uint32_t imageSizeMax = 2048;
+
+    const bool useMipMaps = rand.Generate() % 2 != 0;
+
+    ZeroMemory(&m_CreateInfo, sizeof(m_CreateInfo));
+    m_CreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
+    m_CreateInfo.imageType = VK_IMAGE_TYPE_2D;
+    m_CreateInfo.extent.width = rand.Generate() % (imageSizeMax - imageSizeMin) + imageSizeMin;
+    m_CreateInfo.extent.height = rand.Generate() % (imageSizeMax - imageSizeMin) + imageSizeMin;
+    m_CreateInfo.extent.depth = 1;
+    m_CreateInfo.mipLevels = useMipMaps ?
+        CalculateMipMapCount(m_CreateInfo.extent.width, m_CreateInfo.extent.height, m_CreateInfo.extent.depth) : 1;
+    m_CreateInfo.arrayLayers = 1;
+    m_CreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
+    m_CreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
+    m_CreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+    m_CreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+    m_CreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
+    m_CreateInfo.flags = 0;
+}
+
+void BaseImage::UploadContent()
+{
+    VkBufferCreateInfo srcBufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+    srcBufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+    srcBufCreateInfo.size = 4 * m_CreateInfo.extent.width * m_CreateInfo.extent.height;
+
+    VmaAllocationCreateInfo srcBufAllocCreateInfo = {};
+    srcBufAllocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
+    srcBufAllocCreateInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
+
+    VkBuffer srcBuf = nullptr;
+    VmaAllocation srcBufAlloc = nullptr;
+    VmaAllocationInfo srcAllocInfo = {};
+    TEST( vmaCreateBuffer(g_hAllocator, &srcBufCreateInfo, &srcBufAllocCreateInfo, &srcBuf, &srcBufAlloc, &srcAllocInfo) == VK_SUCCESS );
+    
+    // Fill texels with: r = x % 255, g = u % 255, b = 13, a = 25
+    uint32_t* srcBufPtr = (uint32_t*)srcAllocInfo.pMappedData;
+    for(uint32_t y = 0, sizeY = m_CreateInfo.extent.height; y < sizeY; ++y)
+    {
+        for(uint32_t x = 0, sizeX = m_CreateInfo.extent.width; x < sizeX; ++x, ++srcBufPtr)
+        {
+            const uint8_t r = (uint8_t)x;
+            const uint8_t g = (uint8_t)y;
+            const uint8_t b = 13;
+            const uint8_t a = 25;
+            *srcBufPtr = (uint32_t)r << 24 | (uint32_t)g << 16 |
+                (uint32_t)b << 8 | (uint32_t)a;
+        }
+    }
+
+    BeginSingleTimeCommands();
+
+    // Barrier undefined to transfer dst.
+    {
+        VkImageMemoryBarrier barrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER };
+        barrier.srcAccessMask = 0;
+        barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+        barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+        barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+        barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+        barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+        barrier.image = m_Image;
+        barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+        barrier.subresourceRange.baseArrayLayer = 0;
+        barrier.subresourceRange.baseMipLevel = 0;
+        barrier.subresourceRange.layerCount = 1;
+        barrier.subresourceRange.levelCount = 1;
+
+        vkCmdPipelineBarrier(g_hTemporaryCommandBuffer,
+            VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, // srcStageMask
+            VK_PIPELINE_STAGE_TRANSFER_BIT, // dstStageMask
+            0, // dependencyFlags
+            0, nullptr, // memoryBarriers
+            0, nullptr, // bufferMemoryBarriers
+            1, &barrier); // imageMemoryBarriers
+    }
+
+    // CopyBufferToImage
+    {
+        VkBufferImageCopy region = {};
+        region.bufferOffset = 0;
+        region.bufferRowLength = 0; // Zeros mean tightly packed.
+        region.bufferImageHeight = 0; // Zeros mean tightly packed.
+        region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+        region.imageSubresource.mipLevel = 0;
+        region.imageSubresource.baseArrayLayer = 0;
+        region.imageSubresource.layerCount = 1;
+        region.imageOffset = { 0, 0, 0 };
+        region.imageExtent = m_CreateInfo.extent;
+        vkCmdCopyBufferToImage(g_hTemporaryCommandBuffer, srcBuf, m_Image,
+            VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
+    }
+    
+    // Barrier transfer dst to fragment shader read only.
+    {
+        VkImageMemoryBarrier barrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER };
+        barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+        barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
+        barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+        barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+        barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+        barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+        barrier.image = m_Image;
+        barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+        barrier.subresourceRange.baseArrayLayer = 0;
+        barrier.subresourceRange.baseMipLevel = 0;
+        barrier.subresourceRange.layerCount = 1;
+        barrier.subresourceRange.levelCount = 1;
+
+        vkCmdPipelineBarrier(g_hTemporaryCommandBuffer,
+            VK_PIPELINE_STAGE_TRANSFER_BIT, // srcStageMask
+            VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // dstStageMask
+            0, // dependencyFlags
+            0, nullptr, // memoryBarriers
+            0, nullptr, // bufferMemoryBarriers
+            1, &barrier); // imageMemoryBarriers
+    }
+
+    EndSingleTimeCommands();
+
+    vmaDestroyBuffer(g_hAllocator, srcBuf, srcBufAlloc);
+}
+
+void BaseImage::ValidateContent(RandomNumberGenerator& rand)
+{
+    /*
+    dstBuf has following layout:
+    For each of texels to be sampled, [0..valueCount):
+    struct {
+        in uint32_t pixelX;
+        in uint32_t pixelY;
+        out uint32_t pixelColor;
+    }
+    */
+
+    const uint32_t valueCount = 128;
+
+    VkBufferCreateInfo dstBufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+    dstBufCreateInfo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
+    dstBufCreateInfo.size = valueCount * sizeof(uint32_t) * 3;
+
+    VmaAllocationCreateInfo dstBufAllocCreateInfo = {};
+    dstBufAllocCreateInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
+    dstBufAllocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_TO_CPU;
+
+    VkBuffer dstBuf = nullptr;
+    VmaAllocation dstBufAlloc = nullptr;
+    VmaAllocationInfo dstBufAllocInfo = {};
+    TEST( vmaCreateBuffer(g_hAllocator, &dstBufCreateInfo, &dstBufAllocCreateInfo, &dstBuf, &dstBufAlloc, &dstBufAllocInfo) == VK_SUCCESS );
+
+    // Fill dstBuf input data.
+    {
+        uint32_t* dstBufContent = (uint32_t*)dstBufAllocInfo.pMappedData;
+        for(uint32_t i = 0; i < valueCount; ++i)
+        {
+            const uint32_t x = rand.Generate() % m_CreateInfo.extent.width;
+            const uint32_t y = rand.Generate() % m_CreateInfo.extent.height;
+            dstBufContent[i * 3    ] = x;
+            dstBufContent[i * 3 + 1] = y;
+            dstBufContent[i * 3 + 2] = 0;
+        }
+    }
+
+    VkSamplerCreateInfo samplerCreateInfo = { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO };
+    samplerCreateInfo.magFilter = VK_FILTER_NEAREST;
+    samplerCreateInfo.minFilter = VK_FILTER_NEAREST;
+    samplerCreateInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
+    samplerCreateInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
+    samplerCreateInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
+    samplerCreateInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
+    samplerCreateInfo.unnormalizedCoordinates = VK_TRUE;
+
+    VkSampler sampler = nullptr;
+    TEST( vkCreateSampler( g_hDevice, &samplerCreateInfo, nullptr, &sampler) == VK_SUCCESS );
+
+    VkDescriptorSetLayoutBinding bindings[2] = {};
+    bindings[0].binding = 0;
+    bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+    bindings[0].descriptorCount = 1;
+    bindings[0].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
+    bindings[0].pImmutableSamplers = &sampler;
+    bindings[1].binding = 1;
+    bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+    bindings[1].descriptorCount = 1;
+    bindings[1].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
+
+    VkDescriptorSetLayoutCreateInfo descSetLayoutCreateInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO };
+    descSetLayoutCreateInfo.bindingCount = 2;
+    descSetLayoutCreateInfo.pBindings = bindings;
+
+    VkDescriptorSetLayout descSetLayout = nullptr;
+    TEST( vkCreateDescriptorSetLayout(g_hDevice, &descSetLayoutCreateInfo, nullptr, &descSetLayout) == VK_SUCCESS );
+
+    VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };
+    pipelineLayoutCreateInfo.setLayoutCount = 1;
+    pipelineLayoutCreateInfo.pSetLayouts = &descSetLayout;
+
+    VkPipelineLayout pipelineLayout = nullptr;
+    TEST( vkCreatePipelineLayout(g_hDevice, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout) == VK_SUCCESS );
+
+    std::vector<char> shaderCode;
+    LoadShader(shaderCode, "SparseBindingTest.comp.spv");
+
+    VkShaderModuleCreateInfo shaderModuleCreateInfo = { VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO };
+    shaderModuleCreateInfo.codeSize = shaderCode.size();
+    shaderModuleCreateInfo.pCode = (const uint32_t*)shaderCode.data();
+
+    VkShaderModule shaderModule = nullptr;
+    TEST( vkCreateShaderModule(g_hDevice, &shaderModuleCreateInfo, nullptr, &shaderModule) == VK_SUCCESS );
+
+    VkComputePipelineCreateInfo pipelineCreateInfo = { VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO };
+    pipelineCreateInfo.stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
+    pipelineCreateInfo.stage.stage = VK_SHADER_STAGE_COMPUTE_BIT;
+    pipelineCreateInfo.stage.module = shaderModule;
+    pipelineCreateInfo.stage.pName = "main";
+    pipelineCreateInfo.layout = pipelineLayout;
+
+    VkPipeline pipeline = nullptr;
+    TEST( vkCreateComputePipelines(g_hDevice, nullptr, 1, &pipelineCreateInfo, nullptr, &pipeline) == VK_SUCCESS );
+
+    VkDescriptorPoolSize poolSizes[2] = {};
+    poolSizes[0].type = bindings[0].descriptorType;
+    poolSizes[0].descriptorCount = bindings[0].descriptorCount;
+    poolSizes[1].type = bindings[1].descriptorType;
+    poolSizes[1].descriptorCount = bindings[1].descriptorCount;
+
+    VkDescriptorPoolCreateInfo descPoolCreateInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO };
+    descPoolCreateInfo.maxSets = 1;
+    descPoolCreateInfo.poolSizeCount = 2;
+    descPoolCreateInfo.pPoolSizes = poolSizes;
+
+    VkDescriptorPool descPool = nullptr;
+    TEST( vkCreateDescriptorPool(g_hDevice, &descPoolCreateInfo, nullptr, &descPool) == VK_SUCCESS );
+
+    VkDescriptorSetAllocateInfo descSetAllocInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO };
+    descSetAllocInfo.descriptorPool = descPool;
+    descSetAllocInfo.descriptorSetCount = 1;
+    descSetAllocInfo.pSetLayouts = &descSetLayout;
+
+    VkDescriptorSet descSet = nullptr;
+    TEST( vkAllocateDescriptorSets(g_hDevice, &descSetAllocInfo, &descSet) == VK_SUCCESS );
+
+    VkImageViewCreateInfo imageViewCreateInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO };
+    imageViewCreateInfo.image = m_Image;
+    imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
+    imageViewCreateInfo.format = m_CreateInfo.format;
+    imageViewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+    imageViewCreateInfo.subresourceRange.layerCount = 1;
+    imageViewCreateInfo.subresourceRange.levelCount = 1;
+
+    VkImageView imageView = nullptr;
+    TEST( vkCreateImageView(g_hDevice, &imageViewCreateInfo, nullptr, &imageView) == VK_SUCCESS );
+
+    VkDescriptorImageInfo descImageInfo = {};
+    descImageInfo.imageView = imageView;
+    descImageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+
+    VkDescriptorBufferInfo descBufferInfo = {};
+    descBufferInfo.buffer = dstBuf;
+    descBufferInfo.offset = 0;
+    descBufferInfo.range = VK_WHOLE_SIZE;
+
+    VkWriteDescriptorSet descWrites[2] = {};
+    descWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+    descWrites[0].dstSet = descSet;
+    descWrites[0].dstBinding = bindings[0].binding;
+    descWrites[0].dstArrayElement = 0;
+    descWrites[0].descriptorCount = 1;
+    descWrites[0].descriptorType = bindings[0].descriptorType;
+    descWrites[0].pImageInfo = &descImageInfo;
+    descWrites[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+    descWrites[1].dstSet = descSet;
+    descWrites[1].dstBinding = bindings[1].binding;
+    descWrites[1].dstArrayElement = 0;
+    descWrites[1].descriptorCount = 1;
+    descWrites[1].descriptorType = bindings[1].descriptorType;
+    descWrites[1].pBufferInfo = &descBufferInfo;
+    vkUpdateDescriptorSets(g_hDevice, 2, descWrites, 0, nullptr);
+
+    BeginSingleTimeCommands();
+    vkCmdBindPipeline(g_hTemporaryCommandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline);
+    vkCmdBindDescriptorSets(g_hTemporaryCommandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0, 1, &descSet, 0, nullptr);
+    vkCmdDispatch(g_hTemporaryCommandBuffer, valueCount, 1, 1);
+    EndSingleTimeCommands();
+
+    // Validate dstBuf output data.
+    {
+        const uint32_t* dstBufContent = (const uint32_t*)dstBufAllocInfo.pMappedData;
+        for(uint32_t i = 0; i < valueCount; ++i)
+        {
+            const uint32_t x     = dstBufContent[i * 3    ];
+            const uint32_t y     = dstBufContent[i * 3 + 1];
+            const uint32_t color = dstBufContent[i * 3 + 2];
+            const uint8_t a = (uint8_t)(color >> 24);
+            const uint8_t b = (uint8_t)(color >> 16);
+            const uint8_t g = (uint8_t)(color >>  8);
+            const uint8_t r = (uint8_t)color;
+            TEST(r == (uint8_t)x && g == (uint8_t)y && b == 13 && a == 25);
+        }
+    }
+
+    vkDestroyImageView(g_hDevice, imageView, nullptr);
+    vkDestroyDescriptorPool(g_hDevice, descPool, nullptr);
+    vmaDestroyBuffer(g_hAllocator, dstBuf, dstBufAlloc);
+    vkDestroyPipeline(g_hDevice, pipeline, nullptr);
+    vkDestroyShaderModule(g_hDevice, shaderModule, nullptr);
+    vkDestroyPipelineLayout(g_hDevice, pipelineLayout, nullptr);
+    vkDestroyDescriptorSetLayout(g_hDevice, descSetLayout, nullptr);
+    vkDestroySampler(g_hDevice, sampler, nullptr);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// class TraditionalImage
+
+void TraditionalImage::Init(RandomNumberGenerator& rand)
+{
+    FillImageCreateInfo(rand);
+
+    VmaAllocationCreateInfo allocCreateInfo = {};
+    allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+    // Default BEST_FIT is clearly better.
+    //allocCreateInfo.flags |= VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT;
+    
+    ERR_GUARD_VULKAN( vmaCreateImage(g_hAllocator, &m_CreateInfo, &allocCreateInfo,
+        &m_Image, &m_Allocation, nullptr) );
+}
+
+TraditionalImage::~TraditionalImage()
+{
+    if(m_Allocation)
+    {
+        vmaFreeMemory(g_hAllocator, m_Allocation);
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// class SparseBindingImage
+
+void SparseBindingImage::Init(RandomNumberGenerator& rand)
+{
+    assert(g_SparseBindingEnabled && g_hSparseBindingQueue);
+
+    // Create image.
+    FillImageCreateInfo(rand);
+    m_CreateInfo.flags |= VK_IMAGE_CREATE_SPARSE_BINDING_BIT;
+    ERR_GUARD_VULKAN( vkCreateImage(g_hDevice, &m_CreateInfo, nullptr, &m_Image) );
+
+    // Get memory requirements.
+    VkMemoryRequirements imageMemReq;
+    vkGetImageMemoryRequirements(g_hDevice, m_Image, &imageMemReq);
+
+    // This is just to silence validation layer warning.
+    // But it doesn't help. Looks like a bug in Vulkan validation layers.
+    // See: https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/364
+    uint32_t sparseMemReqCount = 0;
+    vkGetImageSparseMemoryRequirements(g_hDevice, m_Image, &sparseMemReqCount, nullptr);
+    TEST(sparseMemReqCount <= 8);
+    VkSparseImageMemoryRequirements sparseMemReq[8];
+    vkGetImageSparseMemoryRequirements(g_hDevice, m_Image, &sparseMemReqCount, sparseMemReq);
+
+    // According to Vulkan specification, for sparse resources memReq.alignment is also page size.
+    const VkDeviceSize pageSize = imageMemReq.alignment;
+    const uint32_t pageCount = (uint32_t)ceil_div<VkDeviceSize>(imageMemReq.size, pageSize);
+
+    VmaAllocationCreateInfo allocCreateInfo = {};
+    allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+
+    VkMemoryRequirements pageMemReq = imageMemReq;
+    pageMemReq.size = pageSize;
+
+    // Allocate and bind memory pages.
+    m_Allocations.resize(pageCount);
+    std::fill(m_Allocations.begin(), m_Allocations.end(), nullptr);
+    std::vector<VkSparseMemoryBind> binds{pageCount};
+    std::vector<VmaAllocationInfo> allocInfo{pageCount};
+    ERR_GUARD_VULKAN( vmaAllocateMemoryPages(g_hAllocator, &pageMemReq, &allocCreateInfo, pageCount, m_Allocations.data(), allocInfo.data()) );
+
+    for(uint32_t i = 0; i < pageCount; ++i)
+    {
+        binds[i] = {};
+        binds[i].resourceOffset = pageSize * i;
+        binds[i].size = pageSize;
+        binds[i].memory = allocInfo[i].deviceMemory;
+        binds[i].memoryOffset = allocInfo[i].offset;
+    }
+
+    VkSparseImageOpaqueMemoryBindInfo imageBindInfo;
+    imageBindInfo.image = m_Image;
+    imageBindInfo.bindCount = pageCount;
+    imageBindInfo.pBinds = binds.data();
+
+    VkBindSparseInfo bindSparseInfo = { VK_STRUCTURE_TYPE_BIND_SPARSE_INFO };
+    bindSparseInfo.pImageOpaqueBinds = &imageBindInfo;
+    bindSparseInfo.imageOpaqueBindCount = 1;
+    
+    ERR_GUARD_VULKAN( vkResetFences(g_hDevice, 1, &g_ImmediateFence) );
+    ERR_GUARD_VULKAN( vkQueueBindSparse(g_hSparseBindingQueue, 1, &bindSparseInfo, g_ImmediateFence) );
+    ERR_GUARD_VULKAN( vkWaitForFences(g_hDevice, 1, &g_ImmediateFence, VK_TRUE, UINT64_MAX) );
+}
+
+SparseBindingImage::~SparseBindingImage()
+{
+    vmaFreeMemoryPages(g_hAllocator, m_Allocations.size(), m_Allocations.data());
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Private functions
+
+////////////////////////////////////////////////////////////////////////////////
+// Public functions
+
+void TestSparseBinding()
+{
+    struct ImageInfo
+    {
+        std::unique_ptr<BaseImage> image;
+        uint32_t endFrame;
+    };
+    std::vector<ImageInfo> images;
+
+    constexpr uint32_t frameCount = 1000;
+    constexpr uint32_t imageLifeFramesMin = 1;
+    constexpr uint32_t imageLifeFramesMax = 400;
+
+    RandomNumberGenerator rand(4652467);
+
+    for(uint32_t i = 0; i < frameCount; ++i)
+    {
+        // Bump frame index.
+        ++g_FrameIndex;
+        vmaSetCurrentFrameIndex(g_hAllocator, g_FrameIndex);
+
+        // Create one new, random image.
+        ImageInfo imageInfo;
+        //imageInfo.image = std::make_unique<TraditionalImage>();
+        imageInfo.image = std::make_unique<SparseBindingImage>();
+        imageInfo.image->Init(rand);
+        imageInfo.endFrame = g_FrameIndex + rand.Generate() % (imageLifeFramesMax - imageLifeFramesMin) + imageLifeFramesMin;
+        images.push_back(std::move(imageInfo));
+
+        // Delete all images that expired.
+        for(size_t i = images.size(); i--; )
+        {
+            if(g_FrameIndex >= images[i].endFrame)
+            {
+                images.erase(images.begin() + i);
+            }
+        }
+    }
+
+    SaveAllocatorStatsToFile(L"SparseBindingTest.json");
+
+    // Choose biggest image. Test uploading and sampling.
+    BaseImage* biggestImage = nullptr;
+    for(size_t i = 0, count = images.size(); i < count; ++i)
+    {
+        if(!biggestImage ||
+            images[i].image->GetCreateInfo().extent.width * images[i].image->GetCreateInfo().extent.height >
+                biggestImage->GetCreateInfo().extent.width * biggestImage->GetCreateInfo().extent.height)
+        {
+            biggestImage = images[i].image.get();
+        }
+    }
+    assert(biggestImage);
+
+    biggestImage->TestContent(rand);
+
+    // Free remaining images.
+    images.clear();
+}
+
+#endif // #ifdef _WIN32
diff --git a/third_party/VulkanMemoryAllocator/src/SparseBindingTest.h b/third_party/VulkanMemoryAllocator/src/SparseBindingTest.h
new file mode 100644
index 0000000..05a6aa8
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/src/SparseBindingTest.h
@@ -0,0 +1,29 @@
+//
+// Copyright (c) 2017-2020 Advanced Micro Devices, Inc. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#pragma once
+
+#ifdef _WIN32
+
+void TestSparseBinding();
+
+#endif // #ifdef _WIN32
diff --git a/third_party/VulkanMemoryAllocator/src/Tests.cpp b/third_party/VulkanMemoryAllocator/src/Tests.cpp
new file mode 100644
index 0000000..ee5fae1
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/src/Tests.cpp
@@ -0,0 +1,6359 @@
+//
+// Copyright (c) 2017-2020 Advanced Micro Devices, Inc. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#include "Tests.h"
+#include "VmaUsage.h"
+#include "Common.h"
+#include <atomic>
+#include <thread>
+#include <mutex>
+#include <functional>
+
+#ifdef _WIN32
+
+static const char* CODE_DESCRIPTION = "Foo";
+
+extern VkCommandBuffer g_hTemporaryCommandBuffer;
+extern const VkAllocationCallbacks* g_Allocs;
+extern bool g_BufferDeviceAddressEnabled;
+extern PFN_vkGetBufferDeviceAddressEXT g_vkGetBufferDeviceAddressEXT;
+void BeginSingleTimeCommands();
+void EndSingleTimeCommands();
+
+#ifndef VMA_DEBUG_MARGIN
+    #define VMA_DEBUG_MARGIN 0
+#endif
+
+enum CONFIG_TYPE {
+    CONFIG_TYPE_MINIMUM,
+    CONFIG_TYPE_SMALL,
+    CONFIG_TYPE_AVERAGE,
+    CONFIG_TYPE_LARGE,
+    CONFIG_TYPE_MAXIMUM,
+    CONFIG_TYPE_COUNT
+};
+
+static constexpr CONFIG_TYPE ConfigType = CONFIG_TYPE_SMALL;
+//static constexpr CONFIG_TYPE ConfigType = CONFIG_TYPE_LARGE;
+
+enum class FREE_ORDER { FORWARD, BACKWARD, RANDOM, COUNT };
+
+static const char* FREE_ORDER_NAMES[] = {
+    "FORWARD",
+    "BACKWARD",
+    "RANDOM",
+};
+
+// Copy of internal VmaAlgorithmToStr.
+static const char* AlgorithmToStr(uint32_t algorithm)
+{
+    switch(algorithm)
+    {
+    case VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT:
+        return "Linear";
+    case VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT:
+        return "Buddy";
+    case 0:
+        return "Default";
+    default:
+        assert(0);
+        return "";
+    }
+}
+
+struct AllocationSize
+{
+    uint32_t Probability;
+    VkDeviceSize BufferSizeMin, BufferSizeMax;
+    uint32_t ImageSizeMin, ImageSizeMax;
+};
+
+struct Config
+{
+    uint32_t RandSeed;
+    VkDeviceSize BeginBytesToAllocate;
+    uint32_t AdditionalOperationCount;
+    VkDeviceSize MaxBytesToAllocate;
+    uint32_t MemUsageProbability[4]; // For VMA_MEMORY_USAGE_*
+    std::vector<AllocationSize> AllocationSizes;
+    uint32_t ThreadCount;
+    uint32_t ThreadsUsingCommonAllocationsProbabilityPercent;
+    FREE_ORDER FreeOrder;
+    VmaAllocationCreateFlags AllocationStrategy; // For VMA_ALLOCATION_CREATE_STRATEGY_*
+};
+
+struct Result
+{
+    duration TotalTime;
+    duration AllocationTimeMin, AllocationTimeAvg, AllocationTimeMax;
+    duration DeallocationTimeMin, DeallocationTimeAvg, DeallocationTimeMax;
+    VkDeviceSize TotalMemoryAllocated;
+    VkDeviceSize FreeRangeSizeAvg, FreeRangeSizeMax;
+};
+
+void TestDefragmentationSimple();
+void TestDefragmentationFull();
+
+struct PoolTestConfig
+{
+    uint32_t RandSeed;
+    uint32_t ThreadCount;
+    VkDeviceSize PoolSize;
+    uint32_t FrameCount;
+    uint32_t TotalItemCount;
+    // Range for number of items used in each frame.
+    uint32_t UsedItemCountMin, UsedItemCountMax;
+    // Percent of items to make unused, and possibly make some others used in each frame.
+    uint32_t ItemsToMakeUnusedPercent;
+    std::vector<AllocationSize> AllocationSizes;
+
+    VkDeviceSize CalcAvgResourceSize() const
+    {
+        uint32_t probabilitySum = 0;
+        VkDeviceSize sizeSum = 0;
+        for(size_t i = 0; i < AllocationSizes.size(); ++i)
+        {
+            const AllocationSize& allocSize = AllocationSizes[i];
+            if(allocSize.BufferSizeMax > 0)
+                sizeSum += (allocSize.BufferSizeMin + allocSize.BufferSizeMax) / 2 * allocSize.Probability;
+            else
+            {
+                const VkDeviceSize avgDimension = (allocSize.ImageSizeMin + allocSize.ImageSizeMax) / 2;
+                sizeSum += avgDimension * avgDimension * 4 * allocSize.Probability;
+            }
+            probabilitySum += allocSize.Probability;
+        }
+        return sizeSum / probabilitySum;
+    }
+
+    bool UsesBuffers() const
+    {
+        for(size_t i = 0; i < AllocationSizes.size(); ++i)
+            if(AllocationSizes[i].BufferSizeMax > 0)
+                return true;
+        return false;
+    }
+
+    bool UsesImages() const
+    {
+        for(size_t i = 0; i < AllocationSizes.size(); ++i)
+            if(AllocationSizes[i].ImageSizeMax > 0)
+                return true;
+        return false;
+    }
+};
+
+struct PoolTestResult
+{
+    duration TotalTime;
+    duration AllocationTimeMin, AllocationTimeAvg, AllocationTimeMax;
+    duration DeallocationTimeMin, DeallocationTimeAvg, DeallocationTimeMax;
+    size_t LostAllocationCount, LostAllocationTotalSize;
+    size_t FailedAllocationCount, FailedAllocationTotalSize;
+};
+
+static const uint32_t IMAGE_BYTES_PER_PIXEL = 1;
+
+uint32_t g_FrameIndex = 0;
+
+struct BufferInfo
+{
+    VkBuffer Buffer = VK_NULL_HANDLE;
+    VmaAllocation Allocation = VK_NULL_HANDLE;
+};
+
+static uint32_t MemoryTypeToHeap(uint32_t memoryTypeIndex)
+{
+    const VkPhysicalDeviceMemoryProperties* props;
+    vmaGetMemoryProperties(g_hAllocator, &props);
+    return props->memoryTypes[memoryTypeIndex].heapIndex;
+}
+
+static uint32_t GetAllocationStrategyCount()
+{
+    uint32_t strategyCount = 0;
+    switch(ConfigType)
+    {
+    case CONFIG_TYPE_MINIMUM: strategyCount = 1; break;
+    case CONFIG_TYPE_SMALL:   strategyCount = 1; break;
+    case CONFIG_TYPE_AVERAGE: strategyCount = 2; break;
+    case CONFIG_TYPE_LARGE:   strategyCount = 2; break;
+    case CONFIG_TYPE_MAXIMUM: strategyCount = 3; break;
+    default: assert(0);
+    }
+    return strategyCount;
+}
+
+static const char* GetAllocationStrategyName(VmaAllocationCreateFlags allocStrategy)
+{
+    switch(allocStrategy)
+    {
+    case VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT: return "BEST_FIT"; break;
+    case VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT: return "WORST_FIT"; break;
+    case VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT: return "FIRST_FIT"; break;
+    case 0: return "Default"; break;
+    default: assert(0); return "";   
+    }
+}
+
+static void InitResult(Result& outResult)
+{
+    outResult.TotalTime = duration::zero();
+    outResult.AllocationTimeMin = duration::max();
+    outResult.AllocationTimeAvg = duration::zero();
+    outResult.AllocationTimeMax = duration::min();
+    outResult.DeallocationTimeMin = duration::max();
+    outResult.DeallocationTimeAvg = duration::zero();
+    outResult.DeallocationTimeMax = duration::min();
+    outResult.TotalMemoryAllocated = 0;
+    outResult.FreeRangeSizeAvg = 0;
+    outResult.FreeRangeSizeMax = 0;
+}
+
+class TimeRegisterObj
+{
+public:
+    TimeRegisterObj(duration& min, duration& sum, duration& max) :
+        m_Min(min),
+        m_Sum(sum),
+        m_Max(max),
+        m_TimeBeg(std::chrono::high_resolution_clock::now())
+    {
+    }
+
+    ~TimeRegisterObj()
+    {
+        duration d = std::chrono::high_resolution_clock::now() - m_TimeBeg;
+        m_Sum += d;
+        if(d < m_Min) m_Min = d;
+        if(d > m_Max) m_Max = d;
+    }
+
+private:
+    duration& m_Min;
+    duration& m_Sum;
+    duration& m_Max;
+    time_point m_TimeBeg;
+};
+
+struct PoolTestThreadResult
+{
+    duration AllocationTimeMin, AllocationTimeSum, AllocationTimeMax;
+    duration DeallocationTimeMin, DeallocationTimeSum, DeallocationTimeMax;
+    size_t AllocationCount, DeallocationCount;
+    size_t LostAllocationCount, LostAllocationTotalSize;
+    size_t FailedAllocationCount, FailedAllocationTotalSize;
+};
+
+class AllocationTimeRegisterObj : public TimeRegisterObj
+{
+public:
+    AllocationTimeRegisterObj(Result& result) :
+        TimeRegisterObj(result.AllocationTimeMin, result.AllocationTimeAvg, result.AllocationTimeMax)
+    {
+    }
+};
+
+class DeallocationTimeRegisterObj : public TimeRegisterObj
+{
+public:
+    DeallocationTimeRegisterObj(Result& result) :
+        TimeRegisterObj(result.DeallocationTimeMin, result.DeallocationTimeAvg, result.DeallocationTimeMax)
+    {
+    }
+};
+
+class PoolAllocationTimeRegisterObj : public TimeRegisterObj
+{
+public:
+    PoolAllocationTimeRegisterObj(PoolTestThreadResult& result) :
+        TimeRegisterObj(result.AllocationTimeMin, result.AllocationTimeSum, result.AllocationTimeMax)
+    {
+    }
+};
+
+class PoolDeallocationTimeRegisterObj : public TimeRegisterObj
+{
+public:
+    PoolDeallocationTimeRegisterObj(PoolTestThreadResult& result) :
+        TimeRegisterObj(result.DeallocationTimeMin, result.DeallocationTimeSum, result.DeallocationTimeMax)
+    {
+    }
+};
+
+static void CurrentTimeToStr(std::string& out)
+{
+    time_t rawTime; time(&rawTime);
+    struct tm timeInfo; localtime_s(&timeInfo, &rawTime);
+    char timeStr[128];
+    strftime(timeStr, _countof(timeStr), "%c", &timeInfo);
+    out = timeStr;
+}
+
+VkResult MainTest(Result& outResult, const Config& config)
+{
+    assert(config.ThreadCount > 0);
+
+    InitResult(outResult);
+
+    RandomNumberGenerator mainRand{config.RandSeed};
+
+    time_point timeBeg = std::chrono::high_resolution_clock::now();
+
+    std::atomic<size_t> allocationCount = 0;
+    VkResult res = VK_SUCCESS;
+
+    uint32_t memUsageProbabilitySum =
+        config.MemUsageProbability[0] + config.MemUsageProbability[1] +
+        config.MemUsageProbability[2] + config.MemUsageProbability[3];
+    assert(memUsageProbabilitySum > 0);
+
+    uint32_t allocationSizeProbabilitySum = std::accumulate(
+        config.AllocationSizes.begin(),
+        config.AllocationSizes.end(),
+        0u,
+        [](uint32_t sum, const AllocationSize& allocSize) {
+            return sum + allocSize.Probability;
+        });
+
+    struct Allocation
+    {
+        VkBuffer Buffer;
+        VkImage Image;
+        VmaAllocation Alloc;
+    };
+
+    std::vector<Allocation> commonAllocations;
+    std::mutex commonAllocationsMutex;
+
+    auto Allocate = [&](
+        VkDeviceSize bufferSize,
+        const VkExtent2D imageExtent,
+        RandomNumberGenerator& localRand,
+        VkDeviceSize& totalAllocatedBytes,
+        std::vector<Allocation>& allocations) -> VkResult
+    {
+        assert((bufferSize == 0) != (imageExtent.width == 0 && imageExtent.height == 0));
+
+        uint32_t memUsageIndex = 0;
+        uint32_t memUsageRand = localRand.Generate() % memUsageProbabilitySum;
+        while(memUsageRand >= config.MemUsageProbability[memUsageIndex])
+            memUsageRand -= config.MemUsageProbability[memUsageIndex++];
+
+        VmaAllocationCreateInfo memReq = {};
+        memReq.usage = (VmaMemoryUsage)(VMA_MEMORY_USAGE_GPU_ONLY + memUsageIndex);
+        memReq.flags |= config.AllocationStrategy;
+
+        Allocation allocation = {};
+        VmaAllocationInfo allocationInfo;
+
+        // Buffer
+        if(bufferSize > 0)
+        {
+            assert(imageExtent.width == 0);
+            VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+            bufferInfo.size = bufferSize;
+            bufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
+
+            {
+                AllocationTimeRegisterObj timeRegisterObj{outResult};
+                res = vmaCreateBuffer(g_hAllocator, &bufferInfo, &memReq, &allocation.Buffer, &allocation.Alloc, &allocationInfo);
+            }
+        }
+        // Image
+        else
+        {
+            VkImageCreateInfo imageInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
+            imageInfo.imageType = VK_IMAGE_TYPE_2D;
+            imageInfo.extent.width = imageExtent.width;
+            imageInfo.extent.height = imageExtent.height;
+            imageInfo.extent.depth = 1;
+            imageInfo.mipLevels = 1;
+            imageInfo.arrayLayers = 1;
+            imageInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
+            imageInfo.tiling = memReq.usage == VMA_MEMORY_USAGE_GPU_ONLY ?
+                VK_IMAGE_TILING_OPTIMAL :
+                VK_IMAGE_TILING_LINEAR;
+            imageInfo.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
+            switch(memReq.usage)
+            {
+            case VMA_MEMORY_USAGE_GPU_ONLY:
+                switch(localRand.Generate() % 3)
+                {
+                case 0:
+                    imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
+                    break;
+                case 1:
+                    imageInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
+                    break;
+                case 2:
+                    imageInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
+                    break;
+                }
+                break;
+            case VMA_MEMORY_USAGE_CPU_ONLY:
+            case VMA_MEMORY_USAGE_CPU_TO_GPU:
+                imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
+                break;
+            case VMA_MEMORY_USAGE_GPU_TO_CPU:
+                imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+                break;
+            }
+            imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
+            imageInfo.flags = 0;
+
+            {
+                AllocationTimeRegisterObj timeRegisterObj{outResult};
+                res = vmaCreateImage(g_hAllocator, &imageInfo, &memReq, &allocation.Image, &allocation.Alloc, &allocationInfo);
+            }
+        }
+
+        if(res == VK_SUCCESS)
+        {
+            ++allocationCount;
+            totalAllocatedBytes += allocationInfo.size;
+            bool useCommonAllocations = localRand.Generate() % 100 < config.ThreadsUsingCommonAllocationsProbabilityPercent;
+            if(useCommonAllocations)
+            {
+                std::unique_lock<std::mutex> lock(commonAllocationsMutex);
+                commonAllocations.push_back(allocation);
+            }
+            else
+                allocations.push_back(allocation);
+        }
+        else
+        {
+            TEST(0);
+        }
+        return res;
+    };
+
+    auto GetNextAllocationSize = [&](
+        VkDeviceSize& outBufSize,
+        VkExtent2D& outImageSize,
+        RandomNumberGenerator& localRand)
+    {
+        outBufSize = 0;
+        outImageSize = {0, 0};
+
+        uint32_t allocSizeIndex = 0;
+        uint32_t r = localRand.Generate() % allocationSizeProbabilitySum;
+        while(r >= config.AllocationSizes[allocSizeIndex].Probability)
+            r -= config.AllocationSizes[allocSizeIndex++].Probability;
+
+        const AllocationSize& allocSize = config.AllocationSizes[allocSizeIndex];
+        if(allocSize.BufferSizeMax > 0)
+        {
+            assert(allocSize.ImageSizeMax == 0);
+            if(allocSize.BufferSizeMax == allocSize.BufferSizeMin)
+                outBufSize = allocSize.BufferSizeMin;
+            else
+            {
+                outBufSize = allocSize.BufferSizeMin + localRand.Generate() % (allocSize.BufferSizeMax - allocSize.BufferSizeMin);
+                outBufSize = outBufSize / 16 * 16;
+            }
+        }
+        else
+        {
+            if(allocSize.ImageSizeMax == allocSize.ImageSizeMin)
+                outImageSize.width = outImageSize.height = allocSize.ImageSizeMax;
+            else
+            {
+                outImageSize.width  = allocSize.ImageSizeMin + localRand.Generate() % (allocSize.ImageSizeMax - allocSize.ImageSizeMin);
+                outImageSize.height = allocSize.ImageSizeMin + localRand.Generate() % (allocSize.ImageSizeMax - allocSize.ImageSizeMin);
+            }
+        }
+    };
+
+    std::atomic<uint32_t> numThreadsReachedMaxAllocations = 0;
+    HANDLE threadsFinishEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+    auto ThreadProc = [&](uint32_t randSeed) -> void
+    {
+        RandomNumberGenerator threadRand(randSeed);
+        VkDeviceSize threadTotalAllocatedBytes = 0;
+        std::vector<Allocation> threadAllocations;
+        VkDeviceSize threadBeginBytesToAllocate = config.BeginBytesToAllocate / config.ThreadCount;
+        VkDeviceSize threadMaxBytesToAllocate = config.MaxBytesToAllocate / config.ThreadCount;
+        uint32_t threadAdditionalOperationCount = config.AdditionalOperationCount / config.ThreadCount;
+
+        // BEGIN ALLOCATIONS
+        for(;;)
+        {
+            VkDeviceSize bufferSize = 0;
+            VkExtent2D imageExtent = {};
+            GetNextAllocationSize(bufferSize, imageExtent, threadRand);
+            if(threadTotalAllocatedBytes + bufferSize + imageExtent.width * imageExtent.height * IMAGE_BYTES_PER_PIXEL <
+                threadBeginBytesToAllocate)
+            {
+                if(Allocate(bufferSize, imageExtent, threadRand, threadTotalAllocatedBytes, threadAllocations) != VK_SUCCESS)
+                    break;
+            }
+            else
+                break;
+        }
+
+        // ADDITIONAL ALLOCATIONS AND FREES
+        for(size_t i = 0; i < threadAdditionalOperationCount; ++i)
+        {
+            VkDeviceSize bufferSize = 0;
+            VkExtent2D imageExtent = {};
+            GetNextAllocationSize(bufferSize, imageExtent, threadRand);
+
+            // true = allocate, false = free
+            bool allocate = threadRand.Generate() % 2 != 0;
+
+            if(allocate)
+            {
+                if(threadTotalAllocatedBytes +
+                    bufferSize +
+                    imageExtent.width * imageExtent.height * IMAGE_BYTES_PER_PIXEL <
+                    threadMaxBytesToAllocate)
+                {
+                    if(Allocate(bufferSize, imageExtent, threadRand, threadTotalAllocatedBytes, threadAllocations) != VK_SUCCESS)
+                        break;
+                }
+            }
+            else
+            {
+                bool useCommonAllocations = threadRand.Generate() % 100 < config.ThreadsUsingCommonAllocationsProbabilityPercent;
+                if(useCommonAllocations)
+                {
+                    std::unique_lock<std::mutex> lock(commonAllocationsMutex);
+                    if(!commonAllocations.empty())
+                    {
+                        size_t indexToFree = threadRand.Generate() % commonAllocations.size();
+                        VmaAllocationInfo allocationInfo;
+                        vmaGetAllocationInfo(g_hAllocator, commonAllocations[indexToFree].Alloc, &allocationInfo);
+                        if(threadTotalAllocatedBytes >= allocationInfo.size)
+                        {
+                            DeallocationTimeRegisterObj timeRegisterObj{outResult};
+                            if(commonAllocations[indexToFree].Buffer != VK_NULL_HANDLE)
+                                vmaDestroyBuffer(g_hAllocator, commonAllocations[indexToFree].Buffer, commonAllocations[indexToFree].Alloc);
+                            else
+                                vmaDestroyImage(g_hAllocator, commonAllocations[indexToFree].Image, commonAllocations[indexToFree].Alloc);
+                            threadTotalAllocatedBytes -= allocationInfo.size;
+                            commonAllocations.erase(commonAllocations.begin() + indexToFree);
+                        }
+                    }
+                }
+                else
+                {
+                    if(!threadAllocations.empty())
+                    {
+                        size_t indexToFree = threadRand.Generate() % threadAllocations.size();
+                        VmaAllocationInfo allocationInfo;
+                        vmaGetAllocationInfo(g_hAllocator, threadAllocations[indexToFree].Alloc, &allocationInfo);
+                        if(threadTotalAllocatedBytes >= allocationInfo.size)
+                        {
+                            DeallocationTimeRegisterObj timeRegisterObj{outResult};
+                            if(threadAllocations[indexToFree].Buffer != VK_NULL_HANDLE)
+                                vmaDestroyBuffer(g_hAllocator, threadAllocations[indexToFree].Buffer, threadAllocations[indexToFree].Alloc);
+                            else
+                                vmaDestroyImage(g_hAllocator, threadAllocations[indexToFree].Image, threadAllocations[indexToFree].Alloc);
+                            threadTotalAllocatedBytes -= allocationInfo.size;
+                            threadAllocations.erase(threadAllocations.begin() + indexToFree);
+                        }
+                    }
+                }
+            }
+        }
+
+        ++numThreadsReachedMaxAllocations;
+
+        WaitForSingleObject(threadsFinishEvent, INFINITE);
+
+        // DEALLOCATION
+        while(!threadAllocations.empty())
+        {
+            size_t indexToFree = 0;
+            switch(config.FreeOrder)
+            {
+            case FREE_ORDER::FORWARD:
+                indexToFree = 0;
+                break;
+            case FREE_ORDER::BACKWARD:
+                indexToFree = threadAllocations.size() - 1;
+                break;
+            case FREE_ORDER::RANDOM:
+                indexToFree = mainRand.Generate() % threadAllocations.size();
+                break;
+            }
+
+            {
+                DeallocationTimeRegisterObj timeRegisterObj{outResult};
+                if(threadAllocations[indexToFree].Buffer != VK_NULL_HANDLE)
+                    vmaDestroyBuffer(g_hAllocator, threadAllocations[indexToFree].Buffer, threadAllocations[indexToFree].Alloc);
+                else
+                    vmaDestroyImage(g_hAllocator, threadAllocations[indexToFree].Image, threadAllocations[indexToFree].Alloc);
+            }
+            threadAllocations.erase(threadAllocations.begin() + indexToFree);
+        }
+    };
+
+    uint32_t threadRandSeed = mainRand.Generate();
+    std::vector<std::thread> bkgThreads;
+    for(size_t i = 0; i < config.ThreadCount; ++i)
+    {
+        bkgThreads.emplace_back(std::bind(ThreadProc, threadRandSeed + (uint32_t)i));
+    }
+    
+    // Wait for threads reached max allocations
+    while(numThreadsReachedMaxAllocations < config.ThreadCount)
+        Sleep(0);
+
+    // CALCULATE MEMORY STATISTICS ON FINAL USAGE
+    VmaStats vmaStats = {};
+    vmaCalculateStats(g_hAllocator, &vmaStats);
+    outResult.TotalMemoryAllocated = vmaStats.total.usedBytes + vmaStats.total.unusedBytes;
+    outResult.FreeRangeSizeMax = vmaStats.total.unusedRangeSizeMax;
+    outResult.FreeRangeSizeAvg = vmaStats.total.unusedRangeSizeAvg;
+
+    // Signal threads to deallocate
+    SetEvent(threadsFinishEvent);
+
+    // Wait for threads finished
+    for(size_t i = 0; i < bkgThreads.size(); ++i)
+        bkgThreads[i].join();
+    bkgThreads.clear();
+
+    CloseHandle(threadsFinishEvent);
+
+    // Deallocate remaining common resources
+    while(!commonAllocations.empty())
+    {
+        size_t indexToFree = 0;
+        switch(config.FreeOrder)
+        {
+        case FREE_ORDER::FORWARD:
+            indexToFree = 0;
+            break;
+        case FREE_ORDER::BACKWARD:
+            indexToFree = commonAllocations.size() - 1;
+            break;
+        case FREE_ORDER::RANDOM:
+            indexToFree = mainRand.Generate() % commonAllocations.size();
+            break;
+        }
+
+        {
+            DeallocationTimeRegisterObj timeRegisterObj{outResult};
+            if(commonAllocations[indexToFree].Buffer != VK_NULL_HANDLE)
+                vmaDestroyBuffer(g_hAllocator, commonAllocations[indexToFree].Buffer, commonAllocations[indexToFree].Alloc);
+            else
+                vmaDestroyImage(g_hAllocator, commonAllocations[indexToFree].Image, commonAllocations[indexToFree].Alloc);
+        }
+        commonAllocations.erase(commonAllocations.begin() + indexToFree);
+    }
+
+    if(allocationCount)
+    {
+        outResult.AllocationTimeAvg /= allocationCount;
+        outResult.DeallocationTimeAvg /= allocationCount;
+    }
+
+    outResult.TotalTime = std::chrono::high_resolution_clock::now() - timeBeg;
+
+    return res;
+}
+
+void SaveAllocatorStatsToFile(const wchar_t* filePath)
+{
+    wprintf(L"Saving JSON dump to file \"%s\"\n", filePath);
+    char* stats;
+    vmaBuildStatsString(g_hAllocator, &stats, VK_TRUE);
+    SaveFile(filePath, stats, strlen(stats));
+    vmaFreeStatsString(g_hAllocator, stats);
+}
+
+struct AllocInfo
+{
+    VmaAllocation m_Allocation = VK_NULL_HANDLE;
+    VkBuffer m_Buffer = VK_NULL_HANDLE;
+    VkImage m_Image = VK_NULL_HANDLE;
+    VkImageLayout m_ImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+    uint32_t m_StartValue = 0;
+    union
+    {
+        VkBufferCreateInfo m_BufferInfo;
+        VkImageCreateInfo m_ImageInfo;
+    };
+
+    // After defragmentation.
+    VkBuffer m_NewBuffer = VK_NULL_HANDLE;
+    VkImage m_NewImage = VK_NULL_HANDLE;
+
+    void CreateBuffer(
+        const VkBufferCreateInfo& bufCreateInfo,
+        const VmaAllocationCreateInfo& allocCreateInfo);
+    void CreateImage(
+        const VkImageCreateInfo& imageCreateInfo,
+        const VmaAllocationCreateInfo& allocCreateInfo,
+        VkImageLayout layout);
+    void Destroy();
+};
+
+void AllocInfo::CreateBuffer(
+    const VkBufferCreateInfo& bufCreateInfo,
+    const VmaAllocationCreateInfo& allocCreateInfo)
+{
+    m_BufferInfo = bufCreateInfo;
+    VkResult res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo, &m_Buffer, &m_Allocation, nullptr);
+    TEST(res == VK_SUCCESS);
+}
+void AllocInfo::CreateImage(
+    const VkImageCreateInfo& imageCreateInfo,
+    const VmaAllocationCreateInfo& allocCreateInfo,
+    VkImageLayout layout)
+{
+    m_ImageInfo = imageCreateInfo;
+    m_ImageLayout = layout;
+    VkResult res = vmaCreateImage(g_hAllocator, &imageCreateInfo, &allocCreateInfo, &m_Image, &m_Allocation, nullptr);
+    TEST(res == VK_SUCCESS);
+}
+
+void AllocInfo::Destroy()
+{
+    if(m_Image)
+    {
+        assert(!m_Buffer);
+        vkDestroyImage(g_hDevice, m_Image, g_Allocs);
+        m_Image = VK_NULL_HANDLE;
+    }
+    if(m_Buffer)
+    {
+        assert(!m_Image);
+        vkDestroyBuffer(g_hDevice, m_Buffer, g_Allocs);
+        m_Buffer = VK_NULL_HANDLE;
+    }
+    if(m_Allocation)
+    {
+        vmaFreeMemory(g_hAllocator, m_Allocation);
+        m_Allocation = VK_NULL_HANDLE;
+    }
+}
+
+class StagingBufferCollection
+{
+public:
+    StagingBufferCollection() { }
+    ~StagingBufferCollection();
+    // Returns false if maximum total size of buffers would be exceeded.
+    bool AcquireBuffer(VkDeviceSize size, VkBuffer& outBuffer, void*& outMappedPtr);
+    void ReleaseAllBuffers();
+
+private:
+    static const VkDeviceSize MAX_TOTAL_SIZE = 256ull * 1024 * 1024;
+    struct BufInfo
+    {
+        VmaAllocation Allocation = VK_NULL_HANDLE;
+        VkBuffer Buffer = VK_NULL_HANDLE;
+        VkDeviceSize Size = VK_WHOLE_SIZE;
+        void* MappedPtr = nullptr;
+        bool Used = false;
+    };
+    std::vector<BufInfo> m_Bufs;
+    // Including both used and unused.
+    VkDeviceSize m_TotalSize = 0;
+};
+
+StagingBufferCollection::~StagingBufferCollection()
+{
+    for(size_t i = m_Bufs.size(); i--; )
+    {
+        vmaDestroyBuffer(g_hAllocator, m_Bufs[i].Buffer, m_Bufs[i].Allocation);
+    }
+}
+
+bool StagingBufferCollection::AcquireBuffer(VkDeviceSize size, VkBuffer& outBuffer, void*& outMappedPtr)
+{
+    assert(size <= MAX_TOTAL_SIZE);
+
+    // Try to find existing unused buffer with best size.
+    size_t bestIndex = SIZE_MAX;
+    for(size_t i = 0, count = m_Bufs.size(); i < count; ++i)
+    {
+        BufInfo& currBufInfo = m_Bufs[i];
+        if(!currBufInfo.Used && currBufInfo.Size >= size &&
+            (bestIndex == SIZE_MAX || currBufInfo.Size < m_Bufs[bestIndex].Size))
+        {
+            bestIndex = i;
+        }
+    }
+
+    if(bestIndex != SIZE_MAX)
+    {
+        m_Bufs[bestIndex].Used = true;
+        outBuffer = m_Bufs[bestIndex].Buffer;
+        outMappedPtr = m_Bufs[bestIndex].MappedPtr;
+        return true;
+    }
+    
+    // Allocate new buffer with requested size.
+    if(m_TotalSize + size <= MAX_TOTAL_SIZE)
+    {
+        BufInfo bufInfo;
+        bufInfo.Size = size;
+        bufInfo.Used = true;
+
+        VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+        bufCreateInfo.size = size;
+        bufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+
+        VmaAllocationCreateInfo allocCreateInfo = {};
+        allocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
+        allocCreateInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
+
+        VmaAllocationInfo allocInfo;
+        VkResult res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo, &bufInfo.Buffer, &bufInfo.Allocation, &allocInfo);
+        bufInfo.MappedPtr = allocInfo.pMappedData;
+        TEST(res == VK_SUCCESS && bufInfo.MappedPtr);
+
+        outBuffer = bufInfo.Buffer;
+        outMappedPtr = bufInfo.MappedPtr;
+
+        m_Bufs.push_back(std::move(bufInfo));
+
+        m_TotalSize += size;
+
+        return true;
+    }
+
+    // There are some unused but smaller buffers: Free them and try again.
+    bool hasUnused = false;
+    for(size_t i = 0, count = m_Bufs.size(); i < count; ++i)
+    {
+        if(!m_Bufs[i].Used)
+        {
+            hasUnused = true;
+            break;
+        }
+    }
+    if(hasUnused)
+    {
+        for(size_t i = m_Bufs.size(); i--; )
+        {
+            if(!m_Bufs[i].Used)
+            {
+                m_TotalSize -= m_Bufs[i].Size;
+                vmaDestroyBuffer(g_hAllocator, m_Bufs[i].Buffer, m_Bufs[i].Allocation);
+                m_Bufs.erase(m_Bufs.begin() + i);
+            }
+        }
+
+        return AcquireBuffer(size, outBuffer, outMappedPtr);
+   }
+
+    return false;
+}
+
+void StagingBufferCollection::ReleaseAllBuffers()
+{
+    for(size_t i = 0, count = m_Bufs.size(); i < count; ++i)
+    {
+        m_Bufs[i].Used = false;
+    }
+}
+
+static void UploadGpuData(const AllocInfo* allocInfo, size_t allocInfoCount)
+{
+    StagingBufferCollection stagingBufs;
+
+    bool cmdBufferStarted = false;
+    for(size_t allocInfoIndex = 0; allocInfoIndex < allocInfoCount; ++allocInfoIndex)
+    {
+        const AllocInfo& currAllocInfo = allocInfo[allocInfoIndex];
+        if(currAllocInfo.m_Buffer)
+        {
+            const VkDeviceSize size = currAllocInfo.m_BufferInfo.size;
+
+            VkBuffer stagingBuf = VK_NULL_HANDLE;
+            void* stagingBufMappedPtr = nullptr;
+            if(!stagingBufs.AcquireBuffer(size, stagingBuf, stagingBufMappedPtr))
+            {
+                TEST(cmdBufferStarted);
+                EndSingleTimeCommands();
+                stagingBufs.ReleaseAllBuffers();
+                cmdBufferStarted = false;
+
+                bool ok = stagingBufs.AcquireBuffer(size, stagingBuf, stagingBufMappedPtr);
+                TEST(ok);
+            }
+
+            // Fill staging buffer.
+            {
+                assert(size % sizeof(uint32_t) == 0);
+                uint32_t* stagingValPtr = (uint32_t*)stagingBufMappedPtr;
+                uint32_t val = currAllocInfo.m_StartValue;
+                for(size_t i = 0; i < size / sizeof(uint32_t); ++i)
+                {
+                    *stagingValPtr = val;
+                    ++stagingValPtr;
+                    ++val;
+                }
+            }
+
+            // Issue copy command from staging buffer to destination buffer.
+            if(!cmdBufferStarted)
+            {
+                cmdBufferStarted = true;
+                BeginSingleTimeCommands();
+            }
+
+            VkBufferCopy copy = {};
+            copy.srcOffset = 0;
+            copy.dstOffset = 0;
+            copy.size = size;
+            vkCmdCopyBuffer(g_hTemporaryCommandBuffer, stagingBuf, currAllocInfo.m_Buffer, 1, &copy);
+        }
+        else
+        {
+            TEST(currAllocInfo.m_ImageInfo.format == VK_FORMAT_R8G8B8A8_UNORM && "Only RGBA8 images are currently supported.");
+            TEST(currAllocInfo.m_ImageInfo.mipLevels == 1 && "Only single mip images are currently supported.");
+
+            const VkDeviceSize size = (VkDeviceSize)currAllocInfo.m_ImageInfo.extent.width * currAllocInfo.m_ImageInfo.extent.height * sizeof(uint32_t);
+
+            VkBuffer stagingBuf = VK_NULL_HANDLE;
+            void* stagingBufMappedPtr = nullptr;
+            if(!stagingBufs.AcquireBuffer(size, stagingBuf, stagingBufMappedPtr))
+            {
+                TEST(cmdBufferStarted);
+                EndSingleTimeCommands();
+                stagingBufs.ReleaseAllBuffers();
+                cmdBufferStarted = false;
+
+                bool ok = stagingBufs.AcquireBuffer(size, stagingBuf, stagingBufMappedPtr);
+                TEST(ok);
+            }
+
+            // Fill staging buffer.
+            {
+                assert(size % sizeof(uint32_t) == 0);
+                uint32_t *stagingValPtr = (uint32_t *)stagingBufMappedPtr;
+                uint32_t val = currAllocInfo.m_StartValue;
+                for(size_t i = 0; i < size / sizeof(uint32_t); ++i)
+                {
+                    *stagingValPtr = val;
+                    ++stagingValPtr;
+                    ++val;
+                }
+            }
+            
+            // Issue copy command from staging buffer to destination buffer.
+            if(!cmdBufferStarted)
+            {
+                cmdBufferStarted = true;
+                BeginSingleTimeCommands();
+            }
+
+            
+            // Transfer to transfer dst layout
+            VkImageSubresourceRange subresourceRange = {
+                VK_IMAGE_ASPECT_COLOR_BIT,
+                0, VK_REMAINING_MIP_LEVELS,
+                0, VK_REMAINING_ARRAY_LAYERS
+            };
+            
+            VkImageMemoryBarrier barrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER };
+            barrier.srcAccessMask = 0;
+            barrier.dstAccessMask = 0;
+            barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+            barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+            barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+            barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+            barrier.image = currAllocInfo.m_Image;
+            barrier.subresourceRange = subresourceRange;
+
+            vkCmdPipelineBarrier(g_hTemporaryCommandBuffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0,
+                0, nullptr,
+                0, nullptr,
+                1, &barrier);
+
+            // Copy image date
+            VkBufferImageCopy copy = {};
+            copy.bufferOffset = 0;
+            copy.bufferRowLength = 0;
+            copy.bufferImageHeight = 0;
+            copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+            copy.imageSubresource.layerCount = 1;
+            copy.imageExtent = currAllocInfo.m_ImageInfo.extent;
+
+            vkCmdCopyBufferToImage(g_hTemporaryCommandBuffer, stagingBuf, currAllocInfo.m_Image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &copy);
+
+            // Transfer to desired layout
+            barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+            barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
+            barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+            barrier.newLayout = currAllocInfo.m_ImageLayout;
+
+            vkCmdPipelineBarrier(g_hTemporaryCommandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0,
+                0, nullptr,
+                0, nullptr,
+                1, &barrier);
+        }
+    }
+
+    if(cmdBufferStarted)
+    {
+        EndSingleTimeCommands();
+        stagingBufs.ReleaseAllBuffers();
+    }
+}
+
+static void ValidateGpuData(const AllocInfo* allocInfo, size_t allocInfoCount)
+{
+    StagingBufferCollection stagingBufs;
+
+    bool cmdBufferStarted = false;
+    size_t validateAllocIndexOffset = 0;
+    std::vector<void*> validateStagingBuffers;
+    for(size_t allocInfoIndex = 0; allocInfoIndex < allocInfoCount; ++allocInfoIndex)
+    {
+        const AllocInfo& currAllocInfo = allocInfo[allocInfoIndex];
+        if(currAllocInfo.m_Buffer)
+        {
+            const VkDeviceSize size = currAllocInfo.m_BufferInfo.size;
+
+            VkBuffer stagingBuf = VK_NULL_HANDLE;
+            void* stagingBufMappedPtr = nullptr;
+            if(!stagingBufs.AcquireBuffer(size, stagingBuf, stagingBufMappedPtr))
+            {
+                TEST(cmdBufferStarted);
+                EndSingleTimeCommands();
+                cmdBufferStarted = false;
+
+                for(size_t validateIndex = 0;
+                    validateIndex < validateStagingBuffers.size();
+                    ++validateIndex)
+                {
+                    const size_t validateAllocIndex = validateIndex + validateAllocIndexOffset;
+                    const VkDeviceSize validateSize = allocInfo[validateAllocIndex].m_BufferInfo.size;
+                    TEST(validateSize % sizeof(uint32_t) == 0);
+                    const uint32_t* stagingValPtr = (const uint32_t*)validateStagingBuffers[validateIndex];
+                    uint32_t val = allocInfo[validateAllocIndex].m_StartValue;
+                    bool valid = true;
+                    for(size_t i = 0; i < validateSize / sizeof(uint32_t); ++i)
+                    {
+                        if(*stagingValPtr != val)
+                        {
+                            valid = false;
+                            break;
+                        }
+                        ++stagingValPtr;
+                        ++val;
+                    }
+                    TEST(valid);
+                }
+
+                stagingBufs.ReleaseAllBuffers();
+
+                validateAllocIndexOffset = allocInfoIndex;
+                validateStagingBuffers.clear();
+
+                bool ok = stagingBufs.AcquireBuffer(size, stagingBuf, stagingBufMappedPtr);
+                TEST(ok);
+            }
+
+            // Issue copy command from staging buffer to destination buffer.
+            if(!cmdBufferStarted)
+            {
+                cmdBufferStarted = true;
+                BeginSingleTimeCommands();
+            }
+
+            VkBufferCopy copy = {};
+            copy.srcOffset = 0;
+            copy.dstOffset = 0;
+            copy.size = size;
+            vkCmdCopyBuffer(g_hTemporaryCommandBuffer, currAllocInfo.m_Buffer, stagingBuf, 1, &copy);
+
+            // Sava mapped pointer for later validation.
+            validateStagingBuffers.push_back(stagingBufMappedPtr);
+        }
+        else
+        {
+            TEST(0 && "Images not currently supported.");
+        }
+    }
+
+    if(cmdBufferStarted)
+    {
+        EndSingleTimeCommands();
+
+        for(size_t validateIndex = 0;
+            validateIndex < validateStagingBuffers.size();
+            ++validateIndex)
+        {
+            const size_t validateAllocIndex = validateIndex + validateAllocIndexOffset;
+            const VkDeviceSize validateSize = allocInfo[validateAllocIndex].m_BufferInfo.size;
+            TEST(validateSize % sizeof(uint32_t) == 0);
+            const uint32_t* stagingValPtr = (const uint32_t*)validateStagingBuffers[validateIndex];
+            uint32_t val = allocInfo[validateAllocIndex].m_StartValue;
+            bool valid = true;
+            for(size_t i = 0; i < validateSize / sizeof(uint32_t); ++i)
+            {
+                if(*stagingValPtr != val)
+                {
+                    valid = false;
+                    break;
+                }
+                ++stagingValPtr;
+                ++val;
+            }
+            TEST(valid);
+        }
+
+        stagingBufs.ReleaseAllBuffers();
+    }
+}
+
+static void GetMemReq(VmaAllocationCreateInfo& outMemReq)
+{
+    outMemReq = {};
+    outMemReq.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
+    //outMemReq.flags = VMA_ALLOCATION_CREATE_PERSISTENT_MAP_BIT;
+}
+
+static void CreateBuffer(
+    VmaPool pool,
+    const VkBufferCreateInfo& bufCreateInfo,
+    bool persistentlyMapped,
+    AllocInfo& outAllocInfo)
+{
+    outAllocInfo = {};
+    outAllocInfo.m_BufferInfo = bufCreateInfo;
+    
+    VmaAllocationCreateInfo allocCreateInfo = {};
+    allocCreateInfo.pool = pool;
+    if(persistentlyMapped)
+        allocCreateInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
+
+    VmaAllocationInfo vmaAllocInfo = {};
+    ERR_GUARD_VULKAN( vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo, &outAllocInfo.m_Buffer, &outAllocInfo.m_Allocation, &vmaAllocInfo) );
+
+    // Setup StartValue and fill.
+    {
+        outAllocInfo.m_StartValue = (uint32_t)rand();
+        uint32_t* data = (uint32_t*)vmaAllocInfo.pMappedData;
+        TEST((data != nullptr) == persistentlyMapped);
+        if(!persistentlyMapped)
+        {
+            ERR_GUARD_VULKAN( vmaMapMemory(g_hAllocator, outAllocInfo.m_Allocation, (void**)&data) );
+        }
+
+        uint32_t value = outAllocInfo.m_StartValue;
+        TEST(bufCreateInfo.size % 4 == 0);
+        for(size_t i = 0; i < bufCreateInfo.size / sizeof(uint32_t); ++i)
+            data[i] = value++;
+
+        if(!persistentlyMapped)
+            vmaUnmapMemory(g_hAllocator, outAllocInfo.m_Allocation);
+    }
+}
+
+static void CreateAllocation(AllocInfo& outAllocation)
+{
+    outAllocation.m_Allocation = nullptr;
+    outAllocation.m_Buffer = nullptr;
+    outAllocation.m_Image = nullptr;
+    outAllocation.m_StartValue = (uint32_t)rand();
+
+    VmaAllocationCreateInfo vmaMemReq;
+    GetMemReq(vmaMemReq);
+
+    VmaAllocationInfo allocInfo;
+
+    const bool isBuffer = true;//(rand() & 0x1) != 0;
+    const bool isLarge = (rand() % 16) == 0;
+    if(isBuffer)
+    {
+        const uint32_t bufferSize = isLarge ?
+            (rand() % 10 + 1) * (1024 * 1024) : // 1 MB ... 10 MB
+            (rand() % 1024 + 1) * 1024; // 1 KB ... 1 MB
+
+        VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+        bufferInfo.size = bufferSize;
+        bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+
+        VkResult res = vmaCreateBuffer(g_hAllocator, &bufferInfo, &vmaMemReq, &outAllocation.m_Buffer, &outAllocation.m_Allocation, &allocInfo);
+        outAllocation.m_BufferInfo = bufferInfo;
+        TEST(res == VK_SUCCESS);
+    }
+    else
+    {
+        const uint32_t imageSizeX = isLarge ?
+            1024 + rand() % (4096 - 1024) : // 1024 ... 4096
+            rand() % 1024 + 1; // 1 ... 1024
+        const uint32_t imageSizeY = isLarge ?
+            1024 + rand() % (4096 - 1024) : // 1024 ... 4096
+            rand() % 1024 + 1; // 1 ... 1024
+
+        VkImageCreateInfo imageInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
+        imageInfo.imageType = VK_IMAGE_TYPE_2D;
+        imageInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
+        imageInfo.extent.width = imageSizeX;
+        imageInfo.extent.height = imageSizeY;
+        imageInfo.extent.depth = 1;
+        imageInfo.mipLevels = 1;
+        imageInfo.arrayLayers = 1;
+        imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
+        imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
+        imageInfo.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
+        imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
+
+        VkResult res = vmaCreateImage(g_hAllocator, &imageInfo, &vmaMemReq, &outAllocation.m_Image, &outAllocation.m_Allocation, &allocInfo);
+        outAllocation.m_ImageInfo = imageInfo;
+        TEST(res == VK_SUCCESS);
+    }
+
+    uint32_t* data = (uint32_t*)allocInfo.pMappedData;
+    if(allocInfo.pMappedData == nullptr)
+    {
+        VkResult res = vmaMapMemory(g_hAllocator, outAllocation.m_Allocation, (void**)&data);
+        TEST(res == VK_SUCCESS);
+    }
+
+    uint32_t value = outAllocation.m_StartValue;
+    TEST(allocInfo.size % 4 == 0);
+    for(size_t i = 0; i < allocInfo.size / sizeof(uint32_t); ++i)
+        data[i] = value++;
+
+    if(allocInfo.pMappedData == nullptr)
+        vmaUnmapMemory(g_hAllocator, outAllocation.m_Allocation);
+}
+
+static void DestroyAllocation(const AllocInfo& allocation)
+{
+    if(allocation.m_Buffer)
+        vmaDestroyBuffer(g_hAllocator, allocation.m_Buffer, allocation.m_Allocation);
+    else
+        vmaDestroyImage(g_hAllocator, allocation.m_Image, allocation.m_Allocation);
+}
+
+static void DestroyAllAllocations(std::vector<AllocInfo>& allocations)
+{
+    for(size_t i = allocations.size(); i--; )
+        DestroyAllocation(allocations[i]);
+    allocations.clear();
+}
+
+static void ValidateAllocationData(const AllocInfo& allocation)
+{
+    VmaAllocationInfo allocInfo;
+    vmaGetAllocationInfo(g_hAllocator, allocation.m_Allocation, &allocInfo);
+
+    uint32_t* data = (uint32_t*)allocInfo.pMappedData;
+    if(allocInfo.pMappedData == nullptr)
+    {
+        VkResult res = vmaMapMemory(g_hAllocator, allocation.m_Allocation, (void**)&data);
+        TEST(res == VK_SUCCESS);
+    }
+
+    uint32_t value = allocation.m_StartValue;
+    bool ok = true;
+    size_t i;
+    TEST(allocInfo.size % 4 == 0);
+    for(i = 0; i < allocInfo.size / sizeof(uint32_t); ++i)
+    {
+        if(data[i] != value++)
+        {
+            ok = false;
+            break;
+        }
+    }
+    TEST(ok);
+
+    if(allocInfo.pMappedData == nullptr)
+        vmaUnmapMemory(g_hAllocator, allocation.m_Allocation);
+}
+
+static void RecreateAllocationResource(AllocInfo& allocation)
+{
+    VmaAllocationInfo allocInfo;
+    vmaGetAllocationInfo(g_hAllocator, allocation.m_Allocation, &allocInfo);
+
+    if(allocation.m_Buffer)
+    {
+        vkDestroyBuffer(g_hDevice, allocation.m_Buffer, g_Allocs);
+
+        VkResult res = vkCreateBuffer(g_hDevice, &allocation.m_BufferInfo, g_Allocs, &allocation.m_Buffer);
+        TEST(res == VK_SUCCESS);
+
+        // Just to silence validation layer warnings.
+        VkMemoryRequirements vkMemReq;
+        vkGetBufferMemoryRequirements(g_hDevice, allocation.m_Buffer, &vkMemReq);
+        TEST(vkMemReq.size >= allocation.m_BufferInfo.size);
+
+        res = vmaBindBufferMemory(g_hAllocator, allocation.m_Allocation, allocation.m_Buffer);
+        TEST(res == VK_SUCCESS);
+    }
+    else
+    {
+        vkDestroyImage(g_hDevice, allocation.m_Image, g_Allocs);
+
+        VkResult res = vkCreateImage(g_hDevice, &allocation.m_ImageInfo, g_Allocs, &allocation.m_Image);
+        TEST(res == VK_SUCCESS);
+
+        // Just to silence validation layer warnings.
+        VkMemoryRequirements vkMemReq;
+        vkGetImageMemoryRequirements(g_hDevice, allocation.m_Image, &vkMemReq);
+
+        res = vmaBindImageMemory(g_hAllocator, allocation.m_Allocation, allocation.m_Image);
+        TEST(res == VK_SUCCESS);
+    }
+}
+
+static void Defragment(AllocInfo* allocs, size_t allocCount,
+    const VmaDefragmentationInfo* defragmentationInfo = nullptr,
+    VmaDefragmentationStats* defragmentationStats = nullptr)
+{
+    std::vector<VmaAllocation> vmaAllocs(allocCount);
+    for(size_t i = 0; i < allocCount; ++i)
+        vmaAllocs[i] = allocs[i].m_Allocation;
+
+    std::vector<VkBool32> allocChanged(allocCount);
+    
+    ERR_GUARD_VULKAN( vmaDefragment(g_hAllocator, vmaAllocs.data(), allocCount, allocChanged.data(),
+        defragmentationInfo, defragmentationStats) );
+
+    for(size_t i = 0; i < allocCount; ++i)
+    {
+        if(allocChanged[i])
+        {
+            RecreateAllocationResource(allocs[i]);
+        }
+    }
+}
+
+static void ValidateAllocationsData(const AllocInfo* allocs, size_t allocCount)
+{
+    std::for_each(allocs, allocs + allocCount, [](const AllocInfo& allocInfo) {
+        ValidateAllocationData(allocInfo);
+    });
+}
+
+void TestDefragmentationSimple()
+{
+    wprintf(L"Test defragmentation simple\n");
+
+    RandomNumberGenerator rand(667);
+
+    const VkDeviceSize BUF_SIZE = 0x10000;
+    const VkDeviceSize BLOCK_SIZE = BUF_SIZE * 8;
+    
+    const VkDeviceSize MIN_BUF_SIZE = 32;
+    const VkDeviceSize MAX_BUF_SIZE = BUF_SIZE * 4;
+    auto RandomBufSize = [&]() -> VkDeviceSize {
+        return align_up<VkDeviceSize>(rand.Generate() % (MAX_BUF_SIZE - MIN_BUF_SIZE + 1) + MIN_BUF_SIZE, 32);
+    };
+
+    VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+    bufCreateInfo.size = BUF_SIZE;
+    bufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+
+    VmaAllocationCreateInfo exampleAllocCreateInfo = {};
+    exampleAllocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
+
+    uint32_t memTypeIndex = UINT32_MAX;
+    vmaFindMemoryTypeIndexForBufferInfo(g_hAllocator, &bufCreateInfo, &exampleAllocCreateInfo, &memTypeIndex);
+
+    VmaPoolCreateInfo poolCreateInfo = {};
+    poolCreateInfo.blockSize = BLOCK_SIZE;
+    poolCreateInfo.memoryTypeIndex = memTypeIndex;
+
+    VmaPool pool;
+    ERR_GUARD_VULKAN( vmaCreatePool(g_hAllocator, &poolCreateInfo, &pool) );
+
+    // Defragmentation of empty pool.
+    {
+        VmaDefragmentationInfo2 defragInfo = {};
+        defragInfo.maxCpuBytesToMove = VK_WHOLE_SIZE;
+        defragInfo.maxCpuAllocationsToMove = UINT32_MAX;
+        defragInfo.poolCount = 1;
+        defragInfo.pPools = &pool;
+
+        VmaDefragmentationStats defragStats = {};
+        VmaDefragmentationContext defragCtx = nullptr;
+        VkResult res = vmaDefragmentationBegin(g_hAllocator, &defragInfo, &defragStats, &defragCtx);
+        TEST(res >= VK_SUCCESS);
+        vmaDefragmentationEnd(g_hAllocator, defragCtx);
+        TEST(defragStats.allocationsMoved == 0 && defragStats.bytesFreed == 0 &&
+            defragStats.bytesMoved == 0 && defragStats.deviceMemoryBlocksFreed == 0);
+    }
+
+    std::vector<AllocInfo> allocations;
+
+    // persistentlyMappedOption = 0 - not persistently mapped.
+    // persistentlyMappedOption = 1 - persistently mapped.
+    for(uint32_t persistentlyMappedOption = 0; persistentlyMappedOption < 2; ++persistentlyMappedOption)
+    {
+        wprintf(L"  Persistently mapped option = %u\n", persistentlyMappedOption);
+        const bool persistentlyMapped = persistentlyMappedOption != 0;
+
+        // # Test 1
+        // Buffers of fixed size.
+        // Fill 2 blocks. Remove odd buffers. Defragment everything.
+        // Expected result: at least 1 block freed.
+        {
+            for(size_t i = 0; i < BLOCK_SIZE / BUF_SIZE * 2; ++i)
+            {
+                AllocInfo allocInfo;
+                CreateBuffer(pool, bufCreateInfo, persistentlyMapped, allocInfo);
+                allocations.push_back(allocInfo);
+            }
+
+            for(size_t i = 1; i < allocations.size(); ++i)
+            {
+                DestroyAllocation(allocations[i]);
+                allocations.erase(allocations.begin() + i);
+            }
+
+            VmaDefragmentationStats defragStats;
+            Defragment(allocations.data(), allocations.size(), nullptr, &defragStats);
+            TEST(defragStats.allocationsMoved > 0 && defragStats.bytesMoved > 0);
+            TEST(defragStats.deviceMemoryBlocksFreed >= 1);
+
+            ValidateAllocationsData(allocations.data(), allocations.size());
+
+            DestroyAllAllocations(allocations);
+        }
+
+        // # Test 2
+        // Buffers of fixed size.
+        // Fill 2 blocks. Remove odd buffers. Defragment one buffer at time.
+        // Expected result: Each of 4 interations makes some progress.
+        {
+            for(size_t i = 0; i < BLOCK_SIZE / BUF_SIZE * 2; ++i)
+            {
+                AllocInfo allocInfo;
+                CreateBuffer(pool, bufCreateInfo, persistentlyMapped, allocInfo);
+                allocations.push_back(allocInfo);
+            }
+
+            for(size_t i = 1; i < allocations.size(); ++i)
+            {
+                DestroyAllocation(allocations[i]);
+                allocations.erase(allocations.begin() + i);
+            }
+
+            VmaDefragmentationInfo defragInfo = {};
+            defragInfo.maxAllocationsToMove = 1;
+            defragInfo.maxBytesToMove = BUF_SIZE;
+
+            for(size_t i = 0; i < BLOCK_SIZE / BUF_SIZE / 2; ++i)
+            {
+                VmaDefragmentationStats defragStats;
+                Defragment(allocations.data(), allocations.size(), &defragInfo, &defragStats);
+                TEST(defragStats.allocationsMoved > 0 && defragStats.bytesMoved > 0);
+            }
+
+            ValidateAllocationsData(allocations.data(), allocations.size());
+
+            DestroyAllAllocations(allocations);
+        }
+
+        // # Test 3
+        // Buffers of variable size.
+        // Create a number of buffers. Remove some percent of them.
+        // Defragment while having some percent of them unmovable.
+        // Expected result: Just simple validation.
+        {
+            for(size_t i = 0; i < 100; ++i)
+            {
+                VkBufferCreateInfo localBufCreateInfo = bufCreateInfo;
+                localBufCreateInfo.size = RandomBufSize();
+
+                AllocInfo allocInfo;
+                CreateBuffer(pool, bufCreateInfo, persistentlyMapped, allocInfo);
+                allocations.push_back(allocInfo);
+            }
+
+            const uint32_t percentToDelete = 60;
+            const size_t numberToDelete = allocations.size() * percentToDelete / 100;
+            for(size_t i = 0; i < numberToDelete; ++i)
+            {
+                size_t indexToDelete = rand.Generate() % (uint32_t)allocations.size();
+                DestroyAllocation(allocations[indexToDelete]);
+                allocations.erase(allocations.begin() + indexToDelete);
+            }
+
+            // Non-movable allocations will be at the beginning of allocations array.
+            const uint32_t percentNonMovable = 20;
+            const size_t numberNonMovable = allocations.size() * percentNonMovable / 100;
+            for(size_t i = 0; i < numberNonMovable; ++i)
+            {
+                size_t indexNonMovable = i + rand.Generate() % (uint32_t)(allocations.size() - i);
+                if(indexNonMovable != i)
+                    std::swap(allocations[i], allocations[indexNonMovable]);
+            }
+
+            VmaDefragmentationStats defragStats;
+            Defragment(
+                allocations.data() + numberNonMovable,
+                allocations.size() - numberNonMovable,
+                nullptr, &defragStats);
+
+            ValidateAllocationsData(allocations.data(), allocations.size());
+
+            DestroyAllAllocations(allocations);
+        }
+    }
+
+    /*
+    Allocation that must be move to an overlapping place using memmove().
+    Create 2 buffers, second slightly bigger than the first. Delete first. Then defragment.
+    */
+    if(VMA_DEBUG_MARGIN == 0) // FAST algorithm works only when DEBUG_MARGIN disabled.
+    {
+        AllocInfo allocInfo[2];
+
+        bufCreateInfo.size = BUF_SIZE;
+        CreateBuffer(pool, bufCreateInfo, false, allocInfo[0]);
+        const VkDeviceSize biggerBufSize = BUF_SIZE + BUF_SIZE / 256;
+        bufCreateInfo.size = biggerBufSize;
+        CreateBuffer(pool, bufCreateInfo, false, allocInfo[1]);
+
+        DestroyAllocation(allocInfo[0]);
+
+        VmaDefragmentationStats defragStats;
+        Defragment(&allocInfo[1], 1, nullptr, &defragStats);
+        // If this fails, it means we couldn't do memmove with overlapping regions.
+        TEST(defragStats.allocationsMoved == 1 && defragStats.bytesMoved > 0);
+
+        ValidateAllocationsData(&allocInfo[1], 1);
+        DestroyAllocation(allocInfo[1]);
+    }
+
+    vmaDestroyPool(g_hAllocator, pool);
+}
+
+void TestDefragmentationWholePool()
+{
+    wprintf(L"Test defragmentation whole pool\n");
+
+    RandomNumberGenerator rand(668);
+
+    const VkDeviceSize BUF_SIZE = 0x10000;
+    const VkDeviceSize BLOCK_SIZE = BUF_SIZE * 8;
+    
+    VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+    bufCreateInfo.size = BUF_SIZE;
+    bufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+
+    VmaAllocationCreateInfo exampleAllocCreateInfo = {};
+    exampleAllocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
+
+    uint32_t memTypeIndex = UINT32_MAX;
+    vmaFindMemoryTypeIndexForBufferInfo(g_hAllocator, &bufCreateInfo, &exampleAllocCreateInfo, &memTypeIndex);
+
+    VmaPoolCreateInfo poolCreateInfo = {};
+    poolCreateInfo.blockSize = BLOCK_SIZE;
+    poolCreateInfo.memoryTypeIndex = memTypeIndex;
+
+    VmaDefragmentationStats defragStats[2];
+    for(size_t caseIndex = 0; caseIndex < 2; ++caseIndex)
+    {
+        VmaPool pool;
+        ERR_GUARD_VULKAN( vmaCreatePool(g_hAllocator, &poolCreateInfo, &pool) );
+
+        std::vector<AllocInfo> allocations;
+
+        // Buffers of fixed size.
+        // Fill 2 blocks. Remove odd buffers. Defragment all of them.
+        for(size_t i = 0; i < BLOCK_SIZE / BUF_SIZE * 2; ++i)
+        {
+            AllocInfo allocInfo;
+            CreateBuffer(pool, bufCreateInfo, false, allocInfo);
+            allocations.push_back(allocInfo);
+        }
+
+        for(size_t i = 1; i < allocations.size(); ++i)
+        {
+            DestroyAllocation(allocations[i]);
+            allocations.erase(allocations.begin() + i);
+        }
+
+        VmaDefragmentationInfo2 defragInfo = {};
+        defragInfo.maxCpuAllocationsToMove = UINT32_MAX;
+        defragInfo.maxCpuBytesToMove = VK_WHOLE_SIZE;
+        std::vector<VmaAllocation> allocationsToDefrag;
+        if(caseIndex == 0)
+        {
+            defragInfo.poolCount = 1;
+            defragInfo.pPools = &pool;
+        }
+        else
+        {
+            const size_t allocCount = allocations.size();
+            allocationsToDefrag.resize(allocCount);
+            std::transform(
+                allocations.begin(), allocations.end(),
+                allocationsToDefrag.begin(),
+                [](const AllocInfo& allocInfo) { return allocInfo.m_Allocation; });
+            defragInfo.allocationCount = (uint32_t)allocCount;
+            defragInfo.pAllocations = allocationsToDefrag.data();
+        }
+
+        VmaDefragmentationContext defragCtx = VK_NULL_HANDLE;
+        VkResult res = vmaDefragmentationBegin(g_hAllocator, &defragInfo, &defragStats[caseIndex], &defragCtx);
+        TEST(res >= VK_SUCCESS);
+        vmaDefragmentationEnd(g_hAllocator, defragCtx);
+
+        TEST(defragStats[caseIndex].allocationsMoved > 0 && defragStats[caseIndex].bytesMoved > 0);
+
+        ValidateAllocationsData(allocations.data(), allocations.size());
+
+        DestroyAllAllocations(allocations);
+
+        vmaDestroyPool(g_hAllocator, pool);
+    }
+
+    TEST(defragStats[0].bytesMoved == defragStats[1].bytesMoved);
+    TEST(defragStats[0].allocationsMoved == defragStats[1].allocationsMoved);
+    TEST(defragStats[0].bytesFreed == defragStats[1].bytesFreed);
+    TEST(defragStats[0].deviceMemoryBlocksFreed == defragStats[1].deviceMemoryBlocksFreed);
+}
+
+void TestDefragmentationFull()
+{
+    std::vector<AllocInfo> allocations;
+
+    // Create initial allocations.
+    for(size_t i = 0; i < 400; ++i)
+    {
+        AllocInfo allocation;
+        CreateAllocation(allocation);
+        allocations.push_back(allocation);
+    }
+
+    // Delete random allocations
+    const size_t allocationsToDeletePercent = 80;
+    size_t allocationsToDelete = allocations.size() * allocationsToDeletePercent / 100;
+    for(size_t i = 0; i < allocationsToDelete; ++i)
+    {
+        size_t index = (size_t)rand() % allocations.size();
+        DestroyAllocation(allocations[index]);
+        allocations.erase(allocations.begin() + index);
+    }
+
+    for(size_t i = 0; i < allocations.size(); ++i)
+        ValidateAllocationData(allocations[i]);
+
+    //SaveAllocatorStatsToFile(L"Before.csv");
+
+    {
+        std::vector<VmaAllocation> vmaAllocations(allocations.size());
+        for(size_t i = 0; i < allocations.size(); ++i)
+            vmaAllocations[i] = allocations[i].m_Allocation;
+
+        const size_t nonMovablePercent = 0;
+        size_t nonMovableCount = vmaAllocations.size() * nonMovablePercent / 100;
+        for(size_t i = 0; i < nonMovableCount; ++i)
+        {
+            size_t index = (size_t)rand() % vmaAllocations.size();
+            vmaAllocations.erase(vmaAllocations.begin() + index);
+        }
+
+        const uint32_t defragCount = 1;
+        for(uint32_t defragIndex = 0; defragIndex < defragCount; ++defragIndex)
+        {
+            std::vector<VkBool32> allocationsChanged(vmaAllocations.size());
+
+            VmaDefragmentationInfo defragmentationInfo;
+            defragmentationInfo.maxAllocationsToMove = UINT_MAX;
+            defragmentationInfo.maxBytesToMove = SIZE_MAX;
+
+            wprintf(L"Defragmentation #%u\n", defragIndex);
+
+            time_point begTime = std::chrono::high_resolution_clock::now();
+
+            VmaDefragmentationStats stats;
+            VkResult res = vmaDefragment(g_hAllocator, vmaAllocations.data(), vmaAllocations.size(), allocationsChanged.data(), &defragmentationInfo, &stats);
+            TEST(res >= 0);
+
+            float defragmentDuration = ToFloatSeconds(std::chrono::high_resolution_clock::now() - begTime);
+
+            wprintf(L"Moved allocations %u, bytes %llu\n", stats.allocationsMoved, stats.bytesMoved);
+            wprintf(L"Freed blocks %u, bytes %llu\n", stats.deviceMemoryBlocksFreed, stats.bytesFreed);
+            wprintf(L"Time: %.2f s\n", defragmentDuration);
+
+            for(size_t i = 0; i < vmaAllocations.size(); ++i)
+            {
+                if(allocationsChanged[i])
+                {
+                    RecreateAllocationResource(allocations[i]);
+                }
+            }
+
+            for(size_t i = 0; i < allocations.size(); ++i)
+                ValidateAllocationData(allocations[i]);
+
+            //wchar_t fileName[MAX_PATH];
+            //swprintf(fileName, MAX_PATH, L"After_%02u.csv", defragIndex);
+            //SaveAllocatorStatsToFile(fileName);
+        }
+    }
+
+    // Destroy all remaining allocations.
+    DestroyAllAllocations(allocations);
+}
+
+static void TestDefragmentationGpu()
+{
+    wprintf(L"Test defragmentation GPU\n");
+    g_MemoryAliasingWarningEnabled = false;
+
+    std::vector<AllocInfo> allocations;
+
+    // Create that many allocations to surely fill 3 new blocks of 256 MB.
+    const VkDeviceSize bufSizeMin = 5ull * 1024 * 1024;
+    const VkDeviceSize bufSizeMax = 10ull * 1024 * 1024;
+    const VkDeviceSize totalSize = 3ull * 256 * 1024 * 1024;
+    const size_t bufCount = (size_t)(totalSize / bufSizeMin);
+    const size_t percentToLeave = 30;
+    const size_t percentNonMovable = 3;
+    RandomNumberGenerator rand = { 234522 };
+
+    VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+
+    VmaAllocationCreateInfo allocCreateInfo = {};
+    allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+    allocCreateInfo.flags = 0;
+
+    // Create all intended buffers.
+    for(size_t i = 0; i < bufCount; ++i)
+    {
+        bufCreateInfo.size = align_up(rand.Generate() % (bufSizeMax - bufSizeMin) + bufSizeMin, 32ull);
+
+        if(rand.Generate() % 100 < percentNonMovable)
+        {
+            bufCreateInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
+                VK_BUFFER_USAGE_TRANSFER_DST_BIT |
+                VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+            allocCreateInfo.pUserData = (void*)(uintptr_t)2;
+        }
+        else
+        {
+            // Different usage just to see different color in output from VmaDumpVis.
+            bufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT |
+                VK_BUFFER_USAGE_TRANSFER_DST_BIT |
+                VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+            // And in JSON dump.
+            allocCreateInfo.pUserData = (void*)(uintptr_t)1;
+        }
+
+        AllocInfo alloc;
+        alloc.CreateBuffer(bufCreateInfo, allocCreateInfo);
+        alloc.m_StartValue = rand.Generate();
+        allocations.push_back(alloc);
+    }
+
+    // Destroy some percentage of them.
+    {
+        const size_t buffersToDestroy = round_div<size_t>(bufCount * (100 - percentToLeave), 100);
+        for(size_t i = 0; i < buffersToDestroy; ++i)
+        {
+            const size_t index = rand.Generate() % allocations.size();
+            allocations[index].Destroy();
+            allocations.erase(allocations.begin() + index);
+        }
+    }
+
+    // Fill them with meaningful data.
+    UploadGpuData(allocations.data(), allocations.size());
+
+    wchar_t fileName[MAX_PATH];
+    swprintf_s(fileName, L"GPU_defragmentation_A_before.json");
+    SaveAllocatorStatsToFile(fileName);
+
+    // Defragment using GPU only.
+    {
+        const size_t allocCount = allocations.size();
+
+        std::vector<VmaAllocation> allocationPtrs;
+        std::vector<VkBool32> allocationChanged;
+        std::vector<size_t> allocationOriginalIndex;
+
+        for(size_t i = 0; i < allocCount; ++i)
+        {
+            VmaAllocationInfo allocInfo = {};
+            vmaGetAllocationInfo(g_hAllocator, allocations[i].m_Allocation, &allocInfo);
+            if((uintptr_t)allocInfo.pUserData == 1) // Movable
+            {
+                allocationPtrs.push_back(allocations[i].m_Allocation);
+                allocationChanged.push_back(VK_FALSE);
+                allocationOriginalIndex.push_back(i);
+            }
+        }
+
+        const size_t movableAllocCount = allocationPtrs.size();
+
+        BeginSingleTimeCommands();
+
+        VmaDefragmentationInfo2 defragInfo = {};
+        defragInfo.flags = 0;
+        defragInfo.allocationCount = (uint32_t)movableAllocCount;
+        defragInfo.pAllocations = allocationPtrs.data();
+        defragInfo.pAllocationsChanged = allocationChanged.data();
+        defragInfo.maxGpuBytesToMove = VK_WHOLE_SIZE;
+        defragInfo.maxGpuAllocationsToMove = UINT32_MAX;
+        defragInfo.commandBuffer = g_hTemporaryCommandBuffer;
+
+        VmaDefragmentationStats stats = {};
+        VmaDefragmentationContext ctx = VK_NULL_HANDLE;
+        VkResult res = vmaDefragmentationBegin(g_hAllocator, &defragInfo, &stats, &ctx);
+        TEST(res >= VK_SUCCESS);
+
+        EndSingleTimeCommands();
+
+        vmaDefragmentationEnd(g_hAllocator, ctx);
+
+        for(size_t i = 0; i < movableAllocCount; ++i)
+        {
+            if(allocationChanged[i])
+            {
+                const size_t origAllocIndex = allocationOriginalIndex[i];
+                RecreateAllocationResource(allocations[origAllocIndex]);
+            }
+        }
+
+        // If corruption detection is enabled, GPU defragmentation may not work on
+        // memory types that have this detection active, e.g. on Intel.
+        #if !defined(VMA_DEBUG_DETECT_CORRUPTION) || VMA_DEBUG_DETECT_CORRUPTION == 0
+            TEST(stats.allocationsMoved > 0 && stats.bytesMoved > 0);
+            TEST(stats.deviceMemoryBlocksFreed > 0 && stats.bytesFreed > 0);
+        #endif
+    }
+
+    ValidateGpuData(allocations.data(), allocations.size());
+
+    swprintf_s(fileName, L"GPU_defragmentation_B_after.json");
+    SaveAllocatorStatsToFile(fileName);
+
+    // Destroy all remaining buffers.
+    for(size_t i = allocations.size(); i--; )
+    {
+        allocations[i].Destroy();
+    }
+
+    g_MemoryAliasingWarningEnabled = true;
+}
+
+static void ProcessDefragmentationStepInfo(VmaDefragmentationPassInfo &stepInfo)
+{
+    std::vector<VkImageMemoryBarrier> beginImageBarriers;
+    std::vector<VkImageMemoryBarrier> finalizeImageBarriers;
+
+    VkPipelineStageFlags beginSrcStageMask = 0;
+    VkPipelineStageFlags beginDstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
+
+    VkPipelineStageFlags finalizeSrcStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
+    VkPipelineStageFlags finalizeDstStageMask = 0;
+
+    bool wantsMemoryBarrier = false;
+
+    VkMemoryBarrier beginMemoryBarrier = { VK_STRUCTURE_TYPE_MEMORY_BARRIER };
+    VkMemoryBarrier finalizeMemoryBarrier = { VK_STRUCTURE_TYPE_MEMORY_BARRIER };
+
+    for(uint32_t i = 0; i < stepInfo.moveCount; ++i)
+    {
+        VmaAllocationInfo info;
+        vmaGetAllocationInfo(g_hAllocator, stepInfo.pMoves[i].allocation, &info);
+
+        AllocInfo *allocInfo = (AllocInfo *)info.pUserData;
+
+        if(allocInfo->m_Image)
+        {
+            VkImage newImage;
+
+            const VkResult result = vkCreateImage(g_hDevice, &allocInfo->m_ImageInfo, g_Allocs, &newImage);
+            TEST(result >= VK_SUCCESS);
+
+            vkBindImageMemory(g_hDevice, newImage, stepInfo.pMoves[i].memory, stepInfo.pMoves[i].offset);
+            allocInfo->m_NewImage = newImage;
+
+            // Keep track of our pipeline stages that we need to wait/signal on
+            beginSrcStageMask |= VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+            finalizeDstStageMask |= VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+
+            // We need one pipeline barrier and two image layout transitions here
+            // First we'll have to turn our newly created image into VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
+            // And the second one is turning the old image into VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
+
+            VkImageSubresourceRange subresourceRange = {
+                VK_IMAGE_ASPECT_COLOR_BIT,
+                0, VK_REMAINING_MIP_LEVELS,
+                0, VK_REMAINING_ARRAY_LAYERS
+            };
+
+            VkImageMemoryBarrier barrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER };
+            barrier.srcAccessMask = 0;
+            barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
+            barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+            barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+            barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+            barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+            barrier.image = newImage;
+            barrier.subresourceRange = subresourceRange;
+
+            beginImageBarriers.push_back(barrier);
+
+            // Second barrier to convert the existing image. This one actually needs a real barrier                         
+            barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
+            barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
+            barrier.oldLayout = allocInfo->m_ImageLayout;
+            barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
+            barrier.image = allocInfo->m_Image;
+
+            beginImageBarriers.push_back(barrier);
+
+            // And lastly we need a barrier that turns our new image into the layout of the old one
+            barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+            barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
+            barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+            barrier.newLayout = allocInfo->m_ImageLayout;
+            barrier.image = newImage;
+
+            finalizeImageBarriers.push_back(barrier);
+        }
+        else if(allocInfo->m_Buffer)
+        {
+            VkBuffer newBuffer;
+
+            const VkResult result = vkCreateBuffer(g_hDevice, &allocInfo->m_BufferInfo, g_Allocs, &newBuffer);
+            TEST(result >= VK_SUCCESS);
+
+            vkBindBufferMemory(g_hDevice, newBuffer, stepInfo.pMoves[i].memory, stepInfo.pMoves[i].offset);
+            allocInfo->m_NewBuffer = newBuffer;
+
+            // Keep track of our pipeline stages that we need to wait/signal on
+            beginSrcStageMask |= VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+            finalizeDstStageMask |= VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+
+            beginMemoryBarrier.srcAccessMask |= VK_ACCESS_MEMORY_WRITE_BIT;
+            beginMemoryBarrier.dstAccessMask |= VK_ACCESS_TRANSFER_READ_BIT;
+
+            finalizeMemoryBarrier.srcAccessMask |= VK_ACCESS_TRANSFER_WRITE_BIT;
+            finalizeMemoryBarrier.dstAccessMask |= VK_ACCESS_MEMORY_READ_BIT;
+
+            wantsMemoryBarrier = true;
+        }
+    }
+
+    if(!beginImageBarriers.empty() || wantsMemoryBarrier)
+    {
+        const uint32_t memoryBarrierCount = wantsMemoryBarrier ? 1 : 0;
+
+        vkCmdPipelineBarrier(g_hTemporaryCommandBuffer, beginSrcStageMask, beginDstStageMask, 0,
+            memoryBarrierCount, &beginMemoryBarrier,
+            0, nullptr,
+            (uint32_t)beginImageBarriers.size(), beginImageBarriers.data());
+    }
+
+    for(uint32_t i = 0; i < stepInfo.moveCount; ++ i)
+    {
+        VmaAllocationInfo info;
+        vmaGetAllocationInfo(g_hAllocator, stepInfo.pMoves[i].allocation, &info);
+
+        AllocInfo *allocInfo = (AllocInfo *)info.pUserData;
+
+        if(allocInfo->m_Image)
+        {
+            std::vector<VkImageCopy> imageCopies;
+
+            // Copy all mips of the source image into the target image
+            VkOffset3D offset = { 0, 0, 0 };
+            VkExtent3D extent = allocInfo->m_ImageInfo.extent;
+
+            VkImageSubresourceLayers subresourceLayers = {
+                VK_IMAGE_ASPECT_COLOR_BIT,
+                0,
+                0, 1
+            };
+
+            for(uint32_t mip = 0; mip < allocInfo->m_ImageInfo.mipLevels; ++ mip)
+            {
+                subresourceLayers.mipLevel = mip;
+
+                VkImageCopy imageCopy{
+                    subresourceLayers,
+                    offset,
+                    subresourceLayers,
+                    offset,
+                    extent
+                };
+
+                imageCopies.push_back(imageCopy);
+
+                extent.width = std::max(uint32_t(1), extent.width >> 1);
+                extent.height = std::max(uint32_t(1), extent.height >> 1);
+                extent.depth = std::max(uint32_t(1), extent.depth >> 1);
+            }
+
+            vkCmdCopyImage(
+                g_hTemporaryCommandBuffer,
+                allocInfo->m_Image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+                allocInfo->m_NewImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+                (uint32_t)imageCopies.size(), imageCopies.data());
+        }
+        else if(allocInfo->m_Buffer)
+        {
+            VkBufferCopy region = {
+                0,
+                0,
+                allocInfo->m_BufferInfo.size };
+
+            vkCmdCopyBuffer(g_hTemporaryCommandBuffer, 
+                allocInfo->m_Buffer, allocInfo->m_NewBuffer,
+                1, &region);
+        }
+    }
+
+    if(!finalizeImageBarriers.empty() || wantsMemoryBarrier)
+    {
+        const uint32_t memoryBarrierCount = wantsMemoryBarrier ? 1 : 0;
+
+        vkCmdPipelineBarrier(g_hTemporaryCommandBuffer, finalizeSrcStageMask, finalizeDstStageMask, 0,
+            memoryBarrierCount, &finalizeMemoryBarrier,
+            0, nullptr,
+            (uint32_t)finalizeImageBarriers.size(), finalizeImageBarriers.data());
+    }
+}
+
+
+static void TestDefragmentationIncrementalBasic()
+{
+    wprintf(L"Test defragmentation incremental basic\n");
+    g_MemoryAliasingWarningEnabled = false;
+
+    std::vector<AllocInfo> allocations;
+
+    // Create that many allocations to surely fill 3 new blocks of 256 MB.
+    const std::array<uint32_t, 3> imageSizes = { 256, 512, 1024 };
+    const VkDeviceSize bufSizeMin = 5ull * 1024 * 1024;
+    const VkDeviceSize bufSizeMax = 10ull * 1024 * 1024;
+    const VkDeviceSize totalSize = 3ull * 256 * 1024 * 1024;
+    const size_t imageCount = totalSize / ((size_t)imageSizes[0] * imageSizes[0] * 4) / 2;
+    const size_t bufCount = (size_t)(totalSize / bufSizeMin) / 2;
+    const size_t percentToLeave = 30;
+    RandomNumberGenerator rand = { 234522 };
+
+    VkImageCreateInfo imageInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
+    imageInfo.imageType = VK_IMAGE_TYPE_2D;
+    imageInfo.extent.depth = 1;
+    imageInfo.mipLevels = 1;
+    imageInfo.arrayLayers = 1;
+    imageInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
+    imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
+    imageInfo.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
+    imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
+    imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
+
+    VmaAllocationCreateInfo allocCreateInfo = {};
+    allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+    allocCreateInfo.flags = 0;
+
+    // Create all intended images.
+    for(size_t i = 0; i < imageCount; ++i)
+    {
+        const uint32_t size = imageSizes[rand.Generate() % 3];
+
+        imageInfo.extent.width = size;
+        imageInfo.extent.height = size;
+
+        AllocInfo alloc;
+        alloc.CreateImage(imageInfo, allocCreateInfo, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
+        alloc.m_StartValue = 0;
+
+        allocations.push_back(alloc);
+    }
+
+    // And all buffers
+    VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+
+    for(size_t i = 0; i < bufCount; ++i)
+    {
+        bufCreateInfo.size = align_up<VkDeviceSize>(bufSizeMin + rand.Generate() % (bufSizeMax - bufSizeMin), 16);
+        bufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+
+        AllocInfo alloc;
+        alloc.CreateBuffer(bufCreateInfo, allocCreateInfo);
+        alloc.m_StartValue = 0;
+
+        allocations.push_back(alloc);
+    }
+
+    // Destroy some percentage of them.
+    {
+        const size_t allocationsToDestroy = round_div<size_t>((imageCount + bufCount) * (100 - percentToLeave), 100);
+        for(size_t i = 0; i < allocationsToDestroy; ++i)
+        {
+            const size_t index = rand.Generate() % allocations.size();
+            allocations[index].Destroy();
+            allocations.erase(allocations.begin() + index);
+        }
+    }
+
+    {
+        // Set our user data pointers. A real application should probably be more clever here
+        const size_t allocationCount = allocations.size();
+        for(size_t i = 0; i < allocationCount; ++i)
+        {
+            AllocInfo &alloc = allocations[i];
+            vmaSetAllocationUserData(g_hAllocator, alloc.m_Allocation, &alloc);
+        }
+    }
+
+    // Fill them with meaningful data.
+    UploadGpuData(allocations.data(), allocations.size());
+
+    wchar_t fileName[MAX_PATH];
+    swprintf_s(fileName, L"GPU_defragmentation_incremental_basic_A_before.json");
+    SaveAllocatorStatsToFile(fileName);
+
+    // Defragment using GPU only.
+    {
+        const size_t allocCount = allocations.size();
+
+        std::vector<VmaAllocation> allocationPtrs;
+
+        for(size_t i = 0; i < allocCount; ++i)
+        {
+            allocationPtrs.push_back(allocations[i].m_Allocation);
+        }
+
+        const size_t movableAllocCount = allocationPtrs.size();
+
+        VmaDefragmentationInfo2 defragInfo = {};
+        defragInfo.flags = VMA_DEFRAGMENTATION_FLAG_INCREMENTAL;
+        defragInfo.allocationCount = (uint32_t)movableAllocCount;
+        defragInfo.pAllocations = allocationPtrs.data();
+        defragInfo.maxGpuBytesToMove = VK_WHOLE_SIZE;
+        defragInfo.maxGpuAllocationsToMove = UINT32_MAX;
+
+        VmaDefragmentationStats stats = {};
+        VmaDefragmentationContext ctx = VK_NULL_HANDLE;
+        VkResult res = vmaDefragmentationBegin(g_hAllocator, &defragInfo, &stats, &ctx);
+        TEST(res >= VK_SUCCESS);
+
+        res = VK_NOT_READY;
+
+        std::vector<VmaDefragmentationPassMoveInfo> moveInfo;
+        moveInfo.resize(movableAllocCount);
+
+        while(res == VK_NOT_READY)
+        {
+            VmaDefragmentationPassInfo stepInfo = {};
+            stepInfo.pMoves = moveInfo.data();
+            stepInfo.moveCount = (uint32_t)moveInfo.size();
+
+            res = vmaBeginDefragmentationPass(g_hAllocator, ctx, &stepInfo);
+            TEST(res >= VK_SUCCESS);
+
+            BeginSingleTimeCommands();
+            std::vector<void*> newHandles;
+            ProcessDefragmentationStepInfo(stepInfo);
+            EndSingleTimeCommands();
+
+            res = vmaEndDefragmentationPass(g_hAllocator, ctx);
+            
+            // Destroy old buffers/images and replace them with new handles.
+            for(size_t i = 0; i < stepInfo.moveCount; ++i)
+            {
+                VmaAllocation const alloc = stepInfo.pMoves[i].allocation;
+                VmaAllocationInfo vmaAllocInfo;
+                vmaGetAllocationInfo(g_hAllocator, alloc, &vmaAllocInfo);
+                AllocInfo* allocInfo = (AllocInfo*)vmaAllocInfo.pUserData;
+                if(allocInfo->m_Buffer)
+                {
+                    assert(allocInfo->m_NewBuffer && !allocInfo->m_Image && !allocInfo->m_NewImage);
+                    vkDestroyBuffer(g_hDevice, allocInfo->m_Buffer, g_Allocs);
+                    allocInfo->m_Buffer = allocInfo->m_NewBuffer;
+                    allocInfo->m_NewBuffer = VK_NULL_HANDLE;
+                }
+                else if(allocInfo->m_Image)
+                {
+                    assert(allocInfo->m_NewImage && !allocInfo->m_Buffer && !allocInfo->m_NewBuffer);
+                    vkDestroyImage(g_hDevice, allocInfo->m_Image, g_Allocs);
+                    allocInfo->m_Image = allocInfo->m_NewImage;
+                    allocInfo->m_NewImage = VK_NULL_HANDLE;
+                }
+                else
+                    assert(0);
+            }
+        }
+
+        TEST(res >= VK_SUCCESS);
+        vmaDefragmentationEnd(g_hAllocator, ctx);
+
+        // If corruption detection is enabled, GPU defragmentation may not work on
+        // memory types that have this detection active, e.g. on Intel.
+#if !defined(VMA_DEBUG_DETECT_CORRUPTION) || VMA_DEBUG_DETECT_CORRUPTION == 0
+        TEST(stats.allocationsMoved > 0 && stats.bytesMoved > 0);
+        TEST(stats.deviceMemoryBlocksFreed > 0 && stats.bytesFreed > 0);
+#endif
+    }
+
+    //ValidateGpuData(allocations.data(), allocations.size());
+
+    swprintf_s(fileName, L"GPU_defragmentation_incremental_basic_B_after.json");
+    SaveAllocatorStatsToFile(fileName);
+
+    // Destroy all remaining buffers and images.
+    for(size_t i = allocations.size(); i--; )
+    {
+        allocations[i].Destroy();
+    }
+
+    g_MemoryAliasingWarningEnabled = true;
+}
+
+void TestDefragmentationIncrementalComplex()
+{
+    wprintf(L"Test defragmentation incremental complex\n");
+    g_MemoryAliasingWarningEnabled = false;
+
+    std::vector<AllocInfo> allocations;
+
+    // Create that many allocations to surely fill 3 new blocks of 256 MB.
+    const std::array<uint32_t, 3> imageSizes = { 256, 512, 1024 };
+    const VkDeviceSize bufSizeMin = 5ull * 1024 * 1024;
+    const VkDeviceSize bufSizeMax = 10ull * 1024 * 1024;
+    const VkDeviceSize totalSize = 3ull * 256 * 1024 * 1024;
+    const size_t imageCount = (size_t)(totalSize / (imageSizes[0] * imageSizes[0] * 4)) / 2;
+    const size_t bufCount = (size_t)(totalSize / bufSizeMin) / 2;
+    const size_t percentToLeave = 30;
+    RandomNumberGenerator rand = { 234522 };
+
+    VkImageCreateInfo imageInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
+    imageInfo.imageType = VK_IMAGE_TYPE_2D;
+    imageInfo.extent.depth = 1;
+    imageInfo.mipLevels = 1;
+    imageInfo.arrayLayers = 1;
+    imageInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
+    imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
+    imageInfo.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
+    imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
+    imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
+
+    VmaAllocationCreateInfo allocCreateInfo = {};
+    allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+    allocCreateInfo.flags = 0;
+
+    // Create all intended images.
+    for(size_t i = 0; i < imageCount; ++i)
+    {
+        const uint32_t size = imageSizes[rand.Generate() % 3];
+
+        imageInfo.extent.width = size;
+        imageInfo.extent.height = size;
+
+        AllocInfo alloc;
+        alloc.CreateImage(imageInfo, allocCreateInfo, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
+        alloc.m_StartValue = 0;
+
+        allocations.push_back(alloc);
+    }
+
+    // And all buffers
+    VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+
+    for(size_t i = 0; i < bufCount; ++i)
+    {
+        bufCreateInfo.size = align_up<VkDeviceSize>(bufSizeMin + rand.Generate() % (bufSizeMax - bufSizeMin), 16);
+        bufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+
+        AllocInfo alloc;
+        alloc.CreateBuffer(bufCreateInfo, allocCreateInfo);
+        alloc.m_StartValue = 0;
+
+        allocations.push_back(alloc);
+    }
+
+    // Destroy some percentage of them.
+    {
+        const size_t allocationsToDestroy = round_div<size_t>((imageCount + bufCount) * (100 - percentToLeave), 100);
+        for(size_t i = 0; i < allocationsToDestroy; ++i)
+        {
+            const size_t index = rand.Generate() % allocations.size();
+            allocations[index].Destroy();
+            allocations.erase(allocations.begin() + index);
+        }
+    }
+
+    {
+        // Set our user data pointers. A real application should probably be more clever here
+        const size_t allocationCount = allocations.size();
+        for(size_t i = 0; i < allocationCount; ++i)
+        {
+            AllocInfo &alloc = allocations[i];
+            vmaSetAllocationUserData(g_hAllocator, alloc.m_Allocation, &alloc);
+        }
+    }
+
+    // Fill them with meaningful data.
+    UploadGpuData(allocations.data(), allocations.size());
+
+    wchar_t fileName[MAX_PATH];
+    swprintf_s(fileName, L"GPU_defragmentation_incremental_complex_A_before.json");
+    SaveAllocatorStatsToFile(fileName);
+
+    std::vector<AllocInfo> additionalAllocations;
+
+#define MakeAdditionalAllocation() \
+    do { \
+        { \
+            bufCreateInfo.size = align_up<VkDeviceSize>(bufSizeMin + rand.Generate() % (bufSizeMax - bufSizeMin), 16); \
+            bufCreateInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT; \
+            \
+            AllocInfo alloc; \
+            alloc.CreateBuffer(bufCreateInfo, allocCreateInfo); \
+            \
+            additionalAllocations.push_back(alloc); \
+        } \
+    } while(0)
+
+    // Defragment using GPU only.
+    {
+        const size_t allocCount = allocations.size();
+
+        std::vector<VmaAllocation> allocationPtrs;
+
+        for(size_t i = 0; i < allocCount; ++i)
+        {
+            VmaAllocationInfo allocInfo = {};
+            vmaGetAllocationInfo(g_hAllocator, allocations[i].m_Allocation, &allocInfo);
+
+            allocationPtrs.push_back(allocations[i].m_Allocation);
+        }
+
+        const size_t movableAllocCount = allocationPtrs.size();
+
+        VmaDefragmentationInfo2 defragInfo = {};
+        defragInfo.flags = VMA_DEFRAGMENTATION_FLAG_INCREMENTAL;
+        defragInfo.allocationCount = (uint32_t)movableAllocCount;
+        defragInfo.pAllocations = allocationPtrs.data();
+        defragInfo.maxGpuBytesToMove = VK_WHOLE_SIZE;
+        defragInfo.maxGpuAllocationsToMove = UINT32_MAX;
+
+        VmaDefragmentationStats stats = {};
+        VmaDefragmentationContext ctx = VK_NULL_HANDLE;
+        VkResult res = vmaDefragmentationBegin(g_hAllocator, &defragInfo, &stats, &ctx);
+        TEST(res >= VK_SUCCESS);
+
+        res = VK_NOT_READY;
+
+        std::vector<VmaDefragmentationPassMoveInfo> moveInfo;
+        moveInfo.resize(movableAllocCount);
+
+        MakeAdditionalAllocation();
+
+        while(res == VK_NOT_READY)
+        {
+            VmaDefragmentationPassInfo stepInfo = {};
+            stepInfo.pMoves = moveInfo.data();
+            stepInfo.moveCount = (uint32_t)moveInfo.size();
+
+            res = vmaBeginDefragmentationPass(g_hAllocator, ctx, &stepInfo);
+            TEST(res >= VK_SUCCESS);
+
+            MakeAdditionalAllocation();
+
+            BeginSingleTimeCommands();
+            ProcessDefragmentationStepInfo(stepInfo);
+            EndSingleTimeCommands();
+
+            res = vmaEndDefragmentationPass(g_hAllocator, ctx);
+
+            // Destroy old buffers/images and replace them with new handles.
+            for(size_t i = 0; i < stepInfo.moveCount; ++i)
+            {
+                VmaAllocation const alloc = stepInfo.pMoves[i].allocation;
+                VmaAllocationInfo vmaAllocInfo;
+                vmaGetAllocationInfo(g_hAllocator, alloc, &vmaAllocInfo);
+                AllocInfo* allocInfo = (AllocInfo*)vmaAllocInfo.pUserData;
+                if(allocInfo->m_Buffer)
+                {
+                    assert(allocInfo->m_NewBuffer && !allocInfo->m_Image && !allocInfo->m_NewImage);
+                    vkDestroyBuffer(g_hDevice, allocInfo->m_Buffer, g_Allocs);
+                    allocInfo->m_Buffer = allocInfo->m_NewBuffer;
+                    allocInfo->m_NewBuffer = VK_NULL_HANDLE;
+                }
+                else if(allocInfo->m_Image)
+                {
+                    assert(allocInfo->m_NewImage && !allocInfo->m_Buffer && !allocInfo->m_NewBuffer);
+                    vkDestroyImage(g_hDevice, allocInfo->m_Image, g_Allocs);
+                    allocInfo->m_Image = allocInfo->m_NewImage;
+                    allocInfo->m_NewImage = VK_NULL_HANDLE;
+                }
+                else
+                    assert(0);
+            }
+
+            MakeAdditionalAllocation();
+        }
+
+        TEST(res >= VK_SUCCESS);
+        vmaDefragmentationEnd(g_hAllocator, ctx);
+
+        // If corruption detection is enabled, GPU defragmentation may not work on
+        // memory types that have this detection active, e.g. on Intel.
+#if !defined(VMA_DEBUG_DETECT_CORRUPTION) || VMA_DEBUG_DETECT_CORRUPTION == 0
+        TEST(stats.allocationsMoved > 0 && stats.bytesMoved > 0);
+        TEST(stats.deviceMemoryBlocksFreed > 0 && stats.bytesFreed > 0);
+#endif
+    }
+
+    //ValidateGpuData(allocations.data(), allocations.size());
+
+    swprintf_s(fileName, L"GPU_defragmentation_incremental_complex_B_after.json");
+    SaveAllocatorStatsToFile(fileName);
+
+    // Destroy all remaining buffers.
+    for(size_t i = allocations.size(); i--; )
+    {
+        allocations[i].Destroy();
+    }
+
+    for(size_t i = additionalAllocations.size(); i--; )
+    {
+        additionalAllocations[i].Destroy();
+    }
+
+    g_MemoryAliasingWarningEnabled = true;
+}
+
+
+static void TestUserData()
+{
+    VkResult res;
+
+    VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+    bufCreateInfo.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
+    bufCreateInfo.size = 0x10000;
+
+    for(uint32_t testIndex = 0; testIndex < 2; ++testIndex)
+    {
+        // Opaque pointer
+        {
+
+            void* numberAsPointer = (void*)(size_t)0xC2501FF3u;
+            void* pointerToSomething = &res;
+
+            VmaAllocationCreateInfo allocCreateInfo = {};
+            allocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
+            allocCreateInfo.pUserData = numberAsPointer;
+            if(testIndex == 1)
+                allocCreateInfo.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
+
+            VkBuffer buf; VmaAllocation alloc; VmaAllocationInfo allocInfo;
+            res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);
+            TEST(res == VK_SUCCESS);
+            TEST(allocInfo.pUserData = numberAsPointer);
+
+            vmaGetAllocationInfo(g_hAllocator, alloc, &allocInfo);
+            TEST(allocInfo.pUserData == numberAsPointer);
+
+            vmaSetAllocationUserData(g_hAllocator, alloc, pointerToSomething);
+            vmaGetAllocationInfo(g_hAllocator, alloc, &allocInfo);
+            TEST(allocInfo.pUserData == pointerToSomething);
+
+            vmaDestroyBuffer(g_hAllocator, buf, alloc);
+        }
+
+        // String
+        {
+            const char* name1 = "Buffer name \\\"\'<>&% \nSecond line .,;=";
+            const char* name2 = "2";
+            const size_t name1Len = strlen(name1);
+
+            char* name1Buf = new char[name1Len + 1];
+            strcpy_s(name1Buf, name1Len + 1, name1);
+
+            VmaAllocationCreateInfo allocCreateInfo = {};
+            allocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
+            allocCreateInfo.flags = VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT;
+            allocCreateInfo.pUserData = name1Buf;
+            if(testIndex == 1)
+                allocCreateInfo.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
+
+            VkBuffer buf; VmaAllocation alloc; VmaAllocationInfo allocInfo;
+            res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);
+            TEST(res == VK_SUCCESS);
+            TEST(allocInfo.pUserData != nullptr && allocInfo.pUserData != name1Buf);
+            TEST(strcmp(name1, (const char*)allocInfo.pUserData) == 0);
+
+            delete[] name1Buf;
+
+            vmaGetAllocationInfo(g_hAllocator, alloc, &allocInfo);
+            TEST(strcmp(name1, (const char*)allocInfo.pUserData) == 0);
+
+            vmaSetAllocationUserData(g_hAllocator, alloc, (void*)name2);
+            vmaGetAllocationInfo(g_hAllocator, alloc, &allocInfo);
+            TEST(strcmp(name2, (const char*)allocInfo.pUserData) == 0);
+
+            vmaSetAllocationUserData(g_hAllocator, alloc, nullptr);
+            vmaGetAllocationInfo(g_hAllocator, alloc, &allocInfo);
+            TEST(allocInfo.pUserData == nullptr);
+
+            vmaDestroyBuffer(g_hAllocator, buf, alloc);
+        }
+    }
+}
+
+static void TestInvalidAllocations()
+{
+    VkResult res;
+
+    VmaAllocationCreateInfo allocCreateInfo = {};
+    allocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
+
+    // Try to allocate 0 bytes.
+    {
+        VkMemoryRequirements memReq = {};
+        memReq.size = 0; // !!!
+        memReq.alignment = 4;
+        memReq.memoryTypeBits = UINT32_MAX;
+        VmaAllocation alloc = VK_NULL_HANDLE;
+        res = vmaAllocateMemory(g_hAllocator, &memReq, &allocCreateInfo, &alloc, nullptr);
+        TEST(res == VK_ERROR_VALIDATION_FAILED_EXT && alloc == VK_NULL_HANDLE);
+    }
+
+    // Try to create buffer with size = 0.
+    {
+        VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+        bufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+        bufCreateInfo.size = 0; // !!!
+        VkBuffer buf = VK_NULL_HANDLE;
+        VmaAllocation alloc = VK_NULL_HANDLE;
+        res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, nullptr);
+        TEST(res == VK_ERROR_VALIDATION_FAILED_EXT && buf == VK_NULL_HANDLE && alloc == VK_NULL_HANDLE);
+    }
+
+    // Try to create image with one dimension = 0.
+    {
+        VkImageCreateInfo imageCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+        imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
+        imageCreateInfo.format = VK_FORMAT_B8G8R8A8_UNORM;
+        imageCreateInfo.extent.width = 128;
+        imageCreateInfo.extent.height = 0; // !!!
+        imageCreateInfo.extent.depth = 1;
+        imageCreateInfo.mipLevels = 1;
+        imageCreateInfo.arrayLayers = 1;
+        imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
+        imageCreateInfo.tiling = VK_IMAGE_TILING_LINEAR;
+        imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
+        imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
+        VkImage image = VK_NULL_HANDLE;
+        VmaAllocation alloc = VK_NULL_HANDLE;
+        res = vmaCreateImage(g_hAllocator, &imageCreateInfo, &allocCreateInfo, &image, &alloc, nullptr);
+        TEST(res == VK_ERROR_VALIDATION_FAILED_EXT && image == VK_NULL_HANDLE && alloc == VK_NULL_HANDLE);
+    }
+}
+
+static void TestMemoryRequirements()
+{
+    VkResult res;
+    VkBuffer buf;
+    VmaAllocation alloc;
+    VmaAllocationInfo allocInfo;
+
+    const VkPhysicalDeviceMemoryProperties* memProps;
+    vmaGetMemoryProperties(g_hAllocator, &memProps);
+
+    VkBufferCreateInfo bufInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+    bufInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+    bufInfo.size = 128;
+
+    VmaAllocationCreateInfo allocCreateInfo = {};
+
+    // No requirements.
+    res = vmaCreateBuffer(g_hAllocator, &bufInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);
+    TEST(res == VK_SUCCESS);
+    vmaDestroyBuffer(g_hAllocator, buf, alloc);
+
+    // Usage.
+    allocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
+    allocCreateInfo.requiredFlags = 0;
+    allocCreateInfo.preferredFlags = 0;
+    allocCreateInfo.memoryTypeBits = UINT32_MAX;
+
+    res = vmaCreateBuffer(g_hAllocator, &bufInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);
+    TEST(res == VK_SUCCESS);
+    TEST(memProps->memoryTypes[allocInfo.memoryType].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
+    vmaDestroyBuffer(g_hAllocator, buf, alloc);
+
+    // Required flags, preferred flags.
+    allocCreateInfo.usage = VMA_MEMORY_USAGE_UNKNOWN;
+    allocCreateInfo.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
+    allocCreateInfo.preferredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
+    allocCreateInfo.memoryTypeBits = 0;
+
+    res = vmaCreateBuffer(g_hAllocator, &bufInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);
+    TEST(res == VK_SUCCESS);
+    TEST(memProps->memoryTypes[allocInfo.memoryType].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
+    TEST(memProps->memoryTypes[allocInfo.memoryType].propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
+    vmaDestroyBuffer(g_hAllocator, buf, alloc);
+
+    // memoryTypeBits.
+    const uint32_t memType = allocInfo.memoryType;
+    allocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
+    allocCreateInfo.requiredFlags = 0;
+    allocCreateInfo.preferredFlags = 0;
+    allocCreateInfo.memoryTypeBits = 1u << memType;
+
+    res = vmaCreateBuffer(g_hAllocator, &bufInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);
+    TEST(res == VK_SUCCESS);
+    TEST(allocInfo.memoryType == memType);
+    vmaDestroyBuffer(g_hAllocator, buf, alloc);
+
+}
+
+static void TestGetAllocatorInfo()
+{
+    wprintf(L"Test vnaGetAllocatorInfo\n");
+
+    VmaAllocatorInfo allocInfo = {};
+    vmaGetAllocatorInfo(g_hAllocator, &allocInfo);
+    TEST(allocInfo.instance == g_hVulkanInstance);
+    TEST(allocInfo.physicalDevice == g_hPhysicalDevice);
+    TEST(allocInfo.device == g_hDevice);
+}
+
+static void TestBasics()
+{
+    VkResult res;
+
+    TestGetAllocatorInfo();
+
+    TestMemoryRequirements();
+
+    // Lost allocation
+    {
+        VmaAllocation alloc = VK_NULL_HANDLE;
+        vmaCreateLostAllocation(g_hAllocator, &alloc);
+        TEST(alloc != VK_NULL_HANDLE);
+
+        VmaAllocationInfo allocInfo;
+        vmaGetAllocationInfo(g_hAllocator, alloc, &allocInfo);
+        TEST(allocInfo.deviceMemory == VK_NULL_HANDLE);
+        TEST(allocInfo.size == 0);
+
+        vmaFreeMemory(g_hAllocator, alloc);
+    }
+    
+    // Allocation that is MAPPED and not necessarily HOST_VISIBLE.
+    {
+        VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+        bufCreateInfo.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
+        bufCreateInfo.size = 128;
+
+        VmaAllocationCreateInfo allocCreateInfo = {};
+        allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+        allocCreateInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
+
+        VkBuffer buf; VmaAllocation alloc; VmaAllocationInfo allocInfo;
+        res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);
+        TEST(res == VK_SUCCESS);
+
+        vmaDestroyBuffer(g_hAllocator, buf, alloc);
+
+        // Same with OWN_MEMORY.
+        allocCreateInfo.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
+
+        res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);
+        TEST(res == VK_SUCCESS);
+
+        vmaDestroyBuffer(g_hAllocator, buf, alloc);
+    }
+
+    TestUserData();
+
+    TestInvalidAllocations();
+}
+
+static void TestPool_MinBlockCount()
+{
+#if defined(VMA_DEBUG_MARGIN) && VMA_DEBUG_MARGIN > 0
+    return;
+#endif
+
+    wprintf(L"Test Pool MinBlockCount\n");
+    VkResult res;
+
+    static const VkDeviceSize ALLOC_SIZE = 512ull * 1024;
+    static const VkDeviceSize BLOCK_SIZE = ALLOC_SIZE * 2; // Each block can fit 2 allocations.
+
+    VmaAllocationCreateInfo allocCreateInfo = {};
+    allocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_COPY;
+
+    VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+    bufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+    bufCreateInfo.size = ALLOC_SIZE;
+
+    VmaPoolCreateInfo poolCreateInfo = {};
+    poolCreateInfo.blockSize = BLOCK_SIZE;
+    poolCreateInfo.minBlockCount = 2; // At least 2 blocks always present.
+    res = vmaFindMemoryTypeIndexForBufferInfo(g_hAllocator, &bufCreateInfo, &allocCreateInfo, &poolCreateInfo.memoryTypeIndex);
+    TEST(res == VK_SUCCESS);
+
+    VmaPool pool = VK_NULL_HANDLE;
+    res = vmaCreatePool(g_hAllocator, &poolCreateInfo, &pool);
+    TEST(res == VK_SUCCESS && pool != VK_NULL_HANDLE);
+
+    // Check that there are 2 blocks preallocated as requested.
+    VmaPoolStats begPoolStats = {};
+    vmaGetPoolStats(g_hAllocator, pool, &begPoolStats);
+    TEST(begPoolStats.blockCount == 2 && begPoolStats.allocationCount == 0 && begPoolStats.size == BLOCK_SIZE * 2);
+
+    // Allocate 5 buffers to create 3 blocks.
+    static const uint32_t BUF_COUNT = 5;
+    allocCreateInfo.pool = pool;
+    std::vector<AllocInfo> allocs(BUF_COUNT);
+    for(uint32_t i = 0; i < BUF_COUNT; ++i)
+    {
+        res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo, &allocs[i].m_Buffer, &allocs[i].m_Allocation, nullptr);
+        TEST(res == VK_SUCCESS && allocs[i].m_Buffer != VK_NULL_HANDLE && allocs[i].m_Allocation != VK_NULL_HANDLE);
+    }
+
+    // Check that there are really 3 blocks.
+    VmaPoolStats poolStats2 = {};
+    vmaGetPoolStats(g_hAllocator, pool, &poolStats2);
+    TEST(poolStats2.blockCount == 3 && poolStats2.allocationCount == BUF_COUNT && poolStats2.size == BLOCK_SIZE * 3);
+
+    // Free two first allocations to make one block empty.
+    allocs[0].Destroy();
+    allocs[1].Destroy();
+
+    // Check that there are still 3 blocks due to hysteresis.
+    VmaPoolStats poolStats3 = {};
+    vmaGetPoolStats(g_hAllocator, pool, &poolStats3);
+    TEST(poolStats3.blockCount == 3 && poolStats3.allocationCount == BUF_COUNT - 2 && poolStats2.size == BLOCK_SIZE * 3);
+
+    // Free the last allocation to make second block empty.
+    allocs[BUF_COUNT - 1].Destroy();
+
+    // Check that there are now 2 blocks only.
+    VmaPoolStats poolStats4 = {};
+    vmaGetPoolStats(g_hAllocator, pool, &poolStats4);
+    TEST(poolStats4.blockCount == 2 && poolStats4.allocationCount == BUF_COUNT - 3 && poolStats4.size == BLOCK_SIZE * 2);
+
+    // Cleanup.
+    for(size_t i = allocs.size(); i--; )
+    {
+        allocs[i].Destroy();
+    }
+    vmaDestroyPool(g_hAllocator, pool);
+}
+
+void TestHeapSizeLimit()
+{
+    const VkDeviceSize HEAP_SIZE_LIMIT = 100ull * 1024 * 1024; // 100 MB
+    const VkDeviceSize BLOCK_SIZE      =  10ull * 1024 * 1024; // 10 MB
+
+    VkDeviceSize heapSizeLimit[VK_MAX_MEMORY_HEAPS];
+    for(uint32_t i = 0; i < VK_MAX_MEMORY_HEAPS; ++i)
+    {
+        heapSizeLimit[i] = HEAP_SIZE_LIMIT;
+    }
+
+    VmaAllocatorCreateInfo allocatorCreateInfo = {};
+    allocatorCreateInfo.physicalDevice = g_hPhysicalDevice;
+    allocatorCreateInfo.device = g_hDevice;
+    allocatorCreateInfo.instance = g_hVulkanInstance;
+    allocatorCreateInfo.pHeapSizeLimit = heapSizeLimit;
+
+    VmaAllocator hAllocator;
+    VkResult res = vmaCreateAllocator(&allocatorCreateInfo, &hAllocator);
+    TEST(res == VK_SUCCESS);
+
+    struct Item
+    {
+        VkBuffer hBuf;
+        VmaAllocation hAlloc;
+    };
+    std::vector<Item> items;
+
+    VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+    bufCreateInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
+
+    // 1. Allocate two blocks of dedicated memory, half the size of BLOCK_SIZE.
+    VmaAllocationInfo dedicatedAllocInfo;
+    {
+        VmaAllocationCreateInfo allocCreateInfo = {};
+        allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+        allocCreateInfo.flags = VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
+
+        bufCreateInfo.size = BLOCK_SIZE / 2;
+
+        for(size_t i = 0; i < 2; ++i)
+        {
+            Item item;
+            res = vmaCreateBuffer(hAllocator, &bufCreateInfo, &allocCreateInfo, &item.hBuf, &item.hAlloc, &dedicatedAllocInfo);
+            TEST(res == VK_SUCCESS);
+            items.push_back(item);
+        }
+    }
+
+    // Create pool to make sure allocations must be out of this memory type.
+    VmaPoolCreateInfo poolCreateInfo = {};
+    poolCreateInfo.memoryTypeIndex = dedicatedAllocInfo.memoryType;
+    poolCreateInfo.blockSize = BLOCK_SIZE;
+
+    VmaPool hPool;
+    res = vmaCreatePool(hAllocator, &poolCreateInfo, &hPool);
+    TEST(res == VK_SUCCESS);
+
+    // 2. Allocate normal buffers from all the remaining memory.
+    {
+        VmaAllocationCreateInfo allocCreateInfo = {};
+        allocCreateInfo.pool = hPool;
+
+        bufCreateInfo.size = BLOCK_SIZE / 2;
+
+        const size_t bufCount = ((HEAP_SIZE_LIMIT / BLOCK_SIZE) - 1) * 2;
+        for(size_t i = 0; i < bufCount; ++i)
+        {
+            Item item;
+            res = vmaCreateBuffer(hAllocator, &bufCreateInfo, &allocCreateInfo, &item.hBuf, &item.hAlloc, nullptr);
+            TEST(res == VK_SUCCESS);
+            items.push_back(item);
+        }
+    }
+
+    // 3. Allocation of one more (even small) buffer should fail.
+    {
+        VmaAllocationCreateInfo allocCreateInfo = {};
+        allocCreateInfo.pool = hPool;
+
+        bufCreateInfo.size = 128;
+
+        VkBuffer hBuf;
+        VmaAllocation hAlloc;
+        res = vmaCreateBuffer(hAllocator, &bufCreateInfo, &allocCreateInfo, &hBuf, &hAlloc, nullptr);
+        TEST(res == VK_ERROR_OUT_OF_DEVICE_MEMORY);
+    }
+
+    // Destroy everything.
+    for(size_t i = items.size(); i--; )
+    {
+        vmaDestroyBuffer(hAllocator, items[i].hBuf, items[i].hAlloc);
+    }
+
+    vmaDestroyPool(hAllocator, hPool);
+
+    vmaDestroyAllocator(hAllocator);
+}
+
+#if VMA_DEBUG_MARGIN
+static void TestDebugMargin()
+{
+    if(VMA_DEBUG_MARGIN == 0)
+    {
+        return;
+    }
+
+    VkBufferCreateInfo bufInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+    bufInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+    
+    VmaAllocationCreateInfo allocCreateInfo = {};
+    allocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
+
+    // Create few buffers of different size.
+    const size_t BUF_COUNT = 10;
+    BufferInfo buffers[BUF_COUNT];
+    VmaAllocationInfo allocInfo[BUF_COUNT];
+    for(size_t i = 0; i < 10; ++i)
+    {
+        bufInfo.size = (VkDeviceSize)(i + 1) * 64;
+        // Last one will be mapped.
+        allocCreateInfo.flags = (i == BUF_COUNT - 1) ? VMA_ALLOCATION_CREATE_MAPPED_BIT : 0;
+
+        VkResult res = vmaCreateBuffer(g_hAllocator, &bufInfo, &allocCreateInfo, &buffers[i].Buffer, &buffers[i].Allocation, &allocInfo[i]);
+        TEST(res == VK_SUCCESS);
+        // Margin is preserved also at the beginning of a block.
+        TEST(allocInfo[i].offset >= VMA_DEBUG_MARGIN);
+
+        if(i == BUF_COUNT - 1)
+        {
+            // Fill with data.
+            TEST(allocInfo[i].pMappedData != nullptr);
+            // Uncomment this "+ 1" to overwrite past end of allocation and check corruption detection.
+            memset(allocInfo[i].pMappedData, 0xFF, bufInfo.size /* + 1 */);
+        }
+    }
+
+    // Check if their offsets preserve margin between them.
+    std::sort(allocInfo, allocInfo + BUF_COUNT, [](const VmaAllocationInfo& lhs, const VmaAllocationInfo& rhs) -> bool
+    {
+        if(lhs.deviceMemory != rhs.deviceMemory)
+        {
+            return lhs.deviceMemory < rhs.deviceMemory;
+        }
+        return lhs.offset < rhs.offset;
+    });
+    for(size_t i = 1; i < BUF_COUNT; ++i)
+    {
+        if(allocInfo[i].deviceMemory == allocInfo[i - 1].deviceMemory)
+        {
+            TEST(allocInfo[i].offset >= allocInfo[i - 1].offset + VMA_DEBUG_MARGIN);
+        }
+    }
+
+    VkResult res = vmaCheckCorruption(g_hAllocator, UINT32_MAX);
+    TEST(res == VK_SUCCESS);
+
+    // Destroy all buffers.
+    for(size_t i = BUF_COUNT; i--; )
+    {
+        vmaDestroyBuffer(g_hAllocator, buffers[i].Buffer, buffers[i].Allocation);
+    }
+}
+#endif
+
+static void TestLinearAllocator()
+{
+    wprintf(L"Test linear allocator\n");
+
+    RandomNumberGenerator rand{645332};
+
+    VkBufferCreateInfo sampleBufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+    sampleBufCreateInfo.size = 1024; // Whatever.
+    sampleBufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
+
+    VmaAllocationCreateInfo sampleAllocCreateInfo = {};
+    sampleAllocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+
+    VmaPoolCreateInfo poolCreateInfo = {};
+    VkResult res = vmaFindMemoryTypeIndexForBufferInfo(g_hAllocator, &sampleBufCreateInfo, &sampleAllocCreateInfo, &poolCreateInfo.memoryTypeIndex);
+    TEST(res == VK_SUCCESS);
+
+    poolCreateInfo.blockSize = 1024 * 300;
+    poolCreateInfo.flags = VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT;
+    poolCreateInfo.minBlockCount = poolCreateInfo.maxBlockCount = 1;
+
+    VmaPool pool = nullptr;
+    res = vmaCreatePool(g_hAllocator, &poolCreateInfo, &pool);
+    TEST(res == VK_SUCCESS);
+
+    VkBufferCreateInfo bufCreateInfo = sampleBufCreateInfo;
+
+    VmaAllocationCreateInfo allocCreateInfo = {};
+    allocCreateInfo.pool = pool;
+
+    constexpr size_t maxBufCount = 100;
+    std::vector<BufferInfo> bufInfo;
+
+    constexpr VkDeviceSize bufSizeMin = 16;
+    constexpr VkDeviceSize bufSizeMax = 1024;
+    VmaAllocationInfo allocInfo;
+    VkDeviceSize prevOffset = 0;
+
+    // Test one-time free.
+    for(size_t i = 0; i < 2; ++i)
+    {
+        // Allocate number of buffers of varying size that surely fit into this block.
+        VkDeviceSize bufSumSize = 0;
+        for(size_t i = 0; i < maxBufCount; ++i)
+        {
+			bufCreateInfo.size = align_up<VkDeviceSize>(bufSizeMin + rand.Generate() % (bufSizeMax - bufSizeMin), 16);
+            BufferInfo newBufInfo;
+            res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo,
+                &newBufInfo.Buffer, &newBufInfo.Allocation, &allocInfo);
+            TEST(res == VK_SUCCESS);
+            TEST(i == 0 || allocInfo.offset > prevOffset);
+            bufInfo.push_back(newBufInfo);
+            prevOffset = allocInfo.offset;
+            bufSumSize += bufCreateInfo.size;
+        }
+
+        // Validate pool stats.
+        VmaPoolStats stats;
+        vmaGetPoolStats(g_hAllocator, pool, &stats);
+        TEST(stats.size == poolCreateInfo.blockSize);
+        TEST(stats.unusedSize = poolCreateInfo.blockSize - bufSumSize);
+        TEST(stats.allocationCount == bufInfo.size());
+
+        // Destroy the buffers in random order.
+        while(!bufInfo.empty())
+        {
+            const size_t indexToDestroy = rand.Generate() % bufInfo.size();
+            const BufferInfo& currBufInfo = bufInfo[indexToDestroy];
+            vmaDestroyBuffer(g_hAllocator, currBufInfo.Buffer, currBufInfo.Allocation);
+            bufInfo.erase(bufInfo.begin() + indexToDestroy);
+        }
+    }
+
+    // Test stack.
+    {
+        // Allocate number of buffers of varying size that surely fit into this block.
+        for(size_t i = 0; i < maxBufCount; ++i)
+        {
+            bufCreateInfo.size = align_up<VkDeviceSize>(bufSizeMin + rand.Generate() % (bufSizeMax - bufSizeMin), 16);
+            BufferInfo newBufInfo;
+            res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo,
+                &newBufInfo.Buffer, &newBufInfo.Allocation, &allocInfo);
+            TEST(res == VK_SUCCESS);
+            TEST(i == 0 || allocInfo.offset > prevOffset);
+            bufInfo.push_back(newBufInfo);
+            prevOffset = allocInfo.offset;
+        }
+
+        // Destroy few buffers from top of the stack.
+        for(size_t i = 0; i < maxBufCount / 5; ++i)
+        {
+            const BufferInfo& currBufInfo = bufInfo.back();
+            vmaDestroyBuffer(g_hAllocator, currBufInfo.Buffer, currBufInfo.Allocation);
+            bufInfo.pop_back();
+        }
+
+        // Create some more
+        for(size_t i = 0; i < maxBufCount / 5; ++i)
+        {
+            bufCreateInfo.size = align_up<VkDeviceSize>(bufSizeMin + rand.Generate() % (bufSizeMax - bufSizeMin), 16);
+            BufferInfo newBufInfo;
+            res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo,
+                &newBufInfo.Buffer, &newBufInfo.Allocation, &allocInfo);
+            TEST(res == VK_SUCCESS);
+            TEST(i == 0 || allocInfo.offset > prevOffset);
+            bufInfo.push_back(newBufInfo);
+            prevOffset = allocInfo.offset;
+        }
+
+        // Destroy the buffers in reverse order.
+        while(!bufInfo.empty())
+        {
+            const BufferInfo& currBufInfo = bufInfo.back();
+            vmaDestroyBuffer(g_hAllocator, currBufInfo.Buffer, currBufInfo.Allocation);
+            bufInfo.pop_back();
+        }
+    }
+
+    // Test ring buffer.
+    {
+        // Allocate number of buffers that surely fit into this block.
+        bufCreateInfo.size = bufSizeMax;
+        for(size_t i = 0; i < maxBufCount; ++i)
+        {
+            BufferInfo newBufInfo;
+            res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo,
+                &newBufInfo.Buffer, &newBufInfo.Allocation, &allocInfo);
+            TEST(res == VK_SUCCESS);
+            TEST(i == 0 || allocInfo.offset > prevOffset);
+            bufInfo.push_back(newBufInfo);
+            prevOffset = allocInfo.offset;
+        }
+
+        // Free and allocate new buffers so many times that we make sure we wrap-around at least once.
+        const size_t buffersPerIter = maxBufCount / 10 - 1;
+        const size_t iterCount = poolCreateInfo.blockSize / bufCreateInfo.size / buffersPerIter * 2;
+        for(size_t iter = 0; iter < iterCount; ++iter)
+        {
+            for(size_t bufPerIter = 0; bufPerIter < buffersPerIter; ++bufPerIter)
+            {
+                const BufferInfo& currBufInfo = bufInfo.front();
+                vmaDestroyBuffer(g_hAllocator, currBufInfo.Buffer, currBufInfo.Allocation);
+                bufInfo.erase(bufInfo.begin());
+            }
+            for(size_t bufPerIter = 0; bufPerIter < buffersPerIter; ++bufPerIter)
+            {
+                BufferInfo newBufInfo;
+                res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo,
+                    &newBufInfo.Buffer, &newBufInfo.Allocation, &allocInfo);
+                TEST(res == VK_SUCCESS);
+                bufInfo.push_back(newBufInfo);
+            }
+        }
+        
+        // Allocate buffers until we reach out-of-memory.
+        uint32_t debugIndex = 0;
+        while(res == VK_SUCCESS)
+        {
+            BufferInfo newBufInfo;
+            res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo,
+                &newBufInfo.Buffer, &newBufInfo.Allocation, &allocInfo);
+            if(res == VK_SUCCESS)
+            {
+                bufInfo.push_back(newBufInfo);
+            }
+            else
+            {
+                TEST(res == VK_ERROR_OUT_OF_DEVICE_MEMORY);
+            }
+            ++debugIndex;
+        }
+
+        // Destroy the buffers in random order.
+        while(!bufInfo.empty())
+        {
+            const size_t indexToDestroy = rand.Generate() % bufInfo.size();
+            const BufferInfo& currBufInfo = bufInfo[indexToDestroy];
+            vmaDestroyBuffer(g_hAllocator, currBufInfo.Buffer, currBufInfo.Allocation);
+            bufInfo.erase(bufInfo.begin() + indexToDestroy);
+        }
+    }
+
+    // Test double stack.
+    {
+        // Allocate number of buffers of varying size that surely fit into this block, alternate from bottom/top.
+        VkDeviceSize prevOffsetLower = 0;
+        VkDeviceSize prevOffsetUpper = poolCreateInfo.blockSize;
+        for(size_t i = 0; i < maxBufCount; ++i)
+        {
+            const bool upperAddress = (i % 2) != 0;
+            if(upperAddress)
+                allocCreateInfo.flags |= VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT;
+            else
+                allocCreateInfo.flags &= ~VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT;
+            bufCreateInfo.size = align_up<VkDeviceSize>(bufSizeMin + rand.Generate() % (bufSizeMax - bufSizeMin), 16);
+            BufferInfo newBufInfo;
+            res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo,
+                &newBufInfo.Buffer, &newBufInfo.Allocation, &allocInfo);
+            TEST(res == VK_SUCCESS);
+            if(upperAddress)
+            {
+                TEST(allocInfo.offset < prevOffsetUpper);
+                prevOffsetUpper = allocInfo.offset;
+            }
+            else
+            {
+                TEST(allocInfo.offset >= prevOffsetLower);
+                prevOffsetLower = allocInfo.offset;
+            }
+            TEST(prevOffsetLower < prevOffsetUpper);
+            bufInfo.push_back(newBufInfo);
+        }
+
+        // Destroy few buffers from top of the stack.
+        for(size_t i = 0; i < maxBufCount / 5; ++i)
+        {
+            const BufferInfo& currBufInfo = bufInfo.back();
+            vmaDestroyBuffer(g_hAllocator, currBufInfo.Buffer, currBufInfo.Allocation);
+            bufInfo.pop_back();
+        }
+
+        // Create some more
+        for(size_t i = 0; i < maxBufCount / 5; ++i)
+        {
+            const bool upperAddress = (i % 2) != 0;
+            if(upperAddress)
+                allocCreateInfo.flags |= VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT;
+            else
+                allocCreateInfo.flags &= ~VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT;
+            bufCreateInfo.size = align_up<VkDeviceSize>(bufSizeMin + rand.Generate() % (bufSizeMax - bufSizeMin), 16);
+            BufferInfo newBufInfo;
+            res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo,
+                &newBufInfo.Buffer, &newBufInfo.Allocation, &allocInfo);
+            TEST(res == VK_SUCCESS);
+            bufInfo.push_back(newBufInfo);
+        }
+
+        // Destroy the buffers in reverse order.
+        while(!bufInfo.empty())
+        {
+            const BufferInfo& currBufInfo = bufInfo.back();
+            vmaDestroyBuffer(g_hAllocator, currBufInfo.Buffer, currBufInfo.Allocation);
+            bufInfo.pop_back();
+        }
+
+        // Create buffers on both sides until we reach out of memory.
+        prevOffsetLower = 0;
+        prevOffsetUpper = poolCreateInfo.blockSize;
+        res = VK_SUCCESS;
+        for(size_t i = 0; res == VK_SUCCESS; ++i)
+        {
+            const bool upperAddress = (i % 2) != 0;
+            if(upperAddress)
+                allocCreateInfo.flags |= VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT;
+            else
+                allocCreateInfo.flags &= ~VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT;
+            bufCreateInfo.size = align_up<VkDeviceSize>(bufSizeMin + rand.Generate() % (bufSizeMax - bufSizeMin), 16);
+            BufferInfo newBufInfo;
+            res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo,
+                &newBufInfo.Buffer, &newBufInfo.Allocation, &allocInfo);
+            if(res == VK_SUCCESS)
+            {
+                if(upperAddress)
+                {
+                    TEST(allocInfo.offset < prevOffsetUpper);
+                    prevOffsetUpper = allocInfo.offset;
+                }
+                else
+                {
+                    TEST(allocInfo.offset >= prevOffsetLower);
+                    prevOffsetLower = allocInfo.offset;
+                }
+                TEST(prevOffsetLower < prevOffsetUpper);
+                bufInfo.push_back(newBufInfo);
+            }
+        }
+
+        // Destroy the buffers in random order.
+        while(!bufInfo.empty())
+        {
+            const size_t indexToDestroy = rand.Generate() % bufInfo.size();
+            const BufferInfo& currBufInfo = bufInfo[indexToDestroy];
+            vmaDestroyBuffer(g_hAllocator, currBufInfo.Buffer, currBufInfo.Allocation);
+            bufInfo.erase(bufInfo.begin() + indexToDestroy);
+        }
+
+        // Create buffers on upper side only, constant size, until we reach out of memory.
+        prevOffsetUpper = poolCreateInfo.blockSize;
+        res = VK_SUCCESS;
+        allocCreateInfo.flags |= VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT;
+        bufCreateInfo.size = bufSizeMax;
+        for(size_t i = 0; res == VK_SUCCESS; ++i)
+        {
+            BufferInfo newBufInfo;
+            res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo,
+                &newBufInfo.Buffer, &newBufInfo.Allocation, &allocInfo);
+            if(res == VK_SUCCESS)
+            {
+                TEST(allocInfo.offset < prevOffsetUpper);
+                prevOffsetUpper = allocInfo.offset;
+                bufInfo.push_back(newBufInfo);
+            }
+        }
+
+        // Destroy the buffers in reverse order.
+        while(!bufInfo.empty())
+        {
+            const BufferInfo& currBufInfo = bufInfo.back();
+            vmaDestroyBuffer(g_hAllocator, currBufInfo.Buffer, currBufInfo.Allocation);
+            bufInfo.pop_back();
+        }
+    }
+
+    // Test ring buffer with lost allocations.
+    {
+        // Allocate number of buffers until pool is full.
+        // Notice CAN_BECOME_LOST flag and call to vmaSetCurrentFrameIndex.
+        allocCreateInfo.flags = VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT;
+        res = VK_SUCCESS;
+        for(size_t i = 0; res == VK_SUCCESS; ++i)
+        {
+            vmaSetCurrentFrameIndex(g_hAllocator, ++g_FrameIndex);
+
+            bufCreateInfo.size = align_up<VkDeviceSize>(bufSizeMin + rand.Generate() % (bufSizeMax - bufSizeMin), 16);
+
+            BufferInfo newBufInfo;
+            res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo,
+                &newBufInfo.Buffer, &newBufInfo.Allocation, &allocInfo);
+            if(res == VK_SUCCESS)
+                bufInfo.push_back(newBufInfo);
+        }
+
+        // Free first half of it.
+        {
+            const size_t buffersToDelete = bufInfo.size() / 2;
+            for(size_t i = 0; i < buffersToDelete; ++i)
+            {
+                vmaDestroyBuffer(g_hAllocator, bufInfo[i].Buffer, bufInfo[i].Allocation);
+            }
+            bufInfo.erase(bufInfo.begin(), bufInfo.begin() + buffersToDelete);
+        }
+
+        // Allocate number of buffers until pool is full again.
+        // This way we make sure ring buffers wraps around, front in in the middle.
+        res = VK_SUCCESS;
+        for(size_t i = 0; res == VK_SUCCESS; ++i)
+        {
+            vmaSetCurrentFrameIndex(g_hAllocator, ++g_FrameIndex);
+
+            bufCreateInfo.size = align_up<VkDeviceSize>(bufSizeMin + rand.Generate() % (bufSizeMax - bufSizeMin), 16);
+
+            BufferInfo newBufInfo;
+            res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo,
+                &newBufInfo.Buffer, &newBufInfo.Allocation, &allocInfo);
+            if(res == VK_SUCCESS)
+                bufInfo.push_back(newBufInfo);
+        }
+
+        VkDeviceSize firstNewOffset;
+        {
+            vmaSetCurrentFrameIndex(g_hAllocator, ++g_FrameIndex);
+
+            // Allocate a large buffer with CAN_MAKE_OTHER_LOST.
+            allocCreateInfo.flags = VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT;
+            bufCreateInfo.size = bufSizeMax;
+
+            BufferInfo newBufInfo;
+            res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo,
+                &newBufInfo.Buffer, &newBufInfo.Allocation, &allocInfo);
+            TEST(res == VK_SUCCESS);
+            bufInfo.push_back(newBufInfo);
+            firstNewOffset = allocInfo.offset;
+
+            // Make sure at least one buffer from the beginning became lost.
+            vmaGetAllocationInfo(g_hAllocator, bufInfo[0].Allocation, &allocInfo);
+            TEST(allocInfo.deviceMemory == VK_NULL_HANDLE);
+        }
+
+#if 0 // TODO Fix and uncomment. Failing on Intel.
+        // Allocate more buffers that CAN_MAKE_OTHER_LOST until we wrap-around with this.
+        size_t newCount = 1;
+        for(;;)
+        {
+            vmaSetCurrentFrameIndex(g_hAllocator, ++g_FrameIndex);
+
+            bufCreateInfo.size = align_up<VkDeviceSize>(bufSizeMin + rand.Generate() % (bufSizeMax - bufSizeMin), 16);
+
+            BufferInfo newBufInfo;
+            res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo,
+                &newBufInfo.Buffer, &newBufInfo.Allocation, &allocInfo);
+
+            TEST(res == VK_SUCCESS);
+            bufInfo.push_back(newBufInfo);
+            ++newCount;
+            if(allocInfo.offset < firstNewOffset)
+                break;
+        }
+#endif
+
+        // Delete buffers that are lost.
+        for(size_t i = bufInfo.size(); i--; )
+        {
+            vmaGetAllocationInfo(g_hAllocator, bufInfo[i].Allocation, &allocInfo);
+            if(allocInfo.deviceMemory == VK_NULL_HANDLE)
+            {
+                vmaDestroyBuffer(g_hAllocator, bufInfo[i].Buffer, bufInfo[i].Allocation);
+                bufInfo.erase(bufInfo.begin() + i);
+            }
+        }
+
+        // Test vmaMakePoolAllocationsLost
+        {
+            vmaSetCurrentFrameIndex(g_hAllocator, ++g_FrameIndex);
+
+            size_t lostAllocCount = 0;
+            vmaMakePoolAllocationsLost(g_hAllocator, pool, &lostAllocCount);
+            TEST(lostAllocCount > 0);
+
+            size_t realLostAllocCount = 0;
+            for(size_t i = 0; i < bufInfo.size(); ++i)
+            {
+                vmaGetAllocationInfo(g_hAllocator, bufInfo[i].Allocation, &allocInfo);
+                if(allocInfo.deviceMemory == VK_NULL_HANDLE)
+                    ++realLostAllocCount;
+            }
+            TEST(realLostAllocCount == lostAllocCount);
+        }
+
+        // Destroy all the buffers in forward order.
+        for(size_t i = 0; i < bufInfo.size(); ++i)
+            vmaDestroyBuffer(g_hAllocator, bufInfo[i].Buffer, bufInfo[i].Allocation);
+        bufInfo.clear();
+    }
+
+    vmaDestroyPool(g_hAllocator, pool);
+}
+
+static void TestLinearAllocatorMultiBlock()
+{
+    wprintf(L"Test linear allocator multi block\n");
+
+    RandomNumberGenerator rand{345673};
+
+    VkBufferCreateInfo sampleBufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+    sampleBufCreateInfo.size = 1024 * 1024;
+    sampleBufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+
+    VmaAllocationCreateInfo sampleAllocCreateInfo = {};
+    sampleAllocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
+
+    VmaPoolCreateInfo poolCreateInfo = {};
+    poolCreateInfo.flags = VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT;
+    VkResult res = vmaFindMemoryTypeIndexForBufferInfo(g_hAllocator, &sampleBufCreateInfo, &sampleAllocCreateInfo, &poolCreateInfo.memoryTypeIndex);
+    TEST(res == VK_SUCCESS);
+
+    VmaPool pool = nullptr;
+    res = vmaCreatePool(g_hAllocator, &poolCreateInfo, &pool);
+    TEST(res == VK_SUCCESS);
+
+    VkBufferCreateInfo bufCreateInfo = sampleBufCreateInfo;
+
+    VmaAllocationCreateInfo allocCreateInfo = {};
+    allocCreateInfo.pool = pool;
+    
+    std::vector<BufferInfo> bufInfo;
+    VmaAllocationInfo allocInfo;
+
+    // Test one-time free.
+    {
+        // Allocate buffers until we move to a second block.
+        VkDeviceMemory lastMem = VK_NULL_HANDLE;
+        for(uint32_t i = 0; ; ++i)
+        {
+            BufferInfo newBufInfo;
+            res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo,
+                &newBufInfo.Buffer, &newBufInfo.Allocation, &allocInfo);
+            TEST(res == VK_SUCCESS);
+            bufInfo.push_back(newBufInfo);
+            if(lastMem && allocInfo.deviceMemory != lastMem)
+            {
+                break;
+            }
+            lastMem = allocInfo.deviceMemory;
+        }
+
+        TEST(bufInfo.size() > 2);
+
+        // Make sure that pool has now two blocks.
+        VmaPoolStats poolStats = {};
+        vmaGetPoolStats(g_hAllocator, pool, &poolStats);
+        TEST(poolStats.blockCount == 2);
+
+        // Destroy all the buffers in random order.
+        while(!bufInfo.empty())
+        {
+            const size_t indexToDestroy = rand.Generate() % bufInfo.size();
+            const BufferInfo& currBufInfo = bufInfo[indexToDestroy];
+            vmaDestroyBuffer(g_hAllocator, currBufInfo.Buffer, currBufInfo.Allocation);
+            bufInfo.erase(bufInfo.begin() + indexToDestroy);
+        }
+
+        // Make sure that pool has now at most one block.
+        vmaGetPoolStats(g_hAllocator, pool, &poolStats);
+        TEST(poolStats.blockCount <= 1);
+    }
+
+    // Test stack.
+    {
+        // Allocate buffers until we move to a second block.
+        VkDeviceMemory lastMem = VK_NULL_HANDLE;
+        for(uint32_t i = 0; ; ++i)
+        {
+            BufferInfo newBufInfo;
+            res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo,
+                &newBufInfo.Buffer, &newBufInfo.Allocation, &allocInfo);
+            TEST(res == VK_SUCCESS);
+            bufInfo.push_back(newBufInfo);
+            if(lastMem && allocInfo.deviceMemory != lastMem)
+            {
+                break;
+            }
+            lastMem = allocInfo.deviceMemory;
+        }
+
+        TEST(bufInfo.size() > 2);
+
+        // Add few more buffers.
+        for(uint32_t i = 0; i < 5; ++i)
+        {
+            BufferInfo newBufInfo;
+            res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo,
+                &newBufInfo.Buffer, &newBufInfo.Allocation, &allocInfo);
+            TEST(res == VK_SUCCESS);
+            bufInfo.push_back(newBufInfo);
+        }
+
+        // Make sure that pool has now two blocks.
+        VmaPoolStats poolStats = {};
+        vmaGetPoolStats(g_hAllocator, pool, &poolStats);
+        TEST(poolStats.blockCount == 2);
+        
+        // Delete half of buffers, LIFO.
+        for(size_t i = 0, countToDelete = bufInfo.size() / 2; i < countToDelete; ++i)
+        {
+            const BufferInfo& currBufInfo = bufInfo.back();
+            vmaDestroyBuffer(g_hAllocator, currBufInfo.Buffer, currBufInfo.Allocation);
+            bufInfo.pop_back();
+        }
+
+        // Add one more buffer.
+        BufferInfo newBufInfo;
+        res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo,
+            &newBufInfo.Buffer, &newBufInfo.Allocation, &allocInfo);
+        TEST(res == VK_SUCCESS);
+        bufInfo.push_back(newBufInfo);
+
+        // Make sure that pool has now one block.
+        vmaGetPoolStats(g_hAllocator, pool, &poolStats);
+        TEST(poolStats.blockCount == 1);
+
+        // Delete all the remaining buffers, LIFO.
+        while(!bufInfo.empty())
+        {
+            const BufferInfo& currBufInfo = bufInfo.back();
+            vmaDestroyBuffer(g_hAllocator, currBufInfo.Buffer, currBufInfo.Allocation);
+            bufInfo.pop_back();
+        }
+    }
+
+    vmaDestroyPool(g_hAllocator, pool);
+}
+
+static void ManuallyTestLinearAllocator()
+{
+    VmaStats origStats;
+    vmaCalculateStats(g_hAllocator, &origStats);
+
+    wprintf(L"Manually test linear allocator\n");
+
+    RandomNumberGenerator rand{645332};
+
+    VkBufferCreateInfo sampleBufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+    sampleBufCreateInfo.size = 1024; // Whatever.
+    sampleBufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
+
+    VmaAllocationCreateInfo sampleAllocCreateInfo = {};
+    sampleAllocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+
+    VmaPoolCreateInfo poolCreateInfo = {};
+    VkResult res = vmaFindMemoryTypeIndexForBufferInfo(g_hAllocator, &sampleBufCreateInfo, &sampleAllocCreateInfo, &poolCreateInfo.memoryTypeIndex);
+    TEST(res == VK_SUCCESS);
+
+    poolCreateInfo.blockSize = 10 * 1024;
+    poolCreateInfo.flags = VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT;
+    poolCreateInfo.minBlockCount = poolCreateInfo.maxBlockCount = 1;
+
+    VmaPool pool = nullptr;
+    res = vmaCreatePool(g_hAllocator, &poolCreateInfo, &pool);
+    TEST(res == VK_SUCCESS);
+
+    VkBufferCreateInfo bufCreateInfo = sampleBufCreateInfo;
+
+    VmaAllocationCreateInfo allocCreateInfo = {};
+    allocCreateInfo.pool = pool;
+
+    std::vector<BufferInfo> bufInfo;
+    VmaAllocationInfo allocInfo;
+    BufferInfo newBufInfo;
+
+    // Test double stack.
+    {
+        /*
+        Lower: Buffer 32 B, Buffer 1024 B, Buffer 32 B
+        Upper: Buffer 16 B, Buffer 1024 B, Buffer 128 B
+
+        Totally:
+        1 block allocated
+        10240 Vulkan bytes
+        6 new allocations
+        2256 bytes in allocations
+        */
+
+        bufCreateInfo.size = 32;
+        res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo,
+            &newBufInfo.Buffer, &newBufInfo.Allocation, &allocInfo);
+        TEST(res == VK_SUCCESS);
+        bufInfo.push_back(newBufInfo);
+
+        bufCreateInfo.size = 1024;
+        res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo,
+            &newBufInfo.Buffer, &newBufInfo.Allocation, &allocInfo);
+        TEST(res == VK_SUCCESS);
+        bufInfo.push_back(newBufInfo);
+
+        bufCreateInfo.size = 32;
+        res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo,
+            &newBufInfo.Buffer, &newBufInfo.Allocation, &allocInfo);
+        TEST(res == VK_SUCCESS);
+        bufInfo.push_back(newBufInfo);
+
+        allocCreateInfo.flags |= VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT;
+
+        bufCreateInfo.size = 128;
+        res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo,
+            &newBufInfo.Buffer, &newBufInfo.Allocation, &allocInfo);
+        TEST(res == VK_SUCCESS);
+        bufInfo.push_back(newBufInfo);
+
+        bufCreateInfo.size = 1024;
+        res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo,
+            &newBufInfo.Buffer, &newBufInfo.Allocation, &allocInfo);
+        TEST(res == VK_SUCCESS);
+        bufInfo.push_back(newBufInfo);
+
+        bufCreateInfo.size = 16;
+        res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo,
+            &newBufInfo.Buffer, &newBufInfo.Allocation, &allocInfo);
+        TEST(res == VK_SUCCESS);
+        bufInfo.push_back(newBufInfo);
+
+        VmaStats currStats;
+        vmaCalculateStats(g_hAllocator, &currStats);
+        VmaPoolStats poolStats;
+        vmaGetPoolStats(g_hAllocator, pool, &poolStats);
+
+        char* statsStr = nullptr;
+        vmaBuildStatsString(g_hAllocator, &statsStr, VK_TRUE);
+
+        // PUT BREAKPOINT HERE TO CHECK.
+        // Inspect: currStats versus origStats, poolStats, statsStr.
+        int I = 0;
+
+        vmaFreeStatsString(g_hAllocator, statsStr);
+
+        // Destroy the buffers in reverse order.
+        while(!bufInfo.empty())
+        {
+            const BufferInfo& currBufInfo = bufInfo.back();
+            vmaDestroyBuffer(g_hAllocator, currBufInfo.Buffer, currBufInfo.Allocation);
+            bufInfo.pop_back();
+        }
+    }
+
+    vmaDestroyPool(g_hAllocator, pool);
+}
+
+static void BenchmarkAlgorithmsCase(FILE* file,
+    uint32_t algorithm,
+    bool empty,
+    VmaAllocationCreateFlags allocStrategy,
+    FREE_ORDER freeOrder)
+{
+    RandomNumberGenerator rand{16223};
+
+    const VkDeviceSize bufSizeMin = 32;
+    const VkDeviceSize bufSizeMax = 1024;
+    const size_t maxBufCapacity = 10000;
+    const uint32_t iterationCount = 10;
+
+    VkBufferCreateInfo sampleBufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+    sampleBufCreateInfo.size = bufSizeMax;
+    sampleBufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
+
+    VmaAllocationCreateInfo sampleAllocCreateInfo = {};
+    sampleAllocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+
+    VmaPoolCreateInfo poolCreateInfo = {};
+    VkResult res = vmaFindMemoryTypeIndexForBufferInfo(g_hAllocator, &sampleBufCreateInfo, &sampleAllocCreateInfo, &poolCreateInfo.memoryTypeIndex);
+    TEST(res == VK_SUCCESS);
+
+    poolCreateInfo.blockSize = bufSizeMax * maxBufCapacity;
+    poolCreateInfo.flags |= algorithm;
+    poolCreateInfo.minBlockCount = poolCreateInfo.maxBlockCount = 1;
+
+    VmaPool pool = nullptr;
+    res = vmaCreatePool(g_hAllocator, &poolCreateInfo, &pool);
+    TEST(res == VK_SUCCESS);
+
+    // Buffer created just to get memory requirements. Never bound to any memory.
+    VkBuffer dummyBuffer = VK_NULL_HANDLE;
+    res = vkCreateBuffer(g_hDevice, &sampleBufCreateInfo, g_Allocs, &dummyBuffer);
+    TEST(res == VK_SUCCESS && dummyBuffer);
+
+    VkMemoryRequirements memReq = {};
+    vkGetBufferMemoryRequirements(g_hDevice, dummyBuffer, &memReq);
+
+    vkDestroyBuffer(g_hDevice, dummyBuffer, g_Allocs);
+
+    VmaAllocationCreateInfo allocCreateInfo = {};
+    allocCreateInfo.pool = pool;
+    allocCreateInfo.flags = allocStrategy;
+
+    VmaAllocation alloc;
+    std::vector<VmaAllocation> baseAllocations;
+
+    if(!empty)
+    {
+        // Make allocations up to 1/3 of pool size.
+        VkDeviceSize totalSize = 0;
+        while(totalSize < poolCreateInfo.blockSize / 3)
+        {
+            // This test intentionally allows sizes that are aligned to 4 or 16 bytes.
+            // This is theoretically allowed and already uncovered one bug.
+            memReq.size = bufSizeMin + rand.Generate() % (bufSizeMax - bufSizeMin);
+            res = vmaAllocateMemory(g_hAllocator, &memReq, &allocCreateInfo, &alloc, nullptr);
+            TEST(res == VK_SUCCESS);
+            baseAllocations.push_back(alloc);
+            totalSize += memReq.size;
+        }
+
+        // Delete half of them, choose randomly.
+        size_t allocsToDelete = baseAllocations.size() / 2;
+        for(size_t i = 0; i < allocsToDelete; ++i)
+        {
+            const size_t index = (size_t)rand.Generate() % baseAllocations.size();
+            vmaFreeMemory(g_hAllocator, baseAllocations[index]);
+            baseAllocations.erase(baseAllocations.begin() + index);
+        }
+    }
+
+    // BENCHMARK
+    const size_t allocCount = maxBufCapacity / 3;
+    std::vector<VmaAllocation> testAllocations;
+    testAllocations.reserve(allocCount);
+    duration allocTotalDuration = duration::zero();
+    duration freeTotalDuration = duration::zero();
+    for(uint32_t iterationIndex = 0; iterationIndex < iterationCount; ++iterationIndex)
+    {
+        // Allocations
+        time_point allocTimeBeg = std::chrono::high_resolution_clock::now();
+        for(size_t i = 0; i < allocCount; ++i)
+        {
+            memReq.size = bufSizeMin + rand.Generate() % (bufSizeMax - bufSizeMin);
+            res = vmaAllocateMemory(g_hAllocator, &memReq, &allocCreateInfo, &alloc, nullptr);
+            TEST(res == VK_SUCCESS);
+            testAllocations.push_back(alloc);
+        }
+        allocTotalDuration += std::chrono::high_resolution_clock::now() - allocTimeBeg;
+
+        // Deallocations
+        switch(freeOrder)
+        {
+        case FREE_ORDER::FORWARD:
+            // Leave testAllocations unchanged.
+            break;
+        case FREE_ORDER::BACKWARD:
+            std::reverse(testAllocations.begin(), testAllocations.end());
+            break;
+        case FREE_ORDER::RANDOM:
+            std::shuffle(testAllocations.begin(), testAllocations.end(), MyUniformRandomNumberGenerator(rand));
+            break;
+        default: assert(0);
+        }
+
+        time_point freeTimeBeg = std::chrono::high_resolution_clock::now();
+        for(size_t i = 0; i < allocCount; ++i)
+            vmaFreeMemory(g_hAllocator, testAllocations[i]);
+        freeTotalDuration += std::chrono::high_resolution_clock::now() - freeTimeBeg;
+
+        testAllocations.clear();
+    }
+
+    // Delete baseAllocations
+    while(!baseAllocations.empty())
+    {
+        vmaFreeMemory(g_hAllocator, baseAllocations.back());
+        baseAllocations.pop_back();
+    }
+
+    vmaDestroyPool(g_hAllocator, pool);
+
+    const float allocTotalSeconds = ToFloatSeconds(allocTotalDuration);
+    const float freeTotalSeconds  = ToFloatSeconds(freeTotalDuration);
+
+    printf("    Algorithm=%s %s Allocation=%s FreeOrder=%s: allocations %g s, free %g s\n",
+        AlgorithmToStr(algorithm),
+        empty ? "Empty" : "Not empty",
+        GetAllocationStrategyName(allocStrategy),
+        FREE_ORDER_NAMES[(size_t)freeOrder],
+        allocTotalSeconds,
+        freeTotalSeconds);
+
+    if(file)
+    {
+        std::string currTime;
+        CurrentTimeToStr(currTime);
+
+        fprintf(file, "%s,%s,%s,%u,%s,%s,%g,%g\n",
+            CODE_DESCRIPTION, currTime.c_str(),
+            AlgorithmToStr(algorithm),
+            empty ? 1 : 0,
+            GetAllocationStrategyName(allocStrategy),
+            FREE_ORDER_NAMES[(uint32_t)freeOrder],
+            allocTotalSeconds,
+            freeTotalSeconds);
+    }
+}
+
+static void TestBufferDeviceAddress()
+{
+    wprintf(L"Test buffer device address\n");
+
+    assert(g_BufferDeviceAddressEnabled);
+
+    VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+    bufCreateInfo.size = 0x10000;
+    bufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
+        VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; // !!!
+
+    VmaAllocationCreateInfo allocCreateInfo = {};
+    allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+
+    for(uint32_t testIndex = 0; testIndex < 2; ++testIndex)
+    {
+        // 1st is placed, 2nd is dedicated.
+        if(testIndex == 1)
+            allocCreateInfo.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
+
+        BufferInfo bufInfo = {};
+        VkResult res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo,
+            &bufInfo.Buffer, &bufInfo.Allocation, nullptr);
+        TEST(res == VK_SUCCESS);
+
+        VkBufferDeviceAddressInfoEXT bufferDeviceAddressInfo = { VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO_EXT };
+        bufferDeviceAddressInfo.buffer = bufInfo.Buffer;
+        //assert(g_vkGetBufferDeviceAddressEXT != nullptr);
+        if(g_vkGetBufferDeviceAddressEXT != nullptr)
+        {
+            VkDeviceAddress addr = g_vkGetBufferDeviceAddressEXT(g_hDevice, &bufferDeviceAddressInfo);
+            TEST(addr != 0);
+        }
+
+        vmaDestroyBuffer(g_hAllocator, bufInfo.Buffer, bufInfo.Allocation);
+    }
+}
+
+static void BenchmarkAlgorithms(FILE* file)
+{
+    wprintf(L"Benchmark algorithms\n");
+
+    if(file)
+    {
+        fprintf(file,
+            "Code,Time,"
+            "Algorithm,Empty,Allocation strategy,Free order,"
+            "Allocation time (s),Deallocation time (s)\n");
+    }
+
+    uint32_t freeOrderCount = 1;
+    if(ConfigType >= CONFIG_TYPE::CONFIG_TYPE_LARGE)
+        freeOrderCount = 3;
+    else if(ConfigType >= CONFIG_TYPE::CONFIG_TYPE_SMALL)
+        freeOrderCount = 2;
+
+    const uint32_t emptyCount = ConfigType >= CONFIG_TYPE::CONFIG_TYPE_SMALL ? 2 : 1;
+    const uint32_t allocStrategyCount = GetAllocationStrategyCount();
+
+    for(uint32_t freeOrderIndex = 0; freeOrderIndex < freeOrderCount; ++freeOrderIndex)
+    {
+        FREE_ORDER freeOrder = FREE_ORDER::COUNT;
+        switch(freeOrderIndex)
+        {
+        case 0: freeOrder = FREE_ORDER::BACKWARD; break;
+        case 1: freeOrder = FREE_ORDER::FORWARD; break;
+        case 2: freeOrder = FREE_ORDER::RANDOM; break;
+        default: assert(0);
+        }
+
+        for(uint32_t emptyIndex = 0; emptyIndex < emptyCount; ++emptyIndex)
+        {
+            for(uint32_t algorithmIndex = 0; algorithmIndex < 3; ++algorithmIndex)
+            {
+                uint32_t algorithm = 0;
+                switch(algorithmIndex)
+                {
+                case 0:
+                    break;
+                case 1:
+                    algorithm = VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT;
+                    break;
+                case 2:
+                    algorithm = VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT;
+                    break;
+                default:
+                    assert(0);
+                }
+
+                uint32_t currAllocStrategyCount = algorithm != 0 ? 1 : allocStrategyCount;
+                for(uint32_t allocStrategyIndex = 0; allocStrategyIndex < currAllocStrategyCount; ++allocStrategyIndex)
+                {
+                    VmaAllocatorCreateFlags strategy = 0;
+                    if(currAllocStrategyCount > 1)
+                    {
+                        switch(allocStrategyIndex)
+                        {
+                        case 0: strategy = VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT; break;
+                        case 1: strategy = VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT; break;
+                        case 2: strategy = VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT; break;
+                        default: assert(0);
+                        }
+                    }
+
+                    BenchmarkAlgorithmsCase(
+                        file,
+                        algorithm,
+                        (emptyIndex == 0), // empty
+                        strategy,
+                        freeOrder); // freeOrder
+                }
+            }
+        }
+    }
+}
+
+static void TestPool_SameSize()
+{
+    const VkDeviceSize BUF_SIZE = 1024 * 1024;
+    const size_t BUF_COUNT = 100;
+    VkResult res;
+
+    RandomNumberGenerator rand{123};
+
+    VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+    bufferInfo.size = BUF_SIZE;
+    bufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+
+    uint32_t memoryTypeBits = UINT32_MAX;
+    {
+        VkBuffer dummyBuffer;
+        res = vkCreateBuffer(g_hDevice, &bufferInfo, g_Allocs, &dummyBuffer);
+        TEST(res == VK_SUCCESS);
+
+        VkMemoryRequirements memReq;
+        vkGetBufferMemoryRequirements(g_hDevice, dummyBuffer, &memReq);
+        memoryTypeBits = memReq.memoryTypeBits;
+
+        vkDestroyBuffer(g_hDevice, dummyBuffer, g_Allocs);
+    }
+
+    VmaAllocationCreateInfo poolAllocInfo = {};
+    poolAllocInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
+    uint32_t memTypeIndex;
+    res = vmaFindMemoryTypeIndex(
+        g_hAllocator,
+        memoryTypeBits,
+        &poolAllocInfo,
+        &memTypeIndex);
+
+    VmaPoolCreateInfo poolCreateInfo = {};
+    poolCreateInfo.memoryTypeIndex = memTypeIndex;
+    poolCreateInfo.blockSize = BUF_SIZE * BUF_COUNT / 4;
+    poolCreateInfo.minBlockCount = 1;
+    poolCreateInfo.maxBlockCount = 4;
+    poolCreateInfo.frameInUseCount = 0;
+
+    VmaPool pool;
+    res = vmaCreatePool(g_hAllocator, &poolCreateInfo, &pool);
+    TEST(res == VK_SUCCESS);
+
+    // Test pool name
+    {
+        static const char* const POOL_NAME = "Pool name";
+        vmaSetPoolName(g_hAllocator, pool, POOL_NAME);
+
+        const char* fetchedPoolName = nullptr;
+        vmaGetPoolName(g_hAllocator, pool, &fetchedPoolName);
+        TEST(strcmp(fetchedPoolName, POOL_NAME) == 0);
+
+        vmaSetPoolName(g_hAllocator, pool, nullptr);
+    }
+
+    vmaSetCurrentFrameIndex(g_hAllocator, 1);
+
+    VmaAllocationCreateInfo allocInfo = {};
+    allocInfo.pool = pool;
+    allocInfo.flags = VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT |
+        VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT;
+
+    struct BufItem
+    {
+        VkBuffer Buf;
+        VmaAllocation Alloc;
+    };
+    std::vector<BufItem> items;
+
+    // Fill entire pool.
+    for(size_t i = 0; i < BUF_COUNT; ++i)
+    {
+        BufItem item;
+        res = vmaCreateBuffer(g_hAllocator, &bufferInfo, &allocInfo, &item.Buf, &item.Alloc, nullptr);
+        TEST(res == VK_SUCCESS);
+        items.push_back(item);
+    }
+
+    // Make sure that another allocation would fail.
+    {
+        BufItem item;
+        res = vmaCreateBuffer(g_hAllocator, &bufferInfo, &allocInfo, &item.Buf, &item.Alloc, nullptr);
+        TEST(res == VK_ERROR_OUT_OF_DEVICE_MEMORY);
+    }
+
+    // Validate that no buffer is lost. Also check that they are not mapped.
+    for(size_t i = 0; i < items.size(); ++i)
+    {
+        VmaAllocationInfo allocInfo;
+        vmaGetAllocationInfo(g_hAllocator, items[i].Alloc, &allocInfo);
+        TEST(allocInfo.deviceMemory != VK_NULL_HANDLE);
+        TEST(allocInfo.pMappedData == nullptr);
+    }
+
+    // Free some percent of random items.
+    {
+        const size_t PERCENT_TO_FREE = 10;
+        size_t itemsToFree = items.size() * PERCENT_TO_FREE / 100;
+        for(size_t i = 0; i < itemsToFree; ++i)
+        {
+            size_t index = (size_t)rand.Generate() % items.size();
+            vmaDestroyBuffer(g_hAllocator, items[index].Buf, items[index].Alloc);
+            items.erase(items.begin() + index);
+        }
+    }
+
+    // Randomly allocate and free items.
+    {
+        const size_t OPERATION_COUNT = BUF_COUNT;
+        for(size_t i = 0; i < OPERATION_COUNT; ++i)
+        {
+            bool allocate = rand.Generate() % 2 != 0;
+            if(allocate)
+            {
+                if(items.size() < BUF_COUNT)
+                {
+                    BufItem item;
+                    res = vmaCreateBuffer(g_hAllocator, &bufferInfo, &allocInfo, &item.Buf, &item.Alloc, nullptr);
+                    TEST(res == VK_SUCCESS);
+                    items.push_back(item);
+               }
+            }
+            else // Free
+            {
+                if(!items.empty())
+                {
+                    size_t index = (size_t)rand.Generate() % items.size();
+                    vmaDestroyBuffer(g_hAllocator, items[index].Buf, items[index].Alloc);
+                    items.erase(items.begin() + index);
+                }
+            }
+        }
+    }
+
+    // Allocate up to maximum.
+    while(items.size() < BUF_COUNT)
+    {
+        BufItem item;
+        res = vmaCreateBuffer(g_hAllocator, &bufferInfo, &allocInfo, &item.Buf, &item.Alloc, nullptr);
+        TEST(res == VK_SUCCESS);
+        items.push_back(item);
+    }
+
+    // Validate that no buffer is lost.
+    for(size_t i = 0; i < items.size(); ++i)
+    {
+        VmaAllocationInfo allocInfo;
+        vmaGetAllocationInfo(g_hAllocator, items[i].Alloc, &allocInfo);
+        TEST(allocInfo.deviceMemory != VK_NULL_HANDLE);
+    }
+    
+    // Next frame.
+    vmaSetCurrentFrameIndex(g_hAllocator, 2);
+
+    // Allocate another BUF_COUNT buffers.
+    for(size_t i = 0; i < BUF_COUNT; ++i)
+    {
+        BufItem item;
+        res = vmaCreateBuffer(g_hAllocator, &bufferInfo, &allocInfo, &item.Buf, &item.Alloc, nullptr);
+        TEST(res == VK_SUCCESS);
+        items.push_back(item);
+    }
+
+    // Make sure the first BUF_COUNT is lost. Delete them.
+    for(size_t i = 0; i < BUF_COUNT; ++i)
+    {
+        VmaAllocationInfo allocInfo;
+        vmaGetAllocationInfo(g_hAllocator, items[i].Alloc, &allocInfo);
+        TEST(allocInfo.deviceMemory == VK_NULL_HANDLE);
+        vmaDestroyBuffer(g_hAllocator, items[i].Buf, items[i].Alloc);
+    }
+    items.erase(items.begin(), items.begin() + BUF_COUNT);
+
+    // Validate that no buffer is lost.
+    for(size_t i = 0; i < items.size(); ++i)
+    {
+        VmaAllocationInfo allocInfo;
+        vmaGetAllocationInfo(g_hAllocator, items[i].Alloc, &allocInfo);
+        TEST(allocInfo.deviceMemory != VK_NULL_HANDLE);
+    }
+
+    // Free one item.
+    vmaDestroyBuffer(g_hAllocator, items.back().Buf, items.back().Alloc);
+    items.pop_back();
+
+    // Validate statistics.
+    {
+        VmaPoolStats poolStats = {};
+        vmaGetPoolStats(g_hAllocator, pool, &poolStats);
+        TEST(poolStats.allocationCount == items.size());
+        TEST(poolStats.size = BUF_COUNT * BUF_SIZE);
+        TEST(poolStats.unusedRangeCount == 1);
+        TEST(poolStats.unusedRangeSizeMax == BUF_SIZE);
+        TEST(poolStats.unusedSize == BUF_SIZE);
+    }
+
+    // Free all remaining items.
+    for(size_t i = items.size(); i--; )
+        vmaDestroyBuffer(g_hAllocator, items[i].Buf, items[i].Alloc);
+    items.clear();
+
+    // Allocate maximum items again.
+    for(size_t i = 0; i < BUF_COUNT; ++i)
+    {
+        BufItem item;
+        res = vmaCreateBuffer(g_hAllocator, &bufferInfo, &allocInfo, &item.Buf, &item.Alloc, nullptr);
+        TEST(res == VK_SUCCESS);
+        items.push_back(item);
+    }
+
+    // Delete every other item.
+    for(size_t i = 0; i < BUF_COUNT / 2; ++i)
+    {
+        vmaDestroyBuffer(g_hAllocator, items[i].Buf, items[i].Alloc);
+        items.erase(items.begin() + i);
+    }
+
+    // Defragment!
+    {
+        std::vector<VmaAllocation> allocationsToDefragment(items.size());
+        for(size_t i = 0; i < items.size(); ++i)
+            allocationsToDefragment[i] = items[i].Alloc;
+
+        VmaDefragmentationStats defragmentationStats;
+        res = vmaDefragment(g_hAllocator, allocationsToDefragment.data(), items.size(), nullptr, nullptr, &defragmentationStats);
+        TEST(res == VK_SUCCESS);
+        TEST(defragmentationStats.deviceMemoryBlocksFreed == 2);
+    }
+
+    // Free all remaining items.
+    for(size_t i = items.size(); i--; )
+        vmaDestroyBuffer(g_hAllocator, items[i].Buf, items[i].Alloc);
+    items.clear();
+
+    ////////////////////////////////////////////////////////////////////////////////
+    // Test for vmaMakePoolAllocationsLost
+
+    // Allocate 4 buffers on frame 10.
+    vmaSetCurrentFrameIndex(g_hAllocator, 10);
+    for(size_t i = 0; i < 4; ++i)
+    {
+        BufItem item;
+        res = vmaCreateBuffer(g_hAllocator, &bufferInfo, &allocInfo, &item.Buf, &item.Alloc, nullptr);
+        TEST(res == VK_SUCCESS);
+        items.push_back(item);
+    }
+
+    // Touch first 2 of them on frame 11.
+    vmaSetCurrentFrameIndex(g_hAllocator, 11);
+    for(size_t i = 0; i < 2; ++i)
+    {
+        VmaAllocationInfo allocInfo;
+        vmaGetAllocationInfo(g_hAllocator, items[i].Alloc, &allocInfo);
+    }
+
+    // vmaMakePoolAllocationsLost. Only remaining 2 should be lost.
+    size_t lostCount = 0xDEADC0DE;
+    vmaMakePoolAllocationsLost(g_hAllocator, pool, &lostCount);
+    TEST(lostCount == 2);
+
+    // Make another call. Now 0 should be lost.
+    vmaMakePoolAllocationsLost(g_hAllocator, pool, &lostCount);
+    TEST(lostCount == 0);
+
+    // Make another call, with null count. Should not crash.
+    vmaMakePoolAllocationsLost(g_hAllocator, pool, nullptr);
+
+    // END: Free all remaining items.
+    for(size_t i = items.size(); i--; )
+        vmaDestroyBuffer(g_hAllocator, items[i].Buf, items[i].Alloc);
+
+    items.clear();
+
+    ////////////////////////////////////////////////////////////////////////////////
+    // Test for allocation too large for pool
+
+    {
+        VmaAllocationCreateInfo allocCreateInfo = {};
+        allocCreateInfo.pool = pool;
+
+        VkMemoryRequirements memReq;
+        memReq.memoryTypeBits = UINT32_MAX;
+        memReq.alignment = 1;
+        memReq.size = poolCreateInfo.blockSize + 4;
+        
+        VmaAllocation alloc = nullptr;
+        res = vmaAllocateMemory(g_hAllocator, &memReq, &allocCreateInfo, &alloc, nullptr);
+        TEST(res == VK_ERROR_OUT_OF_DEVICE_MEMORY && alloc == nullptr);
+    }
+
+    vmaDestroyPool(g_hAllocator, pool);
+}
+
+static bool ValidatePattern(const void* pMemory, size_t size, uint8_t pattern)
+{
+    const uint8_t* pBytes = (const uint8_t*)pMemory;
+    for(size_t i = 0; i < size; ++i)
+    {
+        if(pBytes[i] != pattern)
+        {
+            return false;
+        }
+    }
+    return true;
+}
+
+static void TestAllocationsInitialization()
+{
+    VkResult res;
+
+    const size_t BUF_SIZE = 1024;
+
+    // Create pool.
+
+    VkBufferCreateInfo bufInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+    bufInfo.size = BUF_SIZE;
+    bufInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+
+    VmaAllocationCreateInfo dummyBufAllocCreateInfo = {};
+    dummyBufAllocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
+
+    VmaPoolCreateInfo poolCreateInfo = {};
+    poolCreateInfo.blockSize = BUF_SIZE * 10;
+    poolCreateInfo.minBlockCount = 1; // To keep memory alive while pool exists.
+    poolCreateInfo.maxBlockCount = 1;
+    res = vmaFindMemoryTypeIndexForBufferInfo(g_hAllocator, &bufInfo, &dummyBufAllocCreateInfo, &poolCreateInfo.memoryTypeIndex);
+    TEST(res == VK_SUCCESS);
+
+    VmaAllocationCreateInfo bufAllocCreateInfo = {};
+    res = vmaCreatePool(g_hAllocator, &poolCreateInfo, &bufAllocCreateInfo.pool);
+    TEST(res == VK_SUCCESS);
+
+    // Create one persistently mapped buffer to keep memory of this block mapped,
+    // so that pointer to mapped data will remain (more or less...) valid even
+    // after destruction of other allocations.
+    
+    bufAllocCreateInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
+    VkBuffer firstBuf;
+    VmaAllocation firstAlloc;
+    res = vmaCreateBuffer(g_hAllocator, &bufInfo, &bufAllocCreateInfo, &firstBuf, &firstAlloc, nullptr);
+    TEST(res == VK_SUCCESS);
+
+    // Test buffers.
+
+    for(uint32_t i = 0; i < 2; ++i)
+    {
+        const bool persistentlyMapped = i == 0;
+        bufAllocCreateInfo.flags = persistentlyMapped ? VMA_ALLOCATION_CREATE_MAPPED_BIT : 0;
+        VkBuffer buf;
+        VmaAllocation alloc;
+        VmaAllocationInfo allocInfo;
+        res = vmaCreateBuffer(g_hAllocator, &bufInfo, &bufAllocCreateInfo, &buf, &alloc, &allocInfo);
+        TEST(res == VK_SUCCESS);
+
+        void* pMappedData;
+        if(!persistentlyMapped)
+        {
+            res = vmaMapMemory(g_hAllocator, alloc, &pMappedData);
+            TEST(res == VK_SUCCESS);
+        }
+        else
+        {
+            pMappedData = allocInfo.pMappedData;
+        }
+
+        // Validate initialized content
+        bool valid = ValidatePattern(pMappedData, BUF_SIZE, 0xDC);
+        TEST(valid);
+
+        if(!persistentlyMapped)
+        {
+            vmaUnmapMemory(g_hAllocator, alloc);
+        }
+
+        vmaDestroyBuffer(g_hAllocator, buf, alloc);
+
+        // Validate freed content
+        valid = ValidatePattern(pMappedData, BUF_SIZE, 0xEF);
+        TEST(valid);
+    }
+
+    vmaDestroyBuffer(g_hAllocator, firstBuf, firstAlloc);
+    vmaDestroyPool(g_hAllocator, bufAllocCreateInfo.pool);
+}
+
+static void TestPool_Benchmark(
+    PoolTestResult& outResult,
+    const PoolTestConfig& config)
+{
+    TEST(config.ThreadCount > 0);
+
+    RandomNumberGenerator mainRand{config.RandSeed};
+
+    uint32_t allocationSizeProbabilitySum = std::accumulate(
+        config.AllocationSizes.begin(),
+        config.AllocationSizes.end(),
+        0u,
+        [](uint32_t sum, const AllocationSize& allocSize) {
+            return sum + allocSize.Probability;
+        });
+
+    VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+    bufferInfo.size = 256; // Whatever.
+    bufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+
+    VkImageCreateInfo imageInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
+    imageInfo.imageType = VK_IMAGE_TYPE_2D;
+    imageInfo.extent.width = 256; // Whatever.
+    imageInfo.extent.height = 256; // Whatever.
+    imageInfo.extent.depth = 1;
+    imageInfo.mipLevels = 1;
+    imageInfo.arrayLayers = 1;
+    imageInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
+    imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL; // LINEAR if CPU memory.
+    imageInfo.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
+    imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; // TRANSFER_SRC if CPU memory.
+    imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
+
+    uint32_t bufferMemoryTypeBits = UINT32_MAX;
+    {
+        VkBuffer dummyBuffer;
+        VkResult res = vkCreateBuffer(g_hDevice, &bufferInfo, g_Allocs, &dummyBuffer);
+        TEST(res == VK_SUCCESS);
+
+        VkMemoryRequirements memReq;
+        vkGetBufferMemoryRequirements(g_hDevice, dummyBuffer, &memReq);
+        bufferMemoryTypeBits = memReq.memoryTypeBits;
+
+        vkDestroyBuffer(g_hDevice, dummyBuffer, g_Allocs);
+    }
+
+    uint32_t imageMemoryTypeBits = UINT32_MAX;
+    {
+        VkImage dummyImage;
+        VkResult res = vkCreateImage(g_hDevice, &imageInfo, g_Allocs, &dummyImage);
+        TEST(res == VK_SUCCESS);
+
+        VkMemoryRequirements memReq;
+        vkGetImageMemoryRequirements(g_hDevice, dummyImage, &memReq);
+        imageMemoryTypeBits = memReq.memoryTypeBits;
+
+        vkDestroyImage(g_hDevice, dummyImage, g_Allocs);
+    }
+
+    uint32_t memoryTypeBits = 0;
+    if(config.UsesBuffers() && config.UsesImages())
+    {
+        memoryTypeBits = bufferMemoryTypeBits & imageMemoryTypeBits;
+        if(memoryTypeBits == 0)
+        {
+            PrintWarning(L"Cannot test buffers + images in the same memory pool on this GPU.");
+            return;
+        }
+    }
+    else if(config.UsesBuffers())
+        memoryTypeBits = bufferMemoryTypeBits;
+    else if(config.UsesImages())
+        memoryTypeBits = imageMemoryTypeBits;
+    else
+        TEST(0);
+
+    VmaPoolCreateInfo poolCreateInfo = {};
+    poolCreateInfo.memoryTypeIndex = 0;
+    poolCreateInfo.minBlockCount = 1;
+    poolCreateInfo.maxBlockCount = 1;
+    poolCreateInfo.blockSize = config.PoolSize;
+    poolCreateInfo.frameInUseCount = 1;
+
+    VmaAllocationCreateInfo dummyAllocCreateInfo = {};
+    dummyAllocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+    vmaFindMemoryTypeIndex(g_hAllocator, memoryTypeBits, &dummyAllocCreateInfo, &poolCreateInfo.memoryTypeIndex);
+
+    VmaPool pool;
+    VkResult res = vmaCreatePool(g_hAllocator, &poolCreateInfo, &pool);
+    TEST(res == VK_SUCCESS);
+
+    // Start time measurement - after creating pool and initializing data structures.
+    time_point timeBeg = std::chrono::high_resolution_clock::now();
+
+    ////////////////////////////////////////////////////////////////////////////////
+    // ThreadProc
+    auto ThreadProc = [&](
+        PoolTestThreadResult* outThreadResult,
+        uint32_t randSeed,
+        HANDLE frameStartEvent,
+        HANDLE frameEndEvent) -> void
+    {
+        RandomNumberGenerator threadRand{randSeed};
+
+        outThreadResult->AllocationTimeMin = duration::max();
+        outThreadResult->AllocationTimeSum = duration::zero();
+        outThreadResult->AllocationTimeMax = duration::min();
+        outThreadResult->DeallocationTimeMin = duration::max();
+        outThreadResult->DeallocationTimeSum = duration::zero();
+        outThreadResult->DeallocationTimeMax = duration::min();
+        outThreadResult->AllocationCount = 0;
+        outThreadResult->DeallocationCount = 0;
+        outThreadResult->LostAllocationCount = 0;
+        outThreadResult->LostAllocationTotalSize = 0;
+        outThreadResult->FailedAllocationCount = 0;
+        outThreadResult->FailedAllocationTotalSize = 0;
+
+        struct Item
+        {
+            VkDeviceSize BufferSize;
+            VkExtent2D ImageSize;
+            VkBuffer Buf;
+            VkImage Image;
+            VmaAllocation Alloc;
+            
+            VkDeviceSize CalcSizeBytes() const
+            {
+                return BufferSize +
+                    ImageSize.width * ImageSize.height * 4;
+            }
+        };
+        std::vector<Item> unusedItems, usedItems;
+
+        const size_t threadTotalItemCount = config.TotalItemCount / config.ThreadCount;
+
+        // Create all items - all unused, not yet allocated.
+        for(size_t i = 0; i < threadTotalItemCount; ++i)
+        {
+            Item item = {};
+
+            uint32_t allocSizeIndex = 0;
+            uint32_t r = threadRand.Generate() % allocationSizeProbabilitySum;
+            while(r >= config.AllocationSizes[allocSizeIndex].Probability)
+                r -= config.AllocationSizes[allocSizeIndex++].Probability;
+
+            const AllocationSize& allocSize = config.AllocationSizes[allocSizeIndex];
+            if(allocSize.BufferSizeMax > 0)
+            {
+                TEST(allocSize.BufferSizeMin > 0);
+                TEST(allocSize.ImageSizeMin == 0 && allocSize.ImageSizeMax == 0);
+                if(allocSize.BufferSizeMax == allocSize.BufferSizeMin)
+                    item.BufferSize = allocSize.BufferSizeMin;
+                else
+                {
+                    item.BufferSize = allocSize.BufferSizeMin + threadRand.Generate() % (allocSize.BufferSizeMax - allocSize.BufferSizeMin);
+                    item.BufferSize = item.BufferSize / 16 * 16;
+                }
+            }
+            else
+            {
+                TEST(allocSize.ImageSizeMin > 0 && allocSize.ImageSizeMax > 0);
+                if(allocSize.ImageSizeMax == allocSize.ImageSizeMin)
+                    item.ImageSize.width = item.ImageSize.height = allocSize.ImageSizeMax;
+                else
+                {
+                    item.ImageSize.width  = allocSize.ImageSizeMin + threadRand.Generate() % (allocSize.ImageSizeMax - allocSize.ImageSizeMin);
+                    item.ImageSize.height = allocSize.ImageSizeMin + threadRand.Generate() % (allocSize.ImageSizeMax - allocSize.ImageSizeMin);
+                }
+            }
+
+            unusedItems.push_back(item);
+        }
+
+        auto Allocate = [&](Item& item) -> VkResult
+        {
+            VmaAllocationCreateInfo allocCreateInfo = {};
+            allocCreateInfo.pool = pool;
+            allocCreateInfo.flags = VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT |
+                VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT;
+
+            if(item.BufferSize)
+            {
+                bufferInfo.size = item.BufferSize;
+                PoolAllocationTimeRegisterObj timeRegisterObj(*outThreadResult);
+                return vmaCreateBuffer(g_hAllocator, &bufferInfo, &allocCreateInfo, &item.Buf, &item.Alloc, nullptr);
+            }
+            else
+            {
+                TEST(item.ImageSize.width && item.ImageSize.height);
+
+                imageInfo.extent.width = item.ImageSize.width;
+                imageInfo.extent.height = item.ImageSize.height;
+                PoolAllocationTimeRegisterObj timeRegisterObj(*outThreadResult);
+                return vmaCreateImage(g_hAllocator, &imageInfo, &allocCreateInfo, &item.Image, &item.Alloc, nullptr);
+            }
+        };
+
+        ////////////////////////////////////////////////////////////////////////////////
+        // Frames
+        for(uint32_t frameIndex = 0; frameIndex < config.FrameCount; ++frameIndex)
+        {
+            WaitForSingleObject(frameStartEvent, INFINITE);
+
+            // Always make some percent of used bufs unused, to choose different used ones.
+            const size_t bufsToMakeUnused = usedItems.size() * config.ItemsToMakeUnusedPercent / 100;
+            for(size_t i = 0; i < bufsToMakeUnused; ++i)
+            {
+                size_t index = threadRand.Generate() % usedItems.size();
+                unusedItems.push_back(usedItems[index]);
+                usedItems.erase(usedItems.begin() + index);
+            }
+
+            // Determine which bufs we want to use in this frame.
+            const size_t usedBufCount = (threadRand.Generate() % (config.UsedItemCountMax - config.UsedItemCountMin) + config.UsedItemCountMin)
+                / config.ThreadCount;
+            TEST(usedBufCount < usedItems.size() + unusedItems.size());
+            // Move some used to unused.
+            while(usedBufCount < usedItems.size())
+            {
+                size_t index = threadRand.Generate() % usedItems.size();
+                unusedItems.push_back(usedItems[index]);
+                usedItems.erase(usedItems.begin() + index);
+            }
+            // Move some unused to used.
+            while(usedBufCount > usedItems.size())
+            {
+                size_t index = threadRand.Generate() % unusedItems.size();
+                usedItems.push_back(unusedItems[index]);
+                unusedItems.erase(unusedItems.begin() + index);
+            }
+
+            uint32_t touchExistingCount = 0;
+            uint32_t touchLostCount = 0;
+            uint32_t createSucceededCount = 0;
+            uint32_t createFailedCount = 0;
+
+            // Touch all used bufs. If not created or lost, allocate.
+            for(size_t i = 0; i < usedItems.size(); ++i)
+            {
+                Item& item = usedItems[i];
+                // Not yet created.
+                if(item.Alloc == VK_NULL_HANDLE)
+                {
+                    res = Allocate(item);
+                    ++outThreadResult->AllocationCount;
+                    if(res != VK_SUCCESS)
+                    {
+                        item.Alloc = VK_NULL_HANDLE;
+                        item.Buf = VK_NULL_HANDLE;
+                        ++outThreadResult->FailedAllocationCount;
+                        outThreadResult->FailedAllocationTotalSize += item.CalcSizeBytes();
+                        ++createFailedCount;
+                    }
+                    else
+                        ++createSucceededCount;
+                }
+                else
+                {
+                    // Touch.
+                    VmaAllocationInfo allocInfo;
+                    vmaGetAllocationInfo(g_hAllocator, item.Alloc, &allocInfo);
+                    // Lost.
+                    if(allocInfo.deviceMemory == VK_NULL_HANDLE)
+                    {
+                        ++touchLostCount;
+
+                        // Destroy.
+                        {
+                            PoolDeallocationTimeRegisterObj timeRegisterObj(*outThreadResult);
+                            if(item.Buf)
+                                vmaDestroyBuffer(g_hAllocator, item.Buf, item.Alloc);
+                            else
+                                vmaDestroyImage(g_hAllocator, item.Image, item.Alloc);
+                            ++outThreadResult->DeallocationCount;
+                        }
+                        item.Alloc = VK_NULL_HANDLE;
+                        item.Buf = VK_NULL_HANDLE;
+
+                        ++outThreadResult->LostAllocationCount;
+                        outThreadResult->LostAllocationTotalSize += item.CalcSizeBytes();
+
+                        // Recreate.
+                        res = Allocate(item);
+                        ++outThreadResult->AllocationCount;
+                        // Creation failed.
+                        if(res != VK_SUCCESS)
+                        {
+                            ++outThreadResult->FailedAllocationCount;
+                            outThreadResult->FailedAllocationTotalSize += item.CalcSizeBytes();
+                            ++createFailedCount;
+                        }
+                        else
+                            ++createSucceededCount;
+                    }
+                    else
+                        ++touchExistingCount;
+                }
+            }
+ 
+            /*
+            printf("Thread %u frame %u: Touch existing %u lost %u, create succeeded %u failed %u\n",
+                randSeed, frameIndex,
+                touchExistingCount, touchLostCount,
+                createSucceededCount, createFailedCount);
+            */
+
+            SetEvent(frameEndEvent);
+        }
+
+        // Free all remaining items.
+        for(size_t i = usedItems.size(); i--; )
+        {
+            PoolDeallocationTimeRegisterObj timeRegisterObj(*outThreadResult);
+            if(usedItems[i].Buf)
+                vmaDestroyBuffer(g_hAllocator, usedItems[i].Buf, usedItems[i].Alloc);
+            else
+                vmaDestroyImage(g_hAllocator, usedItems[i].Image, usedItems[i].Alloc);
+            ++outThreadResult->DeallocationCount;
+        }
+        for(size_t i = unusedItems.size(); i--; )
+        {
+            PoolDeallocationTimeRegisterObj timeRegisterOb(*outThreadResult);
+            if(unusedItems[i].Buf)
+                vmaDestroyBuffer(g_hAllocator, unusedItems[i].Buf, unusedItems[i].Alloc);
+            else
+                vmaDestroyImage(g_hAllocator, unusedItems[i].Image, unusedItems[i].Alloc);
+            ++outThreadResult->DeallocationCount;
+        }
+    };
+
+    // Launch threads.
+    uint32_t threadRandSeed = mainRand.Generate();
+    std::vector<HANDLE> frameStartEvents{config.ThreadCount};
+    std::vector<HANDLE> frameEndEvents{config.ThreadCount};
+    std::vector<std::thread> bkgThreads;
+    std::vector<PoolTestThreadResult> threadResults{config.ThreadCount};
+    for(uint32_t threadIndex = 0; threadIndex < config.ThreadCount; ++threadIndex)
+    {
+        frameStartEvents[threadIndex] = CreateEvent(NULL, FALSE, FALSE, NULL);
+        frameEndEvents[threadIndex] = CreateEvent(NULL, FALSE, FALSE, NULL);
+        bkgThreads.emplace_back(std::bind(
+            ThreadProc,
+            &threadResults[threadIndex],
+            threadRandSeed + threadIndex,
+            frameStartEvents[threadIndex],
+            frameEndEvents[threadIndex]));
+    }
+
+    // Execute frames.
+    TEST(config.ThreadCount <= MAXIMUM_WAIT_OBJECTS);
+    for(uint32_t frameIndex = 0; frameIndex < config.FrameCount; ++frameIndex)
+    {
+        vmaSetCurrentFrameIndex(g_hAllocator, frameIndex);
+        for(size_t threadIndex = 0; threadIndex < config.ThreadCount; ++threadIndex)
+            SetEvent(frameStartEvents[threadIndex]);
+        WaitForMultipleObjects(config.ThreadCount, &frameEndEvents[0], TRUE, INFINITE);
+    }
+
+    // Wait for threads finished
+    for(size_t i = 0; i < bkgThreads.size(); ++i)
+    {
+        bkgThreads[i].join();
+        CloseHandle(frameEndEvents[i]);
+        CloseHandle(frameStartEvents[i]);
+    }
+    bkgThreads.clear();
+
+    // Finish time measurement - before destroying pool.
+    outResult.TotalTime = std::chrono::high_resolution_clock::now() - timeBeg;
+
+    vmaDestroyPool(g_hAllocator, pool);
+
+    outResult.AllocationTimeMin = duration::max();
+    outResult.AllocationTimeAvg = duration::zero();
+    outResult.AllocationTimeMax = duration::min();
+    outResult.DeallocationTimeMin = duration::max();
+    outResult.DeallocationTimeAvg = duration::zero();
+    outResult.DeallocationTimeMax = duration::min();
+    outResult.LostAllocationCount = 0;
+    outResult.LostAllocationTotalSize = 0;
+    outResult.FailedAllocationCount = 0;
+    outResult.FailedAllocationTotalSize = 0;
+    size_t allocationCount = 0;
+    size_t deallocationCount = 0;
+    for(size_t threadIndex = 0; threadIndex < config.ThreadCount; ++threadIndex)
+    {
+        const PoolTestThreadResult& threadResult = threadResults[threadIndex];
+        outResult.AllocationTimeMin = std::min(outResult.AllocationTimeMin, threadResult.AllocationTimeMin);
+        outResult.AllocationTimeMax = std::max(outResult.AllocationTimeMax, threadResult.AllocationTimeMax);
+        outResult.AllocationTimeAvg += threadResult.AllocationTimeSum;
+        outResult.DeallocationTimeMin = std::min(outResult.DeallocationTimeMin, threadResult.DeallocationTimeMin);
+        outResult.DeallocationTimeMax = std::max(outResult.DeallocationTimeMax, threadResult.DeallocationTimeMax);
+        outResult.DeallocationTimeAvg += threadResult.DeallocationTimeSum;
+        allocationCount += threadResult.AllocationCount;
+        deallocationCount += threadResult.DeallocationCount;
+        outResult.FailedAllocationCount += threadResult.FailedAllocationCount;
+        outResult.FailedAllocationTotalSize += threadResult.FailedAllocationTotalSize;
+        outResult.LostAllocationCount += threadResult.LostAllocationCount;
+        outResult.LostAllocationTotalSize += threadResult.LostAllocationTotalSize;
+    }
+    if(allocationCount)
+        outResult.AllocationTimeAvg /= allocationCount;
+    if(deallocationCount)
+        outResult.DeallocationTimeAvg /= deallocationCount;
+}
+
+static inline bool MemoryRegionsOverlap(char* ptr1, size_t size1, char* ptr2, size_t size2)
+{
+    if(ptr1 < ptr2)
+        return ptr1 + size1 > ptr2;
+    else if(ptr2 < ptr1)
+        return ptr2 + size2 > ptr1;
+    else
+        return true;
+}
+
+static void TestMemoryUsage()
+{
+    wprintf(L"Testing memory usage:\n");
+
+    static const VmaMemoryUsage lastUsage = VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED;
+    for(uint32_t usage = 0; usage <= lastUsage; ++usage)
+    {
+        switch(usage)
+        {
+        case VMA_MEMORY_USAGE_UNKNOWN: printf("  VMA_MEMORY_USAGE_UNKNOWN:\n"); break;
+        case VMA_MEMORY_USAGE_GPU_ONLY: printf("  VMA_MEMORY_USAGE_GPU_ONLY:\n"); break;
+        case VMA_MEMORY_USAGE_CPU_ONLY: printf("  VMA_MEMORY_USAGE_CPU_ONLY:\n"); break;
+        case VMA_MEMORY_USAGE_CPU_TO_GPU: printf("  VMA_MEMORY_USAGE_CPU_TO_GPU:\n"); break;
+        case VMA_MEMORY_USAGE_GPU_TO_CPU: printf("  VMA_MEMORY_USAGE_GPU_TO_CPU:\n"); break;
+        case VMA_MEMORY_USAGE_CPU_COPY: printf("  VMA_MEMORY_USAGE_CPU_COPY:\n"); break;
+        case VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED: printf("  VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED:\n"); break;
+        default: assert(0);
+        }
+
+        auto printResult = [](const char* testName, VkResult res, uint32_t memoryTypeBits, uint32_t memoryTypeIndex)
+        {
+            if(res == VK_SUCCESS)
+                printf("    %s: memoryTypeBits=0x%X, memoryTypeIndex=%u\n", testName, memoryTypeBits, memoryTypeIndex);
+            else
+                printf("    %s: memoryTypeBits=0x%X, FAILED with res=%d\n", testName, memoryTypeBits, (int32_t)res);
+        };
+        
+        // 1: Buffer for copy
+        {
+            VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+            bufCreateInfo.size = 65536;
+            bufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+
+            VkBuffer buf = VK_NULL_HANDLE;
+            VkResult res = vkCreateBuffer(g_hDevice, &bufCreateInfo, g_Allocs, &buf);
+            TEST(res == VK_SUCCESS && buf != VK_NULL_HANDLE);
+
+            VkMemoryRequirements memReq = {};
+            vkGetBufferMemoryRequirements(g_hDevice, buf, &memReq);
+
+            VmaAllocationCreateInfo allocCreateInfo = {};
+            allocCreateInfo.usage = (VmaMemoryUsage)usage;
+            VmaAllocation alloc = VK_NULL_HANDLE;
+            VmaAllocationInfo allocInfo = {};
+            res = vmaAllocateMemoryForBuffer(g_hAllocator, buf, &allocCreateInfo, &alloc, &allocInfo);
+            if(res == VK_SUCCESS)
+            {
+                TEST((memReq.memoryTypeBits & (1u << allocInfo.memoryType)) != 0);
+                res = vkBindBufferMemory(g_hDevice, buf, allocInfo.deviceMemory, allocInfo.offset);
+                TEST(res == VK_SUCCESS);
+            }
+            printResult("Buffer TRANSFER_DST + TRANSFER_SRC", res, memReq.memoryTypeBits, allocInfo.memoryType);
+            vmaDestroyBuffer(g_hAllocator, buf, alloc);
+        }
+
+        // 2: Vertex buffer
+        {
+            VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+            bufCreateInfo.size = 65536;
+            bufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
+
+            VkBuffer buf = VK_NULL_HANDLE;
+            VkResult res = vkCreateBuffer(g_hDevice, &bufCreateInfo, g_Allocs, &buf);
+            TEST(res == VK_SUCCESS && buf != VK_NULL_HANDLE);
+
+            VkMemoryRequirements memReq = {};
+            vkGetBufferMemoryRequirements(g_hDevice, buf, &memReq);
+
+            VmaAllocationCreateInfo allocCreateInfo = {};
+            allocCreateInfo.usage = (VmaMemoryUsage)usage;
+            VmaAllocation alloc = VK_NULL_HANDLE;
+            VmaAllocationInfo allocInfo = {};
+            res = vmaAllocateMemoryForBuffer(g_hAllocator, buf, &allocCreateInfo, &alloc, &allocInfo);
+            if(res == VK_SUCCESS)
+            {
+                TEST((memReq.memoryTypeBits & (1u << allocInfo.memoryType)) != 0);
+                res = vkBindBufferMemory(g_hDevice, buf, allocInfo.deviceMemory, allocInfo.offset);
+                TEST(res == VK_SUCCESS);
+            }
+            printResult("Buffer TRANSFER_DST + VERTEX_BUFFER", res, memReq.memoryTypeBits, allocInfo.memoryType);
+            vmaDestroyBuffer(g_hAllocator, buf, alloc);
+        }
+
+        // 3: Image for copy, OPTIMAL
+        {
+            VkImageCreateInfo imgCreateInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
+            imgCreateInfo.imageType = VK_IMAGE_TYPE_2D;
+            imgCreateInfo.extent.width = 256;
+            imgCreateInfo.extent.height = 256;
+            imgCreateInfo.extent.depth = 1;
+            imgCreateInfo.mipLevels = 1;
+            imgCreateInfo.arrayLayers = 1;
+            imgCreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
+            imgCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
+            imgCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+            imgCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
+            imgCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
+
+            VkImage img = VK_NULL_HANDLE;
+            VkResult res = vkCreateImage(g_hDevice, &imgCreateInfo, g_Allocs, &img);
+            TEST(res == VK_SUCCESS && img != VK_NULL_HANDLE);
+
+            VkMemoryRequirements memReq = {};
+            vkGetImageMemoryRequirements(g_hDevice, img, &memReq);
+
+            VmaAllocationCreateInfo allocCreateInfo = {};
+            allocCreateInfo.usage = (VmaMemoryUsage)usage;
+            VmaAllocation alloc = VK_NULL_HANDLE;
+            VmaAllocationInfo allocInfo = {};
+            res = vmaAllocateMemoryForImage(g_hAllocator, img, &allocCreateInfo, &alloc, &allocInfo);
+            if(res == VK_SUCCESS)
+            {
+                TEST((memReq.memoryTypeBits & (1u << allocInfo.memoryType)) != 0);
+                res = vkBindImageMemory(g_hDevice, img, allocInfo.deviceMemory, allocInfo.offset);
+                TEST(res == VK_SUCCESS);
+            }
+            printResult("Image OPTIMAL TRANSFER_DST + TRANSFER_SRC", res, memReq.memoryTypeBits, allocInfo.memoryType);
+
+            vmaDestroyImage(g_hAllocator, img, alloc);
+        }
+
+        // 4: Image SAMPLED, OPTIMAL
+        {
+            VkImageCreateInfo imgCreateInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
+            imgCreateInfo.imageType = VK_IMAGE_TYPE_2D;
+            imgCreateInfo.extent.width = 256;
+            imgCreateInfo.extent.height = 256;
+            imgCreateInfo.extent.depth = 1;
+            imgCreateInfo.mipLevels = 1;
+            imgCreateInfo.arrayLayers = 1;
+            imgCreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
+            imgCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
+            imgCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+            imgCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
+            imgCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
+
+            VkImage img = VK_NULL_HANDLE;
+            VkResult res = vkCreateImage(g_hDevice, &imgCreateInfo, g_Allocs, &img);
+            TEST(res == VK_SUCCESS && img != VK_NULL_HANDLE);
+
+            VkMemoryRequirements memReq = {};
+            vkGetImageMemoryRequirements(g_hDevice, img, &memReq);
+
+            VmaAllocationCreateInfo allocCreateInfo = {};
+            allocCreateInfo.usage = (VmaMemoryUsage)usage;
+            VmaAllocation alloc = VK_NULL_HANDLE;
+            VmaAllocationInfo allocInfo = {};
+            res = vmaAllocateMemoryForImage(g_hAllocator, img, &allocCreateInfo, &alloc, &allocInfo);
+            if(res == VK_SUCCESS)
+            {
+                TEST((memReq.memoryTypeBits & (1u << allocInfo.memoryType)) != 0);
+                res = vkBindImageMemory(g_hDevice, img, allocInfo.deviceMemory, allocInfo.offset);
+                TEST(res == VK_SUCCESS);
+            }
+            printResult("Image OPTIMAL TRANSFER_DST + SAMPLED", res, memReq.memoryTypeBits, allocInfo.memoryType);
+            vmaDestroyImage(g_hAllocator, img, alloc);
+        }
+
+        // 5: Image COLOR_ATTACHMENT, OPTIMAL
+        {
+            VkImageCreateInfo imgCreateInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
+            imgCreateInfo.imageType = VK_IMAGE_TYPE_2D;
+            imgCreateInfo.extent.width = 256;
+            imgCreateInfo.extent.height = 256;
+            imgCreateInfo.extent.depth = 1;
+            imgCreateInfo.mipLevels = 1;
+            imgCreateInfo.arrayLayers = 1;
+            imgCreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
+            imgCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
+            imgCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+            imgCreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+            imgCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
+
+            VkImage img = VK_NULL_HANDLE;
+            VkResult res = vkCreateImage(g_hDevice, &imgCreateInfo, g_Allocs, &img);
+            TEST(res == VK_SUCCESS && img != VK_NULL_HANDLE);
+
+            VkMemoryRequirements memReq = {};
+            vkGetImageMemoryRequirements(g_hDevice, img, &memReq);
+
+            VmaAllocationCreateInfo allocCreateInfo = {};
+            allocCreateInfo.usage = (VmaMemoryUsage)usage;
+            VmaAllocation alloc = VK_NULL_HANDLE;
+            VmaAllocationInfo allocInfo = {};
+            res = vmaAllocateMemoryForImage(g_hAllocator, img, &allocCreateInfo, &alloc, &allocInfo);
+            if(res == VK_SUCCESS)
+            {
+                TEST((memReq.memoryTypeBits & (1u << allocInfo.memoryType)) != 0);
+                res = vkBindImageMemory(g_hDevice, img, allocInfo.deviceMemory, allocInfo.offset);
+                TEST(res == VK_SUCCESS);
+            }
+            printResult("Image OPTIMAL SAMPLED + COLOR_ATTACHMENT", res, memReq.memoryTypeBits, allocInfo.memoryType);
+            vmaDestroyImage(g_hAllocator, img, alloc);
+        }
+    }
+}
+
+static uint32_t FindDeviceCoherentMemoryTypeBits()
+{
+    VkPhysicalDeviceMemoryProperties memProps;
+    vkGetPhysicalDeviceMemoryProperties(g_hPhysicalDevice, &memProps);
+
+    uint32_t memTypeBits = 0;
+    for(uint32_t i = 0; i < memProps.memoryTypeCount; ++i)
+    {
+        if(memProps.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD)
+            memTypeBits |= 1u << i;
+    }
+    return memTypeBits;
+}
+
+static void TestDeviceCoherentMemory()
+{
+    if(!VK_AMD_device_coherent_memory_enabled)
+        return;
+
+    uint32_t deviceCoherentMemoryTypeBits = FindDeviceCoherentMemoryTypeBits();
+    // Extension is enabled, feature is enabled, and the device still doesn't support any such memory type?
+    // OK then, so it's just fake!
+    if(deviceCoherentMemoryTypeBits == 0)
+        return;
+
+    wprintf(L"Testing device coherent memory...\n");
+
+    // 1. Try to allocate buffer from a memory type that is DEVICE_COHERENT.
+
+    VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+    bufCreateInfo.size = 0x10000;
+    bufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+
+    VmaAllocationCreateInfo allocCreateInfo = {};
+    allocCreateInfo.flags = VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
+    allocCreateInfo.requiredFlags = VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD;
+
+    AllocInfo alloc = {};
+    VmaAllocationInfo allocInfo = {};
+    VkResult res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo, &alloc.m_Buffer, &alloc.m_Allocation, &allocInfo);
+
+    // Make sure it succeeded and was really created in such memory type.
+    TEST(res == VK_SUCCESS);
+    TEST((1u << allocInfo.memoryType) & deviceCoherentMemoryTypeBits);
+
+    alloc.Destroy();
+
+    // 2. Try to create a pool in such memory type.
+    {
+        VmaPoolCreateInfo poolCreateInfo = {};
+
+        res = vmaFindMemoryTypeIndex(g_hAllocator, UINT32_MAX, &allocCreateInfo, &poolCreateInfo.memoryTypeIndex);
+        TEST(res == VK_SUCCESS);
+        TEST((1u << poolCreateInfo.memoryTypeIndex) & deviceCoherentMemoryTypeBits);
+
+        VmaPool pool = VK_NULL_HANDLE;
+        res = vmaCreatePool(g_hAllocator, &poolCreateInfo, &pool);
+        TEST(res == VK_SUCCESS);
+
+        vmaDestroyPool(g_hAllocator, pool);
+    }
+
+    // 3. Try the same with a local allocator created without VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT.
+
+    VmaAllocatorCreateInfo allocatorCreateInfo = {};
+    SetAllocatorCreateInfo(allocatorCreateInfo);
+    allocatorCreateInfo.flags &= ~VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT;
+    
+    VmaAllocator localAllocator = VK_NULL_HANDLE;
+    res = vmaCreateAllocator(&allocatorCreateInfo, &localAllocator);
+    TEST(res == VK_SUCCESS && localAllocator);
+
+    res = vmaCreateBuffer(localAllocator, &bufCreateInfo, &allocCreateInfo, &alloc.m_Buffer, &alloc.m_Allocation, &allocInfo);
+
+    // Make sure it failed.
+    TEST(res != VK_SUCCESS && !alloc.m_Buffer && !alloc.m_Allocation);
+
+    // 4. Try to find memory type.
+    {
+        uint32_t memTypeIndex = UINT_MAX;
+        res = vmaFindMemoryTypeIndex(localAllocator, UINT32_MAX, &allocCreateInfo, &memTypeIndex);
+        TEST(res != VK_SUCCESS);
+    }
+
+    vmaDestroyAllocator(localAllocator);
+}
+
+static void TestBudget()
+{
+    wprintf(L"Testing budget...\n");
+
+    static const VkDeviceSize BUF_SIZE = 10ull * 1024 * 1024;
+    static const uint32_t BUF_COUNT = 4;
+
+    const VkPhysicalDeviceMemoryProperties* memProps = {};
+    vmaGetMemoryProperties(g_hAllocator, &memProps);
+
+    for(uint32_t testIndex = 0; testIndex < 2; ++testIndex)
+    {
+        vmaSetCurrentFrameIndex(g_hAllocator, ++g_FrameIndex);
+
+        VmaBudget budgetBeg[VK_MAX_MEMORY_HEAPS] = {};
+        vmaGetBudget(g_hAllocator, budgetBeg);
+
+        for(uint32_t i = 0; i < memProps->memoryHeapCount; ++i)
+        {
+            TEST(budgetBeg[i].budget > 0);
+            TEST(budgetBeg[i].budget <= memProps->memoryHeaps[i].size);
+            TEST(budgetBeg[i].allocationBytes <= budgetBeg[i].blockBytes);
+        }
+
+        VkBufferCreateInfo bufInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+        bufInfo.size = BUF_SIZE;
+        bufInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+    
+        VmaAllocationCreateInfo allocCreateInfo = {};
+        allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+        if(testIndex == 0)
+        {
+            allocCreateInfo.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
+        }
+
+        // CREATE BUFFERS
+        uint32_t heapIndex = 0;
+        BufferInfo bufInfos[BUF_COUNT] = {};
+        for(uint32_t bufIndex = 0; bufIndex < BUF_COUNT; ++bufIndex)
+        {
+            VmaAllocationInfo allocInfo;
+            VkResult res = vmaCreateBuffer(g_hAllocator, &bufInfo, &allocCreateInfo,
+                &bufInfos[bufIndex].Buffer, &bufInfos[bufIndex].Allocation, &allocInfo);
+            TEST(res == VK_SUCCESS);
+            if(bufIndex == 0)
+            {
+                heapIndex = MemoryTypeToHeap(allocInfo.memoryType);
+            }
+            else
+            {
+                // All buffers need to fall into the same heap.
+                TEST(MemoryTypeToHeap(allocInfo.memoryType) == heapIndex);
+            }
+        }
+
+        VmaBudget budgetWithBufs[VK_MAX_MEMORY_HEAPS] = {};
+        vmaGetBudget(g_hAllocator, budgetWithBufs);
+
+        // DESTROY BUFFERS
+        for(size_t bufIndex = BUF_COUNT; bufIndex--; )
+        {
+            vmaDestroyBuffer(g_hAllocator, bufInfos[bufIndex].Buffer, bufInfos[bufIndex].Allocation);
+        }
+
+        VmaBudget budgetEnd[VK_MAX_MEMORY_HEAPS] = {};
+        vmaGetBudget(g_hAllocator, budgetEnd);
+
+        // CHECK
+        for(uint32_t i = 0; i < memProps->memoryHeapCount; ++i)
+        {
+            TEST(budgetEnd[i].allocationBytes <= budgetEnd[i].blockBytes);
+            if(i == heapIndex)
+            {
+                TEST(budgetEnd[i].allocationBytes == budgetBeg[i].allocationBytes);
+                TEST(budgetWithBufs[i].allocationBytes == budgetBeg[i].allocationBytes + BUF_SIZE * BUF_COUNT);
+                TEST(budgetWithBufs[i].blockBytes >= budgetEnd[i].blockBytes);
+            }
+            else
+            {
+                TEST(budgetEnd[i].allocationBytes == budgetEnd[i].allocationBytes &&
+                    budgetEnd[i].allocationBytes == budgetWithBufs[i].allocationBytes);
+                TEST(budgetEnd[i].blockBytes == budgetEnd[i].blockBytes &&
+                    budgetEnd[i].blockBytes == budgetWithBufs[i].blockBytes);
+            }
+        }
+    }
+}
+
+static void TestMapping()
+{
+    wprintf(L"Testing mapping...\n");
+
+    VkResult res;
+    uint32_t memTypeIndex = UINT32_MAX;
+
+    enum TEST
+    {
+        TEST_NORMAL,
+        TEST_POOL,
+        TEST_DEDICATED,
+        TEST_COUNT
+    };
+    for(uint32_t testIndex = 0; testIndex < TEST_COUNT; ++testIndex)
+    {
+        VmaPool pool = nullptr;
+        if(testIndex == TEST_POOL)
+        {
+            TEST(memTypeIndex != UINT32_MAX);
+            VmaPoolCreateInfo poolInfo = {};
+            poolInfo.memoryTypeIndex = memTypeIndex;
+            res = vmaCreatePool(g_hAllocator, &poolInfo, &pool);
+            TEST(res == VK_SUCCESS);
+        }
+
+        VkBufferCreateInfo bufInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+        bufInfo.size = 0x10000;
+        bufInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+
+        VmaAllocationCreateInfo allocCreateInfo = {};
+        allocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
+        allocCreateInfo.pool = pool;
+        if(testIndex == TEST_DEDICATED)
+            allocCreateInfo.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
+
+        VmaAllocationInfo allocInfo;
+
+        // Mapped manually
+
+        // Create 2 buffers.
+        BufferInfo bufferInfos[3];
+        for(size_t i = 0; i < 2; ++i)
+        {
+            res = vmaCreateBuffer(g_hAllocator, &bufInfo, &allocCreateInfo,
+                &bufferInfos[i].Buffer, &bufferInfos[i].Allocation, &allocInfo);
+            TEST(res == VK_SUCCESS);
+            TEST(allocInfo.pMappedData == nullptr);
+            memTypeIndex = allocInfo.memoryType;
+        }
+
+        // Map buffer 0.
+        char* data00 = nullptr;
+        res = vmaMapMemory(g_hAllocator, bufferInfos[0].Allocation, (void**)&data00);
+        TEST(res == VK_SUCCESS && data00 != nullptr);
+        data00[0xFFFF] = data00[0];
+
+        // Map buffer 0 second time.
+        char* data01 = nullptr;
+        res = vmaMapMemory(g_hAllocator, bufferInfos[0].Allocation, (void**)&data01);
+        TEST(res == VK_SUCCESS && data01 == data00);
+
+        // Map buffer 1.
+        char* data1 = nullptr;
+        res = vmaMapMemory(g_hAllocator, bufferInfos[1].Allocation, (void**)&data1);
+        TEST(res == VK_SUCCESS && data1 != nullptr);
+        TEST(!MemoryRegionsOverlap(data00, (size_t)bufInfo.size, data1, (size_t)bufInfo.size));
+        data1[0xFFFF] = data1[0];
+
+        // Unmap buffer 0 two times.
+        vmaUnmapMemory(g_hAllocator, bufferInfos[0].Allocation);
+        vmaUnmapMemory(g_hAllocator, bufferInfos[0].Allocation);
+        vmaGetAllocationInfo(g_hAllocator, bufferInfos[0].Allocation, &allocInfo);
+        TEST(allocInfo.pMappedData == nullptr);
+
+        // Unmap buffer 1.
+        vmaUnmapMemory(g_hAllocator, bufferInfos[1].Allocation);
+        vmaGetAllocationInfo(g_hAllocator, bufferInfos[1].Allocation, &allocInfo);
+        TEST(allocInfo.pMappedData == nullptr);
+
+        // Create 3rd buffer - persistently mapped.
+        allocCreateInfo.flags |= VMA_ALLOCATION_CREATE_MAPPED_BIT;
+        res = vmaCreateBuffer(g_hAllocator, &bufInfo, &allocCreateInfo,
+            &bufferInfos[2].Buffer, &bufferInfos[2].Allocation, &allocInfo);
+        TEST(res == VK_SUCCESS && allocInfo.pMappedData != nullptr);
+
+        // Map buffer 2.
+        char* data2 = nullptr;
+        res = vmaMapMemory(g_hAllocator, bufferInfos[2].Allocation, (void**)&data2);
+        TEST(res == VK_SUCCESS && data2 == allocInfo.pMappedData);
+        data2[0xFFFF] = data2[0];
+
+        // Unmap buffer 2.
+        vmaUnmapMemory(g_hAllocator, bufferInfos[2].Allocation);
+        vmaGetAllocationInfo(g_hAllocator, bufferInfos[2].Allocation, &allocInfo);
+        TEST(allocInfo.pMappedData == data2);
+
+        // Destroy all buffers.
+        for(size_t i = 3; i--; )
+            vmaDestroyBuffer(g_hAllocator, bufferInfos[i].Buffer, bufferInfos[i].Allocation);
+
+        vmaDestroyPool(g_hAllocator, pool);
+    }
+}
+
+// Test CREATE_MAPPED with required DEVICE_LOCAL. There was a bug with it.
+static void TestDeviceLocalMapped()
+{
+    VkResult res;
+
+    for(uint32_t testIndex = 0; testIndex < 3; ++testIndex)
+    {
+        VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+        bufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+        bufCreateInfo.size = 4096;
+
+        VmaPool pool = VK_NULL_HANDLE;
+        VmaAllocationCreateInfo allocCreateInfo = {};
+        allocCreateInfo.requiredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+        allocCreateInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
+        if(testIndex == 2)
+        {
+            VmaPoolCreateInfo poolCreateInfo = {};
+            res = vmaFindMemoryTypeIndexForBufferInfo(g_hAllocator, &bufCreateInfo, &allocCreateInfo, &poolCreateInfo.memoryTypeIndex);
+            TEST(res == VK_SUCCESS);
+            res = vmaCreatePool(g_hAllocator, &poolCreateInfo, &pool);
+            TEST(res == VK_SUCCESS);
+            allocCreateInfo.pool = pool;
+        }
+        else if(testIndex == 1)
+        {
+            allocCreateInfo.flags |= VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT;
+        }
+
+        VkBuffer buf = VK_NULL_HANDLE;
+        VmaAllocation alloc = VK_NULL_HANDLE;
+        VmaAllocationInfo allocInfo = {};
+        res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);
+        TEST(res == VK_SUCCESS && alloc);
+
+        VkMemoryPropertyFlags memTypeFlags = 0;
+        vmaGetMemoryTypeProperties(g_hAllocator, allocInfo.memoryType, &memTypeFlags);
+        const bool shouldBeMapped = (memTypeFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0;
+        TEST((allocInfo.pMappedData != nullptr) == shouldBeMapped);
+
+        vmaDestroyBuffer(g_hAllocator, buf, alloc);
+        vmaDestroyPool(g_hAllocator, pool);
+    }
+}
+
+static void TestMappingMultithreaded()
+{
+    wprintf(L"Testing mapping multithreaded...\n");
+
+    static const uint32_t threadCount = 16;
+    static const uint32_t bufferCount = 1024;
+    static const uint32_t threadBufferCount = bufferCount / threadCount;
+
+    VkResult res;
+    volatile uint32_t memTypeIndex = UINT32_MAX;
+
+    enum TEST
+    {
+        TEST_NORMAL,
+        TEST_POOL,
+        TEST_DEDICATED,
+        TEST_COUNT
+    };
+    for(uint32_t testIndex = 0; testIndex < TEST_COUNT; ++testIndex)
+    {
+        VmaPool pool = nullptr;
+        if(testIndex == TEST_POOL)
+        {
+            TEST(memTypeIndex != UINT32_MAX);
+            VmaPoolCreateInfo poolInfo = {};
+            poolInfo.memoryTypeIndex = memTypeIndex;
+            res = vmaCreatePool(g_hAllocator, &poolInfo, &pool);
+            TEST(res == VK_SUCCESS);
+        }
+
+        VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+        bufCreateInfo.size = 0x10000;
+        bufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+    
+        VmaAllocationCreateInfo allocCreateInfo = {};
+        allocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
+        allocCreateInfo.pool = pool;
+        if(testIndex == TEST_DEDICATED)
+            allocCreateInfo.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
+    
+        std::thread threads[threadCount];
+        for(uint32_t threadIndex = 0; threadIndex < threadCount; ++threadIndex)
+        {
+            threads[threadIndex] = std::thread([=, &memTypeIndex](){
+                // ======== THREAD FUNCTION ========
+
+                RandomNumberGenerator rand{threadIndex};
+                
+                enum class MODE
+                {
+                    // Don't map this buffer at all.
+                    DONT_MAP,
+                    // Map and quickly unmap.
+                    MAP_FOR_MOMENT,
+                    // Map and unmap before destruction.
+                    MAP_FOR_LONGER,
+                    // Map two times. Quickly unmap, second unmap before destruction.
+                    MAP_TWO_TIMES,
+                    // Create this buffer as persistently mapped.
+                    PERSISTENTLY_MAPPED,
+                    COUNT
+                };
+                std::vector<BufferInfo> bufInfos{threadBufferCount};
+                std::vector<MODE> bufModes{threadBufferCount};
+                
+                for(uint32_t bufferIndex = 0; bufferIndex < threadBufferCount; ++bufferIndex)
+                {
+                    BufferInfo& bufInfo = bufInfos[bufferIndex];
+                    const MODE mode = (MODE)(rand.Generate() % (uint32_t)MODE::COUNT);
+                    bufModes[bufferIndex] = mode;
+
+                    VmaAllocationCreateInfo localAllocCreateInfo = allocCreateInfo;
+                    if(mode == MODE::PERSISTENTLY_MAPPED)
+                        localAllocCreateInfo.flags |= VMA_ALLOCATION_CREATE_MAPPED_BIT;
+                    
+                    VmaAllocationInfo allocInfo;
+                    VkResult res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &localAllocCreateInfo,
+                        &bufInfo.Buffer, &bufInfo.Allocation, &allocInfo);
+                    TEST(res == VK_SUCCESS);
+                    
+                    if(memTypeIndex == UINT32_MAX)
+                        memTypeIndex = allocInfo.memoryType;
+
+                    char* data = nullptr;
+
+                    if(mode == MODE::PERSISTENTLY_MAPPED)
+                    {
+                        data = (char*)allocInfo.pMappedData;
+                        TEST(data != nullptr);
+                    }
+                    else if(mode == MODE::MAP_FOR_MOMENT || mode == MODE::MAP_FOR_LONGER ||
+                        mode == MODE::MAP_TWO_TIMES)
+                    {
+                        TEST(data == nullptr);
+                        res = vmaMapMemory(g_hAllocator, bufInfo.Allocation, (void**)&data);
+                        TEST(res == VK_SUCCESS && data != nullptr);
+
+                        if(mode == MODE::MAP_TWO_TIMES)
+                        {
+                            char* data2 = nullptr;
+                            res = vmaMapMemory(g_hAllocator, bufInfo.Allocation, (void**)&data2);
+                            TEST(res == VK_SUCCESS && data2 == data);
+                        }
+                    }
+                    else if(mode == MODE::DONT_MAP)
+                    {
+                        TEST(allocInfo.pMappedData == nullptr);
+                    }
+                    else
+                        TEST(0);
+
+                    // Test if reading and writing from the beginning and end of mapped memory doesn't crash.
+                    if(data)
+                        data[0xFFFF] = data[0];
+
+                    if(mode == MODE::MAP_FOR_MOMENT || mode == MODE::MAP_TWO_TIMES)
+                    {
+                        vmaUnmapMemory(g_hAllocator, bufInfo.Allocation);
+
+                        VmaAllocationInfo allocInfo;
+                        vmaGetAllocationInfo(g_hAllocator, bufInfo.Allocation, &allocInfo);
+                        if(mode == MODE::MAP_FOR_MOMENT)
+                            TEST(allocInfo.pMappedData == nullptr);
+                        else
+                            TEST(allocInfo.pMappedData == data);
+                    }
+
+                    switch(rand.Generate() % 3)
+                    {
+                    case 0: Sleep(0); break; // Yield.
+                    case 1: Sleep(10); break; // 10 ms
+                    // default: No sleep.
+                    }
+
+                    // Test if reading and writing from the beginning and end of mapped memory doesn't crash.
+                    if(data)
+                        data[0xFFFF] = data[0];
+                }
+
+                for(size_t bufferIndex = threadBufferCount; bufferIndex--; )
+                {
+                    if(bufModes[bufferIndex] == MODE::MAP_FOR_LONGER ||
+                        bufModes[bufferIndex] == MODE::MAP_TWO_TIMES)
+                    {
+                        vmaUnmapMemory(g_hAllocator, bufInfos[bufferIndex].Allocation);
+
+                        VmaAllocationInfo allocInfo;
+                        vmaGetAllocationInfo(g_hAllocator, bufInfos[bufferIndex].Allocation, &allocInfo);
+                        TEST(allocInfo.pMappedData == nullptr);
+                    }
+
+                    vmaDestroyBuffer(g_hAllocator, bufInfos[bufferIndex].Buffer, bufInfos[bufferIndex].Allocation);
+                }
+            });
+        }
+
+        for(uint32_t threadIndex = 0; threadIndex < threadCount; ++threadIndex)
+            threads[threadIndex].join();
+    
+        vmaDestroyPool(g_hAllocator, pool);
+    }
+}
+
+static void WriteMainTestResultHeader(FILE* file)
+{
+    fprintf(file,
+        "Code,Time,"
+        "Threads,Buffers and images,Sizes,Operations,Allocation strategy,Free order,"
+        "Total Time (us),"
+        "Allocation Time Min (us),"
+        "Allocation Time Avg (us),"
+        "Allocation Time Max (us),"
+        "Deallocation Time Min (us),"
+        "Deallocation Time Avg (us),"
+        "Deallocation Time Max (us),"
+        "Total Memory Allocated (B),"
+        "Free Range Size Avg (B),"
+        "Free Range Size Max (B)\n");
+}
+
+static void WriteMainTestResult(
+    FILE* file,
+    const char* codeDescription,
+    const char* testDescription,
+    const Config& config, const Result& result)
+{
+    float totalTimeSeconds = ToFloatSeconds(result.TotalTime);
+    float allocationTimeMinSeconds = ToFloatSeconds(result.AllocationTimeMin);
+    float allocationTimeAvgSeconds = ToFloatSeconds(result.AllocationTimeAvg);
+    float allocationTimeMaxSeconds = ToFloatSeconds(result.AllocationTimeMax);
+    float deallocationTimeMinSeconds = ToFloatSeconds(result.DeallocationTimeMin);
+    float deallocationTimeAvgSeconds = ToFloatSeconds(result.DeallocationTimeAvg);
+    float deallocationTimeMaxSeconds = ToFloatSeconds(result.DeallocationTimeMax);
+
+    std::string currTime;
+    CurrentTimeToStr(currTime);
+
+    fprintf(file,
+        "%s,%s,%s,"
+        "%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%I64u,%I64u,%I64u\n",
+        codeDescription,
+        currTime.c_str(),
+        testDescription,
+        totalTimeSeconds * 1e6f,
+        allocationTimeMinSeconds * 1e6f,
+        allocationTimeAvgSeconds * 1e6f,
+        allocationTimeMaxSeconds * 1e6f,
+        deallocationTimeMinSeconds * 1e6f,
+        deallocationTimeAvgSeconds * 1e6f,
+        deallocationTimeMaxSeconds * 1e6f,
+        result.TotalMemoryAllocated,
+        result.FreeRangeSizeAvg,
+        result.FreeRangeSizeMax);
+}
+
+static void WritePoolTestResultHeader(FILE* file)
+{
+    fprintf(file,
+        "Code,Test,Time,"
+        "Config,"
+        "Total Time (us),"
+        "Allocation Time Min (us),"
+        "Allocation Time Avg (us),"
+        "Allocation Time Max (us),"
+        "Deallocation Time Min (us),"
+        "Deallocation Time Avg (us),"
+        "Deallocation Time Max (us),"
+        "Lost Allocation Count,"
+        "Lost Allocation Total Size (B),"
+        "Failed Allocation Count,"
+        "Failed Allocation Total Size (B)\n");
+}
+
+static void WritePoolTestResult(
+    FILE* file,
+    const char* codeDescription,
+    const char* testDescription,
+    const PoolTestConfig& config,
+    const PoolTestResult& result)
+{
+    float totalTimeSeconds = ToFloatSeconds(result.TotalTime);
+    float allocationTimeMinSeconds = ToFloatSeconds(result.AllocationTimeMin);
+    float allocationTimeAvgSeconds = ToFloatSeconds(result.AllocationTimeAvg);
+    float allocationTimeMaxSeconds = ToFloatSeconds(result.AllocationTimeMax);
+    float deallocationTimeMinSeconds = ToFloatSeconds(result.DeallocationTimeMin);
+    float deallocationTimeAvgSeconds = ToFloatSeconds(result.DeallocationTimeAvg);
+    float deallocationTimeMaxSeconds = ToFloatSeconds(result.DeallocationTimeMax);
+
+    std::string currTime;
+    CurrentTimeToStr(currTime);
+
+    fprintf(file,
+        "%s,%s,%s,"
+        "ThreadCount=%u PoolSize=%llu FrameCount=%u TotalItemCount=%u UsedItemCount=%u...%u ItemsToMakeUnusedPercent=%u,"
+        "%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%I64u,%I64u,%I64u,%I64u\n",
+        // General
+        codeDescription,
+        testDescription,
+        currTime.c_str(),
+        // Config
+        config.ThreadCount,
+        (unsigned long long)config.PoolSize,
+        config.FrameCount,
+        config.TotalItemCount,
+        config.UsedItemCountMin,
+        config.UsedItemCountMax,
+        config.ItemsToMakeUnusedPercent,
+        // Results
+        totalTimeSeconds * 1e6f,
+        allocationTimeMinSeconds * 1e6f,
+        allocationTimeAvgSeconds * 1e6f,
+        allocationTimeMaxSeconds * 1e6f,
+        deallocationTimeMinSeconds * 1e6f,
+        deallocationTimeAvgSeconds * 1e6f,
+        deallocationTimeMaxSeconds * 1e6f,
+        result.LostAllocationCount,
+        result.LostAllocationTotalSize,
+        result.FailedAllocationCount,
+        result.FailedAllocationTotalSize);
+}
+
+static void PerformCustomMainTest(FILE* file)
+{
+    Config config{};
+    config.RandSeed = 65735476;
+    //config.MaxBytesToAllocate = 4ull * 1024 * 1024; // 4 MB
+    config.MaxBytesToAllocate = 4ull * 1024 * 1024 * 1024; // 4 GB
+    config.MemUsageProbability[0] = 1; // VMA_MEMORY_USAGE_GPU_ONLY
+    config.FreeOrder = FREE_ORDER::FORWARD;
+    config.ThreadCount = 16;
+    config.ThreadsUsingCommonAllocationsProbabilityPercent = 50;
+    config.AllocationStrategy = 0;
+
+    // Buffers
+    //config.AllocationSizes.push_back({4, 16, 1024});
+    config.AllocationSizes.push_back({4, 0x10000, 0xA00000}); // 64 KB ... 10 MB
+
+    // Images
+    //config.AllocationSizes.push_back({4, 0, 0, 4, 32});
+    //config.AllocationSizes.push_back({4, 0, 0, 256, 2048});
+
+    config.BeginBytesToAllocate = config.MaxBytesToAllocate * 5 / 100;
+    config.AdditionalOperationCount = 1024;
+
+    Result result{};
+    VkResult res = MainTest(result, config);
+    TEST(res == VK_SUCCESS);
+    WriteMainTestResult(file, "Foo", "CustomTest", config, result);
+}
+
+static void PerformCustomPoolTest(FILE* file)
+{
+    PoolTestConfig config;
+    config.PoolSize = 100 * 1024 * 1024;
+    config.RandSeed = 2345764;
+    config.ThreadCount = 1;
+    config.FrameCount = 200;
+    config.ItemsToMakeUnusedPercent = 2;
+    
+    AllocationSize allocSize = {};
+    allocSize.BufferSizeMin = 1024;
+    allocSize.BufferSizeMax = 1024 * 1024;
+    allocSize.Probability = 1;
+    config.AllocationSizes.push_back(allocSize);
+
+    allocSize.BufferSizeMin = 0;
+    allocSize.BufferSizeMax = 0;
+    allocSize.ImageSizeMin = 128;
+    allocSize.ImageSizeMax = 1024;
+    allocSize.Probability = 1;
+    config.AllocationSizes.push_back(allocSize);
+
+    config.PoolSize = config.CalcAvgResourceSize() * 200;
+    config.UsedItemCountMax = 160;
+    config.TotalItemCount = config.UsedItemCountMax * 10;
+    config.UsedItemCountMin = config.UsedItemCountMax * 80 / 100;
+
+    g_MemoryAliasingWarningEnabled = false;
+    PoolTestResult result = {};
+    TestPool_Benchmark(result, config);
+    g_MemoryAliasingWarningEnabled = true;
+
+    WritePoolTestResult(file, "Code desc", "Test desc", config, result);
+}
+
+static void PerformMainTests(FILE* file)
+{
+    uint32_t repeatCount = 1;
+    if(ConfigType >= CONFIG_TYPE_MAXIMUM) repeatCount = 3;
+
+    Config config{};
+    config.RandSeed = 65735476;
+    config.MemUsageProbability[0] = 1; // VMA_MEMORY_USAGE_GPU_ONLY
+    config.FreeOrder = FREE_ORDER::FORWARD;
+
+    size_t threadCountCount = 1;
+    switch(ConfigType)
+    {
+    case CONFIG_TYPE_MINIMUM: threadCountCount = 1; break;
+    case CONFIG_TYPE_SMALL:   threadCountCount = 2; break;
+    case CONFIG_TYPE_AVERAGE: threadCountCount = 3; break;
+    case CONFIG_TYPE_LARGE:   threadCountCount = 5; break;
+    case CONFIG_TYPE_MAXIMUM: threadCountCount = 7; break;
+    default: assert(0);
+    }
+
+    const size_t strategyCount = GetAllocationStrategyCount();
+
+    for(size_t threadCountIndex = 0; threadCountIndex < threadCountCount; ++threadCountIndex)
+    {
+        std::string desc1;
+
+        switch(threadCountIndex)
+        {
+        case 0:
+            desc1 += "1_thread";
+            config.ThreadCount = 1;
+            config.ThreadsUsingCommonAllocationsProbabilityPercent = 0;
+            break;
+        case 1:
+            desc1 += "16_threads+0%_common";
+            config.ThreadCount = 16;
+            config.ThreadsUsingCommonAllocationsProbabilityPercent = 0;
+            break;
+        case 2:
+            desc1 += "16_threads+50%_common";
+            config.ThreadCount = 16;
+            config.ThreadsUsingCommonAllocationsProbabilityPercent = 50;
+            break;
+        case 3:
+            desc1 += "16_threads+100%_common";
+            config.ThreadCount = 16;
+            config.ThreadsUsingCommonAllocationsProbabilityPercent = 100;
+            break;
+        case 4:
+            desc1 += "2_threads+0%_common";
+            config.ThreadCount = 2;
+            config.ThreadsUsingCommonAllocationsProbabilityPercent = 0;
+            break;
+        case 5:
+            desc1 += "2_threads+50%_common";
+            config.ThreadCount = 2;
+            config.ThreadsUsingCommonAllocationsProbabilityPercent = 50;
+            break;
+        case 6:
+            desc1 += "2_threads+100%_common";
+            config.ThreadCount = 2;
+            config.ThreadsUsingCommonAllocationsProbabilityPercent = 100;
+            break;
+        default:
+            assert(0);
+        }
+
+        // 0 = buffers, 1 = images, 2 = buffers and images
+        size_t buffersVsImagesCount = 2;
+        if(ConfigType >= CONFIG_TYPE_LARGE) ++buffersVsImagesCount;
+        for(size_t buffersVsImagesIndex = 0; buffersVsImagesIndex < buffersVsImagesCount; ++buffersVsImagesIndex)
+        {
+            std::string desc2 = desc1;
+            switch(buffersVsImagesIndex)
+            {
+            case 0: desc2 += ",Buffers"; break;
+            case 1: desc2 += ",Images"; break;
+            case 2: desc2 += ",Buffers+Images"; break;
+            default: assert(0);
+            }
+
+            // 0 = small, 1 = large, 2 = small and large
+            size_t smallVsLargeCount = 2;
+            if(ConfigType >= CONFIG_TYPE_LARGE) ++smallVsLargeCount;
+            for(size_t smallVsLargeIndex = 0; smallVsLargeIndex < smallVsLargeCount; ++smallVsLargeIndex)
+            {
+                std::string desc3 = desc2;
+                switch(smallVsLargeIndex)
+                {
+                case 0: desc3 += ",Small"; break;
+                case 1: desc3 += ",Large"; break;
+                case 2: desc3 += ",Small+Large"; break;
+                default: assert(0);
+                }
+
+                if(smallVsLargeIndex == 1 || smallVsLargeIndex == 2)
+                    config.MaxBytesToAllocate = 4ull * 1024 * 1024 * 1024; // 4 GB
+                else
+                    config.MaxBytesToAllocate = 4ull * 1024 * 1024;
+
+                // 0 = varying sizes min...max, 1 = set of constant sizes
+                size_t constantSizesCount = 1;
+                if(ConfigType >= CONFIG_TYPE_SMALL) ++constantSizesCount;
+                for(size_t constantSizesIndex = 0; constantSizesIndex < constantSizesCount; ++constantSizesIndex)
+                {
+                    std::string desc4 = desc3;
+                    switch(constantSizesIndex)
+                    {
+                    case 0: desc4 += " Varying_sizes"; break;
+                    case 1: desc4 += " Constant_sizes"; break;
+                    default: assert(0);
+                    }
+
+                    config.AllocationSizes.clear();
+                    // Buffers present
+                    if(buffersVsImagesIndex == 0 || buffersVsImagesIndex == 2)
+                    {
+                        // Small
+                        if(smallVsLargeIndex == 0 || smallVsLargeIndex == 2)
+                        {
+                            // Varying size
+                            if(constantSizesIndex == 0)
+                                config.AllocationSizes.push_back({4, 16, 1024});
+                            // Constant sizes
+                            else
+                            {
+                                config.AllocationSizes.push_back({1, 16, 16});
+                                config.AllocationSizes.push_back({1, 64, 64});
+                                config.AllocationSizes.push_back({1, 256, 256});
+                                config.AllocationSizes.push_back({1, 1024, 1024});
+                            }
+                        }
+                        // Large
+                        if(smallVsLargeIndex == 1 || smallVsLargeIndex == 2)
+                        {
+                            // Varying size
+                            if(constantSizesIndex == 0)
+                                config.AllocationSizes.push_back({4, 0x10000, 0xA00000}); // 64 KB ... 10 MB
+                            // Constant sizes
+                            else
+                            {
+                                config.AllocationSizes.push_back({1, 0x10000, 0x10000});
+                                config.AllocationSizes.push_back({1, 0x80000, 0x80000});
+                                config.AllocationSizes.push_back({1, 0x200000, 0x200000});
+                                config.AllocationSizes.push_back({1, 0xA00000, 0xA00000});
+                            }
+                        }
+                    }
+                    // Images present
+                    if(buffersVsImagesIndex == 1 || buffersVsImagesIndex == 2)
+                    {
+                        // Small
+                        if(smallVsLargeIndex == 0 || smallVsLargeIndex == 2)
+                        {
+                            // Varying size
+                            if(constantSizesIndex == 0)
+                                config.AllocationSizes.push_back({4, 0, 0, 4, 32});
+                            // Constant sizes
+                            else
+                            {
+                                config.AllocationSizes.push_back({1, 0, 0,  4,  4});
+                                config.AllocationSizes.push_back({1, 0, 0,  8,  8});
+                                config.AllocationSizes.push_back({1, 0, 0, 16, 16});
+                                config.AllocationSizes.push_back({1, 0, 0, 32, 32});
+                            }
+                        }
+                        // Large
+                        if(smallVsLargeIndex == 1 || smallVsLargeIndex == 2)
+                        {
+                            // Varying size
+                            if(constantSizesIndex == 0)
+                                config.AllocationSizes.push_back({4, 0, 0, 256, 2048});
+                            // Constant sizes
+                            else
+                            {
+                                config.AllocationSizes.push_back({1, 0, 0,  256,  256});
+                                config.AllocationSizes.push_back({1, 0, 0,  512,  512});
+                                config.AllocationSizes.push_back({1, 0, 0, 1024, 1024});
+                                config.AllocationSizes.push_back({1, 0, 0, 2048, 2048});
+                            }
+                        }
+                    }
+
+                    // 0 = 100%, additional_operations = 0, 1 = 50%, 2 = 5%, 3 = 95% additional_operations = a lot
+                    size_t beginBytesToAllocateCount = 1;
+                    if(ConfigType >= CONFIG_TYPE_SMALL) ++beginBytesToAllocateCount;
+                    if(ConfigType >= CONFIG_TYPE_AVERAGE) ++beginBytesToAllocateCount;
+                    if(ConfigType >= CONFIG_TYPE_LARGE) ++beginBytesToAllocateCount;
+                    for(size_t beginBytesToAllocateIndex = 0; beginBytesToAllocateIndex < beginBytesToAllocateCount; ++beginBytesToAllocateIndex)
+                    {
+                        std::string desc5 = desc4;
+
+                        switch(beginBytesToAllocateIndex)
+                        {
+                        case 0:
+                            desc5 += ",Allocate_100%";
+                            config.BeginBytesToAllocate = config.MaxBytesToAllocate;
+                            config.AdditionalOperationCount = 0;
+                            break;
+                        case 1:
+                            desc5 += ",Allocate_50%+Operations";
+                            config.BeginBytesToAllocate = config.MaxBytesToAllocate * 50 / 100;
+                            config.AdditionalOperationCount = 1024;
+                            break;
+                        case 2:
+                            desc5 += ",Allocate_5%+Operations";
+                            config.BeginBytesToAllocate = config.MaxBytesToAllocate *  5 / 100;
+                            config.AdditionalOperationCount = 1024;
+                            break;
+                        case 3:
+                            desc5 += ",Allocate_95%+Operations";
+                            config.BeginBytesToAllocate = config.MaxBytesToAllocate * 95 / 100;
+                            config.AdditionalOperationCount = 1024;
+                            break;
+                        default:
+                            assert(0);
+                        }
+
+                        for(size_t strategyIndex = 0; strategyIndex < strategyCount; ++strategyIndex)
+                        {
+                            std::string desc6 = desc5;
+                            switch(strategyIndex)
+                            {
+                            case 0:
+                                desc6 += ",BestFit";
+                                config.AllocationStrategy = VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT;
+                                break;
+                            case 1:
+                                desc6 += ",WorstFit";
+                                config.AllocationStrategy = VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT;
+                                break;
+                            case 2:
+                                desc6 += ",FirstFit";
+                                config.AllocationStrategy = VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT;
+                                break;
+                            default:
+                                assert(0);
+                            }
+
+                            desc6 += ',';
+                            desc6 += FREE_ORDER_NAMES[(uint32_t)config.FreeOrder];
+
+                            const char* testDescription = desc6.c_str();
+
+                            for(size_t repeat = 0; repeat < repeatCount; ++repeat)
+                            {
+                                printf("%s #%u\n", testDescription, (uint32_t)repeat);
+
+                                Result result{};
+                                VkResult res = MainTest(result, config);
+                                TEST(res == VK_SUCCESS);
+                                if(file)
+                                {
+                                    WriteMainTestResult(file, CODE_DESCRIPTION, testDescription, config, result);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+static void PerformPoolTests(FILE* file)
+{
+    const size_t AVG_RESOURCES_PER_POOL = 300;
+
+    uint32_t repeatCount = 1;
+    if(ConfigType >= CONFIG_TYPE_MAXIMUM) repeatCount = 3;
+
+    PoolTestConfig config{};
+    config.RandSeed = 2346343;
+    config.FrameCount = 200;
+    config.ItemsToMakeUnusedPercent = 2;
+
+    size_t threadCountCount = 1;
+    switch(ConfigType)
+    {
+    case CONFIG_TYPE_MINIMUM: threadCountCount = 1; break;
+    case CONFIG_TYPE_SMALL:   threadCountCount = 2; break;
+    case CONFIG_TYPE_AVERAGE: threadCountCount = 2; break;
+    case CONFIG_TYPE_LARGE:   threadCountCount = 3; break;
+    case CONFIG_TYPE_MAXIMUM: threadCountCount = 3; break;
+    default: assert(0);
+    }
+    for(size_t threadCountIndex = 0; threadCountIndex < threadCountCount; ++threadCountIndex)
+    {
+        std::string desc1;
+
+        switch(threadCountIndex)
+        {
+        case 0:
+            desc1 += "1_thread";
+            config.ThreadCount = 1;
+            break;
+        case 1:
+            desc1 += "16_threads";
+            config.ThreadCount = 16;
+            break;
+        case 2:
+            desc1 += "2_threads";
+            config.ThreadCount = 2;
+            break;
+        default:
+            assert(0);
+        }
+
+        // 0 = buffers, 1 = images, 2 = buffers and images
+        size_t buffersVsImagesCount = 2;
+        if(ConfigType >= CONFIG_TYPE_LARGE) ++buffersVsImagesCount;
+        for(size_t buffersVsImagesIndex = 0; buffersVsImagesIndex < buffersVsImagesCount; ++buffersVsImagesIndex)
+        {
+            std::string desc2 = desc1;
+            switch(buffersVsImagesIndex)
+            {
+            case 0: desc2 += " Buffers"; break;
+            case 1: desc2 += " Images"; break;
+            case 2: desc2 += " Buffers+Images"; break;
+            default: assert(0);
+            }
+
+            // 0 = small, 1 = large, 2 = small and large
+            size_t smallVsLargeCount = 2;
+            if(ConfigType >= CONFIG_TYPE_LARGE) ++smallVsLargeCount;
+            for(size_t smallVsLargeIndex = 0; smallVsLargeIndex < smallVsLargeCount; ++smallVsLargeIndex)
+            {
+                std::string desc3 = desc2;
+                switch(smallVsLargeIndex)
+                {
+                case 0: desc3 += " Small"; break;
+                case 1: desc3 += " Large"; break;
+                case 2: desc3 += " Small+Large"; break;
+                default: assert(0);
+                }
+
+                if(smallVsLargeIndex == 1 || smallVsLargeIndex == 2)
+                    config.PoolSize = 6ull * 1024 * 1024 * 1024; // 6 GB
+                else
+                    config.PoolSize = 4ull * 1024 * 1024;
+
+                // 0 = varying sizes min...max, 1 = set of constant sizes
+                size_t constantSizesCount = 1;
+                if(ConfigType >= CONFIG_TYPE_SMALL) ++constantSizesCount;
+                for(size_t constantSizesIndex = 0; constantSizesIndex < constantSizesCount; ++constantSizesIndex)
+                {
+                    std::string desc4 = desc3;
+                    switch(constantSizesIndex)
+                    {
+                    case 0: desc4 += " Varying_sizes"; break;
+                    case 1: desc4 += " Constant_sizes"; break;
+                    default: assert(0);
+                    }
+
+                    config.AllocationSizes.clear();
+                    // Buffers present
+                    if(buffersVsImagesIndex == 0 || buffersVsImagesIndex == 2)
+                    {
+                        // Small
+                        if(smallVsLargeIndex == 0 || smallVsLargeIndex == 2)
+                        {
+                            // Varying size
+                            if(constantSizesIndex == 0)
+                                config.AllocationSizes.push_back({4, 16, 1024});
+                            // Constant sizes
+                            else
+                            {
+                                config.AllocationSizes.push_back({1, 16, 16});
+                                config.AllocationSizes.push_back({1, 64, 64});
+                                config.AllocationSizes.push_back({1, 256, 256});
+                                config.AllocationSizes.push_back({1, 1024, 1024});
+                            }
+                        }
+                        // Large
+                        if(smallVsLargeIndex == 1 || smallVsLargeIndex == 2)
+                        {
+                            // Varying size
+                            if(constantSizesIndex == 0)
+                                config.AllocationSizes.push_back({4, 0x10000, 0xA00000}); // 64 KB ... 10 MB
+                            // Constant sizes
+                            else
+                            {
+                                config.AllocationSizes.push_back({1, 0x10000, 0x10000});
+                                config.AllocationSizes.push_back({1, 0x80000, 0x80000});
+                                config.AllocationSizes.push_back({1, 0x200000, 0x200000});
+                                config.AllocationSizes.push_back({1, 0xA00000, 0xA00000});
+                            }
+                        }
+                    }
+                    // Images present
+                    if(buffersVsImagesIndex == 1 || buffersVsImagesIndex == 2)
+                    {
+                        // Small
+                        if(smallVsLargeIndex == 0 || smallVsLargeIndex == 2)
+                        {
+                            // Varying size
+                            if(constantSizesIndex == 0)
+                                config.AllocationSizes.push_back({4, 0, 0, 4, 32});
+                            // Constant sizes
+                            else
+                            {
+                                config.AllocationSizes.push_back({1, 0, 0,  4,  4});
+                                config.AllocationSizes.push_back({1, 0, 0,  8,  8});
+                                config.AllocationSizes.push_back({1, 0, 0, 16, 16});
+                                config.AllocationSizes.push_back({1, 0, 0, 32, 32});
+                            }
+                        }
+                        // Large
+                        if(smallVsLargeIndex == 1 || smallVsLargeIndex == 2)
+                        {
+                            // Varying size
+                            if(constantSizesIndex == 0)
+                                config.AllocationSizes.push_back({4, 0, 0, 256, 2048});
+                            // Constant sizes
+                            else
+                            {
+                                config.AllocationSizes.push_back({1, 0, 0,  256,  256});
+                                config.AllocationSizes.push_back({1, 0, 0,  512,  512});
+                                config.AllocationSizes.push_back({1, 0, 0, 1024, 1024});
+                                config.AllocationSizes.push_back({1, 0, 0, 2048, 2048});
+                            }
+                        }
+                    }
+
+                    const VkDeviceSize avgResourceSize = config.CalcAvgResourceSize();
+                    config.PoolSize = avgResourceSize * AVG_RESOURCES_PER_POOL;
+
+                    // 0 = 66%, 1 = 133%, 2 = 100%, 3 = 33%, 4 = 166%
+                    size_t subscriptionModeCount;
+                    switch(ConfigType)
+                    {
+                    case CONFIG_TYPE_MINIMUM: subscriptionModeCount = 2; break;
+                    case CONFIG_TYPE_SMALL:   subscriptionModeCount = 2; break;
+                    case CONFIG_TYPE_AVERAGE: subscriptionModeCount = 3; break;
+                    case CONFIG_TYPE_LARGE:   subscriptionModeCount = 5; break;
+                    case CONFIG_TYPE_MAXIMUM: subscriptionModeCount = 5; break;
+                    default: assert(0);
+                    }
+                    for(size_t subscriptionModeIndex = 0; subscriptionModeIndex < subscriptionModeCount; ++subscriptionModeIndex)
+                    {
+                        std::string desc5 = desc4;
+
+                        switch(subscriptionModeIndex)
+                        {
+                        case 0:
+                            desc5 += " Subscription_66%";
+                            config.UsedItemCountMax = AVG_RESOURCES_PER_POOL * 66 / 100;
+                            break;
+                        case 1:
+                            desc5 += " Subscription_133%";
+                            config.UsedItemCountMax = AVG_RESOURCES_PER_POOL * 133 / 100;
+                            break;
+                        case 2:
+                            desc5 += " Subscription_100%";
+                            config.UsedItemCountMax = AVG_RESOURCES_PER_POOL;
+                            break;
+                        case 3:
+                            desc5 += " Subscription_33%";
+                            config.UsedItemCountMax = AVG_RESOURCES_PER_POOL * 33 / 100;
+                            break;
+                        case 4:
+                            desc5 += " Subscription_166%";
+                            config.UsedItemCountMax = AVG_RESOURCES_PER_POOL * 166 / 100;
+                            break;
+                        default:
+                            assert(0);
+                        }
+
+                        config.TotalItemCount = config.UsedItemCountMax * 5;
+                        config.UsedItemCountMin = config.UsedItemCountMax * 80 / 100;
+
+                        const char* testDescription = desc5.c_str();
+
+                        for(size_t repeat = 0; repeat < repeatCount; ++repeat)
+                        {
+                            printf("%s #%u\n", testDescription, (uint32_t)repeat);
+
+                            PoolTestResult result{};
+                            g_MemoryAliasingWarningEnabled = false;
+                            TestPool_Benchmark(result, config);
+                            g_MemoryAliasingWarningEnabled = true;
+                            WritePoolTestResult(file, CODE_DESCRIPTION, testDescription, config, result);
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+static void BasicTestBuddyAllocator()
+{
+    wprintf(L"Basic test buddy allocator\n");
+
+    RandomNumberGenerator rand{76543};
+
+    VkBufferCreateInfo sampleBufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+    sampleBufCreateInfo.size = 1024; // Whatever.
+    sampleBufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
+
+    VmaAllocationCreateInfo sampleAllocCreateInfo = {};
+    sampleAllocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+
+    VmaPoolCreateInfo poolCreateInfo = {};
+    VkResult res = vmaFindMemoryTypeIndexForBufferInfo(g_hAllocator, &sampleBufCreateInfo, &sampleAllocCreateInfo, &poolCreateInfo.memoryTypeIndex);
+    TEST(res == VK_SUCCESS);
+
+    // Deliberately adding 1023 to test usable size smaller than memory block size.
+    poolCreateInfo.blockSize = 1024 * 1024 + 1023;
+    poolCreateInfo.flags = VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT;
+    //poolCreateInfo.minBlockCount = poolCreateInfo.maxBlockCount = 1;
+
+    VmaPool pool = nullptr;
+    res = vmaCreatePool(g_hAllocator, &poolCreateInfo, &pool);
+    TEST(res == VK_SUCCESS);
+
+    VkBufferCreateInfo bufCreateInfo = sampleBufCreateInfo;
+
+    VmaAllocationCreateInfo allocCreateInfo = {};
+    allocCreateInfo.pool = pool;
+
+    std::vector<BufferInfo> bufInfo;
+    BufferInfo newBufInfo;
+    VmaAllocationInfo allocInfo;
+    
+    bufCreateInfo.size = 1024 * 256;
+    res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo,
+        &newBufInfo.Buffer, &newBufInfo.Allocation, &allocInfo);
+    TEST(res == VK_SUCCESS);
+    bufInfo.push_back(newBufInfo);
+
+    bufCreateInfo.size = 1024 * 512;
+    res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo,
+        &newBufInfo.Buffer, &newBufInfo.Allocation, &allocInfo);
+    TEST(res == VK_SUCCESS);
+    bufInfo.push_back(newBufInfo);
+
+    bufCreateInfo.size = 1024 * 128;
+    res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo,
+        &newBufInfo.Buffer, &newBufInfo.Allocation, &allocInfo);
+    TEST(res == VK_SUCCESS);
+    bufInfo.push_back(newBufInfo);
+    
+    // Test very small allocation, smaller than minimum node size.
+    bufCreateInfo.size = 1;
+    res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo,
+        &newBufInfo.Buffer, &newBufInfo.Allocation, &allocInfo);
+    TEST(res == VK_SUCCESS);
+    bufInfo.push_back(newBufInfo);
+
+    // Test some small allocation with alignment requirement.
+    {
+        VkMemoryRequirements memReq;
+        memReq.alignment = 256;
+        memReq.memoryTypeBits = UINT32_MAX;
+        memReq.size = 32;
+
+        newBufInfo.Buffer = VK_NULL_HANDLE;
+        res = vmaAllocateMemory(g_hAllocator, &memReq, &allocCreateInfo,
+            &newBufInfo.Allocation, &allocInfo);
+        TEST(res == VK_SUCCESS);
+        TEST(allocInfo.offset % memReq.alignment == 0);
+        bufInfo.push_back(newBufInfo);
+    }
+
+    //SaveAllocatorStatsToFile(L"TEST.json");
+
+    VmaPoolStats stats = {};
+    vmaGetPoolStats(g_hAllocator, pool, &stats);
+    int DBG = 0; // Set breakpoint here to inspect `stats`.
+
+    // Allocate enough new buffers to surely fall into second block.
+    for(uint32_t i = 0; i < 32; ++i)
+    {
+        bufCreateInfo.size = 1024 * (rand.Generate() % 32 + 1);
+        res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo,
+            &newBufInfo.Buffer, &newBufInfo.Allocation, &allocInfo);
+        TEST(res == VK_SUCCESS);
+        bufInfo.push_back(newBufInfo);
+    }
+
+    SaveAllocatorStatsToFile(L"BuddyTest01.json");
+
+    // Destroy the buffers in random order.
+    while(!bufInfo.empty())
+    {
+        const size_t indexToDestroy = rand.Generate() % bufInfo.size();
+        const BufferInfo& currBufInfo = bufInfo[indexToDestroy];
+        vmaDestroyBuffer(g_hAllocator, currBufInfo.Buffer, currBufInfo.Allocation);
+        bufInfo.erase(bufInfo.begin() + indexToDestroy);
+    }
+
+    vmaDestroyPool(g_hAllocator, pool);
+}
+
+static void BasicTestAllocatePages()
+{
+    wprintf(L"Basic test allocate pages\n");
+
+    RandomNumberGenerator rand{765461};
+
+    VkBufferCreateInfo sampleBufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+    sampleBufCreateInfo.size = 1024; // Whatever.
+    sampleBufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+
+    VmaAllocationCreateInfo sampleAllocCreateInfo = {};
+    sampleAllocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
+
+    VmaPoolCreateInfo poolCreateInfo = {};
+    VkResult res = vmaFindMemoryTypeIndexForBufferInfo(g_hAllocator, &sampleBufCreateInfo, &sampleAllocCreateInfo, &poolCreateInfo.memoryTypeIndex);
+    TEST(res == VK_SUCCESS);
+
+    // 1 block of 1 MB.
+    poolCreateInfo.blockSize = 1024 * 1024;
+    poolCreateInfo.minBlockCount = poolCreateInfo.maxBlockCount = 1;
+
+    // Create pool.
+    VmaPool pool = nullptr;
+    res = vmaCreatePool(g_hAllocator, &poolCreateInfo, &pool);
+    TEST(res == VK_SUCCESS);
+
+    // Make 100 allocations of 4 KB - they should fit into the pool.
+    VkMemoryRequirements memReq;
+    memReq.memoryTypeBits = UINT32_MAX;
+    memReq.alignment = 4 * 1024;
+    memReq.size = 4 * 1024;
+
+    VmaAllocationCreateInfo allocCreateInfo = {};
+    allocCreateInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
+    allocCreateInfo.pool = pool;
+
+    constexpr uint32_t allocCount = 100;
+
+    std::vector<VmaAllocation> alloc{allocCount};
+    std::vector<VmaAllocationInfo> allocInfo{allocCount};
+    res = vmaAllocateMemoryPages(g_hAllocator, &memReq, &allocCreateInfo, allocCount, alloc.data(), allocInfo.data());
+    TEST(res == VK_SUCCESS);
+    for(uint32_t i = 0; i < allocCount; ++i)
+    {
+        TEST(alloc[i] != VK_NULL_HANDLE &&
+            allocInfo[i].pMappedData != nullptr &&
+            allocInfo[i].deviceMemory == allocInfo[0].deviceMemory &&
+            allocInfo[i].memoryType == allocInfo[0].memoryType);
+    }
+
+    // Free the allocations.
+    vmaFreeMemoryPages(g_hAllocator, allocCount, alloc.data());
+    std::fill(alloc.begin(), alloc.end(), nullptr);
+    std::fill(allocInfo.begin(), allocInfo.end(), VmaAllocationInfo{});
+
+    // Try to make 100 allocations of 100 KB. This call should fail due to not enough memory.
+    // Also test optional allocationInfo = null.
+    memReq.size = 100 * 1024;
+    res = vmaAllocateMemoryPages(g_hAllocator, &memReq, &allocCreateInfo, allocCount, alloc.data(), nullptr);
+    TEST(res != VK_SUCCESS);
+    TEST(std::find_if(alloc.begin(), alloc.end(), [](VmaAllocation alloc){ return alloc != VK_NULL_HANDLE; }) == alloc.end());
+
+    // Make 100 allocations of 4 KB, but with required alignment of 128 KB. This should also fail.
+    memReq.size = 4 * 1024;
+    memReq.alignment = 128 * 1024;
+    res = vmaAllocateMemoryPages(g_hAllocator, &memReq, &allocCreateInfo, allocCount, alloc.data(), allocInfo.data());
+    TEST(res != VK_SUCCESS);
+
+    // Make 100 dedicated allocations of 4 KB.
+    memReq.alignment = 4 * 1024;
+    memReq.size = 4 * 1024;
+
+    VmaAllocationCreateInfo dedicatedAllocCreateInfo = {};
+    dedicatedAllocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
+    dedicatedAllocCreateInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
+    res = vmaAllocateMemoryPages(g_hAllocator, &memReq, &dedicatedAllocCreateInfo, allocCount, alloc.data(), allocInfo.data());
+    TEST(res == VK_SUCCESS);
+    for(uint32_t i = 0; i < allocCount; ++i)
+    {
+        TEST(alloc[i] != VK_NULL_HANDLE &&
+            allocInfo[i].pMappedData != nullptr &&
+            allocInfo[i].memoryType == allocInfo[0].memoryType &&
+            allocInfo[i].offset == 0);
+        if(i > 0)
+        {
+            TEST(allocInfo[i].deviceMemory != allocInfo[0].deviceMemory);
+        }
+    }
+
+    // Free the allocations.
+    vmaFreeMemoryPages(g_hAllocator, allocCount, alloc.data());
+    std::fill(alloc.begin(), alloc.end(), nullptr);
+    std::fill(allocInfo.begin(), allocInfo.end(), VmaAllocationInfo{});
+
+    vmaDestroyPool(g_hAllocator, pool);
+}
+
+// Test the testing environment.
+static void TestGpuData()
+{
+    RandomNumberGenerator rand = { 53434 };
+
+    std::vector<AllocInfo> allocInfo;
+
+    for(size_t i = 0; i < 100; ++i)
+    {
+        AllocInfo info = {};
+
+        info.m_BufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+        info.m_BufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT |
+            VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
+            VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
+        info.m_BufferInfo.size = 1024 * 1024 * (rand.Generate() % 9 + 1);
+
+        VmaAllocationCreateInfo allocCreateInfo = {};
+        allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+
+        VkResult res = vmaCreateBuffer(g_hAllocator, &info.m_BufferInfo, &allocCreateInfo, &info.m_Buffer, &info.m_Allocation, nullptr);
+        TEST(res == VK_SUCCESS);
+
+        info.m_StartValue = rand.Generate();
+
+        allocInfo.push_back(std::move(info));
+    }
+
+    UploadGpuData(allocInfo.data(), allocInfo.size());
+
+    ValidateGpuData(allocInfo.data(), allocInfo.size());
+
+    DestroyAllAllocations(allocInfo);
+}
+
+void Test()
+{
+    wprintf(L"TESTING:\n");
+
+    if(false)
+    {
+        ////////////////////////////////////////////////////////////////////////////////
+        // Temporarily insert custom tests here:
+        return;
+    }
+
+    // # Simple tests
+
+    TestBasics();
+    //TestGpuData(); // Not calling this because it's just testing the testing environment.
+#if VMA_DEBUG_MARGIN
+    TestDebugMargin();
+#else
+    TestPool_SameSize();
+    TestPool_MinBlockCount();
+    TestHeapSizeLimit();
+#endif
+#if VMA_DEBUG_INITIALIZE_ALLOCATIONS
+    TestAllocationsInitialization();
+#endif
+    TestMemoryUsage();
+    TestDeviceCoherentMemory();
+    TestBudget();
+    TestMapping();
+    TestDeviceLocalMapped();
+    TestMappingMultithreaded();
+    TestLinearAllocator();
+    ManuallyTestLinearAllocator();
+    TestLinearAllocatorMultiBlock();
+
+    BasicTestBuddyAllocator();
+    BasicTestAllocatePages();
+
+    if(g_BufferDeviceAddressEnabled)
+        TestBufferDeviceAddress();
+
+    {
+        FILE* file;
+        fopen_s(&file, "Algorithms.csv", "w");
+        assert(file != NULL);
+        BenchmarkAlgorithms(file);
+        fclose(file);
+    }
+
+    TestDefragmentationSimple();
+    TestDefragmentationFull();
+    TestDefragmentationWholePool();
+    TestDefragmentationGpu();
+    TestDefragmentationIncrementalBasic();
+    TestDefragmentationIncrementalComplex();
+
+    // # Detailed tests
+    FILE* file;
+    fopen_s(&file, "Results.csv", "w");
+    assert(file != NULL);
+    
+    WriteMainTestResultHeader(file);
+    PerformMainTests(file);
+    //PerformCustomMainTest(file);
+
+    WritePoolTestResultHeader(file);
+    PerformPoolTests(file);
+    //PerformCustomPoolTest(file);
+    
+    fclose(file);
+    
+    wprintf(L"Done.\n");
+}
+
+#endif // #ifdef _WIN32
diff --git a/third_party/VulkanMemoryAllocator/src/Tests.h b/third_party/VulkanMemoryAllocator/src/Tests.h
new file mode 100644
index 0000000..50f4ac8
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/src/Tests.h
@@ -0,0 +1,32 @@
+//
+// Copyright (c) 2017-2020 Advanced Micro Devices, Inc. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#ifndef TESTS_H_
+#define TESTS_H_
+
+#ifdef _WIN32
+
+void Test();
+
+#endif // #ifdef _WIN32
+
+#endif
diff --git a/third_party/VulkanMemoryAllocator/src/VmaReplay/Common.cpp b/third_party/VulkanMemoryAllocator/src/VmaReplay/Common.cpp
new file mode 100644
index 0000000..a66e973
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/src/VmaReplay/Common.cpp
@@ -0,0 +1,721 @@
+//
+// Copyright (c) 2017-2020 Advanced Micro Devices, Inc. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#include "Common.h"
+
+bool StrRangeToPtrList(const StrRange& s, std::vector<uint64_t>& out)
+{
+    out.clear();
+    StrRange currRange = { s.beg, nullptr };
+    while(currRange.beg < s.end)
+    {
+        currRange.end = currRange.beg;
+        while(currRange.end < s.end && *currRange.end != ' ')
+        {
+            ++currRange.end;
+        }
+
+        uint64_t ptr = 0;
+        if(!StrRangeToPtr(currRange, ptr))
+        {
+            return false;
+        }
+        out.push_back(ptr);
+
+        currRange.beg = currRange.end + 1;
+    }
+    return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// LineSplit class
+
+bool LineSplit::GetNextLine(StrRange& out)
+{
+    if(m_NextLineBeg < m_NumBytes)
+    {
+        out.beg = m_Data + m_NextLineBeg;
+        size_t currLineEnd = m_NextLineBeg;
+        while(currLineEnd < m_NumBytes && m_Data[currLineEnd] != '\n')
+            ++currLineEnd;
+        out.end = m_Data + currLineEnd;
+        // Ignore trailing '\r' to support Windows end of line.
+        if(out.end > out.beg && *(out.end - 1) == '\r')
+        {
+            --out.end;
+        }
+        m_NextLineBeg = currLineEnd + 1; // Past '\n'
+        ++m_NextLineIndex;
+        return true;
+    }
+    else
+        return false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// CsvSplit class
+
+void CsvSplit::Set(const StrRange& line, size_t maxCount)
+{
+    assert(maxCount <= RANGE_COUNT_MAX);
+    m_Line = line;
+    const size_t strLen = line.length();
+    size_t rangeIndex = 0;
+    size_t charIndex = 0;
+    while(charIndex < strLen && rangeIndex < maxCount)
+    {
+        m_Ranges[rangeIndex * 2] = charIndex;
+        while(charIndex < strLen && (rangeIndex + 1 == maxCount || m_Line.beg[charIndex] != ','))
+            ++charIndex;
+        m_Ranges[rangeIndex * 2 + 1] = charIndex;
+        ++rangeIndex;
+        ++charIndex; // Past ','
+    }
+    m_Count = rangeIndex;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// class CmdLineParser
+
+bool CmdLineParser::ReadNextArg(std::string *OutArg)
+{
+	if (m_argv != NULL)
+	{
+		if (m_ArgIndex >= (size_t)m_argc) return false;
+
+		*OutArg = m_argv[m_ArgIndex];
+		m_ArgIndex++;
+		return true;
+	}
+	else
+	{
+		if (m_ArgIndex >= m_CmdLineLength) return false;
+		
+		OutArg->clear();
+		bool InsideQuotes = false;
+		while (m_ArgIndex < m_CmdLineLength)
+		{
+			char Ch = m_CmdLine[m_ArgIndex];
+			if (Ch == '\\')
+			{
+				bool FollowedByQuote = false;
+				size_t BackslashCount = 1;
+				size_t TmpIndex = m_ArgIndex + 1;
+				while (TmpIndex < m_CmdLineLength)
+				{
+					char TmpCh = m_CmdLine[TmpIndex];
+					if (TmpCh == '\\')
+					{
+						BackslashCount++;
+						TmpIndex++;
+					}
+					else if (TmpCh == '"')
+					{
+						FollowedByQuote = true;
+						break;
+					}
+					else
+						break;
+				}
+
+				if (FollowedByQuote)
+				{
+					if (BackslashCount % 2 == 0)
+					{
+						for (size_t i = 0; i < BackslashCount / 2; i++)
+							*OutArg += '\\';
+						m_ArgIndex += BackslashCount + 1;
+						InsideQuotes = !InsideQuotes;
+					}
+					else
+					{
+						for (size_t i = 0; i < BackslashCount / 2; i++)
+							*OutArg += '\\';
+						*OutArg += '"';
+						m_ArgIndex += BackslashCount + 1;
+					}
+				}
+				else
+				{
+					for (size_t i = 0; i < BackslashCount; i++)
+						*OutArg += '\\';
+					m_ArgIndex += BackslashCount;
+				}
+			}
+			else if (Ch == '"')
+			{
+				InsideQuotes = !InsideQuotes;
+				m_ArgIndex++;
+			}
+			else if (isspace(Ch))
+			{
+				if (InsideQuotes)
+				{
+					*OutArg += Ch;
+					m_ArgIndex++;
+				}
+				else
+				{
+					m_ArgIndex++;
+					break;
+				}
+			}
+			else
+			{
+				*OutArg += Ch;
+				m_ArgIndex++;
+			}
+		}
+
+		while (m_ArgIndex < m_CmdLineLength && isspace(m_CmdLine[m_ArgIndex]))
+			m_ArgIndex++;
+
+		return true;
+	}
+}
+
+CmdLineParser::SHORT_OPT * CmdLineParser::FindShortOpt(char Opt)
+{
+	for (size_t i = 0; i < m_ShortOpts.size(); i++)
+		if (m_ShortOpts[i].Opt == Opt)
+			return &m_ShortOpts[i];
+	return NULL;
+}
+
+CmdLineParser::LONG_OPT * CmdLineParser::FindLongOpt(const std::string &Opt)
+{
+	for (size_t i = 0; i < m_LongOpts.size(); i++)
+		if (m_LongOpts[i].Opt == Opt)
+			return &m_LongOpts[i];
+	return NULL;
+}
+
+CmdLineParser::CmdLineParser(int argc, char **argv) :
+	m_argv(argv),
+	m_CmdLine(NULL),
+	m_argc(argc),
+	m_CmdLineLength(0),
+	m_ArgIndex(1),
+	m_InsideMultioption(false),
+	m_LastArgIndex(0),
+	m_LastOptId(0)
+{
+	assert(argc > 0);
+	assert(argv != NULL);
+}
+
+CmdLineParser::CmdLineParser(const char *CmdLine) :
+	m_argv(NULL),
+	m_CmdLine(CmdLine),
+	m_argc(0),
+	m_ArgIndex(0),
+	m_InsideMultioption(false),
+	m_LastArgIndex(0),
+	m_LastOptId(0)
+{
+	assert(CmdLine != NULL);
+
+	m_CmdLineLength = strlen(m_CmdLine);
+
+	while (m_ArgIndex < m_CmdLineLength && isspace(m_CmdLine[m_ArgIndex]))
+		m_ArgIndex++;
+}
+
+void CmdLineParser::RegisterOpt(uint32_t Id, char Opt, bool Parameter)
+{
+	assert(Opt != '\0');
+
+	m_ShortOpts.push_back(SHORT_OPT(Id, Opt, Parameter));
+}
+
+void CmdLineParser::RegisterOpt(uint32_t Id, const std::string &Opt, bool Parameter)
+{
+	assert(!Opt.empty());
+	
+	m_LongOpts.push_back(LONG_OPT(Id, Opt, Parameter));
+}
+
+CmdLineParser::RESULT CmdLineParser::ReadNext()
+{
+	if (m_InsideMultioption)
+	{
+		assert(m_LastArgIndex < m_LastArg.length());
+		SHORT_OPT *so = FindShortOpt(m_LastArg[m_LastArgIndex]);
+		if (so == NULL)
+		{
+			m_LastOptId = 0;
+			m_LastParameter.clear();
+			return CmdLineParser::RESULT_ERROR;
+		}
+		if (so->Parameter)
+		{
+			if (m_LastArg.length() == m_LastArgIndex+1)
+			{
+				if (!ReadNextArg(&m_LastParameter))
+				{
+					m_LastOptId = 0;
+					m_LastParameter.clear();
+					return CmdLineParser::RESULT_ERROR;
+				}
+				m_InsideMultioption = false;
+				m_LastOptId = so->Id;
+				return CmdLineParser::RESULT_OPT;
+			}
+			else if (m_LastArg[m_LastArgIndex+1] == '=')
+			{
+				m_InsideMultioption = false;
+				m_LastParameter = m_LastArg.substr(m_LastArgIndex+2);
+				m_LastOptId = so->Id;
+				return CmdLineParser::RESULT_OPT;
+			}
+			else
+			{
+				m_InsideMultioption = false;
+				m_LastParameter = m_LastArg.substr(m_LastArgIndex+1);
+				m_LastOptId = so->Id;
+				return CmdLineParser::RESULT_OPT;
+			}
+		}
+		else
+		{
+			if (m_LastArg.length() == m_LastArgIndex+1)
+			{
+				m_InsideMultioption = false;
+				m_LastParameter.clear();
+				m_LastOptId = so->Id;
+				return CmdLineParser::RESULT_OPT;
+			}
+			else
+			{
+				m_LastArgIndex++;
+
+				m_LastParameter.clear();
+				m_LastOptId = so->Id;
+				return CmdLineParser::RESULT_OPT;
+			}
+		}
+	}
+	else
+	{
+		if (!ReadNextArg(&m_LastArg))
+		{
+			m_LastParameter.clear();
+			m_LastOptId = 0;
+			return CmdLineParser::RESULT_END;
+		}
+		
+		if (!m_LastArg.empty() && m_LastArg[0] == '-')
+		{
+			if (m_LastArg.length() > 1 && m_LastArg[1] == '-')
+			{
+				size_t EqualIndex = m_LastArg.find('=', 2);
+				if (EqualIndex != std::string::npos)
+				{
+					LONG_OPT *lo = FindLongOpt(m_LastArg.substr(2, EqualIndex-2));
+					if (lo == NULL || lo->Parameter == false)
+					{
+						m_LastOptId = 0;
+						m_LastParameter.clear();
+						return CmdLineParser::RESULT_ERROR;
+					}
+					m_LastParameter = m_LastArg.substr(EqualIndex+1);
+					m_LastOptId = lo->Id;
+					return CmdLineParser::RESULT_OPT;
+				}
+				else
+				{
+					LONG_OPT *lo = FindLongOpt(m_LastArg.substr(2));
+					if (lo == NULL)
+					{
+						m_LastOptId = 0;
+						m_LastParameter.clear();
+						return CmdLineParser::RESULT_ERROR;
+					}
+					if (lo->Parameter)
+					{
+						if (!ReadNextArg(&m_LastParameter))
+						{
+							m_LastOptId = 0;
+							m_LastParameter.clear();
+							return CmdLineParser::RESULT_ERROR;
+						}
+					}
+					else
+						m_LastParameter.clear();
+					m_LastOptId = lo->Id;
+					return CmdLineParser::RESULT_OPT;
+				}
+			}
+			else
+			{
+				if (m_LastArg.length() < 2)
+				{
+					m_LastOptId = 0;
+					m_LastParameter.clear();
+					return CmdLineParser::RESULT_ERROR;
+				}
+				SHORT_OPT *so = FindShortOpt(m_LastArg[1]);
+				if (so == NULL)
+				{
+					m_LastOptId = 0;
+					m_LastParameter.clear();
+					return CmdLineParser::RESULT_ERROR;
+				}
+				if (so->Parameter)
+				{
+					if (m_LastArg.length() == 2)
+					{
+						if (!ReadNextArg(&m_LastParameter))
+						{
+							m_LastOptId = 0;
+							m_LastParameter.clear();
+							return CmdLineParser::RESULT_ERROR;
+						}
+						m_LastOptId = so->Id;
+						return CmdLineParser::RESULT_OPT;
+					}
+					else if (m_LastArg[2] == '=')
+					{
+						m_LastParameter = m_LastArg.substr(3);
+						m_LastOptId = so->Id;
+						return CmdLineParser::RESULT_OPT;
+					}
+					else
+					{
+						m_LastParameter = m_LastArg.substr(2);
+						m_LastOptId = so->Id;
+						return CmdLineParser::RESULT_OPT;
+					}
+				}
+				else
+				{
+					if (m_LastArg.length() == 2)
+					{
+						m_LastParameter.clear();
+						m_LastOptId = so->Id;
+						return CmdLineParser::RESULT_OPT;
+					}
+					else
+					{
+						m_InsideMultioption = true;
+						m_LastArgIndex = 2;
+
+						m_LastParameter.clear();
+						m_LastOptId = so->Id;
+						return CmdLineParser::RESULT_OPT;
+					}
+				}
+			}
+		}
+		else if (!m_LastArg.empty() && m_LastArg[0] == '/')
+		{
+			size_t EqualIndex = m_LastArg.find('=', 1);
+			if (EqualIndex != std::string::npos)
+			{
+				if (EqualIndex == 2)
+				{
+					SHORT_OPT *so = FindShortOpt(m_LastArg[1]);
+					if (so != NULL)
+					{
+						if (so->Parameter == false)	
+						{
+							m_LastOptId = 0;
+							m_LastParameter.clear();
+							return CmdLineParser::RESULT_ERROR;
+						}
+						m_LastParameter = m_LastArg.substr(EqualIndex+1);
+						m_LastOptId = so->Id;
+						return CmdLineParser::RESULT_OPT;
+					}
+				}
+				LONG_OPT *lo = FindLongOpt(m_LastArg.substr(1, EqualIndex-1));
+				if (lo == NULL || lo->Parameter == false)
+				{
+					m_LastOptId = 0;
+					m_LastParameter.clear();
+					return CmdLineParser::RESULT_ERROR;
+				}
+				m_LastParameter = m_LastArg.substr(EqualIndex+1);
+				m_LastOptId = lo->Id;
+				return CmdLineParser::RESULT_OPT;
+			}
+			else
+			{
+				if (m_LastArg.length() == 2)
+				{
+					SHORT_OPT *so = FindShortOpt(m_LastArg[1]);
+					if (so != NULL)
+					{
+						if (so->Parameter)
+						{
+							if (!ReadNextArg(&m_LastParameter))
+							{
+								m_LastOptId = 0;
+								m_LastParameter.clear();
+								return CmdLineParser::RESULT_ERROR;
+							}
+						}
+						else
+							m_LastParameter.clear();
+						m_LastOptId = so->Id;
+						return CmdLineParser::RESULT_OPT;
+					}
+				}
+				LONG_OPT *lo = FindLongOpt(m_LastArg.substr(1));
+				if (lo == NULL)
+				{
+					m_LastOptId = 0;
+					m_LastParameter.clear();
+					return CmdLineParser::RESULT_ERROR;
+				}
+				if (lo->Parameter)
+				{
+					if (!ReadNextArg(&m_LastParameter))
+					{
+						m_LastOptId = 0;
+						m_LastParameter.clear();
+						return CmdLineParser::RESULT_ERROR;
+					}
+				}
+				else
+					m_LastParameter.clear();
+				m_LastOptId = lo->Id;
+				return CmdLineParser::RESULT_OPT;
+			}
+		}
+		else
+		{
+			m_LastOptId = 0;
+			m_LastParameter = m_LastArg;
+			return CmdLineParser::RESULT_PARAMETER;
+		}
+	}
+}
+
+uint32_t CmdLineParser::GetOptId()
+{
+	return m_LastOptId;
+}
+
+const std::string & CmdLineParser::GetParameter()
+{
+	return m_LastParameter;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Glolals
+
+/*
+
+void SetConsoleColor(CONSOLE_COLOR color)
+{
+    WORD attr = 0;
+    switch(color)
+    {
+    case CONSOLE_COLOR::INFO:
+        attr = FOREGROUND_INTENSITY;;
+        break;
+    case CONSOLE_COLOR::NORMAL:
+        attr = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
+        break;
+    case CONSOLE_COLOR::WARNING:
+        attr = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY;
+        break;
+    case CONSOLE_COLOR::ERROR_:
+        attr = FOREGROUND_RED | FOREGROUND_INTENSITY;
+        break;
+    default:
+        assert(0);
+    }
+
+    HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
+    SetConsoleTextAttribute(out, attr);
+}
+
+void PrintMessage(CONSOLE_COLOR color, const char* msg)
+{
+    if(color != CONSOLE_COLOR::NORMAL)
+        SetConsoleColor(color);
+    
+    printf("%s\n", msg);
+    
+    if (color != CONSOLE_COLOR::NORMAL)
+        SetConsoleColor(CONSOLE_COLOR::NORMAL);
+}
+
+void PrintMessage(CONSOLE_COLOR color, const wchar_t* msg)
+{
+    if(color != CONSOLE_COLOR::NORMAL)
+        SetConsoleColor(color);
+    
+    wprintf(L"%s\n", msg);
+    
+    if (color != CONSOLE_COLOR::NORMAL)
+        SetConsoleColor(CONSOLE_COLOR::NORMAL);
+}
+
+static const size_t CONSOLE_SMALL_BUF_SIZE = 256;
+
+void PrintMessageV(CONSOLE_COLOR color, const char* format, va_list argList)
+{
+	size_t dstLen = (size_t)::_vscprintf(format, argList);
+	if(dstLen)
+	{
+		bool useSmallBuf = dstLen < CONSOLE_SMALL_BUF_SIZE;
+		char smallBuf[CONSOLE_SMALL_BUF_SIZE];
+		std::vector<char> bigBuf(useSmallBuf ? 0 : dstLen + 1);
+		char* bufPtr = useSmallBuf ? smallBuf : bigBuf.data();
+		::vsprintf_s(bufPtr, dstLen + 1, format, argList);
+		PrintMessage(color, bufPtr);
+	}
+}
+
+void PrintMessageV(CONSOLE_COLOR color, const wchar_t* format, va_list argList)
+{
+	size_t dstLen = (size_t)::_vcwprintf(format, argList);
+	if(dstLen)
+	{
+		bool useSmallBuf = dstLen < CONSOLE_SMALL_BUF_SIZE;
+		wchar_t smallBuf[CONSOLE_SMALL_BUF_SIZE];
+		std::vector<wchar_t> bigBuf(useSmallBuf ? 0 : dstLen + 1);
+		wchar_t* bufPtr = useSmallBuf ? smallBuf : bigBuf.data();
+		::vswprintf_s(bufPtr, dstLen + 1, format, argList);
+		PrintMessage(color, bufPtr);
+	}
+}
+
+void PrintMessageF(CONSOLE_COLOR color, const char* format, ...)
+{
+	va_list argList;
+	va_start(argList, format);
+	PrintMessageV(color, format, argList);
+	va_end(argList);
+}
+
+void PrintMessageF(CONSOLE_COLOR color, const wchar_t* format, ...)
+{
+	va_list argList;
+	va_start(argList, format);
+	PrintMessageV(color, format, argList);
+	va_end(argList);
+}
+
+void PrintWarningF(const char* format, ...)
+{
+	va_list argList;
+	va_start(argList, format);
+	PrintMessageV(CONSOLE_COLOR::WARNING, format, argList);
+	va_end(argList);
+}
+
+void PrintWarningF(const wchar_t* format, ...)
+{
+	va_list argList;
+	va_start(argList, format);
+	PrintMessageV(CONSOLE_COLOR::WARNING, format, argList);
+	va_end(argList);
+}
+
+void PrintErrorF(const char* format, ...)
+{
+	va_list argList;
+	va_start(argList, format);
+	PrintMessageV(CONSOLE_COLOR::WARNING, format, argList);
+	va_end(argList);
+}
+
+void PrintErrorF(const wchar_t* format, ...)
+{
+	va_list argList;
+	va_start(argList, format);
+	PrintMessageV(CONSOLE_COLOR::WARNING, format, argList);
+	va_end(argList);
+}
+*/
+
+void SecondsToFriendlyStr(float seconds, std::string& out)
+{
+    if(seconds == 0.f)
+    {
+        out = "0";
+        return;
+    }
+
+    if (seconds < 0.f)
+	{
+		out = "-";
+        seconds = -seconds;
+	}
+	else
+	{
+		out.clear();
+	}
+
+	char s[32];
+
+    // #.### ns
+    if(seconds < 1e-6)
+    {
+        sprintf_s(s, "%.3f ns", seconds * 1e9);
+        out += s;
+    }
+    // #.### us
+    else if(seconds < 1e-3)
+    {
+        sprintf_s(s, "%.3f us", seconds * 1e6);
+        out += s;
+    }
+    // #.### ms
+    else if(seconds < 1.f)
+    {
+        sprintf_s(s, "%.3f ms", seconds * 1e3);
+        out += s;
+    }
+    // #.### s
+    else if(seconds < 60.f)
+    {
+        sprintf_s(s, "%.3f s", seconds);
+        out += s;
+    }
+    else
+    {
+	    uint64_t seconds_u = (uint64_t)seconds;
+	    // "#:## min"
+	    if (seconds_u < 3600)
+	    {
+		    uint64_t minutes = seconds_u / 60;
+		    seconds_u -= minutes * 60;
+            sprintf_s(s, "%llu:%02llu min", minutes, seconds_u);
+            out += s;
+	    }
+	    // "#:##:## h"
+	    else
+	    {
+		    uint64_t minutes = seconds_u / 60;
+            seconds_u -= minutes * 60;
+		    uint64_t hours = minutes / 60;
+		    minutes -= hours * 60;
+            sprintf_s(s, "%llu:%02llu:%02llu h", hours, minutes, seconds_u);
+            out += s;
+	    }
+    }
+}
diff --git a/third_party/VulkanMemoryAllocator/src/VmaReplay/Common.h b/third_party/VulkanMemoryAllocator/src/VmaReplay/Common.h
new file mode 100644
index 0000000..4f130a4
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/src/VmaReplay/Common.h
@@ -0,0 +1,426 @@
+//
+// Copyright (c) 2017-2020 Advanced Micro Devices, Inc. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#pragma once
+
+#include "VmaUsage.h"
+
+#include <iostream>
+#include <fstream>
+#include <vector>
+#include <memory>
+#include <algorithm>
+#include <numeric>
+#include <array>
+#include <type_traits>
+#include <utility>
+#include <chrono>
+#include <string>
+#include <limits>
+
+#include <cassert>
+#include <cstdlib>
+#include <cstdio>
+#include <cstdarg>
+
+typedef std::chrono::high_resolution_clock::time_point time_point;
+typedef std::chrono::high_resolution_clock::duration duration;
+
+inline float ToFloatSeconds(duration d)
+{
+    return std::chrono::duration_cast<std::chrono::duration<float>>(d).count();
+}
+
+void SecondsToFriendlyStr(float seconds, std::string& out);
+
+template <typename T>
+T ceil_div(T x, T y)
+{
+    return (x+y-1) / y;
+}
+template <typename T>
+inline T round_div(T x, T y)
+{
+    return (x+y/(T)2) / y;
+}
+
+template <typename T>
+inline T align_up(T val, T align)
+{
+    return (val + align - 1) / align * align;
+}
+
+struct StrRange
+{
+    const char* beg;
+    const char* end;
+
+    StrRange() { }
+    StrRange(const char* beg, const char* end) : beg(beg), end(end) { }
+    explicit StrRange(const char* sz) : beg(sz), end(sz + strlen(sz)) { }
+    explicit StrRange(const std::string& s) : beg(s.data()), end(s.data() + s.length()) { }
+
+    size_t length() const { return end - beg; }
+    void to_str(std::string& out) const { out.assign(beg, end); }
+};
+
+inline bool StrRangeEq(const StrRange& lhs, const char* rhsSz)
+{
+    const size_t rhsLen = strlen(rhsSz);
+    return rhsLen == lhs.length() &&
+        memcmp(lhs.beg, rhsSz, rhsLen) == 0;
+}
+
+inline bool StrRangeToUint(const StrRange& s, uint32_t& out)
+{
+    char* end = (char*)s.end;
+    out = (uint32_t)strtoul(s.beg, &end, 10);
+    return end == s.end;
+}
+inline bool StrRangeToUint(const StrRange& s, uint64_t& out)
+{
+    char* end = (char*)s.end;
+    out = (uint64_t)strtoull(s.beg, &end, 10);
+    return end == s.end;
+}
+inline bool StrRangeToPtr(const StrRange& s, uint64_t& out)
+{
+    char* end = (char*)s.end;
+    out = (uint64_t)strtoull(s.beg, &end, 16);
+    return end == s.end;
+}
+inline bool StrRangeToFloat(const StrRange& s, float& out)
+{
+    char* end = (char*)s.end;
+    out = strtof(s.beg, &end);
+    return end == s.end;
+}
+inline bool StrRangeToBool(const StrRange& s, bool& out)
+{
+    if(s.end - s.beg == 1)
+    {
+        if(*s.beg == '1')
+        {
+            out = true;
+        }
+        else if(*s.beg == '0')
+        {
+            out = false;
+        }
+        else
+        {
+            return false;
+        }
+    }
+    else
+    {
+        return false;
+    }
+
+    return true;
+}
+bool StrRangeToPtrList(const StrRange& s, std::vector<uint64_t>& out);
+
+class LineSplit
+{
+public:
+    LineSplit(const char* data, size_t numBytes) :
+        m_Data(data),
+        m_NumBytes(numBytes),
+        m_NextLineBeg(0),
+        m_NextLineIndex(0)
+    {
+    }
+
+    bool GetNextLine(StrRange& out);
+    size_t GetNextLineIndex() const { return m_NextLineIndex; }
+
+private:
+    const char* const m_Data;
+    const size_t m_NumBytes;
+    size_t m_NextLineBeg;
+    size_t m_NextLineIndex;
+};
+
+class CsvSplit
+{
+public:
+    static const size_t RANGE_COUNT_MAX = 32;
+
+    void Set(const StrRange& line, size_t maxCount = RANGE_COUNT_MAX);
+
+    const StrRange& GetLine() const { return m_Line; }
+
+    size_t GetCount() const { return m_Count; }
+    StrRange GetRange(size_t index) const 
+    {
+        if(index < m_Count)
+        {
+            return StrRange {
+                m_Line.beg + m_Ranges[index * 2],
+                m_Line.beg + m_Ranges[index * 2 + 1] };
+        }
+        else
+        {
+            return StrRange{0, 0};
+        }
+    }
+
+private:
+    StrRange m_Line = { nullptr, nullptr };
+    size_t m_Count = 0;
+    size_t m_Ranges[RANGE_COUNT_MAX * 2]; // Pairs of begin-end.
+};
+
+class CmdLineParser
+{
+public:
+	enum RESULT
+	{
+		RESULT_OPT,
+		RESULT_PARAMETER,
+		RESULT_END,
+		RESULT_ERROR,
+	};
+
+	CmdLineParser(int argc, char **argv);
+	CmdLineParser(const char *CmdLine);
+	
+    void RegisterOpt(uint32_t Id, char Opt, bool Parameter);
+	void RegisterOpt(uint32_t Id, const std::string &Opt, bool Parameter);
+	
+    RESULT ReadNext();
+	uint32_t GetOptId();
+	const std::string & GetParameter();
+
+private:
+	struct SHORT_OPT
+	{
+		uint32_t Id;
+		char Opt;
+		bool Parameter;
+
+		SHORT_OPT(uint32_t Id, char Opt, bool Parameter) : Id(Id), Opt(Opt), Parameter(Parameter) { }
+	};
+
+	struct LONG_OPT
+	{
+		uint32_t Id;
+		std::string Opt;
+		bool Parameter;
+
+		LONG_OPT(uint32_t Id, std::string Opt, bool Parameter) : Id(Id), Opt(Opt), Parameter(Parameter) { }
+	};
+
+	char **m_argv;
+	const char *m_CmdLine;
+	int m_argc;
+	size_t m_CmdLineLength;
+	size_t m_ArgIndex;
+
+	bool ReadNextArg(std::string *OutArg);
+
+	std::vector<SHORT_OPT> m_ShortOpts;
+	std::vector<LONG_OPT> m_LongOpts;
+
+	SHORT_OPT * FindShortOpt(char Opt);
+	LONG_OPT * FindLongOpt(const std::string &Opt);
+
+	bool m_InsideMultioption;
+	std::string m_LastArg;
+	size_t m_LastArgIndex;
+	uint32_t m_LastOptId;
+	std::string m_LastParameter;
+};
+
+/*
+Parses and stores a sequence of ranges.
+
+Upper range is inclusive.
+
+Examples:
+
+    "1" -> [ {1, 1} ]
+    "1,10" -> [ {1, 1}, {10, 10} ]
+    "2-6" -> [ {2, 6} ]
+    "-8" -> [ {MIN, 8} ]
+    "12-" -> [ {12, MAX} ]
+    "1-10,12,15-" -> [ {1, 10}, {12, 12}, {15, MAX} ]
+
+TODO: Optimize it: Do sorting and merging while parsing. Do binary search while
+reading.
+*/
+template<typename T>
+class RangeSequence
+{
+public:
+    typedef std::pair<T, T> RangeType;
+
+    void Clear() { m_Ranges.clear(); }
+    bool Parse(const StrRange& str);
+
+    bool IsEmpty() const { return m_Ranges.empty(); }
+    size_t GetCount() const { return m_Ranges.size(); }
+    const RangeType* GetRanges() const { return m_Ranges.data(); }
+
+    bool Includes(T number) const;
+    
+private:
+    std::vector<RangeType> m_Ranges;
+};
+
+template<typename T>
+bool RangeSequence<T>::Parse(const StrRange& str)
+{
+    m_Ranges.clear();
+
+    StrRange currRange = { str.beg, str.beg };
+    while(currRange.beg < str.end)
+    {
+        currRange.end = currRange.beg + 1;
+        // Find next ',' or the end.
+        while(currRange.end < str.end && *currRange.end != ',')
+        {
+            ++currRange.end;
+        }
+
+        // Find '-' within this range.
+        const char* hyphenPos = currRange.beg;
+        while(hyphenPos < currRange.end && *hyphenPos != '-')
+        {
+            ++hyphenPos;
+        }
+
+        // No hyphen - single number like '10'.
+        if(hyphenPos == currRange.end)
+        {
+            RangeType range;
+            if(!StrRangeToUint(currRange, range.first))
+            {
+                return false;
+            }
+            range.second = range.first;
+            m_Ranges.push_back(range);
+        }
+        // Hyphen at the end, like '10-'.
+        else if(hyphenPos + 1 == currRange.end)
+        {
+            const StrRange numberRange = { currRange.beg, hyphenPos };
+            RangeType range;
+            if(!StrRangeToUint(numberRange, range.first))
+            {
+                return false;
+            }
+            range.second = std::numeric_limits<T>::max();
+            m_Ranges.push_back(range);
+        }
+        // Hyphen at the beginning, like "-10".
+        else if(hyphenPos == currRange.beg)
+        {
+            const StrRange numberRange = { currRange.beg + 1, currRange.end };
+            RangeType range;
+            range.first = std::numeric_limits<T>::min();
+            if(!StrRangeToUint(numberRange, range.second))
+            {
+                return false;
+            }
+            m_Ranges.push_back(range);
+        }
+        // Hyphen in the middle, like "1-10".
+        else
+        {
+            const StrRange numberRange1 = { currRange.beg, hyphenPos };
+            const StrRange numberRange2 = { hyphenPos + 1, currRange.end };
+            RangeType range;
+            if(!StrRangeToUint(numberRange1, range.first) ||
+                !StrRangeToUint(numberRange2, range.second) ||
+                range.second < range.first)
+            {
+                return false;
+            }
+            m_Ranges.push_back(range);
+        }
+
+        // Skip ','
+        currRange.beg = currRange.end + 1;
+    }
+
+    return true;
+}
+
+template<typename T>
+bool RangeSequence<T>::Includes(T number) const
+{
+    for(const auto& it : m_Ranges)
+    {
+        if(number >= it.first && number <= it.second)
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
+/*
+class RandomNumberGenerator
+{
+public:
+    RandomNumberGenerator() : m_Value{GetTickCount()} {}
+    RandomNumberGenerator(uint32_t seed) : m_Value{seed} { }
+    void Seed(uint32_t seed) { m_Value = seed; }
+    uint32_t Generate() { return GenerateFast() ^ (GenerateFast() >> 7); }
+
+private:
+    uint32_t m_Value;
+    uint32_t GenerateFast() { return m_Value = (m_Value * 196314165 + 907633515); }
+};
+
+enum class CONSOLE_COLOR
+{
+    INFO,
+    NORMAL,
+    WARNING,
+    ERROR_,
+    COUNT
+};
+
+void SetConsoleColor(CONSOLE_COLOR color);
+
+void PrintMessage(CONSOLE_COLOR color, const char* msg);
+void PrintMessage(CONSOLE_COLOR color, const wchar_t* msg);
+
+inline void Print(const char* msg) { PrintMessage(CONSOLE_COLOR::NORMAL, msg); }
+inline void Print(const wchar_t* msg) { PrintMessage(CONSOLE_COLOR::NORMAL, msg); }
+inline void PrintWarning(const char* msg) { PrintMessage(CONSOLE_COLOR::WARNING, msg); }
+inline void PrintWarning(const wchar_t* msg) { PrintMessage(CONSOLE_COLOR::WARNING, msg); }
+inline void PrintError(const char* msg) { PrintMessage(CONSOLE_COLOR::ERROR_, msg); }
+inline void PrintError(const wchar_t* msg) { PrintMessage(CONSOLE_COLOR::ERROR_, msg); }
+
+void PrintMessageV(CONSOLE_COLOR color, const char* format, va_list argList);
+void PrintMessageV(CONSOLE_COLOR color, const wchar_t* format, va_list argList);
+void PrintMessageF(CONSOLE_COLOR color, const char* format, ...);
+void PrintMessageF(CONSOLE_COLOR color, const wchar_t* format, ...);
+void PrintWarningF(const char* format, ...);
+void PrintWarningF(const wchar_t* format, ...);
+void PrintErrorF(const char* format, ...);
+void PrintErrorF(const wchar_t* format, ...);
+*/
diff --git a/third_party/VulkanMemoryAllocator/src/VmaReplay/Constants.cpp b/third_party/VulkanMemoryAllocator/src/VmaReplay/Constants.cpp
new file mode 100644
index 0000000..865cb80
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/src/VmaReplay/Constants.cpp
@@ -0,0 +1,795 @@
+//
+// Copyright (c) 2017-2020 Advanced Micro Devices, Inc. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#include "Common.h"
+#include "Constants.h"
+
+const int RESULT_EXCEPTION          = -1000;
+const int RESULT_ERROR_COMMAND_LINE = -1;
+const int RESULT_ERROR_SOURCE_FILE  = -2;
+const int RESULT_ERROR_FORMAT       = -3;
+const int RESULT_ERROR_VULKAN       = -4;
+
+const char* VMA_FUNCTION_NAMES[] = {
+    "vmaCreatePool",
+    "vmaDestroyPool",
+    "vmaSetAllocationUserData",
+    "vmaCreateBuffer",
+    "vmaDestroyBuffer",
+    "vmaCreateImage",
+    "vmaDestroyImage",
+    "vmaFreeMemory",
+    "vmaFreeMemoryPages",
+    "vmaCreateLostAllocation",
+    "vmaAllocateMemory",
+    "vmaAllocateMemoryPages",
+    "vmaAllocateMemoryForBuffer",
+    "vmaAllocateMemoryForImage",
+    "vmaMapMemory",
+    "vmaUnmapMemory",
+    "vmaFlushAllocation",
+    "vmaInvalidateAllocation",
+    "vmaTouchAllocation",
+    "vmaGetAllocationInfo",
+    "vmaMakePoolAllocationsLost",
+    "vmaResizeAllocation",
+    "vmaDefragmentationBegin",
+    "vmaDefragmentationEnd",
+    "vmaSetPoolName",
+};
+static_assert(
+    _countof(VMA_FUNCTION_NAMES) == (size_t)VMA_FUNCTION::Count,
+    "VMA_FUNCTION_NAMES array doesn't match VMA_FUNCTION enum.");
+
+const char* VMA_POOL_CREATE_FLAG_NAMES[] = {
+    "VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT",
+    "VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT",
+    "VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT",
+};
+const uint32_t VMA_POOL_CREATE_FLAG_VALUES[] = {
+    VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT,
+    VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT,
+    VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT,
+};
+const size_t VMA_POOL_CREATE_FLAG_COUNT = _countof(VMA_POOL_CREATE_FLAG_NAMES);
+static_assert(
+    _countof(VMA_POOL_CREATE_FLAG_NAMES) == _countof(VMA_POOL_CREATE_FLAG_VALUES),
+    "VMA_POOL_CREATE_FLAG_NAMES array doesn't match VMA_POOL_CREATE_FLAG_VALUES.");
+
+const char* VK_BUFFER_CREATE_FLAG_NAMES[] = {
+    "VK_BUFFER_CREATE_SPARSE_BINDING_BIT",
+    "VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT",
+    "VK_BUFFER_CREATE_SPARSE_ALIASED_BIT",
+    "VK_BUFFER_CREATE_PROTECTED_BIT",
+};
+const uint32_t VK_BUFFER_CREATE_FLAG_VALUES[] = {
+    VK_BUFFER_CREATE_SPARSE_BINDING_BIT,
+    VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT,
+    VK_BUFFER_CREATE_SPARSE_ALIASED_BIT,
+    VK_BUFFER_CREATE_PROTECTED_BIT,
+};
+const size_t VK_BUFFER_CREATE_FLAG_COUNT = _countof(VK_BUFFER_CREATE_FLAG_NAMES);
+static_assert(
+    _countof(VK_BUFFER_CREATE_FLAG_NAMES) == _countof(VK_BUFFER_CREATE_FLAG_VALUES),
+    "VK_BUFFER_CREATE_FLAG_NAMES array doesn't match VK_BUFFER_CREATE_FLAG_VALUES.");
+
+const char* VK_BUFFER_USAGE_FLAG_NAMES[] = {
+    "VK_BUFFER_USAGE_TRANSFER_SRC_BIT",
+    "VK_BUFFER_USAGE_TRANSFER_DST_BIT",
+    "VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT",
+    "VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT",
+    "VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT",
+    "VK_BUFFER_USAGE_STORAGE_BUFFER_BIT",
+    "VK_BUFFER_USAGE_INDEX_BUFFER_BIT",
+    "VK_BUFFER_USAGE_VERTEX_BUFFER_BIT",
+    "VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT",
+    "VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT",
+    //"VK_BUFFER_USAGE_RAYTRACING_BIT_NVX",
+};
+const uint32_t VK_BUFFER_USAGE_FLAG_VALUES[] = {
+    VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
+    VK_BUFFER_USAGE_TRANSFER_DST_BIT,
+    VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT,
+    VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT,
+    VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
+    VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
+    VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
+    VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
+    VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT,
+    VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT,
+    //VK_BUFFER_USAGE_RAYTRACING_BIT_NVX,
+};
+const size_t VK_BUFFER_USAGE_FLAG_COUNT = _countof(VK_BUFFER_USAGE_FLAG_NAMES);
+static_assert(
+    _countof(VK_BUFFER_USAGE_FLAG_NAMES) == _countof(VK_BUFFER_USAGE_FLAG_VALUES),
+    "VK_BUFFER_USAGE_FLAG_NAMES array doesn't match VK_BUFFER_USAGE_FLAG_VALUES.");
+
+const char* VK_SHARING_MODE_NAMES[] = {
+    "VK_SHARING_MODE_EXCLUSIVE",
+    "VK_SHARING_MODE_CONCURRENT",
+};
+const size_t VK_SHARING_MODE_COUNT = _countof(VK_SHARING_MODE_NAMES);
+
+const char* VK_IMAGE_CREATE_FLAG_NAMES[] = {
+    "VK_IMAGE_CREATE_SPARSE_BINDING_BIT",
+    "VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT",
+    "VK_IMAGE_CREATE_SPARSE_ALIASED_BIT",
+    "VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT",
+    "VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT",
+    "VK_IMAGE_CREATE_ALIAS_BIT",
+    "VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT",
+    "VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT",
+    "VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT",
+    "VK_IMAGE_CREATE_EXTENDED_USAGE_BIT",
+    "VK_IMAGE_CREATE_PROTECTED_BIT",
+    "VK_IMAGE_CREATE_DISJOINT_BIT",
+    //"VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV",
+    "VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT",
+};
+const uint32_t VK_IMAGE_CREATE_FLAG_VALUES[] = {
+    VK_IMAGE_CREATE_SPARSE_BINDING_BIT,
+    VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT,
+    VK_IMAGE_CREATE_SPARSE_ALIASED_BIT,
+    VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
+    VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT,
+    VK_IMAGE_CREATE_ALIAS_BIT,
+    VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT,
+    VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT,
+    VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT,
+    VK_IMAGE_CREATE_EXTENDED_USAGE_BIT,
+    VK_IMAGE_CREATE_PROTECTED_BIT,
+    VK_IMAGE_CREATE_DISJOINT_BIT,
+    //VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV,
+    VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT,
+};
+const size_t VK_IMAGE_CREATE_FLAG_COUNT = _countof(VK_IMAGE_CREATE_FLAG_NAMES);
+static_assert(
+    _countof(VK_IMAGE_CREATE_FLAG_NAMES) == _countof(VK_IMAGE_CREATE_FLAG_VALUES),
+    "VK_IMAGE_CREATE_FLAG_NAMES array doesn't match VK_IMAGE_CREATE_FLAG_VALUES.");
+
+const char* VK_IMAGE_TYPE_NAMES[] = {
+    "VK_IMAGE_TYPE_1D",
+    "VK_IMAGE_TYPE_2D",
+    "VK_IMAGE_TYPE_3D",
+};
+const size_t VK_IMAGE_TYPE_COUNT = _countof(VK_IMAGE_TYPE_NAMES);
+
+const char* VK_FORMAT_NAMES[] = {
+    "VK_FORMAT_UNDEFINED",
+    "VK_FORMAT_R4G4_UNORM_PACK8",
+    "VK_FORMAT_R4G4B4A4_UNORM_PACK16",
+    "VK_FORMAT_B4G4R4A4_UNORM_PACK16",
+    "VK_FORMAT_R5G6B5_UNORM_PACK16",
+    "VK_FORMAT_B5G6R5_UNORM_PACK16",
+    "VK_FORMAT_R5G5B5A1_UNORM_PACK16",
+    "VK_FORMAT_B5G5R5A1_UNORM_PACK16",
+    "VK_FORMAT_A1R5G5B5_UNORM_PACK16",
+    "VK_FORMAT_R8_UNORM",
+    "VK_FORMAT_R8_SNORM",
+    "VK_FORMAT_R8_USCALED",
+    "VK_FORMAT_R8_SSCALED",
+    "VK_FORMAT_R8_UINT",
+    "VK_FORMAT_R8_SINT",
+    "VK_FORMAT_R8_SRGB",
+    "VK_FORMAT_R8G8_UNORM",
+    "VK_FORMAT_R8G8_SNORM",
+    "VK_FORMAT_R8G8_USCALED",
+    "VK_FORMAT_R8G8_SSCALED",
+    "VK_FORMAT_R8G8_UINT",
+    "VK_FORMAT_R8G8_SINT",
+    "VK_FORMAT_R8G8_SRGB",
+    "VK_FORMAT_R8G8B8_UNORM",
+    "VK_FORMAT_R8G8B8_SNORM",
+    "VK_FORMAT_R8G8B8_USCALED",
+    "VK_FORMAT_R8G8B8_SSCALED",
+    "VK_FORMAT_R8G8B8_UINT",
+    "VK_FORMAT_R8G8B8_SINT",
+    "VK_FORMAT_R8G8B8_SRGB",
+    "VK_FORMAT_B8G8R8_UNORM",
+    "VK_FORMAT_B8G8R8_SNORM",
+    "VK_FORMAT_B8G8R8_USCALED",
+    "VK_FORMAT_B8G8R8_SSCALED",
+    "VK_FORMAT_B8G8R8_UINT",
+    "VK_FORMAT_B8G8R8_SINT",
+    "VK_FORMAT_B8G8R8_SRGB",
+    "VK_FORMAT_R8G8B8A8_UNORM",
+    "VK_FORMAT_R8G8B8A8_SNORM",
+    "VK_FORMAT_R8G8B8A8_USCALED",
+    "VK_FORMAT_R8G8B8A8_SSCALED",
+    "VK_FORMAT_R8G8B8A8_UINT",
+    "VK_FORMAT_R8G8B8A8_SINT",
+    "VK_FORMAT_R8G8B8A8_SRGB",
+    "VK_FORMAT_B8G8R8A8_UNORM",
+    "VK_FORMAT_B8G8R8A8_SNORM",
+    "VK_FORMAT_B8G8R8A8_USCALED",
+    "VK_FORMAT_B8G8R8A8_SSCALED",
+    "VK_FORMAT_B8G8R8A8_UINT",
+    "VK_FORMAT_B8G8R8A8_SINT",
+    "VK_FORMAT_B8G8R8A8_SRGB",
+    "VK_FORMAT_A8B8G8R8_UNORM_PACK32",
+    "VK_FORMAT_A8B8G8R8_SNORM_PACK32",
+    "VK_FORMAT_A8B8G8R8_USCALED_PACK32",
+    "VK_FORMAT_A8B8G8R8_SSCALED_PACK32",
+    "VK_FORMAT_A8B8G8R8_UINT_PACK32",
+    "VK_FORMAT_A8B8G8R8_SINT_PACK32",
+    "VK_FORMAT_A8B8G8R8_SRGB_PACK32",
+    "VK_FORMAT_A2R10G10B10_UNORM_PACK32",
+    "VK_FORMAT_A2R10G10B10_SNORM_PACK32",
+    "VK_FORMAT_A2R10G10B10_USCALED_PACK32",
+    "VK_FORMAT_A2R10G10B10_SSCALED_PACK32",
+    "VK_FORMAT_A2R10G10B10_UINT_PACK32",
+    "VK_FORMAT_A2R10G10B10_SINT_PACK32",
+    "VK_FORMAT_A2B10G10R10_UNORM_PACK32",
+    "VK_FORMAT_A2B10G10R10_SNORM_PACK32",
+    "VK_FORMAT_A2B10G10R10_USCALED_PACK32",
+    "VK_FORMAT_A2B10G10R10_SSCALED_PACK32",
+    "VK_FORMAT_A2B10G10R10_UINT_PACK32",
+    "VK_FORMAT_A2B10G10R10_SINT_PACK32",
+    "VK_FORMAT_R16_UNORM",
+    "VK_FORMAT_R16_SNORM",
+    "VK_FORMAT_R16_USCALED",
+    "VK_FORMAT_R16_SSCALED",
+    "VK_FORMAT_R16_UINT",
+    "VK_FORMAT_R16_SINT",
+    "VK_FORMAT_R16_SFLOAT",
+    "VK_FORMAT_R16G16_UNORM",
+    "VK_FORMAT_R16G16_SNORM",
+    "VK_FORMAT_R16G16_USCALED",
+    "VK_FORMAT_R16G16_SSCALED",
+    "VK_FORMAT_R16G16_UINT",
+    "VK_FORMAT_R16G16_SINT",
+    "VK_FORMAT_R16G16_SFLOAT",
+    "VK_FORMAT_R16G16B16_UNORM",
+    "VK_FORMAT_R16G16B16_SNORM",
+    "VK_FORMAT_R16G16B16_USCALED",
+    "VK_FORMAT_R16G16B16_SSCALED",
+    "VK_FORMAT_R16G16B16_UINT",
+    "VK_FORMAT_R16G16B16_SINT",
+    "VK_FORMAT_R16G16B16_SFLOAT",
+    "VK_FORMAT_R16G16B16A16_UNORM",
+    "VK_FORMAT_R16G16B16A16_SNORM",
+    "VK_FORMAT_R16G16B16A16_USCALED",
+    "VK_FORMAT_R16G16B16A16_SSCALED",
+    "VK_FORMAT_R16G16B16A16_UINT",
+    "VK_FORMAT_R16G16B16A16_SINT",
+    "VK_FORMAT_R16G16B16A16_SFLOAT",
+    "VK_FORMAT_R32_UINT",
+    "VK_FORMAT_R32_SINT",
+    "VK_FORMAT_R32_SFLOAT",
+    "VK_FORMAT_R32G32_UINT",
+    "VK_FORMAT_R32G32_SINT",
+    "VK_FORMAT_R32G32_SFLOAT",
+    "VK_FORMAT_R32G32B32_UINT",
+    "VK_FORMAT_R32G32B32_SINT",
+    "VK_FORMAT_R32G32B32_SFLOAT",
+    "VK_FORMAT_R32G32B32A32_UINT",
+    "VK_FORMAT_R32G32B32A32_SINT",
+    "VK_FORMAT_R32G32B32A32_SFLOAT",
+    "VK_FORMAT_R64_UINT",
+    "VK_FORMAT_R64_SINT",
+    "VK_FORMAT_R64_SFLOAT",
+    "VK_FORMAT_R64G64_UINT",
+    "VK_FORMAT_R64G64_SINT",
+    "VK_FORMAT_R64G64_SFLOAT",
+    "VK_FORMAT_R64G64B64_UINT",
+    "VK_FORMAT_R64G64B64_SINT",
+    "VK_FORMAT_R64G64B64_SFLOAT",
+    "VK_FORMAT_R64G64B64A64_UINT",
+    "VK_FORMAT_R64G64B64A64_SINT",
+    "VK_FORMAT_R64G64B64A64_SFLOAT",
+    "VK_FORMAT_B10G11R11_UFLOAT_PACK32",
+    "VK_FORMAT_E5B9G9R9_UFLOAT_PACK32",
+    "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",
+    "VK_FORMAT_BC1_RGB_UNORM_BLOCK",
+    "VK_FORMAT_BC1_RGB_SRGB_BLOCK",
+    "VK_FORMAT_BC1_RGBA_UNORM_BLOCK",
+    "VK_FORMAT_BC1_RGBA_SRGB_BLOCK",
+    "VK_FORMAT_BC2_UNORM_BLOCK",
+    "VK_FORMAT_BC2_SRGB_BLOCK",
+    "VK_FORMAT_BC3_UNORM_BLOCK",
+    "VK_FORMAT_BC3_SRGB_BLOCK",
+    "VK_FORMAT_BC4_UNORM_BLOCK",
+    "VK_FORMAT_BC4_SNORM_BLOCK",
+    "VK_FORMAT_BC5_UNORM_BLOCK",
+    "VK_FORMAT_BC5_SNORM_BLOCK",
+    "VK_FORMAT_BC6H_UFLOAT_BLOCK",
+    "VK_FORMAT_BC6H_SFLOAT_BLOCK",
+    "VK_FORMAT_BC7_UNORM_BLOCK",
+    "VK_FORMAT_BC7_SRGB_BLOCK",
+    "VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK",
+    "VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK",
+    "VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK",
+    "VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK",
+    "VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK",
+    "VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK",
+    "VK_FORMAT_EAC_R11_UNORM_BLOCK",
+    "VK_FORMAT_EAC_R11_SNORM_BLOCK",
+    "VK_FORMAT_EAC_R11G11_UNORM_BLOCK",
+    "VK_FORMAT_EAC_R11G11_SNORM_BLOCK",
+    "VK_FORMAT_ASTC_4x4_UNORM_BLOCK",
+    "VK_FORMAT_ASTC_4x4_SRGB_BLOCK",
+    "VK_FORMAT_ASTC_5x4_UNORM_BLOCK",
+    "VK_FORMAT_ASTC_5x4_SRGB_BLOCK",
+    "VK_FORMAT_ASTC_5x5_UNORM_BLOCK",
+    "VK_FORMAT_ASTC_5x5_SRGB_BLOCK",
+    "VK_FORMAT_ASTC_6x5_UNORM_BLOCK",
+    "VK_FORMAT_ASTC_6x5_SRGB_BLOCK",
+    "VK_FORMAT_ASTC_6x6_UNORM_BLOCK",
+    "VK_FORMAT_ASTC_6x6_SRGB_BLOCK",
+    "VK_FORMAT_ASTC_8x5_UNORM_BLOCK",
+    "VK_FORMAT_ASTC_8x5_SRGB_BLOCK",
+    "VK_FORMAT_ASTC_8x6_UNORM_BLOCK",
+    "VK_FORMAT_ASTC_8x6_SRGB_BLOCK",
+    "VK_FORMAT_ASTC_8x8_UNORM_BLOCK",
+    "VK_FORMAT_ASTC_8x8_SRGB_BLOCK",
+    "VK_FORMAT_ASTC_10x5_UNORM_BLOCK",
+    "VK_FORMAT_ASTC_10x5_SRGB_BLOCK",
+    "VK_FORMAT_ASTC_10x6_UNORM_BLOCK",
+    "VK_FORMAT_ASTC_10x6_SRGB_BLOCK",
+    "VK_FORMAT_ASTC_10x8_UNORM_BLOCK",
+    "VK_FORMAT_ASTC_10x8_SRGB_BLOCK",
+    "VK_FORMAT_ASTC_10x10_UNORM_BLOCK",
+    "VK_FORMAT_ASTC_10x10_SRGB_BLOCK",
+    "VK_FORMAT_ASTC_12x10_UNORM_BLOCK",
+    "VK_FORMAT_ASTC_12x10_SRGB_BLOCK",
+    "VK_FORMAT_ASTC_12x12_UNORM_BLOCK",
+    "VK_FORMAT_ASTC_12x12_SRGB_BLOCK",
+    "VK_FORMAT_G8B8G8R8_422_UNORM",
+    "VK_FORMAT_B8G8R8G8_422_UNORM",
+    "VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM",
+    "VK_FORMAT_G8_B8R8_2PLANE_420_UNORM",
+    "VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM",
+    "VK_FORMAT_G8_B8R8_2PLANE_422_UNORM",
+    "VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM",
+    "VK_FORMAT_R10X6_UNORM_PACK16",
+    "VK_FORMAT_R10X6G10X6_UNORM_2PACK16",
+    "VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16",
+    "VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16",
+    "VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16",
+    "VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16",
+    "VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16",
+    "VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16",
+    "VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16",
+    "VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16",
+    "VK_FORMAT_R12X4_UNORM_PACK16",
+    "VK_FORMAT_R12X4G12X4_UNORM_2PACK16",
+    "VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16",
+    "VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16",
+    "VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16",
+    "VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16",
+    "VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16",
+    "VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16",
+    "VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16",
+    "VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16",
+    "VK_FORMAT_G16B16G16R16_422_UNORM",
+    "VK_FORMAT_B16G16R16G16_422_UNORM",
+    "VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM",
+    "VK_FORMAT_G16_B16R16_2PLANE_420_UNORM",
+    "VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM",
+    "VK_FORMAT_G16_B16R16_2PLANE_422_UNORM",
+    "VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM",
+    "VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG",
+    "VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG",
+    "VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG",
+    "VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG",
+    "VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG",
+    "VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG",
+    "VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG",
+    "VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG",
+};
+const uint32_t VK_FORMAT_VALUES[] = {
+    VK_FORMAT_UNDEFINED,
+    VK_FORMAT_R4G4_UNORM_PACK8,
+    VK_FORMAT_R4G4B4A4_UNORM_PACK16,
+    VK_FORMAT_B4G4R4A4_UNORM_PACK16,
+    VK_FORMAT_R5G6B5_UNORM_PACK16,
+    VK_FORMAT_B5G6R5_UNORM_PACK16,
+    VK_FORMAT_R5G5B5A1_UNORM_PACK16,
+    VK_FORMAT_B5G5R5A1_UNORM_PACK16,
+    VK_FORMAT_A1R5G5B5_UNORM_PACK16,
+    VK_FORMAT_R8_UNORM,
+    VK_FORMAT_R8_SNORM,
+    VK_FORMAT_R8_USCALED,
+    VK_FORMAT_R8_SSCALED,
+    VK_FORMAT_R8_UINT,
+    VK_FORMAT_R8_SINT,
+    VK_FORMAT_R8_SRGB,
+    VK_FORMAT_R8G8_UNORM,
+    VK_FORMAT_R8G8_SNORM,
+    VK_FORMAT_R8G8_USCALED,
+    VK_FORMAT_R8G8_SSCALED,
+    VK_FORMAT_R8G8_UINT,
+    VK_FORMAT_R8G8_SINT,
+    VK_FORMAT_R8G8_SRGB,
+    VK_FORMAT_R8G8B8_UNORM,
+    VK_FORMAT_R8G8B8_SNORM,
+    VK_FORMAT_R8G8B8_USCALED,
+    VK_FORMAT_R8G8B8_SSCALED,
+    VK_FORMAT_R8G8B8_UINT,
+    VK_FORMAT_R8G8B8_SINT,
+    VK_FORMAT_R8G8B8_SRGB,
+    VK_FORMAT_B8G8R8_UNORM,
+    VK_FORMAT_B8G8R8_SNORM,
+    VK_FORMAT_B8G8R8_USCALED,
+    VK_FORMAT_B8G8R8_SSCALED,
+    VK_FORMAT_B8G8R8_UINT,
+    VK_FORMAT_B8G8R8_SINT,
+    VK_FORMAT_B8G8R8_SRGB,
+    VK_FORMAT_R8G8B8A8_UNORM,
+    VK_FORMAT_R8G8B8A8_SNORM,
+    VK_FORMAT_R8G8B8A8_USCALED,
+    VK_FORMAT_R8G8B8A8_SSCALED,
+    VK_FORMAT_R8G8B8A8_UINT,
+    VK_FORMAT_R8G8B8A8_SINT,
+    VK_FORMAT_R8G8B8A8_SRGB,
+    VK_FORMAT_B8G8R8A8_UNORM,
+    VK_FORMAT_B8G8R8A8_SNORM,
+    VK_FORMAT_B8G8R8A8_USCALED,
+    VK_FORMAT_B8G8R8A8_SSCALED,
+    VK_FORMAT_B8G8R8A8_UINT,
+    VK_FORMAT_B8G8R8A8_SINT,
+    VK_FORMAT_B8G8R8A8_SRGB,
+    VK_FORMAT_A8B8G8R8_UNORM_PACK32,
+    VK_FORMAT_A8B8G8R8_SNORM_PACK32,
+    VK_FORMAT_A8B8G8R8_USCALED_PACK32,
+    VK_FORMAT_A8B8G8R8_SSCALED_PACK32,
+    VK_FORMAT_A8B8G8R8_UINT_PACK32,
+    VK_FORMAT_A8B8G8R8_SINT_PACK32,
+    VK_FORMAT_A8B8G8R8_SRGB_PACK32,
+    VK_FORMAT_A2R10G10B10_UNORM_PACK32,
+    VK_FORMAT_A2R10G10B10_SNORM_PACK32,
+    VK_FORMAT_A2R10G10B10_USCALED_PACK32,
+    VK_FORMAT_A2R10G10B10_SSCALED_PACK32,
+    VK_FORMAT_A2R10G10B10_UINT_PACK32,
+    VK_FORMAT_A2R10G10B10_SINT_PACK32,
+    VK_FORMAT_A2B10G10R10_UNORM_PACK32,
+    VK_FORMAT_A2B10G10R10_SNORM_PACK32,
+    VK_FORMAT_A2B10G10R10_USCALED_PACK32,
+    VK_FORMAT_A2B10G10R10_SSCALED_PACK32,
+    VK_FORMAT_A2B10G10R10_UINT_PACK32,
+    VK_FORMAT_A2B10G10R10_SINT_PACK32,
+    VK_FORMAT_R16_UNORM,
+    VK_FORMAT_R16_SNORM,
+    VK_FORMAT_R16_USCALED,
+    VK_FORMAT_R16_SSCALED,
+    VK_FORMAT_R16_UINT,
+    VK_FORMAT_R16_SINT,
+    VK_FORMAT_R16_SFLOAT,
+    VK_FORMAT_R16G16_UNORM,
+    VK_FORMAT_R16G16_SNORM,
+    VK_FORMAT_R16G16_USCALED,
+    VK_FORMAT_R16G16_SSCALED,
+    VK_FORMAT_R16G16_UINT,
+    VK_FORMAT_R16G16_SINT,
+    VK_FORMAT_R16G16_SFLOAT,
+    VK_FORMAT_R16G16B16_UNORM,
+    VK_FORMAT_R16G16B16_SNORM,
+    VK_FORMAT_R16G16B16_USCALED,
+    VK_FORMAT_R16G16B16_SSCALED,
+    VK_FORMAT_R16G16B16_UINT,
+    VK_FORMAT_R16G16B16_SINT,
+    VK_FORMAT_R16G16B16_SFLOAT,
+    VK_FORMAT_R16G16B16A16_UNORM,
+    VK_FORMAT_R16G16B16A16_SNORM,
+    VK_FORMAT_R16G16B16A16_USCALED,
+    VK_FORMAT_R16G16B16A16_SSCALED,
+    VK_FORMAT_R16G16B16A16_UINT,
+    VK_FORMAT_R16G16B16A16_SINT,
+    VK_FORMAT_R16G16B16A16_SFLOAT,
+    VK_FORMAT_R32_UINT,
+    VK_FORMAT_R32_SINT,
+    VK_FORMAT_R32_SFLOAT,
+    VK_FORMAT_R32G32_UINT,
+    VK_FORMAT_R32G32_SINT,
+    VK_FORMAT_R32G32_SFLOAT,
+    VK_FORMAT_R32G32B32_UINT,
+    VK_FORMAT_R32G32B32_SINT,
+    VK_FORMAT_R32G32B32_SFLOAT,
+    VK_FORMAT_R32G32B32A32_UINT,
+    VK_FORMAT_R32G32B32A32_SINT,
+    VK_FORMAT_R32G32B32A32_SFLOAT,
+    VK_FORMAT_R64_UINT,
+    VK_FORMAT_R64_SINT,
+    VK_FORMAT_R64_SFLOAT,
+    VK_FORMAT_R64G64_UINT,
+    VK_FORMAT_R64G64_SINT,
+    VK_FORMAT_R64G64_SFLOAT,
+    VK_FORMAT_R64G64B64_UINT,
+    VK_FORMAT_R64G64B64_SINT,
+    VK_FORMAT_R64G64B64_SFLOAT,
+    VK_FORMAT_R64G64B64A64_UINT,
+    VK_FORMAT_R64G64B64A64_SINT,
+    VK_FORMAT_R64G64B64A64_SFLOAT,
+    VK_FORMAT_B10G11R11_UFLOAT_PACK32,
+    VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
+    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,
+    VK_FORMAT_BC1_RGB_UNORM_BLOCK,
+    VK_FORMAT_BC1_RGB_SRGB_BLOCK,
+    VK_FORMAT_BC1_RGBA_UNORM_BLOCK,
+    VK_FORMAT_BC1_RGBA_SRGB_BLOCK,
+    VK_FORMAT_BC2_UNORM_BLOCK,
+    VK_FORMAT_BC2_SRGB_BLOCK,
+    VK_FORMAT_BC3_UNORM_BLOCK,
+    VK_FORMAT_BC3_SRGB_BLOCK,
+    VK_FORMAT_BC4_UNORM_BLOCK,
+    VK_FORMAT_BC4_SNORM_BLOCK,
+    VK_FORMAT_BC5_UNORM_BLOCK,
+    VK_FORMAT_BC5_SNORM_BLOCK,
+    VK_FORMAT_BC6H_UFLOAT_BLOCK,
+    VK_FORMAT_BC6H_SFLOAT_BLOCK,
+    VK_FORMAT_BC7_UNORM_BLOCK,
+    VK_FORMAT_BC7_SRGB_BLOCK,
+    VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,
+    VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK,
+    VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK,
+    VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK,
+    VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK,
+    VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK,
+    VK_FORMAT_EAC_R11_UNORM_BLOCK,
+    VK_FORMAT_EAC_R11_SNORM_BLOCK,
+    VK_FORMAT_EAC_R11G11_UNORM_BLOCK,
+    VK_FORMAT_EAC_R11G11_SNORM_BLOCK,
+    VK_FORMAT_ASTC_4x4_UNORM_BLOCK,
+    VK_FORMAT_ASTC_4x4_SRGB_BLOCK,
+    VK_FORMAT_ASTC_5x4_UNORM_BLOCK,
+    VK_FORMAT_ASTC_5x4_SRGB_BLOCK,
+    VK_FORMAT_ASTC_5x5_UNORM_BLOCK,
+    VK_FORMAT_ASTC_5x5_SRGB_BLOCK,
+    VK_FORMAT_ASTC_6x5_UNORM_BLOCK,
+    VK_FORMAT_ASTC_6x5_SRGB_BLOCK,
+    VK_FORMAT_ASTC_6x6_UNORM_BLOCK,
+    VK_FORMAT_ASTC_6x6_SRGB_BLOCK,
+    VK_FORMAT_ASTC_8x5_UNORM_BLOCK,
+    VK_FORMAT_ASTC_8x5_SRGB_BLOCK,
+    VK_FORMAT_ASTC_8x6_UNORM_BLOCK,
+    VK_FORMAT_ASTC_8x6_SRGB_BLOCK,
+    VK_FORMAT_ASTC_8x8_UNORM_BLOCK,
+    VK_FORMAT_ASTC_8x8_SRGB_BLOCK,
+    VK_FORMAT_ASTC_10x5_UNORM_BLOCK,
+    VK_FORMAT_ASTC_10x5_SRGB_BLOCK,
+    VK_FORMAT_ASTC_10x6_UNORM_BLOCK,
+    VK_FORMAT_ASTC_10x6_SRGB_BLOCK,
+    VK_FORMAT_ASTC_10x8_UNORM_BLOCK,
+    VK_FORMAT_ASTC_10x8_SRGB_BLOCK,
+    VK_FORMAT_ASTC_10x10_UNORM_BLOCK,
+    VK_FORMAT_ASTC_10x10_SRGB_BLOCK,
+    VK_FORMAT_ASTC_12x10_UNORM_BLOCK,
+    VK_FORMAT_ASTC_12x10_SRGB_BLOCK,
+    VK_FORMAT_ASTC_12x12_UNORM_BLOCK,
+    VK_FORMAT_ASTC_12x12_SRGB_BLOCK,
+    VK_FORMAT_G8B8G8R8_422_UNORM,
+    VK_FORMAT_B8G8R8G8_422_UNORM,
+    VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM,
+    VK_FORMAT_G8_B8R8_2PLANE_420_UNORM,
+    VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM,
+    VK_FORMAT_G8_B8R8_2PLANE_422_UNORM,
+    VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM,
+    VK_FORMAT_R10X6_UNORM_PACK16,
+    VK_FORMAT_R10X6G10X6_UNORM_2PACK16,
+    VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
+    VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16,
+    VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16,
+    VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16,
+    VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16,
+    VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16,
+    VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16,
+    VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16,
+    VK_FORMAT_R12X4_UNORM_PACK16,
+    VK_FORMAT_R12X4G12X4_UNORM_2PACK16,
+    VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16,
+    VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16,
+    VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16,
+    VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16,
+    VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16,
+    VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16,
+    VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16,
+    VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16,
+    VK_FORMAT_G16B16G16R16_422_UNORM,
+    VK_FORMAT_B16G16R16G16_422_UNORM,
+    VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM,
+    VK_FORMAT_G16_B16R16_2PLANE_420_UNORM,
+    VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM,
+    VK_FORMAT_G16_B16R16_2PLANE_422_UNORM,
+    VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM,
+    VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG,
+    VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG,
+    VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG,
+    VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG,
+    VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG,
+    VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG,
+    VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG,
+    VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG,
+};
+const size_t VK_FORMAT_COUNT = _countof(VK_FORMAT_NAMES);
+static_assert(
+    _countof(VK_FORMAT_NAMES) == _countof(VK_FORMAT_VALUES),
+    "VK_FORMAT_NAMES array doesn't match VK_FORMAT_VALUES.");
+
+const char* VK_SAMPLE_COUNT_NAMES[] = {
+    "VK_SAMPLE_COUNT_1_BIT",
+    "VK_SAMPLE_COUNT_2_BIT",
+    "VK_SAMPLE_COUNT_4_BIT",
+    "VK_SAMPLE_COUNT_8_BIT",
+    "VK_SAMPLE_COUNT_16_BIT",
+    "VK_SAMPLE_COUNT_32_BIT",
+    "VK_SAMPLE_COUNT_64_BIT",
+};
+const uint32_t VK_SAMPLE_COUNT_VALUES[] = {
+    VK_SAMPLE_COUNT_1_BIT,
+    VK_SAMPLE_COUNT_2_BIT,
+    VK_SAMPLE_COUNT_4_BIT,
+    VK_SAMPLE_COUNT_8_BIT,
+    VK_SAMPLE_COUNT_16_BIT,
+    VK_SAMPLE_COUNT_32_BIT,
+    VK_SAMPLE_COUNT_64_BIT,
+};
+const size_t VK_SAMPLE_COUNT_COUNT = _countof(VK_SAMPLE_COUNT_NAMES);
+static_assert(
+    _countof(VK_SAMPLE_COUNT_NAMES) == _countof(VK_SAMPLE_COUNT_VALUES),
+    "VK_SAMPLE_COUNT_NAMES array doesn't match VK_SAMPLE_COUNT_VALUES.");
+
+const char* VK_IMAGE_TILING_NAMES[] = {
+    "VK_IMAGE_TILING_OPTIMAL",
+    "VK_IMAGE_TILING_LINEAR",
+};
+const size_t VK_IMAGE_TILING_COUNT = _countof(VK_IMAGE_TILING_NAMES);
+
+const char* VK_IMAGE_USAGE_FLAG_NAMES[] = {
+    "VK_IMAGE_USAGE_TRANSFER_SRC_BIT",
+    "VK_IMAGE_USAGE_TRANSFER_DST_BIT",
+    "VK_IMAGE_USAGE_SAMPLED_BIT",
+    "VK_IMAGE_USAGE_STORAGE_BIT",
+    "VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT",
+    "VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT",
+    "VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT",
+    "VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT",
+    //"VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV",
+};
+const uint32_t VK_IMAGE_USAGE_FLAG_VALUES[] = {
+    VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
+    VK_IMAGE_USAGE_TRANSFER_DST_BIT,
+    VK_IMAGE_USAGE_SAMPLED_BIT,
+    VK_IMAGE_USAGE_STORAGE_BIT,
+    VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
+    VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
+    VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
+    VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT,
+    //VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV,
+};
+const size_t VK_IMAGE_USAGE_FLAG_COUNT = _countof(VK_IMAGE_USAGE_FLAG_NAMES);
+static_assert(
+    _countof(VK_IMAGE_USAGE_FLAG_NAMES) == _countof(VK_IMAGE_USAGE_FLAG_VALUES),
+    "VK_IMAGE_USAGE_FLAG_NAMES array doesn't match VK_IMAGE_USAGE_FLAG_VALUES.");
+
+const char* VK_IMAGE_LAYOUT_NAMES[] = {
+    "VK_IMAGE_LAYOUT_UNDEFINED",
+    "VK_IMAGE_LAYOUT_GENERAL",
+    "VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL",
+    "VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL",
+    "VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL",
+    "VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL",
+    "VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL",
+    "VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL",
+    "VK_IMAGE_LAYOUT_PREINITIALIZED",
+    "VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL",
+    "VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL",
+    "VK_IMAGE_LAYOUT_PRESENT_SRC_KHR",
+    "VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR",
+    //"VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV",
+};
+const uint32_t VK_IMAGE_LAYOUT_VALUES[] = {
+    VK_IMAGE_LAYOUT_UNDEFINED,
+    VK_IMAGE_LAYOUT_GENERAL,
+    VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+    VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
+    VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL,
+    VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
+    VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+    VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+    VK_IMAGE_LAYOUT_PREINITIALIZED,
+    VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL,
+    VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL,
+    VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
+    VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR,
+    //VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV,
+};
+const size_t VK_IMAGE_LAYOUT_COUNT = _countof(VK_IMAGE_LAYOUT_NAMES);
+static_assert(
+    _countof(VK_IMAGE_LAYOUT_NAMES) == _countof(VK_IMAGE_LAYOUT_VALUES),
+    "VK_IMAGE_LAYOUT_NAMES array doesn't match VK_IMAGE_LAYOUT_VALUES.");
+
+const char* VMA_ALLOCATION_CREATE_FLAG_NAMES[] = {
+    "VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT",
+    "VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT",
+    "VMA_ALLOCATION_CREATE_MAPPED_BIT",
+    "VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT",
+    "VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT",
+    "VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT",
+    "VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT",
+    "VMA_ALLOCATION_CREATE_DONT_BIND_BIT",
+    "VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT",
+    "VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT",
+    "VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT",
+    "VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT",
+};
+const uint32_t VMA_ALLOCATION_CREATE_FLAG_VALUES[] = {
+    VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT,
+    VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT,
+    VMA_ALLOCATION_CREATE_MAPPED_BIT,
+    VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT,
+    VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT,
+    VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT,
+    VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT,
+    VMA_ALLOCATION_CREATE_DONT_BIND_BIT,
+    VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT,
+    VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT,
+    VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT,
+    VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT,
+};
+const size_t VMA_ALLOCATION_CREATE_FLAG_COUNT = _countof(VMA_ALLOCATION_CREATE_FLAG_NAMES);
+static_assert(
+    _countof(VMA_ALLOCATION_CREATE_FLAG_NAMES) == _countof(VMA_ALLOCATION_CREATE_FLAG_VALUES),
+    "VMA_ALLOCATION_CREATE_FLAG_NAMES array doesn't match VMA_ALLOCATION_CREATE_FLAG_VALUES.");
+
+const char* VMA_MEMORY_USAGE_NAMES[] = {
+    "VMA_MEMORY_USAGE_UNKNOWN",
+    "VMA_MEMORY_USAGE_GPU_ONLY",
+    "VMA_MEMORY_USAGE_CPU_ONLY",
+    "VMA_MEMORY_USAGE_CPU_TO_GPU",
+    "VMA_MEMORY_USAGE_GPU_TO_CPU",
+    "VMA_MEMORY_USAGE_CPU_COPY",
+    "VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED",
+};
+const size_t VMA_MEMORY_USAGE_COUNT = _countof(VMA_MEMORY_USAGE_NAMES);
+
+const char* VK_MEMORY_PROPERTY_FLAG_NAMES[] = {
+    "VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT",
+    "VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT",
+    "VK_MEMORY_PROPERTY_HOST_COHERENT_BIT",
+    "VK_MEMORY_PROPERTY_HOST_CACHED_BIT",
+    "VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT",
+    "VK_MEMORY_PROPERTY_PROTECTED_BIT",
+};
+const uint32_t VK_MEMORY_PROPERTY_FLAG_VALUES[] = {
+    VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
+    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
+    VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
+    VK_MEMORY_PROPERTY_HOST_CACHED_BIT,
+    VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT,
+    VK_MEMORY_PROPERTY_PROTECTED_BIT,
+};
+const size_t VK_MEMORY_PROPERTY_FLAG_COUNT = _countof(VK_MEMORY_PROPERTY_FLAG_NAMES);
+static_assert(
+    _countof(VK_MEMORY_PROPERTY_FLAG_NAMES) == _countof(VK_MEMORY_PROPERTY_FLAG_VALUES),
+    "VK_MEMORY_PROPERTY_FLAG_NAMES array doesn't match VK_MEMORY_PROPERTY_FLAG_VALUES.");
diff --git a/third_party/VulkanMemoryAllocator/src/VmaReplay/Constants.h b/third_party/VulkanMemoryAllocator/src/VmaReplay/Constants.h
new file mode 100644
index 0000000..d6d6812
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/src/VmaReplay/Constants.h
@@ -0,0 +1,149 @@
+//
+// Copyright (c) 2017-2020 Advanced Micro Devices, Inc. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#pragma once
+
+extern const int RESULT_EXCEPTION;
+extern const int RESULT_ERROR_COMMAND_LINE;
+extern const int RESULT_ERROR_SOURCE_FILE;
+extern const int RESULT_ERROR_FORMAT;
+extern const int RESULT_ERROR_VULKAN;
+
+enum CMD_LINE_OPT
+{
+    CMD_LINE_OPT_VERBOSITY,
+    CMD_LINE_OPT_ITERATIONS,
+    CMD_LINE_OPT_LINES,
+    CMD_LINE_OPT_PHYSICAL_DEVICE,
+    CMD_LINE_OPT_USER_DATA,
+    CMD_LINE_OPT_VK_KHR_DEDICATED_ALLOCATION,
+    CMD_LINE_OPT_VK_EXT_MEMORY_BUDGET,
+    CMD_LINE_OPT_VK_LAYER_LUNARG_STANDARD_VALIDATION,
+    CMD_LINE_OPT_MEM_STATS,
+    CMD_LINE_OPT_DUMP_STATS_AFTER_LINE,
+    CMD_LINE_OPT_DEFRAGMENT_AFTER_LINE,
+    CMD_LINE_OPT_DEFRAGMENTATION_FLAGS,
+    CMD_LINE_OPT_DUMP_DETAILED_STATS_AFTER_LINE,
+};
+
+enum class VERBOSITY
+{
+    MINIMUM = 0,
+    DEFAULT,
+    MAXIMUM,
+    COUNT,
+};
+
+enum class VULKAN_EXTENSION_REQUEST
+{
+    DISABLED,
+    ENABLED,
+    DEFAULT
+};
+
+enum class OBJECT_TYPE { BUFFER, IMAGE };
+
+enum class VMA_FUNCTION
+{
+    CreatePool,
+    DestroyPool,
+    SetAllocationUserData,
+    CreateBuffer,
+    DestroyBuffer,
+    CreateImage,
+    DestroyImage,
+    FreeMemory,
+    FreeMemoryPages,
+    CreateLostAllocation,
+    AllocateMemory,
+    AllocateMemoryPages,
+    AllocateMemoryForBuffer,
+    AllocateMemoryForImage,
+    MapMemory,
+    UnmapMemory,
+    FlushAllocation,
+    InvalidateAllocation,
+    TouchAllocation,
+    GetAllocationInfo,
+    MakePoolAllocationsLost,
+    ResizeAllocation,
+    DefragmentationBegin,
+    DefragmentationEnd,
+    SetPoolName,
+    Count
+};
+extern const char* VMA_FUNCTION_NAMES[];
+
+extern const char* VMA_POOL_CREATE_FLAG_NAMES[];
+extern const uint32_t VMA_POOL_CREATE_FLAG_VALUES[];
+extern const size_t VMA_POOL_CREATE_FLAG_COUNT;
+
+extern const char* VK_BUFFER_CREATE_FLAG_NAMES[];
+extern const uint32_t VK_BUFFER_CREATE_FLAG_VALUES[];
+extern const size_t VK_BUFFER_CREATE_FLAG_COUNT;
+
+extern const char* VK_BUFFER_USAGE_FLAG_NAMES[];
+extern const uint32_t VK_BUFFER_USAGE_FLAG_VALUES[];
+extern const size_t VK_BUFFER_USAGE_FLAG_COUNT;
+
+extern const char* VK_SHARING_MODE_NAMES[];
+extern const size_t VK_SHARING_MODE_COUNT;
+
+extern const char* VK_IMAGE_CREATE_FLAG_NAMES[];
+extern const uint32_t VK_IMAGE_CREATE_FLAG_VALUES[];
+extern const size_t VK_IMAGE_CREATE_FLAG_COUNT;
+
+extern const char* VK_IMAGE_TYPE_NAMES[];
+extern const size_t VK_IMAGE_TYPE_COUNT;
+
+extern const char* VK_FORMAT_NAMES[];
+extern const uint32_t VK_FORMAT_VALUES[];
+extern const size_t VK_FORMAT_COUNT;
+
+extern const char* VK_SAMPLE_COUNT_NAMES[];
+extern const uint32_t VK_SAMPLE_COUNT_VALUES[];
+extern const size_t VK_SAMPLE_COUNT_COUNT;
+
+extern const char* VK_IMAGE_TILING_NAMES[];
+extern const size_t VK_IMAGE_TILING_COUNT;
+
+extern const char* VK_IMAGE_USAGE_FLAG_NAMES[];
+extern const uint32_t VK_IMAGE_USAGE_FLAG_VALUES[];
+extern const size_t VK_IMAGE_USAGE_FLAG_COUNT;
+
+extern const char* VK_IMAGE_TILING_NAMES[];
+extern const size_t VK_IMAGE_TILING_COUNT;
+
+extern const char* VK_IMAGE_LAYOUT_NAMES[];
+extern const uint32_t VK_IMAGE_LAYOUT_VALUES[];
+extern const size_t VK_IMAGE_LAYOUT_COUNT;
+
+extern const char* VMA_ALLOCATION_CREATE_FLAG_NAMES[];
+extern const uint32_t VMA_ALLOCATION_CREATE_FLAG_VALUES[];
+extern const size_t VMA_ALLOCATION_CREATE_FLAG_COUNT;
+
+extern const char* VMA_MEMORY_USAGE_NAMES[];
+extern const size_t VMA_MEMORY_USAGE_COUNT;
+
+extern const char* VK_MEMORY_PROPERTY_FLAG_NAMES[];
+extern const uint32_t VK_MEMORY_PROPERTY_FLAG_VALUES[];
+extern const size_t VK_MEMORY_PROPERTY_FLAG_COUNT;
diff --git a/third_party/VulkanMemoryAllocator/src/VmaReplay/VmaReplay.cpp b/third_party/VulkanMemoryAllocator/src/VmaReplay/VmaReplay.cpp
new file mode 100644
index 0000000..552555b
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/src/VmaReplay/VmaReplay.cpp
@@ -0,0 +1,4417 @@
+//
+// Copyright (c) 2018-2020 Advanced Micro Devices, Inc. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#include "VmaUsage.h"
+#include "Common.h"
+#include "Constants.h"
+#include <unordered_map>
+#include <map>
+#include <algorithm>
+
+static VERBOSITY g_Verbosity = VERBOSITY::DEFAULT;
+
+static const uint32_t VULKAN_API_VERSION = VK_API_VERSION_1_1;
+
+namespace DetailedStats
+{
+    
+struct Flag
+{
+    uint32_t setCount = 0;
+
+    void PostValue(bool v)
+    {
+        if(v)
+        {
+            ++setCount;
+        }
+    }
+
+    void Print(uint32_t totalCount) const
+    {
+        if(setCount)
+        {
+            printf(" %u (%.2f%%)\n", setCount, (double)setCount * 100.0 / (double)totalCount);
+        }
+        else
+        {
+            printf(" 0\n");
+        }
+    }
+};
+
+struct Enum
+{
+    Enum(size_t itemCount, const char* const* itemNames, const uint32_t* itemValues = nullptr) :
+        m_ItemCount(itemCount),
+        m_ItemNames(itemNames),
+        m_ItemValues(itemValues)
+    {
+    }
+
+    void PostValue(uint32_t v)
+    {
+        if(v < _countof(m_BaseCount))
+        {
+            ++m_BaseCount[v];
+        }
+        else
+        {
+            auto it = m_ExtendedCount.find(v);
+            if(it != m_ExtendedCount.end())
+            {
+                ++it->second;
+            }
+            else
+            {
+                m_ExtendedCount.insert(std::make_pair(v, 1u));
+            }
+        }
+    }
+
+    void Print(uint32_t totalCount) const
+    {
+        if(totalCount &&
+            (!m_ExtendedCount.empty() || std::count_if(m_BaseCount, m_BaseCount + _countof(m_BaseCount), [](uint32_t v) { return v > 0; })))
+        {
+            printf("\n");
+            
+            for(size_t i = 0; i < _countof(m_BaseCount); ++i)
+            {
+                const uint32_t currCount = m_BaseCount[i];
+                if(currCount)
+                {
+                    PrintItem((uint32_t)i, currCount, totalCount);
+                }
+            }
+
+            for(const auto& it : m_ExtendedCount)
+            {
+                PrintItem(it.first, it.second, totalCount);
+            }
+        }
+        else
+        {
+            printf(" 0\n");
+        }
+    }
+
+private:
+    const size_t m_ItemCount;
+    const char* const* const m_ItemNames;
+    const uint32_t* const m_ItemValues;
+
+    uint32_t m_BaseCount[32] = {};
+    std::map<uint32_t, uint32_t> m_ExtendedCount;
+
+    void PrintItem(uint32_t value, uint32_t count, uint32_t totalCount) const
+    {
+        size_t itemIndex = m_ItemCount;
+        if(m_ItemValues)
+        {
+            for(itemIndex = 0; itemIndex < m_ItemCount; ++itemIndex)
+            {
+                if(m_ItemValues[itemIndex] == value)
+                {
+                    break;
+                }
+            }
+        }
+        else
+        {
+            if(value < m_ItemCount)
+            {
+                itemIndex = value;
+            }
+        }
+
+        if(itemIndex < m_ItemCount)
+        {
+            printf("        %s: ", m_ItemNames[itemIndex]);
+        }
+        else
+        {
+            printf("        0x%X: ", value);
+        }
+
+        printf("%u (%.2f%%)\n", count, (double)count * 100.0 / (double)totalCount);
+    }
+};
+
+struct FlagSet
+{
+    uint32_t count[32] = {};
+
+    FlagSet(size_t count, const char* const* names, const uint32_t* values = nullptr) :
+        m_Count(count),
+        m_Names(names),
+        m_Values(values)
+    {
+    }
+
+    void PostValue(uint32_t v)
+    {
+        for(size_t i = 0; i < 32; ++i)
+        {
+            if((v & (1u << i)) != 0)
+            {
+                ++count[i];
+            }
+        }
+    }
+
+    void Print(uint32_t totalCount) const
+    {
+        if(totalCount &&
+            std::count_if(count, count + _countof(count), [](uint32_t v) { return v > 0; }))
+        {
+            printf("\n");
+            for(uint32_t bitIndex = 0; bitIndex < 32; ++bitIndex)
+            {
+                const uint32_t currCount = count[bitIndex];
+                if(currCount)
+                {
+                    size_t itemIndex = m_Count;
+                    if(m_Values)
+                    {
+                        for(itemIndex = 0; itemIndex < m_Count; ++itemIndex)
+                        {
+                            if(m_Values[itemIndex] == (1u << bitIndex))
+                            {
+                                break;
+                            }
+                        }
+                    }
+                    else
+                    {
+                        if(bitIndex < m_Count)
+                        {
+                            itemIndex = bitIndex;
+                        }
+                    }
+
+                    if(itemIndex < m_Count)
+                    {
+                        printf("        %s: ", m_Names[itemIndex]);
+                    }
+                    else
+                    {
+                        printf("        0x%X: ", 1u << bitIndex);
+                    }
+
+                    printf("%u (%.2f%%)\n", currCount, (double)currCount * 100.0 / (double)totalCount);
+                }
+            }
+        }
+        else
+        {
+            printf(" 0\n");
+        }
+    }
+
+private:
+    const size_t m_Count;
+    const char* const* const m_Names;
+    const uint32_t* const m_Values;
+};
+
+// T should be unsigned int
+template<typename T>
+struct MinMaxAvg
+{
+    T min = std::numeric_limits<T>::max();
+    T max = 0;
+    T sum = T();
+
+    void PostValue(T v)
+    {
+        this->min = std::min(this->min, v);
+        this->max = std::max(this->max, v);
+        sum += v;
+    }
+
+    void Print(uint32_t totalCount) const
+    {
+        if(totalCount && sum > T())
+        {
+            if(this->min == this->max)
+            {
+                printf(" %llu\n", (uint64_t)this->max);
+            }
+            else
+            {
+                printf("\n        Min: %llu\n        Max: %llu\n        Avg: %llu\n",
+                    (uint64_t)this->min,
+                    (uint64_t)this->max,
+                    round_div<uint64_t>(this->sum, totalCount));
+            }
+        }
+        else
+        {
+            printf(" 0\n");
+        }
+    }
+};
+
+template<typename T>
+struct BitMask
+{
+    uint32_t zeroCount = 0;
+    uint32_t maxCount = 0;
+
+    void PostValue(T v)
+    {
+        if(v)
+        {
+            if(v == std::numeric_limits<T>::max())
+            {
+                ++maxCount;
+            }
+        }
+        else
+        {
+            ++zeroCount;
+        }
+    }
+
+    void Print(uint32_t totalCount) const
+    {
+        if(totalCount > 0 && zeroCount < totalCount)
+        {
+            const uint32_t otherCount = totalCount - (zeroCount + maxCount);
+            
+            printf("\n        0: %u (%.2f%%)\n        Max: %u (%.2f%%)\n        Other: %u (%.2f%%)\n",
+                zeroCount,  (double)zeroCount  * 100.0 / (double)totalCount,
+                maxCount,   (double)maxCount   * 100.0 / (double)totalCount,
+                otherCount, (double)otherCount * 100.0 / (double)totalCount);
+        }
+        else
+        {
+            printf(" 0\n");
+        }
+    }
+};
+
+struct CountPerMemType
+{
+    uint32_t count[VK_MAX_MEMORY_TYPES] = {};
+
+    void PostValue(uint32_t v)
+    {
+        for(uint32_t i = 0; i < VK_MAX_MEMORY_TYPES; ++i)
+        {
+            if((v & (1u << i)) != 0)
+            {
+                ++count[i];
+            }
+        }
+    }
+
+    void Print(uint32_t totalCount) const
+    {
+        if(totalCount)
+        {
+            printf("\n");
+            for(uint32_t i = 0; i < VK_MAX_MEMORY_TYPES; ++i)
+            {
+                if(count[i])
+                {
+                    printf("        %u: %u (%.2f%%)\n", i, count[i],
+                        (double)count[i] * 100.0 / (double)totalCount);
+                }
+            }
+        }
+        else
+        {
+            printf(" 0\n");
+        }
+    }
+};
+
+struct StructureStats
+{
+    uint32_t totalCount = 0;
+};
+
+#define PRINT_FIELD(name) \
+    printf("    " #name ":"); \
+    (name).Print(totalCount);
+#define PRINT_FIELD_NAMED(name, nameStr) \
+    printf("    " nameStr ":"); \
+    (name).Print(totalCount);
+
+struct VmaPoolCreateInfoStats : public StructureStats
+{
+    CountPerMemType memoryTypeIndex;
+    FlagSet flags;
+    MinMaxAvg<VkDeviceSize> blockSize;
+    MinMaxAvg<size_t> minBlockCount;
+    MinMaxAvg<size_t> maxBlockCount;
+    Flag minMaxBlockCountEqual;
+    MinMaxAvg<uint32_t> frameInUseCount;
+
+    VmaPoolCreateInfoStats() :
+        flags(VMA_POOL_CREATE_FLAG_COUNT, VMA_POOL_CREATE_FLAG_NAMES, VMA_POOL_CREATE_FLAG_VALUES)
+    {
+    }
+
+    void PostValue(const VmaPoolCreateInfo& v)
+    {
+        ++totalCount;
+
+        memoryTypeIndex.PostValue(v.memoryTypeIndex);
+        flags.PostValue(v.flags);
+        blockSize.PostValue(v.blockSize);
+        minBlockCount.PostValue(v.minBlockCount);
+        maxBlockCount.PostValue(v.maxBlockCount);
+        minMaxBlockCountEqual.PostValue(v.minBlockCount == v.maxBlockCount);
+        frameInUseCount.PostValue(v.frameInUseCount);
+    }
+
+    void Print() const
+    {
+        if(totalCount == 0)
+        {
+            return;
+        }
+
+        printf("VmaPoolCreateInfo (%u):\n", totalCount);
+
+        PRINT_FIELD(memoryTypeIndex);
+        PRINT_FIELD(flags);
+        PRINT_FIELD(blockSize);
+        PRINT_FIELD(minBlockCount);
+        PRINT_FIELD(maxBlockCount);
+        PRINT_FIELD_NAMED(minMaxBlockCountEqual, "minBlockCount == maxBlockCount");
+        PRINT_FIELD(frameInUseCount);
+    }
+};
+
+struct VkBufferCreateInfoStats : public StructureStats
+{
+    FlagSet flags;
+    MinMaxAvg<VkDeviceSize> size;
+    FlagSet usage;
+    Enum sharingMode;
+
+    VkBufferCreateInfoStats() :
+        flags(VK_BUFFER_CREATE_FLAG_COUNT, VK_BUFFER_CREATE_FLAG_NAMES, VK_BUFFER_CREATE_FLAG_VALUES),
+        usage(VK_BUFFER_USAGE_FLAG_COUNT, VK_BUFFER_USAGE_FLAG_NAMES, VK_BUFFER_USAGE_FLAG_VALUES),
+        sharingMode(VK_SHARING_MODE_COUNT, VK_SHARING_MODE_NAMES)
+    {
+    }
+
+    void PostValue(const VkBufferCreateInfo& v)
+    {
+        ++totalCount;
+
+        flags.PostValue(v.flags);
+        size.PostValue(v.size);
+        usage.PostValue(v.usage);
+        sharingMode.PostValue(v.sharingMode);
+    }
+
+    void Print() const
+    {
+        if(totalCount == 0)
+        {
+            return;
+        }
+
+        printf("VkBufferCreateInfo (%u):\n", totalCount);
+
+        PRINT_FIELD(flags);
+        PRINT_FIELD(size);
+        PRINT_FIELD(usage);
+        PRINT_FIELD(sharingMode);
+    }
+};
+
+struct VkImageCreateInfoStats : public StructureStats
+{
+    FlagSet flags;
+    Enum imageType;
+    Enum format;
+    MinMaxAvg<uint32_t> width, height, depth, mipLevels, arrayLayers;
+    Flag depthGreaterThanOne, mipLevelsGreaterThanOne, arrayLayersGreaterThanOne;
+    Enum samples;
+    Enum tiling;
+    FlagSet usage;
+    Enum sharingMode;
+    Enum initialLayout;
+
+    VkImageCreateInfoStats() :
+        flags(VK_IMAGE_CREATE_FLAG_COUNT, VK_IMAGE_CREATE_FLAG_NAMES, VK_IMAGE_CREATE_FLAG_VALUES),
+        imageType(VK_IMAGE_TYPE_COUNT, VK_IMAGE_TYPE_NAMES),
+        format(VK_FORMAT_COUNT, VK_FORMAT_NAMES, VK_FORMAT_VALUES),
+        samples(VK_SAMPLE_COUNT_COUNT, VK_SAMPLE_COUNT_NAMES, VK_SAMPLE_COUNT_VALUES),
+        tiling(VK_IMAGE_TILING_COUNT, VK_IMAGE_TILING_NAMES),
+        usage(VK_IMAGE_USAGE_FLAG_COUNT, VK_IMAGE_USAGE_FLAG_NAMES, VK_IMAGE_USAGE_FLAG_VALUES),
+        sharingMode(VK_SHARING_MODE_COUNT, VK_SHARING_MODE_NAMES),
+        initialLayout(VK_IMAGE_LAYOUT_COUNT, VK_IMAGE_LAYOUT_NAMES, VK_IMAGE_LAYOUT_VALUES)
+    {
+    }
+
+    void PostValue(const VkImageCreateInfo& v)
+    {
+        ++totalCount;
+
+        flags.PostValue(v.flags);
+        imageType.PostValue(v.imageType);
+        format.PostValue(v.format);
+        width.PostValue(v.extent.width);
+        height.PostValue(v.extent.height);
+        depth.PostValue(v.extent.depth);
+        mipLevels.PostValue(v.mipLevels);
+        arrayLayers.PostValue(v.arrayLayers);
+        depthGreaterThanOne.PostValue(v.extent.depth > 1);
+        mipLevelsGreaterThanOne.PostValue(v.mipLevels > 1);
+        arrayLayersGreaterThanOne.PostValue(v.arrayLayers > 1);
+        samples.PostValue(v.samples);
+        tiling.PostValue(v.tiling);
+        usage.PostValue(v.usage);
+        sharingMode.PostValue(v.sharingMode);
+        initialLayout.PostValue(v.initialLayout);
+    }
+
+    void Print() const
+    {
+        if(totalCount == 0)
+        {
+            return;
+        }
+
+        printf("VkImageCreateInfo (%u):\n", totalCount);
+
+        PRINT_FIELD(flags);
+        PRINT_FIELD(imageType);
+        PRINT_FIELD(format);
+        PRINT_FIELD(width);
+        PRINT_FIELD(height);
+        PRINT_FIELD(depth);
+        PRINT_FIELD(mipLevels);
+        PRINT_FIELD(arrayLayers);
+        PRINT_FIELD_NAMED(depthGreaterThanOne, "depth > 1");
+        PRINT_FIELD_NAMED(mipLevelsGreaterThanOne, "mipLevels > 1");
+        PRINT_FIELD_NAMED(arrayLayersGreaterThanOne, "arrayLayers > 1");
+        PRINT_FIELD(samples);
+        PRINT_FIELD(tiling);
+        PRINT_FIELD(usage);
+        PRINT_FIELD(sharingMode);
+        PRINT_FIELD(initialLayout);
+    }
+};
+
+struct VmaAllocationCreateInfoStats : public StructureStats
+{
+    FlagSet flags;
+    Enum usage;
+    FlagSet requiredFlags, preferredFlags;
+    Flag requiredFlagsNotZero, preferredFlagsNotZero;
+    BitMask<uint32_t> memoryTypeBits;
+    Flag poolNotNull;
+    Flag userDataNotNull;
+
+    VmaAllocationCreateInfoStats() :
+        flags(VMA_ALLOCATION_CREATE_FLAG_COUNT, VMA_ALLOCATION_CREATE_FLAG_NAMES, VMA_ALLOCATION_CREATE_FLAG_VALUES),
+        usage(VMA_MEMORY_USAGE_COUNT, VMA_MEMORY_USAGE_NAMES),
+        requiredFlags(VK_MEMORY_PROPERTY_FLAG_COUNT, VK_MEMORY_PROPERTY_FLAG_NAMES, VK_MEMORY_PROPERTY_FLAG_VALUES),
+        preferredFlags(VK_MEMORY_PROPERTY_FLAG_COUNT, VK_MEMORY_PROPERTY_FLAG_NAMES, VK_MEMORY_PROPERTY_FLAG_VALUES)
+    {
+    }
+
+    void PostValue(const VmaAllocationCreateInfo& v, size_t count = 1)
+    {
+        totalCount += (uint32_t)count;
+
+        for(size_t i = 0; i < count; ++i)
+        {
+            flags.PostValue(v.flags);
+            usage.PostValue(v.usage);
+            requiredFlags.PostValue(v.requiredFlags);
+            preferredFlags.PostValue(v.preferredFlags);
+            requiredFlagsNotZero.PostValue(v.requiredFlags != 0);
+            preferredFlagsNotZero.PostValue(v.preferredFlags != 0);
+            memoryTypeBits.PostValue(v.memoryTypeBits);
+            poolNotNull.PostValue(v.pool != VK_NULL_HANDLE);
+            userDataNotNull.PostValue(v.pUserData != nullptr);
+        }
+    }
+
+    void Print() const
+    {
+        if(totalCount == 0)
+        {
+            return;
+        }
+
+        printf("VmaAllocationCreateInfo (%u):\n", totalCount);
+
+        PRINT_FIELD(flags);
+        PRINT_FIELD(usage);
+        PRINT_FIELD(requiredFlags);
+        PRINT_FIELD(preferredFlags);
+        PRINT_FIELD_NAMED(requiredFlagsNotZero, "requiredFlags != 0");
+        PRINT_FIELD_NAMED(preferredFlagsNotZero, "preferredFlags != 0");
+        PRINT_FIELD(memoryTypeBits);
+        PRINT_FIELD_NAMED(poolNotNull, "pool != VK_NULL_HANDLE");
+        PRINT_FIELD_NAMED(userDataNotNull, "pUserData != nullptr");
+    }
+};
+
+struct VmaAllocateMemoryPagesStats : public StructureStats
+{
+    MinMaxAvg<size_t> allocationCount;
+
+    void PostValue(size_t allocationCount)
+    {
+        this->allocationCount.PostValue(allocationCount);
+    }
+
+    void Print() const
+    {
+        if(totalCount == 0)
+        {
+            return;
+        }
+
+        printf("vmaAllocateMemoryPages (%u):\n", totalCount);
+
+        PRINT_FIELD(allocationCount);
+    }
+};
+
+struct VmaDefragmentationInfo2Stats : public StructureStats
+{
+    BitMask<VkDeviceSize> maxCpuBytesToMove;
+    BitMask<uint32_t> maxCpuAllocationsToMove;
+    BitMask<VkDeviceSize> maxGpuBytesToMove;
+    BitMask<uint32_t> maxGpuAllocationsToMove;
+    Flag commandBufferNotNull;
+    MinMaxAvg<uint32_t> allocationCount;
+    Flag allocationCountNotZero;
+    MinMaxAvg<uint32_t> poolCount;
+    Flag poolCountNotZero;
+
+    void PostValue(const VmaDefragmentationInfo2& info)
+    {
+        ++totalCount;
+
+        maxCpuBytesToMove.PostValue(info.maxCpuBytesToMove);
+        maxCpuAllocationsToMove.PostValue(info.maxCpuAllocationsToMove);
+        maxGpuBytesToMove.PostValue(info.maxGpuBytesToMove);
+        maxGpuAllocationsToMove.PostValue(info.maxGpuAllocationsToMove);
+        commandBufferNotNull.PostValue(info.commandBuffer != VK_NULL_HANDLE);
+        allocationCount.PostValue(info.allocationCount);
+        allocationCountNotZero.PostValue(info.allocationCount != 0);
+        poolCount.PostValue(info.poolCount);
+        poolCountNotZero.PostValue(info.poolCount != 0);
+    }
+
+    void Print() const
+    {
+        if(totalCount == 0)
+        {
+            return;
+        }
+
+        printf("VmaDefragmentationInfo2 (%u):\n", totalCount);
+
+        PRINT_FIELD(maxCpuBytesToMove);
+        PRINT_FIELD(maxCpuAllocationsToMove);
+        PRINT_FIELD(maxGpuBytesToMove);
+        PRINT_FIELD(maxGpuAllocationsToMove);
+        PRINT_FIELD_NAMED(commandBufferNotNull, "commandBuffer != VK_NULL_HANDLE");
+        PRINT_FIELD(allocationCount);
+        PRINT_FIELD_NAMED(allocationCountNotZero, "allocationCount > 0");
+        PRINT_FIELD(poolCount);
+        PRINT_FIELD_NAMED(poolCountNotZero, "poolCount > 0");
+    }
+};
+
+#undef PRINT_FIELD_NAMED
+#undef PRINT_FIELD
+
+} // namespace DetailedStats
+
+// Set this to false to disable deleting leaked VmaAllocation, VmaPool objects
+// and let VMA report asserts about them.
+static const bool CLEANUP_LEAKED_OBJECTS = true;
+
+static std::string g_FilePath;
+// Most significant 16 bits are major version, least significant 16 bits are minor version.
+static uint32_t g_FileVersion;
+
+inline uint32_t MakeVersion(uint32_t major, uint32_t minor) { return (major << 16) | minor; }
+inline uint32_t GetVersionMajor(uint32_t version) { return version >> 16; }
+inline uint32_t GetVersionMinor(uint32_t version) { return version & 0xFFFF; }
+
+static size_t g_IterationCount = 1;
+static uint32_t g_PhysicalDeviceIndex = 0;
+static RangeSequence<size_t> g_LineRanges;
+static bool g_UserDataEnabled = true;
+static bool g_MemStatsEnabled = false;
+VULKAN_EXTENSION_REQUEST g_VK_LAYER_LUNARG_standard_validation = VULKAN_EXTENSION_REQUEST::DEFAULT;
+VULKAN_EXTENSION_REQUEST g_VK_EXT_memory_budget_request        = VULKAN_EXTENSION_REQUEST::DEFAULT;
+VULKAN_EXTENSION_REQUEST g_VK_AMD_device_coherent_memory_request = VULKAN_EXTENSION_REQUEST::DEFAULT;
+
+struct StatsAfterLineEntry
+{
+    size_t line;
+    bool detailed;
+
+    bool operator<(const StatsAfterLineEntry& rhs) const { return line < rhs.line; }
+    bool operator==(const StatsAfterLineEntry& rhs) const { return line == rhs.line; }
+};
+static std::vector<StatsAfterLineEntry> g_DumpStatsAfterLine;
+static std::vector<size_t> g_DefragmentAfterLine;
+static uint32_t g_DefragmentationFlags = 0;
+static size_t g_DumpStatsAfterLineNextIndex = 0;
+static size_t g_DefragmentAfterLineNextIndex = 0;
+
+static bool ValidateFileVersion()
+{
+    if(GetVersionMajor(g_FileVersion) == 1 &&
+        GetVersionMinor(g_FileVersion) <= 8)
+    {
+        return true;
+    }
+
+    return false;
+}
+
+static bool ParseFileVersion(const StrRange& s)
+{
+    CsvSplit csvSplit;
+    csvSplit.Set(s, 2);
+    uint32_t major, minor;
+    if(csvSplit.GetCount() == 2 &&
+        StrRangeToUint(csvSplit.GetRange(0), major) &&
+        StrRangeToUint(csvSplit.GetRange(1), minor))
+    {
+        g_FileVersion = (major << 16) | minor;
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// class Statistics
+
+class Statistics
+{
+public:
+    static uint32_t BufferUsageToClass(uint32_t usage);
+    static uint32_t ImageUsageToClass(uint32_t usage);
+
+    Statistics();
+    ~Statistics();
+    void Init(uint32_t memHeapCount, uint32_t memTypeCount);
+    void PrintDeviceMemStats() const;
+    void PrintMemStats() const;
+    void PrintDetailedStats() const;
+
+    const size_t* GetFunctionCallCount() const { return m_FunctionCallCount; }
+    size_t GetImageCreationCount(uint32_t imgClass) const { return m_ImageCreationCount[imgClass]; }
+    size_t GetLinearImageCreationCount() const { return m_LinearImageCreationCount; }
+    size_t GetBufferCreationCount(uint32_t bufClass) const { return m_BufferCreationCount[bufClass]; }
+    size_t GetAllocationCreationCount() const { return (size_t)m_VmaAllocationCreateInfo.totalCount + m_CreateLostAllocationCount; }
+    size_t GetPoolCreationCount() const { return m_VmaPoolCreateInfo.totalCount; }
+    size_t GetBufferCreationCount() const { return (size_t)m_VkBufferCreateInfo.totalCount; }
+
+    void RegisterFunctionCall(VMA_FUNCTION func);
+    void RegisterCreateImage(const VkImageCreateInfo& info);
+    void RegisterCreateBuffer(const VkBufferCreateInfo& info);
+    void RegisterCreatePool(const VmaPoolCreateInfo& info);
+    void RegisterCreateAllocation(const VmaAllocationCreateInfo& info, size_t allocCount = 1);
+    void RegisterCreateLostAllocation() { ++m_CreateLostAllocationCount; }
+    void RegisterAllocateMemoryPages(size_t allocCount) { m_VmaAllocateMemoryPages.PostValue(allocCount); }
+    void RegisterDefragmentation(const VmaDefragmentationInfo2& info);
+
+    void RegisterDeviceMemoryAllocation(uint32_t memoryType, VkDeviceSize size);
+    void UpdateMemStats(const VmaStats& currStats);
+
+private:
+    uint32_t m_MemHeapCount = 0;
+    uint32_t m_MemTypeCount = 0;
+
+    size_t m_FunctionCallCount[(size_t)VMA_FUNCTION::Count] = {};
+    size_t m_ImageCreationCount[4] = { };
+    size_t m_LinearImageCreationCount = 0;
+    size_t m_BufferCreationCount[4] = { };
+
+    struct DeviceMemStatInfo
+    {
+        size_t allocationCount;
+        VkDeviceSize allocationTotalSize;
+    };
+    struct DeviceMemStats
+    {
+        DeviceMemStatInfo memoryType[VK_MAX_MEMORY_TYPES];
+        DeviceMemStatInfo total;
+    } m_DeviceMemStats;
+    
+    // Structure similar to VmaStatInfo, but not the same.
+    struct MemStatInfo
+    {
+        uint32_t blockCount;
+        uint32_t allocationCount;
+        uint32_t unusedRangeCount;
+        VkDeviceSize usedBytes;
+        VkDeviceSize unusedBytes;
+        VkDeviceSize totalBytes;
+    };
+    struct MemStats
+    {
+        MemStatInfo memoryType[VK_MAX_MEMORY_TYPES];
+        MemStatInfo memoryHeap[VK_MAX_MEMORY_HEAPS];
+        MemStatInfo total;
+    } m_PeakMemStats;
+
+    DetailedStats::VmaPoolCreateInfoStats m_VmaPoolCreateInfo;
+    DetailedStats::VkBufferCreateInfoStats m_VkBufferCreateInfo;
+    DetailedStats::VkImageCreateInfoStats m_VkImageCreateInfo;
+    DetailedStats::VmaAllocationCreateInfoStats m_VmaAllocationCreateInfo;
+    size_t m_CreateLostAllocationCount = 0;
+    DetailedStats::VmaAllocateMemoryPagesStats m_VmaAllocateMemoryPages;
+    DetailedStats::VmaDefragmentationInfo2Stats m_VmaDefragmentationInfo2;
+
+    void UpdateMemStatInfo(MemStatInfo& inoutPeakInfo, const VmaStatInfo& currInfo);
+    static void PrintMemStatInfo(const MemStatInfo& info);
+};
+
+// Hack for global AllocateDeviceMemoryCallback.
+static Statistics* g_Statistics;
+
+static void VKAPI_CALL AllocateDeviceMemoryCallback(
+    VmaAllocator      allocator,
+    uint32_t          memoryType,
+    VkDeviceMemory    memory,
+    VkDeviceSize      size,
+    void*             pUserData)
+{
+    g_Statistics->RegisterDeviceMemoryAllocation(memoryType, size);
+}
+
+/// Callback function called before vkFreeMemory.
+static void VKAPI_CALL FreeDeviceMemoryCallback(
+    VmaAllocator      allocator,
+    uint32_t          memoryType,
+    VkDeviceMemory    memory,
+    VkDeviceSize      size,
+    void*             pUserData)
+{
+    // Nothing.
+}
+
+uint32_t Statistics::BufferUsageToClass(uint32_t usage)
+{
+    // Buffer is used as source of data for fixed-function stage of graphics pipeline.
+    // It's indirect, vertex, or index buffer.
+    if ((usage & (VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT |
+        VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
+        VK_BUFFER_USAGE_INDEX_BUFFER_BIT)) != 0)
+    {
+        return 0;
+    }
+    // Buffer is accessed by shaders for load/store/atomic.
+    // Aka "UAV"
+    else if ((usage & (VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
+        VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT)) != 0)
+    {
+        return 1;
+    }
+    // Buffer is accessed by shaders for reading uniform data.
+    // Aka "constant buffer"
+    else if ((usage & (VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT |
+    VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT)) != 0)
+    {
+        return 2;
+    }
+    // Any other type of buffer.
+    // Notice that VK_BUFFER_USAGE_TRANSFER_SRC_BIT and VK_BUFFER_USAGE_TRANSFER_DST_BIT
+    // flags are intentionally ignored.
+    else
+    {
+        return 3;
+    }
+}
+
+uint32_t Statistics::ImageUsageToClass(uint32_t usage)
+{
+    // Image is used as depth/stencil "texture/surface".
+    if ((usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0)
+    {
+        return 0;
+    }
+    // Image is used as other type of attachment.
+    // Aka "render target"
+    else if ((usage & (VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
+        VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT |
+        VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)) != 0)
+    {
+        return 1;
+    }
+    // Image is accessed by shaders for sampling.
+    // Aka "texture"
+    else if ((usage & VK_IMAGE_USAGE_SAMPLED_BIT) != 0)
+    {
+        return 2;
+    }
+    // Any other type of image.
+    // Notice that VK_IMAGE_USAGE_TRANSFER_SRC_BIT and VK_IMAGE_USAGE_TRANSFER_DST_BIT
+    // flags are intentionally ignored.
+    else
+    {
+        return 3;
+    }
+}
+
+Statistics::Statistics()
+{
+    ZeroMemory(&m_DeviceMemStats, sizeof(m_DeviceMemStats));
+    ZeroMemory(&m_PeakMemStats, sizeof(m_PeakMemStats));
+
+    assert(g_Statistics == nullptr);
+    g_Statistics = this;
+}
+
+Statistics::~Statistics()
+{
+    assert(g_Statistics == this);
+    g_Statistics = nullptr;
+}
+
+void Statistics::Init(uint32_t memHeapCount, uint32_t memTypeCount)
+{
+    m_MemHeapCount = memHeapCount;
+    m_MemTypeCount = memTypeCount;
+}
+
+void Statistics::PrintDeviceMemStats() const
+{
+    printf("Successful device memory allocations:\n");
+    printf("    Total: count = %zu, total size = %llu\n",
+        m_DeviceMemStats.total.allocationCount, m_DeviceMemStats.total.allocationTotalSize);
+    for(uint32_t i = 0; i < m_MemTypeCount; ++i)
+    {
+        printf("    Memory type %u: count = %zu, total size = %llu\n",
+            i, m_DeviceMemStats.memoryType[i].allocationCount, m_DeviceMemStats.memoryType[i].allocationTotalSize);
+    }
+}
+
+void Statistics::PrintMemStats() const
+{
+    printf("Memory statistics:\n");
+
+    printf("    Total:\n");
+    PrintMemStatInfo(m_PeakMemStats.total);
+
+    for(uint32_t i = 0; i < m_MemHeapCount; ++i)
+    {
+        const MemStatInfo& info = m_PeakMemStats.memoryHeap[i];
+        if(info.blockCount > 0 || info.totalBytes > 0)
+        {
+            printf("    Heap %u:\n", i);
+            PrintMemStatInfo(info);
+        }
+    }
+
+    for(uint32_t i = 0; i < m_MemTypeCount; ++i)
+    {
+        const MemStatInfo& info = m_PeakMemStats.memoryType[i];
+        if(info.blockCount > 0 || info.totalBytes > 0)
+        {
+            printf("    Type %u:\n", i);
+            PrintMemStatInfo(info);
+        }
+    }
+}
+
+void Statistics::PrintDetailedStats() const
+{
+    m_VmaPoolCreateInfo.Print();
+    m_VmaAllocationCreateInfo.Print();
+    m_VmaAllocateMemoryPages.Print();
+    m_VkBufferCreateInfo.Print();
+    m_VkImageCreateInfo.Print();
+    m_VmaDefragmentationInfo2.Print();
+}
+
+void Statistics::RegisterFunctionCall(VMA_FUNCTION func)
+{
+    ++m_FunctionCallCount[(size_t)func];
+}
+
+void Statistics::RegisterCreateImage(const VkImageCreateInfo& info)
+{
+    if(info.tiling == VK_IMAGE_TILING_LINEAR)
+        ++m_LinearImageCreationCount;
+    else
+    {
+        const uint32_t imgClass = ImageUsageToClass(info.usage);
+        ++m_ImageCreationCount[imgClass];
+    }
+
+    m_VkImageCreateInfo.PostValue(info);
+}
+
+void Statistics::RegisterCreateBuffer(const VkBufferCreateInfo& info)
+{
+    const uint32_t bufClass = BufferUsageToClass(info.usage);
+    ++m_BufferCreationCount[bufClass];
+
+    m_VkBufferCreateInfo.PostValue(info);
+}
+
+void Statistics::RegisterCreatePool(const VmaPoolCreateInfo& info)
+{
+    m_VmaPoolCreateInfo.PostValue(info);
+}
+
+void Statistics::RegisterCreateAllocation(const VmaAllocationCreateInfo& info, size_t allocCount)
+{
+    m_VmaAllocationCreateInfo.PostValue(info, allocCount);
+}
+
+void Statistics::RegisterDefragmentation(const VmaDefragmentationInfo2& info)
+{
+    m_VmaDefragmentationInfo2.PostValue(info);
+}
+
+void Statistics::UpdateMemStats(const VmaStats& currStats)
+{
+    UpdateMemStatInfo(m_PeakMemStats.total, currStats.total);
+    
+    for(uint32_t i = 0; i < m_MemHeapCount; ++i)
+    {
+        UpdateMemStatInfo(m_PeakMemStats.memoryHeap[i], currStats.memoryHeap[i]);
+    }
+
+    for(uint32_t i = 0; i < m_MemTypeCount; ++i)
+    {
+        UpdateMemStatInfo(m_PeakMemStats.memoryType[i], currStats.memoryType[i]);
+    }
+}
+
+void Statistics::RegisterDeviceMemoryAllocation(uint32_t memoryType, VkDeviceSize size)
+{
+    ++m_DeviceMemStats.total.allocationCount;
+    m_DeviceMemStats.total.allocationTotalSize += size;
+
+    ++m_DeviceMemStats.memoryType[memoryType].allocationCount;
+    m_DeviceMemStats.memoryType[memoryType].allocationTotalSize += size;
+}
+
+void Statistics::UpdateMemStatInfo(MemStatInfo& inoutPeakInfo, const VmaStatInfo& currInfo)
+{
+#define SET_PEAK(inoutDst, src) \
+    if((src) > (inoutDst)) \
+    { \
+        (inoutDst) = (src); \
+    }
+
+    SET_PEAK(inoutPeakInfo.blockCount, currInfo.blockCount);
+    SET_PEAK(inoutPeakInfo.allocationCount, currInfo.allocationCount);
+    SET_PEAK(inoutPeakInfo.unusedRangeCount, currInfo.unusedRangeCount);
+    SET_PEAK(inoutPeakInfo.usedBytes, currInfo.usedBytes);
+    SET_PEAK(inoutPeakInfo.unusedBytes, currInfo.unusedBytes);
+    SET_PEAK(inoutPeakInfo.totalBytes, currInfo.usedBytes + currInfo.unusedBytes);
+
+#undef SET_PEAK
+}
+
+void Statistics::PrintMemStatInfo(const MemStatInfo& info)
+{
+    printf("        Peak blocks %u, allocations %u, unused ranges %u\n",
+        info.blockCount,
+        info.allocationCount,
+        info.unusedRangeCount);
+    printf("        Peak total bytes %llu, used bytes %llu, unused bytes %llu\n",
+        info.totalBytes,
+        info.usedBytes,
+        info.unusedBytes);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// class ConfigurationParser
+
+class ConfigurationParser
+{
+public:
+    ConfigurationParser();
+    
+    bool Parse(LineSplit& lineSplit);
+
+    void Compare(
+        const VkPhysicalDeviceProperties& currDevProps,
+        const VkPhysicalDeviceMemoryProperties& currMemProps,
+        uint32_t vulkanApiVersion,
+        bool currMemoryBudgetEnabled);
+
+private:
+    enum class OPTION
+    {
+        VulkanApiVersion,
+        PhysicalDevice_apiVersion,
+        PhysicalDevice_driverVersion,
+        PhysicalDevice_vendorID,
+        PhysicalDevice_deviceID,
+        PhysicalDevice_deviceType,
+        PhysicalDevice_deviceName,
+        PhysicalDeviceLimits_maxMemoryAllocationCount,
+        PhysicalDeviceLimits_bufferImageGranularity,
+        PhysicalDeviceLimits_nonCoherentAtomSize,
+        Extension_VK_KHR_dedicated_allocation,
+        Extension_VK_KHR_bind_memory2,
+        Extension_VK_EXT_memory_budget,
+        Extension_VK_AMD_device_coherent_memory,
+        Macro_VMA_DEBUG_ALWAYS_DEDICATED_MEMORY,
+        Macro_VMA_DEBUG_ALIGNMENT,
+        Macro_VMA_DEBUG_MARGIN,
+        Macro_VMA_DEBUG_INITIALIZE_ALLOCATIONS,
+        Macro_VMA_DEBUG_DETECT_CORRUPTION,
+        Macro_VMA_DEBUG_GLOBAL_MUTEX,
+        Macro_VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY,
+        Macro_VMA_SMALL_HEAP_MAX_SIZE,
+        Macro_VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE,
+        Count
+    };
+
+    std::vector<bool> m_OptionSet;
+    std::vector<std::string> m_OptionValue;
+    VkPhysicalDeviceMemoryProperties m_MemProps;
+
+    bool m_WarningHeaderPrinted = false;
+
+    void SetOption(
+        size_t lineNumber,
+        OPTION option,
+        const StrRange& str);
+    void EnsureWarningHeader();
+    void CompareOption(VERBOSITY minVerbosity, const char* name,
+        OPTION option, uint32_t currValue);
+    void CompareOption(VERBOSITY minVerbosity, const char* name,
+        OPTION option, uint64_t currValue);
+    void CompareOption(VERBOSITY minVerbosity, const char* name,
+        OPTION option, bool currValue);
+    void CompareOption(VERBOSITY minVerbosity, const char* name,
+        OPTION option, const char* currValue);
+    void CompareMemProps(
+        const VkPhysicalDeviceMemoryProperties& currMemProps);
+};
+
+ConfigurationParser::ConfigurationParser() :
+    m_OptionSet((size_t)OPTION::Count),
+    m_OptionValue((size_t)OPTION::Count)
+{
+    ZeroMemory(&m_MemProps, sizeof(m_MemProps));
+}
+
+bool ConfigurationParser::Parse(LineSplit& lineSplit)
+{
+    for(auto& it : m_OptionSet)
+    {
+        it = false;
+    }
+    for(auto& it : m_OptionValue)
+    {
+        it.clear();
+    }
+
+    StrRange line;
+
+    if(!lineSplit.GetNextLine(line) && !StrRangeEq(line, "Config,Begin"))
+    {
+        return false;
+    }
+
+    CsvSplit csvSplit;
+    while(lineSplit.GetNextLine(line))
+    {
+        if(StrRangeEq(line, "Config,End"))
+        {
+            break;
+        }
+
+        const size_t currLineNumber = lineSplit.GetNextLineIndex();
+
+        csvSplit.Set(line);
+        if(csvSplit.GetCount() == 0)
+        {
+            return false;
+        }
+
+        const StrRange optionName = csvSplit.GetRange(0);
+        if(StrRangeEq(optionName, "VulkanApiVersion"))
+        {
+            SetOption(currLineNumber, OPTION::VulkanApiVersion, StrRange{csvSplit.GetRange(1).beg, csvSplit.GetRange(2).end});
+        }
+        else if(StrRangeEq(optionName, "PhysicalDevice"))
+        {
+            if(csvSplit.GetCount() >= 3)
+            {
+                const StrRange subOptionName = csvSplit.GetRange(1);
+                if(StrRangeEq(subOptionName, "apiVersion"))
+                    SetOption(currLineNumber, OPTION::PhysicalDevice_apiVersion, csvSplit.GetRange(2));
+                else if(StrRangeEq(subOptionName, "driverVersion"))
+                    SetOption(currLineNumber, OPTION::PhysicalDevice_driverVersion, csvSplit.GetRange(2));
+                else if(StrRangeEq(subOptionName, "vendorID"))
+                    SetOption(currLineNumber, OPTION::PhysicalDevice_vendorID, csvSplit.GetRange(2));
+                else if(StrRangeEq(subOptionName, "deviceID"))
+                    SetOption(currLineNumber, OPTION::PhysicalDevice_deviceID, csvSplit.GetRange(2));
+                else if(StrRangeEq(subOptionName, "deviceType"))
+                    SetOption(currLineNumber, OPTION::PhysicalDevice_deviceType, csvSplit.GetRange(2));
+                else if(StrRangeEq(subOptionName, "deviceName"))
+                    SetOption(currLineNumber, OPTION::PhysicalDevice_deviceName, StrRange(csvSplit.GetRange(2).beg, line.end));
+                else
+                    printf("Line %zu: Unrecognized configuration option.\n", currLineNumber);
+            }
+            else
+                printf("Line %zu: Too few columns.\n", currLineNumber);
+        }
+        else if(StrRangeEq(optionName, "PhysicalDeviceLimits"))
+        {
+            if(csvSplit.GetCount() >= 3)
+            {
+                const StrRange subOptionName = csvSplit.GetRange(1);
+                if(StrRangeEq(subOptionName, "maxMemoryAllocationCount"))
+                    SetOption(currLineNumber, OPTION::PhysicalDeviceLimits_maxMemoryAllocationCount, csvSplit.GetRange(2));
+                else if(StrRangeEq(subOptionName, "bufferImageGranularity"))
+                    SetOption(currLineNumber, OPTION::PhysicalDeviceLimits_bufferImageGranularity, csvSplit.GetRange(2));
+                else if(StrRangeEq(subOptionName, "nonCoherentAtomSize"))
+                    SetOption(currLineNumber, OPTION::PhysicalDeviceLimits_nonCoherentAtomSize, csvSplit.GetRange(2));
+                else
+                    printf("Line %zu: Unrecognized configuration option.\n", currLineNumber);
+            }
+            else
+                printf("Line %zu: Too few columns.\n", currLineNumber);
+        }
+        else if(StrRangeEq(optionName, "Extension"))
+        {
+            if(csvSplit.GetCount() >= 3)
+            {
+                const StrRange subOptionName = csvSplit.GetRange(1);
+                if(StrRangeEq(subOptionName, "VK_KHR_dedicated_allocation"))
+                {
+                    // Ignore because this extension is promoted to Vulkan 1.1.
+                }
+                else if(StrRangeEq(subOptionName, "VK_KHR_bind_memory2"))
+                    SetOption(currLineNumber, OPTION::Extension_VK_KHR_bind_memory2, csvSplit.GetRange(2));
+                else if(StrRangeEq(subOptionName, "VK_EXT_memory_budget"))
+                    SetOption(currLineNumber, OPTION::Extension_VK_EXT_memory_budget, csvSplit.GetRange(2));
+                else if(StrRangeEq(subOptionName, "VK_AMD_device_coherent_memory"))
+                    SetOption(currLineNumber, OPTION::Extension_VK_AMD_device_coherent_memory, csvSplit.GetRange(2));
+                else
+                    printf("Line %zu: Unrecognized configuration option.\n", currLineNumber);
+            }
+            else
+                printf("Line %zu: Too few columns.\n", currLineNumber);
+        }
+        else if(StrRangeEq(optionName, "Macro"))
+        {
+            if(csvSplit.GetCount() >= 3)
+            {
+                const StrRange subOptionName = csvSplit.GetRange(1);
+                if(StrRangeEq(subOptionName, "VMA_DEBUG_ALWAYS_DEDICATED_MEMORY"))
+                    SetOption(currLineNumber, OPTION::Macro_VMA_DEBUG_ALWAYS_DEDICATED_MEMORY, csvSplit.GetRange(2));
+                else if(StrRangeEq(subOptionName, "VMA_DEBUG_ALIGNMENT"))
+                    SetOption(currLineNumber, OPTION::Macro_VMA_DEBUG_ALIGNMENT, csvSplit.GetRange(2));
+                else if(StrRangeEq(subOptionName, "VMA_DEBUG_MARGIN"))
+                    SetOption(currLineNumber, OPTION::Macro_VMA_DEBUG_MARGIN, csvSplit.GetRange(2));
+                else if(StrRangeEq(subOptionName, "VMA_DEBUG_INITIALIZE_ALLOCATIONS"))
+                    SetOption(currLineNumber, OPTION::Macro_VMA_DEBUG_INITIALIZE_ALLOCATIONS, csvSplit.GetRange(2));
+                else if(StrRangeEq(subOptionName, "VMA_DEBUG_DETECT_CORRUPTION"))
+                    SetOption(currLineNumber, OPTION::Macro_VMA_DEBUG_DETECT_CORRUPTION, csvSplit.GetRange(2));
+                else if(StrRangeEq(subOptionName, "VMA_DEBUG_GLOBAL_MUTEX"))
+                    SetOption(currLineNumber, OPTION::Macro_VMA_DEBUG_GLOBAL_MUTEX, csvSplit.GetRange(2));
+                else if(StrRangeEq(subOptionName, "VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY"))
+                    SetOption(currLineNumber, OPTION::Macro_VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY, csvSplit.GetRange(2));
+                else if(StrRangeEq(subOptionName, "VMA_SMALL_HEAP_MAX_SIZE"))
+                    SetOption(currLineNumber, OPTION::Macro_VMA_SMALL_HEAP_MAX_SIZE, csvSplit.GetRange(2));
+                else if(StrRangeEq(subOptionName, "VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE"))
+                    SetOption(currLineNumber, OPTION::Macro_VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE, csvSplit.GetRange(2));
+                else
+                    printf("Line %zu: Unrecognized configuration option.\n", currLineNumber);
+            }
+            else
+                printf("Line %zu: Too few columns.\n", currLineNumber);
+        }
+        else if(StrRangeEq(optionName, "PhysicalDeviceMemory"))
+        {
+            uint32_t value = 0;
+            if(csvSplit.GetCount() == 3 && StrRangeEq(csvSplit.GetRange(1), "HeapCount") &&
+                StrRangeToUint(csvSplit.GetRange(2), value))
+            {
+                m_MemProps.memoryHeapCount = value;
+            }
+            else if(csvSplit.GetCount() == 3 && StrRangeEq(csvSplit.GetRange(1), "TypeCount") &&
+                StrRangeToUint(csvSplit.GetRange(2), value))
+            {
+                m_MemProps.memoryTypeCount = value;
+            }
+            else if(csvSplit.GetCount() == 5 && StrRangeEq(csvSplit.GetRange(1), "Heap") &&
+                StrRangeToUint(csvSplit.GetRange(2), value) &&
+                value < m_MemProps.memoryHeapCount)
+            {
+                if(StrRangeEq(csvSplit.GetRange(3), "size") &&
+                    StrRangeToUint(csvSplit.GetRange(4), m_MemProps.memoryHeaps[value].size))
+                {
+                     // Parsed.
+                }
+                else if(StrRangeEq(csvSplit.GetRange(3), "flags") &&
+                    StrRangeToUint(csvSplit.GetRange(4), m_MemProps.memoryHeaps[value].flags))
+                {
+                     // Parsed.
+                }
+                else
+                    printf("Line %zu: Invalid configuration option.\n", currLineNumber);
+            }
+            else if(csvSplit.GetCount() == 5 && StrRangeEq(csvSplit.GetRange(1), "Type") &&
+                StrRangeToUint(csvSplit.GetRange(2), value) &&
+                value < m_MemProps.memoryTypeCount)
+            {
+                if(StrRangeEq(csvSplit.GetRange(3), "heapIndex") &&
+                    StrRangeToUint(csvSplit.GetRange(4), m_MemProps.memoryTypes[value].heapIndex))
+                {
+                     // Parsed.
+                }
+                else if(StrRangeEq(csvSplit.GetRange(3), "propertyFlags") &&
+                    StrRangeToUint(csvSplit.GetRange(4), m_MemProps.memoryTypes[value].propertyFlags))
+                {
+                     // Parsed.
+                }
+                else
+                    printf("Line %zu: Invalid configuration option.\n", currLineNumber);
+            }
+            else
+                printf("Line %zu: Invalid configuration option.\n", currLineNumber);
+        }
+        else
+            printf("Line %zu: Unrecognized configuration option.\n", currLineNumber);
+    }
+
+    return true;
+}
+
+void ConfigurationParser::Compare(
+    const VkPhysicalDeviceProperties& currDevProps,
+    const VkPhysicalDeviceMemoryProperties& currMemProps,
+    uint32_t vulkanApiVersion,
+    bool currMemoryBudgetEnabled)
+{
+    char vulkanApiVersionStr[32];
+    sprintf_s(vulkanApiVersionStr, "%u,%u", VK_VERSION_MAJOR(vulkanApiVersion), VK_VERSION_MINOR(vulkanApiVersion));
+    CompareOption(VERBOSITY::DEFAULT, "VulkanApiVersion",
+        OPTION::VulkanApiVersion, vulkanApiVersionStr);
+
+    CompareOption(VERBOSITY::MAXIMUM, "PhysicalDevice apiVersion",
+        OPTION::PhysicalDevice_apiVersion, currDevProps.apiVersion);
+    CompareOption(VERBOSITY::MAXIMUM, "PhysicalDevice driverVersion",
+        OPTION::PhysicalDevice_driverVersion, currDevProps.driverVersion);
+    CompareOption(VERBOSITY::MAXIMUM, "PhysicalDevice vendorID",
+        OPTION::PhysicalDevice_vendorID, currDevProps.vendorID);
+    CompareOption(VERBOSITY::MAXIMUM, "PhysicalDevice deviceID",
+        OPTION::PhysicalDevice_deviceID, currDevProps.deviceID);
+    CompareOption(VERBOSITY::MAXIMUM, "PhysicalDevice deviceType",
+        OPTION::PhysicalDevice_deviceType, (uint32_t)currDevProps.deviceType);
+    CompareOption(VERBOSITY::MAXIMUM, "PhysicalDevice deviceName",
+        OPTION::PhysicalDevice_deviceName, currDevProps.deviceName);
+
+    CompareOption(VERBOSITY::DEFAULT, "PhysicalDeviceLimits maxMemoryAllocationCount",
+        OPTION::PhysicalDeviceLimits_maxMemoryAllocationCount, currDevProps.limits.maxMemoryAllocationCount);
+    CompareOption(VERBOSITY::DEFAULT, "PhysicalDeviceLimits bufferImageGranularity",
+        OPTION::PhysicalDeviceLimits_bufferImageGranularity, currDevProps.limits.bufferImageGranularity);
+    CompareOption(VERBOSITY::DEFAULT, "PhysicalDeviceLimits nonCoherentAtomSize",
+        OPTION::PhysicalDeviceLimits_nonCoherentAtomSize, currDevProps.limits.nonCoherentAtomSize);
+
+    CompareMemProps(currMemProps);
+}
+
+void ConfigurationParser::SetOption(
+    size_t lineNumber,
+    OPTION option,
+    const StrRange& str)
+{
+    if(m_OptionSet[(size_t)option])
+    {
+        printf("Line %zu: Option already specified.\n" ,lineNumber);
+    }
+
+    m_OptionSet[(size_t)option] = true;
+
+    std::string val;
+    str.to_str(val);
+    m_OptionValue[(size_t)option] = std::move(val);
+}
+
+void ConfigurationParser::EnsureWarningHeader()
+{
+    if(!m_WarningHeaderPrinted)
+    {
+        printf("WARNING: Following configuration parameters don't match:\n");
+        m_WarningHeaderPrinted = true;
+    }
+}
+
+void ConfigurationParser::CompareOption(VERBOSITY minVerbosity, const char* name,
+    OPTION option, uint32_t currValue)
+{
+    if(m_OptionSet[(size_t)option] &&
+        g_Verbosity >= minVerbosity)
+    {
+        uint32_t origValue;
+        if(StrRangeToUint(StrRange(m_OptionValue[(size_t)option]), origValue))
+        {
+            if(origValue != currValue)
+            {
+                EnsureWarningHeader();
+                printf("    %s: original %u, current %u\n", name, origValue, currValue);
+            }
+        }
+    }
+}
+
+void ConfigurationParser::CompareOption(VERBOSITY minVerbosity, const char* name,
+    OPTION option, uint64_t currValue)
+{
+    if(m_OptionSet[(size_t)option] &&
+        g_Verbosity >= minVerbosity)
+    {
+        uint64_t origValue;
+        if(StrRangeToUint(StrRange(m_OptionValue[(size_t)option]), origValue))
+        {
+            if(origValue != currValue)
+            {
+                EnsureWarningHeader();
+                printf("    %s: original %llu, current %llu\n", name, origValue, currValue);
+            }
+        }
+    }
+}
+
+void ConfigurationParser::CompareOption(VERBOSITY minVerbosity, const char* name,
+    OPTION option, bool currValue)
+{
+    if(m_OptionSet[(size_t)option] &&
+        g_Verbosity >= minVerbosity)
+    {
+        bool origValue;
+        if(StrRangeToBool(StrRange(m_OptionValue[(size_t)option]), origValue))
+        {
+            if(origValue != currValue)
+            {
+                EnsureWarningHeader();
+                printf("    %s: original %u, current %u\n", name,
+                    origValue ? 1 : 0,
+                    currValue ? 1 : 0);
+            }
+        }
+    }
+}
+
+void ConfigurationParser::CompareOption(VERBOSITY minVerbosity, const char* name,
+    OPTION option, const char* currValue)
+{
+    if(m_OptionSet[(size_t)option] &&
+        g_Verbosity >= minVerbosity)
+    {
+        const std::string& origValue = m_OptionValue[(size_t)option];
+        if(origValue != currValue)
+        {
+            EnsureWarningHeader();
+            printf("    %s: original \"%s\", current \"%s\"\n", name, origValue.c_str(), currValue);
+        }
+    }
+}
+
+void ConfigurationParser::CompareMemProps(
+    const VkPhysicalDeviceMemoryProperties& currMemProps)
+{
+    if(g_Verbosity < VERBOSITY::DEFAULT)
+    {
+        return;
+    }
+
+    bool memoryMatch =
+        currMemProps.memoryHeapCount == m_MemProps.memoryHeapCount &&
+        currMemProps.memoryTypeCount == m_MemProps.memoryTypeCount;
+
+    for(uint32_t i = 0; memoryMatch && i < currMemProps.memoryHeapCount; ++i)
+    {
+        memoryMatch =
+            currMemProps.memoryHeaps[i].flags == m_MemProps.memoryHeaps[i].flags;
+    }
+    for(uint32_t i = 0; memoryMatch && i < currMemProps.memoryTypeCount; ++i)
+    {
+        memoryMatch =
+            currMemProps.memoryTypes[i].heapIndex == m_MemProps.memoryTypes[i].heapIndex &&
+            currMemProps.memoryTypes[i].propertyFlags == m_MemProps.memoryTypes[i].propertyFlags;
+    }
+
+    if(memoryMatch && g_Verbosity == VERBOSITY::MAXIMUM)
+    {
+        bool memorySizeMatch = true;
+        for(uint32_t i = 0; memorySizeMatch && i < currMemProps.memoryHeapCount; ++i)
+        {
+            memorySizeMatch =
+                currMemProps.memoryHeaps[i].size == m_MemProps.memoryHeaps[i].size;
+        }
+
+        if(!memorySizeMatch)
+        {
+            printf("WARNING: Sizes of original memory heaps are different from current ones.\n");
+        }
+    }
+    else
+    {
+        printf("WARNING: Layout of original memory heaps and types is different from current one.\n");
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// class Player
+
+static const char* const VALIDATION_LAYER_NAME = "VK_LAYER_LUNARG_standard_validation";
+
+static const bool g_MemoryAliasingWarningEnabled = false;
+
+static VKAPI_ATTR VkBool32 VKAPI_CALL MyDebugReportCallback(
+    VkDebugReportFlagsEXT flags,
+    VkDebugReportObjectTypeEXT objectType,
+    uint64_t object,
+    size_t location,
+    int32_t messageCode,
+    const char* pLayerPrefix,
+    const char* pMessage,
+    void* pUserData)
+{
+    // "Non-linear image 0xebc91 is aliased with linear buffer 0xeb8e4 which may indicate a bug."
+    if(!g_MemoryAliasingWarningEnabled && flags == VK_DEBUG_REPORT_WARNING_BIT_EXT &&
+        (strstr(pMessage, " is aliased with non-linear ") || strstr(pMessage, " is aliased with linear ")))
+    {
+        return VK_FALSE;
+    }
+
+    // Ignoring because when VK_KHR_dedicated_allocation extension is enabled,
+    // vkGetBufferMemoryRequirements2KHR function is used instead, while Validation
+    // Layer seems to be unaware of it.
+    if (strstr(pMessage, "but vkGetBufferMemoryRequirements() has not been called on that buffer") != nullptr)
+    {
+        return VK_FALSE;
+    }
+    if (strstr(pMessage, "but vkGetImageMemoryRequirements() has not been called on that image") != nullptr)
+    {
+        return VK_FALSE;
+    }
+    
+    /*
+    "Mapping an image with layout VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL can result in undefined behavior if this memory is used by the device. Only GENERAL or PREINITIALIZED should be used."
+    Ignoring because we map entire VkDeviceMemory blocks, where different types of
+    images and buffers may end up together, especially on GPUs with unified memory
+    like Intel.
+    */
+    if(strstr(pMessage, "Mapping an image with layout") != nullptr &&
+        strstr(pMessage, "can result in undefined behavior if this memory is used by the device") != nullptr)
+    {
+        return VK_FALSE;
+    }
+
+    printf("%s \xBA %s\n", pLayerPrefix, pMessage);
+
+    return VK_FALSE;
+}
+
+static bool IsLayerSupported(const VkLayerProperties* pProps, size_t propCount, const char* pLayerName)
+{
+    const VkLayerProperties* propsEnd = pProps + propCount;
+    return std::find_if(
+        pProps,
+        propsEnd,
+        [pLayerName](const VkLayerProperties& prop) -> bool {
+            return strcmp(pLayerName, prop.layerName) == 0;
+        }) != propsEnd;
+}
+
+static const size_t FIRST_PARAM_INDEX = 4;
+
+static void InitVulkanFeatures(
+    VkPhysicalDeviceFeatures& outFeatures,
+    const VkPhysicalDeviceFeatures& supportedFeatures)
+{
+    ZeroMemory(&outFeatures, sizeof(outFeatures));
+
+    // Enable something what may interact with memory/buffer/image support.
+
+    outFeatures.fullDrawIndexUint32 = supportedFeatures.fullDrawIndexUint32;
+    outFeatures.imageCubeArray = supportedFeatures.imageCubeArray;
+    outFeatures.geometryShader = supportedFeatures.geometryShader;
+    outFeatures.tessellationShader = supportedFeatures.tessellationShader;
+    outFeatures.multiDrawIndirect = supportedFeatures.multiDrawIndirect;
+    outFeatures.textureCompressionETC2 = supportedFeatures.textureCompressionETC2;
+    outFeatures.textureCompressionASTC_LDR = supportedFeatures.textureCompressionASTC_LDR;
+    outFeatures.textureCompressionBC = supportedFeatures.textureCompressionBC;
+}
+
+class Player
+{
+public:
+    Player();
+    int Init();
+    ~Player();
+
+    void ApplyConfig(ConfigurationParser& configParser);
+    void ExecuteLine(size_t lineNumber, const StrRange& line);
+    void DumpStats(const char* fileNameFormat, size_t lineNumber, bool detailed);
+    void Defragment();
+
+    void PrintStats();
+
+private:
+    static const size_t MAX_WARNINGS_TO_SHOW = 64;
+
+    size_t m_WarningCount = 0;
+    bool m_AllocateForBufferImageWarningIssued = false;
+
+    VkInstance m_VulkanInstance = VK_NULL_HANDLE;
+    VkPhysicalDevice m_PhysicalDevice = VK_NULL_HANDLE;
+    uint32_t m_GraphicsQueueFamilyIndex = UINT32_MAX;
+    uint32_t m_TransferQueueFamilyIndex = UINT32_MAX;
+    VkDevice m_Device = VK_NULL_HANDLE;
+    VkQueue m_GraphicsQueue = VK_NULL_HANDLE;
+    VkQueue m_TransferQueue = VK_NULL_HANDLE;
+    VmaAllocator m_Allocator = VK_NULL_HANDLE;
+    VkCommandPool m_CommandPool = VK_NULL_HANDLE;
+    VkCommandBuffer m_CommandBuffer = VK_NULL_HANDLE;
+    bool m_MemoryBudgetEnabled = false;
+    const VkPhysicalDeviceProperties* m_DevProps = nullptr;
+    const VkPhysicalDeviceMemoryProperties* m_MemProps = nullptr;
+
+    PFN_vkCreateDebugReportCallbackEXT m_pvkCreateDebugReportCallbackEXT;
+    PFN_vkDebugReportMessageEXT m_pvkDebugReportMessageEXT;
+    PFN_vkDestroyDebugReportCallbackEXT m_pvkDestroyDebugReportCallbackEXT;
+    VkDebugReportCallbackEXT m_hCallback;
+
+    uint32_t m_VmaFrameIndex = 0;
+
+    // Any of these handles null can mean it was created in original but couldn't be created now.
+    struct Pool
+    {
+        VmaPool pool;
+    };
+    struct Allocation
+    {
+        uint32_t allocationFlags = 0;
+        VmaAllocation allocation = VK_NULL_HANDLE;
+        VkBuffer buffer = VK_NULL_HANDLE;
+        VkImage image = VK_NULL_HANDLE;
+    };
+    std::unordered_map<uint64_t, Pool> m_Pools;
+    std::unordered_map<uint64_t, Allocation> m_Allocations;
+    std::unordered_map<uint64_t, VmaDefragmentationContext> m_DefragmentationContexts;
+
+    struct Thread
+    {
+        uint32_t callCount;
+    };
+    std::unordered_map<uint32_t, Thread> m_Threads;
+
+    // Copy of column [1] from previously parsed line.
+    std::string m_LastLineTimeStr;
+    Statistics m_Stats;
+
+    std::vector<char> m_UserDataTmpStr;
+
+    void Destroy(const Allocation& alloc);
+
+    // Finds VmaPool bu original pointer.
+    // If origPool = null, returns true and outPool = null.
+    // If failed, prints warning, returns false and outPool = null.
+    bool FindPool(size_t lineNumber, uint64_t origPool, VmaPool& outPool);
+    // If allocation with that origPtr already exists, prints warning and replaces it.
+    void AddAllocation(size_t lineNumber, uint64_t origPtr, VkResult res, const char* functionName, Allocation&& allocDesc);
+
+    // Increments warning counter. Returns true if warning message should be printed.
+    bool IssueWarning();
+
+    int InitVulkan();
+    void FinalizeVulkan();
+    void RegisterDebugCallbacks();
+
+    // If parmeter count doesn't match, issues warning and returns false.
+    bool ValidateFunctionParameterCount(size_t lineNumber, const CsvSplit& csvSplit, size_t expectedParamCount, bool lastUnbound);
+
+    // If failed, prints warning, returns false, and sets allocCreateInfo.pUserData to null.
+    bool PrepareUserData(size_t lineNumber, uint32_t allocCreateFlags, const StrRange& userDataColumn, const StrRange& wholeLine, void*& outUserData);
+
+    void UpdateMemStats();
+
+    void ExecuteCreatePool(size_t lineNumber, const CsvSplit& csvSplit);
+    void ExecuteDestroyPool(size_t lineNumber, const CsvSplit& csvSplit);
+    void ExecuteSetAllocationUserData(size_t lineNumber, const CsvSplit& csvSplit);
+    void ExecuteCreateBuffer(size_t lineNumber, const CsvSplit& csvSplit);
+    void ExecuteDestroyBuffer(size_t lineNumber, const CsvSplit& csvSplit) { m_Stats.RegisterFunctionCall(VMA_FUNCTION::DestroyBuffer); DestroyAllocation(lineNumber, csvSplit, "vmaDestroyBuffer"); }
+    void ExecuteCreateImage(size_t lineNumber, const CsvSplit& csvSplit);
+    void ExecuteDestroyImage(size_t lineNumber, const CsvSplit& csvSplit) { m_Stats.RegisterFunctionCall(VMA_FUNCTION::DestroyImage); DestroyAllocation(lineNumber, csvSplit, "vmaDestroyImage"); }
+    void ExecuteFreeMemory(size_t lineNumber, const CsvSplit& csvSplit) { m_Stats.RegisterFunctionCall(VMA_FUNCTION::FreeMemory); DestroyAllocation(lineNumber, csvSplit, "vmaFreeMemory"); }
+    void ExecuteFreeMemoryPages(size_t lineNumber, const CsvSplit& csvSplit);
+    void ExecuteCreateLostAllocation(size_t lineNumber, const CsvSplit& csvSplit);
+    void ExecuteAllocateMemory(size_t lineNumber, const CsvSplit& csvSplit);
+    void ExecuteAllocateMemoryPages(size_t lineNumber, const CsvSplit& csvSplit);
+    void ExecuteAllocateMemoryForBufferOrImage(size_t lineNumber, const CsvSplit& csvSplit, OBJECT_TYPE objType);
+    void ExecuteMapMemory(size_t lineNumber, const CsvSplit& csvSplit);
+    void ExecuteUnmapMemory(size_t lineNumber, const CsvSplit& csvSplit);
+    void ExecuteFlushAllocation(size_t lineNumber, const CsvSplit& csvSplit);
+    void ExecuteInvalidateAllocation(size_t lineNumber, const CsvSplit& csvSplit);
+    void ExecuteTouchAllocation(size_t lineNumber, const CsvSplit& csvSplit);
+    void ExecuteGetAllocationInfo(size_t lineNumber, const CsvSplit& csvSplit);
+    void ExecuteMakePoolAllocationsLost(size_t lineNumber, const CsvSplit& csvSplit);
+    void ExecuteResizeAllocation(size_t lineNumber, const CsvSplit& csvSplit);
+    void ExecuteDefragmentationBegin(size_t lineNumber, const CsvSplit& csvSplit);
+    void ExecuteDefragmentationEnd(size_t lineNumber, const CsvSplit& csvSplit);
+    void ExecuteSetPoolName(size_t lineNumber, const CsvSplit& csvSplit);
+
+    void DestroyAllocation(size_t lineNumber, const CsvSplit& csvSplit, const char* functionName);
+
+    void PrintStats(const VmaStats& stats, const char* suffix);
+    void PrintStatInfo(const VmaStatInfo& info);
+};
+
+Player::Player()
+{
+}
+
+int Player::Init()
+{
+    int result = InitVulkan();
+    
+    if(result == 0)
+    {
+        m_Stats.Init(m_MemProps->memoryHeapCount, m_MemProps->memoryTypeCount);
+        UpdateMemStats();
+    }
+    
+    return result;
+}
+
+Player::~Player()
+{
+    FinalizeVulkan();
+
+    if(g_Verbosity < VERBOSITY::MAXIMUM && m_WarningCount > MAX_WARNINGS_TO_SHOW)
+        printf("WARNING: %zu more warnings not shown.\n", m_WarningCount - MAX_WARNINGS_TO_SHOW);
+}
+
+void Player::ApplyConfig(ConfigurationParser& configParser)
+{
+    configParser.Compare(*m_DevProps, *m_MemProps,
+        VULKAN_API_VERSION,
+        m_MemoryBudgetEnabled);
+}
+
+void Player::ExecuteLine(size_t lineNumber, const StrRange& line)
+{
+    CsvSplit csvSplit;
+    csvSplit.Set(line);
+
+    if(csvSplit.GetCount() >= FIRST_PARAM_INDEX)
+    {
+        // Check thread ID.
+        uint32_t threadId;
+        if(StrRangeToUint(csvSplit.GetRange(0), threadId))
+        {
+            const auto it = m_Threads.find(threadId);
+            if(it != m_Threads.end())
+            {
+                ++it->second.callCount;
+            }
+            else
+            {
+                Thread threadInfo{};
+                threadInfo.callCount = 1;
+                m_Threads[threadId] = threadInfo;
+            }
+        }
+        else
+        {
+            if(IssueWarning())
+            {
+                printf("Line %zu: Incorrect thread ID.\n", lineNumber);
+            }
+        }
+
+        // Save time.
+        csvSplit.GetRange(1).to_str(m_LastLineTimeStr);
+
+        // Update VMA current frame index.
+        StrRange frameIndexStr = csvSplit.GetRange(2);
+        uint32_t frameIndex;
+        if(StrRangeToUint(frameIndexStr, frameIndex))
+        {
+            if(frameIndex != m_VmaFrameIndex)
+            {
+                vmaSetCurrentFrameIndex(m_Allocator, frameIndex);
+                m_VmaFrameIndex = frameIndex;
+            }
+        }
+        else
+        {
+            if(IssueWarning())
+            {
+                printf("Line %zu: Incorrect frame index.\n", lineNumber);
+            }
+        }
+
+        StrRange functionName = csvSplit.GetRange(3);
+
+        if(StrRangeEq(functionName, "vmaCreateAllocator"))
+        {
+            if(ValidateFunctionParameterCount(lineNumber, csvSplit, 0, false))
+            {
+                // Nothing.
+            }
+        }
+        else if(StrRangeEq(functionName, "vmaDestroyAllocator"))
+        {
+            if(ValidateFunctionParameterCount(lineNumber, csvSplit, 0, false))
+            {
+                // Nothing.
+            }
+        }
+        else if(StrRangeEq(functionName, VMA_FUNCTION_NAMES[(uint32_t)VMA_FUNCTION::CreatePool]))
+            ExecuteCreatePool(lineNumber, csvSplit);
+        else if(StrRangeEq(functionName, VMA_FUNCTION_NAMES[(uint32_t)VMA_FUNCTION::DestroyPool]))
+            ExecuteDestroyPool(lineNumber, csvSplit);
+        else if(StrRangeEq(functionName, VMA_FUNCTION_NAMES[(uint32_t)VMA_FUNCTION::SetAllocationUserData]))
+            ExecuteSetAllocationUserData(lineNumber, csvSplit);
+        else if(StrRangeEq(functionName, VMA_FUNCTION_NAMES[(uint32_t)VMA_FUNCTION::CreateBuffer]))
+            ExecuteCreateBuffer(lineNumber, csvSplit);
+        else if(StrRangeEq(functionName, VMA_FUNCTION_NAMES[(uint32_t)VMA_FUNCTION::DestroyBuffer]))
+            ExecuteDestroyBuffer(lineNumber, csvSplit);
+        else if(StrRangeEq(functionName, VMA_FUNCTION_NAMES[(uint32_t)VMA_FUNCTION::CreateImage]))
+            ExecuteCreateImage(lineNumber, csvSplit);
+        else if(StrRangeEq(functionName, VMA_FUNCTION_NAMES[(uint32_t)VMA_FUNCTION::DestroyImage]))
+            ExecuteDestroyImage(lineNumber, csvSplit);
+        else if(StrRangeEq(functionName, VMA_FUNCTION_NAMES[(uint32_t)VMA_FUNCTION::FreeMemory]))
+            ExecuteFreeMemory(lineNumber, csvSplit);
+        else if(StrRangeEq(functionName, VMA_FUNCTION_NAMES[(uint32_t)VMA_FUNCTION::FreeMemoryPages]))
+            ExecuteFreeMemoryPages(lineNumber, csvSplit);
+        else if(StrRangeEq(functionName, VMA_FUNCTION_NAMES[(uint32_t)VMA_FUNCTION::CreateLostAllocation]))
+            ExecuteCreateLostAllocation(lineNumber, csvSplit);
+        else if(StrRangeEq(functionName, VMA_FUNCTION_NAMES[(uint32_t)VMA_FUNCTION::AllocateMemory]))
+            ExecuteAllocateMemory(lineNumber, csvSplit);
+        else if(StrRangeEq(functionName, VMA_FUNCTION_NAMES[(uint32_t)VMA_FUNCTION::AllocateMemoryPages]))
+            ExecuteAllocateMemoryPages(lineNumber, csvSplit);
+        else if(StrRangeEq(functionName, VMA_FUNCTION_NAMES[(uint32_t)VMA_FUNCTION::AllocateMemoryForBuffer]))
+            ExecuteAllocateMemoryForBufferOrImage(lineNumber, csvSplit, OBJECT_TYPE::BUFFER);
+        else if(StrRangeEq(functionName, VMA_FUNCTION_NAMES[(uint32_t)VMA_FUNCTION::AllocateMemoryForImage]))
+            ExecuteAllocateMemoryForBufferOrImage(lineNumber, csvSplit, OBJECT_TYPE::IMAGE);
+        else if(StrRangeEq(functionName, VMA_FUNCTION_NAMES[(uint32_t)VMA_FUNCTION::MapMemory]))
+            ExecuteMapMemory(lineNumber, csvSplit);
+        else if(StrRangeEq(functionName, VMA_FUNCTION_NAMES[(uint32_t)VMA_FUNCTION::UnmapMemory]))
+            ExecuteUnmapMemory(lineNumber, csvSplit);
+        else if(StrRangeEq(functionName, VMA_FUNCTION_NAMES[(uint32_t)VMA_FUNCTION::FlushAllocation]))
+            ExecuteFlushAllocation(lineNumber, csvSplit);
+        else if(StrRangeEq(functionName, VMA_FUNCTION_NAMES[(uint32_t)VMA_FUNCTION::InvalidateAllocation]))
+            ExecuteInvalidateAllocation(lineNumber, csvSplit);
+        else if(StrRangeEq(functionName, VMA_FUNCTION_NAMES[(uint32_t)VMA_FUNCTION::TouchAllocation]))
+            ExecuteTouchAllocation(lineNumber, csvSplit);
+        else if(StrRangeEq(functionName, VMA_FUNCTION_NAMES[(uint32_t)VMA_FUNCTION::GetAllocationInfo]))
+            ExecuteGetAllocationInfo(lineNumber, csvSplit);
+        else if(StrRangeEq(functionName, VMA_FUNCTION_NAMES[(uint32_t)VMA_FUNCTION::MakePoolAllocationsLost]))
+            ExecuteMakePoolAllocationsLost(lineNumber, csvSplit);
+        else if(StrRangeEq(functionName, VMA_FUNCTION_NAMES[(uint32_t)VMA_FUNCTION::ResizeAllocation]))
+            ExecuteResizeAllocation(lineNumber, csvSplit);
+        else if(StrRangeEq(functionName, VMA_FUNCTION_NAMES[(uint32_t)VMA_FUNCTION::DefragmentationBegin]))
+            ExecuteDefragmentationBegin(lineNumber, csvSplit);
+        else if(StrRangeEq(functionName, VMA_FUNCTION_NAMES[(uint32_t)VMA_FUNCTION::DefragmentationEnd]))
+            ExecuteDefragmentationEnd(lineNumber, csvSplit);
+        else if(StrRangeEq(functionName, VMA_FUNCTION_NAMES[(uint32_t)VMA_FUNCTION::SetPoolName]))
+            ExecuteSetPoolName(lineNumber, csvSplit);
+        else
+        {
+            if(IssueWarning())
+            {
+                printf("Line %zu: Unknown function.\n", lineNumber);
+            }
+        }
+    }
+    else
+    {
+        if(IssueWarning())
+        {
+            printf("Line %zu: Too few columns.\n", lineNumber);
+        }
+    }
+}
+
+void Player::DumpStats(const char* fileNameFormat, size_t lineNumber, bool detailed)
+{
+    char* pStatsString = nullptr;
+    vmaBuildStatsString(m_Allocator, &pStatsString, detailed ? VK_TRUE : VK_FALSE);
+
+    char fileName[MAX_PATH];
+    sprintf_s(fileName, fileNameFormat, lineNumber);
+
+    FILE* file = nullptr;
+    errno_t err = fopen_s(&file, fileName, "wb");
+    if(err == 0)
+    {
+        fwrite(pStatsString, 1, strlen(pStatsString), file);
+        fclose(file);
+    }
+    else
+    {
+        printf("ERROR: Failed to write file: %s\n", fileName);
+    }
+
+    vmaFreeStatsString(m_Allocator, pStatsString);
+}
+
+void Player::Destroy(const Allocation& alloc)
+{
+    if(alloc.buffer)
+    {
+        assert(alloc.image == VK_NULL_HANDLE);
+        vmaDestroyBuffer(m_Allocator, alloc.buffer, alloc.allocation);
+    }
+    else if(alloc.image)
+    {
+        vmaDestroyImage(m_Allocator, alloc.image, alloc.allocation);
+    }
+    else
+        vmaFreeMemory(m_Allocator, alloc.allocation);
+}
+
+bool Player::FindPool(size_t lineNumber, uint64_t origPool, VmaPool& outPool)
+{
+    outPool = VK_NULL_HANDLE;
+
+    if(origPool != 0)
+    {
+        const auto poolIt = m_Pools.find(origPool);
+        if(poolIt != m_Pools.end())
+        {
+            outPool = poolIt->second.pool;
+            return true;
+        }
+        else
+        {
+            if(IssueWarning())
+            {
+                printf("Line %zu: Pool %llX not found.\n", lineNumber, origPool);
+            }
+        }
+    }
+
+    return true;
+}
+
+void Player::AddAllocation(size_t lineNumber, uint64_t origPtr, VkResult res, const char* functionName, Allocation&& allocDesc)
+{
+    if(origPtr)
+    {
+        if(res == VK_SUCCESS)
+        {
+            // Originally succeeded, currently succeeded.
+            // Just save pointer (done below).
+        }
+        else
+        {
+            // Originally succeeded, currently failed.
+            // Print warning. Save null pointer.
+            if(IssueWarning())
+            {
+                printf("Line %zu: %s failed (%d), while originally succeeded.\n", lineNumber, functionName, res);
+            }
+        }
+
+        const auto existingIt = m_Allocations.find(origPtr);
+        if(existingIt != m_Allocations.end())
+        {
+            if(IssueWarning())
+            {
+                printf("Line %zu: Allocation %llX already exists.\n", lineNumber, origPtr);
+            }
+        }
+        m_Allocations[origPtr] = std::move(allocDesc);
+    }
+    else
+    {
+        if(res == VK_SUCCESS)
+        {
+            // Originally failed, currently succeeded.
+            // Print warning, destroy the object.
+            if(IssueWarning())
+            {
+                printf("Line %zu: %s succeeded, originally failed.\n", lineNumber, functionName);
+            }
+
+            Destroy(allocDesc);
+        }
+        else
+        {
+            // Originally failed, currently failed.
+            // Print warning.
+            if(IssueWarning())
+            {
+                printf("Line %zu: %s failed (%d), originally also failed.\n", lineNumber, functionName, res);
+            }
+        }
+    }
+}
+
+bool Player::IssueWarning()
+{
+    if(g_Verbosity < VERBOSITY::MAXIMUM)
+    {
+        return m_WarningCount++ < MAX_WARNINGS_TO_SHOW;
+    }
+    else
+    {
+        ++m_WarningCount;
+        return true;
+    }
+}
+
+int Player::InitVulkan()
+{
+    if(g_Verbosity == VERBOSITY::MAXIMUM)
+    {
+        printf("Initializing Vulkan...\n");
+    }
+
+    uint32_t instanceLayerPropCount = 0;
+    VkResult res = vkEnumerateInstanceLayerProperties(&instanceLayerPropCount, nullptr);
+    assert(res == VK_SUCCESS);
+
+    std::vector<VkLayerProperties> instanceLayerProps(instanceLayerPropCount);
+    if(instanceLayerPropCount > 0)
+    {
+        res = vkEnumerateInstanceLayerProperties(&instanceLayerPropCount, instanceLayerProps.data());
+        assert(res == VK_SUCCESS);
+    }
+
+    const bool validationLayersAvailable =
+        IsLayerSupported(instanceLayerProps.data(), instanceLayerProps.size(), VALIDATION_LAYER_NAME);
+
+    bool validationLayersEnabled = false;
+    switch(g_VK_LAYER_LUNARG_standard_validation)
+    {
+    case VULKAN_EXTENSION_REQUEST::DISABLED:
+        break;
+    case VULKAN_EXTENSION_REQUEST::DEFAULT:
+        validationLayersEnabled = validationLayersAvailable;
+        break;
+    case VULKAN_EXTENSION_REQUEST::ENABLED:
+        validationLayersEnabled = validationLayersAvailable;
+        if(!validationLayersAvailable)
+        {
+            printf("WARNING: %s layer cannot be enabled.\n", VALIDATION_LAYER_NAME);
+        }
+        break;
+    default: assert(0);
+    }
+
+    uint32_t availableInstanceExtensionCount = 0;
+    res = vkEnumerateInstanceExtensionProperties(nullptr, &availableInstanceExtensionCount, nullptr);
+    assert(res == VK_SUCCESS);
+    std::vector<VkExtensionProperties> availableInstanceExtensions(availableInstanceExtensionCount);
+    if(availableInstanceExtensionCount > 0)
+    {
+        res = vkEnumerateInstanceExtensionProperties(nullptr, &availableInstanceExtensionCount, availableInstanceExtensions.data());
+        assert(res == VK_SUCCESS);
+    }
+
+    std::vector<const char*> enabledInstanceExtensions;
+    //enabledInstanceExtensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
+    //enabledInstanceExtensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
+
+    std::vector<const char*> instanceLayers;
+    if(validationLayersEnabled)
+    {
+        instanceLayers.push_back(VALIDATION_LAYER_NAME);
+        enabledInstanceExtensions.push_back("VK_EXT_debug_report");
+    }
+
+    bool VK_KHR_get_physical_device_properties2_enabled = false;
+    for(const auto& extensionProperties : availableInstanceExtensions)
+    {
+        if(strcmp(extensionProperties.extensionName, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME) == 0)
+        {
+            enabledInstanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
+            VK_KHR_get_physical_device_properties2_enabled = true;
+        }
+    }
+
+    VkApplicationInfo appInfo = { VK_STRUCTURE_TYPE_APPLICATION_INFO };
+    appInfo.pApplicationName = "VmaReplay";
+    appInfo.applicationVersion = VK_MAKE_VERSION(2, 3, 0);
+    appInfo.pEngineName = "Vulkan Memory Allocator";
+    appInfo.engineVersion = VK_MAKE_VERSION(2, 3, 0);
+    appInfo.apiVersion = VULKAN_API_VERSION;
+
+    VkInstanceCreateInfo instInfo = { VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO };
+    instInfo.pApplicationInfo = &appInfo;
+    instInfo.enabledExtensionCount = (uint32_t)enabledInstanceExtensions.size();
+    instInfo.ppEnabledExtensionNames = enabledInstanceExtensions.data();
+    instInfo.enabledLayerCount = (uint32_t)instanceLayers.size();
+    instInfo.ppEnabledLayerNames = instanceLayers.data();
+
+    res = vkCreateInstance(&instInfo, NULL, &m_VulkanInstance);
+    if(res != VK_SUCCESS)
+    {
+        printf("ERROR: vkCreateInstance failed (%d)\n", res);
+        return RESULT_ERROR_VULKAN;
+    }
+
+    if(validationLayersEnabled)
+    {
+        RegisterDebugCallbacks();
+    }
+
+    // Find physical device
+
+    uint32_t physicalDeviceCount = 0;
+    res = vkEnumeratePhysicalDevices(m_VulkanInstance, &physicalDeviceCount, nullptr);
+    assert(res == VK_SUCCESS);
+    if(physicalDeviceCount == 0)
+    {
+        printf("ERROR: No Vulkan physical devices found.\n");
+        return RESULT_ERROR_VULKAN;
+    }
+
+    std::vector<VkPhysicalDevice> physicalDevices(physicalDeviceCount);
+    res = vkEnumeratePhysicalDevices(m_VulkanInstance, &physicalDeviceCount, physicalDevices.data());
+    assert(res == VK_SUCCESS);
+
+    if(g_PhysicalDeviceIndex >= physicalDeviceCount)
+    {
+        printf("ERROR: Incorrect Vulkan physical device index %u. System has %u physical devices.\n",
+            g_PhysicalDeviceIndex,
+            physicalDeviceCount);
+        return RESULT_ERROR_VULKAN;
+    }
+
+    m_PhysicalDevice = physicalDevices[0];
+
+    // Find queue family index
+
+    uint32_t queueFamilyCount = 0;
+    vkGetPhysicalDeviceQueueFamilyProperties(m_PhysicalDevice, &queueFamilyCount, nullptr);
+    if(queueFamilyCount)
+    {
+        std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
+        vkGetPhysicalDeviceQueueFamilyProperties(m_PhysicalDevice, &queueFamilyCount, queueFamilies.data());
+        for(uint32_t i = 0; i < queueFamilyCount; ++i)
+        {
+            if(queueFamilies[i].queueCount > 0)
+            {
+                if(m_GraphicsQueueFamilyIndex == UINT32_MAX &&
+                    (queueFamilies[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0)
+                {
+                    m_GraphicsQueueFamilyIndex = i;
+                }
+                if(m_TransferQueueFamilyIndex == UINT32_MAX &&
+                    (queueFamilies[i].queueFlags & VK_QUEUE_TRANSFER_BIT) != 0)
+                {
+                    m_TransferQueueFamilyIndex = i;
+                }
+            }
+        }
+    }
+    if(m_GraphicsQueueFamilyIndex == UINT_MAX)
+    {
+        printf("ERROR: Couldn't find graphics queue.\n");
+        return RESULT_ERROR_VULKAN;
+    }
+    if(m_TransferQueueFamilyIndex == UINT_MAX)
+    {
+        printf("ERROR: Couldn't find transfer queue.\n");
+        return RESULT_ERROR_VULKAN;
+    }
+
+    VkPhysicalDeviceFeatures supportedFeatures;
+    vkGetPhysicalDeviceFeatures(m_PhysicalDevice, &supportedFeatures);
+
+    // Create logical device
+
+    const float queuePriority = 1.f;
+
+    VkDeviceQueueCreateInfo deviceQueueCreateInfo[2] = {};
+    deviceQueueCreateInfo[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
+    deviceQueueCreateInfo[0].queueFamilyIndex = m_GraphicsQueueFamilyIndex;
+    deviceQueueCreateInfo[0].queueCount = 1;
+    deviceQueueCreateInfo[0].pQueuePriorities = &queuePriority;
+
+    if(m_TransferQueueFamilyIndex != m_GraphicsQueueFamilyIndex)
+    {
+        deviceQueueCreateInfo[1].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
+        deviceQueueCreateInfo[1].queueFamilyIndex = m_TransferQueueFamilyIndex;
+        deviceQueueCreateInfo[1].queueCount = 1;
+        deviceQueueCreateInfo[1].pQueuePriorities = &queuePriority;
+    }
+
+    // Enable something what may interact with memory/buffer/image support.
+    VkPhysicalDeviceFeatures enabledFeatures;
+    InitVulkanFeatures(enabledFeatures, supportedFeatures);
+
+    bool VK_KHR_get_memory_requirements2_available = false;
+
+    // Determine list of device extensions to enable.
+    std::vector<const char*> enabledDeviceExtensions;
+    //enabledDeviceExtensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
+    bool memoryBudgetAvailable = false;
+    {
+        uint32_t propertyCount = 0;
+        res = vkEnumerateDeviceExtensionProperties(m_PhysicalDevice, nullptr, &propertyCount, nullptr);
+        assert(res == VK_SUCCESS);
+
+        if(propertyCount)
+        {
+            std::vector<VkExtensionProperties> properties{propertyCount};
+            res = vkEnumerateDeviceExtensionProperties(m_PhysicalDevice, nullptr, &propertyCount, properties.data());
+            assert(res == VK_SUCCESS);
+
+            for(uint32_t i = 0; i < propertyCount; ++i)
+            {
+                if(strcmp(properties[i].extensionName, VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME) == 0)
+                {
+                    VK_KHR_get_memory_requirements2_available = true;
+                }
+                else if(strcmp(properties[i].extensionName, VK_EXT_MEMORY_BUDGET_EXTENSION_NAME) == 0)
+                {
+                    if(VK_KHR_get_physical_device_properties2_enabled)
+                    {
+                        memoryBudgetAvailable = true;
+                    }
+                }
+            }
+        }
+    }
+
+    switch(g_VK_EXT_memory_budget_request)
+    {
+    case VULKAN_EXTENSION_REQUEST::DISABLED:
+        break;
+    case VULKAN_EXTENSION_REQUEST::DEFAULT:
+        m_MemoryBudgetEnabled = memoryBudgetAvailable;
+        break;
+    case VULKAN_EXTENSION_REQUEST::ENABLED:
+        m_MemoryBudgetEnabled = memoryBudgetAvailable;
+        if(!memoryBudgetAvailable)
+        {
+            printf("WARNING: VK_EXT_memory_budget extension cannot be enabled.\n");
+        }
+        break;
+    default: assert(0);
+    }
+
+    if(g_VK_AMD_device_coherent_memory_request == VULKAN_EXTENSION_REQUEST::ENABLED)
+    {
+        printf("WARNING: AMD_device_coherent_memory requested but not currently supported by the player.\n");
+    }
+
+    if(m_MemoryBudgetEnabled)
+    {
+        enabledDeviceExtensions.push_back(VK_EXT_MEMORY_BUDGET_EXTENSION_NAME);
+    }
+
+    VkDeviceCreateInfo deviceCreateInfo = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO };
+    deviceCreateInfo.enabledExtensionCount = (uint32_t)enabledDeviceExtensions.size();
+    deviceCreateInfo.ppEnabledExtensionNames = !enabledDeviceExtensions.empty() ? enabledDeviceExtensions.data() : nullptr;
+    deviceCreateInfo.queueCreateInfoCount = m_TransferQueueFamilyIndex != m_GraphicsQueueFamilyIndex ? 2 : 1;
+    deviceCreateInfo.pQueueCreateInfos = deviceQueueCreateInfo;
+    deviceCreateInfo.pEnabledFeatures = &enabledFeatures;
+
+    res = vkCreateDevice(m_PhysicalDevice, &deviceCreateInfo, nullptr, &m_Device);
+    if(res != VK_SUCCESS)
+    {
+        printf("ERROR: vkCreateDevice failed (%d)\n", res);
+        return RESULT_ERROR_VULKAN;
+    }
+
+    // Fetch queues
+    vkGetDeviceQueue(m_Device, m_GraphicsQueueFamilyIndex, 0, &m_GraphicsQueue);
+    vkGetDeviceQueue(m_Device, m_TransferQueueFamilyIndex, 0, &m_TransferQueue);
+
+    // Create memory allocator
+
+    VmaDeviceMemoryCallbacks deviceMemoryCallbacks = {};
+    deviceMemoryCallbacks.pfnAllocate = AllocateDeviceMemoryCallback;
+    deviceMemoryCallbacks.pfnFree = FreeDeviceMemoryCallback;
+
+    VmaAllocatorCreateInfo allocatorInfo = {};
+    allocatorInfo.instance = m_VulkanInstance;
+    allocatorInfo.physicalDevice = m_PhysicalDevice;
+    allocatorInfo.device = m_Device;
+    allocatorInfo.flags = VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT;
+    allocatorInfo.pDeviceMemoryCallbacks = &deviceMemoryCallbacks;
+    allocatorInfo.vulkanApiVersion = VULKAN_API_VERSION;
+
+    if(m_MemoryBudgetEnabled)
+    {
+        allocatorInfo.flags |= VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT;
+    }
+
+    res = vmaCreateAllocator(&allocatorInfo, &m_Allocator);
+    if(res != VK_SUCCESS)
+    {
+        printf("ERROR: vmaCreateAllocator failed (%d)\n", res);
+        return RESULT_ERROR_VULKAN;
+    }
+
+    vmaGetPhysicalDeviceProperties(m_Allocator, &m_DevProps);
+    vmaGetMemoryProperties(m_Allocator, &m_MemProps);
+
+    // Create command pool
+
+    VkCommandPoolCreateInfo cmdPoolCreateInfo = { VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO };
+    cmdPoolCreateInfo.queueFamilyIndex = m_TransferQueueFamilyIndex;
+    cmdPoolCreateInfo.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT;
+
+    res = vkCreateCommandPool(m_Device, &cmdPoolCreateInfo, nullptr, &m_CommandPool);
+    if(res != VK_SUCCESS)
+    {
+        printf("ERROR: vkCreateCommandPool failed (%d)\n", res);
+        return RESULT_ERROR_VULKAN;
+    }
+
+    // Create command buffer
+
+    VkCommandBufferAllocateInfo cmdBufAllocInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO };
+    cmdBufAllocInfo.commandBufferCount = 1;
+    cmdBufAllocInfo.commandPool = m_CommandPool;
+    cmdBufAllocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+    res = vkAllocateCommandBuffers(m_Device, &cmdBufAllocInfo, &m_CommandBuffer);
+    if(res != VK_SUCCESS)
+    {
+        printf("ERROR: vkAllocateCommandBuffers failed (%d)\n", res);
+        return RESULT_ERROR_VULKAN;
+    }
+
+    return 0;
+}
+
+void Player::FinalizeVulkan()
+{
+    if(!m_DefragmentationContexts.empty())
+    {
+        printf("WARNING: Defragmentation contexts not destroyed: %zu.\n", m_DefragmentationContexts.size());
+
+        if(CLEANUP_LEAKED_OBJECTS)
+        {
+            for(const auto& it : m_DefragmentationContexts)
+            {
+                vmaDefragmentationEnd(m_Allocator, it.second);
+            }
+        }
+
+        m_DefragmentationContexts.clear();
+    }
+
+    if(!m_Allocations.empty())
+    {
+        printf("WARNING: Allocations not destroyed: %zu.\n", m_Allocations.size());
+
+        if(CLEANUP_LEAKED_OBJECTS)
+        {
+            for(const auto it : m_Allocations)
+            {
+                Destroy(it.second);
+            }
+        }
+
+        m_Allocations.clear();
+    }
+
+    if(!m_Pools.empty())
+    {
+        printf("WARNING: Custom pools not destroyed: %zu.\n", m_Pools.size());
+
+        if(CLEANUP_LEAKED_OBJECTS)
+        {
+            for(const auto it : m_Pools)
+            {
+                vmaDestroyPool(m_Allocator, it.second.pool);
+            }
+        }
+
+        m_Pools.clear();
+    }
+
+    vkDeviceWaitIdle(m_Device);
+
+    if(m_CommandBuffer != VK_NULL_HANDLE)
+    {
+        vkFreeCommandBuffers(m_Device, m_CommandPool, 1, &m_CommandBuffer);
+        m_CommandBuffer = VK_NULL_HANDLE;
+    }
+
+    if(m_CommandPool != VK_NULL_HANDLE)
+    {
+        vkDestroyCommandPool(m_Device, m_CommandPool, nullptr);
+        m_CommandPool = VK_NULL_HANDLE;
+    }
+
+    if(m_Allocator != VK_NULL_HANDLE)
+    {
+        vmaDestroyAllocator(m_Allocator);
+        m_Allocator = nullptr;
+    }
+
+    if(m_Device != VK_NULL_HANDLE)
+    {
+        vkDestroyDevice(m_Device, nullptr);
+        m_Device = nullptr;
+    }
+
+    if(m_pvkDestroyDebugReportCallbackEXT && m_hCallback != VK_NULL_HANDLE)
+    {
+        m_pvkDestroyDebugReportCallbackEXT(m_VulkanInstance, m_hCallback, nullptr);
+        m_hCallback = VK_NULL_HANDLE;
+    }
+
+    if(m_VulkanInstance != VK_NULL_HANDLE)
+    {
+        vkDestroyInstance(m_VulkanInstance, NULL);
+        m_VulkanInstance = VK_NULL_HANDLE;
+    }
+}
+
+void Player::RegisterDebugCallbacks()
+{
+    m_pvkCreateDebugReportCallbackEXT =
+        reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>
+            (vkGetInstanceProcAddr(m_VulkanInstance, "vkCreateDebugReportCallbackEXT"));
+    m_pvkDebugReportMessageEXT =
+        reinterpret_cast<PFN_vkDebugReportMessageEXT>
+            (vkGetInstanceProcAddr(m_VulkanInstance, "vkDebugReportMessageEXT"));
+    m_pvkDestroyDebugReportCallbackEXT =
+        reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>
+            (vkGetInstanceProcAddr(m_VulkanInstance, "vkDestroyDebugReportCallbackEXT"));
+    assert(m_pvkCreateDebugReportCallbackEXT);
+    assert(m_pvkDebugReportMessageEXT);
+    assert(m_pvkDestroyDebugReportCallbackEXT);
+
+    VkDebugReportCallbackCreateInfoEXT callbackCreateInfo = { VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT };
+    callbackCreateInfo.flags = //VK_DEBUG_REPORT_INFORMATION_BIT_EXT |
+        VK_DEBUG_REPORT_ERROR_BIT_EXT |
+        VK_DEBUG_REPORT_WARNING_BIT_EXT |
+        VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT /*|
+        VK_DEBUG_REPORT_DEBUG_BIT_EXT*/;
+    callbackCreateInfo.pfnCallback = &MyDebugReportCallback;
+
+    VkResult res = m_pvkCreateDebugReportCallbackEXT(m_VulkanInstance, &callbackCreateInfo, nullptr, &m_hCallback);
+    assert(res == VK_SUCCESS);
+}
+
+void Player::Defragment()
+{
+    VmaStats stats;
+    vmaCalculateStats(m_Allocator, &stats);
+    PrintStats(stats, "before defragmentation");
+
+    const size_t allocCount = m_Allocations.size();
+    std::vector<VmaAllocation> allocations(allocCount);
+    size_t notNullAllocCount = 0;
+    for(const auto& it : m_Allocations)
+    {
+        if(it.second.allocation != VK_NULL_HANDLE)
+        {
+            allocations[notNullAllocCount] = it.second.allocation;
+            ++notNullAllocCount;
+        }
+    }
+    if(notNullAllocCount == 0)
+    {
+        printf("    Nothing to defragment.\n");
+        return;
+    }
+
+    allocations.resize(notNullAllocCount);
+    std::vector<VkBool32> allocationsChanged(notNullAllocCount);
+
+    VmaDefragmentationStats defragStats = {};
+
+    VkCommandBufferBeginInfo cmdBufBeginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
+    cmdBufBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
+    VkResult res = vkBeginCommandBuffer(m_CommandBuffer, &cmdBufBeginInfo);
+    if(res != VK_SUCCESS)
+    {
+        printf("ERROR: vkBeginCommandBuffer failed (%d)\n", res);
+        return;
+    }
+
+    const time_point timeBeg = std::chrono::high_resolution_clock::now();
+
+    VmaDefragmentationInfo2 defragInfo = {};
+    defragInfo.allocationCount = (uint32_t)notNullAllocCount;
+    defragInfo.pAllocations = allocations.data();
+    defragInfo.pAllocationsChanged = allocationsChanged.data();
+    defragInfo.maxCpuAllocationsToMove = UINT32_MAX;
+    defragInfo.maxCpuBytesToMove = VK_WHOLE_SIZE;
+    defragInfo.maxGpuAllocationsToMove = UINT32_MAX;
+    defragInfo.maxGpuBytesToMove = VK_WHOLE_SIZE;
+    defragInfo.flags = g_DefragmentationFlags;
+    defragInfo.commandBuffer = m_CommandBuffer;
+
+    VmaDefragmentationContext defragCtx = VK_NULL_HANDLE;
+    res = vmaDefragmentationBegin(m_Allocator, &defragInfo, &defragStats, &defragCtx);
+    
+    const time_point timeAfterDefragBegin = std::chrono::high_resolution_clock::now();
+
+    vkEndCommandBuffer(m_CommandBuffer);
+
+    if(res >= VK_SUCCESS)
+    {
+        VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO };
+        submitInfo.commandBufferCount = 1;
+        submitInfo.pCommandBuffers = &m_CommandBuffer;
+        vkQueueSubmit(m_TransferQueue, 1, &submitInfo, VK_NULL_HANDLE);
+        vkQueueWaitIdle(m_TransferQueue);
+
+        const time_point timeAfterGpu = std::chrono::high_resolution_clock::now();
+
+        vmaDefragmentationEnd(m_Allocator, defragCtx);
+
+        const time_point timeAfterDefragEnd = std::chrono::high_resolution_clock::now();
+
+        const duration defragDurationBegin = timeAfterDefragBegin - timeBeg;
+        const duration defragDurationGpu   = timeAfterGpu - timeAfterDefragBegin;
+        const duration defragDurationEnd   = timeAfterDefragEnd - timeAfterGpu;
+
+        // If anything changed.
+        if(defragStats.allocationsMoved > 0)
+        {
+            // Go over allocation that changed and destroy their buffers and images.
+            size_t i = 0;
+            for(auto& it : m_Allocations)
+            {
+                if(allocationsChanged[i] != VK_FALSE)
+                {
+                    if(it.second.buffer != VK_NULL_HANDLE)
+                    {
+                        vkDestroyBuffer(m_Device, it.second.buffer, nullptr);
+                        it.second.buffer = VK_NULL_HANDLE;
+                    }
+                    if(it.second.image != VK_NULL_HANDLE)
+                    {
+                        vkDestroyImage(m_Device, it.second.image, nullptr);
+                        it.second.image = VK_NULL_HANDLE;
+                    }
+                }
+                ++i;
+            }
+        }
+
+        // Print statistics
+        std::string defragDurationBeginStr;
+        std::string defragDurationGpuStr;
+        std::string defragDurationEndStr;
+        SecondsToFriendlyStr(ToFloatSeconds(defragDurationBegin), defragDurationBeginStr);
+        SecondsToFriendlyStr(ToFloatSeconds(defragDurationGpu), defragDurationGpuStr);
+        SecondsToFriendlyStr(ToFloatSeconds(defragDurationEnd), defragDurationEndStr);
+
+        printf("    Defragmentation took:\n");
+        printf("        vmaDefragmentationBegin: %s\n", defragDurationBeginStr.c_str());
+        printf("        GPU: %s\n", defragDurationGpuStr.c_str());
+        printf("        vmaDefragmentationEnd: %s\n", defragDurationEndStr.c_str());
+        printf("    VmaDefragmentationStats:\n");
+        printf("        bytesMoved: %llu\n", defragStats.bytesMoved);
+        printf("        bytesFreed: %llu\n", defragStats.bytesFreed);
+        printf("        allocationsMoved: %u\n", defragStats.allocationsMoved);
+        printf("        deviceMemoryBlocksFreed: %u\n", defragStats.deviceMemoryBlocksFreed);
+
+        vmaCalculateStats(m_Allocator, &stats);
+        PrintStats(stats, "after defragmentation");
+    }
+    else
+    {
+        printf("vmaDefragmentationBegin failed (%d).\n", res);
+    }
+
+    vkResetCommandPool(m_Device, m_CommandPool, 0);
+}
+
+void Player::PrintStats()
+{
+    if(g_Verbosity == VERBOSITY::MINIMUM)
+    {
+        return;
+    }
+
+    m_Stats.PrintDeviceMemStats();
+
+    printf("Statistics:\n");
+    if(m_Stats.GetAllocationCreationCount() > 0)
+    {
+        printf("    Total allocations created: %zu\n", m_Stats.GetAllocationCreationCount());
+    }
+
+    // Buffers
+    if(m_Stats.GetBufferCreationCount())
+    {
+        printf("    Total buffers created: %zu\n", m_Stats.GetBufferCreationCount());
+        if(g_Verbosity == VERBOSITY::MAXIMUM)
+        {
+            printf("        Class 0 (indirect/vertex/index): %zu\n", m_Stats.GetBufferCreationCount(0));
+            printf("        Class 1 (storage): %zu\n", m_Stats.GetBufferCreationCount(1));
+            printf("        Class 2 (uniform): %zu\n", m_Stats.GetBufferCreationCount(2));
+            printf("        Class 3 (other): %zu\n", m_Stats.GetBufferCreationCount(3));
+        }
+    }
+    
+    // Images
+    const size_t imageCreationCount =
+        m_Stats.GetImageCreationCount(0) +
+        m_Stats.GetImageCreationCount(1) +
+        m_Stats.GetImageCreationCount(2) +
+        m_Stats.GetImageCreationCount(3) +
+        m_Stats.GetLinearImageCreationCount();
+    if(imageCreationCount > 0)
+    {
+        printf("    Total images created: %zu\n", imageCreationCount);
+        if(g_Verbosity == VERBOSITY::MAXIMUM)
+        {
+            printf("        Class 0 (depth/stencil): %zu\n", m_Stats.GetImageCreationCount(0));
+            printf("        Class 1 (attachment): %zu\n", m_Stats.GetImageCreationCount(1));
+            printf("        Class 2 (sampled): %zu\n", m_Stats.GetImageCreationCount(2));
+            printf("        Class 3 (other): %zu\n", m_Stats.GetImageCreationCount(3));
+            if(m_Stats.GetLinearImageCreationCount() > 0)
+            {
+                printf("        LINEAR tiling: %zu\n", m_Stats.GetLinearImageCreationCount());
+            }
+        }
+    }
+    
+    if(m_Stats.GetPoolCreationCount() > 0)
+    {
+        printf("    Total custom pools created: %zu\n", m_Stats.GetPoolCreationCount());
+    }
+
+    float lastTime;
+    if(!m_LastLineTimeStr.empty() && StrRangeToFloat(StrRange(m_LastLineTimeStr), lastTime))
+    {
+        std::string origTimeStr;
+        SecondsToFriendlyStr(lastTime, origTimeStr);
+        printf("    Original recording time: %s\n", origTimeStr.c_str());
+    }
+
+    // Thread statistics.
+    const size_t threadCount = m_Threads.size();
+    if(threadCount > 1)
+    {
+        uint32_t threadCallCountMax = 0;
+        uint32_t threadCallCountSum = 0;
+        for(const auto& it : m_Threads)
+        {
+            threadCallCountMax = std::max(threadCallCountMax, it.second.callCount);
+            threadCallCountSum += it.second.callCount;
+        }
+        printf("    Threads making calls to VMA: %zu\n", threadCount);
+        printf("        %.2f%% calls from most active thread.\n",
+            (float)threadCallCountMax * 100.f / (float)threadCallCountSum);
+    }
+    else
+    {
+        printf("    VMA used from only one thread.\n");
+    }
+
+    // Function call count
+    if(g_Verbosity == VERBOSITY::MAXIMUM)
+    {
+        printf("    Function call count:\n");
+        const size_t* const functionCallCount = m_Stats.GetFunctionCallCount();
+        for(size_t i = 0; i < (size_t)VMA_FUNCTION::Count; ++i)
+        {
+            if(functionCallCount[i] > 0)
+            {
+                printf("        %s %zu\n", VMA_FUNCTION_NAMES[i], functionCallCount[i]);
+            }
+        }
+    }
+
+    // Detailed stats
+    if(g_Verbosity == VERBOSITY::MAXIMUM)
+    {
+        m_Stats.PrintDetailedStats();
+    }
+
+    if(g_MemStatsEnabled)
+    {
+        m_Stats.PrintMemStats();
+    }
+}
+
+bool Player::ValidateFunctionParameterCount(size_t lineNumber, const CsvSplit& csvSplit, size_t expectedParamCount, bool lastUnbound)
+{
+    bool ok;
+    if(lastUnbound)
+        ok = csvSplit.GetCount() >= FIRST_PARAM_INDEX + expectedParamCount - 1;
+    else
+        ok = csvSplit.GetCount() == FIRST_PARAM_INDEX + expectedParamCount;
+
+    if(!ok)
+    {
+        if(IssueWarning())
+        {
+            printf("Line %zu: Incorrect number of function parameters.\n", lineNumber);
+        }
+    }
+
+    return ok;
+}
+
+bool Player::PrepareUserData(size_t lineNumber, uint32_t allocCreateFlags, const StrRange& userDataColumn, const StrRange& wholeLine, void*& outUserData)
+{
+    if(!g_UserDataEnabled)
+    {
+        outUserData = nullptr;
+        return true;
+    }
+
+    // String
+    if((allocCreateFlags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0)
+    {
+        const size_t len = wholeLine.end - userDataColumn.beg;
+        m_UserDataTmpStr.resize(len + 1);
+        memcpy(m_UserDataTmpStr.data(), userDataColumn.beg, len);
+        m_UserDataTmpStr[len] = '\0';
+        outUserData = m_UserDataTmpStr.data();
+        return true;
+    }
+    // Pointer
+    else
+    {
+        uint64_t pUserData = 0;
+        if(StrRangeToPtr(userDataColumn, pUserData))
+        {
+            outUserData = (void*)(uintptr_t)pUserData;
+            return true;
+        }
+    }
+
+    if(IssueWarning())
+    {
+        printf("Line %zu: Invalid pUserData.\n", lineNumber);
+    }
+    outUserData = 0;
+    return false;
+}
+
+void Player::UpdateMemStats()
+{
+    if(!g_MemStatsEnabled)
+    {
+        return;
+    }
+
+    VmaStats stats;
+    vmaCalculateStats(m_Allocator, &stats);
+    m_Stats.UpdateMemStats(stats);
+}
+
+void Player::ExecuteCreatePool(size_t lineNumber, const CsvSplit& csvSplit)
+{
+    m_Stats.RegisterFunctionCall(VMA_FUNCTION::CreatePool);
+
+    if(ValidateFunctionParameterCount(lineNumber, csvSplit, 7, false))
+    {
+        VmaPoolCreateInfo poolCreateInfo = {};
+        uint64_t origPtr = 0;
+
+        if(StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX), poolCreateInfo.memoryTypeIndex) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 1), poolCreateInfo.flags) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 2), poolCreateInfo.blockSize) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 3), poolCreateInfo.minBlockCount) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 4), poolCreateInfo.maxBlockCount) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 5), poolCreateInfo.frameInUseCount) &&
+            StrRangeToPtr(csvSplit.GetRange(FIRST_PARAM_INDEX + 6), origPtr))
+        {
+            m_Stats.RegisterCreatePool(poolCreateInfo);
+
+            Pool poolDesc = {};
+            VkResult res = vmaCreatePool(m_Allocator, &poolCreateInfo, &poolDesc.pool);
+
+            if(origPtr)
+            {
+                if(res == VK_SUCCESS)
+                {
+                    // Originally succeeded, currently succeeded.
+                    // Just save pointer (done below).
+                }
+                else
+                {
+                    // Originally succeeded, currently failed.
+                    // Print warning. Save null pointer.
+                    if(IssueWarning())
+                    {
+                        printf("Line %zu: vmaCreatePool failed (%d), while originally succeeded.\n", lineNumber, res);
+                    }
+               }
+
+                const auto existingIt = m_Pools.find(origPtr);
+                if(existingIt != m_Pools.end())
+                {
+                    if(IssueWarning())
+                    {
+                        printf("Line %zu: Pool %llX already exists.\n", lineNumber, origPtr);
+                    }
+                }
+                m_Pools[origPtr] = poolDesc;
+            }
+            else
+            {
+                if(res == VK_SUCCESS)
+                {
+                    // Originally failed, currently succeeded.
+                    // Print warning, destroy the pool.
+                    if(IssueWarning())
+                    {
+                        printf("Line %zu: vmaCreatePool succeeded, originally failed.\n", lineNumber);
+                    }
+
+                    vmaDestroyPool(m_Allocator, poolDesc.pool);
+                }
+                else
+                {
+                    // Originally failed, currently failed.
+                    // Print warning.
+                    if(IssueWarning())
+                    {
+                        printf("Line %zu: vmaCreatePool failed (%d), originally also failed.\n", lineNumber, res);
+                    }
+                }
+            }
+
+            UpdateMemStats();
+        }
+        else
+        {
+            if(IssueWarning())
+            {
+                printf("Line %zu: Invalid parameters for vmaCreatePool.\n", lineNumber);
+            }
+        }
+    }
+}
+
+void Player::ExecuteDestroyPool(size_t lineNumber, const CsvSplit& csvSplit)
+{
+    m_Stats.RegisterFunctionCall(VMA_FUNCTION::DestroyPool);
+
+    if(ValidateFunctionParameterCount(lineNumber, csvSplit, 1, false))
+    {
+        uint64_t origPtr = 0;
+
+        if(StrRangeToPtr(csvSplit.GetRange(FIRST_PARAM_INDEX), origPtr))
+        {
+            if(origPtr != 0)
+            {
+                const auto it = m_Pools.find(origPtr);
+                if(it != m_Pools.end())
+                {
+                    vmaDestroyPool(m_Allocator, it->second.pool);
+                    UpdateMemStats();
+                    m_Pools.erase(it);
+                }
+                else
+                {
+                    if(IssueWarning())
+                    {
+                        printf("Line %zu: Pool %llX not found.\n", lineNumber, origPtr);
+                    }
+                }
+            }
+        }
+        else
+        {
+            if(IssueWarning())
+            {
+                printf("Line %zu: Invalid parameters for vmaDestroyPool.\n", lineNumber);
+            }
+        }
+    }
+}
+
+void Player::ExecuteSetAllocationUserData(size_t lineNumber, const CsvSplit& csvSplit)
+{
+    m_Stats.RegisterFunctionCall(VMA_FUNCTION::SetAllocationUserData);
+
+    if(!g_UserDataEnabled)
+    {
+        return;
+    }
+
+    if(ValidateFunctionParameterCount(lineNumber, csvSplit, 2, true))
+    {
+        uint64_t origPtr = 0;
+        if(StrRangeToPtr(csvSplit.GetRange(FIRST_PARAM_INDEX), origPtr))
+        {
+            const auto it = m_Allocations.find(origPtr);
+            if(it != m_Allocations.end())
+            {
+                void* pUserData = nullptr;
+                if(csvSplit.GetCount() > FIRST_PARAM_INDEX + 1)
+                {
+                    PrepareUserData(
+                        lineNumber,
+                        it->second.allocationFlags,
+                        csvSplit.GetRange(FIRST_PARAM_INDEX + 1),
+                        csvSplit.GetLine(),
+                        pUserData);
+                }
+
+                vmaSetAllocationUserData(m_Allocator, it->second.allocation, pUserData);
+            }
+            else
+            {
+                if(IssueWarning())
+                {
+                    printf("Line %zu: Allocation %llX not found.\n", lineNumber, origPtr);
+                }
+            }
+        }
+        else
+        {
+            if(IssueWarning())
+            {
+                printf("Line %zu: Invalid parameters for vmaSetAllocationUserData.\n", lineNumber);
+            }
+        }
+    }
+}
+
+void Player::ExecuteCreateBuffer(size_t lineNumber, const CsvSplit& csvSplit)
+{
+    m_Stats.RegisterFunctionCall(VMA_FUNCTION::CreateBuffer);
+
+    if(ValidateFunctionParameterCount(lineNumber, csvSplit, 12, true))
+    {
+        VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+        VmaAllocationCreateInfo allocCreateInfo = {};
+        uint64_t origPool = 0;
+        uint64_t origPtr = 0;
+
+        if(StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX), bufCreateInfo.flags) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 1), bufCreateInfo.size) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 2), bufCreateInfo.usage) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 3), (uint32_t&)bufCreateInfo.sharingMode) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 4), allocCreateInfo.flags) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 5), (uint32_t&)allocCreateInfo.usage) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 6), allocCreateInfo.requiredFlags) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 7), allocCreateInfo.preferredFlags) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 8), allocCreateInfo.memoryTypeBits) &&
+            StrRangeToPtr(csvSplit.GetRange(FIRST_PARAM_INDEX + 9), origPool) &&
+            StrRangeToPtr(csvSplit.GetRange(FIRST_PARAM_INDEX + 10), origPtr))
+        {
+            FindPool(lineNumber, origPool, allocCreateInfo.pool);
+
+            if(csvSplit.GetCount() > FIRST_PARAM_INDEX + 11)
+            {
+                PrepareUserData(
+                    lineNumber,
+                    allocCreateInfo.flags,
+                    csvSplit.GetRange(FIRST_PARAM_INDEX + 11),
+                    csvSplit.GetLine(),
+                    allocCreateInfo.pUserData);
+            }
+
+            m_Stats.RegisterCreateBuffer(bufCreateInfo);
+            m_Stats.RegisterCreateAllocation(allocCreateInfo);
+
+            // Forcing VK_SHARING_MODE_EXCLUSIVE because we use only one queue anyway.
+            bufCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+
+            Allocation allocDesc = { };
+            allocDesc.allocationFlags = allocCreateInfo.flags;
+            VkResult res = vmaCreateBuffer(m_Allocator, &bufCreateInfo, &allocCreateInfo, &allocDesc.buffer, &allocDesc.allocation, nullptr);
+            UpdateMemStats();
+            AddAllocation(lineNumber, origPtr, res, "vmaCreateBuffer", std::move(allocDesc));
+        }
+        else
+        {
+            if(IssueWarning())
+            {
+                printf("Line %zu: Invalid parameters for vmaCreateBuffer.\n", lineNumber);
+            }
+        }
+    }
+}
+
+void Player::DestroyAllocation(size_t lineNumber, const CsvSplit& csvSplit, const char* functionName)
+{
+    if(ValidateFunctionParameterCount(lineNumber, csvSplit, 1, false))
+    {
+        uint64_t origAllocPtr = 0;
+
+        if(StrRangeToPtr(csvSplit.GetRange(FIRST_PARAM_INDEX), origAllocPtr))
+        {
+            if(origAllocPtr != 0)
+            {
+                const auto it = m_Allocations.find(origAllocPtr);
+                if(it != m_Allocations.end())
+                {
+                    Destroy(it->second);
+                    UpdateMemStats();
+                    m_Allocations.erase(it);
+                }
+                else
+                {
+                    if(IssueWarning())
+                    {
+                        printf("Line %zu: Allocation %llX not found.\n", lineNumber, origAllocPtr);
+                    }
+                }
+            }
+        }
+        else
+        {
+            if(IssueWarning())
+            {
+                printf("Line %zu: Invalid parameters for %s.\n", lineNumber, functionName);
+            }
+        }
+    }
+}
+
+void Player::PrintStats(const VmaStats& stats, const char* suffix)
+{
+    printf("    VmaStats %s:\n", suffix);
+    printf("        total:\n");
+    PrintStatInfo(stats.total);
+
+    if(g_Verbosity == VERBOSITY::MAXIMUM)
+    {
+        for(uint32_t i = 0; i < m_MemProps->memoryHeapCount; ++i)
+        {
+            printf("        memoryHeap[%u]:\n", i);
+            PrintStatInfo(stats.memoryHeap[i]);
+        }
+        for(uint32_t i = 0; i < m_MemProps->memoryTypeCount; ++i)
+        {
+            printf("        memoryType[%u]:\n", i);
+            PrintStatInfo(stats.memoryType[i]);
+        }
+    }
+}
+
+void Player::PrintStatInfo(const VmaStatInfo& info)
+{
+    printf("            blockCount: %u\n", info.blockCount);
+    printf("            allocationCount: %u\n", info.allocationCount);
+    printf("            unusedRangeCount: %u\n", info.unusedRangeCount);
+    printf("            usedBytes: %llu\n", info.usedBytes);
+    printf("            unusedBytes: %llu\n", info.unusedBytes);
+    printf("            allocationSizeMin: %llu\n", info.allocationSizeMin);
+    printf("            allocationSizeAvg: %llu\n", info.allocationSizeAvg);
+    printf("            allocationSizeMax: %llu\n", info.allocationSizeMax);
+    printf("            unusedRangeSizeMin: %llu\n", info.unusedRangeSizeMin);
+    printf("            unusedRangeSizeAvg: %llu\n", info.unusedRangeSizeAvg);
+    printf("            unusedRangeSizeMax: %llu\n", info.unusedRangeSizeMax);
+}
+
+void Player::ExecuteCreateImage(size_t lineNumber, const CsvSplit& csvSplit)
+{
+    m_Stats.RegisterFunctionCall(VMA_FUNCTION::CreateImage);
+
+    if(ValidateFunctionParameterCount(lineNumber, csvSplit, 21, true))
+    {
+        VkImageCreateInfo imageCreateInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
+        VmaAllocationCreateInfo allocCreateInfo = {};
+        uint64_t origPool = 0;
+        uint64_t origPtr = 0;
+
+        if(StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX), imageCreateInfo.flags) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 1), (uint32_t&)imageCreateInfo.imageType) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 2), (uint32_t&)imageCreateInfo.format) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 3), imageCreateInfo.extent.width) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 4), imageCreateInfo.extent.height) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 5), imageCreateInfo.extent.depth) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 6), imageCreateInfo.mipLevels) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 7), imageCreateInfo.arrayLayers) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 8), (uint32_t&)imageCreateInfo.samples) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 9), (uint32_t&)imageCreateInfo.tiling) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 10), imageCreateInfo.usage) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 11), (uint32_t&)imageCreateInfo.sharingMode) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 12), (uint32_t&)imageCreateInfo.initialLayout) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 13), allocCreateInfo.flags) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 14), (uint32_t&)allocCreateInfo.usage) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 15), allocCreateInfo.requiredFlags) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 16), allocCreateInfo.preferredFlags) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 17), allocCreateInfo.memoryTypeBits) &&
+            StrRangeToPtr(csvSplit.GetRange(FIRST_PARAM_INDEX + 18), origPool) &&
+            StrRangeToPtr(csvSplit.GetRange(FIRST_PARAM_INDEX + 19), origPtr))
+        {
+            FindPool(lineNumber, origPool, allocCreateInfo.pool);
+
+            if(csvSplit.GetCount() > FIRST_PARAM_INDEX + 20)
+            {
+                PrepareUserData(
+                    lineNumber,
+                    allocCreateInfo.flags,
+                    csvSplit.GetRange(FIRST_PARAM_INDEX + 20),
+                    csvSplit.GetLine(),
+                    allocCreateInfo.pUserData);
+            }
+
+            m_Stats.RegisterCreateImage(imageCreateInfo);
+            m_Stats.RegisterCreateAllocation(allocCreateInfo);
+
+            // Forcing VK_SHARING_MODE_EXCLUSIVE because we use only one queue anyway.
+            imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+
+            Allocation allocDesc = {};
+            allocDesc.allocationFlags = allocCreateInfo.flags;
+            VkResult res = vmaCreateImage(m_Allocator, &imageCreateInfo, &allocCreateInfo, &allocDesc.image, &allocDesc.allocation, nullptr);
+            UpdateMemStats();
+            AddAllocation(lineNumber, origPtr, res, "vmaCreateImage", std::move(allocDesc));
+        }
+        else
+        {
+            if(IssueWarning())
+            {
+                printf("Line %zu: Invalid parameters for vmaCreateImage.\n", lineNumber);
+            }
+        }
+    }
+}
+
+void Player::ExecuteFreeMemoryPages(size_t lineNumber, const CsvSplit& csvSplit)
+{
+    m_Stats.RegisterFunctionCall(VMA_FUNCTION::FreeMemoryPages);
+    
+    if(ValidateFunctionParameterCount(lineNumber, csvSplit, 1, false))
+    {
+        std::vector<uint64_t> origAllocPtrs;
+        if(StrRangeToPtrList(csvSplit.GetRange(FIRST_PARAM_INDEX), origAllocPtrs))
+        {
+            const size_t allocCount = origAllocPtrs.size();
+            size_t notNullCount = 0;
+            for(size_t i = 0; i < allocCount; ++i)
+            {
+                const uint64_t origAllocPtr = origAllocPtrs[i];
+                if(origAllocPtr != 0)
+                {
+                    const auto it = m_Allocations.find(origAllocPtr);
+                    if(it != m_Allocations.end())
+                    {
+                        Destroy(it->second);
+                        m_Allocations.erase(it);
+                        ++notNullCount;
+                    }
+                    else
+                    {
+                        if(IssueWarning())
+                        {
+                            printf("Line %zu: Allocation %llX not found.\n", lineNumber, origAllocPtr);
+                        }
+                    }
+                }
+            }
+            if(notNullCount)
+            {
+                UpdateMemStats();
+            }
+        }
+        else
+        {
+            if(IssueWarning())
+            {
+                printf("Line %zu: Invalid parameters for vmaFreeMemoryPages.\n", lineNumber);
+            }
+        }
+    }
+}
+
+void Player::ExecuteCreateLostAllocation(size_t lineNumber, const CsvSplit& csvSplit)
+{
+    m_Stats.RegisterFunctionCall(VMA_FUNCTION::CreateLostAllocation);
+
+    if(ValidateFunctionParameterCount(lineNumber, csvSplit, 1, false))
+    {
+        uint64_t origPtr = 0;
+
+        if(StrRangeToPtr(csvSplit.GetRange(FIRST_PARAM_INDEX), origPtr))
+        {
+            Allocation allocDesc = {};
+            vmaCreateLostAllocation(m_Allocator, &allocDesc.allocation);
+            UpdateMemStats();
+            m_Stats.RegisterCreateLostAllocation();
+
+            AddAllocation(lineNumber, origPtr, VK_SUCCESS, "vmaCreateLostAllocation", std::move(allocDesc));
+        }
+        else
+        {
+            if(IssueWarning())
+            {
+                printf("Line %zu: Invalid parameters for vmaCreateLostAllocation.\n", lineNumber);
+            }
+        }
+    }
+}
+
+void Player::ExecuteAllocateMemory(size_t lineNumber, const CsvSplit& csvSplit)
+{
+    m_Stats.RegisterFunctionCall(VMA_FUNCTION::AllocateMemory);
+
+    if(ValidateFunctionParameterCount(lineNumber, csvSplit, 11, true))
+    {
+        VkMemoryRequirements memReq = {};
+        VmaAllocationCreateInfo allocCreateInfo = {};
+        uint64_t origPool = 0;
+        uint64_t origPtr = 0;
+
+        if(StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX), memReq.size) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 1), memReq.alignment) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 2), memReq.memoryTypeBits) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 3), allocCreateInfo.flags) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 4), (uint32_t&)allocCreateInfo.usage) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 5), allocCreateInfo.requiredFlags) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 6), allocCreateInfo.preferredFlags) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 7), allocCreateInfo.memoryTypeBits) &&
+            StrRangeToPtr(csvSplit.GetRange(FIRST_PARAM_INDEX + 8), origPool) &&
+            StrRangeToPtr(csvSplit.GetRange(FIRST_PARAM_INDEX + 9), origPtr))
+        {
+            FindPool(lineNumber, origPool, allocCreateInfo.pool);
+
+            if(csvSplit.GetCount() > FIRST_PARAM_INDEX + 10)
+            {
+                PrepareUserData(
+                    lineNumber,
+                    allocCreateInfo.flags,
+                    csvSplit.GetRange(FIRST_PARAM_INDEX + 10),
+                    csvSplit.GetLine(),
+                    allocCreateInfo.pUserData);
+            }
+
+            UpdateMemStats();
+            m_Stats.RegisterCreateAllocation(allocCreateInfo);
+
+            Allocation allocDesc = {};
+            allocDesc.allocationFlags = allocCreateInfo.flags;
+            VkResult res = vmaAllocateMemory(m_Allocator, &memReq, &allocCreateInfo, &allocDesc.allocation, nullptr);
+            AddAllocation(lineNumber, origPtr, res, "vmaAllocateMemory", std::move(allocDesc));
+        }
+        else
+        {
+            if(IssueWarning())
+            {
+                printf("Line %zu: Invalid parameters for vmaAllocateMemory.\n", lineNumber);
+            }
+        }
+    }
+}
+
+void Player::ExecuteAllocateMemoryPages(size_t lineNumber, const CsvSplit& csvSplit)
+{
+    m_Stats.RegisterFunctionCall(VMA_FUNCTION::AllocateMemoryPages);
+
+    if(ValidateFunctionParameterCount(lineNumber, csvSplit, 11, true))
+    {
+        VkMemoryRequirements memReq = {};
+        VmaAllocationCreateInfo allocCreateInfo = {};
+        uint64_t origPool = 0;
+        std::vector<uint64_t> origPtrs;
+
+        if(StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX), memReq.size) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 1), memReq.alignment) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 2), memReq.memoryTypeBits) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 3), allocCreateInfo.flags) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 4), (uint32_t&)allocCreateInfo.usage) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 5), allocCreateInfo.requiredFlags) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 6), allocCreateInfo.preferredFlags) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 7), allocCreateInfo.memoryTypeBits) &&
+            StrRangeToPtr(csvSplit.GetRange(FIRST_PARAM_INDEX + 8), origPool) &&
+            StrRangeToPtrList(csvSplit.GetRange(FIRST_PARAM_INDEX + 9), origPtrs))
+        {
+            const size_t allocCount = origPtrs.size();
+            if(allocCount > 0)
+            {
+                FindPool(lineNumber, origPool, allocCreateInfo.pool);
+
+                if(csvSplit.GetCount() > FIRST_PARAM_INDEX + 10)
+                {
+                    PrepareUserData(
+                        lineNumber,
+                        allocCreateInfo.flags,
+                        csvSplit.GetRange(FIRST_PARAM_INDEX + 10),
+                        csvSplit.GetLine(),
+                        allocCreateInfo.pUserData);
+                }
+
+                UpdateMemStats();
+                m_Stats.RegisterCreateAllocation(allocCreateInfo, allocCount);
+                m_Stats.RegisterAllocateMemoryPages(allocCount);
+
+                std::vector<VmaAllocation> allocations(allocCount);
+
+                VkResult res = vmaAllocateMemoryPages(m_Allocator, &memReq, &allocCreateInfo, allocCount, allocations.data(), nullptr);
+                for(size_t i = 0; i < allocCount; ++i)
+                {
+                    Allocation allocDesc = {};
+                    allocDesc.allocationFlags = allocCreateInfo.flags;
+                    allocDesc.allocation = allocations[i];
+                    AddAllocation(lineNumber, origPtrs[i], res, "vmaAllocateMemoryPages", std::move(allocDesc));
+                }
+            }
+        }
+        else
+        {
+            if(IssueWarning())
+            {
+                printf("Line %zu: Invalid parameters for vmaAllocateMemoryPages.\n", lineNumber);
+            }
+        }
+    }
+}
+
+void Player::ExecuteAllocateMemoryForBufferOrImage(size_t lineNumber, const CsvSplit& csvSplit, OBJECT_TYPE objType)
+{
+    switch(objType)
+    {
+    case OBJECT_TYPE::BUFFER:
+        m_Stats.RegisterFunctionCall(VMA_FUNCTION::AllocateMemoryForBuffer);
+        break;
+    case OBJECT_TYPE::IMAGE:
+        m_Stats.RegisterFunctionCall(VMA_FUNCTION::AllocateMemoryForImage);
+        break;
+    default: assert(0);
+    }
+
+    if(ValidateFunctionParameterCount(lineNumber, csvSplit, 13, true))
+    {
+        VkMemoryRequirements memReq = {};
+        VmaAllocationCreateInfo allocCreateInfo = {};
+        bool requiresDedicatedAllocation = false;
+        bool prefersDedicatedAllocation = false;
+        uint64_t origPool = 0;
+        uint64_t origPtr = 0;
+
+        if(StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX), memReq.size) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 1), memReq.alignment) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 2), memReq.memoryTypeBits) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 3), allocCreateInfo.flags) &&
+            StrRangeToBool(csvSplit.GetRange(FIRST_PARAM_INDEX + 4), requiresDedicatedAllocation) &&
+            StrRangeToBool(csvSplit.GetRange(FIRST_PARAM_INDEX + 5), prefersDedicatedAllocation) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 6), (uint32_t&)allocCreateInfo.usage) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 7), allocCreateInfo.requiredFlags) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 8), allocCreateInfo.preferredFlags) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 9), allocCreateInfo.memoryTypeBits) &&
+            StrRangeToPtr(csvSplit.GetRange(FIRST_PARAM_INDEX + 10), origPool) &&
+            StrRangeToPtr(csvSplit.GetRange(FIRST_PARAM_INDEX + 11), origPtr))
+        {
+            FindPool(lineNumber, origPool, allocCreateInfo.pool);
+
+            if(csvSplit.GetCount() > FIRST_PARAM_INDEX + 12)
+            {
+                PrepareUserData(
+                    lineNumber,
+                    allocCreateInfo.flags,
+                    csvSplit.GetRange(FIRST_PARAM_INDEX + 12),
+                    csvSplit.GetLine(),
+                    allocCreateInfo.pUserData);
+            }
+
+            UpdateMemStats();
+            m_Stats.RegisterCreateAllocation(allocCreateInfo);
+
+            if(requiresDedicatedAllocation || prefersDedicatedAllocation)
+            {
+                allocCreateInfo.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
+            }
+
+            if(!m_AllocateForBufferImageWarningIssued)
+            {
+                if(IssueWarning())
+                {
+                    printf("Line %zu: vmaAllocateMemoryForBuffer or vmaAllocateMemoryForImage cannot be replayed accurately. Using vmaCreateAllocation instead.\n", lineNumber);
+                }
+                m_AllocateForBufferImageWarningIssued = true;
+            }
+
+            Allocation allocDesc = {};
+            allocDesc.allocationFlags = allocCreateInfo.flags;
+            VkResult res = vmaAllocateMemory(m_Allocator, &memReq, &allocCreateInfo, &allocDesc.allocation, nullptr);
+            AddAllocation(lineNumber, origPtr, res, "vmaAllocateMemory (called as vmaAllocateMemoryForBuffer or vmaAllocateMemoryForImage)", std::move(allocDesc));
+        }
+        else
+        {
+            if(IssueWarning())
+            {
+                printf("Line %zu: Invalid parameters for vmaAllocateMemoryForBuffer or vmaAllocateMemoryForImage.\n", lineNumber);
+            }
+        }
+    }
+}
+
+void Player::ExecuteMapMemory(size_t lineNumber, const CsvSplit& csvSplit)
+{
+    m_Stats.RegisterFunctionCall(VMA_FUNCTION::MapMemory);
+
+    if(ValidateFunctionParameterCount(lineNumber, csvSplit, 1, false))
+    {
+        uint64_t origPtr = 0;
+
+        if(StrRangeToPtr(csvSplit.GetRange(FIRST_PARAM_INDEX), origPtr))
+        {
+            if(origPtr != 0)
+            {
+                const auto it = m_Allocations.find(origPtr);
+                if(it != m_Allocations.end())
+                {
+                    if(it->second.allocation)
+                    {
+                        void* pData;
+                        VkResult res = vmaMapMemory(m_Allocator, it->second.allocation, &pData);
+                        if(res != VK_SUCCESS)
+                        {
+                            printf("Line %zu: vmaMapMemory failed (%d)\n", lineNumber, res);
+                        }
+                    }
+                    else
+                    {
+                        if(IssueWarning())
+                        {
+                            printf("Line %zu: Cannot call vmaMapMemory - allocation is null.\n", lineNumber);
+                        }
+                    }
+                }
+                else
+                {
+                    if(IssueWarning())
+                    {
+                        printf("Line %zu: Allocation %llX not found.\n", lineNumber, origPtr);
+                    }
+                }
+            }
+        }
+        else
+        {
+            if(IssueWarning())
+            {
+                printf("Line %zu: Invalid parameters for vmaMapMemory.\n", lineNumber);
+            }
+        }
+    }
+}
+
+void Player::ExecuteUnmapMemory(size_t lineNumber, const CsvSplit& csvSplit)
+{
+    m_Stats.RegisterFunctionCall(VMA_FUNCTION::UnmapMemory);
+
+    if(ValidateFunctionParameterCount(lineNumber, csvSplit, 1, false))
+    {
+        uint64_t origPtr = 0;
+
+        if(StrRangeToPtr(csvSplit.GetRange(FIRST_PARAM_INDEX), origPtr))
+        {
+            if(origPtr != 0)
+            {
+                const auto it = m_Allocations.find(origPtr);
+                if(it != m_Allocations.end())
+                {
+                    if(it->second.allocation)
+                    {
+                        vmaUnmapMemory(m_Allocator, it->second.allocation);
+                    }
+                    else
+                    {
+                        if(IssueWarning())
+                        {
+                            printf("Line %zu: Cannot call vmaUnmapMemory - allocation is null.\n", lineNumber);
+                        }
+                    }
+                }
+                else
+                {
+                    if(IssueWarning())
+                    {
+                        printf("Line %zu: Allocation %llX not found.\n", lineNumber, origPtr);
+                    }
+                }
+            }
+        }
+        else
+        {
+            if(IssueWarning())
+            {
+                printf("Line %zu: Invalid parameters for vmaMapMemory.\n", lineNumber);
+            }
+        }
+    }
+}
+
+void Player::ExecuteFlushAllocation(size_t lineNumber, const CsvSplit& csvSplit)
+{
+    m_Stats.RegisterFunctionCall(VMA_FUNCTION::FlushAllocation);
+
+    if(ValidateFunctionParameterCount(lineNumber, csvSplit, 3, false))
+    {
+        uint64_t origPtr = 0;
+        uint64_t offset = 0;
+        uint64_t size = 0;
+
+        if(StrRangeToPtr(csvSplit.GetRange(FIRST_PARAM_INDEX), origPtr) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 1), offset) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 2), size))
+        {
+            if(origPtr != 0)
+            {
+                const auto it = m_Allocations.find(origPtr);
+                if(it != m_Allocations.end())
+                {
+                    if(it->second.allocation)
+                    {
+                        vmaFlushAllocation(m_Allocator, it->second.allocation, offset, size);
+                    }
+                    else
+                    {
+                        if(IssueWarning())
+                        {
+                            printf("Line %zu: Cannot call vmaFlushAllocation - allocation is null.\n", lineNumber);
+                        }
+                    }
+                }
+                else
+                {
+                    if(IssueWarning())
+                    {
+                        printf("Line %zu: Allocation %llX not found.\n", lineNumber, origPtr);
+                    }
+                }
+            }
+        }
+        else
+        {
+            if(IssueWarning())
+            {
+                printf("Line %zu: Invalid parameters for vmaFlushAllocation.\n", lineNumber);
+            }
+        }
+    }
+}
+
+void Player::ExecuteInvalidateAllocation(size_t lineNumber, const CsvSplit& csvSplit)
+{
+    m_Stats.RegisterFunctionCall(VMA_FUNCTION::InvalidateAllocation);
+
+    if(ValidateFunctionParameterCount(lineNumber, csvSplit, 3, false))
+    {
+        uint64_t origPtr = 0;
+        uint64_t offset = 0;
+        uint64_t size = 0;
+
+        if(StrRangeToPtr(csvSplit.GetRange(FIRST_PARAM_INDEX), origPtr) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 1), offset) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 2), size))
+        {
+            if(origPtr != 0)
+            {
+                const auto it = m_Allocations.find(origPtr);
+                if(it != m_Allocations.end())
+                {
+                    if(it->second.allocation)
+                    {
+                        vmaInvalidateAllocation(m_Allocator, it->second.allocation, offset, size);
+                    }
+                    else
+                    {
+                        if(IssueWarning())
+                        {
+                            printf("Line %zu: Cannot call vmaInvalidateAllocation - allocation is null.\n", lineNumber);
+                        }
+                    }
+                }
+                else
+                {
+                    if(IssueWarning())
+                    {
+                        printf("Line %zu: Allocation %llX not found.\n", lineNumber, origPtr);
+                    }
+                }
+            }
+        }
+        else
+        {
+            if(IssueWarning())
+            {
+                printf("Line %zu: Invalid parameters for vmaInvalidateAllocation.\n", lineNumber);
+            }
+        }
+    }
+}
+
+void Player::ExecuteTouchAllocation(size_t lineNumber, const CsvSplit& csvSplit)
+{
+    m_Stats.RegisterFunctionCall(VMA_FUNCTION::TouchAllocation);
+
+    if(ValidateFunctionParameterCount(lineNumber, csvSplit, 1, false))
+    {
+        uint64_t origPtr = 0;
+        if(StrRangeToPtr(csvSplit.GetRange(FIRST_PARAM_INDEX), origPtr))
+        {
+            const auto it = m_Allocations.find(origPtr);
+            if(it != m_Allocations.end())
+            {
+                if(it->second.allocation)
+                {
+                    vmaTouchAllocation(m_Allocator, it->second.allocation);
+                }
+                else
+                {
+                    if(IssueWarning())
+                    {
+                        printf("Line %zu: Cannot call vmaTouchAllocation - allocation is null.\n", lineNumber);
+                    }
+                }
+            }
+            else
+            {
+                if(IssueWarning())
+                {
+                    printf("Line %zu: Allocation %llX not found.\n", lineNumber, origPtr);
+                }
+            }
+        }
+        else
+        {
+            if(IssueWarning())
+            {
+                printf("Line %zu: Invalid parameters for vmaTouchAllocation.\n", lineNumber);
+            }
+        }
+    }
+}
+
+void Player::ExecuteGetAllocationInfo(size_t lineNumber, const CsvSplit& csvSplit)
+{
+    m_Stats.RegisterFunctionCall(VMA_FUNCTION::GetAllocationInfo);
+
+    if(ValidateFunctionParameterCount(lineNumber, csvSplit, 1, false))
+    {
+        uint64_t origPtr = 0;
+        if(StrRangeToPtr(csvSplit.GetRange(FIRST_PARAM_INDEX), origPtr))
+        {
+            const auto it = m_Allocations.find(origPtr);
+            if(it != m_Allocations.end())
+            {
+                if(it->second.allocation)
+                {
+                    VmaAllocationInfo allocInfo;
+                    vmaGetAllocationInfo(m_Allocator, it->second.allocation, &allocInfo);
+                }
+                else
+                {
+                    if(IssueWarning())
+                    {
+                        printf("Line %zu: Cannot call vmaGetAllocationInfo - allocation is null.\n", lineNumber);
+                    }
+                }
+            }
+            else
+            {
+                if(IssueWarning())
+                {
+                    printf("Line %zu: Allocation %llX not found.\n", lineNumber, origPtr);
+                }
+            }
+        }
+        else
+        {
+            if(IssueWarning())
+            {
+                printf("Line %zu: Invalid parameters for vmaGetAllocationInfo.\n", lineNumber);
+            }
+        }
+    }
+}
+
+void Player::ExecuteMakePoolAllocationsLost(size_t lineNumber, const CsvSplit& csvSplit)
+{
+    m_Stats.RegisterFunctionCall(VMA_FUNCTION::MakePoolAllocationsLost);
+
+    if(ValidateFunctionParameterCount(lineNumber, csvSplit, 1, false))
+    {
+        uint64_t origPtr = 0;
+
+        if(StrRangeToPtr(csvSplit.GetRange(FIRST_PARAM_INDEX), origPtr))
+        {
+            if(origPtr != 0)
+            {
+                const auto it = m_Pools.find(origPtr);
+                if(it != m_Pools.end())
+                {
+                    vmaMakePoolAllocationsLost(m_Allocator, it->second.pool, nullptr);
+                    UpdateMemStats();
+                }
+                else
+                {
+                    if(IssueWarning())
+                    {
+                        printf("Line %zu: Pool %llX not found.\n", lineNumber, origPtr);
+                    }
+                }
+            }
+        }
+        else
+        {
+            if(IssueWarning())
+            {
+                printf("Line %zu: Invalid parameters for vmaMakePoolAllocationsLost.\n", lineNumber);
+            }
+        }
+    }
+}
+
+void Player::ExecuteResizeAllocation(size_t lineNumber, const CsvSplit& csvSplit)
+{
+    m_Stats.RegisterFunctionCall(VMA_FUNCTION::ResizeAllocation);
+
+    if(ValidateFunctionParameterCount(lineNumber, csvSplit, 2, false))
+    {
+        uint64_t origPtr = 0;
+        uint64_t newSize = 0;
+
+        if(StrRangeToPtr(csvSplit.GetRange(FIRST_PARAM_INDEX), origPtr) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 1), newSize))
+        {
+            if(origPtr != 0)
+            {
+                const auto it = m_Allocations.find(origPtr);
+                if(it != m_Allocations.end())
+                {
+                    vmaResizeAllocation(m_Allocator, it->second.allocation, newSize);
+                    UpdateMemStats();
+                }
+                else
+                {
+                    if(IssueWarning())
+                    {
+                        printf("Line %zu: Allocation %llX not found.\n", lineNumber, origPtr);
+                    }
+                }
+            }
+        }
+        else
+        {
+            if(IssueWarning())
+            {
+                printf("Line %zu: Invalid parameters for vmaResizeAllocation.\n", lineNumber);
+            }
+        }
+    }
+}
+
+void Player::ExecuteDefragmentationBegin(size_t lineNumber, const CsvSplit& csvSplit)
+{
+    m_Stats.RegisterFunctionCall(VMA_FUNCTION::DefragmentationBegin);
+
+    if(ValidateFunctionParameterCount(lineNumber, csvSplit, 9, false))
+    {
+        VmaDefragmentationInfo2 defragInfo = {};
+        std::vector<uint64_t> allocationOrigPtrs;
+        std::vector<uint64_t> poolOrigPtrs;
+        uint64_t cmdBufOrigPtr = 0;
+        uint64_t defragCtxOrigPtr = 0;
+
+        if(StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX), defragInfo.flags) &&
+            StrRangeToPtrList(csvSplit.GetRange(FIRST_PARAM_INDEX + 1), allocationOrigPtrs) &&
+            StrRangeToPtrList(csvSplit.GetRange(FIRST_PARAM_INDEX + 2), poolOrigPtrs) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 3), defragInfo.maxCpuBytesToMove) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 4), defragInfo.maxCpuAllocationsToMove) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 5), defragInfo.maxGpuBytesToMove) &&
+            StrRangeToUint(csvSplit.GetRange(FIRST_PARAM_INDEX + 6), defragInfo.maxGpuAllocationsToMove) &&
+            StrRangeToPtr(csvSplit.GetRange(FIRST_PARAM_INDEX + 7), cmdBufOrigPtr) &&
+            StrRangeToPtr(csvSplit.GetRange(FIRST_PARAM_INDEX + 8), defragCtxOrigPtr))
+        {
+            const size_t allocationOrigPtrCount = allocationOrigPtrs.size();
+            std::vector<VmaAllocation> allocations;
+            allocations.reserve(allocationOrigPtrCount);
+            for(size_t i = 0; i < allocationOrigPtrCount; ++i)
+            {
+                const auto it = m_Allocations.find(allocationOrigPtrs[i]);
+                if(it != m_Allocations.end() && it->second.allocation)
+                {
+                    allocations.push_back(it->second.allocation);
+                }
+            }
+            if(!allocations.empty())
+            {
+                defragInfo.allocationCount = (uint32_t)allocations.size();
+                defragInfo.pAllocations = allocations.data();
+            }
+
+            const size_t poolOrigPtrCount = poolOrigPtrs.size();
+            std::vector<VmaPool> pools;
+            pools.reserve(poolOrigPtrCount);
+            for(size_t i = 0; i < poolOrigPtrCount; ++i)
+            {
+                const auto it = m_Pools.find(poolOrigPtrs[i]);
+                if(it != m_Pools.end() && it->second.pool)
+                {
+                    pools.push_back(it->second.pool);
+                }
+            }
+            if(!pools.empty())
+            {
+                defragInfo.poolCount = (uint32_t)pools.size();
+                defragInfo.pPools = pools.data();
+            }
+
+            if(allocations.size() != allocationOrigPtrCount ||
+                pools.size() != poolOrigPtrCount)
+            {
+                if(IssueWarning())
+                {
+                    printf("Line %zu: Passing %zu allocations and %zu pools to vmaDefragmentationBegin, while originally %zu allocations and %zu pools were passed.\n",
+                        lineNumber,
+                        allocations.size(), pools.size(),
+                        allocationOrigPtrCount, poolOrigPtrCount);
+                }
+            }
+
+            if(cmdBufOrigPtr)
+            {
+                VkCommandBufferBeginInfo cmdBufBeginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
+                cmdBufBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
+                VkResult res = vkBeginCommandBuffer(m_CommandBuffer, &cmdBufBeginInfo);
+                if(res == VK_SUCCESS)
+                {
+                    defragInfo.commandBuffer = m_CommandBuffer;
+                }
+                else
+                {
+                    printf("Line %zu: vkBeginCommandBuffer failed (%d)\n", lineNumber, res);
+                }
+            }
+
+            m_Stats.RegisterDefragmentation(defragInfo);
+
+            VmaDefragmentationContext defragCtx = nullptr;
+            VkResult res = vmaDefragmentationBegin(m_Allocator, &defragInfo, nullptr, &defragCtx);
+
+            if(defragInfo.commandBuffer)
+            {
+                vkEndCommandBuffer(m_CommandBuffer);
+
+                VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO };
+                submitInfo.commandBufferCount = 1;
+                submitInfo.pCommandBuffers = &m_CommandBuffer;
+                vkQueueSubmit(m_TransferQueue, 1, &submitInfo, VK_NULL_HANDLE);
+                vkQueueWaitIdle(m_TransferQueue);
+            }
+
+            if(res >= VK_SUCCESS)
+            {
+                if(defragCtx)
+                {
+                    if(defragCtxOrigPtr)
+                    {
+                        // We have defragmentation context, originally had defragmentation context: Store it.
+                        m_DefragmentationContexts[defragCtxOrigPtr] = defragCtx;
+                    }
+                    else
+                    {
+                        // We have defragmentation context, originally it was null: End immediately.
+                        vmaDefragmentationEnd(m_Allocator, defragCtx);
+                    }
+                }
+                else
+                {
+                    if(defragCtxOrigPtr)
+                    {
+                        // We have no defragmentation context, originally there was one: Store null.
+                        m_DefragmentationContexts[defragCtxOrigPtr] = nullptr;
+                    }
+                    else
+                    {
+                        // We have no defragmentation context, originally there wasn't as well - nothing to do.
+                    }
+                }
+            }
+            else
+            {
+                if(defragCtxOrigPtr)
+                {
+                    // Currently failed, originally succeeded.
+                    if(IssueWarning())
+                    {
+                        printf("Line %zu: vmaDefragmentationBegin failed (%d), while originally succeeded.\n", lineNumber, res);
+                    }
+                }
+                else
+                {
+                    // Currently failed, originally don't know.
+                    if(IssueWarning())
+                    {
+                        printf("Line %zu: vmaDefragmentationBegin failed (%d).\n", lineNumber, res);
+                    }
+                }
+            }
+        }
+        else
+        {
+            if(IssueWarning())
+            {
+                printf("Line %zu: Invalid parameters for vmaDefragmentationBegin.\n", lineNumber);
+            }
+        }
+    }
+}
+
+void Player::ExecuteDefragmentationEnd(size_t lineNumber, const CsvSplit& csvSplit)
+{
+    m_Stats.RegisterFunctionCall(VMA_FUNCTION::DefragmentationEnd);
+
+    if(ValidateFunctionParameterCount(lineNumber, csvSplit, 1, false))
+    {
+        uint64_t origPtr = 0;
+
+        if(StrRangeToPtr(csvSplit.GetRange(FIRST_PARAM_INDEX), origPtr))
+        {
+            if(origPtr != 0)
+            {
+                const auto it = m_DefragmentationContexts.find(origPtr);
+                if(it != m_DefragmentationContexts.end())
+                {
+                    vmaDefragmentationEnd(m_Allocator, it->second);
+                    m_DefragmentationContexts.erase(it);
+                }
+                else
+                {
+                    if(IssueWarning())
+                    {
+                        printf("Line %zu: Defragmentation context %llX not found.\n", lineNumber, origPtr);
+                    }
+                }
+            }
+        }
+        else
+        {
+            if(IssueWarning())
+            {
+                printf("Line %zu: Invalid parameters for vmaDefragmentationEnd.\n", lineNumber);
+            }
+        }
+    }
+}
+
+void Player::ExecuteSetPoolName(size_t lineNumber, const CsvSplit& csvSplit)
+{
+    m_Stats.RegisterFunctionCall(VMA_FUNCTION::SetPoolName);
+
+    if(!g_UserDataEnabled)
+    {
+        return;
+    }
+
+    if(ValidateFunctionParameterCount(lineNumber, csvSplit, 2, true))
+    {
+        uint64_t origPtr = 0;
+        if(StrRangeToPtr(csvSplit.GetRange(FIRST_PARAM_INDEX), origPtr))
+        {
+            if(origPtr != 0)
+            {
+                const auto it = m_Pools.find(origPtr);
+                if(it != m_Pools.end())
+                {
+                    std::string poolName;
+                    csvSplit.GetRange(FIRST_PARAM_INDEX + 1).to_str(poolName);
+                    vmaSetPoolName(m_Allocator, it->second.pool, !poolName.empty() ? poolName.c_str() : nullptr);
+                }
+                else
+                {
+                    if(IssueWarning())
+                    {
+                        printf("Line %zu: Pool %llX not found.\n", lineNumber, origPtr);
+                    }
+                }
+            }
+        }
+        else
+        {
+            if(IssueWarning())
+            {
+                printf("Line %zu: Invalid parameters for vmaSetPoolName.\n", lineNumber);
+            }
+        }
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Main functions
+
+static void PrintCommandLineSyntax()
+{
+    printf(
+        "Command line syntax:\n"
+        "    VmaReplay [Options] <SrcFile.csv>\n"
+        "Available options:\n"
+        "    -v <Number> - Verbosity level:\n"
+        "        0 - Minimum verbosity. Prints only warnings and errors.\n"
+        "        1 - Default verbosity. Prints important messages and statistics.\n"
+        "        2 - Maximum verbosity. Prints a lot of information.\n"
+        "    -i <Number> - Repeat playback given number of times (iterations)\n"
+        "        Default is 1. Vulkan is reinitialized with every iteration.\n"
+        "    --MemStats <Value> - 0 to disable or 1 to enable memory statistics.\n"
+        "        Default is 0. Enabling it may negatively impact playback performance.\n"
+        "    --DumpStatsAfterLine <Line> - Dump VMA statistics to JSON file after specified source file line finishes execution.\n"
+        "        File is written to current directory with name: VmaReplay_Line####.json.\n"
+        "        This parameter can be repeated.\n"
+        "    --DumpDetailedStatsAfterLine <Line> - Like command above, but includes detailed map.\n"
+        "    --DefragmentAfterLine <Line> - Defragment memory after specified source file line and print statistics.\n"
+        "        It also prints detailed statistics to files VmaReplay_Line####_Defragment*.json\n"
+        "    --DefragmentationFlags <Flags> - Flags to be applied when using DefragmentAfterLine.\n"
+        "    --Lines <Ranges> - Replay only limited set of lines from file\n"
+        "        Ranges is comma-separated list of ranges, e.g. \"-10,15,18-25,31-\".\n"
+        "    --PhysicalDevice <Index> - Choice of Vulkan physical device. Default: 0.\n"
+        "    --UserData <Value> - 0 to disable or 1 to enable setting pUserData during playback.\n"
+        "        Default is 1. Affects both creation of buffers and images, as well as calls to vmaSetAllocationUserData.\n"
+        "    --VK_LAYER_LUNARG_standard_validation <Value> - 0 to disable or 1 to enable validation layers.\n"
+        "        By default the layers are silently enabled if available.\n"
+        "    --VK_EXT_memory_budget <Value> - 0 to disable or 1 to enable this extension.\n"
+        "        By default the extension is silently enabled if available.\n"
+    );
+}
+
+static int ProcessFile(size_t iterationIndex, const char* data, size_t numBytes, duration& outDuration)
+{
+    outDuration = duration::max();
+
+    const bool useLineRanges = !g_LineRanges.IsEmpty();
+    const bool useDumpStatsAfterLine = !g_DumpStatsAfterLine.empty();
+    const bool useDefragmentAfterLine = !g_DefragmentAfterLine.empty();
+
+    LineSplit lineSplit(data, numBytes);
+    StrRange line;
+
+    if(!lineSplit.GetNextLine(line) ||
+        !StrRangeEq(line, "Vulkan Memory Allocator,Calls recording"))
+    {
+        printf("ERROR: Incorrect file format.\n");
+        return RESULT_ERROR_FORMAT;
+    }
+
+    if(!lineSplit.GetNextLine(line) || !ParseFileVersion(line) || !ValidateFileVersion())
+    {
+        printf("ERROR: Incorrect file format version.\n");
+        return RESULT_ERROR_FORMAT;
+    }
+
+    if(g_Verbosity == VERBOSITY::MAXIMUM)
+    {
+        printf("Format version: %u,%u\n",
+            GetVersionMajor(g_FileVersion),
+            GetVersionMinor(g_FileVersion));
+    }
+
+    // Parse configuration
+    const bool configEnabled = g_FileVersion >= MakeVersion(1, 3);
+    ConfigurationParser configParser;
+    if(configEnabled)
+    {
+        if(!configParser.Parse(lineSplit))
+        {
+            return RESULT_ERROR_FORMAT;
+        }
+    }
+
+    Player player;
+    int result = player.Init();
+
+    if(configEnabled)
+    {
+        player.ApplyConfig(configParser);
+    }
+
+    size_t executedLineCount = 0;
+    if(result == 0)
+    {
+        if(g_Verbosity > VERBOSITY::MINIMUM)
+        {
+            if(useLineRanges)
+            {
+                printf("Playing #%zu (limited range of lines)...\n", iterationIndex + 1);
+            }
+            else
+            {
+                printf("Playing #%zu...\n", iterationIndex + 1);
+            }
+        }
+
+        const time_point timeBeg = std::chrono::high_resolution_clock::now();
+
+        while(lineSplit.GetNextLine(line))
+        {
+            const size_t currLineNumber = lineSplit.GetNextLineIndex();
+
+            bool execute = true;
+            if(useLineRanges)
+            {
+                execute = g_LineRanges.Includes(currLineNumber);
+            }
+
+            if(execute)
+            {
+                player.ExecuteLine(currLineNumber, line);
+                ++executedLineCount;
+            }
+
+            while(useDumpStatsAfterLine &&
+                g_DumpStatsAfterLineNextIndex < g_DumpStatsAfterLine.size() &&
+                currLineNumber >= g_DumpStatsAfterLine[g_DumpStatsAfterLineNextIndex].line)
+            {
+                const size_t requestedLine = g_DumpStatsAfterLine[g_DumpStatsAfterLineNextIndex].line;
+                const bool detailed = g_DumpStatsAfterLine[g_DumpStatsAfterLineNextIndex].detailed;
+                
+                if(g_Verbosity == VERBOSITY::MAXIMUM)
+                {
+                    printf("Dumping %sstats after line %zu actual line %zu...\n",
+                        detailed ? "detailed " : "",
+                        requestedLine,
+                        currLineNumber);
+                }
+
+                player.DumpStats("VmaReplay_Line%04zu.json", requestedLine, detailed);
+                
+                ++g_DumpStatsAfterLineNextIndex;
+            }
+
+            while(useDefragmentAfterLine &&
+                g_DefragmentAfterLineNextIndex < g_DefragmentAfterLine.size() &&
+                currLineNumber >= g_DefragmentAfterLine[g_DefragmentAfterLineNextIndex])
+            {
+                const size_t requestedLine = g_DefragmentAfterLine[g_DefragmentAfterLineNextIndex];
+                if(g_Verbosity >= VERBOSITY::DEFAULT)
+                {
+                    printf("Defragmenting after line %zu actual line %zu...\n",
+                        requestedLine,
+                        currLineNumber);
+                }
+
+                player.DumpStats("VmaReplay_Line%04zu_Defragment_1Before.json", requestedLine, true);
+                player.Defragment();
+                player.DumpStats("VmaReplay_Line%04zu_Defragment_2After.json", requestedLine, true);
+                
+                ++g_DefragmentAfterLineNextIndex;
+            }
+        }
+
+        const duration playDuration = std::chrono::high_resolution_clock::now() - timeBeg;
+        outDuration = playDuration;
+
+        // End stats.
+        if(g_Verbosity > VERBOSITY::MINIMUM)
+        {
+            std::string playDurationStr;
+            SecondsToFriendlyStr(ToFloatSeconds(playDuration), playDurationStr);
+
+            printf("Done.\n");
+            printf("Playback took: %s\n", playDurationStr.c_str());
+        }
+        if(g_Verbosity == VERBOSITY::MAXIMUM)
+        {
+            printf("File lines: %zu\n", lineSplit.GetNextLineIndex());
+            printf("Executed %zu file lines\n", executedLineCount);
+        }
+
+        player.PrintStats();
+    }
+
+    return result;
+}
+
+static int ProcessFile()
+{
+    if(g_Verbosity > VERBOSITY::MINIMUM)
+    {
+        printf("Loading file \"%s\"...\n", g_FilePath.c_str());
+    }
+    int result = 0;
+
+    FILE* file = nullptr;
+    const errno_t err = fopen_s(&file, g_FilePath.c_str(), "rb");
+    if(err == 0)
+    {
+        _fseeki64(file, 0, SEEK_END);
+        const size_t fileSize = (size_t)_ftelli64(file);
+        _fseeki64(file, 0, SEEK_SET);
+
+        if(fileSize > 0)
+        {
+            std::vector<char> fileContents(fileSize);
+            fread(fileContents.data(), 1, fileSize, file);
+
+            // Begin stats.
+            if(g_Verbosity == VERBOSITY::MAXIMUM)
+            {
+                printf("File size: %zu B\n", fileSize);
+            }
+
+            duration durationSum = duration::zero();
+            for(size_t i = 0; i < g_IterationCount; ++i)
+            {
+                duration currDuration;
+                ProcessFile(i, fileContents.data(), fileContents.size(), currDuration);
+                durationSum += currDuration;
+            }
+
+            if(g_IterationCount > 1)
+            {
+                std::string playDurationStr;
+                SecondsToFriendlyStr(ToFloatSeconds(durationSum / g_IterationCount), playDurationStr);
+                printf("Average playback time from %zu iterations: %s\n", g_IterationCount, playDurationStr.c_str());
+            }
+        }
+        else
+        {
+            printf("ERROR: Source file is empty.\n");
+            result = RESULT_ERROR_SOURCE_FILE;
+        }
+
+        fclose(file);
+    }
+    else
+    {
+        printf("ERROR: Couldn't open file (%i).\n", err);
+        result = RESULT_ERROR_SOURCE_FILE;
+    }
+
+    return result;
+}
+
+static int main2(int argc, char** argv)
+{
+    CmdLineParser cmdLineParser(argc, argv);
+
+    cmdLineParser.RegisterOpt(CMD_LINE_OPT_VERBOSITY, 'v', true);
+    cmdLineParser.RegisterOpt(CMD_LINE_OPT_ITERATIONS, 'i', true);
+    cmdLineParser.RegisterOpt(CMD_LINE_OPT_LINES, "Lines", true);
+    cmdLineParser.RegisterOpt(CMD_LINE_OPT_PHYSICAL_DEVICE, "PhysicalDevice", true);
+    cmdLineParser.RegisterOpt(CMD_LINE_OPT_USER_DATA, "UserData", true);
+    cmdLineParser.RegisterOpt(CMD_LINE_OPT_VK_EXT_MEMORY_BUDGET, "VK_EXT_memory_budget", true);
+    cmdLineParser.RegisterOpt(CMD_LINE_OPT_VK_LAYER_LUNARG_STANDARD_VALIDATION, VALIDATION_LAYER_NAME, true);
+    cmdLineParser.RegisterOpt(CMD_LINE_OPT_MEM_STATS, "MemStats", true);
+    cmdLineParser.RegisterOpt(CMD_LINE_OPT_DUMP_STATS_AFTER_LINE, "DumpStatsAfterLine", true);
+    cmdLineParser.RegisterOpt(CMD_LINE_OPT_DEFRAGMENT_AFTER_LINE, "DefragmentAfterLine", true);
+    cmdLineParser.RegisterOpt(CMD_LINE_OPT_DEFRAGMENTATION_FLAGS, "DefragmentationFlags", true);
+    cmdLineParser.RegisterOpt(CMD_LINE_OPT_DUMP_DETAILED_STATS_AFTER_LINE, "DumpDetailedStatsAfterLine", true);
+
+    CmdLineParser::RESULT res;
+    while((res = cmdLineParser.ReadNext()) != CmdLineParser::RESULT_END)
+    {
+        switch(res)
+        {
+        case CmdLineParser::RESULT_OPT:
+            switch(cmdLineParser.GetOptId())
+            {
+            case CMD_LINE_OPT_VERBOSITY:
+                {
+                    uint32_t verbosityVal = UINT32_MAX;
+                    if(StrRangeToUint(StrRange(cmdLineParser.GetParameter()), verbosityVal) &&
+                        verbosityVal < (uint32_t)VERBOSITY::COUNT)
+                    {
+                        g_Verbosity = (VERBOSITY)verbosityVal;
+                    }
+                    else
+                    {
+                        PrintCommandLineSyntax();
+                        return RESULT_ERROR_COMMAND_LINE;
+                    }
+                }
+                break;
+            case CMD_LINE_OPT_ITERATIONS:
+                if(!StrRangeToUint(StrRange(cmdLineParser.GetParameter()), g_IterationCount))
+                {
+                    PrintCommandLineSyntax();
+                    return RESULT_ERROR_COMMAND_LINE;
+                }
+                break;
+            case CMD_LINE_OPT_LINES:
+                if(!g_LineRanges.Parse(StrRange(cmdLineParser.GetParameter())))
+                {
+                    PrintCommandLineSyntax();
+                    return RESULT_ERROR_COMMAND_LINE;
+                }
+                break;
+            case CMD_LINE_OPT_PHYSICAL_DEVICE:
+                if(!StrRangeToUint(StrRange(cmdLineParser.GetParameter()), g_PhysicalDeviceIndex))
+                {
+                    PrintCommandLineSyntax();
+                    return RESULT_ERROR_COMMAND_LINE;
+                }
+                break;
+            case CMD_LINE_OPT_USER_DATA:
+                if(!StrRangeToBool(StrRange(cmdLineParser.GetParameter()), g_UserDataEnabled))
+                {
+                    PrintCommandLineSyntax();
+                    return RESULT_ERROR_COMMAND_LINE;
+                }
+                break;
+            case CMD_LINE_OPT_VK_EXT_MEMORY_BUDGET:
+                {
+                    bool newValue;
+                    if(StrRangeToBool(StrRange(cmdLineParser.GetParameter()), newValue))
+                    {
+                        g_VK_EXT_memory_budget_request = newValue ?
+                            VULKAN_EXTENSION_REQUEST::ENABLED :
+                            VULKAN_EXTENSION_REQUEST::DISABLED;
+                    }
+                    else
+                    {
+                        PrintCommandLineSyntax();
+                        return RESULT_ERROR_COMMAND_LINE;
+                    }
+                }
+                break;
+            case CMD_LINE_OPT_VK_LAYER_LUNARG_STANDARD_VALIDATION:
+                {
+                    bool newValue;
+                    if(StrRangeToBool(StrRange(cmdLineParser.GetParameter()), newValue))
+                    {
+                        g_VK_LAYER_LUNARG_standard_validation = newValue ?
+                            VULKAN_EXTENSION_REQUEST::ENABLED :
+                            VULKAN_EXTENSION_REQUEST::DISABLED;
+                    }
+                    else
+                    {
+                        PrintCommandLineSyntax();
+                        return RESULT_ERROR_COMMAND_LINE;
+                    }
+                }
+                break;
+            case CMD_LINE_OPT_MEM_STATS:
+                if(!StrRangeToBool(StrRange(cmdLineParser.GetParameter()), g_MemStatsEnabled))
+                {
+                    PrintCommandLineSyntax();
+                    return RESULT_ERROR_COMMAND_LINE;
+                }
+                break;
+            case CMD_LINE_OPT_DUMP_STATS_AFTER_LINE:
+            case CMD_LINE_OPT_DUMP_DETAILED_STATS_AFTER_LINE:
+                {
+                    size_t line;
+                    if(StrRangeToUint(StrRange(cmdLineParser.GetParameter()), line))
+                    {
+                        const bool detailed =
+                            cmdLineParser.GetOptId() == CMD_LINE_OPT_DUMP_DETAILED_STATS_AFTER_LINE;
+                        g_DumpStatsAfterLine.push_back({line, detailed});
+                    }
+                    else
+                    {
+                        PrintCommandLineSyntax();
+                        return RESULT_ERROR_COMMAND_LINE;
+                    }
+                }
+                break;
+            case CMD_LINE_OPT_DEFRAGMENT_AFTER_LINE:
+                {
+                    size_t line;
+                    if(StrRangeToUint(StrRange(cmdLineParser.GetParameter()), line))
+                    {
+                        g_DefragmentAfterLine.push_back(line);
+                    }
+                    else
+                    {
+                        PrintCommandLineSyntax();
+                        return RESULT_ERROR_COMMAND_LINE;
+                    }
+                }
+                break;
+            case CMD_LINE_OPT_DEFRAGMENTATION_FLAGS:
+                {
+                    if(!StrRangeToUint(StrRange(cmdLineParser.GetParameter()), g_DefragmentationFlags))
+                    {
+                        PrintCommandLineSyntax();
+                        return RESULT_ERROR_COMMAND_LINE;
+                    }
+                }
+                break;
+            default:
+                assert(0);
+            }
+            break;
+        case CmdLineParser::RESULT_PARAMETER:
+            if(g_FilePath.empty())
+            {
+                g_FilePath = cmdLineParser.GetParameter();
+            }
+            else
+            {
+                PrintCommandLineSyntax();
+                return RESULT_ERROR_COMMAND_LINE;
+            }
+            break;
+        case CmdLineParser::RESULT_ERROR:
+            PrintCommandLineSyntax();
+            return RESULT_ERROR_COMMAND_LINE;
+            break;
+        default:
+            assert(0);
+        }
+    }
+
+    // Postprocess command line parameters.
+
+    if(g_FilePath.empty())
+    {
+        PrintCommandLineSyntax();
+        return RESULT_ERROR_COMMAND_LINE;
+    }
+
+    // Sort g_DumpStatsAfterLine and make unique.
+    std::sort(g_DumpStatsAfterLine.begin(), g_DumpStatsAfterLine.end());
+    g_DumpStatsAfterLine.erase(
+        std::unique(g_DumpStatsAfterLine.begin(), g_DumpStatsAfterLine.end()),
+        g_DumpStatsAfterLine.end());
+
+    // Sort g_DefragmentAfterLine and make unique.
+    std::sort(g_DefragmentAfterLine.begin(), g_DefragmentAfterLine.end());
+    g_DefragmentAfterLine.erase(
+        std::unique(g_DefragmentAfterLine.begin(), g_DefragmentAfterLine.end()),
+        g_DefragmentAfterLine.end());
+
+    return ProcessFile();
+}
+
+int main(int argc, char** argv)
+{
+    try
+    {
+        return main2(argc, argv);
+    }
+    catch(const std::exception& e)
+    {
+        printf("ERROR: %s\n", e.what());
+        return RESULT_EXCEPTION;
+    }
+    catch(...)
+    {
+        printf("UNKNOWN ERROR\n");
+        return RESULT_EXCEPTION;
+    }
+}
diff --git a/third_party/VulkanMemoryAllocator/src/VmaReplay/VmaUsage.cpp b/third_party/VulkanMemoryAllocator/src/VmaReplay/VmaUsage.cpp
new file mode 100644
index 0000000..f2a1447
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/src/VmaReplay/VmaUsage.cpp
@@ -0,0 +1,24 @@
+//
+// Copyright (c) 2017-2020 Advanced Micro Devices, Inc. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#define VMA_IMPLEMENTATION
+#include "VmaUsage.h"
diff --git a/third_party/VulkanMemoryAllocator/src/VmaReplay/VmaUsage.h b/third_party/VulkanMemoryAllocator/src/VmaReplay/VmaUsage.h
new file mode 100644
index 0000000..47b3f51
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/src/VmaReplay/VmaUsage.h
@@ -0,0 +1,50 @@
+//
+// Copyright (c) 2017-2020 Advanced Micro Devices, Inc. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#pragma once
+
+#define NOMINMAX
+#define WIN32_LEAN_AND_MEAN
+#include <Windows.h>
+
+#define VK_USE_PLATFORM_WIN32_KHR
+#include <vulkan/vulkan.h>
+
+//#define VMA_USE_STL_CONTAINERS 1
+
+//#define VMA_HEAVY_ASSERT(expr) assert(expr)
+
+//#define VMA_DEDICATED_ALLOCATION 0
+
+//#define VMA_DEBUG_MARGIN 16
+//#define VMA_DEBUG_DETECT_CORRUPTION 1
+//#define VMA_DEBUG_INITIALIZE_ALLOCATIONS 1
+
+#pragma warning(push, 4)
+#pragma warning(disable: 4127) // conditional expression is constant
+#pragma warning(disable: 4100) // unreferenced formal parameter
+#pragma warning(disable: 4189) // local variable is initialized but not referenced
+#pragma warning(disable: 4324) // structure was padded due to alignment specifier
+
+#include "../vk_mem_alloc.h"
+
+#pragma warning(pop)
diff --git a/third_party/VulkanMemoryAllocator/src/VmaUsage.cpp b/third_party/VulkanMemoryAllocator/src/VmaUsage.cpp
new file mode 100644
index 0000000..12400db
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/src/VmaUsage.cpp
@@ -0,0 +1,30 @@
+//
+// Copyright (c) 2017-2020 Advanced Micro Devices, Inc. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+/*
+In exactly one CPP file define macro VMA_IMPLEMENTATION and then include
+vk_mem_alloc.h to include definitions of its internal implementation
+*/
+
+#define VMA_IMPLEMENTATION
+
+#include "VmaUsage.h"
diff --git a/third_party/VulkanMemoryAllocator/src/VmaUsage.h b/third_party/VulkanMemoryAllocator/src/VmaUsage.h
new file mode 100644
index 0000000..592e9aac
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/src/VmaUsage.h
@@ -0,0 +1,99 @@
+//
+// Copyright (c) 2017-2020 Advanced Micro Devices, Inc. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#ifndef VMA_USAGE_H_
+#define VMA_USAGE_H_
+
+#ifdef _WIN32
+
+#define NOMINMAX
+#define WIN32_LEAN_AND_MEAN
+#include <Windows.h>
+#define VK_USE_PLATFORM_WIN32_KHR
+
+#else  // #ifdef _WIN32
+
+#include <vulkan/vulkan.h>
+
+#endif  // #ifdef _WIN32
+
+#ifdef _MSVC_LANG
+
+// Uncomment to test including `vulkan.h` on your own before including VMA.
+//#include <vulkan/vulkan.h>
+
+/*
+In every place where you want to use Vulkan Memory Allocator, define appropriate
+macros if you want to configure the library and then include its header to
+include all public interface declarations. Example:
+*/
+
+//#define VMA_HEAVY_ASSERT(expr) assert(expr)
+//#define VMA_USE_STL_CONTAINERS 1
+//#define VMA_DEDICATED_ALLOCATION 0
+//#define VMA_DEBUG_MARGIN 16
+//#define VMA_DEBUG_DETECT_CORRUPTION 1
+//#define VMA_DEBUG_INITIALIZE_ALLOCATIONS 1
+//#define VMA_RECORDING_ENABLED 1
+//#define VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY 256
+//#define VMA_USE_STL_SHARED_MUTEX 0
+//#define VMA_DEBUG_GLOBAL_MUTEX 1
+//#define VMA_MEMORY_BUDGET 0
+
+//#define VMA_VULKAN_VERSION 1002000 // Vulkan 1.2
+#define VMA_VULKAN_VERSION 1001000 // Vulkan 1.1
+//#define VMA_VULKAN_VERSION 1000000 // Vulkan 1.0
+
+/*
+#define VMA_DEBUG_LOG(format, ...) do { \
+        printf(format, __VA_ARGS__); \
+        printf("\n"); \
+    } while(false)
+*/
+
+#pragma warning(push, 4)
+#pragma warning(disable: 4127) // conditional expression is constant
+#pragma warning(disable: 4100) // unreferenced formal parameter
+#pragma warning(disable: 4189) // local variable is initialized but not referenced
+#pragma warning(disable: 4324) // structure was padded due to alignment specifier
+
+#endif  // #ifdef _MSVC_LANG
+
+#ifdef __clang__
+    #pragma clang diagnostic push
+    #pragma clang diagnostic ignored "-Wtautological-compare" // comparison of unsigned expression < 0 is always false
+    #pragma clang diagnostic ignored "-Wunused-private-field"
+    #pragma clang diagnostic ignored "-Wunused-parameter"
+    #pragma clang diagnostic ignored "-Wmissing-field-initializers"
+#endif
+
+#include "vk_mem_alloc.h"
+
+#ifdef __clang__
+    #pragma clang diagnostic pop
+#endif
+
+#ifdef _MSVC_LANG
+    #pragma warning(pop)
+#endif
+
+#endif
diff --git a/third_party/VulkanMemoryAllocator/src/VulkanSample.cpp b/third_party/VulkanMemoryAllocator/src/VulkanSample.cpp
new file mode 100644
index 0000000..4510efa
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/src/VulkanSample.cpp
@@ -0,0 +1,2092 @@
+//
+// Copyright (c) 2017-2020 Advanced Micro Devices, Inc. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#ifdef _WIN32
+
+#include "SparseBindingTest.h"
+#include "Tests.h"
+#include "VmaUsage.h"
+#include "Common.h"
+#include <atomic>
+
+static const char* const SHADER_PATH1 = "./";
+static const char* const SHADER_PATH2 = "../bin/";
+static const wchar_t* const WINDOW_CLASS_NAME = L"VULKAN_MEMORY_ALLOCATOR_SAMPLE";
+static const char* const VALIDATION_LAYER_NAME = "VK_LAYER_LUNARG_standard_validation";
+static const char* const APP_TITLE_A =     "Vulkan Memory Allocator Sample 2.4.0";
+static const wchar_t* const APP_TITLE_W = L"Vulkan Memory Allocator Sample 2.4.0";
+
+static const bool VSYNC = true;
+static const uint32_t COMMAND_BUFFER_COUNT = 2;
+static void* const CUSTOM_CPU_ALLOCATION_CALLBACK_USER_DATA = (void*)(intptr_t)43564544;
+static const bool USE_CUSTOM_CPU_ALLOCATION_CALLBACKS = true;
+
+VkPhysicalDevice g_hPhysicalDevice;
+VkDevice g_hDevice;
+VmaAllocator g_hAllocator;
+VkInstance g_hVulkanInstance;
+bool g_MemoryAliasingWarningEnabled = true;
+
+bool g_EnableValidationLayer = true;
+bool VK_KHR_get_memory_requirements2_enabled = false;
+bool VK_KHR_get_physical_device_properties2_enabled = false;
+bool VK_KHR_dedicated_allocation_enabled = false;
+bool VK_KHR_bind_memory2_enabled = false;
+bool VK_EXT_memory_budget_enabled = false;
+bool VK_AMD_device_coherent_memory_enabled = false;
+bool VK_EXT_buffer_device_address_enabled = false;
+bool VK_KHR_buffer_device_address_enabled = false;
+bool g_SparseBindingEnabled = false;
+bool g_BufferDeviceAddressEnabled = false;
+
+// # Pointers to functions from extensions
+PFN_vkGetBufferDeviceAddressEXT g_vkGetBufferDeviceAddressEXT;
+
+static HINSTANCE g_hAppInstance;
+static HWND g_hWnd;
+static LONG g_SizeX = 1280, g_SizeY = 720;
+static VkSurfaceKHR g_hSurface;
+static VkQueue g_hPresentQueue;
+static VkSurfaceFormatKHR g_SurfaceFormat;
+static VkExtent2D g_Extent;
+static VkSwapchainKHR g_hSwapchain;
+static std::vector<VkImage> g_SwapchainImages;
+static std::vector<VkImageView> g_SwapchainImageViews;
+static std::vector<VkFramebuffer> g_Framebuffers;
+static VkCommandPool g_hCommandPool;
+static VkCommandBuffer g_MainCommandBuffers[COMMAND_BUFFER_COUNT];
+static VkFence g_MainCommandBufferExecutedFances[COMMAND_BUFFER_COUNT];
+VkFence g_ImmediateFence;
+static uint32_t g_NextCommandBufferIndex;
+static VkSemaphore g_hImageAvailableSemaphore;
+static VkSemaphore g_hRenderFinishedSemaphore;
+static uint32_t g_GraphicsQueueFamilyIndex = UINT_MAX;
+static uint32_t g_PresentQueueFamilyIndex = UINT_MAX;
+static uint32_t g_SparseBindingQueueFamilyIndex = UINT_MAX;
+static VkDescriptorSetLayout g_hDescriptorSetLayout;
+static VkDescriptorPool g_hDescriptorPool;
+static VkDescriptorSet g_hDescriptorSet; // Automatically destroyed with m_DescriptorPool.
+static VkSampler g_hSampler;
+static VkFormat g_DepthFormat;
+static VkImage g_hDepthImage;
+static VmaAllocation g_hDepthImageAlloc;
+static VkImageView g_hDepthImageView;
+
+static VkSurfaceCapabilitiesKHR g_SurfaceCapabilities;
+static std::vector<VkSurfaceFormatKHR> g_SurfaceFormats;
+static std::vector<VkPresentModeKHR> g_PresentModes;
+
+static PFN_vkCreateDebugReportCallbackEXT g_pvkCreateDebugReportCallbackEXT;
+static PFN_vkDebugReportMessageEXT g_pvkDebugReportMessageEXT;
+static PFN_vkDestroyDebugReportCallbackEXT g_pvkDestroyDebugReportCallbackEXT;
+static VkDebugReportCallbackEXT g_hCallback;
+
+static VkQueue g_hGraphicsQueue;
+VkQueue g_hSparseBindingQueue;
+VkCommandBuffer g_hTemporaryCommandBuffer;
+
+static VkPipelineLayout g_hPipelineLayout;
+static VkRenderPass g_hRenderPass;
+static VkPipeline g_hPipeline;
+
+static VkBuffer g_hVertexBuffer;
+static VmaAllocation g_hVertexBufferAlloc;
+static VkBuffer g_hIndexBuffer;
+static VmaAllocation g_hIndexBufferAlloc;
+static uint32_t g_VertexCount;
+static uint32_t g_IndexCount;
+
+static VkImage g_hTextureImage;
+static VmaAllocation g_hTextureImageAlloc;
+static VkImageView g_hTextureImageView;
+
+static std::atomic_uint32_t g_CpuAllocCount;
+
+static void* CustomCpuAllocation(
+    void* pUserData, size_t size, size_t alignment,
+    VkSystemAllocationScope allocationScope)
+{
+    assert(pUserData == CUSTOM_CPU_ALLOCATION_CALLBACK_USER_DATA);
+    void* const result = _aligned_malloc(size, alignment);
+    if(result)
+    {
+        ++g_CpuAllocCount;
+    }
+    return result;
+}
+
+static void* CustomCpuReallocation(
+    void* pUserData, void* pOriginal, size_t size, size_t alignment,
+    VkSystemAllocationScope allocationScope)
+{
+    assert(pUserData == CUSTOM_CPU_ALLOCATION_CALLBACK_USER_DATA);
+    void* const result = _aligned_realloc(pOriginal, size, alignment);
+    if(pOriginal && !result)
+    {
+        --g_CpuAllocCount;
+    }
+    else if(!pOriginal && result)
+    {
+        ++g_CpuAllocCount;
+    }
+    return result;
+}
+
+static void CustomCpuFree(void* pUserData, void* pMemory)
+{
+    assert(pUserData == CUSTOM_CPU_ALLOCATION_CALLBACK_USER_DATA);
+    if(pMemory)
+    {
+        const uint32_t oldAllocCount = g_CpuAllocCount.fetch_sub(1);
+        TEST(oldAllocCount > 0);
+        _aligned_free(pMemory);
+    }
+}
+
+static const VkAllocationCallbacks g_CpuAllocationCallbacks = {
+    CUSTOM_CPU_ALLOCATION_CALLBACK_USER_DATA, // pUserData
+    &CustomCpuAllocation, // pfnAllocation
+    &CustomCpuReallocation, // pfnReallocation
+    &CustomCpuFree // pfnFree
+};
+
+const VkAllocationCallbacks* g_Allocs;
+
+void BeginSingleTimeCommands()
+{
+    VkCommandBufferBeginInfo cmdBufBeginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
+    cmdBufBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
+    ERR_GUARD_VULKAN( vkBeginCommandBuffer(g_hTemporaryCommandBuffer, &cmdBufBeginInfo) );
+}
+
+void EndSingleTimeCommands()
+{
+    ERR_GUARD_VULKAN( vkEndCommandBuffer(g_hTemporaryCommandBuffer) );
+
+    VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO };
+    submitInfo.commandBufferCount = 1;
+    submitInfo.pCommandBuffers = &g_hTemporaryCommandBuffer;
+
+    ERR_GUARD_VULKAN( vkQueueSubmit(g_hGraphicsQueue, 1, &submitInfo, VK_NULL_HANDLE) );
+    ERR_GUARD_VULKAN( vkQueueWaitIdle(g_hGraphicsQueue) );
+}
+
+void LoadShader(std::vector<char>& out, const char* fileName)
+{
+    std::ifstream file(std::string(SHADER_PATH1) + fileName, std::ios::ate | std::ios::binary);
+    if(file.is_open() == false)
+        file.open(std::string(SHADER_PATH2) + fileName, std::ios::ate | std::ios::binary);
+    assert(file.is_open());
+    size_t fileSize = (size_t)file.tellg();
+    if(fileSize > 0)
+    {
+        out.resize(fileSize);
+        file.seekg(0);
+        file.read(out.data(), fileSize);
+        file.close();
+    }
+    else
+        out.clear();
+}
+
+VKAPI_ATTR VkBool32 VKAPI_CALL MyDebugReportCallback(
+    VkDebugReportFlagsEXT flags,
+    VkDebugReportObjectTypeEXT objectType,
+    uint64_t object,
+    size_t location,
+    int32_t messageCode,
+    const char* pLayerPrefix,
+    const char* pMessage,
+    void* pUserData)
+{
+    // "Non-linear image 0xebc91 is aliased with linear buffer 0xeb8e4 which may indicate a bug."
+    if(!g_MemoryAliasingWarningEnabled && flags == VK_DEBUG_REPORT_WARNING_BIT_EXT &&
+        (strstr(pMessage, " is aliased with non-linear ") || strstr(pMessage, " is aliased with linear ")))
+    {
+        return VK_FALSE;
+    }
+
+    // Ignoring because when VK_KHR_dedicated_allocation extension is enabled,
+    // vkGetBufferMemoryRequirements2KHR function is used instead, while Validation
+    // Layer seems to be unaware of it.
+    if (strstr(pMessage, "but vkGetBufferMemoryRequirements() has not been called on that buffer") != nullptr)
+    {
+        return VK_FALSE;
+    }
+    if (strstr(pMessage, "but vkGetImageMemoryRequirements() has not been called on that image") != nullptr)
+    {
+        return VK_FALSE;
+    }
+
+    /*
+    "Mapping an image with layout VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL can result in undefined behavior if this memory is used by the device. Only GENERAL or PREINITIALIZED should be used."
+    Ignoring because we map entire VkDeviceMemory blocks, where different types of
+    images and buffers may end up together, especially on GPUs with unified memory
+    like Intel.
+    */
+    if(strstr(pMessage, "Mapping an image with layout") != nullptr &&
+        strstr(pMessage, "can result in undefined behavior if this memory is used by the device") != nullptr)
+    {
+        return VK_FALSE;
+    }
+    
+    switch(flags)
+    {
+    case VK_DEBUG_REPORT_WARNING_BIT_EXT:
+        SetConsoleColor(CONSOLE_COLOR::WARNING);
+        break;
+    case VK_DEBUG_REPORT_ERROR_BIT_EXT:
+        SetConsoleColor(CONSOLE_COLOR::ERROR_);
+        break;
+    default:
+        SetConsoleColor(CONSOLE_COLOR::INFO);
+    }
+
+    printf("%s \xBA %s\n", pLayerPrefix, pMessage);
+
+    SetConsoleColor(CONSOLE_COLOR::NORMAL);
+
+    if(flags == VK_DEBUG_REPORT_WARNING_BIT_EXT ||
+        flags == VK_DEBUG_REPORT_ERROR_BIT_EXT)
+    {
+        OutputDebugStringA(pMessage);
+        OutputDebugStringA("\n");
+    }
+
+    return VK_FALSE;
+}
+
+static VkSurfaceFormatKHR ChooseSurfaceFormat()
+{
+    assert(!g_SurfaceFormats.empty());
+
+    if((g_SurfaceFormats.size() == 1) && (g_SurfaceFormats[0].format == VK_FORMAT_UNDEFINED))
+    {
+        VkSurfaceFormatKHR result = { VK_FORMAT_B8G8R8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
+        return result;
+    }
+    
+    for(const auto& format : g_SurfaceFormats)
+    {
+        if((format.format == VK_FORMAT_B8G8R8A8_UNORM) &&
+            (format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR))
+        {
+            return format;
+        }
+    }
+
+    return g_SurfaceFormats[0];
+}
+
+VkPresentModeKHR ChooseSwapPresentMode()
+{
+    VkPresentModeKHR preferredMode = VSYNC ? VK_PRESENT_MODE_MAILBOX_KHR : VK_PRESENT_MODE_IMMEDIATE_KHR;
+    
+    if(std::find(g_PresentModes.begin(), g_PresentModes.end(), preferredMode) !=
+        g_PresentModes.end())
+    {
+        return preferredMode;
+    }
+
+    return VK_PRESENT_MODE_FIFO_KHR;
+}
+
+static VkExtent2D ChooseSwapExtent()
+{
+    if(g_SurfaceCapabilities.currentExtent.width != UINT_MAX)
+        return g_SurfaceCapabilities.currentExtent;
+
+    VkExtent2D result = {
+        std::max(g_SurfaceCapabilities.minImageExtent.width,
+            std::min(g_SurfaceCapabilities.maxImageExtent.width, (uint32_t)g_SizeX)),
+        std::max(g_SurfaceCapabilities.minImageExtent.height,
+            std::min(g_SurfaceCapabilities.maxImageExtent.height, (uint32_t)g_SizeY)) };
+    return result;
+}
+
+struct Vertex
+{
+    float pos[3];
+    float color[3];
+    float texCoord[2];
+};
+
+static void CreateMesh()
+{
+    assert(g_hAllocator);
+
+    static Vertex vertices[] = {
+        // -X
+        { { -1.f, -1.f, -1.f}, {1.0f, 0.0f, 0.0f}, {0.f, 0.f} },
+        { { -1.f, -1.f,  1.f}, {1.0f, 0.0f, 0.0f}, {1.f, 0.f} },
+        { { -1.f,  1.f, -1.f}, {1.0f, 0.0f, 0.0f}, {0.f, 1.f} },
+        { { -1.f,  1.f,  1.f}, {1.0f, 0.0f, 0.0f}, {1.f, 1.f} },
+        // +X
+        { { 1.f, -1.f,  1.f}, {0.0f, 1.0f, 0.0f}, {0.f, 0.f} },
+        { { 1.f, -1.f, -1.f}, {0.0f, 1.0f, 0.0f}, {1.f, 0.f} },
+        { { 1.f,  1.f,  1.f}, {0.0f, 1.0f, 0.0f}, {0.f, 1.f} },
+        { { 1.f,  1.f, -1.f}, {0.0f, 1.0f, 0.0f}, {1.f, 1.f} },
+        // -Z
+        { { 1.f, -1.f, -1.f}, {0.0f, 0.0f, 1.0f}, {0.f, 0.f} },
+        { {-1.f, -1.f, -1.f}, {0.0f, 0.0f, 1.0f}, {1.f, 0.f} },
+        { { 1.f,  1.f, -1.f}, {0.0f, 0.0f, 1.0f}, {0.f, 1.f} },
+        { {-1.f,  1.f, -1.f}, {0.0f, 0.0f, 1.0f}, {1.f, 1.f} },
+        // +Z
+        { {-1.f, -1.f,  1.f}, {1.0f, 1.0f, 0.0f}, {0.f, 0.f} },
+        { { 1.f, -1.f,  1.f}, {1.0f, 1.0f, 0.0f}, {1.f, 0.f} },
+        { {-1.f,  1.f,  1.f}, {1.0f, 1.0f, 0.0f}, {0.f, 1.f} },
+        { { 1.f,  1.f,  1.f}, {1.0f, 1.0f, 0.0f}, {1.f, 1.f} },
+        // -Y
+        { {-1.f, -1.f, -1.f}, {0.0f, 1.0f, 1.0f}, {0.f, 0.f} },
+        { { 1.f, -1.f, -1.f}, {0.0f, 1.0f, 1.0f}, {1.f, 0.f} },
+        { {-1.f, -1.f,  1.f}, {0.0f, 1.0f, 1.0f}, {0.f, 1.f} },
+        { { 1.f, -1.f,  1.f}, {0.0f, 1.0f, 1.0f}, {1.f, 1.f} },
+        // +Y
+        { { 1.f,  1.f, -1.f}, {1.0f, 0.0f, 1.0f}, {0.f, 0.f} },
+        { {-1.f,  1.f, -1.f}, {1.0f, 0.0f, 1.0f}, {1.f, 0.f} },
+        { { 1.f,  1.f,  1.f}, {1.0f, 0.0f, 1.0f}, {0.f, 1.f} },
+        { {-1.f,  1.f,  1.f}, {1.0f, 0.0f, 1.0f}, {1.f, 1.f} },
+    };
+    static uint16_t indices[] = {
+         0,  1,  2,  3, USHRT_MAX,
+         4,  5,  6,  7, USHRT_MAX,
+         8,  9, 10, 11, USHRT_MAX,
+        12, 13, 14, 15, USHRT_MAX,
+        16, 17, 18, 19, USHRT_MAX,
+        20, 21, 22, 23, USHRT_MAX,
+    };
+
+    size_t vertexBufferSize = sizeof(Vertex) * _countof(vertices);
+    size_t indexBufferSize = sizeof(uint16_t) * _countof(indices);
+    g_IndexCount = (uint32_t)_countof(indices);
+
+    // Create vertex buffer
+
+    VkBufferCreateInfo vbInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+    vbInfo.size = vertexBufferSize;
+    vbInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+    vbInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+
+    VmaAllocationCreateInfo vbAllocCreateInfo = {};
+    vbAllocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
+    vbAllocCreateInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
+
+    VkBuffer stagingVertexBuffer = VK_NULL_HANDLE;
+    VmaAllocation stagingVertexBufferAlloc = VK_NULL_HANDLE;
+    VmaAllocationInfo stagingVertexBufferAllocInfo = {};
+    ERR_GUARD_VULKAN( vmaCreateBuffer(g_hAllocator, &vbInfo, &vbAllocCreateInfo, &stagingVertexBuffer, &stagingVertexBufferAlloc, &stagingVertexBufferAllocInfo) );
+
+    memcpy(stagingVertexBufferAllocInfo.pMappedData, vertices, vertexBufferSize);
+
+    // No need to flush stagingVertexBuffer memory because CPU_ONLY memory is always HOST_COHERENT.
+
+    vbInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
+    vbAllocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+    vbAllocCreateInfo.flags = 0;
+    ERR_GUARD_VULKAN( vmaCreateBuffer(g_hAllocator, &vbInfo, &vbAllocCreateInfo, &g_hVertexBuffer, &g_hVertexBufferAlloc, nullptr) );
+
+    // Create index buffer
+
+    VkBufferCreateInfo ibInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+    ibInfo.size = indexBufferSize;
+    ibInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+    ibInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+    
+    VmaAllocationCreateInfo ibAllocCreateInfo = {};
+    ibAllocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
+    ibAllocCreateInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
+    
+    VkBuffer stagingIndexBuffer = VK_NULL_HANDLE;
+    VmaAllocation stagingIndexBufferAlloc = VK_NULL_HANDLE;
+    VmaAllocationInfo stagingIndexBufferAllocInfo = {};
+    ERR_GUARD_VULKAN( vmaCreateBuffer(g_hAllocator, &ibInfo, &ibAllocCreateInfo, &stagingIndexBuffer, &stagingIndexBufferAlloc, &stagingIndexBufferAllocInfo) );
+
+    memcpy(stagingIndexBufferAllocInfo.pMappedData, indices, indexBufferSize);
+
+    // No need to flush stagingIndexBuffer memory because CPU_ONLY memory is always HOST_COHERENT.
+
+    ibInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
+    ibAllocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+    ibAllocCreateInfo.flags = 0;
+    ERR_GUARD_VULKAN( vmaCreateBuffer(g_hAllocator, &ibInfo, &ibAllocCreateInfo, &g_hIndexBuffer, &g_hIndexBufferAlloc, nullptr) );
+
+    // Copy buffers
+
+    BeginSingleTimeCommands();
+
+    VkBufferCopy vbCopyRegion = {};
+    vbCopyRegion.srcOffset = 0;
+    vbCopyRegion.dstOffset = 0;
+    vbCopyRegion.size = vbInfo.size;
+    vkCmdCopyBuffer(g_hTemporaryCommandBuffer, stagingVertexBuffer, g_hVertexBuffer, 1, &vbCopyRegion);
+
+    VkBufferCopy ibCopyRegion = {};
+    ibCopyRegion.srcOffset = 0;
+    ibCopyRegion.dstOffset = 0;
+    ibCopyRegion.size = ibInfo.size;
+    vkCmdCopyBuffer(g_hTemporaryCommandBuffer, stagingIndexBuffer, g_hIndexBuffer, 1, &ibCopyRegion);
+
+    EndSingleTimeCommands();
+
+    vmaDestroyBuffer(g_hAllocator, stagingIndexBuffer, stagingIndexBufferAlloc);
+    vmaDestroyBuffer(g_hAllocator, stagingVertexBuffer, stagingVertexBufferAlloc);
+}
+
+static void CreateTexture(uint32_t sizeX, uint32_t sizeY)
+{
+    // Create staging buffer.
+
+    const VkDeviceSize imageSize = sizeX * sizeY * 4;
+
+    VkBufferCreateInfo stagingBufInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+    stagingBufInfo.size = imageSize;
+    stagingBufInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+
+    VmaAllocationCreateInfo stagingBufAllocCreateInfo = {};
+    stagingBufAllocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
+    stagingBufAllocCreateInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
+    
+    VkBuffer stagingBuf = VK_NULL_HANDLE;
+    VmaAllocation stagingBufAlloc = VK_NULL_HANDLE;
+    VmaAllocationInfo stagingBufAllocInfo = {};
+    ERR_GUARD_VULKAN( vmaCreateBuffer(g_hAllocator, &stagingBufInfo, &stagingBufAllocCreateInfo, &stagingBuf, &stagingBufAlloc, &stagingBufAllocInfo) );
+
+    char* const pImageData = (char*)stagingBufAllocInfo.pMappedData;
+    uint8_t* pRowData = (uint8_t*)pImageData;
+    for(uint32_t y = 0; y < sizeY; ++y)
+    {
+        uint32_t* pPixelData = (uint32_t*)pRowData;
+        for(uint32_t x = 0; x < sizeY; ++x)
+        {
+            *pPixelData =
+                ((x & 0x18) == 0x08 ? 0x000000FF : 0x00000000) |
+                ((x & 0x18) == 0x10 ? 0x0000FFFF : 0x00000000) |
+                ((y & 0x18) == 0x08 ? 0x0000FF00 : 0x00000000) |
+                ((y & 0x18) == 0x10 ? 0x00FF0000 : 0x00000000);
+            ++pPixelData;
+        }
+        pRowData += sizeX * 4;
+    }
+
+    // No need to flush stagingImage memory because CPU_ONLY memory is always HOST_COHERENT.
+
+    // Create g_hTextureImage in GPU memory.
+
+    VkImageCreateInfo imageInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
+    imageInfo.imageType = VK_IMAGE_TYPE_2D;
+    imageInfo.extent.width = sizeX;
+    imageInfo.extent.height = sizeY;
+    imageInfo.extent.depth = 1;
+    imageInfo.mipLevels = 1;
+    imageInfo.arrayLayers = 1;
+    imageInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
+    imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
+    imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+    imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
+    imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+    imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
+    imageInfo.flags = 0;
+
+    VmaAllocationCreateInfo imageAllocCreateInfo = {};
+    imageAllocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+    
+    ERR_GUARD_VULKAN( vmaCreateImage(g_hAllocator, &imageInfo, &imageAllocCreateInfo, &g_hTextureImage, &g_hTextureImageAlloc, nullptr) );
+
+    // Transition image layouts, copy image.
+
+    BeginSingleTimeCommands();
+
+    VkImageMemoryBarrier imgMemBarrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER };
+    imgMemBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+    imgMemBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+    imgMemBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+    imgMemBarrier.subresourceRange.baseMipLevel = 0;
+    imgMemBarrier.subresourceRange.levelCount = 1;
+    imgMemBarrier.subresourceRange.baseArrayLayer = 0;
+    imgMemBarrier.subresourceRange.layerCount = 1;
+    imgMemBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+    imgMemBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+    imgMemBarrier.image = g_hTextureImage;
+    imgMemBarrier.srcAccessMask = 0;
+    imgMemBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+
+    vkCmdPipelineBarrier(
+        g_hTemporaryCommandBuffer,
+        VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+        VK_PIPELINE_STAGE_TRANSFER_BIT,
+        0,
+        0, nullptr,
+        0, nullptr,
+        1, &imgMemBarrier);
+
+    VkBufferImageCopy region = {};
+    region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+    region.imageSubresource.layerCount = 1;
+    region.imageExtent.width = sizeX;
+    region.imageExtent.height = sizeY;
+    region.imageExtent.depth = 1;
+
+    vkCmdCopyBufferToImage(g_hTemporaryCommandBuffer, stagingBuf, g_hTextureImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
+
+    imgMemBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+    imgMemBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+    imgMemBarrier.image = g_hTextureImage;
+    imgMemBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+    imgMemBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
+
+    vkCmdPipelineBarrier(
+        g_hTemporaryCommandBuffer,
+        VK_PIPELINE_STAGE_TRANSFER_BIT,
+        VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
+        0,
+        0, nullptr,
+        0, nullptr,
+        1, &imgMemBarrier);
+
+    EndSingleTimeCommands();
+
+    vmaDestroyBuffer(g_hAllocator, stagingBuf, stagingBufAlloc);
+
+    // Create ImageView
+
+    VkImageViewCreateInfo textureImageViewInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO };
+    textureImageViewInfo.image = g_hTextureImage;
+    textureImageViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
+    textureImageViewInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
+    textureImageViewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+    textureImageViewInfo.subresourceRange.baseMipLevel = 0;
+    textureImageViewInfo.subresourceRange.levelCount = 1;
+    textureImageViewInfo.subresourceRange.baseArrayLayer = 0;
+    textureImageViewInfo.subresourceRange.layerCount = 1;
+    ERR_GUARD_VULKAN( vkCreateImageView(g_hDevice, &textureImageViewInfo, g_Allocs, &g_hTextureImageView) );
+}
+
+struct UniformBufferObject
+{
+    mat4 ModelViewProj;
+};
+
+static void RegisterDebugCallbacks()
+{
+    g_pvkCreateDebugReportCallbackEXT =
+        reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>
+            (vkGetInstanceProcAddr(g_hVulkanInstance, "vkCreateDebugReportCallbackEXT"));
+    g_pvkDebugReportMessageEXT =
+        reinterpret_cast<PFN_vkDebugReportMessageEXT>
+            (vkGetInstanceProcAddr(g_hVulkanInstance, "vkDebugReportMessageEXT"));
+    g_pvkDestroyDebugReportCallbackEXT =
+        reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>
+            (vkGetInstanceProcAddr(g_hVulkanInstance, "vkDestroyDebugReportCallbackEXT"));
+    assert(g_pvkCreateDebugReportCallbackEXT);
+    assert(g_pvkDebugReportMessageEXT);
+    assert(g_pvkDestroyDebugReportCallbackEXT);
+
+    VkDebugReportCallbackCreateInfoEXT callbackCreateInfo = { VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT };
+    callbackCreateInfo.flags = //VK_DEBUG_REPORT_INFORMATION_BIT_EXT |
+        VK_DEBUG_REPORT_ERROR_BIT_EXT |
+        VK_DEBUG_REPORT_WARNING_BIT_EXT |
+        VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT /*|
+        VK_DEBUG_REPORT_DEBUG_BIT_EXT*/;
+    callbackCreateInfo.pfnCallback = &MyDebugReportCallback;
+
+    ERR_GUARD_VULKAN( g_pvkCreateDebugReportCallbackEXT(g_hVulkanInstance, &callbackCreateInfo, g_Allocs, &g_hCallback) );
+}
+
+static bool IsLayerSupported(const VkLayerProperties* pProps, size_t propCount, const char* pLayerName)
+{
+    const VkLayerProperties* propsEnd = pProps + propCount;
+    return std::find_if(
+        pProps,
+        propsEnd,
+        [pLayerName](const VkLayerProperties& prop) -> bool {
+            return strcmp(pLayerName, prop.layerName) == 0;
+        }) != propsEnd;
+}
+
+static VkFormat FindSupportedFormat(
+    const std::vector<VkFormat>& candidates,
+    VkImageTiling tiling,
+    VkFormatFeatureFlags features)
+{
+    for (VkFormat format : candidates)
+    {
+        VkFormatProperties props;
+        vkGetPhysicalDeviceFormatProperties(g_hPhysicalDevice, format, &props);
+        
+        if ((tiling == VK_IMAGE_TILING_LINEAR) &&
+            ((props.linearTilingFeatures & features) == features))
+        {
+            return format;
+        }
+        else if ((tiling == VK_IMAGE_TILING_OPTIMAL) &&
+            ((props.optimalTilingFeatures & features) == features))
+        {
+            return format;
+        }
+    }
+    return VK_FORMAT_UNDEFINED;
+}
+
+static VkFormat FindDepthFormat()
+{
+    std::vector<VkFormat> formats;
+    formats.push_back(VK_FORMAT_D32_SFLOAT);
+    formats.push_back(VK_FORMAT_D32_SFLOAT_S8_UINT);
+    formats.push_back(VK_FORMAT_D24_UNORM_S8_UINT);
+
+    return FindSupportedFormat(
+        formats,
+        VK_IMAGE_TILING_OPTIMAL,
+        VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT);
+}
+
+static void CreateSwapchain()
+{
+    // Query surface formats.
+
+    ERR_GUARD_VULKAN( vkGetPhysicalDeviceSurfaceCapabilitiesKHR(g_hPhysicalDevice, g_hSurface, &g_SurfaceCapabilities) );
+    
+    uint32_t formatCount = 0;
+    ERR_GUARD_VULKAN( vkGetPhysicalDeviceSurfaceFormatsKHR(g_hPhysicalDevice, g_hSurface, &formatCount, nullptr) );
+    g_SurfaceFormats.resize(formatCount);
+    ERR_GUARD_VULKAN( vkGetPhysicalDeviceSurfaceFormatsKHR(g_hPhysicalDevice, g_hSurface, &formatCount, g_SurfaceFormats.data()) );
+
+    uint32_t presentModeCount = 0;
+    ERR_GUARD_VULKAN( vkGetPhysicalDeviceSurfacePresentModesKHR(g_hPhysicalDevice, g_hSurface, &presentModeCount, nullptr) );
+    g_PresentModes.resize(presentModeCount);
+    ERR_GUARD_VULKAN( vkGetPhysicalDeviceSurfacePresentModesKHR(g_hPhysicalDevice, g_hSurface, &presentModeCount, g_PresentModes.data()) );
+
+    // Create swap chain
+
+    g_SurfaceFormat = ChooseSurfaceFormat();
+    VkPresentModeKHR presentMode = ChooseSwapPresentMode();
+    g_Extent = ChooseSwapExtent();
+
+    uint32_t imageCount = g_SurfaceCapabilities.minImageCount + 1;
+    if((g_SurfaceCapabilities.maxImageCount > 0) &&
+        (imageCount > g_SurfaceCapabilities.maxImageCount))
+    {
+        imageCount = g_SurfaceCapabilities.maxImageCount;
+    }
+
+    VkSwapchainCreateInfoKHR swapChainInfo = { VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR };
+    swapChainInfo.surface = g_hSurface;
+    swapChainInfo.minImageCount = imageCount;
+    swapChainInfo.imageFormat = g_SurfaceFormat.format;
+    swapChainInfo.imageColorSpace = g_SurfaceFormat.colorSpace;
+    swapChainInfo.imageExtent = g_Extent;
+    swapChainInfo.imageArrayLayers = 1;
+    swapChainInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+    swapChainInfo.preTransform = g_SurfaceCapabilities.currentTransform;
+    swapChainInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
+    swapChainInfo.presentMode = presentMode;
+    swapChainInfo.clipped = VK_TRUE;
+    swapChainInfo.oldSwapchain = g_hSwapchain;
+
+    uint32_t queueFamilyIndices[] = { g_GraphicsQueueFamilyIndex, g_PresentQueueFamilyIndex };
+    if(g_PresentQueueFamilyIndex != g_GraphicsQueueFamilyIndex)
+    {
+        swapChainInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
+        swapChainInfo.queueFamilyIndexCount = 2;
+        swapChainInfo.pQueueFamilyIndices = queueFamilyIndices;
+    }
+    else
+    {
+        swapChainInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
+    }
+
+    VkSwapchainKHR hNewSwapchain = VK_NULL_HANDLE;
+    ERR_GUARD_VULKAN( vkCreateSwapchainKHR(g_hDevice, &swapChainInfo, g_Allocs, &hNewSwapchain) );
+    if(g_hSwapchain != VK_NULL_HANDLE)
+        vkDestroySwapchainKHR(g_hDevice, g_hSwapchain, g_Allocs);
+    g_hSwapchain = hNewSwapchain;
+
+    // Retrieve swapchain images.
+
+    uint32_t swapchainImageCount = 0;
+    ERR_GUARD_VULKAN( vkGetSwapchainImagesKHR(g_hDevice, g_hSwapchain, &swapchainImageCount, nullptr) );
+    g_SwapchainImages.resize(swapchainImageCount);
+    ERR_GUARD_VULKAN( vkGetSwapchainImagesKHR(g_hDevice, g_hSwapchain, &swapchainImageCount, g_SwapchainImages.data()) );
+
+    // Create swapchain image views.
+
+    for(size_t i = g_SwapchainImageViews.size(); i--; )
+        vkDestroyImageView(g_hDevice, g_SwapchainImageViews[i], g_Allocs);
+    g_SwapchainImageViews.clear();
+
+    VkImageViewCreateInfo swapchainImageViewInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO };
+    g_SwapchainImageViews.resize(swapchainImageCount);
+    for(uint32_t i = 0; i < swapchainImageCount; ++i)
+    {
+        swapchainImageViewInfo.image = g_SwapchainImages[i];
+        swapchainImageViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
+        swapchainImageViewInfo.format = g_SurfaceFormat.format;
+        swapchainImageViewInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
+        swapchainImageViewInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
+        swapchainImageViewInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
+        swapchainImageViewInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
+        swapchainImageViewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+        swapchainImageViewInfo.subresourceRange.baseMipLevel = 0;
+        swapchainImageViewInfo.subresourceRange.levelCount = 1;
+        swapchainImageViewInfo.subresourceRange.baseArrayLayer = 0;
+        swapchainImageViewInfo.subresourceRange.layerCount = 1;
+        ERR_GUARD_VULKAN( vkCreateImageView(g_hDevice, &swapchainImageViewInfo, g_Allocs, &g_SwapchainImageViews[i]) );
+    }
+
+    // Create depth buffer
+
+    g_DepthFormat = FindDepthFormat();
+    assert(g_DepthFormat != VK_FORMAT_UNDEFINED);
+
+    VkImageCreateInfo depthImageInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
+    depthImageInfo.imageType = VK_IMAGE_TYPE_2D;
+    depthImageInfo.extent.width = g_Extent.width;
+    depthImageInfo.extent.height = g_Extent.height;
+    depthImageInfo.extent.depth = 1;
+    depthImageInfo.mipLevels = 1;
+    depthImageInfo.arrayLayers = 1;
+    depthImageInfo.format = g_DepthFormat;
+    depthImageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
+    depthImageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+    depthImageInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
+    depthImageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+    depthImageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
+    depthImageInfo.flags = 0;
+
+    VmaAllocationCreateInfo depthImageAllocCreateInfo = {};
+    depthImageAllocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+
+    ERR_GUARD_VULKAN( vmaCreateImage(g_hAllocator, &depthImageInfo, &depthImageAllocCreateInfo, &g_hDepthImage, &g_hDepthImageAlloc, nullptr) );
+
+    VkImageViewCreateInfo depthImageViewInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO };
+    depthImageViewInfo.image = g_hDepthImage;
+    depthImageViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
+    depthImageViewInfo.format = g_DepthFormat;
+    depthImageViewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
+    depthImageViewInfo.subresourceRange.baseMipLevel = 0;
+    depthImageViewInfo.subresourceRange.levelCount = 1;
+    depthImageViewInfo.subresourceRange.baseArrayLayer = 0;
+    depthImageViewInfo.subresourceRange.layerCount = 1;
+
+    ERR_GUARD_VULKAN( vkCreateImageView(g_hDevice, &depthImageViewInfo, g_Allocs, &g_hDepthImageView) );
+
+    // Create pipeline layout
+    {
+        if(g_hPipelineLayout != VK_NULL_HANDLE)
+        {
+            vkDestroyPipelineLayout(g_hDevice, g_hPipelineLayout, g_Allocs);
+            g_hPipelineLayout = VK_NULL_HANDLE;
+        }
+
+        VkPushConstantRange pushConstantRanges[1];
+        ZeroMemory(&pushConstantRanges, sizeof pushConstantRanges);
+        pushConstantRanges[0].offset = 0;
+        pushConstantRanges[0].size = sizeof(UniformBufferObject);
+        pushConstantRanges[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
+
+        VkDescriptorSetLayout descriptorSetLayouts[] = { g_hDescriptorSetLayout };
+        VkPipelineLayoutCreateInfo pipelineLayoutInfo = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };
+        pipelineLayoutInfo.setLayoutCount = 1;
+        pipelineLayoutInfo.pSetLayouts = descriptorSetLayouts;
+        pipelineLayoutInfo.pushConstantRangeCount = 1;
+        pipelineLayoutInfo.pPushConstantRanges = pushConstantRanges;
+        ERR_GUARD_VULKAN( vkCreatePipelineLayout(g_hDevice, &pipelineLayoutInfo, g_Allocs, &g_hPipelineLayout) );
+    }
+
+    // Create render pass
+    {
+        if(g_hRenderPass != VK_NULL_HANDLE)
+        {
+            vkDestroyRenderPass(g_hDevice, g_hRenderPass, g_Allocs);
+            g_hRenderPass = VK_NULL_HANDLE;
+        }
+
+        VkAttachmentDescription attachments[2];
+        ZeroMemory(attachments, sizeof(attachments));
+
+        attachments[0].format = g_SurfaceFormat.format;
+        attachments[0].samples = VK_SAMPLE_COUNT_1_BIT;
+        attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+        attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+        attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+        attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+        attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+        attachments[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+
+        attachments[1].format = g_DepthFormat;
+        attachments[1].samples = VK_SAMPLE_COUNT_1_BIT;
+        attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+        attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+        attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+        attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+        attachments[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+        attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+
+        VkAttachmentReference colorAttachmentRef = {};
+        colorAttachmentRef.attachment = 0;
+        colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+        
+        VkAttachmentReference depthStencilAttachmentRef = {};
+        depthStencilAttachmentRef.attachment = 1;
+        depthStencilAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+        
+        VkSubpassDescription subpassDesc = {};
+        subpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+        subpassDesc.colorAttachmentCount = 1;
+        subpassDesc.pColorAttachments = &colorAttachmentRef;
+        subpassDesc.pDepthStencilAttachment = &depthStencilAttachmentRef;
+
+        VkRenderPassCreateInfo renderPassInfo = { VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO };
+        renderPassInfo.attachmentCount = (uint32_t)_countof(attachments);
+        renderPassInfo.pAttachments = attachments;
+        renderPassInfo.subpassCount = 1;
+        renderPassInfo.pSubpasses = &subpassDesc;
+        renderPassInfo.dependencyCount = 0;
+        ERR_GUARD_VULKAN( vkCreateRenderPass(g_hDevice, &renderPassInfo, g_Allocs, &g_hRenderPass) );
+    }
+
+    // Create pipeline
+    {
+        std::vector<char> vertShaderCode;
+        LoadShader(vertShaderCode, "Shader.vert.spv");
+        VkShaderModuleCreateInfo shaderModuleInfo = { VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO };
+        shaderModuleInfo.codeSize = vertShaderCode.size();
+        shaderModuleInfo.pCode = (const uint32_t*)vertShaderCode.data();
+        VkShaderModule hVertShaderModule = VK_NULL_HANDLE;
+        ERR_GUARD_VULKAN( vkCreateShaderModule(g_hDevice, &shaderModuleInfo, g_Allocs, &hVertShaderModule) );
+
+        std::vector<char> hFragShaderCode;
+        LoadShader(hFragShaderCode, "Shader.frag.spv");
+        shaderModuleInfo.codeSize = hFragShaderCode.size();
+        shaderModuleInfo.pCode = (const uint32_t*)hFragShaderCode.data();
+        VkShaderModule fragShaderModule = VK_NULL_HANDLE;
+        ERR_GUARD_VULKAN( vkCreateShaderModule(g_hDevice, &shaderModuleInfo, g_Allocs, &fragShaderModule) );
+
+        VkPipelineShaderStageCreateInfo vertPipelineShaderStageInfo = { VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO };
+        vertPipelineShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
+        vertPipelineShaderStageInfo.module = hVertShaderModule;
+        vertPipelineShaderStageInfo.pName = "main";
+
+        VkPipelineShaderStageCreateInfo fragPipelineShaderStageInfo = { VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO };
+        fragPipelineShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
+        fragPipelineShaderStageInfo.module = fragShaderModule;
+        fragPipelineShaderStageInfo.pName = "main";
+
+        VkPipelineShaderStageCreateInfo pipelineShaderStageInfos[] = {
+            vertPipelineShaderStageInfo,
+            fragPipelineShaderStageInfo
+        };
+
+        VkVertexInputBindingDescription bindingDescription = {};
+        bindingDescription.binding = 0;
+        bindingDescription.stride = sizeof(Vertex);
+        bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
+
+        VkVertexInputAttributeDescription attributeDescriptions[3];
+        ZeroMemory(attributeDescriptions, sizeof(attributeDescriptions));
+
+        attributeDescriptions[0].binding = 0;
+        attributeDescriptions[0].location = 0;
+        attributeDescriptions[0].format = VK_FORMAT_R32G32B32_SFLOAT;
+        attributeDescriptions[0].offset = offsetof(Vertex, pos);
+        
+        attributeDescriptions[1].binding = 0;
+        attributeDescriptions[1].location = 1;
+        attributeDescriptions[1].format = VK_FORMAT_R32G32B32_SFLOAT;
+        attributeDescriptions[1].offset = offsetof(Vertex, color);
+
+        attributeDescriptions[2].binding = 0;
+        attributeDescriptions[2].location = 2;
+        attributeDescriptions[2].format = VK_FORMAT_R32G32_SFLOAT;
+        attributeDescriptions[2].offset = offsetof(Vertex, texCoord);
+
+        VkPipelineVertexInputStateCreateInfo pipelineVertexInputStateInfo = { VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO };
+        pipelineVertexInputStateInfo.vertexBindingDescriptionCount = 1;
+        pipelineVertexInputStateInfo.pVertexBindingDescriptions = &bindingDescription;
+        pipelineVertexInputStateInfo.vertexAttributeDescriptionCount = _countof(attributeDescriptions);
+        pipelineVertexInputStateInfo.pVertexAttributeDescriptions = attributeDescriptions;
+
+        VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo = { VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO };
+        pipelineInputAssemblyStateInfo.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
+        pipelineInputAssemblyStateInfo.primitiveRestartEnable = VK_TRUE;
+
+        VkViewport viewport = {};
+        viewport.x = 0.f;
+        viewport.y = 0.f;
+        viewport.width = (float)g_Extent.width;
+        viewport.height = (float)g_Extent.height;
+        viewport.minDepth = 0.f;
+        viewport.maxDepth = 1.f;
+
+        VkRect2D scissor = {};
+        scissor.offset.x = 0;
+        scissor.offset.y = 0;
+        scissor.extent = g_Extent;
+
+        VkPipelineViewportStateCreateInfo pipelineViewportStateInfo = { VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO };
+        pipelineViewportStateInfo.viewportCount = 1;
+        pipelineViewportStateInfo.pViewports = &viewport;
+        pipelineViewportStateInfo.scissorCount = 1;
+        pipelineViewportStateInfo.pScissors = &scissor;
+
+        VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo = { VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO };
+        pipelineRasterizationStateInfo.depthClampEnable = VK_FALSE;
+        pipelineRasterizationStateInfo.rasterizerDiscardEnable = VK_FALSE;
+        pipelineRasterizationStateInfo.polygonMode = VK_POLYGON_MODE_FILL;
+        pipelineRasterizationStateInfo.lineWidth = 1.f;
+        pipelineRasterizationStateInfo.cullMode = VK_CULL_MODE_BACK_BIT;
+        pipelineRasterizationStateInfo.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
+        pipelineRasterizationStateInfo.depthBiasEnable = VK_FALSE;
+        pipelineRasterizationStateInfo.depthBiasConstantFactor = 0.f;
+        pipelineRasterizationStateInfo.depthBiasClamp = 0.f;
+        pipelineRasterizationStateInfo.depthBiasSlopeFactor = 0.f;
+
+        VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo = { VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO };
+        pipelineMultisampleStateInfo.sampleShadingEnable = VK_FALSE;
+        pipelineMultisampleStateInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
+        pipelineMultisampleStateInfo.minSampleShading = 1.f;
+        pipelineMultisampleStateInfo.pSampleMask = nullptr;
+        pipelineMultisampleStateInfo.alphaToCoverageEnable = VK_FALSE;
+        pipelineMultisampleStateInfo.alphaToOneEnable = VK_FALSE;
+
+        VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState = {};
+        pipelineColorBlendAttachmentState.colorWriteMask =
+            VK_COLOR_COMPONENT_R_BIT |
+            VK_COLOR_COMPONENT_G_BIT |
+            VK_COLOR_COMPONENT_B_BIT |
+            VK_COLOR_COMPONENT_A_BIT;
+        pipelineColorBlendAttachmentState.blendEnable = VK_FALSE;
+        pipelineColorBlendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; // Optional
+        pipelineColorBlendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO; // Optional
+        pipelineColorBlendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD; // Optional
+        pipelineColorBlendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; // Optional
+        pipelineColorBlendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; // Optional
+        pipelineColorBlendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD; // Optional
+
+        VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo = { VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO };
+        pipelineColorBlendStateInfo.logicOpEnable = VK_FALSE;
+        pipelineColorBlendStateInfo.logicOp = VK_LOGIC_OP_COPY;
+        pipelineColorBlendStateInfo.attachmentCount = 1;
+        pipelineColorBlendStateInfo.pAttachments = &pipelineColorBlendAttachmentState;
+
+        VkPipelineDepthStencilStateCreateInfo depthStencilStateInfo = { VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO };
+        depthStencilStateInfo.depthTestEnable = VK_TRUE;
+        depthStencilStateInfo.depthWriteEnable = VK_TRUE;
+        depthStencilStateInfo.depthCompareOp = VK_COMPARE_OP_LESS;
+        depthStencilStateInfo.depthBoundsTestEnable = VK_FALSE;
+        depthStencilStateInfo.stencilTestEnable = VK_FALSE;
+
+        VkGraphicsPipelineCreateInfo pipelineInfo = { VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO };
+        pipelineInfo.stageCount = 2;
+        pipelineInfo.pStages = pipelineShaderStageInfos;
+        pipelineInfo.pVertexInputState = &pipelineVertexInputStateInfo;
+        pipelineInfo.pInputAssemblyState = &pipelineInputAssemblyStateInfo;
+        pipelineInfo.pViewportState = &pipelineViewportStateInfo;
+        pipelineInfo.pRasterizationState = &pipelineRasterizationStateInfo;
+        pipelineInfo.pMultisampleState = &pipelineMultisampleStateInfo;
+        pipelineInfo.pDepthStencilState = &depthStencilStateInfo;
+        pipelineInfo.pColorBlendState = &pipelineColorBlendStateInfo;
+        pipelineInfo.pDynamicState = nullptr;
+        pipelineInfo.layout = g_hPipelineLayout;
+        pipelineInfo.renderPass = g_hRenderPass;
+        pipelineInfo.subpass = 0;
+        pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
+        pipelineInfo.basePipelineIndex = -1;
+        ERR_GUARD_VULKAN( vkCreateGraphicsPipelines(
+            g_hDevice,
+            VK_NULL_HANDLE,
+            1,
+            &pipelineInfo,
+            g_Allocs,
+            &g_hPipeline) );
+
+        vkDestroyShaderModule(g_hDevice, fragShaderModule, g_Allocs);
+        vkDestroyShaderModule(g_hDevice, hVertShaderModule, g_Allocs);
+    }
+
+    // Create frambuffers
+
+    for(size_t i = g_Framebuffers.size(); i--; )
+        vkDestroyFramebuffer(g_hDevice, g_Framebuffers[i], g_Allocs);
+    g_Framebuffers.clear();
+
+    g_Framebuffers.resize(g_SwapchainImageViews.size());
+    for(size_t i = 0; i < g_SwapchainImages.size(); ++i)
+    {
+        VkImageView attachments[] = { g_SwapchainImageViews[i], g_hDepthImageView };
+
+        VkFramebufferCreateInfo framebufferInfo = { VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO };
+        framebufferInfo.renderPass = g_hRenderPass;
+        framebufferInfo.attachmentCount = (uint32_t)_countof(attachments);
+        framebufferInfo.pAttachments = attachments;
+        framebufferInfo.width = g_Extent.width;
+        framebufferInfo.height = g_Extent.height;
+        framebufferInfo.layers = 1;
+        ERR_GUARD_VULKAN( vkCreateFramebuffer(g_hDevice, &framebufferInfo, g_Allocs, &g_Framebuffers[i]) );
+    }
+
+    // Create semaphores
+
+    if(g_hImageAvailableSemaphore != VK_NULL_HANDLE)
+    {
+        vkDestroySemaphore(g_hDevice, g_hImageAvailableSemaphore, g_Allocs);
+        g_hImageAvailableSemaphore = VK_NULL_HANDLE;
+    }
+    if(g_hRenderFinishedSemaphore != VK_NULL_HANDLE)
+    {
+        vkDestroySemaphore(g_hDevice, g_hRenderFinishedSemaphore, g_Allocs);
+        g_hRenderFinishedSemaphore = VK_NULL_HANDLE;
+    }
+
+    VkSemaphoreCreateInfo semaphoreInfo = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO };
+    ERR_GUARD_VULKAN( vkCreateSemaphore(g_hDevice, &semaphoreInfo, g_Allocs, &g_hImageAvailableSemaphore) );
+    ERR_GUARD_VULKAN( vkCreateSemaphore(g_hDevice, &semaphoreInfo, g_Allocs, &g_hRenderFinishedSemaphore) );
+}
+
+static void DestroySwapchain(bool destroyActualSwapchain)
+{
+    if(g_hImageAvailableSemaphore != VK_NULL_HANDLE)
+    {
+        vkDestroySemaphore(g_hDevice, g_hImageAvailableSemaphore, g_Allocs);
+        g_hImageAvailableSemaphore = VK_NULL_HANDLE;
+    }
+    if(g_hRenderFinishedSemaphore != VK_NULL_HANDLE)
+    {
+        vkDestroySemaphore(g_hDevice, g_hRenderFinishedSemaphore, g_Allocs);
+        g_hRenderFinishedSemaphore = VK_NULL_HANDLE;
+    }
+
+    for(size_t i = g_Framebuffers.size(); i--; )
+        vkDestroyFramebuffer(g_hDevice, g_Framebuffers[i], g_Allocs);
+    g_Framebuffers.clear();
+
+    if(g_hDepthImageView != VK_NULL_HANDLE)
+    {
+        vkDestroyImageView(g_hDevice, g_hDepthImageView, g_Allocs);
+        g_hDepthImageView = VK_NULL_HANDLE;
+    }
+    if(g_hDepthImage != VK_NULL_HANDLE)
+    {
+        vmaDestroyImage(g_hAllocator, g_hDepthImage, g_hDepthImageAlloc);
+        g_hDepthImage = VK_NULL_HANDLE;
+    }
+
+    if(g_hPipeline != VK_NULL_HANDLE)
+    {
+        vkDestroyPipeline(g_hDevice, g_hPipeline, g_Allocs);
+        g_hPipeline = VK_NULL_HANDLE;
+    }
+
+    if(g_hRenderPass != VK_NULL_HANDLE)
+    {
+        vkDestroyRenderPass(g_hDevice, g_hRenderPass, g_Allocs);
+        g_hRenderPass = VK_NULL_HANDLE;
+    }
+
+    if(g_hPipelineLayout != VK_NULL_HANDLE)
+    {
+        vkDestroyPipelineLayout(g_hDevice, g_hPipelineLayout, g_Allocs);
+        g_hPipelineLayout = VK_NULL_HANDLE;
+    }
+    
+    for(size_t i = g_SwapchainImageViews.size(); i--; )
+        vkDestroyImageView(g_hDevice, g_SwapchainImageViews[i], g_Allocs);
+    g_SwapchainImageViews.clear();
+
+    if(destroyActualSwapchain && (g_hSwapchain != VK_NULL_HANDLE))
+    {
+        vkDestroySwapchainKHR(g_hDevice, g_hSwapchain, g_Allocs);
+        g_hSwapchain = VK_NULL_HANDLE;
+    }
+}
+
+static constexpr uint32_t GetVulkanApiVersion()
+{
+#if VMA_VULKAN_VERSION == 1002000
+    return VK_API_VERSION_1_2;
+#elif VMA_VULKAN_VERSION == 1001000
+    return VK_API_VERSION_1_1;
+#elif VMA_VULKAN_VERSION == 1000000
+    return VK_API_VERSION_1_0;
+#else
+    #error Invalid VMA_VULKAN_VERSION.
+    return UINT32_MAX;
+#endif
+}
+
+static void PrintEnabledFeatures()
+{
+    wprintf(L"Validation layer: %d\n", g_EnableValidationLayer ? 1 : 0);
+    wprintf(L"Sparse binding: %d\n", g_SparseBindingEnabled ? 1 : 0);
+    wprintf(L"Buffer device address: %d\n", g_BufferDeviceAddressEnabled ? 1 : 0);
+    if(GetVulkanApiVersion() == VK_API_VERSION_1_0)
+    {
+        wprintf(L"VK_KHR_get_memory_requirements2: %d\n", VK_KHR_get_memory_requirements2_enabled ? 1 : 0);
+        wprintf(L"VK_KHR_get_physical_device_properties2: %d\n", VK_KHR_get_physical_device_properties2_enabled ? 1 : 0);
+        wprintf(L"VK_KHR_dedicated_allocation: %d\n", VK_KHR_dedicated_allocation_enabled ? 1 : 0);
+        wprintf(L"VK_KHR_bind_memory2: %d\n", VK_KHR_bind_memory2_enabled ? 1 : 0);
+    }
+    wprintf(L"VK_EXT_memory_budget: %d\n", VK_EXT_memory_budget_enabled ? 1 : 0);
+    wprintf(L"VK_AMD_device_coherent_memory: %d\n", VK_AMD_device_coherent_memory_enabled ? 1 : 0);
+    wprintf(L"VK_KHR_buffer_device_address: %d\n", VK_KHR_buffer_device_address_enabled ? 1 : 0);
+    wprintf(L"VK_EXT_buffer_device_address: %d\n", VK_EXT_buffer_device_address_enabled ? 1 : 0);
+}
+
+void SetAllocatorCreateInfo(VmaAllocatorCreateInfo& outInfo)
+{
+    outInfo = {};
+
+    outInfo.physicalDevice = g_hPhysicalDevice;
+    outInfo.device = g_hDevice;
+    outInfo.instance = g_hVulkanInstance;
+    outInfo.vulkanApiVersion = GetVulkanApiVersion();
+
+    if(VK_KHR_dedicated_allocation_enabled)
+    {
+        outInfo.flags |= VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT;
+    }
+    if(VK_KHR_bind_memory2_enabled)
+    {
+        outInfo.flags |= VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT;
+    }
+#if !defined(VMA_MEMORY_BUDGET) || VMA_MEMORY_BUDGET == 1
+    if(VK_EXT_memory_budget_enabled && (
+        GetVulkanApiVersion() >= VK_API_VERSION_1_1 || VK_KHR_get_physical_device_properties2_enabled))
+    {
+        outInfo.flags |= VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT;
+    }
+#endif
+    if(VK_AMD_device_coherent_memory_enabled)
+    {
+        outInfo.flags |= VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT;
+    }
+    if(g_BufferDeviceAddressEnabled)
+    {
+        outInfo.flags |= VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT;
+    }
+
+    if(USE_CUSTOM_CPU_ALLOCATION_CALLBACKS)
+    {
+        outInfo.pAllocationCallbacks = &g_CpuAllocationCallbacks;
+    }
+
+    // Uncomment to enable recording to CSV file.
+    /*
+    static VmaRecordSettings recordSettings = {};
+    recordSettings.pFilePath = "VulkanSample.csv";
+    outInfo.pRecordSettings = &recordSettings;
+    */
+
+    // Uncomment to enable HeapSizeLimit.
+    /*
+    static std::array<VkDeviceSize, VK_MAX_MEMORY_HEAPS> heapSizeLimit;
+    std::fill(heapSizeLimit.begin(), heapSizeLimit.end(), VK_WHOLE_SIZE);
+    heapSizeLimit[0] = 512ull * 1024 * 1024;
+    outInfo.pHeapSizeLimit = heapSizeLimit.data();
+    */
+}
+
+static void PrintPhysicalDeviceProperties(const VkPhysicalDeviceProperties& properties)
+{
+    wprintf(L"Physical device:\n");
+    wprintf(L"    Driver version: 0x%X\n", properties.driverVersion);
+    wprintf(L"    Vendor ID: 0x%X\n", properties.vendorID);
+    wprintf(L"    Device ID: 0x%X\n", properties.deviceID);
+    wprintf(L"    Device type: %u\n", properties.deviceType);
+    wprintf(L"    Device name: %hs\n", properties.deviceName);
+}
+
+static void InitializeApplication()
+{
+    if(USE_CUSTOM_CPU_ALLOCATION_CALLBACKS)
+    {
+        g_Allocs = &g_CpuAllocationCallbacks;
+    }
+
+    uint32_t instanceLayerPropCount = 0;
+    ERR_GUARD_VULKAN( vkEnumerateInstanceLayerProperties(&instanceLayerPropCount, nullptr) );
+    std::vector<VkLayerProperties> instanceLayerProps(instanceLayerPropCount);
+    if(instanceLayerPropCount > 0)
+    {
+        ERR_GUARD_VULKAN( vkEnumerateInstanceLayerProperties(&instanceLayerPropCount, instanceLayerProps.data()) );
+    }
+
+    if(g_EnableValidationLayer == true)
+    {
+        if(IsLayerSupported(instanceLayerProps.data(), instanceLayerProps.size(), VALIDATION_LAYER_NAME) == false)
+        {
+            wprintf(L"Layer \"%hs\" not supported.", VALIDATION_LAYER_NAME);
+            g_EnableValidationLayer = false;
+        }
+    }
+
+    uint32_t availableInstanceExtensionCount = 0;
+    ERR_GUARD_VULKAN( vkEnumerateInstanceExtensionProperties(nullptr, &availableInstanceExtensionCount, nullptr) );
+    std::vector<VkExtensionProperties> availableInstanceExtensions(availableInstanceExtensionCount);
+    if(availableInstanceExtensionCount > 0)
+    {
+        ERR_GUARD_VULKAN( vkEnumerateInstanceExtensionProperties(nullptr, &availableInstanceExtensionCount, availableInstanceExtensions.data()) );
+    }
+
+    std::vector<const char*> enabledInstanceExtensions;
+    enabledInstanceExtensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
+    enabledInstanceExtensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
+
+    std::vector<const char*> instanceLayers;
+    if(g_EnableValidationLayer == true)
+    {
+        instanceLayers.push_back(VALIDATION_LAYER_NAME);
+        enabledInstanceExtensions.push_back("VK_EXT_debug_report");
+    }
+
+    for(const auto& extensionProperties : availableInstanceExtensions)
+    {
+        if(strcmp(extensionProperties.extensionName, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME) == 0)
+        {
+            if(GetVulkanApiVersion() == VK_API_VERSION_1_0)
+            {   
+                enabledInstanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
+                VK_KHR_get_physical_device_properties2_enabled = true;
+            }
+        }
+    }
+
+    VkApplicationInfo appInfo = { VK_STRUCTURE_TYPE_APPLICATION_INFO };
+    appInfo.pApplicationName = APP_TITLE_A;
+    appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
+    appInfo.pEngineName = "Adam Sawicki Engine";
+    appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
+    appInfo.apiVersion = GetVulkanApiVersion();
+
+    VkInstanceCreateInfo instInfo = { VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO };
+    instInfo.pApplicationInfo = &appInfo;
+    instInfo.enabledExtensionCount = static_cast<uint32_t>(enabledInstanceExtensions.size());
+    instInfo.ppEnabledExtensionNames = enabledInstanceExtensions.data();
+    instInfo.enabledLayerCount = static_cast<uint32_t>(instanceLayers.size());
+    instInfo.ppEnabledLayerNames = instanceLayers.data();
+
+    wprintf(L"Vulkan API version: ");
+    switch(appInfo.apiVersion)
+    {
+    case VK_API_VERSION_1_0: wprintf(L"1.0\n"); break;
+    case VK_API_VERSION_1_1: wprintf(L"1.1\n"); break;
+    case VK_API_VERSION_1_2: wprintf(L"1.2\n"); break;
+    default: assert(0);
+    }
+
+    ERR_GUARD_VULKAN( vkCreateInstance(&instInfo, g_Allocs, &g_hVulkanInstance) );
+
+    // Create VkSurfaceKHR.
+    VkWin32SurfaceCreateInfoKHR surfaceInfo = { VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR };
+    surfaceInfo.hinstance = g_hAppInstance;
+    surfaceInfo.hwnd = g_hWnd;
+    VkResult result = vkCreateWin32SurfaceKHR(g_hVulkanInstance, &surfaceInfo, g_Allocs, &g_hSurface);
+    assert(result == VK_SUCCESS);
+
+    if(g_EnableValidationLayer == true)
+        RegisterDebugCallbacks();
+
+    // Find physical device
+
+    uint32_t deviceCount = 0;
+    ERR_GUARD_VULKAN( vkEnumeratePhysicalDevices(g_hVulkanInstance, &deviceCount, nullptr) );
+    assert(deviceCount > 0);
+
+    std::vector<VkPhysicalDevice> physicalDevices(deviceCount);
+    ERR_GUARD_VULKAN( vkEnumeratePhysicalDevices(g_hVulkanInstance, &deviceCount, physicalDevices.data()) );
+
+    g_hPhysicalDevice = physicalDevices[0];
+
+    // Query for device extensions
+
+    uint32_t physicalDeviceExtensionPropertyCount = 0;
+    ERR_GUARD_VULKAN( vkEnumerateDeviceExtensionProperties(g_hPhysicalDevice, nullptr, &physicalDeviceExtensionPropertyCount, nullptr) );
+    std::vector<VkExtensionProperties> physicalDeviceExtensionProperties{physicalDeviceExtensionPropertyCount};
+    if(physicalDeviceExtensionPropertyCount)
+    {
+        ERR_GUARD_VULKAN( vkEnumerateDeviceExtensionProperties(
+            g_hPhysicalDevice,
+            nullptr,
+            &physicalDeviceExtensionPropertyCount,
+            physicalDeviceExtensionProperties.data()) );
+    }
+
+    for(uint32_t i = 0; i < physicalDeviceExtensionPropertyCount; ++i)
+    {
+        if(strcmp(physicalDeviceExtensionProperties[i].extensionName, VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME) == 0)
+        {
+            if(GetVulkanApiVersion() == VK_API_VERSION_1_0)
+            {
+                VK_KHR_get_memory_requirements2_enabled = true;
+            }
+        }
+        else if(strcmp(physicalDeviceExtensionProperties[i].extensionName, VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME) == 0)
+        {
+            if(GetVulkanApiVersion() == VK_API_VERSION_1_0)
+            {
+                VK_KHR_dedicated_allocation_enabled = true;
+            }
+        }
+        else if(strcmp(physicalDeviceExtensionProperties[i].extensionName, VK_KHR_BIND_MEMORY_2_EXTENSION_NAME) == 0)
+        {
+            if(GetVulkanApiVersion() == VK_API_VERSION_1_0)
+            {
+                VK_KHR_bind_memory2_enabled = true;
+            }
+        }
+        else if(strcmp(physicalDeviceExtensionProperties[i].extensionName, VK_EXT_MEMORY_BUDGET_EXTENSION_NAME) == 0)
+            VK_EXT_memory_budget_enabled = true;
+        else if(strcmp(physicalDeviceExtensionProperties[i].extensionName, VK_AMD_DEVICE_COHERENT_MEMORY_EXTENSION_NAME) == 0)
+            VK_AMD_device_coherent_memory_enabled = true;
+        else if(strcmp(physicalDeviceExtensionProperties[i].extensionName, VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME) == 0)
+        {
+            if(GetVulkanApiVersion() < VK_API_VERSION_1_2)
+            {
+                VK_KHR_buffer_device_address_enabled = true;
+            }
+        }
+        else if(strcmp(physicalDeviceExtensionProperties[i].extensionName, VK_EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME) == 0)
+        {
+            if(GetVulkanApiVersion() < VK_API_VERSION_1_2)
+            {
+                VK_EXT_buffer_device_address_enabled = true;
+            }
+        }
+    }
+
+    if(VK_EXT_buffer_device_address_enabled && VK_KHR_buffer_device_address_enabled)
+        VK_EXT_buffer_device_address_enabled = false;
+
+    // Query for features
+
+    VkPhysicalDeviceProperties physicalDeviceProperties = {};
+    vkGetPhysicalDeviceProperties(g_hPhysicalDevice, &physicalDeviceProperties);
+
+    PrintPhysicalDeviceProperties(physicalDeviceProperties);
+
+    VkPhysicalDeviceFeatures2 physicalDeviceFeatures = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 };
+    
+    VkPhysicalDeviceCoherentMemoryFeaturesAMD physicalDeviceCoherentMemoryFeatures = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COHERENT_MEMORY_FEATURES_AMD };
+    if(VK_AMD_device_coherent_memory_enabled)
+    {
+        PnextChainPushFront(&physicalDeviceFeatures, &physicalDeviceCoherentMemoryFeatures);
+    }
+    
+    VkPhysicalDeviceBufferDeviceAddressFeaturesEXT physicalDeviceBufferDeviceAddressFeatures = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_EXT };
+    if(VK_KHR_buffer_device_address_enabled || VK_EXT_buffer_device_address_enabled || GetVulkanApiVersion() >= VK_API_VERSION_1_2)
+    {
+        PnextChainPushFront(&physicalDeviceFeatures, &physicalDeviceBufferDeviceAddressFeatures);
+    }
+
+    vkGetPhysicalDeviceFeatures2(g_hPhysicalDevice, &physicalDeviceFeatures);
+
+    g_SparseBindingEnabled = physicalDeviceFeatures.features.sparseBinding != 0;
+
+    // The extension is supported as fake with no real support for this feature? Don't use it.
+    if(VK_AMD_device_coherent_memory_enabled && !physicalDeviceCoherentMemoryFeatures.deviceCoherentMemory)
+        VK_AMD_device_coherent_memory_enabled = false;
+    if(VK_KHR_buffer_device_address_enabled || VK_EXT_buffer_device_address_enabled || GetVulkanApiVersion() >= VK_API_VERSION_1_2)
+        g_BufferDeviceAddressEnabled = physicalDeviceBufferDeviceAddressFeatures.bufferDeviceAddress != VK_FALSE;
+
+    // Find queue family index
+
+    uint32_t queueFamilyCount = 0;
+    vkGetPhysicalDeviceQueueFamilyProperties(g_hPhysicalDevice, &queueFamilyCount, nullptr);
+    assert(queueFamilyCount > 0);
+    std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
+    vkGetPhysicalDeviceQueueFamilyProperties(g_hPhysicalDevice, &queueFamilyCount, queueFamilies.data());
+    for(uint32_t i = 0;
+        (i < queueFamilyCount) &&
+            (g_GraphicsQueueFamilyIndex == UINT_MAX ||
+                g_PresentQueueFamilyIndex == UINT_MAX ||
+                (g_SparseBindingEnabled && g_SparseBindingQueueFamilyIndex == UINT_MAX));
+        ++i)
+    {
+        if(queueFamilies[i].queueCount > 0)
+        {
+            const uint32_t flagsForGraphicsQueue = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT;
+            if((g_GraphicsQueueFamilyIndex != 0) &&
+                ((queueFamilies[i].queueFlags & flagsForGraphicsQueue) == flagsForGraphicsQueue))
+            {
+                g_GraphicsQueueFamilyIndex = i;
+            }
+
+            VkBool32 surfaceSupported = 0;
+            VkResult res = vkGetPhysicalDeviceSurfaceSupportKHR(g_hPhysicalDevice, i, g_hSurface, &surfaceSupported);
+            if((res >= 0) && (surfaceSupported == VK_TRUE))
+            {
+                g_PresentQueueFamilyIndex = i;
+            }
+
+            if(g_SparseBindingEnabled &&
+                g_SparseBindingQueueFamilyIndex == UINT32_MAX &&
+                (queueFamilies[i].queueFlags & VK_QUEUE_SPARSE_BINDING_BIT) != 0)
+            {
+                g_SparseBindingQueueFamilyIndex = i;
+            }
+        }
+    }
+    assert(g_GraphicsQueueFamilyIndex != UINT_MAX);
+
+    g_SparseBindingEnabled = g_SparseBindingEnabled && g_SparseBindingQueueFamilyIndex != UINT32_MAX;
+
+    // Create logical device
+
+    const float queuePriority = 1.f;
+
+    VkDeviceQueueCreateInfo queueCreateInfo[3] = {};
+    uint32_t queueCount = 1;
+    queueCreateInfo[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
+    queueCreateInfo[0].queueFamilyIndex = g_GraphicsQueueFamilyIndex;
+    queueCreateInfo[0].queueCount = 1;
+    queueCreateInfo[0].pQueuePriorities = &queuePriority;
+    
+    if(g_PresentQueueFamilyIndex != g_GraphicsQueueFamilyIndex)
+    {
+
+        queueCreateInfo[queueCount].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
+        queueCreateInfo[queueCount].queueFamilyIndex = g_PresentQueueFamilyIndex;
+        queueCreateInfo[queueCount].queueCount = 1;
+        queueCreateInfo[queueCount].pQueuePriorities = &queuePriority;
+        ++queueCount;
+    }
+    
+    if(g_SparseBindingEnabled &&
+        g_SparseBindingQueueFamilyIndex != g_GraphicsQueueFamilyIndex &&
+        g_SparseBindingQueueFamilyIndex != g_PresentQueueFamilyIndex)
+    {
+
+        queueCreateInfo[queueCount].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
+        queueCreateInfo[queueCount].queueFamilyIndex = g_SparseBindingQueueFamilyIndex;
+        queueCreateInfo[queueCount].queueCount = 1;
+        queueCreateInfo[queueCount].pQueuePriorities = &queuePriority;
+        ++queueCount;
+    }
+
+    std::vector<const char*> enabledDeviceExtensions;
+    enabledDeviceExtensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
+    if(VK_KHR_get_memory_requirements2_enabled)
+        enabledDeviceExtensions.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME);
+    if(VK_KHR_dedicated_allocation_enabled)
+        enabledDeviceExtensions.push_back(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME);
+    if(VK_KHR_bind_memory2_enabled)
+        enabledDeviceExtensions.push_back(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME);
+    if(VK_EXT_memory_budget_enabled)
+        enabledDeviceExtensions.push_back(VK_EXT_MEMORY_BUDGET_EXTENSION_NAME);
+    if(VK_AMD_device_coherent_memory_enabled)
+        enabledDeviceExtensions.push_back(VK_AMD_DEVICE_COHERENT_MEMORY_EXTENSION_NAME);
+    if(VK_KHR_buffer_device_address_enabled)
+        enabledDeviceExtensions.push_back(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
+    if(VK_EXT_buffer_device_address_enabled)
+        enabledDeviceExtensions.push_back(VK_EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
+
+    VkPhysicalDeviceFeatures2 deviceFeatures = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 };
+    deviceFeatures.features.samplerAnisotropy = VK_TRUE;
+    deviceFeatures.features.sparseBinding = g_SparseBindingEnabled ? VK_TRUE : VK_FALSE;
+
+    if(VK_AMD_device_coherent_memory_enabled)
+    {
+        physicalDeviceCoherentMemoryFeatures.deviceCoherentMemory = VK_TRUE;
+        PnextChainPushBack(&deviceFeatures, &physicalDeviceCoherentMemoryFeatures);
+    }
+    if(g_BufferDeviceAddressEnabled)
+    {
+        physicalDeviceBufferDeviceAddressFeatures = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_EXT };
+        physicalDeviceBufferDeviceAddressFeatures.bufferDeviceAddress = VK_TRUE;
+        PnextChainPushBack(&deviceFeatures, &physicalDeviceBufferDeviceAddressFeatures);
+    }
+
+    VkDeviceCreateInfo deviceCreateInfo = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO };
+    deviceCreateInfo.pNext = &deviceFeatures;
+    deviceCreateInfo.enabledLayerCount = 0;
+    deviceCreateInfo.ppEnabledLayerNames = nullptr;
+    deviceCreateInfo.enabledExtensionCount = (uint32_t)enabledDeviceExtensions.size();
+    deviceCreateInfo.ppEnabledExtensionNames = !enabledDeviceExtensions.empty() ? enabledDeviceExtensions.data() : nullptr;
+    deviceCreateInfo.queueCreateInfoCount = queueCount;
+    deviceCreateInfo.pQueueCreateInfos = queueCreateInfo;
+
+    ERR_GUARD_VULKAN( vkCreateDevice(g_hPhysicalDevice, &deviceCreateInfo, g_Allocs, &g_hDevice) );
+
+    // Fetch pointers to extension functions
+    if(g_BufferDeviceAddressEnabled)
+    {
+        if(GetVulkanApiVersion() >= VK_API_VERSION_1_2)
+        {
+            g_vkGetBufferDeviceAddressEXT = (PFN_vkGetBufferDeviceAddressEXT)vkGetDeviceProcAddr(g_hDevice, "vkGetBufferDeviceAddress");
+            //assert(g_vkGetBufferDeviceAddressEXT != nullptr);
+            /*
+            For some reason this doesn't work, the pointer is NULL :( None of the below methods help.
+
+            Validation layers also report following error:
+            [ VUID-VkMemoryAllocateInfo-flags-03331 ] Object: VK_NULL_HANDLE (Type = 0) | If VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR is set, bufferDeviceAddress must be enabled. The Vulkan spec states: If VkMemoryAllocateFlagsInfo::flags includes VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT, the bufferDeviceAddress feature must be enabled (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkMemoryAllocateInfo-flags-03331)
+            Despite I'm posting VkPhysicalDeviceBufferDeviceAddressFeaturesEXT::bufferDeviceAddress = VK_TRUE in VkDeviceCreateInfo::pNext chain.
+
+            if(g_vkGetBufferDeviceAddressEXT == nullptr)
+            {
+                g_vkGetBufferDeviceAddressEXT = &vkGetBufferDeviceAddress; // Doesn't run, cannot find entry point...
+            }
+
+            if(g_vkGetBufferDeviceAddressEXT == nullptr)
+            {
+                g_vkGetBufferDeviceAddressEXT = (PFN_vkGetBufferDeviceAddressEXT)vkGetInstanceProcAddr(g_hVulkanInstance, "vkGetBufferDeviceAddress");
+            }
+            if(g_vkGetBufferDeviceAddressEXT == nullptr)
+            {
+                g_vkGetBufferDeviceAddressEXT = (PFN_vkGetBufferDeviceAddressEXT)vkGetDeviceProcAddr(g_hDevice, "vkGetBufferDeviceAddressKHR");
+            }
+            if(g_vkGetBufferDeviceAddressEXT == nullptr)
+            {
+                g_vkGetBufferDeviceAddressEXT = (PFN_vkGetBufferDeviceAddressEXT)vkGetDeviceProcAddr(g_hDevice, "vkGetBufferDeviceAddressEXT");
+            }
+            */
+        }
+        else if(VK_KHR_buffer_device_address_enabled)
+        {
+            g_vkGetBufferDeviceAddressEXT = (PFN_vkGetBufferDeviceAddressEXT)vkGetDeviceProcAddr(g_hDevice, "vkGetBufferDeviceAddressKHR");
+            assert(g_vkGetBufferDeviceAddressEXT != nullptr);
+        }
+        else if(VK_EXT_buffer_device_address_enabled)
+        {
+            g_vkGetBufferDeviceAddressEXT = (PFN_vkGetBufferDeviceAddressEXT)vkGetDeviceProcAddr(g_hDevice, "vkGetBufferDeviceAddressEXT");
+            assert(g_vkGetBufferDeviceAddressEXT != nullptr);
+        }
+    }
+
+    // Create memory allocator
+
+    VmaAllocatorCreateInfo allocatorInfo = {};
+    SetAllocatorCreateInfo(allocatorInfo);
+    ERR_GUARD_VULKAN( vmaCreateAllocator(&allocatorInfo, &g_hAllocator) );
+
+    PrintEnabledFeatures();
+
+    // Retrieve queues (don't need to be destroyed).
+
+    vkGetDeviceQueue(g_hDevice, g_GraphicsQueueFamilyIndex, 0, &g_hGraphicsQueue);
+    vkGetDeviceQueue(g_hDevice, g_PresentQueueFamilyIndex, 0, &g_hPresentQueue);
+    assert(g_hGraphicsQueue);
+    assert(g_hPresentQueue);
+
+    if(g_SparseBindingEnabled)
+    {
+        vkGetDeviceQueue(g_hDevice, g_SparseBindingQueueFamilyIndex, 0, &g_hSparseBindingQueue);
+        assert(g_hSparseBindingQueue);
+    }
+
+    // Create command pool
+
+    VkCommandPoolCreateInfo commandPoolInfo = { VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO };
+    commandPoolInfo.queueFamilyIndex = g_GraphicsQueueFamilyIndex;
+    commandPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
+    ERR_GUARD_VULKAN( vkCreateCommandPool(g_hDevice, &commandPoolInfo, g_Allocs, &g_hCommandPool) );
+
+    VkCommandBufferAllocateInfo commandBufferInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO };
+    commandBufferInfo.commandPool = g_hCommandPool;
+    commandBufferInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+    commandBufferInfo.commandBufferCount = COMMAND_BUFFER_COUNT;
+    ERR_GUARD_VULKAN( vkAllocateCommandBuffers(g_hDevice, &commandBufferInfo, g_MainCommandBuffers) );
+
+    VkFenceCreateInfo fenceInfo = { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO };
+    fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
+    for(size_t i = 0; i < COMMAND_BUFFER_COUNT; ++i)
+    {
+        ERR_GUARD_VULKAN( vkCreateFence(g_hDevice, &fenceInfo, g_Allocs, &g_MainCommandBufferExecutedFances[i]) );
+    }
+
+    ERR_GUARD_VULKAN( vkCreateFence(g_hDevice, &fenceInfo, g_Allocs, &g_ImmediateFence) );
+
+    commandBufferInfo.commandBufferCount = 1;
+    ERR_GUARD_VULKAN( vkAllocateCommandBuffers(g_hDevice, &commandBufferInfo, &g_hTemporaryCommandBuffer) );
+
+    // Create texture sampler
+
+    VkSamplerCreateInfo samplerInfo = { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO };
+    samplerInfo.magFilter = VK_FILTER_LINEAR;
+    samplerInfo.minFilter = VK_FILTER_LINEAR;
+    samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
+    samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
+    samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
+    samplerInfo.anisotropyEnable = VK_TRUE;
+    samplerInfo.maxAnisotropy = 16;
+    samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
+    samplerInfo.unnormalizedCoordinates = VK_FALSE;
+    samplerInfo.compareEnable = VK_FALSE;
+    samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
+    samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
+    samplerInfo.mipLodBias = 0.f;
+    samplerInfo.minLod = 0.f;
+    samplerInfo.maxLod = FLT_MAX;
+    ERR_GUARD_VULKAN( vkCreateSampler(g_hDevice, &samplerInfo, g_Allocs, &g_hSampler) );
+
+    CreateTexture(128, 128);
+    CreateMesh();
+
+    VkDescriptorSetLayoutBinding samplerLayoutBinding = {};
+    samplerLayoutBinding.binding = 1;
+    samplerLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+    samplerLayoutBinding.descriptorCount = 1;
+    samplerLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
+
+    VkDescriptorSetLayoutCreateInfo descriptorSetLayoutInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO };
+    descriptorSetLayoutInfo.bindingCount = 1;
+    descriptorSetLayoutInfo.pBindings = &samplerLayoutBinding;
+    ERR_GUARD_VULKAN( vkCreateDescriptorSetLayout(g_hDevice, &descriptorSetLayoutInfo, g_Allocs, &g_hDescriptorSetLayout) );
+
+    // Create descriptor pool
+
+    VkDescriptorPoolSize descriptorPoolSizes[2];
+    ZeroMemory(descriptorPoolSizes, sizeof(descriptorPoolSizes));
+    descriptorPoolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+    descriptorPoolSizes[0].descriptorCount = 1;
+    descriptorPoolSizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+    descriptorPoolSizes[1].descriptorCount = 1;
+
+    VkDescriptorPoolCreateInfo descriptorPoolInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO };
+    descriptorPoolInfo.poolSizeCount = (uint32_t)_countof(descriptorPoolSizes);
+    descriptorPoolInfo.pPoolSizes = descriptorPoolSizes;
+    descriptorPoolInfo.maxSets = 1;
+    ERR_GUARD_VULKAN( vkCreateDescriptorPool(g_hDevice, &descriptorPoolInfo, g_Allocs, &g_hDescriptorPool) );
+
+    // Create descriptor set layout
+
+    VkDescriptorSetLayout descriptorSetLayouts[] = { g_hDescriptorSetLayout };
+    VkDescriptorSetAllocateInfo descriptorSetInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO };
+    descriptorSetInfo.descriptorPool = g_hDescriptorPool;
+    descriptorSetInfo.descriptorSetCount = 1;
+    descriptorSetInfo.pSetLayouts = descriptorSetLayouts;
+    ERR_GUARD_VULKAN( vkAllocateDescriptorSets(g_hDevice, &descriptorSetInfo, &g_hDescriptorSet) );
+
+    VkDescriptorImageInfo descriptorImageInfo = {};
+    descriptorImageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+    descriptorImageInfo.imageView = g_hTextureImageView;
+    descriptorImageInfo.sampler = g_hSampler;
+
+    VkWriteDescriptorSet writeDescriptorSet = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET };
+    writeDescriptorSet.dstSet = g_hDescriptorSet;
+    writeDescriptorSet.dstBinding = 1;
+    writeDescriptorSet.dstArrayElement = 0;
+    writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+    writeDescriptorSet.descriptorCount = 1;
+    writeDescriptorSet.pImageInfo = &descriptorImageInfo;
+
+    vkUpdateDescriptorSets(g_hDevice, 1, &writeDescriptorSet, 0, nullptr);
+
+    CreateSwapchain();
+}
+
+static void FinalizeApplication()
+{
+    vkDeviceWaitIdle(g_hDevice);
+
+    DestroySwapchain(true);
+
+    if(g_hDescriptorPool != VK_NULL_HANDLE)
+    {
+        vkDestroyDescriptorPool(g_hDevice, g_hDescriptorPool, g_Allocs);
+        g_hDescriptorPool = VK_NULL_HANDLE;
+    }
+
+    if(g_hDescriptorSetLayout != VK_NULL_HANDLE)
+    {
+        vkDestroyDescriptorSetLayout(g_hDevice, g_hDescriptorSetLayout, g_Allocs);
+        g_hDescriptorSetLayout = VK_NULL_HANDLE;
+    }
+
+    if(g_hTextureImageView != VK_NULL_HANDLE)
+    {
+        vkDestroyImageView(g_hDevice, g_hTextureImageView, g_Allocs);
+        g_hTextureImageView = VK_NULL_HANDLE;
+    }
+    if(g_hTextureImage != VK_NULL_HANDLE)
+    {
+        vmaDestroyImage(g_hAllocator, g_hTextureImage, g_hTextureImageAlloc);
+        g_hTextureImage = VK_NULL_HANDLE;
+    }
+
+    if(g_hIndexBuffer != VK_NULL_HANDLE)
+    {
+        vmaDestroyBuffer(g_hAllocator, g_hIndexBuffer, g_hIndexBufferAlloc);
+        g_hIndexBuffer = VK_NULL_HANDLE;
+    }
+    if(g_hVertexBuffer != VK_NULL_HANDLE)
+    {
+        vmaDestroyBuffer(g_hAllocator, g_hVertexBuffer, g_hVertexBufferAlloc);
+        g_hVertexBuffer = VK_NULL_HANDLE;
+    }
+    
+    if(g_hSampler != VK_NULL_HANDLE)
+    {
+        vkDestroySampler(g_hDevice, g_hSampler, g_Allocs);
+        g_hSampler = VK_NULL_HANDLE;
+    }
+
+    if(g_ImmediateFence)
+    {
+        vkDestroyFence(g_hDevice, g_ImmediateFence, g_Allocs);
+        g_ImmediateFence = VK_NULL_HANDLE;
+    }
+
+    for(size_t i = COMMAND_BUFFER_COUNT; i--; )
+    {
+        if(g_MainCommandBufferExecutedFances[i] != VK_NULL_HANDLE)
+        {
+            vkDestroyFence(g_hDevice, g_MainCommandBufferExecutedFances[i], g_Allocs);
+            g_MainCommandBufferExecutedFances[i] = VK_NULL_HANDLE;
+        }
+    }
+    if(g_MainCommandBuffers[0] != VK_NULL_HANDLE)
+    {
+        vkFreeCommandBuffers(g_hDevice, g_hCommandPool, COMMAND_BUFFER_COUNT, g_MainCommandBuffers);
+        ZeroMemory(g_MainCommandBuffers, sizeof(g_MainCommandBuffers));
+    }
+    if(g_hTemporaryCommandBuffer != VK_NULL_HANDLE)
+    {
+        vkFreeCommandBuffers(g_hDevice, g_hCommandPool, 1, &g_hTemporaryCommandBuffer);
+        g_hTemporaryCommandBuffer = VK_NULL_HANDLE;
+    }
+
+    if(g_hCommandPool != VK_NULL_HANDLE)
+    {
+        vkDestroyCommandPool(g_hDevice, g_hCommandPool, g_Allocs);
+        g_hCommandPool = VK_NULL_HANDLE;
+    }
+
+    if(g_hAllocator != VK_NULL_HANDLE)
+    {
+        vmaDestroyAllocator(g_hAllocator);
+        g_hAllocator = nullptr;
+    }
+
+    if(g_hDevice != VK_NULL_HANDLE)
+    {
+        vkDestroyDevice(g_hDevice, g_Allocs);
+        g_hDevice = nullptr;
+    }
+
+    if(g_pvkDestroyDebugReportCallbackEXT && g_hCallback != VK_NULL_HANDLE)
+    {
+        g_pvkDestroyDebugReportCallbackEXT(g_hVulkanInstance, g_hCallback, g_Allocs);
+        g_hCallback = VK_NULL_HANDLE;
+    }
+
+    if(g_hSurface != VK_NULL_HANDLE)
+    {
+        vkDestroySurfaceKHR(g_hVulkanInstance, g_hSurface, g_Allocs);
+        g_hSurface = VK_NULL_HANDLE;
+    }
+
+    if(g_hVulkanInstance != VK_NULL_HANDLE)
+    {
+        vkDestroyInstance(g_hVulkanInstance, g_Allocs);
+        g_hVulkanInstance = VK_NULL_HANDLE;
+    }
+}
+
+static void PrintAllocatorStats()
+{
+#if VMA_STATS_STRING_ENABLED
+    char* statsString = nullptr;
+    vmaBuildStatsString(g_hAllocator, &statsString, true);
+    printf("%s\n", statsString);
+    vmaFreeStatsString(g_hAllocator, statsString);
+#endif
+}
+
+static void RecreateSwapChain()
+{
+    vkDeviceWaitIdle(g_hDevice);
+    DestroySwapchain(false);
+    CreateSwapchain();
+}
+
+static void DrawFrame()
+{
+    // Begin main command buffer
+    size_t cmdBufIndex = (g_NextCommandBufferIndex++) % COMMAND_BUFFER_COUNT;
+    VkCommandBuffer hCommandBuffer = g_MainCommandBuffers[cmdBufIndex];
+    VkFence hCommandBufferExecutedFence = g_MainCommandBufferExecutedFances[cmdBufIndex];
+
+    ERR_GUARD_VULKAN( vkWaitForFences(g_hDevice, 1, &hCommandBufferExecutedFence, VK_TRUE, UINT64_MAX) );
+    ERR_GUARD_VULKAN( vkResetFences(g_hDevice, 1, &hCommandBufferExecutedFence) );
+
+    VkCommandBufferBeginInfo commandBufferBeginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
+    commandBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
+    ERR_GUARD_VULKAN( vkBeginCommandBuffer(hCommandBuffer, &commandBufferBeginInfo) );
+    
+    // Acquire swapchain image
+    uint32_t imageIndex = 0;
+    VkResult res = vkAcquireNextImageKHR(g_hDevice, g_hSwapchain, UINT64_MAX, g_hImageAvailableSemaphore, VK_NULL_HANDLE, &imageIndex);
+    if(res == VK_ERROR_OUT_OF_DATE_KHR)
+    {
+        RecreateSwapChain();
+        return;
+    }
+    else if(res < 0)
+    {
+        ERR_GUARD_VULKAN(res);
+    }
+
+    // Record geometry pass
+
+    VkClearValue clearValues[2];
+    ZeroMemory(clearValues, sizeof(clearValues));
+    clearValues[0].color.float32[0] = 0.25f;
+    clearValues[0].color.float32[1] = 0.25f;
+    clearValues[0].color.float32[2] = 0.5f;
+    clearValues[0].color.float32[3] = 1.0f;
+    clearValues[1].depthStencil.depth = 1.0f;
+
+    VkRenderPassBeginInfo renderPassBeginInfo = { VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO };
+    renderPassBeginInfo.renderPass = g_hRenderPass;
+    renderPassBeginInfo.framebuffer = g_Framebuffers[imageIndex];
+    renderPassBeginInfo.renderArea.offset.x = 0;
+    renderPassBeginInfo.renderArea.offset.y = 0;
+    renderPassBeginInfo.renderArea.extent = g_Extent;
+    renderPassBeginInfo.clearValueCount = (uint32_t)_countof(clearValues);
+    renderPassBeginInfo.pClearValues = clearValues;
+    vkCmdBeginRenderPass(hCommandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
+    
+    vkCmdBindPipeline(
+        hCommandBuffer,
+        VK_PIPELINE_BIND_POINT_GRAPHICS,
+        g_hPipeline);
+
+    mat4 view = mat4::LookAt(
+        vec3(0.f, 0.f, 0.f),
+        vec3(0.f, -2.f, 4.f),
+        vec3(0.f, 1.f, 0.f));
+    mat4 proj = mat4::Perspective(
+        1.0471975511966f, // 60 degrees
+        (float)g_Extent.width / (float)g_Extent.height,
+        0.1f,
+        1000.f);
+    mat4 viewProj = view * proj;
+
+    vkCmdBindDescriptorSets(
+        hCommandBuffer,
+        VK_PIPELINE_BIND_POINT_GRAPHICS,
+        g_hPipelineLayout,
+        0,
+        1,
+        &g_hDescriptorSet,
+        0,
+        nullptr);
+
+    float rotationAngle = (float)GetTickCount() * 0.001f * (float)PI * 0.2f;
+    mat4 model = mat4::RotationY(rotationAngle);
+
+    UniformBufferObject ubo = {};
+    ubo.ModelViewProj = model * viewProj;
+    vkCmdPushConstants(hCommandBuffer, g_hPipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(UniformBufferObject), &ubo);
+
+    VkBuffer vertexBuffers[] = { g_hVertexBuffer };
+    VkDeviceSize offsets[] = { 0 };
+    vkCmdBindVertexBuffers(hCommandBuffer, 0, 1, vertexBuffers, offsets);
+
+    vkCmdBindIndexBuffer(hCommandBuffer, g_hIndexBuffer, 0, VK_INDEX_TYPE_UINT16);
+
+    vkCmdDrawIndexed(hCommandBuffer, g_IndexCount, 1, 0, 0, 0);
+
+    vkCmdEndRenderPass(hCommandBuffer);
+    
+    vkEndCommandBuffer(hCommandBuffer);
+
+    // Submit command buffer
+    
+    VkSemaphore submitWaitSemaphores[] = { g_hImageAvailableSemaphore };
+    VkPipelineStageFlags submitWaitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
+    VkSemaphore submitSignalSemaphores[] = { g_hRenderFinishedSemaphore };
+    VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO };
+    submitInfo.waitSemaphoreCount = 1;
+    submitInfo.pWaitSemaphores = submitWaitSemaphores;
+    submitInfo.pWaitDstStageMask = submitWaitStages;
+    submitInfo.commandBufferCount = 1;
+    submitInfo.pCommandBuffers = &hCommandBuffer;
+    submitInfo.signalSemaphoreCount = _countof(submitSignalSemaphores);
+    submitInfo.pSignalSemaphores = submitSignalSemaphores;
+    ERR_GUARD_VULKAN( vkQueueSubmit(g_hGraphicsQueue, 1, &submitInfo, hCommandBufferExecutedFence) );
+
+    VkSemaphore presentWaitSemaphores[] = { g_hRenderFinishedSemaphore };
+
+    VkSwapchainKHR swapchains[] = { g_hSwapchain };
+    VkPresentInfoKHR presentInfo = { VK_STRUCTURE_TYPE_PRESENT_INFO_KHR };
+    presentInfo.waitSemaphoreCount = _countof(presentWaitSemaphores);
+    presentInfo.pWaitSemaphores = presentWaitSemaphores;
+    presentInfo.swapchainCount = 1;
+    presentInfo.pSwapchains = swapchains;
+    presentInfo.pImageIndices = &imageIndex;
+    presentInfo.pResults = nullptr;
+    res = vkQueuePresentKHR(g_hPresentQueue, &presentInfo);
+    if(res == VK_ERROR_OUT_OF_DATE_KHR)
+    {
+        RecreateSwapChain();
+    }
+    else
+        ERR_GUARD_VULKAN(res);
+}
+
+static void HandlePossibleSizeChange()
+{
+    RECT clientRect;
+    GetClientRect(g_hWnd, &clientRect);
+    LONG newSizeX = clientRect.right - clientRect.left;
+    LONG newSizeY = clientRect.bottom - clientRect.top;
+    if((newSizeX > 0) &&
+        (newSizeY > 0) &&
+        ((newSizeX != g_SizeX) || (newSizeY != g_SizeY)))
+    {
+        g_SizeX = newSizeX;
+        g_SizeY = newSizeY;
+
+        RecreateSwapChain();
+    }
+}
+
+static LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+    switch(msg)
+    {
+    case WM_CREATE:
+        // This is intentionally assigned here because we are now inside CreateWindow, before it returns.
+        g_hWnd = hWnd;
+        InitializeApplication();
+        PrintAllocatorStats();
+        return 0;
+
+    case WM_DESTROY:
+        FinalizeApplication();
+        PostQuitMessage(0);
+        return 0;
+
+    // This prevents app from freezing when left Alt is pressed
+    // (which normally enters modal menu loop).
+    case WM_SYSKEYDOWN:
+    case WM_SYSKEYUP:
+        return 0;
+
+    case WM_SIZE:
+        if((wParam == SIZE_MAXIMIZED) || (wParam == SIZE_RESTORED))
+            HandlePossibleSizeChange();
+        return 0;
+
+    case WM_EXITSIZEMOVE:
+        HandlePossibleSizeChange();
+        return 0;
+
+    case WM_KEYDOWN:
+        switch(wParam)
+        {
+        case VK_ESCAPE:
+            PostMessage(hWnd, WM_CLOSE, 0, 0);
+            break;
+        case 'T':
+            try
+            {
+                Test();
+            }
+            catch(const std::exception& ex)
+            {
+                printf("ERROR: %s\n", ex.what());
+            }
+            break;
+        case 'S':
+            try
+            {
+                if(g_SparseBindingEnabled)
+                {
+                    TestSparseBinding();
+                }
+                else
+                {
+                    printf("Sparse binding not supported.\n");
+                }
+            }
+            catch(const std::exception& ex)
+            {
+                printf("ERROR: %s\n", ex.what());
+            }
+            break;
+        }
+        return 0;
+
+    default:
+        break;
+    }
+
+    return DefWindowProc(hWnd, msg, wParam, lParam);
+}
+
+int main()
+{
+    g_hAppInstance = (HINSTANCE)GetModuleHandle(NULL);
+
+    WNDCLASSEX wndClassDesc = { sizeof(WNDCLASSEX) };
+    wndClassDesc.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
+    wndClassDesc.hbrBackground = NULL;
+    wndClassDesc.hCursor = LoadCursor(NULL, IDC_CROSS);
+    wndClassDesc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
+    wndClassDesc.hInstance = g_hAppInstance;
+    wndClassDesc.lpfnWndProc = WndProc;
+    wndClassDesc.lpszClassName = WINDOW_CLASS_NAME;
+    
+    const ATOM hWndClass = RegisterClassEx(&wndClassDesc);
+    assert(hWndClass);
+
+    const DWORD style = WS_VISIBLE | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME;
+    const DWORD exStyle = 0;
+
+    RECT rect = { 0, 0, g_SizeX, g_SizeY };
+    AdjustWindowRectEx(&rect, style, FALSE, exStyle);
+
+    CreateWindowEx(
+        exStyle, WINDOW_CLASS_NAME, APP_TITLE_W, style,
+        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
+        NULL, NULL, g_hAppInstance, NULL);
+
+    MSG msg;
+    for(;;)
+    {
+        if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
+        {
+            if(msg.message == WM_QUIT)
+                break;
+            TranslateMessage(&msg);
+            DispatchMessage(&msg);
+        }
+        if(g_hDevice != VK_NULL_HANDLE)
+            DrawFrame();
+    }
+
+    TEST(g_CpuAllocCount.load() == 0);
+
+    return 0;
+}
+
+#else // #ifdef _WIN32
+
+#include "VmaUsage.h"
+
+int main()
+{
+}
+
+#endif // #ifdef _WIN32
diff --git a/third_party/VulkanMemoryAllocator/src/vk_mem_alloc.h b/third_party/VulkanMemoryAllocator/src/vk_mem_alloc.h
new file mode 100644
index 0000000..e8da257
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/src/vk_mem_alloc.h
@@ -0,0 +1,18574 @@
+//
+// Copyright (c) 2017-2020 Advanced Micro Devices, Inc. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#ifndef AMD_VULKAN_MEMORY_ALLOCATOR_H
+#define AMD_VULKAN_MEMORY_ALLOCATOR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** \mainpage Vulkan Memory Allocator
+
+<b>Version 3.0.0-development</b> (2020-03-23)
+
+Copyright (c) 2017-2020 Advanced Micro Devices, Inc. All rights reserved. \n
+License: MIT
+
+Documentation of all members: vk_mem_alloc.h
+
+\section main_table_of_contents Table of contents
+
+- <b>User guide</b>
+  - \subpage quick_start
+    - [Project setup](@ref quick_start_project_setup)
+    - [Initialization](@ref quick_start_initialization)
+    - [Resource allocation](@ref quick_start_resource_allocation)
+  - \subpage choosing_memory_type
+    - [Usage](@ref choosing_memory_type_usage)
+    - [Required and preferred flags](@ref choosing_memory_type_required_preferred_flags)
+    - [Explicit memory types](@ref choosing_memory_type_explicit_memory_types)
+    - [Custom memory pools](@ref choosing_memory_type_custom_memory_pools)
+    - [Dedicated allocations](@ref choosing_memory_type_dedicated_allocations)
+  - \subpage memory_mapping
+    - [Mapping functions](@ref memory_mapping_mapping_functions)
+    - [Persistently mapped memory](@ref memory_mapping_persistently_mapped_memory)
+    - [Cache flush and invalidate](@ref memory_mapping_cache_control)
+    - [Finding out if memory is mappable](@ref memory_mapping_finding_if_memory_mappable)
+  - \subpage staying_within_budget
+    - [Querying for budget](@ref staying_within_budget_querying_for_budget)
+    - [Controlling memory usage](@ref staying_within_budget_controlling_memory_usage)
+  - \subpage custom_memory_pools
+    - [Choosing memory type index](@ref custom_memory_pools_MemTypeIndex)
+    - [Linear allocation algorithm](@ref linear_algorithm)
+      - [Free-at-once](@ref linear_algorithm_free_at_once)
+      - [Stack](@ref linear_algorithm_stack)
+      - [Double stack](@ref linear_algorithm_double_stack)
+      - [Ring buffer](@ref linear_algorithm_ring_buffer)
+    - [Buddy allocation algorithm](@ref buddy_algorithm)
+  - \subpage defragmentation
+  	- [Defragmenting CPU memory](@ref defragmentation_cpu)
+  	- [Defragmenting GPU memory](@ref defragmentation_gpu)
+  	- [Additional notes](@ref defragmentation_additional_notes)
+  	- [Writing custom allocation algorithm](@ref defragmentation_custom_algorithm)
+  - \subpage lost_allocations
+  - \subpage statistics
+    - [Numeric statistics](@ref statistics_numeric_statistics)
+    - [JSON dump](@ref statistics_json_dump)
+  - \subpage allocation_annotation
+    - [Allocation user data](@ref allocation_user_data)
+    - [Allocation names](@ref allocation_names)
+  - \subpage debugging_memory_usage
+    - [Memory initialization](@ref debugging_memory_usage_initialization)
+    - [Margins](@ref debugging_memory_usage_margins)
+    - [Corruption detection](@ref debugging_memory_usage_corruption_detection)
+  - \subpage record_and_replay
+- \subpage usage_patterns
+  - [Common mistakes](@ref usage_patterns_common_mistakes)
+  - [Simple patterns](@ref usage_patterns_simple)
+  - [Advanced patterns](@ref usage_patterns_advanced)
+- \subpage configuration
+  - [Pointers to Vulkan functions](@ref config_Vulkan_functions)
+  - [Custom host memory allocator](@ref custom_memory_allocator)
+  - [Device memory allocation callbacks](@ref allocation_callbacks)
+  - [Device heap memory limit](@ref heap_memory_limit)
+  - \subpage vk_khr_dedicated_allocation
+  - \subpage enabling_buffer_device_address
+  - \subpage vk_amd_device_coherent_memory
+- \subpage general_considerations
+  - [Thread safety](@ref general_considerations_thread_safety)
+  - [Validation layer warnings](@ref general_considerations_validation_layer_warnings)
+  - [Allocation algorithm](@ref general_considerations_allocation_algorithm)
+  - [Features not supported](@ref general_considerations_features_not_supported)
+
+\section main_see_also See also
+
+- [Product page on GPUOpen](https://gpuopen.com/gaming-product/vulkan-memory-allocator/)
+- [Source repository on GitHub](https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator)
+
+
+
+
+\page quick_start Quick start
+
+\section quick_start_project_setup Project setup
+
+Vulkan Memory Allocator comes in form of a "stb-style" single header file.
+You don't need to build it as a separate library project.
+You can add this file directly to your project and submit it to code repository next to your other source files.
+
+"Single header" doesn't mean that everything is contained in C/C++ declarations,
+like it tends to be in case of inline functions or C++ templates.
+It means that implementation is bundled with interface in a single file and needs to be extracted using preprocessor macro.
+If you don't do it properly, you will get linker errors.
+
+To do it properly:
+
+-# Include "vk_mem_alloc.h" file in each CPP file where you want to use the library.
+   This includes declarations of all members of the library.
+-# In exacly one CPP file define following macro before this include.
+   It enables also internal definitions.
+
+\code
+#define VMA_IMPLEMENTATION
+#include "vk_mem_alloc.h"
+\endcode
+
+It may be a good idea to create dedicated CPP file just for this purpose.
+
+Note on language: This library is written in C++, but has C-compatible interface.
+Thus you can include and use vk_mem_alloc.h in C or C++ code, but full
+implementation with `VMA_IMPLEMENTATION` macro must be compiled as C++, NOT as C.
+
+Please note that this library includes header `<vulkan/vulkan.h>`, which in turn
+includes `<windows.h>` on Windows. If you need some specific macros defined
+before including these headers (like `WIN32_LEAN_AND_MEAN` or
+`WINVER` for Windows, `VK_USE_PLATFORM_WIN32_KHR` for Vulkan), you must define
+them before every `#include` of this library.
+
+
+\section quick_start_initialization Initialization
+
+At program startup:
+
+-# Initialize Vulkan to have `VkPhysicalDevice` and `VkDevice` object.
+-# Fill VmaAllocatorCreateInfo structure and create #VmaAllocator object by
+   calling vmaCreateAllocator().
+
+\code
+VmaAllocatorCreateInfo allocatorInfo = {};
+allocatorInfo.physicalDevice = physicalDevice;
+allocatorInfo.device = device;
+
+VmaAllocator allocator;
+vmaCreateAllocator(&allocatorInfo, &allocator);
+\endcode
+
+\section quick_start_resource_allocation Resource allocation
+
+When you want to create a buffer or image:
+
+-# Fill `VkBufferCreateInfo` / `VkImageCreateInfo` structure.
+-# Fill VmaAllocationCreateInfo structure.
+-# Call vmaCreateBuffer() / vmaCreateImage() to get `VkBuffer`/`VkImage` with memory
+   already allocated and bound to it.
+
+\code
+VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+bufferInfo.size = 65536;
+bufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+
+VmaAllocationCreateInfo allocInfo = {};
+allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+
+VkBuffer buffer;
+VmaAllocation allocation;
+vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr);
+\endcode
+
+Don't forget to destroy your objects when no longer needed:
+
+\code
+vmaDestroyBuffer(allocator, buffer, allocation);
+vmaDestroyAllocator(allocator);
+\endcode
+
+
+\page choosing_memory_type Choosing memory type
+
+Physical devices in Vulkan support various combinations of memory heaps and
+types. Help with choosing correct and optimal memory type for your specific
+resource is one of the key features of this library. You can use it by filling
+appropriate members of VmaAllocationCreateInfo structure, as described below.
+You can also combine multiple methods.
+
+-# If you just want to find memory type index that meets your requirements, you
+   can use function: vmaFindMemoryTypeIndex(), vmaFindMemoryTypeIndexForBufferInfo(),
+   vmaFindMemoryTypeIndexForImageInfo().
+-# If you want to allocate a region of device memory without association with any
+   specific image or buffer, you can use function vmaAllocateMemory(). Usage of
+   this function is not recommended and usually not needed.
+   vmaAllocateMemoryPages() function is also provided for creating multiple allocations at once,
+   which may be useful for sparse binding.
+-# If you already have a buffer or an image created, you want to allocate memory
+   for it and then you will bind it yourself, you can use function
+   vmaAllocateMemoryForBuffer(), vmaAllocateMemoryForImage().
+   For binding you should use functions: vmaBindBufferMemory(), vmaBindImageMemory()
+   or their extended versions: vmaBindBufferMemory2(), vmaBindImageMemory2().
+-# If you want to create a buffer or an image, allocate memory for it and bind
+   them together, all in one call, you can use function vmaCreateBuffer(),
+   vmaCreateImage(). This is the easiest and recommended way to use this library.
+
+When using 3. or 4., the library internally queries Vulkan for memory types
+supported for that buffer or image (function `vkGetBufferMemoryRequirements()`)
+and uses only one of these types.
+
+If no memory type can be found that meets all the requirements, these functions
+return `VK_ERROR_FEATURE_NOT_PRESENT`.
+
+You can leave VmaAllocationCreateInfo structure completely filled with zeros.
+It means no requirements are specified for memory type.
+It is valid, although not very useful.
+
+\section choosing_memory_type_usage Usage
+
+The easiest way to specify memory requirements is to fill member
+VmaAllocationCreateInfo::usage using one of the values of enum #VmaMemoryUsage.
+It defines high level, common usage types.
+For more details, see description of this enum.
+
+For example, if you want to create a uniform buffer that will be filled using
+transfer only once or infrequently and used for rendering every frame, you can
+do it using following code:
+
+\code
+VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+bufferInfo.size = 65536;
+bufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+
+VmaAllocationCreateInfo allocInfo = {};
+allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+
+VkBuffer buffer;
+VmaAllocation allocation;
+vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr);
+\endcode
+
+\section choosing_memory_type_required_preferred_flags Required and preferred flags
+
+You can specify more detailed requirements by filling members
+VmaAllocationCreateInfo::requiredFlags and VmaAllocationCreateInfo::preferredFlags
+with a combination of bits from enum `VkMemoryPropertyFlags`. For example,
+if you want to create a buffer that will be persistently mapped on host (so it
+must be `HOST_VISIBLE`) and preferably will also be `HOST_COHERENT` and `HOST_CACHED`,
+use following code:
+
+\code
+VmaAllocationCreateInfo allocInfo = {};
+allocInfo.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
+allocInfo.preferredFlags = VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
+allocInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
+
+VkBuffer buffer;
+VmaAllocation allocation;
+vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr);
+\endcode
+
+A memory type is chosen that has all the required flags and as many preferred
+flags set as possible.
+
+If you use VmaAllocationCreateInfo::usage, it is just internally converted to
+a set of required and preferred flags.
+
+\section choosing_memory_type_explicit_memory_types Explicit memory types
+
+If you inspected memory types available on the physical device and you have
+a preference for memory types that you want to use, you can fill member
+VmaAllocationCreateInfo::memoryTypeBits. It is a bit mask, where each bit set
+means that a memory type with that index is allowed to be used for the
+allocation. Special value 0, just like `UINT32_MAX`, means there are no
+restrictions to memory type index.
+
+Please note that this member is NOT just a memory type index.
+Still you can use it to choose just one, specific memory type.
+For example, if you already determined that your buffer should be created in
+memory type 2, use following code:
+
+\code
+uint32_t memoryTypeIndex = 2;
+
+VmaAllocationCreateInfo allocInfo = {};
+allocInfo.memoryTypeBits = 1u << memoryTypeIndex;
+
+VkBuffer buffer;
+VmaAllocation allocation;
+vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr);
+\endcode
+
+\section choosing_memory_type_custom_memory_pools Custom memory pools
+
+If you allocate from custom memory pool, all the ways of specifying memory
+requirements described above are not applicable and the aforementioned members
+of VmaAllocationCreateInfo structure are ignored. Memory type is selected
+explicitly when creating the pool and then used to make all the allocations from
+that pool. For further details, see \ref custom_memory_pools.
+
+\section choosing_memory_type_dedicated_allocations Dedicated allocations
+
+Memory for allocations is reserved out of larger block of `VkDeviceMemory`
+allocated from Vulkan internally. That's the main feature of this whole library.
+You can still request a separate memory block to be created for an allocation,
+just like you would do in a trivial solution without using any allocator.
+In that case, a buffer or image is always bound to that memory at offset 0.
+This is called a "dedicated allocation".
+You can explicitly request it by using flag #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT.
+The library can also internally decide to use dedicated allocation in some cases, e.g.:
+
+- When the size of the allocation is large.
+- When [VK_KHR_dedicated_allocation](@ref vk_khr_dedicated_allocation) extension is enabled
+  and it reports that dedicated allocation is required or recommended for the resource.
+- When allocation of next big memory block fails due to not enough device memory,
+  but allocation with the exact requested size succeeds.
+
+
+\page memory_mapping Memory mapping
+
+To "map memory" in Vulkan means to obtain a CPU pointer to `VkDeviceMemory`,
+to be able to read from it or write to it in CPU code.
+Mapping is possible only of memory allocated from a memory type that has
+`VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT` flag.
+Functions `vkMapMemory()`, `vkUnmapMemory()` are designed for this purpose.
+You can use them directly with memory allocated by this library,
+but it is not recommended because of following issue:
+Mapping the same `VkDeviceMemory` block multiple times is illegal - only one mapping at a time is allowed.
+This includes mapping disjoint regions. Mapping is not reference-counted internally by Vulkan.
+Because of this, Vulkan Memory Allocator provides following facilities:
+
+\section memory_mapping_mapping_functions Mapping functions
+
+The library provides following functions for mapping of a specific #VmaAllocation: vmaMapMemory(), vmaUnmapMemory().
+They are safer and more convenient to use than standard Vulkan functions.
+You can map an allocation multiple times simultaneously - mapping is reference-counted internally.
+You can also map different allocations simultaneously regardless of whether they use the same `VkDeviceMemory` block.
+The way it's implemented is that the library always maps entire memory block, not just region of the allocation.
+For further details, see description of vmaMapMemory() function.
+Example:
+
+\code
+// Having these objects initialized:
+
+struct ConstantBuffer
+{
+    ...
+};
+ConstantBuffer constantBufferData;
+
+VmaAllocator allocator;
+VkBuffer constantBuffer;
+VmaAllocation constantBufferAllocation;
+
+// You can map and fill your buffer using following code:
+
+void* mappedData;
+vmaMapMemory(allocator, constantBufferAllocation, &mappedData);
+memcpy(mappedData, &constantBufferData, sizeof(constantBufferData));
+vmaUnmapMemory(allocator, constantBufferAllocation);
+\endcode
+
+When mapping, you may see a warning from Vulkan validation layer similar to this one:
+
+<i>Mapping an image with layout VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL can result in undefined behavior if this memory is used by the device. Only GENERAL or PREINITIALIZED should be used.</i>
+
+It happens because the library maps entire `VkDeviceMemory` block, where different
+types of images and buffers may end up together, especially on GPUs with unified memory like Intel.
+You can safely ignore it if you are sure you access only memory of the intended
+object that you wanted to map.
+
+
+\section memory_mapping_persistently_mapped_memory Persistently mapped memory
+
+Kepping your memory persistently mapped is generally OK in Vulkan.
+You don't need to unmap it before using its data on the GPU.
+The library provides a special feature designed for that:
+Allocations made with #VMA_ALLOCATION_CREATE_MAPPED_BIT flag set in
+VmaAllocationCreateInfo::flags stay mapped all the time,
+so you can just access CPU pointer to it any time
+without a need to call any "map" or "unmap" function.
+Example:
+
+\code
+VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+bufCreateInfo.size = sizeof(ConstantBuffer);
+bufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+
+VmaAllocationCreateInfo allocCreateInfo = {};
+allocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
+allocCreateInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
+
+VkBuffer buf;
+VmaAllocation alloc;
+VmaAllocationInfo allocInfo;
+vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);
+
+// Buffer is already mapped. You can access its memory.
+memcpy(allocInfo.pMappedData, &constantBufferData, sizeof(constantBufferData));
+\endcode
+
+There are some exceptions though, when you should consider mapping memory only for a short period of time:
+
+- When operating system is Windows 7 or 8.x (Windows 10 is not affected because it uses WDDM2),
+  device is discrete AMD GPU,
+  and memory type is the special 256 MiB pool of `DEVICE_LOCAL + HOST_VISIBLE` memory
+  (selected when you use #VMA_MEMORY_USAGE_CPU_TO_GPU),
+  then whenever a memory block allocated from this memory type stays mapped
+  for the time of any call to `vkQueueSubmit()` or `vkQueuePresentKHR()`, this
+  block is migrated by WDDM to system RAM, which degrades performance. It doesn't
+  matter if that particular memory block is actually used by the command buffer
+  being submitted.
+- On Mac/MoltenVK there is a known bug - [Issue #175](https://github.com/KhronosGroup/MoltenVK/issues/175)
+  which requires unmapping before GPU can see updated texture.
+- Keeping many large memory blocks mapped may impact performance or stability of some debugging tools.
+
+\section memory_mapping_cache_control Cache flush and invalidate
+  
+Memory in Vulkan doesn't need to be unmapped before using it on GPU,
+but unless a memory types has `VK_MEMORY_PROPERTY_HOST_COHERENT_BIT` flag set,
+you need to manually **invalidate** cache before reading of mapped pointer
+and **flush** cache after writing to mapped pointer.
+Map/unmap operations don't do that automatically.
+Vulkan provides following functions for this purpose `vkFlushMappedMemoryRanges()`,
+`vkInvalidateMappedMemoryRanges()`, but this library provides more convenient
+functions that refer to given allocation object: vmaFlushAllocation(),
+vmaInvalidateAllocation().
+
+Regions of memory specified for flush/invalidate must be aligned to
+`VkPhysicalDeviceLimits::nonCoherentAtomSize`. This is automatically ensured by the library.
+In any memory type that is `HOST_VISIBLE` but not `HOST_COHERENT`, all allocations
+within blocks are aligned to this value, so their offsets are always multiply of
+`nonCoherentAtomSize` and two different allocations never share same "line" of this size.
+
+Please note that memory allocated with #VMA_MEMORY_USAGE_CPU_ONLY is guaranteed to be `HOST_COHERENT`.
+
+Also, Windows drivers from all 3 **PC** GPU vendors (AMD, Intel, NVIDIA)
+currently provide `HOST_COHERENT` flag on all memory types that are
+`HOST_VISIBLE`, so on this platform you may not need to bother.
+
+\section memory_mapping_finding_if_memory_mappable Finding out if memory is mappable
+
+It may happen that your allocation ends up in memory that is `HOST_VISIBLE` (available for mapping)
+despite it wasn't explicitly requested.
+For example, application may work on integrated graphics with unified memory (like Intel) or
+allocation from video memory might have failed, so the library chose system memory as fallback.
+
+You can detect this case and map such allocation to access its memory on CPU directly,
+instead of launching a transfer operation.
+In order to do that: inspect `allocInfo.memoryType`, call vmaGetMemoryTypeProperties(),
+and look for `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT` flag in properties of that memory type.
+
+\code
+VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+bufCreateInfo.size = sizeof(ConstantBuffer);
+bufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+
+VmaAllocationCreateInfo allocCreateInfo = {};
+allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+allocCreateInfo.preferredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
+
+VkBuffer buf;
+VmaAllocation alloc;
+VmaAllocationInfo allocInfo;
+vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);
+
+VkMemoryPropertyFlags memFlags;
+vmaGetMemoryTypeProperties(allocator, allocInfo.memoryType, &memFlags);
+if((memFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0)
+{
+    // Allocation ended up in mappable memory. You can map it and access it directly.
+    void* mappedData;
+    vmaMapMemory(allocator, alloc, &mappedData);
+    memcpy(mappedData, &constantBufferData, sizeof(constantBufferData));
+    vmaUnmapMemory(allocator, alloc);
+}
+else
+{
+    // Allocation ended up in non-mappable memory.
+    // You need to create CPU-side buffer in VMA_MEMORY_USAGE_CPU_ONLY and make a transfer.
+}
+\endcode
+
+You can even use #VMA_ALLOCATION_CREATE_MAPPED_BIT flag while creating allocations
+that are not necessarily `HOST_VISIBLE` (e.g. using #VMA_MEMORY_USAGE_GPU_ONLY).
+If the allocation ends up in memory type that is `HOST_VISIBLE`, it will be persistently mapped and you can use it directly.
+If not, the flag is just ignored.
+Example:
+
+\code
+VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+bufCreateInfo.size = sizeof(ConstantBuffer);
+bufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+
+VmaAllocationCreateInfo allocCreateInfo = {};
+allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+allocCreateInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
+
+VkBuffer buf;
+VmaAllocation alloc;
+VmaAllocationInfo allocInfo;
+vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);
+
+if(allocInfo.pUserData != nullptr)
+{
+    // Allocation ended up in mappable memory.
+    // It's persistently mapped. You can access it directly.
+    memcpy(allocInfo.pMappedData, &constantBufferData, sizeof(constantBufferData));
+}
+else
+{
+    // Allocation ended up in non-mappable memory.
+    // You need to create CPU-side buffer in VMA_MEMORY_USAGE_CPU_ONLY and make a transfer.
+}
+\endcode
+
+
+\page staying_within_budget Staying within budget
+
+When developing a graphics-intensive game or program, it is important to avoid allocating
+more GPU memory than it's physically available. When the memory is over-committed,
+various bad things can happen, depending on the specific GPU, graphics driver, and
+operating system:
+
+- It may just work without any problems.
+- The application may slow down because some memory blocks are moved to system RAM
+  and the GPU has to access them through PCI Express bus.
+- A new allocation may take very long time to complete, even few seconds, and possibly
+  freeze entire system.
+- The new allocation may fail with `VK_ERROR_OUT_OF_DEVICE_MEMORY`.
+- It may even result in GPU crash (TDR), observed as `VK_ERROR_DEVICE_LOST`
+  returned somewhere later.
+
+\section staying_within_budget_querying_for_budget Querying for budget
+
+To query for current memory usage and available budget, use function vmaGetBudget().
+Returned structure #VmaBudget contains quantities expressed in bytes, per Vulkan memory heap.
+
+Please note that this function returns different information and works faster than
+vmaCalculateStats(). vmaGetBudget() can be called every frame or even before every
+allocation, while vmaCalculateStats() is intended to be used rarely,
+only to obtain statistical information, e.g. for debugging purposes.
+
+It is recommended to use <b>VK_EXT_memory_budget</b> device extension to obtain information
+about the budget from Vulkan device. VMA is able to use this extension automatically.
+When not enabled, the allocator behaves same way, but then it estimates current usage
+and available budget based on its internal information and Vulkan memory heap sizes,
+which may be less precise. In order to use this extension:
+
+1. Make sure extensions VK_EXT_memory_budget and VK_KHR_get_physical_device_properties2
+   required by it are available and enable them. Please note that the first is a device
+   extension and the second is instance extension!
+2. Use flag #VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT when creating #VmaAllocator object.
+3. Make sure to call vmaSetCurrentFrameIndex() every frame. Budget is queried from
+   Vulkan inside of it to avoid overhead of querying it with every allocation.
+
+\section staying_within_budget_controlling_memory_usage Controlling memory usage
+
+There are many ways in which you can try to stay within the budget.
+
+First, when making new allocation requires allocating a new memory block, the library
+tries not to exceed the budget automatically. If a block with default recommended size
+(e.g. 256 MB) would go over budget, a smaller block is allocated, possibly even
+dedicated memory for just this resource.
+
+If the size of the requested resource plus current memory usage is more than the
+budget, by default the library still tries to create it, leaving it to the Vulkan
+implementation whether the allocation succeeds or fails. You can change this behavior
+by using #VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT flag. With it, the allocation is
+not made if it would exceed the budget or if the budget is already exceeded.
+Some other allocations become lost instead to make room for it, if the mechanism of
+[lost allocations](@ref lost_allocations) is used.
+If that is not possible, the allocation fails with `VK_ERROR_OUT_OF_DEVICE_MEMORY`.
+Example usage pattern may be to pass the #VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT flag
+when creating resources that are not essential for the application (e.g. the texture
+of a specific object) and not to pass it when creating critically important resources
+(e.g. render targets).
+
+Finally, you can also use #VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT flag to make sure
+a new allocation is created only when it fits inside one of the existing memory blocks.
+If it would require to allocate a new block, if fails instead with `VK_ERROR_OUT_OF_DEVICE_MEMORY`.
+This also ensures that the function call is very fast because it never goes to Vulkan
+to obtain a new block.
+
+Please note that creating \ref custom_memory_pools with VmaPoolCreateInfo::minBlockCount
+set to more than 0 will try to allocate memory blocks without checking whether they
+fit within budget.
+
+
+\page custom_memory_pools Custom memory pools
+
+A memory pool contains a number of `VkDeviceMemory` blocks.
+The library automatically creates and manages default pool for each memory type available on the device.
+Default memory pool automatically grows in size.
+Size of allocated blocks is also variable and managed automatically.
+
+You can create custom pool and allocate memory out of it.
+It can be useful if you want to:
+
+- Keep certain kind of allocations separate from others.
+- Enforce particular, fixed size of Vulkan memory blocks.
+- Limit maximum amount of Vulkan memory allocated for that pool.
+- Reserve minimum or fixed amount of Vulkan memory always preallocated for that pool.
+
+To use custom memory pools:
+
+-# Fill VmaPoolCreateInfo structure.
+-# Call vmaCreatePool() to obtain #VmaPool handle.
+-# When making an allocation, set VmaAllocationCreateInfo::pool to this handle.
+   You don't need to specify any other parameters of this structure, like `usage`.
+
+Example:
+
+\code
+// Create a pool that can have at most 2 blocks, 128 MiB each.
+VmaPoolCreateInfo poolCreateInfo = {};
+poolCreateInfo.memoryTypeIndex = ...
+poolCreateInfo.blockSize = 128ull * 1024 * 1024;
+poolCreateInfo.maxBlockCount = 2;
+
+VmaPool pool;
+vmaCreatePool(allocator, &poolCreateInfo, &pool);
+
+// Allocate a buffer out of it.
+VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+bufCreateInfo.size = 1024;
+bufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+
+VmaAllocationCreateInfo allocCreateInfo = {};
+allocCreateInfo.pool = pool;
+
+VkBuffer buf;
+VmaAllocation alloc;
+VmaAllocationInfo allocInfo;
+vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);
+\endcode
+
+You have to free all allocations made from this pool before destroying it.
+
+\code
+vmaDestroyBuffer(allocator, buf, alloc);
+vmaDestroyPool(allocator, pool);
+\endcode
+
+\section custom_memory_pools_MemTypeIndex Choosing memory type index
+
+When creating a pool, you must explicitly specify memory type index.
+To find the one suitable for your buffers or images, you can use helper functions
+vmaFindMemoryTypeIndexForBufferInfo(), vmaFindMemoryTypeIndexForImageInfo().
+You need to provide structures with example parameters of buffers or images
+that you are going to create in that pool.
+
+\code
+VkBufferCreateInfo exampleBufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+exampleBufCreateInfo.size = 1024; // Whatever.
+exampleBufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; // Change if needed.
+
+VmaAllocationCreateInfo allocCreateInfo = {};
+allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY; // Change if needed.
+
+uint32_t memTypeIndex;
+vmaFindMemoryTypeIndexForBufferInfo(allocator, &exampleBufCreateInfo, &allocCreateInfo, &memTypeIndex);
+
+VmaPoolCreateInfo poolCreateInfo = {};
+poolCreateInfo.memoryTypeIndex = memTypeIndex;
+// ...
+\endcode
+
+When creating buffers/images allocated in that pool, provide following parameters:
+
+- `VkBufferCreateInfo`: Prefer to pass same parameters as above.
+  Otherwise you risk creating resources in a memory type that is not suitable for them, which may result in undefined behavior.
+  Using different `VK_BUFFER_USAGE_` flags may work, but you shouldn't create images in a pool intended for buffers
+  or the other way around.
+- VmaAllocationCreateInfo: You don't need to pass same parameters. Fill only `pool` member.
+  Other members are ignored anyway.
+
+\section linear_algorithm Linear allocation algorithm
+
+Each Vulkan memory block managed by this library has accompanying metadata that
+keeps track of used and unused regions. By default, the metadata structure and
+algorithm tries to find best place for new allocations among free regions to
+optimize memory usage. This way you can allocate and free objects in any order.
+
+![Default allocation algorithm](../gfx/Linear_allocator_1_algo_default.png)
+
+Sometimes there is a need to use simpler, linear allocation algorithm. You can
+create custom pool that uses such algorithm by adding flag
+#VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT to VmaPoolCreateInfo::flags while creating
+#VmaPool object. Then an alternative metadata management is used. It always
+creates new allocations after last one and doesn't reuse free regions after
+allocations freed in the middle. It results in better allocation performance and
+less memory consumed by metadata.
+
+![Linear allocation algorithm](../gfx/Linear_allocator_2_algo_linear.png)
+
+With this one flag, you can create a custom pool that can be used in many ways:
+free-at-once, stack, double stack, and ring buffer. See below for details.
+
+\subsection linear_algorithm_free_at_once Free-at-once
+
+In a pool that uses linear algorithm, you still need to free all the allocations
+individually, e.g. by using vmaFreeMemory() or vmaDestroyBuffer(). You can free
+them in any order. New allocations are always made after last one - free space
+in the middle is not reused. However, when you release all the allocation and
+the pool becomes empty, allocation starts from the beginning again. This way you
+can use linear algorithm to speed up creation of allocations that you are going
+to release all at once.
+
+![Free-at-once](../gfx/Linear_allocator_3_free_at_once.png)
+
+This mode is also available for pools created with VmaPoolCreateInfo::maxBlockCount
+value that allows multiple memory blocks.
+
+\subsection linear_algorithm_stack Stack
+
+When you free an allocation that was created last, its space can be reused.
+Thanks to this, if you always release allocations in the order opposite to their
+creation (LIFO - Last In First Out), you can achieve behavior of a stack.
+
+![Stack](../gfx/Linear_allocator_4_stack.png)
+
+This mode is also available for pools created with VmaPoolCreateInfo::maxBlockCount
+value that allows multiple memory blocks.
+
+\subsection linear_algorithm_double_stack Double stack
+
+The space reserved by a custom pool with linear algorithm may be used by two
+stacks:
+
+- First, default one, growing up from offset 0.
+- Second, "upper" one, growing down from the end towards lower offsets.
+
+To make allocation from upper stack, add flag #VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT
+to VmaAllocationCreateInfo::flags.
+
+![Double stack](../gfx/Linear_allocator_7_double_stack.png)
+
+Double stack is available only in pools with one memory block -
+VmaPoolCreateInfo::maxBlockCount must be 1. Otherwise behavior is undefined.
+
+When the two stacks' ends meet so there is not enough space between them for a
+new allocation, such allocation fails with usual
+`VK_ERROR_OUT_OF_DEVICE_MEMORY` error.
+
+\subsection linear_algorithm_ring_buffer Ring buffer
+
+When you free some allocations from the beginning and there is not enough free space
+for a new one at the end of a pool, allocator's "cursor" wraps around to the
+beginning and starts allocation there. Thanks to this, if you always release
+allocations in the same order as you created them (FIFO - First In First Out),
+you can achieve behavior of a ring buffer / queue.
+
+![Ring buffer](../gfx/Linear_allocator_5_ring_buffer.png)
+
+Pools with linear algorithm support [lost allocations](@ref lost_allocations) when used as ring buffer.
+If there is not enough free space for a new allocation, but existing allocations
+from the front of the queue can become lost, they become lost and the allocation
+succeeds.
+
+![Ring buffer with lost allocations](../gfx/Linear_allocator_6_ring_buffer_lost.png)
+
+Ring buffer is available only in pools with one memory block -
+VmaPoolCreateInfo::maxBlockCount must be 1. Otherwise behavior is undefined.
+
+\section buddy_algorithm Buddy allocation algorithm
+
+There is another allocation algorithm that can be used with custom pools, called
+"buddy". Its internal data structure is based on a tree of blocks, each having
+size that is a power of two and a half of its parent's size. When you want to
+allocate memory of certain size, a free node in the tree is located. If it's too
+large, it is recursively split into two halves (called "buddies"). However, if
+requested allocation size is not a power of two, the size of a tree node is
+aligned up to the nearest power of two and the remaining space is wasted. When
+two buddy nodes become free, they are merged back into one larger node.
+
+![Buddy allocator](../gfx/Buddy_allocator.png)
+
+The advantage of buddy allocation algorithm over default algorithm is faster
+allocation and deallocation, as well as smaller external fragmentation. The
+disadvantage is more wasted space (internal fragmentation).
+
+For more information, please read ["Buddy memory allocation" on Wikipedia](https://en.wikipedia.org/wiki/Buddy_memory_allocation)
+or other sources that describe this concept in general.
+
+To use buddy allocation algorithm with a custom pool, add flag
+#VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT to VmaPoolCreateInfo::flags while creating
+#VmaPool object.
+
+Several limitations apply to pools that use buddy algorithm:
+
+- It is recommended to use VmaPoolCreateInfo::blockSize that is a power of two.
+  Otherwise, only largest power of two smaller than the size is used for
+  allocations. The remaining space always stays unused.
+- [Margins](@ref debugging_memory_usage_margins) and
+  [corruption detection](@ref debugging_memory_usage_corruption_detection)
+  don't work in such pools.
+- [Lost allocations](@ref lost_allocations) don't work in such pools. You can
+  use them, but they never become lost. Support may be added in the future.
+- [Defragmentation](@ref defragmentation) doesn't work with allocations made from
+  such pool.
+
+\page defragmentation Defragmentation
+
+Interleaved allocations and deallocations of many objects of varying size can
+cause fragmentation over time, which can lead to a situation where the library is unable
+to find a continuous range of free memory for a new allocation despite there is
+enough free space, just scattered across many small free ranges between existing
+allocations.
+
+To mitigate this problem, you can use defragmentation feature:
+structure #VmaDefragmentationInfo2, function vmaDefragmentationBegin(), vmaDefragmentationEnd().
+Given set of allocations, 
+this function can move them to compact used memory, ensure more continuous free
+space and possibly also free some `VkDeviceMemory` blocks.
+
+What the defragmentation does is:
+
+- Updates #VmaAllocation objects to point to new `VkDeviceMemory` and offset.
+  After allocation has been moved, its VmaAllocationInfo::deviceMemory and/or
+  VmaAllocationInfo::offset changes. You must query them again using
+  vmaGetAllocationInfo() if you need them.
+- Moves actual data in memory.
+
+What it doesn't do, so you need to do it yourself:
+
+- Recreate buffers and images that were bound to allocations that were defragmented and
+  bind them with their new places in memory.
+  You must use `vkDestroyBuffer()`, `vkDestroyImage()`,
+  `vkCreateBuffer()`, `vkCreateImage()`, vmaBindBufferMemory(), vmaBindImageMemory()
+  for that purpose and NOT vmaDestroyBuffer(),
+  vmaDestroyImage(), vmaCreateBuffer(), vmaCreateImage(), because you don't need to
+  destroy or create allocation objects!
+- Recreate views and update descriptors that point to these buffers and images.
+
+\section defragmentation_cpu Defragmenting CPU memory
+
+Following example demonstrates how you can run defragmentation on CPU.
+Only allocations created in memory types that are `HOST_VISIBLE` can be defragmented.
+Others are ignored.
+
+The way it works is:
+
+- It temporarily maps entire memory blocks when necessary.
+- It moves data using `memmove()` function.
+
+\code
+// Given following variables already initialized:
+VkDevice device;
+VmaAllocator allocator;
+std::vector<VkBuffer> buffers;
+std::vector<VmaAllocation> allocations;
+
+
+const uint32_t allocCount = (uint32_t)allocations.size();
+std::vector<VkBool32> allocationsChanged(allocCount);
+
+VmaDefragmentationInfo2 defragInfo = {};
+defragInfo.allocationCount = allocCount;
+defragInfo.pAllocations = allocations.data();
+defragInfo.pAllocationsChanged = allocationsChanged.data();
+defragInfo.maxCpuBytesToMove = VK_WHOLE_SIZE; // No limit.
+defragInfo.maxCpuAllocationsToMove = UINT32_MAX; // No limit.
+
+VmaDefragmentationContext defragCtx;
+vmaDefragmentationBegin(allocator, &defragInfo, nullptr, &defragCtx);
+vmaDefragmentationEnd(allocator, defragCtx);
+
+for(uint32_t i = 0; i < allocCount; ++i)
+{
+    if(allocationsChanged[i])
+    {
+        // Destroy buffer that is immutably bound to memory region which is no longer valid.
+        vkDestroyBuffer(device, buffers[i], nullptr);
+
+        // Create new buffer with same parameters.
+        VkBufferCreateInfo bufferInfo = ...;
+        vkCreateBuffer(device, &bufferInfo, nullptr, &buffers[i]);
+            
+        // You can make dummy call to vkGetBufferMemoryRequirements here to silence validation layer warning.
+            
+        // Bind new buffer to new memory region. Data contained in it is already moved.
+        VmaAllocationInfo allocInfo;
+        vmaGetAllocationInfo(allocator, allocations[i], &allocInfo);
+        vmaBindBufferMemory(allocator, allocations[i], buffers[i]);
+    }
+}
+\endcode
+
+Setting VmaDefragmentationInfo2::pAllocationsChanged is optional.
+This output array tells whether particular allocation in VmaDefragmentationInfo2::pAllocations at the same index
+has been modified during defragmentation.
+You can pass null, but you then need to query every allocation passed to defragmentation
+for new parameters using vmaGetAllocationInfo() if you might need to recreate and rebind a buffer or image associated with it.
+
+If you use [Custom memory pools](@ref choosing_memory_type_custom_memory_pools),
+you can fill VmaDefragmentationInfo2::poolCount and VmaDefragmentationInfo2::pPools
+instead of VmaDefragmentationInfo2::allocationCount and VmaDefragmentationInfo2::pAllocations
+to defragment all allocations in given pools.
+You cannot use VmaDefragmentationInfo2::pAllocationsChanged in that case.
+You can also combine both methods.
+
+\section defragmentation_gpu Defragmenting GPU memory
+
+It is also possible to defragment allocations created in memory types that are not `HOST_VISIBLE`.
+To do that, you need to pass a command buffer that meets requirements as described in
+VmaDefragmentationInfo2::commandBuffer. The way it works is:
+
+- It creates temporary buffers and binds them to entire memory blocks when necessary.
+- It issues `vkCmdCopyBuffer()` to passed command buffer.
+
+Example:
+
+\code
+// Given following variables already initialized:
+VkDevice device;
+VmaAllocator allocator;
+VkCommandBuffer commandBuffer;
+std::vector<VkBuffer> buffers;
+std::vector<VmaAllocation> allocations;
+
+
+const uint32_t allocCount = (uint32_t)allocations.size();
+std::vector<VkBool32> allocationsChanged(allocCount);
+
+VkCommandBufferBeginInfo cmdBufBeginInfo = ...;
+vkBeginCommandBuffer(commandBuffer, &cmdBufBeginInfo);
+
+VmaDefragmentationInfo2 defragInfo = {};
+defragInfo.allocationCount = allocCount;
+defragInfo.pAllocations = allocations.data();
+defragInfo.pAllocationsChanged = allocationsChanged.data();
+defragInfo.maxGpuBytesToMove = VK_WHOLE_SIZE; // Notice it's "GPU" this time.
+defragInfo.maxGpuAllocationsToMove = UINT32_MAX; // Notice it's "GPU" this time.
+defragInfo.commandBuffer = commandBuffer;
+
+VmaDefragmentationContext defragCtx;
+vmaDefragmentationBegin(allocator, &defragInfo, nullptr, &defragCtx);
+
+vkEndCommandBuffer(commandBuffer);
+
+// Submit commandBuffer.
+// Wait for a fence that ensures commandBuffer execution finished.
+
+vmaDefragmentationEnd(allocator, defragCtx);
+
+for(uint32_t i = 0; i < allocCount; ++i)
+{
+    if(allocationsChanged[i])
+    {
+        // Destroy buffer that is immutably bound to memory region which is no longer valid.
+        vkDestroyBuffer(device, buffers[i], nullptr);
+
+        // Create new buffer with same parameters.
+        VkBufferCreateInfo bufferInfo = ...;
+        vkCreateBuffer(device, &bufferInfo, nullptr, &buffers[i]);
+            
+        // You can make dummy call to vkGetBufferMemoryRequirements here to silence validation layer warning.
+            
+        // Bind new buffer to new memory region. Data contained in it is already moved.
+        VmaAllocationInfo allocInfo;
+        vmaGetAllocationInfo(allocator, allocations[i], &allocInfo);
+        vmaBindBufferMemory(allocator, allocations[i], buffers[i]);
+    }
+}
+\endcode
+
+You can combine these two methods by specifying non-zero `maxGpu*` as well as `maxCpu*` parameters.
+The library automatically chooses best method to defragment each memory pool.
+
+You may try not to block your entire program to wait until defragmentation finishes,
+but do it in the background, as long as you carefully fullfill requirements described
+in function vmaDefragmentationBegin().
+
+\section defragmentation_additional_notes Additional notes
+
+It is only legal to defragment allocations bound to:
+
+- buffers
+- images created with `VK_IMAGE_CREATE_ALIAS_BIT`, `VK_IMAGE_TILING_LINEAR`, and
+  being currently in `VK_IMAGE_LAYOUT_GENERAL` or `VK_IMAGE_LAYOUT_PREINITIALIZED`.
+
+Defragmentation of images created with `VK_IMAGE_TILING_OPTIMAL` or in any other
+layout may give undefined results.
+
+If you defragment allocations bound to images, new images to be bound to new
+memory region after defragmentation should be created with `VK_IMAGE_LAYOUT_PREINITIALIZED`
+and then transitioned to their original layout from before defragmentation if
+needed using an image memory barrier.
+
+While using defragmentation, you may experience validation layer warnings, which you just need to ignore.
+See [Validation layer warnings](@ref general_considerations_validation_layer_warnings).
+
+Please don't expect memory to be fully compacted after defragmentation.
+Algorithms inside are based on some heuristics that try to maximize number of Vulkan
+memory blocks to make totally empty to release them, as well as to maximimze continuous
+empty space inside remaining blocks, while minimizing the number and size of allocations that
+need to be moved. Some fragmentation may still remain - this is normal.
+
+\section defragmentation_custom_algorithm Writing custom defragmentation algorithm
+
+If you want to implement your own, custom defragmentation algorithm,
+there is infrastructure prepared for that,
+but it is not exposed through the library API - you need to hack its source code.
+Here are steps needed to do this:
+
+-# Main thing you need to do is to define your own class derived from base abstract
+   class `VmaDefragmentationAlgorithm` and implement your version of its pure virtual methods.
+   See definition and comments of this class for details.
+-# Your code needs to interact with device memory block metadata.
+   If you need more access to its data than it's provided by its public interface,
+   declare your new class as a friend class e.g. in class `VmaBlockMetadata_Generic`.
+-# If you want to create a flag that would enable your algorithm or pass some additional
+   flags to configure it, add them to `VmaDefragmentationFlagBits` and use them in
+   VmaDefragmentationInfo2::flags.
+-# Modify function `VmaBlockVectorDefragmentationContext::Begin` to create object
+   of your new class whenever needed.
+
+
+\page lost_allocations Lost allocations
+
+If your game oversubscribes video memory, if may work OK in previous-generation
+graphics APIs (DirectX 9, 10, 11, OpenGL) because resources are automatically
+paged to system RAM. In Vulkan you can't do it because when you run out of
+memory, an allocation just fails. If you have more data (e.g. textures) that can
+fit into VRAM and you don't need it all at once, you may want to upload them to
+GPU on demand and "push out" ones that are not used for a long time to make room
+for the new ones, effectively using VRAM (or a cartain memory pool) as a form of
+cache. Vulkan Memory Allocator can help you with that by supporting a concept of
+"lost allocations".
+
+To create an allocation that can become lost, include #VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT
+flag in VmaAllocationCreateInfo::flags. Before using a buffer or image bound to
+such allocation in every new frame, you need to query it if it's not lost.
+To check it, call vmaTouchAllocation().
+If the allocation is lost, you should not use it or buffer/image bound to it.
+You mustn't forget to destroy this allocation and this buffer/image.
+vmaGetAllocationInfo() can also be used for checking status of the allocation.
+Allocation is lost when returned VmaAllocationInfo::deviceMemory == `VK_NULL_HANDLE`.
+
+To create an allocation that can make some other allocations lost to make room
+for it, use #VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT flag. You will
+usually use both flags #VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT and
+#VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT at the same time.
+
+Warning! Current implementation uses quite naive, brute force algorithm,
+which can make allocation calls that use #VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT
+flag quite slow. A new, more optimal algorithm and data structure to speed this
+up is planned for the future.
+
+<b>Q: When interleaving creation of new allocations with usage of existing ones,
+how do you make sure that an allocation won't become lost while it's used in the
+current frame?</b>
+
+It is ensured because vmaTouchAllocation() / vmaGetAllocationInfo() not only returns allocation
+status/parameters and checks whether it's not lost, but when it's not, it also
+atomically marks it as used in the current frame, which makes it impossible to
+become lost in that frame. It uses lockless algorithm, so it works fast and
+doesn't involve locking any internal mutex.
+
+<b>Q: What if my allocation may still be in use by the GPU when it's rendering a
+previous frame while I already submit new frame on the CPU?</b>
+
+You can make sure that allocations "touched" by vmaTouchAllocation() / vmaGetAllocationInfo() will not
+become lost for a number of additional frames back from the current one by
+specifying this number as VmaAllocatorCreateInfo::frameInUseCount (for default
+memory pool) and VmaPoolCreateInfo::frameInUseCount (for custom pool).
+
+<b>Q: How do you inform the library when new frame starts?</b>
+
+You need to call function vmaSetCurrentFrameIndex().
+
+Example code:
+
+\code
+struct MyBuffer
+{
+    VkBuffer m_Buf = nullptr;
+    VmaAllocation m_Alloc = nullptr;
+
+    // Called when the buffer is really needed in the current frame.
+    void EnsureBuffer();
+};
+
+void MyBuffer::EnsureBuffer()
+{
+    // Buffer has been created.
+    if(m_Buf != VK_NULL_HANDLE)
+    {
+        // Check if its allocation is not lost + mark it as used in current frame.
+        if(vmaTouchAllocation(allocator, m_Alloc))
+        {
+            // It's all OK - safe to use m_Buf.
+            return;
+        }
+    }
+
+    // Buffer not yet exists or lost - destroy and recreate it.
+
+    vmaDestroyBuffer(allocator, m_Buf, m_Alloc);
+
+    VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+    bufCreateInfo.size = 1024;
+    bufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+
+    VmaAllocationCreateInfo allocCreateInfo = {};
+    allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+    allocCreateInfo.flags = VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT |
+        VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT;
+
+    vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &m_Buf, &m_Alloc, nullptr);
+}
+\endcode
+
+When using lost allocations, you may see some Vulkan validation layer warnings
+about overlapping regions of memory bound to different kinds of buffers and
+images. This is still valid as long as you implement proper handling of lost
+allocations (like in the example above) and don't use them.
+
+You can create an allocation that is already in lost state from the beginning using function
+vmaCreateLostAllocation(). It may be useful if you need a "dummy" allocation that is not null.
+
+You can call function vmaMakePoolAllocationsLost() to set all eligible allocations
+in a specified custom pool to lost state.
+Allocations that have been "touched" in current frame or VmaPoolCreateInfo::frameInUseCount frames back
+cannot become lost.
+
+<b>Q: Can I touch allocation that cannot become lost?</b>
+
+Yes, although it has no visible effect.
+Calls to vmaGetAllocationInfo() and vmaTouchAllocation() update last use frame index
+also for allocations that cannot become lost, but the only way to observe it is to dump
+internal allocator state using vmaBuildStatsString().
+You can use this feature for debugging purposes to explicitly mark allocations that you use
+in current frame and then analyze JSON dump to see for how long each allocation stays unused.
+
+
+\page statistics Statistics
+
+This library contains functions that return information about its internal state,
+especially the amount of memory allocated from Vulkan.
+Please keep in mind that these functions need to traverse all internal data structures
+to gather these information, so they may be quite time-consuming.
+Don't call them too often.
+
+\section statistics_numeric_statistics Numeric statistics
+
+You can query for overall statistics of the allocator using function vmaCalculateStats().
+Information are returned using structure #VmaStats.
+It contains #VmaStatInfo - number of allocated blocks, number of allocations
+(occupied ranges in these blocks), number of unused (free) ranges in these blocks,
+number of bytes used and unused (but still allocated from Vulkan) and other information.
+They are summed across memory heaps, memory types and total for whole allocator.
+
+You can query for statistics of a custom pool using function vmaGetPoolStats().
+Information are returned using structure #VmaPoolStats.
+
+You can query for information about specific allocation using function vmaGetAllocationInfo().
+It fill structure #VmaAllocationInfo.
+
+\section statistics_json_dump JSON dump
+
+You can dump internal state of the allocator to a string in JSON format using function vmaBuildStatsString().
+The result is guaranteed to be correct JSON.
+It uses ANSI encoding.
+Any strings provided by user (see [Allocation names](@ref allocation_names))
+are copied as-is and properly escaped for JSON, so if they use UTF-8, ISO-8859-2 or any other encoding,
+this JSON string can be treated as using this encoding.
+It must be freed using function vmaFreeStatsString().
+
+The format of this JSON string is not part of official documentation of the library,
+but it will not change in backward-incompatible way without increasing library major version number
+and appropriate mention in changelog.
+
+The JSON string contains all the data that can be obtained using vmaCalculateStats().
+It can also contain detailed map of allocated memory blocks and their regions -
+free and occupied by allocations.
+This allows e.g. to visualize the memory or assess fragmentation.
+
+
+\page allocation_annotation Allocation names and user data
+
+\section allocation_user_data Allocation user data
+
+You can annotate allocations with your own information, e.g. for debugging purposes.
+To do that, fill VmaAllocationCreateInfo::pUserData field when creating
+an allocation. It's an opaque `void*` pointer. You can use it e.g. as a pointer,
+some handle, index, key, ordinal number or any other value that would associate
+the allocation with your custom metadata.
+
+\code
+VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+// Fill bufferInfo...
+
+MyBufferMetadata* pMetadata = CreateBufferMetadata();
+
+VmaAllocationCreateInfo allocCreateInfo = {};
+allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+allocCreateInfo.pUserData = pMetadata;
+
+VkBuffer buffer;
+VmaAllocation allocation;
+vmaCreateBuffer(allocator, &bufferInfo, &allocCreateInfo, &buffer, &allocation, nullptr);
+\endcode
+
+The pointer may be later retrieved as VmaAllocationInfo::pUserData:
+
+\code
+VmaAllocationInfo allocInfo;
+vmaGetAllocationInfo(allocator, allocation, &allocInfo);
+MyBufferMetadata* pMetadata = (MyBufferMetadata*)allocInfo.pUserData;
+\endcode
+
+It can also be changed using function vmaSetAllocationUserData().
+
+Values of (non-zero) allocations' `pUserData` are printed in JSON report created by
+vmaBuildStatsString(), in hexadecimal form.
+
+\section allocation_names Allocation names
+
+There is alternative mode available where `pUserData` pointer is used to point to
+a null-terminated string, giving a name to the allocation. To use this mode,
+set #VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT flag in VmaAllocationCreateInfo::flags.
+Then `pUserData` passed as VmaAllocationCreateInfo::pUserData or argument to
+vmaSetAllocationUserData() must be either null or pointer to a null-terminated string.
+The library creates internal copy of the string, so the pointer you pass doesn't need
+to be valid for whole lifetime of the allocation. You can free it after the call.
+
+\code
+VkImageCreateInfo imageInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
+// Fill imageInfo...
+
+std::string imageName = "Texture: ";
+imageName += fileName;
+
+VmaAllocationCreateInfo allocCreateInfo = {};
+allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+allocCreateInfo.flags = VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT;
+allocCreateInfo.pUserData = imageName.c_str();
+
+VkImage image;
+VmaAllocation allocation;
+vmaCreateImage(allocator, &imageInfo, &allocCreateInfo, &image, &allocation, nullptr);
+\endcode
+
+The value of `pUserData` pointer of the allocation will be different than the one
+you passed when setting allocation's name - pointing to a buffer managed
+internally that holds copy of the string.
+
+\code
+VmaAllocationInfo allocInfo;
+vmaGetAllocationInfo(allocator, allocation, &allocInfo);
+const char* imageName = (const char*)allocInfo.pUserData;
+printf("Image name: %s\n", imageName);
+\endcode
+
+That string is also printed in JSON report created by vmaBuildStatsString().
+
+\note Passing string name to VMA allocation doesn't automatically set it to the Vulkan buffer or image created with it.
+You must do it manually using an extension like VK_EXT_debug_utils, which is independent of this library.
+
+
+\page debugging_memory_usage Debugging incorrect memory usage
+
+If you suspect a bug with memory usage, like usage of uninitialized memory or
+memory being overwritten out of bounds of an allocation,
+you can use debug features of this library to verify this.
+
+\section debugging_memory_usage_initialization Memory initialization
+
+If you experience a bug with incorrect and nondeterministic data in your program and you suspect uninitialized memory to be used,
+you can enable automatic memory initialization to verify this.
+To do it, define macro `VMA_DEBUG_INITIALIZE_ALLOCATIONS` to 1.
+
+\code
+#define VMA_DEBUG_INITIALIZE_ALLOCATIONS 1
+#include "vk_mem_alloc.h"
+\endcode
+
+It makes memory of all new allocations initialized to bit pattern `0xDCDCDCDC`.
+Before an allocation is destroyed, its memory is filled with bit pattern `0xEFEFEFEF`.
+Memory is automatically mapped and unmapped if necessary.
+
+If you find these values while debugging your program, good chances are that you incorrectly
+read Vulkan memory that is allocated but not initialized, or already freed, respectively.
+
+Memory initialization works only with memory types that are `HOST_VISIBLE`.
+It works also with dedicated allocations.
+It doesn't work with allocations created with #VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT flag,
+as they cannot be mapped.
+
+\section debugging_memory_usage_margins Margins
+
+By default, allocations are laid out in memory blocks next to each other if possible
+(considering required alignment, `bufferImageGranularity`, and `nonCoherentAtomSize`).
+
+![Allocations without margin](../gfx/Margins_1.png)
+
+Define macro `VMA_DEBUG_MARGIN` to some non-zero value (e.g. 16) to enforce specified
+number of bytes as a margin before and after every allocation.
+
+\code
+#define VMA_DEBUG_MARGIN 16
+#include "vk_mem_alloc.h"
+\endcode
+
+![Allocations with margin](../gfx/Margins_2.png)
+
+If your bug goes away after enabling margins, it means it may be caused by memory
+being overwritten outside of allocation boundaries. It is not 100% certain though.
+Change in application behavior may also be caused by different order and distribution
+of allocations across memory blocks after margins are applied.
+
+The margin is applied also before first and after last allocation in a block.
+It may occur only once between two adjacent allocations.
+
+Margins work with all types of memory.
+
+Margin is applied only to allocations made out of memory blocks and not to dedicated
+allocations, which have their own memory block of specific size.
+It is thus not applied to allocations made using #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT flag
+or those automatically decided to put into dedicated allocations, e.g. due to its
+large size or recommended by VK_KHR_dedicated_allocation extension.
+Margins are also not active in custom pools created with #VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT flag.
+
+Margins appear in [JSON dump](@ref statistics_json_dump) as part of free space.
+
+Note that enabling margins increases memory usage and fragmentation.
+
+\section debugging_memory_usage_corruption_detection Corruption detection
+
+You can additionally define macro `VMA_DEBUG_DETECT_CORRUPTION` to 1 to enable validation
+of contents of the margins.
+
+\code
+#define VMA_DEBUG_MARGIN 16
+#define VMA_DEBUG_DETECT_CORRUPTION 1
+#include "vk_mem_alloc.h"
+\endcode
+
+When this feature is enabled, number of bytes specified as `VMA_DEBUG_MARGIN`
+(it must be multiply of 4) before and after every allocation is filled with a magic number.
+This idea is also know as "canary".
+Memory is automatically mapped and unmapped if necessary.
+
+This number is validated automatically when the allocation is destroyed.
+If it's not equal to the expected value, `VMA_ASSERT()` is executed.
+It clearly means that either CPU or GPU overwritten the memory outside of boundaries of the allocation,
+which indicates a serious bug.
+
+You can also explicitly request checking margins of all allocations in all memory blocks
+that belong to specified memory types by using function vmaCheckCorruption(),
+or in memory blocks that belong to specified custom pool, by using function 
+vmaCheckPoolCorruption().
+
+Margin validation (corruption detection) works only for memory types that are
+`HOST_VISIBLE` and `HOST_COHERENT`.
+
+
+\page record_and_replay Record and replay
+
+\section record_and_replay_introduction Introduction
+
+While using the library, sequence of calls to its functions together with their
+parameters can be recorded to a file and later replayed using standalone player
+application. It can be useful to:
+
+- Test correctness - check if same sequence of calls will not cause crash or
+  failures on a target platform.
+- Gather statistics - see number of allocations, peak memory usage, number of
+  calls etc.
+- Benchmark performance - see how much time it takes to replay the whole
+  sequence.
+
+\section record_and_replay_usage Usage
+
+Recording functionality is disabled by default.
+To enable it, define following macro before every include of this library:
+
+\code
+#define VMA_RECORDING_ENABLED 1
+\endcode
+
+<b>To record sequence of calls to a file:</b> Fill in
+VmaAllocatorCreateInfo::pRecordSettings member while creating #VmaAllocator
+object. File is opened and written during whole lifetime of the allocator.
+
+<b>To replay file:</b> Use VmaReplay - standalone command-line program.
+Precompiled binary can be found in "bin" directory.
+Its source can be found in "src/VmaReplay" directory.
+Its project is generated by Premake.
+Command line syntax is printed when the program is launched without parameters.
+Basic usage:
+
+    VmaReplay.exe MyRecording.csv
+
+<b>Documentation of file format</b> can be found in file: "docs/Recording file format.md".
+It's a human-readable, text file in CSV format (Comma Separated Values).
+
+\section record_and_replay_additional_considerations Additional considerations
+
+- Replaying file that was recorded on a different GPU (with different parameters
+  like `bufferImageGranularity`, `nonCoherentAtomSize`, and especially different
+  set of memory heaps and types) may give different performance and memory usage
+  results, as well as issue some warnings and errors.
+- Current implementation of recording in VMA, as well as VmaReplay application, is
+  coded and tested only on Windows. Inclusion of recording code is driven by
+  `VMA_RECORDING_ENABLED` macro. Support for other platforms should be easy to
+  add. Contributions are welcomed.
+
+
+\page usage_patterns Recommended usage patterns
+
+See also slides from talk:
+[Sawicki, Adam. Advanced Graphics Techniques Tutorial: Memory management in Vulkan and DX12. Game Developers Conference, 2018](https://www.gdcvault.com/play/1025458/Advanced-Graphics-Techniques-Tutorial-New)
+
+
+\section usage_patterns_common_mistakes Common mistakes
+
+<b>Use of CPU_TO_GPU instead of CPU_ONLY memory</b>
+
+#VMA_MEMORY_USAGE_CPU_TO_GPU is recommended only for resources that will be
+mapped and written by the CPU, as well as read directly by the GPU - like some
+buffers or textures updated every frame (dynamic). If you create a staging copy
+of a resource to be written by CPU and then used as a source of transfer to
+another resource placed in the GPU memory, that staging resource should be
+created with #VMA_MEMORY_USAGE_CPU_ONLY. Please read the descriptions of these
+enums carefully for details.
+
+<b>Unnecessary use of custom pools</b>
+
+\ref custom_memory_pools may be useful for special purposes - when you want to
+keep certain type of resources separate e.g. to reserve minimum amount of memory
+for them, limit maximum amount of memory they can occupy, or make some of them
+push out the other through the mechanism of \ref lost_allocations. For most
+resources this is not needed and so it is not recommended to create #VmaPool
+objects and allocations out of them. Allocating from the default pool is sufficient.
+
+\section usage_patterns_simple Simple patterns
+
+\subsection usage_patterns_simple_render_targets Render targets
+
+<b>When:</b>
+Any resources that you frequently write and read on GPU,
+e.g. images used as color attachments (aka "render targets"), depth-stencil attachments,
+images/buffers used as storage image/buffer (aka "Unordered Access View (UAV)").
+
+<b>What to do:</b>
+Create them in video memory that is fastest to access from GPU using
+#VMA_MEMORY_USAGE_GPU_ONLY.
+
+Consider using [VK_KHR_dedicated_allocation](@ref vk_khr_dedicated_allocation) extension
+and/or manually creating them as dedicated allocations using #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT,
+especially if they are large or if you plan to destroy and recreate them e.g. when
+display resolution changes.
+Prefer to create such resources first and all other GPU resources (like textures and vertex buffers) later.
+
+\subsection usage_patterns_simple_immutable_resources Immutable resources
+
+<b>When:</b>
+Any resources that you fill on CPU only once (aka "immutable") or infrequently
+and then read frequently on GPU,
+e.g. textures, vertex and index buffers, constant buffers that don't change often.
+
+<b>What to do:</b>
+Create them in video memory that is fastest to access from GPU using
+#VMA_MEMORY_USAGE_GPU_ONLY.
+
+To initialize content of such resource, create a CPU-side (aka "staging") copy of it
+in system memory - #VMA_MEMORY_USAGE_CPU_ONLY, map it, fill it,
+and submit a transfer from it to the GPU resource.
+You can keep the staging copy if you need it for another upload transfer in the future.
+If you don't, you can destroy it or reuse this buffer for uploading different resource
+after the transfer finishes.
+
+Prefer to create just buffers in system memory rather than images, even for uploading textures.
+Use `vkCmdCopyBufferToImage()`.
+Dont use images with `VK_IMAGE_TILING_LINEAR`.
+
+\subsection usage_patterns_dynamic_resources Dynamic resources
+
+<b>When:</b>
+Any resources that change frequently (aka "dynamic"), e.g. every frame or every draw call,
+written on CPU, read on GPU.
+
+<b>What to do:</b>
+Create them using #VMA_MEMORY_USAGE_CPU_TO_GPU.
+You can map it and write to it directly on CPU, as well as read from it on GPU.
+
+This is a more complex situation. Different solutions are possible,
+and the best one depends on specific GPU type, but you can use this simple approach for the start.
+Prefer to write to such resource sequentially (e.g. using `memcpy`).
+Don't perform random access or any reads from it on CPU, as it may be very slow.
+
+\subsection usage_patterns_readback Readback
+
+<b>When:</b>
+Resources that contain data written by GPU that you want to read back on CPU,
+e.g. results of some computations.
+
+<b>What to do:</b>
+Create them using #VMA_MEMORY_USAGE_GPU_TO_CPU.
+You can write to them directly on GPU, as well as map and read them on CPU.
+
+\section usage_patterns_advanced Advanced patterns
+
+\subsection usage_patterns_integrated_graphics Detecting integrated graphics
+
+You can support integrated graphics (like Intel HD Graphics, AMD APU) better
+by detecting it in Vulkan.
+To do it, call `vkGetPhysicalDeviceProperties()`, inspect
+`VkPhysicalDeviceProperties::deviceType` and look for `VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU`.
+When you find it, you can assume that memory is unified and all memory types are comparably fast
+to access from GPU, regardless of `VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT`.
+
+You can then sum up sizes of all available memory heaps and treat them as useful for
+your GPU resources, instead of only `DEVICE_LOCAL` ones.
+You can also prefer to create your resources in memory types that are `HOST_VISIBLE` to map them
+directly instead of submitting explicit transfer (see below).
+
+\subsection usage_patterns_direct_vs_transfer Direct access versus transfer
+
+For resources that you frequently write on CPU and read on GPU, many solutions are possible:
+
+-# Create one copy in video memory using #VMA_MEMORY_USAGE_GPU_ONLY,
+   second copy in system memory using #VMA_MEMORY_USAGE_CPU_ONLY and submit explicit tranfer each time.
+-# Create just single copy using #VMA_MEMORY_USAGE_CPU_TO_GPU, map it and fill it on CPU,
+   read it directly on GPU.
+-# Create just single copy using #VMA_MEMORY_USAGE_CPU_ONLY, map it and fill it on CPU,
+   read it directly on GPU.
+
+Which solution is the most efficient depends on your resource and especially on the GPU.
+It is best to measure it and then make the decision.
+Some general recommendations:
+
+- On integrated graphics use (2) or (3) to avoid unnecesary time and memory overhead
+  related to using a second copy and making transfer.
+- For small resources (e.g. constant buffers) use (2).
+  Discrete AMD cards have special 256 MiB pool of video memory that is directly mappable.
+  Even if the resource ends up in system memory, its data may be cached on GPU after first
+  fetch over PCIe bus.
+- For larger resources (e.g. textures), decide between (1) and (2).
+  You may want to differentiate NVIDIA and AMD, e.g. by looking for memory type that is
+  both `DEVICE_LOCAL` and `HOST_VISIBLE`. When you find it, use (2), otherwise use (1).
+
+Similarly, for resources that you frequently write on GPU and read on CPU, multiple
+solutions are possible:
+
+-# Create one copy in video memory using #VMA_MEMORY_USAGE_GPU_ONLY,
+   second copy in system memory using #VMA_MEMORY_USAGE_GPU_TO_CPU and submit explicit tranfer each time.
+-# Create just single copy using #VMA_MEMORY_USAGE_GPU_TO_CPU, write to it directly on GPU,
+   map it and read it on CPU.
+
+You should take some measurements to decide which option is faster in case of your specific
+resource.
+
+If you don't want to specialize your code for specific types of GPUs, you can still make
+an simple optimization for cases when your resource ends up in mappable memory to use it
+directly in this case instead of creating CPU-side staging copy.
+For details see [Finding out if memory is mappable](@ref memory_mapping_finding_if_memory_mappable).
+
+
+\page configuration Configuration
+
+Please check "CONFIGURATION SECTION" in the code to find macros that you can define
+before each include of this file or change directly in this file to provide
+your own implementation of basic facilities like assert, `min()` and `max()` functions,
+mutex, atomic etc.
+The library uses its own implementation of containers by default, but you can switch to using
+STL containers instead.
+
+For example, define `VMA_ASSERT(expr)` before including the library to provide
+custom implementation of the assertion, compatible with your project.
+By default it is defined to standard C `assert(expr)` in `_DEBUG` configuration
+and empty otherwise.
+
+\section config_Vulkan_functions Pointers to Vulkan functions
+
+There are multiple ways to import pointers to Vulkan functions in the library.
+In the simplest case you don't need to do anything.
+If the compilation or linking of your program or the initialization of the #VmaAllocator
+doesn't work for you, you can try to reconfigure it.
+
+First, the allocator tries to fetch pointers to Vulkan functions linked statically,
+like this:
+
+\code
+m_VulkanFunctions.vkAllocateMemory = (PFN_vkAllocateMemory)vkAllocateMemory;
+\endcode
+
+If you want to disable this feature, set configuration macro: `#define VMA_STATIC_VULKAN_FUNCTIONS 0`.
+
+Second, you can provide the pointers yourself by setting member VmaAllocatorCreateInfo::pVulkanFunctions.
+You can fetch them e.g. using functions `vkGetInstanceProcAddr` and `vkGetDeviceProcAddr` or
+by using a helper library like [volk](https://github.com/zeux/volk).
+
+Third, VMA tries to fetch remaining pointers that are still null by calling
+`vkGetInstanceProcAddr` and `vkGetDeviceProcAddr` on its own.
+If you want to disable this feature, set configuration macro: `#define VMA_DYNAMIC_VULKAN_FUNCTIONS 0`.
+
+Finally, all the function pointers required by the library (considering selected
+Vulkan version and enabled extensions) are checked with `VMA_ASSERT` if they are not null.
+
+
+\section custom_memory_allocator Custom host memory allocator
+
+If you use custom allocator for CPU memory rather than default operator `new`
+and `delete` from C++, you can make this library using your allocator as well
+by filling optional member VmaAllocatorCreateInfo::pAllocationCallbacks. These
+functions will be passed to Vulkan, as well as used by the library itself to
+make any CPU-side allocations.
+
+\section allocation_callbacks Device memory allocation callbacks
+
+The library makes calls to `vkAllocateMemory()` and `vkFreeMemory()` internally.
+You can setup callbacks to be informed about these calls, e.g. for the purpose
+of gathering some statistics. To do it, fill optional member
+VmaAllocatorCreateInfo::pDeviceMemoryCallbacks.
+
+\section heap_memory_limit Device heap memory limit
+
+When device memory of certain heap runs out of free space, new allocations may
+fail (returning error code) or they may succeed, silently pushing some existing
+memory blocks from GPU VRAM to system RAM (which degrades performance). This
+behavior is implementation-dependant - it depends on GPU vendor and graphics
+driver.
+
+On AMD cards it can be controlled while creating Vulkan device object by using
+VK_AMD_memory_overallocation_behavior extension, if available.
+
+Alternatively, if you want to test how your program behaves with limited amount of Vulkan device
+memory available without switching your graphics card to one that really has
+smaller VRAM, you can use a feature of this library intended for this purpose.
+To do it, fill optional member VmaAllocatorCreateInfo::pHeapSizeLimit.
+
+
+
+\page vk_khr_dedicated_allocation VK_KHR_dedicated_allocation
+
+VK_KHR_dedicated_allocation is a Vulkan extension which can be used to improve
+performance on some GPUs. It augments Vulkan API with possibility to query
+driver whether it prefers particular buffer or image to have its own, dedicated
+allocation (separate `VkDeviceMemory` block) for better efficiency - to be able
+to do some internal optimizations.
+
+The extension is supported by this library. It will be used automatically when
+enabled. To enable it:
+
+1 . When creating Vulkan device, check if following 2 device extensions are
+supported (call `vkEnumerateDeviceExtensionProperties()`).
+If yes, enable them (fill `VkDeviceCreateInfo::ppEnabledExtensionNames`).
+
+- VK_KHR_get_memory_requirements2
+- VK_KHR_dedicated_allocation
+
+If you enabled these extensions:
+
+2 . Use #VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT flag when creating
+your #VmaAllocator`to inform the library that you enabled required extensions
+and you want the library to use them.
+
+\code
+allocatorInfo.flags |= VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT;
+
+vmaCreateAllocator(&allocatorInfo, &allocator);
+\endcode
+
+That's all. The extension will be automatically used whenever you create a
+buffer using vmaCreateBuffer() or image using vmaCreateImage().
+
+When using the extension together with Vulkan Validation Layer, you will receive
+warnings like this:
+
+    vkBindBufferMemory(): Binding memory to buffer 0x33 but vkGetBufferMemoryRequirements() has not been called on that buffer.
+
+It is OK, you should just ignore it. It happens because you use function
+`vkGetBufferMemoryRequirements2KHR()` instead of standard
+`vkGetBufferMemoryRequirements()`, while the validation layer seems to be
+unaware of it.
+
+To learn more about this extension, see:
+
+- [VK_KHR_dedicated_allocation in Vulkan specification](https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/chap44.html#VK_KHR_dedicated_allocation)
+- [VK_KHR_dedicated_allocation unofficial manual](http://asawicki.info/articles/VK_KHR_dedicated_allocation.php5)
+
+
+
+\page vk_amd_device_coherent_memory VK_AMD_device_coherent_memory
+
+VK_AMD_device_coherent_memory is a device extension that enables access to
+additional memory types with `VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD` and
+`VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD` flag. It is useful mostly for
+allocation of buffers intended for writing "breadcrumb markers" in between passes
+or draw calls, which in turn are useful for debugging GPU crash/hang/TDR cases.
+
+When the extension is available but has not been enabled, Vulkan physical device
+still exposes those memory types, but their usage is forbidden. VMA automatically
+takes care of that - it returns `VK_ERROR_FEATURE_NOT_PRESENT` when an attempt
+to allocate memory of such type is made.
+
+If you want to use this extension in connection with VMA, follow these steps:
+
+\section vk_amd_device_coherent_memory_initialization Initialization
+
+1) Call `vkEnumerateDeviceExtensionProperties` for the physical device.
+Check if the extension is supported - if returned array of `VkExtensionProperties` contains "VK_AMD_device_coherent_memory".
+
+2) Call `vkGetPhysicalDeviceFeatures2` for the physical device instead of old `vkGetPhysicalDeviceFeatures`.
+Attach additional structure `VkPhysicalDeviceCoherentMemoryFeaturesAMD` to `VkPhysicalDeviceFeatures2::pNext` to be returned.
+Check if the device feature is really supported - check if `VkPhysicalDeviceCoherentMemoryFeaturesAMD::deviceCoherentMemory` is true.
+
+3) While creating device with `vkCreateDevice`, enable this extension - add "VK_AMD_device_coherent_memory"
+to the list passed as `VkDeviceCreateInfo::ppEnabledExtensionNames`.
+
+4) While creating the device, also don't set `VkDeviceCreateInfo::pEnabledFeatures`.
+Fill in `VkPhysicalDeviceFeatures2` structure instead and pass it as `VkDeviceCreateInfo::pNext`.
+Enable this device feature - attach additional structure `VkPhysicalDeviceCoherentMemoryFeaturesAMD` to
+`VkPhysicalDeviceFeatures2::pNext` and set its member `deviceCoherentMemory` to `VK_TRUE`.
+
+5) While creating #VmaAllocator with vmaCreateAllocator() inform VMA that you
+have enabled this extension and feature - add #VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT
+to VmaAllocatorCreateInfo::flags.
+
+\section vk_amd_device_coherent_memory_usage Usage
+
+After following steps described above, you can create VMA allocations and custom pools
+out of the special `DEVICE_COHERENT` and `DEVICE_UNCACHED` memory types on eligible
+devices. There are multiple ways to do it, for example:
+
+- You can request or prefer to allocate out of such memory types by adding
+  `VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD` to VmaAllocationCreateInfo::requiredFlags
+  or VmaAllocationCreateInfo::preferredFlags. Those flags can be freely mixed with
+  other ways of \ref choosing_memory_type, like setting VmaAllocationCreateInfo::usage.
+- If you manually found memory type index to use for this purpose, force allocation
+  from this specific index by setting VmaAllocationCreateInfo::memoryTypeBits `= 1u << index`.
+
+\section vk_amd_device_coherent_memory_more_information More information
+
+To learn more about this extension, see [VK_AMD_device_coherent_memory in Vulkan specification](https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/chap44.html#VK_AMD_device_coherent_memory)
+
+Example use of this extension can be found in the code of the sample and test suite
+accompanying this library.
+
+
+\page enabling_buffer_device_address Enabling buffer device address
+
+Device extension VK_KHR_buffer_device_address
+allow to fetch raw GPU pointer to a buffer and pass it for usage in a shader code.
+It is promoted to core Vulkan 1.2.
+
+If you want to use this feature in connection with VMA, follow these steps:
+
+\section enabling_buffer_device_address_initialization Initialization
+
+1) (For Vulkan version < 1.2) Call `vkEnumerateDeviceExtensionProperties` for the physical device.
+Check if the extension is supported - if returned array of `VkExtensionProperties` contains
+"VK_KHR_buffer_device_address".
+
+2) Call `vkGetPhysicalDeviceFeatures2` for the physical device instead of old `vkGetPhysicalDeviceFeatures`.
+Attach additional structure `VkPhysicalDeviceBufferDeviceAddressFeatures*` to `VkPhysicalDeviceFeatures2::pNext` to be returned.
+Check if the device feature is really supported - check if `VkPhysicalDeviceBufferDeviceAddressFeatures*::bufferDeviceAddress` is true.
+
+3) (For Vulkan version < 1.2) While creating device with `vkCreateDevice`, enable this extension - add
+"VK_KHR_buffer_device_address" to the list passed as `VkDeviceCreateInfo::ppEnabledExtensionNames`.
+
+4) While creating the device, also don't set `VkDeviceCreateInfo::pEnabledFeatures`.
+Fill in `VkPhysicalDeviceFeatures2` structure instead and pass it as `VkDeviceCreateInfo::pNext`.
+Enable this device feature - attach additional structure `VkPhysicalDeviceBufferDeviceAddressFeatures*` to
+`VkPhysicalDeviceFeatures2::pNext` and set its member `bufferDeviceAddress` to `VK_TRUE`.
+
+5) While creating #VmaAllocator with vmaCreateAllocator() inform VMA that you
+have enabled this feature - add #VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT
+to VmaAllocatorCreateInfo::flags.
+
+\section enabling_buffer_device_address_usage Usage
+
+After following steps described above, you can create buffers with `VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT*` using VMA.
+The library automatically adds `VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT*` to
+allocated memory blocks wherever it might be needed.
+
+Please note that the library supports only `VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT*`.
+The second part of this functionality related to "capture and replay" is not supported,
+as it is intended for usage in debugging tools like RenderDoc, not in everyday Vulkan usage.
+
+\section enabling_buffer_device_address_more_information More information
+
+To learn more about this extension, see [VK_KHR_buffer_device_address in Vulkan specification](https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/chap46.html#VK_KHR_buffer_device_address)
+
+Example use of this extension can be found in the code of the sample and test suite
+accompanying this library.
+
+\page general_considerations General considerations
+
+\section general_considerations_thread_safety Thread safety
+
+- The library has no global state, so separate #VmaAllocator objects can be used
+  independently.
+  There should be no need to create multiple such objects though - one per `VkDevice` is enough.
+- By default, all calls to functions that take #VmaAllocator as first parameter
+  are safe to call from multiple threads simultaneously because they are
+  synchronized internally when needed.
+- When the allocator is created with #VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT
+  flag, calls to functions that take such #VmaAllocator object must be
+  synchronized externally.
+- Access to a #VmaAllocation object must be externally synchronized. For example,
+  you must not call vmaGetAllocationInfo() and vmaMapMemory() from different
+  threads at the same time if you pass the same #VmaAllocation object to these
+  functions.
+
+\section general_considerations_validation_layer_warnings Validation layer warnings
+
+When using this library, you can meet following types of warnings issued by
+Vulkan validation layer. They don't necessarily indicate a bug, so you may need
+to just ignore them.
+
+- *vkBindBufferMemory(): Binding memory to buffer 0xeb8e4 but vkGetBufferMemoryRequirements() has not been called on that buffer.*
+  - It happens when VK_KHR_dedicated_allocation extension is enabled.
+    `vkGetBufferMemoryRequirements2KHR` function is used instead, while validation layer seems to be unaware of it.
+- *Mapping an image with layout VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL can result in undefined behavior if this memory is used by the device. Only GENERAL or PREINITIALIZED should be used.*
+  - It happens when you map a buffer or image, because the library maps entire
+    `VkDeviceMemory` block, where different types of images and buffers may end
+    up together, especially on GPUs with unified memory like Intel.
+- *Non-linear image 0xebc91 is aliased with linear buffer 0xeb8e4 which may indicate a bug.*
+  - It happens when you use lost allocations, and a new image or buffer is
+    created in place of an existing object that bacame lost.
+  - It may happen also when you use [defragmentation](@ref defragmentation).
+
+\section general_considerations_allocation_algorithm Allocation algorithm
+
+The library uses following algorithm for allocation, in order:
+
+-# Try to find free range of memory in existing blocks.
+-# If failed, try to create a new block of `VkDeviceMemory`, with preferred block size.
+-# If failed, try to create such block with size/2, size/4, size/8.
+-# If failed and #VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT flag was
+   specified, try to find space in existing blocks, possilby making some other
+   allocations lost.
+-# If failed, try to allocate separate `VkDeviceMemory` for this allocation,
+   just like when you use #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT.
+-# If failed, choose other memory type that meets the requirements specified in
+   VmaAllocationCreateInfo and go to point 1.
+-# If failed, return `VK_ERROR_OUT_OF_DEVICE_MEMORY`.
+
+\section general_considerations_features_not_supported Features not supported
+
+Features deliberately excluded from the scope of this library:
+
+- Data transfer. Uploading (straming) and downloading data of buffers and images
+  between CPU and GPU memory and related synchronization is responsibility of the user.
+  Defining some "texture" object that would automatically stream its data from a
+  staging copy in CPU memory to GPU memory would rather be a feature of another,
+  higher-level library implemented on top of VMA.
+- Allocations for imported/exported external memory. They tend to require
+  explicit memory type index and dedicated allocation anyway, so they don't
+  interact with main features of this library. Such special purpose allocations
+  should be made manually, using `vkCreateBuffer()` and `vkAllocateMemory()`.
+- Recreation of buffers and images. Although the library has functions for
+  buffer and image creation (vmaCreateBuffer(), vmaCreateImage()), you need to
+  recreate these objects yourself after defragmentation. That's because the big
+  structures `VkBufferCreateInfo`, `VkImageCreateInfo` are not stored in
+  #VmaAllocation object.
+- Handling CPU memory allocation failures. When dynamically creating small C++
+  objects in CPU memory (not Vulkan memory), allocation failures are not checked
+  and handled gracefully, because that would complicate code significantly and
+  is usually not needed in desktop PC applications anyway.
+- Code free of any compiler warnings. Maintaining the library to compile and
+  work correctly on so many different platforms is hard enough. Being free of 
+  any warnings, on any version of any compiler, is simply not feasible.
+- This is a C++ library with C interface.
+  Bindings or ports to any other programming languages are welcomed as external projects and
+  are not going to be included into this repository.
+
+*/
+
+/*
+Define this macro to 0/1 to disable/enable support for recording functionality,
+available through VmaAllocatorCreateInfo::pRecordSettings.
+*/
+#ifndef VMA_RECORDING_ENABLED
+    #define VMA_RECORDING_ENABLED 0
+#endif
+
+#ifndef NOMINMAX
+    #define NOMINMAX // For windows.h
+#endif
+
+#if defined(__ANDROID__) && defined(VK_NO_PROTOTYPES) && VMA_STATIC_VULKAN_FUNCTIONS
+    extern PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr;
+    extern PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr;
+    extern PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties;
+    extern PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties;
+    extern PFN_vkAllocateMemory vkAllocateMemory;
+    extern PFN_vkFreeMemory vkFreeMemory;
+    extern PFN_vkMapMemory vkMapMemory;
+    extern PFN_vkUnmapMemory vkUnmapMemory;
+    extern PFN_vkFlushMappedMemoryRanges vkFlushMappedMemoryRanges;
+    extern PFN_vkInvalidateMappedMemoryRanges vkInvalidateMappedMemoryRanges;
+    extern PFN_vkBindBufferMemory vkBindBufferMemory;
+    extern PFN_vkBindImageMemory vkBindImageMemory;
+    extern PFN_vkGetBufferMemoryRequirements vkGetBufferMemoryRequirements;
+    extern PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements;
+    extern PFN_vkCreateBuffer vkCreateBuffer;
+    extern PFN_vkDestroyBuffer vkDestroyBuffer;
+    extern PFN_vkCreateImage vkCreateImage;
+    extern PFN_vkDestroyImage vkDestroyImage;
+    extern PFN_vkCmdCopyBuffer vkCmdCopyBuffer;
+    #if VMA_VULKAN_VERSION >= 1001000
+        extern PFN_vkGetBufferMemoryRequirements2 vkGetBufferMemoryRequirements2;
+        extern PFN_vkGetImageMemoryRequirements2 vkGetImageMemoryRequirements2;
+        extern PFN_vkBindBufferMemory2 vkBindBufferMemory2;
+        extern PFN_vkBindImageMemory2 vkBindImageMemory2;
+        extern PFN_vkGetPhysicalDeviceMemoryProperties2 vkGetPhysicalDeviceMemoryProperties2;
+    #endif // #if VMA_VULKAN_VERSION >= 1001000
+#endif // #if defined(__ANDROID__) && VMA_STATIC_VULKAN_FUNCTIONS && VK_NO_PROTOTYPES
+
+#ifndef VULKAN_H_
+    #include <vulkan/vulkan.h>
+#endif
+
+#if VMA_RECORDING_ENABLED
+    #include <windows.h>
+#endif
+
+// Define this macro to declare maximum supported Vulkan version in format AAABBBCCC,
+// where AAA = major, BBB = minor, CCC = patch.
+// If you want to use version > 1.0, it still needs to be enabled via VmaAllocatorCreateInfo::vulkanApiVersion.
+#if !defined(VMA_VULKAN_VERSION)
+    #if defined(VK_VERSION_1_2)
+        #define VMA_VULKAN_VERSION 1002000
+    #elif defined(VK_VERSION_1_1)
+        #define VMA_VULKAN_VERSION 1001000
+    #else
+        #define VMA_VULKAN_VERSION 1000000
+    #endif
+#endif
+
+#if !defined(VMA_DEDICATED_ALLOCATION)
+    #if VK_KHR_get_memory_requirements2 && VK_KHR_dedicated_allocation
+        #define VMA_DEDICATED_ALLOCATION 1
+    #else
+        #define VMA_DEDICATED_ALLOCATION 0
+    #endif
+#endif
+
+#if !defined(VMA_BIND_MEMORY2)
+    #if VK_KHR_bind_memory2
+        #define VMA_BIND_MEMORY2 1
+    #else
+        #define VMA_BIND_MEMORY2 0
+    #endif
+#endif
+
+#if !defined(VMA_MEMORY_BUDGET)
+    #if VK_EXT_memory_budget && (VK_KHR_get_physical_device_properties2 || VMA_VULKAN_VERSION >= 1001000)
+        #define VMA_MEMORY_BUDGET 1
+    #else
+        #define VMA_MEMORY_BUDGET 0
+    #endif
+#endif
+
+// Defined to 1 when VK_KHR_buffer_device_address device extension or equivalent core Vulkan 1.2 feature is defined in its headers.
+#if !defined(VMA_BUFFER_DEVICE_ADDRESS)
+    #if VK_KHR_buffer_device_address || VMA_VULKAN_VERSION >= 1002000
+        #define VMA_BUFFER_DEVICE_ADDRESS 1
+    #else
+        #define VMA_BUFFER_DEVICE_ADDRESS 0
+    #endif
+#endif
+
+// Define these macros to decorate all public functions with additional code,
+// before and after returned type, appropriately. This may be useful for
+// exporing the functions when compiling VMA as a separate library. Example:
+// #define VMA_CALL_PRE  __declspec(dllexport)
+// #define VMA_CALL_POST __cdecl
+#ifndef VMA_CALL_PRE
+    #define VMA_CALL_PRE
+#endif
+#ifndef VMA_CALL_POST
+    #define VMA_CALL_POST
+#endif
+
+/** \struct VmaAllocator
+\brief Represents main object of this library initialized.
+
+Fill structure #VmaAllocatorCreateInfo and call function vmaCreateAllocator() to create it.
+Call function vmaDestroyAllocator() to destroy it.
+
+It is recommended to create just one object of this type per `VkDevice` object,
+right after Vulkan is initialized and keep it alive until before Vulkan device is destroyed.
+*/
+VK_DEFINE_HANDLE(VmaAllocator)
+
+/// Callback function called after successful vkAllocateMemory.
+typedef void (VKAPI_PTR *PFN_vmaAllocateDeviceMemoryFunction)(
+    VmaAllocator      allocator,
+    uint32_t          memoryType,
+    VkDeviceMemory    memory,
+    VkDeviceSize      size,
+    void* pUserData);
+/// Callback function called before vkFreeMemory.
+typedef void (VKAPI_PTR *PFN_vmaFreeDeviceMemoryFunction)(
+    VmaAllocator      allocator,
+    uint32_t          memoryType,
+    VkDeviceMemory    memory,
+    VkDeviceSize      size,
+    void* pUserData);
+
+/** \brief Set of callbacks that the library will call for `vkAllocateMemory` and `vkFreeMemory`.
+
+Provided for informative purpose, e.g. to gather statistics about number of
+allocations or total amount of memory allocated in Vulkan.
+
+Used in VmaAllocatorCreateInfo::pDeviceMemoryCallbacks.
+*/
+typedef struct VmaDeviceMemoryCallbacks {
+    /// Optional, can be null.
+    PFN_vmaAllocateDeviceMemoryFunction pfnAllocate;
+    /// Optional, can be null.
+    PFN_vmaFreeDeviceMemoryFunction pfnFree;
+    /// Optional, can be null.
+    void* pUserData;
+} VmaDeviceMemoryCallbacks;
+
+/// Flags for created #VmaAllocator.
+typedef enum VmaAllocatorCreateFlagBits {
+    /** \brief Allocator and all objects created from it will not be synchronized internally, so you must guarantee they are used from only one thread at a time or synchronized externally by you.
+
+    Using this flag may increase performance because internal mutexes are not used.
+    */
+    VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT = 0x00000001,
+    /** \brief Enables usage of VK_KHR_dedicated_allocation extension.
+
+    The flag works only if VmaAllocatorCreateInfo::vulkanApiVersion `== VK_API_VERSION_1_0`.
+    When it's `VK_API_VERSION_1_1`, the flag is ignored because the extension has been promoted to Vulkan 1.1.
+
+    Using this extenion will automatically allocate dedicated blocks of memory for
+    some buffers and images instead of suballocating place for them out of bigger
+    memory blocks (as if you explicitly used #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT
+    flag) when it is recommended by the driver. It may improve performance on some
+    GPUs.
+
+    You may set this flag only if you found out that following device extensions are
+    supported, you enabled them while creating Vulkan device passed as
+    VmaAllocatorCreateInfo::device, and you want them to be used internally by this
+    library:
+
+    - VK_KHR_get_memory_requirements2 (device extension)
+    - VK_KHR_dedicated_allocation (device extension)
+
+    When this flag is set, you can experience following warnings reported by Vulkan
+    validation layer. You can ignore them.
+
+    > vkBindBufferMemory(): Binding memory to buffer 0x2d but vkGetBufferMemoryRequirements() has not been called on that buffer.
+    */
+    VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT = 0x00000002,
+    /**
+    Enables usage of VK_KHR_bind_memory2 extension.
+
+    The flag works only if VmaAllocatorCreateInfo::vulkanApiVersion `== VK_API_VERSION_1_0`.
+    When it's `VK_API_VERSION_1_1`, the flag is ignored because the extension has been promoted to Vulkan 1.1.
+
+    You may set this flag only if you found out that this device extension is supported,
+    you enabled it while creating Vulkan device passed as VmaAllocatorCreateInfo::device,
+    and you want it to be used internally by this library.
+
+    The extension provides functions `vkBindBufferMemory2KHR` and `vkBindImageMemory2KHR`,
+    which allow to pass a chain of `pNext` structures while binding.
+    This flag is required if you use `pNext` parameter in vmaBindBufferMemory2() or vmaBindImageMemory2().
+    */
+    VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT = 0x00000004,
+    /**
+    Enables usage of VK_EXT_memory_budget extension.
+
+    You may set this flag only if you found out that this device extension is supported,
+    you enabled it while creating Vulkan device passed as VmaAllocatorCreateInfo::device,
+    and you want it to be used internally by this library, along with another instance extension
+    VK_KHR_get_physical_device_properties2, which is required by it (or Vulkan 1.1, where this extension is promoted).
+
+    The extension provides query for current memory usage and budget, which will probably
+    be more accurate than an estimation used by the library otherwise.
+    */
+    VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT = 0x00000008,
+    /**
+    Enables usage of VK_AMD_device_coherent_memory extension.
+    
+    You may set this flag only if you:
+
+    - found out that this device extension is supported and enabled it while creating Vulkan device passed as VmaAllocatorCreateInfo::device,
+    - checked that `VkPhysicalDeviceCoherentMemoryFeaturesAMD::deviceCoherentMemory` is true and set it while creating the Vulkan device,
+    - want it to be used internally by this library.
+
+    The extension and accompanying device feature provide access to memory types with
+    `VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD` and `VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD` flags.
+    They are useful mostly for writing breadcrumb markers - a common method for debugging GPU crash/hang/TDR.
+    
+    When the extension is not enabled, such memory types are still enumerated, but their usage is illegal.
+    To protect from this error, if you don't create the allocator with this flag, it will refuse to allocate any memory or create a custom pool in such memory type,
+    returning `VK_ERROR_FEATURE_NOT_PRESENT`.
+    */
+    VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT = 0x00000010,
+    /**
+    Enables usage of "buffer device address" feature, which allows you to use function
+    `vkGetBufferDeviceAddress*` to get raw GPU pointer to a buffer and pass it for usage inside a shader.
+
+    You may set this flag only if you:
+
+    1. (For Vulkan version < 1.2) Found as available and enabled device extension
+    VK_KHR_buffer_device_address.
+    This extension is promoted to core Vulkan 1.2.
+    2. Found as available and enabled device feature `VkPhysicalDeviceBufferDeviceAddressFeatures*::bufferDeviceAddress`.
+
+    When this flag is set, you can create buffers with `VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT*` using VMA.
+    The library automatically adds `VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT*` to
+    allocated memory blocks wherever it might be needed.
+
+    For more information, see documentation chapter \ref enabling_buffer_device_address.
+    */
+    VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT = 0x00000020,
+
+    VMA_ALLOCATOR_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VmaAllocatorCreateFlagBits;
+typedef VkFlags VmaAllocatorCreateFlags;
+
+/** \brief Pointers to some Vulkan functions - a subset used by the library.
+
+Used in VmaAllocatorCreateInfo::pVulkanFunctions.
+*/
+typedef struct VmaVulkanFunctions {
+    PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties;
+    PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties;
+    PFN_vkAllocateMemory vkAllocateMemory;
+    PFN_vkFreeMemory vkFreeMemory;
+    PFN_vkMapMemory vkMapMemory;
+    PFN_vkUnmapMemory vkUnmapMemory;
+    PFN_vkFlushMappedMemoryRanges vkFlushMappedMemoryRanges;
+    PFN_vkInvalidateMappedMemoryRanges vkInvalidateMappedMemoryRanges;
+    PFN_vkBindBufferMemory vkBindBufferMemory;
+    PFN_vkBindImageMemory vkBindImageMemory;
+    PFN_vkGetBufferMemoryRequirements vkGetBufferMemoryRequirements;
+    PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements;
+    PFN_vkCreateBuffer vkCreateBuffer;
+    PFN_vkDestroyBuffer vkDestroyBuffer;
+    PFN_vkCreateImage vkCreateImage;
+    PFN_vkDestroyImage vkDestroyImage;
+    PFN_vkCmdCopyBuffer vkCmdCopyBuffer;
+#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000
+    PFN_vkGetBufferMemoryRequirements2KHR vkGetBufferMemoryRequirements2KHR;
+    PFN_vkGetImageMemoryRequirements2KHR vkGetImageMemoryRequirements2KHR;
+#endif
+#if VMA_BIND_MEMORY2 || VMA_VULKAN_VERSION >= 1001000
+    PFN_vkBindBufferMemory2KHR vkBindBufferMemory2KHR;
+    PFN_vkBindImageMemory2KHR vkBindImageMemory2KHR;
+#endif
+#if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION >= 1001000
+    PFN_vkGetPhysicalDeviceMemoryProperties2KHR vkGetPhysicalDeviceMemoryProperties2KHR;
+#endif
+} VmaVulkanFunctions;
+
+/// Flags to be used in VmaRecordSettings::flags.
+typedef enum VmaRecordFlagBits {
+    /** \brief Enables flush after recording every function call.
+
+    Enable it if you expect your application to crash, which may leave recording file truncated.
+    It may degrade performance though.
+    */
+    VMA_RECORD_FLUSH_AFTER_CALL_BIT = 0x00000001,
+    
+    VMA_RECORD_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VmaRecordFlagBits;
+typedef VkFlags VmaRecordFlags;
+
+/// Parameters for recording calls to VMA functions. To be used in VmaAllocatorCreateInfo::pRecordSettings.
+typedef struct VmaRecordSettings
+{
+    /// Flags for recording. Use #VmaRecordFlagBits enum.
+    VmaRecordFlags flags;
+    /** \brief Path to the file that should be written by the recording.
+
+    Suggested extension: "csv".
+    If the file already exists, it will be overwritten.
+    It will be opened for the whole time #VmaAllocator object is alive.
+    If opening this file fails, creation of the whole allocator object fails.
+    */
+    const char* pFilePath;
+} VmaRecordSettings;
+
+/// Description of a Allocator to be created.
+typedef struct VmaAllocatorCreateInfo
+{
+    /// Flags for created allocator. Use #VmaAllocatorCreateFlagBits enum.
+    VmaAllocatorCreateFlags flags;
+    /// Vulkan physical device.
+    /** It must be valid throughout whole lifetime of created allocator. */
+    VkPhysicalDevice physicalDevice;
+    /// Vulkan device.
+    /** It must be valid throughout whole lifetime of created allocator. */
+    VkDevice device;
+    /// Preferred size of a single `VkDeviceMemory` block to be allocated from large heaps > 1 GiB. Optional.
+    /** Set to 0 to use default, which is currently 256 MiB. */
+    VkDeviceSize preferredLargeHeapBlockSize;
+    /// Custom CPU memory allocation callbacks. Optional.
+    /** Optional, can be null. When specified, will also be used for all CPU-side memory allocations. */
+    const VkAllocationCallbacks* pAllocationCallbacks;
+    /// Informative callbacks for `vkAllocateMemory`, `vkFreeMemory`. Optional.
+    /** Optional, can be null. */
+    const VmaDeviceMemoryCallbacks* pDeviceMemoryCallbacks;
+    /** \brief Maximum number of additional frames that are in use at the same time as current frame.
+
+    This value is used only when you make allocations with
+    VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT flag. Such allocation cannot become
+    lost if allocation.lastUseFrameIndex >= allocator.currentFrameIndex - frameInUseCount.
+
+    For example, if you double-buffer your command buffers, so resources used for
+    rendering in previous frame may still be in use by the GPU at the moment you
+    allocate resources needed for the current frame, set this value to 1.
+
+    If you want to allow any allocations other than used in the current frame to
+    become lost, set this value to 0.
+    */
+    uint32_t frameInUseCount;
+    /** \brief Either null or a pointer to an array of limits on maximum number of bytes that can be allocated out of particular Vulkan memory heap.
+
+    If not NULL, it must be a pointer to an array of
+    `VkPhysicalDeviceMemoryProperties::memoryHeapCount` elements, defining limit on
+    maximum number of bytes that can be allocated out of particular Vulkan memory
+    heap.
+
+    Any of the elements may be equal to `VK_WHOLE_SIZE`, which means no limit on that
+    heap. This is also the default in case of `pHeapSizeLimit` = NULL.
+
+    If there is a limit defined for a heap:
+
+    - If user tries to allocate more memory from that heap using this allocator,
+      the allocation fails with `VK_ERROR_OUT_OF_DEVICE_MEMORY`.
+    - If the limit is smaller than heap size reported in `VkMemoryHeap::size`, the
+      value of this limit will be reported instead when using vmaGetMemoryProperties().
+
+    Warning! Using this feature may not be equivalent to installing a GPU with
+    smaller amount of memory, because graphics driver doesn't necessary fail new
+    allocations with `VK_ERROR_OUT_OF_DEVICE_MEMORY` result when memory capacity is
+    exceeded. It may return success and just silently migrate some device memory
+    blocks to system RAM. This driver behavior can also be controlled using
+    VK_AMD_memory_overallocation_behavior extension.
+    */
+    const VkDeviceSize* pHeapSizeLimit;
+    /** \brief Pointers to Vulkan functions. Can be null.
+
+    For details see [Pointers to Vulkan functions](@ref config_Vulkan_functions).
+    */
+    const VmaVulkanFunctions* pVulkanFunctions;
+    /** \brief Parameters for recording of VMA calls. Can be null.
+
+    If not null, it enables recording of calls to VMA functions to a file.
+    If support for recording is not enabled using `VMA_RECORDING_ENABLED` macro,
+    creation of the allocator object fails with `VK_ERROR_FEATURE_NOT_PRESENT`.
+    */
+    const VmaRecordSettings* pRecordSettings;
+    /** \brief Handle to Vulkan instance object.
+
+    Starting from version 3.0.0 this member is no longer optional, it must be set!
+    */
+    VkInstance instance;
+    /** \brief Optional. The highest version of Vulkan that the application is designed to use.
+    
+    It must be a value in the format as created by macro `VK_MAKE_VERSION` or a constant like: `VK_API_VERSION_1_1`, `VK_API_VERSION_1_0`.
+    The patch version number specified is ignored. Only the major and minor versions are considered.
+    It must be less or equal (preferably equal) to value as passed to `vkCreateInstance` as `VkApplicationInfo::apiVersion`.
+    Only versions 1.0 and 1.1 are supported by the current implementation.
+    Leaving it initialized to zero is equivalent to `VK_API_VERSION_1_0`.
+    */
+    uint32_t vulkanApiVersion;
+} VmaAllocatorCreateInfo;
+
+/// Creates Allocator object.
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAllocator(
+    const VmaAllocatorCreateInfo* pCreateInfo,
+    VmaAllocator* pAllocator);
+
+/// Destroys allocator object.
+VMA_CALL_PRE void VMA_CALL_POST vmaDestroyAllocator(
+    VmaAllocator allocator);
+
+/** \brief Information about existing #VmaAllocator object.
+*/
+typedef struct VmaAllocatorInfo
+{
+    /** \brief Handle to Vulkan instance object.
+
+    This is the same value as has been passed through VmaAllocatorCreateInfo::instance.
+    */
+    VkInstance instance;
+    /** \brief Handle to Vulkan physical device object.
+
+    This is the same value as has been passed through VmaAllocatorCreateInfo::physicalDevice.
+    */
+    VkPhysicalDevice physicalDevice;
+    /** \brief Handle to Vulkan device object.
+
+    This is the same value as has been passed through VmaAllocatorCreateInfo::device.
+    */
+    VkDevice device;
+} VmaAllocatorInfo;
+
+/** \brief Returns information about existing #VmaAllocator object - handle to Vulkan device etc.
+
+It might be useful if you want to keep just the #VmaAllocator handle and fetch other required handles to
+`VkPhysicalDevice`, `VkDevice` etc. every time using this function.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocatorInfo(VmaAllocator allocator, VmaAllocatorInfo* pAllocatorInfo);
+
+/**
+PhysicalDeviceProperties are fetched from physicalDevice by the allocator.
+You can access it here, without fetching it again on your own.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaGetPhysicalDeviceProperties(
+    VmaAllocator allocator,
+    const VkPhysicalDeviceProperties** ppPhysicalDeviceProperties);
+
+/**
+PhysicalDeviceMemoryProperties are fetched from physicalDevice by the allocator.
+You can access it here, without fetching it again on your own.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaGetMemoryProperties(
+    VmaAllocator allocator,
+    const VkPhysicalDeviceMemoryProperties** ppPhysicalDeviceMemoryProperties);
+
+/**
+\brief Given Memory Type Index, returns Property Flags of this memory type.
+
+This is just a convenience function. Same information can be obtained using
+vmaGetMemoryProperties().
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaGetMemoryTypeProperties(
+    VmaAllocator allocator,
+    uint32_t memoryTypeIndex,
+    VkMemoryPropertyFlags* pFlags);
+
+/** \brief Sets index of the current frame.
+
+This function must be used if you make allocations with
+#VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT and
+#VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT flags to inform the allocator
+when a new frame begins. Allocations queried using vmaGetAllocationInfo() cannot
+become lost in the current frame.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaSetCurrentFrameIndex(
+    VmaAllocator allocator,
+    uint32_t frameIndex);
+
+/** \brief Calculated statistics of memory usage in entire allocator.
+*/
+typedef struct VmaStatInfo
+{
+    /// Number of `VkDeviceMemory` Vulkan memory blocks allocated.
+    uint32_t blockCount;
+    /// Number of #VmaAllocation allocation objects allocated.
+    uint32_t allocationCount;
+    /// Number of free ranges of memory between allocations.
+    uint32_t unusedRangeCount;
+    /// Total number of bytes occupied by all allocations.
+    VkDeviceSize usedBytes;
+    /// Total number of bytes occupied by unused ranges.
+    VkDeviceSize unusedBytes;
+    VkDeviceSize allocationSizeMin, allocationSizeAvg, allocationSizeMax;
+    VkDeviceSize unusedRangeSizeMin, unusedRangeSizeAvg, unusedRangeSizeMax;
+} VmaStatInfo;
+
+/// General statistics from current state of Allocator.
+typedef struct VmaStats
+{
+    VmaStatInfo memoryType[VK_MAX_MEMORY_TYPES];
+    VmaStatInfo memoryHeap[VK_MAX_MEMORY_HEAPS];
+    VmaStatInfo total;
+} VmaStats;
+
+/** \brief Retrieves statistics from current state of the Allocator.
+
+This function is called "calculate" not "get" because it has to traverse all
+internal data structures, so it may be quite slow. For faster but more brief statistics
+suitable to be called every frame or every allocation, use vmaGetBudget().
+
+Note that when using allocator from multiple threads, returned information may immediately
+become outdated.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaCalculateStats(
+    VmaAllocator allocator,
+    VmaStats* pStats);
+
+/** \brief Statistics of current memory usage and available budget, in bytes, for specific memory heap.
+*/
+typedef struct VmaBudget
+{
+    /** \brief Sum size of all `VkDeviceMemory` blocks allocated from particular heap, in bytes.
+    */
+    VkDeviceSize blockBytes;
+    
+    /** \brief Sum size of all allocations created in particular heap, in bytes.
+    
+    Usually less or equal than `blockBytes`.
+    Difference `blockBytes - allocationBytes` is the amount of memory allocated but unused -
+    available for new allocations or wasted due to fragmentation.
+    
+    It might be greater than `blockBytes` if there are some allocations in lost state, as they account
+    to this value as well.
+    */
+    VkDeviceSize allocationBytes;
+    
+    /** \brief Estimated current memory usage of the program, in bytes.
+    
+    Fetched from system using `VK_EXT_memory_budget` extension if enabled.
+    
+    It might be different than `blockBytes` (usually higher) due to additional implicit objects
+    also occupying the memory, like swapchain, pipelines, descriptor heaps, command buffers, or
+    `VkDeviceMemory` blocks allocated outside of this library, if any.
+    */
+    VkDeviceSize usage;
+    
+    /** \brief Estimated amount of memory available to the program, in bytes.
+    
+    Fetched from system using `VK_EXT_memory_budget` extension if enabled.
+    
+    It might be different (most probably smaller) than `VkMemoryHeap::size[heapIndex]` due to factors
+    external to the program, like other programs also consuming system resources.
+    Difference `budget - usage` is the amount of additional memory that can probably
+    be allocated without problems. Exceeding the budget may result in various problems.
+    */
+    VkDeviceSize budget;
+} VmaBudget;
+
+/** \brief Retrieves information about current memory budget for all memory heaps.
+
+\param[out] pBudget Must point to array with number of elements at least equal to number of memory heaps in physical device used.
+
+This function is called "get" not "calculate" because it is very fast, suitable to be called
+every frame or every allocation. For more detailed statistics use vmaCalculateStats().
+
+Note that when using allocator from multiple threads, returned information may immediately
+become outdated.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaGetBudget(
+    VmaAllocator allocator,
+    VmaBudget* pBudget);
+
+#ifndef VMA_STATS_STRING_ENABLED
+#define VMA_STATS_STRING_ENABLED 1
+#endif
+
+#if VMA_STATS_STRING_ENABLED
+
+/// Builds and returns statistics as string in JSON format.
+/** @param[out] ppStatsString Must be freed using vmaFreeStatsString() function.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaBuildStatsString(
+    VmaAllocator allocator,
+    char** ppStatsString,
+    VkBool32 detailedMap);
+
+VMA_CALL_PRE void VMA_CALL_POST vmaFreeStatsString(
+    VmaAllocator allocator,
+    char* pStatsString);
+
+#endif // #if VMA_STATS_STRING_ENABLED
+
+/** \struct VmaPool
+\brief Represents custom memory pool
+
+Fill structure VmaPoolCreateInfo and call function vmaCreatePool() to create it.
+Call function vmaDestroyPool() to destroy it.
+
+For more information see [Custom memory pools](@ref choosing_memory_type_custom_memory_pools).
+*/
+VK_DEFINE_HANDLE(VmaPool)
+
+typedef enum VmaMemoryUsage
+{
+    /** No intended memory usage specified.
+    Use other members of VmaAllocationCreateInfo to specify your requirements.
+    */
+    VMA_MEMORY_USAGE_UNKNOWN = 0,
+    /** Memory will be used on device only, so fast access from the device is preferred.
+    It usually means device-local GPU (video) memory.
+    No need to be mappable on host.
+    It is roughly equivalent of `D3D12_HEAP_TYPE_DEFAULT`.
+
+    Usage:
+    
+    - Resources written and read by device, e.g. images used as attachments.
+    - Resources transferred from host once (immutable) or infrequently and read by
+      device multiple times, e.g. textures to be sampled, vertex buffers, uniform
+      (constant) buffers, and majority of other types of resources used on GPU.
+
+    Allocation may still end up in `HOST_VISIBLE` memory on some implementations.
+    In such case, you are free to map it.
+    You can use #VMA_ALLOCATION_CREATE_MAPPED_BIT with this usage type.
+    */
+    VMA_MEMORY_USAGE_GPU_ONLY = 1,
+    /** Memory will be mappable on host.
+    It usually means CPU (system) memory.
+    Guarantees to be `HOST_VISIBLE` and `HOST_COHERENT`.
+    CPU access is typically uncached. Writes may be write-combined.
+    Resources created in this pool may still be accessible to the device, but access to them can be slow.
+    It is roughly equivalent of `D3D12_HEAP_TYPE_UPLOAD`.
+
+    Usage: Staging copy of resources used as transfer source.
+    */
+    VMA_MEMORY_USAGE_CPU_ONLY = 2,
+    /**
+    Memory that is both mappable on host (guarantees to be `HOST_VISIBLE`) and preferably fast to access by GPU.
+    CPU access is typically uncached. Writes may be write-combined.
+
+    Usage: Resources written frequently by host (dynamic), read by device. E.g. textures, vertex buffers, uniform buffers updated every frame or every draw call.
+    */
+    VMA_MEMORY_USAGE_CPU_TO_GPU = 3,
+    /** Memory mappable on host (guarantees to be `HOST_VISIBLE`) and cached.
+    It is roughly equivalent of `D3D12_HEAP_TYPE_READBACK`.
+
+    Usage:
+
+    - Resources written by device, read by host - results of some computations, e.g. screen capture, average scene luminance for HDR tone mapping.
+    - Any resources read or accessed randomly on host, e.g. CPU-side copy of vertex buffer used as source of transfer, but also used for collision detection.
+    */
+    VMA_MEMORY_USAGE_GPU_TO_CPU = 4,
+    /** CPU memory - memory that is preferably not `DEVICE_LOCAL`, but also not guaranteed to be `HOST_VISIBLE`.
+
+    Usage: Staging copy of resources moved from GPU memory to CPU memory as part
+    of custom paging/residency mechanism, to be moved back to GPU memory when needed.
+    */
+    VMA_MEMORY_USAGE_CPU_COPY = 5,
+    /** Lazily allocated GPU memory having `VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT`.
+    Exists mostly on mobile platforms. Using it on desktop PC or other GPUs with no such memory type present will fail the allocation.
+    
+    Usage: Memory for transient attachment images (color attachments, depth attachments etc.), created with `VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT`.
+
+    Allocations with this usage are always created as dedicated - it implies #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT.
+    */
+    VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED = 6,
+
+    VMA_MEMORY_USAGE_MAX_ENUM = 0x7FFFFFFF
+} VmaMemoryUsage;
+
+/// Flags to be passed as VmaAllocationCreateInfo::flags.
+typedef enum VmaAllocationCreateFlagBits {
+    /** \brief Set this flag if the allocation should have its own memory block.
+    
+    Use it for special, big resources, like fullscreen images used as attachments.
+   
+    You should not use this flag if VmaAllocationCreateInfo::pool is not null.
+    */
+    VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT = 0x00000001,
+
+    /** \brief Set this flag to only try to allocate from existing `VkDeviceMemory` blocks and never create new such block.
+    
+    If new allocation cannot be placed in any of the existing blocks, allocation
+    fails with `VK_ERROR_OUT_OF_DEVICE_MEMORY` error.
+    
+    You should not use #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT and
+    #VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT at the same time. It makes no sense.
+    
+    If VmaAllocationCreateInfo::pool is not null, this flag is implied and ignored. */
+    VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT = 0x00000002,
+    /** \brief Set this flag to use a memory that will be persistently mapped and retrieve pointer to it.
+    
+    Pointer to mapped memory will be returned through VmaAllocationInfo::pMappedData.
+
+    Is it valid to use this flag for allocation made from memory type that is not
+    `HOST_VISIBLE`. This flag is then ignored and memory is not mapped. This is
+    useful if you need an allocation that is efficient to use on GPU
+    (`DEVICE_LOCAL`) and still want to map it directly if possible on platforms that
+    support it (e.g. Intel GPU).
+
+    You should not use this flag together with #VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT.
+    */
+    VMA_ALLOCATION_CREATE_MAPPED_BIT = 0x00000004,
+    /** Allocation created with this flag can become lost as a result of another
+    allocation with #VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT flag, so you
+    must check it before use.
+
+    To check if allocation is not lost, call vmaGetAllocationInfo() and check if
+    VmaAllocationInfo::deviceMemory is not `VK_NULL_HANDLE`.
+
+    For details about supporting lost allocations, see Lost Allocations
+    chapter of User Guide on Main Page.
+
+    You should not use this flag together with #VMA_ALLOCATION_CREATE_MAPPED_BIT.
+    */
+    VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT = 0x00000008,
+    /** While creating allocation using this flag, other allocations that were
+    created with flag #VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT can become lost.
+
+    For details about supporting lost allocations, see Lost Allocations
+    chapter of User Guide on Main Page.
+    */
+    VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT = 0x00000010,
+    /** Set this flag to treat VmaAllocationCreateInfo::pUserData as pointer to a
+    null-terminated string. Instead of copying pointer value, a local copy of the
+    string is made and stored in allocation's `pUserData`. The string is automatically
+    freed together with the allocation. It is also used in vmaBuildStatsString().
+    */
+    VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT = 0x00000020,
+    /** Allocation will be created from upper stack in a double stack pool.
+
+    This flag is only allowed for custom pools created with #VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT flag.
+    */
+    VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT = 0x00000040,
+    /** Create both buffer/image and allocation, but don't bind them together.
+    It is useful when you want to bind yourself to do some more advanced binding, e.g. using some extensions.
+    The flag is meaningful only with functions that bind by default: vmaCreateBuffer(), vmaCreateImage().
+    Otherwise it is ignored.
+    */
+    VMA_ALLOCATION_CREATE_DONT_BIND_BIT = 0x00000080,
+    /** Create allocation only if additional device memory required for it, if any, won't exceed
+    memory budget. Otherwise return `VK_ERROR_OUT_OF_DEVICE_MEMORY`.
+    */
+    VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT = 0x00000100,
+
+    /** Allocation strategy that chooses smallest possible free range for the
+    allocation.
+    */
+    VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT  = 0x00010000,
+    /** Allocation strategy that chooses biggest possible free range for the
+    allocation.
+    */
+    VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT = 0x00020000,
+    /** Allocation strategy that chooses first suitable free range for the
+    allocation.
+
+    "First" doesn't necessarily means the one with smallest offset in memory,
+    but rather the one that is easiest and fastest to find.
+    */
+    VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT = 0x00040000,
+
+    /** Allocation strategy that tries to minimize memory usage.
+    */
+    VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT = VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT,
+    /** Allocation strategy that tries to minimize allocation time.
+    */
+    VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT = VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT,
+    /** Allocation strategy that tries to minimize memory fragmentation.
+    */
+    VMA_ALLOCATION_CREATE_STRATEGY_MIN_FRAGMENTATION_BIT = VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT,
+
+    /** A bit mask to extract only `STRATEGY` bits from entire set of flags.
+    */
+    VMA_ALLOCATION_CREATE_STRATEGY_MASK =
+        VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT |
+        VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT |
+        VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT,
+
+    VMA_ALLOCATION_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VmaAllocationCreateFlagBits;
+typedef VkFlags VmaAllocationCreateFlags;
+
+typedef struct VmaAllocationCreateInfo
+{
+    /// Use #VmaAllocationCreateFlagBits enum.
+    VmaAllocationCreateFlags flags;
+    /** \brief Intended usage of memory.
+    
+    You can leave #VMA_MEMORY_USAGE_UNKNOWN if you specify memory requirements in other way. \n
+    If `pool` is not null, this member is ignored.
+    */
+    VmaMemoryUsage usage;
+    /** \brief Flags that must be set in a Memory Type chosen for an allocation.
+    
+    Leave 0 if you specify memory requirements in other way. \n
+    If `pool` is not null, this member is ignored.*/
+    VkMemoryPropertyFlags requiredFlags;
+    /** \brief Flags that preferably should be set in a memory type chosen for an allocation.
+    
+    Set to 0 if no additional flags are prefered. \n
+    If `pool` is not null, this member is ignored. */
+    VkMemoryPropertyFlags preferredFlags;
+    /** \brief Bitmask containing one bit set for every memory type acceptable for this allocation.
+
+    Value 0 is equivalent to `UINT32_MAX` - it means any memory type is accepted if
+    it meets other requirements specified by this structure, with no further
+    restrictions on memory type index. \n
+    If `pool` is not null, this member is ignored.
+    */
+    uint32_t memoryTypeBits;
+    /** \brief Pool that this allocation should be created in.
+
+    Leave `VK_NULL_HANDLE` to allocate from default pool. If not null, members:
+    `usage`, `requiredFlags`, `preferredFlags`, `memoryTypeBits` are ignored.
+    */
+    VmaPool pool;
+    /** \brief Custom general-purpose pointer that will be stored in #VmaAllocation, can be read as VmaAllocationInfo::pUserData and changed using vmaSetAllocationUserData().
+    
+    If #VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT is used, it must be either
+    null or pointer to a null-terminated string. The string will be then copied to
+    internal buffer, so it doesn't need to be valid after allocation call.
+    */
+    void* pUserData;
+} VmaAllocationCreateInfo;
+
+/**
+\brief Helps to find memoryTypeIndex, given memoryTypeBits and VmaAllocationCreateInfo.
+
+This algorithm tries to find a memory type that:
+
+- Is allowed by memoryTypeBits.
+- Contains all the flags from pAllocationCreateInfo->requiredFlags.
+- Matches intended usage.
+- Has as many flags from pAllocationCreateInfo->preferredFlags as possible.
+
+\return Returns VK_ERROR_FEATURE_NOT_PRESENT if not found. Receiving such result
+from this function or any other allocating function probably means that your
+device doesn't support any memory type with requested features for the specific
+type of resource you want to use it for. Please check parameters of your
+resource, like image layout (OPTIMAL versus LINEAR) or mip level count.
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndex(
+    VmaAllocator allocator,
+    uint32_t memoryTypeBits,
+    const VmaAllocationCreateInfo* pAllocationCreateInfo,
+    uint32_t* pMemoryTypeIndex);
+
+/**
+\brief Helps to find memoryTypeIndex, given VkBufferCreateInfo and VmaAllocationCreateInfo.
+
+It can be useful e.g. to determine value to be used as VmaPoolCreateInfo::memoryTypeIndex.
+It internally creates a temporary, dummy buffer that never has memory bound.
+It is just a convenience function, equivalent to calling:
+
+- `vkCreateBuffer`
+- `vkGetBufferMemoryRequirements`
+- `vmaFindMemoryTypeIndex`
+- `vkDestroyBuffer`
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndexForBufferInfo(
+    VmaAllocator allocator,
+    const VkBufferCreateInfo* pBufferCreateInfo,
+    const VmaAllocationCreateInfo* pAllocationCreateInfo,
+    uint32_t* pMemoryTypeIndex);
+
+/**
+\brief Helps to find memoryTypeIndex, given VkImageCreateInfo and VmaAllocationCreateInfo.
+
+It can be useful e.g. to determine value to be used as VmaPoolCreateInfo::memoryTypeIndex.
+It internally creates a temporary, dummy image that never has memory bound.
+It is just a convenience function, equivalent to calling:
+
+- `vkCreateImage`
+- `vkGetImageMemoryRequirements`
+- `vmaFindMemoryTypeIndex`
+- `vkDestroyImage`
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndexForImageInfo(
+    VmaAllocator allocator,
+    const VkImageCreateInfo* pImageCreateInfo,
+    const VmaAllocationCreateInfo* pAllocationCreateInfo,
+    uint32_t* pMemoryTypeIndex);
+
+/// Flags to be passed as VmaPoolCreateInfo::flags.
+typedef enum VmaPoolCreateFlagBits {
+    /** \brief Use this flag if you always allocate only buffers and linear images or only optimal images out of this pool and so Buffer-Image Granularity can be ignored.
+
+    This is an optional optimization flag.
+
+    If you always allocate using vmaCreateBuffer(), vmaCreateImage(),
+    vmaAllocateMemoryForBuffer(), then you don't need to use it because allocator
+    knows exact type of your allocations so it can handle Buffer-Image Granularity
+    in the optimal way.
+
+    If you also allocate using vmaAllocateMemoryForImage() or vmaAllocateMemory(),
+    exact type of such allocations is not known, so allocator must be conservative
+    in handling Buffer-Image Granularity, which can lead to suboptimal allocation
+    (wasted memory). In that case, if you can make sure you always allocate only
+    buffers and linear images or only optimal images out of this pool, use this flag
+    to make allocator disregard Buffer-Image Granularity and so make allocations
+    faster and more optimal.
+    */
+    VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT = 0x00000002,
+
+    /** \brief Enables alternative, linear allocation algorithm in this pool.
+
+    Specify this flag to enable linear allocation algorithm, which always creates
+    new allocations after last one and doesn't reuse space from allocations freed in
+    between. It trades memory consumption for simplified algorithm and data
+    structure, which has better performance and uses less memory for metadata.
+
+    By using this flag, you can achieve behavior of free-at-once, stack,
+    ring buffer, and double stack. For details, see documentation chapter
+    \ref linear_algorithm.
+
+    When using this flag, you must specify VmaPoolCreateInfo::maxBlockCount == 1 (or 0 for default).
+
+    For more details, see [Linear allocation algorithm](@ref linear_algorithm).
+    */
+    VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT = 0x00000004,
+
+    /** \brief Enables alternative, buddy allocation algorithm in this pool.
+
+    It operates on a tree of blocks, each having size that is a power of two and
+    a half of its parent's size. Comparing to default algorithm, this one provides
+    faster allocation and deallocation and decreased external fragmentation,
+    at the expense of more memory wasted (internal fragmentation).
+
+    For more details, see [Buddy allocation algorithm](@ref buddy_algorithm).
+    */
+    VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT = 0x00000008,
+
+    /** Bit mask to extract only `ALGORITHM` bits from entire set of flags.
+    */
+    VMA_POOL_CREATE_ALGORITHM_MASK =
+        VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT |
+        VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT,
+
+    VMA_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VmaPoolCreateFlagBits;
+typedef VkFlags VmaPoolCreateFlags;
+
+/** \brief Describes parameter of created #VmaPool.
+*/
+typedef struct VmaPoolCreateInfo {
+    /** \brief Vulkan memory type index to allocate this pool from.
+    */
+    uint32_t memoryTypeIndex;
+    /** \brief Use combination of #VmaPoolCreateFlagBits.
+    */
+    VmaPoolCreateFlags flags;
+    /** \brief Size of a single `VkDeviceMemory` block to be allocated as part of this pool, in bytes. Optional.
+
+    Specify nonzero to set explicit, constant size of memory blocks used by this
+    pool.
+
+    Leave 0 to use default and let the library manage block sizes automatically.
+    Sizes of particular blocks may vary.
+    */
+    VkDeviceSize blockSize;
+    /** \brief Minimum number of blocks to be always allocated in this pool, even if they stay empty.
+
+    Set to 0 to have no preallocated blocks and allow the pool be completely empty.
+    */
+    size_t minBlockCount;
+    /** \brief Maximum number of blocks that can be allocated in this pool. Optional.
+
+    Set to 0 to use default, which is `SIZE_MAX`, which means no limit.
+    
+    Set to same value as VmaPoolCreateInfo::minBlockCount to have fixed amount of memory allocated
+    throughout whole lifetime of this pool.
+    */
+    size_t maxBlockCount;
+    /** \brief Maximum number of additional frames that are in use at the same time as current frame.
+
+    This value is used only when you make allocations with
+    #VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT flag. Such allocation cannot become
+    lost if allocation.lastUseFrameIndex >= allocator.currentFrameIndex - frameInUseCount.
+
+    For example, if you double-buffer your command buffers, so resources used for
+    rendering in previous frame may still be in use by the GPU at the moment you
+    allocate resources needed for the current frame, set this value to 1.
+
+    If you want to allow any allocations other than used in the current frame to
+    become lost, set this value to 0.
+    */
+    uint32_t frameInUseCount;
+} VmaPoolCreateInfo;
+
+/** \brief Describes parameter of existing #VmaPool.
+*/
+typedef struct VmaPoolStats {
+    /** \brief Total amount of `VkDeviceMemory` allocated from Vulkan for this pool, in bytes.
+    */
+    VkDeviceSize size;
+    /** \brief Total number of bytes in the pool not used by any #VmaAllocation.
+    */
+    VkDeviceSize unusedSize;
+    /** \brief Number of #VmaAllocation objects created from this pool that were not destroyed or lost.
+    */
+    size_t allocationCount;
+    /** \brief Number of continuous memory ranges in the pool not used by any #VmaAllocation.
+    */
+    size_t unusedRangeCount;
+    /** \brief Size of the largest continuous free memory region available for new allocation.
+
+    Making a new allocation of that size is not guaranteed to succeed because of
+    possible additional margin required to respect alignment and buffer/image
+    granularity.
+    */
+    VkDeviceSize unusedRangeSizeMax;
+    /** \brief Number of `VkDeviceMemory` blocks allocated for this pool.
+    */
+    size_t blockCount;
+} VmaPoolStats;
+
+/** \brief Allocates Vulkan device memory and creates #VmaPool object.
+
+@param allocator Allocator object.
+@param pCreateInfo Parameters of pool to create.
+@param[out] pPool Handle to created pool.
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreatePool(
+	VmaAllocator allocator,
+	const VmaPoolCreateInfo* pCreateInfo,
+	VmaPool* pPool);
+
+/** \brief Destroys #VmaPool object and frees Vulkan device memory.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaDestroyPool(
+    VmaAllocator allocator,
+    VmaPool pool);
+
+/** \brief Retrieves statistics of existing #VmaPool object.
+
+@param allocator Allocator object.
+@param pool Pool object.
+@param[out] pPoolStats Statistics of specified pool.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaGetPoolStats(
+    VmaAllocator allocator,
+    VmaPool pool,
+    VmaPoolStats* pPoolStats);
+
+/** \brief Marks all allocations in given pool as lost if they are not used in current frame or VmaPoolCreateInfo::frameInUseCount back from now.
+
+@param allocator Allocator object.
+@param pool Pool.
+@param[out] pLostAllocationCount Number of allocations marked as lost. Optional - pass null if you don't need this information.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaMakePoolAllocationsLost(
+    VmaAllocator allocator,
+    VmaPool pool,
+    size_t* pLostAllocationCount);
+
+/** \brief Checks magic number in margins around all allocations in given memory pool in search for corruptions.
+
+Corruption detection is enabled only when `VMA_DEBUG_DETECT_CORRUPTION` macro is defined to nonzero,
+`VMA_DEBUG_MARGIN` is defined to nonzero and the pool is created in memory type that is
+`HOST_VISIBLE` and `HOST_COHERENT`. For more information, see [Corruption detection](@ref debugging_memory_usage_corruption_detection).
+
+Possible return values:
+
+- `VK_ERROR_FEATURE_NOT_PRESENT` - corruption detection is not enabled for specified pool.
+- `VK_SUCCESS` - corruption detection has been performed and succeeded.
+- `VK_ERROR_VALIDATION_FAILED_EXT` - corruption detection has been performed and found memory corruptions around one of the allocations.
+  `VMA_ASSERT` is also fired in that case.
+- Other value: Error returned by Vulkan, e.g. memory mapping failure.
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaCheckPoolCorruption(VmaAllocator allocator, VmaPool pool);
+
+/** \brief Retrieves name of a custom pool.
+
+After the call `ppName` is either null or points to an internally-owned null-terminated string
+containing name of the pool that was previously set. The pointer becomes invalid when the pool is
+destroyed or its name is changed using vmaSetPoolName().
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaGetPoolName(
+    VmaAllocator allocator,
+    VmaPool pool,
+    const char** ppName);
+
+/** \brief Sets name of a custom pool.
+
+`pName` can be either null or pointer to a null-terminated string with new name for the pool.
+Function makes internal copy of the string, so it can be changed or freed immediately after this call.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaSetPoolName(
+    VmaAllocator allocator,
+    VmaPool pool,
+    const char* pName);
+
+/** \struct VmaAllocation
+\brief Represents single memory allocation.
+
+It may be either dedicated block of `VkDeviceMemory` or a specific region of a bigger block of this type
+plus unique offset.
+
+There are multiple ways to create such object.
+You need to fill structure VmaAllocationCreateInfo.
+For more information see [Choosing memory type](@ref choosing_memory_type).
+
+Although the library provides convenience functions that create Vulkan buffer or image,
+allocate memory for it and bind them together,
+binding of the allocation to a buffer or an image is out of scope of the allocation itself.
+Allocation object can exist without buffer/image bound,
+binding can be done manually by the user, and destruction of it can be done
+independently of destruction of the allocation.
+
+The object also remembers its size and some other information.
+To retrieve this information, use function vmaGetAllocationInfo() and inspect
+returned structure VmaAllocationInfo.
+
+Some kinds allocations can be in lost state.
+For more information, see [Lost allocations](@ref lost_allocations).
+*/
+VK_DEFINE_HANDLE(VmaAllocation)
+
+/** \brief Parameters of #VmaAllocation objects, that can be retrieved using function vmaGetAllocationInfo().
+*/
+typedef struct VmaAllocationInfo {
+    /** \brief Memory type index that this allocation was allocated from.
+    
+    It never changes.
+    */
+    uint32_t memoryType;
+    /** \brief Handle to Vulkan memory object.
+
+    Same memory object can be shared by multiple allocations.
+    
+    It can change after call to vmaDefragment() if this allocation is passed to the function, or if allocation is lost.
+
+    If the allocation is lost, it is equal to `VK_NULL_HANDLE`.
+    */
+    VkDeviceMemory deviceMemory;
+    /** \brief Offset into deviceMemory object to the beginning of this allocation, in bytes. (deviceMemory, offset) pair is unique to this allocation.
+
+    It can change after call to vmaDefragment() if this allocation is passed to the function, or if allocation is lost.
+    */
+    VkDeviceSize offset;
+    /** \brief Size of this allocation, in bytes.
+
+    It never changes, unless allocation is lost.
+    */
+    VkDeviceSize size;
+    /** \brief Pointer to the beginning of this allocation as mapped data.
+
+    If the allocation hasn't been mapped using vmaMapMemory() and hasn't been
+    created with #VMA_ALLOCATION_CREATE_MAPPED_BIT flag, this value null.
+
+    It can change after call to vmaMapMemory(), vmaUnmapMemory().
+    It can also change after call to vmaDefragment() if this allocation is passed to the function.
+    */
+    void* pMappedData;
+    /** \brief Custom general-purpose pointer that was passed as VmaAllocationCreateInfo::pUserData or set using vmaSetAllocationUserData().
+
+    It can change after call to vmaSetAllocationUserData() for this allocation.
+    */
+    void* pUserData;
+} VmaAllocationInfo;
+
+/** \brief General purpose memory allocation.
+
+@param[out] pAllocation Handle to allocated memory.
+@param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo().
+
+You should free the memory using vmaFreeMemory() or vmaFreeMemoryPages().
+
+It is recommended to use vmaAllocateMemoryForBuffer(), vmaAllocateMemoryForImage(),
+vmaCreateBuffer(), vmaCreateImage() instead whenever possible.
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemory(
+    VmaAllocator allocator,
+    const VkMemoryRequirements* pVkMemoryRequirements,
+    const VmaAllocationCreateInfo* pCreateInfo,
+    VmaAllocation* pAllocation,
+    VmaAllocationInfo* pAllocationInfo);
+
+/** \brief General purpose memory allocation for multiple allocation objects at once.
+
+@param allocator Allocator object.
+@param pVkMemoryRequirements Memory requirements for each allocation.
+@param pCreateInfo Creation parameters for each alloction.
+@param allocationCount Number of allocations to make.
+@param[out] pAllocations Pointer to array that will be filled with handles to created allocations.
+@param[out] pAllocationInfo Optional. Pointer to array that will be filled with parameters of created allocations.
+
+You should free the memory using vmaFreeMemory() or vmaFreeMemoryPages().
+
+Word "pages" is just a suggestion to use this function to allocate pieces of memory needed for sparse binding.
+It is just a general purpose allocation function able to make multiple allocations at once.
+It may be internally optimized to be more efficient than calling vmaAllocateMemory() `allocationCount` times.
+
+All allocations are made using same parameters. All of them are created out of the same memory pool and type.
+If any allocation fails, all allocations already made within this function call are also freed, so that when
+returned result is not `VK_SUCCESS`, `pAllocation` array is always entirely filled with `VK_NULL_HANDLE`.
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryPages(
+    VmaAllocator allocator,
+    const VkMemoryRequirements* pVkMemoryRequirements,
+    const VmaAllocationCreateInfo* pCreateInfo,
+    size_t allocationCount,
+    VmaAllocation* pAllocations,
+    VmaAllocationInfo* pAllocationInfo);
+
+/**
+@param[out] pAllocation Handle to allocated memory.
+@param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo().
+
+You should free the memory using vmaFreeMemory().
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryForBuffer(
+    VmaAllocator allocator,
+    VkBuffer buffer,
+    const VmaAllocationCreateInfo* pCreateInfo,
+    VmaAllocation* pAllocation,
+    VmaAllocationInfo* pAllocationInfo);
+
+/// Function similar to vmaAllocateMemoryForBuffer().
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryForImage(
+    VmaAllocator allocator,
+    VkImage image,
+    const VmaAllocationCreateInfo* pCreateInfo,
+    VmaAllocation* pAllocation,
+    VmaAllocationInfo* pAllocationInfo);
+
+/** \brief Frees memory previously allocated using vmaAllocateMemory(), vmaAllocateMemoryForBuffer(), or vmaAllocateMemoryForImage().
+
+Passing `VK_NULL_HANDLE` as `allocation` is valid. Such function call is just skipped.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaFreeMemory(
+    VmaAllocator allocator,
+    VmaAllocation allocation);
+
+/** \brief Frees memory and destroys multiple allocations.
+
+Word "pages" is just a suggestion to use this function to free pieces of memory used for sparse binding.
+It is just a general purpose function to free memory and destroy allocations made using e.g. vmaAllocateMemory(),
+vmaAllocateMemoryPages() and other functions.
+It may be internally optimized to be more efficient than calling vmaFreeMemory() `allocationCount` times.
+
+Allocations in `pAllocations` array can come from any memory pools and types.
+Passing `VK_NULL_HANDLE` as elements of `pAllocations` array is valid. Such entries are just skipped.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaFreeMemoryPages(
+    VmaAllocator allocator,
+    size_t allocationCount,
+    VmaAllocation* pAllocations);
+
+/** \brief Deprecated.
+
+\deprecated
+In version 2.2.0 it used to try to change allocation's size without moving or reallocating it.
+In current version it returns `VK_SUCCESS` only if `newSize` equals current allocation's size.
+Otherwise returns `VK_ERROR_OUT_OF_POOL_MEMORY`, indicating that allocation's size could not be changed.
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaResizeAllocation(
+    VmaAllocator allocator,
+    VmaAllocation allocation,
+    VkDeviceSize newSize);
+
+/** \brief Returns current information about specified allocation and atomically marks it as used in current frame.
+
+Current paramters of given allocation are returned in `pAllocationInfo`.
+
+This function also atomically "touches" allocation - marks it as used in current frame,
+just like vmaTouchAllocation().
+If the allocation is in lost state, `pAllocationInfo->deviceMemory == VK_NULL_HANDLE`.
+
+Although this function uses atomics and doesn't lock any mutex, so it should be quite efficient,
+you can avoid calling it too often.
+
+- You can retrieve same VmaAllocationInfo structure while creating your resource, from function
+  vmaCreateBuffer(), vmaCreateImage(). You can remember it if you are sure parameters don't change
+  (e.g. due to defragmentation or allocation becoming lost).
+- If you just want to check if allocation is not lost, vmaTouchAllocation() will work faster.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocationInfo(
+    VmaAllocator allocator,
+    VmaAllocation allocation,
+    VmaAllocationInfo* pAllocationInfo);
+
+/** \brief Returns `VK_TRUE` if allocation is not lost and atomically marks it as used in current frame.
+
+If the allocation has been created with #VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT flag,
+this function returns `VK_TRUE` if it's not in lost state, so it can still be used.
+It then also atomically "touches" the allocation - marks it as used in current frame,
+so that you can be sure it won't become lost in current frame or next `frameInUseCount` frames.
+
+If the allocation is in lost state, the function returns `VK_FALSE`.
+Memory of such allocation, as well as buffer or image bound to it, should not be used.
+Lost allocation and the buffer/image still need to be destroyed.
+
+If the allocation has been created without #VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT flag,
+this function always returns `VK_TRUE`.
+*/
+VMA_CALL_PRE VkBool32 VMA_CALL_POST vmaTouchAllocation(
+    VmaAllocator allocator,
+    VmaAllocation allocation);
+
+/** \brief Sets pUserData in given allocation to new value.
+
+If the allocation was created with VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT,
+pUserData must be either null, or pointer to a null-terminated string. The function
+makes local copy of the string and sets it as allocation's `pUserData`. String
+passed as pUserData doesn't need to be valid for whole lifetime of the allocation -
+you can free it after this call. String previously pointed by allocation's
+pUserData is freed from memory.
+
+If the flag was not used, the value of pointer `pUserData` is just copied to
+allocation's `pUserData`. It is opaque, so you can use it however you want - e.g.
+as a pointer, ordinal number or some handle to you own data.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaSetAllocationUserData(
+    VmaAllocator allocator,
+    VmaAllocation allocation,
+    void* pUserData);
+
+/** \brief Creates new allocation that is in lost state from the beginning.
+
+It can be useful if you need a dummy, non-null allocation.
+
+You still need to destroy created object using vmaFreeMemory().
+
+Returned allocation is not tied to any specific memory pool or memory type and
+not bound to any image or buffer. It has size = 0. It cannot be turned into
+a real, non-empty allocation.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaCreateLostAllocation(
+    VmaAllocator allocator,
+    VmaAllocation* pAllocation);
+
+/** \brief Maps memory represented by given allocation and returns pointer to it.
+
+Maps memory represented by given allocation to make it accessible to CPU code.
+When succeeded, `*ppData` contains pointer to first byte of this memory.
+If the allocation is part of bigger `VkDeviceMemory` block, the pointer is
+correctly offseted to the beginning of region assigned to this particular
+allocation.
+
+Mapping is internally reference-counted and synchronized, so despite raw Vulkan
+function `vkMapMemory()` cannot be used to map same block of `VkDeviceMemory`
+multiple times simultaneously, it is safe to call this function on allocations
+assigned to the same memory block. Actual Vulkan memory will be mapped on first
+mapping and unmapped on last unmapping.
+
+If the function succeeded, you must call vmaUnmapMemory() to unmap the
+allocation when mapping is no longer needed or before freeing the allocation, at
+the latest.
+
+It also safe to call this function multiple times on the same allocation. You
+must call vmaUnmapMemory() same number of times as you called vmaMapMemory().
+
+It is also safe to call this function on allocation created with
+#VMA_ALLOCATION_CREATE_MAPPED_BIT flag. Its memory stays mapped all the time.
+You must still call vmaUnmapMemory() same number of times as you called
+vmaMapMemory(). You must not call vmaUnmapMemory() additional time to free the
+"0-th" mapping made automatically due to #VMA_ALLOCATION_CREATE_MAPPED_BIT flag.
+
+This function fails when used on allocation made in memory type that is not
+`HOST_VISIBLE`.
+
+This function always fails when called for allocation that was created with
+#VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT flag. Such allocations cannot be
+mapped.
+
+This function doesn't automatically flush or invalidate caches.
+If the allocation is made from a memory types that is not `HOST_COHERENT`,
+you also need to use vmaInvalidateAllocation() / vmaFlushAllocation(), as required by Vulkan specification.
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaMapMemory(
+    VmaAllocator allocator,
+    VmaAllocation allocation,
+    void** ppData);
+
+/** \brief Unmaps memory represented by given allocation, mapped previously using vmaMapMemory().
+
+For details, see description of vmaMapMemory().
+
+This function doesn't automatically flush or invalidate caches.
+If the allocation is made from a memory types that is not `HOST_COHERENT`,
+you also need to use vmaInvalidateAllocation() / vmaFlushAllocation(), as required by Vulkan specification.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaUnmapMemory(
+    VmaAllocator allocator,
+    VmaAllocation allocation);
+
+/** \brief Flushes memory of given allocation.
+
+Calls `vkFlushMappedMemoryRanges()` for memory associated with given range of given allocation.
+It needs to be called after writing to a mapped memory for memory types that are not `HOST_COHERENT`.
+Unmap operation doesn't do that automatically.
+
+- `offset` must be relative to the beginning of allocation.
+- `size` can be `VK_WHOLE_SIZE`. It means all memory from `offset` the the end of given allocation.
+- `offset` and `size` don't have to be aligned.
+  They are internally rounded down/up to multiply of `nonCoherentAtomSize`.
+- If `size` is 0, this call is ignored.
+- If memory type that the `allocation` belongs to is not `HOST_VISIBLE` or it is `HOST_COHERENT`,
+  this call is ignored.
+
+Warning! `offset` and `size` are relative to the contents of given `allocation`.
+If you mean whole allocation, you can pass 0 and `VK_WHOLE_SIZE`, respectively.
+Do not pass allocation's offset as `offset`!!!
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaFlushAllocation(VmaAllocator allocator, VmaAllocation allocation, VkDeviceSize offset, VkDeviceSize size);
+
+/** \brief Invalidates memory of given allocation.
+
+Calls `vkInvalidateMappedMemoryRanges()` for memory associated with given range of given allocation.
+It needs to be called before reading from a mapped memory for memory types that are not `HOST_COHERENT`.
+Map operation doesn't do that automatically.
+
+- `offset` must be relative to the beginning of allocation.
+- `size` can be `VK_WHOLE_SIZE`. It means all memory from `offset` the the end of given allocation.
+- `offset` and `size` don't have to be aligned.
+  They are internally rounded down/up to multiply of `nonCoherentAtomSize`.
+- If `size` is 0, this call is ignored.
+- If memory type that the `allocation` belongs to is not `HOST_VISIBLE` or it is `HOST_COHERENT`,
+  this call is ignored.
+
+Warning! `offset` and `size` are relative to the contents of given `allocation`.
+If you mean whole allocation, you can pass 0 and `VK_WHOLE_SIZE`, respectively.
+Do not pass allocation's offset as `offset`!!!
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaInvalidateAllocation(VmaAllocator allocator, VmaAllocation allocation, VkDeviceSize offset, VkDeviceSize size);
+
+/** \brief Checks magic number in margins around all allocations in given memory types (in both default and custom pools) in search for corruptions.
+
+@param memoryTypeBits Bit mask, where each bit set means that a memory type with that index should be checked.
+
+Corruption detection is enabled only when `VMA_DEBUG_DETECT_CORRUPTION` macro is defined to nonzero,
+`VMA_DEBUG_MARGIN` is defined to nonzero and only for memory types that are
+`HOST_VISIBLE` and `HOST_COHERENT`. For more information, see [Corruption detection](@ref debugging_memory_usage_corruption_detection).
+
+Possible return values:
+
+- `VK_ERROR_FEATURE_NOT_PRESENT` - corruption detection is not enabled for any of specified memory types.
+- `VK_SUCCESS` - corruption detection has been performed and succeeded.
+- `VK_ERROR_VALIDATION_FAILED_EXT` - corruption detection has been performed and found memory corruptions around one of the allocations.
+  `VMA_ASSERT` is also fired in that case.
+- Other value: Error returned by Vulkan, e.g. memory mapping failure.
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaCheckCorruption(VmaAllocator allocator, uint32_t memoryTypeBits);
+
+/** \struct VmaDefragmentationContext
+\brief Represents Opaque object that represents started defragmentation process.
+
+Fill structure #VmaDefragmentationInfo2 and call function vmaDefragmentationBegin() to create it.
+Call function vmaDefragmentationEnd() to destroy it.
+*/
+VK_DEFINE_HANDLE(VmaDefragmentationContext)
+
+/// Flags to be used in vmaDefragmentationBegin(). None at the moment. Reserved for future use.
+typedef enum VmaDefragmentationFlagBits {
+    VMA_DEFRAGMENTATION_FLAG_INCREMENTAL = 0x1,
+    VMA_DEFRAGMENTATION_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VmaDefragmentationFlagBits;
+typedef VkFlags VmaDefragmentationFlags;
+
+/** \brief Parameters for defragmentation.
+
+To be used with function vmaDefragmentationBegin().
+*/
+typedef struct VmaDefragmentationInfo2 {
+    /** \brief Reserved for future use. Should be 0.
+    */
+    VmaDefragmentationFlags flags;
+    /** \brief Number of allocations in `pAllocations` array.
+    */
+    uint32_t allocationCount;
+    /** \brief Pointer to array of allocations that can be defragmented.
+
+    The array should have `allocationCount` elements.
+    The array should not contain nulls.
+    Elements in the array should be unique - same allocation cannot occur twice.
+    It is safe to pass allocations that are in the lost state - they are ignored.
+    All allocations not present in this array are considered non-moveable during this defragmentation.
+    */
+    VmaAllocation* pAllocations;
+    /** \brief Optional, output. Pointer to array that will be filled with information whether the allocation at certain index has been changed during defragmentation.
+
+    The array should have `allocationCount` elements.
+    You can pass null if you are not interested in this information.
+    */
+    VkBool32* pAllocationsChanged;
+    /** \brief Numer of pools in `pPools` array.
+    */
+    uint32_t poolCount;
+    /** \brief Either null or pointer to array of pools to be defragmented.
+
+    All the allocations in the specified pools can be moved during defragmentation
+    and there is no way to check if they were really moved as in `pAllocationsChanged`,
+    so you must query all the allocations in all these pools for new `VkDeviceMemory`
+    and offset using vmaGetAllocationInfo() if you might need to recreate buffers
+    and images bound to them.
+
+    The array should have `poolCount` elements.
+    The array should not contain nulls.
+    Elements in the array should be unique - same pool cannot occur twice.
+
+    Using this array is equivalent to specifying all allocations from the pools in `pAllocations`.
+    It might be more efficient.
+    */
+    VmaPool* pPools;
+    /** \brief Maximum total numbers of bytes that can be copied while moving allocations to different places using transfers on CPU side, like `memcpy()`, `memmove()`.
+    
+    `VK_WHOLE_SIZE` means no limit.
+    */
+    VkDeviceSize maxCpuBytesToMove;
+    /** \brief Maximum number of allocations that can be moved to a different place using transfers on CPU side, like `memcpy()`, `memmove()`.
+
+    `UINT32_MAX` means no limit.
+    */
+    uint32_t maxCpuAllocationsToMove;
+    /** \brief Maximum total numbers of bytes that can be copied while moving allocations to different places using transfers on GPU side, posted to `commandBuffer`.
+    
+    `VK_WHOLE_SIZE` means no limit.
+    */
+    VkDeviceSize maxGpuBytesToMove;
+    /** \brief Maximum number of allocations that can be moved to a different place using transfers on GPU side, posted to `commandBuffer`.
+
+    `UINT32_MAX` means no limit.
+    */
+    uint32_t maxGpuAllocationsToMove;
+    /** \brief Optional. Command buffer where GPU copy commands will be posted.
+
+    If not null, it must be a valid command buffer handle that supports Transfer queue type.
+    It must be in the recording state and outside of a render pass instance.
+    You need to submit it and make sure it finished execution before calling vmaDefragmentationEnd().
+
+    Passing null means that only CPU defragmentation will be performed.
+    */
+    VkCommandBuffer commandBuffer;
+} VmaDefragmentationInfo2;
+
+typedef struct VmaDefragmentationPassMoveInfo {
+    VmaAllocation allocation;
+    VkDeviceMemory memory;
+    VkDeviceSize offset;
+} VmaDefragmentationPassMoveInfo;
+
+/** \brief Parameters for incremental defragmentation steps.
+
+To be used with function vmaBeginDefragmentationPass().
+*/
+typedef struct VmaDefragmentationPassInfo {
+    uint32_t moveCount;
+    VmaDefragmentationPassMoveInfo* pMoves;
+} VmaDefragmentationPassInfo;
+
+/** \brief Deprecated. Optional configuration parameters to be passed to function vmaDefragment().
+
+\deprecated This is a part of the old interface. It is recommended to use structure #VmaDefragmentationInfo2 and function vmaDefragmentationBegin() instead.
+*/
+typedef struct VmaDefragmentationInfo {
+    /** \brief Maximum total numbers of bytes that can be copied while moving allocations to different places.
+    
+    Default is `VK_WHOLE_SIZE`, which means no limit.
+    */
+    VkDeviceSize maxBytesToMove;
+    /** \brief Maximum number of allocations that can be moved to different place.
+
+    Default is `UINT32_MAX`, which means no limit.
+    */
+    uint32_t maxAllocationsToMove;
+} VmaDefragmentationInfo;
+
+/** \brief Statistics returned by function vmaDefragment(). */
+typedef struct VmaDefragmentationStats {
+    /// Total number of bytes that have been copied while moving allocations to different places.
+    VkDeviceSize bytesMoved;
+    /// Total number of bytes that have been released to the system by freeing empty `VkDeviceMemory` objects.
+    VkDeviceSize bytesFreed;
+    /// Number of allocations that have been moved to different places.
+    uint32_t allocationsMoved;
+    /// Number of empty `VkDeviceMemory` objects that have been released to the system.
+    uint32_t deviceMemoryBlocksFreed;
+} VmaDefragmentationStats;
+
+/** \brief Begins defragmentation process.
+
+@param allocator Allocator object.
+@param pInfo Structure filled with parameters of defragmentation.
+@param[out] pStats Optional. Statistics of defragmentation. You can pass null if you are not interested in this information.
+@param[out] pContext Context object that must be passed to vmaDefragmentationEnd() to finish defragmentation.
+@return `VK_SUCCESS` and `*pContext == null` if defragmentation finished within this function call. `VK_NOT_READY` and `*pContext != null` if defragmentation has been started and you need to call vmaDefragmentationEnd() to finish it. Negative value in case of error.
+
+Use this function instead of old, deprecated vmaDefragment().
+
+Warning! Between the call to vmaDefragmentationBegin() and vmaDefragmentationEnd():
+
+- You should not use any of allocations passed as `pInfo->pAllocations` or
+  any allocations that belong to pools passed as `pInfo->pPools`,
+  including calling vmaGetAllocationInfo(), vmaTouchAllocation(), or access
+  their data.
+- Some mutexes protecting internal data structures may be locked, so trying to
+  make or free any allocations, bind buffers or images, map memory, or launch
+  another simultaneous defragmentation in between may cause stall (when done on
+  another thread) or deadlock (when done on the same thread), unless you are
+  100% sure that defragmented allocations are in different pools.
+- Information returned via `pStats` and `pInfo->pAllocationsChanged` are undefined.
+  They become valid after call to vmaDefragmentationEnd().
+- If `pInfo->commandBuffer` is not null, you must submit that command buffer
+  and make sure it finished execution before calling vmaDefragmentationEnd().
+
+For more information and important limitations regarding defragmentation, see documentation chapter:
+[Defragmentation](@ref defragmentation).
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaDefragmentationBegin(
+    VmaAllocator allocator,
+    const VmaDefragmentationInfo2* pInfo,
+    VmaDefragmentationStats* pStats,
+    VmaDefragmentationContext *pContext);
+
+/** \brief Ends defragmentation process.
+
+Use this function to finish defragmentation started by vmaDefragmentationBegin().
+It is safe to pass `context == null`. The function then does nothing.
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaDefragmentationEnd(
+    VmaAllocator allocator,
+    VmaDefragmentationContext context);
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaBeginDefragmentationPass(
+    VmaAllocator allocator,
+    VmaDefragmentationContext context,
+    VmaDefragmentationPassInfo* pInfo
+);
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaEndDefragmentationPass(
+    VmaAllocator allocator,
+    VmaDefragmentationContext context
+);
+
+/** \brief Deprecated. Compacts memory by moving allocations.
+
+@param pAllocations Array of allocations that can be moved during this compation.
+@param allocationCount Number of elements in pAllocations and pAllocationsChanged arrays.
+@param[out] pAllocationsChanged Array of boolean values that will indicate whether matching allocation in pAllocations array has been moved. This parameter is optional. Pass null if you don't need this information.
+@param pDefragmentationInfo Configuration parameters. Optional - pass null to use default values.
+@param[out] pDefragmentationStats Statistics returned by the function. Optional - pass null if you don't need this information.
+@return `VK_SUCCESS` if completed, negative error code in case of error.
+
+\deprecated This is a part of the old interface. It is recommended to use structure #VmaDefragmentationInfo2 and function vmaDefragmentationBegin() instead.
+
+This function works by moving allocations to different places (different
+`VkDeviceMemory` objects and/or different offsets) in order to optimize memory
+usage. Only allocations that are in `pAllocations` array can be moved. All other
+allocations are considered nonmovable in this call. Basic rules:
+
+- Only allocations made in memory types that have
+  `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT` and `VK_MEMORY_PROPERTY_HOST_COHERENT_BIT`
+  flags can be compacted. You may pass other allocations but it makes no sense -
+  these will never be moved.
+- Custom pools created with #VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT or
+  #VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT flag are not defragmented. Allocations
+  passed to this function that come from such pools are ignored.
+- Allocations created with #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT or
+  created as dedicated allocations for any other reason are also ignored.
+- Both allocations made with or without #VMA_ALLOCATION_CREATE_MAPPED_BIT
+  flag can be compacted. If not persistently mapped, memory will be mapped
+  temporarily inside this function if needed.
+- You must not pass same #VmaAllocation object multiple times in `pAllocations` array.
+
+The function also frees empty `VkDeviceMemory` blocks.
+
+Warning: This function may be time-consuming, so you shouldn't call it too often
+(like after every resource creation/destruction).
+You can call it on special occasions (like when reloading a game level or
+when you just destroyed a lot of objects). Calling it every frame may be OK, but
+you should measure that on your platform.
+
+For more information, see [Defragmentation](@ref defragmentation) chapter.
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaDefragment(
+    VmaAllocator allocator,
+    VmaAllocation* pAllocations,
+    size_t allocationCount,
+    VkBool32* pAllocationsChanged,
+    const VmaDefragmentationInfo *pDefragmentationInfo,
+    VmaDefragmentationStats* pDefragmentationStats);
+
+/** \brief Binds buffer to allocation.
+
+Binds specified buffer to region of memory represented by specified allocation.
+Gets `VkDeviceMemory` handle and offset from the allocation.
+If you want to create a buffer, allocate memory for it and bind them together separately,
+you should use this function for binding instead of standard `vkBindBufferMemory()`,
+because it ensures proper synchronization so that when a `VkDeviceMemory` object is used by multiple
+allocations, calls to `vkBind*Memory()` or `vkMapMemory()` won't happen from multiple threads simultaneously
+(which is illegal in Vulkan).
+
+It is recommended to use function vmaCreateBuffer() instead of this one.
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindBufferMemory(
+    VmaAllocator allocator,
+    VmaAllocation allocation,
+    VkBuffer buffer);
+
+/** \brief Binds buffer to allocation with additional parameters.
+
+@param allocationLocalOffset Additional offset to be added while binding, relative to the beginnig of the `allocation`. Normally it should be 0.
+@param pNext A chain of structures to be attached to `VkBindBufferMemoryInfoKHR` structure used internally. Normally it should be null.
+
+This function is similar to vmaBindBufferMemory(), but it provides additional parameters.
+
+If `pNext` is not null, #VmaAllocator object must have been created with #VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT flag
+or with VmaAllocatorCreateInfo::vulkanApiVersion `== VK_API_VERSION_1_1`. Otherwise the call fails.
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindBufferMemory2(
+    VmaAllocator allocator,
+    VmaAllocation allocation,
+    VkDeviceSize allocationLocalOffset,
+    VkBuffer buffer,
+    const void* pNext);
+
+/** \brief Binds image to allocation.
+
+Binds specified image to region of memory represented by specified allocation.
+Gets `VkDeviceMemory` handle and offset from the allocation.
+If you want to create an image, allocate memory for it and bind them together separately,
+you should use this function for binding instead of standard `vkBindImageMemory()`,
+because it ensures proper synchronization so that when a `VkDeviceMemory` object is used by multiple
+allocations, calls to `vkBind*Memory()` or `vkMapMemory()` won't happen from multiple threads simultaneously
+(which is illegal in Vulkan).
+
+It is recommended to use function vmaCreateImage() instead of this one.
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindImageMemory(
+    VmaAllocator allocator,
+    VmaAllocation allocation,
+    VkImage image);
+
+/** \brief Binds image to allocation with additional parameters.
+
+@param allocationLocalOffset Additional offset to be added while binding, relative to the beginnig of the `allocation`. Normally it should be 0.
+@param pNext A chain of structures to be attached to `VkBindImageMemoryInfoKHR` structure used internally. Normally it should be null.
+
+This function is similar to vmaBindImageMemory(), but it provides additional parameters.
+
+If `pNext` is not null, #VmaAllocator object must have been created with #VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT flag
+or with VmaAllocatorCreateInfo::vulkanApiVersion `== VK_API_VERSION_1_1`. Otherwise the call fails.
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindImageMemory2(
+    VmaAllocator allocator,
+    VmaAllocation allocation,
+    VkDeviceSize allocationLocalOffset,
+    VkImage image,
+    const void* pNext);
+
+/**
+@param[out] pBuffer Buffer that was created.
+@param[out] pAllocation Allocation that was created.
+@param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo().
+
+This function automatically:
+
+-# Creates buffer.
+-# Allocates appropriate memory for it.
+-# Binds the buffer with the memory.
+
+If any of these operations fail, buffer and allocation are not created,
+returned value is negative error code, *pBuffer and *pAllocation are null.
+
+If the function succeeded, you must destroy both buffer and allocation when you
+no longer need them using either convenience function vmaDestroyBuffer() or
+separately, using `vkDestroyBuffer()` and vmaFreeMemory().
+
+If VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT flag was used,
+VK_KHR_dedicated_allocation extension is used internally to query driver whether
+it requires or prefers the new buffer to have dedicated allocation. If yes,
+and if dedicated allocation is possible (VmaAllocationCreateInfo::pool is null
+and VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT is not used), it creates dedicated
+allocation for this buffer, just like when using
+VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT.
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateBuffer(
+    VmaAllocator allocator,
+    const VkBufferCreateInfo* pBufferCreateInfo,
+    const VmaAllocationCreateInfo* pAllocationCreateInfo,
+    VkBuffer* pBuffer,
+    VmaAllocation* pAllocation,
+    VmaAllocationInfo* pAllocationInfo);
+
+/** \brief Destroys Vulkan buffer and frees allocated memory.
+
+This is just a convenience function equivalent to:
+
+\code
+vkDestroyBuffer(device, buffer, allocationCallbacks);
+vmaFreeMemory(allocator, allocation);
+\endcode
+
+It it safe to pass null as buffer and/or allocation.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaDestroyBuffer(
+    VmaAllocator allocator,
+    VkBuffer buffer,
+    VmaAllocation allocation);
+
+/// Function similar to vmaCreateBuffer().
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateImage(
+    VmaAllocator allocator,
+    const VkImageCreateInfo* pImageCreateInfo,
+    const VmaAllocationCreateInfo* pAllocationCreateInfo,
+    VkImage* pImage,
+    VmaAllocation* pAllocation,
+    VmaAllocationInfo* pAllocationInfo);
+
+/** \brief Destroys Vulkan image and frees allocated memory.
+
+This is just a convenience function equivalent to:
+
+\code
+vkDestroyImage(device, image, allocationCallbacks);
+vmaFreeMemory(allocator, allocation);
+\endcode
+
+It it safe to pass null as image and/or allocation.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaDestroyImage(
+    VmaAllocator allocator,
+    VkImage image,
+    VmaAllocation allocation);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // AMD_VULKAN_MEMORY_ALLOCATOR_H
+
+// For Visual Studio IntelliSense.
+#if defined(__cplusplus) && defined(__INTELLISENSE__)
+#define VMA_IMPLEMENTATION
+#endif
+
+#ifdef VMA_IMPLEMENTATION
+#undef VMA_IMPLEMENTATION
+
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <utility>
+
+/*******************************************************************************
+CONFIGURATION SECTION
+
+Define some of these macros before each #include of this header or change them
+here if you need other then default behavior depending on your environment.
+*/
+
+/*
+Define this macro to 1 to make the library fetch pointers to Vulkan functions
+internally, like:
+
+    vulkanFunctions.vkAllocateMemory = &vkAllocateMemory;
+*/
+#if !defined(VMA_STATIC_VULKAN_FUNCTIONS) && !defined(VK_NO_PROTOTYPES)
+    #define VMA_STATIC_VULKAN_FUNCTIONS 1
+#endif
+
+/*
+Define this macro to 1 to make the library fetch pointers to Vulkan functions
+internally, like:
+
+    vulkanFunctions.vkAllocateMemory = (PFN_vkAllocateMemory)vkGetDeviceProcAddr(m_hDevice, vkAllocateMemory);
+*/
+#if !defined(VMA_DYNAMIC_VULKAN_FUNCTIONS)
+    #define VMA_DYNAMIC_VULKAN_FUNCTIONS 1
+#endif
+
+// Define this macro to 1 to make the library use STL containers instead of its own implementation.
+//#define VMA_USE_STL_CONTAINERS 1
+
+/* Set this macro to 1 to make the library including and using STL containers:
+std::pair, std::vector, std::list, std::unordered_map.
+
+Set it to 0 or undefined to make the library using its own implementation of
+the containers.
+*/
+#if VMA_USE_STL_CONTAINERS
+   #define VMA_USE_STL_VECTOR 1
+   #define VMA_USE_STL_UNORDERED_MAP 1
+   #define VMA_USE_STL_LIST 1
+#endif
+
+#ifndef VMA_USE_STL_SHARED_MUTEX
+    // Compiler conforms to C++17.
+    #if __cplusplus >= 201703L
+        #define VMA_USE_STL_SHARED_MUTEX 1
+    // Visual studio defines __cplusplus properly only when passed additional parameter: /Zc:__cplusplus
+    // Otherwise it's always 199711L, despite shared_mutex works since Visual Studio 2015 Update 2.
+    // See: https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/
+    #elif defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 190023918 && __cplusplus == 199711L && _MSVC_LANG >= 201703L
+        #define VMA_USE_STL_SHARED_MUTEX 1
+    #else
+        #define VMA_USE_STL_SHARED_MUTEX 0
+    #endif
+#endif
+
+/*
+THESE INCLUDES ARE NOT ENABLED BY DEFAULT.
+Library has its own container implementation.
+*/
+#if VMA_USE_STL_VECTOR
+   #include <vector>
+#endif
+
+#if VMA_USE_STL_UNORDERED_MAP
+   #include <unordered_map>
+#endif
+
+#if VMA_USE_STL_LIST
+   #include <list>
+#endif
+
+/*
+Following headers are used in this CONFIGURATION section only, so feel free to
+remove them if not needed.
+*/
+#include <cassert> // for assert
+#include <algorithm> // for min, max
+#include <mutex>
+
+#ifndef VMA_NULL
+   // Value used as null pointer. Define it to e.g.: nullptr, NULL, 0, (void*)0.
+   #define VMA_NULL   nullptr
+#endif
+
+#if defined(__ANDROID_API__) && (__ANDROID_API__ < 16)
+#include <cstdlib>
+void *aligned_alloc(size_t alignment, size_t size)
+{
+    // alignment must be >= sizeof(void*)
+    if(alignment < sizeof(void*))
+    {
+        alignment = sizeof(void*);
+    }
+
+    return memalign(alignment, size);
+}
+#elif defined(__APPLE__) || defined(__ANDROID__) || (defined(__linux__) && defined(__GLIBCXX__) && !defined(_GLIBCXX_HAVE_ALIGNED_ALLOC))
+#include <cstdlib>
+void *aligned_alloc(size_t alignment, size_t size)
+{
+    // alignment must be >= sizeof(void*)
+    if(alignment < sizeof(void*))
+    {
+        alignment = sizeof(void*);
+    }
+
+    void *pointer;
+    if(posix_memalign(&pointer, alignment, size) == 0)
+        return pointer;
+    return VMA_NULL;
+}
+#endif
+
+// If your compiler is not compatible with C++11 and definition of
+// aligned_alloc() function is missing, uncommeting following line may help:
+
+//#include <malloc.h>
+
+// Normal assert to check for programmer's errors, especially in Debug configuration.
+#ifndef VMA_ASSERT
+   #ifdef NDEBUG
+       #define VMA_ASSERT(expr)
+   #else
+       #define VMA_ASSERT(expr)         assert(expr)
+   #endif
+#endif
+
+// Assert that will be called very often, like inside data structures e.g. operator[].
+// Making it non-empty can make program slow.
+#ifndef VMA_HEAVY_ASSERT
+   #ifdef NDEBUG
+       #define VMA_HEAVY_ASSERT(expr)
+   #else
+       #define VMA_HEAVY_ASSERT(expr)   //VMA_ASSERT(expr)
+   #endif
+#endif
+
+#ifndef VMA_ALIGN_OF
+   #define VMA_ALIGN_OF(type)       (__alignof(type))
+#endif
+
+#ifndef VMA_SYSTEM_ALIGNED_MALLOC
+   #if defined(_WIN32)
+       #define VMA_SYSTEM_ALIGNED_MALLOC(size, alignment)   (_aligned_malloc((size), (alignment)))
+   #else
+       #define VMA_SYSTEM_ALIGNED_MALLOC(size, alignment)   (aligned_alloc((alignment), (size) ))
+   #endif
+#endif
+
+#ifndef VMA_SYSTEM_FREE
+   #if defined(_WIN32)
+       #define VMA_SYSTEM_FREE(ptr)   _aligned_free(ptr)
+   #else
+       #define VMA_SYSTEM_FREE(ptr)   free(ptr)
+   #endif
+#endif
+
+#ifndef VMA_MIN
+   #define VMA_MIN(v1, v2)    (std::min((v1), (v2)))
+#endif
+
+#ifndef VMA_MAX
+   #define VMA_MAX(v1, v2)    (std::max((v1), (v2)))
+#endif
+
+#ifndef VMA_SWAP
+   #define VMA_SWAP(v1, v2)   std::swap((v1), (v2))
+#endif
+
+#ifndef VMA_SORT
+   #define VMA_SORT(beg, end, cmp)  std::sort(beg, end, cmp)
+#endif
+
+#ifndef VMA_DEBUG_LOG
+   #define VMA_DEBUG_LOG(format, ...)
+   /*
+   #define VMA_DEBUG_LOG(format, ...) do { \
+       printf(format, __VA_ARGS__); \
+       printf("\n"); \
+   } while(false)
+   */
+#endif
+
+// Define this macro to 1 to enable functions: vmaBuildStatsString, vmaFreeStatsString.
+#if VMA_STATS_STRING_ENABLED
+    static inline void VmaUint32ToStr(char* outStr, size_t strLen, uint32_t num)
+    {
+        snprintf(outStr, strLen, "%u", static_cast<unsigned int>(num));
+    }
+    static inline void VmaUint64ToStr(char* outStr, size_t strLen, uint64_t num)
+    {
+        snprintf(outStr, strLen, "%llu", static_cast<unsigned long long>(num));
+    }
+    static inline void VmaPtrToStr(char* outStr, size_t strLen, const void* ptr)
+    {
+        snprintf(outStr, strLen, "%p", ptr);
+    }
+#endif
+
+#ifndef VMA_MUTEX
+    class VmaMutex
+    {
+    public:
+        void Lock() { m_Mutex.lock(); }
+        void Unlock() { m_Mutex.unlock(); }
+        bool TryLock() { return m_Mutex.try_lock(); }
+    private:
+        std::mutex m_Mutex;
+    };
+    #define VMA_MUTEX VmaMutex
+#endif
+
+// Read-write mutex, where "read" is shared access, "write" is exclusive access.
+#ifndef VMA_RW_MUTEX
+    #if VMA_USE_STL_SHARED_MUTEX
+        // Use std::shared_mutex from C++17.
+        #include <shared_mutex>
+        class VmaRWMutex
+        {
+        public:
+            void LockRead() { m_Mutex.lock_shared(); }
+            void UnlockRead() { m_Mutex.unlock_shared(); }
+            bool TryLockRead() { return m_Mutex.try_lock_shared(); }
+            void LockWrite() { m_Mutex.lock(); }
+            void UnlockWrite() { m_Mutex.unlock(); }
+            bool TryLockWrite() { return m_Mutex.try_lock(); }
+        private:
+            std::shared_mutex m_Mutex;
+        };
+        #define VMA_RW_MUTEX VmaRWMutex
+    #elif defined(_WIN32) && defined(WINVER) && WINVER >= 0x0600
+        // Use SRWLOCK from WinAPI.
+        // Minimum supported client = Windows Vista, server = Windows Server 2008.
+        class VmaRWMutex
+        {
+        public:
+            VmaRWMutex() { InitializeSRWLock(&m_Lock); }
+            void LockRead() { AcquireSRWLockShared(&m_Lock); }
+            void UnlockRead() { ReleaseSRWLockShared(&m_Lock); }
+            bool TryLockRead() { return TryAcquireSRWLockShared(&m_Lock) != FALSE; }
+            void LockWrite() { AcquireSRWLockExclusive(&m_Lock); }
+            void UnlockWrite() { ReleaseSRWLockExclusive(&m_Lock); }
+            bool TryLockWrite() { return TryAcquireSRWLockExclusive(&m_Lock) != FALSE; }
+        private:
+            SRWLOCK m_Lock;
+        };
+        #define VMA_RW_MUTEX VmaRWMutex
+    #else
+        // Less efficient fallback: Use normal mutex.
+        class VmaRWMutex
+        {
+        public:
+            void LockRead() { m_Mutex.Lock(); }
+            void UnlockRead() { m_Mutex.Unlock(); }
+            bool TryLockRead() { return m_Mutex.TryLock(); }
+            void LockWrite() { m_Mutex.Lock(); }
+            void UnlockWrite() { m_Mutex.Unlock(); }
+            bool TryLockWrite() { return m_Mutex.TryLock(); }
+        private:
+            VMA_MUTEX m_Mutex;
+        };
+        #define VMA_RW_MUTEX VmaRWMutex
+    #endif // #if VMA_USE_STL_SHARED_MUTEX
+#endif // #ifndef VMA_RW_MUTEX
+
+/*
+If providing your own implementation, you need to implement a subset of std::atomic.
+*/
+#ifndef VMA_ATOMIC_UINT32
+    #include <atomic>
+    #define VMA_ATOMIC_UINT32 std::atomic<uint32_t>
+#endif
+
+#ifndef VMA_ATOMIC_UINT64
+    #include <atomic>
+    #define VMA_ATOMIC_UINT64 std::atomic<uint64_t>
+#endif
+
+#ifndef VMA_DEBUG_ALWAYS_DEDICATED_MEMORY
+    /**
+    Every allocation will have its own memory block.
+    Define to 1 for debugging purposes only.
+    */
+    #define VMA_DEBUG_ALWAYS_DEDICATED_MEMORY (0)
+#endif
+
+#ifndef VMA_DEBUG_ALIGNMENT
+    /**
+    Minimum alignment of all allocations, in bytes.
+    Set to more than 1 for debugging purposes only. Must be power of two.
+    */
+    #define VMA_DEBUG_ALIGNMENT (1)
+#endif
+
+#ifndef VMA_DEBUG_MARGIN
+    /**
+    Minimum margin before and after every allocation, in bytes.
+    Set nonzero for debugging purposes only.
+    */
+    #define VMA_DEBUG_MARGIN (0)
+#endif
+
+#ifndef VMA_DEBUG_INITIALIZE_ALLOCATIONS
+    /**
+    Define this macro to 1 to automatically fill new allocations and destroyed
+    allocations with some bit pattern.
+    */
+    #define VMA_DEBUG_INITIALIZE_ALLOCATIONS (0)
+#endif
+
+#ifndef VMA_DEBUG_DETECT_CORRUPTION
+    /**
+    Define this macro to 1 together with non-zero value of VMA_DEBUG_MARGIN to
+    enable writing magic value to the margin before and after every allocation and
+    validating it, so that memory corruptions (out-of-bounds writes) are detected.
+    */
+    #define VMA_DEBUG_DETECT_CORRUPTION (0)
+#endif
+
+#ifndef VMA_DEBUG_GLOBAL_MUTEX
+    /**
+    Set this to 1 for debugging purposes only, to enable single mutex protecting all
+    entry calls to the library. Can be useful for debugging multithreading issues.
+    */
+    #define VMA_DEBUG_GLOBAL_MUTEX (0)
+#endif
+
+#ifndef VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY
+    /**
+    Minimum value for VkPhysicalDeviceLimits::bufferImageGranularity.
+    Set to more than 1 for debugging purposes only. Must be power of two.
+    */
+    #define VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY (1)
+#endif
+
+#ifndef VMA_SMALL_HEAP_MAX_SIZE
+   /// Maximum size of a memory heap in Vulkan to consider it "small".
+   #define VMA_SMALL_HEAP_MAX_SIZE (1024ull * 1024 * 1024)
+#endif
+
+#ifndef VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE
+   /// Default size of a block allocated as single VkDeviceMemory from a "large" heap.
+   #define VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE (256ull * 1024 * 1024)
+#endif
+
+#ifndef VMA_CLASS_NO_COPY
+    #define VMA_CLASS_NO_COPY(className) \
+        private: \
+            className(const className&) = delete; \
+            className& operator=(const className&) = delete;
+#endif
+
+static const uint32_t VMA_FRAME_INDEX_LOST = UINT32_MAX;
+
+// Decimal 2139416166, float NaN, little-endian binary 66 E6 84 7F.
+static const uint32_t VMA_CORRUPTION_DETECTION_MAGIC_VALUE = 0x7F84E666;
+
+static const uint8_t VMA_ALLOCATION_FILL_PATTERN_CREATED   = 0xDC;
+static const uint8_t VMA_ALLOCATION_FILL_PATTERN_DESTROYED = 0xEF;
+
+/*******************************************************************************
+END OF CONFIGURATION
+*/
+
+// # Copy of some Vulkan definitions so we don't need to check their existence just to handle few constants.
+
+static const uint32_t VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD_COPY = 0x00000040;
+static const uint32_t VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD_COPY = 0x00000080;
+static const uint32_t VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_COPY = 0x00020000;
+
+static const uint32_t VMA_ALLOCATION_INTERNAL_STRATEGY_MIN_OFFSET = 0x10000000u;
+
+static VkAllocationCallbacks VmaEmptyAllocationCallbacks = {
+    VMA_NULL, VMA_NULL, VMA_NULL, VMA_NULL, VMA_NULL, VMA_NULL };
+
+// Returns number of bits set to 1 in (v).
+static inline uint32_t VmaCountBitsSet(uint32_t v)
+{
+	uint32_t c = v - ((v >> 1) & 0x55555555);
+	c = ((c >>  2) & 0x33333333) + (c & 0x33333333);
+	c = ((c >>  4) + c) & 0x0F0F0F0F;
+	c = ((c >>  8) + c) & 0x00FF00FF;
+	c = ((c >> 16) + c) & 0x0000FFFF;
+	return c;
+}
+
+// Aligns given value up to nearest multiply of align value. For example: VmaAlignUp(11, 8) = 16.
+// Use types like uint32_t, uint64_t as T.
+template <typename T>
+static inline T VmaAlignUp(T val, T align)
+{
+	return (val + align - 1) / align * align;
+}
+// Aligns given value down to nearest multiply of align value. For example: VmaAlignUp(11, 8) = 8.
+// Use types like uint32_t, uint64_t as T.
+template <typename T>
+static inline T VmaAlignDown(T val, T align)
+{
+    return val / align * align;
+}
+
+// Division with mathematical rounding to nearest number.
+template <typename T>
+static inline T VmaRoundDiv(T x, T y)
+{
+	return (x + (y / (T)2)) / y;
+}
+
+/*
+Returns true if given number is a power of two.
+T must be unsigned integer number or signed integer but always nonnegative.
+For 0 returns true.
+*/
+template <typename T>
+inline bool VmaIsPow2(T x)
+{
+    return (x & (x-1)) == 0;
+}
+
+// Returns smallest power of 2 greater or equal to v.
+static inline uint32_t VmaNextPow2(uint32_t v)
+{
+	v--;
+    v |= v >> 1;
+    v |= v >> 2;
+    v |= v >> 4;
+    v |= v >> 8;
+    v |= v >> 16;
+    v++;
+    return v;
+}
+static inline uint64_t VmaNextPow2(uint64_t v)
+{
+	v--;
+    v |= v >> 1;
+    v |= v >> 2;
+    v |= v >> 4;
+    v |= v >> 8;
+    v |= v >> 16;
+    v |= v >> 32;
+    v++;
+    return v;
+}
+
+// Returns largest power of 2 less or equal to v.
+static inline uint32_t VmaPrevPow2(uint32_t v)
+{
+    v |= v >> 1;
+    v |= v >> 2;
+    v |= v >> 4;
+    v |= v >> 8;
+    v |= v >> 16;
+    v = v ^ (v >> 1);
+    return v;
+}
+static inline uint64_t VmaPrevPow2(uint64_t v)
+{
+    v |= v >> 1;
+    v |= v >> 2;
+    v |= v >> 4;
+    v |= v >> 8;
+    v |= v >> 16;
+    v |= v >> 32;
+    v = v ^ (v >> 1);
+    return v;
+}
+
+static inline bool VmaStrIsEmpty(const char* pStr)
+{
+    return pStr == VMA_NULL || *pStr == '\0';
+}
+
+#if VMA_STATS_STRING_ENABLED
+
+static const char* VmaAlgorithmToStr(uint32_t algorithm)
+{
+    switch(algorithm)
+    {
+    case VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT:
+        return "Linear";
+    case VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT:
+        return "Buddy";
+    case 0:
+        return "Default";
+    default:
+        VMA_ASSERT(0);
+        return "";
+    }
+}
+
+#endif // #if VMA_STATS_STRING_ENABLED
+
+#ifndef VMA_SORT
+
+template<typename Iterator, typename Compare>
+Iterator VmaQuickSortPartition(Iterator beg, Iterator end, Compare cmp)
+{
+    Iterator centerValue = end; --centerValue;
+    Iterator insertIndex = beg;
+    for(Iterator memTypeIndex = beg; memTypeIndex < centerValue; ++memTypeIndex)
+    {
+        if(cmp(*memTypeIndex, *centerValue))
+        {
+            if(insertIndex != memTypeIndex)
+            {
+                VMA_SWAP(*memTypeIndex, *insertIndex);
+            }
+            ++insertIndex;
+        }
+    }
+    if(insertIndex != centerValue)
+    {
+        VMA_SWAP(*insertIndex, *centerValue);
+    }
+    return insertIndex;
+}
+
+template<typename Iterator, typename Compare>
+void VmaQuickSort(Iterator beg, Iterator end, Compare cmp)
+{
+    if(beg < end)
+    {
+        Iterator it = VmaQuickSortPartition<Iterator, Compare>(beg, end, cmp);
+        VmaQuickSort<Iterator, Compare>(beg, it, cmp);
+        VmaQuickSort<Iterator, Compare>(it + 1, end, cmp);
+    }
+}
+
+#define VMA_SORT(beg, end, cmp) VmaQuickSort(beg, end, cmp)
+
+#endif // #ifndef VMA_SORT
+
+/*
+Returns true if two memory blocks occupy overlapping pages.
+ResourceA must be in less memory offset than ResourceB.
+
+Algorithm is based on "Vulkan 1.0.39 - A Specification (with all registered Vulkan extensions)"
+chapter 11.6 "Resource Memory Association", paragraph "Buffer-Image Granularity".
+*/
+static inline bool VmaBlocksOnSamePage(
+    VkDeviceSize resourceAOffset,
+    VkDeviceSize resourceASize,
+    VkDeviceSize resourceBOffset,
+    VkDeviceSize pageSize)
+{
+    VMA_ASSERT(resourceAOffset + resourceASize <= resourceBOffset && resourceASize > 0 && pageSize > 0);
+    VkDeviceSize resourceAEnd = resourceAOffset + resourceASize - 1;
+    VkDeviceSize resourceAEndPage = resourceAEnd & ~(pageSize - 1);
+    VkDeviceSize resourceBStart = resourceBOffset;
+    VkDeviceSize resourceBStartPage = resourceBStart & ~(pageSize - 1);
+    return resourceAEndPage == resourceBStartPage;
+}
+
+enum VmaSuballocationType
+{
+    VMA_SUBALLOCATION_TYPE_FREE = 0,
+    VMA_SUBALLOCATION_TYPE_UNKNOWN = 1,
+    VMA_SUBALLOCATION_TYPE_BUFFER = 2,
+    VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN = 3,
+    VMA_SUBALLOCATION_TYPE_IMAGE_LINEAR = 4,
+    VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL = 5,
+    VMA_SUBALLOCATION_TYPE_MAX_ENUM = 0x7FFFFFFF
+};
+
+/*
+Returns true if given suballocation types could conflict and must respect
+VkPhysicalDeviceLimits::bufferImageGranularity. They conflict if one is buffer
+or linear image and another one is optimal image. If type is unknown, behave
+conservatively.
+*/
+static inline bool VmaIsBufferImageGranularityConflict(
+    VmaSuballocationType suballocType1,
+    VmaSuballocationType suballocType2)
+{
+    if(suballocType1 > suballocType2)
+    {
+        VMA_SWAP(suballocType1, suballocType2);
+    }
+    
+    switch(suballocType1)
+    {
+    case VMA_SUBALLOCATION_TYPE_FREE:
+        return false;
+    case VMA_SUBALLOCATION_TYPE_UNKNOWN:
+        return true;
+    case VMA_SUBALLOCATION_TYPE_BUFFER:
+        return
+            suballocType2 == VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN ||
+            suballocType2 == VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL;
+    case VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN:
+        return
+            suballocType2 == VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN ||
+            suballocType2 == VMA_SUBALLOCATION_TYPE_IMAGE_LINEAR ||
+            suballocType2 == VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL;
+    case VMA_SUBALLOCATION_TYPE_IMAGE_LINEAR:
+        return
+            suballocType2 == VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL;
+    case VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL:
+        return false;
+    default:
+        VMA_ASSERT(0);
+        return true;
+    }
+}
+
+static void VmaWriteMagicValue(void* pData, VkDeviceSize offset)
+{
+#if VMA_DEBUG_MARGIN > 0 && VMA_DEBUG_DETECT_CORRUPTION
+    uint32_t* pDst = (uint32_t*)((char*)pData + offset);
+    const size_t numberCount = VMA_DEBUG_MARGIN / sizeof(uint32_t);
+    for(size_t i = 0; i < numberCount; ++i, ++pDst)
+    {
+        *pDst = VMA_CORRUPTION_DETECTION_MAGIC_VALUE;
+    }
+#else
+    // no-op
+#endif
+}
+
+static bool VmaValidateMagicValue(const void* pData, VkDeviceSize offset)
+{
+#if VMA_DEBUG_MARGIN > 0 && VMA_DEBUG_DETECT_CORRUPTION
+    const uint32_t* pSrc = (const uint32_t*)((const char*)pData + offset);
+    const size_t numberCount = VMA_DEBUG_MARGIN / sizeof(uint32_t);
+    for(size_t i = 0; i < numberCount; ++i, ++pSrc)
+    {
+        if(*pSrc != VMA_CORRUPTION_DETECTION_MAGIC_VALUE)
+        {
+            return false;
+        }
+    }
+#endif
+    return true;
+}
+
+/*
+Fills structure with parameters of an example buffer to be used for transfers
+during GPU memory defragmentation.
+*/
+static void VmaFillGpuDefragmentationBufferCreateInfo(VkBufferCreateInfo& outBufCreateInfo)
+{
+    memset(&outBufCreateInfo, 0, sizeof(outBufCreateInfo));
+    outBufCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+    outBufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+    outBufCreateInfo.size = (VkDeviceSize)VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE; // Example size.
+}
+
+// Helper RAII class to lock a mutex in constructor and unlock it in destructor (at the end of scope).
+struct VmaMutexLock
+{
+    VMA_CLASS_NO_COPY(VmaMutexLock)
+public:
+    VmaMutexLock(VMA_MUTEX& mutex, bool useMutex = true) :
+        m_pMutex(useMutex ? &mutex : VMA_NULL)
+    { if(m_pMutex) { m_pMutex->Lock(); } }
+    ~VmaMutexLock()
+    { if(m_pMutex) { m_pMutex->Unlock(); } }
+private:
+    VMA_MUTEX* m_pMutex;
+};
+
+// Helper RAII class to lock a RW mutex in constructor and unlock it in destructor (at the end of scope), for reading.
+struct VmaMutexLockRead
+{
+    VMA_CLASS_NO_COPY(VmaMutexLockRead)
+public:
+    VmaMutexLockRead(VMA_RW_MUTEX& mutex, bool useMutex) :
+        m_pMutex(useMutex ? &mutex : VMA_NULL)
+    { if(m_pMutex) { m_pMutex->LockRead(); } }
+    ~VmaMutexLockRead() { if(m_pMutex) { m_pMutex->UnlockRead(); } }
+private:
+    VMA_RW_MUTEX* m_pMutex;
+};
+
+// Helper RAII class to lock a RW mutex in constructor and unlock it in destructor (at the end of scope), for writing.
+struct VmaMutexLockWrite
+{
+    VMA_CLASS_NO_COPY(VmaMutexLockWrite)
+public:
+    VmaMutexLockWrite(VMA_RW_MUTEX& mutex, bool useMutex) :
+        m_pMutex(useMutex ? &mutex : VMA_NULL)
+    { if(m_pMutex) { m_pMutex->LockWrite(); } }
+    ~VmaMutexLockWrite() { if(m_pMutex) { m_pMutex->UnlockWrite(); } }
+private:
+    VMA_RW_MUTEX* m_pMutex;
+};
+
+#if VMA_DEBUG_GLOBAL_MUTEX
+    static VMA_MUTEX gDebugGlobalMutex;
+    #define VMA_DEBUG_GLOBAL_MUTEX_LOCK VmaMutexLock debugGlobalMutexLock(gDebugGlobalMutex, true);
+#else
+    #define VMA_DEBUG_GLOBAL_MUTEX_LOCK
+#endif
+
+// Minimum size of a free suballocation to register it in the free suballocation collection.
+static const VkDeviceSize VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER = 16;
+
+/*
+Performs binary search and returns iterator to first element that is greater or
+equal to (key), according to comparison (cmp).
+
+Cmp should return true if first argument is less than second argument.
+
+Returned value is the found element, if present in the collection or place where
+new element with value (key) should be inserted.
+*/
+template <typename CmpLess, typename IterT, typename KeyT>
+static IterT VmaBinaryFindFirstNotLess(IterT beg, IterT end, const KeyT &key, const CmpLess& cmp)
+{
+    size_t down = 0, up = (end - beg);
+    while(down < up)
+    {
+        const size_t mid = (down + up) / 2;
+        if(cmp(*(beg+mid), key))
+        {
+            down = mid + 1;
+        }
+        else
+        {
+            up = mid;
+        }
+    }
+    return beg + down;
+}
+
+template<typename CmpLess, typename IterT, typename KeyT>
+IterT VmaBinaryFindSorted(const IterT& beg, const IterT& end, const KeyT& value, const CmpLess& cmp)
+{
+    IterT it = VmaBinaryFindFirstNotLess<CmpLess, IterT, KeyT>(
+        beg, end, value, cmp);
+    if(it == end ||
+        (!cmp(*it, value) && !cmp(value, *it)))
+    {
+        return it;
+    }
+    return end;
+}
+
+/*
+Returns true if all pointers in the array are not-null and unique.
+Warning! O(n^2) complexity. Use only inside VMA_HEAVY_ASSERT.
+T must be pointer type, e.g. VmaAllocation, VmaPool.
+*/
+template<typename T>
+static bool VmaValidatePointerArray(uint32_t count, const T* arr)
+{
+    for(uint32_t i = 0; i < count; ++i)
+    {
+        const T iPtr = arr[i];
+        if(iPtr == VMA_NULL)
+        {
+            return false;
+        }
+        for(uint32_t j = i + 1; j < count; ++j)
+        {
+            if(iPtr == arr[j])
+            {
+                return false;
+            }
+        }
+    }
+    return true;
+}
+
+template<typename MainT, typename NewT>
+static inline void VmaPnextChainPushFront(MainT* mainStruct, NewT* newStruct)
+{
+    newStruct->pNext = mainStruct->pNext;
+    mainStruct->pNext = newStruct;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Memory allocation
+
+static void* VmaMalloc(const VkAllocationCallbacks* pAllocationCallbacks, size_t size, size_t alignment)
+{
+    if((pAllocationCallbacks != VMA_NULL) &&
+        (pAllocationCallbacks->pfnAllocation != VMA_NULL))
+    {
+        return (*pAllocationCallbacks->pfnAllocation)(
+            pAllocationCallbacks->pUserData,
+            size,
+            alignment,
+            VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+    }
+    else
+    {
+        return VMA_SYSTEM_ALIGNED_MALLOC(size, alignment);
+    }
+}
+
+static void VmaFree(const VkAllocationCallbacks* pAllocationCallbacks, void* ptr)
+{
+    if((pAllocationCallbacks != VMA_NULL) &&
+        (pAllocationCallbacks->pfnFree != VMA_NULL))
+    {
+        (*pAllocationCallbacks->pfnFree)(pAllocationCallbacks->pUserData, ptr);
+    }
+    else
+    {
+        VMA_SYSTEM_FREE(ptr);
+    }
+}
+
+template<typename T>
+static T* VmaAllocate(const VkAllocationCallbacks* pAllocationCallbacks)
+{
+    return (T*)VmaMalloc(pAllocationCallbacks, sizeof(T), VMA_ALIGN_OF(T));
+}
+
+template<typename T>
+static T* VmaAllocateArray(const VkAllocationCallbacks* pAllocationCallbacks, size_t count)
+{
+    return (T*)VmaMalloc(pAllocationCallbacks, sizeof(T) * count, VMA_ALIGN_OF(T));
+}
+
+#define vma_new(allocator, type)   new(VmaAllocate<type>(allocator))(type)
+
+#define vma_new_array(allocator, type, count)   new(VmaAllocateArray<type>((allocator), (count)))(type)
+
+template<typename T>
+static void vma_delete(const VkAllocationCallbacks* pAllocationCallbacks, T* ptr)
+{
+    ptr->~T();
+    VmaFree(pAllocationCallbacks, ptr);
+}
+
+template<typename T>
+static void vma_delete_array(const VkAllocationCallbacks* pAllocationCallbacks, T* ptr, size_t count)
+{
+    if(ptr != VMA_NULL)
+    {
+        for(size_t i = count; i--; )
+        {
+            ptr[i].~T();
+        }
+        VmaFree(pAllocationCallbacks, ptr);
+    }
+}
+
+static char* VmaCreateStringCopy(const VkAllocationCallbacks* allocs, const char* srcStr)
+{
+    if(srcStr != VMA_NULL)
+    {
+        const size_t len = strlen(srcStr);
+        char* const result = vma_new_array(allocs, char, len + 1);
+        memcpy(result, srcStr, len + 1);
+        return result;
+    }
+    else
+    {
+        return VMA_NULL;
+    }
+}
+
+static void VmaFreeString(const VkAllocationCallbacks* allocs, char* str)
+{
+    if(str != VMA_NULL)
+    {
+        const size_t len = strlen(str);
+        vma_delete_array(allocs, str, len + 1);
+    }
+}
+
+// STL-compatible allocator.
+template<typename T>
+class VmaStlAllocator
+{
+public:
+    const VkAllocationCallbacks* const m_pCallbacks;
+    typedef T value_type;
+    
+    VmaStlAllocator(const VkAllocationCallbacks* pCallbacks) : m_pCallbacks(pCallbacks) { }
+    template<typename U> VmaStlAllocator(const VmaStlAllocator<U>& src) : m_pCallbacks(src.m_pCallbacks) { }
+
+    T* allocate(size_t n) { return VmaAllocateArray<T>(m_pCallbacks, n); }
+    void deallocate(T* p, size_t n) { VmaFree(m_pCallbacks, p); }
+
+    template<typename U>
+    bool operator==(const VmaStlAllocator<U>& rhs) const
+    {
+        return m_pCallbacks == rhs.m_pCallbacks;
+    }
+    template<typename U>
+    bool operator!=(const VmaStlAllocator<U>& rhs) const
+    {
+        return m_pCallbacks != rhs.m_pCallbacks;
+    }
+
+    VmaStlAllocator& operator=(const VmaStlAllocator& x) = delete;
+};
+
+#if VMA_USE_STL_VECTOR
+
+#define VmaVector std::vector
+
+template<typename T, typename allocatorT>
+static void VmaVectorInsert(std::vector<T, allocatorT>& vec, size_t index, const T& item)
+{
+    vec.insert(vec.begin() + index, item);
+}
+
+template<typename T, typename allocatorT>
+static void VmaVectorRemove(std::vector<T, allocatorT>& vec, size_t index)
+{
+    vec.erase(vec.begin() + index);
+}
+
+#else // #if VMA_USE_STL_VECTOR
+
+/* Class with interface compatible with subset of std::vector.
+T must be POD because constructors and destructors are not called and memcpy is
+used for these objects. */
+template<typename T, typename AllocatorT>
+class VmaVector
+{
+public:
+    typedef T value_type;
+
+    VmaVector(const AllocatorT& allocator) :
+        m_Allocator(allocator),
+        m_pArray(VMA_NULL),
+        m_Count(0),
+        m_Capacity(0)
+    {
+    }
+
+    VmaVector(size_t count, const AllocatorT& allocator) :
+        m_Allocator(allocator),
+        m_pArray(count ? (T*)VmaAllocateArray<T>(allocator.m_pCallbacks, count) : VMA_NULL),
+        m_Count(count),
+        m_Capacity(count)
+    {
+    }
+    
+    // This version of the constructor is here for compatibility with pre-C++14 std::vector.
+    // value is unused.
+    VmaVector(size_t count, const T& value, const AllocatorT& allocator)
+        : VmaVector(count, allocator) {}
+    
+    VmaVector(const VmaVector<T, AllocatorT>& src) :
+        m_Allocator(src.m_Allocator),
+        m_pArray(src.m_Count ? (T*)VmaAllocateArray<T>(src.m_Allocator.m_pCallbacks, src.m_Count) : VMA_NULL),
+        m_Count(src.m_Count),
+        m_Capacity(src.m_Count)
+    {
+        if(m_Count != 0)
+        {
+            memcpy(m_pArray, src.m_pArray, m_Count * sizeof(T));
+        }
+    }
+    
+    ~VmaVector()
+    {
+        VmaFree(m_Allocator.m_pCallbacks, m_pArray);
+    }
+
+    VmaVector& operator=(const VmaVector<T, AllocatorT>& rhs)
+    {
+        if(&rhs != this)
+        {
+            resize(rhs.m_Count);
+            if(m_Count != 0)
+            {
+                memcpy(m_pArray, rhs.m_pArray, m_Count * sizeof(T));
+            }
+        }
+        return *this;
+    }
+    
+    bool empty() const { return m_Count == 0; }
+    size_t size() const { return m_Count; }
+    T* data() { return m_pArray; }
+    const T* data() const { return m_pArray; }
+    
+    T& operator[](size_t index)
+    {
+        VMA_HEAVY_ASSERT(index < m_Count);
+        return m_pArray[index];
+    }
+    const T& operator[](size_t index) const
+    {
+        VMA_HEAVY_ASSERT(index < m_Count);
+        return m_pArray[index];
+    }
+
+    T& front()
+    {
+        VMA_HEAVY_ASSERT(m_Count > 0);
+        return m_pArray[0];
+    }
+    const T& front() const
+    {
+        VMA_HEAVY_ASSERT(m_Count > 0);
+        return m_pArray[0];
+    }
+    T& back()
+    {
+        VMA_HEAVY_ASSERT(m_Count > 0);
+        return m_pArray[m_Count - 1];
+    }
+    const T& back() const
+    {
+        VMA_HEAVY_ASSERT(m_Count > 0);
+        return m_pArray[m_Count - 1];
+    }
+
+    void reserve(size_t newCapacity, bool freeMemory = false)
+    {
+        newCapacity = VMA_MAX(newCapacity, m_Count);
+        
+        if((newCapacity < m_Capacity) && !freeMemory)
+        {
+            newCapacity = m_Capacity;
+        }
+        
+        if(newCapacity != m_Capacity)
+        {
+            T* const newArray = newCapacity ? VmaAllocateArray<T>(m_Allocator, newCapacity) : VMA_NULL;
+            if(m_Count != 0)
+            {
+                memcpy(newArray, m_pArray, m_Count * sizeof(T));
+            }
+            VmaFree(m_Allocator.m_pCallbacks, m_pArray);
+            m_Capacity = newCapacity;
+            m_pArray = newArray;
+        }
+    }
+
+    void resize(size_t newCount, bool freeMemory = false)
+    {
+        size_t newCapacity = m_Capacity;
+        if(newCount > m_Capacity)
+        {
+            newCapacity = VMA_MAX(newCount, VMA_MAX(m_Capacity * 3 / 2, (size_t)8));
+        }
+        else if(freeMemory)
+        {
+            newCapacity = newCount;
+        }
+
+        if(newCapacity != m_Capacity)
+        {
+            T* const newArray = newCapacity ? VmaAllocateArray<T>(m_Allocator.m_pCallbacks, newCapacity) : VMA_NULL;
+            const size_t elementsToCopy = VMA_MIN(m_Count, newCount);
+            if(elementsToCopy != 0)
+            {
+                memcpy(newArray, m_pArray, elementsToCopy * sizeof(T));
+            }
+            VmaFree(m_Allocator.m_pCallbacks, m_pArray);
+            m_Capacity = newCapacity;
+            m_pArray = newArray;
+        }
+
+        m_Count = newCount;
+    }
+
+    void clear(bool freeMemory = false)
+    {
+        resize(0, freeMemory);
+    }
+
+    void insert(size_t index, const T& src)
+    {
+        VMA_HEAVY_ASSERT(index <= m_Count);
+        const size_t oldCount = size();
+        resize(oldCount + 1);
+        if(index < oldCount)
+        {
+            memmove(m_pArray + (index + 1), m_pArray + index, (oldCount - index) * sizeof(T));
+        }
+        m_pArray[index] = src;
+    }
+
+    void remove(size_t index)
+    {
+        VMA_HEAVY_ASSERT(index < m_Count);
+        const size_t oldCount = size();
+        if(index < oldCount - 1)
+        {
+            memmove(m_pArray + index, m_pArray + (index + 1), (oldCount - index - 1) * sizeof(T));
+        }
+        resize(oldCount - 1);
+    }
+
+    void push_back(const T& src)
+    {
+        const size_t newIndex = size();
+        resize(newIndex + 1);
+        m_pArray[newIndex] = src;
+    }
+
+    void pop_back()
+    {
+        VMA_HEAVY_ASSERT(m_Count > 0);
+        resize(size() - 1);
+    }
+
+    void push_front(const T& src)
+    {
+        insert(0, src);
+    }
+
+    void pop_front()
+    {
+        VMA_HEAVY_ASSERT(m_Count > 0);
+        remove(0);
+    }
+
+    typedef T* iterator;
+
+    iterator begin() { return m_pArray; }
+    iterator end() { return m_pArray + m_Count; }
+
+private:
+    AllocatorT m_Allocator;
+    T* m_pArray;
+    size_t m_Count;
+    size_t m_Capacity;
+};
+
+template<typename T, typename allocatorT>
+static void VmaVectorInsert(VmaVector<T, allocatorT>& vec, size_t index, const T& item)
+{
+    vec.insert(index, item);
+}
+
+template<typename T, typename allocatorT>
+static void VmaVectorRemove(VmaVector<T, allocatorT>& vec, size_t index)
+{
+    vec.remove(index);
+}
+
+#endif // #if VMA_USE_STL_VECTOR
+
+template<typename CmpLess, typename VectorT>
+size_t VmaVectorInsertSorted(VectorT& vector, const typename VectorT::value_type& value)
+{
+    const size_t indexToInsert = VmaBinaryFindFirstNotLess(
+        vector.data(),
+        vector.data() + vector.size(),
+        value,
+        CmpLess()) - vector.data();
+    VmaVectorInsert(vector, indexToInsert, value);
+    return indexToInsert;
+}
+
+template<typename CmpLess, typename VectorT>
+bool VmaVectorRemoveSorted(VectorT& vector, const typename VectorT::value_type& value)
+{
+    CmpLess comparator;
+    typename VectorT::iterator it = VmaBinaryFindFirstNotLess(
+        vector.begin(),
+        vector.end(),
+        value,
+        comparator);
+    if((it != vector.end()) && !comparator(*it, value) && !comparator(value, *it))
+    {
+        size_t indexToRemove = it - vector.begin();
+        VmaVectorRemove(vector, indexToRemove);
+        return true;
+    }
+    return false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// class VmaPoolAllocator
+
+/*
+Allocator for objects of type T using a list of arrays (pools) to speed up
+allocation. Number of elements that can be allocated is not bounded because
+allocator can create multiple blocks.
+*/
+template<typename T>
+class VmaPoolAllocator
+{
+    VMA_CLASS_NO_COPY(VmaPoolAllocator)
+public:
+    VmaPoolAllocator(const VkAllocationCallbacks* pAllocationCallbacks, uint32_t firstBlockCapacity);
+    ~VmaPoolAllocator();
+    template<typename... Types> T* Alloc(Types... args);
+    void Free(T* ptr);
+
+private:
+    union Item
+    {
+        uint32_t NextFreeIndex;
+        alignas(T) char Value[sizeof(T)];
+    };
+
+    struct ItemBlock
+    {
+        Item* pItems;
+        uint32_t Capacity;
+        uint32_t FirstFreeIndex;
+    };
+    
+    const VkAllocationCallbacks* m_pAllocationCallbacks;
+    const uint32_t m_FirstBlockCapacity;
+    VmaVector< ItemBlock, VmaStlAllocator<ItemBlock> > m_ItemBlocks;
+
+    ItemBlock& CreateNewBlock();
+};
+
+template<typename T>
+VmaPoolAllocator<T>::VmaPoolAllocator(const VkAllocationCallbacks* pAllocationCallbacks, uint32_t firstBlockCapacity) :
+    m_pAllocationCallbacks(pAllocationCallbacks),
+    m_FirstBlockCapacity(firstBlockCapacity),
+    m_ItemBlocks(VmaStlAllocator<ItemBlock>(pAllocationCallbacks))
+{
+    VMA_ASSERT(m_FirstBlockCapacity > 1);
+}
+
+template<typename T>
+VmaPoolAllocator<T>::~VmaPoolAllocator()
+{
+    for(size_t i = m_ItemBlocks.size(); i--; )
+        vma_delete_array(m_pAllocationCallbacks, m_ItemBlocks[i].pItems, m_ItemBlocks[i].Capacity);
+    m_ItemBlocks.clear();
+}
+
+template<typename T>
+template<typename... Types> T* VmaPoolAllocator<T>::Alloc(Types... args)
+{
+    for(size_t i = m_ItemBlocks.size(); i--; )
+    {
+        ItemBlock& block = m_ItemBlocks[i];
+        // This block has some free items: Use first one.
+        if(block.FirstFreeIndex != UINT32_MAX)
+        {
+            Item* const pItem = &block.pItems[block.FirstFreeIndex];
+            block.FirstFreeIndex = pItem->NextFreeIndex;
+            T* result = (T*)&pItem->Value;
+            new(result)T(std::forward<Types>(args)...); // Explicit constructor call.
+            return result;
+        }
+    }
+
+    // No block has free item: Create new one and use it.
+    ItemBlock& newBlock = CreateNewBlock();
+    Item* const pItem = &newBlock.pItems[0];
+    newBlock.FirstFreeIndex = pItem->NextFreeIndex;
+    T* result = (T*)&pItem->Value;
+    new(result)T(std::forward<Types>(args)...); // Explicit constructor call.
+    return result;
+}
+
+template<typename T>
+void VmaPoolAllocator<T>::Free(T* ptr)
+{
+    // Search all memory blocks to find ptr.
+    for(size_t i = m_ItemBlocks.size(); i--; )
+    {
+        ItemBlock& block = m_ItemBlocks[i];
+        
+        // Casting to union.
+        Item* pItemPtr;
+        memcpy(&pItemPtr, &ptr, sizeof(pItemPtr));
+        
+        // Check if pItemPtr is in address range of this block.
+        if((pItemPtr >= block.pItems) && (pItemPtr < block.pItems + block.Capacity))
+        {
+            ptr->~T(); // Explicit destructor call.
+            const uint32_t index = static_cast<uint32_t>(pItemPtr - block.pItems);
+            pItemPtr->NextFreeIndex = block.FirstFreeIndex;
+            block.FirstFreeIndex = index;
+            return;
+        }
+    }
+    VMA_ASSERT(0 && "Pointer doesn't belong to this memory pool.");
+}
+
+template<typename T>
+typename VmaPoolAllocator<T>::ItemBlock& VmaPoolAllocator<T>::CreateNewBlock()
+{
+    const uint32_t newBlockCapacity = m_ItemBlocks.empty() ?
+        m_FirstBlockCapacity : m_ItemBlocks.back().Capacity * 3 / 2;
+
+    const ItemBlock newBlock = {
+        vma_new_array(m_pAllocationCallbacks, Item, newBlockCapacity),
+        newBlockCapacity,
+        0 };
+
+    m_ItemBlocks.push_back(newBlock);
+
+    // Setup singly-linked list of all free items in this block.
+    for(uint32_t i = 0; i < newBlockCapacity - 1; ++i)
+        newBlock.pItems[i].NextFreeIndex = i + 1;
+    newBlock.pItems[newBlockCapacity - 1].NextFreeIndex = UINT32_MAX;
+    return m_ItemBlocks.back();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// class VmaRawList, VmaList
+
+#if VMA_USE_STL_LIST
+
+#define VmaList std::list
+
+#else // #if VMA_USE_STL_LIST
+
+template<typename T>
+struct VmaListItem
+{
+    VmaListItem* pPrev;
+    VmaListItem* pNext;
+    T Value;
+};
+
+// Doubly linked list.
+template<typename T>
+class VmaRawList
+{
+    VMA_CLASS_NO_COPY(VmaRawList)
+public:
+    typedef VmaListItem<T> ItemType;
+
+    VmaRawList(const VkAllocationCallbacks* pAllocationCallbacks);
+    ~VmaRawList();
+    void Clear();
+
+    size_t GetCount() const { return m_Count; }
+    bool IsEmpty() const { return m_Count == 0; }
+
+    ItemType* Front() { return m_pFront; }
+    const ItemType* Front() const { return m_pFront; }
+    ItemType* Back() { return m_pBack; }
+    const ItemType* Back() const { return m_pBack; }
+
+    ItemType* PushBack();
+    ItemType* PushFront();
+    ItemType* PushBack(const T& value);
+    ItemType* PushFront(const T& value);
+    void PopBack();
+    void PopFront();
+    
+    // Item can be null - it means PushBack.
+    ItemType* InsertBefore(ItemType* pItem);
+    // Item can be null - it means PushFront.
+    ItemType* InsertAfter(ItemType* pItem);
+
+    ItemType* InsertBefore(ItemType* pItem, const T& value);
+    ItemType* InsertAfter(ItemType* pItem, const T& value);
+
+    void Remove(ItemType* pItem);
+
+private:
+    const VkAllocationCallbacks* const m_pAllocationCallbacks;
+    VmaPoolAllocator<ItemType> m_ItemAllocator;
+    ItemType* m_pFront;
+    ItemType* m_pBack;
+    size_t m_Count;
+};
+
+template<typename T>
+VmaRawList<T>::VmaRawList(const VkAllocationCallbacks* pAllocationCallbacks) :
+    m_pAllocationCallbacks(pAllocationCallbacks),
+    m_ItemAllocator(pAllocationCallbacks, 128),
+    m_pFront(VMA_NULL),
+    m_pBack(VMA_NULL),
+    m_Count(0)
+{
+}
+
+template<typename T>
+VmaRawList<T>::~VmaRawList()
+{
+    // Intentionally not calling Clear, because that would be unnecessary
+    // computations to return all items to m_ItemAllocator as free.
+}
+
+template<typename T>
+void VmaRawList<T>::Clear()
+{
+    if(IsEmpty() == false)
+    {
+        ItemType* pItem = m_pBack;
+        while(pItem != VMA_NULL)
+        {
+            ItemType* const pPrevItem = pItem->pPrev;
+            m_ItemAllocator.Free(pItem);
+            pItem = pPrevItem;
+        }
+        m_pFront = VMA_NULL;
+        m_pBack = VMA_NULL;
+        m_Count = 0;
+    }
+}
+
+template<typename T>
+VmaListItem<T>* VmaRawList<T>::PushBack()
+{
+    ItemType* const pNewItem = m_ItemAllocator.Alloc();
+    pNewItem->pNext = VMA_NULL;
+    if(IsEmpty())
+    {
+        pNewItem->pPrev = VMA_NULL;
+        m_pFront = pNewItem;
+        m_pBack = pNewItem;
+        m_Count = 1;
+    }
+    else
+    {
+        pNewItem->pPrev = m_pBack;
+        m_pBack->pNext = pNewItem;
+        m_pBack = pNewItem;
+        ++m_Count;
+    }
+    return pNewItem;
+}
+
+template<typename T>
+VmaListItem<T>* VmaRawList<T>::PushFront()
+{
+    ItemType* const pNewItem = m_ItemAllocator.Alloc();
+    pNewItem->pPrev = VMA_NULL;
+    if(IsEmpty())
+    {
+        pNewItem->pNext = VMA_NULL;
+        m_pFront = pNewItem;
+        m_pBack = pNewItem;
+        m_Count = 1;
+    }
+    else
+    {
+        pNewItem->pNext = m_pFront;
+        m_pFront->pPrev = pNewItem;
+        m_pFront = pNewItem;
+        ++m_Count;
+    }
+    return pNewItem;
+}
+
+template<typename T>
+VmaListItem<T>* VmaRawList<T>::PushBack(const T& value)
+{
+    ItemType* const pNewItem = PushBack();
+    pNewItem->Value = value;
+    return pNewItem;
+}
+
+template<typename T>
+VmaListItem<T>* VmaRawList<T>::PushFront(const T& value)
+{
+    ItemType* const pNewItem = PushFront();
+    pNewItem->Value = value;
+    return pNewItem;
+}
+
+template<typename T>
+void VmaRawList<T>::PopBack()
+{
+    VMA_HEAVY_ASSERT(m_Count > 0);
+    ItemType* const pBackItem = m_pBack;
+    ItemType* const pPrevItem = pBackItem->pPrev;
+    if(pPrevItem != VMA_NULL)
+    {
+        pPrevItem->pNext = VMA_NULL;
+    }
+    m_pBack = pPrevItem;
+    m_ItemAllocator.Free(pBackItem);
+    --m_Count;
+}
+
+template<typename T>
+void VmaRawList<T>::PopFront()
+{
+    VMA_HEAVY_ASSERT(m_Count > 0);
+    ItemType* const pFrontItem = m_pFront;
+    ItemType* const pNextItem = pFrontItem->pNext;
+    if(pNextItem != VMA_NULL)
+    {
+        pNextItem->pPrev = VMA_NULL;
+    }
+    m_pFront = pNextItem;
+    m_ItemAllocator.Free(pFrontItem);
+    --m_Count;
+}
+
+template<typename T>
+void VmaRawList<T>::Remove(ItemType* pItem)
+{
+    VMA_HEAVY_ASSERT(pItem != VMA_NULL);
+    VMA_HEAVY_ASSERT(m_Count > 0);
+
+    if(pItem->pPrev != VMA_NULL)
+    {
+        pItem->pPrev->pNext = pItem->pNext;
+    }
+    else
+    {
+        VMA_HEAVY_ASSERT(m_pFront == pItem);
+        m_pFront = pItem->pNext;
+    }
+
+    if(pItem->pNext != VMA_NULL)
+    {
+        pItem->pNext->pPrev = pItem->pPrev;
+    }
+    else
+    {
+        VMA_HEAVY_ASSERT(m_pBack == pItem);
+        m_pBack = pItem->pPrev;
+    }
+
+    m_ItemAllocator.Free(pItem);
+    --m_Count;
+}
+
+template<typename T>
+VmaListItem<T>* VmaRawList<T>::InsertBefore(ItemType* pItem)
+{
+    if(pItem != VMA_NULL)
+    {
+        ItemType* const prevItem = pItem->pPrev;
+        ItemType* const newItem = m_ItemAllocator.Alloc();
+        newItem->pPrev = prevItem;
+        newItem->pNext = pItem;
+        pItem->pPrev = newItem;
+        if(prevItem != VMA_NULL)
+        {
+            prevItem->pNext = newItem;
+        }
+        else
+        {
+            VMA_HEAVY_ASSERT(m_pFront == pItem);
+            m_pFront = newItem;
+        }
+        ++m_Count;
+        return newItem;
+    }
+    else
+        return PushBack();
+}
+
+template<typename T>
+VmaListItem<T>* VmaRawList<T>::InsertAfter(ItemType* pItem)
+{
+    if(pItem != VMA_NULL)
+    {
+        ItemType* const nextItem = pItem->pNext;
+        ItemType* const newItem = m_ItemAllocator.Alloc();
+        newItem->pNext = nextItem;
+        newItem->pPrev = pItem;
+        pItem->pNext = newItem;
+        if(nextItem != VMA_NULL)
+        {
+            nextItem->pPrev = newItem;
+        }
+        else
+        {
+            VMA_HEAVY_ASSERT(m_pBack == pItem);
+            m_pBack = newItem;
+        }
+        ++m_Count;
+        return newItem;
+    }
+    else
+        return PushFront();
+}
+
+template<typename T>
+VmaListItem<T>* VmaRawList<T>::InsertBefore(ItemType* pItem, const T& value)
+{
+    ItemType* const newItem = InsertBefore(pItem);
+    newItem->Value = value;
+    return newItem;
+}
+
+template<typename T>
+VmaListItem<T>* VmaRawList<T>::InsertAfter(ItemType* pItem, const T& value)
+{
+    ItemType* const newItem = InsertAfter(pItem);
+    newItem->Value = value;
+    return newItem;
+}
+
+template<typename T, typename AllocatorT>
+class VmaList
+{
+    VMA_CLASS_NO_COPY(VmaList)
+public:
+    class iterator
+    {
+    public:
+        iterator() :
+            m_pList(VMA_NULL),
+            m_pItem(VMA_NULL)
+        {
+        }
+
+        T& operator*() const
+        {
+            VMA_HEAVY_ASSERT(m_pItem != VMA_NULL);
+            return m_pItem->Value;
+        }
+        T* operator->() const
+        {
+            VMA_HEAVY_ASSERT(m_pItem != VMA_NULL);
+            return &m_pItem->Value;
+        }
+
+        iterator& operator++()
+        {
+            VMA_HEAVY_ASSERT(m_pItem != VMA_NULL);
+            m_pItem = m_pItem->pNext;
+            return *this;
+        }
+        iterator& operator--()
+        {
+            if(m_pItem != VMA_NULL)
+            {
+                m_pItem = m_pItem->pPrev;
+            }
+            else
+            {
+                VMA_HEAVY_ASSERT(!m_pList->IsEmpty());
+                m_pItem = m_pList->Back();
+            }
+            return *this;
+        }
+
+        iterator operator++(int)
+        {
+            iterator result = *this;
+            ++*this;
+            return result;
+        }
+        iterator operator--(int)
+        {
+            iterator result = *this;
+            --*this;
+            return result;
+        }
+
+        bool operator==(const iterator& rhs) const
+        {
+            VMA_HEAVY_ASSERT(m_pList == rhs.m_pList);
+            return m_pItem == rhs.m_pItem;
+        }
+        bool operator!=(const iterator& rhs) const
+        {
+            VMA_HEAVY_ASSERT(m_pList == rhs.m_pList);
+            return m_pItem != rhs.m_pItem;
+        }
+        
+    private:
+        VmaRawList<T>* m_pList;
+        VmaListItem<T>* m_pItem;
+
+        iterator(VmaRawList<T>* pList, VmaListItem<T>* pItem) :
+            m_pList(pList),
+            m_pItem(pItem)
+        {
+        }
+
+        friend class VmaList<T, AllocatorT>;
+    };
+
+    class const_iterator
+    {
+    public:
+        const_iterator() :
+            m_pList(VMA_NULL),
+            m_pItem(VMA_NULL)
+        {
+        }
+
+        const_iterator(const iterator& src) :
+            m_pList(src.m_pList),
+            m_pItem(src.m_pItem)
+        {
+        }
+        
+        const T& operator*() const
+        {
+            VMA_HEAVY_ASSERT(m_pItem != VMA_NULL);
+            return m_pItem->Value;
+        }
+        const T* operator->() const
+        {
+            VMA_HEAVY_ASSERT(m_pItem != VMA_NULL);
+            return &m_pItem->Value;
+        }
+
+        const_iterator& operator++()
+        {
+            VMA_HEAVY_ASSERT(m_pItem != VMA_NULL);
+            m_pItem = m_pItem->pNext;
+            return *this;
+        }
+        const_iterator& operator--()
+        {
+            if(m_pItem != VMA_NULL)
+            {
+                m_pItem = m_pItem->pPrev;
+            }
+            else
+            {
+                VMA_HEAVY_ASSERT(!m_pList->IsEmpty());
+                m_pItem = m_pList->Back();
+            }
+            return *this;
+        }
+
+        const_iterator operator++(int)
+        {
+            const_iterator result = *this;
+            ++*this;
+            return result;
+        }
+        const_iterator operator--(int)
+        {
+            const_iterator result = *this;
+            --*this;
+            return result;
+        }
+
+        bool operator==(const const_iterator& rhs) const
+        {
+            VMA_HEAVY_ASSERT(m_pList == rhs.m_pList);
+            return m_pItem == rhs.m_pItem;
+        }
+        bool operator!=(const const_iterator& rhs) const
+        {
+            VMA_HEAVY_ASSERT(m_pList == rhs.m_pList);
+            return m_pItem != rhs.m_pItem;
+        }
+        
+    private:
+        const_iterator(const VmaRawList<T>* pList, const VmaListItem<T>* pItem) :
+            m_pList(pList),
+            m_pItem(pItem)
+        {
+        }
+
+        const VmaRawList<T>* m_pList;
+        const VmaListItem<T>* m_pItem;
+
+        friend class VmaList<T, AllocatorT>;
+    };
+
+    VmaList(const AllocatorT& allocator) : m_RawList(allocator.m_pCallbacks) { }
+
+    bool empty() const { return m_RawList.IsEmpty(); }
+    size_t size() const { return m_RawList.GetCount(); }
+
+    iterator begin() { return iterator(&m_RawList, m_RawList.Front()); }
+    iterator end() { return iterator(&m_RawList, VMA_NULL); }
+
+    const_iterator cbegin() const { return const_iterator(&m_RawList, m_RawList.Front()); }
+    const_iterator cend() const { return const_iterator(&m_RawList, VMA_NULL); }
+
+    void clear() { m_RawList.Clear(); }
+    void push_back(const T& value) { m_RawList.PushBack(value); }
+    void erase(iterator it) { m_RawList.Remove(it.m_pItem); }
+    iterator insert(iterator it, const T& value) { return iterator(&m_RawList, m_RawList.InsertBefore(it.m_pItem, value)); }
+
+private:
+    VmaRawList<T> m_RawList;
+};
+
+#endif // #if VMA_USE_STL_LIST
+
+////////////////////////////////////////////////////////////////////////////////
+// class VmaMap
+
+// Unused in this version.
+#if 0
+
+#if VMA_USE_STL_UNORDERED_MAP
+
+#define VmaPair std::pair
+
+#define VMA_MAP_TYPE(KeyT, ValueT) \
+    std::unordered_map< KeyT, ValueT, std::hash<KeyT>, std::equal_to<KeyT>, VmaStlAllocator< std::pair<KeyT, ValueT> > >
+
+#else // #if VMA_USE_STL_UNORDERED_MAP
+
+template<typename T1, typename T2>
+struct VmaPair
+{
+    T1 first;
+    T2 second;
+
+    VmaPair() : first(), second() { }
+    VmaPair(const T1& firstSrc, const T2& secondSrc) : first(firstSrc), second(secondSrc) { }
+};
+
+/* Class compatible with subset of interface of std::unordered_map.
+KeyT, ValueT must be POD because they will be stored in VmaVector.
+*/
+template<typename KeyT, typename ValueT>
+class VmaMap
+{
+public:
+    typedef VmaPair<KeyT, ValueT> PairType;
+    typedef PairType* iterator;
+
+    VmaMap(const VmaStlAllocator<PairType>& allocator) : m_Vector(allocator) { }
+
+    iterator begin() { return m_Vector.begin(); }
+    iterator end() { return m_Vector.end(); }
+
+    void insert(const PairType& pair);
+    iterator find(const KeyT& key);
+    void erase(iterator it);
+    
+private:
+    VmaVector< PairType, VmaStlAllocator<PairType> > m_Vector;
+};
+
+#define VMA_MAP_TYPE(KeyT, ValueT) VmaMap<KeyT, ValueT>
+
+template<typename FirstT, typename SecondT>
+struct VmaPairFirstLess
+{
+    bool operator()(const VmaPair<FirstT, SecondT>& lhs, const VmaPair<FirstT, SecondT>& rhs) const
+    {
+        return lhs.first < rhs.first;
+    }
+    bool operator()(const VmaPair<FirstT, SecondT>& lhs, const FirstT& rhsFirst) const
+    {
+        return lhs.first < rhsFirst;
+    }
+};
+
+template<typename KeyT, typename ValueT>
+void VmaMap<KeyT, ValueT>::insert(const PairType& pair)
+{
+    const size_t indexToInsert = VmaBinaryFindFirstNotLess(
+        m_Vector.data(),
+        m_Vector.data() + m_Vector.size(),
+        pair,
+        VmaPairFirstLess<KeyT, ValueT>()) - m_Vector.data();
+    VmaVectorInsert(m_Vector, indexToInsert, pair);
+}
+
+template<typename KeyT, typename ValueT>
+VmaPair<KeyT, ValueT>* VmaMap<KeyT, ValueT>::find(const KeyT& key)
+{
+    PairType* it = VmaBinaryFindFirstNotLess(
+        m_Vector.data(),
+        m_Vector.data() + m_Vector.size(),
+        key,
+        VmaPairFirstLess<KeyT, ValueT>());
+    if((it != m_Vector.end()) && (it->first == key))
+    {
+        return it;
+    }
+    else
+    {
+        return m_Vector.end();
+    }
+}
+
+template<typename KeyT, typename ValueT>
+void VmaMap<KeyT, ValueT>::erase(iterator it)
+{
+    VmaVectorRemove(m_Vector, it - m_Vector.begin());
+}
+
+#endif // #if VMA_USE_STL_UNORDERED_MAP
+
+#endif // #if 0
+
+////////////////////////////////////////////////////////////////////////////////
+
+class VmaDeviceMemoryBlock;
+
+enum VMA_CACHE_OPERATION { VMA_CACHE_FLUSH, VMA_CACHE_INVALIDATE };
+
+struct VmaAllocation_T
+{
+private:
+    static const uint8_t MAP_COUNT_FLAG_PERSISTENT_MAP = 0x80;
+
+    enum FLAGS
+    {
+        FLAG_USER_DATA_STRING = 0x01,
+    };
+
+public:
+    enum ALLOCATION_TYPE
+    {
+        ALLOCATION_TYPE_NONE,
+        ALLOCATION_TYPE_BLOCK,
+        ALLOCATION_TYPE_DEDICATED,
+    };
+
+    /*
+    This struct is allocated using VmaPoolAllocator.
+    */
+
+    VmaAllocation_T(uint32_t currentFrameIndex, bool userDataString) :
+        m_Alignment{1},
+        m_Size{0},
+        m_pUserData{VMA_NULL},
+        m_LastUseFrameIndex{currentFrameIndex},
+        m_MemoryTypeIndex{0},
+        m_Type{(uint8_t)ALLOCATION_TYPE_NONE},
+        m_SuballocationType{(uint8_t)VMA_SUBALLOCATION_TYPE_UNKNOWN},
+        m_MapCount{0},
+        m_Flags{userDataString ? (uint8_t)FLAG_USER_DATA_STRING : (uint8_t)0}
+    {
+#if VMA_STATS_STRING_ENABLED
+        m_CreationFrameIndex = currentFrameIndex;
+        m_BufferImageUsage = 0;
+#endif
+    }
+
+    ~VmaAllocation_T()
+    {
+        VMA_ASSERT((m_MapCount & ~MAP_COUNT_FLAG_PERSISTENT_MAP) == 0 && "Allocation was not unmapped before destruction.");
+
+        // Check if owned string was freed.
+        VMA_ASSERT(m_pUserData == VMA_NULL);
+    }
+
+    void InitBlockAllocation(
+        VmaDeviceMemoryBlock* block,
+        VkDeviceSize offset,
+        VkDeviceSize alignment,
+        VkDeviceSize size,
+        uint32_t memoryTypeIndex,
+        VmaSuballocationType suballocationType,
+        bool mapped,
+        bool canBecomeLost)
+    {
+        VMA_ASSERT(m_Type == ALLOCATION_TYPE_NONE);
+        VMA_ASSERT(block != VMA_NULL);
+        m_Type = (uint8_t)ALLOCATION_TYPE_BLOCK;
+        m_Alignment = alignment;
+        m_Size = size;
+        m_MemoryTypeIndex = memoryTypeIndex;
+        m_MapCount = mapped ? MAP_COUNT_FLAG_PERSISTENT_MAP : 0;
+        m_SuballocationType = (uint8_t)suballocationType;
+        m_BlockAllocation.m_Block = block;
+        m_BlockAllocation.m_Offset = offset;
+        m_BlockAllocation.m_CanBecomeLost = canBecomeLost;
+    }
+
+    void InitLost()
+    {
+        VMA_ASSERT(m_Type == ALLOCATION_TYPE_NONE);
+        VMA_ASSERT(m_LastUseFrameIndex.load() == VMA_FRAME_INDEX_LOST);
+        m_Type = (uint8_t)ALLOCATION_TYPE_BLOCK;
+        m_MemoryTypeIndex = 0;
+        m_BlockAllocation.m_Block = VMA_NULL;
+        m_BlockAllocation.m_Offset = 0;
+        m_BlockAllocation.m_CanBecomeLost = true;
+    }
+
+    void ChangeBlockAllocation(
+        VmaAllocator hAllocator,
+        VmaDeviceMemoryBlock* block,
+        VkDeviceSize offset); 
+
+    void ChangeOffset(VkDeviceSize newOffset);
+
+    // pMappedData not null means allocation is created with MAPPED flag.
+    void InitDedicatedAllocation(
+        uint32_t memoryTypeIndex,
+        VkDeviceMemory hMemory,
+        VmaSuballocationType suballocationType,
+        void* pMappedData,
+        VkDeviceSize size)
+    {
+        VMA_ASSERT(m_Type == ALLOCATION_TYPE_NONE);
+        VMA_ASSERT(hMemory != VK_NULL_HANDLE);
+        m_Type = (uint8_t)ALLOCATION_TYPE_DEDICATED;
+        m_Alignment = 0;
+        m_Size = size;
+        m_MemoryTypeIndex = memoryTypeIndex;
+        m_SuballocationType = (uint8_t)suballocationType;
+        m_MapCount = (pMappedData != VMA_NULL) ? MAP_COUNT_FLAG_PERSISTENT_MAP : 0;
+        m_DedicatedAllocation.m_hMemory = hMemory;
+        m_DedicatedAllocation.m_pMappedData = pMappedData;
+    }
+
+    ALLOCATION_TYPE GetType() const { return (ALLOCATION_TYPE)m_Type; }
+    VkDeviceSize GetAlignment() const { return m_Alignment; }
+    VkDeviceSize GetSize() const { return m_Size; }
+    bool IsUserDataString() const { return (m_Flags & FLAG_USER_DATA_STRING) != 0; }
+    void* GetUserData() const { return m_pUserData; }
+    void SetUserData(VmaAllocator hAllocator, void* pUserData);
+    VmaSuballocationType GetSuballocationType() const { return (VmaSuballocationType)m_SuballocationType; }
+
+    VmaDeviceMemoryBlock* GetBlock() const
+    {
+        VMA_ASSERT(m_Type == ALLOCATION_TYPE_BLOCK);
+        return m_BlockAllocation.m_Block;
+    }
+    VkDeviceSize GetOffset() const;
+    VkDeviceMemory GetMemory() const;
+    uint32_t GetMemoryTypeIndex() const { return m_MemoryTypeIndex; }
+    bool IsPersistentMap() const { return (m_MapCount & MAP_COUNT_FLAG_PERSISTENT_MAP) != 0; }
+    void* GetMappedData() const;
+    bool CanBecomeLost() const;
+    
+    uint32_t GetLastUseFrameIndex() const
+    {
+        return m_LastUseFrameIndex.load();
+    }
+    bool CompareExchangeLastUseFrameIndex(uint32_t& expected, uint32_t desired)
+    {
+        return m_LastUseFrameIndex.compare_exchange_weak(expected, desired);
+    }
+    /*
+    - If hAllocation.LastUseFrameIndex + frameInUseCount < allocator.CurrentFrameIndex,
+      makes it lost by setting LastUseFrameIndex = VMA_FRAME_INDEX_LOST and returns true.
+    - Else, returns false.
+    
+    If hAllocation is already lost, assert - you should not call it then.
+    If hAllocation was not created with CAN_BECOME_LOST_BIT, assert.
+    */
+    bool MakeLost(uint32_t currentFrameIndex, uint32_t frameInUseCount);
+
+    void DedicatedAllocCalcStatsInfo(VmaStatInfo& outInfo)
+    {
+        VMA_ASSERT(m_Type == ALLOCATION_TYPE_DEDICATED);
+        outInfo.blockCount = 1;
+        outInfo.allocationCount = 1;
+        outInfo.unusedRangeCount = 0;
+        outInfo.usedBytes = m_Size;
+        outInfo.unusedBytes = 0;
+        outInfo.allocationSizeMin = outInfo.allocationSizeMax = m_Size;
+        outInfo.unusedRangeSizeMin = UINT64_MAX;
+        outInfo.unusedRangeSizeMax = 0;
+    }
+
+    void BlockAllocMap();
+    void BlockAllocUnmap();
+    VkResult DedicatedAllocMap(VmaAllocator hAllocator, void** ppData);
+    void DedicatedAllocUnmap(VmaAllocator hAllocator);
+
+#if VMA_STATS_STRING_ENABLED
+    uint32_t GetCreationFrameIndex() const { return m_CreationFrameIndex; }
+    uint32_t GetBufferImageUsage() const { return m_BufferImageUsage; }
+
+    void InitBufferImageUsage(uint32_t bufferImageUsage)
+    {
+        VMA_ASSERT(m_BufferImageUsage == 0);
+        m_BufferImageUsage = bufferImageUsage;
+    }
+
+    void PrintParameters(class VmaJsonWriter& json) const;
+#endif
+
+private:
+    VkDeviceSize m_Alignment;
+    VkDeviceSize m_Size;
+    void* m_pUserData;
+    VMA_ATOMIC_UINT32 m_LastUseFrameIndex;
+    uint32_t m_MemoryTypeIndex;
+    uint8_t m_Type; // ALLOCATION_TYPE
+    uint8_t m_SuballocationType; // VmaSuballocationType
+    // Bit 0x80 is set when allocation was created with VMA_ALLOCATION_CREATE_MAPPED_BIT.
+    // Bits with mask 0x7F are reference counter for vmaMapMemory()/vmaUnmapMemory().
+    uint8_t m_MapCount;
+    uint8_t m_Flags; // enum FLAGS
+
+    // Allocation out of VmaDeviceMemoryBlock.
+    struct BlockAllocation
+    {
+        VmaDeviceMemoryBlock* m_Block;
+        VkDeviceSize m_Offset;
+        bool m_CanBecomeLost;
+    };
+
+    // Allocation for an object that has its own private VkDeviceMemory.
+    struct DedicatedAllocation
+    {
+        VkDeviceMemory m_hMemory;
+        void* m_pMappedData; // Not null means memory is mapped.
+    };
+
+    union
+    {
+        // Allocation out of VmaDeviceMemoryBlock.
+        BlockAllocation m_BlockAllocation;
+        // Allocation for an object that has its own private VkDeviceMemory.
+        DedicatedAllocation m_DedicatedAllocation;
+    };
+
+#if VMA_STATS_STRING_ENABLED
+    uint32_t m_CreationFrameIndex;
+    uint32_t m_BufferImageUsage; // 0 if unknown.
+#endif
+
+    void FreeUserDataString(VmaAllocator hAllocator);
+};
+
+/*
+Represents a region of VmaDeviceMemoryBlock that is either assigned and returned as
+allocated memory block or free.
+*/
+struct VmaSuballocation
+{
+    VkDeviceSize offset;
+    VkDeviceSize size;
+    VmaAllocation hAllocation;
+    VmaSuballocationType type;
+};
+
+// Comparator for offsets.
+struct VmaSuballocationOffsetLess
+{
+    bool operator()(const VmaSuballocation& lhs, const VmaSuballocation& rhs) const
+    {
+        return lhs.offset < rhs.offset;
+    }
+};
+struct VmaSuballocationOffsetGreater
+{
+    bool operator()(const VmaSuballocation& lhs, const VmaSuballocation& rhs) const
+    {
+        return lhs.offset > rhs.offset;
+    }
+};
+
+typedef VmaList< VmaSuballocation, VmaStlAllocator<VmaSuballocation> > VmaSuballocationList;
+
+// Cost of one additional allocation lost, as equivalent in bytes.
+static const VkDeviceSize VMA_LOST_ALLOCATION_COST = 1048576;
+
+enum class VmaAllocationRequestType
+{
+    Normal,
+    // Used by "Linear" algorithm.
+    UpperAddress,
+    EndOf1st,
+    EndOf2nd,
+};
+
+/*
+Parameters of planned allocation inside a VmaDeviceMemoryBlock.
+
+If canMakeOtherLost was false:
+- item points to a FREE suballocation.
+- itemsToMakeLostCount is 0.
+
+If canMakeOtherLost was true:
+- item points to first of sequence of suballocations, which are either FREE,
+  or point to VmaAllocations that can become lost.
+- itemsToMakeLostCount is the number of VmaAllocations that need to be made lost for
+  the requested allocation to succeed.
+*/
+struct VmaAllocationRequest
+{
+    VkDeviceSize offset;
+    VkDeviceSize sumFreeSize; // Sum size of free items that overlap with proposed allocation.
+    VkDeviceSize sumItemSize; // Sum size of items to make lost that overlap with proposed allocation.
+    VmaSuballocationList::iterator item;
+    size_t itemsToMakeLostCount;
+    void* customData;
+    VmaAllocationRequestType type;
+
+    VkDeviceSize CalcCost() const
+    {
+        return sumItemSize + itemsToMakeLostCount * VMA_LOST_ALLOCATION_COST;
+    }
+};
+
+/*
+Data structure used for bookkeeping of allocations and unused ranges of memory
+in a single VkDeviceMemory block.
+*/
+class VmaBlockMetadata
+{
+public:
+    VmaBlockMetadata(VmaAllocator hAllocator);
+    virtual ~VmaBlockMetadata() { }
+    virtual void Init(VkDeviceSize size) { m_Size = size; }
+
+    // Validates all data structures inside this object. If not valid, returns false.
+    virtual bool Validate() const = 0;
+    VkDeviceSize GetSize() const { return m_Size; }
+    virtual size_t GetAllocationCount() const = 0;
+    virtual VkDeviceSize GetSumFreeSize() const = 0;
+    virtual VkDeviceSize GetUnusedRangeSizeMax() const = 0;
+    // Returns true if this block is empty - contains only single free suballocation.
+    virtual bool IsEmpty() const = 0;
+
+    virtual void CalcAllocationStatInfo(VmaStatInfo& outInfo) const = 0;
+    // Shouldn't modify blockCount.
+    virtual void AddPoolStats(VmaPoolStats& inoutStats) const = 0;
+
+#if VMA_STATS_STRING_ENABLED
+    virtual void PrintDetailedMap(class VmaJsonWriter& json) const = 0;
+#endif
+
+    // Tries to find a place for suballocation with given parameters inside this block.
+    // If succeeded, fills pAllocationRequest and returns true.
+    // If failed, returns false.
+    virtual bool CreateAllocationRequest(
+        uint32_t currentFrameIndex,
+        uint32_t frameInUseCount,
+        VkDeviceSize bufferImageGranularity,
+        VkDeviceSize allocSize,
+        VkDeviceSize allocAlignment,
+        bool upperAddress,
+        VmaSuballocationType allocType,
+        bool canMakeOtherLost,
+        // Always one of VMA_ALLOCATION_CREATE_STRATEGY_* or VMA_ALLOCATION_INTERNAL_STRATEGY_* flags.
+        uint32_t strategy,
+        VmaAllocationRequest* pAllocationRequest) = 0;
+
+    virtual bool MakeRequestedAllocationsLost(
+        uint32_t currentFrameIndex,
+        uint32_t frameInUseCount,
+        VmaAllocationRequest* pAllocationRequest) = 0;
+
+    virtual uint32_t MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount) = 0;
+
+    virtual VkResult CheckCorruption(const void* pBlockData) = 0;
+
+    // Makes actual allocation based on request. Request must already be checked and valid.
+    virtual void Alloc(
+        const VmaAllocationRequest& request,
+        VmaSuballocationType type,
+        VkDeviceSize allocSize,
+        VmaAllocation hAllocation) = 0;
+
+    // Frees suballocation assigned to given memory region.
+    virtual void Free(const VmaAllocation allocation) = 0;
+    virtual void FreeAtOffset(VkDeviceSize offset) = 0;
+
+protected:
+    const VkAllocationCallbacks* GetAllocationCallbacks() const { return m_pAllocationCallbacks; }
+
+#if VMA_STATS_STRING_ENABLED
+    void PrintDetailedMap_Begin(class VmaJsonWriter& json,
+        VkDeviceSize unusedBytes,
+        size_t allocationCount,
+        size_t unusedRangeCount) const;
+    void PrintDetailedMap_Allocation(class VmaJsonWriter& json,
+        VkDeviceSize offset,
+        VmaAllocation hAllocation) const;
+    void PrintDetailedMap_UnusedRange(class VmaJsonWriter& json,
+        VkDeviceSize offset,
+        VkDeviceSize size) const;
+    void PrintDetailedMap_End(class VmaJsonWriter& json) const;
+#endif
+
+private:
+    VkDeviceSize m_Size;
+    const VkAllocationCallbacks* m_pAllocationCallbacks;
+};
+
+#define VMA_VALIDATE(cond) do { if(!(cond)) { \
+        VMA_ASSERT(0 && "Validation failed: " #cond); \
+        return false; \
+    } } while(false)
+
+class VmaBlockMetadata_Generic : public VmaBlockMetadata
+{
+    VMA_CLASS_NO_COPY(VmaBlockMetadata_Generic)
+public:
+    VmaBlockMetadata_Generic(VmaAllocator hAllocator);
+    virtual ~VmaBlockMetadata_Generic();
+    virtual void Init(VkDeviceSize size);
+
+    virtual bool Validate() const;
+    virtual size_t GetAllocationCount() const { return m_Suballocations.size() - m_FreeCount; }
+    virtual VkDeviceSize GetSumFreeSize() const { return m_SumFreeSize; }
+    virtual VkDeviceSize GetUnusedRangeSizeMax() const;
+    virtual bool IsEmpty() const;
+
+    virtual void CalcAllocationStatInfo(VmaStatInfo& outInfo) const;
+    virtual void AddPoolStats(VmaPoolStats& inoutStats) const;
+
+#if VMA_STATS_STRING_ENABLED
+    virtual void PrintDetailedMap(class VmaJsonWriter& json) const;
+#endif
+
+    virtual bool CreateAllocationRequest(
+        uint32_t currentFrameIndex,
+        uint32_t frameInUseCount,
+        VkDeviceSize bufferImageGranularity,
+        VkDeviceSize allocSize,
+        VkDeviceSize allocAlignment,
+        bool upperAddress,
+        VmaSuballocationType allocType,
+        bool canMakeOtherLost,
+        uint32_t strategy,
+        VmaAllocationRequest* pAllocationRequest);
+
+    virtual bool MakeRequestedAllocationsLost(
+        uint32_t currentFrameIndex,
+        uint32_t frameInUseCount,
+        VmaAllocationRequest* pAllocationRequest);
+
+    virtual uint32_t MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount);
+
+    virtual VkResult CheckCorruption(const void* pBlockData);
+
+    virtual void Alloc(
+        const VmaAllocationRequest& request,
+        VmaSuballocationType type,
+        VkDeviceSize allocSize,
+        VmaAllocation hAllocation);
+
+    virtual void Free(const VmaAllocation allocation);
+    virtual void FreeAtOffset(VkDeviceSize offset);
+
+    ////////////////////////////////////////////////////////////////////////////////
+    // For defragmentation
+    
+    bool IsBufferImageGranularityConflictPossible(
+        VkDeviceSize bufferImageGranularity,
+        VmaSuballocationType& inOutPrevSuballocType) const;
+
+private:
+    friend class VmaDefragmentationAlgorithm_Generic;
+    friend class VmaDefragmentationAlgorithm_Fast;
+
+    uint32_t m_FreeCount;
+    VkDeviceSize m_SumFreeSize;
+    VmaSuballocationList m_Suballocations;
+    // Suballocations that are free and have size greater than certain threshold.
+    // Sorted by size, ascending.
+    VmaVector< VmaSuballocationList::iterator, VmaStlAllocator< VmaSuballocationList::iterator > > m_FreeSuballocationsBySize;
+
+    bool ValidateFreeSuballocationList() const;
+
+    // Checks if requested suballocation with given parameters can be placed in given pFreeSuballocItem.
+    // If yes, fills pOffset and returns true. If no, returns false.
+    bool CheckAllocation(
+        uint32_t currentFrameIndex,
+        uint32_t frameInUseCount,
+        VkDeviceSize bufferImageGranularity,
+        VkDeviceSize allocSize,
+        VkDeviceSize allocAlignment,
+        VmaSuballocationType allocType,
+        VmaSuballocationList::const_iterator suballocItem,
+        bool canMakeOtherLost,
+        VkDeviceSize* pOffset,
+        size_t* itemsToMakeLostCount,
+        VkDeviceSize* pSumFreeSize,
+        VkDeviceSize* pSumItemSize) const;
+    // Given free suballocation, it merges it with following one, which must also be free.
+    void MergeFreeWithNext(VmaSuballocationList::iterator item);
+    // Releases given suballocation, making it free.
+    // Merges it with adjacent free suballocations if applicable.
+    // Returns iterator to new free suballocation at this place.
+    VmaSuballocationList::iterator FreeSuballocation(VmaSuballocationList::iterator suballocItem);
+    // Given free suballocation, it inserts it into sorted list of
+    // m_FreeSuballocationsBySize if it's suitable.
+    void RegisterFreeSuballocation(VmaSuballocationList::iterator item);
+    // Given free suballocation, it removes it from sorted list of
+    // m_FreeSuballocationsBySize if it's suitable.
+    void UnregisterFreeSuballocation(VmaSuballocationList::iterator item);
+};
+
+/*
+Allocations and their references in internal data structure look like this:
+
+if(m_2ndVectorMode == SECOND_VECTOR_EMPTY):
+
+        0 +-------+
+          |       |
+          |       |
+          |       |
+          +-------+
+          | Alloc |  1st[m_1stNullItemsBeginCount]
+          +-------+
+          | Alloc |  1st[m_1stNullItemsBeginCount + 1]
+          +-------+
+          |  ...  |
+          +-------+
+          | Alloc |  1st[1st.size() - 1]
+          +-------+
+          |       |
+          |       |
+          |       |
+GetSize() +-------+
+
+if(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER):
+
+        0 +-------+
+          | Alloc |  2nd[0]
+          +-------+
+          | Alloc |  2nd[1]
+          +-------+
+          |  ...  |
+          +-------+
+          | Alloc |  2nd[2nd.size() - 1]
+          +-------+
+          |       |
+          |       |
+          |       |
+          +-------+
+          | Alloc |  1st[m_1stNullItemsBeginCount]
+          +-------+
+          | Alloc |  1st[m_1stNullItemsBeginCount + 1]
+          +-------+
+          |  ...  |
+          +-------+
+          | Alloc |  1st[1st.size() - 1]
+          +-------+
+          |       |
+GetSize() +-------+
+
+if(m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK):
+
+        0 +-------+
+          |       |
+          |       |
+          |       |
+          +-------+
+          | Alloc |  1st[m_1stNullItemsBeginCount]
+          +-------+
+          | Alloc |  1st[m_1stNullItemsBeginCount + 1]
+          +-------+
+          |  ...  |
+          +-------+
+          | Alloc |  1st[1st.size() - 1]
+          +-------+
+          |       |
+          |       |
+          |       |
+          +-------+
+          | Alloc |  2nd[2nd.size() - 1]
+          +-------+
+          |  ...  |
+          +-------+
+          | Alloc |  2nd[1]
+          +-------+
+          | Alloc |  2nd[0]
+GetSize() +-------+
+
+*/
+class VmaBlockMetadata_Linear : public VmaBlockMetadata
+{
+    VMA_CLASS_NO_COPY(VmaBlockMetadata_Linear)
+public:
+    VmaBlockMetadata_Linear(VmaAllocator hAllocator);
+    virtual ~VmaBlockMetadata_Linear();
+    virtual void Init(VkDeviceSize size);
+
+    virtual bool Validate() const;
+    virtual size_t GetAllocationCount() const;
+    virtual VkDeviceSize GetSumFreeSize() const { return m_SumFreeSize; }
+    virtual VkDeviceSize GetUnusedRangeSizeMax() const;
+    virtual bool IsEmpty() const { return GetAllocationCount() == 0; }
+
+    virtual void CalcAllocationStatInfo(VmaStatInfo& outInfo) const;
+    virtual void AddPoolStats(VmaPoolStats& inoutStats) const;
+
+#if VMA_STATS_STRING_ENABLED
+    virtual void PrintDetailedMap(class VmaJsonWriter& json) const;
+#endif
+
+    virtual bool CreateAllocationRequest(
+        uint32_t currentFrameIndex,
+        uint32_t frameInUseCount,
+        VkDeviceSize bufferImageGranularity,
+        VkDeviceSize allocSize,
+        VkDeviceSize allocAlignment,
+        bool upperAddress,
+        VmaSuballocationType allocType,
+        bool canMakeOtherLost,
+        uint32_t strategy,
+        VmaAllocationRequest* pAllocationRequest);
+
+    virtual bool MakeRequestedAllocationsLost(
+        uint32_t currentFrameIndex,
+        uint32_t frameInUseCount,
+        VmaAllocationRequest* pAllocationRequest);
+
+    virtual uint32_t MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount);
+
+    virtual VkResult CheckCorruption(const void* pBlockData);
+
+    virtual void Alloc(
+        const VmaAllocationRequest& request,
+        VmaSuballocationType type,
+        VkDeviceSize allocSize,
+        VmaAllocation hAllocation);
+
+    virtual void Free(const VmaAllocation allocation);
+    virtual void FreeAtOffset(VkDeviceSize offset);
+
+private:
+    /*
+    There are two suballocation vectors, used in ping-pong way.
+    The one with index m_1stVectorIndex is called 1st.
+    The one with index (m_1stVectorIndex ^ 1) is called 2nd.
+    2nd can be non-empty only when 1st is not empty.
+    When 2nd is not empty, m_2ndVectorMode indicates its mode of operation.
+    */
+    typedef VmaVector< VmaSuballocation, VmaStlAllocator<VmaSuballocation> > SuballocationVectorType;
+
+    enum SECOND_VECTOR_MODE
+    {
+        SECOND_VECTOR_EMPTY,
+        /*
+        Suballocations in 2nd vector are created later than the ones in 1st, but they
+        all have smaller offset.
+        */
+        SECOND_VECTOR_RING_BUFFER,
+        /*
+        Suballocations in 2nd vector are upper side of double stack.
+        They all have offsets higher than those in 1st vector.
+        Top of this stack means smaller offsets, but higher indices in this vector.
+        */
+        SECOND_VECTOR_DOUBLE_STACK,
+    };
+
+    VkDeviceSize m_SumFreeSize;
+    SuballocationVectorType m_Suballocations0, m_Suballocations1;
+    uint32_t m_1stVectorIndex;
+    SECOND_VECTOR_MODE m_2ndVectorMode;
+
+    SuballocationVectorType& AccessSuballocations1st() { return m_1stVectorIndex ? m_Suballocations1 : m_Suballocations0; }
+    SuballocationVectorType& AccessSuballocations2nd() { return m_1stVectorIndex ? m_Suballocations0 : m_Suballocations1; }
+    const SuballocationVectorType& AccessSuballocations1st() const { return m_1stVectorIndex ? m_Suballocations1 : m_Suballocations0; }
+    const SuballocationVectorType& AccessSuballocations2nd() const { return m_1stVectorIndex ? m_Suballocations0 : m_Suballocations1; }
+    
+    // Number of items in 1st vector with hAllocation = null at the beginning.
+    size_t m_1stNullItemsBeginCount;
+    // Number of other items in 1st vector with hAllocation = null somewhere in the middle.
+    size_t m_1stNullItemsMiddleCount;
+    // Number of items in 2nd vector with hAllocation = null.
+    size_t m_2ndNullItemsCount;
+
+    bool ShouldCompact1st() const;
+    void CleanupAfterFree();
+
+    bool CreateAllocationRequest_LowerAddress(
+        uint32_t currentFrameIndex,
+        uint32_t frameInUseCount,
+        VkDeviceSize bufferImageGranularity,
+        VkDeviceSize allocSize,
+        VkDeviceSize allocAlignment,
+        VmaSuballocationType allocType,
+        bool canMakeOtherLost,
+        uint32_t strategy,
+        VmaAllocationRequest* pAllocationRequest);
+    bool CreateAllocationRequest_UpperAddress(
+        uint32_t currentFrameIndex,
+        uint32_t frameInUseCount,
+        VkDeviceSize bufferImageGranularity,
+        VkDeviceSize allocSize,
+        VkDeviceSize allocAlignment,
+        VmaSuballocationType allocType,
+        bool canMakeOtherLost,
+        uint32_t strategy,
+        VmaAllocationRequest* pAllocationRequest);
+};
+
+/*
+- GetSize() is the original size of allocated memory block.
+- m_UsableSize is this size aligned down to a power of two.
+  All allocations and calculations happen relative to m_UsableSize.
+- GetUnusableSize() is the difference between them.
+  It is repoted as separate, unused range, not available for allocations.
+
+Node at level 0 has size = m_UsableSize.
+Each next level contains nodes with size 2 times smaller than current level.
+m_LevelCount is the maximum number of levels to use in the current object.
+*/
+class VmaBlockMetadata_Buddy : public VmaBlockMetadata
+{
+    VMA_CLASS_NO_COPY(VmaBlockMetadata_Buddy)
+public:
+    VmaBlockMetadata_Buddy(VmaAllocator hAllocator);
+    virtual ~VmaBlockMetadata_Buddy();
+    virtual void Init(VkDeviceSize size);
+
+    virtual bool Validate() const;
+    virtual size_t GetAllocationCount() const { return m_AllocationCount; }
+    virtual VkDeviceSize GetSumFreeSize() const { return m_SumFreeSize + GetUnusableSize(); }
+    virtual VkDeviceSize GetUnusedRangeSizeMax() const;
+    virtual bool IsEmpty() const { return m_Root->type == Node::TYPE_FREE; }
+
+    virtual void CalcAllocationStatInfo(VmaStatInfo& outInfo) const;
+    virtual void AddPoolStats(VmaPoolStats& inoutStats) const;
+
+#if VMA_STATS_STRING_ENABLED
+    virtual void PrintDetailedMap(class VmaJsonWriter& json) const;
+#endif
+
+    virtual bool CreateAllocationRequest(
+        uint32_t currentFrameIndex,
+        uint32_t frameInUseCount,
+        VkDeviceSize bufferImageGranularity,
+        VkDeviceSize allocSize,
+        VkDeviceSize allocAlignment,
+        bool upperAddress,
+        VmaSuballocationType allocType,
+        bool canMakeOtherLost,
+        uint32_t strategy,
+        VmaAllocationRequest* pAllocationRequest);
+
+    virtual bool MakeRequestedAllocationsLost(
+        uint32_t currentFrameIndex,
+        uint32_t frameInUseCount,
+        VmaAllocationRequest* pAllocationRequest);
+
+    virtual uint32_t MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount);
+
+    virtual VkResult CheckCorruption(const void* pBlockData) { return VK_ERROR_FEATURE_NOT_PRESENT; }
+
+    virtual void Alloc(
+        const VmaAllocationRequest& request,
+        VmaSuballocationType type,
+        VkDeviceSize allocSize,
+        VmaAllocation hAllocation);
+
+    virtual void Free(const VmaAllocation allocation) { FreeAtOffset(allocation, allocation->GetOffset()); }
+    virtual void FreeAtOffset(VkDeviceSize offset) { FreeAtOffset(VMA_NULL, offset); }
+
+private:
+    static const VkDeviceSize MIN_NODE_SIZE = 32;
+    static const size_t MAX_LEVELS = 30;
+
+    struct ValidationContext
+    {
+        size_t calculatedAllocationCount;
+        size_t calculatedFreeCount;
+        VkDeviceSize calculatedSumFreeSize;
+
+        ValidationContext() :
+            calculatedAllocationCount(0),
+            calculatedFreeCount(0),
+            calculatedSumFreeSize(0) { }
+    };
+
+    struct Node
+    {
+        VkDeviceSize offset;
+        enum TYPE
+        {
+            TYPE_FREE,
+            TYPE_ALLOCATION,
+            TYPE_SPLIT,
+            TYPE_COUNT
+        } type;
+        Node* parent;
+        Node* buddy;
+
+        union
+        {
+            struct
+            {
+                Node* prev;
+                Node* next;
+            } free;
+            struct
+            {
+                VmaAllocation alloc;
+            } allocation;
+            struct
+            {
+                Node* leftChild;
+            } split;
+        };
+    };
+
+    // Size of the memory block aligned down to a power of two.
+    VkDeviceSize m_UsableSize;
+    uint32_t m_LevelCount;
+
+    Node* m_Root;
+    struct {
+        Node* front;
+        Node* back;
+    } m_FreeList[MAX_LEVELS];
+    // Number of nodes in the tree with type == TYPE_ALLOCATION.
+    size_t m_AllocationCount;
+    // Number of nodes in the tree with type == TYPE_FREE.
+    size_t m_FreeCount;
+    // This includes space wasted due to internal fragmentation. Doesn't include unusable size.
+    VkDeviceSize m_SumFreeSize;
+
+    VkDeviceSize GetUnusableSize() const { return GetSize() - m_UsableSize; }
+    void DeleteNode(Node* node);
+    bool ValidateNode(ValidationContext& ctx, const Node* parent, const Node* curr, uint32_t level, VkDeviceSize levelNodeSize) const;
+    uint32_t AllocSizeToLevel(VkDeviceSize allocSize) const;
+    inline VkDeviceSize LevelToNodeSize(uint32_t level) const { return m_UsableSize >> level; }
+    // Alloc passed just for validation. Can be null.
+    void FreeAtOffset(VmaAllocation alloc, VkDeviceSize offset);
+    void CalcAllocationStatInfoNode(VmaStatInfo& outInfo, const Node* node, VkDeviceSize levelNodeSize) const;
+    // Adds node to the front of FreeList at given level.
+    // node->type must be FREE.
+    // node->free.prev, next can be undefined.
+    void AddToFreeListFront(uint32_t level, Node* node);
+    // Removes node from FreeList at given level.
+    // node->type must be FREE.
+    // node->free.prev, next stay untouched.
+    void RemoveFromFreeList(uint32_t level, Node* node);
+
+#if VMA_STATS_STRING_ENABLED
+    void PrintDetailedMapNode(class VmaJsonWriter& json, const Node* node, VkDeviceSize levelNodeSize) const;
+#endif
+};
+
+/*
+Represents a single block of device memory (`VkDeviceMemory`) with all the
+data about its regions (aka suballocations, #VmaAllocation), assigned and free.
+
+Thread-safety: This class must be externally synchronized.
+*/
+class VmaDeviceMemoryBlock
+{
+    VMA_CLASS_NO_COPY(VmaDeviceMemoryBlock)
+public:
+    VmaBlockMetadata* m_pMetadata;
+
+    VmaDeviceMemoryBlock(VmaAllocator hAllocator);
+
+    ~VmaDeviceMemoryBlock()
+    {
+        VMA_ASSERT(m_MapCount == 0 && "VkDeviceMemory block is being destroyed while it is still mapped.");
+        VMA_ASSERT(m_hMemory == VK_NULL_HANDLE);
+    }
+
+    // Always call after construction.
+    void Init(
+        VmaAllocator hAllocator,
+        VmaPool hParentPool,
+        uint32_t newMemoryTypeIndex,
+        VkDeviceMemory newMemory,
+        VkDeviceSize newSize,
+        uint32_t id,
+        uint32_t algorithm);
+    // Always call before destruction.
+    void Destroy(VmaAllocator allocator);
+    
+    VmaPool GetParentPool() const { return m_hParentPool; }
+    VkDeviceMemory GetDeviceMemory() const { return m_hMemory; }
+    uint32_t GetMemoryTypeIndex() const { return m_MemoryTypeIndex; }
+    uint32_t GetId() const { return m_Id; }
+    void* GetMappedData() const { return m_pMappedData; }
+
+    // Validates all data structures inside this object. If not valid, returns false.
+    bool Validate() const;
+
+    VkResult CheckCorruption(VmaAllocator hAllocator);
+
+    // ppData can be null.
+    VkResult Map(VmaAllocator hAllocator, uint32_t count, void** ppData);
+    void Unmap(VmaAllocator hAllocator, uint32_t count);
+
+    VkResult WriteMagicValueAroundAllocation(VmaAllocator hAllocator, VkDeviceSize allocOffset, VkDeviceSize allocSize);
+    VkResult ValidateMagicValueAroundAllocation(VmaAllocator hAllocator, VkDeviceSize allocOffset, VkDeviceSize allocSize);
+
+    VkResult BindBufferMemory(
+        const VmaAllocator hAllocator,
+        const VmaAllocation hAllocation,
+        VkDeviceSize allocationLocalOffset,
+        VkBuffer hBuffer,
+        const void* pNext);
+    VkResult BindImageMemory(
+        const VmaAllocator hAllocator,
+        const VmaAllocation hAllocation,
+        VkDeviceSize allocationLocalOffset,
+        VkImage hImage,
+        const void* pNext);
+
+private:
+    VmaPool m_hParentPool; // VK_NULL_HANDLE if not belongs to custom pool.
+    uint32_t m_MemoryTypeIndex;
+    uint32_t m_Id;
+    VkDeviceMemory m_hMemory;
+
+    /*
+    Protects access to m_hMemory so it's not used by multiple threads simultaneously, e.g. vkMapMemory, vkBindBufferMemory.
+    Also protects m_MapCount, m_pMappedData.
+    Allocations, deallocations, any change in m_pMetadata is protected by parent's VmaBlockVector::m_Mutex.
+    */
+    VMA_MUTEX m_Mutex;
+    uint32_t m_MapCount;
+    void* m_pMappedData;
+};
+
+struct VmaPointerLess
+{
+    bool operator()(const void* lhs, const void* rhs) const
+    {
+        return lhs < rhs;
+    }
+};
+
+struct VmaDefragmentationMove
+{
+    size_t srcBlockIndex;
+    size_t dstBlockIndex;
+    VkDeviceSize srcOffset;
+    VkDeviceSize dstOffset;
+    VkDeviceSize size;
+    VmaAllocation hAllocation;
+    VmaDeviceMemoryBlock* pSrcBlock;
+    VmaDeviceMemoryBlock* pDstBlock;
+};
+
+class VmaDefragmentationAlgorithm;
+
+/*
+Sequence of VmaDeviceMemoryBlock. Represents memory blocks allocated for a specific
+Vulkan memory type.
+
+Synchronized internally with a mutex.
+*/
+struct VmaBlockVector
+{
+    VMA_CLASS_NO_COPY(VmaBlockVector)
+public:
+    VmaBlockVector(
+        VmaAllocator hAllocator,
+        VmaPool hParentPool,
+        uint32_t memoryTypeIndex,
+        VkDeviceSize preferredBlockSize,
+        size_t minBlockCount,
+        size_t maxBlockCount,
+        VkDeviceSize bufferImageGranularity,
+        uint32_t frameInUseCount,
+        bool explicitBlockSize,
+        uint32_t algorithm);
+    ~VmaBlockVector();
+
+    VkResult CreateMinBlocks();
+
+    VmaAllocator GetAllocator() const { return m_hAllocator; }
+    VmaPool GetParentPool() const { return m_hParentPool; }
+    bool IsCustomPool() const { return m_hParentPool != VMA_NULL; }
+    uint32_t GetMemoryTypeIndex() const { return m_MemoryTypeIndex; }
+    VkDeviceSize GetPreferredBlockSize() const { return m_PreferredBlockSize; }
+    VkDeviceSize GetBufferImageGranularity() const { return m_BufferImageGranularity; }
+    uint32_t GetFrameInUseCount() const { return m_FrameInUseCount; }
+    uint32_t GetAlgorithm() const { return m_Algorithm; }
+
+    void GetPoolStats(VmaPoolStats* pStats);
+
+    bool IsEmpty();
+    bool IsCorruptionDetectionEnabled() const;
+
+    VkResult Allocate(
+        uint32_t currentFrameIndex,
+        VkDeviceSize size,
+        VkDeviceSize alignment,
+        const VmaAllocationCreateInfo& createInfo,
+        VmaSuballocationType suballocType,
+        size_t allocationCount,
+        VmaAllocation* pAllocations);
+
+    void Free(const VmaAllocation hAllocation);
+
+    // Adds statistics of this BlockVector to pStats.
+    void AddStats(VmaStats* pStats);
+
+#if VMA_STATS_STRING_ENABLED
+    void PrintDetailedMap(class VmaJsonWriter& json);
+#endif
+
+    void MakePoolAllocationsLost(
+        uint32_t currentFrameIndex,
+        size_t* pLostAllocationCount);
+    VkResult CheckCorruption();
+
+    // Saves results in pCtx->res.
+    void Defragment(
+        class VmaBlockVectorDefragmentationContext* pCtx,
+        VmaDefragmentationStats* pStats, VmaDefragmentationFlags flags,
+        VkDeviceSize& maxCpuBytesToMove, uint32_t& maxCpuAllocationsToMove,
+        VkDeviceSize& maxGpuBytesToMove, uint32_t& maxGpuAllocationsToMove,
+        VkCommandBuffer commandBuffer);
+    void DefragmentationEnd(
+        class VmaBlockVectorDefragmentationContext* pCtx,
+        uint32_t flags,
+        VmaDefragmentationStats* pStats);
+
+    uint32_t ProcessDefragmentations(
+        class VmaBlockVectorDefragmentationContext *pCtx,
+        VmaDefragmentationPassMoveInfo* pMove, uint32_t maxMoves);
+
+    void CommitDefragmentations(
+        class VmaBlockVectorDefragmentationContext *pCtx,
+        VmaDefragmentationStats* pStats);
+
+    ////////////////////////////////////////////////////////////////////////////////
+    // To be used only while the m_Mutex is locked. Used during defragmentation.
+
+    size_t GetBlockCount() const { return m_Blocks.size(); }
+    VmaDeviceMemoryBlock* GetBlock(size_t index) const { return m_Blocks[index]; }
+    size_t CalcAllocationCount() const;
+    bool IsBufferImageGranularityConflictPossible() const;
+
+private:
+    friend class VmaDefragmentationAlgorithm_Generic;
+
+    const VmaAllocator m_hAllocator;
+    const VmaPool m_hParentPool;
+    const uint32_t m_MemoryTypeIndex;
+    const VkDeviceSize m_PreferredBlockSize;
+    const size_t m_MinBlockCount;
+    const size_t m_MaxBlockCount;
+    const VkDeviceSize m_BufferImageGranularity;
+    const uint32_t m_FrameInUseCount;
+    const bool m_ExplicitBlockSize;
+    const uint32_t m_Algorithm;
+    VMA_RW_MUTEX m_Mutex;
+
+    /* There can be at most one allocation that is completely empty (except when minBlockCount > 0) -
+    a hysteresis to avoid pessimistic case of alternating creation and destruction of a VkDeviceMemory. */
+    bool m_HasEmptyBlock;
+    // Incrementally sorted by sumFreeSize, ascending.
+    VmaVector< VmaDeviceMemoryBlock*, VmaStlAllocator<VmaDeviceMemoryBlock*> > m_Blocks;
+    uint32_t m_NextBlockId;
+
+    VkDeviceSize CalcMaxBlockSize() const;
+
+    // Finds and removes given block from vector.
+    void Remove(VmaDeviceMemoryBlock* pBlock);
+
+    // Performs single step in sorting m_Blocks. They may not be fully sorted
+    // after this call.
+    void IncrementallySortBlocks();
+
+    VkResult AllocatePage(
+        uint32_t currentFrameIndex,
+        VkDeviceSize size,
+        VkDeviceSize alignment,
+        const VmaAllocationCreateInfo& createInfo,
+        VmaSuballocationType suballocType,
+        VmaAllocation* pAllocation);
+
+    // To be used only without CAN_MAKE_OTHER_LOST flag.
+    VkResult AllocateFromBlock(
+        VmaDeviceMemoryBlock* pBlock,
+        uint32_t currentFrameIndex,
+        VkDeviceSize size,
+        VkDeviceSize alignment,
+        VmaAllocationCreateFlags allocFlags,
+        void* pUserData,
+        VmaSuballocationType suballocType,
+        uint32_t strategy,
+        VmaAllocation* pAllocation);
+
+    VkResult CreateBlock(VkDeviceSize blockSize, size_t* pNewBlockIndex);
+
+    // Saves result to pCtx->res.
+    void ApplyDefragmentationMovesCpu(
+        class VmaBlockVectorDefragmentationContext* pDefragCtx,
+        const VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves);
+    // Saves result to pCtx->res.
+    void ApplyDefragmentationMovesGpu(
+        class VmaBlockVectorDefragmentationContext* pDefragCtx,
+        VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves,
+        VkCommandBuffer commandBuffer);
+
+    /*
+    Used during defragmentation. pDefragmentationStats is optional. It's in/out
+    - updated with new data.
+    */
+    void FreeEmptyBlocks(VmaDefragmentationStats* pDefragmentationStats);
+
+    void UpdateHasEmptyBlock();
+};
+
+struct VmaPool_T
+{
+    VMA_CLASS_NO_COPY(VmaPool_T)
+public:
+    VmaBlockVector m_BlockVector;
+
+    VmaPool_T(
+        VmaAllocator hAllocator,
+        const VmaPoolCreateInfo& createInfo,
+        VkDeviceSize preferredBlockSize);
+    ~VmaPool_T();
+
+    uint32_t GetId() const { return m_Id; }
+    void SetId(uint32_t id) { VMA_ASSERT(m_Id == 0); m_Id = id; }
+
+    const char* GetName() const { return m_Name; }
+    void SetName(const char* pName);
+
+#if VMA_STATS_STRING_ENABLED
+    //void PrintDetailedMap(class VmaStringBuilder& sb);
+#endif
+
+private:
+    uint32_t m_Id;
+    char* m_Name;
+};
+
+/*
+Performs defragmentation:
+
+- Updates `pBlockVector->m_pMetadata`.
+- Updates allocations by calling ChangeBlockAllocation() or ChangeOffset().
+- Does not move actual data, only returns requested moves as `moves`.
+*/
+class VmaDefragmentationAlgorithm
+{
+    VMA_CLASS_NO_COPY(VmaDefragmentationAlgorithm)
+public:
+    VmaDefragmentationAlgorithm(
+        VmaAllocator hAllocator,
+        VmaBlockVector* pBlockVector,
+        uint32_t currentFrameIndex) :
+        m_hAllocator(hAllocator),
+        m_pBlockVector(pBlockVector),
+        m_CurrentFrameIndex(currentFrameIndex)
+    {
+    }
+    virtual ~VmaDefragmentationAlgorithm()
+    {
+    }
+
+    virtual void AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged) = 0;
+    virtual void AddAll() = 0;
+
+    virtual VkResult Defragment(
+        VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves,
+        VkDeviceSize maxBytesToMove,
+        uint32_t maxAllocationsToMove,
+        VmaDefragmentationFlags flags) = 0;
+
+    virtual VkDeviceSize GetBytesMoved() const = 0;
+    virtual uint32_t GetAllocationsMoved() const = 0;
+
+protected:
+    VmaAllocator const m_hAllocator;
+    VmaBlockVector* const m_pBlockVector;
+    const uint32_t m_CurrentFrameIndex;
+
+    struct AllocationInfo
+    {
+        VmaAllocation m_hAllocation;
+        VkBool32* m_pChanged;
+
+        AllocationInfo() :
+            m_hAllocation(VK_NULL_HANDLE),
+            m_pChanged(VMA_NULL)
+        {
+        }
+        AllocationInfo(VmaAllocation hAlloc, VkBool32* pChanged) :
+            m_hAllocation(hAlloc),
+            m_pChanged(pChanged)
+        {
+        }
+    };
+};
+
+class VmaDefragmentationAlgorithm_Generic : public VmaDefragmentationAlgorithm
+{
+    VMA_CLASS_NO_COPY(VmaDefragmentationAlgorithm_Generic)
+public:
+    VmaDefragmentationAlgorithm_Generic(
+        VmaAllocator hAllocator,
+        VmaBlockVector* pBlockVector,
+        uint32_t currentFrameIndex,
+        bool overlappingMoveSupported);
+    virtual ~VmaDefragmentationAlgorithm_Generic();
+
+    virtual void AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged);
+    virtual void AddAll() { m_AllAllocations = true; }
+
+    virtual VkResult Defragment(
+        VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves,
+        VkDeviceSize maxBytesToMove,
+        uint32_t maxAllocationsToMove,
+        VmaDefragmentationFlags flags);
+
+    virtual VkDeviceSize GetBytesMoved() const { return m_BytesMoved; }
+    virtual uint32_t GetAllocationsMoved() const { return m_AllocationsMoved; }
+
+private:
+    uint32_t m_AllocationCount;
+    bool m_AllAllocations;
+
+    VkDeviceSize m_BytesMoved;
+    uint32_t m_AllocationsMoved;
+
+    struct AllocationInfoSizeGreater
+    {
+        bool operator()(const AllocationInfo& lhs, const AllocationInfo& rhs) const
+        {
+            return lhs.m_hAllocation->GetSize() > rhs.m_hAllocation->GetSize();
+        }
+    };
+
+    struct AllocationInfoOffsetGreater
+    {
+        bool operator()(const AllocationInfo& lhs, const AllocationInfo& rhs) const
+        {
+            return lhs.m_hAllocation->GetOffset() > rhs.m_hAllocation->GetOffset();
+        }
+    };
+
+    struct BlockInfo
+    {
+        size_t m_OriginalBlockIndex;
+        VmaDeviceMemoryBlock* m_pBlock;
+        bool m_HasNonMovableAllocations;
+        VmaVector< AllocationInfo, VmaStlAllocator<AllocationInfo> > m_Allocations;
+
+        BlockInfo(const VkAllocationCallbacks* pAllocationCallbacks) :
+            m_OriginalBlockIndex(SIZE_MAX),
+            m_pBlock(VMA_NULL),
+            m_HasNonMovableAllocations(true),
+            m_Allocations(pAllocationCallbacks)
+        {
+        }
+
+        void CalcHasNonMovableAllocations()
+        {
+            const size_t blockAllocCount = m_pBlock->m_pMetadata->GetAllocationCount();
+            const size_t defragmentAllocCount = m_Allocations.size();
+            m_HasNonMovableAllocations = blockAllocCount != defragmentAllocCount;
+        }
+
+        void SortAllocationsBySizeDescending()
+        {
+            VMA_SORT(m_Allocations.begin(), m_Allocations.end(), AllocationInfoSizeGreater());
+        }
+
+        void SortAllocationsByOffsetDescending()
+        {
+            VMA_SORT(m_Allocations.begin(), m_Allocations.end(), AllocationInfoOffsetGreater());
+        }
+    };
+
+    struct BlockPointerLess
+    {
+        bool operator()(const BlockInfo* pLhsBlockInfo, const VmaDeviceMemoryBlock* pRhsBlock) const
+        {
+            return pLhsBlockInfo->m_pBlock < pRhsBlock;
+        }
+        bool operator()(const BlockInfo* pLhsBlockInfo, const BlockInfo* pRhsBlockInfo) const
+        {
+            return pLhsBlockInfo->m_pBlock < pRhsBlockInfo->m_pBlock;
+        }
+    };
+
+    // 1. Blocks with some non-movable allocations go first.
+    // 2. Blocks with smaller sumFreeSize go first.
+    struct BlockInfoCompareMoveDestination
+    {
+        bool operator()(const BlockInfo* pLhsBlockInfo, const BlockInfo* pRhsBlockInfo) const
+        {
+            if(pLhsBlockInfo->m_HasNonMovableAllocations && !pRhsBlockInfo->m_HasNonMovableAllocations)
+            {
+                return true;
+            }
+            if(!pLhsBlockInfo->m_HasNonMovableAllocations && pRhsBlockInfo->m_HasNonMovableAllocations)
+            {
+                return false;
+            }
+            if(pLhsBlockInfo->m_pBlock->m_pMetadata->GetSumFreeSize() < pRhsBlockInfo->m_pBlock->m_pMetadata->GetSumFreeSize())
+            {
+                return true;
+            }
+            return false;
+        }
+    };
+
+    typedef VmaVector< BlockInfo*, VmaStlAllocator<BlockInfo*> > BlockInfoVector;
+    BlockInfoVector m_Blocks;
+
+    VkResult DefragmentRound(
+        VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves,
+        VkDeviceSize maxBytesToMove,
+        uint32_t maxAllocationsToMove,
+        bool freeOldAllocations);
+
+    size_t CalcBlocksWithNonMovableCount() const;
+
+    static bool MoveMakesSense(
+        size_t dstBlockIndex, VkDeviceSize dstOffset,
+        size_t srcBlockIndex, VkDeviceSize srcOffset);
+};
+
+class VmaDefragmentationAlgorithm_Fast : public VmaDefragmentationAlgorithm
+{
+    VMA_CLASS_NO_COPY(VmaDefragmentationAlgorithm_Fast)
+public:
+    VmaDefragmentationAlgorithm_Fast(
+        VmaAllocator hAllocator,
+        VmaBlockVector* pBlockVector,
+        uint32_t currentFrameIndex,
+        bool overlappingMoveSupported);
+    virtual ~VmaDefragmentationAlgorithm_Fast();
+
+    virtual void AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged) { ++m_AllocationCount; }
+    virtual void AddAll() { m_AllAllocations = true; }
+
+    virtual VkResult Defragment(
+        VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves,
+        VkDeviceSize maxBytesToMove,
+        uint32_t maxAllocationsToMove,
+        VmaDefragmentationFlags flags);
+
+    virtual VkDeviceSize GetBytesMoved() const { return m_BytesMoved; }
+    virtual uint32_t GetAllocationsMoved() const { return m_AllocationsMoved; }
+
+private:
+    struct BlockInfo
+    {
+        size_t origBlockIndex;
+    };
+
+    class FreeSpaceDatabase
+    {
+    public:
+        FreeSpaceDatabase()
+        {
+            FreeSpace s = {};
+            s.blockInfoIndex = SIZE_MAX;
+            for(size_t i = 0; i < MAX_COUNT; ++i)
+            {
+                m_FreeSpaces[i] = s;
+            }
+        }
+
+        void Register(size_t blockInfoIndex, VkDeviceSize offset, VkDeviceSize size)
+        {
+            if(size < VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER)
+            {
+                return;
+            }
+
+            // Find first invalid or the smallest structure.
+            size_t bestIndex = SIZE_MAX;
+            for(size_t i = 0; i < MAX_COUNT; ++i)
+            {
+                // Empty structure.
+                if(m_FreeSpaces[i].blockInfoIndex == SIZE_MAX)
+                {
+                    bestIndex = i;
+                    break;
+                }
+                if(m_FreeSpaces[i].size < size &&
+                    (bestIndex == SIZE_MAX || m_FreeSpaces[bestIndex].size > m_FreeSpaces[i].size))
+                {
+                    bestIndex = i;
+                }
+            }
+
+            if(bestIndex != SIZE_MAX)
+            {
+                m_FreeSpaces[bestIndex].blockInfoIndex = blockInfoIndex;
+                m_FreeSpaces[bestIndex].offset = offset;
+                m_FreeSpaces[bestIndex].size = size;
+            }
+        }
+
+        bool Fetch(VkDeviceSize alignment, VkDeviceSize size,
+            size_t& outBlockInfoIndex, VkDeviceSize& outDstOffset)
+        {
+            size_t bestIndex = SIZE_MAX;
+            VkDeviceSize bestFreeSpaceAfter = 0;
+            for(size_t i = 0; i < MAX_COUNT; ++i)
+            {
+                // Structure is valid.
+                if(m_FreeSpaces[i].blockInfoIndex != SIZE_MAX)
+                {
+                    const VkDeviceSize dstOffset = VmaAlignUp(m_FreeSpaces[i].offset, alignment);
+                    // Allocation fits into this structure.
+                    if(dstOffset + size <= m_FreeSpaces[i].offset + m_FreeSpaces[i].size)
+                    {
+                        const VkDeviceSize freeSpaceAfter = (m_FreeSpaces[i].offset + m_FreeSpaces[i].size) -
+                            (dstOffset + size);
+                        if(bestIndex == SIZE_MAX || freeSpaceAfter > bestFreeSpaceAfter)
+                        {
+                            bestIndex = i;
+                            bestFreeSpaceAfter = freeSpaceAfter;
+                        }
+                    }
+                }
+            }
+            
+            if(bestIndex != SIZE_MAX)
+            {
+                outBlockInfoIndex = m_FreeSpaces[bestIndex].blockInfoIndex;
+                outDstOffset = VmaAlignUp(m_FreeSpaces[bestIndex].offset, alignment);
+
+                if(bestFreeSpaceAfter >= VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER)
+                {
+                    // Leave this structure for remaining empty space.
+                    const VkDeviceSize alignmentPlusSize = (outDstOffset - m_FreeSpaces[bestIndex].offset) + size;
+                    m_FreeSpaces[bestIndex].offset += alignmentPlusSize;
+                    m_FreeSpaces[bestIndex].size -= alignmentPlusSize;
+                }
+                else
+                {
+                    // This structure becomes invalid.
+                    m_FreeSpaces[bestIndex].blockInfoIndex = SIZE_MAX;
+                }
+
+                return true;
+            }
+
+            return false;
+        }
+
+    private:
+        static const size_t MAX_COUNT = 4;
+
+        struct FreeSpace
+        {
+            size_t blockInfoIndex; // SIZE_MAX means this structure is invalid.
+            VkDeviceSize offset;
+            VkDeviceSize size;
+        } m_FreeSpaces[MAX_COUNT];
+    };
+
+    const bool m_OverlappingMoveSupported;
+
+    uint32_t m_AllocationCount;
+    bool m_AllAllocations;
+
+    VkDeviceSize m_BytesMoved;
+    uint32_t m_AllocationsMoved;
+
+    VmaVector< BlockInfo, VmaStlAllocator<BlockInfo> > m_BlockInfos;
+
+    void PreprocessMetadata();
+    void PostprocessMetadata();
+    void InsertSuballoc(VmaBlockMetadata_Generic* pMetadata, const VmaSuballocation& suballoc);
+};
+
+struct VmaBlockDefragmentationContext
+{
+    enum BLOCK_FLAG
+    {
+        BLOCK_FLAG_USED = 0x00000001,
+    };
+    uint32_t flags;
+    VkBuffer hBuffer;
+};
+
+class VmaBlockVectorDefragmentationContext
+{
+    VMA_CLASS_NO_COPY(VmaBlockVectorDefragmentationContext)
+public:
+    VkResult res;
+    bool mutexLocked;
+    VmaVector< VmaBlockDefragmentationContext, VmaStlAllocator<VmaBlockDefragmentationContext> > blockContexts;
+    VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> > defragmentationMoves;
+    uint32_t defragmentationMovesProcessed;
+    uint32_t defragmentationMovesCommitted;
+    bool hasDefragmentationPlan;
+
+    VmaBlockVectorDefragmentationContext(
+        VmaAllocator hAllocator,
+        VmaPool hCustomPool, // Optional.
+        VmaBlockVector* pBlockVector,
+        uint32_t currFrameIndex);
+    ~VmaBlockVectorDefragmentationContext();
+
+    VmaPool GetCustomPool() const { return m_hCustomPool; }
+    VmaBlockVector* GetBlockVector() const { return m_pBlockVector; }
+    VmaDefragmentationAlgorithm* GetAlgorithm() const { return m_pAlgorithm; }
+
+    void AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged);
+    void AddAll() { m_AllAllocations = true; }
+
+    void Begin(bool overlappingMoveSupported, VmaDefragmentationFlags flags);
+
+private:
+    const VmaAllocator m_hAllocator;
+    // Null if not from custom pool.
+    const VmaPool m_hCustomPool;
+    // Redundant, for convenience not to fetch from m_hCustomPool->m_BlockVector or m_hAllocator->m_pBlockVectors.
+    VmaBlockVector* const m_pBlockVector;
+    const uint32_t m_CurrFrameIndex;
+    // Owner of this object.
+    VmaDefragmentationAlgorithm* m_pAlgorithm;
+
+    struct AllocInfo
+    {
+        VmaAllocation hAlloc;
+        VkBool32* pChanged;
+    };
+    // Used between constructor and Begin.
+    VmaVector< AllocInfo, VmaStlAllocator<AllocInfo> > m_Allocations;
+    bool m_AllAllocations;
+};
+
+struct VmaDefragmentationContext_T
+{
+private:
+    VMA_CLASS_NO_COPY(VmaDefragmentationContext_T)
+public:
+    VmaDefragmentationContext_T(
+        VmaAllocator hAllocator,
+        uint32_t currFrameIndex,
+        uint32_t flags,
+        VmaDefragmentationStats* pStats);
+    ~VmaDefragmentationContext_T();
+
+    void AddPools(uint32_t poolCount, VmaPool* pPools);
+    void AddAllocations(
+        uint32_t allocationCount,
+        VmaAllocation* pAllocations,
+        VkBool32* pAllocationsChanged);
+
+    /*
+    Returns:
+    - `VK_SUCCESS` if succeeded and object can be destroyed immediately.
+    - `VK_NOT_READY` if succeeded but the object must remain alive until vmaDefragmentationEnd().
+    - Negative value if error occured and object can be destroyed immediately.
+    */
+    VkResult Defragment(
+        VkDeviceSize maxCpuBytesToMove, uint32_t maxCpuAllocationsToMove,
+        VkDeviceSize maxGpuBytesToMove, uint32_t maxGpuAllocationsToMove,
+        VkCommandBuffer commandBuffer, VmaDefragmentationStats* pStats, VmaDefragmentationFlags flags);
+
+    VkResult DefragmentPassBegin(VmaDefragmentationPassInfo* pInfo);
+    VkResult DefragmentPassEnd();
+
+private:
+    const VmaAllocator m_hAllocator;
+    const uint32_t m_CurrFrameIndex;
+    const uint32_t m_Flags;
+    VmaDefragmentationStats* const m_pStats;
+
+    VkDeviceSize m_MaxCpuBytesToMove;
+    uint32_t m_MaxCpuAllocationsToMove;
+    VkDeviceSize m_MaxGpuBytesToMove;
+    uint32_t m_MaxGpuAllocationsToMove;
+
+    // Owner of these objects.
+    VmaBlockVectorDefragmentationContext* m_DefaultPoolContexts[VK_MAX_MEMORY_TYPES];
+    // Owner of these objects.
+    VmaVector< VmaBlockVectorDefragmentationContext*, VmaStlAllocator<VmaBlockVectorDefragmentationContext*> > m_CustomPoolContexts;
+};
+
+#if VMA_RECORDING_ENABLED
+
+class VmaRecorder
+{
+public:
+    VmaRecorder();
+    VkResult Init(const VmaRecordSettings& settings, bool useMutex);
+    void WriteConfiguration(
+        const VkPhysicalDeviceProperties& devProps,
+        const VkPhysicalDeviceMemoryProperties& memProps,
+        uint32_t vulkanApiVersion,
+        bool dedicatedAllocationExtensionEnabled,
+        bool bindMemory2ExtensionEnabled,
+        bool memoryBudgetExtensionEnabled,
+        bool deviceCoherentMemoryExtensionEnabled);
+    ~VmaRecorder();
+
+    void RecordCreateAllocator(uint32_t frameIndex);
+    void RecordDestroyAllocator(uint32_t frameIndex);
+    void RecordCreatePool(uint32_t frameIndex,
+        const VmaPoolCreateInfo& createInfo,
+        VmaPool pool);
+    void RecordDestroyPool(uint32_t frameIndex, VmaPool pool);
+    void RecordAllocateMemory(uint32_t frameIndex,
+        const VkMemoryRequirements& vkMemReq,
+        const VmaAllocationCreateInfo& createInfo,
+        VmaAllocation allocation);
+    void RecordAllocateMemoryPages(uint32_t frameIndex,
+        const VkMemoryRequirements& vkMemReq,
+        const VmaAllocationCreateInfo& createInfo,
+        uint64_t allocationCount,
+        const VmaAllocation* pAllocations);
+    void RecordAllocateMemoryForBuffer(uint32_t frameIndex,
+        const VkMemoryRequirements& vkMemReq,
+        bool requiresDedicatedAllocation,
+        bool prefersDedicatedAllocation,
+        const VmaAllocationCreateInfo& createInfo,
+        VmaAllocation allocation);
+    void RecordAllocateMemoryForImage(uint32_t frameIndex,
+        const VkMemoryRequirements& vkMemReq,
+        bool requiresDedicatedAllocation,
+        bool prefersDedicatedAllocation,
+        const VmaAllocationCreateInfo& createInfo,
+        VmaAllocation allocation);
+    void RecordFreeMemory(uint32_t frameIndex,
+        VmaAllocation allocation);
+    void RecordFreeMemoryPages(uint32_t frameIndex,
+        uint64_t allocationCount,
+        const VmaAllocation* pAllocations);
+    void RecordSetAllocationUserData(uint32_t frameIndex,
+        VmaAllocation allocation,
+        const void* pUserData);
+    void RecordCreateLostAllocation(uint32_t frameIndex,
+        VmaAllocation allocation);
+    void RecordMapMemory(uint32_t frameIndex,
+        VmaAllocation allocation);
+    void RecordUnmapMemory(uint32_t frameIndex,
+        VmaAllocation allocation);
+    void RecordFlushAllocation(uint32_t frameIndex,
+        VmaAllocation allocation, VkDeviceSize offset, VkDeviceSize size);
+    void RecordInvalidateAllocation(uint32_t frameIndex,
+        VmaAllocation allocation, VkDeviceSize offset, VkDeviceSize size);
+    void RecordCreateBuffer(uint32_t frameIndex,
+        const VkBufferCreateInfo& bufCreateInfo,
+        const VmaAllocationCreateInfo& allocCreateInfo,
+        VmaAllocation allocation);
+    void RecordCreateImage(uint32_t frameIndex,
+        const VkImageCreateInfo& imageCreateInfo,
+        const VmaAllocationCreateInfo& allocCreateInfo,
+        VmaAllocation allocation);
+    void RecordDestroyBuffer(uint32_t frameIndex,
+        VmaAllocation allocation);
+    void RecordDestroyImage(uint32_t frameIndex,
+        VmaAllocation allocation);
+    void RecordTouchAllocation(uint32_t frameIndex,
+        VmaAllocation allocation);
+    void RecordGetAllocationInfo(uint32_t frameIndex,
+        VmaAllocation allocation);
+    void RecordMakePoolAllocationsLost(uint32_t frameIndex,
+        VmaPool pool);
+    void RecordDefragmentationBegin(uint32_t frameIndex,
+        const VmaDefragmentationInfo2& info,
+        VmaDefragmentationContext ctx);
+    void RecordDefragmentationEnd(uint32_t frameIndex,
+        VmaDefragmentationContext ctx);
+    void RecordSetPoolName(uint32_t frameIndex,
+        VmaPool pool,
+        const char* name);
+
+private:
+    struct CallParams
+    {
+        uint32_t threadId;
+        double time;
+    };
+
+    class UserDataString
+    {
+    public:
+        UserDataString(VmaAllocationCreateFlags allocFlags, const void* pUserData);
+        const char* GetString() const { return m_Str; }
+
+    private:
+        char m_PtrStr[17];
+        const char* m_Str;
+    };
+
+    bool m_UseMutex;
+    VmaRecordFlags m_Flags;
+    FILE* m_File;
+    VMA_MUTEX m_FileMutex;
+    int64_t m_Freq;
+    int64_t m_StartCounter;
+
+    void GetBasicParams(CallParams& outParams);
+
+    // T must be a pointer type, e.g. VmaAllocation, VmaPool.
+    template<typename T>
+    void PrintPointerList(uint64_t count, const T* pItems)
+    {
+        if(count)
+        {
+            fprintf(m_File, "%p", pItems[0]);
+            for(uint64_t i = 1; i < count; ++i)
+            {
+                fprintf(m_File, " %p", pItems[i]);
+            }
+        }
+    }
+
+    void PrintPointerList(uint64_t count, const VmaAllocation* pItems);
+    void Flush();
+};
+
+#endif // #if VMA_RECORDING_ENABLED
+
+/*
+Thread-safe wrapper over VmaPoolAllocator free list, for allocation of VmaAllocation_T objects.
+*/
+class VmaAllocationObjectAllocator
+{
+    VMA_CLASS_NO_COPY(VmaAllocationObjectAllocator)
+public:
+    VmaAllocationObjectAllocator(const VkAllocationCallbacks* pAllocationCallbacks);
+
+    template<typename... Types> VmaAllocation Allocate(Types... args);
+    void Free(VmaAllocation hAlloc);
+
+private:
+    VMA_MUTEX m_Mutex;
+    VmaPoolAllocator<VmaAllocation_T> m_Allocator;
+};
+
+struct VmaCurrentBudgetData
+{
+    VMA_ATOMIC_UINT64 m_BlockBytes[VK_MAX_MEMORY_HEAPS];
+    VMA_ATOMIC_UINT64 m_AllocationBytes[VK_MAX_MEMORY_HEAPS];
+
+#if VMA_MEMORY_BUDGET
+    VMA_ATOMIC_UINT32 m_OperationsSinceBudgetFetch;
+    VMA_RW_MUTEX m_BudgetMutex;
+    uint64_t m_VulkanUsage[VK_MAX_MEMORY_HEAPS];
+    uint64_t m_VulkanBudget[VK_MAX_MEMORY_HEAPS];
+    uint64_t m_BlockBytesAtBudgetFetch[VK_MAX_MEMORY_HEAPS];
+#endif // #if VMA_MEMORY_BUDGET
+
+    VmaCurrentBudgetData()
+    {
+        for(uint32_t heapIndex = 0; heapIndex < VK_MAX_MEMORY_HEAPS; ++heapIndex)
+        {
+            m_BlockBytes[heapIndex] = 0;
+            m_AllocationBytes[heapIndex] = 0;
+#if VMA_MEMORY_BUDGET
+            m_VulkanUsage[heapIndex] = 0;
+            m_VulkanBudget[heapIndex] = 0;
+            m_BlockBytesAtBudgetFetch[heapIndex] = 0;
+#endif
+        }
+
+#if VMA_MEMORY_BUDGET
+        m_OperationsSinceBudgetFetch = 0;
+#endif
+    }
+
+    void AddAllocation(uint32_t heapIndex, VkDeviceSize allocationSize)
+    {
+        m_AllocationBytes[heapIndex] += allocationSize;
+#if VMA_MEMORY_BUDGET
+        ++m_OperationsSinceBudgetFetch;
+#endif
+    }
+
+    void RemoveAllocation(uint32_t heapIndex, VkDeviceSize allocationSize)
+    {
+        VMA_ASSERT(m_AllocationBytes[heapIndex] >= allocationSize); // DELME
+        m_AllocationBytes[heapIndex] -= allocationSize;
+#if VMA_MEMORY_BUDGET
+        ++m_OperationsSinceBudgetFetch;
+#endif
+    }
+};
+
+// Main allocator object.
+struct VmaAllocator_T
+{
+    VMA_CLASS_NO_COPY(VmaAllocator_T)
+public:
+    bool m_UseMutex;
+    uint32_t m_VulkanApiVersion;
+    bool m_UseKhrDedicatedAllocation; // Can be set only if m_VulkanApiVersion < VK_MAKE_VERSION(1, 1, 0).
+    bool m_UseKhrBindMemory2; // Can be set only if m_VulkanApiVersion < VK_MAKE_VERSION(1, 1, 0).
+    bool m_UseExtMemoryBudget;
+    bool m_UseAmdDeviceCoherentMemory;
+    bool m_UseKhrBufferDeviceAddress;
+    VkDevice m_hDevice;
+    VkInstance m_hInstance;
+    bool m_AllocationCallbacksSpecified;
+    VkAllocationCallbacks m_AllocationCallbacks;
+    VmaDeviceMemoryCallbacks m_DeviceMemoryCallbacks;
+    VmaAllocationObjectAllocator m_AllocationObjectAllocator;
+    
+    // Each bit (1 << i) is set if HeapSizeLimit is enabled for that heap, so cannot allocate more than the heap size.
+    uint32_t m_HeapSizeLimitMask;
+
+    VkPhysicalDeviceProperties m_PhysicalDeviceProperties;
+    VkPhysicalDeviceMemoryProperties m_MemProps;
+
+    // Default pools.
+    VmaBlockVector* m_pBlockVectors[VK_MAX_MEMORY_TYPES];
+
+    // Each vector is sorted by memory (handle value).
+    typedef VmaVector< VmaAllocation, VmaStlAllocator<VmaAllocation> > AllocationVectorType;
+    AllocationVectorType* m_pDedicatedAllocations[VK_MAX_MEMORY_TYPES];
+    VMA_RW_MUTEX m_DedicatedAllocationsMutex[VK_MAX_MEMORY_TYPES];
+
+    VmaCurrentBudgetData m_Budget;
+
+    VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo);
+    VkResult Init(const VmaAllocatorCreateInfo* pCreateInfo);
+    ~VmaAllocator_T();
+
+    const VkAllocationCallbacks* GetAllocationCallbacks() const
+    {
+        return m_AllocationCallbacksSpecified ? &m_AllocationCallbacks : 0;
+    }
+    const VmaVulkanFunctions& GetVulkanFunctions() const
+    {
+        return m_VulkanFunctions;
+    }
+
+    VkPhysicalDevice GetPhysicalDevice() const { return m_PhysicalDevice; }
+
+    VkDeviceSize GetBufferImageGranularity() const
+    {
+        return VMA_MAX(
+            static_cast<VkDeviceSize>(VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY),
+            m_PhysicalDeviceProperties.limits.bufferImageGranularity);
+    }
+
+    uint32_t GetMemoryHeapCount() const { return m_MemProps.memoryHeapCount; }
+    uint32_t GetMemoryTypeCount() const { return m_MemProps.memoryTypeCount; }
+
+    uint32_t MemoryTypeIndexToHeapIndex(uint32_t memTypeIndex) const
+    {
+        VMA_ASSERT(memTypeIndex < m_MemProps.memoryTypeCount);
+        return m_MemProps.memoryTypes[memTypeIndex].heapIndex;
+    }
+    // True when specific memory type is HOST_VISIBLE but not HOST_COHERENT.
+    bool IsMemoryTypeNonCoherent(uint32_t memTypeIndex) const
+    {
+        return (m_MemProps.memoryTypes[memTypeIndex].propertyFlags & (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) ==
+            VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
+    }
+    // Minimum alignment for all allocations in specific memory type.
+    VkDeviceSize GetMemoryTypeMinAlignment(uint32_t memTypeIndex) const
+    {
+        return IsMemoryTypeNonCoherent(memTypeIndex) ?
+            VMA_MAX((VkDeviceSize)VMA_DEBUG_ALIGNMENT, m_PhysicalDeviceProperties.limits.nonCoherentAtomSize) :
+            (VkDeviceSize)VMA_DEBUG_ALIGNMENT;
+    }
+
+    bool IsIntegratedGpu() const
+    {
+        return m_PhysicalDeviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
+    }
+
+    uint32_t GetGlobalMemoryTypeBits() const { return m_GlobalMemoryTypeBits; }
+
+#if VMA_RECORDING_ENABLED
+    VmaRecorder* GetRecorder() const { return m_pRecorder; }
+#endif
+
+    void GetBufferMemoryRequirements(
+        VkBuffer hBuffer,
+        VkMemoryRequirements& memReq,
+        bool& requiresDedicatedAllocation,
+        bool& prefersDedicatedAllocation) const;
+    void GetImageMemoryRequirements(
+        VkImage hImage,
+        VkMemoryRequirements& memReq,
+        bool& requiresDedicatedAllocation,
+        bool& prefersDedicatedAllocation) const;
+
+    // Main allocation function.
+    VkResult AllocateMemory(
+        const VkMemoryRequirements& vkMemReq,
+        bool requiresDedicatedAllocation,
+        bool prefersDedicatedAllocation,
+        VkBuffer dedicatedBuffer,
+        VkBufferUsageFlags dedicatedBufferUsage, // UINT32_MAX when unknown.
+        VkImage dedicatedImage,
+        const VmaAllocationCreateInfo& createInfo,
+        VmaSuballocationType suballocType,
+        size_t allocationCount,
+        VmaAllocation* pAllocations);
+
+    // Main deallocation function.
+    void FreeMemory(
+        size_t allocationCount,
+        const VmaAllocation* pAllocations);
+
+    VkResult ResizeAllocation(
+        const VmaAllocation alloc,
+        VkDeviceSize newSize);
+
+    void CalculateStats(VmaStats* pStats);
+
+    void GetBudget(
+        VmaBudget* outBudget, uint32_t firstHeap, uint32_t heapCount);
+
+#if VMA_STATS_STRING_ENABLED
+    void PrintDetailedMap(class VmaJsonWriter& json);
+#endif
+
+    VkResult DefragmentationBegin(
+        const VmaDefragmentationInfo2& info,
+        VmaDefragmentationStats* pStats,
+        VmaDefragmentationContext* pContext);
+    VkResult DefragmentationEnd(
+        VmaDefragmentationContext context);
+
+    VkResult DefragmentationPassBegin(
+        VmaDefragmentationPassInfo* pInfo,
+        VmaDefragmentationContext context);
+    VkResult DefragmentationPassEnd(
+        VmaDefragmentationContext context);
+
+    void GetAllocationInfo(VmaAllocation hAllocation, VmaAllocationInfo* pAllocationInfo);
+    bool TouchAllocation(VmaAllocation hAllocation);
+
+    VkResult CreatePool(const VmaPoolCreateInfo* pCreateInfo, VmaPool* pPool);
+    void DestroyPool(VmaPool pool);
+    void GetPoolStats(VmaPool pool, VmaPoolStats* pPoolStats);
+
+    void SetCurrentFrameIndex(uint32_t frameIndex);
+    uint32_t GetCurrentFrameIndex() const { return m_CurrentFrameIndex.load(); }
+
+    void MakePoolAllocationsLost(
+        VmaPool hPool,
+        size_t* pLostAllocationCount);
+    VkResult CheckPoolCorruption(VmaPool hPool);
+    VkResult CheckCorruption(uint32_t memoryTypeBits);
+
+    void CreateLostAllocation(VmaAllocation* pAllocation);
+
+    // Call to Vulkan function vkAllocateMemory with accompanying bookkeeping.
+    VkResult AllocateVulkanMemory(const VkMemoryAllocateInfo* pAllocateInfo, VkDeviceMemory* pMemory);
+    // Call to Vulkan function vkFreeMemory with accompanying bookkeeping.
+    void FreeVulkanMemory(uint32_t memoryType, VkDeviceSize size, VkDeviceMemory hMemory);
+    // Call to Vulkan function vkBindBufferMemory or vkBindBufferMemory2KHR.
+    VkResult BindVulkanBuffer(
+        VkDeviceMemory memory,
+        VkDeviceSize memoryOffset,
+        VkBuffer buffer,
+        const void* pNext);
+    // Call to Vulkan function vkBindImageMemory or vkBindImageMemory2KHR.
+    VkResult BindVulkanImage(
+        VkDeviceMemory memory,
+        VkDeviceSize memoryOffset,
+        VkImage image,
+        const void* pNext);
+
+    VkResult Map(VmaAllocation hAllocation, void** ppData);
+    void Unmap(VmaAllocation hAllocation);
+
+    VkResult BindBufferMemory(
+        VmaAllocation hAllocation,
+        VkDeviceSize allocationLocalOffset,
+        VkBuffer hBuffer,
+        const void* pNext);
+    VkResult BindImageMemory(
+        VmaAllocation hAllocation,
+        VkDeviceSize allocationLocalOffset,
+        VkImage hImage,
+        const void* pNext);
+
+    void FlushOrInvalidateAllocation(
+        VmaAllocation hAllocation,
+        VkDeviceSize offset, VkDeviceSize size,
+        VMA_CACHE_OPERATION op);
+
+    void FillAllocation(const VmaAllocation hAllocation, uint8_t pattern);
+
+    /*
+    Returns bit mask of memory types that can support defragmentation on GPU as
+    they support creation of required buffer for copy operations.
+    */
+    uint32_t GetGpuDefragmentationMemoryTypeBits();
+
+private:
+    VkDeviceSize m_PreferredLargeHeapBlockSize;
+
+    VkPhysicalDevice m_PhysicalDevice;
+    VMA_ATOMIC_UINT32 m_CurrentFrameIndex;
+    VMA_ATOMIC_UINT32 m_GpuDefragmentationMemoryTypeBits; // UINT32_MAX means uninitialized.
+    
+    VMA_RW_MUTEX m_PoolsMutex;
+    // Protected by m_PoolsMutex. Sorted by pointer value.
+    VmaVector<VmaPool, VmaStlAllocator<VmaPool> > m_Pools;
+    uint32_t m_NextPoolId;
+
+    VmaVulkanFunctions m_VulkanFunctions;
+
+    // Global bit mask AND-ed with any memoryTypeBits to disallow certain memory types.
+    uint32_t m_GlobalMemoryTypeBits;
+
+#if VMA_RECORDING_ENABLED
+    VmaRecorder* m_pRecorder;
+#endif
+
+    void ImportVulkanFunctions(const VmaVulkanFunctions* pVulkanFunctions);
+    void ImportVulkanFunctions_Static();
+    void ImportVulkanFunctions_Custom(const VmaVulkanFunctions* pVulkanFunctions);
+    void ImportVulkanFunctions_Dynamic();
+    void ValidateVulkanFunctions();
+
+    VkDeviceSize CalcPreferredBlockSize(uint32_t memTypeIndex);
+
+    VkResult AllocateMemoryOfType(
+        VkDeviceSize size,
+        VkDeviceSize alignment,
+        bool dedicatedAllocation,
+        VkBuffer dedicatedBuffer,
+        VkBufferUsageFlags dedicatedBufferUsage,
+        VkImage dedicatedImage,
+        const VmaAllocationCreateInfo& createInfo,
+        uint32_t memTypeIndex,
+        VmaSuballocationType suballocType,
+        size_t allocationCount,
+        VmaAllocation* pAllocations);
+
+    // Helper function only to be used inside AllocateDedicatedMemory.
+    VkResult AllocateDedicatedMemoryPage(
+        VkDeviceSize size,
+        VmaSuballocationType suballocType,
+        uint32_t memTypeIndex,
+        const VkMemoryAllocateInfo& allocInfo,
+        bool map,
+        bool isUserDataString,
+        void* pUserData,
+        VmaAllocation* pAllocation);
+
+    // Allocates and registers new VkDeviceMemory specifically for dedicated allocations.
+    VkResult AllocateDedicatedMemory(
+        VkDeviceSize size,
+        VmaSuballocationType suballocType,
+        uint32_t memTypeIndex,
+        bool withinBudget,
+        bool map,
+        bool isUserDataString,
+        void* pUserData,
+        VkBuffer dedicatedBuffer,
+        VkBufferUsageFlags dedicatedBufferUsage,
+        VkImage dedicatedImage,
+        size_t allocationCount,
+        VmaAllocation* pAllocations);
+
+    void FreeDedicatedMemory(const VmaAllocation allocation);
+
+    /*
+    Calculates and returns bit mask of memory types that can support defragmentation
+    on GPU as they support creation of required buffer for copy operations.
+    */
+    uint32_t CalculateGpuDefragmentationMemoryTypeBits() const;
+
+    uint32_t CalculateGlobalMemoryTypeBits() const;
+
+#if VMA_MEMORY_BUDGET
+    void UpdateVulkanBudget();
+#endif // #if VMA_MEMORY_BUDGET
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// Memory allocation #2 after VmaAllocator_T definition
+
+static void* VmaMalloc(VmaAllocator hAllocator, size_t size, size_t alignment)
+{
+    return VmaMalloc(&hAllocator->m_AllocationCallbacks, size, alignment);
+}
+
+static void VmaFree(VmaAllocator hAllocator, void* ptr)
+{
+    VmaFree(&hAllocator->m_AllocationCallbacks, ptr);
+}
+
+template<typename T>
+static T* VmaAllocate(VmaAllocator hAllocator)
+{
+    return (T*)VmaMalloc(hAllocator, sizeof(T), VMA_ALIGN_OF(T));
+}
+
+template<typename T>
+static T* VmaAllocateArray(VmaAllocator hAllocator, size_t count)
+{
+    return (T*)VmaMalloc(hAllocator, sizeof(T) * count, VMA_ALIGN_OF(T));
+}
+
+template<typename T>
+static void vma_delete(VmaAllocator hAllocator, T* ptr)
+{
+    if(ptr != VMA_NULL)
+    {
+        ptr->~T();
+        VmaFree(hAllocator, ptr);
+    }
+}
+
+template<typename T>
+static void vma_delete_array(VmaAllocator hAllocator, T* ptr, size_t count)
+{
+    if(ptr != VMA_NULL)
+    {
+        for(size_t i = count; i--; )
+            ptr[i].~T();
+        VmaFree(hAllocator, ptr);
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// VmaStringBuilder
+
+#if VMA_STATS_STRING_ENABLED
+
+class VmaStringBuilder
+{
+public:
+    VmaStringBuilder(VmaAllocator alloc) : m_Data(VmaStlAllocator<char>(alloc->GetAllocationCallbacks())) { }
+    size_t GetLength() const { return m_Data.size(); }
+    const char* GetData() const { return m_Data.data(); }
+
+    void Add(char ch) { m_Data.push_back(ch); }
+    void Add(const char* pStr);
+    void AddNewLine() { Add('\n'); }
+    void AddNumber(uint32_t num);
+    void AddNumber(uint64_t num);
+    void AddPointer(const void* ptr);
+
+private:
+    VmaVector< char, VmaStlAllocator<char> > m_Data;
+};
+
+void VmaStringBuilder::Add(const char* pStr)
+{
+    const size_t strLen = strlen(pStr);
+    if(strLen > 0)
+    {
+        const size_t oldCount = m_Data.size();
+        m_Data.resize(oldCount + strLen);
+        memcpy(m_Data.data() + oldCount, pStr, strLen);
+    }
+}
+
+void VmaStringBuilder::AddNumber(uint32_t num)
+{
+    char buf[11];
+    buf[10] = '\0';
+    char *p = &buf[10];
+    do
+    {
+        *--p = '0' + (num % 10);
+        num /= 10;
+    }
+    while(num);
+    Add(p);
+}
+
+void VmaStringBuilder::AddNumber(uint64_t num)
+{
+    char buf[21];
+    buf[20] = '\0';
+    char *p = &buf[20];
+    do
+    {
+        *--p = '0' + (num % 10);
+        num /= 10;
+    }
+    while(num);
+    Add(p);
+}
+
+void VmaStringBuilder::AddPointer(const void* ptr)
+{
+    char buf[21];
+    VmaPtrToStr(buf, sizeof(buf), ptr);
+    Add(buf);
+}
+
+#endif // #if VMA_STATS_STRING_ENABLED
+
+////////////////////////////////////////////////////////////////////////////////
+// VmaJsonWriter
+
+#if VMA_STATS_STRING_ENABLED
+
+class VmaJsonWriter
+{
+    VMA_CLASS_NO_COPY(VmaJsonWriter)
+public:
+    VmaJsonWriter(const VkAllocationCallbacks* pAllocationCallbacks, VmaStringBuilder& sb);
+    ~VmaJsonWriter();
+
+    void BeginObject(bool singleLine = false);
+    void EndObject();
+    
+    void BeginArray(bool singleLine = false);
+    void EndArray();
+    
+    void WriteString(const char* pStr);
+    void BeginString(const char* pStr = VMA_NULL);
+    void ContinueString(const char* pStr);
+    void ContinueString(uint32_t n);
+    void ContinueString(uint64_t n);
+    void ContinueString_Pointer(const void* ptr);
+    void EndString(const char* pStr = VMA_NULL);
+    
+    void WriteNumber(uint32_t n);
+    void WriteNumber(uint64_t n);
+    void WriteBool(bool b);
+    void WriteNull();
+
+private:
+    static const char* const INDENT;
+
+    enum COLLECTION_TYPE
+    {
+        COLLECTION_TYPE_OBJECT,
+        COLLECTION_TYPE_ARRAY,
+    };
+    struct StackItem
+    {
+        COLLECTION_TYPE type;
+        uint32_t valueCount;
+        bool singleLineMode;
+    };
+
+    VmaStringBuilder& m_SB;
+    VmaVector< StackItem, VmaStlAllocator<StackItem> > m_Stack;
+    bool m_InsideString;
+
+    void BeginValue(bool isString);
+    void WriteIndent(bool oneLess = false);
+};
+
+const char* const VmaJsonWriter::INDENT = "  ";
+
+VmaJsonWriter::VmaJsonWriter(const VkAllocationCallbacks* pAllocationCallbacks, VmaStringBuilder& sb) :
+    m_SB(sb),
+    m_Stack(VmaStlAllocator<StackItem>(pAllocationCallbacks)),
+    m_InsideString(false)
+{
+}
+
+VmaJsonWriter::~VmaJsonWriter()
+{
+    VMA_ASSERT(!m_InsideString);
+    VMA_ASSERT(m_Stack.empty());
+}
+
+void VmaJsonWriter::BeginObject(bool singleLine)
+{
+    VMA_ASSERT(!m_InsideString);
+
+    BeginValue(false);
+    m_SB.Add('{');
+
+    StackItem item;
+    item.type = COLLECTION_TYPE_OBJECT;
+    item.valueCount = 0;
+    item.singleLineMode = singleLine;
+    m_Stack.push_back(item);
+}
+
+void VmaJsonWriter::EndObject()
+{
+    VMA_ASSERT(!m_InsideString);
+
+    WriteIndent(true);
+    m_SB.Add('}');
+
+    VMA_ASSERT(!m_Stack.empty() && m_Stack.back().type == COLLECTION_TYPE_OBJECT);
+    m_Stack.pop_back();
+}
+
+void VmaJsonWriter::BeginArray(bool singleLine)
+{
+    VMA_ASSERT(!m_InsideString);
+
+    BeginValue(false);
+    m_SB.Add('[');
+
+    StackItem item;
+    item.type = COLLECTION_TYPE_ARRAY;
+    item.valueCount = 0;
+    item.singleLineMode = singleLine;
+    m_Stack.push_back(item);
+}
+
+void VmaJsonWriter::EndArray()
+{
+    VMA_ASSERT(!m_InsideString);
+
+    WriteIndent(true);
+    m_SB.Add(']');
+
+    VMA_ASSERT(!m_Stack.empty() && m_Stack.back().type == COLLECTION_TYPE_ARRAY);
+    m_Stack.pop_back();
+}
+
+void VmaJsonWriter::WriteString(const char* pStr)
+{
+    BeginString(pStr);
+    EndString();
+}
+
+void VmaJsonWriter::BeginString(const char* pStr)
+{
+    VMA_ASSERT(!m_InsideString);
+
+    BeginValue(true);
+    m_SB.Add('"');
+    m_InsideString = true;
+    if(pStr != VMA_NULL && pStr[0] != '\0')
+    {
+        ContinueString(pStr);
+    }
+}
+
+void VmaJsonWriter::ContinueString(const char* pStr)
+{
+    VMA_ASSERT(m_InsideString);
+
+    const size_t strLen = strlen(pStr);
+    for(size_t i = 0; i < strLen; ++i)
+    {
+        char ch = pStr[i];
+        if(ch == '\\')
+        {
+            m_SB.Add("\\\\");
+        }
+        else if(ch == '"')
+        {
+            m_SB.Add("\\\"");
+        }
+        else if(ch >= 32)
+        {
+            m_SB.Add(ch);
+        }
+        else switch(ch)
+        {
+        case '\b':
+            m_SB.Add("\\b");
+            break;
+        case '\f':
+            m_SB.Add("\\f");
+            break;
+        case '\n':
+            m_SB.Add("\\n");
+            break;
+        case '\r':
+            m_SB.Add("\\r");
+            break;
+        case '\t':
+            m_SB.Add("\\t");
+            break;
+        default:
+            VMA_ASSERT(0 && "Character not currently supported.");
+            break;
+        }
+    }
+}
+
+void VmaJsonWriter::ContinueString(uint32_t n)
+{
+    VMA_ASSERT(m_InsideString);
+    m_SB.AddNumber(n);
+}
+
+void VmaJsonWriter::ContinueString(uint64_t n)
+{
+    VMA_ASSERT(m_InsideString);
+    m_SB.AddNumber(n);
+}
+
+void VmaJsonWriter::ContinueString_Pointer(const void* ptr)
+{
+    VMA_ASSERT(m_InsideString);
+    m_SB.AddPointer(ptr);
+}
+
+void VmaJsonWriter::EndString(const char* pStr)
+{
+    VMA_ASSERT(m_InsideString);
+    if(pStr != VMA_NULL && pStr[0] != '\0')
+    {
+        ContinueString(pStr);
+    }
+    m_SB.Add('"');
+    m_InsideString = false;
+}
+
+void VmaJsonWriter::WriteNumber(uint32_t n)
+{
+    VMA_ASSERT(!m_InsideString);
+    BeginValue(false);
+    m_SB.AddNumber(n);
+}
+
+void VmaJsonWriter::WriteNumber(uint64_t n)
+{
+    VMA_ASSERT(!m_InsideString);
+    BeginValue(false);
+    m_SB.AddNumber(n);
+}
+
+void VmaJsonWriter::WriteBool(bool b)
+{
+    VMA_ASSERT(!m_InsideString);
+    BeginValue(false);
+    m_SB.Add(b ? "true" : "false");
+}
+
+void VmaJsonWriter::WriteNull()
+{
+    VMA_ASSERT(!m_InsideString);
+    BeginValue(false);
+    m_SB.Add("null");
+}
+
+void VmaJsonWriter::BeginValue(bool isString)
+{
+    if(!m_Stack.empty())
+    {
+        StackItem& currItem = m_Stack.back();
+        if(currItem.type == COLLECTION_TYPE_OBJECT &&
+            currItem.valueCount % 2 == 0)
+        {
+            VMA_ASSERT(isString);
+        }
+
+        if(currItem.type == COLLECTION_TYPE_OBJECT &&
+            currItem.valueCount % 2 != 0)
+        {
+            m_SB.Add(": ");
+        }
+        else if(currItem.valueCount > 0)
+        {
+            m_SB.Add(", ");
+            WriteIndent();
+        }
+        else
+        {
+            WriteIndent();
+        }
+        ++currItem.valueCount;
+    }
+}
+
+void VmaJsonWriter::WriteIndent(bool oneLess)
+{
+    if(!m_Stack.empty() && !m_Stack.back().singleLineMode)
+    {
+        m_SB.AddNewLine();
+        
+        size_t count = m_Stack.size();
+        if(count > 0 && oneLess)
+        {
+            --count;
+        }
+        for(size_t i = 0; i < count; ++i)
+        {
+            m_SB.Add(INDENT);
+        }
+    }
+}
+
+#endif // #if VMA_STATS_STRING_ENABLED
+
+////////////////////////////////////////////////////////////////////////////////
+
+void VmaAllocation_T::SetUserData(VmaAllocator hAllocator, void* pUserData)
+{
+    if(IsUserDataString())
+    {
+        VMA_ASSERT(pUserData == VMA_NULL || pUserData != m_pUserData);
+
+        FreeUserDataString(hAllocator);
+
+        if(pUserData != VMA_NULL)
+        {
+            m_pUserData = VmaCreateStringCopy(hAllocator->GetAllocationCallbacks(), (const char*)pUserData);
+        }
+    }
+    else
+    {
+        m_pUserData = pUserData;
+    }
+}
+
+void VmaAllocation_T::ChangeBlockAllocation(
+    VmaAllocator hAllocator,
+    VmaDeviceMemoryBlock* block,
+    VkDeviceSize offset)
+{
+    VMA_ASSERT(block != VMA_NULL);
+    VMA_ASSERT(m_Type == ALLOCATION_TYPE_BLOCK);
+
+    // Move mapping reference counter from old block to new block.
+    if(block != m_BlockAllocation.m_Block)
+    {
+        uint32_t mapRefCount = m_MapCount & ~MAP_COUNT_FLAG_PERSISTENT_MAP;
+        if(IsPersistentMap())
+            ++mapRefCount;
+        m_BlockAllocation.m_Block->Unmap(hAllocator, mapRefCount);
+        block->Map(hAllocator, mapRefCount, VMA_NULL);
+    }
+
+    m_BlockAllocation.m_Block = block;
+    m_BlockAllocation.m_Offset = offset;
+}
+
+void VmaAllocation_T::ChangeOffset(VkDeviceSize newOffset)
+{
+    VMA_ASSERT(m_Type == ALLOCATION_TYPE_BLOCK);
+    m_BlockAllocation.m_Offset = newOffset;
+}
+
+VkDeviceSize VmaAllocation_T::GetOffset() const
+{
+    switch(m_Type)
+    {
+    case ALLOCATION_TYPE_BLOCK:
+        return m_BlockAllocation.m_Offset;
+    case ALLOCATION_TYPE_DEDICATED:
+        return 0;
+    default:
+        VMA_ASSERT(0);
+        return 0;
+    }
+}
+
+VkDeviceMemory VmaAllocation_T::GetMemory() const
+{
+    switch(m_Type)
+    {
+    case ALLOCATION_TYPE_BLOCK:
+        return m_BlockAllocation.m_Block->GetDeviceMemory();
+    case ALLOCATION_TYPE_DEDICATED:
+        return m_DedicatedAllocation.m_hMemory;
+    default:
+        VMA_ASSERT(0);
+        return VK_NULL_HANDLE;
+    }
+}
+
+void* VmaAllocation_T::GetMappedData() const
+{
+    switch(m_Type)
+    {
+    case ALLOCATION_TYPE_BLOCK:
+        if(m_MapCount != 0)
+        {
+            void* pBlockData = m_BlockAllocation.m_Block->GetMappedData();
+            VMA_ASSERT(pBlockData != VMA_NULL);
+            return (char*)pBlockData + m_BlockAllocation.m_Offset;
+        }
+        else
+        {
+            return VMA_NULL;
+        }
+        break;
+    case ALLOCATION_TYPE_DEDICATED:
+        VMA_ASSERT((m_DedicatedAllocation.m_pMappedData != VMA_NULL) == (m_MapCount != 0));
+        return m_DedicatedAllocation.m_pMappedData;
+    default:
+        VMA_ASSERT(0);
+        return VMA_NULL;
+    }
+}
+
+bool VmaAllocation_T::CanBecomeLost() const
+{
+    switch(m_Type)
+    {
+    case ALLOCATION_TYPE_BLOCK:
+        return m_BlockAllocation.m_CanBecomeLost;
+    case ALLOCATION_TYPE_DEDICATED:
+        return false;
+    default:
+        VMA_ASSERT(0);
+        return false;
+    }
+}
+
+bool VmaAllocation_T::MakeLost(uint32_t currentFrameIndex, uint32_t frameInUseCount)
+{
+    VMA_ASSERT(CanBecomeLost());
+
+    /*
+    Warning: This is a carefully designed algorithm.
+    Do not modify unless you really know what you're doing :)
+    */
+    uint32_t localLastUseFrameIndex = GetLastUseFrameIndex();
+    for(;;)
+    {
+        if(localLastUseFrameIndex == VMA_FRAME_INDEX_LOST)
+        {
+            VMA_ASSERT(0);
+            return false;
+        }
+        else if(localLastUseFrameIndex + frameInUseCount >= currentFrameIndex)
+        {
+            return false;
+        }
+        else // Last use time earlier than current time.
+        {
+            if(CompareExchangeLastUseFrameIndex(localLastUseFrameIndex, VMA_FRAME_INDEX_LOST))
+            {
+                // Setting hAllocation.LastUseFrameIndex atomic to VMA_FRAME_INDEX_LOST is enough to mark it as LOST.
+                // Calling code just needs to unregister this allocation in owning VmaDeviceMemoryBlock.
+                return true;
+            }
+        }
+    }
+}
+
+#if VMA_STATS_STRING_ENABLED
+
+// Correspond to values of enum VmaSuballocationType.
+static const char* VMA_SUBALLOCATION_TYPE_NAMES[] = {
+    "FREE",
+    "UNKNOWN",
+    "BUFFER",
+    "IMAGE_UNKNOWN",
+    "IMAGE_LINEAR",
+    "IMAGE_OPTIMAL",
+};
+
+void VmaAllocation_T::PrintParameters(class VmaJsonWriter& json) const
+{
+    json.WriteString("Type");
+    json.WriteString(VMA_SUBALLOCATION_TYPE_NAMES[m_SuballocationType]);
+
+    json.WriteString("Size");
+    json.WriteNumber(m_Size);
+
+    if(m_pUserData != VMA_NULL)
+    {
+        json.WriteString("UserData");
+        if(IsUserDataString())
+        {
+            json.WriteString((const char*)m_pUserData);
+        }
+        else
+        {
+            json.BeginString();
+            json.ContinueString_Pointer(m_pUserData);
+            json.EndString();
+        }
+    }
+
+    json.WriteString("CreationFrameIndex");
+    json.WriteNumber(m_CreationFrameIndex);
+
+    json.WriteString("LastUseFrameIndex");
+    json.WriteNumber(GetLastUseFrameIndex());
+
+    if(m_BufferImageUsage != 0)
+    {
+        json.WriteString("Usage");
+        json.WriteNumber(m_BufferImageUsage);
+    }
+}
+
+#endif
+
+void VmaAllocation_T::FreeUserDataString(VmaAllocator hAllocator)
+{
+    VMA_ASSERT(IsUserDataString());
+    VmaFreeString(hAllocator->GetAllocationCallbacks(), (char*)m_pUserData);
+    m_pUserData = VMA_NULL;
+}
+
+void VmaAllocation_T::BlockAllocMap()
+{
+    VMA_ASSERT(GetType() == ALLOCATION_TYPE_BLOCK);
+
+    if((m_MapCount & ~MAP_COUNT_FLAG_PERSISTENT_MAP) < 0x7F)
+    {
+        ++m_MapCount;
+    }
+    else
+    {
+        VMA_ASSERT(0 && "Allocation mapped too many times simultaneously.");
+    }
+}
+
+void VmaAllocation_T::BlockAllocUnmap()
+{
+    VMA_ASSERT(GetType() == ALLOCATION_TYPE_BLOCK);
+
+    if((m_MapCount & ~MAP_COUNT_FLAG_PERSISTENT_MAP) != 0)
+    {
+        --m_MapCount;
+    }
+    else
+    {
+        VMA_ASSERT(0 && "Unmapping allocation not previously mapped.");
+    }
+}
+
+VkResult VmaAllocation_T::DedicatedAllocMap(VmaAllocator hAllocator, void** ppData)
+{
+    VMA_ASSERT(GetType() == ALLOCATION_TYPE_DEDICATED);
+
+    if(m_MapCount != 0)
+    {
+        if((m_MapCount & ~MAP_COUNT_FLAG_PERSISTENT_MAP) < 0x7F)
+        {
+            VMA_ASSERT(m_DedicatedAllocation.m_pMappedData != VMA_NULL);
+            *ppData = m_DedicatedAllocation.m_pMappedData;
+            ++m_MapCount;
+            return VK_SUCCESS;
+        }
+        else
+        {
+            VMA_ASSERT(0 && "Dedicated allocation mapped too many times simultaneously.");
+            return VK_ERROR_MEMORY_MAP_FAILED;
+        }
+    }
+    else
+    {
+        VkResult result = (*hAllocator->GetVulkanFunctions().vkMapMemory)(
+            hAllocator->m_hDevice,
+            m_DedicatedAllocation.m_hMemory,
+            0, // offset
+            VK_WHOLE_SIZE,
+            0, // flags
+            ppData);
+        if(result == VK_SUCCESS)
+        {
+            m_DedicatedAllocation.m_pMappedData = *ppData;
+            m_MapCount = 1;
+        }
+        return result;
+    }
+}
+
+void VmaAllocation_T::DedicatedAllocUnmap(VmaAllocator hAllocator)
+{
+    VMA_ASSERT(GetType() == ALLOCATION_TYPE_DEDICATED);
+
+    if((m_MapCount & ~MAP_COUNT_FLAG_PERSISTENT_MAP) != 0)
+    {
+        --m_MapCount;
+        if(m_MapCount == 0)
+        {
+            m_DedicatedAllocation.m_pMappedData = VMA_NULL;
+            (*hAllocator->GetVulkanFunctions().vkUnmapMemory)(
+                hAllocator->m_hDevice,
+                m_DedicatedAllocation.m_hMemory);
+        }
+    }
+    else
+    {
+        VMA_ASSERT(0 && "Unmapping dedicated allocation not previously mapped.");
+    }
+}
+
+#if VMA_STATS_STRING_ENABLED
+
+static void VmaPrintStatInfo(VmaJsonWriter& json, const VmaStatInfo& stat)
+{
+    json.BeginObject();
+
+    json.WriteString("Blocks");
+    json.WriteNumber(stat.blockCount);
+
+    json.WriteString("Allocations");
+    json.WriteNumber(stat.allocationCount);
+
+    json.WriteString("UnusedRanges");
+    json.WriteNumber(stat.unusedRangeCount);
+
+    json.WriteString("UsedBytes");
+    json.WriteNumber(stat.usedBytes);
+
+    json.WriteString("UnusedBytes");
+    json.WriteNumber(stat.unusedBytes);
+
+    if(stat.allocationCount > 1)
+    {
+        json.WriteString("AllocationSize");
+        json.BeginObject(true);
+        json.WriteString("Min");
+        json.WriteNumber(stat.allocationSizeMin);
+        json.WriteString("Avg");
+        json.WriteNumber(stat.allocationSizeAvg);
+        json.WriteString("Max");
+        json.WriteNumber(stat.allocationSizeMax);
+        json.EndObject();
+    }
+
+    if(stat.unusedRangeCount > 1)
+    {
+        json.WriteString("UnusedRangeSize");
+        json.BeginObject(true);
+        json.WriteString("Min");
+        json.WriteNumber(stat.unusedRangeSizeMin);
+        json.WriteString("Avg");
+        json.WriteNumber(stat.unusedRangeSizeAvg);
+        json.WriteString("Max");
+        json.WriteNumber(stat.unusedRangeSizeMax);
+        json.EndObject();
+    }
+
+    json.EndObject();
+}
+
+#endif // #if VMA_STATS_STRING_ENABLED
+
+struct VmaSuballocationItemSizeLess
+{
+    bool operator()(
+        const VmaSuballocationList::iterator lhs,
+        const VmaSuballocationList::iterator rhs) const
+    {
+        return lhs->size < rhs->size;
+    }
+    bool operator()(
+        const VmaSuballocationList::iterator lhs,
+        VkDeviceSize rhsSize) const
+    {
+        return lhs->size < rhsSize;
+    }
+};
+
+
+////////////////////////////////////////////////////////////////////////////////
+// class VmaBlockMetadata
+
+VmaBlockMetadata::VmaBlockMetadata(VmaAllocator hAllocator) :
+    m_Size(0),
+    m_pAllocationCallbacks(hAllocator->GetAllocationCallbacks())
+{
+}
+
+#if VMA_STATS_STRING_ENABLED
+
+void VmaBlockMetadata::PrintDetailedMap_Begin(class VmaJsonWriter& json,
+    VkDeviceSize unusedBytes,
+    size_t allocationCount,
+    size_t unusedRangeCount) const
+{
+    json.BeginObject();
+
+    json.WriteString("TotalBytes");
+    json.WriteNumber(GetSize());
+
+    json.WriteString("UnusedBytes");
+    json.WriteNumber(unusedBytes);
+
+    json.WriteString("Allocations");
+    json.WriteNumber((uint64_t)allocationCount);
+
+    json.WriteString("UnusedRanges");
+    json.WriteNumber((uint64_t)unusedRangeCount);
+
+    json.WriteString("Suballocations");
+    json.BeginArray();
+}
+
+void VmaBlockMetadata::PrintDetailedMap_Allocation(class VmaJsonWriter& json,
+    VkDeviceSize offset,
+    VmaAllocation hAllocation) const
+{
+    json.BeginObject(true);
+        
+    json.WriteString("Offset");
+    json.WriteNumber(offset);
+
+    hAllocation->PrintParameters(json);
+
+    json.EndObject();
+}
+
+void VmaBlockMetadata::PrintDetailedMap_UnusedRange(class VmaJsonWriter& json,
+    VkDeviceSize offset,
+    VkDeviceSize size) const
+{
+    json.BeginObject(true);
+        
+    json.WriteString("Offset");
+    json.WriteNumber(offset);
+
+    json.WriteString("Type");
+    json.WriteString(VMA_SUBALLOCATION_TYPE_NAMES[VMA_SUBALLOCATION_TYPE_FREE]);
+
+    json.WriteString("Size");
+    json.WriteNumber(size);
+
+    json.EndObject();
+}
+
+void VmaBlockMetadata::PrintDetailedMap_End(class VmaJsonWriter& json) const
+{
+    json.EndArray();
+    json.EndObject();
+}
+
+#endif // #if VMA_STATS_STRING_ENABLED
+
+////////////////////////////////////////////////////////////////////////////////
+// class VmaBlockMetadata_Generic
+
+VmaBlockMetadata_Generic::VmaBlockMetadata_Generic(VmaAllocator hAllocator) :
+    VmaBlockMetadata(hAllocator),
+    m_FreeCount(0),
+    m_SumFreeSize(0),
+    m_Suballocations(VmaStlAllocator<VmaSuballocation>(hAllocator->GetAllocationCallbacks())),
+    m_FreeSuballocationsBySize(VmaStlAllocator<VmaSuballocationList::iterator>(hAllocator->GetAllocationCallbacks()))
+{
+}
+
+VmaBlockMetadata_Generic::~VmaBlockMetadata_Generic()
+{
+}
+
+void VmaBlockMetadata_Generic::Init(VkDeviceSize size)
+{
+    VmaBlockMetadata::Init(size);
+
+    m_FreeCount = 1;
+    m_SumFreeSize = size;
+
+    VmaSuballocation suballoc = {};
+    suballoc.offset = 0;
+    suballoc.size = size;
+    suballoc.type = VMA_SUBALLOCATION_TYPE_FREE;
+    suballoc.hAllocation = VK_NULL_HANDLE;
+
+    VMA_ASSERT(size > VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER);
+    m_Suballocations.push_back(suballoc);
+    VmaSuballocationList::iterator suballocItem = m_Suballocations.end();
+    --suballocItem;
+    m_FreeSuballocationsBySize.push_back(suballocItem);
+}
+
+bool VmaBlockMetadata_Generic::Validate() const
+{
+    VMA_VALIDATE(!m_Suballocations.empty());
+    
+    // Expected offset of new suballocation as calculated from previous ones.
+    VkDeviceSize calculatedOffset = 0;
+    // Expected number of free suballocations as calculated from traversing their list.
+    uint32_t calculatedFreeCount = 0;
+    // Expected sum size of free suballocations as calculated from traversing their list.
+    VkDeviceSize calculatedSumFreeSize = 0;
+    // Expected number of free suballocations that should be registered in
+    // m_FreeSuballocationsBySize calculated from traversing their list.
+    size_t freeSuballocationsToRegister = 0;
+    // True if previous visited suballocation was free.
+    bool prevFree = false;
+
+    for(VmaSuballocationList::const_iterator suballocItem = m_Suballocations.cbegin();
+        suballocItem != m_Suballocations.cend();
+        ++suballocItem)
+    {
+        const VmaSuballocation& subAlloc = *suballocItem;
+        
+        // Actual offset of this suballocation doesn't match expected one.
+        VMA_VALIDATE(subAlloc.offset == calculatedOffset);
+
+        const bool currFree = (subAlloc.type == VMA_SUBALLOCATION_TYPE_FREE);
+        // Two adjacent free suballocations are invalid. They should be merged.
+        VMA_VALIDATE(!prevFree || !currFree);
+
+        VMA_VALIDATE(currFree == (subAlloc.hAllocation == VK_NULL_HANDLE));
+
+        if(currFree)
+        {
+            calculatedSumFreeSize += subAlloc.size;
+            ++calculatedFreeCount;
+            if(subAlloc.size >= VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER)
+            {
+                ++freeSuballocationsToRegister;
+            }
+
+            // Margin required between allocations - every free space must be at least that large.
+            VMA_VALIDATE(subAlloc.size >= VMA_DEBUG_MARGIN);
+        }
+        else
+        {
+            VMA_VALIDATE(subAlloc.hAllocation->GetOffset() == subAlloc.offset);
+            VMA_VALIDATE(subAlloc.hAllocation->GetSize() == subAlloc.size);
+
+            // Margin required between allocations - previous allocation must be free.
+            VMA_VALIDATE(VMA_DEBUG_MARGIN == 0 || prevFree);
+        }
+
+        calculatedOffset += subAlloc.size;
+        prevFree = currFree;
+    }
+
+    // Number of free suballocations registered in m_FreeSuballocationsBySize doesn't
+    // match expected one.
+    VMA_VALIDATE(m_FreeSuballocationsBySize.size() == freeSuballocationsToRegister);
+
+    VkDeviceSize lastSize = 0;
+    for(size_t i = 0; i < m_FreeSuballocationsBySize.size(); ++i)
+    {
+        VmaSuballocationList::iterator suballocItem = m_FreeSuballocationsBySize[i];
+        
+        // Only free suballocations can be registered in m_FreeSuballocationsBySize.
+        VMA_VALIDATE(suballocItem->type == VMA_SUBALLOCATION_TYPE_FREE);
+        // They must be sorted by size ascending.
+        VMA_VALIDATE(suballocItem->size >= lastSize);
+
+        lastSize = suballocItem->size;
+    }
+
+    // Check if totals match calculacted values.
+    VMA_VALIDATE(ValidateFreeSuballocationList());
+    VMA_VALIDATE(calculatedOffset == GetSize());
+    VMA_VALIDATE(calculatedSumFreeSize == m_SumFreeSize);
+    VMA_VALIDATE(calculatedFreeCount == m_FreeCount);
+
+    return true;
+}
+
+VkDeviceSize VmaBlockMetadata_Generic::GetUnusedRangeSizeMax() const
+{
+    if(!m_FreeSuballocationsBySize.empty())
+    {
+        return m_FreeSuballocationsBySize.back()->size;
+    }
+    else
+    {
+        return 0;
+    }
+}
+
+bool VmaBlockMetadata_Generic::IsEmpty() const
+{
+    return (m_Suballocations.size() == 1) && (m_FreeCount == 1);
+}
+
+void VmaBlockMetadata_Generic::CalcAllocationStatInfo(VmaStatInfo& outInfo) const
+{
+    outInfo.blockCount = 1;
+
+    const uint32_t rangeCount = (uint32_t)m_Suballocations.size();
+    outInfo.allocationCount = rangeCount - m_FreeCount;
+    outInfo.unusedRangeCount = m_FreeCount;
+    
+    outInfo.unusedBytes = m_SumFreeSize;
+    outInfo.usedBytes = GetSize() - outInfo.unusedBytes;
+
+    outInfo.allocationSizeMin = UINT64_MAX;
+    outInfo.allocationSizeMax = 0;
+    outInfo.unusedRangeSizeMin = UINT64_MAX;
+    outInfo.unusedRangeSizeMax = 0;
+
+    for(VmaSuballocationList::const_iterator suballocItem = m_Suballocations.cbegin();
+        suballocItem != m_Suballocations.cend();
+        ++suballocItem)
+    {
+        const VmaSuballocation& suballoc = *suballocItem;
+        if(suballoc.type != VMA_SUBALLOCATION_TYPE_FREE)
+        {
+            outInfo.allocationSizeMin = VMA_MIN(outInfo.allocationSizeMin, suballoc.size);
+            outInfo.allocationSizeMax = VMA_MAX(outInfo.allocationSizeMax, suballoc.size);
+        }
+        else
+        {
+            outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, suballoc.size);
+            outInfo.unusedRangeSizeMax = VMA_MAX(outInfo.unusedRangeSizeMax, suballoc.size);
+        }
+    }
+}
+
+void VmaBlockMetadata_Generic::AddPoolStats(VmaPoolStats& inoutStats) const
+{
+    const uint32_t rangeCount = (uint32_t)m_Suballocations.size();
+
+    inoutStats.size += GetSize();
+    inoutStats.unusedSize += m_SumFreeSize;
+    inoutStats.allocationCount += rangeCount - m_FreeCount;
+    inoutStats.unusedRangeCount += m_FreeCount;
+    inoutStats.unusedRangeSizeMax = VMA_MAX(inoutStats.unusedRangeSizeMax, GetUnusedRangeSizeMax());
+}
+
+#if VMA_STATS_STRING_ENABLED
+
+void VmaBlockMetadata_Generic::PrintDetailedMap(class VmaJsonWriter& json) const
+{
+    PrintDetailedMap_Begin(json,
+        m_SumFreeSize, // unusedBytes
+        m_Suballocations.size() - (size_t)m_FreeCount, // allocationCount
+        m_FreeCount); // unusedRangeCount
+
+    size_t i = 0;
+    for(VmaSuballocationList::const_iterator suballocItem = m_Suballocations.cbegin();
+        suballocItem != m_Suballocations.cend();
+        ++suballocItem, ++i)
+    {
+        if(suballocItem->type == VMA_SUBALLOCATION_TYPE_FREE)
+        {
+            PrintDetailedMap_UnusedRange(json, suballocItem->offset, suballocItem->size);
+        }
+        else
+        {
+            PrintDetailedMap_Allocation(json, suballocItem->offset, suballocItem->hAllocation);
+        }
+    }
+
+    PrintDetailedMap_End(json);
+}
+
+#endif // #if VMA_STATS_STRING_ENABLED
+
+bool VmaBlockMetadata_Generic::CreateAllocationRequest(
+    uint32_t currentFrameIndex,
+    uint32_t frameInUseCount,
+    VkDeviceSize bufferImageGranularity,
+    VkDeviceSize allocSize,
+    VkDeviceSize allocAlignment,
+    bool upperAddress,
+    VmaSuballocationType allocType,
+    bool canMakeOtherLost,
+    uint32_t strategy,
+    VmaAllocationRequest* pAllocationRequest)
+{
+    VMA_ASSERT(allocSize > 0);
+    VMA_ASSERT(!upperAddress);
+    VMA_ASSERT(allocType != VMA_SUBALLOCATION_TYPE_FREE);
+    VMA_ASSERT(pAllocationRequest != VMA_NULL);
+    VMA_HEAVY_ASSERT(Validate());
+
+    pAllocationRequest->type = VmaAllocationRequestType::Normal;
+
+    // There is not enough total free space in this block to fullfill the request: Early return.
+    if(canMakeOtherLost == false &&
+        m_SumFreeSize < allocSize + 2 * VMA_DEBUG_MARGIN)
+    {
+        return false;
+    }
+
+    // New algorithm, efficiently searching freeSuballocationsBySize.
+    const size_t freeSuballocCount = m_FreeSuballocationsBySize.size();
+    if(freeSuballocCount > 0)
+    {
+        if(strategy == VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT)
+        {
+            // Find first free suballocation with size not less than allocSize + 2 * VMA_DEBUG_MARGIN.
+            VmaSuballocationList::iterator* const it = VmaBinaryFindFirstNotLess(
+                m_FreeSuballocationsBySize.data(),
+                m_FreeSuballocationsBySize.data() + freeSuballocCount,
+                allocSize + 2 * VMA_DEBUG_MARGIN,
+                VmaSuballocationItemSizeLess());
+            size_t index = it - m_FreeSuballocationsBySize.data();
+            for(; index < freeSuballocCount; ++index)
+            {
+                if(CheckAllocation(
+                    currentFrameIndex,
+                    frameInUseCount,
+                    bufferImageGranularity,
+                    allocSize,
+                    allocAlignment,
+                    allocType,
+                    m_FreeSuballocationsBySize[index],
+                    false, // canMakeOtherLost
+                    &pAllocationRequest->offset,
+                    &pAllocationRequest->itemsToMakeLostCount,
+                    &pAllocationRequest->sumFreeSize,
+                    &pAllocationRequest->sumItemSize))
+                {
+                    pAllocationRequest->item = m_FreeSuballocationsBySize[index];
+                    return true;
+                }
+            }
+        }
+        else if(strategy == VMA_ALLOCATION_INTERNAL_STRATEGY_MIN_OFFSET)
+        {
+            for(VmaSuballocationList::iterator it = m_Suballocations.begin();
+                it != m_Suballocations.end();
+                ++it)
+            {
+                if(it->type == VMA_SUBALLOCATION_TYPE_FREE && CheckAllocation(
+                    currentFrameIndex,
+                    frameInUseCount,
+                    bufferImageGranularity,
+                    allocSize,
+                    allocAlignment,
+                    allocType,
+                    it,
+                    false, // canMakeOtherLost
+                    &pAllocationRequest->offset,
+                    &pAllocationRequest->itemsToMakeLostCount,
+                    &pAllocationRequest->sumFreeSize,
+                    &pAllocationRequest->sumItemSize))
+                {
+                    pAllocationRequest->item = it;
+                    return true;
+                }
+            }
+        }
+        else // WORST_FIT, FIRST_FIT
+        {
+            // Search staring from biggest suballocations.
+            for(size_t index = freeSuballocCount; index--; )
+            {
+                if(CheckAllocation(
+                    currentFrameIndex,
+                    frameInUseCount,
+                    bufferImageGranularity,
+                    allocSize,
+                    allocAlignment,
+                    allocType,
+                    m_FreeSuballocationsBySize[index],
+                    false, // canMakeOtherLost
+                    &pAllocationRequest->offset,
+                    &pAllocationRequest->itemsToMakeLostCount,
+                    &pAllocationRequest->sumFreeSize,
+                    &pAllocationRequest->sumItemSize))
+                {
+                    pAllocationRequest->item = m_FreeSuballocationsBySize[index];
+                    return true;
+                }
+            }
+        }
+    }
+
+    if(canMakeOtherLost)
+    {
+        // Brute-force algorithm. TODO: Come up with something better.
+
+        bool found = false;
+        VmaAllocationRequest tmpAllocRequest = {};
+        tmpAllocRequest.type = VmaAllocationRequestType::Normal;
+        for(VmaSuballocationList::iterator suballocIt = m_Suballocations.begin();
+            suballocIt != m_Suballocations.end();
+            ++suballocIt)
+        {
+            if(suballocIt->type == VMA_SUBALLOCATION_TYPE_FREE ||
+                suballocIt->hAllocation->CanBecomeLost())
+            {
+                if(CheckAllocation(
+                    currentFrameIndex,
+                    frameInUseCount,
+                    bufferImageGranularity,
+                    allocSize,
+                    allocAlignment,
+                    allocType,
+                    suballocIt,
+                    canMakeOtherLost,
+                    &tmpAllocRequest.offset,
+                    &tmpAllocRequest.itemsToMakeLostCount,
+                    &tmpAllocRequest.sumFreeSize,
+                    &tmpAllocRequest.sumItemSize))
+                {
+                    if(strategy == VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT)
+                    {
+                        *pAllocationRequest = tmpAllocRequest;
+                        pAllocationRequest->item = suballocIt;
+                        break;
+                    }
+                    if(!found || tmpAllocRequest.CalcCost() < pAllocationRequest->CalcCost())
+                    {
+                        *pAllocationRequest = tmpAllocRequest;
+                        pAllocationRequest->item = suballocIt;
+                        found = true;
+                    }
+                }
+            }
+        }
+
+        return found;
+    }
+
+    return false;
+}
+
+bool VmaBlockMetadata_Generic::MakeRequestedAllocationsLost(
+    uint32_t currentFrameIndex,
+    uint32_t frameInUseCount,
+    VmaAllocationRequest* pAllocationRequest)
+{
+    VMA_ASSERT(pAllocationRequest && pAllocationRequest->type == VmaAllocationRequestType::Normal);
+
+    while(pAllocationRequest->itemsToMakeLostCount > 0)
+    {
+        if(pAllocationRequest->item->type == VMA_SUBALLOCATION_TYPE_FREE)
+        {
+            ++pAllocationRequest->item;
+        }
+        VMA_ASSERT(pAllocationRequest->item != m_Suballocations.end());
+        VMA_ASSERT(pAllocationRequest->item->hAllocation != VK_NULL_HANDLE);
+        VMA_ASSERT(pAllocationRequest->item->hAllocation->CanBecomeLost());
+        if(pAllocationRequest->item->hAllocation->MakeLost(currentFrameIndex, frameInUseCount))
+        {
+            pAllocationRequest->item = FreeSuballocation(pAllocationRequest->item);
+            --pAllocationRequest->itemsToMakeLostCount;
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+    VMA_HEAVY_ASSERT(Validate());
+    VMA_ASSERT(pAllocationRequest->item != m_Suballocations.end());
+    VMA_ASSERT(pAllocationRequest->item->type == VMA_SUBALLOCATION_TYPE_FREE);
+    
+    return true;
+}
+
+uint32_t VmaBlockMetadata_Generic::MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount)
+{
+    uint32_t lostAllocationCount = 0;
+    for(VmaSuballocationList::iterator it = m_Suballocations.begin();
+        it != m_Suballocations.end();
+        ++it)
+    {
+        if(it->type != VMA_SUBALLOCATION_TYPE_FREE &&
+            it->hAllocation->CanBecomeLost() &&
+            it->hAllocation->MakeLost(currentFrameIndex, frameInUseCount))
+        {
+            it = FreeSuballocation(it);
+            ++lostAllocationCount;
+        }
+    }
+    return lostAllocationCount;
+}
+
+VkResult VmaBlockMetadata_Generic::CheckCorruption(const void* pBlockData)
+{
+    for(VmaSuballocationList::iterator it = m_Suballocations.begin();
+        it != m_Suballocations.end();
+        ++it)
+    {
+        if(it->type != VMA_SUBALLOCATION_TYPE_FREE)
+        {
+            if(!VmaValidateMagicValue(pBlockData, it->offset - VMA_DEBUG_MARGIN))
+            {
+                VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED BEFORE VALIDATED ALLOCATION!");
+                return VK_ERROR_VALIDATION_FAILED_EXT;
+            }
+            if(!VmaValidateMagicValue(pBlockData, it->offset + it->size))
+            {
+                VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED AFTER VALIDATED ALLOCATION!");
+                return VK_ERROR_VALIDATION_FAILED_EXT;
+            }
+        }
+    }
+
+    return VK_SUCCESS;
+}
+
+void VmaBlockMetadata_Generic::Alloc(
+    const VmaAllocationRequest& request,
+    VmaSuballocationType type,
+    VkDeviceSize allocSize,
+    VmaAllocation hAllocation)
+{
+    VMA_ASSERT(request.type == VmaAllocationRequestType::Normal);
+    VMA_ASSERT(request.item != m_Suballocations.end());
+    VmaSuballocation& suballoc = *request.item;
+    // Given suballocation is a free block.
+    VMA_ASSERT(suballoc.type == VMA_SUBALLOCATION_TYPE_FREE);
+    // Given offset is inside this suballocation.
+    VMA_ASSERT(request.offset >= suballoc.offset);
+    const VkDeviceSize paddingBegin = request.offset - suballoc.offset;
+    VMA_ASSERT(suballoc.size >= paddingBegin + allocSize);
+    const VkDeviceSize paddingEnd = suballoc.size - paddingBegin - allocSize;
+
+    // Unregister this free suballocation from m_FreeSuballocationsBySize and update
+    // it to become used.
+    UnregisterFreeSuballocation(request.item);
+
+    suballoc.offset = request.offset;
+    suballoc.size = allocSize;
+    suballoc.type = type;
+    suballoc.hAllocation = hAllocation;
+
+    // If there are any free bytes remaining at the end, insert new free suballocation after current one.
+    if(paddingEnd)
+    {
+        VmaSuballocation paddingSuballoc = {};
+        paddingSuballoc.offset = request.offset + allocSize;
+        paddingSuballoc.size = paddingEnd;
+        paddingSuballoc.type = VMA_SUBALLOCATION_TYPE_FREE;
+        VmaSuballocationList::iterator next = request.item;
+        ++next;
+        const VmaSuballocationList::iterator paddingEndItem =
+            m_Suballocations.insert(next, paddingSuballoc);
+        RegisterFreeSuballocation(paddingEndItem);
+    }
+
+    // If there are any free bytes remaining at the beginning, insert new free suballocation before current one.
+    if(paddingBegin)
+    {
+        VmaSuballocation paddingSuballoc = {};
+        paddingSuballoc.offset = request.offset - paddingBegin;
+        paddingSuballoc.size = paddingBegin;
+        paddingSuballoc.type = VMA_SUBALLOCATION_TYPE_FREE;
+        const VmaSuballocationList::iterator paddingBeginItem =
+            m_Suballocations.insert(request.item, paddingSuballoc);
+        RegisterFreeSuballocation(paddingBeginItem);
+    }
+
+    // Update totals.
+    m_FreeCount = m_FreeCount - 1;
+    if(paddingBegin > 0)
+    {
+        ++m_FreeCount;
+    }
+    if(paddingEnd > 0)
+    {
+        ++m_FreeCount;
+    }
+    m_SumFreeSize -= allocSize;
+}
+
+void VmaBlockMetadata_Generic::Free(const VmaAllocation allocation)
+{
+    for(VmaSuballocationList::iterator suballocItem = m_Suballocations.begin();
+        suballocItem != m_Suballocations.end();
+        ++suballocItem)
+    {
+        VmaSuballocation& suballoc = *suballocItem;
+        if(suballoc.hAllocation == allocation)
+        {
+            FreeSuballocation(suballocItem);
+            VMA_HEAVY_ASSERT(Validate());
+            return;
+        }
+    }
+    VMA_ASSERT(0 && "Not found!");
+}
+
+void VmaBlockMetadata_Generic::FreeAtOffset(VkDeviceSize offset)
+{
+    for(VmaSuballocationList::iterator suballocItem = m_Suballocations.begin();
+        suballocItem != m_Suballocations.end();
+        ++suballocItem)
+    {
+        VmaSuballocation& suballoc = *suballocItem;
+        if(suballoc.offset == offset)
+        {
+            FreeSuballocation(suballocItem);
+            return;
+        }
+    }
+    VMA_ASSERT(0 && "Not found!");
+}
+
+bool VmaBlockMetadata_Generic::ValidateFreeSuballocationList() const
+{
+    VkDeviceSize lastSize = 0;
+    for(size_t i = 0, count = m_FreeSuballocationsBySize.size(); i < count; ++i)
+    {
+        const VmaSuballocationList::iterator it = m_FreeSuballocationsBySize[i];
+
+        VMA_VALIDATE(it->type == VMA_SUBALLOCATION_TYPE_FREE);
+        VMA_VALIDATE(it->size >= VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER);
+        VMA_VALIDATE(it->size >= lastSize);
+        lastSize = it->size;
+    }
+    return true;
+}
+
+bool VmaBlockMetadata_Generic::CheckAllocation(
+    uint32_t currentFrameIndex,
+    uint32_t frameInUseCount,
+    VkDeviceSize bufferImageGranularity,
+    VkDeviceSize allocSize,
+    VkDeviceSize allocAlignment,
+    VmaSuballocationType allocType,
+    VmaSuballocationList::const_iterator suballocItem,
+    bool canMakeOtherLost,
+    VkDeviceSize* pOffset,
+    size_t* itemsToMakeLostCount,
+    VkDeviceSize* pSumFreeSize,
+    VkDeviceSize* pSumItemSize) const
+{
+    VMA_ASSERT(allocSize > 0);
+    VMA_ASSERT(allocType != VMA_SUBALLOCATION_TYPE_FREE);
+    VMA_ASSERT(suballocItem != m_Suballocations.cend());
+    VMA_ASSERT(pOffset != VMA_NULL);
+    
+    *itemsToMakeLostCount = 0;
+    *pSumFreeSize = 0;
+    *pSumItemSize = 0;
+
+    if(canMakeOtherLost)
+    {
+        if(suballocItem->type == VMA_SUBALLOCATION_TYPE_FREE)
+        {
+            *pSumFreeSize = suballocItem->size;
+        }
+        else
+        {
+            if(suballocItem->hAllocation->CanBecomeLost() &&
+                suballocItem->hAllocation->GetLastUseFrameIndex() + frameInUseCount < currentFrameIndex)
+            {
+                ++*itemsToMakeLostCount;
+                *pSumItemSize = suballocItem->size;
+            }
+            else
+            {
+                return false;
+            }
+        }
+
+        // Remaining size is too small for this request: Early return.
+        if(GetSize() - suballocItem->offset < allocSize)
+        {
+            return false;
+        }
+
+        // Start from offset equal to beginning of this suballocation.
+        *pOffset = suballocItem->offset;
+    
+        // Apply VMA_DEBUG_MARGIN at the beginning.
+        if(VMA_DEBUG_MARGIN > 0)
+        {
+            *pOffset += VMA_DEBUG_MARGIN;
+        }
+    
+        // Apply alignment.
+        *pOffset = VmaAlignUp(*pOffset, allocAlignment);
+
+        // Check previous suballocations for BufferImageGranularity conflicts.
+        // Make bigger alignment if necessary.
+        if(bufferImageGranularity > 1)
+        {
+            bool bufferImageGranularityConflict = false;
+            VmaSuballocationList::const_iterator prevSuballocItem = suballocItem;
+            while(prevSuballocItem != m_Suballocations.cbegin())
+            {
+                --prevSuballocItem;
+                const VmaSuballocation& prevSuballoc = *prevSuballocItem;
+                if(VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, *pOffset, bufferImageGranularity))
+                {
+                    if(VmaIsBufferImageGranularityConflict(prevSuballoc.type, allocType))
+                    {
+                        bufferImageGranularityConflict = true;
+                        break;
+                    }
+                }
+                else
+                    // Already on previous page.
+                    break;
+            }
+            if(bufferImageGranularityConflict)
+            {
+                *pOffset = VmaAlignUp(*pOffset, bufferImageGranularity);
+            }
+        }
+    
+        // Now that we have final *pOffset, check if we are past suballocItem.
+        // If yes, return false - this function should be called for another suballocItem as starting point.
+        if(*pOffset >= suballocItem->offset + suballocItem->size)
+        {
+            return false;
+        }
+    
+        // Calculate padding at the beginning based on current offset.
+        const VkDeviceSize paddingBegin = *pOffset - suballocItem->offset;
+
+        // Calculate required margin at the end.
+        const VkDeviceSize requiredEndMargin = VMA_DEBUG_MARGIN;
+
+        const VkDeviceSize totalSize = paddingBegin + allocSize + requiredEndMargin;
+        // Another early return check.
+        if(suballocItem->offset + totalSize > GetSize())
+        {
+            return false;
+        }
+
+        // Advance lastSuballocItem until desired size is reached.
+        // Update itemsToMakeLostCount.
+        VmaSuballocationList::const_iterator lastSuballocItem = suballocItem;
+        if(totalSize > suballocItem->size)
+        {
+            VkDeviceSize remainingSize = totalSize - suballocItem->size;
+            while(remainingSize > 0)
+            {
+                ++lastSuballocItem;
+                if(lastSuballocItem == m_Suballocations.cend())
+                {
+                    return false;
+                }
+                if(lastSuballocItem->type == VMA_SUBALLOCATION_TYPE_FREE)
+                {
+                    *pSumFreeSize += lastSuballocItem->size;
+                }
+                else
+                {
+                    VMA_ASSERT(lastSuballocItem->hAllocation != VK_NULL_HANDLE);
+                    if(lastSuballocItem->hAllocation->CanBecomeLost() &&
+                        lastSuballocItem->hAllocation->GetLastUseFrameIndex() + frameInUseCount < currentFrameIndex)
+                    {
+                        ++*itemsToMakeLostCount;
+                        *pSumItemSize += lastSuballocItem->size;
+                    }
+                    else
+                    {
+                        return false;
+                    }
+                }
+                remainingSize = (lastSuballocItem->size < remainingSize) ?
+                    remainingSize - lastSuballocItem->size : 0;
+            }
+        }
+
+        // Check next suballocations for BufferImageGranularity conflicts.
+        // If conflict exists, we must mark more allocations lost or fail.
+        if(bufferImageGranularity > 1)
+        {
+            VmaSuballocationList::const_iterator nextSuballocItem = lastSuballocItem;
+            ++nextSuballocItem;
+            while(nextSuballocItem != m_Suballocations.cend())
+            {
+                const VmaSuballocation& nextSuballoc = *nextSuballocItem;
+                if(VmaBlocksOnSamePage(*pOffset, allocSize, nextSuballoc.offset, bufferImageGranularity))
+                {
+                    if(VmaIsBufferImageGranularityConflict(allocType, nextSuballoc.type))
+                    {
+                        VMA_ASSERT(nextSuballoc.hAllocation != VK_NULL_HANDLE);
+                        if(nextSuballoc.hAllocation->CanBecomeLost() &&
+                            nextSuballoc.hAllocation->GetLastUseFrameIndex() + frameInUseCount < currentFrameIndex)
+                        {
+                            ++*itemsToMakeLostCount;
+                        }
+                        else
+                        {
+                            return false;
+                        }
+                    }
+                }
+                else
+                {
+                    // Already on next page.
+                    break;
+                }
+                ++nextSuballocItem;
+            }
+        }
+    }
+    else
+    {
+        const VmaSuballocation& suballoc = *suballocItem;
+        VMA_ASSERT(suballoc.type == VMA_SUBALLOCATION_TYPE_FREE);
+
+        *pSumFreeSize = suballoc.size;
+
+        // Size of this suballocation is too small for this request: Early return.
+        if(suballoc.size < allocSize)
+        {
+            return false;
+        }
+
+        // Start from offset equal to beginning of this suballocation.
+        *pOffset = suballoc.offset;
+    
+        // Apply VMA_DEBUG_MARGIN at the beginning.
+        if(VMA_DEBUG_MARGIN > 0)
+        {
+            *pOffset += VMA_DEBUG_MARGIN;
+        }
+    
+        // Apply alignment.
+        *pOffset = VmaAlignUp(*pOffset, allocAlignment);
+    
+        // Check previous suballocations for BufferImageGranularity conflicts.
+        // Make bigger alignment if necessary.
+        if(bufferImageGranularity > 1)
+        {
+            bool bufferImageGranularityConflict = false;
+            VmaSuballocationList::const_iterator prevSuballocItem = suballocItem;
+            while(prevSuballocItem != m_Suballocations.cbegin())
+            {
+                --prevSuballocItem;
+                const VmaSuballocation& prevSuballoc = *prevSuballocItem;
+                if(VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, *pOffset, bufferImageGranularity))
+                {
+                    if(VmaIsBufferImageGranularityConflict(prevSuballoc.type, allocType))
+                    {
+                        bufferImageGranularityConflict = true;
+                        break;
+                    }
+                }
+                else
+                    // Already on previous page.
+                    break;
+            }
+            if(bufferImageGranularityConflict)
+            {
+                *pOffset = VmaAlignUp(*pOffset, bufferImageGranularity);
+            }
+        }
+    
+        // Calculate padding at the beginning based on current offset.
+        const VkDeviceSize paddingBegin = *pOffset - suballoc.offset;
+
+        // Calculate required margin at the end.
+        const VkDeviceSize requiredEndMargin = VMA_DEBUG_MARGIN;
+
+        // Fail if requested size plus margin before and after is bigger than size of this suballocation.
+        if(paddingBegin + allocSize + requiredEndMargin > suballoc.size)
+        {
+            return false;
+        }
+
+        // Check next suballocations for BufferImageGranularity conflicts.
+        // If conflict exists, allocation cannot be made here.
+        if(bufferImageGranularity > 1)
+        {
+            VmaSuballocationList::const_iterator nextSuballocItem = suballocItem;
+            ++nextSuballocItem;
+            while(nextSuballocItem != m_Suballocations.cend())
+            {
+                const VmaSuballocation& nextSuballoc = *nextSuballocItem;
+                if(VmaBlocksOnSamePage(*pOffset, allocSize, nextSuballoc.offset, bufferImageGranularity))
+                {
+                    if(VmaIsBufferImageGranularityConflict(allocType, nextSuballoc.type))
+                    {
+                        return false;
+                    }
+                }
+                else
+                {
+                    // Already on next page.
+                    break;
+                }
+                ++nextSuballocItem;
+            }
+        }
+    }
+
+    // All tests passed: Success. pOffset is already filled.
+    return true;
+}
+
+void VmaBlockMetadata_Generic::MergeFreeWithNext(VmaSuballocationList::iterator item)
+{
+    VMA_ASSERT(item != m_Suballocations.end());
+    VMA_ASSERT(item->type == VMA_SUBALLOCATION_TYPE_FREE);
+    
+    VmaSuballocationList::iterator nextItem = item;
+    ++nextItem;
+    VMA_ASSERT(nextItem != m_Suballocations.end());
+    VMA_ASSERT(nextItem->type == VMA_SUBALLOCATION_TYPE_FREE);
+
+    item->size += nextItem->size;
+    --m_FreeCount;
+    m_Suballocations.erase(nextItem);
+}
+
+VmaSuballocationList::iterator VmaBlockMetadata_Generic::FreeSuballocation(VmaSuballocationList::iterator suballocItem)
+{
+    // Change this suballocation to be marked as free.
+    VmaSuballocation& suballoc = *suballocItem;
+    suballoc.type = VMA_SUBALLOCATION_TYPE_FREE;
+    suballoc.hAllocation = VK_NULL_HANDLE;
+    
+    // Update totals.
+    ++m_FreeCount;
+    m_SumFreeSize += suballoc.size;
+
+    // Merge with previous and/or next suballocation if it's also free.
+    bool mergeWithNext = false;
+    bool mergeWithPrev = false;
+    
+    VmaSuballocationList::iterator nextItem = suballocItem;
+    ++nextItem;
+    if((nextItem != m_Suballocations.end()) && (nextItem->type == VMA_SUBALLOCATION_TYPE_FREE))
+    {
+        mergeWithNext = true;
+    }
+
+    VmaSuballocationList::iterator prevItem = suballocItem;
+    if(suballocItem != m_Suballocations.begin())
+    {
+        --prevItem;
+        if(prevItem->type == VMA_SUBALLOCATION_TYPE_FREE)
+        {
+            mergeWithPrev = true;
+        }
+    }
+
+    if(mergeWithNext)
+    {
+        UnregisterFreeSuballocation(nextItem);
+        MergeFreeWithNext(suballocItem);
+    }
+
+    if(mergeWithPrev)
+    {
+        UnregisterFreeSuballocation(prevItem);
+        MergeFreeWithNext(prevItem);
+        RegisterFreeSuballocation(prevItem);
+        return prevItem;
+    }
+    else
+    {
+        RegisterFreeSuballocation(suballocItem);
+        return suballocItem;
+    }
+}
+
+void VmaBlockMetadata_Generic::RegisterFreeSuballocation(VmaSuballocationList::iterator item)
+{
+    VMA_ASSERT(item->type == VMA_SUBALLOCATION_TYPE_FREE);
+    VMA_ASSERT(item->size > 0);
+
+    // You may want to enable this validation at the beginning or at the end of
+    // this function, depending on what do you want to check.
+    VMA_HEAVY_ASSERT(ValidateFreeSuballocationList());
+
+    if(item->size >= VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER)
+    {
+        if(m_FreeSuballocationsBySize.empty())
+        {
+            m_FreeSuballocationsBySize.push_back(item);
+        }
+        else
+        {
+            VmaVectorInsertSorted<VmaSuballocationItemSizeLess>(m_FreeSuballocationsBySize, item);
+        }
+    }
+
+    //VMA_HEAVY_ASSERT(ValidateFreeSuballocationList());
+}
+
+
+void VmaBlockMetadata_Generic::UnregisterFreeSuballocation(VmaSuballocationList::iterator item)
+{
+    VMA_ASSERT(item->type == VMA_SUBALLOCATION_TYPE_FREE);
+    VMA_ASSERT(item->size > 0);
+
+    // You may want to enable this validation at the beginning or at the end of
+    // this function, depending on what do you want to check.
+    VMA_HEAVY_ASSERT(ValidateFreeSuballocationList());
+
+    if(item->size >= VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER)
+    {
+        VmaSuballocationList::iterator* const it = VmaBinaryFindFirstNotLess(
+            m_FreeSuballocationsBySize.data(),
+            m_FreeSuballocationsBySize.data() + m_FreeSuballocationsBySize.size(),
+            item,
+            VmaSuballocationItemSizeLess());
+        for(size_t index = it - m_FreeSuballocationsBySize.data();
+            index < m_FreeSuballocationsBySize.size();
+            ++index)
+        {
+            if(m_FreeSuballocationsBySize[index] == item)
+            {
+                VmaVectorRemove(m_FreeSuballocationsBySize, index);
+                return;
+            }
+            VMA_ASSERT((m_FreeSuballocationsBySize[index]->size == item->size) && "Not found.");
+        }
+        VMA_ASSERT(0 && "Not found.");
+    }
+
+    //VMA_HEAVY_ASSERT(ValidateFreeSuballocationList());
+}
+
+bool VmaBlockMetadata_Generic::IsBufferImageGranularityConflictPossible(
+    VkDeviceSize bufferImageGranularity,
+    VmaSuballocationType& inOutPrevSuballocType) const
+{
+    if(bufferImageGranularity == 1 || IsEmpty())
+    {
+        return false;
+    }
+
+    VkDeviceSize minAlignment = VK_WHOLE_SIZE;
+    bool typeConflictFound = false;
+    for(VmaSuballocationList::const_iterator it = m_Suballocations.cbegin();
+        it != m_Suballocations.cend();
+        ++it)
+    {
+        const VmaSuballocationType suballocType = it->type;
+        if(suballocType != VMA_SUBALLOCATION_TYPE_FREE)
+        {
+            minAlignment = VMA_MIN(minAlignment, it->hAllocation->GetAlignment());
+            if(VmaIsBufferImageGranularityConflict(inOutPrevSuballocType, suballocType))
+            {
+                typeConflictFound = true;
+            }
+            inOutPrevSuballocType = suballocType;
+        }
+    }
+
+    return typeConflictFound || minAlignment >= bufferImageGranularity;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// class VmaBlockMetadata_Linear
+
+VmaBlockMetadata_Linear::VmaBlockMetadata_Linear(VmaAllocator hAllocator) :
+    VmaBlockMetadata(hAllocator),
+    m_SumFreeSize(0),
+    m_Suballocations0(VmaStlAllocator<VmaSuballocation>(hAllocator->GetAllocationCallbacks())),
+    m_Suballocations1(VmaStlAllocator<VmaSuballocation>(hAllocator->GetAllocationCallbacks())),
+    m_1stVectorIndex(0),
+    m_2ndVectorMode(SECOND_VECTOR_EMPTY),
+    m_1stNullItemsBeginCount(0),
+    m_1stNullItemsMiddleCount(0),
+    m_2ndNullItemsCount(0)
+{
+}
+
+VmaBlockMetadata_Linear::~VmaBlockMetadata_Linear()
+{
+}
+
+void VmaBlockMetadata_Linear::Init(VkDeviceSize size)
+{
+    VmaBlockMetadata::Init(size);
+    m_SumFreeSize = size;
+}
+
+bool VmaBlockMetadata_Linear::Validate() const
+{
+    const SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+    const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+
+    VMA_VALIDATE(suballocations2nd.empty() == (m_2ndVectorMode == SECOND_VECTOR_EMPTY));
+    VMA_VALIDATE(!suballocations1st.empty() ||
+        suballocations2nd.empty() ||
+        m_2ndVectorMode != SECOND_VECTOR_RING_BUFFER);
+
+    if(!suballocations1st.empty())
+    {
+        // Null item at the beginning should be accounted into m_1stNullItemsBeginCount.
+        VMA_VALIDATE(suballocations1st[m_1stNullItemsBeginCount].hAllocation != VK_NULL_HANDLE);
+        // Null item at the end should be just pop_back().
+        VMA_VALIDATE(suballocations1st.back().hAllocation != VK_NULL_HANDLE);
+    }
+    if(!suballocations2nd.empty())
+    {
+        // Null item at the end should be just pop_back().
+        VMA_VALIDATE(suballocations2nd.back().hAllocation != VK_NULL_HANDLE);
+    }
+
+    VMA_VALIDATE(m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount <= suballocations1st.size());
+    VMA_VALIDATE(m_2ndNullItemsCount <= suballocations2nd.size());
+
+    VkDeviceSize sumUsedSize = 0;
+    const size_t suballoc1stCount = suballocations1st.size();
+    VkDeviceSize offset = VMA_DEBUG_MARGIN;
+
+    if(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
+    {
+        const size_t suballoc2ndCount = suballocations2nd.size();
+        size_t nullItem2ndCount = 0;
+        for(size_t i = 0; i < suballoc2ndCount; ++i)
+        {
+            const VmaSuballocation& suballoc = suballocations2nd[i];
+            const bool currFree = (suballoc.type == VMA_SUBALLOCATION_TYPE_FREE);
+
+            VMA_VALIDATE(currFree == (suballoc.hAllocation == VK_NULL_HANDLE));
+            VMA_VALIDATE(suballoc.offset >= offset);
+
+            if(!currFree)
+            {
+                VMA_VALIDATE(suballoc.hAllocation->GetOffset() == suballoc.offset);
+                VMA_VALIDATE(suballoc.hAllocation->GetSize() == suballoc.size);
+                sumUsedSize += suballoc.size;
+            }
+            else
+            {
+                ++nullItem2ndCount;
+            }
+
+            offset = suballoc.offset + suballoc.size + VMA_DEBUG_MARGIN;
+        }
+
+        VMA_VALIDATE(nullItem2ndCount == m_2ndNullItemsCount);
+    }
+
+    for(size_t i = 0; i < m_1stNullItemsBeginCount; ++i)
+    {
+        const VmaSuballocation& suballoc = suballocations1st[i];
+        VMA_VALIDATE(suballoc.type == VMA_SUBALLOCATION_TYPE_FREE &&
+            suballoc.hAllocation == VK_NULL_HANDLE);
+    }
+
+    size_t nullItem1stCount = m_1stNullItemsBeginCount;
+
+    for(size_t i = m_1stNullItemsBeginCount; i < suballoc1stCount; ++i)
+    {
+        const VmaSuballocation& suballoc = suballocations1st[i];
+        const bool currFree = (suballoc.type == VMA_SUBALLOCATION_TYPE_FREE);
+
+        VMA_VALIDATE(currFree == (suballoc.hAllocation == VK_NULL_HANDLE));
+        VMA_VALIDATE(suballoc.offset >= offset);
+        VMA_VALIDATE(i >= m_1stNullItemsBeginCount || currFree);
+
+        if(!currFree)
+        {
+            VMA_VALIDATE(suballoc.hAllocation->GetOffset() == suballoc.offset);
+            VMA_VALIDATE(suballoc.hAllocation->GetSize() == suballoc.size);
+            sumUsedSize += suballoc.size;
+        }
+        else
+        {
+            ++nullItem1stCount;
+        }
+
+        offset = suballoc.offset + suballoc.size + VMA_DEBUG_MARGIN;
+    }
+    VMA_VALIDATE(nullItem1stCount == m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount);
+
+    if(m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)
+    {
+        const size_t suballoc2ndCount = suballocations2nd.size();
+        size_t nullItem2ndCount = 0;
+        for(size_t i = suballoc2ndCount; i--; )
+        {
+            const VmaSuballocation& suballoc = suballocations2nd[i];
+            const bool currFree = (suballoc.type == VMA_SUBALLOCATION_TYPE_FREE);
+
+            VMA_VALIDATE(currFree == (suballoc.hAllocation == VK_NULL_HANDLE));
+            VMA_VALIDATE(suballoc.offset >= offset);
+
+            if(!currFree)
+            {
+                VMA_VALIDATE(suballoc.hAllocation->GetOffset() == suballoc.offset);
+                VMA_VALIDATE(suballoc.hAllocation->GetSize() == suballoc.size);
+                sumUsedSize += suballoc.size;
+            }
+            else
+            {
+                ++nullItem2ndCount;
+            }
+
+            offset = suballoc.offset + suballoc.size + VMA_DEBUG_MARGIN;
+        }
+
+        VMA_VALIDATE(nullItem2ndCount == m_2ndNullItemsCount);
+    }
+
+    VMA_VALIDATE(offset <= GetSize());
+    VMA_VALIDATE(m_SumFreeSize == GetSize() - sumUsedSize);
+
+    return true;
+}
+
+size_t VmaBlockMetadata_Linear::GetAllocationCount() const
+{
+    return AccessSuballocations1st().size() - (m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount) +
+        AccessSuballocations2nd().size() - m_2ndNullItemsCount;
+}
+
+VkDeviceSize VmaBlockMetadata_Linear::GetUnusedRangeSizeMax() const
+{
+    const VkDeviceSize size = GetSize();
+
+    /*
+    We don't consider gaps inside allocation vectors with freed allocations because
+    they are not suitable for reuse in linear allocator. We consider only space that
+    is available for new allocations.
+    */
+    if(IsEmpty())
+    {
+        return size;
+    }
+    
+    const SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+
+    switch(m_2ndVectorMode)
+    {
+    case SECOND_VECTOR_EMPTY:
+        /*
+        Available space is after end of 1st, as well as before beginning of 1st (which
+        whould make it a ring buffer).
+        */
+        {
+            const size_t suballocations1stCount = suballocations1st.size();
+            VMA_ASSERT(suballocations1stCount > m_1stNullItemsBeginCount);
+            const VmaSuballocation& firstSuballoc = suballocations1st[m_1stNullItemsBeginCount];
+            const VmaSuballocation& lastSuballoc  = suballocations1st[suballocations1stCount - 1];
+            return VMA_MAX(
+                firstSuballoc.offset,
+                size - (lastSuballoc.offset + lastSuballoc.size));
+        }
+        break;
+
+    case SECOND_VECTOR_RING_BUFFER:
+        /*
+        Available space is only between end of 2nd and beginning of 1st.
+        */
+        {
+            const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+            const VmaSuballocation& lastSuballoc2nd = suballocations2nd.back();
+            const VmaSuballocation& firstSuballoc1st = suballocations1st[m_1stNullItemsBeginCount];
+            return firstSuballoc1st.offset - (lastSuballoc2nd.offset + lastSuballoc2nd.size);
+        }
+        break;
+
+    case SECOND_VECTOR_DOUBLE_STACK:
+        /*
+        Available space is only between end of 1st and top of 2nd.
+        */
+        {
+            const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+            const VmaSuballocation& topSuballoc2nd = suballocations2nd.back();
+            const VmaSuballocation& lastSuballoc1st = suballocations1st.back();
+            return topSuballoc2nd.offset - (lastSuballoc1st.offset + lastSuballoc1st.size);
+        }
+        break;
+
+    default:
+        VMA_ASSERT(0);
+        return 0;
+    }
+}
+
+void VmaBlockMetadata_Linear::CalcAllocationStatInfo(VmaStatInfo& outInfo) const
+{
+    const VkDeviceSize size = GetSize();
+    const SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+    const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+    const size_t suballoc1stCount = suballocations1st.size();
+    const size_t suballoc2ndCount = suballocations2nd.size();
+
+    outInfo.blockCount = 1;
+    outInfo.allocationCount = (uint32_t)GetAllocationCount();
+    outInfo.unusedRangeCount = 0;
+    outInfo.usedBytes = 0;
+    outInfo.allocationSizeMin = UINT64_MAX;
+    outInfo.allocationSizeMax = 0;
+    outInfo.unusedRangeSizeMin = UINT64_MAX;
+    outInfo.unusedRangeSizeMax = 0;
+
+    VkDeviceSize lastOffset = 0;
+
+    if(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
+    {
+        const VkDeviceSize freeSpace2ndTo1stEnd = suballocations1st[m_1stNullItemsBeginCount].offset;
+        size_t nextAlloc2ndIndex = 0;
+        while(lastOffset < freeSpace2ndTo1stEnd)
+        {
+            // Find next non-null allocation or move nextAllocIndex to the end.
+            while(nextAlloc2ndIndex < suballoc2ndCount &&
+                suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE)
+            {
+                ++nextAlloc2ndIndex;
+            }
+
+            // Found non-null allocation.
+            if(nextAlloc2ndIndex < suballoc2ndCount)
+            {
+                const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex];
+            
+                // 1. Process free space before this allocation.
+                if(lastOffset < suballoc.offset)
+                {
+                    // There is free space from lastOffset to suballoc.offset.
+                    const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;
+                    ++outInfo.unusedRangeCount;
+                    outInfo.unusedBytes += unusedRangeSize;
+                    outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, unusedRangeSize);
+                    outInfo.unusedRangeSizeMax = VMA_MIN(outInfo.unusedRangeSizeMax, unusedRangeSize);
+                }
+            
+                // 2. Process this allocation.
+                // There is allocation with suballoc.offset, suballoc.size.
+                outInfo.usedBytes += suballoc.size;
+                outInfo.allocationSizeMin = VMA_MIN(outInfo.allocationSizeMin, suballoc.size);
+                outInfo.allocationSizeMax = VMA_MIN(outInfo.allocationSizeMax, suballoc.size);
+            
+                // 3. Prepare for next iteration.
+                lastOffset = suballoc.offset + suballoc.size;
+                ++nextAlloc2ndIndex;
+            }
+            // We are at the end.
+            else
+            {
+                // There is free space from lastOffset to freeSpace2ndTo1stEnd.
+                if(lastOffset < freeSpace2ndTo1stEnd)
+                {
+                    const VkDeviceSize unusedRangeSize = freeSpace2ndTo1stEnd - lastOffset;
+                    ++outInfo.unusedRangeCount;
+                    outInfo.unusedBytes += unusedRangeSize;
+                    outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, unusedRangeSize);
+                    outInfo.unusedRangeSizeMax = VMA_MIN(outInfo.unusedRangeSizeMax, unusedRangeSize);
+               }
+
+                // End of loop.
+                lastOffset = freeSpace2ndTo1stEnd;
+            }
+        }
+    }
+
+    size_t nextAlloc1stIndex = m_1stNullItemsBeginCount;
+    const VkDeviceSize freeSpace1stTo2ndEnd =
+        m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK ? suballocations2nd.back().offset : size;
+    while(lastOffset < freeSpace1stTo2ndEnd)
+    {
+        // Find next non-null allocation or move nextAllocIndex to the end.
+        while(nextAlloc1stIndex < suballoc1stCount &&
+            suballocations1st[nextAlloc1stIndex].hAllocation == VK_NULL_HANDLE)
+        {
+            ++nextAlloc1stIndex;
+        }
+
+        // Found non-null allocation.
+        if(nextAlloc1stIndex < suballoc1stCount)
+        {
+            const VmaSuballocation& suballoc = suballocations1st[nextAlloc1stIndex];
+            
+            // 1. Process free space before this allocation.
+            if(lastOffset < suballoc.offset)
+            {
+                // There is free space from lastOffset to suballoc.offset.
+                const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;
+                ++outInfo.unusedRangeCount;
+                outInfo.unusedBytes += unusedRangeSize;
+                outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, unusedRangeSize);
+                outInfo.unusedRangeSizeMax = VMA_MIN(outInfo.unusedRangeSizeMax, unusedRangeSize);
+            }
+            
+            // 2. Process this allocation.
+            // There is allocation with suballoc.offset, suballoc.size.
+            outInfo.usedBytes += suballoc.size;
+            outInfo.allocationSizeMin = VMA_MIN(outInfo.allocationSizeMin, suballoc.size);
+            outInfo.allocationSizeMax = VMA_MIN(outInfo.allocationSizeMax, suballoc.size);
+            
+            // 3. Prepare for next iteration.
+            lastOffset = suballoc.offset + suballoc.size;
+            ++nextAlloc1stIndex;
+        }
+        // We are at the end.
+        else
+        {
+            // There is free space from lastOffset to freeSpace1stTo2ndEnd.
+            if(lastOffset < freeSpace1stTo2ndEnd)
+            {
+                const VkDeviceSize unusedRangeSize = freeSpace1stTo2ndEnd - lastOffset;
+                ++outInfo.unusedRangeCount;
+                outInfo.unusedBytes += unusedRangeSize;
+                outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, unusedRangeSize);
+                outInfo.unusedRangeSizeMax = VMA_MIN(outInfo.unusedRangeSizeMax, unusedRangeSize);
+           }
+
+            // End of loop.
+            lastOffset = freeSpace1stTo2ndEnd;
+        }
+    }
+
+    if(m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)
+    {
+        size_t nextAlloc2ndIndex = suballocations2nd.size() - 1;
+        while(lastOffset < size)
+        {
+            // Find next non-null allocation or move nextAllocIndex to the end.
+            while(nextAlloc2ndIndex != SIZE_MAX &&
+                suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE)
+            {
+                --nextAlloc2ndIndex;
+            }
+
+            // Found non-null allocation.
+            if(nextAlloc2ndIndex != SIZE_MAX)
+            {
+                const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex];
+            
+                // 1. Process free space before this allocation.
+                if(lastOffset < suballoc.offset)
+                {
+                    // There is free space from lastOffset to suballoc.offset.
+                    const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;
+                    ++outInfo.unusedRangeCount;
+                    outInfo.unusedBytes += unusedRangeSize;
+                    outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, unusedRangeSize);
+                    outInfo.unusedRangeSizeMax = VMA_MIN(outInfo.unusedRangeSizeMax, unusedRangeSize);
+                }
+            
+                // 2. Process this allocation.
+                // There is allocation with suballoc.offset, suballoc.size.
+                outInfo.usedBytes += suballoc.size;
+                outInfo.allocationSizeMin = VMA_MIN(outInfo.allocationSizeMin, suballoc.size);
+                outInfo.allocationSizeMax = VMA_MIN(outInfo.allocationSizeMax, suballoc.size);
+            
+                // 3. Prepare for next iteration.
+                lastOffset = suballoc.offset + suballoc.size;
+                --nextAlloc2ndIndex;
+            }
+            // We are at the end.
+            else
+            {
+                // There is free space from lastOffset to size.
+                if(lastOffset < size)
+                {
+                    const VkDeviceSize unusedRangeSize = size - lastOffset;
+                    ++outInfo.unusedRangeCount;
+                    outInfo.unusedBytes += unusedRangeSize;
+                    outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, unusedRangeSize);
+                    outInfo.unusedRangeSizeMax = VMA_MIN(outInfo.unusedRangeSizeMax, unusedRangeSize);
+               }
+
+                // End of loop.
+                lastOffset = size;
+            }
+        }
+    }
+
+    outInfo.unusedBytes = size - outInfo.usedBytes;
+}
+
+void VmaBlockMetadata_Linear::AddPoolStats(VmaPoolStats& inoutStats) const
+{
+    const SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+    const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+    const VkDeviceSize size = GetSize();
+    const size_t suballoc1stCount = suballocations1st.size();
+    const size_t suballoc2ndCount = suballocations2nd.size();
+
+    inoutStats.size += size;
+
+    VkDeviceSize lastOffset = 0;
+
+    if(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
+    {
+        const VkDeviceSize freeSpace2ndTo1stEnd = suballocations1st[m_1stNullItemsBeginCount].offset;
+        size_t nextAlloc2ndIndex = m_1stNullItemsBeginCount;
+        while(lastOffset < freeSpace2ndTo1stEnd)
+        {
+            // Find next non-null allocation or move nextAlloc2ndIndex to the end.
+            while(nextAlloc2ndIndex < suballoc2ndCount &&
+                suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE)
+            {
+                ++nextAlloc2ndIndex;
+            }
+
+            // Found non-null allocation.
+            if(nextAlloc2ndIndex < suballoc2ndCount)
+            {
+                const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex];
+            
+                // 1. Process free space before this allocation.
+                if(lastOffset < suballoc.offset)
+                {
+                    // There is free space from lastOffset to suballoc.offset.
+                    const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;
+                    inoutStats.unusedSize += unusedRangeSize;
+                    ++inoutStats.unusedRangeCount;
+                    inoutStats.unusedRangeSizeMax = VMA_MAX(inoutStats.unusedRangeSizeMax, unusedRangeSize);
+                }
+            
+                // 2. Process this allocation.
+                // There is allocation with suballoc.offset, suballoc.size.
+                ++inoutStats.allocationCount;
+            
+                // 3. Prepare for next iteration.
+                lastOffset = suballoc.offset + suballoc.size;
+                ++nextAlloc2ndIndex;
+            }
+            // We are at the end.
+            else
+            {
+                if(lastOffset < freeSpace2ndTo1stEnd)
+                {
+                    // There is free space from lastOffset to freeSpace2ndTo1stEnd.
+                    const VkDeviceSize unusedRangeSize = freeSpace2ndTo1stEnd - lastOffset;
+                    inoutStats.unusedSize += unusedRangeSize;
+                    ++inoutStats.unusedRangeCount;
+                    inoutStats.unusedRangeSizeMax = VMA_MAX(inoutStats.unusedRangeSizeMax, unusedRangeSize);
+                }
+
+                // End of loop.
+                lastOffset = freeSpace2ndTo1stEnd;
+            }
+        }
+    }
+
+    size_t nextAlloc1stIndex = m_1stNullItemsBeginCount;
+    const VkDeviceSize freeSpace1stTo2ndEnd =
+        m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK ? suballocations2nd.back().offset : size;
+    while(lastOffset < freeSpace1stTo2ndEnd)
+    {
+        // Find next non-null allocation or move nextAllocIndex to the end.
+        while(nextAlloc1stIndex < suballoc1stCount &&
+            suballocations1st[nextAlloc1stIndex].hAllocation == VK_NULL_HANDLE)
+        {
+            ++nextAlloc1stIndex;
+        }
+
+        // Found non-null allocation.
+        if(nextAlloc1stIndex < suballoc1stCount)
+        {
+            const VmaSuballocation& suballoc = suballocations1st[nextAlloc1stIndex];
+            
+            // 1. Process free space before this allocation.
+            if(lastOffset < suballoc.offset)
+            {
+                // There is free space from lastOffset to suballoc.offset.
+                const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;
+                inoutStats.unusedSize += unusedRangeSize;
+                ++inoutStats.unusedRangeCount;
+                inoutStats.unusedRangeSizeMax = VMA_MAX(inoutStats.unusedRangeSizeMax, unusedRangeSize);
+            }
+            
+            // 2. Process this allocation.
+            // There is allocation with suballoc.offset, suballoc.size.
+            ++inoutStats.allocationCount;
+            
+            // 3. Prepare for next iteration.
+            lastOffset = suballoc.offset + suballoc.size;
+            ++nextAlloc1stIndex;
+        }
+        // We are at the end.
+        else
+        {
+            if(lastOffset < freeSpace1stTo2ndEnd)
+            {
+                // There is free space from lastOffset to freeSpace1stTo2ndEnd.
+                const VkDeviceSize unusedRangeSize = freeSpace1stTo2ndEnd - lastOffset;
+                inoutStats.unusedSize += unusedRangeSize;
+                ++inoutStats.unusedRangeCount;
+                inoutStats.unusedRangeSizeMax = VMA_MAX(inoutStats.unusedRangeSizeMax, unusedRangeSize);
+            }
+
+            // End of loop.
+            lastOffset = freeSpace1stTo2ndEnd;
+        }
+    }
+
+    if(m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)
+    {
+        size_t nextAlloc2ndIndex = suballocations2nd.size() - 1;
+        while(lastOffset < size)
+        {
+            // Find next non-null allocation or move nextAlloc2ndIndex to the end.
+            while(nextAlloc2ndIndex != SIZE_MAX &&
+                suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE)
+            {
+                --nextAlloc2ndIndex;
+            }
+
+            // Found non-null allocation.
+            if(nextAlloc2ndIndex != SIZE_MAX)
+            {
+                const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex];
+            
+                // 1. Process free space before this allocation.
+                if(lastOffset < suballoc.offset)
+                {
+                    // There is free space from lastOffset to suballoc.offset.
+                    const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;
+                    inoutStats.unusedSize += unusedRangeSize;
+                    ++inoutStats.unusedRangeCount;
+                    inoutStats.unusedRangeSizeMax = VMA_MAX(inoutStats.unusedRangeSizeMax, unusedRangeSize);
+                }
+            
+                // 2. Process this allocation.
+                // There is allocation with suballoc.offset, suballoc.size.
+                ++inoutStats.allocationCount;
+            
+                // 3. Prepare for next iteration.
+                lastOffset = suballoc.offset + suballoc.size;
+                --nextAlloc2ndIndex;
+            }
+            // We are at the end.
+            else
+            {
+                if(lastOffset < size)
+                {
+                    // There is free space from lastOffset to size.
+                    const VkDeviceSize unusedRangeSize = size - lastOffset;
+                    inoutStats.unusedSize += unusedRangeSize;
+                    ++inoutStats.unusedRangeCount;
+                    inoutStats.unusedRangeSizeMax = VMA_MAX(inoutStats.unusedRangeSizeMax, unusedRangeSize);
+                }
+
+                // End of loop.
+                lastOffset = size;
+            }
+        }
+    }
+}
+
+#if VMA_STATS_STRING_ENABLED
+void VmaBlockMetadata_Linear::PrintDetailedMap(class VmaJsonWriter& json) const
+{
+    const VkDeviceSize size = GetSize();
+    const SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+    const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+    const size_t suballoc1stCount = suballocations1st.size();
+    const size_t suballoc2ndCount = suballocations2nd.size();
+
+    // FIRST PASS
+
+    size_t unusedRangeCount = 0;
+    VkDeviceSize usedBytes = 0;
+
+    VkDeviceSize lastOffset = 0;
+
+    size_t alloc2ndCount = 0;
+    if(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
+    {
+        const VkDeviceSize freeSpace2ndTo1stEnd = suballocations1st[m_1stNullItemsBeginCount].offset;
+        size_t nextAlloc2ndIndex = 0;
+        while(lastOffset < freeSpace2ndTo1stEnd)
+        {
+            // Find next non-null allocation or move nextAlloc2ndIndex to the end.
+            while(nextAlloc2ndIndex < suballoc2ndCount &&
+                suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE)
+            {
+                ++nextAlloc2ndIndex;
+            }
+
+            // Found non-null allocation.
+            if(nextAlloc2ndIndex < suballoc2ndCount)
+            {
+                const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex];
+            
+                // 1. Process free space before this allocation.
+                if(lastOffset < suballoc.offset)
+                {
+                    // There is free space from lastOffset to suballoc.offset.
+                    ++unusedRangeCount;
+                }
+            
+                // 2. Process this allocation.
+                // There is allocation with suballoc.offset, suballoc.size.
+                ++alloc2ndCount;
+                usedBytes += suballoc.size;
+            
+                // 3. Prepare for next iteration.
+                lastOffset = suballoc.offset + suballoc.size;
+                ++nextAlloc2ndIndex;
+            }
+            // We are at the end.
+            else
+            {
+                if(lastOffset < freeSpace2ndTo1stEnd)
+                {
+                    // There is free space from lastOffset to freeSpace2ndTo1stEnd.
+                    ++unusedRangeCount;
+                }
+
+                // End of loop.
+                lastOffset = freeSpace2ndTo1stEnd;
+            }
+        }
+    }
+
+    size_t nextAlloc1stIndex = m_1stNullItemsBeginCount;
+    size_t alloc1stCount = 0;
+    const VkDeviceSize freeSpace1stTo2ndEnd =
+        m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK ? suballocations2nd.back().offset : size;
+    while(lastOffset < freeSpace1stTo2ndEnd)
+    {
+        // Find next non-null allocation or move nextAllocIndex to the end.
+        while(nextAlloc1stIndex < suballoc1stCount &&
+            suballocations1st[nextAlloc1stIndex].hAllocation == VK_NULL_HANDLE)
+        {
+            ++nextAlloc1stIndex;
+        }
+
+        // Found non-null allocation.
+        if(nextAlloc1stIndex < suballoc1stCount)
+        {
+            const VmaSuballocation& suballoc = suballocations1st[nextAlloc1stIndex];
+            
+            // 1. Process free space before this allocation.
+            if(lastOffset < suballoc.offset)
+            {
+                // There is free space from lastOffset to suballoc.offset.
+                ++unusedRangeCount;
+            }
+            
+            // 2. Process this allocation.
+            // There is allocation with suballoc.offset, suballoc.size.
+            ++alloc1stCount;
+            usedBytes += suballoc.size;
+            
+            // 3. Prepare for next iteration.
+            lastOffset = suballoc.offset + suballoc.size;
+            ++nextAlloc1stIndex;
+        }
+        // We are at the end.
+        else
+        {
+            if(lastOffset < size)
+            {
+                // There is free space from lastOffset to freeSpace1stTo2ndEnd.
+                ++unusedRangeCount;
+            }
+
+            // End of loop.
+            lastOffset = freeSpace1stTo2ndEnd;
+        }
+    }
+
+    if(m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)
+    {
+        size_t nextAlloc2ndIndex = suballocations2nd.size() - 1;
+        while(lastOffset < size)
+        {
+            // Find next non-null allocation or move nextAlloc2ndIndex to the end.
+            while(nextAlloc2ndIndex != SIZE_MAX &&
+                suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE)
+            {
+                --nextAlloc2ndIndex;
+            }
+
+            // Found non-null allocation.
+            if(nextAlloc2ndIndex != SIZE_MAX)
+            {
+                const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex];
+            
+                // 1. Process free space before this allocation.
+                if(lastOffset < suballoc.offset)
+                {
+                    // There is free space from lastOffset to suballoc.offset.
+                    ++unusedRangeCount;
+                }
+            
+                // 2. Process this allocation.
+                // There is allocation with suballoc.offset, suballoc.size.
+                ++alloc2ndCount;
+                usedBytes += suballoc.size;
+            
+                // 3. Prepare for next iteration.
+                lastOffset = suballoc.offset + suballoc.size;
+                --nextAlloc2ndIndex;
+            }
+            // We are at the end.
+            else
+            {
+                if(lastOffset < size)
+                {
+                    // There is free space from lastOffset to size.
+                    ++unusedRangeCount;
+                }
+
+                // End of loop.
+                lastOffset = size;
+            }
+        }
+    }
+
+    const VkDeviceSize unusedBytes = size - usedBytes;
+    PrintDetailedMap_Begin(json, unusedBytes, alloc1stCount + alloc2ndCount, unusedRangeCount);
+
+    // SECOND PASS
+    lastOffset = 0;
+
+    if(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
+    {
+        const VkDeviceSize freeSpace2ndTo1stEnd = suballocations1st[m_1stNullItemsBeginCount].offset;
+        size_t nextAlloc2ndIndex = 0;
+        while(lastOffset < freeSpace2ndTo1stEnd)
+        {
+            // Find next non-null allocation or move nextAlloc2ndIndex to the end.
+            while(nextAlloc2ndIndex < suballoc2ndCount &&
+                suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE)
+            {
+                ++nextAlloc2ndIndex;
+            }
+
+            // Found non-null allocation.
+            if(nextAlloc2ndIndex < suballoc2ndCount)
+            {
+                const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex];
+            
+                // 1. Process free space before this allocation.
+                if(lastOffset < suballoc.offset)
+                {
+                    // There is free space from lastOffset to suballoc.offset.
+                    const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;
+                    PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize);
+                }
+            
+                // 2. Process this allocation.
+                // There is allocation with suballoc.offset, suballoc.size.
+                PrintDetailedMap_Allocation(json, suballoc.offset, suballoc.hAllocation);
+            
+                // 3. Prepare for next iteration.
+                lastOffset = suballoc.offset + suballoc.size;
+                ++nextAlloc2ndIndex;
+            }
+            // We are at the end.
+            else
+            {
+                if(lastOffset < freeSpace2ndTo1stEnd)
+                {
+                    // There is free space from lastOffset to freeSpace2ndTo1stEnd.
+                    const VkDeviceSize unusedRangeSize = freeSpace2ndTo1stEnd - lastOffset;
+                    PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize);
+                }
+
+                // End of loop.
+                lastOffset = freeSpace2ndTo1stEnd;
+            }
+        }
+    }
+
+    nextAlloc1stIndex = m_1stNullItemsBeginCount;
+    while(lastOffset < freeSpace1stTo2ndEnd)
+    {
+        // Find next non-null allocation or move nextAllocIndex to the end.
+        while(nextAlloc1stIndex < suballoc1stCount &&
+            suballocations1st[nextAlloc1stIndex].hAllocation == VK_NULL_HANDLE)
+        {
+            ++nextAlloc1stIndex;
+        }
+
+        // Found non-null allocation.
+        if(nextAlloc1stIndex < suballoc1stCount)
+        {
+            const VmaSuballocation& suballoc = suballocations1st[nextAlloc1stIndex];
+            
+            // 1. Process free space before this allocation.
+            if(lastOffset < suballoc.offset)
+            {
+                // There is free space from lastOffset to suballoc.offset.
+                const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;
+                PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize);
+            }
+            
+            // 2. Process this allocation.
+            // There is allocation with suballoc.offset, suballoc.size.
+            PrintDetailedMap_Allocation(json, suballoc.offset, suballoc.hAllocation);
+            
+            // 3. Prepare for next iteration.
+            lastOffset = suballoc.offset + suballoc.size;
+            ++nextAlloc1stIndex;
+        }
+        // We are at the end.
+        else
+        {
+            if(lastOffset < freeSpace1stTo2ndEnd)
+            {
+                // There is free space from lastOffset to freeSpace1stTo2ndEnd.
+                const VkDeviceSize unusedRangeSize = freeSpace1stTo2ndEnd - lastOffset;
+                PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize);
+            }
+
+            // End of loop.
+            lastOffset = freeSpace1stTo2ndEnd;
+        }
+    }
+
+    if(m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)
+    {
+        size_t nextAlloc2ndIndex = suballocations2nd.size() - 1;
+        while(lastOffset < size)
+        {
+            // Find next non-null allocation or move nextAlloc2ndIndex to the end.
+            while(nextAlloc2ndIndex != SIZE_MAX &&
+                suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE)
+            {
+                --nextAlloc2ndIndex;
+            }
+
+            // Found non-null allocation.
+            if(nextAlloc2ndIndex != SIZE_MAX)
+            {
+                const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex];
+            
+                // 1. Process free space before this allocation.
+                if(lastOffset < suballoc.offset)
+                {
+                    // There is free space from lastOffset to suballoc.offset.
+                    const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;
+                    PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize);
+                }
+            
+                // 2. Process this allocation.
+                // There is allocation with suballoc.offset, suballoc.size.
+                PrintDetailedMap_Allocation(json, suballoc.offset, suballoc.hAllocation);
+            
+                // 3. Prepare for next iteration.
+                lastOffset = suballoc.offset + suballoc.size;
+                --nextAlloc2ndIndex;
+            }
+            // We are at the end.
+            else
+            {
+                if(lastOffset < size)
+                {
+                    // There is free space from lastOffset to size.
+                    const VkDeviceSize unusedRangeSize = size - lastOffset;
+                    PrintDetailedMap_UnusedRange(json, lastOffset, unusedRangeSize);
+                }
+
+                // End of loop.
+                lastOffset = size;
+            }
+        }
+    }
+
+    PrintDetailedMap_End(json);
+}
+#endif // #if VMA_STATS_STRING_ENABLED
+
+bool VmaBlockMetadata_Linear::CreateAllocationRequest(
+    uint32_t currentFrameIndex,
+    uint32_t frameInUseCount,
+    VkDeviceSize bufferImageGranularity,
+    VkDeviceSize allocSize,
+    VkDeviceSize allocAlignment,
+    bool upperAddress,
+    VmaSuballocationType allocType,
+    bool canMakeOtherLost,
+    uint32_t strategy,
+    VmaAllocationRequest* pAllocationRequest)
+{
+    VMA_ASSERT(allocSize > 0);
+    VMA_ASSERT(allocType != VMA_SUBALLOCATION_TYPE_FREE);
+    VMA_ASSERT(pAllocationRequest != VMA_NULL);
+    VMA_HEAVY_ASSERT(Validate());
+    return upperAddress ?
+        CreateAllocationRequest_UpperAddress(
+            currentFrameIndex, frameInUseCount, bufferImageGranularity,
+            allocSize, allocAlignment, allocType, canMakeOtherLost, strategy, pAllocationRequest) :
+        CreateAllocationRequest_LowerAddress(
+            currentFrameIndex, frameInUseCount, bufferImageGranularity,
+            allocSize, allocAlignment, allocType, canMakeOtherLost, strategy, pAllocationRequest);
+}
+
+bool VmaBlockMetadata_Linear::CreateAllocationRequest_UpperAddress(
+    uint32_t currentFrameIndex,
+    uint32_t frameInUseCount,
+    VkDeviceSize bufferImageGranularity,
+    VkDeviceSize allocSize,
+    VkDeviceSize allocAlignment,
+    VmaSuballocationType allocType,
+    bool canMakeOtherLost,
+    uint32_t strategy,
+    VmaAllocationRequest* pAllocationRequest)
+{
+    const VkDeviceSize size = GetSize();
+    SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+    SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+
+    if(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
+    {
+        VMA_ASSERT(0 && "Trying to use pool with linear algorithm as double stack, while it is already being used as ring buffer.");
+        return false;
+    }
+
+    // Try to allocate before 2nd.back(), or end of block if 2nd.empty().
+    if(allocSize > size)
+    {
+        return false;
+    }
+    VkDeviceSize resultBaseOffset = size - allocSize;
+    if(!suballocations2nd.empty())
+    {
+        const VmaSuballocation& lastSuballoc = suballocations2nd.back();
+        resultBaseOffset = lastSuballoc.offset - allocSize;
+        if(allocSize > lastSuballoc.offset)
+        {
+            return false;
+        }
+    }
+
+    // Start from offset equal to end of free space.
+    VkDeviceSize resultOffset = resultBaseOffset;
+
+    // Apply VMA_DEBUG_MARGIN at the end.
+    if(VMA_DEBUG_MARGIN > 0)
+    {
+        if(resultOffset < VMA_DEBUG_MARGIN)
+        {
+            return false;
+        }
+        resultOffset -= VMA_DEBUG_MARGIN;
+    }
+
+    // Apply alignment.
+    resultOffset = VmaAlignDown(resultOffset, allocAlignment);
+
+    // Check next suballocations from 2nd for BufferImageGranularity conflicts.
+    // Make bigger alignment if necessary.
+    if(bufferImageGranularity > 1 && !suballocations2nd.empty())
+    {
+        bool bufferImageGranularityConflict = false;
+        for(size_t nextSuballocIndex = suballocations2nd.size(); nextSuballocIndex--; )
+        {
+            const VmaSuballocation& nextSuballoc = suballocations2nd[nextSuballocIndex];
+            if(VmaBlocksOnSamePage(resultOffset, allocSize, nextSuballoc.offset, bufferImageGranularity))
+            {
+                if(VmaIsBufferImageGranularityConflict(nextSuballoc.type, allocType))
+                {
+                    bufferImageGranularityConflict = true;
+                    break;
+                }
+            }
+            else
+                // Already on previous page.
+                break;
+        }
+        if(bufferImageGranularityConflict)
+        {
+            resultOffset = VmaAlignDown(resultOffset, bufferImageGranularity);
+        }
+    }
+
+    // There is enough free space.
+    const VkDeviceSize endOf1st = !suballocations1st.empty() ?
+        suballocations1st.back().offset + suballocations1st.back().size :
+        0;
+    if(endOf1st + VMA_DEBUG_MARGIN <= resultOffset)
+    {
+        // Check previous suballocations for BufferImageGranularity conflicts.
+        // If conflict exists, allocation cannot be made here.
+        if(bufferImageGranularity > 1)
+        {
+            for(size_t prevSuballocIndex = suballocations1st.size(); prevSuballocIndex--; )
+            {
+                const VmaSuballocation& prevSuballoc = suballocations1st[prevSuballocIndex];
+                if(VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, resultOffset, bufferImageGranularity))
+                {
+                    if(VmaIsBufferImageGranularityConflict(allocType, prevSuballoc.type))
+                    {
+                        return false;
+                    }
+                }
+                else
+                {
+                    // Already on next page.
+                    break;
+                }
+            }
+        }
+
+        // All tests passed: Success.
+        pAllocationRequest->offset = resultOffset;
+        pAllocationRequest->sumFreeSize = resultBaseOffset + allocSize - endOf1st;
+        pAllocationRequest->sumItemSize = 0;
+        // pAllocationRequest->item unused.
+        pAllocationRequest->itemsToMakeLostCount = 0;
+        pAllocationRequest->type = VmaAllocationRequestType::UpperAddress;
+        return true;
+    }
+
+    return false;
+}
+
+bool VmaBlockMetadata_Linear::CreateAllocationRequest_LowerAddress(
+    uint32_t currentFrameIndex,
+    uint32_t frameInUseCount,
+    VkDeviceSize bufferImageGranularity,
+    VkDeviceSize allocSize,
+    VkDeviceSize allocAlignment,
+    VmaSuballocationType allocType,
+    bool canMakeOtherLost,
+    uint32_t strategy,
+    VmaAllocationRequest* pAllocationRequest)
+{
+    const VkDeviceSize size = GetSize();
+    SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+    SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+
+    if(m_2ndVectorMode == SECOND_VECTOR_EMPTY || m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)
+    {
+        // Try to allocate at the end of 1st vector.
+
+        VkDeviceSize resultBaseOffset = 0;
+        if(!suballocations1st.empty())
+        {
+            const VmaSuballocation& lastSuballoc = suballocations1st.back();
+            resultBaseOffset = lastSuballoc.offset + lastSuballoc.size;
+        }
+
+        // Start from offset equal to beginning of free space.
+        VkDeviceSize resultOffset = resultBaseOffset;
+
+        // Apply VMA_DEBUG_MARGIN at the beginning.
+        if(VMA_DEBUG_MARGIN > 0)
+        {
+            resultOffset += VMA_DEBUG_MARGIN;
+        }
+
+        // Apply alignment.
+        resultOffset = VmaAlignUp(resultOffset, allocAlignment);
+
+        // Check previous suballocations for BufferImageGranularity conflicts.
+        // Make bigger alignment if necessary.
+        if(bufferImageGranularity > 1 && !suballocations1st.empty())
+        {
+            bool bufferImageGranularityConflict = false;
+            for(size_t prevSuballocIndex = suballocations1st.size(); prevSuballocIndex--; )
+            {
+                const VmaSuballocation& prevSuballoc = suballocations1st[prevSuballocIndex];
+                if(VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, resultOffset, bufferImageGranularity))
+                {
+                    if(VmaIsBufferImageGranularityConflict(prevSuballoc.type, allocType))
+                    {
+                        bufferImageGranularityConflict = true;
+                        break;
+                    }
+                }
+                else
+                    // Already on previous page.
+                    break;
+            }
+            if(bufferImageGranularityConflict)
+            {
+                resultOffset = VmaAlignUp(resultOffset, bufferImageGranularity);
+            }
+        }
+
+        const VkDeviceSize freeSpaceEnd = m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK ?
+            suballocations2nd.back().offset : size;
+
+        // There is enough free space at the end after alignment.
+        if(resultOffset + allocSize + VMA_DEBUG_MARGIN <= freeSpaceEnd)
+        {
+            // Check next suballocations for BufferImageGranularity conflicts.
+            // If conflict exists, allocation cannot be made here.
+            if(bufferImageGranularity > 1 && m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)
+            {
+                for(size_t nextSuballocIndex = suballocations2nd.size(); nextSuballocIndex--; )
+                {
+                    const VmaSuballocation& nextSuballoc = suballocations2nd[nextSuballocIndex];
+                    if(VmaBlocksOnSamePage(resultOffset, allocSize, nextSuballoc.offset, bufferImageGranularity))
+                    {
+                        if(VmaIsBufferImageGranularityConflict(allocType, nextSuballoc.type))
+                        {
+                            return false;
+                        }
+                    }
+                    else
+                    {
+                        // Already on previous page.
+                        break;
+                    }
+                }
+            }
+
+            // All tests passed: Success.
+            pAllocationRequest->offset = resultOffset;
+            pAllocationRequest->sumFreeSize = freeSpaceEnd - resultBaseOffset;
+            pAllocationRequest->sumItemSize = 0;
+            // pAllocationRequest->item, customData unused.
+            pAllocationRequest->type = VmaAllocationRequestType::EndOf1st;
+            pAllocationRequest->itemsToMakeLostCount = 0;
+            return true;
+        }
+    }
+
+    // Wrap-around to end of 2nd vector. Try to allocate there, watching for the
+    // beginning of 1st vector as the end of free space.
+    if(m_2ndVectorMode == SECOND_VECTOR_EMPTY || m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
+    {
+        VMA_ASSERT(!suballocations1st.empty());
+
+        VkDeviceSize resultBaseOffset = 0;
+        if(!suballocations2nd.empty())
+        {
+            const VmaSuballocation& lastSuballoc = suballocations2nd.back();
+            resultBaseOffset = lastSuballoc.offset + lastSuballoc.size;
+        }
+
+        // Start from offset equal to beginning of free space.
+        VkDeviceSize resultOffset = resultBaseOffset;
+
+        // Apply VMA_DEBUG_MARGIN at the beginning.
+        if(VMA_DEBUG_MARGIN > 0)
+        {
+            resultOffset += VMA_DEBUG_MARGIN;
+        }
+
+        // Apply alignment.
+        resultOffset = VmaAlignUp(resultOffset, allocAlignment);
+
+        // Check previous suballocations for BufferImageGranularity conflicts.
+        // Make bigger alignment if necessary.
+        if(bufferImageGranularity > 1 && !suballocations2nd.empty())
+        {
+            bool bufferImageGranularityConflict = false;
+            for(size_t prevSuballocIndex = suballocations2nd.size(); prevSuballocIndex--; )
+            {
+                const VmaSuballocation& prevSuballoc = suballocations2nd[prevSuballocIndex];
+                if(VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, resultOffset, bufferImageGranularity))
+                {
+                    if(VmaIsBufferImageGranularityConflict(prevSuballoc.type, allocType))
+                    {
+                        bufferImageGranularityConflict = true;
+                        break;
+                    }
+                }
+                else
+                    // Already on previous page.
+                    break;
+            }
+            if(bufferImageGranularityConflict)
+            {
+                resultOffset = VmaAlignUp(resultOffset, bufferImageGranularity);
+            }
+        }
+
+        pAllocationRequest->itemsToMakeLostCount = 0;
+        pAllocationRequest->sumItemSize = 0;
+        size_t index1st = m_1stNullItemsBeginCount;
+
+        if(canMakeOtherLost)
+        {
+            while(index1st < suballocations1st.size() &&
+                resultOffset + allocSize + VMA_DEBUG_MARGIN > suballocations1st[index1st].offset)
+            {
+                // Next colliding allocation at the beginning of 1st vector found. Try to make it lost.
+                const VmaSuballocation& suballoc = suballocations1st[index1st];
+                if(suballoc.type == VMA_SUBALLOCATION_TYPE_FREE)
+                {
+                    // No problem.
+                }
+                else
+                {
+                    VMA_ASSERT(suballoc.hAllocation != VK_NULL_HANDLE);
+                    if(suballoc.hAllocation->CanBecomeLost() &&
+                        suballoc.hAllocation->GetLastUseFrameIndex() + frameInUseCount < currentFrameIndex)
+                    {
+                        ++pAllocationRequest->itemsToMakeLostCount;
+                        pAllocationRequest->sumItemSize += suballoc.size;
+                    }
+                    else
+                    {
+                        return false;
+                    }
+                }
+                ++index1st;
+            }
+
+            // Check next suballocations for BufferImageGranularity conflicts.
+            // If conflict exists, we must mark more allocations lost or fail.
+            if(bufferImageGranularity > 1)
+            {
+                while(index1st < suballocations1st.size())
+                {
+                    const VmaSuballocation& suballoc = suballocations1st[index1st];
+                    if(VmaBlocksOnSamePage(resultOffset, allocSize, suballoc.offset, bufferImageGranularity))
+                    {
+                        if(suballoc.hAllocation != VK_NULL_HANDLE)
+                        {
+                            // Not checking actual VmaIsBufferImageGranularityConflict(allocType, suballoc.type).
+                            if(suballoc.hAllocation->CanBecomeLost() &&
+                                suballoc.hAllocation->GetLastUseFrameIndex() + frameInUseCount < currentFrameIndex)
+                            {
+                                ++pAllocationRequest->itemsToMakeLostCount;
+                                pAllocationRequest->sumItemSize += suballoc.size;
+                            }
+                            else
+                            {
+                                return false;
+                            }
+                        }
+                    }
+                    else
+                    {
+                        // Already on next page.
+                        break;
+                    }
+                    ++index1st;
+                }
+            }
+
+            // Special case: There is not enough room at the end for this allocation, even after making all from the 1st lost.
+            if(index1st == suballocations1st.size() &&
+                resultOffset + allocSize + VMA_DEBUG_MARGIN > size)
+            {
+                // TODO: This is a known bug that it's not yet implemented and the allocation is failing.
+                VMA_DEBUG_LOG("Unsupported special case in custom pool with linear allocation algorithm used as ring buffer with allocations that can be lost.");
+            }
+        }
+
+        // There is enough free space at the end after alignment.
+        if((index1st == suballocations1st.size() && resultOffset + allocSize + VMA_DEBUG_MARGIN <= size) ||
+            (index1st < suballocations1st.size() && resultOffset + allocSize + VMA_DEBUG_MARGIN <= suballocations1st[index1st].offset))
+        {
+            // Check next suballocations for BufferImageGranularity conflicts.
+            // If conflict exists, allocation cannot be made here.
+            if(bufferImageGranularity > 1)
+            {
+                for(size_t nextSuballocIndex = index1st;
+                    nextSuballocIndex < suballocations1st.size();
+                    nextSuballocIndex++)
+                {
+                    const VmaSuballocation& nextSuballoc = suballocations1st[nextSuballocIndex];
+                    if(VmaBlocksOnSamePage(resultOffset, allocSize, nextSuballoc.offset, bufferImageGranularity))
+                    {
+                        if(VmaIsBufferImageGranularityConflict(allocType, nextSuballoc.type))
+                        {
+                            return false;
+                        }
+                    }
+                    else
+                    {
+                        // Already on next page.
+                        break;
+                    }
+                }
+            }
+
+            // All tests passed: Success.
+            pAllocationRequest->offset = resultOffset;
+            pAllocationRequest->sumFreeSize =
+                (index1st < suballocations1st.size() ? suballocations1st[index1st].offset : size)
+                - resultBaseOffset
+                - pAllocationRequest->sumItemSize;
+            pAllocationRequest->type = VmaAllocationRequestType::EndOf2nd;
+            // pAllocationRequest->item, customData unused.
+            return true;
+        }
+    }
+
+    return false;
+}
+
+bool VmaBlockMetadata_Linear::MakeRequestedAllocationsLost(
+    uint32_t currentFrameIndex,
+    uint32_t frameInUseCount,
+    VmaAllocationRequest* pAllocationRequest)
+{
+    if(pAllocationRequest->itemsToMakeLostCount == 0)
+    {
+        return true;
+    }
+
+    VMA_ASSERT(m_2ndVectorMode == SECOND_VECTOR_EMPTY || m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER);
+    
+    // We always start from 1st.
+    SuballocationVectorType* suballocations = &AccessSuballocations1st();
+    size_t index = m_1stNullItemsBeginCount;
+    size_t madeLostCount = 0;
+    while(madeLostCount < pAllocationRequest->itemsToMakeLostCount)
+    {
+        if(index == suballocations->size())
+        {
+            index = 0;
+            // If we get to the end of 1st, we wrap around to beginning of 2nd of 1st.
+            if(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
+            {
+                suballocations = &AccessSuballocations2nd();
+            }
+            // else: m_2ndVectorMode == SECOND_VECTOR_EMPTY:
+            // suballocations continues pointing at AccessSuballocations1st().
+            VMA_ASSERT(!suballocations->empty());
+        }
+        VmaSuballocation& suballoc = (*suballocations)[index];
+        if(suballoc.type != VMA_SUBALLOCATION_TYPE_FREE)
+        {
+            VMA_ASSERT(suballoc.hAllocation != VK_NULL_HANDLE);
+            VMA_ASSERT(suballoc.hAllocation->CanBecomeLost());
+            if(suballoc.hAllocation->MakeLost(currentFrameIndex, frameInUseCount))
+            {
+                suballoc.type = VMA_SUBALLOCATION_TYPE_FREE;
+                suballoc.hAllocation = VK_NULL_HANDLE;
+                m_SumFreeSize += suballoc.size;
+                if(suballocations == &AccessSuballocations1st())
+                {
+                    ++m_1stNullItemsMiddleCount;
+                }
+                else
+                {
+                    ++m_2ndNullItemsCount;
+                }
+                ++madeLostCount;
+            }
+            else
+            {
+                return false;
+            }
+        }
+        ++index;
+    }
+
+    CleanupAfterFree();
+    //VMA_HEAVY_ASSERT(Validate()); // Already called by ClanupAfterFree().
+    
+    return true;
+}
+
+uint32_t VmaBlockMetadata_Linear::MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount)
+{
+    uint32_t lostAllocationCount = 0;
+    
+    SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+    for(size_t i = m_1stNullItemsBeginCount, count = suballocations1st.size(); i < count; ++i)
+    {
+        VmaSuballocation& suballoc = suballocations1st[i];
+        if(suballoc.type != VMA_SUBALLOCATION_TYPE_FREE &&
+            suballoc.hAllocation->CanBecomeLost() &&
+            suballoc.hAllocation->MakeLost(currentFrameIndex, frameInUseCount))
+        {
+            suballoc.type = VMA_SUBALLOCATION_TYPE_FREE;
+            suballoc.hAllocation = VK_NULL_HANDLE;
+            ++m_1stNullItemsMiddleCount;
+            m_SumFreeSize += suballoc.size;
+            ++lostAllocationCount;
+        }
+    }
+
+    SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+    for(size_t i = 0, count = suballocations2nd.size(); i < count; ++i)
+    {
+        VmaSuballocation& suballoc = suballocations2nd[i];
+        if(suballoc.type != VMA_SUBALLOCATION_TYPE_FREE &&
+            suballoc.hAllocation->CanBecomeLost() &&
+            suballoc.hAllocation->MakeLost(currentFrameIndex, frameInUseCount))
+        {
+            suballoc.type = VMA_SUBALLOCATION_TYPE_FREE;
+            suballoc.hAllocation = VK_NULL_HANDLE;
+            ++m_2ndNullItemsCount;
+            m_SumFreeSize += suballoc.size;
+            ++lostAllocationCount;
+        }
+    }
+
+    if(lostAllocationCount)
+    {
+        CleanupAfterFree();
+    }
+
+    return lostAllocationCount;
+}
+
+VkResult VmaBlockMetadata_Linear::CheckCorruption(const void* pBlockData)
+{
+    SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+    for(size_t i = m_1stNullItemsBeginCount, count = suballocations1st.size(); i < count; ++i)
+    {
+        const VmaSuballocation& suballoc = suballocations1st[i];
+        if(suballoc.type != VMA_SUBALLOCATION_TYPE_FREE)
+        {
+            if(!VmaValidateMagicValue(pBlockData, suballoc.offset - VMA_DEBUG_MARGIN))
+            {
+                VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED BEFORE VALIDATED ALLOCATION!");
+                return VK_ERROR_VALIDATION_FAILED_EXT;
+            }
+            if(!VmaValidateMagicValue(pBlockData, suballoc.offset + suballoc.size))
+            {
+                VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED AFTER VALIDATED ALLOCATION!");
+                return VK_ERROR_VALIDATION_FAILED_EXT;
+            }
+        }
+    }
+
+    SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+    for(size_t i = 0, count = suballocations2nd.size(); i < count; ++i)
+    {
+        const VmaSuballocation& suballoc = suballocations2nd[i];
+        if(suballoc.type != VMA_SUBALLOCATION_TYPE_FREE)
+        {
+            if(!VmaValidateMagicValue(pBlockData, suballoc.offset - VMA_DEBUG_MARGIN))
+            {
+                VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED BEFORE VALIDATED ALLOCATION!");
+                return VK_ERROR_VALIDATION_FAILED_EXT;
+            }
+            if(!VmaValidateMagicValue(pBlockData, suballoc.offset + suballoc.size))
+            {
+                VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED AFTER VALIDATED ALLOCATION!");
+                return VK_ERROR_VALIDATION_FAILED_EXT;
+            }
+        }
+    }
+
+    return VK_SUCCESS;
+}
+
+void VmaBlockMetadata_Linear::Alloc(
+    const VmaAllocationRequest& request,
+    VmaSuballocationType type,
+    VkDeviceSize allocSize,
+    VmaAllocation hAllocation)
+{
+    const VmaSuballocation newSuballoc = { request.offset, allocSize, hAllocation, type };
+
+    switch(request.type)
+    {
+    case VmaAllocationRequestType::UpperAddress:
+        {
+            VMA_ASSERT(m_2ndVectorMode != SECOND_VECTOR_RING_BUFFER &&
+                "CRITICAL ERROR: Trying to use linear allocator as double stack while it was already used as ring buffer.");
+            SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+            suballocations2nd.push_back(newSuballoc);
+            m_2ndVectorMode = SECOND_VECTOR_DOUBLE_STACK;
+        }
+        break;
+    case VmaAllocationRequestType::EndOf1st:
+        {
+            SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+
+            VMA_ASSERT(suballocations1st.empty() ||
+                request.offset >= suballocations1st.back().offset + suballocations1st.back().size);
+            // Check if it fits before the end of the block.
+            VMA_ASSERT(request.offset + allocSize <= GetSize());
+
+            suballocations1st.push_back(newSuballoc);
+        }
+        break;
+    case VmaAllocationRequestType::EndOf2nd:
+        {
+            SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+            // New allocation at the end of 2-part ring buffer, so before first allocation from 1st vector.
+            VMA_ASSERT(!suballocations1st.empty() &&
+                request.offset + allocSize <= suballocations1st[m_1stNullItemsBeginCount].offset);
+            SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+
+            switch(m_2ndVectorMode)
+            {
+            case SECOND_VECTOR_EMPTY:
+                // First allocation from second part ring buffer.
+                VMA_ASSERT(suballocations2nd.empty());
+                m_2ndVectorMode = SECOND_VECTOR_RING_BUFFER;
+                break;
+            case SECOND_VECTOR_RING_BUFFER:
+                // 2-part ring buffer is already started.
+                VMA_ASSERT(!suballocations2nd.empty());
+                break;
+            case SECOND_VECTOR_DOUBLE_STACK:
+                VMA_ASSERT(0 && "CRITICAL ERROR: Trying to use linear allocator as ring buffer while it was already used as double stack.");
+                break;
+            default:
+                VMA_ASSERT(0);
+            }
+
+            suballocations2nd.push_back(newSuballoc);
+        }
+        break;
+    default:
+        VMA_ASSERT(0 && "CRITICAL INTERNAL ERROR.");
+    }
+
+    m_SumFreeSize -= newSuballoc.size;
+}
+
+void VmaBlockMetadata_Linear::Free(const VmaAllocation allocation)
+{
+    FreeAtOffset(allocation->GetOffset());
+}
+
+void VmaBlockMetadata_Linear::FreeAtOffset(VkDeviceSize offset)
+{
+    SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+    SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+
+    if(!suballocations1st.empty())
+    {
+        // First allocation: Mark it as next empty at the beginning.
+        VmaSuballocation& firstSuballoc = suballocations1st[m_1stNullItemsBeginCount];
+        if(firstSuballoc.offset == offset)
+        {
+            firstSuballoc.type = VMA_SUBALLOCATION_TYPE_FREE;
+            firstSuballoc.hAllocation = VK_NULL_HANDLE;
+            m_SumFreeSize += firstSuballoc.size;
+            ++m_1stNullItemsBeginCount;
+            CleanupAfterFree();
+            return;
+        }
+    }
+
+    // Last allocation in 2-part ring buffer or top of upper stack (same logic).
+    if(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER ||
+        m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)
+    {
+        VmaSuballocation& lastSuballoc = suballocations2nd.back();
+        if(lastSuballoc.offset == offset)
+        {
+            m_SumFreeSize += lastSuballoc.size;
+            suballocations2nd.pop_back();
+            CleanupAfterFree();
+            return;
+        }
+    }
+    // Last allocation in 1st vector.
+    else if(m_2ndVectorMode == SECOND_VECTOR_EMPTY)
+    {
+        VmaSuballocation& lastSuballoc = suballocations1st.back();
+        if(lastSuballoc.offset == offset)
+        {
+            m_SumFreeSize += lastSuballoc.size;
+            suballocations1st.pop_back();
+            CleanupAfterFree();
+            return;
+        }
+    }
+
+    // Item from the middle of 1st vector.
+    {
+        VmaSuballocation refSuballoc;
+        refSuballoc.offset = offset;
+        // Rest of members stays uninitialized intentionally for better performance.
+        SuballocationVectorType::iterator it = VmaBinaryFindSorted(
+            suballocations1st.begin() + m_1stNullItemsBeginCount,
+            suballocations1st.end(),
+            refSuballoc,
+            VmaSuballocationOffsetLess());
+        if(it != suballocations1st.end())
+        {
+            it->type = VMA_SUBALLOCATION_TYPE_FREE;
+            it->hAllocation = VK_NULL_HANDLE;
+            ++m_1stNullItemsMiddleCount;
+            m_SumFreeSize += it->size;
+            CleanupAfterFree();
+            return;
+        }
+    }
+
+    if(m_2ndVectorMode != SECOND_VECTOR_EMPTY)
+    {
+        // Item from the middle of 2nd vector.
+        VmaSuballocation refSuballoc;
+        refSuballoc.offset = offset;
+        // Rest of members stays uninitialized intentionally for better performance.
+        SuballocationVectorType::iterator it = m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER ?
+            VmaBinaryFindSorted(suballocations2nd.begin(), suballocations2nd.end(), refSuballoc, VmaSuballocationOffsetLess()) :
+            VmaBinaryFindSorted(suballocations2nd.begin(), suballocations2nd.end(), refSuballoc, VmaSuballocationOffsetGreater());
+        if(it != suballocations2nd.end())
+        {
+            it->type = VMA_SUBALLOCATION_TYPE_FREE;
+            it->hAllocation = VK_NULL_HANDLE;
+            ++m_2ndNullItemsCount;
+            m_SumFreeSize += it->size;
+            CleanupAfterFree();
+            return;
+        }
+    }
+
+    VMA_ASSERT(0 && "Allocation to free not found in linear allocator!");
+}
+
+bool VmaBlockMetadata_Linear::ShouldCompact1st() const
+{
+    const size_t nullItemCount = m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount;
+    const size_t suballocCount = AccessSuballocations1st().size();
+    return suballocCount > 32 && nullItemCount * 2 >= (suballocCount - nullItemCount) * 3;
+}
+
+void VmaBlockMetadata_Linear::CleanupAfterFree()
+{
+    SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+    SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+
+    if(IsEmpty())
+    {
+        suballocations1st.clear();
+        suballocations2nd.clear();
+        m_1stNullItemsBeginCount = 0;
+        m_1stNullItemsMiddleCount = 0;
+        m_2ndNullItemsCount = 0;
+        m_2ndVectorMode = SECOND_VECTOR_EMPTY;
+    }
+    else
+    {
+        const size_t suballoc1stCount = suballocations1st.size();
+        const size_t nullItem1stCount = m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount;
+        VMA_ASSERT(nullItem1stCount <= suballoc1stCount);
+
+        // Find more null items at the beginning of 1st vector.
+        while(m_1stNullItemsBeginCount < suballoc1stCount &&
+            suballocations1st[m_1stNullItemsBeginCount].hAllocation == VK_NULL_HANDLE)
+        {
+            ++m_1stNullItemsBeginCount;
+            --m_1stNullItemsMiddleCount;
+        }
+
+        // Find more null items at the end of 1st vector.
+        while(m_1stNullItemsMiddleCount > 0 &&
+            suballocations1st.back().hAllocation == VK_NULL_HANDLE)
+        {
+            --m_1stNullItemsMiddleCount;
+            suballocations1st.pop_back();
+        }
+
+        // Find more null items at the end of 2nd vector.
+        while(m_2ndNullItemsCount > 0 &&
+            suballocations2nd.back().hAllocation == VK_NULL_HANDLE)
+        {
+            --m_2ndNullItemsCount;
+            suballocations2nd.pop_back();
+        }
+
+        // Find more null items at the beginning of 2nd vector.
+        while(m_2ndNullItemsCount > 0 &&
+            suballocations2nd[0].hAllocation == VK_NULL_HANDLE)
+        {
+            --m_2ndNullItemsCount;
+            VmaVectorRemove(suballocations2nd, 0);
+        }
+
+        if(ShouldCompact1st())
+        {
+            const size_t nonNullItemCount = suballoc1stCount - nullItem1stCount;
+            size_t srcIndex = m_1stNullItemsBeginCount;
+            for(size_t dstIndex = 0; dstIndex < nonNullItemCount; ++dstIndex)
+            {
+                while(suballocations1st[srcIndex].hAllocation == VK_NULL_HANDLE)
+                {
+                    ++srcIndex;
+                }
+                if(dstIndex != srcIndex)
+                {
+                    suballocations1st[dstIndex] = suballocations1st[srcIndex];
+                }
+                ++srcIndex;
+            }
+            suballocations1st.resize(nonNullItemCount);
+            m_1stNullItemsBeginCount = 0;
+            m_1stNullItemsMiddleCount = 0;
+        }
+
+        // 2nd vector became empty.
+        if(suballocations2nd.empty())
+        {
+            m_2ndVectorMode = SECOND_VECTOR_EMPTY;
+        }
+
+        // 1st vector became empty.
+        if(suballocations1st.size() - m_1stNullItemsBeginCount == 0)
+        {
+            suballocations1st.clear();
+            m_1stNullItemsBeginCount = 0;
+
+            if(!suballocations2nd.empty() && m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
+            {
+                // Swap 1st with 2nd. Now 2nd is empty.
+                m_2ndVectorMode = SECOND_VECTOR_EMPTY;
+                m_1stNullItemsMiddleCount = m_2ndNullItemsCount;
+                while(m_1stNullItemsBeginCount < suballocations2nd.size() &&
+                    suballocations2nd[m_1stNullItemsBeginCount].hAllocation == VK_NULL_HANDLE)
+                {
+                    ++m_1stNullItemsBeginCount;
+                    --m_1stNullItemsMiddleCount;
+                }
+                m_2ndNullItemsCount = 0;
+                m_1stVectorIndex ^= 1;
+            }
+        }
+    }
+
+    VMA_HEAVY_ASSERT(Validate());
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// class VmaBlockMetadata_Buddy
+
+VmaBlockMetadata_Buddy::VmaBlockMetadata_Buddy(VmaAllocator hAllocator) :
+    VmaBlockMetadata(hAllocator),
+    m_Root(VMA_NULL),
+    m_AllocationCount(0),
+    m_FreeCount(1),
+    m_SumFreeSize(0)
+{
+    memset(m_FreeList, 0, sizeof(m_FreeList));
+}
+
+VmaBlockMetadata_Buddy::~VmaBlockMetadata_Buddy()
+{
+    DeleteNode(m_Root);
+}
+
+void VmaBlockMetadata_Buddy::Init(VkDeviceSize size)
+{
+    VmaBlockMetadata::Init(size);
+
+    m_UsableSize = VmaPrevPow2(size);
+    m_SumFreeSize = m_UsableSize;
+
+    // Calculate m_LevelCount.
+    m_LevelCount = 1;
+    while(m_LevelCount < MAX_LEVELS &&
+        LevelToNodeSize(m_LevelCount) >= MIN_NODE_SIZE)
+    {
+        ++m_LevelCount;
+    }
+
+    Node* rootNode = vma_new(GetAllocationCallbacks(), Node)();
+    rootNode->offset = 0;
+    rootNode->type = Node::TYPE_FREE;
+    rootNode->parent = VMA_NULL;
+    rootNode->buddy = VMA_NULL;
+
+    m_Root = rootNode;
+    AddToFreeListFront(0, rootNode);
+}
+
+bool VmaBlockMetadata_Buddy::Validate() const
+{
+    // Validate tree.
+    ValidationContext ctx;
+    if(!ValidateNode(ctx, VMA_NULL, m_Root, 0, LevelToNodeSize(0)))
+    {
+        VMA_VALIDATE(false && "ValidateNode failed.");
+    }
+    VMA_VALIDATE(m_AllocationCount == ctx.calculatedAllocationCount);
+    VMA_VALIDATE(m_SumFreeSize == ctx.calculatedSumFreeSize);
+
+    // Validate free node lists.
+    for(uint32_t level = 0; level < m_LevelCount; ++level)
+    {
+        VMA_VALIDATE(m_FreeList[level].front == VMA_NULL ||
+            m_FreeList[level].front->free.prev == VMA_NULL);
+
+        for(Node* node = m_FreeList[level].front;
+            node != VMA_NULL;
+            node = node->free.next)
+        {
+            VMA_VALIDATE(node->type == Node::TYPE_FREE);
+            
+            if(node->free.next == VMA_NULL)
+            {
+                VMA_VALIDATE(m_FreeList[level].back == node);
+            }
+            else
+            {
+                VMA_VALIDATE(node->free.next->free.prev == node);
+            }
+        }
+    }
+
+    // Validate that free lists ar higher levels are empty.
+    for(uint32_t level = m_LevelCount; level < MAX_LEVELS; ++level)
+    {
+        VMA_VALIDATE(m_FreeList[level].front == VMA_NULL && m_FreeList[level].back == VMA_NULL);
+    }
+
+    return true;
+}
+
+VkDeviceSize VmaBlockMetadata_Buddy::GetUnusedRangeSizeMax() const
+{
+    for(uint32_t level = 0; level < m_LevelCount; ++level)
+    {
+        if(m_FreeList[level].front != VMA_NULL)
+        {
+            return LevelToNodeSize(level);
+        }
+    }
+    return 0;
+}
+
+void VmaBlockMetadata_Buddy::CalcAllocationStatInfo(VmaStatInfo& outInfo) const
+{
+    const VkDeviceSize unusableSize = GetUnusableSize();
+
+    outInfo.blockCount = 1;
+
+    outInfo.allocationCount = outInfo.unusedRangeCount = 0;
+    outInfo.usedBytes = outInfo.unusedBytes = 0;
+
+    outInfo.allocationSizeMax = outInfo.unusedRangeSizeMax = 0;
+    outInfo.allocationSizeMin = outInfo.unusedRangeSizeMin = UINT64_MAX;
+    outInfo.allocationSizeAvg = outInfo.unusedRangeSizeAvg = 0; // Unused.
+
+    CalcAllocationStatInfoNode(outInfo, m_Root, LevelToNodeSize(0));
+
+    if(unusableSize > 0)
+    {
+        ++outInfo.unusedRangeCount;
+        outInfo.unusedBytes += unusableSize;
+        outInfo.unusedRangeSizeMax = VMA_MAX(outInfo.unusedRangeSizeMax, unusableSize);
+        outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, unusableSize);
+    }
+}
+
+void VmaBlockMetadata_Buddy::AddPoolStats(VmaPoolStats& inoutStats) const
+{
+    const VkDeviceSize unusableSize = GetUnusableSize();
+
+    inoutStats.size += GetSize();
+    inoutStats.unusedSize += m_SumFreeSize + unusableSize;
+    inoutStats.allocationCount += m_AllocationCount;
+    inoutStats.unusedRangeCount += m_FreeCount;
+    inoutStats.unusedRangeSizeMax = VMA_MAX(inoutStats.unusedRangeSizeMax, GetUnusedRangeSizeMax());
+
+    if(unusableSize > 0)
+    {
+        ++inoutStats.unusedRangeCount;
+        // Not updating inoutStats.unusedRangeSizeMax with unusableSize because this space is not available for allocations.
+    }
+}
+
+#if VMA_STATS_STRING_ENABLED
+
+void VmaBlockMetadata_Buddy::PrintDetailedMap(class VmaJsonWriter& json) const
+{
+    // TODO optimize
+    VmaStatInfo stat;
+    CalcAllocationStatInfo(stat);
+
+    PrintDetailedMap_Begin(
+        json,
+        stat.unusedBytes,
+        stat.allocationCount,
+        stat.unusedRangeCount);
+
+    PrintDetailedMapNode(json, m_Root, LevelToNodeSize(0));
+
+    const VkDeviceSize unusableSize = GetUnusableSize();
+    if(unusableSize > 0)
+    {
+        PrintDetailedMap_UnusedRange(json,
+            m_UsableSize, // offset
+            unusableSize); // size
+    }
+
+    PrintDetailedMap_End(json);
+}
+
+#endif // #if VMA_STATS_STRING_ENABLED
+
+bool VmaBlockMetadata_Buddy::CreateAllocationRequest(
+    uint32_t currentFrameIndex,
+    uint32_t frameInUseCount,
+    VkDeviceSize bufferImageGranularity,
+    VkDeviceSize allocSize,
+    VkDeviceSize allocAlignment,
+    bool upperAddress,
+    VmaSuballocationType allocType,
+    bool canMakeOtherLost,
+    uint32_t strategy,
+    VmaAllocationRequest* pAllocationRequest)
+{
+    VMA_ASSERT(!upperAddress && "VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT can be used only with linear algorithm.");
+
+    // Simple way to respect bufferImageGranularity. May be optimized some day.
+    // Whenever it might be an OPTIMAL image...
+    if(allocType == VMA_SUBALLOCATION_TYPE_UNKNOWN ||
+        allocType == VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN ||
+        allocType == VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL)
+    {
+        allocAlignment = VMA_MAX(allocAlignment, bufferImageGranularity);
+        allocSize = VMA_MAX(allocSize, bufferImageGranularity);
+    }
+
+    if(allocSize > m_UsableSize)
+    {
+        return false;
+    }
+
+    const uint32_t targetLevel = AllocSizeToLevel(allocSize);
+    for(uint32_t level = targetLevel + 1; level--; )
+    {
+        for(Node* freeNode = m_FreeList[level].front;
+            freeNode != VMA_NULL;
+            freeNode = freeNode->free.next)
+        {
+            if(freeNode->offset % allocAlignment == 0)
+            {
+                pAllocationRequest->type = VmaAllocationRequestType::Normal;
+                pAllocationRequest->offset = freeNode->offset;
+                pAllocationRequest->sumFreeSize = LevelToNodeSize(level);
+                pAllocationRequest->sumItemSize = 0;
+                pAllocationRequest->itemsToMakeLostCount = 0;
+                pAllocationRequest->customData = (void*)(uintptr_t)level;
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+bool VmaBlockMetadata_Buddy::MakeRequestedAllocationsLost(
+    uint32_t currentFrameIndex,
+    uint32_t frameInUseCount,
+    VmaAllocationRequest* pAllocationRequest)
+{
+    /*
+    Lost allocations are not supported in buddy allocator at the moment.
+    Support might be added in the future.
+    */
+    return pAllocationRequest->itemsToMakeLostCount == 0;
+}
+
+uint32_t VmaBlockMetadata_Buddy::MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount)
+{
+    /*
+    Lost allocations are not supported in buddy allocator at the moment.
+    Support might be added in the future.
+    */
+    return 0;
+}
+
+void VmaBlockMetadata_Buddy::Alloc(
+    const VmaAllocationRequest& request,
+    VmaSuballocationType type,
+    VkDeviceSize allocSize,
+    VmaAllocation hAllocation)
+{
+    VMA_ASSERT(request.type == VmaAllocationRequestType::Normal);
+
+    const uint32_t targetLevel = AllocSizeToLevel(allocSize);
+    uint32_t currLevel = (uint32_t)(uintptr_t)request.customData;
+    
+    Node* currNode = m_FreeList[currLevel].front;
+    VMA_ASSERT(currNode != VMA_NULL && currNode->type == Node::TYPE_FREE);
+    while(currNode->offset != request.offset)
+    {
+        currNode = currNode->free.next;
+        VMA_ASSERT(currNode != VMA_NULL && currNode->type == Node::TYPE_FREE);
+    }
+    
+    // Go down, splitting free nodes.
+    while(currLevel < targetLevel)
+    {
+        // currNode is already first free node at currLevel.
+        // Remove it from list of free nodes at this currLevel.
+        RemoveFromFreeList(currLevel, currNode);
+         
+        const uint32_t childrenLevel = currLevel + 1;
+
+        // Create two free sub-nodes.
+        Node* leftChild = vma_new(GetAllocationCallbacks(), Node)();
+        Node* rightChild = vma_new(GetAllocationCallbacks(), Node)();
+
+        leftChild->offset = currNode->offset;
+        leftChild->type = Node::TYPE_FREE;
+        leftChild->parent = currNode;
+        leftChild->buddy = rightChild;
+
+        rightChild->offset = currNode->offset + LevelToNodeSize(childrenLevel);
+        rightChild->type = Node::TYPE_FREE;
+        rightChild->parent = currNode;
+        rightChild->buddy = leftChild;
+
+        // Convert current currNode to split type.
+        currNode->type = Node::TYPE_SPLIT;
+        currNode->split.leftChild = leftChild;
+
+        // Add child nodes to free list. Order is important!
+        AddToFreeListFront(childrenLevel, rightChild);
+        AddToFreeListFront(childrenLevel, leftChild);
+
+        ++m_FreeCount;
+        //m_SumFreeSize -= LevelToNodeSize(currLevel) % 2; // Useful only when level node sizes can be non power of 2.
+        ++currLevel;
+        currNode = m_FreeList[currLevel].front;
+
+        /*
+        We can be sure that currNode, as left child of node previously split,
+        also fullfills the alignment requirement.
+        */
+    }
+
+    // Remove from free list.
+    VMA_ASSERT(currLevel == targetLevel &&
+        currNode != VMA_NULL &&
+        currNode->type == Node::TYPE_FREE);
+    RemoveFromFreeList(currLevel, currNode);
+
+    // Convert to allocation node.
+    currNode->type = Node::TYPE_ALLOCATION;
+    currNode->allocation.alloc = hAllocation;
+
+    ++m_AllocationCount;
+    --m_FreeCount;
+    m_SumFreeSize -= allocSize;
+}
+
+void VmaBlockMetadata_Buddy::DeleteNode(Node* node)
+{
+    if(node->type == Node::TYPE_SPLIT)
+    {
+        DeleteNode(node->split.leftChild->buddy);
+        DeleteNode(node->split.leftChild);
+    }
+
+    vma_delete(GetAllocationCallbacks(), node);
+}
+
+bool VmaBlockMetadata_Buddy::ValidateNode(ValidationContext& ctx, const Node* parent, const Node* curr, uint32_t level, VkDeviceSize levelNodeSize) const
+{
+    VMA_VALIDATE(level < m_LevelCount);
+    VMA_VALIDATE(curr->parent == parent);
+    VMA_VALIDATE((curr->buddy == VMA_NULL) == (parent == VMA_NULL));
+    VMA_VALIDATE(curr->buddy == VMA_NULL || curr->buddy->buddy == curr);
+    switch(curr->type)
+    {
+    case Node::TYPE_FREE:
+        // curr->free.prev, next are validated separately.
+        ctx.calculatedSumFreeSize += levelNodeSize;
+        ++ctx.calculatedFreeCount;
+        break;
+    case Node::TYPE_ALLOCATION:
+        ++ctx.calculatedAllocationCount;
+        ctx.calculatedSumFreeSize += levelNodeSize - curr->allocation.alloc->GetSize();
+        VMA_VALIDATE(curr->allocation.alloc != VK_NULL_HANDLE);
+        break;
+    case Node::TYPE_SPLIT:
+        {
+            const uint32_t childrenLevel = level + 1;
+            const VkDeviceSize childrenLevelNodeSize = levelNodeSize / 2;
+            const Node* const leftChild = curr->split.leftChild;
+            VMA_VALIDATE(leftChild != VMA_NULL);
+            VMA_VALIDATE(leftChild->offset == curr->offset);
+            if(!ValidateNode(ctx, curr, leftChild, childrenLevel, childrenLevelNodeSize))
+            {
+                VMA_VALIDATE(false && "ValidateNode for left child failed.");
+            }
+            const Node* const rightChild = leftChild->buddy;
+            VMA_VALIDATE(rightChild->offset == curr->offset + childrenLevelNodeSize);
+            if(!ValidateNode(ctx, curr, rightChild, childrenLevel, childrenLevelNodeSize))
+            {
+                VMA_VALIDATE(false && "ValidateNode for right child failed.");
+            }
+        }
+        break;
+    default:
+        return false;
+    }
+
+    return true;
+}
+
+uint32_t VmaBlockMetadata_Buddy::AllocSizeToLevel(VkDeviceSize allocSize) const
+{
+    // I know this could be optimized somehow e.g. by using std::log2p1 from C++20.
+    uint32_t level = 0;
+    VkDeviceSize currLevelNodeSize = m_UsableSize;
+    VkDeviceSize nextLevelNodeSize = currLevelNodeSize >> 1;
+    while(allocSize <= nextLevelNodeSize && level + 1 < m_LevelCount)
+    {
+        ++level;
+        currLevelNodeSize = nextLevelNodeSize;
+        nextLevelNodeSize = currLevelNodeSize >> 1;
+    }
+    return level;
+}
+
+void VmaBlockMetadata_Buddy::FreeAtOffset(VmaAllocation alloc, VkDeviceSize offset)
+{
+    // Find node and level.
+    Node* node = m_Root;
+    VkDeviceSize nodeOffset = 0;
+    uint32_t level = 0;
+    VkDeviceSize levelNodeSize = LevelToNodeSize(0);
+    while(node->type == Node::TYPE_SPLIT)
+    {
+        const VkDeviceSize nextLevelSize = levelNodeSize >> 1;
+        if(offset < nodeOffset + nextLevelSize)
+        {
+            node = node->split.leftChild;
+        }
+        else
+        {
+            node = node->split.leftChild->buddy;
+            nodeOffset += nextLevelSize;
+        }
+        ++level;
+        levelNodeSize = nextLevelSize;
+    }
+
+    VMA_ASSERT(node != VMA_NULL && node->type == Node::TYPE_ALLOCATION);
+    VMA_ASSERT(alloc == VK_NULL_HANDLE || node->allocation.alloc == alloc);
+
+    ++m_FreeCount;
+    --m_AllocationCount;
+    m_SumFreeSize += alloc->GetSize();
+
+    node->type = Node::TYPE_FREE;
+
+    // Join free nodes if possible.
+    while(level > 0 && node->buddy->type == Node::TYPE_FREE)
+    {
+        RemoveFromFreeList(level, node->buddy);
+        Node* const parent = node->parent;
+
+        vma_delete(GetAllocationCallbacks(), node->buddy);
+        vma_delete(GetAllocationCallbacks(), node);
+        parent->type = Node::TYPE_FREE;
+        
+        node = parent;
+        --level;
+        //m_SumFreeSize += LevelToNodeSize(level) % 2; // Useful only when level node sizes can be non power of 2.
+        --m_FreeCount;
+    }
+
+    AddToFreeListFront(level, node);
+}
+
+void VmaBlockMetadata_Buddy::CalcAllocationStatInfoNode(VmaStatInfo& outInfo, const Node* node, VkDeviceSize levelNodeSize) const
+{
+    switch(node->type)
+    {
+    case Node::TYPE_FREE:
+        ++outInfo.unusedRangeCount;
+        outInfo.unusedBytes += levelNodeSize;
+        outInfo.unusedRangeSizeMax = VMA_MAX(outInfo.unusedRangeSizeMax, levelNodeSize);
+        outInfo.unusedRangeSizeMin = VMA_MAX(outInfo.unusedRangeSizeMin, levelNodeSize);
+        break;
+    case Node::TYPE_ALLOCATION:
+        {
+            const VkDeviceSize allocSize = node->allocation.alloc->GetSize();
+            ++outInfo.allocationCount;
+            outInfo.usedBytes += allocSize;
+            outInfo.allocationSizeMax = VMA_MAX(outInfo.allocationSizeMax, allocSize);
+            outInfo.allocationSizeMin = VMA_MAX(outInfo.allocationSizeMin, allocSize);
+
+            const VkDeviceSize unusedRangeSize = levelNodeSize - allocSize;
+            if(unusedRangeSize > 0)
+            {
+                ++outInfo.unusedRangeCount;
+                outInfo.unusedBytes += unusedRangeSize;
+                outInfo.unusedRangeSizeMax = VMA_MAX(outInfo.unusedRangeSizeMax, unusedRangeSize);
+                outInfo.unusedRangeSizeMin = VMA_MAX(outInfo.unusedRangeSizeMin, unusedRangeSize);
+            }
+        }
+        break;
+    case Node::TYPE_SPLIT:
+        {
+            const VkDeviceSize childrenNodeSize = levelNodeSize / 2;
+            const Node* const leftChild = node->split.leftChild;
+            CalcAllocationStatInfoNode(outInfo, leftChild, childrenNodeSize);
+            const Node* const rightChild = leftChild->buddy;
+            CalcAllocationStatInfoNode(outInfo, rightChild, childrenNodeSize);
+        }
+        break;
+    default:
+        VMA_ASSERT(0);
+    }
+}
+
+void VmaBlockMetadata_Buddy::AddToFreeListFront(uint32_t level, Node* node)
+{
+    VMA_ASSERT(node->type == Node::TYPE_FREE);
+
+    // List is empty.
+    Node* const frontNode = m_FreeList[level].front;
+    if(frontNode == VMA_NULL)
+    {
+        VMA_ASSERT(m_FreeList[level].back == VMA_NULL);
+        node->free.prev = node->free.next = VMA_NULL;
+        m_FreeList[level].front = m_FreeList[level].back = node;
+    }
+    else
+    {
+        VMA_ASSERT(frontNode->free.prev == VMA_NULL);
+        node->free.prev = VMA_NULL;
+        node->free.next = frontNode;
+        frontNode->free.prev = node;
+        m_FreeList[level].front = node;
+    }
+}
+
+void VmaBlockMetadata_Buddy::RemoveFromFreeList(uint32_t level, Node* node)
+{
+    VMA_ASSERT(m_FreeList[level].front != VMA_NULL);
+
+    // It is at the front.
+    if(node->free.prev == VMA_NULL)
+    {
+        VMA_ASSERT(m_FreeList[level].front == node);
+        m_FreeList[level].front = node->free.next;
+    }
+    else
+    {
+        Node* const prevFreeNode = node->free.prev;
+        VMA_ASSERT(prevFreeNode->free.next == node);
+        prevFreeNode->free.next = node->free.next;
+    }
+
+    // It is at the back.
+    if(node->free.next == VMA_NULL)
+    {
+        VMA_ASSERT(m_FreeList[level].back == node);
+        m_FreeList[level].back = node->free.prev;
+    }
+    else
+    {
+        Node* const nextFreeNode = node->free.next;
+        VMA_ASSERT(nextFreeNode->free.prev == node);
+        nextFreeNode->free.prev = node->free.prev;
+    }
+}
+
+#if VMA_STATS_STRING_ENABLED
+void VmaBlockMetadata_Buddy::PrintDetailedMapNode(class VmaJsonWriter& json, const Node* node, VkDeviceSize levelNodeSize) const
+{
+    switch(node->type)
+    {
+    case Node::TYPE_FREE:
+        PrintDetailedMap_UnusedRange(json, node->offset, levelNodeSize);
+        break;
+    case Node::TYPE_ALLOCATION:
+        {   
+            PrintDetailedMap_Allocation(json, node->offset, node->allocation.alloc);
+            const VkDeviceSize allocSize = node->allocation.alloc->GetSize();
+            if(allocSize < levelNodeSize)
+            {
+                PrintDetailedMap_UnusedRange(json, node->offset + allocSize, levelNodeSize - allocSize);
+            }
+        }
+        break;
+    case Node::TYPE_SPLIT:
+        {
+            const VkDeviceSize childrenNodeSize = levelNodeSize / 2;
+            const Node* const leftChild = node->split.leftChild;
+            PrintDetailedMapNode(json, leftChild, childrenNodeSize);
+            const Node* const rightChild = leftChild->buddy;
+            PrintDetailedMapNode(json, rightChild, childrenNodeSize);
+        }
+        break;
+    default:
+        VMA_ASSERT(0);
+    }
+}
+#endif // #if VMA_STATS_STRING_ENABLED
+
+
+////////////////////////////////////////////////////////////////////////////////
+// class VmaDeviceMemoryBlock
+
+VmaDeviceMemoryBlock::VmaDeviceMemoryBlock(VmaAllocator hAllocator) :
+    m_pMetadata(VMA_NULL),
+    m_MemoryTypeIndex(UINT32_MAX),
+    m_Id(0),
+    m_hMemory(VK_NULL_HANDLE),
+    m_MapCount(0),
+    m_pMappedData(VMA_NULL)
+{
+}
+
+void VmaDeviceMemoryBlock::Init(
+    VmaAllocator hAllocator,
+    VmaPool hParentPool,
+    uint32_t newMemoryTypeIndex,
+    VkDeviceMemory newMemory,
+    VkDeviceSize newSize,
+    uint32_t id,
+    uint32_t algorithm)
+{
+    VMA_ASSERT(m_hMemory == VK_NULL_HANDLE);
+
+    m_hParentPool = hParentPool;
+    m_MemoryTypeIndex = newMemoryTypeIndex;
+    m_Id = id;
+    m_hMemory = newMemory;
+
+    switch(algorithm)
+    {
+    case VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT:
+        m_pMetadata = vma_new(hAllocator, VmaBlockMetadata_Linear)(hAllocator);
+        break;
+    case VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT:
+        m_pMetadata = vma_new(hAllocator, VmaBlockMetadata_Buddy)(hAllocator);
+        break;
+    default:
+        VMA_ASSERT(0);
+    case 0:
+        m_pMetadata = vma_new(hAllocator, VmaBlockMetadata_Generic)(hAllocator);
+    }
+    m_pMetadata->Init(newSize);
+}
+
+void VmaDeviceMemoryBlock::Destroy(VmaAllocator allocator)
+{
+    // This is the most important assert in the entire library.
+    // Hitting it means you have some memory leak - unreleased VmaAllocation objects.
+    VMA_ASSERT(m_pMetadata->IsEmpty() && "Some allocations were not freed before destruction of this memory block!");
+
+    VMA_ASSERT(m_hMemory != VK_NULL_HANDLE);
+    allocator->FreeVulkanMemory(m_MemoryTypeIndex, m_pMetadata->GetSize(), m_hMemory);
+    m_hMemory = VK_NULL_HANDLE;
+
+    vma_delete(allocator, m_pMetadata);
+    m_pMetadata = VMA_NULL;
+}
+
+bool VmaDeviceMemoryBlock::Validate() const
+{
+    VMA_VALIDATE((m_hMemory != VK_NULL_HANDLE) &&
+        (m_pMetadata->GetSize() != 0));
+    
+    return m_pMetadata->Validate();
+}
+
+VkResult VmaDeviceMemoryBlock::CheckCorruption(VmaAllocator hAllocator)
+{
+    void* pData = nullptr;
+    VkResult res = Map(hAllocator, 1, &pData);
+    if(res != VK_SUCCESS)
+    {
+        return res;
+    }
+
+    res = m_pMetadata->CheckCorruption(pData);
+
+    Unmap(hAllocator, 1);
+
+    return res;
+}
+
+VkResult VmaDeviceMemoryBlock::Map(VmaAllocator hAllocator, uint32_t count, void** ppData)
+{
+    if(count == 0)
+    {
+        return VK_SUCCESS;
+    }
+
+    VmaMutexLock lock(m_Mutex, hAllocator->m_UseMutex);
+    if(m_MapCount != 0)
+    {
+        m_MapCount += count;
+        VMA_ASSERT(m_pMappedData != VMA_NULL);
+        if(ppData != VMA_NULL)
+        {
+            *ppData = m_pMappedData;
+        }
+        return VK_SUCCESS;
+    }
+    else
+    {
+        VkResult result = (*hAllocator->GetVulkanFunctions().vkMapMemory)(
+            hAllocator->m_hDevice,
+            m_hMemory,
+            0, // offset
+            VK_WHOLE_SIZE,
+            0, // flags
+            &m_pMappedData);
+        if(result == VK_SUCCESS)
+        {
+            if(ppData != VMA_NULL)
+            {
+                *ppData = m_pMappedData;
+            }
+            m_MapCount = count;
+        }
+        return result;
+    }
+}
+
+void VmaDeviceMemoryBlock::Unmap(VmaAllocator hAllocator, uint32_t count)
+{
+    if(count == 0)
+    {
+        return;
+    }
+
+    VmaMutexLock lock(m_Mutex, hAllocator->m_UseMutex);
+    if(m_MapCount >= count)
+    {
+        m_MapCount -= count;
+        if(m_MapCount == 0)
+        {
+            m_pMappedData = VMA_NULL;
+            (*hAllocator->GetVulkanFunctions().vkUnmapMemory)(hAllocator->m_hDevice, m_hMemory);
+        }
+    }
+    else
+    {
+        VMA_ASSERT(0 && "VkDeviceMemory block is being unmapped while it was not previously mapped.");
+    }
+}
+
+VkResult VmaDeviceMemoryBlock::WriteMagicValueAroundAllocation(VmaAllocator hAllocator, VkDeviceSize allocOffset, VkDeviceSize allocSize)
+{
+    VMA_ASSERT(VMA_DEBUG_MARGIN > 0 && VMA_DEBUG_MARGIN % 4 == 0 && VMA_DEBUG_DETECT_CORRUPTION);
+    VMA_ASSERT(allocOffset >= VMA_DEBUG_MARGIN);
+
+    void* pData;
+    VkResult res = Map(hAllocator, 1, &pData);
+    if(res != VK_SUCCESS)
+    {
+        return res;
+    }
+
+    VmaWriteMagicValue(pData, allocOffset - VMA_DEBUG_MARGIN);
+    VmaWriteMagicValue(pData, allocOffset + allocSize);
+
+    Unmap(hAllocator, 1);
+
+    return VK_SUCCESS;
+}
+
+VkResult VmaDeviceMemoryBlock::ValidateMagicValueAroundAllocation(VmaAllocator hAllocator, VkDeviceSize allocOffset, VkDeviceSize allocSize)
+{
+    VMA_ASSERT(VMA_DEBUG_MARGIN > 0 && VMA_DEBUG_MARGIN % 4 == 0 && VMA_DEBUG_DETECT_CORRUPTION);
+    VMA_ASSERT(allocOffset >= VMA_DEBUG_MARGIN);
+
+    void* pData;
+    VkResult res = Map(hAllocator, 1, &pData);
+    if(res != VK_SUCCESS)
+    {
+        return res;
+    }
+
+    if(!VmaValidateMagicValue(pData, allocOffset - VMA_DEBUG_MARGIN))
+    {
+        VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED BEFORE FREED ALLOCATION!");
+    }
+    else if(!VmaValidateMagicValue(pData, allocOffset + allocSize))
+    {
+        VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED AFTER FREED ALLOCATION!");
+    }
+
+    Unmap(hAllocator, 1);
+
+    return VK_SUCCESS;
+}
+
+VkResult VmaDeviceMemoryBlock::BindBufferMemory(
+    const VmaAllocator hAllocator,
+    const VmaAllocation hAllocation,
+    VkDeviceSize allocationLocalOffset,
+    VkBuffer hBuffer,
+    const void* pNext)
+{
+    VMA_ASSERT(hAllocation->GetType() == VmaAllocation_T::ALLOCATION_TYPE_BLOCK &&
+        hAllocation->GetBlock() == this);
+    VMA_ASSERT(allocationLocalOffset < hAllocation->GetSize() &&
+        "Invalid allocationLocalOffset. Did you forget that this offset is relative to the beginning of the allocation, not the whole memory block?");
+    const VkDeviceSize memoryOffset = hAllocation->GetOffset() + allocationLocalOffset;
+    // This lock is important so that we don't call vkBind... and/or vkMap... simultaneously on the same VkDeviceMemory from multiple threads.
+    VmaMutexLock lock(m_Mutex, hAllocator->m_UseMutex);
+    return hAllocator->BindVulkanBuffer(m_hMemory, memoryOffset, hBuffer, pNext);
+}
+
+VkResult VmaDeviceMemoryBlock::BindImageMemory(
+    const VmaAllocator hAllocator,
+    const VmaAllocation hAllocation,
+    VkDeviceSize allocationLocalOffset,
+    VkImage hImage,
+    const void* pNext)
+{
+    VMA_ASSERT(hAllocation->GetType() == VmaAllocation_T::ALLOCATION_TYPE_BLOCK &&
+        hAllocation->GetBlock() == this);
+    VMA_ASSERT(allocationLocalOffset < hAllocation->GetSize() &&
+        "Invalid allocationLocalOffset. Did you forget that this offset is relative to the beginning of the allocation, not the whole memory block?");
+    const VkDeviceSize memoryOffset = hAllocation->GetOffset() + allocationLocalOffset;
+    // This lock is important so that we don't call vkBind... and/or vkMap... simultaneously on the same VkDeviceMemory from multiple threads.
+    VmaMutexLock lock(m_Mutex, hAllocator->m_UseMutex);
+    return hAllocator->BindVulkanImage(m_hMemory, memoryOffset, hImage, pNext);
+}
+
+static void InitStatInfo(VmaStatInfo& outInfo)
+{
+    memset(&outInfo, 0, sizeof(outInfo));
+    outInfo.allocationSizeMin = UINT64_MAX;
+    outInfo.unusedRangeSizeMin = UINT64_MAX;
+}
+
+// Adds statistics srcInfo into inoutInfo, like: inoutInfo += srcInfo.
+static void VmaAddStatInfo(VmaStatInfo& inoutInfo, const VmaStatInfo& srcInfo)
+{
+    inoutInfo.blockCount += srcInfo.blockCount;
+    inoutInfo.allocationCount += srcInfo.allocationCount;
+    inoutInfo.unusedRangeCount += srcInfo.unusedRangeCount;
+    inoutInfo.usedBytes += srcInfo.usedBytes;
+    inoutInfo.unusedBytes += srcInfo.unusedBytes;
+    inoutInfo.allocationSizeMin = VMA_MIN(inoutInfo.allocationSizeMin, srcInfo.allocationSizeMin);
+    inoutInfo.allocationSizeMax = VMA_MAX(inoutInfo.allocationSizeMax, srcInfo.allocationSizeMax);
+    inoutInfo.unusedRangeSizeMin = VMA_MIN(inoutInfo.unusedRangeSizeMin, srcInfo.unusedRangeSizeMin);
+    inoutInfo.unusedRangeSizeMax = VMA_MAX(inoutInfo.unusedRangeSizeMax, srcInfo.unusedRangeSizeMax);
+}
+
+static void VmaPostprocessCalcStatInfo(VmaStatInfo& inoutInfo)
+{
+    inoutInfo.allocationSizeAvg = (inoutInfo.allocationCount > 0) ?
+        VmaRoundDiv<VkDeviceSize>(inoutInfo.usedBytes, inoutInfo.allocationCount) : 0;
+    inoutInfo.unusedRangeSizeAvg = (inoutInfo.unusedRangeCount > 0) ?
+        VmaRoundDiv<VkDeviceSize>(inoutInfo.unusedBytes, inoutInfo.unusedRangeCount) : 0;
+}
+
+VmaPool_T::VmaPool_T(
+    VmaAllocator hAllocator,
+    const VmaPoolCreateInfo& createInfo,
+    VkDeviceSize preferredBlockSize) :
+    m_BlockVector(
+        hAllocator,
+        this, // hParentPool
+        createInfo.memoryTypeIndex,
+        createInfo.blockSize != 0 ? createInfo.blockSize : preferredBlockSize,
+        createInfo.minBlockCount,
+        createInfo.maxBlockCount,
+        (createInfo.flags & VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT) != 0 ? 1 : hAllocator->GetBufferImageGranularity(),
+        createInfo.frameInUseCount,
+        createInfo.blockSize != 0, // explicitBlockSize
+        createInfo.flags & VMA_POOL_CREATE_ALGORITHM_MASK), // algorithm
+    m_Id(0),
+    m_Name(VMA_NULL)
+{
+}
+
+VmaPool_T::~VmaPool_T()
+{
+}
+
+void VmaPool_T::SetName(const char* pName)
+{
+    const VkAllocationCallbacks* allocs = m_BlockVector.GetAllocator()->GetAllocationCallbacks();
+    VmaFreeString(allocs, m_Name);
+    
+    if(pName != VMA_NULL)
+    {
+        m_Name = VmaCreateStringCopy(allocs, pName);
+    }
+    else
+    {
+        m_Name = VMA_NULL;
+    }
+}
+
+#if VMA_STATS_STRING_ENABLED
+
+#endif // #if VMA_STATS_STRING_ENABLED
+
+VmaBlockVector::VmaBlockVector(
+    VmaAllocator hAllocator,
+    VmaPool hParentPool,
+    uint32_t memoryTypeIndex,
+    VkDeviceSize preferredBlockSize,
+    size_t minBlockCount,
+    size_t maxBlockCount,
+    VkDeviceSize bufferImageGranularity,
+    uint32_t frameInUseCount,
+    bool explicitBlockSize,
+    uint32_t algorithm) :
+    m_hAllocator(hAllocator),
+    m_hParentPool(hParentPool),
+    m_MemoryTypeIndex(memoryTypeIndex),
+    m_PreferredBlockSize(preferredBlockSize),
+    m_MinBlockCount(minBlockCount),
+    m_MaxBlockCount(maxBlockCount),
+    m_BufferImageGranularity(bufferImageGranularity),
+    m_FrameInUseCount(frameInUseCount),
+    m_ExplicitBlockSize(explicitBlockSize),
+    m_Algorithm(algorithm),
+    m_HasEmptyBlock(false),
+    m_Blocks(VmaStlAllocator<VmaDeviceMemoryBlock*>(hAllocator->GetAllocationCallbacks())),
+    m_NextBlockId(0)
+{
+}
+
+VmaBlockVector::~VmaBlockVector()
+{
+    for(size_t i = m_Blocks.size(); i--; )
+    {
+        m_Blocks[i]->Destroy(m_hAllocator);
+        vma_delete(m_hAllocator, m_Blocks[i]);
+    }
+}
+
+VkResult VmaBlockVector::CreateMinBlocks()
+{
+    for(size_t i = 0; i < m_MinBlockCount; ++i)
+    {
+        VkResult res = CreateBlock(m_PreferredBlockSize, VMA_NULL);
+        if(res != VK_SUCCESS)
+        {
+            return res;
+        }
+    }
+    return VK_SUCCESS;
+}
+
+void VmaBlockVector::GetPoolStats(VmaPoolStats* pStats)
+{
+    VmaMutexLockRead lock(m_Mutex, m_hAllocator->m_UseMutex);
+
+    const size_t blockCount = m_Blocks.size();
+
+    pStats->size = 0;
+    pStats->unusedSize = 0;
+    pStats->allocationCount = 0;
+    pStats->unusedRangeCount = 0;
+    pStats->unusedRangeSizeMax = 0;
+    pStats->blockCount = blockCount;
+
+    for(uint32_t blockIndex = 0; blockIndex < blockCount; ++blockIndex)
+    {
+        const VmaDeviceMemoryBlock* const pBlock = m_Blocks[blockIndex];
+        VMA_ASSERT(pBlock);
+        VMA_HEAVY_ASSERT(pBlock->Validate());
+        pBlock->m_pMetadata->AddPoolStats(*pStats);
+    }
+}
+
+bool VmaBlockVector::IsEmpty()
+{
+    VmaMutexLockRead lock(m_Mutex, m_hAllocator->m_UseMutex);
+    return m_Blocks.empty();
+}
+
+bool VmaBlockVector::IsCorruptionDetectionEnabled() const
+{
+    const uint32_t requiredMemFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
+    return (VMA_DEBUG_DETECT_CORRUPTION != 0) &&
+        (VMA_DEBUG_MARGIN > 0) &&
+        (m_Algorithm == 0 || m_Algorithm == VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT) &&
+        (m_hAllocator->m_MemProps.memoryTypes[m_MemoryTypeIndex].propertyFlags & requiredMemFlags) == requiredMemFlags;
+}
+
+static const uint32_t VMA_ALLOCATION_TRY_COUNT = 32;
+
+VkResult VmaBlockVector::Allocate(
+    uint32_t currentFrameIndex,
+    VkDeviceSize size,
+    VkDeviceSize alignment,
+    const VmaAllocationCreateInfo& createInfo,
+    VmaSuballocationType suballocType,
+    size_t allocationCount,
+    VmaAllocation* pAllocations)
+{
+    size_t allocIndex;
+    VkResult res = VK_SUCCESS;
+
+    if(IsCorruptionDetectionEnabled())
+    {
+        size = VmaAlignUp<VkDeviceSize>(size, sizeof(VMA_CORRUPTION_DETECTION_MAGIC_VALUE));
+        alignment = VmaAlignUp<VkDeviceSize>(alignment, sizeof(VMA_CORRUPTION_DETECTION_MAGIC_VALUE));
+    }
+
+    {
+        VmaMutexLockWrite lock(m_Mutex, m_hAllocator->m_UseMutex);
+        for(allocIndex = 0; allocIndex < allocationCount; ++allocIndex)
+        {
+            res = AllocatePage(
+                currentFrameIndex,
+                size,
+                alignment,
+                createInfo,
+                suballocType,
+                pAllocations + allocIndex);
+            if(res != VK_SUCCESS)
+            {
+                break;
+            }
+        }
+    }
+
+    if(res != VK_SUCCESS)
+    {
+        // Free all already created allocations.
+        while(allocIndex--)
+        {
+            Free(pAllocations[allocIndex]);
+        }
+        memset(pAllocations, 0, sizeof(VmaAllocation) * allocationCount);
+    }
+
+    return res;
+}
+
+VkResult VmaBlockVector::AllocatePage(
+    uint32_t currentFrameIndex,
+    VkDeviceSize size,
+    VkDeviceSize alignment,
+    const VmaAllocationCreateInfo& createInfo,
+    VmaSuballocationType suballocType,
+    VmaAllocation* pAllocation)
+{
+    const bool isUpperAddress = (createInfo.flags & VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT) != 0;
+    bool canMakeOtherLost = (createInfo.flags & VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT) != 0;
+    const bool mapped = (createInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0;
+    const bool isUserDataString = (createInfo.flags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0;
+    
+    VkDeviceSize freeMemory;
+    {
+        const uint32_t heapIndex = m_hAllocator->MemoryTypeIndexToHeapIndex(m_MemoryTypeIndex);
+        VmaBudget heapBudget = {};
+        m_hAllocator->GetBudget(&heapBudget, heapIndex, 1);
+        freeMemory = (heapBudget.usage < heapBudget.budget) ? (heapBudget.budget - heapBudget.usage) : 0;
+    }
+    
+    const bool canFallbackToDedicated = !IsCustomPool();
+    const bool canCreateNewBlock =
+        ((createInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) == 0) &&
+        (m_Blocks.size() < m_MaxBlockCount) &&
+        (freeMemory >= size || !canFallbackToDedicated);
+    uint32_t strategy = createInfo.flags & VMA_ALLOCATION_CREATE_STRATEGY_MASK;
+
+    // If linearAlgorithm is used, canMakeOtherLost is available only when used as ring buffer.
+    // Which in turn is available only when maxBlockCount = 1.
+    if(m_Algorithm == VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT && m_MaxBlockCount > 1)
+    {
+        canMakeOtherLost = false;
+    }
+
+    // Upper address can only be used with linear allocator and within single memory block.
+    if(isUpperAddress &&
+        (m_Algorithm != VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT || m_MaxBlockCount > 1))
+    {
+        return VK_ERROR_FEATURE_NOT_PRESENT;
+    }
+
+    // Validate strategy.
+    switch(strategy)
+    {
+    case 0:
+        strategy = VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT;
+        break;
+    case VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT:
+    case VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT:
+    case VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT:
+        break;
+    default:
+        return VK_ERROR_FEATURE_NOT_PRESENT;
+    }
+
+    // Early reject: requested allocation size is larger that maximum block size for this block vector.
+    if(size + 2 * VMA_DEBUG_MARGIN > m_PreferredBlockSize)
+    {
+        return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+    }
+
+    /*
+    Under certain condition, this whole section can be skipped for optimization, so
+    we move on directly to trying to allocate with canMakeOtherLost. That's the case
+    e.g. for custom pools with linear algorithm.
+    */
+    if(!canMakeOtherLost || canCreateNewBlock)
+    {
+        // 1. Search existing allocations. Try to allocate without making other allocations lost.
+        VmaAllocationCreateFlags allocFlagsCopy = createInfo.flags;
+        allocFlagsCopy &= ~VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT;
+
+        if(m_Algorithm == VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT)
+        {
+            // Use only last block.
+            if(!m_Blocks.empty())
+            {
+                VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks.back();
+                VMA_ASSERT(pCurrBlock);
+                VkResult res = AllocateFromBlock(
+                    pCurrBlock,
+                    currentFrameIndex,
+                    size,
+                    alignment,
+                    allocFlagsCopy,
+                    createInfo.pUserData,
+                    suballocType,
+                    strategy,
+                    pAllocation);
+                if(res == VK_SUCCESS)
+                {
+                    VMA_DEBUG_LOG("    Returned from last block #%u", pCurrBlock->GetId());
+                    return VK_SUCCESS;
+                }
+            }
+        }
+        else
+        {
+            if(strategy == VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT)
+            {
+                // Forward order in m_Blocks - prefer blocks with smallest amount of free space.
+                for(size_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex )
+                {
+                    VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks[blockIndex];
+                    VMA_ASSERT(pCurrBlock);
+                    VkResult res = AllocateFromBlock(
+                        pCurrBlock,
+                        currentFrameIndex,
+                        size,
+                        alignment,
+                        allocFlagsCopy,
+                        createInfo.pUserData,
+                        suballocType,
+                        strategy,
+                        pAllocation);
+                    if(res == VK_SUCCESS)
+                    {
+                        VMA_DEBUG_LOG("    Returned from existing block #%u", pCurrBlock->GetId());
+                        return VK_SUCCESS;
+                    }
+                }
+            }
+            else // WORST_FIT, FIRST_FIT
+            {
+                // Backward order in m_Blocks - prefer blocks with largest amount of free space.
+                for(size_t blockIndex = m_Blocks.size(); blockIndex--; )
+                {
+                    VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks[blockIndex];
+                    VMA_ASSERT(pCurrBlock);
+                    VkResult res = AllocateFromBlock(
+                        pCurrBlock,
+                        currentFrameIndex,
+                        size,
+                        alignment,
+                        allocFlagsCopy,
+                        createInfo.pUserData,
+                        suballocType,
+                        strategy,
+                        pAllocation);
+                    if(res == VK_SUCCESS)
+                    {
+                        VMA_DEBUG_LOG("    Returned from existing block #%u", pCurrBlock->GetId());
+                        return VK_SUCCESS;
+                    }
+                }
+            }
+        }
+
+        // 2. Try to create new block.
+        if(canCreateNewBlock)
+        {
+            // Calculate optimal size for new block.
+            VkDeviceSize newBlockSize = m_PreferredBlockSize;
+            uint32_t newBlockSizeShift = 0;
+            const uint32_t NEW_BLOCK_SIZE_SHIFT_MAX = 3;
+
+            if(!m_ExplicitBlockSize)
+            {
+                // Allocate 1/8, 1/4, 1/2 as first blocks.
+                const VkDeviceSize maxExistingBlockSize = CalcMaxBlockSize();
+                for(uint32_t i = 0; i < NEW_BLOCK_SIZE_SHIFT_MAX; ++i)
+                {
+                    const VkDeviceSize smallerNewBlockSize = newBlockSize / 2;
+                    if(smallerNewBlockSize > maxExistingBlockSize && smallerNewBlockSize >= size * 2)
+                    {
+                        newBlockSize = smallerNewBlockSize;
+                        ++newBlockSizeShift;
+                    }
+                    else
+                    {
+                        break;
+                    }
+                }
+            }
+
+            size_t newBlockIndex = 0;
+            VkResult res = (newBlockSize <= freeMemory || !canFallbackToDedicated) ?
+                CreateBlock(newBlockSize, &newBlockIndex) : VK_ERROR_OUT_OF_DEVICE_MEMORY;
+            // Allocation of this size failed? Try 1/2, 1/4, 1/8 of m_PreferredBlockSize.
+            if(!m_ExplicitBlockSize)
+            {
+                while(res < 0 && newBlockSizeShift < NEW_BLOCK_SIZE_SHIFT_MAX)
+                {
+                    const VkDeviceSize smallerNewBlockSize = newBlockSize / 2;
+                    if(smallerNewBlockSize >= size)
+                    {
+                        newBlockSize = smallerNewBlockSize;
+                        ++newBlockSizeShift;
+                        res = (newBlockSize <= freeMemory || !canFallbackToDedicated) ?
+                            CreateBlock(newBlockSize, &newBlockIndex) : VK_ERROR_OUT_OF_DEVICE_MEMORY;
+                    }
+                    else
+                    {
+                        break;
+                    }
+                }
+            }
+
+            if(res == VK_SUCCESS)
+            {
+                VmaDeviceMemoryBlock* const pBlock = m_Blocks[newBlockIndex];
+                VMA_ASSERT(pBlock->m_pMetadata->GetSize() >= size);
+
+                res = AllocateFromBlock(
+                    pBlock,
+                    currentFrameIndex,
+                    size,
+                    alignment,
+                    allocFlagsCopy,
+                    createInfo.pUserData,
+                    suballocType,
+                    strategy,
+                    pAllocation);
+                if(res == VK_SUCCESS)
+                {
+                    VMA_DEBUG_LOG("    Created new block #%u Size=%llu", pBlock->GetId(), newBlockSize);
+                    return VK_SUCCESS;
+                }
+                else
+                {
+                    // Allocation from new block failed, possibly due to VMA_DEBUG_MARGIN or alignment.
+                    return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+                }
+            }
+        }
+    }
+
+    // 3. Try to allocate from existing blocks with making other allocations lost.
+    if(canMakeOtherLost)
+    {
+        uint32_t tryIndex = 0;
+        for(; tryIndex < VMA_ALLOCATION_TRY_COUNT; ++tryIndex)
+        {
+            VmaDeviceMemoryBlock* pBestRequestBlock = VMA_NULL;
+            VmaAllocationRequest bestRequest = {};
+            VkDeviceSize bestRequestCost = VK_WHOLE_SIZE;
+
+            // 1. Search existing allocations.
+            if(strategy == VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT)
+            {
+                // Forward order in m_Blocks - prefer blocks with smallest amount of free space.
+                for(size_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex )
+                {
+                    VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks[blockIndex];
+                    VMA_ASSERT(pCurrBlock);
+                    VmaAllocationRequest currRequest = {};
+                    if(pCurrBlock->m_pMetadata->CreateAllocationRequest(
+                        currentFrameIndex,
+                        m_FrameInUseCount,
+                        m_BufferImageGranularity,
+                        size,
+                        alignment,
+                        (createInfo.flags & VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT) != 0,
+                        suballocType,
+                        canMakeOtherLost,
+                        strategy,
+                        &currRequest))
+                    {
+                        const VkDeviceSize currRequestCost = currRequest.CalcCost();
+                        if(pBestRequestBlock == VMA_NULL ||
+                            currRequestCost < bestRequestCost)
+                        {
+                            pBestRequestBlock = pCurrBlock;
+                            bestRequest = currRequest;
+                            bestRequestCost = currRequestCost;
+
+                            if(bestRequestCost == 0)
+                            {
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+            else // WORST_FIT, FIRST_FIT
+            {
+                // Backward order in m_Blocks - prefer blocks with largest amount of free space.
+                for(size_t blockIndex = m_Blocks.size(); blockIndex--; )
+                {
+                    VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks[blockIndex];
+                    VMA_ASSERT(pCurrBlock);
+                    VmaAllocationRequest currRequest = {};
+                    if(pCurrBlock->m_pMetadata->CreateAllocationRequest(
+                        currentFrameIndex,
+                        m_FrameInUseCount,
+                        m_BufferImageGranularity,
+                        size,
+                        alignment,
+                        (createInfo.flags & VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT) != 0,
+                        suballocType,
+                        canMakeOtherLost,
+                        strategy,
+                        &currRequest))
+                    {
+                        const VkDeviceSize currRequestCost = currRequest.CalcCost();
+                        if(pBestRequestBlock == VMA_NULL ||
+                            currRequestCost < bestRequestCost ||
+                            strategy == VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT)
+                        {
+                            pBestRequestBlock = pCurrBlock;
+                            bestRequest = currRequest;
+                            bestRequestCost = currRequestCost;
+
+                            if(bestRequestCost == 0 ||
+                                strategy == VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT)
+                            {
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+
+            if(pBestRequestBlock != VMA_NULL)
+            {
+                if(mapped)
+                {
+                    VkResult res = pBestRequestBlock->Map(m_hAllocator, 1, VMA_NULL);
+                    if(res != VK_SUCCESS)
+                    {
+                        return res;
+                    }
+                }
+
+                if(pBestRequestBlock->m_pMetadata->MakeRequestedAllocationsLost(
+                    currentFrameIndex,
+                    m_FrameInUseCount,
+                    &bestRequest))
+                {
+                    // Allocate from this pBlock.
+                    *pAllocation = m_hAllocator->m_AllocationObjectAllocator.Allocate(currentFrameIndex, isUserDataString);
+                    pBestRequestBlock->m_pMetadata->Alloc(bestRequest, suballocType, size, *pAllocation);
+                    UpdateHasEmptyBlock();
+                    (*pAllocation)->InitBlockAllocation(
+                        pBestRequestBlock,
+                        bestRequest.offset,
+                        alignment,
+                        size,
+                        m_MemoryTypeIndex,
+                        suballocType,
+                        mapped,
+                        (createInfo.flags & VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT) != 0);
+                    VMA_HEAVY_ASSERT(pBestRequestBlock->Validate());
+                    VMA_DEBUG_LOG("    Returned from existing block");
+                    (*pAllocation)->SetUserData(m_hAllocator, createInfo.pUserData);
+                    m_hAllocator->m_Budget.AddAllocation(m_hAllocator->MemoryTypeIndexToHeapIndex(m_MemoryTypeIndex), size);
+                    if(VMA_DEBUG_INITIALIZE_ALLOCATIONS)
+                    {
+                        m_hAllocator->FillAllocation(*pAllocation, VMA_ALLOCATION_FILL_PATTERN_CREATED);
+                    }
+                    if(IsCorruptionDetectionEnabled())
+                    {
+                        VkResult res = pBestRequestBlock->WriteMagicValueAroundAllocation(m_hAllocator, bestRequest.offset, size);
+                        VMA_ASSERT(res == VK_SUCCESS && "Couldn't map block memory to write magic value.");
+                    }
+                    return VK_SUCCESS;
+                }
+                // else: Some allocations must have been touched while we are here. Next try.
+            }
+            else
+            {
+                // Could not find place in any of the blocks - break outer loop.
+                break;
+            }
+        }
+        /* Maximum number of tries exceeded - a very unlike event when many other
+        threads are simultaneously touching allocations making it impossible to make
+        lost at the same time as we try to allocate. */
+        if(tryIndex == VMA_ALLOCATION_TRY_COUNT)
+        {
+            return VK_ERROR_TOO_MANY_OBJECTS;
+        }
+    }
+
+    return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+}
+
+void VmaBlockVector::Free(
+    const VmaAllocation hAllocation)
+{
+    VmaDeviceMemoryBlock* pBlockToDelete = VMA_NULL;
+
+    bool budgetExceeded = false;
+    {
+        const uint32_t heapIndex = m_hAllocator->MemoryTypeIndexToHeapIndex(m_MemoryTypeIndex);
+        VmaBudget heapBudget = {};
+        m_hAllocator->GetBudget(&heapBudget, heapIndex, 1);
+        budgetExceeded = heapBudget.usage >= heapBudget.budget;
+    }
+
+    // Scope for lock.
+    {
+        VmaMutexLockWrite lock(m_Mutex, m_hAllocator->m_UseMutex);
+
+        VmaDeviceMemoryBlock* pBlock = hAllocation->GetBlock();
+
+        if(IsCorruptionDetectionEnabled())
+        {
+            VkResult res = pBlock->ValidateMagicValueAroundAllocation(m_hAllocator, hAllocation->GetOffset(), hAllocation->GetSize());
+            VMA_ASSERT(res == VK_SUCCESS && "Couldn't map block memory to validate magic value.");
+        }
+
+        if(hAllocation->IsPersistentMap())
+        {
+            pBlock->Unmap(m_hAllocator, 1);
+        }
+
+        pBlock->m_pMetadata->Free(hAllocation);
+        VMA_HEAVY_ASSERT(pBlock->Validate());
+
+        VMA_DEBUG_LOG("  Freed from MemoryTypeIndex=%u", m_MemoryTypeIndex);
+
+        const bool canDeleteBlock = m_Blocks.size() > m_MinBlockCount;
+        // pBlock became empty after this deallocation.
+        if(pBlock->m_pMetadata->IsEmpty())
+        {
+            // Already has empty block. We don't want to have two, so delete this one.
+            if((m_HasEmptyBlock || budgetExceeded) && canDeleteBlock)
+            {
+                pBlockToDelete = pBlock;
+                Remove(pBlock);
+            }
+            // else: We now have an empty block - leave it.
+        }
+        // pBlock didn't become empty, but we have another empty block - find and free that one.
+        // (This is optional, heuristics.)
+        else if(m_HasEmptyBlock && canDeleteBlock)
+        {
+            VmaDeviceMemoryBlock* pLastBlock = m_Blocks.back();
+            if(pLastBlock->m_pMetadata->IsEmpty())
+            {
+                pBlockToDelete = pLastBlock;
+                m_Blocks.pop_back();
+            }
+        }
+
+        UpdateHasEmptyBlock();
+        IncrementallySortBlocks();
+    }
+
+    // Destruction of a free block. Deferred until this point, outside of mutex
+    // lock, for performance reason.
+    if(pBlockToDelete != VMA_NULL)
+    {
+        VMA_DEBUG_LOG("    Deleted empty block");
+        pBlockToDelete->Destroy(m_hAllocator);
+        vma_delete(m_hAllocator, pBlockToDelete);
+    }
+}
+
+VkDeviceSize VmaBlockVector::CalcMaxBlockSize() const
+{
+    VkDeviceSize result = 0;
+    for(size_t i = m_Blocks.size(); i--; )
+    {
+        result = VMA_MAX(result, m_Blocks[i]->m_pMetadata->GetSize());
+        if(result >= m_PreferredBlockSize)
+        {
+            break;
+        }
+    }
+    return result;
+}
+
+void VmaBlockVector::Remove(VmaDeviceMemoryBlock* pBlock)
+{
+    for(uint32_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex)
+    {
+        if(m_Blocks[blockIndex] == pBlock)
+        {
+            VmaVectorRemove(m_Blocks, blockIndex);
+            return;
+        }
+    }
+    VMA_ASSERT(0);
+}
+
+void VmaBlockVector::IncrementallySortBlocks()
+{
+    if(m_Algorithm != VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT)
+    {
+        // Bubble sort only until first swap.
+        for(size_t i = 1; i < m_Blocks.size(); ++i)
+        {
+            if(m_Blocks[i - 1]->m_pMetadata->GetSumFreeSize() > m_Blocks[i]->m_pMetadata->GetSumFreeSize())
+            {
+                VMA_SWAP(m_Blocks[i - 1], m_Blocks[i]);
+                return;
+            }
+        }
+    }
+}
+
+VkResult VmaBlockVector::AllocateFromBlock(
+    VmaDeviceMemoryBlock* pBlock,
+    uint32_t currentFrameIndex,
+    VkDeviceSize size,
+    VkDeviceSize alignment,
+    VmaAllocationCreateFlags allocFlags,
+    void* pUserData,
+    VmaSuballocationType suballocType,
+    uint32_t strategy,
+    VmaAllocation* pAllocation)
+{
+    VMA_ASSERT((allocFlags & VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT) == 0);
+    const bool isUpperAddress = (allocFlags & VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT) != 0;
+    const bool mapped = (allocFlags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0;
+    const bool isUserDataString = (allocFlags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0;
+
+    VmaAllocationRequest currRequest = {};
+    if(pBlock->m_pMetadata->CreateAllocationRequest(
+        currentFrameIndex,
+        m_FrameInUseCount,
+        m_BufferImageGranularity,
+        size,
+        alignment,
+        isUpperAddress,
+        suballocType,
+        false, // canMakeOtherLost
+        strategy,
+        &currRequest))
+    {
+        // Allocate from pCurrBlock.
+        VMA_ASSERT(currRequest.itemsToMakeLostCount == 0);
+
+        if(mapped)
+        {
+            VkResult res = pBlock->Map(m_hAllocator, 1, VMA_NULL);
+            if(res != VK_SUCCESS)
+            {
+                return res;
+            }
+        }
+            
+        *pAllocation = m_hAllocator->m_AllocationObjectAllocator.Allocate(currentFrameIndex, isUserDataString);
+        pBlock->m_pMetadata->Alloc(currRequest, suballocType, size, *pAllocation);
+        UpdateHasEmptyBlock();
+        (*pAllocation)->InitBlockAllocation(
+            pBlock,
+            currRequest.offset,
+            alignment,
+            size,
+            m_MemoryTypeIndex,
+            suballocType,
+            mapped,
+            (allocFlags & VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT) != 0);
+        VMA_HEAVY_ASSERT(pBlock->Validate());
+        (*pAllocation)->SetUserData(m_hAllocator, pUserData);
+        m_hAllocator->m_Budget.AddAllocation(m_hAllocator->MemoryTypeIndexToHeapIndex(m_MemoryTypeIndex), size);
+        if(VMA_DEBUG_INITIALIZE_ALLOCATIONS)
+        {
+            m_hAllocator->FillAllocation(*pAllocation, VMA_ALLOCATION_FILL_PATTERN_CREATED);
+        }
+        if(IsCorruptionDetectionEnabled())
+        {
+            VkResult res = pBlock->WriteMagicValueAroundAllocation(m_hAllocator, currRequest.offset, size);
+            VMA_ASSERT(res == VK_SUCCESS && "Couldn't map block memory to write magic value.");
+        }
+        return VK_SUCCESS;
+    }
+    return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+}
+
+VkResult VmaBlockVector::CreateBlock(VkDeviceSize blockSize, size_t* pNewBlockIndex)
+{
+    VkMemoryAllocateInfo allocInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
+    allocInfo.memoryTypeIndex = m_MemoryTypeIndex;
+    allocInfo.allocationSize = blockSize;
+
+#if VMA_BUFFER_DEVICE_ADDRESS
+    // Every standalone block can potentially contain a buffer with VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT - always enable the feature.
+    VkMemoryAllocateFlagsInfoKHR allocFlagsInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO_KHR };
+    if(m_hAllocator->m_UseKhrBufferDeviceAddress)
+    {
+        allocFlagsInfo.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR;
+        VmaPnextChainPushFront(&allocInfo, &allocFlagsInfo);
+    }
+#endif // #if VMA_BUFFER_DEVICE_ADDRESS
+
+    VkDeviceMemory mem = VK_NULL_HANDLE;
+    VkResult res = m_hAllocator->AllocateVulkanMemory(&allocInfo, &mem);
+    if(res < 0)
+    {
+        return res;
+    }
+
+    // New VkDeviceMemory successfully created.
+
+    // Create new Allocation for it.
+    VmaDeviceMemoryBlock* const pBlock = vma_new(m_hAllocator, VmaDeviceMemoryBlock)(m_hAllocator);
+    pBlock->Init(
+        m_hAllocator,
+        m_hParentPool,
+        m_MemoryTypeIndex,
+        mem,
+        allocInfo.allocationSize,
+        m_NextBlockId++,
+        m_Algorithm);
+
+    m_Blocks.push_back(pBlock);
+    if(pNewBlockIndex != VMA_NULL)
+    {
+        *pNewBlockIndex = m_Blocks.size() - 1;
+    }
+
+    return VK_SUCCESS;
+}
+
+void VmaBlockVector::ApplyDefragmentationMovesCpu(
+    class VmaBlockVectorDefragmentationContext* pDefragCtx,
+    const VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves)
+{
+    const size_t blockCount = m_Blocks.size();
+    const bool isNonCoherent = m_hAllocator->IsMemoryTypeNonCoherent(m_MemoryTypeIndex);
+
+    enum BLOCK_FLAG
+    {
+        BLOCK_FLAG_USED = 0x00000001,
+        BLOCK_FLAG_MAPPED_FOR_DEFRAGMENTATION = 0x00000002,
+    };
+
+    struct BlockInfo
+    {
+        uint32_t flags;
+        void* pMappedData;
+    };
+    VmaVector< BlockInfo, VmaStlAllocator<BlockInfo> >
+        blockInfo(blockCount, BlockInfo(), VmaStlAllocator<BlockInfo>(m_hAllocator->GetAllocationCallbacks()));
+    memset(blockInfo.data(), 0, blockCount * sizeof(BlockInfo));
+
+    // Go over all moves. Mark blocks that are used with BLOCK_FLAG_USED.
+    const size_t moveCount = moves.size();
+    for(size_t moveIndex = 0; moveIndex < moveCount; ++moveIndex)
+    {
+        const VmaDefragmentationMove& move = moves[moveIndex];
+        blockInfo[move.srcBlockIndex].flags |= BLOCK_FLAG_USED;
+        blockInfo[move.dstBlockIndex].flags |= BLOCK_FLAG_USED;
+    }
+
+    VMA_ASSERT(pDefragCtx->res == VK_SUCCESS);
+
+    // Go over all blocks. Get mapped pointer or map if necessary.
+    for(size_t blockIndex = 0; pDefragCtx->res == VK_SUCCESS && blockIndex < blockCount; ++blockIndex)
+    {
+        BlockInfo& currBlockInfo = blockInfo[blockIndex];
+        VmaDeviceMemoryBlock* pBlock = m_Blocks[blockIndex];
+        if((currBlockInfo.flags & BLOCK_FLAG_USED) != 0)
+        {
+            currBlockInfo.pMappedData = pBlock->GetMappedData();
+            // It is not originally mapped - map it.
+            if(currBlockInfo.pMappedData == VMA_NULL)
+            {
+                pDefragCtx->res = pBlock->Map(m_hAllocator, 1, &currBlockInfo.pMappedData);
+                if(pDefragCtx->res == VK_SUCCESS)
+                {
+                    currBlockInfo.flags |= BLOCK_FLAG_MAPPED_FOR_DEFRAGMENTATION;
+                }
+            }
+        }
+    }
+
+    // Go over all moves. Do actual data transfer.
+    if(pDefragCtx->res == VK_SUCCESS)
+    {
+        const VkDeviceSize nonCoherentAtomSize = m_hAllocator->m_PhysicalDeviceProperties.limits.nonCoherentAtomSize;
+        VkMappedMemoryRange memRange = { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE };
+
+        for(size_t moveIndex = 0; moveIndex < moveCount; ++moveIndex)
+        {
+            const VmaDefragmentationMove& move = moves[moveIndex];
+
+            const BlockInfo& srcBlockInfo = blockInfo[move.srcBlockIndex];
+            const BlockInfo& dstBlockInfo = blockInfo[move.dstBlockIndex];
+
+            VMA_ASSERT(srcBlockInfo.pMappedData && dstBlockInfo.pMappedData);
+
+            // Invalidate source.
+            if(isNonCoherent)
+            {
+                VmaDeviceMemoryBlock* const pSrcBlock = m_Blocks[move.srcBlockIndex];
+                memRange.memory = pSrcBlock->GetDeviceMemory();
+                memRange.offset = VmaAlignDown(move.srcOffset, nonCoherentAtomSize);
+                memRange.size = VMA_MIN(
+                    VmaAlignUp(move.size + (move.srcOffset - memRange.offset), nonCoherentAtomSize),
+                    pSrcBlock->m_pMetadata->GetSize() - memRange.offset);
+                (*m_hAllocator->GetVulkanFunctions().vkInvalidateMappedMemoryRanges)(m_hAllocator->m_hDevice, 1, &memRange);
+            }
+
+            // THE PLACE WHERE ACTUAL DATA COPY HAPPENS.
+            memmove(
+                reinterpret_cast<char*>(dstBlockInfo.pMappedData) + move.dstOffset,
+                reinterpret_cast<char*>(srcBlockInfo.pMappedData) + move.srcOffset,
+                static_cast<size_t>(move.size));
+
+            if(IsCorruptionDetectionEnabled())
+            {
+                VmaWriteMagicValue(dstBlockInfo.pMappedData, move.dstOffset - VMA_DEBUG_MARGIN);
+                VmaWriteMagicValue(dstBlockInfo.pMappedData, move.dstOffset + move.size);
+            }
+
+            // Flush destination.
+            if(isNonCoherent)
+            {
+                VmaDeviceMemoryBlock* const pDstBlock = m_Blocks[move.dstBlockIndex];
+                memRange.memory = pDstBlock->GetDeviceMemory();
+                memRange.offset = VmaAlignDown(move.dstOffset, nonCoherentAtomSize);
+                memRange.size = VMA_MIN(
+                    VmaAlignUp(move.size + (move.dstOffset - memRange.offset), nonCoherentAtomSize),
+                    pDstBlock->m_pMetadata->GetSize() - memRange.offset);
+                (*m_hAllocator->GetVulkanFunctions().vkFlushMappedMemoryRanges)(m_hAllocator->m_hDevice, 1, &memRange);
+            }
+        }
+    }
+
+    // Go over all blocks in reverse order. Unmap those that were mapped just for defragmentation.
+    // Regardless of pCtx->res == VK_SUCCESS.
+    for(size_t blockIndex = blockCount; blockIndex--; )
+    {
+        const BlockInfo& currBlockInfo = blockInfo[blockIndex];
+        if((currBlockInfo.flags & BLOCK_FLAG_MAPPED_FOR_DEFRAGMENTATION) != 0)
+        {
+            VmaDeviceMemoryBlock* pBlock = m_Blocks[blockIndex];
+            pBlock->Unmap(m_hAllocator, 1);
+        }
+    }
+}
+
+void VmaBlockVector::ApplyDefragmentationMovesGpu(
+    class VmaBlockVectorDefragmentationContext* pDefragCtx,
+    VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves,
+    VkCommandBuffer commandBuffer)
+{
+    const size_t blockCount = m_Blocks.size();
+
+    pDefragCtx->blockContexts.resize(blockCount);
+    memset(pDefragCtx->blockContexts.data(), 0, blockCount * sizeof(VmaBlockDefragmentationContext));
+
+    // Go over all moves. Mark blocks that are used with BLOCK_FLAG_USED.
+    const size_t moveCount = moves.size();
+    for(size_t moveIndex = 0; moveIndex < moveCount; ++moveIndex)
+    {
+        const VmaDefragmentationMove& move = moves[moveIndex];
+
+        //if(move.type == VMA_ALLOCATION_TYPE_UNKNOWN)
+        {
+            // Old school move still require us to map the whole block
+            pDefragCtx->blockContexts[move.srcBlockIndex].flags |= VmaBlockDefragmentationContext::BLOCK_FLAG_USED;
+            pDefragCtx->blockContexts[move.dstBlockIndex].flags |= VmaBlockDefragmentationContext::BLOCK_FLAG_USED;
+        }
+    }
+
+    VMA_ASSERT(pDefragCtx->res == VK_SUCCESS);
+
+    // Go over all blocks. Create and bind buffer for whole block if necessary.
+    {
+        VkBufferCreateInfo bufCreateInfo;
+        VmaFillGpuDefragmentationBufferCreateInfo(bufCreateInfo);
+
+        for(size_t blockIndex = 0; pDefragCtx->res == VK_SUCCESS && blockIndex < blockCount; ++blockIndex)
+        {
+            VmaBlockDefragmentationContext& currBlockCtx = pDefragCtx->blockContexts[blockIndex];
+            VmaDeviceMemoryBlock* pBlock = m_Blocks[blockIndex];
+            if((currBlockCtx.flags & VmaBlockDefragmentationContext::BLOCK_FLAG_USED) != 0)
+            {
+                bufCreateInfo.size = pBlock->m_pMetadata->GetSize();
+                pDefragCtx->res = (*m_hAllocator->GetVulkanFunctions().vkCreateBuffer)(
+                    m_hAllocator->m_hDevice, &bufCreateInfo, m_hAllocator->GetAllocationCallbacks(), &currBlockCtx.hBuffer);
+                if(pDefragCtx->res == VK_SUCCESS)
+                {
+                    pDefragCtx->res = (*m_hAllocator->GetVulkanFunctions().vkBindBufferMemory)(
+                        m_hAllocator->m_hDevice, currBlockCtx.hBuffer, pBlock->GetDeviceMemory(), 0);
+                }
+            }
+        }
+    }
+
+    // Go over all moves. Post data transfer commands to command buffer.
+    if(pDefragCtx->res == VK_SUCCESS)
+    {
+        for(size_t moveIndex = 0; moveIndex < moveCount; ++moveIndex)
+        {
+            const VmaDefragmentationMove& move = moves[moveIndex];
+
+            const VmaBlockDefragmentationContext& srcBlockCtx = pDefragCtx->blockContexts[move.srcBlockIndex];
+            const VmaBlockDefragmentationContext& dstBlockCtx = pDefragCtx->blockContexts[move.dstBlockIndex];
+
+            VMA_ASSERT(srcBlockCtx.hBuffer && dstBlockCtx.hBuffer);
+
+            VkBufferCopy region = {
+                move.srcOffset,
+                move.dstOffset,
+                move.size };
+            (*m_hAllocator->GetVulkanFunctions().vkCmdCopyBuffer)(
+                commandBuffer, srcBlockCtx.hBuffer, dstBlockCtx.hBuffer, 1, &region);
+        }
+    }
+
+    // Save buffers to defrag context for later destruction.
+    if(pDefragCtx->res == VK_SUCCESS && moveCount > 0)
+    {
+        pDefragCtx->res = VK_NOT_READY;
+    }
+}
+
+void VmaBlockVector::FreeEmptyBlocks(VmaDefragmentationStats* pDefragmentationStats)
+{
+    for(size_t blockIndex = m_Blocks.size(); blockIndex--; )
+    {
+        VmaDeviceMemoryBlock* pBlock = m_Blocks[blockIndex];
+        if(pBlock->m_pMetadata->IsEmpty())
+        {
+            if(m_Blocks.size() > m_MinBlockCount)
+            {
+                if(pDefragmentationStats != VMA_NULL)
+                {
+                    ++pDefragmentationStats->deviceMemoryBlocksFreed;
+                    pDefragmentationStats->bytesFreed += pBlock->m_pMetadata->GetSize();
+                }
+
+                VmaVectorRemove(m_Blocks, blockIndex);
+                pBlock->Destroy(m_hAllocator);
+                vma_delete(m_hAllocator, pBlock);
+            }
+            else
+            {
+                break;
+            }
+        }
+    }
+    UpdateHasEmptyBlock();
+}
+
+void VmaBlockVector::UpdateHasEmptyBlock()
+{
+    m_HasEmptyBlock = false;
+    for(size_t index = 0, count = m_Blocks.size(); index < count; ++index)
+    {
+        VmaDeviceMemoryBlock* const pBlock = m_Blocks[index];
+        if(pBlock->m_pMetadata->IsEmpty())
+        {
+            m_HasEmptyBlock = true;
+            break;
+        }
+    }
+}
+
+#if VMA_STATS_STRING_ENABLED
+
+void VmaBlockVector::PrintDetailedMap(class VmaJsonWriter& json)
+{
+    VmaMutexLockRead lock(m_Mutex, m_hAllocator->m_UseMutex);
+
+    json.BeginObject();
+
+    if(IsCustomPool())
+    {
+        const char* poolName = m_hParentPool->GetName();
+        if(poolName != VMA_NULL && poolName[0] != '\0')
+        {
+            json.WriteString("Name");
+            json.WriteString(poolName);
+        }
+
+        json.WriteString("MemoryTypeIndex");
+        json.WriteNumber(m_MemoryTypeIndex);
+
+        json.WriteString("BlockSize");
+        json.WriteNumber(m_PreferredBlockSize);
+
+        json.WriteString("BlockCount");
+        json.BeginObject(true);
+        if(m_MinBlockCount > 0)
+        {
+            json.WriteString("Min");
+            json.WriteNumber((uint64_t)m_MinBlockCount);
+        }
+        if(m_MaxBlockCount < SIZE_MAX)
+        {
+            json.WriteString("Max");
+            json.WriteNumber((uint64_t)m_MaxBlockCount);
+        }
+        json.WriteString("Cur");
+        json.WriteNumber((uint64_t)m_Blocks.size());
+        json.EndObject();
+
+        if(m_FrameInUseCount > 0)
+        {
+            json.WriteString("FrameInUseCount");
+            json.WriteNumber(m_FrameInUseCount);
+        }
+
+        if(m_Algorithm != 0)
+        {
+            json.WriteString("Algorithm");
+            json.WriteString(VmaAlgorithmToStr(m_Algorithm));
+        }
+    }
+    else
+    {
+        json.WriteString("PreferredBlockSize");
+        json.WriteNumber(m_PreferredBlockSize);
+    }
+
+    json.WriteString("Blocks");
+    json.BeginObject();
+    for(size_t i = 0; i < m_Blocks.size(); ++i)
+    {
+        json.BeginString();
+        json.ContinueString(m_Blocks[i]->GetId());
+        json.EndString();
+
+        m_Blocks[i]->m_pMetadata->PrintDetailedMap(json);
+    }
+    json.EndObject();
+
+    json.EndObject();
+}
+
+#endif // #if VMA_STATS_STRING_ENABLED
+
+void VmaBlockVector::Defragment(
+    class VmaBlockVectorDefragmentationContext* pCtx,
+    VmaDefragmentationStats* pStats, VmaDefragmentationFlags flags,
+    VkDeviceSize& maxCpuBytesToMove, uint32_t& maxCpuAllocationsToMove,
+    VkDeviceSize& maxGpuBytesToMove, uint32_t& maxGpuAllocationsToMove,
+    VkCommandBuffer commandBuffer)
+{
+    pCtx->res = VK_SUCCESS;
+    
+    const VkMemoryPropertyFlags memPropFlags =
+        m_hAllocator->m_MemProps.memoryTypes[m_MemoryTypeIndex].propertyFlags;
+    const bool isHostVisible = (memPropFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0;
+
+    const bool canDefragmentOnCpu = maxCpuBytesToMove > 0 && maxCpuAllocationsToMove > 0 &&
+        isHostVisible;
+    const bool canDefragmentOnGpu = maxGpuBytesToMove > 0 && maxGpuAllocationsToMove > 0 &&
+        !IsCorruptionDetectionEnabled() &&
+        ((1u << m_MemoryTypeIndex) & m_hAllocator->GetGpuDefragmentationMemoryTypeBits()) != 0;
+
+    // There are options to defragment this memory type.
+    if(canDefragmentOnCpu || canDefragmentOnGpu)
+    {
+        bool defragmentOnGpu;
+        // There is only one option to defragment this memory type.
+        if(canDefragmentOnGpu != canDefragmentOnCpu)
+        {
+            defragmentOnGpu = canDefragmentOnGpu;
+        }
+        // Both options are available: Heuristics to choose the best one.
+        else
+        {
+            defragmentOnGpu = (memPropFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) != 0 ||
+                m_hAllocator->IsIntegratedGpu();
+        }
+
+        bool overlappingMoveSupported = !defragmentOnGpu;
+
+        if(m_hAllocator->m_UseMutex)
+        {
+            if(flags & VMA_DEFRAGMENTATION_FLAG_INCREMENTAL)
+            {
+                if(!m_Mutex.TryLockWrite())
+                {
+                    pCtx->res = VK_ERROR_INITIALIZATION_FAILED;
+                    return;
+                }
+            }
+            else
+            {
+                m_Mutex.LockWrite();
+                pCtx->mutexLocked = true;
+            }
+        }
+
+        pCtx->Begin(overlappingMoveSupported, flags);
+
+        // Defragment.
+
+        const VkDeviceSize maxBytesToMove = defragmentOnGpu ? maxGpuBytesToMove : maxCpuBytesToMove;
+        const uint32_t maxAllocationsToMove = defragmentOnGpu ? maxGpuAllocationsToMove : maxCpuAllocationsToMove;
+        pCtx->res = pCtx->GetAlgorithm()->Defragment(pCtx->defragmentationMoves, maxBytesToMove, maxAllocationsToMove, flags);
+
+        // Accumulate statistics.
+        if(pStats != VMA_NULL)
+        {
+            const VkDeviceSize bytesMoved = pCtx->GetAlgorithm()->GetBytesMoved();
+            const uint32_t allocationsMoved = pCtx->GetAlgorithm()->GetAllocationsMoved();
+            pStats->bytesMoved += bytesMoved;
+            pStats->allocationsMoved += allocationsMoved;
+            VMA_ASSERT(bytesMoved <= maxBytesToMove);
+            VMA_ASSERT(allocationsMoved <= maxAllocationsToMove);
+            if(defragmentOnGpu)
+            {
+                maxGpuBytesToMove -= bytesMoved;
+                maxGpuAllocationsToMove -= allocationsMoved;
+            }
+            else
+            {
+                maxCpuBytesToMove -= bytesMoved;
+                maxCpuAllocationsToMove -= allocationsMoved;
+            }
+        }
+
+        if(flags & VMA_DEFRAGMENTATION_FLAG_INCREMENTAL)
+        {
+            if(m_hAllocator->m_UseMutex)
+                m_Mutex.UnlockWrite();
+            
+            if(pCtx->res >= VK_SUCCESS && !pCtx->defragmentationMoves.empty())
+                pCtx->res = VK_NOT_READY;
+
+            return;
+        }
+    
+        if(pCtx->res >= VK_SUCCESS)
+        {
+            if(defragmentOnGpu)
+            {
+                ApplyDefragmentationMovesGpu(pCtx, pCtx->defragmentationMoves, commandBuffer);
+            }
+            else
+            {
+                ApplyDefragmentationMovesCpu(pCtx, pCtx->defragmentationMoves);
+            }
+        }
+    }
+}
+
+void VmaBlockVector::DefragmentationEnd(
+    class VmaBlockVectorDefragmentationContext* pCtx,
+    uint32_t flags,
+    VmaDefragmentationStats* pStats)
+{
+    if(flags & VMA_DEFRAGMENTATION_FLAG_INCREMENTAL && m_hAllocator->m_UseMutex)
+    {
+        VMA_ASSERT(pCtx->mutexLocked == false);
+
+        // Incremental defragmentation doesn't hold the lock, so when we enter here we don't actually have any
+        // lock protecting us. Since we mutate state here, we have to take the lock out now
+        m_Mutex.LockWrite();
+        pCtx->mutexLocked = true;
+    }
+
+    // If the mutex isn't locked we didn't do any work and there is nothing to delete.
+    if(pCtx->mutexLocked || !m_hAllocator->m_UseMutex)
+    {
+        // Destroy buffers.
+        for(size_t blockIndex = pCtx->blockContexts.size(); blockIndex--;)
+        {
+            VmaBlockDefragmentationContext &blockCtx = pCtx->blockContexts[blockIndex];
+            if(blockCtx.hBuffer)
+            {
+                (*m_hAllocator->GetVulkanFunctions().vkDestroyBuffer)(m_hAllocator->m_hDevice, blockCtx.hBuffer, m_hAllocator->GetAllocationCallbacks());
+            }
+        }
+
+        if(pCtx->res >= VK_SUCCESS)
+        {
+            FreeEmptyBlocks(pStats);
+        }
+    }
+
+    if(pCtx->mutexLocked)
+    {
+        VMA_ASSERT(m_hAllocator->m_UseMutex);
+        m_Mutex.UnlockWrite();
+    }
+}
+
+uint32_t VmaBlockVector::ProcessDefragmentations(
+    class VmaBlockVectorDefragmentationContext *pCtx,
+    VmaDefragmentationPassMoveInfo* pMove, uint32_t maxMoves)
+{
+    VmaMutexLockWrite lock(m_Mutex, m_hAllocator->m_UseMutex);
+    
+    const uint32_t moveCount = std::min(uint32_t(pCtx->defragmentationMoves.size()) - pCtx->defragmentationMovesProcessed, maxMoves);
+
+    for(uint32_t i = 0; i < moveCount; ++ i)
+    {
+        VmaDefragmentationMove& move = pCtx->defragmentationMoves[pCtx->defragmentationMovesProcessed + i];
+
+        pMove->allocation = move.hAllocation;
+        pMove->memory = move.pDstBlock->GetDeviceMemory();
+        pMove->offset = move.dstOffset;
+
+        ++ pMove;
+    }
+
+    pCtx->defragmentationMovesProcessed += moveCount;
+
+    return moveCount;
+}
+
+void VmaBlockVector::CommitDefragmentations(
+    class VmaBlockVectorDefragmentationContext *pCtx,
+    VmaDefragmentationStats* pStats)
+{
+    VmaMutexLockWrite lock(m_Mutex, m_hAllocator->m_UseMutex);
+    
+    for(uint32_t i = pCtx->defragmentationMovesCommitted; i < pCtx->defragmentationMovesProcessed; ++ i)
+    {
+        const VmaDefragmentationMove &move = pCtx->defragmentationMoves[i];
+
+        move.pSrcBlock->m_pMetadata->FreeAtOffset(move.srcOffset);
+        move.hAllocation->ChangeBlockAllocation(m_hAllocator, move.pDstBlock, move.dstOffset);
+    }
+
+    pCtx->defragmentationMovesCommitted = pCtx->defragmentationMovesProcessed;
+    FreeEmptyBlocks(pStats);
+}
+
+size_t VmaBlockVector::CalcAllocationCount() const
+{
+    size_t result = 0;
+    for(size_t i = 0; i < m_Blocks.size(); ++i)
+    {
+        result += m_Blocks[i]->m_pMetadata->GetAllocationCount();
+    }
+    return result;
+}
+
+bool VmaBlockVector::IsBufferImageGranularityConflictPossible() const
+{
+    if(m_BufferImageGranularity == 1)
+    {
+        return false;
+    }
+    VmaSuballocationType lastSuballocType = VMA_SUBALLOCATION_TYPE_FREE;
+    for(size_t i = 0, count = m_Blocks.size(); i < count; ++i)
+    {
+        VmaDeviceMemoryBlock* const pBlock = m_Blocks[i];
+        VMA_ASSERT(m_Algorithm == 0);
+        VmaBlockMetadata_Generic* const pMetadata = (VmaBlockMetadata_Generic*)pBlock->m_pMetadata;
+        if(pMetadata->IsBufferImageGranularityConflictPossible(m_BufferImageGranularity, lastSuballocType))
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
+void VmaBlockVector::MakePoolAllocationsLost(
+    uint32_t currentFrameIndex,
+    size_t* pLostAllocationCount)
+{
+    VmaMutexLockWrite lock(m_Mutex, m_hAllocator->m_UseMutex);
+    size_t lostAllocationCount = 0;
+    for(uint32_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex)
+    {
+        VmaDeviceMemoryBlock* const pBlock = m_Blocks[blockIndex];
+        VMA_ASSERT(pBlock);
+        lostAllocationCount += pBlock->m_pMetadata->MakeAllocationsLost(currentFrameIndex, m_FrameInUseCount);
+    }
+    if(pLostAllocationCount != VMA_NULL)
+    {
+        *pLostAllocationCount = lostAllocationCount;
+    }
+}
+
+VkResult VmaBlockVector::CheckCorruption()
+{
+    if(!IsCorruptionDetectionEnabled())
+    {
+        return VK_ERROR_FEATURE_NOT_PRESENT;
+    }
+
+    VmaMutexLockRead lock(m_Mutex, m_hAllocator->m_UseMutex);
+    for(uint32_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex)
+    {
+        VmaDeviceMemoryBlock* const pBlock = m_Blocks[blockIndex];
+        VMA_ASSERT(pBlock);
+        VkResult res = pBlock->CheckCorruption(m_hAllocator);
+        if(res != VK_SUCCESS)
+        {
+            return res;
+        }
+    }
+    return VK_SUCCESS;
+}
+
+void VmaBlockVector::AddStats(VmaStats* pStats)
+{
+    const uint32_t memTypeIndex = m_MemoryTypeIndex;
+    const uint32_t memHeapIndex = m_hAllocator->MemoryTypeIndexToHeapIndex(memTypeIndex);
+
+    VmaMutexLockRead lock(m_Mutex, m_hAllocator->m_UseMutex);
+
+    for(uint32_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex)
+    {
+        const VmaDeviceMemoryBlock* const pBlock = m_Blocks[blockIndex];
+        VMA_ASSERT(pBlock);
+        VMA_HEAVY_ASSERT(pBlock->Validate());
+        VmaStatInfo allocationStatInfo;
+        pBlock->m_pMetadata->CalcAllocationStatInfo(allocationStatInfo);
+        VmaAddStatInfo(pStats->total, allocationStatInfo);
+        VmaAddStatInfo(pStats->memoryType[memTypeIndex], allocationStatInfo);
+        VmaAddStatInfo(pStats->memoryHeap[memHeapIndex], allocationStatInfo);
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// VmaDefragmentationAlgorithm_Generic members definition
+
+VmaDefragmentationAlgorithm_Generic::VmaDefragmentationAlgorithm_Generic(
+    VmaAllocator hAllocator,
+    VmaBlockVector* pBlockVector,
+    uint32_t currentFrameIndex,
+    bool overlappingMoveSupported) :
+    VmaDefragmentationAlgorithm(hAllocator, pBlockVector, currentFrameIndex),
+    m_AllocationCount(0),
+    m_AllAllocations(false),
+    m_BytesMoved(0),
+    m_AllocationsMoved(0),
+    m_Blocks(VmaStlAllocator<BlockInfo*>(hAllocator->GetAllocationCallbacks()))
+{
+    // Create block info for each block.
+    const size_t blockCount = m_pBlockVector->m_Blocks.size();
+    for(size_t blockIndex = 0; blockIndex < blockCount; ++blockIndex)
+    {
+        BlockInfo* pBlockInfo = vma_new(m_hAllocator, BlockInfo)(m_hAllocator->GetAllocationCallbacks());
+        pBlockInfo->m_OriginalBlockIndex = blockIndex;
+        pBlockInfo->m_pBlock = m_pBlockVector->m_Blocks[blockIndex];
+        m_Blocks.push_back(pBlockInfo);
+    }
+
+    // Sort them by m_pBlock pointer value.
+    VMA_SORT(m_Blocks.begin(), m_Blocks.end(), BlockPointerLess());
+}
+
+VmaDefragmentationAlgorithm_Generic::~VmaDefragmentationAlgorithm_Generic()
+{
+    for(size_t i = m_Blocks.size(); i--; )
+    {
+        vma_delete(m_hAllocator, m_Blocks[i]);
+    }
+}
+
+void VmaDefragmentationAlgorithm_Generic::AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged)
+{
+    // Now as we are inside VmaBlockVector::m_Mutex, we can make final check if this allocation was not lost.
+    if(hAlloc->GetLastUseFrameIndex() != VMA_FRAME_INDEX_LOST)
+    {
+        VmaDeviceMemoryBlock* pBlock = hAlloc->GetBlock();
+        BlockInfoVector::iterator it = VmaBinaryFindFirstNotLess(m_Blocks.begin(), m_Blocks.end(), pBlock, BlockPointerLess());
+        if(it != m_Blocks.end() && (*it)->m_pBlock == pBlock)
+        {
+            AllocationInfo allocInfo = AllocationInfo(hAlloc, pChanged);
+            (*it)->m_Allocations.push_back(allocInfo);
+        }
+        else
+        {
+            VMA_ASSERT(0);
+        }
+
+        ++m_AllocationCount;
+    }
+}
+
+VkResult VmaDefragmentationAlgorithm_Generic::DefragmentRound(
+    VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves,
+    VkDeviceSize maxBytesToMove,
+    uint32_t maxAllocationsToMove,
+    bool freeOldAllocations)
+{
+    if(m_Blocks.empty())
+    {
+        return VK_SUCCESS;
+    }
+
+    // This is a choice based on research.
+    // Option 1:
+    uint32_t strategy = VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT;
+    // Option 2:
+    //uint32_t strategy = VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT;
+    // Option 3:
+    //uint32_t strategy = VMA_ALLOCATION_CREATE_STRATEGY_MIN_FRAGMENTATION_BIT;
+
+    size_t srcBlockMinIndex = 0;
+    // When FAST_ALGORITHM, move allocations from only last out of blocks that contain non-movable allocations.
+    /*
+    if(m_AlgorithmFlags & VMA_DEFRAGMENTATION_FAST_ALGORITHM_BIT)
+    {
+        const size_t blocksWithNonMovableCount = CalcBlocksWithNonMovableCount();
+        if(blocksWithNonMovableCount > 0)
+        {
+            srcBlockMinIndex = blocksWithNonMovableCount - 1;
+        }
+    }
+    */
+
+    size_t srcBlockIndex = m_Blocks.size() - 1;
+    size_t srcAllocIndex = SIZE_MAX;
+    for(;;)
+    {
+        // 1. Find next allocation to move.
+        // 1.1. Start from last to first m_Blocks - they are sorted from most "destination" to most "source".
+        // 1.2. Then start from last to first m_Allocations.
+        while(srcAllocIndex >= m_Blocks[srcBlockIndex]->m_Allocations.size())
+        {
+            if(m_Blocks[srcBlockIndex]->m_Allocations.empty())
+            {
+                // Finished: no more allocations to process.
+                if(srcBlockIndex == srcBlockMinIndex)
+                {
+                    return VK_SUCCESS;
+                }
+                else
+                {
+                    --srcBlockIndex;
+                    srcAllocIndex = SIZE_MAX;
+                }
+            }
+            else
+            {
+                srcAllocIndex = m_Blocks[srcBlockIndex]->m_Allocations.size() - 1;
+            }
+        }
+        
+        BlockInfo* pSrcBlockInfo = m_Blocks[srcBlockIndex];
+        AllocationInfo& allocInfo = pSrcBlockInfo->m_Allocations[srcAllocIndex];
+
+        const VkDeviceSize size = allocInfo.m_hAllocation->GetSize();
+        const VkDeviceSize srcOffset = allocInfo.m_hAllocation->GetOffset();
+        const VkDeviceSize alignment = allocInfo.m_hAllocation->GetAlignment();
+        const VmaSuballocationType suballocType = allocInfo.m_hAllocation->GetSuballocationType();
+
+        // 2. Try to find new place for this allocation in preceding or current block.
+        for(size_t dstBlockIndex = 0; dstBlockIndex <= srcBlockIndex; ++dstBlockIndex)
+        {
+            BlockInfo* pDstBlockInfo = m_Blocks[dstBlockIndex];
+            VmaAllocationRequest dstAllocRequest;
+            if(pDstBlockInfo->m_pBlock->m_pMetadata->CreateAllocationRequest(
+                m_CurrentFrameIndex,
+                m_pBlockVector->GetFrameInUseCount(),
+                m_pBlockVector->GetBufferImageGranularity(),
+                size,
+                alignment,
+                false, // upperAddress
+                suballocType,
+                false, // canMakeOtherLost
+                strategy,
+                &dstAllocRequest) &&
+            MoveMakesSense(
+                dstBlockIndex, dstAllocRequest.offset, srcBlockIndex, srcOffset))
+            {
+                VMA_ASSERT(dstAllocRequest.itemsToMakeLostCount == 0);
+
+                // Reached limit on number of allocations or bytes to move.
+                if((m_AllocationsMoved + 1 > maxAllocationsToMove) ||
+                    (m_BytesMoved + size > maxBytesToMove))
+                {
+                    return VK_SUCCESS;
+                }
+
+                VmaDefragmentationMove move = {};
+                move.srcBlockIndex = pSrcBlockInfo->m_OriginalBlockIndex;
+                move.dstBlockIndex = pDstBlockInfo->m_OriginalBlockIndex;
+                move.srcOffset = srcOffset;
+                move.dstOffset = dstAllocRequest.offset;
+                move.size = size;
+                move.hAllocation = allocInfo.m_hAllocation;
+                move.pSrcBlock = pSrcBlockInfo->m_pBlock;
+                move.pDstBlock = pDstBlockInfo->m_pBlock;
+
+                moves.push_back(move);
+
+                pDstBlockInfo->m_pBlock->m_pMetadata->Alloc(
+                    dstAllocRequest,
+                    suballocType,
+                    size,
+                    allocInfo.m_hAllocation);
+
+                if(freeOldAllocations)
+                {
+                    pSrcBlockInfo->m_pBlock->m_pMetadata->FreeAtOffset(srcOffset);
+                    allocInfo.m_hAllocation->ChangeBlockAllocation(m_hAllocator, pDstBlockInfo->m_pBlock, dstAllocRequest.offset);
+                }
+                
+                if(allocInfo.m_pChanged != VMA_NULL)
+                {
+                    *allocInfo.m_pChanged = VK_TRUE;
+                }
+
+                ++m_AllocationsMoved;
+                m_BytesMoved += size;
+
+                VmaVectorRemove(pSrcBlockInfo->m_Allocations, srcAllocIndex);
+
+                break;
+            }
+        }
+
+        // If not processed, this allocInfo remains in pBlockInfo->m_Allocations for next round.
+
+        if(srcAllocIndex > 0)
+        {
+            --srcAllocIndex;
+        }
+        else
+        {
+            if(srcBlockIndex > 0)
+            {
+                --srcBlockIndex;
+                srcAllocIndex = SIZE_MAX;
+            }
+            else
+            {
+                return VK_SUCCESS;
+            }
+        }
+    }
+}
+
+size_t VmaDefragmentationAlgorithm_Generic::CalcBlocksWithNonMovableCount() const
+{
+    size_t result = 0;
+    for(size_t i = 0; i < m_Blocks.size(); ++i)
+    {
+        if(m_Blocks[i]->m_HasNonMovableAllocations)
+        {
+            ++result;
+        }
+    }
+    return result;
+}
+
+VkResult VmaDefragmentationAlgorithm_Generic::Defragment(
+    VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves,
+    VkDeviceSize maxBytesToMove,
+    uint32_t maxAllocationsToMove,
+    VmaDefragmentationFlags flags)
+{
+    if(!m_AllAllocations && m_AllocationCount == 0)
+    {
+        return VK_SUCCESS;
+    }
+
+    const size_t blockCount = m_Blocks.size();
+    for(size_t blockIndex = 0; blockIndex < blockCount; ++blockIndex)
+    {
+        BlockInfo* pBlockInfo = m_Blocks[blockIndex];
+
+        if(m_AllAllocations)
+        {
+            VmaBlockMetadata_Generic* pMetadata = (VmaBlockMetadata_Generic*)pBlockInfo->m_pBlock->m_pMetadata;
+            for(VmaSuballocationList::const_iterator it = pMetadata->m_Suballocations.begin();
+                it != pMetadata->m_Suballocations.end();
+                ++it)
+            {
+                if(it->type != VMA_SUBALLOCATION_TYPE_FREE)
+                {
+                    AllocationInfo allocInfo = AllocationInfo(it->hAllocation, VMA_NULL);
+                    pBlockInfo->m_Allocations.push_back(allocInfo);
+                }
+            }
+        }
+
+        pBlockInfo->CalcHasNonMovableAllocations();
+        
+        // This is a choice based on research.
+        // Option 1:
+        pBlockInfo->SortAllocationsByOffsetDescending();
+        // Option 2:
+        //pBlockInfo->SortAllocationsBySizeDescending();
+    }
+
+    // Sort m_Blocks this time by the main criterium, from most "destination" to most "source" blocks.
+    VMA_SORT(m_Blocks.begin(), m_Blocks.end(), BlockInfoCompareMoveDestination());
+
+    // This is a choice based on research.
+    const uint32_t roundCount = 2;
+
+    // Execute defragmentation rounds (the main part).
+    VkResult result = VK_SUCCESS;
+    for(uint32_t round = 0; (round < roundCount) && (result == VK_SUCCESS); ++round)
+    {
+        result = DefragmentRound(moves, maxBytesToMove, maxAllocationsToMove, !(flags & VMA_DEFRAGMENTATION_FLAG_INCREMENTAL));
+    }
+
+    return result;
+}
+
+bool VmaDefragmentationAlgorithm_Generic::MoveMakesSense(
+        size_t dstBlockIndex, VkDeviceSize dstOffset,
+        size_t srcBlockIndex, VkDeviceSize srcOffset)
+{
+    if(dstBlockIndex < srcBlockIndex)
+    {
+        return true;
+    }
+    if(dstBlockIndex > srcBlockIndex)
+    {
+        return false;
+    }
+    if(dstOffset < srcOffset)
+    {
+        return true;
+    }
+    return false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// VmaDefragmentationAlgorithm_Fast
+
+VmaDefragmentationAlgorithm_Fast::VmaDefragmentationAlgorithm_Fast(
+    VmaAllocator hAllocator,
+    VmaBlockVector* pBlockVector,
+    uint32_t currentFrameIndex,
+    bool overlappingMoveSupported) :
+    VmaDefragmentationAlgorithm(hAllocator, pBlockVector, currentFrameIndex),
+    m_OverlappingMoveSupported(overlappingMoveSupported),
+    m_AllocationCount(0),
+    m_AllAllocations(false),
+    m_BytesMoved(0),
+    m_AllocationsMoved(0),
+    m_BlockInfos(VmaStlAllocator<BlockInfo>(hAllocator->GetAllocationCallbacks()))
+{
+    VMA_ASSERT(VMA_DEBUG_MARGIN == 0);
+
+}
+
+VmaDefragmentationAlgorithm_Fast::~VmaDefragmentationAlgorithm_Fast()
+{
+}
+
+VkResult VmaDefragmentationAlgorithm_Fast::Defragment(
+    VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves,
+    VkDeviceSize maxBytesToMove,
+    uint32_t maxAllocationsToMove,
+    VmaDefragmentationFlags flags)
+{
+    VMA_ASSERT(m_AllAllocations || m_pBlockVector->CalcAllocationCount() == m_AllocationCount);
+
+    const size_t blockCount = m_pBlockVector->GetBlockCount();
+    if(blockCount == 0 || maxBytesToMove == 0 || maxAllocationsToMove == 0)
+    {
+        return VK_SUCCESS;
+    }
+
+    PreprocessMetadata();
+
+    // Sort blocks in order from most destination.
+
+    m_BlockInfos.resize(blockCount);
+    for(size_t i = 0; i < blockCount; ++i)
+    {
+        m_BlockInfos[i].origBlockIndex = i;
+    }
+
+    VMA_SORT(m_BlockInfos.begin(), m_BlockInfos.end(), [this](const BlockInfo& lhs, const BlockInfo& rhs) -> bool {
+        return m_pBlockVector->GetBlock(lhs.origBlockIndex)->m_pMetadata->GetSumFreeSize() <
+            m_pBlockVector->GetBlock(rhs.origBlockIndex)->m_pMetadata->GetSumFreeSize();
+    });
+
+    // THE MAIN ALGORITHM
+
+    FreeSpaceDatabase freeSpaceDb;
+
+    size_t dstBlockInfoIndex = 0;
+    size_t dstOrigBlockIndex = m_BlockInfos[dstBlockInfoIndex].origBlockIndex;
+    VmaDeviceMemoryBlock* pDstBlock = m_pBlockVector->GetBlock(dstOrigBlockIndex);
+    VmaBlockMetadata_Generic* pDstMetadata = (VmaBlockMetadata_Generic*)pDstBlock->m_pMetadata;
+    VkDeviceSize dstBlockSize = pDstMetadata->GetSize();
+    VkDeviceSize dstOffset = 0;
+
+    bool end = false;
+    for(size_t srcBlockInfoIndex = 0; !end && srcBlockInfoIndex < blockCount; ++srcBlockInfoIndex)
+    {
+        const size_t srcOrigBlockIndex = m_BlockInfos[srcBlockInfoIndex].origBlockIndex;
+        VmaDeviceMemoryBlock* const pSrcBlock = m_pBlockVector->GetBlock(srcOrigBlockIndex);
+        VmaBlockMetadata_Generic* const pSrcMetadata = (VmaBlockMetadata_Generic*)pSrcBlock->m_pMetadata;
+        for(VmaSuballocationList::iterator srcSuballocIt = pSrcMetadata->m_Suballocations.begin();
+            !end && srcSuballocIt != pSrcMetadata->m_Suballocations.end(); )
+        {
+            VmaAllocation_T* const pAlloc = srcSuballocIt->hAllocation;
+            const VkDeviceSize srcAllocAlignment = pAlloc->GetAlignment();
+            const VkDeviceSize srcAllocSize = srcSuballocIt->size;
+            if(m_AllocationsMoved == maxAllocationsToMove ||
+                m_BytesMoved + srcAllocSize > maxBytesToMove)
+            {
+                end = true;
+                break;
+            }
+            const VkDeviceSize srcAllocOffset = srcSuballocIt->offset;
+
+            VmaDefragmentationMove move = {};
+            // Try to place it in one of free spaces from the database.
+            size_t freeSpaceInfoIndex;
+            VkDeviceSize dstAllocOffset;
+            if(freeSpaceDb.Fetch(srcAllocAlignment, srcAllocSize,
+                freeSpaceInfoIndex, dstAllocOffset))
+            {
+                size_t freeSpaceOrigBlockIndex = m_BlockInfos[freeSpaceInfoIndex].origBlockIndex;
+                VmaDeviceMemoryBlock* pFreeSpaceBlock = m_pBlockVector->GetBlock(freeSpaceOrigBlockIndex);
+                VmaBlockMetadata_Generic* pFreeSpaceMetadata = (VmaBlockMetadata_Generic*)pFreeSpaceBlock->m_pMetadata;
+
+                // Same block
+                if(freeSpaceInfoIndex == srcBlockInfoIndex)
+                {
+                    VMA_ASSERT(dstAllocOffset <= srcAllocOffset);
+
+                    // MOVE OPTION 1: Move the allocation inside the same block by decreasing offset.
+
+                    VmaSuballocation suballoc = *srcSuballocIt;
+                    suballoc.offset = dstAllocOffset;
+                    suballoc.hAllocation->ChangeOffset(dstAllocOffset);
+                    m_BytesMoved += srcAllocSize;
+                    ++m_AllocationsMoved;
+                    
+                    VmaSuballocationList::iterator nextSuballocIt = srcSuballocIt;
+                    ++nextSuballocIt;
+                    pSrcMetadata->m_Suballocations.erase(srcSuballocIt);
+                    srcSuballocIt = nextSuballocIt;
+
+                    InsertSuballoc(pFreeSpaceMetadata, suballoc);
+
+                    move.srcBlockIndex = srcOrigBlockIndex;
+                    move.dstBlockIndex = freeSpaceOrigBlockIndex;
+                    move.srcOffset = srcAllocOffset;
+                    move.dstOffset = dstAllocOffset;
+                    move.size = srcAllocSize;
+                    
+                    moves.push_back(move);
+                }
+                // Different block
+                else
+                {
+                    // MOVE OPTION 2: Move the allocation to a different block.
+
+                    VMA_ASSERT(freeSpaceInfoIndex < srcBlockInfoIndex);
+
+                    VmaSuballocation suballoc = *srcSuballocIt;
+                    suballoc.offset = dstAllocOffset;
+                    suballoc.hAllocation->ChangeBlockAllocation(m_hAllocator, pFreeSpaceBlock, dstAllocOffset);
+                    m_BytesMoved += srcAllocSize;
+                    ++m_AllocationsMoved;
+
+                    VmaSuballocationList::iterator nextSuballocIt = srcSuballocIt;
+                    ++nextSuballocIt;
+                    pSrcMetadata->m_Suballocations.erase(srcSuballocIt);
+                    srcSuballocIt = nextSuballocIt;
+
+                    InsertSuballoc(pFreeSpaceMetadata, suballoc);
+
+                    move.srcBlockIndex = srcOrigBlockIndex;
+                    move.dstBlockIndex = freeSpaceOrigBlockIndex;
+                    move.srcOffset = srcAllocOffset;
+                    move.dstOffset = dstAllocOffset;
+                    move.size = srcAllocSize;
+                    
+                    moves.push_back(move);
+                }
+            }
+            else
+            {
+                dstAllocOffset = VmaAlignUp(dstOffset, srcAllocAlignment);
+
+                // If the allocation doesn't fit before the end of dstBlock, forward to next block.
+                while(dstBlockInfoIndex < srcBlockInfoIndex &&
+                    dstAllocOffset + srcAllocSize > dstBlockSize)
+                {
+                    // But before that, register remaining free space at the end of dst block.
+                    freeSpaceDb.Register(dstBlockInfoIndex, dstOffset, dstBlockSize - dstOffset);
+
+                    ++dstBlockInfoIndex;
+                    dstOrigBlockIndex = m_BlockInfos[dstBlockInfoIndex].origBlockIndex;
+                    pDstBlock = m_pBlockVector->GetBlock(dstOrigBlockIndex);
+                    pDstMetadata = (VmaBlockMetadata_Generic*)pDstBlock->m_pMetadata;
+                    dstBlockSize = pDstMetadata->GetSize();
+                    dstOffset = 0;
+                    dstAllocOffset = 0;
+                }
+
+                // Same block
+                if(dstBlockInfoIndex == srcBlockInfoIndex)
+                {
+                    VMA_ASSERT(dstAllocOffset <= srcAllocOffset);
+
+                    const bool overlap = dstAllocOffset + srcAllocSize > srcAllocOffset;
+
+                    bool skipOver = overlap;
+                    if(overlap && m_OverlappingMoveSupported && dstAllocOffset < srcAllocOffset)
+                    {
+                        // If destination and source place overlap, skip if it would move it
+                        // by only < 1/64 of its size.
+                        skipOver = (srcAllocOffset - dstAllocOffset) * 64 < srcAllocSize;
+                    }
+
+                    if(skipOver)
+                    {
+                        freeSpaceDb.Register(dstBlockInfoIndex, dstOffset, srcAllocOffset - dstOffset);
+
+                        dstOffset = srcAllocOffset + srcAllocSize;
+                        ++srcSuballocIt;
+                    }
+                    // MOVE OPTION 1: Move the allocation inside the same block by decreasing offset.
+                    else
+                    {
+                        srcSuballocIt->offset = dstAllocOffset;
+                        srcSuballocIt->hAllocation->ChangeOffset(dstAllocOffset);
+                        dstOffset = dstAllocOffset + srcAllocSize;
+                        m_BytesMoved += srcAllocSize;
+                        ++m_AllocationsMoved;
+                        ++srcSuballocIt;
+                        
+                        move.srcBlockIndex = srcOrigBlockIndex;
+                        move.dstBlockIndex = dstOrigBlockIndex;
+                        move.srcOffset = srcAllocOffset;
+                        move.dstOffset = dstAllocOffset;
+                        move.size = srcAllocSize;
+                        
+                        moves.push_back(move);
+                    }
+                }
+                // Different block
+                else
+                {
+                    // MOVE OPTION 2: Move the allocation to a different block.
+
+                    VMA_ASSERT(dstBlockInfoIndex < srcBlockInfoIndex);
+                    VMA_ASSERT(dstAllocOffset + srcAllocSize <= dstBlockSize);
+
+                    VmaSuballocation suballoc = *srcSuballocIt;
+                    suballoc.offset = dstAllocOffset;
+                    suballoc.hAllocation->ChangeBlockAllocation(m_hAllocator, pDstBlock, dstAllocOffset);
+                    dstOffset = dstAllocOffset + srcAllocSize;
+                    m_BytesMoved += srcAllocSize;
+                    ++m_AllocationsMoved;
+
+                    VmaSuballocationList::iterator nextSuballocIt = srcSuballocIt;
+                    ++nextSuballocIt;
+                    pSrcMetadata->m_Suballocations.erase(srcSuballocIt);
+                    srcSuballocIt = nextSuballocIt;
+
+                    pDstMetadata->m_Suballocations.push_back(suballoc);
+
+                    move.srcBlockIndex = srcOrigBlockIndex;
+                    move.dstBlockIndex = dstOrigBlockIndex;
+                    move.srcOffset = srcAllocOffset;
+                    move.dstOffset = dstAllocOffset;
+                    move.size = srcAllocSize;
+                    
+                    moves.push_back(move);
+                }
+            }
+        }
+    }
+
+    m_BlockInfos.clear();
+    
+    PostprocessMetadata();
+
+    return VK_SUCCESS;
+}
+
+void VmaDefragmentationAlgorithm_Fast::PreprocessMetadata()
+{
+    const size_t blockCount = m_pBlockVector->GetBlockCount();
+    for(size_t blockIndex = 0; blockIndex < blockCount; ++blockIndex)
+    {
+        VmaBlockMetadata_Generic* const pMetadata =
+            (VmaBlockMetadata_Generic*)m_pBlockVector->GetBlock(blockIndex)->m_pMetadata;
+        pMetadata->m_FreeCount = 0;
+        pMetadata->m_SumFreeSize = pMetadata->GetSize();
+        pMetadata->m_FreeSuballocationsBySize.clear();
+        for(VmaSuballocationList::iterator it = pMetadata->m_Suballocations.begin();
+            it != pMetadata->m_Suballocations.end(); )
+        {
+            if(it->type == VMA_SUBALLOCATION_TYPE_FREE)
+            {
+                VmaSuballocationList::iterator nextIt = it;
+                ++nextIt;
+                pMetadata->m_Suballocations.erase(it);
+                it = nextIt;
+            }
+            else
+            {
+                ++it;
+            }
+        }
+    }
+}
+
+void VmaDefragmentationAlgorithm_Fast::PostprocessMetadata()
+{
+    const size_t blockCount = m_pBlockVector->GetBlockCount();
+    for(size_t blockIndex = 0; blockIndex < blockCount; ++blockIndex)
+    {
+        VmaBlockMetadata_Generic* const pMetadata =
+            (VmaBlockMetadata_Generic*)m_pBlockVector->GetBlock(blockIndex)->m_pMetadata;
+        const VkDeviceSize blockSize = pMetadata->GetSize();
+        
+        // No allocations in this block - entire area is free.
+        if(pMetadata->m_Suballocations.empty())
+        {
+            pMetadata->m_FreeCount = 1;
+            //pMetadata->m_SumFreeSize is already set to blockSize.
+            VmaSuballocation suballoc = {
+                0, // offset
+                blockSize, // size
+                VMA_NULL, // hAllocation
+                VMA_SUBALLOCATION_TYPE_FREE };
+            pMetadata->m_Suballocations.push_back(suballoc);
+            pMetadata->RegisterFreeSuballocation(pMetadata->m_Suballocations.begin());
+        }
+        // There are some allocations in this block.
+        else
+        {
+            VkDeviceSize offset = 0;
+            VmaSuballocationList::iterator it;
+            for(it = pMetadata->m_Suballocations.begin();
+                it != pMetadata->m_Suballocations.end();
+                ++it)
+            {
+                VMA_ASSERT(it->type != VMA_SUBALLOCATION_TYPE_FREE);
+                VMA_ASSERT(it->offset >= offset);
+
+                // Need to insert preceding free space.
+                if(it->offset > offset)
+                {
+                    ++pMetadata->m_FreeCount;
+                    const VkDeviceSize freeSize = it->offset - offset;
+                    VmaSuballocation suballoc = {
+                        offset, // offset
+                        freeSize, // size
+                        VMA_NULL, // hAllocation
+                        VMA_SUBALLOCATION_TYPE_FREE };
+                    VmaSuballocationList::iterator precedingFreeIt = pMetadata->m_Suballocations.insert(it, suballoc);
+                    if(freeSize >= VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER)
+                    {
+                        pMetadata->m_FreeSuballocationsBySize.push_back(precedingFreeIt);
+                    }
+                }
+
+                pMetadata->m_SumFreeSize -= it->size;
+                offset = it->offset + it->size;
+            }
+
+            // Need to insert trailing free space.
+            if(offset < blockSize)
+            {
+                ++pMetadata->m_FreeCount;
+                const VkDeviceSize freeSize = blockSize - offset;
+                VmaSuballocation suballoc = {
+                    offset, // offset
+                    freeSize, // size
+                    VMA_NULL, // hAllocation
+                    VMA_SUBALLOCATION_TYPE_FREE };
+                VMA_ASSERT(it == pMetadata->m_Suballocations.end());
+                VmaSuballocationList::iterator trailingFreeIt = pMetadata->m_Suballocations.insert(it, suballoc);
+                if(freeSize > VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER)
+                {
+                    pMetadata->m_FreeSuballocationsBySize.push_back(trailingFreeIt);
+                }
+            }
+
+            VMA_SORT(
+                pMetadata->m_FreeSuballocationsBySize.begin(),
+                pMetadata->m_FreeSuballocationsBySize.end(),
+                VmaSuballocationItemSizeLess());
+        }
+
+        VMA_HEAVY_ASSERT(pMetadata->Validate());
+    }
+}
+
+void VmaDefragmentationAlgorithm_Fast::InsertSuballoc(VmaBlockMetadata_Generic* pMetadata, const VmaSuballocation& suballoc)
+{
+    // TODO: Optimize somehow. Remember iterator instead of searching for it linearly.
+    VmaSuballocationList::iterator it = pMetadata->m_Suballocations.begin();
+    while(it != pMetadata->m_Suballocations.end())
+    {
+        if(it->offset < suballoc.offset)
+        {
+            ++it;
+        }
+    }
+    pMetadata->m_Suballocations.insert(it, suballoc);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// VmaBlockVectorDefragmentationContext
+
+VmaBlockVectorDefragmentationContext::VmaBlockVectorDefragmentationContext(
+    VmaAllocator hAllocator,
+    VmaPool hCustomPool,
+    VmaBlockVector* pBlockVector,
+    uint32_t currFrameIndex) :
+    res(VK_SUCCESS),
+    mutexLocked(false),
+    blockContexts(VmaStlAllocator<VmaBlockDefragmentationContext>(hAllocator->GetAllocationCallbacks())),
+    defragmentationMoves(VmaStlAllocator<VmaDefragmentationMove>(hAllocator->GetAllocationCallbacks())),
+    defragmentationMovesProcessed(0),
+    defragmentationMovesCommitted(0),
+    hasDefragmentationPlan(0),
+    m_hAllocator(hAllocator),
+    m_hCustomPool(hCustomPool),
+    m_pBlockVector(pBlockVector),
+    m_CurrFrameIndex(currFrameIndex),
+    m_pAlgorithm(VMA_NULL),
+    m_Allocations(VmaStlAllocator<AllocInfo>(hAllocator->GetAllocationCallbacks())),
+    m_AllAllocations(false)
+{
+}
+
+VmaBlockVectorDefragmentationContext::~VmaBlockVectorDefragmentationContext()
+{
+    vma_delete(m_hAllocator, m_pAlgorithm);
+}
+
+void VmaBlockVectorDefragmentationContext::AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged)
+{
+    AllocInfo info = { hAlloc, pChanged };
+    m_Allocations.push_back(info);
+}
+
+void VmaBlockVectorDefragmentationContext::Begin(bool overlappingMoveSupported, VmaDefragmentationFlags flags)
+{
+    const bool allAllocations = m_AllAllocations ||
+        m_Allocations.size() == m_pBlockVector->CalcAllocationCount();
+
+    /********************************
+    HERE IS THE CHOICE OF DEFRAGMENTATION ALGORITHM.
+    ********************************/
+
+    /*
+    Fast algorithm is supported only when certain criteria are met:
+    - VMA_DEBUG_MARGIN is 0.
+    - All allocations in this block vector are moveable.
+    - There is no possibility of image/buffer granularity conflict.
+    - The defragmentation is not incremental
+    */
+    if(VMA_DEBUG_MARGIN == 0 &&
+        allAllocations &&
+        !m_pBlockVector->IsBufferImageGranularityConflictPossible() &&
+        !(flags & VMA_DEFRAGMENTATION_FLAG_INCREMENTAL))
+    {
+        m_pAlgorithm = vma_new(m_hAllocator, VmaDefragmentationAlgorithm_Fast)(
+            m_hAllocator, m_pBlockVector, m_CurrFrameIndex, overlappingMoveSupported);
+    }
+    else
+    {
+        m_pAlgorithm = vma_new(m_hAllocator, VmaDefragmentationAlgorithm_Generic)(
+            m_hAllocator, m_pBlockVector, m_CurrFrameIndex, overlappingMoveSupported);
+    }
+
+    if(allAllocations)
+    {
+        m_pAlgorithm->AddAll();
+    }
+    else
+    {
+        for(size_t i = 0, count = m_Allocations.size(); i < count; ++i)
+        {
+            m_pAlgorithm->AddAllocation(m_Allocations[i].hAlloc, m_Allocations[i].pChanged);
+        }
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// VmaDefragmentationContext
+
+VmaDefragmentationContext_T::VmaDefragmentationContext_T(
+    VmaAllocator hAllocator,
+    uint32_t currFrameIndex,
+    uint32_t flags,
+    VmaDefragmentationStats* pStats) :
+    m_hAllocator(hAllocator),
+    m_CurrFrameIndex(currFrameIndex),
+    m_Flags(flags),
+    m_pStats(pStats),
+    m_CustomPoolContexts(VmaStlAllocator<VmaBlockVectorDefragmentationContext*>(hAllocator->GetAllocationCallbacks()))
+{
+    memset(m_DefaultPoolContexts, 0, sizeof(m_DefaultPoolContexts));
+}
+
+VmaDefragmentationContext_T::~VmaDefragmentationContext_T()
+{
+    for(size_t i = m_CustomPoolContexts.size(); i--; )
+    {
+        VmaBlockVectorDefragmentationContext* pBlockVectorCtx = m_CustomPoolContexts[i];
+        pBlockVectorCtx->GetBlockVector()->DefragmentationEnd(pBlockVectorCtx, m_Flags, m_pStats);
+        vma_delete(m_hAllocator, pBlockVectorCtx);
+    }
+    for(size_t i = m_hAllocator->m_MemProps.memoryTypeCount; i--; )
+    {
+        VmaBlockVectorDefragmentationContext* pBlockVectorCtx = m_DefaultPoolContexts[i];
+        if(pBlockVectorCtx)
+        {
+            pBlockVectorCtx->GetBlockVector()->DefragmentationEnd(pBlockVectorCtx, m_Flags, m_pStats);
+            vma_delete(m_hAllocator, pBlockVectorCtx);
+        }
+    }
+}
+
+void VmaDefragmentationContext_T::AddPools(uint32_t poolCount, VmaPool* pPools)
+{
+    for(uint32_t poolIndex = 0; poolIndex < poolCount; ++poolIndex)
+    {
+        VmaPool pool = pPools[poolIndex];
+        VMA_ASSERT(pool);
+        // Pools with algorithm other than default are not defragmented.
+        if(pool->m_BlockVector.GetAlgorithm() == 0)
+        {
+            VmaBlockVectorDefragmentationContext* pBlockVectorDefragCtx = VMA_NULL;
+            
+            for(size_t i = m_CustomPoolContexts.size(); i--; )
+            {
+                if(m_CustomPoolContexts[i]->GetCustomPool() == pool)
+                {
+                    pBlockVectorDefragCtx = m_CustomPoolContexts[i];
+                    break;
+                }
+            }
+            
+            if(!pBlockVectorDefragCtx)
+            {
+                pBlockVectorDefragCtx = vma_new(m_hAllocator, VmaBlockVectorDefragmentationContext)(
+                    m_hAllocator,
+                    pool,
+                    &pool->m_BlockVector,
+                    m_CurrFrameIndex);
+                m_CustomPoolContexts.push_back(pBlockVectorDefragCtx);
+            }
+
+            pBlockVectorDefragCtx->AddAll();
+        }
+    }
+}
+
+void VmaDefragmentationContext_T::AddAllocations(
+    uint32_t allocationCount,
+    VmaAllocation* pAllocations,
+    VkBool32* pAllocationsChanged)
+{
+    // Dispatch pAllocations among defragmentators. Create them when necessary.
+    for(uint32_t allocIndex = 0; allocIndex < allocationCount; ++allocIndex)
+    {
+        const VmaAllocation hAlloc = pAllocations[allocIndex];
+        VMA_ASSERT(hAlloc);
+        // DedicatedAlloc cannot be defragmented.
+        if((hAlloc->GetType() == VmaAllocation_T::ALLOCATION_TYPE_BLOCK) &&
+            // Lost allocation cannot be defragmented.
+            (hAlloc->GetLastUseFrameIndex() != VMA_FRAME_INDEX_LOST))
+        {
+            VmaBlockVectorDefragmentationContext* pBlockVectorDefragCtx = VMA_NULL;
+
+            const VmaPool hAllocPool = hAlloc->GetBlock()->GetParentPool();
+            // This allocation belongs to custom pool.
+            if(hAllocPool != VK_NULL_HANDLE)
+            {
+                // Pools with algorithm other than default are not defragmented.
+                if(hAllocPool->m_BlockVector.GetAlgorithm() == 0)
+                {
+                    for(size_t i = m_CustomPoolContexts.size(); i--; )
+                    {
+                        if(m_CustomPoolContexts[i]->GetCustomPool() == hAllocPool)
+                        {
+                            pBlockVectorDefragCtx = m_CustomPoolContexts[i];
+                            break;
+                        }
+                    }
+                    if(!pBlockVectorDefragCtx)
+                    {
+                        pBlockVectorDefragCtx = vma_new(m_hAllocator, VmaBlockVectorDefragmentationContext)(
+                            m_hAllocator,
+                            hAllocPool,
+                            &hAllocPool->m_BlockVector,
+                            m_CurrFrameIndex);
+                        m_CustomPoolContexts.push_back(pBlockVectorDefragCtx);
+                    }
+                }
+            }
+            // This allocation belongs to default pool.
+            else
+            {
+                const uint32_t memTypeIndex = hAlloc->GetMemoryTypeIndex();
+                pBlockVectorDefragCtx = m_DefaultPoolContexts[memTypeIndex];
+                if(!pBlockVectorDefragCtx)
+                {
+                    pBlockVectorDefragCtx = vma_new(m_hAllocator, VmaBlockVectorDefragmentationContext)(
+                        m_hAllocator,
+                        VMA_NULL, // hCustomPool
+                        m_hAllocator->m_pBlockVectors[memTypeIndex],
+                        m_CurrFrameIndex);
+                    m_DefaultPoolContexts[memTypeIndex] = pBlockVectorDefragCtx;
+                }
+            }
+
+            if(pBlockVectorDefragCtx)
+            {
+                VkBool32* const pChanged = (pAllocationsChanged != VMA_NULL) ?
+                    &pAllocationsChanged[allocIndex] : VMA_NULL;
+                pBlockVectorDefragCtx->AddAllocation(hAlloc, pChanged);
+            }
+        }
+    }
+}
+
+VkResult VmaDefragmentationContext_T::Defragment(
+    VkDeviceSize maxCpuBytesToMove, uint32_t maxCpuAllocationsToMove,
+    VkDeviceSize maxGpuBytesToMove, uint32_t maxGpuAllocationsToMove,
+    VkCommandBuffer commandBuffer, VmaDefragmentationStats* pStats, VmaDefragmentationFlags flags)
+{
+    if(pStats)
+    {
+        memset(pStats, 0, sizeof(VmaDefragmentationStats));
+    }
+
+    if(flags & VMA_DEFRAGMENTATION_FLAG_INCREMENTAL)
+    {
+        // For incremental defragmetnations, we just earmark how much we can move
+        // The real meat is in the defragmentation steps
+        m_MaxCpuBytesToMove = maxCpuBytesToMove;
+        m_MaxCpuAllocationsToMove = maxCpuAllocationsToMove;
+
+        m_MaxGpuBytesToMove = maxGpuBytesToMove;
+        m_MaxGpuAllocationsToMove = maxGpuAllocationsToMove;
+
+        if(m_MaxCpuBytesToMove == 0 && m_MaxCpuAllocationsToMove == 0 &&
+            m_MaxGpuBytesToMove == 0 && m_MaxGpuAllocationsToMove == 0)
+            return VK_SUCCESS;
+
+        return VK_NOT_READY;
+    }
+
+    if(commandBuffer == VK_NULL_HANDLE)
+    {
+        maxGpuBytesToMove = 0;
+        maxGpuAllocationsToMove = 0;
+    }
+
+    VkResult res = VK_SUCCESS;
+
+    // Process default pools.
+    for(uint32_t memTypeIndex = 0;
+        memTypeIndex < m_hAllocator->GetMemoryTypeCount() && res >= VK_SUCCESS;
+        ++memTypeIndex)
+    {
+        VmaBlockVectorDefragmentationContext* pBlockVectorCtx = m_DefaultPoolContexts[memTypeIndex];
+        if(pBlockVectorCtx)
+        {
+            VMA_ASSERT(pBlockVectorCtx->GetBlockVector());
+            pBlockVectorCtx->GetBlockVector()->Defragment(
+                pBlockVectorCtx,
+                pStats, flags,
+                maxCpuBytesToMove, maxCpuAllocationsToMove,
+                maxGpuBytesToMove, maxGpuAllocationsToMove,
+                commandBuffer);
+            if(pBlockVectorCtx->res != VK_SUCCESS)
+            {
+                res = pBlockVectorCtx->res;
+            }
+        }
+    }
+
+    // Process custom pools.
+    for(size_t customCtxIndex = 0, customCtxCount = m_CustomPoolContexts.size();
+        customCtxIndex < customCtxCount && res >= VK_SUCCESS;
+        ++customCtxIndex)
+    {
+        VmaBlockVectorDefragmentationContext* pBlockVectorCtx = m_CustomPoolContexts[customCtxIndex];
+        VMA_ASSERT(pBlockVectorCtx && pBlockVectorCtx->GetBlockVector());
+        pBlockVectorCtx->GetBlockVector()->Defragment(
+            pBlockVectorCtx,
+            pStats, flags,
+            maxCpuBytesToMove, maxCpuAllocationsToMove,
+            maxGpuBytesToMove, maxGpuAllocationsToMove,
+            commandBuffer);
+        if(pBlockVectorCtx->res != VK_SUCCESS)
+        {
+            res = pBlockVectorCtx->res;
+        }
+    }
+
+    return res;
+}
+
+VkResult VmaDefragmentationContext_T::DefragmentPassBegin(VmaDefragmentationPassInfo* pInfo)
+{
+    VmaDefragmentationPassMoveInfo* pCurrentMove = pInfo->pMoves;
+    uint32_t movesLeft = pInfo->moveCount;
+
+    // Process default pools.
+    for(uint32_t memTypeIndex = 0;
+        memTypeIndex < m_hAllocator->GetMemoryTypeCount();
+        ++memTypeIndex)
+    {
+        VmaBlockVectorDefragmentationContext *pBlockVectorCtx = m_DefaultPoolContexts[memTypeIndex];
+        if(pBlockVectorCtx)
+        {
+            VMA_ASSERT(pBlockVectorCtx->GetBlockVector());
+
+            if(!pBlockVectorCtx->hasDefragmentationPlan)
+            {
+                pBlockVectorCtx->GetBlockVector()->Defragment(
+                    pBlockVectorCtx,
+                    m_pStats, m_Flags,
+                    m_MaxCpuBytesToMove, m_MaxCpuAllocationsToMove,
+                    m_MaxGpuBytesToMove, m_MaxGpuAllocationsToMove,
+                    VK_NULL_HANDLE);
+
+                if(pBlockVectorCtx->res < VK_SUCCESS)
+                    continue;
+
+                pBlockVectorCtx->hasDefragmentationPlan = true;
+            }
+
+            const uint32_t processed = pBlockVectorCtx->GetBlockVector()->ProcessDefragmentations(
+                pBlockVectorCtx,
+                pCurrentMove, movesLeft);
+
+            movesLeft -= processed;
+            pCurrentMove += processed;
+        }
+    }
+
+    // Process custom pools.
+    for(size_t customCtxIndex = 0, customCtxCount = m_CustomPoolContexts.size();
+        customCtxIndex < customCtxCount;
+        ++customCtxIndex)
+    {
+        VmaBlockVectorDefragmentationContext *pBlockVectorCtx = m_CustomPoolContexts[customCtxIndex];
+        VMA_ASSERT(pBlockVectorCtx && pBlockVectorCtx->GetBlockVector());
+
+        if(!pBlockVectorCtx->hasDefragmentationPlan)
+        {
+            pBlockVectorCtx->GetBlockVector()->Defragment(
+                pBlockVectorCtx,
+                m_pStats, m_Flags,
+                m_MaxCpuBytesToMove, m_MaxCpuAllocationsToMove,
+                m_MaxGpuBytesToMove, m_MaxGpuAllocationsToMove,
+                VK_NULL_HANDLE);
+
+            if(pBlockVectorCtx->res < VK_SUCCESS)
+                continue;
+
+            pBlockVectorCtx->hasDefragmentationPlan = true;
+        }
+
+        const uint32_t processed = pBlockVectorCtx->GetBlockVector()->ProcessDefragmentations(
+            pBlockVectorCtx,
+            pCurrentMove, movesLeft);
+
+        movesLeft -= processed;
+        pCurrentMove += processed;
+    }
+
+    pInfo->moveCount = pInfo->moveCount - movesLeft;
+
+    return VK_SUCCESS;
+}
+VkResult VmaDefragmentationContext_T::DefragmentPassEnd()
+{
+    VkResult res = VK_SUCCESS;
+
+    // Process default pools.
+    for(uint32_t memTypeIndex = 0;
+        memTypeIndex < m_hAllocator->GetMemoryTypeCount();
+        ++memTypeIndex)
+    {
+        VmaBlockVectorDefragmentationContext *pBlockVectorCtx = m_DefaultPoolContexts[memTypeIndex];
+        if(pBlockVectorCtx)
+        {
+            VMA_ASSERT(pBlockVectorCtx->GetBlockVector());
+
+            if(!pBlockVectorCtx->hasDefragmentationPlan)
+            {
+                res = VK_NOT_READY;
+                continue;
+            }
+
+            pBlockVectorCtx->GetBlockVector()->CommitDefragmentations(
+                pBlockVectorCtx, m_pStats);
+
+            if(pBlockVectorCtx->defragmentationMoves.size() != pBlockVectorCtx->defragmentationMovesCommitted)
+                res = VK_NOT_READY;
+        }
+    }
+
+    // Process custom pools.
+    for(size_t customCtxIndex = 0, customCtxCount = m_CustomPoolContexts.size();
+        customCtxIndex < customCtxCount;
+        ++customCtxIndex)
+    {
+        VmaBlockVectorDefragmentationContext *pBlockVectorCtx = m_CustomPoolContexts[customCtxIndex];
+        VMA_ASSERT(pBlockVectorCtx && pBlockVectorCtx->GetBlockVector());
+
+        if(!pBlockVectorCtx->hasDefragmentationPlan)
+        {
+            res = VK_NOT_READY;
+            continue;
+        }
+
+        pBlockVectorCtx->GetBlockVector()->CommitDefragmentations(
+            pBlockVectorCtx, m_pStats);
+
+        if(pBlockVectorCtx->defragmentationMoves.size() != pBlockVectorCtx->defragmentationMovesCommitted)
+            res = VK_NOT_READY;
+    }
+
+    return res;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// VmaRecorder
+
+#if VMA_RECORDING_ENABLED
+
+VmaRecorder::VmaRecorder() :
+    m_UseMutex(true),
+    m_Flags(0),
+    m_File(VMA_NULL),
+    m_Freq(INT64_MAX),
+    m_StartCounter(INT64_MAX)
+{
+}
+
+VkResult VmaRecorder::Init(const VmaRecordSettings& settings, bool useMutex)
+{
+    m_UseMutex = useMutex;
+    m_Flags = settings.flags;
+
+    QueryPerformanceFrequency((LARGE_INTEGER*)&m_Freq);
+    QueryPerformanceCounter((LARGE_INTEGER*)&m_StartCounter);
+
+    // Open file for writing.
+    errno_t err = fopen_s(&m_File, settings.pFilePath, "wb");
+    if(err != 0)
+    {
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+
+    // Write header.
+    fprintf(m_File, "%s\n", "Vulkan Memory Allocator,Calls recording");
+    fprintf(m_File, "%s\n", "1,8");
+
+    return VK_SUCCESS;
+}
+
+VmaRecorder::~VmaRecorder()
+{
+    if(m_File != VMA_NULL)
+    {
+        fclose(m_File);
+    }
+}
+
+void VmaRecorder::RecordCreateAllocator(uint32_t frameIndex)
+{
+    CallParams callParams;
+    GetBasicParams(callParams);
+
+    VmaMutexLock lock(m_FileMutex, m_UseMutex);
+    fprintf(m_File, "%u,%.3f,%u,vmaCreateAllocator\n", callParams.threadId, callParams.time, frameIndex);
+    Flush();
+}
+
+void VmaRecorder::RecordDestroyAllocator(uint32_t frameIndex)
+{
+    CallParams callParams;
+    GetBasicParams(callParams);
+
+    VmaMutexLock lock(m_FileMutex, m_UseMutex);
+    fprintf(m_File, "%u,%.3f,%u,vmaDestroyAllocator\n", callParams.threadId, callParams.time, frameIndex);
+    Flush();
+}
+
+void VmaRecorder::RecordCreatePool(uint32_t frameIndex, const VmaPoolCreateInfo& createInfo, VmaPool pool)
+{
+    CallParams callParams;
+    GetBasicParams(callParams);
+
+    VmaMutexLock lock(m_FileMutex, m_UseMutex);
+    fprintf(m_File, "%u,%.3f,%u,vmaCreatePool,%u,%u,%llu,%llu,%llu,%u,%p\n", callParams.threadId, callParams.time, frameIndex,
+        createInfo.memoryTypeIndex,
+        createInfo.flags,
+        createInfo.blockSize,
+        (uint64_t)createInfo.minBlockCount,
+        (uint64_t)createInfo.maxBlockCount,
+        createInfo.frameInUseCount,
+        pool);
+    Flush();
+}
+
+void VmaRecorder::RecordDestroyPool(uint32_t frameIndex, VmaPool pool)
+{
+    CallParams callParams;
+    GetBasicParams(callParams);
+
+    VmaMutexLock lock(m_FileMutex, m_UseMutex);
+    fprintf(m_File, "%u,%.3f,%u,vmaDestroyPool,%p\n", callParams.threadId, callParams.time, frameIndex,
+        pool);
+    Flush();
+}
+
+void VmaRecorder::RecordAllocateMemory(uint32_t frameIndex,
+        const VkMemoryRequirements& vkMemReq,
+        const VmaAllocationCreateInfo& createInfo,
+        VmaAllocation allocation)
+{
+    CallParams callParams;
+    GetBasicParams(callParams);
+
+    VmaMutexLock lock(m_FileMutex, m_UseMutex);
+    UserDataString userDataStr(createInfo.flags, createInfo.pUserData);
+    fprintf(m_File, "%u,%.3f,%u,vmaAllocateMemory,%llu,%llu,%u,%u,%u,%u,%u,%u,%p,%p,%s\n", callParams.threadId, callParams.time, frameIndex,
+        vkMemReq.size,
+        vkMemReq.alignment,
+        vkMemReq.memoryTypeBits,
+        createInfo.flags,
+        createInfo.usage,
+        createInfo.requiredFlags,
+        createInfo.preferredFlags,
+        createInfo.memoryTypeBits,
+        createInfo.pool,
+        allocation,
+        userDataStr.GetString());
+    Flush();
+}
+
+void VmaRecorder::RecordAllocateMemoryPages(uint32_t frameIndex,
+    const VkMemoryRequirements& vkMemReq,
+    const VmaAllocationCreateInfo& createInfo,
+    uint64_t allocationCount,
+    const VmaAllocation* pAllocations)
+{
+    CallParams callParams;
+    GetBasicParams(callParams);
+
+    VmaMutexLock lock(m_FileMutex, m_UseMutex);
+    UserDataString userDataStr(createInfo.flags, createInfo.pUserData);
+    fprintf(m_File, "%u,%.3f,%u,vmaAllocateMemoryPages,%llu,%llu,%u,%u,%u,%u,%u,%u,%p,", callParams.threadId, callParams.time, frameIndex,
+        vkMemReq.size,
+        vkMemReq.alignment,
+        vkMemReq.memoryTypeBits,
+        createInfo.flags,
+        createInfo.usage,
+        createInfo.requiredFlags,
+        createInfo.preferredFlags,
+        createInfo.memoryTypeBits,
+        createInfo.pool);
+    PrintPointerList(allocationCount, pAllocations);
+    fprintf(m_File, ",%s\n", userDataStr.GetString());
+    Flush();
+}
+
+void VmaRecorder::RecordAllocateMemoryForBuffer(uint32_t frameIndex,
+    const VkMemoryRequirements& vkMemReq,
+    bool requiresDedicatedAllocation,
+    bool prefersDedicatedAllocation,
+    const VmaAllocationCreateInfo& createInfo,
+    VmaAllocation allocation)
+{
+    CallParams callParams;
+    GetBasicParams(callParams);
+
+    VmaMutexLock lock(m_FileMutex, m_UseMutex);
+    UserDataString userDataStr(createInfo.flags, createInfo.pUserData);
+    fprintf(m_File, "%u,%.3f,%u,vmaAllocateMemoryForBuffer,%llu,%llu,%u,%u,%u,%u,%u,%u,%u,%u,%p,%p,%s\n", callParams.threadId, callParams.time, frameIndex,
+        vkMemReq.size,
+        vkMemReq.alignment,
+        vkMemReq.memoryTypeBits,
+        requiresDedicatedAllocation ? 1 : 0,
+        prefersDedicatedAllocation ? 1 : 0,
+        createInfo.flags,
+        createInfo.usage,
+        createInfo.requiredFlags,
+        createInfo.preferredFlags,
+        createInfo.memoryTypeBits,
+        createInfo.pool,
+        allocation,
+        userDataStr.GetString());
+    Flush();
+}
+
+void VmaRecorder::RecordAllocateMemoryForImage(uint32_t frameIndex,
+    const VkMemoryRequirements& vkMemReq,
+    bool requiresDedicatedAllocation,
+    bool prefersDedicatedAllocation,
+    const VmaAllocationCreateInfo& createInfo,
+    VmaAllocation allocation)
+{
+    CallParams callParams;
+    GetBasicParams(callParams);
+
+    VmaMutexLock lock(m_FileMutex, m_UseMutex);
+    UserDataString userDataStr(createInfo.flags, createInfo.pUserData);
+    fprintf(m_File, "%u,%.3f,%u,vmaAllocateMemoryForImage,%llu,%llu,%u,%u,%u,%u,%u,%u,%u,%u,%p,%p,%s\n", callParams.threadId, callParams.time, frameIndex,
+        vkMemReq.size,
+        vkMemReq.alignment,
+        vkMemReq.memoryTypeBits,
+        requiresDedicatedAllocation ? 1 : 0,
+        prefersDedicatedAllocation ? 1 : 0,
+        createInfo.flags,
+        createInfo.usage,
+        createInfo.requiredFlags,
+        createInfo.preferredFlags,
+        createInfo.memoryTypeBits,
+        createInfo.pool,
+        allocation,
+        userDataStr.GetString());
+    Flush();
+}
+
+void VmaRecorder::RecordFreeMemory(uint32_t frameIndex,
+    VmaAllocation allocation)
+{
+    CallParams callParams;
+    GetBasicParams(callParams);
+
+    VmaMutexLock lock(m_FileMutex, m_UseMutex);
+    fprintf(m_File, "%u,%.3f,%u,vmaFreeMemory,%p\n", callParams.threadId, callParams.time, frameIndex,
+        allocation);
+    Flush();
+}
+
+void VmaRecorder::RecordFreeMemoryPages(uint32_t frameIndex,
+    uint64_t allocationCount,
+    const VmaAllocation* pAllocations)
+{
+    CallParams callParams;
+    GetBasicParams(callParams);
+
+    VmaMutexLock lock(m_FileMutex, m_UseMutex);
+    fprintf(m_File, "%u,%.3f,%u,vmaFreeMemoryPages,", callParams.threadId, callParams.time, frameIndex);
+    PrintPointerList(allocationCount, pAllocations);
+    fprintf(m_File, "\n");
+    Flush();
+}
+
+void VmaRecorder::RecordSetAllocationUserData(uint32_t frameIndex,
+    VmaAllocation allocation,
+    const void* pUserData)
+{
+    CallParams callParams;
+    GetBasicParams(callParams);
+
+    VmaMutexLock lock(m_FileMutex, m_UseMutex);
+    UserDataString userDataStr(
+        allocation->IsUserDataString() ? VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT : 0,
+        pUserData);
+    fprintf(m_File, "%u,%.3f,%u,vmaSetAllocationUserData,%p,%s\n", callParams.threadId, callParams.time, frameIndex,
+        allocation,
+        userDataStr.GetString());
+    Flush();
+}
+
+void VmaRecorder::RecordCreateLostAllocation(uint32_t frameIndex,
+    VmaAllocation allocation)
+{
+    CallParams callParams;
+    GetBasicParams(callParams);
+
+    VmaMutexLock lock(m_FileMutex, m_UseMutex);
+    fprintf(m_File, "%u,%.3f,%u,vmaCreateLostAllocation,%p\n", callParams.threadId, callParams.time, frameIndex,
+        allocation);
+    Flush();
+}
+
+void VmaRecorder::RecordMapMemory(uint32_t frameIndex,
+    VmaAllocation allocation)
+{
+    CallParams callParams;
+    GetBasicParams(callParams);
+
+    VmaMutexLock lock(m_FileMutex, m_UseMutex);
+    fprintf(m_File, "%u,%.3f,%u,vmaMapMemory,%p\n", callParams.threadId, callParams.time, frameIndex,
+        allocation);
+    Flush();
+}
+
+void VmaRecorder::RecordUnmapMemory(uint32_t frameIndex,
+    VmaAllocation allocation)
+{
+    CallParams callParams;
+    GetBasicParams(callParams);
+
+    VmaMutexLock lock(m_FileMutex, m_UseMutex);
+    fprintf(m_File, "%u,%.3f,%u,vmaUnmapMemory,%p\n", callParams.threadId, callParams.time, frameIndex,
+        allocation);
+    Flush();
+}
+
+void VmaRecorder::RecordFlushAllocation(uint32_t frameIndex,
+    VmaAllocation allocation, VkDeviceSize offset, VkDeviceSize size)
+{
+    CallParams callParams;
+    GetBasicParams(callParams);
+
+    VmaMutexLock lock(m_FileMutex, m_UseMutex);
+    fprintf(m_File, "%u,%.3f,%u,vmaFlushAllocation,%p,%llu,%llu\n", callParams.threadId, callParams.time, frameIndex,
+        allocation,
+        offset,
+        size);
+    Flush();
+}
+
+void VmaRecorder::RecordInvalidateAllocation(uint32_t frameIndex,
+    VmaAllocation allocation, VkDeviceSize offset, VkDeviceSize size)
+{
+    CallParams callParams;
+    GetBasicParams(callParams);
+
+    VmaMutexLock lock(m_FileMutex, m_UseMutex);
+    fprintf(m_File, "%u,%.3f,%u,vmaInvalidateAllocation,%p,%llu,%llu\n", callParams.threadId, callParams.time, frameIndex,
+        allocation,
+        offset,
+        size);
+    Flush();
+}
+
+void VmaRecorder::RecordCreateBuffer(uint32_t frameIndex,
+    const VkBufferCreateInfo& bufCreateInfo,
+    const VmaAllocationCreateInfo& allocCreateInfo,
+    VmaAllocation allocation)
+{
+    CallParams callParams;
+    GetBasicParams(callParams);
+
+    VmaMutexLock lock(m_FileMutex, m_UseMutex);
+    UserDataString userDataStr(allocCreateInfo.flags, allocCreateInfo.pUserData);
+    fprintf(m_File, "%u,%.3f,%u,vmaCreateBuffer,%u,%llu,%u,%u,%u,%u,%u,%u,%u,%p,%p,%s\n", callParams.threadId, callParams.time, frameIndex,
+        bufCreateInfo.flags,
+        bufCreateInfo.size,
+        bufCreateInfo.usage,
+        bufCreateInfo.sharingMode,
+        allocCreateInfo.flags,
+        allocCreateInfo.usage,
+        allocCreateInfo.requiredFlags,
+        allocCreateInfo.preferredFlags,
+        allocCreateInfo.memoryTypeBits,
+        allocCreateInfo.pool,
+        allocation,
+        userDataStr.GetString());
+    Flush();
+}
+
+void VmaRecorder::RecordCreateImage(uint32_t frameIndex,
+    const VkImageCreateInfo& imageCreateInfo,
+    const VmaAllocationCreateInfo& allocCreateInfo,
+    VmaAllocation allocation)
+{
+    CallParams callParams;
+    GetBasicParams(callParams);
+
+    VmaMutexLock lock(m_FileMutex, m_UseMutex);
+    UserDataString userDataStr(allocCreateInfo.flags, allocCreateInfo.pUserData);
+    fprintf(m_File, "%u,%.3f,%u,vmaCreateImage,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%p,%p,%s\n", callParams.threadId, callParams.time, frameIndex,
+        imageCreateInfo.flags,
+        imageCreateInfo.imageType,
+        imageCreateInfo.format,
+        imageCreateInfo.extent.width,
+        imageCreateInfo.extent.height,
+        imageCreateInfo.extent.depth,
+        imageCreateInfo.mipLevels,
+        imageCreateInfo.arrayLayers,
+        imageCreateInfo.samples,
+        imageCreateInfo.tiling,
+        imageCreateInfo.usage,
+        imageCreateInfo.sharingMode,
+        imageCreateInfo.initialLayout,
+        allocCreateInfo.flags,
+        allocCreateInfo.usage,
+        allocCreateInfo.requiredFlags,
+        allocCreateInfo.preferredFlags,
+        allocCreateInfo.memoryTypeBits,
+        allocCreateInfo.pool,
+        allocation,
+        userDataStr.GetString());
+    Flush();
+}
+
+void VmaRecorder::RecordDestroyBuffer(uint32_t frameIndex,
+    VmaAllocation allocation)
+{
+    CallParams callParams;
+    GetBasicParams(callParams);
+
+    VmaMutexLock lock(m_FileMutex, m_UseMutex);
+    fprintf(m_File, "%u,%.3f,%u,vmaDestroyBuffer,%p\n", callParams.threadId, callParams.time, frameIndex,
+        allocation);
+    Flush();
+}
+
+void VmaRecorder::RecordDestroyImage(uint32_t frameIndex,
+    VmaAllocation allocation)
+{
+    CallParams callParams;
+    GetBasicParams(callParams);
+
+    VmaMutexLock lock(m_FileMutex, m_UseMutex);
+    fprintf(m_File, "%u,%.3f,%u,vmaDestroyImage,%p\n", callParams.threadId, callParams.time, frameIndex,
+        allocation);
+    Flush();
+}
+
+void VmaRecorder::RecordTouchAllocation(uint32_t frameIndex,
+    VmaAllocation allocation)
+{
+    CallParams callParams;
+    GetBasicParams(callParams);
+
+    VmaMutexLock lock(m_FileMutex, m_UseMutex);
+    fprintf(m_File, "%u,%.3f,%u,vmaTouchAllocation,%p\n", callParams.threadId, callParams.time, frameIndex,
+        allocation);
+    Flush();
+}
+
+void VmaRecorder::RecordGetAllocationInfo(uint32_t frameIndex,
+    VmaAllocation allocation)
+{
+    CallParams callParams;
+    GetBasicParams(callParams);
+
+    VmaMutexLock lock(m_FileMutex, m_UseMutex);
+    fprintf(m_File, "%u,%.3f,%u,vmaGetAllocationInfo,%p\n", callParams.threadId, callParams.time, frameIndex,
+        allocation);
+    Flush();
+}
+
+void VmaRecorder::RecordMakePoolAllocationsLost(uint32_t frameIndex,
+    VmaPool pool)
+{
+    CallParams callParams;
+    GetBasicParams(callParams);
+
+    VmaMutexLock lock(m_FileMutex, m_UseMutex);
+    fprintf(m_File, "%u,%.3f,%u,vmaMakePoolAllocationsLost,%p\n", callParams.threadId, callParams.time, frameIndex,
+        pool);
+    Flush();
+}
+
+void VmaRecorder::RecordDefragmentationBegin(uint32_t frameIndex,
+    const VmaDefragmentationInfo2& info,
+    VmaDefragmentationContext ctx)
+{
+    CallParams callParams;
+    GetBasicParams(callParams);
+
+    VmaMutexLock lock(m_FileMutex, m_UseMutex);
+    fprintf(m_File, "%u,%.3f,%u,vmaDefragmentationBegin,%u,", callParams.threadId, callParams.time, frameIndex,
+        info.flags);
+    PrintPointerList(info.allocationCount, info.pAllocations);
+    fprintf(m_File, ",");
+    PrintPointerList(info.poolCount, info.pPools);
+    fprintf(m_File, ",%llu,%u,%llu,%u,%p,%p\n",
+        info.maxCpuBytesToMove,
+        info.maxCpuAllocationsToMove,
+        info.maxGpuBytesToMove,
+        info.maxGpuAllocationsToMove,
+        info.commandBuffer,
+        ctx);
+    Flush();
+}
+
+void VmaRecorder::RecordDefragmentationEnd(uint32_t frameIndex,
+    VmaDefragmentationContext ctx)
+{
+    CallParams callParams;
+    GetBasicParams(callParams);
+
+    VmaMutexLock lock(m_FileMutex, m_UseMutex);
+    fprintf(m_File, "%u,%.3f,%u,vmaDefragmentationEnd,%p\n", callParams.threadId, callParams.time, frameIndex,
+        ctx);
+    Flush();
+}
+
+void VmaRecorder::RecordSetPoolName(uint32_t frameIndex,
+    VmaPool pool,
+    const char* name)
+{
+    CallParams callParams;
+    GetBasicParams(callParams);
+
+    VmaMutexLock lock(m_FileMutex, m_UseMutex);
+    fprintf(m_File, "%u,%.3f,%u,vmaSetPoolName,%p,%s\n", callParams.threadId, callParams.time, frameIndex,
+        pool, name != VMA_NULL ? name : "");
+    Flush();
+}
+
+VmaRecorder::UserDataString::UserDataString(VmaAllocationCreateFlags allocFlags, const void* pUserData)
+{
+    if(pUserData != VMA_NULL)
+    {
+        if((allocFlags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0)
+        {
+            m_Str = (const char*)pUserData;
+        }
+        else
+        {
+            sprintf_s(m_PtrStr, "%p", pUserData);
+            m_Str = m_PtrStr;
+        }
+    }
+    else
+    {
+        m_Str = "";
+    }
+}
+
+void VmaRecorder::WriteConfiguration(
+    const VkPhysicalDeviceProperties& devProps,
+    const VkPhysicalDeviceMemoryProperties& memProps,
+    uint32_t vulkanApiVersion,
+    bool dedicatedAllocationExtensionEnabled,
+    bool bindMemory2ExtensionEnabled,
+    bool memoryBudgetExtensionEnabled,
+    bool deviceCoherentMemoryExtensionEnabled)
+{
+    fprintf(m_File, "Config,Begin\n");
+
+    fprintf(m_File, "VulkanApiVersion,%u,%u\n", VK_VERSION_MAJOR(vulkanApiVersion), VK_VERSION_MINOR(vulkanApiVersion));
+
+    fprintf(m_File, "PhysicalDevice,apiVersion,%u\n", devProps.apiVersion);
+    fprintf(m_File, "PhysicalDevice,driverVersion,%u\n", devProps.driverVersion);
+    fprintf(m_File, "PhysicalDevice,vendorID,%u\n", devProps.vendorID);
+    fprintf(m_File, "PhysicalDevice,deviceID,%u\n", devProps.deviceID);
+    fprintf(m_File, "PhysicalDevice,deviceType,%u\n", devProps.deviceType);
+    fprintf(m_File, "PhysicalDevice,deviceName,%s\n", devProps.deviceName);
+
+    fprintf(m_File, "PhysicalDeviceLimits,maxMemoryAllocationCount,%u\n", devProps.limits.maxMemoryAllocationCount);
+    fprintf(m_File, "PhysicalDeviceLimits,bufferImageGranularity,%llu\n", devProps.limits.bufferImageGranularity);
+    fprintf(m_File, "PhysicalDeviceLimits,nonCoherentAtomSize,%llu\n", devProps.limits.nonCoherentAtomSize);
+
+    fprintf(m_File, "PhysicalDeviceMemory,HeapCount,%u\n", memProps.memoryHeapCount);
+    for(uint32_t i = 0; i < memProps.memoryHeapCount; ++i)
+    {
+        fprintf(m_File, "PhysicalDeviceMemory,Heap,%u,size,%llu\n", i, memProps.memoryHeaps[i].size);
+        fprintf(m_File, "PhysicalDeviceMemory,Heap,%u,flags,%u\n", i, memProps.memoryHeaps[i].flags);
+    }
+    fprintf(m_File, "PhysicalDeviceMemory,TypeCount,%u\n", memProps.memoryTypeCount);
+    for(uint32_t i = 0; i < memProps.memoryTypeCount; ++i)
+    {
+        fprintf(m_File, "PhysicalDeviceMemory,Type,%u,heapIndex,%u\n", i, memProps.memoryTypes[i].heapIndex);
+        fprintf(m_File, "PhysicalDeviceMemory,Type,%u,propertyFlags,%u\n", i, memProps.memoryTypes[i].propertyFlags);
+    }
+
+    fprintf(m_File, "Extension,VK_KHR_dedicated_allocation,%u\n", dedicatedAllocationExtensionEnabled ? 1 : 0);
+    fprintf(m_File, "Extension,VK_KHR_bind_memory2,%u\n", bindMemory2ExtensionEnabled ? 1 : 0);
+    fprintf(m_File, "Extension,VK_EXT_memory_budget,%u\n", memoryBudgetExtensionEnabled ? 1 : 0);
+    fprintf(m_File, "Extension,VK_AMD_device_coherent_memory,%u\n", deviceCoherentMemoryExtensionEnabled ? 1 : 0);
+
+    fprintf(m_File, "Macro,VMA_DEBUG_ALWAYS_DEDICATED_MEMORY,%u\n", VMA_DEBUG_ALWAYS_DEDICATED_MEMORY ? 1 : 0);
+    fprintf(m_File, "Macro,VMA_DEBUG_ALIGNMENT,%llu\n", (VkDeviceSize)VMA_DEBUG_ALIGNMENT);
+    fprintf(m_File, "Macro,VMA_DEBUG_MARGIN,%llu\n", (VkDeviceSize)VMA_DEBUG_MARGIN);
+    fprintf(m_File, "Macro,VMA_DEBUG_INITIALIZE_ALLOCATIONS,%u\n", VMA_DEBUG_INITIALIZE_ALLOCATIONS ? 1 : 0);
+    fprintf(m_File, "Macro,VMA_DEBUG_DETECT_CORRUPTION,%u\n", VMA_DEBUG_DETECT_CORRUPTION ? 1 : 0);
+    fprintf(m_File, "Macro,VMA_DEBUG_GLOBAL_MUTEX,%u\n", VMA_DEBUG_GLOBAL_MUTEX ? 1 : 0);
+    fprintf(m_File, "Macro,VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY,%llu\n", (VkDeviceSize)VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY);
+    fprintf(m_File, "Macro,VMA_SMALL_HEAP_MAX_SIZE,%llu\n", (VkDeviceSize)VMA_SMALL_HEAP_MAX_SIZE);
+    fprintf(m_File, "Macro,VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE,%llu\n", (VkDeviceSize)VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE);
+
+    fprintf(m_File, "Config,End\n");
+}
+
+void VmaRecorder::GetBasicParams(CallParams& outParams)
+{
+    outParams.threadId = GetCurrentThreadId();
+
+    LARGE_INTEGER counter;
+    QueryPerformanceCounter(&counter);
+    outParams.time = (double)(counter.QuadPart - m_StartCounter) / (double)m_Freq;
+}
+
+void VmaRecorder::PrintPointerList(uint64_t count, const VmaAllocation* pItems)
+{
+    if(count)
+    {
+        fprintf(m_File, "%p", pItems[0]);
+        for(uint64_t i = 1; i < count; ++i)
+        {
+            fprintf(m_File, " %p", pItems[i]);
+        }
+    }
+}
+
+void VmaRecorder::Flush()
+{
+    if((m_Flags & VMA_RECORD_FLUSH_AFTER_CALL_BIT) != 0)
+    {
+        fflush(m_File);
+    }
+}
+
+#endif // #if VMA_RECORDING_ENABLED
+
+////////////////////////////////////////////////////////////////////////////////
+// VmaAllocationObjectAllocator
+
+VmaAllocationObjectAllocator::VmaAllocationObjectAllocator(const VkAllocationCallbacks* pAllocationCallbacks) :
+    m_Allocator(pAllocationCallbacks, 1024)
+{
+}
+
+template<typename... Types> VmaAllocation VmaAllocationObjectAllocator::Allocate(Types... args)
+{
+    VmaMutexLock mutexLock(m_Mutex);
+    return m_Allocator.Alloc<Types...>(std::forward<Types>(args)...);
+}
+
+void VmaAllocationObjectAllocator::Free(VmaAllocation hAlloc)
+{
+    VmaMutexLock mutexLock(m_Mutex);
+    m_Allocator.Free(hAlloc);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// VmaAllocator_T
+
+VmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) :
+    m_UseMutex((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT) == 0),
+    m_VulkanApiVersion(pCreateInfo->vulkanApiVersion != 0 ? pCreateInfo->vulkanApiVersion : VK_API_VERSION_1_0),
+    m_UseKhrDedicatedAllocation((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT) != 0),
+    m_UseKhrBindMemory2((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT) != 0),
+    m_UseExtMemoryBudget((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT) != 0),
+    m_UseAmdDeviceCoherentMemory((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT) != 0),
+    m_UseKhrBufferDeviceAddress((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT) != 0),
+    m_hDevice(pCreateInfo->device),
+    m_hInstance(pCreateInfo->instance),
+    m_AllocationCallbacksSpecified(pCreateInfo->pAllocationCallbacks != VMA_NULL),
+    m_AllocationCallbacks(pCreateInfo->pAllocationCallbacks ?
+        *pCreateInfo->pAllocationCallbacks : VmaEmptyAllocationCallbacks),
+    m_AllocationObjectAllocator(&m_AllocationCallbacks),
+    m_HeapSizeLimitMask(0),
+    m_PreferredLargeHeapBlockSize(0),
+    m_PhysicalDevice(pCreateInfo->physicalDevice),
+    m_CurrentFrameIndex(0),
+    m_GpuDefragmentationMemoryTypeBits(UINT32_MAX),
+    m_Pools(VmaStlAllocator<VmaPool>(GetAllocationCallbacks())),
+    m_NextPoolId(0),
+    m_GlobalMemoryTypeBits(UINT32_MAX)
+#if VMA_RECORDING_ENABLED
+    ,m_pRecorder(VMA_NULL)
+#endif
+{
+    if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))
+    {
+        m_UseKhrDedicatedAllocation = false;
+        m_UseKhrBindMemory2 = false;
+    }
+
+    if(VMA_DEBUG_DETECT_CORRUPTION)
+    {
+        // Needs to be multiply of uint32_t size because we are going to write VMA_CORRUPTION_DETECTION_MAGIC_VALUE to it.
+        VMA_ASSERT(VMA_DEBUG_MARGIN % sizeof(uint32_t) == 0);
+    }
+
+    VMA_ASSERT(pCreateInfo->physicalDevice && pCreateInfo->device && pCreateInfo->instance);
+
+    if(m_VulkanApiVersion < VK_MAKE_VERSION(1, 1, 0))
+    {
+#if !(VMA_DEDICATED_ALLOCATION)
+        if((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT) != 0)
+        {
+            VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT set but required extensions are disabled by preprocessor macros.");
+        }
+#endif
+#if !(VMA_BIND_MEMORY2)
+        if((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT) != 0)
+        {
+            VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT set but required extension is disabled by preprocessor macros.");
+        }
+#endif
+    }
+#if !(VMA_MEMORY_BUDGET)
+    if((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT) != 0)
+    {
+        VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT set but required extension is disabled by preprocessor macros.");
+    }
+#endif
+#if !(VMA_BUFFER_DEVICE_ADDRESS)
+    if(m_UseKhrBufferDeviceAddress)
+    {
+        VMA_ASSERT(0 && "VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT is set but required extension or Vulkan 1.2 is not available in your Vulkan header or its support in VMA has been disabled by a preprocessor macro.");
+    }
+#endif
+#if VMA_VULKAN_VERSION < 1002000
+    if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 2, 0))
+    {
+        VMA_ASSERT(0 && "vulkanApiVersion >= VK_API_VERSION_1_2 but required Vulkan version is disabled by preprocessor macros.");
+    }
+#endif
+#if VMA_VULKAN_VERSION < 1001000
+    if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))
+    {
+        VMA_ASSERT(0 && "vulkanApiVersion >= VK_API_VERSION_1_1 but required Vulkan version is disabled by preprocessor macros.");
+    }
+#endif
+
+    memset(&m_DeviceMemoryCallbacks, 0 ,sizeof(m_DeviceMemoryCallbacks));
+    memset(&m_PhysicalDeviceProperties, 0, sizeof(m_PhysicalDeviceProperties));
+    memset(&m_MemProps, 0, sizeof(m_MemProps));
+        
+    memset(&m_pBlockVectors, 0, sizeof(m_pBlockVectors));
+    memset(&m_pDedicatedAllocations, 0, sizeof(m_pDedicatedAllocations));
+    memset(&m_VulkanFunctions, 0, sizeof(m_VulkanFunctions));
+
+    if(pCreateInfo->pDeviceMemoryCallbacks != VMA_NULL)
+    {
+        m_DeviceMemoryCallbacks.pUserData = pCreateInfo->pDeviceMemoryCallbacks->pUserData;
+        m_DeviceMemoryCallbacks.pfnAllocate = pCreateInfo->pDeviceMemoryCallbacks->pfnAllocate;
+        m_DeviceMemoryCallbacks.pfnFree = pCreateInfo->pDeviceMemoryCallbacks->pfnFree;
+    }
+
+    ImportVulkanFunctions(pCreateInfo->pVulkanFunctions);
+
+    (*m_VulkanFunctions.vkGetPhysicalDeviceProperties)(m_PhysicalDevice, &m_PhysicalDeviceProperties);
+    (*m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties)(m_PhysicalDevice, &m_MemProps);
+
+    VMA_ASSERT(VmaIsPow2(VMA_DEBUG_ALIGNMENT));
+    VMA_ASSERT(VmaIsPow2(VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY));
+    VMA_ASSERT(VmaIsPow2(m_PhysicalDeviceProperties.limits.bufferImageGranularity));
+    VMA_ASSERT(VmaIsPow2(m_PhysicalDeviceProperties.limits.nonCoherentAtomSize));
+
+    m_PreferredLargeHeapBlockSize = (pCreateInfo->preferredLargeHeapBlockSize != 0) ?
+        pCreateInfo->preferredLargeHeapBlockSize : static_cast<VkDeviceSize>(VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE);
+
+    m_GlobalMemoryTypeBits = CalculateGlobalMemoryTypeBits();
+
+    if(pCreateInfo->pHeapSizeLimit != VMA_NULL)
+    {
+        for(uint32_t heapIndex = 0; heapIndex < GetMemoryHeapCount(); ++heapIndex)
+        {
+            const VkDeviceSize limit = pCreateInfo->pHeapSizeLimit[heapIndex];
+            if(limit != VK_WHOLE_SIZE)
+            {
+                m_HeapSizeLimitMask |= 1u << heapIndex;
+                if(limit < m_MemProps.memoryHeaps[heapIndex].size)
+                {
+                    m_MemProps.memoryHeaps[heapIndex].size = limit;
+                }
+            }
+        }
+    }
+
+    for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
+    {
+        const VkDeviceSize preferredBlockSize = CalcPreferredBlockSize(memTypeIndex);
+
+        m_pBlockVectors[memTypeIndex] = vma_new(this, VmaBlockVector)(
+            this,
+            VK_NULL_HANDLE, // hParentPool
+            memTypeIndex,
+            preferredBlockSize,
+            0,
+            SIZE_MAX,
+            GetBufferImageGranularity(),
+            pCreateInfo->frameInUseCount,
+            false, // explicitBlockSize
+            false); // linearAlgorithm
+        // No need to call m_pBlockVectors[memTypeIndex][blockVectorTypeIndex]->CreateMinBlocks here,
+        // becase minBlockCount is 0.
+        m_pDedicatedAllocations[memTypeIndex] = vma_new(this, AllocationVectorType)(VmaStlAllocator<VmaAllocation>(GetAllocationCallbacks()));
+
+    }
+}
+
+VkResult VmaAllocator_T::Init(const VmaAllocatorCreateInfo* pCreateInfo)
+{
+    VkResult res = VK_SUCCESS;
+
+    if(pCreateInfo->pRecordSettings != VMA_NULL &&
+        !VmaStrIsEmpty(pCreateInfo->pRecordSettings->pFilePath))
+    {
+#if VMA_RECORDING_ENABLED
+        m_pRecorder = vma_new(this, VmaRecorder)();
+        res = m_pRecorder->Init(*pCreateInfo->pRecordSettings, m_UseMutex);
+        if(res != VK_SUCCESS)
+        {
+            return res;
+        }
+        m_pRecorder->WriteConfiguration(
+            m_PhysicalDeviceProperties,
+            m_MemProps,
+            m_VulkanApiVersion,
+            m_UseKhrDedicatedAllocation,
+            m_UseKhrBindMemory2,
+            m_UseExtMemoryBudget,
+            m_UseAmdDeviceCoherentMemory);
+        m_pRecorder->RecordCreateAllocator(GetCurrentFrameIndex());
+#else
+        VMA_ASSERT(0 && "VmaAllocatorCreateInfo::pRecordSettings used, but not supported due to VMA_RECORDING_ENABLED not defined to 1.");
+        return VK_ERROR_FEATURE_NOT_PRESENT;
+#endif
+    }
+
+#if VMA_MEMORY_BUDGET
+    if(m_UseExtMemoryBudget)
+    {
+        UpdateVulkanBudget();
+    }
+#endif // #if VMA_MEMORY_BUDGET
+
+    return res;
+}
+
+VmaAllocator_T::~VmaAllocator_T()
+{
+#if VMA_RECORDING_ENABLED
+    if(m_pRecorder != VMA_NULL)
+    {
+        m_pRecorder->RecordDestroyAllocator(GetCurrentFrameIndex());
+        vma_delete(this, m_pRecorder);
+    }
+#endif
+    
+    VMA_ASSERT(m_Pools.empty());
+
+    for(size_t i = GetMemoryTypeCount(); i--; )
+    {
+        if(m_pDedicatedAllocations[i] != VMA_NULL && !m_pDedicatedAllocations[i]->empty())
+        {
+            VMA_ASSERT(0 && "Unfreed dedicated allocations found.");
+        }
+
+        vma_delete(this, m_pDedicatedAllocations[i]);
+        vma_delete(this, m_pBlockVectors[i]);
+    }
+}
+
+void VmaAllocator_T::ImportVulkanFunctions(const VmaVulkanFunctions* pVulkanFunctions)
+{
+#if VMA_STATIC_VULKAN_FUNCTIONS == 1
+    ImportVulkanFunctions_Static();
+#endif
+
+    if(pVulkanFunctions != VMA_NULL)
+    {
+        ImportVulkanFunctions_Custom(pVulkanFunctions);
+    }
+
+#if VMA_DYNAMIC_VULKAN_FUNCTIONS == 1
+    ImportVulkanFunctions_Dynamic();
+#endif
+
+    ValidateVulkanFunctions();
+}
+
+#if VMA_STATIC_VULKAN_FUNCTIONS == 1
+
+void VmaAllocator_T::ImportVulkanFunctions_Static()
+{
+    // Vulkan 1.0
+    m_VulkanFunctions.vkGetPhysicalDeviceProperties = (PFN_vkGetPhysicalDeviceProperties)vkGetPhysicalDeviceProperties;
+    m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties = (PFN_vkGetPhysicalDeviceMemoryProperties)vkGetPhysicalDeviceMemoryProperties;
+    m_VulkanFunctions.vkAllocateMemory = (PFN_vkAllocateMemory)vkAllocateMemory;
+    m_VulkanFunctions.vkFreeMemory = (PFN_vkFreeMemory)vkFreeMemory;
+    m_VulkanFunctions.vkMapMemory = (PFN_vkMapMemory)vkMapMemory;
+    m_VulkanFunctions.vkUnmapMemory = (PFN_vkUnmapMemory)vkUnmapMemory;
+    m_VulkanFunctions.vkFlushMappedMemoryRanges = (PFN_vkFlushMappedMemoryRanges)vkFlushMappedMemoryRanges;
+    m_VulkanFunctions.vkInvalidateMappedMemoryRanges = (PFN_vkInvalidateMappedMemoryRanges)vkInvalidateMappedMemoryRanges;
+    m_VulkanFunctions.vkBindBufferMemory = (PFN_vkBindBufferMemory)vkBindBufferMemory;
+    m_VulkanFunctions.vkBindImageMemory = (PFN_vkBindImageMemory)vkBindImageMemory;
+    m_VulkanFunctions.vkGetBufferMemoryRequirements = (PFN_vkGetBufferMemoryRequirements)vkGetBufferMemoryRequirements;
+    m_VulkanFunctions.vkGetImageMemoryRequirements = (PFN_vkGetImageMemoryRequirements)vkGetImageMemoryRequirements;
+    m_VulkanFunctions.vkCreateBuffer = (PFN_vkCreateBuffer)vkCreateBuffer;
+    m_VulkanFunctions.vkDestroyBuffer = (PFN_vkDestroyBuffer)vkDestroyBuffer;
+    m_VulkanFunctions.vkCreateImage = (PFN_vkCreateImage)vkCreateImage;
+    m_VulkanFunctions.vkDestroyImage = (PFN_vkDestroyImage)vkDestroyImage;
+    m_VulkanFunctions.vkCmdCopyBuffer = (PFN_vkCmdCopyBuffer)vkCmdCopyBuffer;
+
+    // Vulkan 1.1
+#if VMA_VULKAN_VERSION >= 1001000
+    if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))
+    {
+        m_VulkanFunctions.vkGetBufferMemoryRequirements2KHR = (PFN_vkGetBufferMemoryRequirements2)vkGetBufferMemoryRequirements2;
+        m_VulkanFunctions.vkGetImageMemoryRequirements2KHR = (PFN_vkGetImageMemoryRequirements2)vkGetImageMemoryRequirements2;
+        m_VulkanFunctions.vkBindBufferMemory2KHR = (PFN_vkBindBufferMemory2)vkBindBufferMemory2;
+        m_VulkanFunctions.vkBindImageMemory2KHR = (PFN_vkBindImageMemory2)vkBindImageMemory2;
+        m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties2KHR = (PFN_vkGetPhysicalDeviceMemoryProperties2)vkGetPhysicalDeviceMemoryProperties2;
+    }
+#endif
+}
+
+#endif // #if VMA_STATIC_VULKAN_FUNCTIONS == 1
+
+void VmaAllocator_T::ImportVulkanFunctions_Custom(const VmaVulkanFunctions* pVulkanFunctions)
+{
+    VMA_ASSERT(pVulkanFunctions != VMA_NULL);
+
+#define VMA_COPY_IF_NOT_NULL(funcName) \
+    if(pVulkanFunctions->funcName != VMA_NULL) m_VulkanFunctions.funcName = pVulkanFunctions->funcName;
+
+    VMA_COPY_IF_NOT_NULL(vkGetPhysicalDeviceProperties);
+    VMA_COPY_IF_NOT_NULL(vkGetPhysicalDeviceMemoryProperties);
+    VMA_COPY_IF_NOT_NULL(vkAllocateMemory);
+    VMA_COPY_IF_NOT_NULL(vkFreeMemory);
+    VMA_COPY_IF_NOT_NULL(vkMapMemory);
+    VMA_COPY_IF_NOT_NULL(vkUnmapMemory);
+    VMA_COPY_IF_NOT_NULL(vkFlushMappedMemoryRanges);
+    VMA_COPY_IF_NOT_NULL(vkInvalidateMappedMemoryRanges);
+    VMA_COPY_IF_NOT_NULL(vkBindBufferMemory);
+    VMA_COPY_IF_NOT_NULL(vkBindImageMemory);
+    VMA_COPY_IF_NOT_NULL(vkGetBufferMemoryRequirements);
+    VMA_COPY_IF_NOT_NULL(vkGetImageMemoryRequirements);
+    VMA_COPY_IF_NOT_NULL(vkCreateBuffer);
+    VMA_COPY_IF_NOT_NULL(vkDestroyBuffer);
+    VMA_COPY_IF_NOT_NULL(vkCreateImage);
+    VMA_COPY_IF_NOT_NULL(vkDestroyImage);
+    VMA_COPY_IF_NOT_NULL(vkCmdCopyBuffer);
+
+#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000
+    VMA_COPY_IF_NOT_NULL(vkGetBufferMemoryRequirements2KHR);
+    VMA_COPY_IF_NOT_NULL(vkGetImageMemoryRequirements2KHR);
+#endif
+
+#if VMA_BIND_MEMORY2 || VMA_VULKAN_VERSION >= 1001000
+    VMA_COPY_IF_NOT_NULL(vkBindBufferMemory2KHR);
+    VMA_COPY_IF_NOT_NULL(vkBindImageMemory2KHR);
+#endif
+
+#if VMA_MEMORY_BUDGET
+    VMA_COPY_IF_NOT_NULL(vkGetPhysicalDeviceMemoryProperties2KHR);
+#endif
+
+#undef VMA_COPY_IF_NOT_NULL
+}
+
+void VmaAllocator_T::ImportVulkanFunctions_Dynamic()
+{
+#define VMA_FETCH_INSTANCE_FUNC(memberName, functionPointerType, functionNameString) \
+    if(m_VulkanFunctions.memberName == VMA_NULL) \
+        m_VulkanFunctions.memberName = \
+            (functionPointerType)vkGetInstanceProcAddr(m_hInstance, functionNameString);
+#define VMA_FETCH_DEVICE_FUNC(memberName, functionPointerType, functionNameString) \
+    if(m_VulkanFunctions.memberName == VMA_NULL) \
+        m_VulkanFunctions.memberName = \
+            (functionPointerType)vkGetDeviceProcAddr(m_hDevice, functionNameString);
+
+    VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceProperties, PFN_vkGetPhysicalDeviceProperties, "vkGetPhysicalDeviceProperties");
+    VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties, PFN_vkGetPhysicalDeviceMemoryProperties, "vkGetPhysicalDeviceMemoryProperties");
+    VMA_FETCH_DEVICE_FUNC(vkAllocateMemory, PFN_vkAllocateMemory, "vkAllocateMemory");
+    VMA_FETCH_DEVICE_FUNC(vkFreeMemory, PFN_vkFreeMemory, "vkFreeMemory");
+    VMA_FETCH_DEVICE_FUNC(vkMapMemory, PFN_vkMapMemory, "vkMapMemory");
+    VMA_FETCH_DEVICE_FUNC(vkUnmapMemory, PFN_vkUnmapMemory, "vkUnmapMemory");
+    VMA_FETCH_DEVICE_FUNC(vkFlushMappedMemoryRanges, PFN_vkFlushMappedMemoryRanges, "vkFlushMappedMemoryRanges");
+    VMA_FETCH_DEVICE_FUNC(vkInvalidateMappedMemoryRanges, PFN_vkInvalidateMappedMemoryRanges, "vkInvalidateMappedMemoryRanges");
+    VMA_FETCH_DEVICE_FUNC(vkBindBufferMemory, PFN_vkBindBufferMemory, "vkBindBufferMemory");
+    VMA_FETCH_DEVICE_FUNC(vkBindImageMemory, PFN_vkBindImageMemory, "vkBindImageMemory");
+    VMA_FETCH_DEVICE_FUNC(vkGetBufferMemoryRequirements, PFN_vkGetBufferMemoryRequirements, "vkGetBufferMemoryRequirements");
+    VMA_FETCH_DEVICE_FUNC(vkGetImageMemoryRequirements, PFN_vkGetImageMemoryRequirements, "vkGetImageMemoryRequirements");
+    VMA_FETCH_DEVICE_FUNC(vkCreateBuffer, PFN_vkCreateBuffer, "vkCreateBuffer");
+    VMA_FETCH_DEVICE_FUNC(vkDestroyBuffer, PFN_vkDestroyBuffer, "vkDestroyBuffer");
+    VMA_FETCH_DEVICE_FUNC(vkCreateImage, PFN_vkCreateImage, "vkCreateImage");
+    VMA_FETCH_DEVICE_FUNC(vkDestroyImage, PFN_vkDestroyImage, "vkDestroyImage");
+    VMA_FETCH_DEVICE_FUNC(vkCmdCopyBuffer, PFN_vkCmdCopyBuffer, "vkCmdCopyBuffer");
+
+#if VMA_DEDICATED_ALLOCATION
+    if(m_UseKhrDedicatedAllocation)
+    {
+        VMA_FETCH_DEVICE_FUNC(vkGetBufferMemoryRequirements2KHR, PFN_vkGetBufferMemoryRequirements2KHR, "vkGetBufferMemoryRequirements2KHR");
+        VMA_FETCH_DEVICE_FUNC(vkGetImageMemoryRequirements2KHR, PFN_vkGetImageMemoryRequirements2KHR, "vkGetImageMemoryRequirements2KHR");
+    }
+#endif
+
+#if VMA_BIND_MEMORY2
+    if(m_UseKhrBindMemory2)
+    {
+        VMA_FETCH_DEVICE_FUNC(vkBindBufferMemory2KHR, PFN_vkBindBufferMemory2KHR, "vkBindBufferMemory2KHR");
+        VMA_FETCH_DEVICE_FUNC(vkBindImageMemory2KHR, PFN_vkBindImageMemory2KHR, "vkBindImageMemory2KHR");
+    }
+#endif // #if VMA_BIND_MEMORY2
+
+#if VMA_MEMORY_BUDGET
+    if(m_UseExtMemoryBudget && m_VulkanApiVersion < VK_MAKE_VERSION(1, 1, 0))
+    {
+        VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties2KHR, PFN_vkGetPhysicalDeviceMemoryProperties2KHR, "vkGetPhysicalDeviceMemoryProperties2KHR");
+    }
+#endif // #if VMA_MEMORY_BUDGET
+
+#undef VMA_FETCH_DEVICE_FUNC
+#undef VMA_FETCH_INSTANCE_FUNC
+}
+
+void VmaAllocator_T::ValidateVulkanFunctions()
+{
+    VMA_ASSERT(m_VulkanFunctions.vkGetPhysicalDeviceProperties != VMA_NULL);
+    VMA_ASSERT(m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties != VMA_NULL);
+    VMA_ASSERT(m_VulkanFunctions.vkAllocateMemory != VMA_NULL);
+    VMA_ASSERT(m_VulkanFunctions.vkFreeMemory != VMA_NULL);
+    VMA_ASSERT(m_VulkanFunctions.vkMapMemory != VMA_NULL);
+    VMA_ASSERT(m_VulkanFunctions.vkUnmapMemory != VMA_NULL);
+    VMA_ASSERT(m_VulkanFunctions.vkFlushMappedMemoryRanges != VMA_NULL);
+    VMA_ASSERT(m_VulkanFunctions.vkInvalidateMappedMemoryRanges != VMA_NULL);
+    VMA_ASSERT(m_VulkanFunctions.vkBindBufferMemory != VMA_NULL);
+    VMA_ASSERT(m_VulkanFunctions.vkBindImageMemory != VMA_NULL);
+    VMA_ASSERT(m_VulkanFunctions.vkGetBufferMemoryRequirements != VMA_NULL);
+    VMA_ASSERT(m_VulkanFunctions.vkGetImageMemoryRequirements != VMA_NULL);
+    VMA_ASSERT(m_VulkanFunctions.vkCreateBuffer != VMA_NULL);
+    VMA_ASSERT(m_VulkanFunctions.vkDestroyBuffer != VMA_NULL);
+    VMA_ASSERT(m_VulkanFunctions.vkCreateImage != VMA_NULL);
+    VMA_ASSERT(m_VulkanFunctions.vkDestroyImage != VMA_NULL);
+    VMA_ASSERT(m_VulkanFunctions.vkCmdCopyBuffer != VMA_NULL);
+
+#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000
+    if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0) || m_UseKhrDedicatedAllocation)
+    {
+        VMA_ASSERT(m_VulkanFunctions.vkGetBufferMemoryRequirements2KHR != VMA_NULL);
+        VMA_ASSERT(m_VulkanFunctions.vkGetImageMemoryRequirements2KHR != VMA_NULL);
+    }
+#endif
+
+#if VMA_BIND_MEMORY2 || VMA_VULKAN_VERSION >= 1001000
+    if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0) || m_UseKhrBindMemory2)
+    {
+        VMA_ASSERT(m_VulkanFunctions.vkBindBufferMemory2KHR != VMA_NULL);
+        VMA_ASSERT(m_VulkanFunctions.vkBindImageMemory2KHR != VMA_NULL);
+    }
+#endif
+
+#if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION >= 1001000
+    if(m_UseExtMemoryBudget || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))
+    {
+        VMA_ASSERT(m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties2KHR != VMA_NULL);
+    }
+#endif
+}
+
+VkDeviceSize VmaAllocator_T::CalcPreferredBlockSize(uint32_t memTypeIndex)
+{
+    const uint32_t heapIndex = MemoryTypeIndexToHeapIndex(memTypeIndex);
+    const VkDeviceSize heapSize = m_MemProps.memoryHeaps[heapIndex].size;
+    const bool isSmallHeap = heapSize <= VMA_SMALL_HEAP_MAX_SIZE;
+    return VmaAlignUp(isSmallHeap ? (heapSize / 8) : m_PreferredLargeHeapBlockSize, (VkDeviceSize)32);
+}
+
+VkResult VmaAllocator_T::AllocateMemoryOfType(
+    VkDeviceSize size,
+    VkDeviceSize alignment,
+    bool dedicatedAllocation,
+    VkBuffer dedicatedBuffer,
+    VkBufferUsageFlags dedicatedBufferUsage,
+    VkImage dedicatedImage,
+    const VmaAllocationCreateInfo& createInfo,
+    uint32_t memTypeIndex,
+    VmaSuballocationType suballocType,
+    size_t allocationCount,
+    VmaAllocation* pAllocations)
+{
+    VMA_ASSERT(pAllocations != VMA_NULL);
+    VMA_DEBUG_LOG("  AllocateMemory: MemoryTypeIndex=%u, AllocationCount=%zu, Size=%llu", memTypeIndex, allocationCount, size);
+
+    VmaAllocationCreateInfo finalCreateInfo = createInfo;
+
+    // If memory type is not HOST_VISIBLE, disable MAPPED.
+    if((finalCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0 &&
+        (m_MemProps.memoryTypes[memTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0)
+    {
+        finalCreateInfo.flags &= ~VMA_ALLOCATION_CREATE_MAPPED_BIT;
+    }
+    // If memory is lazily allocated, it should be always dedicated.
+    if(finalCreateInfo.usage == VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED)
+    {
+        finalCreateInfo.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
+    }
+
+    VmaBlockVector* const blockVector = m_pBlockVectors[memTypeIndex];
+    VMA_ASSERT(blockVector);
+
+    const VkDeviceSize preferredBlockSize = blockVector->GetPreferredBlockSize();
+    bool preferDedicatedMemory =
+        VMA_DEBUG_ALWAYS_DEDICATED_MEMORY ||
+        dedicatedAllocation ||
+        // Heuristics: Allocate dedicated memory if requested size if greater than half of preferred block size.
+        size > preferredBlockSize / 2;
+
+    if(preferDedicatedMemory &&
+        (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) == 0 &&
+        finalCreateInfo.pool == VK_NULL_HANDLE)
+    {
+        finalCreateInfo.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
+    }
+
+    if((finalCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0)
+    {
+        if((finalCreateInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) != 0)
+        {
+            return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+        }
+        else
+        {
+            return AllocateDedicatedMemory(
+                size,
+                suballocType,
+                memTypeIndex,
+                (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT) != 0,
+                (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0,
+                (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0,
+                finalCreateInfo.pUserData,
+                dedicatedBuffer,
+                dedicatedBufferUsage,
+                dedicatedImage,
+                allocationCount,
+                pAllocations);
+        }
+    }
+    else
+    {
+        VkResult res = blockVector->Allocate(
+            m_CurrentFrameIndex.load(),
+            size,
+            alignment,
+            finalCreateInfo,
+            suballocType,
+            allocationCount,
+            pAllocations);
+        if(res == VK_SUCCESS)
+        {
+            return res;
+        }
+
+        // 5. Try dedicated memory.
+        if((finalCreateInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) != 0)
+        {
+            return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+        }
+        else
+        {
+            res = AllocateDedicatedMemory(
+                size,
+                suballocType,
+                memTypeIndex,
+                (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT) != 0,
+                (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0,
+                (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0,
+                finalCreateInfo.pUserData,
+                dedicatedBuffer,
+                dedicatedBufferUsage,
+                dedicatedImage,
+                allocationCount,
+                pAllocations);
+            if(res == VK_SUCCESS)
+            {
+                // Succeeded: AllocateDedicatedMemory function already filld pMemory, nothing more to do here.
+                VMA_DEBUG_LOG("    Allocated as DedicatedMemory");
+                return VK_SUCCESS;
+            }
+            else
+            {
+                // Everything failed: Return error code.
+                VMA_DEBUG_LOG("    vkAllocateMemory FAILED");
+                return res;
+            }
+        }
+    }
+}
+
+VkResult VmaAllocator_T::AllocateDedicatedMemory(
+    VkDeviceSize size,
+    VmaSuballocationType suballocType,
+    uint32_t memTypeIndex,
+    bool withinBudget,
+    bool map,
+    bool isUserDataString,
+    void* pUserData,
+    VkBuffer dedicatedBuffer,
+    VkBufferUsageFlags dedicatedBufferUsage,
+    VkImage dedicatedImage,
+    size_t allocationCount,
+    VmaAllocation* pAllocations)
+{
+    VMA_ASSERT(allocationCount > 0 && pAllocations);
+
+    if(withinBudget)
+    {
+        const uint32_t heapIndex = MemoryTypeIndexToHeapIndex(memTypeIndex);
+        VmaBudget heapBudget = {};
+        GetBudget(&heapBudget, heapIndex, 1);
+        if(heapBudget.usage + size * allocationCount > heapBudget.budget)
+        {
+            return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+        }
+    }
+
+    VkMemoryAllocateInfo allocInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
+    allocInfo.memoryTypeIndex = memTypeIndex;
+    allocInfo.allocationSize = size;
+
+#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000
+    VkMemoryDedicatedAllocateInfoKHR dedicatedAllocInfo = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR };
+    if(m_UseKhrDedicatedAllocation || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))
+    {
+        if(dedicatedBuffer != VK_NULL_HANDLE)
+        {
+            VMA_ASSERT(dedicatedImage == VK_NULL_HANDLE);
+            dedicatedAllocInfo.buffer = dedicatedBuffer;
+            VmaPnextChainPushFront(&allocInfo, &dedicatedAllocInfo);
+        }
+        else if(dedicatedImage != VK_NULL_HANDLE)
+        {
+            dedicatedAllocInfo.image = dedicatedImage;
+            VmaPnextChainPushFront(&allocInfo, &dedicatedAllocInfo);
+        }
+    }
+#endif // #if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000
+
+#if VMA_BUFFER_DEVICE_ADDRESS
+    VkMemoryAllocateFlagsInfoKHR allocFlagsInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO_KHR };
+    if(m_UseKhrBufferDeviceAddress)
+    {
+        bool canContainBufferWithDeviceAddress = true;
+        if(dedicatedBuffer != VK_NULL_HANDLE)
+        {
+            canContainBufferWithDeviceAddress = dedicatedBufferUsage == UINT32_MAX || // Usage flags unknown
+                (dedicatedBufferUsage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_EXT) != 0;
+        }
+        else if(dedicatedImage != VK_NULL_HANDLE)
+        {
+            canContainBufferWithDeviceAddress = false;
+        }
+        if(canContainBufferWithDeviceAddress)
+        {
+            allocFlagsInfo.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR;
+            VmaPnextChainPushFront(&allocInfo, &allocFlagsInfo);
+        }
+    }
+#endif // #if VMA_BUFFER_DEVICE_ADDRESS
+
+    size_t allocIndex;
+    VkResult res = VK_SUCCESS;
+    for(allocIndex = 0; allocIndex < allocationCount; ++allocIndex)
+    {
+        res = AllocateDedicatedMemoryPage(
+            size,
+            suballocType,
+            memTypeIndex,
+            allocInfo,
+            map,
+            isUserDataString,
+            pUserData,
+            pAllocations + allocIndex);
+        if(res != VK_SUCCESS)
+        {
+            break;
+        }
+    }
+
+    if(res == VK_SUCCESS)
+    {
+        // Register them in m_pDedicatedAllocations.
+        {
+            VmaMutexLockWrite lock(m_DedicatedAllocationsMutex[memTypeIndex], m_UseMutex);
+            AllocationVectorType* pDedicatedAllocations = m_pDedicatedAllocations[memTypeIndex];
+            VMA_ASSERT(pDedicatedAllocations);
+            for(allocIndex = 0; allocIndex < allocationCount; ++allocIndex)
+            {
+                VmaVectorInsertSorted<VmaPointerLess>(*pDedicatedAllocations, pAllocations[allocIndex]);
+            }
+        }
+
+        VMA_DEBUG_LOG("    Allocated DedicatedMemory Count=%zu, MemoryTypeIndex=#%u", allocationCount, memTypeIndex);
+    }
+    else
+    {
+        // Free all already created allocations.
+        while(allocIndex--)
+        {
+            VmaAllocation currAlloc = pAllocations[allocIndex];
+            VkDeviceMemory hMemory = currAlloc->GetMemory();
+    
+            /*
+            There is no need to call this, because Vulkan spec allows to skip vkUnmapMemory
+            before vkFreeMemory.
+
+            if(currAlloc->GetMappedData() != VMA_NULL)
+            {
+                (*m_VulkanFunctions.vkUnmapMemory)(m_hDevice, hMemory);
+            }
+            */
+    
+            FreeVulkanMemory(memTypeIndex, currAlloc->GetSize(), hMemory);
+            m_Budget.RemoveAllocation(MemoryTypeIndexToHeapIndex(memTypeIndex), currAlloc->GetSize());
+            currAlloc->SetUserData(this, VMA_NULL);
+            m_AllocationObjectAllocator.Free(currAlloc);
+        }
+
+        memset(pAllocations, 0, sizeof(VmaAllocation) * allocationCount);
+    }
+
+    return res;
+}
+
+VkResult VmaAllocator_T::AllocateDedicatedMemoryPage(
+    VkDeviceSize size,
+    VmaSuballocationType suballocType,
+    uint32_t memTypeIndex,
+    const VkMemoryAllocateInfo& allocInfo,
+    bool map,
+    bool isUserDataString,
+    void* pUserData,
+    VmaAllocation* pAllocation)
+{
+    VkDeviceMemory hMemory = VK_NULL_HANDLE;
+    VkResult res = AllocateVulkanMemory(&allocInfo, &hMemory);
+    if(res < 0)
+    {
+        VMA_DEBUG_LOG("    vkAllocateMemory FAILED");
+        return res;
+    }
+
+    void* pMappedData = VMA_NULL;
+    if(map)
+    {
+        res = (*m_VulkanFunctions.vkMapMemory)(
+            m_hDevice,
+            hMemory,
+            0,
+            VK_WHOLE_SIZE,
+            0,
+            &pMappedData);
+        if(res < 0)
+        {
+            VMA_DEBUG_LOG("    vkMapMemory FAILED");
+            FreeVulkanMemory(memTypeIndex, size, hMemory);
+            return res;
+        }
+    }
+
+    *pAllocation = m_AllocationObjectAllocator.Allocate(m_CurrentFrameIndex.load(), isUserDataString);
+    (*pAllocation)->InitDedicatedAllocation(memTypeIndex, hMemory, suballocType, pMappedData, size);
+    (*pAllocation)->SetUserData(this, pUserData);
+    m_Budget.AddAllocation(MemoryTypeIndexToHeapIndex(memTypeIndex), size);
+    if(VMA_DEBUG_INITIALIZE_ALLOCATIONS)
+    {
+        FillAllocation(*pAllocation, VMA_ALLOCATION_FILL_PATTERN_CREATED);
+    }
+
+    return VK_SUCCESS;
+}
+
+void VmaAllocator_T::GetBufferMemoryRequirements(
+    VkBuffer hBuffer,
+    VkMemoryRequirements& memReq,
+    bool& requiresDedicatedAllocation,
+    bool& prefersDedicatedAllocation) const
+{
+#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000
+    if(m_UseKhrDedicatedAllocation || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))
+    {
+        VkBufferMemoryRequirementsInfo2KHR memReqInfo = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR };
+        memReqInfo.buffer = hBuffer;
+
+        VkMemoryDedicatedRequirementsKHR memDedicatedReq = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR };
+
+        VkMemoryRequirements2KHR memReq2 = { VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR };
+        VmaPnextChainPushFront(&memReq2, &memDedicatedReq);
+
+        (*m_VulkanFunctions.vkGetBufferMemoryRequirements2KHR)(m_hDevice, &memReqInfo, &memReq2);
+
+        memReq = memReq2.memoryRequirements;
+        requiresDedicatedAllocation = (memDedicatedReq.requiresDedicatedAllocation != VK_FALSE);
+        prefersDedicatedAllocation  = (memDedicatedReq.prefersDedicatedAllocation  != VK_FALSE);
+    }
+    else
+#endif // #if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000
+    {
+        (*m_VulkanFunctions.vkGetBufferMemoryRequirements)(m_hDevice, hBuffer, &memReq);
+        requiresDedicatedAllocation = false;
+        prefersDedicatedAllocation  = false;
+    }
+}
+
+void VmaAllocator_T::GetImageMemoryRequirements(
+    VkImage hImage,
+    VkMemoryRequirements& memReq,
+    bool& requiresDedicatedAllocation,
+    bool& prefersDedicatedAllocation) const
+{
+#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000
+    if(m_UseKhrDedicatedAllocation || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))
+    {
+        VkImageMemoryRequirementsInfo2KHR memReqInfo = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR };
+        memReqInfo.image = hImage;
+
+        VkMemoryDedicatedRequirementsKHR memDedicatedReq = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR };
+
+        VkMemoryRequirements2KHR memReq2 = { VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR };
+        VmaPnextChainPushFront(&memReq2, &memDedicatedReq);
+
+        (*m_VulkanFunctions.vkGetImageMemoryRequirements2KHR)(m_hDevice, &memReqInfo, &memReq2);
+
+        memReq = memReq2.memoryRequirements;
+        requiresDedicatedAllocation = (memDedicatedReq.requiresDedicatedAllocation != VK_FALSE);
+        prefersDedicatedAllocation  = (memDedicatedReq.prefersDedicatedAllocation  != VK_FALSE);
+    }
+    else
+#endif // #if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000
+    {
+        (*m_VulkanFunctions.vkGetImageMemoryRequirements)(m_hDevice, hImage, &memReq);
+        requiresDedicatedAllocation = false;
+        prefersDedicatedAllocation  = false;
+    }
+}
+
+VkResult VmaAllocator_T::AllocateMemory(
+    const VkMemoryRequirements& vkMemReq,
+    bool requiresDedicatedAllocation,
+    bool prefersDedicatedAllocation,
+    VkBuffer dedicatedBuffer,
+    VkBufferUsageFlags dedicatedBufferUsage,
+    VkImage dedicatedImage,
+    const VmaAllocationCreateInfo& createInfo,
+    VmaSuballocationType suballocType,
+    size_t allocationCount,
+    VmaAllocation* pAllocations)
+{
+    memset(pAllocations, 0, sizeof(VmaAllocation) * allocationCount);
+
+    VMA_ASSERT(VmaIsPow2(vkMemReq.alignment));
+
+    if(vkMemReq.size == 0)
+    {
+        return VK_ERROR_VALIDATION_FAILED_EXT;
+    }
+    if((createInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0 &&
+        (createInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) != 0)
+    {
+        VMA_ASSERT(0 && "Specifying VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT together with VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT makes no sense.");
+        return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+    }
+    if((createInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0 &&
+        (createInfo.flags & VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT) != 0)
+    {
+        VMA_ASSERT(0 && "Specifying VMA_ALLOCATION_CREATE_MAPPED_BIT together with VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT is invalid.");
+        return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+    }
+    if(requiresDedicatedAllocation)
+    {
+        if((createInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) != 0)
+        {
+            VMA_ASSERT(0 && "VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT specified while dedicated allocation is required.");
+            return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+        }
+        if(createInfo.pool != VK_NULL_HANDLE)
+        {
+            VMA_ASSERT(0 && "Pool specified while dedicated allocation is required.");
+            return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+        }
+    }
+    if((createInfo.pool != VK_NULL_HANDLE) &&
+        ((createInfo.flags & (VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT)) != 0))
+    {
+        VMA_ASSERT(0 && "Specifying VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT when pool != null is invalid.");
+        return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+    }
+
+    if(createInfo.pool != VK_NULL_HANDLE)
+    {
+        const VkDeviceSize alignmentForPool = VMA_MAX(
+            vkMemReq.alignment,
+            GetMemoryTypeMinAlignment(createInfo.pool->m_BlockVector.GetMemoryTypeIndex()));
+
+        VmaAllocationCreateInfo createInfoForPool = createInfo;
+        // If memory type is not HOST_VISIBLE, disable MAPPED.
+        if((createInfoForPool.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0 &&
+            (m_MemProps.memoryTypes[createInfo.pool->m_BlockVector.GetMemoryTypeIndex()].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0)
+        {
+            createInfoForPool.flags &= ~VMA_ALLOCATION_CREATE_MAPPED_BIT;
+        }
+
+        return createInfo.pool->m_BlockVector.Allocate(
+            m_CurrentFrameIndex.load(),
+            vkMemReq.size,
+            alignmentForPool,
+            createInfoForPool,
+            suballocType,
+            allocationCount,
+            pAllocations);
+    }
+    else
+    {
+        // Bit mask of memory Vulkan types acceptable for this allocation.
+        uint32_t memoryTypeBits = vkMemReq.memoryTypeBits;
+        uint32_t memTypeIndex = UINT32_MAX;
+        VkResult res = vmaFindMemoryTypeIndex(this, memoryTypeBits, &createInfo, &memTypeIndex);
+        if(res == VK_SUCCESS)
+        {
+            VkDeviceSize alignmentForMemType = VMA_MAX(
+                vkMemReq.alignment,
+                GetMemoryTypeMinAlignment(memTypeIndex));
+
+            res = AllocateMemoryOfType(
+                vkMemReq.size,
+                alignmentForMemType,
+                requiresDedicatedAllocation || prefersDedicatedAllocation,
+                dedicatedBuffer,
+                dedicatedBufferUsage,
+                dedicatedImage,
+                createInfo,
+                memTypeIndex,
+                suballocType,
+                allocationCount,
+                pAllocations);
+            // Succeeded on first try.
+            if(res == VK_SUCCESS)
+            {
+                return res;
+            }
+            // Allocation from this memory type failed. Try other compatible memory types.
+            else
+            {
+                for(;;)
+                {
+                    // Remove old memTypeIndex from list of possibilities.
+                    memoryTypeBits &= ~(1u << memTypeIndex);
+                    // Find alternative memTypeIndex.
+                    res = vmaFindMemoryTypeIndex(this, memoryTypeBits, &createInfo, &memTypeIndex);
+                    if(res == VK_SUCCESS)
+                    {
+                        alignmentForMemType = VMA_MAX(
+                            vkMemReq.alignment,
+                            GetMemoryTypeMinAlignment(memTypeIndex));
+                        
+                        res = AllocateMemoryOfType(
+                            vkMemReq.size,
+                            alignmentForMemType,
+                            requiresDedicatedAllocation || prefersDedicatedAllocation,
+                            dedicatedBuffer,
+                            dedicatedBufferUsage,
+                            dedicatedImage,
+                            createInfo,
+                            memTypeIndex,
+                            suballocType,
+                            allocationCount,
+                            pAllocations);
+                        // Allocation from this alternative memory type succeeded.
+                        if(res == VK_SUCCESS)
+                        {
+                            return res;
+                        }
+                        // else: Allocation from this memory type failed. Try next one - next loop iteration.
+                    }
+                    // No other matching memory type index could be found.
+                    else
+                    {
+                        // Not returning res, which is VK_ERROR_FEATURE_NOT_PRESENT, because we already failed to allocate once.
+                        return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+                    }
+                }
+            }
+        }
+        // Can't find any single memory type maching requirements. res is VK_ERROR_FEATURE_NOT_PRESENT.
+        else
+            return res;
+    }
+}
+
+void VmaAllocator_T::FreeMemory(
+    size_t allocationCount,
+    const VmaAllocation* pAllocations)
+{
+    VMA_ASSERT(pAllocations);
+
+    for(size_t allocIndex = allocationCount; allocIndex--; )
+    {
+        VmaAllocation allocation = pAllocations[allocIndex];
+
+        if(allocation != VK_NULL_HANDLE)
+        {
+            if(TouchAllocation(allocation))
+            {
+                if(VMA_DEBUG_INITIALIZE_ALLOCATIONS)
+                {
+                    FillAllocation(allocation, VMA_ALLOCATION_FILL_PATTERN_DESTROYED);
+                }
+
+                switch(allocation->GetType())
+                {
+                case VmaAllocation_T::ALLOCATION_TYPE_BLOCK:
+                    {
+                        VmaBlockVector* pBlockVector = VMA_NULL;
+                        VmaPool hPool = allocation->GetBlock()->GetParentPool();
+                        if(hPool != VK_NULL_HANDLE)
+                        {
+                            pBlockVector = &hPool->m_BlockVector;
+                        }
+                        else
+                        {
+                            const uint32_t memTypeIndex = allocation->GetMemoryTypeIndex();
+                            pBlockVector = m_pBlockVectors[memTypeIndex];
+                        }
+                        pBlockVector->Free(allocation);
+                    }
+                    break;
+                case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED:
+                    FreeDedicatedMemory(allocation);
+                    break;
+                default:
+                    VMA_ASSERT(0);
+                }
+            }
+
+            // Do this regardless of whether the allocation is lost. Lost allocations still account to Budget.AllocationBytes.
+            m_Budget.RemoveAllocation(MemoryTypeIndexToHeapIndex(allocation->GetMemoryTypeIndex()), allocation->GetSize());
+            allocation->SetUserData(this, VMA_NULL);
+            m_AllocationObjectAllocator.Free(allocation);
+        }
+    }
+}
+
+VkResult VmaAllocator_T::ResizeAllocation(
+    const VmaAllocation alloc,
+    VkDeviceSize newSize)
+{
+    // This function is deprecated and so it does nothing. It's left for backward compatibility.
+    if(newSize == 0 || alloc->GetLastUseFrameIndex() == VMA_FRAME_INDEX_LOST)
+    {
+        return VK_ERROR_VALIDATION_FAILED_EXT;
+    }
+    if(newSize == alloc->GetSize())
+    {
+        return VK_SUCCESS;
+    }
+    return VK_ERROR_OUT_OF_POOL_MEMORY;
+}
+
+void VmaAllocator_T::CalculateStats(VmaStats* pStats)
+{
+    // Initialize.
+    InitStatInfo(pStats->total);
+    for(size_t i = 0; i < VK_MAX_MEMORY_TYPES; ++i)
+        InitStatInfo(pStats->memoryType[i]);
+    for(size_t i = 0; i < VK_MAX_MEMORY_HEAPS; ++i)
+        InitStatInfo(pStats->memoryHeap[i]);
+    
+    // Process default pools.
+    for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
+    {
+        VmaBlockVector* const pBlockVector = m_pBlockVectors[memTypeIndex];
+        VMA_ASSERT(pBlockVector);
+        pBlockVector->AddStats(pStats);
+    }
+
+    // Process custom pools.
+    {
+        VmaMutexLockRead lock(m_PoolsMutex, m_UseMutex);
+        for(size_t poolIndex = 0, poolCount = m_Pools.size(); poolIndex < poolCount; ++poolIndex)
+        {
+            m_Pools[poolIndex]->m_BlockVector.AddStats(pStats);
+        }
+    }
+
+    // Process dedicated allocations.
+    for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
+    {
+        const uint32_t memHeapIndex = MemoryTypeIndexToHeapIndex(memTypeIndex);
+        VmaMutexLockRead dedicatedAllocationsLock(m_DedicatedAllocationsMutex[memTypeIndex], m_UseMutex);
+        AllocationVectorType* const pDedicatedAllocVector = m_pDedicatedAllocations[memTypeIndex];
+        VMA_ASSERT(pDedicatedAllocVector);
+        for(size_t allocIndex = 0, allocCount = pDedicatedAllocVector->size(); allocIndex < allocCount; ++allocIndex)
+        {
+            VmaStatInfo allocationStatInfo;
+            (*pDedicatedAllocVector)[allocIndex]->DedicatedAllocCalcStatsInfo(allocationStatInfo);
+            VmaAddStatInfo(pStats->total, allocationStatInfo);
+            VmaAddStatInfo(pStats->memoryType[memTypeIndex], allocationStatInfo);
+            VmaAddStatInfo(pStats->memoryHeap[memHeapIndex], allocationStatInfo);
+        }
+    }
+
+    // Postprocess.
+    VmaPostprocessCalcStatInfo(pStats->total);
+    for(size_t i = 0; i < GetMemoryTypeCount(); ++i)
+        VmaPostprocessCalcStatInfo(pStats->memoryType[i]);
+    for(size_t i = 0; i < GetMemoryHeapCount(); ++i)
+        VmaPostprocessCalcStatInfo(pStats->memoryHeap[i]);
+}
+
+void VmaAllocator_T::GetBudget(VmaBudget* outBudget, uint32_t firstHeap, uint32_t heapCount)
+{
+#if VMA_MEMORY_BUDGET
+    if(m_UseExtMemoryBudget)
+    {
+        if(m_Budget.m_OperationsSinceBudgetFetch < 30)
+        {
+            VmaMutexLockRead lockRead(m_Budget.m_BudgetMutex, m_UseMutex);
+            for(uint32_t i = 0; i < heapCount; ++i, ++outBudget)
+            {
+                const uint32_t heapIndex = firstHeap + i;
+
+                outBudget->blockBytes = m_Budget.m_BlockBytes[heapIndex];
+                outBudget->allocationBytes = m_Budget.m_AllocationBytes[heapIndex];
+
+                if(m_Budget.m_VulkanUsage[heapIndex] + outBudget->blockBytes > m_Budget.m_BlockBytesAtBudgetFetch[heapIndex])
+                {
+                    outBudget->usage = m_Budget.m_VulkanUsage[heapIndex] +
+                        outBudget->blockBytes - m_Budget.m_BlockBytesAtBudgetFetch[heapIndex];
+                }
+                else
+                {
+                    outBudget->usage = 0;
+                }
+
+                // Have to take MIN with heap size because explicit HeapSizeLimit is included in it.
+                outBudget->budget = VMA_MIN(
+                    m_Budget.m_VulkanBudget[heapIndex], m_MemProps.memoryHeaps[heapIndex].size);
+            }
+        }
+        else
+        {
+            UpdateVulkanBudget(); // Outside of mutex lock
+            GetBudget(outBudget, firstHeap, heapCount); // Recursion
+        }
+    }
+    else
+#endif
+    {
+        for(uint32_t i = 0; i < heapCount; ++i, ++outBudget)
+        {
+            const uint32_t heapIndex = firstHeap + i;
+
+            outBudget->blockBytes = m_Budget.m_BlockBytes[heapIndex];
+            outBudget->allocationBytes = m_Budget.m_AllocationBytes[heapIndex];
+
+            outBudget->usage = outBudget->blockBytes;
+            outBudget->budget = m_MemProps.memoryHeaps[heapIndex].size * 8 / 10; // 80% heuristics.
+        }
+    }
+}
+
+static const uint32_t VMA_VENDOR_ID_AMD = 4098;
+
+VkResult VmaAllocator_T::DefragmentationBegin(
+    const VmaDefragmentationInfo2& info,
+    VmaDefragmentationStats* pStats,
+    VmaDefragmentationContext* pContext)
+{
+    if(info.pAllocationsChanged != VMA_NULL)
+    {
+        memset(info.pAllocationsChanged, 0, info.allocationCount * sizeof(VkBool32));
+    }
+
+    *pContext = vma_new(this, VmaDefragmentationContext_T)(
+        this, m_CurrentFrameIndex.load(), info.flags, pStats);
+
+    (*pContext)->AddPools(info.poolCount, info.pPools);
+    (*pContext)->AddAllocations(
+        info.allocationCount, info.pAllocations, info.pAllocationsChanged);
+
+    VkResult res = (*pContext)->Defragment(
+        info.maxCpuBytesToMove, info.maxCpuAllocationsToMove,
+        info.maxGpuBytesToMove, info.maxGpuAllocationsToMove,
+        info.commandBuffer, pStats, info.flags);
+
+    if(res != VK_NOT_READY)
+    {
+        vma_delete(this, *pContext);
+        *pContext = VMA_NULL;
+    }
+
+    return res;
+}
+
+VkResult VmaAllocator_T::DefragmentationEnd(
+    VmaDefragmentationContext context)
+{
+    vma_delete(this, context);
+    return VK_SUCCESS;
+}
+
+VkResult VmaAllocator_T::DefragmentationPassBegin(
+    VmaDefragmentationPassInfo* pInfo,
+    VmaDefragmentationContext context)
+{
+    return context->DefragmentPassBegin(pInfo);
+}
+VkResult VmaAllocator_T::DefragmentationPassEnd(
+    VmaDefragmentationContext context)
+{
+    return context->DefragmentPassEnd();
+    
+}
+
+void VmaAllocator_T::GetAllocationInfo(VmaAllocation hAllocation, VmaAllocationInfo* pAllocationInfo)
+{
+    if(hAllocation->CanBecomeLost())
+    {
+        /*
+        Warning: This is a carefully designed algorithm.
+        Do not modify unless you really know what you're doing :)
+        */
+        const uint32_t localCurrFrameIndex = m_CurrentFrameIndex.load();
+        uint32_t localLastUseFrameIndex = hAllocation->GetLastUseFrameIndex();
+        for(;;)
+        {
+            if(localLastUseFrameIndex == VMA_FRAME_INDEX_LOST)
+            {
+                pAllocationInfo->memoryType = UINT32_MAX;
+                pAllocationInfo->deviceMemory = VK_NULL_HANDLE;
+                pAllocationInfo->offset = 0;
+                pAllocationInfo->size = hAllocation->GetSize();
+                pAllocationInfo->pMappedData = VMA_NULL;
+                pAllocationInfo->pUserData = hAllocation->GetUserData();
+                return;
+            }
+            else if(localLastUseFrameIndex == localCurrFrameIndex)
+            {
+                pAllocationInfo->memoryType = hAllocation->GetMemoryTypeIndex();
+                pAllocationInfo->deviceMemory = hAllocation->GetMemory();
+                pAllocationInfo->offset = hAllocation->GetOffset();
+                pAllocationInfo->size = hAllocation->GetSize();
+                pAllocationInfo->pMappedData = VMA_NULL;
+                pAllocationInfo->pUserData = hAllocation->GetUserData();
+                return;
+            }
+            else // Last use time earlier than current time.
+            {
+                if(hAllocation->CompareExchangeLastUseFrameIndex(localLastUseFrameIndex, localCurrFrameIndex))
+                {
+                    localLastUseFrameIndex = localCurrFrameIndex;
+                }
+            }
+        }
+    }
+    else
+    {
+#if VMA_STATS_STRING_ENABLED
+        uint32_t localCurrFrameIndex = m_CurrentFrameIndex.load();
+        uint32_t localLastUseFrameIndex = hAllocation->GetLastUseFrameIndex();
+        for(;;)
+        {
+            VMA_ASSERT(localLastUseFrameIndex != VMA_FRAME_INDEX_LOST);
+            if(localLastUseFrameIndex == localCurrFrameIndex)
+            {
+                break;
+            }
+            else // Last use time earlier than current time.
+            {
+                if(hAllocation->CompareExchangeLastUseFrameIndex(localLastUseFrameIndex, localCurrFrameIndex))
+                {
+                    localLastUseFrameIndex = localCurrFrameIndex;
+                }
+            }
+        }
+#endif
+
+        pAllocationInfo->memoryType = hAllocation->GetMemoryTypeIndex();
+        pAllocationInfo->deviceMemory = hAllocation->GetMemory();
+        pAllocationInfo->offset = hAllocation->GetOffset();
+        pAllocationInfo->size = hAllocation->GetSize();
+        pAllocationInfo->pMappedData = hAllocation->GetMappedData();
+        pAllocationInfo->pUserData = hAllocation->GetUserData();
+    }
+}
+
+bool VmaAllocator_T::TouchAllocation(VmaAllocation hAllocation)
+{
+    // This is a stripped-down version of VmaAllocator_T::GetAllocationInfo.
+    if(hAllocation->CanBecomeLost())
+    {
+        uint32_t localCurrFrameIndex = m_CurrentFrameIndex.load();
+        uint32_t localLastUseFrameIndex = hAllocation->GetLastUseFrameIndex();
+        for(;;)
+        {
+            if(localLastUseFrameIndex == VMA_FRAME_INDEX_LOST)
+            {
+                return false;
+            }
+            else if(localLastUseFrameIndex == localCurrFrameIndex)
+            {
+                return true;
+            }
+            else // Last use time earlier than current time.
+            {
+                if(hAllocation->CompareExchangeLastUseFrameIndex(localLastUseFrameIndex, localCurrFrameIndex))
+                {
+                    localLastUseFrameIndex = localCurrFrameIndex;
+                }
+            }
+        }
+    }
+    else
+    {
+#if VMA_STATS_STRING_ENABLED
+        uint32_t localCurrFrameIndex = m_CurrentFrameIndex.load();
+        uint32_t localLastUseFrameIndex = hAllocation->GetLastUseFrameIndex();
+        for(;;)
+        {
+            VMA_ASSERT(localLastUseFrameIndex != VMA_FRAME_INDEX_LOST);
+            if(localLastUseFrameIndex == localCurrFrameIndex)
+            {
+                break;
+            }
+            else // Last use time earlier than current time.
+            {
+                if(hAllocation->CompareExchangeLastUseFrameIndex(localLastUseFrameIndex, localCurrFrameIndex))
+                {
+                    localLastUseFrameIndex = localCurrFrameIndex;
+                }
+            }
+        }
+#endif
+
+        return true;
+    }
+}
+
+VkResult VmaAllocator_T::CreatePool(const VmaPoolCreateInfo* pCreateInfo, VmaPool* pPool)
+{
+    VMA_DEBUG_LOG("  CreatePool: MemoryTypeIndex=%u, flags=%u", pCreateInfo->memoryTypeIndex, pCreateInfo->flags);
+
+    VmaPoolCreateInfo newCreateInfo = *pCreateInfo;
+
+    if(newCreateInfo.maxBlockCount == 0)
+    {
+        newCreateInfo.maxBlockCount = SIZE_MAX;
+    }
+    if(newCreateInfo.minBlockCount > newCreateInfo.maxBlockCount)
+    {
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+    // Memory type index out of range or forbidden.
+    if(pCreateInfo->memoryTypeIndex >= GetMemoryTypeCount() ||
+        ((1u << pCreateInfo->memoryTypeIndex) & m_GlobalMemoryTypeBits) == 0)
+    {
+        return VK_ERROR_FEATURE_NOT_PRESENT;
+    }
+
+    const VkDeviceSize preferredBlockSize = CalcPreferredBlockSize(newCreateInfo.memoryTypeIndex);
+
+    *pPool = vma_new(this, VmaPool_T)(this, newCreateInfo, preferredBlockSize);
+
+    VkResult res = (*pPool)->m_BlockVector.CreateMinBlocks();
+    if(res != VK_SUCCESS)
+    {
+        vma_delete(this, *pPool);
+        *pPool = VMA_NULL;
+        return res;
+    }
+
+    // Add to m_Pools.
+    {
+        VmaMutexLockWrite lock(m_PoolsMutex, m_UseMutex);
+        (*pPool)->SetId(m_NextPoolId++);
+        VmaVectorInsertSorted<VmaPointerLess>(m_Pools, *pPool);
+    }
+
+    return VK_SUCCESS;
+}
+
+void VmaAllocator_T::DestroyPool(VmaPool pool)
+{
+    // Remove from m_Pools.
+    {
+        VmaMutexLockWrite lock(m_PoolsMutex, m_UseMutex);
+        bool success = VmaVectorRemoveSorted<VmaPointerLess>(m_Pools, pool);
+        VMA_ASSERT(success && "Pool not found in Allocator.");
+    }
+
+    vma_delete(this, pool);
+}
+
+void VmaAllocator_T::GetPoolStats(VmaPool pool, VmaPoolStats* pPoolStats)
+{
+    pool->m_BlockVector.GetPoolStats(pPoolStats);
+}
+
+void VmaAllocator_T::SetCurrentFrameIndex(uint32_t frameIndex)
+{
+    m_CurrentFrameIndex.store(frameIndex);
+
+#if VMA_MEMORY_BUDGET
+    if(m_UseExtMemoryBudget)
+    {
+        UpdateVulkanBudget();
+    }
+#endif // #if VMA_MEMORY_BUDGET
+}
+
+void VmaAllocator_T::MakePoolAllocationsLost(
+    VmaPool hPool,
+    size_t* pLostAllocationCount)
+{
+    hPool->m_BlockVector.MakePoolAllocationsLost(
+        m_CurrentFrameIndex.load(),
+        pLostAllocationCount);
+}
+
+VkResult VmaAllocator_T::CheckPoolCorruption(VmaPool hPool)
+{
+    return hPool->m_BlockVector.CheckCorruption();
+}
+
+VkResult VmaAllocator_T::CheckCorruption(uint32_t memoryTypeBits)
+{
+    VkResult finalRes = VK_ERROR_FEATURE_NOT_PRESENT;
+
+    // Process default pools.
+    for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
+    {
+        if(((1u << memTypeIndex) & memoryTypeBits) != 0)
+        {
+            VmaBlockVector* const pBlockVector = m_pBlockVectors[memTypeIndex];
+            VMA_ASSERT(pBlockVector);
+            VkResult localRes = pBlockVector->CheckCorruption();
+            switch(localRes)
+            {
+            case VK_ERROR_FEATURE_NOT_PRESENT:
+                break;
+            case VK_SUCCESS:
+                finalRes = VK_SUCCESS;
+                break;
+            default:
+                return localRes;
+            }
+        }
+    }
+
+    // Process custom pools.
+    {
+        VmaMutexLockRead lock(m_PoolsMutex, m_UseMutex);
+        for(size_t poolIndex = 0, poolCount = m_Pools.size(); poolIndex < poolCount; ++poolIndex)
+        {
+            if(((1u << m_Pools[poolIndex]->m_BlockVector.GetMemoryTypeIndex()) & memoryTypeBits) != 0)
+            {
+                VkResult localRes = m_Pools[poolIndex]->m_BlockVector.CheckCorruption();
+                switch(localRes)
+                {
+                case VK_ERROR_FEATURE_NOT_PRESENT:
+                    break;
+                case VK_SUCCESS:
+                    finalRes = VK_SUCCESS;
+                    break;
+                default:
+                    return localRes;
+                }
+            }
+        }
+    }
+
+    return finalRes;
+}
+
+void VmaAllocator_T::CreateLostAllocation(VmaAllocation* pAllocation)
+{
+    *pAllocation = m_AllocationObjectAllocator.Allocate(VMA_FRAME_INDEX_LOST, false);
+    (*pAllocation)->InitLost();
+}
+
+VkResult VmaAllocator_T::AllocateVulkanMemory(const VkMemoryAllocateInfo* pAllocateInfo, VkDeviceMemory* pMemory)
+{
+    const uint32_t heapIndex = MemoryTypeIndexToHeapIndex(pAllocateInfo->memoryTypeIndex);
+
+    // HeapSizeLimit is in effect for this heap.
+    if((m_HeapSizeLimitMask & (1u << heapIndex)) != 0)
+    {
+        const VkDeviceSize heapSize = m_MemProps.memoryHeaps[heapIndex].size;
+        VkDeviceSize blockBytes = m_Budget.m_BlockBytes[heapIndex];
+        for(;;)
+        {
+            const VkDeviceSize blockBytesAfterAllocation = blockBytes + pAllocateInfo->allocationSize;
+            if(blockBytesAfterAllocation > heapSize)
+            {
+                return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+            }
+            if(m_Budget.m_BlockBytes[heapIndex].compare_exchange_strong(blockBytes, blockBytesAfterAllocation))
+            {
+                break;
+            }
+        }
+    }
+    else
+    {
+        m_Budget.m_BlockBytes[heapIndex] += pAllocateInfo->allocationSize;
+    }
+
+    // VULKAN CALL vkAllocateMemory.
+    VkResult res = (*m_VulkanFunctions.vkAllocateMemory)(m_hDevice, pAllocateInfo, GetAllocationCallbacks(), pMemory);
+
+    if(res == VK_SUCCESS)
+    {
+#if VMA_MEMORY_BUDGET
+        ++m_Budget.m_OperationsSinceBudgetFetch;
+#endif
+
+        // Informative callback.
+        if(m_DeviceMemoryCallbacks.pfnAllocate != VMA_NULL)
+        {
+            (*m_DeviceMemoryCallbacks.pfnAllocate)(this, pAllocateInfo->memoryTypeIndex, *pMemory, pAllocateInfo->allocationSize, m_DeviceMemoryCallbacks.pUserData);
+        }
+    }
+    else
+    {
+        m_Budget.m_BlockBytes[heapIndex] -= pAllocateInfo->allocationSize;
+    }
+
+    return res;
+}
+
+void VmaAllocator_T::FreeVulkanMemory(uint32_t memoryType, VkDeviceSize size, VkDeviceMemory hMemory)
+{
+    // Informative callback.
+    if(m_DeviceMemoryCallbacks.pfnFree != VMA_NULL)
+    {
+        (*m_DeviceMemoryCallbacks.pfnFree)(this, memoryType, hMemory, size, m_DeviceMemoryCallbacks.pUserData);
+    }
+
+    // VULKAN CALL vkFreeMemory.
+    (*m_VulkanFunctions.vkFreeMemory)(m_hDevice, hMemory, GetAllocationCallbacks());
+
+    m_Budget.m_BlockBytes[MemoryTypeIndexToHeapIndex(memoryType)] -= size;
+}
+
+VkResult VmaAllocator_T::BindVulkanBuffer(
+    VkDeviceMemory memory,
+    VkDeviceSize memoryOffset,
+    VkBuffer buffer,
+    const void* pNext)
+{
+    if(pNext != VMA_NULL)
+    {
+#if VMA_VULKAN_VERSION >= 1001000 || VMA_BIND_MEMORY2
+        if((m_UseKhrBindMemory2 || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) &&
+            m_VulkanFunctions.vkBindBufferMemory2KHR != VMA_NULL)
+        {
+            VkBindBufferMemoryInfoKHR bindBufferMemoryInfo = { VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO_KHR };
+            bindBufferMemoryInfo.pNext = pNext;
+            bindBufferMemoryInfo.buffer = buffer;
+            bindBufferMemoryInfo.memory = memory;
+            bindBufferMemoryInfo.memoryOffset = memoryOffset;
+            return (*m_VulkanFunctions.vkBindBufferMemory2KHR)(m_hDevice, 1, &bindBufferMemoryInfo);
+        }
+        else
+#endif // #if VMA_VULKAN_VERSION >= 1001000 || VMA_BIND_MEMORY2
+        {
+            return VK_ERROR_EXTENSION_NOT_PRESENT;
+        }
+    }
+    else
+    {
+        return (*m_VulkanFunctions.vkBindBufferMemory)(m_hDevice, buffer, memory, memoryOffset);
+    }
+}
+
+VkResult VmaAllocator_T::BindVulkanImage(
+    VkDeviceMemory memory,
+    VkDeviceSize memoryOffset,
+    VkImage image,
+    const void* pNext)
+{
+    if(pNext != VMA_NULL)
+    {
+#if VMA_VULKAN_VERSION >= 1001000 || VMA_BIND_MEMORY2
+        if((m_UseKhrBindMemory2 || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0)) &&
+            m_VulkanFunctions.vkBindImageMemory2KHR != VMA_NULL)
+        {
+            VkBindImageMemoryInfoKHR bindBufferMemoryInfo = { VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO_KHR };
+            bindBufferMemoryInfo.pNext = pNext;
+            bindBufferMemoryInfo.image = image;
+            bindBufferMemoryInfo.memory = memory;
+            bindBufferMemoryInfo.memoryOffset = memoryOffset;
+            return (*m_VulkanFunctions.vkBindImageMemory2KHR)(m_hDevice, 1, &bindBufferMemoryInfo);
+        }
+        else
+#endif // #if VMA_BIND_MEMORY2
+        {
+            return VK_ERROR_EXTENSION_NOT_PRESENT;
+        }
+    }
+    else
+    {
+        return (*m_VulkanFunctions.vkBindImageMemory)(m_hDevice, image, memory, memoryOffset);
+    }
+}
+
+VkResult VmaAllocator_T::Map(VmaAllocation hAllocation, void** ppData)
+{
+    if(hAllocation->CanBecomeLost())
+    {
+        return VK_ERROR_MEMORY_MAP_FAILED;
+    }
+
+    switch(hAllocation->GetType())
+    {
+    case VmaAllocation_T::ALLOCATION_TYPE_BLOCK:
+        {
+            VmaDeviceMemoryBlock* const pBlock = hAllocation->GetBlock();
+            char *pBytes = VMA_NULL;
+            VkResult res = pBlock->Map(this, 1, (void**)&pBytes);
+            if(res == VK_SUCCESS)
+            {
+                *ppData = pBytes + (ptrdiff_t)hAllocation->GetOffset();
+                hAllocation->BlockAllocMap();
+            }
+            return res;
+        }
+    case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED:
+        return hAllocation->DedicatedAllocMap(this, ppData);
+    default:
+        VMA_ASSERT(0);
+        return VK_ERROR_MEMORY_MAP_FAILED;
+    }
+}
+
+void VmaAllocator_T::Unmap(VmaAllocation hAllocation)
+{
+    switch(hAllocation->GetType())
+    {
+    case VmaAllocation_T::ALLOCATION_TYPE_BLOCK:
+        {
+            VmaDeviceMemoryBlock* const pBlock = hAllocation->GetBlock();
+            hAllocation->BlockAllocUnmap();
+            pBlock->Unmap(this, 1);
+        }
+        break;
+    case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED:
+        hAllocation->DedicatedAllocUnmap(this);
+        break;
+    default:
+        VMA_ASSERT(0);
+    }
+}
+
+VkResult VmaAllocator_T::BindBufferMemory(
+    VmaAllocation hAllocation,
+    VkDeviceSize allocationLocalOffset,
+    VkBuffer hBuffer,
+    const void* pNext)
+{
+    VkResult res = VK_SUCCESS;
+    switch(hAllocation->GetType())
+    {
+    case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED:
+        res = BindVulkanBuffer(hAllocation->GetMemory(), allocationLocalOffset, hBuffer, pNext);
+        break;
+    case VmaAllocation_T::ALLOCATION_TYPE_BLOCK:
+    {
+        VmaDeviceMemoryBlock* const pBlock = hAllocation->GetBlock();
+        VMA_ASSERT(pBlock && "Binding buffer to allocation that doesn't belong to any block. Is the allocation lost?");
+        res = pBlock->BindBufferMemory(this, hAllocation, allocationLocalOffset, hBuffer, pNext);
+        break;
+    }
+    default:
+        VMA_ASSERT(0);
+    }
+    return res;
+}
+
+VkResult VmaAllocator_T::BindImageMemory(
+    VmaAllocation hAllocation,
+    VkDeviceSize allocationLocalOffset,
+    VkImage hImage,
+    const void* pNext)
+{
+    VkResult res = VK_SUCCESS;
+    switch(hAllocation->GetType())
+    {
+    case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED:
+        res = BindVulkanImage(hAllocation->GetMemory(), allocationLocalOffset, hImage, pNext);
+        break;
+    case VmaAllocation_T::ALLOCATION_TYPE_BLOCK:
+    {
+        VmaDeviceMemoryBlock* pBlock = hAllocation->GetBlock();
+        VMA_ASSERT(pBlock && "Binding image to allocation that doesn't belong to any block. Is the allocation lost?");
+        res = pBlock->BindImageMemory(this, hAllocation, allocationLocalOffset, hImage, pNext);
+        break;
+    }
+    default:
+        VMA_ASSERT(0);
+    }
+    return res;
+}
+
+void VmaAllocator_T::FlushOrInvalidateAllocation(
+    VmaAllocation hAllocation,
+    VkDeviceSize offset, VkDeviceSize size,
+    VMA_CACHE_OPERATION op)
+{
+    const uint32_t memTypeIndex = hAllocation->GetMemoryTypeIndex();
+    if(size > 0 && IsMemoryTypeNonCoherent(memTypeIndex))
+    {
+        const VkDeviceSize allocationSize = hAllocation->GetSize();
+        VMA_ASSERT(offset <= allocationSize);
+
+        const VkDeviceSize nonCoherentAtomSize = m_PhysicalDeviceProperties.limits.nonCoherentAtomSize;
+
+        VkMappedMemoryRange memRange = { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE };
+        memRange.memory = hAllocation->GetMemory();
+        
+        switch(hAllocation->GetType())
+        {
+        case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED:
+            memRange.offset = VmaAlignDown(offset, nonCoherentAtomSize);
+            if(size == VK_WHOLE_SIZE)
+            {
+                memRange.size = allocationSize - memRange.offset;
+            }
+            else
+            {
+                VMA_ASSERT(offset + size <= allocationSize);
+                memRange.size = VMA_MIN(
+                    VmaAlignUp(size + (offset - memRange.offset), nonCoherentAtomSize),
+                    allocationSize - memRange.offset);
+            }
+            break;
+
+        case VmaAllocation_T::ALLOCATION_TYPE_BLOCK:
+        {
+            // 1. Still within this allocation.
+            memRange.offset = VmaAlignDown(offset, nonCoherentAtomSize);
+            if(size == VK_WHOLE_SIZE)
+            {
+                size = allocationSize - offset;
+            }
+            else
+            {
+                VMA_ASSERT(offset + size <= allocationSize);
+            }
+            memRange.size = VmaAlignUp(size + (offset - memRange.offset), nonCoherentAtomSize);
+
+            // 2. Adjust to whole block.
+            const VkDeviceSize allocationOffset = hAllocation->GetOffset();
+            VMA_ASSERT(allocationOffset % nonCoherentAtomSize == 0);
+            const VkDeviceSize blockSize = hAllocation->GetBlock()->m_pMetadata->GetSize();
+            memRange.offset += allocationOffset;
+            memRange.size = VMA_MIN(memRange.size, blockSize - memRange.offset);
+            
+            break;
+        }
+        
+        default:
+            VMA_ASSERT(0);
+        }
+
+        switch(op)
+        {
+        case VMA_CACHE_FLUSH:
+            (*GetVulkanFunctions().vkFlushMappedMemoryRanges)(m_hDevice, 1, &memRange);
+            break;
+        case VMA_CACHE_INVALIDATE:
+            (*GetVulkanFunctions().vkInvalidateMappedMemoryRanges)(m_hDevice, 1, &memRange);
+            break;
+        default:
+            VMA_ASSERT(0);
+        }
+    }
+    // else: Just ignore this call.
+}
+
+void VmaAllocator_T::FreeDedicatedMemory(const VmaAllocation allocation)
+{
+    VMA_ASSERT(allocation && allocation->GetType() == VmaAllocation_T::ALLOCATION_TYPE_DEDICATED);
+
+    const uint32_t memTypeIndex = allocation->GetMemoryTypeIndex();
+    {
+        VmaMutexLockWrite lock(m_DedicatedAllocationsMutex[memTypeIndex], m_UseMutex);
+        AllocationVectorType* const pDedicatedAllocations = m_pDedicatedAllocations[memTypeIndex];
+        VMA_ASSERT(pDedicatedAllocations);
+        bool success = VmaVectorRemoveSorted<VmaPointerLess>(*pDedicatedAllocations, allocation);
+        VMA_ASSERT(success);
+    }
+
+    VkDeviceMemory hMemory = allocation->GetMemory();
+    
+    /*
+    There is no need to call this, because Vulkan spec allows to skip vkUnmapMemory
+    before vkFreeMemory.
+
+    if(allocation->GetMappedData() != VMA_NULL)
+    {
+        (*m_VulkanFunctions.vkUnmapMemory)(m_hDevice, hMemory);
+    }
+    */
+    
+    FreeVulkanMemory(memTypeIndex, allocation->GetSize(), hMemory);
+
+    VMA_DEBUG_LOG("    Freed DedicatedMemory MemoryTypeIndex=%u", memTypeIndex);
+}
+
+uint32_t VmaAllocator_T::CalculateGpuDefragmentationMemoryTypeBits() const
+{
+    VkBufferCreateInfo dummyBufCreateInfo;
+    VmaFillGpuDefragmentationBufferCreateInfo(dummyBufCreateInfo);
+
+    uint32_t memoryTypeBits = 0;
+
+    // Create buffer.
+    VkBuffer buf = VK_NULL_HANDLE;
+    VkResult res = (*GetVulkanFunctions().vkCreateBuffer)(
+        m_hDevice, &dummyBufCreateInfo, GetAllocationCallbacks(), &buf);
+    if(res == VK_SUCCESS)
+    {
+        // Query for supported memory types.
+        VkMemoryRequirements memReq;
+        (*GetVulkanFunctions().vkGetBufferMemoryRequirements)(m_hDevice, buf, &memReq);
+        memoryTypeBits = memReq.memoryTypeBits;
+
+        // Destroy buffer.
+        (*GetVulkanFunctions().vkDestroyBuffer)(m_hDevice, buf, GetAllocationCallbacks());
+    }
+
+    return memoryTypeBits;
+}
+
+uint32_t VmaAllocator_T::CalculateGlobalMemoryTypeBits() const
+{
+    // Make sure memory information is already fetched.
+    VMA_ASSERT(GetMemoryTypeCount() > 0);
+
+    uint32_t memoryTypeBits = UINT32_MAX;
+
+    if(!m_UseAmdDeviceCoherentMemory)
+    {
+        // Exclude memory types that have VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD.
+        for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
+        {
+            if((m_MemProps.memoryTypes[memTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD_COPY) != 0)
+            {
+                memoryTypeBits &= ~(1u << memTypeIndex);
+            }
+        }
+    }
+
+    return memoryTypeBits;
+}
+
+#if VMA_MEMORY_BUDGET
+
+void VmaAllocator_T::UpdateVulkanBudget()
+{
+    VMA_ASSERT(m_UseExtMemoryBudget);
+
+    VkPhysicalDeviceMemoryProperties2KHR memProps = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR };
+
+    VkPhysicalDeviceMemoryBudgetPropertiesEXT budgetProps = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT };
+    VmaPnextChainPushFront(&memProps, &budgetProps);
+
+    GetVulkanFunctions().vkGetPhysicalDeviceMemoryProperties2KHR(m_PhysicalDevice, &memProps);
+
+    {
+        VmaMutexLockWrite lockWrite(m_Budget.m_BudgetMutex, m_UseMutex);
+
+        for(uint32_t heapIndex = 0; heapIndex < GetMemoryHeapCount(); ++heapIndex)
+        {
+            m_Budget.m_VulkanUsage[heapIndex] = budgetProps.heapUsage[heapIndex];
+            m_Budget.m_VulkanBudget[heapIndex] = budgetProps.heapBudget[heapIndex];
+            m_Budget.m_BlockBytesAtBudgetFetch[heapIndex] = m_Budget.m_BlockBytes[heapIndex].load();
+
+            // Some bugged drivers return the budget incorrectly, e.g. 0 or much bigger than heap size.
+            if(m_Budget.m_VulkanBudget[heapIndex] == 0)
+            {
+                m_Budget.m_VulkanBudget[heapIndex] = m_MemProps.memoryHeaps[heapIndex].size * 8 / 10; // 80% heuristics.
+            }
+            else if(m_Budget.m_VulkanBudget[heapIndex] > m_MemProps.memoryHeaps[heapIndex].size)
+            {
+                m_Budget.m_VulkanBudget[heapIndex] = m_MemProps.memoryHeaps[heapIndex].size;
+            }
+            if(m_Budget.m_VulkanUsage[heapIndex] == 0 && m_Budget.m_BlockBytesAtBudgetFetch[heapIndex] > 0)
+            {
+                m_Budget.m_VulkanUsage[heapIndex] = m_Budget.m_BlockBytesAtBudgetFetch[heapIndex];
+            }
+        }
+        m_Budget.m_OperationsSinceBudgetFetch = 0;
+    }
+}
+
+#endif // #if VMA_MEMORY_BUDGET
+
+void VmaAllocator_T::FillAllocation(const VmaAllocation hAllocation, uint8_t pattern)
+{
+    if(VMA_DEBUG_INITIALIZE_ALLOCATIONS &&
+        !hAllocation->CanBecomeLost() &&
+        (m_MemProps.memoryTypes[hAllocation->GetMemoryTypeIndex()].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0)
+    {
+        void* pData = VMA_NULL;
+        VkResult res = Map(hAllocation, &pData);
+        if(res == VK_SUCCESS)
+        {
+            memset(pData, (int)pattern, (size_t)hAllocation->GetSize());
+            FlushOrInvalidateAllocation(hAllocation, 0, VK_WHOLE_SIZE, VMA_CACHE_FLUSH);
+            Unmap(hAllocation);
+        }
+        else
+        {
+            VMA_ASSERT(0 && "VMA_DEBUG_INITIALIZE_ALLOCATIONS is enabled, but couldn't map memory to fill allocation.");
+        }
+    }
+}
+
+uint32_t VmaAllocator_T::GetGpuDefragmentationMemoryTypeBits()
+{
+    uint32_t memoryTypeBits = m_GpuDefragmentationMemoryTypeBits.load();
+    if(memoryTypeBits == UINT32_MAX)
+    {
+        memoryTypeBits = CalculateGpuDefragmentationMemoryTypeBits();
+        m_GpuDefragmentationMemoryTypeBits.store(memoryTypeBits);
+    }
+    return memoryTypeBits;
+}
+
+#if VMA_STATS_STRING_ENABLED
+
+void VmaAllocator_T::PrintDetailedMap(VmaJsonWriter& json)
+{
+    bool dedicatedAllocationsStarted = false;
+    for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
+    {
+        VmaMutexLockRead dedicatedAllocationsLock(m_DedicatedAllocationsMutex[memTypeIndex], m_UseMutex);
+        AllocationVectorType* const pDedicatedAllocVector = m_pDedicatedAllocations[memTypeIndex];
+        VMA_ASSERT(pDedicatedAllocVector);
+        if(pDedicatedAllocVector->empty() == false)
+        {
+            if(dedicatedAllocationsStarted == false)
+            {
+                dedicatedAllocationsStarted = true;
+                json.WriteString("DedicatedAllocations");
+                json.BeginObject();
+            }
+
+            json.BeginString("Type ");
+            json.ContinueString(memTypeIndex);
+            json.EndString();
+                
+            json.BeginArray();
+
+            for(size_t i = 0; i < pDedicatedAllocVector->size(); ++i)
+            {
+                json.BeginObject(true);
+                const VmaAllocation hAlloc = (*pDedicatedAllocVector)[i];
+                hAlloc->PrintParameters(json);
+                json.EndObject();
+            }
+
+            json.EndArray();
+        }
+    }
+    if(dedicatedAllocationsStarted)
+    {
+        json.EndObject();
+    }
+
+    {
+        bool allocationsStarted = false;
+        for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
+        {
+            if(m_pBlockVectors[memTypeIndex]->IsEmpty() == false)
+            {
+                if(allocationsStarted == false)
+                {
+                    allocationsStarted = true;
+                    json.WriteString("DefaultPools");
+                    json.BeginObject();
+                }
+
+                json.BeginString("Type ");
+                json.ContinueString(memTypeIndex);
+                json.EndString();
+
+                m_pBlockVectors[memTypeIndex]->PrintDetailedMap(json);
+            }
+        }
+        if(allocationsStarted)
+        {
+            json.EndObject();
+        }
+    }
+
+    // Custom pools
+    {
+        VmaMutexLockRead lock(m_PoolsMutex, m_UseMutex);
+        const size_t poolCount = m_Pools.size();
+        if(poolCount > 0)
+        {
+            json.WriteString("Pools");
+            json.BeginObject();
+            for(size_t poolIndex = 0; poolIndex < poolCount; ++poolIndex)
+            {
+                json.BeginString();
+                json.ContinueString(m_Pools[poolIndex]->GetId());
+                json.EndString();
+
+                m_Pools[poolIndex]->m_BlockVector.PrintDetailedMap(json);
+            }
+            json.EndObject();
+        }
+    }
+}
+
+#endif // #if VMA_STATS_STRING_ENABLED
+
+////////////////////////////////////////////////////////////////////////////////
+// Public interface
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAllocator(
+    const VmaAllocatorCreateInfo* pCreateInfo,
+    VmaAllocator* pAllocator)
+{
+    VMA_ASSERT(pCreateInfo && pAllocator);
+    VMA_ASSERT(pCreateInfo->vulkanApiVersion == 0 ||
+        (VK_VERSION_MAJOR(pCreateInfo->vulkanApiVersion) == 1 && VK_VERSION_MINOR(pCreateInfo->vulkanApiVersion) <= 2));
+    VMA_DEBUG_LOG("vmaCreateAllocator");
+    *pAllocator = vma_new(pCreateInfo->pAllocationCallbacks, VmaAllocator_T)(pCreateInfo);
+    return (*pAllocator)->Init(pCreateInfo);
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaDestroyAllocator(
+    VmaAllocator allocator)
+{
+    if(allocator != VK_NULL_HANDLE)
+    {
+        VMA_DEBUG_LOG("vmaDestroyAllocator");
+        VkAllocationCallbacks allocationCallbacks = allocator->m_AllocationCallbacks;
+        vma_delete(&allocationCallbacks, allocator);
+    }
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocatorInfo(VmaAllocator allocator, VmaAllocatorInfo* pAllocatorInfo)
+{
+    VMA_ASSERT(allocator && pAllocatorInfo);
+    pAllocatorInfo->instance = allocator->m_hInstance;
+    pAllocatorInfo->physicalDevice = allocator->GetPhysicalDevice();
+    pAllocatorInfo->device = allocator->m_hDevice;
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaGetPhysicalDeviceProperties(
+    VmaAllocator allocator,
+    const VkPhysicalDeviceProperties **ppPhysicalDeviceProperties)
+{
+    VMA_ASSERT(allocator && ppPhysicalDeviceProperties);
+    *ppPhysicalDeviceProperties = &allocator->m_PhysicalDeviceProperties;
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaGetMemoryProperties(
+    VmaAllocator allocator,
+    const VkPhysicalDeviceMemoryProperties** ppPhysicalDeviceMemoryProperties)
+{
+    VMA_ASSERT(allocator && ppPhysicalDeviceMemoryProperties);
+    *ppPhysicalDeviceMemoryProperties = &allocator->m_MemProps;
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaGetMemoryTypeProperties(
+    VmaAllocator allocator,
+    uint32_t memoryTypeIndex,
+    VkMemoryPropertyFlags* pFlags)
+{
+    VMA_ASSERT(allocator && pFlags);
+    VMA_ASSERT(memoryTypeIndex < allocator->GetMemoryTypeCount());
+    *pFlags = allocator->m_MemProps.memoryTypes[memoryTypeIndex].propertyFlags;
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaSetCurrentFrameIndex(
+    VmaAllocator allocator,
+    uint32_t frameIndex)
+{
+    VMA_ASSERT(allocator);
+    VMA_ASSERT(frameIndex != VMA_FRAME_INDEX_LOST);
+
+    VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+    allocator->SetCurrentFrameIndex(frameIndex);
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaCalculateStats(
+    VmaAllocator allocator,
+    VmaStats* pStats)
+{
+    VMA_ASSERT(allocator && pStats);
+    VMA_DEBUG_GLOBAL_MUTEX_LOCK
+    allocator->CalculateStats(pStats);
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaGetBudget(
+    VmaAllocator allocator,
+    VmaBudget* pBudget)
+{
+    VMA_ASSERT(allocator && pBudget);
+    VMA_DEBUG_GLOBAL_MUTEX_LOCK
+    allocator->GetBudget(pBudget, 0, allocator->GetMemoryHeapCount());
+}
+
+#if VMA_STATS_STRING_ENABLED
+
+VMA_CALL_PRE void VMA_CALL_POST vmaBuildStatsString(
+    VmaAllocator allocator,
+    char** ppStatsString,
+    VkBool32 detailedMap)
+{
+    VMA_ASSERT(allocator && ppStatsString);
+    VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+    VmaStringBuilder sb(allocator);
+    {
+        VmaJsonWriter json(allocator->GetAllocationCallbacks(), sb);
+        json.BeginObject();
+
+        VmaBudget budget[VK_MAX_MEMORY_HEAPS];
+        allocator->GetBudget(budget, 0, allocator->GetMemoryHeapCount());
+
+        VmaStats stats;
+        allocator->CalculateStats(&stats);
+
+        json.WriteString("Total");
+        VmaPrintStatInfo(json, stats.total);
+    
+        for(uint32_t heapIndex = 0; heapIndex < allocator->GetMemoryHeapCount(); ++heapIndex)
+        {
+            json.BeginString("Heap ");
+            json.ContinueString(heapIndex);
+            json.EndString();
+            json.BeginObject();
+
+            json.WriteString("Size");
+            json.WriteNumber(allocator->m_MemProps.memoryHeaps[heapIndex].size);
+
+            json.WriteString("Flags");
+            json.BeginArray(true);
+            if((allocator->m_MemProps.memoryHeaps[heapIndex].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) != 0)
+            {
+                json.WriteString("DEVICE_LOCAL");
+            }
+            json.EndArray();
+
+            json.WriteString("Budget");
+            json.BeginObject();
+            {
+                json.WriteString("BlockBytes");
+                json.WriteNumber(budget[heapIndex].blockBytes);
+                json.WriteString("AllocationBytes");
+                json.WriteNumber(budget[heapIndex].allocationBytes);
+                json.WriteString("Usage");
+                json.WriteNumber(budget[heapIndex].usage);
+                json.WriteString("Budget");
+                json.WriteNumber(budget[heapIndex].budget);
+            }
+            json.EndObject();
+
+            if(stats.memoryHeap[heapIndex].blockCount > 0)
+            {
+                json.WriteString("Stats");
+                VmaPrintStatInfo(json, stats.memoryHeap[heapIndex]);
+            }
+
+            for(uint32_t typeIndex = 0; typeIndex < allocator->GetMemoryTypeCount(); ++typeIndex)
+            {
+                if(allocator->MemoryTypeIndexToHeapIndex(typeIndex) == heapIndex)
+                {
+                    json.BeginString("Type ");
+                    json.ContinueString(typeIndex);
+                    json.EndString();
+
+                    json.BeginObject();
+
+                    json.WriteString("Flags");
+                    json.BeginArray(true);
+                    VkMemoryPropertyFlags flags = allocator->m_MemProps.memoryTypes[typeIndex].propertyFlags;
+                    if((flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) != 0)
+                    {
+                        json.WriteString("DEVICE_LOCAL");
+                    }
+                    if((flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0)
+                    {
+                        json.WriteString("HOST_VISIBLE");
+                    }
+                    if((flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) != 0)
+                    {
+                        json.WriteString("HOST_COHERENT");
+                    }
+                    if((flags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) != 0)
+                    {
+                        json.WriteString("HOST_CACHED");
+                    }
+                    if((flags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) != 0)
+                    {
+                        json.WriteString("LAZILY_ALLOCATED");
+                    }
+                    if((flags & VK_MEMORY_PROPERTY_PROTECTED_BIT) != 0)
+                    {
+                        json.WriteString(" PROTECTED");
+                    }
+                    if((flags & VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD_COPY) != 0)
+                    {
+                        json.WriteString(" DEVICE_COHERENT");
+                    }
+                    if((flags & VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD_COPY) != 0)
+                    {
+                        json.WriteString(" DEVICE_UNCACHED");
+                    }
+                    json.EndArray();
+
+                    if(stats.memoryType[typeIndex].blockCount > 0)
+                    {
+                        json.WriteString("Stats");
+                        VmaPrintStatInfo(json, stats.memoryType[typeIndex]);
+                    }
+
+                    json.EndObject();
+                }
+            }
+
+            json.EndObject();
+        }
+        if(detailedMap == VK_TRUE)
+        {
+            allocator->PrintDetailedMap(json);
+        }
+
+        json.EndObject();
+    }
+
+    const size_t len = sb.GetLength();
+    char* const pChars = vma_new_array(allocator, char, len + 1);
+    if(len > 0)
+    {
+        memcpy(pChars, sb.GetData(), len);
+    }
+    pChars[len] = '\0';
+    *ppStatsString = pChars;
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaFreeStatsString(
+    VmaAllocator allocator,
+    char* pStatsString)
+{
+    if(pStatsString != VMA_NULL)
+    {
+        VMA_ASSERT(allocator);
+        size_t len = strlen(pStatsString);
+        vma_delete_array(allocator, pStatsString, len + 1);
+    }
+}
+
+#endif // #if VMA_STATS_STRING_ENABLED
+
+/*
+This function is not protected by any mutex because it just reads immutable data.
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndex(
+    VmaAllocator allocator,
+    uint32_t memoryTypeBits,
+    const VmaAllocationCreateInfo* pAllocationCreateInfo,
+    uint32_t* pMemoryTypeIndex)
+{
+    VMA_ASSERT(allocator != VK_NULL_HANDLE);
+    VMA_ASSERT(pAllocationCreateInfo != VMA_NULL);
+    VMA_ASSERT(pMemoryTypeIndex != VMA_NULL);
+
+    memoryTypeBits &= allocator->GetGlobalMemoryTypeBits();
+
+    if(pAllocationCreateInfo->memoryTypeBits != 0)
+    {
+        memoryTypeBits &= pAllocationCreateInfo->memoryTypeBits;
+    }
+    
+    uint32_t requiredFlags = pAllocationCreateInfo->requiredFlags;
+    uint32_t preferredFlags = pAllocationCreateInfo->preferredFlags;
+    uint32_t notPreferredFlags = 0;
+
+    // Convert usage to requiredFlags and preferredFlags.
+    switch(pAllocationCreateInfo->usage)
+    {
+    case VMA_MEMORY_USAGE_UNKNOWN:
+        break;
+    case VMA_MEMORY_USAGE_GPU_ONLY:
+        if(!allocator->IsIntegratedGpu() || (preferredFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0)
+        {
+            preferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+        }
+        break;
+    case VMA_MEMORY_USAGE_CPU_ONLY:
+        requiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
+        break;
+    case VMA_MEMORY_USAGE_CPU_TO_GPU:
+        requiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
+        if(!allocator->IsIntegratedGpu() || (preferredFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0)
+        {
+            preferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+        }
+        break;
+    case VMA_MEMORY_USAGE_GPU_TO_CPU:
+        requiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
+        preferredFlags |= VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
+        break;
+    case VMA_MEMORY_USAGE_CPU_COPY:
+        notPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+        break;
+    case VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED:
+        requiredFlags |= VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT;
+        break;
+    default:
+        VMA_ASSERT(0);
+        break;
+    }
+
+    // Avoid DEVICE_COHERENT unless explicitly requested.
+    if(((pAllocationCreateInfo->requiredFlags | pAllocationCreateInfo->preferredFlags) &
+        (VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD_COPY | VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD_COPY)) == 0)
+    {
+        notPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD_COPY;
+    }
+
+    *pMemoryTypeIndex = UINT32_MAX;
+    uint32_t minCost = UINT32_MAX;
+    for(uint32_t memTypeIndex = 0, memTypeBit = 1;
+        memTypeIndex < allocator->GetMemoryTypeCount();
+        ++memTypeIndex, memTypeBit <<= 1)
+    {
+        // This memory type is acceptable according to memoryTypeBits bitmask.
+        if((memTypeBit & memoryTypeBits) != 0)
+        {
+            const VkMemoryPropertyFlags currFlags =
+                allocator->m_MemProps.memoryTypes[memTypeIndex].propertyFlags;
+            // This memory type contains requiredFlags.
+            if((requiredFlags & ~currFlags) == 0)
+            {
+                // Calculate cost as number of bits from preferredFlags not present in this memory type.
+                uint32_t currCost = VmaCountBitsSet(preferredFlags & ~currFlags) +
+                    VmaCountBitsSet(currFlags & notPreferredFlags);
+                // Remember memory type with lowest cost.
+                if(currCost < minCost)
+                {
+                    *pMemoryTypeIndex = memTypeIndex;
+                    if(currCost == 0)
+                    {
+                        return VK_SUCCESS;
+                    }
+                    minCost = currCost;
+                }
+            }
+        }
+    }
+    return (*pMemoryTypeIndex != UINT32_MAX) ? VK_SUCCESS : VK_ERROR_FEATURE_NOT_PRESENT;
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndexForBufferInfo(
+    VmaAllocator allocator,
+    const VkBufferCreateInfo* pBufferCreateInfo,
+    const VmaAllocationCreateInfo* pAllocationCreateInfo,
+    uint32_t* pMemoryTypeIndex)
+{
+    VMA_ASSERT(allocator != VK_NULL_HANDLE);
+    VMA_ASSERT(pBufferCreateInfo != VMA_NULL);
+    VMA_ASSERT(pAllocationCreateInfo != VMA_NULL);
+    VMA_ASSERT(pMemoryTypeIndex != VMA_NULL);
+
+    const VkDevice hDev = allocator->m_hDevice;
+    VkBuffer hBuffer = VK_NULL_HANDLE;
+    VkResult res = allocator->GetVulkanFunctions().vkCreateBuffer(
+        hDev, pBufferCreateInfo, allocator->GetAllocationCallbacks(), &hBuffer);
+    if(res == VK_SUCCESS)
+    {
+        VkMemoryRequirements memReq = {};
+        allocator->GetVulkanFunctions().vkGetBufferMemoryRequirements(
+            hDev, hBuffer, &memReq);
+
+        res = vmaFindMemoryTypeIndex(
+            allocator,
+            memReq.memoryTypeBits,
+            pAllocationCreateInfo,
+            pMemoryTypeIndex);
+
+        allocator->GetVulkanFunctions().vkDestroyBuffer(
+            hDev, hBuffer, allocator->GetAllocationCallbacks());
+    }
+    return res;
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndexForImageInfo(
+    VmaAllocator allocator,
+    const VkImageCreateInfo* pImageCreateInfo,
+    const VmaAllocationCreateInfo* pAllocationCreateInfo,
+    uint32_t* pMemoryTypeIndex)
+{
+    VMA_ASSERT(allocator != VK_NULL_HANDLE);
+    VMA_ASSERT(pImageCreateInfo != VMA_NULL);
+    VMA_ASSERT(pAllocationCreateInfo != VMA_NULL);
+    VMA_ASSERT(pMemoryTypeIndex != VMA_NULL);
+
+    const VkDevice hDev = allocator->m_hDevice;
+    VkImage hImage = VK_NULL_HANDLE;
+    VkResult res = allocator->GetVulkanFunctions().vkCreateImage(
+        hDev, pImageCreateInfo, allocator->GetAllocationCallbacks(), &hImage);
+    if(res == VK_SUCCESS)
+    {
+        VkMemoryRequirements memReq = {};
+        allocator->GetVulkanFunctions().vkGetImageMemoryRequirements(
+            hDev, hImage, &memReq);
+
+        res = vmaFindMemoryTypeIndex(
+            allocator,
+            memReq.memoryTypeBits,
+            pAllocationCreateInfo,
+            pMemoryTypeIndex);
+
+        allocator->GetVulkanFunctions().vkDestroyImage(
+            hDev, hImage, allocator->GetAllocationCallbacks());
+    }
+    return res;
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreatePool(
+	VmaAllocator allocator,
+	const VmaPoolCreateInfo* pCreateInfo,
+	VmaPool* pPool)
+{
+    VMA_ASSERT(allocator && pCreateInfo && pPool);
+    
+    VMA_DEBUG_LOG("vmaCreatePool");
+    
+    VMA_DEBUG_GLOBAL_MUTEX_LOCK
+    
+    VkResult res = allocator->CreatePool(pCreateInfo, pPool);
+    
+#if VMA_RECORDING_ENABLED
+    if(allocator->GetRecorder() != VMA_NULL)
+    {
+        allocator->GetRecorder()->RecordCreatePool(allocator->GetCurrentFrameIndex(), *pCreateInfo, *pPool);
+    }
+#endif
+    
+    return res;
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaDestroyPool(
+    VmaAllocator allocator,
+    VmaPool pool)
+{
+    VMA_ASSERT(allocator);
+    
+    if(pool == VK_NULL_HANDLE)
+    {
+        return;
+    }
+    
+    VMA_DEBUG_LOG("vmaDestroyPool");
+    
+    VMA_DEBUG_GLOBAL_MUTEX_LOCK
+    
+#if VMA_RECORDING_ENABLED
+    if(allocator->GetRecorder() != VMA_NULL)
+    {
+        allocator->GetRecorder()->RecordDestroyPool(allocator->GetCurrentFrameIndex(), pool);
+    }
+#endif
+
+    allocator->DestroyPool(pool);
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaGetPoolStats(
+    VmaAllocator allocator,
+    VmaPool pool,
+    VmaPoolStats* pPoolStats)
+{
+    VMA_ASSERT(allocator && pool && pPoolStats);
+
+    VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+    allocator->GetPoolStats(pool, pPoolStats);
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaMakePoolAllocationsLost(
+    VmaAllocator allocator,
+    VmaPool pool,
+    size_t* pLostAllocationCount)
+{
+    VMA_ASSERT(allocator && pool);
+
+    VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+#if VMA_RECORDING_ENABLED
+    if(allocator->GetRecorder() != VMA_NULL)
+    {
+        allocator->GetRecorder()->RecordMakePoolAllocationsLost(allocator->GetCurrentFrameIndex(), pool);
+    }
+#endif
+
+    allocator->MakePoolAllocationsLost(pool, pLostAllocationCount);
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaCheckPoolCorruption(VmaAllocator allocator, VmaPool pool)
+{
+    VMA_ASSERT(allocator && pool);
+
+    VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+    VMA_DEBUG_LOG("vmaCheckPoolCorruption");
+
+    return allocator->CheckPoolCorruption(pool);
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaGetPoolName(
+    VmaAllocator allocator,
+    VmaPool pool,
+    const char** ppName)
+{
+    VMA_ASSERT(allocator && pool);
+    
+    VMA_DEBUG_LOG("vmaGetPoolName");
+
+    VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+    *ppName = pool->GetName();
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaSetPoolName(
+    VmaAllocator allocator,
+    VmaPool pool,
+    const char* pName)
+{
+    VMA_ASSERT(allocator && pool);
+
+    VMA_DEBUG_LOG("vmaSetPoolName");
+
+    VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+    pool->SetName(pName);
+
+#if VMA_RECORDING_ENABLED
+    if(allocator->GetRecorder() != VMA_NULL)
+    {
+        allocator->GetRecorder()->RecordSetPoolName(allocator->GetCurrentFrameIndex(), pool, pName);
+    }
+#endif
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemory(
+    VmaAllocator allocator,
+    const VkMemoryRequirements* pVkMemoryRequirements,
+    const VmaAllocationCreateInfo* pCreateInfo,
+    VmaAllocation* pAllocation,
+    VmaAllocationInfo* pAllocationInfo)
+{
+    VMA_ASSERT(allocator && pVkMemoryRequirements && pCreateInfo && pAllocation);
+
+    VMA_DEBUG_LOG("vmaAllocateMemory");
+
+    VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+	VkResult result = allocator->AllocateMemory(
+        *pVkMemoryRequirements,
+        false, // requiresDedicatedAllocation
+        false, // prefersDedicatedAllocation
+        VK_NULL_HANDLE, // dedicatedBuffer
+        UINT32_MAX, // dedicatedBufferUsage
+        VK_NULL_HANDLE, // dedicatedImage
+        *pCreateInfo,
+        VMA_SUBALLOCATION_TYPE_UNKNOWN,
+        1, // allocationCount
+        pAllocation);
+
+#if VMA_RECORDING_ENABLED
+    if(allocator->GetRecorder() != VMA_NULL)
+    {
+        allocator->GetRecorder()->RecordAllocateMemory(
+            allocator->GetCurrentFrameIndex(),
+            *pVkMemoryRequirements,
+            *pCreateInfo,
+            *pAllocation);
+    }
+#endif
+        
+    if(pAllocationInfo != VMA_NULL && result == VK_SUCCESS)
+    {
+        allocator->GetAllocationInfo(*pAllocation, pAllocationInfo);
+    }
+
+	return result;
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryPages(
+    VmaAllocator allocator,
+    const VkMemoryRequirements* pVkMemoryRequirements,
+    const VmaAllocationCreateInfo* pCreateInfo,
+    size_t allocationCount,
+    VmaAllocation* pAllocations,
+    VmaAllocationInfo* pAllocationInfo)
+{
+    if(allocationCount == 0)
+    {
+        return VK_SUCCESS;
+    }
+
+    VMA_ASSERT(allocator && pVkMemoryRequirements && pCreateInfo && pAllocations);
+
+    VMA_DEBUG_LOG("vmaAllocateMemoryPages");
+
+    VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+	VkResult result = allocator->AllocateMemory(
+        *pVkMemoryRequirements,
+        false, // requiresDedicatedAllocation
+        false, // prefersDedicatedAllocation
+        VK_NULL_HANDLE, // dedicatedBuffer
+        UINT32_MAX, // dedicatedBufferUsage
+        VK_NULL_HANDLE, // dedicatedImage
+        *pCreateInfo,
+        VMA_SUBALLOCATION_TYPE_UNKNOWN,
+        allocationCount,
+        pAllocations);
+
+#if VMA_RECORDING_ENABLED
+    if(allocator->GetRecorder() != VMA_NULL)
+    {
+        allocator->GetRecorder()->RecordAllocateMemoryPages(
+            allocator->GetCurrentFrameIndex(),
+            *pVkMemoryRequirements,
+            *pCreateInfo,
+            (uint64_t)allocationCount,
+            pAllocations);
+    }
+#endif
+        
+    if(pAllocationInfo != VMA_NULL && result == VK_SUCCESS)
+    {
+        for(size_t i = 0; i < allocationCount; ++i)
+        {
+            allocator->GetAllocationInfo(pAllocations[i], pAllocationInfo + i);
+        }
+    }
+
+	return result;
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryForBuffer(
+    VmaAllocator allocator,
+    VkBuffer buffer,
+    const VmaAllocationCreateInfo* pCreateInfo,
+    VmaAllocation* pAllocation,
+    VmaAllocationInfo* pAllocationInfo)
+{
+    VMA_ASSERT(allocator && buffer != VK_NULL_HANDLE && pCreateInfo && pAllocation);
+
+    VMA_DEBUG_LOG("vmaAllocateMemoryForBuffer");
+
+    VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+    VkMemoryRequirements vkMemReq = {};
+    bool requiresDedicatedAllocation = false;
+    bool prefersDedicatedAllocation = false;
+    allocator->GetBufferMemoryRequirements(buffer, vkMemReq,
+        requiresDedicatedAllocation,
+        prefersDedicatedAllocation);
+
+    VkResult result = allocator->AllocateMemory(
+        vkMemReq,
+        requiresDedicatedAllocation,
+        prefersDedicatedAllocation,
+        buffer, // dedicatedBuffer
+        UINT32_MAX, // dedicatedBufferUsage
+        VK_NULL_HANDLE, // dedicatedImage
+        *pCreateInfo,
+        VMA_SUBALLOCATION_TYPE_BUFFER,
+        1, // allocationCount
+        pAllocation);
+
+#if VMA_RECORDING_ENABLED
+    if(allocator->GetRecorder() != VMA_NULL)
+    {
+        allocator->GetRecorder()->RecordAllocateMemoryForBuffer(
+            allocator->GetCurrentFrameIndex(),
+            vkMemReq,
+            requiresDedicatedAllocation,
+            prefersDedicatedAllocation,
+            *pCreateInfo,
+            *pAllocation);
+    }
+#endif
+
+    if(pAllocationInfo && result == VK_SUCCESS)
+    {
+        allocator->GetAllocationInfo(*pAllocation, pAllocationInfo);
+    }
+
+	return result;
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryForImage(
+    VmaAllocator allocator,
+    VkImage image,
+    const VmaAllocationCreateInfo* pCreateInfo,
+    VmaAllocation* pAllocation,
+    VmaAllocationInfo* pAllocationInfo)
+{
+    VMA_ASSERT(allocator && image != VK_NULL_HANDLE && pCreateInfo && pAllocation);
+
+    VMA_DEBUG_LOG("vmaAllocateMemoryForImage");
+
+    VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+    VkMemoryRequirements vkMemReq = {};
+    bool requiresDedicatedAllocation = false;
+    bool prefersDedicatedAllocation  = false;
+    allocator->GetImageMemoryRequirements(image, vkMemReq,
+        requiresDedicatedAllocation, prefersDedicatedAllocation);
+
+    VkResult result = allocator->AllocateMemory(
+        vkMemReq,
+        requiresDedicatedAllocation,
+        prefersDedicatedAllocation,
+        VK_NULL_HANDLE, // dedicatedBuffer
+        UINT32_MAX, // dedicatedBufferUsage
+        image, // dedicatedImage
+        *pCreateInfo,
+        VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN,
+        1, // allocationCount
+        pAllocation);
+
+#if VMA_RECORDING_ENABLED
+    if(allocator->GetRecorder() != VMA_NULL)
+    {
+        allocator->GetRecorder()->RecordAllocateMemoryForImage(
+            allocator->GetCurrentFrameIndex(),
+            vkMemReq,
+            requiresDedicatedAllocation,
+            prefersDedicatedAllocation,
+            *pCreateInfo,
+            *pAllocation);
+    }
+#endif
+
+    if(pAllocationInfo && result == VK_SUCCESS)
+    {
+        allocator->GetAllocationInfo(*pAllocation, pAllocationInfo);
+    }
+
+	return result;
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaFreeMemory(
+    VmaAllocator allocator,
+    VmaAllocation allocation)
+{
+    VMA_ASSERT(allocator);
+    
+    if(allocation == VK_NULL_HANDLE)
+    {
+        return;
+    }
+    
+    VMA_DEBUG_LOG("vmaFreeMemory");
+    
+    VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+#if VMA_RECORDING_ENABLED
+    if(allocator->GetRecorder() != VMA_NULL)
+    {
+        allocator->GetRecorder()->RecordFreeMemory(
+            allocator->GetCurrentFrameIndex(),
+            allocation);
+    }
+#endif
+    
+    allocator->FreeMemory(
+        1, // allocationCount
+        &allocation);
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaFreeMemoryPages(
+    VmaAllocator allocator,
+    size_t allocationCount,
+    VmaAllocation* pAllocations)
+{
+    if(allocationCount == 0)
+    {
+        return;
+    }
+
+    VMA_ASSERT(allocator);
+    
+    VMA_DEBUG_LOG("vmaFreeMemoryPages");
+    
+    VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+#if VMA_RECORDING_ENABLED
+    if(allocator->GetRecorder() != VMA_NULL)
+    {
+        allocator->GetRecorder()->RecordFreeMemoryPages(
+            allocator->GetCurrentFrameIndex(),
+            (uint64_t)allocationCount,
+            pAllocations);
+    }
+#endif
+    
+    allocator->FreeMemory(allocationCount, pAllocations);
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaResizeAllocation(
+    VmaAllocator allocator,
+    VmaAllocation allocation,
+    VkDeviceSize newSize)
+{
+    VMA_ASSERT(allocator && allocation);
+    
+    VMA_DEBUG_LOG("vmaResizeAllocation");
+    
+    VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+    return allocator->ResizeAllocation(allocation, newSize);
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocationInfo(
+    VmaAllocator allocator,
+    VmaAllocation allocation,
+    VmaAllocationInfo* pAllocationInfo)
+{
+    VMA_ASSERT(allocator && allocation && pAllocationInfo);
+
+    VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+#if VMA_RECORDING_ENABLED
+    if(allocator->GetRecorder() != VMA_NULL)
+    {
+        allocator->GetRecorder()->RecordGetAllocationInfo(
+            allocator->GetCurrentFrameIndex(),
+            allocation);
+    }
+#endif
+
+    allocator->GetAllocationInfo(allocation, pAllocationInfo);
+}
+
+VMA_CALL_PRE VkBool32 VMA_CALL_POST vmaTouchAllocation(
+    VmaAllocator allocator,
+    VmaAllocation allocation)
+{
+    VMA_ASSERT(allocator && allocation);
+
+    VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+#if VMA_RECORDING_ENABLED
+    if(allocator->GetRecorder() != VMA_NULL)
+    {
+        allocator->GetRecorder()->RecordTouchAllocation(
+            allocator->GetCurrentFrameIndex(),
+            allocation);
+    }
+#endif
+
+    return allocator->TouchAllocation(allocation);
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaSetAllocationUserData(
+    VmaAllocator allocator,
+    VmaAllocation allocation,
+    void* pUserData)
+{
+    VMA_ASSERT(allocator && allocation);
+
+    VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+    allocation->SetUserData(allocator, pUserData);
+
+#if VMA_RECORDING_ENABLED
+    if(allocator->GetRecorder() != VMA_NULL)
+    {
+        allocator->GetRecorder()->RecordSetAllocationUserData(
+            allocator->GetCurrentFrameIndex(),
+            allocation,
+            pUserData);
+    }
+#endif
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaCreateLostAllocation(
+    VmaAllocator allocator,
+    VmaAllocation* pAllocation)
+{
+    VMA_ASSERT(allocator && pAllocation);
+
+    VMA_DEBUG_GLOBAL_MUTEX_LOCK;
+
+    allocator->CreateLostAllocation(pAllocation);
+
+#if VMA_RECORDING_ENABLED
+    if(allocator->GetRecorder() != VMA_NULL)
+    {
+        allocator->GetRecorder()->RecordCreateLostAllocation(
+            allocator->GetCurrentFrameIndex(),
+            *pAllocation);
+    }
+#endif
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaMapMemory(
+    VmaAllocator allocator,
+    VmaAllocation allocation,
+    void** ppData)
+{
+    VMA_ASSERT(allocator && allocation && ppData);
+
+    VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+    VkResult res = allocator->Map(allocation, ppData);
+
+#if VMA_RECORDING_ENABLED
+    if(allocator->GetRecorder() != VMA_NULL)
+    {
+        allocator->GetRecorder()->RecordMapMemory(
+            allocator->GetCurrentFrameIndex(),
+            allocation);
+    }
+#endif
+
+    return res;
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaUnmapMemory(
+    VmaAllocator allocator,
+    VmaAllocation allocation)
+{
+    VMA_ASSERT(allocator && allocation);
+
+    VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+#if VMA_RECORDING_ENABLED
+    if(allocator->GetRecorder() != VMA_NULL)
+    {
+        allocator->GetRecorder()->RecordUnmapMemory(
+            allocator->GetCurrentFrameIndex(),
+            allocation);
+    }
+#endif
+
+    allocator->Unmap(allocation);
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaFlushAllocation(VmaAllocator allocator, VmaAllocation allocation, VkDeviceSize offset, VkDeviceSize size)
+{
+    VMA_ASSERT(allocator && allocation);
+
+    VMA_DEBUG_LOG("vmaFlushAllocation");
+
+    VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+    allocator->FlushOrInvalidateAllocation(allocation, offset, size, VMA_CACHE_FLUSH);
+
+#if VMA_RECORDING_ENABLED
+    if(allocator->GetRecorder() != VMA_NULL)
+    {
+        allocator->GetRecorder()->RecordFlushAllocation(
+            allocator->GetCurrentFrameIndex(),
+            allocation, offset, size);
+    }
+#endif
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaInvalidateAllocation(VmaAllocator allocator, VmaAllocation allocation, VkDeviceSize offset, VkDeviceSize size)
+{
+    VMA_ASSERT(allocator && allocation);
+
+    VMA_DEBUG_LOG("vmaInvalidateAllocation");
+
+    VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+    allocator->FlushOrInvalidateAllocation(allocation, offset, size, VMA_CACHE_INVALIDATE);
+
+#if VMA_RECORDING_ENABLED
+    if(allocator->GetRecorder() != VMA_NULL)
+    {
+        allocator->GetRecorder()->RecordInvalidateAllocation(
+            allocator->GetCurrentFrameIndex(),
+            allocation, offset, size);
+    }
+#endif
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaCheckCorruption(VmaAllocator allocator, uint32_t memoryTypeBits)
+{
+    VMA_ASSERT(allocator);
+
+    VMA_DEBUG_LOG("vmaCheckCorruption");
+
+    VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+    return allocator->CheckCorruption(memoryTypeBits);
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaDefragment(
+    VmaAllocator allocator,
+    VmaAllocation* pAllocations,
+    size_t allocationCount,
+    VkBool32* pAllocationsChanged,
+    const VmaDefragmentationInfo *pDefragmentationInfo,
+    VmaDefragmentationStats* pDefragmentationStats)
+{
+    // Deprecated interface, reimplemented using new one.
+
+    VmaDefragmentationInfo2 info2 = {};
+    info2.allocationCount = (uint32_t)allocationCount;
+    info2.pAllocations = pAllocations;
+    info2.pAllocationsChanged = pAllocationsChanged;
+    if(pDefragmentationInfo != VMA_NULL)
+    {
+        info2.maxCpuAllocationsToMove = pDefragmentationInfo->maxAllocationsToMove;
+        info2.maxCpuBytesToMove = pDefragmentationInfo->maxBytesToMove;
+    }
+    else
+    {
+        info2.maxCpuAllocationsToMove = UINT32_MAX;
+        info2.maxCpuBytesToMove = VK_WHOLE_SIZE;
+    }
+    // info2.flags, maxGpuAllocationsToMove, maxGpuBytesToMove, commandBuffer deliberately left zero.
+
+    VmaDefragmentationContext ctx;
+    VkResult res = vmaDefragmentationBegin(allocator, &info2, pDefragmentationStats, &ctx);
+    if(res == VK_NOT_READY)
+    {
+        res = vmaDefragmentationEnd( allocator, ctx);
+    }
+    return res;
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaDefragmentationBegin(
+    VmaAllocator allocator,
+    const VmaDefragmentationInfo2* pInfo,
+    VmaDefragmentationStats* pStats,
+    VmaDefragmentationContext *pContext)
+{
+    VMA_ASSERT(allocator && pInfo && pContext);
+
+    // Degenerate case: Nothing to defragment.
+    if(pInfo->allocationCount == 0 && pInfo->poolCount == 0)
+    {
+        return VK_SUCCESS;
+    }
+
+    VMA_ASSERT(pInfo->allocationCount == 0 || pInfo->pAllocations != VMA_NULL);
+    VMA_ASSERT(pInfo->poolCount == 0 || pInfo->pPools != VMA_NULL);
+    VMA_HEAVY_ASSERT(VmaValidatePointerArray(pInfo->allocationCount, pInfo->pAllocations));
+    VMA_HEAVY_ASSERT(VmaValidatePointerArray(pInfo->poolCount, pInfo->pPools));
+
+    VMA_DEBUG_LOG("vmaDefragmentationBegin");
+
+    VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+    VkResult res = allocator->DefragmentationBegin(*pInfo, pStats, pContext);
+
+#if VMA_RECORDING_ENABLED
+    if(allocator->GetRecorder() != VMA_NULL)
+    {
+        allocator->GetRecorder()->RecordDefragmentationBegin(
+            allocator->GetCurrentFrameIndex(), *pInfo, *pContext);
+    }
+#endif
+
+    return res;
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaDefragmentationEnd(
+    VmaAllocator allocator,
+    VmaDefragmentationContext context)
+{
+    VMA_ASSERT(allocator);
+
+    VMA_DEBUG_LOG("vmaDefragmentationEnd");
+
+    if(context != VK_NULL_HANDLE)
+    {
+        VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+#if VMA_RECORDING_ENABLED
+        if(allocator->GetRecorder() != VMA_NULL)
+        {
+            allocator->GetRecorder()->RecordDefragmentationEnd(
+                allocator->GetCurrentFrameIndex(), context);
+        }
+#endif
+
+        return allocator->DefragmentationEnd(context);
+    }
+    else
+    {
+        return VK_SUCCESS;
+    }
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaBeginDefragmentationPass(
+    VmaAllocator allocator,
+    VmaDefragmentationContext context,
+    VmaDefragmentationPassInfo* pInfo
+    )
+{
+    VMA_ASSERT(allocator);
+    VMA_ASSERT(pInfo);
+    VMA_HEAVY_ASSERT(VmaValidatePointerArray(pInfo->moveCount, pInfo->pMoves));
+
+    VMA_DEBUG_LOG("vmaBeginDefragmentationPass");
+
+    VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+    if(context == VK_NULL_HANDLE)
+    {
+        pInfo->moveCount = 0;
+        return VK_SUCCESS;
+    }
+
+    return allocator->DefragmentationPassBegin(pInfo, context);
+}
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaEndDefragmentationPass(
+    VmaAllocator allocator,
+    VmaDefragmentationContext context)
+{
+    VMA_ASSERT(allocator);
+
+    VMA_DEBUG_LOG("vmaEndDefragmentationPass");
+    VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+    if(context == VK_NULL_HANDLE)
+        return VK_SUCCESS;
+
+    return allocator->DefragmentationPassEnd(context);
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindBufferMemory(
+    VmaAllocator allocator,
+    VmaAllocation allocation,
+    VkBuffer buffer)
+{
+    VMA_ASSERT(allocator && allocation && buffer);
+
+    VMA_DEBUG_LOG("vmaBindBufferMemory");
+
+    VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+    return allocator->BindBufferMemory(allocation, 0, buffer, VMA_NULL);
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindBufferMemory2(
+    VmaAllocator allocator,
+    VmaAllocation allocation,
+    VkDeviceSize allocationLocalOffset,
+    VkBuffer buffer,
+    const void* pNext)
+{
+    VMA_ASSERT(allocator && allocation && buffer);
+
+    VMA_DEBUG_LOG("vmaBindBufferMemory2");
+
+    VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+    return allocator->BindBufferMemory(allocation, allocationLocalOffset, buffer, pNext);
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindImageMemory(
+    VmaAllocator allocator,
+    VmaAllocation allocation,
+    VkImage image)
+{
+    VMA_ASSERT(allocator && allocation && image);
+
+    VMA_DEBUG_LOG("vmaBindImageMemory");
+
+    VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+    return allocator->BindImageMemory(allocation, 0, image, VMA_NULL);
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindImageMemory2(
+    VmaAllocator allocator,
+    VmaAllocation allocation,
+    VkDeviceSize allocationLocalOffset,
+    VkImage image,
+    const void* pNext)
+{
+    VMA_ASSERT(allocator && allocation && image);
+
+    VMA_DEBUG_LOG("vmaBindImageMemory2");
+
+    VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+        return allocator->BindImageMemory(allocation, allocationLocalOffset, image, pNext);
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateBuffer(
+    VmaAllocator allocator,
+    const VkBufferCreateInfo* pBufferCreateInfo,
+    const VmaAllocationCreateInfo* pAllocationCreateInfo,
+    VkBuffer* pBuffer,
+    VmaAllocation* pAllocation,
+    VmaAllocationInfo* pAllocationInfo)
+{
+    VMA_ASSERT(allocator && pBufferCreateInfo && pAllocationCreateInfo && pBuffer && pAllocation);
+
+    if(pBufferCreateInfo->size == 0)
+    {
+        return VK_ERROR_VALIDATION_FAILED_EXT;
+    }
+    if((pBufferCreateInfo->usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_COPY) != 0 &&
+        !allocator->m_UseKhrBufferDeviceAddress)
+    {
+        VMA_ASSERT(0 && "Creating a buffer with VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT is not valid if VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT was not used.");
+        return VK_ERROR_VALIDATION_FAILED_EXT;
+    }
+    
+    VMA_DEBUG_LOG("vmaCreateBuffer");
+    
+    VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+    *pBuffer = VK_NULL_HANDLE;
+    *pAllocation = VK_NULL_HANDLE;
+
+    // 1. Create VkBuffer.
+    VkResult res = (*allocator->GetVulkanFunctions().vkCreateBuffer)(
+        allocator->m_hDevice,
+        pBufferCreateInfo,
+        allocator->GetAllocationCallbacks(),
+        pBuffer);
+    if(res >= 0)
+    {
+        // 2. vkGetBufferMemoryRequirements.
+        VkMemoryRequirements vkMemReq = {};
+        bool requiresDedicatedAllocation = false;
+        bool prefersDedicatedAllocation  = false;
+        allocator->GetBufferMemoryRequirements(*pBuffer, vkMemReq,
+            requiresDedicatedAllocation, prefersDedicatedAllocation);
+
+        // 3. Allocate memory using allocator.
+        res = allocator->AllocateMemory(
+            vkMemReq,
+            requiresDedicatedAllocation,
+            prefersDedicatedAllocation,
+            *pBuffer, // dedicatedBuffer
+            pBufferCreateInfo->usage, // dedicatedBufferUsage
+            VK_NULL_HANDLE, // dedicatedImage
+            *pAllocationCreateInfo,
+            VMA_SUBALLOCATION_TYPE_BUFFER,
+            1, // allocationCount
+            pAllocation);
+
+#if VMA_RECORDING_ENABLED
+        if(allocator->GetRecorder() != VMA_NULL)
+        {
+            allocator->GetRecorder()->RecordCreateBuffer(
+                allocator->GetCurrentFrameIndex(),
+                *pBufferCreateInfo,
+                *pAllocationCreateInfo,
+                *pAllocation);
+        }
+#endif
+
+        if(res >= 0)
+        {
+            // 3. Bind buffer with memory.
+            if((pAllocationCreateInfo->flags & VMA_ALLOCATION_CREATE_DONT_BIND_BIT) == 0)
+            {
+                res = allocator->BindBufferMemory(*pAllocation, 0, *pBuffer, VMA_NULL);
+            }
+            if(res >= 0)
+            {
+                // All steps succeeded.
+                #if VMA_STATS_STRING_ENABLED
+                    (*pAllocation)->InitBufferImageUsage(pBufferCreateInfo->usage);
+                #endif
+                if(pAllocationInfo != VMA_NULL)
+                {
+                    allocator->GetAllocationInfo(*pAllocation, pAllocationInfo);
+                }
+
+                return VK_SUCCESS;
+            }
+            allocator->FreeMemory(
+                1, // allocationCount
+                pAllocation);
+            *pAllocation = VK_NULL_HANDLE;
+            (*allocator->GetVulkanFunctions().vkDestroyBuffer)(allocator->m_hDevice, *pBuffer, allocator->GetAllocationCallbacks());
+            *pBuffer = VK_NULL_HANDLE;
+            return res;
+        }
+        (*allocator->GetVulkanFunctions().vkDestroyBuffer)(allocator->m_hDevice, *pBuffer, allocator->GetAllocationCallbacks());
+        *pBuffer = VK_NULL_HANDLE;
+        return res;
+    }
+    return res;
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaDestroyBuffer(
+    VmaAllocator allocator,
+    VkBuffer buffer,
+    VmaAllocation allocation)
+{
+    VMA_ASSERT(allocator);
+
+    if(buffer == VK_NULL_HANDLE && allocation == VK_NULL_HANDLE)
+    {
+        return;
+    }
+
+    VMA_DEBUG_LOG("vmaDestroyBuffer");
+
+    VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+#if VMA_RECORDING_ENABLED
+    if(allocator->GetRecorder() != VMA_NULL)
+    {
+        allocator->GetRecorder()->RecordDestroyBuffer(
+            allocator->GetCurrentFrameIndex(),
+            allocation);
+    }
+#endif
+
+    if(buffer != VK_NULL_HANDLE)
+    {
+        (*allocator->GetVulkanFunctions().vkDestroyBuffer)(allocator->m_hDevice, buffer, allocator->GetAllocationCallbacks());
+    }
+
+    if(allocation != VK_NULL_HANDLE)
+    {
+        allocator->FreeMemory(
+            1, // allocationCount
+            &allocation);
+    }
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateImage(
+    VmaAllocator allocator,
+    const VkImageCreateInfo* pImageCreateInfo,
+    const VmaAllocationCreateInfo* pAllocationCreateInfo,
+    VkImage* pImage,
+    VmaAllocation* pAllocation,
+    VmaAllocationInfo* pAllocationInfo)
+{
+    VMA_ASSERT(allocator && pImageCreateInfo && pAllocationCreateInfo && pImage && pAllocation);
+
+    if(pImageCreateInfo->extent.width == 0 ||
+        pImageCreateInfo->extent.height == 0 ||
+        pImageCreateInfo->extent.depth == 0 ||
+        pImageCreateInfo->mipLevels == 0 ||
+        pImageCreateInfo->arrayLayers == 0)
+    {
+        return VK_ERROR_VALIDATION_FAILED_EXT;
+    }
+
+    VMA_DEBUG_LOG("vmaCreateImage");
+
+    VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+    *pImage = VK_NULL_HANDLE;
+    *pAllocation = VK_NULL_HANDLE;
+
+    // 1. Create VkImage.
+    VkResult res = (*allocator->GetVulkanFunctions().vkCreateImage)(
+        allocator->m_hDevice,
+        pImageCreateInfo,
+        allocator->GetAllocationCallbacks(),
+        pImage);
+    if(res >= 0)
+    {
+        VmaSuballocationType suballocType = pImageCreateInfo->tiling == VK_IMAGE_TILING_OPTIMAL ?
+            VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL :
+            VMA_SUBALLOCATION_TYPE_IMAGE_LINEAR;
+        
+        // 2. Allocate memory using allocator.
+        VkMemoryRequirements vkMemReq = {};
+        bool requiresDedicatedAllocation = false;
+        bool prefersDedicatedAllocation  = false;
+        allocator->GetImageMemoryRequirements(*pImage, vkMemReq,
+            requiresDedicatedAllocation, prefersDedicatedAllocation);
+
+        res = allocator->AllocateMemory(
+            vkMemReq,
+            requiresDedicatedAllocation,
+            prefersDedicatedAllocation,
+            VK_NULL_HANDLE, // dedicatedBuffer
+            UINT32_MAX, // dedicatedBufferUsage
+            *pImage, // dedicatedImage
+            *pAllocationCreateInfo,
+            suballocType,
+            1, // allocationCount
+            pAllocation);
+
+#if VMA_RECORDING_ENABLED
+        if(allocator->GetRecorder() != VMA_NULL)
+        {
+            allocator->GetRecorder()->RecordCreateImage(
+                allocator->GetCurrentFrameIndex(),
+                *pImageCreateInfo,
+                *pAllocationCreateInfo,
+                *pAllocation);
+        }
+#endif
+
+        if(res >= 0)
+        {
+            // 3. Bind image with memory.
+            if((pAllocationCreateInfo->flags & VMA_ALLOCATION_CREATE_DONT_BIND_BIT) == 0)
+            {
+                res = allocator->BindImageMemory(*pAllocation, 0, *pImage, VMA_NULL);
+            }
+            if(res >= 0)
+            {
+                // All steps succeeded.
+                #if VMA_STATS_STRING_ENABLED
+                    (*pAllocation)->InitBufferImageUsage(pImageCreateInfo->usage);
+                #endif
+                if(pAllocationInfo != VMA_NULL)
+                {
+                    allocator->GetAllocationInfo(*pAllocation, pAllocationInfo);
+                }
+
+                return VK_SUCCESS;
+            }
+            allocator->FreeMemory(
+                1, // allocationCount
+                pAllocation);
+            *pAllocation = VK_NULL_HANDLE;
+            (*allocator->GetVulkanFunctions().vkDestroyImage)(allocator->m_hDevice, *pImage, allocator->GetAllocationCallbacks());
+            *pImage = VK_NULL_HANDLE;
+            return res;
+        }
+        (*allocator->GetVulkanFunctions().vkDestroyImage)(allocator->m_hDevice, *pImage, allocator->GetAllocationCallbacks());
+        *pImage = VK_NULL_HANDLE;
+        return res;
+    }
+    return res;
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaDestroyImage(
+    VmaAllocator allocator,
+    VkImage image,
+    VmaAllocation allocation)
+{
+    VMA_ASSERT(allocator);
+
+    if(image == VK_NULL_HANDLE && allocation == VK_NULL_HANDLE)
+    {
+        return;
+    }
+
+    VMA_DEBUG_LOG("vmaDestroyImage");
+
+    VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+#if VMA_RECORDING_ENABLED
+    if(allocator->GetRecorder() != VMA_NULL)
+    {
+        allocator->GetRecorder()->RecordDestroyImage(
+            allocator->GetCurrentFrameIndex(),
+            allocation);
+    }
+#endif
+
+    if(image != VK_NULL_HANDLE)
+    {
+        (*allocator->GetVulkanFunctions().vkDestroyImage)(allocator->m_hDevice, image, allocator->GetAllocationCallbacks());
+    }
+    if(allocation != VK_NULL_HANDLE)
+    {
+        allocator->FreeMemory(
+            1, // allocationCount
+            &allocation);
+    }
+}
+
+#endif // #ifdef VMA_IMPLEMENTATION
diff --git a/third_party/VulkanMemoryAllocator/src/vk_mem_alloc.natvis b/third_party/VulkanMemoryAllocator/src/vk_mem_alloc.natvis
new file mode 100644
index 0000000..85c7533
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/src/vk_mem_alloc.natvis
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?> 
+<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
+    <Type Name="VmaRawList&lt;*&gt;">
+        <DisplayString>{{ Count={m_Count} }}</DisplayString>
+        <Expand>
+            <Item Name="[Count]">m_Count</Item>
+            <LinkedListItems>
+                <Size>m_Count</Size>
+                <HeadPointer>m_pFront</HeadPointer>
+                <NextPointer>pNext</NextPointer>
+                <ValueNode>Value</ValueNode>
+            </LinkedListItems>
+        </Expand>
+    </Type>
+
+    <Type Name="VmaList&lt;*&gt;">
+        <DisplayString>{{ Count={m_RawList.m_Count} }}</DisplayString>
+        <Expand>
+            <Item Name="[Count]">m_RawList.m_Count</Item>
+            <LinkedListItems>
+                <Size>m_RawList.m_Count</Size>
+                <HeadPointer>m_RawList.m_pFront</HeadPointer>
+                <NextPointer>pNext</NextPointer>
+                <ValueNode>Value</ValueNode>
+            </LinkedListItems>
+        </Expand>
+    </Type>
+
+    <Type Name="VmaVector&lt;*&gt;">
+        <DisplayString>{{ Count={m_Count} }}</DisplayString>
+        <Expand>
+            <Item Name="[Count]">m_Count</Item>
+            <Item Name="[Capacity]">m_Capacity</Item>
+            <ArrayItems>
+                <Size>m_Count</Size>
+                <ValuePointer>m_pArray</ValuePointer>
+            </ArrayItems>
+        </Expand>
+    </Type>
+</AutoVisualizer>
\ No newline at end of file
diff --git a/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README.md b/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README.md
new file mode 100644
index 0000000..f238001
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README.md
@@ -0,0 +1,42 @@
+# VMA Dump Vis
+
+Vulkan Memory Allocator Dump Visualization. It is an auxiliary tool that can visualize internal state of [Vulkan Memory Allocator](../../README.md) library on a picture. It is a Python script that must be launched from command line with appropriate parameters.
+
+## Requirements
+
+- Python 3 installed
+- [Pillow](http://python-pillow.org/) - Python Imaging Library (Fork) installed
+
+## Usage
+
+```
+python VmaDumpVis.py -o OUTPUT_FILE INPUT_FILE
+```
+
+* `INPUT_FILE` - path to source file to be read, containing dump of internal state of the VMA library in JSON format (encoding: UTF-8), generated using `vmaBuildStatsString()` function.
+* `OUTPUT_FILE` - path to destination file to be written that will contain generated image. Image format is automatically recognized based on file extension. List of supported formats can be found [here](http://pillow.readthedocs.io/en/latest/handbook/image-file-formats.html) and includes: BMP, GIF, JPEG, PNG, TGA.
+
+You can also use typical options:
+
+* `-h` - to see help on command line syntax
+* `-v` - to see program version number
+
+## Example output
+
+![Example output](README_files/ExampleOutput.png "Example output")
+
+## Legend
+
+* ![Free space](README_files/Legend_Bkg.png "Free space") Light gray without border - a space in Vulkan device memory block unused by any allocation.
+* ![Buffer 1](README_files/Legend_Buffer_1.png "Buffer 1") Buffer with usage containing INDIRECT_BUFFER, VERTEX_BUFFER, or INDEX_BUFFER.
+* ![Buffer 2](README_files/Legend_Buffer_2.png "Buffer 2") Buffer with usage containing STORAGE_BUFFER or STORAGE_TEXEL_BUFFER.
+* ![Buffer 3](README_files/Legend_Buffer_3.png "Buffer 3") Buffer with usage containing UNIFORM_BUFFER or UNIFORM_TEXEL_BUFFER.
+* ![Buffer 4](README_files/Legend_Buffer_4.png "Buffer 4") Other buffer.
+* ![Image 1](README_files/Legend_Image_1.png "Image 1") Image with OPTIMAL tiling and usage containing DEPTH_STENCIL_ATTACHMENT.
+* ![Image 2](README_files/Legend_Image_2.png "Image 2") Image with OPTIMAL tiling and usage containing INPUT_ATTACHMENT, TRANSIENT_ATTACHMENT, or COLOR_ATTACHMENT.
+* ![Image 3](README_files/Legend_Image_3.png "Image 3") Image with OPTIMAL tiling and usage containing SAMPLED.
+* ![Image 4](README_files/Legend_Image_4.png "Image 4") Other image with OPTIMAL tiling.
+* ![Image Linear](README_files/Legend_Image_Linear.png "Image Linear") Image with LINEAR tiling.
+* ![Image Unknown](README_files/Legend_Image_Unknown.png "Image Unknown") Image with tiling unknown to the allocator.
+* ![Unknown](README_files/Legend_Unknown.png "Unknown") Allocation of unknown type.
+* ![Details](README_files/Legend_Details.png "Details") Black bar - one or more allocations of any kind too small to be visualized as filled rectangles.
diff --git a/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/ExampleOutput.png b/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/ExampleOutput.png
new file mode 100644
index 0000000..2646ed2
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/ExampleOutput.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/Legend_Bkg.png b/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/Legend_Bkg.png
new file mode 100644
index 0000000..f8fd89f
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/Legend_Bkg.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/Legend_Buffer_1.png b/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/Legend_Buffer_1.png
new file mode 100644
index 0000000..3805225
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/Legend_Buffer_1.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/Legend_Buffer_2.png b/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/Legend_Buffer_2.png
new file mode 100644
index 0000000..bc3773f
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/Legend_Buffer_2.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/Legend_Buffer_3.png b/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/Legend_Buffer_3.png
new file mode 100644
index 0000000..992d8b2
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/Legend_Buffer_3.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/Legend_Buffer_4.png b/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/Legend_Buffer_4.png
new file mode 100644
index 0000000..d29f54e
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/Legend_Buffer_4.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/Legend_Details.png b/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/Legend_Details.png
new file mode 100644
index 0000000..a9c8535
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/Legend_Details.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/Legend_Image_1.png b/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/Legend_Image_1.png
new file mode 100644
index 0000000..dc180af
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/Legend_Image_1.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/Legend_Image_2.png b/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/Legend_Image_2.png
new file mode 100644
index 0000000..fc35c7c
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/Legend_Image_2.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/Legend_Image_3.png b/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/Legend_Image_3.png
new file mode 100644
index 0000000..b69849d
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/Legend_Image_3.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/Legend_Image_4.png b/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/Legend_Image_4.png
new file mode 100644
index 0000000..7f3980e
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/Legend_Image_4.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/Legend_Image_Linear.png b/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/Legend_Image_Linear.png
new file mode 100644
index 0000000..36d8be5
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/Legend_Image_Linear.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/Legend_Image_Unknown.png b/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/Legend_Image_Unknown.png
new file mode 100644
index 0000000..f3f40ec
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/Legend_Image_Unknown.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/Legend_Unknown.png b/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/Legend_Unknown.png
new file mode 100644
index 0000000..3053726
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/README_files/Legend_Unknown.png
Binary files differ
diff --git a/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/Sample.json b/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/Sample.json
new file mode 100644
index 0000000..34698a3
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/Sample.json
@@ -0,0 +1,102 @@
+{
+  "Total": {
+    "Blocks": 2,
+    "Allocations": 4,
+    "UnusedRanges": 3,
+    "UsedBytes": 8062124,
+    "UnusedBytes": 59046740,
+    "AllocationSize": {"Min": 60, "Avg": 2015531, "Max": 7995760},
+    "UnusedRangeSize": {"Min": 64708, "Avg": 19682247, "Max": 33554432}
+  },
+  "Heap 0": {
+    "Size": 8304721920,
+    "Flags": ["DEVICE_LOCAL"],
+    "Stats": {
+      "Blocks": 1,
+      "Allocations": 4,
+      "UnusedRanges": 2,
+      "UsedBytes": 8062124,
+      "UnusedBytes": 25492308,
+      "AllocationSize": {"Min": 60, "Avg": 2015531, "Max": 7995760},
+      "UnusedRangeSize": {"Min": 64708, "Avg": 12746154, "Max": 25427600}
+    },
+    "Type 0": {
+      "Flags": ["DEVICE_LOCAL"],
+      "Stats": {
+        "Blocks": 1,
+        "Allocations": 4,
+        "UnusedRanges": 2,
+        "UsedBytes": 8062124,
+        "UnusedBytes": 25492308,
+        "AllocationSize": {"Min": 60, "Avg": 2015531, "Max": 7995760},
+        "UnusedRangeSize": {"Min": 64708, "Avg": 12746154, "Max": 25427600}
+      }
+    }
+  },
+  "Heap 1": {
+    "Size": 8285323264,
+    "Flags": [],
+    "Stats": {
+      "Blocks": 1,
+      "Allocations": 0,
+      "UnusedRanges": 1,
+      "UsedBytes": 0,
+      "UnusedBytes": 33554432
+    },
+    "Type 1": {
+      "Flags": ["HOST_VISIBLE", "HOST_COHERENT"],
+      "Stats": {
+        "Blocks": 1,
+        "Allocations": 0,
+        "UnusedRanges": 1,
+        "UsedBytes": 0,
+        "UnusedBytes": 33554432
+      }
+    },
+    "Type 3": {
+      "Flags": ["HOST_VISIBLE", "HOST_COHERENT", "HOST_CACHED"]
+    }
+  },
+  "Heap 2": {
+    "Size": 268435456,
+    "Flags": ["DEVICE_LOCAL"],
+    "Type 2": {
+      "Flags": ["DEVICE_LOCAL", "HOST_VISIBLE", "HOST_COHERENT"]
+    }
+  },
+  "DefaultPools": {
+    "Type 0": {
+      "PreferredBlockSize": 268435456,
+      "Blocks": {
+        "0": {
+          "TotalBytes": 33554432,
+          "UnusedBytes": 25492308,
+          "Allocations": 4,
+          "UnusedRanges": 2,
+          "Suballocations": [
+            {"Offset": 0, "Type": "IMAGE_OPTIMAL", "Size": 65536, "CreationFrameIndex": 0, "LastUseFrameIndex": 0, "Usage": 6},
+            {"Offset": 65536, "Type": "BUFFER", "Size": 768, "CreationFrameIndex": 0, "LastUseFrameIndex": 0, "Usage": 130},
+            {"Offset": 66304, "Type": "BUFFER", "Size": 60, "CreationFrameIndex": 0, "LastUseFrameIndex": 0, "Usage": 66},
+            {"Offset": 66364, "Type": "FREE", "Size": 64708},
+            {"Offset": 131072, "Type": "IMAGE_OPTIMAL", "Size": 7995760, "CreationFrameIndex": 0, "LastUseFrameIndex": 0, "Usage": 32},
+            {"Offset": 8126832, "Type": "FREE", "Size": 25427600}
+          ]
+        }
+      }
+    },
+    "Type 1": {
+      "PreferredBlockSize": 268435456,
+      "Blocks": {
+        "0": {
+          "TotalBytes": 33554432,
+          "UnusedBytes": 33554432,
+          "Allocations": 0,
+          "UnusedRanges": 1,
+          "Suballocations": [
+            {"Offset": 0, "Type": "FREE", "Size": 33554432}
+          ]
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/VmaDumpVis.py b/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/VmaDumpVis.py
new file mode 100644
index 0000000..415b682
--- /dev/null
+++ b/third_party/VulkanMemoryAllocator/tools/VmaDumpVis/VmaDumpVis.py
@@ -0,0 +1,287 @@
+#
+# Copyright (c) 2018-2020 Advanced Micro Devices, Inc. All rights reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+
+import argparse
+import json
+from PIL import Image, ImageDraw, ImageFont
+
+
+PROGRAM_VERSION = 'VMA Dump Visualization 2.0.1'
+IMG_SIZE_X = 1200
+IMG_MARGIN = 8
+FONT_SIZE = 10
+MAP_SIZE = 24
+COLOR_TEXT_H1 = (0, 0, 0, 255)
+COLOR_TEXT_H2 = (150, 150, 150, 255)
+COLOR_OUTLINE = (155, 155, 155, 255)
+COLOR_OUTLINE_HARD = (0, 0, 0, 255)
+COLOR_GRID_LINE = (224, 224, 224, 255)
+
+
+argParser = argparse.ArgumentParser(description='Visualization of Vulkan Memory Allocator JSON dump.')
+argParser.add_argument('DumpFile', type=argparse.FileType(mode='r', encoding='UTF-8'), help='Path to source JSON file with memory dump created by Vulkan Memory Allocator library')
+argParser.add_argument('-v', '--version', action='version', version=PROGRAM_VERSION)
+argParser.add_argument('-o', '--output', required=True, help='Path to destination image file (e.g. PNG)')
+args = argParser.parse_args()
+
+data = {}
+
+
+def ProcessBlock(dstBlockList, iBlockId, objBlock, sAlgorithm):
+    iBlockSize = int(objBlock['TotalBytes'])
+    arrSuballocs = objBlock['Suballocations']
+    dstBlockObj = {'ID': iBlockId, 'Size':iBlockSize, 'Suballocations':[]}
+    dstBlockObj['Algorithm'] = sAlgorithm
+    for objSuballoc in arrSuballocs:
+        dstBlockObj['Suballocations'].append((objSuballoc['Type'], int(objSuballoc['Size']), int(objSuballoc['Usage']) if ('Usage' in objSuballoc) else 0))
+    dstBlockList.append(dstBlockObj)
+
+
+def GetDataForMemoryType(iMemTypeIndex):
+    global data
+    if iMemTypeIndex in data:
+        return data[iMemTypeIndex]
+    else:
+        newMemTypeData = {'DedicatedAllocations':[], 'DefaultPoolBlocks':[], 'CustomPools':{}}
+        data[iMemTypeIndex] = newMemTypeData
+        return newMemTypeData
+
+
+# Returns tuple:
+# [0] image height : integer
+# [1] pixels per byte : float
+def CalcParams():
+    global data
+    iImgSizeY = IMG_MARGIN
+    iImgSizeY += FONT_SIZE + IMG_MARGIN # Grid lines legend - sizes
+    iMaxBlockSize = 0
+    for dictMemType in data.values():
+        iImgSizeY += IMG_MARGIN + FONT_SIZE
+        lDedicatedAllocations = dictMemType['DedicatedAllocations']
+        iImgSizeY += len(lDedicatedAllocations) * (IMG_MARGIN * 2 + FONT_SIZE + MAP_SIZE)
+        for tDedicatedAlloc in lDedicatedAllocations:
+            iMaxBlockSize = max(iMaxBlockSize, tDedicatedAlloc[1])
+        lDefaultPoolBlocks = dictMemType['DefaultPoolBlocks']
+        iImgSizeY += len(lDefaultPoolBlocks) * (IMG_MARGIN * 2 + FONT_SIZE + MAP_SIZE)
+        for objBlock in lDefaultPoolBlocks:
+            iMaxBlockSize = max(iMaxBlockSize, objBlock['Size'])
+        dCustomPools = dictMemType['CustomPools']
+        for lBlocks in dCustomPools.values():
+            iImgSizeY += len(lBlocks) * (IMG_MARGIN * 2 + FONT_SIZE + MAP_SIZE)
+            for objBlock in lBlocks:
+                iMaxBlockSize = max(iMaxBlockSize, objBlock['Size'])
+    fPixelsPerByte = (IMG_SIZE_X - IMG_MARGIN * 2) / float(iMaxBlockSize)
+    return iImgSizeY, fPixelsPerByte
+
+
+def TypeToColor(sType, iUsage):
+    if sType == 'FREE':
+        return 220, 220, 220, 255
+    elif sType == 'BUFFER':
+        if (iUsage & 0x1C0) != 0: # INDIRECT_BUFFER | VERTEX_BUFFER | INDEX_BUFFER
+            return 255, 148, 148, 255 # Red
+        elif (iUsage & 0x28) != 0: # STORAGE_BUFFER | STORAGE_TEXEL_BUFFER
+            return 255, 187, 121, 255 # Orange
+        elif (iUsage & 0x14) != 0: # UNIFORM_BUFFER | UNIFORM_TEXEL_BUFFER
+            return 255, 255, 0, 255 # Yellow
+        else:
+            return 255, 255, 165, 255 # Light yellow
+    elif sType == 'IMAGE_OPTIMAL':
+        if (iUsage & 0x20) != 0: # DEPTH_STENCIL_ATTACHMENT
+            return 246, 128, 255, 255 # Pink
+        elif (iUsage & 0xD0) != 0: # INPUT_ATTACHMENT | TRANSIENT_ATTACHMENT | COLOR_ATTACHMENT
+            return 179, 179, 255, 255 # Blue
+        elif (iUsage & 0x4) != 0: # SAMPLED
+            return 0, 255, 255, 255 # Aqua
+        else:
+            return 183, 255, 255, 255 # Light aqua
+    elif sType == 'IMAGE_LINEAR':
+        return 0, 255, 0, 255 # Green
+    elif sType == 'IMAGE_UNKNOWN':
+        return 0, 255, 164, 255 # Green/aqua
+    elif sType == 'UNKNOWN':
+        return 175, 175, 175, 255 # Gray
+    assert False
+    return 0, 0, 0, 255
+
+
+def DrawDedicatedAllocationBlock(draw, y, tDedicatedAlloc): 
+    global fPixelsPerByte
+    iSizeBytes = tDedicatedAlloc[1]
+    iSizePixels = int(iSizeBytes * fPixelsPerByte)
+    draw.rectangle([IMG_MARGIN, y, IMG_MARGIN + iSizePixels, y + MAP_SIZE], fill=TypeToColor(tDedicatedAlloc[0], tDedicatedAlloc[2]), outline=COLOR_OUTLINE)
+
+
+def DrawBlock(draw, y, objBlock):
+    global fPixelsPerByte
+    iSizeBytes = objBlock['Size']
+    iSizePixels = int(iSizeBytes * fPixelsPerByte)
+    draw.rectangle([IMG_MARGIN, y, IMG_MARGIN + iSizePixels, y + MAP_SIZE], fill=TypeToColor('FREE', 0), outline=None)
+    iByte = 0
+    iX = 0
+    iLastHardLineX = -1
+    for tSuballoc in objBlock['Suballocations']:
+        sType = tSuballoc[0]
+        iByteEnd = iByte + tSuballoc[1]
+        iXEnd = int(iByteEnd * fPixelsPerByte)
+        if sType != 'FREE':
+            if iXEnd > iX + 1:
+                iUsage = tSuballoc[2]
+                draw.rectangle([IMG_MARGIN + iX, y, IMG_MARGIN + iXEnd, y + MAP_SIZE], fill=TypeToColor(sType, iUsage), outline=COLOR_OUTLINE)
+                # Hard line was been overwritten by rectangle outline: redraw it.
+                if iLastHardLineX == iX:
+                    draw.line([IMG_MARGIN + iX, y, IMG_MARGIN + iX, y + MAP_SIZE], fill=COLOR_OUTLINE_HARD)
+            else:
+                draw.line([IMG_MARGIN + iX, y, IMG_MARGIN + iX, y + MAP_SIZE], fill=COLOR_OUTLINE_HARD)
+                iLastHardLineX = iX
+        iByte = iByteEnd
+        iX = iXEnd
+
+
+def BytesToStr(iBytes):
+    if iBytes < 1024:
+        return "%d B" % iBytes
+    iBytes /= 1024
+    if iBytes < 1024:
+        return "%d KiB" % iBytes
+    iBytes /= 1024
+    if iBytes < 1024:
+        return "%d MiB" % iBytes
+    iBytes /= 1024
+    return "%d GiB" % iBytes
+
+
+jsonSrc = json.load(args.DumpFile)
+if 'DedicatedAllocations' in jsonSrc:
+    for tType in jsonSrc['DedicatedAllocations'].items():
+        sType = tType[0]
+        assert sType[:5] == 'Type '
+        iType = int(sType[5:])
+        typeData = GetDataForMemoryType(iType)
+        for objAlloc in tType[1]:
+            typeData['DedicatedAllocations'].append((objAlloc['Type'], int(objAlloc['Size']), int(objAlloc['Usage']) if ('Usage' in objAlloc) else 0))
+if 'DefaultPools' in jsonSrc:
+    for tType in jsonSrc['DefaultPools'].items():
+        sType = tType[0]
+        assert sType[:5] == 'Type '
+        iType = int(sType[5:])
+        typeData = GetDataForMemoryType(iType)
+        for sBlockId, objBlock in tType[1]['Blocks'].items():
+            ProcessBlock(typeData['DefaultPoolBlocks'], int(sBlockId), objBlock, '')
+if 'Pools' in jsonSrc:
+    objPools = jsonSrc['Pools']
+    for sPoolId, objPool in objPools.items():
+        iType = int(objPool['MemoryTypeIndex'])
+        typeData = GetDataForMemoryType(iType)
+        objBlocks = objPool['Blocks']
+        sAlgorithm = objPool.get('Algorithm', '')
+        sName = objPool.get('Name', None)
+        if sName:
+            sFullName = sPoolId + ' "' + sName + '"'
+        else:
+            sFullName = sPoolId
+        dstBlockArray = []
+        typeData['CustomPools'][sFullName] = dstBlockArray
+        for sBlockId, objBlock in objBlocks.items():
+            ProcessBlock(dstBlockArray, int(sBlockId), objBlock, sAlgorithm)
+
+iImgSizeY, fPixelsPerByte = CalcParams()
+
+img = Image.new('RGB', (IMG_SIZE_X, iImgSizeY), 'white')
+draw = ImageDraw.Draw(img)
+
+try:
+    font = ImageFont.truetype('segoeuib.ttf')
+except:
+    font = ImageFont.load_default()
+
+y = IMG_MARGIN
+
+# Draw grid lines
+iBytesBetweenGridLines = 32
+while iBytesBetweenGridLines * fPixelsPerByte < 64:
+    iBytesBetweenGridLines *= 2
+iByte = 0
+TEXT_MARGIN = 4
+while True:
+    iX = int(iByte * fPixelsPerByte)
+    if iX > IMG_SIZE_X - 2 * IMG_MARGIN:
+        break
+    draw.line([iX + IMG_MARGIN, 0, iX + IMG_MARGIN, iImgSizeY], fill=COLOR_GRID_LINE)
+    if iByte == 0:
+        draw.text((iX + IMG_MARGIN + TEXT_MARGIN, y), "0", fill=COLOR_TEXT_H2, font=font)
+    else:
+        text = BytesToStr(iByte)
+        textSize = draw.textsize(text, font=font)
+        draw.text((iX + IMG_MARGIN - textSize[0] - TEXT_MARGIN, y), text, fill=COLOR_TEXT_H2, font=font)
+    iByte += iBytesBetweenGridLines
+y += FONT_SIZE + IMG_MARGIN
+
+# Draw main content
+for iMemTypeIndex in sorted(data.keys()):
+    dictMemType = data[iMemTypeIndex]
+    draw.text((IMG_MARGIN, y), "Memory type %d" % iMemTypeIndex, fill=COLOR_TEXT_H1, font=font)
+    y += FONT_SIZE + IMG_MARGIN
+    index = 0
+    for tDedicatedAlloc in dictMemType['DedicatedAllocations']:
+        draw.text((IMG_MARGIN, y), "Dedicated allocation %d" % index, fill=COLOR_TEXT_H2, font=font)
+        y += FONT_SIZE + IMG_MARGIN
+        DrawDedicatedAllocationBlock(draw, y, tDedicatedAlloc)
+        y += MAP_SIZE + IMG_MARGIN
+        index += 1
+    for objBlock in dictMemType['DefaultPoolBlocks']:
+        draw.text((IMG_MARGIN, y), "Default pool block %d" % objBlock['ID'], fill=COLOR_TEXT_H2, font=font)
+        y += FONT_SIZE + IMG_MARGIN
+        DrawBlock(draw, y, objBlock)
+        y += MAP_SIZE + IMG_MARGIN
+    index = 0
+    for sPoolName, listPool in dictMemType['CustomPools'].items():
+        for objBlock in listPool:
+            if 'Algorithm' in objBlock and objBlock['Algorithm']:
+                sAlgorithm = ' (Algorithm: %s)' % (objBlock['Algorithm'])
+            else:
+                sAlgorithm = ''
+            draw.text((IMG_MARGIN, y), "Custom pool %s%s block %d" % (sPoolName, sAlgorithm, objBlock['ID']), fill=COLOR_TEXT_H2, font=font)
+            y += FONT_SIZE + IMG_MARGIN
+            DrawBlock(draw, y, objBlock)
+            y += MAP_SIZE + IMG_MARGIN
+            index += 1
+del draw
+img.save(args.output)
+
+"""
+Main data structure - variable `data` - is a dictionary. Key is integer - memory type index. Value is dictionary of:
+- Fixed key 'DedicatedAllocations'. Value is list of tuples, each containing:
+    - [0]: Type : string
+    - [1]: Size : integer
+    - [2]: Usage : integer (0 if unknown)
+- Fixed key 'DefaultPoolBlocks'. Value is list of objects, each containing dictionary with:
+    - Fixed key 'ID'. Value is int.
+    - Fixed key 'Size'. Value is int.
+    - Fixed key 'Suballocations'. Value is list of tuples as above.
+- Fixed key 'CustomPools'. Value is dictionary.
+  - Key is string with pool ID/name. Value is list of objects representing memory blocks, each containing dictionary with:
+    - Fixed key 'ID'. Value is int.
+    - Fixed key 'Size'. Value is int.
+    - Fixed key 'Algorithm'. Optional. Value is string.
+    - Fixed key 'Suballocations'. Value is list of tuples as above.
+"""
diff --git a/third_party/glslang/src/BUILD.bazel b/third_party/glslang/src/BUILD.bazel
index d70bc7f..5930608 100644
--- a/third_party/glslang/src/BUILD.bazel
+++ b/third_party/glslang/src/BUILD.bazel
@@ -85,7 +85,7 @@
         "SPIRV/GLSL.ext.KHR.h",
         "SPIRV/GLSL.ext.NV.h",
         "SPIRV/GLSL.std.450.h",
-        "SPIRV/NonSemanticDebugPrintf.h",

+        "SPIRV/NonSemanticDebugPrintf.h",
         "SPIRV/spirv.hpp",
     ],
     outs = [
@@ -94,7 +94,7 @@
         "include/SPIRV/GLSL.ext.KHR.h",
         "include/SPIRV/GLSL.ext.NV.h",
         "include/SPIRV/GLSL.std.450.h",
-        "include/SPIRV/NonSemanticDebugPrintf.h",

+        "include/SPIRV/NonSemanticDebugPrintf.h",
         "include/SPIRV/spirv.hpp",
     ],
     cmd = "mkdir -p $(@D)/include/SPIRV && cp $(SRCS) $(@D)/include/SPIRV/",
diff --git a/third_party/glslang/src/BUILD.gn b/third_party/glslang/src/BUILD.gn
index 87c28e9..49b4b0a 100644
--- a/third_party/glslang/src/BUILD.gn
+++ b/third_party/glslang/src/BUILD.gn
@@ -70,7 +70,7 @@
     "SPIRV/InReadableOrder.cpp",
     "SPIRV/Logger.cpp",
     "SPIRV/Logger.h",
-    "SPIRV/NonSemanticDebugPrintf.h",

+    "SPIRV/NonSemanticDebugPrintf.h",
     "SPIRV/SPVRemapper.cpp",
     "SPIRV/SPVRemapper.h",
     "SPIRV/SpvBuilder.cpp",
diff --git a/third_party/glslang/src/CMakeLists.txt b/third_party/glslang/src/CMakeLists.txt
index a80cd5f..cd9baf8 100644
--- a/third_party/glslang/src/CMakeLists.txt
+++ b/third_party/glslang/src/CMakeLists.txt
@@ -75,7 +75,7 @@
 
 # Precompiled header macro. Parameters are source file list and filename for pch cpp file.
 macro(glslang_pch SRCS PCHCPP)
-  if(MSVC AND CMAKE_GENERATOR MATCHES "^Visual Studio" AND ENABLE_PCH)
+  if(MSVC AND CMAKE_GENERATOR MATCHES "^Visual Studio" AND NOT ${CMAKE_CXX_COMPILER_ID} MATCHES "Clang" AND ENABLE_PCH)
     set(PCH_NAME "$(IntDir)\\pch.pch")
     # make source files use/depend on PCH_NAME
     set_source_files_properties(${${SRCS}} PROPERTIES COMPILE_FLAGS "/Yupch.h /FIpch.h /Fp${PCH_NAME} /Zm300" OBJECT_DEPENDS "${PCH_NAME}")
@@ -124,14 +124,14 @@
     if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "9.0.0")
         add_compile_options(-Werror=deprecated-copy)
     endif()
-elseif(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")
+elseif(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang" AND NOT MSVC)
     add_compile_options(-Wall -Wuninitialized -Wunused -Wunused-local-typedefs
                         -Wunused-parameter -Wunused-value  -Wunused-variable)
     add_compile_options(-Wno-reorder)  # disable this from -Wall, since it happens all over.
     if(NOT ENABLE_RTTI)
         add_compile_options(-fno-rtti)
     endif()
-elseif(${CMAKE_CXX_COMPILER_ID} MATCHES "MSVC")
+elseif(MSVC)
     if(NOT ENABLE_RTTI)
         add_compile_options(/GR-) # Disable RTTI
     endif()
@@ -142,7 +142,10 @@
         add_compile_options(/Os /GR-)
     else()
         add_compile_options(-Os -fno-exceptions)
-        add_link_options(-Os)
+        if(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang" AND NOT MSVC)
+            add_compile_options(-Wno-unused-parameter)
+            add_compile_options(-Wno-unused-variable -Wno-unused-const-variable)
+        endif()
     endif()
 endif(ENABLE_GLSLANG_JS)
 
@@ -150,7 +153,7 @@
 if(${CMAKE_VERSION} VERSION_LESS 3.1)
     # CMake versions before 3.1 do not understand CMAKE_CXX_STANDARD
     # remove this block once CMake >=3.1 has fixated in the ecosystem
-    add_compile_options(-std=c++11)
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
 else()
     set(CMAKE_CXX_STANDARD 11)
     set(CMAKE_CXX_STANDARD_REQUIRED ON)
diff --git a/third_party/glslang/src/README.md b/third_party/glslang/src/README.md
index 5188ab4..ff844c0 100755
--- a/third_party/glslang/src/README.md
+++ b/third_party/glslang/src/README.md
@@ -209,27 +209,29 @@
 the web grammar subset (see more about the web subset in the next section).
 
 ### Building to WASM for the Web and Node
+### Building a standalone JS/WASM library for the Web and Node
 
 Use the steps in [Build Steps](#build-steps), with the following notes/exceptions:
-* For building the web subset of core glslang:
+* `emsdk` needs to be present in your executable search path, *PATH* for
+  Bash-like environments:
+  + [Instructions located here](https://emscripten.org/docs/getting_started/downloads.html#sdk-download-and-install)
+* Wrap cmake call: `emcmake cmake`
+* Set `-DBUILD_TESTING=OFF -DENABLE_OPT=OFF -DINSTALL_GTEST=OFF`.
+* Set `-DENABLE_HLSL=OFF` if HLSL is not needed.
+* For a standalone JS/WASM library, turn on `-DENABLE_GLSLANG_JS=ON`.
+* For building a minimum-size web subset of core glslang:
+  + turn on `-DENABLE_GLSLANG_WEBMIN=ON` (disables HLSL)
   + execute `updateGrammar web` from the glslang subdirectory
     (or if using your own scripts, `m4` needs a `-DGLSLANG_WEB` argument)
-  + set `-DENABLE_HLSL=OFF -DBUILD_TESTING=OFF -DENABLE_OPT=OFF -DINSTALL_GTEST=OFF`
-  + turn on `-DENABLE_GLSLANG_JS=ON`
-  + optionally, for a minimum-size binary, turn on `-DENABLE_GLSLANG_WEBMIN=ON`
-  + optionally, for GLSL compilation error messages, turn on `-DENABLE_GLSLANG_WEB_DEVEL=ON`
-* `emsdk` needs to be present in your executable search path, *PATH* for
-  Bash-like environments
-  + [Instructions located
-    here](https://emscripten.org/docs/getting_started/downloads.html#sdk-download-and-install)
-* Wrap cmake call: `emcmake cmake`
+  + optionally, for GLSL compilation error messages, turn on
+    `-DENABLE_GLSLANG_WEBMIN_DEVEL=ON`
 * To get a fully minimized build, make sure to use `brotli` to compress the .js
   and .wasm files
 
 Example:
 
 ```sh
-emcmake cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_GLSLANG_WEB=ON \
+emcmake cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_GLSLANG_JS=ON \
     -DENABLE_HLSL=OFF -DBUILD_TESTING=OFF -DENABLE_OPT=OFF -DINSTALL_GTEST=OFF ..
 ```
 
diff --git a/third_party/glslang/src/SPIRV/GLSL.ext.KHR.h b/third_party/glslang/src/SPIRV/GLSL.ext.KHR.h
index 4b3ea90..d783a8f 100644
--- a/third_party/glslang/src/SPIRV/GLSL.ext.KHR.h
+++ b/third_party/glslang/src/SPIRV/GLSL.ext.KHR.h
@@ -1,5 +1,6 @@
 /*
-** Copyright (c) 2014-2016 The Khronos Group Inc.
+** Copyright (c) 2014-2020 The Khronos Group Inc.
+** Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 **
 ** Permission is hereby granted, free of charge, to any person obtaining a copy
 ** of this software and/or associated documentation files (the "Materials"),
@@ -45,5 +46,6 @@
 static const char* const E_SPV_EXT_fragment_shader_interlock    = "SPV_EXT_fragment_shader_interlock";
 static const char* const E_SPV_KHR_shader_clock                 = "SPV_KHR_shader_clock";
 static const char* const E_SPV_KHR_non_semantic_info            = "SPV_KHR_non_semantic_info";
-
+static const char* const E_SPV_KHR_ray_tracing                  = "SPV_KHR_ray_tracing";
+static const char* const E_SPV_KHR_ray_query                    = "SPV_KHR_ray_query";
 #endif  // #ifndef GLSLextKHR_H
diff --git a/third_party/glslang/src/SPIRV/GlslangToSpv.cpp b/third_party/glslang/src/SPIRV/GlslangToSpv.cpp
index 5787e3d..071dad3 100644
--- a/third_party/glslang/src/SPIRV/GlslangToSpv.cpp
+++ b/third_party/glslang/src/SPIRV/GlslangToSpv.cpp
@@ -2,6 +2,7 @@
 // Copyright (C) 2014-2016 LunarG, Inc.
 // Copyright (C) 2015-2020 Google, Inc.
 // Copyright (C) 2017 ARM Limited.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 //
 // All rights reserved.
 //
@@ -227,7 +228,7 @@
     bool isTrivial(const glslang::TIntermTyped* node);
     spv::Id createShortCircuit(glslang::TOperator, glslang::TIntermTyped& left, glslang::TIntermTyped& right);
     spv::Id getExtBuiltins(const char* name);
-    std::pair<spv::Id, spv::Id> getForcedType(spv::BuiltIn, const glslang::TType&);
+    std::pair<spv::Id, spv::Id> getForcedType(glslang::TBuiltInVariable builtIn, const glslang::TType&);
     spv::Id translateForcedType(spv::Id object);
     spv::Id createCompositeConstruct(spv::Id typeId, std::vector<spv::Id> constituents);
 
@@ -312,12 +313,12 @@
     case EShLangTessControl:      return spv::ExecutionModelTessellationControl;
     case EShLangTessEvaluation:   return spv::ExecutionModelTessellationEvaluation;
     case EShLangGeometry:         return spv::ExecutionModelGeometry;
-    case EShLangRayGenNV:         return spv::ExecutionModelRayGenerationNV;
-    case EShLangIntersectNV:      return spv::ExecutionModelIntersectionNV;
-    case EShLangAnyHitNV:         return spv::ExecutionModelAnyHitNV;
-    case EShLangClosestHitNV:     return spv::ExecutionModelClosestHitNV;
-    case EShLangMissNV:           return spv::ExecutionModelMissNV;
-    case EShLangCallableNV:       return spv::ExecutionModelCallableNV;
+    case EShLangRayGen:           return spv::ExecutionModelRayGenerationKHR;
+    case EShLangIntersect:        return spv::ExecutionModelIntersectionKHR;
+    case EShLangAnyHit:           return spv::ExecutionModelAnyHitKHR;
+    case EShLangClosestHit:       return spv::ExecutionModelClosestHitKHR;
+    case EShLangMiss:             return spv::ExecutionModelMissKHR;
+    case EShLangCallable:         return spv::ExecutionModelCallableKHR;
     case EShLangTaskNV:           return spv::ExecutionModelTaskNV;
     case EShLangMeshNV:           return spv::ExecutionModelMeshNV;
 #endif
@@ -371,11 +372,11 @@
         case glslang::EvqVaryingIn:    return spv::DecorationBlock;
         case glslang::EvqVaryingOut:   return spv::DecorationBlock;
 #ifndef GLSLANG_WEB
-        case glslang::EvqPayloadNV:    return spv::DecorationBlock;
-        case glslang::EvqPayloadInNV:  return spv::DecorationBlock;
-        case glslang::EvqHitAttrNV:    return spv::DecorationBlock;
-        case glslang::EvqCallableDataNV:   return spv::DecorationBlock;
-        case glslang::EvqCallableDataInNV: return spv::DecorationBlock;
+        case glslang::EvqPayload:      return spv::DecorationBlock;
+        case glslang::EvqPayloadIn:    return spv::DecorationBlock;
+        case glslang::EvqHitAttr:      return spv::DecorationBlock;
+        case glslang::EvqCallableData:   return spv::DecorationBlock;
+        case glslang::EvqCallableDataIn: return spv::DecorationBlock;
 #endif
         default:
             assert(0);
@@ -447,11 +448,11 @@
                 }
                 return spv::DecorationMax;
 #ifndef GLSLANG_WEB
-            case glslang::EvqPayloadNV:
-            case glslang::EvqPayloadInNV:
-            case glslang::EvqHitAttrNV:
-            case glslang::EvqCallableDataNV:
-            case glslang::EvqCallableDataInNV:
+            case glslang::EvqPayload:
+            case glslang::EvqPayloadIn:
+            case glslang::EvqHitAttr:
+            case glslang::EvqCallableData:
+            case glslang::EvqCallableDataIn:
                 return spv::DecorationMax;
 #endif
             default:
@@ -543,15 +544,11 @@
     if (!glslangIntermediate->usingVulkanMemoryModel() || coherentFlags.isImage)
         return mask;
 
-    if (coherentFlags.volatil ||
-        coherentFlags.coherent ||
-        coherentFlags.devicecoherent ||
-        coherentFlags.queuefamilycoherent ||
-        coherentFlags.workgroupcoherent ||
-        coherentFlags.subgroupcoherent) {
+    if (coherentFlags.isVolatile() || coherentFlags.anyCoherent()) {
         mask = mask | spv::MemoryAccessMakePointerAvailableKHRMask |
                       spv::MemoryAccessMakePointerVisibleKHRMask;
     }
+
     if (coherentFlags.nonprivate) {
         mask = mask | spv::MemoryAccessNonPrivatePointerKHRMask;
     }
@@ -576,11 +573,7 @@
         return mask;
 
     if (coherentFlags.volatil ||
-        coherentFlags.coherent ||
-        coherentFlags.devicecoherent ||
-        coherentFlags.queuefamilycoherent ||
-        coherentFlags.workgroupcoherent ||
-        coherentFlags.subgroupcoherent) {
+        coherentFlags.anyCoherent()) {
         mask = mask | spv::ImageOperandsMakeTexelAvailableKHRMask |
                       spv::ImageOperandsMakeTexelVisibleKHRMask;
     }
@@ -609,14 +602,11 @@
     flags.workgroupcoherent = type.getQualifier().workgroupcoherent ||
                               type.getQualifier().storage == glslang::EvqShared;
     flags.subgroupcoherent = type.getQualifier().subgroupcoherent;
+    flags.shadercallcoherent = type.getQualifier().shadercallcoherent;
     flags.volatil = type.getQualifier().volatil;
     // *coherent variables are implicitly nonprivate in GLSL
     flags.nonprivate = type.getQualifier().nonprivate ||
-                       flags.subgroupcoherent ||
-                       flags.workgroupcoherent ||
-                       flags.queuefamilycoherent ||
-                       flags.devicecoherent ||
-                       flags.coherent ||
+                       flags.anyCoherent() ||
                        flags.volatil;
     flags.isImage = type.getBasicType() == glslang::EbtSampler;
 #endif
@@ -640,6 +630,8 @@
         scope = spv::ScopeWorkgroup;
     } else if (coherentFlags.subgroupcoherent) {
         scope = spv::ScopeSubgroup;
+    } else if (coherentFlags.shadercallcoherent) {
+        scope = spv::ScopeShaderCallKHR;
     }
     if (glslangIntermediate->usingVulkanMemoryModel() && scope == spv::ScopeDevice) {
         builder.addCapability(spv::CapabilityVulkanMemoryModelDeviceScopeKHR);
@@ -948,34 +940,38 @@
         return spv::BuiltInInvocationsPerPixelNV;
 
     // ray tracing
-    case glslang::EbvLaunchIdNV:
-        return spv::BuiltInLaunchIdNV;
-    case glslang::EbvLaunchSizeNV:
-        return spv::BuiltInLaunchSizeNV;
-    case glslang::EbvWorldRayOriginNV:
-        return spv::BuiltInWorldRayOriginNV;
-    case glslang::EbvWorldRayDirectionNV:
-        return spv::BuiltInWorldRayDirectionNV;
-    case glslang::EbvObjectRayOriginNV:
-        return spv::BuiltInObjectRayOriginNV;
-    case glslang::EbvObjectRayDirectionNV:
-        return spv::BuiltInObjectRayDirectionNV;
-    case glslang::EbvRayTminNV:
-        return spv::BuiltInRayTminNV;
-    case glslang::EbvRayTmaxNV:
-        return spv::BuiltInRayTmaxNV;
-    case glslang::EbvInstanceCustomIndexNV:
-        return spv::BuiltInInstanceCustomIndexNV;
-    case glslang::EbvHitTNV:
-        return spv::BuiltInHitTNV;
-    case glslang::EbvHitKindNV:
-        return spv::BuiltInHitKindNV;
-    case glslang::EbvObjectToWorldNV:
-        return spv::BuiltInObjectToWorldNV;
-    case glslang::EbvWorldToObjectNV:
-        return spv::BuiltInWorldToObjectNV;
-    case glslang::EbvIncomingRayFlagsNV:
-        return spv::BuiltInIncomingRayFlagsNV;
+    case glslang::EbvLaunchId:
+        return spv::BuiltInLaunchIdKHR;
+    case glslang::EbvLaunchSize:
+        return spv::BuiltInLaunchSizeKHR;
+    case glslang::EbvWorldRayOrigin:
+        return spv::BuiltInWorldRayOriginKHR;
+    case glslang::EbvWorldRayDirection:
+        return spv::BuiltInWorldRayDirectionKHR;
+    case glslang::EbvObjectRayOrigin:
+        return spv::BuiltInObjectRayOriginKHR;
+    case glslang::EbvObjectRayDirection:
+        return spv::BuiltInObjectRayDirectionKHR;
+    case glslang::EbvRayTmin:
+        return spv::BuiltInRayTminKHR;
+    case glslang::EbvRayTmax:
+        return spv::BuiltInRayTmaxKHR;
+    case glslang::EbvInstanceCustomIndex:
+        return spv::BuiltInInstanceCustomIndexKHR;
+    case glslang::EbvHitT:
+        return spv::BuiltInHitTKHR;
+    case glslang::EbvHitKind:
+        return spv::BuiltInHitKindKHR;
+    case glslang::EbvObjectToWorld:
+    case glslang::EbvObjectToWorld3x4:
+        return spv::BuiltInObjectToWorldKHR;
+    case glslang::EbvWorldToObject:
+    case glslang::EbvWorldToObject3x4:
+        return spv::BuiltInWorldToObjectKHR;
+    case glslang::EbvIncomingRayFlags:
+        return spv::BuiltInIncomingRayFlagsKHR;
+    case glslang::EbvGeometryIndex:
+        return spv::BuiltInRayGeometryIndexKHR;
 
     // barycentrics
     case glslang::EbvBaryCoordNV:
@@ -1186,6 +1182,8 @@
 // Translate glslang type to SPIR-V storage class.
 spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::TType& type)
 {
+    if (type.getBasicType() == glslang::EbtRayQuery)
+        return spv::StorageClassFunction;
     if (type.getQualifier().isPipeInput())
         return spv::StorageClassInput;
     if (type.getQualifier().isPipeOutput())
@@ -1200,8 +1198,8 @@
     }
 
     if (type.getQualifier().isUniformOrBuffer() &&
-        type.getQualifier().isShaderRecordNV()) {
-        return spv::StorageClassShaderRecordBufferNV;
+        type.getQualifier().isShaderRecord()) {
+        return spv::StorageClassShaderRecordBufferKHR;
     }
 
     if (glslangIntermediate->usingStorageBuffer() && type.getQualifier().storage == glslang::EvqBuffer) {
@@ -1223,11 +1221,11 @@
     case glslang::EvqTemporary:     return spv::StorageClassFunction;
     case glslang::EvqShared:           return spv::StorageClassWorkgroup;
 #ifndef GLSLANG_WEB
-    case glslang::EvqPayloadNV:        return spv::StorageClassRayPayloadNV;
-    case glslang::EvqPayloadInNV:      return spv::StorageClassIncomingRayPayloadNV;
-    case glslang::EvqHitAttrNV:        return spv::StorageClassHitAttributeNV;
-    case glslang::EvqCallableDataNV:   return spv::StorageClassCallableDataNV;
-    case glslang::EvqCallableDataInNV: return spv::StorageClassIncomingCallableDataNV;
+    case glslang::EvqPayload:        return spv::StorageClassRayPayloadKHR;
+    case glslang::EvqPayloadIn:      return spv::StorageClassIncomingRayPayloadKHR;
+    case glslang::EvqHitAttr:        return spv::StorageClassHitAttributeKHR;
+    case glslang::EvqCallableData:   return spv::StorageClassCallableDataKHR;
+    case glslang::EvqCallableDataIn: return spv::StorageClassIncomingCallableDataKHR;
 #endif
     default:
         assert(0);
@@ -1287,7 +1285,7 @@
     // uniform and buffer blocks are included, unless it is a push_constant
     if (type.getBasicType() == glslang::EbtBlock)
         return type.getQualifier().isUniformOrBuffer() &&
-        ! type.getQualifier().isShaderRecordNV() &&
+        ! type.getQualifier().isShaderRecord() &&
         ! type.getQualifier().isPushConstant();
 
     // non block...
@@ -1337,6 +1335,8 @@
         child.workgroupcoherent = true;
     if (parent.subgroupcoherent)
         child.subgroupcoherent = true;
+    if (parent.shadercallcoherent)
+        child.shadercallcoherent = true;
     if (parent.nonprivate)
         child.nonprivate = true;
     if (parent.volatil)
@@ -1448,6 +1448,10 @@
         builder.addExecutionMode(shaderEntry, spv::ExecutionModeXfb);
     }
 
+    if (sourceExtensions.find("GL_EXT_ray_flags_primitive_culling") != sourceExtensions.end()) {
+        builder.addCapability(spv::CapabilityRayTraversalPrimitiveCullingProvisionalKHR);
+    }
+
     unsigned int mode;
     switch (glslangIntermediate->getStage()) {
     case EShLangVertex:
@@ -1477,6 +1481,7 @@
             builder.addExecutionMode(shaderEntry, spv::ExecutionModeDepthReplacing);
 
 #ifndef GLSLANG_WEB
+
         switch(glslangIntermediate->getDepth()) {
         case glslang::EldGreater:  mode = spv::ExecutionModeDepthGreater; break;
         case glslang::EldLess:     mode = spv::ExecutionModeDepthLess;    break;
@@ -1514,7 +1519,7 @@
             builder.addExtension(spv::E_SPV_EXT_fragment_shader_interlock);
         }
 #endif
-        break;
+    break;
 
     case EShLangCompute:
         builder.addCapability(spv::CapabilityShader);
@@ -1602,15 +1607,24 @@
         builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, glslangIntermediate->getVertices());
         break;
 
-    case EShLangRayGenNV:
-    case EShLangIntersectNV:
-    case EShLangAnyHitNV:
-    case EShLangClosestHitNV:
-    case EShLangMissNV:
-    case EShLangCallableNV:
-        builder.addCapability(spv::CapabilityRayTracingNV);
-        builder.addExtension("SPV_NV_ray_tracing");
+    case EShLangRayGen:
+    case EShLangIntersect:
+    case EShLangAnyHit:
+    case EShLangClosestHit:
+    case EShLangMiss:
+    case EShLangCallable: 
+    {
+        auto& extensions = glslangIntermediate->getRequestedExtensions();
+        if (extensions.find("GL_NV_ray_tracing") == extensions.end()) {
+            builder.addCapability(spv::CapabilityRayTracingProvisionalKHR);
+            builder.addExtension("SPV_KHR_ray_tracing");
+        }
+        else {
+            builder.addCapability(spv::CapabilityRayTracingNV);
+            builder.addExtension("SPV_NV_ray_tracing");
+        }
         break;
+    }
     case EShLangTaskNV:
     case EShLangMeshNV:
         builder.addCapability(spv::CapabilityMeshShadingNV);
@@ -1709,7 +1723,8 @@
             }
         }
 
-        // If the SPIR-V type is required to be different than the AST type,
+        // If the SPIR-V type is required to be different than the AST type
+        // (for ex SubgroupMasks or 3x4 ObjectToWorld/WorldToObject matrices),
         // translate now from the SPIR-V type to the AST type, for the consuming
         // operation.
         // Note this turns it from an l-value to an r-value.
@@ -2014,16 +2029,16 @@
 // Figure out what, if any, type changes are needed when accessing a specific built-in.
 // Returns <the type SPIR-V requires for declarion, the type to translate to on use>.
 // Also see comment for 'forceType', regarding tracking SPIR-V-required types.
-std::pair<spv::Id, spv::Id> TGlslangToSpvTraverser::getForcedType(spv::BuiltIn builtIn,
+std::pair<spv::Id, spv::Id> TGlslangToSpvTraverser::getForcedType(glslang::TBuiltInVariable glslangBuiltIn,
     const glslang::TType& glslangType)
 {
-    switch(builtIn)
+    switch(glslangBuiltIn)
     {
-        case spv::BuiltInSubgroupEqMask:
-        case spv::BuiltInSubgroupGeMask:
-        case spv::BuiltInSubgroupGtMask:
-        case spv::BuiltInSubgroupLeMask:
-        case spv::BuiltInSubgroupLtMask: {
+        case glslang::EbvSubGroupEqMask:
+        case glslang::EbvSubGroupGeMask:
+        case glslang::EbvSubGroupGtMask:
+        case glslang::EbvSubGroupLeMask:
+        case glslang::EbvSubGroupLtMask: {
             // these require changing a 64-bit scaler -> a vector of 32-bit components
             if (glslangType.isVector())
                 break;
@@ -2031,6 +2046,15 @@
                                             builder.makeUintType(64));
             return ret;
         }
+        // There are no SPIR-V builtins defined for these and map onto original non-transposed
+        // builtins. During visitBinary we insert a transpose
+        case glslang::EbvWorldToObject3x4:
+        case glslang::EbvObjectToWorld3x4: {
+            std::pair<spv::Id, spv::Id> ret(builder.makeMatrixType(builder.makeFloatType(32), 4, 3),
+                builder.makeMatrixType(builder.makeFloatType(32), 3, 4)
+            );
+            return ret;
+        }
         default:
             break;
     }
@@ -2069,7 +2093,15 @@
         } else {
             logger->missingFunctionality("forcing 32-bit vector type to non 64-bit scalar");
         }
-    } else {
+    } else if (builder.isMatrixType(objectTypeId)) {
+            // There are no SPIR-V builtins defined for 3x4 variants of ObjectToWorld/WorldToObject
+            // and we insert a transpose after loading the original non-transposed builtins
+            builder.clearAccessChain();
+            builder.setAccessChainLValue(object);
+            object = builder.accessChainLoad(spv::NoPrecision, spv::DecorationMax, objectTypeId);
+            return builder.createUnaryOp(spv::OpTranspose, desiredTypeId, object);
+
+    } else  {
         logger->missingFunctionality("forcing non 32-bit vector type");
     }
 
@@ -2169,7 +2201,15 @@
     if (node->getOp() == glslang::EOpAtomicCounterIncrement ||
         node->getOp() == glslang::EOpAtomicCounterDecrement ||
         node->getOp() == glslang::EOpAtomicCounter          ||
-        node->getOp() == glslang::EOpInterpolateAtCentroid) {
+        node->getOp() == glslang::EOpInterpolateAtCentroid  ||
+        node->getOp() == glslang::EOpRayQueryProceed        ||
+        node->getOp() == glslang::EOpRayQueryGetRayTMin     ||
+        node->getOp() == glslang::EOpRayQueryGetRayFlags    ||
+        node->getOp() == glslang::EOpRayQueryGetWorldRayOrigin ||
+        node->getOp() == glslang::EOpRayQueryGetWorldRayDirection ||
+        node->getOp() == glslang::EOpRayQueryGetIntersectionCandidateAABBOpaque ||
+        node->getOp() == glslang::EOpRayQueryTerminate ||
+        node->getOp() == glslang::EOpRayQueryConfirmIntersection) {
         operand = builder.accessChainGetLValue(); // Special case l-value operands
         lvalueCoherentFlags = builder.getAccessChain().coherentFlags;
         lvalueCoherentFlags |= TranslateCoherent(operandNode->getAsTyped()->getType());
@@ -2262,6 +2302,12 @@
     case glslang::EOpEndStreamPrimitive:
         builder.createNoResultOp(spv::OpEndStreamPrimitive, operand);
         return false;
+    case glslang::EOpRayQueryTerminate:
+        builder.createNoResultOp(spv::OpRayQueryTerminateKHR, operand);
+        return false;
+    case glslang::EOpRayQueryConfirmIntersection:
+        builder.createNoResultOp(spv::OpRayQueryConfirmIntersectionKHR, operand);
+        return false;
 #endif
 
     default:
@@ -2311,10 +2357,10 @@
         spec_constant_op_mode_setter.turnOnSpecConstantOpMode();
 
     spv::Id result = spv::NoResult;
-    spv::Id invertedType = spv::NoType;       // to use to override the natural type of the node
-    spv::Builder::AccessChain complexLvalue;  // for holding swizzling l-values too complex for SPIR-V,
-                                              // for at out parameter
-    spv::Id temporaryLvalue = spv::NoResult;  // temporary to pass, as proxy for complexLValue
+    spv::Id invertedType = spv::NoType;                     // to use to override the natural type of the node
+    std::vector<spv::Builder::AccessChain> complexLvalues;  // for holding swizzling l-values too complex for
+                                                            // SPIR-V, for an out parameter
+    std::vector<spv::Id> temporaryLvalues;                  // temporaries to pass, as proxies for complexLValues
 
     auto resultType = [&invertedType, &node, this](){ return invertedType != spv::NoType ?
         invertedType :
@@ -2672,13 +2718,43 @@
         binOp = node->getOp();
         break;
 
-    case glslang::EOpIgnoreIntersectionNV:
-    case glslang::EOpTerminateRayNV:
-    case glslang::EOpTraceNV:
-    case glslang::EOpExecuteCallableNV:
+    case glslang::EOpIgnoreIntersection:
+    case glslang::EOpTerminateRay:
+    case glslang::EOpTrace:
+    case glslang::EOpExecuteCallable:
     case glslang::EOpWritePackedPrimitiveIndices4x8NV:
         noReturnValue = true;
         break;
+    case glslang::EOpRayQueryInitialize:
+    case glslang::EOpRayQueryTerminate:
+    case glslang::EOpRayQueryGenerateIntersection:
+    case glslang::EOpRayQueryConfirmIntersection:
+        builder.addExtension("SPV_KHR_ray_query");
+        builder.addCapability(spv::CapabilityRayQueryProvisionalKHR);
+        noReturnValue = true;
+        break;
+    case glslang::EOpRayQueryProceed:
+    case glslang::EOpRayQueryGetIntersectionType:
+    case glslang::EOpRayQueryGetRayTMin:
+    case glslang::EOpRayQueryGetRayFlags:
+    case glslang::EOpRayQueryGetIntersectionT:
+    case glslang::EOpRayQueryGetIntersectionInstanceCustomIndex:
+    case glslang::EOpRayQueryGetIntersectionInstanceId:
+    case glslang::EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset:
+    case glslang::EOpRayQueryGetIntersectionGeometryIndex:
+    case glslang::EOpRayQueryGetIntersectionPrimitiveIndex:
+    case glslang::EOpRayQueryGetIntersectionBarycentrics:
+    case glslang::EOpRayQueryGetIntersectionFrontFace:
+    case glslang::EOpRayQueryGetIntersectionCandidateAABBOpaque:
+    case glslang::EOpRayQueryGetIntersectionObjectRayDirection:
+    case glslang::EOpRayQueryGetIntersectionObjectRayOrigin:
+    case glslang::EOpRayQueryGetWorldRayDirection:
+    case glslang::EOpRayQueryGetWorldRayOrigin:
+    case glslang::EOpRayQueryGetIntersectionObjectToWorld:
+    case glslang::EOpRayQueryGetIntersectionWorldToObject:
+        builder.addExtension("SPV_KHR_ray_query");
+        builder.addCapability(spv::CapabilityRayQueryProvisionalKHR);
+        break;
     case glslang::EOpCooperativeMatrixLoad:
     case glslang::EOpCooperativeMatrixStore:
         noReturnValue = true;
@@ -2745,6 +2821,28 @@
                 lvalue = true;
             break;
 
+        case glslang::EOpRayQueryInitialize:
+        case glslang::EOpRayQueryTerminate:
+        case glslang::EOpRayQueryConfirmIntersection:
+        case glslang::EOpRayQueryProceed:
+        case glslang::EOpRayQueryGenerateIntersection:
+        case glslang::EOpRayQueryGetIntersectionType:
+        case glslang::EOpRayQueryGetIntersectionT:
+        case glslang::EOpRayQueryGetIntersectionInstanceCustomIndex:
+        case glslang::EOpRayQueryGetIntersectionInstanceId:
+        case glslang::EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset:
+        case glslang::EOpRayQueryGetIntersectionGeometryIndex:
+        case glslang::EOpRayQueryGetIntersectionPrimitiveIndex:
+        case glslang::EOpRayQueryGetIntersectionBarycentrics:
+        case glslang::EOpRayQueryGetIntersectionFrontFace:
+        case glslang::EOpRayQueryGetIntersectionObjectRayDirection:
+        case glslang::EOpRayQueryGetIntersectionObjectRayOrigin:
+        case glslang::EOpRayQueryGetIntersectionObjectToWorld:
+        case glslang::EOpRayQueryGetIntersectionWorldToObject:
+            if (arg == 0)
+                lvalue = true;
+            break;
+
         case glslang::EOpAtomicAdd:
         case glslang::EOpAtomicMin:
         case glslang::EOpAtomicMax:
@@ -2878,10 +2976,10 @@
                 // reduce to a simple access chain.  So, we need a temporary vector to
                 // receive the result, and must later swizzle that into the original
                 // l-value.
-                complexLvalue = builder.getAccessChain();
-                temporaryLvalue = builder.createVariable(spv::StorageClassFunction,
-                    builder.accessChainGetInferredType(), "swizzleTemp");
-                operands.push_back(temporaryLvalue);
+                complexLvalues.push_back(builder.getAccessChain());
+                temporaryLvalues.push_back(builder.createVariable(spv::StorageClassFunction,
+                    builder.accessChainGetInferredType(), "swizzleTemp"));
+                operands.push_back(temporaryLvalues.back());
             } else {
                 operands.push_back(builder.accessChainGetLValue());
             }
@@ -2889,7 +2987,29 @@
             lvalueCoherentFlags |= TranslateCoherent(glslangOperands[arg]->getAsTyped()->getType());
         } else {
             builder.setLine(node->getLoc().line, node->getLoc().getFilename());
-            operands.push_back(accessChainLoad(glslangOperands[arg]->getAsTyped()->getType()));
+             glslang::TOperator glslangOp = node->getOp();
+             if (arg == 1 &&
+                (glslangOp == glslang::EOpRayQueryGetIntersectionType ||
+                 glslangOp == glslang::EOpRayQueryGetIntersectionT ||
+                 glslangOp == glslang::EOpRayQueryGetIntersectionInstanceCustomIndex ||
+                 glslangOp == glslang::EOpRayQueryGetIntersectionInstanceId ||
+                 glslangOp == glslang::EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset ||
+                 glslangOp == glslang::EOpRayQueryGetIntersectionGeometryIndex ||
+                 glslangOp == glslang::EOpRayQueryGetIntersectionPrimitiveIndex ||
+                 glslangOp == glslang::EOpRayQueryGetIntersectionBarycentrics ||
+                 glslangOp == glslang::EOpRayQueryGetIntersectionFrontFace ||
+                 glslangOp == glslang::EOpRayQueryGetIntersectionObjectRayDirection ||
+                 glslangOp == glslang::EOpRayQueryGetIntersectionObjectRayOrigin ||
+                 glslangOp == glslang::EOpRayQueryGetIntersectionObjectToWorld ||
+                 glslangOp == glslang::EOpRayQueryGetIntersectionWorldToObject
+                    )) {
+                bool cond = glslangOperands[arg]->getAsConstantUnion()->getConstArray()[0].getBConst();
+                operands.push_back(builder.makeIntConstant(cond ? 1 : 0));
+            }
+            else {
+                operands.push_back(accessChainLoad(glslangOperands[arg]->getAsTyped()->getType()));
+            }
+
         }
     }
 
@@ -2954,11 +3074,13 @@
             result = createMiscOperation(node->getOp(), precision, resultType(), operands, node->getBasicType());
             break;
         }
+
         if (invertedType != spv::NoResult)
             result = createInvertedSwizzle(precision, *glslangOperands[0]->getAsBinaryNode(), result);
-        else if (temporaryLvalue != spv::NoResult) {
-            builder.setAccessChain(complexLvalue);
-            builder.accessChainStore(builder.createLoad(temporaryLvalue));
+
+        for (unsigned int i = 0; i < temporaryLvalues.size(); ++i) {
+            builder.setAccessChain(complexLvalues[i]);
+            builder.accessChainStore(builder.createLoad(temporaryLvalues[i]));
         }
     }
 
@@ -3522,8 +3644,11 @@
         builder.addCapability(spv::CapabilityAtomicStorage);
         spvType = builder.makeUintType(32);
         break;
-    case glslang::EbtAccStructNV:
-        spvType = builder.makeAccelerationStructureNVType();
+    case glslang::EbtAccStruct:
+        spvType = builder.makeAccelerationStructureType();
+        break;
+    case glslang::EbtRayQuery:
+        spvType = builder.makeRayQueryType();
         break;
     case glslang::EbtReference:
         {
@@ -5869,6 +5994,24 @@
     case glslang::EOpFwidthCoarse:
         unaryOp = spv::OpFwidthCoarse;
         break;
+    case glslang::EOpRayQueryProceed:
+        unaryOp = spv::OpRayQueryProceedKHR;
+        break;
+    case glslang::EOpRayQueryGetRayTMin:
+        unaryOp = spv::OpRayQueryGetRayTMinKHR;
+        break;
+    case glslang::EOpRayQueryGetRayFlags:
+        unaryOp = spv::OpRayQueryGetRayFlagsKHR;
+        break;
+    case glslang::EOpRayQueryGetWorldRayOrigin:
+        unaryOp = spv::OpRayQueryGetWorldRayOriginKHR;
+        break;
+    case glslang::EOpRayQueryGetWorldRayDirection:
+        unaryOp = spv::OpRayQueryGetWorldRayDirectionKHR;
+        break;
+    case glslang::EOpRayQueryGetIntersectionCandidateAABBOpaque:
+        unaryOp = spv::OpRayQueryGetIntersectionCandidateAABBOpaqueKHR;
+        break;
     case glslang::EOpInterpolateAtCentroid:
         if (typeProxy == glslang::EbtFloat16)
             builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float);
@@ -7573,24 +7716,105 @@
         libCall = spv::InterpolateAtVertexAMD;
         break;
 
-    case glslang::EOpReportIntersectionNV:
-    {
+    case glslang::EOpReportIntersection:
         typeId = builder.makeBoolType();
-        opCode = spv::OpReportIntersectionNV;
-    }
-    break;
-    case glslang::EOpTraceNV:
-    {
-        builder.createNoResultOp(spv::OpTraceNV, operands);
+        opCode = spv::OpReportIntersectionKHR;
+        break;
+    case glslang::EOpTrace:
+        builder.createNoResultOp(spv::OpTraceRayKHR, operands);
         return 0;
-    }
-    break;
-    case glslang::EOpExecuteCallableNV:
-    {
-        builder.createNoResultOp(spv::OpExecuteCallableNV, operands);
+    case glslang::EOpExecuteCallable:
+        builder.createNoResultOp(spv::OpExecuteCallableKHR, operands);
         return 0;
-    }
-    break;
+
+    case glslang::EOpRayQueryInitialize:
+        builder.createNoResultOp(spv::OpRayQueryInitializeKHR, operands);
+        return 0;
+    case glslang::EOpRayQueryTerminate:
+        builder.createNoResultOp(spv::OpRayQueryTerminateKHR, operands);
+        return 0;
+    case glslang::EOpRayQueryGenerateIntersection:
+        builder.createNoResultOp(spv::OpRayQueryGenerateIntersectionKHR, operands);
+        return 0;
+    case glslang::EOpRayQueryConfirmIntersection:
+        builder.createNoResultOp(spv::OpRayQueryConfirmIntersectionKHR, operands);
+        return 0;
+    case glslang::EOpRayQueryProceed:
+        typeId = builder.makeBoolType();
+        opCode = spv::OpRayQueryProceedKHR;
+        break;
+    case glslang::EOpRayQueryGetIntersectionType:
+        typeId = builder.makeUintType(32);
+        opCode = spv::OpRayQueryGetIntersectionTypeKHR;
+        break;
+    case glslang::EOpRayQueryGetRayTMin:
+        typeId = builder.makeFloatType(32);
+        opCode = spv::OpRayQueryGetRayTMinKHR;
+        break;
+    case glslang::EOpRayQueryGetRayFlags:
+        typeId = builder.makeIntType(32);
+        opCode = spv::OpRayQueryGetRayFlagsKHR;
+        break;
+    case glslang::EOpRayQueryGetIntersectionT:
+        typeId = builder.makeFloatType(32);
+        opCode = spv::OpRayQueryGetIntersectionTKHR;
+        break;
+    case glslang::EOpRayQueryGetIntersectionInstanceCustomIndex:
+        typeId = builder.makeIntType(32);
+        opCode = spv::OpRayQueryGetIntersectionInstanceCustomIndexKHR;
+        break;
+    case glslang::EOpRayQueryGetIntersectionInstanceId:
+        typeId = builder.makeIntType(32);
+        opCode = spv::OpRayQueryGetIntersectionInstanceIdKHR;
+        break;
+    case glslang::EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset:
+        typeId = builder.makeIntType(32);
+        opCode = spv::OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR;
+        break;
+    case glslang::EOpRayQueryGetIntersectionGeometryIndex:
+        typeId = builder.makeIntType(32);
+        opCode = spv::OpRayQueryGetIntersectionGeometryIndexKHR;
+        break;
+    case glslang::EOpRayQueryGetIntersectionPrimitiveIndex:
+        typeId = builder.makeIntType(32);
+        opCode = spv::OpRayQueryGetIntersectionPrimitiveIndexKHR;
+        break;
+    case glslang::EOpRayQueryGetIntersectionBarycentrics:
+        typeId = builder.makeVectorType(builder.makeFloatType(32), 2);
+        opCode = spv::OpRayQueryGetIntersectionBarycentricsKHR;
+        break;
+    case glslang::EOpRayQueryGetIntersectionFrontFace:
+        typeId = builder.makeBoolType();
+        opCode = spv::OpRayQueryGetIntersectionFrontFaceKHR;
+        break;
+    case glslang::EOpRayQueryGetIntersectionCandidateAABBOpaque:
+        typeId = builder.makeBoolType();
+        opCode = spv::OpRayQueryGetIntersectionCandidateAABBOpaqueKHR;
+        break;
+    case glslang::EOpRayQueryGetIntersectionObjectRayDirection:
+        typeId = builder.makeVectorType(builder.makeFloatType(32), 3);
+        opCode = spv::OpRayQueryGetIntersectionObjectRayDirectionKHR;
+        break;
+    case glslang::EOpRayQueryGetIntersectionObjectRayOrigin:
+        typeId = builder.makeVectorType(builder.makeFloatType(32), 3);
+        opCode = spv::OpRayQueryGetIntersectionObjectRayOriginKHR;
+        break;
+    case glslang::EOpRayQueryGetWorldRayDirection:
+        typeId = builder.makeVectorType(builder.makeFloatType(32), 3);
+        opCode = spv::OpRayQueryGetWorldRayDirectionKHR;
+        break;
+    case glslang::EOpRayQueryGetWorldRayOrigin:
+        typeId = builder.makeVectorType(builder.makeFloatType(32), 3);
+        opCode = spv::OpRayQueryGetWorldRayOriginKHR;
+        break;
+    case glslang::EOpRayQueryGetIntersectionObjectToWorld:
+        typeId = builder.makeMatrixType(builder.makeFloatType(32), 4, 3);
+        opCode = spv::OpRayQueryGetIntersectionObjectToWorldKHR;
+        break;
+    case glslang::EOpRayQueryGetIntersectionWorldToObject:
+        typeId = builder.makeMatrixType(builder.makeFloatType(32), 4, 3);
+        opCode = spv::OpRayQueryGetIntersectionWorldToObjectKHR;
+        break;
     case glslang::EOpWritePackedPrimitiveIndices4x8NV:
         builder.createNoResultOp(spv::OpWritePackedPrimitiveIndices4x8NV, operands);
         return 0;
@@ -7787,13 +8011,24 @@
         spv::Id id = builder.createBuiltinCall(typeId, getExtBuiltins(spv::E_SPV_AMD_gcn_shader), spv::TimeAMD, args);
         return builder.setPrecision(id, precision);
     }
-    case glslang::EOpIgnoreIntersectionNV:
-        builder.createNoResultOp(spv::OpIgnoreIntersectionNV);
+    case glslang::EOpIgnoreIntersection:
+        builder.createNoResultOp(spv::OpIgnoreIntersectionKHR);
         return 0;
-    case glslang::EOpTerminateRayNV:
-        builder.createNoResultOp(spv::OpTerminateRayNV);
+    case glslang::EOpTerminateRay:
+        builder.createNoResultOp(spv::OpTerminateRayKHR);
         return 0;
-
+    case glslang::EOpRayQueryInitialize:
+        builder.createNoResultOp(spv::OpRayQueryInitializeKHR);
+        return 0;
+    case glslang::EOpRayQueryTerminate:
+        builder.createNoResultOp(spv::OpRayQueryTerminateKHR);
+        return 0;
+    case glslang::EOpRayQueryGenerateIntersection:
+        builder.createNoResultOp(spv::OpRayQueryGenerateIntersectionKHR);
+        return 0;
+    case glslang::EOpRayQueryConfirmIntersection:
+        builder.createNoResultOp(spv::OpRayQueryConfirmIntersectionKHR);
+        return 0;
     case glslang::EOpBeginInvocationInterlock:
         builder.createNoResultOp(spv::OpBeginInvocationInterlockEXT);
         return 0;
@@ -7845,7 +8080,7 @@
 
     // it was not found, create it
     spv::BuiltIn builtIn = TranslateBuiltInDecoration(symbol->getQualifier().builtIn, false);
-    auto forcedType = getForcedType(builtIn, symbol->getType());
+    auto forcedType = getForcedType(symbol->getQualifier().builtIn, symbol->getType());
     id = createSpvVariable(symbol, forcedType.first);
     symbolValues[symbol->getId()] = id;
     if (forcedType.second != spv::NoType)
diff --git a/third_party/glslang/src/SPIRV/Logger.cpp b/third_party/glslang/src/SPIRV/Logger.cpp
index 7ea0c63..cdc8469 100644
--- a/third_party/glslang/src/SPIRV/Logger.cpp
+++ b/third_party/glslang/src/SPIRV/Logger.cpp
@@ -69,4 +69,4 @@
 
 } // end spv namespace
 
-#endif
\ No newline at end of file
+#endif
diff --git a/third_party/glslang/src/SPIRV/SpvBuilder.cpp b/third_party/glslang/src/SPIRV/SpvBuilder.cpp
index b3b9522..6cf70a1 100644
--- a/third_party/glslang/src/SPIRV/SpvBuilder.cpp
+++ b/third_party/glslang/src/SPIRV/SpvBuilder.cpp
@@ -1,6 +1,7 @@
 //
 // Copyright (C) 2014-2015 LunarG, Inc.
 // Copyright (C) 2015-2018 Google, Inc.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 //
 // All rights reserved.
 //
@@ -602,16 +603,31 @@
 }
 
 #ifndef GLSLANG_WEB
-Id Builder::makeAccelerationStructureNVType()
+Id Builder::makeAccelerationStructureType()
 {
     Instruction *type;
-    if (groupedTypes[OpTypeAccelerationStructureNV].size() == 0) {
-        type = new Instruction(getUniqueId(), NoType, OpTypeAccelerationStructureNV);
-        groupedTypes[OpTypeAccelerationStructureNV].push_back(type);
+    if (groupedTypes[OpTypeAccelerationStructureKHR].size() == 0) {
+        type = new Instruction(getUniqueId(), NoType, OpTypeAccelerationStructureKHR);
+        groupedTypes[OpTypeAccelerationStructureKHR].push_back(type);
         constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
         module.mapInstruction(type);
     } else {
-        type = groupedTypes[OpTypeAccelerationStructureNV].back();
+        type = groupedTypes[OpTypeAccelerationStructureKHR].back();
+    }
+
+    return type->getResultId();
+}
+
+Id Builder::makeRayQueryType()
+{
+    Instruction *type;
+    if (groupedTypes[OpTypeRayQueryProvisionalKHR].size() == 0) {
+        type = new Instruction(getUniqueId(), NoType, OpTypeRayQueryProvisionalKHR);
+        groupedTypes[OpTypeRayQueryProvisionalKHR].push_back(type);
+        constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
+        module.mapInstruction(type);
+    } else {
+        type = groupedTypes[OpTypeRayQueryProvisionalKHR].back();
     }
 
     return type->getResultId();
diff --git a/third_party/glslang/src/SPIRV/SpvBuilder.h b/third_party/glslang/src/SPIRV/SpvBuilder.h
index 405a28c..71b90d6 100644
--- a/third_party/glslang/src/SPIRV/SpvBuilder.h
+++ b/third_party/glslang/src/SPIRV/SpvBuilder.h
@@ -2,6 +2,7 @@
 // Copyright (C) 2014-2015 LunarG, Inc.
 // Copyright (C) 2015-2020 Google, Inc.
 // Copyright (C) 2017 ARM Limited.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 //
 // All rights reserved.
 //
@@ -182,7 +183,9 @@
     Id makeCooperativeMatrixType(Id component, Id scope, Id rows, Id cols);
 
     // accelerationStructureNV type
-    Id makeAccelerationStructureNVType();
+    Id makeAccelerationStructureType();
+    // rayQueryEXT type
+    Id makeRayQueryType();
 
     // For querying about types.
     Id getTypeId(Id resultId) const { return module.getTypeId(resultId); }
@@ -605,12 +608,17 @@
             CoherentFlags operator |=(const CoherentFlags &other) { return *this; }
 #else
             bool isVolatile() const { return volatil; }
+            bool anyCoherent() const {
+                return coherent || devicecoherent || queuefamilycoherent || workgroupcoherent ||
+                    subgroupcoherent || shadercallcoherent;
+            }
 
             unsigned coherent : 1;
             unsigned devicecoherent : 1;
             unsigned queuefamilycoherent : 1;
             unsigned workgroupcoherent : 1;
             unsigned subgroupcoherent : 1;
+            unsigned shadercallcoherent : 1;
             unsigned nonprivate : 1;
             unsigned volatil : 1;
             unsigned isImage : 1;
@@ -621,6 +629,7 @@
                 queuefamilycoherent = 0;
                 workgroupcoherent = 0;
                 subgroupcoherent = 0;
+                shadercallcoherent = 0;
                 nonprivate = 0;
                 volatil = 0;
                 isImage = 0;
@@ -632,6 +641,7 @@
                 queuefamilycoherent |= other.queuefamilycoherent;
                 workgroupcoherent |= other.workgroupcoherent;
                 subgroupcoherent |= other.subgroupcoherent;
+                shadercallcoherent |= other.shadercallcoherent;
                 nonprivate |= other.nonprivate;
                 volatil |= other.volatil;
                 isImage |= other.isImage;
diff --git a/third_party/glslang/src/SPIRV/doc.cpp b/third_party/glslang/src/SPIRV/doc.cpp
index bee5c79..b1f2b82 100644
--- a/third_party/glslang/src/SPIRV/doc.cpp
+++ b/third_party/glslang/src/SPIRV/doc.cpp
@@ -1,5 +1,6 @@
 //
 // Copyright (C) 2014-2015 LunarG, Inc.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 //
 // All rights reserved.
 //
@@ -99,12 +100,12 @@
 
     default: return "Bad";
 
-    case ExecutionModelRayGenerationNV: return "RayGenerationNV";
-    case ExecutionModelIntersectionNV:  return "IntersectionNV";
-    case ExecutionModelAnyHitNV:        return "AnyHitNV";
-    case ExecutionModelClosestHitNV:    return "ClosestHitNV";
-    case ExecutionModelMissNV:          return "MissNV";
-    case ExecutionModelCallableNV:      return "CallableNV";
+    case ExecutionModelRayGenerationKHR: return "RayGenerationKHR";
+    case ExecutionModelIntersectionKHR:  return "IntersectionKHR";
+    case ExecutionModelAnyHitKHR:        return "AnyHitKHR";
+    case ExecutionModelClosestHitKHR:    return "ClosestHitKHR";
+    case ExecutionModelMissKHR:          return "MissKHR";
+    case ExecutionModelCallableKHR:      return "CallableKHR";
     }
 }
 
@@ -209,12 +210,12 @@
     case 11: return "Image";
     case 12: return "StorageBuffer";
 
-    case StorageClassRayPayloadNV:            return "RayPayloadNV";
-    case StorageClassHitAttributeNV:          return "HitAttributeNV";
-    case StorageClassIncomingRayPayloadNV:    return "IncomingRayPayloadNV";
-    case StorageClassShaderRecordBufferNV:    return "ShaderRecordBufferNV";
-    case StorageClassCallableDataNV:          return "CallableDataNV";
-    case StorageClassIncomingCallableDataNV:  return "IncomingCallableDataNV";
+    case StorageClassRayPayloadKHR:            return "RayPayloadKHR";
+    case StorageClassHitAttributeKHR:          return "HitAttributeKHR";
+    case StorageClassIncomingRayPayloadKHR:    return "IncomingRayPayloadKHR";
+    case StorageClassShaderRecordBufferKHR:    return "ShaderRecordBufferKHR";
+    case StorageClassCallableDataKHR:          return "CallableDataKHR";
+    case StorageClassIncomingCallableDataKHR:  return "IncomingCallableDataKHR";
 
     case StorageClassPhysicalStorageBufferEXT: return "PhysicalStorageBufferEXT";
 
@@ -361,32 +362,33 @@
     case 4996: return "BaryCoordSmoothCentroidAMD";
     case 4997: return "BaryCoordSmoothSampleAMD";
     case 4998: return "BaryCoordPullModelAMD";
-    case BuiltInLaunchIdNV:                 return "LaunchIdNV";
-    case BuiltInLaunchSizeNV:               return "LaunchSizeNV";
-    case BuiltInWorldRayOriginNV:           return "WorldRayOriginNV";
-    case BuiltInWorldRayDirectionNV:        return "WorldRayDirectionNV";
-    case BuiltInObjectRayOriginNV:          return "ObjectRayOriginNV";
-    case BuiltInObjectRayDirectionNV:       return "ObjectRayDirectionNV";
-    case BuiltInRayTminNV:                  return "RayTminNV";
-    case BuiltInRayTmaxNV:                  return "RayTmaxNV";
-    case BuiltInInstanceCustomIndexNV:      return "InstanceCustomIndexNV";
-    case BuiltInObjectToWorldNV:            return "ObjectToWorldNV";
-    case BuiltInWorldToObjectNV:            return "WorldToObjectNV";
-    case BuiltInHitTNV:                     return "HitTNV";
-    case BuiltInHitKindNV:                  return "HitKindNV";
-    case BuiltInIncomingRayFlagsNV:         return "IncomingRayFlagsNV";
-    case BuiltInViewportMaskNV:             return "ViewportMaskNV";
-    case BuiltInSecondaryPositionNV:        return "SecondaryPositionNV";
-    case BuiltInSecondaryViewportMaskNV:    return "SecondaryViewportMaskNV";
-    case BuiltInPositionPerViewNV:          return "PositionPerViewNV";
-    case BuiltInViewportMaskPerViewNV:      return "ViewportMaskPerViewNV";
+    case BuiltInLaunchIdKHR:                 return "LaunchIdKHR";
+    case BuiltInLaunchSizeKHR:               return "LaunchSizeKHR";
+    case BuiltInWorldRayOriginKHR:           return "WorldRayOriginKHR";
+    case BuiltInWorldRayDirectionKHR:        return "WorldRayDirectionKHR";
+    case BuiltInObjectRayOriginKHR:          return "ObjectRayOriginKHR";
+    case BuiltInObjectRayDirectionKHR:       return "ObjectRayDirectionKHR";
+    case BuiltInRayTminKHR:                  return "RayTminKHR";
+    case BuiltInRayTmaxKHR:                  return "RayTmaxKHR";
+    case BuiltInInstanceCustomIndexKHR:      return "InstanceCustomIndexKHR";
+    case BuiltInRayGeometryIndexKHR:         return "RayGeometryIndexKHR";
+    case BuiltInObjectToWorldKHR:            return "ObjectToWorldKHR";
+    case BuiltInWorldToObjectKHR:            return "WorldToObjectKHR";
+    case BuiltInHitTKHR:                     return "HitTKHR";
+    case BuiltInHitKindKHR:                  return "HitKindKHR";
+    case BuiltInIncomingRayFlagsKHR:         return "IncomingRayFlagsKHR";
+    case BuiltInViewportMaskNV:              return "ViewportMaskNV";
+    case BuiltInSecondaryPositionNV:         return "SecondaryPositionNV";
+    case BuiltInSecondaryViewportMaskNV:     return "SecondaryViewportMaskNV";
+    case BuiltInPositionPerViewNV:           return "PositionPerViewNV";
+    case BuiltInViewportMaskPerViewNV:       return "ViewportMaskPerViewNV";
 //    case BuiltInFragmentSizeNV:             return "FragmentSizeNV";        // superseded by BuiltInFragSizeEXT
 //    case BuiltInInvocationsPerPixelNV:      return "InvocationsPerPixelNV"; // superseded by BuiltInFragInvocationCountEXT
-    case BuiltInBaryCoordNV:                return "BaryCoordNV";
-    case BuiltInBaryCoordNoPerspNV:         return "BaryCoordNoPerspNV";
+    case BuiltInBaryCoordNV:                 return "BaryCoordNV";
+    case BuiltInBaryCoordNoPerspNV:          return "BaryCoordNoPerspNV";
 
-    case BuiltInFragSizeEXT:                return "FragSizeEXT";
-    case BuiltInFragInvocationCountEXT:     return "FragInvocationCountEXT";
+    case BuiltInFragSizeEXT:                 return "FragSizeEXT";
+    case BuiltInFragInvocationCountEXT:      return "FragInvocationCountEXT";
 
     case 5264: return "FullyCoveredEXT";
 
@@ -890,6 +892,9 @@
     case CapabilityPerViewAttributesNV:             return "PerViewAttributesNV";
     case CapabilityGroupNonUniformPartitionedNV:    return "GroupNonUniformPartitionedNV";
     case CapabilityRayTracingNV:                    return "RayTracingNV";
+    case CapabilityRayTracingProvisionalKHR:        return "RayTracingProvisionalKHR";
+    case CapabilityRayQueryProvisionalKHR:          return "RayQueryProvisionalKHR";
+    case CapabilityRayTraversalPrimitiveCullingProvisionalKHR: return "RayTraversalPrimitiveCullingProvisionalKHR";
     case CapabilityComputeDerivativeGroupQuadsNV:   return "ComputeDerivativeGroupQuadsNV";
     case CapabilityComputeDerivativeGroupLinearNV:  return "ComputeDerivativeGroupLinearNV";
     case CapabilityFragmentBarycentricNV:           return "FragmentBarycentricNV";
@@ -1326,15 +1331,40 @@
     case OpMemberDecorateStringGOOGLE: return "OpMemberDecorateStringGOOGLE";
 
     case OpGroupNonUniformPartitionNV:       return "OpGroupNonUniformPartitionNV";
-    case OpReportIntersectionNV:             return "OpReportIntersectionNV";
-    case OpIgnoreIntersectionNV:             return "OpIgnoreIntersectionNV";
-    case OpTerminateRayNV:                   return "OpTerminateRayNV";
-    case OpTraceNV:                          return "OpTraceNV";
-    case OpTypeAccelerationStructureNV:      return "OpTypeAccelerationStructureNV";
-    case OpExecuteCallableNV:                return "OpExecuteCallableNV";
+    case OpReportIntersectionKHR:            return "OpReportIntersectionKHR";
+    case OpIgnoreIntersectionKHR:            return "OpIgnoreIntersectionKHR";
+    case OpTerminateRayKHR:                  return "OpTerminateRayKHR";
+    case OpTraceRayKHR:                      return "OpTraceRayKHR";
+    case OpTypeAccelerationStructureKHR:     return "OpTypeAccelerationStructureKHR";
+    case OpExecuteCallableKHR:               return "OpExecuteCallableKHR";
     case OpImageSampleFootprintNV:           return "OpImageSampleFootprintNV";
     case OpWritePackedPrimitiveIndices4x8NV: return "OpWritePackedPrimitiveIndices4x8NV";
 
+    case OpTypeRayQueryProvisionalKHR:                                        return "OpTypeRayQueryProvisionalKHR";
+    case OpRayQueryInitializeKHR:                                             return "OpRayQueryInitializeKHR";
+    case OpRayQueryTerminateKHR:                                              return "OpRayQueryTerminateKHR";
+    case OpRayQueryGenerateIntersectionKHR:                                   return "OpRayQueryGenerateIntersectionKHR";
+    case OpRayQueryConfirmIntersectionKHR:                                    return "OpRayQueryConfirmIntersectionKHR";
+    case OpRayQueryProceedKHR:                                                return "OpRayQueryProceedKHR";
+    case OpRayQueryGetIntersectionTypeKHR:                                    return "OpRayQueryGetIntersectionTypeKHR";
+    case OpRayQueryGetRayTMinKHR:                                             return "OpRayQueryGetRayTMinKHR";
+    case OpRayQueryGetRayFlagsKHR:                                            return "OpRayQueryGetRayFlagsKHR";
+    case OpRayQueryGetIntersectionTKHR:                                       return "OpRayQueryGetIntersectionTKHR";
+    case OpRayQueryGetIntersectionInstanceCustomIndexKHR:                     return "OpRayQueryGetIntersectionInstanceCustomIndexKHR";
+    case OpRayQueryGetIntersectionInstanceIdKHR:                              return "OpRayQueryGetIntersectionInstanceIdKHR";
+    case OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR:  return "OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR";
+    case OpRayQueryGetIntersectionGeometryIndexKHR:                           return "OpRayQueryGetIntersectionGeometryIndexKHR";
+    case OpRayQueryGetIntersectionPrimitiveIndexKHR:                          return "OpRayQueryGetIntersectionPrimitiveIndexKHR";
+    case OpRayQueryGetIntersectionBarycentricsKHR:                            return "OpRayQueryGetIntersectionBarycentricsKHR";
+    case OpRayQueryGetIntersectionFrontFaceKHR:                               return "OpRayQueryGetIntersectionFrontFaceKHR";
+    case OpRayQueryGetIntersectionCandidateAABBOpaqueKHR:                     return "OpRayQueryGetIntersectionCandidateAABBOpaqueKHR";
+    case OpRayQueryGetIntersectionObjectRayDirectionKHR:                      return "OpRayQueryGetIntersectionObjectRayDirectionKHR";
+    case OpRayQueryGetIntersectionObjectRayOriginKHR:                         return "OpRayQueryGetIntersectionObjectRayOriginKHR";
+    case OpRayQueryGetWorldRayDirectionKHR:                                   return "OpRayQueryGetWorldRayDirectionKHR";
+    case OpRayQueryGetWorldRayOriginKHR:                                      return "OpRayQueryGetWorldRayOriginKHR";
+    case OpRayQueryGetIntersectionObjectToWorldKHR:                           return "OpRayQueryGetIntersectionObjectToWorldKHR";
+    case OpRayQueryGetIntersectionWorldToObjectKHR:                           return "OpRayQueryGetIntersectionWorldToObjectKHR";
+
     case OpTypeCooperativeMatrixNV:         return "OpTypeCooperativeMatrixNV";
     case OpCooperativeMatrixLoadNV:         return "OpCooperativeMatrixLoadNV";
     case OpCooperativeMatrixStoreNV:        return "OpCooperativeMatrixStoreNV";
@@ -2694,31 +2724,125 @@
 
     InstructionDesc[OpGroupNonUniformPartitionNV].operands.push(OperandId, "X");
 
-    InstructionDesc[OpTypeAccelerationStructureNV].setResultAndType(true, false);
+    InstructionDesc[OpTypeAccelerationStructureKHR].setResultAndType(true, false);
 
-    InstructionDesc[OpTraceNV].operands.push(OperandId, "'NV Acceleration Structure'");
-    InstructionDesc[OpTraceNV].operands.push(OperandId, "'Ray Flags'");
-    InstructionDesc[OpTraceNV].operands.push(OperandId, "'Cull Mask'");
-    InstructionDesc[OpTraceNV].operands.push(OperandId, "'SBT Record Offset'");
-    InstructionDesc[OpTraceNV].operands.push(OperandId, "'SBT Record Stride'");
-    InstructionDesc[OpTraceNV].operands.push(OperandId, "'Miss Index'");
-    InstructionDesc[OpTraceNV].operands.push(OperandId, "'Ray Origin'");
-    InstructionDesc[OpTraceNV].operands.push(OperandId, "'TMin'");
-    InstructionDesc[OpTraceNV].operands.push(OperandId, "'Ray Direction'");
-    InstructionDesc[OpTraceNV].operands.push(OperandId, "'TMax'");
-    InstructionDesc[OpTraceNV].operands.push(OperandId, "'Payload'");
-    InstructionDesc[OpTraceNV].setResultAndType(false, false);
+    InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'NV Acceleration Structure'");
+    InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Ray Flags'");
+    InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Cull Mask'");
+    InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'SBT Record Offset'");
+    InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'SBT Record Stride'");
+    InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Miss Index'");
+    InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Ray Origin'");
+    InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'TMin'");
+    InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Ray Direction'");
+    InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'TMax'");
+    InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Payload'");
+    InstructionDesc[OpTraceRayKHR].setResultAndType(false, false);
 
-    InstructionDesc[OpReportIntersectionNV].operands.push(OperandId, "'Hit Parameter'");
-    InstructionDesc[OpReportIntersectionNV].operands.push(OperandId, "'Hit Kind'");
+    InstructionDesc[OpReportIntersectionKHR].operands.push(OperandId, "'Hit Parameter'");
+    InstructionDesc[OpReportIntersectionKHR].operands.push(OperandId, "'Hit Kind'");
 
-    InstructionDesc[OpIgnoreIntersectionNV].setResultAndType(false, false);
+    InstructionDesc[OpIgnoreIntersectionKHR].setResultAndType(false, false);
 
-    InstructionDesc[OpTerminateRayNV].setResultAndType(false, false);
+    InstructionDesc[OpTerminateRayKHR].setResultAndType(false, false);
     
-    InstructionDesc[OpExecuteCallableNV].operands.push(OperandId, "SBT Record Index");
-    InstructionDesc[OpExecuteCallableNV].operands.push(OperandId, "CallableData ID");
-    InstructionDesc[OpExecuteCallableNV].setResultAndType(false, false);
+    InstructionDesc[OpExecuteCallableKHR].operands.push(OperandId, "SBT Record Index");
+    InstructionDesc[OpExecuteCallableKHR].operands.push(OperandId, "CallableData ID");
+    InstructionDesc[OpExecuteCallableKHR].setResultAndType(false, false);
+
+    // Ray Query
+    InstructionDesc[OpTypeAccelerationStructureKHR].setResultAndType(true, false);
+    InstructionDesc[OpTypeRayQueryProvisionalKHR].setResultAndType(true, false);
+
+    InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'AccelerationS'");
+    InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'RayFlags'");
+    InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'CullMask'");
+    InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'Origin'");
+    InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'Tmin'");
+    InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'Direction'");
+    InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'Tmax'");
+    InstructionDesc[OpRayQueryInitializeKHR].setResultAndType(false, false);
+
+    InstructionDesc[OpRayQueryTerminateKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryTerminateKHR].setResultAndType(false, false);
+
+    InstructionDesc[OpRayQueryGenerateIntersectionKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGenerateIntersectionKHR].operands.push(OperandId, "'THit'");
+    InstructionDesc[OpRayQueryGenerateIntersectionKHR].setResultAndType(false, false);
+
+    InstructionDesc[OpRayQueryConfirmIntersectionKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryConfirmIntersectionKHR].setResultAndType(false, false);
+
+    InstructionDesc[OpRayQueryProceedKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryProceedKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionTypeKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionTypeKHR].operands.push(OperandId, "'Committed'");
+    InstructionDesc[OpRayQueryGetIntersectionTypeKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetRayTMinKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetRayTMinKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetRayFlagsKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetRayFlagsKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionTKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionTKHR].operands.push(OperandId, "'Committed'");
+    InstructionDesc[OpRayQueryGetIntersectionTKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionInstanceCustomIndexKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionInstanceCustomIndexKHR].operands.push(OperandId, "'Committed'");
+    InstructionDesc[OpRayQueryGetIntersectionInstanceCustomIndexKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionInstanceIdKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionInstanceIdKHR].operands.push(OperandId, "'Committed'");
+    InstructionDesc[OpRayQueryGetIntersectionInstanceIdKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR].operands.push(OperandId, "'Committed'");
+    InstructionDesc[OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionGeometryIndexKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionGeometryIndexKHR].operands.push(OperandId, "'Committed'");
+    InstructionDesc[OpRayQueryGetIntersectionGeometryIndexKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionPrimitiveIndexKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionPrimitiveIndexKHR].operands.push(OperandId, "'Committed'");
+    InstructionDesc[OpRayQueryGetIntersectionPrimitiveIndexKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionBarycentricsKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionBarycentricsKHR].operands.push(OperandId, "'Committed'");
+    InstructionDesc[OpRayQueryGetIntersectionBarycentricsKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionFrontFaceKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionFrontFaceKHR].operands.push(OperandId, "'Committed'");
+    InstructionDesc[OpRayQueryGetIntersectionFrontFaceKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionCandidateAABBOpaqueKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionCandidateAABBOpaqueKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionObjectRayDirectionKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionObjectRayDirectionKHR].operands.push(OperandId, "'Committed'");
+    InstructionDesc[OpRayQueryGetIntersectionObjectRayDirectionKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionObjectRayOriginKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionObjectRayOriginKHR].operands.push(OperandId, "'Committed'");
+    InstructionDesc[OpRayQueryGetIntersectionObjectRayOriginKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetWorldRayDirectionKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetWorldRayDirectionKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetWorldRayOriginKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetWorldRayOriginKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionObjectToWorldKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionObjectToWorldKHR].operands.push(OperandId, "'Committed'");
+    InstructionDesc[OpRayQueryGetIntersectionObjectToWorldKHR].setResultAndType(true, true);
+
+    InstructionDesc[OpRayQueryGetIntersectionWorldToObjectKHR].operands.push(OperandId, "'RayQuery'");
+    InstructionDesc[OpRayQueryGetIntersectionWorldToObjectKHR].operands.push(OperandId, "'Committed'");
+    InstructionDesc[OpRayQueryGetIntersectionWorldToObjectKHR].setResultAndType(true, true);
 
     InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandId, "'Sampled Image'");
     InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandId, "'Coordinate'");
diff --git a/third_party/glslang/src/SPIRV/hex_float.h b/third_party/glslang/src/SPIRV/hex_float.h
index 905b21a..8be8e9f 100644
--- a/third_party/glslang/src/SPIRV/hex_float.h
+++ b/third_party/glslang/src/SPIRV/hex_float.h
@@ -784,8 +784,8 @@
   if (val.isInfinity()) {
     // Fail the parse.  Emulate standard behaviour by setting the value to
     // the closest normal value, and set the fail bit on the stream.
-    value.set_value((value.isNegative() | negate_value) ? T::lowest()
-                                                        : T::max());
+    value.set_value((value.isNegative() || negate_value) ? T::lowest()
+                                                         : T::max());
     is.setstate(std::ios_base::failbit);
   }
   return is;
diff --git a/third_party/glslang/src/SPIRV/spirv.hpp b/third_party/glslang/src/SPIRV/spirv.hpp
index 1e96f7b..70c75d0 100644
--- a/third_party/glslang/src/SPIRV/spirv.hpp
+++ b/third_party/glslang/src/SPIRV/spirv.hpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2019 The Khronos Group Inc.
+// Copyright (c) 2014-2020 The Khronos Group Inc.
 // 
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and/or associated documentation files (the "Materials"),
@@ -49,11 +49,11 @@
 
 typedef unsigned int Id;
 
-#define SPV_VERSION 0x10400
+#define SPV_VERSION 0x10500
 #define SPV_REVISION 1
 
 static const unsigned int MagicNumber = 0x07230203;
-static const unsigned int Version = 0x00010400;
+static const unsigned int Version = 0x00010500;
 static const unsigned int Revision = 1;
 static const unsigned int OpCodeMask = 0xffff;
 static const unsigned int WordCountShift = 16;
@@ -78,11 +78,17 @@
     ExecutionModelKernel = 6,
     ExecutionModelTaskNV = 5267,
     ExecutionModelMeshNV = 5268,
+    ExecutionModelRayGenerationKHR = 5313,
     ExecutionModelRayGenerationNV = 5313,
+    ExecutionModelIntersectionKHR = 5314,
     ExecutionModelIntersectionNV = 5314,
+    ExecutionModelAnyHitKHR = 5315,
     ExecutionModelAnyHitNV = 5315,
+    ExecutionModelClosestHitKHR = 5316,
     ExecutionModelClosestHitNV = 5316,
+    ExecutionModelMissKHR = 5317,
     ExecutionModelMissNV = 5317,
+    ExecutionModelCallableKHR = 5318,
     ExecutionModelCallableNV = 5318,
     ExecutionModelMax = 0x7fffffff,
 };
@@ -179,11 +185,17 @@
     StorageClassAtomicCounter = 10,
     StorageClassImage = 11,
     StorageClassStorageBuffer = 12,
+    StorageClassCallableDataKHR = 5328,
     StorageClassCallableDataNV = 5328,
+    StorageClassIncomingCallableDataKHR = 5329,
     StorageClassIncomingCallableDataNV = 5329,
+    StorageClassRayPayloadKHR = 5338,
     StorageClassRayPayloadNV = 5338,
+    StorageClassHitAttributeKHR = 5339,
     StorageClassHitAttributeNV = 5339,
+    StorageClassIncomingRayPayloadKHR = 5342,
     StorageClassIncomingRayPayloadNV = 5342,
+    StorageClassShaderRecordBufferKHR = 5343,
     StorageClassShaderRecordBufferNV = 5343,
     StorageClassPhysicalStorageBuffer = 5349,
     StorageClassPhysicalStorageBufferEXT = 5349,
@@ -558,20 +570,35 @@
     BuiltInFragmentSizeNV = 5292,
     BuiltInFragInvocationCountEXT = 5293,
     BuiltInInvocationsPerPixelNV = 5293,
+    BuiltInLaunchIdKHR = 5319,
     BuiltInLaunchIdNV = 5319,
+    BuiltInLaunchSizeKHR = 5320,
     BuiltInLaunchSizeNV = 5320,
+    BuiltInWorldRayOriginKHR = 5321,
     BuiltInWorldRayOriginNV = 5321,
+    BuiltInWorldRayDirectionKHR = 5322,
     BuiltInWorldRayDirectionNV = 5322,
+    BuiltInObjectRayOriginKHR = 5323,
     BuiltInObjectRayOriginNV = 5323,
+    BuiltInObjectRayDirectionKHR = 5324,
     BuiltInObjectRayDirectionNV = 5324,
+    BuiltInRayTminKHR = 5325,
     BuiltInRayTminNV = 5325,
+    BuiltInRayTmaxKHR = 5326,
     BuiltInRayTmaxNV = 5326,
+    BuiltInInstanceCustomIndexKHR = 5327,
     BuiltInInstanceCustomIndexNV = 5327,
+    BuiltInObjectToWorldKHR = 5330,
     BuiltInObjectToWorldNV = 5330,
+    BuiltInWorldToObjectKHR = 5331,
     BuiltInWorldToObjectNV = 5331,
+    BuiltInHitTKHR = 5332,
     BuiltInHitTNV = 5332,
+    BuiltInHitKindKHR = 5333,
     BuiltInHitKindNV = 5333,
+    BuiltInIncomingRayFlagsKHR = 5351,
     BuiltInIncomingRayFlagsNV = 5351,
+    BuiltInRayGeometryIndexKHR = 5352,
     BuiltInWarpsPerSMNV = 5374,
     BuiltInSMCountNV = 5375,
     BuiltInWarpIDNV = 5376,
@@ -709,6 +736,7 @@
     ScopeInvocation = 4,
     ScopeQueueFamily = 5,
     ScopeQueueFamilyKHR = 5,
+    ScopeShaderCallKHR = 6,
     ScopeMax = 0x7fffffff,
 };
 
@@ -833,6 +861,8 @@
     CapabilitySignedZeroInfNanPreserve = 4466,
     CapabilityRoundingModeRTE = 4467,
     CapabilityRoundingModeRTZ = 4468,
+    CapabilityRayQueryProvisionalKHR = 4471,
+    CapabilityRayTraversalPrimitiveCullingProvisionalKHR = 4478,
     CapabilityFloat16ImageAMD = 5008,
     CapabilityImageGatherBiasLodAMD = 5009,
     CapabilityFragmentMaskAMD = 5010,
@@ -886,6 +916,7 @@
     CapabilityPhysicalStorageBufferAddresses = 5347,
     CapabilityPhysicalStorageBufferAddressesEXT = 5347,
     CapabilityComputeDerivativeGroupLinearNV = 5350,
+    CapabilityRayTracingProvisionalKHR = 5353,
     CapabilityCooperativeMatrixNV = 5357,
     CapabilityFragmentShaderSampleInterlockEXT = 5363,
     CapabilityFragmentShaderShadingRateInterlockEXT = 5372,
@@ -903,6 +934,53 @@
     CapabilityMax = 0x7fffffff,
 };
 
+enum RayFlagsShift {
+    RayFlagsOpaqueKHRShift = 0,
+    RayFlagsNoOpaqueKHRShift = 1,
+    RayFlagsTerminateOnFirstHitKHRShift = 2,
+    RayFlagsSkipClosestHitShaderKHRShift = 3,
+    RayFlagsCullBackFacingTrianglesKHRShift = 4,
+    RayFlagsCullFrontFacingTrianglesKHRShift = 5,
+    RayFlagsCullOpaqueKHRShift = 6,
+    RayFlagsCullNoOpaqueKHRShift = 7,
+    RayFlagsSkipTrianglesKHRShift = 8,
+    RayFlagsSkipAABBsKHRShift = 9,
+    RayFlagsMax = 0x7fffffff,
+};
+
+enum RayFlagsMask {
+    RayFlagsMaskNone = 0,
+    RayFlagsOpaqueKHRMask = 0x00000001,
+    RayFlagsNoOpaqueKHRMask = 0x00000002,
+    RayFlagsTerminateOnFirstHitKHRMask = 0x00000004,
+    RayFlagsSkipClosestHitShaderKHRMask = 0x00000008,
+    RayFlagsCullBackFacingTrianglesKHRMask = 0x00000010,
+    RayFlagsCullFrontFacingTrianglesKHRMask = 0x00000020,
+    RayFlagsCullOpaqueKHRMask = 0x00000040,
+    RayFlagsCullNoOpaqueKHRMask = 0x00000080,
+    RayFlagsSkipTrianglesKHRMask = 0x00000100,
+    RayFlagsSkipAABBsKHRMask = 0x00000200,
+};
+
+enum RayQueryIntersection {
+    RayQueryIntersectionRayQueryCandidateIntersectionKHR = 0,
+    RayQueryIntersectionRayQueryCommittedIntersectionKHR = 1,
+    RayQueryIntersectionMax = 0x7fffffff,
+};
+
+enum RayQueryCommittedIntersectionType {
+    RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionNoneKHR = 0,
+    RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionTriangleKHR = 1,
+    RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionGeneratedKHR = 2,
+    RayQueryCommittedIntersectionTypeMax = 0x7fffffff,
+};
+
+enum RayQueryCandidateIntersectionType {
+    RayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionTriangleKHR = 0,
+    RayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionAABBKHR = 1,
+    RayQueryCandidateIntersectionTypeMax = 0x7fffffff,
+};
+
 enum Op {
     OpNop = 0,
     OpUndef = 1,
@@ -1254,6 +1332,13 @@
     OpSubgroupAnyKHR = 4429,
     OpSubgroupAllEqualKHR = 4430,
     OpSubgroupReadInvocationKHR = 4432,
+    OpTypeRayQueryProvisionalKHR = 4472,
+    OpRayQueryInitializeKHR = 4473,
+    OpRayQueryTerminateKHR = 4474,
+    OpRayQueryGenerateIntersectionKHR = 4475,
+    OpRayQueryConfirmIntersectionKHR = 4476,
+    OpRayQueryProceedKHR = 4477,
+    OpRayQueryGetIntersectionTypeKHR = 4479,
     OpGroupIAddNonUniformAMD = 5000,
     OpGroupFAddNonUniformAMD = 5001,
     OpGroupFMinNonUniformAMD = 5002,
@@ -1268,11 +1353,17 @@
     OpImageSampleFootprintNV = 5283,
     OpGroupNonUniformPartitionNV = 5296,
     OpWritePackedPrimitiveIndices4x8NV = 5299,
+    OpReportIntersectionKHR = 5334,
     OpReportIntersectionNV = 5334,
+    OpIgnoreIntersectionKHR = 5335,
     OpIgnoreIntersectionNV = 5335,
+    OpTerminateRayKHR = 5336,
     OpTerminateRayNV = 5336,
     OpTraceNV = 5337,
+    OpTraceRayKHR = 5337,
+    OpTypeAccelerationStructureKHR = 5341,
     OpTypeAccelerationStructureNV = 5341,
+    OpExecuteCallableKHR = 5344,
     OpExecuteCallableNV = 5344,
     OpTypeCooperativeMatrixNV = 5358,
     OpCooperativeMatrixLoadNV = 5359,
@@ -1429,6 +1520,23 @@
     OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814,
     OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815,
     OpSubgroupAvcSicGetInterRawSadsINTEL = 5816,
+    OpRayQueryGetRayTMinKHR = 6016,
+    OpRayQueryGetRayFlagsKHR = 6017,
+    OpRayQueryGetIntersectionTKHR = 6018,
+    OpRayQueryGetIntersectionInstanceCustomIndexKHR = 6019,
+    OpRayQueryGetIntersectionInstanceIdKHR = 6020,
+    OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR = 6021,
+    OpRayQueryGetIntersectionGeometryIndexKHR = 6022,
+    OpRayQueryGetIntersectionPrimitiveIndexKHR = 6023,
+    OpRayQueryGetIntersectionBarycentricsKHR = 6024,
+    OpRayQueryGetIntersectionFrontFaceKHR = 6025,
+    OpRayQueryGetIntersectionCandidateAABBOpaqueKHR = 6026,
+    OpRayQueryGetIntersectionObjectRayDirectionKHR = 6027,
+    OpRayQueryGetIntersectionObjectRayOriginKHR = 6028,
+    OpRayQueryGetWorldRayDirectionKHR = 6029,
+    OpRayQueryGetWorldRayOriginKHR = 6030,
+    OpRayQueryGetIntersectionObjectToWorldKHR = 6031,
+    OpRayQueryGetIntersectionWorldToObjectKHR = 6032,
     OpMax = 0x7fffffff,
 };
 
@@ -1806,6 +1914,30 @@
     case OpTerminateRayNV: *hasResult = false; *hasResultType = false; break;
     case OpTraceNV: *hasResult = false; *hasResultType = false; break;
     case OpTypeAccelerationStructureNV: *hasResult = true; *hasResultType = false; break;
+    case OpTypeRayQueryProvisionalKHR: *hasResult = true; *hasResultType = false; break;
+    case OpRayQueryInitializeKHR: *hasResult = false; *hasResultType = false; break;
+    case OpRayQueryTerminateKHR: *hasResult = false; *hasResultType = false; break;
+    case OpRayQueryGenerateIntersectionKHR: *hasResult = false; *hasResultType = false; break;
+    case OpRayQueryConfirmIntersectionKHR: *hasResult = false; *hasResultType = false; break;
+    case OpRayQueryProceedKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionTypeKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetRayTMinKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetRayFlagsKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionTKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionInstanceCustomIndexKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionInstanceIdKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionGeometryIndexKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionPrimitiveIndexKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionBarycentricsKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionFrontFaceKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionCandidateAABBOpaqueKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionObjectRayDirectionKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionObjectRayOriginKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetWorldRayDirectionKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetWorldRayOriginKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionObjectToWorldKHR: *hasResult = true; *hasResultType = true; break;
+    case OpRayQueryGetIntersectionWorldToObjectKHR: *hasResult = true; *hasResultType = true; break;
     case OpExecuteCallableNV: *hasResult = false; *hasResultType = false; break;
     case OpTypeCooperativeMatrixNV: *hasResult = true; *hasResultType = false; break;
     case OpCooperativeMatrixLoadNV: *hasResult = true; *hasResultType = true; break;
@@ -1974,8 +2106,8 @@
 inline MemorySemanticsMask operator|(MemorySemanticsMask a, MemorySemanticsMask b) { return MemorySemanticsMask(unsigned(a) | unsigned(b)); }
 inline MemoryAccessMask operator|(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) | unsigned(b)); }
 inline KernelProfilingInfoMask operator|(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) | unsigned(b)); }
+inline RayFlagsMask operator|(RayFlagsMask a, RayFlagsMask b) { return RayFlagsMask(unsigned(a) | unsigned(b)); }
 
 }  // end namespace spv
 
 #endif  // #ifndef spirv_HPP
-
diff --git a/third_party/glslang/src/SPIRV/spvIR.h b/third_party/glslang/src/SPIRV/spvIR.h
index cf6a711..6523035 100755
--- a/third_party/glslang/src/SPIRV/spvIR.h
+++ b/third_party/glslang/src/SPIRV/spvIR.h
@@ -235,8 +235,7 @@
         assert(instructions.size() > 0);
         instructions.resize(1);
         successors.clear();
-        Instruction* unreachable = new Instruction(OpUnreachable);
-        addInstruction(std::unique_ptr<Instruction>(unreachable));
+        addInstruction(std::unique_ptr<Instruction>(new Instruction(OpUnreachable)));
     }
     // Change this block into a canonical dead continue target branching to the
     // given header ID.  Delete instructions as necessary.  A canonical dead continue
diff --git a/third_party/glslang/src/StandAlone/StandAlone.cpp b/third_party/glslang/src/StandAlone/StandAlone.cpp
index 81aca3b..a7ce53d 100644
--- a/third_party/glslang/src/StandAlone/StandAlone.cpp
+++ b/third_party/glslang/src/StandAlone/StandAlone.cpp
@@ -242,6 +242,7 @@
     std::string text;  // contents of preamble
 };
 
+// Track the user's #define and #undef from the command line.
 TPreamble UserPreamble;
 
 //
@@ -258,12 +259,12 @@
         case EShLangGeometry:        name = "geom.spv";    break;
         case EShLangFragment:        name = "frag.spv";    break;
         case EShLangCompute:         name = "comp.spv";    break;
-        case EShLangRayGenNV:        name = "rgen.spv";    break;
-        case EShLangIntersectNV:     name = "rint.spv";    break;
-        case EShLangAnyHitNV:        name = "rahit.spv";   break;
-        case EShLangClosestHitNV:    name = "rchit.spv";   break;
-        case EShLangMissNV:          name = "rmiss.spv";   break;
-        case EShLangCallableNV:      name = "rcall.spv";   break;
+        case EShLangRayGen:          name = "rgen.spv";    break;
+        case EShLangIntersect:       name = "rint.spv";    break;
+        case EShLangAnyHit:          name = "rahit.spv";   break;
+        case EShLangClosestHit:      name = "rchit.spv";   break;
+        case EShLangMiss:            name = "rmiss.spv";   break;
+        case EShLangCallable:        name = "rcall.spv";   break;
         case EShLangMeshNV:          name = "mesh.spv";    break;
         case EShLangTaskNV:          name = "task.spv";    break;
         default:                     name = "unknown";     break;
@@ -1139,7 +1140,6 @@
             for (int stage = 0; stage < EShLangCount; ++stage) {
                 if (program.getIntermediate((EShLanguage)stage)) {
                     std::vector<unsigned int> spirv;
-                    std::string warningsErrors;
                     spv::SpvBuildLogger logger;
                     glslang::SpvOptions spvOptions;
                     if (Options & EOptionDebug)
@@ -1429,17 +1429,17 @@
     else if (stageName == "comp")
         return EShLangCompute;
     else if (stageName == "rgen")
-        return EShLangRayGenNV;
+        return EShLangRayGen;
     else if (stageName == "rint")
-        return EShLangIntersectNV;
+        return EShLangIntersect;
     else if (stageName == "rahit")
-        return EShLangAnyHitNV;
+        return EShLangAnyHit;
     else if (stageName == "rchit")
-        return EShLangClosestHitNV;
+        return EShLangClosestHit;
     else if (stageName == "rmiss")
-        return EShLangMissNV;
+        return EShLangMiss;
     else if (stageName == "rcall")
-        return EShLangCallableNV;
+        return EShLangCallable;
     else if (stageName == "mesh")
         return EShLangMeshNV;
     else if (stageName == "task")
diff --git a/third_party/glslang/src/StandAlone/resource_limits_c.cpp b/third_party/glslang/src/StandAlone/resource_limits_c.cpp
index 1b33f5f..a1f681c 100644
--- a/third_party/glslang/src/StandAlone/resource_limits_c.cpp
+++ b/third_party/glslang/src/StandAlone/resource_limits_c.cpp
@@ -37,6 +37,14 @@
     return reinterpret_cast<const glslang_resource_t*>(&glslang::DefaultTBuiltInResource);
 }
 
+#if defined(__clang__) || defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#elif defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable : 4996)
+#endif
+
 const char* glslang_default_resource_string()
 {
     std::string cpp_str = glslang::GetDefaultTBuiltInResourceString();
@@ -45,6 +53,12 @@
     return c_str;
 }
 
+#if defined(__clang__) || defined(__GNUC__)
+#pragma GCC diagnostic pop
+#elif defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
 void glslang_decode_resource_limits(glslang_resource_t* resources, char* config)
 {
     glslang::DecodeResourceLimits(reinterpret_cast<TBuiltInResource*>(resources), config);
diff --git a/third_party/glslang/src/StandAlone/spirv-remap.cpp b/third_party/glslang/src/StandAlone/spirv-remap.cpp
index 5e2ed0a..48878c3 100644
--- a/third_party/glslang/src/StandAlone/spirv-remap.cpp
+++ b/third_party/glslang/src/StandAlone/spirv-remap.cpp
@@ -334,8 +334,6 @@
     if (outputDir.empty())
         usage(argv[0], "Output directory required");
 
-    std::string errmsg;
-
     // Main operations: read, remap, and write.
     execute(inputFile, outputDir, opts, verbosity);
 
diff --git a/third_party/glslang/src/Test/150.frag b/third_party/glslang/src/Test/150.frag
index 1985d6e..e24dba0 100644
--- a/third_party/glslang/src/Test/150.frag
+++ b/third_party/glslang/src/Test/150.frag
@@ -57,4 +57,25 @@
 int absTest = sqrt(type3);

 double absTest2 = sqrt(type3);

 double absTest3 = sqrt(2);

-float dk = sqrt(11);
\ No newline at end of file
+float dk = sqrt(11);

+

+#extension GL_ARB_shader_bit_encoding: enable

+

+float f;

+vec4 v4;

+ivec4 iv4a;

+uvec2 uv2c;

+void bitEncodingPass()

+{

+    int i = floatBitsToInt(f);

+    uvec4 uv11 = floatBitsToUint(v4);

+    vec4 v14 = intBitsToFloat(iv4a);

+    vec2 v15 = uintBitsToFloat(uv2c);

+}

+

+#extension GL_ARB_shader_bit_encoding: disable

+

+void bitEncodingFail()

+{

+    int i = floatBitsToInt(f); // Error, extention GL_ARB_bit_encoding is diabled

+}

diff --git a/third_party/glslang/src/Test/420.frag b/third_party/glslang/src/Test/420.frag
index 1444758..51f35ff 100644
--- a/third_party/glslang/src/Test/420.frag
+++ b/third_party/glslang/src/Test/420.frag
@@ -12,3 +12,8 @@
 layout(depth_any) out float gl_FragDepth;  // ERROR, done after use
 
 layout(binding=0) uniform atomic_uint a[];
+
+uniform writeonly image2D      i2D;
+ivec2 iv2dim = imageSize(i2D); // ERROR: imageSize called without enabling GL_ARB_shader_image_size extension
+#extension GL_ARB_shader_image_size : enable
+ivec2 iv2dim1 = imageSize(i2D);
diff --git a/third_party/glslang/src/Test/baseResults/150.frag.out b/third_party/glslang/src/Test/baseResults/150.frag.out
index 18c1953..4a55ea4 100644
--- a/third_party/glslang/src/Test/baseResults/150.frag.out
+++ b/third_party/glslang/src/Test/baseResults/150.frag.out
@@ -9,11 +9,13 @@
 ERROR: 0:53: 'double' : not supported for this version or the enabled extensions 
 ERROR: 0:53: 'double' : must be qualified as flat in
 ERROR: 0:57: '=' :  cannot convert from ' global double' to ' global int'
-ERROR: 10 compilation errors.  No code generated.
+ERROR: 0:80: 'floatBitsToInt' : required extension not requested: GL_ARB_shader_bit_encoding
+ERROR: 11 compilation errors.  No code generated.
 
 
 Shader version: 150
 Requested GL_ARB_gpu_shader_fp64
+Requested GL_ARB_shader_bit_encoding
 gl_FragCoord pixel center is integer
 gl_FragCoord origin is upper left
 ERROR: node is still EOpNull!
@@ -134,6 +136,37 @@
 0:60      'dk' ( global float)
 0:60      Constant:
 0:60        3.316625
+0:68  Function Definition: bitEncodingPass( ( global void)
+0:68    Function Parameters: 
+0:70    Sequence
+0:70      Sequence
+0:70        move second child to first child ( temp int)
+0:70          'i' ( temp int)
+0:70          floatBitsToInt ( global int)
+0:70            'f' ( global float)
+0:71      Sequence
+0:71        move second child to first child ( temp 4-component vector of uint)
+0:71          'uv11' ( temp 4-component vector of uint)
+0:71          floatBitsToUint ( global 4-component vector of uint)
+0:71            'v4' ( global 4-component vector of float)
+0:72      Sequence
+0:72        move second child to first child ( temp 4-component vector of float)
+0:72          'v14' ( temp 4-component vector of float)
+0:72          intBitsToFloat ( global 4-component vector of float)
+0:72            'iv4a' ( global 4-component vector of int)
+0:73      Sequence
+0:73        move second child to first child ( temp 2-component vector of float)
+0:73          'v15' ( temp 2-component vector of float)
+0:73          uintBitsToFloat ( global 2-component vector of float)
+0:73            'uv2c' ( global 2-component vector of uint)
+0:78  Function Definition: bitEncodingFail( ( global void)
+0:78    Function Parameters: 
+0:80    Sequence
+0:80      Sequence
+0:80        move second child to first child ( temp int)
+0:80          'i' ( temp int)
+0:80          floatBitsToInt ( global int)
+0:80            'f' ( global float)
 0:?   Linker Objects
 0:?     'gl_FragCoord' ( gl_FragCoord 4-component vector of float FragCoord)
 0:?     'foo' ( smooth in 4-component vector of float)
@@ -155,6 +188,10 @@
 0:?     'absTest2' ( global double)
 0:?     'absTest3' ( global double)
 0:?     'dk' ( global float)
+0:?     'f' ( global float)
+0:?     'v4' ( global 4-component vector of float)
+0:?     'iv4a' ( global 4-component vector of int)
+0:?     'uv2c' ( global 2-component vector of uint)
 
 
 Linked fragment stage:
@@ -162,6 +199,7 @@
 
 Shader version: 150
 Requested GL_ARB_gpu_shader_fp64
+Requested GL_ARB_shader_bit_encoding
 gl_FragCoord pixel center is integer
 gl_FragCoord origin is upper left
 ERROR: node is still EOpNull!
@@ -218,4 +256,8 @@
 0:?     'absTest2' ( global double)
 0:?     'absTest3' ( global double)
 0:?     'dk' ( global float)
+0:?     'f' ( global float)
+0:?     'v4' ( global 4-component vector of float)
+0:?     'iv4a' ( global 4-component vector of int)
+0:?     'uv2c' ( global 2-component vector of uint)
 
diff --git a/third_party/glslang/src/Test/baseResults/420.frag.out b/third_party/glslang/src/Test/baseResults/420.frag.out
index ffb8f6d..05ded72 100644
--- a/third_party/glslang/src/Test/baseResults/420.frag.out
+++ b/third_party/glslang/src/Test/baseResults/420.frag.out
@@ -3,10 +3,12 @@
 ERROR: 0:11: 'layout qualifier' : can only apply depth layout to gl_FragDepth 
 ERROR: 0:12: 'gl_FragDepth' : cannot redeclare after use 
 ERROR: 0:14: 'atomic_uint' : array must be explicitly sized 
-ERROR: 4 compilation errors.  No code generated.
+ERROR: 0:17: 'imageSize' : required extension not requested: GL_ARB_shader_image_size
+ERROR: 5 compilation errors.  No code generated.
 
 
 Shader version: 420
+Requested GL_ARB_shader_image_size
 using depth_any
 ERROR: node is still EOpNull!
 0:6  Function Definition: main( ( global void)
@@ -16,16 +18,30 @@
 0:8        'gl_FragDepth' ( gl_FragDepth float FragDepth)
 0:8        Constant:
 0:8          0.300000
+0:17  Sequence
+0:17    move second child to first child ( temp 2-component vector of int)
+0:17      'iv2dim' ( global 2-component vector of int)
+0:17      imageQuerySize ( global 2-component vector of int)
+0:17        'i2D' ( writeonly uniform image2D)
+0:19  Sequence
+0:19    move second child to first child ( temp 2-component vector of int)
+0:19      'iv2dim1' ( global 2-component vector of int)
+0:19      imageQuerySize ( global 2-component vector of int)
+0:19        'i2D' ( writeonly uniform image2D)
 0:?   Linker Objects
 0:?     'gl_FragDepth' ( gl_FragDepth float FragDepth)
 0:?     'depth' ( smooth in float)
 0:?     'a' (layout( binding=0 offset=0) uniform unsized 1-element array of atomic_uint)
+0:?     'i2D' ( writeonly uniform image2D)
+0:?     'iv2dim' ( global 2-component vector of int)
+0:?     'iv2dim1' ( global 2-component vector of int)
 
 
 Linked fragment stage:
 
 
 Shader version: 420
+Requested GL_ARB_shader_image_size
 using depth_any
 ERROR: node is still EOpNull!
 0:6  Function Definition: main( ( global void)
@@ -35,8 +51,21 @@
 0:8        'gl_FragDepth' ( gl_FragDepth float FragDepth)
 0:8        Constant:
 0:8          0.300000
+0:17  Sequence
+0:17    move second child to first child ( temp 2-component vector of int)
+0:17      'iv2dim' ( global 2-component vector of int)
+0:17      imageQuerySize ( global 2-component vector of int)
+0:17        'i2D' ( writeonly uniform image2D)
+0:19  Sequence
+0:19    move second child to first child ( temp 2-component vector of int)
+0:19      'iv2dim1' ( global 2-component vector of int)
+0:19      imageQuerySize ( global 2-component vector of int)
+0:19        'i2D' ( writeonly uniform image2D)
 0:?   Linker Objects
 0:?     'gl_FragDepth' ( gl_FragDepth float FragDepth)
 0:?     'depth' ( smooth in float)
 0:?     'a' (layout( binding=0 offset=0) uniform 1-element array of atomic_uint)
+0:?     'i2D' ( writeonly uniform image2D)
+0:?     'iv2dim' ( global 2-component vector of int)
+0:?     'iv2dim1' ( global 2-component vector of int)
 
diff --git a/third_party/glslang/src/Test/baseResults/constFold.frag.out b/third_party/glslang/src/Test/baseResults/constFold.frag.out
index 2a48c42..045afc0 100644
--- a/third_party/glslang/src/Test/baseResults/constFold.frag.out
+++ b/third_party/glslang/src/Test/baseResults/constFold.frag.out
@@ -260,27 +260,27 @@
 0:120                1.000000
 0:120          Constant:
 0:120            3 (const int)
-0:126  Function Definition: foo3( ( global void)
-0:126    Function Parameters: 
-0:128    Sequence
-0:128      Sequence
-0:128        move second child to first child ( temp 3X2 matrix of float)
-0:128          'r32' ( temp 3X2 matrix of float)
-0:128          Constant:
-0:128            43.000000
-0:128            64.000000
-0:128            51.000000
-0:128            76.000000
-0:128            59.000000
-0:128            88.000000
-0:138  Function Definition: foo4( ( global void)
-0:138    Function Parameters: 
-0:140    Sequence
-0:140      Sequence
-0:140        move second child to first child ( temp int)
-0:140          'a' ( temp int)
-0:140          Constant:
-0:140            9 (const int)
+0:129  Function Definition: foo3( ( global void)
+0:129    Function Parameters: 
+0:131    Sequence
+0:131      Sequence
+0:131        move second child to first child ( temp 3X2 matrix of float)
+0:131          'r32' ( temp 3X2 matrix of float)
+0:131          Constant:
+0:131            43.000000
+0:131            64.000000
+0:131            51.000000
+0:131            76.000000
+0:131            59.000000
+0:131            88.000000
+0:141  Function Definition: foo4( ( global void)
+0:141    Function Parameters: 
+0:143    Sequence
+0:143      Sequence
+0:143        move second child to first child ( temp int)
+0:143          'a' ( temp int)
+0:143          Constant:
+0:143            9 (const int)
 0:?   Linker Objects
 0:?     'a' ( const int)
 0:?       1 (const int)
@@ -367,6 +367,29 @@
 0:?       13.000000
 0:?       14.000000
 0:?       15.000000
+0:?     'm22' ( const 2X2 matrix of float)
+0:?       1.000000
+0:?       2.000000
+0:?       3.000000
+0:?       4.000000
+0:?     'mm34' ( const 3X4 matrix of float)
+0:?       7.000000
+0:?       0.000000
+0:?       0.000000
+0:?       0.000000
+0:?       0.000000
+0:?       7.000000
+0:?       0.000000
+0:?       0.000000
+0:?       0.000000
+0:?       0.000000
+0:?       7.000000
+0:?       0.000000
+0:?     'mv4' ( const 4-component vector of float)
+0:?       1.000000
+0:?       2.000000
+0:?       3.000000
+0:?       4.000000
 0:?     'a0' ( const 3-element array of structure{ global int i,  global float f,  global bool b})
 0:?       3 (const int)
 0:?       2.000000
@@ -635,6 +658,29 @@
 0:?       13.000000
 0:?       14.000000
 0:?       15.000000
+0:?     'm22' ( const 2X2 matrix of float)
+0:?       1.000000
+0:?       2.000000
+0:?       3.000000
+0:?       4.000000
+0:?     'mm34' ( const 3X4 matrix of float)
+0:?       7.000000
+0:?       0.000000
+0:?       0.000000
+0:?       0.000000
+0:?       0.000000
+0:?       7.000000
+0:?       0.000000
+0:?       0.000000
+0:?       0.000000
+0:?       0.000000
+0:?       7.000000
+0:?       0.000000
+0:?     'mv4' ( const 4-component vector of float)
+0:?       1.000000
+0:?       2.000000
+0:?       3.000000
+0:?       4.000000
 0:?     'a0' ( const 3-element array of structure{ global int i,  global float f,  global bool b})
 0:?       3 (const int)
 0:?       2.000000
diff --git a/third_party/glslang/src/Test/baseResults/link.multiAnonBlocksInvalid.0.0.vert.out b/third_party/glslang/src/Test/baseResults/link.multiAnonBlocksInvalid.0.0.vert.out
new file mode 100755
index 0000000..b8ba789
--- /dev/null
+++ b/third_party/glslang/src/Test/baseResults/link.multiAnonBlocksInvalid.0.0.vert.out
@@ -0,0 +1,177 @@
+link.multiAnonBlocksInvalid.0.0.vert
+ERROR: 0:22: 'ColorBlock' : nameless block contains a member that already has a name at global scope 
+ERROR: 0:42: 'v1' : redefinition 
+ERROR: 0:43: 'uProj' : redefinition 
+ERROR: 3 compilation errors.  No code generated.
+
+
+Shader version: 430
+ERROR: node is still EOpNull!
+0:46  Function Definition: main( ( global void)
+0:46    Function Parameters: 
+0:48    Sequence
+0:48      move second child to first child ( temp 4-component vector of float)
+0:48        'oColor' ( smooth out 4-component vector of float)
+0:48        component-wise multiply ( temp 4-component vector of float)
+0:48          color1: direct index for structure (layout( column_major std140 offset=0) uniform 4-component vector of float)
+0:48            'anon@3' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4-component vector of float color1, layout( column_major std140 offset=16) uniform 4-component vector of float color2, layout( column_major std140 offset=32) uniform 4-component vector of float v1})
+0:48            Constant:
+0:48              0 (const uint)
+0:48          Function Call: getColor2( ( global 4-component vector of float)
+0:49      move second child to first child ( temp 4-component vector of float)
+0:49        v1: direct index for structure ( out 4-component vector of float)
+0:49          'anon@2' ( out block{ out 4-component vector of float v1})
+0:49          Constant:
+0:49            0 (const uint)
+0:49        color1: direct index for structure (layout( column_major std140 offset=0) uniform 4-component vector of float)
+0:49          'anon@3' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4-component vector of float color1, layout( column_major std140 offset=16) uniform 4-component vector of float color2, layout( column_major std140 offset=32) uniform 4-component vector of float v1})
+0:49          Constant:
+0:49            0 (const uint)
+0:51      move second child to first child ( temp 4-component vector of float)
+0:51        gl_Position: direct index for structure ( gl_Position 4-component vector of float Position)
+0:51          'anon@4' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out unsized 1-element array of float ClipDistance gl_ClipDistance,  gl_ClipVertex 4-component vector of float ClipVertex gl_ClipVertex,  out 4-component vector of float FrontColor gl_FrontColor,  out 4-component vector of float BackColor gl_BackColor,  out 4-component vector of float FrontSecondaryColor gl_FrontSecondaryColor,  out 4-component vector of float BackSecondaryColor gl_BackSecondaryColor,  out unsized 1-element array of 4-component vector of float TexCoord gl_TexCoord,  out float FogFragCoord gl_FogFragCoord})
+0:51          Constant:
+0:51            0 (const uint)
+0:51        matrix-times-vector ( temp 4-component vector of float)
+0:51          uProj: direct index for structure (layout( column_major std140 offset=0) uniform 4X4 matrix of float)
+0:51            'anon@0' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4X4 matrix of float uProj})
+0:51            Constant:
+0:51              0 (const uint)
+0:51          Function Call: getWorld( ( global 4-component vector of float)
+0:?   Linker Objects
+0:?     'anon@0' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4X4 matrix of float uProj})
+0:?     'anon@1' (layout( column_major shared) buffer block{layout( column_major shared) buffer 4-component vector of float b})
+0:?     'anon@2' ( out block{ out 4-component vector of float v1})
+0:?     'myName' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4X4 matrix of float m})
+0:?     'oColor' ( smooth out 4-component vector of float)
+0:?     'anon@4' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out unsized 1-element array of float ClipDistance gl_ClipDistance,  gl_ClipVertex 4-component vector of float ClipVertex gl_ClipVertex,  out 4-component vector of float FrontColor gl_FrontColor,  out 4-component vector of float BackColor gl_BackColor,  out 4-component vector of float FrontSecondaryColor gl_FrontSecondaryColor,  out 4-component vector of float BackSecondaryColor gl_BackSecondaryColor,  out unsized 1-element array of 4-component vector of float TexCoord gl_TexCoord,  out float FogFragCoord gl_FogFragCoord})
+0:?     'gl_VertexID' ( gl_VertexId int VertexId)
+0:?     'gl_InstanceID' ( gl_InstanceId int InstanceId)
+
+link.multiAnonBlocksInvalid.0.1.vert
+Shader version: 430
+0:? Sequence
+0:38  Function Definition: getColor2( ( global 4-component vector of float)
+0:38    Function Parameters: 
+0:40    Sequence
+0:40      Branch: Return with expression
+0:40        color2: direct index for structure (layout( column_major std140 offset=0) uniform 4-component vector of float)
+0:40          'anon@0' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4-component vector of float color2})
+0:40          Constant:
+0:40            0 (const uint)
+0:43  Function Definition: getWorld( ( global 4-component vector of float)
+0:43    Function Parameters: 
+0:45    Sequence
+0:45      Branch: Return with expression
+0:45        matrix-times-vector ( temp 4-component vector of float)
+0:45          uWorld: direct index for structure (layout( column_major std140 offset=64) uniform 4X4 matrix of float)
+0:45            'anon@1' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4X4 matrix of float uProj, layout( column_major std140 offset=64) uniform 4X4 matrix of float uWorld})
+0:45            Constant:
+0:45              1 (const uint)
+0:45          'P' ( in 4-component vector of float)
+0:46      move second child to first child ( temp 4-component vector of float)
+0:46        v2: direct index for structure ( out 4-component vector of float)
+0:46          'anon@2' ( out block{ out 4-component vector of float v1,  out 4-component vector of float v2})
+0:46          Constant:
+0:46            1 (const uint)
+0:46        Constant:
+0:46          1.000000
+0:46          1.000000
+0:46          1.000000
+0:46          1.000000
+0:?   Linker Objects
+0:?     'anon@0' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4-component vector of float color2})
+0:?     'anon@1' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4X4 matrix of float uProj, layout( column_major std140 offset=64) uniform 4X4 matrix of float uWorld})
+0:?     'anon@2' ( out block{ out 4-component vector of float v1,  out 4-component vector of float v2})
+0:?     'anon@3' (layout( column_major shared) buffer block{layout( column_major shared) buffer 4-component vector of float a})
+0:?     'anon@4' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4X4 matrix of float m})
+0:?     'P' ( in 4-component vector of float)
+0:?     'gl_VertexID' ( gl_VertexId int VertexId)
+0:?     'gl_InstanceID' ( gl_InstanceId int InstanceId)
+
+
+Linked vertex stage:
+
+ERROR: Linking vertex stage: Types must match:
+    anon@0: "layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4X4 matrix of float uProj}" versus anon@1: "layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4X4 matrix of float uProj, layout( column_major std140 offset=64) uniform 4X4 matrix of float uWorld}"
+ERROR: Linking vertex stage: Types must match:
+    anon@2: " out block{ out 4-component vector of float v1}" versus " out block{ out 4-component vector of float v1,  out 4-component vector of float v2}"
+ERROR: Linking vertex stage: Types must match:
+    anon@1: "layout( column_major shared) buffer block{layout( column_major shared) buffer 4-component vector of float b}" versus anon@3: "layout( column_major shared) buffer block{layout( column_major shared) buffer 4-component vector of float a}"
+ERROR: Linking vertex stage: Matched Uniform or Storage blocks must all be anonymous, or all be named:
+WARNING: Linking vertex stage: Matched shader interfaces are using different instance names.
+    myName: "layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4X4 matrix of float m}" versus anon@4: "layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4X4 matrix of float m}"
+
+Shader version: 430
+ERROR: node is still EOpNull!
+0:46  Function Definition: main( ( global void)
+0:46    Function Parameters: 
+0:48    Sequence
+0:48      move second child to first child ( temp 4-component vector of float)
+0:48        'oColor' ( smooth out 4-component vector of float)
+0:48        component-wise multiply ( temp 4-component vector of float)
+0:48          color1: direct index for structure (layout( column_major std140 offset=0) uniform 4-component vector of float)
+0:48            'anon@3' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4-component vector of float color1, layout( column_major std140 offset=16) uniform 4-component vector of float color2, layout( column_major std140 offset=32) uniform 4-component vector of float v1})
+0:48            Constant:
+0:48              0 (const uint)
+0:48          Function Call: getColor2( ( global 4-component vector of float)
+0:49      move second child to first child ( temp 4-component vector of float)
+0:49        v1: direct index for structure ( out 4-component vector of float)
+0:49          'anon@2' ( out block{ out 4-component vector of float v1})
+0:49          Constant:
+0:49            0 (const uint)
+0:49        color1: direct index for structure (layout( column_major std140 offset=0) uniform 4-component vector of float)
+0:49          'anon@3' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4-component vector of float color1, layout( column_major std140 offset=16) uniform 4-component vector of float color2, layout( column_major std140 offset=32) uniform 4-component vector of float v1})
+0:49          Constant:
+0:49            0 (const uint)
+0:51      move second child to first child ( temp 4-component vector of float)
+0:51        gl_Position: direct index for structure ( gl_Position 4-component vector of float Position)
+0:51          'anon@4' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out 1-element array of float ClipDistance gl_ClipDistance,  gl_ClipVertex 4-component vector of float ClipVertex gl_ClipVertex,  out 4-component vector of float FrontColor gl_FrontColor,  out 4-component vector of float BackColor gl_BackColor,  out 4-component vector of float FrontSecondaryColor gl_FrontSecondaryColor,  out 4-component vector of float BackSecondaryColor gl_BackSecondaryColor,  out 1-element array of 4-component vector of float TexCoord gl_TexCoord,  out float FogFragCoord gl_FogFragCoord})
+0:51          Constant:
+0:51            0 (const uint)
+0:51        matrix-times-vector ( temp 4-component vector of float)
+0:51          uProj: direct index for structure (layout( column_major std140 offset=0) uniform 4X4 matrix of float)
+0:51            'anon@0' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4X4 matrix of float uProj})
+0:51            Constant:
+0:51              0 (const uint)
+0:51          Function Call: getWorld( ( global 4-component vector of float)
+0:38  Function Definition: getColor2( ( global 4-component vector of float)
+0:38    Function Parameters: 
+0:40    Sequence
+0:40      Branch: Return with expression
+0:40        color2: direct index for structure (layout( column_major std140 offset=0) uniform 4-component vector of float)
+0:40          'anon@0' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4-component vector of float color2})
+0:40          Constant:
+0:40            0 (const uint)
+0:43  Function Definition: getWorld( ( global 4-component vector of float)
+0:43    Function Parameters: 
+0:45    Sequence
+0:45      Branch: Return with expression
+0:45        matrix-times-vector ( temp 4-component vector of float)
+0:45          uWorld: direct index for structure (layout( column_major std140 offset=64) uniform 4X4 matrix of float)
+0:45            'anon@1' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4X4 matrix of float uProj, layout( column_major std140 offset=64) uniform 4X4 matrix of float uWorld})
+0:45            Constant:
+0:45              1 (const uint)
+0:45          'P' ( in 4-component vector of float)
+0:46      move second child to first child ( temp 4-component vector of float)
+0:46        v2: direct index for structure ( out 4-component vector of float)
+0:46          'anon@2' ( out block{ out 4-component vector of float v1,  out 4-component vector of float v2})
+0:46          Constant:
+0:46            1 (const uint)
+0:46        Constant:
+0:46          1.000000
+0:46          1.000000
+0:46          1.000000
+0:46          1.000000
+0:?   Linker Objects
+0:?     'anon@0' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4X4 matrix of float uProj})
+0:?     'anon@1' (layout( column_major shared) buffer block{layout( column_major shared) buffer 4-component vector of float b})
+0:?     'anon@2' ( out block{ out 4-component vector of float v1})
+0:?     'myName' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4X4 matrix of float m})
+0:?     'oColor' ( smooth out 4-component vector of float)
+0:?     'anon@4' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out 1-element array of float ClipDistance gl_ClipDistance,  gl_ClipVertex 4-component vector of float ClipVertex gl_ClipVertex,  out 4-component vector of float FrontColor gl_FrontColor,  out 4-component vector of float BackColor gl_BackColor,  out 4-component vector of float FrontSecondaryColor gl_FrontSecondaryColor,  out 4-component vector of float BackSecondaryColor gl_BackSecondaryColor,  out 1-element array of 4-component vector of float TexCoord gl_TexCoord,  out float FogFragCoord gl_FogFragCoord})
+0:?     'gl_VertexID' ( gl_VertexId int VertexId)
+0:?     'gl_InstanceID' ( gl_InstanceId int InstanceId)
+0:?     'anon@0' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4-component vector of float color2})
+0:?     'P' ( in 4-component vector of float)
+
diff --git a/third_party/glslang/src/Test/baseResults/link.multiAnonBlocksValid.0.0.vert.out b/third_party/glslang/src/Test/baseResults/link.multiAnonBlocksValid.0.0.vert.out
new file mode 100755
index 0000000..87c31b1
--- /dev/null
+++ b/third_party/glslang/src/Test/baseResults/link.multiAnonBlocksValid.0.0.vert.out
@@ -0,0 +1,157 @@
+link.multiAnonBlocksValid.0.0.vert
+Shader version: 430
+0:? Sequence
+0:32  Function Definition: main( ( global void)
+0:32    Function Parameters: 
+0:34    Sequence
+0:34      move second child to first child ( temp 4-component vector of float)
+0:34        'oColor' ( smooth out 4-component vector of float)
+0:34        component-wise multiply ( temp 4-component vector of float)
+0:34          color1: direct index for structure (layout( column_major std140 offset=0) uniform 4-component vector of float)
+0:34            'anon@2' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4-component vector of float color1, layout( column_major std140 offset=16) uniform 4-component vector of float color2})
+0:34            Constant:
+0:34              0 (const uint)
+0:34          Function Call: getColor2( ( global 4-component vector of float)
+0:35      move second child to first child ( temp 4-component vector of float)
+0:35        v1: direct index for structure ( out 4-component vector of float)
+0:35          'anon@1' ( out block{ out 4-component vector of float v1,  out 4-component vector of float v2})
+0:35          Constant:
+0:35            0 (const uint)
+0:35        color1: direct index for structure (layout( column_major std140 offset=0) uniform 4-component vector of float)
+0:35          'anon@2' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4-component vector of float color1, layout( column_major std140 offset=16) uniform 4-component vector of float color2})
+0:35          Constant:
+0:35            0 (const uint)
+0:37      move second child to first child ( temp 4-component vector of float)
+0:37        gl_Position: direct index for structure ( gl_Position 4-component vector of float Position)
+0:37          'anon@3' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out unsized 1-element array of float ClipDistance gl_ClipDistance,  gl_ClipVertex 4-component vector of float ClipVertex gl_ClipVertex,  out 4-component vector of float FrontColor gl_FrontColor,  out 4-component vector of float BackColor gl_BackColor,  out 4-component vector of float FrontSecondaryColor gl_FrontSecondaryColor,  out 4-component vector of float BackSecondaryColor gl_BackSecondaryColor,  out unsized 1-element array of 4-component vector of float TexCoord gl_TexCoord,  out float FogFragCoord gl_FogFragCoord})
+0:37          Constant:
+0:37            0 (const uint)
+0:37        matrix-times-vector ( temp 4-component vector of float)
+0:37          uProj: direct index for structure (layout( column_major std140 offset=0) uniform 4X4 matrix of float)
+0:37            'anon@0' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4X4 matrix of float uProj, layout( column_major std140 offset=64) uniform 4X4 matrix of float uWorld})
+0:37            Constant:
+0:37              0 (const uint)
+0:37          Function Call: getWorld( ( global 4-component vector of float)
+0:?   Linker Objects
+0:?     'anon@0' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4X4 matrix of float uProj, layout( column_major std140 offset=64) uniform 4X4 matrix of float uWorld})
+0:?     'anon@1' ( out block{ out 4-component vector of float v1,  out 4-component vector of float v2})
+0:?     'anon@2' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4-component vector of float color1, layout( column_major std140 offset=16) uniform 4-component vector of float color2})
+0:?     'oColor' ( smooth out 4-component vector of float)
+0:?     'anon@3' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out unsized 1-element array of float ClipDistance gl_ClipDistance,  gl_ClipVertex 4-component vector of float ClipVertex gl_ClipVertex,  out 4-component vector of float FrontColor gl_FrontColor,  out 4-component vector of float BackColor gl_BackColor,  out 4-component vector of float FrontSecondaryColor gl_FrontSecondaryColor,  out 4-component vector of float BackSecondaryColor gl_BackSecondaryColor,  out unsized 1-element array of 4-component vector of float TexCoord gl_TexCoord,  out float FogFragCoord gl_FogFragCoord})
+0:?     'gl_VertexID' ( gl_VertexId int VertexId)
+0:?     'gl_InstanceID' ( gl_InstanceId int InstanceId)
+
+link.multiAnonBlocksValid.0.1.vert
+Shader version: 430
+0:? Sequence
+0:24  Function Definition: getColor2( ( global 4-component vector of float)
+0:24    Function Parameters: 
+0:26    Sequence
+0:26      Branch: Return with expression
+0:26        color2: direct index for structure (layout( column_major std140 offset=16) uniform 4-component vector of float)
+0:26          'anon@0' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4-component vector of float color1, layout( column_major std140 offset=16) uniform 4-component vector of float color2})
+0:26          Constant:
+0:26            1 (const uint)
+0:29  Function Definition: getWorld( ( global 4-component vector of float)
+0:29    Function Parameters: 
+0:31    Sequence
+0:31      Branch: Return with expression
+0:31        matrix-times-vector ( temp 4-component vector of float)
+0:31          uWorld: direct index for structure (layout( column_major std140 offset=64) uniform 4X4 matrix of float)
+0:31            'anon@1' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4X4 matrix of float uProj, layout( column_major std140 offset=64) uniform 4X4 matrix of float uWorld})
+0:31            Constant:
+0:31              1 (const uint)
+0:31          'P' ( in 4-component vector of float)
+0:32      move second child to first child ( temp 4-component vector of float)
+0:32        v2: direct index for structure ( out 4-component vector of float)
+0:32          'anon@2' ( out block{ out 4-component vector of float v1,  out 4-component vector of float v2})
+0:32          Constant:
+0:32            1 (const uint)
+0:32        Constant:
+0:32          1.000000
+0:32          1.000000
+0:32          1.000000
+0:32          1.000000
+0:?   Linker Objects
+0:?     'anon@0' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4-component vector of float color1, layout( column_major std140 offset=16) uniform 4-component vector of float color2})
+0:?     'anon@1' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4X4 matrix of float uProj, layout( column_major std140 offset=64) uniform 4X4 matrix of float uWorld})
+0:?     'anon@2' ( out block{ out 4-component vector of float v1,  out 4-component vector of float v2})
+0:?     'P' ( in 4-component vector of float)
+0:?     'gl_VertexID' ( gl_VertexId int VertexId)
+0:?     'gl_InstanceID' ( gl_InstanceId int InstanceId)
+
+
+Linked vertex stage:
+
+
+Shader version: 430
+0:? Sequence
+0:32  Function Definition: main( ( global void)
+0:32    Function Parameters: 
+0:34    Sequence
+0:34      move second child to first child ( temp 4-component vector of float)
+0:34        'oColor' ( smooth out 4-component vector of float)
+0:34        component-wise multiply ( temp 4-component vector of float)
+0:34          color1: direct index for structure (layout( column_major std140 offset=0) uniform 4-component vector of float)
+0:34            'anon@2' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4-component vector of float color1, layout( column_major std140 offset=16) uniform 4-component vector of float color2})
+0:34            Constant:
+0:34              0 (const uint)
+0:34          Function Call: getColor2( ( global 4-component vector of float)
+0:35      move second child to first child ( temp 4-component vector of float)
+0:35        v1: direct index for structure ( out 4-component vector of float)
+0:35          'anon@1' ( out block{ out 4-component vector of float v1,  out 4-component vector of float v2})
+0:35          Constant:
+0:35            0 (const uint)
+0:35        color1: direct index for structure (layout( column_major std140 offset=0) uniform 4-component vector of float)
+0:35          'anon@2' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4-component vector of float color1, layout( column_major std140 offset=16) uniform 4-component vector of float color2})
+0:35          Constant:
+0:35            0 (const uint)
+0:37      move second child to first child ( temp 4-component vector of float)
+0:37        gl_Position: direct index for structure ( gl_Position 4-component vector of float Position)
+0:37          'anon@3' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out 1-element array of float ClipDistance gl_ClipDistance,  gl_ClipVertex 4-component vector of float ClipVertex gl_ClipVertex,  out 4-component vector of float FrontColor gl_FrontColor,  out 4-component vector of float BackColor gl_BackColor,  out 4-component vector of float FrontSecondaryColor gl_FrontSecondaryColor,  out 4-component vector of float BackSecondaryColor gl_BackSecondaryColor,  out 1-element array of 4-component vector of float TexCoord gl_TexCoord,  out float FogFragCoord gl_FogFragCoord})
+0:37          Constant:
+0:37            0 (const uint)
+0:37        matrix-times-vector ( temp 4-component vector of float)
+0:37          uProj: direct index for structure (layout( column_major std140 offset=0) uniform 4X4 matrix of float)
+0:37            'anon@0' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4X4 matrix of float uProj, layout( column_major std140 offset=64) uniform 4X4 matrix of float uWorld})
+0:37            Constant:
+0:37              0 (const uint)
+0:37          Function Call: getWorld( ( global 4-component vector of float)
+0:24  Function Definition: getColor2( ( global 4-component vector of float)
+0:24    Function Parameters: 
+0:26    Sequence
+0:26      Branch: Return with expression
+0:26        color2: direct index for structure (layout( column_major std140 offset=16) uniform 4-component vector of float)
+0:26          'anon@0' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4-component vector of float color1, layout( column_major std140 offset=16) uniform 4-component vector of float color2})
+0:26          Constant:
+0:26            1 (const uint)
+0:29  Function Definition: getWorld( ( global 4-component vector of float)
+0:29    Function Parameters: 
+0:31    Sequence
+0:31      Branch: Return with expression
+0:31        matrix-times-vector ( temp 4-component vector of float)
+0:31          uWorld: direct index for structure (layout( column_major std140 offset=64) uniform 4X4 matrix of float)
+0:31            'anon@1' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4X4 matrix of float uProj, layout( column_major std140 offset=64) uniform 4X4 matrix of float uWorld})
+0:31            Constant:
+0:31              1 (const uint)
+0:31          'P' ( in 4-component vector of float)
+0:32      move second child to first child ( temp 4-component vector of float)
+0:32        v2: direct index for structure ( out 4-component vector of float)
+0:32          'anon@2' ( out block{ out 4-component vector of float v1,  out 4-component vector of float v2})
+0:32          Constant:
+0:32            1 (const uint)
+0:32        Constant:
+0:32          1.000000
+0:32          1.000000
+0:32          1.000000
+0:32          1.000000
+0:?   Linker Objects
+0:?     'anon@0' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4X4 matrix of float uProj, layout( column_major std140 offset=64) uniform 4X4 matrix of float uWorld})
+0:?     'anon@1' ( out block{ out 4-component vector of float v1,  out 4-component vector of float v2})
+0:?     'anon@2' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4-component vector of float color1, layout( column_major std140 offset=16) uniform 4-component vector of float color2})
+0:?     'oColor' ( smooth out 4-component vector of float)
+0:?     'anon@3' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out 1-element array of float ClipDistance gl_ClipDistance,  gl_ClipVertex 4-component vector of float ClipVertex gl_ClipVertex,  out 4-component vector of float FrontColor gl_FrontColor,  out 4-component vector of float BackColor gl_BackColor,  out 4-component vector of float FrontSecondaryColor gl_FrontSecondaryColor,  out 4-component vector of float BackSecondaryColor gl_BackSecondaryColor,  out 1-element array of 4-component vector of float TexCoord gl_TexCoord,  out float FogFragCoord gl_FogFragCoord})
+0:?     'gl_VertexID' ( gl_VertexId int VertexId)
+0:?     'gl_InstanceID' ( gl_InstanceId int InstanceId)
+0:?     'P' ( in 4-component vector of float)
+
diff --git a/third_party/glslang/src/Test/baseResults/link.multiBlocksInvalid.0.0.vert.out b/third_party/glslang/src/Test/baseResults/link.multiBlocksInvalid.0.0.vert.out
new file mode 100755
index 0000000..12b5c43
--- /dev/null
+++ b/third_party/glslang/src/Test/baseResults/link.multiBlocksInvalid.0.0.vert.out
@@ -0,0 +1,182 @@
+link.multiBlocksInvalid.0.0.vert
+Shader version: 430
+0:? Sequence
+0:34  Function Definition: main( ( global void)
+0:34    Function Parameters: 
+0:36    Sequence
+0:36      move second child to first child ( temp 4-component vector of float)
+0:36        'oColor' ( smooth out 4-component vector of float)
+0:36        component-wise multiply ( temp 4-component vector of float)
+0:36          color1: direct index for structure (layout( column_major std140 offset=0) uniform 4-component vector of float)
+0:36            'uC' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4-component vector of float color1})
+0:36            Constant:
+0:36              0 (const int)
+0:36          Function Call: getColor2( ( global 4-component vector of float)
+0:37      move second child to first child ( temp 4-component vector of float)
+0:37        v1: direct index for structure ( out 4-component vector of float)
+0:37          'oV' ( out block{ out 4-component vector of float v1})
+0:37          Constant:
+0:37            0 (const int)
+0:37        add ( temp 4-component vector of float)
+0:37          color1: direct index for structure (layout( column_major std140 offset=0) uniform 4-component vector of float)
+0:37            'uC' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4-component vector of float color1})
+0:37            Constant:
+0:37              0 (const int)
+0:37          color1: direct index for structure (layout( column_major std430 offset=0) buffer 4-component vector of float)
+0:37            'uBufC' (layout( column_major std430) buffer block{layout( column_major std430 offset=0) buffer 4-component vector of float color1})
+0:37            Constant:
+0:37              0 (const int)
+0:39      move second child to first child ( temp 4-component vector of float)
+0:39        gl_Position: direct index for structure ( gl_Position 4-component vector of float Position)
+0:39          'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out unsized 1-element array of float ClipDistance gl_ClipDistance,  gl_ClipVertex 4-component vector of float ClipVertex gl_ClipVertex,  out 4-component vector of float FrontColor gl_FrontColor,  out 4-component vector of float BackColor gl_BackColor,  out 4-component vector of float FrontSecondaryColor gl_FrontSecondaryColor,  out 4-component vector of float BackSecondaryColor gl_BackSecondaryColor,  out unsized 1-element array of 4-component vector of float TexCoord gl_TexCoord,  out float FogFragCoord gl_FogFragCoord})
+0:39          Constant:
+0:39            0 (const uint)
+0:39        matrix-times-vector ( temp 4-component vector of float)
+0:39          uProj: direct index for structure (layout( column_major std140 offset=0) uniform 4X4 matrix of float)
+0:39            'uD' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4X4 matrix of float uProj})
+0:39            Constant:
+0:39              0 (const int)
+0:39          Function Call: getWorld( ( global 4-component vector of float)
+0:?   Linker Objects
+0:?     'uD' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4X4 matrix of float uProj})
+0:?     'oV' ( out block{ out 4-component vector of float v1})
+0:?     'uC' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4-component vector of float color1})
+0:?     'uBufC' (layout( column_major std430) buffer block{layout( column_major std430 offset=0) buffer 4-component vector of float color1})
+0:?     'oColor' ( smooth out 4-component vector of float)
+0:?     'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out unsized 1-element array of float ClipDistance gl_ClipDistance,  gl_ClipVertex 4-component vector of float ClipVertex gl_ClipVertex,  out 4-component vector of float FrontColor gl_FrontColor,  out 4-component vector of float BackColor gl_BackColor,  out 4-component vector of float FrontSecondaryColor gl_FrontSecondaryColor,  out 4-component vector of float BackSecondaryColor gl_BackSecondaryColor,  out unsized 1-element array of 4-component vector of float TexCoord gl_TexCoord,  out float FogFragCoord gl_FogFragCoord})
+0:?     'gl_VertexID' ( gl_VertexId int VertexId)
+0:?     'gl_InstanceID' ( gl_InstanceId int InstanceId)
+
+link.multiBlocksInvalid.0.1.vert
+Shader version: 430
+0:? Sequence
+0:21  Function Definition: getColor2( ( global 4-component vector of float)
+0:21    Function Parameters: 
+0:23    Sequence
+0:23      Branch: Return with expression
+0:23        color2: direct index for structure (layout( column_major std140 offset=0) uniform 4-component vector of float)
+0:23          'uColorB' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4-component vector of float color2})
+0:23          Constant:
+0:23            0 (const int)
+0:26  Function Definition: getWorld( ( global 4-component vector of float)
+0:26    Function Parameters: 
+0:28    Sequence
+0:28      Branch: Return with expression
+0:28        matrix-times-vector ( temp 4-component vector of float)
+0:28          uWorld: direct index for structure (layout( column_major std140 offset=0) uniform 4X4 matrix of float)
+0:28            'uDefaultB' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4X4 matrix of float uWorld})
+0:28            Constant:
+0:28              0 (const int)
+0:28          'P' ( in 4-component vector of float)
+0:29      move second child to first child ( temp 4-component vector of float)
+0:29        v2: direct index for structure ( out 4-component vector of float)
+0:29          'oVert' ( out block{ out 4-component vector of float v2})
+0:29          Constant:
+0:29            0 (const int)
+0:29        Constant:
+0:29          1.000000
+0:29          1.000000
+0:29          1.000000
+0:29          1.000000
+0:?   Linker Objects
+0:?     'uColorB' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4-component vector of float color2})
+0:?     'uDefaultB' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4X4 matrix of float uWorld})
+0:?     'oVert' ( out block{ out 4-component vector of float v2})
+0:?     'P' ( in 4-component vector of float)
+0:?     'gl_VertexID' ( gl_VertexId int VertexId)
+0:?     'gl_InstanceID' ( gl_InstanceId int InstanceId)
+
+
+Linked vertex stage:
+
+ERROR: Linking vertex stage: Types must match:
+WARNING: Linking vertex stage: Matched shader interfaces are using different instance names.
+    uC: "layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4-component vector of float color1}" versus uColorB: "layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4-component vector of float color2}"
+ERROR: Linking vertex stage: Types must match:
+ERROR: Linking vertex stage: Storage qualifiers must match:
+ERROR: Linking vertex stage: Layout qualification must match:
+    uBufC: "layout( column_major std430) buffer block{layout( column_major std430 offset=0) buffer 4-component vector of float color1}" versus uColorB: "layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4-component vector of float color2}"
+ERROR: Linking vertex stage: Types must match:
+WARNING: Linking vertex stage: Matched shader interfaces are using different instance names.
+    uD: "layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4X4 matrix of float uProj}" versus uDefaultB: "layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4X4 matrix of float uWorld}"
+ERROR: Linking vertex stage: Types must match:
+WARNING: Linking vertex stage: Matched shader interfaces are using different instance names.
+    oV: " out block{ out 4-component vector of float v1}" versus oVert: " out block{ out 4-component vector of float v2}"
+
+Shader version: 430
+0:? Sequence
+0:34  Function Definition: main( ( global void)
+0:34    Function Parameters: 
+0:36    Sequence
+0:36      move second child to first child ( temp 4-component vector of float)
+0:36        'oColor' ( smooth out 4-component vector of float)
+0:36        component-wise multiply ( temp 4-component vector of float)
+0:36          color1: direct index for structure (layout( column_major std140 offset=0) uniform 4-component vector of float)
+0:36            'uC' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4-component vector of float color1})
+0:36            Constant:
+0:36              0 (const int)
+0:36          Function Call: getColor2( ( global 4-component vector of float)
+0:37      move second child to first child ( temp 4-component vector of float)
+0:37        v1: direct index for structure ( out 4-component vector of float)
+0:37          'oV' ( out block{ out 4-component vector of float v1})
+0:37          Constant:
+0:37            0 (const int)
+0:37        add ( temp 4-component vector of float)
+0:37          color1: direct index for structure (layout( column_major std140 offset=0) uniform 4-component vector of float)
+0:37            'uC' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4-component vector of float color1})
+0:37            Constant:
+0:37              0 (const int)
+0:37          color1: direct index for structure (layout( column_major std430 offset=0) buffer 4-component vector of float)
+0:37            'uBufC' (layout( column_major std430) buffer block{layout( column_major std430 offset=0) buffer 4-component vector of float color1})
+0:37            Constant:
+0:37              0 (const int)
+0:39      move second child to first child ( temp 4-component vector of float)
+0:39        gl_Position: direct index for structure ( gl_Position 4-component vector of float Position)
+0:39          'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out 1-element array of float ClipDistance gl_ClipDistance,  gl_ClipVertex 4-component vector of float ClipVertex gl_ClipVertex,  out 4-component vector of float FrontColor gl_FrontColor,  out 4-component vector of float BackColor gl_BackColor,  out 4-component vector of float FrontSecondaryColor gl_FrontSecondaryColor,  out 4-component vector of float BackSecondaryColor gl_BackSecondaryColor,  out 1-element array of 4-component vector of float TexCoord gl_TexCoord,  out float FogFragCoord gl_FogFragCoord})
+0:39          Constant:
+0:39            0 (const uint)
+0:39        matrix-times-vector ( temp 4-component vector of float)
+0:39          uProj: direct index for structure (layout( column_major std140 offset=0) uniform 4X4 matrix of float)
+0:39            'uD' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4X4 matrix of float uProj})
+0:39            Constant:
+0:39              0 (const int)
+0:39          Function Call: getWorld( ( global 4-component vector of float)
+0:21  Function Definition: getColor2( ( global 4-component vector of float)
+0:21    Function Parameters: 
+0:23    Sequence
+0:23      Branch: Return with expression
+0:23        color2: direct index for structure (layout( column_major std140 offset=0) uniform 4-component vector of float)
+0:23          'uColorB' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4-component vector of float color2})
+0:23          Constant:
+0:23            0 (const int)
+0:26  Function Definition: getWorld( ( global 4-component vector of float)
+0:26    Function Parameters: 
+0:28    Sequence
+0:28      Branch: Return with expression
+0:28        matrix-times-vector ( temp 4-component vector of float)
+0:28          uWorld: direct index for structure (layout( column_major std140 offset=0) uniform 4X4 matrix of float)
+0:28            'uDefaultB' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4X4 matrix of float uWorld})
+0:28            Constant:
+0:28              0 (const int)
+0:28          'P' ( in 4-component vector of float)
+0:29      move second child to first child ( temp 4-component vector of float)
+0:29        v2: direct index for structure ( out 4-component vector of float)
+0:29          'oVert' ( out block{ out 4-component vector of float v2})
+0:29          Constant:
+0:29            0 (const int)
+0:29        Constant:
+0:29          1.000000
+0:29          1.000000
+0:29          1.000000
+0:29          1.000000
+0:?   Linker Objects
+0:?     'uD' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4X4 matrix of float uProj})
+0:?     'oV' ( out block{ out 4-component vector of float v1})
+0:?     'uC' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4-component vector of float color1})
+0:?     'uBufC' (layout( column_major std430) buffer block{layout( column_major std430 offset=0) buffer 4-component vector of float color1})
+0:?     'oColor' ( smooth out 4-component vector of float)
+0:?     'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out 1-element array of float ClipDistance gl_ClipDistance,  gl_ClipVertex 4-component vector of float ClipVertex gl_ClipVertex,  out 4-component vector of float FrontColor gl_FrontColor,  out 4-component vector of float BackColor gl_BackColor,  out 4-component vector of float FrontSecondaryColor gl_FrontSecondaryColor,  out 4-component vector of float BackSecondaryColor gl_BackSecondaryColor,  out 1-element array of 4-component vector of float TexCoord gl_TexCoord,  out float FogFragCoord gl_FogFragCoord})
+0:?     'gl_VertexID' ( gl_VertexId int VertexId)
+0:?     'gl_InstanceID' ( gl_InstanceId int InstanceId)
+0:?     'P' ( in 4-component vector of float)
+
diff --git a/third_party/glslang/src/Test/baseResults/link.multiBlocksValid.1.0.vert.out b/third_party/glslang/src/Test/baseResults/link.multiBlocksValid.1.0.vert.out
new file mode 100755
index 0000000..2f32abd
--- /dev/null
+++ b/third_party/glslang/src/Test/baseResults/link.multiBlocksValid.1.0.vert.out
@@ -0,0 +1,163 @@
+link.multiBlocksValid.1.0.vert
+Shader version: 430
+0:? Sequence
+0:26  Function Definition: main( ( global void)
+0:26    Function Parameters: 
+0:28    Sequence
+0:28      move second child to first child ( temp 4-component vector of float)
+0:28        'oColor' ( smooth out 4-component vector of float)
+0:28        component-wise multiply ( temp 4-component vector of float)
+0:28          color1: direct index for structure (layout( column_major std140 offset=0) uniform 4-component vector of float)
+0:28            'c' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4-component vector of float color1, layout( column_major std140 offset=16) uniform 4-component vector of float color2})
+0:28            Constant:
+0:28              0 (const int)
+0:28          Function Call: getColor2( ( global 4-component vector of float)
+0:29      move second child to first child ( temp 4-component vector of float)
+0:29        v1: direct index for structure ( out 4-component vector of float)
+0:29          'b' ( out block{ out 4-component vector of float v1,  out 4-component vector of float v2})
+0:29          Constant:
+0:29            0 (const int)
+0:29        color1: direct index for structure (layout( column_major std140 offset=0) uniform 4-component vector of float)
+0:29          'c' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4-component vector of float color1, layout( column_major std140 offset=16) uniform 4-component vector of float color2})
+0:29          Constant:
+0:29            0 (const int)
+0:31      move second child to first child ( temp 4-component vector of float)
+0:31        gl_Position: direct index for structure ( gl_Position 4-component vector of float Position)
+0:31          'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out unsized 1-element array of float ClipDistance gl_ClipDistance,  gl_ClipVertex 4-component vector of float ClipVertex gl_ClipVertex,  out 4-component vector of float FrontColor gl_FrontColor,  out 4-component vector of float BackColor gl_BackColor,  out 4-component vector of float FrontSecondaryColor gl_FrontSecondaryColor,  out 4-component vector of float BackSecondaryColor gl_BackSecondaryColor,  out unsized 1-element array of 4-component vector of float TexCoord gl_TexCoord,  out float FogFragCoord gl_FogFragCoord})
+0:31          Constant:
+0:31            0 (const uint)
+0:31        matrix-times-vector ( temp 4-component vector of float)
+0:31          uProj: direct index for structure (layout( column_major std140 offset=0) uniform 4X4 matrix of float)
+0:31            'a' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4X4 matrix of float uProj, layout( column_major std140 offset=64) uniform 4X4 matrix of float uWorld})
+0:31            Constant:
+0:31              0 (const int)
+0:31          Function Call: getWorld( ( global 4-component vector of float)
+0:?   Linker Objects
+0:?     'a' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4X4 matrix of float uProj, layout( column_major std140 offset=64) uniform 4X4 matrix of float uWorld})
+0:?     'b' ( out block{ out 4-component vector of float v1,  out 4-component vector of float v2})
+0:?     'c' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4-component vector of float color1, layout( column_major std140 offset=16) uniform 4-component vector of float color2})
+0:?     'oColor' ( smooth out 4-component vector of float)
+0:?     'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out unsized 1-element array of float ClipDistance gl_ClipDistance,  gl_ClipVertex 4-component vector of float ClipVertex gl_ClipVertex,  out 4-component vector of float FrontColor gl_FrontColor,  out 4-component vector of float BackColor gl_BackColor,  out 4-component vector of float FrontSecondaryColor gl_FrontSecondaryColor,  out 4-component vector of float BackSecondaryColor gl_BackSecondaryColor,  out unsized 1-element array of 4-component vector of float TexCoord gl_TexCoord,  out float FogFragCoord gl_FogFragCoord})
+0:?     'gl_VertexID' ( gl_VertexId int VertexId)
+0:?     'gl_InstanceID' ( gl_InstanceId int InstanceId)
+
+link.multiBlocksValid.1.1.vert
+Shader version: 430
+0:? Sequence
+0:24  Function Definition: getColor2( ( global 4-component vector of float)
+0:24    Function Parameters: 
+0:26    Sequence
+0:26      Branch: Return with expression
+0:26        color2: direct index for structure (layout( column_major std140 offset=16) uniform 4-component vector of float)
+0:26          'a' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4-component vector of float color1, layout( column_major std140 offset=16) uniform 4-component vector of float color2})
+0:26          Constant:
+0:26            1 (const int)
+0:29  Function Definition: getWorld( ( global 4-component vector of float)
+0:29    Function Parameters: 
+0:31    Sequence
+0:31      Branch: Return with expression
+0:31        matrix-times-vector ( temp 4-component vector of float)
+0:31          uWorld: direct index for structure (layout( column_major std140 offset=64) uniform 4X4 matrix of float)
+0:31            'b' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4X4 matrix of float uProj, layout( column_major std140 offset=64) uniform 4X4 matrix of float uWorld})
+0:31            Constant:
+0:31              1 (const int)
+0:31          'P' ( in 4-component vector of float)
+0:32      move second child to first child ( temp 4-component vector of float)
+0:32        v2: direct index for structure ( out 4-component vector of float)
+0:32          'c' ( out block{ out 4-component vector of float v1,  out 4-component vector of float v2})
+0:32          Constant:
+0:32            1 (const int)
+0:32        Constant:
+0:32          1.000000
+0:32          1.000000
+0:32          1.000000
+0:32          1.000000
+0:?   Linker Objects
+0:?     'a' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4-component vector of float color1, layout( column_major std140 offset=16) uniform 4-component vector of float color2})
+0:?     'b' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4X4 matrix of float uProj, layout( column_major std140 offset=64) uniform 4X4 matrix of float uWorld})
+0:?     'c' ( out block{ out 4-component vector of float v1,  out 4-component vector of float v2})
+0:?     'P' ( in 4-component vector of float)
+0:?     'gl_VertexID' ( gl_VertexId int VertexId)
+0:?     'gl_InstanceID' ( gl_InstanceId int InstanceId)
+
+
+Linked vertex stage:
+
+WARNING: Linking vertex stage: Matched shader interfaces are using different instance names.
+    c: "layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4-component vector of float color1, layout( column_major std140 offset=16) uniform 4-component vector of float color2}" versus a: "layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4-component vector of float color1, layout( column_major std140 offset=16) uniform 4-component vector of float color2}"
+WARNING: Linking vertex stage: Matched shader interfaces are using different instance names.
+    a: "layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4X4 matrix of float uProj, layout( column_major std140 offset=64) uniform 4X4 matrix of float uWorld}" versus b: "layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4X4 matrix of float uProj, layout( column_major std140 offset=64) uniform 4X4 matrix of float uWorld}"
+WARNING: Linking vertex stage: Matched shader interfaces are using different instance names.
+    b: " out block{ out 4-component vector of float v1,  out 4-component vector of float v2}" versus c: " out block{ out 4-component vector of float v1,  out 4-component vector of float v2}"
+
+Shader version: 430
+0:? Sequence
+0:26  Function Definition: main( ( global void)
+0:26    Function Parameters: 
+0:28    Sequence
+0:28      move second child to first child ( temp 4-component vector of float)
+0:28        'oColor' ( smooth out 4-component vector of float)
+0:28        component-wise multiply ( temp 4-component vector of float)
+0:28          color1: direct index for structure (layout( column_major std140 offset=0) uniform 4-component vector of float)
+0:28            'c' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4-component vector of float color1, layout( column_major std140 offset=16) uniform 4-component vector of float color2})
+0:28            Constant:
+0:28              0 (const int)
+0:28          Function Call: getColor2( ( global 4-component vector of float)
+0:29      move second child to first child ( temp 4-component vector of float)
+0:29        v1: direct index for structure ( out 4-component vector of float)
+0:29          'b' ( out block{ out 4-component vector of float v1,  out 4-component vector of float v2})
+0:29          Constant:
+0:29            0 (const int)
+0:29        color1: direct index for structure (layout( column_major std140 offset=0) uniform 4-component vector of float)
+0:29          'c' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4-component vector of float color1, layout( column_major std140 offset=16) uniform 4-component vector of float color2})
+0:29          Constant:
+0:29            0 (const int)
+0:31      move second child to first child ( temp 4-component vector of float)
+0:31        gl_Position: direct index for structure ( gl_Position 4-component vector of float Position)
+0:31          'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out 1-element array of float ClipDistance gl_ClipDistance,  gl_ClipVertex 4-component vector of float ClipVertex gl_ClipVertex,  out 4-component vector of float FrontColor gl_FrontColor,  out 4-component vector of float BackColor gl_BackColor,  out 4-component vector of float FrontSecondaryColor gl_FrontSecondaryColor,  out 4-component vector of float BackSecondaryColor gl_BackSecondaryColor,  out 1-element array of 4-component vector of float TexCoord gl_TexCoord,  out float FogFragCoord gl_FogFragCoord})
+0:31          Constant:
+0:31            0 (const uint)
+0:31        matrix-times-vector ( temp 4-component vector of float)
+0:31          uProj: direct index for structure (layout( column_major std140 offset=0) uniform 4X4 matrix of float)
+0:31            'a' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4X4 matrix of float uProj, layout( column_major std140 offset=64) uniform 4X4 matrix of float uWorld})
+0:31            Constant:
+0:31              0 (const int)
+0:31          Function Call: getWorld( ( global 4-component vector of float)
+0:24  Function Definition: getColor2( ( global 4-component vector of float)
+0:24    Function Parameters: 
+0:26    Sequence
+0:26      Branch: Return with expression
+0:26        color2: direct index for structure (layout( column_major std140 offset=16) uniform 4-component vector of float)
+0:26          'a' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4-component vector of float color1, layout( column_major std140 offset=16) uniform 4-component vector of float color2})
+0:26          Constant:
+0:26            1 (const int)
+0:29  Function Definition: getWorld( ( global 4-component vector of float)
+0:29    Function Parameters: 
+0:31    Sequence
+0:31      Branch: Return with expression
+0:31        matrix-times-vector ( temp 4-component vector of float)
+0:31          uWorld: direct index for structure (layout( column_major std140 offset=64) uniform 4X4 matrix of float)
+0:31            'b' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4X4 matrix of float uProj, layout( column_major std140 offset=64) uniform 4X4 matrix of float uWorld})
+0:31            Constant:
+0:31              1 (const int)
+0:31          'P' ( in 4-component vector of float)
+0:32      move second child to first child ( temp 4-component vector of float)
+0:32        v2: direct index for structure ( out 4-component vector of float)
+0:32          'c' ( out block{ out 4-component vector of float v1,  out 4-component vector of float v2})
+0:32          Constant:
+0:32            1 (const int)
+0:32        Constant:
+0:32          1.000000
+0:32          1.000000
+0:32          1.000000
+0:32          1.000000
+0:?   Linker Objects
+0:?     'a' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4X4 matrix of float uProj, layout( column_major std140 offset=64) uniform 4X4 matrix of float uWorld})
+0:?     'b' ( out block{ out 4-component vector of float v1,  out 4-component vector of float v2})
+0:?     'c' (layout( column_major std140) uniform block{layout( column_major std140 offset=0) uniform 4-component vector of float color1, layout( column_major std140 offset=16) uniform 4-component vector of float color2})
+0:?     'oColor' ( smooth out 4-component vector of float)
+0:?     'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out 1-element array of float ClipDistance gl_ClipDistance,  gl_ClipVertex 4-component vector of float ClipVertex gl_ClipVertex,  out 4-component vector of float FrontColor gl_FrontColor,  out 4-component vector of float BackColor gl_BackColor,  out 4-component vector of float FrontSecondaryColor gl_FrontSecondaryColor,  out 4-component vector of float BackSecondaryColor gl_BackSecondaryColor,  out 1-element array of 4-component vector of float TexCoord gl_TexCoord,  out float FogFragCoord gl_FogFragCoord})
+0:?     'gl_VertexID' ( gl_VertexId int VertexId)
+0:?     'gl_InstanceID' ( gl_InstanceId int InstanceId)
+0:?     'P' ( in 4-component vector of float)
+
diff --git a/third_party/glslang/src/Test/baseResults/link.vk.multiBlocksValid.0.0.vert.out b/third_party/glslang/src/Test/baseResults/link.vk.multiBlocksValid.0.0.vert.out
new file mode 100755
index 0000000..6440a3b
--- /dev/null
+++ b/third_party/glslang/src/Test/baseResults/link.vk.multiBlocksValid.0.0.vert.out
@@ -0,0 +1,321 @@
+link.vk.multiBlocksValid.0.0.vert
+Shader version: 430
+0:? Sequence
+0:43  Function Definition: main( ( global void)
+0:43    Function Parameters: 
+0:45    Sequence
+0:45      move second child to first child ( temp highp 4-component vector of float)
+0:45        'oColor' ( smooth out highp 4-component vector of float)
+0:45        component-wise multiply ( temp highp 4-component vector of float)
+0:45          component-wise multiply ( temp highp 4-component vector of float)
+0:45            color1: direct index for structure (layout( column_major std140 offset=0) uniform highp 4-component vector of float)
+0:45              'uC' (layout( binding=1 column_major std140) uniform block{layout( column_major std140 offset=0) uniform highp 4-component vector of float color1, layout( column_major std140 offset=16) uniform bool b, layout( column_major std140 offset=32) uniform highp 4-component vector of float color2, layout( column_major std140 offset=48) uniform highp 4-component vector of float color3})
+0:45              Constant:
+0:45                0 (const int)
+0:45            Function Call: getColor2( ( global highp 4-component vector of float)
+0:45          c: direct index for structure (layout( column_major std430 offset=0) buffer highp 4-component vector of float)
+0:45            'uColorBuf' (layout( binding=0 column_major std430) buffer block{layout( column_major std430 offset=0) buffer highp 4-component vector of float c})
+0:45            Constant:
+0:45              0 (const int)
+0:46      move second child to first child ( temp highp 4-component vector of float)
+0:46        v1: direct index for structure ( out highp 4-component vector of float)
+0:46          'oV' ( out block{ out highp 4-component vector of float v1,  out highp 4-component vector of float v2})
+0:46          Constant:
+0:46            0 (const int)
+0:46        color1: direct index for structure (layout( column_major std140 offset=0) uniform highp 4-component vector of float)
+0:46          'uC' (layout( binding=1 column_major std140) uniform block{layout( column_major std140 offset=0) uniform highp 4-component vector of float color1, layout( column_major std140 offset=16) uniform bool b, layout( column_major std140 offset=32) uniform highp 4-component vector of float color2, layout( column_major std140 offset=48) uniform highp 4-component vector of float color3})
+0:46          Constant:
+0:46            0 (const int)
+0:48      move second child to first child ( temp highp 4-component vector of float)
+0:48        gl_Position: direct index for structure ( gl_Position highp 4-component vector of float Position)
+0:48          'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out unsized 1-element array of float ClipDistance gl_ClipDistance})
+0:48          Constant:
+0:48            0 (const uint)
+0:48        matrix-times-vector ( temp highp 4-component vector of float)
+0:48          uProj: direct index for structure (layout( column_major std140 offset=0) uniform highp 4X4 matrix of float)
+0:48            'uM' (layout( binding=0 column_major std140) uniform block{layout( column_major std140 offset=0) uniform highp 4X4 matrix of float uProj, layout( column_major std140 offset=64) uniform highp 4X4 matrix of float uWorld})
+0:48            Constant:
+0:48              0 (const int)
+0:48          Function Call: getWorld( ( global highp 4-component vector of float)
+0:?   Linker Objects
+0:?     'uM' (layout( binding=0 column_major std140) uniform block{layout( column_major std140 offset=0) uniform highp 4X4 matrix of float uProj, layout( column_major std140 offset=64) uniform highp 4X4 matrix of float uWorld})
+0:?     'oV' ( out block{ out highp 4-component vector of float v1,  out highp 4-component vector of float v2})
+0:?     'uC' (layout( binding=1 column_major std140) uniform block{layout( column_major std140 offset=0) uniform highp 4-component vector of float color1, layout( column_major std140 offset=16) uniform bool b, layout( column_major std140 offset=32) uniform highp 4-component vector of float color2, layout( column_major std140 offset=48) uniform highp 4-component vector of float color3})
+0:?     'uBuf' (layout( binding=1 column_major std430) buffer block{layout( column_major std430 offset=0) buffer highp 4X4 matrix of float p})
+0:?     'uColorBuf' (layout( binding=0 column_major std430) buffer block{layout( column_major std430 offset=0) buffer highp 4-component vector of float c})
+0:?     'oColor' ( smooth out highp 4-component vector of float)
+0:?     'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out unsized 1-element array of float ClipDistance gl_ClipDistance})
+
+link.vk.multiBlocksValid.0.1.vert
+Shader version: 430
+0:? Sequence
+0:36  Function Definition: getColor2( ( global highp 4-component vector of float)
+0:36    Function Parameters: 
+0:38    Sequence
+0:38      Branch: Return with expression
+0:38        color2: direct index for structure (layout( column_major std140 offset=32) uniform highp 4-component vector of float)
+0:38          'uColor' (layout( binding=1 column_major std140) uniform block{layout( column_major std140 offset=0) uniform highp 4-component vector of float color1, layout( column_major std140 offset=16) uniform bool b, layout( column_major std140 offset=32) uniform highp 4-component vector of float color2, layout( column_major std140 offset=48) uniform highp 4-component vector of float color3})
+0:38          Constant:
+0:38            2 (const int)
+0:41  Function Definition: getWorld( ( global highp 4-component vector of float)
+0:41    Function Parameters: 
+0:43    Sequence
+0:43      move second child to first child ( temp highp 4-component vector of float)
+0:43        v1: direct index for structure ( out highp 4-component vector of float)
+0:43          'anon@0' ( out block{ out highp 4-component vector of float v1,  out highp 4-component vector of float v2})
+0:43          Constant:
+0:43            0 (const uint)
+0:43        Constant:
+0:43          1.000000
+0:43          1.000000
+0:43          1.000000
+0:43          1.000000
+0:44      Branch: Return with expression
+0:44        matrix-times-vector ( temp highp 4-component vector of float)
+0:44          uWorld: direct index for structure (layout( column_major std140 offset=64) uniform highp 4X4 matrix of float)
+0:44            'uMatrix' (layout( binding=0 column_major std140) uniform block{layout( column_major std140 offset=0) uniform highp 4X4 matrix of float uProj, layout( column_major std140 offset=64) uniform highp 4X4 matrix of float uWorld})
+0:44            Constant:
+0:44              1 (const int)
+0:44          'P' ( in highp 4-component vector of float)
+0:?   Linker Objects
+0:?     'uColor' (layout( binding=1 column_major std140) uniform block{layout( column_major std140 offset=0) uniform highp 4-component vector of float color1, layout( column_major std140 offset=16) uniform bool b, layout( column_major std140 offset=32) uniform highp 4-component vector of float color2, layout( column_major std140 offset=48) uniform highp 4-component vector of float color3})
+0:?     'uBuffer' (layout( binding=1 column_major std430) buffer block{layout( column_major std430 offset=0) buffer highp 4X4 matrix of float p})
+0:?     'uMatrix' (layout( binding=0 column_major std140) uniform block{layout( column_major std140 offset=0) uniform highp 4X4 matrix of float uProj, layout( column_major std140 offset=64) uniform highp 4X4 matrix of float uWorld})
+0:?     'anon@0' ( out block{ out highp 4-component vector of float v1,  out highp 4-component vector of float v2})
+0:?     'P' ( in highp 4-component vector of float)
+
+
+Linked vertex stage:
+
+WARNING: Linking vertex stage: Matched shader interfaces are using different instance names.
+    uC: "layout( binding=1 column_major std140) uniform block{layout( column_major std140 offset=0) uniform highp 4-component vector of float color1, layout( column_major std140 offset=16) uniform bool b, layout( column_major std140 offset=32) uniform highp 4-component vector of float color2, layout( column_major std140 offset=48) uniform highp 4-component vector of float color3}" versus uColor: "layout( binding=1 column_major std140) uniform block{layout( column_major std140 offset=0) uniform highp 4-component vector of float color1, layout( column_major std140 offset=16) uniform bool b, layout( column_major std140 offset=32) uniform highp 4-component vector of float color2, layout( column_major std140 offset=48) uniform highp 4-component vector of float color3}"
+WARNING: Linking vertex stage: Matched shader interfaces are using different instance names.
+    uBuf: "layout( binding=1 column_major std430) buffer block{layout( column_major std430 offset=0) buffer highp 4X4 matrix of float p}" versus uBuffer: "layout( binding=1 column_major std430) buffer block{layout( column_major std430 offset=0) buffer highp 4X4 matrix of float p}"
+WARNING: Linking vertex stage: Matched shader interfaces are using different instance names.
+    uM: "layout( binding=0 column_major std140) uniform block{layout( column_major std140 offset=0) uniform highp 4X4 matrix of float uProj, layout( column_major std140 offset=64) uniform highp 4X4 matrix of float uWorld}" versus uMatrix: "layout( binding=0 column_major std140) uniform block{layout( column_major std140 offset=0) uniform highp 4X4 matrix of float uProj, layout( column_major std140 offset=64) uniform highp 4X4 matrix of float uWorld}"
+WARNING: Linking vertex stage: Matched shader interfaces are using different instance names.
+    oV: " out block{ out highp 4-component vector of float v1,  out highp 4-component vector of float v2}" versus anon@0: " out block{ out highp 4-component vector of float v1,  out highp 4-component vector of float v2}"
+
+Shader version: 430
+0:? Sequence
+0:43  Function Definition: main( ( global void)
+0:43    Function Parameters: 
+0:45    Sequence
+0:45      move second child to first child ( temp highp 4-component vector of float)
+0:45        'oColor' ( smooth out highp 4-component vector of float)
+0:45        component-wise multiply ( temp highp 4-component vector of float)
+0:45          component-wise multiply ( temp highp 4-component vector of float)
+0:45            color1: direct index for structure (layout( column_major std140 offset=0) uniform highp 4-component vector of float)
+0:45              'uC' (layout( binding=1 column_major std140) uniform block{layout( column_major std140 offset=0) uniform highp 4-component vector of float color1, layout( column_major std140 offset=16) uniform bool b, layout( column_major std140 offset=32) uniform highp 4-component vector of float color2, layout( column_major std140 offset=48) uniform highp 4-component vector of float color3})
+0:45              Constant:
+0:45                0 (const int)
+0:45            Function Call: getColor2( ( global highp 4-component vector of float)
+0:45          c: direct index for structure (layout( column_major std430 offset=0) buffer highp 4-component vector of float)
+0:45            'uColorBuf' (layout( binding=0 column_major std430) buffer block{layout( column_major std430 offset=0) buffer highp 4-component vector of float c})
+0:45            Constant:
+0:45              0 (const int)
+0:46      move second child to first child ( temp highp 4-component vector of float)
+0:46        v1: direct index for structure ( out highp 4-component vector of float)
+0:46          'oV' ( out block{ out highp 4-component vector of float v1,  out highp 4-component vector of float v2})
+0:46          Constant:
+0:46            0 (const int)
+0:46        color1: direct index for structure (layout( column_major std140 offset=0) uniform highp 4-component vector of float)
+0:46          'uC' (layout( binding=1 column_major std140) uniform block{layout( column_major std140 offset=0) uniform highp 4-component vector of float color1, layout( column_major std140 offset=16) uniform bool b, layout( column_major std140 offset=32) uniform highp 4-component vector of float color2, layout( column_major std140 offset=48) uniform highp 4-component vector of float color3})
+0:46          Constant:
+0:46            0 (const int)
+0:48      move second child to first child ( temp highp 4-component vector of float)
+0:48        gl_Position: direct index for structure ( gl_Position highp 4-component vector of float Position)
+0:48          'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out 1-element array of float ClipDistance gl_ClipDistance})
+0:48          Constant:
+0:48            0 (const uint)
+0:48        matrix-times-vector ( temp highp 4-component vector of float)
+0:48          uProj: direct index for structure (layout( column_major std140 offset=0) uniform highp 4X4 matrix of float)
+0:48            'uM' (layout( binding=0 column_major std140) uniform block{layout( column_major std140 offset=0) uniform highp 4X4 matrix of float uProj, layout( column_major std140 offset=64) uniform highp 4X4 matrix of float uWorld})
+0:48            Constant:
+0:48              0 (const int)
+0:48          Function Call: getWorld( ( global highp 4-component vector of float)
+0:36  Function Definition: getColor2( ( global highp 4-component vector of float)
+0:36    Function Parameters: 
+0:38    Sequence
+0:38      Branch: Return with expression
+0:38        color2: direct index for structure (layout( column_major std140 offset=32) uniform highp 4-component vector of float)
+0:38          'uColor' (layout( binding=1 column_major std140) uniform block{layout( column_major std140 offset=0) uniform highp 4-component vector of float color1, layout( column_major std140 offset=16) uniform bool b, layout( column_major std140 offset=32) uniform highp 4-component vector of float color2, layout( column_major std140 offset=48) uniform highp 4-component vector of float color3})
+0:38          Constant:
+0:38            2 (const int)
+0:41  Function Definition: getWorld( ( global highp 4-component vector of float)
+0:41    Function Parameters: 
+0:43    Sequence
+0:43      move second child to first child ( temp highp 4-component vector of float)
+0:43        v1: direct index for structure ( out highp 4-component vector of float)
+0:43          'anon@0' ( out block{ out highp 4-component vector of float v1,  out highp 4-component vector of float v2})
+0:43          Constant:
+0:43            0 (const uint)
+0:43        Constant:
+0:43          1.000000
+0:43          1.000000
+0:43          1.000000
+0:43          1.000000
+0:44      Branch: Return with expression
+0:44        matrix-times-vector ( temp highp 4-component vector of float)
+0:44          uWorld: direct index for structure (layout( column_major std140 offset=64) uniform highp 4X4 matrix of float)
+0:44            'uMatrix' (layout( binding=0 column_major std140) uniform block{layout( column_major std140 offset=0) uniform highp 4X4 matrix of float uProj, layout( column_major std140 offset=64) uniform highp 4X4 matrix of float uWorld})
+0:44            Constant:
+0:44              1 (const int)
+0:44          'P' ( in highp 4-component vector of float)
+0:?   Linker Objects
+0:?     'uM' (layout( binding=0 column_major std140) uniform block{layout( column_major std140 offset=0) uniform highp 4X4 matrix of float uProj, layout( column_major std140 offset=64) uniform highp 4X4 matrix of float uWorld})
+0:?     'oV' ( out block{ out highp 4-component vector of float v1,  out highp 4-component vector of float v2})
+0:?     'uC' (layout( binding=1 column_major std140) uniform block{layout( column_major std140 offset=0) uniform highp 4-component vector of float color1, layout( column_major std140 offset=16) uniform bool b, layout( column_major std140 offset=32) uniform highp 4-component vector of float color2, layout( column_major std140 offset=48) uniform highp 4-component vector of float color3})
+0:?     'uBuf' (layout( binding=1 column_major std430) buffer block{layout( column_major std430 offset=0) buffer highp 4X4 matrix of float p})
+0:?     'uColorBuf' (layout( binding=0 column_major std430) buffer block{layout( column_major std430 offset=0) buffer highp 4-component vector of float c})
+0:?     'oColor' ( smooth out highp 4-component vector of float)
+0:?     'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out 1-element array of float ClipDistance gl_ClipDistance})
+0:?     'P' ( in highp 4-component vector of float)
+
+// Module Version 10000
+// Generated by (magic number): 80008
+// Id's are bound by 73
+
+                              Capability Shader
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Vertex 4  "main" 14 34 42 65
+                              Source GLSL 430
+                              Name 4  "main"
+                              Name 9  "getColor2("
+                              Name 11  "getWorld("
+                              Name 14  "oColor"
+                              Name 16  "ColorBlock"
+                              MemberName 16(ColorBlock) 0  "color1"
+                              MemberName 16(ColorBlock) 1  "b"
+                              MemberName 16(ColorBlock) 2  "color2"
+                              MemberName 16(ColorBlock) 3  "color3"
+                              Name 18  "uC"
+                              Name 26  "SecondaryColorBlock"
+                              MemberName 26(SecondaryColorBlock) 0  "c"
+                              Name 28  "uColorBuf"
+                              Name 32  "Vertex"
+                              MemberName 32(Vertex) 0  "v1"
+                              MemberName 32(Vertex) 1  "v2"
+                              Name 34  "oV"
+                              Name 40  "gl_PerVertex"
+                              MemberName 40(gl_PerVertex) 0  "gl_Position"
+                              MemberName 40(gl_PerVertex) 1  "gl_PointSize"
+                              MemberName 40(gl_PerVertex) 2  "gl_ClipDistance"
+                              Name 42  ""
+                              Name 44  "MatrixBlock"
+                              MemberName 44(MatrixBlock) 0  "uProj"
+                              MemberName 44(MatrixBlock) 1  "uWorld"
+                              Name 46  "uM"
+                              Name 65  "P"
+                              Name 70  "BufferBlock"
+                              MemberName 70(BufferBlock) 0  "p"
+                              Name 72  "uBuf"
+                              MemberDecorate 16(ColorBlock) 0 Offset 0
+                              MemberDecorate 16(ColorBlock) 1 Offset 16
+                              MemberDecorate 16(ColorBlock) 2 Offset 32
+                              MemberDecorate 16(ColorBlock) 3 Offset 48
+                              Decorate 16(ColorBlock) Block
+                              Decorate 18(uC) DescriptorSet 0
+                              Decorate 18(uC) Binding 1
+                              MemberDecorate 26(SecondaryColorBlock) 0 Offset 0
+                              Decorate 26(SecondaryColorBlock) BufferBlock
+                              Decorate 28(uColorBuf) DescriptorSet 0
+                              Decorate 28(uColorBuf) Binding 0
+                              Decorate 32(Vertex) Block
+                              MemberDecorate 40(gl_PerVertex) 0 BuiltIn Position
+                              MemberDecorate 40(gl_PerVertex) 1 BuiltIn PointSize
+                              MemberDecorate 40(gl_PerVertex) 2 BuiltIn ClipDistance
+                              Decorate 40(gl_PerVertex) Block
+                              MemberDecorate 44(MatrixBlock) 0 ColMajor
+                              MemberDecorate 44(MatrixBlock) 0 Offset 0
+                              MemberDecorate 44(MatrixBlock) 0 MatrixStride 16
+                              MemberDecorate 44(MatrixBlock) 1 ColMajor
+                              MemberDecorate 44(MatrixBlock) 1 Offset 64
+                              MemberDecorate 44(MatrixBlock) 1 MatrixStride 16
+                              Decorate 44(MatrixBlock) Block
+                              Decorate 46(uM) DescriptorSet 0
+                              Decorate 46(uM) Binding 0
+                              MemberDecorate 70(BufferBlock) 0 ColMajor
+                              MemberDecorate 70(BufferBlock) 0 Offset 0
+                              MemberDecorate 70(BufferBlock) 0 MatrixStride 16
+                              Decorate 70(BufferBlock) BufferBlock
+                              Decorate 72(uBuf) DescriptorSet 0
+                              Decorate 72(uBuf) Binding 1
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypeVector 6(float) 4
+               8:             TypeFunction 7(fvec4)
+              13:             TypePointer Output 7(fvec4)
+      14(oColor):     13(ptr) Variable Output
+              15:             TypeInt 32 0
+  16(ColorBlock):             TypeStruct 7(fvec4) 15(int) 7(fvec4) 7(fvec4)
+              17:             TypePointer Uniform 16(ColorBlock)
+          18(uC):     17(ptr) Variable Uniform
+              19:             TypeInt 32 1
+              20:     19(int) Constant 0
+              21:             TypePointer Uniform 7(fvec4)
+26(SecondaryColorBlock):             TypeStruct 7(fvec4)
+              27:             TypePointer Uniform 26(SecondaryColorBlock)
+   28(uColorBuf):     27(ptr) Variable Uniform
+      32(Vertex):             TypeStruct 7(fvec4) 7(fvec4)
+              33:             TypePointer Output 32(Vertex)
+          34(oV):     33(ptr) Variable Output
+              38:     15(int) Constant 1
+              39:             TypeArray 6(float) 38
+40(gl_PerVertex):             TypeStruct 7(fvec4) 6(float) 39
+              41:             TypePointer Output 40(gl_PerVertex)
+              42:     41(ptr) Variable Output
+              43:             TypeMatrix 7(fvec4) 4
+ 44(MatrixBlock):             TypeStruct 43 43
+              45:             TypePointer Uniform 44(MatrixBlock)
+          46(uM):     45(ptr) Variable Uniform
+              47:             TypePointer Uniform 43
+              53:     19(int) Constant 2
+              58:    6(float) Constant 1065353216
+              59:    7(fvec4) ConstantComposite 58 58 58 58
+              61:     19(int) Constant 1
+              64:             TypePointer Input 7(fvec4)
+           65(P):     64(ptr) Variable Input
+ 70(BufferBlock):             TypeStruct 43
+              71:             TypePointer Uniform 70(BufferBlock)
+        72(uBuf):     71(ptr) Variable Uniform
+         4(main):           2 Function None 3
+               5:             Label
+              22:     21(ptr) AccessChain 18(uC) 20
+              23:    7(fvec4) Load 22
+              24:    7(fvec4) FunctionCall 9(getColor2()
+              25:    7(fvec4) FMul 23 24
+              29:     21(ptr) AccessChain 28(uColorBuf) 20
+              30:    7(fvec4) Load 29
+              31:    7(fvec4) FMul 25 30
+                              Store 14(oColor) 31
+              35:     21(ptr) AccessChain 18(uC) 20
+              36:    7(fvec4) Load 35
+              37:     13(ptr) AccessChain 34(oV) 20
+                              Store 37 36
+              48:     47(ptr) AccessChain 46(uM) 20
+              49:          43 Load 48
+              50:    7(fvec4) FunctionCall 11(getWorld()
+              51:    7(fvec4) MatrixTimesVector 49 50
+              52:     13(ptr) AccessChain 42 20
+                              Store 52 51
+                              Return
+                              FunctionEnd
+   9(getColor2():    7(fvec4) Function None 8
+              10:             Label
+              54:     21(ptr) AccessChain 18(uC) 53
+              55:    7(fvec4) Load 54
+                              ReturnValue 55
+                              FunctionEnd
+   11(getWorld():    7(fvec4) Function None 8
+              12:             Label
+              60:     13(ptr) AccessChain 34(oV) 20
+                              Store 60 59
+              62:     47(ptr) AccessChain 46(uM) 61
+              63:          43 Load 62
+              66:    7(fvec4) Load 65(P)
+              67:    7(fvec4) MatrixTimesVector 63 66
+                              ReturnValue 67
+                              FunctionEnd
diff --git a/third_party/glslang/src/Test/baseResults/link.vk.multiBlocksValid.1.0.geom.out b/third_party/glslang/src/Test/baseResults/link.vk.multiBlocksValid.1.0.geom.out
new file mode 100755
index 0000000..413da7e
--- /dev/null
+++ b/third_party/glslang/src/Test/baseResults/link.vk.multiBlocksValid.1.0.geom.out
@@ -0,0 +1,451 @@
+link.vk.multiBlocksValid.1.0.geom
+Shader version: 430
+invocations = -1
+max_vertices = 3
+input primitive = triangles
+output primitive = triangle_strip
+0:? Sequence
+0:48  Function Definition: main( ( global void)
+0:48    Function Parameters: 
+0:50    Sequence
+0:50      move second child to first child ( temp highp 4-component vector of float)
+0:50        'oColor' (layout( stream=0) out highp 4-component vector of float)
+0:50        component-wise multiply ( temp highp 4-component vector of float)
+0:50          color1: direct index for structure (layout( column_major std140 offset=0) uniform highp 4-component vector of float)
+0:50            'uC' (layout( binding=1 column_major std140) uniform block{layout( column_major std140 offset=0) uniform highp 4-component vector of float color1, layout( column_major std140 offset=16) uniform bool b, layout( column_major std140 offset=32) uniform highp 4-component vector of float color2, layout( column_major std140 offset=48) uniform highp 4-component vector of float color3})
+0:50            Constant:
+0:50              0 (const int)
+0:50          Function Call: getColor2( ( global highp 4-component vector of float)
+0:52      move second child to first child ( temp highp float)
+0:52        'globalF' ( global highp float)
+0:52        Constant:
+0:52          1.000000
+0:54      Sequence
+0:54        Sequence
+0:54          move second child to first child ( temp highp int)
+0:54            'i' ( temp highp int)
+0:54            Constant:
+0:54              0 (const int)
+0:54        Loop with condition tested first
+0:54          Loop Condition
+0:54          Compare Less Than ( temp bool)
+0:54            'i' ( temp highp int)
+0:54            Constant:
+0:54              3 (const int)
+0:54          Loop Body
+0:56          Sequence
+0:56            move second child to first child ( temp highp 4-component vector of float)
+0:56              gl_Position: direct index for structure (layout( stream=0) gl_Position highp 4-component vector of float Position)
+0:56                'anon@0' (layout( stream=0) out block{layout( stream=0) gl_Position 4-component vector of float Position gl_Position, layout( stream=0) gl_PointSize float PointSize gl_PointSize, layout( stream=0) out unsized 1-element array of float ClipDistance gl_ClipDistance})
+0:56                Constant:
+0:56                  0 (const uint)
+0:56              matrix-times-vector ( temp highp 4-component vector of float)
+0:56                uProj: direct index for structure (layout( column_major std140 offset=0) uniform highp 4X4 matrix of float)
+0:56                  'uM' (layout( binding=0 column_major std140) uniform block{layout( column_major std140 offset=0) uniform highp 4X4 matrix of float uProj, layout( column_major std140 offset=64) uniform highp 4X4 matrix of float uWorld})
+0:56                  Constant:
+0:56                    0 (const int)
+0:56                Function Call: getWorld(i1; ( global highp 4-component vector of float)
+0:56                  'i' ( temp highp int)
+0:57            move second child to first child ( temp highp 4-component vector of float)
+0:57              val1: direct index for structure (layout( stream=0) out highp 4-component vector of float)
+0:57                'oV' (layout( stream=0) out block{layout( stream=0) out highp 4-component vector of float val1})
+0:57                Constant:
+0:57                  0 (const int)
+0:57              add ( temp highp 4-component vector of float)
+0:57                color1: direct index for structure (layout( column_major std140 offset=0) uniform highp 4-component vector of float)
+0:57                  'uC' (layout( binding=1 column_major std140) uniform block{layout( column_major std140 offset=0) uniform highp 4-component vector of float color1, layout( column_major std140 offset=16) uniform bool b, layout( column_major std140 offset=32) uniform highp 4-component vector of float color2, layout( column_major std140 offset=48) uniform highp 4-component vector of float color3})
+0:57                  Constant:
+0:57                    0 (const int)
+0:57                vector-scale ( temp highp 4-component vector of float)
+0:57                  v2: direct index for structure ( in highp 4-component vector of float)
+0:57                    indirect index ( temp block{ in highp 4-component vector of float v1,  in highp 4-component vector of float v2})
+0:57                      'iV' ( in 3-element array of block{ in highp 4-component vector of float v1,  in highp 4-component vector of float v2})
+0:57                      'i' ( temp highp int)
+0:57                    Constant:
+0:57                      1 (const int)
+0:57                  'globalF' ( global highp float)
+0:58            EmitVertex ( global void)
+0:54          Loop Terminal Expression
+0:54          Post-Increment ( temp highp int)
+0:54            'i' ( temp highp int)
+0:61      EndPrimitive ( global void)
+0:?   Linker Objects
+0:?     'uM' (layout( binding=0 column_major std140) uniform block{layout( column_major std140 offset=0) uniform highp 4X4 matrix of float uProj, layout( column_major std140 offset=64) uniform highp 4X4 matrix of float uWorld})
+0:?     'iV' ( in 3-element array of block{ in highp 4-component vector of float v1,  in highp 4-component vector of float v2})
+0:?     'oV' (layout( stream=0) out block{layout( stream=0) out highp 4-component vector of float val1})
+0:?     'uC' (layout( binding=1 column_major std140) uniform block{layout( column_major std140 offset=0) uniform highp 4-component vector of float color1, layout( column_major std140 offset=16) uniform bool b, layout( column_major std140 offset=32) uniform highp 4-component vector of float color2, layout( column_major std140 offset=48) uniform highp 4-component vector of float color3})
+0:?     'uBuf' (layout( binding=1 column_major std430) buffer block{layout( column_major std430 offset=0) buffer highp 4X4 matrix of float p})
+0:?     'oColor' (layout( stream=0) out highp 4-component vector of float)
+0:?     'globalF' ( global highp float)
+0:?     'anon@0' (layout( stream=0) out block{layout( stream=0) gl_Position 4-component vector of float Position gl_Position, layout( stream=0) gl_PointSize float PointSize gl_PointSize, layout( stream=0) out unsized 1-element array of float ClipDistance gl_ClipDistance})
+
+link.vk.multiBlocksValid.1.1.geom
+Shader version: 430
+invocations = -1
+max_vertices = 3
+input primitive = triangles
+output primitive = triangle_strip
+0:? Sequence
+0:44  Function Definition: getColor2( ( global highp 4-component vector of float)
+0:44    Function Parameters: 
+0:46    Sequence
+0:46      Branch: Return with expression
+0:46        color2: direct index for structure (layout( column_major std140 offset=32) uniform highp 4-component vector of float)
+0:46          'uColor' (layout( binding=1 column_major std140) uniform block{layout( column_major std140 offset=0) uniform highp 4-component vector of float color1, layout( column_major std140 offset=16) uniform bool b, layout( column_major std140 offset=32) uniform highp 4-component vector of float color2, layout( column_major std140 offset=48) uniform highp 4-component vector of float color3})
+0:46          Constant:
+0:46            2 (const int)
+0:49  Function Definition: getWorld(i1; ( global highp 4-component vector of float)
+0:49    Function Parameters: 
+0:49      'i' ( in highp int)
+0:51    Sequence
+0:51      move second child to first child ( temp highp 4-component vector of float)
+0:51        val1: direct index for structure (layout( stream=0) out highp 4-component vector of float)
+0:51          'anon@0' (layout( stream=0) out block{layout( stream=0) out highp 4-component vector of float val1})
+0:51          Constant:
+0:51            0 (const uint)
+0:51        Constant:
+0:51          1.000000
+0:51          1.000000
+0:51          1.000000
+0:51          1.000000
+0:52      Branch: Return with expression
+0:52        matrix-times-vector ( temp highp 4-component vector of float)
+0:52          uWorld: direct index for structure (layout( column_major std140 offset=64) uniform highp 4X4 matrix of float)
+0:52            'uMatrix' (layout( binding=0 column_major std140) uniform block{layout( column_major std140 offset=0) uniform highp 4X4 matrix of float uProj, layout( column_major std140 offset=64) uniform highp 4X4 matrix of float uWorld})
+0:52            Constant:
+0:52              1 (const int)
+0:52          v1: direct index for structure ( in highp 4-component vector of float)
+0:52            indirect index ( temp block{ in highp 4-component vector of float v1,  in highp 4-component vector of float v2})
+0:52              'iVV' ( in 3-element array of block{ in highp 4-component vector of float v1,  in highp 4-component vector of float v2})
+0:52              'i' ( in highp int)
+0:52            Constant:
+0:52              0 (const int)
+0:?   Linker Objects
+0:?     'uColor' (layout( binding=1 column_major std140) uniform block{layout( column_major std140 offset=0) uniform highp 4-component vector of float color1, layout( column_major std140 offset=16) uniform bool b, layout( column_major std140 offset=32) uniform highp 4-component vector of float color2, layout( column_major std140 offset=48) uniform highp 4-component vector of float color3})
+0:?     'uBuffer' (layout( binding=1 column_major std430) buffer block{layout( column_major std430 offset=0) buffer highp 4X4 matrix of float p})
+0:?     'uMatrix' (layout( binding=0 column_major std140) uniform block{layout( column_major std140 offset=0) uniform highp 4X4 matrix of float uProj, layout( column_major std140 offset=64) uniform highp 4X4 matrix of float uWorld})
+0:?     'anon@0' (layout( stream=0) out block{layout( stream=0) out highp 4-component vector of float val1})
+0:?     'iVV' ( in 3-element array of block{ in highp 4-component vector of float v1,  in highp 4-component vector of float v2})
+0:?     'P' ( in 3-element array of highp 4-component vector of float)
+
+
+Linked geometry stage:
+
+WARNING: Linking geometry stage: Matched shader interfaces are using different instance names.
+    uC: "layout( binding=1 column_major std140) uniform block{layout( column_major std140 offset=0) uniform highp 4-component vector of float color1, layout( column_major std140 offset=16) uniform bool b, layout( column_major std140 offset=32) uniform highp 4-component vector of float color2, layout( column_major std140 offset=48) uniform highp 4-component vector of float color3}" versus uColor: "layout( binding=1 column_major std140) uniform block{layout( column_major std140 offset=0) uniform highp 4-component vector of float color1, layout( column_major std140 offset=16) uniform bool b, layout( column_major std140 offset=32) uniform highp 4-component vector of float color2, layout( column_major std140 offset=48) uniform highp 4-component vector of float color3}"
+WARNING: Linking geometry stage: Matched shader interfaces are using different instance names.
+    uBuf: "layout( binding=1 column_major std430) buffer block{layout( column_major std430 offset=0) buffer highp 4X4 matrix of float p}" versus uBuffer: "layout( binding=1 column_major std430) buffer block{layout( column_major std430 offset=0) buffer highp 4X4 matrix of float p}"
+WARNING: Linking geometry stage: Matched shader interfaces are using different instance names.
+    uM: "layout( binding=0 column_major std140) uniform block{layout( column_major std140 offset=0) uniform highp 4X4 matrix of float uProj, layout( column_major std140 offset=64) uniform highp 4X4 matrix of float uWorld}" versus uMatrix: "layout( binding=0 column_major std140) uniform block{layout( column_major std140 offset=0) uniform highp 4X4 matrix of float uProj, layout( column_major std140 offset=64) uniform highp 4X4 matrix of float uWorld}"
+WARNING: Linking geometry stage: Matched shader interfaces are using different instance names.
+    oV: "layout( stream=0) out block{layout( stream=0) out highp 4-component vector of float val1}" versus anon@0: "layout( stream=0) out block{layout( stream=0) out highp 4-component vector of float val1}"
+WARNING: Linking geometry stage: Matched shader interfaces are using different instance names.
+    iV: " in 3-element array of block{ in highp 4-component vector of float v1,  in highp 4-component vector of float v2}" versus iVV: " in 3-element array of block{ in highp 4-component vector of float v1,  in highp 4-component vector of float v2}"
+
+Shader version: 430
+invocations = 1
+max_vertices = 3
+input primitive = triangles
+output primitive = triangle_strip
+0:? Sequence
+0:48  Function Definition: main( ( global void)
+0:48    Function Parameters: 
+0:50    Sequence
+0:50      move second child to first child ( temp highp 4-component vector of float)
+0:50        'oColor' (layout( stream=0) out highp 4-component vector of float)
+0:50        component-wise multiply ( temp highp 4-component vector of float)
+0:50          color1: direct index for structure (layout( column_major std140 offset=0) uniform highp 4-component vector of float)
+0:50            'uC' (layout( binding=1 column_major std140) uniform block{layout( column_major std140 offset=0) uniform highp 4-component vector of float color1, layout( column_major std140 offset=16) uniform bool b, layout( column_major std140 offset=32) uniform highp 4-component vector of float color2, layout( column_major std140 offset=48) uniform highp 4-component vector of float color3})
+0:50            Constant:
+0:50              0 (const int)
+0:50          Function Call: getColor2( ( global highp 4-component vector of float)
+0:52      move second child to first child ( temp highp float)
+0:52        'globalF' ( global highp float)
+0:52        Constant:
+0:52          1.000000
+0:54      Sequence
+0:54        Sequence
+0:54          move second child to first child ( temp highp int)
+0:54            'i' ( temp highp int)
+0:54            Constant:
+0:54              0 (const int)
+0:54        Loop with condition tested first
+0:54          Loop Condition
+0:54          Compare Less Than ( temp bool)
+0:54            'i' ( temp highp int)
+0:54            Constant:
+0:54              3 (const int)
+0:54          Loop Body
+0:56          Sequence
+0:56            move second child to first child ( temp highp 4-component vector of float)
+0:56              gl_Position: direct index for structure (layout( stream=0) gl_Position highp 4-component vector of float Position)
+0:56                'anon@0' (layout( stream=0) out block{layout( stream=0) gl_Position 4-component vector of float Position gl_Position, layout( stream=0) gl_PointSize float PointSize gl_PointSize, layout( stream=0) out 1-element array of float ClipDistance gl_ClipDistance})
+0:56                Constant:
+0:56                  0 (const uint)
+0:56              matrix-times-vector ( temp highp 4-component vector of float)
+0:56                uProj: direct index for structure (layout( column_major std140 offset=0) uniform highp 4X4 matrix of float)
+0:56                  'uM' (layout( binding=0 column_major std140) uniform block{layout( column_major std140 offset=0) uniform highp 4X4 matrix of float uProj, layout( column_major std140 offset=64) uniform highp 4X4 matrix of float uWorld})
+0:56                  Constant:
+0:56                    0 (const int)
+0:56                Function Call: getWorld(i1; ( global highp 4-component vector of float)
+0:56                  'i' ( temp highp int)
+0:57            move second child to first child ( temp highp 4-component vector of float)
+0:57              val1: direct index for structure (layout( stream=0) out highp 4-component vector of float)
+0:57                'oV' (layout( stream=0) out block{layout( stream=0) out highp 4-component vector of float val1})
+0:57                Constant:
+0:57                  0 (const int)
+0:57              add ( temp highp 4-component vector of float)
+0:57                color1: direct index for structure (layout( column_major std140 offset=0) uniform highp 4-component vector of float)
+0:57                  'uC' (layout( binding=1 column_major std140) uniform block{layout( column_major std140 offset=0) uniform highp 4-component vector of float color1, layout( column_major std140 offset=16) uniform bool b, layout( column_major std140 offset=32) uniform highp 4-component vector of float color2, layout( column_major std140 offset=48) uniform highp 4-component vector of float color3})
+0:57                  Constant:
+0:57                    0 (const int)
+0:57                vector-scale ( temp highp 4-component vector of float)
+0:57                  v2: direct index for structure ( in highp 4-component vector of float)
+0:57                    indirect index ( temp block{ in highp 4-component vector of float v1,  in highp 4-component vector of float v2})
+0:57                      'iV' ( in 3-element array of block{ in highp 4-component vector of float v1,  in highp 4-component vector of float v2})
+0:57                      'i' ( temp highp int)
+0:57                    Constant:
+0:57                      1 (const int)
+0:57                  'globalF' ( global highp float)
+0:58            EmitVertex ( global void)
+0:54          Loop Terminal Expression
+0:54          Post-Increment ( temp highp int)
+0:54            'i' ( temp highp int)
+0:61      EndPrimitive ( global void)
+0:44  Function Definition: getColor2( ( global highp 4-component vector of float)
+0:44    Function Parameters: 
+0:46    Sequence
+0:46      Branch: Return with expression
+0:46        color2: direct index for structure (layout( column_major std140 offset=32) uniform highp 4-component vector of float)
+0:46          'uColor' (layout( binding=1 column_major std140) uniform block{layout( column_major std140 offset=0) uniform highp 4-component vector of float color1, layout( column_major std140 offset=16) uniform bool b, layout( column_major std140 offset=32) uniform highp 4-component vector of float color2, layout( column_major std140 offset=48) uniform highp 4-component vector of float color3})
+0:46          Constant:
+0:46            2 (const int)
+0:49  Function Definition: getWorld(i1; ( global highp 4-component vector of float)
+0:49    Function Parameters: 
+0:49      'i' ( in highp int)
+0:51    Sequence
+0:51      move second child to first child ( temp highp 4-component vector of float)
+0:51        val1: direct index for structure (layout( stream=0) out highp 4-component vector of float)
+0:51          'anon@0' (layout( stream=0) out block{layout( stream=0) out highp 4-component vector of float val1})
+0:51          Constant:
+0:51            0 (const uint)
+0:51        Constant:
+0:51          1.000000
+0:51          1.000000
+0:51          1.000000
+0:51          1.000000
+0:52      Branch: Return with expression
+0:52        matrix-times-vector ( temp highp 4-component vector of float)
+0:52          uWorld: direct index for structure (layout( column_major std140 offset=64) uniform highp 4X4 matrix of float)
+0:52            'uMatrix' (layout( binding=0 column_major std140) uniform block{layout( column_major std140 offset=0) uniform highp 4X4 matrix of float uProj, layout( column_major std140 offset=64) uniform highp 4X4 matrix of float uWorld})
+0:52            Constant:
+0:52              1 (const int)
+0:52          v1: direct index for structure ( in highp 4-component vector of float)
+0:52            indirect index ( temp block{ in highp 4-component vector of float v1,  in highp 4-component vector of float v2})
+0:52              'iVV' ( in 3-element array of block{ in highp 4-component vector of float v1,  in highp 4-component vector of float v2})
+0:52              'i' ( in highp int)
+0:52            Constant:
+0:52              0 (const int)
+0:?   Linker Objects
+0:?     'uM' (layout( binding=0 column_major std140) uniform block{layout( column_major std140 offset=0) uniform highp 4X4 matrix of float uProj, layout( column_major std140 offset=64) uniform highp 4X4 matrix of float uWorld})
+0:?     'iV' ( in 3-element array of block{ in highp 4-component vector of float v1,  in highp 4-component vector of float v2})
+0:?     'oV' (layout( stream=0) out block{layout( stream=0) out highp 4-component vector of float val1})
+0:?     'uC' (layout( binding=1 column_major std140) uniform block{layout( column_major std140 offset=0) uniform highp 4-component vector of float color1, layout( column_major std140 offset=16) uniform bool b, layout( column_major std140 offset=32) uniform highp 4-component vector of float color2, layout( column_major std140 offset=48) uniform highp 4-component vector of float color3})
+0:?     'uBuf' (layout( binding=1 column_major std430) buffer block{layout( column_major std430 offset=0) buffer highp 4X4 matrix of float p})
+0:?     'oColor' (layout( stream=0) out highp 4-component vector of float)
+0:?     'globalF' ( global highp float)
+0:?     'anon@0' (layout( stream=0) out block{layout( stream=0) gl_Position 4-component vector of float Position gl_Position, layout( stream=0) gl_PointSize float PointSize gl_PointSize, layout( stream=0) out 1-element array of float ClipDistance gl_ClipDistance})
+0:?     'P' ( in 3-element array of highp 4-component vector of float)
+
+// Module Version 10000
+// Generated by (magic number): 80008
+// Id's are bound by 101
+
+                              Capability Geometry
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Geometry 4  "main" 18 46 61 68 100
+                              ExecutionMode 4 Triangles
+                              ExecutionMode 4 Invocations 1
+                              ExecutionMode 4 OutputTriangleStrip
+                              ExecutionMode 4 OutputVertices 3
+                              Source GLSL 430
+                              Name 4  "main"
+                              Name 9  "getColor2("
+                              Name 15  "getWorld(i1;"
+                              Name 14  "i"
+                              Name 18  "oColor"
+                              Name 20  "ColorBlock"
+                              MemberName 20(ColorBlock) 0  "color1"
+                              MemberName 20(ColorBlock) 1  "b"
+                              MemberName 20(ColorBlock) 2  "color2"
+                              MemberName 20(ColorBlock) 3  "color3"
+                              Name 22  "uC"
+                              Name 30  "globalF"
+                              Name 32  "i"
+                              Name 44  "gl_PerVertex"
+                              MemberName 44(gl_PerVertex) 0  "gl_Position"
+                              MemberName 44(gl_PerVertex) 1  "gl_PointSize"
+                              MemberName 44(gl_PerVertex) 2  "gl_ClipDistance"
+                              Name 46  ""
+                              Name 48  "MatrixBlock"
+                              MemberName 48(MatrixBlock) 0  "uProj"
+                              MemberName 48(MatrixBlock) 1  "uWorld"
+                              Name 50  "uM"
+                              Name 54  "param"
+                              Name 59  "Vertex"
+                              MemberName 59(Vertex) 0  "val1"
+                              Name 61  "oV"
+                              Name 64  "Vertex"
+                              MemberName 64(Vertex) 0  "v1"
+                              MemberName 64(Vertex) 1  "v2"
+                              Name 68  "iV"
+                              Name 95  "BufferBlock"
+                              MemberName 95(BufferBlock) 0  "p"
+                              Name 97  "uBuf"
+                              Name 100  "P"
+                              MemberDecorate 20(ColorBlock) 0 Offset 0
+                              MemberDecorate 20(ColorBlock) 1 Offset 16
+                              MemberDecorate 20(ColorBlock) 2 Offset 32
+                              MemberDecorate 20(ColorBlock) 3 Offset 48
+                              Decorate 20(ColorBlock) Block
+                              Decorate 22(uC) DescriptorSet 0
+                              Decorate 22(uC) Binding 1
+                              MemberDecorate 44(gl_PerVertex) 0 BuiltIn Position
+                              MemberDecorate 44(gl_PerVertex) 1 BuiltIn PointSize
+                              MemberDecorate 44(gl_PerVertex) 2 BuiltIn ClipDistance
+                              Decorate 44(gl_PerVertex) Block
+                              MemberDecorate 48(MatrixBlock) 0 ColMajor
+                              MemberDecorate 48(MatrixBlock) 0 Offset 0
+                              MemberDecorate 48(MatrixBlock) 0 MatrixStride 16
+                              MemberDecorate 48(MatrixBlock) 1 ColMajor
+                              MemberDecorate 48(MatrixBlock) 1 Offset 64
+                              MemberDecorate 48(MatrixBlock) 1 MatrixStride 16
+                              Decorate 48(MatrixBlock) Block
+                              Decorate 50(uM) DescriptorSet 0
+                              Decorate 50(uM) Binding 0
+                              Decorate 59(Vertex) Block
+                              Decorate 64(Vertex) Block
+                              MemberDecorate 95(BufferBlock) 0 ColMajor
+                              MemberDecorate 95(BufferBlock) 0 Offset 0
+                              MemberDecorate 95(BufferBlock) 0 MatrixStride 16
+                              Decorate 95(BufferBlock) BufferBlock
+                              Decorate 97(uBuf) DescriptorSet 0
+                              Decorate 97(uBuf) Binding 1
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypeVector 6(float) 4
+               8:             TypeFunction 7(fvec4)
+              11:             TypeInt 32 1
+              12:             TypePointer Function 11(int)
+              13:             TypeFunction 7(fvec4) 12(ptr)
+              17:             TypePointer Output 7(fvec4)
+      18(oColor):     17(ptr) Variable Output
+              19:             TypeInt 32 0
+  20(ColorBlock):             TypeStruct 7(fvec4) 19(int) 7(fvec4) 7(fvec4)
+              21:             TypePointer Uniform 20(ColorBlock)
+          22(uC):     21(ptr) Variable Uniform
+              23:     11(int) Constant 0
+              24:             TypePointer Uniform 7(fvec4)
+              29:             TypePointer Private 6(float)
+     30(globalF):     29(ptr) Variable Private
+              31:    6(float) Constant 1065353216
+              39:     11(int) Constant 3
+              40:             TypeBool
+              42:     19(int) Constant 1
+              43:             TypeArray 6(float) 42
+44(gl_PerVertex):             TypeStruct 7(fvec4) 6(float) 43
+              45:             TypePointer Output 44(gl_PerVertex)
+              46:     45(ptr) Variable Output
+              47:             TypeMatrix 7(fvec4) 4
+ 48(MatrixBlock):             TypeStruct 47 47
+              49:             TypePointer Uniform 48(MatrixBlock)
+          50(uM):     49(ptr) Variable Uniform
+              51:             TypePointer Uniform 47
+      59(Vertex):             TypeStruct 7(fvec4)
+              60:             TypePointer Output 59(Vertex)
+          61(oV):     60(ptr) Variable Output
+      64(Vertex):             TypeStruct 7(fvec4) 7(fvec4)
+              65:     19(int) Constant 3
+              66:             TypeArray 64(Vertex) 65
+              67:             TypePointer Input 66
+          68(iV):     67(ptr) Variable Input
+              70:     11(int) Constant 1
+              71:             TypePointer Input 7(fvec4)
+              80:     11(int) Constant 2
+              85:    7(fvec4) ConstantComposite 31 31 31 31
+ 95(BufferBlock):             TypeStruct 47
+              96:             TypePointer Uniform 95(BufferBlock)
+        97(uBuf):     96(ptr) Variable Uniform
+              98:             TypeArray 7(fvec4) 65
+              99:             TypePointer Input 98
+          100(P):     99(ptr) Variable Input
+         4(main):           2 Function None 3
+               5:             Label
+           32(i):     12(ptr) Variable Function
+       54(param):     12(ptr) Variable Function
+              25:     24(ptr) AccessChain 22(uC) 23
+              26:    7(fvec4) Load 25
+              27:    7(fvec4) FunctionCall 9(getColor2()
+              28:    7(fvec4) FMul 26 27
+                              Store 18(oColor) 28
+                              Store 30(globalF) 31
+                              Store 32(i) 23
+                              Branch 33
+              33:             Label
+                              LoopMerge 35 36 None
+                              Branch 37
+              37:             Label
+              38:     11(int) Load 32(i)
+              41:    40(bool) SLessThan 38 39
+                              BranchConditional 41 34 35
+              34:               Label
+              52:     51(ptr)   AccessChain 50(uM) 23
+              53:          47   Load 52
+              55:     11(int)   Load 32(i)
+                                Store 54(param) 55
+              56:    7(fvec4)   FunctionCall 15(getWorld(i1;) 54(param)
+              57:    7(fvec4)   MatrixTimesVector 53 56
+              58:     17(ptr)   AccessChain 46 23
+                                Store 58 57
+              62:     24(ptr)   AccessChain 22(uC) 23
+              63:    7(fvec4)   Load 62
+              69:     11(int)   Load 32(i)
+              72:     71(ptr)   AccessChain 68(iV) 69 70
+              73:    7(fvec4)   Load 72
+              74:    6(float)   Load 30(globalF)
+              75:    7(fvec4)   VectorTimesScalar 73 74
+              76:    7(fvec4)   FAdd 63 75
+              77:     17(ptr)   AccessChain 61(oV) 23
+                                Store 77 76
+                                EmitVertex
+                                Branch 36
+              36:               Label
+              78:     11(int)   Load 32(i)
+              79:     11(int)   IAdd 78 70
+                                Store 32(i) 79
+                                Branch 33
+              35:             Label
+                              EndPrimitive
+                              Return
+                              FunctionEnd
+   9(getColor2():    7(fvec4) Function None 8
+              10:             Label
+              81:     24(ptr) AccessChain 22(uC) 80
+              82:    7(fvec4) Load 81
+                              ReturnValue 82
+                              FunctionEnd
+15(getWorld(i1;):    7(fvec4) Function None 13
+           14(i):     12(ptr) FunctionParameter
+              16:             Label
+              86:     17(ptr) AccessChain 61(oV) 23
+                              Store 86 85
+              87:     51(ptr) AccessChain 50(uM) 70
+              88:          47 Load 87
+              89:     11(int) Load 14(i)
+              90:     71(ptr) AccessChain 68(iV) 89 23
+              91:    7(fvec4) Load 90
+              92:    7(fvec4) MatrixTimesVector 88 91
+                              ReturnValue 92
+                              FunctionEnd
diff --git a/third_party/glslang/src/Test/baseResults/link.vk.pcNamingInvalid.0.0.vert.out b/third_party/glslang/src/Test/baseResults/link.vk.pcNamingInvalid.0.0.vert.out
new file mode 100755
index 0000000..45f6a39
--- /dev/null
+++ b/third_party/glslang/src/Test/baseResults/link.vk.pcNamingInvalid.0.0.vert.out
@@ -0,0 +1,111 @@
+link.vk.pcNamingInvalid.0.0.vert
+Shader version: 450
+0:? Sequence
+0:16  Function Definition: main( ( global void)
+0:16    Function Parameters: 
+0:18    Sequence
+0:18      move second child to first child ( temp highp 4-component vector of float)
+0:18        'oColor' ( smooth out highp 4-component vector of float)
+0:18        component-wise multiply ( temp highp 4-component vector of float)
+0:18          color1: direct index for structure (layout( column_major std430 offset=128) uniform highp 4-component vector of float)
+0:18            'a' (layout( column_major std430 push_constant) uniform block{layout( column_major std430 offset=0) uniform highp 4X4 matrix of float uWorld, layout( column_major std430 offset=64) uniform highp 4X4 matrix of float uProj, layout( column_major std430 offset=128) uniform highp 4-component vector of float color1, layout( column_major std430 offset=144) uniform highp 4-component vector of float color2})
+0:18            Constant:
+0:18              2 (const int)
+0:18          Function Call: getColor2( ( global highp 4-component vector of float)
+0:20      move second child to first child ( temp highp 4-component vector of float)
+0:20        gl_Position: direct index for structure ( gl_Position highp 4-component vector of float Position)
+0:20          'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out unsized 1-element array of float ClipDistance gl_ClipDistance,  out unsized 1-element array of float CullDistance gl_CullDistance})
+0:20          Constant:
+0:20            0 (const uint)
+0:20        matrix-times-vector ( temp highp 4-component vector of float)
+0:20          uProj: direct index for structure (layout( column_major std430 offset=64) uniform highp 4X4 matrix of float)
+0:20            'a' (layout( column_major std430 push_constant) uniform block{layout( column_major std430 offset=0) uniform highp 4X4 matrix of float uWorld, layout( column_major std430 offset=64) uniform highp 4X4 matrix of float uProj, layout( column_major std430 offset=128) uniform highp 4-component vector of float color1, layout( column_major std430 offset=144) uniform highp 4-component vector of float color2})
+0:20            Constant:
+0:20              1 (const int)
+0:20          Function Call: getWorld( ( global highp 4-component vector of float)
+0:?   Linker Objects
+0:?     'a' (layout( column_major std430 push_constant) uniform block{layout( column_major std430 offset=0) uniform highp 4X4 matrix of float uWorld, layout( column_major std430 offset=64) uniform highp 4X4 matrix of float uProj, layout( column_major std430 offset=128) uniform highp 4-component vector of float color1, layout( column_major std430 offset=144) uniform highp 4-component vector of float color2})
+0:?     'oColor' ( smooth out highp 4-component vector of float)
+0:?     'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out unsized 1-element array of float ClipDistance gl_ClipDistance,  out unsized 1-element array of float CullDistance gl_CullDistance})
+
+link.vk.pcNamingInvalid.0.1.vert
+Shader version: 450
+0:? Sequence
+0:13  Function Definition: getColor2( ( global highp 4-component vector of float)
+0:13    Function Parameters: 
+0:15    Sequence
+0:15      Branch: Return with expression
+0:15        color2: direct index for structure (layout( column_major std430 offset=144) uniform highp 4-component vector of float)
+0:15          'a' (layout( column_major std430 push_constant) uniform block{layout( column_major std430 offset=0) uniform highp 4X4 matrix of float uWorld, layout( column_major std430 offset=64) uniform highp 4X4 matrix of float uProj, layout( column_major std430 offset=128) uniform highp 4-component vector of float color1, layout( column_major std430 offset=144) uniform highp 4-component vector of float color2})
+0:15          Constant:
+0:15            3 (const int)
+0:18  Function Definition: getWorld( ( global highp 4-component vector of float)
+0:18    Function Parameters: 
+0:20    Sequence
+0:20      Branch: Return with expression
+0:20        matrix-times-vector ( temp highp 4-component vector of float)
+0:20          uWorld: direct index for structure (layout( column_major std430 offset=0) uniform highp 4X4 matrix of float)
+0:20            'a' (layout( column_major std430 push_constant) uniform block{layout( column_major std430 offset=0) uniform highp 4X4 matrix of float uWorld, layout( column_major std430 offset=64) uniform highp 4X4 matrix of float uProj, layout( column_major std430 offset=128) uniform highp 4-component vector of float color1, layout( column_major std430 offset=144) uniform highp 4-component vector of float color2})
+0:20            Constant:
+0:20              0 (const int)
+0:20          'P' ( in highp 4-component vector of float)
+0:?   Linker Objects
+0:?     'a' (layout( column_major std430 push_constant) uniform block{layout( column_major std430 offset=0) uniform highp 4X4 matrix of float uWorld, layout( column_major std430 offset=64) uniform highp 4X4 matrix of float uProj, layout( column_major std430 offset=128) uniform highp 4-component vector of float color1, layout( column_major std430 offset=144) uniform highp 4-component vector of float color2})
+0:?     'P' ( in highp 4-component vector of float)
+
+
+Linked vertex stage:
+
+ERROR: Linking vertex stage: Only one push_constant block is allowed per stage
+
+Shader version: 450
+0:? Sequence
+0:16  Function Definition: main( ( global void)
+0:16    Function Parameters: 
+0:18    Sequence
+0:18      move second child to first child ( temp highp 4-component vector of float)
+0:18        'oColor' ( smooth out highp 4-component vector of float)
+0:18        component-wise multiply ( temp highp 4-component vector of float)
+0:18          color1: direct index for structure (layout( column_major std430 offset=128) uniform highp 4-component vector of float)
+0:18            'a' (layout( column_major std430 push_constant) uniform block{layout( column_major std430 offset=0) uniform highp 4X4 matrix of float uWorld, layout( column_major std430 offset=64) uniform highp 4X4 matrix of float uProj, layout( column_major std430 offset=128) uniform highp 4-component vector of float color1, layout( column_major std430 offset=144) uniform highp 4-component vector of float color2})
+0:18            Constant:
+0:18              2 (const int)
+0:18          Function Call: getColor2( ( global highp 4-component vector of float)
+0:20      move second child to first child ( temp highp 4-component vector of float)
+0:20        gl_Position: direct index for structure ( gl_Position highp 4-component vector of float Position)
+0:20          'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out 1-element array of float ClipDistance gl_ClipDistance,  out 1-element array of float CullDistance gl_CullDistance})
+0:20          Constant:
+0:20            0 (const uint)
+0:20        matrix-times-vector ( temp highp 4-component vector of float)
+0:20          uProj: direct index for structure (layout( column_major std430 offset=64) uniform highp 4X4 matrix of float)
+0:20            'a' (layout( column_major std430 push_constant) uniform block{layout( column_major std430 offset=0) uniform highp 4X4 matrix of float uWorld, layout( column_major std430 offset=64) uniform highp 4X4 matrix of float uProj, layout( column_major std430 offset=128) uniform highp 4-component vector of float color1, layout( column_major std430 offset=144) uniform highp 4-component vector of float color2})
+0:20            Constant:
+0:20              1 (const int)
+0:20          Function Call: getWorld( ( global highp 4-component vector of float)
+0:13  Function Definition: getColor2( ( global highp 4-component vector of float)
+0:13    Function Parameters: 
+0:15    Sequence
+0:15      Branch: Return with expression
+0:15        color2: direct index for structure (layout( column_major std430 offset=144) uniform highp 4-component vector of float)
+0:15          'a' (layout( column_major std430 push_constant) uniform block{layout( column_major std430 offset=0) uniform highp 4X4 matrix of float uWorld, layout( column_major std430 offset=64) uniform highp 4X4 matrix of float uProj, layout( column_major std430 offset=128) uniform highp 4-component vector of float color1, layout( column_major std430 offset=144) uniform highp 4-component vector of float color2})
+0:15          Constant:
+0:15            3 (const int)
+0:18  Function Definition: getWorld( ( global highp 4-component vector of float)
+0:18    Function Parameters: 
+0:20    Sequence
+0:20      Branch: Return with expression
+0:20        matrix-times-vector ( temp highp 4-component vector of float)
+0:20          uWorld: direct index for structure (layout( column_major std430 offset=0) uniform highp 4X4 matrix of float)
+0:20            'a' (layout( column_major std430 push_constant) uniform block{layout( column_major std430 offset=0) uniform highp 4X4 matrix of float uWorld, layout( column_major std430 offset=64) uniform highp 4X4 matrix of float uProj, layout( column_major std430 offset=128) uniform highp 4-component vector of float color1, layout( column_major std430 offset=144) uniform highp 4-component vector of float color2})
+0:20            Constant:
+0:20              0 (const int)
+0:20          'P' ( in highp 4-component vector of float)
+0:?   Linker Objects
+0:?     'a' (layout( column_major std430 push_constant) uniform block{layout( column_major std430 offset=0) uniform highp 4X4 matrix of float uWorld, layout( column_major std430 offset=64) uniform highp 4X4 matrix of float uProj, layout( column_major std430 offset=128) uniform highp 4-component vector of float color1, layout( column_major std430 offset=144) uniform highp 4-component vector of float color2})
+0:?     'oColor' ( smooth out highp 4-component vector of float)
+0:?     'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out 1-element array of float ClipDistance gl_ClipDistance,  out 1-element array of float CullDistance gl_CullDistance})
+0:?     'a' (layout( column_major std430 push_constant) uniform block{layout( column_major std430 offset=0) uniform highp 4X4 matrix of float uWorld, layout( column_major std430 offset=64) uniform highp 4X4 matrix of float uProj, layout( column_major std430 offset=128) uniform highp 4-component vector of float color1, layout( column_major std430 offset=144) uniform highp 4-component vector of float color2})
+0:?     'P' ( in highp 4-component vector of float)
+
+Validation failed
+SPIR-V is not generated for failed compile or link
diff --git a/third_party/glslang/src/Test/baseResults/link.vk.pcNamingValid.0.0.vert.out b/third_party/glslang/src/Test/baseResults/link.vk.pcNamingValid.0.0.vert.out
new file mode 100755
index 0000000..c9dba15
--- /dev/null
+++ b/third_party/glslang/src/Test/baseResults/link.vk.pcNamingValid.0.0.vert.out
@@ -0,0 +1,206 @@
+link.vk.pcNamingValid.0.0.vert
+Shader version: 450
+0:? Sequence
+0:16  Function Definition: main( ( global void)
+0:16    Function Parameters: 
+0:18    Sequence
+0:18      move second child to first child ( temp highp 4-component vector of float)
+0:18        'oColor' (layout( location=0) smooth out highp 4-component vector of float)
+0:18        component-wise multiply ( temp highp 4-component vector of float)
+0:18          color1: direct index for structure (layout( column_major std430 offset=128) uniform highp 4-component vector of float)
+0:18            'a' (layout( column_major std430 push_constant) uniform block{layout( column_major std430 offset=0) uniform highp 4X4 matrix of float uWorld, layout( column_major std430 offset=64) uniform highp 4X4 matrix of float uProj, layout( column_major std430 offset=128) uniform highp 4-component vector of float color1, layout( column_major std430 offset=144) uniform highp 4-component vector of float color2})
+0:18            Constant:
+0:18              2 (const int)
+0:18          Function Call: getColor2( ( global highp 4-component vector of float)
+0:20      move second child to first child ( temp highp 4-component vector of float)
+0:20        gl_Position: direct index for structure ( gl_Position highp 4-component vector of float Position)
+0:20          'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out unsized 1-element array of float ClipDistance gl_ClipDistance,  out unsized 1-element array of float CullDistance gl_CullDistance})
+0:20          Constant:
+0:20            0 (const uint)
+0:20        matrix-times-vector ( temp highp 4-component vector of float)
+0:20          uProj: direct index for structure (layout( column_major std430 offset=64) uniform highp 4X4 matrix of float)
+0:20            'a' (layout( column_major std430 push_constant) uniform block{layout( column_major std430 offset=0) uniform highp 4X4 matrix of float uWorld, layout( column_major std430 offset=64) uniform highp 4X4 matrix of float uProj, layout( column_major std430 offset=128) uniform highp 4-component vector of float color1, layout( column_major std430 offset=144) uniform highp 4-component vector of float color2})
+0:20            Constant:
+0:20              1 (const int)
+0:20          Function Call: getWorld( ( global highp 4-component vector of float)
+0:?   Linker Objects
+0:?     'a' (layout( column_major std430 push_constant) uniform block{layout( column_major std430 offset=0) uniform highp 4X4 matrix of float uWorld, layout( column_major std430 offset=64) uniform highp 4X4 matrix of float uProj, layout( column_major std430 offset=128) uniform highp 4-component vector of float color1, layout( column_major std430 offset=144) uniform highp 4-component vector of float color2})
+0:?     'oColor' (layout( location=0) smooth out highp 4-component vector of float)
+0:?     'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out unsized 1-element array of float ClipDistance gl_ClipDistance,  out unsized 1-element array of float CullDistance gl_CullDistance})
+
+link.vk.pcNamingValid.0.1.vert
+Shader version: 450
+0:? Sequence
+0:13  Function Definition: getColor2( ( global highp 4-component vector of float)
+0:13    Function Parameters: 
+0:15    Sequence
+0:15      Branch: Return with expression
+0:15        color2: direct index for structure (layout( column_major std430 offset=144) uniform highp 4-component vector of float)
+0:15          'b' (layout( column_major std430 push_constant) uniform block{layout( column_major std430 offset=0) uniform highp 4X4 matrix of float uWorld, layout( column_major std430 offset=64) uniform highp 4X4 matrix of float uProj, layout( column_major std430 offset=128) uniform highp 4-component vector of float color1, layout( column_major std430 offset=144) uniform highp 4-component vector of float color2})
+0:15          Constant:
+0:15            3 (const int)
+0:18  Function Definition: getWorld( ( global highp 4-component vector of float)
+0:18    Function Parameters: 
+0:20    Sequence
+0:20      Branch: Return with expression
+0:20        matrix-times-vector ( temp highp 4-component vector of float)
+0:20          uWorld: direct index for structure (layout( column_major std430 offset=0) uniform highp 4X4 matrix of float)
+0:20            'b' (layout( column_major std430 push_constant) uniform block{layout( column_major std430 offset=0) uniform highp 4X4 matrix of float uWorld, layout( column_major std430 offset=64) uniform highp 4X4 matrix of float uProj, layout( column_major std430 offset=128) uniform highp 4-component vector of float color1, layout( column_major std430 offset=144) uniform highp 4-component vector of float color2})
+0:20            Constant:
+0:20              0 (const int)
+0:20          'P' (layout( location=0) in highp 4-component vector of float)
+0:?   Linker Objects
+0:?     'b' (layout( column_major std430 push_constant) uniform block{layout( column_major std430 offset=0) uniform highp 4X4 matrix of float uWorld, layout( column_major std430 offset=64) uniform highp 4X4 matrix of float uProj, layout( column_major std430 offset=128) uniform highp 4-component vector of float color1, layout( column_major std430 offset=144) uniform highp 4-component vector of float color2})
+0:?     'P' (layout( location=0) in highp 4-component vector of float)
+
+
+Linked vertex stage:
+
+WARNING: Linking vertex stage: Matched shader interfaces are using different instance names.
+    a: "layout( column_major std430 push_constant) uniform block{layout( column_major std430 offset=0) uniform highp 4X4 matrix of float uWorld, layout( column_major std430 offset=64) uniform highp 4X4 matrix of float uProj, layout( column_major std430 offset=128) uniform highp 4-component vector of float color1, layout( column_major std430 offset=144) uniform highp 4-component vector of float color2}" versus b: "layout( column_major std430 push_constant) uniform block{layout( column_major std430 offset=0) uniform highp 4X4 matrix of float uWorld, layout( column_major std430 offset=64) uniform highp 4X4 matrix of float uProj, layout( column_major std430 offset=128) uniform highp 4-component vector of float color1, layout( column_major std430 offset=144) uniform highp 4-component vector of float color2}"
+
+Shader version: 450
+0:? Sequence
+0:16  Function Definition: main( ( global void)
+0:16    Function Parameters: 
+0:18    Sequence
+0:18      move second child to first child ( temp highp 4-component vector of float)
+0:18        'oColor' (layout( location=0) smooth out highp 4-component vector of float)
+0:18        component-wise multiply ( temp highp 4-component vector of float)
+0:18          color1: direct index for structure (layout( column_major std430 offset=128) uniform highp 4-component vector of float)
+0:18            'a' (layout( column_major std430 push_constant) uniform block{layout( column_major std430 offset=0) uniform highp 4X4 matrix of float uWorld, layout( column_major std430 offset=64) uniform highp 4X4 matrix of float uProj, layout( column_major std430 offset=128) uniform highp 4-component vector of float color1, layout( column_major std430 offset=144) uniform highp 4-component vector of float color2})
+0:18            Constant:
+0:18              2 (const int)
+0:18          Function Call: getColor2( ( global highp 4-component vector of float)
+0:20      move second child to first child ( temp highp 4-component vector of float)
+0:20        gl_Position: direct index for structure ( gl_Position highp 4-component vector of float Position)
+0:20          'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out 1-element array of float ClipDistance gl_ClipDistance,  out 1-element array of float CullDistance gl_CullDistance})
+0:20          Constant:
+0:20            0 (const uint)
+0:20        matrix-times-vector ( temp highp 4-component vector of float)
+0:20          uProj: direct index for structure (layout( column_major std430 offset=64) uniform highp 4X4 matrix of float)
+0:20            'a' (layout( column_major std430 push_constant) uniform block{layout( column_major std430 offset=0) uniform highp 4X4 matrix of float uWorld, layout( column_major std430 offset=64) uniform highp 4X4 matrix of float uProj, layout( column_major std430 offset=128) uniform highp 4-component vector of float color1, layout( column_major std430 offset=144) uniform highp 4-component vector of float color2})
+0:20            Constant:
+0:20              1 (const int)
+0:20          Function Call: getWorld( ( global highp 4-component vector of float)
+0:13  Function Definition: getColor2( ( global highp 4-component vector of float)
+0:13    Function Parameters: 
+0:15    Sequence
+0:15      Branch: Return with expression
+0:15        color2: direct index for structure (layout( column_major std430 offset=144) uniform highp 4-component vector of float)
+0:15          'b' (layout( column_major std430 push_constant) uniform block{layout( column_major std430 offset=0) uniform highp 4X4 matrix of float uWorld, layout( column_major std430 offset=64) uniform highp 4X4 matrix of float uProj, layout( column_major std430 offset=128) uniform highp 4-component vector of float color1, layout( column_major std430 offset=144) uniform highp 4-component vector of float color2})
+0:15          Constant:
+0:15            3 (const int)
+0:18  Function Definition: getWorld( ( global highp 4-component vector of float)
+0:18    Function Parameters: 
+0:20    Sequence
+0:20      Branch: Return with expression
+0:20        matrix-times-vector ( temp highp 4-component vector of float)
+0:20          uWorld: direct index for structure (layout( column_major std430 offset=0) uniform highp 4X4 matrix of float)
+0:20            'b' (layout( column_major std430 push_constant) uniform block{layout( column_major std430 offset=0) uniform highp 4X4 matrix of float uWorld, layout( column_major std430 offset=64) uniform highp 4X4 matrix of float uProj, layout( column_major std430 offset=128) uniform highp 4-component vector of float color1, layout( column_major std430 offset=144) uniform highp 4-component vector of float color2})
+0:20            Constant:
+0:20              0 (const int)
+0:20          'P' (layout( location=0) in highp 4-component vector of float)
+0:?   Linker Objects
+0:?     'a' (layout( column_major std430 push_constant) uniform block{layout( column_major std430 offset=0) uniform highp 4X4 matrix of float uWorld, layout( column_major std430 offset=64) uniform highp 4X4 matrix of float uProj, layout( column_major std430 offset=128) uniform highp 4-component vector of float color1, layout( column_major std430 offset=144) uniform highp 4-component vector of float color2})
+0:?     'oColor' (layout( location=0) smooth out highp 4-component vector of float)
+0:?     'anon@0' ( out block{ gl_Position 4-component vector of float Position gl_Position,  gl_PointSize float PointSize gl_PointSize,  out 1-element array of float ClipDistance gl_ClipDistance,  out 1-element array of float CullDistance gl_CullDistance})
+0:?     'P' (layout( location=0) in highp 4-component vector of float)
+
+// Module Version 10000
+// Generated by (magic number): 80008
+// Id's are bound by 53
+
+                              Capability Shader
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Vertex 4  "main" 14 31 48
+                              Source GLSL 450
+                              Name 4  "main"
+                              Name 9  "getColor2("
+                              Name 11  "getWorld("
+                              Name 14  "oColor"
+                              Name 16  "PCBlock"
+                              MemberName 16(PCBlock) 0  "uWorld"
+                              MemberName 16(PCBlock) 1  "uProj"
+                              MemberName 16(PCBlock) 2  "color1"
+                              MemberName 16(PCBlock) 3  "color2"
+                              Name 18  "a"
+                              Name 29  "gl_PerVertex"
+                              MemberName 29(gl_PerVertex) 0  "gl_Position"
+                              MemberName 29(gl_PerVertex) 1  "gl_PointSize"
+                              MemberName 29(gl_PerVertex) 2  "gl_ClipDistance"
+                              MemberName 29(gl_PerVertex) 3  "gl_CullDistance"
+                              Name 31  ""
+                              Name 48  "P"
+                              Decorate 14(oColor) Location 0
+                              MemberDecorate 16(PCBlock) 0 ColMajor
+                              MemberDecorate 16(PCBlock) 0 Offset 0
+                              MemberDecorate 16(PCBlock) 0 MatrixStride 16
+                              MemberDecorate 16(PCBlock) 1 ColMajor
+                              MemberDecorate 16(PCBlock) 1 Offset 64
+                              MemberDecorate 16(PCBlock) 1 MatrixStride 16
+                              MemberDecorate 16(PCBlock) 2 Offset 128
+                              MemberDecorate 16(PCBlock) 3 Offset 144
+                              Decorate 16(PCBlock) Block
+                              MemberDecorate 29(gl_PerVertex) 0 BuiltIn Position
+                              MemberDecorate 29(gl_PerVertex) 1 BuiltIn PointSize
+                              MemberDecorate 29(gl_PerVertex) 2 BuiltIn ClipDistance
+                              MemberDecorate 29(gl_PerVertex) 3 BuiltIn CullDistance
+                              Decorate 29(gl_PerVertex) Block
+                              Decorate 48(P) Location 0
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypeVector 6(float) 4
+               8:             TypeFunction 7(fvec4)
+              13:             TypePointer Output 7(fvec4)
+      14(oColor):     13(ptr) Variable Output
+              15:             TypeMatrix 7(fvec4) 4
+     16(PCBlock):             TypeStruct 15 15 7(fvec4) 7(fvec4)
+              17:             TypePointer PushConstant 16(PCBlock)
+           18(a):     17(ptr) Variable PushConstant
+              19:             TypeInt 32 1
+              20:     19(int) Constant 2
+              21:             TypePointer PushConstant 7(fvec4)
+              26:             TypeInt 32 0
+              27:     26(int) Constant 1
+              28:             TypeArray 6(float) 27
+29(gl_PerVertex):             TypeStruct 7(fvec4) 6(float) 28 28
+              30:             TypePointer Output 29(gl_PerVertex)
+              31:     30(ptr) Variable Output
+              32:     19(int) Constant 0
+              33:     19(int) Constant 1
+              34:             TypePointer PushConstant 15
+              40:     19(int) Constant 3
+              47:             TypePointer Input 7(fvec4)
+           48(P):     47(ptr) Variable Input
+         4(main):           2 Function None 3
+               5:             Label
+              22:     21(ptr) AccessChain 18(a) 20
+              23:    7(fvec4) Load 22
+              24:    7(fvec4) FunctionCall 9(getColor2()
+              25:    7(fvec4) FMul 23 24
+                              Store 14(oColor) 25
+              35:     34(ptr) AccessChain 18(a) 33
+              36:          15 Load 35
+              37:    7(fvec4) FunctionCall 11(getWorld()
+              38:    7(fvec4) MatrixTimesVector 36 37
+              39:     13(ptr) AccessChain 31 32
+                              Store 39 38
+                              Return
+                              FunctionEnd
+   9(getColor2():    7(fvec4) Function None 8
+              10:             Label
+              41:     21(ptr) AccessChain 18(a) 40
+              42:    7(fvec4) Load 41
+                              ReturnValue 42
+                              FunctionEnd
+   11(getWorld():    7(fvec4) Function None 8
+              12:             Label
+              45:     34(ptr) AccessChain 18(a) 32
+              46:          15 Load 45
+              49:    7(fvec4) Load 48(P)
+              50:    7(fvec4) MatrixTimesVector 46 49
+                              ReturnValue 50
+                              FunctionEnd
diff --git a/third_party/glslang/src/Test/baseResults/rayQuery-allOps.Error.rgen.out b/third_party/glslang/src/Test/baseResults/rayQuery-allOps.Error.rgen.out
new file mode 100644
index 0000000..98101c3
--- /dev/null
+++ b/third_party/glslang/src/Test/baseResults/rayQuery-allOps.Error.rgen.out
@@ -0,0 +1,26 @@
+rayQuery-allOps.Error.rgen
+ERROR: 0:47: '==' :  wrong operand types: no operation '==' exists that takes a left-hand operand of type ' global bool' and a right operand of type ' const int' (or there is no acceptable conversion)
+ERROR: 0:49: '=' :  cannot convert from ' global uint' to ' temp highp int'
+ERROR: 0:59: '==' :  wrong operand types: no operation '==' exists that takes a left-hand operand of type ' global bool' and a right operand of type ' const int' (or there is no acceptable conversion)
+ERROR: 0:64: '==' :  wrong operand types: no operation '==' exists that takes a left-hand operand of type ' global 2-component vector of float' and a right operand of type ' const int' (or there is no acceptable conversion)
+ERROR: 0:69: '' : boolean expression expected 
+ERROR: 0:74: '' : boolean expression expected 
+ERROR: 0:79: '>' :  wrong operand types: no operation '>' exists that takes a left-hand operand of type ' global 3-component vector of float' and a right operand of type ' const int' (or there is no acceptable conversion)
+ERROR: 0:84: '>' :  wrong operand types: no operation '>' exists that takes a left-hand operand of type ' global 3-component vector of float' and a right operand of type ' const int' (or there is no acceptable conversion)
+ERROR: 0:89: '' : boolean expression expected 
+ERROR: 0:94: '' : boolean expression expected 
+ERROR: 0:99: '' : boolean expression expected 
+ERROR: 0:127: '=' :  cannot convert from ' global uint' to ' temp highp int'
+ERROR: 0:145: '==' :  wrong operand types: no operation '==' exists that takes a left-hand operand of type ' global 2-component vector of float' and a right operand of type ' const int' (or there is no acceptable conversion)
+ERROR: 0:158: '' : boolean expression expected 
+ERROR: 0:163: '' : boolean expression expected 
+ERROR: 0:168: '>' :  wrong operand types: no operation '>' exists that takes a left-hand operand of type ' global 3-component vector of float' and a right operand of type ' const int' (or there is no acceptable conversion)
+ERROR: 0:173: '>' :  wrong operand types: no operation '>' exists that takes a left-hand operand of type ' global 3-component vector of float' and a right operand of type ' const int' (or there is no acceptable conversion)
+ERROR: 0:178: '' : boolean expression expected 
+ERROR: 0:183: '' : boolean expression expected 
+ERROR: 0:195: '' : boolean expression expected 
+ERROR: 0:200: '' : boolean expression expected 
+ERROR: 21 compilation errors.  No code generated.
+
+
+SPIR-V is not generated for failed compile or link
diff --git a/third_party/glslang/src/Test/baseResults/rayQuery-allOps.comp.out b/third_party/glslang/src/Test/baseResults/rayQuery-allOps.comp.out
new file mode 100644
index 0000000..2ac7cd3
--- /dev/null
+++ b/third_party/glslang/src/Test/baseResults/rayQuery-allOps.comp.out
@@ -0,0 +1,433 @@
+rayQuery-allOps.comp
+// Module Version 10000
+// Generated by (magic number): 80008
+// Id's are bound by 258
+
+                              Capability Shader
+                              Capability RayQueryProvisionalKHR
+                              Capability RayTraversalPrimitiveCullingProvisionalKHR
+                              Extension  "SPV_KHR_ray_query"
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint GLCompute 4  "main"
+                              ExecutionMode 4 LocalSize 1 1 1
+                              Source GLSL 460
+                              SourceExtension  "GL_EXT_ray_flags_primitive_culling"
+                              SourceExtension  "GL_EXT_ray_query"
+                              Name 4  "main"
+                              Name 6  "doSomething("
+                              Name 10  "Ray"
+                              MemberName 10(Ray) 0  "pos"
+                              MemberName 10(Ray) 1  "tmin"
+                              MemberName 10(Ray) 2  "dir"
+                              MemberName 10(Ray) 3  "tmax"
+                              Name 12  "makeRayDesc("
+                              Name 15  "Log"
+                              MemberName 15(Log) 0  "x"
+                              MemberName 15(Log) 1  "y"
+                              Name 17  ""
+                              Name 26  "ray"
+                              Name 43  "ray"
+                              Name 47  "rayQuery"
+                              Name 50  "rtas"
+                              Name 69  "candidateType"
+                              Name 78  "_mat4x3"
+                              Name 83  "_mat3x4"
+                              Name 143  "t"
+                              Name 156  "committedStatus"
+                              Name 241  "o"
+                              Name 243  "d"
+                              Name 253  "Ray"
+                              MemberName 253(Ray) 0  "pos"
+                              MemberName 253(Ray) 1  "tmin"
+                              MemberName 253(Ray) 2  "dir"
+                              MemberName 253(Ray) 3  "tmax"
+                              Name 255  "Rays"
+                              MemberName 255(Rays) 0  "rays"
+                              Name 257  ""
+                              MemberDecorate 15(Log) 0 Offset 0
+                              MemberDecorate 15(Log) 1 Offset 4
+                              Decorate 15(Log) BufferBlock
+                              Decorate 17 DescriptorSet 0
+                              Decorate 17 Binding 0
+                              Decorate 50(rtas) DescriptorSet 0
+                              Decorate 50(rtas) Binding 1
+                              MemberDecorate 253(Ray) 0 Offset 0
+                              MemberDecorate 253(Ray) 1 Offset 12
+                              MemberDecorate 253(Ray) 2 Offset 16
+                              MemberDecorate 253(Ray) 3 Offset 28
+                              Decorate 254 ArrayStride 32
+                              MemberDecorate 255(Rays) 0 Offset 0
+                              Decorate 255(Rays) BufferBlock
+                              Decorate 257 DescriptorSet 0
+                              Decorate 257 Binding 2
+               2:             TypeVoid
+               3:             TypeFunction 2
+               8:             TypeFloat 32
+               9:             TypeVector 8(float) 3
+         10(Ray):             TypeStruct 9(fvec3) 8(float) 9(fvec3) 8(float)
+              11:             TypeFunction 10(Ray)
+              14:             TypeInt 32 0
+         15(Log):             TypeStruct 14(int) 14(int)
+              16:             TypePointer Uniform 15(Log)
+              17:     16(ptr) Variable Uniform
+              18:             TypeInt 32 1
+              19:     18(int) Constant 0
+              20:     14(int) Constant 0
+              21:             TypePointer Uniform 14(int)
+              23:     18(int) Constant 1
+              25:             TypePointer Function 10(Ray)
+              27:    8(float) Constant 0
+              28:    9(fvec3) ConstantComposite 27 27 27
+              29:             TypePointer Function 9(fvec3)
+              31:     18(int) Constant 2
+              32:    8(float) Constant 1065353216
+              33:    9(fvec3) ConstantComposite 32 27 27
+              35:             TypePointer Function 8(float)
+              37:     18(int) Constant 3
+              38:    8(float) Constant 1176255488
+              45:             TypeRayQueryProvisionalKHR
+              46:             TypePointer Function 45
+              48:             TypeAccelerationStructureKHR
+              49:             TypePointer UniformConstant 48
+        50(rtas):     49(ptr) Variable UniformConstant
+              52:     14(int) Constant 255
+              66:             TypeBool
+              68:             TypePointer Function 14(int)
+              70:    66(bool) ConstantFalse
+              76:             TypeMatrix 9(fvec3) 4
+              77:             TypePointer Function 76
+              80:             TypeVector 8(float) 4
+              81:             TypeMatrix 80(fvec4) 3
+              82:             TypePointer Function 81
+              86:    66(bool) ConstantTrue
+              91:             TypeVector 8(float) 2
+             144:    8(float) Constant 1056964608
+             175:     14(int) Constant 1
+             198:     14(int) Constant 2
+             231:     14(int) Constant 256
+        253(Ray):             TypeStruct 9(fvec3) 8(float) 9(fvec3) 8(float)
+             254:             TypeRuntimeArray 253(Ray)
+       255(Rays):             TypeStruct 254
+             256:             TypePointer Uniform 255(Rays)
+             257:    256(ptr) Variable Uniform
+         4(main):           2 Function None 3
+               5:             Label
+         43(ray):     25(ptr) Variable Function
+    47(rayQuery):     46(ptr) Variable Function
+69(candidateType):     68(ptr) Variable Function
+     78(_mat4x3):     77(ptr) Variable Function
+     83(_mat3x4):     82(ptr) Variable Function
+          143(t):     35(ptr) Variable Function
+156(committedStatus):     68(ptr) Variable Function
+          241(o):     29(ptr) Variable Function
+          243(d):     29(ptr) Variable Function
+              44:     10(Ray) FunctionCall 12(makeRayDesc()
+                              Store 43(ray) 44
+              51:          48 Load 50(rtas)
+              53:     29(ptr) AccessChain 43(ray) 19
+              54:    9(fvec3) Load 53
+              55:     35(ptr) AccessChain 43(ray) 23
+              56:    8(float) Load 55
+              57:     29(ptr) AccessChain 43(ray) 31
+              58:    9(fvec3) Load 57
+              59:     35(ptr) AccessChain 43(ray) 37
+              60:    8(float) Load 59
+                              RayQueryInitializeKHR 47(rayQuery) 51 20 52 54 56 58 60
+                              Branch 61
+              61:             Label
+                              LoopMerge 63 64 None
+                              Branch 65
+              65:             Label
+              67:    66(bool) RayQueryProceedKHR 47(rayQuery)
+                              BranchConditional 67 62 63
+              62:               Label
+              71:     14(int)   RayQueryGetIntersectionTypeKHR 47(rayQuery) 19
+                                Store 69(candidateType) 71
+              72:     14(int)   Load 69(candidateType)
+                                SelectionMerge 75 None
+                                Switch 72 75 
+                                       case 0: 73
+                                       case 1: 74
+              73:                 Label
+                                  RayQueryTerminateKHR 47(rayQuery)
+              79:          76     RayQueryGetIntersectionObjectToWorldKHR 47(rayQuery) 19
+                                  Store 78(_mat4x3) 79
+              84:          76     Load 78(_mat4x3)
+              85:          81     Transpose 84
+                                  Store 83(_mat3x4) 85
+                                  RayQueryConfirmIntersectionKHR 47(rayQuery)
+              87:    66(bool)     RayQueryGetIntersectionFrontFaceKHR 47(rayQuery) 23
+                                  SelectionMerge 89 None
+                                  BranchConditional 87 88 89
+              88:                   Label
+              90:           2       FunctionCall 6(doSomething()
+                                    Branch 89
+              89:                 Label
+              92:   91(fvec2)     RayQueryGetIntersectionBarycentricsKHR 47(rayQuery) 23
+              93:    8(float)     CompositeExtract 92 0
+              94:    66(bool)     FOrdEqual 93 27
+                                  SelectionMerge 96 None
+                                  BranchConditional 94 95 96
+              95:                   Label
+              97:           2       FunctionCall 6(doSomething()
+                                    Branch 96
+              96:                 Label
+              98:     18(int)     RayQueryGetIntersectionInstanceCustomIndexKHR 47(rayQuery) 23
+              99:    66(bool)     SGreaterThan 98 19
+                                  SelectionMerge 101 None
+                                  BranchConditional 99 100 101
+             100:                   Label
+             102:           2       FunctionCall 6(doSomething()
+                                    Branch 101
+             101:                 Label
+             103:     18(int)     RayQueryGetIntersectionInstanceIdKHR 47(rayQuery) 23
+             104:    66(bool)     SGreaterThan 103 19
+                                  SelectionMerge 106 None
+                                  BranchConditional 104 105 106
+             105:                   Label
+             107:           2       FunctionCall 6(doSomething()
+                                    Branch 106
+             106:                 Label
+             108:    9(fvec3)     RayQueryGetIntersectionObjectRayDirectionKHR 47(rayQuery) 23
+             109:    8(float)     CompositeExtract 108 0
+             110:    66(bool)     FOrdGreaterThan 109 27
+                                  SelectionMerge 112 None
+                                  BranchConditional 110 111 112
+             111:                   Label
+             113:           2       FunctionCall 6(doSomething()
+                                    Branch 112
+             112:                 Label
+             114:    9(fvec3)     RayQueryGetIntersectionObjectRayOriginKHR 47(rayQuery) 23
+             115:    8(float)     CompositeExtract 114 0
+             116:    66(bool)     FOrdGreaterThan 115 27
+                                  SelectionMerge 118 None
+                                  BranchConditional 116 117 118
+             117:                   Label
+             119:           2       FunctionCall 6(doSomething()
+                                    Branch 118
+             118:                 Label
+             120:     18(int)     RayQueryGetIntersectionPrimitiveIndexKHR 47(rayQuery) 23
+             121:    66(bool)     SGreaterThan 120 19
+                                  SelectionMerge 123 None
+                                  BranchConditional 121 122 123
+             122:                   Label
+             124:           2       FunctionCall 6(doSomething()
+                                    Branch 123
+             123:                 Label
+             125:    8(float)     RayQueryGetIntersectionTKHR 47(rayQuery) 23
+             126:    66(bool)     FOrdGreaterThan 125 27
+                                  SelectionMerge 128 None
+                                  BranchConditional 126 127 128
+             127:                   Label
+             129:           2       FunctionCall 6(doSomething()
+                                    Branch 128
+             128:                 Label
+             130:     18(int)     RayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR 47(rayQuery) 23
+             131:    66(bool)     UGreaterThan 130 20
+                                  SelectionMerge 133 None
+                                  BranchConditional 131 132 133
+             132:                   Label
+             134:           2       FunctionCall 6(doSomething()
+                                    Branch 133
+             133:                 Label
+                                  Branch 75
+              74:                 Label
+             136:          76     RayQueryGetIntersectionObjectToWorldKHR 47(rayQuery) 19
+                                  Store 78(_mat4x3) 136
+             137:          76     Load 78(_mat4x3)
+             138:          81     Transpose 137
+                                  Store 83(_mat3x4) 138
+             139:    66(bool)     RayQueryGetIntersectionCandidateAABBOpaqueKHR 47(rayQuery)
+                                  SelectionMerge 141 None
+                                  BranchConditional 139 140 141
+             140:                   Label
+             142:           2       FunctionCall 6(doSomething()
+                                    Branch 141
+             141:                 Label
+                                  Store 143(t) 144
+             145:    8(float)     Load 143(t)
+                                  RayQueryGenerateIntersectionKHR 47(rayQuery) 145
+                                  RayQueryTerminateKHR 47(rayQuery)
+                                  Branch 75
+              75:               Label
+                                Branch 64
+              64:               Label
+                                Branch 61
+              63:             Label
+             148:     35(ptr) AccessChain 83(_mat3x4) 19 20
+             149:    8(float) Load 148
+             150:     35(ptr) AccessChain 78(_mat4x3) 19 20
+             151:    8(float) Load 150
+             152:    66(bool) FOrdEqual 149 151
+                              SelectionMerge 154 None
+                              BranchConditional 152 153 154
+             153:               Label
+             155:           2   FunctionCall 6(doSomething()
+                                Branch 154
+             154:             Label
+             157:     14(int) RayQueryGetIntersectionTypeKHR 47(rayQuery) 23
+                              Store 156(committedStatus) 157
+             158:     14(int) Load 156(committedStatus)
+                              SelectionMerge 162 None
+                              Switch 158 162 
+                                     case 0: 159
+                                     case 1: 160
+                                     case 2: 161
+             159:               Label
+             163:          76   RayQueryGetIntersectionWorldToObjectKHR 47(rayQuery) 19
+                                Store 78(_mat4x3) 163
+             164:          76   Load 78(_mat4x3)
+             165:          81   Transpose 164
+                                Store 83(_mat3x4) 165
+                                Branch 162
+             160:               Label
+             167:          76   RayQueryGetIntersectionWorldToObjectKHR 47(rayQuery) 23
+                                Store 78(_mat4x3) 167
+             168:          76   Load 78(_mat4x3)
+             169:          81   Transpose 168
+                                Store 83(_mat3x4) 169
+             170:    66(bool)   RayQueryGetIntersectionFrontFaceKHR 47(rayQuery) 23
+                                SelectionMerge 172 None
+                                BranchConditional 170 171 172
+             171:                 Label
+             173:           2     FunctionCall 6(doSomething()
+                                  Branch 172
+             172:               Label
+             174:   91(fvec2)   RayQueryGetIntersectionBarycentricsKHR 47(rayQuery) 23
+             176:    8(float)   CompositeExtract 174 1
+             177:    66(bool)   FOrdEqual 176 27
+                                SelectionMerge 179 None
+                                BranchConditional 177 178 179
+             178:                 Label
+             180:           2     FunctionCall 6(doSomething()
+                                  Branch 179
+             179:               Label
+                                Branch 162
+             161:               Label
+             182:     18(int)   RayQueryGetIntersectionGeometryIndexKHR 47(rayQuery) 23
+             183:    66(bool)   SGreaterThan 182 19
+                                SelectionMerge 185 None
+                                BranchConditional 183 184 185
+             184:                 Label
+             186:           2     FunctionCall 6(doSomething()
+                                  Branch 185
+             185:               Label
+             187:     18(int)   RayQueryGetIntersectionInstanceIdKHR 47(rayQuery) 23
+             188:    66(bool)   SGreaterThan 187 19
+                                SelectionMerge 190 None
+                                BranchConditional 188 189 190
+             189:                 Label
+             191:           2     FunctionCall 6(doSomething()
+                                  Branch 190
+             190:               Label
+             192:     18(int)   RayQueryGetIntersectionInstanceCustomIndexKHR 47(rayQuery) 23
+             193:    66(bool)   SGreaterThan 192 19
+                                SelectionMerge 195 None
+                                BranchConditional 193 194 195
+             194:                 Label
+             196:           2     FunctionCall 6(doSomething()
+                                  Branch 195
+             195:               Label
+             197:    9(fvec3)   RayQueryGetIntersectionObjectRayDirectionKHR 47(rayQuery) 23
+             199:    8(float)   CompositeExtract 197 2
+             200:    66(bool)   FOrdGreaterThan 199 27
+                                SelectionMerge 202 None
+                                BranchConditional 200 201 202
+             201:                 Label
+             203:           2     FunctionCall 6(doSomething()
+                                  Branch 202
+             202:               Label
+             204:    9(fvec3)   RayQueryGetIntersectionObjectRayOriginKHR 47(rayQuery) 23
+             205:    8(float)   CompositeExtract 204 0
+             206:    66(bool)   FOrdGreaterThan 205 27
+                                SelectionMerge 208 None
+                                BranchConditional 206 207 208
+             207:                 Label
+             209:           2     FunctionCall 6(doSomething()
+                                  Branch 208
+             208:               Label
+             210:     18(int)   RayQueryGetIntersectionPrimitiveIndexKHR 47(rayQuery) 23
+             211:    66(bool)   SGreaterThan 210 19
+                                SelectionMerge 213 None
+                                BranchConditional 211 212 213
+             212:                 Label
+             214:           2     FunctionCall 6(doSomething()
+                                  Branch 213
+             213:               Label
+             215:    8(float)   RayQueryGetIntersectionTKHR 47(rayQuery) 23
+             216:    66(bool)   FOrdGreaterThan 215 27
+                                SelectionMerge 218 None
+                                BranchConditional 216 217 218
+             217:                 Label
+             219:           2     FunctionCall 6(doSomething()
+                                  Branch 218
+             218:               Label
+                                Branch 162
+             162:             Label
+             222:     35(ptr) AccessChain 83(_mat3x4) 19 20
+             223:    8(float) Load 222
+             224:     35(ptr) AccessChain 78(_mat4x3) 19 20
+             225:    8(float) Load 224
+             226:    66(bool) FOrdEqual 223 225
+                              SelectionMerge 228 None
+                              BranchConditional 226 227 228
+             227:               Label
+             229:           2   FunctionCall 6(doSomething()
+                                Branch 228
+             228:             Label
+             230:     14(int) RayQueryGetRayFlagsKHR 47(rayQuery)
+             232:    66(bool) UGreaterThan 230 231
+                              SelectionMerge 234 None
+                              BranchConditional 232 233 234
+             233:               Label
+             235:           2   FunctionCall 6(doSomething()
+                                Branch 234
+             234:             Label
+             236:    8(float) RayQueryGetRayTMinKHR 47(rayQuery)
+             237:    66(bool) FOrdGreaterThan 236 27
+                              SelectionMerge 239 None
+                              BranchConditional 237 238 239
+             238:               Label
+             240:           2   FunctionCall 6(doSomething()
+                                Branch 239
+             239:             Label
+             242:    9(fvec3) RayQueryGetWorldRayOriginKHR 47(rayQuery)
+                              Store 241(o) 242
+             244:    9(fvec3) RayQueryGetWorldRayDirectionKHR 47(rayQuery)
+                              Store 243(d) 244
+             245:     35(ptr) AccessChain 241(o) 20
+             246:    8(float) Load 245
+             247:     35(ptr) AccessChain 243(d) 198
+             248:    8(float) Load 247
+             249:    66(bool) FOrdEqual 246 248
+                              SelectionMerge 251 None
+                              BranchConditional 249 250 251
+             250:               Label
+             252:           2   FunctionCall 6(doSomething()
+                                Branch 251
+             251:             Label
+                              Return
+                              FunctionEnd
+ 6(doSomething():           2 Function None 3
+               7:             Label
+              22:     21(ptr) AccessChain 17 19
+                              Store 22 20
+              24:     21(ptr) AccessChain 17 23
+                              Store 24 20
+                              Return
+                              FunctionEnd
+12(makeRayDesc():     10(Ray) Function None 11
+              13:             Label
+         26(ray):     25(ptr) Variable Function
+              30:     29(ptr) AccessChain 26(ray) 19
+                              Store 30 28
+              34:     29(ptr) AccessChain 26(ray) 31
+                              Store 34 33
+              36:     35(ptr) AccessChain 26(ray) 23
+                              Store 36 27
+              39:     35(ptr) AccessChain 26(ray) 37
+                              Store 39 38
+              40:     10(Ray) Load 26(ray)
+                              ReturnValue 40
+                              FunctionEnd
diff --git a/third_party/glslang/src/Test/baseResults/rayQuery-allOps.frag.out b/third_party/glslang/src/Test/baseResults/rayQuery-allOps.frag.out
new file mode 100644
index 0000000..3160c2b
--- /dev/null
+++ b/third_party/glslang/src/Test/baseResults/rayQuery-allOps.frag.out
@@ -0,0 +1,431 @@
+rayQuery-allOps.frag
+// Module Version 10000
+// Generated by (magic number): 80008
+// Id's are bound by 257
+
+                              Capability Shader
+                              Capability RayQueryProvisionalKHR
+                              Extension  "SPV_KHR_ray_query"
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Fragment 4  "main"
+                              ExecutionMode 4 OriginUpperLeft
+                              Source GLSL 460
+                              SourceExtension  "GL_EXT_ray_query"
+                              SourceExtension  "GL_NV_ray_tracing"
+                              Name 4  "main"
+                              Name 6  "doSomething("
+                              Name 10  "Ray"
+                              MemberName 10(Ray) 0  "pos"
+                              MemberName 10(Ray) 1  "tmin"
+                              MemberName 10(Ray) 2  "dir"
+                              MemberName 10(Ray) 3  "tmax"
+                              Name 12  "makeRayDesc("
+                              Name 15  "Log"
+                              MemberName 15(Log) 0  "x"
+                              MemberName 15(Log) 1  "y"
+                              Name 17  ""
+                              Name 26  "ray"
+                              Name 43  "ray"
+                              Name 47  "rayQuery"
+                              Name 50  "rtas"
+                              Name 69  "candidateType"
+                              Name 78  "_mat4x3"
+                              Name 83  "_mat3x4"
+                              Name 143  "t"
+                              Name 156  "committedStatus"
+                              Name 240  "o"
+                              Name 242  "d"
+                              Name 252  "Ray"
+                              MemberName 252(Ray) 0  "pos"
+                              MemberName 252(Ray) 1  "tmin"
+                              MemberName 252(Ray) 2  "dir"
+                              MemberName 252(Ray) 3  "tmax"
+                              Name 254  "Rays"
+                              MemberName 254(Rays) 0  "rays"
+                              Name 256  ""
+                              MemberDecorate 15(Log) 0 Offset 0
+                              MemberDecorate 15(Log) 1 Offset 4
+                              Decorate 15(Log) BufferBlock
+                              Decorate 17 DescriptorSet 0
+                              Decorate 17 Binding 0
+                              Decorate 50(rtas) DescriptorSet 0
+                              Decorate 50(rtas) Binding 1
+                              MemberDecorate 252(Ray) 0 Offset 0
+                              MemberDecorate 252(Ray) 1 Offset 12
+                              MemberDecorate 252(Ray) 2 Offset 16
+                              MemberDecorate 252(Ray) 3 Offset 28
+                              Decorate 253 ArrayStride 32
+                              MemberDecorate 254(Rays) 0 Offset 0
+                              Decorate 254(Rays) BufferBlock
+                              Decorate 256 DescriptorSet 0
+                              Decorate 256 Binding 2
+               2:             TypeVoid
+               3:             TypeFunction 2
+               8:             TypeFloat 32
+               9:             TypeVector 8(float) 3
+         10(Ray):             TypeStruct 9(fvec3) 8(float) 9(fvec3) 8(float)
+              11:             TypeFunction 10(Ray)
+              14:             TypeInt 32 0
+         15(Log):             TypeStruct 14(int) 14(int)
+              16:             TypePointer Uniform 15(Log)
+              17:     16(ptr) Variable Uniform
+              18:             TypeInt 32 1
+              19:     18(int) Constant 0
+              20:     14(int) Constant 0
+              21:             TypePointer Uniform 14(int)
+              23:     18(int) Constant 1
+              25:             TypePointer Function 10(Ray)
+              27:    8(float) Constant 0
+              28:    9(fvec3) ConstantComposite 27 27 27
+              29:             TypePointer Function 9(fvec3)
+              31:     18(int) Constant 2
+              32:    8(float) Constant 1065353216
+              33:    9(fvec3) ConstantComposite 32 27 27
+              35:             TypePointer Function 8(float)
+              37:     18(int) Constant 3
+              38:    8(float) Constant 1176255488
+              45:             TypeRayQueryProvisionalKHR
+              46:             TypePointer Function 45
+              48:             TypeAccelerationStructureKHR
+              49:             TypePointer UniformConstant 48
+        50(rtas):     49(ptr) Variable UniformConstant
+              52:     14(int) Constant 255
+              66:             TypeBool
+              68:             TypePointer Function 14(int)
+              70:    66(bool) ConstantFalse
+              76:             TypeMatrix 9(fvec3) 4
+              77:             TypePointer Function 76
+              80:             TypeVector 8(float) 4
+              81:             TypeMatrix 80(fvec4) 3
+              82:             TypePointer Function 81
+              86:    66(bool) ConstantTrue
+              91:             TypeVector 8(float) 2
+             144:    8(float) Constant 1056964608
+             175:     14(int) Constant 1
+             198:     14(int) Constant 2
+        252(Ray):             TypeStruct 9(fvec3) 8(float) 9(fvec3) 8(float)
+             253:             TypeRuntimeArray 252(Ray)
+       254(Rays):             TypeStruct 253
+             255:             TypePointer Uniform 254(Rays)
+             256:    255(ptr) Variable Uniform
+         4(main):           2 Function None 3
+               5:             Label
+         43(ray):     25(ptr) Variable Function
+    47(rayQuery):     46(ptr) Variable Function
+69(candidateType):     68(ptr) Variable Function
+     78(_mat4x3):     77(ptr) Variable Function
+     83(_mat3x4):     82(ptr) Variable Function
+          143(t):     35(ptr) Variable Function
+156(committedStatus):     68(ptr) Variable Function
+          240(o):     29(ptr) Variable Function
+          242(d):     29(ptr) Variable Function
+              44:     10(Ray) FunctionCall 12(makeRayDesc()
+                              Store 43(ray) 44
+              51:          48 Load 50(rtas)
+              53:     29(ptr) AccessChain 43(ray) 19
+              54:    9(fvec3) Load 53
+              55:     35(ptr) AccessChain 43(ray) 23
+              56:    8(float) Load 55
+              57:     29(ptr) AccessChain 43(ray) 31
+              58:    9(fvec3) Load 57
+              59:     35(ptr) AccessChain 43(ray) 37
+              60:    8(float) Load 59
+                              RayQueryInitializeKHR 47(rayQuery) 51 20 52 54 56 58 60
+                              Branch 61
+              61:             Label
+                              LoopMerge 63 64 None
+                              Branch 65
+              65:             Label
+              67:    66(bool) RayQueryProceedKHR 47(rayQuery)
+                              BranchConditional 67 62 63
+              62:               Label
+              71:     14(int)   RayQueryGetIntersectionTypeKHR 47(rayQuery) 19
+                                Store 69(candidateType) 71
+              72:     14(int)   Load 69(candidateType)
+                                SelectionMerge 75 None
+                                Switch 72 75 
+                                       case 0: 73
+                                       case 1: 74
+              73:                 Label
+                                  RayQueryTerminateKHR 47(rayQuery)
+              79:          76     RayQueryGetIntersectionObjectToWorldKHR 47(rayQuery) 19
+                                  Store 78(_mat4x3) 79
+              84:          76     Load 78(_mat4x3)
+              85:          81     Transpose 84
+                                  Store 83(_mat3x4) 85
+                                  RayQueryConfirmIntersectionKHR 47(rayQuery)
+              87:    66(bool)     RayQueryGetIntersectionFrontFaceKHR 47(rayQuery) 23
+                                  SelectionMerge 89 None
+                                  BranchConditional 87 88 89
+              88:                   Label
+              90:           2       FunctionCall 6(doSomething()
+                                    Branch 89
+              89:                 Label
+              92:   91(fvec2)     RayQueryGetIntersectionBarycentricsKHR 47(rayQuery) 23
+              93:    8(float)     CompositeExtract 92 0
+              94:    66(bool)     FOrdEqual 93 27
+                                  SelectionMerge 96 None
+                                  BranchConditional 94 95 96
+              95:                   Label
+              97:           2       FunctionCall 6(doSomething()
+                                    Branch 96
+              96:                 Label
+              98:     18(int)     RayQueryGetIntersectionInstanceCustomIndexKHR 47(rayQuery) 23
+              99:    66(bool)     SGreaterThan 98 19
+                                  SelectionMerge 101 None
+                                  BranchConditional 99 100 101
+             100:                   Label
+             102:           2       FunctionCall 6(doSomething()
+                                    Branch 101
+             101:                 Label
+             103:     18(int)     RayQueryGetIntersectionInstanceIdKHR 47(rayQuery) 23
+             104:    66(bool)     SGreaterThan 103 19
+                                  SelectionMerge 106 None
+                                  BranchConditional 104 105 106
+             105:                   Label
+             107:           2       FunctionCall 6(doSomething()
+                                    Branch 106
+             106:                 Label
+             108:    9(fvec3)     RayQueryGetIntersectionObjectRayDirectionKHR 47(rayQuery) 23
+             109:    8(float)     CompositeExtract 108 0
+             110:    66(bool)     FOrdGreaterThan 109 27
+                                  SelectionMerge 112 None
+                                  BranchConditional 110 111 112
+             111:                   Label
+             113:           2       FunctionCall 6(doSomething()
+                                    Branch 112
+             112:                 Label
+             114:    9(fvec3)     RayQueryGetIntersectionObjectRayOriginKHR 47(rayQuery) 23
+             115:    8(float)     CompositeExtract 114 0
+             116:    66(bool)     FOrdGreaterThan 115 27
+                                  SelectionMerge 118 None
+                                  BranchConditional 116 117 118
+             117:                   Label
+             119:           2       FunctionCall 6(doSomething()
+                                    Branch 118
+             118:                 Label
+             120:     18(int)     RayQueryGetIntersectionPrimitiveIndexKHR 47(rayQuery) 23
+             121:    66(bool)     SGreaterThan 120 19
+                                  SelectionMerge 123 None
+                                  BranchConditional 121 122 123
+             122:                   Label
+             124:           2       FunctionCall 6(doSomething()
+                                    Branch 123
+             123:                 Label
+             125:    8(float)     RayQueryGetIntersectionTKHR 47(rayQuery) 23
+             126:    66(bool)     FOrdGreaterThan 125 27
+                                  SelectionMerge 128 None
+                                  BranchConditional 126 127 128
+             127:                   Label
+             129:           2       FunctionCall 6(doSomething()
+                                    Branch 128
+             128:                 Label
+             130:     18(int)     RayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR 47(rayQuery) 23
+             131:    66(bool)     UGreaterThan 130 20
+                                  SelectionMerge 133 None
+                                  BranchConditional 131 132 133
+             132:                   Label
+             134:           2       FunctionCall 6(doSomething()
+                                    Branch 133
+             133:                 Label
+                                  Branch 75
+              74:                 Label
+             136:          76     RayQueryGetIntersectionObjectToWorldKHR 47(rayQuery) 19
+                                  Store 78(_mat4x3) 136
+             137:          76     Load 78(_mat4x3)
+             138:          81     Transpose 137
+                                  Store 83(_mat3x4) 138
+             139:    66(bool)     RayQueryGetIntersectionCandidateAABBOpaqueKHR 47(rayQuery)
+                                  SelectionMerge 141 None
+                                  BranchConditional 139 140 141
+             140:                   Label
+             142:           2       FunctionCall 6(doSomething()
+                                    Branch 141
+             141:                 Label
+                                  Store 143(t) 144
+             145:    8(float)     Load 143(t)
+                                  RayQueryGenerateIntersectionKHR 47(rayQuery) 145
+                                  RayQueryTerminateKHR 47(rayQuery)
+                                  Branch 75
+              75:               Label
+                                Branch 64
+              64:               Label
+                                Branch 61
+              63:             Label
+             148:     35(ptr) AccessChain 83(_mat3x4) 19 20
+             149:    8(float) Load 148
+             150:     35(ptr) AccessChain 78(_mat4x3) 19 20
+             151:    8(float) Load 150
+             152:    66(bool) FOrdEqual 149 151
+                              SelectionMerge 154 None
+                              BranchConditional 152 153 154
+             153:               Label
+             155:           2   FunctionCall 6(doSomething()
+                                Branch 154
+             154:             Label
+             157:     14(int) RayQueryGetIntersectionTypeKHR 47(rayQuery) 23
+                              Store 156(committedStatus) 157
+             158:     14(int) Load 156(committedStatus)
+                              SelectionMerge 162 None
+                              Switch 158 162 
+                                     case 0: 159
+                                     case 1: 160
+                                     case 2: 161
+             159:               Label
+             163:          76   RayQueryGetIntersectionWorldToObjectKHR 47(rayQuery) 19
+                                Store 78(_mat4x3) 163
+             164:          76   Load 78(_mat4x3)
+             165:          81   Transpose 164
+                                Store 83(_mat3x4) 165
+                                Branch 162
+             160:               Label
+             167:          76   RayQueryGetIntersectionWorldToObjectKHR 47(rayQuery) 23
+                                Store 78(_mat4x3) 167
+             168:          76   Load 78(_mat4x3)
+             169:          81   Transpose 168
+                                Store 83(_mat3x4) 169
+             170:    66(bool)   RayQueryGetIntersectionFrontFaceKHR 47(rayQuery) 23
+                                SelectionMerge 172 None
+                                BranchConditional 170 171 172
+             171:                 Label
+             173:           2     FunctionCall 6(doSomething()
+                                  Branch 172
+             172:               Label
+             174:   91(fvec2)   RayQueryGetIntersectionBarycentricsKHR 47(rayQuery) 23
+             176:    8(float)   CompositeExtract 174 1
+             177:    66(bool)   FOrdEqual 176 27
+                                SelectionMerge 179 None
+                                BranchConditional 177 178 179
+             178:                 Label
+             180:           2     FunctionCall 6(doSomething()
+                                  Branch 179
+             179:               Label
+                                Branch 162
+             161:               Label
+             182:     18(int)   RayQueryGetIntersectionGeometryIndexKHR 47(rayQuery) 23
+             183:    66(bool)   SGreaterThan 182 19
+                                SelectionMerge 185 None
+                                BranchConditional 183 184 185
+             184:                 Label
+             186:           2     FunctionCall 6(doSomething()
+                                  Branch 185
+             185:               Label
+             187:     18(int)   RayQueryGetIntersectionInstanceIdKHR 47(rayQuery) 23
+             188:    66(bool)   SGreaterThan 187 19
+                                SelectionMerge 190 None
+                                BranchConditional 188 189 190
+             189:                 Label
+             191:           2     FunctionCall 6(doSomething()
+                                  Branch 190
+             190:               Label
+             192:     18(int)   RayQueryGetIntersectionInstanceCustomIndexKHR 47(rayQuery) 23
+             193:    66(bool)   SGreaterThan 192 19
+                                SelectionMerge 195 None
+                                BranchConditional 193 194 195
+             194:                 Label
+             196:           2     FunctionCall 6(doSomething()
+                                  Branch 195
+             195:               Label
+             197:    9(fvec3)   RayQueryGetIntersectionObjectRayDirectionKHR 47(rayQuery) 23
+             199:    8(float)   CompositeExtract 197 2
+             200:    66(bool)   FOrdGreaterThan 199 27
+                                SelectionMerge 202 None
+                                BranchConditional 200 201 202
+             201:                 Label
+             203:           2     FunctionCall 6(doSomething()
+                                  Branch 202
+             202:               Label
+             204:    9(fvec3)   RayQueryGetIntersectionObjectRayOriginKHR 47(rayQuery) 23
+             205:    8(float)   CompositeExtract 204 0
+             206:    66(bool)   FOrdGreaterThan 205 27
+                                SelectionMerge 208 None
+                                BranchConditional 206 207 208
+             207:                 Label
+             209:           2     FunctionCall 6(doSomething()
+                                  Branch 208
+             208:               Label
+             210:     18(int)   RayQueryGetIntersectionPrimitiveIndexKHR 47(rayQuery) 23
+             211:    66(bool)   SGreaterThan 210 19
+                                SelectionMerge 213 None
+                                BranchConditional 211 212 213
+             212:                 Label
+             214:           2     FunctionCall 6(doSomething()
+                                  Branch 213
+             213:               Label
+             215:    8(float)   RayQueryGetIntersectionTKHR 47(rayQuery) 23
+             216:    66(bool)   FOrdGreaterThan 215 27
+                                SelectionMerge 218 None
+                                BranchConditional 216 217 218
+             217:                 Label
+             219:           2     FunctionCall 6(doSomething()
+                                  Branch 218
+             218:               Label
+                                Branch 162
+             162:             Label
+             222:     35(ptr) AccessChain 83(_mat3x4) 19 20
+             223:    8(float) Load 222
+             224:     35(ptr) AccessChain 78(_mat4x3) 19 20
+             225:    8(float) Load 224
+             226:    66(bool) FOrdEqual 223 225
+                              SelectionMerge 228 None
+                              BranchConditional 226 227 228
+             227:               Label
+             229:           2   FunctionCall 6(doSomething()
+                                Branch 228
+             228:             Label
+             230:     14(int) RayQueryGetRayFlagsKHR 47(rayQuery)
+             231:    66(bool) UGreaterThan 230 20
+                              SelectionMerge 233 None
+                              BranchConditional 231 232 233
+             232:               Label
+             234:           2   FunctionCall 6(doSomething()
+                                Branch 233
+             233:             Label
+             235:    8(float) RayQueryGetRayTMinKHR 47(rayQuery)
+             236:    66(bool) FOrdGreaterThan 235 27
+                              SelectionMerge 238 None
+                              BranchConditional 236 237 238
+             237:               Label
+             239:           2   FunctionCall 6(doSomething()
+                                Branch 238
+             238:             Label
+             241:    9(fvec3) RayQueryGetWorldRayOriginKHR 47(rayQuery)
+                              Store 240(o) 241
+             243:    9(fvec3) RayQueryGetWorldRayDirectionKHR 47(rayQuery)
+                              Store 242(d) 243
+             244:     35(ptr) AccessChain 240(o) 20
+             245:    8(float) Load 244
+             246:     35(ptr) AccessChain 242(d) 198
+             247:    8(float) Load 246
+             248:    66(bool) FOrdEqual 245 247
+                              SelectionMerge 250 None
+                              BranchConditional 248 249 250
+             249:               Label
+             251:           2   FunctionCall 6(doSomething()
+                                Branch 250
+             250:             Label
+                              Return
+                              FunctionEnd
+ 6(doSomething():           2 Function None 3
+               7:             Label
+              22:     21(ptr) AccessChain 17 19
+                              Store 22 20
+              24:     21(ptr) AccessChain 17 23
+                              Store 24 20
+                              Return
+                              FunctionEnd
+12(makeRayDesc():     10(Ray) Function None 11
+              13:             Label
+         26(ray):     25(ptr) Variable Function
+              30:     29(ptr) AccessChain 26(ray) 19
+                              Store 30 28
+              34:     29(ptr) AccessChain 26(ray) 31
+                              Store 34 33
+              36:     35(ptr) AccessChain 26(ray) 23
+                              Store 36 27
+              39:     35(ptr) AccessChain 26(ray) 37
+                              Store 39 38
+              40:     10(Ray) Load 26(ray)
+                              ReturnValue 40
+                              FunctionEnd
diff --git a/third_party/glslang/src/Test/baseResults/rayQuery-allOps.rgen.out b/third_party/glslang/src/Test/baseResults/rayQuery-allOps.rgen.out
new file mode 100644
index 0000000..a61769e
--- /dev/null
+++ b/third_party/glslang/src/Test/baseResults/rayQuery-allOps.rgen.out
@@ -0,0 +1,431 @@
+rayQuery-allOps.rgen
+// Module Version 10000
+// Generated by (magic number): 80008
+// Id's are bound by 257
+
+                              Capability RayQueryProvisionalKHR
+                              Capability RayTracingNV
+                              Extension  "SPV_KHR_ray_query"
+                              Extension  "SPV_NV_ray_tracing"
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint RayGenerationKHR 4  "main"
+                              Source GLSL 460
+                              SourceExtension  "GL_EXT_ray_query"
+                              SourceExtension  "GL_NV_ray_tracing"
+                              Name 4  "main"
+                              Name 6  "doSomething("
+                              Name 10  "Ray"
+                              MemberName 10(Ray) 0  "pos"
+                              MemberName 10(Ray) 1  "tmin"
+                              MemberName 10(Ray) 2  "dir"
+                              MemberName 10(Ray) 3  "tmax"
+                              Name 12  "makeRayDesc("
+                              Name 15  "Log"
+                              MemberName 15(Log) 0  "x"
+                              MemberName 15(Log) 1  "y"
+                              Name 17  ""
+                              Name 26  "ray"
+                              Name 43  "ray"
+                              Name 47  "rayQuery"
+                              Name 50  "rtas"
+                              Name 69  "candidateType"
+                              Name 78  "_mat4x3"
+                              Name 83  "_mat3x4"
+                              Name 143  "t"
+                              Name 156  "committedStatus"
+                              Name 240  "o"
+                              Name 242  "d"
+                              Name 252  "Ray"
+                              MemberName 252(Ray) 0  "pos"
+                              MemberName 252(Ray) 1  "tmin"
+                              MemberName 252(Ray) 2  "dir"
+                              MemberName 252(Ray) 3  "tmax"
+                              Name 254  "Rays"
+                              MemberName 254(Rays) 0  "rays"
+                              Name 256  ""
+                              MemberDecorate 15(Log) 0 Offset 0
+                              MemberDecorate 15(Log) 1 Offset 4
+                              Decorate 15(Log) BufferBlock
+                              Decorate 17 DescriptorSet 0
+                              Decorate 17 Binding 0
+                              Decorate 50(rtas) DescriptorSet 0
+                              Decorate 50(rtas) Binding 1
+                              MemberDecorate 252(Ray) 0 Offset 0
+                              MemberDecorate 252(Ray) 1 Offset 12
+                              MemberDecorate 252(Ray) 2 Offset 16
+                              MemberDecorate 252(Ray) 3 Offset 28
+                              Decorate 253 ArrayStride 32
+                              MemberDecorate 254(Rays) 0 Offset 0
+                              Decorate 254(Rays) BufferBlock
+                              Decorate 256 DescriptorSet 0
+                              Decorate 256 Binding 2
+               2:             TypeVoid
+               3:             TypeFunction 2
+               8:             TypeFloat 32
+               9:             TypeVector 8(float) 3
+         10(Ray):             TypeStruct 9(fvec3) 8(float) 9(fvec3) 8(float)
+              11:             TypeFunction 10(Ray)
+              14:             TypeInt 32 0
+         15(Log):             TypeStruct 14(int) 14(int)
+              16:             TypePointer Uniform 15(Log)
+              17:     16(ptr) Variable Uniform
+              18:             TypeInt 32 1
+              19:     18(int) Constant 0
+              20:     14(int) Constant 0
+              21:             TypePointer Uniform 14(int)
+              23:     18(int) Constant 1
+              25:             TypePointer Function 10(Ray)
+              27:    8(float) Constant 0
+              28:    9(fvec3) ConstantComposite 27 27 27
+              29:             TypePointer Function 9(fvec3)
+              31:     18(int) Constant 2
+              32:    8(float) Constant 1065353216
+              33:    9(fvec3) ConstantComposite 32 27 27
+              35:             TypePointer Function 8(float)
+              37:     18(int) Constant 3
+              38:    8(float) Constant 1176255488
+              45:             TypeRayQueryProvisionalKHR
+              46:             TypePointer Function 45
+              48:             TypeAccelerationStructureKHR
+              49:             TypePointer UniformConstant 48
+        50(rtas):     49(ptr) Variable UniformConstant
+              52:     14(int) Constant 255
+              66:             TypeBool
+              68:             TypePointer Function 14(int)
+              70:    66(bool) ConstantFalse
+              76:             TypeMatrix 9(fvec3) 4
+              77:             TypePointer Function 76
+              80:             TypeVector 8(float) 4
+              81:             TypeMatrix 80(fvec4) 3
+              82:             TypePointer Function 81
+              86:    66(bool) ConstantTrue
+              91:             TypeVector 8(float) 2
+             144:    8(float) Constant 1056964608
+             175:     14(int) Constant 1
+             198:     14(int) Constant 2
+        252(Ray):             TypeStruct 9(fvec3) 8(float) 9(fvec3) 8(float)
+             253:             TypeRuntimeArray 252(Ray)
+       254(Rays):             TypeStruct 253
+             255:             TypePointer Uniform 254(Rays)
+             256:    255(ptr) Variable Uniform
+         4(main):           2 Function None 3
+               5:             Label
+         43(ray):     25(ptr) Variable Function
+    47(rayQuery):     46(ptr) Variable Function
+69(candidateType):     68(ptr) Variable Function
+     78(_mat4x3):     77(ptr) Variable Function
+     83(_mat3x4):     82(ptr) Variable Function
+          143(t):     35(ptr) Variable Function
+156(committedStatus):     68(ptr) Variable Function
+          240(o):     29(ptr) Variable Function
+          242(d):     29(ptr) Variable Function
+              44:     10(Ray) FunctionCall 12(makeRayDesc()
+                              Store 43(ray) 44
+              51:          48 Load 50(rtas)
+              53:     29(ptr) AccessChain 43(ray) 19
+              54:    9(fvec3) Load 53
+              55:     35(ptr) AccessChain 43(ray) 23
+              56:    8(float) Load 55
+              57:     29(ptr) AccessChain 43(ray) 31
+              58:    9(fvec3) Load 57
+              59:     35(ptr) AccessChain 43(ray) 37
+              60:    8(float) Load 59
+                              RayQueryInitializeKHR 47(rayQuery) 51 20 52 54 56 58 60
+                              Branch 61
+              61:             Label
+                              LoopMerge 63 64 None
+                              Branch 65
+              65:             Label
+              67:    66(bool) RayQueryProceedKHR 47(rayQuery)
+                              BranchConditional 67 62 63
+              62:               Label
+              71:     14(int)   RayQueryGetIntersectionTypeKHR 47(rayQuery) 19
+                                Store 69(candidateType) 71
+              72:     14(int)   Load 69(candidateType)
+                                SelectionMerge 75 None
+                                Switch 72 75 
+                                       case 0: 73
+                                       case 1: 74
+              73:                 Label
+                                  RayQueryTerminateKHR 47(rayQuery)
+              79:          76     RayQueryGetIntersectionObjectToWorldKHR 47(rayQuery) 19
+                                  Store 78(_mat4x3) 79
+              84:          76     Load 78(_mat4x3)
+              85:          81     Transpose 84
+                                  Store 83(_mat3x4) 85
+                                  RayQueryConfirmIntersectionKHR 47(rayQuery)
+              87:    66(bool)     RayQueryGetIntersectionFrontFaceKHR 47(rayQuery) 23
+                                  SelectionMerge 89 None
+                                  BranchConditional 87 88 89
+              88:                   Label
+              90:           2       FunctionCall 6(doSomething()
+                                    Branch 89
+              89:                 Label
+              92:   91(fvec2)     RayQueryGetIntersectionBarycentricsKHR 47(rayQuery) 23
+              93:    8(float)     CompositeExtract 92 0
+              94:    66(bool)     FOrdEqual 93 27
+                                  SelectionMerge 96 None
+                                  BranchConditional 94 95 96
+              95:                   Label
+              97:           2       FunctionCall 6(doSomething()
+                                    Branch 96
+              96:                 Label
+              98:     18(int)     RayQueryGetIntersectionInstanceCustomIndexKHR 47(rayQuery) 23
+              99:    66(bool)     SGreaterThan 98 19
+                                  SelectionMerge 101 None
+                                  BranchConditional 99 100 101
+             100:                   Label
+             102:           2       FunctionCall 6(doSomething()
+                                    Branch 101
+             101:                 Label
+             103:     18(int)     RayQueryGetIntersectionInstanceIdKHR 47(rayQuery) 23
+             104:    66(bool)     SGreaterThan 103 19
+                                  SelectionMerge 106 None
+                                  BranchConditional 104 105 106
+             105:                   Label
+             107:           2       FunctionCall 6(doSomething()
+                                    Branch 106
+             106:                 Label
+             108:    9(fvec3)     RayQueryGetIntersectionObjectRayDirectionKHR 47(rayQuery) 23
+             109:    8(float)     CompositeExtract 108 0
+             110:    66(bool)     FOrdGreaterThan 109 27
+                                  SelectionMerge 112 None
+                                  BranchConditional 110 111 112
+             111:                   Label
+             113:           2       FunctionCall 6(doSomething()
+                                    Branch 112
+             112:                 Label
+             114:    9(fvec3)     RayQueryGetIntersectionObjectRayOriginKHR 47(rayQuery) 23
+             115:    8(float)     CompositeExtract 114 0
+             116:    66(bool)     FOrdGreaterThan 115 27
+                                  SelectionMerge 118 None
+                                  BranchConditional 116 117 118
+             117:                   Label
+             119:           2       FunctionCall 6(doSomething()
+                                    Branch 118
+             118:                 Label
+             120:     18(int)     RayQueryGetIntersectionPrimitiveIndexKHR 47(rayQuery) 23
+             121:    66(bool)     SGreaterThan 120 19
+                                  SelectionMerge 123 None
+                                  BranchConditional 121 122 123
+             122:                   Label
+             124:           2       FunctionCall 6(doSomething()
+                                    Branch 123
+             123:                 Label
+             125:    8(float)     RayQueryGetIntersectionTKHR 47(rayQuery) 23
+             126:    66(bool)     FOrdGreaterThan 125 27
+                                  SelectionMerge 128 None
+                                  BranchConditional 126 127 128
+             127:                   Label
+             129:           2       FunctionCall 6(doSomething()
+                                    Branch 128
+             128:                 Label
+             130:     18(int)     RayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR 47(rayQuery) 23
+             131:    66(bool)     UGreaterThan 130 20
+                                  SelectionMerge 133 None
+                                  BranchConditional 131 132 133
+             132:                   Label
+             134:           2       FunctionCall 6(doSomething()
+                                    Branch 133
+             133:                 Label
+                                  Branch 75
+              74:                 Label
+             136:          76     RayQueryGetIntersectionObjectToWorldKHR 47(rayQuery) 19
+                                  Store 78(_mat4x3) 136
+             137:          76     Load 78(_mat4x3)
+             138:          81     Transpose 137
+                                  Store 83(_mat3x4) 138
+             139:    66(bool)     RayQueryGetIntersectionCandidateAABBOpaqueKHR 47(rayQuery)
+                                  SelectionMerge 141 None
+                                  BranchConditional 139 140 141
+             140:                   Label
+             142:           2       FunctionCall 6(doSomething()
+                                    Branch 141
+             141:                 Label
+                                  Store 143(t) 144
+             145:    8(float)     Load 143(t)
+                                  RayQueryGenerateIntersectionKHR 47(rayQuery) 145
+                                  RayQueryTerminateKHR 47(rayQuery)
+                                  Branch 75
+              75:               Label
+                                Branch 64
+              64:               Label
+                                Branch 61
+              63:             Label
+             148:     35(ptr) AccessChain 83(_mat3x4) 19 20
+             149:    8(float) Load 148
+             150:     35(ptr) AccessChain 78(_mat4x3) 19 20
+             151:    8(float) Load 150
+             152:    66(bool) FOrdEqual 149 151
+                              SelectionMerge 154 None
+                              BranchConditional 152 153 154
+             153:               Label
+             155:           2   FunctionCall 6(doSomething()
+                                Branch 154
+             154:             Label
+             157:     14(int) RayQueryGetIntersectionTypeKHR 47(rayQuery) 23
+                              Store 156(committedStatus) 157
+             158:     14(int) Load 156(committedStatus)
+                              SelectionMerge 162 None
+                              Switch 158 162 
+                                     case 0: 159
+                                     case 1: 160
+                                     case 2: 161
+             159:               Label
+             163:          76   RayQueryGetIntersectionWorldToObjectKHR 47(rayQuery) 19
+                                Store 78(_mat4x3) 163
+             164:          76   Load 78(_mat4x3)
+             165:          81   Transpose 164
+                                Store 83(_mat3x4) 165
+                                Branch 162
+             160:               Label
+             167:          76   RayQueryGetIntersectionWorldToObjectKHR 47(rayQuery) 23
+                                Store 78(_mat4x3) 167
+             168:          76   Load 78(_mat4x3)
+             169:          81   Transpose 168
+                                Store 83(_mat3x4) 169
+             170:    66(bool)   RayQueryGetIntersectionFrontFaceKHR 47(rayQuery) 23
+                                SelectionMerge 172 None
+                                BranchConditional 170 171 172
+             171:                 Label
+             173:           2     FunctionCall 6(doSomething()
+                                  Branch 172
+             172:               Label
+             174:   91(fvec2)   RayQueryGetIntersectionBarycentricsKHR 47(rayQuery) 23
+             176:    8(float)   CompositeExtract 174 1
+             177:    66(bool)   FOrdEqual 176 27
+                                SelectionMerge 179 None
+                                BranchConditional 177 178 179
+             178:                 Label
+             180:           2     FunctionCall 6(doSomething()
+                                  Branch 179
+             179:               Label
+                                Branch 162
+             161:               Label
+             182:     18(int)   RayQueryGetIntersectionGeometryIndexKHR 47(rayQuery) 23
+             183:    66(bool)   SGreaterThan 182 19
+                                SelectionMerge 185 None
+                                BranchConditional 183 184 185
+             184:                 Label
+             186:           2     FunctionCall 6(doSomething()
+                                  Branch 185
+             185:               Label
+             187:     18(int)   RayQueryGetIntersectionInstanceIdKHR 47(rayQuery) 23
+             188:    66(bool)   SGreaterThan 187 19
+                                SelectionMerge 190 None
+                                BranchConditional 188 189 190
+             189:                 Label
+             191:           2     FunctionCall 6(doSomething()
+                                  Branch 190
+             190:               Label
+             192:     18(int)   RayQueryGetIntersectionInstanceCustomIndexKHR 47(rayQuery) 23
+             193:    66(bool)   SGreaterThan 192 19
+                                SelectionMerge 195 None
+                                BranchConditional 193 194 195
+             194:                 Label
+             196:           2     FunctionCall 6(doSomething()
+                                  Branch 195
+             195:               Label
+             197:    9(fvec3)   RayQueryGetIntersectionObjectRayDirectionKHR 47(rayQuery) 23
+             199:    8(float)   CompositeExtract 197 2
+             200:    66(bool)   FOrdGreaterThan 199 27
+                                SelectionMerge 202 None
+                                BranchConditional 200 201 202
+             201:                 Label
+             203:           2     FunctionCall 6(doSomething()
+                                  Branch 202
+             202:               Label
+             204:    9(fvec3)   RayQueryGetIntersectionObjectRayOriginKHR 47(rayQuery) 23
+             205:    8(float)   CompositeExtract 204 0
+             206:    66(bool)   FOrdGreaterThan 205 27
+                                SelectionMerge 208 None
+                                BranchConditional 206 207 208
+             207:                 Label
+             209:           2     FunctionCall 6(doSomething()
+                                  Branch 208
+             208:               Label
+             210:     18(int)   RayQueryGetIntersectionPrimitiveIndexKHR 47(rayQuery) 23
+             211:    66(bool)   SGreaterThan 210 19
+                                SelectionMerge 213 None
+                                BranchConditional 211 212 213
+             212:                 Label
+             214:           2     FunctionCall 6(doSomething()
+                                  Branch 213
+             213:               Label
+             215:    8(float)   RayQueryGetIntersectionTKHR 47(rayQuery) 23
+             216:    66(bool)   FOrdGreaterThan 215 27
+                                SelectionMerge 218 None
+                                BranchConditional 216 217 218
+             217:                 Label
+             219:           2     FunctionCall 6(doSomething()
+                                  Branch 218
+             218:               Label
+                                Branch 162
+             162:             Label
+             222:     35(ptr) AccessChain 83(_mat3x4) 19 20
+             223:    8(float) Load 222
+             224:     35(ptr) AccessChain 78(_mat4x3) 19 20
+             225:    8(float) Load 224
+             226:    66(bool) FOrdEqual 223 225
+                              SelectionMerge 228 None
+                              BranchConditional 226 227 228
+             227:               Label
+             229:           2   FunctionCall 6(doSomething()
+                                Branch 228
+             228:             Label
+             230:     14(int) RayQueryGetRayFlagsKHR 47(rayQuery)
+             231:    66(bool) UGreaterThan 230 20
+                              SelectionMerge 233 None
+                              BranchConditional 231 232 233
+             232:               Label
+             234:           2   FunctionCall 6(doSomething()
+                                Branch 233
+             233:             Label
+             235:    8(float) RayQueryGetRayTMinKHR 47(rayQuery)
+             236:    66(bool) FOrdGreaterThan 235 27
+                              SelectionMerge 238 None
+                              BranchConditional 236 237 238
+             237:               Label
+             239:           2   FunctionCall 6(doSomething()
+                                Branch 238
+             238:             Label
+             241:    9(fvec3) RayQueryGetWorldRayOriginKHR 47(rayQuery)
+                              Store 240(o) 241
+             243:    9(fvec3) RayQueryGetWorldRayDirectionKHR 47(rayQuery)
+                              Store 242(d) 243
+             244:     35(ptr) AccessChain 240(o) 20
+             245:    8(float) Load 244
+             246:     35(ptr) AccessChain 242(d) 198
+             247:    8(float) Load 246
+             248:    66(bool) FOrdEqual 245 247
+                              SelectionMerge 250 None
+                              BranchConditional 248 249 250
+             249:               Label
+             251:           2   FunctionCall 6(doSomething()
+                                Branch 250
+             250:             Label
+                              Return
+                              FunctionEnd
+ 6(doSomething():           2 Function None 3
+               7:             Label
+              22:     21(ptr) AccessChain 17 19
+                              Store 22 20
+              24:     21(ptr) AccessChain 17 23
+                              Store 24 20
+                              Return
+                              FunctionEnd
+12(makeRayDesc():     10(Ray) Function None 11
+              13:             Label
+         26(ray):     25(ptr) Variable Function
+              30:     29(ptr) AccessChain 26(ray) 19
+                              Store 30 28
+              34:     29(ptr) AccessChain 26(ray) 31
+                              Store 34 33
+              36:     35(ptr) AccessChain 26(ray) 23
+                              Store 36 27
+              39:     35(ptr) AccessChain 26(ray) 37
+                              Store 39 38
+              40:     10(Ray) Load 26(ray)
+                              ReturnValue 40
+                              FunctionEnd
diff --git a/third_party/glslang/src/Test/baseResults/rayQuery-committed.Error.rgen.out b/third_party/glslang/src/Test/baseResults/rayQuery-committed.Error.rgen.out
new file mode 100644
index 0000000..037f692
--- /dev/null
+++ b/third_party/glslang/src/Test/baseResults/rayQuery-committed.Error.rgen.out
@@ -0,0 +1,19 @@
+rayQuery-committed.Error.rgen
+ERROR: 0:48: 'committed' : argument must be compile-time constant 
+ERROR: 0:53: 'committed' : argument must be compile-time constant 
+ERROR: 0:54: 'committed' : argument must be compile-time constant 
+ERROR: 0:58: 'committed' : argument must be compile-time constant 
+ERROR: 0:62: 'committed' : argument must be compile-time constant 
+ERROR: 0:66: 'committed' : argument must be compile-time constant 
+ERROR: 0:70: 'committed' : argument must be compile-time constant 
+ERROR: 0:74: 'committed' : argument must be compile-time constant 
+ERROR: 0:78: 'committed' : argument must be compile-time constant 
+ERROR: 0:82: 'committed' : argument must be compile-time constant 
+ERROR: 0:86: 'committed' : argument must be compile-time constant 
+ERROR: 0:90: 'committed' : argument must be compile-time constant 
+ERROR: 0:97: 'committed' : argument must be compile-time constant 
+ERROR: 0:100: 'committed' : argument must be compile-time constant 
+ERROR: 14 compilation errors.  No code generated.
+
+
+SPIR-V is not generated for failed compile or link
diff --git a/third_party/glslang/src/Test/baseResults/rayQuery-initialize.rgen.out b/third_party/glslang/src/Test/baseResults/rayQuery-initialize.rgen.out
new file mode 100644
index 0000000..7824930
--- /dev/null
+++ b/third_party/glslang/src/Test/baseResults/rayQuery-initialize.rgen.out
@@ -0,0 +1,166 @@
+rayQuery-initialize.rgen
+// Module Version 10000
+// Generated by (magic number): 80008
+// Id's are bound by 103
+
+                              Capability RayQueryProvisionalKHR
+                              Capability RayTracingNV
+                              Extension  "SPV_KHR_ray_query"
+                              Extension  "SPV_NV_ray_tracing"
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint RayGenerationKHR 4  "main" 23 28
+                              Source GLSL 460
+                              SourceExtension  "GL_EXT_ray_query"
+                              SourceExtension  "GL_NV_ray_tracing"
+                              Name 4  "main"
+                              Name 8  "launchIndex("
+                              Name 14  "Ray"
+                              MemberName 14(Ray) 0  "pos"
+                              MemberName 14(Ray) 1  "tmin"
+                              MemberName 14(Ray) 2  "dir"
+                              MemberName 14(Ray) 3  "tmax"
+                              Name 19  "doInitialize(rq1;struct-Ray-vf3-f1-vf3-f11;"
+                              Name 17  "rayQuery"
+                              Name 18  "ray"
+                              Name 23  "gl_LaunchIDNV"
+                              Name 28  "gl_LaunchSizeNV"
+                              Name 50  "rtas"
+                              Name 69  "index"
+                              Name 71  "ray"
+                              Name 72  "Ray"
+                              MemberName 72(Ray) 0  "pos"
+                              MemberName 72(Ray) 1  "tmin"
+                              MemberName 72(Ray) 2  "dir"
+                              MemberName 72(Ray) 3  "tmax"
+                              Name 74  "Rays"
+                              MemberName 74(Rays) 0  "rays"
+                              Name 76  ""
+                              Name 89  "rayQuery"
+                              Name 90  "param"
+                              Decorate 23(gl_LaunchIDNV) BuiltIn LaunchIdKHR
+                              Decorate 28(gl_LaunchSizeNV) BuiltIn LaunchSizeKHR
+                              Decorate 50(rtas) DescriptorSet 0
+                              Decorate 50(rtas) Binding 0
+                              MemberDecorate 72(Ray) 0 Offset 0
+                              MemberDecorate 72(Ray) 1 Offset 12
+                              MemberDecorate 72(Ray) 2 Offset 16
+                              MemberDecorate 72(Ray) 3 Offset 28
+                              Decorate 73 ArrayStride 32
+                              MemberDecorate 74(Rays) 0 Offset 0
+                              Decorate 74(Rays) BufferBlock
+                              Decorate 76 DescriptorSet 0
+                              Decorate 76 Binding 2
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeInt 32 0
+               7:             TypeFunction 6(int)
+              10:             TypeRayQueryProvisionalKHR
+              11:             TypePointer Function 10
+              12:             TypeFloat 32
+              13:             TypeVector 12(float) 3
+         14(Ray):             TypeStruct 13(fvec3) 12(float) 13(fvec3) 12(float)
+              15:             TypePointer Function 14(Ray)
+              16:             TypeFunction 2 11(ptr) 15(ptr)
+              21:             TypeVector 6(int) 3
+              22:             TypePointer Input 21(ivec3)
+23(gl_LaunchIDNV):     22(ptr) Variable Input
+              24:      6(int) Constant 2
+              25:             TypePointer Input 6(int)
+28(gl_LaunchSizeNV):     22(ptr) Variable Input
+              29:      6(int) Constant 0
+              33:      6(int) Constant 1
+              48:             TypeAccelerationStructureKHR
+              49:             TypePointer UniformConstant 48
+        50(rtas):     49(ptr) Variable UniformConstant
+              52:      6(int) Constant 16
+              53:             TypeInt 32 1
+              54:     53(int) Constant 0
+              55:             TypePointer Function 13(fvec3)
+              58:     53(int) Constant 1
+              59:             TypePointer Function 12(float)
+              62:     53(int) Constant 2
+              65:     53(int) Constant 3
+              68:             TypePointer Function 6(int)
+         72(Ray):             TypeStruct 13(fvec3) 12(float) 13(fvec3) 12(float)
+              73:             TypeRuntimeArray 72(Ray)
+        74(Rays):             TypeStruct 73
+              75:             TypePointer Uniform 74(Rays)
+              76:     75(ptr) Variable Uniform
+              78:             TypePointer Uniform 72(Ray)
+              94:      6(int) Constant 32
+         4(main):           2 Function None 3
+               5:             Label
+       69(index):     68(ptr) Variable Function
+         71(ray):     15(ptr) Variable Function
+    89(rayQuery):     11(ptr) Variable Function
+       90(param):     15(ptr) Variable Function
+              70:      6(int) FunctionCall 8(launchIndex()
+                              Store 69(index) 70
+              77:      6(int) Load 69(index)
+              79:     78(ptr) AccessChain 76 54 77
+              80:     72(Ray) Load 79
+              81:   13(fvec3) CompositeExtract 80 0
+              82:     55(ptr) AccessChain 71(ray) 54
+                              Store 82 81
+              83:   12(float) CompositeExtract 80 1
+              84:     59(ptr) AccessChain 71(ray) 58
+                              Store 84 83
+              85:   13(fvec3) CompositeExtract 80 2
+              86:     55(ptr) AccessChain 71(ray) 62
+                              Store 86 85
+              87:   12(float) CompositeExtract 80 3
+              88:     59(ptr) AccessChain 71(ray) 65
+                              Store 88 87
+              91:     14(Ray) Load 71(ray)
+                              Store 90(param) 91
+              92:           2 FunctionCall 19(doInitialize(rq1;struct-Ray-vf3-f1-vf3-f11;) 89(rayQuery) 90(param)
+              93:          48 Load 50(rtas)
+              95:     55(ptr) AccessChain 71(ray) 54
+              96:   13(fvec3) Load 95
+              97:     59(ptr) AccessChain 71(ray) 58
+              98:   12(float) Load 97
+              99:     55(ptr) AccessChain 71(ray) 62
+             100:   13(fvec3) Load 99
+             101:     59(ptr) AccessChain 71(ray) 65
+             102:   12(float) Load 101
+                              RayQueryInitializeKHR 89(rayQuery) 93 33 94 96 98 100 102
+                              Return
+                              FunctionEnd
+ 8(launchIndex():      6(int) Function None 7
+               9:             Label
+              26:     25(ptr) AccessChain 23(gl_LaunchIDNV) 24
+              27:      6(int) Load 26
+              30:     25(ptr) AccessChain 28(gl_LaunchSizeNV) 29
+              31:      6(int) Load 30
+              32:      6(int) IMul 27 31
+              34:     25(ptr) AccessChain 28(gl_LaunchSizeNV) 33
+              35:      6(int) Load 34
+              36:      6(int) IMul 32 35
+              37:     25(ptr) AccessChain 23(gl_LaunchIDNV) 33
+              38:      6(int) Load 37
+              39:     25(ptr) AccessChain 28(gl_LaunchSizeNV) 29
+              40:      6(int) Load 39
+              41:      6(int) IMul 38 40
+              42:      6(int) IAdd 36 41
+              43:     25(ptr) AccessChain 23(gl_LaunchIDNV) 29
+              44:      6(int) Load 43
+              45:      6(int) IAdd 42 44
+                              ReturnValue 45
+                              FunctionEnd
+19(doInitialize(rq1;struct-Ray-vf3-f1-vf3-f11;):           2 Function None 16
+    17(rayQuery):     11(ptr) FunctionParameter
+         18(ray):     15(ptr) FunctionParameter
+              20:             Label
+              51:          48 Load 50(rtas)
+              56:     55(ptr) AccessChain 18(ray) 54
+              57:   13(fvec3) Load 56
+              60:     59(ptr) AccessChain 18(ray) 58
+              61:   12(float) Load 60
+              63:     55(ptr) AccessChain 18(ray) 62
+              64:   13(fvec3) Load 63
+              66:     59(ptr) AccessChain 18(ray) 65
+              67:   12(float) Load 66
+                              RayQueryInitializeKHR 17(rayQuery) 51 29 52 57 61 64 67
+                              Return
+                              FunctionEnd
diff --git a/third_party/glslang/src/Test/baseResults/rayQuery-no-cse.rgen.out b/third_party/glslang/src/Test/baseResults/rayQuery-no-cse.rgen.out
new file mode 100644
index 0000000..c09e348
--- /dev/null
+++ b/third_party/glslang/src/Test/baseResults/rayQuery-no-cse.rgen.out
@@ -0,0 +1,173 @@
+rayQuery-no-cse.rgen
+// Module Version 10000
+// Generated by (magic number): 80008
+// Id's are bound by 107
+
+                              Capability RayQueryProvisionalKHR
+                              Capability RayTracingNV
+                              Extension  "SPV_KHR_ray_query"
+                              Extension  "SPV_NV_ray_tracing"
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint RayGenerationKHR 4  "main" 23 28
+                              Source GLSL 460
+                              SourceExtension  "GL_EXT_ray_query"
+                              SourceExtension  "GL_NV_ray_tracing"
+                              Name 4  "main"
+                              Name 8  "launchIndex("
+                              Name 14  "Ray"
+                              MemberName 14(Ray) 0  "pos"
+                              MemberName 14(Ray) 1  "tmin"
+                              MemberName 14(Ray) 2  "dir"
+                              MemberName 14(Ray) 3  "tmax"
+                              Name 19  "doInitialize(rq1;struct-Ray-vf3-f1-vf3-f11;"
+                              Name 17  "rayQuery"
+                              Name 18  "ray"
+                              Name 23  "gl_LaunchIDNV"
+                              Name 28  "gl_LaunchSizeNV"
+                              Name 50  "rtas"
+                              Name 69  "index"
+                              Name 71  "ray"
+                              Name 72  "Ray"
+                              MemberName 72(Ray) 0  "pos"
+                              MemberName 72(Ray) 1  "tmin"
+                              MemberName 72(Ray) 2  "dir"
+                              MemberName 72(Ray) 3  "tmax"
+                              Name 74  "Rays"
+                              MemberName 74(Rays) 0  "rays"
+                              Name 76  ""
+                              Name 89  "rayQuery1"
+                              Name 90  "param"
+                              Name 103  "rayQuery2"
+                              Name 104  "param"
+                              Decorate 23(gl_LaunchIDNV) BuiltIn LaunchIdKHR
+                              Decorate 28(gl_LaunchSizeNV) BuiltIn LaunchSizeKHR
+                              Decorate 50(rtas) DescriptorSet 0
+                              Decorate 50(rtas) Binding 0
+                              MemberDecorate 72(Ray) 0 Offset 0
+                              MemberDecorate 72(Ray) 1 Offset 12
+                              MemberDecorate 72(Ray) 2 Offset 16
+                              MemberDecorate 72(Ray) 3 Offset 28
+                              Decorate 73 ArrayStride 32
+                              MemberDecorate 74(Rays) 0 Offset 0
+                              Decorate 74(Rays) BufferBlock
+                              Decorate 76 DescriptorSet 0
+                              Decorate 76 Binding 2
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeInt 32 0
+               7:             TypeFunction 6(int)
+              10:             TypeRayQueryProvisionalKHR
+              11:             TypePointer Function 10
+              12:             TypeFloat 32
+              13:             TypeVector 12(float) 3
+         14(Ray):             TypeStruct 13(fvec3) 12(float) 13(fvec3) 12(float)
+              15:             TypePointer Function 14(Ray)
+              16:             TypeFunction 2 11(ptr) 15(ptr)
+              21:             TypeVector 6(int) 3
+              22:             TypePointer Input 21(ivec3)
+23(gl_LaunchIDNV):     22(ptr) Variable Input
+              24:      6(int) Constant 2
+              25:             TypePointer Input 6(int)
+28(gl_LaunchSizeNV):     22(ptr) Variable Input
+              29:      6(int) Constant 0
+              33:      6(int) Constant 1
+              48:             TypeAccelerationStructureKHR
+              49:             TypePointer UniformConstant 48
+        50(rtas):     49(ptr) Variable UniformConstant
+              52:      6(int) Constant 16
+              53:             TypeInt 32 1
+              54:     53(int) Constant 0
+              55:             TypePointer Function 13(fvec3)
+              58:     53(int) Constant 1
+              59:             TypePointer Function 12(float)
+              62:     53(int) Constant 2
+              65:     53(int) Constant 3
+              68:             TypePointer Function 6(int)
+         72(Ray):             TypeStruct 13(fvec3) 12(float) 13(fvec3) 12(float)
+              73:             TypeRuntimeArray 72(Ray)
+        74(Rays):             TypeStruct 73
+              75:             TypePointer Uniform 74(Rays)
+              76:     75(ptr) Variable Uniform
+              78:             TypePointer Uniform 72(Ray)
+              94:      6(int) Constant 32
+         4(main):           2 Function None 3
+               5:             Label
+       69(index):     68(ptr) Variable Function
+         71(ray):     15(ptr) Variable Function
+   89(rayQuery1):     11(ptr) Variable Function
+       90(param):     15(ptr) Variable Function
+  103(rayQuery2):     11(ptr) Variable Function
+      104(param):     15(ptr) Variable Function
+              70:      6(int) FunctionCall 8(launchIndex()
+                              Store 69(index) 70
+              77:      6(int) Load 69(index)
+              79:     78(ptr) AccessChain 76 54 77
+              80:     72(Ray) Load 79
+              81:   13(fvec3) CompositeExtract 80 0
+              82:     55(ptr) AccessChain 71(ray) 54
+                              Store 82 81
+              83:   12(float) CompositeExtract 80 1
+              84:     59(ptr) AccessChain 71(ray) 58
+                              Store 84 83
+              85:   13(fvec3) CompositeExtract 80 2
+              86:     55(ptr) AccessChain 71(ray) 62
+                              Store 86 85
+              87:   12(float) CompositeExtract 80 3
+              88:     59(ptr) AccessChain 71(ray) 65
+                              Store 88 87
+              91:     14(Ray) Load 71(ray)
+                              Store 90(param) 91
+              92:           2 FunctionCall 19(doInitialize(rq1;struct-Ray-vf3-f1-vf3-f11;) 89(rayQuery1) 90(param)
+              93:          48 Load 50(rtas)
+              95:     55(ptr) AccessChain 71(ray) 54
+              96:   13(fvec3) Load 95
+              97:     59(ptr) AccessChain 71(ray) 58
+              98:   12(float) Load 97
+              99:     55(ptr) AccessChain 71(ray) 62
+             100:   13(fvec3) Load 99
+             101:     59(ptr) AccessChain 71(ray) 65
+             102:   12(float) Load 101
+                              RayQueryInitializeKHR 89(rayQuery1) 93 33 94 96 98 100 102
+             105:     14(Ray) Load 71(ray)
+                              Store 104(param) 105
+             106:           2 FunctionCall 19(doInitialize(rq1;struct-Ray-vf3-f1-vf3-f11;) 103(rayQuery2) 104(param)
+                              Return
+                              FunctionEnd
+ 8(launchIndex():      6(int) Function None 7
+               9:             Label
+              26:     25(ptr) AccessChain 23(gl_LaunchIDNV) 24
+              27:      6(int) Load 26
+              30:     25(ptr) AccessChain 28(gl_LaunchSizeNV) 29
+              31:      6(int) Load 30
+              32:      6(int) IMul 27 31
+              34:     25(ptr) AccessChain 28(gl_LaunchSizeNV) 33
+              35:      6(int) Load 34
+              36:      6(int) IMul 32 35
+              37:     25(ptr) AccessChain 23(gl_LaunchIDNV) 33
+              38:      6(int) Load 37
+              39:     25(ptr) AccessChain 28(gl_LaunchSizeNV) 29
+              40:      6(int) Load 39
+              41:      6(int) IMul 38 40
+              42:      6(int) IAdd 36 41
+              43:     25(ptr) AccessChain 23(gl_LaunchIDNV) 29
+              44:      6(int) Load 43
+              45:      6(int) IAdd 42 44
+                              ReturnValue 45
+                              FunctionEnd
+19(doInitialize(rq1;struct-Ray-vf3-f1-vf3-f11;):           2 Function None 16
+    17(rayQuery):     11(ptr) FunctionParameter
+         18(ray):     15(ptr) FunctionParameter
+              20:             Label
+              51:          48 Load 50(rtas)
+              56:     55(ptr) AccessChain 18(ray) 54
+              57:   13(fvec3) Load 56
+              60:     59(ptr) AccessChain 18(ray) 58
+              61:   12(float) Load 60
+              63:     55(ptr) AccessChain 18(ray) 62
+              64:   13(fvec3) Load 63
+              66:     59(ptr) AccessChain 18(ray) 65
+              67:   12(float) Load 66
+                              RayQueryInitializeKHR 17(rayQuery) 51 29 52 57 61 64 67
+                              Return
+                              FunctionEnd
diff --git a/third_party/glslang/src/Test/baseResults/rayQuery.rgen.out b/third_party/glslang/src/Test/baseResults/rayQuery.rgen.out
new file mode 100644
index 0000000..4658338
--- /dev/null
+++ b/third_party/glslang/src/Test/baseResults/rayQuery.rgen.out
@@ -0,0 +1,82 @@
+rayQuery.rgen
+// Module Version 10000
+// Generated by (magic number): 80008
+// Id's are bound by 44
+
+                              Capability RayQueryProvisionalKHR
+                              Capability RayTracingNV
+                              Extension  "SPV_KHR_ray_query"
+                              Extension  "SPV_NV_ray_tracing"
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint RayGenerationKHR 4  "main"
+                              Source GLSL 460
+                              SourceExtension  "GL_EXT_ray_query"
+                              SourceExtension  "GL_NV_ray_tracing"
+                              Name 4  "main"
+                              Name 8  "rayFlags"
+                              Name 12  "tMin"
+                              Name 14  "tMax"
+                              Name 18  "localRayQuery"
+                              Name 21  "acc0"
+                              Name 26  "block"
+                              MemberName 26(block) 0  "dir"
+                              MemberName 26(block) 1  "origin"
+                              Name 28  ""
+                              Decorate 21(acc0) DescriptorSet 0
+                              Decorate 21(acc0) Binding 0
+                              MemberDecorate 26(block) 0 Offset 0
+                              MemberDecorate 26(block) 1 Offset 16
+                              Decorate 26(block) BufferBlock
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeInt 32 0
+               7:             TypePointer Function 6(int)
+               9:      6(int) Constant 9
+              10:             TypeFloat 32
+              11:             TypePointer Function 10(float)
+              13:   10(float) Constant 0
+              15:   10(float) Constant 1148846080
+              16:             TypeRayQueryProvisionalKHR
+              17:             TypePointer Function 16
+              19:             TypeAccelerationStructureKHR
+              20:             TypePointer UniformConstant 19
+        21(acc0):     20(ptr) Variable UniformConstant
+              24:      6(int) Constant 255
+              25:             TypeVector 10(float) 3
+       26(block):             TypeStruct 25(fvec3) 25(fvec3)
+              27:             TypePointer ShaderRecordBufferKHR 26(block)
+              28:     27(ptr) Variable ShaderRecordBufferKHR
+              29:             TypeInt 32 1
+              30:     29(int) Constant 1
+              31:             TypePointer ShaderRecordBufferKHR 25(fvec3)
+              35:     29(int) Constant 0
+              39:             TypeBool
+         4(main):           2 Function None 3
+               5:             Label
+     8(rayFlags):      7(ptr) Variable Function
+        12(tMin):     11(ptr) Variable Function
+        14(tMax):     11(ptr) Variable Function
+18(localRayQuery):     17(ptr) Variable Function
+                              Store 8(rayFlags) 9
+                              Store 12(tMin) 13
+                              Store 14(tMax) 15
+              22:          19 Load 21(acc0)
+              23:      6(int) Load 8(rayFlags)
+              32:     31(ptr) AccessChain 28 30
+              33:   25(fvec3) Load 32
+              34:   10(float) Load 12(tMin)
+              36:     31(ptr) AccessChain 28 35
+              37:   25(fvec3) Load 36
+              38:   10(float) Load 14(tMax)
+                              RayQueryInitializeKHR 18(localRayQuery) 22 23 24 33 34 37 38
+              40:    39(bool) RayQueryProceedKHR 18(localRayQuery)
+              41:    39(bool) LogicalNot 40
+                              SelectionMerge 43 None
+                              BranchConditional 41 42 43
+              42:               Label
+                                RayQueryTerminateKHR 18(localRayQuery)
+                                Branch 43
+              43:             Label
+                              Return
+                              FunctionEnd
diff --git a/third_party/glslang/src/Test/baseResults/spv.AnyHitShader.rahit.out b/third_party/glslang/src/Test/baseResults/spv.AnyHitShader.rahit.out
index d044b97..6bef52d 100644
--- a/third_party/glslang/src/Test/baseResults/spv.AnyHitShader.rahit.out
+++ b/third_party/glslang/src/Test/baseResults/spv.AnyHitShader.rahit.out
@@ -7,7 +7,7 @@
                               Extension  "SPV_NV_ray_tracing"
                1:             ExtInstImport  "GLSL.std.450"
                               MemoryModel Logical GLSL450
-                              EntryPoint AnyHitNV 4  "main" 11 14 20 23 26 33 36 39 42 47 50 53 58 64 67
+                              EntryPoint AnyHitKHR 4  "main" 11 14 20 23 26 33 36 39 42 47 50 53 58 64 67
                               Source GLSL 460
                               SourceExtension  "GL_NV_ray_tracing"
                               Name 4  "main"
@@ -42,21 +42,21 @@
                               Name 66  "v14"
                               Name 67  "gl_WorldToObjectNV"
                               Name 71  "incomingPayload"
-                              Decorate 11(gl_LaunchIDNV) BuiltIn LaunchIdNV
-                              Decorate 14(gl_LaunchSizeNV) BuiltIn LaunchSizeNV
+                              Decorate 11(gl_LaunchIDNV) BuiltIn LaunchIdKHR
+                              Decorate 14(gl_LaunchSizeNV) BuiltIn LaunchSizeKHR
                               Decorate 20(gl_PrimitiveID) BuiltIn PrimitiveId
                               Decorate 23(gl_InstanceID) BuiltIn InstanceId
-                              Decorate 26(gl_InstanceCustomIndexNV) BuiltIn InstanceCustomIndexNV
-                              Decorate 33(gl_WorldRayOriginNV) BuiltIn WorldRayOriginNV
-                              Decorate 36(gl_WorldRayDirectionNV) BuiltIn WorldRayDirectionNV
-                              Decorate 39(gl_ObjectRayOriginNV) BuiltIn ObjectRayOriginNV
-                              Decorate 42(gl_ObjectRayDirectionNV) BuiltIn ObjectRayDirectionNV
-                              Decorate 47(gl_RayTminNV) BuiltIn RayTminNV
-                              Decorate 50(gl_RayTmaxNV) BuiltIn RayTmaxNV
-                              Decorate 53(gl_HitTNV) BuiltIn HitTNV
-                              Decorate 58(gl_HitKindNV) BuiltIn HitKindNV
-                              Decorate 64(gl_ObjectToWorldNV) BuiltIn ObjectToWorldNV
-                              Decorate 67(gl_WorldToObjectNV) BuiltIn WorldToObjectNV
+                              Decorate 26(gl_InstanceCustomIndexNV) BuiltIn InstanceCustomIndexKHR
+                              Decorate 33(gl_WorldRayOriginNV) BuiltIn WorldRayOriginKHR
+                              Decorate 36(gl_WorldRayDirectionNV) BuiltIn WorldRayDirectionKHR
+                              Decorate 39(gl_ObjectRayOriginNV) BuiltIn ObjectRayOriginKHR
+                              Decorate 42(gl_ObjectRayDirectionNV) BuiltIn ObjectRayDirectionKHR
+                              Decorate 47(gl_RayTminNV) BuiltIn RayTminKHR
+                              Decorate 50(gl_RayTmaxNV) BuiltIn RayTmaxKHR
+                              Decorate 53(gl_HitTNV) BuiltIn HitTKHR
+                              Decorate 58(gl_HitKindNV) BuiltIn HitKindKHR
+                              Decorate 64(gl_ObjectToWorldNV) BuiltIn ObjectToWorldKHR
+                              Decorate 67(gl_WorldToObjectNV) BuiltIn WorldToObjectKHR
                               Decorate 71(incomingPayload) Location 1
                2:             TypeVoid
                3:             TypeFunction 2
@@ -94,8 +94,8 @@
 64(gl_ObjectToWorldNV):     63(ptr) Variable Input
 67(gl_WorldToObjectNV):     63(ptr) Variable Input
               69:             TypeVector 28(float) 4
-              70:             TypePointer IncomingRayPayloadNV 69(fvec4)
-71(incomingPayload):     70(ptr) Variable IncomingRayPayloadNV
+              70:             TypePointer IncomingRayPayloadKHR 69(fvec4)
+71(incomingPayload):     70(ptr) Variable IncomingRayPayloadKHR
               72:   28(float) Constant 1056964608
               73:   69(fvec4) ConstantComposite 72 72 72 72
               75:     16(int) Constant 1
@@ -153,10 +153,10 @@
                               SelectionMerge 79 None
                               BranchConditional 77 78 80
               78:               Label
-                                IgnoreIntersectionNV
+                                IgnoreIntersectionKHR
                                 Branch 79
               80:               Label
-                                TerminateRayNV
+                                TerminateRayKHR
                                 Branch 79
               79:             Label
                               Return
diff --git a/third_party/glslang/src/Test/baseResults/spv.ClosestHitShader.rchit.out b/third_party/glslang/src/Test/baseResults/spv.ClosestHitShader.rchit.out
index 482008d..cefdc50 100644
--- a/third_party/glslang/src/Test/baseResults/spv.ClosestHitShader.rchit.out
+++ b/third_party/glslang/src/Test/baseResults/spv.ClosestHitShader.rchit.out
@@ -7,7 +7,7 @@
                               Extension  "SPV_NV_ray_tracing"
                1:             ExtInstImport  "GLSL.std.450"
                               MemoryModel Logical GLSL450
-                              EntryPoint ClosestHitNV 4  "main" 11 14 20 23 26 33 36 39 42 47 50 53 58 64 67
+                              EntryPoint ClosestHitKHR 4  "main" 11 14 20 23 26 33 36 39 42 47 50 53 58 64 67
                               Source GLSL 460
                               SourceExtension  "GL_NV_ray_tracing"
                               Name 4  "main"
@@ -44,21 +44,21 @@
                               Name 71  "accNV"
                               Name 85  "localPayload"
                               Name 87  "incomingPayload"
-                              Decorate 11(gl_LaunchIDNV) BuiltIn LaunchIdNV
-                              Decorate 14(gl_LaunchSizeNV) BuiltIn LaunchSizeNV
+                              Decorate 11(gl_LaunchIDNV) BuiltIn LaunchIdKHR
+                              Decorate 14(gl_LaunchSizeNV) BuiltIn LaunchSizeKHR
                               Decorate 20(gl_PrimitiveID) BuiltIn PrimitiveId
                               Decorate 23(gl_InstanceID) BuiltIn InstanceId
-                              Decorate 26(gl_InstanceCustomIndexNV) BuiltIn InstanceCustomIndexNV
-                              Decorate 33(gl_WorldRayOriginNV) BuiltIn WorldRayOriginNV
-                              Decorate 36(gl_WorldRayDirectionNV) BuiltIn WorldRayDirectionNV
-                              Decorate 39(gl_ObjectRayOriginNV) BuiltIn ObjectRayOriginNV
-                              Decorate 42(gl_ObjectRayDirectionNV) BuiltIn ObjectRayDirectionNV
-                              Decorate 47(gl_RayTminNV) BuiltIn RayTminNV
-                              Decorate 50(gl_RayTmaxNV) BuiltIn RayTmaxNV
-                              Decorate 53(gl_HitTNV) BuiltIn HitTNV
-                              Decorate 58(gl_HitKindNV) BuiltIn HitKindNV
-                              Decorate 64(gl_ObjectToWorldNV) BuiltIn ObjectToWorldNV
-                              Decorate 67(gl_WorldToObjectNV) BuiltIn WorldToObjectNV
+                              Decorate 26(gl_InstanceCustomIndexNV) BuiltIn InstanceCustomIndexKHR
+                              Decorate 33(gl_WorldRayOriginNV) BuiltIn WorldRayOriginKHR
+                              Decorate 36(gl_WorldRayDirectionNV) BuiltIn WorldRayDirectionKHR
+                              Decorate 39(gl_ObjectRayOriginNV) BuiltIn ObjectRayOriginKHR
+                              Decorate 42(gl_ObjectRayDirectionNV) BuiltIn ObjectRayDirectionKHR
+                              Decorate 47(gl_RayTminNV) BuiltIn RayTminKHR
+                              Decorate 50(gl_RayTmaxNV) BuiltIn RayTmaxKHR
+                              Decorate 53(gl_HitTNV) BuiltIn HitTKHR
+                              Decorate 58(gl_HitKindNV) BuiltIn HitKindKHR
+                              Decorate 64(gl_ObjectToWorldNV) BuiltIn ObjectToWorldKHR
+                              Decorate 67(gl_WorldToObjectNV) BuiltIn WorldToObjectKHR
                               Decorate 71(accNV) DescriptorSet 0
                               Decorate 71(accNV) Binding 0
                               Decorate 85(localPayload) Location 0
@@ -98,7 +98,7 @@
               63:             TypePointer Input 60
 64(gl_ObjectToWorldNV):     63(ptr) Variable Input
 67(gl_WorldToObjectNV):     63(ptr) Variable Input
-              69:             TypeAccelerationStructureNV
+              69:             TypeAccelerationStructureKHR
               70:             TypePointer UniformConstant 69
        71(accNV):     70(ptr) Variable UniformConstant
               73:      6(int) Constant 0
@@ -112,10 +112,10 @@
               81:   28(float) Constant 1061158912
               82:     16(int) Constant 1
               83:             TypeVector 28(float) 4
-              84:             TypePointer RayPayloadNV 83(fvec4)
-85(localPayload):     84(ptr) Variable RayPayloadNV
-              86:             TypePointer IncomingRayPayloadNV 83(fvec4)
-87(incomingPayload):     86(ptr) Variable IncomingRayPayloadNV
+              84:             TypePointer RayPayloadKHR 83(fvec4)
+85(localPayload):     84(ptr) Variable RayPayloadKHR
+              86:             TypePointer IncomingRayPayloadKHR 83(fvec4)
+87(incomingPayload):     86(ptr) Variable IncomingRayPayloadKHR
          4(main):           2 Function None 3
                5:             Label
            9(v0):      8(ptr) Variable Function
@@ -164,6 +164,6 @@
               68:          60 Load 67(gl_WorldToObjectNV)
                               Store 66(v14) 68
               72:          69 Load 71(accNV)
-                              TraceNV 72 73 74 75 76 73 78 77 80 81 82
+                              TraceRayKHR 72 73 74 75 76 73 78 77 80 81 82
                               Return
                               FunctionEnd
diff --git a/third_party/glslang/src/Test/baseResults/spv.IntersectShader.rint.out b/third_party/glslang/src/Test/baseResults/spv.IntersectShader.rint.out
index 4fe4edf..bf99241 100644
--- a/third_party/glslang/src/Test/baseResults/spv.IntersectShader.rint.out
+++ b/third_party/glslang/src/Test/baseResults/spv.IntersectShader.rint.out
@@ -7,7 +7,7 @@
                               Extension  "SPV_NV_ray_tracing"
                1:             ExtInstImport  "GLSL.std.450"
                               MemoryModel Logical GLSL450
-                              EntryPoint IntersectionNV 4  "main" 11 14 20 23 26 33 36 39 42 47 50 56 59
+                              EntryPoint IntersectionKHR 4  "main" 11 14 20 23 26 33 36 39 42 47 50 56 59
                               Source GLSL 460
                               SourceExtension  "GL_NV_ray_tracing"
                               Name 4  "main"
@@ -38,19 +38,19 @@
                               Name 58  "v12"
                               Name 59  "gl_WorldToObjectNV"
                               Name 63  "iAttr"
-                              Decorate 11(gl_LaunchIDNV) BuiltIn LaunchIdNV
-                              Decorate 14(gl_LaunchSizeNV) BuiltIn LaunchSizeNV
+                              Decorate 11(gl_LaunchIDNV) BuiltIn LaunchIdKHR
+                              Decorate 14(gl_LaunchSizeNV) BuiltIn LaunchSizeKHR
                               Decorate 20(gl_PrimitiveID) BuiltIn PrimitiveId
                               Decorate 23(gl_InstanceID) BuiltIn InstanceId
-                              Decorate 26(gl_InstanceCustomIndexNV) BuiltIn InstanceCustomIndexNV
-                              Decorate 33(gl_WorldRayOriginNV) BuiltIn WorldRayOriginNV
-                              Decorate 36(gl_WorldRayDirectionNV) BuiltIn WorldRayDirectionNV
-                              Decorate 39(gl_ObjectRayOriginNV) BuiltIn ObjectRayOriginNV
-                              Decorate 42(gl_ObjectRayDirectionNV) BuiltIn ObjectRayDirectionNV
-                              Decorate 47(gl_RayTminNV) BuiltIn RayTminNV
-                              Decorate 50(gl_RayTmaxNV) BuiltIn RayTmaxNV
-                              Decorate 56(gl_ObjectToWorldNV) BuiltIn ObjectToWorldNV
-                              Decorate 59(gl_WorldToObjectNV) BuiltIn WorldToObjectNV
+                              Decorate 26(gl_InstanceCustomIndexNV) BuiltIn InstanceCustomIndexKHR
+                              Decorate 33(gl_WorldRayOriginNV) BuiltIn WorldRayOriginKHR
+                              Decorate 36(gl_WorldRayDirectionNV) BuiltIn WorldRayDirectionKHR
+                              Decorate 39(gl_ObjectRayOriginNV) BuiltIn ObjectRayOriginKHR
+                              Decorate 42(gl_ObjectRayDirectionNV) BuiltIn ObjectRayDirectionKHR
+                              Decorate 47(gl_RayTminNV) BuiltIn RayTminKHR
+                              Decorate 50(gl_RayTmaxNV) BuiltIn RayTmaxKHR
+                              Decorate 56(gl_ObjectToWorldNV) BuiltIn ObjectToWorldKHR
+                              Decorate 59(gl_WorldToObjectNV) BuiltIn WorldToObjectKHR
                2:             TypeVoid
                3:             TypeFunction 2
                6:             TypeInt 32 0
@@ -83,8 +83,8 @@
 56(gl_ObjectToWorldNV):     55(ptr) Variable Input
 59(gl_WorldToObjectNV):     55(ptr) Variable Input
               61:             TypeVector 28(float) 4
-              62:             TypePointer HitAttributeNV 61(fvec4)
-       63(iAttr):     62(ptr) Variable HitAttributeNV
+              62:             TypePointer HitAttributeKHR 61(fvec4)
+       63(iAttr):     62(ptr) Variable HitAttributeKHR
               64:   28(float) Constant 1056964608
               65:   28(float) Constant 0
               66:   28(float) Constant 1065353216
@@ -133,6 +133,6 @@
               60:          52 Load 59(gl_WorldToObjectNV)
                               Store 58(v12) 60
                               Store 63(iAttr) 67
-              70:    69(bool) ReportIntersectionNV 64 68
+              70:    69(bool) ReportIntersectionKHR 64 68
                               Return
                               FunctionEnd
diff --git a/third_party/glslang/src/Test/baseResults/spv.MissShader.rmiss.out b/third_party/glslang/src/Test/baseResults/spv.MissShader.rmiss.out
index 37fd3bd..b811044 100644
--- a/third_party/glslang/src/Test/baseResults/spv.MissShader.rmiss.out
+++ b/third_party/glslang/src/Test/baseResults/spv.MissShader.rmiss.out
@@ -7,7 +7,7 @@
                               Extension  "SPV_NV_ray_tracing"
                1:             ExtInstImport  "GLSL.std.450"
                               MemoryModel Logical GLSL450
-                              EntryPoint MissNV 4  "main" 11 14 21 24 27 30 35 38
+                              EntryPoint MissKHR 4  "main" 11 14 21 24 27 30 35 38
                               Source GLSL 460
                               SourceExtension  "GL_NV_ray_tracing"
                               Name 4  "main"
@@ -30,14 +30,14 @@
                               Name 42  "accNV"
                               Name 57  "localPayload"
                               Name 59  "incomingPayload"
-                              Decorate 11(gl_LaunchIDNV) BuiltIn LaunchIdNV
-                              Decorate 14(gl_LaunchSizeNV) BuiltIn LaunchSizeNV
-                              Decorate 21(gl_WorldRayOriginNV) BuiltIn WorldRayOriginNV
-                              Decorate 24(gl_WorldRayDirectionNV) BuiltIn WorldRayDirectionNV
-                              Decorate 27(gl_ObjectRayOriginNV) BuiltIn ObjectRayOriginNV
-                              Decorate 30(gl_ObjectRayDirectionNV) BuiltIn ObjectRayDirectionNV
-                              Decorate 35(gl_RayTminNV) BuiltIn RayTminNV
-                              Decorate 38(gl_RayTmaxNV) BuiltIn RayTmaxNV
+                              Decorate 11(gl_LaunchIDNV) BuiltIn LaunchIdKHR
+                              Decorate 14(gl_LaunchSizeNV) BuiltIn LaunchSizeKHR
+                              Decorate 21(gl_WorldRayOriginNV) BuiltIn WorldRayOriginKHR
+                              Decorate 24(gl_WorldRayDirectionNV) BuiltIn WorldRayDirectionKHR
+                              Decorate 27(gl_ObjectRayOriginNV) BuiltIn ObjectRayOriginKHR
+                              Decorate 30(gl_ObjectRayDirectionNV) BuiltIn ObjectRayDirectionKHR
+                              Decorate 35(gl_RayTminNV) BuiltIn RayTminKHR
+                              Decorate 38(gl_RayTmaxNV) BuiltIn RayTmaxKHR
                               Decorate 42(accNV) DescriptorSet 0
                               Decorate 42(accNV) Binding 0
                               Decorate 57(localPayload) Location 0
@@ -62,7 +62,7 @@
               34:             TypePointer Input 16(float)
 35(gl_RayTminNV):     34(ptr) Variable Input
 38(gl_RayTmaxNV):     34(ptr) Variable Input
-              40:             TypeAccelerationStructureNV
+              40:             TypeAccelerationStructureKHR
               41:             TypePointer UniformConstant 40
        42(accNV):     41(ptr) Variable UniformConstant
               44:      6(int) Constant 0
@@ -77,10 +77,10 @@
               53:             TypeInt 32 1
               54:     53(int) Constant 1
               55:             TypeVector 16(float) 4
-              56:             TypePointer RayPayloadNV 55(fvec4)
-57(localPayload):     56(ptr) Variable RayPayloadNV
-              58:             TypePointer IncomingRayPayloadNV 55(fvec4)
-59(incomingPayload):     58(ptr) Variable IncomingRayPayloadNV
+              56:             TypePointer RayPayloadKHR 55(fvec4)
+57(localPayload):     56(ptr) Variable RayPayloadKHR
+              58:             TypePointer IncomingRayPayloadKHR 55(fvec4)
+59(incomingPayload):     58(ptr) Variable IncomingRayPayloadKHR
          4(main):           2 Function None 3
                5:             Label
            9(v0):      8(ptr) Variable Function
@@ -108,6 +108,6 @@
               39:   16(float) Load 38(gl_RayTmaxNV)
                               Store 37(v7) 39
               43:          40 Load 42(accNV)
-                              TraceNV 43 44 45 46 47 44 49 48 51 52 54
+                              TraceRayKHR 43 44 45 46 47 44 49 48 51 52 54
                               Return
                               FunctionEnd
diff --git a/third_party/glslang/src/Test/baseResults/spv.Operations.frag.out b/third_party/glslang/src/Test/baseResults/spv.Operations.frag.out
index 77f345a..ad54f6c 100644
--- a/third_party/glslang/src/Test/baseResults/spv.Operations.frag.out
+++ b/third_party/glslang/src/Test/baseResults/spv.Operations.frag.out
@@ -1,12 +1,12 @@
 spv.Operations.frag
 // Module Version 10000
 // Generated by (magic number): 80008
-// Id's are bound by 540
+// Id's are bound by 583
 
                               Capability Shader
                1:             ExtInstImport  "GLSL.std.450"
                               MemoryModel Logical GLSL450
-                              EntryPoint Fragment 4  "main" 11 22 220 296 493 534 539
+                              EntryPoint Fragment 4  "main" 11 22 220 296 314 539 580
                               ExecutionMode 4 OriginUpperLeft
                               Source GLSL 450
                               Name 4  "main"
@@ -20,18 +20,23 @@
                               Name 220  "uf"
                               Name 293  "u"
                               Name 296  "uui"
-                              Name 313  "b"
-                              Name 350  "ub42"
-                              Name 493  "FragColor"
-                              Name 511  "m1"
-                              Name 518  "m2"
-                              Name 534  "uiv4"
-                              Name 536  "ub"
-                              Name 539  "uuv4"
+                              Name 314  "uuv4"
+                              Name 321  "msb"
+                              Name 323  "swizzleTemp"
+                              Name 324  "lsb"
+                              Name 325  "swizzleTemp"
+                              Name 326  "ResType"
+                              Name 359  "b"
+                              Name 396  "ub42"
+                              Name 539  "FragColor"
+                              Name 557  "m1"
+                              Name 564  "m2"
+                              Name 580  "uiv4"
+                              Name 582  "ub"
                               Decorate 22(ui) Flat
                               Decorate 296(uui) Flat
-                              Decorate 534(uiv4) Flat
-                              Decorate 539(uuv4) Flat
+                              Decorate 314(uuv4) Flat
+                              Decorate 580(uiv4) Flat
                2:             TypeVoid
                3:             TypeFunction 2
                6:             TypeFloat 32
@@ -55,35 +60,41 @@
              292:             TypePointer Function 141(int)
              295:             TypePointer Input 141(int)
         296(uui):    295(ptr) Variable Input
-             312:             TypePointer Function 186(bool)
-       350(ub42):    188(ptr) Variable Private
-             406:     18(int) Constant 2
-             413:     18(int) Constant 1
-             443:             TypeVector 6(float) 3
-             462:    6(float) Constant 1073741824
-             469:    6(float) Constant 1065353216
-             474:     18(int) Constant 66
-             480:     18(int) Constant 17
-             492:             TypePointer Output 7(fvec4)
-  493(FragColor):    492(ptr) Variable Output
-             509:             TypeMatrix 7(fvec4) 4
-             510:             TypePointer Function 509
-             512:    6(float) Constant 0
-             513:    7(fvec4) ConstantComposite 469 512 512 512
-             514:    7(fvec4) ConstantComposite 512 469 512 512
-             515:    7(fvec4) ConstantComposite 512 512 469 512
-             516:    7(fvec4) ConstantComposite 512 512 512 469
-             517:         509 ConstantComposite 513 514 515 516
-             519:    7(fvec4) ConstantComposite 512 512 512 512
-             520:         509 ConstantComposite 519 519 519 519
-             532:             TypeVector 18(int) 4
-             533:             TypePointer Input 532(ivec4)
-       534(uiv4):    533(ptr) Variable Input
-             535:             TypePointer Private 186(bool)
-         536(ub):    535(ptr) Variable Private
-             537:             TypeVector 141(int) 4
-             538:             TypePointer Input 537(ivec4)
-       539(uuv4):    538(ptr) Variable Input
+             312:             TypeVector 141(int) 4
+             313:             TypePointer Input 312(ivec4)
+       314(uuv4):    313(ptr) Variable Input
+             315:             TypeVector 141(int) 3
+             320:             TypePointer Function 312(ivec4)
+             322:             TypePointer Function 315(ivec3)
+    326(ResType):             TypeStruct 315(ivec3) 315(ivec3)
+             338:    141(int) Constant 1
+             342:    141(int) Constant 2
+             358:             TypePointer Function 186(bool)
+       396(ub42):    188(ptr) Variable Private
+             452:     18(int) Constant 2
+             459:     18(int) Constant 1
+             489:             TypeVector 6(float) 3
+             508:    6(float) Constant 1073741824
+             515:    6(float) Constant 1065353216
+             520:     18(int) Constant 66
+             526:     18(int) Constant 17
+             538:             TypePointer Output 7(fvec4)
+  539(FragColor):    538(ptr) Variable Output
+             555:             TypeMatrix 7(fvec4) 4
+             556:             TypePointer Function 555
+             558:    6(float) Constant 0
+             559:    7(fvec4) ConstantComposite 515 558 558 558
+             560:    7(fvec4) ConstantComposite 558 515 558 558
+             561:    7(fvec4) ConstantComposite 558 558 515 558
+             562:    7(fvec4) ConstantComposite 558 558 558 515
+             563:         555 ConstantComposite 559 560 561 562
+             565:    7(fvec4) ConstantComposite 558 558 558 558
+             566:         555 ConstantComposite 565 565 565 565
+             578:             TypeVector 18(int) 4
+             579:             TypePointer Input 578(ivec4)
+       580(uiv4):    579(ptr) Variable Input
+             581:             TypePointer Private 186(bool)
+         582(ub):    581(ptr) Variable Private
          4(main):           2 Function None 3
                5:             Label
             9(v):      8(ptr) Variable Function
@@ -91,11 +102,15 @@
 155(swizzleTemp):      8(ptr) Variable Function
           196(f):    143(ptr) Variable Function
           293(u):    292(ptr) Variable Function
-          313(b):    312(ptr) Variable Function
-             495:      8(ptr) Variable Function
-         511(m1):    510(ptr) Variable Function
-         518(m2):    510(ptr) Variable Function
-             522:    510(ptr) Variable Function
+        321(msb):    320(ptr) Variable Function
+323(swizzleTemp):    322(ptr) Variable Function
+        324(lsb):    320(ptr) Variable Function
+325(swizzleTemp):    322(ptr) Variable Function
+          359(b):    358(ptr) Variable Function
+             541:      8(ptr) Variable Function
+         557(m1):    556(ptr) Variable Function
+         564(m2):    556(ptr) Variable Function
+             568:    556(ptr) Variable Function
               12:    7(fvec4) Load 11(uv4)
               13:    7(fvec4) ExtInst 1(GLSL.std.450) 11(Radians) 12
                               Store 9(v) 13
@@ -437,277 +452,316 @@
              310:    141(int) Load 293(u)
              311:    141(int) IAdd 310 309
                               Store 293(u) 311
-             314:    6(float) Load 220(uf)
-             315:   186(bool) IsNan 314
-                              Store 313(b) 315
-             316:    6(float) Load 196(f)
-             317:   186(bool) IsInf 316
-                              Store 313(b) 317
-             318:    7(fvec4) Load 9(v)
-             319:    7(fvec4) Load 11(uv4)
-             320:  187(bvec4) FOrdLessThan 318 319
-             321:   186(bool) Any 320
-                              Store 313(b) 321
-             322:   186(bool) Load 313(b)
-                              SelectionMerge 324 None
-                              BranchConditional 322 323 324
-             323:               Label
-             325:    7(fvec4)   Load 9(v)
-             326:    7(fvec4)   Load 11(uv4)
-             327:  187(bvec4)   FOrdLessThanEqual 325 326
-             328:   186(bool)   Any 327
-                                Branch 324
-             324:             Label
-             329:   186(bool) Phi 322 5 328 323
-                              Store 313(b) 329
-             330:   186(bool) Load 313(b)
-                              SelectionMerge 332 None
-                              BranchConditional 330 331 332
-             331:               Label
-             333:    7(fvec4)   Load 9(v)
-             334:    7(fvec4)   Load 11(uv4)
-             335:  187(bvec4)   FOrdGreaterThan 333 334
-             336:   186(bool)   Any 335
-                                Branch 332
-             332:             Label
-             337:   186(bool) Phi 330 324 336 331
-                              Store 313(b) 337
-             338:   186(bool) Load 313(b)
-                              SelectionMerge 340 None
-                              BranchConditional 338 339 340
-             339:               Label
-             341:    7(fvec4)   Load 9(v)
-             342:    7(fvec4)   Load 11(uv4)
-             343:  187(bvec4)   FOrdGreaterThanEqual 341 342
-             344:   186(bool)   Any 343
-                                Branch 340
-             340:             Label
-             345:   186(bool) Phi 338 332 344 339
-                              Store 313(b) 345
-             346:   186(bool) Load 313(b)
-                              SelectionMerge 348 None
-                              BranchConditional 346 347 348
-             347:               Label
-             349:  187(bvec4)   Load 189(ub41)
-             351:  187(bvec4)   Load 350(ub42)
-             352:  187(bvec4)   LogicalEqual 349 351
-             353:   186(bool)   Any 352
-                                Branch 348
-             348:             Label
-             354:   186(bool) Phi 346 340 353 347
-                              Store 313(b) 354
-             355:   186(bool) Load 313(b)
-                              SelectionMerge 357 None
-                              BranchConditional 355 356 357
-             356:               Label
-             358:  187(bvec4)   Load 189(ub41)
-             359:  187(bvec4)   Load 350(ub42)
-             360:  187(bvec4)   LogicalNotEqual 358 359
-             361:   186(bool)   Any 360
-                                Branch 357
-             357:             Label
-             362:   186(bool) Phi 355 348 361 356
-                              Store 313(b) 362
-             363:   186(bool) Load 313(b)
-             364:  187(bvec4) Load 189(ub41)
-             365:   186(bool) Any 364
-             366:   186(bool) LogicalAnd 363 365
-                              Store 313(b) 366
-             367:   186(bool) Load 313(b)
-             368:  187(bvec4) Load 189(ub41)
-             369:   186(bool) All 368
-             370:   186(bool) LogicalAnd 367 369
-                              Store 313(b) 370
-             371:   186(bool) Load 313(b)
-                              SelectionMerge 373 None
-                              BranchConditional 371 372 373
-             372:               Label
-             374:  187(bvec4)   Load 189(ub41)
-             375:  187(bvec4)   LogicalNot 374
-             376:   186(bool)   Any 375
-                                Branch 373
-             373:             Label
-             377:   186(bool) Phi 371 357 376 372
-                              Store 313(b) 377
-             378:     18(int) Load 20(i)
-             379:     18(int) Load 22(ui)
-             380:     18(int) IAdd 378 379
-             381:     18(int) Load 20(i)
-             382:     18(int) IMul 380 381
-             383:     18(int) Load 22(ui)
-             384:     18(int) ISub 382 383
-             385:     18(int) Load 20(i)
-             386:     18(int) SDiv 384 385
-                              Store 20(i) 386
-             387:     18(int) Load 20(i)
-             388:     18(int) Load 22(ui)
-             389:     18(int) SMod 387 388
-                              Store 20(i) 389
-             390:     18(int) Load 20(i)
-             391:     18(int) Load 22(ui)
-             392:   186(bool) IEqual 390 391
-             393:   186(bool) LogicalNot 392
-                              SelectionMerge 395 None
-                              BranchConditional 393 394 395
-             394:               Label
-             396:     18(int)   Load 20(i)
-             397:     18(int)   Load 22(ui)
-             398:   186(bool)   INotEqual 396 397
-                                SelectionMerge 400 None
-                                BranchConditional 398 399 400
-             399:                 Label
-             401:     18(int)     Load 20(i)
-             402:     18(int)     Load 22(ui)
-             403:   186(bool)     IEqual 401 402
-                                  Branch 400
-             400:               Label
-             404:   186(bool)   Phi 398 394 403 399
-             405:     18(int)   Load 20(i)
-             407:   186(bool)   INotEqual 405 406
-             408:   186(bool)   LogicalNotEqual 404 407
-                                Branch 395
-             395:             Label
-             409:   186(bool) Phi 392 373 408 400
-                              SelectionMerge 411 None
-                              BranchConditional 409 410 411
-             410:               Label
-             412:     18(int)   Load 20(i)
-             414:     18(int)   IAdd 412 413
-                                Store 20(i) 414
-                                Branch 411
-             411:             Label
-             415:    6(float) Load 220(uf)
-             416:    6(float) Load 220(uf)
-             417:    6(float) FAdd 415 416
-             418:    6(float) Load 220(uf)
-             419:    6(float) FMul 417 418
-             420:    6(float) Load 220(uf)
-             421:    6(float) FSub 419 420
-             422:    6(float) Load 220(uf)
-             423:    6(float) FDiv 421 422
-                              Store 196(f) 423
-             424:    7(fvec4) Load 9(v)
-             425:    6(float) ExtInst 1(GLSL.std.450) 66(Length) 424
-             426:    6(float) Load 196(f)
-             427:    6(float) FAdd 426 425
-                              Store 196(f) 427
-             428:    7(fvec4) Load 9(v)
-             429:    7(fvec4) Load 9(v)
-             430:    6(float) ExtInst 1(GLSL.std.450) 67(Distance) 428 429
-             431:    6(float) Load 196(f)
-             432:    6(float) FAdd 431 430
-                              Store 196(f) 432
-             433:    7(fvec4) Load 9(v)
-             434:    7(fvec4) Load 9(v)
-             435:    6(float) Dot 433 434
-             436:    6(float) Load 196(f)
-             437:    6(float) FAdd 436 435
-                              Store 196(f) 437
-             438:    6(float) Load 196(f)
-             439:    6(float) Load 220(uf)
-             440:    6(float) FMul 438 439
-             441:    6(float) Load 196(f)
-             442:    6(float) FAdd 441 440
-                              Store 196(f) 442
-             444:    7(fvec4) Load 9(v)
-             445:  443(fvec3) VectorShuffle 444 444 0 1 2
-             446:    7(fvec4) Load 9(v)
-             447:  443(fvec3) VectorShuffle 446 446 0 1 2
-             448:  443(fvec3) ExtInst 1(GLSL.std.450) 68(Cross) 445 447
-             449:    6(float) CompositeExtract 448 0
-             450:    6(float) Load 196(f)
-             451:    6(float) FAdd 450 449
-                              Store 196(f) 451
-             452:    6(float) Load 196(f)
-             453:    6(float) Load 220(uf)
-             454:   186(bool) FOrdEqual 452 453
-             455:   186(bool) LogicalNot 454
+             316:  312(ivec4) Load 314(uuv4)
+             317:  315(ivec3) VectorShuffle 316 316 0 1 2
+             318:  312(ivec4) Load 314(uuv4)
+             319:  315(ivec3) VectorShuffle 318 318 0 1 2
+             327:326(ResType) UMulExtended 317 319
+             328:  315(ivec3) CompositeExtract 327 0
+                              Store 325(swizzleTemp) 328
+             329:  315(ivec3) CompositeExtract 327 1
+                              Store 323(swizzleTemp) 329
+             330:  315(ivec3) Load 323(swizzleTemp)
+             331:  312(ivec4) Load 321(msb)
+             332:  312(ivec4) VectorShuffle 331 330 4 5 6 3
+                              Store 321(msb) 332
+             333:  315(ivec3) Load 325(swizzleTemp)
+             334:  312(ivec4) Load 324(lsb)
+             335:  312(ivec4) VectorShuffle 334 333 4 5 6 3
+                              Store 324(lsb) 335
+             336:    292(ptr) AccessChain 321(msb) 142
+             337:    141(int) Load 336
+             339:    292(ptr) AccessChain 321(msb) 338
+             340:    141(int) Load 339
+             341:    141(int) IAdd 337 340
+             343:    292(ptr) AccessChain 321(msb) 342
+             344:    141(int) Load 343
+             345:    141(int) IAdd 341 344
+             346:    141(int) Load 293(u)
+             347:    141(int) IAdd 346 345
+                              Store 293(u) 347
+             348:    292(ptr) AccessChain 324(lsb) 142
+             349:    141(int) Load 348
+             350:    292(ptr) AccessChain 324(lsb) 338
+             351:    141(int) Load 350
+             352:    141(int) IAdd 349 351
+             353:    292(ptr) AccessChain 324(lsb) 342
+             354:    141(int) Load 353
+             355:    141(int) IAdd 352 354
+             356:    141(int) Load 293(u)
+             357:    141(int) IAdd 356 355
+                              Store 293(u) 357
+             360:    6(float) Load 220(uf)
+             361:   186(bool) IsNan 360
+                              Store 359(b) 361
+             362:    6(float) Load 196(f)
+             363:   186(bool) IsInf 362
+                              Store 359(b) 363
+             364:    7(fvec4) Load 9(v)
+             365:    7(fvec4) Load 11(uv4)
+             366:  187(bvec4) FOrdLessThan 364 365
+             367:   186(bool) Any 366
+                              Store 359(b) 367
+             368:   186(bool) Load 359(b)
+                              SelectionMerge 370 None
+                              BranchConditional 368 369 370
+             369:               Label
+             371:    7(fvec4)   Load 9(v)
+             372:    7(fvec4)   Load 11(uv4)
+             373:  187(bvec4)   FOrdLessThanEqual 371 372
+             374:   186(bool)   Any 373
+                                Branch 370
+             370:             Label
+             375:   186(bool) Phi 368 5 374 369
+                              Store 359(b) 375
+             376:   186(bool) Load 359(b)
+                              SelectionMerge 378 None
+                              BranchConditional 376 377 378
+             377:               Label
+             379:    7(fvec4)   Load 9(v)
+             380:    7(fvec4)   Load 11(uv4)
+             381:  187(bvec4)   FOrdGreaterThan 379 380
+             382:   186(bool)   Any 381
+                                Branch 378
+             378:             Label
+             383:   186(bool) Phi 376 370 382 377
+                              Store 359(b) 383
+             384:   186(bool) Load 359(b)
+                              SelectionMerge 386 None
+                              BranchConditional 384 385 386
+             385:               Label
+             387:    7(fvec4)   Load 9(v)
+             388:    7(fvec4)   Load 11(uv4)
+             389:  187(bvec4)   FOrdGreaterThanEqual 387 388
+             390:   186(bool)   Any 389
+                                Branch 386
+             386:             Label
+             391:   186(bool) Phi 384 378 390 385
+                              Store 359(b) 391
+             392:   186(bool) Load 359(b)
+                              SelectionMerge 394 None
+                              BranchConditional 392 393 394
+             393:               Label
+             395:  187(bvec4)   Load 189(ub41)
+             397:  187(bvec4)   Load 396(ub42)
+             398:  187(bvec4)   LogicalEqual 395 397
+             399:   186(bool)   Any 398
+                                Branch 394
+             394:             Label
+             400:   186(bool) Phi 392 386 399 393
+                              Store 359(b) 400
+             401:   186(bool) Load 359(b)
+                              SelectionMerge 403 None
+                              BranchConditional 401 402 403
+             402:               Label
+             404:  187(bvec4)   Load 189(ub41)
+             405:  187(bvec4)   Load 396(ub42)
+             406:  187(bvec4)   LogicalNotEqual 404 405
+             407:   186(bool)   Any 406
+                                Branch 403
+             403:             Label
+             408:   186(bool) Phi 401 394 407 402
+                              Store 359(b) 408
+             409:   186(bool) Load 359(b)
+             410:  187(bvec4) Load 189(ub41)
+             411:   186(bool) Any 410
+             412:   186(bool) LogicalAnd 409 411
+                              Store 359(b) 412
+             413:   186(bool) Load 359(b)
+             414:  187(bvec4) Load 189(ub41)
+             415:   186(bool) All 414
+             416:   186(bool) LogicalAnd 413 415
+                              Store 359(b) 416
+             417:   186(bool) Load 359(b)
+                              SelectionMerge 419 None
+                              BranchConditional 417 418 419
+             418:               Label
+             420:  187(bvec4)   Load 189(ub41)
+             421:  187(bvec4)   LogicalNot 420
+             422:   186(bool)   Any 421
+                                Branch 419
+             419:             Label
+             423:   186(bool) Phi 417 403 422 418
+                              Store 359(b) 423
+             424:     18(int) Load 20(i)
+             425:     18(int) Load 22(ui)
+             426:     18(int) IAdd 424 425
+             427:     18(int) Load 20(i)
+             428:     18(int) IMul 426 427
+             429:     18(int) Load 22(ui)
+             430:     18(int) ISub 428 429
+             431:     18(int) Load 20(i)
+             432:     18(int) SDiv 430 431
+                              Store 20(i) 432
+             433:     18(int) Load 20(i)
+             434:     18(int) Load 22(ui)
+             435:     18(int) SMod 433 434
+                              Store 20(i) 435
+             436:     18(int) Load 20(i)
+             437:     18(int) Load 22(ui)
+             438:   186(bool) IEqual 436 437
+             439:   186(bool) LogicalNot 438
+                              SelectionMerge 441 None
+                              BranchConditional 439 440 441
+             440:               Label
+             442:     18(int)   Load 20(i)
+             443:     18(int)   Load 22(ui)
+             444:   186(bool)   INotEqual 442 443
+                                SelectionMerge 446 None
+                                BranchConditional 444 445 446
+             445:                 Label
+             447:     18(int)     Load 20(i)
+             448:     18(int)     Load 22(ui)
+             449:   186(bool)     IEqual 447 448
+                                  Branch 446
+             446:               Label
+             450:   186(bool)   Phi 444 440 449 445
+             451:     18(int)   Load 20(i)
+             453:   186(bool)   INotEqual 451 452
+             454:   186(bool)   LogicalNotEqual 450 453
+                                Branch 441
+             441:             Label
+             455:   186(bool) Phi 438 419 454 446
                               SelectionMerge 457 None
                               BranchConditional 455 456 457
              456:               Label
-             458:    6(float)   Load 196(f)
-             459:    6(float)   Load 220(uf)
-             460:   186(bool)   FOrdNotEqual 458 459
-             461:    6(float)   Load 196(f)
-             463:   186(bool)   FOrdNotEqual 461 462
-             464:   186(bool)   LogicalAnd 460 463
+             458:     18(int)   Load 20(i)
+             460:     18(int)   IAdd 458 459
+                                Store 20(i) 460
                                 Branch 457
              457:             Label
-             465:   186(bool) Phi 454 411 464 456
-                              SelectionMerge 467 None
-                              BranchConditional 465 466 467
-             466:               Label
-             468:    6(float)   Load 196(f)
-             470:    6(float)   FAdd 468 469
-                                Store 196(f) 470
-                                Branch 467
-             467:             Label
-             471:     18(int) Load 22(ui)
-             472:     18(int) Load 20(i)
-             473:     18(int) BitwiseAnd 472 471
-                              Store 20(i) 473
-             475:     18(int) Load 20(i)
-             476:     18(int) BitwiseOr 475 474
-                              Store 20(i) 476
-             477:     18(int) Load 22(ui)
-             478:     18(int) Load 20(i)
-             479:     18(int) BitwiseXor 478 477
-                              Store 20(i) 479
-             481:     18(int) Load 20(i)
-             482:     18(int) SMod 481 480
-                              Store 20(i) 482
-             483:     18(int) Load 20(i)
-             484:     18(int) ShiftRightArithmetic 483 406
-                              Store 20(i) 484
-             485:     18(int) Load 22(ui)
-             486:     18(int) Load 20(i)
-             487:     18(int) ShiftLeftLogical 486 485
-                              Store 20(i) 487
-             488:     18(int) Load 20(i)
-             489:     18(int) Not 488
-                              Store 20(i) 489
-             490:   186(bool) Load 313(b)
-             491:   186(bool) LogicalNot 490
-                              Store 313(b) 491
-             494:   186(bool) Load 313(b)
-                              SelectionMerge 497 None
-                              BranchConditional 494 496 506
-             496:               Label
-             498:     18(int)   Load 20(i)
-             499:    6(float)   ConvertSToF 498
-             500:    7(fvec4)   CompositeConstruct 499 499 499 499
-             501:    6(float)   Load 196(f)
-             502:    7(fvec4)   CompositeConstruct 501 501 501 501
-             503:    7(fvec4)   FAdd 500 502
-             504:    7(fvec4)   Load 9(v)
-             505:    7(fvec4)   FAdd 503 504
-                                Store 495 505
-                                Branch 497
-             506:               Label
-             507:    7(fvec4)   Load 9(v)
-                                Store 495 507
-                                Branch 497
-             497:             Label
-             508:    7(fvec4) Load 495
-                              Store 493(FragColor) 508
-                              Store 511(m1) 517
-                              Store 518(m2) 520
-             521:   186(bool) Load 313(b)
-                              SelectionMerge 524 None
-                              BranchConditional 521 523 526
-             523:               Label
-             525:         509   Load 511(m1)
-                                Store 522 525
-                                Branch 524
-             526:               Label
-             527:         509   Load 518(m2)
-                                Store 522 527
-                                Branch 524
-             524:             Label
-             528:      8(ptr) AccessChain 522 413
-             529:    7(fvec4) Load 528
-             530:    7(fvec4) Load 493(FragColor)
-             531:    7(fvec4) FAdd 530 529
-                              Store 493(FragColor) 531
+             461:    6(float) Load 220(uf)
+             462:    6(float) Load 220(uf)
+             463:    6(float) FAdd 461 462
+             464:    6(float) Load 220(uf)
+             465:    6(float) FMul 463 464
+             466:    6(float) Load 220(uf)
+             467:    6(float) FSub 465 466
+             468:    6(float) Load 220(uf)
+             469:    6(float) FDiv 467 468
+                              Store 196(f) 469
+             470:    7(fvec4) Load 9(v)
+             471:    6(float) ExtInst 1(GLSL.std.450) 66(Length) 470
+             472:    6(float) Load 196(f)
+             473:    6(float) FAdd 472 471
+                              Store 196(f) 473
+             474:    7(fvec4) Load 9(v)
+             475:    7(fvec4) Load 9(v)
+             476:    6(float) ExtInst 1(GLSL.std.450) 67(Distance) 474 475
+             477:    6(float) Load 196(f)
+             478:    6(float) FAdd 477 476
+                              Store 196(f) 478
+             479:    7(fvec4) Load 9(v)
+             480:    7(fvec4) Load 9(v)
+             481:    6(float) Dot 479 480
+             482:    6(float) Load 196(f)
+             483:    6(float) FAdd 482 481
+                              Store 196(f) 483
+             484:    6(float) Load 196(f)
+             485:    6(float) Load 220(uf)
+             486:    6(float) FMul 484 485
+             487:    6(float) Load 196(f)
+             488:    6(float) FAdd 487 486
+                              Store 196(f) 488
+             490:    7(fvec4) Load 9(v)
+             491:  489(fvec3) VectorShuffle 490 490 0 1 2
+             492:    7(fvec4) Load 9(v)
+             493:  489(fvec3) VectorShuffle 492 492 0 1 2
+             494:  489(fvec3) ExtInst 1(GLSL.std.450) 68(Cross) 491 493
+             495:    6(float) CompositeExtract 494 0
+             496:    6(float) Load 196(f)
+             497:    6(float) FAdd 496 495
+                              Store 196(f) 497
+             498:    6(float) Load 196(f)
+             499:    6(float) Load 220(uf)
+             500:   186(bool) FOrdEqual 498 499
+             501:   186(bool) LogicalNot 500
+                              SelectionMerge 503 None
+                              BranchConditional 501 502 503
+             502:               Label
+             504:    6(float)   Load 196(f)
+             505:    6(float)   Load 220(uf)
+             506:   186(bool)   FOrdNotEqual 504 505
+             507:    6(float)   Load 196(f)
+             509:   186(bool)   FOrdNotEqual 507 508
+             510:   186(bool)   LogicalAnd 506 509
+                                Branch 503
+             503:             Label
+             511:   186(bool) Phi 500 457 510 502
+                              SelectionMerge 513 None
+                              BranchConditional 511 512 513
+             512:               Label
+             514:    6(float)   Load 196(f)
+             516:    6(float)   FAdd 514 515
+                                Store 196(f) 516
+                                Branch 513
+             513:             Label
+             517:     18(int) Load 22(ui)
+             518:     18(int) Load 20(i)
+             519:     18(int) BitwiseAnd 518 517
+                              Store 20(i) 519
+             521:     18(int) Load 20(i)
+             522:     18(int) BitwiseOr 521 520
+                              Store 20(i) 522
+             523:     18(int) Load 22(ui)
+             524:     18(int) Load 20(i)
+             525:     18(int) BitwiseXor 524 523
+                              Store 20(i) 525
+             527:     18(int) Load 20(i)
+             528:     18(int) SMod 527 526
+                              Store 20(i) 528
+             529:     18(int) Load 20(i)
+             530:     18(int) ShiftRightArithmetic 529 452
+                              Store 20(i) 530
+             531:     18(int) Load 22(ui)
+             532:     18(int) Load 20(i)
+             533:     18(int) ShiftLeftLogical 532 531
+                              Store 20(i) 533
+             534:     18(int) Load 20(i)
+             535:     18(int) Not 534
+                              Store 20(i) 535
+             536:   186(bool) Load 359(b)
+             537:   186(bool) LogicalNot 536
+                              Store 359(b) 537
+             540:   186(bool) Load 359(b)
+                              SelectionMerge 543 None
+                              BranchConditional 540 542 552
+             542:               Label
+             544:     18(int)   Load 20(i)
+             545:    6(float)   ConvertSToF 544
+             546:    7(fvec4)   CompositeConstruct 545 545 545 545
+             547:    6(float)   Load 196(f)
+             548:    7(fvec4)   CompositeConstruct 547 547 547 547
+             549:    7(fvec4)   FAdd 546 548
+             550:    7(fvec4)   Load 9(v)
+             551:    7(fvec4)   FAdd 549 550
+                                Store 541 551
+                                Branch 543
+             552:               Label
+             553:    7(fvec4)   Load 9(v)
+                                Store 541 553
+                                Branch 543
+             543:             Label
+             554:    7(fvec4) Load 541
+                              Store 539(FragColor) 554
+                              Store 557(m1) 563
+                              Store 564(m2) 566
+             567:   186(bool) Load 359(b)
+                              SelectionMerge 570 None
+                              BranchConditional 567 569 572
+             569:               Label
+             571:         555   Load 557(m1)
+                                Store 568 571
+                                Branch 570
+             572:               Label
+             573:         555   Load 564(m2)
+                                Store 568 573
+                                Branch 570
+             570:             Label
+             574:      8(ptr) AccessChain 568 459
+             575:    7(fvec4) Load 574
+             576:    7(fvec4) Load 539(FragColor)
+             577:    7(fvec4) FAdd 576 575
+                              Store 539(FragColor) 577
                               Return
                               FunctionEnd
diff --git a/third_party/glslang/src/Test/baseResults/spv.RayCallable.rcall.out b/third_party/glslang/src/Test/baseResults/spv.RayCallable.rcall.out
index 31df5d1..b5e25be 100644
--- a/third_party/glslang/src/Test/baseResults/spv.RayCallable.rcall.out
+++ b/third_party/glslang/src/Test/baseResults/spv.RayCallable.rcall.out
@@ -7,7 +7,7 @@
                               Extension  "SPV_NV_ray_tracing"
                1:             ExtInstImport  "GLSL.std.450"
                               MemoryModel Logical GLSL450
-                              EntryPoint CallableNV 4  "main" 11 14
+                              EntryPoint CallableKHR 4  "main" 11 14
                               Source GLSL 460
                               SourceExtension  "GL_NV_ray_tracing"
                               Name 4  "main"
@@ -19,8 +19,8 @@
                               MemberName 16(dataBlock) 0  "data1"
                               Name 18  ""
                               Name 29  "data0"
-                              Decorate 11(gl_LaunchIDNV) BuiltIn LaunchIdNV
-                              Decorate 14(gl_LaunchSizeNV) BuiltIn LaunchSizeNV
+                              Decorate 11(gl_LaunchIDNV) BuiltIn LaunchIdKHR
+                              Decorate 14(gl_LaunchSizeNV) BuiltIn LaunchSizeKHR
                               Decorate 16(dataBlock) Block
                               Decorate 18 Location 1
                               Decorate 29(data0) Location 0
@@ -33,18 +33,18 @@
 11(gl_LaunchIDNV):     10(ptr) Variable Input
 14(gl_LaunchSizeNV):     10(ptr) Variable Input
    16(dataBlock):             TypeStruct 6(int)
-              17:             TypePointer IncomingCallableDataNV 16(dataBlock)
-              18:     17(ptr) Variable IncomingCallableDataNV
+              17:             TypePointer IncomingCallableDataKHR 16(dataBlock)
+              18:     17(ptr) Variable IncomingCallableDataKHR
               19:             TypeInt 32 1
               20:     19(int) Constant 0
               21:      6(int) Constant 256
-              22:             TypePointer IncomingCallableDataNV 6(int)
+              22:             TypePointer IncomingCallableDataKHR 6(int)
               24:      6(int) Constant 2
               25:     19(int) Constant 1
               26:             TypeFloat 32
               27:             TypeVector 26(float) 4
-              28:             TypePointer CallableDataNV 27(fvec4)
-       29(data0):     28(ptr) Variable CallableDataNV
+              28:             TypePointer CallableDataKHR 27(fvec4)
+       29(data0):     28(ptr) Variable CallableDataKHR
          4(main):           2 Function None 3
                5:             Label
            9(id):      8(ptr) Variable Function
@@ -55,6 +55,6 @@
                               Store 13(size) 15
               23:     22(ptr) AccessChain 18 20
                               Store 23 21
-                              ExecuteCallableNV 24 25
+                              ExecuteCallableKHR 24 25
                               Return
                               FunctionEnd
diff --git a/third_party/glslang/src/Test/baseResults/spv.RayConstants.rgen.out b/third_party/glslang/src/Test/baseResults/spv.RayConstants.rgen.out
index 033e545..97b47b7 100644
--- a/third_party/glslang/src/Test/baseResults/spv.RayConstants.rgen.out
+++ b/third_party/glslang/src/Test/baseResults/spv.RayConstants.rgen.out
@@ -7,7 +7,7 @@
                               Extension  "SPV_NV_ray_tracing"
                1:             ExtInstImport  "GLSL.std.450"
                               MemoryModel Logical GLSL450
-                              EntryPoint RayGenerationNV 4  "main"
+                              EntryPoint RayGenerationKHR 4  "main"
                               Source GLSL 460
                               SourceExtension  "GL_NV_ray_tracing"
                               Name 4  "main"
@@ -18,7 +18,7 @@
                               Decorate 26(payload) Location 0
                2:             TypeVoid
                3:             TypeFunction 2
-               6:             TypeAccelerationStructureNV
+               6:             TypeAccelerationStructureKHR
                7:             TypePointer UniformConstant 6
         8(accNV):      7(ptr) Variable UniformConstant
               10:             TypeInt 32 0
@@ -36,11 +36,11 @@
               22:             TypeInt 32 1
               23:     22(int) Constant 1
               24:             TypeVector 14(float) 4
-              25:             TypePointer RayPayloadNV 24(fvec4)
-     26(payload):     25(ptr) Variable RayPayloadNV
+              25:             TypePointer RayPayloadKHR 24(fvec4)
+     26(payload):     25(ptr) Variable RayPayloadKHR
          4(main):           2 Function None 3
                5:             Label
                9:           6 Load 8(accNV)
-                              TraceNV 9 11 12 13 13 12 17 18 20 21 23
+                              TraceRayKHR 9 11 12 13 13 12 17 18 20 21 23
                               Return
                               FunctionEnd
diff --git a/third_party/glslang/src/Test/baseResults/spv.RayGenShader.rgen.out b/third_party/glslang/src/Test/baseResults/spv.RayGenShader.rgen.out
index 59eabd0..47b7c92 100644
--- a/third_party/glslang/src/Test/baseResults/spv.RayGenShader.rgen.out
+++ b/third_party/glslang/src/Test/baseResults/spv.RayGenShader.rgen.out
@@ -7,7 +7,7 @@
                               Extension  "SPV_NV_ray_tracing"
                1:             ExtInstImport  "GLSL.std.450"
                               MemoryModel Logical GLSL450
-                              EntryPoint RayGenerationNV 4  "main" 11 21
+                              EntryPoint RayGenerationKHR 4  "main" 11 21
                               Source GLSL 460
                               SourceExtension  "GL_NV_ray_tracing"
                               Name 4  "main"
@@ -24,8 +24,8 @@
                               Name 39  ""
                               Name 50  "accNV1"
                               Name 53  "payload"
-                              Decorate 11(gl_LaunchIDNV) BuiltIn LaunchIdNV
-                              Decorate 21(gl_LaunchSizeNV) BuiltIn LaunchSizeNV
+                              Decorate 11(gl_LaunchIDNV) BuiltIn LaunchIdKHR
+                              Decorate 21(gl_LaunchSizeNV) BuiltIn LaunchSizeKHR
                               Decorate 29(accNV0) DescriptorSet 0
                               Decorate 29(accNV0) Binding 0
                               MemberDecorate 37(block) 0 Offset 0
@@ -45,24 +45,24 @@
               13:             TypePointer Input 6(int)
               17:      6(int) Constant 1
 21(gl_LaunchSizeNV):     10(ptr) Variable Input
-              27:             TypeAccelerationStructureNV
+              27:             TypeAccelerationStructureKHR
               28:             TypePointer UniformConstant 27
       29(accNV0):     28(ptr) Variable UniformConstant
               35:             TypeFloat 32
               36:             TypeVector 35(float) 3
        37(block):             TypeStruct 36(fvec3) 36(fvec3)
-              38:             TypePointer ShaderRecordBufferNV 37(block)
-              39:     38(ptr) Variable ShaderRecordBufferNV
+              38:             TypePointer ShaderRecordBufferKHR 37(block)
+              39:     38(ptr) Variable ShaderRecordBufferKHR
               40:             TypeInt 32 1
               41:     40(int) Constant 1
-              42:             TypePointer ShaderRecordBufferNV 36(fvec3)
+              42:             TypePointer ShaderRecordBufferKHR 36(fvec3)
               45:   35(float) Constant 1056964608
               46:     40(int) Constant 0
               49:   35(float) Constant 1061158912
       50(accNV1):     28(ptr) Variable UniformConstant
               51:             TypeVector 35(float) 4
-              52:             TypePointer RayPayloadNV 51(fvec4)
-     53(payload):     52(ptr) Variable RayPayloadNV
+              52:             TypePointer RayPayloadKHR 51(fvec4)
+     53(payload):     52(ptr) Variable RayPayloadKHR
          4(main):           2 Function None 3
                5:             Label
            8(lx):      7(ptr) Variable Function
@@ -90,6 +90,6 @@
               44:   36(fvec3) Load 43
               47:     42(ptr) AccessChain 39 46
               48:   36(fvec3) Load 47
-                              TraceNV 30 31 32 33 34 12 44 45 48 49 41
+                              TraceRayKHR 30 31 32 33 34 12 44 45 48 49 41
                               Return
                               FunctionEnd
diff --git a/third_party/glslang/src/Test/baseResults/spv.RayGenShader11.rgen.out b/third_party/glslang/src/Test/baseResults/spv.RayGenShader11.rgen.out
index 2d49b0f..0bbcab9 100755
--- a/third_party/glslang/src/Test/baseResults/spv.RayGenShader11.rgen.out
+++ b/third_party/glslang/src/Test/baseResults/spv.RayGenShader11.rgen.out
@@ -7,7 +7,7 @@
                               Extension  "SPV_NV_ray_tracing"
                1:             ExtInstImport  "GLSL.std.450"
                               MemoryModel Logical GLSL450
-                              EntryPoint RayGenerationNV 4  "main" 11 21
+                              EntryPoint RayGenerationKHR 4  "main" 11 21
                               Source GLSL 460
                               SourceExtension  "GL_NV_ray_tracing"
                               Name 4  "main"
@@ -23,8 +23,8 @@
                               MemberName 37(block) 1  "origin"
                               Name 39  ""
                               Name 52  "payload"
-                              Decorate 11(gl_LaunchIDNV) BuiltIn LaunchIdNV
-                              Decorate 21(gl_LaunchSizeNV) BuiltIn LaunchSizeNV
+                              Decorate 11(gl_LaunchIDNV) BuiltIn LaunchIdKHR
+                              Decorate 21(gl_LaunchSizeNV) BuiltIn LaunchSizeKHR
                               Decorate 29(accNV) DescriptorSet 0
                               Decorate 29(accNV) Binding 0
                               MemberDecorate 37(block) 0 Offset 0
@@ -42,23 +42,23 @@
               13:             TypePointer Input 6(int)
               17:      6(int) Constant 1
 21(gl_LaunchSizeNV):     10(ptr) Variable Input
-              27:             TypeAccelerationStructureNV
+              27:             TypeAccelerationStructureKHR
               28:             TypePointer UniformConstant 27
        29(accNV):     28(ptr) Variable UniformConstant
               35:             TypeFloat 32
               36:             TypeVector 35(float) 3
        37(block):             TypeStruct 36(fvec3) 36(fvec3)
-              38:             TypePointer ShaderRecordBufferNV 37(block)
-              39:     38(ptr) Variable ShaderRecordBufferNV
+              38:             TypePointer ShaderRecordBufferKHR 37(block)
+              39:     38(ptr) Variable ShaderRecordBufferKHR
               40:             TypeInt 32 1
               41:     40(int) Constant 1
-              42:             TypePointer ShaderRecordBufferNV 36(fvec3)
+              42:             TypePointer ShaderRecordBufferKHR 36(fvec3)
               45:   35(float) Constant 1056964608
               46:     40(int) Constant 0
               49:   35(float) Constant 1061158912
               50:             TypeVector 35(float) 4
-              51:             TypePointer RayPayloadNV 50(fvec4)
-     52(payload):     51(ptr) Variable RayPayloadNV
+              51:             TypePointer RayPayloadKHR 50(fvec4)
+     52(payload):     51(ptr) Variable RayPayloadKHR
          4(main):           2 Function None 3
                5:             Label
            8(lx):      7(ptr) Variable Function
@@ -86,6 +86,6 @@
               44:   36(fvec3) Load 43
               47:     42(ptr) AccessChain 39 46
               48:   36(fvec3) Load 47
-                              TraceNV 30 31 32 33 34 12 44 45 48 49 41
+                              TraceRayKHR 30 31 32 33 34 12 44 45 48 49 41
                               Return
                               FunctionEnd
diff --git a/third_party/glslang/src/Test/baseResults/spv.RayGenShaderArray.rgen.out b/third_party/glslang/src/Test/baseResults/spv.RayGenShaderArray.rgen.out
index 7a024ec..ce5f016 100644
--- a/third_party/glslang/src/Test/baseResults/spv.RayGenShaderArray.rgen.out
+++ b/third_party/glslang/src/Test/baseResults/spv.RayGenShaderArray.rgen.out
@@ -10,7 +10,7 @@
                               Extension  "SPV_NV_ray_tracing"
                1:             ExtInstImport  "GLSL.std.450"
                               MemoryModel Logical GLSL450
-                              EntryPoint RayGenerationNV 4  "main" 11 21
+                              EntryPoint RayGenerationKHR 4  "main" 11 21
                               Source GLSL 460
                               SourceExtension  "GL_EXT_nonuniform_qualifier"
                               SourceExtension  "GL_NV_ray_tracing"
@@ -29,8 +29,8 @@
                               Name 36  ""
                               Name 60  "accNV1"
                               Name 88  "payload"
-                              Decorate 11(gl_LaunchIDNV) BuiltIn LaunchIdNV
-                              Decorate 21(gl_LaunchSizeNV) BuiltIn LaunchSizeNV
+                              Decorate 11(gl_LaunchIDNV) BuiltIn LaunchIdKHR
+                              Decorate 21(gl_LaunchSizeNV) BuiltIn LaunchSizeKHR
                               Decorate 30(accNV0) DescriptorSet 0
                               Decorate 30(accNV0) Binding 0
                               MemberDecorate 34(block) 0 Offset 0
@@ -54,7 +54,7 @@
               13:             TypePointer Input 6(int)
               17:      6(int) Constant 1
 21(gl_LaunchSizeNV):     10(ptr) Variable Input
-              27:             TypeAccelerationStructureNV
+              27:             TypeAccelerationStructureKHR
               28:             TypeRuntimeArray 27
               29:             TypePointer UniformConstant 28
       30(accNV0):     29(ptr) Variable UniformConstant
@@ -62,13 +62,13 @@
               32:             TypeVector 31(float) 3
               33:             TypeInt 32 1
        34(block):             TypeStruct 32(fvec3) 32(fvec3) 33(int)
-              35:             TypePointer ShaderRecordBufferNV 34(block)
-              36:     35(ptr) Variable ShaderRecordBufferNV
+              35:             TypePointer ShaderRecordBufferKHR 34(block)
+              36:     35(ptr) Variable ShaderRecordBufferKHR
               37:     33(int) Constant 2
-              38:             TypePointer ShaderRecordBufferNV 33(int)
+              38:             TypePointer ShaderRecordBufferKHR 33(int)
               41:             TypePointer UniformConstant 27
               48:     33(int) Constant 1
-              49:             TypePointer ShaderRecordBufferNV 32(fvec3)
+              49:             TypePointer ShaderRecordBufferKHR 32(fvec3)
               52:   31(float) Constant 1056964608
               53:     33(int) Constant 0
               56:   31(float) Constant 1061158912
@@ -77,8 +77,8 @@
               59:             TypePointer UniformConstant 58
       60(accNV1):     59(ptr) Variable UniformConstant
               86:             TypeVector 31(float) 4
-              87:             TypePointer RayPayloadNV 86(fvec4)
-     88(payload):     87(ptr) Variable RayPayloadNV
+              87:             TypePointer RayPayloadKHR 86(fvec4)
+     88(payload):     87(ptr) Variable RayPayloadKHR
          4(main):           2 Function None 3
                5:             Label
            8(lx):      7(ptr) Variable Function
@@ -109,7 +109,7 @@
               51:   32(fvec3) Load 50
               54:     49(ptr) AccessChain 36 53
               55:   32(fvec3) Load 54
-                              TraceNV 43 44 45 46 47 12 51 52 55 56 48
+                              TraceRayKHR 43 44 45 46 47 12 51 52 55 56 48
               61:     38(ptr) AccessChain 36 37
               62:     33(int) Load 61
               63:     41(ptr) AccessChain 60(accNV1) 62
@@ -122,7 +122,7 @@
               70:   32(fvec3) Load 69
               71:     49(ptr) AccessChain 36 53
               72:   32(fvec3) Load 71
-                              TraceNV 64 65 66 67 68 12 70 52 72 56 48
+                              TraceRayKHR 64 65 66 67 68 12 70 52 72 56 48
               73:     38(ptr) AccessChain 36 37
               74:     33(int) Load 73
               75:     33(int) CopyObject 74
@@ -136,6 +136,6 @@
               83:   32(fvec3) Load 82
               84:     49(ptr) AccessChain 36 53
               85:   32(fvec3) Load 84
-                              TraceNV 77 78 79 80 81 12 83 52 85 56 48
+                              TraceRayKHR 77 78 79 80 81 12 83 52 85 56 48
                               Return
                               FunctionEnd
diff --git a/third_party/glslang/src/Test/baseResults/spv.atomicCounter.comp.out b/third_party/glslang/src/Test/baseResults/spv.atomicCounter.comp.out
new file mode 100644
index 0000000..46cccc0
--- /dev/null
+++ b/third_party/glslang/src/Test/baseResults/spv.atomicCounter.comp.out
@@ -0,0 +1,15 @@
+spv.atomicCounter.comp
+ERROR: 0:5: 'atomic counter types' : not allowed when using GLSL for Vulkan 
+ERROR: 0:7: 'atomic counter types' : not allowed when using GLSL for Vulkan 
+ERROR: 0:14: 'atomic counter types' : not allowed when using GLSL for Vulkan 
+ERROR: 0:16: 'atomicCounterIncrement' : no matching overloaded function found 
+ERROR: 0:16: 'return' : type does not match, or is not convertible to, the function's return type 
+ERROR: 0:21: 'memoryBarrierAtomicCounter' : no matching overloaded function found 
+ERROR: 0:23: 'atomicCounter' : no matching overloaded function found 
+ERROR: 0:23: '=' :  cannot convert from ' const float' to ' temp highp uint'
+ERROR: 0:24: 'atomicCounterDecrement' : no matching overloaded function found 
+ERROR: 0:25: 'atomicCounterIncrement' : no matching overloaded function found 
+ERROR: 10 compilation errors.  No code generated.
+
+
+SPIR-V is not generated for failed compile or link
diff --git a/third_party/glslang/src/Test/baseResults/spv.ext.AnyHitShader.rahit.out b/third_party/glslang/src/Test/baseResults/spv.ext.AnyHitShader.rahit.out
new file mode 100644
index 0000000..3cd60c7
--- /dev/null
+++ b/third_party/glslang/src/Test/baseResults/spv.ext.AnyHitShader.rahit.out
@@ -0,0 +1,188 @@
+spv.ext.AnyHitShader.rahit
+// Module Version 10000
+// Generated by (magic number): 80008
+// Id's are bound by 94
+
+                              Capability RayTracingProvisionalKHR
+                              Extension  "SPV_KHR_ray_tracing"
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint AnyHitKHR 4  "main" 11 14 20 23 26 33 36 39 42 47 50 53 58 64 67 70 76 80
+                              Source GLSL 460
+                              SourceExtension  "GL_EXT_ray_tracing"
+                              Name 4  "main"
+                              Name 9  "v0"
+                              Name 11  "gl_LaunchIDEXT"
+                              Name 13  "v1"
+                              Name 14  "gl_LaunchSizeEXT"
+                              Name 18  "v2"
+                              Name 20  "gl_PrimitiveID"
+                              Name 22  "v3"
+                              Name 23  "gl_InstanceID"
+                              Name 25  "v4"
+                              Name 26  "gl_InstanceCustomIndexEXT"
+                              Name 31  "v5"
+                              Name 33  "gl_WorldRayOriginEXT"
+                              Name 35  "v6"
+                              Name 36  "gl_WorldRayDirectionEXT"
+                              Name 38  "v7"
+                              Name 39  "gl_ObjectRayOriginEXT"
+                              Name 41  "v8"
+                              Name 42  "gl_ObjectRayDirectionEXT"
+                              Name 45  "v9"
+                              Name 47  "gl_RayTminEXT"
+                              Name 49  "v10"
+                              Name 50  "gl_RayTmaxEXT"
+                              Name 52  "v11"
+                              Name 53  "gl_HitTEXT"
+                              Name 56  "v12"
+                              Name 58  "gl_HitKindEXT"
+                              Name 62  "v13"
+                              Name 64  "gl_ObjectToWorldEXT"
+                              Name 66  "v14"
+                              Name 67  "gl_WorldToObjectEXT"
+                              Name 69  "v15"
+                              Name 70  "gl_GeometryIndexEXT"
+                              Name 75  "v16"
+                              Name 76  "gl_ObjectToWorld3x4EXT"
+                              Name 79  "v17"
+                              Name 80  "gl_WorldToObject3x4EXT"
+                              Name 84  "incomingPayload"
+                              Decorate 11(gl_LaunchIDEXT) BuiltIn LaunchIdKHR
+                              Decorate 14(gl_LaunchSizeEXT) BuiltIn LaunchSizeKHR
+                              Decorate 20(gl_PrimitiveID) BuiltIn PrimitiveId
+                              Decorate 23(gl_InstanceID) BuiltIn InstanceId
+                              Decorate 26(gl_InstanceCustomIndexEXT) BuiltIn InstanceCustomIndexKHR
+                              Decorate 33(gl_WorldRayOriginEXT) BuiltIn WorldRayOriginKHR
+                              Decorate 36(gl_WorldRayDirectionEXT) BuiltIn WorldRayDirectionKHR
+                              Decorate 39(gl_ObjectRayOriginEXT) BuiltIn ObjectRayOriginKHR
+                              Decorate 42(gl_ObjectRayDirectionEXT) BuiltIn ObjectRayDirectionKHR
+                              Decorate 47(gl_RayTminEXT) BuiltIn RayTminKHR
+                              Decorate 50(gl_RayTmaxEXT) BuiltIn RayTmaxKHR
+                              Decorate 53(gl_HitTEXT) BuiltIn HitTKHR
+                              Decorate 58(gl_HitKindEXT) BuiltIn HitKindKHR
+                              Decorate 64(gl_ObjectToWorldEXT) BuiltIn ObjectToWorldKHR
+                              Decorate 67(gl_WorldToObjectEXT) BuiltIn WorldToObjectKHR
+                              Decorate 70(gl_GeometryIndexEXT) BuiltIn RayGeometryIndexKHR
+                              Decorate 76(gl_ObjectToWorld3x4EXT) BuiltIn ObjectToWorldKHR
+                              Decorate 80(gl_WorldToObject3x4EXT) BuiltIn WorldToObjectKHR
+                              Decorate 84(incomingPayload) Location 1
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeInt 32 0
+               7:             TypeVector 6(int) 3
+               8:             TypePointer Function 7(ivec3)
+              10:             TypePointer Input 7(ivec3)
+11(gl_LaunchIDEXT):     10(ptr) Variable Input
+14(gl_LaunchSizeEXT):     10(ptr) Variable Input
+              16:             TypeInt 32 1
+              17:             TypePointer Function 16(int)
+              19:             TypePointer Input 16(int)
+20(gl_PrimitiveID):     19(ptr) Variable Input
+23(gl_InstanceID):     19(ptr) Variable Input
+26(gl_InstanceCustomIndexEXT):     19(ptr) Variable Input
+              28:             TypeFloat 32
+              29:             TypeVector 28(float) 3
+              30:             TypePointer Function 29(fvec3)
+              32:             TypePointer Input 29(fvec3)
+33(gl_WorldRayOriginEXT):     32(ptr) Variable Input
+36(gl_WorldRayDirectionEXT):     32(ptr) Variable Input
+39(gl_ObjectRayOriginEXT):     32(ptr) Variable Input
+42(gl_ObjectRayDirectionEXT):     32(ptr) Variable Input
+              44:             TypePointer Function 28(float)
+              46:             TypePointer Input 28(float)
+47(gl_RayTminEXT):     46(ptr) Variable Input
+50(gl_RayTmaxEXT):     46(ptr) Variable Input
+  53(gl_HitTEXT):     46(ptr) Variable Input
+              55:             TypePointer Function 6(int)
+              57:             TypePointer Input 6(int)
+58(gl_HitKindEXT):     57(ptr) Variable Input
+              60:             TypeMatrix 29(fvec3) 4
+              61:             TypePointer Function 60
+              63:             TypePointer Input 60
+64(gl_ObjectToWorldEXT):     63(ptr) Variable Input
+67(gl_WorldToObjectEXT):     63(ptr) Variable Input
+70(gl_GeometryIndexEXT):     19(ptr) Variable Input
+              72:             TypeVector 28(float) 4
+              73:             TypeMatrix 72(fvec4) 3
+              74:             TypePointer Function 73
+76(gl_ObjectToWorld3x4EXT):     63(ptr) Variable Input
+80(gl_WorldToObject3x4EXT):     63(ptr) Variable Input
+              83:             TypePointer IncomingRayPayloadKHR 72(fvec4)
+84(incomingPayload):     83(ptr) Variable IncomingRayPayloadKHR
+              85:   28(float) Constant 1056964608
+              86:   72(fvec4) ConstantComposite 85 85 85 85
+              88:     16(int) Constant 1
+              89:             TypeBool
+         4(main):           2 Function None 3
+               5:             Label
+           9(v0):      8(ptr) Variable Function
+          13(v1):      8(ptr) Variable Function
+          18(v2):     17(ptr) Variable Function
+          22(v3):     17(ptr) Variable Function
+          25(v4):     17(ptr) Variable Function
+          31(v5):     30(ptr) Variable Function
+          35(v6):     30(ptr) Variable Function
+          38(v7):     30(ptr) Variable Function
+          41(v8):     30(ptr) Variable Function
+          45(v9):     44(ptr) Variable Function
+         49(v10):     44(ptr) Variable Function
+         52(v11):     44(ptr) Variable Function
+         56(v12):     55(ptr) Variable Function
+         62(v13):     61(ptr) Variable Function
+         66(v14):     61(ptr) Variable Function
+         69(v15):     17(ptr) Variable Function
+         75(v16):     74(ptr) Variable Function
+         79(v17):     74(ptr) Variable Function
+              12:    7(ivec3) Load 11(gl_LaunchIDEXT)
+                              Store 9(v0) 12
+              15:    7(ivec3) Load 14(gl_LaunchSizeEXT)
+                              Store 13(v1) 15
+              21:     16(int) Load 20(gl_PrimitiveID)
+                              Store 18(v2) 21
+              24:     16(int) Load 23(gl_InstanceID)
+                              Store 22(v3) 24
+              27:     16(int) Load 26(gl_InstanceCustomIndexEXT)
+                              Store 25(v4) 27
+              34:   29(fvec3) Load 33(gl_WorldRayOriginEXT)
+                              Store 31(v5) 34
+              37:   29(fvec3) Load 36(gl_WorldRayDirectionEXT)
+                              Store 35(v6) 37
+              40:   29(fvec3) Load 39(gl_ObjectRayOriginEXT)
+                              Store 38(v7) 40
+              43:   29(fvec3) Load 42(gl_ObjectRayDirectionEXT)
+                              Store 41(v8) 43
+              48:   28(float) Load 47(gl_RayTminEXT)
+                              Store 45(v9) 48
+              51:   28(float) Load 50(gl_RayTmaxEXT)
+                              Store 49(v10) 51
+              54:   28(float) Load 53(gl_HitTEXT)
+                              Store 52(v11) 54
+              59:      6(int) Load 58(gl_HitKindEXT)
+                              Store 56(v12) 59
+              65:          60 Load 64(gl_ObjectToWorldEXT)
+                              Store 62(v13) 65
+              68:          60 Load 67(gl_WorldToObjectEXT)
+                              Store 66(v14) 68
+              71:     16(int) Load 70(gl_GeometryIndexEXT)
+                              Store 69(v15) 71
+              77:          60 Load 76(gl_ObjectToWorld3x4EXT)
+              78:          73 Transpose 77
+                              Store 75(v16) 78
+              81:          60 Load 80(gl_WorldToObject3x4EXT)
+              82:          73 Transpose 81
+                              Store 79(v17) 82
+                              Store 84(incomingPayload) 86
+              87:     16(int) Load 18(v2)
+              90:    89(bool) IEqual 87 88
+                              SelectionMerge 92 None
+                              BranchConditional 90 91 93
+              91:               Label
+                                IgnoreIntersectionKHR
+                                Branch 92
+              93:               Label
+                                TerminateRayKHR
+                                Branch 92
+              92:             Label
+                              Return
+                              FunctionEnd
diff --git a/third_party/glslang/src/Test/baseResults/spv.ext.AnyHitShader_Errors.rahit.out b/third_party/glslang/src/Test/baseResults/spv.ext.AnyHitShader_Errors.rahit.out
new file mode 100644
index 0000000..8c47429
--- /dev/null
+++ b/third_party/glslang/src/Test/baseResults/spv.ext.AnyHitShader_Errors.rahit.out
@@ -0,0 +1,8 @@
+spv.ext.AnyHitShader_Errors.rahit
+ERROR: 0:8: 'assign' :  l-value required "payload" (cannot modify hitAttributeNV in this stage)
+ERROR: 0:9: 'reportIntersectionEXT' : no matching overloaded function found 
+ERROR: 0:10: 'traceRayEXT' : no matching overloaded function found 
+ERROR: 3 compilation errors.  No code generated.
+
+
+SPIR-V is not generated for failed compile or link
diff --git a/third_party/glslang/src/Test/baseResults/spv.ext.ClosestHitShader.rchit.out b/third_party/glslang/src/Test/baseResults/spv.ext.ClosestHitShader.rchit.out
new file mode 100644
index 0000000..278b5c1
--- /dev/null
+++ b/third_party/glslang/src/Test/baseResults/spv.ext.ClosestHitShader.rchit.out
@@ -0,0 +1,194 @@
+spv.ext.ClosestHitShader.rchit
+// Module Version 10000
+// Generated by (magic number): 80008
+// Id's are bound by 101
+
+                              Capability RayTracingProvisionalKHR
+                              Extension  "SPV_KHR_ray_tracing"
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint ClosestHitKHR 4  "main" 11 14 20 23 26 33 36 39 42 47 50 53 58 64 67 70 76 80
+                              Source GLSL 460
+                              SourceExtension  "GL_EXT_ray_tracing"
+                              Name 4  "main"
+                              Name 9  "v0"
+                              Name 11  "gl_LaunchIDEXT"
+                              Name 13  "v1"
+                              Name 14  "gl_LaunchSizeEXT"
+                              Name 18  "v2"
+                              Name 20  "gl_PrimitiveID"
+                              Name 22  "v3"
+                              Name 23  "gl_InstanceID"
+                              Name 25  "v4"
+                              Name 26  "gl_InstanceCustomIndexEXT"
+                              Name 31  "v5"
+                              Name 33  "gl_WorldRayOriginEXT"
+                              Name 35  "v6"
+                              Name 36  "gl_WorldRayDirectionEXT"
+                              Name 38  "v7"
+                              Name 39  "gl_ObjectRayOriginEXT"
+                              Name 41  "v8"
+                              Name 42  "gl_ObjectRayDirectionEXT"
+                              Name 45  "v9"
+                              Name 47  "gl_RayTminEXT"
+                              Name 49  "v10"
+                              Name 50  "gl_RayTmaxEXT"
+                              Name 52  "v11"
+                              Name 53  "gl_HitTEXT"
+                              Name 56  "v12"
+                              Name 58  "gl_HitKindEXT"
+                              Name 62  "v13"
+                              Name 64  "gl_ObjectToWorldEXT"
+                              Name 66  "v14"
+                              Name 67  "gl_WorldToObjectEXT"
+                              Name 69  "v15"
+                              Name 70  "gl_GeometryIndexEXT"
+                              Name 75  "v16"
+                              Name 76  "gl_ObjectToWorld3x4EXT"
+                              Name 79  "v17"
+                              Name 80  "gl_WorldToObject3x4EXT"
+                              Name 85  "accEXT"
+                              Name 98  "localPayload"
+                              Name 100  "incomingPayload"
+                              Decorate 11(gl_LaunchIDEXT) BuiltIn LaunchIdKHR
+                              Decorate 14(gl_LaunchSizeEXT) BuiltIn LaunchSizeKHR
+                              Decorate 20(gl_PrimitiveID) BuiltIn PrimitiveId
+                              Decorate 23(gl_InstanceID) BuiltIn InstanceId
+                              Decorate 26(gl_InstanceCustomIndexEXT) BuiltIn InstanceCustomIndexKHR
+                              Decorate 33(gl_WorldRayOriginEXT) BuiltIn WorldRayOriginKHR
+                              Decorate 36(gl_WorldRayDirectionEXT) BuiltIn WorldRayDirectionKHR
+                              Decorate 39(gl_ObjectRayOriginEXT) BuiltIn ObjectRayOriginKHR
+                              Decorate 42(gl_ObjectRayDirectionEXT) BuiltIn ObjectRayDirectionKHR
+                              Decorate 47(gl_RayTminEXT) BuiltIn RayTminKHR
+                              Decorate 50(gl_RayTmaxEXT) BuiltIn RayTmaxKHR
+                              Decorate 53(gl_HitTEXT) BuiltIn HitTKHR
+                              Decorate 58(gl_HitKindEXT) BuiltIn HitKindKHR
+                              Decorate 64(gl_ObjectToWorldEXT) BuiltIn ObjectToWorldKHR
+                              Decorate 67(gl_WorldToObjectEXT) BuiltIn WorldToObjectKHR
+                              Decorate 70(gl_GeometryIndexEXT) BuiltIn RayGeometryIndexKHR
+                              Decorate 76(gl_ObjectToWorld3x4EXT) BuiltIn ObjectToWorldKHR
+                              Decorate 80(gl_WorldToObject3x4EXT) BuiltIn WorldToObjectKHR
+                              Decorate 85(accEXT) DescriptorSet 0
+                              Decorate 85(accEXT) Binding 0
+                              Decorate 98(localPayload) Location 0
+                              Decorate 100(incomingPayload) Location 1
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeInt 32 0
+               7:             TypeVector 6(int) 3
+               8:             TypePointer Function 7(ivec3)
+              10:             TypePointer Input 7(ivec3)
+11(gl_LaunchIDEXT):     10(ptr) Variable Input
+14(gl_LaunchSizeEXT):     10(ptr) Variable Input
+              16:             TypeInt 32 1
+              17:             TypePointer Function 16(int)
+              19:             TypePointer Input 16(int)
+20(gl_PrimitiveID):     19(ptr) Variable Input
+23(gl_InstanceID):     19(ptr) Variable Input
+26(gl_InstanceCustomIndexEXT):     19(ptr) Variable Input
+              28:             TypeFloat 32
+              29:             TypeVector 28(float) 3
+              30:             TypePointer Function 29(fvec3)
+              32:             TypePointer Input 29(fvec3)
+33(gl_WorldRayOriginEXT):     32(ptr) Variable Input
+36(gl_WorldRayDirectionEXT):     32(ptr) Variable Input
+39(gl_ObjectRayOriginEXT):     32(ptr) Variable Input
+42(gl_ObjectRayDirectionEXT):     32(ptr) Variable Input
+              44:             TypePointer Function 28(float)
+              46:             TypePointer Input 28(float)
+47(gl_RayTminEXT):     46(ptr) Variable Input
+50(gl_RayTmaxEXT):     46(ptr) Variable Input
+  53(gl_HitTEXT):     46(ptr) Variable Input
+              55:             TypePointer Function 6(int)
+              57:             TypePointer Input 6(int)
+58(gl_HitKindEXT):     57(ptr) Variable Input
+              60:             TypeMatrix 29(fvec3) 4
+              61:             TypePointer Function 60
+              63:             TypePointer Input 60
+64(gl_ObjectToWorldEXT):     63(ptr) Variable Input
+67(gl_WorldToObjectEXT):     63(ptr) Variable Input
+70(gl_GeometryIndexEXT):     19(ptr) Variable Input
+              72:             TypeVector 28(float) 4
+              73:             TypeMatrix 72(fvec4) 3
+              74:             TypePointer Function 73
+76(gl_ObjectToWorld3x4EXT):     63(ptr) Variable Input
+80(gl_WorldToObject3x4EXT):     63(ptr) Variable Input
+              83:             TypeAccelerationStructureKHR
+              84:             TypePointer UniformConstant 83
+      85(accEXT):     84(ptr) Variable UniformConstant
+              87:      6(int) Constant 0
+              88:      6(int) Constant 1
+              89:      6(int) Constant 2
+              90:      6(int) Constant 3
+              91:   28(float) Constant 1056964608
+              92:   29(fvec3) ConstantComposite 91 91 91
+              93:   28(float) Constant 1065353216
+              94:   29(fvec3) ConstantComposite 93 93 93
+              95:   28(float) Constant 1061158912
+              96:     16(int) Constant 1
+              97:             TypePointer RayPayloadKHR 72(fvec4)
+98(localPayload):     97(ptr) Variable RayPayloadKHR
+              99:             TypePointer IncomingRayPayloadKHR 72(fvec4)
+100(incomingPayload):     99(ptr) Variable IncomingRayPayloadKHR
+         4(main):           2 Function None 3
+               5:             Label
+           9(v0):      8(ptr) Variable Function
+          13(v1):      8(ptr) Variable Function
+          18(v2):     17(ptr) Variable Function
+          22(v3):     17(ptr) Variable Function
+          25(v4):     17(ptr) Variable Function
+          31(v5):     30(ptr) Variable Function
+          35(v6):     30(ptr) Variable Function
+          38(v7):     30(ptr) Variable Function
+          41(v8):     30(ptr) Variable Function
+          45(v9):     44(ptr) Variable Function
+         49(v10):     44(ptr) Variable Function
+         52(v11):     44(ptr) Variable Function
+         56(v12):     55(ptr) Variable Function
+         62(v13):     61(ptr) Variable Function
+         66(v14):     61(ptr) Variable Function
+         69(v15):     17(ptr) Variable Function
+         75(v16):     74(ptr) Variable Function
+         79(v17):     74(ptr) Variable Function
+              12:    7(ivec3) Load 11(gl_LaunchIDEXT)
+                              Store 9(v0) 12
+              15:    7(ivec3) Load 14(gl_LaunchSizeEXT)
+                              Store 13(v1) 15
+              21:     16(int) Load 20(gl_PrimitiveID)
+                              Store 18(v2) 21
+              24:     16(int) Load 23(gl_InstanceID)
+                              Store 22(v3) 24
+              27:     16(int) Load 26(gl_InstanceCustomIndexEXT)
+                              Store 25(v4) 27
+              34:   29(fvec3) Load 33(gl_WorldRayOriginEXT)
+                              Store 31(v5) 34
+              37:   29(fvec3) Load 36(gl_WorldRayDirectionEXT)
+                              Store 35(v6) 37
+              40:   29(fvec3) Load 39(gl_ObjectRayOriginEXT)
+                              Store 38(v7) 40
+              43:   29(fvec3) Load 42(gl_ObjectRayDirectionEXT)
+                              Store 41(v8) 43
+              48:   28(float) Load 47(gl_RayTminEXT)
+                              Store 45(v9) 48
+              51:   28(float) Load 50(gl_RayTmaxEXT)
+                              Store 49(v10) 51
+              54:   28(float) Load 53(gl_HitTEXT)
+                              Store 52(v11) 54
+              59:      6(int) Load 58(gl_HitKindEXT)
+                              Store 56(v12) 59
+              65:          60 Load 64(gl_ObjectToWorldEXT)
+                              Store 62(v13) 65
+              68:          60 Load 67(gl_WorldToObjectEXT)
+                              Store 66(v14) 68
+              71:     16(int) Load 70(gl_GeometryIndexEXT)
+                              Store 69(v15) 71
+              77:          60 Load 76(gl_ObjectToWorld3x4EXT)
+              78:          73 Transpose 77
+                              Store 75(v16) 78
+              81:          60 Load 80(gl_WorldToObject3x4EXT)
+              82:          73 Transpose 81
+                              Store 79(v17) 82
+              86:          83 Load 85(accEXT)
+                              TraceRayKHR 86 87 88 89 90 87 92 91 94 95 96
+                              Return
+                              FunctionEnd
diff --git a/third_party/glslang/src/Test/baseResults/spv.ext.ClosestHitShader_Errors.rchit.out b/third_party/glslang/src/Test/baseResults/spv.ext.ClosestHitShader_Errors.rchit.out
new file mode 100644
index 0000000..6c87d1c
--- /dev/null
+++ b/third_party/glslang/src/Test/baseResults/spv.ext.ClosestHitShader_Errors.rchit.out
@@ -0,0 +1,10 @@
+spv.ext.ClosestHitShader_Errors.rchit
+ERROR: 0:8: 'assign' :  l-value required "payload" (cannot modify hitAttributeNV in this stage)
+ERROR: 0:9: 'reportIntersectionEXT' : no matching overloaded function found 
+ERROR: 0:10: 'terminateRayEXT' : no matching overloaded function found 
+ERROR: 0:11: 'ignoreIntersectionEXT' : no matching overloaded function found 
+ERROR: 0:12: 'gl_RayFlagsSkipAABBEXT' : required extension not requested: GL_EXT_ray_flags_primitive_culling
+ERROR: 5 compilation errors.  No code generated.
+
+
+SPIR-V is not generated for failed compile or link
diff --git a/third_party/glslang/src/Test/baseResults/spv.ext.IntersectShader.rint.out b/third_party/glslang/src/Test/baseResults/spv.ext.IntersectShader.rint.out
new file mode 100644
index 0000000..b8b8de2
--- /dev/null
+++ b/third_party/glslang/src/Test/baseResults/spv.ext.IntersectShader.rint.out
@@ -0,0 +1,156 @@
+spv.ext.IntersectShader.rint
+// Module Version 10000
+// Generated by (magic number): 80008
+// Id's are bound by 81
+
+                              Capability RayTracingProvisionalKHR
+                              Extension  "SPV_KHR_ray_tracing"
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint IntersectionKHR 4  "main" 11 14 20 23 26 33 36 39 42 47 50 56 59 65 69
+                              Source GLSL 460
+                              SourceExtension  "GL_EXT_ray_tracing"
+                              Name 4  "main"
+                              Name 9  "v0"
+                              Name 11  "gl_LaunchIDEXT"
+                              Name 13  "v1"
+                              Name 14  "gl_LaunchSizeEXT"
+                              Name 18  "v2"
+                              Name 20  "gl_PrimitiveID"
+                              Name 22  "v3"
+                              Name 23  "gl_InstanceID"
+                              Name 25  "v4"
+                              Name 26  "gl_InstanceCustomIndexEXT"
+                              Name 31  "v5"
+                              Name 33  "gl_WorldRayOriginEXT"
+                              Name 35  "v6"
+                              Name 36  "gl_WorldRayDirectionEXT"
+                              Name 38  "v7"
+                              Name 39  "gl_ObjectRayOriginEXT"
+                              Name 41  "v8"
+                              Name 42  "gl_ObjectRayDirectionEXT"
+                              Name 45  "v9"
+                              Name 47  "gl_RayTminEXT"
+                              Name 49  "v10"
+                              Name 50  "gl_RayTmaxEXT"
+                              Name 54  "v11"
+                              Name 56  "gl_ObjectToWorldEXT"
+                              Name 58  "v12"
+                              Name 59  "gl_WorldToObjectEXT"
+                              Name 64  "v13"
+                              Name 65  "gl_ObjectToWorld3x4EXT"
+                              Name 68  "v14"
+                              Name 69  "gl_WorldToObject3x4EXT"
+                              Name 73  "iAttr"
+                              Decorate 11(gl_LaunchIDEXT) BuiltIn LaunchIdKHR
+                              Decorate 14(gl_LaunchSizeEXT) BuiltIn LaunchSizeKHR
+                              Decorate 20(gl_PrimitiveID) BuiltIn PrimitiveId
+                              Decorate 23(gl_InstanceID) BuiltIn InstanceId
+                              Decorate 26(gl_InstanceCustomIndexEXT) BuiltIn InstanceCustomIndexKHR
+                              Decorate 33(gl_WorldRayOriginEXT) BuiltIn WorldRayOriginKHR
+                              Decorate 36(gl_WorldRayDirectionEXT) BuiltIn WorldRayDirectionKHR
+                              Decorate 39(gl_ObjectRayOriginEXT) BuiltIn ObjectRayOriginKHR
+                              Decorate 42(gl_ObjectRayDirectionEXT) BuiltIn ObjectRayDirectionKHR
+                              Decorate 47(gl_RayTminEXT) BuiltIn RayTminKHR
+                              Decorate 50(gl_RayTmaxEXT) BuiltIn RayTmaxKHR
+                              Decorate 56(gl_ObjectToWorldEXT) BuiltIn ObjectToWorldKHR
+                              Decorate 59(gl_WorldToObjectEXT) BuiltIn WorldToObjectKHR
+                              Decorate 65(gl_ObjectToWorld3x4EXT) BuiltIn ObjectToWorldKHR
+                              Decorate 69(gl_WorldToObject3x4EXT) BuiltIn WorldToObjectKHR
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeInt 32 0
+               7:             TypeVector 6(int) 3
+               8:             TypePointer Function 7(ivec3)
+              10:             TypePointer Input 7(ivec3)
+11(gl_LaunchIDEXT):     10(ptr) Variable Input
+14(gl_LaunchSizeEXT):     10(ptr) Variable Input
+              16:             TypeInt 32 1
+              17:             TypePointer Function 16(int)
+              19:             TypePointer Input 16(int)
+20(gl_PrimitiveID):     19(ptr) Variable Input
+23(gl_InstanceID):     19(ptr) Variable Input
+26(gl_InstanceCustomIndexEXT):     19(ptr) Variable Input
+              28:             TypeFloat 32
+              29:             TypeVector 28(float) 3
+              30:             TypePointer Function 29(fvec3)
+              32:             TypePointer Input 29(fvec3)
+33(gl_WorldRayOriginEXT):     32(ptr) Variable Input
+36(gl_WorldRayDirectionEXT):     32(ptr) Variable Input
+39(gl_ObjectRayOriginEXT):     32(ptr) Variable Input
+42(gl_ObjectRayDirectionEXT):     32(ptr) Variable Input
+              44:             TypePointer Function 28(float)
+              46:             TypePointer Input 28(float)
+47(gl_RayTminEXT):     46(ptr) Variable Input
+50(gl_RayTmaxEXT):     46(ptr) Variable Input
+              52:             TypeMatrix 29(fvec3) 4
+              53:             TypePointer Function 52
+              55:             TypePointer Input 52
+56(gl_ObjectToWorldEXT):     55(ptr) Variable Input
+59(gl_WorldToObjectEXT):     55(ptr) Variable Input
+              61:             TypeVector 28(float) 4
+              62:             TypeMatrix 61(fvec4) 3
+              63:             TypePointer Function 62
+65(gl_ObjectToWorld3x4EXT):     55(ptr) Variable Input
+69(gl_WorldToObject3x4EXT):     55(ptr) Variable Input
+              72:             TypePointer HitAttributeKHR 61(fvec4)
+       73(iAttr):     72(ptr) Variable HitAttributeKHR
+              74:   28(float) Constant 1056964608
+              75:   28(float) Constant 0
+              76:   28(float) Constant 1065353216
+              77:   61(fvec4) ConstantComposite 74 74 75 76
+              78:      6(int) Constant 1
+              79:             TypeBool
+         4(main):           2 Function None 3
+               5:             Label
+           9(v0):      8(ptr) Variable Function
+          13(v1):      8(ptr) Variable Function
+          18(v2):     17(ptr) Variable Function
+          22(v3):     17(ptr) Variable Function
+          25(v4):     17(ptr) Variable Function
+          31(v5):     30(ptr) Variable Function
+          35(v6):     30(ptr) Variable Function
+          38(v7):     30(ptr) Variable Function
+          41(v8):     30(ptr) Variable Function
+          45(v9):     44(ptr) Variable Function
+         49(v10):     44(ptr) Variable Function
+         54(v11):     53(ptr) Variable Function
+         58(v12):     53(ptr) Variable Function
+         64(v13):     63(ptr) Variable Function
+         68(v14):     63(ptr) Variable Function
+              12:    7(ivec3) Load 11(gl_LaunchIDEXT)
+                              Store 9(v0) 12
+              15:    7(ivec3) Load 14(gl_LaunchSizeEXT)
+                              Store 13(v1) 15
+              21:     16(int) Load 20(gl_PrimitiveID)
+                              Store 18(v2) 21
+              24:     16(int) Load 23(gl_InstanceID)
+                              Store 22(v3) 24
+              27:     16(int) Load 26(gl_InstanceCustomIndexEXT)
+                              Store 25(v4) 27
+              34:   29(fvec3) Load 33(gl_WorldRayOriginEXT)
+                              Store 31(v5) 34
+              37:   29(fvec3) Load 36(gl_WorldRayDirectionEXT)
+                              Store 35(v6) 37
+              40:   29(fvec3) Load 39(gl_ObjectRayOriginEXT)
+                              Store 38(v7) 40
+              43:   29(fvec3) Load 42(gl_ObjectRayDirectionEXT)
+                              Store 41(v8) 43
+              48:   28(float) Load 47(gl_RayTminEXT)
+                              Store 45(v9) 48
+              51:   28(float) Load 50(gl_RayTmaxEXT)
+                              Store 49(v10) 51
+              57:          52 Load 56(gl_ObjectToWorldEXT)
+                              Store 54(v11) 57
+              60:          52 Load 59(gl_WorldToObjectEXT)
+                              Store 58(v12) 60
+              66:          52 Load 65(gl_ObjectToWorld3x4EXT)
+              67:          62 Transpose 66
+                              Store 64(v13) 67
+              70:          52 Load 69(gl_WorldToObject3x4EXT)
+              71:          62 Transpose 70
+                              Store 68(v14) 71
+                              Store 73(iAttr) 77
+              80:    79(bool) ReportIntersectionKHR 74 78
+                              Return
+                              FunctionEnd
diff --git a/third_party/glslang/src/Test/baseResults/spv.ext.IntersectShader_Errors.rint.out b/third_party/glslang/src/Test/baseResults/spv.ext.IntersectShader_Errors.rint.out
new file mode 100644
index 0000000..03f9b27
--- /dev/null
+++ b/third_party/glslang/src/Test/baseResults/spv.ext.IntersectShader_Errors.rint.out
@@ -0,0 +1,10 @@
+spv.ext.IntersectShader_Errors.rint
+ERROR: 0:3: 'rayPayloadInEXT' : not supported in this stage: intersection
+ERROR: 0:4: 'rayPayloadEXT' : not supported in this stage: intersection
+ERROR: 0:8: 'gl_HitTEXT' : undeclared identifier 
+ERROR: 0:9: 'gl_HitKindEXT' : undeclared identifier 
+ERROR: 0:10: 'traceRayEXT' : no matching overloaded function found 
+ERROR: 5 compilation errors.  No code generated.
+
+
+SPIR-V is not generated for failed compile or link
diff --git a/third_party/glslang/src/Test/baseResults/spv.ext.MissShader.rmiss.out b/third_party/glslang/src/Test/baseResults/spv.ext.MissShader.rmiss.out
new file mode 100644
index 0000000..dd3f15f
--- /dev/null
+++ b/third_party/glslang/src/Test/baseResults/spv.ext.MissShader.rmiss.out
@@ -0,0 +1,99 @@
+spv.ext.MissShader.rmiss
+// Module Version 10000
+// Generated by (magic number): 80008
+// Id's are bound by 54
+
+                              Capability RayTracingProvisionalKHR
+                              Extension  "SPV_KHR_ray_tracing"
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint MissKHR 4  "main" 11 14 21 24 29 32
+                              Source GLSL 460
+                              SourceExtension  "GL_EXT_ray_tracing"
+                              Name 4  "main"
+                              Name 9  "v0"
+                              Name 11  "gl_LaunchIDEXT"
+                              Name 13  "v1"
+                              Name 14  "gl_LaunchSizeEXT"
+                              Name 19  "v2"
+                              Name 21  "gl_WorldRayOriginEXT"
+                              Name 23  "v3"
+                              Name 24  "gl_WorldRayDirectionEXT"
+                              Name 27  "v4"
+                              Name 29  "gl_RayTminEXT"
+                              Name 31  "v5"
+                              Name 32  "gl_RayTmaxEXT"
+                              Name 36  "accEXT"
+                              Name 51  "localPayload"
+                              Name 53  "incomingPayload"
+                              Decorate 11(gl_LaunchIDEXT) BuiltIn LaunchIdKHR
+                              Decorate 14(gl_LaunchSizeEXT) BuiltIn LaunchSizeKHR
+                              Decorate 21(gl_WorldRayOriginEXT) BuiltIn WorldRayOriginKHR
+                              Decorate 24(gl_WorldRayDirectionEXT) BuiltIn WorldRayDirectionKHR
+                              Decorate 29(gl_RayTminEXT) BuiltIn RayTminKHR
+                              Decorate 32(gl_RayTmaxEXT) BuiltIn RayTmaxKHR
+                              Decorate 36(accEXT) DescriptorSet 0
+                              Decorate 36(accEXT) Binding 0
+                              Decorate 51(localPayload) Location 0
+                              Decorate 53(incomingPayload) Location 1
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeInt 32 0
+               7:             TypeVector 6(int) 3
+               8:             TypePointer Function 7(ivec3)
+              10:             TypePointer Input 7(ivec3)
+11(gl_LaunchIDEXT):     10(ptr) Variable Input
+14(gl_LaunchSizeEXT):     10(ptr) Variable Input
+              16:             TypeFloat 32
+              17:             TypeVector 16(float) 3
+              18:             TypePointer Function 17(fvec3)
+              20:             TypePointer Input 17(fvec3)
+21(gl_WorldRayOriginEXT):     20(ptr) Variable Input
+24(gl_WorldRayDirectionEXT):     20(ptr) Variable Input
+              26:             TypePointer Function 16(float)
+              28:             TypePointer Input 16(float)
+29(gl_RayTminEXT):     28(ptr) Variable Input
+32(gl_RayTmaxEXT):     28(ptr) Variable Input
+              34:             TypeAccelerationStructureKHR
+              35:             TypePointer UniformConstant 34
+      36(accEXT):     35(ptr) Variable UniformConstant
+              38:      6(int) Constant 0
+              39:      6(int) Constant 1
+              40:      6(int) Constant 2
+              41:      6(int) Constant 3
+              42:   16(float) Constant 1056964608
+              43:   17(fvec3) ConstantComposite 42 42 42
+              44:   16(float) Constant 1065353216
+              45:   17(fvec3) ConstantComposite 44 44 44
+              46:   16(float) Constant 1061158912
+              47:             TypeInt 32 1
+              48:     47(int) Constant 1
+              49:             TypeVector 16(float) 4
+              50:             TypePointer RayPayloadKHR 49(fvec4)
+51(localPayload):     50(ptr) Variable RayPayloadKHR
+              52:             TypePointer IncomingRayPayloadKHR 49(fvec4)
+53(incomingPayload):     52(ptr) Variable IncomingRayPayloadKHR
+         4(main):           2 Function None 3
+               5:             Label
+           9(v0):      8(ptr) Variable Function
+          13(v1):      8(ptr) Variable Function
+          19(v2):     18(ptr) Variable Function
+          23(v3):     18(ptr) Variable Function
+          27(v4):     26(ptr) Variable Function
+          31(v5):     26(ptr) Variable Function
+              12:    7(ivec3) Load 11(gl_LaunchIDEXT)
+                              Store 9(v0) 12
+              15:    7(ivec3) Load 14(gl_LaunchSizeEXT)
+                              Store 13(v1) 15
+              22:   17(fvec3) Load 21(gl_WorldRayOriginEXT)
+                              Store 19(v2) 22
+              25:   17(fvec3) Load 24(gl_WorldRayDirectionEXT)
+                              Store 23(v3) 25
+              30:   16(float) Load 29(gl_RayTminEXT)
+                              Store 27(v4) 30
+              33:   16(float) Load 32(gl_RayTmaxEXT)
+                              Store 31(v5) 33
+              37:          34 Load 36(accEXT)
+                              TraceRayKHR 37 38 39 40 41 38 43 42 45 46 48
+                              Return
+                              FunctionEnd
diff --git a/third_party/glslang/src/Test/baseResults/spv.ext.MissShader_Errors.rmiss.out b/third_party/glslang/src/Test/baseResults/spv.ext.MissShader_Errors.rmiss.out
new file mode 100644
index 0000000..929a2a7
--- /dev/null
+++ b/third_party/glslang/src/Test/baseResults/spv.ext.MissShader_Errors.rmiss.out
@@ -0,0 +1,21 @@
+spv.ext.MissShader_Errors.rmiss
+ERROR: 0:3: 'hitAttributeEXT' : not supported in this stage: miss
+ERROR: 0:6: 'gl_PrimitiveID' : undeclared identifier 
+ERROR: 0:6: '=' :  cannot convert from ' temp float' to ' temp highp int'
+ERROR: 0:7: 'gl_InstanceID' : undeclared identifier (Did you mean gl_InstanceIndex?)
+ERROR: 0:7: '=' :  cannot convert from ' temp float' to ' temp highp int'
+ERROR: 0:8: 'gl_InstanceCustomIndexEXT' : undeclared identifier 
+ERROR: 0:8: '=' :  cannot convert from ' temp float' to ' temp highp int'
+ERROR: 0:9: 'gl_ObjectToWorldEXT' : undeclared identifier 
+ERROR: 0:9: '=' :  cannot convert from ' temp float' to ' temp highp 4X3 matrix of float'
+ERROR: 0:10: 'gl_WorldToObjectEXT' : undeclared identifier 
+ERROR: 0:10: '=' :  cannot convert from ' temp float' to ' temp highp 4X3 matrix of float'
+ERROR: 0:11: 'gl_HitTEXT' : undeclared identifier 
+ERROR: 0:12: 'gl_HitKindEXT' : undeclared identifier 
+ERROR: 0:13: 'reportIntersectionEXT' : no matching overloaded function found 
+ERROR: 0:14: 'ignoreIntersectionEXT' : no matching overloaded function found 
+ERROR: 0:15: 'terminateRayEXT' : no matching overloaded function found 
+ERROR: 16 compilation errors.  No code generated.
+
+
+SPIR-V is not generated for failed compile or link
diff --git a/third_party/glslang/src/Test/baseResults/spv.ext.RayCallable.rcall.out b/third_party/glslang/src/Test/baseResults/spv.ext.RayCallable.rcall.out
new file mode 100644
index 0000000..ac3b2b5
--- /dev/null
+++ b/third_party/glslang/src/Test/baseResults/spv.ext.RayCallable.rcall.out
@@ -0,0 +1,60 @@
+spv.ext.RayCallable.rcall
+// Module Version 10000
+// Generated by (magic number): 80008
+// Id's are bound by 30
+
+                              Capability RayTracingProvisionalKHR
+                              Extension  "SPV_KHR_ray_tracing"
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint CallableKHR 4  "main" 11 14
+                              Source GLSL 460
+                              SourceExtension  "GL_EXT_ray_tracing"
+                              Name 4  "main"
+                              Name 9  "id"
+                              Name 11  "gl_LaunchIDEXT"
+                              Name 13  "size"
+                              Name 14  "gl_LaunchSizeEXT"
+                              Name 16  "dataBlock"
+                              MemberName 16(dataBlock) 0  "data1"
+                              Name 18  ""
+                              Name 29  "data0"
+                              Decorate 11(gl_LaunchIDEXT) BuiltIn LaunchIdKHR
+                              Decorate 14(gl_LaunchSizeEXT) BuiltIn LaunchSizeKHR
+                              Decorate 16(dataBlock) Block
+                              Decorate 18 Location 1
+                              Decorate 29(data0) Location 0
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeInt 32 0
+               7:             TypeVector 6(int) 3
+               8:             TypePointer Function 7(ivec3)
+              10:             TypePointer Input 7(ivec3)
+11(gl_LaunchIDEXT):     10(ptr) Variable Input
+14(gl_LaunchSizeEXT):     10(ptr) Variable Input
+   16(dataBlock):             TypeStruct 6(int)
+              17:             TypePointer IncomingCallableDataKHR 16(dataBlock)
+              18:     17(ptr) Variable IncomingCallableDataKHR
+              19:             TypeInt 32 1
+              20:     19(int) Constant 0
+              21:      6(int) Constant 256
+              22:             TypePointer IncomingCallableDataKHR 6(int)
+              24:      6(int) Constant 2
+              25:     19(int) Constant 1
+              26:             TypeFloat 32
+              27:             TypeVector 26(float) 4
+              28:             TypePointer CallableDataKHR 27(fvec4)
+       29(data0):     28(ptr) Variable CallableDataKHR
+         4(main):           2 Function None 3
+               5:             Label
+           9(id):      8(ptr) Variable Function
+        13(size):      8(ptr) Variable Function
+              12:    7(ivec3) Load 11(gl_LaunchIDEXT)
+                              Store 9(id) 12
+              15:    7(ivec3) Load 14(gl_LaunchSizeEXT)
+                              Store 13(size) 15
+              23:     22(ptr) AccessChain 18 20
+                              Store 23 21
+                              ExecuteCallableKHR 24 25
+                              Return
+                              FunctionEnd
diff --git a/third_party/glslang/src/Test/baseResults/spv.ext.RayCallable_Errors.rcall.out b/third_party/glslang/src/Test/baseResults/spv.ext.RayCallable_Errors.rcall.out
new file mode 100644
index 0000000..4699342
--- /dev/null
+++ b/third_party/glslang/src/Test/baseResults/spv.ext.RayCallable_Errors.rcall.out
@@ -0,0 +1,35 @@
+spv.ext.RayCallable_Errors.rcall
+ERROR: 0:3: 'hitAttributeEXT' : not supported in this stage: callable
+ERROR: 0:4: 'rayPayloadEXT' : not supported in this stage: callable
+ERROR: 0:5: 'rayPayloadInEXT' : not supported in this stage: callable
+ERROR: 0:9: 'gl_PrimitiveID' : undeclared identifier 
+ERROR: 0:9: '=' :  cannot convert from ' temp float' to ' temp highp int'
+ERROR: 0:10: 'gl_InstanceID' : undeclared identifier (Did you mean gl_InstanceIndex?)
+ERROR: 0:10: '=' :  cannot convert from ' temp float' to ' temp highp int'
+ERROR: 0:11: 'gl_InstanceCustomIndexEXT' : undeclared identifier 
+ERROR: 0:11: '=' :  cannot convert from ' temp float' to ' temp highp int'
+ERROR: 0:12: 'gl_WorldRayOriginEXT' : undeclared identifier 
+ERROR: 0:12: '=' :  cannot convert from ' temp float' to ' temp highp 3-component vector of float'
+ERROR: 0:13: 'gl_WorldRayDirectionEXT' : undeclared identifier 
+ERROR: 0:13: '=' :  cannot convert from ' temp float' to ' temp highp 3-component vector of float'
+ERROR: 0:14: 'gl_ObjectRayOriginEXT' : undeclared identifier 
+ERROR: 0:14: '=' :  cannot convert from ' temp float' to ' temp highp 3-component vector of float'
+ERROR: 0:15: 'gl_ObjectRayDirectionEXT' : undeclared identifier 
+ERROR: 0:15: '=' :  cannot convert from ' temp float' to ' temp highp 3-component vector of float'
+ERROR: 0:16: 'gl_RayTminEXT' : undeclared identifier 
+ERROR: 0:17: 'gl_RayTmaxEXT' : undeclared identifier 
+ERROR: 0:18: 'gl_ObjectToWorldEXT' : undeclared identifier 
+ERROR: 0:18: '=' :  cannot convert from ' temp float' to ' temp highp 4X3 matrix of float'
+ERROR: 0:19: 'gl_WorldToObjectEXT' : undeclared identifier 
+ERROR: 0:19: '=' :  cannot convert from ' temp float' to ' temp highp 4X3 matrix of float'
+ERROR: 0:20: 'gl_HitTEXT' : undeclared identifier 
+ERROR: 0:21: 'gl_HitKindEXT' : undeclared identifier 
+ERROR: 0:22: 'gl_IncomingRayFlagsEXT' : undeclared identifier 
+ERROR: 0:22: '=' :  cannot convert from ' temp float' to ' temp highp uint'
+ERROR: 0:23: 'reportIntersectionEXT' : no matching overloaded function found 
+ERROR: 0:24: 'ignoreIntersectionEXT' : no matching overloaded function found 
+ERROR: 0:25: 'terminateRayEXT' : no matching overloaded function found 
+ERROR: 30 compilation errors.  No code generated.
+
+
+SPIR-V is not generated for failed compile or link
diff --git a/third_party/glslang/src/Test/baseResults/spv.ext.RayConstants.rgen.out b/third_party/glslang/src/Test/baseResults/spv.ext.RayConstants.rgen.out
new file mode 100644
index 0000000..5903ec9
--- /dev/null
+++ b/third_party/glslang/src/Test/baseResults/spv.ext.RayConstants.rgen.out
@@ -0,0 +1,46 @@
+spv.ext.RayConstants.rgen
+// Module Version 10000
+// Generated by (magic number): 80008
+// Id's are bound by 27
+
+                              Capability RayTracingProvisionalKHR
+                              Extension  "SPV_KHR_ray_tracing"
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint RayGenerationKHR 4  "main"
+                              Source GLSL 460
+                              SourceExtension  "GL_EXT_ray_tracing"
+                              Name 4  "main"
+                              Name 8  "accEXT"
+                              Name 26  "payload"
+                              Decorate 8(accEXT) DescriptorSet 0
+                              Decorate 8(accEXT) Binding 0
+                              Decorate 26(payload) Location 0
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeAccelerationStructureKHR
+               7:             TypePointer UniformConstant 6
+       8(accEXT):      7(ptr) Variable UniformConstant
+              10:             TypeInt 32 0
+              11:     10(int) Constant 255
+              12:     10(int) Constant 0
+              13:     10(int) Constant 1
+              14:             TypeFloat 32
+              15:             TypeVector 14(float) 3
+              16:   14(float) Constant 0
+              17:   15(fvec3) ConstantComposite 16 16 16
+              18:   14(float) Constant 1056964608
+              19:   14(float) Constant 1065353216
+              20:   15(fvec3) ConstantComposite 19 19 19
+              21:   14(float) Constant 1061158912
+              22:             TypeInt 32 1
+              23:     22(int) Constant 1
+              24:             TypeVector 14(float) 4
+              25:             TypePointer RayPayloadKHR 24(fvec4)
+     26(payload):     25(ptr) Variable RayPayloadKHR
+         4(main):           2 Function None 3
+               5:             Label
+               9:           6 Load 8(accEXT)
+                              TraceRayKHR 9 11 12 13 13 12 17 18 20 21 23
+                              Return
+                              FunctionEnd
diff --git a/third_party/glslang/src/Test/baseResults/spv.ext.RayGenShader.rgen.out b/third_party/glslang/src/Test/baseResults/spv.ext.RayGenShader.rgen.out
new file mode 100644
index 0000000..da16fa4
--- /dev/null
+++ b/third_party/glslang/src/Test/baseResults/spv.ext.RayGenShader.rgen.out
@@ -0,0 +1,104 @@
+spv.ext.RayGenShader.rgen
+// Module Version 10000
+// Generated by (magic number): 80008
+// Id's are bound by 58
+
+                              Capability RayTraversalPrimitiveCullingProvisionalKHR
+                              Capability RayTracingProvisionalKHR
+                              Extension  "SPV_KHR_ray_tracing"
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint RayGenerationKHR 4  "main" 11 21
+                              Source GLSL 460
+                              SourceExtension  "GL_EXT_ray_flags_primitive_culling"
+                              SourceExtension  "GL_EXT_ray_tracing"
+                              Name 4  "main"
+                              Name 8  "lx"
+                              Name 11  "gl_LaunchIDEXT"
+                              Name 16  "ly"
+                              Name 20  "sx"
+                              Name 21  "gl_LaunchSizeEXT"
+                              Name 24  "sy"
+                              Name 29  "accEXT0"
+                              Name 38  "block"
+                              MemberName 38(block) 0  "dir"
+                              MemberName 38(block) 1  "origin"
+                              Name 40  ""
+                              Name 51  "accEXT1"
+                              Name 54  "imageu"
+                              Name 57  "payload"
+                              Decorate 11(gl_LaunchIDEXT) BuiltIn LaunchIdKHR
+                              Decorate 21(gl_LaunchSizeEXT) BuiltIn LaunchSizeKHR
+                              Decorate 29(accEXT0) DescriptorSet 0
+                              Decorate 29(accEXT0) Binding 0
+                              MemberDecorate 38(block) 0 Offset 0
+                              MemberDecorate 38(block) 1 Offset 16
+                              Decorate 38(block) BufferBlock
+                              Decorate 51(accEXT1) DescriptorSet 0
+                              Decorate 51(accEXT1) Binding 1
+                              Decorate 54(imageu) DescriptorSet 0
+                              Decorate 54(imageu) Binding 2
+                              Decorate 57(payload) Location 0
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeInt 32 0
+               7:             TypePointer Function 6(int)
+               9:             TypeVector 6(int) 3
+              10:             TypePointer Input 9(ivec3)
+11(gl_LaunchIDEXT):     10(ptr) Variable Input
+              12:      6(int) Constant 0
+              13:             TypePointer Input 6(int)
+              17:      6(int) Constant 1
+21(gl_LaunchSizeEXT):     10(ptr) Variable Input
+              27:             TypeAccelerationStructureKHR
+              28:             TypePointer UniformConstant 27
+     29(accEXT0):     28(ptr) Variable UniformConstant
+              35:      6(int) Constant 768
+              36:             TypeFloat 32
+              37:             TypeVector 36(float) 3
+       38(block):             TypeStruct 37(fvec3) 37(fvec3)
+              39:             TypePointer ShaderRecordBufferKHR 38(block)
+              40:     39(ptr) Variable ShaderRecordBufferKHR
+              41:             TypeInt 32 1
+              42:     41(int) Constant 1
+              43:             TypePointer ShaderRecordBufferKHR 37(fvec3)
+              46:   36(float) Constant 1056964608
+              47:     41(int) Constant 0
+              50:   36(float) Constant 1061158912
+     51(accEXT1):     28(ptr) Variable UniformConstant
+              52:             TypeImage 6(int) 2D nonsampled format:R32ui
+              53:             TypePointer UniformConstant 52
+      54(imageu):     53(ptr) Variable UniformConstant
+              55:             TypeVector 36(float) 4
+              56:             TypePointer RayPayloadKHR 55(fvec4)
+     57(payload):     56(ptr) Variable RayPayloadKHR
+         4(main):           2 Function None 3
+               5:             Label
+           8(lx):      7(ptr) Variable Function
+          16(ly):      7(ptr) Variable Function
+          20(sx):      7(ptr) Variable Function
+          24(sy):      7(ptr) Variable Function
+              14:     13(ptr) AccessChain 11(gl_LaunchIDEXT) 12
+              15:      6(int) Load 14
+                              Store 8(lx) 15
+              18:     13(ptr) AccessChain 11(gl_LaunchIDEXT) 17
+              19:      6(int) Load 18
+                              Store 16(ly) 19
+              22:     13(ptr) AccessChain 21(gl_LaunchSizeEXT) 12
+              23:      6(int) Load 22
+                              Store 20(sx) 23
+              25:     13(ptr) AccessChain 21(gl_LaunchSizeEXT) 17
+              26:      6(int) Load 25
+                              Store 24(sy) 26
+              30:          27 Load 29(accEXT0)
+              31:      6(int) Load 8(lx)
+              32:      6(int) Load 16(ly)
+              33:      6(int) Load 20(sx)
+              34:      6(int) Load 24(sy)
+              44:     43(ptr) AccessChain 40 42
+              45:   37(fvec3) Load 44
+              48:     43(ptr) AccessChain 40 47
+              49:   37(fvec3) Load 48
+                              TraceRayKHR 30 31 32 33 34 35 45 46 49 50 42
+                              Return
+                              FunctionEnd
diff --git a/third_party/glslang/src/Test/baseResults/spv.ext.RayGenShader11.rgen.out b/third_party/glslang/src/Test/baseResults/spv.ext.RayGenShader11.rgen.out
new file mode 100644
index 0000000..30ed902
--- /dev/null
+++ b/third_party/glslang/src/Test/baseResults/spv.ext.RayGenShader11.rgen.out
@@ -0,0 +1,91 @@
+spv.ext.RayGenShader11.rgen
+// Module Version 10000
+// Generated by (magic number): 80008
+// Id's are bound by 53
+
+                              Capability RayTracingProvisionalKHR
+                              Extension  "SPV_KHR_ray_tracing"
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint RayGenerationKHR 4  "main" 11 21
+                              Source GLSL 460
+                              SourceExtension  "GL_EXT_ray_tracing"
+                              Name 4  "main"
+                              Name 8  "lx"
+                              Name 11  "gl_LaunchIDEXT"
+                              Name 16  "ly"
+                              Name 20  "sx"
+                              Name 21  "gl_LaunchSizeEXT"
+                              Name 24  "sy"
+                              Name 29  "accEXT"
+                              Name 37  "block"
+                              MemberName 37(block) 0  "dir"
+                              MemberName 37(block) 1  "origin"
+                              Name 39  ""
+                              Name 52  "payload"
+                              Decorate 11(gl_LaunchIDEXT) BuiltIn LaunchIdKHR
+                              Decorate 21(gl_LaunchSizeEXT) BuiltIn LaunchSizeKHR
+                              Decorate 29(accEXT) DescriptorSet 0
+                              Decorate 29(accEXT) Binding 0
+                              MemberDecorate 37(block) 0 Offset 0
+                              MemberDecorate 37(block) 1 Offset 16
+                              Decorate 37(block) BufferBlock
+                              Decorate 52(payload) Location 0
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeInt 32 0
+               7:             TypePointer Function 6(int)
+               9:             TypeVector 6(int) 3
+              10:             TypePointer Input 9(ivec3)
+11(gl_LaunchIDEXT):     10(ptr) Variable Input
+              12:      6(int) Constant 0
+              13:             TypePointer Input 6(int)
+              17:      6(int) Constant 1
+21(gl_LaunchSizeEXT):     10(ptr) Variable Input
+              27:             TypeAccelerationStructureKHR
+              28:             TypePointer UniformConstant 27
+      29(accEXT):     28(ptr) Variable UniformConstant
+              35:             TypeFloat 32
+              36:             TypeVector 35(float) 3
+       37(block):             TypeStruct 36(fvec3) 36(fvec3)
+              38:             TypePointer ShaderRecordBufferKHR 37(block)
+              39:     38(ptr) Variable ShaderRecordBufferKHR
+              40:             TypeInt 32 1
+              41:     40(int) Constant 1
+              42:             TypePointer ShaderRecordBufferKHR 36(fvec3)
+              45:   35(float) Constant 1056964608
+              46:     40(int) Constant 0
+              49:   35(float) Constant 1061158912
+              50:             TypeVector 35(float) 4
+              51:             TypePointer RayPayloadKHR 50(fvec4)
+     52(payload):     51(ptr) Variable RayPayloadKHR
+         4(main):           2 Function None 3
+               5:             Label
+           8(lx):      7(ptr) Variable Function
+          16(ly):      7(ptr) Variable Function
+          20(sx):      7(ptr) Variable Function
+          24(sy):      7(ptr) Variable Function
+              14:     13(ptr) AccessChain 11(gl_LaunchIDEXT) 12
+              15:      6(int) Load 14
+                              Store 8(lx) 15
+              18:     13(ptr) AccessChain 11(gl_LaunchIDEXT) 17
+              19:      6(int) Load 18
+                              Store 16(ly) 19
+              22:     13(ptr) AccessChain 21(gl_LaunchSizeEXT) 12
+              23:      6(int) Load 22
+                              Store 20(sx) 23
+              25:     13(ptr) AccessChain 21(gl_LaunchSizeEXT) 17
+              26:      6(int) Load 25
+                              Store 24(sy) 26
+              30:          27 Load 29(accEXT)
+              31:      6(int) Load 8(lx)
+              32:      6(int) Load 16(ly)
+              33:      6(int) Load 20(sx)
+              34:      6(int) Load 24(sy)
+              43:     42(ptr) AccessChain 39 41
+              44:   36(fvec3) Load 43
+              47:     42(ptr) AccessChain 39 46
+              48:   36(fvec3) Load 47
+                              TraceRayKHR 30 31 32 33 34 12 44 45 48 49 41
+                              Return
+                              FunctionEnd
diff --git a/third_party/glslang/src/Test/baseResults/spv.ext.RayGenShaderArray.rgen.out b/third_party/glslang/src/Test/baseResults/spv.ext.RayGenShaderArray.rgen.out
new file mode 100644
index 0000000..3962bcb
--- /dev/null
+++ b/third_party/glslang/src/Test/baseResults/spv.ext.RayGenShaderArray.rgen.out
@@ -0,0 +1,141 @@
+spv.ext.RayGenShaderArray.rgen
+// Module Version 10000
+// Generated by (magic number): 80008
+// Id's are bound by 89
+
+                              Capability ShaderNonUniformEXT
+                              Capability RuntimeDescriptorArrayEXT
+                              Capability RayTracingProvisionalKHR
+                              Extension  "SPV_EXT_descriptor_indexing"
+                              Extension  "SPV_KHR_ray_tracing"
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint RayGenerationKHR 4  "main" 11 21
+                              Source GLSL 460
+                              SourceExtension  "GL_EXT_nonuniform_qualifier"
+                              SourceExtension  "GL_EXT_ray_tracing"
+                              Name 4  "main"
+                              Name 8  "lx"
+                              Name 11  "gl_LaunchIDEXT"
+                              Name 16  "ly"
+                              Name 20  "sx"
+                              Name 21  "gl_LaunchSizeEXT"
+                              Name 24  "sy"
+                              Name 30  "accEXT0"
+                              Name 34  "block"
+                              MemberName 34(block) 0  "dir"
+                              MemberName 34(block) 1  "origin"
+                              MemberName 34(block) 2  "i"
+                              Name 36  ""
+                              Name 60  "accEXT1"
+                              Name 88  "payload"
+                              Decorate 11(gl_LaunchIDEXT) BuiltIn LaunchIdKHR
+                              Decorate 21(gl_LaunchSizeEXT) BuiltIn LaunchSizeKHR
+                              Decorate 30(accEXT0) DescriptorSet 0
+                              Decorate 30(accEXT0) Binding 0
+                              MemberDecorate 34(block) 0 Offset 0
+                              MemberDecorate 34(block) 1 Offset 16
+                              MemberDecorate 34(block) 2 Offset 28
+                              Decorate 34(block) BufferBlock
+                              Decorate 60(accEXT1) DescriptorSet 0
+                              Decorate 60(accEXT1) Binding 1
+                              Decorate 75 DecorationNonUniformEXT
+                              Decorate 76 DecorationNonUniformEXT
+                              Decorate 77 DecorationNonUniformEXT
+                              Decorate 88(payload) Location 0
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeInt 32 0
+               7:             TypePointer Function 6(int)
+               9:             TypeVector 6(int) 3
+              10:             TypePointer Input 9(ivec3)
+11(gl_LaunchIDEXT):     10(ptr) Variable Input
+              12:      6(int) Constant 0
+              13:             TypePointer Input 6(int)
+              17:      6(int) Constant 1
+21(gl_LaunchSizeEXT):     10(ptr) Variable Input
+              27:             TypeAccelerationStructureKHR
+              28:             TypeRuntimeArray 27
+              29:             TypePointer UniformConstant 28
+     30(accEXT0):     29(ptr) Variable UniformConstant
+              31:             TypeFloat 32
+              32:             TypeVector 31(float) 3
+              33:             TypeInt 32 1
+       34(block):             TypeStruct 32(fvec3) 32(fvec3) 33(int)
+              35:             TypePointer ShaderRecordBufferKHR 34(block)
+              36:     35(ptr) Variable ShaderRecordBufferKHR
+              37:     33(int) Constant 2
+              38:             TypePointer ShaderRecordBufferKHR 33(int)
+              41:             TypePointer UniformConstant 27
+              48:     33(int) Constant 1
+              49:             TypePointer ShaderRecordBufferKHR 32(fvec3)
+              52:   31(float) Constant 1056964608
+              53:     33(int) Constant 0
+              56:   31(float) Constant 1061158912
+              57:      6(int) Constant 2
+              58:             TypeArray 27 57
+              59:             TypePointer UniformConstant 58
+     60(accEXT1):     59(ptr) Variable UniformConstant
+              86:             TypeVector 31(float) 4
+              87:             TypePointer RayPayloadKHR 86(fvec4)
+     88(payload):     87(ptr) Variable RayPayloadKHR
+         4(main):           2 Function None 3
+               5:             Label
+           8(lx):      7(ptr) Variable Function
+          16(ly):      7(ptr) Variable Function
+          20(sx):      7(ptr) Variable Function
+          24(sy):      7(ptr) Variable Function
+              14:     13(ptr) AccessChain 11(gl_LaunchIDEXT) 12
+              15:      6(int) Load 14
+                              Store 8(lx) 15
+              18:     13(ptr) AccessChain 11(gl_LaunchIDEXT) 17
+              19:      6(int) Load 18
+                              Store 16(ly) 19
+              22:     13(ptr) AccessChain 21(gl_LaunchSizeEXT) 12
+              23:      6(int) Load 22
+                              Store 20(sx) 23
+              25:     13(ptr) AccessChain 21(gl_LaunchSizeEXT) 17
+              26:      6(int) Load 25
+                              Store 24(sy) 26
+              39:     38(ptr) AccessChain 36 37
+              40:     33(int) Load 39
+              42:     41(ptr) AccessChain 30(accEXT0) 40
+              43:          27 Load 42
+              44:      6(int) Load 8(lx)
+              45:      6(int) Load 16(ly)
+              46:      6(int) Load 20(sx)
+              47:      6(int) Load 24(sy)
+              50:     49(ptr) AccessChain 36 48
+              51:   32(fvec3) Load 50
+              54:     49(ptr) AccessChain 36 53
+              55:   32(fvec3) Load 54
+                              TraceRayKHR 43 44 45 46 47 12 51 52 55 56 48
+              61:     38(ptr) AccessChain 36 37
+              62:     33(int) Load 61
+              63:     41(ptr) AccessChain 60(accEXT1) 62
+              64:          27 Load 63
+              65:      6(int) Load 8(lx)
+              66:      6(int) Load 16(ly)
+              67:      6(int) Load 20(sx)
+              68:      6(int) Load 24(sy)
+              69:     49(ptr) AccessChain 36 48
+              70:   32(fvec3) Load 69
+              71:     49(ptr) AccessChain 36 53
+              72:   32(fvec3) Load 71
+                              TraceRayKHR 64 65 66 67 68 12 70 52 72 56 48
+              73:     38(ptr) AccessChain 36 37
+              74:     33(int) Load 73
+              75:     33(int) CopyObject 74
+              76:     41(ptr) AccessChain 30(accEXT0) 75
+              77:          27 Load 76
+              78:      6(int) Load 8(lx)
+              79:      6(int) Load 16(ly)
+              80:      6(int) Load 20(sx)
+              81:      6(int) Load 24(sy)
+              82:     49(ptr) AccessChain 36 48
+              83:   32(fvec3) Load 82
+              84:     49(ptr) AccessChain 36 53
+              85:   32(fvec3) Load 84
+                              TraceRayKHR 77 78 79 80 81 12 83 52 85 56 48
+                              Return
+                              FunctionEnd
diff --git a/third_party/glslang/src/Test/baseResults/spv.ext.RayGenShader_Errors.rgen.out b/third_party/glslang/src/Test/baseResults/spv.ext.RayGenShader_Errors.rgen.out
new file mode 100644
index 0000000..6dc7480
--- /dev/null
+++ b/third_party/glslang/src/Test/baseResults/spv.ext.RayGenShader_Errors.rgen.out
@@ -0,0 +1,40 @@
+spv.ext.RayGenShader_Errors.rgen
+ERROR: 0:3: 'hitAttributeEXT' : not supported in this stage: ray-generation
+ERROR: 0:4: 'rayPayloadInEXT' : not supported in this stage: ray-generation
+ERROR: 0:5: 'shaderRecordNV' : can only be used with a buffer 
+ERROR: 0:9: 'binding' : cannot be used with shaderRecordNV 
+ERROR: 0:12: 'set' : cannot be used with shaderRecordNV 
+ERROR: 0:23: 'accelerationStructureNV' : accelerationStructureNV can only be used in uniform variables or function parameters: a
+ERROR: 0:23: '=' :  cannot convert from ' const int' to ' temp accelerationStructureNV'
+ERROR: 0:24: 'gl_PrimitiveID' : undeclared identifier 
+ERROR: 0:24: '=' :  cannot convert from ' temp float' to ' temp highp int'
+ERROR: 0:25: 'gl_InstanceID' : undeclared identifier (Did you mean gl_InstanceIndex?)
+ERROR: 0:25: '=' :  cannot convert from ' temp float' to ' temp highp int'
+ERROR: 0:26: 'gl_InstanceCustomIndexEXT' : undeclared identifier 
+ERROR: 0:26: '=' :  cannot convert from ' temp float' to ' temp highp int'
+ERROR: 0:27: 'gl_WorldRayOriginEXT' : undeclared identifier 
+ERROR: 0:27: '=' :  cannot convert from ' temp float' to ' temp highp 3-component vector of float'
+ERROR: 0:28: 'gl_WorldRayDirectionEXT' : undeclared identifier 
+ERROR: 0:28: '=' :  cannot convert from ' temp float' to ' temp highp 3-component vector of float'
+ERROR: 0:29: 'gl_ObjectRayOriginEXT' : undeclared identifier 
+ERROR: 0:29: '=' :  cannot convert from ' temp float' to ' temp highp 3-component vector of float'
+ERROR: 0:30: 'gl_ObjectRayDirectionEXT' : undeclared identifier 
+ERROR: 0:30: '=' :  cannot convert from ' temp float' to ' temp highp 3-component vector of float'
+ERROR: 0:31: 'gl_RayTminEXT' : undeclared identifier 
+ERROR: 0:32: 'gl_RayTmaxEXT' : undeclared identifier 
+ERROR: 0:33: 'gl_ObjectToWorldEXT' : undeclared identifier 
+ERROR: 0:33: '=' :  cannot convert from ' temp float' to ' temp highp 4X3 matrix of float'
+ERROR: 0:34: 'gl_WorldToObjectEXT' : undeclared identifier 
+ERROR: 0:34: '=' :  cannot convert from ' temp float' to ' temp highp 4X3 matrix of float'
+ERROR: 0:35: 'gl_HitTEXT' : undeclared identifier 
+ERROR: 0:36: 'gl_HitKindEXT' : undeclared identifier 
+ERROR: 0:37: 'reportIntersectionEXT' : no matching overloaded function found 
+ERROR: 0:38: 'ignoreIntersectionEXT' : no matching overloaded function found 
+ERROR: 0:39: 'terminateRayEXT' : no matching overloaded function found 
+ERROR: 0:40: 'assign' :  l-value required "anon@3" (can't modify a shaderrecordnv qualified buffer)
+ERROR: 33 compilation errors.  No code generated.
+
+
+ERROR: Linking ray-generation stage: Only one shaderRecordNV buffer block is allowed per stage
+
+SPIR-V is not generated for failed compile or link
diff --git a/third_party/glslang/src/Test/baseResults/spv.specTexture.frag.out b/third_party/glslang/src/Test/baseResults/spv.specTexture.frag.out
new file mode 100755
index 0000000..a4cf47d
--- /dev/null
+++ b/third_party/glslang/src/Test/baseResults/spv.specTexture.frag.out
@@ -0,0 +1,43 @@
+spv.specTexture.frag
+// Module Version 10000
+// Generated by (magic number): 80008
+// Id's are bound by 23
+
+                              Capability Shader
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Fragment 4  "main" 9
+                              ExecutionMode 4 OriginLowerLeft
+                              Source GLSL 450
+                              Name 4  "main"
+                              Name 9  "color_out"
+                              Name 13  "tex"
+                              Name 19  "offs"
+                              Decorate 9(color_out) Location 0
+                              Decorate 13(tex) DescriptorSet 0
+                              Decorate 13(tex) Binding 0
+                              Decorate 19(offs) SpecId 1
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypeVector 6(float) 4
+               8:             TypePointer Output 7(fvec4)
+    9(color_out):      8(ptr) Variable Output
+              10:             TypeImage 6(float) 2D sampled format:Unknown
+              11:             TypeSampledImage 10
+              12:             TypePointer UniformConstant 11
+         13(tex):     12(ptr) Variable UniformConstant
+              15:             TypeVector 6(float) 2
+              16:    6(float) Constant 0
+              17:   15(fvec2) ConstantComposite 16 16
+              18:             TypeInt 32 1
+        19(offs):     18(int) SpecConstant 0
+              20:             TypeVector 18(int) 2
+              21:   20(ivec2) SpecConstantComposite 19(offs) 19(offs)
+         4(main):           2 Function None 3
+               5:             Label
+              14:          11 Load 13(tex)
+              22:    7(fvec4) ImageSampleExplicitLod 14 17 Lod ConstOffset 16 21
+                              Store 9(color_out) 22
+                              Return
+                              FunctionEnd
diff --git a/third_party/glslang/src/Test/baseResults/vulkan.frag.out b/third_party/glslang/src/Test/baseResults/vulkan.frag.out
index c81ed25..e620898 100644
--- a/third_party/glslang/src/Test/baseResults/vulkan.frag.out
+++ b/third_party/glslang/src/Test/baseResults/vulkan.frag.out
@@ -7,14 +7,14 @@
 ERROR: 0:9: 'binding' : sampler/texture/image requires layout(binding=X) 
 ERROR: 0:10: 'binding' : sampler/texture/image requires layout(binding=X) 
 ERROR: 0:14: 'sampler2D' : sampler-constructor requires two arguments 
-ERROR: 0:15: 'sampler2D' : sampler-constructor first argument must be a scalar textureXXX type 
-ERROR: 0:16: 'sampler2D' : sampler-constructor first argument must be a scalar textureXXX type 
-ERROR: 0:17: 'sampler2D' : sampler-constructor second argument must be a scalar type 'sampler' 
-ERROR: 0:18: 'sampler2D' : sampler-constructor second argument must be a scalar type 'sampler' 
-ERROR: 0:19: 'sampler2D' : sampler-constructor second argument must be a scalar type 'sampler' 
+ERROR: 0:15: 'sampler2D' : sampler-constructor first argument must be a scalar *texture* type 
+ERROR: 0:16: 'sampler2D' : sampler-constructor first argument must be a scalar *texture* type 
+ERROR: 0:17: 'sampler2D' : sampler-constructor second argument must be a scalar sampler or samplerShadow 
+ERROR: 0:18: 'sampler2D' : sampler-constructor second argument must be a scalar sampler or samplerShadow 
+ERROR: 0:19: 'sampler2D' : sampler-constructor second argument must be a scalar sampler or samplerShadow 
 ERROR: 0:21: 'sampler3D' : sampler-constructor cannot make an array of samplers 
-ERROR: 0:22: 'sampler2D' : sampler-constructor first argument must be a scalar textureXXX type 
-ERROR: 0:23: 'sampler2D' : sampler-constructor first argument must match type and dimensionality of constructor type 
+ERROR: 0:22: 'sampler2D' : sampler-constructor first argument must be a scalar *texture* type 
+ERROR: 0:23: 'sampler2D' : sampler-constructor first argument must be a *texture* type matching the dimensionality and sampled type of the constructor 
 ERROR: 0:28: 'sampler2D' : sampler/image types can only be used in uniform variables or function parameters: s2D
 ERROR: 0:29: 'sampler3D' : sampler-constructor cannot make an array of samplers 
 ERROR: 0:29: 'sampler3D' : sampler/image types can only be used in uniform variables or function parameters: s3d
diff --git a/third_party/glslang/src/Test/constFold.frag b/third_party/glslang/src/Test/constFold.frag
index daecaa2..49373e6 100644
--- a/third_party/glslang/src/Test/constFold.frag
+++ b/third_party/glslang/src/Test/constFold.frag
@@ -122,6 +122,9 @@
 
 const mat2 mm2 = mat2(1.0, 2.0, 3.0, 4.0);

 const mat3x2 mm32 = mat3x2(10.0, 11.0, 12.0, 13.0, 14.0, 15.0);

+const mat2 m22 = mat2(vec4(1.0, 2.0, 3.0, 4.0));

+const mat3x4 mm34 = mat3x4(7.0);

+const vec4 mv4 = vec4(m22);

 

 void foo3()

 {

diff --git a/third_party/glslang/src/Test/foo.h b/third_party/glslang/src/Test/foo.h
index 7f79340..236277c 100644
--- a/third_party/glslang/src/Test/foo.h
+++ b/third_party/glslang/src/Test/foo.h
@@ -1 +1 @@
-#error should not be included
\ No newline at end of file
+#error should not be included
diff --git a/third_party/glslang/src/Test/inc2/foo.h b/third_party/glslang/src/Test/inc2/foo.h
index fd09e80..ea1e5ba 100644
--- a/third_party/glslang/src/Test/inc2/foo.h
+++ b/third_party/glslang/src/Test/inc2/foo.h
@@ -1 +1 @@
-float4 i6;
\ No newline at end of file
+float4 i6;
diff --git a/third_party/glslang/src/Test/link.multiAnonBlocksInvalid.0.0.vert b/third_party/glslang/src/Test/link.multiAnonBlocksInvalid.0.0.vert
new file mode 100755
index 0000000..106dd25
--- /dev/null
+++ b/third_party/glslang/src/Test/link.multiAnonBlocksInvalid.0.0.vert
@@ -0,0 +1,52 @@
+#version 430
+
+// Error: Block has different members
+layout (std140) uniform Block
+{
+	mat4 uProj;
+};
+
+// Error: BufferBlock has different members
+buffer BufferBlock
+{
+	vec4 b;
+};
+
+// Error: Vertex has different members
+out Vertex
+{
+	vec4 v1;
+};
+
+// Error: ColorBlock has different members
+layout (std140) uniform ColorBlock
+{
+	vec4 color1;
+	vec4 color2;
+	// Error, redeclare varaible in another anonymous block
+	vec4 v1;
+};
+
+// Error: NamedBlock is anonymous in other compilation unit
+layout (std140) uniform NamedBlock
+{
+	mat4 m;
+} myName;
+
+vec4 getWorld();
+vec4 getColor2();
+
+out vec4 oColor;
+
+// Error: redeclare varaibles that are in anonymous blocks
+out vec4 v1;
+uniform mat4 uProj;
+
+void
+main()
+{
+	oColor = color1 * getColor2();
+	v1 = color1;
+
+	gl_Position = uProj * getWorld();
+}
diff --git a/third_party/glslang/src/Test/link.multiAnonBlocksInvalid.0.1.vert b/third_party/glslang/src/Test/link.multiAnonBlocksInvalid.0.1.vert
new file mode 100755
index 0000000..8b4c7f8
--- /dev/null
+++ b/third_party/glslang/src/Test/link.multiAnonBlocksInvalid.0.1.vert
@@ -0,0 +1,48 @@
+#version 430
+
+// Error: ColorBlock has different members
+layout (std140) uniform ColorBlock
+{
+	vec4 color2;
+};
+
+// Error: Block has different members
+layout (std140) uniform Block
+{
+	mat4 uProj;
+	mat4 uWorld;
+};
+
+// Error: Vertex has different members
+out Vertex
+{
+	vec4 v1;
+	vec4 v2;
+};
+
+// Error BufferBlock has different members
+buffer BufferBlock
+{
+	vec4 a;
+};
+
+// Error: NamedBlock is anonymous in other compilation unit
+layout (std140) uniform NamedBlock
+{
+	mat4 m;
+};
+
+
+in vec4 P;
+
+vec4 getColor2()
+{
+	return color2;
+}
+
+vec4 getWorld()
+{
+	return uWorld * P;
+	v2 = vec4(1);
+}
+
diff --git a/third_party/glslang/src/Test/link.multiAnonBlocksValid.0.0.vert b/third_party/glslang/src/Test/link.multiAnonBlocksValid.0.0.vert
new file mode 100755
index 0000000..470d815
--- /dev/null
+++ b/third_party/glslang/src/Test/link.multiAnonBlocksValid.0.0.vert
@@ -0,0 +1,38 @@
+#version 430
+
+// Verify that matching by block name is working, not
+// instance name, which was at one point failing on this
+// test due to E.g anon@1 being different blocks for
+// different compilation units
+
+layout (std140) uniform Block
+{
+	mat4 uProj;
+	mat4 uWorld;
+};
+
+out Vertex
+{
+	vec4 v1;
+	vec4 v2;
+};
+
+layout (std140) uniform ColorBlock
+{
+	vec4 color1;
+	vec4 color2;
+};
+
+vec4 getWorld();
+vec4 getColor2();
+
+out vec4 oColor;
+
+void
+main()
+{
+	oColor = color1 * getColor2();
+	v1 = color1;
+
+	gl_Position = uProj * getWorld();
+}
diff --git a/third_party/glslang/src/Test/link.multiAnonBlocksValid.0.1.vert b/third_party/glslang/src/Test/link.multiAnonBlocksValid.0.1.vert
new file mode 100755
index 0000000..e7dccbe
--- /dev/null
+++ b/third_party/glslang/src/Test/link.multiAnonBlocksValid.0.1.vert
@@ -0,0 +1,34 @@
+#version 430
+
+layout (std140) uniform ColorBlock
+{
+	vec4 color1;
+	vec4 color2;
+};
+
+layout (std140) uniform Block
+{
+	mat4 uProj;
+	mat4 uWorld;
+};
+
+out Vertex
+{
+	vec4 v1;
+	vec4 v2;
+};
+
+
+in vec4 P;
+
+vec4 getColor2()
+{
+	return color2;
+}
+
+vec4 getWorld()
+{
+	return uWorld * P;
+	v2 = vec4(1);
+}
+
diff --git a/third_party/glslang/src/Test/link.multiBlocksInvalid.0.0.vert b/third_party/glslang/src/Test/link.multiBlocksInvalid.0.0.vert
new file mode 100755
index 0000000..19bc049
--- /dev/null
+++ b/third_party/glslang/src/Test/link.multiBlocksInvalid.0.0.vert
@@ -0,0 +1,40 @@
+#version 430
+
+// Verify that blocks with different instance names
+// are correctly detected as invalid non-matching blocks
+// when they are matched up by block name
+layout (std140) uniform Block
+{
+	mat4 uProj;
+} uD;
+
+out Vertex
+{
+	vec4 v1;
+} oV;
+
+layout (std140) uniform ColorBlock
+{
+	vec4 color1;
+} uC;
+
+// Error, buffer blocks and uniform blocks share the
+// same namespace for their block name
+layout (std430) buffer ColorBlock
+{
+	vec4 color1;
+} uBufC;
+
+vec4 getWorld();
+vec4 getColor2();
+
+out vec4 oColor;
+
+void
+main()
+{
+	oColor = uC.color1 * getColor2();
+	oV.v1 = uC.color1 + uBufC.color1;
+
+	gl_Position = uD.uProj * getWorld();
+}
diff --git a/third_party/glslang/src/Test/link.multiBlocksInvalid.0.1.vert b/third_party/glslang/src/Test/link.multiBlocksInvalid.0.1.vert
new file mode 100755
index 0000000..8b9ccd1
--- /dev/null
+++ b/third_party/glslang/src/Test/link.multiBlocksInvalid.0.1.vert
@@ -0,0 +1,31 @@
+#version 430
+
+layout (std140) uniform ColorBlock
+{
+	vec4 color2;
+} uColorB;
+
+layout (std140) uniform Block
+{
+	mat4 uWorld;
+} uDefaultB;
+
+out Vertex
+{
+	vec4 v2;
+} oVert;
+
+
+in vec4 P;
+
+vec4 getColor2()
+{
+	return uColorB.color2;
+}
+
+vec4 getWorld()
+{
+	return uDefaultB.uWorld * P;
+	oVert.v2 = vec4(1);
+}
+
diff --git a/third_party/glslang/src/Test/link.multiBlocksValid.1.0.vert b/third_party/glslang/src/Test/link.multiBlocksValid.1.0.vert
new file mode 100755
index 0000000..b21683b
--- /dev/null
+++ b/third_party/glslang/src/Test/link.multiBlocksValid.1.0.vert
@@ -0,0 +1,32 @@
+#version 430
+layout (std140) uniform Block
+{
+	mat4 uProj;
+	mat4 uWorld;
+} a;
+
+out Vertex
+{
+	vec4 v1;
+	vec4 v2;
+} b;
+
+layout (std140) uniform ColorBlock
+{
+	vec4 color1;
+	vec4 color2;
+} c;
+
+vec4 getWorld();
+vec4 getColor2();
+
+out vec4 oColor;
+
+void
+main()
+{
+	oColor = c.color1 * getColor2();
+	b.v1 = c.color1;
+
+	gl_Position = a.uProj * getWorld();
+}
diff --git a/third_party/glslang/src/Test/link.multiBlocksValid.1.1.vert b/third_party/glslang/src/Test/link.multiBlocksValid.1.1.vert
new file mode 100755
index 0000000..d86a0d1
--- /dev/null
+++ b/third_party/glslang/src/Test/link.multiBlocksValid.1.1.vert
@@ -0,0 +1,34 @@
+#version 430
+
+layout (std140) uniform ColorBlock
+{
+	vec4 color1;
+	vec4 color2;
+} a;
+
+layout (std140) uniform Block
+{
+	mat4 uProj;
+	mat4 uWorld;
+} b;
+
+out Vertex
+{
+	vec4 v1;
+	vec4 v2;
+} c;
+
+
+in vec4 P;
+
+vec4 getColor2()
+{
+	return a.color2;
+}
+
+vec4 getWorld()
+{
+	return b.uWorld * P;
+	c.v2 = vec4(1);
+}
+
diff --git a/third_party/glslang/src/Test/link.vk.multiBlocksValid.0.0.vert b/third_party/glslang/src/Test/link.vk.multiBlocksValid.0.0.vert
new file mode 100755
index 0000000..81747ec
--- /dev/null
+++ b/third_party/glslang/src/Test/link.vk.multiBlocksValid.0.0.vert
@@ -0,0 +1,49 @@
+#version 430
+
+// OK: different instance names is allowed in other unit
+layout (std140, binding = 0) uniform MatrixBlock
+{
+	mat4 uProj;
+	mat4 uWorld;
+} uM;
+
+// OK: other unit has it as anonymous, but that is allowed
+out Vertex
+{
+	vec4 v1;
+	vec4 v2;
+} oV;
+
+// OK: different instance names is allowed in other unit
+layout (std140, binding = 1) uniform ColorBlock
+{
+	vec4 color1;
+	bool b;
+	vec4 color2;
+	vec4 color3;
+} uC;
+
+// OK: different instance names is allowed in other unit
+layout (std430, binding = 1) buffer BufferBlock
+{
+	mat4 p;
+} uBuf;
+
+layout (std430, binding = 0) buffer SecondaryColorBlock
+{
+	vec4 c;
+} uColorBuf;
+
+vec4 getWorld();
+vec4 getColor2();
+
+out vec4 oColor;
+
+void
+main()
+{
+	oColor = uC.color1 * getColor2() * uColorBuf.c;
+	oV.v1 = uC.color1;
+
+	gl_Position = uM.uProj * getWorld();
+}
diff --git a/third_party/glslang/src/Test/link.vk.multiBlocksValid.0.1.vert b/third_party/glslang/src/Test/link.vk.multiBlocksValid.0.1.vert
new file mode 100755
index 0000000..5267778
--- /dev/null
+++ b/third_party/glslang/src/Test/link.vk.multiBlocksValid.0.1.vert
@@ -0,0 +1,46 @@
+#version 430
+
+// OK: different instance names is allowed in other unit
+layout (std140, binding = 1) uniform ColorBlock
+{
+	vec4 color1;
+	bool b;
+	vec4 color2;
+	vec4 color3;
+} uColor;
+
+// OK: different instance names is allowed in other unit
+layout (std430, binding = 1) buffer BufferBlock
+{
+	mat4 p;
+} uBuffer;
+
+// OK: different instance names is allowed in other unit
+layout (std140, binding = 0) uniform MatrixBlock
+{
+	mat4 uProj;
+	mat4 uWorld;
+} uMatrix;
+
+// OK, it's allowed for input/output interfaces to
+// be anonymous is one unit and not in another
+out Vertex
+{
+	vec4 v1;
+	vec4 v2;
+};
+
+
+in vec4 P;
+
+vec4 getColor2()
+{
+	return uColor.color2;
+}
+
+vec4 getWorld()
+{
+	v1 = vec4(1);
+	return uMatrix.uWorld * P;
+}
+
diff --git a/third_party/glslang/src/Test/link.vk.multiBlocksValid.1.0.geom b/third_party/glslang/src/Test/link.vk.multiBlocksValid.1.0.geom
new file mode 100755
index 0000000..9811b08
--- /dev/null
+++ b/third_party/glslang/src/Test/link.vk.multiBlocksValid.1.0.geom
@@ -0,0 +1,62 @@
+#version 430
+
+layout (triangles) in;
+layout (triangle_strip, max_vertices = 3) out;
+
+// OK: different instance names is allowed
+layout (std140, binding = 0) uniform MatrixBlock
+{
+	mat4 uProj;
+	mat4 uWorld;
+} uM;
+
+// Verify that in/out blocks with same block name work
+in Vertex
+{
+	vec4 v1;
+	vec4 v2;
+} iV[3];
+
+out Vertex
+{
+	vec4 val1;
+} oV;
+
+// OK: different instance names is allowed
+layout (std140, binding = 1) uniform ColorBlock
+{
+	vec4 color1;
+	bool b;
+	vec4 color2;
+	vec4 color3;
+} uC;
+
+// OK: different instance names is allowed
+layout (std430, binding = 1) buffer BufferBlock
+{
+	mat4 p;
+} uBuf;
+
+vec4 getWorld(int i);
+vec4 getColor2();
+
+out vec4 oColor;
+
+float globalF;
+
+void
+main()
+{
+	oColor = uC.color1 * getColor2();
+
+	globalF = 1.0;
+
+	for (int i = 0; i < 3; i++)
+	{
+		gl_Position = uM.uProj * getWorld(i);
+		oV.val1 = uC.color1 + iV[i].v2 * globalF;
+		EmitVertex();
+	}
+
+	EndPrimitive();
+}
diff --git a/third_party/glslang/src/Test/link.vk.multiBlocksValid.1.1.geom b/third_party/glslang/src/Test/link.vk.multiBlocksValid.1.1.geom
new file mode 100755
index 0000000..f372343
--- /dev/null
+++ b/third_party/glslang/src/Test/link.vk.multiBlocksValid.1.1.geom
@@ -0,0 +1,54 @@
+#version 430
+
+layout (triangles) in;
+layout (triangle_strip, max_vertices = 3) out;
+
+// OK: different instance names is allowed
+layout (std140, binding = 1) uniform ColorBlock
+{
+	vec4 color1;
+	bool b;
+	vec4 color2;
+	vec4 color3;
+} uColor;
+
+// OK: different instance names is allowed
+layout (std430, binding = 1) buffer BufferBlock
+{
+	mat4 p;
+} uBuffer;
+
+// OK: different instance names is allowed
+layout (std140, binding = 0) uniform MatrixBlock
+{
+	mat4 uProj;
+	mat4 uWorld;
+} uMatrix;
+
+// OK, it's allowed for input/output interfaces to
+// be anonymous is one unit and not in another
+out Vertex
+{
+	vec4 val1;
+};
+
+in Vertex
+{
+	vec4 v1;
+	vec4 v2;
+} iVV[];
+
+
+in vec4 P[3];
+
+vec4 getColor2()
+{
+	return uColor.color2;
+}
+
+vec4 getWorld(int i)
+{
+	val1 = vec4(1);
+	return uMatrix.uWorld * iVV[i].v1;
+}
+
diff --git a/third_party/glslang/src/Test/link.vk.pcNamingInvalid.0.0.vert b/third_party/glslang/src/Test/link.vk.pcNamingInvalid.0.0.vert
new file mode 100755
index 0000000..26a7586
--- /dev/null
+++ b/third_party/glslang/src/Test/link.vk.pcNamingInvalid.0.0.vert
@@ -0,0 +1,21 @@
+#version 450
+layout (push_constant) uniform Block
+{
+	mat4 uWorld;
+	mat4 uProj;
+	vec4 color1;
+	vec4 color2;
+} a;
+
+vec4 getWorld();
+vec4 getColor2();
+
+out vec4 oColor;
+
+void
+main()
+{
+	oColor = a.color1 * getColor2();
+
+	gl_Position = a.uProj * getWorld();
+}
diff --git a/third_party/glslang/src/Test/link.vk.pcNamingInvalid.0.1.vert b/third_party/glslang/src/Test/link.vk.pcNamingInvalid.0.1.vert
new file mode 100755
index 0000000..47d2314
--- /dev/null
+++ b/third_party/glslang/src/Test/link.vk.pcNamingInvalid.0.1.vert
@@ -0,0 +1,22 @@
+#version 450
+
+layout (push_constant) uniform Block2
+{
+	mat4 uWorld;
+	mat4 uProj;
+	vec4 color1;
+	vec4 color2;
+} a;
+
+in vec4 P;
+
+vec4 getColor2()
+{
+	return a.color2;
+}
+
+vec4 getWorld()
+{
+	return a.uWorld * P;
+}
+
diff --git a/third_party/glslang/src/Test/link.vk.pcNamingValid.0.0.vert b/third_party/glslang/src/Test/link.vk.pcNamingValid.0.0.vert
new file mode 100755
index 0000000..7df2190
--- /dev/null
+++ b/third_party/glslang/src/Test/link.vk.pcNamingValid.0.0.vert
@@ -0,0 +1,21 @@
+#version 450
+layout (push_constant) uniform PCBlock
+{
+	mat4 uWorld;
+	mat4 uProj;
+	vec4 color1;
+	vec4 color2;
+} a;
+
+vec4 getWorld();
+vec4 getColor2();
+
+layout(location = 0) out vec4 oColor;
+
+void
+main()
+{
+	oColor = a.color1 * getColor2();
+
+	gl_Position = a.uProj * getWorld();
+}
diff --git a/third_party/glslang/src/Test/link.vk.pcNamingValid.0.1.vert b/third_party/glslang/src/Test/link.vk.pcNamingValid.0.1.vert
new file mode 100755
index 0000000..9a4b41b
--- /dev/null
+++ b/third_party/glslang/src/Test/link.vk.pcNamingValid.0.1.vert
@@ -0,0 +1,22 @@
+#version 450
+
+layout (push_constant) uniform PCBlock
+{
+	mat4 uWorld;
+	mat4 uProj;
+	vec4 color1;
+	vec4 color2;
+} b;
+
+layout(location = 0) in vec4 P;
+
+vec4 getColor2()
+{
+	return b.color2;
+}
+
+vec4 getWorld()
+{
+	return b.uWorld * P;
+}
+
diff --git a/third_party/glslang/src/Test/rayQuery-allOps.Error.rgen b/third_party/glslang/src/Test/rayQuery-allOps.Error.rgen
new file mode 100644
index 0000000..d25a183
--- /dev/null
+++ b/third_party/glslang/src/Test/rayQuery-allOps.Error.rgen
@@ -0,0 +1,212 @@
+#version 460
+#extension GL_NV_ray_tracing : enable
+#extension GL_EXT_ray_query : enable
+
+struct Ray
+{
+    vec3 pos;
+    float tmin;
+    vec3 dir;
+    float tmax;
+};
+
+layout(std430, set = 0, binding = 0) buffer Log
+{
+    uint x;
+    uint y;
+};
+
+layout(binding = 1, set = 0) uniform accelerationStructureEXT rtas;
+layout(std430, set = 0, binding = 2) buffer Rays { Ray rays[]; };
+
+void doSomething()
+{
+    x = 0;
+    y = 0;
+}
+
+Ray makeRayDesc()
+{
+    Ray ray;
+    ray.pos= vec3(0,0,0);
+    ray.dir = vec3(1,0,0);
+    ray.tmin = 0.0f;
+    ray.tmax = 9999.0;
+    return ray;
+}
+
+void main()
+{
+    Ray ray = makeRayDesc();
+    rayQueryEXT rayQuery;
+    rayQueryInitializeEXT(rayQuery, rtas, gl_RayFlagsNoneEXT, 0xFF, ray.pos, ray.tmin, ray.dir, ray.tmax);
+
+    mat4x3 _mat4x3;
+    mat3x4 _mat3x4;
+
+    while (rayQueryProceedEXT(rayQuery) == 1)
+    {
+        int candidateType = rayQueryGetIntersectionTypeEXT(rayQuery, false);
+        switch(candidateType)
+        {
+            case gl_RayQueryCandidateIntersectionTriangleEXT:
+
+                rayQueryTerminateEXT(rayQuery);
+                _mat4x3 = rayQueryGetIntersectionObjectToWorldEXT(rayQuery, false);
+                _mat3x4 = transpose(_mat4x3);
+                rayQueryConfirmIntersectionEXT(rayQuery);
+
+                if (rayQueryGetIntersectionFrontFaceEXT(rayQuery, true) == 1)
+                {
+                    doSomething();
+                }
+
+                if (rayQueryGetIntersectionBarycentricsEXT(rayQuery, true) == 0)
+                {
+                    doSomething();
+                }
+
+                if (rayQueryGetIntersectionInstanceCustomIndexEXT(rayQuery, true))
+                {
+                    doSomething();
+                }
+
+                if (rayQueryGetIntersectionInstanceIdEXT(rayQuery, true))
+                {
+                    doSomething();
+                }
+
+                if (rayQueryGetIntersectionObjectRayDirectionEXT(rayQuery, true) > 0)
+                {
+                    doSomething();
+                }
+
+                if (rayQueryGetIntersectionObjectRayOriginEXT(rayQuery, true) > 0)
+                {
+                    doSomething();
+                }
+
+                if (rayQueryGetIntersectionPrimitiveIndexEXT(rayQuery, true))
+                {
+                    doSomething();
+                }
+
+                if (rayQueryGetIntersectionTEXT(rayQuery, true))
+                {
+                    doSomething();
+                }
+
+                if (rayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetEXT(rayQuery, true))
+                {
+                    doSomething();
+                }
+                break;
+
+            case gl_RayQueryCandidateIntersectionAABBEXT:
+            {
+                _mat4x3 = rayQueryGetIntersectionObjectToWorldEXT(rayQuery, false);
+                _mat3x4 = transpose(_mat4x3);
+                if (rayQueryGetIntersectionCandidateAABBOpaqueEXT(rayQuery))
+                {
+                    doSomething();
+                }
+
+                int t = 1;
+                rayQueryGenerateIntersectionEXT(rayQuery, t);
+                rayQueryTerminateEXT(rayQuery);
+                break;
+            }
+        }
+    }
+
+    if(_mat3x4[0][0] == _mat4x3[0][0])
+    {
+        doSomething();
+    }
+
+    int committedStatus = rayQueryGetIntersectionTypeEXT(rayQuery, true);
+
+    switch(committedStatus)
+    {
+        case gl_RayQueryCommittedIntersectionNoneEXT :
+            _mat4x3 = rayQueryGetIntersectionWorldToObjectEXT(rayQuery, false);
+            _mat3x4 = transpose(_mat4x3);
+            break;
+
+        case gl_RayQueryCommittedIntersectionTriangleEXT :
+            _mat4x3 = rayQueryGetIntersectionWorldToObjectEXT(rayQuery, true);
+            _mat3x4 = transpose(_mat4x3);
+
+            if (rayQueryGetIntersectionFrontFaceEXT(rayQuery, true))
+            {
+                doSomething();
+            }
+
+            if (rayQueryGetIntersectionBarycentricsEXT(rayQuery, true) == 0)
+            {
+                doSomething();
+            }
+            break;
+
+        case gl_RayQueryCommittedIntersectionGeneratedEXT :
+
+            if(rayQueryGetIntersectionGeometryIndexEXT(rayQuery, true) > 0)
+            {
+                doSomething();
+            }
+
+            if(rayQueryGetIntersectionInstanceIdEXT(rayQuery, true))
+            {
+                doSomething();
+            }
+
+            if(rayQueryGetIntersectionInstanceCustomIndexEXT(rayQuery, true))
+            {
+                doSomething();
+            }
+
+            if(rayQueryGetIntersectionObjectRayDirectionEXT(rayQuery, true) > 0)
+            {
+                doSomething();
+            }
+
+            if(rayQueryGetIntersectionObjectRayOriginEXT(rayQuery, true) > 0)
+            {
+                doSomething();
+            }
+
+            if(rayQueryGetIntersectionPrimitiveIndexEXT(rayQuery, true))
+            {
+                doSomething();
+            }
+
+            if(rayQueryGetIntersectionTEXT(rayQuery, true))
+            {
+                doSomething();
+            }
+            break;
+    }
+
+    if (_mat3x4[0][0] == _mat4x3[0][0])
+    {
+        doSomething();
+    }
+
+    if (rayQueryGetRayFlagsEXT(rayQuery))
+    {
+        doSomething();
+    }
+
+    if (rayQueryGetRayTMinEXT(rayQuery))
+    {
+        doSomething();
+    }
+
+    vec3 o = rayQueryGetWorldRayOriginEXT(rayQuery);
+    vec3 d = rayQueryGetWorldRayDirectionEXT(rayQuery);
+
+    if (o.x == d.z)
+    {
+        doSomething();
+    }
+}
diff --git a/third_party/glslang/src/Test/rayQuery-allOps.comp b/third_party/glslang/src/Test/rayQuery-allOps.comp
new file mode 100644
index 0000000..80f2593
--- /dev/null
+++ b/third_party/glslang/src/Test/rayQuery-allOps.comp
@@ -0,0 +1,212 @@
+#version 460
+#extension GL_EXT_ray_query : enable
+#extension GL_EXT_ray_flags_primitive_culling : enable
+
+struct Ray
+{
+    vec3 pos;
+    float tmin;
+    vec3 dir;
+    float tmax;
+};
+
+layout(std430, set = 0, binding = 0) buffer Log
+{
+    uint x;
+    uint y;
+};
+
+layout(binding = 1, set = 0) uniform accelerationStructureEXT rtas;
+layout(std430, set = 0, binding = 2) buffer Rays { Ray rays[]; };
+
+void doSomething()
+{
+    x = 0;
+    y = 0;
+}
+
+Ray makeRayDesc()
+{
+    Ray ray;
+    ray.pos= vec3(0,0,0);
+    ray.dir = vec3(1,0,0);
+    ray.tmin = 0.0f;
+    ray.tmax = 9999.0;
+    return ray;
+}
+
+void main()
+{
+    Ray ray = makeRayDesc();
+    rayQueryEXT rayQuery;
+    rayQueryInitializeEXT(rayQuery, rtas, gl_RayFlagsNoneEXT, 0xFF, ray.pos, ray.tmin, ray.dir, ray.tmax);
+
+    mat4x3 _mat4x3;
+    mat3x4 _mat3x4;
+
+    while (rayQueryProceedEXT(rayQuery))
+    {
+        uint candidateType = rayQueryGetIntersectionTypeEXT(rayQuery, false);
+        switch(candidateType)
+        {
+            case gl_RayQueryCandidateIntersectionTriangleEXT:
+
+                rayQueryTerminateEXT(rayQuery);
+                _mat4x3 = rayQueryGetIntersectionObjectToWorldEXT(rayQuery, false);
+                _mat3x4 = transpose(_mat4x3);
+                rayQueryConfirmIntersectionEXT(rayQuery);
+
+                if (rayQueryGetIntersectionFrontFaceEXT(rayQuery, true))
+                {
+                    doSomething();
+                }
+
+                if (rayQueryGetIntersectionBarycentricsEXT(rayQuery, true).x == 0)
+                {
+                    doSomething();
+                }
+
+                if (rayQueryGetIntersectionInstanceCustomIndexEXT(rayQuery, true) > 0)
+                {
+                    doSomething();
+                }
+
+                if (rayQueryGetIntersectionInstanceIdEXT(rayQuery, true) > 0)
+                {
+                    doSomething();
+                }
+
+                if (rayQueryGetIntersectionObjectRayDirectionEXT(rayQuery, true).x > 0)
+                {
+                    doSomething();
+                }
+
+                if (rayQueryGetIntersectionObjectRayOriginEXT(rayQuery, true).x > 0)
+                {
+                    doSomething();
+                }
+
+                if (rayQueryGetIntersectionPrimitiveIndexEXT(rayQuery, true) > 0)
+                {
+                    doSomething();
+                }
+
+                if (rayQueryGetIntersectionTEXT(rayQuery, true) > 0.f)
+                {
+                    doSomething();
+                }
+
+                if (rayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetEXT(rayQuery, true) > 0)
+                {
+                    doSomething();
+                }
+                break;
+
+            case gl_RayQueryCandidateIntersectionAABBEXT:
+            {
+                _mat4x3 = rayQueryGetIntersectionObjectToWorldEXT(rayQuery, false);
+                _mat3x4 = transpose(_mat4x3);
+                if (rayQueryGetIntersectionCandidateAABBOpaqueEXT(rayQuery))
+                {
+                    doSomething();
+                }
+
+                float t = 0.5;
+                rayQueryGenerateIntersectionEXT(rayQuery, t);
+                rayQueryTerminateEXT(rayQuery);
+                break;
+            }
+        }
+    }
+
+    if(_mat3x4[0][0] == _mat4x3[0][0])
+    {
+        doSomething();
+    }
+
+    uint committedStatus = rayQueryGetIntersectionTypeEXT(rayQuery, true);
+
+    switch(committedStatus)
+    {
+        case gl_RayQueryCommittedIntersectionNoneEXT :
+            _mat4x3 = rayQueryGetIntersectionWorldToObjectEXT(rayQuery, false);
+            _mat3x4 = transpose(_mat4x3);
+            break;
+
+        case gl_RayQueryCommittedIntersectionTriangleEXT :
+            _mat4x3 = rayQueryGetIntersectionWorldToObjectEXT(rayQuery, true);
+            _mat3x4 = transpose(_mat4x3);
+
+            if (rayQueryGetIntersectionFrontFaceEXT(rayQuery, true))
+            {
+                doSomething();
+            }
+
+            if (rayQueryGetIntersectionBarycentricsEXT(rayQuery, true).y == 0)
+            {
+                doSomething();
+            }
+            break;
+
+        case gl_RayQueryCommittedIntersectionGeneratedEXT :
+
+            if(rayQueryGetIntersectionGeometryIndexEXT(rayQuery, true) > 0)
+            {
+                doSomething();
+            }
+
+            if(rayQueryGetIntersectionInstanceIdEXT(rayQuery, true) > 0)
+            {
+                doSomething();
+            }
+
+            if(rayQueryGetIntersectionInstanceCustomIndexEXT(rayQuery, true) > 0)
+            {
+                doSomething();
+            }
+
+            if(rayQueryGetIntersectionObjectRayDirectionEXT(rayQuery, true).z > 0)
+            {
+                doSomething();
+            }
+
+            if(rayQueryGetIntersectionObjectRayOriginEXT(rayQuery, true).x > 0)
+            {
+                doSomething();
+            }
+
+            if(rayQueryGetIntersectionPrimitiveIndexEXT(rayQuery, true) > 0)
+            {
+                doSomething();
+            }
+
+            if(rayQueryGetIntersectionTEXT(rayQuery, true) > 0.f)
+            {
+                doSomething();
+            }
+            break;
+    }
+
+    if (_mat3x4[0][0] == _mat4x3[0][0])
+    {
+        doSomething();
+    }
+
+    if (rayQueryGetRayFlagsEXT(rayQuery) > gl_RayFlagsSkipTrianglesEXT)
+    {
+        doSomething();
+    }
+
+    if (rayQueryGetRayTMinEXT(rayQuery) > 0.0)
+    {
+        doSomething();
+    }
+
+    vec3 o = rayQueryGetWorldRayOriginEXT(rayQuery);
+    vec3 d = rayQueryGetWorldRayDirectionEXT(rayQuery);
+
+    if (o.x == d.z)
+    {
+        doSomething();
+    }
+}
diff --git a/third_party/glslang/src/Test/rayQuery-allOps.frag b/third_party/glslang/src/Test/rayQuery-allOps.frag
new file mode 100644
index 0000000..9fdf0c0
--- /dev/null
+++ b/third_party/glslang/src/Test/rayQuery-allOps.frag
@@ -0,0 +1,212 @@
+#version 460
+#extension GL_NV_ray_tracing : enable
+#extension GL_EXT_ray_query : enable
+
+struct Ray
+{
+    vec3 pos;
+    float tmin;
+    vec3 dir;
+    float tmax;
+};
+
+layout(std430, set = 0, binding = 0) buffer Log
+{
+    uint x;
+    uint y;
+};
+
+layout(binding = 1, set = 0) uniform accelerationStructureEXT rtas;
+layout(std430, set = 0, binding = 2) buffer Rays { Ray rays[]; };
+
+void doSomething()
+{
+    x = 0;
+    y = 0;
+}
+
+Ray makeRayDesc()
+{
+    Ray ray;
+    ray.pos= vec3(0,0,0);
+    ray.dir = vec3(1,0,0);
+    ray.tmin = 0.0f;
+    ray.tmax = 9999.0;
+    return ray;
+}
+
+void main()
+{
+    Ray ray = makeRayDesc();
+    rayQueryEXT rayQuery;
+    rayQueryInitializeEXT(rayQuery, rtas, gl_RayFlagsNoneEXT, 0xFF, ray.pos, ray.tmin, ray.dir, ray.tmax);
+
+    mat4x3 _mat4x3;
+    mat3x4 _mat3x4;
+
+    while (rayQueryProceedEXT(rayQuery))
+    {
+        uint candidateType = rayQueryGetIntersectionTypeEXT(rayQuery, false);
+        switch(candidateType)
+        {
+            case gl_RayQueryCandidateIntersectionTriangleEXT:
+
+                rayQueryTerminateEXT(rayQuery);
+                _mat4x3 = rayQueryGetIntersectionObjectToWorldEXT(rayQuery, false);
+                _mat3x4 = transpose(_mat4x3);
+                rayQueryConfirmIntersectionEXT(rayQuery);
+
+                if (rayQueryGetIntersectionFrontFaceEXT(rayQuery, true))
+                {
+                    doSomething();
+                }
+
+                if (rayQueryGetIntersectionBarycentricsEXT(rayQuery, true).x == 0)
+                {
+                    doSomething();
+                }
+
+                if (rayQueryGetIntersectionInstanceCustomIndexEXT(rayQuery, true) > 0)
+                {
+                    doSomething();
+                }
+
+                if (rayQueryGetIntersectionInstanceIdEXT(rayQuery, true) > 0)
+                {
+                    doSomething();
+                }
+
+                if (rayQueryGetIntersectionObjectRayDirectionEXT(rayQuery, true).x > 0)
+                {
+                    doSomething();
+                }
+
+                if (rayQueryGetIntersectionObjectRayOriginEXT(rayQuery, true).x > 0)
+                {
+                    doSomething();
+                }
+
+                if (rayQueryGetIntersectionPrimitiveIndexEXT(rayQuery, true) > 0)
+                {
+                    doSomething();
+                }
+
+                if (rayQueryGetIntersectionTEXT(rayQuery, true) > 0.f)
+                {
+                    doSomething();
+                }
+
+                if (rayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetEXT(rayQuery, true) > 0)
+                {
+                    doSomething();
+                }
+                break;
+
+            case gl_RayQueryCandidateIntersectionAABBEXT:
+            {
+                _mat4x3 = rayQueryGetIntersectionObjectToWorldEXT(rayQuery, false);
+                _mat3x4 = transpose(_mat4x3);
+                if (rayQueryGetIntersectionCandidateAABBOpaqueEXT(rayQuery))
+                {
+                    doSomething();
+                }
+
+                float t = 0.5;
+                rayQueryGenerateIntersectionEXT(rayQuery, t);
+                rayQueryTerminateEXT(rayQuery);
+                break;
+            }
+        }
+    }
+
+    if(_mat3x4[0][0] == _mat4x3[0][0])
+    {
+        doSomething();
+    }
+
+    uint committedStatus = rayQueryGetIntersectionTypeEXT(rayQuery, true);
+
+    switch(committedStatus)
+    {
+        case gl_RayQueryCommittedIntersectionNoneEXT :
+            _mat4x3 = rayQueryGetIntersectionWorldToObjectEXT(rayQuery, false);
+            _mat3x4 = transpose(_mat4x3);
+            break;
+
+        case gl_RayQueryCommittedIntersectionTriangleEXT :
+            _mat4x3 = rayQueryGetIntersectionWorldToObjectEXT(rayQuery, true);
+            _mat3x4 = transpose(_mat4x3);
+
+            if (rayQueryGetIntersectionFrontFaceEXT(rayQuery, true))
+            {
+                doSomething();
+            }
+
+            if (rayQueryGetIntersectionBarycentricsEXT(rayQuery, true).y == 0)
+            {
+                doSomething();
+            }
+            break;
+
+        case gl_RayQueryCommittedIntersectionGeneratedEXT :
+
+            if(rayQueryGetIntersectionGeometryIndexEXT(rayQuery, true) > 0)
+            {
+                doSomething();
+            }
+
+            if(rayQueryGetIntersectionInstanceIdEXT(rayQuery, true) > 0)
+            {
+                doSomething();
+            }
+
+            if(rayQueryGetIntersectionInstanceCustomIndexEXT(rayQuery, true) > 0)
+            {
+                doSomething();
+            }
+
+            if(rayQueryGetIntersectionObjectRayDirectionEXT(rayQuery, true).z > 0)
+            {
+                doSomething();
+            }
+
+            if(rayQueryGetIntersectionObjectRayOriginEXT(rayQuery, true).x > 0)
+            {
+                doSomething();
+            }
+
+            if(rayQueryGetIntersectionPrimitiveIndexEXT(rayQuery, true) > 0)
+            {
+                doSomething();
+            }
+
+            if(rayQueryGetIntersectionTEXT(rayQuery, true) > 0.f)
+            {
+                doSomething();
+            }
+            break;
+    }
+
+    if (_mat3x4[0][0] == _mat4x3[0][0])
+    {
+        doSomething();
+    }
+
+    if (rayQueryGetRayFlagsEXT(rayQuery) > 0)
+    {
+        doSomething();
+    }
+
+    if (rayQueryGetRayTMinEXT(rayQuery) > 0.0)
+    {
+        doSomething();
+    }
+
+    vec3 o = rayQueryGetWorldRayOriginEXT(rayQuery);
+    vec3 d = rayQueryGetWorldRayDirectionEXT(rayQuery);
+
+    if (o.x == d.z)
+    {
+        doSomething();
+    }
+}
diff --git a/third_party/glslang/src/Test/rayQuery-allOps.rgen b/third_party/glslang/src/Test/rayQuery-allOps.rgen
new file mode 100644
index 0000000..9fdf0c0
--- /dev/null
+++ b/third_party/glslang/src/Test/rayQuery-allOps.rgen
@@ -0,0 +1,212 @@
+#version 460
+#extension GL_NV_ray_tracing : enable
+#extension GL_EXT_ray_query : enable
+
+struct Ray
+{
+    vec3 pos;
+    float tmin;
+    vec3 dir;
+    float tmax;
+};
+
+layout(std430, set = 0, binding = 0) buffer Log
+{
+    uint x;
+    uint y;
+};
+
+layout(binding = 1, set = 0) uniform accelerationStructureEXT rtas;
+layout(std430, set = 0, binding = 2) buffer Rays { Ray rays[]; };
+
+void doSomething()
+{
+    x = 0;
+    y = 0;
+}
+
+Ray makeRayDesc()
+{
+    Ray ray;
+    ray.pos= vec3(0,0,0);
+    ray.dir = vec3(1,0,0);
+    ray.tmin = 0.0f;
+    ray.tmax = 9999.0;
+    return ray;
+}
+
+void main()
+{
+    Ray ray = makeRayDesc();
+    rayQueryEXT rayQuery;
+    rayQueryInitializeEXT(rayQuery, rtas, gl_RayFlagsNoneEXT, 0xFF, ray.pos, ray.tmin, ray.dir, ray.tmax);
+
+    mat4x3 _mat4x3;
+    mat3x4 _mat3x4;
+
+    while (rayQueryProceedEXT(rayQuery))
+    {
+        uint candidateType = rayQueryGetIntersectionTypeEXT(rayQuery, false);
+        switch(candidateType)
+        {
+            case gl_RayQueryCandidateIntersectionTriangleEXT:
+
+                rayQueryTerminateEXT(rayQuery);
+                _mat4x3 = rayQueryGetIntersectionObjectToWorldEXT(rayQuery, false);
+                _mat3x4 = transpose(_mat4x3);
+                rayQueryConfirmIntersectionEXT(rayQuery);
+
+                if (rayQueryGetIntersectionFrontFaceEXT(rayQuery, true))
+                {
+                    doSomething();
+                }
+
+                if (rayQueryGetIntersectionBarycentricsEXT(rayQuery, true).x == 0)
+                {
+                    doSomething();
+                }
+
+                if (rayQueryGetIntersectionInstanceCustomIndexEXT(rayQuery, true) > 0)
+                {
+                    doSomething();
+                }
+
+                if (rayQueryGetIntersectionInstanceIdEXT(rayQuery, true) > 0)
+                {
+                    doSomething();
+                }
+
+                if (rayQueryGetIntersectionObjectRayDirectionEXT(rayQuery, true).x > 0)
+                {
+                    doSomething();
+                }
+
+                if (rayQueryGetIntersectionObjectRayOriginEXT(rayQuery, true).x > 0)
+                {
+                    doSomething();
+                }
+
+                if (rayQueryGetIntersectionPrimitiveIndexEXT(rayQuery, true) > 0)
+                {
+                    doSomething();
+                }
+
+                if (rayQueryGetIntersectionTEXT(rayQuery, true) > 0.f)
+                {
+                    doSomething();
+                }
+
+                if (rayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetEXT(rayQuery, true) > 0)
+                {
+                    doSomething();
+                }
+                break;
+
+            case gl_RayQueryCandidateIntersectionAABBEXT:
+            {
+                _mat4x3 = rayQueryGetIntersectionObjectToWorldEXT(rayQuery, false);
+                _mat3x4 = transpose(_mat4x3);
+                if (rayQueryGetIntersectionCandidateAABBOpaqueEXT(rayQuery))
+                {
+                    doSomething();
+                }
+
+                float t = 0.5;
+                rayQueryGenerateIntersectionEXT(rayQuery, t);
+                rayQueryTerminateEXT(rayQuery);
+                break;
+            }
+        }
+    }
+
+    if(_mat3x4[0][0] == _mat4x3[0][0])
+    {
+        doSomething();
+    }
+
+    uint committedStatus = rayQueryGetIntersectionTypeEXT(rayQuery, true);
+
+    switch(committedStatus)
+    {
+        case gl_RayQueryCommittedIntersectionNoneEXT :
+            _mat4x3 = rayQueryGetIntersectionWorldToObjectEXT(rayQuery, false);
+            _mat3x4 = transpose(_mat4x3);
+            break;
+
+        case gl_RayQueryCommittedIntersectionTriangleEXT :
+            _mat4x3 = rayQueryGetIntersectionWorldToObjectEXT(rayQuery, true);
+            _mat3x4 = transpose(_mat4x3);
+
+            if (rayQueryGetIntersectionFrontFaceEXT(rayQuery, true))
+            {
+                doSomething();
+            }
+
+            if (rayQueryGetIntersectionBarycentricsEXT(rayQuery, true).y == 0)
+            {
+                doSomething();
+            }
+            break;
+
+        case gl_RayQueryCommittedIntersectionGeneratedEXT :
+
+            if(rayQueryGetIntersectionGeometryIndexEXT(rayQuery, true) > 0)
+            {
+                doSomething();
+            }
+
+            if(rayQueryGetIntersectionInstanceIdEXT(rayQuery, true) > 0)
+            {
+                doSomething();
+            }
+
+            if(rayQueryGetIntersectionInstanceCustomIndexEXT(rayQuery, true) > 0)
+            {
+                doSomething();
+            }
+
+            if(rayQueryGetIntersectionObjectRayDirectionEXT(rayQuery, true).z > 0)
+            {
+                doSomething();
+            }
+
+            if(rayQueryGetIntersectionObjectRayOriginEXT(rayQuery, true).x > 0)
+            {
+                doSomething();
+            }
+
+            if(rayQueryGetIntersectionPrimitiveIndexEXT(rayQuery, true) > 0)
+            {
+                doSomething();
+            }
+
+            if(rayQueryGetIntersectionTEXT(rayQuery, true) > 0.f)
+            {
+                doSomething();
+            }
+            break;
+    }
+
+    if (_mat3x4[0][0] == _mat4x3[0][0])
+    {
+        doSomething();
+    }
+
+    if (rayQueryGetRayFlagsEXT(rayQuery) > 0)
+    {
+        doSomething();
+    }
+
+    if (rayQueryGetRayTMinEXT(rayQuery) > 0.0)
+    {
+        doSomething();
+    }
+
+    vec3 o = rayQueryGetWorldRayOriginEXT(rayQuery);
+    vec3 d = rayQueryGetWorldRayDirectionEXT(rayQuery);
+
+    if (o.x == d.z)
+    {
+        doSomething();
+    }
+}
diff --git a/third_party/glslang/src/Test/rayQuery-committed.Error.rgen b/third_party/glslang/src/Test/rayQuery-committed.Error.rgen
new file mode 100644
index 0000000..aeb8ec0
--- /dev/null
+++ b/third_party/glslang/src/Test/rayQuery-committed.Error.rgen
@@ -0,0 +1,105 @@
+#version 460
+#extension GL_NV_ray_tracing : enable
+#extension GL_EXT_ray_query : enable
+
+struct Ray
+{
+    vec3 pos;
+    float tmin;
+    vec3 dir;
+    float tmax;
+};
+
+layout(std430, set = 0, binding = 0) buffer Log
+{
+    uint x;
+    uint y;
+};
+
+layout(binding = 1, set = 0) uniform accelerationStructureEXT rtas;
+layout(std430, set = 0, binding = 2) buffer Rays { Ray rays[]; };
+
+void doSomething()
+{
+    x = 0;
+    y = 0;
+}
+
+uint launchIndex()
+{
+    return gl_LaunchIDNV.z*gl_LaunchSizeNV.x*gl_LaunchSizeNV.y + gl_LaunchIDNV.y*gl_LaunchSizeNV.x + gl_LaunchIDNV.x;
+}
+
+void main()
+{
+    uint index = launchIndex();
+    Ray ray = rays[index];
+    rayQueryEXT rayQuery;
+
+    bool committed_true = true;
+    bool committed_false = false;
+
+    rayQueryInitializeEXT(rayQuery, rtas, gl_RayFlagsOpaqueEXT, gl_RayFlagsCullBackFacingTrianglesEXT, ray.pos, ray.tmin, ray.dir, ray.tmax);
+    while (rayQueryProceedEXT(rayQuery))
+    {
+        mat4x3 mat_o2w;
+        mat4x3 mat_w2o;
+
+        uint candidateType = rayQueryGetIntersectionTypeEXT(rayQuery, committed_false);
+        if (candidateType == gl_RayQueryCandidateIntersectionTriangleEXT)
+        {
+            rayQueryTerminateEXT(rayQuery);
+
+            mat_o2w = rayQueryGetIntersectionObjectToWorldEXT(rayQuery, committed_false);
+            mat_w2o = rayQueryGetIntersectionWorldToObjectEXT(rayQuery, committed_false);
+
+            rayQueryConfirmIntersectionEXT(rayQuery);
+
+            if (rayQueryGetIntersectionFrontFaceEXT(rayQuery, committed_true))
+            {
+                doSomething();
+            }
+            if (rayQueryGetIntersectionBarycentricsEXT(rayQuery, committed_true).x == 0)
+            {
+                doSomething();
+            }
+            if (rayQueryGetIntersectionInstanceCustomIndexEXT(rayQuery, committed_true) > 0)
+            {
+                doSomething();
+            }
+            if (rayQueryGetIntersectionInstanceIdEXT(rayQuery, committed_true) > 0)
+            {
+                doSomething();
+            }
+            if (rayQueryGetIntersectionObjectRayDirectionEXT(rayQuery, committed_true).x > 0)
+            {
+                doSomething();
+            }
+            if (rayQueryGetIntersectionObjectRayOriginEXT(rayQuery, committed_true).x > 0)
+            {
+                doSomething();
+            }
+            if (rayQueryGetIntersectionPrimitiveIndexEXT(rayQuery, committed_true) > 0)
+            {
+                doSomething();
+            }
+            if (rayQueryGetIntersectionTEXT(rayQuery, committed_true) > 0.f)
+            {
+                doSomething();
+            }
+            if (rayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetEXT(rayQuery, committed_true) > 0)
+            {
+                doSomething();
+            }
+        }
+    }
+
+    uint committedStatus = rayQueryGetIntersectionTypeEXT(rayQuery, committed_true);
+    if (committedStatus == gl_RayQueryCommittedIntersectionGeneratedEXT)
+    {
+        if (rayQueryGetIntersectionGeometryIndexEXT(rayQuery, committed_true) > 0)
+        {
+            doSomething();
+        }
+    }
+}
diff --git a/third_party/glslang/src/Test/rayQuery-initialize.rgen b/third_party/glslang/src/Test/rayQuery-initialize.rgen
new file mode 100644
index 0000000..ff61800
--- /dev/null
+++ b/third_party/glslang/src/Test/rayQuery-initialize.rgen
@@ -0,0 +1,33 @@
+#version 460
+#extension GL_NV_ray_tracing : enable
+#extension GL_EXT_ray_query : enable
+
+struct Ray
+{
+    vec3 pos;
+    float tmin;
+    vec3 dir;
+    float tmax;
+};
+
+layout(binding = 0, set = 0) uniform accelerationStructureEXT rtas;
+layout(std430, set = 0, binding = 2) buffer Rays { Ray rays[]; };
+
+uint launchIndex()
+{
+    return gl_LaunchIDNV.z*gl_LaunchSizeNV.x*gl_LaunchSizeNV.y + gl_LaunchIDNV.y*gl_LaunchSizeNV.x + gl_LaunchIDNV.x;
+}
+
+void doInitialize(rayQueryEXT rayQuery, Ray ray)
+{
+    rayQueryInitializeEXT(rayQuery, rtas, gl_RayFlagsNoneEXT, gl_RayFlagsCullBackFacingTrianglesEXT, ray.pos, ray.tmin, ray.dir, ray.tmax);
+}
+
+void main()
+{
+    uint index = launchIndex();
+    Ray ray = rays[index];
+    rayQueryEXT rayQuery;
+    doInitialize(rayQuery, ray);
+    rayQueryInitializeEXT(rayQuery, rtas, gl_RayFlagsOpaqueEXT, gl_RayFlagsCullFrontFacingTrianglesEXT, ray.pos, ray.tmin, ray.dir, ray.tmax);
+}
diff --git a/third_party/glslang/src/Test/rayQuery-no-cse.rgen b/third_party/glslang/src/Test/rayQuery-no-cse.rgen
new file mode 100644
index 0000000..ccec76f
--- /dev/null
+++ b/third_party/glslang/src/Test/rayQuery-no-cse.rgen
@@ -0,0 +1,35 @@
+#version 460
+#extension GL_NV_ray_tracing : enable
+#extension GL_EXT_ray_query : enable
+
+struct Ray
+{
+    vec3 pos;
+    float tmin;
+    vec3 dir;
+    float tmax;
+};
+
+layout(binding = 0, set = 0) uniform accelerationStructureEXT rtas;
+layout(std430, set = 0, binding = 2) buffer Rays { Ray rays[]; };
+
+uint launchIndex()
+{
+    return gl_LaunchIDNV.z*gl_LaunchSizeNV.x*gl_LaunchSizeNV.y + gl_LaunchIDNV.y*gl_LaunchSizeNV.x + gl_LaunchIDNV.x;
+}
+
+void doInitialize(rayQueryEXT rayQuery, Ray ray)
+{
+    rayQueryInitializeEXT(rayQuery, rtas, gl_RayFlagsNoneEXT, gl_RayFlagsCullBackFacingTrianglesEXT, ray.pos, ray.tmin, ray.dir, ray.tmax);
+}
+
+void main()
+{
+    uint index = launchIndex();
+    Ray ray = rays[index];
+    rayQueryEXT rayQuery1;
+    rayQueryEXT rayQuery2;
+    doInitialize(rayQuery1, ray);
+    rayQueryInitializeEXT(rayQuery1, rtas, gl_RayFlagsOpaqueEXT, gl_RayFlagsCullFrontFacingTrianglesEXT, ray.pos, ray.tmin, ray.dir, ray.tmax);
+    doInitialize(rayQuery2, ray);
+}
diff --git a/third_party/glslang/src/Test/rayQuery.rgen b/third_party/glslang/src/Test/rayQuery.rgen
new file mode 100644
index 0000000..8d5638f
--- /dev/null
+++ b/third_party/glslang/src/Test/rayQuery.rgen
@@ -0,0 +1,23 @@
+#version 460
+#extension GL_NV_ray_tracing : enable
+#extension GL_EXT_ray_query : enable
+layout(binding = 0, set = 0) uniform accelerationStructureEXT acc0;
+
+layout(shaderRecordNV) buffer block
+{
+	vec3 dir;
+	vec3 origin;
+};
+
+void main()
+{
+    rayQueryEXT localRayQuery;
+    uint rayFlags = gl_RayFlagsOpaqueEXT | gl_RayFlagsSkipClosestHitShaderEXT;
+    float tMin = 0.f;
+    float tMax = 1000.f;
+    rayQueryInitializeEXT(localRayQuery, acc0, rayFlags, 0xFF , origin, tMin, dir, tMax);
+    if (!rayQueryProceedEXT(localRayQuery))
+    {
+        rayQueryTerminateEXT(localRayQuery);
+    }
+}
diff --git a/third_party/glslang/src/Test/spv.Operations.frag b/third_party/glslang/src/Test/spv.Operations.frag
index d34032d..3477a79 100644
--- a/third_party/glslang/src/Test/spv.Operations.frag
+++ b/third_party/glslang/src/Test/spv.Operations.frag
@@ -97,6 +97,13 @@
     u += max(u, uui);

     u += clamp(u, uui, uui);

 

+    // multiple out operands

+    uvec4 msb;

+    uvec4 lsb;

+    umulExtended(uuv4.xyz, uuv4.xyz, msb.xyz, lsb.xyz);

+    u += msb.x + msb.y + msb.z;

+    u += lsb.x + lsb.y + lsb.z;

+

 	//// bool

 	b = isnan(uf);

     b = isinf(f);

diff --git a/third_party/glslang/src/Test/spv.atomicCounter.comp b/third_party/glslang/src/Test/spv.atomicCounter.comp
new file mode 100644
index 0000000..ecb2304
--- /dev/null
+++ b/third_party/glslang/src/Test/spv.atomicCounter.comp
@@ -0,0 +1,26 @@
+#version 450

+

+

+

+layout(binding = 0) uniform atomic_uint counter;

+

+layout(binding = 0, offset = 4) uniform atomic_uint countArr[4];

+shared uint value;

+

+int arrX[gl_WorkGroupSize.x];

+int arrY[gl_WorkGroupSize.y];

+int arrZ[gl_WorkGroupSize.z];

+

+uint func(atomic_uint c)

+{

+    return atomicCounterIncrement(c);

+}

+

+void main()

+{

+    memoryBarrierAtomicCounter();

+    func(counter);

+    uint val = atomicCounter(countArr[2]);

+    atomicCounterDecrement(counter);

+    atomicCounterIncrement(counter);

+}

diff --git a/third_party/glslang/src/Test/spv.ext.AnyHitShader.rahit b/third_party/glslang/src/Test/spv.ext.AnyHitShader.rahit
new file mode 100644
index 0000000..ee7d9c7
--- /dev/null
+++ b/third_party/glslang/src/Test/spv.ext.AnyHitShader.rahit
@@ -0,0 +1,29 @@
+#version 460
+#extension GL_EXT_ray_tracing : enable
+layout(location = 1) rayPayloadInEXT vec4 incomingPayload;
+void main()
+{
+	uvec3 v0 = gl_LaunchIDEXT;
+	uvec3 v1 = gl_LaunchSizeEXT;
+	int v2 = gl_PrimitiveID;
+	int v3 = gl_InstanceID;
+	int v4 = gl_InstanceCustomIndexEXT;
+	vec3 v5 = gl_WorldRayOriginEXT;
+	vec3 v6 = gl_WorldRayDirectionEXT;
+	vec3 v7 = gl_ObjectRayOriginEXT;
+	vec3 v8 = gl_ObjectRayDirectionEXT;
+	float v9 = gl_RayTminEXT;
+	float v10 = gl_RayTmaxEXT;
+	float v11 = gl_HitTEXT;
+	uint v12 = gl_HitKindEXT;
+	mat4x3 v13 = gl_ObjectToWorldEXT;
+	mat4x3 v14 = gl_WorldToObjectEXT;
+    int v15 = gl_GeometryIndexEXT;
+    mat3x4 v16 = gl_ObjectToWorld3x4EXT;
+    mat3x4 v17 = gl_WorldToObject3x4EXT;
+	incomingPayload = vec4(0.5f);
+	if (v2 == 1)
+	    ignoreIntersectionEXT();
+	else
+	    terminateRayEXT();
+}
diff --git a/third_party/glslang/src/Test/spv.ext.AnyHitShader_Errors.rahit b/third_party/glslang/src/Test/spv.ext.AnyHitShader_Errors.rahit
new file mode 100644
index 0000000..f9fd730
--- /dev/null
+++ b/third_party/glslang/src/Test/spv.ext.AnyHitShader_Errors.rahit
@@ -0,0 +1,11 @@
+#version 460
+#extension GL_EXT_ray_tracing : enable
+hitAttributeEXT vec4 payload;                               
+layout(binding = 0, set = 0) uniform accelerationStructureEXT accEXT;
+
+void main()
+{
+    payload.x = 1.0f;                                       // ERROR, cannot write to hitattributeEXT in stage
+    reportIntersectionEXT(1.0, 1U);                          // ERROR, unsupported builtin in stage
+    traceRayEXT(accEXT, 0, 0, 1, 1, 0, vec3(0.0f), 0.5f, vec3(1.0f), 0.75f, 0); // ERROR, unsupported builtin in stage
+}
diff --git a/third_party/glslang/src/Test/spv.ext.ClosestHitShader.rchit b/third_party/glslang/src/Test/spv.ext.ClosestHitShader.rchit
new file mode 100644
index 0000000..3f9bbaa
--- /dev/null
+++ b/third_party/glslang/src/Test/spv.ext.ClosestHitShader.rchit
@@ -0,0 +1,27 @@
+#version 460
+#extension GL_EXT_ray_tracing : enable
+layout(binding = 0, set = 0) uniform accelerationStructureEXT accEXT;
+layout(location = 0) rayPayloadEXT vec4 localPayload;
+layout(location = 1) rayPayloadInEXT vec4 incomingPayload;
+void main()
+{
+	uvec3 v0 = gl_LaunchIDEXT;
+	uvec3 v1 = gl_LaunchSizeEXT;
+	int v2 = gl_PrimitiveID;
+	int v3 = gl_InstanceID;
+	int v4 = gl_InstanceCustomIndexEXT;
+	vec3 v5 = gl_WorldRayOriginEXT;
+	vec3 v6 = gl_WorldRayDirectionEXT;
+	vec3 v7 = gl_ObjectRayOriginEXT;
+	vec3 v8 = gl_ObjectRayDirectionEXT;
+	float v9 = gl_RayTminEXT;
+	float v10 = gl_RayTmaxEXT;
+	float v11 = gl_HitTEXT;
+	uint v12 = gl_HitKindEXT;
+	mat4x3 v13 = gl_ObjectToWorldEXT;
+	mat4x3 v14 = gl_WorldToObjectEXT;
+    int v15 = gl_GeometryIndexEXT;
+    mat3x4 v16 = gl_ObjectToWorld3x4EXT;
+    mat3x4 v17 = gl_WorldToObject3x4EXT;
+	traceRayEXT(accEXT, 0u, 1u, 2u, 3u, 0u, vec3(0.5f), 0.5f, vec3(1.0f), 0.75f, 1);
+}
diff --git a/third_party/glslang/src/Test/spv.ext.ClosestHitShader_Errors.rchit b/third_party/glslang/src/Test/spv.ext.ClosestHitShader_Errors.rchit
new file mode 100644
index 0000000..05e05fe
--- /dev/null
+++ b/third_party/glslang/src/Test/spv.ext.ClosestHitShader_Errors.rchit
@@ -0,0 +1,13 @@
+#version 460
+#extension GL_EXT_ray_tracing : enable
+hitAttributeEXT vec4 payload;
+layout(binding = 0, set = 0) uniform accelerationStructureEXT accEXT;
+
+void main()
+{
+    payload.x = 1.0f;                                       // ERROR, cannot write to hitattributeEXT in stage
+    reportIntersectionEXT(1.0, 1U);                          // ERROR, unsupported builtin in stage 
+    terminateRayEXT();
+    ignoreIntersectionEXT();
+    bool e1 = gl_IncomingRayFlagsEXT == gl_RayFlagsSkipAABBEXT;
+}
diff --git a/third_party/glslang/src/Test/spv.ext.IntersectShader.rint b/third_party/glslang/src/Test/spv.ext.IntersectShader.rint
new file mode 100644
index 0000000..4933ff5
--- /dev/null
+++ b/third_party/glslang/src/Test/spv.ext.IntersectShader.rint
@@ -0,0 +1,23 @@
+#version 460
+#extension GL_EXT_ray_tracing : enable
+hitAttributeEXT vec4 iAttr;
+void main()
+{
+	uvec3 v0 = gl_LaunchIDEXT;
+	uvec3 v1 = gl_LaunchSizeEXT;
+	int v2 = gl_PrimitiveID;
+	int v3 = gl_InstanceID;
+	int v4 = gl_InstanceCustomIndexEXT;
+	vec3 v5 = gl_WorldRayOriginEXT;
+	vec3 v6 = gl_WorldRayDirectionEXT;
+	vec3 v7 = gl_ObjectRayOriginEXT;
+	vec3 v8 = gl_ObjectRayDirectionEXT;
+	float v9 = gl_RayTminEXT;
+	float v10 = gl_RayTmaxEXT;
+	mat4x3 v11 = gl_ObjectToWorldEXT;
+	mat4x3 v12 = gl_WorldToObjectEXT;
+    mat3x4 v13 = gl_ObjectToWorld3x4EXT;
+    mat3x4 v14 = gl_WorldToObject3x4EXT;
+	iAttr = vec4(0.5f,0.5f,0.0f,1.0f);
+	reportIntersectionEXT(0.5, 1U);
+}
diff --git a/third_party/glslang/src/Test/spv.ext.IntersectShader_Errors.rint b/third_party/glslang/src/Test/spv.ext.IntersectShader_Errors.rint
new file mode 100644
index 0000000..e767ca3
--- /dev/null
+++ b/third_party/glslang/src/Test/spv.ext.IntersectShader_Errors.rint
@@ -0,0 +1,11 @@
+#version 460
+#extension GL_EXT_ray_tracing : enable
+rayPayloadInEXT vec4 payloadIn;                             // ERROR, rayPayloadIn unsupported in this stage
+rayPayloadEXT vec4 payload;                                 // ERROR, rayPayload unsuppoted in this stage
+uniform accelerationStructureEXT accEXT;
+void main()
+{
+    float e12 = gl_HitTEXT;                                 // ERROR, unsupported builtin in stage
+    float e13 = gl_HitKindEXT;                              // ERROR, unsupported builtin in stage
+    traceRayEXT(accEXT, 0, 0, 1, 1, 0, vec3(0.0f), 0.5f, vec3(1.0f), 0.75f, 0); // ERROR, unsupported
+}
diff --git a/third_party/glslang/src/Test/spv.ext.MissShader.rmiss b/third_party/glslang/src/Test/spv.ext.MissShader.rmiss
new file mode 100644
index 0000000..e774334
--- /dev/null
+++ b/third_party/glslang/src/Test/spv.ext.MissShader.rmiss
@@ -0,0 +1,15 @@
+#version 460
+#extension GL_EXT_ray_tracing : enable
+layout(binding = 0, set = 0) uniform accelerationStructureEXT accEXT;
+layout(location = 0) rayPayloadEXT vec4 localPayload;
+layout(location = 1) rayPayloadInEXT vec4 incomingPayload;
+void main()
+{
+	uvec3 v0 = gl_LaunchIDEXT;
+	uvec3 v1 = gl_LaunchSizeEXT;
+	vec3 v2 = gl_WorldRayOriginEXT;
+	vec3 v3 = gl_WorldRayDirectionEXT;
+	float v4 = gl_RayTminEXT;
+	float v5 = gl_RayTmaxEXT;
+	traceRayEXT(accEXT, 0u, 1u, 2u, 3u, 0u, vec3(0.5f), 0.5f, vec3(1.0f), 0.75f, 1);
+}
diff --git a/third_party/glslang/src/Test/spv.ext.MissShader_Errors.rmiss b/third_party/glslang/src/Test/spv.ext.MissShader_Errors.rmiss
new file mode 100644
index 0000000..2391211
--- /dev/null
+++ b/third_party/glslang/src/Test/spv.ext.MissShader_Errors.rmiss
@@ -0,0 +1,16 @@
+#version 460
+#extension GL_EXT_ray_tracing : enable
+hitAttributeEXT vec4 payload;                               // ERROR, hitattributeEXT unsupported in this stage 
+void main()
+{
+    int e0 = gl_PrimitiveID;                               // ERROR, unsupported builtin in stage
+    int e1 = gl_InstanceID;                                // ERROR, unsupported builtin in stage
+    int e3 = gl_InstanceCustomIndexEXT;                     // ERROR, unsupported builtin in stage
+    mat4x3 e10 = gl_ObjectToWorldEXT;                       // ERROR, unsupported builtin in stage
+    mat4x3 e11 = gl_WorldToObjectEXT;                       // ERROR, unsupported builtin in stage
+    float e12 = gl_HitTEXT;                                 // ERROR, unsupported builtin in stage
+    float e13 = gl_HitKindEXT;                              // ERROR, unsupported builtin in stage
+    reportIntersectionEXT(1.0, 1U);                         // ERROR, unsupported builtin in stage
+    ignoreIntersectionEXT();                                // ERROR, unsupported builtin in stage
+    terminateRayEXT();                                      // ERROR, unsupported builtin in stage
+}
diff --git a/third_party/glslang/src/Test/spv.ext.RayCallable.rcall b/third_party/glslang/src/Test/spv.ext.RayCallable.rcall
new file mode 100644
index 0000000..9ec6820
--- /dev/null
+++ b/third_party/glslang/src/Test/spv.ext.RayCallable.rcall
@@ -0,0 +1,13 @@
+#version 460
+#extension GL_EXT_ray_tracing : enable
+layout(location = 0) callableDataEXT vec4 data0;
+layout(location = 1) callableDataInEXT dataBlock {
+	uint data1;
+};
+void main()
+{
+	uvec3 id = gl_LaunchIDEXT;
+	uvec3 size = gl_LaunchSizeEXT;
+	data1 = 256U;
+	executeCallableEXT(2,1);
+}
diff --git a/third_party/glslang/src/Test/spv.ext.RayCallable_Errors.rcall b/third_party/glslang/src/Test/spv.ext.RayCallable_Errors.rcall
new file mode 100644
index 0000000..d35672e
--- /dev/null
+++ b/third_party/glslang/src/Test/spv.ext.RayCallable_Errors.rcall
@@ -0,0 +1,26 @@
+#version 460
+#extension GL_EXT_ray_tracing : enable
+hitAttributeEXT vec4 hitattr;                                // ERROR, hitattributeEXT unsupported in this stage 
+rayPayloadEXT vec4 payload;                                  // ERROR, rayPayloadEXT unsupported in this stage
+rayPayloadInEXT vec4 payloadIn;                              // ERROR, rayPayloadInEXT unsupported in this stage
+
+void main()
+{
+    int e0 = gl_PrimitiveID;                                // ERROR, unsupported builtin in stage
+    int e1 = gl_InstanceID;                                 // ERROR, unsupported builtin in stage
+    int e3 = gl_InstanceCustomIndexEXT;                      // ERROR, unsupported builtin in stage
+    vec3 e4 = gl_WorldRayOriginEXT;                          // ERROR, unsupported builtin in stage
+    vec3 e5 = gl_WorldRayDirectionEXT;                       // ERROR, unsupported builtin in stage
+    vec3 e6 = gl_ObjectRayOriginEXT;                         // ERROR, unsupported builtin in stage
+    vec3 e7 = gl_ObjectRayDirectionEXT;                      // ERROR, unsupported builtin in stage
+    float e8 = gl_RayTminEXT;                                // ERROR, unsupported builtin in stage
+    float e9 = gl_RayTmaxEXT;                                // ERROR, unsupported builtin in stage
+    mat4x3 e10 = gl_ObjectToWorldEXT;                        // ERROR, unsupported builtin in stage
+    mat4x3 e11 = gl_WorldToObjectEXT;                        // ERROR, unsupported builtin in stage
+    float e12 = gl_HitTEXT;                                  // ERROR, unsupported builtin in stage
+    float e13 = gl_HitKindEXT;                               // ERROR, unsupported builtin in stage
+    uint curFlags = gl_IncomingRayFlagsEXT;                  // ERROR, unsupported builtin in stage
+    reportIntersectionEXT(1.0, 1U);                          // ERROR, unsupported builtin in stage
+    ignoreIntersectionEXT();                                 // ERROR, unsupported builtin in stage
+    terminateRayEXT();                                       // ERROR, unsupported builtin in stage
+}
diff --git a/third_party/glslang/src/Test/spv.ext.RayConstants.rgen b/third_party/glslang/src/Test/spv.ext.RayConstants.rgen
new file mode 100644
index 0000000..73cb0c1
--- /dev/null
+++ b/third_party/glslang/src/Test/spv.ext.RayConstants.rgen
@@ -0,0 +1,15 @@
+#version 460
+#extension GL_EXT_ray_tracing : enable
+layout(binding = 0, set = 0) uniform accelerationStructureEXT accEXT;
+layout(location = 0) rayPayloadEXT vec4 payload;
+void main()
+{
+    const uint rayFlags = gl_RayFlagsNoneEXT | gl_RayFlagsOpaqueEXT |
+                          gl_RayFlagsNoOpaqueEXT | gl_RayFlagsTerminateOnFirstHitEXT |
+                          gl_RayFlagsSkipClosestHitShaderEXT | gl_RayFlagsCullBackFacingTrianglesEXT |
+                          gl_RayFlagsCullFrontFacingTrianglesEXT | gl_RayFlagsCullOpaqueEXT | 
+                          gl_RayFlagsCullNoOpaqueEXT;
+
+    const int payloadId = 1;
+    traceRayEXT(accEXT, rayFlags, 0, 1, 1, 0, vec3(0.0f), 0.5f, vec3(1.0f), 0.75f, payloadId);
+}
diff --git a/third_party/glslang/src/Test/spv.ext.RayGenShader.rgen b/third_party/glslang/src/Test/spv.ext.RayGenShader.rgen
new file mode 100644
index 0000000..c92772e
--- /dev/null
+++ b/third_party/glslang/src/Test/spv.ext.RayGenShader.rgen
@@ -0,0 +1,21 @@
+#version 460
+#extension GL_EXT_ray_tracing : enable
+#extension GL_EXT_ray_flags_primitive_culling : enable
+layout(binding = 0, set = 0) uniform accelerationStructureEXT accEXT0;
+layout(binding = 1, set = 0) uniform accelerationStructureEXT accEXT1; // Unused
+layout(binding = 2, r32ui) shadercallcoherent uniform uimage2D imageu;
+layout(location = 0) rayPayloadEXT vec4 payload;
+layout(shaderRecordEXT) buffer block
+{
+	vec3 dir;
+	vec3 origin;
+
+};
+void main()
+{
+    uint lx = gl_LaunchIDEXT.x;
+    uint ly = gl_LaunchIDEXT.y;
+    uint sx = gl_LaunchSizeEXT.x;
+    uint sy = gl_LaunchSizeEXT.y;
+    traceRayEXT(accEXT0, lx, ly, sx, sy, gl_RayFlagsSkipTrianglesEXT | gl_RayFlagsSkipAABBEXT, origin, 0.5f, dir, 0.75f, 1);
+}
diff --git a/third_party/glslang/src/Test/spv.ext.RayGenShader11.rgen b/third_party/glslang/src/Test/spv.ext.RayGenShader11.rgen
new file mode 100644
index 0000000..4817026
--- /dev/null
+++ b/third_party/glslang/src/Test/spv.ext.RayGenShader11.rgen
@@ -0,0 +1,17 @@
+#version 460
+#extension GL_EXT_ray_tracing : enable
+layout(binding = 0, set = 0) uniform accelerationStructureEXT accEXT;
+layout(location = 0) rayPayloadEXT vec4 payload;
+layout(shaderRecordEXT) buffer block
+{
+	vec3 dir;
+	vec3 origin;
+};
+void main()
+{
+    uint lx = gl_LaunchIDEXT.x;
+    uint ly = gl_LaunchIDEXT.y;
+    uint sx = gl_LaunchSizeEXT.x;
+    uint sy = gl_LaunchSizeEXT.y;
+    traceRayEXT(accEXT, lx, ly, sx, sy, 0u, origin, 0.5f, dir, 0.75f, 1);
+}
diff --git a/third_party/glslang/src/Test/spv.ext.RayGenShaderArray.rgen b/third_party/glslang/src/Test/spv.ext.RayGenShaderArray.rgen
new file mode 100644
index 0000000..d3f99de
--- /dev/null
+++ b/third_party/glslang/src/Test/spv.ext.RayGenShaderArray.rgen
@@ -0,0 +1,22 @@
+#version 460
+#extension GL_EXT_ray_tracing : enable
+#extension GL_EXT_nonuniform_qualifier : enable
+layout(binding = 0, set = 0) uniform accelerationStructureEXT accEXT0[];
+layout(binding = 1, set = 0) uniform accelerationStructureEXT accEXT1[2];
+layout(location = 0) rayPayloadEXT vec4 payload;
+layout(shaderRecordEXT) buffer block
+{
+	vec3 dir;
+	vec3 origin;
+    int i;
+};
+void main()
+{
+    uint lx = gl_LaunchIDEXT.x;
+    uint ly = gl_LaunchIDEXT.y;
+    uint sx = gl_LaunchSizeEXT.x;
+    uint sy = gl_LaunchSizeEXT.y;
+    traceRayEXT(accEXT0[i], lx, ly, sx, sy, 0u, origin, 0.5f, dir, 0.75f, 1);
+    traceRayEXT(accEXT1[i], lx, ly, sx, sy, 0u, origin, 0.5f, dir, 0.75f, 1);
+    traceRayEXT(accEXT0[nonuniformEXT(i)], lx, ly, sx, sy, 0u, origin, 0.5f, dir, 0.75f, 1);
+}
diff --git a/third_party/glslang/src/Test/spv.ext.RayGenShader_Errors.rgen b/third_party/glslang/src/Test/spv.ext.RayGenShader_Errors.rgen
new file mode 100644
index 0000000..3498342
--- /dev/null
+++ b/third_party/glslang/src/Test/spv.ext.RayGenShader_Errors.rgen
@@ -0,0 +1,42 @@
+#version 460
+#extension GL_EXT_ray_tracing : enable
+hitAttributeEXT vec4 payload;                                // ERROR, hitattributeEXT unsupported in this stage 
+rayPayloadInEXT vec4 payloadIn;                              // ERROR, rayPayloadIn unsupported in this stage
+layout(shaderRecordEXT) uniform ublock                       // ERROR, shaderRecordEXT unsupported on uniform blocks
+{
+    float a;
+};
+layout(binding = 0, shaderRecordEXT) buffer bblock {         // ERROR, binding unsupported on shaderRecordEXT blocks
+    float b;
+};
+layout(set = 0, shaderRecordEXT) buffer bblock2 {            // ERROR, set unsupported on shaderRecordEXT blocks
+    float c;
+};
+layout(shaderRecordEXT) buffer bblock3 {
+    float d;
+};
+layout(shaderRecordEXT) buffer bblock4 {                     // ERROR, cannot have more than one shaderRecordEXTX block
+    float e;
+};
+void main()
+{
+    accelerationStructureEXT a = 0;
+    int e0 = gl_PrimitiveID;                                // ERROR, unsupported builtin in stage
+    int e1 = gl_InstanceID;                                 // ERROR, unsupported builtin in stage
+    int e3 = gl_InstanceCustomIndexEXT;                      // ERROR, unsupported builtin in stage
+    vec3 e4 = gl_WorldRayOriginEXT;                          // ERROR, unsupported builtin in stage
+    vec3 e5 = gl_WorldRayDirectionEXT;                       // ERROR, unsupported builtin in stage
+    vec3 e6 = gl_ObjectRayOriginEXT;                         // ERROR, unsupported builtin in stage
+    vec3 e7 = gl_ObjectRayDirectionEXT;                      // ERROR, unsupported builtin in stage
+    float e8 = gl_RayTminEXT;                                // ERROR, unsupported builtin in stage
+    float e9 = gl_RayTmaxEXT;                                // ERROR, unsupported builtin in stage
+    mat4x3 e10 = gl_ObjectToWorldEXT;                        // ERROR, unsupported builtin in stage
+    mat4x3 e11 = gl_WorldToObjectEXT;                        // ERROR, unsupported builtin in stage
+    float e12 = gl_HitTEXT;                                  // ERROR, unsupported builtin in stage
+    float e13 = gl_HitKindEXT;                               // ERROR, unsupported builtin in stage
+    int e14 = gl_RayFlagsSkipAABBEXT;                        // ERROR, unsupported builtin in stage
+    reportIntersectionEXT(1.0, 1U);                          // ERROR, unsupported builtin in stage
+    ignoreIntersectionEXT();                                 // ERROR, unsupported builtin in stage
+    terminateRayEXT();                                       // ERROR, unsupported builtin in stage
+    d = 1.0f;                                               // ERROR, can't modify shaderRecordEXT block
+}
diff --git a/third_party/glslang/src/Test/spv.specTexture.frag b/third_party/glslang/src/Test/spv.specTexture.frag
new file mode 100644
index 0000000..7fd89f5
--- /dev/null
+++ b/third_party/glslang/src/Test/spv.specTexture.frag
@@ -0,0 +1,10 @@
+#version 450
+
+layout(constant_id = 1) const int offs = 0;
+layout(binding = 0) uniform sampler2D tex;
+layout(location = 0) out vec4 color_out;
+
+void main(void)
+{
+  color_out = textureLodOffset(tex, vec2(0.0, 0.0), 0.0, ivec2(offs, offs));
+}
\ No newline at end of file
diff --git a/third_party/glslang/src/_config.yml b/third_party/glslang/src/_config.yml
index c50ff38..e8b995b 100644
--- a/third_party/glslang/src/_config.yml
+++ b/third_party/glslang/src/_config.yml
@@ -1 +1 @@
-theme: jekyll-theme-merlot
\ No newline at end of file
+theme: jekyll-theme-merlot
diff --git a/third_party/glslang/src/glslang/CInterface/glslang_c_interface.cpp b/third_party/glslang/src/glslang/CInterface/glslang_c_interface.cpp
index 68446c2..c4c24a9 100644
--- a/third_party/glslang/src/glslang/CInterface/glslang_c_interface.cpp
+++ b/third_party/glslang/src/glslang/CInterface/glslang_c_interface.cpp
@@ -183,17 +183,17 @@
     case GLSLANG_STAGE_COMPUTE:
         return EShLangCompute;
     case GLSLANG_STAGE_RAYGEN_NV:
-        return EShLangRayGenNV;
+        return EShLangRayGen;
     case GLSLANG_STAGE_INTERSECT_NV:
-        return EShLangIntersectNV;
+        return EShLangIntersect;
     case GLSLANG_STAGE_ANYHIT_NV:
-        return EShLangAnyHitNV;
+        return EShLangAnyHit;
     case GLSLANG_STAGE_CLOSESTHIT_NV:
-        return EShLangClosestHitNV;
+        return EShLangClosestHit;
     case GLSLANG_STAGE_MISS_NV:
-        return EShLangMissNV;
+        return EShLangMiss;
     case GLSLANG_STAGE_CALLABLE_NV:
-        return EShLangCallableNV;
+        return EShLangCallable;
     case GLSLANG_STAGE_TASK_NV:
         return EShLangTaskNV;
     case GLSLANG_STAGE_MESH_NV:
diff --git a/third_party/glslang/src/glslang/Include/BaseTypes.h b/third_party/glslang/src/glslang/Include/BaseTypes.h
index 6d4b4ff..816b179 100644
--- a/third_party/glslang/src/glslang/Include/BaseTypes.h
+++ b/third_party/glslang/src/glslang/Include/BaseTypes.h
@@ -2,6 +2,7 @@
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2012-2013 LunarG, Inc.
 // Copyright (C) 2017 ARM Limited.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 //
 // All rights reserved.
 //
@@ -61,8 +62,9 @@
     EbtSampler,
     EbtStruct,
     EbtBlock,
-    EbtAccStructNV,
+    EbtAccStruct,
     EbtReference,
+    EbtRayQuery,
 
     // HLSL types that live only temporarily.
     EbtString,
@@ -90,11 +92,11 @@
     EvqBuffer,        // read/write, shared with app
     EvqShared,        // compute shader's read/write 'shared' qualifier
 
-    EvqPayloadNV,
-    EvqPayloadInNV,
-    EvqHitAttrNV,
-    EvqCallableDataNV,
-    EvqCallableDataInNV,
+    EvqPayload,
+    EvqPayloadIn,
+    EvqHitAttr,
+    EvqCallableData,
+    EvqCallableDataIn,
 
     // parameters
     EvqIn,            // also, for 'in' in the grammar before we know if it's a pipeline input or an 'in' parameter
@@ -238,20 +240,23 @@
     EbvFragmentSizeNV,
     EbvInvocationsPerPixelNV,
     // ray tracing
-    EbvLaunchIdNV,
-    EbvLaunchSizeNV,
-    EbvInstanceCustomIndexNV,
-    EbvWorldRayOriginNV,
-    EbvWorldRayDirectionNV,
-    EbvObjectRayOriginNV,
-    EbvObjectRayDirectionNV,
-    EbvRayTminNV,
-    EbvRayTmaxNV,
-    EbvHitTNV,
-    EbvHitKindNV,
-    EbvObjectToWorldNV,
-    EbvWorldToObjectNV,
-    EbvIncomingRayFlagsNV,
+    EbvLaunchId,
+    EbvLaunchSize,
+    EbvInstanceCustomIndex,
+    EbvGeometryIndex,
+    EbvWorldRayOrigin,
+    EbvWorldRayDirection,
+    EbvObjectRayOrigin,
+    EbvObjectRayDirection,
+    EbvRayTmin,
+    EbvRayTmax,
+    EbvHitT,
+    EbvHitKind,
+    EbvObjectToWorld,
+    EbvObjectToWorld3x4,
+    EbvWorldToObject,
+    EbvWorldToObject3x4,
+    EbvIncomingRayFlags,
     // barycentrics
     EbvBaryCoordNV,
     EbvBaryCoordNoPerspNV,
@@ -328,11 +333,11 @@
     case EvqPointCoord:     return "gl_PointCoord";  break;
     case EvqFragColor:      return "fragColor";      break;
     case EvqFragDepth:      return "gl_FragDepth";   break;
-    case EvqPayloadNV:        return "rayPayloadNV";     break;
-    case EvqPayloadInNV:      return "rayPayloadInNV";   break;
-    case EvqHitAttrNV:        return "hitAttributeNV";   break;
-    case EvqCallableDataNV:   return "callableDataNV";   break;
-    case EvqCallableDataInNV: return "callableDataInNV"; break;
+    case EvqPayload:        return "rayPayloadNV";     break;
+    case EvqPayloadIn:      return "rayPayloadInNV";   break;
+    case EvqHitAttr:        return "hitAttributeNV";   break;
+    case EvqCallableData:   return "callableDataNV";   break;
+    case EvqCallableDataIn: return "callableDataInNV"; break;
     default:                return "unknown qualifier";
     }
 }
@@ -436,20 +441,21 @@
     case EbvFragFullyCoveredNV:         return "FragFullyCoveredNV";
     case EbvFragmentSizeNV:             return "FragmentSizeNV";
     case EbvInvocationsPerPixelNV:      return "InvocationsPerPixelNV";
-    case EbvLaunchIdNV:                 return "LaunchIdNV";
-    case EbvLaunchSizeNV:               return "LaunchSizeNV";
-    case EbvInstanceCustomIndexNV:      return "InstanceCustomIndexNV";
-    case EbvWorldRayOriginNV:           return "WorldRayOriginNV";
-    case EbvWorldRayDirectionNV:        return "WorldRayDirectionNV";
-    case EbvObjectRayOriginNV:          return "ObjectRayOriginNV";
-    case EbvObjectRayDirectionNV:       return "ObjectRayDirectionNV";
-    case EbvRayTminNV:                  return "ObjectRayTminNV";
-    case EbvRayTmaxNV:                  return "ObjectRayTmaxNV";
-    case EbvHitTNV:                     return "HitTNV";
-    case EbvHitKindNV:                  return "HitKindNV";
-    case EbvIncomingRayFlagsNV:         return "IncomingRayFlagsNV";
-    case EbvObjectToWorldNV:            return "ObjectToWorldNV";
-    case EbvWorldToObjectNV:            return "WorldToObjectNV";
+    case EbvLaunchId:                   return "LaunchIdNV";
+    case EbvLaunchSize:                 return "LaunchSizeNV";
+    case EbvInstanceCustomIndex:        return "InstanceCustomIndexNV";
+    case EbvGeometryIndex:              return "GeometryIndexEXT";
+    case EbvWorldRayOrigin:             return "WorldRayOriginNV";
+    case EbvWorldRayDirection:          return "WorldRayDirectionNV";
+    case EbvObjectRayOrigin:            return "ObjectRayOriginNV";
+    case EbvObjectRayDirection:         return "ObjectRayDirectionNV";
+    case EbvRayTmin:                    return "ObjectRayTminNV";
+    case EbvRayTmax:                    return "ObjectRayTmaxNV";
+    case EbvHitT:                       return "HitTNV";
+    case EbvHitKind:                    return "HitKindNV";
+    case EbvIncomingRayFlags:           return "IncomingRayFlagsNV";
+    case EbvObjectToWorld:              return "ObjectToWorldNV";
+    case EbvWorldToObject:              return "WorldToObjectNV";
 
     case EbvBaryCoordNV:                return "BaryCoordNV";
     case EbvBaryCoordNoPerspNV:         return "BaryCoordNoPerspNV";
diff --git a/third_party/glslang/src/glslang/Include/Types.h b/third_party/glslang/src/glslang/Include/Types.h
index db4f0b1..b2c416d 100644
--- a/third_party/glslang/src/glslang/Include/Types.h
+++ b/third_party/glslang/src/glslang/Include/Types.h
@@ -3,6 +3,7 @@
 // Copyright (C) 2012-2016 LunarG, Inc.
 // Copyright (C) 2015-2016 Google, Inc.
 // Copyright (C) 2017 ARM Limited.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 //
 // All rights reserved.
 //
@@ -472,6 +473,18 @@
     EioCount,
 };
 
+enum TShaderInterface
+{
+    // Includes both uniform blocks and buffer blocks
+    EsiUniform = 0,
+    EsiInput,
+    EsiOutput,
+    EsiNone,
+
+    EsiCount
+};
+
+
 class TQualifier {
 public:
     static const int layoutNotSet = -1;
@@ -532,6 +545,7 @@
         queuefamilycoherent = false;
         workgroupcoherent = false;
         subgroupcoherent  = false;
+        shadercallcoherent = false;
         nonprivate = false;
         volatil      = false;
         restrict     = false;
@@ -591,6 +605,7 @@
     bool queuefamilycoherent : 1;
     bool workgroupcoherent : 1;
     bool subgroupcoherent  : 1;
+    bool shadercallcoherent : 1;
     bool nonprivate   : 1;
     bool isWriteOnly() const { return writeonly; }
     bool isReadOnly() const { return readonly; }
@@ -600,11 +615,11 @@
     bool isSample() const { return sample; }
     bool isMemory() const
     {
-        return subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly || nonprivate;
+        return shadercallcoherent || subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly || nonprivate;
     }
     bool isMemoryQualifierImageAndSSBOOnly() const
     {
-        return subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly;
+        return shadercallcoherent || subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly;
     }
     bool bufferReferenceNeedsVulkanMemoryModel() const
     {
@@ -774,7 +789,7 @@
         layoutViewportRelative = false;
         // -2048 as the default value indicating layoutSecondaryViewportRelative is not set
         layoutSecondaryViewportRelativeOffset = -2048;
-        layoutShaderRecordNV = false;
+        layoutShaderRecord = false;
         layoutBufferReferenceAlign = layoutBufferReferenceAlignEnd;
         layoutFormat = ElfNone;
 #endif
@@ -813,7 +828,7 @@
                hasAnyLocation() ||
                hasStream() ||
                hasFormat() ||
-               isShaderRecordNV() ||
+               isShaderRecord() ||
                isPushConstant() ||
                hasBufferReference();
     }
@@ -872,7 +887,7 @@
     bool layoutPassthrough;
     bool layoutViewportRelative;
     int layoutSecondaryViewportRelativeOffset;
-    bool layoutShaderRecordNV;
+    bool layoutShaderRecord;
 #endif
 
     bool hasUniformLayout() const
@@ -943,7 +958,7 @@
     bool hasAttachment() const { return false; }
     TLayoutFormat getFormat() const { return ElfNone; }
     bool isPushConstant() const { return false; }
-    bool isShaderRecordNV() const { return false; }
+    bool isShaderRecord() const { return false; }
     bool hasBufferReference() const { return false; }
     bool hasBufferReferenceAlign() const { return false; }
     bool isNonUniform() const { return false; }
@@ -994,7 +1009,7 @@
     }
     TLayoutFormat getFormat() const { return layoutFormat; }
     bool isPushConstant() const { return layoutPushConstant; }
-    bool isShaderRecordNV() const { return layoutShaderRecordNV; }
+    bool isShaderRecord() const { return layoutShaderRecord; }
     bool hasBufferReference() const { return layoutBufferReference; }
     bool hasBufferReferenceAlign() const
     {
@@ -1613,6 +1628,23 @@
         assert(fieldName);
         return *fieldName;
     }
+    TShaderInterface getShaderInterface() const
+    {
+        if (basicType != EbtBlock)
+            return EsiNone;
+
+        switch (qualifier.storage) {
+        default:
+            return EsiNone;
+        case EvqVaryingIn:
+            return EsiInput;
+        case EvqVaryingOut:
+            return EsiOutput;
+        case EvqUniform:
+        case EvqBuffer:
+            return EsiUniform;
+        }
+    }
 
     virtual TBasicType getBasicType() const { return basicType; }
     virtual const TSampler& getSampler() const { return sampler; }
@@ -1671,7 +1703,7 @@
     }
     virtual bool isOpaque() const { return basicType == EbtSampler
 #ifndef GLSLANG_WEB
-         || basicType == EbtAtomicUint || basicType == EbtAccStructNV
+         || basicType == EbtAtomicUint || basicType == EbtAccStruct || basicType == EbtRayQuery
 #endif
         ; }
     virtual bool isBuiltIn() const { return getQualifier().builtIn != EbvNone; }
@@ -1947,7 +1979,8 @@
         case EbtAtomicUint:        return "atomic_uint";
         case EbtStruct:            return "structure";
         case EbtBlock:             return "block";
-        case EbtAccStructNV:       return "accelerationStructureNV";
+        case EbtAccStruct:         return "accelerationStructureNV";
+        case EbtRayQuery:          return "rayQueryEXT";
         case EbtReference:         return "reference";
 #endif
         default:                   return "unknown type";
@@ -2057,7 +2090,7 @@
                     appendStr(" layoutSecondaryViewportRelativeOffset=");
                     appendInt(qualifier.layoutSecondaryViewportRelativeOffset);
                 }
-                if (qualifier.layoutShaderRecordNV)
+                if (qualifier.layoutShaderRecord)
                     appendStr(" shaderRecordNV");
 
                 appendStr(")");
@@ -2100,6 +2133,8 @@
             appendStr(" workgroupcoherent");
         if (qualifier.subgroupcoherent)
             appendStr(" subgroupcoherent");
+        if (qualifier.shadercallcoherent)
+            appendStr(" shadercallcoherent");
         if (qualifier.nonprivate)
             appendStr(" nonprivate");
         if (qualifier.volatil)
diff --git a/third_party/glslang/src/glslang/Include/glslang_c_shader_types.h b/third_party/glslang/src/glslang/Include/glslang_c_shader_types.h
index 5755281..769f4c4 100644
--- a/third_party/glslang/src/glslang/Include/glslang_c_shader_types.h
+++ b/third_party/glslang/src/glslang/Include/glslang_c_shader_types.h
@@ -1,4 +1,4 @@
-/**
+/**
     This code is based on the glslang_c_interface implementation by Viktor Latypov
 **/
 
diff --git a/third_party/glslang/src/glslang/Include/intermediate.h b/third_party/glslang/src/glslang/Include/intermediate.h
index 5214e29..bf12fcf 100644
--- a/third_party/glslang/src/glslang/Include/intermediate.h
+++ b/third_party/glslang/src/glslang/Include/intermediate.h
@@ -2,6 +2,7 @@
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2012-2016 LunarG, Inc.
 // Copyright (C) 2017 ARM Limited.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 //
 // All rights reserved.
 //
@@ -910,12 +911,41 @@
     EOpAverageRounded,
     EOpMul32x16,
 
-    EOpTraceNV,
-    EOpReportIntersectionNV,
-    EOpIgnoreIntersectionNV,
-    EOpTerminateRayNV,
-    EOpExecuteCallableNV,
+    EOpTrace,
+    EOpReportIntersection,
+    EOpIgnoreIntersection,
+    EOpTerminateRay,
+    EOpExecuteCallable,
     EOpWritePackedPrimitiveIndices4x8NV,
+
+    //
+    // GL_EXT_ray_query operations
+    //
+
+    EOpRayQueryInitialize,
+    EOpRayQueryTerminate,
+    EOpRayQueryGenerateIntersection,
+    EOpRayQueryConfirmIntersection,
+    EOpRayQueryProceed,
+    EOpRayQueryGetIntersectionType,
+    EOpRayQueryGetRayTMin,
+    EOpRayQueryGetRayFlags,
+    EOpRayQueryGetIntersectionT,
+    EOpRayQueryGetIntersectionInstanceCustomIndex,
+    EOpRayQueryGetIntersectionInstanceId,
+    EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset,
+    EOpRayQueryGetIntersectionGeometryIndex,
+    EOpRayQueryGetIntersectionPrimitiveIndex,
+    EOpRayQueryGetIntersectionBarycentrics,
+    EOpRayQueryGetIntersectionFrontFace,
+    EOpRayQueryGetIntersectionCandidateAABBOpaque,
+    EOpRayQueryGetIntersectionObjectRayDirection,
+    EOpRayQueryGetIntersectionObjectRayOrigin,
+    EOpRayQueryGetWorldRayDirection,
+    EOpRayQueryGetWorldRayOrigin,
+    EOpRayQueryGetIntersectionObjectToWorld,
+    EOpRayQueryGetIntersectionWorldToObject,
+
     //
     // HLSL operations
     //
diff --git a/third_party/glslang/src/glslang/Include/revision.h b/third_party/glslang/src/glslang/Include/revision.h
index a0e4b20..d75bf32 100644
--- a/third_party/glslang/src/glslang/Include/revision.h
+++ b/third_party/glslang/src/glslang/Include/revision.h
@@ -1,3 +1,3 @@
 // This header is generated by the make-revision script.
 
-#define GLSLANG_PATCH_LEVEL 3559
+#define GLSLANG_PATCH_LEVEL 3727
diff --git a/third_party/glslang/src/glslang/Include/revision.template b/third_party/glslang/src/glslang/Include/revision.template
index 6c13630..4a16bee 100644
--- a/third_party/glslang/src/glslang/Include/revision.template
+++ b/third_party/glslang/src/glslang/Include/revision.template
@@ -1,13 +1,13 @@
-// The file revision.h should be updated to the latest version, somehow, on

-// check-in, if glslang has changed.

-//

-// revision.template is the source for revision.h when using SubWCRev as the

-// method of updating revision.h.  You don't have to do it this way, the

-// requirement is only that revision.h gets updated.

-//

-// revision.h is under source control so that not all consumers of glslang

-// source have to figure out how to create revision.h just to get a build

-// going.  However, if it is not updated, it can be a version behind.

-

-#define GLSLANG_REVISION "$WCREV$"

-#define GLSLANG_DATE     "$WCDATE$"

+// The file revision.h should be updated to the latest version, somehow, on
+// check-in, if glslang has changed.
+//
+// revision.template is the source for revision.h when using SubWCRev as the
+// method of updating revision.h.  You don't have to do it this way, the
+// requirement is only that revision.h gets updated.
+//
+// revision.h is under source control so that not all consumers of glslang
+// source have to figure out how to create revision.h just to get a build
+// going.  However, if it is not updated, it can be a version behind.
+
+#define GLSLANG_REVISION "$WCREV$"
+#define GLSLANG_DATE     "$WCDATE$"
diff --git a/third_party/glslang/src/glslang/MachineIndependent/Initialize.cpp b/third_party/glslang/src/glslang/MachineIndependent/Initialize.cpp
index 7076e62..eab2098 100644
--- a/third_party/glslang/src/glslang/MachineIndependent/Initialize.cpp
+++ b/third_party/glslang/src/glslang/MachineIndependent/Initialize.cpp
@@ -3,6 +3,7 @@
 // Copyright (C) 2012-2016 LunarG, Inc.
 // Copyright (C) 2015-2020 Google, Inc.
 // Copyright (C) 2017 ARM Limited.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 //
 // All rights reserved.
 //
@@ -125,8 +126,6 @@
 };
 // Mixtures of the above, to help the function tables
 const ArgClass ClassV1FIOCV = (ArgClass)(ClassV1 | ClassFIO | ClassCV);
-const ArgClass ClassV1FOCV  = (ArgClass)(ClassV1 | ClassFO  | ClassCV);
-const ArgClass ClassV1CV    = (ArgClass)(ClassV1 | ClassCV);
 const ArgClass ClassBNS     = (ArgClass)(ClassB  | ClassNS);
 const ArgClass ClassRSNS    = (ArgClass)(ClassRS | ClassNS);
 
@@ -1263,7 +1262,7 @@
 #endif
 
     if ((profile == EEsProfile && version >= 300) ||
-        (profile != EEsProfile && version >= 330)) {
+        (profile != EEsProfile && version >= 150)) { // GL_ARB_shader_bit_encoding
         commonBuiltins.append(
             "int   floatBitsToInt(highp float value);"
             "ivec2 floatBitsToInt(highp vec2  value);"
@@ -4067,10 +4066,10 @@
     }
 #ifndef GLSLANG_WEB
     if ((profile != EEsProfile && version >= 420) || esBarrier) {
-        commonBuiltins.append(
-            "void memoryBarrierAtomicCounter();"
-            "void memoryBarrierImage();"
-            );
+        if (spvVersion.vulkan == 0) {
+            commonBuiltins.append("void memoryBarrierAtomicCounter();");
+        }
+        commonBuiltins.append("void memoryBarrierImage();");
     }
     if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 320)) {
         stageBuiltins[EShLangMeshNV].append(
@@ -4322,29 +4321,64 @@
             "\n");
         }
 
-    // Builtins for GL_NV_ray_tracing
+    // Builtins for GL_NV_ray_tracing/GL_EXT_ray_tracing/GL_EXT_ray_query
     if (profile != EEsProfile && version >= 460) {
-        stageBuiltins[EShLangRayGenNV].append(
-            "void traceNV(accelerationStructureNV,uint,uint,uint,uint,uint,vec3,float,vec3,float,int);"
-            "void executeCallableNV(uint, int);"
+         commonBuiltins.append("void rayQueryInitializeEXT(rayQueryEXT, accelerationStructureEXT, uint, uint, vec3, float, vec3, float);"
+            "void rayQueryTerminateEXT(rayQueryEXT);"
+            "void rayQueryGenerateIntersectionEXT(rayQueryEXT, float);"
+            "void rayQueryConfirmIntersectionEXT(rayQueryEXT);"
+            "bool rayQueryProceedEXT(rayQueryEXT);"
+            "uint rayQueryGetIntersectionTypeEXT(rayQueryEXT, bool);"
+            "float rayQueryGetRayTMinEXT(rayQueryEXT);"
+            "uint rayQueryGetRayFlagsEXT(rayQueryEXT);"
+            "vec3 rayQueryGetWorldRayOriginEXT(rayQueryEXT);"
+            "vec3 rayQueryGetWorldRayDirectionEXT(rayQueryEXT);"
+            "float rayQueryGetIntersectionTEXT(rayQueryEXT, bool);"
+            "int rayQueryGetIntersectionInstanceCustomIndexEXT(rayQueryEXT, bool);"
+            "int rayQueryGetIntersectionInstanceIdEXT(rayQueryEXT, bool);"
+            "uint rayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetEXT(rayQueryEXT, bool);"
+            "int rayQueryGetIntersectionGeometryIndexEXT(rayQueryEXT, bool);"
+            "int rayQueryGetIntersectionPrimitiveIndexEXT(rayQueryEXT, bool);"
+            "vec2 rayQueryGetIntersectionBarycentricsEXT(rayQueryEXT, bool);"
+            "bool rayQueryGetIntersectionFrontFaceEXT(rayQueryEXT, bool);"
+            "bool rayQueryGetIntersectionCandidateAABBOpaqueEXT(rayQueryEXT);"
+            "vec3 rayQueryGetIntersectionObjectRayDirectionEXT(rayQueryEXT, bool);"
+            "vec3 rayQueryGetIntersectionObjectRayOriginEXT(rayQueryEXT, bool);"
+            "mat4x3 rayQueryGetIntersectionObjectToWorldEXT(rayQueryEXT, bool);"
+            "mat4x3 rayQueryGetIntersectionWorldToObjectEXT(rayQueryEXT, bool);"
             "\n");
-        stageBuiltins[EShLangIntersectNV].append(
+
+        stageBuiltins[EShLangRayGen].append(
+            "void traceNV(accelerationStructureNV,uint,uint,uint,uint,uint,vec3,float,vec3,float,int);"
+            "void traceRayEXT(accelerationStructureEXT,uint,uint,uint,uint,uint,vec3,float,vec3,float,int);"
+            "void executeCallableNV(uint, int);"
+            "void executeCallableEXT(uint, int);"
+            "\n");
+        stageBuiltins[EShLangIntersect].append(
             "bool reportIntersectionNV(float, uint);"
+            "bool reportIntersectionEXT(float, uint);"
             "\n");
-        stageBuiltins[EShLangAnyHitNV].append(
+        stageBuiltins[EShLangAnyHit].append(
             "void ignoreIntersectionNV();"
+            "void ignoreIntersectionEXT();"
             "void terminateRayNV();"
+            "void terminateRayEXT();"
             "\n");
-        stageBuiltins[EShLangClosestHitNV].append(
+        stageBuiltins[EShLangClosestHit].append(
             "void traceNV(accelerationStructureNV,uint,uint,uint,uint,uint,vec3,float,vec3,float,int);"
+            "void traceRayEXT(accelerationStructureEXT,uint,uint,uint,uint,uint,vec3,float,vec3,float,int);"
             "void executeCallableNV(uint, int);"
+            "void executeCallableEXT(uint, int);"
             "\n");
-        stageBuiltins[EShLangMissNV].append(
+        stageBuiltins[EShLangMiss].append(
             "void traceNV(accelerationStructureNV,uint,uint,uint,uint,uint,vec3,float,vec3,float,int);"
+            "void traceRayEXT(accelerationStructureEXT,uint,uint,uint,uint,uint,vec3,float,vec3,float,int);"
             "void executeCallableNV(uint, int);"
+            "void executeCallableEXT(uint, int);"
             "\n");
-        stageBuiltins[EShLangCallableNV].append(
+        stageBuiltins[EShLangCallable].append(
             "void executeCallableNV(uint, int);"
+            "void executeCallableEXT(uint, int);"
             "\n");
     }
 
@@ -5393,100 +5427,160 @@
         stageBuiltins[EShLangMeshNV]        .append(computeSubgroupDecls);
         stageBuiltins[EShLangTaskNV]        .append(subgroupDecls);
         stageBuiltins[EShLangTaskNV]        .append(computeSubgroupDecls);
-        stageBuiltins[EShLangRayGenNV]      .append(subgroupDecls);
-        stageBuiltins[EShLangIntersectNV]   .append(subgroupDecls);
-        stageBuiltins[EShLangAnyHitNV]      .append(subgroupDecls);
-        stageBuiltins[EShLangClosestHitNV]  .append(subgroupDecls);
-        stageBuiltins[EShLangMissNV]        .append(subgroupDecls);
-        stageBuiltins[EShLangCallableNV]    .append(subgroupDecls);
+        stageBuiltins[EShLangRayGen]        .append(subgroupDecls);
+        stageBuiltins[EShLangIntersect]     .append(subgroupDecls);
+        stageBuiltins[EShLangAnyHit]        .append(subgroupDecls);
+        stageBuiltins[EShLangClosestHit]    .append(subgroupDecls);
+        stageBuiltins[EShLangMiss]          .append(subgroupDecls);
+        stageBuiltins[EShLangCallable]      .append(subgroupDecls);
     }
 
-    // GL_NV_ray_tracing
+    // GL_NV_ray_tracing/GL_EXT_ray_tracing
     if (profile != EEsProfile && version >= 460) {
 
         const char *constRayFlags =
             "const uint gl_RayFlagsNoneNV = 0U;"
+            "const uint gl_RayFlagsNoneEXT = 0U;"
             "const uint gl_RayFlagsOpaqueNV = 1U;"
+            "const uint gl_RayFlagsOpaqueEXT = 1U;"
             "const uint gl_RayFlagsNoOpaqueNV = 2U;"
+            "const uint gl_RayFlagsNoOpaqueEXT = 2U;"
             "const uint gl_RayFlagsTerminateOnFirstHitNV = 4U;"
+            "const uint gl_RayFlagsTerminateOnFirstHitEXT = 4U;"
             "const uint gl_RayFlagsSkipClosestHitShaderNV = 8U;"
+            "const uint gl_RayFlagsSkipClosestHitShaderEXT = 8U;"
             "const uint gl_RayFlagsCullBackFacingTrianglesNV = 16U;"
+            "const uint gl_RayFlagsCullBackFacingTrianglesEXT = 16U;"
             "const uint gl_RayFlagsCullFrontFacingTrianglesNV = 32U;"
+            "const uint gl_RayFlagsCullFrontFacingTrianglesEXT = 32U;"
             "const uint gl_RayFlagsCullOpaqueNV = 64U;"
+            "const uint gl_RayFlagsCullOpaqueEXT = 64U;"
             "const uint gl_RayFlagsCullNoOpaqueNV = 128U;"
+            "const uint gl_RayFlagsCullNoOpaqueEXT = 128U;"
+            "const uint gl_RayFlagsSkipTrianglesEXT = 256U;"
+            "const uint gl_RayFlagsSkipAABBEXT = 512U;"
+            "const uint gl_HitKindFrontFacingTriangleEXT = 254U;"
+            "const uint gl_HitKindBackFacingTriangleEXT = 255U;"
             "\n";
+
+        const char *constRayQueryIntersection =
+            "const uint gl_RayQueryCandidateIntersectionEXT = 0U;"
+            "const uint gl_RayQueryCommittedIntersectionEXT = 1U;"
+            "const uint gl_RayQueryCommittedIntersectionNoneEXT = 0U;"
+            "const uint gl_RayQueryCommittedIntersectionTriangleEXT = 1U;"
+            "const uint gl_RayQueryCommittedIntersectionGeneratedEXT = 2U;"
+            "const uint gl_RayQueryCandidateIntersectionTriangleEXT = 0U;"
+            "const uint gl_RayQueryCandidateIntersectionAABBEXT = 1U;"
+            "\n";
+
         const char *rayGenDecls =
             "in    uvec3  gl_LaunchIDNV;"
+            "in    uvec3  gl_LaunchIDEXT;"
             "in    uvec3  gl_LaunchSizeNV;"
+            "in    uvec3  gl_LaunchSizeEXT;"
             "\n";
         const char *intersectDecls =
             "in    uvec3  gl_LaunchIDNV;"
+            "in    uvec3  gl_LaunchIDEXT;"
             "in    uvec3  gl_LaunchSizeNV;"
+            "in    uvec3  gl_LaunchSizeEXT;"
             "in     int   gl_PrimitiveID;"
             "in     int   gl_InstanceID;"
             "in     int   gl_InstanceCustomIndexNV;"
+            "in     int   gl_InstanceCustomIndexEXT;"
+            "in     int   gl_GeometryIndexEXT;"
             "in    vec3   gl_WorldRayOriginNV;"
+            "in    vec3   gl_WorldRayOriginEXT;"
             "in    vec3   gl_WorldRayDirectionNV;"
+            "in    vec3   gl_WorldRayDirectionEXT;"
             "in    vec3   gl_ObjectRayOriginNV;"
+            "in    vec3   gl_ObjectRayOriginEXT;"
             "in    vec3   gl_ObjectRayDirectionNV;"
+            "in    vec3   gl_ObjectRayDirectionEXT;"
             "in    float  gl_RayTminNV;"
+            "in    float  gl_RayTminEXT;"
             "in    float  gl_RayTmaxNV;"
+            "in    float  gl_RayTmaxEXT;"
             "in    mat4x3 gl_ObjectToWorldNV;"
+            "in    mat4x3 gl_ObjectToWorldEXT;"
+            "in    mat3x4 gl_ObjectToWorld3x4EXT;"
             "in    mat4x3 gl_WorldToObjectNV;"
+            "in    mat4x3 gl_WorldToObjectEXT;"
+            "in    mat3x4 gl_WorldToObject3x4EXT;"
             "in    uint   gl_IncomingRayFlagsNV;"
+            "in    uint   gl_IncomingRayFlagsEXT;"
             "\n";
         const char *hitDecls =
             "in    uvec3  gl_LaunchIDNV;"
+            "in    uvec3  gl_LaunchIDEXT;"
             "in    uvec3  gl_LaunchSizeNV;"
+            "in    uvec3  gl_LaunchSizeEXT;"
             "in     int   gl_PrimitiveID;"
             "in     int   gl_InstanceID;"
             "in     int   gl_InstanceCustomIndexNV;"
+            "in     int   gl_InstanceCustomIndexEXT;"
+            "in     int   gl_GeometryIndexEXT;"
             "in    vec3   gl_WorldRayOriginNV;"
+            "in    vec3   gl_WorldRayOriginEXT;"
             "in    vec3   gl_WorldRayDirectionNV;"
+            "in    vec3   gl_WorldRayDirectionEXT;"
             "in    vec3   gl_ObjectRayOriginNV;"
+            "in    vec3   gl_ObjectRayOriginEXT;"
             "in    vec3   gl_ObjectRayDirectionNV;"
+            "in    vec3   gl_ObjectRayDirectionEXT;"
             "in    float  gl_RayTminNV;"
+            "in    float  gl_RayTminEXT;"
             "in    float  gl_RayTmaxNV;"
+            "in    float  gl_RayTmaxEXT;"
             "in    float  gl_HitTNV;"
+            "in    float  gl_HitTEXT;"
             "in    uint   gl_HitKindNV;"
+            "in    uint   gl_HitKindEXT;"
             "in    mat4x3 gl_ObjectToWorldNV;"
+            "in    mat4x3 gl_ObjectToWorldEXT;"
+            "in    mat3x4 gl_ObjectToWorld3x4EXT;"
             "in    mat4x3 gl_WorldToObjectNV;"
+            "in    mat4x3 gl_WorldToObjectEXT;"
+            "in    mat3x4 gl_WorldToObject3x4EXT;"
             "in    uint   gl_IncomingRayFlagsNV;"
+            "in    uint   gl_IncomingRayFlagsEXT;"
             "\n";
         const char *missDecls =
             "in    uvec3  gl_LaunchIDNV;"
+            "in    uvec3  gl_LaunchIDEXT;"
             "in    uvec3  gl_LaunchSizeNV;"
+            "in    uvec3  gl_LaunchSizeEXT;"
             "in    vec3   gl_WorldRayOriginNV;"
+            "in    vec3   gl_WorldRayOriginEXT;"
             "in    vec3   gl_WorldRayDirectionNV;"
+            "in    vec3   gl_WorldRayDirectionEXT;"
             "in    vec3   gl_ObjectRayOriginNV;"
             "in    vec3   gl_ObjectRayDirectionNV;"
             "in    float  gl_RayTminNV;"
+            "in    float  gl_RayTminEXT;"
             "in    float  gl_RayTmaxNV;"
+            "in    float  gl_RayTmaxEXT;"
             "in    uint   gl_IncomingRayFlagsNV;"
+            "in    uint   gl_IncomingRayFlagsEXT;"
             "\n";
 
         const char *callableDecls =
             "in    uvec3  gl_LaunchIDNV;"
+            "in    uvec3  gl_LaunchIDEXT;"
             "in    uvec3  gl_LaunchSizeNV;"
+            "in    uvec3  gl_LaunchSizeEXT;"
             "\n";
 
-        stageBuiltins[EShLangRayGenNV].append(rayGenDecls);
-        stageBuiltins[EShLangRayGenNV].append(constRayFlags);
 
-        stageBuiltins[EShLangIntersectNV].append(intersectDecls);
-        stageBuiltins[EShLangIntersectNV].append(constRayFlags);
+        commonBuiltins.append(constRayQueryIntersection);
+        commonBuiltins.append(constRayFlags);
 
-        stageBuiltins[EShLangAnyHitNV].append(hitDecls);
-        stageBuiltins[EShLangAnyHitNV].append(constRayFlags);
-
-        stageBuiltins[EShLangClosestHitNV].append(hitDecls);
-        stageBuiltins[EShLangClosestHitNV].append(constRayFlags);
-
-        stageBuiltins[EShLangMissNV].append(missDecls);
-        stageBuiltins[EShLangMissNV].append(constRayFlags);
-
-        stageBuiltins[EShLangCallableNV].append(callableDecls);
-        stageBuiltins[EShLangCallableNV].append(constRayFlags);
+        stageBuiltins[EShLangRayGen].append(rayGenDecls);
+        stageBuiltins[EShLangIntersect].append(intersectDecls);
+        stageBuiltins[EShLangAnyHit].append(hitDecls);
+        stageBuiltins[EShLangClosestHit].append(hitDecls);
+        stageBuiltins[EShLangMiss].append(missDecls);
+        stageBuiltins[EShLangCallable].append(callableDecls);
 
     }
     if ((profile != EEsProfile && version >= 140)) {
@@ -5494,11 +5588,11 @@
             "in highp int gl_DeviceIndex;"     // GL_EXT_device_group
             "\n";
 
-        stageBuiltins[EShLangRayGenNV].append(deviceIndex);
-        stageBuiltins[EShLangIntersectNV].append(deviceIndex);
-        stageBuiltins[EShLangAnyHitNV].append(deviceIndex);
-        stageBuiltins[EShLangClosestHitNV].append(deviceIndex);
-        stageBuiltins[EShLangMissNV].append(deviceIndex);
+        stageBuiltins[EShLangRayGen].append(deviceIndex);
+        stageBuiltins[EShLangIntersect].append(deviceIndex);
+        stageBuiltins[EShLangAnyHit].append(deviceIndex);
+        stageBuiltins[EShLangClosestHit].append(deviceIndex);
+        stageBuiltins[EShLangMiss].append(deviceIndex);
     }
 
     if (version >= 300 /* both ES and non-ES */) {
@@ -5514,6 +5608,7 @@
         commonBuiltins.append("const int gl_ScopeSubgroup    = 3;\n");
         commonBuiltins.append("const int gl_ScopeInvocation  = 4;\n");
         commonBuiltins.append("const int gl_ScopeQueueFamily = 5;\n");
+        commonBuiltins.append("const int gl_ScopeShaderCallEXT = 6;\n");
 
         commonBuiltins.append("const int gl_SemanticsRelaxed         = 0x0;\n");
         commonBuiltins.append("const int gl_SemanticsAcquire         = 0x2;\n");
@@ -5710,7 +5805,7 @@
     return;
 #endif
 
-    if (sampler.isImage() && ((profile == EEsProfile && version < 310) || (profile != EEsProfile && version < 430)))
+    if (sampler.isImage() && ((profile == EEsProfile && version < 310) || (profile != EEsProfile && version < 420)))
         return;
 
     if (profile == EEsProfile)
@@ -7455,6 +7550,34 @@
             BuiltInVariable("gl_FragStencilRefARB", EbvFragStencilRef, symbolTable);
         }
 
+        if (profile != EEsProfile && version >= 460) {
+            symbolTable.setFunctionExtensions("rayQueryInitializeEXT",                                            1, &E_GL_EXT_ray_query);
+            symbolTable.setFunctionExtensions("rayQueryTerminateEXT",                                             1, &E_GL_EXT_ray_query);
+            symbolTable.setFunctionExtensions("rayQueryGenerateIntersectionEXT",                                  1, &E_GL_EXT_ray_query);
+            symbolTable.setFunctionExtensions("rayQueryConfirmIntersectionEXT",                                   1, &E_GL_EXT_ray_query);
+            symbolTable.setFunctionExtensions("rayQueryProceedEXT",                                               1, &E_GL_EXT_ray_query);
+            symbolTable.setFunctionExtensions("rayQueryGetIntersectionTypeEXT",                                   1, &E_GL_EXT_ray_query);
+            symbolTable.setFunctionExtensions("rayQueryGetIntersectionTEXT",                                      1, &E_GL_EXT_ray_query);
+            symbolTable.setFunctionExtensions("rayQueryGetRayFlagsEXT",                                           1, &E_GL_EXT_ray_query);
+            symbolTable.setFunctionExtensions("rayQueryGetRayTMinEXT",                                            1, &E_GL_EXT_ray_query);
+            symbolTable.setFunctionExtensions("rayQueryGetIntersectionInstanceCustomIndexEXT",                    1, &E_GL_EXT_ray_query);
+            symbolTable.setFunctionExtensions("rayQueryGetIntersectionInstanceIdEXT",                             1, &E_GL_EXT_ray_query);
+            symbolTable.setFunctionExtensions("rayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetEXT", 1, &E_GL_EXT_ray_query);
+            symbolTable.setFunctionExtensions("rayQueryGetIntersectionGeometryIndexEXT",                          1, &E_GL_EXT_ray_query);
+            symbolTable.setFunctionExtensions("rayQueryGetIntersectionPrimitiveIndexEXT",                         1, &E_GL_EXT_ray_query);
+            symbolTable.setFunctionExtensions("rayQueryGetIntersectionBarycentricsEXT",                           1, &E_GL_EXT_ray_query);
+            symbolTable.setFunctionExtensions("rayQueryGetIntersectionFrontFaceEXT",                              1, &E_GL_EXT_ray_query);
+            symbolTable.setFunctionExtensions("rayQueryGetIntersectionCandidateAABBOpaqueEXT",                    1, &E_GL_EXT_ray_query);
+            symbolTable.setFunctionExtensions("rayQueryGetIntersectionObjectRayDirectionEXT",                     1, &E_GL_EXT_ray_query);
+            symbolTable.setFunctionExtensions("rayQueryGetIntersectionObjectRayOriginEXT",                        1, &E_GL_EXT_ray_query);
+            symbolTable.setFunctionExtensions("rayQueryGetIntersectionObjectToWorldEXT",                          1, &E_GL_EXT_ray_query);
+            symbolTable.setFunctionExtensions("rayQueryGetIntersectionWorldToObjectEXT",                          1, &E_GL_EXT_ray_query);
+            symbolTable.setFunctionExtensions("rayQueryGetWorldRayOriginEXT",                                     1, &E_GL_EXT_ray_query);
+            symbolTable.setFunctionExtensions("rayQueryGetWorldRayDirectionEXT",                                  1, &E_GL_EXT_ray_query);
+            symbolTable.setVariableExtensions("gl_RayFlagsSkipAABBEXT",                         1, &E_GL_EXT_ray_flags_primitive_culling);
+            symbolTable.setVariableExtensions("gl_RayFlagsSkipTrianglesEXT",                    1, &E_GL_EXT_ray_flags_primitive_culling);
+        }
+
         if ((profile != EEsProfile && version >= 130) ||
             (profile == EEsProfile && version >= 310)) {
             BuiltInVariable("gl_SampleID",           EbvSampleId,       symbolTable);
@@ -7693,6 +7816,17 @@
             symbolTable.setFunctionExtensions("imageAtomicCompSwap", 1, &E_GL_OES_shader_image_atomic);
         }
 
+        if (profile != EEsProfile && version < 330 ) {
+            symbolTable.setFunctionExtensions("floatBitsToInt", 1, &E_GL_ARB_shader_bit_encoding);
+            symbolTable.setFunctionExtensions("floatBitsToUint", 1, &E_GL_ARB_shader_bit_encoding);
+            symbolTable.setFunctionExtensions("intBitsToFloat", 1, &E_GL_ARB_shader_bit_encoding);
+            symbolTable.setFunctionExtensions("uintBitsToFloat", 1, &E_GL_ARB_shader_bit_encoding);
+        }
+
+        if (profile != EEsProfile && version < 430 ) {
+            symbolTable.setFunctionExtensions("imageSize", 1, &E_GL_ARB_shader_image_size);
+        }
+
         symbolTable.setVariableExtensions("gl_DeviceIndex",  1, &E_GL_EXT_device_group);
         BuiltInVariable("gl_DeviceIndex", EbvDeviceIndex, symbolTable);
         symbolTable.setVariableExtensions("gl_ViewIndex", 1, &E_GL_EXT_multiview);
@@ -7995,49 +8129,97 @@
         break;
 
 #ifndef GLSLANG_WEB
-    case EShLangRayGenNV:
-    case EShLangIntersectNV:
-    case EShLangAnyHitNV:
-    case EShLangClosestHitNV:
-    case EShLangMissNV:
-    case EShLangCallableNV:
+    case EShLangRayGen:
+    case EShLangIntersect:
+    case EShLangAnyHit:
+    case EShLangClosestHit:
+    case EShLangMiss:
+    case EShLangCallable:
         if (profile != EEsProfile && version >= 460) {
+            const char *rtexts[] = { E_GL_NV_ray_tracing, E_GL_EXT_ray_tracing };
             symbolTable.setVariableExtensions("gl_LaunchIDNV", 1, &E_GL_NV_ray_tracing);
+            symbolTable.setVariableExtensions("gl_LaunchIDEXT", 1, &E_GL_EXT_ray_tracing);
             symbolTable.setVariableExtensions("gl_LaunchSizeNV", 1, &E_GL_NV_ray_tracing);
-            symbolTable.setVariableExtensions("gl_PrimitiveID", 1, &E_GL_NV_ray_tracing);
-            symbolTable.setVariableExtensions("gl_InstanceID", 1, &E_GL_NV_ray_tracing);
+            symbolTable.setVariableExtensions("gl_LaunchSizeEXT", 1, &E_GL_EXT_ray_tracing);
+            symbolTable.setVariableExtensions("gl_PrimitiveID", 2, rtexts);
+            symbolTable.setVariableExtensions("gl_InstanceID", 2, rtexts);
             symbolTable.setVariableExtensions("gl_InstanceCustomIndexNV", 1, &E_GL_NV_ray_tracing);
+            symbolTable.setVariableExtensions("gl_InstanceCustomIndexEXT", 1, &E_GL_EXT_ray_tracing);
+            symbolTable.setVariableExtensions("gl_GeometryIndexEXT", 1, &E_GL_EXT_ray_tracing);
             symbolTable.setVariableExtensions("gl_WorldRayOriginNV", 1, &E_GL_NV_ray_tracing);
+            symbolTable.setVariableExtensions("gl_WorldRayOriginEXT", 1, &E_GL_EXT_ray_tracing);
             symbolTable.setVariableExtensions("gl_WorldRayDirectionNV", 1, &E_GL_NV_ray_tracing);
+            symbolTable.setVariableExtensions("gl_WorldRayDirectionEXT", 1, &E_GL_EXT_ray_tracing);
             symbolTable.setVariableExtensions("gl_ObjectRayOriginNV", 1, &E_GL_NV_ray_tracing);
+            symbolTable.setVariableExtensions("gl_ObjectRayOriginEXT", 1, &E_GL_EXT_ray_tracing);
             symbolTable.setVariableExtensions("gl_ObjectRayDirectionNV", 1, &E_GL_NV_ray_tracing);
+            symbolTable.setVariableExtensions("gl_ObjectRayDirectionEXT", 1, &E_GL_EXT_ray_tracing);
             symbolTable.setVariableExtensions("gl_RayTminNV", 1, &E_GL_NV_ray_tracing);
+            symbolTable.setVariableExtensions("gl_RayTminEXT", 1, &E_GL_EXT_ray_tracing);
             symbolTable.setVariableExtensions("gl_RayTmaxNV", 1, &E_GL_NV_ray_tracing);
+            symbolTable.setVariableExtensions("gl_RayTmaxEXT", 1, &E_GL_EXT_ray_tracing);
             symbolTable.setVariableExtensions("gl_HitTNV", 1, &E_GL_NV_ray_tracing);
+            symbolTable.setVariableExtensions("gl_HitTEXT", 1, &E_GL_EXT_ray_tracing);
             symbolTable.setVariableExtensions("gl_HitKindNV", 1, &E_GL_NV_ray_tracing);
+            symbolTable.setVariableExtensions("gl_HitKindEXT", 1, &E_GL_EXT_ray_tracing);
             symbolTable.setVariableExtensions("gl_ObjectToWorldNV", 1, &E_GL_NV_ray_tracing);
+            symbolTable.setVariableExtensions("gl_ObjectToWorldEXT", 1, &E_GL_EXT_ray_tracing);
+            symbolTable.setVariableExtensions("gl_ObjectToWorld3x4EXT", 1, &E_GL_EXT_ray_tracing);
             symbolTable.setVariableExtensions("gl_WorldToObjectNV", 1, &E_GL_NV_ray_tracing);
+            symbolTable.setVariableExtensions("gl_WorldToObjectEXT", 1, &E_GL_EXT_ray_tracing);
+            symbolTable.setVariableExtensions("gl_WorldToObject3x4EXT", 1, &E_GL_EXT_ray_tracing);
             symbolTable.setVariableExtensions("gl_IncomingRayFlagsNV", 1, &E_GL_NV_ray_tracing);
+            symbolTable.setVariableExtensions("gl_IncomingRayFlagsEXT", 1, &E_GL_EXT_ray_tracing);
 
             symbolTable.setVariableExtensions("gl_DeviceIndex", 1, &E_GL_EXT_device_group);
 
-            BuiltInVariable("gl_LaunchIDNV",            EbvLaunchIdNV,           symbolTable);
-            BuiltInVariable("gl_LaunchSizeNV",          EbvLaunchSizeNV,         symbolTable);
-            BuiltInVariable("gl_PrimitiveID",           EbvPrimitiveId,          symbolTable);
-            BuiltInVariable("gl_InstanceID",            EbvInstanceId,           symbolTable);
-            BuiltInVariable("gl_InstanceCustomIndexNV", EbvInstanceCustomIndexNV,symbolTable);
-            BuiltInVariable("gl_WorldRayOriginNV",      EbvWorldRayOriginNV,     symbolTable);
-            BuiltInVariable("gl_WorldRayDirectionNV",   EbvWorldRayDirectionNV,  symbolTable);
-            BuiltInVariable("gl_ObjectRayOriginNV",     EbvObjectRayOriginNV,    symbolTable);
-            BuiltInVariable("gl_ObjectRayDirectionNV",  EbvObjectRayDirectionNV, symbolTable);
-            BuiltInVariable("gl_RayTminNV",             EbvRayTminNV,            symbolTable);
-            BuiltInVariable("gl_RayTmaxNV",             EbvRayTmaxNV,            symbolTable);
-            BuiltInVariable("gl_HitTNV",                EbvHitTNV,               symbolTable);
-            BuiltInVariable("gl_HitKindNV",             EbvHitKindNV,            symbolTable);
-            BuiltInVariable("gl_ObjectToWorldNV",       EbvObjectToWorldNV,      symbolTable);
-            BuiltInVariable("gl_WorldToObjectNV",       EbvWorldToObjectNV,      symbolTable);
-            BuiltInVariable("gl_IncomingRayFlagsNV",    EbvIncomingRayFlagsNV,   symbolTable);
-            BuiltInVariable("gl_DeviceIndex",           EbvDeviceIndex,          symbolTable);
+
+            symbolTable.setFunctionExtensions("traceNV", 1, &E_GL_NV_ray_tracing);
+            symbolTable.setFunctionExtensions("traceRayEXT", 1, &E_GL_EXT_ray_tracing);
+            symbolTable.setFunctionExtensions("reportIntersectionNV", 1, &E_GL_NV_ray_tracing);
+            symbolTable.setFunctionExtensions("reportIntersectionEXT", 1, &E_GL_EXT_ray_tracing);
+            symbolTable.setFunctionExtensions("ignoreIntersectionNV", 1, &E_GL_NV_ray_tracing);
+            symbolTable.setFunctionExtensions("ignoreIntersectionEXT", 1, &E_GL_EXT_ray_tracing);
+            symbolTable.setFunctionExtensions("terminateRayNV", 1, &E_GL_NV_ray_tracing);
+            symbolTable.setFunctionExtensions("terminateRayEXT", 1, &E_GL_EXT_ray_tracing);
+            symbolTable.setFunctionExtensions("executeCallableNV", 1, &E_GL_NV_ray_tracing);
+            symbolTable.setFunctionExtensions("executeCallableEXT", 1, &E_GL_EXT_ray_tracing);
+
+
+            BuiltInVariable("gl_LaunchIDNV",             EbvLaunchId,           symbolTable);
+            BuiltInVariable("gl_LaunchIDEXT",            EbvLaunchId,           symbolTable);
+            BuiltInVariable("gl_LaunchSizeNV",           EbvLaunchSize,         symbolTable);
+            BuiltInVariable("gl_LaunchSizeEXT",          EbvLaunchSize,         symbolTable);
+            BuiltInVariable("gl_PrimitiveID",            EbvPrimitiveId,        symbolTable);
+            BuiltInVariable("gl_InstanceID",             EbvInstanceId,         symbolTable);
+            BuiltInVariable("gl_InstanceCustomIndexNV",  EbvInstanceCustomIndex,symbolTable);
+            BuiltInVariable("gl_InstanceCustomIndexEXT", EbvInstanceCustomIndex,symbolTable);
+            BuiltInVariable("gl_GeometryIndexEXT",       EbvGeometryIndex,      symbolTable);
+            BuiltInVariable("gl_WorldRayOriginNV",       EbvWorldRayOrigin,     symbolTable);
+            BuiltInVariable("gl_WorldRayOriginEXT",      EbvWorldRayOrigin,     symbolTable);
+            BuiltInVariable("gl_WorldRayDirectionNV",    EbvWorldRayDirection,  symbolTable);
+            BuiltInVariable("gl_WorldRayDirectionEXT",   EbvWorldRayDirection,  symbolTable);
+            BuiltInVariable("gl_ObjectRayOriginNV",      EbvObjectRayOrigin,    symbolTable);
+            BuiltInVariable("gl_ObjectRayOriginEXT",     EbvObjectRayOrigin,    symbolTable);
+            BuiltInVariable("gl_ObjectRayDirectionNV",   EbvObjectRayDirection, symbolTable);
+            BuiltInVariable("gl_ObjectRayDirectionEXT",  EbvObjectRayDirection, symbolTable);
+            BuiltInVariable("gl_RayTminNV",              EbvRayTmin,            symbolTable);
+            BuiltInVariable("gl_RayTminEXT",             EbvRayTmin,            symbolTable);
+            BuiltInVariable("gl_RayTmaxNV",              EbvRayTmax,            symbolTable);
+            BuiltInVariable("gl_RayTmaxEXT",             EbvRayTmax,            symbolTable);
+            BuiltInVariable("gl_HitTNV",                 EbvHitT,               symbolTable);
+            BuiltInVariable("gl_HitTEXT",                EbvHitT,               symbolTable);
+            BuiltInVariable("gl_HitKindNV",              EbvHitKind,            symbolTable);
+            BuiltInVariable("gl_HitKindEXT",             EbvHitKind,            symbolTable);
+            BuiltInVariable("gl_ObjectToWorldNV",        EbvObjectToWorld,      symbolTable);
+            BuiltInVariable("gl_ObjectToWorldEXT",       EbvObjectToWorld,      symbolTable);
+            BuiltInVariable("gl_ObjectToWorld3x4EXT",    EbvObjectToWorld3x4,   symbolTable);
+            BuiltInVariable("gl_WorldToObjectNV",        EbvWorldToObject,      symbolTable);
+            BuiltInVariable("gl_WorldToObjectEXT",       EbvWorldToObject,      symbolTable);
+            BuiltInVariable("gl_WorldToObject3x4EXT",    EbvWorldToObject3x4,   symbolTable);
+            BuiltInVariable("gl_IncomingRayFlagsNV",     EbvIncomingRayFlags,   symbolTable);
+            BuiltInVariable("gl_IncomingRayFlagsEXT",    EbvIncomingRayFlags,   symbolTable);
+            BuiltInVariable("gl_DeviceIndex",            EbvDeviceIndex,        symbolTable);
 
             // GL_ARB_shader_ballot
             symbolTable.setVariableExtensions("gl_SubGroupSizeARB",       1, &E_GL_ARB_shader_ballot);
@@ -8745,6 +8927,33 @@
             symbolTable.relateToOperator("dFdyCoarse",   EOpDPdyCoarse);
             symbolTable.relateToOperator("fwidthCoarse", EOpFwidthCoarse);
         }
+
+        if (profile != EEsProfile && version >= 460) {
+            symbolTable.relateToOperator("rayQueryInitializeEXT",                                             EOpRayQueryInitialize);
+            symbolTable.relateToOperator("rayQueryTerminateEXT",                                              EOpRayQueryTerminate);
+            symbolTable.relateToOperator("rayQueryGenerateIntersectionEXT",                                   EOpRayQueryGenerateIntersection);
+            symbolTable.relateToOperator("rayQueryConfirmIntersectionEXT",                                    EOpRayQueryConfirmIntersection);
+            symbolTable.relateToOperator("rayQueryProceedEXT",                                                EOpRayQueryProceed);
+            symbolTable.relateToOperator("rayQueryGetIntersectionTypeEXT",                                    EOpRayQueryGetIntersectionType);
+            symbolTable.relateToOperator("rayQueryGetRayTMinEXT",                                             EOpRayQueryGetRayTMin);
+            symbolTable.relateToOperator("rayQueryGetRayFlagsEXT",                                            EOpRayQueryGetRayFlags);
+            symbolTable.relateToOperator("rayQueryGetIntersectionTEXT",                                       EOpRayQueryGetIntersectionT);
+            symbolTable.relateToOperator("rayQueryGetIntersectionInstanceCustomIndexEXT",                     EOpRayQueryGetIntersectionInstanceCustomIndex);
+            symbolTable.relateToOperator("rayQueryGetIntersectionInstanceIdEXT",                              EOpRayQueryGetIntersectionInstanceId);
+            symbolTable.relateToOperator("rayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetEXT",  EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset);
+            symbolTable.relateToOperator("rayQueryGetIntersectionGeometryIndexEXT",                           EOpRayQueryGetIntersectionGeometryIndex);
+            symbolTable.relateToOperator("rayQueryGetIntersectionPrimitiveIndexEXT",                          EOpRayQueryGetIntersectionPrimitiveIndex);
+            symbolTable.relateToOperator("rayQueryGetIntersectionBarycentricsEXT",                            EOpRayQueryGetIntersectionBarycentrics);
+            symbolTable.relateToOperator("rayQueryGetIntersectionFrontFaceEXT",                               EOpRayQueryGetIntersectionFrontFace);
+            symbolTable.relateToOperator("rayQueryGetIntersectionCandidateAABBOpaqueEXT",                     EOpRayQueryGetIntersectionCandidateAABBOpaque);
+            symbolTable.relateToOperator("rayQueryGetIntersectionObjectRayDirectionEXT",                      EOpRayQueryGetIntersectionObjectRayDirection);
+            symbolTable.relateToOperator("rayQueryGetIntersectionObjectRayOriginEXT",                         EOpRayQueryGetIntersectionObjectRayOrigin);
+            symbolTable.relateToOperator("rayQueryGetWorldRayDirectionEXT",                                   EOpRayQueryGetWorldRayDirection);
+            symbolTable.relateToOperator("rayQueryGetWorldRayOriginEXT",                                      EOpRayQueryGetWorldRayOrigin);
+            symbolTable.relateToOperator("rayQueryGetIntersectionObjectToWorldEXT",                           EOpRayQueryGetIntersectionObjectToWorld);
+            symbolTable.relateToOperator("rayQueryGetIntersectionWorldToObjectEXT",                           EOpRayQueryGetIntersectionWorldToObject);
+        }
+
         symbolTable.relateToOperator("interpolateAtCentroid", EOpInterpolateAtCentroid);
         symbolTable.relateToOperator("interpolateAtSample",   EOpInterpolateAtSample);
         symbolTable.relateToOperator("interpolateAtOffset",   EOpInterpolateAtOffset);
@@ -8776,27 +8985,34 @@
         symbolTable.relateToOperator("coopMatMulAddNV",            EOpCooperativeMatrixMulAdd);
         break;
 
-    case EShLangRayGenNV:
-    case EShLangClosestHitNV:
-    case EShLangMissNV:
+    case EShLangRayGen:
+    case EShLangClosestHit:
+    case EShLangMiss:
         if (profile != EEsProfile && version >= 460) {
-            symbolTable.relateToOperator("traceNV", EOpTraceNV);
-            symbolTable.relateToOperator("executeCallableNV", EOpExecuteCallableNV);
+            symbolTable.relateToOperator("traceNV", EOpTrace);
+            symbolTable.relateToOperator("traceRayEXT", EOpTrace);
+            symbolTable.relateToOperator("executeCallableNV", EOpExecuteCallable);
+            symbolTable.relateToOperator("executeCallableEXT", EOpExecuteCallable);
         }
         break;
-    case EShLangIntersectNV:
-        if (profile != EEsProfile && version >= 460)
-            symbolTable.relateToOperator("reportIntersectionNV", EOpReportIntersectionNV);
-        break;
-    case EShLangAnyHitNV:
+    case EShLangIntersect:
         if (profile != EEsProfile && version >= 460) {
-            symbolTable.relateToOperator("ignoreIntersectionNV", EOpIgnoreIntersectionNV);
-            symbolTable.relateToOperator("terminateRayNV", EOpTerminateRayNV);
+            symbolTable.relateToOperator("reportIntersectionNV", EOpReportIntersection);
+            symbolTable.relateToOperator("reportIntersectionEXT", EOpReportIntersection);
+	}
+        break;
+    case EShLangAnyHit:
+        if (profile != EEsProfile && version >= 460) {
+            symbolTable.relateToOperator("ignoreIntersectionNV", EOpIgnoreIntersection);
+            symbolTable.relateToOperator("ignoreIntersectionEXT", EOpIgnoreIntersection);
+            symbolTable.relateToOperator("terminateRayNV", EOpTerminateRay);
+            symbolTable.relateToOperator("terminateRayEXT", EOpTerminateRay);
         }
         break;
-    case EShLangCallableNV:
+    case EShLangCallable:
         if (profile != EEsProfile && version >= 460) {
-            symbolTable.relateToOperator("executeCallableNV", EOpExecuteCallableNV);
+            symbolTable.relateToOperator("executeCallableNV", EOpExecuteCallable);
+            symbolTable.relateToOperator("executeCallableEXT", EOpExecuteCallable);
         }
         break;
     case EShLangMeshNV:
diff --git a/third_party/glslang/src/glslang/MachineIndependent/Intermediate.cpp b/third_party/glslang/src/glslang/MachineIndependent/Intermediate.cpp
index 1ce20d9..f6a5e7f 100755
--- a/third_party/glslang/src/glslang/MachineIndependent/Intermediate.cpp
+++ b/third_party/glslang/src/glslang/MachineIndependent/Intermediate.cpp
@@ -538,7 +538,7 @@
         return false;
     case EbtAtomicUint:
     case EbtSampler:
-    case EbtAccStructNV:
+    case EbtAccStruct:
         // opaque types can be passed to functions
         if (op == EOpFunction)
             break;
diff --git a/third_party/glslang/src/glslang/MachineIndependent/ParseContextBase.cpp b/third_party/glslang/src/glslang/MachineIndependent/ParseContextBase.cpp
index 282ecca..b464009 100644
--- a/third_party/glslang/src/glslang/MachineIndependent/ParseContextBase.cpp
+++ b/third_party/glslang/src/glslang/MachineIndependent/ParseContextBase.cpp
@@ -157,11 +157,11 @@
     case EvqBuffer:
         if (node->getQualifier().isReadOnly())
             message = "can't modify a readonly buffer";
-        if (node->getQualifier().isShaderRecordNV())
+        if (node->getQualifier().isShaderRecord())
             message = "can't modify a shaderrecordnv qualified buffer";
         break;
-    case EvqHitAttrNV:
-        if (language != EShLangIntersectNV)
+    case EvqHitAttr:
+        if (language != EShLangIntersect)
             message = "cannot modify hitAttributeNV in this stage";
         break;
 #endif
@@ -181,9 +181,12 @@
         case EbtAtomicUint:
             message = "can't modify an atomic_uint";
             break;
-        case EbtAccStructNV:
+        case EbtAccStruct:
             message = "can't modify accelerationStructureNV";
             break;
+        case EbtRayQuery:
+            message = "can't modify rayQueryEXT";
+            break;
 #endif
         default:
             break;
diff --git a/third_party/glslang/src/glslang/MachineIndependent/ParseHelper.cpp b/third_party/glslang/src/glslang/MachineIndependent/ParseHelper.cpp
index d9a4d4a..f954802 100644
--- a/third_party/glslang/src/glslang/MachineIndependent/ParseHelper.cpp
+++ b/third_party/glslang/src/glslang/MachineIndependent/ParseHelper.cpp
@@ -3,6 +3,7 @@
 // Copyright (C) 2012-2015 LunarG, Inc.
 // Copyright (C) 2015-2018 Google, Inc.
 // Copyright (C) 2017, 2019 ARM Limited.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 //
 // All rights reserved.
 //
@@ -2012,18 +2013,20 @@
         if (arg > 0) {
 
 #ifndef GLSLANG_WEB
-            bool f16ShadowCompare = (*argp)[1]->getAsTyped()->getBasicType() == EbtFloat16 && arg0->getType().getSampler().shadow;
+            bool f16ShadowCompare = (*argp)[1]->getAsTyped()->getBasicType() == EbtFloat16 &&
+                                    arg0->getType().getSampler().shadow;
             if (f16ShadowCompare)
                 ++arg;
 #endif
-            if (! (*argp)[arg]->getAsConstantUnion())
+            if (! (*argp)[arg]->getAsTyped()->getQualifier().isConstant())
                 error(loc, "argument must be compile-time constant", "texel offset", "");
-            else {
+            else if ((*argp)[arg]->getAsConstantUnion()) {
                 const TType& type = (*argp)[arg]->getAsTyped()->getType();
                 for (int c = 0; c < type.getVectorSize(); ++c) {
                     int offset = (*argp)[arg]->getAsConstantUnion()->getConstArray()[c].getIConst();
                     if (offset > resources.maxProgramTexelOffset || offset < resources.minProgramTexelOffset)
-                        error(loc, "value is out of range:", "texel offset", "[gl_MinProgramTexelOffset, gl_MaxProgramTexelOffset]");
+                        error(loc, "value is out of range:", "texel offset",
+                              "[gl_MinProgramTexelOffset, gl_MaxProgramTexelOffset]");
                 }
             }
         }
@@ -2032,15 +2035,32 @@
     }
 
 #ifndef GLSLANG_WEB
-    case EOpTraceNV:
+    case EOpTrace:
         if (!(*argp)[10]->getAsConstantUnion())
             error(loc, "argument must be compile-time constant", "payload number", "");
         break;
-    case EOpExecuteCallableNV:
+    case EOpExecuteCallable:
         if (!(*argp)[1]->getAsConstantUnion())
             error(loc, "argument must be compile-time constant", "callable data number", "");
         break;
 
+    case EOpRayQueryGetIntersectionType:
+    case EOpRayQueryGetIntersectionT:
+    case EOpRayQueryGetIntersectionInstanceCustomIndex:
+    case EOpRayQueryGetIntersectionInstanceId:
+    case EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset:
+    case EOpRayQueryGetIntersectionGeometryIndex:
+    case EOpRayQueryGetIntersectionPrimitiveIndex:
+    case EOpRayQueryGetIntersectionBarycentrics:
+    case EOpRayQueryGetIntersectionFrontFace:
+    case EOpRayQueryGetIntersectionObjectRayDirection:
+    case EOpRayQueryGetIntersectionObjectRayOrigin:
+    case EOpRayQueryGetIntersectionObjectToWorld:
+    case EOpRayQueryGetIntersectionWorldToObject:
+        if (!(*argp)[1]->getAsConstantUnion())
+            error(loc, "argument must be compile-time constant", "committed", "");
+        break;
+
     case EOpTextureQuerySamples:
     case EOpImageQuerySamples:
         // GL_ARB_shader_texture_image_samples
@@ -3134,7 +3154,7 @@
     if (function[0].type->getBasicType() != EbtSampler ||
         ! function[0].type->getSampler().isTexture() ||
         function[0].type->isArray()) {
-        error(loc, "sampler-constructor first argument must be a scalar textureXXX type", token, "");
+        error(loc, "sampler-constructor first argument must be a scalar *texture* type", token, "");
         return true;
     }
     // simulate the first argument's impact on the result type, so it can be compared with the encapsulated operator!=()
@@ -3142,7 +3162,8 @@
     texture.setCombined(false);
     texture.shadow = false;
     if (texture != function[0].type->getSampler()) {
-        error(loc, "sampler-constructor first argument must match type and dimensionality of constructor type", token, "");
+        error(loc, "sampler-constructor first argument must be a *texture* type"
+                   " matching the dimensionality and sampled type of the constructor", token, "");
         return true;
     }
 
@@ -3152,7 +3173,7 @@
     if (  function[1].type->getBasicType() != EbtSampler ||
         ! function[1].type->getSampler().isPureSampler() ||
           function[1].type->isArray()) {
-        error(loc, "sampler-constructor second argument must be a scalar type 'sampler'", token, "");
+        error(loc, "sampler-constructor second argument must be a scalar sampler or samplerShadow", token, "");
         return true;
     }
 
@@ -3228,14 +3249,14 @@
         error(loc, "atomic_uints can only be used in uniform variables or function parameters:", type.getBasicTypeString().c_str(), identifier.c_str());
 }
 
-void TParseContext::accStructNVCheck(const TSourceLoc& loc, const TType& type, const TString& identifier)
+void TParseContext::accStructCheck(const TSourceLoc& loc, const TType& type, const TString& identifier)
 {
     if (type.getQualifier().storage == EvqUniform)
         return;
 
-    if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtAccStructNV))
+    if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtAccStruct))
         error(loc, "non-uniform struct contains an accelerationStructureNV:", type.getBasicTypeString().c_str(), identifier.c_str());
-    else if (type.getBasicType() == EbtAccStructNV && type.getQualifier().storage != EvqUniform)
+    else if (type.getBasicType() == EbtAccStruct && type.getQualifier().storage != EvqUniform)
         error(loc, "accelerationStructureNV can only be used in uniform variables or function parameters:",
             type.getBasicTypeString().c_str(), identifier.c_str());
 
@@ -3519,12 +3540,14 @@
         dst.precision = src.precision;
 
 #ifndef GLSLANG_WEB
-    if (!force && ((src.coherent && (dst.devicecoherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.subgroupcoherent)) ||
-                   (src.devicecoherent && (dst.coherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.subgroupcoherent)) ||
-                   (src.queuefamilycoherent && (dst.coherent || dst.devicecoherent || dst.workgroupcoherent || dst.subgroupcoherent)) ||
-                   (src.workgroupcoherent && (dst.coherent || dst.devicecoherent || dst.queuefamilycoherent || dst.subgroupcoherent)) ||
-                   (src.subgroupcoherent  && (dst.coherent || dst.devicecoherent || dst.queuefamilycoherent || dst.workgroupcoherent)))) {
-        error(loc, "only one coherent/devicecoherent/queuefamilycoherent/workgroupcoherent/subgroupcoherent qualifier allowed", GetPrecisionQualifierString(src.precision), "");
+    if (!force && ((src.coherent && (dst.devicecoherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.subgroupcoherent || dst.shadercallcoherent)) ||
+                   (src.devicecoherent && (dst.coherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.subgroupcoherent || dst.shadercallcoherent)) ||
+                   (src.queuefamilycoherent && (dst.coherent || dst.devicecoherent || dst.workgroupcoherent || dst.subgroupcoherent || dst.shadercallcoherent)) ||
+                   (src.workgroupcoherent && (dst.coherent || dst.devicecoherent || dst.queuefamilycoherent || dst.subgroupcoherent || dst.shadercallcoherent)) ||
+                   (src.subgroupcoherent  && (dst.coherent || dst.devicecoherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.shadercallcoherent)) ||
+                   (src.shadercallcoherent && (dst.coherent || dst.devicecoherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.subgroupcoherent)))) {
+        error(loc, "only one coherent/devicecoherent/queuefamilycoherent/workgroupcoherent/subgroupcoherent/shadercallcoherent qualifier allowed", 
+            GetPrecisionQualifierString(src.precision), "");
     }
 #endif
     // Layout qualifiers
@@ -3552,6 +3575,7 @@
     MERGE_SINGLETON(queuefamilycoherent);
     MERGE_SINGLETON(workgroupcoherent);
     MERGE_SINGLETON(subgroupcoherent);
+    MERGE_SINGLETON(shadercallcoherent);
     MERGE_SINGLETON(nonprivate);
     MERGE_SINGLETON(volatil);
     MERGE_SINGLETON(restrict);
@@ -3989,7 +4013,7 @@
     }
 
     // check for additional things allowed by GL_EXT_nonuniform_qualifier
-    if (base.getBasicType() == EbtSampler || base.getBasicType() == EbtAccStructNV ||
+    if (base.getBasicType() == EbtSampler || base.getBasicType() == EbtAccStruct || base.getBasicType() == EbtRayQuery ||
         (base.getBasicType() == EbtBlock && base.getType().getQualifier().isUniformOrBuffer()))
         requireExtensions(loc, 1, &E_GL_EXT_nonuniform_qualifier, "variable index");
     else
@@ -4493,6 +4517,7 @@
         type.getQualifier().queuefamilycoherent  = qualifier.queuefamilycoherent;
         type.getQualifier().workgroupcoherent  = qualifier.workgroupcoherent;
         type.getQualifier().subgroupcoherent  = qualifier.subgroupcoherent;
+        type.getQualifier().shadercallcoherent = qualifier.shadercallcoherent;
         type.getQualifier().nonprivate = qualifier.nonprivate;
         type.getQualifier().readonly  = qualifier.readonly;
         type.getQualifier().writeonly = qualifier.writeonly;
@@ -5073,13 +5098,19 @@
             return;
         }
     } else {
-        if (language == EShLangRayGenNV || language == EShLangIntersectNV ||
-        language == EShLangAnyHitNV || language == EShLangClosestHitNV ||
-        language == EShLangMissNV || language == EShLangCallableNV) {
-            if (id == "shaderrecordnv") {
-                publicType.qualifier.layoutShaderRecordNV = true;
+        if (language == EShLangRayGen || language == EShLangIntersect ||
+        language == EShLangAnyHit || language == EShLangClosestHit ||
+        language == EShLangMiss || language == EShLangCallable) {
+            if (id == "shaderrecordnv" || id == "shaderrecordext") {
+                if (id == "shaderrecordnv") {
+                    requireExtensions(loc, 1, &E_GL_NV_ray_tracing, "shader record NV");
+                } else {
+                    requireExtensions(loc, 1, &E_GL_EXT_ray_tracing, "shader record EXT");
+                }
+                publicType.qualifier.layoutShaderRecord = true;
                 return;
             }
+
         }
     }
     if (language == EShLangCompute) {
@@ -5521,8 +5552,8 @@
             dst.layoutViewportRelative = true;
         if (src.layoutSecondaryViewportRelativeOffset != -2048)
             dst.layoutSecondaryViewportRelativeOffset = src.layoutSecondaryViewportRelativeOffset;
-        if (src.layoutShaderRecordNV)
-            dst.layoutShaderRecordNV = true;
+        if (src.layoutShaderRecord)
+            dst.layoutShaderRecord = true;
         if (src.pervertexNV)
             dst.pervertexNV = true;
 #endif
@@ -5590,7 +5621,7 @@
                     error(loc, "cannot specify on a variable declaration", "align", "");
                 if (qualifier.isPushConstant())
                     error(loc, "can only specify on a uniform block", "push_constant", "");
-                if (qualifier.isShaderRecordNV())
+                if (qualifier.isShaderRecord())
                     error(loc, "can only specify on a buffer block", "shaderRecordNV", "");
             }
             break;
@@ -5664,11 +5695,11 @@
                 error(loc, "cannot apply to uniform or buffer block", "location", "");
             break;
 #ifndef GLSLANG_WEB
-        case EvqPayloadNV:
-        case EvqPayloadInNV:
-        case EvqHitAttrNV:
-        case EvqCallableDataNV:
-        case EvqCallableDataInNV:
+        case EvqPayload:
+        case EvqPayloadIn:
+        case EvqHitAttr:
+        case EvqCallableData:
+        case EvqCallableDataIn:
             break;
 #endif
         default:
@@ -5763,7 +5794,7 @@
         if (spvVersion.spv > 0) {
             if (qualifier.isUniformOrBuffer()) {
                 if (type.getBasicType() == EbtBlock && !qualifier.isPushConstant() &&
-                       !qualifier.isShaderRecordNV() &&
+                       !qualifier.isShaderRecord() &&
                        !qualifier.hasAttachment() &&
                        !qualifier.hasBufferReference())
                     error(loc, "uniform/buffer blocks require layout(binding=X)", "binding", "");
@@ -5820,7 +5851,7 @@
     if (qualifier.hasBufferReference() && type.getBasicType() != EbtBlock)
         error(loc, "can only be used with a block", "buffer_reference", "");
 
-    if (qualifier.isShaderRecordNV() && type.getBasicType() != EbtBlock)
+    if (qualifier.isShaderRecord() && type.getBasicType() != EbtBlock)
         error(loc, "can only be used with a block", "shaderRecordNV", "");
 
     // input attachment
@@ -5965,7 +5996,7 @@
         if (qualifier.storage != EvqBuffer)
             error(loc, "can only be used with buffer", "buffer_reference", "");
     }
-    if (qualifier.isShaderRecordNV()) {
+    if (qualifier.isShaderRecord()) {
         if (qualifier.storage != EvqBuffer)
             error(loc, "can only be used with a buffer", "shaderRecordNV", "");
         if (qualifier.hasBinding())
@@ -5974,7 +6005,7 @@
             error(loc, "cannot be used with shaderRecordNV", "set", "");
 
     }
-    if (qualifier.storage == EvqHitAttrNV && qualifier.hasLayout()) {
+    if (qualifier.storage == EvqHitAttr && qualifier.hasLayout()) {
         error(loc, "cannot apply layout qualifiers to hitAttributeNV variable", "hitAttributeNV", "");
     }
 }
@@ -6477,7 +6508,7 @@
     transparentOpaqueCheck(loc, type, identifier);
 #ifndef GLSLANG_WEB
     atomicUintCheck(loc, type, identifier);
-    accStructNVCheck(loc, type, identifier);
+    accStructCheck(loc, type, identifier);
     checkAndResizeMeshViewDim(loc, type, /*isBlockMember*/ false);
 #endif
     if (type.getQualifier().storage == EvqConst && type.containsReference()) {
@@ -7411,7 +7442,7 @@
     // Special case for "push_constant uniform", which has a default of std430,
     // contrary to normal uniform defaults, and can't have a default tracked for it.
     if ((currentBlockQualifier.isPushConstant() && !currentBlockQualifier.hasPacking()) ||
-        (currentBlockQualifier.isShaderRecordNV() && !currentBlockQualifier.hasPacking()))
+        (currentBlockQualifier.isShaderRecord() && !currentBlockQualifier.hasPacking()))
         currentBlockQualifier.layoutPacking = ElpStd430;
 
     // Special case for "taskNV in/out", which has a default of std430,
@@ -7628,6 +7659,7 @@
 // with a particular stage.
 void TParseContext::blockStageIoCheck(const TSourceLoc& loc, const TQualifier& qualifier)
 {
+    const char *extsrt[2] = { E_GL_NV_ray_tracing, E_GL_EXT_ray_tracing };
     switch (qualifier.storage) {
     case EvqUniform:
         profileRequires(loc, EEsProfile, 300, nullptr, "uniform block");
@@ -7666,28 +7698,28 @@
         }
         break;
 #ifndef GLSLANG_WEB
-    case EvqPayloadNV:
-        profileRequires(loc, ~EEsProfile, 460, E_GL_NV_ray_tracing, "rayPayloadNV block");
-        requireStage(loc, (EShLanguageMask)(EShLangRayGenNVMask | EShLangAnyHitNVMask | EShLangClosestHitNVMask | EShLangMissNVMask),
+    case EvqPayload:
+        profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "rayPayloadNV block");
+        requireStage(loc, (EShLanguageMask)(EShLangRayGenMask | EShLangAnyHitMask | EShLangClosestHitMask | EShLangMissMask),
             "rayPayloadNV block");
         break;
-    case EvqPayloadInNV:
-        profileRequires(loc, ~EEsProfile, 460, E_GL_NV_ray_tracing, "rayPayloadInNV block");
-        requireStage(loc, (EShLanguageMask)(EShLangAnyHitNVMask | EShLangClosestHitNVMask | EShLangMissNVMask),
+    case EvqPayloadIn:
+        profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "rayPayloadInNV block");
+        requireStage(loc, (EShLanguageMask)(EShLangAnyHitMask | EShLangClosestHitMask | EShLangMissMask),
             "rayPayloadInNV block");
         break;
-    case EvqHitAttrNV:
-        profileRequires(loc, ~EEsProfile, 460, E_GL_NV_ray_tracing, "hitAttributeNV block");
-        requireStage(loc, (EShLanguageMask)(EShLangIntersectNVMask | EShLangAnyHitNVMask | EShLangClosestHitNVMask), "hitAttributeNV block");
+    case EvqHitAttr:
+        profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "hitAttributeNV block");
+        requireStage(loc, (EShLanguageMask)(EShLangIntersectMask | EShLangAnyHitMask | EShLangClosestHitMask), "hitAttributeNV block");
         break;
-    case EvqCallableDataNV:
-        profileRequires(loc, ~EEsProfile, 460, E_GL_NV_ray_tracing, "callableDataNV block");
-        requireStage(loc, (EShLanguageMask)(EShLangRayGenNVMask | EShLangClosestHitNVMask | EShLangMissNVMask | EShLangCallableNVMask),
+    case EvqCallableData:
+        profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "callableDataNV block");
+        requireStage(loc, (EShLanguageMask)(EShLangRayGenMask | EShLangClosestHitMask | EShLangMissMask | EShLangCallableMask),
             "callableDataNV block");
         break;
-    case EvqCallableDataInNV:
-        profileRequires(loc, ~EEsProfile, 460, E_GL_NV_ray_tracing, "callableDataInNV block");
-        requireStage(loc, (EShLanguageMask)(EShLangCallableNVMask), "callableDataInNV block");
+    case EvqCallableDataIn:
+        profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "callableDataInNV block");
+        requireStage(loc, (EShLanguageMask)(EShLangCallableMask), "callableDataInNV block");
         break;
 #endif
     default:
@@ -7726,8 +7758,8 @@
         error(loc, "cannot use invariant qualifier on an interface block", "invariant", "");
     if (qualifier.isPushConstant())
         intermediate.addPushConstantCount();
-    if (qualifier.isShaderRecordNV())
-        intermediate.addShaderRecordNVCount();
+    if (qualifier.isShaderRecord())
+        intermediate.addShaderRecordCount();
     if (qualifier.isTaskMemory())
         intermediate.addTaskNVCount();
 }
@@ -8249,7 +8281,7 @@
         error(loc, "cannot declare a default, can only be used on a block", "buffer_reference", "");
     if (qualifier.hasSpecConstantId())
         error(loc, "cannot declare a default, can only be used on a scalar", "constant_id", "");
-    if (qualifier.isShaderRecordNV())
+    if (qualifier.isShaderRecord())
         error(loc, "cannot declare a default, can only be used on a block", "shaderRecordNV", "");
 }
 
diff --git a/third_party/glslang/src/glslang/MachineIndependent/ParseHelper.h b/third_party/glslang/src/glslang/MachineIndependent/ParseHelper.h
index 39363f1..20df640 100644
--- a/third_party/glslang/src/glslang/MachineIndependent/ParseHelper.h
+++ b/third_party/glslang/src/glslang/MachineIndependent/ParseHelper.h
@@ -358,7 +358,7 @@
     void boolCheck(const TSourceLoc&, const TPublicType&);
     void samplerCheck(const TSourceLoc&, const TType&, const TString& identifier, TIntermTyped* initializer);
     void atomicUintCheck(const TSourceLoc&, const TType&, const TString& identifier);
-    void accStructNVCheck(const TSourceLoc & loc, const TType & type, const TString & identifier);
+    void accStructCheck(const TSourceLoc & loc, const TType & type, const TString & identifier);
     void transparentOpaqueCheck(const TSourceLoc&, const TType&, const TString& identifier);
     void memberQualifierCheck(glslang::TPublicType&);
     void globalQualifierFixCheck(const TSourceLoc&, TQualifier&);
diff --git a/third_party/glslang/src/glslang/MachineIndependent/Scan.cpp b/third_party/glslang/src/glslang/MachineIndependent/Scan.cpp
index c2f8969..656daaf 100644
--- a/third_party/glslang/src/glslang/MachineIndependent/Scan.cpp
+++ b/third_party/glslang/src/glslang/MachineIndependent/Scan.cpp
@@ -3,6 +3,7 @@
 // Copyright (C) 2013 LunarG, Inc.
 // Copyright (C) 2017 ARM Limited.
 // Copyright (C) 2020 Google, Inc.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 //
 // All rights reserved.
 //
@@ -415,6 +416,7 @@
     (*KeywordMap)["queuefamilycoherent"] =     QUEUEFAMILYCOHERENT;
     (*KeywordMap)["workgroupcoherent"] =       WORKGROUPCOHERENT;
     (*KeywordMap)["subgroupcoherent"] =        SUBGROUPCOHERENT;
+    (*KeywordMap)["shadercallcoherent"] =      SHADERCALLCOHERENT;
     (*KeywordMap)["nonprivate"] =              NONPRIVATE;
     (*KeywordMap)["restrict"] =                RESTRICT;
     (*KeywordMap)["readonly"] =                READONLY;
@@ -703,11 +705,18 @@
     (*KeywordMap)["precise"] =                 PRECISE;
 
     (*KeywordMap)["rayPayloadNV"] =            PAYLOADNV;
+    (*KeywordMap)["rayPayloadEXT"] =           PAYLOADEXT;
     (*KeywordMap)["rayPayloadInNV"] =          PAYLOADINNV;
+    (*KeywordMap)["rayPayloadInEXT"] =         PAYLOADINEXT;
     (*KeywordMap)["hitAttributeNV"] =          HITATTRNV;
+    (*KeywordMap)["hitAttributeEXT"] =         HITATTREXT;
     (*KeywordMap)["callableDataNV"] =          CALLDATANV;
+    (*KeywordMap)["callableDataEXT"] =         CALLDATAEXT;
     (*KeywordMap)["callableDataInNV"] =        CALLDATAINNV;
+    (*KeywordMap)["callableDataInEXT"] =       CALLDATAINEXT;
     (*KeywordMap)["accelerationStructureNV"] = ACCSTRUCTNV;
+    (*KeywordMap)["accelerationStructureEXT"]   = ACCSTRUCTEXT;
+    (*KeywordMap)["rayQueryEXT"] =              RAYQUERYEXT;
     (*KeywordMap)["perprimitiveNV"] =          PERPRIMITIVENV;
     (*KeywordMap)["perviewNV"] =               PERVIEWNV;
     (*KeywordMap)["taskNV"] =                  PERTASKNV;
@@ -1014,6 +1023,23 @@
             parseContext.extensionTurnedOn(E_GL_NV_ray_tracing))
             return keyword;
         return identifierOrType();
+    case PAYLOADEXT:
+    case PAYLOADINEXT:
+    case HITATTREXT:
+    case CALLDATAEXT:
+    case CALLDATAINEXT:
+    case ACCSTRUCTEXT:
+        if (parseContext.symbolTable.atBuiltInLevel() ||
+            parseContext.extensionTurnedOn(E_GL_EXT_ray_tracing) ||
+            parseContext.extensionTurnedOn(E_GL_EXT_ray_query))
+            return keyword;
+        return identifierOrType();
+    case RAYQUERYEXT:
+        if (parseContext.symbolTable.atBuiltInLevel() ||
+            (!parseContext.isEsProfile() && parseContext.version >= 460
+                 && parseContext.extensionTurnedOn(E_GL_EXT_ray_query)))
+            return keyword;
+        return identifierOrType();
     case ATOMIC_UINT:
         if ((parseContext.isEsProfile() && parseContext.version >= 310) ||
             parseContext.extensionTurnedOn(E_GL_ARB_shader_atomic_counters))
@@ -1025,6 +1051,7 @@
     case QUEUEFAMILYCOHERENT:
     case WORKGROUPCOHERENT:
     case SUBGROUPCOHERENT:
+    case SHADERCALLCOHERENT:
     case NONPRIVATE:
     case RESTRICT:
     case READONLY:
diff --git a/third_party/glslang/src/glslang/MachineIndependent/ShaderLang.cpp b/third_party/glslang/src/glslang/MachineIndependent/ShaderLang.cpp
index f50c805..a1392db 100644
--- a/third_party/glslang/src/glslang/MachineIndependent/ShaderLang.cpp
+++ b/third_party/glslang/src/glslang/MachineIndependent/ShaderLang.cpp
@@ -361,17 +361,17 @@
 
     // check for ray tracing stages
     if (profile != EEsProfile && version >= 450) {
-        InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangRayGenNV, source,
+        InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangRayGen, source,
             infoSink, commonTable, symbolTables);
-        InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangIntersectNV, source,
+        InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangIntersect, source,
             infoSink, commonTable, symbolTables);
-        InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangAnyHitNV, source,
+        InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangAnyHit, source,
             infoSink, commonTable, symbolTables);
-        InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangClosestHitNV, source,
+        InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangClosestHit, source,
             infoSink, commonTable, symbolTables);
-        InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangMissNV, source,
+        InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangMiss, source,
             infoSink, commonTable, symbolTables);
-        InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangCallableNV, source,
+        InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangCallable, source,
             infoSink, commonTable, symbolTables);
     }
 
@@ -623,12 +623,12 @@
             version = profile == EEsProfile ? 310 : 420;
         }
         break;
-    case EShLangRayGenNV:
-    case EShLangIntersectNV:
-    case EShLangAnyHitNV:
-    case EShLangClosestHitNV:
-    case EShLangMissNV:
-    case EShLangCallableNV:
+    case EShLangRayGen:
+    case EShLangIntersect:
+    case EShLangAnyHit:
+    case EShLangClosestHit:
+    case EShLangMiss:
+    case EShLangCallable:
         if (profile == EEsProfile || version < 460) {
             correct = false;
             infoSink.info.message(EPrefixError, "#version: ray tracing shaders require non-es profile with version 460 or above");
@@ -1777,6 +1777,8 @@
     sourceEntryPointName = name;
 }
 
+// Log initial settings and transforms.
+// See comment for class TProcesses.
 void TShader::addProcesses(const std::vector<std::string>& p)
 {
     intermediate->addProcesses(p);
diff --git a/third_party/glslang/src/glslang/MachineIndependent/SymbolTable.cpp b/third_party/glslang/src/glslang/MachineIndependent/SymbolTable.cpp
index 4468237..06b5a81 100644
--- a/third_party/glslang/src/glslang/MachineIndependent/SymbolTable.cpp
+++ b/third_party/glslang/src/glslang/MachineIndependent/SymbolTable.cpp
@@ -3,6 +3,7 @@
 // Copyright (C) 2012-2013 LunarG, Inc.
 // Copyright (C) 2017 ARM Limited.
 // Copyright (C) 2015-2018 Google, Inc.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 //
 // All rights reserved.
 //
@@ -74,7 +75,8 @@
     case EbtInt64:              mangledName += "i64";    break;
     case EbtUint64:             mangledName += "u64";    break;
     case EbtAtomicUint:         mangledName += "au";     break;
-    case EbtAccStructNV:        mangledName += "asnv";   break;
+    case EbtAccStruct:          mangledName += "as";     break;
+    case EbtRayQuery:           mangledName += "rq";     break;
 #endif
     case EbtSampler:
         switch (sampler.type) {
@@ -120,7 +122,7 @@
             mangledName += "-tx-struct";
 
             char text[16]; // plenty enough space for the small integers.
-            snprintf(text, sizeof(text), "%d-", sampler.getStructReturnIndex());
+            snprintf(text, sizeof(text), "%u-", sampler.getStructReturnIndex());
             mangledName += text;
         } else {
             switch (sampler.getVectorSize()) {
diff --git a/third_party/glslang/src/glslang/MachineIndependent/Versions.cpp b/third_party/glslang/src/glslang/MachineIndependent/Versions.cpp
index 65c3463..a01f69b 100644
--- a/third_party/glslang/src/glslang/MachineIndependent/Versions.cpp
+++ b/third_party/glslang/src/glslang/MachineIndependent/Versions.cpp
@@ -3,6 +3,7 @@
 // Copyright (C) 2012-2013 LunarG, Inc.
 // Copyright (C) 2017 ARM Limited.
 // Copyright (C) 2015-2020 Google, Inc.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 //
 // All rights reserved.
 //
@@ -196,6 +197,8 @@
     extensionBehavior[E_GL_ARB_shader_clock]                 = EBhDisable;
     extensionBehavior[E_GL_ARB_uniform_buffer_object]        = EBhDisable;
     extensionBehavior[E_GL_ARB_sample_shading]               = EBhDisable;
+    extensionBehavior[E_GL_ARB_shader_bit_encoding]          = EBhDisable;
+    extensionBehavior[E_GL_ARB_shader_image_size]            = EBhDisable;
 
     extensionBehavior[E_GL_KHR_shader_subgroup_basic]            = EBhDisable;
     extensionBehavior[E_GL_KHR_shader_subgroup_vote]             = EBhDisable;
@@ -292,9 +295,12 @@
     extensionBehavior[E_GL_OES_texture_cube_map_array]   = EBhDisable;
 
     // EXT extensions
-    extensionBehavior[E_GL_EXT_device_group]             = EBhDisable;
-    extensionBehavior[E_GL_EXT_multiview]                = EBhDisable;
-    extensionBehavior[E_GL_EXT_shader_realtime_clock]    = EBhDisable;
+    extensionBehavior[E_GL_EXT_device_group]                = EBhDisable;
+    extensionBehavior[E_GL_EXT_multiview]                   = EBhDisable;
+    extensionBehavior[E_GL_EXT_shader_realtime_clock]       = EBhDisable;
+    extensionBehavior[E_GL_EXT_ray_tracing]                 = EBhDisable;
+    extensionBehavior[E_GL_EXT_ray_query]                   = EBhDisable;
+    extensionBehavior[E_GL_EXT_ray_flags_primitive_culling] = EBhDisable;
 
     // OVR extensions
     extensionBehavior[E_GL_OVR_multiview]                = EBhDisable;
@@ -401,10 +407,12 @@
             "#define GL_ARB_sparse_texture_clamp 1\n"
             "#define GL_ARB_shader_stencil_export 1\n"
             "#define GL_ARB_sample_shading 1\n"
+            "#define GL_ARB_shader_image_size 1\n"
 //            "#define GL_ARB_cull_distance 1\n"    // present for 4.5, but need extension control over block members
             "#define GL_ARB_post_depth_coverage 1\n"
             "#define GL_ARB_fragment_shader_interlock 1\n"
             "#define GL_ARB_uniform_buffer_object 1\n"
+            "#define GL_ARB_shader_bit_encoding 1\n"
             "#define GL_EXT_shader_non_constant_global_initializers 1\n"
             "#define GL_EXT_shader_image_load_formatted 1\n"
             "#define GL_EXT_post_depth_coverage 1\n"
@@ -433,6 +441,9 @@
 
             "#define E_GL_EXT_shader_atomic_int64 1\n"
             "#define E_GL_EXT_shader_realtime_clock 1\n"
+            "#define E_GL_EXT_ray_tracing 1\n"
+            "#define E_GL_EXT_ray_query 1\n"
+            "#define E_GL_EXT_ray_flags_primitive_culling 1\n"
 
             "#define GL_AMD_shader_ballot 1\n"
             "#define GL_AMD_shader_trinary_minmax 1\n"
@@ -546,12 +557,12 @@
     case EShLangTessControl:    return "tessellation control";
     case EShLangTessEvaluation: return "tessellation evaluation";
     case EShLangGeometry:       return "geometry";
-    case EShLangRayGenNV:       return "ray-generation";
-    case EShLangIntersectNV:    return "intersection";
-    case EShLangAnyHitNV:       return "any-hit";
-    case EShLangClosestHitNV:   return "closest-hit";
-    case EShLangMissNV:         return "miss";
-    case EShLangCallableNV:     return "callable";
+    case EShLangRayGen:         return "ray-generation";
+    case EShLangIntersect:      return "intersection";
+    case EShLangAnyHit:         return "any-hit";
+    case EShLangClosestHit:     return "closest-hit";
+    case EShLangMiss:           return "miss";
+    case EShLangCallable:       return "callable";
     case EShLangMeshNV:         return "mesh";
     case EShLangTaskNV:         return "task";
 #endif
diff --git a/third_party/glslang/src/glslang/MachineIndependent/Versions.h b/third_party/glslang/src/glslang/MachineIndependent/Versions.h
index 570d585..65c6bb6 100644
--- a/third_party/glslang/src/glslang/MachineIndependent/Versions.h
+++ b/third_party/glslang/src/glslang/MachineIndependent/Versions.h
@@ -3,6 +3,7 @@
 // Copyright (C) 2012-2013 LunarG, Inc.
 // Copyright (C) 2017 ARM Limited.
 // Copyright (C) 2015-2018 Google, Inc.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 //
 // All rights reserved.
 //
@@ -151,6 +152,8 @@
 const char* const E_GL_ARB_shader_clock                 = "GL_ARB_shader_clock";
 const char* const E_GL_ARB_uniform_buffer_object        = "GL_ARB_uniform_buffer_object";
 const char* const E_GL_ARB_sample_shading               = "GL_ARB_sample_shading";
+const char* const E_GL_ARB_shader_bit_encoding          = "GL_ARB_shader_bit_encoding";
+const char* const E_GL_ARB_shader_image_size            = "GL_ARB_shader_image_size";
 
 const char* const E_GL_KHR_shader_subgroup_basic            = "GL_KHR_shader_subgroup_basic";
 const char* const E_GL_KHR_shader_subgroup_vote             = "GL_KHR_shader_subgroup_vote";
@@ -186,6 +189,9 @@
 const char* const E_GL_EXT_demote_to_helper_invocation      = "GL_EXT_demote_to_helper_invocation";
 const char* const E_GL_EXT_shader_realtime_clock            = "GL_EXT_shader_realtime_clock";
 const char* const E_GL_EXT_debug_printf                     = "GL_EXT_debug_printf";
+const char* const E_GL_EXT_ray_tracing                      = "GL_EXT_ray_tracing";
+const char* const E_GL_EXT_ray_query                        = "GL_EXT_ray_query";
+const char* const E_GL_EXT_ray_flags_primitive_culling      = "GL_EXT_ray_flags_primitive_culling";
 
 // Arrays of extensions for the above viewportEXTs duplications
 
diff --git a/third_party/glslang/src/glslang/MachineIndependent/glslang.m4 b/third_party/glslang/src/glslang/MachineIndependent/glslang.m4
index 2a765ca..1432bf6 100644
--- a/third_party/glslang/src/glslang/MachineIndependent/glslang.m4
+++ b/third_party/glslang/src/glslang/MachineIndependent/glslang.m4
@@ -3,6 +3,7 @@
 // Copyright (C) 2012-2013 LunarG, Inc.
 // Copyright (C) 2017 ARM Limited.
 // Copyright (C) 2015-2019 Google, Inc.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 //
 // All rights reserved.
 //
@@ -204,6 +205,8 @@
 %token <lex> F64MAT4X2 F64MAT4X3 F64MAT4X4
 %token <lex> ATOMIC_UINT
 %token <lex> ACCSTRUCTNV
+%token <lex> ACCSTRUCTEXT
+%token <lex> RAYQUERYEXT
 %token <lex> FCOOPMATNV ICOOPMATNV UCOOPMATNV
 
 // combined image/sampler
@@ -263,7 +266,7 @@
 %token <lex> AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN
 %token <lex> MOD_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN
 %token <lex> SUB_ASSIGN
-%token <lex> STRING_LITERAL

+%token <lex> STRING_LITERAL
 
 %token <lex> LEFT_PAREN RIGHT_PAREN LEFT_BRACKET RIGHT_BRACKET LEFT_BRACE RIGHT_BRACE DOT
 %token <lex> COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT
@@ -286,9 +289,10 @@
 %token <lex> INT64CONSTANT UINT64CONSTANT
 %token <lex> SUBROUTINE DEMOTE
 %token <lex> PAYLOADNV PAYLOADINNV HITATTRNV CALLDATANV CALLDATAINNV
+%token <lex> PAYLOADEXT PAYLOADINEXT HITATTREXT CALLDATAEXT CALLDATAINEXT
 %token <lex> PATCH SAMPLE NONUNIFORM
 %token <lex> COHERENT VOLATILE RESTRICT READONLY WRITEONLY DEVICECOHERENT QUEUEFAMILYCOHERENT WORKGROUPCOHERENT
-%token <lex> SUBGROUPCOHERENT NONPRIVATE
+%token <lex> SUBGROUPCOHERENT NONPRIVATE SHADERCALLCOHERENT
 %token <lex> NOPERSPECTIVE EXPLICITINTERPAMD PERVERTEXNV PERPRIMITIVENV PERVIEWNV PERTASKNV
 %token <lex> PRECISE
 GLSLANG_WEB_EXCLUDE_OFF
@@ -378,9 +382,9 @@
         $$ = parseContext.intermediate.addConstantUnion($1.b, $1.loc, true);
     }
 GLSLANG_WEB_EXCLUDE_ON
-    | STRING_LITERAL {

-        $$ = parseContext.intermediate.addConstantUnion($1.string, $1.loc, true);

-    }

+    | STRING_LITERAL {
+        $$ = parseContext.intermediate.addConstantUnion($1.string, $1.loc, true);
+    }
     | INT32CONSTANT {
         parseContext.explicitInt32Check($1.loc, "32-bit signed literal");
         $$ = parseContext.intermediate.addConstantUnion($1.i, $1.loc, true);
@@ -1419,42 +1423,81 @@
     }
     | HITATTRNV {
         parseContext.globalCheck($1.loc, "hitAttributeNV");
-        parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangIntersectNVMask | EShLangClosestHitNVMask
-            | EShLangAnyHitNVMask), "hitAttributeNV");
+        parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangIntersectMask | EShLangClosestHitMask
+            | EShLangAnyHitMask), "hitAttributeNV");
         parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "hitAttributeNV");
         $$.init($1.loc);
-        $$.qualifier.storage = EvqHitAttrNV;
+        $$.qualifier.storage = EvqHitAttr;
+    }
+    | HITATTREXT {
+        parseContext.globalCheck($1.loc, "hitAttributeEXT");
+        parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangIntersectMask | EShLangClosestHitMask
+            | EShLangAnyHitMask), "hitAttributeEXT");
+        parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "hitAttributeNV");
+        $$.init($1.loc);
+        $$.qualifier.storage = EvqHitAttr;
     }
     | PAYLOADNV {
         parseContext.globalCheck($1.loc, "rayPayloadNV");
-        parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenNVMask | EShLangClosestHitNVMask |
-            EShLangAnyHitNVMask | EShLangMissNVMask), "rayPayloadNV");
+        parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenMask | EShLangClosestHitMask |
+            EShLangAnyHitMask | EShLangMissMask), "rayPayloadNV");
         parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "rayPayloadNV");
         $$.init($1.loc);
-        $$.qualifier.storage = EvqPayloadNV;
+        $$.qualifier.storage = EvqPayload;
+    }
+    | PAYLOADEXT {
+        parseContext.globalCheck($1.loc, "rayPayloadEXT");
+        parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenMask | EShLangClosestHitMask |
+            EShLangAnyHitMask | EShLangMissMask), "rayPayloadEXT");
+        parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "rayPayloadEXT");
+        $$.init($1.loc);
+        $$.qualifier.storage = EvqPayload;
     }
     | PAYLOADINNV {
         parseContext.globalCheck($1.loc, "rayPayloadInNV");
-        parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangClosestHitNVMask |
-            EShLangAnyHitNVMask | EShLangMissNVMask), "rayPayloadInNV");
+        parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangClosestHitMask |
+            EShLangAnyHitMask | EShLangMissMask), "rayPayloadInNV");
         parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "rayPayloadInNV");
         $$.init($1.loc);
-        $$.qualifier.storage = EvqPayloadInNV;
+        $$.qualifier.storage = EvqPayloadIn;
+    }
+    | PAYLOADINEXT {
+        parseContext.globalCheck($1.loc, "rayPayloadInEXT");
+        parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangClosestHitMask |
+            EShLangAnyHitMask | EShLangMissMask), "rayPayloadInEXT");
+        parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "rayPayloadInEXT");
+        $$.init($1.loc);
+        $$.qualifier.storage = EvqPayloadIn;
     }
     | CALLDATANV {
         parseContext.globalCheck($1.loc, "callableDataNV");
-        parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenNVMask |
-            EShLangClosestHitNVMask | EShLangMissNVMask | EShLangCallableNVMask), "callableDataNV");
+        parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenMask |
+            EShLangClosestHitMask | EShLangMissMask | EShLangCallableMask), "callableDataNV");
         parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "callableDataNV");
         $$.init($1.loc);
-        $$.qualifier.storage = EvqCallableDataNV;
+        $$.qualifier.storage = EvqCallableData;
+    }
+    | CALLDATAEXT {
+        parseContext.globalCheck($1.loc, "callableDataEXT");
+        parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenMask |
+            EShLangClosestHitMask | EShLangMissMask | EShLangCallableMask), "callableDataEXT");
+        parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "callableDataEXT");
+        $$.init($1.loc);
+        $$.qualifier.storage = EvqCallableData;
     }
     | CALLDATAINNV {
         parseContext.globalCheck($1.loc, "callableDataInNV");
-        parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangCallableNVMask), "callableDataInNV");
+        parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangCallableMask), "callableDataInNV");
         parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "callableDataInNV");
         $$.init($1.loc);
-        $$.qualifier.storage = EvqCallableDataInNV;
+        $$.qualifier.storage = EvqCallableDataIn;
+    }
+    | CALLDATAINEXT {
+        parseContext.globalCheck($1.loc, "callableDataInEXT");
+        parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangCallableMask), "callableDataInEXT");
+        parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "callableDataInEXT");
+        $$.init($1.loc);
+        $$.qualifier.storage = EvqCallableDataIn;
     }
     | COHERENT {
         $$.init($1.loc);
@@ -1485,6 +1528,11 @@
         parseContext.requireExtensions($1.loc, 1, &E_GL_KHR_memory_scope_semantics, "nonprivate");
         $$.qualifier.nonprivate = true;
     }
+    | SHADERCALLCOHERENT {
+        $$.init($1.loc);
+        parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_ray_tracing, "shadercallcoherent");
+        $$.qualifier.shadercallcoherent = true;
+    }
     | VOLATILE {
         $$.init($1.loc);
         $$.qualifier.volatil = true;
@@ -2354,7 +2402,15 @@
     }
     | ACCSTRUCTNV {
        $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
-       $$.basicType = EbtAccStructNV;
+       $$.basicType = EbtAccStruct;
+    }
+    | ACCSTRUCTEXT {
+       $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+       $$.basicType = EbtAccStruct;
+    }
+    | RAYQUERYEXT {
+       $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+       $$.basicType = EbtRayQuery;
     }
     | ATOMIC_UINT {
         parseContext.vulkanRemoved($1.loc, "atomic counter types");
diff --git a/third_party/glslang/src/glslang/MachineIndependent/glslang.y b/third_party/glslang/src/glslang/MachineIndependent/glslang.y
index abcd4a5..e33d7d1 100644
--- a/third_party/glslang/src/glslang/MachineIndependent/glslang.y
+++ b/third_party/glslang/src/glslang/MachineIndependent/glslang.y
@@ -2,7 +2,8 @@
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2012-2013 LunarG, Inc.
 // Copyright (C) 2017 ARM Limited.
-// Copyright (C) 2015-2018 Google, Inc.
+// Copyright (C) 2015-2019 Google, Inc.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 //
 // All rights reserved.
 //
@@ -204,6 +205,8 @@
 %token <lex> F64MAT4X2 F64MAT4X3 F64MAT4X4
 %token <lex> ATOMIC_UINT
 %token <lex> ACCSTRUCTNV
+%token <lex> ACCSTRUCTEXT
+%token <lex> RAYQUERYEXT
 %token <lex> FCOOPMATNV ICOOPMATNV UCOOPMATNV
 
 // combined image/sampler
@@ -286,9 +289,10 @@
 %token <lex> INT64CONSTANT UINT64CONSTANT
 %token <lex> SUBROUTINE DEMOTE
 %token <lex> PAYLOADNV PAYLOADINNV HITATTRNV CALLDATANV CALLDATAINNV
+%token <lex> PAYLOADEXT PAYLOADINEXT HITATTREXT CALLDATAEXT CALLDATAINEXT
 %token <lex> PATCH SAMPLE NONUNIFORM
 %token <lex> COHERENT VOLATILE RESTRICT READONLY WRITEONLY DEVICECOHERENT QUEUEFAMILYCOHERENT WORKGROUPCOHERENT
-%token <lex> SUBGROUPCOHERENT NONPRIVATE
+%token <lex> SUBGROUPCOHERENT NONPRIVATE SHADERCALLCOHERENT
 %token <lex> NOPERSPECTIVE EXPLICITINTERPAMD PERVERTEXNV PERPRIMITIVENV PERVIEWNV PERTASKNV
 %token <lex> PRECISE
 
@@ -1419,42 +1423,81 @@
     }
     | HITATTRNV {
         parseContext.globalCheck($1.loc, "hitAttributeNV");
-        parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangIntersectNVMask | EShLangClosestHitNVMask
-            | EShLangAnyHitNVMask), "hitAttributeNV");
+        parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangIntersectMask | EShLangClosestHitMask
+            | EShLangAnyHitMask), "hitAttributeNV");
         parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "hitAttributeNV");
         $$.init($1.loc);
-        $$.qualifier.storage = EvqHitAttrNV;
+        $$.qualifier.storage = EvqHitAttr;
+    }
+    | HITATTREXT {
+        parseContext.globalCheck($1.loc, "hitAttributeEXT");
+        parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangIntersectMask | EShLangClosestHitMask
+            | EShLangAnyHitMask), "hitAttributeEXT");
+        parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "hitAttributeNV");
+        $$.init($1.loc);
+        $$.qualifier.storage = EvqHitAttr;
     }
     | PAYLOADNV {
         parseContext.globalCheck($1.loc, "rayPayloadNV");
-        parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenNVMask | EShLangClosestHitNVMask |
-            EShLangAnyHitNVMask | EShLangMissNVMask), "rayPayloadNV");
+        parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenMask | EShLangClosestHitMask |
+            EShLangAnyHitMask | EShLangMissMask), "rayPayloadNV");
         parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "rayPayloadNV");
         $$.init($1.loc);
-        $$.qualifier.storage = EvqPayloadNV;
+        $$.qualifier.storage = EvqPayload;
+    }
+    | PAYLOADEXT {
+        parseContext.globalCheck($1.loc, "rayPayloadEXT");
+        parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenMask | EShLangClosestHitMask |
+            EShLangAnyHitMask | EShLangMissMask), "rayPayloadEXT");
+        parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "rayPayloadEXT");
+        $$.init($1.loc);
+        $$.qualifier.storage = EvqPayload;
     }
     | PAYLOADINNV {
         parseContext.globalCheck($1.loc, "rayPayloadInNV");
-        parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangClosestHitNVMask |
-            EShLangAnyHitNVMask | EShLangMissNVMask), "rayPayloadInNV");
+        parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangClosestHitMask |
+            EShLangAnyHitMask | EShLangMissMask), "rayPayloadInNV");
         parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "rayPayloadInNV");
         $$.init($1.loc);
-        $$.qualifier.storage = EvqPayloadInNV;
+        $$.qualifier.storage = EvqPayloadIn;
+    }
+    | PAYLOADINEXT {
+        parseContext.globalCheck($1.loc, "rayPayloadInEXT");
+        parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangClosestHitMask |
+            EShLangAnyHitMask | EShLangMissMask), "rayPayloadInEXT");
+        parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "rayPayloadInEXT");
+        $$.init($1.loc);
+        $$.qualifier.storage = EvqPayloadIn;
     }
     | CALLDATANV {
         parseContext.globalCheck($1.loc, "callableDataNV");
-        parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenNVMask |
-            EShLangClosestHitNVMask | EShLangMissNVMask | EShLangCallableNVMask), "callableDataNV");
+        parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenMask |
+            EShLangClosestHitMask | EShLangMissMask | EShLangCallableMask), "callableDataNV");
         parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "callableDataNV");
         $$.init($1.loc);
-        $$.qualifier.storage = EvqCallableDataNV;
+        $$.qualifier.storage = EvqCallableData;
+    }
+    | CALLDATAEXT {
+        parseContext.globalCheck($1.loc, "callableDataEXT");
+        parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenMask |
+            EShLangClosestHitMask | EShLangMissMask | EShLangCallableMask), "callableDataEXT");
+        parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "callableDataEXT");
+        $$.init($1.loc);
+        $$.qualifier.storage = EvqCallableData;
     }
     | CALLDATAINNV {
         parseContext.globalCheck($1.loc, "callableDataInNV");
-        parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangCallableNVMask), "callableDataInNV");
+        parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangCallableMask), "callableDataInNV");
         parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "callableDataInNV");
         $$.init($1.loc);
-        $$.qualifier.storage = EvqCallableDataInNV;
+        $$.qualifier.storage = EvqCallableDataIn;
+    }
+    | CALLDATAINEXT {
+        parseContext.globalCheck($1.loc, "callableDataInEXT");
+        parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangCallableMask), "callableDataInEXT");
+        parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "callableDataInEXT");
+        $$.init($1.loc);
+        $$.qualifier.storage = EvqCallableDataIn;
     }
     | COHERENT {
         $$.init($1.loc);
@@ -1485,6 +1528,11 @@
         parseContext.requireExtensions($1.loc, 1, &E_GL_KHR_memory_scope_semantics, "nonprivate");
         $$.qualifier.nonprivate = true;
     }
+    | SHADERCALLCOHERENT {
+        $$.init($1.loc);
+        parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_ray_tracing, "shadercallcoherent");
+        $$.qualifier.shadercallcoherent = true;
+    }
     | VOLATILE {
         $$.init($1.loc);
         $$.qualifier.volatil = true;
@@ -2354,7 +2402,15 @@
     }
     | ACCSTRUCTNV {
        $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
-       $$.basicType = EbtAccStructNV;
+       $$.basicType = EbtAccStruct;
+    }
+    | ACCSTRUCTEXT {
+       $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+       $$.basicType = EbtAccStruct;
+    }
+    | RAYQUERYEXT {
+       $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
+       $$.basicType = EbtRayQuery;
     }
     | ATOMIC_UINT {
         parseContext.vulkanRemoved($1.loc, "atomic counter types");
@@ -3829,3 +3885,4 @@
 
 
 %%
+
diff --git a/third_party/glslang/src/glslang/MachineIndependent/glslang_tab.cpp b/third_party/glslang/src/glslang/MachineIndependent/glslang_tab.cpp
index 30dbc33..69f7f8e 100644
--- a/third_party/glslang/src/glslang/MachineIndependent/glslang_tab.cpp
+++ b/third_party/glslang/src/glslang/MachineIndependent/glslang_tab.cpp
@@ -62,7 +62,7 @@
 
 
 /* Copy the first part of user declarations.  */
-#line 68 "MachineIndependent/glslang.y" /* yacc.c:339  */
+#line 69 "glslang.y" /* yacc.c:339  */
 
 
 /* Based on:
@@ -88,7 +88,7 @@
 using namespace glslang;
 
 
-#line 92 "MachineIndependent/glslang_tab.cpp" /* yacc.c:339  */
+#line 92 "glslang_tab.cpp" /* yacc.c:339  */
 
 # ifndef YY_NULLPTR
 #  if defined __cplusplus && 201103L <= __cplusplus
@@ -108,8 +108,8 @@
 
 /* In a future release of Bison, this section will be replaced
    by #include "glslang_tab.cpp.h".  */
-#ifndef YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED
-# define YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED
+#ifndef YY_YY_GLSLANG_TAB_CPP_H_INCLUDED
+# define YY_YY_GLSLANG_TAB_CPP_H_INCLUDED
 /* Debug traces.  */
 #ifndef YYDEBUG
 # define YYDEBUG 1
@@ -281,257 +281,265 @@
     F64MAT4X4 = 413,
     ATOMIC_UINT = 414,
     ACCSTRUCTNV = 415,
-    FCOOPMATNV = 416,
-    ICOOPMATNV = 417,
-    UCOOPMATNV = 418,
-    SAMPLERCUBEARRAY = 419,
-    SAMPLERCUBEARRAYSHADOW = 420,
-    ISAMPLERCUBEARRAY = 421,
-    USAMPLERCUBEARRAY = 422,
-    SAMPLER1D = 423,
-    SAMPLER1DARRAY = 424,
-    SAMPLER1DARRAYSHADOW = 425,
-    ISAMPLER1D = 426,
-    SAMPLER1DSHADOW = 427,
-    SAMPLER2DRECT = 428,
-    SAMPLER2DRECTSHADOW = 429,
-    ISAMPLER2DRECT = 430,
-    USAMPLER2DRECT = 431,
-    SAMPLERBUFFER = 432,
-    ISAMPLERBUFFER = 433,
-    USAMPLERBUFFER = 434,
-    SAMPLER2DMS = 435,
-    ISAMPLER2DMS = 436,
-    USAMPLER2DMS = 437,
-    SAMPLER2DMSARRAY = 438,
-    ISAMPLER2DMSARRAY = 439,
-    USAMPLER2DMSARRAY = 440,
-    SAMPLEREXTERNALOES = 441,
-    SAMPLEREXTERNAL2DY2YEXT = 442,
-    ISAMPLER1DARRAY = 443,
-    USAMPLER1D = 444,
-    USAMPLER1DARRAY = 445,
-    F16SAMPLER1D = 446,
-    F16SAMPLER2D = 447,
-    F16SAMPLER3D = 448,
-    F16SAMPLER2DRECT = 449,
-    F16SAMPLERCUBE = 450,
-    F16SAMPLER1DARRAY = 451,
-    F16SAMPLER2DARRAY = 452,
-    F16SAMPLERCUBEARRAY = 453,
-    F16SAMPLERBUFFER = 454,
-    F16SAMPLER2DMS = 455,
-    F16SAMPLER2DMSARRAY = 456,
-    F16SAMPLER1DSHADOW = 457,
-    F16SAMPLER2DSHADOW = 458,
-    F16SAMPLER1DARRAYSHADOW = 459,
-    F16SAMPLER2DARRAYSHADOW = 460,
-    F16SAMPLER2DRECTSHADOW = 461,
-    F16SAMPLERCUBESHADOW = 462,
-    F16SAMPLERCUBEARRAYSHADOW = 463,
-    IMAGE1D = 464,
-    IIMAGE1D = 465,
-    UIMAGE1D = 466,
-    IMAGE2D = 467,
-    IIMAGE2D = 468,
-    UIMAGE2D = 469,
-    IMAGE3D = 470,
-    IIMAGE3D = 471,
-    UIMAGE3D = 472,
-    IMAGE2DRECT = 473,
-    IIMAGE2DRECT = 474,
-    UIMAGE2DRECT = 475,
-    IMAGECUBE = 476,
-    IIMAGECUBE = 477,
-    UIMAGECUBE = 478,
-    IMAGEBUFFER = 479,
-    IIMAGEBUFFER = 480,
-    UIMAGEBUFFER = 481,
-    IMAGE1DARRAY = 482,
-    IIMAGE1DARRAY = 483,
-    UIMAGE1DARRAY = 484,
-    IMAGE2DARRAY = 485,
-    IIMAGE2DARRAY = 486,
-    UIMAGE2DARRAY = 487,
-    IMAGECUBEARRAY = 488,
-    IIMAGECUBEARRAY = 489,
-    UIMAGECUBEARRAY = 490,
-    IMAGE2DMS = 491,
-    IIMAGE2DMS = 492,
-    UIMAGE2DMS = 493,
-    IMAGE2DMSARRAY = 494,
-    IIMAGE2DMSARRAY = 495,
-    UIMAGE2DMSARRAY = 496,
-    F16IMAGE1D = 497,
-    F16IMAGE2D = 498,
-    F16IMAGE3D = 499,
-    F16IMAGE2DRECT = 500,
-    F16IMAGECUBE = 501,
-    F16IMAGE1DARRAY = 502,
-    F16IMAGE2DARRAY = 503,
-    F16IMAGECUBEARRAY = 504,
-    F16IMAGEBUFFER = 505,
-    F16IMAGE2DMS = 506,
-    F16IMAGE2DMSARRAY = 507,
-    TEXTURECUBEARRAY = 508,
-    ITEXTURECUBEARRAY = 509,
-    UTEXTURECUBEARRAY = 510,
-    TEXTURE1D = 511,
-    ITEXTURE1D = 512,
-    UTEXTURE1D = 513,
-    TEXTURE1DARRAY = 514,
-    ITEXTURE1DARRAY = 515,
-    UTEXTURE1DARRAY = 516,
-    TEXTURE2DRECT = 517,
-    ITEXTURE2DRECT = 518,
-    UTEXTURE2DRECT = 519,
-    TEXTUREBUFFER = 520,
-    ITEXTUREBUFFER = 521,
-    UTEXTUREBUFFER = 522,
-    TEXTURE2DMS = 523,
-    ITEXTURE2DMS = 524,
-    UTEXTURE2DMS = 525,
-    TEXTURE2DMSARRAY = 526,
-    ITEXTURE2DMSARRAY = 527,
-    UTEXTURE2DMSARRAY = 528,
-    F16TEXTURE1D = 529,
-    F16TEXTURE2D = 530,
-    F16TEXTURE3D = 531,
-    F16TEXTURE2DRECT = 532,
-    F16TEXTURECUBE = 533,
-    F16TEXTURE1DARRAY = 534,
-    F16TEXTURE2DARRAY = 535,
-    F16TEXTURECUBEARRAY = 536,
-    F16TEXTUREBUFFER = 537,
-    F16TEXTURE2DMS = 538,
-    F16TEXTURE2DMSARRAY = 539,
-    SUBPASSINPUT = 540,
-    SUBPASSINPUTMS = 541,
-    ISUBPASSINPUT = 542,
-    ISUBPASSINPUTMS = 543,
-    USUBPASSINPUT = 544,
-    USUBPASSINPUTMS = 545,
-    F16SUBPASSINPUT = 546,
-    F16SUBPASSINPUTMS = 547,
-    LEFT_OP = 548,
-    RIGHT_OP = 549,
-    INC_OP = 550,
-    DEC_OP = 551,
-    LE_OP = 552,
-    GE_OP = 553,
-    EQ_OP = 554,
-    NE_OP = 555,
-    AND_OP = 556,
-    OR_OP = 557,
-    XOR_OP = 558,
-    MUL_ASSIGN = 559,
-    DIV_ASSIGN = 560,
-    ADD_ASSIGN = 561,
-    MOD_ASSIGN = 562,
-    LEFT_ASSIGN = 563,
-    RIGHT_ASSIGN = 564,
-    AND_ASSIGN = 565,
-    XOR_ASSIGN = 566,
-    OR_ASSIGN = 567,
-    SUB_ASSIGN = 568,
-    STRING_LITERAL = 569,
-    LEFT_PAREN = 570,
-    RIGHT_PAREN = 571,
-    LEFT_BRACKET = 572,
-    RIGHT_BRACKET = 573,
-    LEFT_BRACE = 574,
-    RIGHT_BRACE = 575,
-    DOT = 576,
-    COMMA = 577,
-    COLON = 578,
-    EQUAL = 579,
-    SEMICOLON = 580,
-    BANG = 581,
-    DASH = 582,
-    TILDE = 583,
-    PLUS = 584,
-    STAR = 585,
-    SLASH = 586,
-    PERCENT = 587,
-    LEFT_ANGLE = 588,
-    RIGHT_ANGLE = 589,
-    VERTICAL_BAR = 590,
-    CARET = 591,
-    AMPERSAND = 592,
-    QUESTION = 593,
-    INVARIANT = 594,
-    HIGH_PRECISION = 595,
-    MEDIUM_PRECISION = 596,
-    LOW_PRECISION = 597,
-    PRECISION = 598,
-    PACKED = 599,
-    RESOURCE = 600,
-    SUPERP = 601,
-    FLOATCONSTANT = 602,
-    INTCONSTANT = 603,
-    UINTCONSTANT = 604,
-    BOOLCONSTANT = 605,
-    IDENTIFIER = 606,
-    TYPE_NAME = 607,
-    CENTROID = 608,
-    IN = 609,
-    OUT = 610,
-    INOUT = 611,
-    STRUCT = 612,
-    VOID = 613,
-    WHILE = 614,
-    BREAK = 615,
-    CONTINUE = 616,
-    DO = 617,
-    ELSE = 618,
-    FOR = 619,
-    IF = 620,
-    DISCARD = 621,
-    RETURN = 622,
-    SWITCH = 623,
-    CASE = 624,
-    DEFAULT = 625,
-    UNIFORM = 626,
-    SHARED = 627,
-    BUFFER = 628,
-    FLAT = 629,
-    SMOOTH = 630,
-    LAYOUT = 631,
-    DOUBLECONSTANT = 632,
-    INT16CONSTANT = 633,
-    UINT16CONSTANT = 634,
-    FLOAT16CONSTANT = 635,
-    INT32CONSTANT = 636,
-    UINT32CONSTANT = 637,
-    INT64CONSTANT = 638,
-    UINT64CONSTANT = 639,
-    SUBROUTINE = 640,
-    DEMOTE = 641,
-    PAYLOADNV = 642,
-    PAYLOADINNV = 643,
-    HITATTRNV = 644,
-    CALLDATANV = 645,
-    CALLDATAINNV = 646,
-    PATCH = 647,
-    SAMPLE = 648,
-    NONUNIFORM = 649,
-    COHERENT = 650,
-    VOLATILE = 651,
-    RESTRICT = 652,
-    READONLY = 653,
-    WRITEONLY = 654,
-    DEVICECOHERENT = 655,
-    QUEUEFAMILYCOHERENT = 656,
-    WORKGROUPCOHERENT = 657,
-    SUBGROUPCOHERENT = 658,
-    NONPRIVATE = 659,
-    NOPERSPECTIVE = 660,
-    EXPLICITINTERPAMD = 661,
-    PERVERTEXNV = 662,
-    PERPRIMITIVENV = 663,
-    PERVIEWNV = 664,
-    PERTASKNV = 665,
-    PRECISE = 666
+    ACCSTRUCTEXT = 416,
+    RAYQUERYEXT = 417,
+    FCOOPMATNV = 418,
+    ICOOPMATNV = 419,
+    UCOOPMATNV = 420,
+    SAMPLERCUBEARRAY = 421,
+    SAMPLERCUBEARRAYSHADOW = 422,
+    ISAMPLERCUBEARRAY = 423,
+    USAMPLERCUBEARRAY = 424,
+    SAMPLER1D = 425,
+    SAMPLER1DARRAY = 426,
+    SAMPLER1DARRAYSHADOW = 427,
+    ISAMPLER1D = 428,
+    SAMPLER1DSHADOW = 429,
+    SAMPLER2DRECT = 430,
+    SAMPLER2DRECTSHADOW = 431,
+    ISAMPLER2DRECT = 432,
+    USAMPLER2DRECT = 433,
+    SAMPLERBUFFER = 434,
+    ISAMPLERBUFFER = 435,
+    USAMPLERBUFFER = 436,
+    SAMPLER2DMS = 437,
+    ISAMPLER2DMS = 438,
+    USAMPLER2DMS = 439,
+    SAMPLER2DMSARRAY = 440,
+    ISAMPLER2DMSARRAY = 441,
+    USAMPLER2DMSARRAY = 442,
+    SAMPLEREXTERNALOES = 443,
+    SAMPLEREXTERNAL2DY2YEXT = 444,
+    ISAMPLER1DARRAY = 445,
+    USAMPLER1D = 446,
+    USAMPLER1DARRAY = 447,
+    F16SAMPLER1D = 448,
+    F16SAMPLER2D = 449,
+    F16SAMPLER3D = 450,
+    F16SAMPLER2DRECT = 451,
+    F16SAMPLERCUBE = 452,
+    F16SAMPLER1DARRAY = 453,
+    F16SAMPLER2DARRAY = 454,
+    F16SAMPLERCUBEARRAY = 455,
+    F16SAMPLERBUFFER = 456,
+    F16SAMPLER2DMS = 457,
+    F16SAMPLER2DMSARRAY = 458,
+    F16SAMPLER1DSHADOW = 459,
+    F16SAMPLER2DSHADOW = 460,
+    F16SAMPLER1DARRAYSHADOW = 461,
+    F16SAMPLER2DARRAYSHADOW = 462,
+    F16SAMPLER2DRECTSHADOW = 463,
+    F16SAMPLERCUBESHADOW = 464,
+    F16SAMPLERCUBEARRAYSHADOW = 465,
+    IMAGE1D = 466,
+    IIMAGE1D = 467,
+    UIMAGE1D = 468,
+    IMAGE2D = 469,
+    IIMAGE2D = 470,
+    UIMAGE2D = 471,
+    IMAGE3D = 472,
+    IIMAGE3D = 473,
+    UIMAGE3D = 474,
+    IMAGE2DRECT = 475,
+    IIMAGE2DRECT = 476,
+    UIMAGE2DRECT = 477,
+    IMAGECUBE = 478,
+    IIMAGECUBE = 479,
+    UIMAGECUBE = 480,
+    IMAGEBUFFER = 481,
+    IIMAGEBUFFER = 482,
+    UIMAGEBUFFER = 483,
+    IMAGE1DARRAY = 484,
+    IIMAGE1DARRAY = 485,
+    UIMAGE1DARRAY = 486,
+    IMAGE2DARRAY = 487,
+    IIMAGE2DARRAY = 488,
+    UIMAGE2DARRAY = 489,
+    IMAGECUBEARRAY = 490,
+    IIMAGECUBEARRAY = 491,
+    UIMAGECUBEARRAY = 492,
+    IMAGE2DMS = 493,
+    IIMAGE2DMS = 494,
+    UIMAGE2DMS = 495,
+    IMAGE2DMSARRAY = 496,
+    IIMAGE2DMSARRAY = 497,
+    UIMAGE2DMSARRAY = 498,
+    F16IMAGE1D = 499,
+    F16IMAGE2D = 500,
+    F16IMAGE3D = 501,
+    F16IMAGE2DRECT = 502,
+    F16IMAGECUBE = 503,
+    F16IMAGE1DARRAY = 504,
+    F16IMAGE2DARRAY = 505,
+    F16IMAGECUBEARRAY = 506,
+    F16IMAGEBUFFER = 507,
+    F16IMAGE2DMS = 508,
+    F16IMAGE2DMSARRAY = 509,
+    TEXTURECUBEARRAY = 510,
+    ITEXTURECUBEARRAY = 511,
+    UTEXTURECUBEARRAY = 512,
+    TEXTURE1D = 513,
+    ITEXTURE1D = 514,
+    UTEXTURE1D = 515,
+    TEXTURE1DARRAY = 516,
+    ITEXTURE1DARRAY = 517,
+    UTEXTURE1DARRAY = 518,
+    TEXTURE2DRECT = 519,
+    ITEXTURE2DRECT = 520,
+    UTEXTURE2DRECT = 521,
+    TEXTUREBUFFER = 522,
+    ITEXTUREBUFFER = 523,
+    UTEXTUREBUFFER = 524,
+    TEXTURE2DMS = 525,
+    ITEXTURE2DMS = 526,
+    UTEXTURE2DMS = 527,
+    TEXTURE2DMSARRAY = 528,
+    ITEXTURE2DMSARRAY = 529,
+    UTEXTURE2DMSARRAY = 530,
+    F16TEXTURE1D = 531,
+    F16TEXTURE2D = 532,
+    F16TEXTURE3D = 533,
+    F16TEXTURE2DRECT = 534,
+    F16TEXTURECUBE = 535,
+    F16TEXTURE1DARRAY = 536,
+    F16TEXTURE2DARRAY = 537,
+    F16TEXTURECUBEARRAY = 538,
+    F16TEXTUREBUFFER = 539,
+    F16TEXTURE2DMS = 540,
+    F16TEXTURE2DMSARRAY = 541,
+    SUBPASSINPUT = 542,
+    SUBPASSINPUTMS = 543,
+    ISUBPASSINPUT = 544,
+    ISUBPASSINPUTMS = 545,
+    USUBPASSINPUT = 546,
+    USUBPASSINPUTMS = 547,
+    F16SUBPASSINPUT = 548,
+    F16SUBPASSINPUTMS = 549,
+    LEFT_OP = 550,
+    RIGHT_OP = 551,
+    INC_OP = 552,
+    DEC_OP = 553,
+    LE_OP = 554,
+    GE_OP = 555,
+    EQ_OP = 556,
+    NE_OP = 557,
+    AND_OP = 558,
+    OR_OP = 559,
+    XOR_OP = 560,
+    MUL_ASSIGN = 561,
+    DIV_ASSIGN = 562,
+    ADD_ASSIGN = 563,
+    MOD_ASSIGN = 564,
+    LEFT_ASSIGN = 565,
+    RIGHT_ASSIGN = 566,
+    AND_ASSIGN = 567,
+    XOR_ASSIGN = 568,
+    OR_ASSIGN = 569,
+    SUB_ASSIGN = 570,
+    STRING_LITERAL = 571,
+    LEFT_PAREN = 572,
+    RIGHT_PAREN = 573,
+    LEFT_BRACKET = 574,
+    RIGHT_BRACKET = 575,
+    LEFT_BRACE = 576,
+    RIGHT_BRACE = 577,
+    DOT = 578,
+    COMMA = 579,
+    COLON = 580,
+    EQUAL = 581,
+    SEMICOLON = 582,
+    BANG = 583,
+    DASH = 584,
+    TILDE = 585,
+    PLUS = 586,
+    STAR = 587,
+    SLASH = 588,
+    PERCENT = 589,
+    LEFT_ANGLE = 590,
+    RIGHT_ANGLE = 591,
+    VERTICAL_BAR = 592,
+    CARET = 593,
+    AMPERSAND = 594,
+    QUESTION = 595,
+    INVARIANT = 596,
+    HIGH_PRECISION = 597,
+    MEDIUM_PRECISION = 598,
+    LOW_PRECISION = 599,
+    PRECISION = 600,
+    PACKED = 601,
+    RESOURCE = 602,
+    SUPERP = 603,
+    FLOATCONSTANT = 604,
+    INTCONSTANT = 605,
+    UINTCONSTANT = 606,
+    BOOLCONSTANT = 607,
+    IDENTIFIER = 608,
+    TYPE_NAME = 609,
+    CENTROID = 610,
+    IN = 611,
+    OUT = 612,
+    INOUT = 613,
+    STRUCT = 614,
+    VOID = 615,
+    WHILE = 616,
+    BREAK = 617,
+    CONTINUE = 618,
+    DO = 619,
+    ELSE = 620,
+    FOR = 621,
+    IF = 622,
+    DISCARD = 623,
+    RETURN = 624,
+    SWITCH = 625,
+    CASE = 626,
+    DEFAULT = 627,
+    UNIFORM = 628,
+    SHARED = 629,
+    BUFFER = 630,
+    FLAT = 631,
+    SMOOTH = 632,
+    LAYOUT = 633,
+    DOUBLECONSTANT = 634,
+    INT16CONSTANT = 635,
+    UINT16CONSTANT = 636,
+    FLOAT16CONSTANT = 637,
+    INT32CONSTANT = 638,
+    UINT32CONSTANT = 639,
+    INT64CONSTANT = 640,
+    UINT64CONSTANT = 641,
+    SUBROUTINE = 642,
+    DEMOTE = 643,
+    PAYLOADNV = 644,
+    PAYLOADINNV = 645,
+    HITATTRNV = 646,
+    CALLDATANV = 647,
+    CALLDATAINNV = 648,
+    PAYLOADEXT = 649,
+    PAYLOADINEXT = 650,
+    HITATTREXT = 651,
+    CALLDATAEXT = 652,
+    CALLDATAINEXT = 653,
+    PATCH = 654,
+    SAMPLE = 655,
+    NONUNIFORM = 656,
+    COHERENT = 657,
+    VOLATILE = 658,
+    RESTRICT = 659,
+    READONLY = 660,
+    WRITEONLY = 661,
+    DEVICECOHERENT = 662,
+    QUEUEFAMILYCOHERENT = 663,
+    WORKGROUPCOHERENT = 664,
+    SUBGROUPCOHERENT = 665,
+    NONPRIVATE = 666,
+    SHADERCALLCOHERENT = 667,
+    NOPERSPECTIVE = 668,
+    EXPLICITINTERPAMD = 669,
+    PERVERTEXNV = 670,
+    PERPRIMITIVENV = 671,
+    PERVIEWNV = 672,
+    PERTASKNV = 673,
+    PRECISE = 674
   };
 #endif
 
@@ -540,7 +548,7 @@
 
 union YYSTYPE
 {
-#line 96 "MachineIndependent/glslang.y" /* yacc.c:355  */
+#line 97 "glslang.y" /* yacc.c:355  */
 
     struct {
         glslang::TSourceLoc loc;
@@ -576,7 +584,7 @@
         glslang::TArraySizes* typeParameters;
     } interm;
 
-#line 580 "MachineIndependent/glslang_tab.cpp" /* yacc.c:355  */
+#line 588 "glslang_tab.cpp" /* yacc.c:355  */
 };
 
 typedef union YYSTYPE YYSTYPE;
@@ -588,10 +596,10 @@
 
 int yyparse (glslang::TParseContext* pParseContext);
 
-#endif /* !YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED  */
+#endif /* !YY_YY_GLSLANG_TAB_CPP_H_INCLUDED  */
 
 /* Copy the second part of user declarations.  */
-#line 132 "MachineIndependent/glslang.y" /* yacc.c:358  */
+#line 133 "glslang.y" /* yacc.c:358  */
 
 
 /* windows only pragma */
@@ -607,7 +615,7 @@
 extern int yylex(YYSTYPE*, TParseContext&);
 
 
-#line 611 "MachineIndependent/glslang_tab.cpp" /* yacc.c:358  */
+#line 619 "glslang_tab.cpp" /* yacc.c:358  */
 
 #ifdef short
 # undef short
@@ -847,23 +855,23 @@
 #endif /* !YYCOPY_NEEDED */
 
 /* YYFINAL -- State number of the termination state.  */
-#define YYFINAL  386
+#define YYFINAL  394
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   9386
+#define YYLAST   9550
 
 /* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  412
+#define YYNTOKENS  420
 /* YYNNTS -- Number of nonterminals.  */
 #define YYNNTS  111
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  583
+#define YYNRULES  591
 /* YYNSTATES -- Number of states.  */
-#define YYNSTATES  728
+#define YYNSTATES  736
 
 /* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
    by yylex, with out-of-bounds checking.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   666
+#define YYMAXUTOK   674
 
 #define YYTRANSLATE(YYX)                                                \
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -938,72 +946,74 @@
      375,   376,   377,   378,   379,   380,   381,   382,   383,   384,
      385,   386,   387,   388,   389,   390,   391,   392,   393,   394,
      395,   396,   397,   398,   399,   400,   401,   402,   403,   404,
-     405,   406,   407,   408,   409,   410,   411
+     405,   406,   407,   408,   409,   410,   411,   412,   413,   414,
+     415,   416,   417,   418,   419
 };
 
 #if YYDEBUG
   /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,   353,   353,   359,   362,   367,   370,   373,   377,   381,
-     384,   388,   392,   396,   400,   404,   408,   414,   422,   425,
-     428,   431,   434,   439,   447,   454,   461,   467,   471,   478,
-     481,   487,   494,   504,   512,   517,   545,   554,   560,   564,
-     568,   588,   589,   590,   591,   597,   598,   603,   608,   617,
-     618,   623,   631,   632,   638,   647,   648,   653,   658,   663,
-     671,   672,   681,   693,   694,   703,   704,   713,   714,   723,
-     724,   732,   733,   741,   742,   750,   751,   751,   769,   770,
-     786,   790,   794,   798,   803,   807,   811,   815,   819,   823,
-     827,   834,   837,   848,   855,   860,   865,   872,   876,   880,
-     884,   889,   894,   903,   903,   914,   918,   925,   932,   935,
-     942,   950,   970,   993,  1008,  1033,  1044,  1054,  1064,  1074,
-    1083,  1086,  1090,  1094,  1099,  1107,  1114,  1119,  1124,  1129,
-    1138,  1148,  1175,  1184,  1191,  1199,  1206,  1213,  1221,  1231,
-    1238,  1249,  1255,  1258,  1265,  1269,  1273,  1282,  1292,  1295,
-    1306,  1309,  1312,  1316,  1320,  1325,  1329,  1336,  1340,  1345,
-    1351,  1357,  1364,  1369,  1377,  1383,  1395,  1409,  1415,  1420,
-    1428,  1436,  1444,  1452,  1459,  1463,  1468,  1473,  1478,  1483,
-    1488,  1492,  1496,  1500,  1504,  1510,  1521,  1528,  1531,  1540,
-    1545,  1555,  1560,  1568,  1572,  1582,  1585,  1591,  1597,  1604,
-    1614,  1618,  1622,  1626,  1631,  1635,  1640,  1645,  1650,  1655,
-    1660,  1665,  1670,  1675,  1680,  1686,  1692,  1698,  1703,  1708,
-    1713,  1718,  1723,  1728,  1733,  1738,  1743,  1748,  1753,  1759,
-    1766,  1771,  1776,  1781,  1786,  1791,  1796,  1801,  1806,  1811,
-    1816,  1821,  1829,  1837,  1845,  1851,  1857,  1863,  1869,  1875,
-    1881,  1887,  1893,  1899,  1905,  1911,  1917,  1923,  1929,  1935,
-    1941,  1947,  1953,  1959,  1965,  1971,  1977,  1983,  1989,  1995,
-    2001,  2007,  2013,  2019,  2025,  2031,  2037,  2043,  2051,  2059,
-    2067,  2075,  2083,  2091,  2099,  2107,  2115,  2123,  2131,  2139,
-    2145,  2151,  2157,  2163,  2169,  2175,  2181,  2187,  2193,  2199,
-    2205,  2211,  2217,  2223,  2229,  2235,  2241,  2247,  2253,  2259,
-    2265,  2271,  2277,  2283,  2289,  2295,  2301,  2307,  2313,  2319,
-    2325,  2331,  2337,  2343,  2349,  2355,  2359,  2364,  2370,  2375,
-    2380,  2385,  2390,  2395,  2400,  2406,  2411,  2416,  2421,  2426,
-    2431,  2437,  2443,  2449,  2455,  2461,  2467,  2473,  2479,  2485,
-    2491,  2497,  2503,  2509,  2515,  2520,  2525,  2530,  2535,  2540,
-    2545,  2551,  2556,  2561,  2566,  2571,  2576,  2581,  2586,  2592,
-    2597,  2602,  2607,  2612,  2617,  2622,  2627,  2632,  2637,  2642,
-    2647,  2652,  2657,  2662,  2668,  2673,  2678,  2684,  2690,  2695,
-    2700,  2705,  2711,  2716,  2721,  2726,  2732,  2737,  2742,  2747,
-    2753,  2758,  2763,  2768,  2774,  2780,  2786,  2792,  2797,  2803,
-    2809,  2815,  2820,  2825,  2830,  2835,  2840,  2846,  2851,  2856,
-    2861,  2867,  2872,  2877,  2882,  2888,  2893,  2898,  2903,  2909,
-    2914,  2919,  2924,  2930,  2935,  2940,  2945,  2951,  2956,  2961,
-    2966,  2972,  2977,  2982,  2987,  2993,  2998,  3003,  3008,  3014,
-    3019,  3024,  3029,  3035,  3040,  3045,  3050,  3056,  3061,  3066,
-    3071,  3077,  3082,  3087,  3092,  3098,  3103,  3108,  3113,  3119,
-    3124,  3129,  3134,  3140,  3145,  3150,  3156,  3162,  3168,  3174,
-    3181,  3188,  3194,  3200,  3206,  3212,  3218,  3224,  3231,  3236,
-    3252,  3257,  3262,  3270,  3270,  3281,  3281,  3291,  3294,  3307,
-    3329,  3356,  3360,  3366,  3371,  3382,  3386,  3392,  3403,  3406,
-    3413,  3417,  3418,  3424,  3425,  3426,  3427,  3428,  3429,  3430,
-    3432,  3438,  3447,  3448,  3452,  3448,  3464,  3465,  3469,  3469,
-    3476,  3476,  3490,  3493,  3501,  3509,  3520,  3521,  3525,  3529,
-    3536,  3543,  3547,  3555,  3559,  3572,  3576,  3583,  3583,  3603,
-    3606,  3612,  3624,  3636,  3640,  3647,  3647,  3662,  3662,  3678,
-    3678,  3699,  3702,  3708,  3711,  3717,  3721,  3728,  3733,  3738,
-    3745,  3748,  3757,  3761,  3770,  3773,  3777,  3786,  3786,  3809,
-    3815,  3818,  3823,  3826
+       0,   357,   357,   363,   366,   371,   374,   377,   381,   385,
+     388,   392,   396,   400,   404,   408,   412,   418,   426,   429,
+     432,   435,   438,   443,   451,   458,   465,   471,   475,   482,
+     485,   491,   498,   508,   516,   521,   549,   558,   564,   568,
+     572,   592,   593,   594,   595,   601,   602,   607,   612,   621,
+     622,   627,   635,   636,   642,   651,   652,   657,   662,   667,
+     675,   676,   685,   697,   698,   707,   708,   717,   718,   727,
+     728,   736,   737,   745,   746,   754,   755,   755,   773,   774,
+     790,   794,   798,   802,   807,   811,   815,   819,   823,   827,
+     831,   838,   841,   852,   859,   864,   869,   876,   880,   884,
+     888,   893,   898,   907,   907,   918,   922,   929,   936,   939,
+     946,   954,   974,   997,  1012,  1037,  1048,  1058,  1068,  1078,
+    1087,  1090,  1094,  1098,  1103,  1111,  1118,  1123,  1128,  1133,
+    1142,  1152,  1179,  1188,  1195,  1203,  1210,  1217,  1225,  1235,
+    1242,  1253,  1259,  1262,  1269,  1273,  1277,  1286,  1296,  1299,
+    1310,  1313,  1316,  1320,  1324,  1329,  1333,  1340,  1344,  1349,
+    1355,  1361,  1368,  1373,  1381,  1387,  1399,  1413,  1419,  1424,
+    1432,  1440,  1448,  1456,  1464,  1472,  1480,  1488,  1495,  1502,
+    1506,  1511,  1516,  1521,  1526,  1531,  1536,  1540,  1544,  1548,
+    1552,  1558,  1569,  1576,  1579,  1588,  1593,  1603,  1608,  1616,
+    1620,  1630,  1633,  1639,  1645,  1652,  1662,  1666,  1670,  1674,
+    1679,  1683,  1688,  1693,  1698,  1703,  1708,  1713,  1718,  1723,
+    1728,  1734,  1740,  1746,  1751,  1756,  1761,  1766,  1771,  1776,
+    1781,  1786,  1791,  1796,  1801,  1807,  1814,  1819,  1824,  1829,
+    1834,  1839,  1844,  1849,  1854,  1859,  1864,  1869,  1877,  1885,
+    1893,  1899,  1905,  1911,  1917,  1923,  1929,  1935,  1941,  1947,
+    1953,  1959,  1965,  1971,  1977,  1983,  1989,  1995,  2001,  2007,
+    2013,  2019,  2025,  2031,  2037,  2043,  2049,  2055,  2061,  2067,
+    2073,  2079,  2085,  2091,  2099,  2107,  2115,  2123,  2131,  2139,
+    2147,  2155,  2163,  2171,  2179,  2187,  2193,  2199,  2205,  2211,
+    2217,  2223,  2229,  2235,  2241,  2247,  2253,  2259,  2265,  2271,
+    2277,  2283,  2289,  2295,  2301,  2307,  2313,  2319,  2325,  2331,
+    2337,  2343,  2349,  2355,  2361,  2367,  2373,  2379,  2385,  2391,
+    2397,  2403,  2407,  2411,  2415,  2420,  2426,  2431,  2436,  2441,
+    2446,  2451,  2456,  2462,  2467,  2472,  2477,  2482,  2487,  2493,
+    2499,  2505,  2511,  2517,  2523,  2529,  2535,  2541,  2547,  2553,
+    2559,  2565,  2571,  2576,  2581,  2586,  2591,  2596,  2601,  2607,
+    2612,  2617,  2622,  2627,  2632,  2637,  2642,  2648,  2653,  2658,
+    2663,  2668,  2673,  2678,  2683,  2688,  2693,  2698,  2703,  2708,
+    2713,  2718,  2724,  2729,  2734,  2740,  2746,  2751,  2756,  2761,
+    2767,  2772,  2777,  2782,  2788,  2793,  2798,  2803,  2809,  2814,
+    2819,  2824,  2830,  2836,  2842,  2848,  2853,  2859,  2865,  2871,
+    2876,  2881,  2886,  2891,  2896,  2902,  2907,  2912,  2917,  2923,
+    2928,  2933,  2938,  2944,  2949,  2954,  2959,  2965,  2970,  2975,
+    2980,  2986,  2991,  2996,  3001,  3007,  3012,  3017,  3022,  3028,
+    3033,  3038,  3043,  3049,  3054,  3059,  3064,  3070,  3075,  3080,
+    3085,  3091,  3096,  3101,  3106,  3112,  3117,  3122,  3127,  3133,
+    3138,  3143,  3148,  3154,  3159,  3164,  3169,  3175,  3180,  3185,
+    3190,  3196,  3201,  3206,  3212,  3218,  3224,  3230,  3237,  3244,
+    3250,  3256,  3262,  3268,  3274,  3280,  3287,  3292,  3308,  3313,
+    3318,  3326,  3326,  3337,  3337,  3347,  3350,  3363,  3385,  3412,
+    3416,  3422,  3427,  3438,  3442,  3448,  3459,  3462,  3469,  3473,
+    3474,  3480,  3481,  3482,  3483,  3484,  3485,  3486,  3488,  3494,
+    3503,  3504,  3508,  3504,  3520,  3521,  3525,  3525,  3532,  3532,
+    3546,  3549,  3557,  3565,  3576,  3577,  3581,  3585,  3592,  3599,
+    3603,  3611,  3615,  3628,  3632,  3639,  3639,  3659,  3662,  3668,
+    3680,  3692,  3696,  3703,  3703,  3718,  3718,  3734,  3734,  3755,
+    3758,  3764,  3767,  3773,  3777,  3784,  3789,  3794,  3801,  3804,
+    3813,  3817,  3826,  3829,  3833,  3842,  3842,  3865,  3871,  3874,
+    3879,  3882
 };
 #endif
 
@@ -1040,16 +1050,17 @@
   "F32MAT3X2", "F32MAT3X3", "F32MAT3X4", "F32MAT4X2", "F32MAT4X3",
   "F32MAT4X4", "F64MAT2X2", "F64MAT2X3", "F64MAT2X4", "F64MAT3X2",
   "F64MAT3X3", "F64MAT3X4", "F64MAT4X2", "F64MAT4X3", "F64MAT4X4",
-  "ATOMIC_UINT", "ACCSTRUCTNV", "FCOOPMATNV", "ICOOPMATNV", "UCOOPMATNV",
-  "SAMPLERCUBEARRAY", "SAMPLERCUBEARRAYSHADOW", "ISAMPLERCUBEARRAY",
-  "USAMPLERCUBEARRAY", "SAMPLER1D", "SAMPLER1DARRAY",
-  "SAMPLER1DARRAYSHADOW", "ISAMPLER1D", "SAMPLER1DSHADOW", "SAMPLER2DRECT",
-  "SAMPLER2DRECTSHADOW", "ISAMPLER2DRECT", "USAMPLER2DRECT",
-  "SAMPLERBUFFER", "ISAMPLERBUFFER", "USAMPLERBUFFER", "SAMPLER2DMS",
-  "ISAMPLER2DMS", "USAMPLER2DMS", "SAMPLER2DMSARRAY", "ISAMPLER2DMSARRAY",
-  "USAMPLER2DMSARRAY", "SAMPLEREXTERNALOES", "SAMPLEREXTERNAL2DY2YEXT",
-  "ISAMPLER1DARRAY", "USAMPLER1D", "USAMPLER1DARRAY", "F16SAMPLER1D",
-  "F16SAMPLER2D", "F16SAMPLER3D", "F16SAMPLER2DRECT", "F16SAMPLERCUBE",
+  "ATOMIC_UINT", "ACCSTRUCTNV", "ACCSTRUCTEXT", "RAYQUERYEXT",
+  "FCOOPMATNV", "ICOOPMATNV", "UCOOPMATNV", "SAMPLERCUBEARRAY",
+  "SAMPLERCUBEARRAYSHADOW", "ISAMPLERCUBEARRAY", "USAMPLERCUBEARRAY",
+  "SAMPLER1D", "SAMPLER1DARRAY", "SAMPLER1DARRAYSHADOW", "ISAMPLER1D",
+  "SAMPLER1DSHADOW", "SAMPLER2DRECT", "SAMPLER2DRECTSHADOW",
+  "ISAMPLER2DRECT", "USAMPLER2DRECT", "SAMPLERBUFFER", "ISAMPLERBUFFER",
+  "USAMPLERBUFFER", "SAMPLER2DMS", "ISAMPLER2DMS", "USAMPLER2DMS",
+  "SAMPLER2DMSARRAY", "ISAMPLER2DMSARRAY", "USAMPLER2DMSARRAY",
+  "SAMPLEREXTERNALOES", "SAMPLEREXTERNAL2DY2YEXT", "ISAMPLER1DARRAY",
+  "USAMPLER1D", "USAMPLER1DARRAY", "F16SAMPLER1D", "F16SAMPLER2D",
+  "F16SAMPLER3D", "F16SAMPLER2DRECT", "F16SAMPLERCUBE",
   "F16SAMPLER1DARRAY", "F16SAMPLER2DARRAY", "F16SAMPLERCUBEARRAY",
   "F16SAMPLERBUFFER", "F16SAMPLER2DMS", "F16SAMPLER2DMSARRAY",
   "F16SAMPLER1DSHADOW", "F16SAMPLER2DSHADOW", "F16SAMPLER1DARRAYSHADOW",
@@ -1093,14 +1104,16 @@
   "BUFFER", "FLAT", "SMOOTH", "LAYOUT", "DOUBLECONSTANT", "INT16CONSTANT",
   "UINT16CONSTANT", "FLOAT16CONSTANT", "INT32CONSTANT", "UINT32CONSTANT",
   "INT64CONSTANT", "UINT64CONSTANT", "SUBROUTINE", "DEMOTE", "PAYLOADNV",
-  "PAYLOADINNV", "HITATTRNV", "CALLDATANV", "CALLDATAINNV", "PATCH",
+  "PAYLOADINNV", "HITATTRNV", "CALLDATANV", "CALLDATAINNV", "PAYLOADEXT",
+  "PAYLOADINEXT", "HITATTREXT", "CALLDATAEXT", "CALLDATAINEXT", "PATCH",
   "SAMPLE", "NONUNIFORM", "COHERENT", "VOLATILE", "RESTRICT", "READONLY",
   "WRITEONLY", "DEVICECOHERENT", "QUEUEFAMILYCOHERENT",
-  "WORKGROUPCOHERENT", "SUBGROUPCOHERENT", "NONPRIVATE", "NOPERSPECTIVE",
-  "EXPLICITINTERPAMD", "PERVERTEXNV", "PERPRIMITIVENV", "PERVIEWNV",
-  "PERTASKNV", "PRECISE", "$accept", "variable_identifier",
-  "primary_expression", "postfix_expression", "integer_expression",
-  "function_call", "function_call_or_method", "function_call_generic",
+  "WORKGROUPCOHERENT", "SUBGROUPCOHERENT", "NONPRIVATE",
+  "SHADERCALLCOHERENT", "NOPERSPECTIVE", "EXPLICITINTERPAMD",
+  "PERVERTEXNV", "PERPRIMITIVENV", "PERVIEWNV", "PERTASKNV", "PRECISE",
+  "$accept", "variable_identifier", "primary_expression",
+  "postfix_expression", "integer_expression", "function_call",
+  "function_call_or_method", "function_call_generic",
   "function_call_header_no_parameters",
   "function_call_header_with_parameters", "function_call_header",
   "function_identifier", "unary_expression", "unary_operator",
@@ -1186,16 +1199,16 @@
      635,   636,   637,   638,   639,   640,   641,   642,   643,   644,
      645,   646,   647,   648,   649,   650,   651,   652,   653,   654,
      655,   656,   657,   658,   659,   660,   661,   662,   663,   664,
-     665,   666
+     665,   666,   667,   668,   669,   670,   671,   672,   673,   674
 };
 # endif
 
-#define YYPACT_NINF -454
+#define YYPACT_NINF -457
 
 #define yypact_value_is_default(Yystate) \
-  (!!((Yystate) == (-454)))
+  (!!((Yystate) == (-457)))
 
-#define YYTABLE_NINF -529
+#define YYTABLE_NINF -537
 
 #define yytable_value_is_error(Yytable_value) \
   0
@@ -1204,79 +1217,80 @@
      STATE-NUM.  */
 static const yytype_int16 yypact[] =
 {
-    4003,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,
-    -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,
-    -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,
-    -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,
-    -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,
-    -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,
-    -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,
-    -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,
-    -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,
-    -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,
-    -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,
-    -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,
-    -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,
-    -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,
-    -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,
-    -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,
-    -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,
-    -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,
-    -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,
-    -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,
-    -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,
-    -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,
-    -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,
-    -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,
-    -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,
-    -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,
-    -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,
-    -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,
-    -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,
-    -454,  -454,  -454,  -454,  -454,  -454,   127,  -454,  -454,  -454,
-    -454,  -454,    -7,  -454,  -454,  -454,  -454,  -454,  -454,  -305,
-    -244,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,
-    -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,
-    -454,  -454,  -454,  -454,  -454,  -454,  -454,     5,    52,    11,
-      50,  6048,    51,  -454,   -17,  -454,  -454,  -454,  -454,  4412,
-    -454,  -454,  -454,  -454,    77,  -454,  -454,   731,  -454,  -454,
-      10,  -454,   105,   -35,   111,  -454,  -312,  -454,   122,  -454,
-    6048,  -454,  -454,  -454,  6048,   113,   115,  -454,     7,  -454,
-      66,  -454,  -454,  8411,   158,  -454,  -454,  -454,   118,  6048,
-    -454,   162,  -454,  -310,  -454,  -454,    47,  6847,  -454,    21,
-    1140,  -454,  -454,  -454,  -454,   158,  -316,  -454,  7238,    12,
-    -454,   136,  -454,    59,  8411,  8411,  -454,  8411,  -454,  -454,
-    -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,
-    -454,  -454,  -454,  -454,  -454,  -454,  -454,    30,  -454,  -454,
-    -454,   173,    70,  8802,   175,  -454,  8411,  -454,  -454,     1,
-     174,  -454,  6048,   141,  4821,  -454,  6048,  8411,  -454,   -35,
-    -454,   142,  -454,  -454,   140,    93,    71,    20,    95,   157,
-     159,   161,   197,   196,    17,   182,  7629,  -454,   184,   185,
-    -454,  -454,   187,   181,   183,  -454,   194,   195,   186,  8020,
-     198,  8411,   192,   193,   121,  -454,  -454,    90,  -454,    52,
-     202,   204,  -454,  -454,  -454,  -454,  -454,  1549,  -454,  -454,
-    -454,  -454,  -454,  -454,  -454,  -454,  -454,    37,   174,  7238,
-      15,  7238,  -454,  -454,  7238,  6048,  -454,   169,  -454,  -454,
-    -454,    81,  -454,  -454,  8411,   170,  -454,  -454,  8411,   206,
-    -454,  -454,  -454,  8411,  -454,   141,   158,   124,  -454,  -454,
-    -454,  5230,  -454,  -454,  -454,  -454,  8411,  8411,  8411,  8411,
-    8411,  8411,  8411,  8411,  8411,  8411,  8411,  8411,  8411,  8411,
-    8411,  8411,  8411,  8411,  8411,  -454,  -454,  -454,   205,   176,
-    -454,  1958,  -454,  -454,  -454,  1958,  -454,  8411,  -454,  -454,
-     125,  8411,   137,  -454,  -454,  -454,  -454,  -454,  -454,  -454,
-    -454,  -454,  -454,  -454,  -454,  -454,  8411,  8411,  -454,  -454,
-    -454,  -454,  -454,  -454,  -454,  7238,  -454,   133,  -454,  5639,
-    -454,  -454,   210,   207,  -454,  -454,  -454,   126,   174,   141,
-    -454,  -454,  -454,  -454,  -454,   140,   140,    93,    93,    71,
-      71,    71,    71,    20,    20,    95,   157,   159,   161,   197,
-     196,  8411,  -454,   209,  -311,  -454,  1958,  3594,   171,  3185,
-      91,  -454,    92,  -454,  -454,  -454,  -454,  -454,  6456,  -454,
-    -454,  -454,  -454,   151,  8411,   213,   176,   212,   207,   188,
-    6048,   217,   220,  -454,  -454,  3594,   218,  -454,  -454,  -454,
-    8411,   222,  -454,  -454,  -454,   219,  2367,  8411,  -454,   211,
-     225,   179,   226,  2776,  -454,   228,  -454,  -454,  7238,  -454,
-    -454,  -454,   120,  8411,  2367,   218,  -454,  -454,  1958,  -454,
-     223,   207,  -454,  -454,  1958,   224,  -454,  -454
+    4075,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,
+    -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,
+    -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,
+    -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,
+    -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,
+    -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,
+    -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,
+    -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,
+    -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,
+    -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,
+    -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,
+    -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,
+    -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,
+    -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,
+    -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,
+    -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,
+    -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,
+    -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,
+    -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,
+    -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,
+    -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,
+    -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,
+    -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,
+    -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,
+    -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,
+    -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,
+    -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,
+    -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,
+    -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,
+    -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,   132,  -457,
+    -457,  -457,  -457,  -457,    -1,  -457,  -457,  -457,  -457,  -457,
+    -457,  -301,  -298,  -457,  -457,  -457,  -457,  -457,  -457,  -457,
+    -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,
+    -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,
+    -457,  -457,  -457,  -457,  -457,    11,  -249,    17,    30,  6160,
+      20,  -457,    28,  -457,  -457,  -457,  -457,  4492,  -457,  -457,
+    -457,  -457,    50,  -457,  -457,   739,  -457,  -457,    16,  -457,
+      81,   -29,    69,  -457,  -313,  -457,   111,  -457,  6160,  -457,
+    -457,  -457,  6160,   103,   106,  -457,  -314,  -457,    72,  -457,
+    -457,  8566,   142,  -457,  -457,  -457,   136,  6160,  -457,   144,
+    -457,    53,  -457,  -457,    76,  6974,  -457,  -312,  1156,  -457,
+    -457,  -457,  -457,   142,  -309,  -457,  7372,  -308,  -457,   119,
+    -457,    65,  8566,  8566,  -457,  8566,  -457,  -457,  -457,  -457,
+    -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,
+    -457,  -457,  -457,  -457,  -457,    36,  -457,  -457,  -457,   171,
+      85,  8964,   173,  -457,  8566,  -457,  -457,  -323,   174,  -457,
+    6160,   139,  4909,  -457,  6160,  8566,  -457,   -29,  -457,   141,
+    -457,  -457,   145,    99,    35,    26,    71,   156,   159,   161,
+     196,   195,    23,   181,  7770,  -457,   183,   182,  -457,  -457,
+     186,   179,   180,  -457,   191,   192,   187,  8168,   193,  8566,
+     188,   189,   127,  -457,  -457,    96,  -457,  -249,   200,   201,
+    -457,  -457,  -457,  -457,  -457,  1573,  -457,  -457,  -457,  -457,
+    -457,  -457,  -457,  -457,  -457,   -24,   174,  7372,    13,  7372,
+    -457,  -457,  7372,  6160,  -457,   166,  -457,  -457,  -457,    86,
+    -457,  -457,  8566,   168,  -457,  -457,  8566,   205,  -457,  -457,
+    -457,  8566,  -457,   139,   142,   124,  -457,  -457,  -457,  5326,
+    -457,  -457,  -457,  -457,  8566,  8566,  8566,  8566,  8566,  8566,
+    8566,  8566,  8566,  8566,  8566,  8566,  8566,  8566,  8566,  8566,
+    8566,  8566,  8566,  -457,  -457,  -457,   206,   172,  -457,  1990,
+    -457,  -457,  -457,  1990,  -457,  8566,  -457,  -457,   130,  8566,
+     125,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,
+    -457,  -457,  -457,  -457,  8566,  8566,  -457,  -457,  -457,  -457,
+    -457,  -457,  -457,  7372,  -457,    94,  -457,  5743,  -457,  -457,
+     207,   204,  -457,  -457,  -457,   131,   174,   139,  -457,  -457,
+    -457,  -457,  -457,   145,   145,    99,    99,    35,    35,    35,
+      35,    26,    26,    71,   156,   159,   161,   196,   195,  8566,
+    -457,   212,    60,  -457,  1990,  3658,   169,  3241,    87,  -457,
+      89,  -457,  -457,  -457,  -457,  -457,  6576,  -457,  -457,  -457,
+    -457,   143,  8566,   211,   172,   210,   204,   184,  6160,   217,
+     219,  -457,  -457,  3658,   218,  -457,  -457,  -457,  8566,   220,
+    -457,  -457,  -457,   214,  2407,  8566,  -457,   216,   223,   185,
+     224,  2824,  -457,   225,  -457,  -457,  7372,  -457,  -457,  -457,
+      97,  8566,  2407,   218,  -457,  -457,  1990,  -457,   222,   204,
+    -457,  -457,  1990,   229,  -457,  -457
 };
 
   /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
@@ -1284,113 +1298,114 @@
      means the default is an error.  */
 static const yytype_uint16 yydefact[] =
 {
-       0,   157,   204,   202,   203,   201,   208,   209,   210,   211,
-     212,   213,   214,   215,   216,   205,   206,   207,   217,   218,
-     219,   220,   221,   222,   223,   224,   225,   226,   227,   228,
-     328,   329,   330,   331,   332,   333,   334,   354,   355,   356,
-     357,   358,   359,   360,   369,   382,   383,   370,   371,   373,
-     372,   374,   375,   376,   377,   378,   379,   380,   381,   165,
-     166,   230,   231,   229,   232,   239,   240,   237,   238,   235,
-     236,   233,   234,   262,   263,   264,   274,   275,   276,   259,
-     260,   261,   271,   272,   273,   256,   257,   258,   268,   269,
-     270,   253,   254,   255,   265,   266,   267,   241,   242,   243,
-     277,   278,   279,   244,   245,   246,   289,   290,   291,   247,
-     248,   249,   301,   302,   303,   250,   251,   252,   313,   314,
-     315,   280,   281,   282,   283,   284,   285,   286,   287,   288,
-     292,   293,   294,   295,   296,   297,   298,   299,   300,   304,
-     305,   306,   307,   308,   309,   310,   311,   312,   316,   317,
-     318,   319,   320,   321,   322,   323,   324,   326,   325,   485,
-     486,   487,   338,   339,   362,   365,   327,   336,   337,   353,
-     335,   384,   385,   388,   389,   390,   392,   393,   394,   396,
-     397,   398,   400,   401,   475,   476,   361,   363,   364,   340,
-     341,   342,   386,   343,   347,   348,   351,   391,   395,   399,
-     344,   345,   349,   350,   387,   346,   352,   431,   433,   434,
-     435,   437,   438,   439,   441,   442,   443,   445,   446,   447,
-     449,   450,   451,   453,   454,   455,   457,   458,   459,   461,
-     462,   463,   465,   466,   467,   469,   470,   471,   473,   474,
-     432,   436,   440,   444,   448,   456,   460,   464,   452,   468,
-     472,   366,   367,   368,   402,   411,   413,   407,   412,   414,
-     415,   417,   418,   419,   421,   422,   423,   425,   426,   427,
-     429,   430,   403,   404,   405,   416,   406,   408,   409,   410,
-     420,   424,   428,   477,   478,   481,   482,   483,   484,   479,
-     480,   576,   132,   490,   491,   492,     0,   489,   161,   159,
-     160,   158,     0,   200,   162,   163,   164,   134,   133,     0,
-     184,   170,   171,   169,   172,   173,   167,   168,   186,   174,
-     180,   181,   182,   183,   175,   176,   177,   178,   179,   135,
-     136,   137,   138,   139,   140,   147,   575,     0,   577,     0,
-     109,   108,     0,   120,   125,   154,   153,   151,   155,     0,
-     148,   150,   156,   130,   196,   152,   488,     0,   572,   574,
-       0,   495,     0,     0,     0,    97,     0,    94,     0,   107,
-       0,   116,   110,   118,     0,   119,     0,    95,   126,   100,
-       0,   149,   131,     0,   189,   195,     1,   573,     0,     0,
-     493,   144,   146,     0,   142,   187,     0,     0,    98,     0,
-       0,   578,   111,   115,   117,   113,   121,   112,     0,   127,
-     103,     0,   101,     0,     0,     0,     9,     0,    43,    42,
-      44,    41,     5,     6,     7,     8,     2,    16,    14,    15,
-      17,    10,    11,    12,    13,     3,    18,    37,    20,    25,
-      26,     0,     0,    30,     0,   198,     0,    36,    34,     0,
-     190,    96,     0,     0,     0,   497,     0,     0,   141,     0,
-     185,     0,   191,    45,    49,    52,    55,    60,    63,    65,
-      67,    69,    71,    73,    75,     0,     0,    99,     0,   523,
-     532,   536,     0,     0,     0,   557,     0,     0,     0,     0,
-       0,     0,     0,     0,    45,    78,    91,     0,   510,     0,
-     156,   130,   513,   534,   512,   520,   511,     0,   514,   515,
-     538,   516,   545,   517,   518,   553,   519,     0,   114,     0,
-     122,     0,   505,   129,     0,     0,   105,     0,   102,    38,
-      39,     0,    22,    23,     0,     0,    28,    27,     0,   200,
-      31,    33,    40,     0,   197,     0,   503,     0,   501,   496,
-     498,     0,    93,   145,   143,   188,     0,     0,     0,     0,
+       0,   157,   210,   208,   209,   207,   214,   215,   216,   217,
+     218,   219,   220,   221,   222,   211,   212,   213,   223,   224,
+     225,   226,   227,   228,   229,   230,   231,   232,   233,   234,
+     336,   337,   338,   339,   340,   341,   342,   362,   363,   364,
+     365,   366,   367,   368,   377,   390,   391,   378,   379,   381,
+     380,   382,   383,   384,   385,   386,   387,   388,   389,   165,
+     166,   236,   237,   235,   238,   245,   246,   243,   244,   241,
+     242,   239,   240,   268,   269,   270,   280,   281,   282,   265,
+     266,   267,   277,   278,   279,   262,   263,   264,   274,   275,
+     276,   259,   260,   261,   271,   272,   273,   247,   248,   249,
+     283,   284,   285,   250,   251,   252,   295,   296,   297,   253,
+     254,   255,   307,   308,   309,   256,   257,   258,   319,   320,
+     321,   286,   287,   288,   289,   290,   291,   292,   293,   294,
+     298,   299,   300,   301,   302,   303,   304,   305,   306,   310,
+     311,   312,   313,   314,   315,   316,   317,   318,   322,   323,
+     324,   325,   326,   327,   328,   329,   330,   334,   331,   332,
+     333,   493,   494,   495,   346,   347,   370,   373,   335,   344,
+     345,   361,   343,   392,   393,   396,   397,   398,   400,   401,
+     402,   404,   405,   406,   408,   409,   483,   484,   369,   371,
+     372,   348,   349,   350,   394,   351,   355,   356,   359,   399,
+     403,   407,   352,   353,   357,   358,   395,   354,   360,   439,
+     441,   442,   443,   445,   446,   447,   449,   450,   451,   453,
+     454,   455,   457,   458,   459,   461,   462,   463,   465,   466,
+     467,   469,   470,   471,   473,   474,   475,   477,   478,   479,
+     481,   482,   440,   444,   448,   452,   456,   464,   468,   472,
+     460,   476,   480,   374,   375,   376,   410,   419,   421,   415,
+     420,   422,   423,   425,   426,   427,   429,   430,   431,   433,
+     434,   435,   437,   438,   411,   412,   413,   424,   414,   416,
+     417,   418,   428,   432,   436,   485,   486,   489,   490,   491,
+     492,   487,   488,   584,   132,   498,   499,   500,     0,   497,
+     161,   159,   160,   158,     0,   206,   162,   163,   164,   134,
+     133,     0,   190,   171,   173,   169,   175,   177,   172,   174,
+     170,   176,   178,   167,   168,   192,   179,   186,   187,   188,
+     189,   180,   181,   182,   183,   184,   185,   135,   136,   137,
+     138,   139,   140,   147,   583,     0,   585,     0,   109,   108,
+       0,   120,   125,   154,   153,   151,   155,     0,   148,   150,
+     156,   130,   202,   152,   496,     0,   580,   582,     0,   503,
+       0,     0,     0,    97,     0,    94,     0,   107,     0,   116,
+     110,   118,     0,   119,     0,    95,   126,   100,     0,   149,
+     131,     0,   195,   201,     1,   581,     0,     0,   501,   144,
+     146,     0,   142,   193,     0,     0,    98,     0,     0,   586,
+     111,   115,   117,   113,   121,   112,     0,   127,   103,     0,
+     101,     0,     0,     0,     9,     0,    43,    42,    44,    41,
+       5,     6,     7,     8,     2,    16,    14,    15,    17,    10,
+      11,    12,    13,     3,    18,    37,    20,    25,    26,     0,
+       0,    30,     0,   204,     0,    36,    34,     0,   196,    96,
+       0,     0,     0,   505,     0,     0,   141,     0,   191,     0,
+     197,    45,    49,    52,    55,    60,    63,    65,    67,    69,
+      71,    73,    75,     0,     0,    99,     0,   531,   540,   544,
+       0,     0,     0,   565,     0,     0,     0,     0,     0,     0,
+       0,     0,    45,    78,    91,     0,   518,     0,   156,   130,
+     521,   542,   520,   528,   519,     0,   522,   523,   546,   524,
+     553,   525,   526,   561,   527,     0,   114,     0,   122,     0,
+     513,   129,     0,     0,   105,     0,   102,    38,    39,     0,
+      22,    23,     0,     0,    28,    27,     0,   206,    31,    33,
+      40,     0,   203,     0,   511,     0,   509,   504,   506,     0,
+      93,   145,   143,   194,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,    76,   192,   193,     0,     0,
-     522,     0,   555,   568,   567,     0,   559,     0,   571,   569,
-       0,     0,     0,   552,   521,    81,    82,    84,    83,    86,
-      87,    88,    89,    90,    85,    80,     0,     0,   537,   533,
-     535,   539,   546,   554,   124,     0,   508,     0,   128,     0,
-     106,     4,     0,    24,    21,    32,   199,     0,   504,     0,
-     499,   494,    46,    47,    48,    51,    50,    53,    54,    58,
-      59,    56,    57,    61,    62,    64,    66,    68,    70,    72,
-      74,     0,   194,   582,     0,   580,   524,     0,     0,     0,
-       0,   570,     0,   551,    79,    92,   123,   506,     0,   104,
-      19,   500,   502,     0,     0,     0,     0,     0,   543,     0,
-       0,     0,     0,   562,   561,   564,   530,   547,   507,   509,
-       0,     0,   579,   581,   525,     0,     0,     0,   563,     0,
-       0,   542,     0,     0,   540,     0,    77,   583,     0,   527,
-     556,   526,     0,   565,     0,   530,   529,   531,   549,   544,
-       0,   566,   560,   541,   550,     0,   558,   548
+       0,     0,     0,    76,   198,   199,     0,     0,   530,     0,
+     563,   576,   575,     0,   567,     0,   579,   577,     0,     0,
+       0,   560,   529,    81,    82,    84,    83,    86,    87,    88,
+      89,    90,    85,    80,     0,     0,   545,   541,   543,   547,
+     554,   562,   124,     0,   516,     0,   128,     0,   106,     4,
+       0,    24,    21,    32,   205,     0,   512,     0,   507,   502,
+      46,    47,    48,    51,    50,    53,    54,    58,    59,    56,
+      57,    61,    62,    64,    66,    68,    70,    72,    74,     0,
+     200,   590,     0,   588,   532,     0,     0,     0,     0,   578,
+       0,   559,    79,    92,   123,   514,     0,   104,    19,   508,
+     510,     0,     0,     0,     0,     0,   551,     0,     0,     0,
+       0,   570,   569,   572,   538,   555,   515,   517,     0,     0,
+     587,   589,   533,     0,     0,     0,   571,     0,     0,   550,
+       0,     0,   548,     0,    77,   591,     0,   535,   564,   534,
+       0,   573,     0,   538,   537,   539,   557,   552,     0,   574,
+     568,   549,   558,     0,   566,   556
 };
 
   /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int16 yypgoto[] =
 {
-    -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,  -454,
-    -454,  -454,  8712,  -454,   -82,   -80,  -126,   -83,   -20,   -18,
-     -21,   -19,   -16,   -15,  -454,   -86,  -454,  -103,  -454,  -111,
-    -120,     2,  -454,  -454,  -454,     4,  -454,  -454,  -454,   189,
-     191,   190,  -454,  -454,  -337,  -454,  -454,  -454,  -454,    96,
-    -454,   -37,   -46,  -454,     9,  -454,     0,   -63,  -454,  -454,
-    -454,  -454,   260,  -454,  -454,  -454,  -453,  -140,    13,   -67,
-    -211,  -454,   -93,  -198,  -321,  -454,  -135,  -454,  -454,  -146,
-    -145,  -454,  -454,   201,  -274,   -88,  -454,    55,  -454,  -112,
-    -454,    58,  -454,  -454,  -454,  -454,    60,  -454,  -454,  -454,
-    -454,  -454,  -454,  -454,  -454,   221,  -454,  -454,  -454,  -454,
-    -100
+    -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,  -457,
+    -457,  -457,  8868,  -457,   -87,   -84,  -127,   -93,   -33,   -31,
+     -27,   -25,   -28,   -26,  -457,   -86,  -457,  -103,  -457,  -111,
+    -125,     2,  -457,  -457,  -457,     4,  -457,  -457,  -457,   176,
+     194,   178,  -457,  -457,  -337,  -457,  -457,  -457,  -457,    95,
+    -457,   -37,   -46,  -457,     9,  -457,     0,   -63,  -457,  -457,
+    -457,  -457,   263,  -457,  -457,  -457,  -456,  -140,    10,   -73,
+    -211,  -457,  -102,  -198,  -321,  -457,  -144,  -457,  -457,  -155,
+    -154,  -457,  -457,   198,  -274,   -97,  -457,    46,  -457,  -118,
+    -457,    51,  -457,  -457,  -457,  -457,    52,  -457,  -457,  -457,
+    -457,  -457,  -457,  -457,  -457,   213,  -457,  -457,  -457,  -457,
+    -105
 };
 
   /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int16 yydefgoto[] =
 {
-      -1,   435,   436,   437,   622,   438,   439,   440,   441,   442,
-     443,   444,   494,   446,   464,   465,   466,   467,   468,   469,
-     470,   471,   472,   473,   474,   495,   651,   496,   606,   497,
-     553,   498,   337,   525,   413,   499,   339,   340,   341,   371,
-     372,   373,   342,   343,   344,   345,   346,   347,   393,   394,
-     348,   349,   350,   351,   447,   396,   448,   399,   384,   385,
-     449,   354,   355,   356,   456,   389,   454,   455,   547,   548,
-     523,   617,   502,   503,   504,   505,   506,   581,   677,   710,
-     701,   702,   703,   711,   507,   508,   509,   510,   704,   681,
-     511,   512,   705,   725,   513,   514,   515,   657,   585,   659,
-     685,   699,   700,   516,   357,   358,   359,   368,   517,   654,
-     655
+      -1,   443,   444,   445,   630,   446,   447,   448,   449,   450,
+     451,   452,   502,   454,   472,   473,   474,   475,   476,   477,
+     478,   479,   480,   481,   482,   503,   659,   504,   614,   505,
+     561,   506,   345,   533,   421,   507,   347,   348,   349,   379,
+     380,   381,   350,   351,   352,   353,   354,   355,   401,   402,
+     356,   357,   358,   359,   455,   404,   456,   407,   392,   393,
+     457,   362,   363,   364,   464,   397,   462,   463,   555,   556,
+     531,   625,   510,   511,   512,   513,   514,   589,   685,   718,
+     709,   710,   711,   719,   515,   516,   517,   518,   712,   689,
+     519,   520,   713,   733,   521,   522,   523,   665,   593,   667,
+     693,   707,   708,   524,   365,   366,   367,   376,   525,   662,
+     663
 };
 
   /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM.  If
@@ -1398,162 +1413,81 @@
      number is the opposite.  If YYTABLE_NINF, syntax error.  */
 static const yytype_int16 yytable[] =
 {
-     353,   397,   336,   551,   338,   397,   458,   675,   519,   352,
-     363,   676,   459,   398,     2,     3,     4,     5,     6,     7,
-       8,     9,    10,    11,    12,    13,    14,    15,    16,    17,
-      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
-      28,    29,    30,    31,    32,    33,    34,    35,    36,    37,
-      38,    39,    40,    41,    42,    43,    44,    45,    46,    47,
-      48,    49,    50,    51,    52,    53,    54,    55,    56,    57,
-      58,   364,   619,    61,    62,    63,    64,    65,    66,    67,
-      68,    69,    70,    71,    72,    73,    74,    75,    76,    77,
-      78,    79,    80,    81,    82,    83,    84,    85,    86,    87,
-      88,    89,    90,    91,    92,    93,    94,    95,    96,    97,
-      98,    99,   100,   101,   102,   103,   104,   105,   106,   107,
-     108,   109,   110,   111,   112,   113,   114,   115,   116,   117,
-     118,   119,   120,   121,   122,   123,   124,   125,   126,   127,
-     128,   129,   130,   131,   132,   133,   134,   135,   136,   137,
-     138,   139,   140,   141,   142,   143,   144,   145,   146,   147,
-     148,   149,   150,   151,   152,   153,   154,   155,   156,   157,
-     158,   159,   160,   161,   162,   163,   164,   165,   166,   167,
-     168,   169,   170,   171,   172,   173,   174,   175,   176,   177,
-     178,   179,   180,   181,   182,   183,   184,   185,   186,   187,
-     188,   189,   190,   191,   192,   193,   194,   195,   196,   197,
-     198,   199,   200,   201,   202,   203,   204,   205,   206,   207,
-     208,   209,   210,   211,   212,   213,   214,   215,   216,   217,
-     218,   219,   220,   221,   222,   223,   224,   225,   226,   227,
-     228,   229,   230,   231,   232,   233,   234,   235,   236,   237,
-     238,   239,   240,   241,   242,   243,   244,   245,   246,   247,
-     248,   249,   250,   251,   252,   253,   254,   255,   256,   257,
-     258,   259,   260,   261,   262,   263,   264,   265,   266,   267,
-     268,   269,   270,   271,   272,   273,   274,   275,   276,   277,
-     278,   279,   280,   281,   282,   283,   284,   285,   286,   287,
-     288,   289,   290,   381,   374,   522,   531,   656,   614,   610,
-     616,   475,   361,   618,   550,   409,   391,   563,   564,   574,
-     679,   450,   407,   543,   397,   532,   533,   369,   381,   476,
-     365,   408,   476,   374,   378,   544,   524,   392,   476,   615,
-     540,   375,   518,   520,   362,   -35,   477,   534,   679,   382,
-     352,   535,   452,   565,   566,   575,   366,   353,   352,   336,
-     388,   338,   297,   460,   561,   562,   352,   302,   303,   461,
-     375,   552,   370,   376,   375,   709,   377,   367,   590,   352,
-     592,   527,   717,   352,   528,   410,   537,   658,   411,   453,
-     578,   412,   538,   709,   567,   568,   482,   621,   352,   485,
-     501,   486,   487,   607,   666,   490,   381,   686,   687,   500,
-     383,   550,   607,   607,   607,   608,   522,   452,   522,   452,
-     559,   522,   560,   623,   390,   595,   596,   597,   598,   599,
-     600,   601,   602,   603,   604,   625,   720,   639,   640,   641,
-     642,   400,   607,   451,   724,   605,   629,   607,   629,   630,
-     661,   671,   545,   667,   453,   668,   453,   689,   610,   607,
-     663,   352,   395,   352,   405,   352,   406,   293,   294,   295,
-     556,   557,   558,   607,   690,   397,   660,   635,   636,   550,
-     662,   637,   638,   628,   643,   644,   457,   526,   452,   536,
-     541,   476,   546,   555,   569,   570,   571,   719,   572,   573,
-     576,   579,   582,   664,   665,   580,   583,   501,   584,   586,
-     587,   588,   522,   591,   452,   593,   500,   -36,   594,   -34,
-     620,   624,   -29,   652,   674,   453,   610,   653,   670,   607,
-     682,   692,   694,   696,   352,   697,   713,  -528,   707,   695,
-     673,   714,   715,   708,   727,   479,   678,   718,   726,   645,
-     647,   453,   646,   648,   691,   554,   360,   649,   627,   650,
-     352,   402,   672,   403,   404,   522,   683,   716,   722,   401,
-     723,   684,   611,   698,   678,   612,   693,   613,   387,     0,
-       0,   501,   452,     0,     0,   501,   712,   706,   552,     0,
-     500,     0,     0,     0,   500,     0,     0,     0,     0,     0,
-       0,     0,   721,     0,     0,   522,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,   453,
-     680,     0,     0,     0,     0,     0,     0,     0,   352,     0,
-       0,     0,     0,     0,   381,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,   680,     0,
-       0,     0,     0,     0,     0,     0,   501,   501,     0,   501,
-       0,     0,     0,     0,     0,   500,   500,     0,   500,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-     382,     0,     0,     0,     0,   501,     0,     0,     0,   352,
-       0,     0,     0,     0,   500,     0,   501,     0,     0,     0,
-       0,     0,     0,   501,     0,   500,     0,     0,     0,     0,
-       0,     0,   500,     0,   501,     0,     0,     0,   501,     0,
-       0,     0,     0,   500,   501,     0,     0,   500,     0,     0,
-       0,   386,     0,   500,     1,     2,     3,     4,     5,     6,
-       7,     8,     9,    10,    11,    12,    13,    14,    15,    16,
-      17,    18,    19,    20,    21,    22,    23,    24,    25,    26,
-      27,    28,    29,    30,    31,    32,    33,    34,    35,    36,
-      37,    38,    39,    40,    41,    42,    43,    44,    45,    46,
-      47,    48,    49,    50,    51,    52,    53,    54,    55,    56,
-      57,    58,    59,    60,    61,    62,    63,    64,    65,    66,
-      67,    68,    69,    70,    71,    72,    73,    74,    75,    76,
-      77,    78,    79,    80,    81,    82,    83,    84,    85,    86,
-      87,    88,    89,    90,    91,    92,    93,    94,    95,    96,
-      97,    98,    99,   100,   101,   102,   103,   104,   105,   106,
-     107,   108,   109,   110,   111,   112,   113,   114,   115,   116,
-     117,   118,   119,   120,   121,   122,   123,   124,   125,   126,
-     127,   128,   129,   130,   131,   132,   133,   134,   135,   136,
-     137,   138,   139,   140,   141,   142,   143,   144,   145,   146,
-     147,   148,   149,   150,   151,   152,   153,   154,   155,   156,
-     157,   158,   159,   160,   161,   162,   163,   164,   165,   166,
-     167,   168,   169,   170,   171,   172,   173,   174,   175,   176,
-     177,   178,   179,   180,   181,   182,   183,   184,   185,   186,
-     187,   188,   189,   190,   191,   192,   193,   194,   195,   196,
-     197,   198,   199,   200,   201,   202,   203,   204,   205,   206,
-     207,   208,   209,   210,   211,   212,   213,   214,   215,   216,
-     217,   218,   219,   220,   221,   222,   223,   224,   225,   226,
-     227,   228,   229,   230,   231,   232,   233,   234,   235,   236,
-     237,   238,   239,   240,   241,   242,   243,   244,   245,   246,
-     247,   248,   249,   250,   251,   252,   253,   254,   255,   256,
-     257,   258,   259,   260,   261,   262,   263,   264,   265,   266,
-     267,   268,   269,   270,   271,   272,   273,   274,   275,   276,
-     277,   278,   279,   280,   281,   282,   283,   284,   285,   286,
-     287,   288,   289,   290,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,   291,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-     292,   293,   294,   295,   296,     0,     0,     0,     0,     0,
-       0,     0,     0,   297,   298,   299,   300,   301,   302,   303,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,   304,   305,   306,   307,   308,   309,     0,     0,
-       0,     0,     0,     0,     0,     0,   310,     0,   311,   312,
-     313,   314,   315,   316,   317,   318,   319,   320,   321,   322,
-     323,   324,   325,   326,   327,   328,   329,   330,   331,   332,
-     333,   334,   335,     1,     2,     3,     4,     5,     6,     7,
-       8,     9,    10,    11,    12,    13,    14,    15,    16,    17,
-      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
-      28,    29,    30,    31,    32,    33,    34,    35,    36,    37,
-      38,    39,    40,    41,    42,    43,    44,    45,    46,    47,
-      48,    49,    50,    51,    52,    53,    54,    55,    56,    57,
-      58,    59,    60,    61,    62,    63,    64,    65,    66,    67,
-      68,    69,    70,    71,    72,    73,    74,    75,    76,    77,
-      78,    79,    80,    81,    82,    83,    84,    85,    86,    87,
-      88,    89,    90,    91,    92,    93,    94,    95,    96,    97,
-      98,    99,   100,   101,   102,   103,   104,   105,   106,   107,
-     108,   109,   110,   111,   112,   113,   114,   115,   116,   117,
-     118,   119,   120,   121,   122,   123,   124,   125,   126,   127,
-     128,   129,   130,   131,   132,   133,   134,   135,   136,   137,
-     138,   139,   140,   141,   142,   143,   144,   145,   146,   147,
-     148,   149,   150,   151,   152,   153,   154,   155,   156,   157,
-     158,   159,   160,   161,   162,   163,   164,   165,   166,   167,
-     168,   169,   170,   171,   172,   173,   174,   175,   176,   177,
-     178,   179,   180,   181,   182,   183,   184,   185,   186,   187,
-     188,   189,   190,   191,   192,   193,   194,   195,   196,   197,
-     198,   199,   200,   201,   202,   203,   204,   205,   206,   207,
-     208,   209,   210,   211,   212,   213,   214,   215,   216,   217,
-     218,   219,   220,   221,   222,   223,   224,   225,   226,   227,
-     228,   229,   230,   231,   232,   233,   234,   235,   236,   237,
-     238,   239,   240,   241,   242,   243,   244,   245,   246,   247,
-     248,   249,   250,   251,   252,   253,   254,   255,   256,   257,
-     258,   259,   260,   261,   262,   263,   264,   265,   266,   267,
-     268,   269,   270,   271,   272,   273,   274,   275,   276,   277,
-     278,   279,   280,   281,   282,   283,   284,   285,   286,   287,
-     288,   289,   290,     0,     0,   414,   415,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,   416,   417,     0,   478,     0,   479,
-     480,     0,     0,     0,     0,   481,   418,   419,   420,   421,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,   292,
-     293,   294,   295,   296,     0,     0,     0,   422,   423,   424,
-     425,   426,   297,   298,   299,   300,   301,   302,   303,   482,
-     483,   484,   485,     0,   486,   487,   488,   489,   490,   491,
-     492,   304,   305,   306,   307,   308,   309,   427,   428,   429,
-     430,   431,   432,   433,   434,   310,   493,   311,   312,   313,
-     314,   315,   316,   317,   318,   319,   320,   321,   322,   323,
-     324,   325,   326,   327,   328,   329,   330,   331,   332,   333,
-     334,   335,     1,     2,     3,     4,     5,     6,     7,     8,
+     361,   551,   344,   415,   346,   405,   405,   484,   559,   360,
+     405,   484,   416,   552,   406,   485,   371,   527,   532,   372,
+       2,     3,     4,     5,     6,     7,     8,     9,    10,    11,
+      12,    13,    14,    15,    16,    17,    18,    19,    20,    21,
+      22,    23,    24,    25,    26,    27,    28,    29,    30,    31,
+      32,    33,    34,    35,    36,    37,    38,    39,    40,    41,
+      42,    43,    44,    45,    46,    47,    48,    49,    50,    51,
+      52,    53,    54,    55,    56,    57,    58,   627,   375,    61,
+      62,    63,    64,    65,    66,    67,    68,    69,    70,    71,
+      72,    73,    74,    75,    76,    77,    78,    79,    80,    81,
+      82,    83,    84,    85,    86,    87,    88,    89,    90,    91,
+      92,    93,    94,    95,    96,    97,    98,    99,   100,   101,
+     102,   103,   104,   105,   106,   107,   108,   109,   110,   111,
+     112,   113,   114,   115,   116,   117,   118,   119,   120,   121,
+     122,   123,   124,   125,   126,   127,   128,   129,   130,   131,
+     132,   133,   134,   135,   136,   137,   138,   139,   140,   141,
+     142,   143,   144,   145,   146,   147,   148,   149,   150,   151,
+     152,   153,   154,   155,   156,   157,   158,   159,   160,   161,
+     162,   163,   164,   165,   166,   167,   168,   169,   170,   171,
+     172,   173,   174,   175,   176,   177,   178,   179,   180,   181,
+     182,   183,   184,   185,   186,   187,   188,   189,   190,   191,
+     192,   193,   194,   195,   196,   197,   198,   199,   200,   201,
+     202,   203,   204,   205,   206,   207,   208,   209,   210,   211,
+     212,   213,   214,   215,   216,   217,   218,   219,   220,   221,
+     222,   223,   224,   225,   226,   227,   228,   229,   230,   231,
+     232,   233,   234,   235,   236,   237,   238,   239,   240,   241,
+     242,   243,   244,   245,   246,   247,   248,   249,   250,   251,
+     252,   253,   254,   255,   256,   257,   258,   259,   260,   261,
+     262,   263,   264,   265,   266,   267,   268,   269,   270,   271,
+     272,   273,   274,   275,   276,   277,   278,   279,   280,   281,
+     282,   283,   284,   285,   286,   287,   288,   289,   290,   291,
+     292,   389,   382,   530,   539,   664,   622,   618,   624,   483,
+     369,   626,   558,   417,   399,   571,   572,   582,   687,   458,
+     569,   570,   484,   540,   541,   377,   389,   490,   373,   623,
+     493,   382,   494,   495,   384,   400,   498,   385,   548,   383,
+     526,   528,   370,   -35,   378,   542,   687,   390,   360,   543,
+     460,   573,   574,   583,   374,   361,   360,   344,   396,   346,
+     299,   466,   575,   576,   360,   304,   305,   467,   383,   560,
+     683,   386,   383,   717,   684,   391,   598,   360,   600,   535,
+     725,   360,   536,   418,   468,   666,   419,   461,   586,   420,
+     469,   717,   398,   545,   629,   694,   360,   695,   509,   546,
+     615,   615,   674,   615,   389,   728,   675,   508,   676,   558,
+     615,   615,   403,   616,   530,   460,   530,   460,   567,   530,
+     568,   631,   408,   603,   604,   605,   606,   607,   608,   609,
+     610,   611,   612,   633,   647,   648,   649,   650,   637,   615,
+     671,   638,   732,   613,   615,   637,   413,   669,   679,   414,
+     553,   405,   461,   459,   461,   697,   618,   615,   698,   360,
+     465,   360,   534,   360,   295,   296,   297,   564,   565,   566,
+     643,   644,   651,   652,   668,   645,   646,   558,   670,   544,
+     549,   636,   554,   484,   563,   577,   460,   578,   579,   580,
+     581,   584,   587,   590,   588,   727,   591,   592,   594,   595,
+     599,   672,   673,   601,   596,   509,   602,   -36,   -34,   628,
+     530,   632,   460,   -29,   508,   661,   660,   678,   615,   682,
+     690,   700,   702,   461,   618,   704,   705,   703,   715,  -536,
+     716,   722,   360,   721,   653,   487,   726,   654,   681,   734,
+     723,   735,   655,   657,   686,   656,   658,   699,   411,   461,
+     412,   368,   562,   635,   680,   691,   724,   730,   360,   731,
+     692,   619,   410,   530,   409,   706,   620,   621,   395,   701,
+       0,     0,   686,     0,     0,     0,     0,     0,     0,   509,
+     460,     0,     0,   509,   720,   714,   560,     0,   508,     0,
+       0,     0,   508,     0,     0,     0,     0,     0,     0,     0,
+     729,     0,     0,   530,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,   461,   688,     0,
+       0,     0,     0,     0,     0,     0,   360,     0,     0,     0,
+       0,     0,   389,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,   688,     0,     0,     0,
+       0,     0,     0,     0,   509,   509,     0,   509,     0,     0,
+       0,     0,     0,   508,   508,     0,   508,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,   390,     0,
+       0,     0,     0,   509,     0,     0,     0,   360,     0,     0,
+       0,     0,   508,     0,   509,     0,     0,     0,     0,     0,
+       0,   509,     0,   508,     0,     0,     0,     0,     0,     0,
+     508,     0,   509,     0,     0,     0,   509,     0,     0,     0,
+       0,   508,   509,     0,     0,   508,     0,     0,     0,   394,
+       0,   508,     1,     2,     3,     4,     5,     6,     7,     8,
        9,    10,    11,    12,    13,    14,    15,    16,    17,    18,
       19,    20,    21,    22,    23,    24,    25,    26,    27,    28,
       29,    30,    31,    32,    33,    34,    35,    36,    37,    38,
@@ -1582,59 +1516,144 @@
      259,   260,   261,   262,   263,   264,   265,   266,   267,   268,
      269,   270,   271,   272,   273,   274,   275,   276,   277,   278,
      279,   280,   281,   282,   283,   284,   285,   286,   287,   288,
-     289,   290,     0,     0,   414,   415,     0,     0,     0,     0,
+     289,   290,   291,   292,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,   416,   417,     0,   478,     0,   479,   609,
-       0,     0,     0,     0,   481,   418,   419,   420,   421,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,   292,   293,
-     294,   295,   296,     0,     0,     0,   422,   423,   424,   425,
-     426,   297,   298,   299,   300,   301,   302,   303,   482,   483,
-     484,   485,     0,   486,   487,   488,   489,   490,   491,   492,
-     304,   305,   306,   307,   308,   309,   427,   428,   429,   430,
-     431,   432,   433,   434,   310,   493,   311,   312,   313,   314,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,   293,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+     294,   295,   296,   297,   298,     0,     0,     0,     0,     0,
+       0,     0,     0,   299,   300,   301,   302,   303,   304,   305,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,   306,   307,   308,   309,   310,   311,     0,     0,
+       0,     0,     0,     0,     0,     0,   312,     0,   313,   314,
      315,   316,   317,   318,   319,   320,   321,   322,   323,   324,
      325,   326,   327,   328,   329,   330,   331,   332,   333,   334,
-     335,     1,     2,     3,     4,     5,     6,     7,     8,     9,
-      10,    11,    12,    13,    14,    15,    16,    17,    18,    19,
-      20,    21,    22,    23,    24,    25,    26,    27,    28,    29,
-      30,    31,    32,    33,    34,    35,    36,    37,    38,    39,
-      40,    41,    42,    43,    44,    45,    46,    47,    48,    49,
-      50,    51,    52,    53,    54,    55,    56,    57,    58,    59,
-      60,    61,    62,    63,    64,    65,    66,    67,    68,    69,
-      70,    71,    72,    73,    74,    75,    76,    77,    78,    79,
-      80,    81,    82,    83,    84,    85,    86,    87,    88,    89,
-      90,    91,    92,    93,    94,    95,    96,    97,    98,    99,
-     100,   101,   102,   103,   104,   105,   106,   107,   108,   109,
-     110,   111,   112,   113,   114,   115,   116,   117,   118,   119,
-     120,   121,   122,   123,   124,   125,   126,   127,   128,   129,
-     130,   131,   132,   133,   134,   135,   136,   137,   138,   139,
-     140,   141,   142,   143,   144,   145,   146,   147,   148,   149,
-     150,   151,   152,   153,   154,   155,   156,   157,   158,   159,
-     160,   161,   162,   163,   164,   165,   166,   167,   168,   169,
-     170,   171,   172,   173,   174,   175,   176,   177,   178,   179,
-     180,   181,   182,   183,   184,   185,   186,   187,   188,   189,
-     190,   191,   192,   193,   194,   195,   196,   197,   198,   199,
-     200,   201,   202,   203,   204,   205,   206,   207,   208,   209,
-     210,   211,   212,   213,   214,   215,   216,   217,   218,   219,
-     220,   221,   222,   223,   224,   225,   226,   227,   228,   229,
-     230,   231,   232,   233,   234,   235,   236,   237,   238,   239,
-     240,   241,   242,   243,   244,   245,   246,   247,   248,   249,
-     250,   251,   252,   253,   254,   255,   256,   257,   258,   259,
-     260,   261,   262,   263,   264,   265,   266,   267,   268,   269,
-     270,   271,   272,   273,   274,   275,   276,   277,   278,   279,
-     280,   281,   282,   283,   284,   285,   286,   287,   288,   289,
-     290,     0,     0,   414,   415,     0,     0,     0,     0,     0,
+     335,   336,   337,   338,   339,   340,   341,   342,   343,     1,
+       2,     3,     4,     5,     6,     7,     8,     9,    10,    11,
+      12,    13,    14,    15,    16,    17,    18,    19,    20,    21,
+      22,    23,    24,    25,    26,    27,    28,    29,    30,    31,
+      32,    33,    34,    35,    36,    37,    38,    39,    40,    41,
+      42,    43,    44,    45,    46,    47,    48,    49,    50,    51,
+      52,    53,    54,    55,    56,    57,    58,    59,    60,    61,
+      62,    63,    64,    65,    66,    67,    68,    69,    70,    71,
+      72,    73,    74,    75,    76,    77,    78,    79,    80,    81,
+      82,    83,    84,    85,    86,    87,    88,    89,    90,    91,
+      92,    93,    94,    95,    96,    97,    98,    99,   100,   101,
+     102,   103,   104,   105,   106,   107,   108,   109,   110,   111,
+     112,   113,   114,   115,   116,   117,   118,   119,   120,   121,
+     122,   123,   124,   125,   126,   127,   128,   129,   130,   131,
+     132,   133,   134,   135,   136,   137,   138,   139,   140,   141,
+     142,   143,   144,   145,   146,   147,   148,   149,   150,   151,
+     152,   153,   154,   155,   156,   157,   158,   159,   160,   161,
+     162,   163,   164,   165,   166,   167,   168,   169,   170,   171,
+     172,   173,   174,   175,   176,   177,   178,   179,   180,   181,
+     182,   183,   184,   185,   186,   187,   188,   189,   190,   191,
+     192,   193,   194,   195,   196,   197,   198,   199,   200,   201,
+     202,   203,   204,   205,   206,   207,   208,   209,   210,   211,
+     212,   213,   214,   215,   216,   217,   218,   219,   220,   221,
+     222,   223,   224,   225,   226,   227,   228,   229,   230,   231,
+     232,   233,   234,   235,   236,   237,   238,   239,   240,   241,
+     242,   243,   244,   245,   246,   247,   248,   249,   250,   251,
+     252,   253,   254,   255,   256,   257,   258,   259,   260,   261,
+     262,   263,   264,   265,   266,   267,   268,   269,   270,   271,
+     272,   273,   274,   275,   276,   277,   278,   279,   280,   281,
+     282,   283,   284,   285,   286,   287,   288,   289,   290,   291,
+     292,     0,     0,   422,   423,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,   416,   417,     0,   478,     0,   479,     0,     0,
-       0,     0,     0,   481,   418,   419,   420,   421,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,   292,   293,   294,
-     295,   296,     0,     0,     0,   422,   423,   424,   425,   426,
-     297,   298,   299,   300,   301,   302,   303,   482,   483,   484,
-     485,     0,   486,   487,   488,   489,   490,   491,   492,   304,
-     305,   306,   307,   308,   309,   427,   428,   429,   430,   431,
-     432,   433,   434,   310,   493,   311,   312,   313,   314,   315,
-     316,   317,   318,   319,   320,   321,   322,   323,   324,   325,
-     326,   327,   328,   329,   330,   331,   332,   333,   334,   335,
+       0,     0,   424,   425,     0,   486,     0,   487,   488,     0,
+       0,     0,     0,   489,   426,   427,   428,   429,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,   294,   295,   296,
+     297,   298,     0,     0,     0,   430,   431,   432,   433,   434,
+     299,   300,   301,   302,   303,   304,   305,   490,   491,   492,
+     493,     0,   494,   495,   496,   497,   498,   499,   500,   306,
+     307,   308,   309,   310,   311,   435,   436,   437,   438,   439,
+     440,   441,   442,   312,   501,   313,   314,   315,   316,   317,
+     318,   319,   320,   321,   322,   323,   324,   325,   326,   327,
+     328,   329,   330,   331,   332,   333,   334,   335,   336,   337,
+     338,   339,   340,   341,   342,   343,     1,     2,     3,     4,
+       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
+      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
+      45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
+      55,    56,    57,    58,    59,    60,    61,    62,    63,    64,
+      65,    66,    67,    68,    69,    70,    71,    72,    73,    74,
+      75,    76,    77,    78,    79,    80,    81,    82,    83,    84,
+      85,    86,    87,    88,    89,    90,    91,    92,    93,    94,
+      95,    96,    97,    98,    99,   100,   101,   102,   103,   104,
+     105,   106,   107,   108,   109,   110,   111,   112,   113,   114,
+     115,   116,   117,   118,   119,   120,   121,   122,   123,   124,
+     125,   126,   127,   128,   129,   130,   131,   132,   133,   134,
+     135,   136,   137,   138,   139,   140,   141,   142,   143,   144,
+     145,   146,   147,   148,   149,   150,   151,   152,   153,   154,
+     155,   156,   157,   158,   159,   160,   161,   162,   163,   164,
+     165,   166,   167,   168,   169,   170,   171,   172,   173,   174,
+     175,   176,   177,   178,   179,   180,   181,   182,   183,   184,
+     185,   186,   187,   188,   189,   190,   191,   192,   193,   194,
+     195,   196,   197,   198,   199,   200,   201,   202,   203,   204,
+     205,   206,   207,   208,   209,   210,   211,   212,   213,   214,
+     215,   216,   217,   218,   219,   220,   221,   222,   223,   224,
+     225,   226,   227,   228,   229,   230,   231,   232,   233,   234,
+     235,   236,   237,   238,   239,   240,   241,   242,   243,   244,
+     245,   246,   247,   248,   249,   250,   251,   252,   253,   254,
+     255,   256,   257,   258,   259,   260,   261,   262,   263,   264,
+     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
+     275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
+     285,   286,   287,   288,   289,   290,   291,   292,     0,     0,
+     422,   423,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,   424,
+     425,     0,   486,     0,   487,   617,     0,     0,     0,     0,
+     489,   426,   427,   428,   429,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,   294,   295,   296,   297,   298,     0,
+       0,     0,   430,   431,   432,   433,   434,   299,   300,   301,
+     302,   303,   304,   305,   490,   491,   492,   493,     0,   494,
+     495,   496,   497,   498,   499,   500,   306,   307,   308,   309,
+     310,   311,   435,   436,   437,   438,   439,   440,   441,   442,
+     312,   501,   313,   314,   315,   316,   317,   318,   319,   320,
+     321,   322,   323,   324,   325,   326,   327,   328,   329,   330,
+     331,   332,   333,   334,   335,   336,   337,   338,   339,   340,
+     341,   342,   343,     1,     2,     3,     4,     5,     6,     7,
+       8,     9,    10,    11,    12,    13,    14,    15,    16,    17,
+      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
+      28,    29,    30,    31,    32,    33,    34,    35,    36,    37,
+      38,    39,    40,    41,    42,    43,    44,    45,    46,    47,
+      48,    49,    50,    51,    52,    53,    54,    55,    56,    57,
+      58,    59,    60,    61,    62,    63,    64,    65,    66,    67,
+      68,    69,    70,    71,    72,    73,    74,    75,    76,    77,
+      78,    79,    80,    81,    82,    83,    84,    85,    86,    87,
+      88,    89,    90,    91,    92,    93,    94,    95,    96,    97,
+      98,    99,   100,   101,   102,   103,   104,   105,   106,   107,
+     108,   109,   110,   111,   112,   113,   114,   115,   116,   117,
+     118,   119,   120,   121,   122,   123,   124,   125,   126,   127,
+     128,   129,   130,   131,   132,   133,   134,   135,   136,   137,
+     138,   139,   140,   141,   142,   143,   144,   145,   146,   147,
+     148,   149,   150,   151,   152,   153,   154,   155,   156,   157,
+     158,   159,   160,   161,   162,   163,   164,   165,   166,   167,
+     168,   169,   170,   171,   172,   173,   174,   175,   176,   177,
+     178,   179,   180,   181,   182,   183,   184,   185,   186,   187,
+     188,   189,   190,   191,   192,   193,   194,   195,   196,   197,
+     198,   199,   200,   201,   202,   203,   204,   205,   206,   207,
+     208,   209,   210,   211,   212,   213,   214,   215,   216,   217,
+     218,   219,   220,   221,   222,   223,   224,   225,   226,   227,
+     228,   229,   230,   231,   232,   233,   234,   235,   236,   237,
+     238,   239,   240,   241,   242,   243,   244,   245,   246,   247,
+     248,   249,   250,   251,   252,   253,   254,   255,   256,   257,
+     258,   259,   260,   261,   262,   263,   264,   265,   266,   267,
+     268,   269,   270,   271,   272,   273,   274,   275,   276,   277,
+     278,   279,   280,   281,   282,   283,   284,   285,   286,   287,
+     288,   289,   290,   291,   292,     0,     0,   422,   423,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,   424,   425,     0,   486,
+       0,   487,     0,     0,     0,     0,     0,   489,   426,   427,
+     428,   429,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,   294,   295,   296,   297,   298,     0,     0,     0,   430,
+     431,   432,   433,   434,   299,   300,   301,   302,   303,   304,
+     305,   490,   491,   492,   493,     0,   494,   495,   496,   497,
+     498,   499,   500,   306,   307,   308,   309,   310,   311,   435,
+     436,   437,   438,   439,   440,   441,   442,   312,   501,   313,
+     314,   315,   316,   317,   318,   319,   320,   321,   322,   323,
+     324,   325,   326,   327,   328,   329,   330,   331,   332,   333,
+     334,   335,   336,   337,   338,   339,   340,   341,   342,   343,
        1,     2,     3,     4,     5,     6,     7,     8,     9,    10,
       11,    12,    13,    14,    15,    16,    17,    18,    19,    20,
       21,    22,    23,    24,    25,    26,    27,    28,    29,    30,
@@ -1664,100 +1683,19 @@
      261,   262,   263,   264,   265,   266,   267,   268,   269,   270,
      271,   272,   273,   274,   275,   276,   277,   278,   279,   280,
      281,   282,   283,   284,   285,   286,   287,   288,   289,   290,
-       0,     0,   414,   415,     0,     0,     0,     0,     0,     0,
+     291,   292,     0,     0,   422,   423,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,   416,   417,     0,   478,     0,   400,     0,     0,     0,
-       0,     0,   481,   418,   419,   420,   421,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,   292,   293,   294,   295,
-     296,     0,     0,     0,   422,   423,   424,   425,   426,   297,
-     298,   299,   300,   301,   302,   303,   482,   483,   484,   485,
-       0,   486,   487,   488,   489,   490,   491,   492,   304,   305,
-     306,   307,   308,   309,   427,   428,   429,   430,   431,   432,
-     433,   434,   310,   493,   311,   312,   313,   314,   315,   316,
+       0,     0,     0,   424,   425,     0,   486,     0,   408,     0,
+       0,     0,     0,     0,   489,   426,   427,   428,   429,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,   294,   295,
+     296,   297,   298,     0,     0,     0,   430,   431,   432,   433,
+     434,   299,   300,   301,   302,   303,   304,   305,   490,   491,
+     492,   493,     0,   494,   495,   496,   497,   498,   499,   500,
+     306,   307,   308,   309,   310,   311,   435,   436,   437,   438,
+     439,   440,   441,   442,   312,   501,   313,   314,   315,   316,
      317,   318,   319,   320,   321,   322,   323,   324,   325,   326,
-     327,   328,   329,   330,   331,   332,   333,   334,   335,     1,
-       2,     3,     4,     5,     6,     7,     8,     9,    10,    11,
-      12,    13,    14,    15,    16,    17,    18,    19,    20,    21,
-      22,    23,    24,    25,    26,    27,    28,    29,    30,    31,
-      32,    33,    34,    35,    36,    37,    38,    39,    40,    41,
-      42,    43,    44,    45,    46,    47,    48,    49,    50,    51,
-      52,    53,    54,    55,    56,    57,    58,    59,    60,    61,
-      62,    63,    64,    65,    66,    67,    68,    69,    70,    71,
-      72,    73,    74,    75,    76,    77,    78,    79,    80,    81,
-      82,    83,    84,    85,    86,    87,    88,    89,    90,    91,
-      92,    93,    94,    95,    96,    97,    98,    99,   100,   101,
-     102,   103,   104,   105,   106,   107,   108,   109,   110,   111,
-     112,   113,   114,   115,   116,   117,   118,   119,   120,   121,
-     122,   123,   124,   125,   126,   127,   128,   129,   130,   131,
-     132,   133,   134,   135,   136,   137,   138,   139,   140,   141,
-     142,   143,   144,   145,   146,   147,   148,   149,   150,   151,
-     152,   153,   154,   155,   156,   157,   158,   159,   160,   161,
-     162,   163,   164,   165,   166,   167,   168,   169,   170,   171,
-     172,   173,   174,   175,   176,   177,   178,   179,   180,   181,
-     182,   183,   184,   185,   186,   187,   188,   189,   190,   191,
-     192,   193,   194,   195,   196,   197,   198,   199,   200,   201,
-     202,   203,   204,   205,   206,   207,   208,   209,   210,   211,
-     212,   213,   214,   215,   216,   217,   218,   219,   220,   221,
-     222,   223,   224,   225,   226,   227,   228,   229,   230,   231,
-     232,   233,   234,   235,   236,   237,   238,   239,   240,   241,
-     242,   243,   244,   245,   246,   247,   248,   249,   250,   251,
-     252,   253,   254,   255,   256,   257,   258,   259,   260,   261,
-     262,   263,   264,   265,   266,   267,   268,   269,   270,   271,
-     272,   273,   274,   275,   276,   277,   278,   279,   280,   281,
-     282,   283,   284,   285,   286,   287,   288,   289,   290,     0,
-       0,   414,   415,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-     416,   417,     0,   478,     0,     0,     0,     0,     0,     0,
-       0,   481,   418,   419,   420,   421,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,   292,   293,   294,   295,   296,
-       0,     0,     0,   422,   423,   424,   425,   426,   297,   298,
-     299,   300,   301,   302,   303,   482,   483,   484,   485,     0,
-     486,   487,   488,   489,   490,   491,   492,   304,   305,   306,
-     307,   308,   309,   427,   428,   429,   430,   431,   432,   433,
-     434,   310,   493,   311,   312,   313,   314,   315,   316,   317,
-     318,   319,   320,   321,   322,   323,   324,   325,   326,   327,
-     328,   329,   330,   331,   332,   333,   334,   335,     1,     2,
-       3,     4,     5,     6,     7,     8,     9,    10,    11,    12,
-      13,    14,    15,    16,    17,    18,    19,    20,    21,    22,
-      23,    24,    25,    26,    27,    28,    29,    30,    31,    32,
-      33,    34,    35,    36,    37,    38,    39,    40,    41,    42,
-      43,    44,    45,    46,    47,    48,    49,    50,    51,    52,
-      53,    54,    55,    56,    57,    58,    59,    60,    61,    62,
-      63,    64,    65,    66,    67,    68,    69,    70,    71,    72,
-      73,    74,    75,    76,    77,    78,    79,    80,    81,    82,
-      83,    84,    85,    86,    87,    88,    89,    90,    91,    92,
-      93,    94,    95,    96,    97,    98,    99,   100,   101,   102,
-     103,   104,   105,   106,   107,   108,   109,   110,   111,   112,
-     113,   114,   115,   116,   117,   118,   119,   120,   121,   122,
-     123,   124,   125,   126,   127,   128,   129,   130,   131,   132,
-     133,   134,   135,   136,   137,   138,   139,   140,   141,   142,
-     143,   144,   145,   146,   147,   148,   149,   150,   151,   152,
-     153,   154,   155,   156,   157,   158,   159,   160,   161,   162,
-     163,   164,   165,   166,   167,   168,   169,   170,   171,   172,
-     173,   174,   175,   176,   177,   178,   179,   180,   181,   182,
-     183,   184,   185,   186,   187,   188,   189,   190,   191,   192,
-     193,   194,   195,   196,   197,   198,   199,   200,   201,   202,
-     203,   204,   205,   206,   207,   208,   209,   210,   211,   212,
-     213,   214,   215,   216,   217,   218,   219,   220,   221,   222,
-     223,   224,   225,   226,   227,   228,   229,   230,   231,   232,
-     233,   234,   235,   236,   237,   238,   239,   240,   241,   242,
-     243,   244,   245,   246,   247,   248,   249,   250,   251,   252,
-     253,   254,   255,   256,   257,   258,   259,   260,   261,   262,
-     263,   264,   265,   266,   267,   268,   269,   270,   271,   272,
-     273,   274,   275,   276,   277,   278,   279,   280,   281,   282,
-     283,   284,   285,   286,   287,   288,   289,   290,     0,     0,
-     414,   415,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,   416,
-     417,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-     481,   418,   419,   420,   421,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,   292,   293,   294,   295,   296,     0,
-       0,     0,   422,   423,   424,   425,   426,   297,   298,   299,
-     300,   301,   302,   303,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,   304,   305,   306,   307,
-     308,   309,   427,   428,   429,   430,   431,   432,   433,   434,
-     310,     0,   311,   312,   313,   314,   315,   316,   317,   318,
-     319,   320,   321,   322,   323,   324,   325,   326,   327,   328,
-     329,   330,   331,   332,   333,   334,   335,     1,     2,     3,
+     327,   328,   329,   330,   331,   332,   333,   334,   335,   336,
+     337,   338,   339,   340,   341,   342,   343,     1,     2,     3,
        4,     5,     6,     7,     8,     9,    10,    11,    12,    13,
       14,    15,    16,    17,    18,    19,    20,    21,    22,    23,
       24,    25,    26,    27,    28,    29,    30,    31,    32,    33,
@@ -1786,101 +1724,20 @@
      254,   255,   256,   257,   258,   259,   260,   261,   262,   263,
      264,   265,   266,   267,   268,   269,   270,   271,   272,   273,
      274,   275,   276,   277,   278,   279,   280,   281,   282,   283,
-     284,   285,   286,   287,   288,   289,   290,     0,     0,   414,
-     415,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,   416,   417,
+     284,   285,   286,   287,   288,   289,   290,   291,   292,     0,
+       0,   422,   423,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-     418,   419,   420,   421,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,   292,   293,   294,   295,     0,     0,     0,
-       0,   422,   423,   424,   425,   426,   297,   298,   299,   300,
-     301,   302,   303,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,   304,   305,   306,   307,   308,
-     309,   427,   428,   429,   430,   431,   432,   433,   434,   310,
-       0,   311,   312,   313,   314,   315,   316,   317,   318,   319,
+     424,   425,     0,   486,     0,     0,     0,     0,     0,     0,
+       0,   489,   426,   427,   428,   429,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,   294,   295,   296,   297,   298,
+       0,     0,     0,   430,   431,   432,   433,   434,   299,   300,
+     301,   302,   303,   304,   305,   490,   491,   492,   493,     0,
+     494,   495,   496,   497,   498,   499,   500,   306,   307,   308,
+     309,   310,   311,   435,   436,   437,   438,   439,   440,   441,
+     442,   312,   501,   313,   314,   315,   316,   317,   318,   319,
      320,   321,   322,   323,   324,   325,   326,   327,   328,   329,
-     330,   331,   332,   333,   334,   335,     1,     2,     3,     4,
-       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
-      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
-      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
-      45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
-      55,    56,    57,    58,    59,    60,    61,    62,    63,    64,
-      65,    66,    67,    68,    69,    70,    71,    72,    73,    74,
-      75,    76,    77,    78,    79,    80,    81,    82,    83,    84,
-      85,    86,    87,    88,    89,    90,    91,    92,    93,    94,
-      95,    96,    97,    98,    99,   100,   101,   102,   103,   104,
-     105,   106,   107,   108,   109,   110,   111,   112,   113,   114,
-     115,   116,   117,   118,   119,   120,   121,   122,   123,   124,
-     125,   126,   127,   128,   129,   130,   131,   132,   133,   134,
-     135,   136,   137,   138,   139,   140,   141,   142,   143,   144,
-     145,   146,   147,   148,   149,   150,   151,   152,   153,   154,
-     155,   156,   157,   158,   159,   160,   161,   162,   163,   164,
-     165,   166,   167,   168,   169,   170,   171,   172,   173,   174,
-     175,   176,   177,   178,   179,   180,   181,   182,   183,   184,
-     185,   186,   187,   188,   189,   190,   191,   192,   193,   194,
-     195,   196,   197,   198,   199,   200,   201,   202,   203,   204,
-     205,   206,   207,   208,   209,   210,   211,   212,   213,   214,
-     215,   216,   217,   218,   219,   220,   221,   222,   223,   224,
-     225,   226,   227,   228,   229,   230,   231,   232,   233,   234,
-     235,   236,   237,   238,   239,   240,   241,   242,   243,   244,
-     245,   246,   247,   248,   249,   250,   251,   252,   253,   254,
-     255,   256,   257,   258,   259,   260,   261,   262,   263,   264,
-     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
-     275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
-     285,   286,   287,   288,   289,   290,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,   291,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,   292,   293,   294,   295,   296,     0,     0,     0,
-       0,     0,     0,     0,     0,   297,   298,   299,   300,   301,
-     302,   303,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,   304,   305,   306,   307,   308,   309,
-       0,     0,     0,     0,     0,     0,     0,     0,   310,     0,
-     311,   312,   313,   314,   315,   316,   317,   318,   319,   320,
-     321,   322,   323,   324,   325,   326,   327,   328,   329,   330,
-     331,   332,   333,   334,   335,     1,     2,     3,     4,     5,
-       6,     7,     8,     9,    10,    11,    12,    13,    14,    15,
-      16,    17,    18,    19,    20,    21,    22,    23,    24,    25,
-      26,    27,    28,    29,    30,    31,    32,    33,    34,    35,
-      36,    37,    38,    39,    40,    41,    42,    43,    44,    45,
-      46,    47,    48,    49,    50,    51,    52,    53,    54,    55,
-      56,    57,    58,    59,    60,    61,    62,    63,    64,    65,
-      66,    67,    68,    69,    70,    71,    72,    73,    74,    75,
-      76,    77,    78,    79,    80,    81,    82,    83,    84,    85,
-      86,    87,    88,    89,    90,    91,    92,    93,    94,    95,
-      96,    97,    98,    99,   100,   101,   102,   103,   104,   105,
-     106,   107,   108,   109,   110,   111,   112,   113,   114,   115,
-     116,   117,   118,   119,   120,   121,   122,   123,   124,   125,
-     126,   127,   128,   129,   130,   131,   132,   133,   134,   135,
-     136,   137,   138,   139,   140,   141,   142,   143,   144,   145,
-     146,   147,   148,   149,   150,   151,   152,   153,   154,   155,
-     156,   157,   158,   159,   160,   161,   162,   163,   164,   165,
-     166,   167,   168,   169,   170,   171,   172,   173,   174,   175,
-     176,   177,   178,   179,   180,   181,   182,   183,   184,   185,
-     186,   187,   188,   189,   190,   191,   192,   193,   194,   195,
-     196,   197,   198,   199,   200,   201,   202,   203,   204,   205,
-     206,   207,   208,   209,   210,   211,   212,   213,   214,   215,
-     216,   217,   218,   219,   220,   221,   222,   223,   224,   225,
-     226,   227,   228,   229,   230,   231,   232,   233,   234,   235,
-     236,   237,   238,   239,   240,   241,   242,   243,   244,   245,
-     246,   247,   248,   249,   250,   251,   252,   253,   254,   255,
-     256,   257,   258,   259,   260,   261,   262,   263,   264,   265,
-     266,   267,   268,   269,   270,   271,   272,   273,   274,   275,
-     276,   277,   278,   279,   280,   281,   282,   283,   284,   285,
-     286,   287,   288,   289,   290,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,   379,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,   292,   293,   294,   295,     0,     0,     0,     0,     0,
-       0,     0,     0,   380,   297,   298,   299,   300,   301,   302,
-     303,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,   304,   305,   306,   307,   308,   309,     0,
-       0,     0,     0,     0,     0,     0,     0,   310,     0,   311,
-     312,   313,   314,   315,   316,   317,   318,   319,   320,   321,
-     322,   323,   324,   325,   326,   327,   328,   329,   330,   331,
-     332,   333,   334,   335,     1,     2,     3,     4,     5,     6,
+     330,   331,   332,   333,   334,   335,   336,   337,   338,   339,
+     340,   341,   342,   343,     1,     2,     3,     4,     5,     6,
        7,     8,     9,    10,    11,    12,    13,    14,    15,    16,
       17,    18,    19,    20,    21,    22,    23,    24,    25,    26,
       27,    28,    29,    30,    31,    32,    33,    34,    35,    36,
@@ -1909,101 +1766,20 @@
      257,   258,   259,   260,   261,   262,   263,   264,   265,   266,
      267,   268,   269,   270,   271,   272,   273,   274,   275,   276,
      277,   278,   279,   280,   281,   282,   283,   284,   285,   286,
-     287,   288,   289,   290,     0,     0,     0,     0,     0,     0,
+     287,   288,   289,   290,   291,   292,     0,     0,   422,   423,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,   549,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-     292,   293,   294,   295,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,   297,   298,   299,   300,   301,   302,   303,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,   304,   305,   306,   307,   308,   309,     0,     0,
-       0,     0,     0,     0,     0,     0,   310,     0,   311,   312,
+       0,     0,     0,     0,     0,     0,     0,   424,   425,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,   489,   426,
+     427,   428,   429,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,   294,   295,   296,   297,   298,     0,     0,     0,
+     430,   431,   432,   433,   434,   299,   300,   301,   302,   303,
+     304,   305,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,   306,   307,   308,   309,   310,   311,
+     435,   436,   437,   438,   439,   440,   441,   442,   312,     0,
      313,   314,   315,   316,   317,   318,   319,   320,   321,   322,
      323,   324,   325,   326,   327,   328,   329,   330,   331,   332,
-     333,   334,   335,     1,     2,     3,     4,     5,     6,     7,
-       8,     9,    10,    11,    12,    13,    14,    15,    16,    17,
-      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
-      28,    29,    30,    31,    32,    33,    34,    35,    36,    37,
-      38,    39,    40,    41,    42,    43,    44,    45,    46,    47,
-      48,    49,    50,    51,    52,    53,    54,    55,    56,    57,
-      58,    59,    60,    61,    62,    63,    64,    65,    66,    67,
-      68,    69,    70,    71,    72,    73,    74,    75,    76,    77,
-      78,    79,    80,    81,    82,    83,    84,    85,    86,    87,
-      88,    89,    90,    91,    92,    93,    94,    95,    96,    97,
-      98,    99,   100,   101,   102,   103,   104,   105,   106,   107,
-     108,   109,   110,   111,   112,   113,   114,   115,   116,   117,
-     118,   119,   120,   121,   122,   123,   124,   125,   126,   127,
-     128,   129,   130,   131,   132,   133,   134,   135,   136,   137,
-     138,   139,   140,   141,   142,   143,   144,   145,   146,   147,
-     148,   149,   150,   151,   152,   153,   154,   155,   156,   157,
-     158,   159,   160,   161,   162,   163,   164,   165,   166,   167,
-     168,   169,   170,   171,   172,   173,   174,   175,   176,   177,
-     178,   179,   180,   181,   182,   183,   184,   185,   186,   187,
-     188,   189,   190,   191,   192,   193,   194,   195,   196,   197,
-     198,   199,   200,   201,   202,   203,   204,   205,   206,   207,
-     208,   209,   210,   211,   212,   213,   214,   215,   216,   217,
-     218,   219,   220,   221,   222,   223,   224,   225,   226,   227,
-     228,   229,   230,   231,   232,   233,   234,   235,   236,   237,
-     238,   239,   240,   241,   242,   243,   244,   245,   246,   247,
-     248,   249,   250,   251,   252,   253,   254,   255,   256,   257,
-     258,   259,   260,   261,   262,   263,   264,   265,   266,   267,
-     268,   269,   270,   271,   272,   273,   274,   275,   276,   277,
-     278,   279,   280,   281,   282,   283,   284,   285,   286,   287,
-     288,   289,   290,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-     631,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,   292,
-     293,   294,   295,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,   297,   298,   299,   300,   301,   302,   303,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,   304,   305,   306,   307,   308,   309,     0,     0,     0,
-       0,     0,     0,     0,     0,   310,     0,   311,   312,   313,
-     314,   315,   316,   317,   318,   319,   320,   321,   322,   323,
-     324,   325,   326,   327,   328,   329,   330,   331,   332,   333,
-     334,   335,     1,     2,     3,     4,     5,     6,     7,     8,
-       9,    10,    11,    12,    13,    14,    15,    16,    17,    18,
-      19,    20,    21,    22,    23,    24,    25,    26,    27,    28,
-      29,    30,    31,    32,    33,    34,    35,    36,    37,    38,
-      39,    40,    41,    42,    43,    44,    45,    46,    47,    48,
-      49,    50,    51,    52,    53,    54,    55,    56,    57,    58,
-      59,    60,    61,    62,    63,    64,    65,    66,    67,    68,
-      69,    70,    71,    72,    73,    74,    75,    76,    77,    78,
-      79,    80,    81,    82,    83,    84,    85,    86,    87,    88,
-      89,    90,    91,    92,    93,    94,    95,    96,    97,    98,
-      99,   100,   101,   102,   103,   104,   105,   106,   107,   108,
-     109,   110,   111,   112,   113,   114,   115,   116,   117,   118,
-     119,   120,   121,   122,   123,   124,   125,   126,   127,   128,
-     129,   130,   131,   132,   133,   134,   135,   136,   137,   138,
-     139,   140,   141,   142,   143,   144,   145,   146,   147,   148,
-     149,   150,   151,   152,   153,   154,   155,   156,   157,   158,
-     159,   160,   161,   162,   163,   164,   165,   166,   167,   168,
-     169,   170,   171,   172,   173,   174,   175,   176,   177,   178,
-     179,   180,   181,   182,   183,   184,   185,   186,   187,   188,
-     189,   190,   191,   192,   193,   194,   195,   196,   197,   198,
-     199,   200,   201,   202,   203,   204,   205,   206,   207,   208,
-     209,   210,   211,   212,   213,   214,   215,   216,   217,   218,
-     219,   220,   221,   222,   223,   224,   225,   226,   227,   228,
-     229,   230,   231,   232,   233,   234,   235,   236,   237,   238,
-     239,   240,   241,   242,   243,   244,   245,   246,   247,   248,
-     249,   250,   251,   252,   253,   254,   255,   256,   257,   258,
-     259,   260,   261,   262,   263,   264,   265,   266,   267,   268,
-     269,   270,   271,   272,   273,   274,   275,   276,   277,   278,
-     279,   280,   281,   282,   283,   284,   285,   286,   287,   288,
-     289,   290,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,   669,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,   292,   293,
-     294,   295,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,   297,   298,   299,   300,   301,   302,   303,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-     304,   305,   306,   307,   308,   309,     0,     0,     0,     0,
-       0,     0,     0,     0,   310,     0,   311,   312,   313,   314,
-     315,   316,   317,   318,   319,   320,   321,   322,   323,   324,
-     325,   326,   327,   328,   329,   330,   331,   332,   333,   334,
-     335,     1,     2,     3,     4,     5,     6,     7,     8,     9,
+     333,   334,   335,   336,   337,   338,   339,   340,   341,   342,
+     343,     1,     2,     3,     4,     5,     6,     7,     8,     9,
       10,    11,    12,    13,    14,    15,    16,    17,    18,    19,
       20,    21,    22,    23,    24,    25,    26,    27,    28,    29,
       30,    31,    32,    33,    34,    35,    36,    37,    38,    39,
@@ -2032,18 +1808,269 @@
      260,   261,   262,   263,   264,   265,   266,   267,   268,   269,
      270,   271,   272,   273,   274,   275,   276,   277,   278,   279,
      280,   281,   282,   283,   284,   285,   286,   287,   288,   289,
-     290,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+     290,   291,   292,     0,     0,   422,   423,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,   424,   425,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,   426,   427,   428,   429,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,   294,
+     295,   296,   297,     0,     0,     0,     0,   430,   431,   432,
+     433,   434,   299,   300,   301,   302,   303,   304,   305,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,   292,   293,   294,
-     295,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-     297,   298,   299,   300,   301,   302,   303,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,   304,
-     305,   306,   307,   308,   309,     0,     0,     0,     0,     0,
-       0,     0,     0,   310,     0,   311,   312,   313,   314,   315,
+       0,   306,   307,   308,   309,   310,   311,   435,   436,   437,
+     438,   439,   440,   441,   442,   312,     0,   313,   314,   315,
      316,   317,   318,   319,   320,   321,   322,   323,   324,   325,
      326,   327,   328,   329,   330,   331,   332,   333,   334,   335,
+     336,   337,   338,   339,   340,   341,   342,   343,     1,     2,
+       3,     4,     5,     6,     7,     8,     9,    10,    11,    12,
+      13,    14,    15,    16,    17,    18,    19,    20,    21,    22,
+      23,    24,    25,    26,    27,    28,    29,    30,    31,    32,
+      33,    34,    35,    36,    37,    38,    39,    40,    41,    42,
+      43,    44,    45,    46,    47,    48,    49,    50,    51,    52,
+      53,    54,    55,    56,    57,    58,    59,    60,    61,    62,
+      63,    64,    65,    66,    67,    68,    69,    70,    71,    72,
+      73,    74,    75,    76,    77,    78,    79,    80,    81,    82,
+      83,    84,    85,    86,    87,    88,    89,    90,    91,    92,
+      93,    94,    95,    96,    97,    98,    99,   100,   101,   102,
+     103,   104,   105,   106,   107,   108,   109,   110,   111,   112,
+     113,   114,   115,   116,   117,   118,   119,   120,   121,   122,
+     123,   124,   125,   126,   127,   128,   129,   130,   131,   132,
+     133,   134,   135,   136,   137,   138,   139,   140,   141,   142,
+     143,   144,   145,   146,   147,   148,   149,   150,   151,   152,
+     153,   154,   155,   156,   157,   158,   159,   160,   161,   162,
+     163,   164,   165,   166,   167,   168,   169,   170,   171,   172,
+     173,   174,   175,   176,   177,   178,   179,   180,   181,   182,
+     183,   184,   185,   186,   187,   188,   189,   190,   191,   192,
+     193,   194,   195,   196,   197,   198,   199,   200,   201,   202,
+     203,   204,   205,   206,   207,   208,   209,   210,   211,   212,
+     213,   214,   215,   216,   217,   218,   219,   220,   221,   222,
+     223,   224,   225,   226,   227,   228,   229,   230,   231,   232,
+     233,   234,   235,   236,   237,   238,   239,   240,   241,   242,
+     243,   244,   245,   246,   247,   248,   249,   250,   251,   252,
+     253,   254,   255,   256,   257,   258,   259,   260,   261,   262,
+     263,   264,   265,   266,   267,   268,   269,   270,   271,   272,
+     273,   274,   275,   276,   277,   278,   279,   280,   281,   282,
+     283,   284,   285,   286,   287,   288,   289,   290,   291,   292,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,   293,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,   294,   295,   296,   297,
+     298,     0,     0,     0,     0,     0,     0,     0,     0,   299,
+     300,   301,   302,   303,   304,   305,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,   306,   307,
+     308,   309,   310,   311,     0,     0,     0,     0,     0,     0,
+       0,     0,   312,     0,   313,   314,   315,   316,   317,   318,
+     319,   320,   321,   322,   323,   324,   325,   326,   327,   328,
+     329,   330,   331,   332,   333,   334,   335,   336,   337,   338,
+     339,   340,   341,   342,   343,     1,     2,     3,     4,     5,
+       6,     7,     8,     9,    10,    11,    12,    13,    14,    15,
+      16,    17,    18,    19,    20,    21,    22,    23,    24,    25,
+      26,    27,    28,    29,    30,    31,    32,    33,    34,    35,
+      36,    37,    38,    39,    40,    41,    42,    43,    44,    45,
+      46,    47,    48,    49,    50,    51,    52,    53,    54,    55,
+      56,    57,    58,    59,    60,    61,    62,    63,    64,    65,
+      66,    67,    68,    69,    70,    71,    72,    73,    74,    75,
+      76,    77,    78,    79,    80,    81,    82,    83,    84,    85,
+      86,    87,    88,    89,    90,    91,    92,    93,    94,    95,
+      96,    97,    98,    99,   100,   101,   102,   103,   104,   105,
+     106,   107,   108,   109,   110,   111,   112,   113,   114,   115,
+     116,   117,   118,   119,   120,   121,   122,   123,   124,   125,
+     126,   127,   128,   129,   130,   131,   132,   133,   134,   135,
+     136,   137,   138,   139,   140,   141,   142,   143,   144,   145,
+     146,   147,   148,   149,   150,   151,   152,   153,   154,   155,
+     156,   157,   158,   159,   160,   161,   162,   163,   164,   165,
+     166,   167,   168,   169,   170,   171,   172,   173,   174,   175,
+     176,   177,   178,   179,   180,   181,   182,   183,   184,   185,
+     186,   187,   188,   189,   190,   191,   192,   193,   194,   195,
+     196,   197,   198,   199,   200,   201,   202,   203,   204,   205,
+     206,   207,   208,   209,   210,   211,   212,   213,   214,   215,
+     216,   217,   218,   219,   220,   221,   222,   223,   224,   225,
+     226,   227,   228,   229,   230,   231,   232,   233,   234,   235,
+     236,   237,   238,   239,   240,   241,   242,   243,   244,   245,
+     246,   247,   248,   249,   250,   251,   252,   253,   254,   255,
+     256,   257,   258,   259,   260,   261,   262,   263,   264,   265,
+     266,   267,   268,   269,   270,   271,   272,   273,   274,   275,
+     276,   277,   278,   279,   280,   281,   282,   283,   284,   285,
+     286,   287,   288,   289,   290,   291,   292,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,   387,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,   294,   295,   296,   297,     0,     0,     0,
+       0,     0,     0,     0,     0,   388,   299,   300,   301,   302,
+     303,   304,   305,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,   306,   307,   308,   309,   310,
+     311,     0,     0,     0,     0,     0,     0,     0,     0,   312,
+       0,   313,   314,   315,   316,   317,   318,   319,   320,   321,
+     322,   323,   324,   325,   326,   327,   328,   329,   330,   331,
+     332,   333,   334,   335,   336,   337,   338,   339,   340,   341,
+     342,   343,     1,     2,     3,     4,     5,     6,     7,     8,
+       9,    10,    11,    12,    13,    14,    15,    16,    17,    18,
+      19,    20,    21,    22,    23,    24,    25,    26,    27,    28,
+      29,    30,    31,    32,    33,    34,    35,    36,    37,    38,
+      39,    40,    41,    42,    43,    44,    45,    46,    47,    48,
+      49,    50,    51,    52,    53,    54,    55,    56,    57,    58,
+      59,    60,    61,    62,    63,    64,    65,    66,    67,    68,
+      69,    70,    71,    72,    73,    74,    75,    76,    77,    78,
+      79,    80,    81,    82,    83,    84,    85,    86,    87,    88,
+      89,    90,    91,    92,    93,    94,    95,    96,    97,    98,
+      99,   100,   101,   102,   103,   104,   105,   106,   107,   108,
+     109,   110,   111,   112,   113,   114,   115,   116,   117,   118,
+     119,   120,   121,   122,   123,   124,   125,   126,   127,   128,
+     129,   130,   131,   132,   133,   134,   135,   136,   137,   138,
+     139,   140,   141,   142,   143,   144,   145,   146,   147,   148,
+     149,   150,   151,   152,   153,   154,   155,   156,   157,   158,
+     159,   160,   161,   162,   163,   164,   165,   166,   167,   168,
+     169,   170,   171,   172,   173,   174,   175,   176,   177,   178,
+     179,   180,   181,   182,   183,   184,   185,   186,   187,   188,
+     189,   190,   191,   192,   193,   194,   195,   196,   197,   198,
+     199,   200,   201,   202,   203,   204,   205,   206,   207,   208,
+     209,   210,   211,   212,   213,   214,   215,   216,   217,   218,
+     219,   220,   221,   222,   223,   224,   225,   226,   227,   228,
+     229,   230,   231,   232,   233,   234,   235,   236,   237,   238,
+     239,   240,   241,   242,   243,   244,   245,   246,   247,   248,
+     249,   250,   251,   252,   253,   254,   255,   256,   257,   258,
+     259,   260,   261,   262,   263,   264,   265,   266,   267,   268,
+     269,   270,   271,   272,   273,   274,   275,   276,   277,   278,
+     279,   280,   281,   282,   283,   284,   285,   286,   287,   288,
+     289,   290,   291,   292,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,   557,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+     294,   295,   296,   297,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,   299,   300,   301,   302,   303,   304,   305,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,   306,   307,   308,   309,   310,   311,     0,     0,
+       0,     0,     0,     0,     0,     0,   312,     0,   313,   314,
+     315,   316,   317,   318,   319,   320,   321,   322,   323,   324,
+     325,   326,   327,   328,   329,   330,   331,   332,   333,   334,
+     335,   336,   337,   338,   339,   340,   341,   342,   343,     1,
+       2,     3,     4,     5,     6,     7,     8,     9,    10,    11,
+      12,    13,    14,    15,    16,    17,    18,    19,    20,    21,
+      22,    23,    24,    25,    26,    27,    28,    29,    30,    31,
+      32,    33,    34,    35,    36,    37,    38,    39,    40,    41,
+      42,    43,    44,    45,    46,    47,    48,    49,    50,    51,
+      52,    53,    54,    55,    56,    57,    58,    59,    60,    61,
+      62,    63,    64,    65,    66,    67,    68,    69,    70,    71,
+      72,    73,    74,    75,    76,    77,    78,    79,    80,    81,
+      82,    83,    84,    85,    86,    87,    88,    89,    90,    91,
+      92,    93,    94,    95,    96,    97,    98,    99,   100,   101,
+     102,   103,   104,   105,   106,   107,   108,   109,   110,   111,
+     112,   113,   114,   115,   116,   117,   118,   119,   120,   121,
+     122,   123,   124,   125,   126,   127,   128,   129,   130,   131,
+     132,   133,   134,   135,   136,   137,   138,   139,   140,   141,
+     142,   143,   144,   145,   146,   147,   148,   149,   150,   151,
+     152,   153,   154,   155,   156,   157,   158,   159,   160,   161,
+     162,   163,   164,   165,   166,   167,   168,   169,   170,   171,
+     172,   173,   174,   175,   176,   177,   178,   179,   180,   181,
+     182,   183,   184,   185,   186,   187,   188,   189,   190,   191,
+     192,   193,   194,   195,   196,   197,   198,   199,   200,   201,
+     202,   203,   204,   205,   206,   207,   208,   209,   210,   211,
+     212,   213,   214,   215,   216,   217,   218,   219,   220,   221,
+     222,   223,   224,   225,   226,   227,   228,   229,   230,   231,
+     232,   233,   234,   235,   236,   237,   238,   239,   240,   241,
+     242,   243,   244,   245,   246,   247,   248,   249,   250,   251,
+     252,   253,   254,   255,   256,   257,   258,   259,   260,   261,
+     262,   263,   264,   265,   266,   267,   268,   269,   270,   271,
+     272,   273,   274,   275,   276,   277,   278,   279,   280,   281,
+     282,   283,   284,   285,   286,   287,   288,   289,   290,   291,
+     292,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,   639,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,   294,   295,   296,
+     297,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+     299,   300,   301,   302,   303,   304,   305,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,   306,
+     307,   308,   309,   310,   311,     0,     0,     0,     0,     0,
+       0,     0,     0,   312,     0,   313,   314,   315,   316,   317,
+     318,   319,   320,   321,   322,   323,   324,   325,   326,   327,
+     328,   329,   330,   331,   332,   333,   334,   335,   336,   337,
+     338,   339,   340,   341,   342,   343,     1,     2,     3,     4,
+       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
+      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
+      45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
+      55,    56,    57,    58,    59,    60,    61,    62,    63,    64,
+      65,    66,    67,    68,    69,    70,    71,    72,    73,    74,
+      75,    76,    77,    78,    79,    80,    81,    82,    83,    84,
+      85,    86,    87,    88,    89,    90,    91,    92,    93,    94,
+      95,    96,    97,    98,    99,   100,   101,   102,   103,   104,
+     105,   106,   107,   108,   109,   110,   111,   112,   113,   114,
+     115,   116,   117,   118,   119,   120,   121,   122,   123,   124,
+     125,   126,   127,   128,   129,   130,   131,   132,   133,   134,
+     135,   136,   137,   138,   139,   140,   141,   142,   143,   144,
+     145,   146,   147,   148,   149,   150,   151,   152,   153,   154,
+     155,   156,   157,   158,   159,   160,   161,   162,   163,   164,
+     165,   166,   167,   168,   169,   170,   171,   172,   173,   174,
+     175,   176,   177,   178,   179,   180,   181,   182,   183,   184,
+     185,   186,   187,   188,   189,   190,   191,   192,   193,   194,
+     195,   196,   197,   198,   199,   200,   201,   202,   203,   204,
+     205,   206,   207,   208,   209,   210,   211,   212,   213,   214,
+     215,   216,   217,   218,   219,   220,   221,   222,   223,   224,
+     225,   226,   227,   228,   229,   230,   231,   232,   233,   234,
+     235,   236,   237,   238,   239,   240,   241,   242,   243,   244,
+     245,   246,   247,   248,   249,   250,   251,   252,   253,   254,
+     255,   256,   257,   258,   259,   260,   261,   262,   263,   264,
+     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
+     275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
+     285,   286,   287,   288,   289,   290,   291,   292,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,   677,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,   294,   295,   296,   297,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,   299,   300,   301,
+     302,   303,   304,   305,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,   306,   307,   308,   309,
+     310,   311,     0,     0,     0,     0,     0,     0,     0,     0,
+     312,     0,   313,   314,   315,   316,   317,   318,   319,   320,
+     321,   322,   323,   324,   325,   326,   327,   328,   329,   330,
+     331,   332,   333,   334,   335,   336,   337,   338,   339,   340,
+     341,   342,   343,     1,     2,     3,     4,     5,     6,     7,
+       8,     9,    10,    11,    12,    13,    14,    15,    16,    17,
+      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
+      28,    29,    30,    31,    32,    33,    34,    35,    36,    37,
+      38,    39,    40,    41,    42,    43,    44,    45,    46,    47,
+      48,    49,    50,    51,    52,    53,    54,    55,    56,    57,
+      58,    59,    60,    61,    62,    63,    64,    65,    66,    67,
+      68,    69,    70,    71,    72,    73,    74,    75,    76,    77,
+      78,    79,    80,    81,    82,    83,    84,    85,    86,    87,
+      88,    89,    90,    91,    92,    93,    94,    95,    96,    97,
+      98,    99,   100,   101,   102,   103,   104,   105,   106,   107,
+     108,   109,   110,   111,   112,   113,   114,   115,   116,   117,
+     118,   119,   120,   121,   122,   123,   124,   125,   126,   127,
+     128,   129,   130,   131,   132,   133,   134,   135,   136,   137,
+     138,   139,   140,   141,   142,   143,   144,   145,   146,   147,
+     148,   149,   150,   151,   152,   153,   154,   155,   156,   157,
+     158,   159,   160,   161,   162,   163,   164,   165,   166,   167,
+     168,   169,   170,   171,   172,   173,   174,   175,   176,   177,
+     178,   179,   180,   181,   182,   183,   184,   185,   186,   187,
+     188,   189,   190,   191,   192,   193,   194,   195,   196,   197,
+     198,   199,   200,   201,   202,   203,   204,   205,   206,   207,
+     208,   209,   210,   211,   212,   213,   214,   215,   216,   217,
+     218,   219,   220,   221,   222,   223,   224,   225,   226,   227,
+     228,   229,   230,   231,   232,   233,   234,   235,   236,   237,
+     238,   239,   240,   241,   242,   243,   244,   245,   246,   247,
+     248,   249,   250,   251,   252,   253,   254,   255,   256,   257,
+     258,   259,   260,   261,   262,   263,   264,   265,   266,   267,
+     268,   269,   270,   271,   272,   273,   274,   275,   276,   277,
+     278,   279,   280,   281,   282,   283,   284,   285,   286,   287,
+     288,   289,   290,   291,   292,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,   294,   295,   296,   297,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,   299,   300,   301,   302,   303,   304,
+     305,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,   306,   307,   308,   309,   310,   311,     0,
+       0,     0,     0,     0,     0,     0,     0,   312,     0,   313,
+     314,   315,   316,   317,   318,   319,   320,   321,   322,   323,
+     324,   325,   326,   327,   328,   329,   330,   331,   332,   333,
+     334,   335,   336,   337,   338,   339,   340,   341,   342,   343,
        2,     3,     4,     5,     6,     7,     8,     9,    10,    11,
       12,    13,    14,    15,    16,    17,    18,    19,    20,    21,
       22,    23,    24,    25,    26,    27,    28,    29,    30,    31,
@@ -2072,213 +2099,58 @@
      252,   253,   254,   255,   256,   257,   258,   259,   260,   261,
      262,   263,   264,   265,   266,   267,   268,   269,   270,   271,
      272,   273,   274,   275,   276,   277,   278,   279,   280,   281,
-     282,   283,   284,   285,   286,   287,   288,   289,   290,     0,
-       0,   414,   415,     0,     0,     0,     0,     0,     0,     0,
+     282,   283,   284,   285,   286,   287,   288,   289,   290,   291,
+     292,     0,     0,   422,   423,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-     416,   417,     0,     0,     0,   521,   688,     0,     0,     0,
-       0,     0,   418,   419,   420,   421,     0,     0,     0,     0,
+       0,     0,   424,   425,     0,     0,     0,   529,   696,     0,
+       0,     0,     0,     0,   426,   427,   428,   429,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,   422,   423,   424,   425,   426,   297,     0,
-       0,     0,     0,   302,   303,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,   430,   431,   432,   433,   434,
+     299,     0,     0,     0,     0,   304,   305,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,   427,   428,   429,   430,   431,   432,   433,
-     434,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-     318,     2,     3,     4,     5,     6,     7,     8,     9,    10,
-      11,    12,    13,    14,    15,    16,    17,    18,    19,    20,
-      21,    22,    23,    24,    25,    26,    27,    28,    29,    30,
-      31,    32,    33,    34,    35,    36,    37,    38,    39,    40,
-      41,    42,    43,    44,    45,    46,    47,    48,    49,    50,
-      51,    52,    53,    54,    55,    56,    57,    58,     0,     0,
-      61,    62,    63,    64,    65,    66,    67,    68,    69,    70,
-      71,    72,    73,    74,    75,    76,    77,    78,    79,    80,
-      81,    82,    83,    84,    85,    86,    87,    88,    89,    90,
-      91,    92,    93,    94,    95,    96,    97,    98,    99,   100,
-     101,   102,   103,   104,   105,   106,   107,   108,   109,   110,
-     111,   112,   113,   114,   115,   116,   117,   118,   119,   120,
-     121,   122,   123,   124,   125,   126,   127,   128,   129,   130,
-     131,   132,   133,   134,   135,   136,   137,   138,   139,   140,
-     141,   142,   143,   144,   145,   146,   147,   148,   149,   150,
-     151,   152,   153,   154,   155,   156,   157,   158,   159,   160,
-     161,   162,   163,   164,   165,   166,   167,   168,   169,   170,
-     171,   172,   173,   174,   175,   176,   177,   178,   179,   180,
-     181,   182,   183,   184,   185,   186,   187,   188,   189,   190,
-     191,   192,   193,   194,   195,   196,   197,   198,   199,   200,
-     201,   202,   203,   204,   205,   206,   207,   208,   209,   210,
-     211,   212,   213,   214,   215,   216,   217,   218,   219,   220,
-     221,   222,   223,   224,   225,   226,   227,   228,   229,   230,
-     231,   232,   233,   234,   235,   236,   237,   238,   239,   240,
-     241,   242,   243,   244,   245,   246,   247,   248,   249,   250,
-     251,   252,   253,   254,   255,   256,   257,   258,   259,   260,
-     261,   262,   263,   264,   265,   266,   267,   268,   269,   270,
-     271,   272,   273,   274,   275,   276,   277,   278,   279,   280,
-     281,   282,   283,   284,   285,   286,   287,   288,   289,   290,
-       0,     0,   414,   415,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,   435,   436,   437,   438,   439,
+     440,   441,   442,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,   325,     2,     3,
+       4,     5,     6,     7,     8,     9,    10,    11,    12,    13,
+      14,    15,    16,    17,    18,    19,    20,    21,    22,    23,
+      24,    25,    26,    27,    28,    29,    30,    31,    32,    33,
+      34,    35,    36,    37,    38,    39,    40,    41,    42,    43,
+      44,    45,    46,    47,    48,    49,    50,    51,    52,    53,
+      54,    55,    56,    57,    58,     0,     0,    61,    62,    63,
+      64,    65,    66,    67,    68,    69,    70,    71,    72,    73,
+      74,    75,    76,    77,    78,    79,    80,    81,    82,    83,
+      84,    85,    86,    87,    88,    89,    90,    91,    92,    93,
+      94,    95,    96,    97,    98,    99,   100,   101,   102,   103,
+     104,   105,   106,   107,   108,   109,   110,   111,   112,   113,
+     114,   115,   116,   117,   118,   119,   120,   121,   122,   123,
+     124,   125,   126,   127,   128,   129,   130,   131,   132,   133,
+     134,   135,   136,   137,   138,   139,   140,   141,   142,   143,
+     144,   145,   146,   147,   148,   149,   150,   151,   152,   153,
+     154,   155,   156,   157,   158,   159,   160,   161,   162,   163,
+     164,   165,   166,   167,   168,   169,   170,   171,   172,   173,
+     174,   175,   176,   177,   178,   179,   180,   181,   182,   183,
+     184,   185,   186,   187,   188,   189,   190,   191,   192,   193,
+     194,   195,   196,   197,   198,   199,   200,   201,   202,   203,
+     204,   205,   206,   207,   208,   209,   210,   211,   212,   213,
+     214,   215,   216,   217,   218,   219,   220,   221,   222,   223,
+     224,   225,   226,   227,   228,   229,   230,   231,   232,   233,
+     234,   235,   236,   237,   238,   239,   240,   241,   242,   243,
+     244,   245,   246,   247,   248,   249,   250,   251,   252,   253,
+     254,   255,   256,   257,   258,   259,   260,   261,   262,   263,
+     264,   265,   266,   267,   268,   269,   270,   271,   272,   273,
+     274,   275,   276,   277,   278,   279,   280,   281,   282,   283,
+     284,   285,   286,   287,   288,   289,   290,   291,   292,     0,
+       0,   422,   423,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,   416,   417,     0,     0,   462,     0,     0,     0,     0,
-       0,     0,     0,   418,   419,   420,   421,     0,     0,     0,
+     424,   425,     0,     0,   470,     0,     0,     0,     0,     0,
+       0,     0,   426,   427,   428,   429,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,   422,   423,   424,   425,   426,   297,
-       0,     0,     0,     0,   302,   303,     0,     0,     0,     0,
+       0,     0,     0,   430,   431,   432,   433,   434,   299,     0,
+       0,     0,     0,   304,   305,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,   427,   428,   429,   430,   431,   432,
-     433,   434,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,   318,     2,     3,     4,     5,     6,     7,     8,     9,
-      10,    11,    12,    13,    14,    15,    16,    17,    18,    19,
-      20,    21,    22,    23,    24,    25,    26,    27,    28,    29,
-      30,    31,    32,    33,    34,    35,    36,    37,    38,    39,
-      40,    41,    42,    43,    44,    45,    46,    47,    48,    49,
-      50,    51,    52,    53,    54,    55,    56,    57,    58,     0,
-       0,    61,    62,    63,    64,    65,    66,    67,    68,    69,
-      70,    71,    72,    73,    74,    75,    76,    77,    78,    79,
-      80,    81,    82,    83,    84,    85,    86,    87,    88,    89,
-      90,    91,    92,    93,    94,    95,    96,    97,    98,    99,
-     100,   101,   102,   103,   104,   105,   106,   107,   108,   109,
-     110,   111,   112,   113,   114,   115,   116,   117,   118,   119,
-     120,   121,   122,   123,   124,   125,   126,   127,   128,   129,
-     130,   131,   132,   133,   134,   135,   136,   137,   138,   139,
-     140,   141,   142,   143,   144,   145,   146,   147,   148,   149,
-     150,   151,   152,   153,   154,   155,   156,   157,   158,   159,
-     160,   161,   162,   163,   164,   165,   166,   167,   168,   169,
-     170,   171,   172,   173,   174,   175,   176,   177,   178,   179,
-     180,   181,   182,   183,   184,   185,   186,   187,   188,   189,
-     190,   191,   192,   193,   194,   195,   196,   197,   198,   199,
-     200,   201,   202,   203,   204,   205,   206,   207,   208,   209,
-     210,   211,   212,   213,   214,   215,   216,   217,   218,   219,
-     220,   221,   222,   223,   224,   225,   226,   227,   228,   229,
-     230,   231,   232,   233,   234,   235,   236,   237,   238,   239,
-     240,   241,   242,   243,   244,   245,   246,   247,   248,   249,
-     250,   251,   252,   253,   254,   255,   256,   257,   258,   259,
-     260,   261,   262,   263,   264,   265,   266,   267,   268,   269,
-     270,   271,   272,   273,   274,   275,   276,   277,   278,   279,
-     280,   281,   282,   283,   284,   285,   286,   287,   288,   289,
-     290,     0,     0,   414,   415,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,   416,   417,     0,     0,     0,   521,     0,     0,
-       0,     0,     0,     0,   418,   419,   420,   421,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,   422,   423,   424,   425,   426,
-     297,     0,     0,     0,     0,   302,   303,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,   427,   428,   429,   430,   431,
-     432,   433,   434,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,   318,     2,     3,     4,     5,     6,     7,     8,
-       9,    10,    11,    12,    13,    14,    15,    16,    17,    18,
-      19,    20,    21,    22,    23,    24,    25,    26,    27,    28,
-      29,    30,    31,    32,    33,    34,    35,    36,    37,    38,
-      39,    40,    41,    42,    43,    44,    45,    46,    47,    48,
-      49,    50,    51,    52,    53,    54,    55,    56,    57,    58,
-       0,     0,    61,    62,    63,    64,    65,    66,    67,    68,
-      69,    70,    71,    72,    73,    74,    75,    76,    77,    78,
-      79,    80,    81,    82,    83,    84,    85,    86,    87,    88,
-      89,    90,    91,    92,    93,    94,    95,    96,    97,    98,
-      99,   100,   101,   102,   103,   104,   105,   106,   107,   108,
-     109,   110,   111,   112,   113,   114,   115,   116,   117,   118,
-     119,   120,   121,   122,   123,   124,   125,   126,   127,   128,
-     129,   130,   131,   132,   133,   134,   135,   136,   137,   138,
-     139,   140,   141,   142,   143,   144,   145,   146,   147,   148,
-     149,   150,   151,   152,   153,   154,   155,   156,   157,   158,
-     159,   160,   161,   162,   163,   164,   165,   166,   167,   168,
-     169,   170,   171,   172,   173,   174,   175,   176,   177,   178,
-     179,   180,   181,   182,   183,   184,   185,   186,   187,   188,
-     189,   190,   191,   192,   193,   194,   195,   196,   197,   198,
-     199,   200,   201,   202,   203,   204,   205,   206,   207,   208,
-     209,   210,   211,   212,   213,   214,   215,   216,   217,   218,
-     219,   220,   221,   222,   223,   224,   225,   226,   227,   228,
-     229,   230,   231,   232,   233,   234,   235,   236,   237,   238,
-     239,   240,   241,   242,   243,   244,   245,   246,   247,   248,
-     249,   250,   251,   252,   253,   254,   255,   256,   257,   258,
-     259,   260,   261,   262,   263,   264,   265,   266,   267,   268,
-     269,   270,   271,   272,   273,   274,   275,   276,   277,   278,
-     279,   280,   281,   282,   283,   284,   285,   286,   287,   288,
-     289,   290,     0,     0,   414,   415,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,   416,   417,     0,     0,   577,     0,     0,
-       0,     0,     0,     0,     0,   418,   419,   420,   421,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,   422,   423,   424,   425,
-     426,   297,     0,     0,     0,     0,   302,   303,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,   427,   428,   429,   430,
-     431,   432,   433,   434,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,   318,     2,     3,     4,     5,     6,     7,
-       8,     9,    10,    11,    12,    13,    14,    15,    16,    17,
-      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
-      28,    29,    30,    31,    32,    33,    34,    35,    36,    37,
-      38,    39,    40,    41,    42,    43,    44,    45,    46,    47,
-      48,    49,    50,    51,    52,    53,    54,    55,    56,    57,
-      58,     0,     0,    61,    62,    63,    64,    65,    66,    67,
-      68,    69,    70,    71,    72,    73,    74,    75,    76,    77,
-      78,    79,    80,    81,    82,    83,    84,    85,    86,    87,
-      88,    89,    90,    91,    92,    93,    94,    95,    96,    97,
-      98,    99,   100,   101,   102,   103,   104,   105,   106,   107,
-     108,   109,   110,   111,   112,   113,   114,   115,   116,   117,
-     118,   119,   120,   121,   122,   123,   124,   125,   126,   127,
-     128,   129,   130,   131,   132,   133,   134,   135,   136,   137,
-     138,   139,   140,   141,   142,   143,   144,   145,   146,   147,
-     148,   149,   150,   151,   152,   153,   154,   155,   156,   157,
-     158,   159,   160,   161,   162,   163,   164,   165,   166,   167,
-     168,   169,   170,   171,   172,   173,   174,   175,   176,   177,
-     178,   179,   180,   181,   182,   183,   184,   185,   186,   187,
-     188,   189,   190,   191,   192,   193,   194,   195,   196,   197,
-     198,   199,   200,   201,   202,   203,   204,   205,   206,   207,
-     208,   209,   210,   211,   212,   213,   214,   215,   216,   217,
-     218,   219,   220,   221,   222,   223,   224,   225,   226,   227,
-     228,   229,   230,   231,   232,   233,   234,   235,   236,   237,
-     238,   239,   240,   241,   242,   243,   244,   245,   246,   247,
-     248,   249,   250,   251,   252,   253,   254,   255,   256,   257,
-     258,   259,   260,   261,   262,   263,   264,   265,   266,   267,
-     268,   269,   270,   271,   272,   273,   274,   275,   276,   277,
-     278,   279,   280,   281,   282,   283,   284,   285,   286,   287,
-     288,   289,   290,     0,     0,   414,   415,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,   416,   417,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,   589,   418,   419,   420,   421,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,   422,   423,   424,
-     425,   426,   297,     0,     0,     0,     0,   302,   303,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,   427,   428,   429,
-     430,   431,   432,   433,   434,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,   318,     2,     3,     4,     5,     6,
-       7,     8,     9,    10,    11,    12,    13,    14,    15,    16,
-      17,    18,    19,    20,    21,    22,    23,    24,    25,    26,
-      27,    28,    29,    30,    31,    32,    33,    34,    35,    36,
-      37,    38,    39,    40,    41,    42,    43,    44,    45,    46,
-      47,    48,    49,    50,    51,    52,    53,    54,    55,    56,
-      57,    58,     0,     0,    61,    62,    63,    64,    65,    66,
-      67,    68,    69,    70,    71,    72,    73,    74,    75,    76,
-      77,    78,    79,    80,    81,    82,    83,    84,    85,    86,
-      87,    88,    89,    90,    91,    92,    93,    94,    95,    96,
-      97,    98,    99,   100,   101,   102,   103,   104,   105,   106,
-     107,   108,   109,   110,   111,   112,   113,   114,   115,   116,
-     117,   118,   119,   120,   121,   122,   123,   124,   125,   126,
-     127,   128,   129,   130,   131,   132,   133,   134,   135,   136,
-     137,   138,   139,   140,   141,   142,   143,   144,   145,   146,
-     147,   148,   149,   150,   151,   152,   153,   154,   155,   156,
-     157,   158,   159,   160,   161,   162,   163,   164,   165,   166,
-     167,   168,   169,   170,   171,   172,   173,   174,   175,   176,
-     177,   178,   179,   180,   181,   182,   183,   184,   185,   186,
-     187,   188,   189,   190,   191,   192,   193,   194,   195,   196,
-     197,   198,   199,   200,   201,   202,   203,   204,   205,   206,
-     207,   208,   209,   210,   211,   212,   213,   214,   215,   216,
-     217,   218,   219,   220,   221,   222,   223,   224,   225,   226,
-     227,   228,   229,   230,   231,   232,   233,   234,   235,   236,
-     237,   238,   239,   240,   241,   242,   243,   244,   245,   246,
-     247,   248,   249,   250,   251,   252,   253,   254,   255,   256,
-     257,   258,   259,   260,   261,   262,   263,   264,   265,   266,
-     267,   268,   269,   270,   271,   272,   273,   274,   275,   276,
-     277,   278,   279,   280,   281,   282,   283,   284,   285,   286,
-     287,   288,   289,   290,     0,     0,   414,   415,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,   416,   417,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,   418,   419,   420,
-     421,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,   422,   423,
-     424,   425,   426,   297,     0,     0,     0,     0,   302,   303,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,   427,   428,
-     429,   430,   431,   432,   433,   434,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,   318,     2,     3,     4,     5,
+       0,     0,     0,   435,   436,   437,   438,   439,   440,   441,
+     442,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,   325,     2,     3,     4,     5,
        6,     7,     8,     9,    10,    11,    12,    13,    14,    15,
       16,    17,    18,    19,    20,    21,    22,    23,    24,    25,
       26,    27,    28,    29,    30,    31,    32,    33,    34,    35,
@@ -2307,26 +2179,186 @@
      256,   257,   258,   259,   260,   261,   262,   263,   264,   265,
      266,   267,   268,   269,   270,   271,   272,   273,   274,   275,
      276,   277,   278,   279,   280,   281,   282,   283,   284,   285,
-     286,   287,   288,   289,   290,   445,     0,   414,   415,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,   463,
-       0,     0,     0,     0,     0,     0,   416,   417,     0,     0,
-       0,     0,     0,     0,     0,     0,   529,   530,   418,   419,
-     420,   421,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,   422,
-     423,   424,   425,   426,   297,     0,     0,     0,   542,   302,
-     539,     0,     0,     0,     0,     0,     0,     0,     0,   463,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,   427,
-     428,   429,   430,   431,   432,   433,   434,     0,   463,     0,
-       0,     0,     0,     0,     0,     0,   318,     0,     0,     0,
+     286,   287,   288,   289,   290,   291,   292,     0,     0,   422,
+     423,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,   424,   425,
+       0,     0,     0,   529,     0,     0,     0,     0,     0,     0,
+     426,   427,   428,   429,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,   430,   431,   432,   433,   434,   299,     0,     0,     0,
+       0,   304,   305,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,   435,   436,   437,   438,   439,   440,   441,   442,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,   325,     2,     3,     4,     5,     6,     7,
+       8,     9,    10,    11,    12,    13,    14,    15,    16,    17,
+      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
+      28,    29,    30,    31,    32,    33,    34,    35,    36,    37,
+      38,    39,    40,    41,    42,    43,    44,    45,    46,    47,
+      48,    49,    50,    51,    52,    53,    54,    55,    56,    57,
+      58,     0,     0,    61,    62,    63,    64,    65,    66,    67,
+      68,    69,    70,    71,    72,    73,    74,    75,    76,    77,
+      78,    79,    80,    81,    82,    83,    84,    85,    86,    87,
+      88,    89,    90,    91,    92,    93,    94,    95,    96,    97,
+      98,    99,   100,   101,   102,   103,   104,   105,   106,   107,
+     108,   109,   110,   111,   112,   113,   114,   115,   116,   117,
+     118,   119,   120,   121,   122,   123,   124,   125,   126,   127,
+     128,   129,   130,   131,   132,   133,   134,   135,   136,   137,
+     138,   139,   140,   141,   142,   143,   144,   145,   146,   147,
+     148,   149,   150,   151,   152,   153,   154,   155,   156,   157,
+     158,   159,   160,   161,   162,   163,   164,   165,   166,   167,
+     168,   169,   170,   171,   172,   173,   174,   175,   176,   177,
+     178,   179,   180,   181,   182,   183,   184,   185,   186,   187,
+     188,   189,   190,   191,   192,   193,   194,   195,   196,   197,
+     198,   199,   200,   201,   202,   203,   204,   205,   206,   207,
+     208,   209,   210,   211,   212,   213,   214,   215,   216,   217,
+     218,   219,   220,   221,   222,   223,   224,   225,   226,   227,
+     228,   229,   230,   231,   232,   233,   234,   235,   236,   237,
+     238,   239,   240,   241,   242,   243,   244,   245,   246,   247,
+     248,   249,   250,   251,   252,   253,   254,   255,   256,   257,
+     258,   259,   260,   261,   262,   263,   264,   265,   266,   267,
+     268,   269,   270,   271,   272,   273,   274,   275,   276,   277,
+     278,   279,   280,   281,   282,   283,   284,   285,   286,   287,
+     288,   289,   290,   291,   292,     0,     0,   422,   423,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,   424,   425,     0,     0,
+     585,     0,     0,     0,     0,     0,     0,     0,   426,   427,
+     428,   429,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,   430,
+     431,   432,   433,   434,   299,     0,     0,     0,     0,   304,
+     305,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,   435,
+     436,   437,   438,   439,   440,   441,   442,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,   325,     2,     3,     4,     5,     6,     7,     8,     9,
+      10,    11,    12,    13,    14,    15,    16,    17,    18,    19,
+      20,    21,    22,    23,    24,    25,    26,    27,    28,    29,
+      30,    31,    32,    33,    34,    35,    36,    37,    38,    39,
+      40,    41,    42,    43,    44,    45,    46,    47,    48,    49,
+      50,    51,    52,    53,    54,    55,    56,    57,    58,     0,
+       0,    61,    62,    63,    64,    65,    66,    67,    68,    69,
+      70,    71,    72,    73,    74,    75,    76,    77,    78,    79,
+      80,    81,    82,    83,    84,    85,    86,    87,    88,    89,
+      90,    91,    92,    93,    94,    95,    96,    97,    98,    99,
+     100,   101,   102,   103,   104,   105,   106,   107,   108,   109,
+     110,   111,   112,   113,   114,   115,   116,   117,   118,   119,
+     120,   121,   122,   123,   124,   125,   126,   127,   128,   129,
+     130,   131,   132,   133,   134,   135,   136,   137,   138,   139,
+     140,   141,   142,   143,   144,   145,   146,   147,   148,   149,
+     150,   151,   152,   153,   154,   155,   156,   157,   158,   159,
+     160,   161,   162,   163,   164,   165,   166,   167,   168,   169,
+     170,   171,   172,   173,   174,   175,   176,   177,   178,   179,
+     180,   181,   182,   183,   184,   185,   186,   187,   188,   189,
+     190,   191,   192,   193,   194,   195,   196,   197,   198,   199,
+     200,   201,   202,   203,   204,   205,   206,   207,   208,   209,
+     210,   211,   212,   213,   214,   215,   216,   217,   218,   219,
+     220,   221,   222,   223,   224,   225,   226,   227,   228,   229,
+     230,   231,   232,   233,   234,   235,   236,   237,   238,   239,
+     240,   241,   242,   243,   244,   245,   246,   247,   248,   249,
+     250,   251,   252,   253,   254,   255,   256,   257,   258,   259,
+     260,   261,   262,   263,   264,   265,   266,   267,   268,   269,
+     270,   271,   272,   273,   274,   275,   276,   277,   278,   279,
+     280,   281,   282,   283,   284,   285,   286,   287,   288,   289,
+     290,   291,   292,     0,     0,   422,   423,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,   424,   425,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,   597,   426,   427,   428,   429,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,   430,   431,   432,
+     433,   434,   299,     0,     0,     0,     0,   304,   305,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,   435,   436,   437,
+     438,   439,   440,   441,   442,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,   325,
+       2,     3,     4,     5,     6,     7,     8,     9,    10,    11,
+      12,    13,    14,    15,    16,    17,    18,    19,    20,    21,
+      22,    23,    24,    25,    26,    27,    28,    29,    30,    31,
+      32,    33,    34,    35,    36,    37,    38,    39,    40,    41,
+      42,    43,    44,    45,    46,    47,    48,    49,    50,    51,
+      52,    53,    54,    55,    56,    57,    58,     0,     0,    61,
+      62,    63,    64,    65,    66,    67,    68,    69,    70,    71,
+      72,    73,    74,    75,    76,    77,    78,    79,    80,    81,
+      82,    83,    84,    85,    86,    87,    88,    89,    90,    91,
+      92,    93,    94,    95,    96,    97,    98,    99,   100,   101,
+     102,   103,   104,   105,   106,   107,   108,   109,   110,   111,
+     112,   113,   114,   115,   116,   117,   118,   119,   120,   121,
+     122,   123,   124,   125,   126,   127,   128,   129,   130,   131,
+     132,   133,   134,   135,   136,   137,   138,   139,   140,   141,
+     142,   143,   144,   145,   146,   147,   148,   149,   150,   151,
+     152,   153,   154,   155,   156,   157,   158,   159,   160,   161,
+     162,   163,   164,   165,   166,   167,   168,   169,   170,   171,
+     172,   173,   174,   175,   176,   177,   178,   179,   180,   181,
+     182,   183,   184,   185,   186,   187,   188,   189,   190,   191,
+     192,   193,   194,   195,   196,   197,   198,   199,   200,   201,
+     202,   203,   204,   205,   206,   207,   208,   209,   210,   211,
+     212,   213,   214,   215,   216,   217,   218,   219,   220,   221,
+     222,   223,   224,   225,   226,   227,   228,   229,   230,   231,
+     232,   233,   234,   235,   236,   237,   238,   239,   240,   241,
+     242,   243,   244,   245,   246,   247,   248,   249,   250,   251,
+     252,   253,   254,   255,   256,   257,   258,   259,   260,   261,
+     262,   263,   264,   265,   266,   267,   268,   269,   270,   271,
+     272,   273,   274,   275,   276,   277,   278,   279,   280,   281,
+     282,   283,   284,   285,   286,   287,   288,   289,   290,   291,
+     292,     0,     0,   422,   423,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,   424,   425,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,   426,   427,   428,   429,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,   430,   431,   432,   433,   434,
+     299,     0,     0,     0,     0,   304,   305,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,   435,   436,   437,   438,   439,
+     440,   441,   442,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,   325,     2,     3,
+       4,     5,     6,     7,     8,     9,    10,    11,    12,    13,
+      14,    15,    16,    17,    18,    19,    20,    21,    22,    23,
+      24,    25,    26,    27,    28,    29,    30,    31,    32,    33,
+      34,    35,    36,    37,    38,    39,    40,    41,    42,    43,
+      44,    45,    46,    47,    48,    49,    50,    51,    52,    53,
+      54,    55,    56,    57,    58,     0,     0,    61,    62,    63,
+      64,    65,    66,    67,    68,    69,    70,    71,    72,    73,
+      74,    75,    76,    77,    78,    79,    80,    81,    82,    83,
+      84,    85,    86,    87,    88,    89,    90,    91,    92,    93,
+      94,    95,    96,    97,    98,    99,   100,   101,   102,   103,
+     104,   105,   106,   107,   108,   109,   110,   111,   112,   113,
+     114,   115,   116,   117,   118,   119,   120,   121,   122,   123,
+     124,   125,   126,   127,   128,   129,   130,   131,   132,   133,
+     134,   135,   136,   137,   138,   139,   140,   141,   142,   143,
+     144,   145,   146,   147,   148,   149,   150,   151,   152,   153,
+     154,   155,   156,   157,   158,   159,   160,   161,   162,   163,
+     164,   165,   166,   167,   168,   169,   170,   171,   172,   173,
+     174,   175,   176,   177,   178,   179,   180,   181,   182,   183,
+     184,   185,   186,   187,   188,   189,   190,   191,   192,   193,
+     194,   195,   196,   197,   198,   199,   200,   201,   202,   203,
+     204,   205,   206,   207,   208,   209,   210,   211,   212,   213,
+     214,   215,   216,   217,   218,   219,   220,   221,   222,   223,
+     224,   225,   226,   227,   228,   229,   230,   231,   232,   233,
+     234,   235,   236,   237,   238,   239,   240,   241,   242,   243,
+     244,   245,   246,   247,   248,   249,   250,   251,   252,   253,
+     254,   255,   256,   257,   258,   259,   260,   261,   262,   263,
+     264,   265,   266,   267,   268,   269,   270,   271,   272,   273,
+     274,   275,   276,   277,   278,   279,   280,   281,   282,   283,
+     284,   285,   286,   287,   288,   289,   290,   291,   292,   453,
+       0,   422,   423,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,   471,     0,     0,     0,     0,     0,     0,
+     424,   425,     0,     0,     0,     0,     0,     0,     0,     0,
+     537,   538,   426,   427,   428,   429,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,   430,   431,   432,   433,   434,   299,     0,
+       0,     0,   550,   304,   547,     0,     0,     0,     0,     0,
+       0,     0,     0,   471,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,   435,   436,   437,   438,   439,   440,   441,
+     442,     0,   471,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,   325,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,   634,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,   626,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,   632,   633,
-     634,   463,   463,   463,   463,   463,   463,   463,   463,   463,
-     463,   463,   463,   463,   463,   463,   463,     0,     0,     0,
+       0,     0,   640,   641,   642,   471,   471,   471,   471,   471,
+     471,   471,   471,   471,   471,   471,   471,   471,   471,   471,
+     471,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
@@ -2336,167 +2368,86 @@
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,   463
+     471
 };
 
 static const yytype_int16 yycheck[] =
 {
-       0,   317,     0,   456,     0,   317,   316,   318,   324,     0,
-     315,   322,   322,   325,     4,     5,     6,     7,     8,     9,
-      10,    11,    12,    13,    14,    15,    16,    17,    18,    19,
-      20,    21,    22,    23,    24,    25,    26,    27,    28,    29,
-      30,    31,    32,    33,    34,    35,    36,    37,    38,    39,
-      40,    41,    42,    43,    44,    45,    46,    47,    48,    49,
-      50,    51,    52,    53,    54,    55,    56,    57,    58,    59,
-      60,   315,   525,    63,    64,    65,    66,    67,    68,    69,
-      70,    71,    72,    73,    74,    75,    76,    77,    78,    79,
-      80,    81,    82,    83,    84,    85,    86,    87,    88,    89,
-      90,    91,    92,    93,    94,    95,    96,    97,    98,    99,
-     100,   101,   102,   103,   104,   105,   106,   107,   108,   109,
-     110,   111,   112,   113,   114,   115,   116,   117,   118,   119,
-     120,   121,   122,   123,   124,   125,   126,   127,   128,   129,
-     130,   131,   132,   133,   134,   135,   136,   137,   138,   139,
-     140,   141,   142,   143,   144,   145,   146,   147,   148,   149,
-     150,   151,   152,   153,   154,   155,   156,   157,   158,   159,
-     160,   161,   162,   163,   164,   165,   166,   167,   168,   169,
-     170,   171,   172,   173,   174,   175,   176,   177,   178,   179,
-     180,   181,   182,   183,   184,   185,   186,   187,   188,   189,
-     190,   191,   192,   193,   194,   195,   196,   197,   198,   199,
-     200,   201,   202,   203,   204,   205,   206,   207,   208,   209,
-     210,   211,   212,   213,   214,   215,   216,   217,   218,   219,
-     220,   221,   222,   223,   224,   225,   226,   227,   228,   229,
-     230,   231,   232,   233,   234,   235,   236,   237,   238,   239,
-     240,   241,   242,   243,   244,   245,   246,   247,   248,   249,
-     250,   251,   252,   253,   254,   255,   256,   257,   258,   259,
-     260,   261,   262,   263,   264,   265,   266,   267,   268,   269,
-     270,   271,   272,   273,   274,   275,   276,   277,   278,   279,
-     280,   281,   282,   283,   284,   285,   286,   287,   288,   289,
-     290,   291,   292,   349,   341,   408,   417,   581,   519,   507,
-     521,   397,   319,   524,   454,   378,   351,   297,   298,   302,
-     657,   384,   315,   322,   317,   295,   296,   316,   374,   317,
-     325,   324,   317,   370,   351,   334,   324,   372,   317,   324,
-     443,   341,   405,   406,   351,   315,   325,   317,   685,   349,
-     341,   321,   389,   333,   334,   338,   351,   357,   349,   357,
-     360,   357,   352,   316,   293,   294,   357,   357,   358,   322,
-     370,   457,   322,   322,   374,   696,   325,   325,   489,   370,
-     491,   322,   703,   374,   325,   319,   316,   585,   322,   389,
-     476,   325,   322,   714,   299,   300,   359,   316,   389,   362,
-     400,   364,   365,   322,   615,   368,   452,   316,   316,   400,
-     333,   551,   322,   322,   322,   325,   519,   454,   521,   456,
-     327,   524,   329,   534,   319,   304,   305,   306,   307,   308,
-     309,   310,   311,   312,   313,   538,   316,   563,   564,   565,
-     566,   319,   322,   325,   718,   324,   322,   322,   322,   325,
-     325,   325,   452,   320,   454,   322,   456,   668,   656,   322,
-     323,   452,   351,   454,   351,   456,   351,   340,   341,   342,
-     330,   331,   332,   322,   323,   317,   587,   559,   560,   619,
-     591,   561,   562,   546,   567,   568,   324,   351,   525,   316,
-     315,   317,   351,   351,   337,   336,   335,   708,   301,   303,
-     318,   317,   315,   606,   607,   320,   325,   507,   325,   315,
-     315,   325,   615,   315,   551,   323,   507,   315,   325,   315,
-     351,   351,   316,   318,   315,   525,   724,   351,   318,   322,
-     359,   318,   320,   316,   525,   315,   325,   319,   316,   351,
-     651,   316,   363,   324,   320,   319,   657,   319,   325,   569,
-     571,   551,   570,   572,   674,   459,   296,   573,   545,   574,
-     551,   370,   629,   374,   374,   668,   659,   702,   714,   368,
-     715,   659,   517,   685,   685,   517,   676,   517,   357,    -1,
-      -1,   581,   619,    -1,    -1,   585,   697,   690,   674,    -1,
-     581,    -1,    -1,    -1,   585,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,   713,    -1,    -1,   708,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   619,
-     657,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   619,    -1,
-      -1,    -1,    -1,    -1,   680,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   685,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,   656,   657,    -1,   659,
-      -1,    -1,    -1,    -1,    -1,   656,   657,    -1,   659,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-     680,    -1,    -1,    -1,    -1,   685,    -1,    -1,    -1,   680,
-      -1,    -1,    -1,    -1,   685,    -1,   696,    -1,    -1,    -1,
-      -1,    -1,    -1,   703,    -1,   696,    -1,    -1,    -1,    -1,
-      -1,    -1,   703,    -1,   714,    -1,    -1,    -1,   718,    -1,
-      -1,    -1,    -1,   714,   724,    -1,    -1,   718,    -1,    -1,
-      -1,     0,    -1,   724,     3,     4,     5,     6,     7,     8,
-       9,    10,    11,    12,    13,    14,    15,    16,    17,    18,
-      19,    20,    21,    22,    23,    24,    25,    26,    27,    28,
-      29,    30,    31,    32,    33,    34,    35,    36,    37,    38,
-      39,    40,    41,    42,    43,    44,    45,    46,    47,    48,
-      49,    50,    51,    52,    53,    54,    55,    56,    57,    58,
-      59,    60,    61,    62,    63,    64,    65,    66,    67,    68,
-      69,    70,    71,    72,    73,    74,    75,    76,    77,    78,
-      79,    80,    81,    82,    83,    84,    85,    86,    87,    88,
-      89,    90,    91,    92,    93,    94,    95,    96,    97,    98,
-      99,   100,   101,   102,   103,   104,   105,   106,   107,   108,
-     109,   110,   111,   112,   113,   114,   115,   116,   117,   118,
-     119,   120,   121,   122,   123,   124,   125,   126,   127,   128,
-     129,   130,   131,   132,   133,   134,   135,   136,   137,   138,
-     139,   140,   141,   142,   143,   144,   145,   146,   147,   148,
-     149,   150,   151,   152,   153,   154,   155,   156,   157,   158,
-     159,   160,   161,   162,   163,   164,   165,   166,   167,   168,
-     169,   170,   171,   172,   173,   174,   175,   176,   177,   178,
-     179,   180,   181,   182,   183,   184,   185,   186,   187,   188,
-     189,   190,   191,   192,   193,   194,   195,   196,   197,   198,
-     199,   200,   201,   202,   203,   204,   205,   206,   207,   208,
-     209,   210,   211,   212,   213,   214,   215,   216,   217,   218,
-     219,   220,   221,   222,   223,   224,   225,   226,   227,   228,
-     229,   230,   231,   232,   233,   234,   235,   236,   237,   238,
-     239,   240,   241,   242,   243,   244,   245,   246,   247,   248,
-     249,   250,   251,   252,   253,   254,   255,   256,   257,   258,
-     259,   260,   261,   262,   263,   264,   265,   266,   267,   268,
-     269,   270,   271,   272,   273,   274,   275,   276,   277,   278,
-     279,   280,   281,   282,   283,   284,   285,   286,   287,   288,
-     289,   290,   291,   292,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,   325,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-     339,   340,   341,   342,   343,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,   352,   353,   354,   355,   356,   357,   358,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,   371,   372,   373,   374,   375,   376,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,   385,    -1,   387,   388,
-     389,   390,   391,   392,   393,   394,   395,   396,   397,   398,
-     399,   400,   401,   402,   403,   404,   405,   406,   407,   408,
-     409,   410,   411,     3,     4,     5,     6,     7,     8,     9,
-      10,    11,    12,    13,    14,    15,    16,    17,    18,    19,
-      20,    21,    22,    23,    24,    25,    26,    27,    28,    29,
-      30,    31,    32,    33,    34,    35,    36,    37,    38,    39,
-      40,    41,    42,    43,    44,    45,    46,    47,    48,    49,
-      50,    51,    52,    53,    54,    55,    56,    57,    58,    59,
-      60,    61,    62,    63,    64,    65,    66,    67,    68,    69,
-      70,    71,    72,    73,    74,    75,    76,    77,    78,    79,
-      80,    81,    82,    83,    84,    85,    86,    87,    88,    89,
-      90,    91,    92,    93,    94,    95,    96,    97,    98,    99,
-     100,   101,   102,   103,   104,   105,   106,   107,   108,   109,
-     110,   111,   112,   113,   114,   115,   116,   117,   118,   119,
-     120,   121,   122,   123,   124,   125,   126,   127,   128,   129,
-     130,   131,   132,   133,   134,   135,   136,   137,   138,   139,
-     140,   141,   142,   143,   144,   145,   146,   147,   148,   149,
-     150,   151,   152,   153,   154,   155,   156,   157,   158,   159,
-     160,   161,   162,   163,   164,   165,   166,   167,   168,   169,
-     170,   171,   172,   173,   174,   175,   176,   177,   178,   179,
-     180,   181,   182,   183,   184,   185,   186,   187,   188,   189,
-     190,   191,   192,   193,   194,   195,   196,   197,   198,   199,
-     200,   201,   202,   203,   204,   205,   206,   207,   208,   209,
-     210,   211,   212,   213,   214,   215,   216,   217,   218,   219,
-     220,   221,   222,   223,   224,   225,   226,   227,   228,   229,
-     230,   231,   232,   233,   234,   235,   236,   237,   238,   239,
-     240,   241,   242,   243,   244,   245,   246,   247,   248,   249,
-     250,   251,   252,   253,   254,   255,   256,   257,   258,   259,
-     260,   261,   262,   263,   264,   265,   266,   267,   268,   269,
-     270,   271,   272,   273,   274,   275,   276,   277,   278,   279,
-     280,   281,   282,   283,   284,   285,   286,   287,   288,   289,
-     290,   291,   292,    -1,    -1,   295,   296,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,   314,   315,    -1,   317,    -1,   319,
-     320,    -1,    -1,    -1,    -1,   325,   326,   327,   328,   329,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   339,
-     340,   341,   342,   343,    -1,    -1,    -1,   347,   348,   349,
-     350,   351,   352,   353,   354,   355,   356,   357,   358,   359,
-     360,   361,   362,    -1,   364,   365,   366,   367,   368,   369,
-     370,   371,   372,   373,   374,   375,   376,   377,   378,   379,
-     380,   381,   382,   383,   384,   385,   386,   387,   388,   389,
-     390,   391,   392,   393,   394,   395,   396,   397,   398,   399,
-     400,   401,   402,   403,   404,   405,   406,   407,   408,   409,
-     410,   411,     3,     4,     5,     6,     7,     8,     9,    10,
+       0,   324,     0,   317,     0,   319,   319,   319,   464,     0,
+     319,   319,   326,   336,   327,   327,   317,   326,   326,   317,
+       4,     5,     6,     7,     8,     9,    10,    11,    12,    13,
+      14,    15,    16,    17,    18,    19,    20,    21,    22,    23,
+      24,    25,    26,    27,    28,    29,    30,    31,    32,    33,
+      34,    35,    36,    37,    38,    39,    40,    41,    42,    43,
+      44,    45,    46,    47,    48,    49,    50,    51,    52,    53,
+      54,    55,    56,    57,    58,    59,    60,   533,   327,    63,
+      64,    65,    66,    67,    68,    69,    70,    71,    72,    73,
+      74,    75,    76,    77,    78,    79,    80,    81,    82,    83,
+      84,    85,    86,    87,    88,    89,    90,    91,    92,    93,
+      94,    95,    96,    97,    98,    99,   100,   101,   102,   103,
+     104,   105,   106,   107,   108,   109,   110,   111,   112,   113,
+     114,   115,   116,   117,   118,   119,   120,   121,   122,   123,
+     124,   125,   126,   127,   128,   129,   130,   131,   132,   133,
+     134,   135,   136,   137,   138,   139,   140,   141,   142,   143,
+     144,   145,   146,   147,   148,   149,   150,   151,   152,   153,
+     154,   155,   156,   157,   158,   159,   160,   161,   162,   163,
+     164,   165,   166,   167,   168,   169,   170,   171,   172,   173,
+     174,   175,   176,   177,   178,   179,   180,   181,   182,   183,
+     184,   185,   186,   187,   188,   189,   190,   191,   192,   193,
+     194,   195,   196,   197,   198,   199,   200,   201,   202,   203,
+     204,   205,   206,   207,   208,   209,   210,   211,   212,   213,
+     214,   215,   216,   217,   218,   219,   220,   221,   222,   223,
+     224,   225,   226,   227,   228,   229,   230,   231,   232,   233,
+     234,   235,   236,   237,   238,   239,   240,   241,   242,   243,
+     244,   245,   246,   247,   248,   249,   250,   251,   252,   253,
+     254,   255,   256,   257,   258,   259,   260,   261,   262,   263,
+     264,   265,   266,   267,   268,   269,   270,   271,   272,   273,
+     274,   275,   276,   277,   278,   279,   280,   281,   282,   283,
+     284,   285,   286,   287,   288,   289,   290,   291,   292,   293,
+     294,   357,   349,   416,   425,   589,   527,   515,   529,   405,
+     321,   532,   462,   386,   353,   299,   300,   304,   665,   392,
+     295,   296,   319,   297,   298,   318,   382,   361,   327,   326,
+     364,   378,   366,   367,   324,   374,   370,   327,   451,   349,
+     413,   414,   353,   317,   324,   319,   693,   357,   349,   323,
+     397,   335,   336,   340,   353,   365,   357,   365,   368,   365,
+     354,   318,   301,   302,   365,   359,   360,   324,   378,   465,
+     320,   353,   382,   704,   324,   335,   497,   378,   499,   324,
+     711,   382,   327,   321,   318,   593,   324,   397,   484,   327,
+     324,   722,   321,   318,   318,   318,   397,   318,   408,   324,
+     324,   324,   623,   324,   460,   318,   322,   408,   324,   559,
+     324,   324,   353,   327,   527,   462,   529,   464,   329,   532,
+     331,   542,   321,   306,   307,   308,   309,   310,   311,   312,
+     313,   314,   315,   546,   571,   572,   573,   574,   324,   324,
+     325,   327,   726,   326,   324,   324,   353,   327,   327,   353,
+     460,   319,   462,   327,   464,   676,   664,   324,   325,   460,
+     326,   462,   353,   464,   342,   343,   344,   332,   333,   334,
+     567,   568,   575,   576,   595,   569,   570,   627,   599,   318,
+     317,   554,   353,   319,   353,   339,   533,   338,   337,   303,
+     305,   320,   319,   317,   322,   716,   327,   327,   317,   317,
+     317,   614,   615,   325,   327,   515,   327,   317,   317,   353,
+     623,   353,   559,   318,   515,   353,   320,   320,   324,   317,
+     361,   320,   322,   533,   732,   318,   317,   353,   318,   321,
+     326,   318,   533,   327,   577,   321,   321,   578,   659,   327,
+     365,   322,   579,   581,   665,   580,   582,   682,   382,   559,
+     382,   298,   467,   553,   637,   667,   710,   722,   559,   723,
+     667,   525,   378,   676,   376,   693,   525,   525,   365,   684,
+      -1,    -1,   693,    -1,    -1,    -1,    -1,    -1,    -1,   589,
+     627,    -1,    -1,   593,   705,   698,   682,    -1,   589,    -1,
+      -1,    -1,   593,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+     721,    -1,    -1,   716,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,   627,   665,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,   627,    -1,    -1,    -1,
+      -1,    -1,   688,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,   693,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,   664,   665,    -1,   667,    -1,    -1,
+      -1,    -1,    -1,   664,   665,    -1,   667,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   688,    -1,
+      -1,    -1,    -1,   693,    -1,    -1,    -1,   688,    -1,    -1,
+      -1,    -1,   693,    -1,   704,    -1,    -1,    -1,    -1,    -1,
+      -1,   711,    -1,   704,    -1,    -1,    -1,    -1,    -1,    -1,
+     711,    -1,   722,    -1,    -1,    -1,   726,    -1,    -1,    -1,
+      -1,   722,   732,    -1,    -1,   726,    -1,    -1,    -1,     0,
+      -1,   732,     3,     4,     5,     6,     7,     8,     9,    10,
       11,    12,    13,    14,    15,    16,    17,    18,    19,    20,
       21,    22,    23,    24,    25,    26,    27,    28,    29,    30,
       31,    32,    33,    34,    35,    36,    37,    38,    39,    40,
@@ -2525,59 +2476,144 @@
      261,   262,   263,   264,   265,   266,   267,   268,   269,   270,
      271,   272,   273,   274,   275,   276,   277,   278,   279,   280,
      281,   282,   283,   284,   285,   286,   287,   288,   289,   290,
-     291,   292,    -1,    -1,   295,   296,    -1,    -1,    -1,    -1,
+     291,   292,   293,   294,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,   314,   315,    -1,   317,    -1,   319,   320,
-      -1,    -1,    -1,    -1,   325,   326,   327,   328,   329,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   339,   340,
-     341,   342,   343,    -1,    -1,    -1,   347,   348,   349,   350,
-     351,   352,   353,   354,   355,   356,   357,   358,   359,   360,
-     361,   362,    -1,   364,   365,   366,   367,   368,   369,   370,
-     371,   372,   373,   374,   375,   376,   377,   378,   379,   380,
-     381,   382,   383,   384,   385,   386,   387,   388,   389,   390,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,   327,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+     341,   342,   343,   344,   345,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,   354,   355,   356,   357,   358,   359,   360,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,   373,   374,   375,   376,   377,   378,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,   387,    -1,   389,   390,
      391,   392,   393,   394,   395,   396,   397,   398,   399,   400,
      401,   402,   403,   404,   405,   406,   407,   408,   409,   410,
-     411,     3,     4,     5,     6,     7,     8,     9,    10,    11,
-      12,    13,    14,    15,    16,    17,    18,    19,    20,    21,
-      22,    23,    24,    25,    26,    27,    28,    29,    30,    31,
-      32,    33,    34,    35,    36,    37,    38,    39,    40,    41,
-      42,    43,    44,    45,    46,    47,    48,    49,    50,    51,
-      52,    53,    54,    55,    56,    57,    58,    59,    60,    61,
-      62,    63,    64,    65,    66,    67,    68,    69,    70,    71,
-      72,    73,    74,    75,    76,    77,    78,    79,    80,    81,
-      82,    83,    84,    85,    86,    87,    88,    89,    90,    91,
-      92,    93,    94,    95,    96,    97,    98,    99,   100,   101,
-     102,   103,   104,   105,   106,   107,   108,   109,   110,   111,
-     112,   113,   114,   115,   116,   117,   118,   119,   120,   121,
-     122,   123,   124,   125,   126,   127,   128,   129,   130,   131,
-     132,   133,   134,   135,   136,   137,   138,   139,   140,   141,
-     142,   143,   144,   145,   146,   147,   148,   149,   150,   151,
-     152,   153,   154,   155,   156,   157,   158,   159,   160,   161,
-     162,   163,   164,   165,   166,   167,   168,   169,   170,   171,
-     172,   173,   174,   175,   176,   177,   178,   179,   180,   181,
-     182,   183,   184,   185,   186,   187,   188,   189,   190,   191,
-     192,   193,   194,   195,   196,   197,   198,   199,   200,   201,
-     202,   203,   204,   205,   206,   207,   208,   209,   210,   211,
-     212,   213,   214,   215,   216,   217,   218,   219,   220,   221,
-     222,   223,   224,   225,   226,   227,   228,   229,   230,   231,
-     232,   233,   234,   235,   236,   237,   238,   239,   240,   241,
-     242,   243,   244,   245,   246,   247,   248,   249,   250,   251,
-     252,   253,   254,   255,   256,   257,   258,   259,   260,   261,
-     262,   263,   264,   265,   266,   267,   268,   269,   270,   271,
-     272,   273,   274,   275,   276,   277,   278,   279,   280,   281,
-     282,   283,   284,   285,   286,   287,   288,   289,   290,   291,
-     292,    -1,    -1,   295,   296,    -1,    -1,    -1,    -1,    -1,
+     411,   412,   413,   414,   415,   416,   417,   418,   419,     3,
+       4,     5,     6,     7,     8,     9,    10,    11,    12,    13,
+      14,    15,    16,    17,    18,    19,    20,    21,    22,    23,
+      24,    25,    26,    27,    28,    29,    30,    31,    32,    33,
+      34,    35,    36,    37,    38,    39,    40,    41,    42,    43,
+      44,    45,    46,    47,    48,    49,    50,    51,    52,    53,
+      54,    55,    56,    57,    58,    59,    60,    61,    62,    63,
+      64,    65,    66,    67,    68,    69,    70,    71,    72,    73,
+      74,    75,    76,    77,    78,    79,    80,    81,    82,    83,
+      84,    85,    86,    87,    88,    89,    90,    91,    92,    93,
+      94,    95,    96,    97,    98,    99,   100,   101,   102,   103,
+     104,   105,   106,   107,   108,   109,   110,   111,   112,   113,
+     114,   115,   116,   117,   118,   119,   120,   121,   122,   123,
+     124,   125,   126,   127,   128,   129,   130,   131,   132,   133,
+     134,   135,   136,   137,   138,   139,   140,   141,   142,   143,
+     144,   145,   146,   147,   148,   149,   150,   151,   152,   153,
+     154,   155,   156,   157,   158,   159,   160,   161,   162,   163,
+     164,   165,   166,   167,   168,   169,   170,   171,   172,   173,
+     174,   175,   176,   177,   178,   179,   180,   181,   182,   183,
+     184,   185,   186,   187,   188,   189,   190,   191,   192,   193,
+     194,   195,   196,   197,   198,   199,   200,   201,   202,   203,
+     204,   205,   206,   207,   208,   209,   210,   211,   212,   213,
+     214,   215,   216,   217,   218,   219,   220,   221,   222,   223,
+     224,   225,   226,   227,   228,   229,   230,   231,   232,   233,
+     234,   235,   236,   237,   238,   239,   240,   241,   242,   243,
+     244,   245,   246,   247,   248,   249,   250,   251,   252,   253,
+     254,   255,   256,   257,   258,   259,   260,   261,   262,   263,
+     264,   265,   266,   267,   268,   269,   270,   271,   272,   273,
+     274,   275,   276,   277,   278,   279,   280,   281,   282,   283,
+     284,   285,   286,   287,   288,   289,   290,   291,   292,   293,
+     294,    -1,    -1,   297,   298,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,   314,   315,    -1,   317,    -1,   319,    -1,    -1,
-      -1,    -1,    -1,   325,   326,   327,   328,   329,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,   339,   340,   341,
-     342,   343,    -1,    -1,    -1,   347,   348,   349,   350,   351,
-     352,   353,   354,   355,   356,   357,   358,   359,   360,   361,
-     362,    -1,   364,   365,   366,   367,   368,   369,   370,   371,
-     372,   373,   374,   375,   376,   377,   378,   379,   380,   381,
-     382,   383,   384,   385,   386,   387,   388,   389,   390,   391,
-     392,   393,   394,   395,   396,   397,   398,   399,   400,   401,
-     402,   403,   404,   405,   406,   407,   408,   409,   410,   411,
+      -1,    -1,   316,   317,    -1,   319,    -1,   321,   322,    -1,
+      -1,    -1,    -1,   327,   328,   329,   330,   331,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,   341,   342,   343,
+     344,   345,    -1,    -1,    -1,   349,   350,   351,   352,   353,
+     354,   355,   356,   357,   358,   359,   360,   361,   362,   363,
+     364,    -1,   366,   367,   368,   369,   370,   371,   372,   373,
+     374,   375,   376,   377,   378,   379,   380,   381,   382,   383,
+     384,   385,   386,   387,   388,   389,   390,   391,   392,   393,
+     394,   395,   396,   397,   398,   399,   400,   401,   402,   403,
+     404,   405,   406,   407,   408,   409,   410,   411,   412,   413,
+     414,   415,   416,   417,   418,   419,     3,     4,     5,     6,
+       7,     8,     9,    10,    11,    12,    13,    14,    15,    16,
+      17,    18,    19,    20,    21,    22,    23,    24,    25,    26,
+      27,    28,    29,    30,    31,    32,    33,    34,    35,    36,
+      37,    38,    39,    40,    41,    42,    43,    44,    45,    46,
+      47,    48,    49,    50,    51,    52,    53,    54,    55,    56,
+      57,    58,    59,    60,    61,    62,    63,    64,    65,    66,
+      67,    68,    69,    70,    71,    72,    73,    74,    75,    76,
+      77,    78,    79,    80,    81,    82,    83,    84,    85,    86,
+      87,    88,    89,    90,    91,    92,    93,    94,    95,    96,
+      97,    98,    99,   100,   101,   102,   103,   104,   105,   106,
+     107,   108,   109,   110,   111,   112,   113,   114,   115,   116,
+     117,   118,   119,   120,   121,   122,   123,   124,   125,   126,
+     127,   128,   129,   130,   131,   132,   133,   134,   135,   136,
+     137,   138,   139,   140,   141,   142,   143,   144,   145,   146,
+     147,   148,   149,   150,   151,   152,   153,   154,   155,   156,
+     157,   158,   159,   160,   161,   162,   163,   164,   165,   166,
+     167,   168,   169,   170,   171,   172,   173,   174,   175,   176,
+     177,   178,   179,   180,   181,   182,   183,   184,   185,   186,
+     187,   188,   189,   190,   191,   192,   193,   194,   195,   196,
+     197,   198,   199,   200,   201,   202,   203,   204,   205,   206,
+     207,   208,   209,   210,   211,   212,   213,   214,   215,   216,
+     217,   218,   219,   220,   221,   222,   223,   224,   225,   226,
+     227,   228,   229,   230,   231,   232,   233,   234,   235,   236,
+     237,   238,   239,   240,   241,   242,   243,   244,   245,   246,
+     247,   248,   249,   250,   251,   252,   253,   254,   255,   256,
+     257,   258,   259,   260,   261,   262,   263,   264,   265,   266,
+     267,   268,   269,   270,   271,   272,   273,   274,   275,   276,
+     277,   278,   279,   280,   281,   282,   283,   284,   285,   286,
+     287,   288,   289,   290,   291,   292,   293,   294,    -1,    -1,
+     297,   298,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   316,
+     317,    -1,   319,    -1,   321,   322,    -1,    -1,    -1,    -1,
+     327,   328,   329,   330,   331,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,   341,   342,   343,   344,   345,    -1,
+      -1,    -1,   349,   350,   351,   352,   353,   354,   355,   356,
+     357,   358,   359,   360,   361,   362,   363,   364,    -1,   366,
+     367,   368,   369,   370,   371,   372,   373,   374,   375,   376,
+     377,   378,   379,   380,   381,   382,   383,   384,   385,   386,
+     387,   388,   389,   390,   391,   392,   393,   394,   395,   396,
+     397,   398,   399,   400,   401,   402,   403,   404,   405,   406,
+     407,   408,   409,   410,   411,   412,   413,   414,   415,   416,
+     417,   418,   419,     3,     4,     5,     6,     7,     8,     9,
+      10,    11,    12,    13,    14,    15,    16,    17,    18,    19,
+      20,    21,    22,    23,    24,    25,    26,    27,    28,    29,
+      30,    31,    32,    33,    34,    35,    36,    37,    38,    39,
+      40,    41,    42,    43,    44,    45,    46,    47,    48,    49,
+      50,    51,    52,    53,    54,    55,    56,    57,    58,    59,
+      60,    61,    62,    63,    64,    65,    66,    67,    68,    69,
+      70,    71,    72,    73,    74,    75,    76,    77,    78,    79,
+      80,    81,    82,    83,    84,    85,    86,    87,    88,    89,
+      90,    91,    92,    93,    94,    95,    96,    97,    98,    99,
+     100,   101,   102,   103,   104,   105,   106,   107,   108,   109,
+     110,   111,   112,   113,   114,   115,   116,   117,   118,   119,
+     120,   121,   122,   123,   124,   125,   126,   127,   128,   129,
+     130,   131,   132,   133,   134,   135,   136,   137,   138,   139,
+     140,   141,   142,   143,   144,   145,   146,   147,   148,   149,
+     150,   151,   152,   153,   154,   155,   156,   157,   158,   159,
+     160,   161,   162,   163,   164,   165,   166,   167,   168,   169,
+     170,   171,   172,   173,   174,   175,   176,   177,   178,   179,
+     180,   181,   182,   183,   184,   185,   186,   187,   188,   189,
+     190,   191,   192,   193,   194,   195,   196,   197,   198,   199,
+     200,   201,   202,   203,   204,   205,   206,   207,   208,   209,
+     210,   211,   212,   213,   214,   215,   216,   217,   218,   219,
+     220,   221,   222,   223,   224,   225,   226,   227,   228,   229,
+     230,   231,   232,   233,   234,   235,   236,   237,   238,   239,
+     240,   241,   242,   243,   244,   245,   246,   247,   248,   249,
+     250,   251,   252,   253,   254,   255,   256,   257,   258,   259,
+     260,   261,   262,   263,   264,   265,   266,   267,   268,   269,
+     270,   271,   272,   273,   274,   275,   276,   277,   278,   279,
+     280,   281,   282,   283,   284,   285,   286,   287,   288,   289,
+     290,   291,   292,   293,   294,    -1,    -1,   297,   298,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,   316,   317,    -1,   319,
+      -1,   321,    -1,    -1,    -1,    -1,    -1,   327,   328,   329,
+     330,   331,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,   341,   342,   343,   344,   345,    -1,    -1,    -1,   349,
+     350,   351,   352,   353,   354,   355,   356,   357,   358,   359,
+     360,   361,   362,   363,   364,    -1,   366,   367,   368,   369,
+     370,   371,   372,   373,   374,   375,   376,   377,   378,   379,
+     380,   381,   382,   383,   384,   385,   386,   387,   388,   389,
+     390,   391,   392,   393,   394,   395,   396,   397,   398,   399,
+     400,   401,   402,   403,   404,   405,   406,   407,   408,   409,
+     410,   411,   412,   413,   414,   415,   416,   417,   418,   419,
        3,     4,     5,     6,     7,     8,     9,    10,    11,    12,
       13,    14,    15,    16,    17,    18,    19,    20,    21,    22,
       23,    24,    25,    26,    27,    28,    29,    30,    31,    32,
@@ -2607,100 +2643,19 @@
      263,   264,   265,   266,   267,   268,   269,   270,   271,   272,
      273,   274,   275,   276,   277,   278,   279,   280,   281,   282,
      283,   284,   285,   286,   287,   288,   289,   290,   291,   292,
-      -1,    -1,   295,   296,    -1,    -1,    -1,    -1,    -1,    -1,
+     293,   294,    -1,    -1,   297,   298,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,   314,   315,    -1,   317,    -1,   319,    -1,    -1,    -1,
-      -1,    -1,   325,   326,   327,   328,   329,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,   339,   340,   341,   342,
-     343,    -1,    -1,    -1,   347,   348,   349,   350,   351,   352,
+      -1,    -1,    -1,   316,   317,    -1,   319,    -1,   321,    -1,
+      -1,    -1,    -1,    -1,   327,   328,   329,   330,   331,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   341,   342,
+     343,   344,   345,    -1,    -1,    -1,   349,   350,   351,   352,
      353,   354,   355,   356,   357,   358,   359,   360,   361,   362,
-      -1,   364,   365,   366,   367,   368,   369,   370,   371,   372,
+     363,   364,    -1,   366,   367,   368,   369,   370,   371,   372,
      373,   374,   375,   376,   377,   378,   379,   380,   381,   382,
      383,   384,   385,   386,   387,   388,   389,   390,   391,   392,
      393,   394,   395,   396,   397,   398,   399,   400,   401,   402,
-     403,   404,   405,   406,   407,   408,   409,   410,   411,     3,
-       4,     5,     6,     7,     8,     9,    10,    11,    12,    13,
-      14,    15,    16,    17,    18,    19,    20,    21,    22,    23,
-      24,    25,    26,    27,    28,    29,    30,    31,    32,    33,
-      34,    35,    36,    37,    38,    39,    40,    41,    42,    43,
-      44,    45,    46,    47,    48,    49,    50,    51,    52,    53,
-      54,    55,    56,    57,    58,    59,    60,    61,    62,    63,
-      64,    65,    66,    67,    68,    69,    70,    71,    72,    73,
-      74,    75,    76,    77,    78,    79,    80,    81,    82,    83,
-      84,    85,    86,    87,    88,    89,    90,    91,    92,    93,
-      94,    95,    96,    97,    98,    99,   100,   101,   102,   103,
-     104,   105,   106,   107,   108,   109,   110,   111,   112,   113,
-     114,   115,   116,   117,   118,   119,   120,   121,   122,   123,
-     124,   125,   126,   127,   128,   129,   130,   131,   132,   133,
-     134,   135,   136,   137,   138,   139,   140,   141,   142,   143,
-     144,   145,   146,   147,   148,   149,   150,   151,   152,   153,
-     154,   155,   156,   157,   158,   159,   160,   161,   162,   163,
-     164,   165,   166,   167,   168,   169,   170,   171,   172,   173,
-     174,   175,   176,   177,   178,   179,   180,   181,   182,   183,
-     184,   185,   186,   187,   188,   189,   190,   191,   192,   193,
-     194,   195,   196,   197,   198,   199,   200,   201,   202,   203,
-     204,   205,   206,   207,   208,   209,   210,   211,   212,   213,
-     214,   215,   216,   217,   218,   219,   220,   221,   222,   223,
-     224,   225,   226,   227,   228,   229,   230,   231,   232,   233,
-     234,   235,   236,   237,   238,   239,   240,   241,   242,   243,
-     244,   245,   246,   247,   248,   249,   250,   251,   252,   253,
-     254,   255,   256,   257,   258,   259,   260,   261,   262,   263,
-     264,   265,   266,   267,   268,   269,   270,   271,   272,   273,
-     274,   275,   276,   277,   278,   279,   280,   281,   282,   283,
-     284,   285,   286,   287,   288,   289,   290,   291,   292,    -1,
-      -1,   295,   296,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-     314,   315,    -1,   317,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,   325,   326,   327,   328,   329,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,   339,   340,   341,   342,   343,
-      -1,    -1,    -1,   347,   348,   349,   350,   351,   352,   353,
-     354,   355,   356,   357,   358,   359,   360,   361,   362,    -1,
-     364,   365,   366,   367,   368,   369,   370,   371,   372,   373,
-     374,   375,   376,   377,   378,   379,   380,   381,   382,   383,
-     384,   385,   386,   387,   388,   389,   390,   391,   392,   393,
-     394,   395,   396,   397,   398,   399,   400,   401,   402,   403,
-     404,   405,   406,   407,   408,   409,   410,   411,     3,     4,
-       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
-      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
-      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
-      45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
-      55,    56,    57,    58,    59,    60,    61,    62,    63,    64,
-      65,    66,    67,    68,    69,    70,    71,    72,    73,    74,
-      75,    76,    77,    78,    79,    80,    81,    82,    83,    84,
-      85,    86,    87,    88,    89,    90,    91,    92,    93,    94,
-      95,    96,    97,    98,    99,   100,   101,   102,   103,   104,
-     105,   106,   107,   108,   109,   110,   111,   112,   113,   114,
-     115,   116,   117,   118,   119,   120,   121,   122,   123,   124,
-     125,   126,   127,   128,   129,   130,   131,   132,   133,   134,
-     135,   136,   137,   138,   139,   140,   141,   142,   143,   144,
-     145,   146,   147,   148,   149,   150,   151,   152,   153,   154,
-     155,   156,   157,   158,   159,   160,   161,   162,   163,   164,
-     165,   166,   167,   168,   169,   170,   171,   172,   173,   174,
-     175,   176,   177,   178,   179,   180,   181,   182,   183,   184,
-     185,   186,   187,   188,   189,   190,   191,   192,   193,   194,
-     195,   196,   197,   198,   199,   200,   201,   202,   203,   204,
-     205,   206,   207,   208,   209,   210,   211,   212,   213,   214,
-     215,   216,   217,   218,   219,   220,   221,   222,   223,   224,
-     225,   226,   227,   228,   229,   230,   231,   232,   233,   234,
-     235,   236,   237,   238,   239,   240,   241,   242,   243,   244,
-     245,   246,   247,   248,   249,   250,   251,   252,   253,   254,
-     255,   256,   257,   258,   259,   260,   261,   262,   263,   264,
-     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
-     275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
-     285,   286,   287,   288,   289,   290,   291,   292,    -1,    -1,
-     295,   296,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   314,
-     315,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-     325,   326,   327,   328,   329,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,   339,   340,   341,   342,   343,    -1,
-      -1,    -1,   347,   348,   349,   350,   351,   352,   353,   354,
-     355,   356,   357,   358,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,   371,   372,   373,   374,
-     375,   376,   377,   378,   379,   380,   381,   382,   383,   384,
-     385,    -1,   387,   388,   389,   390,   391,   392,   393,   394,
-     395,   396,   397,   398,   399,   400,   401,   402,   403,   404,
-     405,   406,   407,   408,   409,   410,   411,     3,     4,     5,
+     403,   404,   405,   406,   407,   408,   409,   410,   411,   412,
+     413,   414,   415,   416,   417,   418,   419,     3,     4,     5,
        6,     7,     8,     9,    10,    11,    12,    13,    14,    15,
       16,    17,    18,    19,    20,    21,    22,    23,    24,    25,
       26,    27,    28,    29,    30,    31,    32,    33,    34,    35,
@@ -2729,101 +2684,20 @@
      256,   257,   258,   259,   260,   261,   262,   263,   264,   265,
      266,   267,   268,   269,   270,   271,   272,   273,   274,   275,
      276,   277,   278,   279,   280,   281,   282,   283,   284,   285,
-     286,   287,   288,   289,   290,   291,   292,    -1,    -1,   295,
-     296,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   314,   315,
+     286,   287,   288,   289,   290,   291,   292,   293,   294,    -1,
+      -1,   297,   298,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-     326,   327,   328,   329,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,   339,   340,   341,   342,    -1,    -1,    -1,
-      -1,   347,   348,   349,   350,   351,   352,   353,   354,   355,
-     356,   357,   358,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,   371,   372,   373,   374,   375,
+     316,   317,    -1,   319,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,   327,   328,   329,   330,   331,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,   341,   342,   343,   344,   345,
+      -1,    -1,    -1,   349,   350,   351,   352,   353,   354,   355,
+     356,   357,   358,   359,   360,   361,   362,   363,   364,    -1,
+     366,   367,   368,   369,   370,   371,   372,   373,   374,   375,
      376,   377,   378,   379,   380,   381,   382,   383,   384,   385,
-      -1,   387,   388,   389,   390,   391,   392,   393,   394,   395,
+     386,   387,   388,   389,   390,   391,   392,   393,   394,   395,
      396,   397,   398,   399,   400,   401,   402,   403,   404,   405,
-     406,   407,   408,   409,   410,   411,     3,     4,     5,     6,
-       7,     8,     9,    10,    11,    12,    13,    14,    15,    16,
-      17,    18,    19,    20,    21,    22,    23,    24,    25,    26,
-      27,    28,    29,    30,    31,    32,    33,    34,    35,    36,
-      37,    38,    39,    40,    41,    42,    43,    44,    45,    46,
-      47,    48,    49,    50,    51,    52,    53,    54,    55,    56,
-      57,    58,    59,    60,    61,    62,    63,    64,    65,    66,
-      67,    68,    69,    70,    71,    72,    73,    74,    75,    76,
-      77,    78,    79,    80,    81,    82,    83,    84,    85,    86,
-      87,    88,    89,    90,    91,    92,    93,    94,    95,    96,
-      97,    98,    99,   100,   101,   102,   103,   104,   105,   106,
-     107,   108,   109,   110,   111,   112,   113,   114,   115,   116,
-     117,   118,   119,   120,   121,   122,   123,   124,   125,   126,
-     127,   128,   129,   130,   131,   132,   133,   134,   135,   136,
-     137,   138,   139,   140,   141,   142,   143,   144,   145,   146,
-     147,   148,   149,   150,   151,   152,   153,   154,   155,   156,
-     157,   158,   159,   160,   161,   162,   163,   164,   165,   166,
-     167,   168,   169,   170,   171,   172,   173,   174,   175,   176,
-     177,   178,   179,   180,   181,   182,   183,   184,   185,   186,
-     187,   188,   189,   190,   191,   192,   193,   194,   195,   196,
-     197,   198,   199,   200,   201,   202,   203,   204,   205,   206,
-     207,   208,   209,   210,   211,   212,   213,   214,   215,   216,
-     217,   218,   219,   220,   221,   222,   223,   224,   225,   226,
-     227,   228,   229,   230,   231,   232,   233,   234,   235,   236,
-     237,   238,   239,   240,   241,   242,   243,   244,   245,   246,
-     247,   248,   249,   250,   251,   252,   253,   254,   255,   256,
-     257,   258,   259,   260,   261,   262,   263,   264,   265,   266,
-     267,   268,   269,   270,   271,   272,   273,   274,   275,   276,
-     277,   278,   279,   280,   281,   282,   283,   284,   285,   286,
-     287,   288,   289,   290,   291,   292,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   325,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,   339,   340,   341,   342,   343,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,   352,   353,   354,   355,   356,
-     357,   358,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,   371,   372,   373,   374,   375,   376,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   385,    -1,
-     387,   388,   389,   390,   391,   392,   393,   394,   395,   396,
-     397,   398,   399,   400,   401,   402,   403,   404,   405,   406,
-     407,   408,   409,   410,   411,     3,     4,     5,     6,     7,
-       8,     9,    10,    11,    12,    13,    14,    15,    16,    17,
-      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
-      28,    29,    30,    31,    32,    33,    34,    35,    36,    37,
-      38,    39,    40,    41,    42,    43,    44,    45,    46,    47,
-      48,    49,    50,    51,    52,    53,    54,    55,    56,    57,
-      58,    59,    60,    61,    62,    63,    64,    65,    66,    67,
-      68,    69,    70,    71,    72,    73,    74,    75,    76,    77,
-      78,    79,    80,    81,    82,    83,    84,    85,    86,    87,
-      88,    89,    90,    91,    92,    93,    94,    95,    96,    97,
-      98,    99,   100,   101,   102,   103,   104,   105,   106,   107,
-     108,   109,   110,   111,   112,   113,   114,   115,   116,   117,
-     118,   119,   120,   121,   122,   123,   124,   125,   126,   127,
-     128,   129,   130,   131,   132,   133,   134,   135,   136,   137,
-     138,   139,   140,   141,   142,   143,   144,   145,   146,   147,
-     148,   149,   150,   151,   152,   153,   154,   155,   156,   157,
-     158,   159,   160,   161,   162,   163,   164,   165,   166,   167,
-     168,   169,   170,   171,   172,   173,   174,   175,   176,   177,
-     178,   179,   180,   181,   182,   183,   184,   185,   186,   187,
-     188,   189,   190,   191,   192,   193,   194,   195,   196,   197,
-     198,   199,   200,   201,   202,   203,   204,   205,   206,   207,
-     208,   209,   210,   211,   212,   213,   214,   215,   216,   217,
-     218,   219,   220,   221,   222,   223,   224,   225,   226,   227,
-     228,   229,   230,   231,   232,   233,   234,   235,   236,   237,
-     238,   239,   240,   241,   242,   243,   244,   245,   246,   247,
-     248,   249,   250,   251,   252,   253,   254,   255,   256,   257,
-     258,   259,   260,   261,   262,   263,   264,   265,   266,   267,
-     268,   269,   270,   271,   272,   273,   274,   275,   276,   277,
-     278,   279,   280,   281,   282,   283,   284,   285,   286,   287,
-     288,   289,   290,   291,   292,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,   325,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,   339,   340,   341,   342,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,   351,   352,   353,   354,   355,   356,   357,
-     358,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,   371,   372,   373,   374,   375,   376,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,   385,    -1,   387,
-     388,   389,   390,   391,   392,   393,   394,   395,   396,   397,
-     398,   399,   400,   401,   402,   403,   404,   405,   406,   407,
-     408,   409,   410,   411,     3,     4,     5,     6,     7,     8,
+     406,   407,   408,   409,   410,   411,   412,   413,   414,   415,
+     416,   417,   418,   419,     3,     4,     5,     6,     7,     8,
        9,    10,    11,    12,    13,    14,    15,    16,    17,    18,
       19,    20,    21,    22,    23,    24,    25,    26,    27,    28,
       29,    30,    31,    32,    33,    34,    35,    36,    37,    38,
@@ -2852,101 +2726,20 @@
      259,   260,   261,   262,   263,   264,   265,   266,   267,   268,
      269,   270,   271,   272,   273,   274,   275,   276,   277,   278,
      279,   280,   281,   282,   283,   284,   285,   286,   287,   288,
-     289,   290,   291,   292,    -1,    -1,    -1,    -1,    -1,    -1,
+     289,   290,   291,   292,   293,   294,    -1,    -1,   297,   298,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,   320,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-     339,   340,   341,   342,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,   352,   353,   354,   355,   356,   357,   358,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,   371,   372,   373,   374,   375,   376,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,   385,    -1,   387,   388,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,   316,   317,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   327,   328,
+     329,   330,   331,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,   341,   342,   343,   344,   345,    -1,    -1,    -1,
+     349,   350,   351,   352,   353,   354,   355,   356,   357,   358,
+     359,   360,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,   373,   374,   375,   376,   377,   378,
+     379,   380,   381,   382,   383,   384,   385,   386,   387,    -1,
      389,   390,   391,   392,   393,   394,   395,   396,   397,   398,
      399,   400,   401,   402,   403,   404,   405,   406,   407,   408,
-     409,   410,   411,     3,     4,     5,     6,     7,     8,     9,
-      10,    11,    12,    13,    14,    15,    16,    17,    18,    19,
-      20,    21,    22,    23,    24,    25,    26,    27,    28,    29,
-      30,    31,    32,    33,    34,    35,    36,    37,    38,    39,
-      40,    41,    42,    43,    44,    45,    46,    47,    48,    49,
-      50,    51,    52,    53,    54,    55,    56,    57,    58,    59,
-      60,    61,    62,    63,    64,    65,    66,    67,    68,    69,
-      70,    71,    72,    73,    74,    75,    76,    77,    78,    79,
-      80,    81,    82,    83,    84,    85,    86,    87,    88,    89,
-      90,    91,    92,    93,    94,    95,    96,    97,    98,    99,
-     100,   101,   102,   103,   104,   105,   106,   107,   108,   109,
-     110,   111,   112,   113,   114,   115,   116,   117,   118,   119,
-     120,   121,   122,   123,   124,   125,   126,   127,   128,   129,
-     130,   131,   132,   133,   134,   135,   136,   137,   138,   139,
-     140,   141,   142,   143,   144,   145,   146,   147,   148,   149,
-     150,   151,   152,   153,   154,   155,   156,   157,   158,   159,
-     160,   161,   162,   163,   164,   165,   166,   167,   168,   169,
-     170,   171,   172,   173,   174,   175,   176,   177,   178,   179,
-     180,   181,   182,   183,   184,   185,   186,   187,   188,   189,
-     190,   191,   192,   193,   194,   195,   196,   197,   198,   199,
-     200,   201,   202,   203,   204,   205,   206,   207,   208,   209,
-     210,   211,   212,   213,   214,   215,   216,   217,   218,   219,
-     220,   221,   222,   223,   224,   225,   226,   227,   228,   229,
-     230,   231,   232,   233,   234,   235,   236,   237,   238,   239,
-     240,   241,   242,   243,   244,   245,   246,   247,   248,   249,
-     250,   251,   252,   253,   254,   255,   256,   257,   258,   259,
-     260,   261,   262,   263,   264,   265,   266,   267,   268,   269,
-     270,   271,   272,   273,   274,   275,   276,   277,   278,   279,
-     280,   281,   282,   283,   284,   285,   286,   287,   288,   289,
-     290,   291,   292,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-     320,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   339,
-     340,   341,   342,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,   352,   353,   354,   355,   356,   357,   358,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,   371,   372,   373,   374,   375,   376,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,   385,    -1,   387,   388,   389,
-     390,   391,   392,   393,   394,   395,   396,   397,   398,   399,
-     400,   401,   402,   403,   404,   405,   406,   407,   408,   409,
-     410,   411,     3,     4,     5,     6,     7,     8,     9,    10,
-      11,    12,    13,    14,    15,    16,    17,    18,    19,    20,
-      21,    22,    23,    24,    25,    26,    27,    28,    29,    30,
-      31,    32,    33,    34,    35,    36,    37,    38,    39,    40,
-      41,    42,    43,    44,    45,    46,    47,    48,    49,    50,
-      51,    52,    53,    54,    55,    56,    57,    58,    59,    60,
-      61,    62,    63,    64,    65,    66,    67,    68,    69,    70,
-      71,    72,    73,    74,    75,    76,    77,    78,    79,    80,
-      81,    82,    83,    84,    85,    86,    87,    88,    89,    90,
-      91,    92,    93,    94,    95,    96,    97,    98,    99,   100,
-     101,   102,   103,   104,   105,   106,   107,   108,   109,   110,
-     111,   112,   113,   114,   115,   116,   117,   118,   119,   120,
-     121,   122,   123,   124,   125,   126,   127,   128,   129,   130,
-     131,   132,   133,   134,   135,   136,   137,   138,   139,   140,
-     141,   142,   143,   144,   145,   146,   147,   148,   149,   150,
-     151,   152,   153,   154,   155,   156,   157,   158,   159,   160,
-     161,   162,   163,   164,   165,   166,   167,   168,   169,   170,
-     171,   172,   173,   174,   175,   176,   177,   178,   179,   180,
-     181,   182,   183,   184,   185,   186,   187,   188,   189,   190,
-     191,   192,   193,   194,   195,   196,   197,   198,   199,   200,
-     201,   202,   203,   204,   205,   206,   207,   208,   209,   210,
-     211,   212,   213,   214,   215,   216,   217,   218,   219,   220,
-     221,   222,   223,   224,   225,   226,   227,   228,   229,   230,
-     231,   232,   233,   234,   235,   236,   237,   238,   239,   240,
-     241,   242,   243,   244,   245,   246,   247,   248,   249,   250,
-     251,   252,   253,   254,   255,   256,   257,   258,   259,   260,
-     261,   262,   263,   264,   265,   266,   267,   268,   269,   270,
-     271,   272,   273,   274,   275,   276,   277,   278,   279,   280,
-     281,   282,   283,   284,   285,   286,   287,   288,   289,   290,
-     291,   292,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   320,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   339,   340,
-     341,   342,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,   352,   353,   354,   355,   356,   357,   358,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-     371,   372,   373,   374,   375,   376,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,   385,    -1,   387,   388,   389,   390,
-     391,   392,   393,   394,   395,   396,   397,   398,   399,   400,
-     401,   402,   403,   404,   405,   406,   407,   408,   409,   410,
-     411,     3,     4,     5,     6,     7,     8,     9,    10,    11,
+     409,   410,   411,   412,   413,   414,   415,   416,   417,   418,
+     419,     3,     4,     5,     6,     7,     8,     9,    10,    11,
       12,    13,    14,    15,    16,    17,    18,    19,    20,    21,
       22,    23,    24,    25,    26,    27,    28,    29,    30,    31,
       32,    33,    34,    35,    36,    37,    38,    39,    40,    41,
@@ -2975,18 +2768,269 @@
      262,   263,   264,   265,   266,   267,   268,   269,   270,   271,
      272,   273,   274,   275,   276,   277,   278,   279,   280,   281,
      282,   283,   284,   285,   286,   287,   288,   289,   290,   291,
-     292,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+     292,   293,   294,    -1,    -1,   297,   298,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,   316,   317,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,   328,   329,   330,   331,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   341,
+     342,   343,   344,    -1,    -1,    -1,    -1,   349,   350,   351,
+     352,   353,   354,   355,   356,   357,   358,   359,   360,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,   339,   340,   341,
-     342,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-     352,   353,   354,   355,   356,   357,   358,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   371,
-     372,   373,   374,   375,   376,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,   385,    -1,   387,   388,   389,   390,   391,
+      -1,   373,   374,   375,   376,   377,   378,   379,   380,   381,
+     382,   383,   384,   385,   386,   387,    -1,   389,   390,   391,
      392,   393,   394,   395,   396,   397,   398,   399,   400,   401,
      402,   403,   404,   405,   406,   407,   408,   409,   410,   411,
+     412,   413,   414,   415,   416,   417,   418,   419,     3,     4,
+       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
+      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
+      45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
+      55,    56,    57,    58,    59,    60,    61,    62,    63,    64,
+      65,    66,    67,    68,    69,    70,    71,    72,    73,    74,
+      75,    76,    77,    78,    79,    80,    81,    82,    83,    84,
+      85,    86,    87,    88,    89,    90,    91,    92,    93,    94,
+      95,    96,    97,    98,    99,   100,   101,   102,   103,   104,
+     105,   106,   107,   108,   109,   110,   111,   112,   113,   114,
+     115,   116,   117,   118,   119,   120,   121,   122,   123,   124,
+     125,   126,   127,   128,   129,   130,   131,   132,   133,   134,
+     135,   136,   137,   138,   139,   140,   141,   142,   143,   144,
+     145,   146,   147,   148,   149,   150,   151,   152,   153,   154,
+     155,   156,   157,   158,   159,   160,   161,   162,   163,   164,
+     165,   166,   167,   168,   169,   170,   171,   172,   173,   174,
+     175,   176,   177,   178,   179,   180,   181,   182,   183,   184,
+     185,   186,   187,   188,   189,   190,   191,   192,   193,   194,
+     195,   196,   197,   198,   199,   200,   201,   202,   203,   204,
+     205,   206,   207,   208,   209,   210,   211,   212,   213,   214,
+     215,   216,   217,   218,   219,   220,   221,   222,   223,   224,
+     225,   226,   227,   228,   229,   230,   231,   232,   233,   234,
+     235,   236,   237,   238,   239,   240,   241,   242,   243,   244,
+     245,   246,   247,   248,   249,   250,   251,   252,   253,   254,
+     255,   256,   257,   258,   259,   260,   261,   262,   263,   264,
+     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
+     275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
+     285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,   327,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,   341,   342,   343,   344,
+     345,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   354,
+     355,   356,   357,   358,   359,   360,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   373,   374,
+     375,   376,   377,   378,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,   387,    -1,   389,   390,   391,   392,   393,   394,
+     395,   396,   397,   398,   399,   400,   401,   402,   403,   404,
+     405,   406,   407,   408,   409,   410,   411,   412,   413,   414,
+     415,   416,   417,   418,   419,     3,     4,     5,     6,     7,
+       8,     9,    10,    11,    12,    13,    14,    15,    16,    17,
+      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
+      28,    29,    30,    31,    32,    33,    34,    35,    36,    37,
+      38,    39,    40,    41,    42,    43,    44,    45,    46,    47,
+      48,    49,    50,    51,    52,    53,    54,    55,    56,    57,
+      58,    59,    60,    61,    62,    63,    64,    65,    66,    67,
+      68,    69,    70,    71,    72,    73,    74,    75,    76,    77,
+      78,    79,    80,    81,    82,    83,    84,    85,    86,    87,
+      88,    89,    90,    91,    92,    93,    94,    95,    96,    97,
+      98,    99,   100,   101,   102,   103,   104,   105,   106,   107,
+     108,   109,   110,   111,   112,   113,   114,   115,   116,   117,
+     118,   119,   120,   121,   122,   123,   124,   125,   126,   127,
+     128,   129,   130,   131,   132,   133,   134,   135,   136,   137,
+     138,   139,   140,   141,   142,   143,   144,   145,   146,   147,
+     148,   149,   150,   151,   152,   153,   154,   155,   156,   157,
+     158,   159,   160,   161,   162,   163,   164,   165,   166,   167,
+     168,   169,   170,   171,   172,   173,   174,   175,   176,   177,
+     178,   179,   180,   181,   182,   183,   184,   185,   186,   187,
+     188,   189,   190,   191,   192,   193,   194,   195,   196,   197,
+     198,   199,   200,   201,   202,   203,   204,   205,   206,   207,
+     208,   209,   210,   211,   212,   213,   214,   215,   216,   217,
+     218,   219,   220,   221,   222,   223,   224,   225,   226,   227,
+     228,   229,   230,   231,   232,   233,   234,   235,   236,   237,
+     238,   239,   240,   241,   242,   243,   244,   245,   246,   247,
+     248,   249,   250,   251,   252,   253,   254,   255,   256,   257,
+     258,   259,   260,   261,   262,   263,   264,   265,   266,   267,
+     268,   269,   270,   271,   272,   273,   274,   275,   276,   277,
+     278,   279,   280,   281,   282,   283,   284,   285,   286,   287,
+     288,   289,   290,   291,   292,   293,   294,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   327,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,   341,   342,   343,   344,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,   353,   354,   355,   356,   357,
+     358,   359,   360,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,   373,   374,   375,   376,   377,
+     378,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   387,
+      -1,   389,   390,   391,   392,   393,   394,   395,   396,   397,
+     398,   399,   400,   401,   402,   403,   404,   405,   406,   407,
+     408,   409,   410,   411,   412,   413,   414,   415,   416,   417,
+     418,   419,     3,     4,     5,     6,     7,     8,     9,    10,
+      11,    12,    13,    14,    15,    16,    17,    18,    19,    20,
+      21,    22,    23,    24,    25,    26,    27,    28,    29,    30,
+      31,    32,    33,    34,    35,    36,    37,    38,    39,    40,
+      41,    42,    43,    44,    45,    46,    47,    48,    49,    50,
+      51,    52,    53,    54,    55,    56,    57,    58,    59,    60,
+      61,    62,    63,    64,    65,    66,    67,    68,    69,    70,
+      71,    72,    73,    74,    75,    76,    77,    78,    79,    80,
+      81,    82,    83,    84,    85,    86,    87,    88,    89,    90,
+      91,    92,    93,    94,    95,    96,    97,    98,    99,   100,
+     101,   102,   103,   104,   105,   106,   107,   108,   109,   110,
+     111,   112,   113,   114,   115,   116,   117,   118,   119,   120,
+     121,   122,   123,   124,   125,   126,   127,   128,   129,   130,
+     131,   132,   133,   134,   135,   136,   137,   138,   139,   140,
+     141,   142,   143,   144,   145,   146,   147,   148,   149,   150,
+     151,   152,   153,   154,   155,   156,   157,   158,   159,   160,
+     161,   162,   163,   164,   165,   166,   167,   168,   169,   170,
+     171,   172,   173,   174,   175,   176,   177,   178,   179,   180,
+     181,   182,   183,   184,   185,   186,   187,   188,   189,   190,
+     191,   192,   193,   194,   195,   196,   197,   198,   199,   200,
+     201,   202,   203,   204,   205,   206,   207,   208,   209,   210,
+     211,   212,   213,   214,   215,   216,   217,   218,   219,   220,
+     221,   222,   223,   224,   225,   226,   227,   228,   229,   230,
+     231,   232,   233,   234,   235,   236,   237,   238,   239,   240,
+     241,   242,   243,   244,   245,   246,   247,   248,   249,   250,
+     251,   252,   253,   254,   255,   256,   257,   258,   259,   260,
+     261,   262,   263,   264,   265,   266,   267,   268,   269,   270,
+     271,   272,   273,   274,   275,   276,   277,   278,   279,   280,
+     281,   282,   283,   284,   285,   286,   287,   288,   289,   290,
+     291,   292,   293,   294,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,   322,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+     341,   342,   343,   344,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,   354,   355,   356,   357,   358,   359,   360,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,   373,   374,   375,   376,   377,   378,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,   387,    -1,   389,   390,
+     391,   392,   393,   394,   395,   396,   397,   398,   399,   400,
+     401,   402,   403,   404,   405,   406,   407,   408,   409,   410,
+     411,   412,   413,   414,   415,   416,   417,   418,   419,     3,
+       4,     5,     6,     7,     8,     9,    10,    11,    12,    13,
+      14,    15,    16,    17,    18,    19,    20,    21,    22,    23,
+      24,    25,    26,    27,    28,    29,    30,    31,    32,    33,
+      34,    35,    36,    37,    38,    39,    40,    41,    42,    43,
+      44,    45,    46,    47,    48,    49,    50,    51,    52,    53,
+      54,    55,    56,    57,    58,    59,    60,    61,    62,    63,
+      64,    65,    66,    67,    68,    69,    70,    71,    72,    73,
+      74,    75,    76,    77,    78,    79,    80,    81,    82,    83,
+      84,    85,    86,    87,    88,    89,    90,    91,    92,    93,
+      94,    95,    96,    97,    98,    99,   100,   101,   102,   103,
+     104,   105,   106,   107,   108,   109,   110,   111,   112,   113,
+     114,   115,   116,   117,   118,   119,   120,   121,   122,   123,
+     124,   125,   126,   127,   128,   129,   130,   131,   132,   133,
+     134,   135,   136,   137,   138,   139,   140,   141,   142,   143,
+     144,   145,   146,   147,   148,   149,   150,   151,   152,   153,
+     154,   155,   156,   157,   158,   159,   160,   161,   162,   163,
+     164,   165,   166,   167,   168,   169,   170,   171,   172,   173,
+     174,   175,   176,   177,   178,   179,   180,   181,   182,   183,
+     184,   185,   186,   187,   188,   189,   190,   191,   192,   193,
+     194,   195,   196,   197,   198,   199,   200,   201,   202,   203,
+     204,   205,   206,   207,   208,   209,   210,   211,   212,   213,
+     214,   215,   216,   217,   218,   219,   220,   221,   222,   223,
+     224,   225,   226,   227,   228,   229,   230,   231,   232,   233,
+     234,   235,   236,   237,   238,   239,   240,   241,   242,   243,
+     244,   245,   246,   247,   248,   249,   250,   251,   252,   253,
+     254,   255,   256,   257,   258,   259,   260,   261,   262,   263,
+     264,   265,   266,   267,   268,   269,   270,   271,   272,   273,
+     274,   275,   276,   277,   278,   279,   280,   281,   282,   283,
+     284,   285,   286,   287,   288,   289,   290,   291,   292,   293,
+     294,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   322,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,   341,   342,   343,
+     344,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+     354,   355,   356,   357,   358,   359,   360,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   373,
+     374,   375,   376,   377,   378,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,   387,    -1,   389,   390,   391,   392,   393,
+     394,   395,   396,   397,   398,   399,   400,   401,   402,   403,
+     404,   405,   406,   407,   408,   409,   410,   411,   412,   413,
+     414,   415,   416,   417,   418,   419,     3,     4,     5,     6,
+       7,     8,     9,    10,    11,    12,    13,    14,    15,    16,
+      17,    18,    19,    20,    21,    22,    23,    24,    25,    26,
+      27,    28,    29,    30,    31,    32,    33,    34,    35,    36,
+      37,    38,    39,    40,    41,    42,    43,    44,    45,    46,
+      47,    48,    49,    50,    51,    52,    53,    54,    55,    56,
+      57,    58,    59,    60,    61,    62,    63,    64,    65,    66,
+      67,    68,    69,    70,    71,    72,    73,    74,    75,    76,
+      77,    78,    79,    80,    81,    82,    83,    84,    85,    86,
+      87,    88,    89,    90,    91,    92,    93,    94,    95,    96,
+      97,    98,    99,   100,   101,   102,   103,   104,   105,   106,
+     107,   108,   109,   110,   111,   112,   113,   114,   115,   116,
+     117,   118,   119,   120,   121,   122,   123,   124,   125,   126,
+     127,   128,   129,   130,   131,   132,   133,   134,   135,   136,
+     137,   138,   139,   140,   141,   142,   143,   144,   145,   146,
+     147,   148,   149,   150,   151,   152,   153,   154,   155,   156,
+     157,   158,   159,   160,   161,   162,   163,   164,   165,   166,
+     167,   168,   169,   170,   171,   172,   173,   174,   175,   176,
+     177,   178,   179,   180,   181,   182,   183,   184,   185,   186,
+     187,   188,   189,   190,   191,   192,   193,   194,   195,   196,
+     197,   198,   199,   200,   201,   202,   203,   204,   205,   206,
+     207,   208,   209,   210,   211,   212,   213,   214,   215,   216,
+     217,   218,   219,   220,   221,   222,   223,   224,   225,   226,
+     227,   228,   229,   230,   231,   232,   233,   234,   235,   236,
+     237,   238,   239,   240,   241,   242,   243,   244,   245,   246,
+     247,   248,   249,   250,   251,   252,   253,   254,   255,   256,
+     257,   258,   259,   260,   261,   262,   263,   264,   265,   266,
+     267,   268,   269,   270,   271,   272,   273,   274,   275,   276,
+     277,   278,   279,   280,   281,   282,   283,   284,   285,   286,
+     287,   288,   289,   290,   291,   292,   293,   294,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,   322,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,   341,   342,   343,   344,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,   354,   355,   356,
+     357,   358,   359,   360,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,   373,   374,   375,   376,
+     377,   378,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+     387,    -1,   389,   390,   391,   392,   393,   394,   395,   396,
+     397,   398,   399,   400,   401,   402,   403,   404,   405,   406,
+     407,   408,   409,   410,   411,   412,   413,   414,   415,   416,
+     417,   418,   419,     3,     4,     5,     6,     7,     8,     9,
+      10,    11,    12,    13,    14,    15,    16,    17,    18,    19,
+      20,    21,    22,    23,    24,    25,    26,    27,    28,    29,
+      30,    31,    32,    33,    34,    35,    36,    37,    38,    39,
+      40,    41,    42,    43,    44,    45,    46,    47,    48,    49,
+      50,    51,    52,    53,    54,    55,    56,    57,    58,    59,
+      60,    61,    62,    63,    64,    65,    66,    67,    68,    69,
+      70,    71,    72,    73,    74,    75,    76,    77,    78,    79,
+      80,    81,    82,    83,    84,    85,    86,    87,    88,    89,
+      90,    91,    92,    93,    94,    95,    96,    97,    98,    99,
+     100,   101,   102,   103,   104,   105,   106,   107,   108,   109,
+     110,   111,   112,   113,   114,   115,   116,   117,   118,   119,
+     120,   121,   122,   123,   124,   125,   126,   127,   128,   129,
+     130,   131,   132,   133,   134,   135,   136,   137,   138,   139,
+     140,   141,   142,   143,   144,   145,   146,   147,   148,   149,
+     150,   151,   152,   153,   154,   155,   156,   157,   158,   159,
+     160,   161,   162,   163,   164,   165,   166,   167,   168,   169,
+     170,   171,   172,   173,   174,   175,   176,   177,   178,   179,
+     180,   181,   182,   183,   184,   185,   186,   187,   188,   189,
+     190,   191,   192,   193,   194,   195,   196,   197,   198,   199,
+     200,   201,   202,   203,   204,   205,   206,   207,   208,   209,
+     210,   211,   212,   213,   214,   215,   216,   217,   218,   219,
+     220,   221,   222,   223,   224,   225,   226,   227,   228,   229,
+     230,   231,   232,   233,   234,   235,   236,   237,   238,   239,
+     240,   241,   242,   243,   244,   245,   246,   247,   248,   249,
+     250,   251,   252,   253,   254,   255,   256,   257,   258,   259,
+     260,   261,   262,   263,   264,   265,   266,   267,   268,   269,
+     270,   271,   272,   273,   274,   275,   276,   277,   278,   279,
+     280,   281,   282,   283,   284,   285,   286,   287,   288,   289,
+     290,   291,   292,   293,   294,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,   341,   342,   343,   344,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,   354,   355,   356,   357,   358,   359,
+     360,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,   373,   374,   375,   376,   377,   378,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,   387,    -1,   389,
+     390,   391,   392,   393,   394,   395,   396,   397,   398,   399,
+     400,   401,   402,   403,   404,   405,   406,   407,   408,   409,
+     410,   411,   412,   413,   414,   415,   416,   417,   418,   419,
        4,     5,     6,     7,     8,     9,    10,    11,    12,    13,
       14,    15,    16,    17,    18,    19,    20,    21,    22,    23,
       24,    25,    26,    27,    28,    29,    30,    31,    32,    33,
@@ -3015,213 +3059,58 @@
      254,   255,   256,   257,   258,   259,   260,   261,   262,   263,
      264,   265,   266,   267,   268,   269,   270,   271,   272,   273,
      274,   275,   276,   277,   278,   279,   280,   281,   282,   283,
-     284,   285,   286,   287,   288,   289,   290,   291,   292,    -1,
-      -1,   295,   296,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+     284,   285,   286,   287,   288,   289,   290,   291,   292,   293,
+     294,    -1,    -1,   297,   298,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-     314,   315,    -1,    -1,    -1,   319,   320,    -1,    -1,    -1,
-      -1,    -1,   326,   327,   328,   329,    -1,    -1,    -1,    -1,
+      -1,    -1,   316,   317,    -1,    -1,    -1,   321,   322,    -1,
+      -1,    -1,    -1,    -1,   328,   329,   330,   331,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,   347,   348,   349,   350,   351,   352,    -1,
-      -1,    -1,    -1,   357,   358,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,   349,   350,   351,   352,   353,
+     354,    -1,    -1,    -1,    -1,   359,   360,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,   377,   378,   379,   380,   381,   382,   383,
-     384,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-     394,     4,     5,     6,     7,     8,     9,    10,    11,    12,
-      13,    14,    15,    16,    17,    18,    19,    20,    21,    22,
-      23,    24,    25,    26,    27,    28,    29,    30,    31,    32,
-      33,    34,    35,    36,    37,    38,    39,    40,    41,    42,
-      43,    44,    45,    46,    47,    48,    49,    50,    51,    52,
-      53,    54,    55,    56,    57,    58,    59,    60,    -1,    -1,
-      63,    64,    65,    66,    67,    68,    69,    70,    71,    72,
-      73,    74,    75,    76,    77,    78,    79,    80,    81,    82,
-      83,    84,    85,    86,    87,    88,    89,    90,    91,    92,
-      93,    94,    95,    96,    97,    98,    99,   100,   101,   102,
-     103,   104,   105,   106,   107,   108,   109,   110,   111,   112,
-     113,   114,   115,   116,   117,   118,   119,   120,   121,   122,
-     123,   124,   125,   126,   127,   128,   129,   130,   131,   132,
-     133,   134,   135,   136,   137,   138,   139,   140,   141,   142,
-     143,   144,   145,   146,   147,   148,   149,   150,   151,   152,
-     153,   154,   155,   156,   157,   158,   159,   160,   161,   162,
-     163,   164,   165,   166,   167,   168,   169,   170,   171,   172,
-     173,   174,   175,   176,   177,   178,   179,   180,   181,   182,
-     183,   184,   185,   186,   187,   188,   189,   190,   191,   192,
-     193,   194,   195,   196,   197,   198,   199,   200,   201,   202,
-     203,   204,   205,   206,   207,   208,   209,   210,   211,   212,
-     213,   214,   215,   216,   217,   218,   219,   220,   221,   222,
-     223,   224,   225,   226,   227,   228,   229,   230,   231,   232,
-     233,   234,   235,   236,   237,   238,   239,   240,   241,   242,
-     243,   244,   245,   246,   247,   248,   249,   250,   251,   252,
-     253,   254,   255,   256,   257,   258,   259,   260,   261,   262,
-     263,   264,   265,   266,   267,   268,   269,   270,   271,   272,
-     273,   274,   275,   276,   277,   278,   279,   280,   281,   282,
-     283,   284,   285,   286,   287,   288,   289,   290,   291,   292,
-      -1,    -1,   295,   296,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,   379,   380,   381,   382,   383,
+     384,   385,   386,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,   401,     4,     5,
+       6,     7,     8,     9,    10,    11,    12,    13,    14,    15,
+      16,    17,    18,    19,    20,    21,    22,    23,    24,    25,
+      26,    27,    28,    29,    30,    31,    32,    33,    34,    35,
+      36,    37,    38,    39,    40,    41,    42,    43,    44,    45,
+      46,    47,    48,    49,    50,    51,    52,    53,    54,    55,
+      56,    57,    58,    59,    60,    -1,    -1,    63,    64,    65,
+      66,    67,    68,    69,    70,    71,    72,    73,    74,    75,
+      76,    77,    78,    79,    80,    81,    82,    83,    84,    85,
+      86,    87,    88,    89,    90,    91,    92,    93,    94,    95,
+      96,    97,    98,    99,   100,   101,   102,   103,   104,   105,
+     106,   107,   108,   109,   110,   111,   112,   113,   114,   115,
+     116,   117,   118,   119,   120,   121,   122,   123,   124,   125,
+     126,   127,   128,   129,   130,   131,   132,   133,   134,   135,
+     136,   137,   138,   139,   140,   141,   142,   143,   144,   145,
+     146,   147,   148,   149,   150,   151,   152,   153,   154,   155,
+     156,   157,   158,   159,   160,   161,   162,   163,   164,   165,
+     166,   167,   168,   169,   170,   171,   172,   173,   174,   175,
+     176,   177,   178,   179,   180,   181,   182,   183,   184,   185,
+     186,   187,   188,   189,   190,   191,   192,   193,   194,   195,
+     196,   197,   198,   199,   200,   201,   202,   203,   204,   205,
+     206,   207,   208,   209,   210,   211,   212,   213,   214,   215,
+     216,   217,   218,   219,   220,   221,   222,   223,   224,   225,
+     226,   227,   228,   229,   230,   231,   232,   233,   234,   235,
+     236,   237,   238,   239,   240,   241,   242,   243,   244,   245,
+     246,   247,   248,   249,   250,   251,   252,   253,   254,   255,
+     256,   257,   258,   259,   260,   261,   262,   263,   264,   265,
+     266,   267,   268,   269,   270,   271,   272,   273,   274,   275,
+     276,   277,   278,   279,   280,   281,   282,   283,   284,   285,
+     286,   287,   288,   289,   290,   291,   292,   293,   294,    -1,
+      -1,   297,   298,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,   314,   315,    -1,    -1,   318,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,   326,   327,   328,   329,    -1,    -1,    -1,
+     316,   317,    -1,    -1,   320,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,   328,   329,   330,   331,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,   347,   348,   349,   350,   351,   352,
-      -1,    -1,    -1,    -1,   357,   358,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,   349,   350,   351,   352,   353,   354,    -1,
+      -1,    -1,    -1,   359,   360,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,   377,   378,   379,   380,   381,   382,
-     383,   384,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,   394,     4,     5,     6,     7,     8,     9,    10,    11,
-      12,    13,    14,    15,    16,    17,    18,    19,    20,    21,
-      22,    23,    24,    25,    26,    27,    28,    29,    30,    31,
-      32,    33,    34,    35,    36,    37,    38,    39,    40,    41,
-      42,    43,    44,    45,    46,    47,    48,    49,    50,    51,
-      52,    53,    54,    55,    56,    57,    58,    59,    60,    -1,
-      -1,    63,    64,    65,    66,    67,    68,    69,    70,    71,
-      72,    73,    74,    75,    76,    77,    78,    79,    80,    81,
-      82,    83,    84,    85,    86,    87,    88,    89,    90,    91,
-      92,    93,    94,    95,    96,    97,    98,    99,   100,   101,
-     102,   103,   104,   105,   106,   107,   108,   109,   110,   111,
-     112,   113,   114,   115,   116,   117,   118,   119,   120,   121,
-     122,   123,   124,   125,   126,   127,   128,   129,   130,   131,
-     132,   133,   134,   135,   136,   137,   138,   139,   140,   141,
-     142,   143,   144,   145,   146,   147,   148,   149,   150,   151,
-     152,   153,   154,   155,   156,   157,   158,   159,   160,   161,
-     162,   163,   164,   165,   166,   167,   168,   169,   170,   171,
-     172,   173,   174,   175,   176,   177,   178,   179,   180,   181,
-     182,   183,   184,   185,   186,   187,   188,   189,   190,   191,
-     192,   193,   194,   195,   196,   197,   198,   199,   200,   201,
-     202,   203,   204,   205,   206,   207,   208,   209,   210,   211,
-     212,   213,   214,   215,   216,   217,   218,   219,   220,   221,
-     222,   223,   224,   225,   226,   227,   228,   229,   230,   231,
-     232,   233,   234,   235,   236,   237,   238,   239,   240,   241,
-     242,   243,   244,   245,   246,   247,   248,   249,   250,   251,
-     252,   253,   254,   255,   256,   257,   258,   259,   260,   261,
-     262,   263,   264,   265,   266,   267,   268,   269,   270,   271,
-     272,   273,   274,   275,   276,   277,   278,   279,   280,   281,
-     282,   283,   284,   285,   286,   287,   288,   289,   290,   291,
-     292,    -1,    -1,   295,   296,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,   314,   315,    -1,    -1,    -1,   319,    -1,    -1,
-      -1,    -1,    -1,    -1,   326,   327,   328,   329,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,   347,   348,   349,   350,   351,
-     352,    -1,    -1,    -1,    -1,   357,   358,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,   377,   378,   379,   380,   381,
-     382,   383,   384,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,   394,     4,     5,     6,     7,     8,     9,    10,
-      11,    12,    13,    14,    15,    16,    17,    18,    19,    20,
-      21,    22,    23,    24,    25,    26,    27,    28,    29,    30,
-      31,    32,    33,    34,    35,    36,    37,    38,    39,    40,
-      41,    42,    43,    44,    45,    46,    47,    48,    49,    50,
-      51,    52,    53,    54,    55,    56,    57,    58,    59,    60,
-      -1,    -1,    63,    64,    65,    66,    67,    68,    69,    70,
-      71,    72,    73,    74,    75,    76,    77,    78,    79,    80,
-      81,    82,    83,    84,    85,    86,    87,    88,    89,    90,
-      91,    92,    93,    94,    95,    96,    97,    98,    99,   100,
-     101,   102,   103,   104,   105,   106,   107,   108,   109,   110,
-     111,   112,   113,   114,   115,   116,   117,   118,   119,   120,
-     121,   122,   123,   124,   125,   126,   127,   128,   129,   130,
-     131,   132,   133,   134,   135,   136,   137,   138,   139,   140,
-     141,   142,   143,   144,   145,   146,   147,   148,   149,   150,
-     151,   152,   153,   154,   155,   156,   157,   158,   159,   160,
-     161,   162,   163,   164,   165,   166,   167,   168,   169,   170,
-     171,   172,   173,   174,   175,   176,   177,   178,   179,   180,
-     181,   182,   183,   184,   185,   186,   187,   188,   189,   190,
-     191,   192,   193,   194,   195,   196,   197,   198,   199,   200,
-     201,   202,   203,   204,   205,   206,   207,   208,   209,   210,
-     211,   212,   213,   214,   215,   216,   217,   218,   219,   220,
-     221,   222,   223,   224,   225,   226,   227,   228,   229,   230,
-     231,   232,   233,   234,   235,   236,   237,   238,   239,   240,
-     241,   242,   243,   244,   245,   246,   247,   248,   249,   250,
-     251,   252,   253,   254,   255,   256,   257,   258,   259,   260,
-     261,   262,   263,   264,   265,   266,   267,   268,   269,   270,
-     271,   272,   273,   274,   275,   276,   277,   278,   279,   280,
-     281,   282,   283,   284,   285,   286,   287,   288,   289,   290,
-     291,   292,    -1,    -1,   295,   296,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,   314,   315,    -1,    -1,   318,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,   326,   327,   328,   329,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,   347,   348,   349,   350,
-     351,   352,    -1,    -1,    -1,    -1,   357,   358,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,   377,   378,   379,   380,
-     381,   382,   383,   384,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,   394,     4,     5,     6,     7,     8,     9,
-      10,    11,    12,    13,    14,    15,    16,    17,    18,    19,
-      20,    21,    22,    23,    24,    25,    26,    27,    28,    29,
-      30,    31,    32,    33,    34,    35,    36,    37,    38,    39,
-      40,    41,    42,    43,    44,    45,    46,    47,    48,    49,
-      50,    51,    52,    53,    54,    55,    56,    57,    58,    59,
-      60,    -1,    -1,    63,    64,    65,    66,    67,    68,    69,
-      70,    71,    72,    73,    74,    75,    76,    77,    78,    79,
-      80,    81,    82,    83,    84,    85,    86,    87,    88,    89,
-      90,    91,    92,    93,    94,    95,    96,    97,    98,    99,
-     100,   101,   102,   103,   104,   105,   106,   107,   108,   109,
-     110,   111,   112,   113,   114,   115,   116,   117,   118,   119,
-     120,   121,   122,   123,   124,   125,   126,   127,   128,   129,
-     130,   131,   132,   133,   134,   135,   136,   137,   138,   139,
-     140,   141,   142,   143,   144,   145,   146,   147,   148,   149,
-     150,   151,   152,   153,   154,   155,   156,   157,   158,   159,
-     160,   161,   162,   163,   164,   165,   166,   167,   168,   169,
-     170,   171,   172,   173,   174,   175,   176,   177,   178,   179,
-     180,   181,   182,   183,   184,   185,   186,   187,   188,   189,
-     190,   191,   192,   193,   194,   195,   196,   197,   198,   199,
-     200,   201,   202,   203,   204,   205,   206,   207,   208,   209,
-     210,   211,   212,   213,   214,   215,   216,   217,   218,   219,
-     220,   221,   222,   223,   224,   225,   226,   227,   228,   229,
-     230,   231,   232,   233,   234,   235,   236,   237,   238,   239,
-     240,   241,   242,   243,   244,   245,   246,   247,   248,   249,
-     250,   251,   252,   253,   254,   255,   256,   257,   258,   259,
-     260,   261,   262,   263,   264,   265,   266,   267,   268,   269,
-     270,   271,   272,   273,   274,   275,   276,   277,   278,   279,
-     280,   281,   282,   283,   284,   285,   286,   287,   288,   289,
-     290,   291,   292,    -1,    -1,   295,   296,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,   314,   315,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,   325,   326,   327,   328,   329,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,   347,   348,   349,
-     350,   351,   352,    -1,    -1,    -1,    -1,   357,   358,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,   377,   378,   379,
-     380,   381,   382,   383,   384,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,   394,     4,     5,     6,     7,     8,
-       9,    10,    11,    12,    13,    14,    15,    16,    17,    18,
-      19,    20,    21,    22,    23,    24,    25,    26,    27,    28,
-      29,    30,    31,    32,    33,    34,    35,    36,    37,    38,
-      39,    40,    41,    42,    43,    44,    45,    46,    47,    48,
-      49,    50,    51,    52,    53,    54,    55,    56,    57,    58,
-      59,    60,    -1,    -1,    63,    64,    65,    66,    67,    68,
-      69,    70,    71,    72,    73,    74,    75,    76,    77,    78,
-      79,    80,    81,    82,    83,    84,    85,    86,    87,    88,
-      89,    90,    91,    92,    93,    94,    95,    96,    97,    98,
-      99,   100,   101,   102,   103,   104,   105,   106,   107,   108,
-     109,   110,   111,   112,   113,   114,   115,   116,   117,   118,
-     119,   120,   121,   122,   123,   124,   125,   126,   127,   128,
-     129,   130,   131,   132,   133,   134,   135,   136,   137,   138,
-     139,   140,   141,   142,   143,   144,   145,   146,   147,   148,
-     149,   150,   151,   152,   153,   154,   155,   156,   157,   158,
-     159,   160,   161,   162,   163,   164,   165,   166,   167,   168,
-     169,   170,   171,   172,   173,   174,   175,   176,   177,   178,
-     179,   180,   181,   182,   183,   184,   185,   186,   187,   188,
-     189,   190,   191,   192,   193,   194,   195,   196,   197,   198,
-     199,   200,   201,   202,   203,   204,   205,   206,   207,   208,
-     209,   210,   211,   212,   213,   214,   215,   216,   217,   218,
-     219,   220,   221,   222,   223,   224,   225,   226,   227,   228,
-     229,   230,   231,   232,   233,   234,   235,   236,   237,   238,
-     239,   240,   241,   242,   243,   244,   245,   246,   247,   248,
-     249,   250,   251,   252,   253,   254,   255,   256,   257,   258,
-     259,   260,   261,   262,   263,   264,   265,   266,   267,   268,
-     269,   270,   271,   272,   273,   274,   275,   276,   277,   278,
-     279,   280,   281,   282,   283,   284,   285,   286,   287,   288,
-     289,   290,   291,   292,    -1,    -1,   295,   296,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,   314,   315,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,   326,   327,   328,
-     329,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   347,   348,
-     349,   350,   351,   352,    -1,    -1,    -1,    -1,   357,   358,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   377,   378,
-     379,   380,   381,   382,   383,   384,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,   394,     4,     5,     6,     7,
+      -1,    -1,    -1,   379,   380,   381,   382,   383,   384,   385,
+     386,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,   401,     4,     5,     6,     7,
        8,     9,    10,    11,    12,    13,    14,    15,    16,    17,
       18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
       28,    29,    30,    31,    32,    33,    34,    35,    36,    37,
@@ -3250,26 +3139,186 @@
      258,   259,   260,   261,   262,   263,   264,   265,   266,   267,
      268,   269,   270,   271,   272,   273,   274,   275,   276,   277,
      278,   279,   280,   281,   282,   283,   284,   285,   286,   287,
-     288,   289,   290,   291,   292,   383,    -1,   295,   296,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   397,
-      -1,    -1,    -1,    -1,    -1,    -1,   314,   315,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,   414,   415,   326,   327,
-     328,   329,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   347,
-     348,   349,   350,   351,   352,    -1,    -1,    -1,   446,   357,
-     358,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   457,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   377,
-     378,   379,   380,   381,   382,   383,   384,    -1,   476,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,   394,    -1,    -1,    -1,
+     288,   289,   290,   291,   292,   293,   294,    -1,    -1,   297,
+     298,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   316,   317,
+      -1,    -1,    -1,   321,    -1,    -1,    -1,    -1,    -1,    -1,
+     328,   329,   330,   331,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,   349,   350,   351,   352,   353,   354,    -1,    -1,    -1,
+      -1,   359,   360,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,   379,   380,   381,   382,   383,   384,   385,   386,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,   401,     4,     5,     6,     7,     8,     9,
+      10,    11,    12,    13,    14,    15,    16,    17,    18,    19,
+      20,    21,    22,    23,    24,    25,    26,    27,    28,    29,
+      30,    31,    32,    33,    34,    35,    36,    37,    38,    39,
+      40,    41,    42,    43,    44,    45,    46,    47,    48,    49,
+      50,    51,    52,    53,    54,    55,    56,    57,    58,    59,
+      60,    -1,    -1,    63,    64,    65,    66,    67,    68,    69,
+      70,    71,    72,    73,    74,    75,    76,    77,    78,    79,
+      80,    81,    82,    83,    84,    85,    86,    87,    88,    89,
+      90,    91,    92,    93,    94,    95,    96,    97,    98,    99,
+     100,   101,   102,   103,   104,   105,   106,   107,   108,   109,
+     110,   111,   112,   113,   114,   115,   116,   117,   118,   119,
+     120,   121,   122,   123,   124,   125,   126,   127,   128,   129,
+     130,   131,   132,   133,   134,   135,   136,   137,   138,   139,
+     140,   141,   142,   143,   144,   145,   146,   147,   148,   149,
+     150,   151,   152,   153,   154,   155,   156,   157,   158,   159,
+     160,   161,   162,   163,   164,   165,   166,   167,   168,   169,
+     170,   171,   172,   173,   174,   175,   176,   177,   178,   179,
+     180,   181,   182,   183,   184,   185,   186,   187,   188,   189,
+     190,   191,   192,   193,   194,   195,   196,   197,   198,   199,
+     200,   201,   202,   203,   204,   205,   206,   207,   208,   209,
+     210,   211,   212,   213,   214,   215,   216,   217,   218,   219,
+     220,   221,   222,   223,   224,   225,   226,   227,   228,   229,
+     230,   231,   232,   233,   234,   235,   236,   237,   238,   239,
+     240,   241,   242,   243,   244,   245,   246,   247,   248,   249,
+     250,   251,   252,   253,   254,   255,   256,   257,   258,   259,
+     260,   261,   262,   263,   264,   265,   266,   267,   268,   269,
+     270,   271,   272,   273,   274,   275,   276,   277,   278,   279,
+     280,   281,   282,   283,   284,   285,   286,   287,   288,   289,
+     290,   291,   292,   293,   294,    -1,    -1,   297,   298,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,   316,   317,    -1,    -1,
+     320,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   328,   329,
+     330,   331,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   349,
+     350,   351,   352,   353,   354,    -1,    -1,    -1,    -1,   359,
+     360,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   379,
+     380,   381,   382,   383,   384,   385,   386,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,   401,     4,     5,     6,     7,     8,     9,    10,    11,
+      12,    13,    14,    15,    16,    17,    18,    19,    20,    21,
+      22,    23,    24,    25,    26,    27,    28,    29,    30,    31,
+      32,    33,    34,    35,    36,    37,    38,    39,    40,    41,
+      42,    43,    44,    45,    46,    47,    48,    49,    50,    51,
+      52,    53,    54,    55,    56,    57,    58,    59,    60,    -1,
+      -1,    63,    64,    65,    66,    67,    68,    69,    70,    71,
+      72,    73,    74,    75,    76,    77,    78,    79,    80,    81,
+      82,    83,    84,    85,    86,    87,    88,    89,    90,    91,
+      92,    93,    94,    95,    96,    97,    98,    99,   100,   101,
+     102,   103,   104,   105,   106,   107,   108,   109,   110,   111,
+     112,   113,   114,   115,   116,   117,   118,   119,   120,   121,
+     122,   123,   124,   125,   126,   127,   128,   129,   130,   131,
+     132,   133,   134,   135,   136,   137,   138,   139,   140,   141,
+     142,   143,   144,   145,   146,   147,   148,   149,   150,   151,
+     152,   153,   154,   155,   156,   157,   158,   159,   160,   161,
+     162,   163,   164,   165,   166,   167,   168,   169,   170,   171,
+     172,   173,   174,   175,   176,   177,   178,   179,   180,   181,
+     182,   183,   184,   185,   186,   187,   188,   189,   190,   191,
+     192,   193,   194,   195,   196,   197,   198,   199,   200,   201,
+     202,   203,   204,   205,   206,   207,   208,   209,   210,   211,
+     212,   213,   214,   215,   216,   217,   218,   219,   220,   221,
+     222,   223,   224,   225,   226,   227,   228,   229,   230,   231,
+     232,   233,   234,   235,   236,   237,   238,   239,   240,   241,
+     242,   243,   244,   245,   246,   247,   248,   249,   250,   251,
+     252,   253,   254,   255,   256,   257,   258,   259,   260,   261,
+     262,   263,   264,   265,   266,   267,   268,   269,   270,   271,
+     272,   273,   274,   275,   276,   277,   278,   279,   280,   281,
+     282,   283,   284,   285,   286,   287,   288,   289,   290,   291,
+     292,   293,   294,    -1,    -1,   297,   298,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,   316,   317,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,   327,   328,   329,   330,   331,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,   349,   350,   351,
+     352,   353,   354,    -1,    -1,    -1,    -1,   359,   360,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,   379,   380,   381,
+     382,   383,   384,   385,   386,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   401,
+       4,     5,     6,     7,     8,     9,    10,    11,    12,    13,
+      14,    15,    16,    17,    18,    19,    20,    21,    22,    23,
+      24,    25,    26,    27,    28,    29,    30,    31,    32,    33,
+      34,    35,    36,    37,    38,    39,    40,    41,    42,    43,
+      44,    45,    46,    47,    48,    49,    50,    51,    52,    53,
+      54,    55,    56,    57,    58,    59,    60,    -1,    -1,    63,
+      64,    65,    66,    67,    68,    69,    70,    71,    72,    73,
+      74,    75,    76,    77,    78,    79,    80,    81,    82,    83,
+      84,    85,    86,    87,    88,    89,    90,    91,    92,    93,
+      94,    95,    96,    97,    98,    99,   100,   101,   102,   103,
+     104,   105,   106,   107,   108,   109,   110,   111,   112,   113,
+     114,   115,   116,   117,   118,   119,   120,   121,   122,   123,
+     124,   125,   126,   127,   128,   129,   130,   131,   132,   133,
+     134,   135,   136,   137,   138,   139,   140,   141,   142,   143,
+     144,   145,   146,   147,   148,   149,   150,   151,   152,   153,
+     154,   155,   156,   157,   158,   159,   160,   161,   162,   163,
+     164,   165,   166,   167,   168,   169,   170,   171,   172,   173,
+     174,   175,   176,   177,   178,   179,   180,   181,   182,   183,
+     184,   185,   186,   187,   188,   189,   190,   191,   192,   193,
+     194,   195,   196,   197,   198,   199,   200,   201,   202,   203,
+     204,   205,   206,   207,   208,   209,   210,   211,   212,   213,
+     214,   215,   216,   217,   218,   219,   220,   221,   222,   223,
+     224,   225,   226,   227,   228,   229,   230,   231,   232,   233,
+     234,   235,   236,   237,   238,   239,   240,   241,   242,   243,
+     244,   245,   246,   247,   248,   249,   250,   251,   252,   253,
+     254,   255,   256,   257,   258,   259,   260,   261,   262,   263,
+     264,   265,   266,   267,   268,   269,   270,   271,   272,   273,
+     274,   275,   276,   277,   278,   279,   280,   281,   282,   283,
+     284,   285,   286,   287,   288,   289,   290,   291,   292,   293,
+     294,    -1,    -1,   297,   298,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,   316,   317,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,   328,   329,   330,   331,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,   349,   350,   351,   352,   353,
+     354,    -1,    -1,    -1,    -1,   359,   360,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,   379,   380,   381,   382,   383,
+     384,   385,   386,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,   401,     4,     5,
+       6,     7,     8,     9,    10,    11,    12,    13,    14,    15,
+      16,    17,    18,    19,    20,    21,    22,    23,    24,    25,
+      26,    27,    28,    29,    30,    31,    32,    33,    34,    35,
+      36,    37,    38,    39,    40,    41,    42,    43,    44,    45,
+      46,    47,    48,    49,    50,    51,    52,    53,    54,    55,
+      56,    57,    58,    59,    60,    -1,    -1,    63,    64,    65,
+      66,    67,    68,    69,    70,    71,    72,    73,    74,    75,
+      76,    77,    78,    79,    80,    81,    82,    83,    84,    85,
+      86,    87,    88,    89,    90,    91,    92,    93,    94,    95,
+      96,    97,    98,    99,   100,   101,   102,   103,   104,   105,
+     106,   107,   108,   109,   110,   111,   112,   113,   114,   115,
+     116,   117,   118,   119,   120,   121,   122,   123,   124,   125,
+     126,   127,   128,   129,   130,   131,   132,   133,   134,   135,
+     136,   137,   138,   139,   140,   141,   142,   143,   144,   145,
+     146,   147,   148,   149,   150,   151,   152,   153,   154,   155,
+     156,   157,   158,   159,   160,   161,   162,   163,   164,   165,
+     166,   167,   168,   169,   170,   171,   172,   173,   174,   175,
+     176,   177,   178,   179,   180,   181,   182,   183,   184,   185,
+     186,   187,   188,   189,   190,   191,   192,   193,   194,   195,
+     196,   197,   198,   199,   200,   201,   202,   203,   204,   205,
+     206,   207,   208,   209,   210,   211,   212,   213,   214,   215,
+     216,   217,   218,   219,   220,   221,   222,   223,   224,   225,
+     226,   227,   228,   229,   230,   231,   232,   233,   234,   235,
+     236,   237,   238,   239,   240,   241,   242,   243,   244,   245,
+     246,   247,   248,   249,   250,   251,   252,   253,   254,   255,
+     256,   257,   258,   259,   260,   261,   262,   263,   264,   265,
+     266,   267,   268,   269,   270,   271,   272,   273,   274,   275,
+     276,   277,   278,   279,   280,   281,   282,   283,   284,   285,
+     286,   287,   288,   289,   290,   291,   292,   293,   294,   391,
+      -1,   297,   298,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,   405,    -1,    -1,    -1,    -1,    -1,    -1,
+     316,   317,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+     422,   423,   328,   329,   330,   331,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,   349,   350,   351,   352,   353,   354,    -1,
+      -1,    -1,   454,   359,   360,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,   465,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,   379,   380,   381,   382,   383,   384,   385,
+     386,    -1,   484,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,   401,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   551,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,   543,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,   556,   557,
-     558,   559,   560,   561,   562,   563,   564,   565,   566,   567,
-     568,   569,   570,   571,   572,   573,   574,    -1,    -1,    -1,
+      -1,    -1,   564,   565,   566,   567,   568,   569,   570,   571,
+     572,   573,   574,   575,   576,   577,   578,   579,   580,   581,
+     582,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
@@ -3279,7 +3328,7 @@
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
       -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,   674
+     682
 };
 
   /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
@@ -3315,114 +3364,116 @@
      262,   263,   264,   265,   266,   267,   268,   269,   270,   271,
      272,   273,   274,   275,   276,   277,   278,   279,   280,   281,
      282,   283,   284,   285,   286,   287,   288,   289,   290,   291,
-     292,   325,   339,   340,   341,   342,   343,   352,   353,   354,
-     355,   356,   357,   358,   371,   372,   373,   374,   375,   376,
-     385,   387,   388,   389,   390,   391,   392,   393,   394,   395,
+     292,   293,   294,   327,   341,   342,   343,   344,   345,   354,
+     355,   356,   357,   358,   359,   360,   373,   374,   375,   376,
+     377,   378,   387,   389,   390,   391,   392,   393,   394,   395,
      396,   397,   398,   399,   400,   401,   402,   403,   404,   405,
-     406,   407,   408,   409,   410,   411,   443,   444,   447,   448,
-     449,   450,   454,   455,   456,   457,   458,   459,   462,   463,
-     464,   465,   466,   468,   473,   474,   475,   516,   517,   518,
-     474,   319,   351,   315,   315,   325,   351,   325,   519,   316,
-     322,   451,   452,   453,   463,   468,   322,   325,   351,   325,
-     351,   464,   468,   333,   470,   471,     0,   517,   468,   477,
-     319,   351,   372,   460,   461,   351,   467,   317,   325,   469,
-     319,   495,   452,   451,   453,   351,   351,   315,   324,   469,
-     319,   322,   325,   446,   295,   296,   314,   315,   326,   327,
-     328,   329,   347,   348,   349,   350,   351,   377,   378,   379,
-     380,   381,   382,   383,   384,   413,   414,   415,   417,   418,
-     419,   420,   421,   422,   423,   424,   425,   466,   468,   472,
-     469,   325,   463,   468,   478,   479,   476,   324,   316,   322,
-     316,   322,   318,   424,   426,   427,   428,   429,   430,   431,
-     432,   433,   434,   435,   436,   437,   317,   325,   317,   319,
-     320,   325,   359,   360,   361,   362,   364,   365,   366,   367,
-     368,   369,   370,   386,   424,   437,   439,   441,   443,   447,
-     466,   468,   484,   485,   486,   487,   488,   496,   497,   498,
-     499,   502,   503,   506,   507,   508,   515,   520,   469,   324,
-     469,   319,   439,   482,   324,   445,   351,   322,   325,   424,
-     424,   441,   295,   296,   317,   321,   316,   316,   322,   358,
-     439,   315,   424,   322,   334,   468,   351,   480,   481,   320,
-     479,   478,   437,   442,   461,   351,   330,   331,   332,   327,
-     329,   293,   294,   297,   298,   333,   334,   299,   300,   337,
-     336,   335,   301,   303,   302,   338,   318,   318,   437,   317,
-     320,   489,   315,   325,   325,   510,   315,   315,   325,   325,
-     441,   315,   441,   323,   325,   304,   305,   306,   307,   308,
-     309,   310,   311,   312,   313,   324,   440,   322,   325,   320,
-     485,   499,   503,   508,   482,   324,   482,   483,   482,   478,
-     351,   316,   416,   441,   351,   439,   424,   480,   469,   322,
-     325,   320,   424,   424,   424,   426,   426,   427,   427,   428,
-     428,   428,   428,   429,   429,   430,   431,   432,   433,   434,
-     435,   438,   318,   351,   521,   522,   496,   509,   485,   511,
-     441,   325,   441,   323,   439,   439,   482,   320,   322,   320,
-     318,   325,   481,   441,   315,   318,   322,   490,   441,   456,
-     463,   501,   359,   484,   497,   512,   316,   316,   320,   482,
-     323,   442,   318,   522,   320,   351,   316,   315,   501,   513,
-     514,   492,   493,   494,   500,   504,   439,   316,   324,   486,
-     491,   495,   441,   325,   316,   363,   488,   486,   319,   482,
-     316,   441,   491,   492,   496,   505,   325,   320
+     406,   407,   408,   409,   410,   411,   412,   413,   414,   415,
+     416,   417,   418,   419,   451,   452,   455,   456,   457,   458,
+     462,   463,   464,   465,   466,   467,   470,   471,   472,   473,
+     474,   476,   481,   482,   483,   524,   525,   526,   482,   321,
+     353,   317,   317,   327,   353,   327,   527,   318,   324,   459,
+     460,   461,   471,   476,   324,   327,   353,   327,   353,   472,
+     476,   335,   478,   479,     0,   525,   476,   485,   321,   353,
+     374,   468,   469,   353,   475,   319,   327,   477,   321,   503,
+     460,   459,   461,   353,   353,   317,   326,   477,   321,   324,
+     327,   454,   297,   298,   316,   317,   328,   329,   330,   331,
+     349,   350,   351,   352,   353,   379,   380,   381,   382,   383,
+     384,   385,   386,   421,   422,   423,   425,   426,   427,   428,
+     429,   430,   431,   432,   433,   474,   476,   480,   477,   327,
+     471,   476,   486,   487,   484,   326,   318,   324,   318,   324,
+     320,   432,   434,   435,   436,   437,   438,   439,   440,   441,
+     442,   443,   444,   445,   319,   327,   319,   321,   322,   327,
+     361,   362,   363,   364,   366,   367,   368,   369,   370,   371,
+     372,   388,   432,   445,   447,   449,   451,   455,   474,   476,
+     492,   493,   494,   495,   496,   504,   505,   506,   507,   510,
+     511,   514,   515,   516,   523,   528,   477,   326,   477,   321,
+     447,   490,   326,   453,   353,   324,   327,   432,   432,   449,
+     297,   298,   319,   323,   318,   318,   324,   360,   447,   317,
+     432,   324,   336,   476,   353,   488,   489,   322,   487,   486,
+     445,   450,   469,   353,   332,   333,   334,   329,   331,   295,
+     296,   299,   300,   335,   336,   301,   302,   339,   338,   337,
+     303,   305,   304,   340,   320,   320,   445,   319,   322,   497,
+     317,   327,   327,   518,   317,   317,   327,   327,   449,   317,
+     449,   325,   327,   306,   307,   308,   309,   310,   311,   312,
+     313,   314,   315,   326,   448,   324,   327,   322,   493,   507,
+     511,   516,   490,   326,   490,   491,   490,   486,   353,   318,
+     424,   449,   353,   447,   432,   488,   477,   324,   327,   322,
+     432,   432,   432,   434,   434,   435,   435,   436,   436,   436,
+     436,   437,   437,   438,   439,   440,   441,   442,   443,   446,
+     320,   353,   529,   530,   504,   517,   493,   519,   449,   327,
+     449,   325,   447,   447,   490,   322,   324,   322,   320,   327,
+     489,   449,   317,   320,   324,   498,   449,   464,   471,   509,
+     361,   492,   505,   520,   318,   318,   322,   490,   325,   450,
+     320,   530,   322,   353,   318,   317,   509,   521,   522,   500,
+     501,   502,   508,   512,   447,   318,   326,   494,   499,   503,
+     449,   327,   318,   365,   496,   494,   321,   490,   318,   449,
+     499,   500,   504,   513,   327,   322
 };
 
   /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const yytype_uint16 yyr1[] =
 {
-       0,   412,   413,   414,   414,   414,   414,   414,   414,   414,
-     414,   414,   414,   414,   414,   414,   414,   414,   415,   415,
-     415,   415,   415,   415,   416,   417,   418,   419,   419,   420,
-     420,   421,   421,   422,   423,   423,   423,   424,   424,   424,
-     424,   425,   425,   425,   425,   426,   426,   426,   426,   427,
-     427,   427,   428,   428,   428,   429,   429,   429,   429,   429,
-     430,   430,   430,   431,   431,   432,   432,   433,   433,   434,
-     434,   435,   435,   436,   436,   437,   438,   437,   439,   439,
-     440,   440,   440,   440,   440,   440,   440,   440,   440,   440,
-     440,   441,   441,   442,   443,   443,   443,   443,   443,   443,
-     443,   443,   443,   445,   444,   446,   446,   447,   448,   448,
-     449,   449,   450,   451,   451,   452,   452,   452,   452,   453,
-     454,   454,   454,   454,   454,   455,   455,   455,   455,   455,
-     456,   456,   457,   458,   458,   458,   458,   458,   458,   458,
-     458,   459,   460,   460,   461,   461,   461,   462,   463,   463,
-     464,   464,   464,   464,   464,   464,   464,   465,   465,   465,
-     465,   465,   465,   465,   465,   465,   465,   465,   465,   465,
-     465,   465,   465,   465,   465,   465,   465,   465,   465,   465,
-     465,   465,   465,   465,   465,   465,   466,   467,   467,   468,
-     468,   469,   469,   469,   469,   470,   470,   471,   472,   472,
+       0,   420,   421,   422,   422,   422,   422,   422,   422,   422,
+     422,   422,   422,   422,   422,   422,   422,   422,   423,   423,
+     423,   423,   423,   423,   424,   425,   426,   427,   427,   428,
+     428,   429,   429,   430,   431,   431,   431,   432,   432,   432,
+     432,   433,   433,   433,   433,   434,   434,   434,   434,   435,
+     435,   435,   436,   436,   436,   437,   437,   437,   437,   437,
+     438,   438,   438,   439,   439,   440,   440,   441,   441,   442,
+     442,   443,   443,   444,   444,   445,   446,   445,   447,   447,
+     448,   448,   448,   448,   448,   448,   448,   448,   448,   448,
+     448,   449,   449,   450,   451,   451,   451,   451,   451,   451,
+     451,   451,   451,   453,   452,   454,   454,   455,   456,   456,
+     457,   457,   458,   459,   459,   460,   460,   460,   460,   461,
+     462,   462,   462,   462,   462,   463,   463,   463,   463,   463,
+     464,   464,   465,   466,   466,   466,   466,   466,   466,   466,
+     466,   467,   468,   468,   469,   469,   469,   470,   471,   471,
+     472,   472,   472,   472,   472,   472,   472,   473,   473,   473,
      473,   473,   473,   473,   473,   473,   473,   473,   473,   473,
      473,   473,   473,   473,   473,   473,   473,   473,   473,   473,
      473,   473,   473,   473,   473,   473,   473,   473,   473,   473,
-     473,   473,   473,   473,   473,   473,   473,   473,   473,   473,
-     473,   473,   473,   473,   473,   473,   473,   473,   473,   473,
-     473,   473,   473,   473,   473,   473,   473,   473,   473,   473,
-     473,   473,   473,   473,   473,   473,   473,   473,   473,   473,
-     473,   473,   473,   473,   473,   473,   473,   473,   473,   473,
-     473,   473,   473,   473,   473,   473,   473,   473,   473,   473,
-     473,   473,   473,   473,   473,   473,   473,   473,   473,   473,
-     473,   473,   473,   473,   473,   473,   473,   473,   473,   473,
-     473,   473,   473,   473,   473,   473,   473,   473,   473,   473,
-     473,   473,   473,   473,   473,   473,   473,   473,   473,   473,
-     473,   473,   473,   473,   473,   473,   473,   473,   473,   473,
-     473,   473,   473,   473,   473,   473,   473,   473,   473,   473,
-     473,   473,   473,   473,   473,   473,   473,   473,   473,   473,
-     473,   473,   473,   473,   473,   473,   473,   473,   473,   473,
-     473,   473,   473,   473,   473,   473,   473,   473,   473,   473,
-     473,   473,   473,   473,   473,   473,   473,   473,   473,   473,
-     473,   473,   473,   473,   473,   473,   473,   473,   473,   473,
-     473,   473,   473,   473,   473,   473,   473,   473,   473,   473,
-     473,   473,   473,   473,   473,   473,   473,   473,   473,   473,
-     473,   473,   473,   473,   473,   473,   473,   473,   473,   473,
-     473,   473,   473,   473,   473,   473,   473,   473,   473,   473,
-     473,   473,   473,   473,   473,   473,   473,   473,   473,   473,
-     473,   473,   473,   473,   473,   473,   473,   473,   473,   473,
-     473,   473,   473,   473,   473,   473,   473,   473,   473,   473,
-     473,   473,   473,   473,   473,   473,   473,   473,   473,   473,
-     473,   473,   473,   473,   473,   473,   473,   473,   473,   473,
-     474,   474,   474,   476,   475,   477,   475,   478,   478,   479,
-     479,   480,   480,   481,   481,   482,   482,   482,   483,   483,
-     484,   485,   485,   486,   486,   486,   486,   486,   486,   486,
-     486,   487,   488,   489,   490,   488,   491,   491,   493,   492,
-     494,   492,   495,   495,   496,   496,   497,   497,   498,   498,
-     499,   500,   500,   501,   501,   502,   502,   504,   503,   505,
-     505,   506,   506,   507,   507,   509,   508,   510,   508,   511,
-     508,   512,   512,   513,   513,   514,   514,   515,   515,   515,
-     515,   515,   516,   516,   517,   517,   517,   519,   518,   520,
-     521,   521,   522,   522
+     473,   473,   474,   475,   475,   476,   476,   477,   477,   477,
+     477,   478,   478,   479,   480,   480,   481,   481,   481,   481,
+     481,   481,   481,   481,   481,   481,   481,   481,   481,   481,
+     481,   481,   481,   481,   481,   481,   481,   481,   481,   481,
+     481,   481,   481,   481,   481,   481,   481,   481,   481,   481,
+     481,   481,   481,   481,   481,   481,   481,   481,   481,   481,
+     481,   481,   481,   481,   481,   481,   481,   481,   481,   481,
+     481,   481,   481,   481,   481,   481,   481,   481,   481,   481,
+     481,   481,   481,   481,   481,   481,   481,   481,   481,   481,
+     481,   481,   481,   481,   481,   481,   481,   481,   481,   481,
+     481,   481,   481,   481,   481,   481,   481,   481,   481,   481,
+     481,   481,   481,   481,   481,   481,   481,   481,   481,   481,
+     481,   481,   481,   481,   481,   481,   481,   481,   481,   481,
+     481,   481,   481,   481,   481,   481,   481,   481,   481,   481,
+     481,   481,   481,   481,   481,   481,   481,   481,   481,   481,
+     481,   481,   481,   481,   481,   481,   481,   481,   481,   481,
+     481,   481,   481,   481,   481,   481,   481,   481,   481,   481,
+     481,   481,   481,   481,   481,   481,   481,   481,   481,   481,
+     481,   481,   481,   481,   481,   481,   481,   481,   481,   481,
+     481,   481,   481,   481,   481,   481,   481,   481,   481,   481,
+     481,   481,   481,   481,   481,   481,   481,   481,   481,   481,
+     481,   481,   481,   481,   481,   481,   481,   481,   481,   481,
+     481,   481,   481,   481,   481,   481,   481,   481,   481,   481,
+     481,   481,   481,   481,   481,   481,   481,   481,   481,   481,
+     481,   481,   481,   481,   481,   481,   481,   481,   481,   481,
+     481,   481,   481,   481,   481,   481,   481,   481,   481,   481,
+     481,   481,   481,   481,   481,   481,   481,   481,   481,   481,
+     481,   481,   481,   481,   481,   481,   481,   481,   481,   481,
+     481,   481,   481,   481,   481,   481,   481,   481,   481,   481,
+     481,   481,   481,   481,   481,   481,   481,   481,   481,   481,
+     481,   481,   481,   481,   481,   481,   481,   481,   482,   482,
+     482,   484,   483,   485,   483,   486,   486,   487,   487,   488,
+     488,   489,   489,   490,   490,   490,   491,   491,   492,   493,
+     493,   494,   494,   494,   494,   494,   494,   494,   494,   495,
+     496,   497,   498,   496,   499,   499,   501,   500,   502,   500,
+     503,   503,   504,   504,   505,   505,   506,   506,   507,   508,
+     508,   509,   509,   510,   510,   512,   511,   513,   513,   514,
+     514,   515,   515,   517,   516,   518,   516,   519,   516,   520,
+     520,   521,   521,   522,   522,   523,   523,   523,   523,   523,
+     524,   524,   525,   525,   525,   527,   526,   528,   529,   529,
+     530,   530
 };
 
   /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN.  */
@@ -3446,8 +3497,9 @@
        1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
        1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
        1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
-       1,     1,     1,     1,     1,     4,     1,     1,     3,     2,
-       3,     2,     3,     3,     4,     1,     0,     3,     1,     3,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
+       1,     4,     1,     1,     3,     2,     3,     2,     3,     3,
+       4,     1,     0,     3,     1,     3,     1,     1,     1,     1,
        1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
        1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
        1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
@@ -3477,16 +3529,16 @@
        1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
        1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
        1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
-       1,     1,     1,     0,     6,     0,     5,     1,     2,     3,
-       4,     1,     3,     1,     2,     1,     3,     4,     1,     3,
-       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
-       1,     2,     2,     0,     0,     5,     1,     1,     0,     2,
-       0,     2,     2,     3,     1,     2,     1,     2,     1,     2,
-       5,     3,     1,     1,     4,     1,     2,     0,     8,     0,
-       1,     3,     2,     1,     2,     0,     6,     0,     8,     0,
-       7,     1,     1,     1,     0,     2,     3,     2,     2,     2,
-       3,     2,     1,     2,     1,     1,     1,     0,     3,     5,
-       1,     3,     1,     4
+       1,     0,     6,     0,     5,     1,     2,     3,     4,     1,
+       3,     1,     2,     1,     3,     4,     1,     3,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,     2,
+       2,     0,     0,     5,     1,     1,     0,     2,     0,     2,
+       2,     3,     1,     2,     1,     2,     1,     2,     5,     3,
+       1,     1,     4,     1,     2,     0,     8,     0,     1,     3,
+       2,     1,     2,     0,     6,     0,     8,     0,     7,     1,
+       1,     1,     0,     2,     3,     2,     2,     2,     3,     2,
+       1,     2,     1,     1,     1,     0,     3,     5,     1,     3,
+       1,     4
 };
 
 
@@ -4169,260 +4221,260 @@
   switch (yyn)
     {
         case 2:
-#line 353 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 357 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermTypedNode) = parseContext.handleVariable((yyvsp[0].lex).loc, (yyvsp[0].lex).symbol, (yyvsp[0].lex).string);
     }
-#line 4177 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4229 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 3:
-#line 359 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 363 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
     }
-#line 4185 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4237 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 4:
-#line 362 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 366 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermTypedNode) = (yyvsp[-1].interm.intermTypedNode);
         if ((yyval.interm.intermTypedNode)->getAsConstantUnion())
             (yyval.interm.intermTypedNode)->getAsConstantUnion()->setExpression();
     }
-#line 4195 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4247 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 5:
-#line 367 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 371 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).d, EbtFloat, (yyvsp[0].lex).loc, true);
     }
-#line 4203 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4255 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 6:
-#line 370 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 374 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).i, (yyvsp[0].lex).loc, true);
     }
-#line 4211 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4263 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 7:
-#line 373 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 377 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned literal");
         (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).u, (yyvsp[0].lex).loc, true);
     }
-#line 4220 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4272 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 8:
-#line 377 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 381 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).b, (yyvsp[0].lex).loc, true);
     }
-#line 4228 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4280 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 9:
-#line 381 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 385 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).string, (yyvsp[0].lex).loc, true);
     }
-#line 4236 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4288 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 10:
-#line 384 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 388 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed literal");
         (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).i, (yyvsp[0].lex).loc, true);
     }
-#line 4245 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4297 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 11:
-#line 388 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 392 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed literal");
         (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).u, (yyvsp[0].lex).loc, true);
     }
-#line 4254 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4306 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 12:
-#line 392 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 396 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer literal");
         (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).i64, (yyvsp[0].lex).loc, true);
     }
-#line 4263 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4315 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 13:
-#line 396 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 400 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer literal");
         (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).u64, (yyvsp[0].lex).loc, true);
     }
-#line 4272 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4324 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 14:
-#line 400 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 404 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.explicitInt16Check((yyvsp[0].lex).loc, "16-bit integer literal");
         (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((short)(yyvsp[0].lex).i, (yyvsp[0].lex).loc, true);
     }
-#line 4281 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4333 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 15:
-#line 404 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 408 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.explicitInt16Check((yyvsp[0].lex).loc, "16-bit unsigned integer literal");
         (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((unsigned short)(yyvsp[0].lex).u, (yyvsp[0].lex).loc, true);
     }
-#line 4290 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4342 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 16:
-#line 408 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 412 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double literal");
         if (! parseContext.symbolTable.atBuiltInLevel())
             parseContext.doubleCheck((yyvsp[0].lex).loc, "double literal");
         (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).d, EbtDouble, (yyvsp[0].lex).loc, true);
     }
-#line 4301 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4353 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 17:
-#line 414 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 418 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16Check((yyvsp[0].lex).loc, "half float literal");
         (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).d, EbtFloat16, (yyvsp[0].lex).loc, true);
     }
-#line 4310 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4362 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 18:
-#line 422 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 426 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
     }
-#line 4318 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4370 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 19:
-#line 425 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 429 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermTypedNode) = parseContext.handleBracketDereference((yyvsp[-2].lex).loc, (yyvsp[-3].interm.intermTypedNode), (yyvsp[-1].interm.intermTypedNode));
     }
-#line 4326 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4378 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 20:
-#line 428 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 432 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
     }
-#line 4334 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4386 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 21:
-#line 431 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 435 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermTypedNode) = parseContext.handleDotDereference((yyvsp[0].lex).loc, (yyvsp[-2].interm.intermTypedNode), *(yyvsp[0].lex).string);
     }
-#line 4342 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4394 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 22:
-#line 434 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 438 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.variableCheck((yyvsp[-1].interm.intermTypedNode));
         parseContext.lValueErrorCheck((yyvsp[0].lex).loc, "++", (yyvsp[-1].interm.intermTypedNode));
         (yyval.interm.intermTypedNode) = parseContext.handleUnaryMath((yyvsp[0].lex).loc, "++", EOpPostIncrement, (yyvsp[-1].interm.intermTypedNode));
     }
-#line 4352 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4404 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 23:
-#line 439 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 443 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.variableCheck((yyvsp[-1].interm.intermTypedNode));
         parseContext.lValueErrorCheck((yyvsp[0].lex).loc, "--", (yyvsp[-1].interm.intermTypedNode));
         (yyval.interm.intermTypedNode) = parseContext.handleUnaryMath((yyvsp[0].lex).loc, "--", EOpPostDecrement, (yyvsp[-1].interm.intermTypedNode));
     }
-#line 4362 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4414 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 24:
-#line 447 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 451 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.integerCheck((yyvsp[0].interm.intermTypedNode), "[]");
         (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
     }
-#line 4371 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4423 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 25:
-#line 454 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 458 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermTypedNode) = parseContext.handleFunctionCall((yyvsp[0].interm).loc, (yyvsp[0].interm).function, (yyvsp[0].interm).intermNode);
         delete (yyvsp[0].interm).function;
     }
-#line 4380 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4432 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 26:
-#line 461 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 465 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm) = (yyvsp[0].interm);
     }
-#line 4388 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4440 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 27:
-#line 467 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 471 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm) = (yyvsp[-1].interm);
         (yyval.interm).loc = (yyvsp[0].lex).loc;
     }
-#line 4397 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4449 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 28:
-#line 471 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 475 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm) = (yyvsp[-1].interm);
         (yyval.interm).loc = (yyvsp[0].lex).loc;
     }
-#line 4406 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4458 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 29:
-#line 478 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 482 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm) = (yyvsp[-1].interm);
     }
-#line 4414 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4466 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 30:
-#line 481 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 485 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm) = (yyvsp[0].interm);
     }
-#line 4422 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4474 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 31:
-#line 487 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 491 "glslang.y" /* yacc.c:1646  */
     {
         TParameter param = { 0, new TType };
         param.type->shallowCopy((yyvsp[0].interm.intermTypedNode)->getType());
@@ -4430,11 +4482,11 @@
         (yyval.interm).function = (yyvsp[-1].interm).function;
         (yyval.interm).intermNode = (yyvsp[0].interm.intermTypedNode);
     }
-#line 4434 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4486 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 32:
-#line 494 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 498 "glslang.y" /* yacc.c:1646  */
     {
         TParameter param = { 0, new TType };
         param.type->shallowCopy((yyvsp[0].interm.intermTypedNode)->getType());
@@ -4442,29 +4494,29 @@
         (yyval.interm).function = (yyvsp[-2].interm).function;
         (yyval.interm).intermNode = parseContext.intermediate.growAggregate((yyvsp[-2].interm).intermNode, (yyvsp[0].interm.intermTypedNode), (yyvsp[-1].lex).loc);
     }
-#line 4446 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4498 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 33:
-#line 504 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 508 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm) = (yyvsp[-1].interm);
     }
-#line 4454 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4506 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 34:
-#line 512 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 516 "glslang.y" /* yacc.c:1646  */
     {
         // Constructor
         (yyval.interm).intermNode = 0;
         (yyval.interm).function = parseContext.handleConstructorCall((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type));
     }
-#line 4464 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4516 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 35:
-#line 517 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 521 "glslang.y" /* yacc.c:1646  */
     {
         //
         // Should be a method or subroutine call, but we haven't recognized the arguments yet.
@@ -4492,50 +4544,50 @@
             (yyval.interm).function = new TFunction(empty, TType(EbtVoid), EOpNull);
         }
     }
-#line 4496 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4548 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 36:
-#line 545 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 549 "glslang.y" /* yacc.c:1646  */
     {
         // Constructor
         (yyval.interm).intermNode = 0;
         (yyval.interm).function = parseContext.handleConstructorCall((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type));
     }
-#line 4506 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4558 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 37:
-#line 554 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 558 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.variableCheck((yyvsp[0].interm.intermTypedNode));
         (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
         if (TIntermMethod* method = (yyvsp[0].interm.intermTypedNode)->getAsMethodNode())
             parseContext.error((yyvsp[0].interm.intermTypedNode)->getLoc(), "incomplete method syntax", method->getMethodName().c_str(), "");
     }
-#line 4517 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4569 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 38:
-#line 560 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 564 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.lValueErrorCheck((yyvsp[-1].lex).loc, "++", (yyvsp[0].interm.intermTypedNode));
         (yyval.interm.intermTypedNode) = parseContext.handleUnaryMath((yyvsp[-1].lex).loc, "++", EOpPreIncrement, (yyvsp[0].interm.intermTypedNode));
     }
-#line 4526 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4578 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 39:
-#line 564 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 568 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.lValueErrorCheck((yyvsp[-1].lex).loc, "--", (yyvsp[0].interm.intermTypedNode));
         (yyval.interm.intermTypedNode) = parseContext.handleUnaryMath((yyvsp[-1].lex).loc, "--", EOpPreDecrement, (yyvsp[0].interm.intermTypedNode));
     }
-#line 4535 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4587 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 40:
-#line 568 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 572 "glslang.y" /* yacc.c:1646  */
     {
         if ((yyvsp[-1].interm).op != EOpNull) {
             char errorOp[2] = {0, 0};
@@ -4552,179 +4604,179 @@
                 (yyval.interm.intermTypedNode)->getAsConstantUnion()->setExpression();
         }
     }
-#line 4556 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4608 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 41:
-#line 588 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 592 "glslang.y" /* yacc.c:1646  */
     { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpNull; }
-#line 4562 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4614 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 42:
-#line 589 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 593 "glslang.y" /* yacc.c:1646  */
     { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpNegative; }
-#line 4568 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4620 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 43:
-#line 590 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 594 "glslang.y" /* yacc.c:1646  */
     { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpLogicalNot; }
-#line 4574 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4626 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 44:
-#line 591 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 595 "glslang.y" /* yacc.c:1646  */
     { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpBitwiseNot;
               parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bitwise not"); }
-#line 4581 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4633 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 45:
-#line 597 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 601 "glslang.y" /* yacc.c:1646  */
     { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
-#line 4587 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4639 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 46:
-#line 598 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 602 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "*", EOpMul, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
         if ((yyval.interm.intermTypedNode) == 0)
             (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
     }
-#line 4597 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4649 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 47:
-#line 603 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 607 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "/", EOpDiv, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
         if ((yyval.interm.intermTypedNode) == 0)
             (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
     }
-#line 4607 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4659 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 48:
-#line 608 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 612 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "%");
         (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "%", EOpMod, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
         if ((yyval.interm.intermTypedNode) == 0)
             (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
     }
-#line 4618 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4670 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 49:
-#line 617 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 621 "glslang.y" /* yacc.c:1646  */
     { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
-#line 4624 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4676 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 50:
-#line 618 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 622 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "+", EOpAdd, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
         if ((yyval.interm.intermTypedNode) == 0)
             (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
     }
-#line 4634 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4686 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 51:
-#line 623 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 627 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "-", EOpSub, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
         if ((yyval.interm.intermTypedNode) == 0)
             (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
     }
-#line 4644 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4696 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 52:
-#line 631 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 635 "glslang.y" /* yacc.c:1646  */
     { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
-#line 4650 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4702 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 53:
-#line 632 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 636 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bit shift left");
         (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "<<", EOpLeftShift, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
         if ((yyval.interm.intermTypedNode) == 0)
             (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
     }
-#line 4661 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4713 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 54:
-#line 638 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 642 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bit shift right");
         (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, ">>", EOpRightShift, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
         if ((yyval.interm.intermTypedNode) == 0)
             (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
     }
-#line 4672 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4724 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 55:
-#line 647 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 651 "glslang.y" /* yacc.c:1646  */
     { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
-#line 4678 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4730 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 56:
-#line 648 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 652 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "<", EOpLessThan, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
         if ((yyval.interm.intermTypedNode) == 0)
             (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc);
     }
-#line 4688 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4740 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 57:
-#line 653 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 657 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, ">", EOpGreaterThan, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
         if ((yyval.interm.intermTypedNode) == 0)
             (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc);
     }
-#line 4698 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4750 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 58:
-#line 658 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 662 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "<=", EOpLessThanEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
         if ((yyval.interm.intermTypedNode) == 0)
             (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc);
     }
-#line 4708 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4760 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 59:
-#line 663 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 667 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, ">=", EOpGreaterThanEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
         if ((yyval.interm.intermTypedNode) == 0)
             (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc);
     }
-#line 4718 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4770 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 60:
-#line 671 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 675 "glslang.y" /* yacc.c:1646  */
     { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
-#line 4724 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4776 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 61:
-#line 672 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 676 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.arrayObjectCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "array comparison");
         parseContext.opaqueCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "==");
@@ -4734,11 +4786,11 @@
         if ((yyval.interm.intermTypedNode) == 0)
             (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc);
     }
-#line 4738 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4790 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 62:
-#line 681 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 685 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.arrayObjectCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "array comparison");
         parseContext.opaqueCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "!=");
@@ -4748,124 +4800,124 @@
         if ((yyval.interm.intermTypedNode) == 0)
             (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc);
     }
-#line 4752 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4804 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 63:
-#line 693 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 697 "glslang.y" /* yacc.c:1646  */
     { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
-#line 4758 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4810 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 64:
-#line 694 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 698 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bitwise and");
         (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "&", EOpAnd, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
         if ((yyval.interm.intermTypedNode) == 0)
             (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
     }
-#line 4769 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4821 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 65:
-#line 703 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 707 "glslang.y" /* yacc.c:1646  */
     { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
-#line 4775 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4827 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 66:
-#line 704 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 708 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bitwise exclusive or");
         (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "^", EOpExclusiveOr, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
         if ((yyval.interm.intermTypedNode) == 0)
             (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
     }
-#line 4786 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4838 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 67:
-#line 713 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 717 "glslang.y" /* yacc.c:1646  */
     { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
-#line 4792 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4844 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 68:
-#line 714 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 718 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bitwise inclusive or");
         (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "|", EOpInclusiveOr, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
         if ((yyval.interm.intermTypedNode) == 0)
             (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
     }
-#line 4803 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4855 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 69:
-#line 723 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 727 "glslang.y" /* yacc.c:1646  */
     { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
-#line 4809 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4861 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 70:
-#line 724 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 728 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "&&", EOpLogicalAnd, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
         if ((yyval.interm.intermTypedNode) == 0)
             (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc);
     }
-#line 4819 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4871 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 71:
-#line 732 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 736 "glslang.y" /* yacc.c:1646  */
     { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
-#line 4825 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4877 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 72:
-#line 733 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 737 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "^^", EOpLogicalXor, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
         if ((yyval.interm.intermTypedNode) == 0)
             (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc);
     }
-#line 4835 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4887 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 73:
-#line 741 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 745 "glslang.y" /* yacc.c:1646  */
     { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
-#line 4841 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4893 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 74:
-#line 742 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 746 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "||", EOpLogicalOr, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
         if ((yyval.interm.intermTypedNode) == 0)
             (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc);
     }
-#line 4851 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4903 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 75:
-#line 750 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 754 "glslang.y" /* yacc.c:1646  */
     { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
-#line 4857 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4909 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 76:
-#line 751 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 755 "glslang.y" /* yacc.c:1646  */
     {
         ++parseContext.controlFlowNestingLevel;
     }
-#line 4865 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4917 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 77:
-#line 754 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 758 "glslang.y" /* yacc.c:1646  */
     {
         --parseContext.controlFlowNestingLevel;
         parseContext.boolCheck((yyvsp[-4].lex).loc, (yyvsp[-5].interm.intermTypedNode));
@@ -4878,17 +4930,17 @@
             (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
         }
     }
-#line 4882 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4934 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 78:
-#line 769 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 773 "glslang.y" /* yacc.c:1646  */
     { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); }
-#line 4888 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4940 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 79:
-#line 770 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 774 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.arrayObjectCheck((yyvsp[-1].interm).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "array assignment");
         parseContext.opaqueCheck((yyvsp[-1].interm).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "=");
@@ -4902,119 +4954,119 @@
             (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
         }
     }
-#line 4906 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4958 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 80:
-#line 786 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 790 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm).loc = (yyvsp[0].lex).loc;
         (yyval.interm).op = EOpAssign;
     }
-#line 4915 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4967 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 81:
-#line 790 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 794 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm).loc = (yyvsp[0].lex).loc;
         (yyval.interm).op = EOpMulAssign;
     }
-#line 4924 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4976 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 82:
-#line 794 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 798 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm).loc = (yyvsp[0].lex).loc;
         (yyval.interm).op = EOpDivAssign;
     }
-#line 4933 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4985 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 83:
-#line 798 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 802 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "%=");
         (yyval.interm).loc = (yyvsp[0].lex).loc;
         (yyval.interm).op = EOpModAssign;
     }
-#line 4943 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 4995 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 84:
-#line 803 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 807 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm).loc = (yyvsp[0].lex).loc;
         (yyval.interm).op = EOpAddAssign;
     }
-#line 4952 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5004 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 85:
-#line 807 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 811 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm).loc = (yyvsp[0].lex).loc;
         (yyval.interm).op = EOpSubAssign;
     }
-#line 4961 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5013 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 86:
-#line 811 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 815 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bit-shift left assign");
         (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpLeftShiftAssign;
     }
-#line 4970 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5022 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 87:
-#line 815 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 819 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bit-shift right assign");
         (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpRightShiftAssign;
     }
-#line 4979 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5031 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 88:
-#line 819 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 823 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bitwise-and assign");
         (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpAndAssign;
     }
-#line 4988 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5040 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 89:
-#line 823 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 827 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bitwise-xor assign");
         (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpExclusiveOrAssign;
     }
-#line 4997 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5049 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 90:
-#line 827 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 831 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bitwise-or assign");
         (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpInclusiveOrAssign;
     }
-#line 5006 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5058 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 91:
-#line 834 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 838 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
     }
-#line 5014 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5066 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 92:
-#line 837 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 841 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.samplerConstructorLocationCheck((yyvsp[-1].lex).loc, ",", (yyvsp[0].interm.intermTypedNode));
         (yyval.interm.intermTypedNode) = parseContext.intermediate.addComma((yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yyvsp[-1].lex).loc);
@@ -5023,40 +5075,40 @@
             (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
         }
     }
-#line 5027 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5079 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 93:
-#line 848 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 852 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.constantValueCheck((yyvsp[0].interm.intermTypedNode), "");
         (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
     }
-#line 5036 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5088 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 94:
-#line 855 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 859 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.handleFunctionDeclarator((yyvsp[-1].interm).loc, *(yyvsp[-1].interm).function, true /* prototype */);
         (yyval.interm.intermNode) = 0;
         // TODO: 4.0 functionality: subroutines: make the identifier a user type for this signature
     }
-#line 5046 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5098 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 95:
-#line 860 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 864 "glslang.y" /* yacc.c:1646  */
     {
         if ((yyvsp[-1].interm).intermNode && (yyvsp[-1].interm).intermNode->getAsAggregate())
             (yyvsp[-1].interm).intermNode->getAsAggregate()->setOperator(EOpSequence);
         (yyval.interm.intermNode) = (yyvsp[-1].interm).intermNode;
     }
-#line 5056 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5108 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 96:
-#line 865 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 869 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.profileRequires((yyvsp[-3].lex).loc, ENoProfile, 130, 0, "precision statement");
         // lazy setting of the previous scope's defaults, has effect only the first time it is called in a particular scope
@@ -5064,75 +5116,75 @@
         parseContext.setDefaultPrecision((yyvsp[-3].lex).loc, (yyvsp[-1].interm.type), (yyvsp[-2].interm.type).qualifier.precision);
         (yyval.interm.intermNode) = 0;
     }
-#line 5068 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5120 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 97:
-#line 872 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 876 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.declareBlock((yyvsp[-1].interm).loc, *(yyvsp[-1].interm).typeList);
         (yyval.interm.intermNode) = 0;
     }
-#line 5077 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5129 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 98:
-#line 876 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 880 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.declareBlock((yyvsp[-2].interm).loc, *(yyvsp[-2].interm).typeList, (yyvsp[-1].lex).string);
         (yyval.interm.intermNode) = 0;
     }
-#line 5086 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5138 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 99:
-#line 880 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 884 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.declareBlock((yyvsp[-3].interm).loc, *(yyvsp[-3].interm).typeList, (yyvsp[-2].lex).string, (yyvsp[-1].interm).arraySizes);
         (yyval.interm.intermNode) = 0;
     }
-#line 5095 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5147 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 100:
-#line 884 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 888 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.globalQualifierFixCheck((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier);
         parseContext.updateStandaloneQualifierDefaults((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type));
         (yyval.interm.intermNode) = 0;
     }
-#line 5105 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5157 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 101:
-#line 889 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 893 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.checkNoShaderLayouts((yyvsp[-2].interm.type).loc, (yyvsp[-2].interm.type).shaderQualifiers);
         parseContext.addQualifierToExisting((yyvsp[-2].interm.type).loc, (yyvsp[-2].interm.type).qualifier, *(yyvsp[-1].lex).string);
         (yyval.interm.intermNode) = 0;
     }
-#line 5115 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5167 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 102:
-#line 894 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 898 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.checkNoShaderLayouts((yyvsp[-3].interm.type).loc, (yyvsp[-3].interm.type).shaderQualifiers);
         (yyvsp[-1].interm.identifierList)->push_back((yyvsp[-2].lex).string);
         parseContext.addQualifierToExisting((yyvsp[-3].interm.type).loc, (yyvsp[-3].interm.type).qualifier, *(yyvsp[-1].interm.identifierList));
         (yyval.interm.intermNode) = 0;
     }
-#line 5126 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5178 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 103:
-#line 903 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 907 "glslang.y" /* yacc.c:1646  */
     { parseContext.nestedBlockCheck((yyvsp[-2].interm.type).loc); }
-#line 5132 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5184 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 104:
-#line 903 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 907 "glslang.y" /* yacc.c:1646  */
     {
         --parseContext.structNestingLevel;
         parseContext.blockName = (yyvsp[-4].lex).string;
@@ -5142,54 +5194,54 @@
         (yyval.interm).loc = (yyvsp[-5].interm.type).loc;
         (yyval.interm).typeList = (yyvsp[-1].interm.typeList);
     }
-#line 5146 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5198 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 105:
-#line 914 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 918 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.identifierList) = new TIdentifierList;
         (yyval.interm.identifierList)->push_back((yyvsp[0].lex).string);
     }
-#line 5155 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5207 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 106:
-#line 918 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 922 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.identifierList) = (yyvsp[-2].interm.identifierList);
         (yyval.interm.identifierList)->push_back((yyvsp[0].lex).string);
     }
-#line 5164 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5216 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 107:
-#line 925 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 929 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm).function = (yyvsp[-1].interm.function);
         (yyval.interm).loc = (yyvsp[0].lex).loc;
     }
-#line 5173 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5225 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 108:
-#line 932 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 936 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.function) = (yyvsp[0].interm.function);
     }
-#line 5181 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5233 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 109:
-#line 935 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 939 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.function) = (yyvsp[0].interm.function);
     }
-#line 5189 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5241 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 110:
-#line 942 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 946 "glslang.y" /* yacc.c:1646  */
     {
         // Add the parameter
         (yyval.interm.function) = (yyvsp[-1].interm.function);
@@ -5198,11 +5250,11 @@
         else
             delete (yyvsp[0].interm).param.type;
     }
-#line 5202 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5254 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 111:
-#line 950 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 954 "glslang.y" /* yacc.c:1646  */
     {
         //
         // Only first parameter of one-parameter functions can be void
@@ -5220,11 +5272,11 @@
             (yyvsp[-2].interm.function)->addParameter((yyvsp[0].interm).param);
         }
     }
-#line 5224 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5276 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 112:
-#line 970 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 974 "glslang.y" /* yacc.c:1646  */
     {
         if ((yyvsp[-2].interm.type).qualifier.storage != EvqGlobal && (yyvsp[-2].interm.type).qualifier.storage != EvqTemporary) {
             parseContext.error((yyvsp[-1].lex).loc, "no qualifiers allowed for function return",
@@ -5244,11 +5296,11 @@
         function = new TFunction((yyvsp[-1].lex).string, type);
         (yyval.interm.function) = function;
     }
-#line 5248 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5300 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 113:
-#line 993 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 997 "glslang.y" /* yacc.c:1646  */
     {
         if ((yyvsp[-1].interm.type).arraySizes) {
             parseContext.profileRequires((yyvsp[-1].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type");
@@ -5264,11 +5316,11 @@
         (yyval.interm).loc = (yyvsp[0].lex).loc;
         (yyval.interm).param = param;
     }
-#line 5268 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5320 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 114:
-#line 1008 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1012 "glslang.y" /* yacc.c:1646  */
     {
         if ((yyvsp[-2].interm.type).arraySizes) {
             parseContext.profileRequires((yyvsp[-2].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type");
@@ -5288,11 +5340,11 @@
         (yyval.interm).loc = (yyvsp[-1].lex).loc;
         (yyval.interm).param = param;
     }
-#line 5292 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5344 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 115:
-#line 1033 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1037 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm) = (yyvsp[0].interm);
         if ((yyvsp[-1].interm.type).qualifier.precision != EpqNone)
@@ -5304,11 +5356,11 @@
         parseContext.paramCheckFix((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier, *(yyval.interm).param.type);
 
     }
-#line 5308 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5360 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 116:
-#line 1044 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1048 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm) = (yyvsp[0].interm);
 
@@ -5316,11 +5368,11 @@
         parseContext.paramCheckFixStorage((yyvsp[0].interm).loc, EvqTemporary, *(yyval.interm).param.type);
         parseContext.precisionQualifierCheck((yyval.interm).loc, (yyval.interm).param.type->getBasicType(), (yyval.interm).param.type->getQualifier());
     }
-#line 5320 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5372 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 117:
-#line 1054 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1058 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm) = (yyvsp[0].interm);
         if ((yyvsp[-1].interm.type).qualifier.precision != EpqNone)
@@ -5331,11 +5383,11 @@
         parseContext.parameterTypeCheck((yyvsp[0].interm).loc, (yyvsp[-1].interm.type).qualifier.storage, *(yyval.interm).param.type);
         parseContext.paramCheckFix((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier, *(yyval.interm).param.type);
     }
-#line 5335 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5387 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 118:
-#line 1064 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1068 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm) = (yyvsp[0].interm);
 
@@ -5343,68 +5395,68 @@
         parseContext.paramCheckFixStorage((yyvsp[0].interm).loc, EvqTemporary, *(yyval.interm).param.type);
         parseContext.precisionQualifierCheck((yyval.interm).loc, (yyval.interm).param.type->getBasicType(), (yyval.interm).param.type->getQualifier());
     }
-#line 5347 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5399 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 119:
-#line 1074 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1078 "glslang.y" /* yacc.c:1646  */
     {
         TParameter param = { 0, new TType((yyvsp[0].interm.type)) };
         (yyval.interm).param = param;
         if ((yyvsp[0].interm.type).arraySizes)
             parseContext.arraySizeRequiredCheck((yyvsp[0].interm.type).loc, *(yyvsp[0].interm.type).arraySizes);
     }
-#line 5358 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5410 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 120:
-#line 1083 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1087 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm) = (yyvsp[0].interm);
     }
-#line 5366 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5418 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 121:
-#line 1086 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1090 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm) = (yyvsp[-2].interm);
         parseContext.declareVariable((yyvsp[0].lex).loc, *(yyvsp[0].lex).string, (yyvsp[-2].interm).type);
     }
-#line 5375 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5427 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 122:
-#line 1090 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1094 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm) = (yyvsp[-3].interm);
         parseContext.declareVariable((yyvsp[-1].lex).loc, *(yyvsp[-1].lex).string, (yyvsp[-3].interm).type, (yyvsp[0].interm).arraySizes);
     }
-#line 5384 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5436 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 123:
-#line 1094 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1098 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm).type = (yyvsp[-5].interm).type;
         TIntermNode* initNode = parseContext.declareVariable((yyvsp[-3].lex).loc, *(yyvsp[-3].lex).string, (yyvsp[-5].interm).type, (yyvsp[-2].interm).arraySizes, (yyvsp[0].interm.intermTypedNode));
         (yyval.interm).intermNode = parseContext.intermediate.growAggregate((yyvsp[-5].interm).intermNode, initNode, (yyvsp[-1].lex).loc);
     }
-#line 5394 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5446 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 124:
-#line 1099 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1103 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm).type = (yyvsp[-4].interm).type;
         TIntermNode* initNode = parseContext.declareVariable((yyvsp[-2].lex).loc, *(yyvsp[-2].lex).string, (yyvsp[-4].interm).type, 0, (yyvsp[0].interm.intermTypedNode));
         (yyval.interm).intermNode = parseContext.intermediate.growAggregate((yyvsp[-4].interm).intermNode, initNode, (yyvsp[-1].lex).loc);
     }
-#line 5404 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5456 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 125:
-#line 1107 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1111 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm).type = (yyvsp[0].interm.type);
         (yyval.interm).intermNode = 0;
@@ -5412,51 +5464,51 @@
         parseContext.declareTypeDefaults((yyval.interm).loc, (yyval.interm).type);
 
     }
-#line 5416 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5468 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 126:
-#line 1114 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1118 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm).type = (yyvsp[-1].interm.type);
         (yyval.interm).intermNode = 0;
         parseContext.declareVariable((yyvsp[0].lex).loc, *(yyvsp[0].lex).string, (yyvsp[-1].interm.type));
     }
-#line 5426 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5478 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 127:
-#line 1119 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1123 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm).type = (yyvsp[-2].interm.type);
         (yyval.interm).intermNode = 0;
         parseContext.declareVariable((yyvsp[-1].lex).loc, *(yyvsp[-1].lex).string, (yyvsp[-2].interm.type), (yyvsp[0].interm).arraySizes);
     }
-#line 5436 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5488 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 128:
-#line 1124 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1128 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm).type = (yyvsp[-4].interm.type);
         TIntermNode* initNode = parseContext.declareVariable((yyvsp[-3].lex).loc, *(yyvsp[-3].lex).string, (yyvsp[-4].interm.type), (yyvsp[-2].interm).arraySizes, (yyvsp[0].interm.intermTypedNode));
         (yyval.interm).intermNode = parseContext.intermediate.growAggregate(0, initNode, (yyvsp[-1].lex).loc);
     }
-#line 5446 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5498 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 129:
-#line 1129 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1133 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm).type = (yyvsp[-3].interm.type);
         TIntermNode* initNode = parseContext.declareVariable((yyvsp[-2].lex).loc, *(yyvsp[-2].lex).string, (yyvsp[-3].interm.type), 0, (yyvsp[0].interm.intermTypedNode));
         (yyval.interm).intermNode = parseContext.intermediate.growAggregate(0, initNode, (yyvsp[-1].lex).loc);
     }
-#line 5456 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5508 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 130:
-#line 1138 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1142 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type) = (yyvsp[0].interm.type);
 
@@ -5467,11 +5519,11 @@
         }
         parseContext.precisionQualifierCheck((yyval.interm.type).loc, (yyval.interm.type).basicType, (yyval.interm.type).qualifier);
     }
-#line 5471 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5523 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 131:
-#line 1148 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1152 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.globalQualifierFixCheck((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier);
         parseContext.globalQualifierTypeCheck((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier, (yyvsp[0].interm.type));
@@ -5496,22 +5548,22 @@
              (parseContext.language == EShLangFragment && (yyval.interm.type).qualifier.storage == EvqVaryingIn)))
             (yyval.interm.type).qualifier.smooth = true;
     }
-#line 5500 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5552 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 132:
-#line 1175 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1179 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.globalCheck((yyvsp[0].lex).loc, "invariant");
         parseContext.profileRequires((yyval.interm.type).loc, ENoProfile, 120, 0, "invariant");
         (yyval.interm.type).init((yyvsp[0].lex).loc);
         (yyval.interm.type).qualifier.invariant = true;
     }
-#line 5511 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5563 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 133:
-#line 1184 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1188 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.globalCheck((yyvsp[0].lex).loc, "smooth");
         parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "smooth");
@@ -5519,11 +5571,11 @@
         (yyval.interm.type).init((yyvsp[0].lex).loc);
         (yyval.interm.type).qualifier.smooth = true;
     }
-#line 5523 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5575 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 134:
-#line 1191 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1195 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.globalCheck((yyvsp[0].lex).loc, "flat");
         parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "flat");
@@ -5531,11 +5583,11 @@
         (yyval.interm.type).init((yyvsp[0].lex).loc);
         (yyval.interm.type).qualifier.flat = true;
     }
-#line 5535 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5587 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 135:
-#line 1199 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1203 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.globalCheck((yyvsp[0].lex).loc, "noperspective");
         parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 0, E_GL_NV_shader_noperspective_interpolation, "noperspective");
@@ -5543,11 +5595,11 @@
         (yyval.interm.type).init((yyvsp[0].lex).loc);
         (yyval.interm.type).qualifier.nopersp = true;
     }
-#line 5547 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5599 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 136:
-#line 1206 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1210 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.globalCheck((yyvsp[0].lex).loc, "__explicitInterpAMD");
         parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 450, E_GL_AMD_shader_explicit_vertex_parameter, "explicit interpolation");
@@ -5555,11 +5607,11 @@
         (yyval.interm.type).init((yyvsp[0].lex).loc);
         (yyval.interm.type).qualifier.explicitInterp = true;
     }
-#line 5559 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5611 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 137:
-#line 1213 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1217 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.globalCheck((yyvsp[0].lex).loc, "pervertexNV");
         parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 0, E_GL_NV_fragment_shader_barycentric, "fragment shader barycentric");
@@ -5568,11 +5620,11 @@
         (yyval.interm.type).init((yyvsp[0].lex).loc);
         (yyval.interm.type).qualifier.pervertexNV = true;
     }
-#line 5572 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5624 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 138:
-#line 1221 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1225 "glslang.y" /* yacc.c:1646  */
     {
         // No need for profile version or extension check. Shader stage already checks both.
         parseContext.globalCheck((yyvsp[0].lex).loc, "perprimitiveNV");
@@ -5583,11 +5635,11 @@
         (yyval.interm.type).init((yyvsp[0].lex).loc);
         (yyval.interm.type).qualifier.perPrimitiveNV = true;
     }
-#line 5587 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5639 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 139:
-#line 1231 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1235 "glslang.y" /* yacc.c:1646  */
     {
         // No need for profile version or extension check. Shader stage already checks both.
         parseContext.globalCheck((yyvsp[0].lex).loc, "perviewNV");
@@ -5595,11 +5647,11 @@
         (yyval.interm.type).init((yyvsp[0].lex).loc);
         (yyval.interm.type).qualifier.perViewNV = true;
     }
-#line 5599 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5651 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 140:
-#line 1238 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1242 "glslang.y" /* yacc.c:1646  */
     {
         // No need for profile version or extension check. Shader stage already checks both.
         parseContext.globalCheck((yyvsp[0].lex).loc, "taskNV");
@@ -5607,84 +5659,84 @@
         (yyval.interm.type).init((yyvsp[0].lex).loc);
         (yyval.interm.type).qualifier.perTaskNV = true;
     }
-#line 5611 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5663 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 141:
-#line 1249 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1253 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type) = (yyvsp[-1].interm.type);
     }
-#line 5619 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5671 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 142:
-#line 1255 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1259 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type) = (yyvsp[0].interm.type);
     }
-#line 5627 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5679 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 143:
-#line 1258 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1262 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type) = (yyvsp[-2].interm.type);
         (yyval.interm.type).shaderQualifiers.merge((yyvsp[0].interm.type).shaderQualifiers);
         parseContext.mergeObjectLayoutQualifiers((yyval.interm.type).qualifier, (yyvsp[0].interm.type).qualifier, false);
     }
-#line 5637 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5689 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 144:
-#line 1265 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1269 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc);
         parseContext.setLayoutQualifier((yyvsp[0].lex).loc, (yyval.interm.type), *(yyvsp[0].lex).string);
     }
-#line 5646 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5698 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 145:
-#line 1269 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1273 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[-2].lex).loc);
         parseContext.setLayoutQualifier((yyvsp[-2].lex).loc, (yyval.interm.type), *(yyvsp[-2].lex).string, (yyvsp[0].interm.intermTypedNode));
     }
-#line 5655 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5707 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 146:
-#line 1273 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1277 "glslang.y" /* yacc.c:1646  */
     { // because "shared" is both an identifier and a keyword
         (yyval.interm.type).init((yyvsp[0].lex).loc);
         TString strShared("shared");
         parseContext.setLayoutQualifier((yyvsp[0].lex).loc, (yyval.interm.type), strShared);
     }
-#line 5665 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5717 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 147:
-#line 1282 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1286 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.profileRequires((yyval.interm.type).loc, ECoreProfile | ECompatibilityProfile, 400, E_GL_ARB_gpu_shader5, "precise");
         parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5, "precise");
         (yyval.interm.type).init((yyvsp[0].lex).loc);
         (yyval.interm.type).qualifier.noContraction = true;
     }
-#line 5676 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5728 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 148:
-#line 1292 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1296 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type) = (yyvsp[0].interm.type);
     }
-#line 5684 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5736 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 149:
-#line 1295 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1299 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type) = (yyvsp[-1].interm.type);
         if ((yyval.interm.type).basicType == EbtVoid)
@@ -5693,112 +5745,112 @@
         (yyval.interm.type).shaderQualifiers.merge((yyvsp[0].interm.type).shaderQualifiers);
         parseContext.mergeQualifiers((yyval.interm.type).loc, (yyval.interm.type).qualifier, (yyvsp[0].interm.type).qualifier, false);
     }
-#line 5697 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5749 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 150:
-#line 1306 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1310 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type) = (yyvsp[0].interm.type);
     }
-#line 5705 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5757 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 151:
-#line 1309 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1313 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type) = (yyvsp[0].interm.type);
     }
-#line 5713 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5765 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 152:
-#line 1312 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1316 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.checkPrecisionQualifier((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type).qualifier.precision);
         (yyval.interm.type) = (yyvsp[0].interm.type);
     }
-#line 5722 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5774 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 153:
-#line 1316 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1320 "glslang.y" /* yacc.c:1646  */
     {
         // allow inheritance of storage qualifier from block declaration
         (yyval.interm.type) = (yyvsp[0].interm.type);
     }
-#line 5731 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5783 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 154:
-#line 1320 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1324 "glslang.y" /* yacc.c:1646  */
     {
         // allow inheritance of storage qualifier from block declaration
         (yyval.interm.type) = (yyvsp[0].interm.type);
     }
-#line 5740 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5792 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 155:
-#line 1325 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1329 "glslang.y" /* yacc.c:1646  */
     {
         // allow inheritance of storage qualifier from block declaration
         (yyval.interm.type) = (yyvsp[0].interm.type);
     }
-#line 5749 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5801 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 156:
-#line 1329 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1333 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type) = (yyvsp[0].interm.type);
     }
-#line 5757 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5809 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 157:
-#line 1336 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1340 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc);
         (yyval.interm.type).qualifier.storage = EvqConst;  // will later turn into EvqConstReadOnly, if the initializer is not constant
     }
-#line 5766 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5818 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 158:
-#line 1340 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1344 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.globalCheck((yyvsp[0].lex).loc, "inout");
         (yyval.interm.type).init((yyvsp[0].lex).loc);
         (yyval.interm.type).qualifier.storage = EvqInOut;
     }
-#line 5776 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5828 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 159:
-#line 1345 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1349 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.globalCheck((yyvsp[0].lex).loc, "in");
         (yyval.interm.type).init((yyvsp[0].lex).loc);
         // whether this is a parameter "in" or a pipeline "in" will get sorted out a bit later
         (yyval.interm.type).qualifier.storage = EvqIn;
     }
-#line 5787 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5839 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 160:
-#line 1351 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1355 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.globalCheck((yyvsp[0].lex).loc, "out");
         (yyval.interm.type).init((yyvsp[0].lex).loc);
         // whether this is a parameter "out" or a pipeline "out" will get sorted out a bit later
         (yyval.interm.type).qualifier.storage = EvqOut;
     }
-#line 5798 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5850 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 161:
-#line 1357 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1361 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 120, 0, "centroid");
         parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 300, 0, "centroid");
@@ -5806,21 +5858,21 @@
         (yyval.interm.type).init((yyvsp[0].lex).loc);
         (yyval.interm.type).qualifier.centroid = true;
     }
-#line 5810 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5862 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 162:
-#line 1364 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1368 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.globalCheck((yyvsp[0].lex).loc, "uniform");
         (yyval.interm.type).init((yyvsp[0].lex).loc);
         (yyval.interm.type).qualifier.storage = EvqUniform;
     }
-#line 5820 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5872 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 163:
-#line 1369 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1373 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.globalCheck((yyvsp[0].lex).loc, "shared");
         parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, 430, E_GL_ARB_compute_shader, "shared");
@@ -5829,21 +5881,21 @@
         (yyval.interm.type).init((yyvsp[0].lex).loc);
         (yyval.interm.type).qualifier.storage = EvqShared;
     }
-#line 5833 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5885 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 164:
-#line 1377 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1381 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.globalCheck((yyvsp[0].lex).loc, "buffer");
         (yyval.interm.type).init((yyvsp[0].lex).loc);
         (yyval.interm.type).qualifier.storage = EvqBuffer;
     }
-#line 5843 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5895 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 165:
-#line 1383 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1387 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.requireStage((yyvsp[0].lex).loc, EShLangVertex, "attribute");
         parseContext.checkDeprecated((yyvsp[0].lex).loc, ECoreProfile, 130, "attribute");
@@ -5856,11 +5908,11 @@
         (yyval.interm.type).init((yyvsp[0].lex).loc);
         (yyval.interm.type).qualifier.storage = EvqVaryingIn;
     }
-#line 5860 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5912 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 166:
-#line 1395 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1399 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.checkDeprecated((yyvsp[0].lex).loc, ENoProfile, 130, "varying");
         parseContext.checkDeprecated((yyvsp[0].lex).loc, ECoreProfile, 130, "varying");
@@ -5875,250 +5927,324 @@
         else
             (yyval.interm.type).qualifier.storage = EvqVaryingIn;
     }
-#line 5879 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5931 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 167:
-#line 1409 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1413 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.globalCheck((yyvsp[0].lex).loc, "patch");
         parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangTessControlMask | EShLangTessEvaluationMask), "patch");
         (yyval.interm.type).init((yyvsp[0].lex).loc);
         (yyval.interm.type).qualifier.patch = true;
     }
-#line 5890 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5942 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 168:
-#line 1415 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1419 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.globalCheck((yyvsp[0].lex).loc, "sample");
         (yyval.interm.type).init((yyvsp[0].lex).loc);
         (yyval.interm.type).qualifier.sample = true;
     }
-#line 5900 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5952 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 169:
-#line 1420 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1424 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.globalCheck((yyvsp[0].lex).loc, "hitAttributeNV");
-        parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangIntersectNVMask | EShLangClosestHitNVMask
-            | EShLangAnyHitNVMask), "hitAttributeNV");
+        parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangIntersectMask | EShLangClosestHitMask
+            | EShLangAnyHitMask), "hitAttributeNV");
         parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "hitAttributeNV");
         (yyval.interm.type).init((yyvsp[0].lex).loc);
-        (yyval.interm.type).qualifier.storage = EvqHitAttrNV;
+        (yyval.interm.type).qualifier.storage = EvqHitAttr;
     }
-#line 5913 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5965 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 170:
-#line 1428 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1432 "glslang.y" /* yacc.c:1646  */
     {
-        parseContext.globalCheck((yyvsp[0].lex).loc, "rayPayloadNV");
-        parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangRayGenNVMask | EShLangClosestHitNVMask |
-            EShLangAnyHitNVMask | EShLangMissNVMask), "rayPayloadNV");
-        parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "rayPayloadNV");
+        parseContext.globalCheck((yyvsp[0].lex).loc, "hitAttributeEXT");
+        parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangIntersectMask | EShLangClosestHitMask
+            | EShLangAnyHitMask), "hitAttributeEXT");
+        parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "hitAttributeNV");
         (yyval.interm.type).init((yyvsp[0].lex).loc);
-        (yyval.interm.type).qualifier.storage = EvqPayloadNV;
+        (yyval.interm.type).qualifier.storage = EvqHitAttr;
     }
-#line 5926 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5978 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 171:
-#line 1436 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1440 "glslang.y" /* yacc.c:1646  */
     {
-        parseContext.globalCheck((yyvsp[0].lex).loc, "rayPayloadInNV");
-        parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangClosestHitNVMask |
-            EShLangAnyHitNVMask | EShLangMissNVMask), "rayPayloadInNV");
-        parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "rayPayloadInNV");
+        parseContext.globalCheck((yyvsp[0].lex).loc, "rayPayloadNV");
+        parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangRayGenMask | EShLangClosestHitMask |
+            EShLangAnyHitMask | EShLangMissMask), "rayPayloadNV");
+        parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "rayPayloadNV");
         (yyval.interm.type).init((yyvsp[0].lex).loc);
-        (yyval.interm.type).qualifier.storage = EvqPayloadInNV;
+        (yyval.interm.type).qualifier.storage = EvqPayload;
     }
-#line 5939 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 5991 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 172:
-#line 1444 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1448 "glslang.y" /* yacc.c:1646  */
     {
-        parseContext.globalCheck((yyvsp[0].lex).loc, "callableDataNV");
-        parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangRayGenNVMask |
-            EShLangClosestHitNVMask | EShLangMissNVMask | EShLangCallableNVMask), "callableDataNV");
-        parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "callableDataNV");
+        parseContext.globalCheck((yyvsp[0].lex).loc, "rayPayloadEXT");
+        parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangRayGenMask | EShLangClosestHitMask |
+            EShLangAnyHitMask | EShLangMissMask), "rayPayloadEXT");
+        parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "rayPayloadEXT");
         (yyval.interm.type).init((yyvsp[0].lex).loc);
-        (yyval.interm.type).qualifier.storage = EvqCallableDataNV;
+        (yyval.interm.type).qualifier.storage = EvqPayload;
     }
-#line 5952 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6004 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 173:
-#line 1452 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1456 "glslang.y" /* yacc.c:1646  */
     {
-        parseContext.globalCheck((yyvsp[0].lex).loc, "callableDataInNV");
-        parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangCallableNVMask), "callableDataInNV");
-        parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "callableDataInNV");
+        parseContext.globalCheck((yyvsp[0].lex).loc, "rayPayloadInNV");
+        parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangClosestHitMask |
+            EShLangAnyHitMask | EShLangMissMask), "rayPayloadInNV");
+        parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "rayPayloadInNV");
         (yyval.interm.type).init((yyvsp[0].lex).loc);
-        (yyval.interm.type).qualifier.storage = EvqCallableDataInNV;
+        (yyval.interm.type).qualifier.storage = EvqPayloadIn;
     }
-#line 5964 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6017 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 174:
-#line 1459 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1464 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.globalCheck((yyvsp[0].lex).loc, "rayPayloadInEXT");
+        parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangClosestHitMask |
+            EShLangAnyHitMask | EShLangMissMask), "rayPayloadInEXT");
+        parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "rayPayloadInEXT");
+        (yyval.interm.type).init((yyvsp[0].lex).loc);
+        (yyval.interm.type).qualifier.storage = EvqPayloadIn;
+    }
+#line 6030 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 175:
+#line 1472 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.globalCheck((yyvsp[0].lex).loc, "callableDataNV");
+        parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangRayGenMask |
+            EShLangClosestHitMask | EShLangMissMask | EShLangCallableMask), "callableDataNV");
+        parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "callableDataNV");
+        (yyval.interm.type).init((yyvsp[0].lex).loc);
+        (yyval.interm.type).qualifier.storage = EvqCallableData;
+    }
+#line 6043 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 176:
+#line 1480 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.globalCheck((yyvsp[0].lex).loc, "callableDataEXT");
+        parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangRayGenMask |
+            EShLangClosestHitMask | EShLangMissMask | EShLangCallableMask), "callableDataEXT");
+        parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "callableDataEXT");
+        (yyval.interm.type).init((yyvsp[0].lex).loc);
+        (yyval.interm.type).qualifier.storage = EvqCallableData;
+    }
+#line 6056 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 177:
+#line 1488 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.globalCheck((yyvsp[0].lex).loc, "callableDataInNV");
+        parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangCallableMask), "callableDataInNV");
+        parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "callableDataInNV");
+        (yyval.interm.type).init((yyvsp[0].lex).loc);
+        (yyval.interm.type).qualifier.storage = EvqCallableDataIn;
+    }
+#line 6068 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 178:
+#line 1495 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.globalCheck((yyvsp[0].lex).loc, "callableDataInEXT");
+        parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangCallableMask), "callableDataInEXT");
+        parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "callableDataInEXT");
+        (yyval.interm.type).init((yyvsp[0].lex).loc);
+        (yyval.interm.type).qualifier.storage = EvqCallableDataIn;
+    }
+#line 6080 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 179:
+#line 1502 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc);
         (yyval.interm.type).qualifier.coherent = true;
     }
-#line 5973 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6089 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 175:
-#line 1463 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 180:
+#line 1506 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc);
         parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_KHR_memory_scope_semantics, "devicecoherent");
         (yyval.interm.type).qualifier.devicecoherent = true;
     }
-#line 5983 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6099 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 176:
-#line 1468 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 181:
+#line 1511 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc);
         parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_KHR_memory_scope_semantics, "queuefamilycoherent");
         (yyval.interm.type).qualifier.queuefamilycoherent = true;
     }
-#line 5993 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6109 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 177:
-#line 1473 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 182:
+#line 1516 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc);
         parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_KHR_memory_scope_semantics, "workgroupcoherent");
         (yyval.interm.type).qualifier.workgroupcoherent = true;
     }
-#line 6003 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6119 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 178:
-#line 1478 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 183:
+#line 1521 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc);
         parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_KHR_memory_scope_semantics, "subgroupcoherent");
         (yyval.interm.type).qualifier.subgroupcoherent = true;
     }
-#line 6013 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6129 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 179:
-#line 1483 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 184:
+#line 1526 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc);
         parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_KHR_memory_scope_semantics, "nonprivate");
         (yyval.interm.type).qualifier.nonprivate = true;
     }
-#line 6023 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6139 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 180:
-#line 1488 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 185:
+#line 1531 "glslang.y" /* yacc.c:1646  */
+    {
+        (yyval.interm.type).init((yyvsp[0].lex).loc);
+        parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_EXT_ray_tracing, "shadercallcoherent");
+        (yyval.interm.type).qualifier.shadercallcoherent = true;
+    }
+#line 6149 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 186:
+#line 1536 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc);
         (yyval.interm.type).qualifier.volatil = true;
     }
-#line 6032 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6158 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 181:
-#line 1492 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 187:
+#line 1540 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc);
         (yyval.interm.type).qualifier.restrict = true;
     }
-#line 6041 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6167 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 182:
-#line 1496 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 188:
+#line 1544 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc);
         (yyval.interm.type).qualifier.readonly = true;
     }
-#line 6050 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6176 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 183:
-#line 1500 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 189:
+#line 1548 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc);
         (yyval.interm.type).qualifier.writeonly = true;
     }
-#line 6059 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6185 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 184:
-#line 1504 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 190:
+#line 1552 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.spvRemoved((yyvsp[0].lex).loc, "subroutine");
         parseContext.globalCheck((yyvsp[0].lex).loc, "subroutine");
         parseContext.unimplemented((yyvsp[0].lex).loc, "subroutine");
         (yyval.interm.type).init((yyvsp[0].lex).loc);
     }
-#line 6070 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6196 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 185:
-#line 1510 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 191:
+#line 1558 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.spvRemoved((yyvsp[-3].lex).loc, "subroutine");
         parseContext.globalCheck((yyvsp[-3].lex).loc, "subroutine");
         parseContext.unimplemented((yyvsp[-3].lex).loc, "subroutine");
         (yyval.interm.type).init((yyvsp[-3].lex).loc);
     }
-#line 6081 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6207 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 186:
-#line 1521 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 192:
+#line 1569 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc);
         (yyval.interm.type).qualifier.nonUniform = true;
     }
-#line 6090 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6216 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 187:
-#line 1528 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 193:
+#line 1576 "glslang.y" /* yacc.c:1646  */
     {
         // TODO
     }
-#line 6098 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6224 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 188:
-#line 1531 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 194:
+#line 1579 "glslang.y" /* yacc.c:1646  */
     {
         // TODO: 4.0 semantics: subroutines
         // 1) make sure each identifier is a type declared earlier with SUBROUTINE
         // 2) save all of the identifiers for future comparison with the declared function
     }
-#line 6108 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6234 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 189:
-#line 1540 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 195:
+#line 1588 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type) = (yyvsp[-1].interm.type);
         (yyval.interm.type).qualifier.precision = parseContext.getDefaultPrecision((yyval.interm.type));
         (yyval.interm.type).typeParameters = (yyvsp[0].interm.typeParameters);
     }
-#line 6118 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6244 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 190:
-#line 1545 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 196:
+#line 1593 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.arrayOfArrayVersionCheck((yyvsp[0].interm).loc, (yyvsp[0].interm).arraySizes);
         (yyval.interm.type) = (yyvsp[-2].interm.type);
@@ -6126,21 +6252,21 @@
         (yyval.interm.type).typeParameters = (yyvsp[-1].interm.typeParameters);
         (yyval.interm.type).arraySizes = (yyvsp[0].interm).arraySizes;
     }
-#line 6130 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6256 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 191:
-#line 1555 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 197:
+#line 1603 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm).loc = (yyvsp[-1].lex).loc;
         (yyval.interm).arraySizes = new TArraySizes;
         (yyval.interm).arraySizes->addInnerSize();
     }
-#line 6140 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6266 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 192:
-#line 1560 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 198:
+#line 1608 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm).loc = (yyvsp[-2].lex).loc;
         (yyval.interm).arraySizes = new TArraySizes;
@@ -6149,20 +6275,20 @@
         parseContext.arraySizeCheck((yyvsp[-1].interm.intermTypedNode)->getLoc(), (yyvsp[-1].interm.intermTypedNode), size, "array size");
         (yyval.interm).arraySizes->addInnerSize(size);
     }
-#line 6153 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6279 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 193:
-#line 1568 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 199:
+#line 1616 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm) = (yyvsp[-2].interm);
         (yyval.interm).arraySizes->addInnerSize();
     }
-#line 6162 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6288 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 194:
-#line 1572 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 200:
+#line 1620 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm) = (yyvsp[-3].interm);
 
@@ -6170,35 +6296,35 @@
         parseContext.arraySizeCheck((yyvsp[-1].interm.intermTypedNode)->getLoc(), (yyvsp[-1].interm.intermTypedNode), size, "array size");
         (yyval.interm).arraySizes->addInnerSize(size);
     }
-#line 6174 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6300 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 195:
-#line 1582 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 201:
+#line 1630 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.typeParameters) = (yyvsp[0].interm.typeParameters);
     }
-#line 6182 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6308 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 196:
-#line 1585 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 202:
+#line 1633 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.typeParameters) = 0;
     }
-#line 6190 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6316 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 197:
-#line 1591 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 203:
+#line 1639 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.typeParameters) = (yyvsp[-1].interm.typeParameters);
     }
-#line 6198 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6324 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 198:
-#line 1597 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 204:
+#line 1645 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.typeParameters) = new TArraySizes;
 
@@ -6206,11 +6332,11 @@
         parseContext.arraySizeCheck((yyvsp[0].interm.intermTypedNode)->getLoc(), (yyvsp[0].interm.intermTypedNode), size, "type parameter");
         (yyval.interm.typeParameters)->addInnerSize(size);
     }
-#line 6210 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6336 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 199:
-#line 1604 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 205:
+#line 1652 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.typeParameters) = (yyvsp[-2].interm.typeParameters);
 
@@ -6218,300 +6344,300 @@
         parseContext.arraySizeCheck((yyvsp[0].interm.intermTypedNode)->getLoc(), (yyvsp[0].interm.intermTypedNode), size, "type parameter");
         (yyval.interm.typeParameters)->addInnerSize(size);
     }
-#line 6222 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6348 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 200:
-#line 1614 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 206:
+#line 1662 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtVoid;
     }
-#line 6231 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6357 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 201:
-#line 1618 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 207:
+#line 1666 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtFloat;
     }
-#line 6240 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6366 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 202:
-#line 1622 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 208:
+#line 1670 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtInt;
     }
-#line 6249 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6375 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 203:
-#line 1626 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 209:
+#line 1674 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned integer");
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtUint;
     }
-#line 6259 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 204:
-#line 1631 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtBool;
-    }
-#line 6268 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 205:
-#line 1635 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtFloat;
-        (yyval.interm.type).setVector(2);
-    }
-#line 6278 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 206:
-#line 1640 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtFloat;
-        (yyval.interm.type).setVector(3);
-    }
-#line 6288 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 207:
-#line 1645 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtFloat;
-        (yyval.interm.type).setVector(4);
-    }
-#line 6298 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 208:
-#line 1650 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtBool;
-        (yyval.interm.type).setVector(2);
-    }
-#line 6308 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 209:
-#line 1655 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtBool;
-        (yyval.interm.type).setVector(3);
-    }
-#line 6318 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6385 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 210:
-#line 1660 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1679 "glslang.y" /* yacc.c:1646  */
+    {
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtBool;
+    }
+#line 6394 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 211:
+#line 1683 "glslang.y" /* yacc.c:1646  */
+    {
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtFloat;
+        (yyval.interm.type).setVector(2);
+    }
+#line 6404 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 212:
+#line 1688 "glslang.y" /* yacc.c:1646  */
+    {
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtFloat;
+        (yyval.interm.type).setVector(3);
+    }
+#line 6414 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 213:
+#line 1693 "glslang.y" /* yacc.c:1646  */
+    {
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtFloat;
+        (yyval.interm.type).setVector(4);
+    }
+#line 6424 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 214:
+#line 1698 "glslang.y" /* yacc.c:1646  */
+    {
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtBool;
+        (yyval.interm.type).setVector(2);
+    }
+#line 6434 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 215:
+#line 1703 "glslang.y" /* yacc.c:1646  */
+    {
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtBool;
+        (yyval.interm.type).setVector(3);
+    }
+#line 6444 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 216:
+#line 1708 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtBool;
         (yyval.interm.type).setVector(4);
     }
-#line 6328 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 211:
-#line 1665 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtInt;
-        (yyval.interm.type).setVector(2);
-    }
-#line 6338 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 212:
-#line 1670 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtInt;
-        (yyval.interm.type).setVector(3);
-    }
-#line 6348 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 213:
-#line 1675 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtInt;
-        (yyval.interm.type).setVector(4);
-    }
-#line 6358 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 214:
-#line 1680 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned integer vector");
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtUint;
-        (yyval.interm.type).setVector(2);
-    }
-#line 6369 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 215:
-#line 1686 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned integer vector");
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtUint;
-        (yyval.interm.type).setVector(3);
-    }
-#line 6380 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 216:
-#line 1692 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned integer vector");
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtUint;
-        (yyval.interm.type).setVector(4);
-    }
-#line 6391 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6454 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 217:
-#line 1698 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1713 "glslang.y" /* yacc.c:1646  */
+    {
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtInt;
+        (yyval.interm.type).setVector(2);
+    }
+#line 6464 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 218:
+#line 1718 "glslang.y" /* yacc.c:1646  */
+    {
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtInt;
+        (yyval.interm.type).setVector(3);
+    }
+#line 6474 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 219:
+#line 1723 "glslang.y" /* yacc.c:1646  */
+    {
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtInt;
+        (yyval.interm.type).setVector(4);
+    }
+#line 6484 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 220:
+#line 1728 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned integer vector");
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtUint;
+        (yyval.interm.type).setVector(2);
+    }
+#line 6495 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 221:
+#line 1734 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned integer vector");
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtUint;
+        (yyval.interm.type).setVector(3);
+    }
+#line 6506 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 222:
+#line 1740 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned integer vector");
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtUint;
+        (yyval.interm.type).setVector(4);
+    }
+#line 6517 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 223:
+#line 1746 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtFloat;
         (yyval.interm.type).setMatrix(2, 2);
     }
-#line 6401 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6527 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 218:
-#line 1703 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 224:
+#line 1751 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtFloat;
         (yyval.interm.type).setMatrix(3, 3);
     }
-#line 6411 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6537 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 219:
-#line 1708 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 225:
+#line 1756 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtFloat;
         (yyval.interm.type).setMatrix(4, 4);
     }
-#line 6421 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6547 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 220:
-#line 1713 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 226:
+#line 1761 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtFloat;
         (yyval.interm.type).setMatrix(2, 2);
     }
-#line 6431 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6557 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 221:
-#line 1718 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 227:
+#line 1766 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtFloat;
         (yyval.interm.type).setMatrix(2, 3);
     }
-#line 6441 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6567 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 222:
-#line 1723 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 228:
+#line 1771 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtFloat;
         (yyval.interm.type).setMatrix(2, 4);
     }
-#line 6451 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6577 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 223:
-#line 1728 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 229:
+#line 1776 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtFloat;
         (yyval.interm.type).setMatrix(3, 2);
     }
-#line 6461 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6587 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 224:
-#line 1733 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 230:
+#line 1781 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtFloat;
         (yyval.interm.type).setMatrix(3, 3);
     }
-#line 6471 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6597 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 225:
-#line 1738 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 231:
+#line 1786 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtFloat;
         (yyval.interm.type).setMatrix(3, 4);
     }
-#line 6481 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6607 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 226:
-#line 1743 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 232:
+#line 1791 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtFloat;
         (yyval.interm.type).setMatrix(4, 2);
     }
-#line 6491 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6617 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 227:
-#line 1748 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 233:
+#line 1796 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtFloat;
         (yyval.interm.type).setMatrix(4, 3);
     }
-#line 6501 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6627 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 228:
-#line 1753 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 234:
+#line 1801 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtFloat;
         (yyval.interm.type).setMatrix(4, 4);
     }
-#line 6511 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6637 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 229:
-#line 1759 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 235:
+#line 1807 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double");
         if (! parseContext.symbolTable.atBuiltInLevel())
@@ -6519,614 +6645,536 @@
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtDouble;
     }
-#line 6523 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6649 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 230:
-#line 1766 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 236:
+#line 1814 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16ScalarVectorCheck((yyvsp[0].lex).loc, "float16_t", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtFloat16;
     }
-#line 6533 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6659 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 231:
-#line 1771 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 237:
+#line 1819 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtFloat;
     }
-#line 6543 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6669 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 232:
-#line 1776 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 238:
+#line 1824 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtDouble;
     }
-#line 6553 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6679 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 233:
-#line 1781 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 239:
+#line 1829 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit signed integer", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtInt8;
     }
-#line 6563 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6689 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 234:
-#line 1786 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 240:
+#line 1834 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtUint8;
     }
-#line 6573 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6699 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 235:
-#line 1791 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 241:
+#line 1839 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit signed integer", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtInt16;
     }
-#line 6583 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6709 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 236:
-#line 1796 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 242:
+#line 1844 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtUint16;
     }
-#line 6593 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6719 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 237:
-#line 1801 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 243:
+#line 1849 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed integer", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtInt;
     }
-#line 6603 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6729 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 238:
-#line 1806 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 244:
+#line 1854 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtUint;
     }
-#line 6613 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6739 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 239:
-#line 1811 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 245:
+#line 1859 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtInt64;
     }
-#line 6623 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6749 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 240:
-#line 1816 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 246:
+#line 1864 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtUint64;
     }
-#line 6633 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 241:
-#line 1821 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double vector");
-        if (! parseContext.symbolTable.atBuiltInLevel())
-            parseContext.doubleCheck((yyvsp[0].lex).loc, "double vector");
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtDouble;
-        (yyval.interm.type).setVector(2);
-    }
-#line 6646 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 242:
-#line 1829 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double vector");
-        if (! parseContext.symbolTable.atBuiltInLevel())
-            parseContext.doubleCheck((yyvsp[0].lex).loc, "double vector");
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtDouble;
-        (yyval.interm.type).setVector(3);
-    }
-#line 6659 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 243:
-#line 1837 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double vector");
-        if (! parseContext.symbolTable.atBuiltInLevel())
-            parseContext.doubleCheck((yyvsp[0].lex).loc, "double vector");
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtDouble;
-        (yyval.interm.type).setVector(4);
-    }
-#line 6672 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 244:
-#line 1845 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.float16ScalarVectorCheck((yyvsp[0].lex).loc, "half float vector", parseContext.symbolTable.atBuiltInLevel());
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtFloat16;
-        (yyval.interm.type).setVector(2);
-    }
-#line 6683 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 245:
-#line 1851 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.float16ScalarVectorCheck((yyvsp[0].lex).loc, "half float vector", parseContext.symbolTable.atBuiltInLevel());
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtFloat16;
-        (yyval.interm.type).setVector(3);
-    }
-#line 6694 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 246:
-#line 1857 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.float16ScalarVectorCheck((yyvsp[0].lex).loc, "half float vector", parseContext.symbolTable.atBuiltInLevel());
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtFloat16;
-        (yyval.interm.type).setVector(4);
-    }
-#line 6705 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6759 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 247:
-#line 1863 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1869 "glslang.y" /* yacc.c:1646  */
     {
-        parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t vector", parseContext.symbolTable.atBuiltInLevel());
+        parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double vector");
+        if (! parseContext.symbolTable.atBuiltInLevel())
+            parseContext.doubleCheck((yyvsp[0].lex).loc, "double vector");
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtFloat;
+        (yyval.interm.type).basicType = EbtDouble;
         (yyval.interm.type).setVector(2);
     }
-#line 6716 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6772 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 248:
-#line 1869 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1877 "glslang.y" /* yacc.c:1646  */
     {
-        parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t vector", parseContext.symbolTable.atBuiltInLevel());
+        parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double vector");
+        if (! parseContext.symbolTable.atBuiltInLevel())
+            parseContext.doubleCheck((yyvsp[0].lex).loc, "double vector");
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtFloat;
+        (yyval.interm.type).basicType = EbtDouble;
         (yyval.interm.type).setVector(3);
     }
-#line 6727 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6785 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 249:
-#line 1875 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1885 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double vector");
+        if (! parseContext.symbolTable.atBuiltInLevel())
+            parseContext.doubleCheck((yyvsp[0].lex).loc, "double vector");
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtDouble;
+        (yyval.interm.type).setVector(4);
+    }
+#line 6798 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 250:
+#line 1893 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.float16ScalarVectorCheck((yyvsp[0].lex).loc, "half float vector", parseContext.symbolTable.atBuiltInLevel());
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtFloat16;
+        (yyval.interm.type).setVector(2);
+    }
+#line 6809 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 251:
+#line 1899 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.float16ScalarVectorCheck((yyvsp[0].lex).loc, "half float vector", parseContext.symbolTable.atBuiltInLevel());
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtFloat16;
+        (yyval.interm.type).setVector(3);
+    }
+#line 6820 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 252:
+#line 1905 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.float16ScalarVectorCheck((yyvsp[0].lex).loc, "half float vector", parseContext.symbolTable.atBuiltInLevel());
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtFloat16;
+        (yyval.interm.type).setVector(4);
+    }
+#line 6831 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 253:
+#line 1911 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t vector", parseContext.symbolTable.atBuiltInLevel());
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtFloat;
+        (yyval.interm.type).setVector(2);
+    }
+#line 6842 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 254:
+#line 1917 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t vector", parseContext.symbolTable.atBuiltInLevel());
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtFloat;
+        (yyval.interm.type).setVector(3);
+    }
+#line 6853 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 255:
+#line 1923 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t vector", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtFloat;
         (yyval.interm.type).setVector(4);
     }
-#line 6738 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 250:
-#line 1881 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t vector", parseContext.symbolTable.atBuiltInLevel());
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtDouble;
-        (yyval.interm.type).setVector(2);
-    }
-#line 6749 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 251:
-#line 1887 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t vector", parseContext.symbolTable.atBuiltInLevel());
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtDouble;
-        (yyval.interm.type).setVector(3);
-    }
-#line 6760 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 252:
-#line 1893 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t vector", parseContext.symbolTable.atBuiltInLevel());
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtDouble;
-        (yyval.interm.type).setVector(4);
-    }
-#line 6771 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 253:
-#line 1899 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel());
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtInt8;
-        (yyval.interm.type).setVector(2);
-    }
-#line 6782 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 254:
-#line 1905 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel());
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtInt8;
-        (yyval.interm.type).setVector(3);
-    }
-#line 6793 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 255:
-#line 1911 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel());
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtInt8;
-        (yyval.interm.type).setVector(4);
-    }
-#line 6804 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6864 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 256:
-#line 1917 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1929 "glslang.y" /* yacc.c:1646  */
     {
-        parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel());
+        parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t vector", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtInt16;
+        (yyval.interm.type).basicType = EbtDouble;
         (yyval.interm.type).setVector(2);
     }
-#line 6815 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6875 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 257:
-#line 1923 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1935 "glslang.y" /* yacc.c:1646  */
     {
-        parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel());
+        parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t vector", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtInt16;
+        (yyval.interm.type).basicType = EbtDouble;
         (yyval.interm.type).setVector(3);
     }
-#line 6826 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6886 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 258:
-#line 1929 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1941 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t vector", parseContext.symbolTable.atBuiltInLevel());
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtDouble;
+        (yyval.interm.type).setVector(4);
+    }
+#line 6897 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 259:
+#line 1947 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel());
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtInt8;
+        (yyval.interm.type).setVector(2);
+    }
+#line 6908 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 260:
+#line 1953 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel());
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtInt8;
+        (yyval.interm.type).setVector(3);
+    }
+#line 6919 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 261:
+#line 1959 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel());
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtInt8;
+        (yyval.interm.type).setVector(4);
+    }
+#line 6930 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 262:
+#line 1965 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel());
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtInt16;
+        (yyval.interm.type).setVector(2);
+    }
+#line 6941 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 263:
+#line 1971 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel());
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtInt16;
+        (yyval.interm.type).setVector(3);
+    }
+#line 6952 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 264:
+#line 1977 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtInt16;
         (yyval.interm.type).setVector(4);
     }
-#line 6837 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 259:
-#line 1935 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel());
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtInt;
-        (yyval.interm.type).setVector(2);
-    }
-#line 6848 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 260:
-#line 1941 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel());
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtInt;
-        (yyval.interm.type).setVector(3);
-    }
-#line 6859 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 261:
-#line 1947 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel());
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtInt;
-        (yyval.interm.type).setVector(4);
-    }
-#line 6870 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 262:
-#line 1953 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel());
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtInt64;
-        (yyval.interm.type).setVector(2);
-    }
-#line 6881 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 263:
-#line 1959 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel());
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtInt64;
-        (yyval.interm.type).setVector(3);
-    }
-#line 6892 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 264:
-#line 1965 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel());
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtInt64;
-        (yyval.interm.type).setVector(4);
-    }
-#line 6903 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6963 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 265:
-#line 1971 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1983 "glslang.y" /* yacc.c:1646  */
     {
-        parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
+        parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtUint8;
+        (yyval.interm.type).basicType = EbtInt;
         (yyval.interm.type).setVector(2);
     }
-#line 6914 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6974 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 266:
-#line 1977 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1989 "glslang.y" /* yacc.c:1646  */
     {
-        parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
+        parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtUint8;
+        (yyval.interm.type).basicType = EbtInt;
         (yyval.interm.type).setVector(3);
     }
-#line 6925 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 6985 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 267:
-#line 1983 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 1995 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel());
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtInt;
+        (yyval.interm.type).setVector(4);
+    }
+#line 6996 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 268:
+#line 2001 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel());
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtInt64;
+        (yyval.interm.type).setVector(2);
+    }
+#line 7007 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 269:
+#line 2007 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel());
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtInt64;
+        (yyval.interm.type).setVector(3);
+    }
+#line 7018 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 270:
+#line 2013 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel());
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtInt64;
+        (yyval.interm.type).setVector(4);
+    }
+#line 7029 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 271:
+#line 2019 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtUint8;
+        (yyval.interm.type).setVector(2);
+    }
+#line 7040 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 272:
+#line 2025 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtUint8;
+        (yyval.interm.type).setVector(3);
+    }
+#line 7051 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 273:
+#line 2031 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtUint8;
         (yyval.interm.type).setVector(4);
     }
-#line 6936 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 268:
-#line 1989 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtUint16;
-        (yyval.interm.type).setVector(2);
-    }
-#line 6947 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 269:
-#line 1995 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtUint16;
-        (yyval.interm.type).setVector(3);
-    }
-#line 6958 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 270:
-#line 2001 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtUint16;
-        (yyval.interm.type).setVector(4);
-    }
-#line 6969 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 271:
-#line 2007 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtUint;
-        (yyval.interm.type).setVector(2);
-    }
-#line 6980 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 272:
-#line 2013 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtUint;
-        (yyval.interm.type).setVector(3);
-    }
-#line 6991 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 273:
-#line 2019 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtUint;
-        (yyval.interm.type).setVector(4);
-    }
-#line 7002 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7062 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 274:
-#line 2025 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 2037 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtUint16;
+        (yyval.interm.type).setVector(2);
+    }
+#line 7073 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 275:
+#line 2043 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtUint16;
+        (yyval.interm.type).setVector(3);
+    }
+#line 7084 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 276:
+#line 2049 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtUint16;
+        (yyval.interm.type).setVector(4);
+    }
+#line 7095 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 277:
+#line 2055 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtUint;
+        (yyval.interm.type).setVector(2);
+    }
+#line 7106 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 278:
+#line 2061 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtUint;
+        (yyval.interm.type).setVector(3);
+    }
+#line 7117 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 279:
+#line 2067 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtUint;
+        (yyval.interm.type).setVector(4);
+    }
+#line 7128 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 280:
+#line 2073 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtUint64;
         (yyval.interm.type).setVector(2);
     }
-#line 7013 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7139 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 275:
-#line 2031 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 281:
+#line 2079 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtUint64;
         (yyval.interm.type).setVector(3);
     }
-#line 7024 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7150 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 276:
-#line 2037 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 282:
+#line 2085 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtUint64;
         (yyval.interm.type).setVector(4);
     }
-#line 7035 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 277:
-#line 2043 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix");
-        if (! parseContext.symbolTable.atBuiltInLevel())
-            parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix");
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtDouble;
-        (yyval.interm.type).setMatrix(2, 2);
-    }
-#line 7048 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 278:
-#line 2051 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix");
-        if (! parseContext.symbolTable.atBuiltInLevel())
-            parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix");
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtDouble;
-        (yyval.interm.type).setMatrix(3, 3);
-    }
-#line 7061 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 279:
-#line 2059 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix");
-        if (! parseContext.symbolTable.atBuiltInLevel())
-            parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix");
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtDouble;
-        (yyval.interm.type).setMatrix(4, 4);
-    }
-#line 7074 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 280:
-#line 2067 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix");
-        if (! parseContext.symbolTable.atBuiltInLevel())
-            parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix");
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtDouble;
-        (yyval.interm.type).setMatrix(2, 2);
-    }
-#line 7087 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 281:
-#line 2075 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix");
-        if (! parseContext.symbolTable.atBuiltInLevel())
-            parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix");
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtDouble;
-        (yyval.interm.type).setMatrix(2, 3);
-    }
-#line 7100 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 282:
-#line 2083 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix");
-        if (! parseContext.symbolTable.atBuiltInLevel())
-            parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix");
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtDouble;
-        (yyval.interm.type).setMatrix(2, 4);
-    }
-#line 7113 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7161 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 283:
-#line 2091 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 2091 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix");
         if (! parseContext.symbolTable.atBuiltInLevel())
             parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix");
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtDouble;
-        (yyval.interm.type).setMatrix(3, 2);
+        (yyval.interm.type).setMatrix(2, 2);
     }
-#line 7126 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7174 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 284:
-#line 2099 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 2099 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix");
         if (! parseContext.symbolTable.atBuiltInLevel())
@@ -7135,50 +7183,128 @@
         (yyval.interm.type).basicType = EbtDouble;
         (yyval.interm.type).setMatrix(3, 3);
     }
-#line 7139 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7187 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 285:
-#line 2107 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 2107 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix");
         if (! parseContext.symbolTable.atBuiltInLevel())
             parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix");
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtDouble;
-        (yyval.interm.type).setMatrix(3, 4);
+        (yyval.interm.type).setMatrix(4, 4);
     }
-#line 7152 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7200 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 286:
-#line 2115 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 2115 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix");
         if (! parseContext.symbolTable.atBuiltInLevel())
             parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix");
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtDouble;
-        (yyval.interm.type).setMatrix(4, 2);
+        (yyval.interm.type).setMatrix(2, 2);
     }
-#line 7165 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7213 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 287:
-#line 2123 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 2123 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix");
         if (! parseContext.symbolTable.atBuiltInLevel())
             parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix");
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtDouble;
-        (yyval.interm.type).setMatrix(4, 3);
+        (yyval.interm.type).setMatrix(2, 3);
     }
-#line 7178 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7226 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 288:
-#line 2131 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 2131 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix");
+        if (! parseContext.symbolTable.atBuiltInLevel())
+            parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix");
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtDouble;
+        (yyval.interm.type).setMatrix(2, 4);
+    }
+#line 7239 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 289:
+#line 2139 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix");
+        if (! parseContext.symbolTable.atBuiltInLevel())
+            parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix");
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtDouble;
+        (yyval.interm.type).setMatrix(3, 2);
+    }
+#line 7252 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 290:
+#line 2147 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix");
+        if (! parseContext.symbolTable.atBuiltInLevel())
+            parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix");
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtDouble;
+        (yyval.interm.type).setMatrix(3, 3);
+    }
+#line 7265 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 291:
+#line 2155 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix");
+        if (! parseContext.symbolTable.atBuiltInLevel())
+            parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix");
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtDouble;
+        (yyval.interm.type).setMatrix(3, 4);
+    }
+#line 7278 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 292:
+#line 2163 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix");
+        if (! parseContext.symbolTable.atBuiltInLevel())
+            parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix");
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtDouble;
+        (yyval.interm.type).setMatrix(4, 2);
+    }
+#line 7291 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 293:
+#line 2171 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix");
+        if (! parseContext.symbolTable.atBuiltInLevel())
+            parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix");
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtDouble;
+        (yyval.interm.type).setMatrix(4, 3);
+    }
+#line 7304 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 294:
+#line 2179 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix");
         if (! parseContext.symbolTable.atBuiltInLevel())
@@ -7187,1990 +7313,2008 @@
         (yyval.interm.type).basicType = EbtDouble;
         (yyval.interm.type).setMatrix(4, 4);
     }
-#line 7191 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 289:
-#line 2139 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtFloat16;
-        (yyval.interm.type).setMatrix(2, 2);
-    }
-#line 7202 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 290:
-#line 2145 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtFloat16;
-        (yyval.interm.type).setMatrix(3, 3);
-    }
-#line 7213 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 291:
-#line 2151 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtFloat16;
-        (yyval.interm.type).setMatrix(4, 4);
-    }
-#line 7224 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 292:
-#line 2157 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtFloat16;
-        (yyval.interm.type).setMatrix(2, 2);
-    }
-#line 7235 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 293:
-#line 2163 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtFloat16;
-        (yyval.interm.type).setMatrix(2, 3);
-    }
-#line 7246 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 294:
-#line 2169 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtFloat16;
-        (yyval.interm.type).setMatrix(2, 4);
-    }
-#line 7257 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7317 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 295:
-#line 2175 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 2187 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtFloat16;
-        (yyval.interm.type).setMatrix(3, 2);
+        (yyval.interm.type).setMatrix(2, 2);
     }
-#line 7268 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7328 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 296:
-#line 2181 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 2193 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtFloat16;
         (yyval.interm.type).setMatrix(3, 3);
     }
-#line 7279 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7339 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 297:
-#line 2187 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 2199 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtFloat16;
-        (yyval.interm.type).setMatrix(3, 4);
+        (yyval.interm.type).setMatrix(4, 4);
     }
-#line 7290 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7350 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 298:
-#line 2193 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 2205 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtFloat16;
-        (yyval.interm.type).setMatrix(4, 2);
+        (yyval.interm.type).setMatrix(2, 2);
     }
-#line 7301 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7361 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 299:
-#line 2199 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 2211 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtFloat16;
-        (yyval.interm.type).setMatrix(4, 3);
+        (yyval.interm.type).setMatrix(2, 3);
     }
-#line 7312 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7372 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 300:
-#line 2205 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 2217 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtFloat16;
+        (yyval.interm.type).setMatrix(2, 4);
+    }
+#line 7383 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 301:
+#line 2223 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtFloat16;
+        (yyval.interm.type).setMatrix(3, 2);
+    }
+#line 7394 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 302:
+#line 2229 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtFloat16;
+        (yyval.interm.type).setMatrix(3, 3);
+    }
+#line 7405 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 303:
+#line 2235 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtFloat16;
+        (yyval.interm.type).setMatrix(3, 4);
+    }
+#line 7416 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 304:
+#line 2241 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtFloat16;
+        (yyval.interm.type).setMatrix(4, 2);
+    }
+#line 7427 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 305:
+#line 2247 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtFloat16;
+        (yyval.interm.type).setMatrix(4, 3);
+    }
+#line 7438 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 306:
+#line 2253 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtFloat16;
         (yyval.interm.type).setMatrix(4, 4);
     }
-#line 7323 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 301:
-#line 2211 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtFloat;
-        (yyval.interm.type).setMatrix(2, 2);
-    }
-#line 7334 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 302:
-#line 2217 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtFloat;
-        (yyval.interm.type).setMatrix(3, 3);
-    }
-#line 7345 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 303:
-#line 2223 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtFloat;
-        (yyval.interm.type).setMatrix(4, 4);
-    }
-#line 7356 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 304:
-#line 2229 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtFloat;
-        (yyval.interm.type).setMatrix(2, 2);
-    }
-#line 7367 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 305:
-#line 2235 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtFloat;
-        (yyval.interm.type).setMatrix(2, 3);
-    }
-#line 7378 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 306:
-#line 2241 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
-        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-        (yyval.interm.type).basicType = EbtFloat;
-        (yyval.interm.type).setMatrix(2, 4);
-    }
-#line 7389 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7449 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 307:
-#line 2247 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 2259 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtFloat;
+        (yyval.interm.type).setMatrix(2, 2);
+    }
+#line 7460 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 308:
+#line 2265 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtFloat;
+        (yyval.interm.type).setMatrix(3, 3);
+    }
+#line 7471 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 309:
+#line 2271 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtFloat;
+        (yyval.interm.type).setMatrix(4, 4);
+    }
+#line 7482 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 310:
+#line 2277 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtFloat;
+        (yyval.interm.type).setMatrix(2, 2);
+    }
+#line 7493 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 311:
+#line 2283 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtFloat;
+        (yyval.interm.type).setMatrix(2, 3);
+    }
+#line 7504 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 312:
+#line 2289 "glslang.y" /* yacc.c:1646  */
+    {
+        parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
+        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+        (yyval.interm.type).basicType = EbtFloat;
+        (yyval.interm.type).setMatrix(2, 4);
+    }
+#line 7515 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 313:
+#line 2295 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtFloat;
         (yyval.interm.type).setMatrix(3, 2);
     }
-#line 7400 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7526 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 308:
-#line 2253 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 314:
+#line 2301 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtFloat;
         (yyval.interm.type).setMatrix(3, 3);
     }
-#line 7411 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7537 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 309:
-#line 2259 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 315:
+#line 2307 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtFloat;
         (yyval.interm.type).setMatrix(3, 4);
     }
-#line 7422 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7548 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 310:
-#line 2265 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 316:
+#line 2313 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtFloat;
         (yyval.interm.type).setMatrix(4, 2);
     }
-#line 7433 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7559 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 311:
-#line 2271 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 317:
+#line 2319 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtFloat;
         (yyval.interm.type).setMatrix(4, 3);
     }
-#line 7444 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7570 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 312:
-#line 2277 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 318:
+#line 2325 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtFloat;
         (yyval.interm.type).setMatrix(4, 4);
     }
-#line 7455 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7581 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 313:
-#line 2283 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 319:
+#line 2331 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtDouble;
         (yyval.interm.type).setMatrix(2, 2);
     }
-#line 7466 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7592 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 314:
-#line 2289 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 320:
+#line 2337 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtDouble;
         (yyval.interm.type).setMatrix(3, 3);
     }
-#line 7477 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7603 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 315:
-#line 2295 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 321:
+#line 2343 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtDouble;
         (yyval.interm.type).setMatrix(4, 4);
     }
-#line 7488 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7614 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 316:
-#line 2301 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 322:
+#line 2349 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtDouble;
         (yyval.interm.type).setMatrix(2, 2);
     }
-#line 7499 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7625 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 317:
-#line 2307 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 323:
+#line 2355 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtDouble;
         (yyval.interm.type).setMatrix(2, 3);
     }
-#line 7510 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7636 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 318:
-#line 2313 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 324:
+#line 2361 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtDouble;
         (yyval.interm.type).setMatrix(2, 4);
     }
-#line 7521 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7647 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 319:
-#line 2319 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 325:
+#line 2367 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtDouble;
         (yyval.interm.type).setMatrix(3, 2);
     }
-#line 7532 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7658 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 320:
-#line 2325 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 326:
+#line 2373 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtDouble;
         (yyval.interm.type).setMatrix(3, 3);
     }
-#line 7543 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7669 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 321:
-#line 2331 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 327:
+#line 2379 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtDouble;
         (yyval.interm.type).setMatrix(3, 4);
     }
-#line 7554 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7680 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 322:
-#line 2337 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 328:
+#line 2385 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtDouble;
         (yyval.interm.type).setMatrix(4, 2);
     }
-#line 7565 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7691 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 323:
-#line 2343 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 329:
+#line 2391 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtDouble;
         (yyval.interm.type).setMatrix(4, 3);
     }
-#line 7576 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7702 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 324:
-#line 2349 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 330:
+#line 2397 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtDouble;
         (yyval.interm.type).setMatrix(4, 4);
     }
-#line 7587 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7713 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 325:
-#line 2355 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 331:
+#line 2403 "glslang.y" /* yacc.c:1646  */
     {
        (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
-       (yyval.interm.type).basicType = EbtAccStructNV;
+       (yyval.interm.type).basicType = EbtAccStruct;
     }
-#line 7596 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7722 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 326:
-#line 2359 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 332:
+#line 2407 "glslang.y" /* yacc.c:1646  */
+    {
+       (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+       (yyval.interm.type).basicType = EbtAccStruct;
+    }
+#line 7731 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 333:
+#line 2411 "glslang.y" /* yacc.c:1646  */
+    {
+       (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
+       (yyval.interm.type).basicType = EbtRayQuery;
+    }
+#line 7740 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 334:
+#line 2415 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.vulkanRemoved((yyvsp[0].lex).loc, "atomic counter types");
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtAtomicUint;
     }
-#line 7606 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7750 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 327:
-#line 2364 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 335:
+#line 2420 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtFloat, Esd1D);
     }
-#line 7616 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7760 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 328:
-#line 2370 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 336:
+#line 2426 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtFloat, Esd2D);
     }
-#line 7626 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7770 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 329:
-#line 2375 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 337:
+#line 2431 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtFloat, Esd3D);
     }
-#line 7636 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7780 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 330:
-#line 2380 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 338:
+#line 2436 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtFloat, EsdCube);
     }
-#line 7646 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7790 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 331:
-#line 2385 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 339:
+#line 2441 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtFloat, Esd2D, false, true);
     }
-#line 7656 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7800 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 332:
-#line 2390 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 340:
+#line 2446 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtFloat, EsdCube, false, true);
     }
-#line 7666 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7810 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 333:
-#line 2395 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 341:
+#line 2451 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtFloat, Esd2D, true);
     }
-#line 7676 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7820 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 334:
-#line 2400 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 342:
+#line 2456 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtFloat, Esd2D, true, true);
     }
-#line 7686 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7830 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 335:
-#line 2406 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 343:
+#line 2462 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtFloat, Esd1D, false, true);
     }
-#line 7696 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7840 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 336:
-#line 2411 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 344:
+#line 2467 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtFloat, Esd1D, true);
     }
-#line 7706 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7850 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 337:
-#line 2416 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 345:
+#line 2472 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtFloat, Esd1D, true, true);
     }
-#line 7716 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7860 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 338:
-#line 2421 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 346:
+#line 2477 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtFloat, EsdCube, true);
     }
-#line 7726 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7870 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 339:
-#line 2426 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 347:
+#line 2482 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtFloat, EsdCube, true, true);
     }
-#line 7736 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7880 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 340:
-#line 2431 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 348:
+#line 2487 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtFloat16, Esd1D);
     }
-#line 7747 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7891 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 341:
-#line 2437 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 349:
+#line 2493 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtFloat16, Esd2D);
     }
-#line 7758 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7902 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 342:
-#line 2443 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 350:
+#line 2499 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtFloat16, Esd3D);
     }
-#line 7769 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7913 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 343:
-#line 2449 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 351:
+#line 2505 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtFloat16, EsdCube);
     }
-#line 7780 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7924 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 344:
-#line 2455 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 352:
+#line 2511 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtFloat16, Esd1D, false, true);
     }
-#line 7791 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7935 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 345:
-#line 2461 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 353:
+#line 2517 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtFloat16, Esd2D, false, true);
     }
-#line 7802 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7946 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 346:
-#line 2467 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 354:
+#line 2523 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtFloat16, EsdCube, false, true);
     }
-#line 7813 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7957 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 347:
-#line 2473 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 355:
+#line 2529 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtFloat16, Esd1D, true);
     }
-#line 7824 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7968 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 348:
-#line 2479 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 356:
+#line 2535 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtFloat16, Esd2D, true);
     }
-#line 7835 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7979 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 349:
-#line 2485 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 357:
+#line 2541 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtFloat16, Esd1D, true, true);
     }
-#line 7846 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 7990 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 350:
-#line 2491 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 358:
+#line 2547 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtFloat16, Esd2D, true, true);
     }
-#line 7857 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8001 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 351:
-#line 2497 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 359:
+#line 2553 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtFloat16, EsdCube, true);
     }
-#line 7868 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8012 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 352:
-#line 2503 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 360:
+#line 2559 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtFloat16, EsdCube, true, true);
     }
-#line 7879 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8023 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 353:
-#line 2509 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 361:
+#line 2565 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtInt, Esd1D);
     }
-#line 7889 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8033 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 354:
-#line 2515 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 362:
+#line 2571 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtInt, Esd2D);
     }
-#line 7899 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8043 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 355:
-#line 2520 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 363:
+#line 2576 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtInt, Esd3D);
     }
-#line 7909 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8053 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 356:
-#line 2525 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 364:
+#line 2581 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtInt, EsdCube);
     }
-#line 7919 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8063 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 357:
-#line 2530 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 365:
+#line 2586 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtInt, Esd2D, true);
     }
-#line 7929 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8073 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 358:
-#line 2535 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 366:
+#line 2591 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtUint, Esd2D);
     }
-#line 7939 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8083 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 359:
-#line 2540 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 367:
+#line 2596 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtUint, Esd3D);
     }
-#line 7949 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8093 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 360:
-#line 2545 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 368:
+#line 2601 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtUint, EsdCube);
     }
-#line 7959 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8103 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 361:
-#line 2551 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 369:
+#line 2607 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtInt, Esd1D, true);
     }
-#line 7969 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8113 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 362:
-#line 2556 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 370:
+#line 2612 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtInt, EsdCube, true);
     }
-#line 7979 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8123 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 363:
-#line 2561 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 371:
+#line 2617 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtUint, Esd1D);
     }
-#line 7989 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8133 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 364:
-#line 2566 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 372:
+#line 2622 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtUint, Esd1D, true);
     }
-#line 7999 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8143 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 365:
-#line 2571 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 373:
+#line 2627 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtUint, EsdCube, true);
     }
-#line 8009 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8153 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 366:
-#line 2576 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 374:
+#line 2632 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtFloat, EsdCube, true);
     }
-#line 8019 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8163 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 367:
-#line 2581 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 375:
+#line 2637 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtInt, EsdCube, true);
     }
-#line 8029 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8173 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 368:
-#line 2586 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 376:
+#line 2642 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtUint, EsdCube, true);
     }
-#line 8039 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8183 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 369:
-#line 2592 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 377:
+#line 2648 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtUint, Esd2D, true);
     }
-#line 8049 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8193 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 370:
-#line 2597 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 378:
+#line 2653 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtFloat, Esd2D);
     }
-#line 8059 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8203 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 371:
-#line 2602 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 379:
+#line 2658 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtFloat, Esd3D);
     }
-#line 8069 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8213 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 372:
-#line 2607 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 380:
+#line 2663 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtFloat, Esd2D, true);
     }
-#line 8079 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8223 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 373:
-#line 2612 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 381:
+#line 2668 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtFloat, EsdCube);
     }
-#line 8089 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8233 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 374:
-#line 2617 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 382:
+#line 2673 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtInt, Esd2D);
     }
-#line 8099 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8243 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 375:
-#line 2622 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 383:
+#line 2678 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtInt, Esd3D);
     }
-#line 8109 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8253 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 376:
-#line 2627 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 384:
+#line 2683 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtInt, EsdCube);
     }
-#line 8119 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8263 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 377:
-#line 2632 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 385:
+#line 2688 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtInt, Esd2D, true);
     }
-#line 8129 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8273 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 378:
-#line 2637 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 386:
+#line 2693 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtUint, Esd2D);
     }
-#line 8139 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8283 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 379:
-#line 2642 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 387:
+#line 2698 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtUint, Esd3D);
     }
-#line 8149 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8293 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 380:
-#line 2647 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 388:
+#line 2703 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtUint, EsdCube);
     }
-#line 8159 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8303 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 381:
-#line 2652 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 389:
+#line 2708 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtUint, Esd2D, true);
     }
-#line 8169 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8313 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 382:
-#line 2657 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 390:
+#line 2713 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setPureSampler(false);
     }
-#line 8179 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8323 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 383:
-#line 2662 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 391:
+#line 2718 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setPureSampler(true);
     }
-#line 8189 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8333 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 384:
-#line 2668 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 392:
+#line 2724 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtFloat, EsdRect);
     }
-#line 8199 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8343 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 385:
-#line 2673 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 393:
+#line 2729 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtFloat, EsdRect, false, true);
     }
-#line 8209 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8353 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 386:
-#line 2678 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 394:
+#line 2734 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtFloat16, EsdRect);
     }
-#line 8220 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8364 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 387:
-#line 2684 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 395:
+#line 2740 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtFloat16, EsdRect, false, true);
     }
-#line 8231 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8375 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 388:
-#line 2690 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 396:
+#line 2746 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtInt, EsdRect);
     }
-#line 8241 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8385 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 389:
-#line 2695 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 397:
+#line 2751 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtUint, EsdRect);
     }
-#line 8251 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8395 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 390:
-#line 2700 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 398:
+#line 2756 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtFloat, EsdBuffer);
     }
-#line 8261 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8405 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 391:
-#line 2705 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 399:
+#line 2761 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtFloat16, EsdBuffer);
     }
-#line 8272 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8416 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 392:
-#line 2711 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 400:
+#line 2767 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtInt, EsdBuffer);
     }
-#line 8282 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8426 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 393:
-#line 2716 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 401:
+#line 2772 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtUint, EsdBuffer);
     }
-#line 8292 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8436 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 394:
-#line 2721 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 402:
+#line 2777 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtFloat, Esd2D, false, false, true);
     }
-#line 8302 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8446 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 395:
-#line 2726 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 403:
+#line 2782 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtFloat16, Esd2D, false, false, true);
     }
-#line 8313 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8457 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 396:
-#line 2732 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 404:
+#line 2788 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtInt, Esd2D, false, false, true);
     }
-#line 8323 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8467 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 397:
-#line 2737 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 405:
+#line 2793 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtUint, Esd2D, false, false, true);
     }
-#line 8333 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8477 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 398:
-#line 2742 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 406:
+#line 2798 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtFloat, Esd2D, true, false, true);
     }
-#line 8343 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8487 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 399:
-#line 2747 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 407:
+#line 2803 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtFloat16, Esd2D, true, false, true);
     }
-#line 8354 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8498 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 400:
-#line 2753 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 408:
+#line 2809 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtInt, Esd2D, true, false, true);
     }
-#line 8364 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8508 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 401:
-#line 2758 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 409:
+#line 2814 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtUint, Esd2D, true, false, true);
     }
-#line 8374 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8518 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 402:
-#line 2763 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 410:
+#line 2819 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtFloat, Esd1D);
     }
-#line 8384 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8528 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 403:
-#line 2768 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 411:
+#line 2824 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd1D);
     }
-#line 8395 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8539 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 404:
-#line 2774 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 412:
+#line 2830 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd2D);
     }
-#line 8406 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8550 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 405:
-#line 2780 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 413:
+#line 2836 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd3D);
     }
-#line 8417 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8561 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 406:
-#line 2786 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 414:
+#line 2842 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtFloat16, EsdCube);
     }
-#line 8428 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8572 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 407:
-#line 2792 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 415:
+#line 2848 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtFloat, Esd1D, true);
     }
-#line 8438 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8582 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 408:
-#line 2797 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 416:
+#line 2853 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd1D, true);
     }
-#line 8449 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8593 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 409:
-#line 2803 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 417:
+#line 2859 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd2D, true);
     }
-#line 8460 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8604 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 410:
-#line 2809 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 418:
+#line 2865 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtFloat16, EsdCube, true);
     }
-#line 8471 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8615 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 411:
-#line 2815 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 419:
+#line 2871 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtInt, Esd1D);
     }
-#line 8481 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8625 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 412:
-#line 2820 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 420:
+#line 2876 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtInt, Esd1D, true);
     }
-#line 8491 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8635 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 413:
-#line 2825 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 421:
+#line 2881 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtUint, Esd1D);
     }
-#line 8501 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8645 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 414:
-#line 2830 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 422:
+#line 2886 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtUint, Esd1D, true);
     }
-#line 8511 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8655 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 415:
-#line 2835 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 423:
+#line 2891 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtFloat, EsdRect);
     }
-#line 8521 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8665 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 416:
-#line 2840 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 424:
+#line 2896 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtFloat16, EsdRect);
     }
-#line 8532 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8676 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 417:
-#line 2846 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 425:
+#line 2902 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtInt, EsdRect);
     }
-#line 8542 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8686 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 418:
-#line 2851 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 426:
+#line 2907 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtUint, EsdRect);
     }
-#line 8552 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8696 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 419:
-#line 2856 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 427:
+#line 2912 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtFloat, EsdBuffer);
     }
-#line 8562 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8706 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 420:
-#line 2861 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 428:
+#line 2917 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtFloat16, EsdBuffer);
     }
-#line 8573 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8717 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 421:
-#line 2867 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 429:
+#line 2923 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtInt, EsdBuffer);
     }
-#line 8583 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8727 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 422:
-#line 2872 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 430:
+#line 2928 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtUint, EsdBuffer);
     }
-#line 8593 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8737 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 423:
-#line 2877 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 431:
+#line 2933 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtFloat, Esd2D, false, false, true);
     }
-#line 8603 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8747 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 424:
-#line 2882 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 432:
+#line 2938 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd2D, false, false, true);
     }
-#line 8614 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8758 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 425:
-#line 2888 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 433:
+#line 2944 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtInt, Esd2D, false, false, true);
     }
-#line 8624 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8768 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 426:
-#line 2893 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 434:
+#line 2949 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtUint, Esd2D, false, false, true);
     }
-#line 8634 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8778 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 427:
-#line 2898 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 435:
+#line 2954 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtFloat, Esd2D, true, false, true);
     }
-#line 8644 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8788 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 428:
-#line 2903 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 436:
+#line 2959 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd2D, true, false, true);
     }
-#line 8655 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8799 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 429:
-#line 2909 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 437:
+#line 2965 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtInt, Esd2D, true, false, true);
     }
-#line 8665 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8809 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 430:
-#line 2914 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 438:
+#line 2970 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setTexture(EbtUint, Esd2D, true, false, true);
     }
-#line 8675 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8819 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 431:
-#line 2919 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 439:
+#line 2975 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtFloat, Esd1D);
     }
-#line 8685 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8829 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 432:
-#line 2924 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 440:
+#line 2980 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtFloat16, Esd1D);
     }
-#line 8696 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8840 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 433:
-#line 2930 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 441:
+#line 2986 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtInt, Esd1D);
     }
-#line 8706 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8850 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 434:
-#line 2935 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 442:
+#line 2991 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtUint, Esd1D);
     }
-#line 8716 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8860 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 435:
-#line 2940 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 443:
+#line 2996 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtFloat, Esd2D);
     }
-#line 8726 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8870 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 436:
-#line 2945 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 444:
+#line 3001 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtFloat16, Esd2D);
     }
-#line 8737 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8881 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 437:
-#line 2951 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 445:
+#line 3007 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtInt, Esd2D);
     }
-#line 8747 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8891 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 438:
-#line 2956 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 446:
+#line 3012 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtUint, Esd2D);
     }
-#line 8757 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8901 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 439:
-#line 2961 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 447:
+#line 3017 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtFloat, Esd3D);
     }
-#line 8767 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8911 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 440:
-#line 2966 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 448:
+#line 3022 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtFloat16, Esd3D);
     }
-#line 8778 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8922 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 441:
-#line 2972 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 449:
+#line 3028 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtInt, Esd3D);
     }
-#line 8788 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8932 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 442:
-#line 2977 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 450:
+#line 3033 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtUint, Esd3D);
     }
-#line 8798 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8942 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 443:
-#line 2982 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 451:
+#line 3038 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtFloat, EsdRect);
     }
-#line 8808 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8952 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 444:
-#line 2987 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 452:
+#line 3043 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtFloat16, EsdRect);
     }
-#line 8819 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8963 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 445:
-#line 2993 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 453:
+#line 3049 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtInt, EsdRect);
     }
-#line 8829 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8973 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 446:
-#line 2998 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 454:
+#line 3054 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtUint, EsdRect);
     }
-#line 8839 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8983 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 447:
-#line 3003 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 455:
+#line 3059 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtFloat, EsdCube);
     }
-#line 8849 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 8993 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 448:
-#line 3008 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 456:
+#line 3064 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtFloat16, EsdCube);
     }
-#line 8860 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9004 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 449:
-#line 3014 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 457:
+#line 3070 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtInt, EsdCube);
     }
-#line 8870 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9014 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 450:
-#line 3019 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 458:
+#line 3075 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtUint, EsdCube);
     }
-#line 8880 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9024 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 451:
-#line 3024 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 459:
+#line 3080 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtFloat, EsdBuffer);
     }
-#line 8890 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9034 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 452:
-#line 3029 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 460:
+#line 3085 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtFloat16, EsdBuffer);
     }
-#line 8901 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9045 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 453:
-#line 3035 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 461:
+#line 3091 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtInt, EsdBuffer);
     }
-#line 8911 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9055 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 454:
-#line 3040 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 462:
+#line 3096 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtUint, EsdBuffer);
     }
-#line 8921 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9065 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 455:
-#line 3045 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 463:
+#line 3101 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtFloat, Esd1D, true);
     }
-#line 8931 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9075 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 456:
-#line 3050 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 464:
+#line 3106 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtFloat16, Esd1D, true);
     }
-#line 8942 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9086 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 457:
-#line 3056 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 465:
+#line 3112 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtInt, Esd1D, true);
     }
-#line 8952 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9096 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 458:
-#line 3061 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 466:
+#line 3117 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtUint, Esd1D, true);
     }
-#line 8962 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9106 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 459:
-#line 3066 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 467:
+#line 3122 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtFloat, Esd2D, true);
     }
-#line 8972 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9116 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 460:
-#line 3071 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 468:
+#line 3127 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtFloat16, Esd2D, true);
     }
-#line 8983 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9127 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 461:
-#line 3077 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 469:
+#line 3133 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtInt, Esd2D, true);
     }
-#line 8993 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9137 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 462:
-#line 3082 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 470:
+#line 3138 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtUint, Esd2D, true);
     }
-#line 9003 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9147 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 463:
-#line 3087 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 471:
+#line 3143 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtFloat, EsdCube, true);
     }
-#line 9013 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9157 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 464:
-#line 3092 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 472:
+#line 3148 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtFloat16, EsdCube, true);
     }
-#line 9024 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9168 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 465:
-#line 3098 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 473:
+#line 3154 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtInt, EsdCube, true);
     }
-#line 9034 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9178 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 466:
-#line 3103 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 474:
+#line 3159 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtUint, EsdCube, true);
     }
-#line 9044 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9188 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 467:
-#line 3108 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 475:
+#line 3164 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtFloat, Esd2D, false, false, true);
     }
-#line 9054 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9198 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 468:
-#line 3113 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 476:
+#line 3169 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtFloat16, Esd2D, false, false, true);
     }
-#line 9065 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9209 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 469:
-#line 3119 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 477:
+#line 3175 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtInt, Esd2D, false, false, true);
     }
-#line 9075 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9219 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 470:
-#line 3124 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 478:
+#line 3180 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtUint, Esd2D, false, false, true);
     }
-#line 9085 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9229 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 471:
-#line 3129 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 479:
+#line 3185 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtFloat, Esd2D, true, false, true);
     }
-#line 9095 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9239 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 472:
-#line 3134 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 480:
+#line 3190 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtFloat16, Esd2D, true, false, true);
     }
-#line 9106 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9250 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 473:
-#line 3140 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 481:
+#line 3196 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtInt, Esd2D, true, false, true);
     }
-#line 9116 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9260 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 474:
-#line 3145 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 482:
+#line 3201 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setImage(EbtUint, Esd2D, true, false, true);
     }
-#line 9126 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9270 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 475:
-#line 3150 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 483:
+#line 3206 "glslang.y" /* yacc.c:1646  */
     {  // GL_OES_EGL_image_external
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtFloat, Esd2D);
         (yyval.interm.type).sampler.external = true;
     }
-#line 9137 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9281 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 476:
-#line 3156 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 484:
+#line 3212 "glslang.y" /* yacc.c:1646  */
     { // GL_EXT_YUV_target
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.set(EbtFloat, Esd2D);
         (yyval.interm.type).sampler.yuv = true;
     }
-#line 9148 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9292 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 477:
-#line 3162 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 485:
+#line 3218 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input");
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setSubpass(EbtFloat);
     }
-#line 9159 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9303 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 478:
-#line 3168 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 486:
+#line 3224 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input");
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setSubpass(EbtFloat, true);
     }
-#line 9170 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9314 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 479:
-#line 3174 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 487:
+#line 3230 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float subpass input", parseContext.symbolTable.atBuiltInLevel());
         parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input");
@@ -9178,11 +9322,11 @@
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setSubpass(EbtFloat16);
     }
-#line 9182 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9326 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 480:
-#line 3181 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 488:
+#line 3237 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float subpass input", parseContext.symbolTable.atBuiltInLevel());
         parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input");
@@ -9190,98 +9334,98 @@
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setSubpass(EbtFloat16, true);
     }
-#line 9194 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9338 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 481:
-#line 3188 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 489:
+#line 3244 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input");
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setSubpass(EbtInt);
     }
-#line 9205 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9349 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 482:
-#line 3194 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 490:
+#line 3250 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input");
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setSubpass(EbtInt, true);
     }
-#line 9216 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9360 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 483:
-#line 3200 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 491:
+#line 3256 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input");
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setSubpass(EbtUint);
     }
-#line 9227 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9371 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 484:
-#line 3206 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 492:
+#line 3262 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input");
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtSampler;
         (yyval.interm.type).sampler.setSubpass(EbtUint, true);
     }
-#line 9238 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9382 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 485:
-#line 3212 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 493:
+#line 3268 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.fcoopmatCheck((yyvsp[0].lex).loc, "fcoopmatNV", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtFloat;
         (yyval.interm.type).coopmat = true;
     }
-#line 9249 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9393 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 486:
-#line 3218 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 494:
+#line 3274 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.intcoopmatCheck((yyvsp[0].lex).loc, "icoopmatNV", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtInt;
         (yyval.interm.type).coopmat = true;
     }
-#line 9260 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9404 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 487:
-#line 3224 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 495:
+#line 3280 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.intcoopmatCheck((yyvsp[0].lex).loc, "ucoopmatNV", parseContext.symbolTable.atBuiltInLevel());
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         (yyval.interm.type).basicType = EbtUint;
         (yyval.interm.type).coopmat = true;
     }
-#line 9271 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9415 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 488:
-#line 3231 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 496:
+#line 3287 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.type) = (yyvsp[0].interm.type);
         (yyval.interm.type).qualifier.storage = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
         parseContext.structTypeCheck((yyval.interm.type).loc, (yyval.interm.type));
     }
-#line 9281 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9425 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 489:
-#line 3236 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 497:
+#line 3292 "glslang.y" /* yacc.c:1646  */
     {
         //
         // This is for user defined type names.  The lexical phase looked up the
@@ -9295,47 +9439,47 @@
         } else
             parseContext.error((yyvsp[0].lex).loc, "expected type name", (yyvsp[0].lex).string->c_str(), "");
     }
-#line 9299 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9443 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 490:
-#line 3252 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 498:
+#line 3308 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "highp precision qualifier");
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         parseContext.handlePrecisionQualifier((yyvsp[0].lex).loc, (yyval.interm.type).qualifier, EpqHigh);
     }
-#line 9309 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9453 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 491:
-#line 3257 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 499:
+#line 3313 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "mediump precision qualifier");
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         parseContext.handlePrecisionQualifier((yyvsp[0].lex).loc, (yyval.interm.type).qualifier, EpqMedium);
     }
-#line 9319 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9463 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 492:
-#line 3262 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 500:
+#line 3318 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "lowp precision qualifier");
         (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel());
         parseContext.handlePrecisionQualifier((yyvsp[0].lex).loc, (yyval.interm.type).qualifier, EpqLow);
     }
-#line 9329 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9473 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 493:
-#line 3270 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 501:
+#line 3326 "glslang.y" /* yacc.c:1646  */
     { parseContext.nestedStructCheck((yyvsp[-2].lex).loc); }
-#line 9335 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9479 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 494:
-#line 3270 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 502:
+#line 3326 "glslang.y" /* yacc.c:1646  */
     {
         TType* structure = new TType((yyvsp[-1].interm.typeList), *(yyvsp[-4].lex).string);
         parseContext.structArrayCheck((yyvsp[-4].lex).loc, *structure);
@@ -9347,17 +9491,17 @@
         (yyval.interm.type).userDef = structure;
         --parseContext.structNestingLevel;
     }
-#line 9351 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9495 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 495:
-#line 3281 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 503:
+#line 3337 "glslang.y" /* yacc.c:1646  */
     { parseContext.nestedStructCheck((yyvsp[-1].lex).loc); }
-#line 9357 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9501 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 496:
-#line 3281 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 504:
+#line 3337 "glslang.y" /* yacc.c:1646  */
     {
         TType* structure = new TType((yyvsp[-1].interm.typeList), TString(""));
         (yyval.interm.type).init((yyvsp[-4].lex).loc);
@@ -9365,19 +9509,19 @@
         (yyval.interm.type).userDef = structure;
         --parseContext.structNestingLevel;
     }
-#line 9369 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9513 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 497:
-#line 3291 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 505:
+#line 3347 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.typeList) = (yyvsp[0].interm.typeList);
     }
-#line 9377 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9521 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 498:
-#line 3294 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 506:
+#line 3350 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.typeList) = (yyvsp[-1].interm.typeList);
         for (unsigned int i = 0; i < (yyvsp[0].interm.typeList)->size(); ++i) {
@@ -9388,11 +9532,11 @@
             (yyval.interm.typeList)->push_back((*(yyvsp[0].interm.typeList))[i]);
         }
     }
-#line 9392 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9536 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 499:
-#line 3307 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 507:
+#line 3363 "glslang.y" /* yacc.c:1646  */
     {
         if ((yyvsp[-2].interm.type).arraySizes) {
             parseContext.profileRequires((yyvsp[-2].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type");
@@ -9415,11 +9559,11 @@
             (*(yyval.interm.typeList))[i].type->shallowCopy(type);
         }
     }
-#line 9419 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9563 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 500:
-#line 3329 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 508:
+#line 3385 "glslang.y" /* yacc.c:1646  */
     {
         if ((yyvsp[-2].interm.type).arraySizes) {
             parseContext.profileRequires((yyvsp[-2].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type");
@@ -9444,38 +9588,38 @@
             (*(yyval.interm.typeList))[i].type->shallowCopy(type);
         }
     }
-#line 9448 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9592 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 501:
-#line 3356 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 509:
+#line 3412 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.typeList) = new TTypeList;
         (yyval.interm.typeList)->push_back((yyvsp[0].interm.typeLine));
     }
-#line 9457 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9601 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 502:
-#line 3360 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 510:
+#line 3416 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.typeList)->push_back((yyvsp[0].interm.typeLine));
     }
-#line 9465 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9609 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 503:
-#line 3366 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 511:
+#line 3422 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.typeLine).type = new TType(EbtVoid);
         (yyval.interm.typeLine).loc = (yyvsp[0].lex).loc;
         (yyval.interm.typeLine).type->setFieldName(*(yyvsp[0].lex).string);
     }
-#line 9475 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9619 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 504:
-#line 3371 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 512:
+#line 3427 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.arrayOfArrayVersionCheck((yyvsp[-1].lex).loc, (yyvsp[0].interm).arraySizes);
 
@@ -9484,235 +9628,235 @@
         (yyval.interm.typeLine).type->setFieldName(*(yyvsp[-1].lex).string);
         (yyval.interm.typeLine).type->transferArraySizes((yyvsp[0].interm).arraySizes);
     }
-#line 9488 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9632 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 505:
-#line 3382 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 513:
+#line 3438 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
     }
-#line 9496 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9640 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 506:
-#line 3386 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 514:
+#line 3442 "glslang.y" /* yacc.c:1646  */
     {
         const char* initFeature = "{ } style initializers";
         parseContext.requireProfile((yyvsp[-2].lex).loc, ~EEsProfile, initFeature);
         parseContext.profileRequires((yyvsp[-2].lex).loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature);
         (yyval.interm.intermTypedNode) = (yyvsp[-1].interm.intermTypedNode);
     }
-#line 9507 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9651 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 507:
-#line 3392 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 515:
+#line 3448 "glslang.y" /* yacc.c:1646  */
     {
         const char* initFeature = "{ } style initializers";
         parseContext.requireProfile((yyvsp[-3].lex).loc, ~EEsProfile, initFeature);
         parseContext.profileRequires((yyvsp[-3].lex).loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature);
         (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode);
     }
-#line 9518 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 508:
-#line 3403 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        (yyval.interm.intermTypedNode) = parseContext.intermediate.growAggregate(0, (yyvsp[0].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)->getLoc());
-    }
-#line 9526 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 509:
-#line 3406 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    {
-        (yyval.interm.intermTypedNode) = parseContext.intermediate.growAggregate((yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
-    }
-#line 9534 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 510:
-#line 3413 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
-#line 9540 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 511:
-#line 3417 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
-#line 9546 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 512:
-#line 3418 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
-#line 9552 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 513:
-#line 3424 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
-#line 9558 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 514:
-#line 3425 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
-#line 9564 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
-    break;
-
-  case 515:
-#line 3426 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
-#line 9570 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9662 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 516:
-#line 3427 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
-#line 9576 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 3459 "glslang.y" /* yacc.c:1646  */
+    {
+        (yyval.interm.intermTypedNode) = parseContext.intermediate.growAggregate(0, (yyvsp[0].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)->getLoc());
+    }
+#line 9670 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 517:
-#line 3428 "MachineIndependent/glslang.y" /* yacc.c:1646  */
-    { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
-#line 9582 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 3462 "glslang.y" /* yacc.c:1646  */
+    {
+        (yyval.interm.intermTypedNode) = parseContext.intermediate.growAggregate((yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode));
+    }
+#line 9678 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 518:
-#line 3429 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 3469 "glslang.y" /* yacc.c:1646  */
     { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
-#line 9588 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9684 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 519:
-#line 3430 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 3473 "glslang.y" /* yacc.c:1646  */
     { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
-#line 9594 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9690 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 520:
-#line 3432 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 3474 "glslang.y" /* yacc.c:1646  */
     { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
-#line 9600 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9696 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
   case 521:
-#line 3438 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+#line 3480 "glslang.y" /* yacc.c:1646  */
+    { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+#line 9702 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 522:
+#line 3481 "glslang.y" /* yacc.c:1646  */
+    { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+#line 9708 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 523:
+#line 3482 "glslang.y" /* yacc.c:1646  */
+    { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+#line 9714 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 524:
+#line 3483 "glslang.y" /* yacc.c:1646  */
+    { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+#line 9720 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 525:
+#line 3484 "glslang.y" /* yacc.c:1646  */
+    { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+#line 9726 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 526:
+#line 3485 "glslang.y" /* yacc.c:1646  */
+    { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+#line 9732 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 527:
+#line 3486 "glslang.y" /* yacc.c:1646  */
+    { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+#line 9738 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 528:
+#line 3488 "glslang.y" /* yacc.c:1646  */
+    { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
+#line 9744 "glslang_tab.cpp" /* yacc.c:1646  */
+    break;
+
+  case 529:
+#line 3494 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.requireStage((yyvsp[-1].lex).loc, EShLangFragment, "demote");
         parseContext.requireExtensions((yyvsp[-1].lex).loc, 1, &E_GL_EXT_demote_to_helper_invocation, "demote");
         (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpDemote, (yyvsp[-1].lex).loc);
     }
-#line 9610 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9754 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 522:
-#line 3447 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 530:
+#line 3503 "glslang.y" /* yacc.c:1646  */
     { (yyval.interm.intermNode) = 0; }
-#line 9616 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9760 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 523:
-#line 3448 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 531:
+#line 3504 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.symbolTable.push();
         ++parseContext.statementNestingLevel;
     }
-#line 9625 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9769 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 524:
-#line 3452 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 532:
+#line 3508 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
         --parseContext.statementNestingLevel;
     }
-#line 9634 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9778 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 525:
-#line 3456 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 533:
+#line 3512 "glslang.y" /* yacc.c:1646  */
     {
         if ((yyvsp[-2].interm.intermNode) && (yyvsp[-2].interm.intermNode)->getAsAggregate())
             (yyvsp[-2].interm.intermNode)->getAsAggregate()->setOperator(EOpSequence);
         (yyval.interm.intermNode) = (yyvsp[-2].interm.intermNode);
     }
-#line 9644 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9788 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 526:
-#line 3464 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 534:
+#line 3520 "glslang.y" /* yacc.c:1646  */
     { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
-#line 9650 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9794 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 527:
-#line 3465 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 535:
+#line 3521 "glslang.y" /* yacc.c:1646  */
     { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); }
-#line 9656 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9800 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 528:
-#line 3469 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 536:
+#line 3525 "glslang.y" /* yacc.c:1646  */
     {
         ++parseContext.controlFlowNestingLevel;
     }
-#line 9664 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9808 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 529:
-#line 3472 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 537:
+#line 3528 "glslang.y" /* yacc.c:1646  */
     {
         --parseContext.controlFlowNestingLevel;
         (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
     }
-#line 9673 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9817 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 530:
-#line 3476 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 538:
+#line 3532 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.symbolTable.push();
         ++parseContext.statementNestingLevel;
         ++parseContext.controlFlowNestingLevel;
     }
-#line 9683 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9827 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 531:
-#line 3481 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 539:
+#line 3537 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
         --parseContext.statementNestingLevel;
         --parseContext.controlFlowNestingLevel;
         (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
     }
-#line 9694 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9838 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 532:
-#line 3490 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 540:
+#line 3546 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermNode) = 0;
     }
-#line 9702 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9846 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 533:
-#line 3493 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 541:
+#line 3549 "glslang.y" /* yacc.c:1646  */
     {
         if ((yyvsp[-1].interm.intermNode) && (yyvsp[-1].interm.intermNode)->getAsAggregate())
             (yyvsp[-1].interm.intermNode)->getAsAggregate()->setOperator(EOpSequence);
         (yyval.interm.intermNode) = (yyvsp[-1].interm.intermNode);
     }
-#line 9712 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9856 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 534:
-#line 3501 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 542:
+#line 3557 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermNode) = parseContext.intermediate.makeAggregate((yyvsp[0].interm.intermNode));
         if ((yyvsp[0].interm.intermNode) && (yyvsp[0].interm.intermNode)->getAsBranchNode() && ((yyvsp[0].interm.intermNode)->getAsBranchNode()->getFlowOp() == EOpCase ||
@@ -9721,11 +9865,11 @@
             (yyval.interm.intermNode) = 0;  // start a fresh subsequence for what's after this case
         }
     }
-#line 9725 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9869 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 535:
-#line 3509 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 543:
+#line 3565 "glslang.y" /* yacc.c:1646  */
     {
         if ((yyvsp[0].interm.intermNode) && (yyvsp[0].interm.intermNode)->getAsBranchNode() && ((yyvsp[0].interm.intermNode)->getAsBranchNode()->getFlowOp() == EOpCase ||
                                             (yyvsp[0].interm.intermNode)->getAsBranchNode()->getFlowOp() == EOpDefault)) {
@@ -9734,76 +9878,76 @@
         } else
             (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-1].interm.intermNode), (yyvsp[0].interm.intermNode));
     }
-#line 9738 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9882 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 536:
-#line 3520 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 544:
+#line 3576 "glslang.y" /* yacc.c:1646  */
     { (yyval.interm.intermNode) = 0; }
-#line 9744 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9888 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 537:
-#line 3521 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 545:
+#line 3577 "glslang.y" /* yacc.c:1646  */
     { (yyval.interm.intermNode) = static_cast<TIntermNode*>((yyvsp[-1].interm.intermTypedNode)); }
-#line 9750 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9894 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 538:
-#line 3525 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 546:
+#line 3581 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
     }
-#line 9758 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9902 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 539:
-#line 3529 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 547:
+#line 3585 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.handleSelectionAttributes(*(yyvsp[-1].interm.attributes), (yyvsp[0].interm.intermNode));
         (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
     }
-#line 9767 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9911 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 540:
-#line 3536 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 548:
+#line 3592 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.boolCheck((yyvsp[-4].lex).loc, (yyvsp[-2].interm.intermTypedNode));
         (yyval.interm.intermNode) = parseContext.intermediate.addSelection((yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.nodePair), (yyvsp[-4].lex).loc);
     }
-#line 9776 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9920 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 541:
-#line 3543 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 549:
+#line 3599 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.nodePair).node1 = (yyvsp[-2].interm.intermNode);
         (yyval.interm.nodePair).node2 = (yyvsp[0].interm.intermNode);
     }
-#line 9785 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9929 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 542:
-#line 3547 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 550:
+#line 3603 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.nodePair).node1 = (yyvsp[0].interm.intermNode);
         (yyval.interm.nodePair).node2 = 0;
     }
-#line 9794 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9938 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 543:
-#line 3555 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 551:
+#line 3611 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
         parseContext.boolCheck((yyvsp[0].interm.intermTypedNode)->getLoc(), (yyvsp[0].interm.intermTypedNode));
     }
-#line 9803 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9947 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 544:
-#line 3559 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 552:
+#line 3615 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.boolCheck((yyvsp[-2].lex).loc, (yyvsp[-3].interm.type));
 
@@ -9814,28 +9958,28 @@
         else
             (yyval.interm.intermTypedNode) = 0;
     }
-#line 9818 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9962 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 545:
-#line 3572 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 553:
+#line 3628 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
     }
-#line 9826 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9970 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 546:
-#line 3576 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 554:
+#line 3632 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.handleSwitchAttributes(*(yyvsp[-1].interm.attributes), (yyvsp[0].interm.intermNode));
         (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
     }
-#line 9835 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9979 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 547:
-#line 3583 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 555:
+#line 3639 "glslang.y" /* yacc.c:1646  */
     {
         // start new switch sequence on the switch stack
         ++parseContext.controlFlowNestingLevel;
@@ -9844,11 +9988,11 @@
         parseContext.switchLevel.push_back(parseContext.statementNestingLevel);
         parseContext.symbolTable.push();
     }
-#line 9848 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 9992 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 548:
-#line 3591 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 556:
+#line 3647 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermNode) = parseContext.addSwitch((yyvsp[-7].lex).loc, (yyvsp[-5].interm.intermTypedNode), (yyvsp[-1].interm.intermNode) ? (yyvsp[-1].interm.intermNode)->getAsAggregate() : 0);
         delete parseContext.switchSequenceStack.back();
@@ -9858,27 +10002,27 @@
         --parseContext.statementNestingLevel;
         --parseContext.controlFlowNestingLevel;
     }
-#line 9862 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 10006 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 549:
-#line 3603 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 557:
+#line 3659 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermNode) = 0;
     }
-#line 9870 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 10014 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 550:
-#line 3606 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 558:
+#line 3662 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
     }
-#line 9878 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 10022 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 551:
-#line 3612 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 559:
+#line 3668 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermNode) = 0;
         if (parseContext.switchLevel.size() == 0)
@@ -9891,11 +10035,11 @@
             (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpCase, (yyvsp[-1].interm.intermTypedNode), (yyvsp[-2].lex).loc);
         }
     }
-#line 9895 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 10039 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 552:
-#line 3624 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 560:
+#line 3680 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermNode) = 0;
         if (parseContext.switchLevel.size() == 0)
@@ -9905,28 +10049,28 @@
         else
             (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpDefault, (yyvsp[-1].lex).loc);
     }
-#line 9909 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 10053 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 553:
-#line 3636 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 561:
+#line 3692 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
     }
-#line 9917 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 10061 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 554:
-#line 3640 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 562:
+#line 3696 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.handleLoopAttributes(*(yyvsp[-1].interm.attributes), (yyvsp[0].interm.intermNode));
         (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
     }
-#line 9926 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 10070 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 555:
-#line 3647 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 563:
+#line 3703 "glslang.y" /* yacc.c:1646  */
     {
         if (! parseContext.limits.whileLoops)
             parseContext.error((yyvsp[-1].lex).loc, "while loops not available", "limitation", "");
@@ -9935,11 +10079,11 @@
         ++parseContext.statementNestingLevel;
         ++parseContext.controlFlowNestingLevel;
     }
-#line 9939 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 10083 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 556:
-#line 3655 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 564:
+#line 3711 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
         (yyval.interm.intermNode) = parseContext.intermediate.addLoop((yyvsp[0].interm.intermNode), (yyvsp[-2].interm.intermTypedNode), 0, true, (yyvsp[-5].lex).loc);
@@ -9947,21 +10091,21 @@
         --parseContext.statementNestingLevel;
         --parseContext.controlFlowNestingLevel;
     }
-#line 9951 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 10095 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 557:
-#line 3662 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 565:
+#line 3718 "glslang.y" /* yacc.c:1646  */
     {
         ++parseContext.loopNestingLevel;
         ++parseContext.statementNestingLevel;
         ++parseContext.controlFlowNestingLevel;
     }
-#line 9961 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 10105 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 558:
-#line 3667 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 566:
+#line 3723 "glslang.y" /* yacc.c:1646  */
     {
         if (! parseContext.limits.whileLoops)
             parseContext.error((yyvsp[-7].lex).loc, "do-while loops not available", "limitation", "");
@@ -9973,22 +10117,22 @@
         --parseContext.statementNestingLevel;
         --parseContext.controlFlowNestingLevel;
     }
-#line 9977 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 10121 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 559:
-#line 3678 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 567:
+#line 3734 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.symbolTable.push();
         ++parseContext.loopNestingLevel;
         ++parseContext.statementNestingLevel;
         ++parseContext.controlFlowNestingLevel;
     }
-#line 9988 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 10132 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 560:
-#line 3684 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 568:
+#line 3740 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
         (yyval.interm.intermNode) = parseContext.intermediate.makeAggregate((yyvsp[-3].interm.intermNode), (yyvsp[-5].lex).loc);
@@ -10001,81 +10145,81 @@
         --parseContext.statementNestingLevel;
         --parseContext.controlFlowNestingLevel;
     }
-#line 10005 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 10149 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 561:
-#line 3699 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 569:
+#line 3755 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
     }
-#line 10013 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 10157 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 562:
-#line 3702 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 570:
+#line 3758 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
     }
-#line 10021 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 10165 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 563:
-#line 3708 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 571:
+#line 3764 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
     }
-#line 10029 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 10173 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 564:
-#line 3711 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 572:
+#line 3767 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermTypedNode) = 0;
     }
-#line 10037 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 10181 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 565:
-#line 3717 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 573:
+#line 3773 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.nodePair).node1 = (yyvsp[-1].interm.intermTypedNode);
         (yyval.interm.nodePair).node2 = 0;
     }
-#line 10046 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 10190 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 566:
-#line 3721 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 574:
+#line 3777 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.nodePair).node1 = (yyvsp[-2].interm.intermTypedNode);
         (yyval.interm.nodePair).node2 = (yyvsp[0].interm.intermTypedNode);
     }
-#line 10055 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 10199 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 567:
-#line 3728 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 575:
+#line 3784 "glslang.y" /* yacc.c:1646  */
     {
         if (parseContext.loopNestingLevel <= 0)
             parseContext.error((yyvsp[-1].lex).loc, "continue statement only allowed in loops", "", "");
         (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpContinue, (yyvsp[-1].lex).loc);
     }
-#line 10065 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 10209 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 568:
-#line 3733 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 576:
+#line 3789 "glslang.y" /* yacc.c:1646  */
     {
         if (parseContext.loopNestingLevel + parseContext.switchSequenceStack.size() <= 0)
             parseContext.error((yyvsp[-1].lex).loc, "break statement only allowed in switch and loops", "", "");
         (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpBreak, (yyvsp[-1].lex).loc);
     }
-#line 10075 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 10219 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 569:
-#line 3738 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 577:
+#line 3794 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpReturn, (yyvsp[-1].lex).loc);
         if (parseContext.currentFunctionType->getBasicType() != EbtVoid)
@@ -10083,83 +10227,83 @@
         if (parseContext.inMain)
             parseContext.postEntryPointReturn = true;
     }
-#line 10087 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 10231 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 570:
-#line 3745 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 578:
+#line 3801 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermNode) = parseContext.handleReturnValue((yyvsp[-2].lex).loc, (yyvsp[-1].interm.intermTypedNode));
     }
-#line 10095 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 10239 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 571:
-#line 3748 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 579:
+#line 3804 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.requireStage((yyvsp[-1].lex).loc, EShLangFragment, "discard");
         (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpKill, (yyvsp[-1].lex).loc);
     }
-#line 10104 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 10248 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 572:
-#line 3757 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 580:
+#line 3813 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
         parseContext.intermediate.setTreeRoot((yyval.interm.intermNode));
     }
-#line 10113 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 10257 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 573:
-#line 3761 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 581:
+#line 3817 "glslang.y" /* yacc.c:1646  */
     {
         if ((yyvsp[0].interm.intermNode) != nullptr) {
             (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-1].interm.intermNode), (yyvsp[0].interm.intermNode));
             parseContext.intermediate.setTreeRoot((yyval.interm.intermNode));
         }
     }
-#line 10124 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 10268 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 574:
-#line 3770 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 582:
+#line 3826 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
     }
-#line 10132 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 10276 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 575:
-#line 3773 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 583:
+#line 3829 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode);
     }
-#line 10140 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 10284 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 576:
-#line 3777 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 584:
+#line 3833 "glslang.y" /* yacc.c:1646  */
     {
         parseContext.requireProfile((yyvsp[0].lex).loc, ~EEsProfile, "extraneous semicolon");
         parseContext.profileRequires((yyvsp[0].lex).loc, ~EEsProfile, 460, nullptr, "extraneous semicolon");
         (yyval.interm.intermNode) = nullptr;
     }
-#line 10150 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 10294 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 577:
-#line 3786 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 585:
+#line 3842 "glslang.y" /* yacc.c:1646  */
     {
         (yyvsp[0].interm).function = parseContext.handleFunctionDeclarator((yyvsp[0].interm).loc, *(yyvsp[0].interm).function, false /* not prototype */);
         (yyvsp[0].interm).intermNode = parseContext.handleFunctionDefinition((yyvsp[0].interm).loc, *(yyvsp[0].interm).function);
     }
-#line 10159 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 10303 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 578:
-#line 3790 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 586:
+#line 3846 "glslang.y" /* yacc.c:1646  */
     {
         //   May be best done as post process phase on intermediate code
         if (parseContext.currentFunctionType->getBasicType() != EbtVoid && ! parseContext.functionReturnsValue)
@@ -10175,52 +10319,52 @@
         (yyval.interm.intermNode)->getAsAggregate()->setDebug(parseContext.contextPragma.debug);
         (yyval.interm.intermNode)->getAsAggregate()->setPragmaTable(parseContext.contextPragma.pragmaTable);
     }
-#line 10179 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 10323 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 579:
-#line 3809 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 587:
+#line 3865 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.attributes) = (yyvsp[-2].interm.attributes);
         parseContext.requireExtensions((yyvsp[-4].lex).loc, 1, &E_GL_EXT_control_flow_attributes, "attribute");
     }
-#line 10188 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 10332 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 580:
-#line 3815 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 588:
+#line 3871 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.attributes) = (yyvsp[0].interm.attributes);
     }
-#line 10196 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 10340 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 581:
-#line 3818 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 589:
+#line 3874 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.attributes) = parseContext.mergeAttributes((yyvsp[-2].interm.attributes), (yyvsp[0].interm.attributes));
     }
-#line 10204 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 10348 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 582:
-#line 3823 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 590:
+#line 3879 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.attributes) = parseContext.makeAttributes(*(yyvsp[0].lex).string);
     }
-#line 10212 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 10356 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
-  case 583:
-#line 3826 "MachineIndependent/glslang.y" /* yacc.c:1646  */
+  case 591:
+#line 3882 "glslang.y" /* yacc.c:1646  */
     {
         (yyval.interm.attributes) = parseContext.makeAttributes(*(yyvsp[-3].lex).string, (yyvsp[-1].interm.intermTypedNode));
     }
-#line 10220 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 10364 "glslang_tab.cpp" /* yacc.c:1646  */
     break;
 
 
-#line 10224 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646  */
+#line 10368 "glslang_tab.cpp" /* yacc.c:1646  */
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
@@ -10448,5 +10592,6 @@
 #endif
   return yyresult;
 }
-#line 3831 "MachineIndependent/glslang.y" /* yacc.c:1906  */
+#line 3887 "glslang.y" /* yacc.c:1906  */
+
 
diff --git a/third_party/glslang/src/glslang/MachineIndependent/glslang_tab.cpp.h b/third_party/glslang/src/glslang/MachineIndependent/glslang_tab.cpp.h
index 2013790..31c8f90 100644
--- a/third_party/glslang/src/glslang/MachineIndependent/glslang_tab.cpp.h
+++ b/third_party/glslang/src/glslang/MachineIndependent/glslang_tab.cpp.h
@@ -30,8 +30,8 @@
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
 
-#ifndef YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED
-# define YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED
+#ifndef YY_YY_GLSLANG_TAB_CPP_H_INCLUDED
+# define YY_YY_GLSLANG_TAB_CPP_H_INCLUDED
 /* Debug traces.  */
 #ifndef YYDEBUG
 # define YYDEBUG 1
@@ -203,257 +203,265 @@
     F64MAT4X4 = 413,
     ATOMIC_UINT = 414,
     ACCSTRUCTNV = 415,
-    FCOOPMATNV = 416,
-    ICOOPMATNV = 417,
-    UCOOPMATNV = 418,
-    SAMPLERCUBEARRAY = 419,
-    SAMPLERCUBEARRAYSHADOW = 420,
-    ISAMPLERCUBEARRAY = 421,
-    USAMPLERCUBEARRAY = 422,
-    SAMPLER1D = 423,
-    SAMPLER1DARRAY = 424,
-    SAMPLER1DARRAYSHADOW = 425,
-    ISAMPLER1D = 426,
-    SAMPLER1DSHADOW = 427,
-    SAMPLER2DRECT = 428,
-    SAMPLER2DRECTSHADOW = 429,
-    ISAMPLER2DRECT = 430,
-    USAMPLER2DRECT = 431,
-    SAMPLERBUFFER = 432,
-    ISAMPLERBUFFER = 433,
-    USAMPLERBUFFER = 434,
-    SAMPLER2DMS = 435,
-    ISAMPLER2DMS = 436,
-    USAMPLER2DMS = 437,
-    SAMPLER2DMSARRAY = 438,
-    ISAMPLER2DMSARRAY = 439,
-    USAMPLER2DMSARRAY = 440,
-    SAMPLEREXTERNALOES = 441,
-    SAMPLEREXTERNAL2DY2YEXT = 442,
-    ISAMPLER1DARRAY = 443,
-    USAMPLER1D = 444,
-    USAMPLER1DARRAY = 445,
-    F16SAMPLER1D = 446,
-    F16SAMPLER2D = 447,
-    F16SAMPLER3D = 448,
-    F16SAMPLER2DRECT = 449,
-    F16SAMPLERCUBE = 450,
-    F16SAMPLER1DARRAY = 451,
-    F16SAMPLER2DARRAY = 452,
-    F16SAMPLERCUBEARRAY = 453,
-    F16SAMPLERBUFFER = 454,
-    F16SAMPLER2DMS = 455,
-    F16SAMPLER2DMSARRAY = 456,
-    F16SAMPLER1DSHADOW = 457,
-    F16SAMPLER2DSHADOW = 458,
-    F16SAMPLER1DARRAYSHADOW = 459,
-    F16SAMPLER2DARRAYSHADOW = 460,
-    F16SAMPLER2DRECTSHADOW = 461,
-    F16SAMPLERCUBESHADOW = 462,
-    F16SAMPLERCUBEARRAYSHADOW = 463,
-    IMAGE1D = 464,
-    IIMAGE1D = 465,
-    UIMAGE1D = 466,
-    IMAGE2D = 467,
-    IIMAGE2D = 468,
-    UIMAGE2D = 469,
-    IMAGE3D = 470,
-    IIMAGE3D = 471,
-    UIMAGE3D = 472,
-    IMAGE2DRECT = 473,
-    IIMAGE2DRECT = 474,
-    UIMAGE2DRECT = 475,
-    IMAGECUBE = 476,
-    IIMAGECUBE = 477,
-    UIMAGECUBE = 478,
-    IMAGEBUFFER = 479,
-    IIMAGEBUFFER = 480,
-    UIMAGEBUFFER = 481,
-    IMAGE1DARRAY = 482,
-    IIMAGE1DARRAY = 483,
-    UIMAGE1DARRAY = 484,
-    IMAGE2DARRAY = 485,
-    IIMAGE2DARRAY = 486,
-    UIMAGE2DARRAY = 487,
-    IMAGECUBEARRAY = 488,
-    IIMAGECUBEARRAY = 489,
-    UIMAGECUBEARRAY = 490,
-    IMAGE2DMS = 491,
-    IIMAGE2DMS = 492,
-    UIMAGE2DMS = 493,
-    IMAGE2DMSARRAY = 494,
-    IIMAGE2DMSARRAY = 495,
-    UIMAGE2DMSARRAY = 496,
-    F16IMAGE1D = 497,
-    F16IMAGE2D = 498,
-    F16IMAGE3D = 499,
-    F16IMAGE2DRECT = 500,
-    F16IMAGECUBE = 501,
-    F16IMAGE1DARRAY = 502,
-    F16IMAGE2DARRAY = 503,
-    F16IMAGECUBEARRAY = 504,
-    F16IMAGEBUFFER = 505,
-    F16IMAGE2DMS = 506,
-    F16IMAGE2DMSARRAY = 507,
-    TEXTURECUBEARRAY = 508,
-    ITEXTURECUBEARRAY = 509,
-    UTEXTURECUBEARRAY = 510,
-    TEXTURE1D = 511,
-    ITEXTURE1D = 512,
-    UTEXTURE1D = 513,
-    TEXTURE1DARRAY = 514,
-    ITEXTURE1DARRAY = 515,
-    UTEXTURE1DARRAY = 516,
-    TEXTURE2DRECT = 517,
-    ITEXTURE2DRECT = 518,
-    UTEXTURE2DRECT = 519,
-    TEXTUREBUFFER = 520,
-    ITEXTUREBUFFER = 521,
-    UTEXTUREBUFFER = 522,
-    TEXTURE2DMS = 523,
-    ITEXTURE2DMS = 524,
-    UTEXTURE2DMS = 525,
-    TEXTURE2DMSARRAY = 526,
-    ITEXTURE2DMSARRAY = 527,
-    UTEXTURE2DMSARRAY = 528,
-    F16TEXTURE1D = 529,
-    F16TEXTURE2D = 530,
-    F16TEXTURE3D = 531,
-    F16TEXTURE2DRECT = 532,
-    F16TEXTURECUBE = 533,
-    F16TEXTURE1DARRAY = 534,
-    F16TEXTURE2DARRAY = 535,
-    F16TEXTURECUBEARRAY = 536,
-    F16TEXTUREBUFFER = 537,
-    F16TEXTURE2DMS = 538,
-    F16TEXTURE2DMSARRAY = 539,
-    SUBPASSINPUT = 540,
-    SUBPASSINPUTMS = 541,
-    ISUBPASSINPUT = 542,
-    ISUBPASSINPUTMS = 543,
-    USUBPASSINPUT = 544,
-    USUBPASSINPUTMS = 545,
-    F16SUBPASSINPUT = 546,
-    F16SUBPASSINPUTMS = 547,
-    LEFT_OP = 548,
-    RIGHT_OP = 549,
-    INC_OP = 550,
-    DEC_OP = 551,
-    LE_OP = 552,
-    GE_OP = 553,
-    EQ_OP = 554,
-    NE_OP = 555,
-    AND_OP = 556,
-    OR_OP = 557,
-    XOR_OP = 558,
-    MUL_ASSIGN = 559,
-    DIV_ASSIGN = 560,
-    ADD_ASSIGN = 561,
-    MOD_ASSIGN = 562,
-    LEFT_ASSIGN = 563,
-    RIGHT_ASSIGN = 564,
-    AND_ASSIGN = 565,
-    XOR_ASSIGN = 566,
-    OR_ASSIGN = 567,
-    SUB_ASSIGN = 568,
-    STRING_LITERAL = 569,
-    LEFT_PAREN = 570,
-    RIGHT_PAREN = 571,
-    LEFT_BRACKET = 572,
-    RIGHT_BRACKET = 573,
-    LEFT_BRACE = 574,
-    RIGHT_BRACE = 575,
-    DOT = 576,
-    COMMA = 577,
-    COLON = 578,
-    EQUAL = 579,
-    SEMICOLON = 580,
-    BANG = 581,
-    DASH = 582,
-    TILDE = 583,
-    PLUS = 584,
-    STAR = 585,
-    SLASH = 586,
-    PERCENT = 587,
-    LEFT_ANGLE = 588,
-    RIGHT_ANGLE = 589,
-    VERTICAL_BAR = 590,
-    CARET = 591,
-    AMPERSAND = 592,
-    QUESTION = 593,
-    INVARIANT = 594,
-    HIGH_PRECISION = 595,
-    MEDIUM_PRECISION = 596,
-    LOW_PRECISION = 597,
-    PRECISION = 598,
-    PACKED = 599,
-    RESOURCE = 600,
-    SUPERP = 601,
-    FLOATCONSTANT = 602,
-    INTCONSTANT = 603,
-    UINTCONSTANT = 604,
-    BOOLCONSTANT = 605,
-    IDENTIFIER = 606,
-    TYPE_NAME = 607,
-    CENTROID = 608,
-    IN = 609,
-    OUT = 610,
-    INOUT = 611,
-    STRUCT = 612,
-    VOID = 613,
-    WHILE = 614,
-    BREAK = 615,
-    CONTINUE = 616,
-    DO = 617,
-    ELSE = 618,
-    FOR = 619,
-    IF = 620,
-    DISCARD = 621,
-    RETURN = 622,
-    SWITCH = 623,
-    CASE = 624,
-    DEFAULT = 625,
-    UNIFORM = 626,
-    SHARED = 627,
-    BUFFER = 628,
-    FLAT = 629,
-    SMOOTH = 630,
-    LAYOUT = 631,
-    DOUBLECONSTANT = 632,
-    INT16CONSTANT = 633,
-    UINT16CONSTANT = 634,
-    FLOAT16CONSTANT = 635,
-    INT32CONSTANT = 636,
-    UINT32CONSTANT = 637,
-    INT64CONSTANT = 638,
-    UINT64CONSTANT = 639,
-    SUBROUTINE = 640,
-    DEMOTE = 641,
-    PAYLOADNV = 642,
-    PAYLOADINNV = 643,
-    HITATTRNV = 644,
-    CALLDATANV = 645,
-    CALLDATAINNV = 646,
-    PATCH = 647,
-    SAMPLE = 648,
-    NONUNIFORM = 649,
-    COHERENT = 650,
-    VOLATILE = 651,
-    RESTRICT = 652,
-    READONLY = 653,
-    WRITEONLY = 654,
-    DEVICECOHERENT = 655,
-    QUEUEFAMILYCOHERENT = 656,
-    WORKGROUPCOHERENT = 657,
-    SUBGROUPCOHERENT = 658,
-    NONPRIVATE = 659,
-    NOPERSPECTIVE = 660,
-    EXPLICITINTERPAMD = 661,
-    PERVERTEXNV = 662,
-    PERPRIMITIVENV = 663,
-    PERVIEWNV = 664,
-    PERTASKNV = 665,
-    PRECISE = 666
+    ACCSTRUCTEXT = 416,
+    RAYQUERYEXT = 417,
+    FCOOPMATNV = 418,
+    ICOOPMATNV = 419,
+    UCOOPMATNV = 420,
+    SAMPLERCUBEARRAY = 421,
+    SAMPLERCUBEARRAYSHADOW = 422,
+    ISAMPLERCUBEARRAY = 423,
+    USAMPLERCUBEARRAY = 424,
+    SAMPLER1D = 425,
+    SAMPLER1DARRAY = 426,
+    SAMPLER1DARRAYSHADOW = 427,
+    ISAMPLER1D = 428,
+    SAMPLER1DSHADOW = 429,
+    SAMPLER2DRECT = 430,
+    SAMPLER2DRECTSHADOW = 431,
+    ISAMPLER2DRECT = 432,
+    USAMPLER2DRECT = 433,
+    SAMPLERBUFFER = 434,
+    ISAMPLERBUFFER = 435,
+    USAMPLERBUFFER = 436,
+    SAMPLER2DMS = 437,
+    ISAMPLER2DMS = 438,
+    USAMPLER2DMS = 439,
+    SAMPLER2DMSARRAY = 440,
+    ISAMPLER2DMSARRAY = 441,
+    USAMPLER2DMSARRAY = 442,
+    SAMPLEREXTERNALOES = 443,
+    SAMPLEREXTERNAL2DY2YEXT = 444,
+    ISAMPLER1DARRAY = 445,
+    USAMPLER1D = 446,
+    USAMPLER1DARRAY = 447,
+    F16SAMPLER1D = 448,
+    F16SAMPLER2D = 449,
+    F16SAMPLER3D = 450,
+    F16SAMPLER2DRECT = 451,
+    F16SAMPLERCUBE = 452,
+    F16SAMPLER1DARRAY = 453,
+    F16SAMPLER2DARRAY = 454,
+    F16SAMPLERCUBEARRAY = 455,
+    F16SAMPLERBUFFER = 456,
+    F16SAMPLER2DMS = 457,
+    F16SAMPLER2DMSARRAY = 458,
+    F16SAMPLER1DSHADOW = 459,
+    F16SAMPLER2DSHADOW = 460,
+    F16SAMPLER1DARRAYSHADOW = 461,
+    F16SAMPLER2DARRAYSHADOW = 462,
+    F16SAMPLER2DRECTSHADOW = 463,
+    F16SAMPLERCUBESHADOW = 464,
+    F16SAMPLERCUBEARRAYSHADOW = 465,
+    IMAGE1D = 466,
+    IIMAGE1D = 467,
+    UIMAGE1D = 468,
+    IMAGE2D = 469,
+    IIMAGE2D = 470,
+    UIMAGE2D = 471,
+    IMAGE3D = 472,
+    IIMAGE3D = 473,
+    UIMAGE3D = 474,
+    IMAGE2DRECT = 475,
+    IIMAGE2DRECT = 476,
+    UIMAGE2DRECT = 477,
+    IMAGECUBE = 478,
+    IIMAGECUBE = 479,
+    UIMAGECUBE = 480,
+    IMAGEBUFFER = 481,
+    IIMAGEBUFFER = 482,
+    UIMAGEBUFFER = 483,
+    IMAGE1DARRAY = 484,
+    IIMAGE1DARRAY = 485,
+    UIMAGE1DARRAY = 486,
+    IMAGE2DARRAY = 487,
+    IIMAGE2DARRAY = 488,
+    UIMAGE2DARRAY = 489,
+    IMAGECUBEARRAY = 490,
+    IIMAGECUBEARRAY = 491,
+    UIMAGECUBEARRAY = 492,
+    IMAGE2DMS = 493,
+    IIMAGE2DMS = 494,
+    UIMAGE2DMS = 495,
+    IMAGE2DMSARRAY = 496,
+    IIMAGE2DMSARRAY = 497,
+    UIMAGE2DMSARRAY = 498,
+    F16IMAGE1D = 499,
+    F16IMAGE2D = 500,
+    F16IMAGE3D = 501,
+    F16IMAGE2DRECT = 502,
+    F16IMAGECUBE = 503,
+    F16IMAGE1DARRAY = 504,
+    F16IMAGE2DARRAY = 505,
+    F16IMAGECUBEARRAY = 506,
+    F16IMAGEBUFFER = 507,
+    F16IMAGE2DMS = 508,
+    F16IMAGE2DMSARRAY = 509,
+    TEXTURECUBEARRAY = 510,
+    ITEXTURECUBEARRAY = 511,
+    UTEXTURECUBEARRAY = 512,
+    TEXTURE1D = 513,
+    ITEXTURE1D = 514,
+    UTEXTURE1D = 515,
+    TEXTURE1DARRAY = 516,
+    ITEXTURE1DARRAY = 517,
+    UTEXTURE1DARRAY = 518,
+    TEXTURE2DRECT = 519,
+    ITEXTURE2DRECT = 520,
+    UTEXTURE2DRECT = 521,
+    TEXTUREBUFFER = 522,
+    ITEXTUREBUFFER = 523,
+    UTEXTUREBUFFER = 524,
+    TEXTURE2DMS = 525,
+    ITEXTURE2DMS = 526,
+    UTEXTURE2DMS = 527,
+    TEXTURE2DMSARRAY = 528,
+    ITEXTURE2DMSARRAY = 529,
+    UTEXTURE2DMSARRAY = 530,
+    F16TEXTURE1D = 531,
+    F16TEXTURE2D = 532,
+    F16TEXTURE3D = 533,
+    F16TEXTURE2DRECT = 534,
+    F16TEXTURECUBE = 535,
+    F16TEXTURE1DARRAY = 536,
+    F16TEXTURE2DARRAY = 537,
+    F16TEXTURECUBEARRAY = 538,
+    F16TEXTUREBUFFER = 539,
+    F16TEXTURE2DMS = 540,
+    F16TEXTURE2DMSARRAY = 541,
+    SUBPASSINPUT = 542,
+    SUBPASSINPUTMS = 543,
+    ISUBPASSINPUT = 544,
+    ISUBPASSINPUTMS = 545,
+    USUBPASSINPUT = 546,
+    USUBPASSINPUTMS = 547,
+    F16SUBPASSINPUT = 548,
+    F16SUBPASSINPUTMS = 549,
+    LEFT_OP = 550,
+    RIGHT_OP = 551,
+    INC_OP = 552,
+    DEC_OP = 553,
+    LE_OP = 554,
+    GE_OP = 555,
+    EQ_OP = 556,
+    NE_OP = 557,
+    AND_OP = 558,
+    OR_OP = 559,
+    XOR_OP = 560,
+    MUL_ASSIGN = 561,
+    DIV_ASSIGN = 562,
+    ADD_ASSIGN = 563,
+    MOD_ASSIGN = 564,
+    LEFT_ASSIGN = 565,
+    RIGHT_ASSIGN = 566,
+    AND_ASSIGN = 567,
+    XOR_ASSIGN = 568,
+    OR_ASSIGN = 569,
+    SUB_ASSIGN = 570,
+    STRING_LITERAL = 571,
+    LEFT_PAREN = 572,
+    RIGHT_PAREN = 573,
+    LEFT_BRACKET = 574,
+    RIGHT_BRACKET = 575,
+    LEFT_BRACE = 576,
+    RIGHT_BRACE = 577,
+    DOT = 578,
+    COMMA = 579,
+    COLON = 580,
+    EQUAL = 581,
+    SEMICOLON = 582,
+    BANG = 583,
+    DASH = 584,
+    TILDE = 585,
+    PLUS = 586,
+    STAR = 587,
+    SLASH = 588,
+    PERCENT = 589,
+    LEFT_ANGLE = 590,
+    RIGHT_ANGLE = 591,
+    VERTICAL_BAR = 592,
+    CARET = 593,
+    AMPERSAND = 594,
+    QUESTION = 595,
+    INVARIANT = 596,
+    HIGH_PRECISION = 597,
+    MEDIUM_PRECISION = 598,
+    LOW_PRECISION = 599,
+    PRECISION = 600,
+    PACKED = 601,
+    RESOURCE = 602,
+    SUPERP = 603,
+    FLOATCONSTANT = 604,
+    INTCONSTANT = 605,
+    UINTCONSTANT = 606,
+    BOOLCONSTANT = 607,
+    IDENTIFIER = 608,
+    TYPE_NAME = 609,
+    CENTROID = 610,
+    IN = 611,
+    OUT = 612,
+    INOUT = 613,
+    STRUCT = 614,
+    VOID = 615,
+    WHILE = 616,
+    BREAK = 617,
+    CONTINUE = 618,
+    DO = 619,
+    ELSE = 620,
+    FOR = 621,
+    IF = 622,
+    DISCARD = 623,
+    RETURN = 624,
+    SWITCH = 625,
+    CASE = 626,
+    DEFAULT = 627,
+    UNIFORM = 628,
+    SHARED = 629,
+    BUFFER = 630,
+    FLAT = 631,
+    SMOOTH = 632,
+    LAYOUT = 633,
+    DOUBLECONSTANT = 634,
+    INT16CONSTANT = 635,
+    UINT16CONSTANT = 636,
+    FLOAT16CONSTANT = 637,
+    INT32CONSTANT = 638,
+    UINT32CONSTANT = 639,
+    INT64CONSTANT = 640,
+    UINT64CONSTANT = 641,
+    SUBROUTINE = 642,
+    DEMOTE = 643,
+    PAYLOADNV = 644,
+    PAYLOADINNV = 645,
+    HITATTRNV = 646,
+    CALLDATANV = 647,
+    CALLDATAINNV = 648,
+    PAYLOADEXT = 649,
+    PAYLOADINEXT = 650,
+    HITATTREXT = 651,
+    CALLDATAEXT = 652,
+    CALLDATAINEXT = 653,
+    PATCH = 654,
+    SAMPLE = 655,
+    NONUNIFORM = 656,
+    COHERENT = 657,
+    VOLATILE = 658,
+    RESTRICT = 659,
+    READONLY = 660,
+    WRITEONLY = 661,
+    DEVICECOHERENT = 662,
+    QUEUEFAMILYCOHERENT = 663,
+    WORKGROUPCOHERENT = 664,
+    SUBGROUPCOHERENT = 665,
+    NONPRIVATE = 666,
+    SHADERCALLCOHERENT = 667,
+    NOPERSPECTIVE = 668,
+    EXPLICITINTERPAMD = 669,
+    PERVERTEXNV = 670,
+    PERPRIMITIVENV = 671,
+    PERVIEWNV = 672,
+    PERTASKNV = 673,
+    PRECISE = 674
   };
 #endif
 
@@ -462,7 +470,7 @@
 
 union YYSTYPE
 {
-#line 96 "MachineIndependent/glslang.y" /* yacc.c:1909  */
+#line 97 "glslang.y" /* yacc.c:1909  */
 
     struct {
         glslang::TSourceLoc loc;
@@ -498,7 +506,7 @@
         glslang::TArraySizes* typeParameters;
     } interm;
 
-#line 502 "MachineIndependent/glslang_tab.cpp.h" /* yacc.c:1909  */
+#line 510 "glslang_tab.cpp.h" /* yacc.c:1909  */
 };
 
 typedef union YYSTYPE YYSTYPE;
@@ -510,4 +518,4 @@
 
 int yyparse (glslang::TParseContext* pParseContext);
 
-#endif /* !YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED  */
+#endif /* !YY_YY_GLSLANG_TAB_CPP_H_INCLUDED  */
diff --git a/third_party/glslang/src/glslang/MachineIndependent/intermOut.cpp b/third_party/glslang/src/glslang/MachineIndependent/intermOut.cpp
index 53ac047..593ed6f 100644
--- a/third_party/glslang/src/glslang/MachineIndependent/intermOut.cpp
+++ b/third_party/glslang/src/glslang/MachineIndependent/intermOut.cpp
@@ -2,6 +2,7 @@
 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
 // Copyright (C) 2012-2016 LunarG, Inc.
 // Copyright (C) 2017 ARM Limited.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 //
 // All rights reserved.
 //
@@ -1078,13 +1079,37 @@
     case EOpSubpassLoad:   out.debug << "subpassLoad";   break;
     case EOpSubpassLoadMS: out.debug << "subpassLoadMS"; break;
 
-    case EOpTraceNV:                          out.debug << "traceNV"; break;
-    case EOpReportIntersectionNV:             out.debug << "reportIntersectionNV"; break;
-    case EOpIgnoreIntersectionNV:             out.debug << "ignoreIntersectionNV"; break;
-    case EOpTerminateRayNV:                   out.debug << "terminateRayNV"; break;
-    case EOpExecuteCallableNV:                out.debug << "executeCallableNV"; break;
+    case EOpTrace:                            out.debug << "traceNV"; break;
+    case EOpReportIntersection:               out.debug << "reportIntersectionNV"; break;
+    case EOpIgnoreIntersection:               out.debug << "ignoreIntersectionNV"; break;
+    case EOpTerminateRay:                     out.debug << "terminateRayNV"; break;
+    case EOpExecuteCallable:                  out.debug << "executeCallableNV"; break;
     case EOpWritePackedPrimitiveIndices4x8NV: out.debug << "writePackedPrimitiveIndices4x8NV"; break;
 
+    case EOpRayQueryInitialize:                                            out.debug << "rayQueryInitializeEXT"; break;
+    case EOpRayQueryTerminate:                                             out.debug << "rayQueryTerminateEXT"; break;
+    case EOpRayQueryGenerateIntersection:                                  out.debug << "rayQueryGenerateIntersectionEXT"; break;
+    case EOpRayQueryConfirmIntersection:                                   out.debug << "rayQueryConfirmIntersectionEXT"; break;
+    case EOpRayQueryProceed:                                               out.debug << "rayQueryProceedEXT"; break;
+    case EOpRayQueryGetIntersectionType:                                   out.debug << "rayQueryGetIntersectionTypeEXT"; break;
+    case EOpRayQueryGetRayTMin:                                            out.debug << "rayQueryGetRayTMinEXT"; break;
+    case EOpRayQueryGetRayFlags:                                           out.debug << "rayQueryGetRayFlagsEXT"; break;
+    case EOpRayQueryGetIntersectionT:                                      out.debug << "rayQueryGetIntersectionTEXT"; break;
+    case EOpRayQueryGetIntersectionInstanceCustomIndex:                    out.debug << "rayQueryGetIntersectionInstanceCustomIndexEXT"; break;
+    case EOpRayQueryGetIntersectionInstanceId:                             out.debug << "rayQueryGetIntersectionInstanceIdEXT"; break;
+    case EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset: out.debug << "rayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetEXT"; break;
+    case EOpRayQueryGetIntersectionGeometryIndex:                          out.debug << "rayQueryGetIntersectionGeometryIndexEXT"; break;
+    case EOpRayQueryGetIntersectionPrimitiveIndex:                         out.debug << "rayQueryGetIntersectionPrimitiveIndexEXT"; break;
+    case EOpRayQueryGetIntersectionBarycentrics:                           out.debug << "rayQueryGetIntersectionBarycentricsEXT"; break;
+    case EOpRayQueryGetIntersectionFrontFace:                              out.debug << "rayQueryGetIntersectionFrontFaceEXT"; break;
+    case EOpRayQueryGetIntersectionCandidateAABBOpaque:                    out.debug << "rayQueryGetIntersectionCandidateAABBOpaqueEXT"; break;
+    case EOpRayQueryGetIntersectionObjectRayDirection:                     out.debug << "rayQueryGetIntersectionObjectRayDirectionEXT"; break;
+    case EOpRayQueryGetIntersectionObjectRayOrigin:                        out.debug << "rayQueryGetIntersectionObjectRayOriginEXT"; break;
+    case EOpRayQueryGetWorldRayDirection:                                  out.debug << "rayQueryGetWorldRayDirectionEXT"; break;
+    case EOpRayQueryGetWorldRayOrigin:                                     out.debug << "rayQueryGetWorldRayOriginEXT"; break;
+    case EOpRayQueryGetIntersectionObjectToWorld:                          out.debug << "rayQueryGetIntersectionObjectToWorldEXT"; break;
+    case EOpRayQueryGetIntersectionWorldToObject:                          out.debug << "rayQueryGetIntersectionWorldToObjectEXT"; break;
+
     case EOpCooperativeMatrixLoad:  out.debug << "Load cooperative matrix";  break;
     case EOpCooperativeMatrixStore:  out.debug << "Store cooperative matrix";  break;
     case EOpCooperativeMatrixMulAdd: out.debug << "MulAdd cooperative matrices"; break;
@@ -1537,4 +1562,4 @@
 
 } // end namespace glslang
 
-#endif // not GLSLANG_WEB
\ No newline at end of file
+#endif // not GLSLANG_WEB
diff --git a/third_party/glslang/src/glslang/MachineIndependent/iomapper.cpp b/third_party/glslang/src/glslang/MachineIndependent/iomapper.cpp
index 1b2ecc9..9dc1da2 100644
--- a/third_party/glslang/src/glslang/MachineIndependent/iomapper.cpp
+++ b/third_party/glslang/src/glslang/MachineIndependent/iomapper.cpp
@@ -1176,7 +1176,7 @@
         resolver = &defaultResolver;
     }
     resolver->addStage(stage);
-    inVarMaps[stage] = new TVarLiveMap, outVarMaps[stage] = new TVarLiveMap(), uniformVarMap[stage] = new TVarLiveMap();
+    inVarMaps[stage] = new TVarLiveMap(); outVarMaps[stage] = new TVarLiveMap(); uniformVarMap[stage] = new TVarLiveMap();
     TVarGatherTraverser iter_binding_all(intermediate, true, *inVarMaps[stage], *outVarMaps[stage],
                                          *uniformVarMap[stage]);
     TVarGatherTraverser iter_binding_live(intermediate, false, *inVarMaps[stage], *outVarMaps[stage],
diff --git a/third_party/glslang/src/glslang/MachineIndependent/linkValidate.cpp b/third_party/glslang/src/glslang/MachineIndependent/linkValidate.cpp
old mode 100644
new mode 100755
index 7fa084b..dcb1cc8
--- a/third_party/glslang/src/glslang/MachineIndependent/linkValidate.cpp
+++ b/third_party/glslang/src/glslang/MachineIndependent/linkValidate.cpp
@@ -290,7 +290,7 @@
     }
 
     // Getting this far means we have two existing trees to merge...
-    numShaderRecordNVBlocks += unit.numShaderRecordNVBlocks;
+    numShaderRecordBlocks += unit.numShaderRecordBlocks;
     numTaskNVBlocks += unit.numTaskNVBlocks;
 
     // Get the top-level globals of each unit
@@ -303,10 +303,10 @@
 
     // Map by global name to unique ID to rationalize the same object having
     // differing IDs in different trees.
-    TMap<TString, int> idMap;
+    TIdMaps idMaps;
     int maxId;
-    seedIdMap(idMap, maxId);
-    remapIds(idMap, maxId + 1, unit);
+    seedIdMap(idMaps, maxId);
+    remapIds(idMaps, maxId + 1, unit);
 
     mergeBodies(infoSink, globals, unitGlobals);
     mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects);
@@ -315,27 +315,40 @@
 
 #endif
 
+static const TString& getNameForIdMap(TIntermSymbol* symbol)
+{
+    TShaderInterface si = symbol->getType().getShaderInterface();
+    if (si == EsiNone)
+        return symbol->getName();
+    else
+        return symbol->getType().getTypeName();
+}
+
+
+
 // Traverser that seeds an ID map with all built-ins, and tracks the
 // maximum ID used.
 // (It would be nice to put this in a function, but that causes warnings
 // on having no bodies for the copy-constructor/operator=.)
 class TBuiltInIdTraverser : public TIntermTraverser {
 public:
-    TBuiltInIdTraverser(TMap<TString, int>& idMap) : idMap(idMap), maxId(0) { }
+    TBuiltInIdTraverser(TIdMaps& idMaps) : idMaps(idMaps), maxId(0) { }
     // If it's a built in, add it to the map.
     // Track the max ID.
     virtual void visitSymbol(TIntermSymbol* symbol)
     {
         const TQualifier& qualifier = symbol->getType().getQualifier();
-        if (qualifier.builtIn != EbvNone)
-            idMap[symbol->getName()] = symbol->getId();
+        if (qualifier.builtIn != EbvNone) {
+            TShaderInterface si = symbol->getType().getShaderInterface();
+            idMaps[si][getNameForIdMap(symbol)] = symbol->getId();
+        }
         maxId = std::max(maxId, symbol->getId());
     }
     int getMaxId() const { return maxId; }
 protected:
     TBuiltInIdTraverser(TBuiltInIdTraverser&);
     TBuiltInIdTraverser& operator=(TBuiltInIdTraverser&);
-    TMap<TString, int>& idMap;
+    TIdMaps& idMaps;
     int maxId;
 };
 
@@ -344,31 +357,33 @@
 // on having no bodies for the copy-constructor/operator=.)
 class TUserIdTraverser : public TIntermTraverser {
 public:
-    TUserIdTraverser(TMap<TString, int>& idMap) : idMap(idMap) { }
+    TUserIdTraverser(TIdMaps& idMaps) : idMaps(idMaps) { }
     // If its a non-built-in global, add it to the map.
     virtual void visitSymbol(TIntermSymbol* symbol)
     {
         const TQualifier& qualifier = symbol->getType().getQualifier();
-        if (qualifier.builtIn == EbvNone)
-            idMap[symbol->getName()] = symbol->getId();
+        if (qualifier.builtIn == EbvNone) {
+            TShaderInterface si = symbol->getType().getShaderInterface();
+            idMaps[si][getNameForIdMap(symbol)] = symbol->getId();
+        }
     }
 
 protected:
     TUserIdTraverser(TUserIdTraverser&);
     TUserIdTraverser& operator=(TUserIdTraverser&);
-    TMap<TString, int>& idMap; // over biggest id
+    TIdMaps& idMaps; // over biggest id
 };
 
 // Initialize the the ID map with what we know of 'this' AST.
-void TIntermediate::seedIdMap(TMap<TString, int>& idMap, int& maxId)
+void TIntermediate::seedIdMap(TIdMaps& idMaps, int& maxId)
 {
     // all built-ins everywhere need to align on IDs and contribute to the max ID
-    TBuiltInIdTraverser builtInIdTraverser(idMap);
+    TBuiltInIdTraverser builtInIdTraverser(idMaps);
     treeRoot->traverse(&builtInIdTraverser);
     maxId = builtInIdTraverser.getMaxId();
 
     // user variables in the linker object list need to align on ids
-    TUserIdTraverser userIdTraverser(idMap);
+    TUserIdTraverser userIdTraverser(idMaps);
     findLinkerObjects()->traverse(&userIdTraverser);
 }
 
@@ -377,7 +392,7 @@
 // on having no bodies for the copy-constructor/operator=.)
 class TRemapIdTraverser : public TIntermTraverser {
 public:
-    TRemapIdTraverser(const TMap<TString, int>& idMap, int idShift) : idMap(idMap), idShift(idShift) { }
+    TRemapIdTraverser(const TIdMaps& idMaps, int idShift) : idMaps(idMaps), idShift(idShift) { }
     // Do the mapping:
     //  - if the same symbol, adopt the 'this' ID
     //  - otherwise, ensure a unique ID by shifting to a new space
@@ -386,8 +401,9 @@
         const TQualifier& qualifier = symbol->getType().getQualifier();
         bool remapped = false;
         if (qualifier.isLinkable() || qualifier.builtIn != EbvNone) {
-            auto it = idMap.find(symbol->getName());
-            if (it != idMap.end()) {
+            TShaderInterface si = symbol->getType().getShaderInterface();
+            auto it = idMaps[si].find(getNameForIdMap(symbol));
+            if (it != idMaps[si].end()) {
                 symbol->changeId(it->second);
                 remapped = true;
             }
@@ -398,14 +414,14 @@
 protected:
     TRemapIdTraverser(TRemapIdTraverser&);
     TRemapIdTraverser& operator=(TRemapIdTraverser&);
-    const TMap<TString, int>& idMap;
+    const TIdMaps& idMaps;
     int idShift;
 };
 
-void TIntermediate::remapIds(const TMap<TString, int>& idMap, int idShift, TIntermediate& unit)
+void TIntermediate::remapIds(const TIdMaps& idMaps, int idShift, TIntermediate& unit)
 {
     // Remap all IDs to either share or be unique, as dictated by the idMap and idShift.
-    TRemapIdTraverser idTraverser(idMap, idShift);
+    TRemapIdTraverser idTraverser(idMaps, idShift);
     unit.getTreeRoot()->traverse(&idTraverser);
 }
 
@@ -447,7 +463,19 @@
             TIntermSymbol* symbol = linkerObjects[linkObj]->getAsSymbolNode();
             TIntermSymbol* unitSymbol = unitLinkerObjects[unitLinkObj]->getAsSymbolNode();
             assert(symbol && unitSymbol);
-            if (symbol->getName() == unitSymbol->getName()) {
+
+            bool isSameSymbol = false;
+            // If they are both blocks in the same shader interface,
+            // match by the block-name, not the identifier name.
+            if (symbol->getType().getBasicType() == EbtBlock && unitSymbol->getType().getBasicType() == EbtBlock) {
+                if (symbol->getType().getShaderInterface() == unitSymbol->getType().getShaderInterface()) {
+                    isSameSymbol = symbol->getType().getTypeName() == unitSymbol->getType().getTypeName();
+                }
+            }
+            else if (symbol->getName() == unitSymbol->getName())
+                isSameSymbol = true;
+
+            if (isSameSymbol) {
                 // filter out copy
                 merge = false;
 
@@ -527,6 +555,22 @@
         writeTypeComparison = true;
     }
 
+    // Uniform and buffer blocks must either both have an instance name, or
+    // must both be anonymous. The names don't need to match though.
+    if (symbol.getQualifier().isUniformOrBuffer() &&
+        (IsAnonymous(symbol.getName()) != IsAnonymous(unitSymbol.getName()))) {
+        error(infoSink, "Matched Uniform or Storage blocks must all be anonymous,"
+                        " or all be named:");
+        writeTypeComparison = true;
+    }
+
+    if (symbol.getQualifier().storage == unitSymbol.getQualifier().storage &&
+        (IsAnonymous(symbol.getName()) != IsAnonymous(unitSymbol.getName()) ||
+         (!IsAnonymous(symbol.getName()) && symbol.getName() != unitSymbol.getName()))) {
+        warn(infoSink, "Matched shader interfaces are using different instance names.");
+        writeTypeComparison = true;
+    }
+
     // Precision...
     if (symbol.getQualifier().precision != unitSymbol.getQualifier().precision) {
         error(infoSink, "Precision qualifiers must match:");
@@ -562,6 +606,7 @@
         symbol.getQualifier().queuefamilycoherent  != unitSymbol.getQualifier().queuefamilycoherent ||
         symbol.getQualifier().workgroupcoherent != unitSymbol.getQualifier().workgroupcoherent ||
         symbol.getQualifier().subgroupcoherent  != unitSymbol.getQualifier().subgroupcoherent ||
+        symbol.getQualifier().shadercallcoherent!= unitSymbol.getQualifier().shadercallcoherent ||
         symbol.getQualifier().nonprivate        != unitSymbol.getQualifier().nonprivate ||
         symbol.getQualifier().volatil           != unitSymbol.getQualifier().volatil ||
         symbol.getQualifier().restrict          != unitSymbol.getQualifier().restrict ||
@@ -596,9 +641,13 @@
         }
     }
 
-    if (writeTypeComparison)
-        infoSink.info << "    " << symbol.getName() << ": \"" << symbol.getType().getCompleteString() << "\" versus \"" <<
-                                                             unitSymbol.getType().getCompleteString() << "\"\n";
+    if (writeTypeComparison) {
+        infoSink.info << "    " << symbol.getName() << ": \"" << symbol.getType().getCompleteString() << "\" versus ";
+        if (symbol.getName() != unitSymbol.getName())
+            infoSink.info << unitSymbol.getName() << ": ";
+
+        infoSink.info << "\"" << unitSymbol.getType().getCompleteString() << "\"\n";
+    }
 #endif
 }
 
@@ -728,13 +777,13 @@
         break;
     case EShLangCompute:
         break;
-    case EShLangRayGenNV:
-    case EShLangIntersectNV:
-    case EShLangAnyHitNV:
-    case EShLangClosestHitNV:
-    case EShLangMissNV:
-    case EShLangCallableNV:
-        if (numShaderRecordNVBlocks > 1)
+    case EShLangRayGen:
+    case EShLangIntersect:
+    case EShLangAnyHit:
+    case EShLangClosestHit:
+    case EShLangMiss:
+    case EShLangCallable:
+        if (numShaderRecordBlocks > 1)
             error(infoSink, "Only one shaderRecordNV buffer block is allowed per stage");
         break;
     case EShLangMeshNV:
diff --git a/third_party/glslang/src/glslang/MachineIndependent/localintermediate.h b/third_party/glslang/src/glslang/MachineIndependent/localintermediate.h
index 683290a..66f5a88 100644
--- a/third_party/glslang/src/glslang/MachineIndependent/localintermediate.h
+++ b/third_party/glslang/src/glslang/MachineIndependent/localintermediate.h
@@ -162,7 +162,10 @@
 #endif
 
 // Track a set of strings describing how the module was processed.
-// Using the form:
+// This includes command line options, transforms, etc., ideally inclusive enough
+// to reproduce the steps used to transform the input source to the output.
+// E.g., see SPIR-V OpModuleProcessed.
+// Each "process" or "transform" uses is expressed in the form:
 //   process arg0 arg1 arg2 ...
 //   process arg0 arg1 arg2 ...
 // where everything is textual, and there can be zero or more arguments
@@ -222,6 +225,15 @@
     LayoutDerivativeGroupLinear,  // derivative_group_linearNV
 };
 
+class TIdMaps {
+public:
+    TMap<TString, int>& operator[](int i) { return maps[i]; }
+    const TMap<TString, int>& operator[](int i) const { return maps[i]; }
+private:
+    TMap<TString, int> maps[EsiCount];
+};
+
+
 //
 // Set of helper functions to help parse and build the tree.
 //
@@ -244,12 +256,12 @@
         inputPrimitive(ElgNone), outputPrimitive(ElgNone),
         pixelCenterInteger(false), originUpperLeft(false),
         vertexSpacing(EvsNone), vertexOrder(EvoNone), interlockOrdering(EioNone), pointMode(false), earlyFragmentTests(false),
-        postDepthCoverage(false), depthLayout(EldNone), 
+        postDepthCoverage(false), depthLayout(EldNone),
         hlslFunctionality1(false),
         blendEquations(0), xfbMode(false), multiStream(false),
         layoutOverrideCoverage(false),
         geoPassthroughEXT(false),
-        numShaderRecordNVBlocks(0),
+        numShaderRecordBlocks(0),
         computeDerivativeMode(LayoutDerivativeNone),
         primitives(TQualifier::layoutNotSet),
         numTaskNVBlocks(0),
@@ -503,7 +515,7 @@
     bool getAutoMapBindings() const { return false; }
     bool getAutoMapLocations() const { return false; }
     int getNumPushConstants() const { return 0; }
-    void addShaderRecordNVCount() { }
+    void addShaderRecordCount() { }
     void addTaskNVCount() { }
     void setUseVulkanMemoryModel() { }
     bool usingVulkanMemoryModel() const { return false; }
@@ -583,7 +595,7 @@
             processes.addProcess("flatten-uniform-arrays");
     }
     bool getFlattenUniformArrays() const { return flattenUniformArrays; }
-#endif 
+#endif
     void setNoStorageFormat(bool b)
     {
         useUnknownFormat = b;
@@ -620,7 +632,7 @@
 
     void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { textureSamplerTransformMode = mode; }
     int getNumPushConstants() const { return numPushConstants; }
-    void addShaderRecordNVCount() { ++numShaderRecordNVBlocks; }
+    void addShaderRecordCount() { ++numShaderRecordBlocks; }
     void addTaskNVCount() { ++numTaskNVBlocks; }
 
     bool setInvocations(int i)
@@ -859,8 +871,8 @@
     void mergeCallGraphs(TInfoSink&, TIntermediate&);
     void mergeModes(TInfoSink&, TIntermediate&);
     void mergeTrees(TInfoSink&, TIntermediate&);
-    void seedIdMap(TMap<TString, int>& idMap, int& maxId);
-    void remapIds(const TMap<TString, int>& idMap, int idShift, TIntermediate&);
+    void seedIdMap(TIdMaps& idMaps, int& maxId);
+    void remapIds(const TIdMaps& idMaps, int idShift, TIntermediate&);
     void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals);
     void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects);
     void mergeImplicitArraySizes(TType&, const TType&);
@@ -945,7 +957,7 @@
     bool multiStream;
     bool layoutOverrideCoverage;
     bool geoPassthroughEXT;
-    int numShaderRecordNVBlocks;
+    int numShaderRecordBlocks;
     ComputeDerivativeMode computeDerivativeMode;
     int primitives;
     int numTaskNVBlocks;
diff --git a/third_party/glslang/src/glslang/MachineIndependent/parseConst.cpp b/third_party/glslang/src/glslang/MachineIndependent/parseConst.cpp
index 1a8e6d9..7c04743 100644
--- a/third_party/glslang/src/glslang/MachineIndependent/parseConst.cpp
+++ b/third_party/glslang/src/glslang/MachineIndependent/parseConst.cpp
@@ -165,17 +165,27 @@
                     }
                 }
             } else {
-                // matrix from vector
+                // matrix from vector or scalar
                 int count = 0;
                 const int startIndex = index;
                 int nodeComps = node->getType().computeNumComponents();
                 for (int i = startIndex; i < endIndex; i++) {
                     if (i >= instanceSize)
                         return;
-                    if (i == startIndex || (i - startIndex) % (matrixRows + 1) == 0 )
+                    if (nodeComps == 1) {
+                        // If there is a single scalar parameter to a matrix
+                        // constructor, it is used to initialize all the
+                        // components on the matrix's diagonal, with the
+                        // remaining components initialized to 0.0.
+                        if (i == startIndex || (i - startIndex) % (matrixRows + 1) == 0 )
+                            leftUnionArray[i] = rightUnionArray[count];
+                        else
+                            leftUnionArray[i].setDConst(0.0);
+                    } else {
+                        // construct the matrix in column-major order, from
+                        // the components provided, in order
                         leftUnionArray[i] = rightUnionArray[count];
-                    else
-                        leftUnionArray[i].setDConst(0.0);
+                    }
 
                     index++;
 
diff --git a/third_party/glslang/src/glslang/MachineIndependent/propagateNoContraction.cpp b/third_party/glslang/src/glslang/MachineIndependent/propagateNoContraction.cpp
index 83a3230..9def592 100644
--- a/third_party/glslang/src/glslang/MachineIndependent/propagateNoContraction.cpp
+++ b/third_party/glslang/src/glslang/MachineIndependent/propagateNoContraction.cpp
@@ -867,4 +867,4 @@
 }
 };
 
-#endif // GLSLANG_WEB
\ No newline at end of file
+#endif // GLSLANG_WEB
diff --git a/third_party/glslang/src/glslang/MachineIndependent/reflection.cpp b/third_party/glslang/src/glslang/MachineIndependent/reflection.cpp
index b093671..2876933 100644
--- a/third_party/glslang/src/glslang/MachineIndependent/reflection.cpp
+++ b/third_party/glslang/src/glslang/MachineIndependent/reflection.cpp
@@ -1188,7 +1188,7 @@
 
         for (int dim=0; dim<3; ++dim)
             if (getLocalSize(dim) > 1)
-                printf("Local size %s: %d\n", axis[dim], getLocalSize(dim));
+                printf("Local size %s: %u\n", axis[dim], getLocalSize(dim));
 
         printf("\n");
     }
diff --git a/third_party/glslang/src/glslang/MachineIndependent/reflection.h b/third_party/glslang/src/glslang/MachineIndependent/reflection.h
index efdc893..0c33de4 100644
--- a/third_party/glslang/src/glslang/MachineIndependent/reflection.h
+++ b/third_party/glslang/src/glslang/MachineIndependent/reflection.h
@@ -220,4 +220,4 @@
 
 #endif // _REFLECTION_INCLUDED
 
-#endif // GLSLANG_WEB
\ No newline at end of file
+#endif // GLSLANG_WEB
diff --git a/third_party/glslang/src/glslang/OSDependent/Web/CMakeLists.txt b/third_party/glslang/src/glslang/OSDependent/Web/CMakeLists.txt
index 015d6d7..697b0b7 100644
--- a/third_party/glslang/src/glslang/OSDependent/Web/CMakeLists.txt
+++ b/third_party/glslang/src/glslang/OSDependent/Web/CMakeLists.txt
@@ -3,27 +3,31 @@
     glslang_set_link_args(glslang.js)
     target_link_libraries(glslang.js glslang SPIRV)
 
+    # Link library names that start with "-" are treated as link flags.
+    # "-Os" should be OK in MSVC; don't use /Os because CMake won't
+    # treat it as a link flag.
+    target_link_libraries(glslang.js "-Os")
+
     if(EMSCRIPTEN)
         set_target_properties(glslang.js PROPERTIES
             OUTPUT_NAME "glslang"
             SUFFIX ".js")
         em_link_pre_js(glslang.js "${CMAKE_CURRENT_SOURCE_DIR}/glslang.pre.js")
 
-        target_link_options(glslang.js PRIVATE "SHELL: -Os")
-        target_link_options(glslang.js PRIVATE "SHELL: --llvm-lto 1")
-        target_link_options(glslang.js PRIVATE "SHELL: --closure 1")
-        target_link_options(glslang.js PRIVATE "SHELL: -s MODULARIZE=1")
-        target_link_options(glslang.js PRIVATE "SHELL: -s ALLOW_MEMORY_GROWTH=1")
-        target_link_options(glslang.js PRIVATE "SHELL: -s FILESYSTEM=0")
+        target_link_libraries(glslang.js "--llvm-lto 1")
+        target_link_libraries(glslang.js "--closure 1")
+        target_link_libraries(glslang.js "-s MODULARIZE=1")
+        target_link_libraries(glslang.js "-s ALLOW_MEMORY_GROWTH=1")
+        target_link_libraries(glslang.js "-s FILESYSTEM=0")
 
         if(ENABLE_EMSCRIPTEN_SINGLE_FILE)
-            target_link_options(glslang.js PRIVATE "SHELL: -s SINGLE_FILE=1")
+            target_link_libraries(glslang.js "-s SINGLE_FILE=1")
         endif(ENABLE_EMSCRIPTEN_SINGLE_FILE)
 
         if(ENABLE_EMSCRIPTEN_ENVIRONMENT_NODE)
-            target_link_options(glslang.js PRIVATE "SHELL: -s ENVIRONMENT=node -s BINARYEN_ASYNC_COMPILATION=0")
+            target_link_libraries(glslang.js "-s ENVIRONMENT=node -s BINARYEN_ASYNC_COMPILATION=0")
         else()
-            target_link_options(glslang.js PRIVATE "SHELL: -s ENVIRONMENT=web,worker")
+            target_link_libraries(glslang.js "-s ENVIRONMENT=web,worker")
         endif()
 
         if(NOT ENABLE_EMSCRIPTEN_ENVIRONMENT_NODE)
diff --git a/third_party/glslang/src/glslang/Public/ShaderLang.h b/third_party/glslang/src/glslang/Public/ShaderLang.h
index 7cfa57b..acb2a07 100755
--- a/third_party/glslang/src/glslang/Public/ShaderLang.h
+++ b/third_party/glslang/src/glslang/Public/ShaderLang.h
@@ -92,12 +92,18 @@
     EShLangGeometry,
     EShLangFragment,
     EShLangCompute,
-    EShLangRayGenNV,
-    EShLangIntersectNV,
-    EShLangAnyHitNV,
-    EShLangClosestHitNV,
-    EShLangMissNV,
-    EShLangCallableNV,
+    EShLangRayGen,
+    EShLangRayGenNV = EShLangRayGen,
+    EShLangIntersect,
+    EShLangIntersectNV = EShLangIntersect,
+    EShLangAnyHit,
+    EShLangAnyHitNV = EShLangAnyHit,
+    EShLangClosestHit,
+    EShLangClosestHitNV = EShLangClosestHit,
+    EShLangMiss,
+    EShLangMissNV = EShLangMiss,
+    EShLangCallable,
+    EShLangCallableNV = EShLangCallable,
     EShLangTaskNV,
     EShLangMeshNV,
     LAST_ELEMENT_MARKER(EShLangCount),
@@ -110,12 +116,18 @@
     EShLangGeometryMask       = (1 << EShLangGeometry),
     EShLangFragmentMask       = (1 << EShLangFragment),
     EShLangComputeMask        = (1 << EShLangCompute),
-    EShLangRayGenNVMask       = (1 << EShLangRayGenNV),
-    EShLangIntersectNVMask    = (1 << EShLangIntersectNV),
-    EShLangAnyHitNVMask       = (1 << EShLangAnyHitNV),
-    EShLangClosestHitNVMask   = (1 << EShLangClosestHitNV),
-    EShLangMissNVMask         = (1 << EShLangMissNV),
-    EShLangCallableNVMask     = (1 << EShLangCallableNV),
+    EShLangRayGenMask         = (1 << EShLangRayGen),
+    EShLangRayGenNVMask       = EShLangRayGenMask,
+    EShLangIntersectMask      = (1 << EShLangIntersect),
+    EShLangIntersectNVMask    = EShLangIntersectMask,
+    EShLangAnyHitMask         = (1 << EShLangAnyHit),
+    EShLangAnyHitNVMask       = EShLangAnyHitMask,
+    EShLangClosestHitMask     = (1 << EShLangClosestHit),
+    EShLangClosestHitNVMask   = EShLangClosestHitMask,
+    EShLangMissMask           = (1 << EShLangMiss),
+    EShLangMissNVMask         = EShLangMissMask,
+    EShLangCallableMask       = (1 << EShLangCallable),
+    EShLangCallableNVMask     = EShLangCallableMask,
     EShLangTaskNVMask         = (1 << EShLangTaskNV),
     EShLangMeshNVMask         = (1 << EShLangMeshNV),
     LAST_ELEMENT_MARKER(EShLanguageMaskCount),
@@ -405,6 +417,8 @@
 //  - optionally call setEnv*(), see below for more detail
 //  - optionally use setPreamble() to set a special shader string that will be
 //    processed before all others but won't affect the validity of #version
+//  - optionally call addProcesses() for each setting/transform,
+//    see comment for class TProcesses
 //  - call parse(): source language and target environment must be selected
 //    either by correct setting of EShMessages sent to parse(), or by
 //    explicitly calling setEnv*()
@@ -639,11 +653,11 @@
     // stringNames is the optional names for all the strings. If stringNames
     // is null, then none of the strings has name. If a certain element in
     // stringNames is null, then the corresponding string does not have name.
-    const char* const* strings;
+    const char* const* strings;      // explicit code to compile, see previous comment
     const int* lengths;
     const char* const* stringNames;
-    const char* preamble;
-    int numStrings;
+    int numStrings;                  // size of the above arrays
+    const char* preamble;            // string of implicit code to compile before the explicitly provided code
 
     // a function in the source string can be renamed FROM this TO the name given in setEntryPoint.
     std::string sourceEntryPointName;
diff --git a/third_party/glslang/src/gtests/Link.FromFile.Vk.cpp b/third_party/glslang/src/gtests/Link.FromFile.Vk.cpp
old mode 100644
new mode 100755
index a032f11..a43edcf
--- a/third_party/glslang/src/gtests/Link.FromFile.Vk.cpp
+++ b/third_party/glslang/src/gtests/Link.FromFile.Vk.cpp
@@ -115,6 +115,10 @@
 			"link.vk.differentPC.0.2.frag"},
 		{"link.vk.differentPC.1.0.frag", "link.vk.differentPC.1.1.frag",
 			"link.vk.differentPC.1.2.frag"},
+        {"link.vk.pcNamingValid.0.0.vert", "link.vk.pcNamingValid.0.1.vert"},
+        {"link.vk.pcNamingInvalid.0.0.vert", "link.vk.pcNamingInvalid.0.1.vert"},
+        {"link.vk.multiBlocksValid.0.0.vert", "link.vk.multiBlocksValid.0.1.vert"},
+        {"link.vk.multiBlocksValid.1.0.geom", "link.vk.multiBlocksValid.1.1.geom"},
     }))
 );
 // clang-format on
diff --git a/third_party/glslang/src/gtests/Link.FromFile.cpp b/third_party/glslang/src/gtests/Link.FromFile.cpp
old mode 100644
new mode 100755
index abc33a9..dc9bb76
--- a/third_party/glslang/src/gtests/Link.FromFile.cpp
+++ b/third_party/glslang/src/gtests/Link.FromFile.cpp
@@ -100,7 +100,11 @@
         {"150.tesc", "150.tese", "400.tesc", "400.tese", "410.tesc", "420.tesc", "420.tese"},
         {"max_vertices_0.geom"},
         {"es-link1.frag", "es-link2.frag"},
-        {"missingBodies.vert"}
+        {"missingBodies.vert"},
+        {"link.multiAnonBlocksInvalid.0.0.vert", "link.multiAnonBlocksInvalid.0.1.vert"},
+        {"link.multiAnonBlocksValid.0.0.vert", "link.multiAnonBlocksValid.0.1.vert"},
+        {"link.multiBlocksInvalid.0.0.vert", "link.multiBlocksInvalid.0.1.vert"},
+        {"link.multiBlocksValid.1.0.vert", "link.multiBlocksValid.1.1.vert"},
     }))
 );
 // clang-format on
diff --git a/third_party/glslang/src/gtests/Spv.FromFile.cpp b/third_party/glslang/src/gtests/Spv.FromFile.cpp
index 244fa1e..1d061fb 100644
--- a/third_party/glslang/src/gtests/Spv.FromFile.cpp
+++ b/third_party/glslang/src/gtests/Spv.FromFile.cpp
@@ -105,6 +105,7 @@
                             "/baseResults/", false, true);
 }
 
+
 TEST_P(CompileVulkan1_1ToSpirvTest, FromFile)
 {
     loadFileCompileAndCheck(GlobalTestSettings.testRoot, GetParam(),
@@ -229,6 +230,14 @@
         "spv.while-continue-break.vert",
         "spv.while-simple.vert",
         // vulkan-specific tests
+        "rayQuery.rgen",
+        "rayQuery-no-cse.rgen",
+        "rayQuery-initialize.rgen",
+        "rayQuery-allOps.rgen",
+        "rayQuery-allOps.Error.rgen",
+        "rayQuery-committed.Error.rgen",
+        "rayQuery-allOps.comp",
+        "rayQuery-allOps.frag",
         "spv.set.vert",
         "spv.double.comp",
         "spv.100ops.frag",
@@ -271,6 +280,7 @@
         "spv.always-discard2.frag",
         "spv.arbPostDepthCoverage.frag",
         "spv.arbPostDepthCoverage_Error.frag",
+        "spv.atomicCounter.comp",
         "spv.bitCast.frag",
         "spv.bool.vert",
         "spv.boolInBlock.frag",
@@ -319,6 +329,20 @@
         "spv.earlyReturnDiscard.frag",
         "spv.extPostDepthCoverage.frag",
         "spv.extPostDepthCoverage_Error.frag",
+        "spv.ext.AnyHitShader.rahit",
+        "spv.ext.AnyHitShader_Errors.rahit",
+        "spv.ext.ClosestHitShader.rchit",
+        "spv.ext.ClosestHitShader_Errors.rchit",
+        "spv.ext.IntersectShader.rint",
+        "spv.ext.IntersectShader_Errors.rint",
+        "spv.ext.MissShader.rmiss",
+        "spv.ext.MissShader_Errors.rmiss",
+        "spv.ext.RayCallable.rcall",
+        "spv.ext.RayCallable_Errors.rcall",
+        "spv.ext.RayConstants.rgen",
+        "spv.ext.RayGenShader.rgen",
+        "spv.ext.RayGenShader11.rgen",
+        "spv.ext.RayGenShaderArray.rgen",
         "spv.float16convertonlyarith.comp",
         "spv.float16convertonlystorage.comp",
         "spv.flowControl.frag",
@@ -574,6 +598,7 @@
         "spv.glFragColor.frag",
         "spv.rankShift.comp",
         "spv.specConst.vert",
+        "spv.specTexture.frag",
         "spv.OVR_multiview.vert",
         "spv.xfbOffsetOnBlockMembersAssignment.vert",
         "spv.xfbOffsetOnStructMembersAssignment.vert",
diff --git a/third_party/glslang/src/gtests/TestFixture.cpp b/third_party/glslang/src/gtests/TestFixture.cpp
index baf4d16..ced6fcc 100644
--- a/third_party/glslang/src/gtests/TestFixture.cpp
+++ b/third_party/glslang/src/gtests/TestFixture.cpp
@@ -61,17 +61,17 @@
     } else if (stage == "comp") {
         return EShLangCompute;
     } else if (stage == "rgen") {
-        return EShLangRayGenNV;
+        return EShLangRayGen;
     } else if (stage == "rint") {
-        return EShLangIntersectNV;
+        return EShLangIntersect;
     } else if (stage == "rahit") {
-        return EShLangAnyHitNV;
+        return EShLangAnyHit;
     } else if (stage == "rchit") {
-        return EShLangClosestHitNV;
+        return EShLangClosestHit;
     } else if (stage == "rmiss") {
-        return EShLangMissNV;
+        return EShLangMiss;
     } else if (stage == "rcall") {
-        return EShLangCallableNV;
+        return EShLangCallable;
     } else if (stage == "task") {
         return EShLangTaskNV;
     } else if (stage == "mesh") {
diff --git a/third_party/glslang/src/hlsl/hlslParseHelper.cpp b/third_party/glslang/src/hlsl/hlslParseHelper.cpp
index 557d4ae..2dc173f 100755
--- a/third_party/glslang/src/hlsl/hlslParseHelper.cpp
+++ b/third_party/glslang/src/hlsl/hlslParseHelper.cpp
@@ -757,9 +757,6 @@
     // indexStructBufferContent returns nullptr if it isn't a structuredbuffer (SSBO).
     TIntermTyped* sbArray = indexStructBufferContent(loc, base);
     if (sbArray != nullptr) {
-        if (sbArray == nullptr)
-            return nullptr;
-
         // Now we'll apply the [] index to that array
         const TOperator idxOp = (index->getQualifier().storage == EvqConst) ? EOpIndexDirect : EOpIndexIndirect;
 
diff --git a/third_party/glslang/src/known_good.json b/third_party/glslang/src/known_good.json
index 1f108db..9cc8c44 100644
--- a/third_party/glslang/src/known_good.json
+++ b/third_party/glslang/src/known_good.json
@@ -5,14 +5,14 @@
       "site" : "github",
       "subrepo" : "KhronosGroup/SPIRV-Tools",
       "subdir" : "External/spirv-tools",
-      "commit" : "dd3d91691f1e1dc4c0f42818756cf5e165c8918c"
+      "commit" : "fd8e130510a6b002b28eee5885a9505040a9bdc9"
     },
     {
       "name" : "spirv-tools/external/spirv-headers",
       "site" : "github",
       "subrepo" : "KhronosGroup/SPIRV-Headers",
       "subdir" : "External/spirv-tools/external/spirv-headers",
-      "commit" : "204cd131c42b90d129073719f2766293ce35c081"
+      "commit" : "f8bf11a0253a32375c32cad92c841237b96696c0"
     }
   ]
 }
diff --git a/third_party/spirv-tools/src/CHANGES b/third_party/spirv-tools/src/CHANGES
index 48c93a4..fe6641e 100644
--- a/third_party/spirv-tools/src/CHANGES
+++ b/third_party/spirv-tools/src/CHANGES
@@ -1,7 +1,34 @@
 Revision history for SPIRV-Tools
 
-v2020.2-dev 2020-02-03
- - Start v2020.2-dev
+v2020.3-dev 2020-03-26
+ - Start v2020.3-dev
+
+v2020.2 2020-03-26
+ - General:
+   - Support extended instructions in the vscode language server
+   - Make spvOpcodeString part of the public API (#3174)
+   - Added guide to writing a spirv-fuzz fuzzer pass (#3190)
+   - Add support for KHR_ray_{query,tracing} extensions (#3235)
+ - Optimizer
+   - Debug Printf support (#3215)
+   - Add data structure for DebugScope, DebugDeclare in spirv-opt (#3183)
+   - Fix identification of Vulkan images and buffers (#3253)
+ - Validator
+   - Add support for SPV_AMD_shader_image_load_store_lod (#3186)
+   - Add validation rules for OpenCL.DebugInfo.100 extension (#3133)
+   - Adding WebGPU specific Workgroup scope rule (#3204)
+   - Disallow phis of images, samplers and sampled images (#3246)
+ - Reduce
+ - Fuzz
+   - Fuzzer passes to add local and global variables (#3175)
+   - Add fuzzer passes to add loads/stores (#3176)
+   - Fuzzer pass to add function calls (#3178)
+   - Fuzzer pass that adds access chains (#3182)
+   - Fuzzer pass to add equation instructions (#3202)
+   - Add swap commutable operands transformation (#3205)
+   - Add fuzzer pass to permute function parameters (#3212)
+   - Allow OpPhi operand to be replaced with a composite synonym (#3221)
+ - Linker
 
 v2020.1 2020-02-03
  - General:
diff --git a/third_party/spirv-tools/src/CMakeLists.txt b/third_party/spirv-tools/src/CMakeLists.txt
index ef9ad11..9d0eb8b 100644
--- a/third_party/spirv-tools/src/CMakeLists.txt
+++ b/third_party/spirv-tools/src/CMakeLists.txt
@@ -249,7 +249,7 @@
 
 # Precompiled header macro. Parameters are source file list and filename for pch cpp file.
 macro(spvtools_pch SRCS PCHPREFIX)
-  if(MSVC AND CMAKE_GENERATOR MATCHES "^Visual Studio")
+  if(MSVC AND CMAKE_GENERATOR MATCHES "^Visual Studio" AND NOT "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
     set(PCH_NAME "$(IntDir)\\${PCHPREFIX}.pch")
     # make source files use/depend on PCH_NAME
     set_source_files_properties(${${SRCS}} PROPERTIES COMPILE_FLAGS "/Yu${PCHPREFIX}.h /FI${PCHPREFIX}.h /Fp${PCH_NAME} /Zm300" OBJECT_DEPENDS "${PCH_NAME}")
diff --git a/third_party/spirv-tools/src/examples/cpp-interface/CMakeLists.txt b/third_party/spirv-tools/src/examples/cpp-interface/CMakeLists.txt
index d050b07..7887ee7 100644
--- a/third_party/spirv-tools/src/examples/cpp-interface/CMakeLists.txt
+++ b/third_party/spirv-tools/src/examples/cpp-interface/CMakeLists.txt
@@ -16,4 +16,4 @@
   TARGET spirv-tools-cpp-example
   SRCS main.cpp
   LIBS SPIRV-Tools-opt
-)
\ No newline at end of file
+)
diff --git a/third_party/spirv-tools/src/external/CMakeLists.txt b/third_party/spirv-tools/src/external/CMakeLists.txt
index 8bde13c..3c7b403 100644
--- a/third_party/spirv-tools/src/external/CMakeLists.txt
+++ b/third_party/spirv-tools/src/external/CMakeLists.txt
@@ -25,7 +25,17 @@
 endif()
 
 if (IS_DIRECTORY ${SPIRV_HEADER_DIR})
+  # TODO(dneto): We should not be modifying the parent scope.
   set(SPIRV_HEADER_INCLUDE_DIR ${SPIRV_HEADER_DIR}/include PARENT_SCOPE)
+
+  # Add SPIRV-Headers as a sub-project if it isn't already defined.
+  # Do this so enclosing projects can use SPIRV-Headers_SOURCE_DIR to find
+  # headers to include.
+  if (NOT DEFINED SPIRV-Headers_SOURCE_DIR)
+    set(SPIRV_HEADERS_SKIP_INSTALL ON)
+    set(SPIRV_HEADERS_SKIP_EXAMPLES ON)
+    add_subdirectory(${SPIRV_HEADER_DIR})
+  endif()
 else()
   message(FATAL_ERROR
     "SPIRV-Headers was not found - please checkout a copy under external/.")
diff --git a/third_party/spirv-tools/src/source/fuzz/CMakeLists.txt b/third_party/spirv-tools/src/source/fuzz/CMakeLists.txt
index 3a9d604..ce6d3a6 100644
--- a/third_party/spirv-tools/src/source/fuzz/CMakeLists.txt
+++ b/third_party/spirv-tools/src/source/fuzz/CMakeLists.txt
@@ -79,6 +79,7 @@
         transformation_access_chain.h
         transformation_add_constant_boolean.h
         transformation_add_constant_composite.h
+        transformation_add_constant_null.h
         transformation_add_constant_scalar.h
         transformation_add_dead_block.h
         transformation_add_dead_break.h
@@ -99,6 +100,8 @@
         transformation_add_type_vector.h
         transformation_composite_construct.h
         transformation_composite_extract.h
+        transformation_compute_data_synonym_fact_closure.h
+        transformation_context.h
         transformation_copy_object.h
         transformation_equation_instruction.h
         transformation_function_call.h
@@ -170,6 +173,7 @@
         transformation_access_chain.cpp
         transformation_add_constant_boolean.cpp
         transformation_add_constant_composite.cpp
+        transformation_add_constant_null.cpp
         transformation_add_constant_scalar.cpp
         transformation_add_dead_block.cpp
         transformation_add_dead_break.cpp
@@ -190,6 +194,8 @@
         transformation_add_type_vector.cpp
         transformation_composite_construct.cpp
         transformation_composite_extract.cpp
+        transformation_compute_data_synonym_fact_closure.cpp
+        transformation_context.cpp
         transformation_copy_object.cpp
         transformation_equation_instruction.cpp
         transformation_function_call.cpp
diff --git a/third_party/spirv-tools/src/source/fuzz/equivalence_relation.h b/third_party/spirv-tools/src/source/fuzz/equivalence_relation.h
index 7bb8b66..6d0b63e 100644
--- a/third_party/spirv-tools/src/source/fuzz/equivalence_relation.h
+++ b/third_party/spirv-tools/src/source/fuzz/equivalence_relation.h
@@ -68,17 +68,14 @@
 template <typename T, typename PointerHashT, typename PointerEqualsT>
 class EquivalenceRelation {
  public:
-  // Merges the equivalence classes associated with |value1| and |value2|.
-  // If any of these values was not previously in the equivalence relation, it
-  // is added to the pool of values known to be in the relation.
+  // Requires that |value1| and |value2| are already registered in the
+  // equivalence relation.  Merges the equivalence classes associated with
+  // |value1| and |value2|.
   void MakeEquivalent(const T& value1, const T& value2) {
-    // Register each value if necessary.
-    for (auto value : {value1, value2}) {
-      if (!Exists(value)) {
-        // Register the value in the equivalence relation.
-        Register(value);
-      }
-    }
+    assert(Exists(value1) &&
+           "Precondition: value1 must already be registered.");
+    assert(Exists(value2) &&
+           "Precondition: value2 must already be registered.");
 
     // Look up canonical pointers to each of the values in the value pool.
     const T* value1_ptr = *value_set_.find(&value1);
@@ -105,7 +102,7 @@
   // Requires that |value| is not known to the equivalence relation. Registers
   // it in its own equivalence class and returns a pointer to the equivalence
   // class representative.
-  const T* Register(T& value) {
+  const T* Register(const T& value) {
     assert(!Exists(value));
 
     // This relies on T having a copy constructor.
diff --git a/third_party/spirv-tools/src/source/fuzz/fact_manager.cpp b/third_party/spirv-tools/src/source/fuzz/fact_manager.cpp
index 31d3b94..2cfe326 100644
--- a/third_party/spirv-tools/src/source/fuzz/fact_manager.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/fact_manager.cpp
@@ -416,17 +416,18 @@
 
   // See method in FactManager which delegates to this method.
   std::vector<const protobufs::DataDescriptor*> GetSynonymsForDataDescriptor(
-      const protobufs::DataDescriptor& data_descriptor,
-      opt::IRContext* context) const;
+      const protobufs::DataDescriptor& data_descriptor) const;
 
   // See method in FactManager which delegates to this method.
-  std::vector<uint32_t> GetIdsForWhichSynonymsAreKnown(
-      opt::IRContext* context) const;
+  std::vector<uint32_t> GetIdsForWhichSynonymsAreKnown() const;
 
   // See method in FactManager which delegates to this method.
   bool IsSynonymous(const protobufs::DataDescriptor& data_descriptor1,
-                    const protobufs::DataDescriptor& data_descriptor2,
-                    opt::IRContext* context) const;
+                    const protobufs::DataDescriptor& data_descriptor2) const;
+
+  // See method in FactManager which delegates to this method.
+  void ComputeClosureOfFacts(opt::IRContext* context,
+                             uint32_t maximum_equivalence_class_size);
 
  private:
   // Adds the synonym |dd1| = |dd2| to the set of managed facts, and recurses
@@ -436,14 +437,10 @@
                                    const protobufs::DataDescriptor& dd2,
                                    opt::IRContext* context);
 
-  // Inspects all known facts and adds corollary facts; e.g. if we know that
-  // a.x == b.x and a.y == b.y, where a and b have vec2 type, we can record
-  // that a == b holds.
-  //
-  // This method is expensive, and is thus called on demand: rather than
-  // computing the closure of facts each time a data synonym fact is added, we
-  // compute the closure only when a data synonym fact is *queried*.
-  void ComputeClosureOfFacts(opt::IRContext* context) const;
+  // Records the fact that |dd1| and |dd2| are equivalent, and merges the sets
+  // of equations that are known about them.
+  void MakeEquivalent(const protobufs::DataDescriptor& dd1,
+                      const protobufs::DataDescriptor& dd2);
 
   // Returns true if and only if |dd1| and |dd2| are valid data descriptors
   // whose associated data have the same type (modulo integer signedness).
@@ -452,10 +449,11 @@
       const protobufs::DataDescriptor& dd2) const;
 
   // Requires that |lhs_dd| and every element of |rhs_dds| is present in the
-  // |synonymous_| equivalence relation and is its own representative.  Records
-  // the fact that the equation "|lhs_dd| |opcode| |rhs_dds|" holds, and adds
-  // any corollaries, in the form of data synonym or equation facts, that
-  // follow from this and other known facts.
+  // |synonymous_| equivalence relation, but is not necessarily its own
+  // representative.  Records the fact that the equation
+  // "|lhs_dd| |opcode| |rhs_dds_non_canonical|" holds, and adds any
+  // corollaries, in the form of data synonym or equation facts, that follow
+  // from this and other known facts.
   void AddEquationFactRecursive(
       const protobufs::DataDescriptor& lhs_dd, SpvOp opcode,
       const std::vector<const protobufs::DataDescriptor*>& rhs_dds,
@@ -463,28 +461,17 @@
 
   // The data descriptors that are known to be synonymous with one another are
   // captured by this equivalence relation.
-  //
-  // This member is mutable in order to allow the closure of facts captured by
-  // the relation to be computed lazily when a question about data synonym
-  // facts is asked.
-  mutable EquivalenceRelation<protobufs::DataDescriptor, DataDescriptorHash,
-                              DataDescriptorEquals>
+  EquivalenceRelation<protobufs::DataDescriptor, DataDescriptorHash,
+                      DataDescriptorEquals>
       synonymous_;
 
   // When a new synonym fact is added, it may be possible to deduce further
-  // synonym facts by computing a closure of all known facts.  However, there is
-  // no point computing this closure until a question regarding synonym facts is
-  // actually asked: if several facts are added in succession with no questions
-  // asked in between, we can avoid computing fact closures multiple times.
-  //
-  // This boolean tracks whether a closure computation is required - i.e.,
-  // whether a new fact has been added since the last time such a computation
-  // was performed.
-  //
-  // It is mutable to facilitate having const methods, that provide answers to
-  // questions about data synonym facts, triggering closure computation on
-  // demand.
-  mutable bool closure_computation_required_ = false;
+  // synonym facts by computing a closure of all known facts.  However, this is
+  // an expensive operation, so it should be performed sparingly and only there
+  // is some chance of new facts being deduced.  This boolean tracks whether a
+  // closure computation is required - i.e., whether a new fact has been added
+  // since the last time such a computation was performed.
+  bool closure_computation_required_ = false;
 
   // Represents a set of equations on data descriptors as a map indexed by
   // left-hand-side, mapping a left-hand-side to a set of operations, each of
@@ -510,12 +497,10 @@
     const protobufs::FactIdEquation& fact, opt::IRContext* context) {
   protobufs::DataDescriptor lhs_dd = MakeDataDescriptor(fact.lhs_id(), {});
 
-  // Register the LHS in the equivalence relation if needed, and get a pointer
-  // to its representative.
+  // Register the LHS in the equivalence relation if needed.
   if (!synonymous_.Exists(lhs_dd)) {
     synonymous_.Register(lhs_dd);
   }
-  const protobufs::DataDescriptor* lhs_dd_ptr = synonymous_.Find(&lhs_dd);
 
   // Get equivalence class representatives for all ids used on the RHS of the
   // equation.
@@ -529,10 +514,9 @@
     }
     rhs_dd_ptrs.push_back(synonymous_.Find(&rhs_dd));
   }
-  // We now have the equation in a form where it refers exclusively to
-  // equivalence class representatives.  Add it to our set of facts and work
-  // out any follow-on facts.
-  AddEquationFactRecursive(*lhs_dd_ptr, static_cast<SpvOp>(fact.opcode()),
+
+  // Now add the fact.
+  AddEquationFactRecursive(lhs_dd, static_cast<SpvOp>(fact.opcode()),
                            rhs_dd_ptrs, context);
 }
 
@@ -540,27 +524,27 @@
     const protobufs::DataDescriptor& lhs_dd, SpvOp opcode,
     const std::vector<const protobufs::DataDescriptor*>& rhs_dds,
     opt::IRContext* context) {
-  // Precondition: all data descriptors referenced in this equation must be
-  // equivalence class representatives - i.e. the equation must be in canonical
-  // form.
-  assert(synonymous_.Exists(lhs_dd));
-  assert(synonymous_.Find(&lhs_dd) == &lhs_dd);
+  assert(synonymous_.Exists(lhs_dd) &&
+         "The LHS must be known to the equivalence relation.");
   for (auto rhs_dd : rhs_dds) {
-    (void)(rhs_dd);  // Keep compilers happy in release mode.
-    assert(synonymous_.Exists(*rhs_dd));
-    assert(synonymous_.Find(rhs_dd) == rhs_dd);
+    // Keep release compilers happy.
+    (void)(rhs_dd);
+    assert(synonymous_.Exists(*rhs_dd) &&
+           "The RHS operands must be known to the equivalence relation.");
   }
 
-  if (id_equations_.count(&lhs_dd) == 0) {
+  auto lhs_dd_representative = synonymous_.Find(&lhs_dd);
+
+  if (id_equations_.count(lhs_dd_representative) == 0) {
     // We have not seen an equation with this LHS before, so associate the LHS
     // with an initially empty set.
     id_equations_.insert(
-        {&lhs_dd,
+        {lhs_dd_representative,
          std::unordered_set<Operation, OperationHash, OperationEquals>()});
   }
 
   {
-    auto existing_equations = id_equations_.find(&lhs_dd);
+    auto existing_equations = id_equations_.find(lhs_dd_representative);
     assert(existing_equations != id_equations_.end() &&
            "A set of operations should be present, even if empty.");
 
@@ -584,13 +568,15 @@
           for (auto equation : existing_first_operand_equations->second) {
             if (equation.opcode == SpvOpISub) {
               // Equation form: "a = (d - e) + c"
-              if (equation.operands[1] == rhs_dds[1]) {
+              if (synonymous_.IsEquivalent(*equation.operands[1],
+                                           *rhs_dds[1])) {
                 // Equation form: "a = (d - c) + c"
                 // We can thus infer "a = d"
                 AddDataSynonymFactRecursive(lhs_dd, *equation.operands[0],
                                             context);
               }
-              if (equation.operands[0] == rhs_dds[1]) {
+              if (synonymous_.IsEquivalent(*equation.operands[0],
+                                           *rhs_dds[1])) {
                 // Equation form: "a = (c - e) + c"
                 // We can thus infer "a = -e"
                 AddEquationFactRecursive(lhs_dd, SpvOpSNegate,
@@ -606,7 +592,8 @@
           for (auto equation : existing_second_operand_equations->second) {
             if (equation.opcode == SpvOpISub) {
               // Equation form: "a = b + (d - e)"
-              if (equation.operands[1] == rhs_dds[0]) {
+              if (synonymous_.IsEquivalent(*equation.operands[1],
+                                           *rhs_dds[0])) {
                 // Equation form: "a = b + (d - b)"
                 // We can thus infer "a = d"
                 AddDataSynonymFactRecursive(lhs_dd, *equation.operands[0],
@@ -626,13 +613,15 @@
           for (auto equation : existing_first_operand_equations->second) {
             if (equation.opcode == SpvOpIAdd) {
               // Equation form: "a = (d + e) - c"
-              if (equation.operands[0] == rhs_dds[1]) {
+              if (synonymous_.IsEquivalent(*equation.operands[0],
+                                           *rhs_dds[1])) {
                 // Equation form: "a = (c + e) - c"
                 // We can thus infer "a = e"
                 AddDataSynonymFactRecursive(lhs_dd, *equation.operands[1],
                                             context);
               }
-              if (equation.operands[1] == rhs_dds[1]) {
+              if (synonymous_.IsEquivalent(*equation.operands[1],
+                                           *rhs_dds[1])) {
                 // Equation form: "a = (d + c) - c"
                 // We can thus infer "a = d"
                 AddDataSynonymFactRecursive(lhs_dd, *equation.operands[0],
@@ -642,7 +631,8 @@
 
             if (equation.opcode == SpvOpISub) {
               // Equation form: "a = (d - e) - c"
-              if (equation.operands[0] == rhs_dds[1]) {
+              if (synonymous_.IsEquivalent(*equation.operands[0],
+                                           *rhs_dds[1])) {
                 // Equation form: "a = (c - e) - c"
                 // We can thus infer "a = -e"
                 AddEquationFactRecursive(lhs_dd, SpvOpSNegate,
@@ -659,13 +649,15 @@
           for (auto equation : existing_second_operand_equations->second) {
             if (equation.opcode == SpvOpIAdd) {
               // Equation form: "a = b - (d + e)"
-              if (equation.operands[0] == rhs_dds[0]) {
+              if (synonymous_.IsEquivalent(*equation.operands[0],
+                                           *rhs_dds[0])) {
                 // Equation form: "a = b - (b + e)"
                 // We can thus infer "a = -e"
                 AddEquationFactRecursive(lhs_dd, SpvOpSNegate,
                                          {equation.operands[1]}, context);
               }
-              if (equation.operands[1] == rhs_dds[0]) {
+              if (synonymous_.IsEquivalent(*equation.operands[1],
+                                           *rhs_dds[0])) {
                 // Equation form: "a = b - (d + b)"
                 // We can thus infer "a = -d"
                 AddEquationFactRecursive(lhs_dd, SpvOpSNegate,
@@ -674,7 +666,8 @@
             }
             if (equation.opcode == SpvOpISub) {
               // Equation form: "a = b - (d - e)"
-              if (equation.operands[0] == rhs_dds[0]) {
+              if (synonymous_.IsEquivalent(*equation.operands[0],
+                                           *rhs_dds[0])) {
                 // Equation form: "a = b - (b - e)"
                 // We can thus infer "a = e"
                 AddDataSynonymFactRecursive(lhs_dd, *equation.operands[1],
@@ -712,12 +705,7 @@
   assert(DataDescriptorsAreWellFormedAndComparable(context, dd1, dd2));
 
   // Record that the data descriptors provided in the fact are equivalent.
-  synonymous_.MakeEquivalent(dd1, dd2);
-  // As we have updated the equivalence relation, we might be able to deduce
-  // more facts by performing a closure computation, so we record that such a
-  // computation is required; it will be performed next time a method answering
-  // a data synonym fact-related question is invoked.
-  closure_computation_required_ = true;
+  MakeEquivalent(dd1, dd2);
 
   // We now check whether this is a synonym about composite objects.  If it is,
   // we can recursively add synonym facts about their associated sub-components.
@@ -754,7 +742,17 @@
   //   obj_1[a_1, ..., a_m] == obj_2[b_1, ..., b_n]
   // then for each composite index i, we add a fact of the form:
   //   obj_1[a_1, ..., a_m, i] == obj_2[b_1, ..., b_n, i]
-  for (uint32_t i = 0; i < num_composite_elements; i++) {
+  //
+  // However, to avoid adding a large number of synonym facts e.g. in the case
+  // of arrays, we bound the number of composite elements to which this is
+  // applied.  Nevertheless, we always add a synonym fact for the final
+  // components, as this may be an interesting edge case.
+
+  // The bound on the number of indices of the composite pair to note as being
+  // synonymous.
+  const uint32_t kCompositeElementBound = 10;
+
+  for (uint32_t i = 0; i < num_composite_elements;) {
     std::vector<uint32_t> extended_indices1 =
         fuzzerutil::RepeatedFieldToVector(dd1.index());
     extended_indices1.push_back(i);
@@ -765,11 +763,21 @@
         MakeDataDescriptor(dd1.object(), std::move(extended_indices1)),
         MakeDataDescriptor(dd2.object(), std::move(extended_indices2)),
         context);
+
+    if (i < kCompositeElementBound - 1 || i == num_composite_elements - 1) {
+      // We have not reached the bound yet, or have already skipped ahead to the
+      // last element, so increment the loop counter as standard.
+      i++;
+    } else {
+      // We have reached the bound, so skip ahead to the last element.
+      assert(i == kCompositeElementBound - 1);
+      i = num_composite_elements - 1;
+    }
   }
 }
 
 void FactManager::DataSynonymAndIdEquationFacts::ComputeClosureOfFacts(
-    opt::IRContext* context) const {
+    opt::IRContext* context, uint32_t maximum_equivalence_class_size) {
   // Suppose that obj_1[a_1, ..., a_m] and obj_2[b_1, ..., b_n] are distinct
   // data descriptors that describe objects of the same composite type, and that
   // the composite type is comprised of k components.
@@ -855,6 +863,13 @@
          synonymous_.GetEquivalenceClassRepresentatives()) {
       auto equivalence_class = synonymous_.GetEquivalenceClass(*representative);
 
+      if (equivalence_class.size() > maximum_equivalence_class_size) {
+        // This equivalence class is larger than the maximum size we are willing
+        // to consider, so we skip it.  This potentially leads to missed fact
+        // deductions, but avoids excessive runtime for closure computation.
+        continue;
+      }
+
       // Consider every data descriptor in the equivalence class.
       for (auto dd1_it = equivalence_class.begin();
            dd1_it != equivalence_class.end(); ++dd1_it) {
@@ -1029,10 +1044,7 @@
             // synonymous.
             assert(DataDescriptorsAreWellFormedAndComparable(
                 context, dd1_prefix, dd2_prefix));
-            synonymous_.MakeEquivalent(dd1_prefix, dd2_prefix);
-            // As we have added a new synonym fact, we might benefit from doing
-            // another pass over the equivalence relation.
-            closure_computation_required_ = true;
+            MakeEquivalent(dd1_prefix, dd2_prefix);
             // Now that we know this pair of data descriptors are synonymous,
             // there is no point recording how close they are to being
             // synonymous.
@@ -1044,6 +1056,84 @@
   }
 }
 
+void FactManager::DataSynonymAndIdEquationFacts::MakeEquivalent(
+    const protobufs::DataDescriptor& dd1,
+    const protobufs::DataDescriptor& dd2) {
+  // Register the data descriptors if they are not already known to the
+  // equivalence relation.
+  for (const auto& dd : {dd1, dd2}) {
+    if (!synonymous_.Exists(dd)) {
+      synonymous_.Register(dd);
+    }
+  }
+
+  if (synonymous_.IsEquivalent(dd1, dd2)) {
+    // The data descriptors are already known to be equivalent, so there is
+    // nothing to do.
+    return;
+  }
+
+  // We must make the data descriptors equivalent, and also make sure any
+  // equation facts known about their representatives are merged.
+
+  // Record the original equivalence class representatives of the data
+  // descriptors.
+  auto dd1_original_representative = synonymous_.Find(&dd1);
+  auto dd2_original_representative = synonymous_.Find(&dd2);
+
+  // Make the data descriptors equivalent.
+  synonymous_.MakeEquivalent(dd1, dd2);
+  // As we have updated the equivalence relation, we might be able to deduce
+  // more facts by performing a closure computation, so we record that such a
+  // computation is required.
+  closure_computation_required_ = true;
+
+  // At this point, exactly one of |dd1_original_representative| and
+  // |dd2_original_representative| will be the representative of the combined
+  // equivalence class.  We work out which one of them is still the class
+  // representative and which one is no longer the class representative.
+
+  auto still_representative = synonymous_.Find(dd1_original_representative) ==
+                                      dd1_original_representative
+                                  ? dd1_original_representative
+                                  : dd2_original_representative;
+  auto no_longer_representative =
+      still_representative == dd1_original_representative
+          ? dd2_original_representative
+          : dd1_original_representative;
+
+  assert(no_longer_representative != still_representative &&
+         "The current and former representatives cannot be the same.");
+
+  // We now need to add all equations about |no_longer_representative| to the
+  // set of equations known about |still_representative|.
+
+  // Get the equations associated with |no_longer_representative|.
+  auto no_longer_representative_id_equations =
+      id_equations_.find(no_longer_representative);
+  if (no_longer_representative_id_equations != id_equations_.end()) {
+    // There are some equations to transfer.  There might not yet be any
+    // equations about |still_representative|; create an empty set of equations
+    // if this is the case.
+    if (!id_equations_.count(still_representative)) {
+      id_equations_.insert(
+          {still_representative,
+           std::unordered_set<Operation, OperationHash, OperationEquals>()});
+    }
+    auto still_representative_id_equations =
+        id_equations_.find(still_representative);
+    assert(still_representative_id_equations != id_equations_.end() &&
+           "At this point there must be a set of equations.");
+    // Add all the equations known about |no_longer_representative| to the set
+    // of equations known about |still_representative|.
+    still_representative_id_equations->second.insert(
+        no_longer_representative_id_equations->second.begin(),
+        no_longer_representative_id_equations->second.end());
+  }
+  // Delete the no longer-relevant equations about |no_longer_representative|.
+  id_equations_.erase(no_longer_representative);
+}
+
 bool FactManager::DataSynonymAndIdEquationFacts::
     DataDescriptorsAreWellFormedAndComparable(
         opt::IRContext* context, const protobufs::DataDescriptor& dd1,
@@ -1094,9 +1184,7 @@
 
 std::vector<const protobufs::DataDescriptor*>
 FactManager::DataSynonymAndIdEquationFacts::GetSynonymsForDataDescriptor(
-    const protobufs::DataDescriptor& data_descriptor,
-    opt::IRContext* context) const {
-  ComputeClosureOfFacts(context);
+    const protobufs::DataDescriptor& data_descriptor) const {
   if (synonymous_.Exists(data_descriptor)) {
     return synonymous_.GetEquivalenceClass(data_descriptor);
   }
@@ -1104,9 +1192,8 @@
 }
 
 std::vector<uint32_t>
-FactManager::DataSynonymAndIdEquationFacts ::GetIdsForWhichSynonymsAreKnown(
-    opt::IRContext* context) const {
-  ComputeClosureOfFacts(context);
+FactManager::DataSynonymAndIdEquationFacts::GetIdsForWhichSynonymsAreKnown()
+    const {
   std::vector<uint32_t> result;
   for (auto& data_descriptor : synonymous_.GetAllKnownValues()) {
     if (data_descriptor->index().empty()) {
@@ -1118,10 +1205,7 @@
 
 bool FactManager::DataSynonymAndIdEquationFacts::IsSynonymous(
     const protobufs::DataDescriptor& data_descriptor1,
-    const protobufs::DataDescriptor& data_descriptor2,
-    opt::IRContext* context) const {
-  const_cast<FactManager::DataSynonymAndIdEquationFacts*>(this)
-      ->ComputeClosureOfFacts(context);
+    const protobufs::DataDescriptor& data_descriptor2) const {
   return synonymous_.Exists(data_descriptor1) &&
          synonymous_.Exists(data_descriptor2) &&
          synonymous_.IsEquivalent(data_descriptor1, data_descriptor2);
@@ -1303,31 +1387,27 @@
   return uniform_constant_facts_->GetConstantUniformFactsAndTypes();
 }
 
-std::vector<uint32_t> FactManager::GetIdsForWhichSynonymsAreKnown(
-    opt::IRContext* context) const {
-  return data_synonym_and_id_equation_facts_->GetIdsForWhichSynonymsAreKnown(
-      context);
+std::vector<uint32_t> FactManager::GetIdsForWhichSynonymsAreKnown() const {
+  return data_synonym_and_id_equation_facts_->GetIdsForWhichSynonymsAreKnown();
 }
 
 std::vector<const protobufs::DataDescriptor*>
 FactManager::GetSynonymsForDataDescriptor(
-    const protobufs::DataDescriptor& data_descriptor,
-    opt::IRContext* context) const {
+    const protobufs::DataDescriptor& data_descriptor) const {
   return data_synonym_and_id_equation_facts_->GetSynonymsForDataDescriptor(
-      data_descriptor, context);
+      data_descriptor);
 }
 
 std::vector<const protobufs::DataDescriptor*> FactManager::GetSynonymsForId(
-    uint32_t id, opt::IRContext* context) const {
-  return GetSynonymsForDataDescriptor(MakeDataDescriptor(id, {}), context);
+    uint32_t id) const {
+  return GetSynonymsForDataDescriptor(MakeDataDescriptor(id, {}));
 }
 
 bool FactManager::IsSynonymous(
     const protobufs::DataDescriptor& data_descriptor1,
-    const protobufs::DataDescriptor& data_descriptor2,
-    opt::IRContext* context) const {
-  return data_synonym_and_id_equation_facts_->IsSynonymous(
-      data_descriptor1, data_descriptor2, context);
+    const protobufs::DataDescriptor& data_descriptor2) const {
+  return data_synonym_and_id_equation_facts_->IsSynonymous(data_descriptor1,
+                                                           data_descriptor2);
 }
 
 bool FactManager::BlockIsDead(uint32_t block_id) const {
@@ -1372,5 +1452,11 @@
   data_synonym_and_id_equation_facts_->AddFact(fact, context);
 }
 
+void FactManager::ComputeClosureOfFacts(
+    opt::IRContext* ir_context, uint32_t maximum_equivalence_class_size) {
+  data_synonym_and_id_equation_facts_->ComputeClosureOfFacts(
+      ir_context, maximum_equivalence_class_size);
+}
+
 }  // namespace fuzz
 }  // namespace spvtools
diff --git a/third_party/spirv-tools/src/source/fuzz/fact_manager.h b/third_party/spirv-tools/src/source/fuzz/fact_manager.h
index f80d677..f520e42 100644
--- a/third_party/spirv-tools/src/source/fuzz/fact_manager.h
+++ b/third_party/spirv-tools/src/source/fuzz/fact_manager.h
@@ -76,6 +76,21 @@
                          const std::vector<uint32_t>& rhs_id,
                          opt::IRContext* context);
 
+  // Inspects all known facts and adds corollary facts; e.g. if we know that
+  // a.x == b.x and a.y == b.y, where a and b have vec2 type, we can record
+  // that a == b holds.
+  //
+  // This method is expensive, and should only be called (by applying a
+  // transformation) at the start of a fuzzer pass that depends on data
+  // synonym facts, rather than calling it every time a new data synonym fact
+  // is added.
+  //
+  // The parameter |maximum_equivalence_class_size| specifies the size beyond
+  // which equivalence classes should not be mined for new facts, to avoid
+  // excessively-long closure computations.
+  void ComputeClosureOfFacts(opt::IRContext* ir_context,
+                             uint32_t maximum_equivalence_class_size);
+
   // The fact manager is responsible for managing a few distinct categories of
   // facts. In principle there could be different fact managers for each kind
   // of fact, but in practice providing one 'go to' place for facts is
@@ -125,25 +140,22 @@
 
   // Returns every id for which a fact of the form "this id is synonymous with
   // this piece of data" is known.
-  std::vector<uint32_t> GetIdsForWhichSynonymsAreKnown(
-      opt::IRContext* context) const;
+  std::vector<uint32_t> GetIdsForWhichSynonymsAreKnown() const;
 
   // Returns the equivalence class of all known synonyms of |id|, or an empty
   // set if no synonyms are known.
   std::vector<const protobufs::DataDescriptor*> GetSynonymsForId(
-      uint32_t id, opt::IRContext* context) const;
+      uint32_t id) const;
 
   // Returns the equivalence class of all known synonyms of |data_descriptor|,
   // or empty if no synonyms are known.
   std::vector<const protobufs::DataDescriptor*> GetSynonymsForDataDescriptor(
-      const protobufs::DataDescriptor& data_descriptor,
-      opt::IRContext* context) const;
+      const protobufs::DataDescriptor& data_descriptor) const;
 
   // Returns true if and ony if |data_descriptor1| and |data_descriptor2| are
   // known to be synonymous.
   bool IsSynonymous(const protobufs::DataDescriptor& data_descriptor1,
-                    const protobufs::DataDescriptor& data_descriptor2,
-                    opt::IRContext* context) const;
+                    const protobufs::DataDescriptor& data_descriptor2) const;
 
   // End of id synonym facts
   //==============================
diff --git a/third_party/spirv-tools/src/source/fuzz/force_render_red.cpp b/third_party/spirv-tools/src/source/fuzz/force_render_red.cpp
index 46e23e8..5bf2879 100644
--- a/third_party/spirv-tools/src/source/fuzz/force_render_red.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/force_render_red.cpp
@@ -17,6 +17,7 @@
 #include "source/fuzz/fact_manager.h"
 #include "source/fuzz/instruction_descriptor.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/fuzz/transformation_replace_constant_with_uniform.h"
 #include "source/fuzz/uniform_buffer_element_descriptor.h"
 #include "source/opt/build_module.h"
@@ -159,7 +160,8 @@
 }  // namespace
 
 bool ForceRenderRed(
-    const spv_target_env& target_env, const std::vector<uint32_t>& binary_in,
+    const spv_target_env& target_env, spv_validator_options validator_options,
+    const std::vector<uint32_t>& binary_in,
     const spvtools::fuzz::protobufs::FactSequence& initial_facts,
     std::vector<uint32_t>* binary_out) {
   auto message_consumer = spvtools::utils::CLIMessageConsumer;
@@ -171,7 +173,7 @@
   }
 
   // Initial binary should be valid.
-  if (!tools.Validate(&binary_in[0], binary_in.size())) {
+  if (!tools.Validate(&binary_in[0], binary_in.size(), validator_options)) {
     message_consumer(SPV_MSG_ERROR, nullptr, {},
                      "Initial binary is invalid; stopping.");
     return false;
@@ -187,6 +189,8 @@
   for (auto& fact : initial_facts.fact()) {
     fact_manager.AddFact(fact, ir_context.get());
   }
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   auto entry_point_function =
       FindFragmentShaderEntryPoint(ir_context.get(), message_consumer);
@@ -355,8 +359,9 @@
     for (auto& replacement : {first_greater_then_operand_replacement.get(),
                               second_greater_then_operand_replacement.get()}) {
       if (replacement) {
-        assert(replacement->IsApplicable(ir_context.get(), fact_manager));
-        replacement->Apply(ir_context.get(), &fact_manager);
+        assert(replacement->IsApplicable(ir_context.get(),
+                                         transformation_context));
+        replacement->Apply(ir_context.get(), &transformation_context);
       }
     }
   }
diff --git a/third_party/spirv-tools/src/source/fuzz/force_render_red.h b/third_party/spirv-tools/src/source/fuzz/force_render_red.h
index 2484d27..b51c72b 100644
--- a/third_party/spirv-tools/src/source/fuzz/force_render_red.h
+++ b/third_party/spirv-tools/src/source/fuzz/force_render_red.h
@@ -38,7 +38,8 @@
 // instead become: 'u > v', where 'u' and 'v' are pieces of uniform data for
 // which it is known that 'u < v' holds.
 bool ForceRenderRed(
-    const spv_target_env& target_env, const std::vector<uint32_t>& binary_in,
+    const spv_target_env& target_env, spv_validator_options validator_options,
+    const std::vector<uint32_t>& binary_in,
     const spvtools::fuzz::protobufs::FactSequence& initial_facts,
     std::vector<uint32_t>* binary_out);
 
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer.cpp b/third_party/spirv-tools/src/source/fuzz/fuzzer.cpp
index 119bd3c..6524c21 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer.cpp
@@ -51,6 +51,7 @@
 #include "source/fuzz/fuzzer_pass_toggle_access_chain_instruction.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/pseudo_random_generator.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/build_module.h"
 #include "source/spirv_fuzzer_options.h"
 #include "source/util/make_unique.h"
@@ -66,19 +67,19 @@
 const uint32_t kChanceOfApplyingAnotherPass = 85;
 
 // A convenience method to add a fuzzer pass to |passes| with probability 0.5.
-// All fuzzer passes take |ir_context|, |fact_manager|, |fuzzer_context| and
-// |transformation_sequence_out| as parameters.  Extra arguments can be provided
-// via |extra_args|.
+// All fuzzer passes take |ir_context|, |transformation_context|,
+// |fuzzer_context| and |transformation_sequence_out| as parameters.  Extra
+// arguments can be provided via |extra_args|.
 template <typename T, typename... Args>
 void MaybeAddPass(
     std::vector<std::unique_ptr<FuzzerPass>>* passes,
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformation_sequence_out,
     Args&&... extra_args) {
   if (fuzzer_context->ChooseEven()) {
-    passes->push_back(MakeUnique<T>(ir_context, fact_manager, fuzzer_context,
-                                    transformation_sequence_out,
+    passes->push_back(MakeUnique<T>(ir_context, transformation_context,
+                                    fuzzer_context, transformation_sequence_out,
                                     std::forward<Args>(extra_args)...));
   }
 }
@@ -86,26 +87,31 @@
 }  // namespace
 
 struct Fuzzer::Impl {
-  explicit Impl(spv_target_env env, uint32_t random_seed,
-                bool validate_after_each_pass)
+  Impl(spv_target_env env, uint32_t random_seed, bool validate_after_each_pass,
+       spv_validator_options options)
       : target_env(env),
         seed(random_seed),
-        validate_after_each_fuzzer_pass(validate_after_each_pass) {}
+        validate_after_each_fuzzer_pass(validate_after_each_pass),
+        validator_options(options) {}
 
   bool ApplyPassAndCheckValidity(FuzzerPass* pass,
                                  const opt::IRContext& ir_context,
                                  const spvtools::SpirvTools& tools) const;
 
   const spv_target_env target_env;       // Target environment.
+  MessageConsumer consumer;              // Message consumer.
   const uint32_t seed;                   // Seed for random number generator.
   bool validate_after_each_fuzzer_pass;  // Determines whether the validator
-  // should be invoked after every fuzzer pass.
-  MessageConsumer consumer;  // Message consumer.
+                                         // should be invoked after every fuzzer
+                                         // pass.
+  spv_validator_options validator_options;  // Options to control validation.
 };
 
 Fuzzer::Fuzzer(spv_target_env env, uint32_t seed,
-               bool validate_after_each_fuzzer_pass)
-    : impl_(MakeUnique<Impl>(env, seed, validate_after_each_fuzzer_pass)) {}
+               bool validate_after_each_fuzzer_pass,
+               spv_validator_options validator_options)
+    : impl_(MakeUnique<Impl>(env, seed, validate_after_each_fuzzer_pass,
+                             validator_options)) {}
 
 Fuzzer::~Fuzzer() = default;
 
@@ -120,7 +126,8 @@
   if (validate_after_each_fuzzer_pass) {
     std::vector<uint32_t> binary_to_validate;
     ir_context.module()->ToBinary(&binary_to_validate, false);
-    if (!tools.Validate(&binary_to_validate[0], binary_to_validate.size())) {
+    if (!tools.Validate(&binary_to_validate[0], binary_to_validate.size(),
+                        validator_options)) {
       consumer(SPV_MSG_INFO, nullptr, {},
                "Binary became invalid during fuzzing (set a breakpoint to "
                "inspect); stopping.");
@@ -149,7 +156,8 @@
   }
 
   // Initial binary should be valid.
-  if (!tools.Validate(&binary_in[0], binary_in.size())) {
+  if (!tools.Validate(&binary_in[0], binary_in.size(),
+                      impl_->validator_options)) {
     impl_->consumer(SPV_MSG_ERROR, nullptr, {},
                     "Initial binary is invalid; stopping.");
     return Fuzzer::FuzzerResultStatus::kInitialBinaryInvalid;
@@ -175,11 +183,13 @@
 
   FactManager fact_manager;
   fact_manager.AddFacts(impl_->consumer, initial_facts, ir_context.get());
+  TransformationContext transformation_context(&fact_manager,
+                                               impl_->validator_options);
 
   // Add some essential ingredients to the module if they are not already
   // present, such as boolean constants.
   FuzzerPassAddUsefulConstructs add_useful_constructs(
-      ir_context.get(), &fact_manager, &fuzzer_context,
+      ir_context.get(), &transformation_context, &fuzzer_context,
       transformation_sequence_out);
   if (!impl_->ApplyPassAndCheckValidity(&add_useful_constructs, *ir_context,
                                         tools)) {
@@ -189,69 +199,69 @@
   // Apply some semantics-preserving passes.
   std::vector<std::unique_ptr<FuzzerPass>> passes;
   while (passes.empty()) {
-    MaybeAddPass<FuzzerPassAddAccessChains>(&passes, ir_context.get(),
-                                            &fact_manager, &fuzzer_context,
-                                            transformation_sequence_out);
-    MaybeAddPass<FuzzerPassAddCompositeTypes>(&passes, ir_context.get(),
-                                              &fact_manager, &fuzzer_context,
-                                              transformation_sequence_out);
-    MaybeAddPass<FuzzerPassAddDeadBlocks>(&passes, ir_context.get(),
-                                          &fact_manager, &fuzzer_context,
-                                          transformation_sequence_out);
-    MaybeAddPass<FuzzerPassAddDeadBreaks>(&passes, ir_context.get(),
-                                          &fact_manager, &fuzzer_context,
-                                          transformation_sequence_out);
-    MaybeAddPass<FuzzerPassAddDeadContinues>(&passes, ir_context.get(),
-                                             &fact_manager, &fuzzer_context,
-                                             transformation_sequence_out);
+    MaybeAddPass<FuzzerPassAddAccessChains>(
+        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
+        transformation_sequence_out);
+    MaybeAddPass<FuzzerPassAddCompositeTypes>(
+        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
+        transformation_sequence_out);
+    MaybeAddPass<FuzzerPassAddDeadBlocks>(
+        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
+        transformation_sequence_out);
+    MaybeAddPass<FuzzerPassAddDeadBreaks>(
+        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
+        transformation_sequence_out);
+    MaybeAddPass<FuzzerPassAddDeadContinues>(
+        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
+        transformation_sequence_out);
     MaybeAddPass<FuzzerPassAddEquationInstructions>(
-        &passes, ir_context.get(), &fact_manager, &fuzzer_context,
+        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
         transformation_sequence_out);
-    MaybeAddPass<FuzzerPassAddFunctionCalls>(&passes, ir_context.get(),
-                                             &fact_manager, &fuzzer_context,
-                                             transformation_sequence_out);
-    MaybeAddPass<FuzzerPassAddGlobalVariables>(&passes, ir_context.get(),
-                                               &fact_manager, &fuzzer_context,
-                                               transformation_sequence_out);
-    MaybeAddPass<FuzzerPassAddLoads>(&passes, ir_context.get(), &fact_manager,
-                                     &fuzzer_context,
+    MaybeAddPass<FuzzerPassAddFunctionCalls>(
+        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
+        transformation_sequence_out);
+    MaybeAddPass<FuzzerPassAddGlobalVariables>(
+        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
+        transformation_sequence_out);
+    MaybeAddPass<FuzzerPassAddLoads>(&passes, ir_context.get(),
+                                     &transformation_context, &fuzzer_context,
                                      transformation_sequence_out);
-    MaybeAddPass<FuzzerPassAddLocalVariables>(&passes, ir_context.get(),
-                                              &fact_manager, &fuzzer_context,
-                                              transformation_sequence_out);
-    MaybeAddPass<FuzzerPassAddStores>(&passes, ir_context.get(), &fact_manager,
-                                      &fuzzer_context,
-                                      transformation_sequence_out);
-    MaybeAddPass<FuzzerPassApplyIdSynonyms>(&passes, ir_context.get(),
-                                            &fact_manager, &fuzzer_context,
-                                            transformation_sequence_out);
-    MaybeAddPass<FuzzerPassConstructComposites>(&passes, ir_context.get(),
-                                                &fact_manager, &fuzzer_context,
-                                                transformation_sequence_out);
-    MaybeAddPass<FuzzerPassCopyObjects>(&passes, ir_context.get(),
-                                        &fact_manager, &fuzzer_context,
-                                        transformation_sequence_out);
-    MaybeAddPass<FuzzerPassDonateModules>(
-        &passes, ir_context.get(), &fact_manager, &fuzzer_context,
-        transformation_sequence_out, donor_suppliers);
-    MaybeAddPass<FuzzerPassMergeBlocks>(&passes, ir_context.get(),
-                                        &fact_manager, &fuzzer_context,
-                                        transformation_sequence_out);
-    MaybeAddPass<FuzzerPassObfuscateConstants>(&passes, ir_context.get(),
-                                               &fact_manager, &fuzzer_context,
-                                               transformation_sequence_out);
-    MaybeAddPass<FuzzerPassOutlineFunctions>(&passes, ir_context.get(),
-                                             &fact_manager, &fuzzer_context,
-                                             transformation_sequence_out);
-    MaybeAddPass<FuzzerPassPermuteBlocks>(&passes, ir_context.get(),
-                                          &fact_manager, &fuzzer_context,
-                                          transformation_sequence_out);
-    MaybeAddPass<FuzzerPassPermuteFunctionParameters>(
-        &passes, ir_context.get(), &fact_manager, &fuzzer_context,
+    MaybeAddPass<FuzzerPassAddLocalVariables>(
+        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
         transformation_sequence_out);
-    MaybeAddPass<FuzzerPassSplitBlocks>(&passes, ir_context.get(),
-                                        &fact_manager, &fuzzer_context,
-                                        transformation_sequence_out);
+    MaybeAddPass<FuzzerPassAddStores>(&passes, ir_context.get(),
+                                      &transformation_context, &fuzzer_context,
+                                      transformation_sequence_out);
+    MaybeAddPass<FuzzerPassApplyIdSynonyms>(
+        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
+        transformation_sequence_out);
+    MaybeAddPass<FuzzerPassConstructComposites>(
+        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
+        transformation_sequence_out);
+    MaybeAddPass<FuzzerPassCopyObjects>(
+        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
+        transformation_sequence_out);
+    MaybeAddPass<FuzzerPassDonateModules>(
+        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
+        transformation_sequence_out, donor_suppliers);
+    MaybeAddPass<FuzzerPassMergeBlocks>(
+        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
+        transformation_sequence_out);
+    MaybeAddPass<FuzzerPassObfuscateConstants>(
+        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
+        transformation_sequence_out);
+    MaybeAddPass<FuzzerPassOutlineFunctions>(
+        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
+        transformation_sequence_out);
+    MaybeAddPass<FuzzerPassPermuteBlocks>(
+        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
+        transformation_sequence_out);
+    MaybeAddPass<FuzzerPassPermuteFunctionParameters>(
+        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
+        transformation_sequence_out);
+    MaybeAddPass<FuzzerPassSplitBlocks>(
+        &passes, ir_context.get(), &transformation_context, &fuzzer_context,
+        transformation_sequence_out);
   }
 
   bool is_first = true;
@@ -272,25 +282,25 @@
   // as they do not unlock other passes.
   std::vector<std::unique_ptr<FuzzerPass>> final_passes;
   MaybeAddPass<FuzzerPassAdjustFunctionControls>(
-      &final_passes, ir_context.get(), &fact_manager, &fuzzer_context,
+      &final_passes, ir_context.get(), &transformation_context, &fuzzer_context,
       transformation_sequence_out);
-  MaybeAddPass<FuzzerPassAdjustLoopControls>(&final_passes, ir_context.get(),
-                                             &fact_manager, &fuzzer_context,
-                                             transformation_sequence_out);
+  MaybeAddPass<FuzzerPassAdjustLoopControls>(
+      &final_passes, ir_context.get(), &transformation_context, &fuzzer_context,
+      transformation_sequence_out);
   MaybeAddPass<FuzzerPassAdjustMemoryOperandsMasks>(
-      &final_passes, ir_context.get(), &fact_manager, &fuzzer_context,
+      &final_passes, ir_context.get(), &transformation_context, &fuzzer_context,
       transformation_sequence_out);
   MaybeAddPass<FuzzerPassAdjustSelectionControls>(
-      &final_passes, ir_context.get(), &fact_manager, &fuzzer_context,
+      &final_passes, ir_context.get(), &transformation_context, &fuzzer_context,
       transformation_sequence_out);
   MaybeAddPass<FuzzerPassAddNoContractionDecorations>(
-      &final_passes, ir_context.get(), &fact_manager, &fuzzer_context,
+      &final_passes, ir_context.get(), &transformation_context, &fuzzer_context,
       transformation_sequence_out);
   MaybeAddPass<FuzzerPassSwapCommutableOperands>(
-      &final_passes, ir_context.get(), &fact_manager, &fuzzer_context,
+      &final_passes, ir_context.get(), &transformation_context, &fuzzer_context,
       transformation_sequence_out);
   MaybeAddPass<FuzzerPassToggleAccessChainInstruction>(
-      &final_passes, ir_context.get(), &fact_manager, &fuzzer_context,
+      &final_passes, ir_context.get(), &transformation_context, &fuzzer_context,
       transformation_sequence_out);
   for (auto& pass : final_passes) {
     if (!impl_->ApplyPassAndCheckValidity(pass.get(), *ir_context, tools)) {
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer.h b/third_party/spirv-tools/src/source/fuzz/fuzzer.h
index 3ac73a1..6c3ef71 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer.h
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer.h
@@ -41,8 +41,9 @@
   // seed for pseudo-random number generation.
   // |validate_after_each_fuzzer_pass| controls whether the validator will be
   // invoked after every fuzzer pass is applied.
-  explicit Fuzzer(spv_target_env env, uint32_t seed,
-                  bool validate_after_each_fuzzer_pass);
+  Fuzzer(spv_target_env env, uint32_t seed,
+         bool validate_after_each_fuzzer_pass,
+         spv_validator_options validator_options);
 
   // Disables copy/move constructor/assignment operations.
   Fuzzer(const Fuzzer&) = delete;
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_context.cpp b/third_party/spirv-tools/src/source/fuzz/fuzzer_context.cpp
index 2f9fc5a..94032ef 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_context.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_context.cpp
@@ -68,6 +68,7 @@
 
 // Default limits for various quantities that are chosen during fuzzing.
 // Keep them in alphabetical order.
+const uint32_t kDefaultMaxEquivalenceClassSizeForDataSynonymFactClosure = 1000;
 const uint32_t kDefaultMaxLoopControlPartialCount = 100;
 const uint32_t kDefaultMaxLoopControlPeelCount = 100;
 const uint32_t kDefaultMaxLoopLimit = 20;
@@ -89,6 +90,8 @@
                              uint32_t min_fresh_id)
     : random_generator_(random_generator),
       next_fresh_id_(min_fresh_id),
+      max_equivalence_class_size_for_data_synonym_fact_closure_(
+          kDefaultMaxEquivalenceClassSizeForDataSynonymFactClosure),
       max_loop_control_partial_count_(kDefaultMaxLoopControlPartialCount),
       max_loop_control_peel_count_(kDefaultMaxLoopControlPeelCount),
       max_loop_limit_(kDefaultMaxLoopLimit),
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_context.h b/third_party/spirv-tools/src/source/fuzz/fuzzer_context.h
index 1529705..5899235 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_context.h
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_context.h
@@ -183,12 +183,21 @@
   uint32_t GetChanceOfTogglingAccessChainInstruction() {
     return chance_of_toggling_access_chain_instruction_;
   }
-  uint32_t GetRandomLoopControlPeelCount() {
-    return random_generator_->RandomUint32(max_loop_control_peel_count_);
+
+  // Other functions to control transformations. Keep them in alphabetical
+  // order.
+  uint32_t GetMaximumEquivalenceClassSizeForDataSynonymFactClosure() {
+    return max_equivalence_class_size_for_data_synonym_fact_closure_;
+  }
+  uint32_t GetRandomIndexForAccessChain(uint32_t composite_size_bound) {
+    return random_generator_->RandomUint32(composite_size_bound);
   }
   uint32_t GetRandomLoopControlPartialCount() {
     return random_generator_->RandomUint32(max_loop_control_partial_count_);
   }
+  uint32_t GetRandomLoopControlPeelCount() {
+    return random_generator_->RandomUint32(max_loop_control_peel_count_);
+  }
   uint32_t GetRandomLoopLimit() {
     return random_generator_->RandomUint32(max_loop_limit_);
   }
@@ -196,12 +205,6 @@
     // Ensure that the array size is non-zero.
     return random_generator_->RandomUint32(max_new_array_size_limit_ - 1) + 1;
   }
-
-  // Other functions to control transformations. Keep them in alphabetical
-  // order.
-  uint32_t GetRandomIndexForAccessChain(uint32_t composite_size_bound) {
-    return random_generator_->RandomUint32(composite_size_bound);
-  }
   bool GoDeeperInConstantObfuscation(uint32_t depth) {
     return go_deeper_in_constant_obfuscation_(depth, random_generator_);
   }
@@ -251,6 +254,7 @@
   // Limits associated with various quantities for which random values are
   // chosen during fuzzing.
   // Keep them in alphabetical order.
+  uint32_t max_equivalence_class_size_for_data_synonym_fact_closure_;
   uint32_t max_loop_control_partial_count_;
   uint32_t max_loop_control_peel_count_;
   uint32_t max_loop_limit_;
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass.cpp b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass.cpp
index a76f10d..dbe5143 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass.cpp
@@ -14,6 +14,8 @@
 
 #include "source/fuzz/fuzzer_pass.h"
 
+#include <set>
+
 #include "source/fuzz/fuzzer_util.h"
 #include "source/fuzz/instruction_descriptor.h"
 #include "source/fuzz/transformation_add_constant_boolean.h"
@@ -31,11 +33,12 @@
 namespace spvtools {
 namespace fuzz {
 
-FuzzerPass::FuzzerPass(opt::IRContext* ir_context, FactManager* fact_manager,
+FuzzerPass::FuzzerPass(opt::IRContext* ir_context,
+                       TransformationContext* transformation_context,
                        FuzzerContext* fuzzer_context,
                        protobufs::TransformationSequence* transformations)
     : ir_context_(ir_context),
-      fact_manager_(fact_manager),
+      transformation_context_(transformation_context),
       fuzzer_context_(fuzzer_context),
       transformations_(transformations) {}
 
@@ -328,43 +331,72 @@
 }
 
 std::pair<std::vector<uint32_t>, std::map<uint32_t, std::vector<uint32_t>>>
-FuzzerPass::GetAvailableBaseTypesAndPointers(
+FuzzerPass::GetAvailableBasicTypesAndPointers(
     SpvStorageClass storage_class) const {
-  // Records all of the base types available in the module.
-  std::vector<uint32_t> base_types;
+  // Records all of the basic types available in the module.
+  std::set<uint32_t> basic_types;
 
-  // For each base type, records all the associated pointer types that target
-  // that base type and that have |storage_class| as their storage class.
-  std::map<uint32_t, std::vector<uint32_t>> base_type_to_pointers;
+  // For each basic type, records all the associated pointer types that target
+  // the basic type and that have |storage_class| as their storage class.
+  std::map<uint32_t, std::vector<uint32_t>> basic_type_to_pointers;
 
   for (auto& inst : GetIRContext()->types_values()) {
+    // For each basic type that we come across, record type, and the fact that
+    // we cannot yet have seen any pointers that use the basic type as its
+    // pointee type.
+    //
+    // For pointer types with basic pointee types, associate the pointer type
+    // with the basic type.
     switch (inst.opcode()) {
-      case SpvOpTypeArray:
       case SpvOpTypeBool:
       case SpvOpTypeFloat:
       case SpvOpTypeInt:
       case SpvOpTypeMatrix:
-      case SpvOpTypeStruct:
       case SpvOpTypeVector:
-        // These types are suitable as pointer base types.  Record the type,
-        // and the fact that we cannot yet have seen any pointers that use this
-        // as its base type.
-        base_types.push_back(inst.result_id());
-        base_type_to_pointers.insert({inst.result_id(), {}});
+        // These are all basic types.
+        basic_types.insert(inst.result_id());
+        basic_type_to_pointers.insert({inst.result_id(), {}});
         break;
-      case SpvOpTypePointer:
-        if (inst.GetSingleWordInOperand(0) == storage_class) {
-          // The pointer has the desired storage class, so we are interested in
-          // it.  Associate it with its base type.
-          base_type_to_pointers.at(inst.GetSingleWordInOperand(1))
-              .push_back(inst.result_id());
+      case SpvOpTypeArray:
+        // An array type is basic if its base type is basic.
+        if (basic_types.count(inst.GetSingleWordInOperand(0))) {
+          basic_types.insert(inst.result_id());
+          basic_type_to_pointers.insert({inst.result_id(), {}});
         }
         break;
+      case SpvOpTypeStruct: {
+        // A struct type is basic if all of its members are basic.
+        bool all_members_are_basic_types = true;
+        for (uint32_t i = 0; i < inst.NumInOperands(); i++) {
+          if (!basic_types.count(inst.GetSingleWordInOperand(i))) {
+            all_members_are_basic_types = false;
+            break;
+          }
+        }
+        if (all_members_are_basic_types) {
+          basic_types.insert(inst.result_id());
+          basic_type_to_pointers.insert({inst.result_id(), {}});
+        }
+        break;
+      }
+      case SpvOpTypePointer: {
+        // We are interested in the pointer if its pointee type is basic and it
+        // has the right storage class.
+        auto pointee_type = inst.GetSingleWordInOperand(1);
+        if (inst.GetSingleWordInOperand(0) == storage_class &&
+            basic_types.count(pointee_type)) {
+          // The pointer has the desired storage class, and its pointee type is
+          // a basic type, so we are interested in it.  Associate it with its
+          // basic type.
+          basic_type_to_pointers.at(pointee_type).push_back(inst.result_id());
+        }
+        break;
+      }
       default:
         break;
     }
   }
-  return {base_types, base_type_to_pointers};
+  return {{basic_types.begin(), basic_types.end()}, basic_type_to_pointers};
 }
 
 uint32_t FuzzerPass::FindOrCreateZeroConstant(
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass.h b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass.h
index 46ee408..94b8dfa 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass.h
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass.h
@@ -18,9 +18,9 @@
 #include <functional>
 #include <vector>
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/fuzzer_context.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -29,22 +29,25 @@
 // Interface for applying a pass of transformations to a module.
 class FuzzerPass {
  public:
-  FuzzerPass(opt::IRContext* ir_context, FactManager* fact_manager,
+  FuzzerPass(opt::IRContext* ir_context,
+             TransformationContext* transformation_context,
              FuzzerContext* fuzzer_context,
              protobufs::TransformationSequence* transformations);
 
   virtual ~FuzzerPass();
 
   // Applies the pass to the module |ir_context_|, assuming and updating
-  // facts from |fact_manager_|, and using |fuzzer_context_| to guide the
-  // process.  Appends to |transformations_| all transformations that were
-  // applied during the pass.
+  // information from |transformation_context_|, and using |fuzzer_context_| to
+  // guide the process.  Appends to |transformations_| all transformations that
+  // were applied during the pass.
   virtual void Apply() = 0;
 
  protected:
   opt::IRContext* GetIRContext() const { return ir_context_; }
 
-  FactManager* GetFactManager() const { return fact_manager_; }
+  TransformationContext* GetTransformationContext() const {
+    return transformation_context_;
+  }
 
   FuzzerContext* GetFuzzerContext() const { return fuzzer_context_; }
 
@@ -93,9 +96,10 @@
   // by construction, and adding it to the sequence of applied transformations.
   template <typename TransformationType>
   void ApplyTransformation(const TransformationType& transformation) {
-    assert(transformation.IsApplicable(GetIRContext(), *GetFactManager()) &&
+    assert(transformation.IsApplicable(GetIRContext(),
+                                       *GetTransformationContext()) &&
            "Transformation should be applicable by construction.");
-    transformation.Apply(GetIRContext(), GetFactManager());
+    transformation.Apply(GetIRContext(), GetTransformationContext());
     *GetTransformations()->add_transformation() = transformation.ToMessage();
   }
 
@@ -165,18 +169,21 @@
   // If no such instruction exists, a transformation is applied to add it.
   uint32_t FindOrCreateGlobalUndef(uint32_t type_id);
 
-  // Yields a pair, (base_type_ids, base_type_ids_to_pointers), such that:
-  // - base_type_ids captures every scalar or composite type declared in the
-  //   module (i.e., all int, bool, float, vector, matrix, struct and array
-  //   types
-  // - base_type_ids_to_pointers maps every such base type to the sequence
+  // Define a *basic type* to be an integer, boolean or floating-point type,
+  // or a matrix, vector, struct or fixed-size array built from basic types.  In
+  // particular, a basic type cannot contain an opaque type (such as an image),
+  // or a runtime-sized array.
+  //
+  // Yields a pair, (basic_type_ids, basic_type_ids_to_pointers), such that:
+  // - basic_type_ids captures every basic type declared in the module.
+  // - basic_type_ids_to_pointers maps every such basic type to the sequence
   //   of all pointer types that have storage class |storage_class| and the
-  //   given base type as their pointee type.  The sequence may be empty for
-  //   some base types if no pointers to those types are defined for the given
+  //   given basic type as their pointee type.  The sequence may be empty for
+  //   some basic types if no pointers to those types are defined for the given
   //   storage class, and the sequence will have multiple elements if there are
-  //   repeated pointer declarations for the same base type and storage class.
+  //   repeated pointer declarations for the same basic type and storage class.
   std::pair<std::vector<uint32_t>, std::map<uint32_t, std::vector<uint32_t>>>
-  GetAvailableBaseTypesAndPointers(SpvStorageClass storage_class) const;
+  GetAvailableBasicTypesAndPointers(SpvStorageClass storage_class) const;
 
   // Given a type id, |scalar_or_composite_type_id|, which must correspond to
   // some scalar or composite type, returns the result id of an instruction
@@ -230,7 +237,7 @@
       const std::vector<uint32_t>& constant_ids);
 
   opt::IRContext* ir_context_;
-  FactManager* fact_manager_;
+  TransformationContext* transformation_context_;
   FuzzerContext* fuzzer_context_;
   protobufs::TransformationSequence* transformations_;
 };
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_access_chains.cpp b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_access_chains.cpp
index cfc2812..b9c1eed 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_access_chains.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_access_chains.cpp
@@ -21,10 +21,11 @@
 namespace fuzz {
 
 FuzzerPassAddAccessChains::FuzzerPassAddAccessChains(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassAddAccessChains::~FuzzerPassAddAccessChains() = default;
 
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_access_chains.h b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_access_chains.h
index 7e8ed61..8649296 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_access_chains.h
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_access_chains.h
@@ -26,7 +26,7 @@
 class FuzzerPassAddAccessChains : public FuzzerPass {
  public:
   FuzzerPassAddAccessChains(opt::IRContext* ir_context,
-                            FactManager* fact_manager,
+                            TransformationContext* transformation_context,
                             FuzzerContext* fuzzer_context,
                             protobufs::TransformationSequence* transformations);
 
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_composite_types.cpp b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_composite_types.cpp
index 32c720e..9b0dda8 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_composite_types.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_composite_types.cpp
@@ -22,10 +22,11 @@
 namespace fuzz {
 
 FuzzerPassAddCompositeTypes::FuzzerPassAddCompositeTypes(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassAddCompositeTypes::~FuzzerPassAddCompositeTypes() = default;
 
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_composite_types.h b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_composite_types.h
index 29d4bb8..87bc0ff 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_composite_types.h
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_composite_types.h
@@ -25,7 +25,7 @@
 class FuzzerPassAddCompositeTypes : public FuzzerPass {
  public:
   FuzzerPassAddCompositeTypes(
-      opt::IRContext* ir_context, FactManager* fact_manager,
+      opt::IRContext* ir_context, TransformationContext* transformation_context,
       FuzzerContext* fuzzer_context,
       protobufs::TransformationSequence* transformations);
 
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_dead_blocks.cpp b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_dead_blocks.cpp
index c9bc9c4..4e9db1f 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_dead_blocks.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_dead_blocks.cpp
@@ -21,10 +21,11 @@
 namespace fuzz {
 
 FuzzerPassAddDeadBlocks::FuzzerPassAddDeadBlocks(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassAddDeadBlocks::~FuzzerPassAddDeadBlocks() = default;
 
@@ -53,8 +54,9 @@
   }
   // Apply all those transformations that are in fact applicable.
   for (auto& transformation : candidate_transformations) {
-    if (transformation.IsApplicable(GetIRContext(), *GetFactManager())) {
-      transformation.Apply(GetIRContext(), GetFactManager());
+    if (transformation.IsApplicable(GetIRContext(),
+                                    *GetTransformationContext())) {
+      transformation.Apply(GetIRContext(), GetTransformationContext());
       *GetTransformations()->add_transformation() = transformation.ToMessage();
     }
   }
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_dead_blocks.h b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_dead_blocks.h
index 01e3843..d78f088 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_dead_blocks.h
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_dead_blocks.h
@@ -24,7 +24,8 @@
 // passes can then manipulate such blocks.
 class FuzzerPassAddDeadBlocks : public FuzzerPass {
  public:
-  FuzzerPassAddDeadBlocks(opt::IRContext* ir_context, FactManager* fact_manager,
+  FuzzerPassAddDeadBlocks(opt::IRContext* ir_context,
+                          TransformationContext* transformation_context,
                           FuzzerContext* fuzzer_context,
                           protobufs::TransformationSequence* transformations);
 
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_dead_breaks.cpp b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_dead_breaks.cpp
index aefc2fc..6b171dc 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_dead_breaks.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_dead_breaks.cpp
@@ -21,10 +21,11 @@
 namespace fuzz {
 
 FuzzerPassAddDeadBreaks::FuzzerPassAddDeadBreaks(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassAddDeadBreaks::~FuzzerPassAddDeadBreaks() = default;
 
@@ -79,8 +80,8 @@
         auto candidate_transformation = TransformationAddDeadBreak(
             block.id(), merge_block->id(), GetFuzzerContext()->ChooseEven(),
             std::move(phi_ids));
-        if (candidate_transformation.IsApplicable(GetIRContext(),
-                                                  *GetFactManager())) {
+        if (candidate_transformation.IsApplicable(
+                GetIRContext(), *GetTransformationContext())) {
           // Only consider a transformation as a candidate if it is applicable.
           candidate_transformations.push_back(
               std::move(candidate_transformation));
@@ -109,10 +110,11 @@
     candidate_transformations.erase(candidate_transformations.begin() + index);
     // Probabilistically decide whether to try to apply it vs. ignore it, in the
     // case that it is applicable.
-    if (transformation.IsApplicable(GetIRContext(), *GetFactManager()) &&
+    if (transformation.IsApplicable(GetIRContext(),
+                                    *GetTransformationContext()) &&
         GetFuzzerContext()->ChoosePercentage(
             GetFuzzerContext()->GetChanceOfAddingDeadBreak())) {
-      transformation.Apply(GetIRContext(), GetFactManager());
+      transformation.Apply(GetIRContext(), GetTransformationContext());
       *GetTransformations()->add_transformation() = transformation.ToMessage();
     }
   }
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_dead_breaks.h b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_dead_breaks.h
index 12a5095..c379eed 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_dead_breaks.h
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_dead_breaks.h
@@ -23,7 +23,8 @@
 // A fuzzer pass for adding dead break edges to the module.
 class FuzzerPassAddDeadBreaks : public FuzzerPass {
  public:
-  FuzzerPassAddDeadBreaks(opt::IRContext* ir_context, FactManager* fact_manager,
+  FuzzerPassAddDeadBreaks(opt::IRContext* ir_context,
+                          TransformationContext* transformation_context,
                           FuzzerContext* fuzzer_context,
                           protobufs::TransformationSequence* transformations);
 
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_dead_continues.cpp b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_dead_continues.cpp
index 852df3d..b8f07fb 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_dead_continues.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_dead_continues.cpp
@@ -21,10 +21,11 @@
 namespace fuzz {
 
 FuzzerPassAddDeadContinues::FuzzerPassAddDeadContinues(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassAddDeadContinues::~FuzzerPassAddDeadContinues() = default;
 
@@ -75,10 +76,11 @@
       // Probabilistically decide whether to apply the transformation in the
       // case that it is applicable.
       if (candidate_transformation.IsApplicable(GetIRContext(),
-                                                *GetFactManager()) &&
+                                                *GetTransformationContext()) &&
           GetFuzzerContext()->ChoosePercentage(
               GetFuzzerContext()->GetChanceOfAddingDeadContinue())) {
-        candidate_transformation.Apply(GetIRContext(), GetFactManager());
+        candidate_transformation.Apply(GetIRContext(),
+                                       GetTransformationContext());
         *GetTransformations()->add_transformation() =
             candidate_transformation.ToMessage();
       }
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_dead_continues.h b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_dead_continues.h
index d067f1c..b2acb93 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_dead_continues.h
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_dead_continues.h
@@ -24,7 +24,7 @@
 class FuzzerPassAddDeadContinues : public FuzzerPass {
  public:
   FuzzerPassAddDeadContinues(
-      opt::IRContext* ir_context, FactManager* fact_manager,
+      opt::IRContext* ir_context, TransformationContext* transformation_context,
       FuzzerContext* fuzzer_context,
       protobufs::TransformationSequence* transformations);
 
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_equation_instructions.cpp b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_equation_instructions.cpp
index 7f34344..49c4a8a 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_equation_instructions.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_equation_instructions.cpp
@@ -23,10 +23,11 @@
 namespace fuzz {
 
 FuzzerPassAddEquationInstructions::FuzzerPassAddEquationInstructions(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassAddEquationInstructions::~FuzzerPassAddEquationInstructions() =
     default;
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_equation_instructions.h b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_equation_instructions.h
index 84229c0..6e64977 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_equation_instructions.h
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_equation_instructions.h
@@ -27,7 +27,7 @@
 class FuzzerPassAddEquationInstructions : public FuzzerPass {
  public:
   FuzzerPassAddEquationInstructions(
-      opt::IRContext* ir_context, FactManager* fact_manager,
+      opt::IRContext* ir_context, TransformationContext* transformation_context,
       FuzzerContext* fuzzer_context,
       protobufs::TransformationSequence* transformations);
 
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_function_calls.cpp b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_function_calls.cpp
index 545aa16..569df10 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_function_calls.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_function_calls.cpp
@@ -24,10 +24,11 @@
 namespace fuzz {
 
 FuzzerPassAddFunctionCalls::FuzzerPassAddFunctionCalls(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassAddFunctionCalls::~FuzzerPassAddFunctionCalls() = default;
 
@@ -74,8 +75,9 @@
         while (!candidate_functions.empty()) {
           opt::Function* candidate_function =
               GetFuzzerContext()->RemoveAtRandomIndex(&candidate_functions);
-          if (!GetFactManager()->BlockIsDead(block->id()) &&
-              !GetFactManager()->FunctionIsLivesafe(
+          if (!GetTransformationContext()->GetFactManager()->BlockIsDead(
+                  block->id()) &&
+              !GetTransformationContext()->GetFactManager()->FunctionIsLivesafe(
                   candidate_function->result_id())) {
             // Unless in a dead block, only livesafe functions can be invoked
             continue;
@@ -132,9 +134,11 @@
                 default:
                   return false;
               }
-              if (!GetFactManager()->BlockIsDead(block->id()) &&
-                  !GetFactManager()->PointeeValueIsIrrelevant(
-                      inst->result_id())) {
+              if (!GetTransformationContext()->GetFactManager()->BlockIsDead(
+                      block->id()) &&
+                  !GetTransformationContext()
+                       ->GetFactManager()
+                       ->PointeeValueIsIrrelevant(inst->result_id())) {
                 // We can only pass a pointer as an actual parameter
                 // if the pointee value for the pointer is irrelevant,
                 // or if the block from which we would make the
@@ -210,8 +214,9 @@
         result.push_back(fresh_variable_id);
 
         // Now bring the variable into existence.
-        if (type_instruction->GetSingleWordInOperand(0) ==
-            SpvStorageClassFunction) {
+        auto storage_class = static_cast<SpvStorageClass>(
+            type_instruction->GetSingleWordInOperand(0));
+        if (storage_class == SpvStorageClassFunction) {
           // Add a new zero-initialized local variable to the current
           // function, noting that its pointee value is irrelevant.
           ApplyTransformation(TransformationAddLocalVariable(
@@ -220,16 +225,19 @@
                   type_instruction->GetSingleWordInOperand(1)),
               true));
         } else {
-          assert(type_instruction->GetSingleWordInOperand(0) ==
-                     SpvStorageClassPrivate &&
-                 "Only Function and Private storage classes are "
+          assert((storage_class == SpvStorageClassPrivate ||
+                  storage_class == SpvStorageClassWorkgroup) &&
+                 "Only Function, Private and Workgroup storage classes are "
                  "supported at present.");
-          // Add a new zero-initialized global variable to the module,
-          // noting that its pointee value is irrelevant.
+          // Add a new global variable to the module, zero-initializing it if
+          // it has Private storage class, and noting that its pointee value is
+          // irrelevant.
           ApplyTransformation(TransformationAddGlobalVariable(
-              fresh_variable_id, arg_type_id,
-              FindOrCreateZeroConstant(
-                  type_instruction->GetSingleWordInOperand(1)),
+              fresh_variable_id, arg_type_id, storage_class,
+              storage_class == SpvStorageClassPrivate
+                  ? FindOrCreateZeroConstant(
+                        type_instruction->GetSingleWordInOperand(1))
+                  : 0,
               true));
         }
       } else {
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_function_calls.h b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_function_calls.h
index 5d184fd..8f75e8c 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_function_calls.h
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_function_calls.h
@@ -25,7 +25,7 @@
 class FuzzerPassAddFunctionCalls : public FuzzerPass {
  public:
   FuzzerPassAddFunctionCalls(
-      opt::IRContext* ir_context, FactManager* fact_manager,
+      opt::IRContext* ir_context, TransformationContext* transformation_context,
       FuzzerContext* fuzzer_context,
       protobufs::TransformationSequence* transformations);
 
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_global_variables.cpp b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_global_variables.cpp
index 1371f46..4023b22 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_global_variables.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_global_variables.cpp
@@ -21,53 +21,56 @@
 namespace fuzz {
 
 FuzzerPassAddGlobalVariables::FuzzerPassAddGlobalVariables(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassAddGlobalVariables::~FuzzerPassAddGlobalVariables() = default;
 
 void FuzzerPassAddGlobalVariables::Apply() {
-  auto base_type_ids_and_pointers =
-      GetAvailableBaseTypesAndPointers(SpvStorageClassPrivate);
+  auto basic_type_ids_and_pointers =
+      GetAvailableBasicTypesAndPointers(SpvStorageClassPrivate);
 
-  // These are the base types that are available to this fuzzer pass.
-  auto& base_types = base_type_ids_and_pointers.first;
+  // These are the basic types that are available to this fuzzer pass.
+  auto& basic_types = basic_type_ids_and_pointers.first;
 
-  // These are the pointers to those base types that are *initially* available
+  // These are the pointers to those basic types that are *initially* available
   // to the fuzzer pass.  The fuzzer pass might add pointer types in cases where
-  // none are available for a given base type.
-  auto& base_type_to_pointers = base_type_ids_and_pointers.second;
+  // none are available for a given basic type.
+  auto& basic_type_to_pointers = basic_type_ids_and_pointers.second;
 
   // Probabilistically keep adding global variables.
   while (GetFuzzerContext()->ChoosePercentage(
       GetFuzzerContext()->GetChanceOfAddingGlobalVariable())) {
-    // Choose a random base type; the new variable's type will be a pointer to
-    // this base type.
-    uint32_t base_type =
-        base_types[GetFuzzerContext()->RandomIndex(base_types)];
+    // Choose a random basic type; the new variable's type will be a pointer to
+    // this basic type.
+    uint32_t basic_type =
+        basic_types[GetFuzzerContext()->RandomIndex(basic_types)];
     uint32_t pointer_type_id;
-    std::vector<uint32_t>& available_pointers_to_base_type =
-        base_type_to_pointers.at(base_type);
-    // Determine whether there is at least one pointer to this base type.
-    if (available_pointers_to_base_type.empty()) {
+    std::vector<uint32_t>& available_pointers_to_basic_type =
+        basic_type_to_pointers.at(basic_type);
+    // Determine whether there is at least one pointer to this basic type.
+    if (available_pointers_to_basic_type.empty()) {
       // There is not.  Make one, to use here, and add it to the available
-      // pointers for the base type so that future variables can potentially
+      // pointers for the basic type so that future variables can potentially
       // use it.
       pointer_type_id = GetFuzzerContext()->GetFreshId();
-      available_pointers_to_base_type.push_back(pointer_type_id);
+      available_pointers_to_basic_type.push_back(pointer_type_id);
       ApplyTransformation(TransformationAddTypePointer(
-          pointer_type_id, SpvStorageClassPrivate, base_type));
+          pointer_type_id, SpvStorageClassPrivate, basic_type));
     } else {
       // There is - grab one.
       pointer_type_id =
-          available_pointers_to_base_type[GetFuzzerContext()->RandomIndex(
-              available_pointers_to_base_type)];
+          available_pointers_to_basic_type[GetFuzzerContext()->RandomIndex(
+              available_pointers_to_basic_type)];
     }
+    // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3274):  We could
+    //  add new variables with Workgroup storage class in compute shaders.
     ApplyTransformation(TransformationAddGlobalVariable(
         GetFuzzerContext()->GetFreshId(), pointer_type_id,
-        FindOrCreateZeroConstant(base_type), true));
+        SpvStorageClassPrivate, FindOrCreateZeroConstant(basic_type), true));
   }
 }
 
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_global_variables.h b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_global_variables.h
index c71d147..a907d36 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_global_variables.h
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_global_variables.h
@@ -25,7 +25,7 @@
 class FuzzerPassAddGlobalVariables : public FuzzerPass {
  public:
   FuzzerPassAddGlobalVariables(
-      opt::IRContext* ir_context, FactManager* fact_manager,
+      opt::IRContext* ir_context, TransformationContext* transformation_context,
       FuzzerContext* fuzzer_context,
       protobufs::TransformationSequence* transformations);
 
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_loads.cpp b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_loads.cpp
index 851787f..16d88e3 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_loads.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_loads.cpp
@@ -21,10 +21,11 @@
 namespace fuzz {
 
 FuzzerPassAddLoads::FuzzerPassAddLoads(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassAddLoads::~FuzzerPassAddLoads() = default;
 
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_loads.h b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_loads.h
index 125bc5d..c4d5b27 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_loads.h
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_loads.h
@@ -23,7 +23,8 @@
 // Fuzzer pass that adds stores, at random, from pointers in the module.
 class FuzzerPassAddLoads : public FuzzerPass {
  public:
-  FuzzerPassAddLoads(opt::IRContext* ir_context, FactManager* fact_manager,
+  FuzzerPassAddLoads(opt::IRContext* ir_context,
+                     TransformationContext* transformation_context,
                      FuzzerContext* fuzzer_context,
                      protobufs::TransformationSequence* transformations);
 
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_local_variables.cpp b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_local_variables.cpp
index 8d6d80d..661159e 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_local_variables.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_local_variables.cpp
@@ -22,55 +22,56 @@
 namespace fuzz {
 
 FuzzerPassAddLocalVariables::FuzzerPassAddLocalVariables(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassAddLocalVariables::~FuzzerPassAddLocalVariables() = default;
 
 void FuzzerPassAddLocalVariables::Apply() {
-  auto base_type_ids_and_pointers =
-      GetAvailableBaseTypesAndPointers(SpvStorageClassFunction);
+  auto basic_type_ids_and_pointers =
+      GetAvailableBasicTypesAndPointers(SpvStorageClassFunction);
 
-  // These are the base types that are available to this fuzzer pass.
-  auto& base_types = base_type_ids_and_pointers.first;
+  // These are the basic types that are available to this fuzzer pass.
+  auto& basic_types = basic_type_ids_and_pointers.first;
 
-  // These are the pointers to those base types that are *initially* available
+  // These are the pointers to those basic types that are *initially* available
   // to the fuzzer pass.  The fuzzer pass might add pointer types in cases where
-  // none are available for a given base type.
-  auto& base_type_to_pointers = base_type_ids_and_pointers.second;
+  // none are available for a given basic type.
+  auto& basic_type_to_pointers = basic_type_ids_and_pointers.second;
 
   // Consider every function in the module.
   for (auto& function : *GetIRContext()->module()) {
     // Probabilistically keep adding random variables to this function.
     while (GetFuzzerContext()->ChoosePercentage(
         GetFuzzerContext()->GetChanceOfAddingLocalVariable())) {
-      // Choose a random base type; the new variable's type will be a pointer to
-      // this base type.
-      uint32_t base_type =
-          base_types[GetFuzzerContext()->RandomIndex(base_types)];
+      // Choose a random basic type; the new variable's type will be a pointer
+      // to this basic type.
+      uint32_t basic_type =
+          basic_types[GetFuzzerContext()->RandomIndex(basic_types)];
       uint32_t pointer_type;
-      std::vector<uint32_t>& available_pointers_to_base_type =
-          base_type_to_pointers.at(base_type);
-      // Determine whether there is at least one pointer to this base type.
-      if (available_pointers_to_base_type.empty()) {
+      std::vector<uint32_t>& available_pointers_to_basic_type =
+          basic_type_to_pointers.at(basic_type);
+      // Determine whether there is at least one pointer to this basic type.
+      if (available_pointers_to_basic_type.empty()) {
         // There is not.  Make one, to use here, and add it to the available
-        // pointers for the base type so that future variables can potentially
+        // pointers for the basic type so that future variables can potentially
         // use it.
         pointer_type = GetFuzzerContext()->GetFreshId();
         ApplyTransformation(TransformationAddTypePointer(
-            pointer_type, SpvStorageClassFunction, base_type));
-        available_pointers_to_base_type.push_back(pointer_type);
+            pointer_type, SpvStorageClassFunction, basic_type));
+        available_pointers_to_basic_type.push_back(pointer_type);
       } else {
         // There is - grab one.
         pointer_type =
-            available_pointers_to_base_type[GetFuzzerContext()->RandomIndex(
-                available_pointers_to_base_type)];
+            available_pointers_to_basic_type[GetFuzzerContext()->RandomIndex(
+                available_pointers_to_basic_type)];
       }
       ApplyTransformation(TransformationAddLocalVariable(
           GetFuzzerContext()->GetFreshId(), pointer_type, function.result_id(),
-          FindOrCreateZeroConstant(base_type), true));
+          FindOrCreateZeroConstant(basic_type), true));
     }
   }
 }
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_local_variables.h b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_local_variables.h
index eed3665..08d26d8 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_local_variables.h
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_local_variables.h
@@ -25,7 +25,7 @@
 class FuzzerPassAddLocalVariables : public FuzzerPass {
  public:
   FuzzerPassAddLocalVariables(
-      opt::IRContext* ir_context, FactManager* fact_manager,
+      opt::IRContext* ir_context, TransformationContext* transformation_context,
       FuzzerContext* fuzzer_context,
       protobufs::TransformationSequence* transformations);
 
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_no_contraction_decorations.cpp b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_no_contraction_decorations.cpp
index 82fb539..09627d0 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_no_contraction_decorations.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_no_contraction_decorations.cpp
@@ -20,10 +20,11 @@
 namespace fuzz {
 
 FuzzerPassAddNoContractionDecorations::FuzzerPassAddNoContractionDecorations(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassAddNoContractionDecorations::
     ~FuzzerPassAddNoContractionDecorations() = default;
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_no_contraction_decorations.h b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_no_contraction_decorations.h
index abe5bd7..f32e5bc 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_no_contraction_decorations.h
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_no_contraction_decorations.h
@@ -24,7 +24,7 @@
 class FuzzerPassAddNoContractionDecorations : public FuzzerPass {
  public:
   FuzzerPassAddNoContractionDecorations(
-      opt::IRContext* ir_context, FactManager* fact_manager,
+      opt::IRContext* ir_context, TransformationContext* transformation_context,
       FuzzerContext* fuzzer_context,
       protobufs::TransformationSequence* transformations);
 
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_stores.cpp b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_stores.cpp
index 794ddc3..e8871be 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_stores.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_stores.cpp
@@ -21,10 +21,11 @@
 namespace fuzz {
 
 FuzzerPassAddStores::FuzzerPassAddStores(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassAddStores::~FuzzerPassAddStores() = default;
 
@@ -82,9 +83,13 @@
                     default:
                       break;
                   }
-                  return GetFactManager()->BlockIsDead(block->id()) ||
-                         GetFactManager()->PointeeValueIsIrrelevant(
-                             instruction->result_id());
+                  return GetTransformationContext()
+                             ->GetFactManager()
+                             ->BlockIsDead(block->id()) ||
+                         GetTransformationContext()
+                             ->GetFactManager()
+                             ->PointeeValueIsIrrelevant(
+                                 instruction->result_id());
                 });
 
         // At this point, |relevant_pointers| contains all the pointers we might
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_stores.h b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_stores.h
index 9daa9e0..55ec67f 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_stores.h
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_stores.h
@@ -25,7 +25,8 @@
 // are known not to affect the module's overall behaviour.
 class FuzzerPassAddStores : public FuzzerPass {
  public:
-  FuzzerPassAddStores(opt::IRContext* ir_context, FactManager* fact_manager,
+  FuzzerPassAddStores(opt::IRContext* ir_context,
+                      TransformationContext* transformation_context,
                       FuzzerContext* fuzzer_context,
                       protobufs::TransformationSequence* transformations);
 
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_useful_constructs.cpp b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_useful_constructs.cpp
index 8552dfd..a267612 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_useful_constructs.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_useful_constructs.cpp
@@ -25,10 +25,11 @@
 namespace fuzz {
 
 FuzzerPassAddUsefulConstructs::FuzzerPassAddUsefulConstructs(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassAddUsefulConstructs::~FuzzerPassAddUsefulConstructs() = default;
 
@@ -49,9 +50,10 @@
     TransformationAddConstantScalar add_constant_int =
         TransformationAddConstantScalar(GetFuzzerContext()->GetFreshId(),
                                         int_type_id, data);
-    assert(add_constant_int.IsApplicable(GetIRContext(), *GetFactManager()) &&
+    assert(add_constant_int.IsApplicable(GetIRContext(),
+                                         *GetTransformationContext()) &&
            "Should be applicable by construction.");
-    add_constant_int.Apply(GetIRContext(), GetFactManager());
+    add_constant_int.Apply(GetIRContext(), GetTransformationContext());
     *GetTransformations()->add_transformation() = add_constant_int.ToMessage();
   }
 }
@@ -75,9 +77,10 @@
     TransformationAddConstantScalar add_constant_float =
         TransformationAddConstantScalar(GetFuzzerContext()->GetFreshId(),
                                         float_type_id, data);
-    assert(add_constant_float.IsApplicable(GetIRContext(), *GetFactManager()) &&
+    assert(add_constant_float.IsApplicable(GetIRContext(),
+                                           *GetTransformationContext()) &&
            "Should be applicable by construction.");
-    add_constant_float.Apply(GetIRContext(), GetFactManager());
+    add_constant_float.Apply(GetIRContext(), GetTransformationContext());
     *GetTransformations()->add_transformation() =
         add_constant_float.ToMessage();
   }
@@ -90,9 +93,10 @@
     if (!GetIRContext()->get_type_mgr()->GetId(&temp_bool_type)) {
       auto add_type_boolean =
           TransformationAddTypeBoolean(GetFuzzerContext()->GetFreshId());
-      assert(add_type_boolean.IsApplicable(GetIRContext(), *GetFactManager()) &&
+      assert(add_type_boolean.IsApplicable(GetIRContext(),
+                                           *GetTransformationContext()) &&
              "Should be applicable by construction.");
-      add_type_boolean.Apply(GetIRContext(), GetFactManager());
+      add_type_boolean.Apply(GetIRContext(), GetTransformationContext());
       *GetTransformations()->add_transformation() =
           add_type_boolean.ToMessage();
     }
@@ -105,9 +109,10 @@
       if (!GetIRContext()->get_type_mgr()->GetId(&temp_int_type)) {
         TransformationAddTypeInt add_type_int = TransformationAddTypeInt(
             GetFuzzerContext()->GetFreshId(), 32, is_signed);
-        assert(add_type_int.IsApplicable(GetIRContext(), *GetFactManager()) &&
+        assert(add_type_int.IsApplicable(GetIRContext(),
+                                         *GetTransformationContext()) &&
                "Should be applicable by construction.");
-        add_type_int.Apply(GetIRContext(), GetFactManager());
+        add_type_int.Apply(GetIRContext(), GetTransformationContext());
         *GetTransformations()->add_transformation() = add_type_int.ToMessage();
       }
     }
@@ -119,9 +124,10 @@
     if (!GetIRContext()->get_type_mgr()->GetId(&temp_float_type)) {
       TransformationAddTypeFloat add_type_float =
           TransformationAddTypeFloat(GetFuzzerContext()->GetFreshId(), 32);
-      assert(add_type_float.IsApplicable(GetIRContext(), *GetFactManager()) &&
+      assert(add_type_float.IsApplicable(GetIRContext(),
+                                         *GetTransformationContext()) &&
              "Should be applicable by construction.");
-      add_type_float.Apply(GetIRContext(), GetFactManager());
+      add_type_float.Apply(GetIRContext(), GetTransformationContext());
       *GetTransformations()->add_transformation() = add_type_float.ToMessage();
     }
   }
@@ -139,9 +145,9 @@
       TransformationAddConstantBoolean add_constant_boolean(
           GetFuzzerContext()->GetFreshId(), boolean_value);
       assert(add_constant_boolean.IsApplicable(GetIRContext(),
-                                               *GetFactManager()) &&
+                                               *GetTransformationContext()) &&
              "Should be applicable by construction.");
-      add_constant_boolean.Apply(GetIRContext(), GetFactManager());
+      add_constant_boolean.Apply(GetIRContext(), GetTransformationContext());
       *GetTransformations()->add_transformation() =
           add_constant_boolean.ToMessage();
     }
@@ -168,8 +174,9 @@
   //   of the element
   // - a signed integer constant for each index required to access the element
   // - a constant for the constant value itself
-  for (auto& fact_and_type_id :
-       GetFactManager()->GetConstantUniformFactsAndTypes()) {
+  for (auto& fact_and_type_id : GetTransformationContext()
+                                    ->GetFactManager()
+                                    ->GetConstantUniformFactsAndTypes()) {
     uint32_t element_type_id = fact_and_type_id.second;
     assert(element_type_id);
     auto element_type =
@@ -183,9 +190,10 @@
       auto add_pointer =
           TransformationAddTypePointer(GetFuzzerContext()->GetFreshId(),
                                        SpvStorageClassUniform, element_type_id);
-      assert(add_pointer.IsApplicable(GetIRContext(), *GetFactManager()) &&
+      assert(add_pointer.IsApplicable(GetIRContext(),
+                                      *GetTransformationContext()) &&
              "Should be applicable by construction.");
-      add_pointer.Apply(GetIRContext(), GetFactManager());
+      add_pointer.Apply(GetIRContext(), GetTransformationContext());
       *GetTransformations()->add_transformation() = add_pointer.ToMessage();
     }
     std::vector<uint32_t> words;
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_useful_constructs.h b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_useful_constructs.h
index 7dc00f1..17e87a8 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_useful_constructs.h
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_add_useful_constructs.h
@@ -25,7 +25,7 @@
 class FuzzerPassAddUsefulConstructs : public FuzzerPass {
  public:
   FuzzerPassAddUsefulConstructs(
-      opt::IRContext* ir_context, FactManager* fact_manager,
+      opt::IRContext* ir_context, TransformationContext* transformation_context,
       FuzzerContext* fuzzer_context,
       protobufs::TransformationSequence* transformations);
 
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_adjust_function_controls.cpp b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_adjust_function_controls.cpp
index fe229bc..aa62d2f 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_adjust_function_controls.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_adjust_function_controls.cpp
@@ -20,10 +20,11 @@
 namespace fuzz {
 
 FuzzerPassAdjustFunctionControls::FuzzerPassAdjustFunctionControls(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassAdjustFunctionControls::~FuzzerPassAdjustFunctionControls() = default;
 
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_adjust_function_controls.h b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_adjust_function_controls.h
index 02d3600..e20541b 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_adjust_function_controls.h
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_adjust_function_controls.h
@@ -24,7 +24,7 @@
 class FuzzerPassAdjustFunctionControls : public FuzzerPass {
  public:
   FuzzerPassAdjustFunctionControls(
-      opt::IRContext* ir_context, FactManager* fact_manager,
+      opt::IRContext* ir_context, TransformationContext* transformation_context,
       FuzzerContext* fuzzer_context,
       protobufs::TransformationSequence* transformations);
 
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_adjust_loop_controls.cpp b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_adjust_loop_controls.cpp
index c9843d0..f7addff 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_adjust_loop_controls.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_adjust_loop_controls.cpp
@@ -20,10 +20,11 @@
 namespace fuzz {
 
 FuzzerPassAdjustLoopControls::FuzzerPassAdjustLoopControls(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassAdjustLoopControls::~FuzzerPassAdjustLoopControls() = default;
 
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_adjust_loop_controls.h b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_adjust_loop_controls.h
index e945606..ee5cd48 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_adjust_loop_controls.h
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_adjust_loop_controls.h
@@ -24,7 +24,7 @@
 class FuzzerPassAdjustLoopControls : public FuzzerPass {
  public:
   FuzzerPassAdjustLoopControls(
-      opt::IRContext* ir_context, FactManager* fact_manager,
+      opt::IRContext* ir_context, TransformationContext* transformation_context,
       FuzzerContext* fuzzer_context,
       protobufs::TransformationSequence* transformations);
 
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_adjust_memory_operands_masks.cpp b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_adjust_memory_operands_masks.cpp
index 2d3d676..32f5ea5 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_adjust_memory_operands_masks.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_adjust_memory_operands_masks.cpp
@@ -21,10 +21,11 @@
 namespace fuzz {
 
 FuzzerPassAdjustMemoryOperandsMasks::FuzzerPassAdjustMemoryOperandsMasks(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassAdjustMemoryOperandsMasks::~FuzzerPassAdjustMemoryOperandsMasks() =
     default;
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_adjust_memory_operands_masks.h b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_adjust_memory_operands_masks.h
index c3d7118..699dcb5 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_adjust_memory_operands_masks.h
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_adjust_memory_operands_masks.h
@@ -25,7 +25,7 @@
 class FuzzerPassAdjustMemoryOperandsMasks : public FuzzerPass {
  public:
   FuzzerPassAdjustMemoryOperandsMasks(
-      opt::IRContext* ir_context, FactManager* fact_manager,
+      opt::IRContext* ir_context, TransformationContext* transformation_context,
       FuzzerContext* fuzzer_context,
       protobufs::TransformationSequence* transformations);
 
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_adjust_selection_controls.cpp b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_adjust_selection_controls.cpp
index 397dfed..83b1854 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_adjust_selection_controls.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_adjust_selection_controls.cpp
@@ -20,10 +20,11 @@
 namespace fuzz {
 
 FuzzerPassAdjustSelectionControls::FuzzerPassAdjustSelectionControls(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassAdjustSelectionControls::~FuzzerPassAdjustSelectionControls() =
     default;
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_adjust_selection_controls.h b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_adjust_selection_controls.h
index b5b255c..820b30d 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_adjust_selection_controls.h
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_adjust_selection_controls.h
@@ -24,7 +24,7 @@
 class FuzzerPassAdjustSelectionControls : public FuzzerPass {
  public:
   FuzzerPassAdjustSelectionControls(
-      opt::IRContext* ir_context, FactManager* fact_manager,
+      opt::IRContext* ir_context, TransformationContext* transformation_context,
       FuzzerContext* fuzzer_context,
       protobufs::TransformationSequence* transformations);
 
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_apply_id_synonyms.cpp b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_apply_id_synonyms.cpp
index 5711f35..0ec93e1 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_apply_id_synonyms.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_apply_id_synonyms.cpp
@@ -19,32 +19,45 @@
 #include "source/fuzz/id_use_descriptor.h"
 #include "source/fuzz/instruction_descriptor.h"
 #include "source/fuzz/transformation_composite_extract.h"
+#include "source/fuzz/transformation_compute_data_synonym_fact_closure.h"
 #include "source/fuzz/transformation_replace_id_with_synonym.h"
 
 namespace spvtools {
 namespace fuzz {
 
 FuzzerPassApplyIdSynonyms::FuzzerPassApplyIdSynonyms(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassApplyIdSynonyms::~FuzzerPassApplyIdSynonyms() = default;
 
 void FuzzerPassApplyIdSynonyms::Apply() {
-  for (auto id_with_known_synonyms :
-       GetFactManager()->GetIdsForWhichSynonymsAreKnown(GetIRContext())) {
-    // Gather up all uses of |id_with_known_synonym|, and then subsequently
-    // iterate over these uses.  We use this separation because, when
-    // considering a given use, we might apply a transformation that will
+  // Compute a closure of data synonym facts, to enrich the pool of synonyms
+  // that are available.
+  ApplyTransformation(TransformationComputeDataSynonymFactClosure(
+      GetFuzzerContext()
+          ->GetMaximumEquivalenceClassSizeForDataSynonymFactClosure()));
+
+  for (auto id_with_known_synonyms : GetTransformationContext()
+                                         ->GetFactManager()
+                                         ->GetIdsForWhichSynonymsAreKnown()) {
+    // Gather up all uses of |id_with_known_synonym| as a regular id, and
+    // subsequently iterate over these uses.  We use this separation because,
+    // when considering a given use, we might apply a transformation that will
     // invalidate the def-use manager.
     std::vector<std::pair<opt::Instruction*, uint32_t>> uses;
     GetIRContext()->get_def_use_mgr()->ForEachUse(
         id_with_known_synonyms,
         [&uses](opt::Instruction* use_inst, uint32_t use_index) -> void {
-          uses.emplace_back(
-              std::pair<opt::Instruction*, uint32_t>(use_inst, use_index));
+          // We only gather up regular id uses; e.g. we do not include a use of
+          // the id as the scope for an atomic operation.
+          if (use_inst->GetOperand(use_index).type == SPV_OPERAND_TYPE_ID) {
+            uses.emplace_back(
+                std::pair<opt::Instruction*, uint32_t>(use_inst, use_index));
+          }
         });
 
     for (auto& use : uses) {
@@ -70,8 +83,9 @@
       }
 
       std::vector<const protobufs::DataDescriptor*> synonyms_to_try;
-      for (auto& data_descriptor : GetFactManager()->GetSynonymsForId(
-               id_with_known_synonyms, GetIRContext())) {
+      for (auto& data_descriptor :
+           GetTransformationContext()->GetFactManager()->GetSynonymsForId(
+               id_with_known_synonyms)) {
         protobufs::DataDescriptor descriptor_for_this_id =
             MakeDataDescriptor(id_with_known_synonyms, {});
         if (DataDescriptorEquals()(data_descriptor, &descriptor_for_this_id)) {
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_apply_id_synonyms.h b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_apply_id_synonyms.h
index 1a0748e..1a9213d 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_apply_id_synonyms.h
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_apply_id_synonyms.h
@@ -27,7 +27,7 @@
 class FuzzerPassApplyIdSynonyms : public FuzzerPass {
  public:
   FuzzerPassApplyIdSynonyms(opt::IRContext* ir_context,
-                            FactManager* fact_manager,
+                            TransformationContext* transformation_context,
                             FuzzerContext* fuzzer_context,
                             protobufs::TransformationSequence* transformations);
 
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_construct_composites.cpp b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_construct_composites.cpp
index 330b9cf..e78f8ec 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_construct_composites.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_construct_composites.cpp
@@ -25,10 +25,11 @@
 namespace fuzz {
 
 FuzzerPassConstructComposites::FuzzerPassConstructComposites(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassConstructComposites::~FuzzerPassConstructComposites() = default;
 
@@ -87,7 +88,7 @@
         // for constructing a composite of that type.  Otherwise these variables
         // will remain 0 and null respectively.
         uint32_t chosen_composite_type = 0;
-        std::unique_ptr<std::vector<uint32_t>> constructor_arguments = nullptr;
+        std::vector<uint32_t> constructor_arguments;
 
         // Initially, all composite type ids are available for us to try.  Keep
         // trying until we run out of options.
@@ -95,35 +96,38 @@
         while (!composites_to_try_constructing.empty()) {
           // Remove a composite type from the composite types left for us to
           // try.
-          auto index =
-              GetFuzzerContext()->RandomIndex(composites_to_try_constructing);
           auto next_composite_to_try_constructing =
-              composites_to_try_constructing[index];
-          composites_to_try_constructing.erase(
-              composites_to_try_constructing.begin() + index);
+              GetFuzzerContext()->RemoveAtRandomIndex(
+                  &composites_to_try_constructing);
 
           // Now try to construct a composite of this type, using an appropriate
           // helper method depending on the kind of composite type.
-          auto composite_type = GetIRContext()->get_type_mgr()->GetType(
+          auto composite_type_inst = GetIRContext()->get_def_use_mgr()->GetDef(
               next_composite_to_try_constructing);
-          if (auto array_type = composite_type->AsArray()) {
-            constructor_arguments = TryConstructingArrayComposite(
-                *array_type, type_id_to_available_instructions);
-          } else if (auto matrix_type = composite_type->AsMatrix()) {
-            constructor_arguments = TryConstructingMatrixComposite(
-                *matrix_type, type_id_to_available_instructions);
-          } else if (auto struct_type = composite_type->AsStruct()) {
-            constructor_arguments = TryConstructingStructComposite(
-                *struct_type, type_id_to_available_instructions);
-          } else {
-            auto vector_type = composite_type->AsVector();
-            assert(vector_type &&
-                   "The space of possible composite types should be covered by "
-                   "the above cases.");
-            constructor_arguments = TryConstructingVectorComposite(
-                *vector_type, type_id_to_available_instructions);
+          switch (composite_type_inst->opcode()) {
+            case SpvOpTypeArray:
+              constructor_arguments = FindComponentsToConstructArray(
+                  *composite_type_inst, type_id_to_available_instructions);
+              break;
+            case SpvOpTypeMatrix:
+              constructor_arguments = FindComponentsToConstructMatrix(
+                  *composite_type_inst, type_id_to_available_instructions);
+              break;
+            case SpvOpTypeStruct:
+              constructor_arguments = FindComponentsToConstructStruct(
+                  *composite_type_inst, type_id_to_available_instructions);
+              break;
+            case SpvOpTypeVector:
+              constructor_arguments = FindComponentsToConstructVector(
+                  *composite_type_inst, type_id_to_available_instructions);
+              break;
+            default:
+              assert(false &&
+                     "The space of possible composite types should be covered "
+                     "by the above cases.");
+              break;
           }
-          if (constructor_arguments != nullptr) {
+          if (!constructor_arguments.empty()) {
             // We succeeded!  Note the composite type we finally settled on, and
             // exit from the loop.
             chosen_composite_type = next_composite_to_try_constructing;
@@ -134,20 +138,15 @@
         if (!chosen_composite_type) {
           // We did not manage to make a composite; return 0 to indicate that no
           // instructions were added.
-          assert(constructor_arguments == nullptr);
+          assert(constructor_arguments.empty());
           return;
         }
-        assert(constructor_arguments != nullptr);
+        assert(!constructor_arguments.empty());
 
         // Make and apply a transformation.
-        TransformationCompositeConstruct transformation(
-            chosen_composite_type, *constructor_arguments,
-            instruction_descriptor, GetFuzzerContext()->GetFreshId());
-        assert(transformation.IsApplicable(GetIRContext(), *GetFactManager()) &&
-               "This transformation should be applicable by construction.");
-        transformation.Apply(GetIRContext(), GetFactManager());
-        *GetTransformations()->add_transformation() =
-            transformation.ToMessage();
+        ApplyTransformation(TransformationCompositeConstruct(
+            chosen_composite_type, constructor_arguments,
+            instruction_descriptor, GetFuzzerContext()->GetFreshId()));
       });
 }
 
@@ -160,20 +159,15 @@
   type_id_to_available_instructions->at(inst->type_id()).push_back(inst);
 }
 
-std::unique_ptr<std::vector<uint32_t>>
-FuzzerPassConstructComposites::TryConstructingArrayComposite(
-    const opt::analysis::Array& array_type,
+std::vector<uint32_t>
+FuzzerPassConstructComposites::FindComponentsToConstructArray(
+    const opt::Instruction& array_type_instruction,
     const TypeIdToInstructions& type_id_to_available_instructions) {
-  // At present we assume arrays have a constant size.
-  assert(array_type.length_info().words.size() == 2);
-  assert(array_type.length_info().words[0] ==
-         opt::analysis::Array::LengthInfo::kConstant);
-
-  auto result = MakeUnique<std::vector<uint32_t>>();
+  assert(array_type_instruction.opcode() == SpvOpTypeArray &&
+         "Precondition: instruction must be an array type.");
 
   // Get the element type for the array.
-  auto element_type_id =
-      GetIRContext()->get_type_mgr()->GetId(array_type.element_type());
+  auto element_type_id = array_type_instruction.GetSingleWordInOperand(0);
 
   // Get all instructions at our disposal that compute something of this element
   // type.
@@ -184,26 +178,34 @@
     // If there are not any instructions available that compute the element type
     // of the array then we are not in a position to construct a composite with
     // this array type.
-    return nullptr;
+    return {};
   }
-  for (uint32_t index = 0; index < array_type.length_info().words[1]; index++) {
-    result->push_back(available_instructions
-                          ->second[GetFuzzerContext()->RandomIndex(
-                              available_instructions->second)]
-                          ->result_id());
+
+  uint32_t array_length =
+      GetIRContext()
+          ->get_def_use_mgr()
+          ->GetDef(array_type_instruction.GetSingleWordInOperand(1))
+          ->GetSingleWordInOperand(0);
+
+  std::vector<uint32_t> result;
+  for (uint32_t index = 0; index < array_length; index++) {
+    result.push_back(available_instructions
+                         ->second[GetFuzzerContext()->RandomIndex(
+                             available_instructions->second)]
+                         ->result_id());
   }
   return result;
 }
 
-std::unique_ptr<std::vector<uint32_t>>
-FuzzerPassConstructComposites::TryConstructingMatrixComposite(
-    const opt::analysis::Matrix& matrix_type,
+std::vector<uint32_t>
+FuzzerPassConstructComposites::FindComponentsToConstructMatrix(
+    const opt::Instruction& matrix_type_instruction,
     const TypeIdToInstructions& type_id_to_available_instructions) {
-  auto result = MakeUnique<std::vector<uint32_t>>();
+  assert(matrix_type_instruction.opcode() == SpvOpTypeMatrix &&
+         "Precondition: instruction must be a matrix type.");
 
   // Get the element type for the matrix.
-  auto element_type_id =
-      GetIRContext()->get_type_mgr()->GetId(matrix_type.element_type());
+  auto element_type_id = matrix_type_instruction.GetSingleWordInOperand(0);
 
   // Get all instructions at our disposal that compute something of this element
   // type.
@@ -214,25 +216,32 @@
     // If there are not any instructions available that compute the element type
     // of the matrix then we are not in a position to construct a composite with
     // this matrix type.
-    return nullptr;
+    return {};
   }
-  for (uint32_t index = 0; index < matrix_type.element_count(); index++) {
-    result->push_back(available_instructions
-                          ->second[GetFuzzerContext()->RandomIndex(
-                              available_instructions->second)]
-                          ->result_id());
+  std::vector<uint32_t> result;
+  for (uint32_t index = 0;
+       index < matrix_type_instruction.GetSingleWordInOperand(1); index++) {
+    result.push_back(available_instructions
+                         ->second[GetFuzzerContext()->RandomIndex(
+                             available_instructions->second)]
+                         ->result_id());
   }
   return result;
 }
 
-std::unique_ptr<std::vector<uint32_t>>
-FuzzerPassConstructComposites::TryConstructingStructComposite(
-    const opt::analysis::Struct& struct_type,
+std::vector<uint32_t>
+FuzzerPassConstructComposites::FindComponentsToConstructStruct(
+    const opt::Instruction& struct_type_instruction,
     const TypeIdToInstructions& type_id_to_available_instructions) {
-  auto result = MakeUnique<std::vector<uint32_t>>();
+  assert(struct_type_instruction.opcode() == SpvOpTypeStruct &&
+         "Precondition: instruction must be a struct type.");
+  std::vector<uint32_t> result;
   // Consider the type of each field of the struct.
-  for (auto element_type : struct_type.element_types()) {
-    auto element_type_id = GetIRContext()->get_type_mgr()->GetId(element_type);
+  for (uint32_t in_operand_index = 0;
+       in_operand_index < struct_type_instruction.NumInOperands();
+       in_operand_index++) {
+    auto element_type_id =
+        struct_type_instruction.GetSingleWordInOperand(in_operand_index);
     // Find the instructions at our disposal that compute something of the field
     // type.
     auto available_instructions =
@@ -240,24 +249,28 @@
     if (available_instructions == type_id_to_available_instructions.cend()) {
       // If there are no such instructions, we cannot construct a composite of
       // this struct type.
-      return nullptr;
+      return {};
     }
-    result->push_back(available_instructions
-                          ->second[GetFuzzerContext()->RandomIndex(
-                              available_instructions->second)]
-                          ->result_id());
+    result.push_back(available_instructions
+                         ->second[GetFuzzerContext()->RandomIndex(
+                             available_instructions->second)]
+                         ->result_id());
   }
   return result;
 }
 
-std::unique_ptr<std::vector<uint32_t>>
-FuzzerPassConstructComposites::TryConstructingVectorComposite(
-    const opt::analysis::Vector& vector_type,
+std::vector<uint32_t>
+FuzzerPassConstructComposites::FindComponentsToConstructVector(
+    const opt::Instruction& vector_type_instruction,
     const TypeIdToInstructions& type_id_to_available_instructions) {
+  assert(vector_type_instruction.opcode() == SpvOpTypeVector &&
+         "Precondition: instruction must be a vector type.");
+
   // Get details of the type underlying the vector, and the width of the vector,
   // for convenience.
-  auto element_type = vector_type.element_type();
-  auto element_count = vector_type.element_count();
+  auto element_type_id = vector_type_instruction.GetSingleWordInOperand(0);
+  auto element_type = GetIRContext()->get_type_mgr()->GetType(element_type_id);
+  auto element_count = vector_type_instruction.GetSingleWordInOperand(1);
 
   // Collect a mapping, from type id to width, for scalar/vector types that are
   // smaller in width than |vector_type|, but that have the same underlying
@@ -268,14 +281,12 @@
   std::map<uint32_t, uint32_t> smaller_vector_type_id_to_width;
   // Add the underlying type.  This id must exist, in order for |vector_type| to
   // exist.
-  auto scalar_type_id = GetIRContext()->get_type_mgr()->GetId(element_type);
-  smaller_vector_type_id_to_width[scalar_type_id] = 1;
+  smaller_vector_type_id_to_width[element_type_id] = 1;
 
   // Now add every vector type with width at least 2, and less than the width of
   // |vector_type|.
   for (uint32_t width = 2; width < element_count; width++) {
-    opt::analysis::Vector smaller_vector_type(vector_type.element_type(),
-                                              width);
+    opt::analysis::Vector smaller_vector_type(element_type, width);
     auto smaller_vector_type_id =
         GetIRContext()->get_type_mgr()->GetId(&smaller_vector_type);
     // We might find that there is no declared type of this smaller width.
@@ -302,12 +313,11 @@
   // order at this stage.
   std::vector<opt::Instruction*> instructions_to_use;
 
-  while (vector_slots_used < vector_type.element_count()) {
+  while (vector_slots_used < element_count) {
     std::vector<opt::Instruction*> instructions_to_choose_from;
     for (auto& entry : smaller_vector_type_id_to_width) {
       if (entry.second >
-          std::min(vector_type.element_count() - 1,
-                   vector_type.element_count() - vector_slots_used)) {
+          std::min(element_count - 1, element_count - vector_slots_used)) {
         continue;
       }
       auto available_instructions =
@@ -326,7 +336,7 @@
       // another manner, so we could opt to retry a few times here, but it is
       // simpler to just give up on the basis that this will not happen
       // frequently.
-      return nullptr;
+      return {};
     }
     auto instruction_to_use =
         instructions_to_choose_from[GetFuzzerContext()->RandomIndex(
@@ -345,16 +355,16 @@
       vector_slots_used += 1;
     }
   }
-  assert(vector_slots_used == vector_type.element_count());
+  assert(vector_slots_used == element_count);
 
-  auto result = MakeUnique<std::vector<uint32_t>>();
+  std::vector<uint32_t> result;
   std::vector<uint32_t> operands;
   while (!instructions_to_use.empty()) {
     auto index = GetFuzzerContext()->RandomIndex(instructions_to_use);
-    result->push_back(instructions_to_use[index]->result_id());
+    result.push_back(instructions_to_use[index]->result_id());
     instructions_to_use.erase(instructions_to_use.begin() + index);
   }
-  assert(result->size() > 1);
+  assert(result.size() > 1);
   return result;
 }
 
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_construct_composites.h b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_construct_composites.h
index 99ef31f..9853fad 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_construct_composites.h
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_construct_composites.h
@@ -27,7 +27,7 @@
 class FuzzerPassConstructComposites : public FuzzerPass {
  public:
   FuzzerPassConstructComposites(
-      opt::IRContext* ir_context, FactManager* fact_manager,
+      opt::IRContext* ir_context, TransformationContext* transformation_context,
       FuzzerContext* fuzzer_context,
       protobufs::TransformationSequence* transformations);
 
@@ -49,27 +49,28 @@
       opt::Instruction* inst,
       TypeIdToInstructions* type_id_to_available_instructions);
 
+  // Requires that |array_type_instruction| has opcode OpTypeArray.
   // Attempts to find suitable instruction result ids from the values of
   // |type_id_to_available_instructions| that would allow a composite of type
-  // |array_type| to be constructed.  Returns said ids if they can be found.
-  // Returns |nullptr| otherwise.
-  std::unique_ptr<std::vector<uint32_t>> TryConstructingArrayComposite(
-      const opt::analysis::Array& array_type,
+  // |array_type_instruction| to be constructed.  Returns said ids if they can
+  // be found and an empty vector otherwise.
+  std::vector<uint32_t> FindComponentsToConstructArray(
+      const opt::Instruction& array_type_instruction,
       const TypeIdToInstructions& type_id_to_available_instructions);
 
-  // Similar to TryConstructingArrayComposite, but for matrices.
-  std::unique_ptr<std::vector<uint32_t>> TryConstructingMatrixComposite(
-      const opt::analysis::Matrix& matrix_type,
+  // Similar to FindComponentsToConstructArray, but for matrices.
+  std::vector<uint32_t> FindComponentsToConstructMatrix(
+      const opt::Instruction& matrix_type_instruction,
       const TypeIdToInstructions& type_id_to_available_instructions);
 
-  // Similar to TryConstructingArrayComposite, but for structs.
-  std::unique_ptr<std::vector<uint32_t>> TryConstructingStructComposite(
-      const opt::analysis::Struct& struct_type,
+  // Similar to FindComponentsToConstructArray, but for structs.
+  std::vector<uint32_t> FindComponentsToConstructStruct(
+      const opt::Instruction& struct_type_instruction,
       const TypeIdToInstructions& type_id_to_available_instructions);
 
-  // Similar to TryConstructingArrayComposite, but for vectors.
-  std::unique_ptr<std::vector<uint32_t>> TryConstructingVectorComposite(
-      const opt::analysis::Vector& vector_type,
+  // Similar to FindComponentsToConstructArray, but for vectors.
+  std::vector<uint32_t> FindComponentsToConstructVector(
+      const opt::Instruction& vector_type_instruction,
       const TypeIdToInstructions& type_id_to_available_instructions);
 };
 
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_copy_objects.cpp b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_copy_objects.cpp
index 588cfb6..f055b59 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_copy_objects.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_copy_objects.cpp
@@ -21,10 +21,11 @@
 namespace fuzz {
 
 FuzzerPassCopyObjects::FuzzerPassCopyObjects(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassCopyObjects::~FuzzerPassCopyObjects() = default;
 
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_copy_objects.h b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_copy_objects.h
index 5419459..8de382e 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_copy_objects.h
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_copy_objects.h
@@ -23,7 +23,8 @@
 // A fuzzer pass for adding adding copies of objects to the module.
 class FuzzerPassCopyObjects : public FuzzerPass {
  public:
-  FuzzerPassCopyObjects(opt::IRContext* ir_context, FactManager* fact_manager,
+  FuzzerPassCopyObjects(opt::IRContext* ir_context,
+                        TransformationContext* transformation_context,
                         FuzzerContext* fuzzer_context,
                         protobufs::TransformationSequence* transformations);
 
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_donate_modules.cpp b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_donate_modules.cpp
index 27d8a6e..fc71d34 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_donate_modules.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_donate_modules.cpp
@@ -22,6 +22,7 @@
 #include "source/fuzz/instruction_message.h"
 #include "source/fuzz/transformation_add_constant_boolean.h"
 #include "source/fuzz/transformation_add_constant_composite.h"
+#include "source/fuzz/transformation_add_constant_null.h"
 #include "source/fuzz/transformation_add_constant_scalar.h"
 #include "source/fuzz/transformation_add_function.h"
 #include "source/fuzz/transformation_add_global_undef.h"
@@ -40,11 +41,12 @@
 namespace fuzz {
 
 FuzzerPassDonateModules::FuzzerPassDonateModules(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations,
     const std::vector<fuzzerutil::ModuleSupplier>& donor_suppliers)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations),
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations),
       donor_suppliers_(donor_suppliers) {}
 
 FuzzerPassDonateModules::~FuzzerPassDonateModules() = default;
@@ -62,7 +64,9 @@
     std::unique_ptr<opt::IRContext> donor_ir_context = donor_suppliers_.at(
         GetFuzzerContext()->RandomIndex(donor_suppliers_))();
     assert(donor_ir_context != nullptr && "Supplying of donor failed");
-    assert(fuzzerutil::IsValid(donor_ir_context.get()) &&
+    assert(fuzzerutil::IsValid(
+               donor_ir_context.get(),
+               GetTransformationContext()->GetValidatorOptions()) &&
            "The donor module must be valid");
     // Donate the supplied module.
     //
@@ -112,6 +116,7 @@
   switch (donor_storage_class) {
     case SpvStorageClassFunction:
     case SpvStorageClassPrivate:
+    case SpvStorageClassWorkgroup:
       // We leave these alone
       return donor_storage_class;
     case SpvStorageClassInput:
@@ -119,6 +124,7 @@
     case SpvStorageClassUniform:
     case SpvStorageClassUniformConstant:
     case SpvStorageClassPushConstant:
+    case SpvStorageClassImage:
       // We change these to Private
       return SpvStorageClassPrivate;
     default:
@@ -162,284 +168,385 @@
     std::map<uint32_t, uint32_t>* original_id_to_donated_id) {
   // Consider every type/global/constant/undef in the module.
   for (auto& type_or_value : donor_ir_context->module()->types_values()) {
-    // Each such instruction generates a result id, and as part of donation we
-    // need to associate the donor's result id with a new result id.  That new
-    // result id will either be the id of some existing instruction, or a fresh
-    // id.  This variable captures it.
-    uint32_t new_result_id;
+    HandleTypeOrValue(type_or_value, original_id_to_donated_id);
+  }
+}
 
-    // Decide how to handle each kind of instruction on a case-by-case basis.
-    //
-    // Because the donor module is required to be valid, when we encounter a
-    // type comprised of component types (e.g. an aggregate or pointer), we know
-    // that its component types will have been considered previously, and that
-    // |original_id_to_donated_id| will already contain an entry for them.
-    switch (type_or_value.opcode()) {
-      case SpvOpTypeVoid: {
-        // Void has to exist already in order for us to have an entry point.
-        // Get the existing id of void.
-        opt::analysis::Void void_type;
-        new_result_id = GetIRContext()->get_type_mgr()->GetId(&void_type);
-        assert(new_result_id &&
-               "The module being transformed will always have 'void' type "
-               "declared.");
-      } break;
-      case SpvOpTypeBool: {
-        // Bool cannot be declared multiple times, so use its existing id if
-        // present, or add a declaration of Bool with a fresh id if not.
-        opt::analysis::Bool bool_type;
-        auto bool_type_id = GetIRContext()->get_type_mgr()->GetId(&bool_type);
-        if (bool_type_id) {
-          new_result_id = bool_type_id;
-        } else {
-          new_result_id = GetFuzzerContext()->GetFreshId();
-          ApplyTransformation(TransformationAddTypeBoolean(new_result_id));
-        }
-      } break;
-      case SpvOpTypeInt: {
-        // Int cannot be declared multiple times with the same width and
-        // signedness, so check whether an existing identical Int type is
-        // present and use its id if so.  Otherwise add a declaration of the
-        // Int type used by the donor, with a fresh id.
-        const uint32_t width = type_or_value.GetSingleWordInOperand(0);
-        const bool is_signed =
-            static_cast<bool>(type_or_value.GetSingleWordInOperand(1));
-        opt::analysis::Integer int_type(width, is_signed);
-        auto int_type_id = GetIRContext()->get_type_mgr()->GetId(&int_type);
-        if (int_type_id) {
-          new_result_id = int_type_id;
-        } else {
-          new_result_id = GetFuzzerContext()->GetFreshId();
-          ApplyTransformation(
-              TransformationAddTypeInt(new_result_id, width, is_signed));
-        }
-      } break;
-      case SpvOpTypeFloat: {
-        // Similar to SpvOpTypeInt.
-        const uint32_t width = type_or_value.GetSingleWordInOperand(0);
-        opt::analysis::Float float_type(width);
-        auto float_type_id = GetIRContext()->get_type_mgr()->GetId(&float_type);
-        if (float_type_id) {
-          new_result_id = float_type_id;
-        } else {
-          new_result_id = GetFuzzerContext()->GetFreshId();
-          ApplyTransformation(TransformationAddTypeFloat(new_result_id, width));
-        }
-      } break;
-      case SpvOpTypeVector: {
-        // It is not legal to have two Vector type declarations with identical
-        // element types and element counts, so check whether an existing
-        // identical Vector type is present and use its id if so.  Otherwise add
-        // a declaration of the Vector type used by the donor, with a fresh id.
+void FuzzerPassDonateModules::HandleTypeOrValue(
+    const opt::Instruction& type_or_value,
+    std::map<uint32_t, uint32_t>* original_id_to_donated_id) {
+  // The type/value instruction generates a result id, and we need to associate
+  // the donor's result id with a new result id.  That new result id will either
+  // be the id of some existing instruction, or a fresh id.  This variable
+  // captures it.
+  uint32_t new_result_id;
 
-        // When considering the vector's component type id, we look up the id
-        // use in the donor to find the id to which this has been remapped.
-        uint32_t component_type_id = original_id_to_donated_id->at(
-            type_or_value.GetSingleWordInOperand(0));
-        auto component_type =
-            GetIRContext()->get_type_mgr()->GetType(component_type_id);
-        assert(component_type && "The base type should be registered.");
-        auto component_count = type_or_value.GetSingleWordInOperand(1);
-        opt::analysis::Vector vector_type(component_type, component_count);
-        auto vector_type_id =
-            GetIRContext()->get_type_mgr()->GetId(&vector_type);
-        if (vector_type_id) {
-          new_result_id = vector_type_id;
-        } else {
-          new_result_id = GetFuzzerContext()->GetFreshId();
-          ApplyTransformation(TransformationAddTypeVector(
-              new_result_id, component_type_id, component_count));
-        }
-      } break;
-      case SpvOpTypeMatrix: {
-        // Similar to SpvOpTypeVector.
-        uint32_t column_type_id = original_id_to_donated_id->at(
-            type_or_value.GetSingleWordInOperand(0));
-        auto column_type =
-            GetIRContext()->get_type_mgr()->GetType(column_type_id);
-        assert(column_type && column_type->AsVector() &&
-               "The column type should be a registered vector type.");
-        auto column_count = type_or_value.GetSingleWordInOperand(1);
-        opt::analysis::Matrix matrix_type(column_type, column_count);
-        auto matrix_type_id =
-            GetIRContext()->get_type_mgr()->GetId(&matrix_type);
-        if (matrix_type_id) {
-          new_result_id = matrix_type_id;
-        } else {
-          new_result_id = GetFuzzerContext()->GetFreshId();
-          ApplyTransformation(TransformationAddTypeMatrix(
-              new_result_id, column_type_id, column_count));
-        }
-
-      } break;
-      case SpvOpTypeArray: {
-        // It is OK to have multiple structurally identical array types, so
-        // we go ahead and add a remapped version of the type declared by the
-        // donor.
+  // Decide how to handle each kind of instruction on a case-by-case basis.
+  //
+  // Because the donor module is required to be valid, when we encounter a
+  // type comprised of component types (e.g. an aggregate or pointer), we know
+  // that its component types will have been considered previously, and that
+  // |original_id_to_donated_id| will already contain an entry for them.
+  switch (type_or_value.opcode()) {
+    case SpvOpTypeImage:
+    case SpvOpTypeSampledImage:
+    case SpvOpTypeSampler:
+      // We do not donate types and variables that relate to images and
+      // samplers, so we skip these types and subsequently skip anything that
+      // depends on them.
+      return;
+    case SpvOpTypeVoid: {
+      // Void has to exist already in order for us to have an entry point.
+      // Get the existing id of void.
+      opt::analysis::Void void_type;
+      new_result_id = GetIRContext()->get_type_mgr()->GetId(&void_type);
+      assert(new_result_id &&
+             "The module being transformed will always have 'void' type "
+             "declared.");
+    } break;
+    case SpvOpTypeBool: {
+      // Bool cannot be declared multiple times, so use its existing id if
+      // present, or add a declaration of Bool with a fresh id if not.
+      opt::analysis::Bool bool_type;
+      auto bool_type_id = GetIRContext()->get_type_mgr()->GetId(&bool_type);
+      if (bool_type_id) {
+        new_result_id = bool_type_id;
+      } else {
         new_result_id = GetFuzzerContext()->GetFreshId();
-        ApplyTransformation(TransformationAddTypeArray(
+        ApplyTransformation(TransformationAddTypeBoolean(new_result_id));
+      }
+    } break;
+    case SpvOpTypeInt: {
+      // Int cannot be declared multiple times with the same width and
+      // signedness, so check whether an existing identical Int type is
+      // present and use its id if so.  Otherwise add a declaration of the
+      // Int type used by the donor, with a fresh id.
+      const uint32_t width = type_or_value.GetSingleWordInOperand(0);
+      const bool is_signed =
+          static_cast<bool>(type_or_value.GetSingleWordInOperand(1));
+      opt::analysis::Integer int_type(width, is_signed);
+      auto int_type_id = GetIRContext()->get_type_mgr()->GetId(&int_type);
+      if (int_type_id) {
+        new_result_id = int_type_id;
+      } else {
+        new_result_id = GetFuzzerContext()->GetFreshId();
+        ApplyTransformation(
+            TransformationAddTypeInt(new_result_id, width, is_signed));
+      }
+    } break;
+    case SpvOpTypeFloat: {
+      // Similar to SpvOpTypeInt.
+      const uint32_t width = type_or_value.GetSingleWordInOperand(0);
+      opt::analysis::Float float_type(width);
+      auto float_type_id = GetIRContext()->get_type_mgr()->GetId(&float_type);
+      if (float_type_id) {
+        new_result_id = float_type_id;
+      } else {
+        new_result_id = GetFuzzerContext()->GetFreshId();
+        ApplyTransformation(TransformationAddTypeFloat(new_result_id, width));
+      }
+    } break;
+    case SpvOpTypeVector: {
+      // It is not legal to have two Vector type declarations with identical
+      // element types and element counts, so check whether an existing
+      // identical Vector type is present and use its id if so.  Otherwise add
+      // a declaration of the Vector type used by the donor, with a fresh id.
+
+      // When considering the vector's component type id, we look up the id
+      // use in the donor to find the id to which this has been remapped.
+      uint32_t component_type_id = original_id_to_donated_id->at(
+          type_or_value.GetSingleWordInOperand(0));
+      auto component_type =
+          GetIRContext()->get_type_mgr()->GetType(component_type_id);
+      assert(component_type && "The base type should be registered.");
+      auto component_count = type_or_value.GetSingleWordInOperand(1);
+      opt::analysis::Vector vector_type(component_type, component_count);
+      auto vector_type_id = GetIRContext()->get_type_mgr()->GetId(&vector_type);
+      if (vector_type_id) {
+        new_result_id = vector_type_id;
+      } else {
+        new_result_id = GetFuzzerContext()->GetFreshId();
+        ApplyTransformation(TransformationAddTypeVector(
+            new_result_id, component_type_id, component_count));
+      }
+    } break;
+    case SpvOpTypeMatrix: {
+      // Similar to SpvOpTypeVector.
+      uint32_t column_type_id = original_id_to_donated_id->at(
+          type_or_value.GetSingleWordInOperand(0));
+      auto column_type =
+          GetIRContext()->get_type_mgr()->GetType(column_type_id);
+      assert(column_type && column_type->AsVector() &&
+             "The column type should be a registered vector type.");
+      auto column_count = type_or_value.GetSingleWordInOperand(1);
+      opt::analysis::Matrix matrix_type(column_type, column_count);
+      auto matrix_type_id = GetIRContext()->get_type_mgr()->GetId(&matrix_type);
+      if (matrix_type_id) {
+        new_result_id = matrix_type_id;
+      } else {
+        new_result_id = GetFuzzerContext()->GetFreshId();
+        ApplyTransformation(TransformationAddTypeMatrix(
+            new_result_id, column_type_id, column_count));
+      }
+
+    } break;
+    case SpvOpTypeArray: {
+      // It is OK to have multiple structurally identical array types, so
+      // we go ahead and add a remapped version of the type declared by the
+      // donor.
+      uint32_t component_type_id = type_or_value.GetSingleWordInOperand(0);
+      if (!original_id_to_donated_id->count(component_type_id)) {
+        // We did not donate the component type of this array type, so we
+        // cannot donate the array type.
+        return;
+      }
+      new_result_id = GetFuzzerContext()->GetFreshId();
+      ApplyTransformation(TransformationAddTypeArray(
+          new_result_id, original_id_to_donated_id->at(component_type_id),
+          original_id_to_donated_id->at(
+              type_or_value.GetSingleWordInOperand(1))));
+    } break;
+    case SpvOpTypeRuntimeArray: {
+      // A runtime array is allowed as the final member of an SSBO.  During
+      // donation we turn runtime arrays into fixed-size arrays.  For dead
+      // code donations this is OK because the array is never indexed into at
+      // runtime, so it does not matter what its size is.  For live-safe code,
+      // all accesses are made in-bounds, so this is also OK.
+      //
+      // The special OpArrayLength instruction, which works on runtime arrays,
+      // is rewritten to yield the fixed length that is used for the array.
+
+      uint32_t component_type_id = type_or_value.GetSingleWordInOperand(0);
+      if (!original_id_to_donated_id->count(component_type_id)) {
+        // We did not donate the component type of this runtime array type, so
+        // we cannot donate it as a fixed-size array.
+        return;
+      }
+      new_result_id = GetFuzzerContext()->GetFreshId();
+      ApplyTransformation(TransformationAddTypeArray(
+          new_result_id, original_id_to_donated_id->at(component_type_id),
+          FindOrCreate32BitIntegerConstant(
+              GetFuzzerContext()->GetRandomSizeForNewArray(), false)));
+    } break;
+    case SpvOpTypeStruct: {
+      // Similar to SpvOpTypeArray.
+      std::vector<uint32_t> member_type_ids;
+      for (uint32_t i = 0; i < type_or_value.NumInOperands(); i++) {
+        auto component_type_id = type_or_value.GetSingleWordInOperand(i);
+        if (!original_id_to_donated_id->count(component_type_id)) {
+          // We did not donate every member type for this struct type, so we
+          // cannot donate the struct type.
+          return;
+        }
+        member_type_ids.push_back(
+            original_id_to_donated_id->at(component_type_id));
+      }
+      new_result_id = GetFuzzerContext()->GetFreshId();
+      ApplyTransformation(
+          TransformationAddTypeStruct(new_result_id, member_type_ids));
+    } break;
+    case SpvOpTypePointer: {
+      // Similar to SpvOpTypeArray.
+      uint32_t pointee_type_id = type_or_value.GetSingleWordInOperand(1);
+      if (!original_id_to_donated_id->count(pointee_type_id)) {
+        // We did not donate the pointee type for this pointer type, so we
+        // cannot donate the pointer type.
+        return;
+      }
+      new_result_id = GetFuzzerContext()->GetFreshId();
+      ApplyTransformation(TransformationAddTypePointer(
+          new_result_id,
+          AdaptStorageClass(static_cast<SpvStorageClass>(
+              type_or_value.GetSingleWordInOperand(0))),
+          original_id_to_donated_id->at(pointee_type_id)));
+    } break;
+    case SpvOpTypeFunction: {
+      // It is not OK to have multiple function types that use identical ids
+      // for their return and parameter types.  We thus go through all
+      // existing function types to look for a match.  We do not use the
+      // type manager here because we want to regard two function types that
+      // are structurally identical but that differ with respect to the
+      // actual ids used for pointer types as different.
+      //
+      // Example:
+      //
+      // %1 = OpTypeVoid
+      // %2 = OpTypeInt 32 0
+      // %3 = OpTypePointer Function %2
+      // %4 = OpTypePointer Function %2
+      // %5 = OpTypeFunction %1 %3
+      // %6 = OpTypeFunction %1 %4
+      //
+      // We regard %5 and %6 as distinct function types here, even though
+      // they both have the form "uint32* -> void"
+
+      std::vector<uint32_t> return_and_parameter_types;
+      for (uint32_t i = 0; i < type_or_value.NumInOperands(); i++) {
+        uint32_t return_or_parameter_type =
+            type_or_value.GetSingleWordInOperand(i);
+        if (!original_id_to_donated_id->count(return_or_parameter_type)) {
+          // We did not donate every return/parameter type for this function
+          // type, so we cannot donate the function type.
+          return;
+        }
+        return_and_parameter_types.push_back(
+            original_id_to_donated_id->at(return_or_parameter_type));
+      }
+      uint32_t existing_function_id = fuzzerutil::FindFunctionType(
+          GetIRContext(), return_and_parameter_types);
+      if (existing_function_id) {
+        new_result_id = existing_function_id;
+      } else {
+        // No match was found, so add a remapped version of the function type
+        // to the module, with a fresh id.
+        new_result_id = GetFuzzerContext()->GetFreshId();
+        std::vector<uint32_t> argument_type_ids;
+        for (uint32_t i = 1; i < type_or_value.NumInOperands(); i++) {
+          argument_type_ids.push_back(original_id_to_donated_id->at(
+              type_or_value.GetSingleWordInOperand(i)));
+        }
+        ApplyTransformation(TransformationAddTypeFunction(
             new_result_id,
             original_id_to_donated_id->at(
                 type_or_value.GetSingleWordInOperand(0)),
-            original_id_to_donated_id->at(
-                type_or_value.GetSingleWordInOperand(1))));
-      } break;
-      case SpvOpTypeStruct: {
-        // Similar to SpvOpTypeArray.
-        new_result_id = GetFuzzerContext()->GetFreshId();
-        std::vector<uint32_t> member_type_ids;
-        type_or_value.ForEachInId(
-            [&member_type_ids,
-             &original_id_to_donated_id](const uint32_t* component_type_id) {
-              member_type_ids.push_back(
-                  original_id_to_donated_id->at(*component_type_id));
-            });
-        ApplyTransformation(
-            TransformationAddTypeStruct(new_result_id, member_type_ids));
-      } break;
-      case SpvOpTypePointer: {
-        // Similar to SpvOpTypeArray.
-        new_result_id = GetFuzzerContext()->GetFreshId();
-        ApplyTransformation(TransformationAddTypePointer(
-            new_result_id,
-            AdaptStorageClass(static_cast<SpvStorageClass>(
-                type_or_value.GetSingleWordInOperand(0))),
-            original_id_to_donated_id->at(
-                type_or_value.GetSingleWordInOperand(1))));
-      } break;
-      case SpvOpTypeFunction: {
-        // It is not OK to have multiple function types that use identical ids
-        // for their return and parameter types.  We thus go through all
-        // existing function types to look for a match.  We do not use the
-        // type manager here because we want to regard two function types that
-        // are structurally identical but that differ with respect to the
-        // actual ids used for pointer types as different.
-        //
-        // Example:
-        //
-        // %1 = OpTypeVoid
-        // %2 = OpTypeInt 32 0
-        // %3 = OpTypePointer Function %2
-        // %4 = OpTypePointer Function %2
-        // %5 = OpTypeFunction %1 %3
-        // %6 = OpTypeFunction %1 %4
-        //
-        // We regard %5 and %6 as distinct function types here, even though
-        // they both have the form "uint32* -> void"
+            argument_type_ids));
+      }
+    } break;
+    case SpvOpConstantTrue:
+    case SpvOpConstantFalse: {
+      // It is OK to have duplicate definitions of True and False, so add
+      // these to the module, using a remapped Bool type.
+      new_result_id = GetFuzzerContext()->GetFreshId();
+      ApplyTransformation(TransformationAddConstantBoolean(
+          new_result_id, type_or_value.opcode() == SpvOpConstantTrue));
+    } break;
+    case SpvOpConstant: {
+      // It is OK to have duplicate constant definitions, so add this to the
+      // module using a remapped result type.
+      new_result_id = GetFuzzerContext()->GetFreshId();
+      std::vector<uint32_t> data_words;
+      type_or_value.ForEachInOperand([&data_words](const uint32_t* in_operand) {
+        data_words.push_back(*in_operand);
+      });
+      ApplyTransformation(TransformationAddConstantScalar(
+          new_result_id, original_id_to_donated_id->at(type_or_value.type_id()),
+          data_words));
+    } break;
+    case SpvOpConstantComposite: {
+      assert(original_id_to_donated_id->count(type_or_value.type_id()) &&
+             "Composite types for which it is possible to create a constant "
+             "should have been donated.");
 
-        std::vector<uint32_t> return_and_parameter_types;
-        for (uint32_t i = 0; i < type_or_value.NumInOperands(); i++) {
-          return_and_parameter_types.push_back(original_id_to_donated_id->at(
-              type_or_value.GetSingleWordInOperand(i)));
-        }
-        uint32_t existing_function_id = fuzzerutil::FindFunctionType(
-            GetIRContext(), return_and_parameter_types);
-        if (existing_function_id) {
-          new_result_id = existing_function_id;
-        } else {
-          // No match was found, so add a remapped version of the function type
-          // to the module, with a fresh id.
-          new_result_id = GetFuzzerContext()->GetFreshId();
-          std::vector<uint32_t> argument_type_ids;
-          for (uint32_t i = 1; i < type_or_value.NumInOperands(); i++) {
-            argument_type_ids.push_back(original_id_to_donated_id->at(
-                type_or_value.GetSingleWordInOperand(i)));
-          }
-          ApplyTransformation(TransformationAddTypeFunction(
-              new_result_id,
-              original_id_to_donated_id->at(
-                  type_or_value.GetSingleWordInOperand(0)),
-              argument_type_ids));
-        }
-      } break;
-      case SpvOpConstantTrue:
-      case SpvOpConstantFalse: {
-        // It is OK to have duplicate definitions of True and False, so add
-        // these to the module, using a remapped Bool type.
-        new_result_id = GetFuzzerContext()->GetFreshId();
-        ApplyTransformation(TransformationAddConstantBoolean(
-            new_result_id, type_or_value.opcode() == SpvOpConstantTrue));
-      } break;
-      case SpvOpConstant: {
-        // It is OK to have duplicate constant definitions, so add this to the
-        // module using a remapped result type.
-        new_result_id = GetFuzzerContext()->GetFreshId();
-        std::vector<uint32_t> data_words;
-        type_or_value.ForEachInOperand(
-            [&data_words](const uint32_t* in_operand) {
-              data_words.push_back(*in_operand);
-            });
-        ApplyTransformation(TransformationAddConstantScalar(
-            new_result_id,
-            original_id_to_donated_id->at(type_or_value.type_id()),
-            data_words));
-      } break;
-      case SpvOpConstantComposite: {
-        // It is OK to have duplicate constant composite definitions, so add
-        // this to the module using remapped versions of all consituent ids and
-        // the result type.
-        new_result_id = GetFuzzerContext()->GetFreshId();
-        std::vector<uint32_t> constituent_ids;
-        type_or_value.ForEachInId(
-            [&constituent_ids,
-             &original_id_to_donated_id](const uint32_t* constituent_id) {
-              constituent_ids.push_back(
-                  original_id_to_donated_id->at(*constituent_id));
-            });
-        ApplyTransformation(TransformationAddConstantComposite(
-            new_result_id,
-            original_id_to_donated_id->at(type_or_value.type_id()),
-            constituent_ids));
-      } break;
-      case SpvOpVariable: {
-        // This is a global variable that could have one of various storage
-        // classes.  However, we change all global variable pointer storage
-        // classes (such as Uniform, Input and Output) to private when donating
-        // pointer types.  Thus this variable's pointer type is guaranteed to
-        // have storage class private.  As a result, we simply add a Private
-        // storage class global variable, using remapped versions of the result
-        // type and initializer ids for the global variable in the donor.
-        //
-        // We regard the added variable as having an irrelevant value.  This
-        // means that future passes can add stores to the variable in any
-        // way they wish, and pass them as pointer parameters to functions
-        // without worrying about whether their data might get modified.
-        new_result_id = GetFuzzerContext()->GetFreshId();
-        uint32_t remapped_pointer_type =
-            original_id_to_donated_id->at(type_or_value.type_id());
-        uint32_t initializer_id;
-        if (type_or_value.NumInOperands() == 1) {
-          // The variable did not have an initializer; initialize it to zero.
-          // This is to limit problems associated with uninitialized data.
-          initializer_id = FindOrCreateZeroConstant(
-              fuzzerutil::GetPointeeTypeIdFromPointerType(
-                  GetIRContext(), remapped_pointer_type));
-        } else {
-          // The variable already had an initializer; use its remapped id.
-          initializer_id = original_id_to_donated_id->at(
-              type_or_value.GetSingleWordInOperand(1));
-        }
-        ApplyTransformation(TransformationAddGlobalVariable(
-            new_result_id, remapped_pointer_type, initializer_id, true));
-      } break;
-      case SpvOpUndef: {
-        // It is fine to have multiple Undef instructions of the same type, so
-        // we just add this to the recipient module.
-        new_result_id = GetFuzzerContext()->GetFreshId();
-        ApplyTransformation(TransformationAddGlobalUndef(
-            new_result_id,
-            original_id_to_donated_id->at(type_or_value.type_id())));
-      } break;
-      default: {
-        assert(0 && "Unknown type/value.");
-        new_result_id = 0;
-      } break;
-    }
-    // Update the id mapping to associate the instruction's result id with its
-    // corresponding id in the recipient.
-    original_id_to_donated_id->insert(
-        {type_or_value.result_id(), new_result_id});
+      // It is OK to have duplicate constant composite definitions, so add
+      // this to the module using remapped versions of all consituent ids and
+      // the result type.
+      new_result_id = GetFuzzerContext()->GetFreshId();
+      std::vector<uint32_t> constituent_ids;
+      type_or_value.ForEachInId([&constituent_ids, &original_id_to_donated_id](
+                                    const uint32_t* constituent_id) {
+        assert(original_id_to_donated_id->count(*constituent_id) &&
+               "The constants used to construct this composite should "
+               "have been donated.");
+        constituent_ids.push_back(
+            original_id_to_donated_id->at(*constituent_id));
+      });
+      ApplyTransformation(TransformationAddConstantComposite(
+          new_result_id, original_id_to_donated_id->at(type_or_value.type_id()),
+          constituent_ids));
+    } break;
+    case SpvOpConstantNull: {
+      if (!original_id_to_donated_id->count(type_or_value.type_id())) {
+        // We did not donate the type associated with this null constant, so
+        // we cannot donate the null constant.
+        return;
+      }
+
+      // It is fine to have multiple OpConstantNull instructions of the same
+      // type, so we just add this to the recipient module.
+      new_result_id = GetFuzzerContext()->GetFreshId();
+      ApplyTransformation(TransformationAddConstantNull(
+          new_result_id,
+          original_id_to_donated_id->at(type_or_value.type_id())));
+    } break;
+    case SpvOpVariable: {
+      if (!original_id_to_donated_id->count(type_or_value.type_id())) {
+        // We did not donate the pointer type associated with this variable,
+        // so we cannot donate the variable.
+        return;
+      }
+
+      // This is a global variable that could have one of various storage
+      // classes.  However, we change all global variable pointer storage
+      // classes (such as Uniform, Input and Output) to private when donating
+      // pointer types, with the exception of the Workgroup storage class.
+      //
+      // Thus this variable's pointer type is guaranteed to have storage class
+      // Private or Workgroup.
+      //
+      // We add a global variable with either Private or Workgroup storage
+      // class, using remapped versions of the result type and initializer ids
+      // for the global variable in the donor.
+      //
+      // We regard the added variable as having an irrelevant value.  This
+      // means that future passes can add stores to the variable in any
+      // way they wish, and pass them as pointer parameters to functions
+      // without worrying about whether their data might get modified.
+      new_result_id = GetFuzzerContext()->GetFreshId();
+      uint32_t remapped_pointer_type =
+          original_id_to_donated_id->at(type_or_value.type_id());
+      uint32_t initializer_id;
+      SpvStorageClass storage_class =
+          static_cast<SpvStorageClass>(type_or_value.GetSingleWordInOperand(
+              0)) == SpvStorageClassWorkgroup
+              ? SpvStorageClassWorkgroup
+              : SpvStorageClassPrivate;
+      if (type_or_value.NumInOperands() == 1) {
+        // The variable did not have an initializer.  Initialize it to zero
+        // if it has Private storage class (to limit problems associated with
+        // uninitialized data), and leave it uninitialized if it has Workgroup
+        // storage class (as Workgroup variables cannot have initializers).
+
+        // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3275): we
+        //  could initialize Workgroup variables at the start of an entry
+        //  point, and should do so if their uninitialized nature proves
+        //  problematic.
+        initializer_id = storage_class == SpvStorageClassWorkgroup
+                             ? 0
+                             : FindOrCreateZeroConstant(
+                                   fuzzerutil::GetPointeeTypeIdFromPointerType(
+                                       GetIRContext(), remapped_pointer_type));
+      } else {
+        // The variable already had an initializer; use its remapped id.
+        initializer_id = original_id_to_donated_id->at(
+            type_or_value.GetSingleWordInOperand(1));
+      }
+      ApplyTransformation(
+          TransformationAddGlobalVariable(new_result_id, remapped_pointer_type,
+                                          storage_class, initializer_id, true));
+    } break;
+    case SpvOpUndef: {
+      if (!original_id_to_donated_id->count(type_or_value.type_id())) {
+        // We did not donate the type associated with this undef, so we cannot
+        // donate the undef.
+        return;
+      }
+
+      // It is fine to have multiple Undef instructions of the same type, so
+      // we just add this to the recipient module.
+      new_result_id = GetFuzzerContext()->GetFreshId();
+      ApplyTransformation(TransformationAddGlobalUndef(
+          new_result_id,
+          original_id_to_donated_id->at(type_or_value.type_id())));
+    } break;
+    default: {
+      assert(0 && "Unknown type/value.");
+      new_result_id = 0;
+    } break;
   }
+
+  // Update the id mapping to associate the instruction's result id with its
+  // corresponding id in the recipient.
+  original_id_to_donated_id->insert({type_or_value.result_id(), new_result_id});
 }
 
 void FuzzerPassDonateModules::HandleFunctions(
@@ -468,220 +575,49 @@
     }
     assert(function_to_donate && "Function to be donated was not found.");
 
+    if (!original_id_to_donated_id->count(
+            function_to_donate->DefInst().GetSingleWordInOperand(1))) {
+      // We were not able to donate this function's type, so we cannot donate
+      // the function.
+      continue;
+    }
+
     // We will collect up protobuf messages representing the donor function's
     // instructions here, and use them to create an AddFunction transformation.
     std::vector<protobufs::Instruction> donated_instructions;
 
-    // Scan through the function, remapping each result id that it generates to
-    // a fresh id.  This is necessary because functions include forward
-    // references, e.g. to labels.
-    function_to_donate->ForEachInst([this, &original_id_to_donated_id](
-                                        const opt::Instruction* instruction) {
-      if (instruction->result_id()) {
-        original_id_to_donated_id->insert(
-            {instruction->result_id(), GetFuzzerContext()->GetFreshId()});
-      }
-    });
+    // This set tracks the ids of those instructions for which donation was
+    // completely skipped: neither the instruction nor a substitute for it was
+    // donated.
+    std::set<uint32_t> skipped_instructions;
 
     // Consider every instruction of the donor function.
-    function_to_donate->ForEachInst([this, &donated_instructions,
-                                     &original_id_to_donated_id](
-                                        const opt::Instruction* instruction) {
-      // Get the instruction's input operands into donation-ready form,
-      // remapping any id uses in the process.
-      opt::Instruction::OperandList input_operands;
-
-      // Consider each input operand in turn.
-      for (uint32_t in_operand_index = 0;
-           in_operand_index < instruction->NumInOperands();
-           in_operand_index++) {
-        std::vector<uint32_t> operand_data;
-        const opt::Operand& in_operand =
-            instruction->GetInOperand(in_operand_index);
-        switch (in_operand.type) {
-          case SPV_OPERAND_TYPE_ID:
-          case SPV_OPERAND_TYPE_TYPE_ID:
-          case SPV_OPERAND_TYPE_RESULT_ID:
-          case SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID:
-          case SPV_OPERAND_TYPE_SCOPE_ID:
-            // This is an id operand - it consists of a single word of data,
-            // which needs to be remapped so that it is replaced with the
-            // donated form of the id.
-            operand_data.push_back(
-                original_id_to_donated_id->at(in_operand.words[0]));
-            break;
-          default:
-            // For non-id operands, we just add each of the data words.
-            for (auto word : in_operand.words) {
-              operand_data.push_back(word);
-            }
-            break;
-        }
-        input_operands.push_back({in_operand.type, operand_data});
-      }
-
-      if (instruction->opcode() == SpvOpVariable &&
-          instruction->NumInOperands() == 1) {
-        // This is an uninitialized local variable.  Initialize it to zero.
-        input_operands.push_back(
-            {SPV_OPERAND_TYPE_ID,
-             {FindOrCreateZeroConstant(
-                 fuzzerutil::GetPointeeTypeIdFromPointerType(
-                     GetIRContext(),
-                     original_id_to_donated_id->at(instruction->type_id())))}});
-      }
-
-      // Remap the result type and result id (if present) of the
-      // instruction, and turn it into a protobuf message.
-      donated_instructions.push_back(MakeInstructionMessage(
-          instruction->opcode(),
-          instruction->type_id()
-              ? original_id_to_donated_id->at(instruction->type_id())
-              : 0,
-          instruction->result_id()
-              ? original_id_to_donated_id->at(instruction->result_id())
-              : 0,
-          input_operands));
-    });
+    function_to_donate->ForEachInst(
+        [this, &donated_instructions, donor_ir_context,
+         &original_id_to_donated_id,
+         &skipped_instructions](const opt::Instruction* instruction) {
+          if (instruction->opcode() == SpvOpArrayLength) {
+            // We treat OpArrayLength specially.
+            HandleOpArrayLength(*instruction, original_id_to_donated_id,
+                                &donated_instructions);
+          } else if (!CanDonateInstruction(donor_ir_context, *instruction,
+                                           *original_id_to_donated_id,
+                                           skipped_instructions)) {
+            // This is an instruction that we cannot directly donate.
+            HandleDifficultInstruction(*instruction, original_id_to_donated_id,
+                                       &donated_instructions,
+                                       &skipped_instructions);
+          } else {
+            PrepareInstructionForDonation(*instruction, donor_ir_context,
+                                          original_id_to_donated_id,
+                                          &donated_instructions);
+          }
+        });
 
     if (make_livesafe) {
-      // Various types and constants must be in place for a function to be made
-      // live-safe.  Add them if not already present.
-      FindOrCreateBoolType();  // Needed for comparisons
-      FindOrCreatePointerTo32BitIntegerType(
-          false, SpvStorageClassFunction);  // Needed for adding loop limiters
-      FindOrCreate32BitIntegerConstant(
-          0, false);  // Needed for initializing loop limiters
-      FindOrCreate32BitIntegerConstant(
-          1, false);  // Needed for incrementing loop limiters
-
-      // Get a fresh id for the variable that will be used as a loop limiter.
-      const uint32_t loop_limiter_variable_id =
-          GetFuzzerContext()->GetFreshId();
-      // Choose a random loop limit, and add the required constant to the
-      // module if not already there.
-      const uint32_t loop_limit = FindOrCreate32BitIntegerConstant(
-          GetFuzzerContext()->GetRandomLoopLimit(), false);
-
-      // Consider every loop header in the function to donate, and create a
-      // structure capturing the ids to be used for manipulating the loop
-      // limiter each time the loop is iterated.
-      std::vector<protobufs::LoopLimiterInfo> loop_limiters;
-      for (auto& block : *function_to_donate) {
-        if (block.IsLoopHeader()) {
-          protobufs::LoopLimiterInfo loop_limiter;
-          // Grab the loop header's id, mapped to its donated value.
-          loop_limiter.set_loop_header_id(
-              original_id_to_donated_id->at(block.id()));
-          // Get fresh ids that will be used to load the loop limiter, increment
-          // it, compare it with the loop limit, and an id for a new block that
-          // will contain the loop's original terminator.
-          loop_limiter.set_load_id(GetFuzzerContext()->GetFreshId());
-          loop_limiter.set_increment_id(GetFuzzerContext()->GetFreshId());
-          loop_limiter.set_compare_id(GetFuzzerContext()->GetFreshId());
-          loop_limiter.set_logical_op_id(GetFuzzerContext()->GetFreshId());
-          loop_limiters.emplace_back(loop_limiter);
-        }
-      }
-
-      // Consider every access chain in the function to donate, and create a
-      // structure containing the ids necessary to clamp the access chain
-      // indices to be in-bounds.
-      std::vector<protobufs::AccessChainClampingInfo>
-          access_chain_clamping_info;
-      for (auto& block : *function_to_donate) {
-        for (auto& inst : block) {
-          switch (inst.opcode()) {
-            case SpvOpAccessChain:
-            case SpvOpInBoundsAccessChain: {
-              protobufs::AccessChainClampingInfo clamping_info;
-              clamping_info.set_access_chain_id(
-                  original_id_to_donated_id->at(inst.result_id()));
-
-              auto base_object = donor_ir_context->get_def_use_mgr()->GetDef(
-                  inst.GetSingleWordInOperand(0));
-              assert(base_object && "The base object must exist.");
-              auto pointer_type = donor_ir_context->get_def_use_mgr()->GetDef(
-                  base_object->type_id());
-              assert(pointer_type &&
-                     pointer_type->opcode() == SpvOpTypePointer &&
-                     "The base object must have pointer type.");
-
-              auto should_be_composite_type =
-                  donor_ir_context->get_def_use_mgr()->GetDef(
-                      pointer_type->GetSingleWordInOperand(1));
-
-              // Walk the access chain, creating fresh ids to facilitate
-              // clamping each index.  For simplicity we do this for every
-              // index, even though constant indices will not end up being
-              // clamped.
-              for (uint32_t index = 1; index < inst.NumInOperands(); index++) {
-                auto compare_and_select_ids =
-                    clamping_info.add_compare_and_select_ids();
-                compare_and_select_ids->set_first(
-                    GetFuzzerContext()->GetFreshId());
-                compare_and_select_ids->set_second(
-                    GetFuzzerContext()->GetFreshId());
-
-                // Get the bound for the component being indexed into.
-                uint32_t bound =
-                    TransformationAddFunction::GetBoundForCompositeIndex(
-                        donor_ir_context, *should_be_composite_type);
-                const uint32_t index_id = inst.GetSingleWordInOperand(index);
-                auto index_inst =
-                    donor_ir_context->get_def_use_mgr()->GetDef(index_id);
-                auto index_type_inst =
-                    donor_ir_context->get_def_use_mgr()->GetDef(
-                        index_inst->type_id());
-                assert(index_type_inst->opcode() == SpvOpTypeInt);
-                assert(index_type_inst->GetSingleWordInOperand(0) == 32);
-                opt::analysis::Integer* index_int_type =
-                    donor_ir_context->get_type_mgr()
-                        ->GetType(index_type_inst->result_id())
-                        ->AsInteger();
-                if (index_inst->opcode() != SpvOpConstant) {
-                  // We will have to clamp this index, so we need a constant
-                  // whose value is one less than the bound, to compare
-                  // against and to use as the clamped value.
-                  FindOrCreate32BitIntegerConstant(bound - 1,
-                                                   index_int_type->IsSigned());
-                }
-                should_be_composite_type =
-                    TransformationAddFunction::FollowCompositeIndex(
-                        donor_ir_context, *should_be_composite_type, index_id);
-              }
-              access_chain_clamping_info.push_back(clamping_info);
-              break;
-            }
-            default:
-              break;
-          }
-        }
-      }
-
-      // If the function contains OpKill or OpUnreachable instructions, and has
-      // non-void return type, then we need a value %v to use in order to turn
-      // these into instructions of the form OpReturn %v.
-      uint32_t kill_unreachable_return_value_id;
-      auto function_return_type_inst =
-          donor_ir_context->get_def_use_mgr()->GetDef(
-              function_to_donate->type_id());
-      if (function_return_type_inst->opcode() == SpvOpTypeVoid) {
-        // The return type is void, so we don't need a return value.
-        kill_unreachable_return_value_id = 0;
-      } else {
-        // We do need a return value; we use zero.
-        assert(function_return_type_inst->opcode() != SpvOpTypePointer &&
-               "Function return type must not be a pointer.");
-        kill_unreachable_return_value_id =
-            FindOrCreateZeroConstant(original_id_to_donated_id->at(
-                function_return_type_inst->result_id()));
-      }
-      // Add the function in a livesafe manner.
-      ApplyTransformation(TransformationAddFunction(
-          donated_instructions, loop_limiter_variable_id, loop_limit,
-          loop_limiters, kill_unreachable_return_value_id,
-          access_chain_clamping_info));
+      // Make the function livesafe and then add it.
+      AddLivesafeFunction(*function_to_donate, donor_ir_context,
+                          *original_id_to_donated_id, donated_instructions);
     } else {
       // Add the function in a non-livesafe manner.
       ApplyTransformation(TransformationAddFunction(donated_instructions));
@@ -689,6 +625,133 @@
   }
 }
 
+bool FuzzerPassDonateModules::CanDonateInstruction(
+    opt::IRContext* donor_ir_context, const opt::Instruction& instruction,
+    const std::map<uint32_t, uint32_t>& original_id_to_donated_id,
+    const std::set<uint32_t>& skipped_instructions) const {
+  if (instruction.type_id() &&
+      !original_id_to_donated_id.count(instruction.type_id())) {
+    // We could not donate the result type of this instruction, so we cannot
+    // donate the instruction.
+    return false;
+  }
+
+  // Now consider instructions we specifically want to skip because we do not
+  // yet support them.
+  switch (instruction.opcode()) {
+    case SpvOpAtomicLoad:
+    case SpvOpAtomicStore:
+    case SpvOpAtomicExchange:
+    case SpvOpAtomicCompareExchange:
+    case SpvOpAtomicCompareExchangeWeak:
+    case SpvOpAtomicIIncrement:
+    case SpvOpAtomicIDecrement:
+    case SpvOpAtomicIAdd:
+    case SpvOpAtomicISub:
+    case SpvOpAtomicSMin:
+    case SpvOpAtomicUMin:
+    case SpvOpAtomicSMax:
+    case SpvOpAtomicUMax:
+    case SpvOpAtomicAnd:
+    case SpvOpAtomicOr:
+    case SpvOpAtomicXor:
+      // We conservatively ignore all atomic instructions at present.
+      // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3276): Consider
+      //  being less conservative here.
+    case SpvOpImageSampleImplicitLod:
+    case SpvOpImageSampleExplicitLod:
+    case SpvOpImageSampleDrefImplicitLod:
+    case SpvOpImageSampleDrefExplicitLod:
+    case SpvOpImageSampleProjImplicitLod:
+    case SpvOpImageSampleProjExplicitLod:
+    case SpvOpImageSampleProjDrefImplicitLod:
+    case SpvOpImageSampleProjDrefExplicitLod:
+    case SpvOpImageFetch:
+    case SpvOpImageGather:
+    case SpvOpImageDrefGather:
+    case SpvOpImageRead:
+    case SpvOpImageWrite:
+    case SpvOpImageSparseSampleImplicitLod:
+    case SpvOpImageSparseSampleExplicitLod:
+    case SpvOpImageSparseSampleDrefImplicitLod:
+    case SpvOpImageSparseSampleDrefExplicitLod:
+    case SpvOpImageSparseSampleProjImplicitLod:
+    case SpvOpImageSparseSampleProjExplicitLod:
+    case SpvOpImageSparseSampleProjDrefImplicitLod:
+    case SpvOpImageSparseSampleProjDrefExplicitLod:
+    case SpvOpImageSparseFetch:
+    case SpvOpImageSparseGather:
+    case SpvOpImageSparseDrefGather:
+    case SpvOpImageSparseRead:
+    case SpvOpImageSampleFootprintNV:
+    case SpvOpImage:
+    case SpvOpImageQueryFormat:
+    case SpvOpImageQueryLevels:
+    case SpvOpImageQueryLod:
+    case SpvOpImageQueryOrder:
+    case SpvOpImageQuerySamples:
+    case SpvOpImageQuerySize:
+    case SpvOpImageQuerySizeLod:
+    case SpvOpSampledImage:
+      // We ignore all instructions related to accessing images, since we do not
+      // donate images.
+      return false;
+    case SpvOpLoad:
+      switch (donor_ir_context->get_def_use_mgr()
+                  ->GetDef(instruction.type_id())
+                  ->opcode()) {
+        case SpvOpTypeImage:
+        case SpvOpTypeSampledImage:
+        case SpvOpTypeSampler:
+          // Again, we ignore instructions that relate to accessing images.
+          return false;
+        default:
+          break;
+      }
+    default:
+      break;
+  }
+
+  // Examine each id input operand to the instruction.  If it turns out that we
+  // have skipped any of these operands then we cannot donate the instruction.
+  bool result = true;
+  instruction.WhileEachInId(
+      [donor_ir_context, &original_id_to_donated_id, &result,
+       &skipped_instructions](const uint32_t* in_id) -> bool {
+        if (!original_id_to_donated_id.count(*in_id)) {
+          // We do not have a mapped result id for this id operand.  That either
+          // means that it is a forward reference (which is OK), that we skipped
+          // the instruction that generated it (which is not OK), or that it is
+          // the id of a function or global value that we did not donate (which
+          // is not OK).  We check for the latter two cases.
+          if (skipped_instructions.count(*in_id) ||
+              // A function or global value does not have an associated basic
+              // block.
+              !donor_ir_context->get_instr_block(*in_id)) {
+            result = false;
+            return false;
+          }
+        }
+        return true;
+      });
+  return result;
+}
+
+bool FuzzerPassDonateModules::IsBasicType(
+    const opt::Instruction& instruction) const {
+  switch (instruction.opcode()) {
+    case SpvOpTypeArray:
+    case SpvOpTypeFloat:
+    case SpvOpTypeInt:
+    case SpvOpTypeMatrix:
+    case SpvOpTypeStruct:
+    case SpvOpTypeVector:
+      return true;
+    default:
+      return false;
+  }
+}
+
 std::vector<uint32_t>
 FuzzerPassDonateModules::GetFunctionsInCallGraphTopologicalOrder(
     opt::IRContext* context) {
@@ -735,5 +798,333 @@
   return result;
 }
 
+void FuzzerPassDonateModules::HandleOpArrayLength(
+    const opt::Instruction& instruction,
+    std::map<uint32_t, uint32_t>* original_id_to_donated_id,
+    std::vector<protobufs::Instruction>* donated_instructions) const {
+  assert(instruction.opcode() == SpvOpArrayLength &&
+         "Precondition: instruction must be OpArrayLength.");
+  uint32_t donated_variable_id =
+      original_id_to_donated_id->at(instruction.GetSingleWordInOperand(0));
+  auto donated_variable_instruction =
+      GetIRContext()->get_def_use_mgr()->GetDef(donated_variable_id);
+  auto pointer_to_struct_instruction =
+      GetIRContext()->get_def_use_mgr()->GetDef(
+          donated_variable_instruction->type_id());
+  assert(pointer_to_struct_instruction->opcode() == SpvOpTypePointer &&
+         "Type of variable must be pointer.");
+  auto donated_struct_type_instruction =
+      GetIRContext()->get_def_use_mgr()->GetDef(
+          pointer_to_struct_instruction->GetSingleWordInOperand(1));
+  assert(donated_struct_type_instruction->opcode() == SpvOpTypeStruct &&
+         "Pointee type of pointer used by OpArrayLength must be struct.");
+  assert(donated_struct_type_instruction->NumInOperands() ==
+             instruction.GetSingleWordInOperand(1) + 1 &&
+         "OpArrayLength must refer to the final member of the given "
+         "struct.");
+  uint32_t fixed_size_array_type_id =
+      donated_struct_type_instruction->GetSingleWordInOperand(
+          donated_struct_type_instruction->NumInOperands() - 1);
+  auto fixed_size_array_type_instruction =
+      GetIRContext()->get_def_use_mgr()->GetDef(fixed_size_array_type_id);
+  assert(fixed_size_array_type_instruction->opcode() == SpvOpTypeArray &&
+         "The donated array type must be fixed-size.");
+  auto array_size_id =
+      fixed_size_array_type_instruction->GetSingleWordInOperand(1);
+
+  if (instruction.result_id() &&
+      !original_id_to_donated_id->count(instruction.result_id())) {
+    original_id_to_donated_id->insert(
+        {instruction.result_id(), GetFuzzerContext()->GetFreshId()});
+  }
+
+  donated_instructions->push_back(MakeInstructionMessage(
+      SpvOpCopyObject, original_id_to_donated_id->at(instruction.type_id()),
+      original_id_to_donated_id->at(instruction.result_id()),
+      opt::Instruction::OperandList({{SPV_OPERAND_TYPE_ID, {array_size_id}}})));
+}
+
+void FuzzerPassDonateModules::HandleDifficultInstruction(
+    const opt::Instruction& instruction,
+    std::map<uint32_t, uint32_t>* original_id_to_donated_id,
+    std::vector<protobufs::Instruction>* donated_instructions,
+    std::set<uint32_t>* skipped_instructions) {
+  if (!instruction.result_id()) {
+    // It does not generate a result id, so it can be ignored.
+    return;
+  }
+  if (!original_id_to_donated_id->count(instruction.type_id())) {
+    // We cannot handle this instruction's result type, so we need to skip it
+    // all together.
+    skipped_instructions->insert(instruction.result_id());
+    return;
+  }
+
+  // We now attempt to replace the instruction with an OpCopyObject.
+  // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3278): We could do
+  //  something more refined here - we could check which operands to the
+  //  instruction could not be donated and replace those operands with
+  //  references to other ids (such as constants), so that we still get an
+  //  instruction with the opcode and easy-to-handle operands of the donor
+  //  instruction.
+  auto remapped_type_id = original_id_to_donated_id->at(instruction.type_id());
+  if (!IsBasicType(
+          *GetIRContext()->get_def_use_mgr()->GetDef(remapped_type_id))) {
+    // The instruction has a non-basic result type, so we cannot replace it with
+    // an object copy of a constant.  We thus skip it completely.
+    // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3279): We could
+    //  instead look for an available id of the right type and generate an
+    //  OpCopyObject of that id.
+    skipped_instructions->insert(instruction.result_id());
+    return;
+  }
+
+  // We are going to add an OpCopyObject instruction.  Add a mapping for the
+  // result id of the original instruction if does not already exist (it may
+  // exist in the case that it has been forward-referenced).
+  if (!original_id_to_donated_id->count(instruction.result_id())) {
+    original_id_to_donated_id->insert(
+        {instruction.result_id(), GetFuzzerContext()->GetFreshId()});
+  }
+
+  // We find or add a zero constant to the receiving module for the type in
+  // question, and add an OpCopyObject instruction that copies this zero.
+  // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3177):
+  //  Using this particular constant is arbitrary, so if we have a
+  //  mechanism for noting that an id use is arbitrary and could be
+  //  fuzzed we should use it here.
+  auto zero_constant = FindOrCreateZeroConstant(remapped_type_id);
+  donated_instructions->push_back(MakeInstructionMessage(
+      SpvOpCopyObject, remapped_type_id,
+      original_id_to_donated_id->at(instruction.result_id()),
+      opt::Instruction::OperandList({{SPV_OPERAND_TYPE_ID, {zero_constant}}})));
+}
+
+void FuzzerPassDonateModules::PrepareInstructionForDonation(
+    const opt::Instruction& instruction, opt::IRContext* donor_ir_context,
+    std::map<uint32_t, uint32_t>* original_id_to_donated_id,
+    std::vector<protobufs::Instruction>* donated_instructions) {
+  // Get the instruction's input operands into donation-ready form,
+  // remapping any id uses in the process.
+  opt::Instruction::OperandList input_operands;
+
+  // Consider each input operand in turn.
+  for (uint32_t in_operand_index = 0;
+       in_operand_index < instruction.NumInOperands(); in_operand_index++) {
+    std::vector<uint32_t> operand_data;
+    const opt::Operand& in_operand = instruction.GetInOperand(in_operand_index);
+    // Check whether this operand is an id.
+    if (spvIsIdType(in_operand.type)) {
+      // This is an id operand - it consists of a single word of data,
+      // which needs to be remapped so that it is replaced with the
+      // donated form of the id.
+      auto operand_id = in_operand.words[0];
+      if (!original_id_to_donated_id->count(operand_id)) {
+        // This is a forward reference.  We will choose a corresponding
+        // donor id for the referenced id and update the mapping to
+        // reflect it.
+
+        // Keep release compilers happy because |donor_ir_context| is only used
+        // in this assertion.
+        (void)(donor_ir_context);
+        assert((donor_ir_context->get_def_use_mgr()
+                        ->GetDef(operand_id)
+                        ->opcode() == SpvOpLabel ||
+                instruction.opcode() == SpvOpPhi) &&
+               "Unsupported forward reference.");
+        original_id_to_donated_id->insert(
+            {operand_id, GetFuzzerContext()->GetFreshId()});
+      }
+      operand_data.push_back(original_id_to_donated_id->at(operand_id));
+    } else {
+      // For non-id operands, we just add each of the data words.
+      for (auto word : in_operand.words) {
+        operand_data.push_back(word);
+      }
+    }
+    input_operands.push_back({in_operand.type, operand_data});
+  }
+
+  if (instruction.opcode() == SpvOpVariable &&
+      instruction.NumInOperands() == 1) {
+    // This is an uninitialized local variable.  Initialize it to zero.
+    input_operands.push_back(
+        {SPV_OPERAND_TYPE_ID,
+         {FindOrCreateZeroConstant(fuzzerutil::GetPointeeTypeIdFromPointerType(
+             GetIRContext(),
+             original_id_to_donated_id->at(instruction.type_id())))}});
+  }
+
+  if (instruction.result_id() &&
+      !original_id_to_donated_id->count(instruction.result_id())) {
+    original_id_to_donated_id->insert(
+        {instruction.result_id(), GetFuzzerContext()->GetFreshId()});
+  }
+
+  // Remap the result type and result id (if present) of the
+  // instruction, and turn it into a protobuf message.
+  donated_instructions->push_back(MakeInstructionMessage(
+      instruction.opcode(),
+      instruction.type_id()
+          ? original_id_to_donated_id->at(instruction.type_id())
+          : 0,
+      instruction.result_id()
+          ? original_id_to_donated_id->at(instruction.result_id())
+          : 0,
+      input_operands));
+}
+
+void FuzzerPassDonateModules::AddLivesafeFunction(
+    const opt::Function& function_to_donate, opt::IRContext* donor_ir_context,
+    const std::map<uint32_t, uint32_t>& original_id_to_donated_id,
+    const std::vector<protobufs::Instruction>& donated_instructions) {
+  // Various types and constants must be in place for a function to be made
+  // live-safe.  Add them if not already present.
+  FindOrCreateBoolType();  // Needed for comparisons
+  FindOrCreatePointerTo32BitIntegerType(
+      false, SpvStorageClassFunction);  // Needed for adding loop limiters
+  FindOrCreate32BitIntegerConstant(
+      0, false);  // Needed for initializing loop limiters
+  FindOrCreate32BitIntegerConstant(
+      1, false);  // Needed for incrementing loop limiters
+
+  // Get a fresh id for the variable that will be used as a loop limiter.
+  const uint32_t loop_limiter_variable_id = GetFuzzerContext()->GetFreshId();
+  // Choose a random loop limit, and add the required constant to the
+  // module if not already there.
+  const uint32_t loop_limit = FindOrCreate32BitIntegerConstant(
+      GetFuzzerContext()->GetRandomLoopLimit(), false);
+
+  // Consider every loop header in the function to donate, and create a
+  // structure capturing the ids to be used for manipulating the loop
+  // limiter each time the loop is iterated.
+  std::vector<protobufs::LoopLimiterInfo> loop_limiters;
+  for (auto& block : function_to_donate) {
+    if (block.IsLoopHeader()) {
+      protobufs::LoopLimiterInfo loop_limiter;
+      // Grab the loop header's id, mapped to its donated value.
+      loop_limiter.set_loop_header_id(original_id_to_donated_id.at(block.id()));
+      // Get fresh ids that will be used to load the loop limiter, increment
+      // it, compare it with the loop limit, and an id for a new block that
+      // will contain the loop's original terminator.
+      loop_limiter.set_load_id(GetFuzzerContext()->GetFreshId());
+      loop_limiter.set_increment_id(GetFuzzerContext()->GetFreshId());
+      loop_limiter.set_compare_id(GetFuzzerContext()->GetFreshId());
+      loop_limiter.set_logical_op_id(GetFuzzerContext()->GetFreshId());
+      loop_limiters.emplace_back(loop_limiter);
+    }
+  }
+
+  // Consider every access chain in the function to donate, and create a
+  // structure containing the ids necessary to clamp the access chain
+  // indices to be in-bounds.
+  std::vector<protobufs::AccessChainClampingInfo> access_chain_clamping_info;
+  for (auto& block : function_to_donate) {
+    for (auto& inst : block) {
+      switch (inst.opcode()) {
+        case SpvOpAccessChain:
+        case SpvOpInBoundsAccessChain: {
+          protobufs::AccessChainClampingInfo clamping_info;
+          clamping_info.set_access_chain_id(
+              original_id_to_donated_id.at(inst.result_id()));
+
+          auto base_object = donor_ir_context->get_def_use_mgr()->GetDef(
+              inst.GetSingleWordInOperand(0));
+          assert(base_object && "The base object must exist.");
+          auto pointer_type = donor_ir_context->get_def_use_mgr()->GetDef(
+              base_object->type_id());
+          assert(pointer_type && pointer_type->opcode() == SpvOpTypePointer &&
+                 "The base object must have pointer type.");
+
+          auto should_be_composite_type =
+              donor_ir_context->get_def_use_mgr()->GetDef(
+                  pointer_type->GetSingleWordInOperand(1));
+
+          // Walk the access chain, creating fresh ids to facilitate
+          // clamping each index.  For simplicity we do this for every
+          // index, even though constant indices will not end up being
+          // clamped.
+          for (uint32_t index = 1; index < inst.NumInOperands(); index++) {
+            auto compare_and_select_ids =
+                clamping_info.add_compare_and_select_ids();
+            compare_and_select_ids->set_first(GetFuzzerContext()->GetFreshId());
+            compare_and_select_ids->set_second(
+                GetFuzzerContext()->GetFreshId());
+
+            // Get the bound for the component being indexed into.
+            uint32_t bound;
+            if (should_be_composite_type->opcode() == SpvOpTypeRuntimeArray) {
+              // The donor is indexing into a runtime array.  We do not
+              // donate runtime arrays.  Instead, we donate a corresponding
+              // fixed-size array for every runtime array.  We should thus
+              // find that donor composite type's result id maps to a fixed-
+              // size array.
+              auto fixed_size_array_type =
+                  GetIRContext()->get_def_use_mgr()->GetDef(
+                      original_id_to_donated_id.at(
+                          should_be_composite_type->result_id()));
+              assert(fixed_size_array_type->opcode() == SpvOpTypeArray &&
+                     "A runtime array type in the donor should have been "
+                     "replaced by a fixed-sized array in the recipient.");
+              // The size of this fixed-size array is a suitable bound.
+              bound = TransformationAddFunction::GetBoundForCompositeIndex(
+                  GetIRContext(), *fixed_size_array_type);
+            } else {
+              bound = TransformationAddFunction::GetBoundForCompositeIndex(
+                  donor_ir_context, *should_be_composite_type);
+            }
+            const uint32_t index_id = inst.GetSingleWordInOperand(index);
+            auto index_inst =
+                donor_ir_context->get_def_use_mgr()->GetDef(index_id);
+            auto index_type_inst = donor_ir_context->get_def_use_mgr()->GetDef(
+                index_inst->type_id());
+            assert(index_type_inst->opcode() == SpvOpTypeInt);
+            assert(index_type_inst->GetSingleWordInOperand(0) == 32);
+            opt::analysis::Integer* index_int_type =
+                donor_ir_context->get_type_mgr()
+                    ->GetType(index_type_inst->result_id())
+                    ->AsInteger();
+            if (index_inst->opcode() != SpvOpConstant) {
+              // We will have to clamp this index, so we need a constant
+              // whose value is one less than the bound, to compare
+              // against and to use as the clamped value.
+              FindOrCreate32BitIntegerConstant(bound - 1,
+                                               index_int_type->IsSigned());
+            }
+            should_be_composite_type =
+                TransformationAddFunction::FollowCompositeIndex(
+                    donor_ir_context, *should_be_composite_type, index_id);
+          }
+          access_chain_clamping_info.push_back(clamping_info);
+          break;
+        }
+        default:
+          break;
+      }
+    }
+  }
+
+  // If the function contains OpKill or OpUnreachable instructions, and has
+  // non-void return type, then we need a value %v to use in order to turn
+  // these into instructions of the form OpReturn %v.
+  uint32_t kill_unreachable_return_value_id;
+  auto function_return_type_inst =
+      donor_ir_context->get_def_use_mgr()->GetDef(function_to_donate.type_id());
+  if (function_return_type_inst->opcode() == SpvOpTypeVoid) {
+    // The return type is void, so we don't need a return value.
+    kill_unreachable_return_value_id = 0;
+  } else {
+    // We do need a return value; we use zero.
+    assert(function_return_type_inst->opcode() != SpvOpTypePointer &&
+           "Function return type must not be a pointer.");
+    kill_unreachable_return_value_id = FindOrCreateZeroConstant(
+        original_id_to_donated_id.at(function_return_type_inst->result_id()));
+  }
+  // Add the function in a livesafe manner.
+  ApplyTransformation(TransformationAddFunction(
+      donated_instructions, loop_limiter_variable_id, loop_limit, loop_limiters,
+      kill_unreachable_return_value_id, access_chain_clamping_info));
+}
+
 }  // namespace fuzz
 }  // namespace spvtools
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_donate_modules.h b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_donate_modules.h
index ef529db..c59ad71 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_donate_modules.h
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_donate_modules.h
@@ -28,7 +28,7 @@
 class FuzzerPassDonateModules : public FuzzerPass {
  public:
   FuzzerPassDonateModules(
-      opt::IRContext* ir_context, FactManager* fact_manager,
+      opt::IRContext* ir_context, TransformationContext* transformation_context,
       FuzzerContext* fuzzer_context,
       protobufs::TransformationSequence* transformations,
       const std::vector<fuzzerutil::ModuleSupplier>& donor_suppliers);
@@ -66,6 +66,11 @@
       opt::IRContext* donor_ir_context,
       std::map<uint32_t, uint32_t>* original_id_to_donated_id);
 
+  // Helper method for HandleTypesAndValues, to handle a single type/value.
+  void HandleTypeOrValue(
+      const opt::Instruction& type_or_value,
+      std::map<uint32_t, uint32_t>* original_id_to_donated_id);
+
   // Assumes that |donor_ir_context| does not exhibit recursion.  Considers the
   // functions in |donor_ir_context|'s call graph in a reverse-topologically-
   // sorted order (leaves-to-root), adding each function to the recipient
@@ -77,6 +82,68 @@
                        std::map<uint32_t, uint32_t>* original_id_to_donated_id,
                        bool make_livesafe);
 
+  // During donation we will have to ignore some instructions, e.g. because they
+  // use opcodes that we cannot support or because they reference the ids of
+  // instructions that have not been donated.  This function encapsulates the
+  // logic for deciding which whether instruction |instruction| from
+  // |donor_ir_context| can be donated.
+  bool CanDonateInstruction(
+      opt::IRContext* donor_ir_context, const opt::Instruction& instruction,
+      const std::map<uint32_t, uint32_t>& original_id_to_donated_id,
+      const std::set<uint32_t>& skipped_instructions) const;
+
+  // We treat the OpArrayLength instruction specially.  In the donor shader this
+  // instruction yields the length of a runtime array that is the final member
+  // of a struct.  During donation, we will have converted the runtime array
+  // type, and the associated struct field, into a fixed-size array.
+  //
+  // Instead of donating this instruction, we turn it into an OpCopyObject
+  // instruction that copies the size of the fixed-size array.
+  void HandleOpArrayLength(
+      const opt::Instruction& instruction,
+      std::map<uint32_t, uint32_t>* original_id_to_donated_id,
+      std::vector<protobufs::Instruction>* donated_instructions) const;
+
+  // The instruction |instruction| is required to be an instruction that cannot
+  // be easily donated, either because it uses an unsupported opcode, has an
+  // unsupported result type, or uses id operands that could not be donated.
+  //
+  // If |instruction| generates a result id, the function attempts to add a
+  // substitute for |instruction| to |donated_instructions| that has the correct
+  // result type.  If this cannot be done, the instruction's result id is added
+  // to |skipped_instructions|.  The mapping from donor ids to recipient ids is
+  // managed by |original_id_to_donated_id|.
+  void HandleDifficultInstruction(
+      const opt::Instruction& instruction,
+      std::map<uint32_t, uint32_t>* original_id_to_donated_id,
+      std::vector<protobufs::Instruction>* donated_instructions,
+      std::set<uint32_t>* skipped_instructions);
+
+  // Adds an instruction based in |instruction| to |donated_instructions| in a
+  // form ready for donation.  The original instruction comes from
+  // |donor_ir_context|, and |original_id_to_donated_id| maps ids from
+  // |donor_ir_context| to corresponding ids in the recipient module.
+  void PrepareInstructionForDonation(
+      const opt::Instruction& instruction, opt::IRContext* donor_ir_context,
+      std::map<uint32_t, uint32_t>* original_id_to_donated_id,
+      std::vector<protobufs::Instruction>* donated_instructions);
+
+  // Requires that |donated_instructions| represents a prepared version of the
+  // instructions of |function_to_donate| (which comes from |donor_ir_context|)
+  // ready for donation, and |original_id_to_donated_id| maps ids from
+  // |donor_ir_context| to their corresponding ids in the recipient module.
+  //
+  // Adds a livesafe version of the function, based on |donated_instructions|,
+  // to the recipient module.
+  void AddLivesafeFunction(
+      const opt::Function& function_to_donate, opt::IRContext* donor_ir_context,
+      const std::map<uint32_t, uint32_t>& original_id_to_donated_id,
+      const std::vector<protobufs::Instruction>& donated_instructions);
+
+  // Returns true if and only if |instruction| is a scalar, vector, matrix,
+  // array or struct; i.e. it is not an opaque type.
+  bool IsBasicType(const opt::Instruction& instruction) const;
+
   // Returns the ids of all functions in |context| in a topological order in
   // relation to the call graph of |context|, which is assumed to be recursion-
   // free.
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_merge_blocks.cpp b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_merge_blocks.cpp
index ca1bfb3..49778ae 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_merge_blocks.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_merge_blocks.cpp
@@ -22,10 +22,11 @@
 namespace fuzz {
 
 FuzzerPassMergeBlocks::FuzzerPassMergeBlocks(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassMergeBlocks::~FuzzerPassMergeBlocks() = default;
 
@@ -44,7 +45,8 @@
       // For other blocks, we add a transformation to merge the block into its
       // predecessor if that transformation would be applicable.
       TransformationMergeBlocks transformation(block.id());
-      if (transformation.IsApplicable(GetIRContext(), *GetFactManager())) {
+      if (transformation.IsApplicable(GetIRContext(),
+                                      *GetTransformationContext())) {
         potential_transformations.push_back(transformation);
       }
     }
@@ -54,8 +56,9 @@
     uint32_t index = GetFuzzerContext()->RandomIndex(potential_transformations);
     auto transformation = potential_transformations.at(index);
     potential_transformations.erase(potential_transformations.begin() + index);
-    if (transformation.IsApplicable(GetIRContext(), *GetFactManager())) {
-      transformation.Apply(GetIRContext(), GetFactManager());
+    if (transformation.IsApplicable(GetIRContext(),
+                                    *GetTransformationContext())) {
+      transformation.Apply(GetIRContext(), GetTransformationContext());
       *GetTransformations()->add_transformation() = transformation.ToMessage();
     }
   }
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_merge_blocks.h b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_merge_blocks.h
index 457e591..1a6c2c2 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_merge_blocks.h
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_merge_blocks.h
@@ -23,7 +23,8 @@
 // A fuzzer pass for merging blocks in the module.
 class FuzzerPassMergeBlocks : public FuzzerPass {
  public:
-  FuzzerPassMergeBlocks(opt::IRContext* ir_context, FactManager* fact_manager,
+  FuzzerPassMergeBlocks(opt::IRContext* ir_context,
+                        TransformationContext* transformation_context,
                         FuzzerContext* fuzzer_context,
                         protobufs::TransformationSequence* transformations);
 
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_obfuscate_constants.cpp b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_obfuscate_constants.cpp
index 2caf0c6..4ced507 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_obfuscate_constants.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_obfuscate_constants.cpp
@@ -25,10 +25,11 @@
 namespace fuzz {
 
 FuzzerPassObfuscateConstants::FuzzerPassObfuscateConstants(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassObfuscateConstants::~FuzzerPassObfuscateConstants() = default;
 
@@ -83,12 +84,13 @@
       bool_constant_use, lhs_id, rhs_id, comparison_opcode,
       GetFuzzerContext()->GetFreshId());
   // The transformation should be applicable by construction.
-  assert(transformation.IsApplicable(GetIRContext(), *GetFactManager()));
+  assert(
+      transformation.IsApplicable(GetIRContext(), *GetTransformationContext()));
 
   // Applying this transformation yields a pointer to the new instruction that
   // computes the result of the binary expression.
-  auto binary_operator_instruction =
-      transformation.ApplyWithResult(GetIRContext(), GetFactManager());
+  auto binary_operator_instruction = transformation.ApplyWithResult(
+      GetIRContext(), GetTransformationContext());
 
   // Add this transformation to the sequence of transformations that have been
   // applied.
@@ -245,7 +247,9 @@
   // with uniforms of the same value.
 
   auto available_types_with_uniforms =
-      GetFactManager()->GetTypesForWhichUniformValuesAreKnown();
+      GetTransformationContext()
+          ->GetFactManager()
+          ->GetTypesForWhichUniformValuesAreKnown();
   if (available_types_with_uniforms.empty()) {
     // Do not try to obfuscate if we do not have access to any uniform
     // elements with known values.
@@ -254,9 +258,10 @@
   auto chosen_type_id =
       available_types_with_uniforms[GetFuzzerContext()->RandomIndex(
           available_types_with_uniforms)];
-  auto available_constants =
-      GetFactManager()->GetConstantsAvailableFromUniformsForType(
-          GetIRContext(), chosen_type_id);
+  auto available_constants = GetTransformationContext()
+                                 ->GetFactManager()
+                                 ->GetConstantsAvailableFromUniformsForType(
+                                     GetIRContext(), chosen_type_id);
   if (available_constants.size() == 1) {
     // TODO(afd): for now we only obfuscate a boolean if there are at least
     //  two constants available from uniforms, so that we can do a
@@ -308,8 +313,11 @@
 
   // Check whether we know that any uniforms are guaranteed to be equal to the
   // scalar constant associated with |constant_use|.
-  auto uniform_descriptors = GetFactManager()->GetUniformDescriptorsForConstant(
-      GetIRContext(), constant_use.id_of_interest());
+  auto uniform_descriptors =
+      GetTransformationContext()
+          ->GetFactManager()
+          ->GetUniformDescriptorsForConstant(GetIRContext(),
+                                             constant_use.id_of_interest());
   if (uniform_descriptors.empty()) {
     // No relevant uniforms, so do not obfuscate.
     return;
@@ -324,8 +332,9 @@
       constant_use, uniform_descriptor, GetFuzzerContext()->GetFreshId(),
       GetFuzzerContext()->GetFreshId());
   // Transformation should be applicable by construction.
-  assert(transformation.IsApplicable(GetIRContext(), *GetFactManager()));
-  transformation.Apply(GetIRContext(), GetFactManager());
+  assert(
+      transformation.IsApplicable(GetIRContext(), *GetTransformationContext()));
+  transformation.Apply(GetIRContext(), GetTransformationContext());
   *GetTransformations()->add_transformation() = transformation.ToMessage();
 }
 
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_obfuscate_constants.h b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_obfuscate_constants.h
index f34717b..7755d21 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_obfuscate_constants.h
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_obfuscate_constants.h
@@ -28,7 +28,7 @@
 class FuzzerPassObfuscateConstants : public FuzzerPass {
  public:
   FuzzerPassObfuscateConstants(
-      opt::IRContext* ir_context, FactManager* fact_manager,
+      opt::IRContext* ir_context, TransformationContext* transformation_context,
       FuzzerContext* fuzzer_context,
       protobufs::TransformationSequence* transformations);
 
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_outline_functions.cpp b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_outline_functions.cpp
index d59c195..1665d05 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_outline_functions.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_outline_functions.cpp
@@ -23,10 +23,11 @@
 namespace fuzz {
 
 FuzzerPassOutlineFunctions::FuzzerPassOutlineFunctions(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassOutlineFunctions::~FuzzerPassOutlineFunctions() = default;
 
@@ -88,8 +89,9 @@
         /*new_callee_result_id*/ GetFuzzerContext()->GetFreshId(),
         /*input_id_to_fresh_id*/ std::move(input_id_to_fresh_id),
         /*output_id_to_fresh_id*/ std::move(output_id_to_fresh_id));
-    if (transformation.IsApplicable(GetIRContext(), *GetFactManager())) {
-      transformation.Apply(GetIRContext(), GetFactManager());
+    if (transformation.IsApplicable(GetIRContext(),
+                                    *GetTransformationContext())) {
+      transformation.Apply(GetIRContext(), GetTransformationContext());
       *GetTransformations()->add_transformation() = transformation.ToMessage();
     }
   }
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_outline_functions.h b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_outline_functions.h
index 5448e7d..6532ed9 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_outline_functions.h
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_outline_functions.h
@@ -25,7 +25,7 @@
 class FuzzerPassOutlineFunctions : public FuzzerPass {
  public:
   FuzzerPassOutlineFunctions(
-      opt::IRContext* ir_context, FactManager* fact_manager,
+      opt::IRContext* ir_context, TransformationContext* transformation_context,
       FuzzerContext* fuzzer_context,
       protobufs::TransformationSequence* transformations);
 
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_permute_blocks.cpp b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_permute_blocks.cpp
index af6d2a5..27a2d67 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_permute_blocks.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_permute_blocks.cpp
@@ -20,10 +20,11 @@
 namespace fuzz {
 
 FuzzerPassPermuteBlocks::FuzzerPassPermuteBlocks(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassPermuteBlocks::~FuzzerPassPermuteBlocks() = default;
 
@@ -66,8 +67,9 @@
       // down indefinitely.
       while (true) {
         TransformationMoveBlockDown transformation(*id);
-        if (transformation.IsApplicable(GetIRContext(), *GetFactManager())) {
-          transformation.Apply(GetIRContext(), GetFactManager());
+        if (transformation.IsApplicable(GetIRContext(),
+                                        *GetTransformationContext())) {
+          transformation.Apply(GetIRContext(), GetTransformationContext());
           *GetTransformations()->add_transformation() =
               transformation.ToMessage();
         } else {
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_permute_blocks.h b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_permute_blocks.h
index 6735e95..f2d3b39 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_permute_blocks.h
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_permute_blocks.h
@@ -24,7 +24,8 @@
 // manner.
 class FuzzerPassPermuteBlocks : public FuzzerPass {
  public:
-  FuzzerPassPermuteBlocks(opt::IRContext* ir_context, FactManager* fact_manager,
+  FuzzerPassPermuteBlocks(opt::IRContext* ir_context,
+                          TransformationContext* transformation_context,
                           FuzzerContext* fuzzer_context,
                           protobufs::TransformationSequence* transformations);
 
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_permute_function_parameters.cpp b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_permute_function_parameters.cpp
index 2c49860..57d9cab 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_permute_function_parameters.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_permute_function_parameters.cpp
@@ -25,10 +25,11 @@
 namespace fuzz {
 
 FuzzerPassPermuteFunctionParameters::FuzzerPassPermuteFunctionParameters(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassPermuteFunctionParameters::~FuzzerPassPermuteFunctionParameters() =
     default;
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_permute_function_parameters.h b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_permute_function_parameters.h
index bc79804..3f32864 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_permute_function_parameters.h
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_permute_function_parameters.h
@@ -30,7 +30,7 @@
 class FuzzerPassPermuteFunctionParameters : public FuzzerPass {
  public:
   FuzzerPassPermuteFunctionParameters(
-      opt::IRContext* ir_context, FactManager* fact_manager,
+      opt::IRContext* ir_context, TransformationContext* transformation_context,
       FuzzerContext* fuzzer_context,
       protobufs::TransformationSequence* transformations);
 
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_split_blocks.cpp b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_split_blocks.cpp
index 6a2ea4d..15c6790 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_split_blocks.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_split_blocks.cpp
@@ -23,10 +23,11 @@
 namespace fuzz {
 
 FuzzerPassSplitBlocks::FuzzerPassSplitBlocks(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassSplitBlocks::~FuzzerPassSplitBlocks() = default;
 
@@ -95,8 +96,9 @@
     // If the position we have chosen turns out to be a valid place to split
     // the block, we apply the split. Otherwise the block just doesn't get
     // split.
-    if (transformation.IsApplicable(GetIRContext(), *GetFactManager())) {
-      transformation.Apply(GetIRContext(), GetFactManager());
+    if (transformation.IsApplicable(GetIRContext(),
+                                    *GetTransformationContext())) {
+      transformation.Apply(GetIRContext(), GetTransformationContext());
       *GetTransformations()->add_transformation() = transformation.ToMessage();
     }
   }
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_split_blocks.h b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_split_blocks.h
index 6e56dde..278ec6d 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_split_blocks.h
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_split_blocks.h
@@ -24,7 +24,8 @@
 // can be very useful for giving other passes a chance to apply.
 class FuzzerPassSplitBlocks : public FuzzerPass {
  public:
-  FuzzerPassSplitBlocks(opt::IRContext* ir_context, FactManager* fact_manager,
+  FuzzerPassSplitBlocks(opt::IRContext* ir_context,
+                        TransformationContext* transformation_context,
                         FuzzerContext* fuzzer_context,
                         protobufs::TransformationSequence* transformations);
 
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_swap_commutable_operands.cpp b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_swap_commutable_operands.cpp
index 4df97c9..321e8ef 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_swap_commutable_operands.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_swap_commutable_operands.cpp
@@ -22,10 +22,11 @@
 namespace fuzz {
 
 FuzzerPassSwapCommutableOperands::FuzzerPassSwapCommutableOperands(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassSwapCommutableOperands::~FuzzerPassSwapCommutableOperands() = default;
 
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_swap_commutable_operands.h b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_swap_commutable_operands.h
index b0206de..74d937d 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_swap_commutable_operands.h
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_swap_commutable_operands.h
@@ -26,7 +26,7 @@
 class FuzzerPassSwapCommutableOperands : public FuzzerPass {
  public:
   FuzzerPassSwapCommutableOperands(
-      opt::IRContext* ir_context, FactManager* fact_manager,
+      opt::IRContext* ir_context, TransformationContext* transformation_context,
       FuzzerContext* fuzzer_context,
       protobufs::TransformationSequence* transformations);
 
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_toggle_access_chain_instruction.cpp b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_toggle_access_chain_instruction.cpp
index 9fb175b..4f26cba 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_toggle_access_chain_instruction.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_toggle_access_chain_instruction.cpp
@@ -22,10 +22,11 @@
 namespace fuzz {
 
 FuzzerPassToggleAccessChainInstruction::FuzzerPassToggleAccessChainInstruction(
-    opt::IRContext* ir_context, FactManager* fact_manager,
+    opt::IRContext* ir_context, TransformationContext* transformation_context,
     FuzzerContext* fuzzer_context,
     protobufs::TransformationSequence* transformations)
-    : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
+    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
+                 transformations) {}
 
 FuzzerPassToggleAccessChainInstruction::
     ~FuzzerPassToggleAccessChainInstruction() = default;
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_toggle_access_chain_instruction.h b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_toggle_access_chain_instruction.h
index ec8c3f7..d77c7cb 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_toggle_access_chain_instruction.h
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_pass_toggle_access_chain_instruction.h
@@ -25,7 +25,7 @@
 class FuzzerPassToggleAccessChainInstruction : public FuzzerPass {
  public:
   FuzzerPassToggleAccessChainInstruction(
-      opt::IRContext* ir_context, FactManager* fact_manager,
+      opt::IRContext* ir_context, TransformationContext* transformation_context,
       FuzzerContext* fuzzer_context,
       protobufs::TransformationSequence* transformations);
 
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_util.cpp b/third_party/spirv-tools/src/source/fuzz/fuzzer_util.cpp
index 4bfa195..f09943f 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_util.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_util.cpp
@@ -218,6 +218,12 @@
 }
 
 bool CanMakeSynonymOf(opt::IRContext* ir_context, opt::Instruction* inst) {
+  if (inst->opcode() == SpvOpSampledImage) {
+    // The SPIR-V data rules say that only very specific instructions may
+    // may consume the result id of an OpSampledImage, and this excludes the
+    // instructions that are used for making synonyms.
+    return false;
+  }
   if (!inst->HasResultId()) {
     // We can only make a synonym of an instruction that generates an id.
     return false;
@@ -329,11 +335,11 @@
   return array_length_constant->GetU32();
 }
 
-bool IsValid(opt::IRContext* context) {
+bool IsValid(opt::IRContext* context, spv_validator_options validator_options) {
   std::vector<uint32_t> binary;
   context->module()->ToBinary(&binary, false);
   SpirvTools tools(context->grammar().target_env());
-  return tools.Validate(binary);
+  return tools.Validate(binary.data(), binary.size(), validator_options);
 }
 
 std::unique_ptr<opt::IRContext> CloneIRContext(opt::IRContext* context) {
@@ -537,6 +543,13 @@
   return 0;
 }
 
+bool IsNullConstantSupported(const opt::analysis::Type& type) {
+  return type.AsBool() || type.AsInteger() || type.AsFloat() ||
+         type.AsMatrix() || type.AsVector() || type.AsArray() ||
+         type.AsStruct() || type.AsPointer() || type.AsEvent() ||
+         type.AsDeviceEvent() || type.AsReserveId() || type.AsQueue();
+}
+
 }  // namespace fuzzerutil
 
 }  // namespace fuzz
diff --git a/third_party/spirv-tools/src/source/fuzz/fuzzer_util.h b/third_party/spirv-tools/src/source/fuzz/fuzzer_util.h
index 7be0d59..886029a 100644
--- a/third_party/spirv-tools/src/source/fuzz/fuzzer_util.h
+++ b/third_party/spirv-tools/src/source/fuzz/fuzzer_util.h
@@ -132,8 +132,9 @@
 uint32_t GetArraySize(const opt::Instruction& array_type_instruction,
                       opt::IRContext* context);
 
-// Returns true if and only if |context| is valid, according to the validator.
-bool IsValid(opt::IRContext* context);
+// Returns true if and only if |context| is valid, according to the validator
+// instantiated with |validator_options|.
+bool IsValid(opt::IRContext* context, spv_validator_options validator_options);
 
 // Returns a clone of |context|, by writing |context| to a binary and then
 // parsing it again.
@@ -209,6 +210,10 @@
 uint32_t MaybeGetPointerType(opt::IRContext* context, uint32_t pointee_type_id,
                              SpvStorageClass storage_class);
 
+// Returns true if and only if |type| is one of the types for which it is legal
+// to have an OpConstantNull value.
+bool IsNullConstantSupported(const opt::analysis::Type& type);
+
 }  // namespace fuzzerutil
 
 }  // namespace fuzz
diff --git a/third_party/spirv-tools/src/source/fuzz/protobufs/spvtoolsfuzz.proto b/third_party/spirv-tools/src/source/fuzz/protobufs/spvtoolsfuzz.proto
index b816e3b..68460a9 100644
--- a/third_party/spirv-tools/src/source/fuzz/protobufs/spvtoolsfuzz.proto
+++ b/third_party/spirv-tools/src/source/fuzz/protobufs/spvtoolsfuzz.proto
@@ -372,6 +372,8 @@
     TransformationSwapCommutableOperands swap_commutable_operands = 41;
     TransformationPermuteFunctionParameters permute_function_parameters = 42;
     TransformationToggleAccessChainInstruction toggle_access_chain_instruction = 43;
+    TransformationAddConstantNull add_constant_null = 44;
+    TransformationComputeDataSynonymFactClosure compute_data_synonym_fact_closure = 45;
     // Add additional option using the next available number.
   }
 }
@@ -422,6 +424,18 @@
 
 }
 
+message TransformationAddConstantNull {
+
+  // Adds a null constant.
+
+  // Id for the constant
+  uint32 fresh_id = 1;
+
+  // Type of the constant
+  uint32 type_id = 2;
+
+}
+
 message TransformationAddConstantScalar {
 
   // Adds a constant of the given scalar type.
@@ -547,8 +561,9 @@
 
 message TransformationAddGlobalVariable {
 
-  // Adds a global variable of the given type to the module, with Private
-  // storage class and optionally with an initializer.
+  // Adds a global variable of the given type to the module, with Private or
+  // Workgroup storage class, and optionally (for the Private case) with an
+  // initializer.
 
   // Fresh id for the global variable
   uint32 fresh_id = 1;
@@ -556,13 +571,15 @@
   // The type of the global variable
   uint32 type_id = 2;
 
+  uint32 storage_class = 3;
+
   // Initial value of the variable
-  uint32 initializer_id = 3;
+  uint32 initializer_id = 4;
 
   // True if and only if the behaviour of the module should not depend on the
   // value of the variable, in which case stores to the variable can be
   // performed in an arbitrary fashion.
-  bool value_is_irrelevant = 4;
+  bool value_is_irrelevant = 5;
 
 }
 
@@ -765,6 +782,19 @@
 
 }
 
+message TransformationComputeDataSynonymFactClosure {
+
+  // A transformation that impacts the fact manager only, forcing a computation
+  // of the closure of data synonym facts, so that e.g. if the components of
+  // vectors v and w are known to be pairwise synonymous, it is deduced that v
+  // and w are themselves synonymous.
+
+  // When searching equivalence classes for implied facts, equivalence classes
+  // larger than this size will be skipped.
+  uint32 maximum_equivalence_class_size = 1;
+
+}
+
 message TransformationCopyObject {
 
   // A transformation that introduces an OpCopyObject instruction to make a
diff --git a/third_party/spirv-tools/src/source/fuzz/replayer.cpp b/third_party/spirv-tools/src/source/fuzz/replayer.cpp
index 398ce59..6312cba 100644
--- a/third_party/spirv-tools/src/source/fuzz/replayer.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/replayer.cpp
@@ -26,6 +26,7 @@
 #include "source/fuzz/transformation_add_type_float.h"
 #include "source/fuzz/transformation_add_type_int.h"
 #include "source/fuzz/transformation_add_type_pointer.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/fuzz/transformation_move_block_down.h"
 #include "source/fuzz/transformation_replace_boolean_constant_with_constant_binary.h"
 #include "source/fuzz/transformation_replace_constant_with_uniform.h"
@@ -37,18 +38,22 @@
 namespace fuzz {
 
 struct Replayer::Impl {
-  explicit Impl(spv_target_env env, bool validate)
-      : target_env(env), validate_during_replay(validate) {}
+  Impl(spv_target_env env, bool validate, spv_validator_options options)
+      : target_env(env),
+        validate_during_replay(validate),
+        validator_options(options) {}
 
-  const spv_target_env target_env;  // Target environment.
-  MessageConsumer consumer;         // Message consumer.
-
+  const spv_target_env target_env;    // Target environment.
+  MessageConsumer consumer;           // Message consumer.
   const bool validate_during_replay;  // Controls whether the validator should
                                       // be run after every replay step.
+  spv_validator_options validator_options;  // Options to control
+                                            // validation
 };
 
-Replayer::Replayer(spv_target_env env, bool validate_during_replay)
-    : impl_(MakeUnique<Impl>(env, validate_during_replay)) {}
+Replayer::Replayer(spv_target_env env, bool validate_during_replay,
+                   spv_validator_options validator_options)
+    : impl_(MakeUnique<Impl>(env, validate_during_replay, validator_options)) {}
 
 Replayer::~Replayer() = default;
 
@@ -74,7 +79,8 @@
   }
 
   // Initial binary should be valid.
-  if (!tools.Validate(&binary_in[0], binary_in.size())) {
+  if (!tools.Validate(&binary_in[0], binary_in.size(),
+                      impl_->validator_options)) {
     impl_->consumer(SPV_MSG_INFO, nullptr, {},
                     "Initial binary is invalid; stopping.");
     return Replayer::ReplayerResultStatus::kInitialBinaryInvalid;
@@ -94,16 +100,19 @@
 
   FactManager fact_manager;
   fact_manager.AddFacts(impl_->consumer, initial_facts, ir_context.get());
+  TransformationContext transformation_context(&fact_manager,
+                                               impl_->validator_options);
 
   // Consider the transformation proto messages in turn.
   for (auto& message : transformation_sequence_in.transformation()) {
     auto transformation = Transformation::FromMessage(message);
 
     // Check whether the transformation can be applied.
-    if (transformation->IsApplicable(ir_context.get(), fact_manager)) {
+    if (transformation->IsApplicable(ir_context.get(),
+                                     transformation_context)) {
       // The transformation is applicable, so apply it, and copy it to the
       // sequence of transformations that were applied.
-      transformation->Apply(ir_context.get(), &fact_manager);
+      transformation->Apply(ir_context.get(), &transformation_context);
       *transformation_sequence_out->add_transformation() = message;
 
       if (impl_->validate_during_replay) {
@@ -111,8 +120,8 @@
         ir_context->module()->ToBinary(&binary_to_validate, false);
 
         // Check whether the latest transformation led to a valid binary.
-        if (!tools.Validate(&binary_to_validate[0],
-                            binary_to_validate.size())) {
+        if (!tools.Validate(&binary_to_validate[0], binary_to_validate.size(),
+                            impl_->validator_options)) {
           impl_->consumer(SPV_MSG_INFO, nullptr, {},
                           "Binary became invalid during replay (set a "
                           "breakpoint to inspect); stopping.");
diff --git a/third_party/spirv-tools/src/source/fuzz/replayer.h b/third_party/spirv-tools/src/source/fuzz/replayer.h
index 1d58bae..e77d840 100644
--- a/third_party/spirv-tools/src/source/fuzz/replayer.h
+++ b/third_party/spirv-tools/src/source/fuzz/replayer.h
@@ -37,7 +37,8 @@
   };
 
   // Constructs a replayer from the given target environment.
-  explicit Replayer(spv_target_env env, bool validate_during_replay);
+  Replayer(spv_target_env env, bool validate_during_replay,
+           spv_validator_options validator_options);
 
   // Disables copy/move constructor/assignment operations.
   Replayer(const Replayer&) = delete;
diff --git a/third_party/spirv-tools/src/source/fuzz/shrinker.cpp b/third_party/spirv-tools/src/source/fuzz/shrinker.cpp
index 1bb92f1..b8e4145 100644
--- a/third_party/spirv-tools/src/source/fuzz/shrinker.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/shrinker.cpp
@@ -60,20 +60,27 @@
 }  // namespace
 
 struct Shrinker::Impl {
-  explicit Impl(spv_target_env env, uint32_t limit, bool validate)
-      : target_env(env), step_limit(limit), validate_during_replay(validate) {}
+  Impl(spv_target_env env, uint32_t limit, bool validate,
+       spv_validator_options options)
+      : target_env(env),
+        step_limit(limit),
+        validate_during_replay(validate),
+        validator_options(options) {}
 
-  const spv_target_env target_env;    // Target environment.
-  MessageConsumer consumer;           // Message consumer.
-  const uint32_t step_limit;          // Step limit for reductions.
-  const bool validate_during_replay;  // Determines whether to check for
-                                      // validity during the replaying of
-                                      // transformations.
+  const spv_target_env target_env;          // Target environment.
+  MessageConsumer consumer;                 // Message consumer.
+  const uint32_t step_limit;                // Step limit for reductions.
+  const bool validate_during_replay;        // Determines whether to check for
+                                            // validity during the replaying of
+                                            // transformations.
+  spv_validator_options validator_options;  // Options to control validation.
 };
 
 Shrinker::Shrinker(spv_target_env env, uint32_t step_limit,
-                   bool validate_during_replay)
-    : impl_(MakeUnique<Impl>(env, step_limit, validate_during_replay)) {}
+                   bool validate_during_replay,
+                   spv_validator_options validator_options)
+    : impl_(MakeUnique<Impl>(env, step_limit, validate_during_replay,
+                             validator_options)) {}
 
 Shrinker::~Shrinker() = default;
 
@@ -113,7 +120,8 @@
   // succeeds, (b) get the binary that results from running these
   // transformations, and (c) get the subsequence of the initial transformations
   // that actually apply (in principle this could be a strict subsequence).
-  if (Replayer(impl_->target_env, impl_->validate_during_replay)
+  if (Replayer(impl_->target_env, impl_->validate_during_replay,
+               impl_->validator_options)
           .Run(binary_in, initial_facts, transformation_sequence_in,
                &current_best_binary, &current_best_transformations) !=
       Replayer::ReplayerResultStatus::kComplete) {
@@ -184,7 +192,8 @@
       // transformations inapplicable.
       std::vector<uint32_t> next_binary;
       protobufs::TransformationSequence next_transformation_sequence;
-      if (Replayer(impl_->target_env, false)
+      if (Replayer(impl_->target_env, impl_->validate_during_replay,
+                   impl_->validator_options)
               .Run(binary_in, initial_facts, transformations_with_chunk_removed,
                    &next_binary, &next_transformation_sequence) !=
           Replayer::ReplayerResultStatus::kComplete) {
diff --git a/third_party/spirv-tools/src/source/fuzz/shrinker.h b/third_party/spirv-tools/src/source/fuzz/shrinker.h
index 0163a53..17b15bf 100644
--- a/third_party/spirv-tools/src/source/fuzz/shrinker.h
+++ b/third_party/spirv-tools/src/source/fuzz/shrinker.h
@@ -50,8 +50,8 @@
       const std::vector<uint32_t>& binary, uint32_t counter)>;
 
   // Constructs a shrinker from the given target environment.
-  Shrinker(spv_target_env env, uint32_t step_limit,
-           bool validate_during_replay);
+  Shrinker(spv_target_env env, uint32_t step_limit, bool validate_during_replay,
+           spv_validator_options validator_options);
 
   // Disables copy/move constructor/assignment operations.
   Shrinker(const Shrinker&) = delete;
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation.cpp b/third_party/spirv-tools/src/source/fuzz/transformation.cpp
index f18c86b..c8391e1 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation.cpp
@@ -20,6 +20,7 @@
 #include "source/fuzz/transformation_access_chain.h"
 #include "source/fuzz/transformation_add_constant_boolean.h"
 #include "source/fuzz/transformation_add_constant_composite.h"
+#include "source/fuzz/transformation_add_constant_null.h"
 #include "source/fuzz/transformation_add_constant_scalar.h"
 #include "source/fuzz/transformation_add_dead_block.h"
 #include "source/fuzz/transformation_add_dead_break.h"
@@ -40,6 +41,7 @@
 #include "source/fuzz/transformation_add_type_vector.h"
 #include "source/fuzz/transformation_composite_construct.h"
 #include "source/fuzz/transformation_composite_extract.h"
+#include "source/fuzz/transformation_compute_data_synonym_fact_closure.h"
 #include "source/fuzz/transformation_copy_object.h"
 #include "source/fuzz/transformation_equation_instruction.h"
 #include "source/fuzz/transformation_function_call.h"
@@ -78,6 +80,9 @@
     case protobufs::Transformation::TransformationCase::kAddConstantComposite:
       return MakeUnique<TransformationAddConstantComposite>(
           message.add_constant_composite());
+    case protobufs::Transformation::TransformationCase::kAddConstantNull:
+      return MakeUnique<TransformationAddConstantNull>(
+          message.add_constant_null());
     case protobufs::Transformation::TransformationCase::kAddConstantScalar:
       return MakeUnique<TransformationAddConstantScalar>(
           message.add_constant_scalar());
@@ -130,6 +135,10 @@
     case protobufs::Transformation::TransformationCase::kCompositeExtract:
       return MakeUnique<TransformationCompositeExtract>(
           message.composite_extract());
+    case protobufs::Transformation::TransformationCase::
+        kComputeDataSynonymFactClosure:
+      return MakeUnique<TransformationComputeDataSynonymFactClosure>(
+          message.compute_data_synonym_fact_closure());
     case protobufs::Transformation::TransformationCase::kCopyObject:
       return MakeUnique<TransformationCopyObject>(message.copy_object());
     case protobufs::Transformation::TransformationCase::kEquationInstruction:
@@ -195,9 +204,9 @@
 }
 
 bool Transformation::CheckIdIsFreshAndNotUsedByThisTransformation(
-    uint32_t id, opt::IRContext* context,
+    uint32_t id, opt::IRContext* ir_context,
     std::set<uint32_t>* ids_used_by_this_transformation) {
-  if (!fuzzerutil::IsFreshId(context, id)) {
+  if (!fuzzerutil::IsFreshId(ir_context, id)) {
     return false;
   }
   if (ids_used_by_this_transformation->count(id) != 0) {
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation.h b/third_party/spirv-tools/src/source/fuzz/transformation.h
index dbe803f..dbd0fe2 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation.h
@@ -17,8 +17,8 @@
 
 #include <memory>
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -60,19 +60,22 @@
  public:
   // A precondition that determines whether the transformation can be cleanly
   // applied in a semantics-preserving manner to the SPIR-V module given by
-  // |context|, in the presence of facts captured by |fact_manager|.
+  // |ir_context|, in the presence of facts and other contextual information
+  // captured by |transformation_context|.
+  //
   // Preconditions for individual transformations must be documented in the
-  // associated header file using precise English. The fact manager is used to
-  // provide access to facts about the module that are known to be true, on
+  // associated header file using precise English. The transformation context
+  // provides access to facts about the module that are known to be true, on
   // which the precondition may depend.
-  virtual bool IsApplicable(opt::IRContext* context,
-                            const FactManager& fact_manager) const = 0;
+  virtual bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const = 0;
 
-  // Requires that IsApplicable(context, fact_manager) holds.  Applies the
-  // transformation, mutating |context| and possibly updating |fact_manager|
-  // with new facts established by the transformation.
-  virtual void Apply(opt::IRContext* context,
-                     FactManager* fact_manager) const = 0;
+  // Requires that IsApplicable(ir_context, *transformation_context) holds.
+  // Applies the transformation, mutating |ir_context| and possibly updating
+  // |transformation_context| with new facts established by the transformation.
+  virtual void Apply(opt::IRContext* ir_context,
+                     TransformationContext* transformation_context) const = 0;
 
   // Turns the transformation into a protobuf message for serialization.
   virtual protobufs::Transformation ToMessage() const = 0;
@@ -90,7 +93,7 @@
   // checking id freshness for a transformation that uses many ids, all of which
   // must be distinct.
   static bool CheckIdIsFreshAndNotUsedByThisTransformation(
-      uint32_t id, opt::IRContext* context,
+      uint32_t id, opt::IRContext* ir_context,
       std::set<uint32_t>* ids_used_by_this_transformation);
 };
 
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_access_chain.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_access_chain.cpp
index 8c31006..ff17c36 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_access_chain.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_access_chain.cpp
@@ -40,19 +40,18 @@
 }
 
 bool TransformationAccessChain::IsApplicable(
-    opt::IRContext* context,
-    const spvtools::fuzz::FactManager& /*unused*/) const {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
   // The result id must be fresh
-  if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
+  if (!fuzzerutil::IsFreshId(ir_context, message_.fresh_id())) {
     return false;
   }
   // The pointer id must exist and have a type.
-  auto pointer = context->get_def_use_mgr()->GetDef(message_.pointer_id());
+  auto pointer = ir_context->get_def_use_mgr()->GetDef(message_.pointer_id());
   if (!pointer || !pointer->type_id()) {
     return false;
   }
   // The type must indeed be a pointer
-  auto pointer_type = context->get_def_use_mgr()->GetDef(pointer->type_id());
+  auto pointer_type = ir_context->get_def_use_mgr()->GetDef(pointer->type_id());
   if (pointer_type->opcode() != SpvOpTypePointer) {
     return false;
   }
@@ -60,7 +59,7 @@
   // The described instruction to insert before must exist and be a suitable
   // point where an OpAccessChain instruction could be inserted.
   auto instruction_to_insert_before =
-      FindInstruction(message_.instruction_to_insert_before(), context);
+      FindInstruction(message_.instruction_to_insert_before(), ir_context);
   if (!instruction_to_insert_before) {
     return false;
   }
@@ -86,7 +85,7 @@
   // The pointer on which the access chain is to be based needs to be available
   // (according to dominance rules) at the insertion point.
   if (!fuzzerutil::IdIsAvailableBeforeInstruction(
-          context, instruction_to_insert_before, message_.pointer_id())) {
+          ir_context, instruction_to_insert_before, message_.pointer_id())) {
     return false;
   }
 
@@ -104,7 +103,7 @@
     // integer.  Otherwise, the integer with which the id is associated is the
     // second component.
     std::pair<bool, uint32_t> maybe_index_value =
-        GetIndexValue(context, index_id);
+        GetIndexValue(ir_context, index_id);
     if (!maybe_index_value.first) {
       // There was no integer: this index is no good.
       return false;
@@ -113,7 +112,7 @@
     // type is not a composite or the index is out of bounds, and the id of
     // the next type otherwise.
     subobject_type_id = fuzzerutil::WalkOneCompositeTypeIndex(
-        context, subobject_type_id, maybe_index_value.second);
+        ir_context, subobject_type_id, maybe_index_value.second);
     if (!subobject_type_id) {
       // Either the type was not a composite (so that too many indices were
       // provided), or the index was out of bounds.
@@ -128,13 +127,14 @@
   // We do not use the type manager to look up this type, due to problems
   // associated with pointers to isomorphic structs being regarded as the same.
   return fuzzerutil::MaybeGetPointerType(
-             context, subobject_type_id,
+             ir_context, subobject_type_id,
              static_cast<SpvStorageClass>(
                  pointer_type->GetSingleWordInOperand(0))) != 0;
 }
 
 void TransformationAccessChain::Apply(
-    opt::IRContext* context, spvtools::fuzz::FactManager* fact_manager) const {
+    opt::IRContext* ir_context,
+    TransformationContext* transformation_context) const {
   // The operands to the access chain are the pointer followed by the indices.
   // The result type of the access chain is determined by where the indices
   // lead.  We thus push the pointer to a sequence of operands, and then follow
@@ -148,8 +148,8 @@
   operands.push_back({SPV_OPERAND_TYPE_ID, {message_.pointer_id()}});
 
   // Start walking the indices, starting with the pointer's base type.
-  auto pointer_type = context->get_def_use_mgr()->GetDef(
-      context->get_def_use_mgr()->GetDef(message_.pointer_id())->type_id());
+  auto pointer_type = ir_context->get_def_use_mgr()->GetDef(
+      ir_context->get_def_use_mgr()->GetDef(message_.pointer_id())->type_id());
   uint32_t subobject_type_id = pointer_type->GetSingleWordInOperand(1);
 
   // Go through the index ids in turn.
@@ -157,33 +157,35 @@
     // Add the index id to the operands.
     operands.push_back({SPV_OPERAND_TYPE_ID, {index_id}});
     // Get the integer value associated with the index id.
-    uint32_t index_value = GetIndexValue(context, index_id).second;
+    uint32_t index_value = GetIndexValue(ir_context, index_id).second;
     // Walk to the next type in the composite object using this index.
     subobject_type_id = fuzzerutil::WalkOneCompositeTypeIndex(
-        context, subobject_type_id, index_value);
+        ir_context, subobject_type_id, index_value);
   }
   // The access chain's result type is a pointer to the composite component that
   // was reached after following all indices.  The storage class is that of the
   // original pointer.
   uint32_t result_type = fuzzerutil::MaybeGetPointerType(
-      context, subobject_type_id,
+      ir_context, subobject_type_id,
       static_cast<SpvStorageClass>(pointer_type->GetSingleWordInOperand(0)));
 
   // Add the access chain instruction to the module, and update the module's id
   // bound.
-  fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
-  FindInstruction(message_.instruction_to_insert_before(), context)
-      ->InsertBefore(
-          MakeUnique<opt::Instruction>(context, SpvOpAccessChain, result_type,
-                                       message_.fresh_id(), operands));
+  fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
+  FindInstruction(message_.instruction_to_insert_before(), ir_context)
+      ->InsertBefore(MakeUnique<opt::Instruction>(
+          ir_context, SpvOpAccessChain, result_type, message_.fresh_id(),
+          operands));
 
   // Conservatively invalidate all analyses.
-  context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
 
   // If the base pointer's pointee value was irrelevant, the same is true of the
   // pointee value of the result of this access chain.
-  if (fact_manager->PointeeValueIsIrrelevant(message_.pointer_id())) {
-    fact_manager->AddFactValueOfPointeeIsIrrelevant(message_.fresh_id());
+  if (transformation_context->GetFactManager()->PointeeValueIsIrrelevant(
+          message_.pointer_id())) {
+    transformation_context->GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
+        message_.fresh_id());
   }
 }
 
@@ -194,8 +196,8 @@
 }
 
 std::pair<bool, uint32_t> TransformationAccessChain::GetIndexValue(
-    opt::IRContext* context, uint32_t index_id) const {
-  auto index_instruction = context->get_def_use_mgr()->GetDef(index_id);
+    opt::IRContext* ir_context, uint32_t index_id) const {
+  auto index_instruction = ir_context->get_def_use_mgr()->GetDef(index_id);
   if (!index_instruction || !spvOpcodeIsConstant(index_instruction->opcode())) {
     // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3179) We could
     //  allow non-constant indices when looking up non-structs, using clamping
@@ -203,7 +205,7 @@
     return {false, 0};
   }
   auto index_type =
-      context->get_def_use_mgr()->GetDef(index_instruction->type_id());
+      ir_context->get_def_use_mgr()->GetDef(index_instruction->type_id());
   if (index_type->opcode() != SpvOpTypeInt ||
       index_type->GetSingleWordInOperand(0) != 32) {
     return {false, 0};
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_access_chain.h b/third_party/spirv-tools/src/source/fuzz/transformation_access_chain.h
index 92d9e6a..9306a59 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_access_chain.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_access_chain.h
@@ -17,9 +17,9 @@
 
 #include <utility>
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -47,8 +47,9 @@
   // - If type t is the final type reached by walking these indices, the module
   //   must include an instruction "OpTypePointer SC %t" where SC is the storage
   //   class associated with |message_.pointer_id|
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // Adds an instruction of the form:
   //   |message_.fresh_id| = OpAccessChain %ptr |message_.index_id|
@@ -57,10 +58,12 @@
   // the indices in |message_.index_id|, and with the same storage class as
   // |message_.pointer_id|.
   //
-  // If |fact_manager| reports that |message_.pointer_id| has an irrelevant
-  // pointee value, then the fact that |message_.fresh_id| (the result of the
-  // access chain) also has an irrelevant pointee value is also recorded.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  // If the fact manager in |transformation_context| reports that
+  // |message_.pointer_id| has an irrelevant pointee value, then the fact that
+  // |message_.fresh_id| (the result of the access chain) also has an irrelevant
+  // pointee value is also recorded.
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
@@ -68,7 +71,7 @@
   // Returns {false, 0} if |index_id| does not correspond to a 32-bit integer
   // constant.  Otherwise, returns {true, value}, where value is the value of
   // the 32-bit integer constant to which |index_id| corresponds.
-  std::pair<bool, uint32_t> GetIndexValue(opt::IRContext* context,
+  std::pair<bool, uint32_t> GetIndexValue(opt::IRContext* ir_context,
                                           uint32_t index_id) const;
 
   protobufs::TransformationAccessChain message_;
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_constant_boolean.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_add_constant_boolean.cpp
index 21c8ed3..1930f7e 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_add_constant_boolean.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_constant_boolean.cpp
@@ -31,27 +31,28 @@
 }
 
 bool TransformationAddConstantBoolean::IsApplicable(
-    opt::IRContext* context, const FactManager& /*unused*/) const {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
   opt::analysis::Bool bool_type;
-  if (!context->get_type_mgr()->GetId(&bool_type)) {
+  if (!ir_context->get_type_mgr()->GetId(&bool_type)) {
     // No OpTypeBool is present.
     return false;
   }
-  return fuzzerutil::IsFreshId(context, message_.fresh_id());
+  return fuzzerutil::IsFreshId(ir_context, message_.fresh_id());
 }
 
-void TransformationAddConstantBoolean::Apply(opt::IRContext* context,
-                                             FactManager* /*unused*/) const {
+void TransformationAddConstantBoolean::Apply(
+    opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
   opt::analysis::Bool bool_type;
   // Add the boolean constant to the module, ensuring the module's id bound is
   // high enough.
-  fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
-  context->module()->AddGlobalValue(
+  fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
+  ir_context->module()->AddGlobalValue(
       message_.is_true() ? SpvOpConstantTrue : SpvOpConstantFalse,
-      message_.fresh_id(), context->get_type_mgr()->GetId(&bool_type));
+      message_.fresh_id(), ir_context->get_type_mgr()->GetId(&bool_type));
   // We have added an instruction to the module, so need to be careful about the
   // validity of existing analyses.
-  context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(
+      opt::IRContext::Analysis::kAnalysisNone);
 }
 
 protobufs::Transformation TransformationAddConstantBoolean::ToMessage() const {
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_constant_boolean.h b/third_party/spirv-tools/src/source/fuzz/transformation_add_constant_boolean.h
index 79df1cd..5d876cf 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_add_constant_boolean.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_constant_boolean.h
@@ -15,9 +15,9 @@
 #ifndef SOURCE_FUZZ_TRANSFORMATION_ADD_BOOLEAN_CONSTANT_H_
 #define SOURCE_FUZZ_TRANSFORMATION_ADD_BOOLEAN_CONSTANT_H_
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -32,12 +32,14 @@
 
   // - |message_.fresh_id| must not be used by the module.
   // - The module must already contain OpTypeBool.
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // - Adds OpConstantTrue (OpConstantFalse) to the module with id
   //   |message_.fresh_id| if |message_.is_true| holds (does not hold).
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_constant_composite.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_add_constant_composite.cpp
index 7ba1ea4..ae34b26 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_add_constant_composite.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_constant_composite.cpp
@@ -37,15 +37,14 @@
 }
 
 bool TransformationAddConstantComposite::IsApplicable(
-    opt::IRContext* context,
-    const spvtools::fuzz::FactManager& /*unused*/) const {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
   // Check that the given id is fresh.
-  if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
+  if (!fuzzerutil::IsFreshId(ir_context, message_.fresh_id())) {
     return false;
   }
   // Check that the composite type id is an instruction id.
   auto composite_type_instruction =
-      context->get_def_use_mgr()->GetDef(message_.type_id());
+      ir_context->get_def_use_mgr()->GetDef(message_.type_id());
   if (!composite_type_instruction) {
     return false;
   }
@@ -56,7 +55,7 @@
     case SpvOpTypeArray:
       for (uint32_t index = 0;
            index <
-           fuzzerutil::GetArraySize(*composite_type_instruction, context);
+           fuzzerutil::GetArraySize(*composite_type_instruction, ir_context);
            index++) {
         constituent_type_ids.push_back(
             composite_type_instruction->GetSingleWordInOperand(0));
@@ -93,7 +92,7 @@
   // corresponding constituent type.
   for (uint32_t index = 0; index < constituent_type_ids.size(); index++) {
     auto constituent_instruction =
-        context->get_def_use_mgr()->GetDef(message_.constituent_id(index));
+        ir_context->get_def_use_mgr()->GetDef(message_.constituent_id(index));
     if (!constituent_instruction) {
       return false;
     }
@@ -105,18 +104,19 @@
 }
 
 void TransformationAddConstantComposite::Apply(
-    opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/) const {
+    opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
   opt::Instruction::OperandList in_operands;
   for (auto constituent_id : message_.constituent_id()) {
     in_operands.push_back({SPV_OPERAND_TYPE_ID, {constituent_id}});
   }
-  context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
-      context, SpvOpConstantComposite, message_.type_id(), message_.fresh_id(),
-      in_operands));
-  fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
+  ir_context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
+      ir_context, SpvOpConstantComposite, message_.type_id(),
+      message_.fresh_id(), in_operands));
+  fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
   // We have added an instruction to the module, so need to be careful about the
   // validity of existing analyses.
-  context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(
+      opt::IRContext::Analysis::kAnalysisNone);
 }
 
 protobufs::Transformation TransformationAddConstantComposite::ToMessage()
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_constant_composite.h b/third_party/spirv-tools/src/source/fuzz/transformation_add_constant_composite.h
index 9a824a0..4fec561 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_add_constant_composite.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_constant_composite.h
@@ -17,9 +17,9 @@
 
 #include <vector>
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -38,13 +38,15 @@
   // - |message_.type_id| must be the id of a composite type
   // - |message_.constituent_id| must refer to ids that match the constituent
   //   types of this composite type
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // Adds an OpConstantComposite instruction defining a constant of type
   // |message_.type_id|, using |message_.constituent_id| as constituents, with
   // result id |message_.fresh_id|.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_constant_null.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_add_constant_null.cpp
new file mode 100644
index 0000000..dedbc21
--- /dev/null
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_constant_null.cpp
@@ -0,0 +1,66 @@
+// Copyright (c) 2020 Google LLC
+//
+// 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
+//
+//     http://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.
+
+#include "source/fuzz/transformation_add_constant_null.h"
+
+#include "source/fuzz/fuzzer_util.h"
+
+namespace spvtools {
+namespace fuzz {
+
+TransformationAddConstantNull::TransformationAddConstantNull(
+    const spvtools::fuzz::protobufs::TransformationAddConstantNull& message)
+    : message_(message) {}
+
+TransformationAddConstantNull::TransformationAddConstantNull(uint32_t fresh_id,
+                                                             uint32_t type_id) {
+  message_.set_fresh_id(fresh_id);
+  message_.set_type_id(type_id);
+}
+
+bool TransformationAddConstantNull::IsApplicable(
+    opt::IRContext* context, const TransformationContext& /*unused*/) const {
+  // A fresh id is required.
+  if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
+    return false;
+  }
+  auto type = context->get_type_mgr()->GetType(message_.type_id());
+  // The type must exist.
+  if (!type) {
+    return false;
+  }
+  // The type must be one of the types for which null constants are allowed,
+  // according to the SPIR-V spec.
+  return fuzzerutil::IsNullConstantSupported(*type);
+}
+
+void TransformationAddConstantNull::Apply(
+    opt::IRContext* context, TransformationContext* /*unused*/) const {
+  context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
+      context, SpvOpConstantNull, message_.type_id(), message_.fresh_id(),
+      opt::Instruction::OperandList()));
+  fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
+  // We have added an instruction to the module, so need to be careful about the
+  // validity of existing analyses.
+  context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
+}
+
+protobufs::Transformation TransformationAddConstantNull::ToMessage() const {
+  protobufs::Transformation result;
+  *result.mutable_add_constant_null() = message_;
+  return result;
+}
+
+}  // namespace fuzz
+}  // namespace spvtools
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_constant_null.h b/third_party/spirv-tools/src/source/fuzz/transformation_add_constant_null.h
new file mode 100644
index 0000000..590fc0d
--- /dev/null
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_constant_null.h
@@ -0,0 +1,54 @@
+// Copyright (c) 2020 Google LLC
+//
+// 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
+//
+//     http://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.
+
+#ifndef SOURCE_FUZZ_TRANSFORMATION_ADD_CONSTANT_NULL_H_
+#define SOURCE_FUZZ_TRANSFORMATION_ADD_CONSTANT_NULL_H_
+
+#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
+#include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
+#include "source/opt/ir_context.h"
+
+namespace spvtools {
+namespace fuzz {
+
+class TransformationAddConstantNull : public Transformation {
+ public:
+  explicit TransformationAddConstantNull(
+      const protobufs::TransformationAddConstantNull& message);
+
+  TransformationAddConstantNull(uint32_t fresh_id, uint32_t type_id);
+
+  // - |message_.fresh_id| must be fresh
+  // - |message_.type_id| must be the id of a type for which it is acceptable
+  //   to create a null constant
+  bool IsApplicable(
+      opt::IRContext* context,
+      const TransformationContext& transformation_context) const override;
+
+  // Adds an OpConstantNull instruction to the module, with |message_.type_id|
+  // as its type.  The instruction has result id |message_.fresh_id|.
+  void Apply(opt::IRContext* context,
+             TransformationContext* transformation_context) const override;
+
+  protobufs::Transformation ToMessage() const override;
+
+ private:
+  protobufs::TransformationAddConstantNull message_;
+};
+
+}  // namespace fuzz
+}  // namespace spvtools
+
+#endif  // SOURCE_FUZZ_TRANSFORMATION_ADD_CONSTANT_NULL_H_
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_constant_scalar.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_add_constant_scalar.cpp
index 36af5e0..e13d08f 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_add_constant_scalar.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_constant_scalar.cpp
@@ -33,14 +33,13 @@
 }
 
 bool TransformationAddConstantScalar::IsApplicable(
-    opt::IRContext* context,
-    const spvtools::fuzz::FactManager& /*unused*/) const {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
   // The id needs to be fresh.
-  if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
+  if (!fuzzerutil::IsFreshId(ir_context, message_.fresh_id())) {
     return false;
   }
   // The type id for the scalar must exist and be a type.
-  auto type = context->get_type_mgr()->GetType(message_.type_id());
+  auto type = ir_context->get_type_mgr()->GetType(message_.type_id());
   if (!type) {
     return false;
   }
@@ -61,20 +60,21 @@
 }
 
 void TransformationAddConstantScalar::Apply(
-    opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/) const {
+    opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
   opt::Instruction::OperandList operand_list;
   for (auto word : message_.word()) {
     operand_list.push_back({SPV_OPERAND_TYPE_LITERAL_INTEGER, {word}});
   }
-  context->module()->AddGlobalValue(
-      MakeUnique<opt::Instruction>(context, SpvOpConstant, message_.type_id(),
-                                   message_.fresh_id(), operand_list));
+  ir_context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
+      ir_context, SpvOpConstant, message_.type_id(), message_.fresh_id(),
+      operand_list));
 
-  fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
+  fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
 
   // We have added an instruction to the module, so need to be careful about the
   // validity of existing analyses.
-  context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(
+      opt::IRContext::Analysis::kAnalysisNone);
 }
 
 protobufs::Transformation TransformationAddConstantScalar::ToMessage() const {
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_constant_scalar.h b/third_party/spirv-tools/src/source/fuzz/transformation_add_constant_scalar.h
index 914cfe6..e0ed39f 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_add_constant_scalar.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_constant_scalar.h
@@ -17,9 +17,9 @@
 
 #include <vector>
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -37,11 +37,13 @@
   // - |message_.type_id| must be the id of a floating-point or integer type
   // - The size of |message_.word| must be compatible with the width of this
   //   type
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // Adds a new OpConstant instruction with the given type and words.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_dead_block.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_add_dead_block.cpp
index b58f75e..b246c3f 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_add_dead_block.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_dead_block.cpp
@@ -32,16 +32,15 @@
 }
 
 bool TransformationAddDeadBlock::IsApplicable(
-    opt::IRContext* context,
-    const spvtools::fuzz::FactManager& /*unused*/) const {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
   // The new block's id must be fresh.
-  if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
+  if (!fuzzerutil::IsFreshId(ir_context, message_.fresh_id())) {
     return false;
   }
 
   // First, we check that a constant with the same value as
   // |message_.condition_value| is present.
-  if (!fuzzerutil::MaybeGetBoolConstantId(context,
+  if (!fuzzerutil::MaybeGetBoolConstantId(ir_context,
                                           message_.condition_value())) {
     // The required constant is not present, so the transformation cannot be
     // applied.
@@ -50,7 +49,7 @@
 
   // The existing block must indeed exist.
   auto existing_block =
-      fuzzerutil::MaybeFindBlock(context, message_.existing_block());
+      fuzzerutil::MaybeFindBlock(ir_context, message_.existing_block());
   if (!existing_block) {
     return false;
   }
@@ -68,13 +67,13 @@
   // Its successor must not be a merge block nor continue target.
   auto successor_block_id =
       existing_block->terminator()->GetSingleWordInOperand(0);
-  if (fuzzerutil::IsMergeOrContinue(context, successor_block_id)) {
+  if (fuzzerutil::IsMergeOrContinue(ir_context, successor_block_id)) {
     return false;
   }
 
   // The successor must not be a loop header (i.e., |message_.existing_block|
   // must not be a back-edge block.
-  if (context->cfg()->block(successor_block_id)->IsLoopHeader()) {
+  if (ir_context->cfg()->block(successor_block_id)->IsLoopHeader()) {
     return false;
   }
 
@@ -82,34 +81,36 @@
 }
 
 void TransformationAddDeadBlock::Apply(
-    opt::IRContext* context, spvtools::fuzz::FactManager* fact_manager) const {
+    opt::IRContext* ir_context,
+    TransformationContext* transformation_context) const {
   // Update the module id bound so that it is at least the id of the new block.
-  fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
+  fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
 
   // Get the existing block and its successor.
-  auto existing_block = context->cfg()->block(message_.existing_block());
+  auto existing_block = ir_context->cfg()->block(message_.existing_block());
   auto successor_block_id =
       existing_block->terminator()->GetSingleWordInOperand(0);
 
   // Get the id of the boolean value that will be used as the branch condition.
-  auto bool_id =
-      fuzzerutil::MaybeGetBoolConstantId(context, message_.condition_value());
+  auto bool_id = fuzzerutil::MaybeGetBoolConstantId(ir_context,
+                                                    message_.condition_value());
 
   // Make a new block that unconditionally branches to the original successor
   // block.
   auto enclosing_function = existing_block->GetParent();
-  std::unique_ptr<opt::BasicBlock> new_block = MakeUnique<opt::BasicBlock>(
-      MakeUnique<opt::Instruction>(context, SpvOpLabel, 0, message_.fresh_id(),
-                                   opt::Instruction::OperandList()));
+  std::unique_ptr<opt::BasicBlock> new_block =
+      MakeUnique<opt::BasicBlock>(MakeUnique<opt::Instruction>(
+          ir_context, SpvOpLabel, 0, message_.fresh_id(),
+          opt::Instruction::OperandList()));
   new_block->AddInstruction(MakeUnique<opt::Instruction>(
-      context, SpvOpBranch, 0, 0,
+      ir_context, SpvOpBranch, 0, 0,
       opt::Instruction::OperandList(
           {{SPV_OPERAND_TYPE_ID, {successor_block_id}}})));
 
   // Turn the original block into a selection merge, with its original successor
   // as the merge block.
   existing_block->terminator()->InsertBefore(MakeUnique<opt::Instruction>(
-      context, SpvOpSelectionMerge, 0, 0,
+      ir_context, SpvOpSelectionMerge, 0, 0,
       opt::Instruction::OperandList(
           {{SPV_OPERAND_TYPE_ID, {successor_block_id}},
            {SPV_OPERAND_TYPE_SELECTION_CONTROL,
@@ -135,7 +136,8 @@
                                             existing_block);
 
   // Record the fact that the new block is dead.
-  fact_manager->AddFactBlockIsDead(message_.fresh_id());
+  transformation_context->GetFactManager()->AddFactBlockIsDead(
+      message_.fresh_id());
 
   // Fix up OpPhi instructions in the successor block, so that the values they
   // yield when control has transferred from the new block are the same as if
@@ -143,7 +145,7 @@
   // to be valid since |message_.existing_block| dominates the new block by
   // construction.  Other transformations can change these phi operands to more
   // interesting values.
-  context->cfg()
+  ir_context->cfg()
       ->block(successor_block_id)
       ->ForEachPhiInst([this](opt::Instruction* phi_inst) {
         // Copy the operand that provides the phi value for the first of any
@@ -156,7 +158,7 @@
 
   // Do not rely on any existing analysis results since the control flow graph
   // of the module has changed.
-  context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
 }
 
 protobufs::Transformation TransformationAddDeadBlock::ToMessage() const {
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_dead_block.h b/third_party/spirv-tools/src/source/fuzz/transformation_add_dead_block.h
index 059daca..7d07616 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_add_dead_block.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_dead_block.h
@@ -15,9 +15,9 @@
 #ifndef SOURCE_FUZZ_TRANSFORMATION_ADD_DEAD_BLOCK_H_
 #define SOURCE_FUZZ_TRANSFORMATION_ADD_DEAD_BLOCK_H_
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -41,15 +41,17 @@
   // - |message_.existing_block| must not be a back-edge block, since in this
   //   case the newly-added block would lead to another back-edge to the
   //   associated loop header
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // Changes the OpBranch from |message_.existing_block| to its successor 's'
   // to an OpBranchConditional to either 's' or a new block,
   // |message_.fresh_id|, which itself unconditionally branches to 's'.  The
   // conditional branch uses |message.condition_value| as its condition, and is
   // arranged so that control will pass to 's' at runtime.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_dead_break.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_add_dead_break.cpp
index 43847fa..db9de7d 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_add_dead_break.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_dead_break.cpp
@@ -14,8 +14,8 @@
 
 #include "source/fuzz/transformation_add_dead_break.h"
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/fuzzer_util.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/basic_block.h"
 #include "source/opt/ir_context.h"
 #include "source/opt/struct_cfg_analysis.h"
@@ -39,7 +39,7 @@
 }
 
 bool TransformationAddDeadBreak::AddingBreakRespectsStructuredControlFlow(
-    opt::IRContext* context, opt::BasicBlock* bb_from) const {
+    opt::IRContext* ir_context, opt::BasicBlock* bb_from) const {
   // Look at the structured control flow associated with |from_block| and
   // check whether it is contained in an appropriate construct with merge id
   // |to_block| such that a break from |from_block| to |to_block| is legal.
@@ -70,7 +70,7 @@
   // structured control flow construct.
 
   auto containing_construct =
-      context->GetStructuredCFGAnalysis()->ContainingConstruct(
+      ir_context->GetStructuredCFGAnalysis()->ContainingConstruct(
           message_.from_block());
   if (!containing_construct) {
     // |from_block| is not in a construct from which we can break.
@@ -79,7 +79,7 @@
 
   // Consider case (2)
   if (message_.to_block() ==
-      context->cfg()->block(containing_construct)->MergeBlockId()) {
+      ir_context->cfg()->block(containing_construct)->MergeBlockId()) {
     // This looks like an instance of case (2).
     // However, the structured CFG analysis regards the continue construct of a
     // loop as part of the loop, but it is not legal to jump from a loop's
@@ -90,28 +90,29 @@
     //  currently allow a dead break from a back edge block, but we could and
     //  ultimately should.
     return !fuzzerutil::BlockIsInLoopContinueConstruct(
-        context, message_.from_block(), containing_construct);
+        ir_context, message_.from_block(), containing_construct);
   }
 
   // Case (3) holds if and only if |to_block| is the merge block for this
   // innermost loop that contains |from_block|
   auto containing_loop_header =
-      context->GetStructuredCFGAnalysis()->ContainingLoop(
+      ir_context->GetStructuredCFGAnalysis()->ContainingLoop(
           message_.from_block());
   if (containing_loop_header &&
       message_.to_block() ==
-          context->cfg()->block(containing_loop_header)->MergeBlockId()) {
+          ir_context->cfg()->block(containing_loop_header)->MergeBlockId()) {
     return !fuzzerutil::BlockIsInLoopContinueConstruct(
-        context, message_.from_block(), containing_loop_header);
+        ir_context, message_.from_block(), containing_loop_header);
   }
   return false;
 }
 
 bool TransformationAddDeadBreak::IsApplicable(
-    opt::IRContext* context, const FactManager& /*unused*/) const {
+    opt::IRContext* ir_context,
+    const TransformationContext& transformation_context) const {
   // First, we check that a constant with the same value as
   // |message_.break_condition_value| is present.
-  if (!fuzzerutil::MaybeGetBoolConstantId(context,
+  if (!fuzzerutil::MaybeGetBoolConstantId(ir_context,
                                           message_.break_condition_value())) {
     // The required constant is not present, so the transformation cannot be
     // applied.
@@ -121,17 +122,17 @@
   // Check that |message_.from_block| and |message_.to_block| really are block
   // ids
   opt::BasicBlock* bb_from =
-      fuzzerutil::MaybeFindBlock(context, message_.from_block());
+      fuzzerutil::MaybeFindBlock(ir_context, message_.from_block());
   if (bb_from == nullptr) {
     return false;
   }
   opt::BasicBlock* bb_to =
-      fuzzerutil::MaybeFindBlock(context, message_.to_block());
+      fuzzerutil::MaybeFindBlock(ir_context, message_.to_block());
   if (bb_to == nullptr) {
     return false;
   }
 
-  if (!fuzzerutil::BlockIsReachableInItsFunction(context, bb_to)) {
+  if (!fuzzerutil::BlockIsReachableInItsFunction(ir_context, bb_to)) {
     // If the target of the break is unreachable, we conservatively do not
     // allow adding a dead break, to avoid the compilations that arise due to
     // the lack of sensible dominance information for unreachable blocks.
@@ -157,14 +158,14 @@
       "The id of the block we found should match the target id for the break.");
 
   // Check whether the data passed to extend OpPhi instructions is appropriate.
-  if (!fuzzerutil::PhiIdsOkForNewEdge(context, bb_from, bb_to,
+  if (!fuzzerutil::PhiIdsOkForNewEdge(ir_context, bb_from, bb_to,
                                       message_.phi_id())) {
     return false;
   }
 
   // Check that adding the break would respect the rules of structured
   // control flow.
-  if (!AddingBreakRespectsStructuredControlFlow(context, bb_from)) {
+  if (!AddingBreakRespectsStructuredControlFlow(ir_context, bb_from)) {
     return false;
   }
 
@@ -177,16 +178,18 @@
   // being places on the validator.  This should be revisited if we are sure
   // the validator is complete with respect to checking structured control flow
   // rules.
-  auto cloned_context = fuzzerutil::CloneIRContext(context);
+  auto cloned_context = fuzzerutil::CloneIRContext(ir_context);
   ApplyImpl(cloned_context.get());
-  return fuzzerutil::IsValid(cloned_context.get());
+  return fuzzerutil::IsValid(cloned_context.get(),
+                             transformation_context.GetValidatorOptions());
 }
 
-void TransformationAddDeadBreak::Apply(opt::IRContext* context,
-                                       FactManager* /*unused*/) const {
-  ApplyImpl(context);
+void TransformationAddDeadBreak::Apply(
+    opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
+  ApplyImpl(ir_context);
   // Invalidate all analyses
-  context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(
+      opt::IRContext::Analysis::kAnalysisNone);
 }
 
 protobufs::Transformation TransformationAddDeadBreak::ToMessage() const {
@@ -196,10 +199,10 @@
 }
 
 void TransformationAddDeadBreak::ApplyImpl(
-    spvtools::opt::IRContext* context) const {
+    spvtools::opt::IRContext* ir_context) const {
   fuzzerutil::AddUnreachableEdgeAndUpdateOpPhis(
-      context, context->cfg()->block(message_.from_block()),
-      context->cfg()->block(message_.to_block()),
+      ir_context, ir_context->cfg()->block(message_.from_block()),
+      ir_context->cfg()->block(message_.to_block()),
       message_.break_condition_value(), message_.phi_id());
 }
 
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_dead_break.h b/third_party/spirv-tools/src/source/fuzz/transformation_add_dead_break.h
index 81a2c99..0ea9210 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_add_dead_break.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_dead_break.h
@@ -17,9 +17,9 @@
 
 #include <vector>
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -50,21 +50,23 @@
   //   maintain validity of the module.
   //   In particular, the new branch must not lead to violations of the rule
   //   that a use must be dominated by its definition.
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // Replaces the terminator of a with a conditional branch to b or c.
   // The boolean constant associated with |message_.break_condition_value| is
   // used as the condition, and the order of b and c is arranged such that
   // control is guaranteed to jump to c.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
  private:
   // Returns true if and only if adding an edge from |bb_from| to
   // |message_.to_block| respects structured control flow.
-  bool AddingBreakRespectsStructuredControlFlow(opt::IRContext* context,
+  bool AddingBreakRespectsStructuredControlFlow(opt::IRContext* ir_context,
                                                 opt::BasicBlock* bb_from) const;
 
   // Used by 'Apply' to actually apply the transformation to the module of
@@ -73,7 +75,7 @@
   // module.  This is only invoked by 'IsApplicable' after certain basic
   // applicability checks have been made, ensuring that the invocation of this
   // method is legal.
-  void ApplyImpl(opt::IRContext* context) const;
+  void ApplyImpl(opt::IRContext* ir_context) const;
 
   protobufs::TransformationAddDeadBreak message_;
 };
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_dead_continue.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_add_dead_continue.cpp
index 3a4875e..1fc6d67 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_add_dead_continue.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_dead_continue.cpp
@@ -34,11 +34,12 @@
 }
 
 bool TransformationAddDeadContinue::IsApplicable(
-    opt::IRContext* context, const FactManager& /*unused*/) const {
+    opt::IRContext* ir_context,
+    const TransformationContext& transformation_context) const {
   // First, we check that a constant with the same value as
   // |message_.continue_condition_value| is present.
   if (!fuzzerutil::MaybeGetBoolConstantId(
-          context, message_.continue_condition_value())) {
+          ir_context, message_.continue_condition_value())) {
     // The required constant is not present, so the transformation cannot be
     // applied.
     return false;
@@ -46,7 +47,7 @@
 
   // Check that |message_.from_block| really is a block id.
   opt::BasicBlock* bb_from =
-      fuzzerutil::MaybeFindBlock(context, message_.from_block());
+      fuzzerutil::MaybeFindBlock(ir_context, message_.from_block());
   if (bb_from == nullptr) {
     return false;
   }
@@ -68,31 +69,33 @@
   // Because the structured CFG analysis does not regard a loop header as part
   // of the loop it heads, we check first whether bb_from is a loop header
   // before using the structured CFG analysis.
-  auto loop_header = bb_from->IsLoopHeader()
-                         ? message_.from_block()
-                         : context->GetStructuredCFGAnalysis()->ContainingLoop(
-                               message_.from_block());
+  auto loop_header =
+      bb_from->IsLoopHeader()
+          ? message_.from_block()
+          : ir_context->GetStructuredCFGAnalysis()->ContainingLoop(
+                message_.from_block());
   if (!loop_header) {
     return false;
   }
 
-  auto continue_block = context->cfg()->block(loop_header)->ContinueBlockId();
+  auto continue_block =
+      ir_context->cfg()->block(loop_header)->ContinueBlockId();
 
   if (!fuzzerutil::BlockIsReachableInItsFunction(
-          context, context->cfg()->block(continue_block))) {
+          ir_context, ir_context->cfg()->block(continue_block))) {
     // If the loop's continue block is unreachable, we conservatively do not
     // allow adding a dead continue, to avoid the compilations that arise due to
     // the lack of sensible dominance information for unreachable blocks.
     return false;
   }
 
-  if (fuzzerutil::BlockIsInLoopContinueConstruct(context, message_.from_block(),
-                                                 loop_header)) {
+  if (fuzzerutil::BlockIsInLoopContinueConstruct(
+          ir_context, message_.from_block(), loop_header)) {
     // We cannot jump to the continue target from the continue construct.
     return false;
   }
 
-  if (context->GetStructuredCFGAnalysis()->IsMergeBlock(continue_block)) {
+  if (ir_context->GetStructuredCFGAnalysis()->IsMergeBlock(continue_block)) {
     // A branch straight to the continue target that is also a merge block might
     // break the property that a construct header must dominate its merge block
     // (if the merge block is reachable).
@@ -100,8 +103,8 @@
   }
 
   // Check whether the data passed to extend OpPhi instructions is appropriate.
-  if (!fuzzerutil::PhiIdsOkForNewEdge(context, bb_from,
-                                      context->cfg()->block(continue_block),
+  if (!fuzzerutil::PhiIdsOkForNewEdge(ir_context, bb_from,
+                                      ir_context->cfg()->block(continue_block),
                                       message_.phi_id())) {
     return false;
   }
@@ -115,16 +118,18 @@
   // being placed on the validator.  This should be revisited if we are sure
   // the validator is complete with respect to checking structured control flow
   // rules.
-  auto cloned_context = fuzzerutil::CloneIRContext(context);
+  auto cloned_context = fuzzerutil::CloneIRContext(ir_context);
   ApplyImpl(cloned_context.get());
-  return fuzzerutil::IsValid(cloned_context.get());
+  return fuzzerutil::IsValid(cloned_context.get(),
+                             transformation_context.GetValidatorOptions());
 }
 
-void TransformationAddDeadContinue::Apply(opt::IRContext* context,
-                                          FactManager* /*unused*/) const {
-  ApplyImpl(context);
+void TransformationAddDeadContinue::Apply(
+    opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
+  ApplyImpl(ir_context);
   // Invalidate all analyses
-  context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(
+      opt::IRContext::Analysis::kAnalysisNone);
 }
 
 protobufs::Transformation TransformationAddDeadContinue::ToMessage() const {
@@ -134,16 +139,16 @@
 }
 
 void TransformationAddDeadContinue::ApplyImpl(
-    spvtools::opt::IRContext* context) const {
-  auto bb_from = context->cfg()->block(message_.from_block());
+    spvtools::opt::IRContext* ir_context) const {
+  auto bb_from = ir_context->cfg()->block(message_.from_block());
   auto continue_block =
       bb_from->IsLoopHeader()
           ? bb_from->ContinueBlockId()
-          : context->GetStructuredCFGAnalysis()->LoopContinueBlock(
+          : ir_context->GetStructuredCFGAnalysis()->LoopContinueBlock(
                 message_.from_block());
   assert(continue_block && "message_.from_block must be in a loop.");
   fuzzerutil::AddUnreachableEdgeAndUpdateOpPhis(
-      context, bb_from, context->cfg()->block(continue_block),
+      ir_context, bb_from, ir_context->cfg()->block(continue_block),
       message_.continue_condition_value(), message_.phi_id());
 }
 
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_dead_continue.h b/third_party/spirv-tools/src/source/fuzz/transformation_add_dead_continue.h
index 86b4c93..1053c16 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_add_dead_continue.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_dead_continue.h
@@ -17,9 +17,9 @@
 
 #include <vector>
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -52,14 +52,16 @@
   //   In particular, adding an edge from somewhere in the loop to the continue
   //   target must not prevent uses of ids in the continue target from being
   //   dominated by the definitions of those ids.
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // Replaces the terminator of a with a conditional branch to b or c.
   // The boolean constant associated with |message_.continue_condition_value| is
   // used as the condition, and the order of b and c is arranged such that
   // control is guaranteed to jump to c.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
@@ -70,7 +72,7 @@
   // module.  This is only invoked by 'IsApplicable' after certain basic
   // applicability checks have been made, ensuring that the invocation of this
   // method is legal.
-  void ApplyImpl(opt::IRContext* context) const;
+  void ApplyImpl(opt::IRContext* ir_context) const;
 
   protobufs::TransformationAddDeadContinue message_;
 };
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_function.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_add_function.cpp
index 8f0d3c9..c990f23 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_add_function.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_function.cpp
@@ -56,8 +56,8 @@
 }
 
 bool TransformationAddFunction::IsApplicable(
-    opt::IRContext* context,
-    const spvtools::fuzz::FactManager& fact_manager) const {
+    opt::IRContext* ir_context,
+    const TransformationContext& transformation_context) const {
   // This transformation may use a lot of ids, all of which need to be fresh
   // and distinct.  This set tracks them.
   std::set<uint32_t> ids_used_by_this_transformation;
@@ -66,7 +66,7 @@
   for (auto& instruction : message_.instruction()) {
     if (instruction.result_id()) {
       if (!CheckIdIsFreshAndNotUsedByThisTransformation(
-              instruction.result_id(), context,
+              instruction.result_id(), ir_context,
               &ids_used_by_this_transformation)) {
         return false;
       }
@@ -77,28 +77,28 @@
     // Ensure that all ids provided for making the function livesafe are fresh
     // and distinct.
     if (!CheckIdIsFreshAndNotUsedByThisTransformation(
-            message_.loop_limiter_variable_id(), context,
+            message_.loop_limiter_variable_id(), ir_context,
             &ids_used_by_this_transformation)) {
       return false;
     }
     for (auto& loop_limiter_info : message_.loop_limiter_info()) {
       if (!CheckIdIsFreshAndNotUsedByThisTransformation(
-              loop_limiter_info.load_id(), context,
+              loop_limiter_info.load_id(), ir_context,
               &ids_used_by_this_transformation)) {
         return false;
       }
       if (!CheckIdIsFreshAndNotUsedByThisTransformation(
-              loop_limiter_info.increment_id(), context,
+              loop_limiter_info.increment_id(), ir_context,
               &ids_used_by_this_transformation)) {
         return false;
       }
       if (!CheckIdIsFreshAndNotUsedByThisTransformation(
-              loop_limiter_info.compare_id(), context,
+              loop_limiter_info.compare_id(), ir_context,
               &ids_used_by_this_transformation)) {
         return false;
       }
       if (!CheckIdIsFreshAndNotUsedByThisTransformation(
-              loop_limiter_info.logical_op_id(), context,
+              loop_limiter_info.logical_op_id(), ir_context,
               &ids_used_by_this_transformation)) {
         return false;
       }
@@ -107,11 +107,11 @@
          message_.access_chain_clamping_info()) {
       for (auto& pair : access_chain_clamping_info.compare_and_select_ids()) {
         if (!CheckIdIsFreshAndNotUsedByThisTransformation(
-                pair.first(), context, &ids_used_by_this_transformation)) {
+                pair.first(), ir_context, &ids_used_by_this_transformation)) {
           return false;
         }
         if (!CheckIdIsFreshAndNotUsedByThisTransformation(
-                pair.second(), context, &ids_used_by_this_transformation)) {
+                pair.second(), ir_context, &ids_used_by_this_transformation)) {
           return false;
         }
       }
@@ -123,8 +123,8 @@
   // is taken here.
 
   // We first clone the current module, so that we can try adding the new
-  // function without risking wrecking |context|.
-  auto cloned_module = fuzzerutil::CloneIRContext(context);
+  // function without risking wrecking |ir_context|.
+  auto cloned_module = fuzzerutil::CloneIRContext(ir_context);
 
   // We try to add a function to the cloned module, which may fail if
   // |message_.instruction| is not sufficiently well-formed.
@@ -134,12 +134,14 @@
 
   // Check whether the cloned module is still valid after adding the function.
   // If it is not, the transformation is not applicable.
-  if (!fuzzerutil::IsValid(cloned_module.get())) {
+  if (!fuzzerutil::IsValid(cloned_module.get(),
+                           transformation_context.GetValidatorOptions())) {
     return false;
   }
 
   if (message_.is_livesafe()) {
-    if (!TryToMakeFunctionLivesafe(cloned_module.get(), fact_manager)) {
+    if (!TryToMakeFunctionLivesafe(cloned_module.get(),
+                                   transformation_context)) {
       return false;
     }
     // After making the function livesafe, we check validity of the module
@@ -148,7 +150,8 @@
     // has the potential to make the module invalid when it was otherwise valid.
     // It is simpler to rely on the validator to guard against this than to
     // consider all scenarios when making a function livesafe.
-    if (!fuzzerutil::IsValid(cloned_module.get())) {
+    if (!fuzzerutil::IsValid(cloned_module.get(),
+                             transformation_context.GetValidatorOptions())) {
       return false;
     }
   }
@@ -156,10 +159,11 @@
 }
 
 void TransformationAddFunction::Apply(
-    opt::IRContext* context, spvtools::fuzz::FactManager* fact_manager) const {
+    opt::IRContext* ir_context,
+    TransformationContext* transformation_context) const {
   // Add the function to the module.  As the transformation is applicable, this
   // should succeed.
-  bool success = TryToAddFunction(context);
+  bool success = TryToAddFunction(ir_context);
   assert(success && "The function should be successfully added.");
   (void)(success);  // Keep release builds happy (otherwise they may complain
                     // that |success| is not used).
@@ -172,16 +176,16 @@
   for (auto& instruction : message_.instruction()) {
     switch (instruction.opcode()) {
       case SpvOpFunctionParameter:
-        if (context->get_def_use_mgr()
+        if (ir_context->get_def_use_mgr()
                 ->GetDef(instruction.result_type_id())
                 ->opcode() == SpvOpTypePointer) {
-          fact_manager->AddFactValueOfPointeeIsIrrelevant(
-              instruction.result_id());
+          transformation_context->GetFactManager()
+              ->AddFactValueOfPointeeIsIrrelevant(instruction.result_id());
         }
         break;
       case SpvOpVariable:
-        fact_manager->AddFactValueOfPointeeIsIrrelevant(
-            instruction.result_id());
+        transformation_context->GetFactManager()
+            ->AddFactValueOfPointeeIsIrrelevant(instruction.result_id());
         break;
       default:
         break;
@@ -190,7 +194,7 @@
 
   if (message_.is_livesafe()) {
     // Make the function livesafe, which also should succeed.
-    success = TryToMakeFunctionLivesafe(context, *fact_manager);
+    success = TryToMakeFunctionLivesafe(ir_context, *transformation_context);
     assert(success && "It should be possible to make the function livesafe.");
     (void)(success);  // Keep release builds happy.
 
@@ -198,17 +202,18 @@
     assert(message_.instruction(0).opcode() == SpvOpFunction &&
            "The first instruction of an 'add function' transformation must be "
            "OpFunction.");
-    fact_manager->AddFactFunctionIsLivesafe(
+    transformation_context->GetFactManager()->AddFactFunctionIsLivesafe(
         message_.instruction(0).result_id());
   } else {
     // Inform the fact manager that all blocks in the function are dead.
     for (auto& inst : message_.instruction()) {
       if (inst.opcode() == SpvOpLabel) {
-        fact_manager->AddFactBlockIsDead(inst.result_id());
+        transformation_context->GetFactManager()->AddFactBlockIsDead(
+            inst.result_id());
       }
     }
   }
-  context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
 }
 
 protobufs::Transformation TransformationAddFunction::ToMessage() const {
@@ -218,9 +223,9 @@
 }
 
 bool TransformationAddFunction::TryToAddFunction(
-    opt::IRContext* context) const {
+    opt::IRContext* ir_context) const {
   // This function returns false if |message_.instruction| was not well-formed
-  // enough to actually create a function and add it to |context|.
+  // enough to actually create a function and add it to |ir_context|.
 
   // A function must have at least some instructions.
   if (message_.instruction().empty()) {
@@ -235,7 +240,7 @@
 
   // Make a function, headed by the OpFunction instruction.
   std::unique_ptr<opt::Function> new_function = MakeUnique<opt::Function>(
-      InstructionFromMessage(context, function_begin));
+      InstructionFromMessage(ir_context, function_begin));
 
   // Keeps track of which instruction protobuf message we are currently
   // considering.
@@ -249,7 +254,7 @@
          message_.instruction(instruction_index).opcode() ==
              SpvOpFunctionParameter) {
     new_function->AddParameter(InstructionFromMessage(
-        context, message_.instruction(instruction_index)));
+        ir_context, message_.instruction(instruction_index)));
     instruction_index++;
   }
 
@@ -270,7 +275,7 @@
     // as its parent.
     std::unique_ptr<opt::BasicBlock> block =
         MakeUnique<opt::BasicBlock>(InstructionFromMessage(
-            context, message_.instruction(instruction_index)));
+            ir_context, message_.instruction(instruction_index)));
     block->SetParent(new_function.get());
 
     // Consider successive instructions until we hit another label or the end
@@ -281,7 +286,7 @@
                SpvOpFunctionEnd &&
            message_.instruction(instruction_index).opcode() != SpvOpLabel) {
       block->AddInstruction(InstructionFromMessage(
-          context, message_.instruction(instruction_index)));
+          ir_context, message_.instruction(instruction_index)));
       instruction_index++;
     }
     // Add the block to the new function.
@@ -295,22 +300,23 @@
   }
   // Set the function's final instruction, add the function to the module and
   // report success.
-  new_function->SetFunctionEnd(
-      InstructionFromMessage(context, message_.instruction(instruction_index)));
-  context->AddFunction(std::move(new_function));
+  new_function->SetFunctionEnd(InstructionFromMessage(
+      ir_context, message_.instruction(instruction_index)));
+  ir_context->AddFunction(std::move(new_function));
 
-  context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
 
   return true;
 }
 
 bool TransformationAddFunction::TryToMakeFunctionLivesafe(
-    opt::IRContext* context, const FactManager& fact_manager) const {
+    opt::IRContext* ir_context,
+    const TransformationContext& transformation_context) const {
   assert(message_.is_livesafe() && "Precondition: is_livesafe must hold.");
 
   // Get a pointer to the added function.
   opt::Function* added_function = nullptr;
-  for (auto& function : *context->module()) {
+  for (auto& function : *ir_context->module()) {
     if (function.result_id() == message_.instruction(0).result_id()) {
       added_function = &function;
       break;
@@ -318,7 +324,7 @@
   }
   assert(added_function && "The added function should have been found.");
 
-  if (!TryToAddLoopLimiters(context, added_function)) {
+  if (!TryToAddLoopLimiters(ir_context, added_function)) {
     // Adding loop limiters did not work; bail out.
     return false;
   }
@@ -332,20 +338,20 @@
       switch (inst.opcode()) {
         case SpvOpKill:
         case SpvOpUnreachable:
-          if (!TryToTurnKillOrUnreachableIntoReturn(context, added_function,
+          if (!TryToTurnKillOrUnreachableIntoReturn(ir_context, added_function,
                                                     &inst)) {
             return false;
           }
           break;
         case SpvOpAccessChain:
         case SpvOpInBoundsAccessChain:
-          if (!TryToClampAccessChainIndices(context, &inst)) {
+          if (!TryToClampAccessChainIndices(ir_context, &inst)) {
             return false;
           }
           break;
         case SpvOpFunctionCall:
           // A livesafe function my only call other livesafe functions.
-          if (!fact_manager.FunctionIsLivesafe(
+          if (!transformation_context.GetFactManager()->FunctionIsLivesafe(
                   inst.GetSingleWordInOperand(0))) {
             return false;
           }
@@ -358,7 +364,7 @@
 }
 
 bool TransformationAddFunction::TryToAddLoopLimiters(
-    opt::IRContext* context, opt::Function* added_function) const {
+    opt::IRContext* ir_context, opt::Function* added_function) const {
   // Collect up all the loop headers so that we can subsequently add loop
   // limiting logic.
   std::vector<opt::BasicBlock*> loop_headers;
@@ -377,7 +383,7 @@
   // manipulating a loop limiter.
 
   auto loop_limit_constant_id_instr =
-      context->get_def_use_mgr()->GetDef(message_.loop_limit_constant_id());
+      ir_context->get_def_use_mgr()->GetDef(message_.loop_limit_constant_id());
   if (!loop_limit_constant_id_instr ||
       loop_limit_constant_id_instr->opcode() != SpvOpConstant) {
     // The loop limit constant id instruction must exist and have an
@@ -385,7 +391,7 @@
     return false;
   }
 
-  auto loop_limit_type = context->get_def_use_mgr()->GetDef(
+  auto loop_limit_type = ir_context->get_def_use_mgr()->GetDef(
       loop_limit_constant_id_instr->type_id());
   if (loop_limit_type->opcode() != SpvOpTypeInt ||
       loop_limit_type->GetSingleWordInOperand(0) != 32) {
@@ -397,36 +403,36 @@
   // Find the id of the "unsigned int" type.
   opt::analysis::Integer unsigned_int_type(32, false);
   uint32_t unsigned_int_type_id =
-      context->get_type_mgr()->GetId(&unsigned_int_type);
+      ir_context->get_type_mgr()->GetId(&unsigned_int_type);
   if (!unsigned_int_type_id) {
     // Unsigned int is not available; we need this type in order to add loop
     // limiters.
     return false;
   }
   auto registered_unsigned_int_type =
-      context->get_type_mgr()->GetRegisteredType(&unsigned_int_type);
+      ir_context->get_type_mgr()->GetRegisteredType(&unsigned_int_type);
 
   // Look for 0 of type unsigned int.
   opt::analysis::IntConstant zero(registered_unsigned_int_type->AsInteger(),
                                   {0});
-  auto registered_zero = context->get_constant_mgr()->FindConstant(&zero);
+  auto registered_zero = ir_context->get_constant_mgr()->FindConstant(&zero);
   if (!registered_zero) {
     // We need 0 in order to be able to initialize loop limiters.
     return false;
   }
-  uint32_t zero_id = context->get_constant_mgr()
+  uint32_t zero_id = ir_context->get_constant_mgr()
                          ->GetDefiningInstruction(registered_zero)
                          ->result_id();
 
   // Look for 1 of type unsigned int.
   opt::analysis::IntConstant one(registered_unsigned_int_type->AsInteger(),
                                  {1});
-  auto registered_one = context->get_constant_mgr()->FindConstant(&one);
+  auto registered_one = ir_context->get_constant_mgr()->FindConstant(&one);
   if (!registered_one) {
     // We need 1 in order to be able to increment loop limiters.
     return false;
   }
-  uint32_t one_id = context->get_constant_mgr()
+  uint32_t one_id = ir_context->get_constant_mgr()
                         ->GetDefiningInstruction(registered_one)
                         ->result_id();
 
@@ -434,7 +440,7 @@
   opt::analysis::Pointer pointer_to_unsigned_int_type(
       registered_unsigned_int_type, SpvStorageClassFunction);
   uint32_t pointer_to_unsigned_int_type_id =
-      context->get_type_mgr()->GetId(&pointer_to_unsigned_int_type);
+      ir_context->get_type_mgr()->GetId(&pointer_to_unsigned_int_type);
   if (!pointer_to_unsigned_int_type_id) {
     // We need pointer-to-unsigned int in order to declare the loop limiter
     // variable.
@@ -443,7 +449,7 @@
 
   // Look for bool type.
   opt::analysis::Bool bool_type;
-  uint32_t bool_type_id = context->get_type_mgr()->GetId(&bool_type);
+  uint32_t bool_type_id = ir_context->get_type_mgr()->GetId(&bool_type);
   if (!bool_type_id) {
     // We need bool in order to compare the loop limiter's value with the loop
     // limit constant.
@@ -454,22 +460,23 @@
   // block, via an instruction of the form:
   //   %loop_limiter_var = SpvOpVariable %ptr_to_uint Function %zero
   added_function->begin()->begin()->InsertBefore(MakeUnique<opt::Instruction>(
-      context, SpvOpVariable, pointer_to_unsigned_int_type_id,
+      ir_context, SpvOpVariable, pointer_to_unsigned_int_type_id,
       message_.loop_limiter_variable_id(),
       opt::Instruction::OperandList(
           {{SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassFunction}},
            {SPV_OPERAND_TYPE_ID, {zero_id}}})));
   // Update the module's id bound since we have added the loop limiter
   // variable id.
-  fuzzerutil::UpdateModuleIdBound(context, message_.loop_limiter_variable_id());
+  fuzzerutil::UpdateModuleIdBound(ir_context,
+                                  message_.loop_limiter_variable_id());
 
   // Consider each loop in turn.
   for (auto loop_header : loop_headers) {
     // Look for the loop's back-edge block.  This is a predecessor of the loop
     // header that is dominated by the loop header.
     uint32_t back_edge_block_id = 0;
-    for (auto pred : context->cfg()->preds(loop_header->id())) {
-      if (context->GetDominatorAnalysis(added_function)
+    for (auto pred : ir_context->cfg()->preds(loop_header->id())) {
+      if (ir_context->GetDominatorAnalysis(added_function)
               ->Dominates(loop_header->id(), pred)) {
         back_edge_block_id = pred;
         break;
@@ -481,7 +488,7 @@
       // move on from this loop.
       continue;
     }
-    auto back_edge_block = context->cfg()->block(back_edge_block_id);
+    auto back_edge_block = ir_context->cfg()->block(back_edge_block_id);
 
     // Go through the sequence of loop limiter infos and find the one
     // corresponding to this loop.
@@ -579,14 +586,15 @@
     // Add a load from the loop limiter variable, of the form:
     //   %t1 = OpLoad %uint32 %loop_limiter
     new_instructions.push_back(MakeUnique<opt::Instruction>(
-        context, SpvOpLoad, unsigned_int_type_id, loop_limiter_info.load_id(),
+        ir_context, SpvOpLoad, unsigned_int_type_id,
+        loop_limiter_info.load_id(),
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {message_.loop_limiter_variable_id()}}})));
 
     // Increment the loaded value:
     //   %t2 = OpIAdd %uint32 %t1 %one
     new_instructions.push_back(MakeUnique<opt::Instruction>(
-        context, SpvOpIAdd, unsigned_int_type_id,
+        ir_context, SpvOpIAdd, unsigned_int_type_id,
         loop_limiter_info.increment_id(),
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {loop_limiter_info.load_id()}},
@@ -595,7 +603,7 @@
     // Store the incremented value back to the loop limiter variable:
     //   OpStore %loop_limiter %t2
     new_instructions.push_back(MakeUnique<opt::Instruction>(
-        context, SpvOpStore, 0, 0,
+        ir_context, SpvOpStore, 0, 0,
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {message_.loop_limiter_variable_id()}},
              {SPV_OPERAND_TYPE_ID, {loop_limiter_info.increment_id()}}})));
@@ -605,7 +613,7 @@
     // or
     //   %t3 = OpULessThan %bool %t1 %loop_limit
     new_instructions.push_back(MakeUnique<opt::Instruction>(
-        context,
+        ir_context,
         compare_using_greater_than_equal ? SpvOpUGreaterThanEqual
                                          : SpvOpULessThan,
         bool_type_id, loop_limiter_info.compare_id(),
@@ -615,7 +623,7 @@
 
     if (back_edge_block_terminator->opcode() == SpvOpBranchConditional) {
       new_instructions.push_back(MakeUnique<opt::Instruction>(
-          context,
+          ir_context,
           compare_using_greater_than_equal ? SpvOpLogicalOr : SpvOpLogicalAnd,
           bool_type_id, loop_limiter_info.logical_op_id(),
           opt::Instruction::OperandList(
@@ -644,8 +652,9 @@
       // Check that, if the merge block starts with OpPhi instructions, suitable
       // ids have been provided to give these instructions a value corresponding
       // to the new incoming edge from the back edge block.
-      auto merge_block = context->cfg()->block(loop_header->MergeBlockId());
-      if (!fuzzerutil::PhiIdsOkForNewEdge(context, back_edge_block, merge_block,
+      auto merge_block = ir_context->cfg()->block(loop_header->MergeBlockId());
+      if (!fuzzerutil::PhiIdsOkForNewEdge(ir_context, back_edge_block,
+                                          merge_block,
                                           loop_limiter_info.phi_id())) {
         return false;
       }
@@ -681,16 +690,18 @@
 
     // Update the module's id bound with respect to the various ids that
     // have been used for loop limiter manipulation.
-    fuzzerutil::UpdateModuleIdBound(context, loop_limiter_info.load_id());
-    fuzzerutil::UpdateModuleIdBound(context, loop_limiter_info.increment_id());
-    fuzzerutil::UpdateModuleIdBound(context, loop_limiter_info.compare_id());
-    fuzzerutil::UpdateModuleIdBound(context, loop_limiter_info.logical_op_id());
+    fuzzerutil::UpdateModuleIdBound(ir_context, loop_limiter_info.load_id());
+    fuzzerutil::UpdateModuleIdBound(ir_context,
+                                    loop_limiter_info.increment_id());
+    fuzzerutil::UpdateModuleIdBound(ir_context, loop_limiter_info.compare_id());
+    fuzzerutil::UpdateModuleIdBound(ir_context,
+                                    loop_limiter_info.logical_op_id());
   }
   return true;
 }
 
 bool TransformationAddFunction::TryToTurnKillOrUnreachableIntoReturn(
-    opt::IRContext* context, opt::Function* added_function,
+    opt::IRContext* ir_context, opt::Function* added_function,
     opt::Instruction* kill_or_unreachable_inst) const {
   assert((kill_or_unreachable_inst->opcode() == SpvOpKill ||
           kill_or_unreachable_inst->opcode() == SpvOpUnreachable) &&
@@ -698,7 +709,7 @@
 
   // Get the function's return type.
   auto function_return_type_inst =
-      context->get_def_use_mgr()->GetDef(added_function->type_id());
+      ir_context->get_def_use_mgr()->GetDef(added_function->type_id());
 
   if (function_return_type_inst->opcode() == SpvOpTypeVoid) {
     // The function has void return type, so change this instruction to
@@ -712,7 +723,7 @@
     // We first check that the id, %id, provided with the transformation
     // specifically to turn OpKill and OpUnreachable instructions into
     // OpReturnValue %id has the same type as the function's return type.
-    if (context->get_def_use_mgr()
+    if (ir_context->get_def_use_mgr()
             ->GetDef(message_.kill_unreachable_return_value_id())
             ->type_id() != function_return_type_inst->result_id()) {
       return false;
@@ -725,7 +736,7 @@
 }
 
 bool TransformationAddFunction::TryToClampAccessChainIndices(
-    opt::IRContext* context, opt::Instruction* access_chain_inst) const {
+    opt::IRContext* ir_context, opt::Instruction* access_chain_inst) const {
   assert((access_chain_inst->opcode() == SpvOpAccessChain ||
           access_chain_inst->opcode() == SpvOpInBoundsAccessChain) &&
          "Precondition: instruction must be OpAccessChain or "
@@ -756,14 +767,14 @@
 
   // Walk the access chain, clamping each index to be within bounds if it is
   // not a constant.
-  auto base_object = context->get_def_use_mgr()->GetDef(
+  auto base_object = ir_context->get_def_use_mgr()->GetDef(
       access_chain_inst->GetSingleWordInOperand(0));
   assert(base_object && "The base object must exist.");
   auto pointer_type =
-      context->get_def_use_mgr()->GetDef(base_object->type_id());
+      ir_context->get_def_use_mgr()->GetDef(base_object->type_id());
   assert(pointer_type && pointer_type->opcode() == SpvOpTypePointer &&
          "The base object must have pointer type.");
-  auto should_be_composite_type = context->get_def_use_mgr()->GetDef(
+  auto should_be_composite_type = ir_context->get_def_use_mgr()->GetDef(
       pointer_type->GetSingleWordInOperand(1));
 
   // Consider each index input operand in turn (operand 0 is the base object).
@@ -784,18 +795,18 @@
     // Get the bound for the composite being indexed into; e.g. the number of
     // columns of matrix or the size of an array.
     uint32_t bound =
-        GetBoundForCompositeIndex(context, *should_be_composite_type);
+        GetBoundForCompositeIndex(ir_context, *should_be_composite_type);
 
     // Get the instruction associated with the index and figure out its integer
     // type.
     const uint32_t index_id = access_chain_inst->GetSingleWordInOperand(index);
-    auto index_inst = context->get_def_use_mgr()->GetDef(index_id);
+    auto index_inst = ir_context->get_def_use_mgr()->GetDef(index_id);
     auto index_type_inst =
-        context->get_def_use_mgr()->GetDef(index_inst->type_id());
+        ir_context->get_def_use_mgr()->GetDef(index_inst->type_id());
     assert(index_type_inst->opcode() == SpvOpTypeInt);
     assert(index_type_inst->GetSingleWordInOperand(0) == 32);
     opt::analysis::Integer* index_int_type =
-        context->get_type_mgr()
+        ir_context->get_type_mgr()
             ->GetType(index_type_inst->result_id())
             ->AsInteger();
 
@@ -805,20 +816,20 @@
              "Access chain indices into structures are required to be "
              "constants.");
       opt::analysis::IntConstant bound_minus_one(index_int_type, {bound - 1});
-      if (!context->get_constant_mgr()->FindConstant(&bound_minus_one)) {
+      if (!ir_context->get_constant_mgr()->FindConstant(&bound_minus_one)) {
         // We do not have an integer constant whose value is |bound| -1.
         return false;
       }
 
       opt::analysis::Bool bool_type;
-      uint32_t bool_type_id = context->get_type_mgr()->GetId(&bool_type);
+      uint32_t bool_type_id = ir_context->get_type_mgr()->GetId(&bool_type);
       if (!bool_type_id) {
         // Bool type is not declared; we cannot do a comparison.
         return false;
       }
 
       uint32_t bound_minus_one_id =
-          context->get_constant_mgr()
+          ir_context->get_constant_mgr()
               ->GetDefiningInstruction(&bound_minus_one)
               ->result_id();
 
@@ -832,7 +843,7 @@
       // Compare the index with the bound via an instruction of the form:
       //   %t1 = OpULessThanEqual %bool %index %bound_minus_one
       new_instructions.push_back(MakeUnique<opt::Instruction>(
-          context, SpvOpULessThanEqual, bool_type_id, compare_id,
+          ir_context, SpvOpULessThanEqual, bool_type_id, compare_id,
           opt::Instruction::OperandList(
               {{SPV_OPERAND_TYPE_ID, {index_inst->result_id()}},
                {SPV_OPERAND_TYPE_ID, {bound_minus_one_id}}})));
@@ -840,7 +851,7 @@
       // Select the index if in-bounds, otherwise one less than the bound:
       //   %t2 = OpSelect %int_type %t1 %index %bound_minus_one
       new_instructions.push_back(MakeUnique<opt::Instruction>(
-          context, SpvOpSelect, index_type_inst->result_id(), select_id,
+          ir_context, SpvOpSelect, index_type_inst->result_id(), select_id,
           opt::Instruction::OperandList(
               {{SPV_OPERAND_TYPE_ID, {compare_id}},
                {SPV_OPERAND_TYPE_ID, {index_inst->result_id()}},
@@ -851,8 +862,8 @@
 
       // Replace %index with %t2.
       access_chain_inst->SetInOperand(index, {select_id});
-      fuzzerutil::UpdateModuleIdBound(context, compare_id);
-      fuzzerutil::UpdateModuleIdBound(context, select_id);
+      fuzzerutil::UpdateModuleIdBound(ir_context, compare_id);
+      fuzzerutil::UpdateModuleIdBound(ir_context, select_id);
     } else {
       // TODO(afd): At present the SPIR-V spec is not clear on whether
       //  statically out-of-bounds indices mean that a module is invalid (so
@@ -870,22 +881,27 @@
       }
     }
     should_be_composite_type =
-        FollowCompositeIndex(context, *should_be_composite_type, index_id);
+        FollowCompositeIndex(ir_context, *should_be_composite_type, index_id);
   }
   return true;
 }
 
 uint32_t TransformationAddFunction::GetBoundForCompositeIndex(
-    opt::IRContext* context, const opt::Instruction& composite_type_inst) {
+    opt::IRContext* ir_context, const opt::Instruction& composite_type_inst) {
   switch (composite_type_inst.opcode()) {
     case SpvOpTypeArray:
-      return fuzzerutil::GetArraySize(composite_type_inst, context);
+      return fuzzerutil::GetArraySize(composite_type_inst, ir_context);
     case SpvOpTypeMatrix:
     case SpvOpTypeVector:
       return composite_type_inst.GetSingleWordInOperand(1);
     case SpvOpTypeStruct: {
       return fuzzerutil::GetNumberOfStructMembers(composite_type_inst);
     }
+    case SpvOpTypeRuntimeArray:
+      assert(false &&
+             "GetBoundForCompositeIndex should not be invoked with an "
+             "OpTypeRuntimeArray, which does not have a static bound.");
+      return 0;
     default:
       assert(false && "Unknown composite type.");
       return 0;
@@ -893,11 +909,12 @@
 }
 
 opt::Instruction* TransformationAddFunction::FollowCompositeIndex(
-    opt::IRContext* context, const opt::Instruction& composite_type_inst,
+    opt::IRContext* ir_context, const opt::Instruction& composite_type_inst,
     uint32_t index_id) {
   uint32_t sub_object_type_id;
   switch (composite_type_inst.opcode()) {
     case SpvOpTypeArray:
+    case SpvOpTypeRuntimeArray:
       sub_object_type_id = composite_type_inst.GetSingleWordInOperand(0);
       break;
     case SpvOpTypeMatrix:
@@ -905,12 +922,12 @@
       sub_object_type_id = composite_type_inst.GetSingleWordInOperand(0);
       break;
     case SpvOpTypeStruct: {
-      auto index_inst = context->get_def_use_mgr()->GetDef(index_id);
+      auto index_inst = ir_context->get_def_use_mgr()->GetDef(index_id);
       assert(index_inst->opcode() == SpvOpConstant);
-      assert(
-          context->get_def_use_mgr()->GetDef(index_inst->type_id())->opcode() ==
-          SpvOpTypeInt);
-      assert(context->get_def_use_mgr()
+      assert(ir_context->get_def_use_mgr()
+                 ->GetDef(index_inst->type_id())
+                 ->opcode() == SpvOpTypeInt);
+      assert(ir_context->get_def_use_mgr()
                  ->GetDef(index_inst->type_id())
                  ->GetSingleWordInOperand(0) == 32);
       uint32_t index_value = index_inst->GetSingleWordInOperand(0);
@@ -924,7 +941,7 @@
       break;
   }
   assert(sub_object_type_id && "No sub-object found.");
-  return context->get_def_use_mgr()->GetDef(sub_object_type_id);
+  return ir_context->get_def_use_mgr()->GetDef(sub_object_type_id);
 }
 
 }  // namespace fuzz
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_function.h b/third_party/spirv-tools/src/source/fuzz/transformation_add_function.h
index 848b799..5af197b 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_add_function.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_function.h
@@ -15,9 +15,9 @@
 #ifndef SOURCE_FUZZ_TRANSFORMATION_ADD_FUNCTION_H_
 #define SOURCE_FUZZ_TRANSFORMATION_ADD_FUNCTION_H_
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -47,12 +47,14 @@
   //   ingredients to make the function livesafe, and the function must only
   //   invoke other livesafe functions
   // - Adding the created function to the module must lead to a valid module.
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // Adds the function defined by |message_.instruction| to the module, making
   // it livesafe if |message_.is_livesafe| holds.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
@@ -61,26 +63,26 @@
   // an array, the number of components of a vector, or the number of columns of
   // a matrix.
   static uint32_t GetBoundForCompositeIndex(
-      opt::IRContext* context, const opt::Instruction& composite_type_inst);
+      opt::IRContext* ir_context, const opt::Instruction& composite_type_inst);
 
   // Helper method that, given composite type |composite_type_inst|, returns the
   // type of the sub-object at index |index_id|, which is required to be in-
   // bounds.
   static opt::Instruction* FollowCompositeIndex(
-      opt::IRContext* context, const opt::Instruction& composite_type_inst,
+      opt::IRContext* ir_context, const opt::Instruction& composite_type_inst,
       uint32_t index_id);
 
  private:
   // Attempts to create a function from the series of instructions in
-  // |message_.instruction| and add it to |context|.
+  // |message_.instruction| and add it to |ir_context|.
   //
   // Returns false if adding the function is not possible due to the messages
   // not respecting the basic structure of a function, e.g. if there is no
-  // OpFunction instruction or no blocks; in this case |context| is left in an
-  // indeterminate state.
+  // OpFunction instruction or no blocks; in this case |ir_context| is left in
+  // an indeterminate state.
   //
-  // Otherwise returns true.  Whether |context| is valid after addition of the
-  // function depends on the contents of |message_.instruction|.
+  // Otherwise returns true.  Whether |ir_context| is valid after addition of
+  // the function depends on the contents of |message_.instruction|.
   //
   // Intended usage:
   // - Perform a dry run of this method on a clone of a module, and use
@@ -89,30 +91,31 @@
   //   added, or leads to an invalid module.
   // - If the dry run succeeds, run the method on the real module of interest,
   //   to add the function.
-  bool TryToAddFunction(opt::IRContext* context) const;
+  bool TryToAddFunction(opt::IRContext* ir_context) const;
 
   // Should only be called if |message_.is_livesafe| holds.  Attempts to make
   // the function livesafe (see FactFunctionIsLivesafe for a definition).
-  // Returns false if this is not possible, due to |message_| or |context| not
-  // containing sufficient ingredients (such as types and fresh ids) to add
+  // Returns false if this is not possible, due to |message_| or |ir_context|
+  // not containing sufficient ingredients (such as types and fresh ids) to add
   // the instrumentation necessary to make the function livesafe.
-  bool TryToMakeFunctionLivesafe(opt::IRContext* context,
-                                 const FactManager& fact_manager) const;
+  bool TryToMakeFunctionLivesafe(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const;
 
   // A helper for TryToMakeFunctionLivesafe that tries to add loop-limiting
   // logic.
-  bool TryToAddLoopLimiters(opt::IRContext* context,
+  bool TryToAddLoopLimiters(opt::IRContext* ir_context,
                             opt::Function* added_function) const;
 
   // A helper for TryToMakeFunctionLivesafe that tries to replace OpKill and
   // OpUnreachable instructions into return instructions.
   bool TryToTurnKillOrUnreachableIntoReturn(
-      opt::IRContext* context, opt::Function* added_function,
+      opt::IRContext* ir_context, opt::Function* added_function,
       opt::Instruction* kill_or_unreachable_inst) const;
 
   // A helper for TryToMakeFunctionLivesafe that tries to clamp access chain
   // indices so that they are guaranteed to be in-bounds.
-  bool TryToClampAccessChainIndices(opt::IRContext* context,
+  bool TryToClampAccessChainIndices(opt::IRContext* ir_context,
                                     opt::Instruction* access_chain_inst) const;
 
   protobufs::TransformationAddFunction message_;
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_global_undef.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_add_global_undef.cpp
index f9585b3..ba45f22 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_add_global_undef.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_global_undef.cpp
@@ -30,26 +30,26 @@
 }
 
 bool TransformationAddGlobalUndef::IsApplicable(
-    opt::IRContext* context,
-    const spvtools::fuzz::FactManager& /*unused*/) const {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
   // A fresh id is required.
-  if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
+  if (!fuzzerutil::IsFreshId(ir_context, message_.fresh_id())) {
     return false;
   }
-  auto type = context->get_type_mgr()->GetType(message_.type_id());
+  auto type = ir_context->get_type_mgr()->GetType(message_.type_id());
   // The type must exist, and must not be a function type.
   return type && !type->AsFunction();
 }
 
 void TransformationAddGlobalUndef::Apply(
-    opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/) const {
-  context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
-      context, SpvOpUndef, message_.type_id(), message_.fresh_id(),
+    opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
+  ir_context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
+      ir_context, SpvOpUndef, message_.type_id(), message_.fresh_id(),
       opt::Instruction::OperandList()));
-  fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
+  fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
   // We have added an instruction to the module, so need to be careful about the
   // validity of existing analyses.
-  context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(
+      opt::IRContext::Analysis::kAnalysisNone);
 }
 
 protobufs::Transformation TransformationAddGlobalUndef::ToMessage() const {
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_global_undef.h b/third_party/spirv-tools/src/source/fuzz/transformation_add_global_undef.h
index 550d9f6..c89fe9d 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_add_global_undef.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_global_undef.h
@@ -15,9 +15,9 @@
 #ifndef SOURCE_FUZZ_TRANSFORMATION_ADD_GLOBAL_UNDEF_H_
 #define SOURCE_FUZZ_TRANSFORMATION_ADD_GLOBAL_UNDEF_H_
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -32,12 +32,14 @@
 
   // - |message_.fresh_id| must be fresh
   // - |message_.type_id| must be the id of a non-function type
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // Adds an OpUndef instruction to the module, with |message_.type_id| as its
   // type.  The instruction has result id |message_.fresh_id|.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_global_variable.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_add_global_variable.cpp
index e4f9f7a..6464bfb 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_add_global_variable.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_global_variable.cpp
@@ -24,23 +24,34 @@
     : message_(message) {}
 
 TransformationAddGlobalVariable::TransformationAddGlobalVariable(
-    uint32_t fresh_id, uint32_t type_id, uint32_t initializer_id,
-    bool value_is_irrelevant) {
+    uint32_t fresh_id, uint32_t type_id, SpvStorageClass storage_class,
+    uint32_t initializer_id, bool value_is_irrelevant) {
   message_.set_fresh_id(fresh_id);
   message_.set_type_id(type_id);
+  message_.set_storage_class(storage_class);
   message_.set_initializer_id(initializer_id);
   message_.set_value_is_irrelevant(value_is_irrelevant);
 }
 
 bool TransformationAddGlobalVariable::IsApplicable(
-    opt::IRContext* context,
-    const spvtools::fuzz::FactManager& /*unused*/) const {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
   // The result id must be fresh.
-  if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
+  if (!fuzzerutil::IsFreshId(ir_context, message_.fresh_id())) {
     return false;
   }
+
+  // The storage class must be Private or Workgroup.
+  auto storage_class = static_cast<SpvStorageClass>(message_.storage_class());
+  switch (storage_class) {
+    case SpvStorageClassPrivate:
+    case SpvStorageClassWorkgroup:
+      break;
+    default:
+      assert(false && "Unsupported storage class.");
+      return false;
+  }
   // The type id must correspond to a type.
-  auto type = context->get_type_mgr()->GetType(message_.type_id());
+  auto type = ir_context->get_type_mgr()->GetType(message_.type_id());
   if (!type) {
     return false;
   }
@@ -49,42 +60,52 @@
   if (!pointer_type) {
     return false;
   }
-  // ... with Private storage class.
-  if (pointer_type->storage_class() != SpvStorageClassPrivate) {
+  // ... with the right storage class.
+  if (pointer_type->storage_class() != storage_class) {
     return false;
   }
-  // The initializer id must be the id of a constant.  Check this with the
-  // constant manager.
-  auto constant_id = context->get_constant_mgr()->GetConstantsFromIds(
-      {message_.initializer_id()});
-  if (constant_id.empty()) {
-    return false;
-  }
-  assert(constant_id.size() == 1 &&
-         "We asked for the constant associated with a single id; we should "
-         "get a single constant.");
-  // The type of the constant must match the pointee type of the pointer.
-  if (pointer_type->pointee_type() != constant_id[0]->type()) {
-    return false;
+  if (message_.initializer_id()) {
+    // An initializer is not allowed if the storage class is Workgroup.
+    if (storage_class == SpvStorageClassWorkgroup) {
+      assert(false &&
+             "By construction this transformation should not have an "
+             "initializer when Workgroup storage class is used.");
+      return false;
+    }
+    // The initializer id must be the id of a constant.  Check this with the
+    // constant manager.
+    auto constant_id = ir_context->get_constant_mgr()->GetConstantsFromIds(
+        {message_.initializer_id()});
+    if (constant_id.empty()) {
+      return false;
+    }
+    assert(constant_id.size() == 1 &&
+           "We asked for the constant associated with a single id; we should "
+           "get a single constant.");
+    // The type of the constant must match the pointee type of the pointer.
+    if (pointer_type->pointee_type() != constant_id[0]->type()) {
+      return false;
+    }
   }
   return true;
 }
 
 void TransformationAddGlobalVariable::Apply(
-    opt::IRContext* context, spvtools::fuzz::FactManager* fact_manager) const {
+    opt::IRContext* ir_context,
+    TransformationContext* transformation_context) const {
   opt::Instruction::OperandList input_operands;
   input_operands.push_back(
-      {SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassPrivate}});
+      {SPV_OPERAND_TYPE_STORAGE_CLASS, {message_.storage_class()}});
   if (message_.initializer_id()) {
     input_operands.push_back(
         {SPV_OPERAND_TYPE_ID, {message_.initializer_id()}});
   }
-  context->module()->AddGlobalValue(
-      MakeUnique<opt::Instruction>(context, SpvOpVariable, message_.type_id(),
-                                   message_.fresh_id(), input_operands));
-  fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
+  ir_context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
+      ir_context, SpvOpVariable, message_.type_id(), message_.fresh_id(),
+      input_operands));
+  fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
 
-  if (PrivateGlobalsMustBeDeclaredInEntryPointInterfaces(context)) {
+  if (GlobalVariablesMustBeDeclaredInEntryPointInterfaces(ir_context)) {
     // Conservatively add this global to the interface of every entry point in
     // the module.  This means that the global is available for other
     // transformations to use.
@@ -94,18 +115,20 @@
     //
     // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3111) revisit
     //  this if a more thorough approach to entry point interfaces is taken.
-    for (auto& entry_point : context->module()->entry_points()) {
+    for (auto& entry_point : ir_context->module()->entry_points()) {
       entry_point.AddOperand({SPV_OPERAND_TYPE_ID, {message_.fresh_id()}});
     }
   }
 
   if (message_.value_is_irrelevant()) {
-    fact_manager->AddFactValueOfPointeeIsIrrelevant(message_.fresh_id());
+    transformation_context->GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
+        message_.fresh_id());
   }
 
   // We have added an instruction to the module, so need to be careful about the
   // validity of existing analyses.
-  context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(
+      opt::IRContext::Analysis::kAnalysisNone);
 }
 
 protobufs::Transformation TransformationAddGlobalVariable::ToMessage() const {
@@ -115,12 +138,12 @@
 }
 
 bool TransformationAddGlobalVariable::
-    PrivateGlobalsMustBeDeclaredInEntryPointInterfaces(
-        opt::IRContext* context) {
+    GlobalVariablesMustBeDeclaredInEntryPointInterfaces(
+        opt::IRContext* ir_context) {
   // TODO(afd): We capture the universal environments for which this requirement
   //  holds.  The check should be refined on demand for other target
   //  environments.
-  switch (context->grammar().target_env()) {
+  switch (ir_context->grammar().target_env()) {
     case SPV_ENV_UNIVERSAL_1_0:
     case SPV_ENV_UNIVERSAL_1_1:
     case SPV_ENV_UNIVERSAL_1_2:
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_global_variable.h b/third_party/spirv-tools/src/source/fuzz/transformation_add_global_variable.h
index 920ac45..289af9e 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_add_global_variable.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_global_variable.h
@@ -15,9 +15,9 @@
 #ifndef SOURCE_FUZZ_TRANSFORMATION_ADD_GLOBAL_VARIABLE_H_
 #define SOURCE_FUZZ_TRANSFORMATION_ADD_GLOBAL_VARIABLE_H_
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -29,31 +29,40 @@
       const protobufs::TransformationAddGlobalVariable& message);
 
   TransformationAddGlobalVariable(uint32_t fresh_id, uint32_t type_id,
+                                  SpvStorageClass storage_class,
                                   uint32_t initializer_id,
                                   bool value_is_irrelevant);
 
   // - |message_.fresh_id| must be fresh
-  // - |message_.type_id| must be the id of a pointer type with Private storage
-  //   class
-  // - |message_.initializer_id| must either be 0 or the id of a constant whose
+  // - |message_.type_id| must be the id of a pointer type with the same storage
+  //   class as |message_.storage_class|
+  // - |message_.storage_class| must be Private or Workgroup
+  // - |message_.initializer_id| must be 0 if |message_.storage_class| is
+  //   Workgroup, and otherwise may either be 0 or the id of a constant whose
   //   type is the pointee type of |message_.type_id|
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
-  // Adds a global variable with Private storage class to the module, with type
-  // |message_.type_id| and either no initializer or |message_.initializer_id|
-  // as an initializer, depending on whether |message_.initializer_id| is 0.
-  // The global variable has result id |message_.fresh_id|.
+  // Adds a global variable with storage class |message_.storage_class| to the
+  // module, with type |message_.type_id| and either no initializer or
+  // |message_.initializer_id| as an initializer, depending on whether
+  // |message_.initializer_id| is 0.  The global variable has result id
+  // |message_.fresh_id|.
   //
-  // If |message_.value_is_irrelevant| holds, adds a corresponding fact to
-  // |fact_manager|.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  // If |message_.value_is_irrelevant| holds, adds a corresponding fact to the
+  // fact manager in |transformation_context|.
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
  private:
-  static bool PrivateGlobalsMustBeDeclaredInEntryPointInterfaces(
-      opt::IRContext* context);
+  // Returns true if and only if the SPIR-V version being used requires that
+  // global variables accessed in the static call graph of an entry point need
+  // to be listed in that entry point's interface.
+  static bool GlobalVariablesMustBeDeclaredInEntryPointInterfaces(
+      opt::IRContext* ir_context);
 
   protobufs::TransformationAddGlobalVariable message_;
 };
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_local_variable.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_add_local_variable.cpp
index 69e536d..5136249 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_add_local_variable.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_local_variable.cpp
@@ -34,23 +34,22 @@
 }
 
 bool TransformationAddLocalVariable::IsApplicable(
-    opt::IRContext* context,
-    const spvtools::fuzz::FactManager& /*unused*/) const {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
   // The provided id must be fresh.
-  if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
+  if (!fuzzerutil::IsFreshId(ir_context, message_.fresh_id())) {
     return false;
   }
   // The pointer type id must indeed correspond to a pointer, and it must have
   // function storage class.
   auto type_instruction =
-      context->get_def_use_mgr()->GetDef(message_.type_id());
+      ir_context->get_def_use_mgr()->GetDef(message_.type_id());
   if (!type_instruction || type_instruction->opcode() != SpvOpTypePointer ||
       type_instruction->GetSingleWordInOperand(0) != SpvStorageClassFunction) {
     return false;
   }
   // The initializer must...
   auto initializer_instruction =
-      context->get_def_use_mgr()->GetDef(message_.initializer_id());
+      ir_context->get_def_use_mgr()->GetDef(message_.initializer_id());
   // ... exist, ...
   if (!initializer_instruction) {
     return false;
@@ -65,17 +64,18 @@
     return false;
   }
   // The function to which the local variable is to be added must exist.
-  return fuzzerutil::FindFunction(context, message_.function_id());
+  return fuzzerutil::FindFunction(ir_context, message_.function_id());
 }
 
 void TransformationAddLocalVariable::Apply(
-    opt::IRContext* context, spvtools::fuzz::FactManager* fact_manager) const {
-  fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
-  fuzzerutil::FindFunction(context, message_.function_id())
+    opt::IRContext* ir_context,
+    TransformationContext* transformation_context) const {
+  fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
+  fuzzerutil::FindFunction(ir_context, message_.function_id())
       ->begin()
       ->begin()
       ->InsertBefore(MakeUnique<opt::Instruction>(
-          context, SpvOpVariable, message_.type_id(), message_.fresh_id(),
+          ir_context, SpvOpVariable, message_.type_id(), message_.fresh_id(),
           opt::Instruction::OperandList(
               {{SPV_OPERAND_TYPE_STORAGE_CLASS,
                 {
@@ -83,9 +83,10 @@
                     SpvStorageClassFunction}},
                {SPV_OPERAND_TYPE_ID, {message_.initializer_id()}}})));
   if (message_.value_is_irrelevant()) {
-    fact_manager->AddFactValueOfPointeeIsIrrelevant(message_.fresh_id());
+    transformation_context->GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
+        message_.fresh_id());
   }
-  context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
 }
 
 protobufs::Transformation TransformationAddLocalVariable::ToMessage() const {
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_local_variable.h b/third_party/spirv-tools/src/source/fuzz/transformation_add_local_variable.h
index b8e00dd..6460904 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_add_local_variable.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_local_variable.h
@@ -15,9 +15,9 @@
 #ifndef SOURCE_FUZZ_TRANSFORMATION_ADD_LOCAL_VARIABLE_H_
 #define SOURCE_FUZZ_TRANSFORMATION_ADD_LOCAL_VARIABLE_H_
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -38,15 +38,17 @@
   // - |message_.initializer_id| must be the id of a constant with the same
   //   type as the pointer's pointee type
   // - |message_.function_id| must be the id of a function
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // Adds an instruction to the start of |message_.function_id|, of the form:
   //   |message_.fresh_id| = OpVariable |message_.type_id| Function
   //                         |message_.initializer_id|
-  // If |message_.value_is_irrelevant| holds, adds a corresponding fact to
-  // |fact_manager|.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  // If |message_.value_is_irrelevant| holds, adds a corresponding fact to the
+  // fact manager in |transformation_context|.
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_no_contraction_decoration.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_add_no_contraction_decoration.cpp
index 7f22cc2..4668534 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_add_no_contraction_decoration.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_no_contraction_decoration.cpp
@@ -31,10 +31,9 @@
 }
 
 bool TransformationAddNoContractionDecoration::IsApplicable(
-    opt::IRContext* context,
-    const spvtools::fuzz::FactManager& /*unused*/) const {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
   // |message_.result_id| must be the id of an instruction.
-  auto instr = context->get_def_use_mgr()->GetDef(message_.result_id());
+  auto instr = ir_context->get_def_use_mgr()->GetDef(message_.result_id());
   if (!instr) {
     return false;
   }
@@ -43,10 +42,10 @@
 }
 
 void TransformationAddNoContractionDecoration::Apply(
-    opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/) const {
+    opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
   // Add a NoContraction decoration targeting |message_.result_id|.
-  context->get_decoration_mgr()->AddDecoration(message_.result_id(),
-                                               SpvDecorationNoContraction);
+  ir_context->get_decoration_mgr()->AddDecoration(message_.result_id(),
+                                                  SpvDecorationNoContraction);
 }
 
 protobufs::Transformation TransformationAddNoContractionDecoration::ToMessage()
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_no_contraction_decoration.h b/third_party/spirv-tools/src/source/fuzz/transformation_add_no_contraction_decoration.h
index cec1b2c..27c3a80 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_add_no_contraction_decoration.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_no_contraction_decoration.h
@@ -15,9 +15,9 @@
 #ifndef SOURCE_FUZZ_TRANSFORMATION_ADD_NO_CONTRACTION_DECORATION_H_
 #define SOURCE_FUZZ_TRANSFORMATION_ADD_NO_CONTRACTION_DECORATION_H_
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -34,13 +34,15 @@
   //   as defined by the SPIR-V specification.
   // - It does not matter whether this instruction is already annotated with the
   //   NoContraction decoration.
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // Adds a decoration of the form:
   //   'OpDecoration |message_.result_id| NoContraction'
   // to the module.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_type_array.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_add_type_array.cpp
index 2074e98..8f5af07 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_add_type_array.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_type_array.cpp
@@ -32,21 +32,20 @@
 }
 
 bool TransformationAddTypeArray::IsApplicable(
-    opt::IRContext* context,
-    const spvtools::fuzz::FactManager& /*unused*/) const {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
   // A fresh id is required.
-  if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
+  if (!fuzzerutil::IsFreshId(ir_context, message_.fresh_id())) {
     return false;
   }
   auto element_type =
-      context->get_type_mgr()->GetType(message_.element_type_id());
+      ir_context->get_type_mgr()->GetType(message_.element_type_id());
   if (!element_type || element_type->AsFunction()) {
     // The element type id either does not refer to a type, or refers to a
     // function type; both are illegal.
     return false;
   }
   auto constant =
-      context->get_constant_mgr()->GetConstantsFromIds({message_.size_id()});
+      ir_context->get_constant_mgr()->GetConstantsFromIds({message_.size_id()});
   if (constant.empty()) {
     // The size id does not refer to a constant.
     return false;
@@ -66,16 +65,17 @@
 }
 
 void TransformationAddTypeArray::Apply(
-    opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/) const {
+    opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
   opt::Instruction::OperandList in_operands;
   in_operands.push_back({SPV_OPERAND_TYPE_ID, {message_.element_type_id()}});
   in_operands.push_back({SPV_OPERAND_TYPE_ID, {message_.size_id()}});
-  context->module()->AddType(MakeUnique<opt::Instruction>(
-      context, SpvOpTypeArray, 0, message_.fresh_id(), in_operands));
-  fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
+  ir_context->module()->AddType(MakeUnique<opt::Instruction>(
+      ir_context, SpvOpTypeArray, 0, message_.fresh_id(), in_operands));
+  fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
   // We have added an instruction to the module, so need to be careful about the
   // validity of existing analyses.
-  context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(
+      opt::IRContext::Analysis::kAnalysisNone);
 }
 
 protobufs::Transformation TransformationAddTypeArray::ToMessage() const {
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_type_array.h b/third_party/spirv-tools/src/source/fuzz/transformation_add_type_array.h
index b6e0718..5e9b8aa 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_add_type_array.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_type_array.h
@@ -15,9 +15,9 @@
 #ifndef SOURCE_FUZZ_TRANSFORMATION_ADD_TYPE_ARRAY_H_
 #define SOURCE_FUZZ_TRANSFORMATION_ADD_TYPE_ARRAY_H_
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -35,13 +35,15 @@
   // - |message_.element_type_id| must be the id of a non-function type
   // - |message_.size_id| must be the id of a 32-bit integer constant that is
   //   positive when interpreted as signed.
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // Adds an OpTypeArray instruction to the module, with element type given by
   // |message_.element_type_id| and size given by |message_.size_id|.  The
   // result id of the instruction is |message_.fresh_id|.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_type_boolean.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_add_type_boolean.cpp
index b55028a..77409a8 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_add_type_boolean.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_type_boolean.cpp
@@ -28,27 +28,27 @@
 }
 
 bool TransformationAddTypeBoolean::IsApplicable(
-    opt::IRContext* context,
-    const spvtools::fuzz::FactManager& /*unused*/) const {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
   // The id must be fresh.
-  if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
+  if (!fuzzerutil::IsFreshId(ir_context, message_.fresh_id())) {
     return false;
   }
 
   // Applicable if there is no bool type already declared in the module.
   opt::analysis::Bool bool_type;
-  return context->get_type_mgr()->GetId(&bool_type) == 0;
+  return ir_context->get_type_mgr()->GetId(&bool_type) == 0;
 }
 
 void TransformationAddTypeBoolean::Apply(
-    opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/) const {
+    opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
   opt::Instruction::OperandList empty_operands;
-  context->module()->AddType(MakeUnique<opt::Instruction>(
-      context, SpvOpTypeBool, 0, message_.fresh_id(), empty_operands));
-  fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
+  ir_context->module()->AddType(MakeUnique<opt::Instruction>(
+      ir_context, SpvOpTypeBool, 0, message_.fresh_id(), empty_operands));
+  fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
   // We have added an instruction to the module, so need to be careful about the
   // validity of existing analyses.
-  context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(
+      opt::IRContext::Analysis::kAnalysisNone);
 }
 
 protobufs::Transformation TransformationAddTypeBoolean::ToMessage() const {
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_type_boolean.h b/third_party/spirv-tools/src/source/fuzz/transformation_add_type_boolean.h
index 98c1e63..5ce5b9a 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_add_type_boolean.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_type_boolean.h
@@ -15,7 +15,6 @@
 #ifndef SOURCE_FUZZ_TRANSFORMATION_ADD_TYPE_BOOLEAN_H_
 #define SOURCE_FUZZ_TRANSFORMATION_ADD_TYPE_BOOLEAN_H_
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
 #include "source/opt/ir_context.h"
@@ -32,11 +31,13 @@
 
   // - |message_.fresh_id| must not be used by the module.
   // - The module must not yet declare OpTypeBoolean
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // Adds OpTypeBoolean with |message_.fresh_id| as result id.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_type_float.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_add_type_float.cpp
index d2af5f8..80716e1 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_add_type_float.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_type_float.cpp
@@ -30,29 +30,29 @@
     : message_(message) {}
 
 bool TransformationAddTypeFloat::IsApplicable(
-    opt::IRContext* context,
-    const spvtools::fuzz::FactManager& /*unused*/) const {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
   // The id must be fresh.
-  if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
+  if (!fuzzerutil::IsFreshId(ir_context, message_.fresh_id())) {
     return false;
   }
 
   // Applicable if there is no float type with this width already declared in
   // the module.
   opt::analysis::Float float_type(message_.width());
-  return context->get_type_mgr()->GetId(&float_type) == 0;
+  return ir_context->get_type_mgr()->GetId(&float_type) == 0;
 }
 
 void TransformationAddTypeFloat::Apply(
-    opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/) const {
+    opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
   opt::Instruction::OperandList width = {
       {SPV_OPERAND_TYPE_LITERAL_INTEGER, {message_.width()}}};
-  context->module()->AddType(MakeUnique<opt::Instruction>(
-      context, SpvOpTypeFloat, 0, message_.fresh_id(), width));
-  fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
+  ir_context->module()->AddType(MakeUnique<opt::Instruction>(
+      ir_context, SpvOpTypeFloat, 0, message_.fresh_id(), width));
+  fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
   // We have added an instruction to the module, so need to be careful about the
   // validity of existing analyses.
-  context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(
+      opt::IRContext::Analysis::kAnalysisNone);
 }
 
 protobufs::Transformation TransformationAddTypeFloat::ToMessage() const {
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_type_float.h b/third_party/spirv-tools/src/source/fuzz/transformation_add_type_float.h
index 0fdc831..a8fa0e1 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_add_type_float.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_type_float.h
@@ -15,9 +15,9 @@
 #ifndef SOURCE_FUZZ_TRANSFORMATION_ADD_TYPE_FLOAT_H_
 #define SOURCE_FUZZ_TRANSFORMATION_ADD_TYPE_FLOAT_H_
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -33,11 +33,13 @@
   // - |message_.fresh_id| must not be used by the module
   // - The module must not contain an OpTypeFloat instruction with width
   //   |message_.width|
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // Adds an OpTypeFloat instruction to the module with the given width
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_type_function.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_add_type_function.cpp
index 4b6717b..991a28b 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_add_type_function.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_type_function.cpp
@@ -36,19 +36,18 @@
 }
 
 bool TransformationAddTypeFunction::IsApplicable(
-    opt::IRContext* context,
-    const spvtools::fuzz::FactManager& /*unused*/) const {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
   // The result id must be fresh.
-  if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
+  if (!fuzzerutil::IsFreshId(ir_context, message_.fresh_id())) {
     return false;
   }
   // The return and argument types must be type ids but not not be function
   // type ids.
-  if (!fuzzerutil::IsNonFunctionTypeId(context, message_.return_type_id())) {
+  if (!fuzzerutil::IsNonFunctionTypeId(ir_context, message_.return_type_id())) {
     return false;
   }
   for (auto argument_type_id : message_.argument_type_id()) {
-    if (!fuzzerutil::IsNonFunctionTypeId(context, argument_type_id)) {
+    if (!fuzzerutil::IsNonFunctionTypeId(ir_context, argument_type_id)) {
       return false;
     }
   }
@@ -56,7 +55,7 @@
   // exactly the same return and argument type ids.  (Note that the type manager
   // does not allow us to check this, as it does not distinguish between
   // function types with different but isomorphic pointer argument types.)
-  for (auto& inst : context->module()->types_values()) {
+  for (auto& inst : ir_context->module()->types_values()) {
     if (inst.opcode() != SpvOpTypeFunction) {
       // Consider only OpTypeFunction instructions.
       continue;
@@ -89,18 +88,19 @@
 }
 
 void TransformationAddTypeFunction::Apply(
-    opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/) const {
+    opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
   opt::Instruction::OperandList in_operands;
   in_operands.push_back({SPV_OPERAND_TYPE_ID, {message_.return_type_id()}});
   for (auto argument_type_id : message_.argument_type_id()) {
     in_operands.push_back({SPV_OPERAND_TYPE_ID, {argument_type_id}});
   }
-  context->module()->AddType(MakeUnique<opt::Instruction>(
-      context, SpvOpTypeFunction, 0, message_.fresh_id(), in_operands));
-  fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
+  ir_context->module()->AddType(MakeUnique<opt::Instruction>(
+      ir_context, SpvOpTypeFunction, 0, message_.fresh_id(), in_operands));
+  fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
   // We have added an instruction to the module, so need to be careful about the
   // validity of existing analyses.
-  context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(
+      opt::IRContext::Analysis::kAnalysisNone);
 }
 
 protobufs::Transformation TransformationAddTypeFunction::ToMessage() const {
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_type_function.h b/third_party/spirv-tools/src/source/fuzz/transformation_add_type_function.h
index 3880963..f26b250 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_add_type_function.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_type_function.h
@@ -17,9 +17,9 @@
 
 #include <vector>
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -39,13 +39,15 @@
   // - The module must not contain an OpTypeFunction instruction defining a
   //   function type with the signature provided by the given return and
   //   argument types
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // Adds an OpTypeFunction instruction to the module, with signature given by
   // |message_.return_type_id| and |message_.argument_type_id|.  The result id
   // for the instruction is |message_.fresh_id|.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_type_int.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_add_type_int.cpp
index 6f59270..a932a5f 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_add_type_int.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_type_int.cpp
@@ -32,30 +32,30 @@
 }
 
 bool TransformationAddTypeInt::IsApplicable(
-    opt::IRContext* context,
-    const spvtools::fuzz::FactManager& /*unused*/) const {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
   // The id must be fresh.
-  if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
+  if (!fuzzerutil::IsFreshId(ir_context, message_.fresh_id())) {
     return false;
   }
 
   // Applicable if there is no int type with this width and signedness already
   // declared in the module.
   opt::analysis::Integer int_type(message_.width(), message_.is_signed());
-  return context->get_type_mgr()->GetId(&int_type) == 0;
+  return ir_context->get_type_mgr()->GetId(&int_type) == 0;
 }
 
-void TransformationAddTypeInt::Apply(
-    opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/) const {
+void TransformationAddTypeInt::Apply(opt::IRContext* ir_context,
+                                     TransformationContext* /*unused*/) const {
   opt::Instruction::OperandList in_operands = {
       {SPV_OPERAND_TYPE_LITERAL_INTEGER, {message_.width()}},
       {SPV_OPERAND_TYPE_LITERAL_INTEGER, {message_.is_signed() ? 1u : 0u}}};
-  context->module()->AddType(MakeUnique<opt::Instruction>(
-      context, SpvOpTypeInt, 0, message_.fresh_id(), in_operands));
-  fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
+  ir_context->module()->AddType(MakeUnique<opt::Instruction>(
+      ir_context, SpvOpTypeInt, 0, message_.fresh_id(), in_operands));
+  fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
   // We have added an instruction to the module, so need to be careful about the
   // validity of existing analyses.
-  context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(
+      opt::IRContext::Analysis::kAnalysisNone);
 }
 
 protobufs::Transformation TransformationAddTypeInt::ToMessage() const {
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_type_int.h b/third_party/spirv-tools/src/source/fuzz/transformation_add_type_int.h
index 86342d0..5c3c959 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_add_type_int.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_type_int.h
@@ -15,9 +15,9 @@
 #ifndef SOURCE_FUZZ_TRANSFORMATION_ADD_TYPE_INT_H_
 #define SOURCE_FUZZ_TRANSFORMATION_ADD_TYPE_INT_H_
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -33,12 +33,14 @@
   // - |message_.fresh_id| must not be used by the module
   // - The module must not contain an OpTypeInt instruction with width
   //   |message_.width| and signedness |message.is_signed|
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // Adds an OpTypeInt instruction to the module with the given width and
   // signedness.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_type_matrix.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_add_type_matrix.cpp
index 07ab705..2c24eaa 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_add_type_matrix.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_type_matrix.cpp
@@ -31,15 +31,14 @@
 }
 
 bool TransformationAddTypeMatrix::IsApplicable(
-    opt::IRContext* context,
-    const spvtools::fuzz::FactManager& /*unused*/) const {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
   // The result id must be fresh.
-  if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
+  if (!fuzzerutil::IsFreshId(ir_context, message_.fresh_id())) {
     return false;
   }
   // The column type must be a floating-point vector.
   auto column_type =
-      context->get_type_mgr()->GetType(message_.column_type_id());
+      ir_context->get_type_mgr()->GetType(message_.column_type_id());
   if (!column_type) {
     return false;
   }
@@ -48,17 +47,18 @@
 }
 
 void TransformationAddTypeMatrix::Apply(
-    opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/) const {
+    opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
   opt::Instruction::OperandList in_operands;
   in_operands.push_back({SPV_OPERAND_TYPE_ID, {message_.column_type_id()}});
   in_operands.push_back(
       {SPV_OPERAND_TYPE_LITERAL_INTEGER, {message_.column_count()}});
-  context->module()->AddType(MakeUnique<opt::Instruction>(
-      context, SpvOpTypeMatrix, 0, message_.fresh_id(), in_operands));
-  fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
+  ir_context->module()->AddType(MakeUnique<opt::Instruction>(
+      ir_context, SpvOpTypeMatrix, 0, message_.fresh_id(), in_operands));
+  fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
   // We have added an instruction to the module, so need to be careful about the
   // validity of existing analyses.
-  context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(
+      opt::IRContext::Analysis::kAnalysisNone);
 }
 
 protobufs::Transformation TransformationAddTypeMatrix::ToMessage() const {
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_type_matrix.h b/third_party/spirv-tools/src/source/fuzz/transformation_add_type_matrix.h
index 69d6389..6d0724e 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_add_type_matrix.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_type_matrix.h
@@ -15,9 +15,9 @@
 #ifndef SOURCE_FUZZ_TRANSFORMATION_ADD_TYPE_MATRIX_H_
 #define SOURCE_FUZZ_TRANSFORMATION_ADD_TYPE_MATRIX_H_
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -33,13 +33,15 @@
 
   // - |message_.fresh_id| must be a fresh id
   // - |message_.column_type_id| must be the id of a floating-point vector type
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // Adds an OpTypeMatrix instruction to the module, with column type
   // |message_.column_type_id| and |message_.column_count| columns, with result
   // id |message_.fresh_id|.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_type_pointer.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_add_type_pointer.cpp
index 426985a..6cc8171 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_add_type_pointer.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_type_pointer.cpp
@@ -31,28 +31,29 @@
 }
 
 bool TransformationAddTypePointer::IsApplicable(
-    opt::IRContext* context,
-    const spvtools::fuzz::FactManager& /*unused*/) const {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
   // The id must be fresh.
-  if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
+  if (!fuzzerutil::IsFreshId(ir_context, message_.fresh_id())) {
     return false;
   }
   // The base type must be known.
-  return context->get_type_mgr()->GetType(message_.base_type_id()) != nullptr;
+  return ir_context->get_type_mgr()->GetType(message_.base_type_id()) !=
+         nullptr;
 }
 
 void TransformationAddTypePointer::Apply(
-    opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/) const {
+    opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
   // Add the pointer type.
   opt::Instruction::OperandList in_operands = {
       {SPV_OPERAND_TYPE_STORAGE_CLASS, {message_.storage_class()}},
       {SPV_OPERAND_TYPE_ID, {message_.base_type_id()}}};
-  context->module()->AddType(MakeUnique<opt::Instruction>(
-      context, SpvOpTypePointer, 0, message_.fresh_id(), in_operands));
-  fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
+  ir_context->module()->AddType(MakeUnique<opt::Instruction>(
+      ir_context, SpvOpTypePointer, 0, message_.fresh_id(), in_operands));
+  fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
   // We have added an instruction to the module, so need to be careful about the
   // validity of existing analyses.
-  context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(
+      opt::IRContext::Analysis::kAnalysisNone);
 }
 
 protobufs::Transformation TransformationAddTypePointer::ToMessage() const {
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_type_pointer.h b/third_party/spirv-tools/src/source/fuzz/transformation_add_type_pointer.h
index 2b9ff77..3b50a29 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_add_type_pointer.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_type_pointer.h
@@ -15,9 +15,9 @@
 #ifndef SOURCE_FUZZ_TRANSFORMATION_ADD_TYPE_POINTER_H_
 #define SOURCE_FUZZ_TRANSFORMATION_ADD_TYPE_POINTER_H_
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -34,12 +34,14 @@
   // - |message_.fresh_id| must not be used by the module
   // - |message_.base_type_id| must be the result id of an OpType[...]
   // instruction
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // Adds an OpTypePointer instruction with the given storage class and base
   // type to the module.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_type_struct.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_add_type_struct.cpp
index 1ae8372..6ce5ea1 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_add_type_struct.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_type_struct.cpp
@@ -32,14 +32,13 @@
 }
 
 bool TransformationAddTypeStruct::IsApplicable(
-    opt::IRContext* context,
-    const spvtools::fuzz::FactManager& /*unused*/) const {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
   // A fresh id is required.
-  if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
+  if (!fuzzerutil::IsFreshId(ir_context, message_.fresh_id())) {
     return false;
   }
   for (auto member_type : message_.member_type_id()) {
-    auto type = context->get_type_mgr()->GetType(member_type);
+    auto type = ir_context->get_type_mgr()->GetType(member_type);
     if (!type || type->AsFunction()) {
       // The member type id either does not refer to a type, or refers to a
       // function type; both are illegal.
@@ -50,17 +49,18 @@
 }
 
 void TransformationAddTypeStruct::Apply(
-    opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/) const {
+    opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
   opt::Instruction::OperandList in_operands;
   for (auto member_type : message_.member_type_id()) {
     in_operands.push_back({SPV_OPERAND_TYPE_ID, {member_type}});
   }
-  context->module()->AddType(MakeUnique<opt::Instruction>(
-      context, SpvOpTypeStruct, 0, message_.fresh_id(), in_operands));
-  fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
+  ir_context->module()->AddType(MakeUnique<opt::Instruction>(
+      ir_context, SpvOpTypeStruct, 0, message_.fresh_id(), in_operands));
+  fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
   // We have added an instruction to the module, so need to be careful about the
   // validity of existing analyses.
-  context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(
+      opt::IRContext::Analysis::kAnalysisNone);
 }
 
 protobufs::Transformation TransformationAddTypeStruct::ToMessage() const {
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_type_struct.h b/third_party/spirv-tools/src/source/fuzz/transformation_add_type_struct.h
index edf3ec6..86a532d 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_add_type_struct.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_type_struct.h
@@ -17,9 +17,9 @@
 
 #include <vector>
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -35,12 +35,14 @@
 
   // - |message_.fresh_id| must be a fresh id
   // - |message_.member_type_id| must be a sequence of non-function type ids
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // Adds an OpTypeStruct instruction whose field types are given by
   // |message_.member_type_id|, with result id |message_.fresh_id|.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_type_vector.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_add_type_vector.cpp
index 3fdf50b..f7b2fb5 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_add_type_vector.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_type_vector.cpp
@@ -31,13 +31,12 @@
 }
 
 bool TransformationAddTypeVector::IsApplicable(
-    opt::IRContext* context,
-    const spvtools::fuzz::FactManager& /*unused*/) const {
-  if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
+  if (!fuzzerutil::IsFreshId(ir_context, message_.fresh_id())) {
     return false;
   }
   auto component_type =
-      context->get_type_mgr()->GetType(message_.component_type_id());
+      ir_context->get_type_mgr()->GetType(message_.component_type_id());
   if (!component_type) {
     return false;
   }
@@ -46,17 +45,18 @@
 }
 
 void TransformationAddTypeVector::Apply(
-    opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/) const {
+    opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
   opt::Instruction::OperandList in_operands;
   in_operands.push_back({SPV_OPERAND_TYPE_ID, {message_.component_type_id()}});
   in_operands.push_back(
       {SPV_OPERAND_TYPE_LITERAL_INTEGER, {message_.component_count()}});
-  context->module()->AddType(MakeUnique<opt::Instruction>(
-      context, SpvOpTypeVector, 0, message_.fresh_id(), in_operands));
-  fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
+  ir_context->module()->AddType(MakeUnique<opt::Instruction>(
+      ir_context, SpvOpTypeVector, 0, message_.fresh_id(), in_operands));
+  fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
   // We have added an instruction to the module, so need to be careful about the
   // validity of existing analyses.
-  context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(
+      opt::IRContext::Analysis::kAnalysisNone);
 }
 
 protobufs::Transformation TransformationAddTypeVector::ToMessage() const {
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_add_type_vector.h b/third_party/spirv-tools/src/source/fuzz/transformation_add_type_vector.h
index af840f5..240f7cc 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_add_type_vector.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_add_type_vector.h
@@ -15,9 +15,9 @@
 #ifndef SOURCE_FUZZ_TRANSFORMATION_ADD_TYPE_VECTOR_H_
 #define SOURCE_FUZZ_TRANSFORMATION_ADD_TYPE_VECTOR_H_
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -33,13 +33,15 @@
 
   // - |message_.fresh_id| must be a fresh id
   // - |message_.component_type_id| must be the id of a scalar type
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // Adds an OpTypeVector instruction to the module, with component type
   // |message_.component_type_id| and |message_.component_count| components,
   // with result id |message_.fresh_id|.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_composite_construct.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_composite_construct.cpp
index 9c63c1d..cd4f22f 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_composite_construct.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_composite_construct.cpp
@@ -40,14 +40,14 @@
 }
 
 bool TransformationCompositeConstruct::IsApplicable(
-    opt::IRContext* context, const FactManager& /*fact_manager*/) const {
-  if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
+  if (!fuzzerutil::IsFreshId(ir_context, message_.fresh_id())) {
     // We require the id for the composite constructor to be unused.
     return false;
   }
 
   auto insert_before =
-      FindInstruction(message_.instruction_to_insert_before(), context);
+      FindInstruction(message_.instruction_to_insert_before(), ir_context);
   if (!insert_before) {
     // The instruction before which the composite should be inserted was not
     // found.
@@ -55,7 +55,7 @@
   }
 
   auto composite_type =
-      context->get_type_mgr()->GetType(message_.composite_type_id());
+      ir_context->get_type_mgr()->GetType(message_.composite_type_id());
 
   if (!fuzzerutil::IsCompositeType(composite_type)) {
     // The type must actually be a composite.
@@ -64,27 +64,31 @@
 
   // If the type is an array, matrix, struct or vector, the components need to
   // be suitable for constructing something of that type.
-  if (composite_type->AsArray() && !ComponentsForArrayConstructionAreOK(
-                                       context, *composite_type->AsArray())) {
+  if (composite_type->AsArray() &&
+      !ComponentsForArrayConstructionAreOK(ir_context,
+                                           *composite_type->AsArray())) {
     return false;
   }
-  if (composite_type->AsMatrix() && !ComponentsForMatrixConstructionAreOK(
-                                        context, *composite_type->AsMatrix())) {
+  if (composite_type->AsMatrix() &&
+      !ComponentsForMatrixConstructionAreOK(ir_context,
+                                            *composite_type->AsMatrix())) {
     return false;
   }
-  if (composite_type->AsStruct() && !ComponentsForStructConstructionAreOK(
-                                        context, *composite_type->AsStruct())) {
+  if (composite_type->AsStruct() &&
+      !ComponentsForStructConstructionAreOK(ir_context,
+                                            *composite_type->AsStruct())) {
     return false;
   }
-  if (composite_type->AsVector() && !ComponentsForVectorConstructionAreOK(
-                                        context, *composite_type->AsVector())) {
+  if (composite_type->AsVector() &&
+      !ComponentsForVectorConstructionAreOK(ir_context,
+                                            *composite_type->AsVector())) {
     return false;
   }
 
   // Now check whether every component being used to initialize the composite is
   // available at the desired program point.
   for (auto& component : message_.component()) {
-    if (!fuzzerutil::IdIsAvailableBeforeInstruction(context, insert_before,
+    if (!fuzzerutil::IdIsAvailableBeforeInstruction(ir_context, insert_before,
                                                     component)) {
       return false;
     }
@@ -93,13 +97,14 @@
   return true;
 }
 
-void TransformationCompositeConstruct::Apply(opt::IRContext* context,
-                                             FactManager* fact_manager) const {
+void TransformationCompositeConstruct::Apply(
+    opt::IRContext* ir_context,
+    TransformationContext* transformation_context) const {
   // Use the base and offset information from the transformation to determine
   // where in the module a new instruction should be inserted.
   auto insert_before_inst =
-      FindInstruction(message_.instruction_to_insert_before(), context);
-  auto destination_block = context->get_instr_block(insert_before_inst);
+      FindInstruction(message_.instruction_to_insert_before(), ir_context);
+  auto destination_block = ir_context->get_instr_block(insert_before_inst);
   auto insert_before = fuzzerutil::GetIteratorForInstruction(
       destination_block, insert_before_inst);
 
@@ -111,22 +116,22 @@
 
   // Insert an OpCompositeConstruct instruction.
   insert_before.InsertBefore(MakeUnique<opt::Instruction>(
-      context, SpvOpCompositeConstruct, message_.composite_type_id(),
+      ir_context, SpvOpCompositeConstruct, message_.composite_type_id(),
       message_.fresh_id(), in_operands));
 
-  fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
-  context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
+  fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
+  ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
 
   // Inform the fact manager that we now have new synonyms: every component of
   // the composite is synonymous with the id used to construct that component,
   // except in the case of a vector where a single vector id can span multiple
   // components.
   auto composite_type =
-      context->get_type_mgr()->GetType(message_.composite_type_id());
+      ir_context->get_type_mgr()->GetType(message_.composite_type_id());
   uint32_t index = 0;
   for (auto component : message_.component()) {
-    auto component_type = context->get_type_mgr()->GetType(
-        context->get_def_use_mgr()->GetDef(component)->type_id());
+    auto component_type = ir_context->get_type_mgr()->GetType(
+        ir_context->get_def_use_mgr()->GetDef(component)->type_id());
     if (composite_type->AsVector() && component_type->AsVector()) {
       // The case where the composite being constructed is a vector and the
       // component provided for construction is also a vector is special.  It
@@ -139,24 +144,24 @@
       for (uint32_t subvector_index = 0;
            subvector_index < component_type->AsVector()->element_count();
            subvector_index++) {
-        fact_manager->AddFactDataSynonym(
+        transformation_context->GetFactManager()->AddFactDataSynonym(
             MakeDataDescriptor(component, {subvector_index}),
-            MakeDataDescriptor(message_.fresh_id(), {index}), context);
+            MakeDataDescriptor(message_.fresh_id(), {index}), ir_context);
         index++;
       }
     } else {
       // The other cases are simple: the component is made directly synonymous
       // with the element of the composite being constructed.
-      fact_manager->AddFactDataSynonym(
+      transformation_context->GetFactManager()->AddFactDataSynonym(
           MakeDataDescriptor(component, {}),
-          MakeDataDescriptor(message_.fresh_id(), {index}), context);
+          MakeDataDescriptor(message_.fresh_id(), {index}), ir_context);
       index++;
     }
   }
 }
 
 bool TransformationCompositeConstruct::ComponentsForArrayConstructionAreOK(
-    opt::IRContext* context, const opt::analysis::Array& array_type) const {
+    opt::IRContext* ir_context, const opt::analysis::Array& array_type) const {
   if (array_type.length_info().words[0] !=
       opt::analysis::Array::LengthInfo::kConstant) {
     // We only handle constant-sized arrays.
@@ -176,13 +181,13 @@
   // Check that each component is the result id of an instruction whose type is
   // the array's element type.
   for (auto component_id : message_.component()) {
-    auto inst = context->get_def_use_mgr()->GetDef(component_id);
+    auto inst = ir_context->get_def_use_mgr()->GetDef(component_id);
     if (inst == nullptr || !inst->type_id()) {
       // The component does not correspond to an instruction with a result
       // type.
       return false;
     }
-    auto component_type = context->get_type_mgr()->GetType(inst->type_id());
+    auto component_type = ir_context->get_type_mgr()->GetType(inst->type_id());
     assert(component_type);
     if (component_type != array_type.element_type()) {
       // The component's type does not match the array's element type.
@@ -193,7 +198,8 @@
 }
 
 bool TransformationCompositeConstruct::ComponentsForMatrixConstructionAreOK(
-    opt::IRContext* context, const opt::analysis::Matrix& matrix_type) const {
+    opt::IRContext* ir_context,
+    const opt::analysis::Matrix& matrix_type) const {
   if (static_cast<uint32_t>(message_.component().size()) !=
       matrix_type.element_count()) {
     // The number of components must match the number of columns of the matrix.
@@ -202,13 +208,13 @@
   // Check that each component is the result id of an instruction whose type is
   // the matrix's column type.
   for (auto component_id : message_.component()) {
-    auto inst = context->get_def_use_mgr()->GetDef(component_id);
+    auto inst = ir_context->get_def_use_mgr()->GetDef(component_id);
     if (inst == nullptr || !inst->type_id()) {
       // The component does not correspond to an instruction with a result
       // type.
       return false;
     }
-    auto component_type = context->get_type_mgr()->GetType(inst->type_id());
+    auto component_type = ir_context->get_type_mgr()->GetType(inst->type_id());
     assert(component_type);
     if (component_type != matrix_type.element_type()) {
       // The component's type does not match the matrix's column type.
@@ -219,7 +225,8 @@
 }
 
 bool TransformationCompositeConstruct::ComponentsForStructConstructionAreOK(
-    opt::IRContext* context, const opt::analysis::Struct& struct_type) const {
+    opt::IRContext* ir_context,
+    const opt::analysis::Struct& struct_type) const {
   if (static_cast<uint32_t>(message_.component().size()) !=
       struct_type.element_types().size()) {
     // The number of components must match the number of fields of the struct.
@@ -229,14 +236,14 @@
   // matches the associated field type.
   for (uint32_t field_index = 0;
        field_index < struct_type.element_types().size(); field_index++) {
-    auto inst =
-        context->get_def_use_mgr()->GetDef(message_.component()[field_index]);
+    auto inst = ir_context->get_def_use_mgr()->GetDef(
+        message_.component()[field_index]);
     if (inst == nullptr || !inst->type_id()) {
       // The component does not correspond to an instruction with a result
       // type.
       return false;
     }
-    auto component_type = context->get_type_mgr()->GetType(inst->type_id());
+    auto component_type = ir_context->get_type_mgr()->GetType(inst->type_id());
     assert(component_type);
     if (component_type != struct_type.element_types()[field_index]) {
       // The component's type does not match the corresponding field type.
@@ -247,17 +254,18 @@
 }
 
 bool TransformationCompositeConstruct::ComponentsForVectorConstructionAreOK(
-    opt::IRContext* context, const opt::analysis::Vector& vector_type) const {
+    opt::IRContext* ir_context,
+    const opt::analysis::Vector& vector_type) const {
   uint32_t base_element_count = 0;
   auto element_type = vector_type.element_type();
   for (auto& component_id : message_.component()) {
-    auto inst = context->get_def_use_mgr()->GetDef(component_id);
+    auto inst = ir_context->get_def_use_mgr()->GetDef(component_id);
     if (inst == nullptr || !inst->type_id()) {
       // The component does not correspond to an instruction with a result
       // type.
       return false;
     }
-    auto component_type = context->get_type_mgr()->GetType(inst->type_id());
+    auto component_type = ir_context->get_type_mgr()->GetType(inst->type_id());
     assert(component_type);
     if (component_type == element_type) {
       base_element_count++;
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_composite_construct.h b/third_party/spirv-tools/src/source/fuzz/transformation_composite_construct.h
index 5369c4c..2e55e70 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_composite_construct.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_composite_construct.h
@@ -15,9 +15,9 @@
 #ifndef SOURCE_FUZZ_TRANSFORMATION_COMPOSITE_CONSTRUCT_H_
 #define SOURCE_FUZZ_TRANSFORMATION_COMPOSITE_CONSTRUCT_H_
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -49,15 +49,17 @@
   //   before 'inst'.
   // - Each element of |message_.component| must be available directly before
   //   'inst'.
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // Inserts a new OpCompositeConstruct instruction, with id
   // |message_.fresh_id|, directly before the instruction identified by
   // |message_.base_instruction_id| and |message_.offset|.  The instruction
   // creates a composite of type |message_.composite_type_id| using the ids of
   // |message_.component|.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
@@ -65,19 +67,22 @@
   // Helper to decide whether the components of the transformation are suitable
   // for constructing an array of the given type.
   bool ComponentsForArrayConstructionAreOK(
-      opt::IRContext* context, const opt::analysis::Array& array_type) const;
+      opt::IRContext* ir_context, const opt::analysis::Array& array_type) const;
 
   // Similar, but for matrices.
   bool ComponentsForMatrixConstructionAreOK(
-      opt::IRContext* context, const opt::analysis::Matrix& matrix_type) const;
+      opt::IRContext* ir_context,
+      const opt::analysis::Matrix& matrix_type) const;
 
   // Similar, but for structs.
   bool ComponentsForStructConstructionAreOK(
-      opt::IRContext* context, const opt::analysis::Struct& struct_type) const;
+      opt::IRContext* ir_context,
+      const opt::analysis::Struct& struct_type) const;
 
   // Similar, but for vectors.
   bool ComponentsForVectorConstructionAreOK(
-      opt::IRContext* context, const opt::analysis::Vector& vector_type) const;
+      opt::IRContext* ir_context,
+      const opt::analysis::Vector& vector_type) const;
 
   protobufs::TransformationCompositeConstruct message_;
 };
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_composite_extract.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_composite_extract.cpp
index 5d3a386..3dc3953 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_composite_extract.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_composite_extract.cpp
@@ -40,24 +40,23 @@
 }
 
 bool TransformationCompositeExtract::IsApplicable(
-    opt::IRContext* context,
-    const spvtools::fuzz::FactManager& /*unused*/) const {
-  if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
+  if (!fuzzerutil::IsFreshId(ir_context, message_.fresh_id())) {
     return false;
   }
   auto instruction_to_insert_before =
-      FindInstruction(message_.instruction_to_insert_before(), context);
+      FindInstruction(message_.instruction_to_insert_before(), ir_context);
   if (!instruction_to_insert_before) {
     return false;
   }
   auto composite_instruction =
-      context->get_def_use_mgr()->GetDef(message_.composite_id());
+      ir_context->get_def_use_mgr()->GetDef(message_.composite_id());
   if (!composite_instruction) {
     return false;
   }
-  if (auto block = context->get_instr_block(composite_instruction)) {
+  if (auto block = ir_context->get_instr_block(composite_instruction)) {
     if (composite_instruction == instruction_to_insert_before ||
-        !context->GetDominatorAnalysis(block->GetParent())
+        !ir_context->GetDominatorAnalysis(block->GetParent())
              ->Dominates(composite_instruction, instruction_to_insert_before)) {
       return false;
     }
@@ -66,7 +65,7 @@
          "An instruction in a block cannot have a result id but no type id.");
 
   auto composite_type =
-      context->get_type_mgr()->GetType(composite_instruction->type_id());
+      ir_context->get_type_mgr()->GetType(composite_instruction->type_id());
   if (!composite_type) {
     return false;
   }
@@ -76,30 +75,33 @@
     return false;
   }
 
-  return fuzzerutil::WalkCompositeTypeIndices(
-             context, composite_instruction->type_id(), message_.index()) != 0;
+  return fuzzerutil::WalkCompositeTypeIndices(ir_context,
+                                              composite_instruction->type_id(),
+                                              message_.index()) != 0;
 }
 
 void TransformationCompositeExtract::Apply(
-    opt::IRContext* context, spvtools::fuzz::FactManager* fact_manager) const {
+    opt::IRContext* ir_context,
+    TransformationContext* transformation_context) const {
   opt::Instruction::OperandList extract_operands;
   extract_operands.push_back({SPV_OPERAND_TYPE_ID, {message_.composite_id()}});
   for (auto an_index : message_.index()) {
     extract_operands.push_back({SPV_OPERAND_TYPE_LITERAL_INTEGER, {an_index}});
   }
   auto composite_instruction =
-      context->get_def_use_mgr()->GetDef(message_.composite_id());
+      ir_context->get_def_use_mgr()->GetDef(message_.composite_id());
   auto extracted_type = fuzzerutil::WalkCompositeTypeIndices(
-      context, composite_instruction->type_id(), message_.index());
+      ir_context, composite_instruction->type_id(), message_.index());
 
-  FindInstruction(message_.instruction_to_insert_before(), context)
+  FindInstruction(message_.instruction_to_insert_before(), ir_context)
       ->InsertBefore(MakeUnique<opt::Instruction>(
-          context, SpvOpCompositeExtract, extracted_type, message_.fresh_id(),
-          extract_operands));
+          ir_context, SpvOpCompositeExtract, extracted_type,
+          message_.fresh_id(), extract_operands));
 
-  fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
+  fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
 
-  context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(
+      opt::IRContext::Analysis::kAnalysisNone);
 
   // Add the fact that the id storing the extracted element is synonymous with
   // the index into the structure.
@@ -111,8 +113,9 @@
       MakeDataDescriptor(message_.composite_id(), std::move(indices));
   protobufs::DataDescriptor data_descriptor_for_result_id =
       MakeDataDescriptor(message_.fresh_id(), {});
-  fact_manager->AddFactDataSynonym(data_descriptor_for_extracted_element,
-                                   data_descriptor_for_result_id, context);
+  transformation_context->GetFactManager()->AddFactDataSynonym(
+      data_descriptor_for_extracted_element, data_descriptor_for_result_id,
+      ir_context);
 }
 
 protobufs::Transformation TransformationCompositeExtract::ToMessage() const {
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_composite_extract.h b/third_party/spirv-tools/src/source/fuzz/transformation_composite_extract.h
index c4c9278..8f52d22 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_composite_extract.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_composite_extract.h
@@ -15,9 +15,9 @@
 #ifndef SOURCE_FUZZ_TRANSFORMATION_COMPOSITE_EXTRACT_H_
 #define SOURCE_FUZZ_TRANSFORMATION_COMPOSITE_EXTRACT_H_
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -41,15 +41,17 @@
   // - |message_.index| must be a suitable set of indices for
   //   |message_.composite_id|, i.e. it must be possible to follow this chain
   //   of indices to reach a sub-object of |message_.composite_id|
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // Adds an OpCompositeConstruct instruction before the instruction identified
   // by |message_.instruction_to_insert_before|, that extracts from
   // |message_.composite_id| via indices |message_.index| into
   // |message_.fresh_id|.  Generates a data synonym fact relating
   // |message_.fresh_id| to the extracted element.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_compute_data_synonym_fact_closure.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_compute_data_synonym_fact_closure.cpp
new file mode 100644
index 0000000..ff3ba3c
--- /dev/null
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_compute_data_synonym_fact_closure.cpp
@@ -0,0 +1,52 @@
+// Copyright (c) 2020 Google LLC
+//
+// 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
+//
+//     http://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.
+
+#include "source/fuzz/transformation_compute_data_synonym_fact_closure.h"
+
+namespace spvtools {
+namespace fuzz {
+
+TransformationComputeDataSynonymFactClosure::
+    TransformationComputeDataSynonymFactClosure(
+        const spvtools::fuzz::protobufs::
+            TransformationComputeDataSynonymFactClosure& message)
+    : message_(message) {}
+
+TransformationComputeDataSynonymFactClosure::
+    TransformationComputeDataSynonymFactClosure(
+        uint32_t maximum_equivalence_class_size) {
+  message_.set_maximum_equivalence_class_size(maximum_equivalence_class_size);
+}
+
+bool TransformationComputeDataSynonymFactClosure::IsApplicable(
+    opt::IRContext* /*unused*/, const TransformationContext& /*unused*/) const {
+  return true;
+}
+
+void TransformationComputeDataSynonymFactClosure::Apply(
+    opt::IRContext* ir_context,
+    TransformationContext* transformation_context) const {
+  transformation_context->GetFactManager()->ComputeClosureOfFacts(
+      ir_context, message_.maximum_equivalence_class_size());
+}
+
+protobufs::Transformation
+TransformationComputeDataSynonymFactClosure::ToMessage() const {
+  protobufs::Transformation result;
+  *result.mutable_compute_data_synonym_fact_closure() = message_;
+  return result;
+}
+
+}  // namespace fuzz
+}  // namespace spvtools
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_compute_data_synonym_fact_closure.h b/third_party/spirv-tools/src/source/fuzz/transformation_compute_data_synonym_fact_closure.h
new file mode 100644
index 0000000..eab43ff
--- /dev/null
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_compute_data_synonym_fact_closure.h
@@ -0,0 +1,53 @@
+// Copyright (c) 2020 Google LLC
+//
+// 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
+//
+//     http://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.
+
+#ifndef SOURCE_FUZZ_TRANSFORMATION_COMPUTE_DATA_SYNONYM_FACT_CLOSURE_H_
+#define SOURCE_FUZZ_TRANSFORMATION_COMPUTE_DATA_SYNONYM_FACT_CLOSURE_H_
+
+#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
+#include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
+#include "source/opt/ir_context.h"
+
+namespace spvtools {
+namespace fuzz {
+
+class TransformationComputeDataSynonymFactClosure : public Transformation {
+ public:
+  explicit TransformationComputeDataSynonymFactClosure(
+      const protobufs::TransformationComputeDataSynonymFactClosure& message);
+
+  explicit TransformationComputeDataSynonymFactClosure(
+      uint32_t maximum_equivalence_class_size);
+
+  // This transformation is trivially applicable.
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
+
+  // Forces the fact manager to compute a closure of data synonym facts, so that
+  // facts implied by existing facts are deduced.
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
+
+  protobufs::Transformation ToMessage() const override;
+
+ private:
+  protobufs::TransformationComputeDataSynonymFactClosure message_;
+};
+
+}  // namespace fuzz
+}  // namespace spvtools
+
+#endif  // SOURCE_FUZZ_TRANSFORMATION_COMPUTE_DATA_SYNONYM_FACT_CLOSURE_H_
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_context.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_context.cpp
new file mode 100644
index 0000000..9c8a90f
--- /dev/null
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_context.cpp
@@ -0,0 +1,29 @@
+// Copyright (c) 2020 Google LLC
+//
+// 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
+//
+//     http://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.
+
+#include "source/fuzz/transformation_context.h"
+
+namespace spvtools {
+namespace fuzz {
+
+TransformationContext::TransformationContext(
+    FactManager* transformation_context,
+    spv_validator_options validator_options)
+    : fact_manager_(transformation_context),
+      validator_options_(validator_options) {}
+
+TransformationContext::~TransformationContext() = default;
+
+}  // namespace fuzz
+}  // namespace spvtools
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_context.h b/third_party/spirv-tools/src/source/fuzz/transformation_context.h
new file mode 100644
index 0000000..37e15a2
--- /dev/null
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_context.h
@@ -0,0 +1,56 @@
+// Copyright (c) 2020 Google LLC
+//
+// 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
+//
+//     http://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.
+
+#ifndef SOURCE_FUZZ_TRANSFORMATION_CONTEXT_H_
+#define SOURCE_FUZZ_TRANSFORMATION_CONTEXT_H_
+
+#include "source/fuzz/fact_manager.h"
+#include "spirv-tools/libspirv.hpp"
+
+namespace spvtools {
+namespace fuzz {
+
+// Encapsulates all information that is required to inform how to apply a
+// transformation to a module.
+class TransformationContext {
+ public:
+  // Constructs a transformation context with a given fact manager and validator
+  // options.
+  TransformationContext(FactManager* fact_manager,
+                        spv_validator_options validator_options);
+
+  ~TransformationContext();
+
+  FactManager* GetFactManager() { return fact_manager_; }
+
+  const FactManager* GetFactManager() const { return fact_manager_; }
+
+  spv_validator_options GetValidatorOptions() const {
+    return validator_options_;
+  }
+
+ private:
+  // Manages facts that inform whether transformations can be applied, and that
+  // are produced by applying transformations.
+  FactManager* fact_manager_;
+
+  // Options to control validation when deciding whether transformations can be
+  // applied.
+  spv_validator_options validator_options_;
+};
+
+}  // namespace fuzz
+}  // namespace spvtools
+
+#endif  // SOURCE_FUZZ_TRANSFORMATION_CONTEXT_H_
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_copy_object.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_copy_object.cpp
index bfdced3..7b5b5c9 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_copy_object.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_copy_object.cpp
@@ -38,22 +38,22 @@
 }
 
 bool TransformationCopyObject::IsApplicable(
-    opt::IRContext* context, const FactManager& /*fact_manager*/) const {
-  if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
+  if (!fuzzerutil::IsFreshId(ir_context, message_.fresh_id())) {
     // We require the id for the object copy to be unused.
     return false;
   }
   // The id of the object to be copied must exist
-  auto object_inst = context->get_def_use_mgr()->GetDef(message_.object());
+  auto object_inst = ir_context->get_def_use_mgr()->GetDef(message_.object());
   if (!object_inst) {
     return false;
   }
-  if (!fuzzerutil::CanMakeSynonymOf(context, object_inst)) {
+  if (!fuzzerutil::CanMakeSynonymOf(ir_context, object_inst)) {
     return false;
   }
 
   auto insert_before =
-      FindInstruction(message_.instruction_to_insert_before(), context);
+      FindInstruction(message_.instruction_to_insert_before(), ir_context);
   if (!insert_before) {
     // The instruction before which the copy should be inserted was not found.
     return false;
@@ -66,17 +66,18 @@
 
   // |message_object| must be available directly before the point where we want
   // to add the copy.
-  return fuzzerutil::IdIsAvailableBeforeInstruction(context, insert_before,
+  return fuzzerutil::IdIsAvailableBeforeInstruction(ir_context, insert_before,
                                                     message_.object());
 }
 
-void TransformationCopyObject::Apply(opt::IRContext* context,
-                                     FactManager* fact_manager) const {
-  auto object_inst = context->get_def_use_mgr()->GetDef(message_.object());
+void TransformationCopyObject::Apply(
+    opt::IRContext* ir_context,
+    TransformationContext* transformation_context) const {
+  auto object_inst = ir_context->get_def_use_mgr()->GetDef(message_.object());
   assert(object_inst && "The object to be copied must exist.");
   auto insert_before_inst =
-      FindInstruction(message_.instruction_to_insert_before(), context);
-  auto destination_block = context->get_instr_block(insert_before_inst);
+      FindInstruction(message_.instruction_to_insert_before(), ir_context);
+  auto destination_block = ir_context->get_instr_block(insert_before_inst);
   assert(destination_block && "The base instruction must be in a block.");
   auto insert_before = fuzzerutil::GetIteratorForInstruction(
       destination_block, insert_before_inst);
@@ -86,18 +87,21 @@
   opt::Instruction::OperandList operands = {
       {SPV_OPERAND_TYPE_ID, {message_.object()}}};
   insert_before->InsertBefore(MakeUnique<opt::Instruction>(
-      context, SpvOp::SpvOpCopyObject, object_inst->type_id(),
+      ir_context, SpvOp::SpvOpCopyObject, object_inst->type_id(),
       message_.fresh_id(), operands));
 
-  fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
-  context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
+  fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
+  ir_context->InvalidateAnalysesExceptFor(
+      opt::IRContext::Analysis::kAnalysisNone);
 
-  fact_manager->AddFactDataSynonym(MakeDataDescriptor(message_.object(), {}),
-                                   MakeDataDescriptor(message_.fresh_id(), {}),
-                                   context);
+  transformation_context->GetFactManager()->AddFactDataSynonym(
+      MakeDataDescriptor(message_.object(), {}),
+      MakeDataDescriptor(message_.fresh_id(), {}), ir_context);
 
-  if (fact_manager->PointeeValueIsIrrelevant(message_.object())) {
-    fact_manager->AddFactValueOfPointeeIsIrrelevant(message_.fresh_id());
+  if (transformation_context->GetFactManager()->PointeeValueIsIrrelevant(
+          message_.object())) {
+    transformation_context->GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
+        message_.fresh_id());
   }
 }
 
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_copy_object.h b/third_party/spirv-tools/src/source/fuzz/transformation_copy_object.h
index 9e9c26a..80d57ae 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_copy_object.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_copy_object.h
@@ -15,9 +15,9 @@
 #ifndef SOURCE_FUZZ_TRANSFORMATION_COPY_OBJECT_H_
 #define SOURCE_FUZZ_TRANSFORMATION_COPY_OBJECT_H_
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -49,19 +49,21 @@
   // - |message_.object| must be available directly before 'inst'.
   // - |message_.object| must not be a null pointer or undefined pointer (so as
   //   to make it legal to load from copied pointers).
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // - A new instruction,
   //     %|message_.fresh_id| = OpCopyObject %ty %|message_.object|
   //   is added directly before the instruction at |message_.insert_after_id| +
   //   |message_|.offset, where %ty is the type of |message_.object|.
   // - The fact that |message_.fresh_id| and |message_.object| are synonyms
-  //   is added to |fact_manager|.
+  //   is added to the fact manager in |transformation_context|.
   // - If |message_.object| is a pointer whose pointee value is known to be
-  //   irrelevant, the analogous fact is added to |fact_manager| about
-  //   |message_.fresh_id|.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  //   irrelevant, the analogous fact is added to the fact manager in
+  //   |transformation_context| about |message_.fresh_id|.
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_equation_instruction.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_equation_instruction.cpp
index 21b67f6..5c31417 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_equation_instruction.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_equation_instruction.cpp
@@ -37,40 +37,40 @@
 }
 
 bool TransformationEquationInstruction::IsApplicable(
-    opt::IRContext* context,
-    const spvtools::fuzz::FactManager& /*unused*/) const {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
   // The result id must be fresh.
-  if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
+  if (!fuzzerutil::IsFreshId(ir_context, message_.fresh_id())) {
     return false;
   }
   // The instruction to insert before must exist.
   auto insert_before =
-      FindInstruction(message_.instruction_to_insert_before(), context);
+      FindInstruction(message_.instruction_to_insert_before(), ir_context);
   if (!insert_before) {
     return false;
   }
   // The input ids must all exist, not be OpUndef, and be available before this
   // instruction.
   for (auto id : message_.in_operand_id()) {
-    auto inst = context->get_def_use_mgr()->GetDef(id);
+    auto inst = ir_context->get_def_use_mgr()->GetDef(id);
     if (!inst) {
       return false;
     }
     if (inst->opcode() == SpvOpUndef) {
       return false;
     }
-    if (!fuzzerutil::IdIsAvailableBeforeInstruction(context, insert_before,
+    if (!fuzzerutil::IdIsAvailableBeforeInstruction(ir_context, insert_before,
                                                     id)) {
       return false;
     }
   }
 
-  return MaybeGetResultType(context) != 0;
+  return MaybeGetResultType(ir_context) != 0;
 }
 
 void TransformationEquationInstruction::Apply(
-    opt::IRContext* context, spvtools::fuzz::FactManager* fact_manager) const {
-  fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
+    opt::IRContext* ir_context,
+    TransformationContext* transformation_context) const {
+  fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
 
   opt::Instruction::OperandList in_operands;
   std::vector<uint32_t> rhs_id;
@@ -79,16 +79,16 @@
     rhs_id.push_back(id);
   }
 
-  FindInstruction(message_.instruction_to_insert_before(), context)
+  FindInstruction(message_.instruction_to_insert_before(), ir_context)
       ->InsertBefore(MakeUnique<opt::Instruction>(
-          context, static_cast<SpvOp>(message_.opcode()),
-          MaybeGetResultType(context), message_.fresh_id(), in_operands));
+          ir_context, static_cast<SpvOp>(message_.opcode()),
+          MaybeGetResultType(ir_context), message_.fresh_id(), in_operands));
 
-  context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
 
-  fact_manager->AddFactIdEquation(message_.fresh_id(),
-                                  static_cast<SpvOp>(message_.opcode()), rhs_id,
-                                  context);
+  transformation_context->GetFactManager()->AddFactIdEquation(
+      message_.fresh_id(), static_cast<SpvOp>(message_.opcode()), rhs_id,
+      ir_context);
 }
 
 protobufs::Transformation TransformationEquationInstruction::ToMessage() const {
@@ -98,7 +98,7 @@
 }
 
 uint32_t TransformationEquationInstruction::MaybeGetResultType(
-    opt::IRContext* context) const {
+    opt::IRContext* ir_context) const {
   switch (static_cast<SpvOp>(message_.opcode())) {
     case SpvOpIAdd:
     case SpvOpISub: {
@@ -108,13 +108,13 @@
       uint32_t first_operand_width = 0;
       uint32_t first_operand_type_id = 0;
       for (uint32_t index = 0; index < 2; index++) {
-        auto operand_inst =
-            context->get_def_use_mgr()->GetDef(message_.in_operand_id(index));
+        auto operand_inst = ir_context->get_def_use_mgr()->GetDef(
+            message_.in_operand_id(index));
         if (!operand_inst || !operand_inst->type_id()) {
           return 0;
         }
         auto operand_type =
-            context->get_type_mgr()->GetType(operand_inst->type_id());
+            ir_context->get_type_mgr()->GetType(operand_inst->type_id());
         if (!(operand_type->AsInteger() ||
               (operand_type->AsVector() &&
                operand_type->AsVector()->element_type()->AsInteger()))) {
@@ -144,12 +144,12 @@
         return 0;
       }
       auto operand_inst =
-          context->get_def_use_mgr()->GetDef(message_.in_operand_id(0));
+          ir_context->get_def_use_mgr()->GetDef(message_.in_operand_id(0));
       if (!operand_inst || !operand_inst->type_id()) {
         return 0;
       }
       auto operand_type =
-          context->get_type_mgr()->GetType(operand_inst->type_id());
+          ir_context->get_type_mgr()->GetType(operand_inst->type_id());
       if (!(operand_type->AsBool() ||
             (operand_type->AsVector() &&
              operand_type->AsVector()->element_type()->AsBool()))) {
@@ -162,12 +162,12 @@
         return 0;
       }
       auto operand_inst =
-          context->get_def_use_mgr()->GetDef(message_.in_operand_id(0));
+          ir_context->get_def_use_mgr()->GetDef(message_.in_operand_id(0));
       if (!operand_inst || !operand_inst->type_id()) {
         return 0;
       }
       auto operand_type =
-          context->get_type_mgr()->GetType(operand_inst->type_id());
+          ir_context->get_type_mgr()->GetType(operand_inst->type_id());
       if (!(operand_type->AsInteger() ||
             (operand_type->AsVector() &&
              operand_type->AsVector()->element_type()->AsInteger()))) {
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_equation_instruction.h b/third_party/spirv-tools/src/source/fuzz/transformation_equation_instruction.h
index 2456ba5..7eec9c6 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_equation_instruction.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_equation_instruction.h
@@ -17,9 +17,9 @@
 
 #include <vector>
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -44,8 +44,9 @@
   //   equations, the types of the ids in |message_.in_operand_id| must be
   //   suitable for use with this opcode, and the module must contain an
   //   appropriate result type id.
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // Adds an instruction to the module, right before
   // |message_.instruction_to_insert_before|, of the form:
@@ -56,7 +57,8 @@
   // compatible with the opcode and input operands.
   //
   // The fact manager is also updated to inform it of this equation fact.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
@@ -65,7 +67,7 @@
   // in |message_.in_operand_id| are compatible, and that the module contains
   // an appropriate result type id.  If all is well, the result type id is
   // returned.  Otherwise, 0 is returned.
-  uint32_t MaybeGetResultType(opt::IRContext* context) const;
+  uint32_t MaybeGetResultType(opt::IRContext* ir_context) const;
 
   protobufs::TransformationEquationInstruction message_;
 };
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_function_call.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_function_call.cpp
index cea8537..432634d 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_function_call.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_function_call.cpp
@@ -39,25 +39,26 @@
 }
 
 bool TransformationFunctionCall::IsApplicable(
-    opt::IRContext* context,
-    const spvtools::fuzz::FactManager& fact_manager) const {
+    opt::IRContext* ir_context,
+    const TransformationContext& transformation_context) const {
   // The result id must be fresh
-  if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
+  if (!fuzzerutil::IsFreshId(ir_context, message_.fresh_id())) {
     return false;
   }
 
   // The function must exist
-  auto callee_inst = context->get_def_use_mgr()->GetDef(message_.callee_id());
+  auto callee_inst =
+      ir_context->get_def_use_mgr()->GetDef(message_.callee_id());
   if (!callee_inst || callee_inst->opcode() != SpvOpFunction) {
     return false;
   }
 
   // The function must not be an entry point
-  if (fuzzerutil::FunctionIsEntryPoint(context, message_.callee_id())) {
+  if (fuzzerutil::FunctionIsEntryPoint(ir_context, message_.callee_id())) {
     return false;
   }
 
-  auto callee_type_inst = context->get_def_use_mgr()->GetDef(
+  auto callee_type_inst = ir_context->get_def_use_mgr()->GetDef(
       callee_inst->GetSingleWordInOperand(1));
   assert(callee_type_inst->opcode() == SpvOpTypeFunction &&
          "Bad function type.");
@@ -73,7 +74,7 @@
   // The instruction descriptor must refer to a position where it is valid to
   // insert the call
   auto insert_before =
-      FindInstruction(message_.instruction_to_insert_before(), context);
+      FindInstruction(message_.instruction_to_insert_before(), ir_context);
   if (!insert_before) {
     return false;
   }
@@ -82,13 +83,15 @@
     return false;
   }
 
-  auto block = context->get_instr_block(insert_before);
+  auto block = ir_context->get_instr_block(insert_before);
   auto enclosing_function = block->GetParent();
 
   // If the block is not dead, the function must be livesafe
-  bool block_is_dead = fact_manager.BlockIsDead(block->id());
+  bool block_is_dead =
+      transformation_context.GetFactManager()->BlockIsDead(block->id());
   if (!block_is_dead &&
-      !fact_manager.FunctionIsLivesafe(message_.callee_id())) {
+      !transformation_context.GetFactManager()->FunctionIsLivesafe(
+          message_.callee_id())) {
     return false;
   }
 
@@ -98,7 +101,7 @@
        arg_index < static_cast<uint32_t>(message_.argument_id().size());
        arg_index++) {
     opt::Instruction* arg_inst =
-        context->get_def_use_mgr()->GetDef(message_.argument_id(arg_index));
+        ir_context->get_def_use_mgr()->GetDef(message_.argument_id(arg_index));
     if (!arg_inst) {
       // The given argument does not correspond to an instruction.
       return false;
@@ -112,7 +115,7 @@
       return false;
     }
     opt::Instruction* arg_type_inst =
-        context->get_def_use_mgr()->GetDef(arg_inst->type_id());
+        ir_context->get_def_use_mgr()->GetDef(arg_inst->type_id());
     if (arg_type_inst->opcode() == SpvOpTypePointer) {
       switch (arg_inst->opcode()) {
         case SpvOpFunctionParameter:
@@ -124,7 +127,8 @@
           return false;
       }
       if (!block_is_dead &&
-          !fact_manager.PointeeValueIsIrrelevant(arg_inst->result_id())) {
+          !transformation_context.GetFactManager()->PointeeValueIsIrrelevant(
+              arg_inst->result_id())) {
         // This is not a dead block, so pointer parameters passed to the called
         // function might really have their contents modified. We thus require
         // such pointers to be to arbitrary-valued variables, which this is not.
@@ -134,7 +138,7 @@
 
     // The argument id needs to be available (according to dominance rules) at
     // the point where the call will occur.
-    if (!fuzzerutil::IdIsAvailableBeforeInstruction(context, insert_before,
+    if (!fuzzerutil::IdIsAvailableBeforeInstruction(ir_context, insert_before,
                                                     arg_inst->result_id())) {
       return false;
     }
@@ -146,19 +150,19 @@
     return false;
   }
   // Ensure the call would not lead to indirect recursion.
-  return !CallGraph(context)
+  return !CallGraph(ir_context)
               .GetIndirectCallees(message_.callee_id())
               .count(block->GetParent()->result_id());
 }
 
 void TransformationFunctionCall::Apply(
-    opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/) const {
+    opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
   // Update the module's bound to reflect the fresh id for the result of the
   // function call.
-  fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
+  fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
   // Get the return type of the function being called.
   uint32_t return_type =
-      context->get_def_use_mgr()->GetDef(message_.callee_id())->type_id();
+      ir_context->get_def_use_mgr()->GetDef(message_.callee_id())->type_id();
   // Populate the operands to the call instruction, with the function id and the
   // arguments.
   opt::Instruction::OperandList operands;
@@ -167,12 +171,12 @@
     operands.push_back({SPV_OPERAND_TYPE_ID, {arg}});
   }
   // Insert the function call before the instruction specified in the message.
-  FindInstruction(message_.instruction_to_insert_before(), context)
-      ->InsertBefore(
-          MakeUnique<opt::Instruction>(context, SpvOpFunctionCall, return_type,
-                                       message_.fresh_id(), operands));
+  FindInstruction(message_.instruction_to_insert_before(), ir_context)
+      ->InsertBefore(MakeUnique<opt::Instruction>(
+          ir_context, SpvOpFunctionCall, return_type, message_.fresh_id(),
+          operands));
   // Invalidate all analyses since we have changed the module.
-  context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
 }
 
 protobufs::Transformation TransformationFunctionCall::ToMessage() const {
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_function_call.h b/third_party/spirv-tools/src/source/fuzz/transformation_function_call.h
index a9ae5be..4ad7db1 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_function_call.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_function_call.h
@@ -15,9 +15,9 @@
 #ifndef SOURCE_FUZZ_TRANSFORMATION_FUNCTION_CALL_H_
 #define SOURCE_FUZZ_TRANSFORMATION_FUNCTION_CALL_H_
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -44,14 +44,16 @@
   // - If the insertion point is not in a dead block then |message_function_id|
   //   must refer to a livesafe function, and every pointer argument in
   //   |message_.arg_id| must refer to an arbitrary-valued variable
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // Adds an instruction of the form:
   //   |fresh_id| = OpFunctionCall %type |callee_id| |arg_id...|
   // before |instruction_to_insert_before|, where %type is the return type of
   // |callee_id|.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_load.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_load.cpp
index 4cba37d..a260c33 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_load.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_load.cpp
@@ -34,20 +34,19 @@
 }
 
 bool TransformationLoad::IsApplicable(
-    opt::IRContext* context,
-    const spvtools::fuzz::FactManager& /*unused*/) const {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
   // The result id must be fresh.
-  if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
+  if (!fuzzerutil::IsFreshId(ir_context, message_.fresh_id())) {
     return false;
   }
 
   // The pointer must exist and have a type.
-  auto pointer = context->get_def_use_mgr()->GetDef(message_.pointer_id());
+  auto pointer = ir_context->get_def_use_mgr()->GetDef(message_.pointer_id());
   if (!pointer || !pointer->type_id()) {
     return false;
   }
   // The type must indeed be a pointer type.
-  auto pointer_type = context->get_def_use_mgr()->GetDef(pointer->type_id());
+  auto pointer_type = ir_context->get_def_use_mgr()->GetDef(pointer->type_id());
   assert(pointer_type && "Type id must be defined.");
   if (pointer_type->opcode() != SpvOpTypePointer) {
     return false;
@@ -65,7 +64,7 @@
 
   // Determine which instruction we should be inserting before.
   auto insert_before =
-      FindInstruction(message_.instruction_to_insert_before(), context);
+      FindInstruction(message_.instruction_to_insert_before(), ir_context);
   // It must exist, ...
   if (!insert_before) {
     return false;
@@ -76,21 +75,21 @@
   }
 
   // The pointer needs to be available at the insertion point.
-  return fuzzerutil::IdIsAvailableBeforeInstruction(context, insert_before,
+  return fuzzerutil::IdIsAvailableBeforeInstruction(ir_context, insert_before,
                                                     message_.pointer_id());
 }
 
-void TransformationLoad::Apply(opt::IRContext* context,
-                               spvtools::fuzz::FactManager* /*unused*/) const {
+void TransformationLoad::Apply(opt::IRContext* ir_context,
+                               TransformationContext* /*unused*/) const {
   uint32_t result_type = fuzzerutil::GetPointeeTypeIdFromPointerType(
-      context, fuzzerutil::GetTypeId(context, message_.pointer_id()));
-  fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
-  FindInstruction(message_.instruction_to_insert_before(), context)
+      ir_context, fuzzerutil::GetTypeId(ir_context, message_.pointer_id()));
+  fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
+  FindInstruction(message_.instruction_to_insert_before(), ir_context)
       ->InsertBefore(MakeUnique<opt::Instruction>(
-          context, SpvOpLoad, result_type, message_.fresh_id(),
+          ir_context, SpvOpLoad, result_type, message_.fresh_id(),
           opt::Instruction::OperandList(
               {{SPV_OPERAND_TYPE_ID, {message_.pointer_id()}}})));
-  context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
 }
 
 protobufs::Transformation TransformationLoad::ToMessage() const {
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_load.h b/third_party/spirv-tools/src/source/fuzz/transformation_load.h
index ff99016..4c7c00b 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_load.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_load.h
@@ -15,9 +15,9 @@
 #ifndef SOURCE_FUZZ_TRANSFORMATION_LOAD_H_
 #define SOURCE_FUZZ_TRANSFORMATION_LOAD_H_
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -37,15 +37,17 @@
   // - |message_.instruction_to_insert_before| must identify an instruction
   //   before which it is valid to insert an OpLoad, and where
   //   |message_.pointer_id| is available (according to dominance rules)
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // Adds an instruction of the form:
   //   |message_.fresh_id| = OpLoad %type |message_.pointer_id|
   // before the instruction identified by
   // |message_.instruction_to_insert_before|, where %type is the pointer's
   // pointee type.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_merge_blocks.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_merge_blocks.cpp
index 316e80d..68ac092 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_merge_blocks.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_merge_blocks.cpp
@@ -29,40 +29,41 @@
 }
 
 bool TransformationMergeBlocks::IsApplicable(
-    opt::IRContext* context,
-    const spvtools::fuzz::FactManager& /*unused*/) const {
-  auto second_block = fuzzerutil::MaybeFindBlock(context, message_.block_id());
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
+  auto second_block =
+      fuzzerutil::MaybeFindBlock(ir_context, message_.block_id());
   // The given block must exist.
   if (!second_block) {
     return false;
   }
   // The block must have just one predecessor.
-  auto predecessors = context->cfg()->preds(second_block->id());
+  auto predecessors = ir_context->cfg()->preds(second_block->id());
   if (predecessors.size() != 1) {
     return false;
   }
-  auto first_block = context->cfg()->block(predecessors.at(0));
+  auto first_block = ir_context->cfg()->block(predecessors.at(0));
 
-  return opt::blockmergeutil::CanMergeWithSuccessor(context, first_block);
+  return opt::blockmergeutil::CanMergeWithSuccessor(ir_context, first_block);
 }
 
-void TransformationMergeBlocks::Apply(
-    opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/) const {
-  auto second_block = fuzzerutil::MaybeFindBlock(context, message_.block_id());
-  auto first_block =
-      context->cfg()->block(context->cfg()->preds(second_block->id()).at(0));
+void TransformationMergeBlocks::Apply(opt::IRContext* ir_context,
+                                      TransformationContext* /*unused*/) const {
+  auto second_block =
+      fuzzerutil::MaybeFindBlock(ir_context, message_.block_id());
+  auto first_block = ir_context->cfg()->block(
+      ir_context->cfg()->preds(second_block->id()).at(0));
 
   auto function = first_block->GetParent();
   // We need an iterator pointing to the predecessor, hence the loop.
   for (auto bi = function->begin(); bi != function->end(); ++bi) {
     if (bi->id() == first_block->id()) {
-      assert(opt::blockmergeutil::CanMergeWithSuccessor(context, &*bi) &&
+      assert(opt::blockmergeutil::CanMergeWithSuccessor(ir_context, &*bi) &&
              "Because 'Apply' should only be invoked if 'IsApplicable' holds, "
              "it must be possible to merge |bi| with its successor.");
-      opt::blockmergeutil::MergeWithSuccessor(context, function, bi);
+      opt::blockmergeutil::MergeWithSuccessor(ir_context, function, bi);
       // Invalidate all analyses, since we have changed the module
       // significantly.
-      context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
+      ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
       return;
     }
   }
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_merge_blocks.h b/third_party/spirv-tools/src/source/fuzz/transformation_merge_blocks.h
index 86216db..1dc16d2 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_merge_blocks.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_merge_blocks.h
@@ -15,9 +15,9 @@
 #ifndef SOURCE_FUZZ_TRANSFORMATION_MERGE_BLOCKS_H_
 #define SOURCE_FUZZ_TRANSFORMATION_MERGE_BLOCKS_H_
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -35,12 +35,14 @@
   // - b must be the sole successor of a
   // - Replacing a with the merge of a and b (and removing b) must lead to a
   //   valid module
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // The contents of b are merged into a, and a's terminator is replaced with
   // the terminator of b.  Block b is removed from the module.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_move_block_down.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_move_block_down.cpp
index f181855..6c71ab7 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_move_block_down.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_move_block_down.cpp
@@ -28,10 +28,10 @@
 }
 
 bool TransformationMoveBlockDown::IsApplicable(
-    opt::IRContext* context, const FactManager& /*unused*/) const {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
   // Go through every block in every function, looking for a block whose id
   // matches that of the block we want to consider moving down.
-  for (auto& function : *context->module()) {
+  for (auto& function : *ir_context->module()) {
     for (auto block_it = function.begin(); block_it != function.end();
          ++block_it) {
       if (block_it->id() == message_.block_id()) {
@@ -43,7 +43,7 @@
         }
         // Record the block we would like to consider moving down.
         opt::BasicBlock* block_matching_id = &*block_it;
-        if (!context->GetDominatorAnalysis(&function)->IsReachable(
+        if (!ir_context->GetDominatorAnalysis(&function)->IsReachable(
                 block_matching_id)) {
           // The block is not reachable.  We are not allowed to move it down.
           return false;
@@ -60,7 +60,7 @@
         opt::BasicBlock* next_block_in_program_order = &*block_it;
         // We can move the block of interest down if and only if it does not
         // dominate the block that comes next.
-        return !context->GetDominatorAnalysis(&function)->Dominates(
+        return !ir_context->GetDominatorAnalysis(&function)->Dominates(
             block_matching_id, next_block_in_program_order);
       }
     }
@@ -71,11 +71,11 @@
   return false;
 }
 
-void TransformationMoveBlockDown::Apply(opt::IRContext* context,
-                                        FactManager* /*unused*/) const {
+void TransformationMoveBlockDown::Apply(
+    opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
   // Go through every block in every function, looking for a block whose id
   // matches that of the block we want to move down.
-  for (auto& function : *context->module()) {
+  for (auto& function : *ir_context->module()) {
     for (auto block_it = function.begin(); block_it != function.end();
          ++block_it) {
       if (block_it->id() == message_.block_id()) {
@@ -87,7 +87,7 @@
         // For performance, it is vital to keep the dominator analysis valid
         // (which due to https://github.com/KhronosGroup/SPIRV-Tools/issues/2889
         // requires keeping the CFG analysis valid).
-        context->InvalidateAnalysesExceptFor(
+        ir_context->InvalidateAnalysesExceptFor(
             opt::IRContext::Analysis::kAnalysisDefUse |
             opt::IRContext::Analysis::kAnalysisCFG |
             opt::IRContext::Analysis::kAnalysisDominatorAnalysis);
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_move_block_down.h b/third_party/spirv-tools/src/source/fuzz/transformation_move_block_down.h
index fd1584a..7551c38 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_move_block_down.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_move_block_down.h
@@ -15,9 +15,9 @@
 #ifndef SOURCE_FUZZ_TRANSFORMATION_MOVE_BLOCK_DOWN_H_
 #define SOURCE_FUZZ_TRANSFORMATION_MOVE_BLOCK_DOWN_H_
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -35,12 +35,14 @@
   //   in a function.
   // - b must not dominate the block that follows it in program order.
   // - b must be reachable.
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // The block with id |message_.block_id| is moved down; i.e. the program order
   // between it and the block that follows it is swapped.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_outline_function.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_outline_function.cpp
index 01d1c45..d84545a 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_outline_function.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_outline_function.cpp
@@ -70,72 +70,71 @@
 }
 
 bool TransformationOutlineFunction::IsApplicable(
-    opt::IRContext* context,
-    const spvtools::fuzz::FactManager& /*unused*/) const {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
   std::set<uint32_t> ids_used_by_this_transformation;
 
   // The various new ids used by the transformation must be fresh and distinct.
 
   if (!CheckIdIsFreshAndNotUsedByThisTransformation(
-          message_.new_function_struct_return_type_id(), context,
+          message_.new_function_struct_return_type_id(), ir_context,
           &ids_used_by_this_transformation)) {
     return false;
   }
 
   if (!CheckIdIsFreshAndNotUsedByThisTransformation(
-          message_.new_function_type_id(), context,
+          message_.new_function_type_id(), ir_context,
           &ids_used_by_this_transformation)) {
     return false;
   }
 
   if (!CheckIdIsFreshAndNotUsedByThisTransformation(
-          message_.new_function_id(), context,
+          message_.new_function_id(), ir_context,
           &ids_used_by_this_transformation)) {
     return false;
   }
 
   if (!CheckIdIsFreshAndNotUsedByThisTransformation(
-          message_.new_function_region_entry_block(), context,
+          message_.new_function_region_entry_block(), ir_context,
           &ids_used_by_this_transformation)) {
     return false;
   }
 
   if (!CheckIdIsFreshAndNotUsedByThisTransformation(
-          message_.new_caller_result_id(), context,
+          message_.new_caller_result_id(), ir_context,
           &ids_used_by_this_transformation)) {
     return false;
   }
 
   if (!CheckIdIsFreshAndNotUsedByThisTransformation(
-          message_.new_callee_result_id(), context,
+          message_.new_callee_result_id(), ir_context,
           &ids_used_by_this_transformation)) {
     return false;
   }
 
   for (auto& pair : message_.input_id_to_fresh_id()) {
     if (!CheckIdIsFreshAndNotUsedByThisTransformation(
-            pair.second(), context, &ids_used_by_this_transformation)) {
+            pair.second(), ir_context, &ids_used_by_this_transformation)) {
       return false;
     }
   }
 
   for (auto& pair : message_.output_id_to_fresh_id()) {
     if (!CheckIdIsFreshAndNotUsedByThisTransformation(
-            pair.second(), context, &ids_used_by_this_transformation)) {
+            pair.second(), ir_context, &ids_used_by_this_transformation)) {
       return false;
     }
   }
 
   // The entry and exit block ids must indeed refer to blocks.
   for (auto block_id : {message_.entry_block(), message_.exit_block()}) {
-    auto block_label = context->get_def_use_mgr()->GetDef(block_id);
+    auto block_label = ir_context->get_def_use_mgr()->GetDef(block_id);
     if (!block_label || block_label->opcode() != SpvOpLabel) {
       return false;
     }
   }
 
-  auto entry_block = context->cfg()->block(message_.entry_block());
-  auto exit_block = context->cfg()->block(message_.exit_block());
+  auto entry_block = ir_context->cfg()->block(message_.entry_block());
+  auto exit_block = ir_context->cfg()->block(message_.exit_block());
 
   // The entry block cannot start with OpVariable - this would mean that
   // outlining would remove a variable from the function containing the region
@@ -151,7 +150,7 @@
 
   // For simplicity, we do not allow the exit block to be a merge block or
   // continue target.
-  if (fuzzerutil::IsMergeOrContinue(context, exit_block->id())) {
+  if (fuzzerutil::IsMergeOrContinue(ir_context, exit_block->id())) {
     return false;
   }
 
@@ -169,14 +168,14 @@
 
   // The entry block must dominate the exit block.
   auto dominator_analysis =
-      context->GetDominatorAnalysis(entry_block->GetParent());
+      ir_context->GetDominatorAnalysis(entry_block->GetParent());
   if (!dominator_analysis->Dominates(entry_block, exit_block)) {
     return false;
   }
 
   // The exit block must post-dominate the entry block.
   auto postdominator_analysis =
-      context->GetPostDominatorAnalysis(entry_block->GetParent());
+      ir_context->GetPostDominatorAnalysis(entry_block->GetParent());
   if (!postdominator_analysis->Dominates(exit_block, entry_block)) {
     return false;
   }
@@ -184,8 +183,9 @@
   // Find all the blocks dominated by |message_.entry_block| and post-dominated
   // by |message_.exit_block|.
   auto region_set = GetRegionBlocks(
-      context, entry_block = context->cfg()->block(message_.entry_block()),
-      exit_block = context->cfg()->block(message_.exit_block()));
+      ir_context,
+      entry_block = ir_context->cfg()->block(message_.entry_block()),
+      exit_block = ir_context->cfg()->block(message_.exit_block()));
 
   // Check whether |region_set| really is a single-entry single-exit region, and
   // also check whether structured control flow constructs and their merge
@@ -198,10 +198,23 @@
   for (auto& block : *entry_block->GetParent()) {
     if (&block == exit_block) {
       // It is OK (and typically expected) for the exit block of the region to
-      // have successors outside the region.  It is also OK for the exit block
-      // to head a structured control flow construct - the block containing the
-      // call to the outlined function will end up heading this construct if
-      // outlining takes place.
+      // have successors outside the region.
+      //
+      // It is also OK for the exit block to head a structured control flow
+      // construct - the block containing the call to the outlined function will
+      // end up heading this construct if outlining takes place.  However, we
+      // must ensure that if the exit block heads a loop, the continue target
+      // for this loop is outside the region.
+      if (auto loop_merge = block.GetLoopMergeInst()) {
+        // The exit block heads a loop
+        auto continue_target =
+            ir_context->cfg()->block(loop_merge->GetSingleWordOperand(1));
+        if (region_set.count(continue_target)) {
+          // The continue target for the loop is in the region.
+          return false;
+        }
+      }
+
       continue;
     }
 
@@ -210,9 +223,9 @@
       // see whether all of the block's successors are in the region.  If they
       // are not, the region is not single-entry single-exit.
       bool all_successors_in_region = true;
-      block.WhileEachSuccessorLabel([&all_successors_in_region, context,
+      block.WhileEachSuccessorLabel([&all_successors_in_region, ir_context,
                                      &region_set](uint32_t successor) -> bool {
-        if (region_set.count(context->cfg()->block(successor)) == 0) {
+        if (region_set.count(ir_context->cfg()->block(successor)) == 0) {
           all_successors_in_region = false;
           return false;
         }
@@ -227,7 +240,8 @@
       // The block is a loop or selection header -- the header and its
       // associated merge block had better both be in the region or both be
       // outside the region.
-      auto merge_block = context->cfg()->block(merge->GetSingleWordOperand(0));
+      auto merge_block =
+          ir_context->cfg()->block(merge->GetSingleWordOperand(0));
       if (region_set.count(&block) != region_set.count(merge_block)) {
         return false;
       }
@@ -236,7 +250,7 @@
     if (auto loop_merge = block.GetLoopMergeInst()) {
       // Similar to the above, but for the continue target of a loop.
       auto continue_target =
-          context->cfg()->block(loop_merge->GetSingleWordOperand(1));
+          ir_context->cfg()->block(loop_merge->GetSingleWordOperand(1));
       if (continue_target != exit_block &&
           region_set.count(&block) != region_set.count(continue_target)) {
         return false;
@@ -248,7 +262,7 @@
   // used inside the region, ...
   std::map<uint32_t, uint32_t> input_id_to_fresh_id_map =
       PairSequenceToMap(message_.input_id_to_fresh_id());
-  for (auto id : GetRegionInputIds(context, region_set, exit_block)) {
+  for (auto id : GetRegionInputIds(ir_context, region_set, exit_block)) {
     // There needs to be a corresponding fresh id to be used as a function
     // parameter.
     if (input_id_to_fresh_id_map.count(id) == 0) {
@@ -256,8 +270,8 @@
     }
     // Furthermore, if the input id has pointer type it must be an OpVariable
     // or OpFunctionParameter.
-    auto input_id_inst = context->get_def_use_mgr()->GetDef(id);
-    if (context->get_def_use_mgr()
+    auto input_id_inst = ir_context->get_def_use_mgr()->GetDef(id);
+    if (ir_context->get_def_use_mgr()
             ->GetDef(input_id_inst->type_id())
             ->opcode() == SpvOpTypePointer) {
       switch (input_id_inst->opcode()) {
@@ -273,12 +287,20 @@
   }
 
   // For each region output id -- i.e. every id defined inside the region but
-  // used outside the region -- there needs to be a corresponding fresh id that
-  // can hold the value for this id computed in the outlined function.
+  // used outside the region, ...
   std::map<uint32_t, uint32_t> output_id_to_fresh_id_map =
       PairSequenceToMap(message_.output_id_to_fresh_id());
-  for (auto id : GetRegionOutputIds(context, region_set, exit_block)) {
-    if (output_id_to_fresh_id_map.count(id) == 0) {
+  for (auto id : GetRegionOutputIds(ir_context, region_set, exit_block)) {
+    if (
+        // ... there needs to be a corresponding fresh id that can hold the
+        // value for this id computed in the outlined function, and ...
+        output_id_to_fresh_id_map.count(id) == 0
+        // ... the output id must not have pointer type (to avoid creating a
+        // struct with pointer members to pass data out of the outlined
+        // function)
+        || ir_context->get_def_use_mgr()
+                   ->GetDef(fuzzerutil::GetTypeId(ir_context, id))
+                   ->opcode() == SpvOpTypePointer) {
       return false;
     }
   }
@@ -287,25 +309,26 @@
 }
 
 void TransformationOutlineFunction::Apply(
-    opt::IRContext* context, spvtools::fuzz::FactManager* fact_manager) const {
+    opt::IRContext* ir_context,
+    TransformationContext* transformation_context) const {
   // The entry block for the region before outlining.
   auto original_region_entry_block =
-      context->cfg()->block(message_.entry_block());
+      ir_context->cfg()->block(message_.entry_block());
 
   // The exit block for the region before outlining.
   auto original_region_exit_block =
-      context->cfg()->block(message_.exit_block());
+      ir_context->cfg()->block(message_.exit_block());
 
   // The single-entry single-exit region defined by |message_.entry_block| and
   // |message_.exit_block|.
   std::set<opt::BasicBlock*> region_blocks = GetRegionBlocks(
-      context, original_region_entry_block, original_region_exit_block);
+      ir_context, original_region_entry_block, original_region_exit_block);
 
   // Input and output ids for the region being outlined.
   std::vector<uint32_t> region_input_ids =
-      GetRegionInputIds(context, region_blocks, original_region_exit_block);
+      GetRegionInputIds(ir_context, region_blocks, original_region_exit_block);
   std::vector<uint32_t> region_output_ids =
-      GetRegionOutputIds(context, region_blocks, original_region_exit_block);
+      GetRegionOutputIds(ir_context, region_blocks, original_region_exit_block);
 
   // Maps from input and output ids to fresh ids.
   std::map<uint32_t, uint32_t> input_id_to_fresh_id_map =
@@ -313,14 +336,14 @@
   std::map<uint32_t, uint32_t> output_id_to_fresh_id_map =
       PairSequenceToMap(message_.output_id_to_fresh_id());
 
-  UpdateModuleIdBoundForFreshIds(context, input_id_to_fresh_id_map,
+  UpdateModuleIdBoundForFreshIds(ir_context, input_id_to_fresh_id_map,
                                  output_id_to_fresh_id_map);
 
   // Construct a map that associates each output id with its type id.
   std::map<uint32_t, uint32_t> output_id_to_type_id;
   for (uint32_t output_id : region_output_ids) {
     output_id_to_type_id[output_id] =
-        context->get_def_use_mgr()->GetDef(output_id)->type_id();
+        ir_context->get_def_use_mgr()->GetDef(output_id)->type_id();
   }
 
   // The region will be collapsed to a single block that calls a function
@@ -331,53 +354,55 @@
   // collapsed block later.
   std::unique_ptr<opt::Instruction> cloned_exit_block_terminator =
       std::unique_ptr<opt::Instruction>(
-          original_region_exit_block->terminator()->Clone(context));
+          original_region_exit_block->terminator()->Clone(ir_context));
   std::unique_ptr<opt::Instruction> cloned_exit_block_merge =
       original_region_exit_block->GetMergeInst()
           ? std::unique_ptr<opt::Instruction>(
-                original_region_exit_block->GetMergeInst()->Clone(context))
+                original_region_exit_block->GetMergeInst()->Clone(ir_context))
           : nullptr;
 
   // Make a function prototype for the outlined function, which involves
   // figuring out its required type.
-  std::unique_ptr<opt::Function> outlined_function =
-      PrepareFunctionPrototype(region_input_ids, region_output_ids,
-                               input_id_to_fresh_id_map, context, fact_manager);
+  std::unique_ptr<opt::Function> outlined_function = PrepareFunctionPrototype(
+      region_input_ids, region_output_ids, input_id_to_fresh_id_map, ir_context,
+      transformation_context);
 
   // If the original function was livesafe, the new function should also be
   // livesafe.
-  if (fact_manager->FunctionIsLivesafe(
+  if (transformation_context->GetFactManager()->FunctionIsLivesafe(
           original_region_entry_block->GetParent()->result_id())) {
-    fact_manager->AddFactFunctionIsLivesafe(message_.new_function_id());
+    transformation_context->GetFactManager()->AddFactFunctionIsLivesafe(
+        message_.new_function_id());
   }
 
   // Adapt the region to be outlined so that its input ids are replaced with the
   // ids of the outlined function's input parameters, and so that output ids
   // are similarly remapped.
   RemapInputAndOutputIdsInRegion(
-      context, *original_region_exit_block, region_blocks, region_input_ids,
+      ir_context, *original_region_exit_block, region_blocks, region_input_ids,
       region_output_ids, input_id_to_fresh_id_map, output_id_to_fresh_id_map);
 
   // Fill out the body of the outlined function according to the region that is
   // being outlined.
-  PopulateOutlinedFunction(*original_region_entry_block,
-                           *original_region_exit_block, region_blocks,
-                           region_output_ids, output_id_to_fresh_id_map,
-                           context, outlined_function.get(), fact_manager);
+  PopulateOutlinedFunction(
+      *original_region_entry_block, *original_region_exit_block, region_blocks,
+      region_output_ids, output_id_to_fresh_id_map, ir_context,
+      outlined_function.get(), transformation_context);
 
   // Collapse the region that has been outlined into a function down to a single
   // block that calls said function.
   ShrinkOriginalRegion(
-      context, region_blocks, region_input_ids, region_output_ids,
+      ir_context, region_blocks, region_input_ids, region_output_ids,
       output_id_to_type_id, outlined_function->type_id(),
       std::move(cloned_exit_block_merge),
       std::move(cloned_exit_block_terminator), original_region_entry_block);
 
   // Add the outlined function to the module.
-  context->module()->AddFunction(std::move(outlined_function));
+  ir_context->module()->AddFunction(std::move(outlined_function));
 
   // Major surgery has been conducted on the module, so invalidate all analyses.
-  context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(
+      opt::IRContext::Analysis::kAnalysisNone);
 }
 
 protobufs::Transformation TransformationOutlineFunction::ToMessage() const {
@@ -387,30 +412,31 @@
 }
 
 std::vector<uint32_t> TransformationOutlineFunction::GetRegionInputIds(
-    opt::IRContext* context, const std::set<opt::BasicBlock*>& region_set,
+    opt::IRContext* ir_context, const std::set<opt::BasicBlock*>& region_set,
     opt::BasicBlock* region_exit_block) {
   std::vector<uint32_t> result;
 
   auto enclosing_function = region_exit_block->GetParent();
 
   // Consider each parameter of the function containing the region.
-  enclosing_function->ForEachParam([context, &region_set, &result](
-                                       opt::Instruction* function_parameter) {
-    // Consider every use of the parameter.
-    context->get_def_use_mgr()->WhileEachUse(
-        function_parameter, [context, function_parameter, &region_set, &result](
-                                opt::Instruction* use, uint32_t /*unused*/) {
-          // Get the block, if any, in which the parameter is used.
-          auto use_block = context->get_instr_block(use);
-          // If the use is in a block that lies within the region, the
-          // parameter is an input id for the region.
-          if (use_block && region_set.count(use_block) != 0) {
-            result.push_back(function_parameter->result_id());
-            return false;
-          }
-          return true;
-        });
-  });
+  enclosing_function->ForEachParam(
+      [ir_context, &region_set, &result](opt::Instruction* function_parameter) {
+        // Consider every use of the parameter.
+        ir_context->get_def_use_mgr()->WhileEachUse(
+            function_parameter,
+            [ir_context, function_parameter, &region_set, &result](
+                opt::Instruction* use, uint32_t /*unused*/) {
+              // Get the block, if any, in which the parameter is used.
+              auto use_block = ir_context->get_instr_block(use);
+              // If the use is in a block that lies within the region, the
+              // parameter is an input id for the region.
+              if (use_block && region_set.count(use_block) != 0) {
+                result.push_back(function_parameter->result_id());
+                return false;
+              }
+              return true;
+            });
+      });
 
   // Consider all definitions in the function that might turn out to be input
   // ids.
@@ -430,15 +456,15 @@
     // Consider each candidate input id to check whether it is used in the
     // region.
     for (auto& inst : candidate_input_ids_for_block) {
-      context->get_def_use_mgr()->WhileEachUse(
+      ir_context->get_def_use_mgr()->WhileEachUse(
           inst,
-          [context, &inst, region_exit_block, &region_set, &result](
+          [ir_context, &inst, region_exit_block, &region_set, &result](
               opt::Instruction* use, uint32_t /*unused*/) -> bool {
 
             // Find the block in which this id use occurs, recording the id as
             // an input id if the block is outside the region, with some
             // exceptions detailed below.
-            auto use_block = context->get_instr_block(use);
+            auto use_block = ir_context->get_instr_block(use);
 
             if (!use_block) {
               // There might be no containing block, e.g. if the use is in a
@@ -467,7 +493,7 @@
 }
 
 std::vector<uint32_t> TransformationOutlineFunction::GetRegionOutputIds(
-    opt::IRContext* context, const std::set<opt::BasicBlock*>& region_set,
+    opt::IRContext* ir_context, const std::set<opt::BasicBlock*>& region_set,
     opt::BasicBlock* region_exit_block) {
   std::vector<uint32_t> result;
 
@@ -479,15 +505,15 @@
     }
     // Consider each use of each instruction defined in the block.
     for (auto& inst : block) {
-      context->get_def_use_mgr()->WhileEachUse(
+      ir_context->get_def_use_mgr()->WhileEachUse(
           &inst,
-          [&region_set, context, &inst, region_exit_block, &result](
+          [&region_set, ir_context, &inst, region_exit_block, &result](
               opt::Instruction* use, uint32_t /*unused*/) -> bool {
 
             // Find the block in which this id use occurs, recording the id as
             // an output id if the block is outside the region, with some
             // exceptions detailed below.
-            auto use_block = context->get_instr_block(use);
+            auto use_block = ir_context->get_instr_block(use);
 
             if (!use_block) {
               // There might be no containing block, e.g. if the use is in a
@@ -513,12 +539,13 @@
 }
 
 std::set<opt::BasicBlock*> TransformationOutlineFunction::GetRegionBlocks(
-    opt::IRContext* context, opt::BasicBlock* entry_block,
+    opt::IRContext* ir_context, opt::BasicBlock* entry_block,
     opt::BasicBlock* exit_block) {
   auto enclosing_function = entry_block->GetParent();
-  auto dominator_analysis = context->GetDominatorAnalysis(enclosing_function);
+  auto dominator_analysis =
+      ir_context->GetDominatorAnalysis(enclosing_function);
   auto postdominator_analysis =
-      context->GetPostDominatorAnalysis(enclosing_function);
+      ir_context->GetPostDominatorAnalysis(enclosing_function);
 
   std::set<opt::BasicBlock*> result;
   for (auto& block : *enclosing_function) {
@@ -535,7 +562,8 @@
     const std::vector<uint32_t>& region_input_ids,
     const std::vector<uint32_t>& region_output_ids,
     const std::map<uint32_t, uint32_t>& input_id_to_fresh_id_map,
-    opt::IRContext* context, FactManager* fact_manager) const {
+    opt::IRContext* ir_context,
+    TransformationContext* transformation_context) const {
   uint32_t return_type_id = 0;
   uint32_t function_type_id = 0;
 
@@ -547,14 +575,14 @@
   if (region_output_ids.empty()) {
     std::vector<uint32_t> return_and_parameter_types;
     opt::analysis::Void void_type;
-    return_type_id = context->get_type_mgr()->GetId(&void_type);
+    return_type_id = ir_context->get_type_mgr()->GetId(&void_type);
     return_and_parameter_types.push_back(return_type_id);
     for (auto id : region_input_ids) {
       return_and_parameter_types.push_back(
-          context->get_def_use_mgr()->GetDef(id)->type_id());
+          ir_context->get_def_use_mgr()->GetDef(id)->type_id());
     }
     function_type_id =
-        fuzzerutil::FindFunctionType(context, return_and_parameter_types);
+        fuzzerutil::FindFunctionType(ir_context, return_and_parameter_types);
   }
 
   // If no existing function type was found, we need to create one.
@@ -568,12 +596,12 @@
       opt::Instruction::OperandList struct_member_types;
       for (uint32_t output_id : region_output_ids) {
         auto output_id_type =
-            context->get_def_use_mgr()->GetDef(output_id)->type_id();
+            ir_context->get_def_use_mgr()->GetDef(output_id)->type_id();
         struct_member_types.push_back({SPV_OPERAND_TYPE_ID, {output_id_type}});
       }
       // Add a new struct type to the module.
-      context->module()->AddType(MakeUnique<opt::Instruction>(
-          context, SpvOpTypeStruct, 0,
+      ir_context->module()->AddType(MakeUnique<opt::Instruction>(
+          ir_context, SpvOpTypeStruct, 0,
           message_.new_function_struct_return_type_id(),
           std::move(struct_member_types)));
       // The return type for the function is the newly-created struct.
@@ -589,12 +617,12 @@
     for (auto id : region_input_ids) {
       function_type_operands.push_back(
           {SPV_OPERAND_TYPE_ID,
-           {context->get_def_use_mgr()->GetDef(id)->type_id()}});
+           {ir_context->get_def_use_mgr()->GetDef(id)->type_id()}});
     }
     // Add a new function type to the module, and record that this is the type
     // id for the new function.
-    context->module()->AddType(MakeUnique<opt::Instruction>(
-        context, SpvOpTypeFunction, 0, message_.new_function_type_id(),
+    ir_context->module()->AddType(MakeUnique<opt::Instruction>(
+        ir_context, SpvOpTypeFunction, 0, message_.new_function_type_id(),
         function_type_operands));
     function_type_id = message_.new_function_type_id();
   }
@@ -603,7 +631,7 @@
   // and the return type and function type prepared above.
   std::unique_ptr<opt::Function> outlined_function =
       MakeUnique<opt::Function>(MakeUnique<opt::Instruction>(
-          context, SpvOpFunction, return_type_id, message_.new_function_id(),
+          ir_context, SpvOpFunction, return_type_id, message_.new_function_id(),
           opt::Instruction::OperandList(
               {{spv_operand_type_t ::SPV_OPERAND_TYPE_LITERAL_INTEGER,
                 {SpvFunctionControlMaskNone}},
@@ -614,14 +642,15 @@
   // provided in |input_id_to_fresh_id_map|.
   for (auto id : region_input_ids) {
     outlined_function->AddParameter(MakeUnique<opt::Instruction>(
-        context, SpvOpFunctionParameter,
-        context->get_def_use_mgr()->GetDef(id)->type_id(),
+        ir_context, SpvOpFunctionParameter,
+        ir_context->get_def_use_mgr()->GetDef(id)->type_id(),
         input_id_to_fresh_id_map.at(id), opt::Instruction::OperandList()));
     // If the input id is an irrelevant-valued variable, the same should be true
     // of the corresponding parameter.
-    if (fact_manager->PointeeValueIsIrrelevant(id)) {
-      fact_manager->AddFactValueOfPointeeIsIrrelevant(
-          input_id_to_fresh_id_map.at(id));
+    if (transformation_context->GetFactManager()->PointeeValueIsIrrelevant(
+            id)) {
+      transformation_context->GetFactManager()
+          ->AddFactValueOfPointeeIsIrrelevant(input_id_to_fresh_id_map.at(id));
     }
   }
 
@@ -629,31 +658,32 @@
 }
 
 void TransformationOutlineFunction::UpdateModuleIdBoundForFreshIds(
-    opt::IRContext* context,
+    opt::IRContext* ir_context,
     const std::map<uint32_t, uint32_t>& input_id_to_fresh_id_map,
     const std::map<uint32_t, uint32_t>& output_id_to_fresh_id_map) const {
   // Enlarge the module's id bound as needed to accommodate the various fresh
   // ids associated with the transformation.
   fuzzerutil::UpdateModuleIdBound(
-      context, message_.new_function_struct_return_type_id());
-  fuzzerutil::UpdateModuleIdBound(context, message_.new_function_type_id());
-  fuzzerutil::UpdateModuleIdBound(context, message_.new_function_id());
-  fuzzerutil::UpdateModuleIdBound(context,
+      ir_context, message_.new_function_struct_return_type_id());
+  fuzzerutil::UpdateModuleIdBound(ir_context, message_.new_function_type_id());
+  fuzzerutil::UpdateModuleIdBound(ir_context, message_.new_function_id());
+  fuzzerutil::UpdateModuleIdBound(ir_context,
                                   message_.new_function_region_entry_block());
-  fuzzerutil::UpdateModuleIdBound(context, message_.new_caller_result_id());
-  fuzzerutil::UpdateModuleIdBound(context, message_.new_callee_result_id());
+  fuzzerutil::UpdateModuleIdBound(ir_context, message_.new_caller_result_id());
+  fuzzerutil::UpdateModuleIdBound(ir_context, message_.new_callee_result_id());
 
   for (auto& entry : input_id_to_fresh_id_map) {
-    fuzzerutil::UpdateModuleIdBound(context, entry.second);
+    fuzzerutil::UpdateModuleIdBound(ir_context, entry.second);
   }
 
   for (auto& entry : output_id_to_fresh_id_map) {
-    fuzzerutil::UpdateModuleIdBound(context, entry.second);
+    fuzzerutil::UpdateModuleIdBound(ir_context, entry.second);
   }
 }
 
 void TransformationOutlineFunction::RemapInputAndOutputIdsInRegion(
-    opt::IRContext* context, const opt::BasicBlock& original_region_exit_block,
+    opt::IRContext* ir_context,
+    const opt::BasicBlock& original_region_exit_block,
     const std::set<opt::BasicBlock*>& region_blocks,
     const std::vector<uint32_t>& region_input_ids,
     const std::vector<uint32_t>& region_output_ids,
@@ -664,11 +694,11 @@
   // This is done by considering each region input id in turn.
   for (uint32_t id : region_input_ids) {
     // We then consider each use of the input id.
-    context->get_def_use_mgr()->ForEachUse(
-        id, [context, id, &input_id_to_fresh_id_map, region_blocks](
+    ir_context->get_def_use_mgr()->ForEachUse(
+        id, [ir_context, id, &input_id_to_fresh_id_map, region_blocks](
                 opt::Instruction* use, uint32_t operand_index) {
           // Find the block in which this use of the input id occurs.
-          opt::BasicBlock* use_block = context->get_instr_block(use);
+          opt::BasicBlock* use_block = ir_context->get_instr_block(use);
           // We want to rewrite the use id if its block occurs in the outlined
           // region.
           if (region_blocks.count(use_block) != 0) {
@@ -684,12 +714,12 @@
   // This is done by considering each region output id in turn.
   for (uint32_t id : region_output_ids) {
     // First consider each use of the output id and update the relevant uses.
-    context->get_def_use_mgr()->ForEachUse(
-        id,
-        [context, &original_region_exit_block, id, &output_id_to_fresh_id_map,
-         region_blocks](opt::Instruction* use, uint32_t operand_index) {
+    ir_context->get_def_use_mgr()->ForEachUse(
+        id, [ir_context, &original_region_exit_block, id,
+             &output_id_to_fresh_id_map,
+             region_blocks](opt::Instruction* use, uint32_t operand_index) {
           // Find the block in which this use of the output id occurs.
-          auto use_block = context->get_instr_block(use);
+          auto use_block = ir_context->get_instr_block(use);
           // We want to rewrite the use id if its block occurs in the outlined
           // region, with one exception: the terminator of the exit block of
           // the region is going to remain in the original function, so if the
@@ -710,7 +740,7 @@
     // defines the corresponding fresh id.  We do this after changing all the
     // uses so that the definition of the original id is still registered when
     // we analyse its uses.
-    context->get_def_use_mgr()->GetDef(id)->SetResultId(
+    ir_context->get_def_use_mgr()->GetDef(id)->SetResultId(
         output_id_to_fresh_id_map.at(id));
   }
 }
@@ -721,8 +751,8 @@
     const std::set<opt::BasicBlock*>& region_blocks,
     const std::vector<uint32_t>& region_output_ids,
     const std::map<uint32_t, uint32_t>& output_id_to_fresh_id_map,
-    opt::IRContext* context, opt::Function* outlined_function,
-    FactManager* fact_manager) const {
+    opt::IRContext* ir_context, opt::Function* outlined_function,
+    TransformationContext* transformation_context) const {
   // When we create the exit block for the outlined region, we use this pointer
   // to track of it so that we can manipulate it later.
   opt::BasicBlock* outlined_region_exit_block = nullptr;
@@ -732,14 +762,16 @@
   // |message_.new_function_region_entry_block| as its id.
   std::unique_ptr<opt::BasicBlock> outlined_region_entry_block =
       MakeUnique<opt::BasicBlock>(MakeUnique<opt::Instruction>(
-          context, SpvOpLabel, 0, message_.new_function_region_entry_block(),
+          ir_context, SpvOpLabel, 0, message_.new_function_region_entry_block(),
           opt::Instruction::OperandList()));
   outlined_region_entry_block->SetParent(outlined_function);
 
   // If the original region's entry block was dead, the outlined region's entry
   // block is also dead.
-  if (fact_manager->BlockIsDead(original_region_entry_block.id())) {
-    fact_manager->AddFactBlockIsDead(outlined_region_entry_block->id());
+  if (transformation_context->GetFactManager()->BlockIsDead(
+          original_region_entry_block.id())) {
+    transformation_context->GetFactManager()->AddFactBlockIsDead(
+        outlined_region_entry_block->id());
   }
 
   if (&original_region_entry_block == &original_region_exit_block) {
@@ -748,7 +780,7 @@
 
   for (auto& inst : original_region_entry_block) {
     outlined_region_entry_block->AddInstruction(
-        std::unique_ptr<opt::Instruction>(inst.Clone(context)));
+        std::unique_ptr<opt::Instruction>(inst.Clone(ir_context)));
   }
   outlined_function->AddBasicBlock(std::move(outlined_region_entry_block));
 
@@ -767,7 +799,7 @@
     }
     // Clone the block so that it can be added to the new function.
     auto cloned_block =
-        std::unique_ptr<opt::BasicBlock>(block_it->Clone(context));
+        std::unique_ptr<opt::BasicBlock>(block_it->Clone(ir_context));
 
     // If this is the region's exit block, then the cloned block is the outlined
     // region's exit block.
@@ -823,7 +855,7 @@
     // The case where there are no region output ids is simple: we just add
     // OpReturn.
     outlined_region_exit_block->AddInstruction(MakeUnique<opt::Instruction>(
-        context, SpvOpReturn, 0, 0, opt::Instruction::OperandList()));
+        ir_context, SpvOpReturn, 0, 0, opt::Instruction::OperandList()));
   } else {
     // In the case where there are output ids, we add an OpCompositeConstruct
     // instruction to pack all the output values into a struct, and then an
@@ -834,21 +866,21 @@
           {SPV_OPERAND_TYPE_ID, {output_id_to_fresh_id_map.at(id)}});
     }
     outlined_region_exit_block->AddInstruction(MakeUnique<opt::Instruction>(
-        context, SpvOpCompositeConstruct,
+        ir_context, SpvOpCompositeConstruct,
         message_.new_function_struct_return_type_id(),
         message_.new_callee_result_id(), struct_member_operands));
     outlined_region_exit_block->AddInstruction(MakeUnique<opt::Instruction>(
-        context, SpvOpReturnValue, 0, 0,
+        ir_context, SpvOpReturnValue, 0, 0,
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {message_.new_callee_result_id()}}})));
   }
 
   outlined_function->SetFunctionEnd(MakeUnique<opt::Instruction>(
-      context, SpvOpFunctionEnd, 0, 0, opt::Instruction::OperandList()));
+      ir_context, SpvOpFunctionEnd, 0, 0, opt::Instruction::OperandList()));
 }
 
 void TransformationOutlineFunction::ShrinkOriginalRegion(
-    opt::IRContext* context, std::set<opt::BasicBlock*>& region_blocks,
+    opt::IRContext* ir_context, std::set<opt::BasicBlock*>& region_blocks,
     const std::vector<uint32_t>& region_input_ids,
     const std::vector<uint32_t>& region_output_ids,
     const std::map<uint32_t, uint32_t>& output_id_to_type_id,
@@ -912,7 +944,7 @@
   }
 
   original_region_entry_block->AddInstruction(MakeUnique<opt::Instruction>(
-      context, SpvOpFunctionCall, return_type_id,
+      ir_context, SpvOpFunctionCall, return_type_id,
       message_.new_caller_result_id(), function_call_operands));
 
   // If there are output ids, the function call will return a struct.  For each
@@ -921,7 +953,7 @@
   for (uint32_t index = 0; index < region_output_ids.size(); ++index) {
     uint32_t output_id = region_output_ids[index];
     original_region_entry_block->AddInstruction(MakeUnique<opt::Instruction>(
-        context, SpvOpCompositeExtract, output_id_to_type_id.at(output_id),
+        ir_context, SpvOpCompositeExtract, output_id_to_type_id.at(output_id),
         output_id,
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {message_.new_caller_result_id()}},
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_outline_function.h b/third_party/spirv-tools/src/source/fuzz/transformation_outline_function.h
index 5711790..ba439c8 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_outline_function.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_outline_function.h
@@ -19,9 +19,9 @@
 #include <set>
 #include <vector>
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -58,8 +58,9 @@
   //   defined outside the region but used in the region
   // - |message_.output_id_to_fresh_id| must contain an entry for every id
   //   defined in the region but used outside the region
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // - A new function with id |message_.new_function_id| is added to the module.
   // - If the region generates output ids, the return type of this function is
@@ -95,14 +96,15 @@
   //   |message_.new_function_struct_return_type| comprised of all the fresh
   //   output ids (unless the return type is void, in which case no value is
   //   returned.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
   // Returns the set of blocks dominated by |entry_block| and post-dominated
   // by |exit_block|.
   static std::set<opt::BasicBlock*> GetRegionBlocks(
-      opt::IRContext* context, opt::BasicBlock* entry_block,
+      opt::IRContext* ir_context, opt::BasicBlock* entry_block,
       opt::BasicBlock* exit_block);
 
   // Yields ids that are used in |region_set| and that are either parameters
@@ -114,7 +116,7 @@
   // - id uses in OpPhi instructions in |region_entry_block| are ignored
   // - id uses in the terminator instruction of |region_exit_block| are ignored
   static std::vector<uint32_t> GetRegionInputIds(
-      opt::IRContext* context, const std::set<opt::BasicBlock*>& region_set,
+      opt::IRContext* ir_context, const std::set<opt::BasicBlock*>& region_set,
       opt::BasicBlock* region_exit_block);
 
   // Yields all ids that are defined in |region_set| and used outside
@@ -124,14 +126,14 @@
   // - ids defined in the region and used in the terminator of
   //   |region_exit_block| count as output ids
   static std::vector<uint32_t> GetRegionOutputIds(
-      opt::IRContext* context, const std::set<opt::BasicBlock*>& region_set,
+      opt::IRContext* ir_context, const std::set<opt::BasicBlock*>& region_set,
       opt::BasicBlock* region_exit_block);
 
  private:
   // Ensures that the module's id bound is at least the maximum of any fresh id
   // associated with the transformation.
   void UpdateModuleIdBoundForFreshIds(
-      opt::IRContext* context,
+      opt::IRContext* ir_context,
       const std::map<uint32_t, uint32_t>& input_id_to_fresh_id_map,
       const std::map<uint32_t, uint32_t>& output_id_to_fresh_id_map) const;
 
@@ -142,7 +144,7 @@
   // modified, and |original_region_exit_block| allows for some special cases
   // where ids should not be remapped.
   void RemapInputAndOutputIdsInRegion(
-      opt::IRContext* context,
+      opt::IRContext* ir_context,
       const opt::BasicBlock& original_region_exit_block,
       const std::set<opt::BasicBlock*>& region_blocks,
       const std::vector<uint32_t>& region_input_ids,
@@ -160,12 +162,14 @@
   // are already present).
   //
   // Facts about the function containing the outlined region that are relevant
-  // to the new function are propagated via |fact_manager|.
+  // to the new function are propagated via the vact manager in
+  // |transformation_context|.
   std::unique_ptr<opt::Function> PrepareFunctionPrototype(
       const std::vector<uint32_t>& region_input_ids,
       const std::vector<uint32_t>& region_output_ids,
       const std::map<uint32_t, uint32_t>& input_id_to_fresh_id_map,
-      opt::IRContext* context, FactManager* fact_manager) const;
+      opt::IRContext* ir_context,
+      TransformationContext* transformation_context) const;
 
   // Creates the body of the outlined function by cloning blocks from the
   // original region, given by |region_blocks|, adapting the cloned version
@@ -174,17 +178,17 @@
   // clone.  Parameters |region_output_ids| and |output_id_to_fresh_id_map| are
   // used to determine what the function should return.
   //
-  // The |fact_manager| argument allow facts about blocks being outlined, e.g.
-  // whether they are dead blocks, to be asserted about blocks that get created
-  // during outlining.
+  // The |transformation_context| argument allow facts about blocks being
+  // outlined, e.g. whether they are dead blocks, to be asserted about blocks
+  // that get created during outlining.
   void PopulateOutlinedFunction(
       const opt::BasicBlock& original_region_entry_block,
       const opt::BasicBlock& original_region_exit_block,
       const std::set<opt::BasicBlock*>& region_blocks,
       const std::vector<uint32_t>& region_output_ids,
       const std::map<uint32_t, uint32_t>& output_id_to_fresh_id_map,
-      opt::IRContext* context, opt::Function* outlined_function,
-      FactManager* fact_manager) const;
+      opt::IRContext* ir_context, opt::Function* outlined_function,
+      TransformationContext* transformation_context) const;
 
   // Shrinks the outlined region, given by |region_blocks|, down to the single
   // block |original_region_entry_block|.  This block is itself shrunk to just
@@ -203,7 +207,7 @@
   // function is called, this information cannot be gotten from the def-use
   // manager.
   void ShrinkOriginalRegion(
-      opt::IRContext* context, std::set<opt::BasicBlock*>& region_blocks,
+      opt::IRContext* ir_context, std::set<opt::BasicBlock*>& region_blocks,
       const std::vector<uint32_t>& region_input_ids,
       const std::vector<uint32_t>& region_output_ids,
       const std::map<uint32_t, uint32_t>& output_id_to_type_id,
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_permute_function_parameters.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_permute_function_parameters.cpp
index 2141533..0f1220e 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_permute_function_parameters.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_permute_function_parameters.cpp
@@ -40,17 +40,17 @@
 }
 
 bool TransformationPermuteFunctionParameters::IsApplicable(
-    opt::IRContext* context, const FactManager& /*unused*/) const {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
   // Check that function exists
   const auto* function =
-      fuzzerutil::FindFunction(context, message_.function_id());
+      fuzzerutil::FindFunction(ir_context, message_.function_id());
   if (!function || function->DefInst().opcode() != SpvOpFunction ||
-      fuzzerutil::FunctionIsEntryPoint(context, function->result_id())) {
+      fuzzerutil::FunctionIsEntryPoint(ir_context, function->result_id())) {
     return false;
   }
 
   // Check that permutation has valid indices
-  const auto* function_type = fuzzerutil::GetFunctionType(context, function);
+  const auto* function_type = fuzzerutil::GetFunctionType(ir_context, function);
   assert(function_type && "Function type is null");
 
   const auto& permutation = message_.permutation();
@@ -83,7 +83,7 @@
   //   - Has the same result type as the old one
   //   - Order of arguments is permuted
   auto new_type_id = message_.new_type_id();
-  const auto* new_type = context->get_def_use_mgr()->GetDef(new_type_id);
+  const auto* new_type = ir_context->get_def_use_mgr()->GetDef(new_type_id);
 
   if (!new_type || new_type->opcode() != SpvOpTypeFunction ||
       new_type->NumInOperands() != function_type->NumInOperands()) {
@@ -109,14 +109,14 @@
 }
 
 void TransformationPermuteFunctionParameters::Apply(
-    opt::IRContext* context, FactManager* /*unused*/) const {
+    opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
   // Retrieve all data from the message
   uint32_t function_id = message_.function_id();
   uint32_t new_type_id = message_.new_type_id();
   const auto& permutation = message_.permutation();
 
   // Find the function that will be transformed
-  auto* function = fuzzerutil::FindFunction(context, function_id);
+  auto* function = fuzzerutil::FindFunction(ir_context, function_id);
   assert(function && "Can't find the function");
 
   // Change function's type
@@ -149,7 +149,7 @@
       });
 
   // Fix all OpFunctionCall instructions
-  context->get_def_use_mgr()->ForEachUser(
+  ir_context->get_def_use_mgr()->ForEachUser(
       &function->DefInst(),
       [function_id, &permutation](opt::Instruction* call) {
         if (call->opcode() != SpvOpFunctionCall ||
@@ -170,7 +170,8 @@
       });
 
   // Make sure our changes are analyzed
-  context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(
+      opt::IRContext::Analysis::kAnalysisNone);
 }
 
 protobufs::Transformation TransformationPermuteFunctionParameters::ToMessage()
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_permute_function_parameters.h b/third_party/spirv-tools/src/source/fuzz/transformation_permute_function_parameters.h
index c67a735..994e4c2 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_permute_function_parameters.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_permute_function_parameters.h
@@ -15,9 +15,9 @@
 #ifndef SOURCE_FUZZ_TRANSFORMATION_PERMUTE_FUNCTION_PARAMETERS_H_
 #define SOURCE_FUZZ_TRANSFORMATION_PERMUTE_FUNCTION_PARAMETERS_H_
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -40,14 +40,16 @@
   //     - function's arguments are permuted according to |permutation| vector
   // - |permutation| is a set of [0..(n - 1)], where n is a number of arguments
   //   to the function
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // - OpFunction instruction with |result_id == function_id| is changed.
   //   Its arguments are permuted according to the |permutation| vector
   // - Changed function gets a new type specified by |type_id|
   // - Calls to the function are adjusted accordingly
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_replace_boolean_constant_with_constant_binary.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_replace_boolean_constant_with_constant_binary.cpp
index 72d9b22..d6f17fc 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_replace_boolean_constant_with_constant_binary.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_replace_boolean_constant_with_constant_binary.cpp
@@ -128,15 +128,15 @@
 }
 
 bool TransformationReplaceBooleanConstantWithConstantBinary::IsApplicable(
-    opt::IRContext* context, const FactManager& /*unused*/) const {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
   // The id for the binary result must be fresh
-  if (!fuzzerutil::IsFreshId(context,
+  if (!fuzzerutil::IsFreshId(ir_context,
                              message_.fresh_id_for_binary_operation())) {
     return false;
   }
 
   // The used id must be for a boolean constant
-  auto boolean_constant = context->get_def_use_mgr()->GetDef(
+  auto boolean_constant = ir_context->get_def_use_mgr()->GetDef(
       message_.id_use_descriptor().id_of_interest());
   if (!boolean_constant) {
     return false;
@@ -148,7 +148,7 @@
 
   // The left-hand-side id must correspond to a constant instruction.
   auto lhs_constant_inst =
-      context->get_def_use_mgr()->GetDef(message_.lhs_id());
+      ir_context->get_def_use_mgr()->GetDef(message_.lhs_id());
   if (!lhs_constant_inst) {
     return false;
   }
@@ -158,7 +158,7 @@
 
   // The right-hand-side id must correspond to a constant instruction.
   auto rhs_constant_inst =
-      context->get_def_use_mgr()->GetDef(message_.rhs_id());
+      ir_context->get_def_use_mgr()->GetDef(message_.rhs_id());
   if (!rhs_constant_inst) {
     return false;
   }
@@ -173,9 +173,9 @@
 
   // The expression 'LHS opcode RHS' must evaluate to the boolean constant.
   auto lhs_constant =
-      context->get_constant_mgr()->FindDeclaredConstant(message_.lhs_id());
+      ir_context->get_constant_mgr()->FindDeclaredConstant(message_.lhs_id());
   auto rhs_constant =
-      context->get_constant_mgr()->FindDeclaredConstant(message_.rhs_id());
+      ir_context->get_constant_mgr()->FindDeclaredConstant(message_.rhs_id());
   bool expected_result = (boolean_constant->opcode() == SpvOpConstantTrue);
 
   const auto binary_opcode = static_cast<SpvOp>(message_.opcode());
@@ -238,7 +238,7 @@
 
   // The id use descriptor must identify some instruction
   auto instruction =
-      FindInstructionContainingUse(message_.id_use_descriptor(), context);
+      FindInstructionContainingUse(message_.id_use_descriptor(), ir_context);
   if (instruction == nullptr) {
     return false;
   }
@@ -262,24 +262,25 @@
 }
 
 void TransformationReplaceBooleanConstantWithConstantBinary::Apply(
-    opt::IRContext* context, FactManager* fact_manager) const {
-  ApplyWithResult(context, fact_manager);
+    opt::IRContext* ir_context,
+    TransformationContext* transformation_context) const {
+  ApplyWithResult(ir_context, transformation_context);
 }
 
 opt::Instruction*
 TransformationReplaceBooleanConstantWithConstantBinary::ApplyWithResult(
-    opt::IRContext* context, FactManager* /*unused*/) const {
+    opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
   opt::analysis::Bool bool_type;
   opt::Instruction::OperandList operands = {
       {SPV_OPERAND_TYPE_ID, {message_.lhs_id()}},
       {SPV_OPERAND_TYPE_ID, {message_.rhs_id()}}};
   auto binary_instruction = MakeUnique<opt::Instruction>(
-      context, static_cast<SpvOp>(message_.opcode()),
-      context->get_type_mgr()->GetId(&bool_type),
+      ir_context, static_cast<SpvOp>(message_.opcode()),
+      ir_context->get_type_mgr()->GetId(&bool_type),
       message_.fresh_id_for_binary_operation(), operands);
   opt::Instruction* result = binary_instruction.get();
   auto instruction_containing_constant_use =
-      FindInstructionContainingUse(message_.id_use_descriptor(), context);
+      FindInstructionContainingUse(message_.id_use_descriptor(), ir_context);
 
   // We want to insert the new instruction before the instruction that contains
   // the use of the boolean, but we need to go backwards one more instruction if
@@ -298,9 +299,10 @@
   instruction_containing_constant_use->SetInOperand(
       message_.id_use_descriptor().in_operand_index(),
       {message_.fresh_id_for_binary_operation()});
-  fuzzerutil::UpdateModuleIdBound(context,
+  fuzzerutil::UpdateModuleIdBound(ir_context,
                                   message_.fresh_id_for_binary_operation());
-  context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(
+      opt::IRContext::Analysis::kAnalysisNone);
   return result;
 }
 
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_replace_boolean_constant_with_constant_binary.h b/third_party/spirv-tools/src/source/fuzz/transformation_replace_boolean_constant_with_constant_binary.h
index f74cd8d..3abb485 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_replace_boolean_constant_with_constant_binary.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_replace_boolean_constant_with_constant_binary.h
@@ -15,9 +15,9 @@
 #ifndef SOURCE_FUZZ_TRANSFORMATION_REPLACE_BOOLEAN_CONSTANT_WITH_CONSTANT_BINARY_H_
 #define SOURCE_FUZZ_TRANSFORMATION_REPLACE_BOOLEAN_CONSTANT_WITH_CONSTANT_BINARY_H_
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -49,20 +49,23 @@
   //   TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/2902): consider
   //    replacing a boolean in an OpPhi by adding a binary operator instruction
   //    to the parent block for the OpPhi.
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // A new instruction is added before the boolean constant usage that computes
   // the result of applying |message_.opcode| to |message_.lhs_id| and
   // |message_.rhs_id| is added, with result id
   // |message_.fresh_id_for_binary_operation|.  The boolean constant usage is
   // replaced with this result id.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   // The same as Apply, except that the newly-added binary instruction is
   // returned.
-  opt::Instruction* ApplyWithResult(opt::IRContext* context,
-                                    FactManager* fact_manager) const;
+  opt::Instruction* ApplyWithResult(
+      opt::IRContext* ir_context,
+      TransformationContext* transformation_context) const;
 
   protobufs::Transformation ToMessage() const override;
 
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_replace_constant_with_uniform.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_replace_constant_with_uniform.cpp
index 8e0e4e5..a8f9495 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_replace_constant_with_uniform.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_replace_constant_with_uniform.cpp
@@ -39,12 +39,12 @@
 
 std::unique_ptr<opt::Instruction>
 TransformationReplaceConstantWithUniform::MakeAccessChainInstruction(
-    spvtools::opt::IRContext* context, uint32_t constant_type_id) const {
+    spvtools::opt::IRContext* ir_context, uint32_t constant_type_id) const {
   // The input operands for the access chain.
   opt::Instruction::OperandList operands_for_access_chain;
 
   opt::Instruction* uniform_variable =
-      FindUniformVariable(message_.uniform_descriptor(), context, false);
+      FindUniformVariable(message_.uniform_descriptor(), ir_context, false);
 
   // The first input operand is the id of the uniform variable.
   operands_for_access_chain.push_back(
@@ -56,42 +56,43 @@
   // instruction ids as operands.
   opt::analysis::Integer int_type(32, true);
   auto registered_int_type =
-      context->get_type_mgr()->GetRegisteredType(&int_type)->AsInteger();
-  auto int_type_id = context->get_type_mgr()->GetId(&int_type);
+      ir_context->get_type_mgr()->GetRegisteredType(&int_type)->AsInteger();
+  auto int_type_id = ir_context->get_type_mgr()->GetId(&int_type);
   for (auto index : message_.uniform_descriptor().index()) {
     opt::analysis::IntConstant int_constant(registered_int_type, {index});
-    auto constant_id = context->get_constant_mgr()->FindDeclaredConstant(
+    auto constant_id = ir_context->get_constant_mgr()->FindDeclaredConstant(
         &int_constant, int_type_id);
     operands_for_access_chain.push_back({SPV_OPERAND_TYPE_ID, {constant_id}});
   }
 
   // The type id for the access chain is a uniform pointer with base type
   // matching the given constant id type.
-  auto type_and_pointer_type = context->get_type_mgr()->GetTypeAndPointerType(
-      constant_type_id, SpvStorageClassUniform);
+  auto type_and_pointer_type =
+      ir_context->get_type_mgr()->GetTypeAndPointerType(constant_type_id,
+                                                        SpvStorageClassUniform);
   assert(type_and_pointer_type.first != nullptr);
   assert(type_and_pointer_type.second != nullptr);
   auto pointer_to_uniform_constant_type_id =
-      context->get_type_mgr()->GetId(type_and_pointer_type.second.get());
+      ir_context->get_type_mgr()->GetId(type_and_pointer_type.second.get());
 
   return MakeUnique<opt::Instruction>(
-      context, SpvOpAccessChain, pointer_to_uniform_constant_type_id,
+      ir_context, SpvOpAccessChain, pointer_to_uniform_constant_type_id,
       message_.fresh_id_for_access_chain(), operands_for_access_chain);
 }
 
 std::unique_ptr<opt::Instruction>
 TransformationReplaceConstantWithUniform::MakeLoadInstruction(
-    spvtools::opt::IRContext* context, uint32_t constant_type_id) const {
+    spvtools::opt::IRContext* ir_context, uint32_t constant_type_id) const {
   opt::Instruction::OperandList operands_for_load = {
       {SPV_OPERAND_TYPE_ID, {message_.fresh_id_for_access_chain()}}};
-  return MakeUnique<opt::Instruction>(context, SpvOpLoad, constant_type_id,
+  return MakeUnique<opt::Instruction>(ir_context, SpvOpLoad, constant_type_id,
                                       message_.fresh_id_for_load(),
                                       operands_for_load);
 }
 
 bool TransformationReplaceConstantWithUniform::IsApplicable(
-    spvtools::opt::IRContext* context,
-    const spvtools::fuzz::FactManager& fact_manager) const {
+    opt::IRContext* ir_context,
+    const TransformationContext& transformation_context) const {
   // The following is really an invariant of the transformation rather than
   // merely a requirement of the precondition.  We check it here since we cannot
   // check it in the message_ constructor.
@@ -99,16 +100,17 @@
          "Fresh ids for access chain and load result cannot be the same.");
 
   // The ids for the access chain and load instructions must both be fresh.
-  if (!fuzzerutil::IsFreshId(context, message_.fresh_id_for_access_chain())) {
+  if (!fuzzerutil::IsFreshId(ir_context,
+                             message_.fresh_id_for_access_chain())) {
     return false;
   }
-  if (!fuzzerutil::IsFreshId(context, message_.fresh_id_for_load())) {
+  if (!fuzzerutil::IsFreshId(ir_context, message_.fresh_id_for_load())) {
     return false;
   }
 
   // The id specified in the id use descriptor must be that of a declared scalar
   // constant.
-  auto declared_constant = context->get_constant_mgr()->FindDeclaredConstant(
+  auto declared_constant = ir_context->get_constant_mgr()->FindDeclaredConstant(
       message_.id_use_descriptor().id_of_interest());
   if (!declared_constant) {
     return false;
@@ -120,13 +122,13 @@
   // The fact manager needs to believe that the uniform data element described
   // by the uniform buffer element descriptor will hold a scalar value.
   auto constant_id_associated_with_uniform =
-      fact_manager.GetConstantFromUniformDescriptor(
-          context, message_.uniform_descriptor());
+      transformation_context.GetFactManager()->GetConstantFromUniformDescriptor(
+          ir_context, message_.uniform_descriptor());
   if (!constant_id_associated_with_uniform) {
     return false;
   }
   auto constant_associated_with_uniform =
-      context->get_constant_mgr()->FindDeclaredConstant(
+      ir_context->get_constant_mgr()->FindDeclaredConstant(
           constant_id_associated_with_uniform);
   assert(constant_associated_with_uniform &&
          "The constant should be present in the module.");
@@ -149,7 +151,7 @@
   // The id use descriptor must identify some instruction with respect to the
   // module.
   auto instruction_using_constant =
-      FindInstructionContainingUse(message_.id_use_descriptor(), context);
+      FindInstructionContainingUse(message_.id_use_descriptor(), ir_context);
   if (!instruction_using_constant) {
     return false;
   }
@@ -165,23 +167,23 @@
   // replace with a uniform.
   opt::analysis::Pointer pointer_to_type_of_constant(declared_constant->type(),
                                                      SpvStorageClassUniform);
-  if (!context->get_type_mgr()->GetId(&pointer_to_type_of_constant)) {
+  if (!ir_context->get_type_mgr()->GetId(&pointer_to_type_of_constant)) {
     return false;
   }
 
   // In order to index into the uniform, the module has got to contain the int32
   // type, plus an OpConstant for each of the indices of interest.
   opt::analysis::Integer int_type(32, true);
-  if (!context->get_type_mgr()->GetId(&int_type)) {
+  if (!ir_context->get_type_mgr()->GetId(&int_type)) {
     return false;
   }
   auto registered_int_type =
-      context->get_type_mgr()->GetRegisteredType(&int_type)->AsInteger();
-  auto int_type_id = context->get_type_mgr()->GetId(&int_type);
+      ir_context->get_type_mgr()->GetRegisteredType(&int_type)->AsInteger();
+  auto int_type_id = ir_context->get_type_mgr()->GetId(&int_type);
   for (auto index : message_.uniform_descriptor().index()) {
     opt::analysis::IntConstant int_constant(registered_int_type, {index});
-    if (!context->get_constant_mgr()->FindDeclaredConstant(&int_constant,
-                                                           int_type_id)) {
+    if (!ir_context->get_constant_mgr()->FindDeclaredConstant(&int_constant,
+                                                              int_type_id)) {
       return false;
     }
   }
@@ -190,11 +192,11 @@
 }
 
 void TransformationReplaceConstantWithUniform::Apply(
-    spvtools::opt::IRContext* context,
-    spvtools::fuzz::FactManager* /*unused*/) const {
+    spvtools::opt::IRContext* ir_context,
+    TransformationContext* /*unused*/) const {
   // Get the instruction that contains the id use we wish to replace.
   auto instruction_containing_constant_use =
-      FindInstructionContainingUse(message_.id_use_descriptor(), context);
+      FindInstructionContainingUse(message_.id_use_descriptor(), ir_context);
   assert(instruction_containing_constant_use &&
          "Precondition requires that the id use can be found.");
   assert(instruction_containing_constant_use->GetSingleWordInOperand(
@@ -204,17 +206,17 @@
 
   // The id of the type for the constant whose use we wish to replace.
   auto constant_type_id =
-      context->get_def_use_mgr()
+      ir_context->get_def_use_mgr()
           ->GetDef(message_.id_use_descriptor().id_of_interest())
           ->type_id();
 
   // Add an access chain instruction to target the uniform element.
   instruction_containing_constant_use->InsertBefore(
-      MakeAccessChainInstruction(context, constant_type_id));
+      MakeAccessChainInstruction(ir_context, constant_type_id));
 
   // Add a load from this access chain.
   instruction_containing_constant_use->InsertBefore(
-      MakeLoadInstruction(context, constant_type_id));
+      MakeLoadInstruction(ir_context, constant_type_id));
 
   // Adjust the instruction containing the usage of the constant so that this
   // usage refers instead to the result of the load.
@@ -223,11 +225,12 @@
       {message_.fresh_id_for_load()});
 
   // Update the module id bound to reflect the new instructions.
-  fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id_for_load());
-  fuzzerutil::UpdateModuleIdBound(context,
+  fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id_for_load());
+  fuzzerutil::UpdateModuleIdBound(ir_context,
                                   message_.fresh_id_for_access_chain());
 
-  context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(
+      opt::IRContext::Analysis::kAnalysisNone);
 }
 
 protobufs::Transformation TransformationReplaceConstantWithUniform::ToMessage()
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_replace_constant_with_uniform.h b/third_party/spirv-tools/src/source/fuzz/transformation_replace_constant_with_uniform.h
index ed354b1..b72407c 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_replace_constant_with_uniform.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_replace_constant_with_uniform.h
@@ -58,8 +58,9 @@
   //     - According to the fact manager, the uniform data element specified by
   //       |message_.uniform_descriptor| holds a value with the same type and
   //       value as %C
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // - Introduces two new instructions:
   //   - An access chain targeting the uniform data element specified by
@@ -68,7 +69,8 @@
   //   - A load from this access chain, with id |message_.fresh_id_for_load|
   // - Replaces the id use specified by |message_.id_use_descriptor| with
   //   |message_.fresh_id_for_load|
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
@@ -76,11 +78,11 @@
   // Helper method to create an access chain for the uniform element associated
   // with the transformation.
   std::unique_ptr<opt::Instruction> MakeAccessChainInstruction(
-      spvtools::opt::IRContext* context, uint32_t constant_type_id) const;
+      spvtools::opt::IRContext* ir_context, uint32_t constant_type_id) const;
 
   // Helper to create a load instruction.
   std::unique_ptr<opt::Instruction> MakeLoadInstruction(
-      spvtools::opt::IRContext* context, uint32_t constant_type_id) const;
+      spvtools::opt::IRContext* ir_context, uint32_t constant_type_id) const;
 
   protobufs::TransformationReplaceConstantWithUniform message_;
 };
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_replace_id_with_synonym.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_replace_id_with_synonym.cpp
index 88c977a..3a10682 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_replace_id_with_synonym.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_replace_id_with_synonym.cpp
@@ -37,28 +37,29 @@
 }
 
 bool TransformationReplaceIdWithSynonym::IsApplicable(
-    spvtools::opt::IRContext* context,
-    const spvtools::fuzz::FactManager& fact_manager) const {
+    opt::IRContext* ir_context,
+    const TransformationContext& transformation_context) const {
   auto id_of_interest = message_.id_use_descriptor().id_of_interest();
 
   // Does the fact manager know about the synonym?
   auto data_descriptor_for_synonymous_id =
       MakeDataDescriptor(message_.synonymous_id(), {});
-  if (!fact_manager.IsSynonymous(MakeDataDescriptor(id_of_interest, {}),
-                                 data_descriptor_for_synonymous_id, context)) {
+  if (!transformation_context.GetFactManager()->IsSynonymous(
+          MakeDataDescriptor(id_of_interest, {}),
+          data_descriptor_for_synonymous_id)) {
     return false;
   }
 
   // Does the id use descriptor in the transformation identify an instruction?
   auto use_instruction =
-      FindInstructionContainingUse(message_.id_use_descriptor(), context);
+      FindInstructionContainingUse(message_.id_use_descriptor(), ir_context);
   if (!use_instruction) {
     return false;
   }
 
   // Is the use suitable for being replaced in principle?
   if (!UseCanBeReplacedWithSynonym(
-          context, use_instruction,
+          ir_context, use_instruction,
           message_.id_use_descriptor().in_operand_index())) {
     return false;
   }
@@ -66,19 +67,21 @@
   // The transformation is applicable if the synonymous id is available at the
   // use point.
   return fuzzerutil::IdIsAvailableAtUse(
-      context, use_instruction, message_.id_use_descriptor().in_operand_index(),
+      ir_context, use_instruction,
+      message_.id_use_descriptor().in_operand_index(),
       message_.synonymous_id());
 }
 
 void TransformationReplaceIdWithSynonym::Apply(
-    spvtools::opt::IRContext* context,
-    spvtools::fuzz::FactManager* /*unused*/) const {
+    spvtools::opt::IRContext* ir_context,
+    TransformationContext* /*unused*/) const {
   auto instruction_to_change =
-      FindInstructionContainingUse(message_.id_use_descriptor(), context);
+      FindInstructionContainingUse(message_.id_use_descriptor(), ir_context);
   instruction_to_change->SetInOperand(
       message_.id_use_descriptor().in_operand_index(),
       {message_.synonymous_id()});
-  context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(
+      opt::IRContext::Analysis::kAnalysisNone);
 }
 
 protobufs::Transformation TransformationReplaceIdWithSynonym::ToMessage()
@@ -89,7 +92,7 @@
 }
 
 bool TransformationReplaceIdWithSynonym::UseCanBeReplacedWithSynonym(
-    opt::IRContext* context, opt::Instruction* use_instruction,
+    opt::IRContext* ir_context, opt::Instruction* use_instruction,
     uint32_t use_in_operand_index) {
   if (use_instruction->opcode() == SpvOpAccessChain &&
       use_in_operand_index > 0) {
@@ -98,10 +101,10 @@
     // synonym, as the use needs to be an OpConstant.
 
     // Get the top-level composite type that is being accessed.
-    auto object_being_accessed = context->get_def_use_mgr()->GetDef(
+    auto object_being_accessed = ir_context->get_def_use_mgr()->GetDef(
         use_instruction->GetSingleWordInOperand(0));
     auto pointer_type =
-        context->get_type_mgr()->GetType(object_being_accessed->type_id());
+        ir_context->get_type_mgr()->GetType(object_being_accessed->type_id());
     assert(pointer_type->AsPointer());
     auto composite_type_being_accessed =
         pointer_type->AsPointer()->pointee_type();
@@ -122,9 +125,12 @@
       } else if (composite_type_being_accessed->AsArray()) {
         composite_type_being_accessed =
             composite_type_being_accessed->AsArray()->element_type();
+      } else if (composite_type_being_accessed->AsRuntimeArray()) {
+        composite_type_being_accessed =
+            composite_type_being_accessed->AsRuntimeArray()->element_type();
       } else {
         assert(composite_type_being_accessed->AsStruct());
-        auto constant_index_instruction = context->get_def_use_mgr()->GetDef(
+        auto constant_index_instruction = ir_context->get_def_use_mgr()->GetDef(
             use_instruction->GetSingleWordInOperand(index_in_operand));
         assert(constant_index_instruction->opcode() == SpvOpConstant);
         uint32_t member_index =
@@ -149,16 +155,16 @@
     // type.
 
     // Get the definition of the function being called.
-    auto function = context->get_def_use_mgr()->GetDef(
+    auto function = ir_context->get_def_use_mgr()->GetDef(
         use_instruction->GetSingleWordInOperand(0));
     // From the function definition, get the function type.
-    auto function_type =
-        context->get_def_use_mgr()->GetDef(function->GetSingleWordInOperand(1));
+    auto function_type = ir_context->get_def_use_mgr()->GetDef(
+        function->GetSingleWordInOperand(1));
     // OpTypeFunction's 0-th input operand is the function return type, and the
     // function argument types follow. Because the arguments to OpFunctionCall
     // start from input operand 1, we can use |use_in_operand_index| to get the
     // type associated with this function argument.
-    auto parameter_type = context->get_type_mgr()->GetType(
+    auto parameter_type = ir_context->get_type_mgr()->GetType(
         function_type->GetSingleWordInOperand(use_in_operand_index));
     if (parameter_type->AsPointer()) {
       return false;
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_replace_id_with_synonym.h b/third_party/spirv-tools/src/source/fuzz/transformation_replace_id_with_synonym.h
index 48132c1..a5a9dfd 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_replace_id_with_synonym.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_replace_id_with_synonym.h
@@ -15,9 +15,9 @@
 #ifndef SOURCE_FUZZ_TRANSFORMATION_REPLACE_ID_WITH_SYNONYM_H_
 #define SOURCE_FUZZ_TRANSFORMATION_REPLACE_ID_WITH_SYNONYM_H_
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -42,12 +42,14 @@
   // - The id must not be a pointer argument to a function call (because the
   //   synonym might not be a memory object declaration).
   // - |fresh_id_for_temporary| must be 0.
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // Replaces the use identified by |message_.id_use_descriptor| with the
   // synonymous id identified by |message_.synonymous_id|.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
@@ -58,7 +60,7 @@
   //   indices must be constants, so it is dangerous to replace them.
   // - the id use is not a pointer function call argument, on which there are
   //   restrictions that make replacement problematic.
-  static bool UseCanBeReplacedWithSynonym(opt::IRContext* context,
+  static bool UseCanBeReplacedWithSynonym(opt::IRContext* ir_context,
                                           opt::Instruction* use_instruction,
                                           uint32_t use_in_operand_index);
 
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_set_function_control.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_set_function_control.cpp
index d2b61f1..d01e743 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_set_function_control.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_set_function_control.cpp
@@ -28,9 +28,9 @@
 }
 
 bool TransformationSetFunctionControl::IsApplicable(
-    opt::IRContext* context, const FactManager& /*unused*/) const {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
   opt::Instruction* function_def_instruction =
-      FindFunctionDefInstruction(context);
+      FindFunctionDefInstruction(ir_context);
   if (!function_def_instruction) {
     // The given function id does not correspond to any function.
     return false;
@@ -69,10 +69,10 @@
   return true;
 }
 
-void TransformationSetFunctionControl::Apply(opt::IRContext* context,
-                                             FactManager* /*unused*/) const {
+void TransformationSetFunctionControl::Apply(
+    opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
   opt::Instruction* function_def_instruction =
-      FindFunctionDefInstruction(context);
+      FindFunctionDefInstruction(ir_context);
   function_def_instruction->SetInOperand(0, {message_.function_control()});
 }
 
@@ -83,11 +83,11 @@
 }
 
 opt::Instruction* TransformationSetFunctionControl ::FindFunctionDefInstruction(
-    opt::IRContext* context) const {
+    opt::IRContext* ir_context) const {
   // Look through all functions for a function whose defining instruction's
   // result id matches |message_.function_id|, returning the defining
   // instruction if found.
-  for (auto& function : *context->module()) {
+  for (auto& function : *ir_context->module()) {
     if (function.DefInst().result_id() == message_.function_id()) {
       return &function.DefInst();
     }
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_set_function_control.h b/third_party/spirv-tools/src/source/fuzz/transformation_set_function_control.h
index 0526bb9..5109f74 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_set_function_control.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_set_function_control.h
@@ -15,9 +15,9 @@
 #ifndef SOURCE_FUZZ_TRANSFORMATION_SET_FUNCTION_CONTROL_H_
 #define SOURCE_FUZZ_TRANSFORMATION_SET_FUNCTION_CONTROL_H_
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -37,17 +37,20 @@
   //   at most one of 'Inline' or 'DontInline', and that may not contain 'Pure'
   //   (respectively 'Const') unless the existing function control mask contains
   //   'Pure' (respectively 'Const').
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // The function control operand of instruction |message_.function_id| is
   // over-written with |message_.function_control|.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
  private:
-  opt::Instruction* FindFunctionDefInstruction(opt::IRContext* context) const;
+  opt::Instruction* FindFunctionDefInstruction(
+      opt::IRContext* ir_context) const;
 
   protobufs::TransformationSetFunctionControl message_;
 };
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_set_loop_control.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_set_loop_control.cpp
index 9062f17..845ac69 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_set_loop_control.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_set_loop_control.cpp
@@ -31,9 +31,9 @@
 }
 
 bool TransformationSetLoopControl::IsApplicable(
-    opt::IRContext* context, const FactManager& /*unused*/) const {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
   // |message_.block_id| must identify a block that ends with OpLoopMerge.
-  auto block = context->get_instr_block(message_.block_id());
+  auto block = ir_context->get_instr_block(message_.block_id());
   if (!block) {
     return false;
   }
@@ -79,7 +79,8 @@
 
   if ((message_.loop_control() &
        (SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask)) &&
-      !(PeelCountIsSupported(context) && PartialCountIsSupported(context))) {
+      !(PeelCountIsSupported(ir_context) &&
+        PartialCountIsSupported(ir_context))) {
     // At least one of PeelCount or PartialCount is used, but the SPIR-V version
     // in question does not support these loop controls.
     return false;
@@ -104,11 +105,11 @@
             (SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask)));
 }
 
-void TransformationSetLoopControl::Apply(opt::IRContext* context,
-                                         FactManager* /*unused*/) const {
+void TransformationSetLoopControl::Apply(
+    opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
   // Grab the loop merge instruction and its associated loop control mask.
   auto merge_inst =
-      context->get_instr_block(message_.block_id())->GetMergeInst();
+      ir_context->get_instr_block(message_.block_id())->GetMergeInst();
   auto existing_loop_control_mask =
       merge_inst->GetSingleWordInOperand(kLoopControlMaskInOperandIndex);
 
@@ -181,11 +182,11 @@
 }
 
 bool TransformationSetLoopControl::PartialCountIsSupported(
-    opt::IRContext* context) {
+    opt::IRContext* ir_context) {
   // TODO(afd): We capture the universal environments for which this loop
   //  control is definitely not supported.  The check should be refined on
   //  demand for other target environments.
-  switch (context->grammar().target_env()) {
+  switch (ir_context->grammar().target_env()) {
     case SPV_ENV_UNIVERSAL_1_0:
     case SPV_ENV_UNIVERSAL_1_1:
     case SPV_ENV_UNIVERSAL_1_2:
@@ -197,11 +198,11 @@
 }
 
 bool TransformationSetLoopControl::PeelCountIsSupported(
-    opt::IRContext* context) {
+    opt::IRContext* ir_context) {
   // TODO(afd): We capture the universal environments for which this loop
   //  control is definitely not supported.  The check should be refined on
   //  demand for other target environments.
-  switch (context->grammar().target_env()) {
+  switch (ir_context->grammar().target_env()) {
     case SPV_ENV_UNIVERSAL_1_0:
     case SPV_ENV_UNIVERSAL_1_1:
     case SPV_ENV_UNIVERSAL_1_2:
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_set_loop_control.h b/third_party/spirv-tools/src/source/fuzz/transformation_set_loop_control.h
index 28b148c..f0c364f 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_set_loop_control.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_set_loop_control.h
@@ -15,9 +15,9 @@
 #ifndef SOURCE_FUZZ_TRANSFORMATION_SET_LOOP_CONTROL_H_
 #define SOURCE_FUZZ_TRANSFORMATION_SET_LOOP_CONTROL_H_
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -38,13 +38,14 @@
   //   instruction.
   // - |message_.loop_control| must be a legal loop control mask that
   //   only uses controls available in the SPIR-V version associated with
-  //   |context|, and must not add loop controls that are only valid in the
+  //   |ir_context|, and must not add loop controls that are only valid in the
   //   presence of guarantees about what the loop does (e.g. MinIterations).
   // - |message_.peel_count| (respectively |message_.partial_count|) must be
   //   zero PeelCount (respectively PartialCount) is set in
   //   |message_.loop_control|.
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // - The loop control operand of the OpLoopMergeInstruction in
   //   |message_.block_id| is overwritten with |message_.loop_control|.
@@ -52,16 +53,17 @@
   //   controls with associated literals that have been removed (e.g.
   //   MinIterations), and any that have been added (PeelCount and/or
   //   PartialCount).
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
   // Does the version of SPIR-V being used support the PartialCount loop
   // control?
-  static bool PartialCountIsSupported(opt::IRContext* context);
+  static bool PartialCountIsSupported(opt::IRContext* ir_context);
 
   // Does the version of SPIR-V being used support the PeelCount loop control?
-  static bool PeelCountIsSupported(opt::IRContext* context);
+  static bool PeelCountIsSupported(opt::IRContext* ir_context);
 
  private:
   // Returns true if and only if |loop_single_bit_mask| is *not* set in
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_set_memory_operands_mask.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_set_memory_operands_mask.cpp
index a14e1a6..131a499 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_set_memory_operands_mask.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_set_memory_operands_mask.cpp
@@ -42,8 +42,7 @@
 }
 
 bool TransformationSetMemoryOperandsMask::IsApplicable(
-    opt::IRContext* context,
-    const spvtools::fuzz::FactManager& /*unused*/) const {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
   if (message_.memory_operands_mask_index() != 0) {
     // The following conditions should never be violated, even if
     // transformations end up being replayed in a different way to the manner in
@@ -54,11 +53,11 @@
                SpvOpCopyMemory ||
            message_.memory_access_instruction().target_instruction_opcode() ==
                SpvOpCopyMemorySized);
-    assert(MultipleMemoryOperandMasksAreSupported(context));
+    assert(MultipleMemoryOperandMasksAreSupported(ir_context));
   }
 
   auto instruction =
-      FindInstruction(message_.memory_access_instruction(), context);
+      FindInstruction(message_.memory_access_instruction(), ir_context);
   if (!instruction) {
     return false;
   }
@@ -94,9 +93,9 @@
 }
 
 void TransformationSetMemoryOperandsMask::Apply(
-    opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/) const {
+    opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
   auto instruction =
-      FindInstruction(message_.memory_access_instruction(), context);
+      FindInstruction(message_.memory_access_instruction(), ir_context);
   auto original_mask_in_operand_index = GetInOperandIndexForMask(
       *instruction, message_.memory_operands_mask_index());
   // Either add a new operand, if no mask operand was already present, or
@@ -182,11 +181,11 @@
 }
 
 bool TransformationSetMemoryOperandsMask::
-    MultipleMemoryOperandMasksAreSupported(opt::IRContext* context) {
+    MultipleMemoryOperandMasksAreSupported(opt::IRContext* ir_context) {
   // TODO(afd): We capture the universal environments for which this loop
   //  control is definitely not supported.  The check should be refined on
   //  demand for other target environments.
-  switch (context->grammar().target_env()) {
+  switch (ir_context->grammar().target_env()) {
     case SPV_ENV_UNIVERSAL_1_0:
     case SPV_ENV_UNIVERSAL_1_1:
     case SPV_ENV_UNIVERSAL_1_2:
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_set_memory_operands_mask.h b/third_party/spirv-tools/src/source/fuzz/transformation_set_memory_operands_mask.h
index 20ae145..9f5081b 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_set_memory_operands_mask.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_set_memory_operands_mask.h
@@ -15,9 +15,9 @@
 #ifndef SOURCE_FUZZ_TRANSFORMATION_SET_MEMORY_OPERANDS_MASK_H_
 #define SOURCE_FUZZ_TRANSFORMATION_SET_MEMORY_OPERANDS_MASK_H_
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -40,14 +40,16 @@
   // - |message_.memory_operands_mask| must be identical to the original memory
   //   operands mask, except that Volatile may be added, and Nontemporal may be
   //   toggled.
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // Replaces the operands mask identified by
   // |message_.memory_operands_mask_index| in the instruction described by
   // |message_.memory_access_instruction| with |message_.memory_operands_mask|,
   // creating an input operand for the mask if no such operand was present.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
@@ -57,7 +59,8 @@
 
   // Does the version of SPIR-V being used support multiple memory operand
   // masks on relevant memory access instructions?
-  static bool MultipleMemoryOperandMasksAreSupported(opt::IRContext* context);
+  static bool MultipleMemoryOperandMasksAreSupported(
+      opt::IRContext* ir_context);
 
   // Helper function to get the input operand index associated with mask number
   // |mask_index|. This is a bit tricky if there are multiple masks, because the
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_set_selection_control.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_set_selection_control.cpp
index ebabdef..bee1e35 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_set_selection_control.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_set_selection_control.cpp
@@ -28,13 +28,13 @@
 }
 
 bool TransformationSetSelectionControl::IsApplicable(
-    opt::IRContext* context, const FactManager& /*unused*/) const {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
   assert((message_.selection_control() == SpvSelectionControlMaskNone ||
           message_.selection_control() == SpvSelectionControlFlattenMask ||
           message_.selection_control() == SpvSelectionControlDontFlattenMask) &&
          "Selection control should never be set to something other than "
          "'None', 'Flatten' or 'DontFlatten'");
-  if (auto block = context->get_instr_block(message_.block_id())) {
+  if (auto block = ir_context->get_instr_block(message_.block_id())) {
     if (auto merge_inst = block->GetMergeInst()) {
       return merge_inst->opcode() == SpvOpSelectionMerge;
     }
@@ -43,9 +43,9 @@
   return false;
 }
 
-void TransformationSetSelectionControl::Apply(opt::IRContext* context,
-                                              FactManager* /*unused*/) const {
-  context->get_instr_block(message_.block_id())
+void TransformationSetSelectionControl::Apply(
+    opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
+  ir_context->get_instr_block(message_.block_id())
       ->GetMergeInst()
       ->SetInOperand(1, {message_.selection_control()});
 }
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_set_selection_control.h b/third_party/spirv-tools/src/source/fuzz/transformation_set_selection_control.h
index 19e0c3c..21fbdda 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_set_selection_control.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_set_selection_control.h
@@ -15,9 +15,9 @@
 #ifndef SOURCE_FUZZ_TRANSFORMATION_SET_SELECTION_CONTROL_H_
 #define SOURCE_FUZZ_TRANSFORMATION_SET_SELECTION_CONTROL_H_
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -35,12 +35,14 @@
   //   instruction.
   // - |message_.selection_control| must be one of None, Flatten or
   //   DontFlatten.
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // - The selection control operand of the OpSelectionMergeInstruction in
   //   |message_.block_id| is overwritten with |message_.selection_control|.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_split_block.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_split_block.cpp
index fc5229e..b020d98 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_split_block.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_split_block.cpp
@@ -35,18 +35,19 @@
 }
 
 bool TransformationSplitBlock::IsApplicable(
-    opt::IRContext* context, const FactManager& /*unused*/) const {
-  if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
+  if (!fuzzerutil::IsFreshId(ir_context, message_.fresh_id())) {
     // We require the id for the new block to be unused.
     return false;
   }
   auto instruction_to_split_before =
-      FindInstruction(message_.instruction_to_split_before(), context);
+      FindInstruction(message_.instruction_to_split_before(), ir_context);
   if (!instruction_to_split_before) {
     // The instruction describing the block we should split does not exist.
     return false;
   }
-  auto block_to_split = context->get_instr_block(instruction_to_split_before);
+  auto block_to_split =
+      ir_context->get_instr_block(instruction_to_split_before);
   assert(block_to_split &&
          "We should not have managed to find the "
          "instruction if it was not contained in a block.");
@@ -75,16 +76,43 @@
   }
   // We cannot split before an OpPhi unless the OpPhi has exactly one
   // associated incoming edge.
-  return !(split_before->opcode() == SpvOpPhi &&
-           split_before->NumInOperands() != 2);
+  if (split_before->opcode() == SpvOpPhi &&
+      split_before->NumInOperands() != 2) {
+    return false;
+  }
+
+  // Splitting the block must not separate the definition of an OpSampledImage
+  // from its use: the SPIR-V data rules require them to be in the same block.
+  std::set<uint32_t> sampled_image_result_ids;
+  bool before_split = true;
+  for (auto& instruction : *block_to_split) {
+    if (&instruction == &*split_before) {
+      before_split = false;
+    }
+    if (before_split) {
+      if (instruction.opcode() == SpvOpSampledImage) {
+        sampled_image_result_ids.insert(instruction.result_id());
+      }
+    } else {
+      if (!instruction.WhileEachInId(
+              [&sampled_image_result_ids](uint32_t* id) -> bool {
+                return !sampled_image_result_ids.count(*id);
+              })) {
+        return false;
+      }
+    }
+  }
+
+  return true;
 }
 
-void TransformationSplitBlock::Apply(opt::IRContext* context,
-                                     FactManager* fact_manager) const {
+void TransformationSplitBlock::Apply(
+    opt::IRContext* ir_context,
+    TransformationContext* transformation_context) const {
   opt::Instruction* instruction_to_split_before =
-      FindInstruction(message_.instruction_to_split_before(), context);
+      FindInstruction(message_.instruction_to_split_before(), ir_context);
   opt::BasicBlock* block_to_split =
-      context->get_instr_block(instruction_to_split_before);
+      ir_context->get_instr_block(instruction_to_split_before);
   auto split_before = fuzzerutil::GetIteratorForInstruction(
       block_to_split, instruction_to_split_before);
   assert(split_before != block_to_split->end() &&
@@ -93,14 +121,14 @@
 
   // We need to make sure the module's id bound is large enough to add the
   // fresh id.
-  fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
+  fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
   // Split the block.
-  auto new_bb = block_to_split->SplitBasicBlock(context, message_.fresh_id(),
+  auto new_bb = block_to_split->SplitBasicBlock(ir_context, message_.fresh_id(),
                                                 split_before);
   // The split does not automatically add a branch between the two parts of
   // the original block, so we add one.
   block_to_split->AddInstruction(MakeUnique<opt::Instruction>(
-      context, SpvOpBranch, 0, 0,
+      ir_context, SpvOpBranch, 0, 0,
       std::initializer_list<opt::Operand>{opt::Operand(
           spv_operand_type_t::SPV_OPERAND_TYPE_ID, {message_.fresh_id()})}));
   // If we split before OpPhi instructions, we need to update their
@@ -117,12 +145,15 @@
 
   // If the block being split was dead, the new block arising from the split is
   // also dead.
-  if (fact_manager->BlockIsDead(block_to_split->id())) {
-    fact_manager->AddFactBlockIsDead(message_.fresh_id());
+  if (transformation_context->GetFactManager()->BlockIsDead(
+          block_to_split->id())) {
+    transformation_context->GetFactManager()->AddFactBlockIsDead(
+        message_.fresh_id());
   }
 
   // Invalidate all analyses
-  context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(
+      opt::IRContext::Analysis::kAnalysisNone);
 }
 
 protobufs::Transformation TransformationSplitBlock::ToMessage() const {
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_split_block.h b/third_party/spirv-tools/src/source/fuzz/transformation_split_block.h
index a193fc7..3bf6dfd 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_split_block.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_split_block.h
@@ -15,9 +15,9 @@
 #ifndef SOURCE_FUZZ_TRANSFORMATION_SPLIT_BLOCK_H_
 #define SOURCE_FUZZ_TRANSFORMATION_SPLIT_BLOCK_H_
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -40,8 +40,9 @@
   // - Splitting 'blk' at 'inst', so that all instructions from 'inst' onwards
   //   appear in a new block that 'blk' directly jumps to must be valid.
   // - |message_.fresh_id| must not be used by the module.
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // - A new block with label |message_.fresh_id| is inserted right after 'blk'
   //   in program order.
@@ -49,7 +50,8 @@
   //   block.
   // - 'blk' is made to jump unconditionally to the new block.
   // - If 'blk' was dead, the new block is also dead.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_store.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_store.cpp
index 7cb7611..3df1b7d 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_store.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_store.cpp
@@ -34,16 +34,16 @@
 }
 
 bool TransformationStore::IsApplicable(
-    opt::IRContext* context,
-    const spvtools::fuzz::FactManager& fact_manager) const {
+    opt::IRContext* ir_context,
+    const TransformationContext& transformation_context) const {
   // The pointer must exist and have a type.
-  auto pointer = context->get_def_use_mgr()->GetDef(message_.pointer_id());
+  auto pointer = ir_context->get_def_use_mgr()->GetDef(message_.pointer_id());
   if (!pointer || !pointer->type_id()) {
     return false;
   }
 
   // The pointer type must indeed be a pointer.
-  auto pointer_type = context->get_def_use_mgr()->GetDef(pointer->type_id());
+  auto pointer_type = ir_context->get_def_use_mgr()->GetDef(pointer->type_id());
   assert(pointer_type && "Type id must be defined.");
   if (pointer_type->opcode() != SpvOpTypePointer) {
     return false;
@@ -65,7 +65,7 @@
 
   // Determine which instruction we should be inserting before.
   auto insert_before =
-      FindInstruction(message_.instruction_to_insert_before(), context);
+      FindInstruction(message_.instruction_to_insert_before(), ir_context);
   // It must exist, ...
   if (!insert_before) {
     return false;
@@ -79,14 +79,15 @@
   // The block we are inserting into needs to be dead, or else the pointee type
   // of the pointer we are storing to needs to be irrelevant (otherwise the
   // store could impact on the observable behaviour of the module).
-  if (!fact_manager.BlockIsDead(
-          context->get_instr_block(insert_before)->id()) &&
-      !fact_manager.PointeeValueIsIrrelevant(message_.pointer_id())) {
+  if (!transformation_context.GetFactManager()->BlockIsDead(
+          ir_context->get_instr_block(insert_before)->id()) &&
+      !transformation_context.GetFactManager()->PointeeValueIsIrrelevant(
+          message_.pointer_id())) {
     return false;
   }
 
   // The value being stored needs to exist and have a type.
-  auto value = context->get_def_use_mgr()->GetDef(message_.value_id());
+  auto value = ir_context->get_def_use_mgr()->GetDef(message_.value_id());
   if (!value || !value->type_id()) {
     return false;
   }
@@ -97,25 +98,25 @@
   }
 
   // The pointer needs to be available at the insertion point.
-  if (!fuzzerutil::IdIsAvailableBeforeInstruction(context, insert_before,
+  if (!fuzzerutil::IdIsAvailableBeforeInstruction(ir_context, insert_before,
                                                   message_.pointer_id())) {
     return false;
   }
 
   // The value needs to be available at the insertion point.
-  return fuzzerutil::IdIsAvailableBeforeInstruction(context, insert_before,
+  return fuzzerutil::IdIsAvailableBeforeInstruction(ir_context, insert_before,
                                                     message_.value_id());
 }
 
-void TransformationStore::Apply(opt::IRContext* context,
-                                spvtools::fuzz::FactManager* /*unused*/) const {
-  FindInstruction(message_.instruction_to_insert_before(), context)
+void TransformationStore::Apply(opt::IRContext* ir_context,
+                                TransformationContext* /*unused*/) const {
+  FindInstruction(message_.instruction_to_insert_before(), ir_context)
       ->InsertBefore(MakeUnique<opt::Instruction>(
-          context, SpvOpStore, 0, 0,
+          ir_context, SpvOpStore, 0, 0,
           opt::Instruction::OperandList(
               {{SPV_OPERAND_TYPE_ID, {message_.pointer_id()}},
                {SPV_OPERAND_TYPE_ID, {message_.value_id()}}})));
-  context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
+  ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
 }
 
 protobufs::Transformation TransformationStore::ToMessage() const {
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_store.h b/third_party/spirv-tools/src/source/fuzz/transformation_store.h
index 699afdd..6746aab 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_store.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_store.h
@@ -15,9 +15,9 @@
 #ifndef SOURCE_FUZZ_TRANSFORMATION_STORE_H_
 #define SOURCE_FUZZ_TRANSFORMATION_STORE_H_
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -42,14 +42,16 @@
   //   to dominance rules)
   // - Either the insertion point must be in a dead block, or it must be known
   //   that the pointee value of |message_.pointer_id| is irrelevant
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // Adds an instruction of the form:
   //   OpStore |pointer_id| |value_id|
   // before the instruction identified by
   // |message_.instruction_to_insert_before|.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_swap_commutable_operands.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_swap_commutable_operands.cpp
index 49d9de8..b7622a2 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_swap_commutable_operands.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_swap_commutable_operands.cpp
@@ -31,10 +31,10 @@
 }
 
 bool TransformationSwapCommutableOperands::IsApplicable(
-    opt::IRContext* context, const spvtools::fuzz::FactManager& /*unused*/
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/
     ) const {
   auto instruction =
-      FindInstruction(message_.instruction_descriptor(), context);
+      FindInstruction(message_.instruction_descriptor(), ir_context);
   if (instruction == nullptr) return false;
 
   SpvOp opcode = static_cast<SpvOp>(
@@ -46,10 +46,10 @@
 }
 
 void TransformationSwapCommutableOperands::Apply(
-    opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/
+    opt::IRContext* ir_context, TransformationContext* /*unused*/
     ) const {
   auto instruction =
-      FindInstruction(message_.instruction_descriptor(), context);
+      FindInstruction(message_.instruction_descriptor(), ir_context);
   // By design, the instructions defined to be commutative have exactly two
   // input parameters.
   std::swap(instruction->GetInOperand(0), instruction->GetInOperand(1));
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_swap_commutable_operands.h b/third_party/spirv-tools/src/source/fuzz/transformation_swap_commutable_operands.h
index 061e92d..7fe5b70 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_swap_commutable_operands.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_swap_commutable_operands.h
@@ -15,9 +15,9 @@
 #ifndef SOURCE_FUZZ_TRANSFORMATION_SWAP_COMMUTABLE_OPERANDS_H_
 #define SOURCE_FUZZ_TRANSFORMATION_SWAP_COMMUTABLE_OPERANDS_H_
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -33,11 +33,13 @@
 
   // - |message_.instruction_descriptor| must identify an existing
   // commutative instruction
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // Swaps the commutable operands.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_toggle_access_chain_instruction.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_toggle_access_chain_instruction.cpp
index ace331a..ca24a18 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_toggle_access_chain_instruction.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_toggle_access_chain_instruction.cpp
@@ -33,10 +33,10 @@
 }
 
 bool TransformationToggleAccessChainInstruction::IsApplicable(
-    opt::IRContext* context, const spvtools::fuzz::FactManager& /*unused*/
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/
     ) const {
   auto instruction =
-      FindInstruction(message_.instruction_descriptor(), context);
+      FindInstruction(message_.instruction_descriptor(), ir_context);
   if (instruction == nullptr) {
     return false;
   }
@@ -56,10 +56,10 @@
 }
 
 void TransformationToggleAccessChainInstruction::Apply(
-    opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/
+    opt::IRContext* ir_context, TransformationContext* /*unused*/
     ) const {
   auto instruction =
-      FindInstruction(message_.instruction_descriptor(), context);
+      FindInstruction(message_.instruction_descriptor(), ir_context);
   SpvOp opcode = instruction->opcode();
 
   if (opcode == SpvOpAccessChain) {
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_toggle_access_chain_instruction.h b/third_party/spirv-tools/src/source/fuzz/transformation_toggle_access_chain_instruction.h
index 125e1ab..9cd8fd6 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_toggle_access_chain_instruction.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_toggle_access_chain_instruction.h
@@ -15,9 +15,9 @@
 #ifndef SOURCE_FUZZ_TRANSFORMATION_TOGGLE_ACCESS_CHAIN_INSTRUCTION_H_
 #define SOURCE_FUZZ_TRANSFORMATION_TOGGLE_ACCESS_CHAIN_INSTRUCTION_H_
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
 
 namespace spvtools {
@@ -33,11 +33,13 @@
 
   // - |message_.instruction_descriptor| must identify an existing
   //   access chain instruction
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // Toggles the access chain instruction.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_vector_shuffle.cpp b/third_party/spirv-tools/src/source/fuzz/transformation_vector_shuffle.cpp
index e2d889d..ee64292 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_vector_shuffle.cpp
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_vector_shuffle.cpp
@@ -39,38 +39,37 @@
 }
 
 bool TransformationVectorShuffle::IsApplicable(
-    opt::IRContext* context,
-    const spvtools::fuzz::FactManager& /*unused*/) const {
+    opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
   // The fresh id must not already be in use.
-  if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
+  if (!fuzzerutil::IsFreshId(ir_context, message_.fresh_id())) {
     return false;
   }
   // The instruction before which the shuffle will be inserted must exist.
   auto instruction_to_insert_before =
-      FindInstruction(message_.instruction_to_insert_before(), context);
+      FindInstruction(message_.instruction_to_insert_before(), ir_context);
   if (!instruction_to_insert_before) {
     return false;
   }
   // The first vector must be an instruction with a type id
   auto vector1_instruction =
-      context->get_def_use_mgr()->GetDef(message_.vector1());
+      ir_context->get_def_use_mgr()->GetDef(message_.vector1());
   if (!vector1_instruction || !vector1_instruction->type_id()) {
     return false;
   }
   // The second vector must be an instruction with a type id
   auto vector2_instruction =
-      context->get_def_use_mgr()->GetDef(message_.vector2());
+      ir_context->get_def_use_mgr()->GetDef(message_.vector2());
   if (!vector2_instruction || !vector2_instruction->type_id()) {
     return false;
   }
   auto vector1_type =
-      context->get_type_mgr()->GetType(vector1_instruction->type_id());
+      ir_context->get_type_mgr()->GetType(vector1_instruction->type_id());
   // The first vector instruction's type must actually be a vector type.
   if (!vector1_type->AsVector()) {
     return false;
   }
   auto vector2_type =
-      context->get_type_mgr()->GetType(vector2_instruction->type_id());
+      ir_context->get_type_mgr()->GetType(vector2_instruction->type_id());
   // The second vector instruction's type must actually be a vector type.
   if (!vector2_type->AsVector()) {
     return false;
@@ -92,14 +91,14 @@
   }
   // The module must already declare an appropriate type in which to store the
   // result of the shuffle.
-  if (!GetResultTypeId(context, *vector1_type->AsVector()->element_type())) {
+  if (!GetResultTypeId(ir_context, *vector1_type->AsVector()->element_type())) {
     return false;
   }
   // Each of the vectors used in the shuffle must be available at the insertion
   // point.
   for (auto used_instruction : {vector1_instruction, vector2_instruction}) {
-    if (auto block = context->get_instr_block(used_instruction)) {
-      if (!context->GetDominatorAnalysis(block->GetParent())
+    if (auto block = ir_context->get_instr_block(used_instruction)) {
+      if (!ir_context->GetDominatorAnalysis(block->GetParent())
                ->Dominates(used_instruction, instruction_to_insert_before)) {
         return false;
       }
@@ -113,7 +112,8 @@
 }
 
 void TransformationVectorShuffle::Apply(
-    opt::IRContext* context, spvtools::fuzz::FactManager* fact_manager) const {
+    opt::IRContext* ir_context,
+    TransformationContext* transformation_context) const {
   // Make input operands for a shuffle instruction - these comprise the two
   // vectors being shuffled, followed by the integer literal components.
   opt::Instruction::OperandList shuffle_operands = {
@@ -125,16 +125,18 @@
   }
 
   uint32_t result_type_id = GetResultTypeId(
-      context, *GetVectorType(context, message_.vector1())->element_type());
+      ir_context,
+      *GetVectorType(ir_context, message_.vector1())->element_type());
 
   // Add a shuffle instruction right before the instruction identified by
   // |message_.instruction_to_insert_before|.
-  FindInstruction(message_.instruction_to_insert_before(), context)
+  FindInstruction(message_.instruction_to_insert_before(), ir_context)
       ->InsertBefore(MakeUnique<opt::Instruction>(
-          context, SpvOpVectorShuffle, result_type_id, message_.fresh_id(),
+          ir_context, SpvOpVectorShuffle, result_type_id, message_.fresh_id(),
           shuffle_operands));
-  fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
-  context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
+  fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
+  ir_context->InvalidateAnalysesExceptFor(
+      opt::IRContext::Analysis::kAnalysisNone);
 
   // Add synonym facts relating the defined elements of the shuffle result to
   // the vector components that they come from.
@@ -158,24 +160,26 @@
     // Get a data descriptor for the component of the input vector to which
     // |component| refers.
     if (component <
-        GetVectorType(context, message_.vector1())->element_count()) {
+        GetVectorType(ir_context, message_.vector1())->element_count()) {
       descriptor_for_source_component =
           MakeDataDescriptor(message_.vector1(), {component});
     } else {
       auto index_into_vector_2 =
           component -
-          GetVectorType(context, message_.vector1())->element_count();
-      assert(index_into_vector_2 <
-                 GetVectorType(context, message_.vector2())->element_count() &&
-             "Vector shuffle index is out of bounds.");
+          GetVectorType(ir_context, message_.vector1())->element_count();
+      assert(
+          index_into_vector_2 <
+              GetVectorType(ir_context, message_.vector2())->element_count() &&
+          "Vector shuffle index is out of bounds.");
       descriptor_for_source_component =
           MakeDataDescriptor(message_.vector2(), {index_into_vector_2});
     }
 
     // Add a fact relating this input vector component with the associated
     // result component.
-    fact_manager->AddFactDataSynonym(descriptor_for_result_component,
-                                     descriptor_for_source_component, context);
+    transformation_context->GetFactManager()->AddFactDataSynonym(
+        descriptor_for_result_component, descriptor_for_source_component,
+        ir_context);
   }
 }
 
@@ -186,16 +190,16 @@
 }
 
 uint32_t TransformationVectorShuffle::GetResultTypeId(
-    opt::IRContext* context, const opt::analysis::Type& element_type) const {
+    opt::IRContext* ir_context, const opt::analysis::Type& element_type) const {
   opt::analysis::Vector result_type(
       &element_type, static_cast<uint32_t>(message_.component_size()));
-  return context->get_type_mgr()->GetId(&result_type);
+  return ir_context->get_type_mgr()->GetId(&result_type);
 }
 
 opt::analysis::Vector* TransformationVectorShuffle::GetVectorType(
-    opt::IRContext* context, uint32_t id_of_vector) {
-  return context->get_type_mgr()
-      ->GetType(context->get_def_use_mgr()->GetDef(id_of_vector)->type_id())
+    opt::IRContext* ir_context, uint32_t id_of_vector) {
+  return ir_context->get_type_mgr()
+      ->GetType(ir_context->get_def_use_mgr()->GetDef(id_of_vector)->type_id())
       ->AsVector();
 }
 
diff --git a/third_party/spirv-tools/src/source/fuzz/transformation_vector_shuffle.h b/third_party/spirv-tools/src/source/fuzz/transformation_vector_shuffle.h
index 81ed227..f73fc31 100644
--- a/third_party/spirv-tools/src/source/fuzz/transformation_vector_shuffle.h
+++ b/third_party/spirv-tools/src/source/fuzz/transformation_vector_shuffle.h
@@ -15,10 +15,11 @@
 #ifndef SOURCE_FUZZ_TRANSFORMATION_VECTOR_SHUFFLE_H_
 #define SOURCE_FUZZ_TRANSFORMATION_VECTOR_SHUFFLE_H_
 
-#include "source/fuzz/fact_manager.h"
 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
 #include "source/fuzz/transformation.h"
+#include "source/fuzz/transformation_context.h"
 #include "source/opt/ir_context.h"
+
 #include "source/opt/types.h"
 
 namespace spvtools {
@@ -45,8 +46,9 @@
   // - The module must already contain a vector type with the same element type
   //   as |message_.vector1| and |message_.vector2|, and with the size of
   //   |message_component| as its element count
-  bool IsApplicable(opt::IRContext* context,
-                    const FactManager& fact_manager) const override;
+  bool IsApplicable(
+      opt::IRContext* ir_context,
+      const TransformationContext& transformation_context) const override;
 
   // Inserts an OpVectorShuffle instruction before
   // |message_.instruction_to_insert_before|, shuffles vectors
@@ -58,19 +60,20 @@
   // result vector is a contiguous sub-range of one of the input vectors, a
   // fact is added to record that |message_.fresh_id| is synonymous with this
   // sub-range.
-  void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
+  void Apply(opt::IRContext* ir_context,
+             TransformationContext* transformation_context) const override;
 
   protobufs::Transformation ToMessage() const override;
 
  private:
-  // Returns a type id that already exists in |context| suitable for
+  // Returns a type id that already exists in |ir_context| suitable for
   // representing the result of the shuffle, where |element_type| is known to
   // be the common element type of the vectors to which the shuffle is being
   // applied.  Returns 0 if no such id exists.
-  uint32_t GetResultTypeId(opt::IRContext* context,
+  uint32_t GetResultTypeId(opt::IRContext* ir_context,
                            const opt::analysis::Type& element_type) const;
 
-  static opt::analysis::Vector* GetVectorType(opt::IRContext* context,
+  static opt::analysis::Vector* GetVectorType(opt::IRContext* ir_context,
                                               uint32_t id_of_vector);
 
   protobufs::TransformationVectorShuffle message_;
diff --git a/third_party/spirv-tools/src/source/opt/aggressive_dead_code_elim_pass.cpp b/third_party/spirv-tools/src/source/opt/aggressive_dead_code_elim_pass.cpp
index 2cdf5ff..db2b67b 100644
--- a/third_party/spirv-tools/src/source/opt/aggressive_dead_code_elim_pass.cpp
+++ b/third_party/spirv-tools/src/source/opt/aggressive_dead_code_elim_pass.cpp
@@ -931,6 +931,7 @@
       "SPV_NV_shading_rate",
       "SPV_NV_mesh_shader",
       "SPV_NV_ray_tracing",
+      "SPV_KHR_ray_tracing",
       "SPV_EXT_fragment_invocation_density",
       "SPV_EXT_physical_storage_buffer",
   });
diff --git a/third_party/spirv-tools/src/source/opt/dominator_tree.cpp b/third_party/spirv-tools/src/source/opt/dominator_tree.cpp
index c9346e1..da5073a 100644
--- a/third_party/spirv-tools/src/source/opt/dominator_tree.cpp
+++ b/third_party/spirv-tools/src/source/opt/dominator_tree.cpp
@@ -241,6 +241,7 @@
 
 bool DominatorTree::Dominates(const DominatorTreeNode* a,
                               const DominatorTreeNode* b) const {
+  if (!a || !b) return false;
   // Node A dominates node B if they are the same.
   if (a == b) return true;
 
diff --git a/third_party/spirv-tools/src/source/opt/eliminate_dead_members_pass.cpp b/third_party/spirv-tools/src/source/opt/eliminate_dead_members_pass.cpp
index 0b73b2d..5b8f4ec 100644
--- a/third_party/spirv-tools/src/source/opt/eliminate_dead_members_pass.cpp
+++ b/third_party/spirv-tools/src/source/opt/eliminate_dead_members_pass.cpp
@@ -19,6 +19,7 @@
 
 namespace {
 const uint32_t kRemovedMember = 0xFFFFFFFF;
+const uint32_t kSpecConstOpOpcodeIdx = 0;
 }
 
 namespace spvtools {
@@ -40,7 +41,22 @@
   // we have to mark them as fully used just to be safe.
   for (auto& inst : get_module()->types_values()) {
     if (inst.opcode() == SpvOpSpecConstantOp) {
-      MarkTypeAsFullyUsed(inst.type_id());
+      switch (inst.GetSingleWordInOperand(kSpecConstOpOpcodeIdx)) {
+        case SpvOpCompositeExtract:
+          MarkMembersAsLiveForExtract(&inst);
+          break;
+        case SpvOpCompositeInsert:
+          // Nothing specific to do.
+          break;
+        case SpvOpAccessChain:
+        case SpvOpInBoundsAccessChain:
+        case SpvOpPtrAccessChain:
+        case SpvOpInBoundsPtrAccessChain:
+          assert(false && "Not implemented yet.");
+          break;
+        default:
+          break;
+      }
     } else if (inst.opcode() == SpvOpVariable) {
       switch (inst.GetSingleWordInOperand(0)) {
         case SpvStorageClassInput:
@@ -153,13 +169,17 @@
 
 void EliminateDeadMembersPass::MarkMembersAsLiveForExtract(
     const Instruction* inst) {
-  assert(inst->opcode() == SpvOpCompositeExtract);
+  assert(inst->opcode() == SpvOpCompositeExtract ||
+         (inst->opcode() == SpvOpSpecConstantOp &&
+          inst->GetSingleWordInOperand(kSpecConstOpOpcodeIdx) ==
+              SpvOpCompositeExtract));
 
-  uint32_t composite_id = inst->GetSingleWordInOperand(0);
+  uint32_t first_operand = (inst->opcode() == SpvOpSpecConstantOp ? 1 : 0);
+  uint32_t composite_id = inst->GetSingleWordInOperand(first_operand);
   Instruction* composite_inst = get_def_use_mgr()->GetDef(composite_id);
   uint32_t type_id = composite_inst->type_id();
 
-  for (uint32_t i = 1; i < inst->NumInOperands(); ++i) {
+  for (uint32_t i = first_operand + 1; i < inst->NumInOperands(); ++i) {
     Instruction* type_inst = get_def_use_mgr()->GetDef(type_id);
     uint32_t member_idx = inst->GetSingleWordInOperand(i);
     switch (type_inst->opcode()) {
@@ -295,10 +315,22 @@
         modified |= UpdateOpArrayLength(inst);
         break;
       case SpvOpSpecConstantOp:
-        assert(false && "Not yet implemented.");
-        // with OpCompositeExtract, OpCompositeInsert
-        // For kernels: OpAccessChain, OpInBoundsAccessChain, OpPtrAccessChain,
-        // OpInBoundsPtrAccessChain
+        switch (inst->GetSingleWordInOperand(kSpecConstOpOpcodeIdx)) {
+          case SpvOpCompositeExtract:
+            modified |= UpdateCompsiteExtract(inst);
+            break;
+          case SpvOpCompositeInsert:
+            modified |= UpdateCompositeInsert(inst);
+            break;
+          case SpvOpAccessChain:
+          case SpvOpInBoundsAccessChain:
+          case SpvOpPtrAccessChain:
+          case SpvOpInBoundsPtrAccessChain:
+            assert(false && "Not implemented yet.");
+            break;
+          default:
+            break;
+        }
         break;
       default:
         break;
@@ -393,7 +425,8 @@
 }
 
 bool EliminateDeadMembersPass::UpdateConstantComposite(Instruction* inst) {
-  assert(inst->opcode() == SpvOpConstantComposite ||
+  assert(inst->opcode() == SpvOpSpecConstantComposite ||
+         inst->opcode() == SpvOpConstantComposite ||
          inst->opcode() == SpvOpCompositeConstruct);
   uint32_t type_id = inst->type_id();
 
@@ -506,14 +539,25 @@
 }
 
 bool EliminateDeadMembersPass::UpdateCompsiteExtract(Instruction* inst) {
-  uint32_t object_id = inst->GetSingleWordInOperand(0);
+  assert(inst->opcode() == SpvOpCompositeExtract ||
+         (inst->opcode() == SpvOpSpecConstantOp &&
+          inst->GetSingleWordInOperand(kSpecConstOpOpcodeIdx) ==
+              SpvOpCompositeExtract));
+
+  uint32_t first_operand = 0;
+  if (inst->opcode() == SpvOpSpecConstantOp) {
+    first_operand = 1;
+  }
+  uint32_t object_id = inst->GetSingleWordInOperand(first_operand);
   Instruction* object_inst = get_def_use_mgr()->GetDef(object_id);
   uint32_t type_id = object_inst->type_id();
 
   Instruction::OperandList new_operands;
   bool modified = false;
-  new_operands.emplace_back(inst->GetInOperand(0));
-  for (uint32_t i = 1; i < inst->NumInOperands(); ++i) {
+  for (uint32_t i = 0; i < first_operand + 1; i++) {
+    new_operands.emplace_back(inst->GetInOperand(i));
+  }
+  for (uint32_t i = first_operand + 1; i < inst->NumInOperands(); ++i) {
     uint32_t member_idx = inst->GetSingleWordInOperand(i);
     uint32_t new_member_idx = GetNewMemberIndex(type_id, member_idx);
     assert(new_member_idx != kRemovedMember);
@@ -526,8 +570,6 @@
     Instruction* type_inst = get_def_use_mgr()->GetDef(type_id);
     switch (type_inst->opcode()) {
       case SpvOpTypeStruct:
-        assert(i != 1 || (inst->opcode() != SpvOpPtrAccessChain &&
-                          inst->opcode() != SpvOpInBoundsPtrAccessChain));
         // The type will have already been rewriten, so use the new member
         // index.
         type_id = type_inst->GetSingleWordInOperand(new_member_idx);
@@ -552,15 +594,27 @@
 }
 
 bool EliminateDeadMembersPass::UpdateCompositeInsert(Instruction* inst) {
-  uint32_t composite_id = inst->GetSingleWordInOperand(1);
+  assert(inst->opcode() == SpvOpCompositeInsert ||
+         (inst->opcode() == SpvOpSpecConstantOp &&
+          inst->GetSingleWordInOperand(kSpecConstOpOpcodeIdx) ==
+              SpvOpCompositeInsert));
+
+  uint32_t first_operand = 0;
+  if (inst->opcode() == SpvOpSpecConstantOp) {
+    first_operand = 1;
+  }
+
+  uint32_t composite_id = inst->GetSingleWordInOperand(first_operand + 1);
   Instruction* composite_inst = get_def_use_mgr()->GetDef(composite_id);
   uint32_t type_id = composite_inst->type_id();
 
   Instruction::OperandList new_operands;
   bool modified = false;
-  new_operands.emplace_back(inst->GetInOperand(0));
-  new_operands.emplace_back(inst->GetInOperand(1));
-  for (uint32_t i = 2; i < inst->NumInOperands(); ++i) {
+
+  for (uint32_t i = 0; i < first_operand + 2; ++i) {
+    new_operands.emplace_back(inst->GetInOperand(i));
+  }
+  for (uint32_t i = first_operand + 2; i < inst->NumInOperands(); ++i) {
     uint32_t member_idx = inst->GetSingleWordInOperand(i);
     uint32_t new_member_idx = GetNewMemberIndex(type_id, member_idx);
     if (new_member_idx == kRemovedMember) {
diff --git a/third_party/spirv-tools/src/source/opt/feature_manager.cpp b/third_party/spirv-tools/src/source/opt/feature_manager.cpp
index b4d6f1b..ad70c1e 100644
--- a/third_party/spirv-tools/src/source/opt/feature_manager.cpp
+++ b/third_party/spirv-tools/src/source/opt/feature_manager.cpp
@@ -78,6 +78,8 @@
 
 void FeatureManager::AddExtInstImportIds(Module* module) {
   extinst_importid_GLSLstd450_ = module->GetExtInstImportId("GLSL.std.450");
+  extinst_importid_OpenCL100DebugInfo_ =
+      module->GetExtInstImportId("OpenCL.DebugInfo.100");
 }
 
 bool operator==(const FeatureManager& a, const FeatureManager& b) {
@@ -100,6 +102,11 @@
     return false;
   }
 
+  if (a.extinst_importid_OpenCL100DebugInfo_ !=
+      b.extinst_importid_OpenCL100DebugInfo_) {
+    return false;
+  }
+
   return true;
 }
 }  // namespace opt
diff --git a/third_party/spirv-tools/src/source/opt/feature_manager.h b/third_party/spirv-tools/src/source/opt/feature_manager.h
index 881d5e6..66d1cba 100644
--- a/third_party/spirv-tools/src/source/opt/feature_manager.h
+++ b/third_party/spirv-tools/src/source/opt/feature_manager.h
@@ -51,6 +51,10 @@
     return extinst_importid_GLSLstd450_;
   }
 
+  uint32_t GetExtInstImportId_OpenCL100DebugInfo() const {
+    return extinst_importid_OpenCL100DebugInfo_;
+  }
+
   friend bool operator==(const FeatureManager& a, const FeatureManager& b);
   friend bool operator!=(const FeatureManager& a, const FeatureManager& b) {
     return !(a == b);
@@ -84,6 +88,10 @@
 
   // Common external instruction import ids, cached for performance.
   uint32_t extinst_importid_GLSLstd450_ = 0;
+
+  // Common OpenCL100DebugInfo external instruction import ids, cached
+  // for performance.
+  uint32_t extinst_importid_OpenCL100DebugInfo_ = 0;
 };
 
 }  // namespace opt
diff --git a/third_party/spirv-tools/src/source/opt/function.cpp b/third_party/spirv-tools/src/source/opt/function.cpp
index efda68b..2b7b4fb 100644
--- a/third_party/spirv-tools/src/source/opt/function.cpp
+++ b/third_party/spirv-tools/src/source/opt/function.cpp
@@ -34,6 +34,11 @@
       },
       true);
 
+  for (const auto& i : debug_insts_in_header_) {
+    clone->AddDebugInstructionInHeader(
+        std::unique_ptr<Instruction>(i.Clone(ctx)));
+  }
+
   clone->blocks_.reserve(blocks_.size());
   for (const auto& b : blocks_) {
     std::unique_ptr<BasicBlock> bb(b->Clone(ctx));
@@ -79,6 +84,15 @@
     }
   }
 
+  if (!debug_insts_in_header_.empty()) {
+    Instruction* di = &debug_insts_in_header_.front();
+    while (di != nullptr) {
+      Instruction* next_instruction = di->NextNode();
+      if (!di->WhileEachInst(f, run_on_debug_line_insts)) return false;
+      di = next_instruction;
+    }
+  }
+
   for (auto& bb : blocks_) {
     if (!bb->WhileEachInst(f, run_on_debug_line_insts)) {
       return false;
@@ -106,6 +120,12 @@
     }
   }
 
+  for (const auto& di : debug_insts_in_header_) {
+    if (!static_cast<const Instruction*>(&di)->WhileEachInst(
+            f, run_on_debug_line_insts))
+      return false;
+  }
+
   for (const auto& bb : blocks_) {
     if (!static_cast<const BasicBlock*>(bb.get())->WhileEachInst(
             f, run_on_debug_line_insts)) {
diff --git a/third_party/spirv-tools/src/source/opt/function.h b/third_party/spirv-tools/src/source/opt/function.h
index 3908568..f208d8e 100644
--- a/third_party/spirv-tools/src/source/opt/function.h
+++ b/third_party/spirv-tools/src/source/opt/function.h
@@ -56,6 +56,8 @@
 
   // Appends a parameter to this function.
   inline void AddParameter(std::unique_ptr<Instruction> p);
+  // Appends a debug instruction in function header to this function.
+  inline void AddDebugInstructionInHeader(std::unique_ptr<Instruction> p);
   // Appends a basic block to this function.
   inline void AddBasicBlock(std::unique_ptr<BasicBlock> b);
   // Appends a basic block to this function at the position |ip|.
@@ -151,6 +153,8 @@
   std::unique_ptr<Instruction> def_inst_;
   // All parameters to this function.
   std::vector<std::unique_ptr<Instruction>> params_;
+  // All debug instructions in this function's header.
+  InstructionList debug_insts_in_header_;
   // All basic blocks inside this function in specification order
   std::vector<std::unique_ptr<BasicBlock>> blocks_;
   // The OpFunctionEnd instruction.
@@ -167,6 +171,11 @@
   params_.emplace_back(std::move(p));
 }
 
+inline void Function::AddDebugInstructionInHeader(
+    std::unique_ptr<Instruction> p) {
+  debug_insts_in_header_.push_back(std::move(p));
+}
+
 inline void Function::AddBasicBlock(std::unique_ptr<BasicBlock> b) {
   AddBasicBlock(std::move(b), end());
 }
diff --git a/third_party/spirv-tools/src/source/opt/graphics_robust_access_pass.cpp b/third_party/spirv-tools/src/source/opt/graphics_robust_access_pass.cpp
index 22c979c..db14020 100644
--- a/third_party/spirv-tools/src/source/opt/graphics_robust_access_pass.cpp
+++ b/third_party/spirv-tools/src/source/opt/graphics_robust_access_pass.cpp
@@ -802,8 +802,11 @@
     opt::Instruction* image_texel_pointer) {
   // TODO(dneto): Write tests for this code.
   // TODO(dneto): Use signed-clamp
+  (void)(image_texel_pointer);
   return SPV_SUCCESS;
 
+  // Do not compile this code until it is ready to be used.
+#if 0
   // Example:
   //   %texel_ptr = OpImageTexelPointer %texel_ptr_type %image_ptr %coord
   //   %sample
@@ -1035,6 +1038,7 @@
   def_use_mgr->AnalyzeInstUse(image_texel_pointer);
 
   return SPV_SUCCESS;
+#endif
 }
 
 opt::Instruction* GraphicsRobustAccessPass::InsertInst(
diff --git a/third_party/spirv-tools/src/source/opt/instruction.cpp b/third_party/spirv-tools/src/source/opt/instruction.cpp
index 49f9142..9e54e7e 100644
--- a/third_party/spirv-tools/src/source/opt/instruction.cpp
+++ b/third_party/spirv-tools/src/source/opt/instruction.cpp
@@ -16,6 +16,7 @@
 
 #include <initializer_list>
 
+#include "OpenCLDebugInfo100.h"
 #include "source/disassemble.h"
 #include "source/opt/fold.h"
 #include "source/opt/ir_context.h"
@@ -30,6 +31,13 @@
 const uint32_t kLoadBaseIndex = 0;
 const uint32_t kVariableStorageClassIndex = 0;
 const uint32_t kTypeImageSampledIndex = 5;
+
+// Constants for OpenCL.DebugInfo.100 extension instructions.
+const uint32_t kExtInstSetIdInIdx = 0;
+const uint32_t kExtInstInstructionInIdx = 1;
+const uint32_t kDebugScopeNumWords = 7;
+const uint32_t kDebugScopeNumWordsWithoutInlinedAt = 6;
+const uint32_t kDebugNoScopeNumWords = 5;
 }  // namespace
 
 Instruction::Instruction(IRContext* c)
@@ -38,7 +46,8 @@
       opcode_(SpvOpNop),
       has_type_id_(false),
       has_result_id_(false),
-      unique_id_(c->TakeNextUniqueId()) {}
+      unique_id_(c->TakeNextUniqueId()),
+      dbg_scope_(kNoDebugScope, kNoInlinedAt) {}
 
 Instruction::Instruction(IRContext* c, SpvOp op)
     : utils::IntrusiveNodeBase<Instruction>(),
@@ -46,7 +55,8 @@
       opcode_(op),
       has_type_id_(false),
       has_result_id_(false),
-      unique_id_(c->TakeNextUniqueId()) {}
+      unique_id_(c->TakeNextUniqueId()),
+      dbg_scope_(kNoDebugScope, kNoInlinedAt) {}
 
 Instruction::Instruction(IRContext* c, const spv_parsed_instruction_t& inst,
                          std::vector<Instruction>&& dbg_line)
@@ -55,7 +65,8 @@
       has_type_id_(inst.type_id != 0),
       has_result_id_(inst.result_id != 0),
       unique_id_(c->TakeNextUniqueId()),
-      dbg_line_insts_(std::move(dbg_line)) {
+      dbg_line_insts_(std::move(dbg_line)),
+      dbg_scope_(kNoDebugScope, kNoInlinedAt) {
   assert((!IsDebugLineInst(opcode_) || dbg_line.empty()) &&
          "Op(No)Line attaching to Op(No)Line found");
   for (uint32_t i = 0; i < inst.num_operands; ++i) {
@@ -67,6 +78,23 @@
   }
 }
 
+Instruction::Instruction(IRContext* c, const spv_parsed_instruction_t& inst,
+                         const DebugScope& dbg_scope)
+    : context_(c),
+      opcode_(static_cast<SpvOp>(inst.opcode)),
+      has_type_id_(inst.type_id != 0),
+      has_result_id_(inst.result_id != 0),
+      unique_id_(c->TakeNextUniqueId()),
+      dbg_scope_(dbg_scope) {
+  for (uint32_t i = 0; i < inst.num_operands; ++i) {
+    const auto& current_payload = inst.operands[i];
+    std::vector<uint32_t> words(
+        inst.words + current_payload.offset,
+        inst.words + current_payload.offset + current_payload.num_words);
+    operands_.emplace_back(current_payload.type, std::move(words));
+  }
+}
+
 Instruction::Instruction(IRContext* c, SpvOp op, uint32_t ty_id,
                          uint32_t res_id, const OperandList& in_operands)
     : utils::IntrusiveNodeBase<Instruction>(),
@@ -75,7 +103,8 @@
       has_type_id_(ty_id != 0),
       has_result_id_(res_id != 0),
       unique_id_(c->TakeNextUniqueId()),
-      operands_() {
+      operands_(),
+      dbg_scope_(kNoDebugScope, kNoInlinedAt) {
   if (has_type_id_) {
     operands_.emplace_back(spv_operand_type_t::SPV_OPERAND_TYPE_TYPE_ID,
                            std::initializer_list<uint32_t>{ty_id});
@@ -94,7 +123,12 @@
       has_result_id_(that.has_result_id_),
       unique_id_(that.unique_id_),
       operands_(std::move(that.operands_)),
-      dbg_line_insts_(std::move(that.dbg_line_insts_)) {}
+      dbg_line_insts_(std::move(that.dbg_line_insts_)),
+      dbg_scope_(that.dbg_scope_) {
+  for (auto& i : dbg_line_insts_) {
+    i.dbg_scope_ = that.dbg_scope_;
+  }
+}
 
 Instruction& Instruction::operator=(Instruction&& that) {
   opcode_ = that.opcode_;
@@ -103,6 +137,7 @@
   unique_id_ = that.unique_id_;
   operands_ = std::move(that.operands_);
   dbg_line_insts_ = std::move(that.dbg_line_insts_);
+  dbg_scope_ = that.dbg_scope_;
   return *this;
 }
 
@@ -114,6 +149,7 @@
   clone->unique_id_ = c->TakeNextUniqueId();
   clone->operands_ = operands_;
   clone->dbg_line_insts_ = dbg_line_insts_;
+  clone->dbg_scope_ = dbg_scope_;
   return clone;
 }
 
@@ -146,10 +182,27 @@
 bool Instruction::IsReadOnlyLoad() const {
   if (IsLoad()) {
     Instruction* address_def = GetBaseAddress();
-    if (!address_def || address_def->opcode() != SpvOpVariable) {
+    if (!address_def) {
       return false;
     }
-    return address_def->IsReadOnlyVariable();
+
+    if (address_def->opcode() == SpvOpVariable) {
+      if (address_def->IsReadOnlyVariable()) {
+        return true;
+      }
+    }
+
+    if (address_def->opcode() == SpvOpLoad) {
+      const analysis::Type* address_type =
+          context()->get_type_mgr()->GetType(address_def->type_id());
+      if (address_type->AsSampledImage() != nullptr) {
+        const auto* image_type =
+            address_type->AsSampledImage()->image_type()->AsImage();
+        if (image_type->sampled() == 1) {
+          return true;
+        }
+      }
+    }
   }
   return false;
 }
@@ -198,6 +251,14 @@
 
   Instruction* base_type =
       context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1));
+
+  // Unpack the optional layer of arraying.
+  if (base_type->opcode() == SpvOpTypeArray ||
+      base_type->opcode() == SpvOpTypeRuntimeArray) {
+    base_type = context()->get_def_use_mgr()->GetDef(
+        base_type->GetSingleWordInOperand(0));
+  }
+
   if (base_type->opcode() != SpvOpTypeImage) {
     return false;
   }
@@ -224,6 +285,14 @@
 
   Instruction* base_type =
       context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1));
+
+  // Unpack the optional layer of arraying.
+  if (base_type->opcode() == SpvOpTypeArray ||
+      base_type->opcode() == SpvOpTypeRuntimeArray) {
+    base_type = context()->get_def_use_mgr()->GetDef(
+        base_type->GetSingleWordInOperand(0));
+  }
+
   if (base_type->opcode() != SpvOpTypeImage) {
     return false;
   }
@@ -250,6 +319,14 @@
 
   Instruction* base_type =
       context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1));
+
+  // Unpack the optional layer of arraying.
+  if (base_type->opcode() == SpvOpTypeArray ||
+      base_type->opcode() == SpvOpTypeRuntimeArray) {
+    base_type = context()->get_def_use_mgr()->GetDef(
+        base_type->GetSingleWordInOperand(0));
+  }
+
   if (base_type->opcode() != SpvOpTypeImage) {
     return false;
   }
@@ -273,6 +350,13 @@
   Instruction* base_type =
       context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1));
 
+  // Unpack the optional layer of arraying.
+  if (base_type->opcode() == SpvOpTypeArray ||
+      base_type->opcode() == SpvOpTypeRuntimeArray) {
+    base_type = context()->get_def_use_mgr()->GetDef(
+        base_type->GetSingleWordInOperand(0));
+  }
+
   if (base_type->opcode() != SpvOpTypeStruct) {
     return false;
   }
@@ -306,6 +390,14 @@
 
   Instruction* base_type =
       context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1));
+
+  // Unpack the optional layer of arraying.
+  if (base_type->opcode() == SpvOpTypeArray ||
+      base_type->opcode() == SpvOpTypeRuntimeArray) {
+    base_type = context()->get_def_use_mgr()->GetDef(
+        base_type->GetSingleWordInOperand(0));
+  }
+
   if (base_type->opcode() != SpvOpTypeStruct) {
     return false;
   }
@@ -437,6 +529,21 @@
   return false;
 }
 
+OpenCLDebugInfo100Instructions Instruction::GetOpenCL100DebugOpcode() const {
+  if (opcode() != SpvOpExtInst) return OpenCLDebugInfo100InstructionsMax;
+
+  if (!context()->get_feature_mgr()->GetExtInstImportId_OpenCL100DebugInfo())
+    return OpenCLDebugInfo100InstructionsMax;
+
+  if (GetSingleWordInOperand(kExtInstSetIdInIdx) !=
+      context()->get_feature_mgr()->GetExtInstImportId_OpenCL100DebugInfo()) {
+    return OpenCLDebugInfo100InstructionsMax;
+  }
+
+  return OpenCLDebugInfo100Instructions(
+      GetSingleWordInOperand(kExtInstInstructionInIdx));
+}
+
 bool Instruction::IsValidBaseImage() const {
   uint32_t tid = type_id();
   if (tid == 0) {
@@ -641,9 +748,6 @@
     return true;
   }
 
-  const uint32_t kExtInstSetIdInIdx = 0;
-  const uint32_t kExtInstInstructionInIdx = 1;
-
   if (opcode() == SpvOpExtInst) {
     uint32_t instSetId =
         context()->get_feature_mgr()->GetExtInstImportId_GLSLstd450();
@@ -735,5 +839,28 @@
   }
 }
 
+void DebugScope::ToBinary(uint32_t type_id, uint32_t result_id,
+                          uint32_t ext_set,
+                          std::vector<uint32_t>* binary) const {
+  uint32_t num_words = kDebugScopeNumWords;
+  OpenCLDebugInfo100Instructions dbg_opcode = OpenCLDebugInfo100DebugScope;
+  if (GetLexicalScope() == kNoDebugScope) {
+    num_words = kDebugNoScopeNumWords;
+    dbg_opcode = OpenCLDebugInfo100DebugNoScope;
+  } else if (GetInlinedAt() == kNoInlinedAt) {
+    num_words = kDebugScopeNumWordsWithoutInlinedAt;
+  }
+  std::vector<uint32_t> operands = {
+      (num_words << 16) | static_cast<uint16_t>(SpvOpExtInst),
+      type_id,
+      result_id,
+      ext_set,
+      static_cast<uint32_t>(dbg_opcode),
+  };
+  binary->insert(binary->end(), operands.begin(), operands.end());
+  if (GetLexicalScope() != kNoDebugScope) binary->push_back(GetLexicalScope());
+  if (GetInlinedAt() != kNoInlinedAt) binary->push_back(GetInlinedAt());
+}
+
 }  // namespace opt
 }  // namespace spvtools
diff --git a/third_party/spirv-tools/src/source/opt/instruction.h b/third_party/spirv-tools/src/source/opt/instruction.h
index 63dfa87..008a831 100644
--- a/third_party/spirv-tools/src/source/opt/instruction.h
+++ b/third_party/spirv-tools/src/source/opt/instruction.h
@@ -22,16 +22,19 @@
 #include <utility>
 #include <vector>
 
-#include "source/opcode.h"
-#include "source/operand.h"
-#include "source/util/ilist_node.h"
-#include "source/util/small_vector.h"
-
+#include "OpenCLDebugInfo100.h"
 #include "source/latest_version_glsl_std_450_header.h"
 #include "source/latest_version_spirv_header.h"
+#include "source/opcode.h"
+#include "source/operand.h"
 #include "source/opt/reflect.h"
+#include "source/util/ilist_node.h"
+#include "source/util/small_vector.h"
 #include "spirv-tools/libspirv.h"
 
+const uint32_t kNoDebugScope = 0;
+const uint32_t kNoInlinedAt = 0;
+
 namespace spvtools {
 namespace opt {
 
@@ -100,6 +103,44 @@
   return !(o1 == o2);
 }
 
+// This structure is used to represent a DebugScope instruction from
+// the OpenCL.100.DebugInfo extened instruction set. Note that we can
+// ignore the result id of DebugScope instruction because it is not
+// used for anything. We do not keep it to reduce the size of
+// structure.
+// TODO: Let validator check that the result id is not used anywhere.
+class DebugScope {
+ public:
+  DebugScope(uint32_t lexical_scope, uint32_t inlined_at)
+      : lexical_scope_(lexical_scope), inlined_at_(inlined_at) {}
+
+  inline bool operator!=(const DebugScope& d) const {
+    return lexical_scope_ != d.lexical_scope_ || inlined_at_ != d.inlined_at_;
+  }
+
+  // Accessor functions for |lexical_scope_|.
+  uint32_t GetLexicalScope() const { return lexical_scope_; }
+  void SetLexicalScope(uint32_t scope) { lexical_scope_ = scope; }
+
+  // Accessor functions for |inlined_at_|.
+  uint32_t GetInlinedAt() const { return inlined_at_; }
+  void SetInlinedAt(uint32_t at) { inlined_at_ = at; }
+
+  // Pushes the binary segments for this DebugScope instruction into
+  // the back of *|binary|.
+  void ToBinary(uint32_t type_id, uint32_t result_id, uint32_t ext_set,
+                std::vector<uint32_t>* binary) const;
+
+ private:
+  // The result id of the lexical scope in which this debug scope is
+  // contained. The value is kNoDebugScope if there is no scope.
+  uint32_t lexical_scope_;
+
+  // The result id of DebugInlinedAt if instruction in this debug scope
+  // is inlined. The value is kNoInlinedAt if it is not inlined.
+  uint32_t inlined_at_;
+};
+
 // A SPIR-V instruction. It contains the opcode and any additional logical
 // operand, including the result id (if any) and result type id (if any). It
 // may also contain line-related debug instruction (OpLine, OpNoLine) directly
@@ -120,7 +161,8 @@
         opcode_(SpvOpNop),
         has_type_id_(false),
         has_result_id_(false),
-        unique_id_(0) {}
+        unique_id_(0),
+        dbg_scope_(kNoDebugScope, kNoInlinedAt) {}
 
   // Creates a default OpNop instruction.
   Instruction(IRContext*);
@@ -134,6 +176,9 @@
   Instruction(IRContext* c, const spv_parsed_instruction_t& inst,
               std::vector<Instruction>&& dbg_line = {});
 
+  Instruction(IRContext* c, const spv_parsed_instruction_t& inst,
+              const DebugScope& dbg_scope);
+
   // Creates an instruction with the given opcode |op|, type id: |ty_id|,
   // result id: |res_id| and input operands: |in_operands|.
   Instruction(IRContext* c, SpvOp op, uint32_t ty_id, uint32_t res_id,
@@ -230,6 +275,9 @@
   // Sets the result id
   inline void SetResultId(uint32_t res_id);
   inline bool HasResultId() const { return has_result_id_; }
+  // Sets DebugScope.
+  inline void SetDebugScope(const DebugScope& scope);
+  inline const DebugScope& GetDebugScope() const { return dbg_scope_; }
   // Remove the |index|-th operand
   void RemoveOperand(uint32_t index) {
     operands_.erase(operands_.begin() + index);
@@ -448,6 +496,11 @@
   // rules for physical addressing.
   bool IsValidBasePointer() const;
 
+  // Returns debug opcode of an OpenCL.100.DebugInfo instruction. If
+  // it is not an OpenCL.100.DebugInfo instruction, just returns
+  // OpenCLDebugInfo100InstructionsMax.
+  OpenCLDebugInfo100Instructions GetOpenCL100DebugOpcode() const;
+
   // Dump this instruction on stderr.  Useful when running interactive
   // debuggers.
   void Dump() const;
@@ -482,6 +535,9 @@
   // empty.
   std::vector<Instruction> dbg_line_insts_;
 
+  // DebugScope that wraps this instruction.
+  DebugScope dbg_scope_;
+
   friend InstructionList;
 };
 
@@ -553,6 +609,13 @@
   operands_[ridx].words = {res_id};
 }
 
+inline void Instruction::SetDebugScope(const DebugScope& scope) {
+  dbg_scope_ = scope;
+  for (auto& i : dbg_line_insts_) {
+    i.dbg_scope_ = scope;
+  }
+}
+
 inline void Instruction::SetResultType(uint32_t ty_id) {
   // TODO(dsinclair): Allow setting a type id if there wasn't one
   // previously. Need to make room in the operands_ array to place the result,
diff --git a/third_party/spirv-tools/src/source/opt/ir_context.cpp b/third_party/spirv-tools/src/source/opt/ir_context.cpp
index 72993fd..c4378d3 100644
--- a/third_party/spirv-tools/src/source/opt/ir_context.cpp
+++ b/third_party/spirv-tools/src/source/opt/ir_context.cpp
@@ -16,6 +16,7 @@
 
 #include <cstring>
 
+#include "OpenCLDebugInfo100.h"
 #include "source/latest_version_glsl_std_450_header.h"
 #include "source/opt/log.h"
 #include "source/opt/mem_pass.h"
@@ -29,6 +30,10 @@
 static const int kEntryPointInterfaceInIdx = 3;
 static const int kEntryPointFunctionIdInIdx = 1;
 
+// Constants for OpenCL.DebugInfo.100 extension instructions.
+static const uint32_t kDebugFunctionOperandFunctionIndex = 13;
+static const uint32_t kDebugGlobalVariableOperandVariableIndex = 11;
+
 }  // anonymous namespace
 
 namespace spvtools {
@@ -153,6 +158,8 @@
 
   KillNamesAndDecorates(inst);
 
+  KillOperandFromDebugInstructions(inst);
+
   if (AreAnalysesValid(kAnalysisDefUse)) {
     get_def_use_mgr()->ClearInst(inst);
   }
@@ -265,7 +272,7 @@
 bool IRContext::IsConsistent() {
 #ifndef SPIRV_CHECK_CONTEXT
   return true;
-#endif
+#else
   if (AreAnalysesValid(kAnalysisDefUse)) {
     analysis::DefUseManager new_def_use(module());
     if (*get_def_use_mgr() != new_def_use) {
@@ -317,6 +324,7 @@
     }
   }
   return true;
+#endif
 }
 
 void IRContext::ForgetUses(Instruction* inst) {
@@ -365,6 +373,61 @@
   KillNamesAndDecorates(rId);
 }
 
+Instruction* IRContext::GetOpenCL100DebugInfoNone() {
+  if (debug_info_none_inst_) return debug_info_none_inst_;
+  assert(get_feature_mgr()->GetExtInstImportId_OpenCL100DebugInfo() &&
+         "Module does not include debug info extension instruction.");
+
+  // Create a new DebugInfoNone.
+  std::unique_ptr<Instruction> dbg_info_none(new Instruction(
+      this, SpvOpExtInst, get_type_mgr()->GetVoidTypeId(), TakeNextId(),
+      {
+          {SPV_OPERAND_TYPE_RESULT_ID,
+           {get_feature_mgr()->GetExtInstImportId_OpenCL100DebugInfo()}},
+          {SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER,
+           {static_cast<uint32_t>(OpenCLDebugInfo100DebugInfoNone)}},
+      }));
+
+  // Add to the front of |ext_inst_debuginfo_|.
+  debug_info_none_inst_ = module()->ext_inst_debuginfo_begin()->InsertBefore(
+      std::move(dbg_info_none));
+  return debug_info_none_inst_;
+}
+
+void IRContext::KillOperandFromDebugInstructions(Instruction* inst) {
+  const auto opcode = inst->opcode();
+  const uint32_t id = inst->result_id();
+  // Kill id of OpFunction from DebugFunction.
+  if (opcode == SpvOpFunction) {
+    for (auto it = module()->ext_inst_debuginfo_begin();
+         it != module()->ext_inst_debuginfo_end(); ++it) {
+      if (it->GetOpenCL100DebugOpcode() != OpenCLDebugInfo100DebugFunction)
+        continue;
+      auto& operand = it->GetOperand(kDebugFunctionOperandFunctionIndex);
+      if (operand.words[0] == id) {
+        operand.words[0] = GetOpenCL100DebugInfoNone()->result_id();
+      }
+    }
+  }
+  // Kill id of OpVariable for global variable from DebugGlobalVariable.
+  if (opcode == SpvOpVariable || IsConstantInst(opcode)) {
+    for (auto it = module()->ext_inst_debuginfo_begin();
+         it != module()->ext_inst_debuginfo_end(); ++it) {
+      if (it->GetOpenCL100DebugOpcode() !=
+          OpenCLDebugInfo100DebugGlobalVariable)
+        continue;
+      auto& operand = it->GetOperand(kDebugGlobalVariableOperandVariableIndex);
+      if (operand.words[0] == id) {
+        operand.words[0] = GetOpenCL100DebugInfoNone()->result_id();
+      }
+    }
+  }
+  // Notice that we do not need anythings to do for local variables.
+  // DebugLocalVariable does not have an OpVariable operand. Instead,
+  // DebugDeclare/DebugValue has an OpVariable operand for a local
+  // variable. The function inlining pass handles it properly.
+}
+
 void IRContext::AddCombinatorsForCapability(uint32_t capability) {
   if (capability == SpvCapabilityShader) {
     combinator_ops_[0].insert({SpvOpNop,
diff --git a/third_party/spirv-tools/src/source/opt/ir_context.h b/third_party/spirv-tools/src/source/opt/ir_context.h
index 723a2bb..b275ae4 100644
--- a/third_party/spirv-tools/src/source/opt/ir_context.h
+++ b/third_party/spirv-tools/src/source/opt/ir_context.h
@@ -102,7 +102,8 @@
         id_to_name_(nullptr),
         max_id_bound_(kDefaultMaxIdBound),
         preserve_bindings_(false),
-        preserve_spec_constants_(false) {
+        preserve_spec_constants_(false),
+        debug_info_none_inst_(nullptr) {
     SetContextMessageConsumer(syntax_context_, consumer_);
     module_->SetContext(this);
   }
@@ -119,7 +120,8 @@
         id_to_name_(nullptr),
         max_id_bound_(kDefaultMaxIdBound),
         preserve_bindings_(false),
-        preserve_spec_constants_(false) {
+        preserve_spec_constants_(false),
+        debug_info_none_inst_(nullptr) {
     SetContextMessageConsumer(syntax_context_, consumer_);
     module_->SetContext(this);
     InitializeCombinators();
@@ -426,6 +428,9 @@
   // Kill all name and decorate ops targeting the result id of |inst|.
   void KillNamesAndDecorates(Instruction* inst);
 
+  // Change operands of debug instruction to DebugInfoNone.
+  void KillOperandFromDebugInstructions(Instruction* inst);
+
   // Returns the next unique id for use by an instruction.
   inline uint32_t TakeNextUniqueId() {
     assert(unique_id_ != std::numeric_limits<uint32_t>::max());
@@ -705,6 +710,9 @@
   // Add |var_id| to all entry points in module.
   void AddVarToEntryPoints(uint32_t var_id);
 
+  // Get the existing DebugInfoNone. If it is null, create one and keep it.
+  Instruction* GetOpenCL100DebugInfoNone();
+
   // The SPIR-V syntax context containing grammar tables for opcodes and
   // operands.
   spv_context syntax_context_;
@@ -798,6 +806,10 @@
   // Whether all specialization constants within |module_|
   // should be preserved.
   bool preserve_spec_constants_;
+
+  // DebugInfoNone instruction. We need only a single DebugInfoNone.
+  // To reuse the existing one, we keep it using this member variable.
+  Instruction* debug_info_none_inst_;
 };
 
 inline IRContext::Analysis operator|(IRContext::Analysis lhs,
diff --git a/third_party/spirv-tools/src/source/opt/ir_loader.cpp b/third_party/spirv-tools/src/source/opt/ir_loader.cpp
index 836012f..fcde079 100644
--- a/third_party/spirv-tools/src/source/opt/ir_loader.cpp
+++ b/third_party/spirv-tools/src/source/opt/ir_loader.cpp
@@ -23,6 +23,10 @@
 #include "source/opt/reflect.h"
 #include "source/util/make_unique.h"
 
+static const uint32_t kExtInstSetIndex = 4;
+static const uint32_t kLexicalScopeIndex = 5;
+static const uint32_t kInlinedAtIndex = 6;
+
 namespace spvtools {
 namespace opt {
 
@@ -30,16 +34,60 @@
     : consumer_(consumer),
       module_(m),
       source_("<instruction>"),
-      inst_index_(0) {}
+      inst_index_(0),
+      last_dbg_scope_(kNoDebugScope, kNoInlinedAt) {}
 
 bool IrLoader::AddInstruction(const spv_parsed_instruction_t* inst) {
   ++inst_index_;
   const auto opcode = static_cast<SpvOp>(inst->opcode);
   if (IsDebugLineInst(opcode)) {
-    dbg_line_info_.push_back(Instruction(module()->context(), *inst));
+    dbg_line_info_.push_back(
+        Instruction(module()->context(), *inst, last_dbg_scope_));
     return true;
   }
 
+  // If it is a DebugScope or DebugNoScope of debug extension, we do not
+  // create a new instruction, but simply keep the information in
+  // struct DebugScope.
+  if (opcode == SpvOpExtInst && spvExtInstIsDebugInfo(inst->ext_inst_type)) {
+    const uint32_t ext_inst_index = inst->words[kExtInstSetIndex];
+    if (inst->ext_inst_type == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100) {
+      const OpenCLDebugInfo100Instructions ext_inst_key =
+          OpenCLDebugInfo100Instructions(ext_inst_index);
+      if (ext_inst_key == OpenCLDebugInfo100DebugScope) {
+        uint32_t inlined_at = 0;
+        if (inst->num_words > kInlinedAtIndex)
+          inlined_at = inst->words[kInlinedAtIndex];
+        last_dbg_scope_ =
+            DebugScope(inst->words[kLexicalScopeIndex], inlined_at);
+        module()->SetContainsDebugScope();
+        return true;
+      }
+      if (ext_inst_key == OpenCLDebugInfo100DebugNoScope) {
+        last_dbg_scope_ = DebugScope(kNoDebugScope, kNoInlinedAt);
+        module()->SetContainsDebugScope();
+        return true;
+      }
+    } else {
+      const DebugInfoInstructions ext_inst_key =
+          DebugInfoInstructions(ext_inst_index);
+      if (ext_inst_key == DebugInfoDebugScope) {
+        uint32_t inlined_at = 0;
+        if (inst->num_words > kInlinedAtIndex)
+          inlined_at = inst->words[kInlinedAtIndex];
+        last_dbg_scope_ =
+            DebugScope(inst->words[kLexicalScopeIndex], inlined_at);
+        module()->SetContainsDebugScope();
+        return true;
+      }
+      if (ext_inst_key == DebugInfoDebugNoScope) {
+        last_dbg_scope_ = DebugScope(kNoDebugScope, kNoInlinedAt);
+        module()->SetContainsDebugScope();
+        return true;
+      }
+    }
+  }
+
   std::unique_ptr<Instruction> spv_inst(
       new Instruction(module()->context(), *inst, std::move(dbg_line_info_)));
   dbg_line_info_.clear();
@@ -90,6 +138,7 @@
     block_->AddInstruction(std::move(spv_inst));
     function_->AddBasicBlock(std::move(block_));
     block_ = nullptr;
+    last_dbg_scope_ = DebugScope(kNoDebugScope, kNoInlinedAt);
   } else {
     if (function_ == nullptr) {  // Outside function definition
       SPIRV_ASSERT(consumer_, block_ == nullptr);
@@ -131,26 +180,32 @@
         return false;
       }
     } else {
-      if (block_ == nullptr) {  // Inside function but outside blocks
-        if (opcode != SpvOpFunctionParameter) {
-          Errorf(consumer_, src, loc,
-                 "Non-OpFunctionParameter (opcode: %d) found inside "
-                 "function but outside basic block",
-                 opcode);
-          return false;
-        }
-        function_->AddParameter(std::move(spv_inst));
-      } else {
-        if (opcode == SpvOpExtInst &&
-            spvExtInstIsDebugInfo(inst->ext_inst_type)) {
-          const uint32_t ext_inst_index = inst->words[4];
-          if (inst->ext_inst_type == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100) {
-            const OpenCLDebugInfo100Instructions ext_inst_key =
-                OpenCLDebugInfo100Instructions(ext_inst_index);
-            if (ext_inst_key != OpenCLDebugInfo100DebugScope &&
-                ext_inst_key != OpenCLDebugInfo100DebugNoScope &&
-                ext_inst_key != OpenCLDebugInfo100DebugDeclare &&
-                ext_inst_key != OpenCLDebugInfo100DebugValue) {
+      if (opcode == SpvOpLoopMerge || opcode == SpvOpSelectionMerge)
+        last_dbg_scope_ = DebugScope(kNoDebugScope, kNoInlinedAt);
+      if (last_dbg_scope_.GetLexicalScope() != kNoDebugScope)
+        spv_inst->SetDebugScope(last_dbg_scope_);
+      if (opcode == SpvOpExtInst &&
+          spvExtInstIsDebugInfo(inst->ext_inst_type)) {
+        const uint32_t ext_inst_index = inst->words[kExtInstSetIndex];
+        if (inst->ext_inst_type == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100) {
+          const OpenCLDebugInfo100Instructions ext_inst_key =
+              OpenCLDebugInfo100Instructions(ext_inst_index);
+          switch (ext_inst_key) {
+            case OpenCLDebugInfo100DebugDeclare: {
+              if (block_ == nullptr)  // Inside function but outside blocks
+                function_->AddDebugInstructionInHeader(std::move(spv_inst));
+              else
+                block_->AddInstruction(std::move(spv_inst));
+              break;
+            }
+            case OpenCLDebugInfo100DebugValue: {
+              if (block_ == nullptr)  // Inside function but outside blocks
+                function_->AddDebugInstructionInHeader(std::move(spv_inst));
+              else
+                block_->AddInstruction(std::move(spv_inst));
+              break;
+            }
+            default: {
               Errorf(consumer_, src, loc,
                      "Debug info extension instruction other than DebugScope, "
                      "DebugNoScope, DebugDeclare, and DebugValue found inside "
@@ -158,13 +213,26 @@
                      opcode);
               return false;
             }
-          } else {
-            const DebugInfoInstructions ext_inst_key =
-                DebugInfoInstructions(ext_inst_index);
-            if (ext_inst_key != DebugInfoDebugScope &&
-                ext_inst_key != DebugInfoDebugNoScope &&
-                ext_inst_key != DebugInfoDebugDeclare &&
-                ext_inst_key != DebugInfoDebugValue) {
+          }
+        } else {
+          const DebugInfoInstructions ext_inst_key =
+              DebugInfoInstructions(ext_inst_index);
+          switch (ext_inst_key) {
+            case DebugInfoDebugDeclare: {
+              if (block_ == nullptr)  // Inside function but outside blocks
+                function_->AddDebugInstructionInHeader(std::move(spv_inst));
+              else
+                block_->AddInstruction(std::move(spv_inst));
+              break;
+            }
+            case DebugInfoDebugValue: {
+              if (block_ == nullptr)  // Inside function but outside blocks
+                function_->AddDebugInstructionInHeader(std::move(spv_inst));
+              else
+                block_->AddInstruction(std::move(spv_inst));
+              break;
+            }
+            default: {
               Errorf(consumer_, src, loc,
                      "Debug info extension instruction other than DebugScope, "
                      "DebugNoScope, DebugDeclare, and DebugValue found inside "
@@ -174,7 +242,19 @@
             }
           }
         }
-        block_->AddInstruction(std::move(spv_inst));
+      } else {
+        if (block_ == nullptr) {  // Inside function but outside blocks
+          if (opcode != SpvOpFunctionParameter) {
+            Errorf(consumer_, src, loc,
+                   "Non-OpFunctionParameter (opcode: %d) found inside "
+                   "function but outside basic block",
+                   opcode);
+            return false;
+          }
+          function_->AddParameter(std::move(spv_inst));
+        } else {
+          block_->AddInstruction(std::move(spv_inst));
+        }
       }
     }
   }
diff --git a/third_party/spirv-tools/src/source/opt/ir_loader.h b/third_party/spirv-tools/src/source/opt/ir_loader.h
index 940d7b0..5079921 100644
--- a/third_party/spirv-tools/src/source/opt/ir_loader.h
+++ b/third_party/spirv-tools/src/source/opt/ir_loader.h
@@ -78,6 +78,9 @@
   std::unique_ptr<BasicBlock> block_;
   // Line related debug instructions accumulated thus far.
   std::vector<Instruction> dbg_line_info_;
+
+  // The last DebugScope information that IrLoader::AddInstruction() handled.
+  DebugScope last_dbg_scope_;
 };
 
 }  // namespace opt
diff --git a/third_party/spirv-tools/src/source/opt/local_access_chain_convert_pass.cpp b/third_party/spirv-tools/src/source/opt/local_access_chain_convert_pass.cpp
index a8cf94b..0afe798 100644
--- a/third_party/spirv-tools/src/source/opt/local_access_chain_convert_pass.cpp
+++ b/third_party/spirv-tools/src/source/opt/local_access_chain_convert_pass.cpp
@@ -379,6 +379,7 @@
       "SPV_NV_shading_rate",
       "SPV_NV_mesh_shader",
       "SPV_NV_ray_tracing",
+      "SPV_KHR_ray_tracing",
       "SPV_KHR_ray_query",
       "SPV_EXT_fragment_invocation_density",
   });
diff --git a/third_party/spirv-tools/src/source/opt/local_single_block_elim_pass.cpp b/third_party/spirv-tools/src/source/opt/local_single_block_elim_pass.cpp
index c66271e..b5435bb 100644
--- a/third_party/spirv-tools/src/source/opt/local_single_block_elim_pass.cpp
+++ b/third_party/spirv-tools/src/source/opt/local_single_block_elim_pass.cpp
@@ -256,6 +256,7 @@
       "SPV_NV_shading_rate",
       "SPV_NV_mesh_shader",
       "SPV_NV_ray_tracing",
+      "SPV_KHR_ray_tracing",
       "SPV_KHR_ray_query",
       "SPV_EXT_fragment_invocation_density",
       "SPV_EXT_physical_storage_buffer",
diff --git a/third_party/spirv-tools/src/source/opt/module.cpp b/third_party/spirv-tools/src/source/opt/module.cpp
index 4403894..2959d3d 100644
--- a/third_party/spirv-tools/src/source/opt/module.cpp
+++ b/third_party/spirv-tools/src/source/opt/module.cpp
@@ -137,10 +137,27 @@
   binary->push_back(header_.bound);
   binary->push_back(header_.reserved);
 
-  auto write_inst = [binary, skip_nop](const Instruction* i) {
-    if (!(skip_nop && i->IsNop())) i->ToBinaryWithoutAttachedDebugInsts(binary);
+  size_t bound_idx = binary->size() - 2;
+  DebugScope last_scope(kNoDebugScope, kNoInlinedAt);
+  auto write_inst = [binary, skip_nop, &last_scope,
+                     this](const Instruction* i) {
+    if (!(skip_nop && i->IsNop())) {
+      const auto& scope = i->GetDebugScope();
+      if (scope != last_scope) {
+        // Emit DebugScope |scope| to |binary|.
+        auto dbg_inst = ext_inst_debuginfo_.begin();
+        scope.ToBinary(dbg_inst->type_id(), context()->TakeNextId(),
+                       dbg_inst->GetSingleWordOperand(2), binary);
+        last_scope = scope;
+      }
+
+      i->ToBinaryWithoutAttachedDebugInsts(binary);
+    }
   };
   ForEachInst(write_inst, true);
+
+  // We create new instructions for DebugScope. The bound must be updated.
+  binary->data()[bound_idx] = header_.bound;
 }
 
 uint32_t Module::ComputeIdBound() const {
diff --git a/third_party/spirv-tools/src/source/opt/module.h b/third_party/spirv-tools/src/source/opt/module.h
index fc53d35..2c96f02 100644
--- a/third_party/spirv-tools/src/source/opt/module.h
+++ b/third_party/spirv-tools/src/source/opt/module.h
@@ -17,6 +17,7 @@
 
 #include <functional>
 #include <memory>
+#include <unordered_map>
 #include <utility>
 #include <vector>
 
@@ -48,7 +49,7 @@
   using const_inst_iterator = InstructionList::const_iterator;
 
   // Creates an empty module with zero'd header.
-  Module() : header_({}) {}
+  Module() : header_({}), contains_debug_scope_(false) {}
 
   // Sets the header to the given |header|.
   void SetHeader(const ModuleHeader& header) { header_ = header; }
@@ -118,6 +119,10 @@
   // Appends a function to this module.
   inline void AddFunction(std::unique_ptr<Function> f);
 
+  // Sets |contains_debug_scope_| as true.
+  inline void SetContainsDebugScope();
+  inline bool ContainsDebugScope() { return contains_debug_scope_; }
+
   // Returns a vector of pointers to type-declaration instructions in this
   // module.
   std::vector<Instruction*> GetTypes();
@@ -295,6 +300,9 @@
   // If the module ends with Op*Line instruction, they will not be attached to
   // any instruction.  We record them here, so they will not be lost.
   std::vector<Instruction> trailing_dbg_line_info_;
+
+  // This module contains DebugScope or DebugNoScope.
+  bool contains_debug_scope_;
 };
 
 // Pretty-prints |module| to |str|. Returns |str|.
@@ -356,6 +364,8 @@
   functions_.emplace_back(std::move(f));
 }
 
+inline void Module::SetContainsDebugScope() { contains_debug_scope_ = true; }
+
 inline Module::inst_iterator Module::capability_begin() {
   return capabilities_.begin();
 }
diff --git a/third_party/spirv-tools/src/source/opt/optimizer.cpp b/third_party/spirv-tools/src/source/opt/optimizer.cpp
index 6e271f5..f11dc34 100644
--- a/third_party/spirv-tools/src/source/opt/optimizer.cpp
+++ b/third_party/spirv-tools/src/source/opt/optimizer.cpp
@@ -498,7 +498,7 @@
   } else if (pass_name == "legalize-vector-shuffle") {
     RegisterPass(CreateLegalizeVectorShufflePass());
   } else if (pass_name == "split-invalid-unreachable") {
-    RegisterPass(CreateLegalizeVectorShufflePass());
+    RegisterPass(CreateSplitInvalidUnreachablePass());
   } else if (pass_name == "decompose-initialized-variables") {
     RegisterPass(CreateDecomposeInitializedVariablesPass());
   } else if (pass_name == "graphics-robust-access") {
@@ -569,7 +569,12 @@
   }
 
 #ifndef NDEBUG
-  if (status == opt::Pass::Status::SuccessWithoutChange) {
+  // We do not keep the result id of DebugScope in struct DebugScope.
+  // Instead, we assign random ids for them, which results in sanity
+  // check failures. We want to skip the sanity check when the module
+  // contains DebugScope instructions.
+  if (status == opt::Pass::Status::SuccessWithoutChange &&
+      !context->module()->ContainsDebugScope()) {
     std::vector<uint32_t> optimized_binary_with_nop;
     context->module()->ToBinary(&optimized_binary_with_nop,
                                 /* skip_nop = */ false);
diff --git a/third_party/spirv-tools/src/source/opt/struct_cfg_analysis.cpp b/third_party/spirv-tools/src/source/opt/struct_cfg_analysis.cpp
index b16322c..57fc49c 100644
--- a/third_party/spirv-tools/src/source/opt/struct_cfg_analysis.cpp
+++ b/third_party/spirv-tools/src/source/opt/struct_cfg_analysis.cpp
@@ -85,9 +85,14 @@
       if (merge_inst->opcode() == SpvOpLoopMerge) {
         new_state.cinfo.containing_loop = block->id();
         new_state.cinfo.containing_switch = 0;
-        new_state.cinfo.in_continue = false;
         new_state.continue_node =
             merge_inst->GetSingleWordInOperand(kContinueNodeIndex);
+        if (block->id() == new_state.continue_node) {
+          new_state.cinfo.in_continue = true;
+          bb_to_construct_[block->id()].in_continue = true;
+        } else {
+          new_state.cinfo.in_continue = false;
+        }
       } else {
         new_state.cinfo.containing_loop = state.back().cinfo.containing_loop;
         new_state.cinfo.in_continue = state.back().cinfo.in_continue;
diff --git a/third_party/spirv-tools/src/source/opt/type_manager.h b/third_party/spirv-tools/src/source/opt/type_manager.h
index 8fcf8aa..ce9d83d 100644
--- a/third_party/spirv-tools/src/source/opt/type_manager.h
+++ b/third_party/spirv-tools/src/source/opt/type_manager.h
@@ -194,6 +194,13 @@
 
   uint32_t GetBoolTypeId() { return GetTypeInstruction(GetBoolType()); }
 
+  Type* GetVoidType() {
+    Void void_type;
+    return GetRegisteredType(&void_type);
+  }
+
+  uint32_t GetVoidTypeId() { return GetTypeInstruction(GetVoidType()); }
+
  private:
   using TypeToIdMap = std::unordered_map<const Type*, uint32_t, HashTypePointer,
                                          CompareTypePointers>;
diff --git a/third_party/spirv-tools/src/source/opt/wrap_opkill.cpp b/third_party/spirv-tools/src/source/opt/wrap_opkill.cpp
index ffd7a10..05e1db0 100644
--- a/third_party/spirv-tools/src/source/opt/wrap_opkill.cpp
+++ b/third_party/spirv-tools/src/source/opt/wrap_opkill.cpp
@@ -147,6 +147,7 @@
   bb->AddInstruction(std::move(kill_inst));
 
   // Add the bb to the function
+  bb->SetParent(opkill_function_.get());
   opkill_function_->AddBasicBlock(std::move(bb));
 
   // Add the function to the module.
diff --git a/third_party/spirv-tools/src/source/val/validate_cfg.cpp b/third_party/spirv-tools/src/source/val/validate_cfg.cpp
index f3019d1..1e33e51 100644
--- a/third_party/spirv-tools/src/source/val/validate_cfg.cpp
+++ b/third_party/spirv-tools/src/source/val/validate_cfg.cpp
@@ -62,6 +62,15 @@
     }
   }
 
+  if (!_.options()->before_hlsl_legalization) {
+    if (type_opcode == SpvOpTypeSampledImage ||
+        (_.HasCapability(SpvCapabilityShader) &&
+         (type_opcode == SpvOpTypeImage || type_opcode == SpvOpTypeSampler))) {
+      return _.diag(SPV_ERROR_INVALID_ID, inst)
+             << "Result type cannot be Op" << spvOpcodeString(type_opcode);
+    }
+  }
+
   // Create a uniqued vector of predecessor ids for comparison against
   // incoming values. OpBranchConditional %cond %label %label produces two
   // predecessors in the CFG.
@@ -1081,8 +1090,9 @@
         return _.diag(SPV_ERROR_INVALID_CFG, inst)
                << "OpReturn can only be called from a function with void "
                << "return type.";
+      _.current_function().RegisterBlockEnd(std::vector<uint32_t>(), opcode);
+      break;
     }
-    // Fallthrough.
     case SpvOpKill:
     case SpvOpReturnValue:
     case SpvOpUnreachable:
diff --git a/third_party/spirv-tools/src/source/val/validate_decorations.cpp b/third_party/spirv-tools/src/source/val/validate_decorations.cpp
index 3b44833..ce09e18 100644
--- a/third_party/spirv-tools/src/source/val/validate_decorations.cpp
+++ b/third_party/spirv-tools/src/source/val/validate_decorations.cpp
@@ -1524,6 +1524,22 @@
   return SPV_SUCCESS;
 }
 
+// Returns SPV_SUCCESS if validation rules are satisfied for the Block
+// decoration.  Otherwise emits a diagnostic and returns something other than
+// SPV_SUCCESS.
+spv_result_t CheckBlockDecoration(ValidationState_t& vstate,
+                                  const Instruction& inst,
+                                  const Decoration& decoration) {
+  assert(inst.id() && "Parser ensures the target of the decoration has an ID");
+  if (inst.opcode() != SpvOpTypeStruct) {
+    const char* const dec_name =
+        decoration.dec_type() == SpvDecorationBlock ? "Block" : "BufferBlock";
+    return vstate.diag(SPV_ERROR_INVALID_ID, &inst)
+           << dec_name << " decoration on a non-struct type.";
+  }
+  return SPV_SUCCESS;
+}
+
 #define PASS_OR_BAIL_AT_LINE(X, LINE)           \
   {                                             \
     spv_result_t e##LINE = (X);                 \
@@ -1570,6 +1586,10 @@
         case SpvDecorationNoUnsignedWrap:
           PASS_OR_BAIL(CheckIntegerWrapDecoration(vstate, *inst, decoration));
           break;
+        case SpvDecorationBlock:
+        case SpvDecorationBufferBlock:
+          PASS_OR_BAIL(CheckBlockDecoration(vstate, *inst, decoration));
+          break;
         default:
           break;
       }
diff --git a/third_party/spirv-tools/src/test/fuzz/CMakeLists.txt b/third_party/spirv-tools/src/test/fuzz/CMakeLists.txt
index 99a78fd..8c5d512 100644
--- a/third_party/spirv-tools/src/test/fuzz/CMakeLists.txt
+++ b/third_party/spirv-tools/src/test/fuzz/CMakeLists.txt
@@ -22,11 +22,13 @@
           fact_manager_test.cpp
           fuzz_test_util.cpp
           fuzzer_pass_add_useful_constructs_test.cpp
+          fuzzer_pass_construct_composites_test.cpp
           fuzzer_pass_donate_modules_test.cpp
           instruction_descriptor_test.cpp
           transformation_access_chain_test.cpp
           transformation_add_constant_boolean_test.cpp
           transformation_add_constant_composite_test.cpp
+          transformation_add_constant_null_test.cpp
           transformation_add_constant_scalar_test.cpp
           transformation_add_dead_block_test.cpp
           transformation_add_dead_break_test.cpp
@@ -47,6 +49,7 @@
           transformation_add_type_vector_test.cpp
           transformation_composite_construct_test.cpp
           transformation_composite_extract_test.cpp
+          transformation_compute_data_synonym_fact_closure_test.cpp
           transformation_copy_object_test.cpp
           transformation_equation_instruction_test.cpp
           transformation_function_call_test.cpp
diff --git a/third_party/spirv-tools/src/test/fuzz/data_synonym_transformation_test.cpp b/third_party/spirv-tools/src/test/fuzz/data_synonym_transformation_test.cpp
index 21ea068..66ce769 100644
--- a/third_party/spirv-tools/src/test/fuzz/data_synonym_transformation_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/data_synonym_transformation_test.cpp
@@ -123,13 +123,24 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
-  fact_manager.AddFact(MakeSynonymFact(12, {}, 100, {0}), context.get());
-  fact_manager.AddFact(MakeSynonymFact(13, {}, 100, {1}), context.get());
-  fact_manager.AddFact(MakeSynonymFact(22, {}, 100, {2}), context.get());
-  fact_manager.AddFact(MakeSynonymFact(28, {}, 101, {0}), context.get());
-  fact_manager.AddFact(MakeSynonymFact(23, {}, 101, {1}), context.get());
-  fact_manager.AddFact(MakeSynonymFact(32, {}, 101, {2}), context.get());
-  fact_manager.AddFact(MakeSynonymFact(23, {}, 101, {3}), context.get());
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
+
+  transformation_context.GetFactManager()->AddFact(
+      MakeSynonymFact(12, {}, 100, {0}), context.get());
+  transformation_context.GetFactManager()->AddFact(
+      MakeSynonymFact(13, {}, 100, {1}), context.get());
+  transformation_context.GetFactManager()->AddFact(
+      MakeSynonymFact(22, {}, 100, {2}), context.get());
+  transformation_context.GetFactManager()->AddFact(
+      MakeSynonymFact(28, {}, 101, {0}), context.get());
+  transformation_context.GetFactManager()->AddFact(
+      MakeSynonymFact(23, {}, 101, {1}), context.get());
+  transformation_context.GetFactManager()->AddFact(
+      MakeSynonymFact(32, {}, 101, {2}), context.get());
+  transformation_context.GetFactManager()->AddFact(
+      MakeSynonymFact(23, {}, 101, {3}), context.get());
 
   // Replace %12 with %100[0] in '%25 = OpAccessChain %24 %20 %12'
   auto instruction_descriptor_1 =
@@ -139,13 +150,16 @@
   // Bad: id already in use
   auto bad_extract_1 = TransformationCompositeExtract(
       MakeInstructionDescriptor(25, SpvOpAccessChain, 0), 25, 100, {0});
-  ASSERT_TRUE(good_extract_1.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(bad_extract_1.IsApplicable(context.get(), fact_manager));
-  good_extract_1.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      good_extract_1.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      bad_extract_1.IsApplicable(context.get(), transformation_context));
+  good_extract_1.Apply(context.get(), &transformation_context);
   auto replacement_1 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(12, instruction_descriptor_1, 1), 102);
-  ASSERT_TRUE(replacement_1.IsApplicable(context.get(), fact_manager));
-  replacement_1.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      replacement_1.IsApplicable(context.get(), transformation_context));
+  replacement_1.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Replace %13 with %100[1] in 'OpStore %15 %13'
@@ -153,12 +167,14 @@
   auto good_extract_2 =
       TransformationCompositeExtract(instruction_descriptor_2, 103, 100, {1});
   // No bad example provided here.
-  ASSERT_TRUE(good_extract_2.IsApplicable(context.get(), fact_manager));
-  good_extract_2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      good_extract_2.IsApplicable(context.get(), transformation_context));
+  good_extract_2.Apply(context.get(), &transformation_context);
   auto replacement_2 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(13, instruction_descriptor_2, 1), 103);
-  ASSERT_TRUE(replacement_2.IsApplicable(context.get(), fact_manager));
-  replacement_2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      replacement_2.IsApplicable(context.get(), transformation_context));
+  replacement_2.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Replace %22 with %100[2] in '%23 = OpConvertSToF %16 %22'
@@ -166,16 +182,19 @@
       MakeInstructionDescriptor(23, SpvOpConvertSToF, 0);
   auto good_extract_3 =
       TransformationCompositeExtract(instruction_descriptor_3, 104, 100, {2});
-  ASSERT_TRUE(good_extract_3.IsApplicable(context.get(), fact_manager));
-  good_extract_3.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      good_extract_3.IsApplicable(context.get(), transformation_context));
+  good_extract_3.Apply(context.get(), &transformation_context);
   auto replacement_3 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(22, instruction_descriptor_3, 0), 104);
   // Bad: wrong input operand index
   auto bad_replacement_3 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(22, instruction_descriptor_3, 1), 104);
-  ASSERT_TRUE(replacement_3.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(bad_replacement_3.IsApplicable(context.get(), fact_manager));
-  replacement_3.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      replacement_3.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      bad_replacement_3.IsApplicable(context.get(), transformation_context));
+  replacement_3.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Replace %28 with %101[0] in 'OpStore %33 %28'
@@ -185,13 +204,16 @@
   // Bad: instruction descriptor does not identify an appropriate instruction
   auto bad_extract_4 = TransformationCompositeExtract(
       MakeInstructionDescriptor(33, SpvOpCopyObject, 0), 105, 101, {0});
-  ASSERT_TRUE(good_extract_4.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(bad_extract_4.IsApplicable(context.get(), fact_manager));
-  good_extract_4.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      good_extract_4.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      bad_extract_4.IsApplicable(context.get(), transformation_context));
+  good_extract_4.Apply(context.get(), &transformation_context);
   auto replacement_4 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(28, instruction_descriptor_4, 1), 105);
-  ASSERT_TRUE(replacement_4.IsApplicable(context.get(), fact_manager));
-  replacement_4.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      replacement_4.IsApplicable(context.get(), transformation_context));
+  replacement_4.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Replace %23 with %101[1] in '%50 = OpCopyObject %16 %23'
@@ -199,16 +221,19 @@
       MakeInstructionDescriptor(50, SpvOpCopyObject, 0);
   auto good_extract_5 =
       TransformationCompositeExtract(instruction_descriptor_5, 106, 101, {1});
-  ASSERT_TRUE(good_extract_5.IsApplicable(context.get(), fact_manager));
-  good_extract_5.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      good_extract_5.IsApplicable(context.get(), transformation_context));
+  good_extract_5.Apply(context.get(), &transformation_context);
   auto replacement_5 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(23, instruction_descriptor_5, 0), 106);
   // Bad: wrong synonym fact being used
   auto bad_replacement_5 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(23, instruction_descriptor_5, 0), 105);
-  ASSERT_TRUE(replacement_5.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(bad_replacement_5.IsApplicable(context.get(), fact_manager));
-  replacement_5.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      replacement_5.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      bad_replacement_5.IsApplicable(context.get(), transformation_context));
+  replacement_5.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Replace %32 with %101[2] in 'OpStore %33 %32'
@@ -218,13 +243,16 @@
   // Bad: id 1001 does not exist
   auto bad_extract_6 =
       TransformationCompositeExtract(instruction_descriptor_6, 107, 1001, {2});
-  ASSERT_TRUE(good_extract_6.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(bad_extract_6.IsApplicable(context.get(), fact_manager));
-  good_extract_6.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      good_extract_6.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      bad_extract_6.IsApplicable(context.get(), transformation_context));
+  good_extract_6.Apply(context.get(), &transformation_context);
   auto replacement_6 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(32, instruction_descriptor_6, 1), 107);
-  ASSERT_TRUE(replacement_6.IsApplicable(context.get(), fact_manager));
-  replacement_6.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      replacement_6.IsApplicable(context.get(), transformation_context));
+  replacement_6.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Replace %23 with %101[3] in '%51 = OpCopyObject %16 %23'
@@ -232,16 +260,19 @@
       MakeInstructionDescriptor(51, SpvOpCopyObject, 0);
   auto good_extract_7 =
       TransformationCompositeExtract(instruction_descriptor_7, 108, 101, {3});
-  ASSERT_TRUE(good_extract_7.IsApplicable(context.get(), fact_manager));
-  good_extract_7.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      good_extract_7.IsApplicable(context.get(), transformation_context));
+  good_extract_7.Apply(context.get(), &transformation_context);
   auto replacement_7 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(23, instruction_descriptor_7, 0), 108);
   // Bad: use id 0 is invalid
   auto bad_replacement_7 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(0, instruction_descriptor_7, 0), 108);
-  ASSERT_TRUE(replacement_7.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(bad_replacement_7.IsApplicable(context.get(), fact_manager));
-  replacement_7.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      replacement_7.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      bad_replacement_7.IsApplicable(context.get(), transformation_context));
+  replacement_7.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   const std::string after_transformation = R"(
@@ -380,32 +411,41 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
-  fact_manager.AddFact(MakeSynonymFact(23, {}, 100, {0}), context.get());
-  fact_manager.AddFact(MakeSynonymFact(25, {}, 100, {1}), context.get());
-  fact_manager.AddFact(MakeSynonymFact(50, {}, 100, {2}), context.get());
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
+
+  transformation_context.GetFactManager()->AddFact(
+      MakeSynonymFact(23, {}, 100, {0}), context.get());
+  transformation_context.GetFactManager()->AddFact(
+      MakeSynonymFact(25, {}, 100, {1}), context.get());
+  transformation_context.GetFactManager()->AddFact(
+      MakeSynonymFact(50, {}, 100, {2}), context.get());
 
   // Replace %23 with %100[0] in '%26 = OpFAdd %7 %23 %25'
   auto instruction_descriptor_1 = MakeInstructionDescriptor(26, SpvOpFAdd, 0);
   auto extract_1 =
       TransformationCompositeExtract(instruction_descriptor_1, 101, 100, {0});
-  ASSERT_TRUE(extract_1.IsApplicable(context.get(), fact_manager));
-  extract_1.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(extract_1.IsApplicable(context.get(), transformation_context));
+  extract_1.Apply(context.get(), &transformation_context);
   auto replacement_1 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(23, instruction_descriptor_1, 0), 101);
-  ASSERT_TRUE(replacement_1.IsApplicable(context.get(), fact_manager));
-  replacement_1.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      replacement_1.IsApplicable(context.get(), transformation_context));
+  replacement_1.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Replace %25 with %100[1] in '%26 = OpFAdd %7 %23 %25'
   auto instruction_descriptor_2 = MakeInstructionDescriptor(26, SpvOpFAdd, 0);
   auto extract_2 =
       TransformationCompositeExtract(instruction_descriptor_2, 102, 100, {1});
-  ASSERT_TRUE(extract_2.IsApplicable(context.get(), fact_manager));
-  extract_2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(extract_2.IsApplicable(context.get(), transformation_context));
+  extract_2.Apply(context.get(), &transformation_context);
   auto replacement_2 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(25, instruction_descriptor_2, 1), 102);
-  ASSERT_TRUE(replacement_2.IsApplicable(context.get(), fact_manager));
-  replacement_2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      replacement_2.IsApplicable(context.get(), transformation_context));
+  replacement_2.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   const std::string after_transformation = R"(
@@ -541,26 +581,37 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
-  fact_manager.AddFact(MakeSynonymFact(16, {}, 100, {0}), context.get());
-  fact_manager.AddFact(MakeSynonymFact(45, {}, 100, {1}), context.get());
-  fact_manager.AddFact(MakeSynonymFact(27, {}, 101, {0}), context.get());
-  fact_manager.AddFact(MakeSynonymFact(36, {}, 101, {1}), context.get());
-  fact_manager.AddFact(MakeSynonymFact(27, {}, 101, {2}), context.get());
-  fact_manager.AddFact(MakeSynonymFact(22, {}, 102, {0}), context.get());
-  fact_manager.AddFact(MakeSynonymFact(15, {}, 102, {1}), context.get());
+  transformation_context.GetFactManager()->AddFact(
+      MakeSynonymFact(16, {}, 100, {0}), context.get());
+  transformation_context.GetFactManager()->AddFact(
+      MakeSynonymFact(45, {}, 100, {1}), context.get());
+  transformation_context.GetFactManager()->AddFact(
+      MakeSynonymFact(27, {}, 101, {0}), context.get());
+  transformation_context.GetFactManager()->AddFact(
+      MakeSynonymFact(36, {}, 101, {1}), context.get());
+  transformation_context.GetFactManager()->AddFact(
+      MakeSynonymFact(27, {}, 101, {2}), context.get());
+  transformation_context.GetFactManager()->AddFact(
+      MakeSynonymFact(22, {}, 102, {0}), context.get());
+  transformation_context.GetFactManager()->AddFact(
+      MakeSynonymFact(15, {}, 102, {1}), context.get());
 
   // Replace %45 with %100[1] in '%46 = OpCompositeConstruct %32 %35 %45'
   auto instruction_descriptor_1 =
       MakeInstructionDescriptor(46, SpvOpCompositeConstruct, 0);
   auto extract_1 =
       TransformationCompositeExtract(instruction_descriptor_1, 201, 100, {1});
-  ASSERT_TRUE(extract_1.IsApplicable(context.get(), fact_manager));
-  extract_1.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(extract_1.IsApplicable(context.get(), transformation_context));
+  extract_1.Apply(context.get(), &transformation_context);
   auto replacement_1 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(45, instruction_descriptor_1, 1), 201);
-  ASSERT_TRUE(replacement_1.IsApplicable(context.get(), fact_manager));
-  replacement_1.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      replacement_1.IsApplicable(context.get(), transformation_context));
+  replacement_1.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Replace second occurrence of %27 with %101[0] in '%28 =
@@ -569,12 +620,13 @@
       MakeInstructionDescriptor(28, SpvOpCompositeConstruct, 0);
   auto extract_2 =
       TransformationCompositeExtract(instruction_descriptor_2, 202, 101, {0});
-  ASSERT_TRUE(extract_2.IsApplicable(context.get(), fact_manager));
-  extract_2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(extract_2.IsApplicable(context.get(), transformation_context));
+  extract_2.Apply(context.get(), &transformation_context);
   auto replacement_2 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(27, instruction_descriptor_2, 1), 202);
-  ASSERT_TRUE(replacement_2.IsApplicable(context.get(), fact_manager));
-  replacement_2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      replacement_2.IsApplicable(context.get(), transformation_context));
+  replacement_2.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Replace %36 with %101[1] in '%45 = OpCompositeConstruct %31 %36 %41 %44'
@@ -582,12 +634,13 @@
       MakeInstructionDescriptor(45, SpvOpCompositeConstruct, 0);
   auto extract_3 =
       TransformationCompositeExtract(instruction_descriptor_3, 203, 101, {1});
-  ASSERT_TRUE(extract_3.IsApplicable(context.get(), fact_manager));
-  extract_3.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(extract_3.IsApplicable(context.get(), transformation_context));
+  extract_3.Apply(context.get(), &transformation_context);
   auto replacement_3 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(36, instruction_descriptor_3, 0), 203);
-  ASSERT_TRUE(replacement_3.IsApplicable(context.get(), fact_manager));
-  replacement_3.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      replacement_3.IsApplicable(context.get(), transformation_context));
+  replacement_3.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Replace first occurrence of %27 with %101[2] in '%28 = OpCompositeConstruct
@@ -596,24 +649,26 @@
       MakeInstructionDescriptor(28, SpvOpCompositeConstruct, 0);
   auto extract_4 =
       TransformationCompositeExtract(instruction_descriptor_4, 204, 101, {2});
-  ASSERT_TRUE(extract_4.IsApplicable(context.get(), fact_manager));
-  extract_4.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(extract_4.IsApplicable(context.get(), transformation_context));
+  extract_4.Apply(context.get(), &transformation_context);
   auto replacement_4 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(27, instruction_descriptor_4, 0), 204);
-  ASSERT_TRUE(replacement_4.IsApplicable(context.get(), fact_manager));
-  replacement_4.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      replacement_4.IsApplicable(context.get(), transformation_context));
+  replacement_4.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Replace %22 with %102[0] in 'OpStore %23 %22'
   auto instruction_descriptor_5 = MakeInstructionDescriptor(23, SpvOpStore, 0);
   auto extract_5 =
       TransformationCompositeExtract(instruction_descriptor_5, 205, 102, {0});
-  ASSERT_TRUE(extract_5.IsApplicable(context.get(), fact_manager));
-  extract_5.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(extract_5.IsApplicable(context.get(), transformation_context));
+  extract_5.Apply(context.get(), &transformation_context);
   auto replacement_5 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(22, instruction_descriptor_5, 1), 205);
-  ASSERT_TRUE(replacement_5.IsApplicable(context.get(), fact_manager));
-  replacement_5.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      replacement_5.IsApplicable(context.get(), transformation_context));
+  replacement_5.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   const std::string after_transformation = R"(
@@ -816,38 +871,65 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
-  fact_manager.AddFact(MakeSynonymFact(20, {0}, 100, {0}), context.get());
-  fact_manager.AddFact(MakeSynonymFact(20, {1}, 100, {1}), context.get());
-  fact_manager.AddFact(MakeSynonymFact(20, {2}, 100, {2}), context.get());
-  fact_manager.AddFact(MakeSynonymFact(54, {}, 100, {3}), context.get());
-  fact_manager.AddFact(MakeSynonymFact(15, {0}, 101, {0}), context.get());
-  fact_manager.AddFact(MakeSynonymFact(15, {1}, 101, {1}), context.get());
-  fact_manager.AddFact(MakeSynonymFact(19, {0}, 101, {2}), context.get());
-  fact_manager.AddFact(MakeSynonymFact(19, {1}, 101, {3}), context.get());
-  fact_manager.AddFact(MakeSynonymFact(27, {}, 102, {0}), context.get());
-  fact_manager.AddFact(MakeSynonymFact(15, {0}, 102, {1}), context.get());
-  fact_manager.AddFact(MakeSynonymFact(15, {1}, 102, {2}), context.get());
-  fact_manager.AddFact(MakeSynonymFact(33, {}, 103, {0}), context.get());
-  fact_manager.AddFact(MakeSynonymFact(47, {0}, 103, {1}), context.get());
-  fact_manager.AddFact(MakeSynonymFact(47, {1}, 103, {2}), context.get());
-  fact_manager.AddFact(MakeSynonymFact(47, {2}, 103, {3}), context.get());
-  fact_manager.AddFact(MakeSynonymFact(42, {}, 104, {0}), context.get());
-  fact_manager.AddFact(MakeSynonymFact(45, {}, 104, {1}), context.get());
-  fact_manager.AddFact(MakeSynonymFact(38, {0}, 105, {0}), context.get());
-  fact_manager.AddFact(MakeSynonymFact(38, {1}, 105, {1}), context.get());
-  fact_manager.AddFact(MakeSynonymFact(46, {}, 105, {2}), context.get());
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
+
+  transformation_context.GetFactManager()->AddFact(
+      MakeSynonymFact(20, {0}, 100, {0}), context.get());
+  transformation_context.GetFactManager()->AddFact(
+      MakeSynonymFact(20, {1}, 100, {1}), context.get());
+  transformation_context.GetFactManager()->AddFact(
+      MakeSynonymFact(20, {2}, 100, {2}), context.get());
+  transformation_context.GetFactManager()->AddFact(
+      MakeSynonymFact(54, {}, 100, {3}), context.get());
+  transformation_context.GetFactManager()->AddFact(
+      MakeSynonymFact(15, {0}, 101, {0}), context.get());
+  transformation_context.GetFactManager()->AddFact(
+      MakeSynonymFact(15, {1}, 101, {1}), context.get());
+  transformation_context.GetFactManager()->AddFact(
+      MakeSynonymFact(19, {0}, 101, {2}), context.get());
+  transformation_context.GetFactManager()->AddFact(
+      MakeSynonymFact(19, {1}, 101, {3}), context.get());
+  transformation_context.GetFactManager()->AddFact(
+      MakeSynonymFact(27, {}, 102, {0}), context.get());
+  transformation_context.GetFactManager()->AddFact(
+      MakeSynonymFact(15, {0}, 102, {1}), context.get());
+  transformation_context.GetFactManager()->AddFact(
+      MakeSynonymFact(15, {1}, 102, {2}), context.get());
+  transformation_context.GetFactManager()->AddFact(
+      MakeSynonymFact(33, {}, 103, {0}), context.get());
+  transformation_context.GetFactManager()->AddFact(
+      MakeSynonymFact(47, {0}, 103, {1}), context.get());
+  transformation_context.GetFactManager()->AddFact(
+      MakeSynonymFact(47, {1}, 103, {2}), context.get());
+  transformation_context.GetFactManager()->AddFact(
+      MakeSynonymFact(47, {2}, 103, {3}), context.get());
+  transformation_context.GetFactManager()->AddFact(
+      MakeSynonymFact(42, {}, 104, {0}), context.get());
+  transformation_context.GetFactManager()->AddFact(
+      MakeSynonymFact(45, {}, 104, {1}), context.get());
+  transformation_context.GetFactManager()->AddFact(
+      MakeSynonymFact(38, {0}, 105, {0}), context.get());
+  transformation_context.GetFactManager()->AddFact(
+      MakeSynonymFact(38, {1}, 105, {1}), context.get());
+  transformation_context.GetFactManager()->AddFact(
+      MakeSynonymFact(46, {}, 105, {2}), context.get());
 
   // Replace %20 with %100[0:2] in '%80 = OpCopyObject %16 %20'
   auto instruction_descriptor_1 =
       MakeInstructionDescriptor(80, SpvOpCopyObject, 0);
   auto shuffle_1 = TransformationVectorShuffle(instruction_descriptor_1, 200,
                                                100, 100, {0, 1, 2});
-  ASSERT_TRUE(shuffle_1.IsApplicable(context.get(), fact_manager));
-  shuffle_1.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(shuffle_1.IsApplicable(context.get(), transformation_context));
+  shuffle_1.Apply(context.get(), &transformation_context);
+  fact_manager.ComputeClosureOfFacts(context.get(), 100);
+
   auto replacement_1 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(20, instruction_descriptor_1, 0), 200);
-  ASSERT_TRUE(replacement_1.IsApplicable(context.get(), fact_manager));
-  replacement_1.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      replacement_1.IsApplicable(context.get(), transformation_context));
+  replacement_1.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Replace %54 with %100[3] in '%56 = OpFOrdNotEqual %30 %54 %55'
@@ -856,24 +938,28 @@
   auto extract_2 =
       TransformationCompositeExtract(instruction_descriptor_2, 201, 100, {3});
 
-  ASSERT_TRUE(extract_2.IsApplicable(context.get(), fact_manager));
-  extract_2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(extract_2.IsApplicable(context.get(), transformation_context));
+  extract_2.Apply(context.get(), &transformation_context);
   auto replacement_2 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(54, instruction_descriptor_2, 0), 201);
-  ASSERT_TRUE(replacement_2.IsApplicable(context.get(), fact_manager));
-  replacement_2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      replacement_2.IsApplicable(context.get(), transformation_context));
+  replacement_2.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Replace %15 with %101[0:1] in 'OpStore %12 %15'
   auto instruction_descriptor_3 = MakeInstructionDescriptor(64, SpvOpStore, 0);
   auto shuffle_3 = TransformationVectorShuffle(instruction_descriptor_3, 202,
                                                101, 101, {0, 1});
-  ASSERT_TRUE(shuffle_3.IsApplicable(context.get(), fact_manager));
-  shuffle_3.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(shuffle_3.IsApplicable(context.get(), transformation_context));
+  shuffle_3.Apply(context.get(), &transformation_context);
+  fact_manager.ComputeClosureOfFacts(context.get(), 100);
+
   auto replacement_3 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(15, instruction_descriptor_3, 1), 202);
-  ASSERT_TRUE(replacement_3.IsApplicable(context.get(), fact_manager));
-  replacement_3.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      replacement_3.IsApplicable(context.get(), transformation_context));
+  replacement_3.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Replace %19 with %101[2:3] in '%81 = OpVectorShuffle %16 %19 %19 0 0 1'
@@ -881,12 +967,15 @@
       MakeInstructionDescriptor(81, SpvOpVectorShuffle, 0);
   auto shuffle_4 = TransformationVectorShuffle(instruction_descriptor_4, 203,
                                                101, 101, {2, 3});
-  ASSERT_TRUE(shuffle_4.IsApplicable(context.get(), fact_manager));
-  shuffle_4.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(shuffle_4.IsApplicable(context.get(), transformation_context));
+  shuffle_4.Apply(context.get(), &transformation_context);
+  fact_manager.ComputeClosureOfFacts(context.get(), 100);
+
   auto replacement_4 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(19, instruction_descriptor_4, 0), 203);
-  ASSERT_TRUE(replacement_4.IsApplicable(context.get(), fact_manager));
-  replacement_4.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      replacement_4.IsApplicable(context.get(), transformation_context));
+  replacement_4.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Replace %27 with %102[0] in '%82 = OpCompositeConstruct %21 %26 %27 %28
@@ -896,12 +985,13 @@
   auto extract_5 =
       TransformationCompositeExtract(instruction_descriptor_5, 204, 102, {0});
 
-  ASSERT_TRUE(extract_5.IsApplicable(context.get(), fact_manager));
-  extract_5.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(extract_5.IsApplicable(context.get(), transformation_context));
+  extract_5.Apply(context.get(), &transformation_context);
   auto replacement_5 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(27, instruction_descriptor_5, 1), 204);
-  ASSERT_TRUE(replacement_5.IsApplicable(context.get(), fact_manager));
-  replacement_5.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      replacement_5.IsApplicable(context.get(), transformation_context));
+  replacement_5.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Replace %15 with %102[1:2] in '%83 = OpCopyObject %10 %15'
@@ -909,12 +999,15 @@
       MakeInstructionDescriptor(83, SpvOpCopyObject, 0);
   auto shuffle_6 = TransformationVectorShuffle(instruction_descriptor_6, 205,
                                                102, 102, {1, 2});
-  ASSERT_TRUE(shuffle_6.IsApplicable(context.get(), fact_manager));
-  shuffle_6.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(shuffle_6.IsApplicable(context.get(), transformation_context));
+  shuffle_6.Apply(context.get(), &transformation_context);
+  fact_manager.ComputeClosureOfFacts(context.get(), 100);
+
   auto replacement_6 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(15, instruction_descriptor_6, 0), 205);
-  ASSERT_TRUE(replacement_6.IsApplicable(context.get(), fact_manager));
-  replacement_6.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      replacement_6.IsApplicable(context.get(), transformation_context));
+  replacement_6.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Replace %33 with %103[0] in '%86 = OpCopyObject %30 %33'
@@ -922,12 +1015,13 @@
       MakeInstructionDescriptor(86, SpvOpCopyObject, 0);
   auto extract_7 =
       TransformationCompositeExtract(instruction_descriptor_7, 206, 103, {0});
-  ASSERT_TRUE(extract_7.IsApplicable(context.get(), fact_manager));
-  extract_7.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(extract_7.IsApplicable(context.get(), transformation_context));
+  extract_7.Apply(context.get(), &transformation_context);
   auto replacement_7 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(33, instruction_descriptor_7, 0), 206);
-  ASSERT_TRUE(replacement_7.IsApplicable(context.get(), fact_manager));
-  replacement_7.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      replacement_7.IsApplicable(context.get(), transformation_context));
+  replacement_7.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Replace %47 with %103[1:3] in '%84 = OpCopyObject %39 %47'
@@ -935,12 +1029,15 @@
       MakeInstructionDescriptor(84, SpvOpCopyObject, 0);
   auto shuffle_8 = TransformationVectorShuffle(instruction_descriptor_8, 207,
                                                103, 103, {1, 2, 3});
-  ASSERT_TRUE(shuffle_8.IsApplicable(context.get(), fact_manager));
-  shuffle_8.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(shuffle_8.IsApplicable(context.get(), transformation_context));
+  shuffle_8.Apply(context.get(), &transformation_context);
+  fact_manager.ComputeClosureOfFacts(context.get(), 100);
+
   auto replacement_8 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(47, instruction_descriptor_8, 0), 207);
-  ASSERT_TRUE(replacement_8.IsApplicable(context.get(), fact_manager));
-  replacement_8.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      replacement_8.IsApplicable(context.get(), transformation_context));
+  replacement_8.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Replace %42 with %104[0] in '%85 = OpCopyObject %30 %42'
@@ -948,12 +1045,13 @@
       MakeInstructionDescriptor(85, SpvOpCopyObject, 0);
   auto extract_9 =
       TransformationCompositeExtract(instruction_descriptor_9, 208, 104, {0});
-  ASSERT_TRUE(extract_9.IsApplicable(context.get(), fact_manager));
-  extract_9.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(extract_9.IsApplicable(context.get(), transformation_context));
+  extract_9.Apply(context.get(), &transformation_context);
   auto replacement_9 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(42, instruction_descriptor_9, 0), 208);
-  ASSERT_TRUE(replacement_9.IsApplicable(context.get(), fact_manager));
-  replacement_9.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      replacement_9.IsApplicable(context.get(), transformation_context));
+  replacement_9.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Replace %45 with %104[1] in '%63 = OpLogicalOr %30 %45 %46'
@@ -961,24 +1059,28 @@
       MakeInstructionDescriptor(63, SpvOpLogicalOr, 0);
   auto extract_10 =
       TransformationCompositeExtract(instruction_descriptor_10, 209, 104, {1});
-  ASSERT_TRUE(extract_10.IsApplicable(context.get(), fact_manager));
-  extract_10.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(extract_10.IsApplicable(context.get(), transformation_context));
+  extract_10.Apply(context.get(), &transformation_context);
   auto replacement_10 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(45, instruction_descriptor_10, 0), 209);
-  ASSERT_TRUE(replacement_10.IsApplicable(context.get(), fact_manager));
-  replacement_10.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      replacement_10.IsApplicable(context.get(), transformation_context));
+  replacement_10.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Replace %38 with %105[0:1] in 'OpStore %36 %38'
   auto instruction_descriptor_11 = MakeInstructionDescriptor(85, SpvOpStore, 0);
   auto shuffle_11 = TransformationVectorShuffle(instruction_descriptor_11, 210,
                                                 105, 105, {0, 1});
-  ASSERT_TRUE(shuffle_11.IsApplicable(context.get(), fact_manager));
-  shuffle_11.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(shuffle_11.IsApplicable(context.get(), transformation_context));
+  shuffle_11.Apply(context.get(), &transformation_context);
+  fact_manager.ComputeClosureOfFacts(context.get(), 100);
+
   auto replacement_11 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(38, instruction_descriptor_11, 1), 210);
-  ASSERT_TRUE(replacement_11.IsApplicable(context.get(), fact_manager));
-  replacement_11.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      replacement_11.IsApplicable(context.get(), transformation_context));
+  replacement_11.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Replace %46 with %105[2] in '%62 = OpLogicalAnd %30 %45 %46'
@@ -986,12 +1088,13 @@
       MakeInstructionDescriptor(62, SpvOpLogicalAnd, 0);
   auto extract_12 =
       TransformationCompositeExtract(instruction_descriptor_12, 211, 105, {2});
-  ASSERT_TRUE(extract_12.IsApplicable(context.get(), fact_manager));
-  extract_12.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(extract_12.IsApplicable(context.get(), transformation_context));
+  extract_12.Apply(context.get(), &transformation_context);
   auto replacement_12 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(46, instruction_descriptor_12, 1), 211);
-  ASSERT_TRUE(replacement_12.IsApplicable(context.get(), fact_manager));
-  replacement_12.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      replacement_12.IsApplicable(context.get(), transformation_context));
+  replacement_12.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   const std::string after_transformation = R"(
diff --git a/third_party/spirv-tools/src/test/fuzz/equivalence_relation_test.cpp b/third_party/spirv-tools/src/test/fuzz/equivalence_relation_test.cpp
index 3f2ea58..280aa3a 100644
--- a/third_party/spirv-tools/src/test/fuzz/equivalence_relation_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/equivalence_relation_test.cpp
@@ -47,6 +47,10 @@
   EquivalenceRelation<uint32_t, UInt32Hash, UInt32Equals> relation;
   ASSERT_TRUE(relation.GetAllKnownValues().empty());
 
+  for (uint32_t element = 0; element < 100; element++) {
+    relation.Register(element);
+  }
+
   for (uint32_t element = 2; element < 80; element += 2) {
     relation.MakeEquivalent(0, element);
     relation.MakeEquivalent(element - 1, element + 1);
@@ -123,6 +127,11 @@
   EquivalenceRelation<uint32_t, UInt32Hash, UInt32Equals> relation2;
 
   for (uint32_t i = 0; i < 1000; ++i) {
+    relation1.Register(i);
+    relation2.Register(i);
+  }
+
+  for (uint32_t i = 0; i < 1000; ++i) {
     if (i >= 10) {
       relation1.MakeEquivalent(i, i - 10);
       relation2.MakeEquivalent(i, i - 10);
diff --git a/third_party/spirv-tools/src/test/fuzz/fact_manager_test.cpp b/third_party/spirv-tools/src/test/fuzz/fact_manager_test.cpp
index 2c79f12..04f0372 100644
--- a/third_party/spirv-tools/src/test/fuzz/fact_manager_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/fact_manager_test.cpp
@@ -738,393 +738,6 @@
                              uniform_buffer_element_descriptor));
 }
 
-TEST(FactManagerTest, DataSynonymFacts) {
-  // The SPIR-V types and constants come from the following code.  The body of
-  // the SPIR-V function then constructs a composite that is synonymous with
-  // myT.
-  //
-  // #version 310 es
-  //
-  // precision highp float;
-  //
-  // struct S {
-  //   int a;
-  //   uvec2 b;
-  // };
-  //
-  // struct T {
-  //   bool c[5];
-  //   mat4x2 d;
-  //   S e;
-  // };
-  //
-  // void main() {
-  //   T myT = T(bool[5](true, false, true, false, true),
-  //             mat4x2(vec2(1.0, 2.0), vec2(3.0, 4.0),
-  // 	           vec2(5.0, 6.0), vec2(7.0, 8.0)),
-  //             S(10, uvec2(100u, 200u)));
-  // }
-
-  std::string shader = R"(
-               OpCapability Shader
-          %1 = OpExtInstImport "GLSL.std.450"
-               OpMemoryModel Logical GLSL450
-               OpEntryPoint Fragment %4 "main"
-               OpExecutionMode %4 OriginUpperLeft
-               OpSource ESSL 310
-               OpName %4 "main"
-               OpName %15 "S"
-               OpMemberName %15 0 "a"
-               OpMemberName %15 1 "b"
-               OpName %16 "T"
-               OpMemberName %16 0 "c"
-               OpMemberName %16 1 "d"
-               OpMemberName %16 2 "e"
-               OpName %18 "myT"
-               OpMemberDecorate %15 0 RelaxedPrecision
-               OpMemberDecorate %15 1 RelaxedPrecision
-          %2 = OpTypeVoid
-          %3 = OpTypeFunction %2
-          %6 = OpTypeBool
-          %7 = OpTypeInt 32 0
-          %8 = OpConstant %7 5
-          %9 = OpTypeArray %6 %8
-         %10 = OpTypeFloat 32
-         %11 = OpTypeVector %10 2
-         %12 = OpTypeMatrix %11 4
-         %13 = OpTypeInt 32 1
-         %14 = OpTypeVector %7 2
-         %15 = OpTypeStruct %13 %14
-         %16 = OpTypeStruct %9 %12 %15
-         %17 = OpTypePointer Function %16
-         %19 = OpConstantTrue %6
-         %20 = OpConstantFalse %6
-         %21 = OpConstantComposite %9 %19 %20 %19 %20 %19
-         %22 = OpConstant %10 1
-         %23 = OpConstant %10 2
-         %24 = OpConstantComposite %11 %22 %23
-         %25 = OpConstant %10 3
-         %26 = OpConstant %10 4
-         %27 = OpConstantComposite %11 %25 %26
-         %28 = OpConstant %10 5
-         %29 = OpConstant %10 6
-         %30 = OpConstantComposite %11 %28 %29
-         %31 = OpConstant %10 7
-         %32 = OpConstant %10 8
-         %33 = OpConstantComposite %11 %31 %32
-         %34 = OpConstantComposite %12 %24 %27 %30 %33
-         %35 = OpConstant %13 10
-         %36 = OpConstant %7 100
-         %37 = OpConstant %7 200
-         %38 = OpConstantComposite %14 %36 %37
-         %39 = OpConstantComposite %15 %35 %38
-         %40 = OpConstantComposite %16 %21 %34 %39
-          %4 = OpFunction %2 None %3
-          %5 = OpLabel
-         %18 = OpVariable %17 Function
-               OpStore %18 %40
-        %100 = OpCompositeConstruct %9 %19 %20 %19 %20 %19
-        %101 = OpCompositeConstruct %11 %22 %23
-        %102 = OpCompositeConstruct %11 %25 %26
-        %103 = OpCompositeConstruct %11 %28 %29
-        %104 = OpCompositeConstruct %11 %31 %32
-        %105 = OpCompositeConstruct %12 %101 %102 %103 %104
-        %106 = OpCompositeConstruct %14 %36 %37
-        %107 = OpCompositeConstruct %15 %35 %106
-        %108 = OpCompositeConstruct %16 %100 %105 %107
-               OpReturn
-               OpFunctionEnd
-  )";
-
-  const auto env = SPV_ENV_UNIVERSAL_1_3;
-  const auto consumer = nullptr;
-  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
-  ASSERT_TRUE(IsValid(env, context.get()));
-
-  FactManager fact_manager;
-
-  ASSERT_FALSE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(24, {}), MakeDataDescriptor(101, {}), context.get()));
-  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(24, {0}),
-                                         MakeDataDescriptor(101, {0}),
-                                         context.get()));
-  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(24, {1}),
-                                         MakeDataDescriptor(101, {1}),
-                                         context.get()));
-  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(24, {0}),
-                                         MakeDataDescriptor(101, {1}),
-                                         context.get()));
-
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(24, {}),
-                                  MakeDataDescriptor(101, {}), context.get());
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(24, {}), MakeDataDescriptor(101, {}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(24, {0}),
-                                        MakeDataDescriptor(101, {0}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(24, {1}),
-                                        MakeDataDescriptor(101, {1}),
-                                        context.get()));
-  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(24, {0}),
-                                         MakeDataDescriptor(101, {1}),
-                                         context.get()));
-
-  ASSERT_FALSE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(27, {}), MakeDataDescriptor(102, {}), context.get()));
-  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(27, {0}),
-                                         MakeDataDescriptor(102, {0}),
-                                         context.get()));
-  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(27, {1}),
-                                         MakeDataDescriptor(102, {1}),
-                                         context.get()));
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(27, {0}),
-                                  MakeDataDescriptor(102, {0}), context.get());
-  ASSERT_FALSE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(27, {}), MakeDataDescriptor(102, {}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(27, {0}),
-                                        MakeDataDescriptor(102, {0}),
-                                        context.get()));
-  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(27, {1}),
-                                         MakeDataDescriptor(102, {1}),
-                                         context.get()));
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(27, {1}),
-                                  MakeDataDescriptor(102, {1}), context.get());
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(27, {}), MakeDataDescriptor(102, {}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(27, {0}),
-                                        MakeDataDescriptor(102, {0}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(27, {1}),
-                                        MakeDataDescriptor(102, {1}),
-                                        context.get()));
-
-  ASSERT_FALSE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(30, {}), MakeDataDescriptor(103, {}), context.get()));
-  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(30, {0}),
-                                         MakeDataDescriptor(103, {0}),
-                                         context.get()));
-  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(30, {1}),
-                                         MakeDataDescriptor(103, {1}),
-                                         context.get()));
-  ASSERT_FALSE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(33, {}), MakeDataDescriptor(104, {}), context.get()));
-  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(33, {0}),
-                                         MakeDataDescriptor(104, {0}),
-                                         context.get()));
-  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(33, {1}),
-                                         MakeDataDescriptor(104, {1}),
-                                         context.get()));
-  ASSERT_FALSE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(34, {}), MakeDataDescriptor(105, {}), context.get()));
-  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(34, {0}),
-                                         MakeDataDescriptor(105, {0}),
-                                         context.get()));
-  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(34, {1}),
-                                         MakeDataDescriptor(105, {1}),
-                                         context.get()));
-  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(34, {2}),
-                                         MakeDataDescriptor(105, {2}),
-                                         context.get()));
-  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(34, {3}),
-                                         MakeDataDescriptor(105, {3}),
-                                         context.get()));
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(30, {}),
-                                  MakeDataDescriptor(103, {}), context.get());
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(33, {}),
-                                  MakeDataDescriptor(104, {}), context.get());
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(34, {0}),
-                                  MakeDataDescriptor(105, {0}), context.get());
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(34, {1}),
-                                  MakeDataDescriptor(105, {1}), context.get());
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(34, {2}),
-                                  MakeDataDescriptor(105, {2}), context.get());
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(30, {}), MakeDataDescriptor(103, {}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(30, {0}),
-                                        MakeDataDescriptor(103, {0}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(30, {1}),
-                                        MakeDataDescriptor(103, {1}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(33, {}), MakeDataDescriptor(104, {}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(33, {0}),
-                                        MakeDataDescriptor(104, {0}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(33, {1}),
-                                        MakeDataDescriptor(104, {1}),
-                                        context.get()));
-  ASSERT_FALSE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(34, {}), MakeDataDescriptor(105, {}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(34, {0}),
-                                        MakeDataDescriptor(105, {0}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(34, {1}),
-                                        MakeDataDescriptor(105, {1}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(34, {2}),
-                                        MakeDataDescriptor(105, {2}),
-                                        context.get()));
-  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(34, {3}),
-                                         MakeDataDescriptor(105, {3}),
-                                         context.get()));
-
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(34, {3}),
-                                  MakeDataDescriptor(105, {3}), context.get());
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(33, {0}),
-                                        MakeDataDescriptor(104, {0}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(34, {3}),
-                                        MakeDataDescriptor(105, {3}),
-                                        context.get()));
-
-  ASSERT_FALSE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(21, {}), MakeDataDescriptor(100, {}), context.get()));
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(21, {0}),
-                                  MakeDataDescriptor(100, {0}), context.get());
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(21, {1}),
-                                  MakeDataDescriptor(100, {1}), context.get());
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(21, {2}),
-                                  MakeDataDescriptor(100, {2}), context.get());
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(21, {3}),
-                                  MakeDataDescriptor(100, {3}), context.get());
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(21, {4}),
-                                  MakeDataDescriptor(100, {4}), context.get());
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(21, {}), MakeDataDescriptor(100, {}), context.get()));
-
-  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(39, {0}),
-                                         MakeDataDescriptor(107, {0}),
-                                         context.get()));
-  ASSERT_FALSE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(35, {}), MakeDataDescriptor(39, {0}), context.get()));
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(39, {0}),
-                                  MakeDataDescriptor(35, {}), context.get());
-  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(39, {0}),
-                                         MakeDataDescriptor(107, {0}),
-                                         context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(35, {}), MakeDataDescriptor(39, {0}), context.get()));
-
-  ASSERT_FALSE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(38, {0}), MakeDataDescriptor(36, {}), context.get()));
-  ASSERT_FALSE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(38, {1}), MakeDataDescriptor(37, {}), context.get()));
-  ASSERT_FALSE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(106, {0}), MakeDataDescriptor(36, {}), context.get()));
-  ASSERT_FALSE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(106, {1}), MakeDataDescriptor(37, {}), context.get()));
-  ASSERT_FALSE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(38, {}), MakeDataDescriptor(106, {}), context.get()));
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(38, {0}),
-                                  MakeDataDescriptor(36, {}), context.get());
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(106, {0}),
-                                  MakeDataDescriptor(36, {}), context.get());
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(38, {1}),
-                                  MakeDataDescriptor(37, {}), context.get());
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(106, {1}),
-                                  MakeDataDescriptor(37, {}), context.get());
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(38, {0}), MakeDataDescriptor(36, {}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(38, {1}), MakeDataDescriptor(37, {}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(106, {0}), MakeDataDescriptor(36, {}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(106, {1}), MakeDataDescriptor(37, {}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(38, {}), MakeDataDescriptor(106, {}), context.get()));
-
-  ASSERT_FALSE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(40, {}), MakeDataDescriptor(108, {}), context.get()));
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(107, {0}),
-                                  MakeDataDescriptor(35, {}), context.get());
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(40, {0}),
-                                  MakeDataDescriptor(108, {0}), context.get());
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(40, {1}),
-                                  MakeDataDescriptor(108, {1}), context.get());
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(40, {2}),
-                                  MakeDataDescriptor(108, {2}), context.get());
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(40, {}), MakeDataDescriptor(108, {}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {0}),
-                                        MakeDataDescriptor(108, {0}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1}),
-                                        MakeDataDescriptor(108, {1}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {2}),
-                                        MakeDataDescriptor(108, {2}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {0, 0}),
-                                        MakeDataDescriptor(108, {0, 0}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {0, 1}),
-                                        MakeDataDescriptor(108, {0, 1}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {0, 2}),
-                                        MakeDataDescriptor(108, {0, 2}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {0, 3}),
-                                        MakeDataDescriptor(108, {0, 3}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {0, 4}),
-                                        MakeDataDescriptor(108, {0, 4}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 0}),
-                                        MakeDataDescriptor(108, {1, 0}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 1}),
-                                        MakeDataDescriptor(108, {1, 1}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 2}),
-                                        MakeDataDescriptor(108, {1, 2}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 3}),
-                                        MakeDataDescriptor(108, {1, 3}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 0, 0}),
-                                        MakeDataDescriptor(108, {1, 0, 0}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 1, 0}),
-                                        MakeDataDescriptor(108, {1, 1, 0}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 2, 0}),
-                                        MakeDataDescriptor(108, {1, 2, 0}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 3, 0}),
-                                        MakeDataDescriptor(108, {1, 3, 0}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 0, 1}),
-                                        MakeDataDescriptor(108, {1, 0, 1}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 1, 1}),
-                                        MakeDataDescriptor(108, {1, 1, 1}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 2, 1}),
-                                        MakeDataDescriptor(108, {1, 2, 1}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 3, 1}),
-                                        MakeDataDescriptor(108, {1, 3, 1}),
-                                        context.get()));
-
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {2, 0}),
-                                        MakeDataDescriptor(108, {2, 0}),
-                                        context.get()));
-
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {2, 1}),
-                                        MakeDataDescriptor(108, {2, 1}),
-                                        context.get()));
-
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {2, 1, 0}),
-                                        MakeDataDescriptor(108, {2, 1, 0}),
-                                        context.get()));
-
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {2, 1, 1}),
-                                        MakeDataDescriptor(108, {2, 1, 1}),
-                                        context.get()));
-}
-
 TEST(FactManagerTest, RecursiveAdditionOfFacts) {
   std::string shader = R"(
                OpCapability Shader
@@ -1157,20 +770,16 @@
   fact_manager.AddFactDataSynonym(MakeDataDescriptor(10, {}),
                                   MakeDataDescriptor(11, {2}), context.get());
 
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(10, {}), MakeDataDescriptor(11, {2}), context.get()));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(10, {}),
+                                        MakeDataDescriptor(11, {2})));
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(10, {0}),
-                                        MakeDataDescriptor(11, {2, 0}),
-                                        context.get()));
+                                        MakeDataDescriptor(11, {2, 0})));
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(10, {1}),
-                                        MakeDataDescriptor(11, {2, 1}),
-                                        context.get()));
+                                        MakeDataDescriptor(11, {2, 1})));
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(10, {2}),
-                                        MakeDataDescriptor(11, {2, 2}),
-                                        context.get()));
+                                        MakeDataDescriptor(11, {2, 2})));
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(10, {3}),
-                                        MakeDataDescriptor(11, {2, 3}),
-                                        context.get()));
+                                        MakeDataDescriptor(11, {2, 3})));
 }
 
 TEST(FactManagerTest, LogicalNotEquationFacts) {
@@ -1209,14 +818,14 @@
   fact_manager.AddFactIdEquation(14, SpvOpLogicalNot, {7}, context.get());
   fact_manager.AddFactIdEquation(17, SpvOpLogicalNot, {16}, context.get());
 
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(15, {}), MakeDataDescriptor(7, {}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(17, {}), MakeDataDescriptor(7, {}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(15, {}), MakeDataDescriptor(17, {}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(16, {}), MakeDataDescriptor(14, {}), context.get()));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(15, {}),
+                                        MakeDataDescriptor(7, {})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(17, {}),
+                                        MakeDataDescriptor(7, {})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(15, {}),
+                                        MakeDataDescriptor(17, {})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(16, {}),
+                                        MakeDataDescriptor(14, {})));
 }
 
 TEST(FactManagerTest, SignedNegateEquationFacts) {
@@ -1249,8 +858,8 @@
   fact_manager.AddFactIdEquation(14, SpvOpSNegate, {7}, context.get());
   fact_manager.AddFactIdEquation(15, SpvOpSNegate, {14}, context.get());
 
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(7, {}), MakeDataDescriptor(15, {}), context.get()));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(7, {}),
+                                        MakeDataDescriptor(15, {})));
 }
 
 TEST(FactManagerTest, AddSubNegateFacts1) {
@@ -1302,12 +911,12 @@
                                   MakeDataDescriptor(22, {}), context.get());
   fact_manager.AddFactIdEquation(24, SpvOpSNegate, {23}, context.get());
 
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(19, {}), MakeDataDescriptor(15, {}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(20, {}), MakeDataDescriptor(16, {}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(24, {}), MakeDataDescriptor(15, {}), context.get()));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(19, {}),
+                                        MakeDataDescriptor(15, {})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(20, {}),
+                                        MakeDataDescriptor(16, {})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(24, {}),
+                                        MakeDataDescriptor(15, {})));
 }
 
 TEST(FactManagerTest, AddSubNegateFacts2) {
@@ -1347,30 +956,102 @@
   fact_manager.AddFactIdEquation(14, SpvOpISub, {15, 16}, context.get());
   fact_manager.AddFactIdEquation(17, SpvOpIAdd, {14, 16}, context.get());
 
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(17, {}), MakeDataDescriptor(15, {}), context.get()));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(17, {}),
+                                        MakeDataDescriptor(15, {})));
 
   fact_manager.AddFactIdEquation(18, SpvOpIAdd, {16, 14}, context.get());
 
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(18, {}), MakeDataDescriptor(15, {}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(17, {}), MakeDataDescriptor(18, {}), context.get()));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(18, {}),
+                                        MakeDataDescriptor(15, {})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(17, {}),
+                                        MakeDataDescriptor(18, {})));
 
   fact_manager.AddFactIdEquation(19, SpvOpISub, {14, 15}, context.get());
   fact_manager.AddFactIdEquation(20, SpvOpSNegate, {19}, context.get());
 
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(20, {}), MakeDataDescriptor(16, {}), context.get()));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(20, {}),
+                                        MakeDataDescriptor(16, {})));
 
   fact_manager.AddFactIdEquation(21, SpvOpISub, {14, 19}, context.get());
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(21, {}), MakeDataDescriptor(15, {}), context.get()));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(21, {}),
+                                        MakeDataDescriptor(15, {})));
 
   fact_manager.AddFactIdEquation(22, SpvOpISub, {14, 18}, context.get());
   fact_manager.AddFactIdEquation(23, SpvOpSNegate, {22}, context.get());
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(23, {}), MakeDataDescriptor(16, {}), context.get()));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(23, {}),
+                                        MakeDataDescriptor(16, {})));
+}
+
+TEST(FactManagerTest, EquationAndEquivalenceFacts) {
+  std::string shader = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %12 "main"
+               OpExecutionMode %12 OriginUpperLeft
+               OpSource ESSL 310
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %6 = OpTypeInt 32 1
+         %15 = OpConstant %6 24
+         %16 = OpConstant %6 37
+         %12 = OpFunction %2 None %3
+         %13 = OpLabel
+         %14 = OpISub %6 %15 %16
+        %114 = OpCopyObject %6 %14
+         %17 = OpIAdd %6 %114 %16 ; ==> synonymous(%17, %15)
+         %18 = OpIAdd %6 %16 %114 ; ==> synonymous(%17, %18, %15)
+         %19 = OpISub %6 %114 %15
+        %119 = OpCopyObject %6 %19
+         %20 = OpSNegate %6 %119 ; ==> synonymous(%20, %16)
+         %21 = OpISub %6 %14 %19 ; ==> synonymous(%21, %15)
+         %22 = OpISub %6 %14 %18
+        %220 = OpCopyObject %6 %22
+         %23 = OpSNegate %6 %220 ; ==> synonymous(%23, %16)
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  const auto env = SPV_ENV_UNIVERSAL_1_3;
+  const auto consumer = nullptr;
+  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+  ASSERT_TRUE(IsValid(env, context.get()));
+
+  FactManager fact_manager;
+
+  fact_manager.AddFactIdEquation(14, SpvOpISub, {15, 16}, context.get());
+  fact_manager.AddFactDataSynonym(MakeDataDescriptor(114, {}),
+                                  MakeDataDescriptor(14, {}), context.get());
+  fact_manager.AddFactIdEquation(17, SpvOpIAdd, {114, 16}, context.get());
+
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(17, {}),
+                                        MakeDataDescriptor(15, {})));
+
+  fact_manager.AddFactIdEquation(18, SpvOpIAdd, {16, 114}, context.get());
+
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(18, {}),
+                                        MakeDataDescriptor(15, {})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(17, {}),
+                                        MakeDataDescriptor(18, {})));
+
+  fact_manager.AddFactIdEquation(19, SpvOpISub, {14, 15}, context.get());
+  fact_manager.AddFactDataSynonym(MakeDataDescriptor(119, {}),
+                                  MakeDataDescriptor(19, {}), context.get());
+  fact_manager.AddFactIdEquation(20, SpvOpSNegate, {119}, context.get());
+
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(20, {}),
+                                        MakeDataDescriptor(16, {})));
+
+  fact_manager.AddFactIdEquation(21, SpvOpISub, {14, 19}, context.get());
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(21, {}),
+                                        MakeDataDescriptor(15, {})));
+
+  fact_manager.AddFactIdEquation(22, SpvOpISub, {14, 18}, context.get());
+  fact_manager.AddFactDataSynonym(MakeDataDescriptor(22, {}),
+                                  MakeDataDescriptor(220, {}), context.get());
+  fact_manager.AddFactIdEquation(23, SpvOpSNegate, {220}, context.get());
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(23, {}),
+                                        MakeDataDescriptor(16, {})));
 }
 
 }  // namespace
diff --git a/third_party/spirv-tools/src/test/fuzz/fuzzer_pass_add_useful_constructs_test.cpp b/third_party/spirv-tools/src/test/fuzz/fuzzer_pass_add_useful_constructs_test.cpp
index 89f006e..90d1c84 100644
--- a/third_party/spirv-tools/src/test/fuzz/fuzzer_pass_add_useful_constructs_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/fuzzer_pass_add_useful_constructs_test.cpp
@@ -64,10 +64,14 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
+
   FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0).get(), 100);
   protobufs::TransformationSequence transformation_sequence;
 
-  FuzzerPassAddUsefulConstructs pass(context.get(), &fact_manager,
+  FuzzerPassAddUsefulConstructs pass(context.get(), &transformation_context,
                                      &fuzzer_context, &transformation_sequence);
   pass.Apply();
   ASSERT_TRUE(IsValid(env, context.get()));
@@ -173,6 +177,10 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
+
   FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0).get(), 100);
   protobufs::TransformationSequence transformation_sequence;
 
@@ -292,7 +300,7 @@
               context->get_constant_mgr()->FindConstant(&int_constant_8));
   }
 
-  FuzzerPassAddUsefulConstructs pass(context.get(), &fact_manager,
+  FuzzerPassAddUsefulConstructs pass(context.get(), &transformation_context,
                                      &fuzzer_context, &transformation_sequence);
   pass.Apply();
   ASSERT_TRUE(IsValid(env, context.get()));
diff --git a/third_party/spirv-tools/src/test/fuzz/fuzzer_pass_construct_composites_test.cpp b/third_party/spirv-tools/src/test/fuzz/fuzzer_pass_construct_composites_test.cpp
new file mode 100644
index 0000000..cc21f74
--- /dev/null
+++ b/third_party/spirv-tools/src/test/fuzz/fuzzer_pass_construct_composites_test.cpp
@@ -0,0 +1,187 @@
+// Copyright (c) 2020 Google LLC
+//
+// 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
+//
+//     http://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.
+
+#include "source/fuzz/fuzzer_pass_construct_composites.h"
+#include "source/fuzz/pseudo_random_generator.h"
+#include "test/fuzz/fuzz_test_util.h"
+
+namespace spvtools {
+namespace fuzz {
+namespace {
+
+TEST(FuzzerPassConstructCompositesTest, IsomorphicStructs) {
+  // This test declares various isomorphic structs, and a struct that is made up
+  // of these isomorphic structs.  The pass to construct composites is then
+  // applied several times to check that no issues arise related to using a
+  // value of one struct type when a value of an isomorphic struct type is
+  // required.
+
+  std::string shader = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main"
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 310
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %6 = OpTypeFloat 32
+          %7 = OpConstant %6 0
+          %8 = OpTypeStruct %6 %6 %6
+          %9 = OpTypeStruct %6 %6 %6
+         %10 = OpTypeStruct %6 %6 %6
+         %11 = OpTypeStruct %6 %6 %6
+         %12 = OpTypeStruct %6 %6 %6
+         %13 = OpTypeStruct %8 %9 %10 %11 %12
+         %14 = OpConstantComposite %8 %7 %7 %7
+         %15 = OpConstantComposite %9 %7 %7 %7
+         %16 = OpConstantComposite %10 %7 %7 %7
+         %17 = OpConstantComposite %11 %7 %7 %7
+         %18 = OpConstantComposite %12 %7 %7 %7
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+               OpNop
+               OpNop
+               OpNop
+               OpNop
+               OpNop
+               OpNop
+               OpNop
+               OpNop
+               OpNop
+               OpNop
+               OpNop
+               OpNop
+               OpNop
+               OpNop
+               OpNop
+               OpNop
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  const auto env = SPV_ENV_UNIVERSAL_1_3;
+  const auto consumer = nullptr;
+
+  auto prng = MakeUnique<PseudoRandomGenerator>(0);
+
+  for (uint32_t i = 0; i < 10; i++) {
+    const auto context =
+        BuildModule(env, consumer, shader, kFuzzAssembleOption);
+    ASSERT_TRUE(IsValid(env, context.get()));
+
+    FactManager fact_manager;
+    spvtools::ValidatorOptions validator_options;
+    TransformationContext transformation_context(&fact_manager,
+                                                 validator_options);
+
+    FuzzerContext fuzzer_context(prng.get(), 100);
+    protobufs::TransformationSequence transformation_sequence;
+
+    FuzzerPassConstructComposites fuzzer_pass(
+        context.get(), &transformation_context, &fuzzer_context,
+        &transformation_sequence);
+
+    fuzzer_pass.Apply();
+
+    // We just check that the result is valid.
+    ASSERT_TRUE(IsValid(env, context.get()));
+  }
+}
+
+TEST(FuzzerPassConstructCompositesTest, IsomorphicArrays) {
+  // This test declares various isomorphic arrays, and a struct that is made up
+  // of these isomorphic arrays.  The pass to construct composites is then
+  // applied several times to check that no issues arise related to using a
+  // value of one array type when a value of an isomorphic array type is
+  // required.
+
+  std::string shader = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main"
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 310
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %6 = OpTypeFloat 32
+         %50 = OpTypeInt 32 0
+         %51 = OpConstant %50 3
+          %7 = OpConstant %6 0
+          %8 = OpTypeArray %6 %51
+          %9 = OpTypeArray %6 %51
+         %10 = OpTypeArray %6 %51
+         %11 = OpTypeArray %6 %51
+         %12 = OpTypeArray %6 %51
+         %13 = OpTypeStruct %8 %9 %10 %11 %12
+         %14 = OpConstantComposite %8 %7 %7 %7
+         %15 = OpConstantComposite %9 %7 %7 %7
+         %16 = OpConstantComposite %10 %7 %7 %7
+         %17 = OpConstantComposite %11 %7 %7 %7
+         %18 = OpConstantComposite %12 %7 %7 %7
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+               OpNop
+               OpNop
+               OpNop
+               OpNop
+               OpNop
+               OpNop
+               OpNop
+               OpNop
+               OpNop
+               OpNop
+               OpNop
+               OpNop
+               OpNop
+               OpNop
+               OpNop
+               OpNop
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  const auto env = SPV_ENV_UNIVERSAL_1_3;
+  const auto consumer = nullptr;
+
+  auto prng = MakeUnique<PseudoRandomGenerator>(0);
+
+  for (uint32_t i = 0; i < 10; i++) {
+    const auto context =
+        BuildModule(env, consumer, shader, kFuzzAssembleOption);
+    ASSERT_TRUE(IsValid(env, context.get()));
+
+    FactManager fact_manager;
+    spvtools::ValidatorOptions validator_options;
+    TransformationContext transformation_context(&fact_manager,
+                                                 validator_options);
+
+    FuzzerContext fuzzer_context(prng.get(), 100);
+    protobufs::TransformationSequence transformation_sequence;
+
+    FuzzerPassConstructComposites fuzzer_pass(
+        context.get(), &transformation_context, &fuzzer_context,
+        &transformation_sequence);
+
+    fuzzer_pass.Apply();
+
+    // We just check that the result is valid.
+    ASSERT_TRUE(IsValid(env, context.get()));
+  }
+}
+
+}  // namespace
+}  // namespace fuzz
+}  // namespace spvtools
diff --git a/third_party/spirv-tools/src/test/fuzz/fuzzer_pass_donate_modules_test.cpp b/third_party/spirv-tools/src/test/fuzz/fuzzer_pass_donate_modules_test.cpp
index dc7ba3a..0833c1d 100644
--- a/third_party/spirv-tools/src/test/fuzz/fuzzer_pass_donate_modules_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/fuzzer_pass_donate_modules_test.cpp
@@ -194,14 +194,17 @@
   ASSERT_TRUE(IsValid(env, donor_context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
-  auto prng = MakeUnique<PseudoRandomGenerator>(0);
-  FuzzerContext fuzzer_context(prng.get(), 100);
+  PseudoRandomGenerator prng(0);
+  FuzzerContext fuzzer_context(&prng, 100);
   protobufs::TransformationSequence transformation_sequence;
 
-  FuzzerPassDonateModules fuzzer_pass(recipient_context.get(), &fact_manager,
-                                      &fuzzer_context, &transformation_sequence,
-                                      {});
+  FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
+                                      &transformation_context, &fuzzer_context,
+                                      &transformation_sequence, {});
 
   fuzzer_pass.DonateSingleModule(donor_context.get(), false);
 
@@ -269,13 +272,17 @@
   ASSERT_TRUE(IsValid(env, donor_context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
-  FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0).get(), 100);
+  PseudoRandomGenerator prng(0);
+  FuzzerContext fuzzer_context(&prng, 100);
   protobufs::TransformationSequence transformation_sequence;
 
-  FuzzerPassDonateModules fuzzer_pass(recipient_context.get(), &fact_manager,
-                                      &fuzzer_context, &transformation_sequence,
-                                      {});
+  FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
+                                      &transformation_context, &fuzzer_context,
+                                      &transformation_sequence, {});
 
   fuzzer_pass.DonateSingleModule(donor_context.get(), false);
 
@@ -393,13 +400,17 @@
   ASSERT_TRUE(IsValid(env, donor_context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
-  FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0).get(), 100);
+  PseudoRandomGenerator prng(0);
+  FuzzerContext fuzzer_context(&prng, 100);
   protobufs::TransformationSequence transformation_sequence;
 
-  FuzzerPassDonateModules fuzzer_pass(recipient_context.get(), &fact_manager,
-                                      &fuzzer_context, &transformation_sequence,
-                                      {});
+  FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
+                                      &transformation_context, &fuzzer_context,
+                                      &transformation_sequence, {});
 
   fuzzer_pass.DonateSingleModule(donor_context.get(), false);
 
@@ -481,13 +492,17 @@
   ASSERT_TRUE(IsValid(env, donor_context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
-  FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0).get(), 100);
+  PseudoRandomGenerator prng(0);
+  FuzzerContext fuzzer_context(&prng, 100);
   protobufs::TransformationSequence transformation_sequence;
 
-  FuzzerPassDonateModules fuzzer_pass(recipient_context.get(), &fact_manager,
-                                      &fuzzer_context, &transformation_sequence,
-                                      {});
+  FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
+                                      &transformation_context, &fuzzer_context,
+                                      &transformation_sequence, {});
 
   fuzzer_pass.DonateSingleModule(donor_context.get(), false);
 
@@ -496,6 +511,993 @@
   ASSERT_TRUE(IsValid(env, recipient_context.get()));
 }
 
+TEST(FuzzerPassDonateModulesTest, DonateOpConstantNull) {
+  std::string recipient_shader = R"(
+               OpCapability Shader
+               OpCapability ImageQuery
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main"
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 320
+               OpSourceExtension "GL_EXT_samplerless_texture_functions"
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  std::string donor_shader = R"(
+               OpCapability Shader
+               OpCapability ImageQuery
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main"
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 320
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %6 = OpTypeFloat 32
+          %7 = OpTypePointer Private %6
+          %8 = OpConstantNull %7
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  const auto env = SPV_ENV_UNIVERSAL_1_3;
+  const auto consumer = nullptr;
+  const auto recipient_context =
+      BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption);
+  ASSERT_TRUE(IsValid(env, recipient_context.get()));
+
+  const auto donor_context =
+      BuildModule(env, consumer, donor_shader, kFuzzAssembleOption);
+  ASSERT_TRUE(IsValid(env, donor_context.get()));
+
+  FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
+
+  PseudoRandomGenerator prng(0);
+  FuzzerContext fuzzer_context(&prng, 100);
+  protobufs::TransformationSequence transformation_sequence;
+
+  FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
+                                      &transformation_context, &fuzzer_context,
+                                      &transformation_sequence, {});
+
+  fuzzer_pass.DonateSingleModule(donor_context.get(), false);
+
+  // We just check that the result is valid.  Checking to what it should be
+  // exactly equal to would be very fragile.
+  ASSERT_TRUE(IsValid(env, recipient_context.get()));
+}
+
+TEST(FuzzerPassDonateModulesTest, DonateCodeThatUsesImages) {
+  std::string recipient_shader = R"(
+               OpCapability Shader
+               OpCapability ImageQuery
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main"
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 320
+               OpSourceExtension "GL_EXT_samplerless_texture_functions"
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  std::string donor_shader = R"(
+               OpCapability Shader
+               OpCapability ImageQuery
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main"
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 320
+               OpSourceExtension "GL_EXT_samplerless_texture_functions"
+               OpName %4 "main"
+               OpName %10 "mySampler"
+               OpName %21 "myTexture"
+               OpName %33 "v"
+               OpDecorate %10 RelaxedPrecision
+               OpDecorate %10 DescriptorSet 0
+               OpDecorate %10 Binding 0
+               OpDecorate %11 RelaxedPrecision
+               OpDecorate %21 RelaxedPrecision
+               OpDecorate %21 DescriptorSet 0
+               OpDecorate %21 Binding 1
+               OpDecorate %22 RelaxedPrecision
+               OpDecorate %34 RelaxedPrecision
+               OpDecorate %40 RelaxedPrecision
+               OpDecorate %42 RelaxedPrecision
+               OpDecorate %43 RelaxedPrecision
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %6 = OpTypeFloat 32
+          %7 = OpTypeImage %6 2D 0 0 0 1 Unknown
+          %8 = OpTypeSampledImage %7
+          %9 = OpTypePointer UniformConstant %8
+         %10 = OpVariable %9 UniformConstant
+         %12 = OpTypeInt 32 1
+         %13 = OpConstant %12 2
+         %15 = OpTypeVector %12 2
+         %17 = OpTypeInt 32 0
+         %18 = OpConstant %17 0
+         %20 = OpTypePointer UniformConstant %7
+         %21 = OpVariable %20 UniformConstant
+         %23 = OpConstant %12 1
+         %25 = OpConstant %17 1
+         %27 = OpTypeBool
+         %31 = OpTypeVector %6 4
+         %32 = OpTypePointer Function %31
+         %35 = OpConstantComposite %15 %23 %23
+         %36 = OpConstant %12 3
+         %37 = OpConstant %12 4
+         %38 = OpConstantComposite %15 %36 %37
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+         %33 = OpVariable %32 Function
+         %11 = OpLoad %8 %10
+         %14 = OpImage %7 %11
+         %16 = OpImageQuerySizeLod %15 %14 %13
+         %19 = OpCompositeExtract %12 %16 0
+         %22 = OpLoad %7 %21
+         %24 = OpImageQuerySizeLod %15 %22 %23
+         %26 = OpCompositeExtract %12 %24 1
+         %28 = OpSGreaterThan %27 %19 %26
+               OpSelectionMerge %30 None
+               OpBranchConditional %28 %29 %41
+         %29 = OpLabel
+         %34 = OpLoad %8 %10
+         %39 = OpImage %7 %34
+         %40 = OpImageFetch %31 %39 %35 Lod|ConstOffset %13 %38
+               OpStore %33 %40
+               OpBranch %30
+         %41 = OpLabel
+         %42 = OpLoad %7 %21
+         %43 = OpImageFetch %31 %42 %35 Lod|ConstOffset %13 %38
+               OpStore %33 %43
+               OpBranch %30
+         %30 = OpLabel
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  const auto env = SPV_ENV_UNIVERSAL_1_3;
+  const auto consumer = nullptr;
+  const auto recipient_context =
+      BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption);
+  ASSERT_TRUE(IsValid(env, recipient_context.get()));
+
+  const auto donor_context =
+      BuildModule(env, consumer, donor_shader, kFuzzAssembleOption);
+  ASSERT_TRUE(IsValid(env, donor_context.get()));
+
+  FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
+
+  PseudoRandomGenerator prng(0);
+  FuzzerContext fuzzer_context(&prng, 100);
+  protobufs::TransformationSequence transformation_sequence;
+
+  FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
+                                      &transformation_context, &fuzzer_context,
+                                      &transformation_sequence, {});
+
+  fuzzer_pass.DonateSingleModule(donor_context.get(), false);
+
+  // We just check that the result is valid.  Checking to what it should be
+  // exactly equal to would be very fragile.
+  ASSERT_TRUE(IsValid(env, recipient_context.get()));
+}
+
+TEST(FuzzerPassDonateModulesTest, DonateCodeThatUsesSampler) {
+  std::string recipient_shader = R"(
+               OpCapability Shader
+               OpCapability ImageQuery
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main"
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 320
+               OpSourceExtension "GL_EXT_samplerless_texture_functions"
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  std::string donor_shader = R"(
+               OpCapability Shader
+               OpCapability ImageQuery
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main"
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 320
+               OpDecorate %16 DescriptorSet 0
+               OpDecorate %16 Binding 0
+               OpDecorate %12 DescriptorSet 0
+               OpDecorate %12 Binding 64
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+         %23 = OpTypeFloat 32
+          %6 = OpTypeImage %23 2D 2 0 0 1 Unknown
+         %47 = OpTypePointer UniformConstant %6
+         %12 = OpVariable %47 UniformConstant
+         %15 = OpTypeSampler
+         %55 = OpTypePointer UniformConstant %15
+         %17 = OpTypeSampledImage %6
+         %16 = OpVariable %55 UniformConstant
+         %37 = OpTypeVector %23 4
+        %109 = OpConstant %23 0
+         %66 = OpConstantComposite %37 %109 %109 %109 %109
+         %56 = OpTypeBool
+         %54 = OpConstantTrue %56
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+               OpBranch %50
+         %50 = OpLabel
+         %51 = OpPhi %37 %66 %5 %111 %53
+               OpLoopMerge %52 %53 None
+               OpBranchConditional %54 %53 %52
+         %53 = OpLabel
+        %106 = OpLoad %6 %12
+        %107 = OpLoad %15 %16
+        %110 = OpSampledImage %17 %106 %107
+        %111 = OpImageSampleImplicitLod %37 %110 %66 Bias %109
+               OpBranch %50
+         %52 = OpLabel
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  const auto env = SPV_ENV_UNIVERSAL_1_3;
+  const auto consumer = nullptr;
+  const auto recipient_context =
+      BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption);
+  ASSERT_TRUE(IsValid(env, recipient_context.get()));
+
+  const auto donor_context =
+      BuildModule(env, consumer, donor_shader, kFuzzAssembleOption);
+  ASSERT_TRUE(IsValid(env, donor_context.get()));
+
+  FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
+
+  PseudoRandomGenerator prng(0);
+  FuzzerContext fuzzer_context(&prng, 100);
+  protobufs::TransformationSequence transformation_sequence;
+
+  FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
+                                      &transformation_context, &fuzzer_context,
+                                      &transformation_sequence, {});
+
+  fuzzer_pass.DonateSingleModule(donor_context.get(), false);
+
+  // We just check that the result is valid.  Checking to what it should be
+  // exactly equal to would be very fragile.
+  ASSERT_TRUE(IsValid(env, recipient_context.get()));
+}
+
+TEST(FuzzerPassDonateModulesTest, DonateCodeThatUsesImageStructField) {
+  std::string recipient_shader = R"(
+               OpCapability Shader
+               OpCapability ImageQuery
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main"
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 320
+               OpSourceExtension "GL_EXT_samplerless_texture_functions"
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  std::string donor_shader = R"(
+               OpCapability Shader
+               OpCapability ImageQuery
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main"
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 320
+               OpSourceExtension "GL_EXT_samplerless_texture_functions"
+               OpName %4 "main"
+               OpName %10 "mySampler"
+               OpName %21 "myTexture"
+               OpName %33 "v"
+               OpDecorate %10 RelaxedPrecision
+               OpDecorate %10 DescriptorSet 0
+               OpDecorate %10 Binding 0
+               OpDecorate %11 RelaxedPrecision
+               OpDecorate %21 RelaxedPrecision
+               OpDecorate %21 DescriptorSet 0
+               OpDecorate %21 Binding 1
+               OpDecorate %22 RelaxedPrecision
+               OpDecorate %34 RelaxedPrecision
+               OpDecorate %40 RelaxedPrecision
+               OpDecorate %42 RelaxedPrecision
+               OpDecorate %43 RelaxedPrecision
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %6 = OpTypeFloat 32
+          %7 = OpTypeImage %6 2D 0 0 0 1 Unknown
+          %8 = OpTypeSampledImage %7
+          %9 = OpTypePointer UniformConstant %8
+         %10 = OpVariable %9 UniformConstant
+         %12 = OpTypeInt 32 1
+         %13 = OpConstant %12 2
+         %15 = OpTypeVector %12 2
+         %17 = OpTypeInt 32 0
+         %18 = OpConstant %17 0
+         %20 = OpTypePointer UniformConstant %7
+         %21 = OpVariable %20 UniformConstant
+         %23 = OpConstant %12 1
+         %25 = OpConstant %17 1
+         %27 = OpTypeBool
+         %31 = OpTypeVector %6 4
+         %32 = OpTypePointer Function %31
+         %35 = OpConstantComposite %15 %23 %23
+         %36 = OpConstant %12 3
+         %37 = OpConstant %12 4
+         %38 = OpConstantComposite %15 %36 %37
+        %201 = OpTypeStruct %7 %7
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+         %33 = OpVariable %32 Function
+         %11 = OpLoad %8 %10
+         %14 = OpImage %7 %11
+         %22 = OpLoad %7 %21
+        %200 = OpCompositeConstruct %201 %14 %22
+        %202 = OpCompositeExtract %7 %200 0
+        %203 = OpCompositeExtract %7 %200 1
+         %24 = OpImageQuerySizeLod %15 %203 %23
+         %16 = OpImageQuerySizeLod %15 %202 %13
+         %26 = OpCompositeExtract %12 %24 1
+         %19 = OpCompositeExtract %12 %16 0
+         %28 = OpSGreaterThan %27 %19 %26
+               OpSelectionMerge %30 None
+               OpBranchConditional %28 %29 %41
+         %29 = OpLabel
+         %34 = OpLoad %8 %10
+         %39 = OpImage %7 %34
+         %40 = OpImageFetch %31 %39 %35 Lod|ConstOffset %13 %38
+               OpStore %33 %40
+               OpBranch %30
+         %41 = OpLabel
+         %42 = OpLoad %7 %21
+         %43 = OpImageFetch %31 %42 %35 Lod|ConstOffset %13 %38
+               OpStore %33 %43
+               OpBranch %30
+         %30 = OpLabel
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  const auto env = SPV_ENV_UNIVERSAL_1_3;
+  const auto consumer = nullptr;
+  const auto recipient_context =
+      BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption);
+  ASSERT_TRUE(IsValid(env, recipient_context.get()));
+
+  const auto donor_context =
+      BuildModule(env, consumer, donor_shader, kFuzzAssembleOption);
+  ASSERT_TRUE(IsValid(env, donor_context.get()));
+
+  FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
+
+  PseudoRandomGenerator prng(0);
+  FuzzerContext fuzzer_context(&prng, 100);
+  protobufs::TransformationSequence transformation_sequence;
+
+  FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
+                                      &transformation_context, &fuzzer_context,
+                                      &transformation_sequence, {});
+
+  fuzzer_pass.DonateSingleModule(donor_context.get(), false);
+
+  // We just check that the result is valid.  Checking to what it should be
+  // exactly equal to would be very fragile.
+  ASSERT_TRUE(IsValid(env, recipient_context.get()));
+}
+
+TEST(FuzzerPassDonateModulesTest, DonateCodeThatUsesImageFunctionParameter) {
+  std::string recipient_shader = R"(
+               OpCapability Shader
+               OpCapability ImageQuery
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main"
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 320
+               OpSourceExtension "GL_EXT_samplerless_texture_functions"
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  std::string donor_shader = R"(
+               OpCapability Shader
+               OpCapability ImageQuery
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main"
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 320
+               OpSourceExtension "GL_EXT_samplerless_texture_functions"
+               OpName %4 "main"
+               OpName %10 "mySampler"
+               OpName %21 "myTexture"
+               OpName %33 "v"
+               OpDecorate %10 RelaxedPrecision
+               OpDecorate %10 DescriptorSet 0
+               OpDecorate %10 Binding 0
+               OpDecorate %11 RelaxedPrecision
+               OpDecorate %21 RelaxedPrecision
+               OpDecorate %21 DescriptorSet 0
+               OpDecorate %21 Binding 1
+               OpDecorate %22 RelaxedPrecision
+               OpDecorate %34 RelaxedPrecision
+               OpDecorate %40 RelaxedPrecision
+               OpDecorate %42 RelaxedPrecision
+               OpDecorate %43 RelaxedPrecision
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %6 = OpTypeFloat 32
+          %7 = OpTypeImage %6 2D 0 0 0 1 Unknown
+          %8 = OpTypeSampledImage %7
+          %9 = OpTypePointer UniformConstant %8
+         %10 = OpVariable %9 UniformConstant
+         %12 = OpTypeInt 32 1
+         %13 = OpConstant %12 2
+         %15 = OpTypeVector %12 2
+         %17 = OpTypeInt 32 0
+         %18 = OpConstant %17 0
+         %20 = OpTypePointer UniformConstant %7
+         %21 = OpVariable %20 UniformConstant
+         %23 = OpConstant %12 1
+         %25 = OpConstant %17 1
+         %27 = OpTypeBool
+         %31 = OpTypeVector %6 4
+         %32 = OpTypePointer Function %31
+         %35 = OpConstantComposite %15 %23 %23
+         %36 = OpConstant %12 3
+         %37 = OpConstant %12 4
+         %38 = OpConstantComposite %15 %36 %37
+        %201 = OpTypeFunction %15 %7 %12
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+         %33 = OpVariable %32 Function
+         %11 = OpLoad %8 %10
+         %14 = OpImage %7 %11
+         %16 = OpFunctionCall %15 %200 %14 %13
+         %19 = OpCompositeExtract %12 %16 0
+         %22 = OpLoad %7 %21
+         %24 = OpImageQuerySizeLod %15 %22 %23
+         %26 = OpCompositeExtract %12 %24 1
+         %28 = OpSGreaterThan %27 %19 %26
+               OpSelectionMerge %30 None
+               OpBranchConditional %28 %29 %41
+         %29 = OpLabel
+         %34 = OpLoad %8 %10
+         %39 = OpImage %7 %34
+         %40 = OpImageFetch %31 %39 %35 Lod|ConstOffset %13 %38
+               OpStore %33 %40
+               OpBranch %30
+         %41 = OpLabel
+         %42 = OpLoad %7 %21
+         %43 = OpImageFetch %31 %42 %35 Lod|ConstOffset %13 %38
+               OpStore %33 %43
+               OpBranch %30
+         %30 = OpLabel
+               OpReturn
+               OpFunctionEnd
+        %200 = OpFunction %15 None %201
+        %202 = OpFunctionParameter %7
+        %203 = OpFunctionParameter %12
+        %204 = OpLabel
+        %205 = OpImageQuerySizeLod %15 %202 %203
+               OpReturnValue %205
+               OpFunctionEnd
+  )";
+
+  const auto env = SPV_ENV_UNIVERSAL_1_3;
+  const auto consumer = nullptr;
+  const auto recipient_context =
+      BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption);
+  ASSERT_TRUE(IsValid(env, recipient_context.get()));
+
+  const auto donor_context =
+      BuildModule(env, consumer, donor_shader, kFuzzAssembleOption);
+  ASSERT_TRUE(IsValid(env, donor_context.get()));
+
+  FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
+
+  PseudoRandomGenerator prng(0);
+  FuzzerContext fuzzer_context(&prng, 100);
+  protobufs::TransformationSequence transformation_sequence;
+
+  FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
+                                      &transformation_context, &fuzzer_context,
+                                      &transformation_sequence, {});
+
+  fuzzer_pass.DonateSingleModule(donor_context.get(), false);
+
+  // We just check that the result is valid.  Checking to what it should be
+  // exactly equal to would be very fragile.
+  ASSERT_TRUE(IsValid(env, recipient_context.get()));
+}
+
+TEST(FuzzerPassDonateModulesTest, DonateShaderWithImageStorageClass) {
+  std::string recipient_shader = R"(
+               OpCapability Shader
+               OpCapability ImageQuery
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main"
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 320
+               OpSourceExtension "GL_EXT_samplerless_texture_functions"
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  std::string donor_shader = R"(
+               OpCapability Shader
+               OpCapability SampledBuffer
+               OpCapability ImageBuffer
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %2 "MainPSPacked"
+               OpExecutionMode %2 OriginUpperLeft
+               OpDecorate %18 DescriptorSet 0
+               OpDecorate %18 Binding 128
+         %49 = OpTypeInt 32 0
+         %50 = OpTypeFloat 32
+         %58 = OpConstant %50 1
+         %66 = OpConstant %49 0
+         %87 = OpTypeVector %50 2
+         %88 = OpConstantComposite %87 %58 %58
+         %17 = OpTypeImage %49 2D 2 0 0 2 R32ui
+        %118 = OpTypePointer UniformConstant %17
+        %123 = OpTypeVector %49 2
+        %132 = OpTypeVoid
+        %133 = OpTypeFunction %132
+        %142 = OpTypePointer Image %49
+         %18 = OpVariable %118 UniformConstant
+          %2 = OpFunction %132 None %133
+        %153 = OpLabel
+        %495 = OpConvertFToU %123 %88
+        %501 = OpImageTexelPointer %142 %18 %495 %66
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  const auto env = SPV_ENV_UNIVERSAL_1_3;
+  const auto consumer = nullptr;
+  const auto recipient_context =
+      BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption);
+  ASSERT_TRUE(IsValid(env, recipient_context.get()));
+
+  const auto donor_context =
+      BuildModule(env, consumer, donor_shader, kFuzzAssembleOption);
+  ASSERT_TRUE(IsValid(env, donor_context.get()));
+
+  FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
+
+  PseudoRandomGenerator prng(0);
+  FuzzerContext fuzzer_context(&prng, 100);
+  protobufs::TransformationSequence transformation_sequence;
+
+  FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
+                                      &transformation_context, &fuzzer_context,
+                                      &transformation_sequence, {});
+
+  fuzzer_pass.DonateSingleModule(donor_context.get(), true);
+
+  // We just check that the result is valid.  Checking to what it should be
+  // exactly equal to would be very fragile.
+  ASSERT_TRUE(IsValid(env, recipient_context.get()));
+}
+
+TEST(FuzzerPassDonateModulesTest, DonateComputeShaderWithRuntimeArray) {
+  std::string recipient_shader = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %4 "main"
+               OpExecutionMode %4 LocalSize 1 1 1
+               OpSource ESSL 310
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  std::string donor_shader = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %4 "main"
+               OpExecutionMode %4 LocalSize 1 1 1
+               OpSource ESSL 310
+               OpDecorate %9 ArrayStride 4
+               OpMemberDecorate %10 0 Offset 0
+               OpDecorate %10 BufferBlock
+               OpDecorate %12 DescriptorSet 0
+               OpDecorate %12 Binding 0
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %6 = OpTypeInt 32 1
+          %7 = OpTypePointer Function %6
+          %9 = OpTypeRuntimeArray %6
+         %10 = OpTypeStruct %9
+         %11 = OpTypePointer Uniform %10
+         %12 = OpVariable %11 Uniform
+         %13 = OpTypeInt 32 0
+         %16 = OpConstant %6 0
+         %18 = OpConstant %6 1
+         %20 = OpTypePointer Uniform %6
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+          %8 = OpVariable %7 Function
+         %14 = OpArrayLength %13 %12 0
+         %15 = OpBitcast %6 %14
+               OpStore %8 %15
+         %17 = OpLoad %6 %8
+         %19 = OpISub %6 %17 %18
+         %21 = OpAccessChain %20 %12 %16 %19
+               OpStore %21 %16
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  const auto env = SPV_ENV_UNIVERSAL_1_3;
+  const auto consumer = nullptr;
+  const auto recipient_context =
+      BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption);
+  ASSERT_TRUE(IsValid(env, recipient_context.get()));
+
+  const auto donor_context =
+      BuildModule(env, consumer, donor_shader, kFuzzAssembleOption);
+  ASSERT_TRUE(IsValid(env, donor_context.get()));
+
+  FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
+
+  PseudoRandomGenerator prng(0);
+  FuzzerContext fuzzer_context(&prng, 100);
+  protobufs::TransformationSequence transformation_sequence;
+
+  FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
+                                      &transformation_context, &fuzzer_context,
+                                      &transformation_sequence, {});
+
+  fuzzer_pass.DonateSingleModule(donor_context.get(), false);
+
+  // We just check that the result is valid.  Checking to what it should be
+  // exactly equal to would be very fragile.
+  ASSERT_TRUE(IsValid(env, recipient_context.get()));
+}
+
+TEST(FuzzerPassDonateModulesTest, DonateComputeShaderWithRuntimeArrayLivesafe) {
+  std::string recipient_shader = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %4 "main"
+               OpExecutionMode %4 LocalSize 1 1 1
+               OpSource ESSL 310
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  std::string donor_shader = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %4 "main"
+               OpExecutionMode %4 LocalSize 1 1 1
+               OpSource ESSL 310
+               OpDecorate %16 ArrayStride 4
+               OpMemberDecorate %17 0 Offset 0
+               OpDecorate %17 BufferBlock
+               OpDecorate %19 DescriptorSet 0
+               OpDecorate %19 Binding 0
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %6 = OpTypeInt 32 1
+          %7 = OpTypePointer Function %6
+          %9 = OpConstant %6 0
+         %16 = OpTypeRuntimeArray %6
+         %17 = OpTypeStruct %16
+         %18 = OpTypePointer Uniform %17
+         %19 = OpVariable %18 Uniform
+         %20 = OpTypeInt 32 0
+         %23 = OpTypeBool
+         %26 = OpConstant %6 32
+         %27 = OpTypePointer Uniform %6
+         %30 = OpConstant %6 1
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+          %8 = OpVariable %7 Function
+               OpStore %8 %9
+               OpBranch %10
+         %10 = OpLabel
+               OpLoopMerge %12 %13 None
+               OpBranch %14
+         %14 = OpLabel
+         %15 = OpLoad %6 %8
+         %21 = OpArrayLength %20 %19 0
+         %22 = OpBitcast %6 %21
+         %24 = OpSLessThan %23 %15 %22
+               OpBranchConditional %24 %11 %12
+         %11 = OpLabel
+         %25 = OpLoad %6 %8
+         %28 = OpAccessChain %27 %19 %9 %25
+               OpStore %28 %26
+               OpBranch %13
+         %13 = OpLabel
+         %29 = OpLoad %6 %8
+         %31 = OpIAdd %6 %29 %30
+               OpStore %8 %31
+               OpBranch %10
+         %12 = OpLabel
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  const auto env = SPV_ENV_UNIVERSAL_1_3;
+  const auto consumer = nullptr;
+  const auto recipient_context =
+      BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption);
+  ASSERT_TRUE(IsValid(env, recipient_context.get()));
+
+  const auto donor_context =
+      BuildModule(env, consumer, donor_shader, kFuzzAssembleOption);
+  ASSERT_TRUE(IsValid(env, donor_context.get()));
+
+  FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
+
+  PseudoRandomGenerator prng(0);
+  FuzzerContext fuzzer_context(&prng, 100);
+  protobufs::TransformationSequence transformation_sequence;
+
+  FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
+                                      &transformation_context, &fuzzer_context,
+                                      &transformation_sequence, {});
+
+  fuzzer_pass.DonateSingleModule(donor_context.get(), true);
+
+  // We just check that the result is valid.  Checking to what it should be
+  // exactly equal to would be very fragile.
+  ASSERT_TRUE(IsValid(env, recipient_context.get()));
+}
+
+TEST(FuzzerPassDonateModulesTest, DonateComputeShaderWithWorkgroupVariables) {
+  std::string recipient_shader = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %4 "main"
+               OpExecutionMode %4 LocalSize 1 1 1
+               OpSource ESSL 310
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  std::string donor_shader = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %4 "main"
+               OpExecutionMode %4 LocalSize 1 1 1
+               OpSource ESSL 310
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %6 = OpTypeInt 32 1
+          %7 = OpTypePointer Workgroup %6
+          %8 = OpVariable %7 Workgroup
+          %9 = OpConstant %6 2
+         %10 = OpVariable %7 Workgroup
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+               OpStore %8 %9
+         %11 = OpLoad %6 %8
+               OpStore %10 %11
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  const auto env = SPV_ENV_UNIVERSAL_1_3;
+  const auto consumer = nullptr;
+  const auto recipient_context =
+      BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption);
+  ASSERT_TRUE(IsValid(env, recipient_context.get()));
+
+  const auto donor_context =
+      BuildModule(env, consumer, donor_shader, kFuzzAssembleOption);
+  ASSERT_TRUE(IsValid(env, donor_context.get()));
+
+  FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
+
+  PseudoRandomGenerator prng(0);
+  FuzzerContext fuzzer_context(&prng, 100);
+  protobufs::TransformationSequence transformation_sequence;
+
+  FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
+                                      &transformation_context, &fuzzer_context,
+                                      &transformation_sequence, {});
+
+  fuzzer_pass.DonateSingleModule(donor_context.get(), true);
+
+  // We just check that the result is valid.  Checking to what it should be
+  // exactly equal to would be very fragile.
+  ASSERT_TRUE(IsValid(env, recipient_context.get()));
+}
+
+TEST(FuzzerPassDonateModulesTest, DonateComputeShaderWithAtomics) {
+  std::string recipient_shader = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %4 "main"
+               OpExecutionMode %4 LocalSize 1 1 1
+               OpSource ESSL 310
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  std::string donor_shader = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %4 "main"
+               OpExecutionMode %4 LocalSize 1 1 1
+               OpSource ESSL 310
+               OpMemberDecorate %9 0 Offset 0
+               OpDecorate %9 BufferBlock
+               OpDecorate %11 DescriptorSet 0
+               OpDecorate %11 Binding 0
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %6 = OpTypeInt 32 0
+          %7 = OpTypePointer Function %6
+          %9 = OpTypeStruct %6
+         %10 = OpTypePointer Uniform %9
+         %11 = OpVariable %10 Uniform
+         %12 = OpTypeInt 32 1
+         %13 = OpConstant %12 0
+         %14 = OpTypePointer Uniform %6
+         %16 = OpConstant %6 1
+         %17 = OpConstant %6 0
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+          %8 = OpVariable %7 Function
+         %15 = OpAccessChain %14 %11 %13
+         %18 = OpAtomicIAdd %6 %15 %16 %17 %16
+               OpStore %8 %18
+         %19 = OpAccessChain %14 %11 %13
+         %20 = OpLoad %6 %8
+         %21 = OpAtomicUMin %6 %19 %16 %17 %20
+               OpStore %8 %21
+         %22 = OpAccessChain %14 %11 %13
+         %23 = OpLoad %6 %8
+         %24 = OpAtomicUMax %6 %22 %16 %17 %23
+               OpStore %8 %24
+         %25 = OpAccessChain %14 %11 %13
+         %26 = OpLoad %6 %8
+         %27 = OpAtomicAnd %6 %25 %16 %17 %26
+               OpStore %8 %27
+         %28 = OpAccessChain %14 %11 %13
+         %29 = OpLoad %6 %8
+         %30 = OpAtomicOr %6 %28 %16 %17 %29
+               OpStore %8 %30
+         %31 = OpAccessChain %14 %11 %13
+         %32 = OpLoad %6 %8
+         %33 = OpAtomicXor %6 %31 %16 %17 %32
+               OpStore %8 %33
+         %34 = OpAccessChain %14 %11 %13
+         %35 = OpLoad %6 %8
+         %36 = OpAtomicExchange %6 %34 %16 %17 %35
+               OpStore %8 %36
+         %37 = OpAccessChain %14 %11 %13
+         %38 = OpLoad %6 %8
+         %39 = OpAtomicCompareExchange %6 %37 %16 %17 %17 %16 %38
+               OpStore %8 %39
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  const auto env = SPV_ENV_UNIVERSAL_1_3;
+  const auto consumer = nullptr;
+  const auto recipient_context =
+      BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption);
+  ASSERT_TRUE(IsValid(env, recipient_context.get()));
+
+  const auto donor_context =
+      BuildModule(env, consumer, donor_shader, kFuzzAssembleOption);
+  ASSERT_TRUE(IsValid(env, donor_context.get()));
+
+  FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
+
+  PseudoRandomGenerator prng(0);
+  FuzzerContext fuzzer_context(&prng, 100);
+  protobufs::TransformationSequence transformation_sequence;
+
+  FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
+                                      &transformation_context, &fuzzer_context,
+                                      &transformation_sequence, {});
+
+  fuzzer_pass.DonateSingleModule(donor_context.get(), true);
+
+  // We just check that the result is valid.  Checking to what it should be
+  // exactly equal to would be very fragile.
+  ASSERT_TRUE(IsValid(env, recipient_context.get()));
+}
+
 TEST(FuzzerPassDonateModulesTest, Miscellaneous1) {
   std::string recipient_shader = R"(
                OpCapability Shader
@@ -658,13 +1660,16 @@
   ASSERT_TRUE(IsValid(env, donor_context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0).get(), 100);
   protobufs::TransformationSequence transformation_sequence;
 
-  FuzzerPassDonateModules fuzzer_pass(recipient_context.get(), &fact_manager,
-                                      &fuzzer_context, &transformation_sequence,
-                                      {});
+  FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
+                                      &transformation_context, &fuzzer_context,
+                                      &transformation_sequence, {});
 
   fuzzer_pass.DonateSingleModule(donor_context.get(), false);
 
diff --git a/third_party/spirv-tools/src/test/fuzz/fuzzer_replayer_test.cpp b/third_party/spirv-tools/src/test/fuzz/fuzzer_replayer_test.cpp
index b91393e..1e7c643 100644
--- a/third_party/spirv-tools/src/test/fuzz/fuzzer_replayer_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/fuzzer_replayer_test.cpp
@@ -1553,6 +1553,47 @@
                OpFunctionEnd
   )";
 
+// Some miscellaneous SPIR-V.
+
+const std::string kTestShader6 = R"(
+               OpCapability Shader
+               OpCapability SampledBuffer
+               OpCapability ImageBuffer
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %2 "main" %40 %41
+               OpExecutionMode %2 OriginUpperLeft
+               OpSource GLSL 450
+               OpDecorate %40 DescriptorSet 0
+               OpDecorate %40 Binding 69
+               OpDecorate %41 DescriptorSet 0
+               OpDecorate %41 Binding 1
+         %54 = OpTypeFloat 32
+         %76 = OpTypeVector %54 4
+         %55 = OpConstant %54 0
+         %56 = OpTypeVector %54 3
+         %94 = OpTypeVector %54 2
+        %112 = OpConstantComposite %94 %55 %55
+         %57 = OpConstantComposite %56 %55 %55 %55
+         %15 = OpTypeImage %54 2D 2 0 0 1 Unknown
+        %114 = OpTypePointer UniformConstant %15
+         %38 = OpTypeSampler
+        %125 = OpTypePointer UniformConstant %38
+        %132 = OpTypeVoid
+        %133 = OpTypeFunction %132
+         %45 = OpTypeSampledImage %15
+         %40 = OpVariable %114 UniformConstant
+         %41 = OpVariable %125 UniformConstant
+          %2 = OpFunction %132 None %133
+        %164 = OpLabel
+        %184 = OpLoad %15 %40
+	%213 = OpLoad %38 %41
+        %216 = OpSampledImage %45 %184 %213
+        %217 = OpImageSampleImplicitLod %76 %216 %112 Bias %55
+               OpReturn
+               OpFunctionEnd
+  )";
+
 void AddConstantUniformFact(protobufs::FactSequence* facts,
                             uint32_t descriptor_set, uint32_t binding,
                             std::vector<uint32_t>&& indices, uint32_t value) {
@@ -1591,7 +1632,7 @@
 
   std::vector<fuzzerutil::ModuleSupplier> donor_suppliers;
   for (auto donor : {&kTestShader1, &kTestShader2, &kTestShader3, &kTestShader4,
-                     &kTestShader5}) {
+                     &kTestShader5, &kTestShader6}) {
     donor_suppliers.emplace_back([donor]() {
       return BuildModule(env, kConsoleMessageConsumer, *donor,
                          kFuzzAssembleOption);
@@ -1602,8 +1643,9 @@
     std::vector<uint32_t> fuzzer_binary_out;
     protobufs::TransformationSequence fuzzer_transformation_sequence_out;
 
-    Fuzzer fuzzer(env, seed, true);
-    fuzzer.SetMessageConsumer(kSilentConsumer);
+    spvtools::ValidatorOptions validator_options;
+    Fuzzer fuzzer(env, seed, true, validator_options);
+    fuzzer.SetMessageConsumer(kConsoleMessageConsumer);
     auto fuzzer_result_status =
         fuzzer.Run(binary_in, initial_facts, donor_suppliers,
                    &fuzzer_binary_out, &fuzzer_transformation_sequence_out);
@@ -1613,8 +1655,8 @@
     std::vector<uint32_t> replayer_binary_out;
     protobufs::TransformationSequence replayer_transformation_sequence_out;
 
-    Replayer replayer(env, false);
-    replayer.SetMessageConsumer(kSilentConsumer);
+    Replayer replayer(env, false, validator_options);
+    replayer.SetMessageConsumer(kConsoleMessageConsumer);
     auto replayer_result_status = replayer.Run(
         binary_in, initial_facts, fuzzer_transformation_sequence_out,
         &replayer_binary_out, &replayer_transformation_sequence_out);
@@ -1681,6 +1723,13 @@
                        kNumFuzzerRuns);
 }
 
+TEST(FuzzerReplayerTest, Miscellaneous6) {
+  // Do some fuzzer runs, starting from an initial seed of 57 (seed value chosen
+  // arbitrarily).
+  RunFuzzerAndReplayer(kTestShader6, protobufs::FactSequence(), 57,
+                       kNumFuzzerRuns);
+}
+
 }  // namespace
 }  // namespace fuzz
 }  // namespace spvtools
diff --git a/third_party/spirv-tools/src/test/fuzz/fuzzer_shrinker_test.cpp b/third_party/spirv-tools/src/test/fuzz/fuzzer_shrinker_test.cpp
index c906a1e..24b4460 100644
--- a/third_party/spirv-tools/src/test/fuzz/fuzzer_shrinker_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/fuzzer_shrinker_test.cpp
@@ -979,15 +979,19 @@
 // The |step_limit| parameter restricts the number of steps that the shrinker
 // will try; it can be set to something small for a faster (but less thorough)
 // test.
+//
+// The |validator_options| parameter provides validator options that should be
+// used during shrinking.
 void RunAndCheckShrinker(
     const spv_target_env& target_env, const std::vector<uint32_t>& binary_in,
     const protobufs::FactSequence& initial_facts,
     const protobufs::TransformationSequence& transformation_sequence_in,
     const Shrinker::InterestingnessFunction& interestingness_function,
     const std::vector<uint32_t>& expected_binary_out,
-    uint32_t expected_transformations_out_size, uint32_t step_limit) {
+    uint32_t expected_transformations_out_size, uint32_t step_limit,
+    spv_validator_options validator_options) {
   // Run the shrinker.
-  Shrinker shrinker(target_env, step_limit, false);
+  Shrinker shrinker(target_env, step_limit, false, validator_options);
   shrinker.SetMessageConsumer(kSilentConsumer);
 
   std::vector<uint32_t> binary_out;
@@ -1035,7 +1039,8 @@
   // Run the fuzzer and check that it successfully yields a valid binary.
   std::vector<uint32_t> fuzzer_binary_out;
   protobufs::TransformationSequence fuzzer_transformation_sequence_out;
-  Fuzzer fuzzer(env, seed, true);
+  spvtools::ValidatorOptions validator_options;
+  Fuzzer fuzzer(env, seed, true, validator_options);
   fuzzer.SetMessageConsumer(kSilentConsumer);
   auto fuzzer_result_status =
       fuzzer.Run(binary_in, initial_facts, donor_suppliers, &fuzzer_binary_out,
@@ -1048,9 +1053,10 @@
 
   // With the AlwaysInteresting test, we should quickly shrink to the original
   // binary with no transformations remaining.
-  RunAndCheckShrinker(
-      env, binary_in, initial_facts, fuzzer_transformation_sequence_out,
-      AlwaysInteresting().AsFunction(), binary_in, 0, kReasonableStepLimit);
+  RunAndCheckShrinker(env, binary_in, initial_facts,
+                      fuzzer_transformation_sequence_out,
+                      AlwaysInteresting().AsFunction(), binary_in, 0,
+                      kReasonableStepLimit, validator_options);
 
   // With the OnlyInterestingFirstTime test, no shrinking should be achieved.
   RunAndCheckShrinker(
@@ -1058,14 +1064,14 @@
       OnlyInterestingFirstTime().AsFunction(), fuzzer_binary_out,
       static_cast<uint32_t>(
           fuzzer_transformation_sequence_out.transformation_size()),
-      kReasonableStepLimit);
+      kReasonableStepLimit, validator_options);
 
   // The PingPong test is unpredictable; passing an empty expected binary
   // means that we don't check anything beyond that shrinking completes
   // successfully.
-  RunAndCheckShrinker(env, binary_in, initial_facts,
-                      fuzzer_transformation_sequence_out,
-                      PingPong().AsFunction(), {}, 0, kSmallStepLimit);
+  RunAndCheckShrinker(
+      env, binary_in, initial_facts, fuzzer_transformation_sequence_out,
+      PingPong().AsFunction(), {}, 0, kSmallStepLimit, validator_options);
 
   // The InterestingThenRandom test is unpredictable; passing an empty
   // expected binary means that we do not check anything about shrinking
@@ -1073,7 +1079,7 @@
   RunAndCheckShrinker(
       env, binary_in, initial_facts, fuzzer_transformation_sequence_out,
       InterestingThenRandom(PseudoRandomGenerator(seed)).AsFunction(), {}, 0,
-      kSmallStepLimit);
+      kSmallStepLimit, validator_options);
 }
 
 TEST(FuzzerShrinkerTest, Miscellaneous1) {
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_access_chain_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_access_chain_test.cpp
index 516d371..443c31c 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_access_chain_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_access_chain_test.cpp
@@ -118,169 +118,194 @@
   // Indices 0-5 are in ids 80-85
 
   FactManager fact_manager;
-  fact_manager.AddFactValueOfPointeeIsIrrelevant(54);
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
+
+  transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
+      54);
 
   // Bad: id is not fresh
   ASSERT_FALSE(TransformationAccessChain(
                    43, 43, {80}, MakeInstructionDescriptor(24, SpvOpLoad, 0))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: pointer id does not exist
   ASSERT_FALSE(TransformationAccessChain(
                    100, 1000, {80}, MakeInstructionDescriptor(24, SpvOpLoad, 0))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: pointer id is not a type
   ASSERT_FALSE(TransformationAccessChain(
                    100, 5, {80}, MakeInstructionDescriptor(24, SpvOpLoad, 0))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: pointer id is not a pointer
   ASSERT_FALSE(TransformationAccessChain(
                    100, 23, {80}, MakeInstructionDescriptor(24, SpvOpLoad, 0))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: index id does not exist
   ASSERT_FALSE(TransformationAccessChain(
                    100, 43, {1000}, MakeInstructionDescriptor(24, SpvOpLoad, 0))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: index id is not a constant
   ASSERT_FALSE(TransformationAccessChain(
                    100, 43, {24}, MakeInstructionDescriptor(25, SpvOpIAdd, 0))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: too many indices
   ASSERT_FALSE(
       TransformationAccessChain(100, 43, {80, 80, 80},
                                 MakeInstructionDescriptor(24, SpvOpLoad, 0))
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   // Bad: index id is out of bounds
   ASSERT_FALSE(
       TransformationAccessChain(100, 43, {80, 83},
                                 MakeInstructionDescriptor(24, SpvOpLoad, 0))
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   // Bad: attempt to insert before variable
   ASSERT_FALSE(TransformationAccessChain(
                    100, 34, {}, MakeInstructionDescriptor(36, SpvOpVariable, 0))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: pointer not available
   ASSERT_FALSE(
       TransformationAccessChain(
           100, 43, {80}, MakeInstructionDescriptor(21, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   // Bad: instruction descriptor does not identify anything
   ASSERT_FALSE(TransformationAccessChain(
                    100, 43, {80}, MakeInstructionDescriptor(24, SpvOpLoad, 100))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: pointer is null
   ASSERT_FALSE(TransformationAccessChain(
                    100, 45, {80}, MakeInstructionDescriptor(24, SpvOpLoad, 0))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: pointer is undef
   ASSERT_FALSE(TransformationAccessChain(
                    100, 46, {80}, MakeInstructionDescriptor(24, SpvOpLoad, 0))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: pointer to result type does not exist
   ASSERT_FALSE(TransformationAccessChain(
                    100, 52, {0}, MakeInstructionDescriptor(24, SpvOpLoad, 0))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   {
     TransformationAccessChain transformation(
         100, 43, {80}, MakeInstructionDescriptor(24, SpvOpLoad, 0));
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
     ASSERT_TRUE(IsValid(env, context.get()));
-    ASSERT_FALSE(fact_manager.PointeeValueIsIrrelevant(100));
+    ASSERT_FALSE(
+        transformation_context.GetFactManager()->PointeeValueIsIrrelevant(100));
   }
 
   {
     TransformationAccessChain transformation(
         101, 28, {81}, MakeInstructionDescriptor(42, SpvOpReturn, 0));
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
     ASSERT_TRUE(IsValid(env, context.get()));
-    ASSERT_FALSE(fact_manager.PointeeValueIsIrrelevant(101));
+    ASSERT_FALSE(
+        transformation_context.GetFactManager()->PointeeValueIsIrrelevant(101));
   }
 
   {
     TransformationAccessChain transformation(
         102, 36, {80, 81}, MakeInstructionDescriptor(37, SpvOpStore, 0));
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
     ASSERT_TRUE(IsValid(env, context.get()));
-    ASSERT_FALSE(fact_manager.PointeeValueIsIrrelevant(102));
+    ASSERT_FALSE(
+        transformation_context.GetFactManager()->PointeeValueIsIrrelevant(102));
   }
 
   {
     TransformationAccessChain transformation(
         103, 44, {}, MakeInstructionDescriptor(44, SpvOpStore, 0));
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
     ASSERT_TRUE(IsValid(env, context.get()));
-    ASSERT_FALSE(fact_manager.PointeeValueIsIrrelevant(103));
+    ASSERT_FALSE(
+        transformation_context.GetFactManager()->PointeeValueIsIrrelevant(103));
   }
 
   {
     TransformationAccessChain transformation(
         104, 13, {80}, MakeInstructionDescriptor(21, SpvOpAccessChain, 0));
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
     ASSERT_TRUE(IsValid(env, context.get()));
-    ASSERT_FALSE(fact_manager.PointeeValueIsIrrelevant(104));
+    ASSERT_FALSE(
+        transformation_context.GetFactManager()->PointeeValueIsIrrelevant(104));
   }
 
   {
     TransformationAccessChain transformation(
         105, 34, {}, MakeInstructionDescriptor(44, SpvOpStore, 1));
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
     ASSERT_TRUE(IsValid(env, context.get()));
-    ASSERT_FALSE(fact_manager.PointeeValueIsIrrelevant(105));
+    ASSERT_FALSE(
+        transformation_context.GetFactManager()->PointeeValueIsIrrelevant(105));
   }
 
   {
     TransformationAccessChain transformation(
         106, 38, {}, MakeInstructionDescriptor(40, SpvOpFunctionCall, 0));
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
     ASSERT_TRUE(IsValid(env, context.get()));
-    ASSERT_FALSE(fact_manager.PointeeValueIsIrrelevant(106));
+    ASSERT_FALSE(
+        transformation_context.GetFactManager()->PointeeValueIsIrrelevant(106));
   }
 
   {
     TransformationAccessChain transformation(
         107, 14, {}, MakeInstructionDescriptor(24, SpvOpLoad, 0));
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
     ASSERT_TRUE(IsValid(env, context.get()));
-    ASSERT_FALSE(fact_manager.PointeeValueIsIrrelevant(107));
+    ASSERT_FALSE(
+        transformation_context.GetFactManager()->PointeeValueIsIrrelevant(107));
   }
 
   {
     TransformationAccessChain transformation(
         108, 54, {85, 81, 81}, MakeInstructionDescriptor(24, SpvOpLoad, 0));
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
     ASSERT_TRUE(IsValid(env, context.get()));
-    ASSERT_TRUE(fact_manager.PointeeValueIsIrrelevant(108));
+    ASSERT_TRUE(
+        transformation_context.GetFactManager()->PointeeValueIsIrrelevant(108));
   }
 
   {
     TransformationAccessChain transformation(
         109, 48, {80, 80}, MakeInstructionDescriptor(24, SpvOpLoad, 0));
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
     ASSERT_TRUE(IsValid(env, context.get()));
-    ASSERT_FALSE(fact_manager.PointeeValueIsIrrelevant(109));
+    ASSERT_FALSE(
+        transformation_context.GetFactManager()->PointeeValueIsIrrelevant(109));
   }
 
   std::string after_transformation = R"(
@@ -401,19 +426,24 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   {
     TransformationAccessChain transformation(
         100, 11, {}, MakeInstructionDescriptor(5, SpvOpReturn, 0));
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
     ASSERT_TRUE(IsValid(env, context.get()));
   }
   {
     TransformationAccessChain transformation(
         101, 12, {}, MakeInstructionDescriptor(5, SpvOpReturn, 0));
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
     ASSERT_TRUE(IsValid(env, context.get()));
   }
 
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_add_constant_boolean_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_add_constant_boolean_test.cpp
index f51c46b..c603333 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_add_constant_boolean_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_add_constant_boolean_test.cpp
@@ -43,42 +43,47 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // True and false can both be added as neither is present.
   ASSERT_TRUE(TransformationAddConstantBoolean(7, true).IsApplicable(
-      context.get(), fact_manager));
+      context.get(), transformation_context));
   ASSERT_TRUE(TransformationAddConstantBoolean(7, false).IsApplicable(
-      context.get(), fact_manager));
+      context.get(), transformation_context));
 
   // Id 5 is already taken.
   ASSERT_FALSE(TransformationAddConstantBoolean(5, true).IsApplicable(
-      context.get(), fact_manager));
+      context.get(), transformation_context));
 
   auto add_true = TransformationAddConstantBoolean(7, true);
   auto add_false = TransformationAddConstantBoolean(8, false);
 
-  ASSERT_TRUE(add_true.IsApplicable(context.get(), fact_manager));
-  add_true.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(add_true.IsApplicable(context.get(), transformation_context));
+  add_true.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Having added true, we cannot add it again with the same id.
-  ASSERT_FALSE(add_true.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(add_true.IsApplicable(context.get(), transformation_context));
   // But we can add it with a different id.
   auto add_true_again = TransformationAddConstantBoolean(100, true);
-  ASSERT_TRUE(add_true_again.IsApplicable(context.get(), fact_manager));
-  add_true_again.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      add_true_again.IsApplicable(context.get(), transformation_context));
+  add_true_again.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(add_false.IsApplicable(context.get(), fact_manager));
-  add_false.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(add_false.IsApplicable(context.get(), transformation_context));
+  add_false.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Having added false, we cannot add it again with the same id.
-  ASSERT_FALSE(add_false.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(add_false.IsApplicable(context.get(), transformation_context));
   // But we can add it with a different id.
   auto add_false_again = TransformationAddConstantBoolean(101, false);
-  ASSERT_TRUE(add_false_again.IsApplicable(context.get(), fact_manager));
-  add_false_again.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      add_false_again.IsApplicable(context.get(), transformation_context));
+  add_false_again.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_transformation = R"(
@@ -128,12 +133,15 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // Neither true nor false can be added as OpTypeBool is not present.
   ASSERT_FALSE(TransformationAddConstantBoolean(6, true).IsApplicable(
-      context.get(), fact_manager));
+      context.get(), transformation_context));
   ASSERT_FALSE(TransformationAddConstantBoolean(6, false).IsApplicable(
-      context.get(), fact_manager));
+      context.get(), transformation_context));
 }
 
 }  // namespace
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_add_constant_composite_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_add_constant_composite_test.cpp
index 5ce171b..021bf58 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_add_constant_composite_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_add_constant_composite_test.cpp
@@ -64,19 +64,22 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // Too few ids
   ASSERT_FALSE(TransformationAddConstantComposite(103, 8, {100, 101})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   // Too many ids
   ASSERT_FALSE(TransformationAddConstantComposite(101, 7, {14, 15, 14})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   // Id already in use
   ASSERT_FALSE(TransformationAddConstantComposite(40, 7, {11, 12})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   // %39 is not a type
   ASSERT_FALSE(TransformationAddConstantComposite(100, 39, {11, 12})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   TransformationAddConstantComposite transformations[] = {
       // %100 = OpConstantComposite %7 %11 %12
@@ -101,8 +104,9 @@
       TransformationAddConstantComposite(106, 35, {38, 39, 40})};
 
   for (auto& transformation : transformations) {
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
   }
   ASSERT_TRUE(IsValid(env, context.get()));
 
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_add_constant_null_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_add_constant_null_test.cpp
new file mode 100644
index 0000000..0bfee34
--- /dev/null
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_add_constant_null_test.cpp
@@ -0,0 +1,140 @@
+// Copyright (c) 2020 Google LLC
+//
+// 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
+//
+//     http://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.
+
+#include "source/fuzz/transformation_add_constant_null.h"
+#include "test/fuzz/fuzz_test_util.h"
+
+namespace spvtools {
+namespace fuzz {
+namespace {
+
+TEST(TransformationAddConstantNullTest, BasicTest) {
+  std::string shader = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main"
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 310
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %6 = OpTypeFloat 32
+          %7 = OpTypeInt 32 1
+          %8 = OpTypeVector %6 2
+          %9 = OpTypeVector %6 3
+         %10 = OpTypeVector %6 4
+         %11 = OpTypeVector %7 2
+         %20 = OpTypeSampler
+         %21 = OpTypeImage %6 2D 0 0 0 0 Rgba32f
+         %22 = OpTypeSampledImage %21
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  const auto env = SPV_ENV_UNIVERSAL_1_4;
+  const auto consumer = nullptr;
+  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+  ASSERT_TRUE(IsValid(env, context.get()));
+
+  FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
+
+  // Id already in use
+  ASSERT_FALSE(TransformationAddConstantNull(4, 11).IsApplicable(
+      context.get(), transformation_context));
+  // %1 is not a type
+  ASSERT_FALSE(TransformationAddConstantNull(100, 1).IsApplicable(
+      context.get(), transformation_context));
+
+  // %3 is a function type
+  ASSERT_FALSE(TransformationAddConstantNull(100, 3).IsApplicable(
+      context.get(), transformation_context));
+
+  // %20 is a sampler type
+  ASSERT_FALSE(TransformationAddConstantNull(100, 20).IsApplicable(
+      context.get(), transformation_context));
+
+  // %21 is an image type
+  ASSERT_FALSE(TransformationAddConstantNull(100, 21).IsApplicable(
+      context.get(), transformation_context));
+
+  // %22 is a sampled image type
+  ASSERT_FALSE(TransformationAddConstantNull(100, 22).IsApplicable(
+      context.get(), transformation_context));
+
+  TransformationAddConstantNull transformations[] = {
+      // %100 = OpConstantNull %6
+      TransformationAddConstantNull(100, 6),
+
+      // %101 = OpConstantNull %7
+      TransformationAddConstantNull(101, 7),
+
+      // %102 = OpConstantNull %8
+      TransformationAddConstantNull(102, 8),
+
+      // %103 = OpConstantNull %9
+      TransformationAddConstantNull(103, 9),
+
+      // %104 = OpConstantNull %10
+      TransformationAddConstantNull(104, 10),
+
+      // %105 = OpConstantNull %11
+      TransformationAddConstantNull(105, 11)};
+
+  for (auto& transformation : transformations) {
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
+  }
+  ASSERT_TRUE(IsValid(env, context.get()));
+
+  std::string after_transformation = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main"
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 310
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %6 = OpTypeFloat 32
+          %7 = OpTypeInt 32 1
+          %8 = OpTypeVector %6 2
+          %9 = OpTypeVector %6 3
+         %10 = OpTypeVector %6 4
+         %11 = OpTypeVector %7 2
+         %20 = OpTypeSampler
+         %21 = OpTypeImage %6 2D 0 0 0 0 Rgba32f
+         %22 = OpTypeSampledImage %21
+        %100 = OpConstantNull %6
+        %101 = OpConstantNull %7
+        %102 = OpConstantNull %8
+        %103 = OpConstantNull %9
+        %104 = OpConstantNull %10
+        %105 = OpConstantNull %11
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+               OpReturn
+               OpFunctionEnd
+  )";
+  ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
+}
+
+}  // namespace
+}  // namespace fuzz
+}  // namespace spvtools
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_add_constant_scalar_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_add_constant_scalar_test.cpp
index b156111..5124b7d 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_add_constant_scalar_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_add_constant_scalar_test.cpp
@@ -62,6 +62,9 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   const float float_values[2] = {3.0, 30.0};
   uint32_t uint_for_float[2];
@@ -87,55 +90,62 @@
   auto bad_type_id_is_pointer = TransformationAddConstantScalar(111, 11, {0});
 
   // Id is already in use.
-  ASSERT_FALSE(bad_id_already_used.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      bad_id_already_used.IsApplicable(context.get(), transformation_context));
 
   // At least one word of data must be provided.
-  ASSERT_FALSE(bad_no_data.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(bad_no_data.IsApplicable(context.get(), transformation_context));
 
   // Cannot give two data words for a 32-bit type.
-  ASSERT_FALSE(bad_too_much_data.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      bad_too_much_data.IsApplicable(context.get(), transformation_context));
 
   // Type id does not exist
-  ASSERT_FALSE(
-      bad_type_id_does_not_exist.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(bad_type_id_does_not_exist.IsApplicable(context.get(),
+                                                       transformation_context));
 
   // Type id is not a type
-  ASSERT_FALSE(
-      bad_type_id_is_not_a_type.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(bad_type_id_is_not_a_type.IsApplicable(context.get(),
+                                                      transformation_context));
 
   // Type id is void
-  ASSERT_FALSE(bad_type_id_is_void.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      bad_type_id_is_void.IsApplicable(context.get(), transformation_context));
 
   // Type id is pointer
-  ASSERT_FALSE(
-      bad_type_id_is_pointer.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(bad_type_id_is_pointer.IsApplicable(context.get(),
+                                                   transformation_context));
 
-  ASSERT_TRUE(add_signed_int_1.IsApplicable(context.get(), fact_manager));
-  add_signed_int_1.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      add_signed_int_1.IsApplicable(context.get(), transformation_context));
+  add_signed_int_1.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(add_signed_int_10.IsApplicable(context.get(), fact_manager));
-  add_signed_int_10.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      add_signed_int_10.IsApplicable(context.get(), transformation_context));
+  add_signed_int_10.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(add_unsigned_int_2.IsApplicable(context.get(), fact_manager));
-  add_unsigned_int_2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      add_unsigned_int_2.IsApplicable(context.get(), transformation_context));
+  add_unsigned_int_2.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(add_unsigned_int_20.IsApplicable(context.get(), fact_manager));
-  add_unsigned_int_20.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      add_unsigned_int_20.IsApplicable(context.get(), transformation_context));
+  add_unsigned_int_20.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(add_float_3.IsApplicable(context.get(), fact_manager));
-  add_float_3.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(add_float_3.IsApplicable(context.get(), transformation_context));
+  add_float_3.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(add_float_30.IsApplicable(context.get(), fact_manager));
-  add_float_30.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(add_float_30.IsApplicable(context.get(), transformation_context));
+  add_float_30.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_FALSE(bad_add_float_30_id_already_used.IsApplicable(context.get(),
-                                                             fact_manager));
+  ASSERT_FALSE(bad_add_float_30_id_already_used.IsApplicable(
+      context.get(), transformation_context));
 
   std::string after_transformation = R"(
                OpCapability Shader
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_add_dead_block_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_add_dead_block_test.cpp
index f89140f..c9be520 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_add_dead_block_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_add_dead_block_test.cpp
@@ -46,21 +46,25 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // Id 4 is already in use
   ASSERT_FALSE(TransformationAddDeadBlock(4, 5, true)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Id 7 is not a block
   ASSERT_FALSE(TransformationAddDeadBlock(100, 7, true)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   TransformationAddDeadBlock transformation(100, 5, true);
-  ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-  transformation.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
+  transformation.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(fact_manager.BlockIsDead(100));
+  ASSERT_TRUE(transformation_context.GetFactManager()->BlockIsDead(100));
 
   std::string after_transformation = R"(
                OpCapability Shader
@@ -119,9 +123,12 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   ASSERT_FALSE(TransformationAddDeadBlock(100, 9, true)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationAddDeadBlockTest, TargetBlockMustNotBeLoopMergeOrContinue) {
@@ -160,13 +167,16 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // Bad because 9's successor is the loop continue target.
   ASSERT_FALSE(TransformationAddDeadBlock(100, 9, true)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   // Bad because 10's successor is the loop merge.
   ASSERT_FALSE(TransformationAddDeadBlock(100, 10, true)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationAddDeadBlockTest, SourceBlockMustNotBeLoopHead) {
@@ -203,10 +213,13 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // Bad because 8 is a loop head.
   ASSERT_FALSE(TransformationAddDeadBlock(100, 8, true)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationAddDeadBlockTest, OpPhiInTarget) {
@@ -240,13 +253,17 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationAddDeadBlock transformation(100, 5, true);
-  ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-  transformation.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
+  transformation.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(fact_manager.BlockIsDead(100));
+  ASSERT_TRUE(transformation_context.GetFactManager()->BlockIsDead(100));
 
   std::string after_transformation = R"(
                OpCapability Shader
@@ -309,11 +326,14 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // 9 is a back edge block, so it would not be OK to add a dead block here,
   // as then both 9 and the dead block would branch to the loop header, 8.
   ASSERT_FALSE(TransformationAddDeadBlock(100, 9, true)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 }
 
 }  // namespace
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_add_dead_break_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_add_dead_break_test.cpp
index d60fc1f..8400b0c 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_add_dead_break_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_add_dead_break_test.cpp
@@ -100,44 +100,47 @@
   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
   ASSERT_TRUE(IsValid(env, context.get()));
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   const uint32_t merge_block = 16;
 
   // These are all possibilities.
   ASSERT_TRUE(TransformationAddDeadBreak(15, merge_block, true, {})
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationAddDeadBreak(15, merge_block, false, {})
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationAddDeadBreak(21, merge_block, true, {})
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationAddDeadBreak(21, merge_block, false, {})
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationAddDeadBreak(22, merge_block, true, {})
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationAddDeadBreak(22, merge_block, false, {})
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationAddDeadBreak(19, merge_block, true, {})
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationAddDeadBreak(19, merge_block, false, {})
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationAddDeadBreak(23, merge_block, true, {})
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationAddDeadBreak(23, merge_block, false, {})
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationAddDeadBreak(24, merge_block, true, {})
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationAddDeadBreak(24, merge_block, false, {})
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable: 100 is not a block id.
   ASSERT_FALSE(TransformationAddDeadBreak(100, merge_block, true, {})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationAddDeadBreak(15, 100, true, {})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable: 24 is not a merge block.
   ASSERT_FALSE(TransformationAddDeadBreak(15, 24, true, {})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // These are the transformations we will apply.
   auto transformation1 = TransformationAddDeadBreak(15, merge_block, true, {});
@@ -147,28 +150,34 @@
   auto transformation5 = TransformationAddDeadBreak(23, merge_block, true, {});
   auto transformation6 = TransformationAddDeadBreak(24, merge_block, false, {});
 
-  ASSERT_TRUE(transformation1.IsApplicable(context.get(), fact_manager));
-  transformation1.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation1.IsApplicable(context.get(), transformation_context));
+  transformation1.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(transformation2.IsApplicable(context.get(), fact_manager));
-  transformation2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation2.IsApplicable(context.get(), transformation_context));
+  transformation2.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(transformation3.IsApplicable(context.get(), fact_manager));
-  transformation3.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation3.IsApplicable(context.get(), transformation_context));
+  transformation3.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(transformation4.IsApplicable(context.get(), fact_manager));
-  transformation4.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation4.IsApplicable(context.get(), transformation_context));
+  transformation4.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(transformation5.IsApplicable(context.get(), fact_manager));
-  transformation5.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation5.IsApplicable(context.get(), transformation_context));
+  transformation5.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(transformation6.IsApplicable(context.get(), fact_manager));
-  transformation6.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation6.IsApplicable(context.get(), transformation_context));
+  transformation6.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_transformation = R"(
@@ -333,6 +342,9 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // The header and merge blocks
   const uint32_t header_inner = 34;
@@ -354,53 +366,53 @@
 
   // Fine to break from a construct to its merge
   ASSERT_TRUE(TransformationAddDeadBreak(inner_block_1, merge_inner, true, {})
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationAddDeadBreak(inner_block_2, merge_inner, false, {})
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationAddDeadBreak(outer_block_1, merge_outer, true, {})
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationAddDeadBreak(outer_block_2, merge_outer, false, {})
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationAddDeadBreak(outer_block_3, merge_outer, true, {})
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationAddDeadBreak(outer_block_4, merge_outer, false, {})
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationAddDeadBreak(after_block_1, merge_after, true, {})
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationAddDeadBreak(after_block_2, merge_after, false, {})
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
 
   // Not OK to break to the wrong merge (whether enclosing or not)
   ASSERT_FALSE(TransformationAddDeadBreak(inner_block_1, merge_outer, true, {})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationAddDeadBreak(inner_block_2, merge_after, false, {})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationAddDeadBreak(outer_block_1, merge_inner, true, {})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationAddDeadBreak(outer_block_2, merge_after, false, {})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationAddDeadBreak(after_block_1, merge_inner, true, {})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationAddDeadBreak(after_block_2, merge_outer, false, {})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Not OK to break from header (as it does not branch unconditionally)
   ASSERT_FALSE(TransformationAddDeadBreak(header_inner, merge_inner, true, {})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationAddDeadBreak(header_outer, merge_outer, false, {})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationAddDeadBreak(header_after, merge_after, true, {})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Not OK to break to non-merge
   ASSERT_FALSE(
       TransformationAddDeadBreak(inner_block_1, inner_block_2, true, {})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationAddDeadBreak(outer_block_2, after_block_1, false, {})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationAddDeadBreak(outer_block_1, header_after, true, {})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   auto transformation1 =
       TransformationAddDeadBreak(inner_block_1, merge_inner, true, {});
@@ -419,36 +431,44 @@
   auto transformation8 =
       TransformationAddDeadBreak(after_block_2, merge_after, false, {});
 
-  ASSERT_TRUE(transformation1.IsApplicable(context.get(), fact_manager));
-  transformation1.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation1.IsApplicable(context.get(), transformation_context));
+  transformation1.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(transformation2.IsApplicable(context.get(), fact_manager));
-  transformation2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation2.IsApplicable(context.get(), transformation_context));
+  transformation2.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(transformation3.IsApplicable(context.get(), fact_manager));
-  transformation3.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation3.IsApplicable(context.get(), transformation_context));
+  transformation3.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(transformation4.IsApplicable(context.get(), fact_manager));
-  transformation4.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation4.IsApplicable(context.get(), transformation_context));
+  transformation4.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(transformation5.IsApplicable(context.get(), fact_manager));
-  transformation5.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation5.IsApplicable(context.get(), transformation_context));
+  transformation5.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(transformation6.IsApplicable(context.get(), fact_manager));
-  transformation6.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation6.IsApplicable(context.get(), transformation_context));
+  transformation6.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(transformation7.IsApplicable(context.get(), fact_manager));
-  transformation7.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation7.IsApplicable(context.get(), transformation_context));
+  transformation7.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(transformation8.IsApplicable(context.get(), fact_manager));
-  transformation8.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation8.IsApplicable(context.get(), transformation_context));
+  transformation8.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_transformation = R"(
@@ -685,6 +705,9 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // The header and merge blocks
   const uint32_t header_outer_if = 5;
@@ -715,63 +738,63 @@
   // Fine to branch straight to direct merge block for a construct
   ASSERT_TRUE(TransformationAddDeadBreak(then_outer_switch_block_1,
                                          merge_then_outer_switch, true, {})
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationAddDeadBreak(then_inner_switch_block_1,
                                          merge_then_inner_switch, false, {})
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationAddDeadBreak(then_inner_switch_block_2,
                                          merge_then_inner_switch, true, {})
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationAddDeadBreak(then_inner_switch_block_3,
                                          merge_then_inner_switch, true, {})
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationAddDeadBreak(else_switch_block_1, merge_else_switch,
                                          false, {})
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationAddDeadBreak(else_switch_block_2, merge_else_switch,
                                          true, {})
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationAddDeadBreak(else_switch_block_3, merge_else_switch,
                                          false, {})
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(
       TransformationAddDeadBreak(inner_if_1_block_1, merge_inner_if_1, true, {})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationAddDeadBreak(inner_if_1_block_2, merge_inner_if_1,
                                          false, {})
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(
       TransformationAddDeadBreak(inner_if_2_block_1, merge_inner_if_2, true, {})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   // Not OK to break out of a switch from a selection construct inside the
   // switch.
   ASSERT_FALSE(TransformationAddDeadBreak(inner_if_1_block_1,
                                           merge_then_outer_switch, true, {})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationAddDeadBreak(inner_if_1_block_2,
                                           merge_then_outer_switch, false, {})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationAddDeadBreak(inner_if_2_block_1,
                                           merge_then_outer_switch, true, {})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Some miscellaneous inapplicable cases.
   ASSERT_FALSE(
       TransformationAddDeadBreak(header_outer_if, merge_outer_if, true, {})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationAddDeadBreak(header_inner_if_1, inner_if_1_block_2,
                                           false, {})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationAddDeadBreak(header_then_inner_switch,
                                           header_then_outer_switch, false, {})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationAddDeadBreak(header_else_switch,
                                           then_inner_switch_block_3, false, {})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationAddDeadBreak(header_inner_if_2, header_inner_if_2,
                                           false, {})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   auto transformation1 = TransformationAddDeadBreak(
       then_outer_switch_block_1, merge_then_outer_switch, true, {});
@@ -794,44 +817,54 @@
   auto transformation10 = TransformationAddDeadBreak(
       inner_if_2_block_1, merge_inner_if_2, true, {});
 
-  ASSERT_TRUE(transformation1.IsApplicable(context.get(), fact_manager));
-  transformation1.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation1.IsApplicable(context.get(), transformation_context));
+  transformation1.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(transformation2.IsApplicable(context.get(), fact_manager));
-  transformation2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation2.IsApplicable(context.get(), transformation_context));
+  transformation2.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(transformation3.IsApplicable(context.get(), fact_manager));
-  transformation3.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation3.IsApplicable(context.get(), transformation_context));
+  transformation3.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(transformation4.IsApplicable(context.get(), fact_manager));
-  transformation4.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation4.IsApplicable(context.get(), transformation_context));
+  transformation4.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(transformation5.IsApplicable(context.get(), fact_manager));
-  transformation5.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation5.IsApplicable(context.get(), transformation_context));
+  transformation5.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(transformation6.IsApplicable(context.get(), fact_manager));
-  transformation6.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation6.IsApplicable(context.get(), transformation_context));
+  transformation6.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(transformation7.IsApplicable(context.get(), fact_manager));
-  transformation7.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation7.IsApplicable(context.get(), transformation_context));
+  transformation7.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(transformation8.IsApplicable(context.get(), fact_manager));
-  transformation8.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation8.IsApplicable(context.get(), transformation_context));
+  transformation8.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(transformation9.IsApplicable(context.get(), fact_manager));
-  transformation9.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation9.IsApplicable(context.get(), transformation_context));
+  transformation9.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(transformation10.IsApplicable(context.get(), fact_manager));
-  transformation10.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation10.IsApplicable(context.get(), transformation_context));
+  transformation10.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_transformation = R"(
@@ -1094,6 +1127,9 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // The header and merge blocks
   const uint32_t header_do_while = 6;
@@ -1123,75 +1159,75 @@
   // Fine to break from any loop header to its merge
   ASSERT_TRUE(
       TransformationAddDeadBreak(header_do_while, merge_do_while, true, {})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationAddDeadBreak(header_for_i, merge_for_i, false, {})
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationAddDeadBreak(header_for_j, merge_for_j, true, {})
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
 
   // Fine to break from any of the blocks in constructs in the "for j" loop to
   // that loop's merge
   ASSERT_TRUE(
       TransformationAddDeadBreak(block_in_inner_if, merge_for_j, false, {})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(
       TransformationAddDeadBreak(block_switch_case, merge_for_j, true, {})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(
       TransformationAddDeadBreak(block_switch_default, merge_for_j, false, {})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   // Fine to break from the body of the "for i" loop to that loop's merge
   ASSERT_TRUE(
       TransformationAddDeadBreak(block_in_for_i_loop, merge_for_i, true, {})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   // Not OK to break from multiple loops
   ASSERT_FALSE(
       TransformationAddDeadBreak(block_in_inner_if, merge_do_while, false, {})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationAddDeadBreak(block_switch_case, merge_do_while, true, {})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationAddDeadBreak(block_switch_default, merge_do_while,
                                           false, {})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationAddDeadBreak(header_for_j, merge_do_while, true, {})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   // Not OK to break loop from its continue construct
   ASSERT_FALSE(
       TransformationAddDeadBreak(continue_do_while, merge_do_while, true, {})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationAddDeadBreak(continue_for_j, merge_for_j, false, {})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationAddDeadBreak(continue_for_i, merge_for_i, true, {})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Not OK to break out of multiple non-loop constructs if not breaking to a
   // loop merge
   ASSERT_FALSE(
       TransformationAddDeadBreak(block_in_inner_if, merge_if_x_eq_y, false, {})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationAddDeadBreak(block_switch_case, merge_if_x_eq_y, true, {})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationAddDeadBreak(block_switch_default, merge_if_x_eq_y,
                                           false, {})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Some miscellaneous inapplicable transformations
   ASSERT_FALSE(
       TransformationAddDeadBreak(header_if_x_eq_2, header_if_x_eq_y, false, {})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationAddDeadBreak(merge_if_x_eq_2, merge_switch, false, {})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationAddDeadBreak(header_switch, header_switch, false, {})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   auto transformation1 =
       TransformationAddDeadBreak(header_do_while, merge_do_while, true, {});
@@ -1208,32 +1244,39 @@
   auto transformation7 =
       TransformationAddDeadBreak(block_in_for_i_loop, merge_for_i, true, {});
 
-  ASSERT_TRUE(transformation1.IsApplicable(context.get(), fact_manager));
-  transformation1.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation1.IsApplicable(context.get(), transformation_context));
+  transformation1.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(transformation2.IsApplicable(context.get(), fact_manager));
-  transformation2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation2.IsApplicable(context.get(), transformation_context));
+  transformation2.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(transformation3.IsApplicable(context.get(), fact_manager));
-  transformation3.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation3.IsApplicable(context.get(), transformation_context));
+  transformation3.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(transformation4.IsApplicable(context.get(), fact_manager));
-  transformation4.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation4.IsApplicable(context.get(), transformation_context));
+  transformation4.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(transformation5.IsApplicable(context.get(), fact_manager));
-  transformation5.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation5.IsApplicable(context.get(), transformation_context));
+  transformation5.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(transformation6.IsApplicable(context.get(), fact_manager));
-  transformation6.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation6.IsApplicable(context.get(), transformation_context));
+  transformation6.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(transformation7.IsApplicable(context.get(), fact_manager));
-  transformation7.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation7.IsApplicable(context.get(), transformation_context));
+  transformation7.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_transformation = R"(
@@ -1421,12 +1464,15 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // Not OK to break loop from its continue construct
   ASSERT_FALSE(TransformationAddDeadBreak(13, 12, true, {})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationAddDeadBreak(23, 12, true, {})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationAddDeadBreakTest, SelectionInContinueConstruct) {
@@ -1509,6 +1555,9 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   const uint32_t loop_merge = 12;
   const uint32_t selection_merge = 24;
@@ -1520,13 +1569,13 @@
   // Not OK to jump from the selection to the loop merge, as this would break
   // from the loop's continue construct.
   ASSERT_FALSE(TransformationAddDeadBreak(in_selection_1, loop_merge, true, {})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationAddDeadBreak(in_selection_2, loop_merge, true, {})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationAddDeadBreak(in_selection_3, loop_merge, true, {})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationAddDeadBreak(in_selection_4, loop_merge, true, {})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // But fine to jump from the selection to its merge.
 
@@ -1539,20 +1588,24 @@
   auto transformation4 =
       TransformationAddDeadBreak(in_selection_4, selection_merge, true, {});
 
-  ASSERT_TRUE(transformation1.IsApplicable(context.get(), fact_manager));
-  transformation1.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation1.IsApplicable(context.get(), transformation_context));
+  transformation1.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(transformation2.IsApplicable(context.get(), fact_manager));
-  transformation2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation2.IsApplicable(context.get(), transformation_context));
+  transformation2.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(transformation3.IsApplicable(context.get(), fact_manager));
-  transformation3.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation3.IsApplicable(context.get(), transformation_context));
+  transformation3.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(transformation4.IsApplicable(context.get(), fact_manager));
-  transformation4.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation4.IsApplicable(context.get(), transformation_context));
+  transformation4.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_transformation = R"(
@@ -1720,6 +1773,9 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   const uint32_t outer_loop_merge = 34;
   const uint32_t outer_loop_block = 33;
@@ -1729,22 +1785,24 @@
   // Some inapplicable cases
   ASSERT_FALSE(
       TransformationAddDeadBreak(inner_loop_block, outer_loop_merge, true, {})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationAddDeadBreak(outer_loop_block, inner_loop_merge, true, {})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   auto transformation1 =
       TransformationAddDeadBreak(inner_loop_block, inner_loop_merge, true, {});
   auto transformation2 =
       TransformationAddDeadBreak(outer_loop_block, outer_loop_merge, true, {});
 
-  ASSERT_TRUE(transformation1.IsApplicable(context.get(), fact_manager));
-  transformation1.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation1.IsApplicable(context.get(), transformation_context));
+  transformation1.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(transformation2.IsApplicable(context.get(), fact_manager));
-  transformation2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation2.IsApplicable(context.get(), transformation_context));
+  transformation2.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_transformation = R"(
@@ -1936,36 +1994,39 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // Some inapplicable transformations
   // Not applicable because there is already an edge 19->20, so the OpPhis at 20
   // do not need to be updated
   ASSERT_FALSE(TransformationAddDeadBreak(19, 20, true, {13, 21})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   // Not applicable because two OpPhis (not zero) need to be updated at 20
   ASSERT_FALSE(TransformationAddDeadBreak(23, 20, true, {})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   // Not applicable because two OpPhis (not just one) need to be updated at 20
   ASSERT_FALSE(TransformationAddDeadBreak(23, 20, true, {13})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   // Not applicable because the given ids do not have types that match the
   // OpPhis at 20, in order
   ASSERT_FALSE(TransformationAddDeadBreak(23, 20, true, {21, 13})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   // Not applicable because id 23 is a label
   ASSERT_FALSE(TransformationAddDeadBreak(23, 20, true, {21, 23})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   // Not applicable because 101 is not an id
   ASSERT_FALSE(TransformationAddDeadBreak(23, 20, true, {21, 101})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   // Not applicable because ids 51 and 47 are not available at the end of block
   // 23
   ASSERT_FALSE(TransformationAddDeadBreak(23, 20, true, {51, 47})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Not applicable because OpConstantFalse is not present in the module
   ASSERT_FALSE(TransformationAddDeadBreak(19, 20, false, {})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   auto transformation1 = TransformationAddDeadBreak(19, 20, true, {});
   auto transformation2 = TransformationAddDeadBreak(23, 20, true, {13, 21});
@@ -1973,24 +2034,29 @@
   auto transformation4 = TransformationAddDeadBreak(30, 31, true, {21, 13});
   auto transformation5 = TransformationAddDeadBreak(75, 31, true, {47, 51});
 
-  ASSERT_TRUE(transformation1.IsApplicable(context.get(), fact_manager));
-  transformation1.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation1.IsApplicable(context.get(), transformation_context));
+  transformation1.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(transformation2.IsApplicable(context.get(), fact_manager));
-  transformation2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation2.IsApplicable(context.get(), transformation_context));
+  transformation2.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(transformation3.IsApplicable(context.get(), fact_manager));
-  transformation3.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation3.IsApplicable(context.get(), transformation_context));
+  transformation3.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(transformation4.IsApplicable(context.get(), fact_manager));
-  transformation4.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation4.IsApplicable(context.get(), transformation_context));
+  transformation4.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(transformation5.IsApplicable(context.get(), fact_manager));
-  transformation5.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation5.IsApplicable(context.get(), transformation_context));
+  transformation5.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_transformation = R"(
@@ -2119,9 +2185,13 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   auto bad_transformation = TransformationAddDeadBreak(100, 101, false, {});
-  ASSERT_FALSE(bad_transformation.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      bad_transformation.IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationAddDeadBreakTest, RespectDominanceRules2) {
@@ -2172,9 +2242,13 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   auto bad_transformation = TransformationAddDeadBreak(102, 101, false, {});
-  ASSERT_FALSE(bad_transformation.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      bad_transformation.IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationAddDeadBreakTest, RespectDominanceRules3) {
@@ -2219,11 +2293,15 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   auto good_transformation = TransformationAddDeadBreak(100, 101, false, {11});
-  ASSERT_TRUE(good_transformation.IsApplicable(context.get(), fact_manager));
+  ASSERT_TRUE(
+      good_transformation.IsApplicable(context.get(), transformation_context));
 
-  good_transformation.Apply(context.get(), &fact_manager);
+  good_transformation.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_transformation = R"(
@@ -2307,11 +2385,15 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   auto good_transformation = TransformationAddDeadBreak(102, 101, false, {11});
-  ASSERT_TRUE(good_transformation.IsApplicable(context.get(), fact_manager));
+  ASSERT_TRUE(
+      good_transformation.IsApplicable(context.get(), transformation_context));
 
-  good_transformation.Apply(context.get(), &fact_manager);
+  good_transformation.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_transformation = R"(
@@ -2389,9 +2471,13 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   auto bad_transformation = TransformationAddDeadBreak(100, 101, false, {});
-  ASSERT_FALSE(bad_transformation.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      bad_transformation.IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationAddDeadBreakTest, RespectDominanceRules6) {
@@ -2446,9 +2532,13 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   auto bad_transformation = TransformationAddDeadBreak(102, 101, false, {});
-  ASSERT_FALSE(bad_transformation.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      bad_transformation.IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationAddDeadBreakTest, RespectDominanceRules7) {
@@ -2505,9 +2595,13 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   auto bad_transformation = TransformationAddDeadBreak(102, 101, false, {});
-  ASSERT_FALSE(bad_transformation.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      bad_transformation.IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationAddDeadBreakTest, RespectDominanceRules8) {
@@ -2551,9 +2645,13 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   auto bad_transformation = TransformationAddDeadBreak(102, 101, false, {});
-  ASSERT_FALSE(bad_transformation.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      bad_transformation.IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationAddDeadBreakTest,
@@ -2597,12 +2695,16 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // Bad because 14 comes before 12 in the module, and 14 has no predecessors.
   // This means that an edge from 12 to 14 will lead to 12 dominating 14, which
   // is illegal if 12 appears after 14.
   auto bad_transformation = TransformationAddDeadBreak(12, 14, true, {});
-  ASSERT_FALSE(bad_transformation.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      bad_transformation.IsApplicable(context.get(), transformation_context));
 }
 
 }  // namespace
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_add_dead_continue_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_add_dead_continue_test.cpp
index ff93da8..07ee3b1 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_add_dead_continue_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_add_dead_continue_test.cpp
@@ -97,57 +97,63 @@
   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
   ASSERT_TRUE(IsValid(env, context.get()));
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // These are all possibilities.
   ASSERT_TRUE(TransformationAddDeadContinue(11, true, {})
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationAddDeadContinue(11, false, {})
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationAddDeadContinue(12, true, {})
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationAddDeadContinue(12, false, {})
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationAddDeadContinue(40, true, {})
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationAddDeadContinue(40, false, {})
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable: 100 is not a block id.
   ASSERT_FALSE(TransformationAddDeadContinue(100, true, {})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable: 10 is not in a loop.
   ASSERT_FALSE(TransformationAddDeadContinue(10, true, {})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable: 15 does not branch unconditionally to a single successor.
   ASSERT_FALSE(TransformationAddDeadContinue(15, true, {})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable: 13 is not in a loop and has no successor.
   ASSERT_FALSE(TransformationAddDeadContinue(13, true, {})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable: 14 is the loop continue target, so it's not OK to jump to
   // the loop continue from there.
   ASSERT_FALSE(TransformationAddDeadContinue(14, false, {})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // These are the transformations we will apply.
   auto transformation1 = TransformationAddDeadContinue(11, true, {});
   auto transformation2 = TransformationAddDeadContinue(12, false, {});
   auto transformation3 = TransformationAddDeadContinue(40, true, {});
 
-  ASSERT_TRUE(transformation1.IsApplicable(context.get(), fact_manager));
-  transformation1.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation1.IsApplicable(context.get(), transformation_context));
+  transformation1.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(transformation2.IsApplicable(context.get(), fact_manager));
-  transformation2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation2.IsApplicable(context.get(), transformation_context));
+  transformation2.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(transformation3.IsApplicable(context.get(), fact_manager));
-  transformation3.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation3.IsApplicable(context.get(), transformation_context));
+  transformation3.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_transformation = R"(
@@ -365,19 +371,24 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   std::vector<uint32_t> good = {6, 7, 18, 20, 34, 40, 45, 46, 47, 56, 57};
   std::vector<uint32_t> bad = {5, 8, 9, 19, 21, 22, 33, 41, 58, 59, 60};
 
   for (uint32_t from_block : bad) {
     ASSERT_FALSE(TransformationAddDeadContinue(from_block, true, {})
-                     .IsApplicable(context.get(), fact_manager));
+                     .IsApplicable(context.get(), transformation_context));
   }
   for (uint32_t from_block : good) {
     const TransformationAddDeadContinue transformation(from_block, true, {});
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
-    ASSERT_FALSE(transformation.IsApplicable(context.get(), fact_manager));
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
+    ASSERT_FALSE(
+        transformation.IsApplicable(context.get(), transformation_context));
   }
 
   std::string after_transformation = R"(
@@ -600,19 +611,24 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   std::vector<uint32_t> good = {32, 33, 46, 52, 101};
   std::vector<uint32_t> bad = {5, 34, 36, 35, 47, 49, 48};
 
   for (uint32_t from_block : bad) {
     ASSERT_FALSE(TransformationAddDeadContinue(from_block, false, {})
-                     .IsApplicable(context.get(), fact_manager));
+                     .IsApplicable(context.get(), transformation_context));
   }
   for (uint32_t from_block : good) {
     const TransformationAddDeadContinue transformation(from_block, false, {});
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
-    ASSERT_FALSE(transformation.IsApplicable(context.get(), fact_manager));
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
+    ASSERT_FALSE(
+        transformation.IsApplicable(context.get(), transformation_context));
   }
 
   std::string after_transformation = R"(
@@ -806,6 +822,9 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   std::vector<uint32_t> bad = {5, 19, 20, 23, 31, 32, 33, 70};
 
@@ -813,24 +832,28 @@
 
   for (uint32_t from_block : bad) {
     ASSERT_FALSE(TransformationAddDeadContinue(from_block, true, {})
-                     .IsApplicable(context.get(), fact_manager));
+                     .IsApplicable(context.get(), transformation_context));
   }
   auto transformation1 = TransformationAddDeadContinue(29, true, {13, 21});
-  ASSERT_TRUE(transformation1.IsApplicable(context.get(), fact_manager));
-  transformation1.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation1.IsApplicable(context.get(), transformation_context));
+  transformation1.Apply(context.get(), &transformation_context);
 
   auto transformation2 = TransformationAddDeadContinue(30, true, {22, 46});
-  ASSERT_TRUE(transformation2.IsApplicable(context.get(), fact_manager));
-  transformation2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation2.IsApplicable(context.get(), transformation_context));
+  transformation2.Apply(context.get(), &transformation_context);
 
   // 75 already has the continue block as a successor, so we should not provide
   // phi ids.
   auto transformationBad = TransformationAddDeadContinue(75, true, {27, 46});
-  ASSERT_FALSE(transformationBad.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      transformationBad.IsApplicable(context.get(), transformation_context));
 
   auto transformation3 = TransformationAddDeadContinue(75, true, {});
-  ASSERT_TRUE(transformation3.IsApplicable(context.get(), fact_manager));
-  transformation3.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation3.IsApplicable(context.get(), transformation_context));
+  transformation3.Apply(context.get(), &transformation_context);
 
   std::string after_transformation = R"(
                OpCapability Shader
@@ -974,26 +997,33 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // This transformation is not applicable because the dead continue from the
   // loop body prevents the definition of %23 later in the loop body from
   // dominating its use in the loop's continue target.
   auto bad_transformation = TransformationAddDeadContinue(13, false, {});
-  ASSERT_FALSE(bad_transformation.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      bad_transformation.IsApplicable(context.get(), transformation_context));
 
   auto good_transformation_1 = TransformationAddDeadContinue(7, false, {});
-  ASSERT_TRUE(good_transformation_1.IsApplicable(context.get(), fact_manager));
-  good_transformation_1.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(good_transformation_1.IsApplicable(context.get(),
+                                                 transformation_context));
+  good_transformation_1.Apply(context.get(), &transformation_context);
 
   auto good_transformation_2 = TransformationAddDeadContinue(22, false, {});
-  ASSERT_TRUE(good_transformation_2.IsApplicable(context.get(), fact_manager));
-  good_transformation_2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(good_transformation_2.IsApplicable(context.get(),
+                                                 transformation_context));
+  good_transformation_2.Apply(context.get(), &transformation_context);
 
   // This transformation is OK, because the definition of %21 in the loop body
   // is only used in an OpPhi in the loop's continue target.
   auto good_transformation_3 = TransformationAddDeadContinue(6, false, {11});
-  ASSERT_TRUE(good_transformation_3.IsApplicable(context.get(), fact_manager));
-  good_transformation_3.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(good_transformation_3.IsApplicable(context.get(),
+                                                 transformation_context));
+  good_transformation_3.Apply(context.get(), &transformation_context);
 
   std::string after_transformations = R"(
                OpCapability Shader
@@ -1083,11 +1113,15 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // This transformation would shortcut the part of the loop body that defines
   // an id used after the loop.
   auto bad_transformation = TransformationAddDeadContinue(100, false, {});
-  ASSERT_FALSE(bad_transformation.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      bad_transformation.IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationAddDeadContinueTest, RespectDominanceRules3) {
@@ -1131,11 +1165,15 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // This transformation would shortcut the part of the loop body that defines
   // an id used after the loop.
   auto bad_transformation = TransformationAddDeadContinue(100, false, {});
-  ASSERT_FALSE(bad_transformation.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      bad_transformation.IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationAddDeadContinueTest, Miscellaneous1) {
@@ -1270,11 +1308,15 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // This transformation would shortcut the part of the loop body that defines
   // an id used in the continue target.
   auto bad_transformation = TransformationAddDeadContinue(165, false, {});
-  ASSERT_FALSE(bad_transformation.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      bad_transformation.IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationAddDeadContinueTest, Miscellaneous2) {
@@ -1336,11 +1378,15 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // This transformation would introduce a branch from a continue target to
   // itself.
   auto bad_transformation = TransformationAddDeadContinue(1554, true, {});
-  ASSERT_FALSE(bad_transformation.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      bad_transformation.IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationAddDeadContinueTest, Miscellaneous3) {
@@ -1394,13 +1440,17 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   auto bad_transformation = TransformationAddDeadContinue(299, false, {});
 
   // The continue edge would connect %299 to the previously-unreachable %236,
   // making %299 dominate %236, and breaking the rule that block ordering must
   // respect dominance.
-  ASSERT_FALSE(bad_transformation.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      bad_transformation.IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationAddDeadContinueTest, Miscellaneous4) {
@@ -1454,13 +1504,17 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   auto bad_transformation = TransformationAddDeadContinue(10, false, {});
 
   // The continue edge would connect %10 to the previously-unreachable %13,
   // making %10 dominate %13, and breaking the rule that block ordering must
   // respect dominance.
-  ASSERT_FALSE(bad_transformation.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      bad_transformation.IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationAddDeadContinueTest, Miscellaneous5) {
@@ -1506,12 +1560,16 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   auto bad_transformation = TransformationAddDeadContinue(110, true, {});
 
   // The continue edge would lead to the use of %200 in block %101 no longer
   // being dominated by its definition in block %111.
-  ASSERT_FALSE(bad_transformation.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      bad_transformation.IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationAddDeadContinueTest, Miscellaneous6) {
@@ -1551,10 +1609,14 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   auto bad_transformation = TransformationAddDeadContinue(10, true, {});
 
-  ASSERT_FALSE(bad_transformation.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      bad_transformation.IsApplicable(context.get(), transformation_context));
 }
 
 }  // namespace
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_add_function_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_add_function_test.cpp
index aed12dc..0d1f2c4 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_add_function_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_add_function_test.cpp
@@ -59,13 +59,14 @@
 }
 
 // Returns true if and only if every pointer parameter and variable associated
-// with |function_id| in |context| is known by |fact_manager| to be irrelevant,
-// with the exception of |loop_limiter_id|, which must not be irrelevant.  (It
-// can be 0 if no loop limiter is expected, and 0 should not be deemed
-// irrelevant).
+// with |function_id| in |context| is known by |transformation_context| to be
+// irrelevant, with the exception of |loop_limiter_id|, which must not be
+// irrelevant.  (It can be 0 if no loop limiter is expected, and 0 should not be
+// deemed irrelevant).
 bool AllVariablesAndParametersExceptLoopLimiterAreIrrelevant(
-    opt::IRContext* context, const FactManager& fact_manager,
-    uint32_t function_id, uint32_t loop_limiter_id) {
+    opt::IRContext* context,
+    const TransformationContext& transformation_context, uint32_t function_id,
+    uint32_t loop_limiter_id) {
   // Look at all the functions until the function of interest is found.
   for (auto& function : *context->module()) {
     if (function.result_id() != function_id) {
@@ -73,15 +74,16 @@
     }
     // Check that the parameters are all irrelevant.
     bool found_non_irrelevant_parameter = false;
-    function.ForEachParam(
-        [context, &fact_manager,
-         &found_non_irrelevant_parameter](opt::Instruction* inst) {
-          if (context->get_def_use_mgr()->GetDef(inst->type_id())->opcode() ==
-                  SpvOpTypePointer &&
-              !fact_manager.PointeeValueIsIrrelevant(inst->result_id())) {
-            found_non_irrelevant_parameter = true;
-          }
-        });
+    function.ForEachParam([context, &transformation_context,
+                           &found_non_irrelevant_parameter](
+                              opt::Instruction* inst) {
+      if (context->get_def_use_mgr()->GetDef(inst->type_id())->opcode() ==
+              SpvOpTypePointer &&
+          !transformation_context.GetFactManager()->PointeeValueIsIrrelevant(
+              inst->result_id())) {
+        found_non_irrelevant_parameter = true;
+      }
+    });
     if (found_non_irrelevant_parameter) {
       // A non-irrelevant parameter was found.
       return false;
@@ -96,7 +98,8 @@
       // The variable should be irrelevant if and only if it is not the loop
       // limiter.
       if ((inst.result_id() == loop_limiter_id) ==
-          fact_manager.PointeeValueIsIrrelevant(inst.result_id())) {
+          transformation_context.GetFactManager()->PointeeValueIsIrrelevant(
+              inst.result_id())) {
         return false;
       }
     }
@@ -142,6 +145,9 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationAddFunction transformation1(std::vector<protobufs::Instruction>(
       {MakeInstructionMessage(
@@ -212,8 +218,9 @@
                               {{SPV_OPERAND_TYPE_ID, {39}}}),
        MakeInstructionMessage(SpvOpFunctionEnd, 0, 0, {})}));
 
-  ASSERT_TRUE(transformation1.IsApplicable(context.get(), fact_manager));
-  transformation1.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation1.IsApplicable(context.get(), transformation_context));
+  transformation1.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_transformation1 = R"(
@@ -278,12 +285,12 @@
                OpFunctionEnd
   )";
   ASSERT_TRUE(IsEqual(env, after_transformation1, context.get()));
-  ASSERT_TRUE(fact_manager.BlockIsDead(14));
-  ASSERT_TRUE(fact_manager.BlockIsDead(21));
-  ASSERT_TRUE(fact_manager.BlockIsDead(22));
-  ASSERT_TRUE(fact_manager.BlockIsDead(23));
-  ASSERT_TRUE(fact_manager.BlockIsDead(24));
-  ASSERT_TRUE(fact_manager.BlockIsDead(25));
+  ASSERT_TRUE(transformation_context.GetFactManager()->BlockIsDead(14));
+  ASSERT_TRUE(transformation_context.GetFactManager()->BlockIsDead(21));
+  ASSERT_TRUE(transformation_context.GetFactManager()->BlockIsDead(22));
+  ASSERT_TRUE(transformation_context.GetFactManager()->BlockIsDead(23));
+  ASSERT_TRUE(transformation_context.GetFactManager()->BlockIsDead(24));
+  ASSERT_TRUE(transformation_context.GetFactManager()->BlockIsDead(25));
 
   TransformationAddFunction transformation2(std::vector<protobufs::Instruction>(
       {MakeInstructionMessage(
@@ -332,8 +339,9 @@
        MakeInstructionMessage(SpvOpReturn, 0, 0, {}),
        MakeInstructionMessage(SpvOpFunctionEnd, 0, 0, {})}));
 
-  ASSERT_TRUE(transformation2.IsApplicable(context.get(), fact_manager));
-  transformation2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation2.IsApplicable(context.get(), transformation_context));
+  transformation2.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_transformation2 = R"(
@@ -414,7 +422,7 @@
                OpFunctionEnd
   )";
   ASSERT_TRUE(IsEqual(env, after_transformation2, context.get()));
-  ASSERT_TRUE(fact_manager.BlockIsDead(16));
+  ASSERT_TRUE(transformation_context.GetFactManager()->BlockIsDead(16));
 }
 
 TEST(TransformationAddFunctionTest, InapplicableTransformations) {
@@ -486,11 +494,14 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // No instructions
   ASSERT_FALSE(
       TransformationAddFunction(std::vector<protobufs::Instruction>({}))
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   // No function begin
   ASSERT_FALSE(
@@ -499,7 +510,7 @@
               {MakeInstructionMessage(SpvOpFunctionParameter, 7, 11, {}),
                MakeInstructionMessage(SpvOpFunctionParameter, 9, 12, {}),
                MakeInstructionMessage(SpvOpLabel, 0, 14, {})}))
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   // No OpLabel
   ASSERT_FALSE(
@@ -512,7 +523,7 @@
                MakeInstructionMessage(SpvOpReturnValue, 0, 0,
                                       {{SPV_OPERAND_TYPE_ID, {39}}}),
                MakeInstructionMessage(SpvOpFunctionEnd, 0, 0, {})}))
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   // Abrupt end of instructions
   ASSERT_FALSE(TransformationAddFunction(
@@ -521,7 +532,7 @@
                        {{SPV_OPERAND_TYPE_FUNCTION_CONTROL,
                          {SpvFunctionControlMaskNone}},
                         {SPV_OPERAND_TYPE_ID, {10}}})}))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // No function end
   ASSERT_FALSE(
@@ -534,7 +545,7 @@
                MakeInstructionMessage(SpvOpLabel, 0, 14, {}),
                MakeInstructionMessage(SpvOpReturnValue, 0, 0,
                                       {{SPV_OPERAND_TYPE_ID, {39}}})}))
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationAddFunctionTest, LoopLimiters) {
@@ -622,20 +633,27 @@
 
   FactManager fact_manager1;
   FactManager fact_manager2;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context1(&fact_manager1,
+                                                validator_options);
+  TransformationContext transformation_context2(&fact_manager2,
+                                                validator_options);
 
   const auto context1 = BuildModule(env, consumer, shader, kFuzzAssembleOption);
   const auto context2 = BuildModule(env, consumer, shader, kFuzzAssembleOption);
   ASSERT_TRUE(IsValid(env, context1.get()));
 
   TransformationAddFunction add_dead_function(instructions);
-  ASSERT_TRUE(add_dead_function.IsApplicable(context1.get(), fact_manager1));
-  add_dead_function.Apply(context1.get(), &fact_manager1);
+  ASSERT_TRUE(
+      add_dead_function.IsApplicable(context1.get(), transformation_context1));
+  add_dead_function.Apply(context1.get(), &transformation_context1);
   ASSERT_TRUE(IsValid(env, context1.get()));
   // The added function should not be deemed livesafe.
-  ASSERT_FALSE(fact_manager1.FunctionIsLivesafe(30));
+  ASSERT_FALSE(
+      transformation_context1.GetFactManager()->FunctionIsLivesafe(30));
   // All variables/parameters in the function should be deemed irrelevant.
   ASSERT_TRUE(AllVariablesAndParametersExceptLoopLimiterAreIrrelevant(
-      context1.get(), fact_manager1, 30, 0));
+      context1.get(), transformation_context1, 30, 0));
 
   std::string added_as_dead_code = R"(
                OpCapability Shader
@@ -711,16 +729,16 @@
 
   TransformationAddFunction add_livesafe_function(instructions, 100, 10,
                                                   loop_limiters, 0, {});
-  ASSERT_TRUE(
-      add_livesafe_function.IsApplicable(context2.get(), fact_manager2));
-  add_livesafe_function.Apply(context2.get(), &fact_manager2);
+  ASSERT_TRUE(add_livesafe_function.IsApplicable(context2.get(),
+                                                 transformation_context2));
+  add_livesafe_function.Apply(context2.get(), &transformation_context2);
   ASSERT_TRUE(IsValid(env, context2.get()));
   // The added function should indeed be deemed livesafe.
-  ASSERT_TRUE(fact_manager2.FunctionIsLivesafe(30));
+  ASSERT_TRUE(transformation_context2.GetFactManager()->FunctionIsLivesafe(30));
   // All variables/parameters in the function should be deemed irrelevant,
   // except the loop limiter.
   ASSERT_TRUE(AllVariablesAndParametersExceptLoopLimiterAreIrrelevant(
-      context2.get(), fact_manager2, 30, 100));
+      context2.get(), transformation_context2, 30, 100));
   std::string added_as_livesafe_code = R"(
                OpCapability Shader
           %1 = OpExtInstImport "GLSL.std.450"
@@ -837,20 +855,27 @@
 
   FactManager fact_manager1;
   FactManager fact_manager2;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context1(&fact_manager1,
+                                                validator_options);
+  TransformationContext transformation_context2(&fact_manager2,
+                                                validator_options);
 
   const auto context1 = BuildModule(env, consumer, shader, kFuzzAssembleOption);
   const auto context2 = BuildModule(env, consumer, shader, kFuzzAssembleOption);
   ASSERT_TRUE(IsValid(env, context1.get()));
 
   TransformationAddFunction add_dead_function(instructions);
-  ASSERT_TRUE(add_dead_function.IsApplicable(context1.get(), fact_manager1));
-  add_dead_function.Apply(context1.get(), &fact_manager1);
+  ASSERT_TRUE(
+      add_dead_function.IsApplicable(context1.get(), transformation_context1));
+  add_dead_function.Apply(context1.get(), &transformation_context1);
   ASSERT_TRUE(IsValid(env, context1.get()));
   // The added function should not be deemed livesafe.
-  ASSERT_FALSE(fact_manager1.FunctionIsLivesafe(10));
+  ASSERT_FALSE(
+      transformation_context1.GetFactManager()->FunctionIsLivesafe(10));
   // All variables/parameters in the function should be deemed irrelevant.
   ASSERT_TRUE(AllVariablesAndParametersExceptLoopLimiterAreIrrelevant(
-      context1.get(), fact_manager1, 10, 0));
+      context1.get(), transformation_context1, 10, 0));
 
   std::string added_as_dead_code = R"(
                OpCapability Shader
@@ -887,15 +912,15 @@
 
   TransformationAddFunction add_livesafe_function(instructions, 0, 0, {}, 0,
                                                   {});
-  ASSERT_TRUE(
-      add_livesafe_function.IsApplicable(context2.get(), fact_manager2));
-  add_livesafe_function.Apply(context2.get(), &fact_manager2);
+  ASSERT_TRUE(add_livesafe_function.IsApplicable(context2.get(),
+                                                 transformation_context2));
+  add_livesafe_function.Apply(context2.get(), &transformation_context2);
   ASSERT_TRUE(IsValid(env, context2.get()));
   // The added function should indeed be deemed livesafe.
-  ASSERT_TRUE(fact_manager2.FunctionIsLivesafe(10));
+  ASSERT_TRUE(transformation_context2.GetFactManager()->FunctionIsLivesafe(10));
   // All variables/parameters in the function should be deemed irrelevant.
   ASSERT_TRUE(AllVariablesAndParametersExceptLoopLimiterAreIrrelevant(
-      context2.get(), fact_manager2, 10, 0));
+      context2.get(), transformation_context2, 10, 0));
   std::string added_as_livesafe_code = R"(
                OpCapability Shader
           %1 = OpExtInstImport "GLSL.std.450"
@@ -985,20 +1010,27 @@
 
   FactManager fact_manager1;
   FactManager fact_manager2;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context1(&fact_manager1,
+                                                validator_options);
+  TransformationContext transformation_context2(&fact_manager2,
+                                                validator_options);
 
   const auto context1 = BuildModule(env, consumer, shader, kFuzzAssembleOption);
   const auto context2 = BuildModule(env, consumer, shader, kFuzzAssembleOption);
   ASSERT_TRUE(IsValid(env, context1.get()));
 
   TransformationAddFunction add_dead_function(instructions);
-  ASSERT_TRUE(add_dead_function.IsApplicable(context1.get(), fact_manager1));
-  add_dead_function.Apply(context1.get(), &fact_manager1);
+  ASSERT_TRUE(
+      add_dead_function.IsApplicable(context1.get(), transformation_context1));
+  add_dead_function.Apply(context1.get(), &transformation_context1);
   ASSERT_TRUE(IsValid(env, context1.get()));
   // The added function should not be deemed livesafe.
-  ASSERT_FALSE(fact_manager1.FunctionIsLivesafe(10));
+  ASSERT_FALSE(
+      transformation_context1.GetFactManager()->FunctionIsLivesafe(10));
   // All variables/parameters in the function should be deemed irrelevant.
   ASSERT_TRUE(AllVariablesAndParametersExceptLoopLimiterAreIrrelevant(
-      context1.get(), fact_manager1, 10, 0));
+      context1.get(), transformation_context1, 10, 0));
 
   std::string added_as_dead_code = R"(
                OpCapability Shader
@@ -1036,15 +1068,15 @@
 
   TransformationAddFunction add_livesafe_function(instructions, 0, 0, {}, 13,
                                                   {});
-  ASSERT_TRUE(
-      add_livesafe_function.IsApplicable(context2.get(), fact_manager2));
-  add_livesafe_function.Apply(context2.get(), &fact_manager2);
+  ASSERT_TRUE(add_livesafe_function.IsApplicable(context2.get(),
+                                                 transformation_context2));
+  add_livesafe_function.Apply(context2.get(), &transformation_context2);
   ASSERT_TRUE(IsValid(env, context2.get()));
   // The added function should indeed be deemed livesafe.
-  ASSERT_TRUE(fact_manager2.FunctionIsLivesafe(10));
+  ASSERT_TRUE(transformation_context2.GetFactManager()->FunctionIsLivesafe(10));
   // All variables/parameters in the function should be deemed irrelevant.
   ASSERT_TRUE(AllVariablesAndParametersExceptLoopLimiterAreIrrelevant(
-      context2.get(), fact_manager2, 10, 0));
+      context2.get(), transformation_context2, 10, 0));
   std::string added_as_livesafe_code = R"(
                OpCapability Shader
           %1 = OpExtInstImport "GLSL.std.450"
@@ -1265,20 +1297,27 @@
 
   FactManager fact_manager1;
   FactManager fact_manager2;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context1(&fact_manager1,
+                                                validator_options);
+  TransformationContext transformation_context2(&fact_manager2,
+                                                validator_options);
 
   const auto context1 = BuildModule(env, consumer, shader, kFuzzAssembleOption);
   const auto context2 = BuildModule(env, consumer, shader, kFuzzAssembleOption);
   ASSERT_TRUE(IsValid(env, context1.get()));
 
   TransformationAddFunction add_dead_function(instructions);
-  ASSERT_TRUE(add_dead_function.IsApplicable(context1.get(), fact_manager1));
-  add_dead_function.Apply(context1.get(), &fact_manager1);
+  ASSERT_TRUE(
+      add_dead_function.IsApplicable(context1.get(), transformation_context1));
+  add_dead_function.Apply(context1.get(), &transformation_context1);
   ASSERT_TRUE(IsValid(env, context1.get()));
   // The function should not be deemed livesafe
-  ASSERT_FALSE(fact_manager1.FunctionIsLivesafe(12));
+  ASSERT_FALSE(
+      transformation_context1.GetFactManager()->FunctionIsLivesafe(12));
   // All variables/parameters in the function should be deemed irrelevant.
   ASSERT_TRUE(AllVariablesAndParametersExceptLoopLimiterAreIrrelevant(
-      context1.get(), fact_manager1, 12, 0));
+      context1.get(), transformation_context1, 12, 0));
 
   std::string added_as_dead_code = R"(
                OpCapability Shader
@@ -1409,15 +1448,15 @@
 
   TransformationAddFunction add_livesafe_function(instructions, 0, 0, {}, 13,
                                                   access_chain_clamping_info);
-  ASSERT_TRUE(
-      add_livesafe_function.IsApplicable(context2.get(), fact_manager2));
-  add_livesafe_function.Apply(context2.get(), &fact_manager2);
+  ASSERT_TRUE(add_livesafe_function.IsApplicable(context2.get(),
+                                                 transformation_context2));
+  add_livesafe_function.Apply(context2.get(), &transformation_context2);
   ASSERT_TRUE(IsValid(env, context2.get()));
   // The function should be deemed livesafe
-  ASSERT_TRUE(fact_manager2.FunctionIsLivesafe(12));
+  ASSERT_TRUE(transformation_context2.GetFactManager()->FunctionIsLivesafe(12));
   // All variables/parameters in the function should be deemed irrelevant.
   ASSERT_TRUE(AllVariablesAndParametersExceptLoopLimiterAreIrrelevant(
-      context2.get(), fact_manager2, 12, 0));
+      context2.get(), transformation_context2, 12, 0));
   std::string added_as_livesafe_code = R"(
                OpCapability Shader
           %1 = OpExtInstImport "GLSL.std.450"
@@ -1585,23 +1624,29 @@
 
   FactManager fact_manager1;
   FactManager fact_manager2;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context1(&fact_manager1,
+                                                validator_options);
+  TransformationContext transformation_context2(&fact_manager2,
+                                                validator_options);
 
   // Mark function 6 as livesafe.
-  fact_manager2.AddFactFunctionIsLivesafe(6);
+  transformation_context2.GetFactManager()->AddFactFunctionIsLivesafe(6);
 
   const auto context1 = BuildModule(env, consumer, shader, kFuzzAssembleOption);
   const auto context2 = BuildModule(env, consumer, shader, kFuzzAssembleOption);
   ASSERT_TRUE(IsValid(env, context1.get()));
 
   TransformationAddFunction add_dead_function(instructions);
-  ASSERT_TRUE(add_dead_function.IsApplicable(context1.get(), fact_manager1));
-  add_dead_function.Apply(context1.get(), &fact_manager1);
+  ASSERT_TRUE(
+      add_dead_function.IsApplicable(context1.get(), transformation_context1));
+  add_dead_function.Apply(context1.get(), &transformation_context1);
   ASSERT_TRUE(IsValid(env, context1.get()));
   // The function should not be deemed livesafe
-  ASSERT_FALSE(fact_manager1.FunctionIsLivesafe(8));
+  ASSERT_FALSE(transformation_context1.GetFactManager()->FunctionIsLivesafe(8));
   // All variables/parameters in the function should be deemed irrelevant.
   ASSERT_TRUE(AllVariablesAndParametersExceptLoopLimiterAreIrrelevant(
-      context1.get(), fact_manager1, 8, 0));
+      context1.get(), transformation_context1, 8, 0));
 
   std::string added_as_live_or_dead_code = R"(
                OpCapability Shader
@@ -1630,15 +1675,15 @@
 
   TransformationAddFunction add_livesafe_function(instructions, 0, 0, {}, 0,
                                                   {});
-  ASSERT_TRUE(
-      add_livesafe_function.IsApplicable(context2.get(), fact_manager2));
-  add_livesafe_function.Apply(context2.get(), &fact_manager2);
+  ASSERT_TRUE(add_livesafe_function.IsApplicable(context2.get(),
+                                                 transformation_context2));
+  add_livesafe_function.Apply(context2.get(), &transformation_context2);
   ASSERT_TRUE(IsValid(env, context2.get()));
   // The function should be deemed livesafe
-  ASSERT_TRUE(fact_manager2.FunctionIsLivesafe(8));
+  ASSERT_TRUE(transformation_context2.GetFactManager()->FunctionIsLivesafe(8));
   // All variables/parameters in the function should be deemed irrelevant.
   ASSERT_TRUE(AllVariablesAndParametersExceptLoopLimiterAreIrrelevant(
-      context2.get(), fact_manager2, 8, 0));
+      context2.get(), transformation_context2, 8, 0));
   ASSERT_TRUE(IsEqual(env, added_as_live_or_dead_code, context2.get()));
 }
 
@@ -1679,20 +1724,26 @@
 
   FactManager fact_manager1;
   FactManager fact_manager2;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context1(&fact_manager1,
+                                                validator_options);
+  TransformationContext transformation_context2(&fact_manager2,
+                                                validator_options);
 
   const auto context1 = BuildModule(env, consumer, shader, kFuzzAssembleOption);
   const auto context2 = BuildModule(env, consumer, shader, kFuzzAssembleOption);
   ASSERT_TRUE(IsValid(env, context1.get()));
 
   TransformationAddFunction add_dead_function(instructions);
-  ASSERT_TRUE(add_dead_function.IsApplicable(context1.get(), fact_manager1));
-  add_dead_function.Apply(context1.get(), &fact_manager1);
+  ASSERT_TRUE(
+      add_dead_function.IsApplicable(context1.get(), transformation_context1));
+  add_dead_function.Apply(context1.get(), &transformation_context1);
   ASSERT_TRUE(IsValid(env, context1.get()));
   // The function should not be deemed livesafe
-  ASSERT_FALSE(fact_manager1.FunctionIsLivesafe(8));
+  ASSERT_FALSE(transformation_context1.GetFactManager()->FunctionIsLivesafe(8));
   // All variables/parameters in the function should be deemed irrelevant.
   ASSERT_TRUE(AllVariablesAndParametersExceptLoopLimiterAreIrrelevant(
-      context1.get(), fact_manager1, 8, 0));
+      context1.get(), transformation_context1, 8, 0));
 
   std::string added_as_dead_code = R"(
                OpCapability Shader
@@ -1721,8 +1772,8 @@
 
   TransformationAddFunction add_livesafe_function(instructions, 0, 0, {}, 0,
                                                   {});
-  ASSERT_FALSE(
-      add_livesafe_function.IsApplicable(context2.get(), fact_manager2));
+  ASSERT_FALSE(add_livesafe_function.IsApplicable(context2.get(),
+                                                  transformation_context2));
 }
 
 TEST(TransformationAddFunctionTest,
@@ -1804,6 +1855,9 @@
   const auto consumer = nullptr;
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
   ASSERT_TRUE(IsValid(env, context.get()));
@@ -1821,8 +1875,9 @@
   loop_limiter_info.set_logical_op_id(105);
   TransformationAddFunction add_livesafe_function(instructions, 100, 32,
                                                   {loop_limiter_info}, 0, {});
-  ASSERT_TRUE(add_livesafe_function.IsApplicable(context.get(), fact_manager));
-  add_livesafe_function.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(add_livesafe_function.IsApplicable(context.get(),
+                                                 transformation_context));
+  add_livesafe_function.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
   std::string expected = R"(
                OpCapability Shader
@@ -1958,6 +2013,9 @@
   const auto consumer = nullptr;
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
   ASSERT_TRUE(IsValid(env, context.get()));
@@ -1975,8 +2033,9 @@
   loop_limiter_info.set_logical_op_id(105);
   TransformationAddFunction add_livesafe_function(instructions, 100, 32,
                                                   {loop_limiter_info}, 0, {});
-  ASSERT_TRUE(add_livesafe_function.IsApplicable(context.get(), fact_manager));
-  add_livesafe_function.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(add_livesafe_function.IsApplicable(context.get(),
+                                                 transformation_context));
+  add_livesafe_function.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
   std::string expected = R"(
                OpCapability Shader
@@ -2110,6 +2169,9 @@
   const auto consumer = nullptr;
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
   ASSERT_TRUE(IsValid(env, context.get()));
@@ -2127,8 +2189,9 @@
   loop_limiter_info.set_logical_op_id(105);
   TransformationAddFunction add_livesafe_function(instructions, 100, 32,
                                                   {loop_limiter_info}, 0, {});
-  ASSERT_TRUE(add_livesafe_function.IsApplicable(context.get(), fact_manager));
-  add_livesafe_function.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(add_livesafe_function.IsApplicable(context.get(),
+                                                 transformation_context));
+  add_livesafe_function.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
   std::string expected = R"(
                OpCapability Shader
@@ -2254,6 +2317,9 @@
   const auto consumer = nullptr;
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
   ASSERT_TRUE(IsValid(env, context.get()));
@@ -2271,8 +2337,9 @@
   loop_limiter_info.set_logical_op_id(105);
   TransformationAddFunction add_livesafe_function(instructions, 100, 32,
                                                   {loop_limiter_info}, 0, {});
-  ASSERT_TRUE(add_livesafe_function.IsApplicable(context.get(), fact_manager));
-  add_livesafe_function.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(add_livesafe_function.IsApplicable(context.get(),
+                                                 transformation_context));
+  add_livesafe_function.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
   std::string expected = R"(
                OpCapability Shader
@@ -2408,6 +2475,9 @@
   const auto consumer = nullptr;
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
   ASSERT_TRUE(IsValid(env, context.get()));
@@ -2425,8 +2495,9 @@
   loop_limiter_info.set_logical_op_id(105);
   TransformationAddFunction add_livesafe_function(instructions, 100, 32,
                                                   {loop_limiter_info}, 0, {});
-  ASSERT_TRUE(add_livesafe_function.IsApplicable(context.get(), fact_manager));
-  add_livesafe_function.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(add_livesafe_function.IsApplicable(context.get(),
+                                                 transformation_context));
+  add_livesafe_function.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
   std::string expected = R"(
                OpCapability Shader
@@ -2570,6 +2641,9 @@
   const auto consumer = nullptr;
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
   ASSERT_TRUE(IsValid(env, context.get()));
@@ -2590,15 +2664,17 @@
                                            {loop_limiter_info}, 0, {});
   // The loop limiter info is not good enough; it does not include ids to patch
   // up the OpPhi at the loop merge.
-  ASSERT_FALSE(no_op_phi_data.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      no_op_phi_data.IsApplicable(context.get(), transformation_context));
 
   // Add a phi id for the new edge from the loop back edge block to the loop
   // merge.
   loop_limiter_info.add_phi_id(28);
   TransformationAddFunction with_op_phi_data(instructions, 100, 28,
                                              {loop_limiter_info}, 0, {});
-  ASSERT_TRUE(with_op_phi_data.IsApplicable(context.get(), fact_manager));
-  with_op_phi_data.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      with_op_phi_data.IsApplicable(context.get(), transformation_context));
+  with_op_phi_data.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
   std::string expected = R"(
                OpCapability Shader
@@ -2758,6 +2834,9 @@
   const auto consumer = nullptr;
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
   ASSERT_TRUE(IsValid(env, context.get()));
@@ -2776,8 +2855,9 @@
 
   TransformationAddFunction transformation(instructions, 100, 28,
                                            {loop_limiter_info}, 0, {});
-  ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-  transformation.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
+  transformation.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
   std::string expected = R"(
                OpCapability Shader
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_add_global_undef_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_add_global_undef_test.cpp
index c14f7e9..8c06db0 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_add_global_undef_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_add_global_undef_test.cpp
@@ -47,17 +47,20 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // Id already in use
-  ASSERT_FALSE(TransformationAddGlobalUndef(4, 11).IsApplicable(context.get(),
-                                                                fact_manager));
+  ASSERT_FALSE(TransformationAddGlobalUndef(4, 11).IsApplicable(
+      context.get(), transformation_context));
   // %1 is not a type
-  ASSERT_FALSE(TransformationAddGlobalUndef(100, 1).IsApplicable(context.get(),
-                                                                 fact_manager));
+  ASSERT_FALSE(TransformationAddGlobalUndef(100, 1).IsApplicable(
+      context.get(), transformation_context));
 
   // %3 is a function type
-  ASSERT_FALSE(TransformationAddGlobalUndef(100, 3).IsApplicable(context.get(),
-                                                                 fact_manager));
+  ASSERT_FALSE(TransformationAddGlobalUndef(100, 3).IsApplicable(
+      context.get(), transformation_context));
 
   TransformationAddGlobalUndef transformations[] = {
       // %100 = OpUndef %6
@@ -79,8 +82,9 @@
       TransformationAddGlobalUndef(105, 11)};
 
   for (auto& transformation : transformations) {
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
   }
   ASSERT_TRUE(IsValid(env, context.get()));
 
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_add_global_variable_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_add_global_variable_test.cpp
index 619f068..5c74ca0 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_add_global_variable_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_add_global_variable_test.cpp
@@ -60,79 +60,105 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // Id already in use
-  ASSERT_FALSE(TransformationAddGlobalVariable(4, 10, 0, true)
-                   .IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      TransformationAddGlobalVariable(4, 10, SpvStorageClassPrivate, 0, true)
+          .IsApplicable(context.get(), transformation_context));
   // %1 is not a type
-  ASSERT_FALSE(TransformationAddGlobalVariable(100, 1, 0, false)
-                   .IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      TransformationAddGlobalVariable(100, 1, SpvStorageClassPrivate, 0, false)
+          .IsApplicable(context.get(), transformation_context));
 
   // %7 is not a pointer type
-  ASSERT_FALSE(TransformationAddGlobalVariable(100, 7, 0, true)
-                   .IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      TransformationAddGlobalVariable(100, 7, SpvStorageClassPrivate, 0, true)
+          .IsApplicable(context.get(), transformation_context));
 
   // %9 does not have Private storage class
-  ASSERT_FALSE(TransformationAddGlobalVariable(100, 9, 0, false)
-                   .IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      TransformationAddGlobalVariable(100, 9, SpvStorageClassPrivate, 0, false)
+          .IsApplicable(context.get(), transformation_context));
 
   // %15 does not have Private storage class
-  ASSERT_FALSE(TransformationAddGlobalVariable(100, 15, 0, true)
-                   .IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      TransformationAddGlobalVariable(100, 15, SpvStorageClassPrivate, 0, true)
+          .IsApplicable(context.get(), transformation_context));
 
   // %10 is a pointer to float, while %16 is an int constant
-  ASSERT_FALSE(TransformationAddGlobalVariable(100, 10, 16, false)
-                   .IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(TransformationAddGlobalVariable(100, 10, SpvStorageClassPrivate,
+                                               16, false)
+                   .IsApplicable(context.get(), transformation_context));
 
   // %10 is a Private pointer to float, while %15 is a variable with type
   // Uniform float pointer
-  ASSERT_FALSE(TransformationAddGlobalVariable(100, 10, 15, true)
-                   .IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      TransformationAddGlobalVariable(100, 10, SpvStorageClassPrivate, 15, true)
+          .IsApplicable(context.get(), transformation_context));
 
   // %12 is a Private pointer to int, while %10 is a variable with type
   // Private float pointer
-  ASSERT_FALSE(TransformationAddGlobalVariable(100, 12, 10, false)
-                   .IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(TransformationAddGlobalVariable(100, 12, SpvStorageClassPrivate,
+                                               10, false)
+                   .IsApplicable(context.get(), transformation_context));
 
   // %10 is pointer-to-float, and %14 has type pointer-to-float; that's not OK
   // since the initializer's type should be the *pointee* type.
-  ASSERT_FALSE(TransformationAddGlobalVariable(104, 10, 14, true)
-                   .IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      TransformationAddGlobalVariable(104, 10, SpvStorageClassPrivate, 14, true)
+          .IsApplicable(context.get(), transformation_context));
 
   // This would work in principle, but logical addressing does not allow
   // a pointer to a pointer.
-  ASSERT_FALSE(TransformationAddGlobalVariable(104, 17, 14, false)
-                   .IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(TransformationAddGlobalVariable(104, 17, SpvStorageClassPrivate,
+                                               14, false)
+                   .IsApplicable(context.get(), transformation_context));
 
   TransformationAddGlobalVariable transformations[] = {
       // %100 = OpVariable %12 Private
-      TransformationAddGlobalVariable(100, 12, 16, true),
+      TransformationAddGlobalVariable(100, 12, SpvStorageClassPrivate, 16,
+                                      true),
 
       // %101 = OpVariable %10 Private
-      TransformationAddGlobalVariable(101, 10, 40, false),
+      TransformationAddGlobalVariable(101, 10, SpvStorageClassPrivate, 40,
+                                      false),
 
       // %102 = OpVariable %13 Private
-      TransformationAddGlobalVariable(102, 13, 41, true),
+      TransformationAddGlobalVariable(102, 13, SpvStorageClassPrivate, 41,
+                                      true),
 
       // %103 = OpVariable %12 Private %16
-      TransformationAddGlobalVariable(103, 12, 16, false),
+      TransformationAddGlobalVariable(103, 12, SpvStorageClassPrivate, 16,
+                                      false),
 
       // %104 = OpVariable %19 Private %21
-      TransformationAddGlobalVariable(104, 19, 21, true),
+      TransformationAddGlobalVariable(104, 19, SpvStorageClassPrivate, 21,
+                                      true),
 
       // %105 = OpVariable %19 Private %22
-      TransformationAddGlobalVariable(105, 19, 22, false)};
+      TransformationAddGlobalVariable(105, 19, SpvStorageClassPrivate, 22,
+                                      false)};
 
   for (auto& transformation : transformations) {
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
   }
-  ASSERT_TRUE(fact_manager.PointeeValueIsIrrelevant(100));
-  ASSERT_TRUE(fact_manager.PointeeValueIsIrrelevant(102));
-  ASSERT_TRUE(fact_manager.PointeeValueIsIrrelevant(104));
-  ASSERT_FALSE(fact_manager.PointeeValueIsIrrelevant(101));
-  ASSERT_FALSE(fact_manager.PointeeValueIsIrrelevant(103));
-  ASSERT_FALSE(fact_manager.PointeeValueIsIrrelevant(105));
+  ASSERT_TRUE(
+      transformation_context.GetFactManager()->PointeeValueIsIrrelevant(100));
+  ASSERT_TRUE(
+      transformation_context.GetFactManager()->PointeeValueIsIrrelevant(102));
+  ASSERT_TRUE(
+      transformation_context.GetFactManager()->PointeeValueIsIrrelevant(104));
+  ASSERT_FALSE(
+      transformation_context.GetFactManager()->PointeeValueIsIrrelevant(101));
+  ASSERT_FALSE(
+      transformation_context.GetFactManager()->PointeeValueIsIrrelevant(103));
+  ASSERT_FALSE(
+      transformation_context.GetFactManager()->PointeeValueIsIrrelevant(105));
 
   ASSERT_TRUE(IsValid(env, context.get()));
 
@@ -223,24 +249,34 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationAddGlobalVariable transformations[] = {
       // %100 = OpVariable %12 Private
-      TransformationAddGlobalVariable(100, 12, 16, true),
+      TransformationAddGlobalVariable(100, 12, SpvStorageClassPrivate, 16,
+                                      true),
 
       // %101 = OpVariable %12 Private %16
-      TransformationAddGlobalVariable(101, 12, 16, false),
+      TransformationAddGlobalVariable(101, 12, SpvStorageClassPrivate, 16,
+                                      false),
 
       // %102 = OpVariable %19 Private %21
-      TransformationAddGlobalVariable(102, 19, 21, true)};
+      TransformationAddGlobalVariable(102, 19, SpvStorageClassPrivate, 21,
+                                      true)};
 
   for (auto& transformation : transformations) {
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
   }
-  ASSERT_TRUE(fact_manager.PointeeValueIsIrrelevant(100));
-  ASSERT_TRUE(fact_manager.PointeeValueIsIrrelevant(102));
-  ASSERT_FALSE(fact_manager.PointeeValueIsIrrelevant(101));
+  ASSERT_TRUE(
+      transformation_context.GetFactManager()->PointeeValueIsIrrelevant(100));
+  ASSERT_TRUE(
+      transformation_context.GetFactManager()->PointeeValueIsIrrelevant(102));
+  ASSERT_FALSE(
+      transformation_context.GetFactManager()->PointeeValueIsIrrelevant(101));
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_transformation = R"(
@@ -284,6 +320,85 @@
   ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
 }
 
+TEST(TransformationAddGlobalVariableTest, TestAddingWorkgroupGlobals) {
+  // This checks that workgroup globals can be added to a compute shader.
+  std::string shader = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %4 "main"
+               OpExecutionMode %4 LocalSize 1 1 1
+               OpSource ESSL 310
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %6 = OpTypeInt 32 1
+          %7 = OpTypePointer Workgroup %6
+         %50 = OpConstant %6 2
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  const auto env = SPV_ENV_UNIVERSAL_1_4;
+  const auto consumer = nullptr;
+  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+  ASSERT_TRUE(IsValid(env, context.get()));
+
+  FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
+
+#ifndef NDEBUG
+  ASSERT_DEATH(
+      TransformationAddGlobalVariable(8, 7, SpvStorageClassWorkgroup, 50, true)
+          .IsApplicable(context.get(), transformation_context),
+      "By construction this transformation should not have an.*initializer "
+      "when Workgroup storage class is used");
+#endif
+
+  TransformationAddGlobalVariable transformations[] = {
+      // %8 = OpVariable %7 Workgroup
+      TransformationAddGlobalVariable(8, 7, SpvStorageClassWorkgroup, 0, true),
+
+      // %10 = OpVariable %7 Workgroup
+      TransformationAddGlobalVariable(10, 7, SpvStorageClassWorkgroup, 0,
+                                      false)};
+
+  for (auto& transformation : transformations) {
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
+  }
+  ASSERT_TRUE(
+      transformation_context.GetFactManager()->PointeeValueIsIrrelevant(8));
+  ASSERT_FALSE(
+      transformation_context.GetFactManager()->PointeeValueIsIrrelevant(10));
+  ASSERT_TRUE(IsValid(env, context.get()));
+
+  std::string after_transformation = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %4 "main" %8 %10
+               OpExecutionMode %4 LocalSize 1 1 1
+               OpSource ESSL 310
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %6 = OpTypeInt 32 1
+          %7 = OpTypePointer Workgroup %6
+         %50 = OpConstant %6 2
+          %8 = OpVariable %7 Workgroup
+         %10 = OpVariable %7 Workgroup
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+               OpReturn
+               OpFunctionEnd
+  )";
+  ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
+}
+
 }  // namespace
 }  // namespace fuzz
 }  // namespace spvtools
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_add_local_variable_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_add_local_variable_test.cpp
index fd7047f..e989b33 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_add_local_variable_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_add_local_variable_test.cpp
@@ -79,66 +79,81 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // A few cases of inapplicable transformations:
   // Id 4 is already in use
   ASSERT_FALSE(TransformationAddLocalVariable(4, 50, 4, 51, true)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   // Type mismatch between initializer and pointer
   ASSERT_FALSE(TransformationAddLocalVariable(105, 46, 4, 51, true)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   // Id 5 is not a function
   ASSERT_FALSE(TransformationAddLocalVariable(105, 50, 5, 51, true)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // %105 = OpVariable %50 Function %51
   {
     TransformationAddLocalVariable transformation(105, 50, 4, 51, true);
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
   }
 
   // %104 = OpVariable %41 Function %46
   {
     TransformationAddLocalVariable transformation(104, 41, 4, 46, false);
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
   }
 
   // %103 = OpVariable %35 Function %38
   {
     TransformationAddLocalVariable transformation(103, 35, 4, 38, true);
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
   }
 
   // %102 = OpVariable %31 Function %33
   {
     TransformationAddLocalVariable transformation(102, 31, 4, 33, false);
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
   }
 
   // %101 = OpVariable %19 Function %29
   {
     TransformationAddLocalVariable transformation(101, 19, 4, 29, true);
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
   }
 
   // %100 = OpVariable %8 Function %12
   {
     TransformationAddLocalVariable transformation(100, 8, 4, 12, false);
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
   }
 
-  ASSERT_FALSE(fact_manager.PointeeValueIsIrrelevant(100));
-  ASSERT_TRUE(fact_manager.PointeeValueIsIrrelevant(101));
-  ASSERT_FALSE(fact_manager.PointeeValueIsIrrelevant(102));
-  ASSERT_TRUE(fact_manager.PointeeValueIsIrrelevant(103));
-  ASSERT_FALSE(fact_manager.PointeeValueIsIrrelevant(104));
-  ASSERT_TRUE(fact_manager.PointeeValueIsIrrelevant(105));
+  ASSERT_FALSE(
+      transformation_context.GetFactManager()->PointeeValueIsIrrelevant(100));
+  ASSERT_TRUE(
+      transformation_context.GetFactManager()->PointeeValueIsIrrelevant(101));
+  ASSERT_FALSE(
+      transformation_context.GetFactManager()->PointeeValueIsIrrelevant(102));
+  ASSERT_TRUE(
+      transformation_context.GetFactManager()->PointeeValueIsIrrelevant(103));
+  ASSERT_FALSE(
+      transformation_context.GetFactManager()->PointeeValueIsIrrelevant(104));
+  ASSERT_TRUE(
+      transformation_context.GetFactManager()->PointeeValueIsIrrelevant(105));
 
   std::string after_transformation = R"(
                OpCapability Shader
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_add_no_contraction_decoration_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_add_no_contraction_decoration_test.cpp
index b1a87ea..46841a5 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_add_no_contraction_decoration_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_add_no_contraction_decoration_test.cpp
@@ -94,23 +94,27 @@
   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
   ASSERT_TRUE(IsValid(env, context.get()));
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // Invalid: 200 is not an id
   ASSERT_FALSE(TransformationAddNoContractionDecoration(200).IsApplicable(
-      context.get(), fact_manager));
+      context.get(), transformation_context));
   // Invalid: 17 is a block id
   ASSERT_FALSE(TransformationAddNoContractionDecoration(17).IsApplicable(
-      context.get(), fact_manager));
+      context.get(), transformation_context));
   // Invalid: 24 is not arithmetic
   ASSERT_FALSE(TransformationAddNoContractionDecoration(24).IsApplicable(
-      context.get(), fact_manager));
+      context.get(), transformation_context));
 
   // It is valid to add NoContraction to each of these ids (and it's fine to
   // have duplicates of the decoration, in the case of 32).
   for (uint32_t result_id : {32u, 32u, 27u, 29u, 39u}) {
     TransformationAddNoContractionDecoration transformation(result_id);
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
     ASSERT_TRUE(IsValid(env, context.get()));
   }
 
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_add_type_array_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_add_type_array_test.cpp
index 2bcbe73..4392f99 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_add_type_array_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_add_type_array_test.cpp
@@ -54,37 +54,40 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // Id already in use
   ASSERT_FALSE(TransformationAddTypeArray(4, 10, 16).IsApplicable(
-      context.get(), fact_manager));
+      context.get(), transformation_context));
   // %1 is not a type
   ASSERT_FALSE(TransformationAddTypeArray(100, 1, 16)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // %3 is a function type
   ASSERT_FALSE(TransformationAddTypeArray(100, 3, 16)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // %2 is not a constant
   ASSERT_FALSE(TransformationAddTypeArray(100, 11, 2)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // %18 is not an integer
   ASSERT_FALSE(TransformationAddTypeArray(100, 11, 18)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // %13 is signed 0
   ASSERT_FALSE(TransformationAddTypeArray(100, 11, 13)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // %14 is negative
   ASSERT_FALSE(TransformationAddTypeArray(100, 11, 14)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // %17 is unsigned 0
   ASSERT_FALSE(TransformationAddTypeArray(100, 11, 17)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   TransformationAddTypeArray transformations[] = {
       // %100 = OpTypeArray %10 %16
@@ -94,8 +97,9 @@
       TransformationAddTypeArray(101, 7, 12)};
 
   for (auto& transformation : transformations) {
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
   }
   ASSERT_TRUE(IsValid(env, context.get()));
 
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_add_type_boolean_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_add_type_boolean_test.cpp
index 9975953..60eabd9 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_add_type_boolean_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_add_type_boolean_test.cpp
@@ -42,19 +42,23 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // Not applicable because id 1 is already in use.
-  ASSERT_FALSE(TransformationAddTypeBoolean(1).IsApplicable(context.get(),
-                                                            fact_manager));
+  ASSERT_FALSE(TransformationAddTypeBoolean(1).IsApplicable(
+      context.get(), transformation_context));
 
   auto add_type_bool = TransformationAddTypeBoolean(100);
-  ASSERT_TRUE(add_type_bool.IsApplicable(context.get(), fact_manager));
-  add_type_bool.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      add_type_bool.IsApplicable(context.get(), transformation_context));
+  add_type_bool.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Not applicable as we already have this type now.
-  ASSERT_FALSE(TransformationAddTypeBoolean(101).IsApplicable(context.get(),
-                                                              fact_manager));
+  ASSERT_FALSE(TransformationAddTypeBoolean(101).IsApplicable(
+      context.get(), transformation_context));
 
   std::string after_transformation = R"(
                OpCapability Shader
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_add_type_float_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_add_type_float_test.cpp
index 67408da..7d17266 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_add_type_float_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_add_type_float_test.cpp
@@ -42,19 +42,23 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // Not applicable because id 1 is already in use.
-  ASSERT_FALSE(TransformationAddTypeFloat(1, 32).IsApplicable(context.get(),
-                                                              fact_manager));
+  ASSERT_FALSE(TransformationAddTypeFloat(1, 32).IsApplicable(
+      context.get(), transformation_context));
 
   auto add_type_float_32 = TransformationAddTypeFloat(100, 32);
-  ASSERT_TRUE(add_type_float_32.IsApplicable(context.get(), fact_manager));
-  add_type_float_32.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      add_type_float_32.IsApplicable(context.get(), transformation_context));
+  add_type_float_32.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Not applicable as we already have this type now.
-  ASSERT_FALSE(TransformationAddTypeFloat(101, 32).IsApplicable(context.get(),
-                                                                fact_manager));
+  ASSERT_FALSE(TransformationAddTypeFloat(101, 32).IsApplicable(
+      context.get(), transformation_context));
 
   std::string after_transformation = R"(
                OpCapability Shader
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_add_type_function_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_add_type_function_test.cpp
index 46bd436..1557bb8 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_add_type_function_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_add_type_function_test.cpp
@@ -59,21 +59,24 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // Id already in use
   ASSERT_FALSE(TransformationAddTypeFunction(4, 12, {12, 16, 14})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   // %1 is not a type
   ASSERT_FALSE(TransformationAddTypeFunction(100, 1, {12, 16, 14})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // %18 is a function type
   ASSERT_FALSE(TransformationAddTypeFunction(100, 12, {18})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // A function of this signature already exists
   ASSERT_FALSE(TransformationAddTypeFunction(100, 17, {14, 16})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   TransformationAddTypeFunction transformations[] = {
       // %100 = OpTypeFunction %12 %12 %16 %14
@@ -86,8 +89,9 @@
       TransformationAddTypeFunction(102, 17, {200, 16})};
 
   for (auto& transformation : transformations) {
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
   }
   ASSERT_TRUE(IsValid(env, context.get()));
 
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_add_type_int_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_add_type_int_test.cpp
index c6f884c..63b17c2 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_add_type_int_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_add_type_int_test.cpp
@@ -42,10 +42,13 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // Not applicable because id 1 is already in use.
   ASSERT_FALSE(TransformationAddTypeInt(1, 32, false)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   auto add_type_signed_int_32 = TransformationAddTypeInt(100, 32, true);
   auto add_type_unsigned_int_32 = TransformationAddTypeInt(101, 32, false);
@@ -53,20 +56,21 @@
   auto add_type_unsigned_int_32_again =
       TransformationAddTypeInt(103, 32, false);
 
-  ASSERT_TRUE(add_type_signed_int_32.IsApplicable(context.get(), fact_manager));
-  add_type_signed_int_32.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(add_type_signed_int_32.IsApplicable(context.get(),
+                                                  transformation_context));
+  add_type_signed_int_32.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(
-      add_type_unsigned_int_32.IsApplicable(context.get(), fact_manager));
-  add_type_unsigned_int_32.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(add_type_unsigned_int_32.IsApplicable(context.get(),
+                                                    transformation_context));
+  add_type_unsigned_int_32.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Not applicable as we already have these types now.
-  ASSERT_FALSE(
-      add_type_signed_int_32_again.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(
-      add_type_unsigned_int_32_again.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(add_type_signed_int_32_again.IsApplicable(
+      context.get(), transformation_context));
+  ASSERT_FALSE(add_type_unsigned_int_32_again.IsApplicable(
+      context.get(), transformation_context));
 
   std::string after_transformation = R"(
                OpCapability Shader
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_add_type_matrix_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_add_type_matrix_test.cpp
index 84f27e9..e925012 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_add_type_matrix_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_add_type_matrix_test.cpp
@@ -47,17 +47,20 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // Id already in use
-  ASSERT_FALSE(TransformationAddTypeMatrix(4, 9, 2).IsApplicable(context.get(),
-                                                                 fact_manager));
+  ASSERT_FALSE(TransformationAddTypeMatrix(4, 9, 2).IsApplicable(
+      context.get(), transformation_context));
   // %1 is not a type
   ASSERT_FALSE(TransformationAddTypeMatrix(100, 1, 2).IsApplicable(
-      context.get(), fact_manager));
+      context.get(), transformation_context));
 
   // %11 is not a floating-point vector
   ASSERT_FALSE(TransformationAddTypeMatrix(100, 11, 2)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   TransformationAddTypeMatrix transformations[] = {
       // %100 = OpTypeMatrix %8 2
@@ -88,8 +91,9 @@
       TransformationAddTypeMatrix(108, 10, 4)};
 
   for (auto& transformation : transformations) {
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
   }
   ASSERT_TRUE(IsValid(env, context.get()));
 
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_add_type_pointer_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_add_type_pointer_test.cpp
index e36707f..35303e4 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_add_type_pointer_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_add_type_pointer_test.cpp
@@ -97,6 +97,9 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   auto bad_type_id_does_not_exist =
       TransformationAddTypePointer(100, SpvStorageClassFunction, 101);
@@ -122,12 +125,12 @@
   auto good_new_private_pointer_to_uniform_pointer_to_vec2 =
       TransformationAddTypePointer(108, SpvStorageClassPrivate, 107);
 
-  ASSERT_FALSE(
-      bad_type_id_does_not_exist.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(
-      bad_type_id_is_not_type.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(
-      bad_result_id_is_not_fresh.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(bad_type_id_does_not_exist.IsApplicable(context.get(),
+                                                       transformation_context));
+  ASSERT_FALSE(bad_type_id_is_not_type.IsApplicable(context.get(),
+                                                    transformation_context));
+  ASSERT_FALSE(bad_result_id_is_not_fresh.IsApplicable(context.get(),
+                                                       transformation_context));
 
   for (auto& transformation :
        {good_new_private_pointer_to_t, good_new_uniform_pointer_to_t,
@@ -136,8 +139,9 @@
         good_new_private_pointer_to_private_pointer_to_float,
         good_new_uniform_pointer_to_vec2,
         good_new_private_pointer_to_uniform_pointer_to_vec2}) {
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
     ASSERT_TRUE(IsValid(env, context.get()));
   }
 
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_add_type_struct_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_add_type_struct_test.cpp
index ae68c9a..06f78cd 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_add_type_struct_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_add_type_struct_test.cpp
@@ -47,17 +47,20 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // Id already in use
-  ASSERT_FALSE(TransformationAddTypeStruct(4, {}).IsApplicable(context.get(),
-                                                               fact_manager));
+  ASSERT_FALSE(TransformationAddTypeStruct(4, {}).IsApplicable(
+      context.get(), transformation_context));
   // %1 is not a type
   ASSERT_FALSE(TransformationAddTypeStruct(100, {1}).IsApplicable(
-      context.get(), fact_manager));
+      context.get(), transformation_context));
 
   // %3 is a function type
   ASSERT_FALSE(TransformationAddTypeStruct(100, {3}).IsApplicable(
-      context.get(), fact_manager));
+      context.get(), transformation_context));
 
   TransformationAddTypeStruct transformations[] = {
       // %100 = OpTypeStruct %6 %7 %8 %9 %10 %11
@@ -73,8 +76,9 @@
       TransformationAddTypeStruct(103, {6, 6})};
 
   for (auto& transformation : transformations) {
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
   }
   ASSERT_TRUE(IsValid(env, context.get()));
 
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_add_type_vector_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_add_type_vector_test.cpp
index 6ac4498..f1252a3 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_add_type_vector_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_add_type_vector_test.cpp
@@ -45,13 +45,16 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // Id already in use
-  ASSERT_FALSE(TransformationAddTypeVector(4, 6, 2).IsApplicable(context.get(),
-                                                                 fact_manager));
+  ASSERT_FALSE(TransformationAddTypeVector(4, 6, 2).IsApplicable(
+      context.get(), transformation_context));
   // %1 is not a type
   ASSERT_FALSE(TransformationAddTypeVector(100, 1, 2).IsApplicable(
-      context.get(), fact_manager));
+      context.get(), transformation_context));
 
   TransformationAddTypeVector transformations[] = {
       // %100 = OpTypeVector %6 2
@@ -67,8 +70,9 @@
       TransformationAddTypeVector(103, 9, 2)};
 
   for (auto& transformation : transformations) {
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
   }
   ASSERT_TRUE(IsValid(env, context.get()));
 
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_composite_construct_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_composite_construct_test.cpp
index d303368..b663866 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_composite_construct_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_composite_construct_test.cpp
@@ -129,6 +129,9 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // Make a vec2[3]
   TransformationCompositeConstruct make_vec2_array_length_3(
@@ -138,18 +141,18 @@
   TransformationCompositeConstruct make_vec2_array_length_3_bad(
       37, {41, 45, 27, 27}, MakeInstructionDescriptor(46, SpvOpAccessChain, 0),
       200);
-  ASSERT_TRUE(
-      make_vec2_array_length_3.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(
-      make_vec2_array_length_3_bad.IsApplicable(context.get(), fact_manager));
-  make_vec2_array_length_3.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(make_vec2_array_length_3.IsApplicable(context.get(),
+                                                    transformation_context));
+  ASSERT_FALSE(make_vec2_array_length_3_bad.IsApplicable(
+      context.get(), transformation_context));
+  make_vec2_array_length_3.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(41, {}), MakeDataDescriptor(200, {0}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(45, {}), MakeDataDescriptor(200, {1}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(27, {}), MakeDataDescriptor(200, {2}), context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(41, {}), MakeDataDescriptor(200, {0})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(45, {}), MakeDataDescriptor(200, {1})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(27, {}), MakeDataDescriptor(200, {2})));
 
   // Make a float[2]
   TransformationCompositeConstruct make_float_array_length_2(
@@ -157,16 +160,16 @@
   // Bad: %41 does not have type float
   TransformationCompositeConstruct make_float_array_length_2_bad(
       9, {41, 40}, MakeInstructionDescriptor(71, SpvOpStore, 0), 201);
-  ASSERT_TRUE(
-      make_float_array_length_2.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(
-      make_float_array_length_2_bad.IsApplicable(context.get(), fact_manager));
-  make_float_array_length_2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(make_float_array_length_2.IsApplicable(context.get(),
+                                                     transformation_context));
+  ASSERT_FALSE(make_float_array_length_2_bad.IsApplicable(
+      context.get(), transformation_context));
+  make_float_array_length_2.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(24, {}), MakeDataDescriptor(201, {0}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(40, {}), MakeDataDescriptor(201, {1}), context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(24, {}), MakeDataDescriptor(201, {0})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(40, {}), MakeDataDescriptor(201, {1})));
 
   // Make a bool[3]
   TransformationCompositeConstruct make_bool_array_length_3(
@@ -176,18 +179,18 @@
   TransformationCompositeConstruct make_bool_array_length_3_bad(
       47, {33, 54, 50}, MakeInstructionDescriptor(33, SpvOpSelectionMerge, 0),
       202);
-  ASSERT_TRUE(
-      make_bool_array_length_3.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(
-      make_bool_array_length_3_bad.IsApplicable(context.get(), fact_manager));
-  make_bool_array_length_3.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(make_bool_array_length_3.IsApplicable(context.get(),
+                                                    transformation_context));
+  ASSERT_FALSE(make_bool_array_length_3_bad.IsApplicable(
+      context.get(), transformation_context));
+  make_bool_array_length_3.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(33, {}), MakeDataDescriptor(202, {0}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(50, {}), MakeDataDescriptor(202, {1}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(50, {}), MakeDataDescriptor(202, {2}), context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(33, {}), MakeDataDescriptor(202, {0})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(50, {}), MakeDataDescriptor(202, {1})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(50, {}), MakeDataDescriptor(202, {2})));
 
   // make a uvec3[2][2]
   TransformationCompositeConstruct make_uvec3_array_length_2_2(
@@ -195,17 +198,16 @@
   // Bad: Skip count 100 is too large.
   TransformationCompositeConstruct make_uvec3_array_length_2_2_bad(
       58, {33, 54}, MakeInstructionDescriptor(64, SpvOpStore, 100), 203);
-  ASSERT_TRUE(
-      make_uvec3_array_length_2_2.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(make_uvec3_array_length_2_2_bad.IsApplicable(context.get(),
-                                                            fact_manager));
-  make_uvec3_array_length_2_2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(make_uvec3_array_length_2_2.IsApplicable(context.get(),
+                                                       transformation_context));
+  ASSERT_FALSE(make_uvec3_array_length_2_2_bad.IsApplicable(
+      context.get(), transformation_context));
+  make_uvec3_array_length_2_2.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(69, {}), MakeDataDescriptor(203, {0}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(100, {}),
-                                        MakeDataDescriptor(203, {1}),
-                                        context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(69, {}), MakeDataDescriptor(203, {0})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(100, {}), MakeDataDescriptor(203, {1})));
 
   std::string after_transformation = R"(
                OpCapability Shader
@@ -393,6 +395,9 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // make a mat3x4
   TransformationCompositeConstruct make_mat34(
@@ -400,16 +405,17 @@
   // Bad: %35 is mat4x3, not mat3x4.
   TransformationCompositeConstruct make_mat34_bad(
       35, {25, 28, 31}, MakeInstructionDescriptor(31, SpvOpReturn, 0), 200);
-  ASSERT_TRUE(make_mat34.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(make_mat34_bad.IsApplicable(context.get(), fact_manager));
-  make_mat34.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(make_mat34.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      make_mat34_bad.IsApplicable(context.get(), transformation_context));
+  make_mat34.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(25, {}), MakeDataDescriptor(200, {0}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(28, {}), MakeDataDescriptor(200, {1}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(31, {}), MakeDataDescriptor(200, {2}), context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(25, {}), MakeDataDescriptor(200, {0})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(28, {}), MakeDataDescriptor(200, {1})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(31, {}), MakeDataDescriptor(200, {2})));
 
   // make a mat4x3
   TransformationCompositeConstruct make_mat43(
@@ -417,19 +423,19 @@
   // Bad: %25 does not match the matrix's column type.
   TransformationCompositeConstruct make_mat43_bad(
       35, {25, 13, 16, 100}, MakeInstructionDescriptor(31, SpvOpStore, 0), 201);
-  ASSERT_TRUE(make_mat43.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(make_mat43_bad.IsApplicable(context.get(), fact_manager));
-  make_mat43.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(make_mat43.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      make_mat43_bad.IsApplicable(context.get(), transformation_context));
+  make_mat43.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(11, {}), MakeDataDescriptor(201, {0}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(13, {}), MakeDataDescriptor(201, {1}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(16, {}), MakeDataDescriptor(201, {2}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(100, {}),
-                                        MakeDataDescriptor(201, {3}),
-                                        context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(11, {}), MakeDataDescriptor(201, {0})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(13, {}), MakeDataDescriptor(201, {1})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(16, {}), MakeDataDescriptor(201, {2})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(100, {}), MakeDataDescriptor(201, {3})));
 
   std::string after_transformation = R"(
                OpCapability Shader
@@ -602,6 +608,9 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // make an Inner
   TransformationCompositeConstruct make_inner(
@@ -609,14 +618,15 @@
   // Bad: Too few fields to make the struct.
   TransformationCompositeConstruct make_inner_bad(
       9, {25}, MakeInstructionDescriptor(57, SpvOpAccessChain, 0), 200);
-  ASSERT_TRUE(make_inner.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(make_inner_bad.IsApplicable(context.get(), fact_manager));
-  make_inner.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(make_inner.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      make_inner_bad.IsApplicable(context.get(), transformation_context));
+  make_inner.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(25, {}), MakeDataDescriptor(200, {0}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(19, {}), MakeDataDescriptor(200, {1}), context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(25, {}), MakeDataDescriptor(200, {0})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(19, {}), MakeDataDescriptor(200, {1})));
 
   // make an Outer
   TransformationCompositeConstruct make_outer(
@@ -626,17 +636,17 @@
   TransformationCompositeConstruct make_outer_bad(
       33, {46, 200, 56},
       MakeInstructionDescriptor(200, SpvOpCompositeConstruct, 0), 201);
-  ASSERT_TRUE(make_outer.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(make_outer_bad.IsApplicable(context.get(), fact_manager));
-  make_outer.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(make_outer.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      make_outer_bad.IsApplicable(context.get(), transformation_context));
+  make_outer.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(46, {}), MakeDataDescriptor(201, {0}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(200, {}),
-                                        MakeDataDescriptor(201, {1}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(56, {}), MakeDataDescriptor(201, {2}), context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(46, {}), MakeDataDescriptor(201, {0})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(200, {}), MakeDataDescriptor(201, {1})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(56, {}), MakeDataDescriptor(201, {2})));
 
   std::string after_transformation = R"(
                OpCapability Shader
@@ -922,20 +932,24 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationCompositeConstruct make_vec2(
       7, {17, 11}, MakeInstructionDescriptor(100, SpvOpStore, 0), 200);
   // Bad: not enough data for a vec2
   TransformationCompositeConstruct make_vec2_bad(
       7, {11}, MakeInstructionDescriptor(100, SpvOpStore, 0), 200);
-  ASSERT_TRUE(make_vec2.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(make_vec2_bad.IsApplicable(context.get(), fact_manager));
-  make_vec2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(make_vec2.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      make_vec2_bad.IsApplicable(context.get(), transformation_context));
+  make_vec2.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(17, {}), MakeDataDescriptor(200, {0}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(11, {}), MakeDataDescriptor(200, {1}), context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(17, {}), MakeDataDescriptor(200, {0})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(11, {}), MakeDataDescriptor(200, {1})));
 
   TransformationCompositeConstruct make_vec3(
       25, {12, 32}, MakeInstructionDescriptor(35, SpvOpCompositeConstruct, 0),
@@ -944,18 +958,17 @@
   TransformationCompositeConstruct make_vec3_bad(
       25, {12, 32, 32},
       MakeInstructionDescriptor(35, SpvOpCompositeConstruct, 0), 201);
-  ASSERT_TRUE(make_vec3.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(make_vec3_bad.IsApplicable(context.get(), fact_manager));
-  make_vec3.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(make_vec3.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      make_vec3_bad.IsApplicable(context.get(), transformation_context));
+  make_vec3.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(12, {0}),
-                                        MakeDataDescriptor(201, {0}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(12, {1}),
-                                        MakeDataDescriptor(201, {1}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(32, {}), MakeDataDescriptor(201, {2}), context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(12, {0}), MakeDataDescriptor(201, {0})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(12, {1}), MakeDataDescriptor(201, {1})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(32, {}), MakeDataDescriptor(201, {2})));
 
   TransformationCompositeConstruct make_vec4(
       44, {32, 32, 10, 11}, MakeInstructionDescriptor(75, SpvOpAccessChain, 0),
@@ -964,34 +977,34 @@
   TransformationCompositeConstruct make_vec4_bad(
       44, {48, 32, 10, 11}, MakeInstructionDescriptor(75, SpvOpAccessChain, 0),
       202);
-  ASSERT_TRUE(make_vec4.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(make_vec4_bad.IsApplicable(context.get(), fact_manager));
-  make_vec4.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(make_vec4.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      make_vec4_bad.IsApplicable(context.get(), transformation_context));
+  make_vec4.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(32, {}), MakeDataDescriptor(202, {0}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(32, {}), MakeDataDescriptor(202, {1}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(10, {}), MakeDataDescriptor(202, {2}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(11, {}), MakeDataDescriptor(202, {3}), context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(32, {}), MakeDataDescriptor(202, {0})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(32, {}), MakeDataDescriptor(202, {1})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(10, {}), MakeDataDescriptor(202, {2})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(11, {}), MakeDataDescriptor(202, {3})));
 
   TransformationCompositeConstruct make_ivec2(
       51, {126, 120}, MakeInstructionDescriptor(128, SpvOpLoad, 0), 203);
   // Bad: if 128 is not available at the instruction that defines 128
   TransformationCompositeConstruct make_ivec2_bad(
       51, {128, 120}, MakeInstructionDescriptor(128, SpvOpLoad, 0), 203);
-  ASSERT_TRUE(make_ivec2.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(make_ivec2_bad.IsApplicable(context.get(), fact_manager));
-  make_ivec2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(make_ivec2.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      make_ivec2_bad.IsApplicable(context.get(), transformation_context));
+  make_ivec2.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(126, {}),
-                                        MakeDataDescriptor(203, {0}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(120, {}),
-                                        MakeDataDescriptor(203, {1}),
-                                        context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(126, {}), MakeDataDescriptor(203, {0})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(120, {}), MakeDataDescriptor(203, {1})));
 
   TransformationCompositeConstruct make_ivec3(
       114, {56, 117, 56}, MakeInstructionDescriptor(66, SpvOpAccessChain, 0),
@@ -1000,17 +1013,17 @@
   TransformationCompositeConstruct make_ivec3_bad(
       114, {56, 117, 1300}, MakeInstructionDescriptor(66, SpvOpAccessChain, 0),
       204);
-  ASSERT_TRUE(make_ivec3.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(make_ivec3_bad.IsApplicable(context.get(), fact_manager));
-  make_ivec3.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(make_ivec3.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      make_ivec3_bad.IsApplicable(context.get(), transformation_context));
+  make_ivec3.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(56, {}), MakeDataDescriptor(204, {0}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(117, {}),
-                                        MakeDataDescriptor(204, {1}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(56, {}), MakeDataDescriptor(204, {2}), context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(56, {}), MakeDataDescriptor(204, {0})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(117, {}), MakeDataDescriptor(204, {1})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(56, {}), MakeDataDescriptor(204, {2})));
 
   TransformationCompositeConstruct make_ivec4(
       122, {56, 117, 117, 117}, MakeInstructionDescriptor(66, SpvOpIAdd, 0),
@@ -1019,51 +1032,50 @@
   TransformationCompositeConstruct make_ivec4_bad(
       86, {56, 117, 117, 117}, MakeInstructionDescriptor(66, SpvOpIAdd, 0),
       205);
-  ASSERT_TRUE(make_ivec4.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(make_ivec4_bad.IsApplicable(context.get(), fact_manager));
-  make_ivec4.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(make_ivec4.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      make_ivec4_bad.IsApplicable(context.get(), transformation_context));
+  make_ivec4.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(56, {}), MakeDataDescriptor(205, {0}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(117, {}),
-                                        MakeDataDescriptor(205, {1}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(117, {}),
-                                        MakeDataDescriptor(205, {2}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(117, {}),
-                                        MakeDataDescriptor(205, {3}),
-                                        context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(56, {}), MakeDataDescriptor(205, {0})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(117, {}), MakeDataDescriptor(205, {1})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(117, {}), MakeDataDescriptor(205, {2})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(117, {}), MakeDataDescriptor(205, {3})));
 
   TransformationCompositeConstruct make_uvec2(
       86, {18, 38}, MakeInstructionDescriptor(133, SpvOpAccessChain, 0), 206);
   TransformationCompositeConstruct make_uvec2_bad(
       86, {18, 38}, MakeInstructionDescriptor(133, SpvOpAccessChain, 200), 206);
-  ASSERT_TRUE(make_uvec2.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(make_uvec2_bad.IsApplicable(context.get(), fact_manager));
-  make_uvec2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(make_uvec2.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      make_uvec2_bad.IsApplicable(context.get(), transformation_context));
+  make_uvec2.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(18, {}), MakeDataDescriptor(206, {0}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(38, {}), MakeDataDescriptor(206, {1}), context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(18, {}), MakeDataDescriptor(206, {0})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(38, {}), MakeDataDescriptor(206, {1})));
 
   TransformationCompositeConstruct make_uvec3(
       59, {14, 18, 136}, MakeInstructionDescriptor(137, SpvOpReturn, 0), 207);
   // Bad because 1300 is not an id
   TransformationCompositeConstruct make_uvec3_bad(
       59, {14, 18, 1300}, MakeInstructionDescriptor(137, SpvOpReturn, 0), 207);
-  ASSERT_TRUE(make_uvec3.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(make_uvec3_bad.IsApplicable(context.get(), fact_manager));
-  make_uvec3.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(make_uvec3.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      make_uvec3_bad.IsApplicable(context.get(), transformation_context));
+  make_uvec3.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(14, {}), MakeDataDescriptor(207, {0}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(18, {}), MakeDataDescriptor(207, {1}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(136, {}),
-                                        MakeDataDescriptor(207, {2}),
-                                        context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(14, {}), MakeDataDescriptor(207, {0})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(18, {}), MakeDataDescriptor(207, {1})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(136, {}), MakeDataDescriptor(207, {2})));
 
   TransformationCompositeConstruct make_uvec4(
       131, {14, 18, 136, 136},
@@ -1072,20 +1084,19 @@
   TransformationCompositeConstruct make_uvec4_bad(
       86, {14, 18, 136, 136},
       MakeInstructionDescriptor(137, SpvOpAccessChain, 0), 208);
-  ASSERT_TRUE(make_uvec4.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(make_uvec4_bad.IsApplicable(context.get(), fact_manager));
-  make_uvec4.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(make_uvec4.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      make_uvec4_bad.IsApplicable(context.get(), transformation_context));
+  make_uvec4.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(14, {}), MakeDataDescriptor(208, {0}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(18, {}), MakeDataDescriptor(208, {1}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(136, {}),
-                                        MakeDataDescriptor(208, {2}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(136, {}),
-                                        MakeDataDescriptor(208, {3}),
-                                        context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(14, {}), MakeDataDescriptor(208, {0})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(18, {}), MakeDataDescriptor(208, {1})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(136, {}), MakeDataDescriptor(208, {2})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(136, {}), MakeDataDescriptor(208, {3})));
 
   TransformationCompositeConstruct make_bvec2(
       102,
@@ -1102,55 +1113,51 @@
           41,
       },
       MakeInstructionDescriptor(0, SpvOpExtInstImport, 0), 209);
-  ASSERT_TRUE(make_bvec2.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(make_bvec2_bad.IsApplicable(context.get(), fact_manager));
-  make_bvec2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(make_bvec2.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      make_bvec2_bad.IsApplicable(context.get(), transformation_context));
+  make_bvec2.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(111, {}),
-                                        MakeDataDescriptor(209, {0}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(41, {}), MakeDataDescriptor(209, {1}), context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(111, {}), MakeDataDescriptor(209, {0})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(41, {}), MakeDataDescriptor(209, {1})));
 
   TransformationCompositeConstruct make_bvec3(
       93, {108, 73}, MakeInstructionDescriptor(108, SpvOpStore, 0), 210);
   // Bad because there are too many components for a bvec3
   TransformationCompositeConstruct make_bvec3_bad(
       93, {108, 108}, MakeInstructionDescriptor(108, SpvOpStore, 0), 210);
-  ASSERT_TRUE(make_bvec3.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(make_bvec3_bad.IsApplicable(context.get(), fact_manager));
-  make_bvec3.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(make_bvec3.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      make_bvec3_bad.IsApplicable(context.get(), transformation_context));
+  make_bvec3.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(108, {0}),
-                                        MakeDataDescriptor(210, {0}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(108, {1}),
-                                        MakeDataDescriptor(210, {1}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(73, {}), MakeDataDescriptor(210, {2}), context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(108, {0}), MakeDataDescriptor(210, {0})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(108, {1}), MakeDataDescriptor(210, {1})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(73, {}), MakeDataDescriptor(210, {2})));
 
   TransformationCompositeConstruct make_bvec4(
       70, {108, 108}, MakeInstructionDescriptor(108, SpvOpBranch, 0), 211);
   // Bad because 21 is a type, not a result id
   TransformationCompositeConstruct make_bvec4_bad(
       70, {21, 108}, MakeInstructionDescriptor(108, SpvOpBranch, 0), 211);
-  ASSERT_TRUE(make_bvec4.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(make_bvec4_bad.IsApplicable(context.get(), fact_manager));
-  make_bvec4.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(make_bvec4.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      make_bvec4_bad.IsApplicable(context.get(), transformation_context));
+  make_bvec4.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(108, {0}),
-                                        MakeDataDescriptor(211, {0}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(108, {1}),
-                                        MakeDataDescriptor(211, {1}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(108, {0}),
-                                        MakeDataDescriptor(211, {2}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(108, {1}),
-                                        MakeDataDescriptor(211, {3}),
-                                        context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(108, {0}), MakeDataDescriptor(211, {0})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(108, {1}), MakeDataDescriptor(211, {1})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(108, {0}), MakeDataDescriptor(211, {2})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(108, {1}), MakeDataDescriptor(211, {3})));
 
   std::string after_transformation = R"(
                OpCapability Shader
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_composite_extract_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_composite_extract_test.cpp
index 5cc2115..a7674a6 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_composite_extract_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_composite_extract_test.cpp
@@ -96,100 +96,103 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // Instruction does not exist.
   ASSERT_FALSE(TransformationCompositeExtract(
                    MakeInstructionDescriptor(36, SpvOpIAdd, 0), 200, 101, {0})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Id for composite is not a composite.
   ASSERT_FALSE(TransformationCompositeExtract(
                    MakeInstructionDescriptor(36, SpvOpIAdd, 0), 200, 27, {})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Composite does not dominate instruction being inserted before.
   ASSERT_FALSE(
       TransformationCompositeExtract(
           MakeInstructionDescriptor(37, SpvOpAccessChain, 0), 200, 101, {0})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   // Too many indices for extraction from struct composite.
   ASSERT_FALSE(
       TransformationCompositeExtract(
           MakeInstructionDescriptor(24, SpvOpAccessChain, 0), 200, 101, {0, 0})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   // Too many indices for extraction from struct composite.
   ASSERT_FALSE(
       TransformationCompositeExtract(
           MakeInstructionDescriptor(13, SpvOpIEqual, 0), 200, 104, {0, 0, 0})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   // Out of bounds index for extraction from struct composite.
   ASSERT_FALSE(
       TransformationCompositeExtract(
           MakeInstructionDescriptor(13, SpvOpIEqual, 0), 200, 104, {0, 3})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   // Result id already used.
   ASSERT_FALSE(TransformationCompositeExtract(
                    MakeInstructionDescriptor(35, SpvOpFAdd, 0), 80, 103, {0})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   TransformationCompositeExtract transformation_1(
       MakeInstructionDescriptor(36, SpvOpConvertFToS, 0), 201, 100, {2});
-  ASSERT_TRUE(transformation_1.IsApplicable(context.get(), fact_manager));
-  transformation_1.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation_1.IsApplicable(context.get(), transformation_context));
+  transformation_1.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   TransformationCompositeExtract transformation_2(
       MakeInstructionDescriptor(37, SpvOpAccessChain, 0), 202, 104, {0, 2});
-  ASSERT_TRUE(transformation_2.IsApplicable(context.get(), fact_manager));
-  transformation_2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation_2.IsApplicable(context.get(), transformation_context));
+  transformation_2.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   TransformationCompositeExtract transformation_3(
       MakeInstructionDescriptor(29, SpvOpAccessChain, 0), 203, 104, {0});
-  ASSERT_TRUE(transformation_3.IsApplicable(context.get(), fact_manager));
-  transformation_3.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation_3.IsApplicable(context.get(), transformation_context));
+  transformation_3.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   TransformationCompositeExtract transformation_4(
       MakeInstructionDescriptor(24, SpvOpStore, 0), 204, 101, {0});
-  ASSERT_TRUE(transformation_4.IsApplicable(context.get(), fact_manager));
-  transformation_4.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation_4.IsApplicable(context.get(), transformation_context));
+  transformation_4.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   TransformationCompositeExtract transformation_5(
       MakeInstructionDescriptor(29, SpvOpBranch, 0), 205, 102, {2});
-  ASSERT_TRUE(transformation_5.IsApplicable(context.get(), fact_manager));
-  transformation_5.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation_5.IsApplicable(context.get(), transformation_context));
+  transformation_5.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   TransformationCompositeExtract transformation_6(
       MakeInstructionDescriptor(37, SpvOpReturn, 0), 206, 103, {1});
-  ASSERT_TRUE(transformation_6.IsApplicable(context.get(), fact_manager));
-  transformation_6.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation_6.IsApplicable(context.get(), transformation_context));
+  transformation_6.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(201, {}),
-                                        MakeDataDescriptor(100, {2}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(202, {}),
-                                        MakeDataDescriptor(104, {0, 2}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(203, {}),
-                                        MakeDataDescriptor(104, {0}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(204, {}),
-                                        MakeDataDescriptor(101, {0}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(205, {}),
-                                        MakeDataDescriptor(102, {2}),
-                                        context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(206, {}),
-                                        MakeDataDescriptor(103, {1}),
-                                        context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(201, {}), MakeDataDescriptor(100, {2})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(202, {}), MakeDataDescriptor(104, {0, 2})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(203, {}), MakeDataDescriptor(104, {0})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(204, {}), MakeDataDescriptor(101, {0})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(205, {}), MakeDataDescriptor(102, {2})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(206, {}), MakeDataDescriptor(103, {1})));
 
   std::string after_transformation = R"(
                OpCapability Shader
@@ -348,49 +351,52 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // Cannot insert before the OpVariables of a function.
   ASSERT_FALSE(
       TransformationCompositeExtract(
           MakeInstructionDescriptor(101, SpvOpVariable, 0), 200, 14, {0})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationCompositeExtract(
           MakeInstructionDescriptor(101, SpvOpVariable, 1), 200, 14, {1})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationCompositeExtract(
           MakeInstructionDescriptor(102, SpvOpVariable, 0), 200, 14, {1})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   // OK to insert right after the OpVariables.
   ASSERT_FALSE(TransformationCompositeExtract(
                    MakeInstructionDescriptor(102, SpvOpBranch, 1), 200, 14, {1})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Cannot insert before the OpPhis of a block.
   ASSERT_FALSE(TransformationCompositeExtract(
                    MakeInstructionDescriptor(60, SpvOpPhi, 0), 200, 14, {2})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationCompositeExtract(
                    MakeInstructionDescriptor(59, SpvOpPhi, 0), 200, 14, {3})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   // OK to insert after the OpPhis.
   ASSERT_TRUE(
       TransformationCompositeExtract(
           MakeInstructionDescriptor(59, SpvOpAccessChain, 0), 200, 14, {3})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   // Cannot insert before OpLoopMerge
   ASSERT_FALSE(TransformationCompositeExtract(
                    MakeInstructionDescriptor(33, SpvOpBranchConditional, 0),
                    200, 14, {3})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Cannot insert before OpSelectionMerge
   ASSERT_FALSE(TransformationCompositeExtract(
                    MakeInstructionDescriptor(21, SpvOpBranchConditional, 0),
                    200, 14, {2})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 }
 
 }  // namespace
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_compute_data_synonym_fact_closure_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_compute_data_synonym_fact_closure_test.cpp
new file mode 100644
index 0000000..5fa74b7
--- /dev/null
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_compute_data_synonym_fact_closure_test.cpp
@@ -0,0 +1,377 @@
+// Copyright (c) 2020 Google LLC
+//
+// 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
+//
+//     http://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.
+
+#include "source/fuzz/transformation_compute_data_synonym_fact_closure.h"
+#include "test/fuzz/fuzz_test_util.h"
+
+namespace spvtools {
+namespace fuzz {
+namespace {
+
+TEST(TransformationComputeDataSynonymFactClosureTest, DataSynonymFacts) {
+  // The SPIR-V types and constants come from the following code.  The body of
+  // the SPIR-V function then constructs a composite that is synonymous with
+  // myT.
+  //
+  // #version 310 es
+  //
+  // precision highp float;
+  //
+  // struct S {
+  //   int a;
+  //   uvec2 b;
+  // };
+  //
+  // struct T {
+  //   bool c[5];
+  //   mat4x2 d;
+  //   S e;
+  // };
+  //
+  // void main() {
+  //   T myT = T(bool[5](true, false, true, false, true),
+  //             mat4x2(vec2(1.0, 2.0), vec2(3.0, 4.0),
+  // 	           vec2(5.0, 6.0), vec2(7.0, 8.0)),
+  //             S(10, uvec2(100u, 200u)));
+  // }
+
+  std::string shader = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main"
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 310
+               OpName %4 "main"
+               OpName %15 "S"
+               OpMemberName %15 0 "a"
+               OpMemberName %15 1 "b"
+               OpName %16 "T"
+               OpMemberName %16 0 "c"
+               OpMemberName %16 1 "d"
+               OpMemberName %16 2 "e"
+               OpName %18 "myT"
+               OpMemberDecorate %15 0 RelaxedPrecision
+               OpMemberDecorate %15 1 RelaxedPrecision
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %6 = OpTypeBool
+          %7 = OpTypeInt 32 0
+          %8 = OpConstant %7 5
+          %9 = OpTypeArray %6 %8
+         %10 = OpTypeFloat 32
+         %11 = OpTypeVector %10 2
+         %12 = OpTypeMatrix %11 4
+         %13 = OpTypeInt 32 1
+         %14 = OpTypeVector %7 2
+         %15 = OpTypeStruct %13 %14
+         %16 = OpTypeStruct %9 %12 %15
+         %17 = OpTypePointer Function %16
+         %19 = OpConstantTrue %6
+         %20 = OpConstantFalse %6
+         %21 = OpConstantComposite %9 %19 %20 %19 %20 %19
+         %22 = OpConstant %10 1
+         %23 = OpConstant %10 2
+         %24 = OpConstantComposite %11 %22 %23
+         %25 = OpConstant %10 3
+         %26 = OpConstant %10 4
+         %27 = OpConstantComposite %11 %25 %26
+         %28 = OpConstant %10 5
+         %29 = OpConstant %10 6
+         %30 = OpConstantComposite %11 %28 %29
+         %31 = OpConstant %10 7
+         %32 = OpConstant %10 8
+         %33 = OpConstantComposite %11 %31 %32
+         %34 = OpConstantComposite %12 %24 %27 %30 %33
+         %35 = OpConstant %13 10
+         %36 = OpConstant %7 100
+         %37 = OpConstant %7 200
+         %38 = OpConstantComposite %14 %36 %37
+         %39 = OpConstantComposite %15 %35 %38
+         %40 = OpConstantComposite %16 %21 %34 %39
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+         %18 = OpVariable %17 Function
+               OpStore %18 %40
+        %100 = OpCompositeConstruct %9 %19 %20 %19 %20 %19
+        %101 = OpCompositeConstruct %11 %22 %23
+        %102 = OpCompositeConstruct %11 %25 %26
+        %103 = OpCompositeConstruct %11 %28 %29
+        %104 = OpCompositeConstruct %11 %31 %32
+        %105 = OpCompositeConstruct %12 %101 %102 %103 %104
+        %106 = OpCompositeConstruct %14 %36 %37
+        %107 = OpCompositeConstruct %15 %35 %106
+        %108 = OpCompositeConstruct %16 %100 %105 %107
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  const auto env = SPV_ENV_UNIVERSAL_1_3;
+  const auto consumer = nullptr;
+  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+  ASSERT_TRUE(IsValid(env, context.get()));
+
+  FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
+
+  ASSERT_TRUE(TransformationComputeDataSynonymFactClosure(100).IsApplicable(
+      context.get(), transformation_context));
+
+  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(24, {}),
+                                         MakeDataDescriptor(101, {})));
+  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(24, {0}),
+                                         MakeDataDescriptor(101, {0})));
+  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(24, {1}),
+                                         MakeDataDescriptor(101, {1})));
+  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(24, {0}),
+                                         MakeDataDescriptor(101, {1})));
+
+  fact_manager.AddFactDataSynonym(MakeDataDescriptor(24, {}),
+                                  MakeDataDescriptor(101, {}), context.get());
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(24, {}),
+                                        MakeDataDescriptor(101, {})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(24, {0}),
+                                        MakeDataDescriptor(101, {0})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(24, {1}),
+                                        MakeDataDescriptor(101, {1})));
+  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(24, {0}),
+                                         MakeDataDescriptor(101, {1})));
+
+  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(27, {}),
+                                         MakeDataDescriptor(102, {})));
+  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(27, {0}),
+                                         MakeDataDescriptor(102, {0})));
+  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(27, {1}),
+                                         MakeDataDescriptor(102, {1})));
+  fact_manager.AddFactDataSynonym(MakeDataDescriptor(27, {0}),
+                                  MakeDataDescriptor(102, {0}), context.get());
+  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(27, {}),
+                                         MakeDataDescriptor(102, {})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(27, {0}),
+                                        MakeDataDescriptor(102, {0})));
+  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(27, {1}),
+                                         MakeDataDescriptor(102, {1})));
+  fact_manager.AddFactDataSynonym(MakeDataDescriptor(27, {1}),
+                                  MakeDataDescriptor(102, {1}), context.get());
+
+  TransformationComputeDataSynonymFactClosure(100).Apply(
+      context.get(), &transformation_context);
+
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(27, {}),
+                                        MakeDataDescriptor(102, {})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(27, {0}),
+                                        MakeDataDescriptor(102, {0})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(27, {1}),
+                                        MakeDataDescriptor(102, {1})));
+
+  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(30, {}),
+                                         MakeDataDescriptor(103, {})));
+  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(30, {0}),
+                                         MakeDataDescriptor(103, {0})));
+  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(30, {1}),
+                                         MakeDataDescriptor(103, {1})));
+  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(33, {}),
+                                         MakeDataDescriptor(104, {})));
+  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(33, {0}),
+                                         MakeDataDescriptor(104, {0})));
+  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(33, {1}),
+                                         MakeDataDescriptor(104, {1})));
+  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(34, {}),
+                                         MakeDataDescriptor(105, {})));
+  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(34, {0}),
+                                         MakeDataDescriptor(105, {0})));
+  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(34, {1}),
+                                         MakeDataDescriptor(105, {1})));
+  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(34, {2}),
+                                         MakeDataDescriptor(105, {2})));
+  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(34, {3}),
+                                         MakeDataDescriptor(105, {3})));
+  fact_manager.AddFactDataSynonym(MakeDataDescriptor(30, {}),
+                                  MakeDataDescriptor(103, {}), context.get());
+  fact_manager.AddFactDataSynonym(MakeDataDescriptor(33, {}),
+                                  MakeDataDescriptor(104, {}), context.get());
+  fact_manager.AddFactDataSynonym(MakeDataDescriptor(34, {0}),
+                                  MakeDataDescriptor(105, {0}), context.get());
+  fact_manager.AddFactDataSynonym(MakeDataDescriptor(34, {1}),
+                                  MakeDataDescriptor(105, {1}), context.get());
+  fact_manager.AddFactDataSynonym(MakeDataDescriptor(34, {2}),
+                                  MakeDataDescriptor(105, {2}), context.get());
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(30, {}),
+                                        MakeDataDescriptor(103, {})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(30, {0}),
+                                        MakeDataDescriptor(103, {0})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(30, {1}),
+                                        MakeDataDescriptor(103, {1})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(33, {}),
+                                        MakeDataDescriptor(104, {})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(33, {0}),
+                                        MakeDataDescriptor(104, {0})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(33, {1}),
+                                        MakeDataDescriptor(104, {1})));
+  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(34, {}),
+                                         MakeDataDescriptor(105, {})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(34, {0}),
+                                        MakeDataDescriptor(105, {0})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(34, {1}),
+                                        MakeDataDescriptor(105, {1})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(34, {2}),
+                                        MakeDataDescriptor(105, {2})));
+  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(34, {3}),
+                                         MakeDataDescriptor(105, {3})));
+
+  fact_manager.AddFactDataSynonym(MakeDataDescriptor(34, {3}),
+                                  MakeDataDescriptor(105, {3}), context.get());
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(33, {0}),
+                                        MakeDataDescriptor(104, {0})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(34, {3}),
+                                        MakeDataDescriptor(105, {3})));
+
+  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(21, {}),
+                                         MakeDataDescriptor(100, {})));
+  fact_manager.AddFactDataSynonym(MakeDataDescriptor(21, {0}),
+                                  MakeDataDescriptor(100, {0}), context.get());
+  fact_manager.AddFactDataSynonym(MakeDataDescriptor(21, {1}),
+                                  MakeDataDescriptor(100, {1}), context.get());
+  fact_manager.AddFactDataSynonym(MakeDataDescriptor(21, {2}),
+                                  MakeDataDescriptor(100, {2}), context.get());
+  fact_manager.AddFactDataSynonym(MakeDataDescriptor(21, {3}),
+                                  MakeDataDescriptor(100, {3}), context.get());
+  fact_manager.AddFactDataSynonym(MakeDataDescriptor(21, {4}),
+                                  MakeDataDescriptor(100, {4}), context.get());
+
+  TransformationComputeDataSynonymFactClosure(100).Apply(
+      context.get(), &transformation_context);
+
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(21, {}),
+                                        MakeDataDescriptor(100, {})));
+
+  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(39, {0}),
+                                         MakeDataDescriptor(107, {0})));
+  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(35, {}),
+                                         MakeDataDescriptor(39, {0})));
+  fact_manager.AddFactDataSynonym(MakeDataDescriptor(39, {0}),
+                                  MakeDataDescriptor(35, {}), context.get());
+  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(39, {0}),
+                                         MakeDataDescriptor(107, {0})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(35, {}),
+                                        MakeDataDescriptor(39, {0})));
+
+  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(38, {0}),
+                                         MakeDataDescriptor(36, {})));
+  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(38, {1}),
+                                         MakeDataDescriptor(37, {})));
+  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(106, {0}),
+                                         MakeDataDescriptor(36, {})));
+  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(106, {1}),
+                                         MakeDataDescriptor(37, {})));
+  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(38, {}),
+                                         MakeDataDescriptor(106, {})));
+  fact_manager.AddFactDataSynonym(MakeDataDescriptor(38, {0}),
+                                  MakeDataDescriptor(36, {}), context.get());
+  fact_manager.AddFactDataSynonym(MakeDataDescriptor(106, {0}),
+                                  MakeDataDescriptor(36, {}), context.get());
+  fact_manager.AddFactDataSynonym(MakeDataDescriptor(38, {1}),
+                                  MakeDataDescriptor(37, {}), context.get());
+  fact_manager.AddFactDataSynonym(MakeDataDescriptor(106, {1}),
+                                  MakeDataDescriptor(37, {}), context.get());
+
+  TransformationComputeDataSynonymFactClosure(100).Apply(
+      context.get(), &transformation_context);
+
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(38, {0}),
+                                        MakeDataDescriptor(36, {})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(38, {1}),
+                                        MakeDataDescriptor(37, {})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(106, {0}),
+                                        MakeDataDescriptor(36, {})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(106, {1}),
+                                        MakeDataDescriptor(37, {})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(38, {}),
+                                        MakeDataDescriptor(106, {})));
+
+  ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {}),
+                                         MakeDataDescriptor(108, {})));
+  fact_manager.AddFactDataSynonym(MakeDataDescriptor(107, {0}),
+                                  MakeDataDescriptor(35, {}), context.get());
+  fact_manager.AddFactDataSynonym(MakeDataDescriptor(40, {0}),
+                                  MakeDataDescriptor(108, {0}), context.get());
+  fact_manager.AddFactDataSynonym(MakeDataDescriptor(40, {1}),
+                                  MakeDataDescriptor(108, {1}), context.get());
+  fact_manager.AddFactDataSynonym(MakeDataDescriptor(40, {2}),
+                                  MakeDataDescriptor(108, {2}), context.get());
+
+  TransformationComputeDataSynonymFactClosure(100).Apply(
+      context.get(), &transformation_context);
+
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {}),
+                                        MakeDataDescriptor(108, {})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {0}),
+                                        MakeDataDescriptor(108, {0})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1}),
+                                        MakeDataDescriptor(108, {1})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {2}),
+                                        MakeDataDescriptor(108, {2})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {0, 0}),
+                                        MakeDataDescriptor(108, {0, 0})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {0, 1}),
+                                        MakeDataDescriptor(108, {0, 1})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {0, 2}),
+                                        MakeDataDescriptor(108, {0, 2})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {0, 3}),
+                                        MakeDataDescriptor(108, {0, 3})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {0, 4}),
+                                        MakeDataDescriptor(108, {0, 4})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 0}),
+                                        MakeDataDescriptor(108, {1, 0})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 1}),
+                                        MakeDataDescriptor(108, {1, 1})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 2}),
+                                        MakeDataDescriptor(108, {1, 2})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 3}),
+                                        MakeDataDescriptor(108, {1, 3})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 0, 0}),
+                                        MakeDataDescriptor(108, {1, 0, 0})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 1, 0}),
+                                        MakeDataDescriptor(108, {1, 1, 0})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 2, 0}),
+                                        MakeDataDescriptor(108, {1, 2, 0})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 3, 0}),
+                                        MakeDataDescriptor(108, {1, 3, 0})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 0, 1}),
+                                        MakeDataDescriptor(108, {1, 0, 1})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 1, 1}),
+                                        MakeDataDescriptor(108, {1, 1, 1})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 2, 1}),
+                                        MakeDataDescriptor(108, {1, 2, 1})));
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {1, 3, 1}),
+                                        MakeDataDescriptor(108, {1, 3, 1})));
+
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {2, 0}),
+                                        MakeDataDescriptor(108, {2, 0})));
+
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {2, 1}),
+                                        MakeDataDescriptor(108, {2, 1})));
+
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {2, 1, 0}),
+                                        MakeDataDescriptor(108, {2, 1, 0})));
+
+  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {2, 1, 1}),
+                                        MakeDataDescriptor(108, {2, 1, 1})));
+}
+
+}  // namespace
+}  // namespace fuzz
+}  // namespace spvtools
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_copy_object_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_copy_object_test.cpp
index b85f75b..cf9d135 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_copy_object_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_copy_object_test.cpp
@@ -51,77 +51,92 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
-  ASSERT_EQ(0,
-            fact_manager.GetIdsForWhichSynonymsAreKnown(context.get()).size());
+  ASSERT_EQ(0, transformation_context.GetFactManager()
+                   ->GetIdsForWhichSynonymsAreKnown()
+                   .size());
 
   {
     TransformationCopyObject copy_true(
         7, MakeInstructionDescriptor(5, SpvOpReturn, 0), 100);
-    ASSERT_TRUE(copy_true.IsApplicable(context.get(), fact_manager));
-    copy_true.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(copy_true.IsApplicable(context.get(), transformation_context));
+    copy_true.Apply(context.get(), &transformation_context);
 
     std::vector<uint32_t> ids_for_which_synonyms_are_known =
-        fact_manager.GetIdsForWhichSynonymsAreKnown(context.get());
+        transformation_context.GetFactManager()
+            ->GetIdsForWhichSynonymsAreKnown();
     ASSERT_EQ(2, ids_for_which_synonyms_are_known.size());
     ASSERT_TRUE(std::find(ids_for_which_synonyms_are_known.begin(),
                           ids_for_which_synonyms_are_known.end(),
                           7) != ids_for_which_synonyms_are_known.end());
-    ASSERT_EQ(2, fact_manager.GetSynonymsForId(7, context.get()).size());
+    ASSERT_EQ(
+        2, transformation_context.GetFactManager()->GetSynonymsForId(7).size());
     protobufs::DataDescriptor descriptor_100 = MakeDataDescriptor(100, {});
-    ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(7, {}),
-                                          descriptor_100, context.get()));
+    ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+        MakeDataDescriptor(7, {}), descriptor_100));
   }
 
   {
     TransformationCopyObject copy_false(
         8, MakeInstructionDescriptor(100, SpvOpReturn, 0), 101);
-    ASSERT_TRUE(copy_false.IsApplicable(context.get(), fact_manager));
-    copy_false.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(copy_false.IsApplicable(context.get(), transformation_context));
+    copy_false.Apply(context.get(), &transformation_context);
     std::vector<uint32_t> ids_for_which_synonyms_are_known =
-        fact_manager.GetIdsForWhichSynonymsAreKnown(context.get());
+        transformation_context.GetFactManager()
+            ->GetIdsForWhichSynonymsAreKnown();
     ASSERT_EQ(4, ids_for_which_synonyms_are_known.size());
     ASSERT_TRUE(std::find(ids_for_which_synonyms_are_known.begin(),
                           ids_for_which_synonyms_are_known.end(),
                           8) != ids_for_which_synonyms_are_known.end());
-    ASSERT_EQ(2, fact_manager.GetSynonymsForId(8, context.get()).size());
+    ASSERT_EQ(
+        2, transformation_context.GetFactManager()->GetSynonymsForId(8).size());
     protobufs::DataDescriptor descriptor_101 = MakeDataDescriptor(101, {});
-    ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(8, {}),
-                                          descriptor_101, context.get()));
+    ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+        MakeDataDescriptor(8, {}), descriptor_101));
   }
 
   {
     TransformationCopyObject copy_false_again(
         101, MakeInstructionDescriptor(5, SpvOpReturn, 0), 102);
-    ASSERT_TRUE(copy_false_again.IsApplicable(context.get(), fact_manager));
-    copy_false_again.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        copy_false_again.IsApplicable(context.get(), transformation_context));
+    copy_false_again.Apply(context.get(), &transformation_context);
     std::vector<uint32_t> ids_for_which_synonyms_are_known =
-        fact_manager.GetIdsForWhichSynonymsAreKnown(context.get());
+        transformation_context.GetFactManager()
+            ->GetIdsForWhichSynonymsAreKnown();
     ASSERT_EQ(5, ids_for_which_synonyms_are_known.size());
     ASSERT_TRUE(std::find(ids_for_which_synonyms_are_known.begin(),
                           ids_for_which_synonyms_are_known.end(),
                           101) != ids_for_which_synonyms_are_known.end());
-    ASSERT_EQ(3, fact_manager.GetSynonymsForId(101, context.get()).size());
+    ASSERT_EQ(
+        3,
+        transformation_context.GetFactManager()->GetSynonymsForId(101).size());
     protobufs::DataDescriptor descriptor_102 = MakeDataDescriptor(102, {});
-    ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(101, {}),
-                                          descriptor_102, context.get()));
+    ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+        MakeDataDescriptor(101, {}), descriptor_102));
   }
 
   {
     TransformationCopyObject copy_true_again(
         7, MakeInstructionDescriptor(102, SpvOpReturn, 0), 103);
-    ASSERT_TRUE(copy_true_again.IsApplicable(context.get(), fact_manager));
-    copy_true_again.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        copy_true_again.IsApplicable(context.get(), transformation_context));
+    copy_true_again.Apply(context.get(), &transformation_context);
     std::vector<uint32_t> ids_for_which_synonyms_are_known =
-        fact_manager.GetIdsForWhichSynonymsAreKnown(context.get());
+        transformation_context.GetFactManager()
+            ->GetIdsForWhichSynonymsAreKnown();
     ASSERT_EQ(6, ids_for_which_synonyms_are_known.size());
     ASSERT_TRUE(std::find(ids_for_which_synonyms_are_known.begin(),
                           ids_for_which_synonyms_are_known.end(),
                           7) != ids_for_which_synonyms_are_known.end());
-    ASSERT_EQ(3, fact_manager.GetSynonymsForId(7, context.get()).size());
+    ASSERT_EQ(
+        3, transformation_context.GetFactManager()->GetSynonymsForId(7).size());
     protobufs::DataDescriptor descriptor_103 = MakeDataDescriptor(103, {});
-    ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(7, {}),
-                                          descriptor_103, context.get()));
+    ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+        MakeDataDescriptor(7, {}), descriptor_103));
   }
 
   std::string after_transformation = R"(
@@ -340,116 +355,119 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // Inapplicable because %18 is decorated.
   ASSERT_FALSE(TransformationCopyObject(
                    18, MakeInstructionDescriptor(21, SpvOpAccessChain, 0), 200)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable because %77 is decorated.
   ASSERT_FALSE(TransformationCopyObject(
                    77, MakeInstructionDescriptor(77, SpvOpBranch, 0), 200)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable because %80 is decorated.
   ASSERT_FALSE(TransformationCopyObject(
                    80, MakeInstructionDescriptor(77, SpvOpIAdd, 0), 200)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable because %84 is not available at the requested point
   ASSERT_FALSE(
       TransformationCopyObject(
           84, MakeInstructionDescriptor(32, SpvOpCompositeExtract, 0), 200)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   // Fine because %84 is available at the requested point
   ASSERT_TRUE(
       TransformationCopyObject(
           84, MakeInstructionDescriptor(32, SpvOpCompositeConstruct, 0), 200)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable because id %9 is already in use
   ASSERT_FALSE(
       TransformationCopyObject(
           84, MakeInstructionDescriptor(32, SpvOpCompositeConstruct, 0), 9)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable because the requested point does not exist
   ASSERT_FALSE(TransformationCopyObject(
                    84, MakeInstructionDescriptor(86, SpvOpReturn, 2), 200)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable because %9 is not in a function
   ASSERT_FALSE(TransformationCopyObject(
                    9, MakeInstructionDescriptor(9, SpvOpTypeInt, 0), 200)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable because the insert point is right before, or inside, a chunk
   // of OpPhis
   ASSERT_FALSE(TransformationCopyObject(
                    9, MakeInstructionDescriptor(30, SpvOpPhi, 0), 200)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationCopyObject(
                    9, MakeInstructionDescriptor(99, SpvOpPhi, 1), 200)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // OK, because the insert point is just after a chunk of OpPhis.
   ASSERT_TRUE(TransformationCopyObject(
                   9, MakeInstructionDescriptor(96, SpvOpAccessChain, 0), 200)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable because the insert point is right after an OpSelectionMerge
   ASSERT_FALSE(
       TransformationCopyObject(
           9, MakeInstructionDescriptor(58, SpvOpBranchConditional, 0), 200)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   // OK, because the insert point is right before the OpSelectionMerge
   ASSERT_TRUE(TransformationCopyObject(
                   9, MakeInstructionDescriptor(58, SpvOpSelectionMerge, 0), 200)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable because the insert point is right after an OpSelectionMerge
   ASSERT_FALSE(TransformationCopyObject(
                    9, MakeInstructionDescriptor(43, SpvOpSwitch, 0), 200)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // OK, because the insert point is right before the OpSelectionMerge
   ASSERT_TRUE(TransformationCopyObject(
                   9, MakeInstructionDescriptor(43, SpvOpSelectionMerge, 0), 200)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable because the insert point is right after an OpLoopMerge
   ASSERT_FALSE(
       TransformationCopyObject(
           9, MakeInstructionDescriptor(40, SpvOpBranchConditional, 0), 200)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   // OK, because the insert point is right before the OpLoopMerge
   ASSERT_TRUE(TransformationCopyObject(
                   9, MakeInstructionDescriptor(40, SpvOpLoopMerge, 0), 200)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable because id %300 does not exist
   ASSERT_FALSE(TransformationCopyObject(
                    300, MakeInstructionDescriptor(40, SpvOpLoopMerge, 0), 200)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable because the following instruction is OpVariable
   ASSERT_FALSE(TransformationCopyObject(
                    9, MakeInstructionDescriptor(180, SpvOpVariable, 0), 200)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationCopyObject(
                    9, MakeInstructionDescriptor(181, SpvOpVariable, 0), 200)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationCopyObject(
                    9, MakeInstructionDescriptor(182, SpvOpVariable, 0), 200)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // OK, because this is just past the group of OpVariable instructions.
   ASSERT_TRUE(TransformationCopyObject(
                   9, MakeInstructionDescriptor(182, SpvOpAccessChain, 0), 200)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationCopyObjectTest, MiscellaneousCopies) {
@@ -515,6 +533,9 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   std::vector<TransformationCopyObject> transformations = {
       TransformationCopyObject(19, MakeInstructionDescriptor(22, SpvOpStore, 0),
@@ -533,8 +554,9 @@
           17, MakeInstructionDescriptor(22, SpvOpCopyObject, 0), 106)};
 
   for (auto& transformation : transformations) {
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
   }
 
   ASSERT_TRUE(IsValid(env, context.get()));
@@ -614,16 +636,19 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // Illegal to copy null.
   ASSERT_FALSE(TransformationCopyObject(
                    8, MakeInstructionDescriptor(5, SpvOpReturn, 0), 100)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Illegal to copy an OpUndef of pointer type.
   ASSERT_FALSE(TransformationCopyObject(
                    9, MakeInstructionDescriptor(5, SpvOpReturn, 0), 100)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationCopyObjectTest, PropagateIrrelevantPointeeFact) {
@@ -655,7 +680,11 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
-  fact_manager.AddFactValueOfPointeeIsIrrelevant(8);
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
+
+  transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(8);
 
   TransformationCopyObject transformation1(
       8, MakeInstructionDescriptor(9, SpvOpReturn, 0), 100);
@@ -664,18 +693,84 @@
   TransformationCopyObject transformation3(
       100, MakeInstructionDescriptor(9, SpvOpReturn, 0), 102);
 
-  ASSERT_TRUE(transformation1.IsApplicable(context.get(), fact_manager));
-  transformation1.Apply(context.get(), &fact_manager);
-  ASSERT_TRUE(transformation2.IsApplicable(context.get(), fact_manager));
-  transformation2.Apply(context.get(), &fact_manager);
-  ASSERT_TRUE(transformation3.IsApplicable(context.get(), fact_manager));
-  transformation3.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation1.IsApplicable(context.get(), transformation_context));
+  transformation1.Apply(context.get(), &transformation_context);
+  ASSERT_TRUE(
+      transformation2.IsApplicable(context.get(), transformation_context));
+  transformation2.Apply(context.get(), &transformation_context);
+  ASSERT_TRUE(
+      transformation3.IsApplicable(context.get(), transformation_context));
+  transformation3.Apply(context.get(), &transformation_context);
 
-  ASSERT_TRUE(fact_manager.PointeeValueIsIrrelevant(8));
-  ASSERT_TRUE(fact_manager.PointeeValueIsIrrelevant(100));
-  ASSERT_TRUE(fact_manager.PointeeValueIsIrrelevant(102));
-  ASSERT_FALSE(fact_manager.PointeeValueIsIrrelevant(9));
-  ASSERT_FALSE(fact_manager.PointeeValueIsIrrelevant(101));
+  ASSERT_TRUE(
+      transformation_context.GetFactManager()->PointeeValueIsIrrelevant(8));
+  ASSERT_TRUE(
+      transformation_context.GetFactManager()->PointeeValueIsIrrelevant(100));
+  ASSERT_TRUE(
+      transformation_context.GetFactManager()->PointeeValueIsIrrelevant(102));
+  ASSERT_FALSE(
+      transformation_context.GetFactManager()->PointeeValueIsIrrelevant(9));
+  ASSERT_FALSE(
+      transformation_context.GetFactManager()->PointeeValueIsIrrelevant(101));
+}
+
+TEST(TransformationCopyObject, DoNotCopyOpSampledImage) {
+  // This checks that we do not try to copy the result id of an OpSampledImage
+  // instruction.
+  std::string shader = R"(
+               OpCapability Shader
+               OpCapability SampledBuffer
+               OpCapability ImageBuffer
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %2 "main" %40 %41
+               OpExecutionMode %2 OriginUpperLeft
+               OpSource GLSL 450
+               OpDecorate %40 DescriptorSet 0
+               OpDecorate %40 Binding 69
+               OpDecorate %41 DescriptorSet 0
+               OpDecorate %41 Binding 1
+         %54 = OpTypeFloat 32
+         %76 = OpTypeVector %54 4
+         %55 = OpConstant %54 0
+         %56 = OpTypeVector %54 3
+         %94 = OpTypeVector %54 2
+        %112 = OpConstantComposite %94 %55 %55
+         %57 = OpConstantComposite %56 %55 %55 %55
+         %15 = OpTypeImage %54 2D 2 0 0 1 Unknown
+        %114 = OpTypePointer UniformConstant %15
+         %38 = OpTypeSampler
+        %125 = OpTypePointer UniformConstant %38
+        %132 = OpTypeVoid
+        %133 = OpTypeFunction %132
+         %45 = OpTypeSampledImage %15
+         %40 = OpVariable %114 UniformConstant
+         %41 = OpVariable %125 UniformConstant
+          %2 = OpFunction %132 None %133
+        %164 = OpLabel
+        %184 = OpLoad %15 %40
+        %213 = OpLoad %38 %41
+        %216 = OpSampledImage %45 %184 %213
+        %217 = OpImageSampleImplicitLod %76 %216 %112 Bias %55
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  const auto env = SPV_ENV_UNIVERSAL_1_3;
+  const auto consumer = nullptr;
+  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+
+  FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
+
+  ASSERT_FALSE(
+      TransformationCopyObject(
+          216, MakeInstructionDescriptor(217, SpvOpImageSampleImplicitLod, 0),
+          500)
+          .IsApplicable(context.get(), transformation_context));
 }
 
 }  // namespace
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_equation_instruction_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_equation_instruction_test.cpp
index 81d849b..1e8aa7e 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_equation_instruction_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_equation_instruction_test.cpp
@@ -48,6 +48,9 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   protobufs::InstructionDescriptor return_instruction =
       MakeInstructionDescriptor(13, SpvOpReturn, 0);
@@ -55,59 +58,61 @@
   // Bad: id already in use.
   ASSERT_FALSE(TransformationEquationInstruction(7, SpvOpSNegate, {7},
                                                  return_instruction)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: identified instruction does not exist.
   ASSERT_FALSE(
       TransformationEquationInstruction(
           14, SpvOpSNegate, {7}, MakeInstructionDescriptor(13, SpvOpLoad, 0))
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   // Bad: id 100 does not exist
   ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpSNegate, {100},
                                                  return_instruction)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: id 20 is an OpUndef
   ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpSNegate, {20},
                                                  return_instruction)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: id 30 is not available right before its definition
   ASSERT_FALSE(TransformationEquationInstruction(
                    14, SpvOpSNegate, {30},
                    MakeInstructionDescriptor(30, SpvOpCopyObject, 0))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: too many arguments to OpSNegate.
   ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpSNegate, {7, 7},
                                                  return_instruction)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: 40 is a type id.
   ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpSNegate, {40},
                                                  return_instruction)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: wrong type of argument to OpSNegate.
   ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpSNegate, {41},
                                                  return_instruction)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   auto transformation1 = TransformationEquationInstruction(
       14, SpvOpSNegate, {7}, return_instruction);
-  ASSERT_TRUE(transformation1.IsApplicable(context.get(), fact_manager));
-  transformation1.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation1.IsApplicable(context.get(), transformation_context));
+  transformation1.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   auto transformation2 = TransformationEquationInstruction(
       15, SpvOpSNegate, {14}, return_instruction);
-  ASSERT_TRUE(transformation2.IsApplicable(context.get(), fact_manager));
-  transformation2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation2.IsApplicable(context.get(), transformation_context));
+  transformation2.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(15, {}), MakeDataDescriptor(7, {}), context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(15, {}), MakeDataDescriptor(7, {})));
 
   std::string after_transformation = R"(
                OpCapability Shader
@@ -161,6 +166,9 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   protobufs::InstructionDescriptor return_instruction =
       MakeInstructionDescriptor(13, SpvOpReturn, 0);
@@ -168,32 +176,34 @@
   // Bad: too few arguments to OpLogicalNot.
   ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpLogicalNot, {},
                                                  return_instruction)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: 6 is a type id.
   ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpLogicalNot, {6},
                                                  return_instruction)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: wrong type of argument to OpLogicalNot.
   ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpLogicalNot, {21},
                                                  return_instruction)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   auto transformation1 = TransformationEquationInstruction(
       14, SpvOpLogicalNot, {7}, return_instruction);
-  ASSERT_TRUE(transformation1.IsApplicable(context.get(), fact_manager));
-  transformation1.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation1.IsApplicable(context.get(), transformation_context));
+  transformation1.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   auto transformation2 = TransformationEquationInstruction(
       15, SpvOpLogicalNot, {14}, return_instruction);
-  ASSERT_TRUE(transformation2.IsApplicable(context.get(), fact_manager));
-  transformation2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation2.IsApplicable(context.get(), transformation_context));
+  transformation2.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(15, {}), MakeDataDescriptor(7, {}), context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(15, {}), MakeDataDescriptor(7, {})));
 
   std::string after_transformation = R"(
                OpCapability Shader
@@ -248,6 +258,9 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   protobufs::InstructionDescriptor return_instruction =
       MakeInstructionDescriptor(13, SpvOpReturn, 0);
@@ -255,59 +268,64 @@
   // Bad: too many arguments to OpIAdd.
   ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpIAdd, {15, 16, 16},
                                                  return_instruction)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   // Bad: boolean argument to OpIAdd.
   ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpIAdd, {15, 32},
                                                  return_instruction)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   // Bad: type as argument to OpIAdd.
   ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpIAdd, {33, 16},
                                                  return_instruction)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   // Bad: arguments of mismatched widths
   ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpIAdd, {15, 31},
                                                  return_instruction)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   // Bad: arguments of mismatched widths
   ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpIAdd, {31, 15},
                                                  return_instruction)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   auto transformation1 = TransformationEquationInstruction(
       14, SpvOpIAdd, {15, 16}, return_instruction);
-  ASSERT_TRUE(transformation1.IsApplicable(context.get(), fact_manager));
-  transformation1.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation1.IsApplicable(context.get(), transformation_context));
+  transformation1.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   auto transformation2 = TransformationEquationInstruction(
       19, SpvOpISub, {14, 16}, return_instruction);
-  ASSERT_TRUE(transformation2.IsApplicable(context.get(), fact_manager));
-  transformation2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation2.IsApplicable(context.get(), transformation_context));
+  transformation2.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(15, {}), MakeDataDescriptor(19, {}), context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(15, {}), MakeDataDescriptor(19, {})));
 
   auto transformation3 = TransformationEquationInstruction(
       20, SpvOpISub, {14, 15}, return_instruction);
-  ASSERT_TRUE(transformation3.IsApplicable(context.get(), fact_manager));
-  transformation3.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation3.IsApplicable(context.get(), transformation_context));
+  transformation3.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(20, {}), MakeDataDescriptor(16, {}), context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(20, {}), MakeDataDescriptor(16, {})));
 
   auto transformation4 = TransformationEquationInstruction(
       22, SpvOpISub, {16, 14}, return_instruction);
-  ASSERT_TRUE(transformation4.IsApplicable(context.get(), fact_manager));
-  transformation4.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation4.IsApplicable(context.get(), transformation_context));
+  transformation4.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   auto transformation5 = TransformationEquationInstruction(
       24, SpvOpSNegate, {22}, return_instruction);
-  ASSERT_TRUE(transformation5.IsApplicable(context.get(), fact_manager));
-  transformation5.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation5.IsApplicable(context.get(), transformation_context));
+  transformation5.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(24, {}), MakeDataDescriptor(15, {}), context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(24, {}), MakeDataDescriptor(15, {})));
 
   std::string after_transformation = R"(
                OpCapability Shader
@@ -364,69 +382,80 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   protobufs::InstructionDescriptor return_instruction =
       MakeInstructionDescriptor(13, SpvOpReturn, 0);
 
   auto transformation1 = TransformationEquationInstruction(
       14, SpvOpISub, {15, 16}, return_instruction);
-  ASSERT_TRUE(transformation1.IsApplicable(context.get(), fact_manager));
-  transformation1.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation1.IsApplicable(context.get(), transformation_context));
+  transformation1.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   auto transformation2 = TransformationEquationInstruction(
       17, SpvOpIAdd, {14, 16}, return_instruction);
-  ASSERT_TRUE(transformation2.IsApplicable(context.get(), fact_manager));
-  transformation2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation2.IsApplicable(context.get(), transformation_context));
+  transformation2.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(17, {}), MakeDataDescriptor(15, {}), context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(17, {}), MakeDataDescriptor(15, {})));
 
   auto transformation3 = TransformationEquationInstruction(
       18, SpvOpIAdd, {16, 14}, return_instruction);
-  ASSERT_TRUE(transformation3.IsApplicable(context.get(), fact_manager));
-  transformation3.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation3.IsApplicable(context.get(), transformation_context));
+  transformation3.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(17, {}), MakeDataDescriptor(18, {}), context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(18, {}), MakeDataDescriptor(15, {}), context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(17, {}), MakeDataDescriptor(18, {})));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(18, {}), MakeDataDescriptor(15, {})));
 
   auto transformation4 = TransformationEquationInstruction(
       19, SpvOpISub, {14, 15}, return_instruction);
-  ASSERT_TRUE(transformation4.IsApplicable(context.get(), fact_manager));
-  transformation4.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation4.IsApplicable(context.get(), transformation_context));
+  transformation4.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   auto transformation5 = TransformationEquationInstruction(
       20, SpvOpSNegate, {19}, return_instruction);
-  ASSERT_TRUE(transformation5.IsApplicable(context.get(), fact_manager));
-  transformation5.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation5.IsApplicable(context.get(), transformation_context));
+  transformation5.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(20, {}), MakeDataDescriptor(16, {}), context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(20, {}), MakeDataDescriptor(16, {})));
 
   auto transformation6 = TransformationEquationInstruction(
       21, SpvOpISub, {14, 19}, return_instruction);
-  ASSERT_TRUE(transformation6.IsApplicable(context.get(), fact_manager));
-  transformation6.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation6.IsApplicable(context.get(), transformation_context));
+  transformation6.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(21, {}), MakeDataDescriptor(15, {}), context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(21, {}), MakeDataDescriptor(15, {})));
 
   auto transformation7 = TransformationEquationInstruction(
       22, SpvOpISub, {14, 18}, return_instruction);
-  ASSERT_TRUE(transformation7.IsApplicable(context.get(), fact_manager));
-  transformation7.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation7.IsApplicable(context.get(), transformation_context));
+  transformation7.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   auto transformation8 = TransformationEquationInstruction(
       23, SpvOpSNegate, {22}, return_instruction);
-  ASSERT_TRUE(transformation8.IsApplicable(context.get(), fact_manager));
-  transformation8.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation8.IsApplicable(context.get(), transformation_context));
+  transformation8.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
-  ASSERT_TRUE(fact_manager.IsSynonymous(
-      MakeDataDescriptor(23, {}), MakeDataDescriptor(16, {}), context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(23, {}), MakeDataDescriptor(16, {})));
 
   std::string after_transformation = R"(
                OpCapability Shader
@@ -457,6 +486,146 @@
   ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
 }
 
+TEST(TransformationEquationInstructionTest, Miscellaneous1) {
+  std::string shader = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %12 "main"
+               OpExecutionMode %12 OriginUpperLeft
+               OpSource ESSL 310
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %6 = OpTypeInt 32 1
+        %113 = OpConstant %6 24
+         %12 = OpFunction %2 None %3
+         %13 = OpLabel
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  const auto env = SPV_ENV_UNIVERSAL_1_3;
+  const auto consumer = nullptr;
+  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+  ASSERT_TRUE(IsValid(env, context.get()));
+
+  FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
+
+  protobufs::InstructionDescriptor return_instruction =
+      MakeInstructionDescriptor(13, SpvOpReturn, 0);
+
+  auto transformation1 = TransformationEquationInstruction(
+      522, SpvOpISub, {113, 113}, return_instruction);
+  ASSERT_TRUE(
+      transformation1.IsApplicable(context.get(), transformation_context));
+  transformation1.Apply(context.get(), &transformation_context);
+  ASSERT_TRUE(IsValid(env, context.get()));
+
+  auto transformation2 = TransformationEquationInstruction(
+      570, SpvOpIAdd, {522, 113}, return_instruction);
+  ASSERT_TRUE(
+      transformation2.IsApplicable(context.get(), transformation_context));
+  transformation2.Apply(context.get(), &transformation_context);
+  ASSERT_TRUE(IsValid(env, context.get()));
+
+  std::string after_transformation = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %12 "main"
+               OpExecutionMode %12 OriginUpperLeft
+               OpSource ESSL 310
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %6 = OpTypeInt 32 1
+        %113 = OpConstant %6 24
+         %12 = OpFunction %2 None %3
+         %13 = OpLabel
+        %522 = OpISub %6 %113 %113
+        %570 = OpIAdd %6 %522 %113
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(570, {}), MakeDataDescriptor(113, {})));
+
+  ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
+}
+
+TEST(TransformationEquationInstructionTest, Miscellaneous2) {
+  std::string shader = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %12 "main"
+               OpExecutionMode %12 OriginUpperLeft
+               OpSource ESSL 310
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %6 = OpTypeInt 32 1
+        %113 = OpConstant %6 24
+         %12 = OpFunction %2 None %3
+         %13 = OpLabel
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  const auto env = SPV_ENV_UNIVERSAL_1_3;
+  const auto consumer = nullptr;
+  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+  ASSERT_TRUE(IsValid(env, context.get()));
+
+  FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
+
+  protobufs::InstructionDescriptor return_instruction =
+      MakeInstructionDescriptor(13, SpvOpReturn, 0);
+
+  auto transformation1 = TransformationEquationInstruction(
+      522, SpvOpISub, {113, 113}, return_instruction);
+  ASSERT_TRUE(
+      transformation1.IsApplicable(context.get(), transformation_context));
+  transformation1.Apply(context.get(), &transformation_context);
+  ASSERT_TRUE(IsValid(env, context.get()));
+
+  auto transformation2 = TransformationEquationInstruction(
+      570, SpvOpIAdd, {522, 113}, return_instruction);
+  ASSERT_TRUE(
+      transformation2.IsApplicable(context.get(), transformation_context));
+  transformation2.Apply(context.get(), &transformation_context);
+  ASSERT_TRUE(IsValid(env, context.get()));
+
+  std::string after_transformation = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %12 "main"
+               OpExecutionMode %12 OriginUpperLeft
+               OpSource ESSL 310
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %6 = OpTypeInt 32 1
+        %113 = OpConstant %6 24
+         %12 = OpFunction %2 None %3
+         %13 = OpLabel
+        %522 = OpISub %6 %113 %113
+        %570 = OpIAdd %6 %522 %113
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(570, {}), MakeDataDescriptor(113, {})));
+
+  ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
+}
+
 }  // namespace
 }  // namespace fuzz
 }  // namespace spvtools
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_function_call_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_function_call_test.cpp
index 9bd971e..d7305f8 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_function_call_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_function_call_test.cpp
@@ -134,24 +134,36 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
-  fact_manager.AddFactBlockIsDead(59);
-  fact_manager.AddFactBlockIsDead(11);
-  fact_manager.AddFactBlockIsDead(18);
-  fact_manager.AddFactBlockIsDead(25);
-  fact_manager.AddFactBlockIsDead(96);
-  fact_manager.AddFactBlockIsDead(205);
-  fact_manager.AddFactFunctionIsLivesafe(21);
-  fact_manager.AddFactFunctionIsLivesafe(200);
-  fact_manager.AddFactValueOfPointeeIsIrrelevant(71);
-  fact_manager.AddFactValueOfPointeeIsIrrelevant(72);
-  fact_manager.AddFactValueOfPointeeIsIrrelevant(19);
-  fact_manager.AddFactValueOfPointeeIsIrrelevant(20);
-  fact_manager.AddFactValueOfPointeeIsIrrelevant(23);
-  fact_manager.AddFactValueOfPointeeIsIrrelevant(44);
-  fact_manager.AddFactValueOfPointeeIsIrrelevant(46);
-  fact_manager.AddFactValueOfPointeeIsIrrelevant(51);
-  fact_manager.AddFactValueOfPointeeIsIrrelevant(52);
+  transformation_context.GetFactManager()->AddFactBlockIsDead(59);
+  transformation_context.GetFactManager()->AddFactBlockIsDead(11);
+  transformation_context.GetFactManager()->AddFactBlockIsDead(18);
+  transformation_context.GetFactManager()->AddFactBlockIsDead(25);
+  transformation_context.GetFactManager()->AddFactBlockIsDead(96);
+  transformation_context.GetFactManager()->AddFactBlockIsDead(205);
+  transformation_context.GetFactManager()->AddFactFunctionIsLivesafe(21);
+  transformation_context.GetFactManager()->AddFactFunctionIsLivesafe(200);
+  transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
+      71);
+  transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
+      72);
+  transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
+      19);
+  transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
+      20);
+  transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
+      23);
+  transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
+      44);
+  transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
+      46);
+  transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
+      51);
+  transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
+      52);
 
   // Livesafe functions with argument types: 21(7, 13), 200(7, 13)
   // Non-livesafe functions with argument types: 4(), 10(7), 17(7, 13), 24(7)
@@ -164,127 +176,133 @@
   ASSERT_FALSE(
       TransformationFunctionCall(100, 21, {71, 72, 71},
                                  MakeInstructionDescriptor(59, SpvOpBranch, 0))
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   // Too few arguments
   ASSERT_FALSE(TransformationFunctionCall(
                    100, 21, {71}, MakeInstructionDescriptor(59, SpvOpBranch, 0))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   // Arguments are the wrong way around (types do not match)
   ASSERT_FALSE(
       TransformationFunctionCall(100, 21, {72, 71},
                                  MakeInstructionDescriptor(59, SpvOpBranch, 0))
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   // 21 is not an appropriate argument
   ASSERT_FALSE(
       TransformationFunctionCall(100, 21, {21, 72},
                                  MakeInstructionDescriptor(59, SpvOpBranch, 0))
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   // 300 does not exist
   ASSERT_FALSE(
       TransformationFunctionCall(100, 21, {300, 72},
                                  MakeInstructionDescriptor(59, SpvOpBranch, 0))
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   // 71 is not a function
   ASSERT_FALSE(
       TransformationFunctionCall(100, 71, {71, 72},
                                  MakeInstructionDescriptor(59, SpvOpBranch, 0))
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   // 500 does not exist
   ASSERT_FALSE(
       TransformationFunctionCall(100, 500, {71, 72},
                                  MakeInstructionDescriptor(59, SpvOpBranch, 0))
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   // Id is not fresh
   ASSERT_FALSE(
       TransformationFunctionCall(21, 21, {71, 72},
                                  MakeInstructionDescriptor(59, SpvOpBranch, 0))
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   // Access chain as pointer parameter
   ASSERT_FALSE(
       TransformationFunctionCall(100, 21, {98, 72},
                                  MakeInstructionDescriptor(59, SpvOpBranch, 0))
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   // Copied object as pointer parameter
   ASSERT_FALSE(
       TransformationFunctionCall(100, 21, {99, 72},
                                  MakeInstructionDescriptor(59, SpvOpBranch, 0))
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   // Non-livesafe called from original live block
   ASSERT_FALSE(
       TransformationFunctionCall(
           100, 10, {71}, MakeInstructionDescriptor(99, SpvOpSelectionMerge, 0))
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   // Non-livesafe called from livesafe function
   ASSERT_FALSE(
       TransformationFunctionCall(
           100, 10, {19}, MakeInstructionDescriptor(38, SpvOpConvertFToS, 0))
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   // Livesafe function called with pointer to non-arbitrary local variable
   ASSERT_FALSE(
       TransformationFunctionCall(
           100, 21, {61, 72}, MakeInstructionDescriptor(38, SpvOpConvertFToS, 0))
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   // Direct recursion
   ASSERT_FALSE(TransformationFunctionCall(
                    100, 4, {}, MakeInstructionDescriptor(59, SpvOpBranch, 0))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   // Indirect recursion
   ASSERT_FALSE(TransformationFunctionCall(
                    100, 24, {9}, MakeInstructionDescriptor(96, SpvOpBranch, 0))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   // Parameter 23 is not available at the call site
   ASSERT_FALSE(
       TransformationFunctionCall(104, 10, {23},
                                  MakeInstructionDescriptor(205, SpvOpBranch, 0))
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   // Good transformations
   {
     // Livesafe called from dead block: fine
     TransformationFunctionCall transformation(
         100, 21, {71, 72}, MakeInstructionDescriptor(59, SpvOpBranch, 0));
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
     ASSERT_TRUE(IsValid(env, context.get()));
   }
   {
     // Livesafe called from original live block: fine
     TransformationFunctionCall transformation(
         101, 21, {71, 72}, MakeInstructionDescriptor(98, SpvOpAccessChain, 0));
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
     ASSERT_TRUE(IsValid(env, context.get()));
   }
   {
     // Livesafe called from livesafe function: fine
     TransformationFunctionCall transformation(
         102, 200, {19, 20}, MakeInstructionDescriptor(36, SpvOpLoad, 0));
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
     ASSERT_TRUE(IsValid(env, context.get()));
   }
   {
     // Dead called from dead block in injected function: fine
     TransformationFunctionCall transformation(
         103, 10, {23}, MakeInstructionDescriptor(45, SpvOpLoad, 0));
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
     ASSERT_TRUE(IsValid(env, context.get()));
   }
   {
     // Non-livesafe called from dead block in livesafe function: OK
     TransformationFunctionCall transformation(
         104, 10, {201}, MakeInstructionDescriptor(205, SpvOpBranch, 0));
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
     ASSERT_TRUE(IsValid(env, context.get()));
   }
   {
     // Livesafe called from dead block with non-arbitrary parameter
     TransformationFunctionCall transformation(
         105, 21, {62, 65}, MakeInstructionDescriptor(59, SpvOpBranch, 0));
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
     ASSERT_TRUE(IsValid(env, context.get()));
   }
 
@@ -429,13 +447,16 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
-  fact_manager.AddFactBlockIsDead(11);
+  transformation_context.GetFactManager()->AddFactBlockIsDead(11);
 
   // 4 is an entry point, so it is not legal for it to be the target of a call.
   ASSERT_FALSE(TransformationFunctionCall(
                    100, 4, {}, MakeInstructionDescriptor(11, SpvOpReturn, 0))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 }
 
 }  // namespace
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_load_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_load_test.cpp
index 1f728ff..18ca195 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_load_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_load_test.cpp
@@ -85,14 +85,22 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
-  fact_manager.AddFactValueOfPointeeIsIrrelevant(27);
-  fact_manager.AddFactValueOfPointeeIsIrrelevant(11);
-  fact_manager.AddFactValueOfPointeeIsIrrelevant(46);
-  fact_manager.AddFactValueOfPointeeIsIrrelevant(16);
-  fact_manager.AddFactValueOfPointeeIsIrrelevant(52);
+  transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
+      27);
+  transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
+      11);
+  transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
+      46);
+  transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
+      16);
+  transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
+      52);
 
-  fact_manager.AddFactBlockIsDead(36);
+  transformation_context.GetFactManager()->AddFactBlockIsDead(36);
 
   // Variables with pointee types:
   //  52 - ptr_to(7)
@@ -125,86 +133,90 @@
   // Bad: id is not fresh
   ASSERT_FALSE(TransformationLoad(
                    33, 33, MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   // Bad: attempt to load from 11 from outside its function
   ASSERT_FALSE(TransformationLoad(
                    100, 11, MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: pointer is not available
   ASSERT_FALSE(TransformationLoad(
                    100, 33, MakeInstructionDescriptor(45, SpvOpCopyObject, 0))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: attempt to insert before OpVariable
   ASSERT_FALSE(TransformationLoad(
                    100, 27, MakeInstructionDescriptor(27, SpvOpVariable, 0))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: pointer id does not exist
   ASSERT_FALSE(
       TransformationLoad(100, 1000,
                          MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   // Bad: pointer id exists but does not have a type
   ASSERT_FALSE(TransformationLoad(
                    100, 5, MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: pointer id exists and has a type, but is not a pointer
   ASSERT_FALSE(TransformationLoad(
                    100, 24, MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: attempt to load from null pointer
   ASSERT_FALSE(TransformationLoad(
                    100, 60, MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: attempt to load from undefined pointer
   ASSERT_FALSE(TransformationLoad(
                    100, 61, MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   // Bad: %40 is not available at the program point
   ASSERT_FALSE(
       TransformationLoad(100, 40, MakeInstructionDescriptor(37, SpvOpReturn, 0))
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   // Bad: The described instruction does not exist
   ASSERT_FALSE(TransformationLoad(
                    100, 33, MakeInstructionDescriptor(1000, SpvOpReturn, 0))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   {
     TransformationLoad transformation(
         100, 33, MakeInstructionDescriptor(38, SpvOpAccessChain, 0));
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
     ASSERT_TRUE(IsValid(env, context.get()));
   }
 
   {
     TransformationLoad transformation(
         101, 46, MakeInstructionDescriptor(16, SpvOpReturnValue, 0));
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
     ASSERT_TRUE(IsValid(env, context.get()));
   }
 
   {
     TransformationLoad transformation(
         102, 16, MakeInstructionDescriptor(16, SpvOpReturnValue, 0));
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
     ASSERT_TRUE(IsValid(env, context.get()));
   }
 
   {
     TransformationLoad transformation(
         103, 40, MakeInstructionDescriptor(43, SpvOpAccessChain, 0));
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
     ASSERT_TRUE(IsValid(env, context.get()));
   }
 
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_merge_blocks_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_merge_blocks_test.cpp
index e2b4aa6..4500445 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_merge_blocks_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_merge_blocks_test.cpp
@@ -45,11 +45,14 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
-  ASSERT_FALSE(
-      TransformationMergeBlocks(3).IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(
-      TransformationMergeBlocks(7).IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(TransformationMergeBlocks(3).IsApplicable(
+      context.get(), transformation_context));
+  ASSERT_FALSE(TransformationMergeBlocks(7).IsApplicable(
+      context.get(), transformation_context));
 }
 
 TEST(TransformationMergeBlocksTest, DoNotMergeFirstBlockHasMultipleSuccessors) {
@@ -84,9 +87,12 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
-  ASSERT_FALSE(
-      TransformationMergeBlocks(6).IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(TransformationMergeBlocks(6).IsApplicable(
+      context.get(), transformation_context));
 }
 
 TEST(TransformationMergeBlocksTest,
@@ -122,9 +128,12 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
-  ASSERT_FALSE(
-      TransformationMergeBlocks(10).IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(TransformationMergeBlocks(10).IsApplicable(
+      context.get(), transformation_context));
 }
 
 TEST(TransformationMergeBlocksTest, MergeWhenSecondBlockIsSelectionMerge) {
@@ -161,10 +170,14 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationMergeBlocks transformation(10);
-  ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-  transformation.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
+  transformation.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_transformation = R"(
@@ -231,10 +244,14 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationMergeBlocks transformation(10);
-  ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-  transformation.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
+  transformation.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_transformation = R"(
@@ -306,10 +323,14 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationMergeBlocks transformation(11);
-  ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-  transformation.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
+  transformation.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_transformation = R"(
@@ -377,10 +398,14 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationMergeBlocks transformation(6);
-  ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-  transformation.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
+  transformation.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_transformation = R"(
@@ -454,12 +479,16 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   for (auto& transformation :
        {TransformationMergeBlocks(100), TransformationMergeBlocks(101),
         TransformationMergeBlocks(102), TransformationMergeBlocks(103)}) {
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
     ASSERT_TRUE(IsValid(env, context.get()));
   }
 
@@ -542,11 +571,15 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   for (auto& transformation :
        {TransformationMergeBlocks(101), TransformationMergeBlocks(100)}) {
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
     ASSERT_TRUE(IsValid(env, context.get()));
   }
 
@@ -629,10 +662,14 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationMergeBlocks transformation(101);
-  ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-  transformation.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
+  transformation.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_transformation = R"(
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_move_block_down_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_move_block_down_test.cpp
index 02761a2..662e88c 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_move_block_down_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_move_block_down_test.cpp
@@ -53,9 +53,13 @@
   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   auto transformation = TransformationMoveBlockDown(11);
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationMoveBlockDownTest, NoMovePossible2) {
@@ -90,9 +94,13 @@
   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   auto transformation = TransformationMoveBlockDown(5);
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationMoveBlockDownTest, NoMovePossible3) {
@@ -129,9 +137,13 @@
   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   auto transformation = TransformationMoveBlockDown(100);
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationMoveBlockDownTest, NoMovePossible4) {
@@ -172,9 +184,13 @@
   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   auto transformation = TransformationMoveBlockDown(12);
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationMoveBlockDownTest, ManyMovesPossible) {
@@ -277,6 +293,9 @@
       BuildModule(env, consumer, before_transformation, kFuzzAssembleOption);
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // The block ids are: 5 14 20 23 21 25 29 32 30 15
   // We make a transformation to move each of them down, plus a transformation
@@ -306,110 +325,130 @@
   // 15 dominates nothing
 
   // Current ordering: 5 14 20 23 21 25 29 32 30 15
-  ASSERT_FALSE(move_down_5.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(move_down_14.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_20.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_23.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_21.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(move_down_25.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_29.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_32.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_30.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(move_down_15.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(move_down_5.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      move_down_14.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_20.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_23.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_21.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      move_down_25.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_29.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_32.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_30.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      move_down_15.IsApplicable(context.get(), transformation_context));
 
   // Let's bubble 20 all the way down.
 
-  move_down_20.Apply(context.get(), &fact_manager);
+  move_down_20.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Current ordering: 5 14 23 20 21 25 29 32 30 15
-  ASSERT_FALSE(move_down_5.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(move_down_14.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_23.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_20.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_21.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(move_down_25.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_29.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_32.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_30.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(move_down_15.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(move_down_5.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      move_down_14.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_23.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_20.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_21.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      move_down_25.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_29.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_32.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_30.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      move_down_15.IsApplicable(context.get(), transformation_context));
 
-  move_down_20.Apply(context.get(), &fact_manager);
+  move_down_20.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Current ordering: 5 14 23 21 20 25 29 32 30 15
-  ASSERT_FALSE(move_down_5.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(move_down_14.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_23.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_21.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_20.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(move_down_25.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_29.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_32.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_30.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(move_down_15.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(move_down_5.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      move_down_14.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_23.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_21.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_20.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      move_down_25.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_29.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_32.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_30.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      move_down_15.IsApplicable(context.get(), transformation_context));
 
-  move_down_20.Apply(context.get(), &fact_manager);
+  move_down_20.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Current ordering: 5 14 23 21 25 20 29 32 30 15
-  ASSERT_FALSE(move_down_5.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(move_down_14.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_23.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_21.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_25.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_20.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_29.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_32.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_30.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(move_down_15.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(move_down_5.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      move_down_14.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_23.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_21.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_25.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_20.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_29.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_32.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_30.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      move_down_15.IsApplicable(context.get(), transformation_context));
 
-  move_down_20.Apply(context.get(), &fact_manager);
+  move_down_20.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Current ordering: 5 14 23 21 25 29 20 32 30 15
-  ASSERT_FALSE(move_down_5.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(move_down_14.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_23.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_21.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(move_down_25.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_29.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_20.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_32.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_30.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(move_down_15.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(move_down_5.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      move_down_14.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_23.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_21.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      move_down_25.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_29.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_20.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_32.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_30.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      move_down_15.IsApplicable(context.get(), transformation_context));
 
-  move_down_20.Apply(context.get(), &fact_manager);
+  move_down_20.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Current ordering: 5 14 23 21 25 29 32 20 30 15
-  ASSERT_FALSE(move_down_5.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(move_down_14.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_23.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_21.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(move_down_25.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_29.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_32.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_20.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_30.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(move_down_15.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(move_down_5.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      move_down_14.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_23.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_21.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      move_down_25.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_29.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_32.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_20.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_30.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      move_down_15.IsApplicable(context.get(), transformation_context));
 
-  move_down_20.Apply(context.get(), &fact_manager);
+  move_down_20.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Current ordering: 5 14 23 21 25 29 32 30 20 15
-  ASSERT_FALSE(move_down_5.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(move_down_14.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_23.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_21.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(move_down_25.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_29.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_32.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_30.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_20.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(move_down_15.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(move_down_5.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      move_down_14.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_23.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_21.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      move_down_25.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_29.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_32.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_30.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_20.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      move_down_15.IsApplicable(context.get(), transformation_context));
 
-  move_down_20.Apply(context.get(), &fact_manager);
+  move_down_20.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_bubbling_20_down = R"(
@@ -485,63 +524,72 @@
   ASSERT_TRUE(IsEqual(env, after_bubbling_20_down, context.get()));
 
   // Current ordering: 5 14 23 21 25 29 32 30 15 20
-  ASSERT_FALSE(move_down_5.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(move_down_14.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_23.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_21.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(move_down_25.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_29.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_32.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_30.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_15.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(move_down_20.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(move_down_5.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      move_down_14.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_23.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_21.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      move_down_25.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_29.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_32.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_30.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_15.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      move_down_20.IsApplicable(context.get(), transformation_context));
 
-  move_down_23.Apply(context.get(), &fact_manager);
+  move_down_23.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Current ordering: 5 14 21 23 25 29 32 30 15 20
-  ASSERT_FALSE(move_down_5.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(move_down_14.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_21.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_23.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(move_down_25.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_29.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_32.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_30.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_15.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(move_down_20.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(move_down_5.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      move_down_14.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_21.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_23.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      move_down_25.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_29.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_32.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_30.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_15.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      move_down_20.IsApplicable(context.get(), transformation_context));
 
-  move_down_23.Apply(context.get(), &fact_manager);
+  move_down_23.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Current ordering: 5 14 21 25 23 29 32 30 15 20
-  ASSERT_FALSE(move_down_5.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(move_down_14.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_21.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_25.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_23.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_29.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_32.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_30.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_15.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(move_down_20.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(move_down_5.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      move_down_14.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_21.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_25.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_23.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_29.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_32.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_30.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_15.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      move_down_20.IsApplicable(context.get(), transformation_context));
 
-  move_down_21.Apply(context.get(), &fact_manager);
+  move_down_21.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Current ordering: 5 14 25 21 23 29 32 30 15 20
-  ASSERT_FALSE(move_down_5.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_14.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_21.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_25.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_23.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_29.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_32.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_30.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_15.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(move_down_20.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(move_down_5.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_14.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_21.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_25.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_23.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_29.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_32.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_30.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_15.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      move_down_20.IsApplicable(context.get(), transformation_context));
 
-  move_down_14.Apply(context.get(), &fact_manager);
+  move_down_14.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_more_shuffling = R"(
@@ -617,16 +665,18 @@
   ASSERT_TRUE(IsEqual(env, after_more_shuffling, context.get()));
 
   // Final ordering: 5 25 14 21 23 29 32 30 15 20
-  ASSERT_FALSE(move_down_5.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_25.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(move_down_14.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_21.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_23.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_29.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_32.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_30.IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(move_down_15.IsApplicable(context.get(), fact_manager));
-  ASSERT_FALSE(move_down_20.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(move_down_5.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_25.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      move_down_14.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_21.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_23.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_29.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_32.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_30.IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(move_down_15.IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      move_down_20.IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationMoveBlockDownTest, DoNotMoveUnreachable) {
@@ -660,9 +710,13 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   auto transformation = TransformationMoveBlockDown(6);
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 }
 
 }  // namespace
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_outline_function_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_outline_function_test.cpp
index 40aaebc..01bba31 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_outline_function_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_outline_function_test.cpp
@@ -44,12 +44,16 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationOutlineFunction transformation(5, 5, /* not relevant */ 200,
                                                100, 101, 102, 103,
                                                /* not relevant */ 201, {}, {});
-  ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-  transformation.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
+  transformation.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_transformation = R"(
@@ -105,11 +109,15 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationOutlineFunction transformation(5, 5, /* not relevant */ 200,
                                                100, 101, 102, 103,
                                                /* not relevant */ 201, {}, {});
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationOutlineFunctionTest, OutlineInterestingControlFlowNoState) {
@@ -158,12 +166,16 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationOutlineFunction transformation(6, 13, /* not relevant */
                                                200, 100, 101, 102, 103,
                                                /* not relevant */ 201, {}, {});
-  ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-  transformation.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
+  transformation.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_transformation = R"(
@@ -243,12 +255,16 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationOutlineFunction transformation(6, 6, /* not relevant */ 200,
                                                100, 101, 102, 103,
                                                /* not relevant */ 201, {}, {});
-  ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-  transformation.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
+  transformation.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_transformation = R"(
@@ -317,11 +333,15 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationOutlineFunction transformation(6, 6, 99, 100, 101, 102, 103,
                                                105, {}, {{9, 104}});
-  ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-  transformation.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
+  transformation.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_transformation = R"(
@@ -412,12 +432,16 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationOutlineFunction transformation(
       6, 80, 100, 101, 102, 103, 104, 105, {},
       {{15, 106}, {9, 107}, {7, 108}, {8, 109}});
-  ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-  transformation.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
+  transformation.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_transformation = R"(
@@ -508,11 +532,15 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationOutlineFunction transformation(6, 6, 100, 101, 102, 103, 104,
                                                105, {{7, 106}}, {});
-  ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-  transformation.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
+  transformation.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_transformation = R"(
@@ -582,11 +610,15 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationOutlineFunction transformation(6, 6, 100, 101, 102, 103, 104,
                                                105, {{13, 106}}, {});
-  ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-  transformation.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
+  transformation.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_transformation = R"(
@@ -666,11 +698,15 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationOutlineFunction transformation(11, 11, 100, 101, 102, 103, 104,
                                                105, {{9, 106}}, {{14, 107}});
-  ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-  transformation.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
+  transformation.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_transformation = R"(
@@ -752,10 +788,14 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationOutlineFunction transformation(6, 8, 100, 101, 102, 103, 104,
                                                105, {}, {});
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationOutlineFunctionTest, DoNotOutlineIfRegionInvolvesReturn) {
@@ -798,11 +838,15 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationOutlineFunction transformation(6, 11, /* not relevant */ 200,
                                                100, 101, 102, 103,
                                                /* not relevant */ 201, {}, {});
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationOutlineFunctionTest, DoNotOutlineIfRegionInvolvesKill) {
@@ -845,11 +889,15 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationOutlineFunction transformation(6, 11, /* not relevant */ 200,
                                                100, 101, 102, 103,
                                                /* not relevant */ 201, {}, {});
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationOutlineFunctionTest,
@@ -893,11 +941,15 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationOutlineFunction transformation(6, 11, /* not relevant */ 200,
                                                100, 101, 102, 103,
                                                /* not relevant */ 201, {}, {});
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationOutlineFunctionTest,
@@ -933,10 +985,14 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationOutlineFunction transformation(6, 8, 100, 101, 102, 103, 104,
                                                105, {}, {});
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationOutlineFunctionTest, DoNotOutlineIfLoopHeadIsOutsideRegion) {
@@ -973,10 +1029,14 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationOutlineFunction transformation(7, 8, 100, 101, 102, 103, 104,
                                                105, {}, {});
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationOutlineFunctionTest,
@@ -1012,10 +1072,14 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationOutlineFunction transformation(6, 7, 100, 101, 102, 103, 104,
                                                105, {}, {});
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationOutlineFunctionTest,
@@ -1053,10 +1117,14 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationOutlineFunction transformation(6, 7, 100, 101, 102, 103, 104,
                                                105, {}, {});
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationOutlineFunctionTest,
@@ -1094,10 +1162,14 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationOutlineFunction transformation(8, 11, 100, 101, 102, 103, 104,
                                                105, {}, {});
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationOutlineFunctionTest, OutlineRegionEndingWithReturnVoid) {
@@ -1132,6 +1204,9 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationOutlineFunction transformation(
       /*entry_block*/ 54,
@@ -1145,8 +1220,9 @@
       /*input_id_to_fresh_id*/ {{22, 206}},
       /*output_id_to_fresh_id*/ {});
 
-  ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-  transformation.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
+  transformation.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_transformation = R"(
@@ -1219,6 +1295,9 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationOutlineFunction transformation(
       /*entry_block*/ 9,
@@ -1232,8 +1311,9 @@
       /*input_id_to_fresh_id*/ {{31, 206}},
       /*output_id_to_fresh_id*/ {{32, 207}});
 
-  ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-  transformation.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
+  transformation.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_transformation = R"(
@@ -1310,6 +1390,9 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationOutlineFunction transformation(
       /*entry_block*/ 54,
@@ -1323,8 +1406,9 @@
       /*input_id_to_fresh_id*/ {{}},
       /*output_id_to_fresh_id*/ {{6, 206}});
 
-  ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-  transformation.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
+  transformation.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_transformation = R"(
@@ -1396,6 +1480,9 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationOutlineFunction transformation(
       /*entry_block*/ 54,
@@ -1409,8 +1496,9 @@
       /*input_id_to_fresh_id*/ {},
       /*output_id_to_fresh_id*/ {});
 
-  ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-  transformation.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
+  transformation.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_transformation = R"(
@@ -1478,6 +1566,9 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationOutlineFunction transformation(
       /*entry_block*/ 21,
@@ -1491,7 +1582,8 @@
       /*input_id_to_fresh_id*/ {{22, 207}},
       /*output_id_to_fresh_id*/ {{23, 208}});
 
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationOutlineFunctionTest,
@@ -1531,6 +1623,9 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationOutlineFunction transformation(
       /*entry_block*/ 21,
@@ -1544,7 +1639,8 @@
       /*input_id_to_fresh_id*/ {},
       /*output_id_to_fresh_id*/ {});
 
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationOutlineFunctionTest,
@@ -1584,6 +1680,9 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationOutlineFunction transformation(
       /*entry_block*/ 5,
@@ -1597,7 +1696,8 @@
       /*input_id_to_fresh_id*/ {},
       /*output_id_to_fresh_id*/ {});
 
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationOutlineFunctionTest, DoNotOutlineRegionThatUsesAccessChain) {
@@ -1640,6 +1740,9 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationOutlineFunction transformation(
       /*entry_block*/ 13,
@@ -1653,7 +1756,8 @@
       /*input_id_to_fresh_id*/ {{12, 207}},
       /*output_id_to_fresh_id*/ {});
 
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationOutlineFunctionTest,
@@ -1698,6 +1802,9 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationOutlineFunction transformation(
       /*entry_block*/ 13,
@@ -1711,7 +1818,8 @@
       /*input_id_to_fresh_id*/ {{20, 207}},
       /*output_id_to_fresh_id*/ {});
 
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationOutlineFunctionTest,
@@ -1761,6 +1869,9 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationOutlineFunction transformation(
       /*entry_block*/ 11,
@@ -1774,8 +1885,9 @@
       /*input_id_to_fresh_id*/ {{9, 207}},
       /*output_id_to_fresh_id*/ {{14, 208}});
 
-  ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-  transformation.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
+  transformation.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_transformation = R"(
@@ -1913,9 +2025,15 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
-  fact_manager.AddFactFunctionIsLivesafe(30);
-  fact_manager.AddFactValueOfPointeeIsIrrelevant(200);
-  fact_manager.AddFactValueOfPointeeIsIrrelevant(201);
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
+
+  transformation_context.GetFactManager()->AddFactFunctionIsLivesafe(30);
+  transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
+      200);
+  transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
+      201);
 
   TransformationOutlineFunction transformation(
       /*entry_block*/ 198,
@@ -1929,24 +2047,31 @@
       /*input_id_to_fresh_id*/ {{100, 407}, {200, 408}, {201, 409}},
       /*output_id_to_fresh_id*/ {});
 
-  ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-  transformation.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
+  transformation.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // The original function should still be livesafe.
-  ASSERT_TRUE(fact_manager.FunctionIsLivesafe(30));
+  ASSERT_TRUE(transformation_context.GetFactManager()->FunctionIsLivesafe(30));
   // The outlined function should be livesafe.
-  ASSERT_TRUE(fact_manager.FunctionIsLivesafe(402));
+  ASSERT_TRUE(transformation_context.GetFactManager()->FunctionIsLivesafe(402));
   // The variable and parameter that were originally irrelevant should still be.
-  ASSERT_TRUE(fact_manager.PointeeValueIsIrrelevant(200));
-  ASSERT_TRUE(fact_manager.PointeeValueIsIrrelevant(201));
+  ASSERT_TRUE(
+      transformation_context.GetFactManager()->PointeeValueIsIrrelevant(200));
+  ASSERT_TRUE(
+      transformation_context.GetFactManager()->PointeeValueIsIrrelevant(201));
   // The loop limiter should still be non-irrelevant.
-  ASSERT_FALSE(fact_manager.PointeeValueIsIrrelevant(100));
+  ASSERT_FALSE(
+      transformation_context.GetFactManager()->PointeeValueIsIrrelevant(100));
   // The parameters for the original irrelevant variables should be irrelevant.
-  ASSERT_TRUE(fact_manager.PointeeValueIsIrrelevant(408));
-  ASSERT_TRUE(fact_manager.PointeeValueIsIrrelevant(409));
+  ASSERT_TRUE(
+      transformation_context.GetFactManager()->PointeeValueIsIrrelevant(408));
+  ASSERT_TRUE(
+      transformation_context.GetFactManager()->PointeeValueIsIrrelevant(409));
   // The parameter for the loop limiter should not be irrelevant.
-  ASSERT_FALSE(fact_manager.PointeeValueIsIrrelevant(407));
+  ASSERT_FALSE(
+      transformation_context.GetFactManager()->PointeeValueIsIrrelevant(407));
 
   std::string after_transformation = R"(
                OpCapability Shader
@@ -2129,8 +2254,12 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
+
   for (uint32_t block_id : {16u, 23u, 24u, 26u, 27u, 34u, 35u, 50u}) {
-    fact_manager.AddFactBlockIsDead(block_id);
+    transformation_context.GetFactManager()->AddFactBlockIsDead(block_id);
   }
 
   TransformationOutlineFunction transformation(
@@ -2145,12 +2274,13 @@
       /*input_id_to_fresh_id*/ {{9, 206}, {12, 207}, {21, 208}},
       /*output_id_to_fresh_id*/ {});
 
-  ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-  transformation.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
+  transformation.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
   // All the original blocks, plus the new function entry block, should be dead.
   for (uint32_t block_id : {16u, 23u, 24u, 26u, 27u, 34u, 35u, 50u, 203u}) {
-    ASSERT_TRUE(fact_manager.BlockIsDead(block_id));
+    ASSERT_TRUE(transformation_context.GetFactManager()->BlockIsDead(block_id));
   }
 }
 
@@ -2208,8 +2338,12 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
+
   for (uint32_t block_id : {32u, 34u, 35u}) {
-    fact_manager.AddFactBlockIsDead(block_id);
+    transformation_context.GetFactManager()->AddFactBlockIsDead(block_id);
   }
 
   TransformationOutlineFunction transformation(
@@ -2224,15 +2358,17 @@
       /*input_id_to_fresh_id*/ {{11, 206}},
       /*output_id_to_fresh_id*/ {});
 
-  ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-  transformation.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
+  transformation.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
   // The blocks that were originally dead, but not others, should be dead.
   for (uint32_t block_id : {32u, 34u, 35u}) {
-    ASSERT_TRUE(fact_manager.BlockIsDead(block_id));
+    ASSERT_TRUE(transformation_context.GetFactManager()->BlockIsDead(block_id));
   }
   for (uint32_t block_id : {5u, 30u, 31u, 33u, 36u, 37u, 203u}) {
-    ASSERT_FALSE(fact_manager.BlockIsDead(block_id));
+    ASSERT_FALSE(
+        transformation_context.GetFactManager()->BlockIsDead(block_id));
   }
 }
 
@@ -2287,8 +2423,13 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
-  fact_manager.AddFactValueOfPointeeIsIrrelevant(9);
-  fact_manager.AddFactValueOfPointeeIsIrrelevant(14);
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
+
+  transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(9);
+  transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
+      14);
 
   TransformationOutlineFunction transformation(
       /*entry_block*/ 50,
@@ -2302,19 +2443,142 @@
       /*input_id_to_fresh_id*/ {{9, 206}, {10, 207}, {14, 208}, {20, 209}},
       /*output_id_to_fresh_id*/ {});
 
-  ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-  transformation.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
+  transformation.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
   // The variables that were originally irrelevant, plus input parameters
   // corresponding to them, should be irrelevant.  The rest should not be.
   for (uint32_t variable_id : {9u, 14u, 206u, 208u}) {
-    ASSERT_TRUE(fact_manager.PointeeValueIsIrrelevant(variable_id));
+    ASSERT_TRUE(
+        transformation_context.GetFactManager()->PointeeValueIsIrrelevant(
+            variable_id));
   }
   for (uint32_t variable_id : {10u, 20u, 207u, 209u}) {
-    ASSERT_FALSE(fact_manager.BlockIsDead(variable_id));
+    ASSERT_FALSE(
+        transformation_context.GetFactManager()->BlockIsDead(variable_id));
   }
 }
 
+TEST(TransformationOutlineFunctionTest,
+     DoNotOutlineCodeThatProducesUsedPointer) {
+  // This checks that we cannot outline a region of code if it produces a
+  // pointer result id that gets used outside the region.  This avoids creating
+  // a struct with a pointer member.
+  std::string shader = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %6 "main"
+               OpExecutionMode %6 OriginUpperLeft
+               OpSource ESSL 310
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+         %21 = OpTypeBool
+        %100 = OpTypeInt 32 0
+         %99 = OpConstant %100 0
+        %101 = OpTypeVector %100 2
+        %102 = OpTypePointer Function %100
+        %103 = OpTypePointer Function %101
+          %6 = OpFunction %2 None %3
+          %7 = OpLabel
+        %104 = OpVariable %103 Function
+               OpBranch %80
+         %80 = OpLabel
+        %105 = OpAccessChain %102 %104 %99
+               OpBranch %106
+        %106 = OpLabel
+               OpStore %105 %99
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  const auto env = SPV_ENV_UNIVERSAL_1_5;
+  const auto consumer = nullptr;
+  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+  ASSERT_TRUE(IsValid(env, context.get()));
+
+  FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
+
+  TransformationOutlineFunction transformation(
+      /*entry_block*/ 80,
+      /*exit_block*/ 80,
+      /*new_function_struct_return_type_id*/ 300,
+      /*new_function_type_id*/ 301,
+      /*new_function_id*/ 302,
+      /*new_function_region_entry_block*/ 304,
+      /*new_caller_result_id*/ 305,
+      /*new_callee_result_id*/ 306,
+      /*input_id_to_fresh_id*/ {{104, 307}},
+      /*output_id_to_fresh_id*/ {{105, 308}});
+
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
+}
+
+TEST(TransformationOutlineFunctionTest,
+     ExitBlockHeadsLoopButContinueConstructIsInRegion) {
+  // This checks that it is not possible outline a region that ends in a loop
+  // head if the continue target for the loop is inside the region.
+  std::string shader = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main"
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 310
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+         %15 = OpTypeInt 32 1
+         %35 = OpTypeBool
+         %39 = OpConstant %15 1
+         %40 = OpConstantTrue %35
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+               OpBranch %22
+         %22 = OpLabel
+               OpBranch %23
+         %23 = OpLabel
+         %24 = OpPhi %15 %39 %22 %39 %25
+               OpLoopMerge %26 %25 None
+               OpBranchConditional %40 %25 %26
+         %25 = OpLabel
+               OpBranch %23
+         %26 = OpLabel
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  const auto env = SPV_ENV_UNIVERSAL_1_5;
+  const auto consumer = nullptr;
+  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+  ASSERT_TRUE(IsValid(env, context.get()));
+
+  FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
+
+  TransformationOutlineFunction transformation(
+      /*entry_block*/ 22,
+      /*exit_block*/ 23,
+      /*new_function_struct_return_type_id*/ 200,
+      /*new_function_type_id*/ 201,
+      /*new_function_id*/ 202,
+      /*new_function_region_entry_block*/ 203,
+      /*new_caller_result_id*/ 204,
+      /*new_callee_result_id*/ 205,
+      /*input_id_to_fresh_id*/ {},
+      /*output_id_to_fresh_id*/ {});
+
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
+  transformation.Apply(context.get(), &transformation_context);
+}
+
 TEST(TransformationOutlineFunctionTest, Miscellaneous1) {
   // This tests outlining of some non-trivial code.
 
@@ -2423,6 +2687,9 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationOutlineFunction transformation(
       /*entry_block*/ 150,
@@ -2436,8 +2703,9 @@
       /*input_id_to_fresh_id*/ {{102, 300}, {103, 301}, {40, 302}},
       /*output_id_to_fresh_id*/ {{106, 400}, {107, 401}});
 
-  ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-  transformation.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
+  transformation.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_transformation = R"(
@@ -2588,6 +2856,9 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationOutlineFunction transformation(
       /*entry_block*/ 38,
@@ -2601,7 +2872,8 @@
       /*input_id_to_fresh_id*/ {},
       /*output_id_to_fresh_id*/ {});
 
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationOutlineFunctionTest, Miscellaneous3) {
@@ -2643,6 +2915,9 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationOutlineFunction transformation(
       /*entry_block*/ 80,
@@ -2656,8 +2931,9 @@
       /*input_id_to_fresh_id*/ {},
       /*output_id_to_fresh_id*/ {});
 
-  ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-  transformation.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
+  transformation.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_transformation = R"(
@@ -2732,6 +3008,9 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationOutlineFunction transformation(
       /*entry_block*/ 80,
@@ -2745,8 +3024,9 @@
       /*input_id_to_fresh_id*/ {{104, 307}},
       /*output_id_to_fresh_id*/ {});
 
-  ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-  transformation.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
+  transformation.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_transformation = R"(
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_permute_function_parameters_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_permute_function_parameters_test.cpp
index 1af4699..a4a7c00 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_permute_function_parameters_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_permute_function_parameters_test.cpp
@@ -200,52 +200,57 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // Can't permute main function
   ASSERT_FALSE(TransformationPermuteFunctionParameters(4, 0, {}).IsApplicable(
-      context.get(), fact_manager));
+      context.get(), transformation_context));
 
   // Can't permute invalid instruction
   ASSERT_FALSE(TransformationPermuteFunctionParameters(101, 0, {})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Permutation has too many values
   ASSERT_FALSE(TransformationPermuteFunctionParameters(22, 0, {2, 1, 0, 3})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Permutation has too few values
   ASSERT_FALSE(TransformationPermuteFunctionParameters(22, 0, {0, 1})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Permutation has invalid values
   ASSERT_FALSE(TransformationPermuteFunctionParameters(22, 0, {3, 1, 0})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Type id is not an OpTypeFunction instruction
   ASSERT_FALSE(TransformationPermuteFunctionParameters(22, 42, {2, 1, 0})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Type id has incorrect number of operands
   ASSERT_FALSE(TransformationPermuteFunctionParameters(22, 9, {2, 1, 0})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // OpTypeFunction has operands out of order
   ASSERT_FALSE(TransformationPermuteFunctionParameters(22, 18, {2, 1, 0})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Successful transformations
   {
     // Function has two operands of the same type:
     // initial OpTypeFunction should be enough
     TransformationPermuteFunctionParameters transformation(12, 9, {1, 0});
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
     ASSERT_TRUE(IsValid(env, context.get()));
   }
   {
     TransformationPermuteFunctionParameters transformation(28, 105, {1, 0});
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
     ASSERT_TRUE(IsValid(env, context.get()));
   }
 
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_replace_boolean_constant_with_constant_binary_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_replace_boolean_constant_with_constant_binary_test.cpp
index 527a7b7..b320308 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_replace_boolean_constant_with_constant_binary_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_replace_boolean_constant_with_constant_binary_test.cpp
@@ -163,6 +163,9 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   std::vector<protobufs::IdUseDescriptor> uses_of_true = {
       MakeIdUseDescriptor(41, MakeInstructionDescriptor(44, SpvOpStore, 12), 1),
@@ -197,10 +200,10 @@
 #define CHECK_OPERATOR(USE_DESCRIPTOR, LHS_ID, RHS_ID, OPCODE, FRESH_ID) \
   ASSERT_TRUE(TransformationReplaceBooleanConstantWithConstantBinary(    \
                   USE_DESCRIPTOR, LHS_ID, RHS_ID, OPCODE, FRESH_ID)      \
-                  .IsApplicable(context.get(), fact_manager));           \
+                  .IsApplicable(context.get(), transformation_context)); \
   ASSERT_FALSE(TransformationReplaceBooleanConstantWithConstantBinary(   \
                    USE_DESCRIPTOR, RHS_ID, LHS_ID, OPCODE, FRESH_ID)     \
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
 #define CHECK_TRANSFORMATION_APPLICABILITY(GT_OPCODES, LT_OPCODES, SMALL_ID, \
                                            LARGE_ID)                         \
@@ -252,27 +255,27 @@
   // Target id is not fresh
   ASSERT_FALSE(TransformationReplaceBooleanConstantWithConstantBinary(
                    uses_of_true[0], 15, 17, SpvOpFOrdLessThan, 15)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // LHS id does not exist
   ASSERT_FALSE(TransformationReplaceBooleanConstantWithConstantBinary(
                    uses_of_true[0], 300, 17, SpvOpFOrdLessThan, 200)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // RHS id does not exist
   ASSERT_FALSE(TransformationReplaceBooleanConstantWithConstantBinary(
                    uses_of_true[0], 15, 300, SpvOpFOrdLessThan, 200)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // LHS and RHS ids do not match type
   ASSERT_FALSE(TransformationReplaceBooleanConstantWithConstantBinary(
                    uses_of_true[0], 11, 17, SpvOpFOrdLessThan, 200)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Opcode not appropriate
   ASSERT_FALSE(TransformationReplaceBooleanConstantWithConstantBinary(
                    uses_of_true[0], 15, 17, SpvOpFDiv, 200)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   auto replace_true_with_double_comparison =
       TransformationReplaceBooleanConstantWithConstantBinary(
@@ -287,21 +290,25 @@
       TransformationReplaceBooleanConstantWithConstantBinary(
           uses_of_false[1], 33, 31, SpvOpSLessThan, 103);
 
-  ASSERT_TRUE(replace_true_with_double_comparison.IsApplicable(context.get(),
-                                                               fact_manager));
-  replace_true_with_double_comparison.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(replace_true_with_double_comparison.IsApplicable(
+      context.get(), transformation_context));
+  replace_true_with_double_comparison.Apply(context.get(),
+                                            &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
-  ASSERT_TRUE(replace_true_with_uint32_comparison.IsApplicable(context.get(),
-                                                               fact_manager));
-  replace_true_with_uint32_comparison.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(replace_true_with_uint32_comparison.IsApplicable(
+      context.get(), transformation_context));
+  replace_true_with_uint32_comparison.Apply(context.get(),
+                                            &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
-  ASSERT_TRUE(replace_false_with_float_comparison.IsApplicable(context.get(),
-                                                               fact_manager));
-  replace_false_with_float_comparison.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(replace_false_with_float_comparison.IsApplicable(
+      context.get(), transformation_context));
+  replace_false_with_float_comparison.Apply(context.get(),
+                                            &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
-  ASSERT_TRUE(replace_false_with_sint64_comparison.IsApplicable(context.get(),
-                                                                fact_manager));
-  replace_false_with_sint64_comparison.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(replace_false_with_sint64_comparison.IsApplicable(
+      context.get(), transformation_context));
+  replace_false_with_sint64_comparison.Apply(context.get(),
+                                             &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after = R"(
@@ -419,7 +426,7 @@
     // The transformation is not applicable because %200 is NaN.
     ASSERT_FALSE(TransformationReplaceBooleanConstantWithConstantBinary(
                      uses_of_true[0], 11, 200, SpvOpFOrdLessThan, 300)
-                     .IsApplicable(context.get(), fact_manager));
+                     .IsApplicable(context.get(), transformation_context));
   }
   if (std::numeric_limits<double>::has_infinity) {
     double positive_infinity_double = std::numeric_limits<double>::infinity();
@@ -436,7 +443,7 @@
     // transformation is restricted to only apply to finite values.
     ASSERT_FALSE(TransformationReplaceBooleanConstantWithConstantBinary(
                      uses_of_true[0], 11, 201, SpvOpFOrdLessThan, 300)
-                     .IsApplicable(context.get(), fact_manager));
+                     .IsApplicable(context.get(), transformation_context));
   }
   if (std::numeric_limits<float>::has_infinity) {
     float positive_infinity_float = std::numeric_limits<float>::infinity();
@@ -461,7 +468,7 @@
     // values.
     ASSERT_FALSE(TransformationReplaceBooleanConstantWithConstantBinary(
                      uses_of_true[0], 203, 202, SpvOpFOrdLessThan, 300)
-                     .IsApplicable(context.get(), fact_manager));
+                     .IsApplicable(context.get(), transformation_context));
   }
 }
 
@@ -531,6 +538,9 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   auto use_of_true_in_if = MakeIdUseDescriptor(
       13, MakeInstructionDescriptor(10, SpvOpBranchConditional, 0), 0);
@@ -542,12 +552,14 @@
   auto replacement_2 = TransformationReplaceBooleanConstantWithConstantBinary(
       use_of_false_in_while, 9, 11, SpvOpSGreaterThanEqual, 101);
 
-  ASSERT_TRUE(replacement_1.IsApplicable(context.get(), fact_manager));
-  replacement_1.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      replacement_1.IsApplicable(context.get(), transformation_context));
+  replacement_1.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(replacement_2.IsApplicable(context.get(), fact_manager));
-  replacement_2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      replacement_2.IsApplicable(context.get(), transformation_context));
+  replacement_2.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after = R"(
@@ -642,12 +654,15 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   auto replacement = TransformationReplaceBooleanConstantWithConstantBinary(
       MakeIdUseDescriptor(9, MakeInstructionDescriptor(23, SpvOpPhi, 0), 0), 13,
       15, SpvOpSLessThan, 100);
 
-  ASSERT_FALSE(replacement.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(replacement.IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationReplaceBooleanConstantWithConstantBinaryTest,
@@ -681,12 +696,15 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   ASSERT_FALSE(TransformationReplaceBooleanConstantWithConstantBinary(
                    MakeIdUseDescriptor(
                        9, MakeInstructionDescriptor(50, SpvOpVariable, 0), 1),
                    13, 15, SpvOpSLessThan, 100)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 }
 
 }  // namespace
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_replace_constant_with_uniform_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_replace_constant_with_uniform_test.cpp
index 58d4a89..8cbba46 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_replace_constant_with_uniform_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_replace_constant_with_uniform_test.cpp
@@ -22,7 +22,8 @@
 namespace {
 
 bool AddFactHelper(
-    FactManager* fact_manager, opt::IRContext* context, uint32_t word,
+    TransformationContext* transformation_context, opt::IRContext* context,
+    uint32_t word,
     const protobufs::UniformBufferElementDescriptor& descriptor) {
   protobufs::FactConstantUniform constant_uniform_fact;
   constant_uniform_fact.add_constant_word(word);
@@ -30,7 +31,7 @@
       descriptor;
   protobufs::Fact fact;
   *fact.mutable_constant_uniform_fact() = constant_uniform_fact;
-  return fact_manager->AddFact(fact, context);
+  return transformation_context->GetFactManager()->AddFact(fact, context);
 }
 
 TEST(TransformationReplaceConstantWithUniformTest, BasicReplacements) {
@@ -104,6 +105,10 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
+
   protobufs::UniformBufferElementDescriptor blockname_a =
       MakeUniformBufferElementDescriptor(0, 0, {0});
   protobufs::UniformBufferElementDescriptor blockname_b =
@@ -111,9 +116,12 @@
   protobufs::UniformBufferElementDescriptor blockname_c =
       MakeUniformBufferElementDescriptor(0, 0, {2});
 
-  ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 1, blockname_a));
-  ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 2, blockname_b));
-  ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 3, blockname_c));
+  ASSERT_TRUE(
+      AddFactHelper(&transformation_context, context.get(), 1, blockname_a));
+  ASSERT_TRUE(
+      AddFactHelper(&transformation_context, context.get(), 2, blockname_b));
+  ASSERT_TRUE(
+      AddFactHelper(&transformation_context, context.get(), 3, blockname_c));
 
   // The constant ids are 9, 11 and 14, for 1, 2 and 3 respectively.
   protobufs::IdUseDescriptor use_of_9_in_store =
@@ -127,30 +135,30 @@
   auto transformation_use_of_9_in_store =
       TransformationReplaceConstantWithUniform(use_of_9_in_store, blockname_a,
                                                100, 101);
-  ASSERT_TRUE(transformation_use_of_9_in_store.IsApplicable(context.get(),
-                                                            fact_manager));
+  ASSERT_TRUE(transformation_use_of_9_in_store.IsApplicable(
+      context.get(), transformation_context));
   auto transformation_use_of_11_in_add =
       TransformationReplaceConstantWithUniform(use_of_11_in_add, blockname_b,
                                                102, 103);
-  ASSERT_TRUE(transformation_use_of_11_in_add.IsApplicable(context.get(),
-                                                           fact_manager));
+  ASSERT_TRUE(transformation_use_of_11_in_add.IsApplicable(
+      context.get(), transformation_context));
   auto transformation_use_of_14_in_add =
       TransformationReplaceConstantWithUniform(use_of_14_in_add, blockname_c,
                                                104, 105);
-  ASSERT_TRUE(transformation_use_of_14_in_add.IsApplicable(context.get(),
-                                                           fact_manager));
+  ASSERT_TRUE(transformation_use_of_14_in_add.IsApplicable(
+      context.get(), transformation_context));
 
   // The transformations are not applicable if we change which uniforms are
   // applied to which constants.
   ASSERT_FALSE(TransformationReplaceConstantWithUniform(use_of_9_in_store,
                                                         blockname_b, 101, 102)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationReplaceConstantWithUniform(use_of_11_in_add,
                                                         blockname_c, 101, 102)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationReplaceConstantWithUniform(use_of_14_in_add,
                                                         blockname_a, 101, 102)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // The following transformations do not apply because the uniform descriptors
   // are not sensible.
@@ -160,10 +168,10 @@
       MakeUniformBufferElementDescriptor(0, 0, {5});
   ASSERT_FALSE(TransformationReplaceConstantWithUniform(
                    use_of_9_in_store, nonsense_uniform_descriptor1, 101, 102)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationReplaceConstantWithUniform(
                    use_of_9_in_store, nonsense_uniform_descriptor2, 101, 102)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // The following transformation does not apply because the id descriptor is
   // not sensible.
@@ -171,18 +179,19 @@
       MakeIdUseDescriptor(9, MakeInstructionDescriptor(15, SpvOpIAdd, 0), 0);
   ASSERT_FALSE(TransformationReplaceConstantWithUniform(
                    nonsense_id_use_descriptor, blockname_a, 101, 102)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // The following transformations do not apply because the ids are not fresh.
   ASSERT_FALSE(TransformationReplaceConstantWithUniform(use_of_11_in_add,
                                                         blockname_b, 15, 103)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationReplaceConstantWithUniform(use_of_11_in_add,
                                                         blockname_b, 102, 15)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Apply the use of 9 in a store.
-  transformation_use_of_9_in_store.Apply(context.get(), &fact_manager);
+  transformation_use_of_9_in_store.Apply(context.get(),
+                                         &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
   std::string after_replacing_use_of_9_in_store = R"(
                OpCapability Shader
@@ -233,10 +242,10 @@
   )";
   ASSERT_TRUE(IsEqual(env, after_replacing_use_of_9_in_store, context.get()));
 
-  ASSERT_TRUE(transformation_use_of_11_in_add.IsApplicable(context.get(),
-                                                           fact_manager));
+  ASSERT_TRUE(transformation_use_of_11_in_add.IsApplicable(
+      context.get(), transformation_context));
   // Apply the use of 11 in an add.
-  transformation_use_of_11_in_add.Apply(context.get(), &fact_manager);
+  transformation_use_of_11_in_add.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
   std::string after_replacing_use_of_11_in_add = R"(
                OpCapability Shader
@@ -289,10 +298,10 @@
   )";
   ASSERT_TRUE(IsEqual(env, after_replacing_use_of_11_in_add, context.get()));
 
-  ASSERT_TRUE(transformation_use_of_14_in_add.IsApplicable(context.get(),
-                                                           fact_manager));
+  ASSERT_TRUE(transformation_use_of_14_in_add.IsApplicable(
+      context.get(), transformation_context));
   // Apply the use of 15 in an add.
-  transformation_use_of_14_in_add.Apply(context.get(), &fact_manager);
+  transformation_use_of_14_in_add.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
   std::string after_replacing_use_of_14_in_add = R"(
                OpCapability Shader
@@ -462,6 +471,10 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
+
   protobufs::UniformBufferElementDescriptor blockname_1 =
       MakeUniformBufferElementDescriptor(0, 0, {0});
   protobufs::UniformBufferElementDescriptor blockname_2 =
@@ -471,10 +484,14 @@
   protobufs::UniformBufferElementDescriptor blockname_4 =
       MakeUniformBufferElementDescriptor(0, 0, {1, 0, 1, 0});
 
-  ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 1, blockname_1));
-  ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 2, blockname_2));
-  ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 3, blockname_3));
-  ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 4, blockname_4));
+  ASSERT_TRUE(
+      AddFactHelper(&transformation_context, context.get(), 1, blockname_1));
+  ASSERT_TRUE(
+      AddFactHelper(&transformation_context, context.get(), 2, blockname_2));
+  ASSERT_TRUE(
+      AddFactHelper(&transformation_context, context.get(), 3, blockname_3));
+  ASSERT_TRUE(
+      AddFactHelper(&transformation_context, context.get(), 4, blockname_4));
 
   // The constant ids are 13, 15, 17 and 20, for 1, 2, 3 and 4 respectively.
   protobufs::IdUseDescriptor use_of_13_in_store =
@@ -490,76 +507,78 @@
   auto transformation_use_of_13_in_store =
       TransformationReplaceConstantWithUniform(use_of_13_in_store, blockname_1,
                                                100, 101);
-  ASSERT_TRUE(transformation_use_of_13_in_store.IsApplicable(context.get(),
-                                                             fact_manager));
+  ASSERT_TRUE(transformation_use_of_13_in_store.IsApplicable(
+      context.get(), transformation_context));
   auto transformation_use_of_15_in_add =
       TransformationReplaceConstantWithUniform(use_of_15_in_add, blockname_2,
                                                102, 103);
-  ASSERT_TRUE(transformation_use_of_15_in_add.IsApplicable(context.get(),
-                                                           fact_manager));
+  ASSERT_TRUE(transformation_use_of_15_in_add.IsApplicable(
+      context.get(), transformation_context));
   auto transformation_use_of_17_in_add =
       TransformationReplaceConstantWithUniform(use_of_17_in_add, blockname_3,
                                                104, 105);
-  ASSERT_TRUE(transformation_use_of_17_in_add.IsApplicable(context.get(),
-                                                           fact_manager));
+  ASSERT_TRUE(transformation_use_of_17_in_add.IsApplicable(
+      context.get(), transformation_context));
   auto transformation_use_of_20_in_store =
       TransformationReplaceConstantWithUniform(use_of_20_in_store, blockname_4,
                                                106, 107);
-  ASSERT_TRUE(transformation_use_of_20_in_store.IsApplicable(context.get(),
-                                                             fact_manager));
+  ASSERT_TRUE(transformation_use_of_20_in_store.IsApplicable(
+      context.get(), transformation_context));
 
-  ASSERT_TRUE(transformation_use_of_13_in_store.IsApplicable(context.get(),
-                                                             fact_manager));
-  ASSERT_TRUE(transformation_use_of_15_in_add.IsApplicable(context.get(),
-                                                           fact_manager));
-  ASSERT_TRUE(transformation_use_of_17_in_add.IsApplicable(context.get(),
-                                                           fact_manager));
-  ASSERT_TRUE(transformation_use_of_20_in_store.IsApplicable(context.get(),
-                                                             fact_manager));
+  ASSERT_TRUE(transformation_use_of_13_in_store.IsApplicable(
+      context.get(), transformation_context));
+  ASSERT_TRUE(transformation_use_of_15_in_add.IsApplicable(
+      context.get(), transformation_context));
+  ASSERT_TRUE(transformation_use_of_17_in_add.IsApplicable(
+      context.get(), transformation_context));
+  ASSERT_TRUE(transformation_use_of_20_in_store.IsApplicable(
+      context.get(), transformation_context));
 
-  transformation_use_of_13_in_store.Apply(context.get(), &fact_manager);
+  transformation_use_of_13_in_store.Apply(context.get(),
+                                          &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
-  ASSERT_FALSE(transformation_use_of_13_in_store.IsApplicable(context.get(),
-                                                              fact_manager));
-  ASSERT_TRUE(transformation_use_of_15_in_add.IsApplicable(context.get(),
-                                                           fact_manager));
-  ASSERT_TRUE(transformation_use_of_17_in_add.IsApplicable(context.get(),
-                                                           fact_manager));
-  ASSERT_TRUE(transformation_use_of_20_in_store.IsApplicable(context.get(),
-                                                             fact_manager));
+  ASSERT_FALSE(transformation_use_of_13_in_store.IsApplicable(
+      context.get(), transformation_context));
+  ASSERT_TRUE(transformation_use_of_15_in_add.IsApplicable(
+      context.get(), transformation_context));
+  ASSERT_TRUE(transformation_use_of_17_in_add.IsApplicable(
+      context.get(), transformation_context));
+  ASSERT_TRUE(transformation_use_of_20_in_store.IsApplicable(
+      context.get(), transformation_context));
 
-  transformation_use_of_15_in_add.Apply(context.get(), &fact_manager);
+  transformation_use_of_15_in_add.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
-  ASSERT_FALSE(transformation_use_of_13_in_store.IsApplicable(context.get(),
-                                                              fact_manager));
-  ASSERT_FALSE(transformation_use_of_15_in_add.IsApplicable(context.get(),
-                                                            fact_manager));
-  ASSERT_TRUE(transformation_use_of_17_in_add.IsApplicable(context.get(),
-                                                           fact_manager));
-  ASSERT_TRUE(transformation_use_of_20_in_store.IsApplicable(context.get(),
-                                                             fact_manager));
+  ASSERT_FALSE(transformation_use_of_13_in_store.IsApplicable(
+      context.get(), transformation_context));
+  ASSERT_FALSE(transformation_use_of_15_in_add.IsApplicable(
+      context.get(), transformation_context));
+  ASSERT_TRUE(transformation_use_of_17_in_add.IsApplicable(
+      context.get(), transformation_context));
+  ASSERT_TRUE(transformation_use_of_20_in_store.IsApplicable(
+      context.get(), transformation_context));
 
-  transformation_use_of_17_in_add.Apply(context.get(), &fact_manager);
+  transformation_use_of_17_in_add.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
-  ASSERT_FALSE(transformation_use_of_13_in_store.IsApplicable(context.get(),
-                                                              fact_manager));
-  ASSERT_FALSE(transformation_use_of_15_in_add.IsApplicable(context.get(),
-                                                            fact_manager));
-  ASSERT_FALSE(transformation_use_of_17_in_add.IsApplicable(context.get(),
-                                                            fact_manager));
-  ASSERT_TRUE(transformation_use_of_20_in_store.IsApplicable(context.get(),
-                                                             fact_manager));
+  ASSERT_FALSE(transformation_use_of_13_in_store.IsApplicable(
+      context.get(), transformation_context));
+  ASSERT_FALSE(transformation_use_of_15_in_add.IsApplicable(
+      context.get(), transformation_context));
+  ASSERT_FALSE(transformation_use_of_17_in_add.IsApplicable(
+      context.get(), transformation_context));
+  ASSERT_TRUE(transformation_use_of_20_in_store.IsApplicable(
+      context.get(), transformation_context));
 
-  transformation_use_of_20_in_store.Apply(context.get(), &fact_manager);
+  transformation_use_of_20_in_store.Apply(context.get(),
+                                          &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
-  ASSERT_FALSE(transformation_use_of_13_in_store.IsApplicable(context.get(),
-                                                              fact_manager));
-  ASSERT_FALSE(transformation_use_of_15_in_add.IsApplicable(context.get(),
-                                                            fact_manager));
-  ASSERT_FALSE(transformation_use_of_17_in_add.IsApplicable(context.get(),
-                                                            fact_manager));
-  ASSERT_FALSE(transformation_use_of_20_in_store.IsApplicable(context.get(),
-                                                              fact_manager));
+  ASSERT_FALSE(transformation_use_of_13_in_store.IsApplicable(
+      context.get(), transformation_context));
+  ASSERT_FALSE(transformation_use_of_15_in_add.IsApplicable(
+      context.get(), transformation_context));
+  ASSERT_FALSE(transformation_use_of_17_in_add.IsApplicable(
+      context.get(), transformation_context));
+  ASSERT_FALSE(transformation_use_of_20_in_store.IsApplicable(
+      context.get(), transformation_context));
 
   std::string after = R"(
                OpCapability Shader
@@ -697,10 +716,15 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
+
   protobufs::UniformBufferElementDescriptor blockname_0 =
       MakeUniformBufferElementDescriptor(0, 0, {0});
 
-  ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 0, blockname_0));
+  ASSERT_TRUE(
+      AddFactHelper(&transformation_context, context.get(), 0, blockname_0));
 
   // The constant id is 9 for 0.
   protobufs::IdUseDescriptor use_of_9_in_store =
@@ -710,7 +734,7 @@
   // type is present:
   ASSERT_FALSE(TransformationReplaceConstantWithUniform(use_of_9_in_store,
                                                         blockname_0, 100, 101)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationReplaceConstantWithUniformTest, NoConstantPresentForIndex) {
@@ -770,12 +794,17 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
+
   protobufs::UniformBufferElementDescriptor blockname_0 =
       MakeUniformBufferElementDescriptor(0, 0, {0});
   protobufs::UniformBufferElementDescriptor blockname_9 =
       MakeUniformBufferElementDescriptor(0, 0, {1});
 
-  ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 9, blockname_9));
+  ASSERT_TRUE(
+      AddFactHelper(&transformation_context, context.get(), 9, blockname_9));
 
   // The constant id is 9 for 9.
   protobufs::IdUseDescriptor use_of_9_in_store =
@@ -785,7 +814,7 @@
   // index 1 required to index into the uniform buffer:
   ASSERT_FALSE(TransformationReplaceConstantWithUniform(use_of_9_in_store,
                                                         blockname_9, 100, 101)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationReplaceConstantWithUniformTest,
@@ -842,14 +871,18 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
+
   protobufs::UniformBufferElementDescriptor blockname_3 =
       MakeUniformBufferElementDescriptor(0, 0, {0});
 
   uint32_t float_data[1];
   float temp = 3.0;
   memcpy(&float_data[0], &temp, sizeof(float));
-  ASSERT_TRUE(
-      AddFactHelper(&fact_manager, context.get(), float_data[0], blockname_3));
+  ASSERT_TRUE(AddFactHelper(&transformation_context, context.get(),
+                            float_data[0], blockname_3));
 
   // The constant id is 9 for 3.0.
   protobufs::IdUseDescriptor use_of_9_in_store =
@@ -859,7 +892,7 @@
   // allow a constant index to be expressed:
   ASSERT_FALSE(TransformationReplaceConstantWithUniform(use_of_9_in_store,
                                                         blockname_3, 100, 101)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationReplaceConstantWithUniformTest,
@@ -928,13 +961,19 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
+
   protobufs::UniformBufferElementDescriptor blockname_9 =
       MakeUniformBufferElementDescriptor(0, 0, {0});
   protobufs::UniformBufferElementDescriptor blockname_10 =
       MakeUniformBufferElementDescriptor(0, 0, {1});
 
-  ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 9, blockname_9));
-  ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 10, blockname_10));
+  ASSERT_TRUE(
+      AddFactHelper(&transformation_context, context.get(), 9, blockname_9));
+  ASSERT_TRUE(
+      AddFactHelper(&transformation_context, context.get(), 10, blockname_10));
 
   // The constant ids for 9 and 10 are 9 and 11 respectively
   protobufs::IdUseDescriptor use_of_9_in_store =
@@ -945,19 +984,19 @@
   // These are right:
   ASSERT_TRUE(TransformationReplaceConstantWithUniform(use_of_9_in_store,
                                                        blockname_9, 100, 101)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationReplaceConstantWithUniform(use_of_11_in_store,
                                                        blockname_10, 102, 103)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
 
   // These are wrong because the constants do not match the facts about
   // uniforms.
   ASSERT_FALSE(TransformationReplaceConstantWithUniform(use_of_11_in_store,
                                                         blockname_9, 100, 101)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationReplaceConstantWithUniform(use_of_9_in_store,
                                                         blockname_10, 102, 103)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationReplaceConstantWithUniformTest, ComplexReplacements) {
@@ -1141,6 +1180,9 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   const float float_array_values[5] = {1.0, 1.5, 1.75, 1.875, 1.9375};
   uint32_t float_array_data[5];
@@ -1188,35 +1230,43 @@
   protobufs::UniformBufferElementDescriptor uniform_h_y =
       MakeUniformBufferElementDescriptor(0, 0, {2, 1});
 
-  ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), float_array_data[0],
-                            uniform_f_a_0));
-  ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), float_array_data[1],
-                            uniform_f_a_1));
-  ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), float_array_data[2],
-                            uniform_f_a_2));
-  ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), float_array_data[3],
-                            uniform_f_a_3));
-  ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), float_array_data[4],
-                            uniform_f_a_4));
+  ASSERT_TRUE(AddFactHelper(&transformation_context, context.get(),
+                            float_array_data[0], uniform_f_a_0));
+  ASSERT_TRUE(AddFactHelper(&transformation_context, context.get(),
+                            float_array_data[1], uniform_f_a_1));
+  ASSERT_TRUE(AddFactHelper(&transformation_context, context.get(),
+                            float_array_data[2], uniform_f_a_2));
+  ASSERT_TRUE(AddFactHelper(&transformation_context, context.get(),
+                            float_array_data[3], uniform_f_a_3));
+  ASSERT_TRUE(AddFactHelper(&transformation_context, context.get(),
+                            float_array_data[4], uniform_f_a_4));
 
-  ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 1, uniform_f_b_x));
-  ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 2, uniform_f_b_y));
-  ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 3, uniform_f_b_z));
-  ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 4, uniform_f_b_w));
+  ASSERT_TRUE(
+      AddFactHelper(&transformation_context, context.get(), 1, uniform_f_b_x));
+  ASSERT_TRUE(
+      AddFactHelper(&transformation_context, context.get(), 2, uniform_f_b_y));
+  ASSERT_TRUE(
+      AddFactHelper(&transformation_context, context.get(), 3, uniform_f_b_z));
+  ASSERT_TRUE(
+      AddFactHelper(&transformation_context, context.get(), 4, uniform_f_b_w));
 
-  ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), float_vector_data[0],
-                            uniform_f_c_x));
-  ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), float_vector_data[1],
-                            uniform_f_c_y));
-  ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), float_vector_data[2],
-                            uniform_f_c_z));
+  ASSERT_TRUE(AddFactHelper(&transformation_context, context.get(),
+                            float_vector_data[0], uniform_f_c_x));
+  ASSERT_TRUE(AddFactHelper(&transformation_context, context.get(),
+                            float_vector_data[1], uniform_f_c_y));
+  ASSERT_TRUE(AddFactHelper(&transformation_context, context.get(),
+                            float_vector_data[2], uniform_f_c_z));
 
-  ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 42, uniform_f_d));
+  ASSERT_TRUE(
+      AddFactHelper(&transformation_context, context.get(), 42, uniform_f_d));
 
-  ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 22, uniform_g));
+  ASSERT_TRUE(
+      AddFactHelper(&transformation_context, context.get(), 22, uniform_g));
 
-  ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 100, uniform_h_x));
-  ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 200, uniform_h_y));
+  ASSERT_TRUE(
+      AddFactHelper(&transformation_context, context.get(), 100, uniform_h_x));
+  ASSERT_TRUE(
+      AddFactHelper(&transformation_context, context.get(), 200, uniform_h_y));
 
   std::vector<TransformationReplaceConstantWithUniform> transformations;
 
@@ -1275,8 +1325,9 @@
       uniform_g, 218, 219));
 
   for (auto& transformation : transformations) {
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
     ASSERT_TRUE(IsValid(env, context.get()));
   }
 
@@ -1480,16 +1531,21 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
+
   protobufs::UniformBufferElementDescriptor blockname_a =
       MakeUniformBufferElementDescriptor(0, 0, {0});
 
-  ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 0, blockname_a));
+  ASSERT_TRUE(
+      AddFactHelper(&transformation_context, context.get(), 0, blockname_a));
 
   ASSERT_FALSE(TransformationReplaceConstantWithUniform(
                    MakeIdUseDescriptor(
                        50, MakeInstructionDescriptor(8, SpvOpVariable, 0), 1),
                    blockname_a, 100, 101)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 }
 
 }  // namespace
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_replace_id_with_synonym_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_replace_id_with_synonym_test.cpp
index 41b6116..6b514a3 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_replace_id_with_synonym_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_replace_id_with_synonym_test.cpp
@@ -220,15 +220,19 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
-  SetUpIdSynonyms(&fact_manager, context.get());
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
+
+  SetUpIdSynonyms(transformation_context.GetFactManager(), context.get());
 
   // %202 cannot replace %15 as in-operand 0 of %300, since %202 does not
   // dominate %300.
   auto synonym_does_not_dominate_use = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(15, MakeInstructionDescriptor(300, SpvOpIAdd, 0), 0),
       202);
-  ASSERT_FALSE(
-      synonym_does_not_dominate_use.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(synonym_does_not_dominate_use.IsApplicable(
+      context.get(), transformation_context));
 
   // %202 cannot replace %15 as in-operand 2 of %301, since this is the OpPhi's
   // incoming value for block %72, and %202 does not dominate %72.
@@ -237,22 +241,23 @@
           MakeIdUseDescriptor(15, MakeInstructionDescriptor(301, SpvOpPhi, 0),
                               2),
           202);
-  ASSERT_FALSE(synonym_does_not_dominate_use_op_phi.IsApplicable(context.get(),
-                                                                 fact_manager));
+  ASSERT_FALSE(synonym_does_not_dominate_use_op_phi.IsApplicable(
+      context.get(), transformation_context));
 
   // %200 is not a synonym for %84
   auto id_in_use_is_not_synonymous = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
           84, MakeInstructionDescriptor(67, SpvOpSGreaterThan, 0), 0),
       200);
-  ASSERT_FALSE(
-      id_in_use_is_not_synonymous.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(id_in_use_is_not_synonymous.IsApplicable(
+      context.get(), transformation_context));
 
   // %86 is not a synonym for anything (and in particular not for %74)
   auto id_has_no_synonyms = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(86, MakeInstructionDescriptor(84, SpvOpPhi, 0), 2),
       74);
-  ASSERT_FALSE(id_has_no_synonyms.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      id_has_no_synonyms.IsApplicable(context.get(), transformation_context));
 
   // This would lead to %207 = 'OpCopyObject %type %207' if it were allowed
   auto synonym_use_is_in_synonym_definition =
@@ -260,8 +265,8 @@
           MakeIdUseDescriptor(
               84, MakeInstructionDescriptor(207, SpvOpCopyObject, 0), 0),
           207);
-  ASSERT_FALSE(synonym_use_is_in_synonym_definition.IsApplicable(context.get(),
-                                                                 fact_manager));
+  ASSERT_FALSE(synonym_use_is_in_synonym_definition.IsApplicable(
+      context.get(), transformation_context));
 
   // The id use descriptor does not lead to a use (%84 is not used in the
   // definition of %207)
@@ -269,7 +274,8 @@
       MakeIdUseDescriptor(
           84, MakeInstructionDescriptor(200, SpvOpCopyObject, 0), 0),
       207);
-  ASSERT_FALSE(bad_id_use_descriptor.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(bad_id_use_descriptor.IsApplicable(context.get(),
+                                                  transformation_context));
 
   // This replacement would lead to an access chain into a struct using a
   // non-constant index.
@@ -277,7 +283,8 @@
       MakeIdUseDescriptor(
           12, MakeInstructionDescriptor(14, SpvOpAccessChain, 0), 1),
       209);
-  ASSERT_FALSE(bad_access_chain.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      bad_access_chain.IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationReplaceIdWithSynonymTest, LegalTransformations) {
@@ -288,23 +295,28 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
-  SetUpIdSynonyms(&fact_manager, context.get());
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
+
+  SetUpIdSynonyms(transformation_context.GetFactManager(), context.get());
 
   auto global_constant_synonym = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(19, MakeInstructionDescriptor(47, SpvOpStore, 0), 1),
       210);
-  ASSERT_TRUE(
-      global_constant_synonym.IsApplicable(context.get(), fact_manager));
-  global_constant_synonym.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(global_constant_synonym.IsApplicable(context.get(),
+                                                   transformation_context));
+  global_constant_synonym.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   auto replace_vector_access_chain_index = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
           54, MakeInstructionDescriptor(55, SpvOpAccessChain, 0), 1),
       204);
-  ASSERT_TRUE(replace_vector_access_chain_index.IsApplicable(context.get(),
-                                                             fact_manager));
-  replace_vector_access_chain_index.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(replace_vector_access_chain_index.IsApplicable(
+      context.get(), transformation_context));
+  replace_vector_access_chain_index.Apply(context.get(),
+                                          &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // This is an interesting case because it replaces something that is being
@@ -313,22 +325,24 @@
       MakeIdUseDescriptor(
           15, MakeInstructionDescriptor(202, SpvOpCopyObject, 0), 0),
       201);
-  ASSERT_TRUE(regular_replacement.IsApplicable(context.get(), fact_manager));
-  regular_replacement.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      regular_replacement.IsApplicable(context.get(), transformation_context));
+  regular_replacement.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   auto regular_replacement2 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(55, MakeInstructionDescriptor(203, SpvOpStore, 0), 0),
       203);
-  ASSERT_TRUE(regular_replacement2.IsApplicable(context.get(), fact_manager));
-  regular_replacement2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      regular_replacement2.IsApplicable(context.get(), transformation_context));
+  regular_replacement2.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   auto good_op_phi = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(74, MakeInstructionDescriptor(86, SpvOpPhi, 0), 2),
       205);
-  ASSERT_TRUE(good_op_phi.IsApplicable(context.get(), fact_manager));
-  good_op_phi.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(good_op_phi.IsApplicable(context.get(), transformation_context));
+  good_op_phi.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   const std::string after_transformation = R"(
@@ -504,17 +518,22 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
-  fact_manager.AddFact(MakeSynonymFact(10, 100), context.get());
-  fact_manager.AddFact(MakeSynonymFact(8, 101), context.get());
+  transformation_context.GetFactManager()->AddFact(MakeSynonymFact(10, 100),
+                                                   context.get());
+  transformation_context.GetFactManager()->AddFact(MakeSynonymFact(8, 101),
+                                                   context.get());
 
   // Replace %10 with %100 in:
   // %11 = OpLoad %6 %10
   auto replacement1 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(10, MakeInstructionDescriptor(11, SpvOpLoad, 0), 0),
       100);
-  ASSERT_TRUE(replacement1.IsApplicable(context.get(), fact_manager));
-  replacement1.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(replacement1.IsApplicable(context.get(), transformation_context));
+  replacement1.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Replace %8 with %101 in:
@@ -522,8 +541,8 @@
   auto replacement2 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(8, MakeInstructionDescriptor(11, SpvOpStore, 0), 0),
       101);
-  ASSERT_TRUE(replacement2.IsApplicable(context.get(), fact_manager));
-  replacement2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(replacement2.IsApplicable(context.get(), transformation_context));
+  replacement2.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Replace %8 with %101 in:
@@ -531,8 +550,8 @@
   auto replacement3 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(8, MakeInstructionDescriptor(12, SpvOpLoad, 0), 0),
       101);
-  ASSERT_TRUE(replacement3.IsApplicable(context.get(), fact_manager));
-  replacement3.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(replacement3.IsApplicable(context.get(), transformation_context));
+  replacement3.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Replace %10 with %100 in:
@@ -540,8 +559,8 @@
   auto replacement4 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(10, MakeInstructionDescriptor(12, SpvOpStore, 0), 0),
       100);
-  ASSERT_TRUE(replacement4.IsApplicable(context.get(), fact_manager));
-  replacement4.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(replacement4.IsApplicable(context.get(), transformation_context));
+  replacement4.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   const std::string after_transformation = R"(
@@ -633,8 +652,12 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
-  fact_manager.AddFact(MakeSynonymFact(14, 100), context.get());
+  transformation_context.GetFactManager()->AddFact(MakeSynonymFact(14, 100),
+                                                   context.get());
 
   // Replace %14 with %100 in:
   // %16 = OpFunctionCall %2 %10 %14
@@ -642,7 +665,7 @@
       MakeIdUseDescriptor(
           14, MakeInstructionDescriptor(16, SpvOpFunctionCall, 0), 1),
       100);
-  ASSERT_FALSE(replacement.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(replacement.IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationReplaceIdWithSynonymTest, SynonymsOfAccessChainIndices) {
@@ -795,22 +818,38 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // Add synonym facts corresponding to the OpCopyObject operations that have
   // been applied to all constants in the module.
-  fact_manager.AddFact(MakeSynonymFact(16, 100), context.get());
-  fact_manager.AddFact(MakeSynonymFact(21, 101), context.get());
-  fact_manager.AddFact(MakeSynonymFact(17, 102), context.get());
-  fact_manager.AddFact(MakeSynonymFact(57, 103), context.get());
-  fact_manager.AddFact(MakeSynonymFact(18, 104), context.get());
-  fact_manager.AddFact(MakeSynonymFact(40, 105), context.get());
-  fact_manager.AddFact(MakeSynonymFact(32, 106), context.get());
-  fact_manager.AddFact(MakeSynonymFact(43, 107), context.get());
-  fact_manager.AddFact(MakeSynonymFact(55, 108), context.get());
-  fact_manager.AddFact(MakeSynonymFact(8, 109), context.get());
-  fact_manager.AddFact(MakeSynonymFact(47, 110), context.get());
-  fact_manager.AddFact(MakeSynonymFact(28, 111), context.get());
-  fact_manager.AddFact(MakeSynonymFact(45, 112), context.get());
+  transformation_context.GetFactManager()->AddFact(MakeSynonymFact(16, 100),
+                                                   context.get());
+  transformation_context.GetFactManager()->AddFact(MakeSynonymFact(21, 101),
+                                                   context.get());
+  transformation_context.GetFactManager()->AddFact(MakeSynonymFact(17, 102),
+                                                   context.get());
+  transformation_context.GetFactManager()->AddFact(MakeSynonymFact(57, 103),
+                                                   context.get());
+  transformation_context.GetFactManager()->AddFact(MakeSynonymFact(18, 104),
+                                                   context.get());
+  transformation_context.GetFactManager()->AddFact(MakeSynonymFact(40, 105),
+                                                   context.get());
+  transformation_context.GetFactManager()->AddFact(MakeSynonymFact(32, 106),
+                                                   context.get());
+  transformation_context.GetFactManager()->AddFact(MakeSynonymFact(43, 107),
+                                                   context.get());
+  transformation_context.GetFactManager()->AddFact(MakeSynonymFact(55, 108),
+                                                   context.get());
+  transformation_context.GetFactManager()->AddFact(MakeSynonymFact(8, 109),
+                                                   context.get());
+  transformation_context.GetFactManager()->AddFact(MakeSynonymFact(47, 110),
+                                                   context.get());
+  transformation_context.GetFactManager()->AddFact(MakeSynonymFact(28, 111),
+                                                   context.get());
+  transformation_context.GetFactManager()->AddFact(MakeSynonymFact(45, 112),
+                                                   context.get());
 
   // Replacements of the form %16 -> %100
 
@@ -821,7 +860,8 @@
       MakeIdUseDescriptor(
           16, MakeInstructionDescriptor(20, SpvOpAccessChain, 0), 1),
       100);
-  ASSERT_FALSE(replacement1.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      replacement1.IsApplicable(context.get(), transformation_context));
 
   // %39 = OpAccessChain %23 %37 *%16*
   // Corresponds to h.*f*
@@ -830,7 +870,8 @@
       MakeIdUseDescriptor(
           16, MakeInstructionDescriptor(39, SpvOpAccessChain, 0), 1),
       100);
-  ASSERT_FALSE(replacement2.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      replacement2.IsApplicable(context.get(), transformation_context));
 
   // %41 = OpAccessChain %19 %37 %21 *%16* %21
   // Corresponds to h.g.*a*[1]
@@ -839,7 +880,8 @@
       MakeIdUseDescriptor(
           16, MakeInstructionDescriptor(41, SpvOpAccessChain, 0), 2),
       100);
-  ASSERT_FALSE(replacement3.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      replacement3.IsApplicable(context.get(), transformation_context));
 
   // %52 = OpAccessChain %23 %50 *%16* %16
   // Corresponds to i[*0*].f
@@ -848,8 +890,8 @@
       MakeIdUseDescriptor(
           16, MakeInstructionDescriptor(52, SpvOpAccessChain, 0), 1),
       100);
-  ASSERT_TRUE(replacement4.IsApplicable(context.get(), fact_manager));
-  replacement4.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(replacement4.IsApplicable(context.get(), transformation_context));
+  replacement4.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // %52 = OpAccessChain %23 %50 %16 *%16*
@@ -859,7 +901,8 @@
       MakeIdUseDescriptor(
           16, MakeInstructionDescriptor(52, SpvOpAccessChain, 0), 2),
       100);
-  ASSERT_FALSE(replacement5.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      replacement5.IsApplicable(context.get(), transformation_context));
 
   // %53 = OpAccessChain %19 %50 %21 %21 *%16* %16
   // Corresponds to i[1].g.*a*[0]
@@ -868,7 +911,8 @@
       MakeIdUseDescriptor(
           16, MakeInstructionDescriptor(53, SpvOpAccessChain, 0), 3),
       100);
-  ASSERT_FALSE(replacement6.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      replacement6.IsApplicable(context.get(), transformation_context));
 
   // %53 = OpAccessChain %19 %50 %21 %21 %16 *%16*
   // Corresponds to i[1].g.a[*0*]
@@ -877,8 +921,8 @@
       MakeIdUseDescriptor(
           16, MakeInstructionDescriptor(53, SpvOpAccessChain, 0), 4),
       100);
-  ASSERT_TRUE(replacement7.IsApplicable(context.get(), fact_manager));
-  replacement7.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(replacement7.IsApplicable(context.get(), transformation_context));
+  replacement7.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Replacements of the form %21 -> %101
@@ -890,7 +934,8 @@
       MakeIdUseDescriptor(
           21, MakeInstructionDescriptor(24, SpvOpAccessChain, 0), 1),
       101);
-  ASSERT_FALSE(replacement8.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      replacement8.IsApplicable(context.get(), transformation_context));
 
   // %41 = OpAccessChain %19 %37 *%21* %16 %21
   // Corresponds to h.*g*.a[1]
@@ -899,7 +944,8 @@
       MakeIdUseDescriptor(
           21, MakeInstructionDescriptor(41, SpvOpAccessChain, 0), 1),
       101);
-  ASSERT_FALSE(replacement9.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      replacement9.IsApplicable(context.get(), transformation_context));
 
   // %41 = OpAccessChain %19 %37 %21 %16 *%21*
   // Corresponds to h.g.a[*1*]
@@ -908,8 +954,9 @@
       MakeIdUseDescriptor(
           21, MakeInstructionDescriptor(41, SpvOpAccessChain, 0), 3),
       101);
-  ASSERT_TRUE(replacement10.IsApplicable(context.get(), fact_manager));
-  replacement10.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      replacement10.IsApplicable(context.get(), transformation_context));
+  replacement10.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // %44 = OpAccessChain %23 %37 *%21* %21 %43
@@ -919,7 +966,8 @@
       MakeIdUseDescriptor(
           21, MakeInstructionDescriptor(44, SpvOpAccessChain, 0), 1),
       101);
-  ASSERT_FALSE(replacement11.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      replacement11.IsApplicable(context.get(), transformation_context));
 
   // %44 = OpAccessChain %23 %37 %21 *%21* %43
   // Corresponds to h.g.*b*[0]
@@ -928,7 +976,8 @@
       MakeIdUseDescriptor(
           21, MakeInstructionDescriptor(44, SpvOpAccessChain, 0), 2),
       101);
-  ASSERT_FALSE(replacement12.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      replacement12.IsApplicable(context.get(), transformation_context));
 
   // %46 = OpAccessChain %26 %37 *%21* %17
   // Corresponds to h.*g*.c
@@ -937,7 +986,8 @@
       MakeIdUseDescriptor(
           21, MakeInstructionDescriptor(46, SpvOpAccessChain, 0), 1),
       101);
-  ASSERT_FALSE(replacement13.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      replacement13.IsApplicable(context.get(), transformation_context));
 
   // %53 = OpAccessChain %19 %50 *%21* %21 %16 %16
   // Corresponds to i[*1*].g.a[0]
@@ -946,8 +996,9 @@
       MakeIdUseDescriptor(
           21, MakeInstructionDescriptor(53, SpvOpAccessChain, 0), 1),
       101);
-  ASSERT_TRUE(replacement14.IsApplicable(context.get(), fact_manager));
-  replacement14.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      replacement14.IsApplicable(context.get(), transformation_context));
+  replacement14.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // %53 = OpAccessChain %19 %50 %21 *%21* %16 %16
@@ -957,7 +1008,8 @@
       MakeIdUseDescriptor(
           21, MakeInstructionDescriptor(53, SpvOpAccessChain, 0), 2),
       101);
-  ASSERT_FALSE(replacement15.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      replacement15.IsApplicable(context.get(), transformation_context));
 
   // %56 = OpAccessChain %23 %50 %17 *%21* %21 %55
   // Corresponds to i[2].*g*.b[1]
@@ -966,7 +1018,8 @@
       MakeIdUseDescriptor(
           21, MakeInstructionDescriptor(56, SpvOpAccessChain, 0), 2),
       101);
-  ASSERT_FALSE(replacement16.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      replacement16.IsApplicable(context.get(), transformation_context));
 
   // %56 = OpAccessChain %23 %50 %17 %21 *%21* %55
   // Corresponds to i[2].g.*b*[1]
@@ -975,7 +1028,8 @@
       MakeIdUseDescriptor(
           21, MakeInstructionDescriptor(56, SpvOpAccessChain, 0), 3),
       101);
-  ASSERT_FALSE(replacement17.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      replacement17.IsApplicable(context.get(), transformation_context));
 
   // %58 = OpAccessChain %26 %50 %57 *%21* %17
   // Corresponds to i[3].*g*.c
@@ -984,7 +1038,8 @@
       MakeIdUseDescriptor(
           21, MakeInstructionDescriptor(58, SpvOpAccessChain, 0), 2),
       101);
-  ASSERT_FALSE(replacement18.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      replacement18.IsApplicable(context.get(), transformation_context));
 
   // Replacements of the form %17 -> %102
 
@@ -995,8 +1050,9 @@
       MakeIdUseDescriptor(
           17, MakeInstructionDescriptor(20, SpvOpAccessChain, 0), 2),
       102);
-  ASSERT_TRUE(replacement19.IsApplicable(context.get(), fact_manager));
-  replacement19.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      replacement19.IsApplicable(context.get(), transformation_context));
+  replacement19.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // %27 = OpAccessChain %26 %15 %17
@@ -1006,7 +1062,8 @@
       MakeIdUseDescriptor(
           17, MakeInstructionDescriptor(27, SpvOpAccessChain, 0), 1),
       102);
-  ASSERT_FALSE(replacement20.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      replacement20.IsApplicable(context.get(), transformation_context));
 
   // %46 = OpAccessChain %26 %37 %21 %17
   // Corresponds to h.g.*c*
@@ -1015,7 +1072,8 @@
       MakeIdUseDescriptor(
           17, MakeInstructionDescriptor(46, SpvOpAccessChain, 0), 2),
       102);
-  ASSERT_FALSE(replacement21.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      replacement21.IsApplicable(context.get(), transformation_context));
 
   // %56 = OpAccessChain %23 %50 %17 %21 %21 %55
   // Corresponds to i[*2*].g.b[1]
@@ -1024,8 +1082,9 @@
       MakeIdUseDescriptor(
           17, MakeInstructionDescriptor(56, SpvOpAccessChain, 0), 1),
       102);
-  ASSERT_TRUE(replacement22.IsApplicable(context.get(), fact_manager));
-  replacement22.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      replacement22.IsApplicable(context.get(), transformation_context));
+  replacement22.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // %58 = OpAccessChain %26 %50 %57 %21 %17
@@ -1035,7 +1094,8 @@
       MakeIdUseDescriptor(
           17, MakeInstructionDescriptor(58, SpvOpAccessChain, 0), 3),
       102);
-  ASSERT_FALSE(replacement23.IsApplicable(context.get(), fact_manager));
+  ASSERT_FALSE(
+      replacement23.IsApplicable(context.get(), transformation_context));
 
   // Replacements of the form %57 -> %103
 
@@ -1046,8 +1106,9 @@
       MakeIdUseDescriptor(
           57, MakeInstructionDescriptor(58, SpvOpAccessChain, 0), 1),
       103);
-  ASSERT_TRUE(replacement24.IsApplicable(context.get(), fact_manager));
-  replacement24.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      replacement24.IsApplicable(context.get(), transformation_context));
+  replacement24.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Replacements of the form %32 -> %106
@@ -1059,8 +1120,9 @@
       MakeIdUseDescriptor(
           32, MakeInstructionDescriptor(34, SpvOpAccessChain, 0), 1),
       106);
-  ASSERT_TRUE(replacement25.IsApplicable(context.get(), fact_manager));
-  replacement25.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      replacement25.IsApplicable(context.get(), transformation_context));
+  replacement25.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Replacements of the form %43 -> %107
@@ -1072,8 +1134,9 @@
       MakeIdUseDescriptor(
           43, MakeInstructionDescriptor(44, SpvOpAccessChain, 0), 3),
       107);
-  ASSERT_TRUE(replacement26.IsApplicable(context.get(), fact_manager));
-  replacement26.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      replacement26.IsApplicable(context.get(), transformation_context));
+  replacement26.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Replacements of the form %55 -> %108
@@ -1085,8 +1148,9 @@
       MakeIdUseDescriptor(
           55, MakeInstructionDescriptor(56, SpvOpAccessChain, 0), 4),
       108);
-  ASSERT_TRUE(replacement27.IsApplicable(context.get(), fact_manager));
-  replacement27.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      replacement27.IsApplicable(context.get(), transformation_context));
+  replacement27.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   // Replacements of the form %8 -> %109
@@ -1098,8 +1162,9 @@
       MakeIdUseDescriptor(8, MakeInstructionDescriptor(24, SpvOpAccessChain, 0),
                           2),
       109);
-  ASSERT_TRUE(replacement28.IsApplicable(context.get(), fact_manager));
-  replacement28.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      replacement28.IsApplicable(context.get(), transformation_context));
+  replacement28.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   const std::string after_transformation = R"(
@@ -1212,6 +1277,122 @@
   ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
 }
 
+TEST(TransformationReplaceIdWithSynonymTest, RuntimeArrayTest) {
+  // This checks that OpRuntimeArray is correctly handled.
+  const std::string shader = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main"
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 310
+               OpDecorate %8 ArrayStride 8
+               OpMemberDecorate %9 0 Offset 0
+               OpDecorate %9 BufferBlock
+               OpDecorate %11 DescriptorSet 0
+               OpDecorate %11 Binding 0
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %6 = OpTypeInt 32 1
+          %7 = OpTypeVector %6 2
+          %8 = OpTypeRuntimeArray %7
+          %9 = OpTypeStruct %8
+         %10 = OpTypePointer Uniform %9
+         %11 = OpVariable %10 Uniform
+         %12 = OpConstant %6 0
+         %13 = OpTypeInt 32 0
+         %14 = OpConstant %13 0
+         %15 = OpTypePointer Uniform %6
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+         %50 = OpCopyObject %6 %12
+         %51 = OpCopyObject %13 %14
+         %16 = OpAccessChain %15 %11 %12 %12 %14
+               OpStore %16 %12
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  const auto env = SPV_ENV_UNIVERSAL_1_3;
+  const auto consumer = nullptr;
+  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+  ASSERT_TRUE(IsValid(env, context.get()));
+
+  FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
+
+  // Add synonym fact relating %50 and %12.
+  transformation_context.GetFactManager()->AddFact(MakeSynonymFact(50, 12),
+                                                   context.get());
+  // Add synonym fact relating %51 and %14.
+  transformation_context.GetFactManager()->AddFact(MakeSynonymFact(51, 14),
+                                                   context.get());
+
+  // Not legal because the index being replaced is a struct index.
+  ASSERT_FALSE(
+      TransformationReplaceIdWithSynonym(
+          MakeIdUseDescriptor(
+              12, MakeInstructionDescriptor(16, SpvOpAccessChain, 0), 1),
+          50)
+          .IsApplicable(context.get(), transformation_context));
+
+  // Fine to replace an index into a runtime array.
+  auto replacement1 = TransformationReplaceIdWithSynonym(
+      MakeIdUseDescriptor(
+          12, MakeInstructionDescriptor(16, SpvOpAccessChain, 0), 2),
+      50);
+  ASSERT_TRUE(replacement1.IsApplicable(context.get(), transformation_context));
+  replacement1.Apply(context.get(), &transformation_context);
+
+  // Fine to replace an index into a vector inside the runtime array.
+  auto replacement2 = TransformationReplaceIdWithSynonym(
+      MakeIdUseDescriptor(
+          14, MakeInstructionDescriptor(16, SpvOpAccessChain, 0), 3),
+      51);
+  ASSERT_TRUE(replacement2.IsApplicable(context.get(), transformation_context));
+  replacement2.Apply(context.get(), &transformation_context);
+
+  ASSERT_TRUE(IsValid(env, context.get()));
+
+  const std::string after_transformation = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main"
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 310
+               OpDecorate %8 ArrayStride 8
+               OpMemberDecorate %9 0 Offset 0
+               OpDecorate %9 BufferBlock
+               OpDecorate %11 DescriptorSet 0
+               OpDecorate %11 Binding 0
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %6 = OpTypeInt 32 1
+          %7 = OpTypeVector %6 2
+          %8 = OpTypeRuntimeArray %7
+          %9 = OpTypeStruct %8
+         %10 = OpTypePointer Uniform %9
+         %11 = OpVariable %10 Uniform
+         %12 = OpConstant %6 0
+         %13 = OpTypeInt 32 0
+         %14 = OpConstant %13 0
+         %15 = OpTypePointer Uniform %6
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+         %50 = OpCopyObject %6 %12
+         %51 = OpCopyObject %13 %14
+         %16 = OpAccessChain %15 %11 %12 %50 %51
+               OpStore %16 %12
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
+}
+
 }  // namespace
 }  // namespace fuzz
 }  // namespace spvtools
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_set_function_control_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_set_function_control_test.cpp
index 536e965..be7f2be 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_set_function_control_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_set_function_control_test.cpp
@@ -118,41 +118,48 @@
   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // %36 is not a function
   ASSERT_FALSE(TransformationSetFunctionControl(36, SpvFunctionControlMaskNone)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   // Cannot add the Pure function control to %4 as it did not already have it
   ASSERT_FALSE(TransformationSetFunctionControl(4, SpvFunctionControlPureMask)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   // Cannot add the Const function control to %21 as it did not already
   // have it
   ASSERT_FALSE(TransformationSetFunctionControl(21, SpvFunctionControlConstMask)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Set to None, removing Const
   TransformationSetFunctionControl transformation1(11,
                                                    SpvFunctionControlMaskNone);
-  ASSERT_TRUE(transformation1.IsApplicable(context.get(), fact_manager));
-  transformation1.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation1.IsApplicable(context.get(), transformation_context));
+  transformation1.Apply(context.get(), &transformation_context);
 
   // Set to Inline; silly to do it on an entry point, but it is allowed
   TransformationSetFunctionControl transformation2(
       4, SpvFunctionControlInlineMask);
-  ASSERT_TRUE(transformation2.IsApplicable(context.get(), fact_manager));
-  transformation2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation2.IsApplicable(context.get(), transformation_context));
+  transformation2.Apply(context.get(), &transformation_context);
 
   // Set to Pure, removing DontInline
   TransformationSetFunctionControl transformation3(17,
                                                    SpvFunctionControlPureMask);
-  ASSERT_TRUE(transformation3.IsApplicable(context.get(), fact_manager));
-  transformation3.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation3.IsApplicable(context.get(), transformation_context));
+  transformation3.Apply(context.get(), &transformation_context);
 
   // Change from Inline to DontInline
   TransformationSetFunctionControl transformation4(
       13, SpvFunctionControlDontInlineMask);
-  ASSERT_TRUE(transformation4.IsApplicable(context.get(), fact_manager));
-  transformation4.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation4.IsApplicable(context.get(), transformation_context));
+  transformation4.Apply(context.get(), &transformation_context);
 
   std::string after_transformation = R"(
                OpCapability Shader
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_set_loop_control_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_set_loop_control_test.cpp
index 83953ec..531aa7a 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_set_loop_control_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_set_loop_control_test.cpp
@@ -256,6 +256,9 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // These are the loop headers together with the selection controls of their
   // merge instructions:
@@ -275,310 +278,310 @@
   // 2 5 90 4 7 14
 
   ASSERT_TRUE(TransformationSetLoopControl(10, SpvLoopControlMaskNone, 0, 0)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationSetLoopControl(10, SpvLoopControlUnrollMask, 0, 0)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(
       TransformationSetLoopControl(10, SpvLoopControlDontUnrollMask, 0, 0)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationSetLoopControl(
                    10, SpvLoopControlDependencyInfiniteMask, 0, 0)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationSetLoopControl(10, SpvLoopControlDependencyLengthMask, 0, 0)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationSetLoopControl(10, SpvLoopControlMinIterationsMask, 0, 0)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationSetLoopControl(10, SpvLoopControlMaxIterationsMask, 0, 0)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationSetLoopControl(
                    10, SpvLoopControlIterationMultipleMask, 0, 0)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(
       TransformationSetLoopControl(10, SpvLoopControlPeelCountMask, 3, 0)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationSetLoopControl(10, SpvLoopControlPeelCountMask, 3, 3)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(
       TransformationSetLoopControl(10, SpvLoopControlPartialCountMask, 0, 3)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationSetLoopControl(10, SpvLoopControlPartialCountMask, 3, 3)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationSetLoopControl(
                   10,
                   SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask,
                   3, 3)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationSetLoopControl(10,
                                            SpvLoopControlUnrollMask |
                                                SpvLoopControlPeelCountMask |
                                                SpvLoopControlPartialCountMask,
                                            3, 3)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationSetLoopControl(10,
                                             SpvLoopControlDontUnrollMask |
                                                 SpvLoopControlPeelCountMask |
                                                 SpvLoopControlPartialCountMask,
                                             3, 3)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   ASSERT_TRUE(TransformationSetLoopControl(23, SpvLoopControlMaskNone, 0, 0)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationSetLoopControl(23, SpvLoopControlUnrollMask, 0, 0)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(
       TransformationSetLoopControl(23, SpvLoopControlDontUnrollMask, 0, 0)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationSetLoopControl(
                   23,
                   SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask,
                   3, 3)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationSetLoopControl(23, SpvLoopControlMaxIterationsMask, 2, 3)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   ASSERT_TRUE(TransformationSetLoopControl(33, SpvLoopControlMaskNone, 0, 0)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationSetLoopControl(33, SpvLoopControlUnrollMask, 0, 0)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(
       TransformationSetLoopControl(33, SpvLoopControlDontUnrollMask, 0, 0)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationSetLoopControl(33, SpvLoopControlMinIterationsMask, 0, 0)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(
       TransformationSetLoopControl(
           33, SpvLoopControlUnrollMask | SpvLoopControlPeelCountMask, 5, 0)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationSetLoopControl(33,
                                             SpvLoopControlDontUnrollMask |
                                                 SpvLoopControlPartialCountMask,
                                             0, 10)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   ASSERT_TRUE(TransformationSetLoopControl(43, SpvLoopControlMaskNone, 0, 0)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationSetLoopControl(43, SpvLoopControlUnrollMask, 0, 0)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(
       TransformationSetLoopControl(43, SpvLoopControlDontUnrollMask, 0, 0)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationSetLoopControl(
                   43,
                   SpvLoopControlMaskNone | SpvLoopControlDependencyInfiniteMask,
                   0, 0)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(
       TransformationSetLoopControl(
           43, SpvLoopControlUnrollMask | SpvLoopControlDependencyInfiniteMask,
           0, 0)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(
       TransformationSetLoopControl(
           43,
           SpvLoopControlDontUnrollMask | SpvLoopControlDependencyInfiniteMask,
           0, 0)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationSetLoopControl(43,
                                    SpvLoopControlDependencyInfiniteMask |
                                        SpvLoopControlDependencyLengthMask,
                                    0, 0)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(
       TransformationSetLoopControl(
           43, SpvLoopControlUnrollMask | SpvLoopControlPeelCountMask, 5, 0)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   ASSERT_TRUE(TransformationSetLoopControl(53, SpvLoopControlMaskNone, 0, 0)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationSetLoopControl(53, SpvLoopControlUnrollMask, 0, 0)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(
       TransformationSetLoopControl(53, SpvLoopControlDontUnrollMask, 0, 0)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationSetLoopControl(53, SpvLoopControlMaxIterationsMask, 0, 0)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(
       TransformationSetLoopControl(
           53, SpvLoopControlMaskNone | SpvLoopControlDependencyLengthMask, 0, 0)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationSetLoopControl(
           53, SpvLoopControlUnrollMask | SpvLoopControlDependencyInfiniteMask,
           0, 0)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(
       TransformationSetLoopControl(
           53, SpvLoopControlDontUnrollMask | SpvLoopControlDependencyLengthMask,
           0, 0)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationSetLoopControl(53,
                                    SpvLoopControlDependencyInfiniteMask |
                                        SpvLoopControlDependencyLengthMask,
                                    0, 0)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(
       TransformationSetLoopControl(
           53,
           SpvLoopControlUnrollMask | SpvLoopControlDependencyLengthMask |
               SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask,
           5, 3)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   ASSERT_TRUE(TransformationSetLoopControl(63, SpvLoopControlMaskNone, 0, 0)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationSetLoopControl(63, SpvLoopControlUnrollMask, 0, 0)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(
       TransformationSetLoopControl(63, SpvLoopControlDontUnrollMask, 0, 0)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationSetLoopControl(63,
                                            SpvLoopControlUnrollMask |
                                                SpvLoopControlMinIterationsMask |
                                                SpvLoopControlPeelCountMask |
                                                SpvLoopControlPartialCountMask,
                                            5, 3)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationSetLoopControl(63,
                                            SpvLoopControlUnrollMask |
                                                SpvLoopControlMinIterationsMask |
                                                SpvLoopControlPeelCountMask,
                                            23, 0)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationSetLoopControl(
                    63,
                    SpvLoopControlUnrollMask | SpvLoopControlMinIterationsMask |
                        SpvLoopControlPeelCountMask,
                    2, 23)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   ASSERT_TRUE(TransformationSetLoopControl(73, SpvLoopControlMaskNone, 0, 0)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationSetLoopControl(73, SpvLoopControlUnrollMask, 0, 0)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(
       TransformationSetLoopControl(73, SpvLoopControlDontUnrollMask, 0, 0)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationSetLoopControl(
                    73,
                    SpvLoopControlUnrollMask | SpvLoopControlMinIterationsMask |
                        SpvLoopControlPeelCountMask |
                        SpvLoopControlPartialCountMask,
                    5, 3)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationSetLoopControl(73,
                                            SpvLoopControlUnrollMask |
                                                SpvLoopControlMaxIterationsMask |
                                                SpvLoopControlPeelCountMask,
                                            23, 0)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationSetLoopControl(
                    73,
                    SpvLoopControlUnrollMask | SpvLoopControlMaxIterationsMask |
                        SpvLoopControlPeelCountMask,
                    2, 23)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   ASSERT_TRUE(TransformationSetLoopControl(83, SpvLoopControlMaskNone, 0, 0)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationSetLoopControl(83, SpvLoopControlUnrollMask, 0, 0)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(
       TransformationSetLoopControl(83, SpvLoopControlDontUnrollMask, 0, 0)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationSetLoopControl(
                    83,
                    SpvLoopControlUnrollMask | SpvLoopControlMinIterationsMask |
                        SpvLoopControlPeelCountMask |
                        SpvLoopControlPartialCountMask,
                    5, 3)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(
       TransformationSetLoopControl(83,
                                    SpvLoopControlUnrollMask |
                                        SpvLoopControlIterationMultipleMask |
                                        SpvLoopControlPeelCountMask,
                                    23, 0)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationSetLoopControl(83,
                                    SpvLoopControlUnrollMask |
                                        SpvLoopControlIterationMultipleMask |
                                        SpvLoopControlPeelCountMask,
                                    2, 23)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   ASSERT_TRUE(TransformationSetLoopControl(93, SpvLoopControlMaskNone, 0, 0)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationSetLoopControl(93, SpvLoopControlUnrollMask, 0, 0)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(
       TransformationSetLoopControl(93, SpvLoopControlDontUnrollMask, 0, 0)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(
       TransformationSetLoopControl(93, SpvLoopControlPeelCountMask, 8, 0)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationSetLoopControl(93, SpvLoopControlPeelCountMask, 8, 8)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(
       TransformationSetLoopControl(93, SpvLoopControlPartialCountMask, 0, 8)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationSetLoopControl(
                   93,
                   SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask,
                   16, 8)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
 
   ASSERT_TRUE(TransformationSetLoopControl(103, SpvLoopControlMaskNone, 0, 0)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationSetLoopControl(103, SpvLoopControlUnrollMask, 0, 0)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(
       TransformationSetLoopControl(103, SpvLoopControlDontUnrollMask, 0, 0)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(
       TransformationSetLoopControl(103, SpvLoopControlPartialCountMask, 0, 60)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationSetLoopControl(103,
                                             SpvLoopControlDontUnrollMask |
                                                 SpvLoopControlPartialCountMask,
                                             0, 60)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   ASSERT_TRUE(TransformationSetLoopControl(113, SpvLoopControlMaskNone, 0, 0)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationSetLoopControl(113, SpvLoopControlUnrollMask, 0, 0)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(
       TransformationSetLoopControl(113, SpvLoopControlDontUnrollMask, 0, 0)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(
       TransformationSetLoopControl(113, SpvLoopControlPeelCountMask, 12, 0)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationSetLoopControl(
           113,
           SpvLoopControlIterationMultipleMask | SpvLoopControlPeelCountMask, 12,
           0)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   ASSERT_TRUE(TransformationSetLoopControl(123, SpvLoopControlMaskNone, 0, 0)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationSetLoopControl(123, SpvLoopControlUnrollMask, 0, 0)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(
       TransformationSetLoopControl(123, SpvLoopControlDontUnrollMask, 0, 0)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(
       TransformationSetLoopControl(
           123,
@@ -586,72 +589,72 @@
               SpvLoopControlIterationMultipleMask |
               SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask,
           7, 8)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationSetLoopControl(123,
                                            SpvLoopControlUnrollMask |
                                                SpvLoopControlMinIterationsMask |
                                                SpvLoopControlMaxIterationsMask |
                                                SpvLoopControlPartialCountMask,
                                            0, 9)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationSetLoopControl(
                    123,
                    SpvLoopControlUnrollMask | SpvLoopControlMinIterationsMask |
                        SpvLoopControlMaxIterationsMask |
                        SpvLoopControlPartialCountMask,
                    7, 9)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationSetLoopControl(
           123,
           SpvLoopControlDontUnrollMask | SpvLoopControlMinIterationsMask |
               SpvLoopControlMaxIterationsMask | SpvLoopControlPartialCountMask,
           7, 9)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   TransformationSetLoopControl(10,
                                SpvLoopControlUnrollMask |
                                    SpvLoopControlPeelCountMask |
                                    SpvLoopControlPartialCountMask,
                                3, 3)
-      .Apply(context.get(), &fact_manager);
+      .Apply(context.get(), &transformation_context);
   TransformationSetLoopControl(23, SpvLoopControlDontUnrollMask, 0, 0)
-      .Apply(context.get(), &fact_manager);
+      .Apply(context.get(), &transformation_context);
   TransformationSetLoopControl(33, SpvLoopControlUnrollMask, 0, 0)
-      .Apply(context.get(), &fact_manager);
+      .Apply(context.get(), &transformation_context);
   TransformationSetLoopControl(
       43, SpvLoopControlDontUnrollMask | SpvLoopControlDependencyInfiniteMask,
       0, 0)
-      .Apply(context.get(), &fact_manager);
+      .Apply(context.get(), &transformation_context);
   TransformationSetLoopControl(53, SpvLoopControlMaskNone, 0, 0)
-      .Apply(context.get(), &fact_manager);
+      .Apply(context.get(), &transformation_context);
   TransformationSetLoopControl(63,
                                SpvLoopControlUnrollMask |
                                    SpvLoopControlMinIterationsMask |
                                    SpvLoopControlPeelCountMask,
                                23, 0)
-      .Apply(context.get(), &fact_manager);
+      .Apply(context.get(), &transformation_context);
   TransformationSetLoopControl(73,
                                SpvLoopControlUnrollMask |
                                    SpvLoopControlMaxIterationsMask |
                                    SpvLoopControlPeelCountMask,
                                23, 0)
-      .Apply(context.get(), &fact_manager);
+      .Apply(context.get(), &transformation_context);
   TransformationSetLoopControl(83, SpvLoopControlDontUnrollMask, 0, 0)
-      .Apply(context.get(), &fact_manager);
+      .Apply(context.get(), &transformation_context);
   TransformationSetLoopControl(
       93, SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask, 16, 8)
-      .Apply(context.get(), &fact_manager);
+      .Apply(context.get(), &transformation_context);
   TransformationSetLoopControl(103, SpvLoopControlPartialCountMask, 0, 60)
-      .Apply(context.get(), &fact_manager);
+      .Apply(context.get(), &transformation_context);
   TransformationSetLoopControl(113, SpvLoopControlPeelCountMask, 12, 0)
-      .Apply(context.get(), &fact_manager);
+      .Apply(context.get(), &transformation_context);
   TransformationSetLoopControl(
       123,
       SpvLoopControlUnrollMask | SpvLoopControlMinIterationsMask |
           SpvLoopControlMaxIterationsMask | SpvLoopControlPartialCountMask,
       0, 9)
-      .Apply(context.get(), &fact_manager);
+      .Apply(context.get(), &transformation_context);
 
   std::string after_transformation = R"(
                OpCapability Shader
@@ -942,25 +945,28 @@
       BuildModule(SPV_ENV_UNIVERSAL_1_5, consumer, shader, kFuzzAssembleOption);
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationSetLoopControl set_peel_and_partial(
       10, SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask, 4, 4);
 
   // PeelCount and PartialCount were introduced in SPIRV 1.4, so are not valid
   // in the context of older versions.
-  ASSERT_FALSE(
-      set_peel_and_partial.IsApplicable(context_1_0.get(), fact_manager));
-  ASSERT_FALSE(
-      set_peel_and_partial.IsApplicable(context_1_1.get(), fact_manager));
-  ASSERT_FALSE(
-      set_peel_and_partial.IsApplicable(context_1_2.get(), fact_manager));
-  ASSERT_FALSE(
-      set_peel_and_partial.IsApplicable(context_1_3.get(), fact_manager));
+  ASSERT_FALSE(set_peel_and_partial.IsApplicable(context_1_0.get(),
+                                                 transformation_context));
+  ASSERT_FALSE(set_peel_and_partial.IsApplicable(context_1_1.get(),
+                                                 transformation_context));
+  ASSERT_FALSE(set_peel_and_partial.IsApplicable(context_1_2.get(),
+                                                 transformation_context));
+  ASSERT_FALSE(set_peel_and_partial.IsApplicable(context_1_3.get(),
+                                                 transformation_context));
 
-  ASSERT_TRUE(
-      set_peel_and_partial.IsApplicable(context_1_4.get(), fact_manager));
-  ASSERT_TRUE(
-      set_peel_and_partial.IsApplicable(context_1_5.get(), fact_manager));
+  ASSERT_TRUE(set_peel_and_partial.IsApplicable(context_1_4.get(),
+                                                transformation_context));
+  ASSERT_TRUE(set_peel_and_partial.IsApplicable(context_1_5.get(),
+                                                transformation_context));
 }
 
 }  // namespace
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_set_memory_operands_mask_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_set_memory_operands_mask_test.cpp
index ad4dc25..c02d8d4 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_set_memory_operands_mask_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_set_memory_operands_mask_test.cpp
@@ -92,37 +92,41 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // Not OK: the instruction is not a memory access.
   ASSERT_FALSE(TransformationSetMemoryOperandsMask(
                    MakeInstructionDescriptor(21, SpvOpAccessChain, 0),
                    SpvMemoryAccessMaskNone, 0)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Not OK to remove Aligned
   ASSERT_FALSE(TransformationSetMemoryOperandsMask(
                    MakeInstructionDescriptor(147, SpvOpLoad, 0),
                    SpvMemoryAccessVolatileMask | SpvMemoryAccessNontemporalMask,
                    0)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   TransformationSetMemoryOperandsMask transformation1(
       MakeInstructionDescriptor(147, SpvOpLoad, 0),
       SpvMemoryAccessAlignedMask | SpvMemoryAccessVolatileMask, 0);
-  ASSERT_TRUE(transformation1.IsApplicable(context.get(), fact_manager));
-  transformation1.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation1.IsApplicable(context.get(), transformation_context));
+  transformation1.Apply(context.get(), &transformation_context);
 
   // Not OK to remove Aligned
   ASSERT_FALSE(TransformationSetMemoryOperandsMask(
                    MakeInstructionDescriptor(21, SpvOpCopyMemory, 0),
                    SpvMemoryAccessMaskNone, 0)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // OK: leaves the mask as is
   ASSERT_TRUE(TransformationSetMemoryOperandsMask(
                   MakeInstructionDescriptor(21, SpvOpCopyMemory, 0),
                   SpvMemoryAccessAlignedMask, 0)
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
 
   // OK: adds Nontemporal and Volatile
   TransformationSetMemoryOperandsMask transformation2(
@@ -130,41 +134,45 @@
       SpvMemoryAccessAlignedMask | SpvMemoryAccessNontemporalMask |
           SpvMemoryAccessVolatileMask,
       0);
-  ASSERT_TRUE(transformation2.IsApplicable(context.get(), fact_manager));
-  transformation2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation2.IsApplicable(context.get(), transformation_context));
+  transformation2.Apply(context.get(), &transformation_context);
 
   // Not OK to remove Volatile
   ASSERT_FALSE(TransformationSetMemoryOperandsMask(
                    MakeInstructionDescriptor(21, SpvOpCopyMemory, 1),
                    SpvMemoryAccessNontemporalMask, 0)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Not OK to add Aligned
   ASSERT_FALSE(TransformationSetMemoryOperandsMask(
                    MakeInstructionDescriptor(21, SpvOpCopyMemory, 1),
                    SpvMemoryAccessAlignedMask | SpvMemoryAccessVolatileMask, 0)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // OK: adds Nontemporal
   TransformationSetMemoryOperandsMask transformation3(
       MakeInstructionDescriptor(21, SpvOpCopyMemory, 1),
       SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 0);
-  ASSERT_TRUE(transformation3.IsApplicable(context.get(), fact_manager));
-  transformation3.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation3.IsApplicable(context.get(), transformation_context));
+  transformation3.Apply(context.get(), &transformation_context);
 
   // OK: adds Nontemporal and Volatile
   TransformationSetMemoryOperandsMask transformation4(
       MakeInstructionDescriptor(138, SpvOpCopyMemory, 0),
       SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 0);
-  ASSERT_TRUE(transformation4.IsApplicable(context.get(), fact_manager));
-  transformation4.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation4.IsApplicable(context.get(), transformation_context));
+  transformation4.Apply(context.get(), &transformation_context);
 
   // OK: removes Nontemporal, adds Volatile
   TransformationSetMemoryOperandsMask transformation5(
       MakeInstructionDescriptor(148, SpvOpStore, 0),
       SpvMemoryAccessVolatileMask, 0);
-  ASSERT_TRUE(transformation5.IsApplicable(context.get(), fact_manager));
-  transformation5.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation5.IsApplicable(context.get(), transformation_context));
+  transformation5.Apply(context.get(), &transformation_context);
 
   std::string after_transformation = R"(
                OpCapability Shader
@@ -306,6 +314,9 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   TransformationSetMemoryOperandsMask transformation1(
       MakeInstructionDescriptor(21, SpvOpCopyMemory, 0),
@@ -314,9 +325,10 @@
   ASSERT_FALSE(TransformationSetMemoryOperandsMask(
                    MakeInstructionDescriptor(21, SpvOpCopyMemory, 0),
                    SpvMemoryAccessVolatileMask, 1)
-                   .IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(transformation1.IsApplicable(context.get(), fact_manager));
-  transformation1.Apply(context.get(), &fact_manager);
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(
+      transformation1.IsApplicable(context.get(), transformation_context));
+  transformation1.Apply(context.get(), &transformation_context);
 
   TransformationSetMemoryOperandsMask transformation2(
       MakeInstructionDescriptor(21, SpvOpCopyMemory, 1),
@@ -325,9 +337,10 @@
   ASSERT_FALSE(TransformationSetMemoryOperandsMask(
                    MakeInstructionDescriptor(21, SpvOpCopyMemory, 1),
                    SpvMemoryAccessNontemporalMask, 0)
-                   .IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(transformation2.IsApplicable(context.get(), fact_manager));
-  transformation2.Apply(context.get(), &fact_manager);
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(
+      transformation2.IsApplicable(context.get(), transformation_context));
+  transformation2.Apply(context.get(), &transformation_context);
 
   TransformationSetMemoryOperandsMask transformation3(
       MakeInstructionDescriptor(138, SpvOpCopyMemory, 0),
@@ -337,27 +350,31 @@
                    MakeInstructionDescriptor(138, SpvOpCopyMemory, 0),
                    SpvMemoryAccessAlignedMask | SpvMemoryAccessNontemporalMask,
                    0)
-                   .IsApplicable(context.get(), fact_manager));
-  ASSERT_TRUE(transformation3.IsApplicable(context.get(), fact_manager));
-  transformation3.Apply(context.get(), &fact_manager);
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(
+      transformation3.IsApplicable(context.get(), transformation_context));
+  transformation3.Apply(context.get(), &transformation_context);
 
   TransformationSetMemoryOperandsMask transformation4(
       MakeInstructionDescriptor(138, SpvOpCopyMemory, 1),
       SpvMemoryAccessVolatileMask, 1);
-  ASSERT_TRUE(transformation4.IsApplicable(context.get(), fact_manager));
-  transformation4.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation4.IsApplicable(context.get(), transformation_context));
+  transformation4.Apply(context.get(), &transformation_context);
 
   TransformationSetMemoryOperandsMask transformation5(
       MakeInstructionDescriptor(147, SpvOpLoad, 0),
       SpvMemoryAccessVolatileMask | SpvMemoryAccessAlignedMask, 0);
-  ASSERT_TRUE(transformation5.IsApplicable(context.get(), fact_manager));
-  transformation5.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation5.IsApplicable(context.get(), transformation_context));
+  transformation5.Apply(context.get(), &transformation_context);
 
   TransformationSetMemoryOperandsMask transformation6(
       MakeInstructionDescriptor(148, SpvOpStore, 0), SpvMemoryAccessMaskNone,
       0);
-  ASSERT_TRUE(transformation6.IsApplicable(context.get(), fact_manager));
-  transformation6.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation6.IsApplicable(context.get(), transformation_context));
+  transformation6.Apply(context.get(), &transformation_context);
 
   std::string after_transformation = R"(
                OpCapability Shader
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_set_selection_control_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_set_selection_control_test.cpp
index 9696417..9afb89d 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_set_selection_control_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_set_selection_control_test.cpp
@@ -103,39 +103,46 @@
   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // %44 is not a block
   ASSERT_FALSE(
       TransformationSetSelectionControl(44, SpvSelectionControlFlattenMask)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   // %13 does not end with OpSelectionMerge
   ASSERT_FALSE(
       TransformationSetSelectionControl(13, SpvSelectionControlMaskNone)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   // %10 ends in OpLoopMerge, not OpSelectionMerge
   ASSERT_FALSE(
       TransformationSetSelectionControl(10, SpvSelectionControlMaskNone)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   TransformationSetSelectionControl transformation1(
       11, SpvSelectionControlDontFlattenMask);
-  ASSERT_TRUE(transformation1.IsApplicable(context.get(), fact_manager));
-  transformation1.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation1.IsApplicable(context.get(), transformation_context));
+  transformation1.Apply(context.get(), &transformation_context);
 
   TransformationSetSelectionControl transformation2(
       23, SpvSelectionControlFlattenMask);
-  ASSERT_TRUE(transformation2.IsApplicable(context.get(), fact_manager));
-  transformation2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation2.IsApplicable(context.get(), transformation_context));
+  transformation2.Apply(context.get(), &transformation_context);
 
   TransformationSetSelectionControl transformation3(
       31, SpvSelectionControlMaskNone);
-  ASSERT_TRUE(transformation3.IsApplicable(context.get(), fact_manager));
-  transformation3.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation3.IsApplicable(context.get(), transformation_context));
+  transformation3.Apply(context.get(), &transformation_context);
 
   TransformationSetSelectionControl transformation4(
       31, SpvSelectionControlFlattenMask);
-  ASSERT_TRUE(transformation4.IsApplicable(context.get(), fact_manager));
-  transformation4.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation4.IsApplicable(context.get(), transformation_context));
+  transformation4.Apply(context.get(), &transformation_context);
 
   std::string after_transformation = R"(
                OpCapability Shader
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_split_block_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_split_block_test.cpp
index 09007a5..30bac02 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_split_block_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_split_block_test.cpp
@@ -89,57 +89,60 @@
   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // No split before OpVariable
   ASSERT_FALSE(TransformationSplitBlock(
                    MakeInstructionDescriptor(8, SpvOpVariable, 0), 100)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationSplitBlock(
                    MakeInstructionDescriptor(8, SpvOpVariable, 1), 100)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // No split before OpLabel
   ASSERT_FALSE(TransformationSplitBlock(
                    MakeInstructionDescriptor(14, SpvOpLabel, 0), 100)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // No split if base instruction is outside a function
   ASSERT_FALSE(
       TransformationSplitBlock(MakeInstructionDescriptor(1, SpvOpLabel, 0), 100)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationSplitBlock(
                    MakeInstructionDescriptor(1, SpvOpExecutionMode, 0), 100)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // No split if block is loop header
   ASSERT_FALSE(
       TransformationSplitBlock(MakeInstructionDescriptor(27, SpvOpPhi, 0), 100)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationSplitBlock(MakeInstructionDescriptor(27, SpvOpPhi, 1), 100)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   // No split if base instruction does not exist
   ASSERT_FALSE(
       TransformationSplitBlock(MakeInstructionDescriptor(88, SpvOpIAdd, 0), 100)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationSplitBlock(
                    MakeInstructionDescriptor(88, SpvOpIMul, 22), 100)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // No split if too many instructions with the desired opcode are skipped
   ASSERT_FALSE(
       TransformationSplitBlock(
           MakeInstructionDescriptor(18, SpvOpBranchConditional, 1), 100)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   // No split if id in use
   ASSERT_FALSE(TransformationSplitBlock(
                    MakeInstructionDescriptor(18, SpvOpSLessThan, 0), 27)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationSplitBlock(
                    MakeInstructionDescriptor(18, SpvOpSLessThan, 0), 14)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationSplitBlockTest, SplitBlockSeveralTimes) {
@@ -199,11 +202,14 @@
   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   auto split_1 = TransformationSplitBlock(
       MakeInstructionDescriptor(5, SpvOpStore, 0), 100);
-  ASSERT_TRUE(split_1.IsApplicable(context.get(), fact_manager));
-  split_1.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(split_1.IsApplicable(context.get(), transformation_context));
+  split_1.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_split_1 = R"(
@@ -250,8 +256,8 @@
 
   auto split_2 = TransformationSplitBlock(
       MakeInstructionDescriptor(11, SpvOpStore, 0), 101);
-  ASSERT_TRUE(split_2.IsApplicable(context.get(), fact_manager));
-  split_2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(split_2.IsApplicable(context.get(), transformation_context));
+  split_2.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_split_2 = R"(
@@ -300,8 +306,8 @@
 
   auto split_3 = TransformationSplitBlock(
       MakeInstructionDescriptor(14, SpvOpLoad, 0), 102);
-  ASSERT_TRUE(split_3.IsApplicable(context.get(), fact_manager));
-  split_3.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(split_3.IsApplicable(context.get(), transformation_context));
+  split_3.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_split_3 = R"(
@@ -412,21 +418,24 @@
   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // Illegal to split between the merge and the conditional branch.
   ASSERT_FALSE(
       TransformationSplitBlock(
           MakeInstructionDescriptor(14, SpvOpBranchConditional, 0), 100)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationSplitBlock(
           MakeInstructionDescriptor(12, SpvOpBranchConditional, 0), 100)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   auto split = TransformationSplitBlock(
       MakeInstructionDescriptor(14, SpvOpSelectionMerge, 0), 100);
-  ASSERT_TRUE(split.IsApplicable(context.get(), fact_manager));
-  split.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(split.IsApplicable(context.get(), transformation_context));
+  split.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_split = R"(
@@ -541,19 +550,22 @@
   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // Illegal to split between the merge and the conditional branch.
   ASSERT_FALSE(TransformationSplitBlock(
                    MakeInstructionDescriptor(9, SpvOpSwitch, 0), 100)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationSplitBlock(
                    MakeInstructionDescriptor(15, SpvOpSwitch, 0), 100)
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   auto split = TransformationSplitBlock(
       MakeInstructionDescriptor(9, SpvOpSelectionMerge, 0), 100);
-  ASSERT_TRUE(split.IsApplicable(context.get(), fact_manager));
-  split.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(split.IsApplicable(context.get(), transformation_context));
+  split.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_split = R"(
@@ -674,18 +686,21 @@
   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // We cannot split before OpPhi instructions, since the number of incoming
   // blocks may not appropriately match after splitting.
   ASSERT_FALSE(
       TransformationSplitBlock(MakeInstructionDescriptor(26, SpvOpPhi, 0), 100)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationSplitBlock(MakeInstructionDescriptor(27, SpvOpPhi, 0), 100)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationSplitBlock(MakeInstructionDescriptor(27, SpvOpPhi, 1), 100)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationSplitBlockTest, SplitOpPhiWithSinglePredecessor) {
@@ -726,16 +741,19 @@
   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   ASSERT_TRUE(
       TransformationSplitBlock(MakeInstructionDescriptor(21, SpvOpPhi, 0), 100)
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   // An equivalent transformation to the above, just described with respect to a
   // different base instruction.
   auto split =
       TransformationSplitBlock(MakeInstructionDescriptor(20, SpvOpPhi, 0), 100);
-  ASSERT_TRUE(split.IsApplicable(context.get(), fact_manager));
-  split.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(split.IsApplicable(context.get(), transformation_context));
+  split.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
   std::string after_split = R"(
@@ -805,18 +823,21 @@
   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // Record the fact that block 8 is dead.
-  fact_manager.AddFactBlockIsDead(8);
+  transformation_context.GetFactManager()->AddFactBlockIsDead(8);
 
   auto split = TransformationSplitBlock(
       MakeInstructionDescriptor(8, SpvOpBranch, 0), 100);
-  ASSERT_TRUE(split.IsApplicable(context.get(), fact_manager));
-  split.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(split.IsApplicable(context.get(), transformation_context));
+  split.Apply(context.get(), &transformation_context);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  ASSERT_TRUE(fact_manager.BlockIsDead(8));
-  ASSERT_TRUE(fact_manager.BlockIsDead(100));
+  ASSERT_TRUE(transformation_context.GetFactManager()->BlockIsDead(8));
+  ASSERT_TRUE(transformation_context.GetFactManager()->BlockIsDead(100));
 
   std::string after_split = R"(
                OpCapability Shader
@@ -845,6 +866,62 @@
   ASSERT_TRUE(IsEqual(env, after_split, context.get()));
 }
 
+TEST(TransformationSplitBlockTest, DoNotSplitUseOfOpSampledImage) {
+  // This checks that we cannot split the definition of an OpSampledImage
+  // from its use.
+  std::string shader = R"(
+               OpCapability Shader
+               OpCapability SampledBuffer
+               OpCapability ImageBuffer
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %2 "main" %40 %41
+               OpExecutionMode %2 OriginUpperLeft
+               OpSource GLSL 450
+               OpDecorate %40 DescriptorSet 0
+               OpDecorate %40 Binding 69
+               OpDecorate %41 DescriptorSet 0
+               OpDecorate %41 Binding 1
+         %54 = OpTypeFloat 32
+         %76 = OpTypeVector %54 4
+         %55 = OpConstant %54 0
+         %56 = OpTypeVector %54 3
+         %94 = OpTypeVector %54 2
+        %112 = OpConstantComposite %94 %55 %55
+         %57 = OpConstantComposite %56 %55 %55 %55
+         %15 = OpTypeImage %54 2D 2 0 0 1 Unknown
+        %114 = OpTypePointer UniformConstant %15
+         %38 = OpTypeSampler
+        %125 = OpTypePointer UniformConstant %38
+        %132 = OpTypeVoid
+        %133 = OpTypeFunction %132
+         %45 = OpTypeSampledImage %15
+         %40 = OpVariable %114 UniformConstant
+         %41 = OpVariable %125 UniformConstant
+          %2 = OpFunction %132 None %133
+        %164 = OpLabel
+        %184 = OpLoad %15 %40
+        %213 = OpLoad %38 %41
+        %216 = OpSampledImage %45 %184 %213
+        %217 = OpImageSampleImplicitLod %76 %216 %112 Bias %55
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  const auto env = SPV_ENV_UNIVERSAL_1_3;
+  const auto consumer = nullptr;
+  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+
+  FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
+
+  auto split = TransformationSplitBlock(
+      MakeInstructionDescriptor(217, SpvOpImageSampleImplicitLod, 0), 500);
+  ASSERT_FALSE(split.IsApplicable(context.get(), transformation_context));
+}
+
 }  // namespace
 }  // namespace fuzz
 }  // namespace spvtools
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_store_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_store_test.cpp
index 3fb9b61..067a5a1 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_store_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_store_test.cpp
@@ -94,16 +94,26 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
-  fact_manager.AddFactValueOfPointeeIsIrrelevant(27);
-  fact_manager.AddFactValueOfPointeeIsIrrelevant(11);
-  fact_manager.AddFactValueOfPointeeIsIrrelevant(46);
-  fact_manager.AddFactValueOfPointeeIsIrrelevant(16);
-  fact_manager.AddFactValueOfPointeeIsIrrelevant(52);
-  fact_manager.AddFactValueOfPointeeIsIrrelevant(81);
-  fact_manager.AddFactValueOfPointeeIsIrrelevant(82);
+  transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
+      27);
+  transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
+      11);
+  transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
+      46);
+  transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
+      16);
+  transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
+      52);
+  transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
+      81);
+  transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
+      82);
 
-  fact_manager.AddFactBlockIsDead(36);
+  transformation_context.GetFactManager()->AddFactBlockIsDead(36);
 
   // Variables with pointee types:
   //  52 - ptr_to(7)
@@ -139,90 +149,91 @@
   // Bad: attempt to store to 11 from outside its function
   ASSERT_FALSE(TransformationStore(
                    11, 80, MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: pointer is not available
   ASSERT_FALSE(TransformationStore(
                    81, 80, MakeInstructionDescriptor(45, SpvOpCopyObject, 0))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: attempt to insert before OpVariable
   ASSERT_FALSE(TransformationStore(
                    52, 24, MakeInstructionDescriptor(27, SpvOpVariable, 0))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: pointer id does not exist
   ASSERT_FALSE(TransformationStore(
                    1000, 24, MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: pointer id exists but does not have a type
   ASSERT_FALSE(TransformationStore(
                    5, 24, MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: pointer id exists and has a type, but is not a pointer
   ASSERT_FALSE(TransformationStore(
                    24, 24, MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: attempt to store to a null pointer
   ASSERT_FALSE(TransformationStore(
                    60, 24, MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: attempt to store to an undefined pointer
   ASSERT_FALSE(TransformationStore(
                    61, 21, MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: %82 is not available at the program point
   ASSERT_FALSE(
       TransformationStore(82, 80, MakeInstructionDescriptor(37, SpvOpReturn, 0))
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   // Bad: value id does not exist
   ASSERT_FALSE(TransformationStore(
                    27, 1000, MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: value id exists but does not have a type
   ASSERT_FALSE(TransformationStore(
                    27, 15, MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: value id exists but has the wrong type
   ASSERT_FALSE(TransformationStore(
                    27, 14, MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: attempt to store to read-only variable
   ASSERT_FALSE(TransformationStore(
                    92, 93, MakeInstructionDescriptor(40, SpvOpAccessChain, 0))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: value is not available
   ASSERT_FALSE(TransformationStore(
                    27, 95, MakeInstructionDescriptor(40, SpvOpAccessChain, 0))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: variable being stored to does not have an irrelevant pointee value,
   // and the store is not in a dead block.
   ASSERT_FALSE(TransformationStore(
                    20, 95, MakeInstructionDescriptor(45, SpvOpCopyObject, 0))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // The described instruction does not exist.
   ASSERT_FALSE(TransformationStore(
                    27, 80, MakeInstructionDescriptor(1000, SpvOpAccessChain, 0))
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   {
     // Store to irrelevant variable from dead block.
     TransformationStore transformation(
         27, 80, MakeInstructionDescriptor(38, SpvOpAccessChain, 0));
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
     ASSERT_TRUE(IsValid(env, context.get()));
   }
 
@@ -230,8 +241,9 @@
     // Store to irrelevant variable from live block.
     TransformationStore transformation(
         11, 95, MakeInstructionDescriptor(95, SpvOpReturnValue, 0));
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
     ASSERT_TRUE(IsValid(env, context.get()));
   }
 
@@ -239,8 +251,9 @@
     // Store to irrelevant variable from live block.
     TransformationStore transformation(
         46, 80, MakeInstructionDescriptor(95, SpvOpReturnValue, 0));
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
     ASSERT_TRUE(IsValid(env, context.get()));
   }
 
@@ -248,8 +261,9 @@
     // Store to irrelevant variable from live block.
     TransformationStore transformation(
         16, 21, MakeInstructionDescriptor(95, SpvOpReturnValue, 0));
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
     ASSERT_TRUE(IsValid(env, context.get()));
   }
 
@@ -257,8 +271,9 @@
     // Store to non-irrelevant variable from dead block.
     TransformationStore transformation(
         53, 21, MakeInstructionDescriptor(38, SpvOpAccessChain, 0));
-    ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
-    transformation.Apply(context.get(), &fact_manager);
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    transformation.Apply(context.get(), &transformation_context);
     ASSERT_TRUE(IsValid(env, context.get()));
   }
 
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_swap_commutable_operands_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_swap_commutable_operands_test.cpp
index f0591cf..c213dfe 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_swap_commutable_operands_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_swap_commutable_operands_test.cpp
@@ -111,113 +111,140 @@
   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  FactManager factManager;
+  FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // Tests existing commutative instructions
   auto instructionDescriptor = MakeInstructionDescriptor(22, SpvOpIAdd, 0);
   auto transformation =
       TransformationSwapCommutableOperands(instructionDescriptor);
-  ASSERT_TRUE(transformation.IsApplicable(context.get(), factManager));
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor = MakeInstructionDescriptor(28, SpvOpIMul, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
-  ASSERT_TRUE(transformation.IsApplicable(context.get(), factManager));
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor = MakeInstructionDescriptor(42, SpvOpFAdd, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
-  ASSERT_TRUE(transformation.IsApplicable(context.get(), factManager));
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor = MakeInstructionDescriptor(48, SpvOpFMul, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
-  ASSERT_TRUE(transformation.IsApplicable(context.get(), factManager));
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor = MakeInstructionDescriptor(66, SpvOpDot, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
-  ASSERT_TRUE(transformation.IsApplicable(context.get(), factManager));
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
 
   // Tests existing non-commutative instructions
   instructionDescriptor = MakeInstructionDescriptor(1, SpvOpExtInstImport, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor = MakeInstructionDescriptor(5, SpvOpLabel, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor = MakeInstructionDescriptor(8, SpvOpConstant, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor = MakeInstructionDescriptor(11, SpvOpVariable, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor =
       MakeInstructionDescriptor(14, SpvOpConstantComposite, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 
   // Tests the base instruction id not existing
   instructionDescriptor = MakeInstructionDescriptor(67, SpvOpIAddCarry, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor = MakeInstructionDescriptor(68, SpvOpIEqual, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor = MakeInstructionDescriptor(69, SpvOpINotEqual, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor = MakeInstructionDescriptor(70, SpvOpFOrdEqual, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor = MakeInstructionDescriptor(71, SpvOpPtrEqual, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 
   // Tests there being no instruction with the desired opcode after the base
   // instruction id
   instructionDescriptor = MakeInstructionDescriptor(24, SpvOpIAdd, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor = MakeInstructionDescriptor(38, SpvOpIMul, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor = MakeInstructionDescriptor(45, SpvOpFAdd, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor = MakeInstructionDescriptor(66, SpvOpFMul, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 
   // Tests there being an instruction with the desired opcode after the base
   // instruction id, but the skip count associated with the instruction
   // descriptor being so high.
   instructionDescriptor = MakeInstructionDescriptor(11, SpvOpIAdd, 100);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor = MakeInstructionDescriptor(16, SpvOpIMul, 100);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor = MakeInstructionDescriptor(23, SpvOpFAdd, 100);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor = MakeInstructionDescriptor(32, SpvOpFMul, 100);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor = MakeInstructionDescriptor(37, SpvOpDot, 100);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationSwapCommutableOperandsTest, ApplyTest) {
@@ -311,28 +338,31 @@
   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  FactManager factManager;
+  FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   auto instructionDescriptor = MakeInstructionDescriptor(22, SpvOpIAdd, 0);
   auto transformation =
       TransformationSwapCommutableOperands(instructionDescriptor);
-  transformation.Apply(context.get(), &factManager);
+  transformation.Apply(context.get(), &transformation_context);
 
   instructionDescriptor = MakeInstructionDescriptor(28, SpvOpIMul, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
-  transformation.Apply(context.get(), &factManager);
+  transformation.Apply(context.get(), &transformation_context);
 
   instructionDescriptor = MakeInstructionDescriptor(42, SpvOpFAdd, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
-  transformation.Apply(context.get(), &factManager);
+  transformation.Apply(context.get(), &transformation_context);
 
   instructionDescriptor = MakeInstructionDescriptor(48, SpvOpFMul, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
-  transformation.Apply(context.get(), &factManager);
+  transformation.Apply(context.get(), &transformation_context);
 
   instructionDescriptor = MakeInstructionDescriptor(66, SpvOpDot, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
-  transformation.Apply(context.get(), &factManager);
+  transformation.Apply(context.get(), &transformation_context);
 
   std::string variantShader = R"(
                OpCapability Shader
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_toggle_access_chain_instruction_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_toggle_access_chain_instruction_test.cpp
index 98e0a64..b20f59e 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_toggle_access_chain_instruction_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_toggle_access_chain_instruction_test.cpp
@@ -111,78 +111,93 @@
   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  FactManager factManager;
+  FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // Tests existing access chain instructions
   auto instructionDescriptor =
       MakeInstructionDescriptor(18, SpvOpAccessChain, 0);
   auto transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
-  ASSERT_TRUE(transformation.IsApplicable(context.get(), factManager));
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor =
       MakeInstructionDescriptor(20, SpvOpInBoundsAccessChain, 0);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
-  ASSERT_TRUE(transformation.IsApplicable(context.get(), factManager));
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor = MakeInstructionDescriptor(24, SpvOpAccessChain, 0);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
-  ASSERT_TRUE(transformation.IsApplicable(context.get(), factManager));
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor =
       MakeInstructionDescriptor(26, SpvOpInBoundsAccessChain, 0);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
-  ASSERT_TRUE(transformation.IsApplicable(context.get(), factManager));
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
 
   // Tests existing non-access chain instructions
   instructionDescriptor = MakeInstructionDescriptor(1, SpvOpExtInstImport, 0);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor = MakeInstructionDescriptor(5, SpvOpLabel, 0);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor =
       MakeInstructionDescriptor(14, SpvOpConstantComposite, 0);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 
   // Tests the base instruction id not existing
   instructionDescriptor = MakeInstructionDescriptor(67, SpvOpAccessChain, 0);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor = MakeInstructionDescriptor(68, SpvOpAccessChain, 0);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor =
       MakeInstructionDescriptor(69, SpvOpInBoundsAccessChain, 0);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 
   // Tests there being no instruction with the desired opcode after the base
   // instruction id
   instructionDescriptor = MakeInstructionDescriptor(65, SpvOpAccessChain, 0);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor =
       MakeInstructionDescriptor(66, SpvOpInBoundsAccessChain, 0);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 
   // Tests there being an instruction with the desired opcode after the base
   // instruction id, but the skip count associated with the instruction
@@ -190,13 +205,15 @@
   instructionDescriptor = MakeInstructionDescriptor(11, SpvOpAccessChain, 100);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor =
       MakeInstructionDescriptor(16, SpvOpInBoundsAccessChain, 100);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
-  ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationToggleAccessChainInstructionTest, ApplyTest) {
@@ -290,35 +307,38 @@
   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
   ASSERT_TRUE(IsValid(env, context.get()));
 
-  FactManager factManager;
+  FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   auto instructionDescriptor =
       MakeInstructionDescriptor(18, SpvOpAccessChain, 0);
   auto transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
-  transformation.Apply(context.get(), &factManager);
+  transformation.Apply(context.get(), &transformation_context);
 
   instructionDescriptor =
       MakeInstructionDescriptor(20, SpvOpInBoundsAccessChain, 0);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
-  transformation.Apply(context.get(), &factManager);
+  transformation.Apply(context.get(), &transformation_context);
 
   instructionDescriptor = MakeInstructionDescriptor(24, SpvOpAccessChain, 0);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
-  transformation.Apply(context.get(), &factManager);
+  transformation.Apply(context.get(), &transformation_context);
 
   instructionDescriptor =
       MakeInstructionDescriptor(26, SpvOpInBoundsAccessChain, 0);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
-  transformation.Apply(context.get(), &factManager);
+  transformation.Apply(context.get(), &transformation_context);
 
   instructionDescriptor = MakeInstructionDescriptor(38, SpvOpAccessChain, 0);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
-  transformation.Apply(context.get(), &factManager);
+  transformation.Apply(context.get(), &transformation_context);
 
   std::string variantShader = R"(
                OpCapability Shader
diff --git a/third_party/spirv-tools/src/test/fuzz/transformation_vector_shuffle_test.cpp b/third_party/spirv-tools/src/test/fuzz/transformation_vector_shuffle_test.cpp
index 385c38b..a29c511 100644
--- a/third_party/spirv-tools/src/test/fuzz/transformation_vector_shuffle_test.cpp
+++ b/third_party/spirv-tools/src/test/fuzz/transformation_vector_shuffle_test.cpp
@@ -86,249 +86,259 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(10, {}),
-                                  MakeDataDescriptor(12, {0}), context.get());
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(11, {}),
-                                  MakeDataDescriptor(12, {1}), context.get());
+  transformation_context.GetFactManager()->AddFactDataSynonym(
+      MakeDataDescriptor(10, {}), MakeDataDescriptor(12, {0}), context.get());
+  transformation_context.GetFactManager()->AddFactDataSynonym(
+      MakeDataDescriptor(11, {}), MakeDataDescriptor(12, {1}), context.get());
 
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(10, {}),
-                                  MakeDataDescriptor(16, {0}), context.get());
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(11, {}),
-                                  MakeDataDescriptor(16, {1}), context.get());
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(10, {}),
-                                  MakeDataDescriptor(16, {2}), context.get());
+  transformation_context.GetFactManager()->AddFactDataSynonym(
+      MakeDataDescriptor(10, {}), MakeDataDescriptor(16, {0}), context.get());
+  transformation_context.GetFactManager()->AddFactDataSynonym(
+      MakeDataDescriptor(11, {}), MakeDataDescriptor(16, {1}), context.get());
+  transformation_context.GetFactManager()->AddFactDataSynonym(
+      MakeDataDescriptor(10, {}), MakeDataDescriptor(16, {2}), context.get());
 
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(10, {}),
-                                  MakeDataDescriptor(20, {0}), context.get());
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(11, {}),
-                                  MakeDataDescriptor(20, {1}), context.get());
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(10, {}),
-                                  MakeDataDescriptor(20, {2}), context.get());
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(11, {}),
-                                  MakeDataDescriptor(20, {3}), context.get());
+  transformation_context.GetFactManager()->AddFactDataSynonym(
+      MakeDataDescriptor(10, {}), MakeDataDescriptor(20, {0}), context.get());
+  transformation_context.GetFactManager()->AddFactDataSynonym(
+      MakeDataDescriptor(11, {}), MakeDataDescriptor(20, {1}), context.get());
+  transformation_context.GetFactManager()->AddFactDataSynonym(
+      MakeDataDescriptor(10, {}), MakeDataDescriptor(20, {2}), context.get());
+  transformation_context.GetFactManager()->AddFactDataSynonym(
+      MakeDataDescriptor(11, {}), MakeDataDescriptor(20, {3}), context.get());
 
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(25, {}),
-                                  MakeDataDescriptor(27, {0}), context.get());
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(26, {}),
-                                  MakeDataDescriptor(27, {1}), context.get());
+  transformation_context.GetFactManager()->AddFactDataSynonym(
+      MakeDataDescriptor(25, {}), MakeDataDescriptor(27, {0}), context.get());
+  transformation_context.GetFactManager()->AddFactDataSynonym(
+      MakeDataDescriptor(26, {}), MakeDataDescriptor(27, {1}), context.get());
 
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(25, {}),
-                                  MakeDataDescriptor(31, {0}), context.get());
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(26, {}),
-                                  MakeDataDescriptor(31, {1}), context.get());
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(25, {}),
-                                  MakeDataDescriptor(31, {2}), context.get());
+  transformation_context.GetFactManager()->AddFactDataSynonym(
+      MakeDataDescriptor(25, {}), MakeDataDescriptor(31, {0}), context.get());
+  transformation_context.GetFactManager()->AddFactDataSynonym(
+      MakeDataDescriptor(26, {}), MakeDataDescriptor(31, {1}), context.get());
+  transformation_context.GetFactManager()->AddFactDataSynonym(
+      MakeDataDescriptor(25, {}), MakeDataDescriptor(31, {2}), context.get());
 
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(25, {}),
-                                  MakeDataDescriptor(35, {0}), context.get());
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(26, {}),
-                                  MakeDataDescriptor(35, {1}), context.get());
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(25, {}),
-                                  MakeDataDescriptor(35, {2}), context.get());
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(26, {}),
-                                  MakeDataDescriptor(35, {3}), context.get());
+  transformation_context.GetFactManager()->AddFactDataSynonym(
+      MakeDataDescriptor(25, {}), MakeDataDescriptor(35, {0}), context.get());
+  transformation_context.GetFactManager()->AddFactDataSynonym(
+      MakeDataDescriptor(26, {}), MakeDataDescriptor(35, {1}), context.get());
+  transformation_context.GetFactManager()->AddFactDataSynonym(
+      MakeDataDescriptor(25, {}), MakeDataDescriptor(35, {2}), context.get());
+  transformation_context.GetFactManager()->AddFactDataSynonym(
+      MakeDataDescriptor(26, {}), MakeDataDescriptor(35, {3}), context.get());
 
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(40, {}),
-                                  MakeDataDescriptor(42, {0}), context.get());
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(41, {}),
-                                  MakeDataDescriptor(42, {1}), context.get());
+  transformation_context.GetFactManager()->AddFactDataSynonym(
+      MakeDataDescriptor(40, {}), MakeDataDescriptor(42, {0}), context.get());
+  transformation_context.GetFactManager()->AddFactDataSynonym(
+      MakeDataDescriptor(41, {}), MakeDataDescriptor(42, {1}), context.get());
 
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(40, {}),
-                                  MakeDataDescriptor(46, {0}), context.get());
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(41, {}),
-                                  MakeDataDescriptor(46, {1}), context.get());
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(40, {}),
-                                  MakeDataDescriptor(46, {2}), context.get());
+  transformation_context.GetFactManager()->AddFactDataSynonym(
+      MakeDataDescriptor(40, {}), MakeDataDescriptor(46, {0}), context.get());
+  transformation_context.GetFactManager()->AddFactDataSynonym(
+      MakeDataDescriptor(41, {}), MakeDataDescriptor(46, {1}), context.get());
+  transformation_context.GetFactManager()->AddFactDataSynonym(
+      MakeDataDescriptor(40, {}), MakeDataDescriptor(46, {2}), context.get());
 
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(40, {}),
-                                  MakeDataDescriptor(50, {0}), context.get());
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(41, {}),
-                                  MakeDataDescriptor(50, {1}), context.get());
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(40, {}),
-                                  MakeDataDescriptor(50, {2}), context.get());
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(41, {}),
-                                  MakeDataDescriptor(50, {3}), context.get());
+  transformation_context.GetFactManager()->AddFactDataSynonym(
+      MakeDataDescriptor(40, {}), MakeDataDescriptor(50, {0}), context.get());
+  transformation_context.GetFactManager()->AddFactDataSynonym(
+      MakeDataDescriptor(41, {}), MakeDataDescriptor(50, {1}), context.get());
+  transformation_context.GetFactManager()->AddFactDataSynonym(
+      MakeDataDescriptor(40, {}), MakeDataDescriptor(50, {2}), context.get());
+  transformation_context.GetFactManager()->AddFactDataSynonym(
+      MakeDataDescriptor(41, {}), MakeDataDescriptor(50, {3}), context.get());
 
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(55, {}),
-                                  MakeDataDescriptor(61, {0}), context.get());
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(56, {}),
-                                  MakeDataDescriptor(61, {1}), context.get());
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(55, {}),
-                                  MakeDataDescriptor(61, {2}), context.get());
+  transformation_context.GetFactManager()->AddFactDataSynonym(
+      MakeDataDescriptor(55, {}), MakeDataDescriptor(61, {0}), context.get());
+  transformation_context.GetFactManager()->AddFactDataSynonym(
+      MakeDataDescriptor(56, {}), MakeDataDescriptor(61, {1}), context.get());
+  transformation_context.GetFactManager()->AddFactDataSynonym(
+      MakeDataDescriptor(55, {}), MakeDataDescriptor(61, {2}), context.get());
 
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(55, {}),
-                                  MakeDataDescriptor(65, {0}), context.get());
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(56, {}),
-                                  MakeDataDescriptor(65, {1}), context.get());
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(55, {}),
-                                  MakeDataDescriptor(65, {2}), context.get());
-  fact_manager.AddFactDataSynonym(MakeDataDescriptor(56, {}),
-                                  MakeDataDescriptor(65, {3}), context.get());
+  transformation_context.GetFactManager()->AddFactDataSynonym(
+      MakeDataDescriptor(55, {}), MakeDataDescriptor(65, {0}), context.get());
+  transformation_context.GetFactManager()->AddFactDataSynonym(
+      MakeDataDescriptor(56, {}), MakeDataDescriptor(65, {1}), context.get());
+  transformation_context.GetFactManager()->AddFactDataSynonym(
+      MakeDataDescriptor(55, {}), MakeDataDescriptor(65, {2}), context.get());
+  transformation_context.GetFactManager()->AddFactDataSynonym(
+      MakeDataDescriptor(56, {}), MakeDataDescriptor(65, {3}), context.get());
 
   // %103 does not dominate the return instruction.
   ASSERT_FALSE(TransformationVectorShuffle(
                    MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 103, 65,
                    {3, 5, 7})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Illegal to shuffle a bvec2 and a vec3
   ASSERT_FALSE(TransformationVectorShuffle(
                    MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 112, 61,
                    {0, 2, 4})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Illegal to shuffle an ivec2 and a uvec4
   ASSERT_FALSE(TransformationVectorShuffle(
                    MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 27, 50,
                    {1, 3, 5})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Vector 1 does not exist
   ASSERT_FALSE(TransformationVectorShuffle(
                    MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 300, 50,
                    {1, 3, 5})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Vector 2 does not exist
   ASSERT_FALSE(TransformationVectorShuffle(
                    MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 27, 300,
                    {1, 3, 5})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Index out of range
   ASSERT_FALSE(
       TransformationVectorShuffle(
           MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 12, 112, {0, 20})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   // Too many indices
   ASSERT_FALSE(TransformationVectorShuffle(
                    MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 12, 112,
                    {0, 1, 0, 1, 0, 1, 0, 1})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Too few indices
   ASSERT_FALSE(
       TransformationVectorShuffle(
           MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 12, 112, {})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   // Too few indices again
   ASSERT_FALSE(
       TransformationVectorShuffle(
           MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 12, 112, {0})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   // Indices define unknown type: we do not have vec2
   ASSERT_FALSE(
       TransformationVectorShuffle(
           MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 65, 65, {0, 1})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   // The instruction to insert before does not exist
   ASSERT_FALSE(TransformationVectorShuffle(
                    MakeInstructionDescriptor(100, SpvOpCompositeConstruct, 1),
                    201, 20, 12, {0xFFFFFFFF, 3, 5})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // The 'fresh' id is already in use
   ASSERT_FALSE(
       TransformationVectorShuffle(
           MakeInstructionDescriptor(100, SpvOpReturn, 0), 12, 12, 112, {})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   protobufs::DataDescriptor temp_dd;
 
   TransformationVectorShuffle transformation1(
       MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 12, 112, {1, 0});
-  ASSERT_TRUE(transformation1.IsApplicable(context.get(), fact_manager));
-  transformation1.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation1.IsApplicable(context.get(), transformation_context));
+  transformation1.Apply(context.get(), &transformation_context);
   temp_dd = MakeDataDescriptor(200, {0});
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(11, {}), temp_dd,
-                                        context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(11, {}), temp_dd));
   temp_dd = MakeDataDescriptor(200, {1});
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(10, {}), temp_dd,
-                                        context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(10, {}), temp_dd));
 
   TransformationVectorShuffle transformation2(
       MakeInstructionDescriptor(100, SpvOpReturn, 0), 201, 20, 12,
       {0xFFFFFFFF, 3, 5});
-  ASSERT_TRUE(transformation2.IsApplicable(context.get(), fact_manager));
-  transformation2.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation2.IsApplicable(context.get(), transformation_context));
+  transformation2.Apply(context.get(), &transformation_context);
   temp_dd = MakeDataDescriptor(201, {1});
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(11, {}), temp_dd,
-                                        context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(11, {}), temp_dd));
   temp_dd = MakeDataDescriptor(201, {2});
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(11, {}), temp_dd,
-                                        context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(11, {}), temp_dd));
 
   TransformationVectorShuffle transformation3(
       MakeInstructionDescriptor(100, SpvOpReturn, 0), 202, 27, 35, {5, 4, 1});
-  ASSERT_TRUE(transformation3.IsApplicable(context.get(), fact_manager));
-  transformation3.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation3.IsApplicable(context.get(), transformation_context));
+  transformation3.Apply(context.get(), &transformation_context);
   temp_dd = MakeDataDescriptor(202, {0});
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(26, {}), temp_dd,
-                                        context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(26, {}), temp_dd));
   temp_dd = MakeDataDescriptor(202, {1});
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(25, {}), temp_dd,
-                                        context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(25, {}), temp_dd));
   temp_dd = MakeDataDescriptor(202, {2});
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(26, {}), temp_dd,
-                                        context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(26, {}), temp_dd));
 
   TransformationVectorShuffle transformation4(
       MakeInstructionDescriptor(100, SpvOpReturn, 0), 203, 42, 46, {0, 1});
-  ASSERT_TRUE(transformation4.IsApplicable(context.get(), fact_manager));
-  transformation4.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation4.IsApplicable(context.get(), transformation_context));
+  transformation4.Apply(context.get(), &transformation_context);
   temp_dd = MakeDataDescriptor(203, {0});
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {}), temp_dd,
-                                        context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(40, {}), temp_dd));
   temp_dd = MakeDataDescriptor(203, {1});
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(41, {}), temp_dd,
-                                        context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(41, {}), temp_dd));
 
   TransformationVectorShuffle transformation5(
       MakeInstructionDescriptor(100, SpvOpReturn, 0), 204, 42, 46, {2, 3, 4});
-  ASSERT_TRUE(transformation5.IsApplicable(context.get(), fact_manager));
-  transformation5.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation5.IsApplicable(context.get(), transformation_context));
+  transformation5.Apply(context.get(), &transformation_context);
   temp_dd = MakeDataDescriptor(204, {0});
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {}), temp_dd,
-                                        context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(40, {}), temp_dd));
   temp_dd = MakeDataDescriptor(204, {1});
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(41, {}), temp_dd,
-                                        context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(41, {}), temp_dd));
   temp_dd = MakeDataDescriptor(204, {2});
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {}), temp_dd,
-                                        context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(40, {}), temp_dd));
 
   TransformationVectorShuffle transformation6(
       MakeInstructionDescriptor(100, SpvOpReturn, 0), 205, 42, 42,
       {0, 1, 2, 3});
-  ASSERT_TRUE(transformation6.IsApplicable(context.get(), fact_manager));
-  transformation6.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation6.IsApplicable(context.get(), transformation_context));
+  transformation6.Apply(context.get(), &transformation_context);
   temp_dd = MakeDataDescriptor(205, {0});
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {}), temp_dd,
-                                        context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(40, {}), temp_dd));
   temp_dd = MakeDataDescriptor(205, {1});
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(41, {}), temp_dd,
-                                        context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(41, {}), temp_dd));
   temp_dd = MakeDataDescriptor(205, {2});
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {}), temp_dd,
-                                        context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(40, {}), temp_dd));
   temp_dd = MakeDataDescriptor(205, {3});
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(41, {}), temp_dd,
-                                        context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(41, {}), temp_dd));
 
   // swizzle vec4 from vec4 and vec4 using some undefs
   TransformationVectorShuffle transformation7(
       MakeInstructionDescriptor(100, SpvOpReturn, 0), 206, 65, 65,
       {0xFFFFFFFF, 3, 6, 0xFFFFFFFF});
-  ASSERT_TRUE(transformation7.IsApplicable(context.get(), fact_manager));
-  transformation7.Apply(context.get(), &fact_manager);
+  ASSERT_TRUE(
+      transformation7.IsApplicable(context.get(), transformation_context));
+  transformation7.Apply(context.get(), &transformation_context);
   temp_dd = MakeDataDescriptor(206, {1});
-  ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(56, {}), temp_dd,
-                                        context.get()));
+  ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
+      MakeDataDescriptor(56, {}), temp_dd));
 
   std::string after_transformation = R"(
                OpCapability Shader
@@ -479,52 +489,55 @@
   ASSERT_TRUE(IsValid(env, context.get()));
 
   FactManager fact_manager;
+  spvtools::ValidatorOptions validator_options;
+  TransformationContext transformation_context(&fact_manager,
+                                               validator_options);
 
   // Cannot insert before the OpVariables of a function.
   ASSERT_FALSE(
       TransformationVectorShuffle(
           MakeInstructionDescriptor(101, SpvOpVariable, 0), 200, 14, 14, {0, 1})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationVectorShuffle(
           MakeInstructionDescriptor(101, SpvOpVariable, 1), 200, 14, 14, {1, 2})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationVectorShuffle(
           MakeInstructionDescriptor(102, SpvOpVariable, 0), 200, 14, 14, {1, 2})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   // OK to insert right after the OpVariables.
   ASSERT_FALSE(
       TransformationVectorShuffle(
           MakeInstructionDescriptor(102, SpvOpBranch, 1), 200, 14, 14, {1, 1})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
 
   // Cannot insert before the OpPhis of a block.
   ASSERT_FALSE(
       TransformationVectorShuffle(MakeInstructionDescriptor(60, SpvOpPhi, 0),
                                   200, 14, 14, {2, 0})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationVectorShuffle(MakeInstructionDescriptor(59, SpvOpPhi, 0),
                                   200, 14, 14, {3, 0})
-          .IsApplicable(context.get(), fact_manager));
+          .IsApplicable(context.get(), transformation_context));
   // OK to insert after the OpPhis.
   ASSERT_TRUE(TransformationVectorShuffle(
                   MakeInstructionDescriptor(59, SpvOpAccessChain, 0), 200, 14,
                   14, {3, 4})
-                  .IsApplicable(context.get(), fact_manager));
+                  .IsApplicable(context.get(), transformation_context));
 
   // Cannot insert before OpLoopMerge
   ASSERT_FALSE(TransformationVectorShuffle(
                    MakeInstructionDescriptor(33, SpvOpBranchConditional, 0),
                    200, 14, 14, {3})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 
   // Cannot insert before OpSelectionMerge
   ASSERT_FALSE(TransformationVectorShuffle(
                    MakeInstructionDescriptor(21, SpvOpBranchConditional, 0),
                    200, 14, 14, {2})
-                   .IsApplicable(context.get(), fact_manager));
+                   .IsApplicable(context.get(), transformation_context));
 }
 
 }  // namespace
diff --git a/third_party/spirv-tools/src/test/opt/eliminate_dead_functions_test.cpp b/third_party/spirv-tools/src/test/opt/eliminate_dead_functions_test.cpp
index 0a3d490..5474673 100644
--- a/third_party/spirv-tools/src/test/opt/eliminate_dead_functions_test.cpp
+++ b/third_party/spirv-tools/src/test/opt/eliminate_dead_functions_test.cpp
@@ -204,6 +204,75 @@
                                                     /* skip_nop = */ true);
 }
 
+TEST_F(EliminateDeadFunctionsBasicTest, DebugRemoveFunctionFromDebugFunction) {
+  // We want to remove id of OpFunction from DebugFunction.
+  const std::string text = R"(OpCapability Shader
+%1 = OpExtInstImport "OpenCL.DebugInfo.100"
+OpMemoryModel Logical GLSL450
+OpEntryPoint Fragment %2 "main" %3 %4
+OpExecutionMode %2 OriginUpperLeft
+%5 = OpString "ps.hlsl"
+OpSource HLSL 600 %5 "float4 foo() {
+  return 1;
+}
+float4 main(float4 color : COLOR) : SV_TARGET {
+  return foo() + color;
+}
+"
+%6 = OpString "float"
+%7 = OpString "main"
+%8 = OpString "foo"
+; CHECK: [[foo:%\d+]] = OpString "foo"
+OpDecorate %3 Location 0
+OpDecorate %4 Location 0
+%uint = OpTypeInt 32 0
+%uint_32 = OpConstant %uint 32
+%float = OpTypeFloat 32
+%float_1 = OpConstant %float 1
+%v4float = OpTypeVector %float 4
+%14 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%void = OpTypeVoid
+%18 = OpTypeFunction %void
+%19 = OpTypeFunction %v4float
+%3 = OpVariable %_ptr_Input_v4float Input
+%4 = OpVariable %_ptr_Output_v4float Output
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+; CHECK: [[info_none:%\d+]] = OpExtInst %void %1 DebugInfoNone
+%20 = OpExtInst %void %1 DebugSource %5
+%21 = OpExtInst %void %1 DebugCompilationUnit 1 4 %20 HLSL
+%22 = OpExtInst %void %1 DebugTypeBasic %6 %uint_32 Float
+%23 = OpExtInst %void %1 DebugTypeVector %22 4
+%24 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %23 %23
+%25 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %23
+%26 = OpExtInst %void %1 DebugFunction %7 %24 %20 4 1 %21 %7 FlagIsProtected|FlagIsPrivate 4 %2
+%27 = OpExtInst %void %1 DebugFunction %8 %25 %20 1 1 %21 %8 FlagIsProtected|FlagIsPrivate 1 %28
+; CHECK: {{%\d+}} = OpExtInst %void %1 DebugFunction [[foo]] {{%\d+}} {{%\d+}} 1 1 {{%\d+}} {{%\d+}} FlagIsProtected|FlagIsPrivate 1 [[info_none]]
+%29 = OpExtInst %void %1 DebugLexicalBlock %20 1 14 %27
+%40 = OpExtInst %void %1 DebugInlinedAt 4 %26
+%2 = OpFunction %void None %18
+%30 = OpLabel
+%39 = OpVariable %_ptr_Function_v4float Function
+%41 = OpExtInst %void %1 DebugScope %27 %40
+OpStore %39 %14
+%32 = OpLoad %v4float %39
+%42 = OpExtInst %void %1 DebugScope %26
+%33 = OpLoad %v4float %3
+%34 = OpFAdd %v4float %32 %33
+OpStore %4 %34
+%43 = OpExtInst %void %1 DebugNoScope
+OpReturn
+OpFunctionEnd
+%28 = OpFunction %v4float None %19
+%36 = OpLabel
+OpReturnValue %14
+OpFunctionEnd
+)";
+
+  SinglePassRunAndMatch<EliminateDeadFunctionsPass>(text, false);
+}
+
 }  // namespace
 }  // namespace opt
 }  // namespace spvtools
diff --git a/third_party/spirv-tools/src/test/opt/eliminate_dead_member_test.cpp b/third_party/spirv-tools/src/test/opt/eliminate_dead_member_test.cpp
index b6925d7..a9b0f28 100644
--- a/third_party/spirv-tools/src/test/opt/eliminate_dead_member_test.cpp
+++ b/third_party/spirv-tools/src/test/opt/eliminate_dead_member_test.cpp
@@ -1085,4 +1085,103 @@
   EXPECT_EQ(opt::Pass::Status::SuccessWithoutChange, std::get<1>(result));
 }
 
+TEST_F(EliminateDeadMemberTest, UpdateSpecConstOpExtract) {
+  // Test that an extract in an OpSpecConstantOp is correctly updated.
+  const std::string text = R"(
+; CHECK: OpName
+; CHECK-NEXT: OpMemberName %type__Globals 0 "y"
+; CHECK-NOT: OpMemberName
+; CHECK: OpDecorate [[spec_const:%\w+]] SpecId 1
+; CHECK: OpMemberDecorate %type__Globals 0 Offset 4
+; CHECK: %type__Globals = OpTypeStruct %uint
+; CHECK: [[struct:%\w+]] = OpSpecConstantComposite %type__Globals [[spec_const]]
+; CHECK: OpSpecConstantOp %uint CompositeExtract [[struct]] 0
+               OpCapability Shader
+               OpCapability Addresses
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %main "main"
+               OpSource HLSL 600
+               OpName %type__Globals "type.$Globals"
+               OpMemberName %type__Globals 0 "x"
+               OpMemberName %type__Globals 1 "y"
+               OpMemberName %type__Globals 2 "z"
+               OpName %main "main"
+               OpDecorate %c_0 SpecId 0
+               OpDecorate %c_1 SpecId 1
+               OpDecorate %c_2 SpecId 2
+               OpMemberDecorate %type__Globals 0 Offset 0
+               OpMemberDecorate %type__Globals 1 Offset 4
+               OpMemberDecorate %type__Globals 2 Offset 16
+       %uint = OpTypeInt 32 0
+        %c_0 = OpSpecConstant %uint 0
+        %c_1 = OpSpecConstant %uint 1
+        %c_2 = OpSpecConstant %uint 2
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_2 = OpConstant %uint 2
+     %uint_3 = OpConstant %uint 3
+%type__Globals = OpTypeStruct %uint %uint %uint
+%spec_const_global = OpSpecConstantComposite %type__Globals %c_0 %c_1 %c_2
+%extract = OpSpecConstantOp %uint CompositeExtract %spec_const_global 1
+       %void = OpTypeVoid
+         %14 = OpTypeFunction %void
+       %main = OpFunction %void None %14
+         %16 = OpLabel
+               OpReturn
+               OpFunctionEnd
+)";
+
+  SinglePassRunAndMatch<opt::EliminateDeadMembersPass>(text, true);
+}
+
+TEST_F(EliminateDeadMemberTest, UpdateSpecConstOpInsert) {
+  // Test that an insert in an OpSpecConstantOp is correctly updated.
+  const std::string text = R"(
+; CHECK: OpName
+; CHECK-NEXT: OpMemberName %type__Globals 0 "y"
+; CHECK-NOT: OpMemberName
+; CHECK: OpDecorate [[spec_const:%\w+]] SpecId 1
+; CHECK: OpMemberDecorate %type__Globals 0 Offset 4
+; CHECK: %type__Globals = OpTypeStruct %uint
+; CHECK: [[struct:%\w+]] = OpSpecConstantComposite %type__Globals [[spec_const]]
+; CHECK: OpSpecConstantOp %type__Globals CompositeInsert %uint_3 [[struct]] 0
+               OpCapability Shader
+               OpCapability Addresses
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %main "main"
+               OpSource HLSL 600
+               OpName %type__Globals "type.$Globals"
+               OpMemberName %type__Globals 0 "x"
+               OpMemberName %type__Globals 1 "y"
+               OpMemberName %type__Globals 2 "z"
+               OpName %main "main"
+               OpDecorate %c_0 SpecId 0
+               OpDecorate %c_1 SpecId 1
+               OpDecorate %c_2 SpecId 2
+               OpMemberDecorate %type__Globals 0 Offset 0
+               OpMemberDecorate %type__Globals 1 Offset 4
+               OpMemberDecorate %type__Globals 2 Offset 16
+       %uint = OpTypeInt 32 0
+        %c_0 = OpSpecConstant %uint 0
+        %c_1 = OpSpecConstant %uint 1
+        %c_2 = OpSpecConstant %uint 2
+     %uint_0 = OpConstant %uint 0
+     %uint_1 = OpConstant %uint 1
+     %uint_2 = OpConstant %uint 2
+     %uint_3 = OpConstant %uint 3
+%type__Globals = OpTypeStruct %uint %uint %uint
+%spec_const_global = OpSpecConstantComposite %type__Globals %c_0 %c_1 %c_2
+%insert = OpSpecConstantOp %type__Globals CompositeInsert %uint_3 %spec_const_global 1
+%extract = OpSpecConstantOp %uint CompositeExtract %insert 1
+       %void = OpTypeVoid
+         %14 = OpTypeFunction %void
+       %main = OpFunction %void None %14
+         %16 = OpLabel
+               OpReturn
+               OpFunctionEnd
+)";
+
+  SinglePassRunAndMatch<opt::EliminateDeadMembersPass>(text, true);
+}
+
 }  // namespace
diff --git a/third_party/spirv-tools/src/test/opt/instruction_test.cpp b/third_party/spirv-tools/src/test/opt/instruction_test.cpp
index d219f3e..1995c5b 100644
--- a/third_party/spirv-tools/src/test/opt/instruction_test.cpp
+++ b/third_party/spirv-tools/src/test/opt/instruction_test.cpp
@@ -35,6 +35,7 @@
 using OpaqueTypeTest = PassTest<::testing::Test>;
 using GetBaseTest = PassTest<::testing::Test>;
 using ValidBasePointerTest = PassTest<::testing::Test>;
+using VulkanBufferTest = PassTest<::testing::Test>;
 
 TEST(InstructionTest, CreateTrivial) {
   Instruction empty;
@@ -1143,6 +1144,260 @@
   EXPECT_TRUE(null_inst->IsValidBasePointer());
 }
 
+TEST_F(VulkanBufferTest, VulkanStorageBuffer) {
+  const std::string text = R"(
+OpCapability Shader
+OpCapability RuntimeDescriptorArray
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %1 "main"
+OpExecutionMode %1 LocalSize 1 1 1
+OpDecorate %2 Block
+OpMemberDecorate %2 0 Offset 0
+OpDecorate %3 BufferBlock
+OpMemberDecorate %3 0 Offset 0
+%4 = OpTypeVoid
+%5 = OpTypeInt 32 0
+%2 = OpTypeStruct %5
+%3 = OpTypeStruct %5
+
+%6 = OpTypePointer StorageBuffer %2
+%7 = OpTypePointer Uniform %2
+%8 = OpTypePointer Uniform %3
+
+%9 = OpConstant %5 1
+%10 = OpTypeArray %2 %9
+%11 = OpTypeArray %3 %9
+%12 = OpTypePointer StorageBuffer %10
+%13 = OpTypePointer Uniform %10
+%14 = OpTypePointer Uniform %11
+
+%15 = OpTypeRuntimeArray %2
+%16 = OpTypeRuntimeArray %3
+%17 = OpTypePointer StorageBuffer %15
+%18 = OpTypePointer Uniform %15
+%19 = OpTypePointer Uniform %16
+
+%50 = OpTypeFunction %4
+%1 = OpFunction %4 None %50
+%51 = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  std::unique_ptr<IRContext> context =
+      BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
+  EXPECT_NE(context, nullptr);
+
+  // Standard SSBO and UBO
+  Instruction* inst = context->get_def_use_mgr()->GetDef(6);
+  EXPECT_EQ(true, inst->IsVulkanStorageBuffer());
+  inst = context->get_def_use_mgr()->GetDef(7);
+  EXPECT_EQ(false, inst->IsVulkanStorageBuffer());
+  inst = context->get_def_use_mgr()->GetDef(8);
+  EXPECT_EQ(true, inst->IsVulkanStorageBuffer());
+
+  // Arrayed SSBO and UBO
+  inst = context->get_def_use_mgr()->GetDef(12);
+  EXPECT_EQ(true, inst->IsVulkanStorageBuffer());
+  inst = context->get_def_use_mgr()->GetDef(13);
+  EXPECT_EQ(false, inst->IsVulkanStorageBuffer());
+  inst = context->get_def_use_mgr()->GetDef(14);
+  EXPECT_EQ(true, inst->IsVulkanStorageBuffer());
+
+  // Runtime arrayed SSBO and UBO
+  inst = context->get_def_use_mgr()->GetDef(17);
+  EXPECT_EQ(true, inst->IsVulkanStorageBuffer());
+  inst = context->get_def_use_mgr()->GetDef(18);
+  EXPECT_EQ(false, inst->IsVulkanStorageBuffer());
+  inst = context->get_def_use_mgr()->GetDef(19);
+  EXPECT_EQ(true, inst->IsVulkanStorageBuffer());
+}
+
+TEST_F(VulkanBufferTest, VulkanUniformBuffer) {
+  const std::string text = R"(
+OpCapability Shader
+OpCapability RuntimeDescriptorArray
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %1 "main"
+OpExecutionMode %1 LocalSize 1 1 1
+OpDecorate %2 Block
+OpMemberDecorate %2 0 Offset 0
+OpDecorate %3 BufferBlock
+OpMemberDecorate %3 0 Offset 0
+%4 = OpTypeVoid
+%5 = OpTypeInt 32 0
+%2 = OpTypeStruct %5
+%3 = OpTypeStruct %5
+
+%6 = OpTypePointer StorageBuffer %2
+%7 = OpTypePointer Uniform %2
+%8 = OpTypePointer Uniform %3
+
+%9 = OpConstant %5 1
+%10 = OpTypeArray %2 %9
+%11 = OpTypeArray %3 %9
+%12 = OpTypePointer StorageBuffer %10
+%13 = OpTypePointer Uniform %10
+%14 = OpTypePointer Uniform %11
+
+%15 = OpTypeRuntimeArray %2
+%16 = OpTypeRuntimeArray %3
+%17 = OpTypePointer StorageBuffer %15
+%18 = OpTypePointer Uniform %15
+%19 = OpTypePointer Uniform %16
+
+%50 = OpTypeFunction %4
+%1 = OpFunction %4 None %50
+%51 = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  std::unique_ptr<IRContext> context =
+      BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
+  EXPECT_NE(context, nullptr);
+
+  // Standard SSBO and UBO
+  Instruction* inst = context->get_def_use_mgr()->GetDef(6);
+  EXPECT_EQ(false, inst->IsVulkanUniformBuffer());
+  inst = context->get_def_use_mgr()->GetDef(7);
+  EXPECT_EQ(true, inst->IsVulkanUniformBuffer());
+  inst = context->get_def_use_mgr()->GetDef(8);
+  EXPECT_EQ(false, inst->IsVulkanUniformBuffer());
+
+  // Arrayed SSBO and UBO
+  inst = context->get_def_use_mgr()->GetDef(12);
+  EXPECT_EQ(false, inst->IsVulkanUniformBuffer());
+  inst = context->get_def_use_mgr()->GetDef(13);
+  EXPECT_EQ(true, inst->IsVulkanUniformBuffer());
+  inst = context->get_def_use_mgr()->GetDef(14);
+  EXPECT_EQ(false, inst->IsVulkanUniformBuffer());
+
+  // Runtime arrayed SSBO and UBO
+  inst = context->get_def_use_mgr()->GetDef(17);
+  EXPECT_EQ(false, inst->IsVulkanUniformBuffer());
+  inst = context->get_def_use_mgr()->GetDef(18);
+  EXPECT_EQ(true, inst->IsVulkanUniformBuffer());
+  inst = context->get_def_use_mgr()->GetDef(19);
+  EXPECT_EQ(false, inst->IsVulkanUniformBuffer());
+}
+
+TEST_F(VulkanBufferTest, ImageQueries) {
+  const std::string text = R"(
+OpCapability Shader
+OpCapability ImageBuffer
+OpCapability RuntimeDescriptorArray
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %1 "main"
+OpExecutionMode %1 LocalSize 1 1 1
+%2 = OpTypeVoid
+%3 = OpTypeFloat 32
+
+%4 = OpTypeImage %3 Buffer 0 0 0 1 Rgba32f
+%5 = OpTypeImage %3 Buffer 0 0 0 2 Rgba32f
+%6 = OpTypeImage %3 2D 0 0 0 1 Rgba32f
+%7 = OpTypeImage %3 2D 0 0 0 2 Rgba32f
+
+%8 = OpTypePointer UniformConstant %4
+%9 = OpTypePointer UniformConstant %5
+%10 = OpTypePointer UniformConstant %6
+%11 = OpTypePointer UniformConstant %7
+
+%12 = OpTypeInt 32 0
+%13 = OpConstant %12 1
+%14 = OpTypeArray %4 %13
+%15 = OpTypeArray %5 %13
+%16 = OpTypeArray %6 %13
+%17 = OpTypeArray %7 %13
+%18 = OpTypePointer UniformConstant %14
+%19 = OpTypePointer UniformConstant %15
+%20 = OpTypePointer UniformConstant %16
+%21 = OpTypePointer UniformConstant %17
+
+%22 = OpTypeRuntimeArray %4
+%23 = OpTypeRuntimeArray %5
+%24 = OpTypeRuntimeArray %6
+%25 = OpTypeRuntimeArray %7
+%26 = OpTypePointer UniformConstant %22
+%27 = OpTypePointer UniformConstant %23
+%28 = OpTypePointer UniformConstant %24
+%29 = OpTypePointer UniformConstant %25
+
+%50 = OpTypeFunction %4
+%1 = OpFunction %4 None %50
+%51 = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  std::unique_ptr<IRContext> context =
+      BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
+  EXPECT_NE(context, nullptr);
+
+  // Bare pointers
+  Instruction* inst = context->get_def_use_mgr()->GetDef(8);
+  EXPECT_EQ(false, inst->IsVulkanStorageImage());
+  EXPECT_EQ(false, inst->IsVulkanSampledImage());
+  EXPECT_EQ(false, inst->IsVulkanStorageTexelBuffer());
+
+  inst = context->get_def_use_mgr()->GetDef(9);
+  EXPECT_EQ(false, inst->IsVulkanStorageImage());
+  EXPECT_EQ(false, inst->IsVulkanSampledImage());
+  EXPECT_EQ(true, inst->IsVulkanStorageTexelBuffer());
+
+  inst = context->get_def_use_mgr()->GetDef(10);
+  EXPECT_EQ(false, inst->IsVulkanStorageImage());
+  EXPECT_EQ(true, inst->IsVulkanSampledImage());
+  EXPECT_EQ(false, inst->IsVulkanStorageTexelBuffer());
+
+  inst = context->get_def_use_mgr()->GetDef(11);
+  EXPECT_EQ(true, inst->IsVulkanStorageImage());
+  EXPECT_EQ(false, inst->IsVulkanSampledImage());
+  EXPECT_EQ(false, inst->IsVulkanStorageTexelBuffer());
+
+  // Array pointers
+  inst = context->get_def_use_mgr()->GetDef(18);
+  EXPECT_EQ(false, inst->IsVulkanStorageImage());
+  EXPECT_EQ(false, inst->IsVulkanSampledImage());
+  EXPECT_EQ(false, inst->IsVulkanStorageTexelBuffer());
+
+  inst = context->get_def_use_mgr()->GetDef(19);
+  EXPECT_EQ(false, inst->IsVulkanStorageImage());
+  EXPECT_EQ(false, inst->IsVulkanSampledImage());
+  EXPECT_EQ(true, inst->IsVulkanStorageTexelBuffer());
+
+  inst = context->get_def_use_mgr()->GetDef(20);
+  EXPECT_EQ(false, inst->IsVulkanStorageImage());
+  EXPECT_EQ(true, inst->IsVulkanSampledImage());
+  EXPECT_EQ(false, inst->IsVulkanStorageTexelBuffer());
+
+  inst = context->get_def_use_mgr()->GetDef(21);
+  EXPECT_EQ(true, inst->IsVulkanStorageImage());
+  EXPECT_EQ(false, inst->IsVulkanSampledImage());
+  EXPECT_EQ(false, inst->IsVulkanStorageTexelBuffer());
+
+  // Runtime array pointers
+  inst = context->get_def_use_mgr()->GetDef(26);
+  EXPECT_EQ(false, inst->IsVulkanStorageImage());
+  EXPECT_EQ(false, inst->IsVulkanSampledImage());
+  EXPECT_EQ(false, inst->IsVulkanStorageTexelBuffer());
+
+  inst = context->get_def_use_mgr()->GetDef(27);
+  EXPECT_EQ(false, inst->IsVulkanStorageImage());
+  EXPECT_EQ(false, inst->IsVulkanSampledImage());
+  EXPECT_EQ(true, inst->IsVulkanStorageTexelBuffer());
+
+  inst = context->get_def_use_mgr()->GetDef(28);
+  EXPECT_EQ(false, inst->IsVulkanStorageImage());
+  EXPECT_EQ(true, inst->IsVulkanSampledImage());
+  EXPECT_EQ(false, inst->IsVulkanStorageTexelBuffer());
+
+  inst = context->get_def_use_mgr()->GetDef(29);
+  EXPECT_EQ(true, inst->IsVulkanStorageImage());
+  EXPECT_EQ(false, inst->IsVulkanSampledImage());
+  EXPECT_EQ(false, inst->IsVulkanStorageTexelBuffer());
+}
+
 }  // namespace
 }  // namespace opt
 }  // namespace spvtools
diff --git a/third_party/spirv-tools/src/test/opt/ir_context_test.cpp b/third_party/spirv-tools/src/test/opt/ir_context_test.cpp
index d5710fc..e72561c 100644
--- a/third_party/spirv-tools/src/test/opt/ir_context_test.cpp
+++ b/third_party/spirv-tools/src/test/opt/ir_context_test.cpp
@@ -19,6 +19,7 @@
 #include <string>
 #include <utility>
 
+#include "OpenCLDebugInfo100.h"
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 #include "source/opt/pass.h"
@@ -372,6 +373,123 @@
   EXPECT_TRUE(context->annotations().empty());
 }
 
+TEST_F(IRContextTest, KillFunctionFromDebugFunction) {
+  const std::string text = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "OpenCL.DebugInfo.100"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %2 "main"
+               OpExecutionMode %2 OriginUpperLeft
+          %3 = OpString "ps.hlsl"
+          %4 = OpString "foo"
+               OpSource HLSL 600
+       %void = OpTypeVoid
+          %6 = OpTypeFunction %void
+          %7 = OpExtInst %void %1 DebugSource %3
+          %8 = OpExtInst %void %1 DebugCompilationUnit 1 4 %7 HLSL
+          %9 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %void
+         %10 = OpExtInst %void %1 DebugFunction %4 %9 %7 1 1 %8 %4 FlagIsProtected|FlagIsPrivate 1 %11
+          %2 = OpFunction %void None %6
+         %12 = OpLabel
+               OpReturn
+               OpFunctionEnd
+         %11 = OpFunction %void None %6
+         %13 = OpLabel
+               OpReturn
+               OpFunctionEnd
+)";
+
+  std::unique_ptr<IRContext> context =
+      BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
+
+  // Delete the second variable.
+  context->KillDef(11);
+
+  // Get DebugInfoNone id.
+  uint32_t debug_info_none_id = 0;
+  for (auto it = context->ext_inst_debuginfo_begin();
+       it != context->ext_inst_debuginfo_end(); ++it) {
+    if (it->GetOpenCL100DebugOpcode() == OpenCLDebugInfo100DebugInfoNone) {
+      debug_info_none_id = it->result_id();
+    }
+  }
+  EXPECT_NE(0, debug_info_none_id);
+
+  // Check the Function operand of DebugFunction is DebugInfoNone.
+  const uint32_t kDebugFunctionOperandFunctionIndex = 13;
+  bool checked = false;
+  for (auto it = context->ext_inst_debuginfo_begin();
+       it != context->ext_inst_debuginfo_end(); ++it) {
+    if (it->GetOpenCL100DebugOpcode() == OpenCLDebugInfo100DebugFunction) {
+      EXPECT_FALSE(checked);
+      EXPECT_EQ(it->GetOperand(kDebugFunctionOperandFunctionIndex).words[0],
+                debug_info_none_id);
+      checked = true;
+    }
+  }
+  EXPECT_TRUE(checked);
+}
+
+TEST_F(IRContextTest, KillVariableFromDebugGlobalVariable) {
+  const std::string text = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "OpenCL.DebugInfo.100"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %2 "main"
+               OpExecutionMode %2 OriginUpperLeft
+          %3 = OpString "ps.hlsl"
+          %4 = OpString "foo"
+          %5 = OpString "int"
+               OpSource HLSL 600
+       %uint = OpTypeInt 32 0
+    %uint_32 = OpConstant %uint 32
+%_ptr_Private_uint = OpTypePointer Private %uint
+       %void = OpTypeVoid
+         %10 = OpTypeFunction %void
+         %11 = OpVariable %_ptr_Private_uint Private
+         %12 = OpExtInst %void %1 DebugSource %3
+         %13 = OpExtInst %void %1 DebugCompilationUnit 1 4 %12 HLSL
+         %14 = OpExtInst %void %1 DebugTypeBasic %5 %uint_32 Signed
+         %15 = OpExtInst %void %1 DebugGlobalVariable %4 %14 %12 1 12 %13 %4 %11 FlagIsDefinition
+          %2 = OpFunction %void None %10
+         %16 = OpLabel
+               OpReturn
+               OpFunctionEnd
+)";
+
+  std::unique_ptr<IRContext> context =
+      BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
+
+  // Delete the second variable.
+  context->KillDef(11);
+
+  // Get DebugInfoNone id.
+  uint32_t debug_info_none_id = 0;
+  for (auto it = context->ext_inst_debuginfo_begin();
+       it != context->ext_inst_debuginfo_end(); ++it) {
+    if (it->GetOpenCL100DebugOpcode() == OpenCLDebugInfo100DebugInfoNone) {
+      debug_info_none_id = it->result_id();
+    }
+  }
+  EXPECT_NE(0, debug_info_none_id);
+
+  // Check the Function operand of DebugFunction is DebugInfoNone.
+  const uint32_t kDebugGlobalVariableOperandVariableIndex = 11;
+  bool checked = false;
+  for (auto it = context->ext_inst_debuginfo_begin();
+       it != context->ext_inst_debuginfo_end(); ++it) {
+    if (it->GetOpenCL100DebugOpcode() ==
+        OpenCLDebugInfo100DebugGlobalVariable) {
+      EXPECT_FALSE(checked);
+      EXPECT_EQ(
+          it->GetOperand(kDebugGlobalVariableOperandVariableIndex).words[0],
+          debug_info_none_id);
+      checked = true;
+    }
+  }
+  EXPECT_TRUE(checked);
+}
+
 TEST_F(IRContextTest, BasicVisitFromEntryPoint) {
   // Make sure we visit the entry point, and the function it calls.
   // Do not visit Dead or Exported.
diff --git a/third_party/spirv-tools/src/test/opt/ir_loader_test.cpp b/third_party/spirv-tools/src/test/opt/ir_loader_test.cpp
index c60e853..50e3a08 100644
--- a/third_party/spirv-tools/src/test/opt/ir_loader_test.cpp
+++ b/third_party/spirv-tools/src/test/opt/ir_loader_test.cpp
@@ -234,34 +234,33 @@
 %44 = OpExtInst %void %1 DebugLocalVariable %16 %40 %34 6 16 %43 FlagIsLocal 0
 %45 = OpExtInst %void %1 DebugLocalVariable %17 %40 %34 7 16 %43 FlagIsLocal 1
 %46 = OpExtInst %void %1 DebugLocalVariable %18 %36 %34 8 3 %43 FlagIsLocal
-%47 = OpExtInst %void %1 DebugDeclare %44 %pos %42
-%48 = OpExtInst %void %1 DebugDeclare %45 %color %42
 OpLine %7 6 1
 %main = OpFunction %void None %31
-%49 = OpLabel
-%50 = OpExtInst %void %1 DebugScope %43
+%47 = OpLabel
+%60 = OpExtInst %void %1 DebugScope %43
 OpLine %7 8 13
 %vout = OpVariable %_ptr_Function_VS_OUTPUT Function
-%51 = OpExtInst %void %1 DebugDeclare %46 %vout %42
+%49 = OpExtInst %void %1 DebugDeclare %46 %vout %42
 OpLine %7 9 14
-%52 = OpLoad %v4float %pos
+%50 = OpLoad %v4float %pos
 OpLine %7 9 3
-%53 = OpAccessChain %_ptr_Function_v4float %vout %int_0
-%54 = OpExtInst %void %1 DebugValue %46 %53 %42 %int_0
-OpStore %53 %52
+%51 = OpAccessChain %_ptr_Function_v4float %vout %int_0
+%52 = OpExtInst %void %1 DebugValue %46 %51 %42 %int_0
+OpStore %51 %50
 OpLine %7 10 16
-%55 = OpLoad %v4float %color
+%53 = OpLoad %v4float %color
 OpLine %7 10 3
-%56 = OpAccessChain %_ptr_Function_v4float %vout %int_1
-%57 = OpExtInst %void %1 DebugValue %46 %56 %42 %int_1
-OpStore %56 %55
+%54 = OpAccessChain %_ptr_Function_v4float %vout %int_1
+%55 = OpExtInst %void %1 DebugValue %46 %54 %42 %int_1
+OpStore %54 %53
 OpLine %7 11 10
-%58 = OpLoad %VS_OUTPUT %vout
+%56 = OpLoad %VS_OUTPUT %vout
 OpLine %7 11 3
-%59 = OpCompositeExtract %v4float %58 0
-OpStore %gl_Position %59
-%60 = OpCompositeExtract %v4float %58 1
-OpStore %out_var_COLOR %60
+%57 = OpCompositeExtract %v4float %56 0
+OpStore %gl_Position %57
+%58 = OpCompositeExtract %v4float %56 1
+OpStore %out_var_COLOR %58
+%61 = OpExtInst %void %1 DebugNoScope
 OpReturn
 OpFunctionEnd
 )");
@@ -377,7 +376,7 @@
 OpLine %5 12 1
 %main = OpFunction %void None %36
 %bb_entry = OpLabel
-%52 = OpExtInst %void %1 DebugScope %47
+%70 = OpExtInst %void %1 DebugScope %47
 OpLine %5 13 16
 %param_var_arg1 = OpVariable %_ptr_Function_float Function
 %53 = OpLoad %float %pos
@@ -386,6 +385,7 @@
 %54 = OpFunctionCall %v4float %func1 %param_var_arg1
 OpLine %5 13 3
 OpStore %gl_Position %54
+%71 = OpExtInst %void %1 DebugNoScope
 OpReturn
 OpFunctionEnd
 OpLine %5 5 1
@@ -393,41 +393,45 @@
 OpLine %5 5 20
 %arg1 = OpFunctionParameter %_ptr_Function_float
 %bb_entry_0 = OpLabel
-%55 = OpExtInst %void %1 DebugScope %48
+%72 = OpExtInst %void %1 DebugScope %48
 OpLine %5 9 16
 %param_var_arg2 = OpVariable %_ptr_Function_float Function
 OpLine %5 6 7
-%56 = OpLoad %float %arg1
+%57 = OpLoad %float %arg1
 OpLine %5 6 12
-%57 = OpFOrdGreaterThan %bool %56 %float_1
+%58 = OpFOrdGreaterThan %bool %57 %float_1
 OpLine %5 6 17
+%73 = OpExtInst %void %1 DebugNoScope
 OpSelectionMerge %if_merge None
-OpBranchConditional %57 %if_true %if_merge
+OpBranchConditional %58 %if_true %if_merge
 %if_true = OpLabel
-%58 = OpExtInst %void %1 DebugScope %50
+%74 = OpExtInst %void %1 DebugScope %50
 OpLine %5 7 5
+%75 = OpExtInst %void %1 DebugNoScope
 OpReturnValue %32
 %if_merge = OpLabel
-%59 = OpExtInst %void %1 DebugScope %51
+%76 = OpExtInst %void %1 DebugScope %51
 OpLine %5 9 16
-%60 = OpLoad %float %arg1
-OpStore %param_var_arg2 %60
+%63 = OpLoad %float %arg1
+OpStore %param_var_arg2 %63
 OpLine %5 9 10
-%61 = OpFunctionCall %v4float %func2 %param_var_arg2
+%64 = OpFunctionCall %v4float %func2 %param_var_arg2
 OpLine %5 9 3
-OpReturnValue %61
+%77 = OpExtInst %void %1 DebugNoScope
+OpReturnValue %64
 OpFunctionEnd
 OpLine %5 1 1
 %func2 = OpFunction %v4float None %38
 OpLine %5 1 20
 %arg2 = OpFunctionParameter %_ptr_Function_float
 %bb_entry_1 = OpLabel
-%62 = OpExtInst %void %1 DebugScope %49
+%78 = OpExtInst %void %1 DebugScope %49
 OpLine %5 2 17
-%63 = OpLoad %float %arg2
-%64 = OpCompositeConstruct %v4float %63 %float_0 %float_0 %float_0
+%67 = OpLoad %float %arg2
+%68 = OpCompositeConstruct %v4float %67 %float_0 %float_0 %float_0
 OpLine %5 2 3
-OpReturnValue %64
+%79 = OpExtInst %void %1 DebugNoScope
+OpReturnValue %68
 OpFunctionEnd
 )");
 }
@@ -547,28 +551,31 @@
 OpLine %5 12 1
 %main = OpFunction %void None %28
 %bb_entry = OpLabel
-%51 = OpExtInst %void %1 DebugScope %44 %49
+%62 = OpExtInst %void %1 DebugScope %44 %49
 OpLine %5 6 7
 %52 = OpLoad %float %pos
 OpLine %5 6 12
 %53 = OpFOrdGreaterThan %bool %52 %float_1
 OpLine %5 6 17
+%63 = OpExtInst %void %1 DebugNoScope
 OpSelectionMerge %if_merge None
 OpBranchConditional %53 %if_true %if_merge
 %if_true = OpLabel
-%54 = OpExtInst %void %1 DebugScope %46 %49
+%64 = OpExtInst %void %1 DebugScope %46 %49
 OpLine %5 7 5
 OpStore %gl_Position %24
+%65 = OpExtInst %void %1 DebugNoScope
 OpReturn
 %if_merge = OpLabel
-%55 = OpExtInst %void %1 DebugScope %45 %50
+%66 = OpExtInst %void %1 DebugScope %45 %50
 OpLine %5 2 17
-%56 = OpLoad %float %pos
+%58 = OpLoad %float %pos
 OpLine %5 2 10
-%57 = OpCompositeConstruct %v4float %56 %float_0 %float_0 %float_0
-%58 = OpExtInst %void %1 DebugScope %43
+%59 = OpCompositeConstruct %v4float %58 %float_0 %float_0 %float_0
+%67 = OpExtInst %void %1 DebugScope %43
 OpLine %5 13 3
-OpStore %gl_Position %57
+OpStore %gl_Position %59
+%68 = OpExtInst %void %1 DebugNoScope
 OpReturn
 OpFunctionEnd
 )");
@@ -683,8 +690,8 @@
 %51 = OpExtInst %void %1 DebugLexicalBlock %40 9 3 %48
 OpLine %5 12 1
 %main = OpFunction %void None %36
-%52 = OpExtInst %void %1 DebugScope %47
 %bb_entry = OpLabel
+%70 = OpExtInst %void %1 DebugScope %47
 OpLine %5 13 16
 %param_var_arg1 = OpVariable %_ptr_Function_float Function
 %53 = OpLoad %float %pos
@@ -693,6 +700,7 @@
 %54 = OpFunctionCall %v4float %func1 %param_var_arg1
 OpLine %5 13 3
 OpStore %gl_Position %54
+%71 = OpExtInst %void %1 DebugNoScope
 OpReturn
 OpFunctionEnd
 OpLine %5 5 1
@@ -700,48 +708,244 @@
 OpLine %5 5 20
 %arg1 = OpFunctionParameter %_ptr_Function_float
 %bb_entry_0 = OpLabel
-%55 = OpExtInst %void %1 DebugScope %48
+%72 = OpExtInst %void %1 DebugScope %48
 OpLine %5 9 16
 %param_var_arg2 = OpVariable %_ptr_Function_float Function
 OpLine %5 6 7
-%56 = OpLoad %float %arg1
+%57 = OpLoad %float %arg1
 OpLine %5 6 12
-%57 = OpFOrdGreaterThan %bool %56 %float_1
+%58 = OpFOrdGreaterThan %bool %57 %float_1
 OpLine %5 6 17
+%73 = OpExtInst %void %1 DebugNoScope
 OpSelectionMerge %if_merge None
-OpBranchConditional %57 %if_true %if_merge
+OpBranchConditional %58 %if_true %if_merge
 %if_true = OpLabel
-%58 = OpExtInst %void %1 DebugScope %50
+%74 = OpExtInst %void %1 DebugScope %50
 OpLine %5 7 5
+%75 = OpExtInst %void %1 DebugNoScope
 OpReturnValue %32
 %if_merge = OpLabel
-%59 = OpExtInst %void %1 DebugScope %51
+%76 = OpExtInst %void %1 DebugScope %51
 OpLine %5 9 16
-%60 = OpLoad %float %arg1
-OpStore %param_var_arg2 %60
+%63 = OpLoad %float %arg1
+OpStore %param_var_arg2 %63
 OpLine %5 9 10
-%61 = OpFunctionCall %v4float %func2 %param_var_arg2
+%64 = OpFunctionCall %v4float %func2 %param_var_arg2
 OpLine %5 9 3
-OpReturnValue %61
+%77 = OpExtInst %void %1 DebugNoScope
+OpReturnValue %64
 OpFunctionEnd
 OpLine %5 1 1
 %func2 = OpFunction %v4float None %38
 OpLine %5 1 20
 %arg2 = OpFunctionParameter %_ptr_Function_float
 %bb_entry_1 = OpLabel
-%62 = OpExtInst %void %1 DebugScope %49
+%78 = OpExtInst %void %1 DebugScope %49
 OpLine %5 2 17
-%63 = OpLoad %float %arg2
-%64 = OpCompositeConstruct %v4float %63 %float_0 %float_0 %float_0
+%67 = OpLoad %float %arg2
+%68 = OpCompositeConstruct %v4float %67 %float_0 %float_0 %float_0
 OpLine %5 2 3
-OpReturnValue %64
+%79 = OpExtInst %void %1 DebugNoScope
+OpReturnValue %68
 OpFunctionEnd
 )";
 
   SpirvTools t(SPV_ENV_UNIVERSAL_1_1);
   std::unique_ptr<IRContext> context =
       BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text);
-  ASSERT_EQ(nullptr, context);
+  ASSERT_NE(nullptr, context);
+
+  std::vector<uint32_t> binary;
+  context->module()->ToBinary(&binary, /* skip_nop = */ false);
+
+  std::string disassembled_text;
+  EXPECT_TRUE(t.Disassemble(binary, &disassembled_text));
+  EXPECT_EQ(text, disassembled_text);
+}
+
+TEST(IrBuilder, DebugInfoInstInFunctionOutOfBlock2) {
+  // /* HLSL */
+  //
+  // struct VS_OUTPUT {
+  //   float4 pos : SV_POSITION;
+  //   float4 color : COLOR;
+  // };
+  //
+  // VS_OUTPUT main(float4 pos : POSITION,
+  //                float4 color : COLOR) {
+  //   VS_OUTPUT vout;
+  //   vout.pos = pos;
+  //   vout.color = color;
+  //   return vout;
+  // }
+  const std::string text = R"(OpCapability Shader
+%1 = OpExtInstImport "OpenCL.DebugInfo.100"
+OpMemoryModel Logical GLSL450
+OpEntryPoint Vertex %main "main" %in_var_POSITION %in_var_COLOR %gl_Position %out_var_COLOR
+%7 = OpString "vs.hlsl"
+OpSource HLSL 600 %7 "#line 1 \"vs.hlsl\"
+struct VS_OUTPUT {
+  float4 pos : SV_POSITION;
+  float4 color : COLOR;
+};
+
+VS_OUTPUT main(float4 pos : POSITION,
+               float4 color : COLOR) {
+  VS_OUTPUT vout;
+  vout.pos = pos;
+  vout.color = color;
+  return vout;
+}
+"
+%8 = OpString "#line 1 \"vs.hlsl\"
+struct VS_OUTPUT {
+  float4 pos : SV_POSITION;
+  float4 color : COLOR;
+};
+
+VS_OUTPUT main(float4 pos : POSITION,
+               float4 color : COLOR) {
+  VS_OUTPUT vout;
+  vout.pos = pos;
+  vout.color = color;
+  return vout;
+}
+"
+%9 = OpString "VS_OUTPUT"
+%10 = OpString "float"
+%11 = OpString "src.main"
+%12 = OpString "pos"
+%13 = OpString "color"
+%14 = OpString "vout"
+OpName %in_var_POSITION "in.var.POSITION"
+OpName %in_var_COLOR "in.var.COLOR"
+OpName %out_var_COLOR "out.var.COLOR"
+OpName %main "main"
+OpName %param_var_pos "param.var.pos"
+OpName %param_var_color "param.var.color"
+OpName %VS_OUTPUT "VS_OUTPUT"
+OpMemberName %VS_OUTPUT 0 "pos"
+OpMemberName %VS_OUTPUT 1 "color"
+OpName %src_main "src.main"
+OpName %pos "pos"
+OpName %color "color"
+OpName %bb_entry "bb.entry"
+OpName %vout "vout"
+OpDecorate %gl_Position BuiltIn Position
+OpDecorate %in_var_POSITION Location 0
+OpDecorate %in_var_COLOR Location 1
+OpDecorate %out_var_COLOR Location 0
+%int = OpTypeInt 32 1
+%int_0 = OpConstant %int 0
+%int_1 = OpConstant %int 1
+%uint = OpTypeInt 32 0
+%uint_32 = OpConstant %uint 32
+%float = OpTypeFloat 32
+%v4float = OpTypeVector %float 4
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%void = OpTypeVoid
+%uint_256 = OpConstant %uint 256
+%uint_0 = OpConstant %uint 0
+%uint_128 = OpConstant %uint 128
+%36 = OpTypeFunction %void
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+%VS_OUTPUT = OpTypeStruct %v4float %v4float
+%38 = OpTypeFunction %VS_OUTPUT %_ptr_Function_v4float %_ptr_Function_v4float
+%_ptr_Function_VS_OUTPUT = OpTypePointer Function %VS_OUTPUT
+OpLine %7 6 29
+%in_var_POSITION = OpVariable %_ptr_Input_v4float Input
+OpLine %7 7 31
+%in_var_COLOR = OpVariable %_ptr_Input_v4float Input
+OpLine %7 2 16
+%gl_Position = OpVariable %_ptr_Output_v4float Output
+OpLine %7 3 18
+%out_var_COLOR = OpVariable %_ptr_Output_v4float Output
+%40 = OpExtInst %void %1 DebugExpression
+%41 = OpExtInst %void %1 DebugSource %7 %8
+%42 = OpExtInst %void %1 DebugCompilationUnit 1 4 %41 HLSL
+%43 = OpExtInst %void %1 DebugTypeComposite %9 Structure %41 1 1 %42 %9 %uint_256 FlagIsProtected|FlagIsPrivate %44 %45
+%46 = OpExtInst %void %1 DebugTypeBasic %10 %uint_32 Float
+%47 = OpExtInst %void %1 DebugTypeVector %46 4
+%48 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %43 %47 %47
+%49 = OpExtInst %void %1 DebugFunction %11 %48 %41 6 1 %42 %11 FlagIsProtected|FlagIsPrivate 7 %src_main
+%50 = OpExtInst %void %1 DebugLocalVariable %12 %47 %41 6 23 %49 FlagIsLocal 0
+%51 = OpExtInst %void %1 DebugLocalVariable %13 %47 %41 7 23 %49 FlagIsLocal 1
+%52 = OpExtInst %void %1 DebugLexicalBlock %41 7 38 %49
+%53 = OpExtInst %void %1 DebugLocalVariable %14 %43 %41 8 13 %52 FlagIsLocal
+%44 = OpExtInst %void %1 DebugTypeMember %12 %47 %41 2 3 %43 %uint_0 %uint_128 FlagIsProtected|FlagIsPrivate
+%45 = OpExtInst %void %1 DebugTypeMember %13 %47 %41 3 3 %43 %uint_128 %uint_128 FlagIsProtected|FlagIsPrivate
+OpLine %7 6 1
+%main = OpFunction %void None %36
+%54 = OpLabel
+%74 = OpExtInst %void %1 DebugScope %42
+OpLine %7 6 23
+%param_var_pos = OpVariable %_ptr_Function_v4float Function
+OpLine %7 7 23
+%param_var_color = OpVariable %_ptr_Function_v4float Function
+OpLine %7 6 23
+%56 = OpLoad %v4float %in_var_POSITION
+OpStore %param_var_pos %56
+OpLine %7 7 23
+%57 = OpLoad %v4float %in_var_COLOR
+OpStore %param_var_color %57
+OpLine %7 6 1
+%58 = OpFunctionCall %VS_OUTPUT %src_main %param_var_pos %param_var_color
+OpLine %7 6 11
+%59 = OpCompositeExtract %v4float %58 0
+OpLine %7 2 16
+OpStore %gl_Position %59
+OpLine %7 6 11
+%60 = OpCompositeExtract %v4float %58 1
+OpLine %7 3 18
+OpStore %out_var_COLOR %60
+%75 = OpExtInst %void %1 DebugNoScope
+OpReturn
+OpFunctionEnd
+OpLine %7 6 1
+%src_main = OpFunction %VS_OUTPUT None %38
+%76 = OpExtInst %void %1 DebugScope %49
+OpLine %7 6 23
+%pos = OpFunctionParameter %_ptr_Function_v4float
+OpLine %7 7 23
+%color = OpFunctionParameter %_ptr_Function_v4float
+%63 = OpExtInst %void %1 DebugDeclare %50 %pos %40
+%64 = OpExtInst %void %1 DebugDeclare %51 %color %40
+%77 = OpExtInst %void %1 DebugNoScope
+%bb_entry = OpLabel
+%78 = OpExtInst %void %1 DebugScope %52
+OpLine %7 8 13
+%vout = OpVariable %_ptr_Function_VS_OUTPUT Function
+%67 = OpExtInst %void %1 DebugDeclare %53 %vout %40
+OpLine %7 9 14
+%68 = OpLoad %v4float %pos
+OpLine %7 9 3
+%69 = OpAccessChain %_ptr_Function_v4float %vout %int_0
+OpStore %69 %68
+OpLine %7 10 16
+%70 = OpLoad %v4float %color
+OpLine %7 10 3
+%71 = OpAccessChain %_ptr_Function_v4float %vout %int_1
+OpStore %71 %70
+OpLine %7 11 10
+%72 = OpLoad %VS_OUTPUT %vout
+OpLine %7 11 3
+%79 = OpExtInst %void %1 DebugNoScope
+OpReturnValue %72
+OpFunctionEnd
+)";
+
+  SpirvTools t(SPV_ENV_UNIVERSAL_1_1);
+  std::unique_ptr<IRContext> context =
+      BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text);
+  ASSERT_NE(nullptr, context);
+
+  std::vector<uint32_t> binary;
+  context->module()->ToBinary(&binary, /* skip_nop = */ false);
+
+  std::string disassembled_text;
+  EXPECT_TRUE(t.Disassemble(binary, &disassembled_text));
+  EXPECT_EQ(text, disassembled_text);
 }
 
 TEST(IrBuilder, LocalGlobalVariables) {
diff --git a/third_party/spirv-tools/src/test/opt/local_redundancy_elimination_test.cpp b/third_party/spirv-tools/src/test/opt/local_redundancy_elimination_test.cpp
index bc4635e..291e1bc 100644
--- a/third_party/spirv-tools/src/test/opt/local_redundancy_elimination_test.cpp
+++ b/third_party/spirv-tools/src/test/opt/local_redundancy_elimination_test.cpp
@@ -154,6 +154,50 @@
   SinglePassRunAndMatch<LocalRedundancyEliminationPass>(text, false);
 }
 
+TEST_F(LocalRedundancyEliminationTest, StorageBufferIdentification) {
+  const std::string text = R"(
+; CHECK: [[gep:%\w+]] = OpAccessChain
+; CHECK: [[ld:%\w+]] = OpLoad {{%\w+}} [[gep]]
+; CHECK: [[add:%\w+]] = OpIAdd {{%\w+}} [[ld]]
+; CHECK: OpStore [[gep]] [[add]]
+; CHECK: [[ld:%\w+]] = OpLoad {{%\w+}} [[gep]]
+; CHECK: [[add:%\w+]] = OpIAdd {{%\w+}} [[ld]]
+; CHECK: OpStore [[gep]] [[add]]
+
+OpCapability Shader
+OpCapability Linkage
+OpMemoryModel Logical GLSL450
+OpDecorate %block BufferBlock
+OpMemberDecorate %block 0 Offset 0
+%void = OpTypeVoid
+%int = OpTypeInt 32 0
+%int_0 = OpConstant %int 0
+%int_1 = OpConstant %int 1
+%block = OpTypeStruct %int
+%array = OpTypeArray %block %int_1
+%ptr_ssbo_array = OpTypePointer Uniform %array
+%ptr_ssbo_int = OpTypePointer Uniform %int
+%var = OpVariable %ptr_ssbo_array Uniform
+%void_fn = OpTypeFunction %void
+%fn = OpFunction %void None %void_fn
+%entry = OpLabel
+%gep1 = OpAccessChain %ptr_ssbo_int %var %int_0 %int_0
+%ld1 = OpLoad %int %gep1
+%add1 = OpIAdd %int %ld1 %int_1
+%gep2 = OpAccessChain %ptr_ssbo_int %var %int_0 %int_0
+OpStore %gep2 %add1
+%gep3 = OpAccessChain %ptr_ssbo_int %var %int_0 %int_0
+%ld3 = OpLoad %int %gep3
+%add3 = OpIAdd %int %ld3 %int_1
+%gep4 = OpAccessChain %ptr_ssbo_int %var %int_0 %int_0
+OpStore %gep4 %add3
+OpReturn
+OpFunctionEnd
+)";
+
+  SinglePassRunAndMatch<LocalRedundancyEliminationPass>(text, true);
+}
+
 }  // namespace
 }  // namespace opt
 }  // namespace spvtools
diff --git a/third_party/spirv-tools/src/test/opt/loop_optimizations/loop_descriptions.cpp b/third_party/spirv-tools/src/test/opt/loop_optimizations/loop_descriptions.cpp
index 91dbdc6..4d2f989 100644
--- a/third_party/spirv-tools/src/test/opt/loop_optimizations/loop_descriptions.cpp
+++ b/third_party/spirv-tools/src/test/opt/loop_optimizations/loop_descriptions.cpp
@@ -379,6 +379,43 @@
   EXPECT_EQ(loop.GetLatchBlock()->id(), 30u);
 }
 
+TEST_F(PassClassTest, UnreachableMerge) {
+  const std::string text = R"(
+               OpCapability Shader
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %1 "main"
+               OpExecutionMode %1 OriginUpperLeft
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+          %1 = OpFunction %void None %3
+          %4 = OpLabel
+               OpBranch %5
+          %5 = OpLabel
+               OpLoopMerge %6 %7 None
+               OpBranch %8
+          %8 = OpLabel
+               OpBranch %9
+          %9 = OpLabel
+               OpBranch %7
+          %7 = OpLabel
+               OpBranch %5
+          %6 = OpLabel
+               OpUnreachable
+               OpFunctionEnd
+)";
+
+  std::unique_ptr<IRContext> context =
+      BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text,
+                  SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+  Module* module = context->module();
+  EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n"
+                             << text << std::endl;
+  const Function* f = spvtest::GetFunction(module, 1);
+  LoopDescriptor ld{context.get(), f};
+
+  EXPECT_EQ(ld.NumLoops(), 1u);
+}
+
 }  // namespace
 }  // namespace opt
 }  // namespace spvtools
diff --git a/third_party/spirv-tools/src/test/opt/struct_cfg_analysis_test.cpp b/third_party/spirv-tools/src/test/opt/struct_cfg_analysis_test.cpp
index 0451a8b..2d1deec 100644
--- a/third_party/spirv-tools/src/test/opt/struct_cfg_analysis_test.cpp
+++ b/third_party/spirv-tools/src/test/opt/struct_cfg_analysis_test.cpp
@@ -1369,6 +1369,35 @@
   auto c = analysis.FindFuncsCalledFromContinue();
   EXPECT_THAT(c, UnorderedElementsAre(14u, 16u, 21u));
 }
+
+TEST_F(StructCFGAnalysisTest, SingleBlockLoop) {
+  const std::string text = R"(
+              OpCapability Shader
+              OpCapability Linkage
+              OpMemoryModel Logical GLSL450
+      %void = OpTypeVoid
+      %bool = OpTypeBool
+     %undef = OpUndef %bool
+   %void_fn = OpTypeFunction %void
+      %main = OpFunction %void None %void_fn
+         %2 = OpLabel
+              OpBranch %3
+         %3 = OpLabel
+              OpLoopMerge %4 %3 None
+              OpBranchConditional %undef %3 %4
+         %4 = OpLabel
+              OpReturn
+              OpFunctionEnd
+)";
+
+  std::unique_ptr<IRContext> context =
+      BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
+                  SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+
+  StructuredCFGAnalysis analysis(context.get());
+
+  EXPECT_TRUE(analysis.IsInContinueConstruct(3));
+}
 }  // namespace
 }  // namespace opt
 }  // namespace spvtools
diff --git a/third_party/spirv-tools/src/test/opt/value_table_test.cpp b/third_party/spirv-tools/src/test/opt/value_table_test.cpp
index a0942cc..76e7f73 100644
--- a/third_party/spirv-tools/src/test/opt/value_table_test.cpp
+++ b/third_party/spirv-tools/src/test/opt/value_table_test.cpp
@@ -684,6 +684,50 @@
   vtable.GetValueNumber(inst);
 }
 
+TEST_F(ValueTableTest, RedundantSampledImageLoad) {
+  const std::string text = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main" %gl_FragColor
+               OpExecutionMode %main OriginLowerLeft
+               OpSource GLSL 330
+               OpName %main "main"
+               OpName %tex0 "tex0"
+               OpName %gl_FragColor "gl_FragColor"
+               OpDecorate %tex0 Location 0
+               OpDecorate %tex0 DescriptorSet 0
+               OpDecorate %tex0 Binding 0
+               OpDecorate %gl_FragColor Location 0
+       %void = OpTypeVoid
+          %6 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+          %9 = OpTypeImage %float 2D 0 0 0 1 Unknown
+         %10 = OpTypeSampledImage %9
+%_ptr_UniformConstant_10 = OpTypePointer UniformConstant %10
+       %tex0 = OpVariable %_ptr_UniformConstant_10 UniformConstant
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+         %13 = OpConstantNull %v4float
+%gl_FragColor = OpVariable %_ptr_Output_v4float Output
+         %14 = OpUndef %v4float
+       %main = OpFunction %void None %6
+         %15 = OpLabel
+         %16 = OpLoad %10 %tex0
+         %17 = OpImageSampleProjImplicitLod %v4float %16 %13
+         %18 = OpImageSampleProjImplicitLod %v4float %16 %13
+         %19 = OpFAdd %v4float %18 %17
+               OpStore %gl_FragColor %19
+               OpReturn
+               OpFunctionEnd
+  )";
+  auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
+  ValueNumberTable vtable(context.get());
+  Instruction* load1 = context->get_def_use_mgr()->GetDef(17);
+  Instruction* load2 = context->get_def_use_mgr()->GetDef(18);
+  EXPECT_EQ(vtable.GetValueNumber(load1), vtable.GetValueNumber(load2));
+}
+
 }  // namespace
 }  // namespace opt
 }  // namespace spvtools
diff --git a/third_party/spirv-tools/src/test/opt/wrap_opkill_test.cpp b/third_party/spirv-tools/src/test/opt/wrap_opkill_test.cpp
index d50af28..359a9f2 100644
--- a/third_party/spirv-tools/src/test/opt/wrap_opkill_test.cpp
+++ b/third_party/spirv-tools/src/test/opt/wrap_opkill_test.cpp
@@ -513,6 +513,82 @@
   EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
 }
 
+TEST_F(WrapOpKillTest, SetParentBlock) {
+  const std::string text = R"(
+OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint Fragment %main "main"
+OpExecutionMode %main OriginUpperLeft
+%void = OpTypeVoid
+%bool = OpTypeBool
+%undef = OpUndef %bool
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+OpBranch %loop
+%loop = OpLabel
+OpLoopMerge %merge %continue None
+OpBranchConditional %undef %merge %continue
+%continue = OpLabel
+%call = OpFunctionCall %void %kill_func
+OpBranch %loop
+%merge = OpLabel
+OpReturn
+OpFunctionEnd
+%kill_func = OpFunction %void None %void_fn
+%kill_entry = OpLabel
+OpKill
+OpFunctionEnd
+)";
+
+  auto result = SinglePassRunToBinary<WrapOpKill>(text, true);
+  EXPECT_EQ(Pass::Status::SuccessWithChange, std::get<1>(result));
+  result = SinglePassRunToBinary<WrapOpKill>(text, true);
+  EXPECT_EQ(Pass::Status::SuccessWithChange, std::get<1>(result));
+}
+
+TEST_F(WrapOpKillTest, KillInSingleBlockLoop) {
+  const std::string text = R"(
+; CHECK: OpFunction %void
+; CHECK: OpFunction %void
+; CHECK-NOT: OpKill
+; CHECK: OpFunctionCall %void [[new_kill:%\w+]]
+; CHECK-NOT: OpKill
+; CHECK: [[new_kill]] = OpFunction
+; CHECK-NEXT: OpLabel
+; CHECK-NEXT: OpKill
+; CHECK-NEXT: OpFunctionEnd
+              OpCapability Shader
+              OpCapability Linkage
+              OpMemoryModel Logical GLSL450
+      %void = OpTypeVoid
+      %bool = OpTypeBool
+     %undef = OpUndef %bool
+   %void_fn = OpTypeFunction %void
+      %main = OpFunction %void None %void_fn
+%main_entry = OpLabel
+              OpBranch %loop
+      %loop = OpLabel
+      %call = OpFunctionCall %void %sub
+              OpLoopMerge %exit %loop None
+              OpBranchConditional %undef %loop %exit
+      %exit = OpLabel
+              OpReturn
+              OpFunctionEnd
+       %sub = OpFunction %void None %void_fn
+ %sub_entry = OpLabel
+              OpSelectionMerge %ret None
+              OpBranchConditional %undef %kill %ret
+      %kill = OpLabel
+              OpKill
+       %ret = OpLabel
+              OpReturn
+              OpFunctionEnd
+)";
+
+  SinglePassRunAndMatch<WrapOpKill>(text, true);
+}
+
 }  // namespace
 }  // namespace opt
 }  // namespace spvtools
diff --git a/third_party/spirv-tools/src/test/tools/opt/flags.py b/third_party/spirv-tools/src/test/tools/opt/flags.py
index 2f6c0a7..8aaaf31 100644
--- a/third_party/spirv-tools/src/test/tools/opt/flags.py
+++ b/third_party/spirv-tools/src/test/tools/opt/flags.py
@@ -73,7 +73,10 @@
       '--remove-duplicates', '--replace-invalid-opcode', '--ssa-rewrite',
       '--scalar-replacement', '--scalar-replacement=42', '--strength-reduction',
       '--strip-debug', '--strip-reflect', '--vector-dce', '--workaround-1209',
-      '--unify-const'
+      '--unify-const', '--legalize-vector-shuffle',
+      '--split-invalid-unreachable', '--generate-webgpu-initializers',
+      '--decompose-initialized-variables', '--graphics-robust-access',
+      '--wrap-opkill', '--amd-ext-to-khr'
   ]
   expected_passes = [
       'wrap-opkill',
@@ -120,7 +123,14 @@
       'strip-reflect',
       'vector-dce',
       'workaround-1209',
-      'unify-const'
+      'unify-const',
+      'legalize-vector-shuffle',
+      'split-invalid-unreachable',
+      'generate-webgpu-initializers',
+      'decompose-initialized-variables',
+      'graphics-robust-access',
+      'wrap-opkill',
+      'amd-ext-to-khr'
   ]
   shader = placeholder.FileSPIRVShader(empty_main_assembly(), '.spvasm')
   output = placeholder.TempFileName('output.spv')
diff --git a/third_party/spirv-tools/src/test/val/val_capability_test.cpp b/third_party/spirv-tools/src/test/val/val_capability_test.cpp
index 098fa2f..8580818 100644
--- a/third_party/spirv-tools/src/test/val/val_capability_test.cpp
+++ b/third_party/spirv-tools/src/test/val/val_capability_test.cpp
@@ -1229,14 +1229,18 @@
           "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
           ShaderDependencies()),
 std::make_pair(std::string(kOpenCLMemoryModel) +
+          // Block applies to struct type.
           "OpEntryPoint Kernel %func \"compute\" \n"
-          "OpDecorate %intt Block\n"
-          "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
+          "OpDecorate %block Block\n"
+          "%intt = OpTypeInt 32 0\n"
+          "%block = OpTypeStruct %intt\n" + std::string(kVoidFVoid),
           ShaderDependencies()),
 std::make_pair(std::string(kOpenCLMemoryModel) +
+          // BufferBlock applies to struct type.
           "OpEntryPoint Kernel %func \"compute\" \n"
-          "OpDecorate %intt BufferBlock\n"
-          "%intt = OpTypeInt 32 0\n" + std::string(kVoidFVoid),
+          "OpDecorate %block BufferBlock\n"
+          "%intt = OpTypeInt 32 0\n"
+          "%block = OpTypeStruct %intt\n" + std::string(kVoidFVoid),
           ShaderDependencies()),
 std::make_pair(std::string(kOpenCLMemoryModel) +
           "OpEntryPoint Kernel %func \"compute\" \n"
diff --git a/third_party/spirv-tools/src/test/val/val_cfg_test.cpp b/third_party/spirv-tools/src/test/val/val_cfg_test.cpp
index 4cf4029..0d09642 100644
--- a/third_party/spirv-tools/src/test/val/val_cfg_test.cpp
+++ b/third_party/spirv-tools/src/test/val/val_cfg_test.cpp
@@ -4296,6 +4296,213 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
+TEST_F(ValidateCFG, PhiResultInvalidSampler) {
+  const std::string text = R"(
+OpCapability Shader
+OpCapability Linkage
+OpMemoryModel Logical GLSL450
+%void = OpTypeVoid
+%bool = OpTypeBool
+%f32 = OpTypeFloat 32
+%sampler = OpTypeSampler
+%ptr_uc_sampler = OpTypePointer UniformConstant %sampler
+%sampler_var = OpVariable %ptr_uc_sampler UniformConstant
+%undef_bool = OpUndef %bool
+%undef_sampler = OpUndef %sampler
+%void_fn = OpTypeFunction %void
+%fn = OpFunction %void None %void_fn
+%entry = OpLabel
+%ld_sampler = OpLoad %sampler %sampler_var
+OpBranch %loop
+%loop = OpLabel
+%phi = OpPhi %sampler %undef_sampler %entry %ld_sampler %loop
+OpLoopMerge %exit %loop None
+OpBranchConditional %undef_bool %exit %loop
+%exit = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(text);
+  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Result type cannot be OpTypeSampler"));
+}
+
+TEST_F(ValidateCFG, PhiResultInvalidImage) {
+  const std::string text = R"(
+OpCapability Shader
+OpCapability Linkage
+OpMemoryModel Logical GLSL450
+%void = OpTypeVoid
+%bool = OpTypeBool
+%f32 = OpTypeFloat 32
+%image = OpTypeImage %f32 2D 0 0 0 1 Rgba32f
+%ptr_uc_image = OpTypePointer UniformConstant %image
+%image_var = OpVariable %ptr_uc_image UniformConstant
+%undef_bool = OpUndef %bool
+%undef_image = OpUndef %image
+%void_fn = OpTypeFunction %void
+%fn = OpFunction %void None %void_fn
+%entry = OpLabel
+%ld_image = OpLoad %image %image_var
+OpBranch %loop
+%loop = OpLabel
+%phi = OpPhi %image %undef_image %entry %ld_image %loop
+OpLoopMerge %exit %loop None
+OpBranchConditional %undef_bool %exit %loop
+%exit = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(text);
+  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Result type cannot be OpTypeImage"));
+}
+
+TEST_F(ValidateCFG, PhiResultInvalidSampledImage) {
+  const std::string text = R"(
+OpCapability Shader
+OpCapability Linkage
+OpMemoryModel Logical GLSL450
+%void = OpTypeVoid
+%bool = OpTypeBool
+%f32 = OpTypeFloat 32
+%sampler = OpTypeSampler
+%ptr_uc_sampler = OpTypePointer UniformConstant %sampler
+%sampler_var = OpVariable %ptr_uc_sampler UniformConstant
+%image = OpTypeImage %f32 2D 0 0 0 1 Rgba32f
+%ptr_uc_image = OpTypePointer UniformConstant %image
+%image_var = OpVariable %ptr_uc_image UniformConstant
+%sampled_image = OpTypeSampledImage %image
+%undef_bool = OpUndef %bool
+%undef_sampled_image = OpUndef %sampled_image
+%void_fn = OpTypeFunction %void
+%fn = OpFunction %void None %void_fn
+%entry = OpLabel
+%ld_image = OpLoad %image %image_var
+%ld_sampler = OpLoad %sampler %sampler_var
+OpBranch %loop
+%loop = OpLabel
+%phi = OpPhi %sampled_image %undef_sampled_image %entry %sample %loop
+%sample = OpSampledImage %sampled_image %ld_image %ld_sampler
+OpLoopMerge %exit %loop None
+OpBranchConditional %undef_bool %exit %loop
+%exit = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(text);
+  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Result type cannot be OpTypeSampledImage"));
+}
+
+TEST_F(ValidateCFG, PhiResultValidPreLegalizationSampler) {
+  const std::string text = R"(
+OpCapability Shader
+OpCapability Linkage
+OpMemoryModel Logical GLSL450
+%void = OpTypeVoid
+%bool = OpTypeBool
+%f32 = OpTypeFloat 32
+%sampler = OpTypeSampler
+%ptr_uc_sampler = OpTypePointer UniformConstant %sampler
+%sampler_var = OpVariable %ptr_uc_sampler UniformConstant
+%undef_bool = OpUndef %bool
+%undef_sampler = OpUndef %sampler
+%void_fn = OpTypeFunction %void
+%fn = OpFunction %void None %void_fn
+%entry = OpLabel
+%ld_sampler = OpLoad %sampler %sampler_var
+OpBranch %loop
+%loop = OpLabel
+%phi = OpPhi %sampler %undef_sampler %entry %ld_sampler %loop
+OpLoopMerge %exit %loop None
+OpBranchConditional %undef_bool %exit %loop
+%exit = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  options_->before_hlsl_legalization = true;
+  CompileSuccessfully(text);
+  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateCFG, PhiResultValidPreLegalizationImage) {
+  const std::string text = R"(
+OpCapability Shader
+OpCapability Linkage
+OpMemoryModel Logical GLSL450
+%void = OpTypeVoid
+%bool = OpTypeBool
+%f32 = OpTypeFloat 32
+%image = OpTypeImage %f32 2D 0 0 0 1 Rgba32f
+%ptr_uc_image = OpTypePointer UniformConstant %image
+%image_var = OpVariable %ptr_uc_image UniformConstant
+%undef_bool = OpUndef %bool
+%undef_image = OpUndef %image
+%void_fn = OpTypeFunction %void
+%fn = OpFunction %void None %void_fn
+%entry = OpLabel
+%ld_image = OpLoad %image %image_var
+OpBranch %loop
+%loop = OpLabel
+%phi = OpPhi %image %undef_image %entry %ld_image %loop
+OpLoopMerge %exit %loop None
+OpBranchConditional %undef_bool %exit %loop
+%exit = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  options_->before_hlsl_legalization = true;
+  CompileSuccessfully(text);
+  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateCFG, PhiResultValidPreLegalizationSampledImage) {
+  const std::string text = R"(
+OpCapability Shader
+OpCapability Linkage
+OpMemoryModel Logical GLSL450
+%void = OpTypeVoid
+%bool = OpTypeBool
+%f32 = OpTypeFloat 32
+%sampler = OpTypeSampler
+%ptr_uc_sampler = OpTypePointer UniformConstant %sampler
+%sampler_var = OpVariable %ptr_uc_sampler UniformConstant
+%image = OpTypeImage %f32 2D 0 0 0 1 Rgba32f
+%ptr_uc_image = OpTypePointer UniformConstant %image
+%image_var = OpVariable %ptr_uc_image UniformConstant
+%sampled_image = OpTypeSampledImage %image
+%undef_bool = OpUndef %bool
+%undef_sampled_image = OpUndef %sampled_image
+%void_fn = OpTypeFunction %void
+%fn = OpFunction %void None %void_fn
+%entry = OpLabel
+%ld_image = OpLoad %image %image_var
+%ld_sampler = OpLoad %sampler %sampler_var
+OpBranch %loop
+%loop = OpLabel
+%phi = OpPhi %sampled_image %undef_sampled_image %entry %sample %loop
+%sample = OpSampledImage %sampled_image %ld_image %ld_sampler
+OpLoopMerge %exit %loop None
+OpBranchConditional %undef_bool %exit %loop
+%exit = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  options_->before_hlsl_legalization = true;
+  CompileSuccessfully(text);
+  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
 }  // namespace
 }  // namespace val
 }  // namespace spvtools
diff --git a/third_party/spirv-tools/src/test/val/val_decoration_test.cpp b/third_party/spirv-tools/src/test/val/val_decoration_test.cpp
index 256e115..ec25d58 100644
--- a/third_party/spirv-tools/src/test/val/val_decoration_test.cpp
+++ b/third_party/spirv-tools/src/test/val/val_decoration_test.cpp
@@ -700,6 +700,61 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
 }
 
+TEST_F(ValidateDecorations, BlockDecoratingArrayBad) {
+  std::string spirv = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpSource GLSL 430
+               OpDecorate %Output Block
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+        %int = OpTypeInt 32 1
+      %int_3 = OpConstant %int 3
+     %Output = OpTypeArray %float %int_3
+%_ptr_Uniform_Output = OpTypePointer Uniform %Output
+ %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  CompileSuccessfully(spirv);
+  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Block decoration on a non-struct type"));
+}
+
+TEST_F(ValidateDecorations, BlockDecoratingIntBad) {
+  std::string spirv = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %main "main"
+               OpExecutionMode %main LocalSize 1 1 1
+               OpSource GLSL 430
+               OpDecorate %Output Block
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+     %Output = OpTypeInt 32 1
+%_ptr_Uniform_Output = OpTypePointer Uniform %Output
+ %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+               OpReturn
+               OpFunctionEnd
+  )";
+
+  CompileSuccessfully(spirv);
+  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Block decoration on a non-struct type"));
+}
+
 TEST_F(ValidateDecorations, BlockMissingOffsetBad) {
   std::string spirv = R"(
                OpCapability Shader
diff --git a/third_party/spirv-tools/src/tools/fuzz/fuzz.cpp b/third_party/spirv-tools/src/tools/fuzz/fuzz.cpp
index 718d038..2c9807d 100644
--- a/third_party/spirv-tools/src/tools/fuzz/fuzz.cpp
+++ b/third_party/spirv-tools/src/tools/fuzz/fuzz.cpp
@@ -145,6 +145,13 @@
   --version
                Display fuzzer version information.
 
+Supported validator options are as follows. See `spirv-val --help` for details.
+  --before-hlsl-legalization
+  --relax-block-layout
+  --relax-logical-pointer
+  --relax-struct-store
+  --scalar-block-layout
+  --skip-block-layout
 )",
       program, program, program, program);
 }
@@ -166,7 +173,8 @@
                       std::vector<std::string>* interestingness_test,
                       std::string* shrink_transformations_file,
                       std::string* shrink_temp_file_prefix,
-                      spvtools::FuzzerOptions* fuzzer_options) {
+                      spvtools::FuzzerOptions* fuzzer_options,
+                      spvtools::ValidatorOptions* validator_options) {
   uint32_t positional_arg_index = 0;
   bool only_positional_arguments_remain = false;
   bool force_render_red = false;
@@ -227,6 +235,18 @@
                               sizeof("--shrinker-temp-file-prefix=") - 1)) {
         const auto split_flag = spvtools::utils::SplitFlagArgs(cur_arg);
         *shrink_temp_file_prefix = std::string(split_flag.second);
+      } else if (0 == strcmp(cur_arg, "--before-hlsl-legalization")) {
+        validator_options->SetBeforeHlslLegalization(true);
+      } else if (0 == strcmp(cur_arg, "--relax-logical-pointer")) {
+        validator_options->SetRelaxLogicalPointer(true);
+      } else if (0 == strcmp(cur_arg, "--relax-block-layout")) {
+        validator_options->SetRelaxBlockLayout(true);
+      } else if (0 == strcmp(cur_arg, "--scalar-block-layout")) {
+        validator_options->SetScalarBlockLayout(true);
+      } else if (0 == strcmp(cur_arg, "--skip-block-layout")) {
+        validator_options->SetSkipBlockLayout(true);
+      } else if (0 == strcmp(cur_arg, "--relax-struct-store")) {
+        validator_options->SetRelaxStructStore(true);
       } else if (0 == strcmp(cur_arg, "--")) {
         only_positional_arguments_remain = true;
       } else {
@@ -357,6 +377,7 @@
 
 bool Replay(const spv_target_env& target_env,
             spv_const_fuzzer_options fuzzer_options,
+            spv_validator_options validator_options,
             const std::vector<uint32_t>& binary_in,
             const spvtools::fuzz::protobufs::FactSequence& initial_facts,
             const std::string& replay_transformations_file,
@@ -368,8 +389,8 @@
                             &transformation_sequence)) {
     return false;
   }
-  spvtools::fuzz::Replayer replayer(target_env,
-                                    fuzzer_options->replay_validation_enabled);
+  spvtools::fuzz::Replayer replayer(
+      target_env, fuzzer_options->replay_validation_enabled, validator_options);
   replayer.SetMessageConsumer(spvtools::utils::CLIMessageConsumer);
   auto replay_result_status =
       replayer.Run(binary_in, initial_facts, transformation_sequence,
@@ -380,6 +401,7 @@
 
 bool Shrink(const spv_target_env& target_env,
             spv_const_fuzzer_options fuzzer_options,
+            spv_validator_options validator_options,
             const std::vector<uint32_t>& binary_in,
             const spvtools::fuzz::protobufs::FactSequence& initial_facts,
             const std::string& shrink_transformations_file,
@@ -393,9 +415,9 @@
                             &transformation_sequence)) {
     return false;
   }
-  spvtools::fuzz::Shrinker shrinker(target_env,
-                                    fuzzer_options->shrinker_step_limit,
-                                    fuzzer_options->replay_validation_enabled);
+  spvtools::fuzz::Shrinker shrinker(
+      target_env, fuzzer_options->shrinker_step_limit,
+      fuzzer_options->replay_validation_enabled, validator_options);
   shrinker.SetMessageConsumer(spvtools::utils::CLIMessageConsumer);
 
   assert(!interestingness_command.empty() &&
@@ -434,6 +456,7 @@
 
 bool Fuzz(const spv_target_env& target_env,
           spv_const_fuzzer_options fuzzer_options,
+          spv_validator_options validator_options,
           const std::vector<uint32_t>& binary_in,
           const spvtools::fuzz::protobufs::FactSequence& initial_facts,
           const std::string& donors, std::vector<uint32_t>* binary_out,
@@ -469,7 +492,7 @@
       fuzzer_options->has_random_seed
           ? fuzzer_options->random_seed
           : static_cast<uint32_t>(std::random_device()()),
-      fuzzer_options->fuzzer_pass_validation_enabled);
+      fuzzer_options->fuzzer_pass_validation_enabled, validator_options);
   fuzzer.SetMessageConsumer(message_consumer);
   auto fuzz_result_status =
       fuzzer.Run(binary_in, initial_facts, donor_suppliers, binary_out,
@@ -513,11 +536,13 @@
   std::string shrink_temp_file_prefix = "temp_";
 
   spvtools::FuzzerOptions fuzzer_options;
+  spvtools::ValidatorOptions validator_options;
 
-  FuzzStatus status = ParseFlags(
-      argc, argv, &in_binary_file, &out_binary_file, &donors_file,
-      &replay_transformations_file, &interestingness_test,
-      &shrink_transformations_file, &shrink_temp_file_prefix, &fuzzer_options);
+  FuzzStatus status =
+      ParseFlags(argc, argv, &in_binary_file, &out_binary_file, &donors_file,
+                 &replay_transformations_file, &interestingness_test,
+                 &shrink_transformations_file, &shrink_temp_file_prefix,
+                 &fuzzer_options, &validator_options);
 
   if (status.action == FuzzActions::STOP) {
     return status.code;
@@ -555,20 +580,22 @@
 
   switch (status.action) {
     case FuzzActions::FORCE_RENDER_RED:
-      if (!spvtools::fuzz::ForceRenderRed(target_env, binary_in, initial_facts,
+      if (!spvtools::fuzz::ForceRenderRed(target_env, validator_options,
+                                          binary_in, initial_facts,
                                           &binary_out)) {
         return 1;
       }
       break;
     case FuzzActions::FUZZ:
-      if (!Fuzz(target_env, fuzzer_options, binary_in, initial_facts,
-                donors_file, &binary_out, &transformations_applied)) {
+      if (!Fuzz(target_env, fuzzer_options, validator_options, binary_in,
+                initial_facts, donors_file, &binary_out,
+                &transformations_applied)) {
         return 1;
       }
       break;
     case FuzzActions::REPLAY:
-      if (!Replay(target_env, fuzzer_options, binary_in, initial_facts,
-                  replay_transformations_file, &binary_out,
+      if (!Replay(target_env, fuzzer_options, validator_options, binary_in,
+                  initial_facts, replay_transformations_file, &binary_out,
                   &transformations_applied)) {
         return 1;
       }
@@ -579,9 +606,9 @@
                   << std::endl;
         return 1;
       }
-      if (!Shrink(target_env, fuzzer_options, binary_in, initial_facts,
-                  shrink_transformations_file, shrink_temp_file_prefix,
-                  interestingness_test, &binary_out,
+      if (!Shrink(target_env, fuzzer_options, validator_options, binary_in,
+                  initial_facts, shrink_transformations_file,
+                  shrink_temp_file_prefix, interestingness_test, &binary_out,
                   &transformations_applied)) {
         return 1;
       }
diff --git a/third_party/spirv-tools/src/tools/sva/yarn.lock b/third_party/spirv-tools/src/tools/sva/yarn.lock
index be19e7c..11ba12f 100644
--- a/third_party/spirv-tools/src/tools/sva/yarn.lock
+++ b/third_party/spirv-tools/src/tools/sva/yarn.lock
@@ -47,9 +47,9 @@
   integrity sha512-tiNTrP1MP0QrChmD2DdupCr6HWSFeKVw5d/dHTu4Y7rkAkRhU/Dt7dphAfIUyxtHpl/eBVip5uTNSpQJHylpAw==
 
 acorn@^7.0.0:
-  version "7.0.0"
-  resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.0.0.tgz#26b8d1cd9a9b700350b71c0905546f64d1284e7a"
-  integrity sha512-PaF/MduxijYYt7unVGRuds1vBC9bFxbNf+VWqhOClfdgy7RlVkQqt610ig1/yxTgsDIfW1cWDel5EBbOy3jdtQ==
+  version "7.1.1"
+  resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.1.tgz#e35668de0b402f359de515c5482a1ab9f89a69bf"
+  integrity sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==
 
 ajv@6.5.3:
   version "6.5.3"
diff --git a/third_party/spirv-tools/src/utils/vscode/extension.js b/third_party/spirv-tools/src/utils/vscode/extension.js
index f220172..e7fec28 100644
--- a/third_party/spirv-tools/src/utils/vscode/extension.js
+++ b/third_party/spirv-tools/src/utils/vscode/extension.js
@@ -63,4 +63,4 @@
 // this method is called when your extension is deactivated
 function deactivate() {
 }
-exports.deactivate = deactivate;
\ No newline at end of file
+exports.deactivate = deactivate;
diff --git a/third_party/vulkan-headers/src/CMakeLists.txt b/third_party/vulkan-headers/src/CMakeLists.txt
index fc96c5e..7ab25eb 100644
--- a/third_party/vulkan-headers/src/CMakeLists.txt
+++ b/third_party/vulkan-headers/src/CMakeLists.txt
@@ -22,6 +22,26 @@
 
 # NONE = this project has no language toolchain requirement.
 project(Vulkan-Headers NONE)
+file(READ "include/vulkan/vulkan_core.h" ver)
+string(REGEX MATCH "#define[ ]+VK_HEADER_VERSION_COMPLETE[ ]+VK_MAKE_VERSION\\([ ]*([0-9]+),[ ]*([0-9]+),[ ]*VK_HEADER_VERSION[ ]*\\)" _ ${ver})
+set(VK_VERSION_MAJOR "${CMAKE_MATCH_1}")
+set(VK_VERSION_MINOR "${CMAKE_MATCH_2}")
+string(REGEX MATCH "#define[ ]+VK_HEADER_VERSION[ ]+([0-9]+)" _ ${ver})
+set(VK_HEADER_VERSION "${CMAKE_MATCH_1}")
+# check if version parsing was successful
+if(VK_VERSION_MAJOR STREQUAL "")
+    message(FATAL_ERROR "Error reading major version from 'include/vulkan/vulkan_core.h'")
+endif()
+if(VK_VERSION_MINOR STREQUAL "")
+    message(FATAL_ERROR "Error reading minor version from 'include/vulkan/vulkan_core.h'")
+endif()
+if(VK_HEADER_VERSION STREQUAL "")
+    message(FATAL_ERROR "Error reading header version from 'include/vulkan/vulkan_core.h'")
+endif()
+set(VK_VERSION_STRING "${VK_VERSION_MAJOR}.${VK_VERSION_MINOR}.${VK_HEADER_VERSION}")
+message(STATUS "Found Vulkan-Headers VK_VERSION_STRING '${VK_VERSION_STRING}'")
+
+option(VULKAN_HEADERS_SKIP_INSTALL "Skip install" OFF)
 
 # User-interface declarations ----------------------------------------------------------------------------------------------------
 # This section contains variables that affect development GUIs (e.g. CMake GUI and IDEs), such as option(), folders, and variables
@@ -38,21 +58,74 @@
 
 # define exported targets for nested project builds to consume
 add_library(Vulkan-Headers INTERFACE)
-target_include_directories(Vulkan-Headers INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/include")
+target_include_directories(Vulkan-Headers INTERFACE
+    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
+    $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+)
 add_library(Vulkan::Headers ALIAS Vulkan-Headers)
 
 add_library(Vulkan-Registry INTERFACE)
-target_include_directories(Vulkan-Registry INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/registry")
+target_include_directories(Vulkan-Registry INTERFACE
+    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/registry>
+    $<INSTALL_INTERFACE:${CMAKE_INSTALL_DATADIR}/vulkan>
+)
 add_library(Vulkan::Registry ALIAS Vulkan-Registry)
 
-install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/vulkan" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
-install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/registry" DESTINATION ${CMAKE_INSTALL_DATADIR}/vulkan)
+# Installation
+# This adds the following files to the install target
+# - Vulkan Header files
+# - Vulkan Registry files
+# - CMake config files generated by CMake
+#   - VulkanHeadersConfig.cmake:        searched for by find_package(VulkanHeaders)
+#   - VulkanHeadersConfigVersion.cmake: provides version numbers
+#   - VulkanHeadersTargets.cmake:       CMake target definitions used by config file
+if(NOT VULKAN_HEADERS_SKIP_INSTALL)
+    set(config_install_dir "${CMAKE_INSTALL_DATADIR}/cmake/VulkanHeaders")
+    set(generated_dir "${CMAKE_CURRENT_BINARY_DIR}/generated")
+    set(version_config "${generated_dir}/VulkanHeadersConfigVersion.cmake")
+    set(project_config "${generated_dir}/VulkanHeadersConfig.cmake")
+    set(TARGETS_EXPORT_NAME "VulkanHeadersTargets")
+    set(namespace "Vulkan::")
 
-# uninstall target
-if(NOT TARGET uninstall)
-    configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in"
-                   "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
-                   IMMEDIATE
-                   @ONLY)
-    add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
+    include(CMakePackageConfigHelpers)
+    write_basic_package_version_file(
+        "${version_config}"
+        VERSION ${VK_VERSION_STRING}
+        COMPATIBILITY AnyNewerVersion
+    )
+    configure_package_config_file(
+        "cmake/Config.cmake.in"
+        "${project_config}"
+        INSTALL_DESTINATION "${config_install_dir}"
+    )
+    install(
+        TARGETS Vulkan-Headers Vulkan-Registry
+        EXPORT "${TARGETS_EXPORT_NAME}"
+        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+        ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+        RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+    )
+    install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/vulkan"
+        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
+    )
+    install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/registry"
+        DESTINATION ${CMAKE_INSTALL_DATADIR}/vulkan
+    )
+    install(FILES "${project_config}" "${version_config}"
+        DESTINATION "${config_install_dir}"
+    )
+    install(
+        EXPORT "${TARGETS_EXPORT_NAME}"
+        NAMESPACE "${namespace}"
+        DESTINATION "${config_install_dir}")
+
+    # uninstall target
+    if(NOT TARGET uninstall)
+        configure_file(
+            "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in"
+            "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
+            IMMEDIATE
+            @ONLY)
+        add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
+    endif()
 endif()
diff --git a/third_party/vulkan-headers/src/README.md b/third_party/vulkan-headers/src/README.md
index 4687289..b29f4b4 100644
--- a/third_party/vulkan-headers/src/README.md
+++ b/third_party/vulkan-headers/src/README.md
@@ -2,6 +2,20 @@
 
 Vulkan header files and API registry
 
+## Advance Notice of Pending Header Change (posted 2020-04-06)
+
+Shortly after 2020-04-24, we will be removing the automatically generated
+`VK_*_BEGIN_RANGE`, `VK_*_END_RANGE`, and `VK_*_RANGE_SIZE` tokens
+from the Vulkan headers.
+These tokens are currently defined for some enumerated types, but are
+explicitly not part of the Vulkan API.
+They existed only to support some Vulkan implementation internals, which no
+longer require them.
+We will be accepting comments on this topic in
+https://github.com/KhronosGroup/Vulkan-Docs/issues/1230, but we strongly
+suggest any external projects using these tokens immediately migrate away
+from them.
+
 ## Repository Content
 
 The contents of this repository are largely obtained from other repositories and are
diff --git a/third_party/vulkan-headers/src/cmake/Config.cmake.in b/third_party/vulkan-headers/src/cmake/Config.cmake.in
new file mode 100644
index 0000000..4bf6cd5
--- /dev/null
+++ b/third_party/vulkan-headers/src/cmake/Config.cmake.in
@@ -0,0 +1,25 @@
+@PACKAGE_INIT@
+
+include("${CMAKE_CURRENT_LIST_DIR}/@TARGETS_EXPORT_NAME@.cmake")
+check_required_components("@PROJECT_NAME@")
+
+# ALIAS for imported target requires CMake >= 3.11:
+# - https://cmake.org/cmake/help/latest/release/3.11.html#other
+if(NOT CMAKE_VERSION VERSION_LESS 3.11)
+    if(NOT TARGET Vulkan::Headers)
+        set_target_properties(
+            Vulkan::Vulkan-Headers
+            PROPERTIES
+            IMPORTED_GLOBAL True
+        )
+        add_library(Vulkan::Headers ALIAS Vulkan::Vulkan-Headers)
+      endif()
+      if(NOT TARGET Vulkan::Registry)
+        set_target_properties(
+            Vulkan::Vulkan-Registry
+            PROPERTIES
+            IMPORTED_GLOBAL True
+        )
+        add_library(Vulkan::Registry ALIAS Vulkan::Vulkan-Registry)
+    endif()
+endif()
diff --git a/third_party/vulkan-headers/src/include/vulkan/vulkan.h b/third_party/vulkan-headers/src/include/vulkan/vulkan.h
index ee3fd3c..20ecd10 100644
--- a/third_party/vulkan-headers/src/include/vulkan/vulkan.h
+++ b/third_party/vulkan-headers/src/include/vulkan/vulkan.h
@@ -83,4 +83,9 @@
 #include "vulkan_ggp.h"
 #endif
 
+
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+#include "vulkan_beta.h"
+#endif
+
 #endif // VULKAN_H_
diff --git a/third_party/vulkan-headers/src/include/vulkan/vulkan.hpp b/third_party/vulkan-headers/src/include/vulkan/vulkan.hpp
index 2709dac..08be754 100644
--- a/third_party/vulkan-headers/src/include/vulkan/vulkan.hpp
+++ b/third_party/vulkan-headers/src/include/vulkan/vulkan.hpp
@@ -39,6 +39,7 @@
 #include <cstddef>
 #include <cstdint>
 #include <cstring>
+#include <functional>
 #include <initializer_list>
 #include <string>
 #include <system_error>
@@ -81,7 +82,7 @@
 # include <compare>
 #endif
 
-static_assert( VK_HEADER_VERSION ==  134 , "Wrong VK_HEADER_VERSION!" );
+static_assert( VK_HEADER_VERSION ==  137 , "Wrong VK_HEADER_VERSION!" );
 
 // 32-bit vulkan is not typesafe for handles, so don't allow copy constructors on this platform by default.
 // To enable this feature on 32-bit platforms please define VULKAN_HPP_TYPESAFE_CONVERSION
@@ -271,6 +272,91 @@
   };
 #endif
 
+  template <typename T, size_t N>
+  class ArrayWrapper1D : public std::array<T,N>
+  {
+  public:
+    VULKAN_HPP_CONSTEXPR ArrayWrapper1D() VULKAN_HPP_NOEXCEPT
+      : std::array<T, N>()
+    {}
+
+    VULKAN_HPP_CONSTEXPR ArrayWrapper1D(std::array<T,N> const& data) VULKAN_HPP_NOEXCEPT
+      : std::array<T, N>(data)
+    {}
+
+#if defined(_WIN32) && !defined(_WIN64)
+    VULKAN_HPP_CONSTEXPR T const& operator[](int index) const VULKAN_HPP_NOEXCEPT
+    {
+      return std::array<T, N>::operator[](index);
+    }
+
+    VULKAN_HPP_CONSTEXPR T & operator[](int index) VULKAN_HPP_NOEXCEPT
+    {
+      return std::array<T, N>::operator[](index);
+    }
+#endif
+
+    operator T const* () const VULKAN_HPP_NOEXCEPT
+    {
+      return this->data();
+    }
+
+    operator T * () VULKAN_HPP_NOEXCEPT
+    {
+      return this->data();
+    }
+  };
+
+  // specialization of relational operators between std::string and arrays of chars
+  template <size_t N>
+  bool operator<(std::string const& lhs, ArrayWrapper1D<char, N> const& rhs) VULKAN_HPP_NOEXCEPT
+  {
+    return lhs < rhs.data();
+  }
+
+  template <size_t N>
+  bool operator<=(std::string const& lhs, ArrayWrapper1D<char, N> const& rhs) VULKAN_HPP_NOEXCEPT
+  {
+    return lhs <= rhs.data();
+  }
+
+  template <size_t N>
+  bool operator>(std::string const& lhs, ArrayWrapper1D<char, N> const& rhs) VULKAN_HPP_NOEXCEPT
+  {
+    return lhs > rhs.data();
+  }
+
+  template <size_t N>
+  bool operator>=(std::string const& lhs, ArrayWrapper1D<char, N> const& rhs) VULKAN_HPP_NOEXCEPT
+  {
+    return lhs >= rhs.data();
+  }
+
+  template <size_t N>
+  bool operator==(std::string const& lhs, ArrayWrapper1D<char, N> const& rhs) VULKAN_HPP_NOEXCEPT
+  {
+    return lhs == rhs.data();
+  }
+
+  template <size_t N>
+  bool operator!=(std::string const& lhs, ArrayWrapper1D<char, N> const& rhs) VULKAN_HPP_NOEXCEPT
+  {
+    return lhs != rhs.data();
+  }
+
+  template <typename T, size_t N, size_t M>
+  class ArrayWrapper2D : public std::array<ArrayWrapper1D<T,M>,N>
+  {
+  public:
+    VULKAN_HPP_CONSTEXPR ArrayWrapper2D() VULKAN_HPP_NOEXCEPT
+      : std::array<ArrayWrapper1D<T,M>, N>()
+    {}
+
+    VULKAN_HPP_CONSTEXPR ArrayWrapper2D(std::array<std::array<T,M>,N> const& data) VULKAN_HPP_NOEXCEPT
+      : std::array<ArrayWrapper1D<T,M>, N>(*reinterpret_cast<std::array<ArrayWrapper1D<T,M>,N> const*>(&data))
+    {}
+  };
+
   template <typename FlagBitsType> struct FlagTraits
   {
     enum { allFlags = 0 };
@@ -861,6 +947,11 @@
       return ::vkCmdBindPipeline( commandBuffer, pipelineBindPoint, pipeline );
     }
 
+    void vkCmdBindPipelineShaderGroupNV( VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline, uint32_t groupIndex ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ::vkCmdBindPipelineShaderGroupNV( commandBuffer, pipelineBindPoint, pipeline, groupIndex );
+    }
+
     void vkCmdBindShadingRateImageNV( VkCommandBuffer commandBuffer, VkImageView imageView, VkImageLayout imageLayout ) const VULKAN_HPP_NOEXCEPT
     {
       return ::vkCmdBindShadingRateImageNV( commandBuffer, imageView, imageLayout );
@@ -881,7 +972,21 @@
       return ::vkCmdBlitImage( commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions, filter );
     }
 
-    void vkCmdBuildAccelerationStructureNV( VkCommandBuffer commandBuffer, const VkAccelerationStructureInfoNV* pInfo, VkBuffer instanceData, VkDeviceSize instanceOffset, VkBool32 update, VkAccelerationStructureNV dst, VkAccelerationStructureNV src, VkBuffer scratch, VkDeviceSize scratchOffset ) const VULKAN_HPP_NOEXCEPT
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    void vkCmdBuildAccelerationStructureIndirectKHR( VkCommandBuffer commandBuffer, const VkAccelerationStructureBuildGeometryInfoKHR* pInfo, VkBuffer indirectBuffer, VkDeviceSize indirectOffset, uint32_t indirectStride ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ::vkCmdBuildAccelerationStructureIndirectKHR( commandBuffer, pInfo, indirectBuffer, indirectOffset, indirectStride );
+    }
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    void vkCmdBuildAccelerationStructureKHR( VkCommandBuffer commandBuffer, uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, const VkAccelerationStructureBuildOffsetInfoKHR* const* ppOffsetInfos ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ::vkCmdBuildAccelerationStructureKHR( commandBuffer, infoCount, pInfos, ppOffsetInfos );
+    }
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+    void vkCmdBuildAccelerationStructureNV( VkCommandBuffer commandBuffer, const VkAccelerationStructureInfoNV* pInfo, VkBuffer instanceData, VkDeviceSize instanceOffset, VkBool32 update, VkAccelerationStructureKHR dst, VkAccelerationStructureKHR src, VkBuffer scratch, VkDeviceSize scratchOffset ) const VULKAN_HPP_NOEXCEPT
     {
       return ::vkCmdBuildAccelerationStructureNV( commandBuffer, pInfo, instanceData, instanceOffset, update, dst, src, scratch, scratchOffset );
     }
@@ -901,11 +1006,25 @@
       return ::vkCmdClearDepthStencilImage( commandBuffer, image, imageLayout, pDepthStencil, rangeCount, pRanges );
     }
 
-    void vkCmdCopyAccelerationStructureNV( VkCommandBuffer commandBuffer, VkAccelerationStructureNV dst, VkAccelerationStructureNV src, VkCopyAccelerationStructureModeNV mode ) const VULKAN_HPP_NOEXCEPT
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    void vkCmdCopyAccelerationStructureKHR( VkCommandBuffer commandBuffer, const VkCopyAccelerationStructureInfoKHR* pInfo ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ::vkCmdCopyAccelerationStructureKHR( commandBuffer, pInfo );
+    }
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+    void vkCmdCopyAccelerationStructureNV( VkCommandBuffer commandBuffer, VkAccelerationStructureKHR dst, VkAccelerationStructureKHR src, VkCopyAccelerationStructureModeKHR mode ) const VULKAN_HPP_NOEXCEPT
     {
       return ::vkCmdCopyAccelerationStructureNV( commandBuffer, dst, src, mode );
     }
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    void vkCmdCopyAccelerationStructureToMemoryKHR( VkCommandBuffer commandBuffer, const VkCopyAccelerationStructureToMemoryInfoKHR* pInfo ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ::vkCmdCopyAccelerationStructureToMemoryKHR( commandBuffer, pInfo );
+    }
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
     void vkCmdCopyBuffer( VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferCopy* pRegions ) const VULKAN_HPP_NOEXCEPT
     {
       return ::vkCmdCopyBuffer( commandBuffer, srcBuffer, dstBuffer, regionCount, pRegions );
@@ -926,6 +1045,13 @@
       return ::vkCmdCopyImageToBuffer( commandBuffer, srcImage, srcImageLayout, dstBuffer, regionCount, pRegions );
     }
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    void vkCmdCopyMemoryToAccelerationStructureKHR( VkCommandBuffer commandBuffer, const VkCopyMemoryToAccelerationStructureInfoKHR* pInfo ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ::vkCmdCopyMemoryToAccelerationStructureKHR( commandBuffer, pInfo );
+    }
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
     void vkCmdCopyQueryPoolResults( VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags ) const VULKAN_HPP_NOEXCEPT
     {
       return ::vkCmdCopyQueryPoolResults( commandBuffer, queryPool, firstQuery, queryCount, dstBuffer, dstOffset, stride, flags );
@@ -1081,6 +1207,11 @@
       return ::vkCmdExecuteCommands( commandBuffer, commandBufferCount, pCommandBuffers );
     }
 
+    void vkCmdExecuteGeneratedCommandsNV( VkCommandBuffer commandBuffer, VkBool32 isPreprocessed, const VkGeneratedCommandsInfoNV* pGeneratedCommandsInfo ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ::vkCmdExecuteGeneratedCommandsNV( commandBuffer, isPreprocessed, pGeneratedCommandsInfo );
+    }
+
     void vkCmdFillBuffer( VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data ) const VULKAN_HPP_NOEXCEPT
     {
       return ::vkCmdFillBuffer( commandBuffer, dstBuffer, dstOffset, size, data );
@@ -1111,9 +1242,9 @@
       return ::vkCmdPipelineBarrier( commandBuffer, srcStageMask, dstStageMask, dependencyFlags, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers );
     }
 
-    void vkCmdProcessCommandsNVX( VkCommandBuffer commandBuffer, const VkCmdProcessCommandsInfoNVX* pProcessCommandsInfo ) const VULKAN_HPP_NOEXCEPT
+    void vkCmdPreprocessGeneratedCommandsNV( VkCommandBuffer commandBuffer, const VkGeneratedCommandsInfoNV* pGeneratedCommandsInfo ) const VULKAN_HPP_NOEXCEPT
     {
-      return ::vkCmdProcessCommandsNVX( commandBuffer, pProcessCommandsInfo );
+      return ::vkCmdPreprocessGeneratedCommandsNV( commandBuffer, pGeneratedCommandsInfo );
     }
 
     void vkCmdPushConstants( VkCommandBuffer commandBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size, const void* pValues ) const VULKAN_HPP_NOEXCEPT
@@ -1131,11 +1262,6 @@
       return ::vkCmdPushDescriptorSetWithTemplateKHR( commandBuffer, descriptorUpdateTemplate, layout, set, pData );
     }
 
-    void vkCmdReserveSpaceForCommandsNVX( VkCommandBuffer commandBuffer, const VkCmdReserveSpaceForCommandsInfoNVX* pReserveSpaceInfo ) const VULKAN_HPP_NOEXCEPT
-    {
-      return ::vkCmdReserveSpaceForCommandsNVX( commandBuffer, pReserveSpaceInfo );
-    }
-
     void vkCmdResetEvent( VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask ) const VULKAN_HPP_NOEXCEPT
     {
       return ::vkCmdResetEvent( commandBuffer, event, stageMask );
@@ -1266,6 +1392,20 @@
       return ::vkCmdSetViewportWScalingNV( commandBuffer, firstViewport, viewportCount, pViewportWScalings );
     }
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    void vkCmdTraceRaysIndirectKHR( VkCommandBuffer commandBuffer, const VkStridedBufferRegionKHR* pRaygenShaderBindingTable, const VkStridedBufferRegionKHR* pMissShaderBindingTable, const VkStridedBufferRegionKHR* pHitShaderBindingTable, const VkStridedBufferRegionKHR* pCallableShaderBindingTable, VkBuffer buffer, VkDeviceSize offset ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ::vkCmdTraceRaysIndirectKHR( commandBuffer, pRaygenShaderBindingTable, pMissShaderBindingTable, pHitShaderBindingTable, pCallableShaderBindingTable, buffer, offset );
+    }
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    void vkCmdTraceRaysKHR( VkCommandBuffer commandBuffer, const VkStridedBufferRegionKHR* pRaygenShaderBindingTable, const VkStridedBufferRegionKHR* pMissShaderBindingTable, const VkStridedBufferRegionKHR* pHitShaderBindingTable, const VkStridedBufferRegionKHR* pCallableShaderBindingTable, uint32_t width, uint32_t height, uint32_t depth ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ::vkCmdTraceRaysKHR( commandBuffer, pRaygenShaderBindingTable, pMissShaderBindingTable, pHitShaderBindingTable, pCallableShaderBindingTable, width, height, depth );
+    }
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
     void vkCmdTraceRaysNV( VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer, VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer, VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride, VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset, VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer, VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride, uint32_t width, uint32_t height, uint32_t depth ) const VULKAN_HPP_NOEXCEPT
     {
       return ::vkCmdTraceRaysNV( commandBuffer, raygenShaderBindingTableBuffer, raygenShaderBindingOffset, missShaderBindingTableBuffer, missShaderBindingOffset, missShaderBindingStride, hitShaderBindingTableBuffer, hitShaderBindingOffset, hitShaderBindingStride, callableShaderBindingTableBuffer, callableShaderBindingOffset, callableShaderBindingStride, width, height, depth );
@@ -1281,7 +1421,12 @@
       return ::vkCmdWaitEvents( commandBuffer, eventCount, pEvents, srcStageMask, dstStageMask, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers );
     }
 
-    void vkCmdWriteAccelerationStructuresPropertiesNV( VkCommandBuffer commandBuffer, uint32_t accelerationStructureCount, const VkAccelerationStructureNV* pAccelerationStructures, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery ) const VULKAN_HPP_NOEXCEPT
+    void vkCmdWriteAccelerationStructuresPropertiesKHR( VkCommandBuffer commandBuffer, uint32_t accelerationStructureCount, const VkAccelerationStructureKHR* pAccelerationStructures, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ::vkCmdWriteAccelerationStructuresPropertiesKHR( commandBuffer, accelerationStructureCount, pAccelerationStructures, queryType, queryPool, firstQuery );
+    }
+
+    void vkCmdWriteAccelerationStructuresPropertiesNV( VkCommandBuffer commandBuffer, uint32_t accelerationStructureCount, const VkAccelerationStructureKHR* pAccelerationStructures, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery ) const VULKAN_HPP_NOEXCEPT
     {
       return ::vkCmdWriteAccelerationStructuresPropertiesNV( commandBuffer, accelerationStructureCount, pAccelerationStructures, queryType, queryPool, firstQuery );
     }
@@ -1348,7 +1493,12 @@
       return ::vkAllocateMemory( device, pAllocateInfo, pAllocator, pMemory );
     }
 
-    VkResult vkBindAccelerationStructureMemoryNV( VkDevice device, uint32_t bindInfoCount, const VkBindAccelerationStructureMemoryInfoNV* pBindInfos ) const VULKAN_HPP_NOEXCEPT
+    VkResult vkBindAccelerationStructureMemoryKHR( VkDevice device, uint32_t bindInfoCount, const VkBindAccelerationStructureMemoryInfoKHR* pBindInfos ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ::vkBindAccelerationStructureMemoryKHR( device, bindInfoCount, pBindInfos );
+    }
+
+    VkResult vkBindAccelerationStructureMemoryNV( VkDevice device, uint32_t bindInfoCount, const VkBindAccelerationStructureMemoryInfoKHR* pBindInfos ) const VULKAN_HPP_NOEXCEPT
     {
       return ::vkBindAccelerationStructureMemoryNV( device, bindInfoCount, pBindInfos );
     }
@@ -1383,11 +1533,46 @@
       return ::vkBindImageMemory2KHR( device, bindInfoCount, pBindInfos );
     }
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    VkResult vkBuildAccelerationStructureKHR( VkDevice device, uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, const VkAccelerationStructureBuildOffsetInfoKHR* const* ppOffsetInfos ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ::vkBuildAccelerationStructureKHR( device, infoCount, pInfos, ppOffsetInfos );
+    }
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
     VkResult vkCompileDeferredNV( VkDevice device, VkPipeline pipeline, uint32_t shader ) const VULKAN_HPP_NOEXCEPT
     {
       return ::vkCompileDeferredNV( device, pipeline, shader );
     }
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    VkResult vkCopyAccelerationStructureKHR( VkDevice device, const VkCopyAccelerationStructureInfoKHR* pInfo ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ::vkCopyAccelerationStructureKHR( device, pInfo );
+    }
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    VkResult vkCopyAccelerationStructureToMemoryKHR( VkDevice device, const VkCopyAccelerationStructureToMemoryInfoKHR* pInfo ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ::vkCopyAccelerationStructureToMemoryKHR( device, pInfo );
+    }
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    VkResult vkCopyMemoryToAccelerationStructureKHR( VkDevice device, const VkCopyMemoryToAccelerationStructureInfoKHR* pInfo ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ::vkCopyMemoryToAccelerationStructureKHR( device, pInfo );
+    }
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    VkResult vkCreateAccelerationStructureKHR( VkDevice device, const VkAccelerationStructureCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkAccelerationStructureKHR* pAccelerationStructure ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ::vkCreateAccelerationStructureKHR( device, pCreateInfo, pAllocator, pAccelerationStructure );
+    }
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
     VkResult vkCreateAccelerationStructureNV( VkDevice device, const VkAccelerationStructureCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkAccelerationStructureNV* pAccelerationStructure ) const VULKAN_HPP_NOEXCEPT
     {
       return ::vkCreateAccelerationStructureNV( device, pCreateInfo, pAllocator, pAccelerationStructure );
@@ -1413,6 +1598,13 @@
       return ::vkCreateComputePipelines( device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines );
     }
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    VkResult vkCreateDeferredOperationKHR( VkDevice device, const VkAllocationCallbacks* pAllocator, VkDeferredOperationKHR* pDeferredOperation ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ::vkCreateDeferredOperationKHR( device, pAllocator, pDeferredOperation );
+    }
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
     VkResult vkCreateDescriptorPool( VkDevice device, const VkDescriptorPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorPool* pDescriptorPool ) const VULKAN_HPP_NOEXCEPT
     {
       return ::vkCreateDescriptorPool( device, pCreateInfo, pAllocator, pDescriptorPool );
@@ -1463,14 +1655,9 @@
       return ::vkCreateImageView( device, pCreateInfo, pAllocator, pView );
     }
 
-    VkResult vkCreateIndirectCommandsLayoutNVX( VkDevice device, const VkIndirectCommandsLayoutCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkIndirectCommandsLayoutNVX* pIndirectCommandsLayout ) const VULKAN_HPP_NOEXCEPT
+    VkResult vkCreateIndirectCommandsLayoutNV( VkDevice device, const VkIndirectCommandsLayoutCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkIndirectCommandsLayoutNV* pIndirectCommandsLayout ) const VULKAN_HPP_NOEXCEPT
     {
-      return ::vkCreateIndirectCommandsLayoutNVX( device, pCreateInfo, pAllocator, pIndirectCommandsLayout );
-    }
-
-    VkResult vkCreateObjectTableNVX( VkDevice device, const VkObjectTableCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkObjectTableNVX* pObjectTable ) const VULKAN_HPP_NOEXCEPT
-    {
-      return ::vkCreateObjectTableNVX( device, pCreateInfo, pAllocator, pObjectTable );
+      return ::vkCreateIndirectCommandsLayoutNV( device, pCreateInfo, pAllocator, pIndirectCommandsLayout );
     }
 
     VkResult vkCreatePipelineCache( VkDevice device, const VkPipelineCacheCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineCache* pPipelineCache ) const VULKAN_HPP_NOEXCEPT
@@ -1488,6 +1675,13 @@
       return ::vkCreateQueryPool( device, pCreateInfo, pAllocator, pQueryPool );
     }
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    VkResult vkCreateRayTracingPipelinesKHR( VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoKHR* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ::vkCreateRayTracingPipelinesKHR( device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines );
+    }
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
     VkResult vkCreateRayTracingPipelinesNV( VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines ) const VULKAN_HPP_NOEXCEPT
     {
       return ::vkCreateRayTracingPipelinesNV( device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines );
@@ -1558,7 +1752,19 @@
       return ::vkDebugMarkerSetObjectTagEXT( device, pTagInfo );
     }
 
-    void vkDestroyAccelerationStructureNV( VkDevice device, VkAccelerationStructureNV accelerationStructure, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    VkResult vkDeferredOperationJoinKHR( VkDevice device, VkDeferredOperationKHR operation ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ::vkDeferredOperationJoinKHR( device, operation );
+    }
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+    void vkDestroyAccelerationStructureKHR( VkDevice device, VkAccelerationStructureKHR accelerationStructure, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ::vkDestroyAccelerationStructureKHR( device, accelerationStructure, pAllocator );
+    }
+
+    void vkDestroyAccelerationStructureNV( VkDevice device, VkAccelerationStructureKHR accelerationStructure, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
     {
       return ::vkDestroyAccelerationStructureNV( device, accelerationStructure, pAllocator );
     }
@@ -1578,6 +1784,13 @@
       return ::vkDestroyCommandPool( device, commandPool, pAllocator );
     }
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    void vkDestroyDeferredOperationKHR( VkDevice device, VkDeferredOperationKHR operation, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ::vkDestroyDeferredOperationKHR( device, operation, pAllocator );
+    }
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
     void vkDestroyDescriptorPool( VkDevice device, VkDescriptorPool descriptorPool, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
     {
       return ::vkDestroyDescriptorPool( device, descriptorPool, pAllocator );
@@ -1628,14 +1841,9 @@
       return ::vkDestroyImageView( device, imageView, pAllocator );
     }
 
-    void vkDestroyIndirectCommandsLayoutNVX( VkDevice device, VkIndirectCommandsLayoutNVX indirectCommandsLayout, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
+    void vkDestroyIndirectCommandsLayoutNV( VkDevice device, VkIndirectCommandsLayoutNV indirectCommandsLayout, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
     {
-      return ::vkDestroyIndirectCommandsLayoutNVX( device, indirectCommandsLayout, pAllocator );
-    }
-
-    void vkDestroyObjectTableNVX( VkDevice device, VkObjectTableNVX objectTable, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
-    {
-      return ::vkDestroyObjectTableNVX( device, objectTable, pAllocator );
+      return ::vkDestroyIndirectCommandsLayoutNV( device, indirectCommandsLayout, pAllocator );
     }
 
     void vkDestroyPipeline( VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks* pAllocator ) const VULKAN_HPP_NOEXCEPT
@@ -1728,11 +1936,25 @@
       return ::vkFreeMemory( device, memory, pAllocator );
     }
 
-    VkResult vkGetAccelerationStructureHandleNV( VkDevice device, VkAccelerationStructureNV accelerationStructure, size_t dataSize, void* pData ) const VULKAN_HPP_NOEXCEPT
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    VkDeviceAddress vkGetAccelerationStructureDeviceAddressKHR( VkDevice device, const VkAccelerationStructureDeviceAddressInfoKHR* pInfo ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ::vkGetAccelerationStructureDeviceAddressKHR( device, pInfo );
+    }
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+    VkResult vkGetAccelerationStructureHandleNV( VkDevice device, VkAccelerationStructureKHR accelerationStructure, size_t dataSize, void* pData ) const VULKAN_HPP_NOEXCEPT
     {
       return ::vkGetAccelerationStructureHandleNV( device, accelerationStructure, dataSize, pData );
     }
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    void vkGetAccelerationStructureMemoryRequirementsKHR( VkDevice device, const VkAccelerationStructureMemoryRequirementsInfoKHR* pInfo, VkMemoryRequirements2* pMemoryRequirements ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ::vkGetAccelerationStructureMemoryRequirementsKHR( device, pInfo, pMemoryRequirements );
+    }
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
     void vkGetAccelerationStructureMemoryRequirementsNV( VkDevice device, const VkAccelerationStructureMemoryRequirementsInfoNV* pInfo, VkMemoryRequirements2KHR* pMemoryRequirements ) const VULKAN_HPP_NOEXCEPT
     {
       return ::vkGetAccelerationStructureMemoryRequirementsNV( device, pInfo, pMemoryRequirements );
@@ -1790,6 +2012,20 @@
       return ::vkGetCalibratedTimestampsEXT( device, timestampCount, pTimestampInfos, pTimestamps, pMaxDeviation );
     }
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    uint32_t vkGetDeferredOperationMaxConcurrencyKHR( VkDevice device, VkDeferredOperationKHR operation ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ::vkGetDeferredOperationMaxConcurrencyKHR( device, operation );
+    }
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    VkResult vkGetDeferredOperationResultKHR( VkDevice device, VkDeferredOperationKHR operation ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ::vkGetDeferredOperationResultKHR( device, operation );
+    }
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
     void vkGetDescriptorSetLayoutSupport( VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport ) const VULKAN_HPP_NOEXCEPT
     {
       return ::vkGetDescriptorSetLayoutSupport( device, pCreateInfo, pSupport );
@@ -1800,6 +2036,13 @@
       return ::vkGetDescriptorSetLayoutSupportKHR( device, pCreateInfo, pSupport );
     }
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    VkResult vkGetDeviceAccelerationStructureCompatibilityKHR( VkDevice device, const VkAccelerationStructureVersionKHR* version ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ::vkGetDeviceAccelerationStructureCompatibilityKHR( device, version );
+    }
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
     void vkGetDeviceGroupPeerMemoryFeatures( VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags* pPeerMemoryFeatures ) const VULKAN_HPP_NOEXCEPT
     {
       return ::vkGetDeviceGroupPeerMemoryFeatures( device, heapIndex, localDeviceIndex, remoteDeviceIndex, pPeerMemoryFeatures );
@@ -1879,6 +2122,11 @@
     }
 #endif /*VK_USE_PLATFORM_WIN32_KHR*/
 
+    void vkGetGeneratedCommandsMemoryRequirementsNV( VkDevice device, const VkGeneratedCommandsMemoryRequirementsInfoNV* pInfo, VkMemoryRequirements2* pMemoryRequirements ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ::vkGetGeneratedCommandsMemoryRequirementsNV( device, pInfo, pMemoryRequirements );
+    }
+
     VkResult vkGetImageDrmFormatModifierPropertiesEXT( VkDevice device, VkImage image, VkImageDrmFormatModifierPropertiesEXT* pProperties ) const VULKAN_HPP_NOEXCEPT
     {
       return ::vkGetImageDrmFormatModifierPropertiesEXT( device, image, pProperties );
@@ -1919,6 +2167,11 @@
       return ::vkGetImageSubresourceLayout( device, image, pSubresource, pLayout );
     }
 
+    VkResult vkGetImageViewAddressNVX( VkDevice device, VkImageView imageView, VkImageViewAddressPropertiesNVX* pProperties ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ::vkGetImageViewAddressNVX( device, imageView, pProperties );
+    }
+
     uint32_t vkGetImageViewHandleNVX( VkDevice device, const VkImageViewHandleInfoNVX* pInfo ) const VULKAN_HPP_NOEXCEPT
     {
       return ::vkGetImageViewHandleNVX( device, pInfo );
@@ -2002,6 +2255,18 @@
       return ::vkGetQueryPoolResults( device, queryPool, firstQuery, queryCount, dataSize, pData, stride, flags );
     }
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    VkResult vkGetRayTracingCaptureReplayShaderGroupHandlesKHR( VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ::vkGetRayTracingCaptureReplayShaderGroupHandlesKHR( device, pipeline, firstGroup, groupCount, dataSize, pData );
+    }
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+    VkResult vkGetRayTracingShaderGroupHandlesKHR( VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ::vkGetRayTracingShaderGroupHandlesKHR( device, pipeline, firstGroup, groupCount, dataSize, pData );
+    }
+
     VkResult vkGetRayTracingShaderGroupHandlesNV( VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData ) const VULKAN_HPP_NOEXCEPT
     {
       return ::vkGetRayTracingShaderGroupHandlesNV( device, pipeline, firstGroup, groupCount, dataSize, pData );
@@ -2123,11 +2388,6 @@
       return ::vkRegisterDisplayEventEXT( device, display, pDisplayEventInfo, pAllocator, pFence );
     }
 
-    VkResult vkRegisterObjectsNVX( VkDevice device, VkObjectTableNVX objectTable, uint32_t objectCount, const VkObjectTableEntryNVX* const* ppObjectTableEntries, const uint32_t* pObjectIndices ) const VULKAN_HPP_NOEXCEPT
-    {
-      return ::vkRegisterObjectsNVX( device, objectTable, objectCount, ppObjectTableEntries, pObjectIndices );
-    }
-
 #ifdef VK_USE_PLATFORM_WIN32_KHR
     VkResult vkReleaseFullScreenExclusiveModeEXT( VkDevice device, VkSwapchainKHR swapchain ) const VULKAN_HPP_NOEXCEPT
     {
@@ -2230,11 +2490,6 @@
       return ::vkUnmapMemory( device, memory );
     }
 
-    VkResult vkUnregisterObjectsNVX( VkDevice device, VkObjectTableNVX objectTable, uint32_t objectCount, const VkObjectEntryTypeNVX* pObjectEntryTypes, const uint32_t* pObjectIndices ) const VULKAN_HPP_NOEXCEPT
-    {
-      return ::vkUnregisterObjectsNVX( device, objectTable, objectCount, pObjectEntryTypes, pObjectIndices );
-    }
-
     void vkUpdateDescriptorSetWithTemplate( VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData ) const VULKAN_HPP_NOEXCEPT
     {
       return ::vkUpdateDescriptorSetWithTemplate( device, descriptorSet, descriptorUpdateTemplate, pData );
@@ -2265,6 +2520,13 @@
       return ::vkWaitSemaphoresKHR( device, pWaitInfo, timeout );
     }
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    VkResult vkWriteAccelerationStructuresPropertiesKHR( VkDevice device, uint32_t accelerationStructureCount, const VkAccelerationStructureKHR* pAccelerationStructures, VkQueryType queryType, size_t dataSize, void* pData, size_t stride ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ::vkWriteAccelerationStructuresPropertiesKHR( device, accelerationStructureCount, pAccelerationStructures, queryType, dataSize, pData, stride );
+    }
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
 #ifdef VK_USE_PLATFORM_ANDROID_KHR
     VkResult vkCreateAndroidSurfaceKHR( VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface ) const VULKAN_HPP_NOEXCEPT
     {
@@ -2564,11 +2826,6 @@
       return ::vkGetPhysicalDeviceFormatProperties2KHR( physicalDevice, format, pFormatProperties );
     }
 
-    void vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX( VkPhysicalDevice physicalDevice, VkDeviceGeneratedCommandsFeaturesNVX* pFeatures, VkDeviceGeneratedCommandsLimitsNVX* pLimits ) const VULKAN_HPP_NOEXCEPT
-    {
-      return ::vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX( physicalDevice, pFeatures, pLimits );
-    }
-
     VkResult vkGetPhysicalDeviceImageFormatProperties( VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties* pImageFormatProperties ) const VULKAN_HPP_NOEXCEPT
     {
       return ::vkGetPhysicalDeviceImageFormatProperties( physicalDevice, format, type, tiling, usage, flags, pImageFormatProperties );
@@ -2951,123 +3208,63 @@
       Dispatch const* m_dispatch;
   };
 
-  template<typename T, size_t N, size_t I>
-  class PrivateConstExpression1DArrayCopy
-  {
-  public:
-    VULKAN_HPP_CONSTEXPR_14 static void copy( T * dst, T const* src ) VULKAN_HPP_NOEXCEPT
-    {
-      PrivateConstExpression1DArrayCopy<T, N, I - 1>::copy( dst, src );
-      dst[I - 1] = src[I - 1];
-    }
-  };
-
-  template<typename T, size_t N>
-  class PrivateConstExpression1DArrayCopy<T, N, 0>
-  {
-  public:
-    VULKAN_HPP_CONSTEXPR_14 static void copy( T * /*dst*/, T const* /*src*/ ) VULKAN_HPP_NOEXCEPT
-    {}
-  };
-
-  template <typename T, size_t N>
-  class ConstExpression1DArrayCopy
-  {
-  public:
-    VULKAN_HPP_CONSTEXPR_14 static void copy( T dst[N], const T src[N] ) VULKAN_HPP_NOEXCEPT
-    {
-      const size_t C = N / 2;
-      PrivateConstExpression1DArrayCopy<T, C, C>::copy( dst, src );
-      PrivateConstExpression1DArrayCopy<T, N - C, N - C>::copy(dst + C, src + C);
-    }
-
-    VULKAN_HPP_CONSTEXPR_14 static void copy( T dst[N], std::array<T, N> const& src ) VULKAN_HPP_NOEXCEPT
-    {
-      const size_t C = N / 2;
-      PrivateConstExpression1DArrayCopy<T, C, C>::copy(dst, src.data());
-      PrivateConstExpression1DArrayCopy<T, N - C, N - C>::copy(dst + C, src.data() + C);
-    }
-  };
-
-  template<typename T, size_t N, size_t M, size_t I, size_t J>
-  class PrivateConstExpression2DArrayCopy
-  {
-  public:
-    VULKAN_HPP_CONSTEXPR_14 static void copy( T * dst, T const* src ) VULKAN_HPP_NOEXCEPT
-    {
-      PrivateConstExpression2DArrayCopy<T, N, M, I, J - 1>::copy( dst, src );
-      dst[(I - 1) * M + J - 1] = src[(I - 1) * M + J - 1];
-    }
-  };
-
-  template<typename T, size_t N, size_t M, size_t I>
-  class PrivateConstExpression2DArrayCopy<T, N, M, I,0>
-  {
-  public:
-    VULKAN_HPP_CONSTEXPR_14 static void copy( T * dst, T const* src ) VULKAN_HPP_NOEXCEPT
-    {
-      PrivateConstExpression2DArrayCopy<T, N, M, I - 1, M>::copy( dst, src );
-    }
-  };
-
-  template<typename T, size_t N, size_t M, size_t J>
-  class PrivateConstExpression2DArrayCopy<T, N, M, 0, J>
-  {
-  public:
-    VULKAN_HPP_CONSTEXPR_14 static void copy( T * /*dst*/, T const* /*src*/ ) VULKAN_HPP_NOEXCEPT
-    {}
-  };
-
-  template <typename T, size_t N, size_t M>
-  class ConstExpression2DArrayCopy
-  {
-  public:
-    VULKAN_HPP_CONSTEXPR_14 static void copy( T dst[N][M], const T src[N][M] ) VULKAN_HPP_NOEXCEPT
-    {
-      PrivateConstExpression2DArrayCopy<T, N, M, N, M>::copy( &dst[0][0], &src[0][0] );
-    }
-
-    VULKAN_HPP_CONSTEXPR_14 static void copy( T dst[N][M], std::array<std::array<T, M>, N> const& src ) VULKAN_HPP_NOEXCEPT
-    {
-      PrivateConstExpression2DArrayCopy<T, N, M, N, M>::copy( &dst[0][0], src.data()->data() );
-    }
-  };
-
   using Bool32 = uint32_t;
   using DeviceAddress = uint64_t;
   using DeviceSize = uint64_t;
   using SampleMask = uint32_t;
 
-  enum class AccelerationStructureMemoryRequirementsTypeNV
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  enum class AccelerationStructureBuildTypeKHR
   {
-    eObject = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV,
-    eBuildScratch = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV,
-    eUpdateScratch = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV
+    eHost = VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR,
+    eDevice = VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,
+    eHostOrDevice = VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_OR_DEVICE_KHR
   };
 
-  VULKAN_HPP_INLINE std::string to_string( AccelerationStructureMemoryRequirementsTypeNV value )
+  VULKAN_HPP_INLINE std::string to_string( AccelerationStructureBuildTypeKHR value )
   {
     switch ( value )
     {
-      case AccelerationStructureMemoryRequirementsTypeNV::eObject : return "Object";
-      case AccelerationStructureMemoryRequirementsTypeNV::eBuildScratch : return "BuildScratch";
-      case AccelerationStructureMemoryRequirementsTypeNV::eUpdateScratch : return "UpdateScratch";
+      case AccelerationStructureBuildTypeKHR::eHost : return "Host";
+      case AccelerationStructureBuildTypeKHR::eDevice : return "Device";
+      case AccelerationStructureBuildTypeKHR::eHostOrDevice : return "HostOrDevice";
+      default: return "invalid";
+    }
+  }
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+  enum class AccelerationStructureMemoryRequirementsTypeKHR
+  {
+    eObject = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR,
+    eBuildScratch = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR,
+    eUpdateScratch = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_KHR
+  };
+  using AccelerationStructureMemoryRequirementsTypeNV = AccelerationStructureMemoryRequirementsTypeKHR;
+
+  VULKAN_HPP_INLINE std::string to_string( AccelerationStructureMemoryRequirementsTypeKHR value )
+  {
+    switch ( value )
+    {
+      case AccelerationStructureMemoryRequirementsTypeKHR::eObject : return "Object";
+      case AccelerationStructureMemoryRequirementsTypeKHR::eBuildScratch : return "BuildScratch";
+      case AccelerationStructureMemoryRequirementsTypeKHR::eUpdateScratch : return "UpdateScratch";
       default: return "invalid";
     }
   }
 
-  enum class AccelerationStructureTypeNV
+  enum class AccelerationStructureTypeKHR
   {
-    eTopLevel = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV,
-    eBottomLevel = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV
+    eTopLevel = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR,
+    eBottomLevel = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR
   };
+  using AccelerationStructureTypeNV = AccelerationStructureTypeKHR;
 
-  VULKAN_HPP_INLINE std::string to_string( AccelerationStructureTypeNV value )
+  VULKAN_HPP_INLINE std::string to_string( AccelerationStructureTypeKHR value )
   {
     switch ( value )
     {
-      case AccelerationStructureTypeNV::eTopLevel : return "TopLevel";
-      case AccelerationStructureTypeNV::eBottomLevel : return "BottomLevel";
+      case AccelerationStructureTypeKHR::eTopLevel : return "TopLevel";
+      case AccelerationStructureTypeKHR::eBottomLevel : return "BottomLevel";
       default: return "invalid";
     }
   }
@@ -3095,13 +3292,15 @@
     eTransformFeedbackCounterReadEXT = VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT,
     eTransformFeedbackCounterWriteEXT = VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT,
     eConditionalRenderingReadEXT = VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT,
-    eCommandProcessReadNVX = VK_ACCESS_COMMAND_PROCESS_READ_BIT_NVX,
-    eCommandProcessWriteNVX = VK_ACCESS_COMMAND_PROCESS_WRITE_BIT_NVX,
     eColorAttachmentReadNoncoherentEXT = VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT,
+    eAccelerationStructureReadKHR = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR,
+    eAccelerationStructureWriteKHR = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR,
     eShadingRateImageReadNV = VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV,
+    eFragmentDensityMapReadEXT = VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT,
+    eCommandPreprocessReadNV = VK_ACCESS_COMMAND_PREPROCESS_READ_BIT_NV,
+    eCommandPreprocessWriteNV = VK_ACCESS_COMMAND_PREPROCESS_WRITE_BIT_NV,
     eAccelerationStructureReadNV = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV,
-    eAccelerationStructureWriteNV = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NV,
-    eFragmentDensityMapReadEXT = VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT
+    eAccelerationStructureWriteNV = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NV
   };
 
   VULKAN_HPP_INLINE std::string to_string( AccessFlagBits value )
@@ -3129,13 +3328,13 @@
       case AccessFlagBits::eTransformFeedbackCounterReadEXT : return "TransformFeedbackCounterReadEXT";
       case AccessFlagBits::eTransformFeedbackCounterWriteEXT : return "TransformFeedbackCounterWriteEXT";
       case AccessFlagBits::eConditionalRenderingReadEXT : return "ConditionalRenderingReadEXT";
-      case AccessFlagBits::eCommandProcessReadNVX : return "CommandProcessReadNVX";
-      case AccessFlagBits::eCommandProcessWriteNVX : return "CommandProcessWriteNVX";
       case AccessFlagBits::eColorAttachmentReadNoncoherentEXT : return "ColorAttachmentReadNoncoherentEXT";
+      case AccessFlagBits::eAccelerationStructureReadKHR : return "AccelerationStructureReadKHR";
+      case AccessFlagBits::eAccelerationStructureWriteKHR : return "AccelerationStructureWriteKHR";
       case AccessFlagBits::eShadingRateImageReadNV : return "ShadingRateImageReadNV";
-      case AccessFlagBits::eAccelerationStructureReadNV : return "AccelerationStructureReadNV";
-      case AccessFlagBits::eAccelerationStructureWriteNV : return "AccelerationStructureWriteNV";
       case AccessFlagBits::eFragmentDensityMapReadEXT : return "FragmentDensityMapReadEXT";
+      case AccessFlagBits::eCommandPreprocessReadNV : return "CommandPreprocessReadNV";
+      case AccessFlagBits::eCommandPreprocessWriteNV : return "CommandPreprocessWriteNV";
       default: return "invalid";
     }
   }
@@ -3183,7 +3382,8 @@
   enum class AttachmentStoreOp
   {
     eStore = VK_ATTACHMENT_STORE_OP_STORE,
-    eDontCare = VK_ATTACHMENT_STORE_OP_DONT_CARE
+    eDontCare = VK_ATTACHMENT_STORE_OP_DONT_CARE,
+    eNoneQCOM = VK_ATTACHMENT_STORE_OP_NONE_QCOM
   };
 
   VULKAN_HPP_INLINE std::string to_string( AttachmentStoreOp value )
@@ -3192,6 +3392,7 @@
     {
       case AttachmentStoreOp::eStore : return "Store";
       case AttachmentStoreOp::eDontCare : return "DontCare";
+      case AttachmentStoreOp::eNoneQCOM : return "NoneQCOM";
       default: return "invalid";
     }
   }
@@ -3441,6 +3642,7 @@
     eTransformFeedbackBufferEXT = VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT,
     eTransformFeedbackCounterBufferEXT = VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT,
     eConditionalRenderingEXT = VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT,
+    eRayTracingKHR = VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR,
     eRayTracingNV = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV,
     eShaderDeviceAddressEXT = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_EXT,
     eShaderDeviceAddressKHR = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR
@@ -3463,7 +3665,7 @@
       case BufferUsageFlagBits::eTransformFeedbackBufferEXT : return "TransformFeedbackBufferEXT";
       case BufferUsageFlagBits::eTransformFeedbackCounterBufferEXT : return "TransformFeedbackCounterBufferEXT";
       case BufferUsageFlagBits::eConditionalRenderingEXT : return "ConditionalRenderingEXT";
-      case BufferUsageFlagBits::eRayTracingNV : return "RayTracingNV";
+      case BufferUsageFlagBits::eRayTracingKHR : return "RayTracingKHR";
       default: return "invalid";
     }
   }
@@ -3476,24 +3678,25 @@
     return "(void)";
   }
 
-  enum class BuildAccelerationStructureFlagBitsNV : VkBuildAccelerationStructureFlagsNV
+  enum class BuildAccelerationStructureFlagBitsKHR : VkBuildAccelerationStructureFlagsKHR
   {
-    eAllowUpdate = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_NV,
-    eAllowCompaction = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_NV,
-    ePreferFastTrace = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_NV,
-    ePreferFastBuild = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_NV,
-    eLowMemory = VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_NV
+    eAllowUpdate = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR,
+    eAllowCompaction = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR,
+    ePreferFastTrace = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR,
+    ePreferFastBuild = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR,
+    eLowMemory = VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR
   };
+  using BuildAccelerationStructureFlagBitsNV = BuildAccelerationStructureFlagBitsKHR;
 
-  VULKAN_HPP_INLINE std::string to_string( BuildAccelerationStructureFlagBitsNV value )
+  VULKAN_HPP_INLINE std::string to_string( BuildAccelerationStructureFlagBitsKHR value )
   {
     switch ( value )
     {
-      case BuildAccelerationStructureFlagBitsNV::eAllowUpdate : return "AllowUpdate";
-      case BuildAccelerationStructureFlagBitsNV::eAllowCompaction : return "AllowCompaction";
-      case BuildAccelerationStructureFlagBitsNV::ePreferFastTrace : return "PreferFastTrace";
-      case BuildAccelerationStructureFlagBitsNV::ePreferFastBuild : return "PreferFastBuild";
-      case BuildAccelerationStructureFlagBitsNV::eLowMemory : return "LowMemory";
+      case BuildAccelerationStructureFlagBitsKHR::eAllowUpdate : return "AllowUpdate";
+      case BuildAccelerationStructureFlagBitsKHR::eAllowCompaction : return "AllowCompaction";
+      case BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace : return "PreferFastTrace";
+      case BuildAccelerationStructureFlagBitsKHR::ePreferFastBuild : return "PreferFastBuild";
+      case BuildAccelerationStructureFlagBitsKHR::eLowMemory : return "LowMemory";
       default: return "invalid";
     }
   }
@@ -3821,18 +4024,23 @@
     }
   }
 
-  enum class CopyAccelerationStructureModeNV
+  enum class CopyAccelerationStructureModeKHR
   {
-    eClone = VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV,
-    eCompact = VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV
+    eClone = VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR,
+    eCompact = VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR,
+    eSerialize = VK_COPY_ACCELERATION_STRUCTURE_MODE_SERIALIZE_KHR,
+    eDeserialize = VK_COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR
   };
+  using CopyAccelerationStructureModeNV = CopyAccelerationStructureModeKHR;
 
-  VULKAN_HPP_INLINE std::string to_string( CopyAccelerationStructureModeNV value )
+  VULKAN_HPP_INLINE std::string to_string( CopyAccelerationStructureModeKHR value )
   {
     switch ( value )
     {
-      case CopyAccelerationStructureModeNV::eClone : return "Clone";
-      case CopyAccelerationStructureModeNV::eCompact : return "Compact";
+      case CopyAccelerationStructureModeKHR::eClone : return "Clone";
+      case CopyAccelerationStructureModeKHR::eCompact : return "Compact";
+      case CopyAccelerationStructureModeKHR::eSerialize : return "Serialize";
+      case CopyAccelerationStructureModeKHR::eDeserialize : return "Deserialize";
       default: return "invalid";
     }
   }
@@ -3948,16 +4156,15 @@
     eDebugReportCallbackEXT = VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT,
     eDisplayKHR = VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT,
     eDisplayModeKHR = VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT,
-    eObjectTableNVX = VK_DEBUG_REPORT_OBJECT_TYPE_OBJECT_TABLE_NVX_EXT,
-    eIndirectCommandsLayoutNVX = VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT,
     eValidationCacheEXT = VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT,
     eSamplerYcbcrConversion = VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT,
     eDescriptorUpdateTemplate = VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT,
-    eAccelerationStructureNV = VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT,
+    eAccelerationStructureKHR = VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR_EXT,
     eDebugReport = VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT,
     eValidationCache = VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT,
     eDescriptorUpdateTemplateKHR = VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR_EXT,
-    eSamplerYcbcrConversionKHR = VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR_EXT
+    eSamplerYcbcrConversionKHR = VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR_EXT,
+    eAccelerationStructureNV = VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT
   };
 
   VULKAN_HPP_INLINE std::string to_string( DebugReportObjectTypeEXT value )
@@ -3995,12 +4202,10 @@
       case DebugReportObjectTypeEXT::eDebugReportCallbackEXT : return "DebugReportCallbackEXT";
       case DebugReportObjectTypeEXT::eDisplayKHR : return "DisplayKHR";
       case DebugReportObjectTypeEXT::eDisplayModeKHR : return "DisplayModeKHR";
-      case DebugReportObjectTypeEXT::eObjectTableNVX : return "ObjectTableNVX";
-      case DebugReportObjectTypeEXT::eIndirectCommandsLayoutNVX : return "IndirectCommandsLayoutNVX";
       case DebugReportObjectTypeEXT::eValidationCacheEXT : return "ValidationCacheEXT";
       case DebugReportObjectTypeEXT::eSamplerYcbcrConversion : return "SamplerYcbcrConversion";
       case DebugReportObjectTypeEXT::eDescriptorUpdateTemplate : return "DescriptorUpdateTemplate";
-      case DebugReportObjectTypeEXT::eAccelerationStructureNV : return "AccelerationStructureNV";
+      case DebugReportObjectTypeEXT::eAccelerationStructureKHR : return "AccelerationStructureKHR";
       default: return "invalid";
     }
   }
@@ -4132,6 +4337,7 @@
     eStorageBufferDynamic = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC,
     eInputAttachment = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
     eInlineUniformBlockEXT = VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT,
+    eAccelerationStructureKHR = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR,
     eAccelerationStructureNV = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV
   };
 
@@ -4151,7 +4357,7 @@
       case DescriptorType::eStorageBufferDynamic : return "StorageBufferDynamic";
       case DescriptorType::eInputAttachment : return "InputAttachment";
       case DescriptorType::eInlineUniformBlockEXT : return "InlineUniformBlockEXT";
-      case DescriptorType::eAccelerationStructureNV : return "AccelerationStructureNV";
+      case DescriptorType::eAccelerationStructureKHR : return "AccelerationStructureKHR";
       default: return "invalid";
     }
   }
@@ -4181,6 +4387,24 @@
     return "(void)";
   }
 
+  enum class DeviceDiagnosticsConfigFlagBitsNV : VkDeviceDiagnosticsConfigFlagsNV
+  {
+    eEnableShaderDebugInfo = VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_SHADER_DEBUG_INFO_BIT_NV,
+    eEnableResourceTracking = VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_RESOURCE_TRACKING_BIT_NV,
+    eEnableAutomaticCheckpoints = VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_AUTOMATIC_CHECKPOINTS_BIT_NV
+  };
+
+  VULKAN_HPP_INLINE std::string to_string( DeviceDiagnosticsConfigFlagBitsNV value )
+  {
+    switch ( value )
+    {
+      case DeviceDiagnosticsConfigFlagBitsNV::eEnableShaderDebugInfo : return "EnableShaderDebugInfo";
+      case DeviceDiagnosticsConfigFlagBitsNV::eEnableResourceTracking : return "EnableResourceTracking";
+      case DeviceDiagnosticsConfigFlagBitsNV::eEnableAutomaticCheckpoints : return "EnableAutomaticCheckpoints";
+      default: return "invalid";
+    }
+  }
+
   enum class DeviceEventTypeEXT
   {
     eDisplayHotplug = VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT
@@ -5151,6 +5375,7 @@
     eCositedChromaSamples = VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT,
     eSampledImageFilterMinmax = VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT,
     eSampledImageFilterCubicIMG = VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG,
+    eAccelerationStructureVertexBufferKHR = VK_FORMAT_FEATURE_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR,
     eFragmentDensityMapEXT = VK_FORMAT_FEATURE_FRAGMENT_DENSITY_MAP_BIT_EXT,
     eTransferSrcKHR = VK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR,
     eTransferDstKHR = VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR,
@@ -5193,6 +5418,7 @@
       case FormatFeatureFlagBits::eCositedChromaSamples : return "CositedChromaSamples";
       case FormatFeatureFlagBits::eSampledImageFilterMinmax : return "SampledImageFilterMinmax";
       case FormatFeatureFlagBits::eSampledImageFilterCubicIMG : return "SampledImageFilterCubicIMG";
+      case FormatFeatureFlagBits::eAccelerationStructureVertexBufferKHR : return "AccelerationStructureVertexBufferKHR";
       case FormatFeatureFlagBits::eFragmentDensityMapEXT : return "FragmentDensityMapEXT";
       default: return "invalid";
     }
@@ -5251,54 +5477,60 @@
   }
 #endif /*VK_USE_PLATFORM_WIN32_KHR*/
 
-  enum class GeometryFlagBitsNV : VkGeometryFlagsNV
+  enum class GeometryFlagBitsKHR : VkGeometryFlagsKHR
   {
-    eOpaque = VK_GEOMETRY_OPAQUE_BIT_NV,
-    eNoDuplicateAnyHitInvocation = VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_NV
+    eOpaque = VK_GEOMETRY_OPAQUE_BIT_KHR,
+    eNoDuplicateAnyHitInvocation = VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR
   };
+  using GeometryFlagBitsNV = GeometryFlagBitsKHR;
 
-  VULKAN_HPP_INLINE std::string to_string( GeometryFlagBitsNV value )
+  VULKAN_HPP_INLINE std::string to_string( GeometryFlagBitsKHR value )
   {
     switch ( value )
     {
-      case GeometryFlagBitsNV::eOpaque : return "Opaque";
-      case GeometryFlagBitsNV::eNoDuplicateAnyHitInvocation : return "NoDuplicateAnyHitInvocation";
+      case GeometryFlagBitsKHR::eOpaque : return "Opaque";
+      case GeometryFlagBitsKHR::eNoDuplicateAnyHitInvocation : return "NoDuplicateAnyHitInvocation";
       default: return "invalid";
     }
   }
 
-  enum class GeometryInstanceFlagBitsNV : VkGeometryInstanceFlagsNV
+  enum class GeometryInstanceFlagBitsKHR : VkGeometryInstanceFlagsKHR
   {
-    eTriangleCullDisable = VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NV,
-    eTriangleFrontCounterclockwise = VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_NV,
-    eForceOpaque = VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_NV,
-    eForceNoOpaque = VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_NV
+    eTriangleFacingCullDisable = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR,
+    eTriangleFrontCounterclockwise = VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_KHR,
+    eForceOpaque = VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR,
+    eForceNoOpaque = VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR,
+    eTriangleCullDisable = VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NV
   };
+  using GeometryInstanceFlagBitsNV = GeometryInstanceFlagBitsKHR;
 
-  VULKAN_HPP_INLINE std::string to_string( GeometryInstanceFlagBitsNV value )
+  VULKAN_HPP_INLINE std::string to_string( GeometryInstanceFlagBitsKHR value )
   {
     switch ( value )
     {
-      case GeometryInstanceFlagBitsNV::eTriangleCullDisable : return "TriangleCullDisable";
-      case GeometryInstanceFlagBitsNV::eTriangleFrontCounterclockwise : return "TriangleFrontCounterclockwise";
-      case GeometryInstanceFlagBitsNV::eForceOpaque : return "ForceOpaque";
-      case GeometryInstanceFlagBitsNV::eForceNoOpaque : return "ForceNoOpaque";
+      case GeometryInstanceFlagBitsKHR::eTriangleFacingCullDisable : return "TriangleFacingCullDisable";
+      case GeometryInstanceFlagBitsKHR::eTriangleFrontCounterclockwise : return "TriangleFrontCounterclockwise";
+      case GeometryInstanceFlagBitsKHR::eForceOpaque : return "ForceOpaque";
+      case GeometryInstanceFlagBitsKHR::eForceNoOpaque : return "ForceNoOpaque";
       default: return "invalid";
     }
   }
 
-  enum class GeometryTypeNV
+  enum class GeometryTypeKHR
   {
-    eTriangles = VK_GEOMETRY_TYPE_TRIANGLES_NV,
-    eAabbs = VK_GEOMETRY_TYPE_AABBS_NV
+    eTriangles = VK_GEOMETRY_TYPE_TRIANGLES_KHR,
+    eAabbs = VK_GEOMETRY_TYPE_AABBS_KHR,
+    eInstances = VK_GEOMETRY_TYPE_INSTANCES_KHR
   };
+  using GeometryTypeNV = GeometryTypeKHR;
 
-  VULKAN_HPP_INLINE std::string to_string( GeometryTypeNV value )
+  VULKAN_HPP_INLINE std::string to_string( GeometryTypeKHR value )
   {
     switch ( value )
     {
-      case GeometryTypeNV::eTriangles : return "Triangles";
-      case GeometryTypeNV::eAabbs : return "Aabbs";
+      case GeometryTypeKHR::eTriangles : return "Triangles";
+      case GeometryTypeKHR::eAabbs : return "Aabbs";
+      case GeometryTypeKHR::eInstances : return "Instances";
       default: return "invalid";
     }
   }
@@ -5556,8 +5788,9 @@
   {
     eUint16 = VK_INDEX_TYPE_UINT16,
     eUint32 = VK_INDEX_TYPE_UINT32,
-    eNoneNV = VK_INDEX_TYPE_NONE_NV,
-    eUint8EXT = VK_INDEX_TYPE_UINT8_EXT
+    eNoneKHR = VK_INDEX_TYPE_NONE_KHR,
+    eUint8EXT = VK_INDEX_TYPE_UINT8_EXT,
+    eNoneNV = VK_INDEX_TYPE_NONE_NV
   };
 
   VULKAN_HPP_INLINE std::string to_string( IndexType value )
@@ -5566,56 +5799,68 @@
     {
       case IndexType::eUint16 : return "Uint16";
       case IndexType::eUint32 : return "Uint32";
-      case IndexType::eNoneNV : return "NoneNV";
+      case IndexType::eNoneKHR : return "NoneKHR";
       case IndexType::eUint8EXT : return "Uint8EXT";
       default: return "invalid";
     }
   }
 
-  enum class IndirectCommandsLayoutUsageFlagBitsNVX : VkIndirectCommandsLayoutUsageFlagsNVX
+  enum class IndirectCommandsLayoutUsageFlagBitsNV : VkIndirectCommandsLayoutUsageFlagsNV
   {
-    eUnorderedSequences = VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NVX,
-    eSparseSequences = VK_INDIRECT_COMMANDS_LAYOUT_USAGE_SPARSE_SEQUENCES_BIT_NVX,
-    eEmptyExecutions = VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EMPTY_EXECUTIONS_BIT_NVX,
-    eIndexedSequences = VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NVX
+    eExplicitPreprocess = VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EXPLICIT_PREPROCESS_BIT_NV,
+    eIndexedSequences = VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NV,
+    eUnorderedSequences = VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NV
   };
 
-  VULKAN_HPP_INLINE std::string to_string( IndirectCommandsLayoutUsageFlagBitsNVX value )
+  VULKAN_HPP_INLINE std::string to_string( IndirectCommandsLayoutUsageFlagBitsNV value )
   {
     switch ( value )
     {
-      case IndirectCommandsLayoutUsageFlagBitsNVX::eUnorderedSequences : return "UnorderedSequences";
-      case IndirectCommandsLayoutUsageFlagBitsNVX::eSparseSequences : return "SparseSequences";
-      case IndirectCommandsLayoutUsageFlagBitsNVX::eEmptyExecutions : return "EmptyExecutions";
-      case IndirectCommandsLayoutUsageFlagBitsNVX::eIndexedSequences : return "IndexedSequences";
+      case IndirectCommandsLayoutUsageFlagBitsNV::eExplicitPreprocess : return "ExplicitPreprocess";
+      case IndirectCommandsLayoutUsageFlagBitsNV::eIndexedSequences : return "IndexedSequences";
+      case IndirectCommandsLayoutUsageFlagBitsNV::eUnorderedSequences : return "UnorderedSequences";
       default: return "invalid";
     }
   }
 
-  enum class IndirectCommandsTokenTypeNVX
+  enum class IndirectCommandsTokenTypeNV
   {
-    ePipeline = VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NVX,
-    eDescriptorSet = VK_INDIRECT_COMMANDS_TOKEN_TYPE_DESCRIPTOR_SET_NVX,
-    eIndexBuffer = VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_NVX,
-    eVertexBuffer = VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_NVX,
-    ePushConstant = VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NVX,
-    eDrawIndexed = VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NVX,
-    eDraw = VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NVX,
-    eDispatch = VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NVX
+    eShaderGroup = VK_INDIRECT_COMMANDS_TOKEN_TYPE_SHADER_GROUP_NV,
+    eStateFlags = VK_INDIRECT_COMMANDS_TOKEN_TYPE_STATE_FLAGS_NV,
+    eIndexBuffer = VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_NV,
+    eVertexBuffer = VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_NV,
+    ePushConstant = VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NV,
+    eDrawIndexed = VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NV,
+    eDraw = VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NV,
+    eDrawTasks = VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_TASKS_NV
   };
 
-  VULKAN_HPP_INLINE std::string to_string( IndirectCommandsTokenTypeNVX value )
+  VULKAN_HPP_INLINE std::string to_string( IndirectCommandsTokenTypeNV value )
   {
     switch ( value )
     {
-      case IndirectCommandsTokenTypeNVX::ePipeline : return "Pipeline";
-      case IndirectCommandsTokenTypeNVX::eDescriptorSet : return "DescriptorSet";
-      case IndirectCommandsTokenTypeNVX::eIndexBuffer : return "IndexBuffer";
-      case IndirectCommandsTokenTypeNVX::eVertexBuffer : return "VertexBuffer";
-      case IndirectCommandsTokenTypeNVX::ePushConstant : return "PushConstant";
-      case IndirectCommandsTokenTypeNVX::eDrawIndexed : return "DrawIndexed";
-      case IndirectCommandsTokenTypeNVX::eDraw : return "Draw";
-      case IndirectCommandsTokenTypeNVX::eDispatch : return "Dispatch";
+      case IndirectCommandsTokenTypeNV::eShaderGroup : return "ShaderGroup";
+      case IndirectCommandsTokenTypeNV::eStateFlags : return "StateFlags";
+      case IndirectCommandsTokenTypeNV::eIndexBuffer : return "IndexBuffer";
+      case IndirectCommandsTokenTypeNV::eVertexBuffer : return "VertexBuffer";
+      case IndirectCommandsTokenTypeNV::ePushConstant : return "PushConstant";
+      case IndirectCommandsTokenTypeNV::eDrawIndexed : return "DrawIndexed";
+      case IndirectCommandsTokenTypeNV::eDraw : return "Draw";
+      case IndirectCommandsTokenTypeNV::eDrawTasks : return "DrawTasks";
+      default: return "invalid";
+    }
+  }
+
+  enum class IndirectStateFlagBitsNV : VkIndirectStateFlagsNV
+  {
+    eFlagFrontface = VK_INDIRECT_STATE_FLAG_FRONTFACE_BIT_NV
+  };
+
+  VULKAN_HPP_INLINE std::string to_string( IndirectStateFlagBitsNV value )
+  {
+    switch ( value )
+    {
+      case IndirectStateFlagBitsNV::eFlagFrontface : return "FlagFrontface";
       default: return "invalid";
     }
   }
@@ -5788,44 +6033,6 @@
     }
   }
 
-  enum class ObjectEntryTypeNVX
-  {
-    eDescriptorSet = VK_OBJECT_ENTRY_TYPE_DESCRIPTOR_SET_NVX,
-    ePipeline = VK_OBJECT_ENTRY_TYPE_PIPELINE_NVX,
-    eIndexBuffer = VK_OBJECT_ENTRY_TYPE_INDEX_BUFFER_NVX,
-    eVertexBuffer = VK_OBJECT_ENTRY_TYPE_VERTEX_BUFFER_NVX,
-    ePushConstant = VK_OBJECT_ENTRY_TYPE_PUSH_CONSTANT_NVX
-  };
-
-  VULKAN_HPP_INLINE std::string to_string( ObjectEntryTypeNVX value )
-  {
-    switch ( value )
-    {
-      case ObjectEntryTypeNVX::eDescriptorSet : return "DescriptorSet";
-      case ObjectEntryTypeNVX::ePipeline : return "Pipeline";
-      case ObjectEntryTypeNVX::eIndexBuffer : return "IndexBuffer";
-      case ObjectEntryTypeNVX::eVertexBuffer : return "VertexBuffer";
-      case ObjectEntryTypeNVX::ePushConstant : return "PushConstant";
-      default: return "invalid";
-    }
-  }
-
-  enum class ObjectEntryUsageFlagBitsNVX : VkObjectEntryUsageFlagsNVX
-  {
-    eGraphics = VK_OBJECT_ENTRY_USAGE_GRAPHICS_BIT_NVX,
-    eCompute = VK_OBJECT_ENTRY_USAGE_COMPUTE_BIT_NVX
-  };
-
-  VULKAN_HPP_INLINE std::string to_string( ObjectEntryUsageFlagBitsNVX value )
-  {
-    switch ( value )
-    {
-      case ObjectEntryUsageFlagBitsNVX::eGraphics : return "Graphics";
-      case ObjectEntryUsageFlagBitsNVX::eCompute : return "Compute";
-      default: return "invalid";
-    }
-  }
-
   enum class ObjectType
   {
     eUnknown = VK_OBJECT_TYPE_UNKNOWN,
@@ -5861,14 +6068,15 @@
     eDisplayKHR = VK_OBJECT_TYPE_DISPLAY_KHR,
     eDisplayModeKHR = VK_OBJECT_TYPE_DISPLAY_MODE_KHR,
     eDebugReportCallbackEXT = VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT,
-    eObjectTableNVX = VK_OBJECT_TYPE_OBJECT_TABLE_NVX,
-    eIndirectCommandsLayoutNVX = VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX,
     eDebugUtilsMessengerEXT = VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT,
+    eAccelerationStructureKHR = VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR,
     eValidationCacheEXT = VK_OBJECT_TYPE_VALIDATION_CACHE_EXT,
-    eAccelerationStructureNV = VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV,
     ePerformanceConfigurationINTEL = VK_OBJECT_TYPE_PERFORMANCE_CONFIGURATION_INTEL,
+    eDeferredOperationKHR = VK_OBJECT_TYPE_DEFERRED_OPERATION_KHR,
+    eIndirectCommandsLayoutNV = VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NV,
     eDescriptorUpdateTemplateKHR = VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR,
-    eSamplerYcbcrConversionKHR = VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR
+    eSamplerYcbcrConversionKHR = VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR,
+    eAccelerationStructureNV = VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV
   };
 
   VULKAN_HPP_INLINE std::string to_string( ObjectType value )
@@ -5908,12 +6116,12 @@
       case ObjectType::eDisplayKHR : return "DisplayKHR";
       case ObjectType::eDisplayModeKHR : return "DisplayModeKHR";
       case ObjectType::eDebugReportCallbackEXT : return "DebugReportCallbackEXT";
-      case ObjectType::eObjectTableNVX : return "ObjectTableNVX";
-      case ObjectType::eIndirectCommandsLayoutNVX : return "IndirectCommandsLayoutNVX";
       case ObjectType::eDebugUtilsMessengerEXT : return "DebugUtilsMessengerEXT";
+      case ObjectType::eAccelerationStructureKHR : return "AccelerationStructureKHR";
       case ObjectType::eValidationCacheEXT : return "ValidationCacheEXT";
-      case ObjectType::eAccelerationStructureNV : return "AccelerationStructureNV";
       case ObjectType::ePerformanceConfigurationINTEL : return "PerformanceConfigurationINTEL";
+      case ObjectType::eDeferredOperationKHR : return "DeferredOperationKHR";
+      case ObjectType::eIndirectCommandsLayoutNV : return "IndirectCommandsLayoutNV";
       default: return "invalid";
     }
   }
@@ -6128,6 +6336,7 @@
   {
     eGraphics = VK_PIPELINE_BIND_POINT_GRAPHICS,
     eCompute = VK_PIPELINE_BIND_POINT_COMPUTE,
+    eRayTracingKHR = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR,
     eRayTracingNV = VK_PIPELINE_BIND_POINT_RAY_TRACING_NV
   };
 
@@ -6137,17 +6346,23 @@
     {
       case PipelineBindPoint::eGraphics : return "Graphics";
       case PipelineBindPoint::eCompute : return "Compute";
-      case PipelineBindPoint::eRayTracingNV : return "RayTracingNV";
+      case PipelineBindPoint::eRayTracingKHR : return "RayTracingKHR";
       default: return "invalid";
     }
   }
 
-  enum class PipelineCacheCreateFlagBits
-  {};
-
-  VULKAN_HPP_INLINE std::string to_string( PipelineCacheCreateFlagBits )
+  enum class PipelineCacheCreateFlagBits : VkPipelineCacheCreateFlags
   {
-    return "(void)";
+    eExternallySynchronizedEXT = VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT_EXT
+  };
+
+  VULKAN_HPP_INLINE std::string to_string( PipelineCacheCreateFlagBits value )
+  {
+    switch ( value )
+    {
+      case PipelineCacheCreateFlagBits::eExternallySynchronizedEXT : return "ExternallySynchronizedEXT";
+      default: return "invalid";
+    }
   }
 
   enum class PipelineCacheHeaderVersion
@@ -6187,9 +6402,19 @@
     eDerivative = VK_PIPELINE_CREATE_DERIVATIVE_BIT,
     eViewIndexFromDeviceIndex = VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT,
     eDispatchBase = VK_PIPELINE_CREATE_DISPATCH_BASE_BIT,
+    eRayTracingNoNullAnyHitShadersKHR = VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_ANY_HIT_SHADERS_BIT_KHR,
+    eRayTracingNoNullClosestHitShadersKHR = VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_CLOSEST_HIT_SHADERS_BIT_KHR,
+    eRayTracingNoNullMissShadersKHR = VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_MISS_SHADERS_BIT_KHR,
+    eRayTracingNoNullIntersectionShadersKHR = VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_INTERSECTION_SHADERS_BIT_KHR,
+    eRayTracingSkipTrianglesKHR = VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR,
+    eRayTracingSkipAabbsKHR = VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR,
     eDeferCompileNV = VK_PIPELINE_CREATE_DEFER_COMPILE_BIT_NV,
     eCaptureStatisticsKHR = VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR,
     eCaptureInternalRepresentationsKHR = VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR,
+    eIndirectBindableNV = VK_PIPELINE_CREATE_INDIRECT_BINDABLE_BIT_NV,
+    eLibraryKHR = VK_PIPELINE_CREATE_LIBRARY_BIT_KHR,
+    eFailOnPipelineCompileRequiredEXT = VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_EXT,
+    eEarlyReturnOnFailureEXT = VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT_EXT,
     eViewIndexFromDeviceIndexKHR = VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHR,
     eDispatchBaseKHR = VK_PIPELINE_CREATE_DISPATCH_BASE_KHR
   };
@@ -6203,9 +6428,19 @@
       case PipelineCreateFlagBits::eDerivative : return "Derivative";
       case PipelineCreateFlagBits::eViewIndexFromDeviceIndex : return "ViewIndexFromDeviceIndex";
       case PipelineCreateFlagBits::eDispatchBase : return "DispatchBase";
+      case PipelineCreateFlagBits::eRayTracingNoNullAnyHitShadersKHR : return "RayTracingNoNullAnyHitShadersKHR";
+      case PipelineCreateFlagBits::eRayTracingNoNullClosestHitShadersKHR : return "RayTracingNoNullClosestHitShadersKHR";
+      case PipelineCreateFlagBits::eRayTracingNoNullMissShadersKHR : return "RayTracingNoNullMissShadersKHR";
+      case PipelineCreateFlagBits::eRayTracingNoNullIntersectionShadersKHR : return "RayTracingNoNullIntersectionShadersKHR";
+      case PipelineCreateFlagBits::eRayTracingSkipTrianglesKHR : return "RayTracingSkipTrianglesKHR";
+      case PipelineCreateFlagBits::eRayTracingSkipAabbsKHR : return "RayTracingSkipAabbsKHR";
       case PipelineCreateFlagBits::eDeferCompileNV : return "DeferCompileNV";
       case PipelineCreateFlagBits::eCaptureStatisticsKHR : return "CaptureStatisticsKHR";
       case PipelineCreateFlagBits::eCaptureInternalRepresentationsKHR : return "CaptureInternalRepresentationsKHR";
+      case PipelineCreateFlagBits::eIndirectBindableNV : return "IndirectBindableNV";
+      case PipelineCreateFlagBits::eLibraryKHR : return "LibraryKHR";
+      case PipelineCreateFlagBits::eFailOnPipelineCompileRequiredEXT : return "FailOnPipelineCompileRequiredEXT";
+      case PipelineCreateFlagBits::eEarlyReturnOnFailureEXT : return "EarlyReturnOnFailureEXT";
       default: return "invalid";
     }
   }
@@ -6333,13 +6568,15 @@
     eAllCommands = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
     eTransformFeedbackEXT = VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT,
     eConditionalRenderingEXT = VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT,
-    eCommandProcessNVX = VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX,
+    eRayTracingShaderKHR = VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR,
+    eAccelerationStructureBuildKHR = VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR,
     eShadingRateImageNV = VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV,
-    eRayTracingShaderNV = VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_NV,
-    eAccelerationStructureBuildNV = VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV,
     eTaskShaderNV = VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV,
     eMeshShaderNV = VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV,
-    eFragmentDensityProcessEXT = VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT
+    eFragmentDensityProcessEXT = VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT,
+    eCommandPreprocessNV = VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_NV,
+    eRayTracingShaderNV = VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_NV,
+    eAccelerationStructureBuildNV = VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV
   };
 
   VULKAN_HPP_INLINE std::string to_string( PipelineStageFlagBits value )
@@ -6365,13 +6602,13 @@
       case PipelineStageFlagBits::eAllCommands : return "AllCommands";
       case PipelineStageFlagBits::eTransformFeedbackEXT : return "TransformFeedbackEXT";
       case PipelineStageFlagBits::eConditionalRenderingEXT : return "ConditionalRenderingEXT";
-      case PipelineStageFlagBits::eCommandProcessNVX : return "CommandProcessNVX";
+      case PipelineStageFlagBits::eRayTracingShaderKHR : return "RayTracingShaderKHR";
+      case PipelineStageFlagBits::eAccelerationStructureBuildKHR : return "AccelerationStructureBuildKHR";
       case PipelineStageFlagBits::eShadingRateImageNV : return "ShadingRateImageNV";
-      case PipelineStageFlagBits::eRayTracingShaderNV : return "RayTracingShaderNV";
-      case PipelineStageFlagBits::eAccelerationStructureBuildNV : return "AccelerationStructureBuildNV";
       case PipelineStageFlagBits::eTaskShaderNV : return "TaskShaderNV";
       case PipelineStageFlagBits::eMeshShaderNV : return "MeshShaderNV";
       case PipelineStageFlagBits::eFragmentDensityProcessEXT : return "FragmentDensityProcessEXT";
+      case PipelineStageFlagBits::eCommandPreprocessNV : return "CommandPreprocessNV";
       default: return "invalid";
     }
   }
@@ -6592,8 +6829,10 @@
     eTimestamp = VK_QUERY_TYPE_TIMESTAMP,
     eTransformFeedbackStreamEXT = VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT,
     ePerformanceQueryKHR = VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR,
-    eAccelerationStructureCompactedSizeNV = VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV,
-    ePerformanceQueryINTEL = VK_QUERY_TYPE_PERFORMANCE_QUERY_INTEL
+    eAccelerationStructureCompactedSizeKHR = VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR,
+    eAccelerationStructureSerializationSizeKHR = VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR,
+    ePerformanceQueryINTEL = VK_QUERY_TYPE_PERFORMANCE_QUERY_INTEL,
+    eAccelerationStructureCompactedSizeNV = VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV
   };
 
   VULKAN_HPP_INLINE std::string to_string( QueryType value )
@@ -6605,7 +6844,8 @@
       case QueryType::eTimestamp : return "Timestamp";
       case QueryType::eTransformFeedbackStreamEXT : return "TransformFeedbackStreamEXT";
       case QueryType::ePerformanceQueryKHR : return "PerformanceQueryKHR";
-      case QueryType::eAccelerationStructureCompactedSizeNV : return "AccelerationStructureCompactedSizeNV";
+      case QueryType::eAccelerationStructureCompactedSizeKHR : return "AccelerationStructureCompactedSizeKHR";
+      case QueryType::eAccelerationStructureSerializationSizeKHR : return "AccelerationStructureSerializationSizeKHR";
       case QueryType::ePerformanceQueryINTEL : return "PerformanceQueryINTEL";
       default: return "invalid";
     }
@@ -6669,20 +6909,21 @@
     }
   }
 
-  enum class RayTracingShaderGroupTypeNV
+  enum class RayTracingShaderGroupTypeKHR
   {
-    eGeneral = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV,
-    eTrianglesHitGroup = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_NV,
-    eProceduralHitGroup = VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV
+    eGeneral = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR,
+    eTrianglesHitGroup = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR,
+    eProceduralHitGroup = VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR
   };
+  using RayTracingShaderGroupTypeNV = RayTracingShaderGroupTypeKHR;
 
-  VULKAN_HPP_INLINE std::string to_string( RayTracingShaderGroupTypeNV value )
+  VULKAN_HPP_INLINE std::string to_string( RayTracingShaderGroupTypeKHR value )
   {
     switch ( value )
     {
-      case RayTracingShaderGroupTypeNV::eGeneral : return "General";
-      case RayTracingShaderGroupTypeNV::eTrianglesHitGroup : return "TrianglesHitGroup";
-      case RayTracingShaderGroupTypeNV::eProceduralHitGroup : return "ProceduralHitGroup";
+      case RayTracingShaderGroupTypeKHR::eGeneral : return "General";
+      case RayTracingShaderGroupTypeKHR::eTrianglesHitGroup : return "TrianglesHitGroup";
+      case RayTracingShaderGroupTypeKHR::eProceduralHitGroup : return "ProceduralHitGroup";
       default: return "invalid";
     }
   }
@@ -6756,14 +6997,21 @@
     eErrorIncompatibleDisplayKHR = VK_ERROR_INCOMPATIBLE_DISPLAY_KHR,
     eErrorValidationFailedEXT = VK_ERROR_VALIDATION_FAILED_EXT,
     eErrorInvalidShaderNV = VK_ERROR_INVALID_SHADER_NV,
+    eErrorIncompatibleVersionKHR = VK_ERROR_INCOMPATIBLE_VERSION_KHR,
     eErrorInvalidDrmFormatModifierPlaneLayoutEXT = VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT,
     eErrorNotPermittedEXT = VK_ERROR_NOT_PERMITTED_EXT,
     eErrorFullScreenExclusiveModeLostEXT = VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT,
+    eThreadIdleKHR = VK_THREAD_IDLE_KHR,
+    eThreadDoneKHR = VK_THREAD_DONE_KHR,
+    eOperationDeferredKHR = VK_OPERATION_DEFERRED_KHR,
+    eOperationNotDeferredKHR = VK_OPERATION_NOT_DEFERRED_KHR,
+    ePipelineCompileRequiredEXT = VK_PIPELINE_COMPILE_REQUIRED_EXT,
     eErrorOutOfPoolMemoryKHR = VK_ERROR_OUT_OF_POOL_MEMORY_KHR,
     eErrorInvalidExternalHandleKHR = VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR,
     eErrorFragmentationEXT = VK_ERROR_FRAGMENTATION_EXT,
     eErrorInvalidDeviceAddressEXT = VK_ERROR_INVALID_DEVICE_ADDRESS_EXT,
-    eErrorInvalidOpaqueCaptureAddressKHR = VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS_KHR
+    eErrorInvalidOpaqueCaptureAddressKHR = VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS_KHR,
+    eErrorPipelineCompileRequiredEXT = VK_ERROR_PIPELINE_COMPILE_REQUIRED_EXT
   };
 
   VULKAN_HPP_INLINE std::string to_string( Result value )
@@ -6800,9 +7048,15 @@
       case Result::eErrorIncompatibleDisplayKHR : return "ErrorIncompatibleDisplayKHR";
       case Result::eErrorValidationFailedEXT : return "ErrorValidationFailedEXT";
       case Result::eErrorInvalidShaderNV : return "ErrorInvalidShaderNV";
+      case Result::eErrorIncompatibleVersionKHR : return "ErrorIncompatibleVersionKHR";
       case Result::eErrorInvalidDrmFormatModifierPlaneLayoutEXT : return "ErrorInvalidDrmFormatModifierPlaneLayoutEXT";
       case Result::eErrorNotPermittedEXT : return "ErrorNotPermittedEXT";
       case Result::eErrorFullScreenExclusiveModeLostEXT : return "ErrorFullScreenExclusiveModeLostEXT";
+      case Result::eThreadIdleKHR : return "ThreadIdleKHR";
+      case Result::eThreadDoneKHR : return "ThreadDoneKHR";
+      case Result::eOperationDeferredKHR : return "OperationDeferredKHR";
+      case Result::eOperationNotDeferredKHR : return "OperationNotDeferredKHR";
+      case Result::ePipelineCompileRequiredEXT : return "PipelineCompileRequiredEXT";
       default: return "invalid";
     }
   }
@@ -7085,14 +7339,20 @@
     eCompute = VK_SHADER_STAGE_COMPUTE_BIT,
     eAllGraphics = VK_SHADER_STAGE_ALL_GRAPHICS,
     eAll = VK_SHADER_STAGE_ALL,
+    eRaygenKHR = VK_SHADER_STAGE_RAYGEN_BIT_KHR,
+    eAnyHitKHR = VK_SHADER_STAGE_ANY_HIT_BIT_KHR,
+    eClosestHitKHR = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,
+    eMissKHR = VK_SHADER_STAGE_MISS_BIT_KHR,
+    eIntersectionKHR = VK_SHADER_STAGE_INTERSECTION_BIT_KHR,
+    eCallableKHR = VK_SHADER_STAGE_CALLABLE_BIT_KHR,
+    eTaskNV = VK_SHADER_STAGE_TASK_BIT_NV,
+    eMeshNV = VK_SHADER_STAGE_MESH_BIT_NV,
     eRaygenNV = VK_SHADER_STAGE_RAYGEN_BIT_NV,
     eAnyHitNV = VK_SHADER_STAGE_ANY_HIT_BIT_NV,
     eClosestHitNV = VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV,
     eMissNV = VK_SHADER_STAGE_MISS_BIT_NV,
     eIntersectionNV = VK_SHADER_STAGE_INTERSECTION_BIT_NV,
-    eCallableNV = VK_SHADER_STAGE_CALLABLE_BIT_NV,
-    eTaskNV = VK_SHADER_STAGE_TASK_BIT_NV,
-    eMeshNV = VK_SHADER_STAGE_MESH_BIT_NV
+    eCallableNV = VK_SHADER_STAGE_CALLABLE_BIT_NV
   };
 
   VULKAN_HPP_INLINE std::string to_string( ShaderStageFlagBits value )
@@ -7107,12 +7367,12 @@
       case ShaderStageFlagBits::eCompute : return "Compute";
       case ShaderStageFlagBits::eAllGraphics : return "AllGraphics";
       case ShaderStageFlagBits::eAll : return "All";
-      case ShaderStageFlagBits::eRaygenNV : return "RaygenNV";
-      case ShaderStageFlagBits::eAnyHitNV : return "AnyHitNV";
-      case ShaderStageFlagBits::eClosestHitNV : return "ClosestHitNV";
-      case ShaderStageFlagBits::eMissNV : return "MissNV";
-      case ShaderStageFlagBits::eIntersectionNV : return "IntersectionNV";
-      case ShaderStageFlagBits::eCallableNV : return "CallableNV";
+      case ShaderStageFlagBits::eRaygenKHR : return "RaygenKHR";
+      case ShaderStageFlagBits::eAnyHitKHR : return "AnyHitKHR";
+      case ShaderStageFlagBits::eClosestHitKHR : return "ClosestHitKHR";
+      case ShaderStageFlagBits::eMissKHR : return "MissKHR";
+      case ShaderStageFlagBits::eIntersectionKHR : return "IntersectionKHR";
+      case ShaderStageFlagBits::eCallableKHR : return "CallableKHR";
       case ShaderStageFlagBits::eTaskNV : return "TaskNV";
       case ShaderStageFlagBits::eMeshNV : return "MeshNV";
       default: return "invalid";
@@ -7444,6 +7704,7 @@
     ePhysicalDeviceTransformFeedbackPropertiesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT,
     ePipelineRasterizationStateStreamCreateInfoEXT = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT,
     eImageViewHandleInfoNVX = VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX,
+    eImageViewAddressPropertiesNVX = VK_STRUCTURE_TYPE_IMAGE_VIEW_ADDRESS_PROPERTIES_NVX,
     eTextureLodGatherFormatPropertiesAMD = VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD,
     eStreamDescriptorSurfaceCreateInfoGGP = VK_STRUCTURE_TYPE_STREAM_DESCRIPTOR_SURFACE_CREATE_INFO_GGP,
     ePhysicalDeviceCornerSampledImageFeaturesNV = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CORNER_SAMPLED_IMAGE_FEATURES_NV,
@@ -7476,12 +7737,6 @@
     ePhysicalDeviceConditionalRenderingFeaturesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT,
     eConditionalRenderingBeginInfoEXT = VK_STRUCTURE_TYPE_CONDITIONAL_RENDERING_BEGIN_INFO_EXT,
     ePresentRegionsKHR = VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR,
-    eObjectTableCreateInfoNVX = VK_STRUCTURE_TYPE_OBJECT_TABLE_CREATE_INFO_NVX,
-    eIndirectCommandsLayoutCreateInfoNVX = VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NVX,
-    eCmdProcessCommandsInfoNVX = VK_STRUCTURE_TYPE_CMD_PROCESS_COMMANDS_INFO_NVX,
-    eCmdReserveSpaceForCommandsInfoNVX = VK_STRUCTURE_TYPE_CMD_RESERVE_SPACE_FOR_COMMANDS_INFO_NVX,
-    eDeviceGeneratedCommandsLimitsNVX = VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_LIMITS_NVX,
-    eDeviceGeneratedCommandsFeaturesNVX = VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_FEATURES_NVX,
     ePipelineViewportWScalingStateCreateInfoNV = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_W_SCALING_STATE_CREATE_INFO_NV,
     eSurfaceCapabilities2EXT = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT,
     eDisplayPowerInfoEXT = VK_STRUCTURE_TYPE_DISPLAY_POWER_INFO_EXT,
@@ -7545,6 +7800,26 @@
     ePhysicalDeviceBlendOperationAdvancedPropertiesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT,
     ePipelineColorBlendAdvancedStateCreateInfoEXT = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT,
     ePipelineCoverageToColorStateCreateInfoNV = VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_TO_COLOR_STATE_CREATE_INFO_NV,
+    eBindAccelerationStructureMemoryInfoKHR = VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_KHR,
+    eWriteDescriptorSetAccelerationStructureKHR = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR,
+    eAccelerationStructureBuildGeometryInfoKHR = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR,
+    eAccelerationStructureCreateGeometryTypeInfoKHR = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR,
+    eAccelerationStructureDeviceAddressInfoKHR = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR,
+    eAccelerationStructureGeometryAabbsDataKHR = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR,
+    eAccelerationStructureGeometryInstancesDataKHR = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR,
+    eAccelerationStructureGeometryTrianglesDataKHR = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR,
+    eAccelerationStructureGeometryKHR = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR,
+    eAccelerationStructureMemoryRequirementsInfoKHR = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR,
+    eAccelerationStructureVersionKHR = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_VERSION_KHR,
+    eCopyAccelerationStructureInfoKHR = VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR,
+    eCopyAccelerationStructureToMemoryInfoKHR = VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_TO_MEMORY_INFO_KHR,
+    eCopyMemoryToAccelerationStructureInfoKHR = VK_STRUCTURE_TYPE_COPY_MEMORY_TO_ACCELERATION_STRUCTURE_INFO_KHR,
+    ePhysicalDeviceRayTracingFeaturesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_FEATURES_KHR,
+    ePhysicalDeviceRayTracingPropertiesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_KHR,
+    eRayTracingPipelineCreateInfoKHR = VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR,
+    eRayTracingShaderGroupCreateInfoKHR = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR,
+    eAccelerationStructureCreateInfoKHR = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR,
+    eRayTracingPipelineInterfaceCreateInfoKHR = VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_INTERFACE_CREATE_INFO_KHR,
     ePipelineCoverageModulationStateCreateInfoNV = VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_MODULATION_STATE_CREATE_INFO_NV,
     ePhysicalDeviceShaderSmBuiltinsFeaturesNV = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_FEATURES_NV,
     ePhysicalDeviceShaderSmBuiltinsPropertiesNV = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_PROPERTIES_NV,
@@ -7565,8 +7840,6 @@
     eGeometryNV = VK_STRUCTURE_TYPE_GEOMETRY_NV,
     eGeometryTrianglesNV = VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV,
     eGeometryAabbNV = VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV,
-    eBindAccelerationStructureMemoryInfoNV = VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV,
-    eWriteDescriptorSetAccelerationStructureNV = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_NV,
     eAccelerationStructureMemoryRequirementsInfoNV = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV,
     ePhysicalDeviceRayTracingPropertiesNV = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_NV,
     eRayTracingShaderGroupCreateInfoNV = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV,
@@ -7599,7 +7872,7 @@
     eCheckpointDataNV = VK_STRUCTURE_TYPE_CHECKPOINT_DATA_NV,
     eQueueFamilyCheckpointPropertiesNV = VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_NV,
     ePhysicalDeviceShaderIntegerFunctions2FeaturesINTEL = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_FUNCTIONS_2_FEATURES_INTEL,
-    eQueryPoolCreateInfoINTEL = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO_INTEL,
+    eQueryPoolPerformanceQueryCreateInfoINTEL = VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_QUERY_CREATE_INFO_INTEL,
     eInitializePerformanceApiInfoINTEL = VK_STRUCTURE_TYPE_INITIALIZE_PERFORMANCE_API_INFO_INTEL,
     ePerformanceMarkerInfoINTEL = VK_STRUCTURE_TYPE_PERFORMANCE_MARKER_INFO_INTEL,
     ePerformanceStreamMarkerInfoINTEL = VK_STRUCTURE_TYPE_PERFORMANCE_STREAM_MARKER_INFO_INTEL,
@@ -7643,6 +7916,7 @@
     ePipelineRasterizationLineStateCreateInfoEXT = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT,
     ePhysicalDeviceLineRasterizationPropertiesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES_EXT,
     ePhysicalDeviceIndexTypeUint8FeaturesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT,
+    eDeferredOperationInfoKHR = VK_STRUCTURE_TYPE_DEFERRED_OPERATION_INFO_KHR,
     ePhysicalDevicePipelineExecutablePropertiesFeaturesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR,
     ePipelineInfoKHR = VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR,
     ePipelineExecutablePropertiesKHR = VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_PROPERTIES_KHR,
@@ -7650,10 +7924,22 @@
     ePipelineExecutableStatisticKHR = VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_STATISTIC_KHR,
     ePipelineExecutableInternalRepresentationKHR = VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INTERNAL_REPRESENTATION_KHR,
     ePhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT,
+    ePhysicalDeviceDeviceGeneratedCommandsPropertiesNV = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_PROPERTIES_NV,
+    eGraphicsShaderGroupCreateInfoNV = VK_STRUCTURE_TYPE_GRAPHICS_SHADER_GROUP_CREATE_INFO_NV,
+    eGraphicsPipelineShaderGroupsCreateInfoNV = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_SHADER_GROUPS_CREATE_INFO_NV,
+    eIndirectCommandsLayoutTokenNV = VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_TOKEN_NV,
+    eIndirectCommandsLayoutCreateInfoNV = VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NV,
+    eGeneratedCommandsInfoNV = VK_STRUCTURE_TYPE_GENERATED_COMMANDS_INFO_NV,
+    eGeneratedCommandsMemoryRequirementsInfoNV = VK_STRUCTURE_TYPE_GENERATED_COMMANDS_MEMORY_REQUIREMENTS_INFO_NV,
+    ePhysicalDeviceDeviceGeneratedCommandsFeaturesNV = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_FEATURES_NV,
     ePhysicalDeviceTexelBufferAlignmentFeaturesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_FEATURES_EXT,
     ePhysicalDeviceTexelBufferAlignmentPropertiesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT,
     eCommandBufferInheritanceRenderPassTransformInfoQCOM = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDER_PASS_TRANSFORM_INFO_QCOM,
     eRenderPassTransformBeginInfoQCOM = VK_STRUCTURE_TYPE_RENDER_PASS_TRANSFORM_BEGIN_INFO_QCOM,
+    ePipelineLibraryCreateInfoKHR = VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR,
+    ePhysicalDevicePipelineCreationCacheControlFeaturesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES_EXT,
+    ePhysicalDeviceDiagnosticsConfigFeaturesNV = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DIAGNOSTICS_CONFIG_FEATURES_NV,
+    eDeviceDiagnosticsConfigCreateInfoNV = VK_STRUCTURE_TYPE_DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV,
     ePhysicalDeviceVariablePointerFeatures = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES,
     ePhysicalDeviceShaderDrawParameterFeatures = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES,
     eDebugReportCreateInfoEXT = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT,
@@ -7736,6 +8022,8 @@
     ePhysicalDeviceDescriptorIndexingPropertiesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES_EXT,
     eDescriptorSetVariableDescriptorCountAllocateInfoEXT = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO_EXT,
     eDescriptorSetVariableDescriptorCountLayoutSupportEXT = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT_EXT,
+    eBindAccelerationStructureMemoryInfoNV = VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV,
+    eWriteDescriptorSetAccelerationStructureNV = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_NV,
     ePhysicalDeviceMaintenance3PropertiesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES_KHR,
     eDescriptorSetLayoutSupportKHR = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT_KHR,
     ePhysicalDeviceShaderSubgroupExtendedTypesFeaturesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES_KHR,
@@ -7751,6 +8039,7 @@
     eTimelineSemaphoreSubmitInfoKHR = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO_KHR,
     eSemaphoreWaitInfoKHR = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO_KHR,
     eSemaphoreSignalInfoKHR = VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO_KHR,
+    eQueryPoolCreateInfoINTEL = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO_INTEL,
     ePhysicalDeviceVulkanMemoryModelFeaturesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR,
     ePhysicalDeviceScalarBlockLayoutFeaturesEXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT,
     ePhysicalDeviceSeparateDepthStencilLayoutsFeaturesKHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES_KHR,
@@ -7964,6 +8253,7 @@
       case StructureType::ePhysicalDeviceTransformFeedbackPropertiesEXT : return "PhysicalDeviceTransformFeedbackPropertiesEXT";
       case StructureType::ePipelineRasterizationStateStreamCreateInfoEXT : return "PipelineRasterizationStateStreamCreateInfoEXT";
       case StructureType::eImageViewHandleInfoNVX : return "ImageViewHandleInfoNVX";
+      case StructureType::eImageViewAddressPropertiesNVX : return "ImageViewAddressPropertiesNVX";
       case StructureType::eTextureLodGatherFormatPropertiesAMD : return "TextureLodGatherFormatPropertiesAMD";
       case StructureType::eStreamDescriptorSurfaceCreateInfoGGP : return "StreamDescriptorSurfaceCreateInfoGGP";
       case StructureType::ePhysicalDeviceCornerSampledImageFeaturesNV : return "PhysicalDeviceCornerSampledImageFeaturesNV";
@@ -7996,12 +8286,6 @@
       case StructureType::ePhysicalDeviceConditionalRenderingFeaturesEXT : return "PhysicalDeviceConditionalRenderingFeaturesEXT";
       case StructureType::eConditionalRenderingBeginInfoEXT : return "ConditionalRenderingBeginInfoEXT";
       case StructureType::ePresentRegionsKHR : return "PresentRegionsKHR";
-      case StructureType::eObjectTableCreateInfoNVX : return "ObjectTableCreateInfoNVX";
-      case StructureType::eIndirectCommandsLayoutCreateInfoNVX : return "IndirectCommandsLayoutCreateInfoNVX";
-      case StructureType::eCmdProcessCommandsInfoNVX : return "CmdProcessCommandsInfoNVX";
-      case StructureType::eCmdReserveSpaceForCommandsInfoNVX : return "CmdReserveSpaceForCommandsInfoNVX";
-      case StructureType::eDeviceGeneratedCommandsLimitsNVX : return "DeviceGeneratedCommandsLimitsNVX";
-      case StructureType::eDeviceGeneratedCommandsFeaturesNVX : return "DeviceGeneratedCommandsFeaturesNVX";
       case StructureType::ePipelineViewportWScalingStateCreateInfoNV : return "PipelineViewportWScalingStateCreateInfoNV";
       case StructureType::eSurfaceCapabilities2EXT : return "SurfaceCapabilities2EXT";
       case StructureType::eDisplayPowerInfoEXT : return "DisplayPowerInfoEXT";
@@ -8065,6 +8349,26 @@
       case StructureType::ePhysicalDeviceBlendOperationAdvancedPropertiesEXT : return "PhysicalDeviceBlendOperationAdvancedPropertiesEXT";
       case StructureType::ePipelineColorBlendAdvancedStateCreateInfoEXT : return "PipelineColorBlendAdvancedStateCreateInfoEXT";
       case StructureType::ePipelineCoverageToColorStateCreateInfoNV : return "PipelineCoverageToColorStateCreateInfoNV";
+      case StructureType::eBindAccelerationStructureMemoryInfoKHR : return "BindAccelerationStructureMemoryInfoKHR";
+      case StructureType::eWriteDescriptorSetAccelerationStructureKHR : return "WriteDescriptorSetAccelerationStructureKHR";
+      case StructureType::eAccelerationStructureBuildGeometryInfoKHR : return "AccelerationStructureBuildGeometryInfoKHR";
+      case StructureType::eAccelerationStructureCreateGeometryTypeInfoKHR : return "AccelerationStructureCreateGeometryTypeInfoKHR";
+      case StructureType::eAccelerationStructureDeviceAddressInfoKHR : return "AccelerationStructureDeviceAddressInfoKHR";
+      case StructureType::eAccelerationStructureGeometryAabbsDataKHR : return "AccelerationStructureGeometryAabbsDataKHR";
+      case StructureType::eAccelerationStructureGeometryInstancesDataKHR : return "AccelerationStructureGeometryInstancesDataKHR";
+      case StructureType::eAccelerationStructureGeometryTrianglesDataKHR : return "AccelerationStructureGeometryTrianglesDataKHR";
+      case StructureType::eAccelerationStructureGeometryKHR : return "AccelerationStructureGeometryKHR";
+      case StructureType::eAccelerationStructureMemoryRequirementsInfoKHR : return "AccelerationStructureMemoryRequirementsInfoKHR";
+      case StructureType::eAccelerationStructureVersionKHR : return "AccelerationStructureVersionKHR";
+      case StructureType::eCopyAccelerationStructureInfoKHR : return "CopyAccelerationStructureInfoKHR";
+      case StructureType::eCopyAccelerationStructureToMemoryInfoKHR : return "CopyAccelerationStructureToMemoryInfoKHR";
+      case StructureType::eCopyMemoryToAccelerationStructureInfoKHR : return "CopyMemoryToAccelerationStructureInfoKHR";
+      case StructureType::ePhysicalDeviceRayTracingFeaturesKHR : return "PhysicalDeviceRayTracingFeaturesKHR";
+      case StructureType::ePhysicalDeviceRayTracingPropertiesKHR : return "PhysicalDeviceRayTracingPropertiesKHR";
+      case StructureType::eRayTracingPipelineCreateInfoKHR : return "RayTracingPipelineCreateInfoKHR";
+      case StructureType::eRayTracingShaderGroupCreateInfoKHR : return "RayTracingShaderGroupCreateInfoKHR";
+      case StructureType::eAccelerationStructureCreateInfoKHR : return "AccelerationStructureCreateInfoKHR";
+      case StructureType::eRayTracingPipelineInterfaceCreateInfoKHR : return "RayTracingPipelineInterfaceCreateInfoKHR";
       case StructureType::ePipelineCoverageModulationStateCreateInfoNV : return "PipelineCoverageModulationStateCreateInfoNV";
       case StructureType::ePhysicalDeviceShaderSmBuiltinsFeaturesNV : return "PhysicalDeviceShaderSmBuiltinsFeaturesNV";
       case StructureType::ePhysicalDeviceShaderSmBuiltinsPropertiesNV : return "PhysicalDeviceShaderSmBuiltinsPropertiesNV";
@@ -8085,8 +8389,6 @@
       case StructureType::eGeometryNV : return "GeometryNV";
       case StructureType::eGeometryTrianglesNV : return "GeometryTrianglesNV";
       case StructureType::eGeometryAabbNV : return "GeometryAabbNV";
-      case StructureType::eBindAccelerationStructureMemoryInfoNV : return "BindAccelerationStructureMemoryInfoNV";
-      case StructureType::eWriteDescriptorSetAccelerationStructureNV : return "WriteDescriptorSetAccelerationStructureNV";
       case StructureType::eAccelerationStructureMemoryRequirementsInfoNV : return "AccelerationStructureMemoryRequirementsInfoNV";
       case StructureType::ePhysicalDeviceRayTracingPropertiesNV : return "PhysicalDeviceRayTracingPropertiesNV";
       case StructureType::eRayTracingShaderGroupCreateInfoNV : return "RayTracingShaderGroupCreateInfoNV";
@@ -8119,7 +8421,7 @@
       case StructureType::eCheckpointDataNV : return "CheckpointDataNV";
       case StructureType::eQueueFamilyCheckpointPropertiesNV : return "QueueFamilyCheckpointPropertiesNV";
       case StructureType::ePhysicalDeviceShaderIntegerFunctions2FeaturesINTEL : return "PhysicalDeviceShaderIntegerFunctions2FeaturesINTEL";
-      case StructureType::eQueryPoolCreateInfoINTEL : return "QueryPoolCreateInfoINTEL";
+      case StructureType::eQueryPoolPerformanceQueryCreateInfoINTEL : return "QueryPoolPerformanceQueryCreateInfoINTEL";
       case StructureType::eInitializePerformanceApiInfoINTEL : return "InitializePerformanceApiInfoINTEL";
       case StructureType::ePerformanceMarkerInfoINTEL : return "PerformanceMarkerInfoINTEL";
       case StructureType::ePerformanceStreamMarkerInfoINTEL : return "PerformanceStreamMarkerInfoINTEL";
@@ -8163,6 +8465,7 @@
       case StructureType::ePipelineRasterizationLineStateCreateInfoEXT : return "PipelineRasterizationLineStateCreateInfoEXT";
       case StructureType::ePhysicalDeviceLineRasterizationPropertiesEXT : return "PhysicalDeviceLineRasterizationPropertiesEXT";
       case StructureType::ePhysicalDeviceIndexTypeUint8FeaturesEXT : return "PhysicalDeviceIndexTypeUint8FeaturesEXT";
+      case StructureType::eDeferredOperationInfoKHR : return "DeferredOperationInfoKHR";
       case StructureType::ePhysicalDevicePipelineExecutablePropertiesFeaturesKHR : return "PhysicalDevicePipelineExecutablePropertiesFeaturesKHR";
       case StructureType::ePipelineInfoKHR : return "PipelineInfoKHR";
       case StructureType::ePipelineExecutablePropertiesKHR : return "PipelineExecutablePropertiesKHR";
@@ -8170,10 +8473,22 @@
       case StructureType::ePipelineExecutableStatisticKHR : return "PipelineExecutableStatisticKHR";
       case StructureType::ePipelineExecutableInternalRepresentationKHR : return "PipelineExecutableInternalRepresentationKHR";
       case StructureType::ePhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT : return "PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT";
+      case StructureType::ePhysicalDeviceDeviceGeneratedCommandsPropertiesNV : return "PhysicalDeviceDeviceGeneratedCommandsPropertiesNV";
+      case StructureType::eGraphicsShaderGroupCreateInfoNV : return "GraphicsShaderGroupCreateInfoNV";
+      case StructureType::eGraphicsPipelineShaderGroupsCreateInfoNV : return "GraphicsPipelineShaderGroupsCreateInfoNV";
+      case StructureType::eIndirectCommandsLayoutTokenNV : return "IndirectCommandsLayoutTokenNV";
+      case StructureType::eIndirectCommandsLayoutCreateInfoNV : return "IndirectCommandsLayoutCreateInfoNV";
+      case StructureType::eGeneratedCommandsInfoNV : return "GeneratedCommandsInfoNV";
+      case StructureType::eGeneratedCommandsMemoryRequirementsInfoNV : return "GeneratedCommandsMemoryRequirementsInfoNV";
+      case StructureType::ePhysicalDeviceDeviceGeneratedCommandsFeaturesNV : return "PhysicalDeviceDeviceGeneratedCommandsFeaturesNV";
       case StructureType::ePhysicalDeviceTexelBufferAlignmentFeaturesEXT : return "PhysicalDeviceTexelBufferAlignmentFeaturesEXT";
       case StructureType::ePhysicalDeviceTexelBufferAlignmentPropertiesEXT : return "PhysicalDeviceTexelBufferAlignmentPropertiesEXT";
       case StructureType::eCommandBufferInheritanceRenderPassTransformInfoQCOM : return "CommandBufferInheritanceRenderPassTransformInfoQCOM";
       case StructureType::eRenderPassTransformBeginInfoQCOM : return "RenderPassTransformBeginInfoQCOM";
+      case StructureType::ePipelineLibraryCreateInfoKHR : return "PipelineLibraryCreateInfoKHR";
+      case StructureType::ePhysicalDevicePipelineCreationCacheControlFeaturesEXT : return "PhysicalDevicePipelineCreationCacheControlFeaturesEXT";
+      case StructureType::ePhysicalDeviceDiagnosticsConfigFeaturesNV : return "PhysicalDeviceDiagnosticsConfigFeaturesNV";
+      case StructureType::eDeviceDiagnosticsConfigCreateInfoNV : return "DeviceDiagnosticsConfigCreateInfoNV";
       default: return "invalid";
     }
   }
@@ -8447,7 +8762,8 @@
   {
     eGpuAssisted = VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT,
     eGpuAssistedReserveBindingSlot = VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT,
-    eBestPractices = VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT
+    eBestPractices = VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT,
+    eDebugPrintf = VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT
   };
 
   VULKAN_HPP_INLINE std::string to_string( ValidationFeatureEnableEXT value )
@@ -8457,6 +8773,7 @@
       case ValidationFeatureEnableEXT::eGpuAssisted : return "GpuAssisted";
       case ValidationFeatureEnableEXT::eGpuAssistedReserveBindingSlot : return "GpuAssistedReserveBindingSlot";
       case ValidationFeatureEnableEXT::eBestPractices : return "BestPractices";
+      case ValidationFeatureEnableEXT::eDebugPrintf : return "DebugPrintf";
       default: return "invalid";
     }
   }
@@ -8536,7 +8853,7 @@
   {
     enum : VkFlags
     {
-      allFlags = VkFlags(AccessFlagBits::eIndirectCommandRead) | VkFlags(AccessFlagBits::eIndexRead) | VkFlags(AccessFlagBits::eVertexAttributeRead) | VkFlags(AccessFlagBits::eUniformRead) | VkFlags(AccessFlagBits::eInputAttachmentRead) | VkFlags(AccessFlagBits::eShaderRead) | VkFlags(AccessFlagBits::eShaderWrite) | VkFlags(AccessFlagBits::eColorAttachmentRead) | VkFlags(AccessFlagBits::eColorAttachmentWrite) | VkFlags(AccessFlagBits::eDepthStencilAttachmentRead) | VkFlags(AccessFlagBits::eDepthStencilAttachmentWrite) | VkFlags(AccessFlagBits::eTransferRead) | VkFlags(AccessFlagBits::eTransferWrite) | VkFlags(AccessFlagBits::eHostRead) | VkFlags(AccessFlagBits::eHostWrite) | VkFlags(AccessFlagBits::eMemoryRead) | VkFlags(AccessFlagBits::eMemoryWrite) | VkFlags(AccessFlagBits::eTransformFeedbackWriteEXT) | VkFlags(AccessFlagBits::eTransformFeedbackCounterReadEXT) | VkFlags(AccessFlagBits::eTransformFeedbackCounterWriteEXT) | VkFlags(AccessFlagBits::eConditionalRenderingReadEXT) | VkFlags(AccessFlagBits::eCommandProcessReadNVX) | VkFlags(AccessFlagBits::eCommandProcessWriteNVX) | VkFlags(AccessFlagBits::eColorAttachmentReadNoncoherentEXT) | VkFlags(AccessFlagBits::eShadingRateImageReadNV) | VkFlags(AccessFlagBits::eAccelerationStructureReadNV) | VkFlags(AccessFlagBits::eAccelerationStructureWriteNV) | VkFlags(AccessFlagBits::eFragmentDensityMapReadEXT)
+      allFlags = VkFlags(AccessFlagBits::eIndirectCommandRead) | VkFlags(AccessFlagBits::eIndexRead) | VkFlags(AccessFlagBits::eVertexAttributeRead) | VkFlags(AccessFlagBits::eUniformRead) | VkFlags(AccessFlagBits::eInputAttachmentRead) | VkFlags(AccessFlagBits::eShaderRead) | VkFlags(AccessFlagBits::eShaderWrite) | VkFlags(AccessFlagBits::eColorAttachmentRead) | VkFlags(AccessFlagBits::eColorAttachmentWrite) | VkFlags(AccessFlagBits::eDepthStencilAttachmentRead) | VkFlags(AccessFlagBits::eDepthStencilAttachmentWrite) | VkFlags(AccessFlagBits::eTransferRead) | VkFlags(AccessFlagBits::eTransferWrite) | VkFlags(AccessFlagBits::eHostRead) | VkFlags(AccessFlagBits::eHostWrite) | VkFlags(AccessFlagBits::eMemoryRead) | VkFlags(AccessFlagBits::eMemoryWrite) | VkFlags(AccessFlagBits::eTransformFeedbackWriteEXT) | VkFlags(AccessFlagBits::eTransformFeedbackCounterReadEXT) | VkFlags(AccessFlagBits::eTransformFeedbackCounterWriteEXT) | VkFlags(AccessFlagBits::eConditionalRenderingReadEXT) | VkFlags(AccessFlagBits::eColorAttachmentReadNoncoherentEXT) | VkFlags(AccessFlagBits::eAccelerationStructureReadKHR) | VkFlags(AccessFlagBits::eAccelerationStructureWriteKHR) | VkFlags(AccessFlagBits::eShadingRateImageReadNV) | VkFlags(AccessFlagBits::eFragmentDensityMapReadEXT) | VkFlags(AccessFlagBits::eCommandPreprocessReadNV) | VkFlags(AccessFlagBits::eCommandPreprocessWriteNV)
     };
   };
 
@@ -8586,13 +8903,13 @@
     if ( value & AccessFlagBits::eTransformFeedbackCounterReadEXT ) result += "TransformFeedbackCounterReadEXT | ";
     if ( value & AccessFlagBits::eTransformFeedbackCounterWriteEXT ) result += "TransformFeedbackCounterWriteEXT | ";
     if ( value & AccessFlagBits::eConditionalRenderingReadEXT ) result += "ConditionalRenderingReadEXT | ";
-    if ( value & AccessFlagBits::eCommandProcessReadNVX ) result += "CommandProcessReadNVX | ";
-    if ( value & AccessFlagBits::eCommandProcessWriteNVX ) result += "CommandProcessWriteNVX | ";
     if ( value & AccessFlagBits::eColorAttachmentReadNoncoherentEXT ) result += "ColorAttachmentReadNoncoherentEXT | ";
+    if ( value & AccessFlagBits::eAccelerationStructureReadKHR ) result += "AccelerationStructureReadKHR | ";
+    if ( value & AccessFlagBits::eAccelerationStructureWriteKHR ) result += "AccelerationStructureWriteKHR | ";
     if ( value & AccessFlagBits::eShadingRateImageReadNV ) result += "ShadingRateImageReadNV | ";
-    if ( value & AccessFlagBits::eAccelerationStructureReadNV ) result += "AccelerationStructureReadNV | ";
-    if ( value & AccessFlagBits::eAccelerationStructureWriteNV ) result += "AccelerationStructureWriteNV | ";
     if ( value & AccessFlagBits::eFragmentDensityMapReadEXT ) result += "FragmentDensityMapReadEXT | ";
+    if ( value & AccessFlagBits::eCommandPreprocessReadNV ) result += "CommandPreprocessReadNV | ";
+    if ( value & AccessFlagBits::eCommandPreprocessWriteNV ) result += "CommandPreprocessWriteNV | ";
     return "{ " + result.substr(0, result.size() - 3) + " }";
   }
 
@@ -8708,7 +9025,7 @@
   {
     enum : VkFlags
     {
-      allFlags = VkFlags(BufferUsageFlagBits::eTransferSrc) | VkFlags(BufferUsageFlagBits::eTransferDst) | VkFlags(BufferUsageFlagBits::eUniformTexelBuffer) | VkFlags(BufferUsageFlagBits::eStorageTexelBuffer) | VkFlags(BufferUsageFlagBits::eUniformBuffer) | VkFlags(BufferUsageFlagBits::eStorageBuffer) | VkFlags(BufferUsageFlagBits::eIndexBuffer) | VkFlags(BufferUsageFlagBits::eVertexBuffer) | VkFlags(BufferUsageFlagBits::eIndirectBuffer) | VkFlags(BufferUsageFlagBits::eShaderDeviceAddress) | VkFlags(BufferUsageFlagBits::eTransformFeedbackBufferEXT) | VkFlags(BufferUsageFlagBits::eTransformFeedbackCounterBufferEXT) | VkFlags(BufferUsageFlagBits::eConditionalRenderingEXT) | VkFlags(BufferUsageFlagBits::eRayTracingNV)
+      allFlags = VkFlags(BufferUsageFlagBits::eTransferSrc) | VkFlags(BufferUsageFlagBits::eTransferDst) | VkFlags(BufferUsageFlagBits::eUniformTexelBuffer) | VkFlags(BufferUsageFlagBits::eStorageTexelBuffer) | VkFlags(BufferUsageFlagBits::eUniformBuffer) | VkFlags(BufferUsageFlagBits::eStorageBuffer) | VkFlags(BufferUsageFlagBits::eIndexBuffer) | VkFlags(BufferUsageFlagBits::eVertexBuffer) | VkFlags(BufferUsageFlagBits::eIndirectBuffer) | VkFlags(BufferUsageFlagBits::eShaderDeviceAddress) | VkFlags(BufferUsageFlagBits::eTransformFeedbackBufferEXT) | VkFlags(BufferUsageFlagBits::eTransformFeedbackCounterBufferEXT) | VkFlags(BufferUsageFlagBits::eConditionalRenderingEXT) | VkFlags(BufferUsageFlagBits::eRayTracingKHR)
     };
   };
 
@@ -8750,7 +9067,7 @@
     if ( value & BufferUsageFlagBits::eTransformFeedbackBufferEXT ) result += "TransformFeedbackBufferEXT | ";
     if ( value & BufferUsageFlagBits::eTransformFeedbackCounterBufferEXT ) result += "TransformFeedbackCounterBufferEXT | ";
     if ( value & BufferUsageFlagBits::eConditionalRenderingEXT ) result += "ConditionalRenderingEXT | ";
-    if ( value & BufferUsageFlagBits::eRayTracingNV ) result += "RayTracingNV | ";
+    if ( value & BufferUsageFlagBits::eRayTracingKHR ) result += "RayTracingKHR | ";
     return "{ " + result.substr(0, result.size() - 3) + " }";
   }
 
@@ -8761,46 +9078,48 @@
     return "{}";
   }
 
-  using BuildAccelerationStructureFlagsNV = Flags<BuildAccelerationStructureFlagBitsNV>;
+  using BuildAccelerationStructureFlagsKHR = Flags<BuildAccelerationStructureFlagBitsKHR>;
 
-  template <> struct FlagTraits<BuildAccelerationStructureFlagBitsNV>
+  template <> struct FlagTraits<BuildAccelerationStructureFlagBitsKHR>
   {
     enum : VkFlags
     {
-      allFlags = VkFlags(BuildAccelerationStructureFlagBitsNV::eAllowUpdate) | VkFlags(BuildAccelerationStructureFlagBitsNV::eAllowCompaction) | VkFlags(BuildAccelerationStructureFlagBitsNV::ePreferFastTrace) | VkFlags(BuildAccelerationStructureFlagBitsNV::ePreferFastBuild) | VkFlags(BuildAccelerationStructureFlagBitsNV::eLowMemory)
+      allFlags = VkFlags(BuildAccelerationStructureFlagBitsKHR::eAllowUpdate) | VkFlags(BuildAccelerationStructureFlagBitsKHR::eAllowCompaction) | VkFlags(BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace) | VkFlags(BuildAccelerationStructureFlagBitsKHR::ePreferFastBuild) | VkFlags(BuildAccelerationStructureFlagBitsKHR::eLowMemory)
     };
   };
 
-  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR BuildAccelerationStructureFlagsNV operator|( BuildAccelerationStructureFlagBitsNV bit0, BuildAccelerationStructureFlagBitsNV bit1 ) VULKAN_HPP_NOEXCEPT
+  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR BuildAccelerationStructureFlagsKHR operator|( BuildAccelerationStructureFlagBitsKHR bit0, BuildAccelerationStructureFlagBitsKHR bit1 ) VULKAN_HPP_NOEXCEPT
   {
-    return BuildAccelerationStructureFlagsNV( bit0 ) | bit1;
+    return BuildAccelerationStructureFlagsKHR( bit0 ) | bit1;
   }
 
-  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR BuildAccelerationStructureFlagsNV operator&( BuildAccelerationStructureFlagBitsNV bit0, BuildAccelerationStructureFlagBitsNV bit1 ) VULKAN_HPP_NOEXCEPT
+  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR BuildAccelerationStructureFlagsKHR operator&( BuildAccelerationStructureFlagBitsKHR bit0, BuildAccelerationStructureFlagBitsKHR bit1 ) VULKAN_HPP_NOEXCEPT
   {
-    return BuildAccelerationStructureFlagsNV( bit0 ) & bit1;
+    return BuildAccelerationStructureFlagsKHR( bit0 ) & bit1;
   }
 
-  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR BuildAccelerationStructureFlagsNV operator^( BuildAccelerationStructureFlagBitsNV bit0, BuildAccelerationStructureFlagBitsNV bit1 ) VULKAN_HPP_NOEXCEPT
+  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR BuildAccelerationStructureFlagsKHR operator^( BuildAccelerationStructureFlagBitsKHR bit0, BuildAccelerationStructureFlagBitsKHR bit1 ) VULKAN_HPP_NOEXCEPT
   {
-    return BuildAccelerationStructureFlagsNV( bit0 ) ^ bit1;
+    return BuildAccelerationStructureFlagsKHR( bit0 ) ^ bit1;
   }
 
-  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR BuildAccelerationStructureFlagsNV operator~( BuildAccelerationStructureFlagBitsNV bits ) VULKAN_HPP_NOEXCEPT
+  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR BuildAccelerationStructureFlagsKHR operator~( BuildAccelerationStructureFlagBitsKHR bits ) VULKAN_HPP_NOEXCEPT
   {
-    return ~( BuildAccelerationStructureFlagsNV( bits ) );
+    return ~( BuildAccelerationStructureFlagsKHR( bits ) );
   }
 
-  VULKAN_HPP_INLINE std::string to_string( BuildAccelerationStructureFlagsNV value  )
+  using BuildAccelerationStructureFlagsNV = BuildAccelerationStructureFlagsKHR;
+
+  VULKAN_HPP_INLINE std::string to_string( BuildAccelerationStructureFlagsKHR value  )
   {
     if ( !value ) return "{}";
     std::string result;
 
-    if ( value & BuildAccelerationStructureFlagBitsNV::eAllowUpdate ) result += "AllowUpdate | ";
-    if ( value & BuildAccelerationStructureFlagBitsNV::eAllowCompaction ) result += "AllowCompaction | ";
-    if ( value & BuildAccelerationStructureFlagBitsNV::ePreferFastTrace ) result += "PreferFastTrace | ";
-    if ( value & BuildAccelerationStructureFlagBitsNV::ePreferFastBuild ) result += "PreferFastBuild | ";
-    if ( value & BuildAccelerationStructureFlagBitsNV::eLowMemory ) result += "LowMemory | ";
+    if ( value & BuildAccelerationStructureFlagBitsKHR::eAllowUpdate ) result += "AllowUpdate | ";
+    if ( value & BuildAccelerationStructureFlagBitsKHR::eAllowCompaction ) result += "AllowCompaction | ";
+    if ( value & BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace ) result += "PreferFastTrace | ";
+    if ( value & BuildAccelerationStructureFlagBitsKHR::ePreferFastBuild ) result += "PreferFastBuild | ";
+    if ( value & BuildAccelerationStructureFlagBitsKHR::eLowMemory ) result += "LowMemory | ";
     return "{ " + result.substr(0, result.size() - 3) + " }";
   }
 
@@ -9504,6 +9823,47 @@
     return "{}";
   }
 
+  using DeviceDiagnosticsConfigFlagsNV = Flags<DeviceDiagnosticsConfigFlagBitsNV>;
+
+  template <> struct FlagTraits<DeviceDiagnosticsConfigFlagBitsNV>
+  {
+    enum : VkFlags
+    {
+      allFlags = VkFlags(DeviceDiagnosticsConfigFlagBitsNV::eEnableShaderDebugInfo) | VkFlags(DeviceDiagnosticsConfigFlagBitsNV::eEnableResourceTracking) | VkFlags(DeviceDiagnosticsConfigFlagBitsNV::eEnableAutomaticCheckpoints)
+    };
+  };
+
+  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DeviceDiagnosticsConfigFlagsNV operator|( DeviceDiagnosticsConfigFlagBitsNV bit0, DeviceDiagnosticsConfigFlagBitsNV bit1 ) VULKAN_HPP_NOEXCEPT
+  {
+    return DeviceDiagnosticsConfigFlagsNV( bit0 ) | bit1;
+  }
+
+  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DeviceDiagnosticsConfigFlagsNV operator&( DeviceDiagnosticsConfigFlagBitsNV bit0, DeviceDiagnosticsConfigFlagBitsNV bit1 ) VULKAN_HPP_NOEXCEPT
+  {
+    return DeviceDiagnosticsConfigFlagsNV( bit0 ) & bit1;
+  }
+
+  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DeviceDiagnosticsConfigFlagsNV operator^( DeviceDiagnosticsConfigFlagBitsNV bit0, DeviceDiagnosticsConfigFlagBitsNV bit1 ) VULKAN_HPP_NOEXCEPT
+  {
+    return DeviceDiagnosticsConfigFlagsNV( bit0 ) ^ bit1;
+  }
+
+  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR DeviceDiagnosticsConfigFlagsNV operator~( DeviceDiagnosticsConfigFlagBitsNV bits ) VULKAN_HPP_NOEXCEPT
+  {
+    return ~( DeviceDiagnosticsConfigFlagsNV( bits ) );
+  }
+
+  VULKAN_HPP_INLINE std::string to_string( DeviceDiagnosticsConfigFlagsNV value  )
+  {
+    if ( !value ) return "{}";
+    std::string result;
+
+    if ( value & DeviceDiagnosticsConfigFlagBitsNV::eEnableShaderDebugInfo ) result += "EnableShaderDebugInfo | ";
+    if ( value & DeviceDiagnosticsConfigFlagBitsNV::eEnableResourceTracking ) result += "EnableResourceTracking | ";
+    if ( value & DeviceDiagnosticsConfigFlagBitsNV::eEnableAutomaticCheckpoints ) result += "EnableAutomaticCheckpoints | ";
+    return "{ " + result.substr(0, result.size() - 3) + " }";
+  }
+
   using DeviceGroupPresentModeFlagsKHR = Flags<DeviceGroupPresentModeFlagBitsKHR>;
 
   template <> struct FlagTraits<DeviceGroupPresentModeFlagBitsKHR>
@@ -10108,7 +10468,7 @@
   {
     enum : VkFlags
     {
-      allFlags = VkFlags(FormatFeatureFlagBits::eSampledImage) | VkFlags(FormatFeatureFlagBits::eStorageImage) | VkFlags(FormatFeatureFlagBits::eStorageImageAtomic) | VkFlags(FormatFeatureFlagBits::eUniformTexelBuffer) | VkFlags(FormatFeatureFlagBits::eStorageTexelBuffer) | VkFlags(FormatFeatureFlagBits::eStorageTexelBufferAtomic) | VkFlags(FormatFeatureFlagBits::eVertexBuffer) | VkFlags(FormatFeatureFlagBits::eColorAttachment) | VkFlags(FormatFeatureFlagBits::eColorAttachmentBlend) | VkFlags(FormatFeatureFlagBits::eDepthStencilAttachment) | VkFlags(FormatFeatureFlagBits::eBlitSrc) | VkFlags(FormatFeatureFlagBits::eBlitDst) | VkFlags(FormatFeatureFlagBits::eSampledImageFilterLinear) | VkFlags(FormatFeatureFlagBits::eTransferSrc) | VkFlags(FormatFeatureFlagBits::eTransferDst) | VkFlags(FormatFeatureFlagBits::eMidpointChromaSamples) | VkFlags(FormatFeatureFlagBits::eSampledImageYcbcrConversionLinearFilter) | VkFlags(FormatFeatureFlagBits::eSampledImageYcbcrConversionSeparateReconstructionFilter) | VkFlags(FormatFeatureFlagBits::eSampledImageYcbcrConversionChromaReconstructionExplicit) | VkFlags(FormatFeatureFlagBits::eSampledImageYcbcrConversionChromaReconstructionExplicitForceable) | VkFlags(FormatFeatureFlagBits::eDisjoint) | VkFlags(FormatFeatureFlagBits::eCositedChromaSamples) | VkFlags(FormatFeatureFlagBits::eSampledImageFilterMinmax) | VkFlags(FormatFeatureFlagBits::eSampledImageFilterCubicIMG) | VkFlags(FormatFeatureFlagBits::eFragmentDensityMapEXT)
+      allFlags = VkFlags(FormatFeatureFlagBits::eSampledImage) | VkFlags(FormatFeatureFlagBits::eStorageImage) | VkFlags(FormatFeatureFlagBits::eStorageImageAtomic) | VkFlags(FormatFeatureFlagBits::eUniformTexelBuffer) | VkFlags(FormatFeatureFlagBits::eStorageTexelBuffer) | VkFlags(FormatFeatureFlagBits::eStorageTexelBufferAtomic) | VkFlags(FormatFeatureFlagBits::eVertexBuffer) | VkFlags(FormatFeatureFlagBits::eColorAttachment) | VkFlags(FormatFeatureFlagBits::eColorAttachmentBlend) | VkFlags(FormatFeatureFlagBits::eDepthStencilAttachment) | VkFlags(FormatFeatureFlagBits::eBlitSrc) | VkFlags(FormatFeatureFlagBits::eBlitDst) | VkFlags(FormatFeatureFlagBits::eSampledImageFilterLinear) | VkFlags(FormatFeatureFlagBits::eTransferSrc) | VkFlags(FormatFeatureFlagBits::eTransferDst) | VkFlags(FormatFeatureFlagBits::eMidpointChromaSamples) | VkFlags(FormatFeatureFlagBits::eSampledImageYcbcrConversionLinearFilter) | VkFlags(FormatFeatureFlagBits::eSampledImageYcbcrConversionSeparateReconstructionFilter) | VkFlags(FormatFeatureFlagBits::eSampledImageYcbcrConversionChromaReconstructionExplicit) | VkFlags(FormatFeatureFlagBits::eSampledImageYcbcrConversionChromaReconstructionExplicitForceable) | VkFlags(FormatFeatureFlagBits::eDisjoint) | VkFlags(FormatFeatureFlagBits::eCositedChromaSamples) | VkFlags(FormatFeatureFlagBits::eSampledImageFilterMinmax) | VkFlags(FormatFeatureFlagBits::eSampledImageFilterCubicIMG) | VkFlags(FormatFeatureFlagBits::eAccelerationStructureVertexBufferKHR) | VkFlags(FormatFeatureFlagBits::eFragmentDensityMapEXT)
     };
   };
 
@@ -10161,6 +10521,7 @@
     if ( value & FormatFeatureFlagBits::eCositedChromaSamples ) result += "CositedChromaSamples | ";
     if ( value & FormatFeatureFlagBits::eSampledImageFilterMinmax ) result += "SampledImageFilterMinmax | ";
     if ( value & FormatFeatureFlagBits::eSampledImageFilterCubicIMG ) result += "SampledImageFilterCubicIMG | ";
+    if ( value & FormatFeatureFlagBits::eAccelerationStructureVertexBufferKHR ) result += "AccelerationStructureVertexBufferKHR | ";
     if ( value & FormatFeatureFlagBits::eFragmentDensityMapEXT ) result += "FragmentDensityMapEXT | ";
     return "{ " + result.substr(0, result.size() - 3) + " }";
   }
@@ -10204,85 +10565,89 @@
     return "{ " + result.substr(0, result.size() - 3) + " }";
   }
 
-  using GeometryFlagsNV = Flags<GeometryFlagBitsNV>;
+  using GeometryFlagsKHR = Flags<GeometryFlagBitsKHR>;
 
-  template <> struct FlagTraits<GeometryFlagBitsNV>
+  template <> struct FlagTraits<GeometryFlagBitsKHR>
   {
     enum : VkFlags
     {
-      allFlags = VkFlags(GeometryFlagBitsNV::eOpaque) | VkFlags(GeometryFlagBitsNV::eNoDuplicateAnyHitInvocation)
+      allFlags = VkFlags(GeometryFlagBitsKHR::eOpaque) | VkFlags(GeometryFlagBitsKHR::eNoDuplicateAnyHitInvocation)
     };
   };
 
-  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR GeometryFlagsNV operator|( GeometryFlagBitsNV bit0, GeometryFlagBitsNV bit1 ) VULKAN_HPP_NOEXCEPT
+  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR GeometryFlagsKHR operator|( GeometryFlagBitsKHR bit0, GeometryFlagBitsKHR bit1 ) VULKAN_HPP_NOEXCEPT
   {
-    return GeometryFlagsNV( bit0 ) | bit1;
+    return GeometryFlagsKHR( bit0 ) | bit1;
   }
 
-  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR GeometryFlagsNV operator&( GeometryFlagBitsNV bit0, GeometryFlagBitsNV bit1 ) VULKAN_HPP_NOEXCEPT
+  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR GeometryFlagsKHR operator&( GeometryFlagBitsKHR bit0, GeometryFlagBitsKHR bit1 ) VULKAN_HPP_NOEXCEPT
   {
-    return GeometryFlagsNV( bit0 ) & bit1;
+    return GeometryFlagsKHR( bit0 ) & bit1;
   }
 
-  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR GeometryFlagsNV operator^( GeometryFlagBitsNV bit0, GeometryFlagBitsNV bit1 ) VULKAN_HPP_NOEXCEPT
+  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR GeometryFlagsKHR operator^( GeometryFlagBitsKHR bit0, GeometryFlagBitsKHR bit1 ) VULKAN_HPP_NOEXCEPT
   {
-    return GeometryFlagsNV( bit0 ) ^ bit1;
+    return GeometryFlagsKHR( bit0 ) ^ bit1;
   }
 
-  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR GeometryFlagsNV operator~( GeometryFlagBitsNV bits ) VULKAN_HPP_NOEXCEPT
+  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR GeometryFlagsKHR operator~( GeometryFlagBitsKHR bits ) VULKAN_HPP_NOEXCEPT
   {
-    return ~( GeometryFlagsNV( bits ) );
+    return ~( GeometryFlagsKHR( bits ) );
   }
 
-  VULKAN_HPP_INLINE std::string to_string( GeometryFlagsNV value  )
+  using GeometryFlagsNV = GeometryFlagsKHR;
+
+  VULKAN_HPP_INLINE std::string to_string( GeometryFlagsKHR value  )
   {
     if ( !value ) return "{}";
     std::string result;
 
-    if ( value & GeometryFlagBitsNV::eOpaque ) result += "Opaque | ";
-    if ( value & GeometryFlagBitsNV::eNoDuplicateAnyHitInvocation ) result += "NoDuplicateAnyHitInvocation | ";
+    if ( value & GeometryFlagBitsKHR::eOpaque ) result += "Opaque | ";
+    if ( value & GeometryFlagBitsKHR::eNoDuplicateAnyHitInvocation ) result += "NoDuplicateAnyHitInvocation | ";
     return "{ " + result.substr(0, result.size() - 3) + " }";
   }
 
-  using GeometryInstanceFlagsNV = Flags<GeometryInstanceFlagBitsNV>;
+  using GeometryInstanceFlagsKHR = Flags<GeometryInstanceFlagBitsKHR>;
 
-  template <> struct FlagTraits<GeometryInstanceFlagBitsNV>
+  template <> struct FlagTraits<GeometryInstanceFlagBitsKHR>
   {
     enum : VkFlags
     {
-      allFlags = VkFlags(GeometryInstanceFlagBitsNV::eTriangleCullDisable) | VkFlags(GeometryInstanceFlagBitsNV::eTriangleFrontCounterclockwise) | VkFlags(GeometryInstanceFlagBitsNV::eForceOpaque) | VkFlags(GeometryInstanceFlagBitsNV::eForceNoOpaque)
+      allFlags = VkFlags(GeometryInstanceFlagBitsKHR::eTriangleFacingCullDisable) | VkFlags(GeometryInstanceFlagBitsKHR::eTriangleFrontCounterclockwise) | VkFlags(GeometryInstanceFlagBitsKHR::eForceOpaque) | VkFlags(GeometryInstanceFlagBitsKHR::eForceNoOpaque)
     };
   };
 
-  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR GeometryInstanceFlagsNV operator|( GeometryInstanceFlagBitsNV bit0, GeometryInstanceFlagBitsNV bit1 ) VULKAN_HPP_NOEXCEPT
+  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR GeometryInstanceFlagsKHR operator|( GeometryInstanceFlagBitsKHR bit0, GeometryInstanceFlagBitsKHR bit1 ) VULKAN_HPP_NOEXCEPT
   {
-    return GeometryInstanceFlagsNV( bit0 ) | bit1;
+    return GeometryInstanceFlagsKHR( bit0 ) | bit1;
   }
 
-  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR GeometryInstanceFlagsNV operator&( GeometryInstanceFlagBitsNV bit0, GeometryInstanceFlagBitsNV bit1 ) VULKAN_HPP_NOEXCEPT
+  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR GeometryInstanceFlagsKHR operator&( GeometryInstanceFlagBitsKHR bit0, GeometryInstanceFlagBitsKHR bit1 ) VULKAN_HPP_NOEXCEPT
   {
-    return GeometryInstanceFlagsNV( bit0 ) & bit1;
+    return GeometryInstanceFlagsKHR( bit0 ) & bit1;
   }
 
-  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR GeometryInstanceFlagsNV operator^( GeometryInstanceFlagBitsNV bit0, GeometryInstanceFlagBitsNV bit1 ) VULKAN_HPP_NOEXCEPT
+  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR GeometryInstanceFlagsKHR operator^( GeometryInstanceFlagBitsKHR bit0, GeometryInstanceFlagBitsKHR bit1 ) VULKAN_HPP_NOEXCEPT
   {
-    return GeometryInstanceFlagsNV( bit0 ) ^ bit1;
+    return GeometryInstanceFlagsKHR( bit0 ) ^ bit1;
   }
 
-  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR GeometryInstanceFlagsNV operator~( GeometryInstanceFlagBitsNV bits ) VULKAN_HPP_NOEXCEPT
+  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR GeometryInstanceFlagsKHR operator~( GeometryInstanceFlagBitsKHR bits ) VULKAN_HPP_NOEXCEPT
   {
-    return ~( GeometryInstanceFlagsNV( bits ) );
+    return ~( GeometryInstanceFlagsKHR( bits ) );
   }
 
-  VULKAN_HPP_INLINE std::string to_string( GeometryInstanceFlagsNV value  )
+  using GeometryInstanceFlagsNV = GeometryInstanceFlagsKHR;
+
+  VULKAN_HPP_INLINE std::string to_string( GeometryInstanceFlagsKHR value  )
   {
     if ( !value ) return "{}";
     std::string result;
 
-    if ( value & GeometryInstanceFlagBitsNV::eTriangleCullDisable ) result += "TriangleCullDisable | ";
-    if ( value & GeometryInstanceFlagBitsNV::eTriangleFrontCounterclockwise ) result += "TriangleFrontCounterclockwise | ";
-    if ( value & GeometryInstanceFlagBitsNV::eForceOpaque ) result += "ForceOpaque | ";
-    if ( value & GeometryInstanceFlagBitsNV::eForceNoOpaque ) result += "ForceNoOpaque | ";
+    if ( value & GeometryInstanceFlagBitsKHR::eTriangleFacingCullDisable ) result += "TriangleFacingCullDisable | ";
+    if ( value & GeometryInstanceFlagBitsKHR::eTriangleFrontCounterclockwise ) result += "TriangleFrontCounterclockwise | ";
+    if ( value & GeometryInstanceFlagBitsKHR::eForceOpaque ) result += "ForceOpaque | ";
+    if ( value & GeometryInstanceFlagBitsKHR::eForceNoOpaque ) result += "ForceNoOpaque | ";
     return "{ " + result.substr(0, result.size() - 3) + " }";
   }
 
@@ -10524,45 +10889,83 @@
     return "{ " + result.substr(0, result.size() - 3) + " }";
   }
 
-  using IndirectCommandsLayoutUsageFlagsNVX = Flags<IndirectCommandsLayoutUsageFlagBitsNVX>;
+  using IndirectCommandsLayoutUsageFlagsNV = Flags<IndirectCommandsLayoutUsageFlagBitsNV>;
 
-  template <> struct FlagTraits<IndirectCommandsLayoutUsageFlagBitsNVX>
+  template <> struct FlagTraits<IndirectCommandsLayoutUsageFlagBitsNV>
   {
     enum : VkFlags
     {
-      allFlags = VkFlags(IndirectCommandsLayoutUsageFlagBitsNVX::eUnorderedSequences) | VkFlags(IndirectCommandsLayoutUsageFlagBitsNVX::eSparseSequences) | VkFlags(IndirectCommandsLayoutUsageFlagBitsNVX::eEmptyExecutions) | VkFlags(IndirectCommandsLayoutUsageFlagBitsNVX::eIndexedSequences)
+      allFlags = VkFlags(IndirectCommandsLayoutUsageFlagBitsNV::eExplicitPreprocess) | VkFlags(IndirectCommandsLayoutUsageFlagBitsNV::eIndexedSequences) | VkFlags(IndirectCommandsLayoutUsageFlagBitsNV::eUnorderedSequences)
     };
   };
 
-  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR IndirectCommandsLayoutUsageFlagsNVX operator|( IndirectCommandsLayoutUsageFlagBitsNVX bit0, IndirectCommandsLayoutUsageFlagBitsNVX bit1 ) VULKAN_HPP_NOEXCEPT
+  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR IndirectCommandsLayoutUsageFlagsNV operator|( IndirectCommandsLayoutUsageFlagBitsNV bit0, IndirectCommandsLayoutUsageFlagBitsNV bit1 ) VULKAN_HPP_NOEXCEPT
   {
-    return IndirectCommandsLayoutUsageFlagsNVX( bit0 ) | bit1;
+    return IndirectCommandsLayoutUsageFlagsNV( bit0 ) | bit1;
   }
 
-  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR IndirectCommandsLayoutUsageFlagsNVX operator&( IndirectCommandsLayoutUsageFlagBitsNVX bit0, IndirectCommandsLayoutUsageFlagBitsNVX bit1 ) VULKAN_HPP_NOEXCEPT
+  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR IndirectCommandsLayoutUsageFlagsNV operator&( IndirectCommandsLayoutUsageFlagBitsNV bit0, IndirectCommandsLayoutUsageFlagBitsNV bit1 ) VULKAN_HPP_NOEXCEPT
   {
-    return IndirectCommandsLayoutUsageFlagsNVX( bit0 ) & bit1;
+    return IndirectCommandsLayoutUsageFlagsNV( bit0 ) & bit1;
   }
 
-  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR IndirectCommandsLayoutUsageFlagsNVX operator^( IndirectCommandsLayoutUsageFlagBitsNVX bit0, IndirectCommandsLayoutUsageFlagBitsNVX bit1 ) VULKAN_HPP_NOEXCEPT
+  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR IndirectCommandsLayoutUsageFlagsNV operator^( IndirectCommandsLayoutUsageFlagBitsNV bit0, IndirectCommandsLayoutUsageFlagBitsNV bit1 ) VULKAN_HPP_NOEXCEPT
   {
-    return IndirectCommandsLayoutUsageFlagsNVX( bit0 ) ^ bit1;
+    return IndirectCommandsLayoutUsageFlagsNV( bit0 ) ^ bit1;
   }
 
-  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR IndirectCommandsLayoutUsageFlagsNVX operator~( IndirectCommandsLayoutUsageFlagBitsNVX bits ) VULKAN_HPP_NOEXCEPT
+  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR IndirectCommandsLayoutUsageFlagsNV operator~( IndirectCommandsLayoutUsageFlagBitsNV bits ) VULKAN_HPP_NOEXCEPT
   {
-    return ~( IndirectCommandsLayoutUsageFlagsNVX( bits ) );
+    return ~( IndirectCommandsLayoutUsageFlagsNV( bits ) );
   }
 
-  VULKAN_HPP_INLINE std::string to_string( IndirectCommandsLayoutUsageFlagsNVX value  )
+  VULKAN_HPP_INLINE std::string to_string( IndirectCommandsLayoutUsageFlagsNV value  )
   {
     if ( !value ) return "{}";
     std::string result;
 
-    if ( value & IndirectCommandsLayoutUsageFlagBitsNVX::eUnorderedSequences ) result += "UnorderedSequences | ";
-    if ( value & IndirectCommandsLayoutUsageFlagBitsNVX::eSparseSequences ) result += "SparseSequences | ";
-    if ( value & IndirectCommandsLayoutUsageFlagBitsNVX::eEmptyExecutions ) result += "EmptyExecutions | ";
-    if ( value & IndirectCommandsLayoutUsageFlagBitsNVX::eIndexedSequences ) result += "IndexedSequences | ";
+    if ( value & IndirectCommandsLayoutUsageFlagBitsNV::eExplicitPreprocess ) result += "ExplicitPreprocess | ";
+    if ( value & IndirectCommandsLayoutUsageFlagBitsNV::eIndexedSequences ) result += "IndexedSequences | ";
+    if ( value & IndirectCommandsLayoutUsageFlagBitsNV::eUnorderedSequences ) result += "UnorderedSequences | ";
+    return "{ " + result.substr(0, result.size() - 3) + " }";
+  }
+
+  using IndirectStateFlagsNV = Flags<IndirectStateFlagBitsNV>;
+
+  template <> struct FlagTraits<IndirectStateFlagBitsNV>
+  {
+    enum : VkFlags
+    {
+      allFlags = VkFlags(IndirectStateFlagBitsNV::eFlagFrontface)
+    };
+  };
+
+  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR IndirectStateFlagsNV operator|( IndirectStateFlagBitsNV bit0, IndirectStateFlagBitsNV bit1 ) VULKAN_HPP_NOEXCEPT
+  {
+    return IndirectStateFlagsNV( bit0 ) | bit1;
+  }
+
+  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR IndirectStateFlagsNV operator&( IndirectStateFlagBitsNV bit0, IndirectStateFlagBitsNV bit1 ) VULKAN_HPP_NOEXCEPT
+  {
+    return IndirectStateFlagsNV( bit0 ) & bit1;
+  }
+
+  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR IndirectStateFlagsNV operator^( IndirectStateFlagBitsNV bit0, IndirectStateFlagBitsNV bit1 ) VULKAN_HPP_NOEXCEPT
+  {
+    return IndirectStateFlagsNV( bit0 ) ^ bit1;
+  }
+
+  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR IndirectStateFlagsNV operator~( IndirectStateFlagBitsNV bits ) VULKAN_HPP_NOEXCEPT
+  {
+    return ~( IndirectStateFlagsNV( bits ) );
+  }
+
+  VULKAN_HPP_INLINE std::string to_string( IndirectStateFlagsNV value  )
+  {
+    if ( !value ) return "{}";
+    std::string result;
+
+    if ( value & IndirectStateFlagBitsNV::eFlagFrontface ) result += "FlagFrontface | ";
     return "{ " + result.substr(0, result.size() - 3) + " }";
   }
 
@@ -10751,46 +11154,6 @@
   }
 #endif /*VK_USE_PLATFORM_METAL_EXT*/
 
-  using ObjectEntryUsageFlagsNVX = Flags<ObjectEntryUsageFlagBitsNVX>;
-
-  template <> struct FlagTraits<ObjectEntryUsageFlagBitsNVX>
-  {
-    enum : VkFlags
-    {
-      allFlags = VkFlags(ObjectEntryUsageFlagBitsNVX::eGraphics) | VkFlags(ObjectEntryUsageFlagBitsNVX::eCompute)
-    };
-  };
-
-  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ObjectEntryUsageFlagsNVX operator|( ObjectEntryUsageFlagBitsNVX bit0, ObjectEntryUsageFlagBitsNVX bit1 ) VULKAN_HPP_NOEXCEPT
-  {
-    return ObjectEntryUsageFlagsNVX( bit0 ) | bit1;
-  }
-
-  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ObjectEntryUsageFlagsNVX operator&( ObjectEntryUsageFlagBitsNVX bit0, ObjectEntryUsageFlagBitsNVX bit1 ) VULKAN_HPP_NOEXCEPT
-  {
-    return ObjectEntryUsageFlagsNVX( bit0 ) & bit1;
-  }
-
-  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ObjectEntryUsageFlagsNVX operator^( ObjectEntryUsageFlagBitsNVX bit0, ObjectEntryUsageFlagBitsNVX bit1 ) VULKAN_HPP_NOEXCEPT
-  {
-    return ObjectEntryUsageFlagsNVX( bit0 ) ^ bit1;
-  }
-
-  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR ObjectEntryUsageFlagsNVX operator~( ObjectEntryUsageFlagBitsNVX bits ) VULKAN_HPP_NOEXCEPT
-  {
-    return ~( ObjectEntryUsageFlagsNVX( bits ) );
-  }
-
-  VULKAN_HPP_INLINE std::string to_string( ObjectEntryUsageFlagsNVX value  )
-  {
-    if ( !value ) return "{}";
-    std::string result;
-
-    if ( value & ObjectEntryUsageFlagBitsNVX::eGraphics ) result += "Graphics | ";
-    if ( value & ObjectEntryUsageFlagBitsNVX::eCompute ) result += "Compute | ";
-    return "{ " + result.substr(0, result.size() - 3) + " }";
-  }
-
   using PeerMemoryFeatureFlags = Flags<PeerMemoryFeatureFlagBits>;
 
   template <> struct FlagTraits<PeerMemoryFeatureFlagBits>
@@ -10877,9 +11240,41 @@
 
   using PipelineCacheCreateFlags = Flags<PipelineCacheCreateFlagBits>;
 
-  VULKAN_HPP_INLINE std::string to_string( PipelineCacheCreateFlags  )
+  template <> struct FlagTraits<PipelineCacheCreateFlagBits>
   {
-    return "{}";
+    enum : VkFlags
+    {
+      allFlags = VkFlags(PipelineCacheCreateFlagBits::eExternallySynchronizedEXT)
+    };
+  };
+
+  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR PipelineCacheCreateFlags operator|( PipelineCacheCreateFlagBits bit0, PipelineCacheCreateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+  {
+    return PipelineCacheCreateFlags( bit0 ) | bit1;
+  }
+
+  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR PipelineCacheCreateFlags operator&( PipelineCacheCreateFlagBits bit0, PipelineCacheCreateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+  {
+    return PipelineCacheCreateFlags( bit0 ) & bit1;
+  }
+
+  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR PipelineCacheCreateFlags operator^( PipelineCacheCreateFlagBits bit0, PipelineCacheCreateFlagBits bit1 ) VULKAN_HPP_NOEXCEPT
+  {
+    return PipelineCacheCreateFlags( bit0 ) ^ bit1;
+  }
+
+  VULKAN_HPP_INLINE VULKAN_HPP_CONSTEXPR PipelineCacheCreateFlags operator~( PipelineCacheCreateFlagBits bits ) VULKAN_HPP_NOEXCEPT
+  {
+    return ~( PipelineCacheCreateFlags( bits ) );
+  }
+
+  VULKAN_HPP_INLINE std::string to_string( PipelineCacheCreateFlags value  )
+  {
+    if ( !value ) return "{}";
+    std::string result;
+
+    if ( value & PipelineCacheCreateFlagBits::eExternallySynchronizedEXT ) result += "ExternallySynchronizedEXT | ";
+    return "{ " + result.substr(0, result.size() - 3) + " }";
   }
 
   using PipelineColorBlendStateCreateFlags = Flags<PipelineColorBlendStateCreateFlagBits>;
@@ -10947,7 +11342,7 @@
   {
     enum : VkFlags
     {
-      allFlags = VkFlags(PipelineCreateFlagBits::eDisableOptimization) | VkFlags(PipelineCreateFlagBits::eAllowDerivatives) | VkFlags(PipelineCreateFlagBits::eDerivative) | VkFlags(PipelineCreateFlagBits::eViewIndexFromDeviceIndex) | VkFlags(PipelineCreateFlagBits::eDispatchBase) | VkFlags(PipelineCreateFlagBits::eDeferCompileNV) | VkFlags(PipelineCreateFlagBits::eCaptureStatisticsKHR) | VkFlags(PipelineCreateFlagBits::eCaptureInternalRepresentationsKHR)
+      allFlags = VkFlags(PipelineCreateFlagBits::eDisableOptimization) | VkFlags(PipelineCreateFlagBits::eAllowDerivatives) | VkFlags(PipelineCreateFlagBits::eDerivative) | VkFlags(PipelineCreateFlagBits::eViewIndexFromDeviceIndex) | VkFlags(PipelineCreateFlagBits::eDispatchBase) | VkFlags(PipelineCreateFlagBits::eRayTracingNoNullAnyHitShadersKHR) | VkFlags(PipelineCreateFlagBits::eRayTracingNoNullClosestHitShadersKHR) | VkFlags(PipelineCreateFlagBits::eRayTracingNoNullMissShadersKHR) | VkFlags(PipelineCreateFlagBits::eRayTracingNoNullIntersectionShadersKHR) | VkFlags(PipelineCreateFlagBits::eRayTracingSkipTrianglesKHR) | VkFlags(PipelineCreateFlagBits::eRayTracingSkipAabbsKHR) | VkFlags(PipelineCreateFlagBits::eDeferCompileNV) | VkFlags(PipelineCreateFlagBits::eCaptureStatisticsKHR) | VkFlags(PipelineCreateFlagBits::eCaptureInternalRepresentationsKHR) | VkFlags(PipelineCreateFlagBits::eIndirectBindableNV) | VkFlags(PipelineCreateFlagBits::eLibraryKHR) | VkFlags(PipelineCreateFlagBits::eFailOnPipelineCompileRequiredEXT) | VkFlags(PipelineCreateFlagBits::eEarlyReturnOnFailureEXT)
     };
   };
 
@@ -10981,9 +11376,19 @@
     if ( value & PipelineCreateFlagBits::eDerivative ) result += "Derivative | ";
     if ( value & PipelineCreateFlagBits::eViewIndexFromDeviceIndex ) result += "ViewIndexFromDeviceIndex | ";
     if ( value & PipelineCreateFlagBits::eDispatchBase ) result += "DispatchBase | ";
+    if ( value & PipelineCreateFlagBits::eRayTracingNoNullAnyHitShadersKHR ) result += "RayTracingNoNullAnyHitShadersKHR | ";
+    if ( value & PipelineCreateFlagBits::eRayTracingNoNullClosestHitShadersKHR ) result += "RayTracingNoNullClosestHitShadersKHR | ";
+    if ( value & PipelineCreateFlagBits::eRayTracingNoNullMissShadersKHR ) result += "RayTracingNoNullMissShadersKHR | ";
+    if ( value & PipelineCreateFlagBits::eRayTracingNoNullIntersectionShadersKHR ) result += "RayTracingNoNullIntersectionShadersKHR | ";
+    if ( value & PipelineCreateFlagBits::eRayTracingSkipTrianglesKHR ) result += "RayTracingSkipTrianglesKHR | ";
+    if ( value & PipelineCreateFlagBits::eRayTracingSkipAabbsKHR ) result += "RayTracingSkipAabbsKHR | ";
     if ( value & PipelineCreateFlagBits::eDeferCompileNV ) result += "DeferCompileNV | ";
     if ( value & PipelineCreateFlagBits::eCaptureStatisticsKHR ) result += "CaptureStatisticsKHR | ";
     if ( value & PipelineCreateFlagBits::eCaptureInternalRepresentationsKHR ) result += "CaptureInternalRepresentationsKHR | ";
+    if ( value & PipelineCreateFlagBits::eIndirectBindableNV ) result += "IndirectBindableNV | ";
+    if ( value & PipelineCreateFlagBits::eLibraryKHR ) result += "LibraryKHR | ";
+    if ( value & PipelineCreateFlagBits::eFailOnPipelineCompileRequiredEXT ) result += "FailOnPipelineCompileRequiredEXT | ";
+    if ( value & PipelineCreateFlagBits::eEarlyReturnOnFailureEXT ) result += "EarlyReturnOnFailureEXT | ";
     return "{ " + result.substr(0, result.size() - 3) + " }";
   }
 
@@ -11176,7 +11581,7 @@
   {
     enum : VkFlags
     {
-      allFlags = VkFlags(PipelineStageFlagBits::eTopOfPipe) | VkFlags(PipelineStageFlagBits::eDrawIndirect) | VkFlags(PipelineStageFlagBits::eVertexInput) | VkFlags(PipelineStageFlagBits::eVertexShader) | VkFlags(PipelineStageFlagBits::eTessellationControlShader) | VkFlags(PipelineStageFlagBits::eTessellationEvaluationShader) | VkFlags(PipelineStageFlagBits::eGeometryShader) | VkFlags(PipelineStageFlagBits::eFragmentShader) | VkFlags(PipelineStageFlagBits::eEarlyFragmentTests) | VkFlags(PipelineStageFlagBits::eLateFragmentTests) | VkFlags(PipelineStageFlagBits::eColorAttachmentOutput) | VkFlags(PipelineStageFlagBits::eComputeShader) | VkFlags(PipelineStageFlagBits::eTransfer) | VkFlags(PipelineStageFlagBits::eBottomOfPipe) | VkFlags(PipelineStageFlagBits::eHost) | VkFlags(PipelineStageFlagBits::eAllGraphics) | VkFlags(PipelineStageFlagBits::eAllCommands) | VkFlags(PipelineStageFlagBits::eTransformFeedbackEXT) | VkFlags(PipelineStageFlagBits::eConditionalRenderingEXT) | VkFlags(PipelineStageFlagBits::eCommandProcessNVX) | VkFlags(PipelineStageFlagBits::eShadingRateImageNV) | VkFlags(PipelineStageFlagBits::eRayTracingShaderNV) | VkFlags(PipelineStageFlagBits::eAccelerationStructureBuildNV) | VkFlags(PipelineStageFlagBits::eTaskShaderNV) | VkFlags(PipelineStageFlagBits::eMeshShaderNV) | VkFlags(PipelineStageFlagBits::eFragmentDensityProcessEXT)
+      allFlags = VkFlags(PipelineStageFlagBits::eTopOfPipe) | VkFlags(PipelineStageFlagBits::eDrawIndirect) | VkFlags(PipelineStageFlagBits::eVertexInput) | VkFlags(PipelineStageFlagBits::eVertexShader) | VkFlags(PipelineStageFlagBits::eTessellationControlShader) | VkFlags(PipelineStageFlagBits::eTessellationEvaluationShader) | VkFlags(PipelineStageFlagBits::eGeometryShader) | VkFlags(PipelineStageFlagBits::eFragmentShader) | VkFlags(PipelineStageFlagBits::eEarlyFragmentTests) | VkFlags(PipelineStageFlagBits::eLateFragmentTests) | VkFlags(PipelineStageFlagBits::eColorAttachmentOutput) | VkFlags(PipelineStageFlagBits::eComputeShader) | VkFlags(PipelineStageFlagBits::eTransfer) | VkFlags(PipelineStageFlagBits::eBottomOfPipe) | VkFlags(PipelineStageFlagBits::eHost) | VkFlags(PipelineStageFlagBits::eAllGraphics) | VkFlags(PipelineStageFlagBits::eAllCommands) | VkFlags(PipelineStageFlagBits::eTransformFeedbackEXT) | VkFlags(PipelineStageFlagBits::eConditionalRenderingEXT) | VkFlags(PipelineStageFlagBits::eRayTracingShaderKHR) | VkFlags(PipelineStageFlagBits::eAccelerationStructureBuildKHR) | VkFlags(PipelineStageFlagBits::eShadingRateImageNV) | VkFlags(PipelineStageFlagBits::eTaskShaderNV) | VkFlags(PipelineStageFlagBits::eMeshShaderNV) | VkFlags(PipelineStageFlagBits::eFragmentDensityProcessEXT) | VkFlags(PipelineStageFlagBits::eCommandPreprocessNV)
     };
   };
 
@@ -11224,13 +11629,13 @@
     if ( value & PipelineStageFlagBits::eAllCommands ) result += "AllCommands | ";
     if ( value & PipelineStageFlagBits::eTransformFeedbackEXT ) result += "TransformFeedbackEXT | ";
     if ( value & PipelineStageFlagBits::eConditionalRenderingEXT ) result += "ConditionalRenderingEXT | ";
-    if ( value & PipelineStageFlagBits::eCommandProcessNVX ) result += "CommandProcessNVX | ";
+    if ( value & PipelineStageFlagBits::eRayTracingShaderKHR ) result += "RayTracingShaderKHR | ";
+    if ( value & PipelineStageFlagBits::eAccelerationStructureBuildKHR ) result += "AccelerationStructureBuildKHR | ";
     if ( value & PipelineStageFlagBits::eShadingRateImageNV ) result += "ShadingRateImageNV | ";
-    if ( value & PipelineStageFlagBits::eRayTracingShaderNV ) result += "RayTracingShaderNV | ";
-    if ( value & PipelineStageFlagBits::eAccelerationStructureBuildNV ) result += "AccelerationStructureBuildNV | ";
     if ( value & PipelineStageFlagBits::eTaskShaderNV ) result += "TaskShaderNV | ";
     if ( value & PipelineStageFlagBits::eMeshShaderNV ) result += "MeshShaderNV | ";
     if ( value & PipelineStageFlagBits::eFragmentDensityProcessEXT ) result += "FragmentDensityProcessEXT | ";
+    if ( value & PipelineStageFlagBits::eCommandPreprocessNV ) result += "CommandPreprocessNV | ";
     return "{ " + result.substr(0, result.size() - 3) + " }";
   }
 
@@ -11727,7 +12132,7 @@
   {
     enum : VkFlags
     {
-      allFlags = VkFlags(ShaderStageFlagBits::eVertex) | VkFlags(ShaderStageFlagBits::eTessellationControl) | VkFlags(ShaderStageFlagBits::eTessellationEvaluation) | VkFlags(ShaderStageFlagBits::eGeometry) | VkFlags(ShaderStageFlagBits::eFragment) | VkFlags(ShaderStageFlagBits::eCompute) | VkFlags(ShaderStageFlagBits::eAllGraphics) | VkFlags(ShaderStageFlagBits::eAll) | VkFlags(ShaderStageFlagBits::eRaygenNV) | VkFlags(ShaderStageFlagBits::eAnyHitNV) | VkFlags(ShaderStageFlagBits::eClosestHitNV) | VkFlags(ShaderStageFlagBits::eMissNV) | VkFlags(ShaderStageFlagBits::eIntersectionNV) | VkFlags(ShaderStageFlagBits::eCallableNV) | VkFlags(ShaderStageFlagBits::eTaskNV) | VkFlags(ShaderStageFlagBits::eMeshNV)
+      allFlags = VkFlags(ShaderStageFlagBits::eVertex) | VkFlags(ShaderStageFlagBits::eTessellationControl) | VkFlags(ShaderStageFlagBits::eTessellationEvaluation) | VkFlags(ShaderStageFlagBits::eGeometry) | VkFlags(ShaderStageFlagBits::eFragment) | VkFlags(ShaderStageFlagBits::eCompute) | VkFlags(ShaderStageFlagBits::eAllGraphics) | VkFlags(ShaderStageFlagBits::eAll) | VkFlags(ShaderStageFlagBits::eRaygenKHR) | VkFlags(ShaderStageFlagBits::eAnyHitKHR) | VkFlags(ShaderStageFlagBits::eClosestHitKHR) | VkFlags(ShaderStageFlagBits::eMissKHR) | VkFlags(ShaderStageFlagBits::eIntersectionKHR) | VkFlags(ShaderStageFlagBits::eCallableKHR) | VkFlags(ShaderStageFlagBits::eTaskNV) | VkFlags(ShaderStageFlagBits::eMeshNV)
     };
   };
 
@@ -11762,12 +12167,12 @@
     if ( value & ShaderStageFlagBits::eGeometry ) result += "Geometry | ";
     if ( value & ShaderStageFlagBits::eFragment ) result += "Fragment | ";
     if ( value & ShaderStageFlagBits::eCompute ) result += "Compute | ";
-    if ( value & ShaderStageFlagBits::eRaygenNV ) result += "RaygenNV | ";
-    if ( value & ShaderStageFlagBits::eAnyHitNV ) result += "AnyHitNV | ";
-    if ( value & ShaderStageFlagBits::eClosestHitNV ) result += "ClosestHitNV | ";
-    if ( value & ShaderStageFlagBits::eMissNV ) result += "MissNV | ";
-    if ( value & ShaderStageFlagBits::eIntersectionNV ) result += "IntersectionNV | ";
-    if ( value & ShaderStageFlagBits::eCallableNV ) result += "CallableNV | ";
+    if ( value & ShaderStageFlagBits::eRaygenKHR ) result += "RaygenKHR | ";
+    if ( value & ShaderStageFlagBits::eAnyHitKHR ) result += "AnyHitKHR | ";
+    if ( value & ShaderStageFlagBits::eClosestHitKHR ) result += "ClosestHitKHR | ";
+    if ( value & ShaderStageFlagBits::eMissKHR ) result += "MissKHR | ";
+    if ( value & ShaderStageFlagBits::eIntersectionKHR ) result += "IntersectionKHR | ";
+    if ( value & ShaderStageFlagBits::eCallableKHR ) result += "CallableKHR | ";
     if ( value & ShaderStageFlagBits::eTaskNV ) result += "TaskNV | ";
     if ( value & ShaderStageFlagBits::eMeshNV ) result += "MeshNV | ";
     return "{ " + result.substr(0, result.size() - 3) + " }";
@@ -12552,6 +12957,15 @@
       : SystemError( make_error_code( Result::eErrorInvalidShaderNV ), message ) {}
   };
 
+  class IncompatibleVersionKHRError : public SystemError
+  {
+  public:
+    IncompatibleVersionKHRError( std::string const& message )
+      : SystemError( make_error_code( Result::eErrorIncompatibleVersionKHR ), message ) {}
+    IncompatibleVersionKHRError( char const * message )
+      : SystemError( make_error_code( Result::eErrorIncompatibleVersionKHR ), message ) {}
+  };
+
   class InvalidDrmFormatModifierPlaneLayoutEXTError : public SystemError
   {
   public:
@@ -12606,6 +13020,7 @@
       case Result::eErrorIncompatibleDisplayKHR: throw IncompatibleDisplayKHRError( message );
       case Result::eErrorValidationFailedEXT: throw ValidationFailedEXTError( message );
       case Result::eErrorInvalidShaderNV: throw InvalidShaderNVError( message );
+      case Result::eErrorIncompatibleVersionKHR: throw IncompatibleVersionKHRError( message );
       case Result::eErrorInvalidDrmFormatModifierPlaneLayoutEXT: throw InvalidDrmFormatModifierPlaneLayoutEXTError( message );
       case Result::eErrorNotPermittedEXT: throw NotPermittedEXTError( message );
       case Result::eErrorFullScreenExclusiveModeLostEXT: throw FullScreenExclusiveModeLostEXTError( message );
@@ -12641,8 +13056,54 @@
     T       value;
 
     operator std::tuple<Result&, T&>() VULKAN_HPP_NOEXCEPT { return std::tuple<Result&, T&>(result, value); }
+
+#if !defined(VULKAN_HPP_DISABLE_IMPLICIT_RESULT_VALUE_CAST)
+    operator T const& () const VULKAN_HPP_NOEXCEPT
+    {
+      return value;
+    }
+
+    operator T& () VULKAN_HPP_NOEXCEPT
+    {
+      return value;
+    }
+#endif
   };
 
+#if !defined(VULKAN_HPP_DISABLE_IMPLICIT_RESULT_VALUE_CAST)
+  template <typename Type, typename Dispatch>
+  struct ResultValue<UniqueHandle<Type,Dispatch>>
+  {
+#ifdef VULKAN_HPP_HAS_NOEXCEPT
+    ResultValue(Result r, UniqueHandle<Type, Dispatch> & v) VULKAN_HPP_NOEXCEPT
+#else
+    ResultValue(Result r, UniqueHandle<Type, Dispatch>& v)
+#endif
+      : result(r)
+      , value(v)
+    {}
+
+#ifdef VULKAN_HPP_HAS_NOEXCEPT
+    ResultValue(Result r, UniqueHandle<Type, Dispatch> && v) VULKAN_HPP_NOEXCEPT
+#else
+    ResultValue(Result r, UniqueHandle<Type, Dispatch> && v)
+#endif
+      : result(r)
+      , value(std::move(v))
+    {}
+
+    Result                        result;
+    UniqueHandle<Type, Dispatch>  value;
+
+    operator std::tuple<Result&, UniqueHandle<Type, Dispatch>&>() VULKAN_HPP_NOEXCEPT { return std::tuple<Result&, UniqueHandle<Type, Dispatch>&>(result, value); }
+
+    operator UniqueHandle<Type, Dispatch>() VULKAN_HPP_NOEXCEPT
+    {
+      return std::move(value);
+    }
+  };
+#endif
+
   template <typename T>
   struct ResultValueType
   {
@@ -12738,11 +13199,67 @@
     return UniqueHandle<T,D>(data, deleter);
 #endif
   }
+
+  template <typename T, typename D>
+  VULKAN_HPP_INLINE ResultValue<UniqueHandle<T,D>> createResultValue( Result result, T & data, char const * message, std::initializer_list<Result> successCodes, typename UniqueHandleTraits<T,D>::deleter const& deleter )
+  {
+#ifdef VULKAN_HPP_NO_EXCEPTIONS
+    ignore(message);
+    VULKAN_HPP_ASSERT( std::find( successCodes.begin(), successCodes.end(), result ) != successCodes.end() );
+    return ResultValue<UniqueHandle<T,D>>( result, UniqueHandle<T,D>(data, deleter) );
+#else
+    if ( std::find( successCodes.begin(), successCodes.end(), result ) == successCodes.end() )
+    {
+      throwResultException( result, message );
+    }
+    return ResultValue<UniqueHandle<T,D>>( result, UniqueHandle<T,D>(data, deleter) );
+#endif
+  }
 #endif
 
+  struct AabbPositionsKHR;
+  using AabbPositionsNV = AabbPositionsKHR;
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct AccelerationStructureBuildGeometryInfoKHR;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct AccelerationStructureBuildOffsetInfoKHR;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct AccelerationStructureCreateGeometryTypeInfoKHR;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct AccelerationStructureCreateInfoKHR;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
   struct AccelerationStructureCreateInfoNV;
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct AccelerationStructureDeviceAddressInfoKHR;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct AccelerationStructureGeometryAabbsDataKHR;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  union AccelerationStructureGeometryDataKHR;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct AccelerationStructureGeometryInstancesDataKHR;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct AccelerationStructureGeometryKHR;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct AccelerationStructureGeometryTrianglesDataKHR;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
   struct AccelerationStructureInfoNV;
+  struct AccelerationStructureInstanceKHR;
+  using AccelerationStructureInstanceNV = AccelerationStructureInstanceKHR;
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct AccelerationStructureMemoryRequirementsInfoKHR;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
   struct AccelerationStructureMemoryRequirementsInfoNV;
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct AccelerationStructureVersionKHR;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
   struct AcquireNextImageInfoKHR;
   struct AcquireProfilingLockInfoKHR;
   struct AllocationCallbacks;
@@ -12772,7 +13289,8 @@
   struct AttachmentSampleLocationsEXT;
   struct BaseInStructure;
   struct BaseOutStructure;
-  struct BindAccelerationStructureMemoryInfoNV;
+  struct BindAccelerationStructureMemoryInfoKHR;
+  using BindAccelerationStructureMemoryInfoNV = BindAccelerationStructureMemoryInfoKHR;
   struct BindBufferMemoryDeviceGroupInfo;
   using BindBufferMemoryDeviceGroupInfoKHR = BindBufferMemoryDeviceGroupInfo;
   struct BindBufferMemoryInfo;
@@ -12784,7 +13302,10 @@
   struct BindImageMemorySwapchainInfoKHR;
   struct BindImagePlaneMemoryInfo;
   using BindImagePlaneMemoryInfoKHR = BindImagePlaneMemoryInfo;
+  struct BindIndexBufferIndirectCommandNV;
+  struct BindShaderGroupIndirectCommandNV;
   struct BindSparseInfo;
+  struct BindVertexBufferIndirectCommandNV;
   struct BufferCopy;
   struct BufferCreateInfo;
   struct BufferDeviceAddressCreateInfoEXT;
@@ -12805,8 +13326,6 @@
   struct ClearDepthStencilValue;
   struct ClearRect;
   union ClearValue;
-  struct CmdProcessCommandsInfoNVX;
-  struct CmdReserveSpaceForCommandsInfoNVX;
   struct CoarseSampleLocationNV;
   struct CoarseSampleOrderCustomNV;
   struct CommandBufferAllocateInfo;
@@ -12821,7 +13340,16 @@
   struct ConformanceVersion;
   using ConformanceVersionKHR = ConformanceVersion;
   struct CooperativeMatrixPropertiesNV;
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct CopyAccelerationStructureInfoKHR;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct CopyAccelerationStructureToMemoryInfoKHR;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
   struct CopyDescriptorSet;
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct CopyMemoryToAccelerationStructureInfoKHR;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
 #ifdef VK_USE_PLATFORM_WIN32_KHR
   struct D3D12FenceSubmitInfoKHR;
 #endif /*VK_USE_PLATFORM_WIN32_KHR*/
@@ -12837,6 +13365,9 @@
   struct DedicatedAllocationBufferCreateInfoNV;
   struct DedicatedAllocationImageCreateInfoNV;
   struct DedicatedAllocationMemoryAllocateInfoNV;
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct DeferredOperationInfoKHR;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
   struct DescriptorBufferInfo;
   struct DescriptorImageInfo;
   struct DescriptorPoolCreateInfo;
@@ -12858,9 +13389,8 @@
   struct DescriptorUpdateTemplateEntry;
   using DescriptorUpdateTemplateEntryKHR = DescriptorUpdateTemplateEntry;
   struct DeviceCreateInfo;
+  struct DeviceDiagnosticsConfigCreateInfoNV;
   struct DeviceEventInfoEXT;
-  struct DeviceGeneratedCommandsFeaturesNVX;
-  struct DeviceGeneratedCommandsLimitsNVX;
   struct DeviceGroupBindSparseInfo;
   using DeviceGroupBindSparseInfoKHR = DeviceGroupBindSparseInfo;
   struct DeviceGroupCommandBufferBeginInfo;
@@ -12877,6 +13407,12 @@
   struct DeviceMemoryOpaqueCaptureAddressInfo;
   using DeviceMemoryOpaqueCaptureAddressInfoKHR = DeviceMemoryOpaqueCaptureAddressInfo;
   struct DeviceMemoryOverallocationCreateInfoAMD;
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  union DeviceOrHostAddressConstKHR;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  union DeviceOrHostAddressKHR;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
   struct DeviceQueueCreateInfo;
   struct DeviceQueueGlobalPriorityCreateInfoEXT;
   struct DeviceQueueInfo2;
@@ -12959,11 +13495,15 @@
   using FramebufferAttachmentsCreateInfoKHR = FramebufferAttachmentsCreateInfo;
   struct FramebufferCreateInfo;
   struct FramebufferMixedSamplesCombinationNV;
+  struct GeneratedCommandsInfoNV;
+  struct GeneratedCommandsMemoryRequirementsInfoNV;
   struct GeometryAABBNV;
   struct GeometryDataNV;
   struct GeometryNV;
   struct GeometryTrianglesNV;
   struct GraphicsPipelineCreateInfo;
+  struct GraphicsPipelineShaderGroupsCreateInfoNV;
+  struct GraphicsShaderGroupCreateInfoNV;
   struct HdrMetadataEXT;
   struct HeadlessSurfaceCreateInfoEXT;
 #ifdef VK_USE_PLATFORM_IOS_MVK
@@ -12998,6 +13538,7 @@
   struct ImageSubresourceRange;
   struct ImageSwapchainCreateInfoKHR;
   struct ImageViewASTCDecodeModeEXT;
+  struct ImageViewAddressPropertiesNVX;
   struct ImageViewCreateInfo;
   struct ImageViewHandleInfoNVX;
   struct ImageViewUsageCreateInfo;
@@ -13021,9 +13562,9 @@
 #ifdef VK_USE_PLATFORM_WIN32_KHR
   struct ImportSemaphoreWin32HandleInfoKHR;
 #endif /*VK_USE_PLATFORM_WIN32_KHR*/
-  struct IndirectCommandsLayoutCreateInfoNVX;
-  struct IndirectCommandsLayoutTokenNVX;
-  struct IndirectCommandsTokenNVX;
+  struct IndirectCommandsLayoutCreateInfoNV;
+  struct IndirectCommandsLayoutTokenNV;
+  struct IndirectCommandsStreamNV;
   struct InitializePerformanceApiInfoINTEL;
   struct InputAttachmentAspectReference;
   using InputAttachmentAspectReferenceKHR = InputAttachmentAspectReference;
@@ -13065,13 +13606,6 @@
   struct MetalSurfaceCreateInfoEXT;
 #endif /*VK_USE_PLATFORM_METAL_EXT*/
   struct MultisamplePropertiesEXT;
-  struct ObjectTableCreateInfoNVX;
-  struct ObjectTableDescriptorSetEntryNVX;
-  struct ObjectTableEntryNVX;
-  struct ObjectTableIndexBufferEntryNVX;
-  struct ObjectTablePipelineEntryNVX;
-  struct ObjectTablePushConstantEntryNVX;
-  struct ObjectTableVertexBufferEntryNVX;
   struct Offset2D;
   struct Offset3D;
   struct PastPresentationTimingGOOGLE;
@@ -13112,6 +13646,9 @@
   using PhysicalDeviceDescriptorIndexingFeaturesEXT = PhysicalDeviceDescriptorIndexingFeatures;
   struct PhysicalDeviceDescriptorIndexingProperties;
   using PhysicalDeviceDescriptorIndexingPropertiesEXT = PhysicalDeviceDescriptorIndexingProperties;
+  struct PhysicalDeviceDeviceGeneratedCommandsFeaturesNV;
+  struct PhysicalDeviceDeviceGeneratedCommandsPropertiesNV;
+  struct PhysicalDeviceDiagnosticsConfigFeaturesNV;
   struct PhysicalDeviceDiscardRectanglePropertiesEXT;
   struct PhysicalDeviceDriverProperties;
   using PhysicalDeviceDriverPropertiesKHR = PhysicalDeviceDriverProperties;
@@ -13169,6 +13706,7 @@
   struct PhysicalDevicePCIBusInfoPropertiesEXT;
   struct PhysicalDevicePerformanceQueryFeaturesKHR;
   struct PhysicalDevicePerformanceQueryPropertiesKHR;
+  struct PhysicalDevicePipelineCreationCacheControlFeaturesEXT;
   struct PhysicalDevicePipelineExecutablePropertiesFeaturesKHR;
   struct PhysicalDevicePointClippingProperties;
   using PhysicalDevicePointClippingPropertiesKHR = PhysicalDevicePointClippingProperties;
@@ -13178,6 +13716,12 @@
   struct PhysicalDeviceProtectedMemoryFeatures;
   struct PhysicalDeviceProtectedMemoryProperties;
   struct PhysicalDevicePushDescriptorPropertiesKHR;
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct PhysicalDeviceRayTracingFeaturesKHR;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct PhysicalDeviceRayTracingPropertiesKHR;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
   struct PhysicalDeviceRayTracingPropertiesNV;
   struct PhysicalDeviceRepresentativeFragmentTestFeaturesNV;
   struct PhysicalDeviceSampleLocationsPropertiesEXT;
@@ -13261,6 +13805,9 @@
   struct PipelineInfoKHR;
   struct PipelineInputAssemblyStateCreateInfo;
   struct PipelineLayoutCreateInfo;
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct PipelineLibraryCreateInfoKHR;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
   struct PipelineMultisampleStateCreateInfo;
   struct PipelineRasterizationConservativeStateCreateInfoEXT;
   struct PipelineRasterizationDepthClipStateCreateInfoEXT;
@@ -13294,13 +13841,23 @@
   struct ProtectedSubmitInfo;
   struct PushConstantRange;
   struct QueryPoolCreateInfo;
-  struct QueryPoolCreateInfoINTEL;
   struct QueryPoolPerformanceCreateInfoKHR;
+  struct QueryPoolPerformanceQueryCreateInfoINTEL;
+  using QueryPoolCreateInfoINTEL = QueryPoolPerformanceQueryCreateInfoINTEL;
   struct QueueFamilyCheckpointPropertiesNV;
   struct QueueFamilyProperties;
   struct QueueFamilyProperties2;
   using QueueFamilyProperties2KHR = QueueFamilyProperties2;
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct RayTracingPipelineCreateInfoKHR;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
   struct RayTracingPipelineCreateInfoNV;
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct RayTracingPipelineInterfaceCreateInfoKHR;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct RayTracingShaderGroupCreateInfoKHR;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
   struct RayTracingShaderGroupCreateInfoNV;
   struct Rect2D;
   struct RectLayerKHR;
@@ -13340,6 +13897,7 @@
   using SemaphoreTypeCreateInfoKHR = SemaphoreTypeCreateInfo;
   struct SemaphoreWaitInfo;
   using SemaphoreWaitInfoKHR = SemaphoreWaitInfo;
+  struct SetStateFlagsIndirectCommandNV;
   struct ShaderModuleCreateInfo;
   struct ShaderModuleValidationCacheCreateInfoEXT;
   struct ShaderResourceUsageAMD;
@@ -13363,6 +13921,9 @@
 #ifdef VK_USE_PLATFORM_GGP
   struct StreamDescriptorSurfaceCreateInfoGGP;
 #endif /*VK_USE_PLATFORM_GGP*/
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct StridedBufferRegionKHR;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
   struct SubmitInfo;
   struct SubpassBeginInfo;
   using SubpassBeginInfoKHR = SubpassBeginInfo;
@@ -13399,6 +13960,11 @@
   struct TextureLODGatherFormatPropertiesAMD;
   struct TimelineSemaphoreSubmitInfo;
   using TimelineSemaphoreSubmitInfoKHR = TimelineSemaphoreSubmitInfo;
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct TraceRaysIndirectCommandKHR;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+  struct TransformMatrixKHR;
+  using TransformMatrixNV = TransformMatrixKHR;
   struct ValidationCacheCreateInfoEXT;
   struct ValidationFeaturesEXT;
   struct ValidationFlagsEXT;
@@ -13424,7 +13990,8 @@
   struct Win32SurfaceCreateInfoKHR;
 #endif /*VK_USE_PLATFORM_WIN32_KHR*/
   struct WriteDescriptorSet;
-  struct WriteDescriptorSetAccelerationStructureNV;
+  struct WriteDescriptorSetAccelerationStructureKHR;
+  using WriteDescriptorSetAccelerationStructureNV = WriteDescriptorSetAccelerationStructureKHR;
   struct WriteDescriptorSetInlineUniformBlockEXT;
   struct XYColorEXT;
 #ifdef VK_USE_PLATFORM_XCB_KHR
@@ -14619,84 +15186,85 @@
     using type = Image;
   };
 
-  class AccelerationStructureNV
+  class AccelerationStructureKHR
   {
   public:
-    using CType = VkAccelerationStructureNV;
+    using CType = VkAccelerationStructureKHR;
 
-    static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::eAccelerationStructureNV;
+    static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::eAccelerationStructureKHR;
 
   public:
-    VULKAN_HPP_CONSTEXPR AccelerationStructureNV() VULKAN_HPP_NOEXCEPT
-      : m_accelerationStructureNV(VK_NULL_HANDLE)
+    VULKAN_HPP_CONSTEXPR AccelerationStructureKHR() VULKAN_HPP_NOEXCEPT
+      : m_accelerationStructureKHR(VK_NULL_HANDLE)
     {}
 
-    VULKAN_HPP_CONSTEXPR AccelerationStructureNV( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
-      : m_accelerationStructureNV(VK_NULL_HANDLE)
+    VULKAN_HPP_CONSTEXPR AccelerationStructureKHR( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+      : m_accelerationStructureKHR(VK_NULL_HANDLE)
     {}
 
-    VULKAN_HPP_TYPESAFE_EXPLICIT AccelerationStructureNV( VkAccelerationStructureNV accelerationStructureNV ) VULKAN_HPP_NOEXCEPT
-      : m_accelerationStructureNV( accelerationStructureNV )
+    VULKAN_HPP_TYPESAFE_EXPLICIT AccelerationStructureKHR( VkAccelerationStructureKHR accelerationStructureKHR ) VULKAN_HPP_NOEXCEPT
+      : m_accelerationStructureKHR( accelerationStructureKHR )
     {}
 
 #if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
-    AccelerationStructureNV & operator=(VkAccelerationStructureNV accelerationStructureNV) VULKAN_HPP_NOEXCEPT
+    AccelerationStructureKHR & operator=(VkAccelerationStructureKHR accelerationStructureKHR) VULKAN_HPP_NOEXCEPT
     {
-      m_accelerationStructureNV = accelerationStructureNV;
+      m_accelerationStructureKHR = accelerationStructureKHR;
       return *this;
     }
 #endif
 
-    AccelerationStructureNV & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+    AccelerationStructureKHR & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
     {
-      m_accelerationStructureNV = VK_NULL_HANDLE;
+      m_accelerationStructureKHR = VK_NULL_HANDLE;
       return *this;
     }
 
 #if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
-    auto operator<=>( AccelerationStructureNV const& ) const = default;
+    auto operator<=>( AccelerationStructureKHR const& ) const = default;
 #else
-    bool operator==( AccelerationStructureNV const & rhs ) const VULKAN_HPP_NOEXCEPT
+    bool operator==( AccelerationStructureKHR const & rhs ) const VULKAN_HPP_NOEXCEPT
     {
-      return m_accelerationStructureNV == rhs.m_accelerationStructureNV;
+      return m_accelerationStructureKHR == rhs.m_accelerationStructureKHR;
     }
 
-    bool operator!=(AccelerationStructureNV const & rhs ) const VULKAN_HPP_NOEXCEPT
+    bool operator!=(AccelerationStructureKHR const & rhs ) const VULKAN_HPP_NOEXCEPT
     {
-      return m_accelerationStructureNV != rhs.m_accelerationStructureNV;
+      return m_accelerationStructureKHR != rhs.m_accelerationStructureKHR;
     }
 
-    bool operator<(AccelerationStructureNV const & rhs ) const VULKAN_HPP_NOEXCEPT
+    bool operator<(AccelerationStructureKHR const & rhs ) const VULKAN_HPP_NOEXCEPT
     {
-      return m_accelerationStructureNV < rhs.m_accelerationStructureNV;
+      return m_accelerationStructureKHR < rhs.m_accelerationStructureKHR;
     }
 #endif
 
-    VULKAN_HPP_TYPESAFE_EXPLICIT operator VkAccelerationStructureNV() const VULKAN_HPP_NOEXCEPT
+    VULKAN_HPP_TYPESAFE_EXPLICIT operator VkAccelerationStructureKHR() const VULKAN_HPP_NOEXCEPT
     {
-      return m_accelerationStructureNV;
+      return m_accelerationStructureKHR;
     }
 
     explicit operator bool() const VULKAN_HPP_NOEXCEPT
     {
-      return m_accelerationStructureNV != VK_NULL_HANDLE;
+      return m_accelerationStructureKHR != VK_NULL_HANDLE;
     }
 
     bool operator!() const VULKAN_HPP_NOEXCEPT
     {
-      return m_accelerationStructureNV == VK_NULL_HANDLE;
+      return m_accelerationStructureKHR == VK_NULL_HANDLE;
     }
 
   private:
-    VkAccelerationStructureNV m_accelerationStructureNV;
+    VkAccelerationStructureKHR m_accelerationStructureKHR;
   };
-  static_assert( sizeof( AccelerationStructureNV ) == sizeof( VkAccelerationStructureNV ), "handle and wrapper have different size!" );
+  static_assert( sizeof( AccelerationStructureKHR ) == sizeof( VkAccelerationStructureKHR ), "handle and wrapper have different size!" );
 
   template <>
-  struct cpp_type<ObjectType::eAccelerationStructureNV>
+  struct cpp_type<ObjectType::eAccelerationStructureKHR>
   {
-    using type = AccelerationStructureNV;
+    using type = AccelerationStructureKHR;
   };
+  using AccelerationStructureNV = AccelerationStructureKHR;
 
   class DescriptorUpdateTemplate
   {
@@ -14979,6 +15547,9 @@
     void bindPipeline( VULKAN_HPP_NAMESPACE::PipelineBindPoint pipelineBindPoint, VULKAN_HPP_NAMESPACE::Pipeline pipeline, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    void bindPipelineShaderGroupNV( VULKAN_HPP_NAMESPACE::PipelineBindPoint pipelineBindPoint, VULKAN_HPP_NAMESPACE::Pipeline pipeline, uint32_t groupIndex, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
     void bindShadingRateImageNV( VULKAN_HPP_NAMESPACE::ImageView imageView, VULKAN_HPP_NAMESPACE::ImageLayout imageLayout, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
@@ -15002,11 +15573,29 @@
     void blitImage( VULKAN_HPP_NAMESPACE::Image srcImage, VULKAN_HPP_NAMESPACE::ImageLayout srcImageLayout, VULKAN_HPP_NAMESPACE::Image dstImage, VULKAN_HPP_NAMESPACE::ImageLayout dstImageLayout, ArrayProxy<const VULKAN_HPP_NAMESPACE::ImageBlit> regions, VULKAN_HPP_NAMESPACE::Filter filter, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    void buildAccelerationStructureNV( const VULKAN_HPP_NAMESPACE::AccelerationStructureInfoNV* pInfo, VULKAN_HPP_NAMESPACE::Buffer instanceData, VULKAN_HPP_NAMESPACE::DeviceSize instanceOffset, VULKAN_HPP_NAMESPACE::Bool32 update, VULKAN_HPP_NAMESPACE::AccelerationStructureNV dst, VULKAN_HPP_NAMESPACE::AccelerationStructureNV src, VULKAN_HPP_NAMESPACE::Buffer scratch, VULKAN_HPP_NAMESPACE::DeviceSize scratchOffset, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+    void buildAccelerationStructureIndirectKHR( const VULKAN_HPP_NAMESPACE::AccelerationStructureBuildGeometryInfoKHR* pInfo, VULKAN_HPP_NAMESPACE::Buffer indirectBuffer, VULKAN_HPP_NAMESPACE::DeviceSize indirectOffset, uint32_t indirectStride, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    void buildAccelerationStructureNV( const AccelerationStructureInfoNV & info, VULKAN_HPP_NAMESPACE::Buffer instanceData, VULKAN_HPP_NAMESPACE::DeviceSize instanceOffset, VULKAN_HPP_NAMESPACE::Bool32 update, VULKAN_HPP_NAMESPACE::AccelerationStructureNV dst, VULKAN_HPP_NAMESPACE::AccelerationStructureNV src, VULKAN_HPP_NAMESPACE::Buffer scratch, VULKAN_HPP_NAMESPACE::DeviceSize scratchOffset, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+    void buildAccelerationStructureIndirectKHR( const AccelerationStructureBuildGeometryInfoKHR & info, VULKAN_HPP_NAMESPACE::Buffer indirectBuffer, VULKAN_HPP_NAMESPACE::DeviceSize indirectOffset, uint32_t indirectStride, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    void buildAccelerationStructureKHR( uint32_t infoCount, const VULKAN_HPP_NAMESPACE::AccelerationStructureBuildGeometryInfoKHR* pInfos, const VULKAN_HPP_NAMESPACE::AccelerationStructureBuildOffsetInfoKHR* const* ppOffsetInfos, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    void buildAccelerationStructureKHR( ArrayProxy<const VULKAN_HPP_NAMESPACE::AccelerationStructureBuildGeometryInfoKHR> infos, ArrayProxy<const VULKAN_HPP_NAMESPACE::AccelerationStructureBuildOffsetInfoKHR* const> pOffsetInfos, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    void buildAccelerationStructureNV( const VULKAN_HPP_NAMESPACE::AccelerationStructureInfoNV* pInfo, VULKAN_HPP_NAMESPACE::Buffer instanceData, VULKAN_HPP_NAMESPACE::DeviceSize instanceOffset, VULKAN_HPP_NAMESPACE::Bool32 update, VULKAN_HPP_NAMESPACE::AccelerationStructureKHR dst, VULKAN_HPP_NAMESPACE::AccelerationStructureKHR src, VULKAN_HPP_NAMESPACE::Buffer scratch, VULKAN_HPP_NAMESPACE::DeviceSize scratchOffset, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    void buildAccelerationStructureNV( const AccelerationStructureInfoNV & info, VULKAN_HPP_NAMESPACE::Buffer instanceData, VULKAN_HPP_NAMESPACE::DeviceSize instanceOffset, VULKAN_HPP_NAMESPACE::Bool32 update, VULKAN_HPP_NAMESPACE::AccelerationStructureKHR dst, VULKAN_HPP_NAMESPACE::AccelerationStructureKHR src, VULKAN_HPP_NAMESPACE::Buffer scratch, VULKAN_HPP_NAMESPACE::DeviceSize scratchOffset, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
@@ -15030,8 +15619,26 @@
     void clearDepthStencilImage( VULKAN_HPP_NAMESPACE::Image image, VULKAN_HPP_NAMESPACE::ImageLayout imageLayout, const ClearDepthStencilValue & depthStencil, ArrayProxy<const VULKAN_HPP_NAMESPACE::ImageSubresourceRange> ranges, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    void copyAccelerationStructureNV( VULKAN_HPP_NAMESPACE::AccelerationStructureNV dst, VULKAN_HPP_NAMESPACE::AccelerationStructureNV src, VULKAN_HPP_NAMESPACE::CopyAccelerationStructureModeNV mode, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+    void copyAccelerationStructureKHR( const VULKAN_HPP_NAMESPACE::CopyAccelerationStructureInfoKHR* pInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    void copyAccelerationStructureKHR( const CopyAccelerationStructureInfoKHR & info, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    void copyAccelerationStructureNV( VULKAN_HPP_NAMESPACE::AccelerationStructureKHR dst, VULKAN_HPP_NAMESPACE::AccelerationStructureKHR src, VULKAN_HPP_NAMESPACE::CopyAccelerationStructureModeKHR mode, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    void copyAccelerationStructureToMemoryKHR( const VULKAN_HPP_NAMESPACE::CopyAccelerationStructureToMemoryInfoKHR* pInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    void copyAccelerationStructureToMemoryKHR( const CopyAccelerationStructureToMemoryInfoKHR & info, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
 
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
     void copyBuffer( VULKAN_HPP_NAMESPACE::Buffer srcBuffer, VULKAN_HPP_NAMESPACE::Buffer dstBuffer, uint32_t regionCount, const VULKAN_HPP_NAMESPACE::BufferCopy* pRegions, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
@@ -15061,6 +15668,15 @@
     void copyImageToBuffer( VULKAN_HPP_NAMESPACE::Image srcImage, VULKAN_HPP_NAMESPACE::ImageLayout srcImageLayout, VULKAN_HPP_NAMESPACE::Buffer dstBuffer, ArrayProxy<const VULKAN_HPP_NAMESPACE::BufferImageCopy> regions, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    void copyMemoryToAccelerationStructureKHR( const VULKAN_HPP_NAMESPACE::CopyMemoryToAccelerationStructureInfoKHR* pInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    void copyMemoryToAccelerationStructureKHR( const CopyMemoryToAccelerationStructureInfoKHR & info, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
     void copyQueryPoolResults( VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, VULKAN_HPP_NAMESPACE::Buffer dstBuffer, VULKAN_HPP_NAMESPACE::DeviceSize dstOffset, VULKAN_HPP_NAMESPACE::DeviceSize stride, VULKAN_HPP_NAMESPACE::QueryResultFlags flags, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 
@@ -15179,6 +15795,13 @@
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    void executeGeneratedCommandsNV( VULKAN_HPP_NAMESPACE::Bool32 isPreprocessed, const VULKAN_HPP_NAMESPACE::GeneratedCommandsInfoNV* pGeneratedCommandsInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    void executeGeneratedCommandsNV( VULKAN_HPP_NAMESPACE::Bool32 isPreprocessed, const GeneratedCommandsInfoNV & generatedCommandsInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
     void fillBuffer( VULKAN_HPP_NAMESPACE::Buffer dstBuffer, VULKAN_HPP_NAMESPACE::DeviceSize dstOffset, VULKAN_HPP_NAMESPACE::DeviceSize size, uint32_t data, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
@@ -15213,10 +15836,10 @@
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    void processCommandsNVX( const VULKAN_HPP_NAMESPACE::CmdProcessCommandsInfoNVX* pProcessCommandsInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+    void preprocessGeneratedCommandsNV( const VULKAN_HPP_NAMESPACE::GeneratedCommandsInfoNV* pGeneratedCommandsInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    void processCommandsNVX( const CmdProcessCommandsInfoNVX & processCommandsInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+    void preprocessGeneratedCommandsNV( const GeneratedCommandsInfoNV & generatedCommandsInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
@@ -15237,13 +15860,6 @@
     void pushDescriptorSetWithTemplateKHR( VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate descriptorUpdateTemplate, VULKAN_HPP_NAMESPACE::PipelineLayout layout, uint32_t set, const void* pData, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    void reserveSpaceForCommandsNVX( const VULKAN_HPP_NAMESPACE::CmdReserveSpaceForCommandsInfoNVX* pReserveSpaceInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
-#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
-    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    void reserveSpaceForCommandsNVX( const CmdReserveSpaceForCommandsInfoNVX & reserveSpaceInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
-#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
-
-    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
     void resetEvent( VULKAN_HPP_NAMESPACE::Event event, VULKAN_HPP_NAMESPACE::PipelineStageFlags stageMask, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
@@ -15369,6 +15985,24 @@
     void setViewportWScalingNV( uint32_t firstViewport, ArrayProxy<const VULKAN_HPP_NAMESPACE::ViewportWScalingNV> viewportWScalings, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    void traceRaysIndirectKHR( const VULKAN_HPP_NAMESPACE::StridedBufferRegionKHR* pRaygenShaderBindingTable, const VULKAN_HPP_NAMESPACE::StridedBufferRegionKHR* pMissShaderBindingTable, const VULKAN_HPP_NAMESPACE::StridedBufferRegionKHR* pHitShaderBindingTable, const VULKAN_HPP_NAMESPACE::StridedBufferRegionKHR* pCallableShaderBindingTable, VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    void traceRaysIndirectKHR( const StridedBufferRegionKHR & raygenShaderBindingTable, const StridedBufferRegionKHR & missShaderBindingTable, const StridedBufferRegionKHR & hitShaderBindingTable, const StridedBufferRegionKHR & callableShaderBindingTable, VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    void traceRaysKHR( const VULKAN_HPP_NAMESPACE::StridedBufferRegionKHR* pRaygenShaderBindingTable, const VULKAN_HPP_NAMESPACE::StridedBufferRegionKHR* pMissShaderBindingTable, const VULKAN_HPP_NAMESPACE::StridedBufferRegionKHR* pHitShaderBindingTable, const VULKAN_HPP_NAMESPACE::StridedBufferRegionKHR* pCallableShaderBindingTable, uint32_t width, uint32_t height, uint32_t depth, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    void traceRaysKHR( const StridedBufferRegionKHR & raygenShaderBindingTable, const StridedBufferRegionKHR & missShaderBindingTable, const StridedBufferRegionKHR & hitShaderBindingTable, const StridedBufferRegionKHR & callableShaderBindingTable, uint32_t width, uint32_t height, uint32_t depth, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
     void traceRaysNV( VULKAN_HPP_NAMESPACE::Buffer raygenShaderBindingTableBuffer, VULKAN_HPP_NAMESPACE::DeviceSize raygenShaderBindingOffset, VULKAN_HPP_NAMESPACE::Buffer missShaderBindingTableBuffer, VULKAN_HPP_NAMESPACE::DeviceSize missShaderBindingOffset, VULKAN_HPP_NAMESPACE::DeviceSize missShaderBindingStride, VULKAN_HPP_NAMESPACE::Buffer hitShaderBindingTableBuffer, VULKAN_HPP_NAMESPACE::DeviceSize hitShaderBindingOffset, VULKAN_HPP_NAMESPACE::DeviceSize hitShaderBindingStride, VULKAN_HPP_NAMESPACE::Buffer callableShaderBindingTableBuffer, VULKAN_HPP_NAMESPACE::DeviceSize callableShaderBindingOffset, VULKAN_HPP_NAMESPACE::DeviceSize callableShaderBindingStride, uint32_t width, uint32_t height, uint32_t depth, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 
@@ -15387,10 +16021,17 @@
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    void writeAccelerationStructuresPropertiesNV( uint32_t accelerationStructureCount, const VULKAN_HPP_NAMESPACE::AccelerationStructureNV* pAccelerationStructures, VULKAN_HPP_NAMESPACE::QueryType queryType, VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t firstQuery, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+    void writeAccelerationStructuresPropertiesKHR( uint32_t accelerationStructureCount, const VULKAN_HPP_NAMESPACE::AccelerationStructureKHR* pAccelerationStructures, VULKAN_HPP_NAMESPACE::QueryType queryType, VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t firstQuery, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    void writeAccelerationStructuresPropertiesNV( ArrayProxy<const VULKAN_HPP_NAMESPACE::AccelerationStructureNV> accelerationStructures, VULKAN_HPP_NAMESPACE::QueryType queryType, VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t firstQuery, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+    void writeAccelerationStructuresPropertiesKHR( ArrayProxy<const VULKAN_HPP_NAMESPACE::AccelerationStructureKHR> accelerationStructures, VULKAN_HPP_NAMESPACE::QueryType queryType, VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t firstQuery, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    void writeAccelerationStructuresPropertiesNV( uint32_t accelerationStructureCount, const VULKAN_HPP_NAMESPACE::AccelerationStructureKHR* pAccelerationStructures, VULKAN_HPP_NAMESPACE::QueryType queryType, VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t firstQuery, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    void writeAccelerationStructuresPropertiesNV( ArrayProxy<const VULKAN_HPP_NAMESPACE::AccelerationStructureKHR> accelerationStructures, VULKAN_HPP_NAMESPACE::QueryType queryType, VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t firstQuery, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
@@ -15757,6 +16398,87 @@
     using type = PipelineCache;
   };
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  class DeferredOperationKHR
+  {
+  public:
+    using CType = VkDeferredOperationKHR;
+
+    static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::eDeferredOperationKHR;
+
+  public:
+    VULKAN_HPP_CONSTEXPR DeferredOperationKHR() VULKAN_HPP_NOEXCEPT
+      : m_deferredOperationKHR(VK_NULL_HANDLE)
+    {}
+
+    VULKAN_HPP_CONSTEXPR DeferredOperationKHR( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+      : m_deferredOperationKHR(VK_NULL_HANDLE)
+    {}
+
+    VULKAN_HPP_TYPESAFE_EXPLICIT DeferredOperationKHR( VkDeferredOperationKHR deferredOperationKHR ) VULKAN_HPP_NOEXCEPT
+      : m_deferredOperationKHR( deferredOperationKHR )
+    {}
+
+#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
+    DeferredOperationKHR & operator=(VkDeferredOperationKHR deferredOperationKHR) VULKAN_HPP_NOEXCEPT
+    {
+      m_deferredOperationKHR = deferredOperationKHR;
+      return *this;
+    }
+#endif
+
+    DeferredOperationKHR & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+    {
+      m_deferredOperationKHR = VK_NULL_HANDLE;
+      return *this;
+    }
+
+#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
+    auto operator<=>( DeferredOperationKHR const& ) const = default;
+#else
+    bool operator==( DeferredOperationKHR const & rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return m_deferredOperationKHR == rhs.m_deferredOperationKHR;
+    }
+
+    bool operator!=(DeferredOperationKHR const & rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return m_deferredOperationKHR != rhs.m_deferredOperationKHR;
+    }
+
+    bool operator<(DeferredOperationKHR const & rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return m_deferredOperationKHR < rhs.m_deferredOperationKHR;
+    }
+#endif
+
+    VULKAN_HPP_TYPESAFE_EXPLICIT operator VkDeferredOperationKHR() const VULKAN_HPP_NOEXCEPT
+    {
+      return m_deferredOperationKHR;
+    }
+
+    explicit operator bool() const VULKAN_HPP_NOEXCEPT
+    {
+      return m_deferredOperationKHR != VK_NULL_HANDLE;
+    }
+
+    bool operator!() const VULKAN_HPP_NOEXCEPT
+    {
+      return m_deferredOperationKHR == VK_NULL_HANDLE;
+    }
+
+  private:
+    VkDeferredOperationKHR m_deferredOperationKHR;
+  };
+  static_assert( sizeof( DeferredOperationKHR ) == sizeof( VkDeferredOperationKHR ), "handle and wrapper have different size!" );
+
+  template <>
+  struct cpp_type<ObjectType::eDeferredOperationKHR>
+  {
+    using type = DeferredOperationKHR;
+  };
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
   class DescriptorPool
   {
   public:
@@ -15994,162 +16716,83 @@
     using type = Framebuffer;
   };
 
-  class IndirectCommandsLayoutNVX
+  class IndirectCommandsLayoutNV
   {
   public:
-    using CType = VkIndirectCommandsLayoutNVX;
+    using CType = VkIndirectCommandsLayoutNV;
 
-    static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::eIndirectCommandsLayoutNVX;
+    static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::eIndirectCommandsLayoutNV;
 
   public:
-    VULKAN_HPP_CONSTEXPR IndirectCommandsLayoutNVX() VULKAN_HPP_NOEXCEPT
-      : m_indirectCommandsLayoutNVX(VK_NULL_HANDLE)
+    VULKAN_HPP_CONSTEXPR IndirectCommandsLayoutNV() VULKAN_HPP_NOEXCEPT
+      : m_indirectCommandsLayoutNV(VK_NULL_HANDLE)
     {}
 
-    VULKAN_HPP_CONSTEXPR IndirectCommandsLayoutNVX( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
-      : m_indirectCommandsLayoutNVX(VK_NULL_HANDLE)
+    VULKAN_HPP_CONSTEXPR IndirectCommandsLayoutNV( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+      : m_indirectCommandsLayoutNV(VK_NULL_HANDLE)
     {}
 
-    VULKAN_HPP_TYPESAFE_EXPLICIT IndirectCommandsLayoutNVX( VkIndirectCommandsLayoutNVX indirectCommandsLayoutNVX ) VULKAN_HPP_NOEXCEPT
-      : m_indirectCommandsLayoutNVX( indirectCommandsLayoutNVX )
+    VULKAN_HPP_TYPESAFE_EXPLICIT IndirectCommandsLayoutNV( VkIndirectCommandsLayoutNV indirectCommandsLayoutNV ) VULKAN_HPP_NOEXCEPT
+      : m_indirectCommandsLayoutNV( indirectCommandsLayoutNV )
     {}
 
 #if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
-    IndirectCommandsLayoutNVX & operator=(VkIndirectCommandsLayoutNVX indirectCommandsLayoutNVX) VULKAN_HPP_NOEXCEPT
+    IndirectCommandsLayoutNV & operator=(VkIndirectCommandsLayoutNV indirectCommandsLayoutNV) VULKAN_HPP_NOEXCEPT
     {
-      m_indirectCommandsLayoutNVX = indirectCommandsLayoutNVX;
+      m_indirectCommandsLayoutNV = indirectCommandsLayoutNV;
       return *this;
     }
 #endif
 
-    IndirectCommandsLayoutNVX & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
+    IndirectCommandsLayoutNV & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
     {
-      m_indirectCommandsLayoutNVX = VK_NULL_HANDLE;
+      m_indirectCommandsLayoutNV = VK_NULL_HANDLE;
       return *this;
     }
 
 #if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
-    auto operator<=>( IndirectCommandsLayoutNVX const& ) const = default;
+    auto operator<=>( IndirectCommandsLayoutNV const& ) const = default;
 #else
-    bool operator==( IndirectCommandsLayoutNVX const & rhs ) const VULKAN_HPP_NOEXCEPT
+    bool operator==( IndirectCommandsLayoutNV const & rhs ) const VULKAN_HPP_NOEXCEPT
     {
-      return m_indirectCommandsLayoutNVX == rhs.m_indirectCommandsLayoutNVX;
+      return m_indirectCommandsLayoutNV == rhs.m_indirectCommandsLayoutNV;
     }
 
-    bool operator!=(IndirectCommandsLayoutNVX const & rhs ) const VULKAN_HPP_NOEXCEPT
+    bool operator!=(IndirectCommandsLayoutNV const & rhs ) const VULKAN_HPP_NOEXCEPT
     {
-      return m_indirectCommandsLayoutNVX != rhs.m_indirectCommandsLayoutNVX;
+      return m_indirectCommandsLayoutNV != rhs.m_indirectCommandsLayoutNV;
     }
 
-    bool operator<(IndirectCommandsLayoutNVX const & rhs ) const VULKAN_HPP_NOEXCEPT
+    bool operator<(IndirectCommandsLayoutNV const & rhs ) const VULKAN_HPP_NOEXCEPT
     {
-      return m_indirectCommandsLayoutNVX < rhs.m_indirectCommandsLayoutNVX;
+      return m_indirectCommandsLayoutNV < rhs.m_indirectCommandsLayoutNV;
     }
 #endif
 
-    VULKAN_HPP_TYPESAFE_EXPLICIT operator VkIndirectCommandsLayoutNVX() const VULKAN_HPP_NOEXCEPT
+    VULKAN_HPP_TYPESAFE_EXPLICIT operator VkIndirectCommandsLayoutNV() const VULKAN_HPP_NOEXCEPT
     {
-      return m_indirectCommandsLayoutNVX;
+      return m_indirectCommandsLayoutNV;
     }
 
     explicit operator bool() const VULKAN_HPP_NOEXCEPT
     {
-      return m_indirectCommandsLayoutNVX != VK_NULL_HANDLE;
+      return m_indirectCommandsLayoutNV != VK_NULL_HANDLE;
     }
 
     bool operator!() const VULKAN_HPP_NOEXCEPT
     {
-      return m_indirectCommandsLayoutNVX == VK_NULL_HANDLE;
+      return m_indirectCommandsLayoutNV == VK_NULL_HANDLE;
     }
 
   private:
-    VkIndirectCommandsLayoutNVX m_indirectCommandsLayoutNVX;
+    VkIndirectCommandsLayoutNV m_indirectCommandsLayoutNV;
   };
-  static_assert( sizeof( IndirectCommandsLayoutNVX ) == sizeof( VkIndirectCommandsLayoutNVX ), "handle and wrapper have different size!" );
+  static_assert( sizeof( IndirectCommandsLayoutNV ) == sizeof( VkIndirectCommandsLayoutNV ), "handle and wrapper have different size!" );
 
   template <>
-  struct cpp_type<ObjectType::eIndirectCommandsLayoutNVX>
+  struct cpp_type<ObjectType::eIndirectCommandsLayoutNV>
   {
-    using type = IndirectCommandsLayoutNVX;
-  };
-
-  class ObjectTableNVX
-  {
-  public:
-    using CType = VkObjectTableNVX;
-
-    static VULKAN_HPP_CONST_OR_CONSTEXPR ObjectType objectType = ObjectType::eObjectTableNVX;
-
-  public:
-    VULKAN_HPP_CONSTEXPR ObjectTableNVX() VULKAN_HPP_NOEXCEPT
-      : m_objectTableNVX(VK_NULL_HANDLE)
-    {}
-
-    VULKAN_HPP_CONSTEXPR ObjectTableNVX( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
-      : m_objectTableNVX(VK_NULL_HANDLE)
-    {}
-
-    VULKAN_HPP_TYPESAFE_EXPLICIT ObjectTableNVX( VkObjectTableNVX objectTableNVX ) VULKAN_HPP_NOEXCEPT
-      : m_objectTableNVX( objectTableNVX )
-    {}
-
-#if defined(VULKAN_HPP_TYPESAFE_CONVERSION)
-    ObjectTableNVX & operator=(VkObjectTableNVX objectTableNVX) VULKAN_HPP_NOEXCEPT
-    {
-      m_objectTableNVX = objectTableNVX;
-      return *this;
-    }
-#endif
-
-    ObjectTableNVX & operator=( std::nullptr_t ) VULKAN_HPP_NOEXCEPT
-    {
-      m_objectTableNVX = VK_NULL_HANDLE;
-      return *this;
-    }
-
-#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
-    auto operator<=>( ObjectTableNVX const& ) const = default;
-#else
-    bool operator==( ObjectTableNVX const & rhs ) const VULKAN_HPP_NOEXCEPT
-    {
-      return m_objectTableNVX == rhs.m_objectTableNVX;
-    }
-
-    bool operator!=(ObjectTableNVX const & rhs ) const VULKAN_HPP_NOEXCEPT
-    {
-      return m_objectTableNVX != rhs.m_objectTableNVX;
-    }
-
-    bool operator<(ObjectTableNVX const & rhs ) const VULKAN_HPP_NOEXCEPT
-    {
-      return m_objectTableNVX < rhs.m_objectTableNVX;
-    }
-#endif
-
-    VULKAN_HPP_TYPESAFE_EXPLICIT operator VkObjectTableNVX() const VULKAN_HPP_NOEXCEPT
-    {
-      return m_objectTableNVX;
-    }
-
-    explicit operator bool() const VULKAN_HPP_NOEXCEPT
-    {
-      return m_objectTableNVX != VK_NULL_HANDLE;
-    }
-
-    bool operator!() const VULKAN_HPP_NOEXCEPT
-    {
-      return m_objectTableNVX == VK_NULL_HANDLE;
-    }
-
-  private:
-    VkObjectTableNVX m_objectTableNVX;
-  };
-  static_assert( sizeof( ObjectTableNVX ) == sizeof( VkObjectTableNVX ), "handle and wrapper have different size!" );
-
-  template <>
-  struct cpp_type<ObjectType::eObjectTableNVX>
-  {
-    using type = ObjectTableNVX;
+    using type = IndirectCommandsLayoutNV;
   };
 
   class RenderPass
@@ -16692,8 +17335,9 @@
 
 #ifndef VULKAN_HPP_NO_SMART_HANDLE
   class Device;
-  template <typename Dispatch> class UniqueHandleTraits<AccelerationStructureNV, Dispatch> { public: using deleter = ObjectDestroy<Device, Dispatch>; };
-  using UniqueAccelerationStructureNV = UniqueHandle<AccelerationStructureNV, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
+  template <typename Dispatch> class UniqueHandleTraits<AccelerationStructureKHR, Dispatch> { public: using deleter = ObjectDestroy<Device, Dispatch>; };
+  using UniqueAccelerationStructureKHR = UniqueHandle<AccelerationStructureKHR, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
+  using UniqueAccelerationStructureNV = UniqueHandle<AccelerationStructureKHR, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
   template <typename Dispatch> class UniqueHandleTraits<Buffer, Dispatch> { public: using deleter = ObjectDestroy<Device, Dispatch>; };
   using UniqueBuffer = UniqueHandle<Buffer, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
   template <typename Dispatch> class UniqueHandleTraits<BufferView, Dispatch> { public: using deleter = ObjectDestroy<Device, Dispatch>; };
@@ -16702,6 +17346,10 @@
   using UniqueCommandBuffer = UniqueHandle<CommandBuffer, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
   template <typename Dispatch> class UniqueHandleTraits<CommandPool, Dispatch> { public: using deleter = ObjectDestroy<Device, Dispatch>; };
   using UniqueCommandPool = UniqueHandle<CommandPool, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  template <typename Dispatch> class UniqueHandleTraits<DeferredOperationKHR, Dispatch> { public: using deleter = ObjectDestroy<Device, Dispatch>; };
+  using UniqueDeferredOperationKHR = UniqueHandle<DeferredOperationKHR, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
   template <typename Dispatch> class UniqueHandleTraits<DescriptorPool, Dispatch> { public: using deleter = ObjectDestroy<Device, Dispatch>; };
   using UniqueDescriptorPool = UniqueHandle<DescriptorPool, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
   template <typename Dispatch> class UniqueHandleTraits<DescriptorSet, Dispatch> { public: using deleter = PoolFree<Device, DescriptorPool, Dispatch>; };
@@ -16723,10 +17371,8 @@
   using UniqueImage = UniqueHandle<Image, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
   template <typename Dispatch> class UniqueHandleTraits<ImageView, Dispatch> { public: using deleter = ObjectDestroy<Device, Dispatch>; };
   using UniqueImageView = UniqueHandle<ImageView, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
-  template <typename Dispatch> class UniqueHandleTraits<IndirectCommandsLayoutNVX, Dispatch> { public: using deleter = ObjectDestroy<Device, Dispatch>; };
-  using UniqueIndirectCommandsLayoutNVX = UniqueHandle<IndirectCommandsLayoutNVX, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
-  template <typename Dispatch> class UniqueHandleTraits<ObjectTableNVX, Dispatch> { public: using deleter = ObjectDestroy<Device, Dispatch>; };
-  using UniqueObjectTableNVX = UniqueHandle<ObjectTableNVX, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
+  template <typename Dispatch> class UniqueHandleTraits<IndirectCommandsLayoutNV, Dispatch> { public: using deleter = ObjectDestroy<Device, Dispatch>; };
+  using UniqueIndirectCommandsLayoutNV = UniqueHandle<IndirectCommandsLayoutNV, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
   template <typename Dispatch> class UniqueHandleTraits<Pipeline, Dispatch> { public: using deleter = ObjectDestroy<Device, Dispatch>; };
   using UniquePipeline = UniqueHandle<Pipeline, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>;
   template <typename Dispatch> class UniqueHandleTraits<PipelineCache, Dispatch> { public: using deleter = ObjectDestroy<Device, Dispatch>; };
@@ -16885,10 +17531,17 @@
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    Result bindAccelerationStructureMemoryNV( uint32_t bindInfoCount, const VULKAN_HPP_NAMESPACE::BindAccelerationStructureMemoryInfoNV* pBindInfos, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+    Result bindAccelerationStructureMemoryKHR( uint32_t bindInfoCount, const VULKAN_HPP_NAMESPACE::BindAccelerationStructureMemoryInfoKHR* pBindInfos, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    typename ResultValueType<void>::type bindAccelerationStructureMemoryNV( ArrayProxy<const VULKAN_HPP_NAMESPACE::BindAccelerationStructureMemoryInfoNV> bindInfos, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+    typename ResultValueType<void>::type bindAccelerationStructureMemoryKHR( ArrayProxy<const VULKAN_HPP_NAMESPACE::BindAccelerationStructureMemoryInfoKHR> bindInfos, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    Result bindAccelerationStructureMemoryNV( uint32_t bindInfoCount, const VULKAN_HPP_NAMESPACE::BindAccelerationStructureMemoryInfoKHR* pBindInfos, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    typename ResultValueType<void>::type bindAccelerationStructureMemoryNV( ArrayProxy<const VULKAN_HPP_NAMESPACE::BindAccelerationStructureMemoryInfoKHR> bindInfos, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
 #ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
@@ -16935,6 +17588,15 @@
     typename ResultValueType<void>::type bindImageMemory2KHR( ArrayProxy<const VULKAN_HPP_NAMESPACE::BindImageMemoryInfo> bindInfos, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    Result buildAccelerationStructureKHR( uint32_t infoCount, const VULKAN_HPP_NAMESPACE::AccelerationStructureBuildGeometryInfoKHR* pInfos, const VULKAN_HPP_NAMESPACE::AccelerationStructureBuildOffsetInfoKHR* const* ppOffsetInfos, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    Result buildAccelerationStructureKHR( ArrayProxy<const VULKAN_HPP_NAMESPACE::AccelerationStructureBuildGeometryInfoKHR> infos, ArrayProxy<const VULKAN_HPP_NAMESPACE::AccelerationStructureBuildOffsetInfoKHR* const> pOffsetInfos, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
 #ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
     Result compileDeferredNV( VULKAN_HPP_NAMESPACE::Pipeline pipeline, uint32_t shader, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
@@ -16943,6 +17605,46 @@
     typename ResultValueType<void>::type compileDeferredNV( VULKAN_HPP_NAMESPACE::Pipeline pipeline, uint32_t shader, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    Result copyAccelerationStructureKHR( const VULKAN_HPP_NAMESPACE::CopyAccelerationStructureInfoKHR* pInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    Result copyAccelerationStructureKHR( const CopyAccelerationStructureInfoKHR & info, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    Result copyAccelerationStructureToMemoryKHR( const VULKAN_HPP_NAMESPACE::CopyAccelerationStructureToMemoryInfoKHR* pInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    Result copyAccelerationStructureToMemoryKHR( const CopyAccelerationStructureToMemoryInfoKHR & info, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    Result copyMemoryToAccelerationStructureKHR( const VULKAN_HPP_NAMESPACE::CopyMemoryToAccelerationStructureInfoKHR* pInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    Result copyMemoryToAccelerationStructureKHR( const CopyMemoryToAccelerationStructureInfoKHR & info, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    Result createAccelerationStructureKHR( const VULKAN_HPP_NAMESPACE::AccelerationStructureCreateInfoKHR* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::AccelerationStructureKHR* pAccelerationStructure, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    typename ResultValueType<VULKAN_HPP_NAMESPACE::AccelerationStructureKHR>::type createAccelerationStructureKHR( const AccelerationStructureCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    typename ResultValueType<UniqueHandle<AccelerationStructureKHR,Dispatch>>::type createAccelerationStructureKHRUnique( const AccelerationStructureCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
     Result createAccelerationStructureNV( const VULKAN_HPP_NAMESPACE::AccelerationStructureCreateInfoNV* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::AccelerationStructureNV* pAccelerationStructure, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
@@ -16991,21 +17693,34 @@
     Result createComputePipelines( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, uint32_t createInfoCount, const VULKAN_HPP_NAMESPACE::ComputePipelineCreateInfo* pCreateInfos, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::Pipeline* pPipelines, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
     template<typename Allocator = std::allocator<Pipeline>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    typename ResultValueType<std::vector<Pipeline,Allocator>>::type createComputePipelines( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::ComputePipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+    ResultValue<std::vector<Pipeline,Allocator>> createComputePipelines( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::ComputePipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
     template<typename Allocator = std::allocator<Pipeline>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    typename ResultValueType<std::vector<Pipeline,Allocator>>::type createComputePipelines( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::ComputePipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const;
+    ResultValue<std::vector<Pipeline,Allocator>> createComputePipelines( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::ComputePipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const;
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    typename ResultValueType<Pipeline>::type createComputePipeline( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const ComputePipelineCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+    ResultValue<Pipeline> createComputePipeline( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const ComputePipelineCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
 #ifndef VULKAN_HPP_NO_SMART_HANDLE
     template<typename Allocator = std::allocator<UniquePipeline>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    typename ResultValueType<std::vector<UniqueHandle<Pipeline,Dispatch>,Allocator>>::type createComputePipelinesUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::ComputePipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+    ResultValue<std::vector<UniqueHandle<Pipeline,Dispatch>,Allocator>> createComputePipelinesUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::ComputePipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
     template<typename Allocator = std::allocator<UniquePipeline>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    typename ResultValueType<std::vector<UniqueHandle<Pipeline,Dispatch>,Allocator>>::type createComputePipelinesUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::ComputePipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const;
+    ResultValue<std::vector<UniqueHandle<Pipeline,Dispatch>,Allocator>> createComputePipelinesUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::ComputePipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const;
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    typename ResultValueType<UniqueHandle<Pipeline,Dispatch>>::type createComputePipelineUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const ComputePipelineCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+    ResultValue<UniqueHandle<Pipeline,Dispatch>> createComputePipelineUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const ComputePipelineCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
 #endif /*VULKAN_HPP_NO_SMART_HANDLE*/
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    Result createDeferredOperationKHR( const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::DeferredOperationKHR* pDeferredOperation, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    typename ResultValueType<VULKAN_HPP_NAMESPACE::DeferredOperationKHR>::type createDeferredOperationKHR( Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    typename ResultValueType<UniqueHandle<DeferredOperationKHR,Dispatch>>::type createDeferredOperationKHRUnique( Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
     Result createDescriptorPool( const VULKAN_HPP_NAMESPACE::DescriptorPoolCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::DescriptorPool* pDescriptorPool, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
@@ -17087,18 +17802,18 @@
     Result createGraphicsPipelines( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, uint32_t createInfoCount, const VULKAN_HPP_NAMESPACE::GraphicsPipelineCreateInfo* pCreateInfos, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::Pipeline* pPipelines, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
     template<typename Allocator = std::allocator<Pipeline>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    typename ResultValueType<std::vector<Pipeline,Allocator>>::type createGraphicsPipelines( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::GraphicsPipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+    ResultValue<std::vector<Pipeline,Allocator>> createGraphicsPipelines( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::GraphicsPipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
     template<typename Allocator = std::allocator<Pipeline>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    typename ResultValueType<std::vector<Pipeline,Allocator>>::type createGraphicsPipelines( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::GraphicsPipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const;
+    ResultValue<std::vector<Pipeline,Allocator>> createGraphicsPipelines( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::GraphicsPipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const;
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    typename ResultValueType<Pipeline>::type createGraphicsPipeline( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const GraphicsPipelineCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+    ResultValue<Pipeline> createGraphicsPipeline( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const GraphicsPipelineCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
 #ifndef VULKAN_HPP_NO_SMART_HANDLE
     template<typename Allocator = std::allocator<UniquePipeline>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    typename ResultValueType<std::vector<UniqueHandle<Pipeline,Dispatch>,Allocator>>::type createGraphicsPipelinesUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::GraphicsPipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+    ResultValue<std::vector<UniqueHandle<Pipeline,Dispatch>,Allocator>> createGraphicsPipelinesUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::GraphicsPipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
     template<typename Allocator = std::allocator<UniquePipeline>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    typename ResultValueType<std::vector<UniqueHandle<Pipeline,Dispatch>,Allocator>>::type createGraphicsPipelinesUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::GraphicsPipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const;
+    ResultValue<std::vector<UniqueHandle<Pipeline,Dispatch>,Allocator>> createGraphicsPipelinesUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::GraphicsPipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const;
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    typename ResultValueType<UniqueHandle<Pipeline,Dispatch>>::type createGraphicsPipelineUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const GraphicsPipelineCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+    ResultValue<UniqueHandle<Pipeline,Dispatch>> createGraphicsPipelineUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const GraphicsPipelineCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
 #endif /*VULKAN_HPP_NO_SMART_HANDLE*/
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
@@ -17125,24 +17840,13 @@
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    Result createIndirectCommandsLayoutNVX( const VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutCreateInfoNVX* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNVX* pIndirectCommandsLayout, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+    Result createIndirectCommandsLayoutNV( const VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutCreateInfoNV* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNV* pIndirectCommandsLayout, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    typename ResultValueType<VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNVX>::type createIndirectCommandsLayoutNVX( const IndirectCommandsLayoutCreateInfoNVX & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+    typename ResultValueType<VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNV>::type createIndirectCommandsLayoutNV( const IndirectCommandsLayoutCreateInfoNV & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
 #ifndef VULKAN_HPP_NO_SMART_HANDLE
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    typename ResultValueType<UniqueHandle<IndirectCommandsLayoutNVX,Dispatch>>::type createIndirectCommandsLayoutNVXUnique( const IndirectCommandsLayoutCreateInfoNVX & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
-#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
-#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
-
-    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    Result createObjectTableNVX( const VULKAN_HPP_NAMESPACE::ObjectTableCreateInfoNVX* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::ObjectTableNVX* pObjectTable, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
-#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
-    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    typename ResultValueType<VULKAN_HPP_NAMESPACE::ObjectTableNVX>::type createObjectTableNVX( const ObjectTableCreateInfoNVX & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
-#ifndef VULKAN_HPP_NO_SMART_HANDLE
-    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    typename ResultValueType<UniqueHandle<ObjectTableNVX,Dispatch>>::type createObjectTableNVXUnique( const ObjectTableCreateInfoNVX & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+    typename ResultValueType<UniqueHandle<IndirectCommandsLayoutNV,Dispatch>>::type createIndirectCommandsLayoutNVUnique( const IndirectCommandsLayoutCreateInfoNV & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
 #endif /*VULKAN_HPP_NO_SMART_HANDLE*/
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
@@ -17179,22 +17883,43 @@
 #endif /*VULKAN_HPP_NO_SMART_HANDLE*/
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    Result createRayTracingPipelinesKHR( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, uint32_t createInfoCount, const VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoKHR* pCreateInfos, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::Pipeline* pPipelines, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+    template<typename Allocator = std::allocator<Pipeline>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    ResultValue<std::vector<Pipeline,Allocator>> createRayTracingPipelinesKHR( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoKHR> createInfos, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+    template<typename Allocator = std::allocator<Pipeline>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    ResultValue<std::vector<Pipeline,Allocator>> createRayTracingPipelinesKHR( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoKHR> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const;
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    ResultValue<Pipeline> createRayTracingPipelineKHR( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const RayTracingPipelineCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+    template<typename Allocator = std::allocator<UniquePipeline>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    ResultValue<std::vector<UniqueHandle<Pipeline,Dispatch>,Allocator>> createRayTracingPipelinesKHRUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoKHR> createInfos, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+    template<typename Allocator = std::allocator<UniquePipeline>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    ResultValue<std::vector<UniqueHandle<Pipeline,Dispatch>,Allocator>> createRayTracingPipelinesKHRUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoKHR> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const;
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    ResultValue<UniqueHandle<Pipeline,Dispatch>> createRayTracingPipelineKHRUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const RayTracingPipelineCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
     Result createRayTracingPipelinesNV( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, uint32_t createInfoCount, const VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoNV* pCreateInfos, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::Pipeline* pPipelines, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
     template<typename Allocator = std::allocator<Pipeline>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    typename ResultValueType<std::vector<Pipeline,Allocator>>::type createRayTracingPipelinesNV( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoNV> createInfos, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+    ResultValue<std::vector<Pipeline,Allocator>> createRayTracingPipelinesNV( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoNV> createInfos, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
     template<typename Allocator = std::allocator<Pipeline>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    typename ResultValueType<std::vector<Pipeline,Allocator>>::type createRayTracingPipelinesNV( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoNV> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const;
+    ResultValue<std::vector<Pipeline,Allocator>> createRayTracingPipelinesNV( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoNV> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const;
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    typename ResultValueType<Pipeline>::type createRayTracingPipelineNV( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const RayTracingPipelineCreateInfoNV & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+    ResultValue<Pipeline> createRayTracingPipelineNV( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const RayTracingPipelineCreateInfoNV & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
 #ifndef VULKAN_HPP_NO_SMART_HANDLE
     template<typename Allocator = std::allocator<UniquePipeline>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    typename ResultValueType<std::vector<UniqueHandle<Pipeline,Dispatch>,Allocator>>::type createRayTracingPipelinesNVUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoNV> createInfos, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+    ResultValue<std::vector<UniqueHandle<Pipeline,Dispatch>,Allocator>> createRayTracingPipelinesNVUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoNV> createInfos, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
     template<typename Allocator = std::allocator<UniquePipeline>, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    typename ResultValueType<std::vector<UniqueHandle<Pipeline,Dispatch>,Allocator>>::type createRayTracingPipelinesNVUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoNV> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const;
+    ResultValue<std::vector<UniqueHandle<Pipeline,Dispatch>,Allocator>> createRayTracingPipelinesNVUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoNV> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const;
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    typename ResultValueType<UniqueHandle<Pipeline,Dispatch>>::type createRayTracingPipelineNVUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const RayTracingPipelineCreateInfoNV & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+    ResultValue<UniqueHandle<Pipeline,Dispatch>> createRayTracingPipelineNVUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const RayTracingPipelineCreateInfoNV & createInfo, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
 #endif /*VULKAN_HPP_NO_SMART_HANDLE*/
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
@@ -17341,18 +18066,35 @@
     typename ResultValueType<void>::type debugMarkerSetObjectTagEXT( const DebugMarkerObjectTagInfoEXT & tagInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    void destroyAccelerationStructureNV( VULKAN_HPP_NAMESPACE::AccelerationStructureNV accelerationStructure, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+    Result deferredOperationJoinKHR( VULKAN_HPP_NAMESPACE::DeferredOperationKHR operation, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#else
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    Result deferredOperationJoinKHR( VULKAN_HPP_NAMESPACE::DeferredOperationKHR operation, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    void destroyAccelerationStructureKHR( VULKAN_HPP_NAMESPACE::AccelerationStructureKHR accelerationStructure, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    void destroyAccelerationStructureNV( VULKAN_HPP_NAMESPACE::AccelerationStructureNV accelerationStructure, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+    void destroyAccelerationStructureKHR( VULKAN_HPP_NAMESPACE::AccelerationStructureKHR accelerationStructure, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    void destroy( VULKAN_HPP_NAMESPACE::AccelerationStructureNV accelerationStructure, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+    void destroyAccelerationStructureNV( VULKAN_HPP_NAMESPACE::AccelerationStructureKHR accelerationStructure, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    void destroy( VULKAN_HPP_NAMESPACE::AccelerationStructureNV accelerationStructure, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+    void destroyAccelerationStructureNV( VULKAN_HPP_NAMESPACE::AccelerationStructureKHR accelerationStructure, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    void destroy( VULKAN_HPP_NAMESPACE::AccelerationStructureKHR accelerationStructure, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    void destroy( VULKAN_HPP_NAMESPACE::AccelerationStructureKHR accelerationStructure, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
@@ -17397,6 +18139,22 @@
     void destroy( VULKAN_HPP_NAMESPACE::CommandPool commandPool, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    void destroyDeferredOperationKHR( VULKAN_HPP_NAMESPACE::DeferredOperationKHR operation, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    void destroyDeferredOperationKHR( VULKAN_HPP_NAMESPACE::DeferredOperationKHR operation, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    void destroy( VULKAN_HPP_NAMESPACE::DeferredOperationKHR operation, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    void destroy( VULKAN_HPP_NAMESPACE::DeferredOperationKHR operation, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
     void destroyDescriptorPool( VULKAN_HPP_NAMESPACE::DescriptorPool descriptorPool, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
@@ -17524,31 +18282,17 @@
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    void destroyIndirectCommandsLayoutNVX( VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNVX indirectCommandsLayout, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+    void destroyIndirectCommandsLayoutNV( VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNV indirectCommandsLayout, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    void destroyIndirectCommandsLayoutNVX( VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNVX indirectCommandsLayout, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+    void destroyIndirectCommandsLayoutNV( VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNV indirectCommandsLayout, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    void destroy( VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNVX indirectCommandsLayout, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+    void destroy( VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNV indirectCommandsLayout, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    void destroy( VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNVX indirectCommandsLayout, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
-#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
-
-    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    void destroyObjectTableNVX( VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
-#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
-    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    void destroyObjectTableNVX( VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
-#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
-
-    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    void destroy( VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
-#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
-    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    void destroy( VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+    void destroy( VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNV indirectCommandsLayout, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
@@ -17776,13 +18520,33 @@
     void free( VULKAN_HPP_NAMESPACE::DeviceMemory memory, Optional<const AllocationCallbacks> allocator = nullptr, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    Result getAccelerationStructureHandleNV( VULKAN_HPP_NAMESPACE::AccelerationStructureNV accelerationStructure, size_t dataSize, void* pData, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+    DeviceAddress getAccelerationStructureAddressKHR( const VULKAN_HPP_NAMESPACE::AccelerationStructureDeviceAddressInfoKHR* pInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    DeviceAddress getAccelerationStructureAddressKHR( const AccelerationStructureDeviceAddressInfoKHR & info, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    Result getAccelerationStructureHandleNV( VULKAN_HPP_NAMESPACE::AccelerationStructureKHR accelerationStructure, size_t dataSize, void* pData, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
     template<typename T, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    typename ResultValueType<void>::type getAccelerationStructureHandleNV( VULKAN_HPP_NAMESPACE::AccelerationStructureNV accelerationStructure, ArrayProxy<T> data, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+    typename ResultValueType<void>::type getAccelerationStructureHandleNV( VULKAN_HPP_NAMESPACE::AccelerationStructureKHR accelerationStructure, ArrayProxy<T> data, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    void getAccelerationStructureMemoryRequirementsKHR( const VULKAN_HPP_NAMESPACE::AccelerationStructureMemoryRequirementsInfoKHR* pInfo, VULKAN_HPP_NAMESPACE::MemoryRequirements2* pMemoryRequirements, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    VULKAN_HPP_NAMESPACE::MemoryRequirements2 getAccelerationStructureMemoryRequirementsKHR( const AccelerationStructureMemoryRequirementsInfoKHR & info, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+    template<typename X, typename Y, typename ...Z, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    StructureChain<X, Y, Z...> getAccelerationStructureMemoryRequirementsKHR( const AccelerationStructureMemoryRequirementsInfoKHR & info, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
     void getAccelerationStructureMemoryRequirementsNV( const VULKAN_HPP_NAMESPACE::AccelerationStructureMemoryRequirementsInfoNV* pInfo, VULKAN_HPP_NAMESPACE::MemoryRequirements2KHR* pMemoryRequirements, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
@@ -17870,6 +18634,21 @@
     typename ResultValueType<uint64_t>::type getCalibratedTimestampsEXT( ArrayProxy<const VULKAN_HPP_NAMESPACE::CalibratedTimestampInfoEXT> timestampInfos, ArrayProxy<uint64_t> timestamps, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    uint32_t getDeferredOperationMaxConcurrencyKHR( VULKAN_HPP_NAMESPACE::DeferredOperationKHR operation, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    Result getDeferredOperationResultKHR( VULKAN_HPP_NAMESPACE::DeferredOperationKHR operation, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#else
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    Result getDeferredOperationResultKHR( VULKAN_HPP_NAMESPACE::DeferredOperationKHR operation, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
     void getDescriptorSetLayoutSupport( const VULKAN_HPP_NAMESPACE::DescriptorSetLayoutCreateInfo* pCreateInfo, VULKAN_HPP_NAMESPACE::DescriptorSetLayoutSupport* pSupport, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
@@ -17888,6 +18667,15 @@
     StructureChain<X, Y, Z...> getDescriptorSetLayoutSupportKHR( const DescriptorSetLayoutCreateInfo & createInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    Result getAccelerationStructureCompatibilityKHR( const VULKAN_HPP_NAMESPACE::AccelerationStructureVersionKHR* version, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    typename ResultValueType<void>::type getAccelerationStructureCompatibilityKHR( const AccelerationStructureVersionKHR & version, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
     void getGroupPeerMemoryFeatures( uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VULKAN_HPP_NAMESPACE::PeerMemoryFeatureFlags* pPeerMemoryFeatures, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
@@ -18000,6 +18788,15 @@
 #endif /*VK_USE_PLATFORM_WIN32_KHR*/
 
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    void getGeneratedCommandsMemoryRequirementsNV( const VULKAN_HPP_NAMESPACE::GeneratedCommandsMemoryRequirementsInfoNV* pInfo, VULKAN_HPP_NAMESPACE::MemoryRequirements2* pMemoryRequirements, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    VULKAN_HPP_NAMESPACE::MemoryRequirements2 getGeneratedCommandsMemoryRequirementsNV( const GeneratedCommandsMemoryRequirementsInfoNV & info, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+    template<typename X, typename Y, typename ...Z, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    StructureChain<X, Y, Z...> getGeneratedCommandsMemoryRequirementsNV( const GeneratedCommandsMemoryRequirementsInfoNV & info, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
     Result getImageDrmFormatModifierPropertiesEXT( VULKAN_HPP_NAMESPACE::Image image, VULKAN_HPP_NAMESPACE::ImageDrmFormatModifierPropertiesEXT* pProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
@@ -18066,6 +18863,13 @@
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    Result getImageViewAddressNVX( VULKAN_HPP_NAMESPACE::ImageView imageView, VULKAN_HPP_NAMESPACE::ImageViewAddressPropertiesNVX* pProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    typename ResultValueType<VULKAN_HPP_NAMESPACE::ImageViewAddressPropertiesNVX>::type getImageViewAddressNVX( VULKAN_HPP_NAMESPACE::ImageView imageView, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
     uint32_t getImageViewHandleNVX( const VULKAN_HPP_NAMESPACE::ImageViewHandleInfoNVX* pInfo, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
@@ -18188,6 +18992,22 @@
     Result getQueryPoolResults( VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, ArrayProxy<T> data, VULKAN_HPP_NAMESPACE::DeviceSize stride, VULKAN_HPP_NAMESPACE::QueryResultFlags flags, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    Result getRayTracingCaptureReplayShaderGroupHandlesKHR( VULKAN_HPP_NAMESPACE::Pipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+    template<typename T, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    typename ResultValueType<void>::type getRayTracingCaptureReplayShaderGroupHandlesKHR( VULKAN_HPP_NAMESPACE::Pipeline pipeline, uint32_t firstGroup, uint32_t groupCount, ArrayProxy<T> data, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    Result getRayTracingShaderGroupHandlesKHR( VULKAN_HPP_NAMESPACE::Pipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+    template<typename T, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    typename ResultValueType<void>::type getRayTracingShaderGroupHandlesKHR( VULKAN_HPP_NAMESPACE::Pipeline pipeline, uint32_t firstGroup, uint32_t groupCount, ArrayProxy<T> data, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
     Result getRayTracingShaderGroupHandlesNV( VULKAN_HPP_NAMESPACE::Pipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
@@ -18370,13 +19190,6 @@
 #endif /*VULKAN_HPP_NO_SMART_HANDLE*/
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
-    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    Result registerObjectsNVX( VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable, uint32_t objectCount, const VULKAN_HPP_NAMESPACE::ObjectTableEntryNVX* const* ppObjectTableEntries, const uint32_t* pObjectIndices, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
-#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
-    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    typename ResultValueType<void>::type registerObjectsNVX( VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable, ArrayProxy<const VULKAN_HPP_NAMESPACE::ObjectTableEntryNVX* const> pObjectTableEntries, ArrayProxy<const uint32_t> objectIndices, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
-#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
-
 #ifdef VK_USE_PLATFORM_WIN32_KHR
 #ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
@@ -18494,13 +19307,6 @@
     void unmapMemory( VULKAN_HPP_NAMESPACE::DeviceMemory memory, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    Result unregisterObjectsNVX( VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable, uint32_t objectCount, const VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX* pObjectEntryTypes, const uint32_t* pObjectIndices, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
-#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
-    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    typename ResultValueType<void>::type unregisterObjectsNVX( VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable, ArrayProxy<const VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX> objectEntryTypes, ArrayProxy<const uint32_t> objectIndices, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
-#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
-
-    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
     void updateDescriptorSetWithTemplate( VULKAN_HPP_NAMESPACE::DescriptorSet descriptorSet, VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
@@ -18534,6 +19340,15 @@
     Result waitSemaphoresKHR( const SemaphoreWaitInfo & waitInfo, uint64_t timeout, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    Result writeAccelerationStructuresPropertiesKHR( uint32_t accelerationStructureCount, const VULKAN_HPP_NAMESPACE::AccelerationStructureKHR* pAccelerationStructures, VULKAN_HPP_NAMESPACE::QueryType queryType, size_t dataSize, void* pData, size_t stride, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+    template<typename T, typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
+    typename ResultValueType<void>::type writeAccelerationStructuresPropertiesKHR( ArrayProxy<const VULKAN_HPP_NAMESPACE::AccelerationStructureKHR> accelerationStructures, VULKAN_HPP_NAMESPACE::QueryType queryType, ArrayProxy<T> data, size_t stride, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const;
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
     VULKAN_HPP_TYPESAFE_EXPLICIT operator VkDevice() const VULKAN_HPP_NOEXCEPT
     {
       return m_device;
@@ -18946,13 +19761,6 @@
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    void getGeneratedCommandsPropertiesNVX( VULKAN_HPP_NAMESPACE::DeviceGeneratedCommandsFeaturesNVX* pFeatures, VULKAN_HPP_NAMESPACE::DeviceGeneratedCommandsLimitsNVX* pLimits, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
-#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
-    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
-    VULKAN_HPP_NAMESPACE::DeviceGeneratedCommandsLimitsNVX getGeneratedCommandsPropertiesNVX( DeviceGeneratedCommandsFeaturesNVX & features, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
-#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
-
-    template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
     Result getImageFormatProperties( VULKAN_HPP_NAMESPACE::Format format, VULKAN_HPP_NAMESPACE::ImageType type, VULKAN_HPP_NAMESPACE::ImageTiling tiling, VULKAN_HPP_NAMESPACE::ImageUsageFlags usage, VULKAN_HPP_NAMESPACE::ImageCreateFlags flags, VULKAN_HPP_NAMESPACE::ImageFormatProperties* pImageFormatProperties, Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER ) const VULKAN_HPP_NOEXCEPT;
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
     template<typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
@@ -19687,6 +20495,1045 @@
   typename ResultValueType<uint32_t>::type enumerateInstanceVersion(Dispatch const &d = VULKAN_HPP_DEFAULT_DISPATCHER );
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
+  struct AabbPositionsKHR
+  {
+    VULKAN_HPP_CONSTEXPR AabbPositionsKHR( float minX_ = {},
+                                           float minY_ = {},
+                                           float minZ_ = {},
+                                           float maxX_ = {},
+                                           float maxY_ = {},
+                                           float maxZ_ = {} ) VULKAN_HPP_NOEXCEPT
+      : minX( minX_ )
+      , minY( minY_ )
+      , minZ( minZ_ )
+      , maxX( maxX_ )
+      , maxY( maxY_ )
+      , maxZ( maxZ_ )
+    {}
+
+    AabbPositionsKHR( VkAabbPositionsKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    AabbPositionsKHR& operator=( VkAabbPositionsKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::AabbPositionsKHR const *>(&rhs);
+      return *this;
+    }
+
+    AabbPositionsKHR & setMinX( float minX_ ) VULKAN_HPP_NOEXCEPT
+    {
+      minX = minX_;
+      return *this;
+    }
+
+    AabbPositionsKHR & setMinY( float minY_ ) VULKAN_HPP_NOEXCEPT
+    {
+      minY = minY_;
+      return *this;
+    }
+
+    AabbPositionsKHR & setMinZ( float minZ_ ) VULKAN_HPP_NOEXCEPT
+    {
+      minZ = minZ_;
+      return *this;
+    }
+
+    AabbPositionsKHR & setMaxX( float maxX_ ) VULKAN_HPP_NOEXCEPT
+    {
+      maxX = maxX_;
+      return *this;
+    }
+
+    AabbPositionsKHR & setMaxY( float maxY_ ) VULKAN_HPP_NOEXCEPT
+    {
+      maxY = maxY_;
+      return *this;
+    }
+
+    AabbPositionsKHR & setMaxZ( float maxZ_ ) VULKAN_HPP_NOEXCEPT
+    {
+      maxZ = maxZ_;
+      return *this;
+    }
+
+    operator VkAabbPositionsKHR const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkAabbPositionsKHR*>( this );
+    }
+
+    operator VkAabbPositionsKHR &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkAabbPositionsKHR*>( this );
+    }
+
+#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
+    auto operator<=>( AabbPositionsKHR const& ) const = default;
+#else
+    bool operator==( AabbPositionsKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ( minX == rhs.minX )
+          && ( minY == rhs.minY )
+          && ( minZ == rhs.minZ )
+          && ( maxX == rhs.maxX )
+          && ( maxY == rhs.maxY )
+          && ( maxZ == rhs.maxZ );
+    }
+
+    bool operator!=( AabbPositionsKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return !operator==( rhs );
+    }
+#endif
+
+  public:
+    float minX = {};
+    float minY = {};
+    float minZ = {};
+    float maxX = {};
+    float maxY = {};
+    float maxZ = {};
+  };
+  static_assert( sizeof( AabbPositionsKHR ) == sizeof( VkAabbPositionsKHR ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<AabbPositionsKHR>::value, "struct wrapper is not a standard layout!" );
+
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  union DeviceOrHostAddressConstKHR
+  {
+    DeviceOrHostAddressConstKHR( VULKAN_HPP_NAMESPACE::DeviceOrHostAddressConstKHR const& rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      memcpy( static_cast<void*>(this), &rhs, sizeof( VULKAN_HPP_NAMESPACE::DeviceOrHostAddressConstKHR ) );
+    }
+
+    DeviceOrHostAddressConstKHR( VULKAN_HPP_NAMESPACE::DeviceAddress deviceAddress_ = {} )
+    {
+      deviceAddress = deviceAddress_;
+    }
+
+    DeviceOrHostAddressConstKHR( const void* hostAddress_ )
+    {
+      hostAddress = hostAddress_;
+    }
+
+    DeviceOrHostAddressConstKHR & setDeviceAddress( VULKAN_HPP_NAMESPACE::DeviceAddress deviceAddress_ ) VULKAN_HPP_NOEXCEPT
+    {
+      deviceAddress = deviceAddress_;
+      return *this;
+    }
+
+    DeviceOrHostAddressConstKHR & setHostAddress( const void* hostAddress_ ) VULKAN_HPP_NOEXCEPT
+    {
+      hostAddress = hostAddress_;
+      return *this;
+    }
+
+    VULKAN_HPP_NAMESPACE::DeviceOrHostAddressConstKHR & operator=( VULKAN_HPP_NAMESPACE::DeviceOrHostAddressConstKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      memcpy( static_cast<void*>(this), &rhs, sizeof( VULKAN_HPP_NAMESPACE::DeviceOrHostAddressConstKHR ) );
+      return *this;
+    }
+
+    operator VkDeviceOrHostAddressConstKHR const&() const
+    {
+      return *reinterpret_cast<const VkDeviceOrHostAddressConstKHR*>(this);
+    }
+
+    operator VkDeviceOrHostAddressConstKHR &()
+    {
+      return *reinterpret_cast<VkDeviceOrHostAddressConstKHR*>(this);
+    }
+
+#ifdef VULKAN_HPP_HAS_UNRESTRICTED_UNIONS
+    VULKAN_HPP_NAMESPACE::DeviceAddress deviceAddress;
+    const void* hostAddress;
+#else
+    VkDeviceAddress deviceAddress;
+    const void* hostAddress;
+#endif  /*VULKAN_HPP_HAS_UNRESTRICTED_UNIONS*/
+  };
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct AccelerationStructureGeometryTrianglesDataKHR
+  {
+    AccelerationStructureGeometryTrianglesDataKHR( VULKAN_HPP_NAMESPACE::Format vertexFormat_ = VULKAN_HPP_NAMESPACE::Format::eUndefined,
+                                                   VULKAN_HPP_NAMESPACE::DeviceOrHostAddressConstKHR vertexData_ = {},
+                                                   VULKAN_HPP_NAMESPACE::DeviceSize vertexStride_ = {},
+                                                   VULKAN_HPP_NAMESPACE::IndexType indexType_ = VULKAN_HPP_NAMESPACE::IndexType::eUint16,
+                                                   VULKAN_HPP_NAMESPACE::DeviceOrHostAddressConstKHR indexData_ = {},
+                                                   VULKAN_HPP_NAMESPACE::DeviceOrHostAddressConstKHR transformData_ = {} ) VULKAN_HPP_NOEXCEPT
+      : vertexFormat( vertexFormat_ )
+      , vertexData( vertexData_ )
+      , vertexStride( vertexStride_ )
+      , indexType( indexType_ )
+      , indexData( indexData_ )
+      , transformData( transformData_ )
+    {}
+
+    AccelerationStructureGeometryTrianglesDataKHR & operator=( AccelerationStructureGeometryTrianglesDataKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      memcpy( &pNext, &rhs.pNext, sizeof( AccelerationStructureGeometryTrianglesDataKHR ) - offsetof( AccelerationStructureGeometryTrianglesDataKHR, pNext ) );
+      return *this;
+    }
+
+    AccelerationStructureGeometryTrianglesDataKHR( VkAccelerationStructureGeometryTrianglesDataKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    AccelerationStructureGeometryTrianglesDataKHR& operator=( VkAccelerationStructureGeometryTrianglesDataKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::AccelerationStructureGeometryTrianglesDataKHR const *>(&rhs);
+      return *this;
+    }
+
+    AccelerationStructureGeometryTrianglesDataKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pNext = pNext_;
+      return *this;
+    }
+
+    AccelerationStructureGeometryTrianglesDataKHR & setVertexFormat( VULKAN_HPP_NAMESPACE::Format vertexFormat_ ) VULKAN_HPP_NOEXCEPT
+    {
+      vertexFormat = vertexFormat_;
+      return *this;
+    }
+
+    AccelerationStructureGeometryTrianglesDataKHR & setVertexData( VULKAN_HPP_NAMESPACE::DeviceOrHostAddressConstKHR vertexData_ ) VULKAN_HPP_NOEXCEPT
+    {
+      vertexData = vertexData_;
+      return *this;
+    }
+
+    AccelerationStructureGeometryTrianglesDataKHR & setVertexStride( VULKAN_HPP_NAMESPACE::DeviceSize vertexStride_ ) VULKAN_HPP_NOEXCEPT
+    {
+      vertexStride = vertexStride_;
+      return *this;
+    }
+
+    AccelerationStructureGeometryTrianglesDataKHR & setIndexType( VULKAN_HPP_NAMESPACE::IndexType indexType_ ) VULKAN_HPP_NOEXCEPT
+    {
+      indexType = indexType_;
+      return *this;
+    }
+
+    AccelerationStructureGeometryTrianglesDataKHR & setIndexData( VULKAN_HPP_NAMESPACE::DeviceOrHostAddressConstKHR indexData_ ) VULKAN_HPP_NOEXCEPT
+    {
+      indexData = indexData_;
+      return *this;
+    }
+
+    AccelerationStructureGeometryTrianglesDataKHR & setTransformData( VULKAN_HPP_NAMESPACE::DeviceOrHostAddressConstKHR transformData_ ) VULKAN_HPP_NOEXCEPT
+    {
+      transformData = transformData_;
+      return *this;
+    }
+
+    operator VkAccelerationStructureGeometryTrianglesDataKHR const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkAccelerationStructureGeometryTrianglesDataKHR*>( this );
+    }
+
+    operator VkAccelerationStructureGeometryTrianglesDataKHR &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkAccelerationStructureGeometryTrianglesDataKHR*>( this );
+    }
+
+  public:
+    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eAccelerationStructureGeometryTrianglesDataKHR;
+    const void* pNext = {};
+    VULKAN_HPP_NAMESPACE::Format vertexFormat = VULKAN_HPP_NAMESPACE::Format::eUndefined;
+    VULKAN_HPP_NAMESPACE::DeviceOrHostAddressConstKHR vertexData = {};
+    VULKAN_HPP_NAMESPACE::DeviceSize vertexStride = {};
+    VULKAN_HPP_NAMESPACE::IndexType indexType = VULKAN_HPP_NAMESPACE::IndexType::eUint16;
+    VULKAN_HPP_NAMESPACE::DeviceOrHostAddressConstKHR indexData = {};
+    VULKAN_HPP_NAMESPACE::DeviceOrHostAddressConstKHR transformData = {};
+  };
+  static_assert( sizeof( AccelerationStructureGeometryTrianglesDataKHR ) == sizeof( VkAccelerationStructureGeometryTrianglesDataKHR ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<AccelerationStructureGeometryTrianglesDataKHR>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct AccelerationStructureGeometryAabbsDataKHR
+  {
+    AccelerationStructureGeometryAabbsDataKHR( VULKAN_HPP_NAMESPACE::DeviceOrHostAddressConstKHR data_ = {},
+                                               VULKAN_HPP_NAMESPACE::DeviceSize stride_ = {} ) VULKAN_HPP_NOEXCEPT
+      : data( data_ )
+      , stride( stride_ )
+    {}
+
+    AccelerationStructureGeometryAabbsDataKHR & operator=( AccelerationStructureGeometryAabbsDataKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      memcpy( &pNext, &rhs.pNext, sizeof( AccelerationStructureGeometryAabbsDataKHR ) - offsetof( AccelerationStructureGeometryAabbsDataKHR, pNext ) );
+      return *this;
+    }
+
+    AccelerationStructureGeometryAabbsDataKHR( VkAccelerationStructureGeometryAabbsDataKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    AccelerationStructureGeometryAabbsDataKHR& operator=( VkAccelerationStructureGeometryAabbsDataKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::AccelerationStructureGeometryAabbsDataKHR const *>(&rhs);
+      return *this;
+    }
+
+    AccelerationStructureGeometryAabbsDataKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pNext = pNext_;
+      return *this;
+    }
+
+    AccelerationStructureGeometryAabbsDataKHR & setData( VULKAN_HPP_NAMESPACE::DeviceOrHostAddressConstKHR data_ ) VULKAN_HPP_NOEXCEPT
+    {
+      data = data_;
+      return *this;
+    }
+
+    AccelerationStructureGeometryAabbsDataKHR & setStride( VULKAN_HPP_NAMESPACE::DeviceSize stride_ ) VULKAN_HPP_NOEXCEPT
+    {
+      stride = stride_;
+      return *this;
+    }
+
+    operator VkAccelerationStructureGeometryAabbsDataKHR const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkAccelerationStructureGeometryAabbsDataKHR*>( this );
+    }
+
+    operator VkAccelerationStructureGeometryAabbsDataKHR &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkAccelerationStructureGeometryAabbsDataKHR*>( this );
+    }
+
+  public:
+    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eAccelerationStructureGeometryAabbsDataKHR;
+    const void* pNext = {};
+    VULKAN_HPP_NAMESPACE::DeviceOrHostAddressConstKHR data = {};
+    VULKAN_HPP_NAMESPACE::DeviceSize stride = {};
+  };
+  static_assert( sizeof( AccelerationStructureGeometryAabbsDataKHR ) == sizeof( VkAccelerationStructureGeometryAabbsDataKHR ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<AccelerationStructureGeometryAabbsDataKHR>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct AccelerationStructureGeometryInstancesDataKHR
+  {
+    AccelerationStructureGeometryInstancesDataKHR( VULKAN_HPP_NAMESPACE::Bool32 arrayOfPointers_ = {},
+                                                   VULKAN_HPP_NAMESPACE::DeviceOrHostAddressConstKHR data_ = {} ) VULKAN_HPP_NOEXCEPT
+      : arrayOfPointers( arrayOfPointers_ )
+      , data( data_ )
+    {}
+
+    AccelerationStructureGeometryInstancesDataKHR & operator=( AccelerationStructureGeometryInstancesDataKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      memcpy( &pNext, &rhs.pNext, sizeof( AccelerationStructureGeometryInstancesDataKHR ) - offsetof( AccelerationStructureGeometryInstancesDataKHR, pNext ) );
+      return *this;
+    }
+
+    AccelerationStructureGeometryInstancesDataKHR( VkAccelerationStructureGeometryInstancesDataKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    AccelerationStructureGeometryInstancesDataKHR& operator=( VkAccelerationStructureGeometryInstancesDataKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::AccelerationStructureGeometryInstancesDataKHR const *>(&rhs);
+      return *this;
+    }
+
+    AccelerationStructureGeometryInstancesDataKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pNext = pNext_;
+      return *this;
+    }
+
+    AccelerationStructureGeometryInstancesDataKHR & setArrayOfPointers( VULKAN_HPP_NAMESPACE::Bool32 arrayOfPointers_ ) VULKAN_HPP_NOEXCEPT
+    {
+      arrayOfPointers = arrayOfPointers_;
+      return *this;
+    }
+
+    AccelerationStructureGeometryInstancesDataKHR & setData( VULKAN_HPP_NAMESPACE::DeviceOrHostAddressConstKHR data_ ) VULKAN_HPP_NOEXCEPT
+    {
+      data = data_;
+      return *this;
+    }
+
+    operator VkAccelerationStructureGeometryInstancesDataKHR const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkAccelerationStructureGeometryInstancesDataKHR*>( this );
+    }
+
+    operator VkAccelerationStructureGeometryInstancesDataKHR &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkAccelerationStructureGeometryInstancesDataKHR*>( this );
+    }
+
+  public:
+    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eAccelerationStructureGeometryInstancesDataKHR;
+    const void* pNext = {};
+    VULKAN_HPP_NAMESPACE::Bool32 arrayOfPointers = {};
+    VULKAN_HPP_NAMESPACE::DeviceOrHostAddressConstKHR data = {};
+  };
+  static_assert( sizeof( AccelerationStructureGeometryInstancesDataKHR ) == sizeof( VkAccelerationStructureGeometryInstancesDataKHR ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<AccelerationStructureGeometryInstancesDataKHR>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  union AccelerationStructureGeometryDataKHR
+  {
+    AccelerationStructureGeometryDataKHR( VULKAN_HPP_NAMESPACE::AccelerationStructureGeometryDataKHR const& rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      memcpy( static_cast<void*>(this), &rhs, sizeof( VULKAN_HPP_NAMESPACE::AccelerationStructureGeometryDataKHR ) );
+    }
+
+    AccelerationStructureGeometryDataKHR( VULKAN_HPP_NAMESPACE::AccelerationStructureGeometryTrianglesDataKHR triangles_ = {} )
+    {
+      triangles = triangles_;
+    }
+
+    AccelerationStructureGeometryDataKHR( VULKAN_HPP_NAMESPACE::AccelerationStructureGeometryAabbsDataKHR aabbs_ )
+    {
+      aabbs = aabbs_;
+    }
+
+    AccelerationStructureGeometryDataKHR( VULKAN_HPP_NAMESPACE::AccelerationStructureGeometryInstancesDataKHR instances_ )
+    {
+      instances = instances_;
+    }
+
+    AccelerationStructureGeometryDataKHR & setTriangles( VULKAN_HPP_NAMESPACE::AccelerationStructureGeometryTrianglesDataKHR triangles_ ) VULKAN_HPP_NOEXCEPT
+    {
+      triangles = triangles_;
+      return *this;
+    }
+
+    AccelerationStructureGeometryDataKHR & setAabbs( VULKAN_HPP_NAMESPACE::AccelerationStructureGeometryAabbsDataKHR aabbs_ ) VULKAN_HPP_NOEXCEPT
+    {
+      aabbs = aabbs_;
+      return *this;
+    }
+
+    AccelerationStructureGeometryDataKHR & setInstances( VULKAN_HPP_NAMESPACE::AccelerationStructureGeometryInstancesDataKHR instances_ ) VULKAN_HPP_NOEXCEPT
+    {
+      instances = instances_;
+      return *this;
+    }
+
+    VULKAN_HPP_NAMESPACE::AccelerationStructureGeometryDataKHR & operator=( VULKAN_HPP_NAMESPACE::AccelerationStructureGeometryDataKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      memcpy( static_cast<void*>(this), &rhs, sizeof( VULKAN_HPP_NAMESPACE::AccelerationStructureGeometryDataKHR ) );
+      return *this;
+    }
+
+    operator VkAccelerationStructureGeometryDataKHR const&() const
+    {
+      return *reinterpret_cast<const VkAccelerationStructureGeometryDataKHR*>(this);
+    }
+
+    operator VkAccelerationStructureGeometryDataKHR &()
+    {
+      return *reinterpret_cast<VkAccelerationStructureGeometryDataKHR*>(this);
+    }
+
+#ifdef VULKAN_HPP_HAS_UNRESTRICTED_UNIONS
+    VULKAN_HPP_NAMESPACE::AccelerationStructureGeometryTrianglesDataKHR triangles;
+    VULKAN_HPP_NAMESPACE::AccelerationStructureGeometryAabbsDataKHR aabbs;
+    VULKAN_HPP_NAMESPACE::AccelerationStructureGeometryInstancesDataKHR instances;
+#else
+    VkAccelerationStructureGeometryTrianglesDataKHR triangles;
+    VkAccelerationStructureGeometryAabbsDataKHR aabbs;
+    VkAccelerationStructureGeometryInstancesDataKHR instances;
+#endif  /*VULKAN_HPP_HAS_UNRESTRICTED_UNIONS*/
+  };
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct AccelerationStructureGeometryKHR
+  {
+    AccelerationStructureGeometryKHR( VULKAN_HPP_NAMESPACE::GeometryTypeKHR geometryType_ = VULKAN_HPP_NAMESPACE::GeometryTypeKHR::eTriangles,
+                                      VULKAN_HPP_NAMESPACE::AccelerationStructureGeometryDataKHR geometry_ = {},
+                                      VULKAN_HPP_NAMESPACE::GeometryFlagsKHR flags_ = {} ) VULKAN_HPP_NOEXCEPT
+      : geometryType( geometryType_ )
+      , geometry( geometry_ )
+      , flags( flags_ )
+    {}
+
+    AccelerationStructureGeometryKHR & operator=( AccelerationStructureGeometryKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      memcpy( &pNext, &rhs.pNext, sizeof( AccelerationStructureGeometryKHR ) - offsetof( AccelerationStructureGeometryKHR, pNext ) );
+      return *this;
+    }
+
+    AccelerationStructureGeometryKHR( VkAccelerationStructureGeometryKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    AccelerationStructureGeometryKHR& operator=( VkAccelerationStructureGeometryKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::AccelerationStructureGeometryKHR const *>(&rhs);
+      return *this;
+    }
+
+    AccelerationStructureGeometryKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pNext = pNext_;
+      return *this;
+    }
+
+    AccelerationStructureGeometryKHR & setGeometryType( VULKAN_HPP_NAMESPACE::GeometryTypeKHR geometryType_ ) VULKAN_HPP_NOEXCEPT
+    {
+      geometryType = geometryType_;
+      return *this;
+    }
+
+    AccelerationStructureGeometryKHR & setGeometry( VULKAN_HPP_NAMESPACE::AccelerationStructureGeometryDataKHR geometry_ ) VULKAN_HPP_NOEXCEPT
+    {
+      geometry = geometry_;
+      return *this;
+    }
+
+    AccelerationStructureGeometryKHR & setFlags( VULKAN_HPP_NAMESPACE::GeometryFlagsKHR flags_ ) VULKAN_HPP_NOEXCEPT
+    {
+      flags = flags_;
+      return *this;
+    }
+
+    operator VkAccelerationStructureGeometryKHR const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkAccelerationStructureGeometryKHR*>( this );
+    }
+
+    operator VkAccelerationStructureGeometryKHR &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkAccelerationStructureGeometryKHR*>( this );
+    }
+
+  public:
+    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eAccelerationStructureGeometryKHR;
+    const void* pNext = {};
+    VULKAN_HPP_NAMESPACE::GeometryTypeKHR geometryType = VULKAN_HPP_NAMESPACE::GeometryTypeKHR::eTriangles;
+    VULKAN_HPP_NAMESPACE::AccelerationStructureGeometryDataKHR geometry = {};
+    VULKAN_HPP_NAMESPACE::GeometryFlagsKHR flags = {};
+  };
+  static_assert( sizeof( AccelerationStructureGeometryKHR ) == sizeof( VkAccelerationStructureGeometryKHR ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<AccelerationStructureGeometryKHR>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  union DeviceOrHostAddressKHR
+  {
+    DeviceOrHostAddressKHR( VULKAN_HPP_NAMESPACE::DeviceOrHostAddressKHR const& rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      memcpy( static_cast<void*>(this), &rhs, sizeof( VULKAN_HPP_NAMESPACE::DeviceOrHostAddressKHR ) );
+    }
+
+    DeviceOrHostAddressKHR( VULKAN_HPP_NAMESPACE::DeviceAddress deviceAddress_ = {} )
+    {
+      deviceAddress = deviceAddress_;
+    }
+
+    DeviceOrHostAddressKHR( void* hostAddress_ )
+    {
+      hostAddress = hostAddress_;
+    }
+
+    DeviceOrHostAddressKHR & setDeviceAddress( VULKAN_HPP_NAMESPACE::DeviceAddress deviceAddress_ ) VULKAN_HPP_NOEXCEPT
+    {
+      deviceAddress = deviceAddress_;
+      return *this;
+    }
+
+    DeviceOrHostAddressKHR & setHostAddress( void* hostAddress_ ) VULKAN_HPP_NOEXCEPT
+    {
+      hostAddress = hostAddress_;
+      return *this;
+    }
+
+    VULKAN_HPP_NAMESPACE::DeviceOrHostAddressKHR & operator=( VULKAN_HPP_NAMESPACE::DeviceOrHostAddressKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      memcpy( static_cast<void*>(this), &rhs, sizeof( VULKAN_HPP_NAMESPACE::DeviceOrHostAddressKHR ) );
+      return *this;
+    }
+
+    operator VkDeviceOrHostAddressKHR const&() const
+    {
+      return *reinterpret_cast<const VkDeviceOrHostAddressKHR*>(this);
+    }
+
+    operator VkDeviceOrHostAddressKHR &()
+    {
+      return *reinterpret_cast<VkDeviceOrHostAddressKHR*>(this);
+    }
+
+#ifdef VULKAN_HPP_HAS_UNRESTRICTED_UNIONS
+    VULKAN_HPP_NAMESPACE::DeviceAddress deviceAddress;
+    void* hostAddress;
+#else
+    VkDeviceAddress deviceAddress;
+    void* hostAddress;
+#endif  /*VULKAN_HPP_HAS_UNRESTRICTED_UNIONS*/
+  };
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct AccelerationStructureBuildGeometryInfoKHR
+  {
+    AccelerationStructureBuildGeometryInfoKHR( VULKAN_HPP_NAMESPACE::AccelerationStructureTypeKHR type_ = VULKAN_HPP_NAMESPACE::AccelerationStructureTypeKHR::eTopLevel,
+                                               VULKAN_HPP_NAMESPACE::BuildAccelerationStructureFlagsKHR flags_ = {},
+                                               VULKAN_HPP_NAMESPACE::Bool32 update_ = {},
+                                               VULKAN_HPP_NAMESPACE::AccelerationStructureKHR srcAccelerationStructure_ = {},
+                                               VULKAN_HPP_NAMESPACE::AccelerationStructureKHR dstAccelerationStructure_ = {},
+                                               VULKAN_HPP_NAMESPACE::Bool32 geometryArrayOfPointers_ = {},
+                                               uint32_t geometryCount_ = {},
+                                               const VULKAN_HPP_NAMESPACE::AccelerationStructureGeometryKHR* const* ppGeometries_ = {},
+                                               VULKAN_HPP_NAMESPACE::DeviceOrHostAddressKHR scratchData_ = {} ) VULKAN_HPP_NOEXCEPT
+      : type( type_ )
+      , flags( flags_ )
+      , update( update_ )
+      , srcAccelerationStructure( srcAccelerationStructure_ )
+      , dstAccelerationStructure( dstAccelerationStructure_ )
+      , geometryArrayOfPointers( geometryArrayOfPointers_ )
+      , geometryCount( geometryCount_ )
+      , ppGeometries( ppGeometries_ )
+      , scratchData( scratchData_ )
+    {}
+
+    AccelerationStructureBuildGeometryInfoKHR & operator=( AccelerationStructureBuildGeometryInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      memcpy( &pNext, &rhs.pNext, sizeof( AccelerationStructureBuildGeometryInfoKHR ) - offsetof( AccelerationStructureBuildGeometryInfoKHR, pNext ) );
+      return *this;
+    }
+
+    AccelerationStructureBuildGeometryInfoKHR( VkAccelerationStructureBuildGeometryInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    AccelerationStructureBuildGeometryInfoKHR& operator=( VkAccelerationStructureBuildGeometryInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::AccelerationStructureBuildGeometryInfoKHR const *>(&rhs);
+      return *this;
+    }
+
+    AccelerationStructureBuildGeometryInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pNext = pNext_;
+      return *this;
+    }
+
+    AccelerationStructureBuildGeometryInfoKHR & setType( VULKAN_HPP_NAMESPACE::AccelerationStructureTypeKHR type_ ) VULKAN_HPP_NOEXCEPT
+    {
+      type = type_;
+      return *this;
+    }
+
+    AccelerationStructureBuildGeometryInfoKHR & setFlags( VULKAN_HPP_NAMESPACE::BuildAccelerationStructureFlagsKHR flags_ ) VULKAN_HPP_NOEXCEPT
+    {
+      flags = flags_;
+      return *this;
+    }
+
+    AccelerationStructureBuildGeometryInfoKHR & setUpdate( VULKAN_HPP_NAMESPACE::Bool32 update_ ) VULKAN_HPP_NOEXCEPT
+    {
+      update = update_;
+      return *this;
+    }
+
+    AccelerationStructureBuildGeometryInfoKHR & setSrcAccelerationStructure( VULKAN_HPP_NAMESPACE::AccelerationStructureKHR srcAccelerationStructure_ ) VULKAN_HPP_NOEXCEPT
+    {
+      srcAccelerationStructure = srcAccelerationStructure_;
+      return *this;
+    }
+
+    AccelerationStructureBuildGeometryInfoKHR & setDstAccelerationStructure( VULKAN_HPP_NAMESPACE::AccelerationStructureKHR dstAccelerationStructure_ ) VULKAN_HPP_NOEXCEPT
+    {
+      dstAccelerationStructure = dstAccelerationStructure_;
+      return *this;
+    }
+
+    AccelerationStructureBuildGeometryInfoKHR & setGeometryArrayOfPointers( VULKAN_HPP_NAMESPACE::Bool32 geometryArrayOfPointers_ ) VULKAN_HPP_NOEXCEPT
+    {
+      geometryArrayOfPointers = geometryArrayOfPointers_;
+      return *this;
+    }
+
+    AccelerationStructureBuildGeometryInfoKHR & setGeometryCount( uint32_t geometryCount_ ) VULKAN_HPP_NOEXCEPT
+    {
+      geometryCount = geometryCount_;
+      return *this;
+    }
+
+    AccelerationStructureBuildGeometryInfoKHR & setPpGeometries( const VULKAN_HPP_NAMESPACE::AccelerationStructureGeometryKHR* const* ppGeometries_ ) VULKAN_HPP_NOEXCEPT
+    {
+      ppGeometries = ppGeometries_;
+      return *this;
+    }
+
+    AccelerationStructureBuildGeometryInfoKHR & setScratchData( VULKAN_HPP_NAMESPACE::DeviceOrHostAddressKHR scratchData_ ) VULKAN_HPP_NOEXCEPT
+    {
+      scratchData = scratchData_;
+      return *this;
+    }
+
+    operator VkAccelerationStructureBuildGeometryInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkAccelerationStructureBuildGeometryInfoKHR*>( this );
+    }
+
+    operator VkAccelerationStructureBuildGeometryInfoKHR &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkAccelerationStructureBuildGeometryInfoKHR*>( this );
+    }
+
+  public:
+    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eAccelerationStructureBuildGeometryInfoKHR;
+    const void* pNext = {};
+    VULKAN_HPP_NAMESPACE::AccelerationStructureTypeKHR type = VULKAN_HPP_NAMESPACE::AccelerationStructureTypeKHR::eTopLevel;
+    VULKAN_HPP_NAMESPACE::BuildAccelerationStructureFlagsKHR flags = {};
+    VULKAN_HPP_NAMESPACE::Bool32 update = {};
+    VULKAN_HPP_NAMESPACE::AccelerationStructureKHR srcAccelerationStructure = {};
+    VULKAN_HPP_NAMESPACE::AccelerationStructureKHR dstAccelerationStructure = {};
+    VULKAN_HPP_NAMESPACE::Bool32 geometryArrayOfPointers = {};
+    uint32_t geometryCount = {};
+    const VULKAN_HPP_NAMESPACE::AccelerationStructureGeometryKHR* const* ppGeometries = {};
+    VULKAN_HPP_NAMESPACE::DeviceOrHostAddressKHR scratchData = {};
+  };
+  static_assert( sizeof( AccelerationStructureBuildGeometryInfoKHR ) == sizeof( VkAccelerationStructureBuildGeometryInfoKHR ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<AccelerationStructureBuildGeometryInfoKHR>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct AccelerationStructureBuildOffsetInfoKHR
+  {
+    VULKAN_HPP_CONSTEXPR AccelerationStructureBuildOffsetInfoKHR( uint32_t primitiveCount_ = {},
+                                                                  uint32_t primitiveOffset_ = {},
+                                                                  uint32_t firstVertex_ = {},
+                                                                  uint32_t transformOffset_ = {} ) VULKAN_HPP_NOEXCEPT
+      : primitiveCount( primitiveCount_ )
+      , primitiveOffset( primitiveOffset_ )
+      , firstVertex( firstVertex_ )
+      , transformOffset( transformOffset_ )
+    {}
+
+    AccelerationStructureBuildOffsetInfoKHR( VkAccelerationStructureBuildOffsetInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    AccelerationStructureBuildOffsetInfoKHR& operator=( VkAccelerationStructureBuildOffsetInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::AccelerationStructureBuildOffsetInfoKHR const *>(&rhs);
+      return *this;
+    }
+
+    AccelerationStructureBuildOffsetInfoKHR & setPrimitiveCount( uint32_t primitiveCount_ ) VULKAN_HPP_NOEXCEPT
+    {
+      primitiveCount = primitiveCount_;
+      return *this;
+    }
+
+    AccelerationStructureBuildOffsetInfoKHR & setPrimitiveOffset( uint32_t primitiveOffset_ ) VULKAN_HPP_NOEXCEPT
+    {
+      primitiveOffset = primitiveOffset_;
+      return *this;
+    }
+
+    AccelerationStructureBuildOffsetInfoKHR & setFirstVertex( uint32_t firstVertex_ ) VULKAN_HPP_NOEXCEPT
+    {
+      firstVertex = firstVertex_;
+      return *this;
+    }
+
+    AccelerationStructureBuildOffsetInfoKHR & setTransformOffset( uint32_t transformOffset_ ) VULKAN_HPP_NOEXCEPT
+    {
+      transformOffset = transformOffset_;
+      return *this;
+    }
+
+    operator VkAccelerationStructureBuildOffsetInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkAccelerationStructureBuildOffsetInfoKHR*>( this );
+    }
+
+    operator VkAccelerationStructureBuildOffsetInfoKHR &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkAccelerationStructureBuildOffsetInfoKHR*>( this );
+    }
+
+#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
+    auto operator<=>( AccelerationStructureBuildOffsetInfoKHR const& ) const = default;
+#else
+    bool operator==( AccelerationStructureBuildOffsetInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ( primitiveCount == rhs.primitiveCount )
+          && ( primitiveOffset == rhs.primitiveOffset )
+          && ( firstVertex == rhs.firstVertex )
+          && ( transformOffset == rhs.transformOffset );
+    }
+
+    bool operator!=( AccelerationStructureBuildOffsetInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return !operator==( rhs );
+    }
+#endif
+
+  public:
+    uint32_t primitiveCount = {};
+    uint32_t primitiveOffset = {};
+    uint32_t firstVertex = {};
+    uint32_t transformOffset = {};
+  };
+  static_assert( sizeof( AccelerationStructureBuildOffsetInfoKHR ) == sizeof( VkAccelerationStructureBuildOffsetInfoKHR ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<AccelerationStructureBuildOffsetInfoKHR>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct AccelerationStructureCreateGeometryTypeInfoKHR
+  {
+    VULKAN_HPP_CONSTEXPR AccelerationStructureCreateGeometryTypeInfoKHR( VULKAN_HPP_NAMESPACE::GeometryTypeKHR geometryType_ = VULKAN_HPP_NAMESPACE::GeometryTypeKHR::eTriangles,
+                                                                         uint32_t maxPrimitiveCount_ = {},
+                                                                         VULKAN_HPP_NAMESPACE::IndexType indexType_ = VULKAN_HPP_NAMESPACE::IndexType::eUint16,
+                                                                         uint32_t maxVertexCount_ = {},
+                                                                         VULKAN_HPP_NAMESPACE::Format vertexFormat_ = VULKAN_HPP_NAMESPACE::Format::eUndefined,
+                                                                         VULKAN_HPP_NAMESPACE::Bool32 allowsTransforms_ = {} ) VULKAN_HPP_NOEXCEPT
+      : geometryType( geometryType_ )
+      , maxPrimitiveCount( maxPrimitiveCount_ )
+      , indexType( indexType_ )
+      , maxVertexCount( maxVertexCount_ )
+      , vertexFormat( vertexFormat_ )
+      , allowsTransforms( allowsTransforms_ )
+    {}
+
+    AccelerationStructureCreateGeometryTypeInfoKHR & operator=( AccelerationStructureCreateGeometryTypeInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      memcpy( &pNext, &rhs.pNext, sizeof( AccelerationStructureCreateGeometryTypeInfoKHR ) - offsetof( AccelerationStructureCreateGeometryTypeInfoKHR, pNext ) );
+      return *this;
+    }
+
+    AccelerationStructureCreateGeometryTypeInfoKHR( VkAccelerationStructureCreateGeometryTypeInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    AccelerationStructureCreateGeometryTypeInfoKHR& operator=( VkAccelerationStructureCreateGeometryTypeInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::AccelerationStructureCreateGeometryTypeInfoKHR const *>(&rhs);
+      return *this;
+    }
+
+    AccelerationStructureCreateGeometryTypeInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pNext = pNext_;
+      return *this;
+    }
+
+    AccelerationStructureCreateGeometryTypeInfoKHR & setGeometryType( VULKAN_HPP_NAMESPACE::GeometryTypeKHR geometryType_ ) VULKAN_HPP_NOEXCEPT
+    {
+      geometryType = geometryType_;
+      return *this;
+    }
+
+    AccelerationStructureCreateGeometryTypeInfoKHR & setMaxPrimitiveCount( uint32_t maxPrimitiveCount_ ) VULKAN_HPP_NOEXCEPT
+    {
+      maxPrimitiveCount = maxPrimitiveCount_;
+      return *this;
+    }
+
+    AccelerationStructureCreateGeometryTypeInfoKHR & setIndexType( VULKAN_HPP_NAMESPACE::IndexType indexType_ ) VULKAN_HPP_NOEXCEPT
+    {
+      indexType = indexType_;
+      return *this;
+    }
+
+    AccelerationStructureCreateGeometryTypeInfoKHR & setMaxVertexCount( uint32_t maxVertexCount_ ) VULKAN_HPP_NOEXCEPT
+    {
+      maxVertexCount = maxVertexCount_;
+      return *this;
+    }
+
+    AccelerationStructureCreateGeometryTypeInfoKHR & setVertexFormat( VULKAN_HPP_NAMESPACE::Format vertexFormat_ ) VULKAN_HPP_NOEXCEPT
+    {
+      vertexFormat = vertexFormat_;
+      return *this;
+    }
+
+    AccelerationStructureCreateGeometryTypeInfoKHR & setAllowsTransforms( VULKAN_HPP_NAMESPACE::Bool32 allowsTransforms_ ) VULKAN_HPP_NOEXCEPT
+    {
+      allowsTransforms = allowsTransforms_;
+      return *this;
+    }
+
+    operator VkAccelerationStructureCreateGeometryTypeInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkAccelerationStructureCreateGeometryTypeInfoKHR*>( this );
+    }
+
+    operator VkAccelerationStructureCreateGeometryTypeInfoKHR &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkAccelerationStructureCreateGeometryTypeInfoKHR*>( this );
+    }
+
+#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
+    auto operator<=>( AccelerationStructureCreateGeometryTypeInfoKHR const& ) const = default;
+#else
+    bool operator==( AccelerationStructureCreateGeometryTypeInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ( sType == rhs.sType )
+          && ( pNext == rhs.pNext )
+          && ( geometryType == rhs.geometryType )
+          && ( maxPrimitiveCount == rhs.maxPrimitiveCount )
+          && ( indexType == rhs.indexType )
+          && ( maxVertexCount == rhs.maxVertexCount )
+          && ( vertexFormat == rhs.vertexFormat )
+          && ( allowsTransforms == rhs.allowsTransforms );
+    }
+
+    bool operator!=( AccelerationStructureCreateGeometryTypeInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return !operator==( rhs );
+    }
+#endif
+
+  public:
+    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eAccelerationStructureCreateGeometryTypeInfoKHR;
+    const void* pNext = {};
+    VULKAN_HPP_NAMESPACE::GeometryTypeKHR geometryType = VULKAN_HPP_NAMESPACE::GeometryTypeKHR::eTriangles;
+    uint32_t maxPrimitiveCount = {};
+    VULKAN_HPP_NAMESPACE::IndexType indexType = VULKAN_HPP_NAMESPACE::IndexType::eUint16;
+    uint32_t maxVertexCount = {};
+    VULKAN_HPP_NAMESPACE::Format vertexFormat = VULKAN_HPP_NAMESPACE::Format::eUndefined;
+    VULKAN_HPP_NAMESPACE::Bool32 allowsTransforms = {};
+  };
+  static_assert( sizeof( AccelerationStructureCreateGeometryTypeInfoKHR ) == sizeof( VkAccelerationStructureCreateGeometryTypeInfoKHR ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<AccelerationStructureCreateGeometryTypeInfoKHR>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct AccelerationStructureCreateInfoKHR
+  {
+    VULKAN_HPP_CONSTEXPR AccelerationStructureCreateInfoKHR( VULKAN_HPP_NAMESPACE::DeviceSize compactedSize_ = {},
+                                                             VULKAN_HPP_NAMESPACE::AccelerationStructureTypeKHR type_ = VULKAN_HPP_NAMESPACE::AccelerationStructureTypeKHR::eTopLevel,
+                                                             VULKAN_HPP_NAMESPACE::BuildAccelerationStructureFlagsKHR flags_ = {},
+                                                             uint32_t maxGeometryCount_ = {},
+                                                             const VULKAN_HPP_NAMESPACE::AccelerationStructureCreateGeometryTypeInfoKHR* pGeometryInfos_ = {},
+                                                             VULKAN_HPP_NAMESPACE::DeviceAddress deviceAddress_ = {} ) VULKAN_HPP_NOEXCEPT
+      : compactedSize( compactedSize_ )
+      , type( type_ )
+      , flags( flags_ )
+      , maxGeometryCount( maxGeometryCount_ )
+      , pGeometryInfos( pGeometryInfos_ )
+      , deviceAddress( deviceAddress_ )
+    {}
+
+    AccelerationStructureCreateInfoKHR & operator=( AccelerationStructureCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      memcpy( &pNext, &rhs.pNext, sizeof( AccelerationStructureCreateInfoKHR ) - offsetof( AccelerationStructureCreateInfoKHR, pNext ) );
+      return *this;
+    }
+
+    AccelerationStructureCreateInfoKHR( VkAccelerationStructureCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    AccelerationStructureCreateInfoKHR& operator=( VkAccelerationStructureCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::AccelerationStructureCreateInfoKHR const *>(&rhs);
+      return *this;
+    }
+
+    AccelerationStructureCreateInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pNext = pNext_;
+      return *this;
+    }
+
+    AccelerationStructureCreateInfoKHR & setCompactedSize( VULKAN_HPP_NAMESPACE::DeviceSize compactedSize_ ) VULKAN_HPP_NOEXCEPT
+    {
+      compactedSize = compactedSize_;
+      return *this;
+    }
+
+    AccelerationStructureCreateInfoKHR & setType( VULKAN_HPP_NAMESPACE::AccelerationStructureTypeKHR type_ ) VULKAN_HPP_NOEXCEPT
+    {
+      type = type_;
+      return *this;
+    }
+
+    AccelerationStructureCreateInfoKHR & setFlags( VULKAN_HPP_NAMESPACE::BuildAccelerationStructureFlagsKHR flags_ ) VULKAN_HPP_NOEXCEPT
+    {
+      flags = flags_;
+      return *this;
+    }
+
+    AccelerationStructureCreateInfoKHR & setMaxGeometryCount( uint32_t maxGeometryCount_ ) VULKAN_HPP_NOEXCEPT
+    {
+      maxGeometryCount = maxGeometryCount_;
+      return *this;
+    }
+
+    AccelerationStructureCreateInfoKHR & setPGeometryInfos( const VULKAN_HPP_NAMESPACE::AccelerationStructureCreateGeometryTypeInfoKHR* pGeometryInfos_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pGeometryInfos = pGeometryInfos_;
+      return *this;
+    }
+
+    AccelerationStructureCreateInfoKHR & setDeviceAddress( VULKAN_HPP_NAMESPACE::DeviceAddress deviceAddress_ ) VULKAN_HPP_NOEXCEPT
+    {
+      deviceAddress = deviceAddress_;
+      return *this;
+    }
+
+    operator VkAccelerationStructureCreateInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkAccelerationStructureCreateInfoKHR*>( this );
+    }
+
+    operator VkAccelerationStructureCreateInfoKHR &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkAccelerationStructureCreateInfoKHR*>( this );
+    }
+
+#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
+    auto operator<=>( AccelerationStructureCreateInfoKHR const& ) const = default;
+#else
+    bool operator==( AccelerationStructureCreateInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ( sType == rhs.sType )
+          && ( pNext == rhs.pNext )
+          && ( compactedSize == rhs.compactedSize )
+          && ( type == rhs.type )
+          && ( flags == rhs.flags )
+          && ( maxGeometryCount == rhs.maxGeometryCount )
+          && ( pGeometryInfos == rhs.pGeometryInfos )
+          && ( deviceAddress == rhs.deviceAddress );
+    }
+
+    bool operator!=( AccelerationStructureCreateInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return !operator==( rhs );
+    }
+#endif
+
+  public:
+    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eAccelerationStructureCreateInfoKHR;
+    const void* pNext = {};
+    VULKAN_HPP_NAMESPACE::DeviceSize compactedSize = {};
+    VULKAN_HPP_NAMESPACE::AccelerationStructureTypeKHR type = VULKAN_HPP_NAMESPACE::AccelerationStructureTypeKHR::eTopLevel;
+    VULKAN_HPP_NAMESPACE::BuildAccelerationStructureFlagsKHR flags = {};
+    uint32_t maxGeometryCount = {};
+    const VULKAN_HPP_NAMESPACE::AccelerationStructureCreateGeometryTypeInfoKHR* pGeometryInfos = {};
+    VULKAN_HPP_NAMESPACE::DeviceAddress deviceAddress = {};
+  };
+  static_assert( sizeof( AccelerationStructureCreateInfoKHR ) == sizeof( VkAccelerationStructureCreateInfoKHR ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<AccelerationStructureCreateInfoKHR>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
   struct GeometryTrianglesNV
   {
     VULKAN_HPP_CONSTEXPR GeometryTrianglesNV( VULKAN_HPP_NAMESPACE::Buffer vertexData_ = {},
@@ -19713,21 +21560,6 @@
       , transformOffset( transformOffset_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR GeometryTrianglesNV( GeometryTrianglesNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , vertexData( rhs.vertexData )
-      , vertexOffset( rhs.vertexOffset )
-      , vertexCount( rhs.vertexCount )
-      , vertexStride( rhs.vertexStride )
-      , vertexFormat( rhs.vertexFormat )
-      , indexData( rhs.indexData )
-      , indexOffset( rhs.indexOffset )
-      , indexCount( rhs.indexCount )
-      , indexType( rhs.indexType )
-      , transformData( rhs.transformData )
-      , transformOffset( rhs.transformOffset )
-    {}
-
     GeometryTrianglesNV & operator=( GeometryTrianglesNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( GeometryTrianglesNV ) - offsetof( GeometryTrianglesNV, pNext ) );
@@ -19883,14 +21715,6 @@
       , offset( offset_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR GeometryAABBNV( GeometryAABBNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , aabbData( rhs.aabbData )
-      , numAABBs( rhs.numAABBs )
-      , stride( rhs.stride )
-      , offset( rhs.offset )
-    {}
-
     GeometryAABBNV & operator=( GeometryAABBNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( GeometryAABBNV ) - offsetof( GeometryAABBNV, pNext ) );
@@ -19986,17 +21810,6 @@
       , aabbs( aabbs_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR GeometryDataNV( GeometryDataNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : triangles( rhs.triangles )
-      , aabbs( rhs.aabbs )
-    {}
-
-    GeometryDataNV & operator=( GeometryDataNV const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( GeometryDataNV ) );
-      return *this;
-    }
-
     GeometryDataNV( VkGeometryDataNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -20054,21 +21867,14 @@
 
   struct GeometryNV
   {
-    VULKAN_HPP_CONSTEXPR GeometryNV( VULKAN_HPP_NAMESPACE::GeometryTypeNV geometryType_ = VULKAN_HPP_NAMESPACE::GeometryTypeNV::eTriangles,
+    VULKAN_HPP_CONSTEXPR GeometryNV( VULKAN_HPP_NAMESPACE::GeometryTypeKHR geometryType_ = VULKAN_HPP_NAMESPACE::GeometryTypeKHR::eTriangles,
                                      VULKAN_HPP_NAMESPACE::GeometryDataNV geometry_ = {},
-                                     VULKAN_HPP_NAMESPACE::GeometryFlagsNV flags_ = {} ) VULKAN_HPP_NOEXCEPT
+                                     VULKAN_HPP_NAMESPACE::GeometryFlagsKHR flags_ = {} ) VULKAN_HPP_NOEXCEPT
       : geometryType( geometryType_ )
       , geometry( geometry_ )
       , flags( flags_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR GeometryNV( GeometryNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , geometryType( rhs.geometryType )
-      , geometry( rhs.geometry )
-      , flags( rhs.flags )
-    {}
-
     GeometryNV & operator=( GeometryNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( GeometryNV ) - offsetof( GeometryNV, pNext ) );
@@ -20092,7 +21898,7 @@
       return *this;
     }
 
-    GeometryNV & setGeometryType( VULKAN_HPP_NAMESPACE::GeometryTypeNV geometryType_ ) VULKAN_HPP_NOEXCEPT
+    GeometryNV & setGeometryType( VULKAN_HPP_NAMESPACE::GeometryTypeKHR geometryType_ ) VULKAN_HPP_NOEXCEPT
     {
       geometryType = geometryType_;
       return *this;
@@ -20104,7 +21910,7 @@
       return *this;
     }
 
-    GeometryNV & setFlags( VULKAN_HPP_NAMESPACE::GeometryFlagsNV flags_ ) VULKAN_HPP_NOEXCEPT
+    GeometryNV & setFlags( VULKAN_HPP_NAMESPACE::GeometryFlagsKHR flags_ ) VULKAN_HPP_NOEXCEPT
     {
       flags = flags_;
       return *this;
@@ -20141,16 +21947,16 @@
   public:
     const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eGeometryNV;
     const void* pNext = {};
-    VULKAN_HPP_NAMESPACE::GeometryTypeNV geometryType = VULKAN_HPP_NAMESPACE::GeometryTypeNV::eTriangles;
+    VULKAN_HPP_NAMESPACE::GeometryTypeKHR geometryType = VULKAN_HPP_NAMESPACE::GeometryTypeKHR::eTriangles;
     VULKAN_HPP_NAMESPACE::GeometryDataNV geometry = {};
-    VULKAN_HPP_NAMESPACE::GeometryFlagsNV flags = {};
+    VULKAN_HPP_NAMESPACE::GeometryFlagsKHR flags = {};
   };
   static_assert( sizeof( GeometryNV ) == sizeof( VkGeometryNV ), "struct and wrapper have different size!" );
   static_assert( std::is_standard_layout<GeometryNV>::value, "struct wrapper is not a standard layout!" );
 
   struct AccelerationStructureInfoNV
   {
-    VULKAN_HPP_CONSTEXPR AccelerationStructureInfoNV( VULKAN_HPP_NAMESPACE::AccelerationStructureTypeNV type_ = VULKAN_HPP_NAMESPACE::AccelerationStructureTypeNV::eTopLevel,
+    VULKAN_HPP_CONSTEXPR AccelerationStructureInfoNV( VULKAN_HPP_NAMESPACE::AccelerationStructureTypeNV type_ = {},
                                                       VULKAN_HPP_NAMESPACE::BuildAccelerationStructureFlagsNV flags_ = {},
                                                       uint32_t instanceCount_ = {},
                                                       uint32_t geometryCount_ = {},
@@ -20162,15 +21968,6 @@
       , pGeometries( pGeometries_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR AccelerationStructureInfoNV( AccelerationStructureInfoNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , type( rhs.type )
-      , flags( rhs.flags )
-      , instanceCount( rhs.instanceCount )
-      , geometryCount( rhs.geometryCount )
-      , pGeometries( rhs.pGeometries )
-    {}
-
     AccelerationStructureInfoNV & operator=( AccelerationStructureInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( AccelerationStructureInfoNV ) - offsetof( AccelerationStructureInfoNV, pNext ) );
@@ -20257,7 +22054,7 @@
   public:
     const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eAccelerationStructureInfoNV;
     const void* pNext = {};
-    VULKAN_HPP_NAMESPACE::AccelerationStructureTypeNV type = VULKAN_HPP_NAMESPACE::AccelerationStructureTypeNV::eTopLevel;
+    VULKAN_HPP_NAMESPACE::AccelerationStructureTypeNV type = {};
     VULKAN_HPP_NAMESPACE::BuildAccelerationStructureFlagsNV flags = {};
     uint32_t instanceCount = {};
     uint32_t geometryCount = {};
@@ -20274,12 +22071,6 @@
       , info( info_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR AccelerationStructureCreateInfoNV( AccelerationStructureCreateInfoNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , compactedSize( rhs.compactedSize )
-      , info( rhs.info )
-    {}
-
     AccelerationStructureCreateInfoNV & operator=( AccelerationStructureCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( AccelerationStructureCreateInfoNV ) - offsetof( AccelerationStructureCreateInfoNV, pNext ) );
@@ -20351,18 +22142,330 @@
   static_assert( sizeof( AccelerationStructureCreateInfoNV ) == sizeof( VkAccelerationStructureCreateInfoNV ), "struct and wrapper have different size!" );
   static_assert( std::is_standard_layout<AccelerationStructureCreateInfoNV>::value, "struct wrapper is not a standard layout!" );
 
-  struct AccelerationStructureMemoryRequirementsInfoNV
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct AccelerationStructureDeviceAddressInfoKHR
   {
-    VULKAN_HPP_CONSTEXPR AccelerationStructureMemoryRequirementsInfoNV( VULKAN_HPP_NAMESPACE::AccelerationStructureMemoryRequirementsTypeNV type_ = VULKAN_HPP_NAMESPACE::AccelerationStructureMemoryRequirementsTypeNV::eObject,
-                                                                        VULKAN_HPP_NAMESPACE::AccelerationStructureNV accelerationStructure_ = {} ) VULKAN_HPP_NOEXCEPT
+    VULKAN_HPP_CONSTEXPR AccelerationStructureDeviceAddressInfoKHR( VULKAN_HPP_NAMESPACE::AccelerationStructureKHR accelerationStructure_ = {} ) VULKAN_HPP_NOEXCEPT
+      : accelerationStructure( accelerationStructure_ )
+    {}
+
+    AccelerationStructureDeviceAddressInfoKHR & operator=( AccelerationStructureDeviceAddressInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      memcpy( &pNext, &rhs.pNext, sizeof( AccelerationStructureDeviceAddressInfoKHR ) - offsetof( AccelerationStructureDeviceAddressInfoKHR, pNext ) );
+      return *this;
+    }
+
+    AccelerationStructureDeviceAddressInfoKHR( VkAccelerationStructureDeviceAddressInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    AccelerationStructureDeviceAddressInfoKHR& operator=( VkAccelerationStructureDeviceAddressInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::AccelerationStructureDeviceAddressInfoKHR const *>(&rhs);
+      return *this;
+    }
+
+    AccelerationStructureDeviceAddressInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pNext = pNext_;
+      return *this;
+    }
+
+    AccelerationStructureDeviceAddressInfoKHR & setAccelerationStructure( VULKAN_HPP_NAMESPACE::AccelerationStructureKHR accelerationStructure_ ) VULKAN_HPP_NOEXCEPT
+    {
+      accelerationStructure = accelerationStructure_;
+      return *this;
+    }
+
+    operator VkAccelerationStructureDeviceAddressInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkAccelerationStructureDeviceAddressInfoKHR*>( this );
+    }
+
+    operator VkAccelerationStructureDeviceAddressInfoKHR &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkAccelerationStructureDeviceAddressInfoKHR*>( this );
+    }
+
+#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
+    auto operator<=>( AccelerationStructureDeviceAddressInfoKHR const& ) const = default;
+#else
+    bool operator==( AccelerationStructureDeviceAddressInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ( sType == rhs.sType )
+          && ( pNext == rhs.pNext )
+          && ( accelerationStructure == rhs.accelerationStructure );
+    }
+
+    bool operator!=( AccelerationStructureDeviceAddressInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return !operator==( rhs );
+    }
+#endif
+
+  public:
+    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eAccelerationStructureDeviceAddressInfoKHR;
+    const void* pNext = {};
+    VULKAN_HPP_NAMESPACE::AccelerationStructureKHR accelerationStructure = {};
+  };
+  static_assert( sizeof( AccelerationStructureDeviceAddressInfoKHR ) == sizeof( VkAccelerationStructureDeviceAddressInfoKHR ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<AccelerationStructureDeviceAddressInfoKHR>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+  struct TransformMatrixKHR
+  {
+    VULKAN_HPP_CONSTEXPR_14 TransformMatrixKHR( std::array<std::array<float,4>,3> const& matrix_ = {} ) VULKAN_HPP_NOEXCEPT
+      : matrix( matrix_ )
+    {}
+
+    TransformMatrixKHR( VkTransformMatrixKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    TransformMatrixKHR& operator=( VkTransformMatrixKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::TransformMatrixKHR const *>(&rhs);
+      return *this;
+    }
+
+    TransformMatrixKHR & setMatrix( std::array<std::array<float,4>,3> matrix_ ) VULKAN_HPP_NOEXCEPT
+    {
+      matrix = matrix_;
+      return *this;
+    }
+
+    operator VkTransformMatrixKHR const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkTransformMatrixKHR*>( this );
+    }
+
+    operator VkTransformMatrixKHR &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkTransformMatrixKHR*>( this );
+    }
+
+#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
+    auto operator<=>( TransformMatrixKHR const& ) const = default;
+#else
+    bool operator==( TransformMatrixKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ( matrix == rhs.matrix );
+    }
+
+    bool operator!=( TransformMatrixKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return !operator==( rhs );
+    }
+#endif
+
+  public:
+    VULKAN_HPP_NAMESPACE::ArrayWrapper2D<float, 3, 4> matrix = {};
+  };
+  static_assert( sizeof( TransformMatrixKHR ) == sizeof( VkTransformMatrixKHR ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<TransformMatrixKHR>::value, "struct wrapper is not a standard layout!" );
+
+  struct AccelerationStructureInstanceKHR
+  {
+    VULKAN_HPP_CONSTEXPR_14 AccelerationStructureInstanceKHR( VULKAN_HPP_NAMESPACE::TransformMatrixKHR transform_ = {},
+                                                              uint32_t instanceCustomIndex_ = {},
+                                                              uint32_t mask_ = {},
+                                                              uint32_t instanceShaderBindingTableRecordOffset_ = {},
+                                                              VULKAN_HPP_NAMESPACE::GeometryInstanceFlagsKHR flags_ = {},
+                                                              uint64_t accelerationStructureReference_ = {} ) VULKAN_HPP_NOEXCEPT
+      : transform( transform_ )
+      , instanceCustomIndex( instanceCustomIndex_ )
+      , mask( mask_ )
+      , instanceShaderBindingTableRecordOffset( instanceShaderBindingTableRecordOffset_ )
+      , flags( flags_ )
+      , accelerationStructureReference( accelerationStructureReference_ )
+    {}
+
+    AccelerationStructureInstanceKHR( VkAccelerationStructureInstanceKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    AccelerationStructureInstanceKHR& operator=( VkAccelerationStructureInstanceKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::AccelerationStructureInstanceKHR const *>(&rhs);
+      return *this;
+    }
+
+    AccelerationStructureInstanceKHR & setTransform( VULKAN_HPP_NAMESPACE::TransformMatrixKHR transform_ ) VULKAN_HPP_NOEXCEPT
+    {
+      transform = transform_;
+      return *this;
+    }
+
+    AccelerationStructureInstanceKHR & setInstanceCustomIndex( uint32_t instanceCustomIndex_ ) VULKAN_HPP_NOEXCEPT
+    {
+      instanceCustomIndex = instanceCustomIndex_;
+      return *this;
+    }
+
+    AccelerationStructureInstanceKHR & setMask( uint32_t mask_ ) VULKAN_HPP_NOEXCEPT
+    {
+      mask = mask_;
+      return *this;
+    }
+
+    AccelerationStructureInstanceKHR & setInstanceShaderBindingTableRecordOffset( uint32_t instanceShaderBindingTableRecordOffset_ ) VULKAN_HPP_NOEXCEPT
+    {
+      instanceShaderBindingTableRecordOffset = instanceShaderBindingTableRecordOffset_;
+      return *this;
+    }
+
+    AccelerationStructureInstanceKHR & setFlags( VULKAN_HPP_NAMESPACE::GeometryInstanceFlagsKHR flags_ ) VULKAN_HPP_NOEXCEPT
+    {
+      flags = *reinterpret_cast<VkGeometryInstanceFlagsKHR*>(&flags_);
+      return *this;
+    }
+
+    AccelerationStructureInstanceKHR & setAccelerationStructureReference( uint64_t accelerationStructureReference_ ) VULKAN_HPP_NOEXCEPT
+    {
+      accelerationStructureReference = accelerationStructureReference_;
+      return *this;
+    }
+
+    operator VkAccelerationStructureInstanceKHR const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkAccelerationStructureInstanceKHR*>( this );
+    }
+
+    operator VkAccelerationStructureInstanceKHR &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkAccelerationStructureInstanceKHR*>( this );
+    }
+
+#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
+    auto operator<=>( AccelerationStructureInstanceKHR const& ) const = default;
+#else
+    bool operator==( AccelerationStructureInstanceKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ( transform == rhs.transform )
+          && ( instanceCustomIndex == rhs.instanceCustomIndex )
+          && ( mask == rhs.mask )
+          && ( instanceShaderBindingTableRecordOffset == rhs.instanceShaderBindingTableRecordOffset )
+          && ( flags == rhs.flags )
+          && ( accelerationStructureReference == rhs.accelerationStructureReference );
+    }
+
+    bool operator!=( AccelerationStructureInstanceKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return !operator==( rhs );
+    }
+#endif
+
+  public:
+    VULKAN_HPP_NAMESPACE::TransformMatrixKHR transform = {};
+    uint32_t instanceCustomIndex : 24;
+    uint32_t mask : 8;
+    uint32_t instanceShaderBindingTableRecordOffset : 24;
+    VkGeometryInstanceFlagsKHR flags : 8;
+    uint64_t accelerationStructureReference = {};
+  };
+  static_assert( sizeof( AccelerationStructureInstanceKHR ) == sizeof( VkAccelerationStructureInstanceKHR ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<AccelerationStructureInstanceKHR>::value, "struct wrapper is not a standard layout!" );
+
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct AccelerationStructureMemoryRequirementsInfoKHR
+  {
+    VULKAN_HPP_CONSTEXPR AccelerationStructureMemoryRequirementsInfoKHR( VULKAN_HPP_NAMESPACE::AccelerationStructureMemoryRequirementsTypeKHR type_ = VULKAN_HPP_NAMESPACE::AccelerationStructureMemoryRequirementsTypeKHR::eObject,
+                                                                         VULKAN_HPP_NAMESPACE::AccelerationStructureBuildTypeKHR buildType_ = VULKAN_HPP_NAMESPACE::AccelerationStructureBuildTypeKHR::eHost,
+                                                                         VULKAN_HPP_NAMESPACE::AccelerationStructureKHR accelerationStructure_ = {} ) VULKAN_HPP_NOEXCEPT
       : type( type_ )
+      , buildType( buildType_ )
       , accelerationStructure( accelerationStructure_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR AccelerationStructureMemoryRequirementsInfoNV( AccelerationStructureMemoryRequirementsInfoNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , type( rhs.type )
-      , accelerationStructure( rhs.accelerationStructure )
+    AccelerationStructureMemoryRequirementsInfoKHR & operator=( AccelerationStructureMemoryRequirementsInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      memcpy( &pNext, &rhs.pNext, sizeof( AccelerationStructureMemoryRequirementsInfoKHR ) - offsetof( AccelerationStructureMemoryRequirementsInfoKHR, pNext ) );
+      return *this;
+    }
+
+    AccelerationStructureMemoryRequirementsInfoKHR( VkAccelerationStructureMemoryRequirementsInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    AccelerationStructureMemoryRequirementsInfoKHR& operator=( VkAccelerationStructureMemoryRequirementsInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::AccelerationStructureMemoryRequirementsInfoKHR const *>(&rhs);
+      return *this;
+    }
+
+    AccelerationStructureMemoryRequirementsInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pNext = pNext_;
+      return *this;
+    }
+
+    AccelerationStructureMemoryRequirementsInfoKHR & setType( VULKAN_HPP_NAMESPACE::AccelerationStructureMemoryRequirementsTypeKHR type_ ) VULKAN_HPP_NOEXCEPT
+    {
+      type = type_;
+      return *this;
+    }
+
+    AccelerationStructureMemoryRequirementsInfoKHR & setBuildType( VULKAN_HPP_NAMESPACE::AccelerationStructureBuildTypeKHR buildType_ ) VULKAN_HPP_NOEXCEPT
+    {
+      buildType = buildType_;
+      return *this;
+    }
+
+    AccelerationStructureMemoryRequirementsInfoKHR & setAccelerationStructure( VULKAN_HPP_NAMESPACE::AccelerationStructureKHR accelerationStructure_ ) VULKAN_HPP_NOEXCEPT
+    {
+      accelerationStructure = accelerationStructure_;
+      return *this;
+    }
+
+    operator VkAccelerationStructureMemoryRequirementsInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkAccelerationStructureMemoryRequirementsInfoKHR*>( this );
+    }
+
+    operator VkAccelerationStructureMemoryRequirementsInfoKHR &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkAccelerationStructureMemoryRequirementsInfoKHR*>( this );
+    }
+
+#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
+    auto operator<=>( AccelerationStructureMemoryRequirementsInfoKHR const& ) const = default;
+#else
+    bool operator==( AccelerationStructureMemoryRequirementsInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ( sType == rhs.sType )
+          && ( pNext == rhs.pNext )
+          && ( type == rhs.type )
+          && ( buildType == rhs.buildType )
+          && ( accelerationStructure == rhs.accelerationStructure );
+    }
+
+    bool operator!=( AccelerationStructureMemoryRequirementsInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return !operator==( rhs );
+    }
+#endif
+
+  public:
+    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eAccelerationStructureMemoryRequirementsInfoKHR;
+    const void* pNext = {};
+    VULKAN_HPP_NAMESPACE::AccelerationStructureMemoryRequirementsTypeKHR type = VULKAN_HPP_NAMESPACE::AccelerationStructureMemoryRequirementsTypeKHR::eObject;
+    VULKAN_HPP_NAMESPACE::AccelerationStructureBuildTypeKHR buildType = VULKAN_HPP_NAMESPACE::AccelerationStructureBuildTypeKHR::eHost;
+    VULKAN_HPP_NAMESPACE::AccelerationStructureKHR accelerationStructure = {};
+  };
+  static_assert( sizeof( AccelerationStructureMemoryRequirementsInfoKHR ) == sizeof( VkAccelerationStructureMemoryRequirementsInfoKHR ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<AccelerationStructureMemoryRequirementsInfoKHR>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+  struct AccelerationStructureMemoryRequirementsInfoNV
+  {
+    VULKAN_HPP_CONSTEXPR AccelerationStructureMemoryRequirementsInfoNV( VULKAN_HPP_NAMESPACE::AccelerationStructureMemoryRequirementsTypeNV type_ = {},
+                                                                        VULKAN_HPP_NAMESPACE::AccelerationStructureNV accelerationStructure_ = {} ) VULKAN_HPP_NOEXCEPT
+      : type( type_ )
+      , accelerationStructure( accelerationStructure_ )
     {}
 
     AccelerationStructureMemoryRequirementsInfoNV & operator=( AccelerationStructureMemoryRequirementsInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
@@ -20430,12 +22533,83 @@
   public:
     const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eAccelerationStructureMemoryRequirementsInfoNV;
     const void* pNext = {};
-    VULKAN_HPP_NAMESPACE::AccelerationStructureMemoryRequirementsTypeNV type = VULKAN_HPP_NAMESPACE::AccelerationStructureMemoryRequirementsTypeNV::eObject;
+    VULKAN_HPP_NAMESPACE::AccelerationStructureMemoryRequirementsTypeNV type = {};
     VULKAN_HPP_NAMESPACE::AccelerationStructureNV accelerationStructure = {};
   };
   static_assert( sizeof( AccelerationStructureMemoryRequirementsInfoNV ) == sizeof( VkAccelerationStructureMemoryRequirementsInfoNV ), "struct and wrapper have different size!" );
   static_assert( std::is_standard_layout<AccelerationStructureMemoryRequirementsInfoNV>::value, "struct wrapper is not a standard layout!" );
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct AccelerationStructureVersionKHR
+  {
+    VULKAN_HPP_CONSTEXPR AccelerationStructureVersionKHR( const uint8_t* versionData_ = {} ) VULKAN_HPP_NOEXCEPT
+      : versionData( versionData_ )
+    {}
+
+    AccelerationStructureVersionKHR & operator=( AccelerationStructureVersionKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      memcpy( &pNext, &rhs.pNext, sizeof( AccelerationStructureVersionKHR ) - offsetof( AccelerationStructureVersionKHR, pNext ) );
+      return *this;
+    }
+
+    AccelerationStructureVersionKHR( VkAccelerationStructureVersionKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    AccelerationStructureVersionKHR& operator=( VkAccelerationStructureVersionKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::AccelerationStructureVersionKHR const *>(&rhs);
+      return *this;
+    }
+
+    AccelerationStructureVersionKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pNext = pNext_;
+      return *this;
+    }
+
+    AccelerationStructureVersionKHR & setVersionData( const uint8_t* versionData_ ) VULKAN_HPP_NOEXCEPT
+    {
+      versionData = versionData_;
+      return *this;
+    }
+
+    operator VkAccelerationStructureVersionKHR const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkAccelerationStructureVersionKHR*>( this );
+    }
+
+    operator VkAccelerationStructureVersionKHR &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkAccelerationStructureVersionKHR*>( this );
+    }
+
+#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
+    auto operator<=>( AccelerationStructureVersionKHR const& ) const = default;
+#else
+    bool operator==( AccelerationStructureVersionKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ( sType == rhs.sType )
+          && ( pNext == rhs.pNext )
+          && ( versionData == rhs.versionData );
+    }
+
+    bool operator!=( AccelerationStructureVersionKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return !operator==( rhs );
+    }
+#endif
+
+  public:
+    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eAccelerationStructureVersionKHR;
+    const void* pNext = {};
+    const uint8_t* versionData = {};
+  };
+  static_assert( sizeof( AccelerationStructureVersionKHR ) == sizeof( VkAccelerationStructureVersionKHR ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<AccelerationStructureVersionKHR>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
   struct AcquireNextImageInfoKHR
   {
     VULKAN_HPP_CONSTEXPR AcquireNextImageInfoKHR( VULKAN_HPP_NAMESPACE::SwapchainKHR swapchain_ = {},
@@ -20450,15 +22624,6 @@
       , deviceMask( deviceMask_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR AcquireNextImageInfoKHR( AcquireNextImageInfoKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , swapchain( rhs.swapchain )
-      , timeout( rhs.timeout )
-      , semaphore( rhs.semaphore )
-      , fence( rhs.fence )
-      , deviceMask( rhs.deviceMask )
-    {}
-
     AcquireNextImageInfoKHR & operator=( AcquireNextImageInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( AcquireNextImageInfoKHR ) - offsetof( AcquireNextImageInfoKHR, pNext ) );
@@ -20562,12 +22727,6 @@
       , timeout( timeout_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR AcquireProfilingLockInfoKHR( AcquireProfilingLockInfoKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , timeout( rhs.timeout )
-    {}
-
     AcquireProfilingLockInfoKHR & operator=( AcquireProfilingLockInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( AcquireProfilingLockInfoKHR ) - offsetof( AcquireProfilingLockInfoKHR, pNext ) );
@@ -20655,21 +22814,6 @@
       , pfnInternalFree( pfnInternalFree_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR AllocationCallbacks( AllocationCallbacks const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pUserData( rhs.pUserData )
-      , pfnAllocation( rhs.pfnAllocation )
-      , pfnReallocation( rhs.pfnReallocation )
-      , pfnFree( rhs.pfnFree )
-      , pfnInternalAllocation( rhs.pfnInternalAllocation )
-      , pfnInternalFree( rhs.pfnInternalFree )
-    {}
-
-    AllocationCallbacks & operator=( AllocationCallbacks const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( AllocationCallbacks ) );
-      return *this;
-    }
-
     AllocationCallbacks( VkAllocationCallbacks const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -20769,19 +22913,6 @@
       , a( a_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ComponentMapping( ComponentMapping const& rhs ) VULKAN_HPP_NOEXCEPT
-      : r( rhs.r )
-      , g( rhs.g )
-      , b( rhs.b )
-      , a( rhs.a )
-    {}
-
-    ComponentMapping & operator=( ComponentMapping const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( ComponentMapping ) );
-      return *this;
-    }
-
     ComponentMapping( VkComponentMapping const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -20874,18 +23005,6 @@
       , suggestedYChromaOffset( suggestedYChromaOffset_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR AndroidHardwareBufferFormatPropertiesANDROID( AndroidHardwareBufferFormatPropertiesANDROID const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , format( rhs.format )
-      , externalFormat( rhs.externalFormat )
-      , formatFeatures( rhs.formatFeatures )
-      , samplerYcbcrConversionComponents( rhs.samplerYcbcrConversionComponents )
-      , suggestedYcbcrModel( rhs.suggestedYcbcrModel )
-      , suggestedYcbcrRange( rhs.suggestedYcbcrRange )
-      , suggestedXChromaOffset( rhs.suggestedXChromaOffset )
-      , suggestedYChromaOffset( rhs.suggestedYChromaOffset )
-    {}
-
     AndroidHardwareBufferFormatPropertiesANDROID & operator=( AndroidHardwareBufferFormatPropertiesANDROID const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( AndroidHardwareBufferFormatPropertiesANDROID ) - offsetof( AndroidHardwareBufferFormatPropertiesANDROID, pNext ) );
@@ -20961,12 +23080,6 @@
       , memoryTypeBits( memoryTypeBits_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR AndroidHardwareBufferPropertiesANDROID( AndroidHardwareBufferPropertiesANDROID const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , allocationSize( rhs.allocationSize )
-      , memoryTypeBits( rhs.memoryTypeBits )
-    {}
-
     AndroidHardwareBufferPropertiesANDROID & operator=( AndroidHardwareBufferPropertiesANDROID const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( AndroidHardwareBufferPropertiesANDROID ) - offsetof( AndroidHardwareBufferPropertiesANDROID, pNext ) );
@@ -21028,11 +23141,6 @@
       : androidHardwareBufferUsage( androidHardwareBufferUsage_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR AndroidHardwareBufferUsageANDROID( AndroidHardwareBufferUsageANDROID const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , androidHardwareBufferUsage( rhs.androidHardwareBufferUsage )
-    {}
-
     AndroidHardwareBufferUsageANDROID & operator=( AndroidHardwareBufferUsageANDROID const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( AndroidHardwareBufferUsageANDROID ) - offsetof( AndroidHardwareBufferUsageANDROID, pNext ) );
@@ -21094,12 +23202,6 @@
       , window( window_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR AndroidSurfaceCreateInfoKHR( AndroidSurfaceCreateInfoKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , window( rhs.window )
-    {}
-
     AndroidSurfaceCreateInfoKHR & operator=( AndroidSurfaceCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( AndroidSurfaceCreateInfoKHR ) - offsetof( AndroidSurfaceCreateInfoKHR, pNext ) );
@@ -21186,15 +23288,6 @@
       , apiVersion( apiVersion_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ApplicationInfo( ApplicationInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , pApplicationName( rhs.pApplicationName )
-      , applicationVersion( rhs.applicationVersion )
-      , pEngineName( rhs.pEngineName )
-      , engineVersion( rhs.engineVersion )
-      , apiVersion( rhs.apiVersion )
-    {}
-
     ApplicationInfo & operator=( ApplicationInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ApplicationInfo ) - offsetof( ApplicationInfo, pNext ) );
@@ -21312,24 +23405,6 @@
       , finalLayout( finalLayout_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR AttachmentDescription( AttachmentDescription const& rhs ) VULKAN_HPP_NOEXCEPT
-      : flags( rhs.flags )
-      , format( rhs.format )
-      , samples( rhs.samples )
-      , loadOp( rhs.loadOp )
-      , storeOp( rhs.storeOp )
-      , stencilLoadOp( rhs.stencilLoadOp )
-      , stencilStoreOp( rhs.stencilStoreOp )
-      , initialLayout( rhs.initialLayout )
-      , finalLayout( rhs.finalLayout )
-    {}
-
-    AttachmentDescription & operator=( AttachmentDescription const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( AttachmentDescription ) );
-      return *this;
-    }
-
     AttachmentDescription( VkAttachmentDescription const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -21463,19 +23538,6 @@
       , finalLayout( finalLayout_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR AttachmentDescription2( AttachmentDescription2 const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , format( rhs.format )
-      , samples( rhs.samples )
-      , loadOp( rhs.loadOp )
-      , storeOp( rhs.storeOp )
-      , stencilLoadOp( rhs.stencilLoadOp )
-      , stencilStoreOp( rhs.stencilStoreOp )
-      , initialLayout( rhs.initialLayout )
-      , finalLayout( rhs.finalLayout )
-    {}
-
     AttachmentDescription2 & operator=( AttachmentDescription2 const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( AttachmentDescription2 ) - offsetof( AttachmentDescription2, pNext ) );
@@ -21611,12 +23673,6 @@
       , stencilFinalLayout( stencilFinalLayout_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR AttachmentDescriptionStencilLayout( AttachmentDescriptionStencilLayout const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , stencilInitialLayout( rhs.stencilInitialLayout )
-      , stencilFinalLayout( rhs.stencilFinalLayout )
-    {}
-
     AttachmentDescriptionStencilLayout & operator=( AttachmentDescriptionStencilLayout const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( AttachmentDescriptionStencilLayout ) - offsetof( AttachmentDescriptionStencilLayout, pNext ) );
@@ -21696,17 +23752,6 @@
       , layout( layout_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR AttachmentReference( AttachmentReference const& rhs ) VULKAN_HPP_NOEXCEPT
-      : attachment( rhs.attachment )
-      , layout( rhs.layout )
-    {}
-
-    AttachmentReference & operator=( AttachmentReference const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( AttachmentReference ) );
-      return *this;
-    }
-
     AttachmentReference( VkAttachmentReference const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -21772,13 +23817,6 @@
       , aspectMask( aspectMask_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR AttachmentReference2( AttachmentReference2 const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , attachment( rhs.attachment )
-      , layout( rhs.layout )
-      , aspectMask( rhs.aspectMask )
-    {}
-
     AttachmentReference2 & operator=( AttachmentReference2 const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( AttachmentReference2 ) - offsetof( AttachmentReference2, pNext ) );
@@ -21864,11 +23902,6 @@
       : stencilLayout( stencilLayout_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR AttachmentReferenceStencilLayout( AttachmentReferenceStencilLayout const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , stencilLayout( rhs.stencilLayout )
-    {}
-
     AttachmentReferenceStencilLayout & operator=( AttachmentReferenceStencilLayout const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( AttachmentReferenceStencilLayout ) - offsetof( AttachmentReferenceStencilLayout, pNext ) );
@@ -21940,17 +23973,6 @@
       , height( height_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR Extent2D( Extent2D const& rhs ) VULKAN_HPP_NOEXCEPT
-      : width( rhs.width )
-      , height( rhs.height )
-    {}
-
-    Extent2D & operator=( Extent2D const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( Extent2D ) );
-      return *this;
-    }
-
     Extent2D( VkExtent2D const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -22014,17 +24036,6 @@
       , y( y_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SampleLocationEXT( SampleLocationEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : x( rhs.x )
-      , y( rhs.y )
-    {}
-
-    SampleLocationEXT & operator=( SampleLocationEXT const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( SampleLocationEXT ) );
-      return *this;
-    }
-
     SampleLocationEXT( VkSampleLocationEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -22092,14 +24103,6 @@
       , pSampleLocations( pSampleLocations_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SampleLocationsInfoEXT( SampleLocationsInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , sampleLocationsPerPixel( rhs.sampleLocationsPerPixel )
-      , sampleLocationGridSize( rhs.sampleLocationGridSize )
-      , sampleLocationsCount( rhs.sampleLocationsCount )
-      , pSampleLocations( rhs.pSampleLocations )
-    {}
-
     SampleLocationsInfoEXT & operator=( SampleLocationsInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( SampleLocationsInfoEXT ) - offsetof( SampleLocationsInfoEXT, pNext ) );
@@ -22195,17 +24198,6 @@
       , sampleLocationsInfo( sampleLocationsInfo_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR AttachmentSampleLocationsEXT( AttachmentSampleLocationsEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : attachmentIndex( rhs.attachmentIndex )
-      , sampleLocationsInfo( rhs.sampleLocationsInfo )
-    {}
-
-    AttachmentSampleLocationsEXT & operator=( AttachmentSampleLocationsEXT const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( AttachmentSampleLocationsEXT ) );
-      return *this;
-    }
-
     AttachmentSampleLocationsEXT( VkAttachmentSampleLocationsEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -22266,16 +24258,6 @@
     BaseInStructure() VULKAN_HPP_NOEXCEPT
     {}
 
-    BaseInStructure( BaseInStructure const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-    {}
-
-    BaseInStructure & operator=( BaseInStructure const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( BaseInStructure ) );
-      return *this;
-    }
-
     BaseInStructure( VkBaseInStructure const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -22330,16 +24312,6 @@
     BaseOutStructure() VULKAN_HPP_NOEXCEPT
     {}
 
-    BaseOutStructure( BaseOutStructure const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-    {}
-
-    BaseOutStructure & operator=( BaseOutStructure const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( BaseOutStructure ) );
-      return *this;
-    }
-
     BaseOutStructure( VkBaseOutStructure const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -22389,13 +24361,13 @@
   static_assert( sizeof( BaseOutStructure ) == sizeof( VkBaseOutStructure ), "struct and wrapper have different size!" );
   static_assert( std::is_standard_layout<BaseOutStructure>::value, "struct wrapper is not a standard layout!" );
 
-  struct BindAccelerationStructureMemoryInfoNV
+  struct BindAccelerationStructureMemoryInfoKHR
   {
-    VULKAN_HPP_CONSTEXPR BindAccelerationStructureMemoryInfoNV( VULKAN_HPP_NAMESPACE::AccelerationStructureNV accelerationStructure_ = {},
-                                                                VULKAN_HPP_NAMESPACE::DeviceMemory memory_ = {},
-                                                                VULKAN_HPP_NAMESPACE::DeviceSize memoryOffset_ = {},
-                                                                uint32_t deviceIndexCount_ = {},
-                                                                const uint32_t* pDeviceIndices_ = {} ) VULKAN_HPP_NOEXCEPT
+    VULKAN_HPP_CONSTEXPR BindAccelerationStructureMemoryInfoKHR( VULKAN_HPP_NAMESPACE::AccelerationStructureKHR accelerationStructure_ = {},
+                                                                 VULKAN_HPP_NAMESPACE::DeviceMemory memory_ = {},
+                                                                 VULKAN_HPP_NAMESPACE::DeviceSize memoryOffset_ = {},
+                                                                 uint32_t deviceIndexCount_ = {},
+                                                                 const uint32_t* pDeviceIndices_ = {} ) VULKAN_HPP_NOEXCEPT
       : accelerationStructure( accelerationStructure_ )
       , memory( memory_ )
       , memoryOffset( memoryOffset_ )
@@ -22403,82 +24375,73 @@
       , pDeviceIndices( pDeviceIndices_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR BindAccelerationStructureMemoryInfoNV( BindAccelerationStructureMemoryInfoNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , accelerationStructure( rhs.accelerationStructure )
-      , memory( rhs.memory )
-      , memoryOffset( rhs.memoryOffset )
-      , deviceIndexCount( rhs.deviceIndexCount )
-      , pDeviceIndices( rhs.pDeviceIndices )
-    {}
-
-    BindAccelerationStructureMemoryInfoNV & operator=( BindAccelerationStructureMemoryInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    BindAccelerationStructureMemoryInfoKHR & operator=( BindAccelerationStructureMemoryInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
-      memcpy( &pNext, &rhs.pNext, sizeof( BindAccelerationStructureMemoryInfoNV ) - offsetof( BindAccelerationStructureMemoryInfoNV, pNext ) );
+      memcpy( &pNext, &rhs.pNext, sizeof( BindAccelerationStructureMemoryInfoKHR ) - offsetof( BindAccelerationStructureMemoryInfoKHR, pNext ) );
       return *this;
     }
 
-    BindAccelerationStructureMemoryInfoNV( VkBindAccelerationStructureMemoryInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    BindAccelerationStructureMemoryInfoKHR( VkBindAccelerationStructureMemoryInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
     }
 
-    BindAccelerationStructureMemoryInfoNV& operator=( VkBindAccelerationStructureMemoryInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    BindAccelerationStructureMemoryInfoKHR& operator=( VkBindAccelerationStructureMemoryInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
-      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::BindAccelerationStructureMemoryInfoNV const *>(&rhs);
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::BindAccelerationStructureMemoryInfoKHR const *>(&rhs);
       return *this;
     }
 
-    BindAccelerationStructureMemoryInfoNV & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+    BindAccelerationStructureMemoryInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
     {
       pNext = pNext_;
       return *this;
     }
 
-    BindAccelerationStructureMemoryInfoNV & setAccelerationStructure( VULKAN_HPP_NAMESPACE::AccelerationStructureNV accelerationStructure_ ) VULKAN_HPP_NOEXCEPT
+    BindAccelerationStructureMemoryInfoKHR & setAccelerationStructure( VULKAN_HPP_NAMESPACE::AccelerationStructureKHR accelerationStructure_ ) VULKAN_HPP_NOEXCEPT
     {
       accelerationStructure = accelerationStructure_;
       return *this;
     }
 
-    BindAccelerationStructureMemoryInfoNV & setMemory( VULKAN_HPP_NAMESPACE::DeviceMemory memory_ ) VULKAN_HPP_NOEXCEPT
+    BindAccelerationStructureMemoryInfoKHR & setMemory( VULKAN_HPP_NAMESPACE::DeviceMemory memory_ ) VULKAN_HPP_NOEXCEPT
     {
       memory = memory_;
       return *this;
     }
 
-    BindAccelerationStructureMemoryInfoNV & setMemoryOffset( VULKAN_HPP_NAMESPACE::DeviceSize memoryOffset_ ) VULKAN_HPP_NOEXCEPT
+    BindAccelerationStructureMemoryInfoKHR & setMemoryOffset( VULKAN_HPP_NAMESPACE::DeviceSize memoryOffset_ ) VULKAN_HPP_NOEXCEPT
     {
       memoryOffset = memoryOffset_;
       return *this;
     }
 
-    BindAccelerationStructureMemoryInfoNV & setDeviceIndexCount( uint32_t deviceIndexCount_ ) VULKAN_HPP_NOEXCEPT
+    BindAccelerationStructureMemoryInfoKHR & setDeviceIndexCount( uint32_t deviceIndexCount_ ) VULKAN_HPP_NOEXCEPT
     {
       deviceIndexCount = deviceIndexCount_;
       return *this;
     }
 
-    BindAccelerationStructureMemoryInfoNV & setPDeviceIndices( const uint32_t* pDeviceIndices_ ) VULKAN_HPP_NOEXCEPT
+    BindAccelerationStructureMemoryInfoKHR & setPDeviceIndices( const uint32_t* pDeviceIndices_ ) VULKAN_HPP_NOEXCEPT
     {
       pDeviceIndices = pDeviceIndices_;
       return *this;
     }
 
-    operator VkBindAccelerationStructureMemoryInfoNV const&() const VULKAN_HPP_NOEXCEPT
+    operator VkBindAccelerationStructureMemoryInfoKHR const&() const VULKAN_HPP_NOEXCEPT
     {
-      return *reinterpret_cast<const VkBindAccelerationStructureMemoryInfoNV*>( this );
+      return *reinterpret_cast<const VkBindAccelerationStructureMemoryInfoKHR*>( this );
     }
 
-    operator VkBindAccelerationStructureMemoryInfoNV &() VULKAN_HPP_NOEXCEPT
+    operator VkBindAccelerationStructureMemoryInfoKHR &() VULKAN_HPP_NOEXCEPT
     {
-      return *reinterpret_cast<VkBindAccelerationStructureMemoryInfoNV*>( this );
+      return *reinterpret_cast<VkBindAccelerationStructureMemoryInfoKHR*>( this );
     }
 
 #if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
-    auto operator<=>( BindAccelerationStructureMemoryInfoNV const& ) const = default;
+    auto operator<=>( BindAccelerationStructureMemoryInfoKHR const& ) const = default;
 #else
-    bool operator==( BindAccelerationStructureMemoryInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+    bool operator==( BindAccelerationStructureMemoryInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
     {
       return ( sType == rhs.sType )
           && ( pNext == rhs.pNext )
@@ -22489,23 +24452,23 @@
           && ( pDeviceIndices == rhs.pDeviceIndices );
     }
 
-    bool operator!=( BindAccelerationStructureMemoryInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+    bool operator!=( BindAccelerationStructureMemoryInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
     {
       return !operator==( rhs );
     }
 #endif
 
   public:
-    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eBindAccelerationStructureMemoryInfoNV;
+    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eBindAccelerationStructureMemoryInfoKHR;
     const void* pNext = {};
-    VULKAN_HPP_NAMESPACE::AccelerationStructureNV accelerationStructure = {};
+    VULKAN_HPP_NAMESPACE::AccelerationStructureKHR accelerationStructure = {};
     VULKAN_HPP_NAMESPACE::DeviceMemory memory = {};
     VULKAN_HPP_NAMESPACE::DeviceSize memoryOffset = {};
     uint32_t deviceIndexCount = {};
     const uint32_t* pDeviceIndices = {};
   };
-  static_assert( sizeof( BindAccelerationStructureMemoryInfoNV ) == sizeof( VkBindAccelerationStructureMemoryInfoNV ), "struct and wrapper have different size!" );
-  static_assert( std::is_standard_layout<BindAccelerationStructureMemoryInfoNV>::value, "struct wrapper is not a standard layout!" );
+  static_assert( sizeof( BindAccelerationStructureMemoryInfoKHR ) == sizeof( VkBindAccelerationStructureMemoryInfoKHR ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<BindAccelerationStructureMemoryInfoKHR>::value, "struct wrapper is not a standard layout!" );
 
   struct BindBufferMemoryDeviceGroupInfo
   {
@@ -22515,12 +24478,6 @@
       , pDeviceIndices( pDeviceIndices_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR BindBufferMemoryDeviceGroupInfo( BindBufferMemoryDeviceGroupInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , deviceIndexCount( rhs.deviceIndexCount )
-      , pDeviceIndices( rhs.pDeviceIndices )
-    {}
-
     BindBufferMemoryDeviceGroupInfo & operator=( BindBufferMemoryDeviceGroupInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( BindBufferMemoryDeviceGroupInfo ) - offsetof( BindBufferMemoryDeviceGroupInfo, pNext ) );
@@ -22602,13 +24559,6 @@
       , memoryOffset( memoryOffset_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR BindBufferMemoryInfo( BindBufferMemoryInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , buffer( rhs.buffer )
-      , memory( rhs.memory )
-      , memoryOffset( rhs.memoryOffset )
-    {}
-
     BindBufferMemoryInfo & operator=( BindBufferMemoryInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( BindBufferMemoryInfo ) - offsetof( BindBufferMemoryInfo, pNext ) );
@@ -22696,17 +24646,6 @@
       , y( y_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR Offset2D( Offset2D const& rhs ) VULKAN_HPP_NOEXCEPT
-      : x( rhs.x )
-      , y( rhs.y )
-    {}
-
-    Offset2D & operator=( Offset2D const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( Offset2D ) );
-      return *this;
-    }
-
     Offset2D( VkOffset2D const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -22770,17 +24709,6 @@
       , extent( extent_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR Rect2D( Rect2D const& rhs ) VULKAN_HPP_NOEXCEPT
-      : offset( rhs.offset )
-      , extent( rhs.extent )
-    {}
-
-    Rect2D & operator=( Rect2D const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( Rect2D ) );
-      return *this;
-    }
-
     Rect2D( VkRect2D const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -22848,14 +24776,6 @@
       , pSplitInstanceBindRegions( pSplitInstanceBindRegions_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR BindImageMemoryDeviceGroupInfo( BindImageMemoryDeviceGroupInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , deviceIndexCount( rhs.deviceIndexCount )
-      , pDeviceIndices( rhs.pDeviceIndices )
-      , splitInstanceBindRegionCount( rhs.splitInstanceBindRegionCount )
-      , pSplitInstanceBindRegions( rhs.pSplitInstanceBindRegions )
-    {}
-
     BindImageMemoryDeviceGroupInfo & operator=( BindImageMemoryDeviceGroupInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( BindImageMemoryDeviceGroupInfo ) - offsetof( BindImageMemoryDeviceGroupInfo, pNext ) );
@@ -22953,13 +24873,6 @@
       , memoryOffset( memoryOffset_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR BindImageMemoryInfo( BindImageMemoryInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , image( rhs.image )
-      , memory( rhs.memory )
-      , memoryOffset( rhs.memoryOffset )
-    {}
-
     BindImageMemoryInfo & operator=( BindImageMemoryInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( BindImageMemoryInfo ) - offsetof( BindImageMemoryInfo, pNext ) );
@@ -23047,12 +24960,6 @@
       , imageIndex( imageIndex_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR BindImageMemorySwapchainInfoKHR( BindImageMemorySwapchainInfoKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , swapchain( rhs.swapchain )
-      , imageIndex( rhs.imageIndex )
-    {}
-
     BindImageMemorySwapchainInfoKHR & operator=( BindImageMemorySwapchainInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( BindImageMemorySwapchainInfoKHR ) - offsetof( BindImageMemorySwapchainInfoKHR, pNext ) );
@@ -23130,11 +25037,6 @@
       : planeAspect( planeAspect_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR BindImagePlaneMemoryInfo( BindImagePlaneMemoryInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , planeAspect( rhs.planeAspect )
-    {}
-
     BindImagePlaneMemoryInfo & operator=( BindImagePlaneMemoryInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( BindImagePlaneMemoryInfo ) - offsetof( BindImagePlaneMemoryInfo, pNext ) );
@@ -23198,6 +25100,132 @@
   static_assert( sizeof( BindImagePlaneMemoryInfo ) == sizeof( VkBindImagePlaneMemoryInfo ), "struct and wrapper have different size!" );
   static_assert( std::is_standard_layout<BindImagePlaneMemoryInfo>::value, "struct wrapper is not a standard layout!" );
 
+  struct BindIndexBufferIndirectCommandNV
+  {
+    VULKAN_HPP_CONSTEXPR BindIndexBufferIndirectCommandNV( VULKAN_HPP_NAMESPACE::DeviceAddress bufferAddress_ = {},
+                                                           uint32_t size_ = {},
+                                                           VULKAN_HPP_NAMESPACE::IndexType indexType_ = VULKAN_HPP_NAMESPACE::IndexType::eUint16 ) VULKAN_HPP_NOEXCEPT
+      : bufferAddress( bufferAddress_ )
+      , size( size_ )
+      , indexType( indexType_ )
+    {}
+
+    BindIndexBufferIndirectCommandNV( VkBindIndexBufferIndirectCommandNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    BindIndexBufferIndirectCommandNV& operator=( VkBindIndexBufferIndirectCommandNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::BindIndexBufferIndirectCommandNV const *>(&rhs);
+      return *this;
+    }
+
+    BindIndexBufferIndirectCommandNV & setBufferAddress( VULKAN_HPP_NAMESPACE::DeviceAddress bufferAddress_ ) VULKAN_HPP_NOEXCEPT
+    {
+      bufferAddress = bufferAddress_;
+      return *this;
+    }
+
+    BindIndexBufferIndirectCommandNV & setSize( uint32_t size_ ) VULKAN_HPP_NOEXCEPT
+    {
+      size = size_;
+      return *this;
+    }
+
+    BindIndexBufferIndirectCommandNV & setIndexType( VULKAN_HPP_NAMESPACE::IndexType indexType_ ) VULKAN_HPP_NOEXCEPT
+    {
+      indexType = indexType_;
+      return *this;
+    }
+
+    operator VkBindIndexBufferIndirectCommandNV const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkBindIndexBufferIndirectCommandNV*>( this );
+    }
+
+    operator VkBindIndexBufferIndirectCommandNV &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkBindIndexBufferIndirectCommandNV*>( this );
+    }
+
+#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
+    auto operator<=>( BindIndexBufferIndirectCommandNV const& ) const = default;
+#else
+    bool operator==( BindIndexBufferIndirectCommandNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ( bufferAddress == rhs.bufferAddress )
+          && ( size == rhs.size )
+          && ( indexType == rhs.indexType );
+    }
+
+    bool operator!=( BindIndexBufferIndirectCommandNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return !operator==( rhs );
+    }
+#endif
+
+  public:
+    VULKAN_HPP_NAMESPACE::DeviceAddress bufferAddress = {};
+    uint32_t size = {};
+    VULKAN_HPP_NAMESPACE::IndexType indexType = VULKAN_HPP_NAMESPACE::IndexType::eUint16;
+  };
+  static_assert( sizeof( BindIndexBufferIndirectCommandNV ) == sizeof( VkBindIndexBufferIndirectCommandNV ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<BindIndexBufferIndirectCommandNV>::value, "struct wrapper is not a standard layout!" );
+
+  struct BindShaderGroupIndirectCommandNV
+  {
+    VULKAN_HPP_CONSTEXPR BindShaderGroupIndirectCommandNV( uint32_t groupIndex_ = {} ) VULKAN_HPP_NOEXCEPT
+      : groupIndex( groupIndex_ )
+    {}
+
+    BindShaderGroupIndirectCommandNV( VkBindShaderGroupIndirectCommandNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    BindShaderGroupIndirectCommandNV& operator=( VkBindShaderGroupIndirectCommandNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::BindShaderGroupIndirectCommandNV const *>(&rhs);
+      return *this;
+    }
+
+    BindShaderGroupIndirectCommandNV & setGroupIndex( uint32_t groupIndex_ ) VULKAN_HPP_NOEXCEPT
+    {
+      groupIndex = groupIndex_;
+      return *this;
+    }
+
+    operator VkBindShaderGroupIndirectCommandNV const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkBindShaderGroupIndirectCommandNV*>( this );
+    }
+
+    operator VkBindShaderGroupIndirectCommandNV &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkBindShaderGroupIndirectCommandNV*>( this );
+    }
+
+#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
+    auto operator<=>( BindShaderGroupIndirectCommandNV const& ) const = default;
+#else
+    bool operator==( BindShaderGroupIndirectCommandNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ( groupIndex == rhs.groupIndex );
+    }
+
+    bool operator!=( BindShaderGroupIndirectCommandNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return !operator==( rhs );
+    }
+#endif
+
+  public:
+    uint32_t groupIndex = {};
+  };
+  static_assert( sizeof( BindShaderGroupIndirectCommandNV ) == sizeof( VkBindShaderGroupIndirectCommandNV ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<BindShaderGroupIndirectCommandNV>::value, "struct wrapper is not a standard layout!" );
+
   struct SparseMemoryBind
   {
     VULKAN_HPP_CONSTEXPR SparseMemoryBind( VULKAN_HPP_NAMESPACE::DeviceSize resourceOffset_ = {},
@@ -23212,20 +25240,6 @@
       , flags( flags_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SparseMemoryBind( SparseMemoryBind const& rhs ) VULKAN_HPP_NOEXCEPT
-      : resourceOffset( rhs.resourceOffset )
-      , size( rhs.size )
-      , memory( rhs.memory )
-      , memoryOffset( rhs.memoryOffset )
-      , flags( rhs.flags )
-    {}
-
-    SparseMemoryBind & operator=( SparseMemoryBind const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( SparseMemoryBind ) );
-      return *this;
-    }
-
     SparseMemoryBind( VkSparseMemoryBind const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -23315,18 +25329,6 @@
       , pBinds( pBinds_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SparseBufferMemoryBindInfo( SparseBufferMemoryBindInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : buffer( rhs.buffer )
-      , bindCount( rhs.bindCount )
-      , pBinds( rhs.pBinds )
-    {}
-
-    SparseBufferMemoryBindInfo & operator=( SparseBufferMemoryBindInfo const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( SparseBufferMemoryBindInfo ) );
-      return *this;
-    }
-
     SparseBufferMemoryBindInfo( VkSparseBufferMemoryBindInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -23400,18 +25402,6 @@
       , pBinds( pBinds_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SparseImageOpaqueMemoryBindInfo( SparseImageOpaqueMemoryBindInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : image( rhs.image )
-      , bindCount( rhs.bindCount )
-      , pBinds( rhs.pBinds )
-    {}
-
-    SparseImageOpaqueMemoryBindInfo & operator=( SparseImageOpaqueMemoryBindInfo const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( SparseImageOpaqueMemoryBindInfo ) );
-      return *this;
-    }
-
     SparseImageOpaqueMemoryBindInfo( VkSparseImageOpaqueMemoryBindInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -23485,18 +25475,6 @@
       , arrayLayer( arrayLayer_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ImageSubresource( ImageSubresource const& rhs ) VULKAN_HPP_NOEXCEPT
-      : aspectMask( rhs.aspectMask )
-      , mipLevel( rhs.mipLevel )
-      , arrayLayer( rhs.arrayLayer )
-    {}
-
-    ImageSubresource & operator=( ImageSubresource const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( ImageSubresource ) );
-      return *this;
-    }
-
     ImageSubresource( VkImageSubresource const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -23570,12 +25548,6 @@
       , z( z_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR Offset3D( Offset3D const& rhs ) VULKAN_HPP_NOEXCEPT
-      : x( rhs.x )
-      , y( rhs.y )
-      , z( rhs.z )
-    {}
-
     explicit Offset3D( Offset2D const& offset2D,
                        int32_t z_ = {} )
       : x( offset2D.x )
@@ -23583,12 +25555,6 @@
       , z( z_ )
     {}
 
-    Offset3D & operator=( Offset3D const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( Offset3D ) );
-      return *this;
-    }
-
     Offset3D( VkOffset3D const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -23662,12 +25628,6 @@
       , depth( depth_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR Extent3D( Extent3D const& rhs ) VULKAN_HPP_NOEXCEPT
-      : width( rhs.width )
-      , height( rhs.height )
-      , depth( rhs.depth )
-    {}
-
     explicit Extent3D( Extent2D const& extent2D,
                        uint32_t depth_ = {} )
       : width( extent2D.width )
@@ -23675,12 +25635,6 @@
       , depth( depth_ )
     {}
 
-    Extent3D & operator=( Extent3D const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( Extent3D ) );
-      return *this;
-    }
-
     Extent3D( VkExtent3D const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -23760,21 +25714,6 @@
       , flags( flags_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SparseImageMemoryBind( SparseImageMemoryBind const& rhs ) VULKAN_HPP_NOEXCEPT
-      : subresource( rhs.subresource )
-      , offset( rhs.offset )
-      , extent( rhs.extent )
-      , memory( rhs.memory )
-      , memoryOffset( rhs.memoryOffset )
-      , flags( rhs.flags )
-    {}
-
-    SparseImageMemoryBind & operator=( SparseImageMemoryBind const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( SparseImageMemoryBind ) );
-      return *this;
-    }
-
     SparseImageMemoryBind( VkSparseImageMemoryBind const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -23872,18 +25811,6 @@
       , pBinds( pBinds_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SparseImageMemoryBindInfo( SparseImageMemoryBindInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : image( rhs.image )
-      , bindCount( rhs.bindCount )
-      , pBinds( rhs.pBinds )
-    {}
-
-    SparseImageMemoryBindInfo & operator=( SparseImageMemoryBindInfo const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( SparseImageMemoryBindInfo ) );
-      return *this;
-    }
-
     SparseImageMemoryBindInfo( VkSparseImageMemoryBindInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -23971,20 +25898,6 @@
       , pSignalSemaphores( pSignalSemaphores_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR BindSparseInfo( BindSparseInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , waitSemaphoreCount( rhs.waitSemaphoreCount )
-      , pWaitSemaphores( rhs.pWaitSemaphores )
-      , bufferBindCount( rhs.bufferBindCount )
-      , pBufferBinds( rhs.pBufferBinds )
-      , imageOpaqueBindCount( rhs.imageOpaqueBindCount )
-      , pImageOpaqueBinds( rhs.pImageOpaqueBinds )
-      , imageBindCount( rhs.imageBindCount )
-      , pImageBinds( rhs.pImageBinds )
-      , signalSemaphoreCount( rhs.signalSemaphoreCount )
-      , pSignalSemaphores( rhs.pSignalSemaphores )
-    {}
-
     BindSparseInfo & operator=( BindSparseInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( BindSparseInfo ) - offsetof( BindSparseInfo, pNext ) );
@@ -24120,6 +26033,79 @@
   static_assert( sizeof( BindSparseInfo ) == sizeof( VkBindSparseInfo ), "struct and wrapper have different size!" );
   static_assert( std::is_standard_layout<BindSparseInfo>::value, "struct wrapper is not a standard layout!" );
 
+  struct BindVertexBufferIndirectCommandNV
+  {
+    VULKAN_HPP_CONSTEXPR BindVertexBufferIndirectCommandNV( VULKAN_HPP_NAMESPACE::DeviceAddress bufferAddress_ = {},
+                                                            uint32_t size_ = {},
+                                                            uint32_t stride_ = {} ) VULKAN_HPP_NOEXCEPT
+      : bufferAddress( bufferAddress_ )
+      , size( size_ )
+      , stride( stride_ )
+    {}
+
+    BindVertexBufferIndirectCommandNV( VkBindVertexBufferIndirectCommandNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    BindVertexBufferIndirectCommandNV& operator=( VkBindVertexBufferIndirectCommandNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::BindVertexBufferIndirectCommandNV const *>(&rhs);
+      return *this;
+    }
+
+    BindVertexBufferIndirectCommandNV & setBufferAddress( VULKAN_HPP_NAMESPACE::DeviceAddress bufferAddress_ ) VULKAN_HPP_NOEXCEPT
+    {
+      bufferAddress = bufferAddress_;
+      return *this;
+    }
+
+    BindVertexBufferIndirectCommandNV & setSize( uint32_t size_ ) VULKAN_HPP_NOEXCEPT
+    {
+      size = size_;
+      return *this;
+    }
+
+    BindVertexBufferIndirectCommandNV & setStride( uint32_t stride_ ) VULKAN_HPP_NOEXCEPT
+    {
+      stride = stride_;
+      return *this;
+    }
+
+    operator VkBindVertexBufferIndirectCommandNV const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkBindVertexBufferIndirectCommandNV*>( this );
+    }
+
+    operator VkBindVertexBufferIndirectCommandNV &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkBindVertexBufferIndirectCommandNV*>( this );
+    }
+
+#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
+    auto operator<=>( BindVertexBufferIndirectCommandNV const& ) const = default;
+#else
+    bool operator==( BindVertexBufferIndirectCommandNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ( bufferAddress == rhs.bufferAddress )
+          && ( size == rhs.size )
+          && ( stride == rhs.stride );
+    }
+
+    bool operator!=( BindVertexBufferIndirectCommandNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return !operator==( rhs );
+    }
+#endif
+
+  public:
+    VULKAN_HPP_NAMESPACE::DeviceAddress bufferAddress = {};
+    uint32_t size = {};
+    uint32_t stride = {};
+  };
+  static_assert( sizeof( BindVertexBufferIndirectCommandNV ) == sizeof( VkBindVertexBufferIndirectCommandNV ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<BindVertexBufferIndirectCommandNV>::value, "struct wrapper is not a standard layout!" );
+
   struct BufferCopy
   {
     VULKAN_HPP_CONSTEXPR BufferCopy( VULKAN_HPP_NAMESPACE::DeviceSize srcOffset_ = {},
@@ -24130,18 +26116,6 @@
       , size( size_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR BufferCopy( BufferCopy const& rhs ) VULKAN_HPP_NOEXCEPT
-      : srcOffset( rhs.srcOffset )
-      , dstOffset( rhs.dstOffset )
-      , size( rhs.size )
-    {}
-
-    BufferCopy & operator=( BufferCopy const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( BufferCopy ) );
-      return *this;
-    }
-
     BufferCopy( VkBufferCopy const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -24221,16 +26195,6 @@
       , pQueueFamilyIndices( pQueueFamilyIndices_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR BufferCreateInfo( BufferCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , size( rhs.size )
-      , usage( rhs.usage )
-      , sharingMode( rhs.sharingMode )
-      , queueFamilyIndexCount( rhs.queueFamilyIndexCount )
-      , pQueueFamilyIndices( rhs.pQueueFamilyIndices )
-    {}
-
     BufferCreateInfo & operator=( BufferCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( BufferCreateInfo ) - offsetof( BufferCreateInfo, pNext ) );
@@ -24340,11 +26304,6 @@
       : deviceAddress( deviceAddress_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR BufferDeviceAddressCreateInfoEXT( BufferDeviceAddressCreateInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , deviceAddress( rhs.deviceAddress )
-    {}
-
     BufferDeviceAddressCreateInfoEXT & operator=( BufferDeviceAddressCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( BufferDeviceAddressCreateInfoEXT ) - offsetof( BufferDeviceAddressCreateInfoEXT, pNext ) );
@@ -24414,11 +26373,6 @@
       : buffer( buffer_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR BufferDeviceAddressInfo( BufferDeviceAddressInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , buffer( rhs.buffer )
-    {}
-
     BufferDeviceAddressInfo & operator=( BufferDeviceAddressInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( BufferDeviceAddressInfo ) - offsetof( BufferDeviceAddressInfo, pNext ) );
@@ -24494,19 +26448,6 @@
       , layerCount( layerCount_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ImageSubresourceLayers( ImageSubresourceLayers const& rhs ) VULKAN_HPP_NOEXCEPT
-      : aspectMask( rhs.aspectMask )
-      , mipLevel( rhs.mipLevel )
-      , baseArrayLayer( rhs.baseArrayLayer )
-      , layerCount( rhs.layerCount )
-    {}
-
-    ImageSubresourceLayers & operator=( ImageSubresourceLayers const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( ImageSubresourceLayers ) );
-      return *this;
-    }
-
     ImageSubresourceLayers( VkImageSubresourceLayers const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -24594,21 +26535,6 @@
       , imageExtent( imageExtent_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR BufferImageCopy( BufferImageCopy const& rhs ) VULKAN_HPP_NOEXCEPT
-      : bufferOffset( rhs.bufferOffset )
-      , bufferRowLength( rhs.bufferRowLength )
-      , bufferImageHeight( rhs.bufferImageHeight )
-      , imageSubresource( rhs.imageSubresource )
-      , imageOffset( rhs.imageOffset )
-      , imageExtent( rhs.imageExtent )
-    {}
-
-    BufferImageCopy & operator=( BufferImageCopy const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( BufferImageCopy ) );
-      return *this;
-    }
-
     BufferImageCopy( VkBufferImageCopy const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -24714,17 +26640,6 @@
       , size( size_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR BufferMemoryBarrier( BufferMemoryBarrier const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , srcAccessMask( rhs.srcAccessMask )
-      , dstAccessMask( rhs.dstAccessMask )
-      , srcQueueFamilyIndex( rhs.srcQueueFamilyIndex )
-      , dstQueueFamilyIndex( rhs.dstQueueFamilyIndex )
-      , buffer( rhs.buffer )
-      , offset( rhs.offset )
-      , size( rhs.size )
-    {}
-
     BufferMemoryBarrier & operator=( BufferMemoryBarrier const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( BufferMemoryBarrier ) - offsetof( BufferMemoryBarrier, pNext ) );
@@ -24842,11 +26757,6 @@
       : buffer( buffer_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR BufferMemoryRequirementsInfo2( BufferMemoryRequirementsInfo2 const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , buffer( rhs.buffer )
-    {}
-
     BufferMemoryRequirementsInfo2 & operator=( BufferMemoryRequirementsInfo2 const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( BufferMemoryRequirementsInfo2 ) - offsetof( BufferMemoryRequirementsInfo2, pNext ) );
@@ -24916,11 +26826,6 @@
       : opaqueCaptureAddress( opaqueCaptureAddress_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR BufferOpaqueCaptureAddressCreateInfo( BufferOpaqueCaptureAddressCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , opaqueCaptureAddress( rhs.opaqueCaptureAddress )
-    {}
-
     BufferOpaqueCaptureAddressCreateInfo & operator=( BufferOpaqueCaptureAddressCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( BufferOpaqueCaptureAddressCreateInfo ) - offsetof( BufferOpaqueCaptureAddressCreateInfo, pNext ) );
@@ -24998,15 +26903,6 @@
       , range( range_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR BufferViewCreateInfo( BufferViewCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , buffer( rhs.buffer )
-      , format( rhs.format )
-      , offset( rhs.offset )
-      , range( rhs.range )
-    {}
-
     BufferViewCreateInfo & operator=( BufferViewCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( BufferViewCreateInfo ) - offsetof( BufferViewCreateInfo, pNext ) );
@@ -25108,11 +27004,6 @@
       : timeDomain( timeDomain_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR CalibratedTimestampInfoEXT( CalibratedTimestampInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , timeDomain( rhs.timeDomain )
-    {}
-
     CalibratedTimestampInfoEXT & operator=( CalibratedTimestampInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( CalibratedTimestampInfoEXT ) - offsetof( CalibratedTimestampInfoEXT, pNext ) );
@@ -25184,12 +27075,6 @@
       , pCheckpointMarker( pCheckpointMarker_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR CheckpointDataNV( CheckpointDataNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , stage( rhs.stage )
-      , pCheckpointMarker( rhs.pCheckpointMarker )
-    {}
-
     CheckpointDataNV & operator=( CheckpointDataNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( CheckpointDataNV ) - offsetof( CheckpointDataNV, pNext ) );
@@ -25252,34 +27137,34 @@
 
     ClearColorValue( const std::array<float,4>& float32_ = {} )
     {
-      memcpy( float32, float32_.data(), 4 * sizeof( float ) );
+      float32 = float32_;
     }
 
     ClearColorValue( const std::array<int32_t,4>& int32_ )
     {
-      memcpy( int32, int32_.data(), 4 * sizeof( int32_t ) );
+      int32 = int32_;
     }
 
     ClearColorValue( const std::array<uint32_t,4>& uint32_ )
     {
-      memcpy( uint32, uint32_.data(), 4 * sizeof( uint32_t ) );
+      uint32 = uint32_;
     }
 
     ClearColorValue & setFloat32( std::array<float,4> float32_ ) VULKAN_HPP_NOEXCEPT
     {
-      memcpy( float32, float32_.data(), 4 * sizeof( float ) );
+      float32 = float32_;
       return *this;
     }
 
     ClearColorValue & setInt32( std::array<int32_t,4> int32_ ) VULKAN_HPP_NOEXCEPT
     {
-      memcpy( int32, int32_.data(), 4 * sizeof( int32_t ) );
+      int32 = int32_;
       return *this;
     }
 
     ClearColorValue & setUint32( std::array<uint32_t,4> uint32_ ) VULKAN_HPP_NOEXCEPT
     {
-      memcpy( uint32, uint32_.data(), 4 * sizeof( uint32_t ) );
+      uint32 = uint32_;
       return *this;
     }
 
@@ -25299,9 +27184,9 @@
       return *reinterpret_cast<VkClearColorValue*>(this);
     }
 
-    float float32[4];
-    int32_t int32[4];
-    uint32_t uint32[4];
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<float, 4> float32;
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<int32_t, 4> int32;
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<uint32_t, 4> uint32;
   };
 
   struct ClearDepthStencilValue
@@ -25312,17 +27197,6 @@
       , stencil( stencil_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ClearDepthStencilValue( ClearDepthStencilValue const& rhs ) VULKAN_HPP_NOEXCEPT
-      : depth( rhs.depth )
-      , stencil( rhs.stencil )
-    {}
-
-    ClearDepthStencilValue & operator=( ClearDepthStencilValue const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( ClearDepthStencilValue ) );
-      return *this;
-    }
-
     ClearDepthStencilValue( VkClearDepthStencilValue const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -25442,18 +27316,6 @@
       , clearValue( clearValue_ )
     {}
 
-    ClearAttachment( ClearAttachment const& rhs ) VULKAN_HPP_NOEXCEPT
-      : aspectMask( rhs.aspectMask )
-      , colorAttachment( rhs.colorAttachment )
-      , clearValue( rhs.clearValue )
-    {}
-
-    ClearAttachment & operator=( ClearAttachment const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( ClearAttachment ) );
-      return *this;
-    }
-
     ClearAttachment( VkClearAttachment const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -25511,18 +27373,6 @@
       , layerCount( layerCount_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ClearRect( ClearRect const& rhs ) VULKAN_HPP_NOEXCEPT
-      : rect( rhs.rect )
-      , baseArrayLayer( rhs.baseArrayLayer )
-      , layerCount( rhs.layerCount )
-    {}
-
-    ClearRect & operator=( ClearRect const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( ClearRect ) );
-      return *this;
-    }
-
     ClearRect( VkClearRect const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -25586,360 +27436,6 @@
   static_assert( sizeof( ClearRect ) == sizeof( VkClearRect ), "struct and wrapper have different size!" );
   static_assert( std::is_standard_layout<ClearRect>::value, "struct wrapper is not a standard layout!" );
 
-  struct IndirectCommandsTokenNVX
-  {
-    VULKAN_HPP_CONSTEXPR IndirectCommandsTokenNVX( VULKAN_HPP_NAMESPACE::IndirectCommandsTokenTypeNVX tokenType_ = VULKAN_HPP_NAMESPACE::IndirectCommandsTokenTypeNVX::ePipeline,
-                                                   VULKAN_HPP_NAMESPACE::Buffer buffer_ = {},
-                                                   VULKAN_HPP_NAMESPACE::DeviceSize offset_ = {} ) VULKAN_HPP_NOEXCEPT
-      : tokenType( tokenType_ )
-      , buffer( buffer_ )
-      , offset( offset_ )
-    {}
-
-    VULKAN_HPP_CONSTEXPR IndirectCommandsTokenNVX( IndirectCommandsTokenNVX const& rhs ) VULKAN_HPP_NOEXCEPT
-      : tokenType( rhs.tokenType )
-      , buffer( rhs.buffer )
-      , offset( rhs.offset )
-    {}
-
-    IndirectCommandsTokenNVX & operator=( IndirectCommandsTokenNVX const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( IndirectCommandsTokenNVX ) );
-      return *this;
-    }
-
-    IndirectCommandsTokenNVX( VkIndirectCommandsTokenNVX const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      *this = rhs;
-    }
-
-    IndirectCommandsTokenNVX& operator=( VkIndirectCommandsTokenNVX const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::IndirectCommandsTokenNVX const *>(&rhs);
-      return *this;
-    }
-
-    IndirectCommandsTokenNVX & setTokenType( VULKAN_HPP_NAMESPACE::IndirectCommandsTokenTypeNVX tokenType_ ) VULKAN_HPP_NOEXCEPT
-    {
-      tokenType = tokenType_;
-      return *this;
-    }
-
-    IndirectCommandsTokenNVX & setBuffer( VULKAN_HPP_NAMESPACE::Buffer buffer_ ) VULKAN_HPP_NOEXCEPT
-    {
-      buffer = buffer_;
-      return *this;
-    }
-
-    IndirectCommandsTokenNVX & setOffset( VULKAN_HPP_NAMESPACE::DeviceSize offset_ ) VULKAN_HPP_NOEXCEPT
-    {
-      offset = offset_;
-      return *this;
-    }
-
-    operator VkIndirectCommandsTokenNVX const&() const VULKAN_HPP_NOEXCEPT
-    {
-      return *reinterpret_cast<const VkIndirectCommandsTokenNVX*>( this );
-    }
-
-    operator VkIndirectCommandsTokenNVX &() VULKAN_HPP_NOEXCEPT
-    {
-      return *reinterpret_cast<VkIndirectCommandsTokenNVX*>( this );
-    }
-
-#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
-    auto operator<=>( IndirectCommandsTokenNVX const& ) const = default;
-#else
-    bool operator==( IndirectCommandsTokenNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
-    {
-      return ( tokenType == rhs.tokenType )
-          && ( buffer == rhs.buffer )
-          && ( offset == rhs.offset );
-    }
-
-    bool operator!=( IndirectCommandsTokenNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
-    {
-      return !operator==( rhs );
-    }
-#endif
-
-  public:
-    VULKAN_HPP_NAMESPACE::IndirectCommandsTokenTypeNVX tokenType = VULKAN_HPP_NAMESPACE::IndirectCommandsTokenTypeNVX::ePipeline;
-    VULKAN_HPP_NAMESPACE::Buffer buffer = {};
-    VULKAN_HPP_NAMESPACE::DeviceSize offset = {};
-  };
-  static_assert( sizeof( IndirectCommandsTokenNVX ) == sizeof( VkIndirectCommandsTokenNVX ), "struct and wrapper have different size!" );
-  static_assert( std::is_standard_layout<IndirectCommandsTokenNVX>::value, "struct wrapper is not a standard layout!" );
-
-  struct CmdProcessCommandsInfoNVX
-  {
-    VULKAN_HPP_CONSTEXPR CmdProcessCommandsInfoNVX( VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable_ = {},
-                                                    VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNVX indirectCommandsLayout_ = {},
-                                                    uint32_t indirectCommandsTokenCount_ = {},
-                                                    const VULKAN_HPP_NAMESPACE::IndirectCommandsTokenNVX* pIndirectCommandsTokens_ = {},
-                                                    uint32_t maxSequencesCount_ = {},
-                                                    VULKAN_HPP_NAMESPACE::CommandBuffer targetCommandBuffer_ = {},
-                                                    VULKAN_HPP_NAMESPACE::Buffer sequencesCountBuffer_ = {},
-                                                    VULKAN_HPP_NAMESPACE::DeviceSize sequencesCountOffset_ = {},
-                                                    VULKAN_HPP_NAMESPACE::Buffer sequencesIndexBuffer_ = {},
-                                                    VULKAN_HPP_NAMESPACE::DeviceSize sequencesIndexOffset_ = {} ) VULKAN_HPP_NOEXCEPT
-      : objectTable( objectTable_ )
-      , indirectCommandsLayout( indirectCommandsLayout_ )
-      , indirectCommandsTokenCount( indirectCommandsTokenCount_ )
-      , pIndirectCommandsTokens( pIndirectCommandsTokens_ )
-      , maxSequencesCount( maxSequencesCount_ )
-      , targetCommandBuffer( targetCommandBuffer_ )
-      , sequencesCountBuffer( sequencesCountBuffer_ )
-      , sequencesCountOffset( sequencesCountOffset_ )
-      , sequencesIndexBuffer( sequencesIndexBuffer_ )
-      , sequencesIndexOffset( sequencesIndexOffset_ )
-    {}
-
-    VULKAN_HPP_CONSTEXPR CmdProcessCommandsInfoNVX( CmdProcessCommandsInfoNVX const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , objectTable( rhs.objectTable )
-      , indirectCommandsLayout( rhs.indirectCommandsLayout )
-      , indirectCommandsTokenCount( rhs.indirectCommandsTokenCount )
-      , pIndirectCommandsTokens( rhs.pIndirectCommandsTokens )
-      , maxSequencesCount( rhs.maxSequencesCount )
-      , targetCommandBuffer( rhs.targetCommandBuffer )
-      , sequencesCountBuffer( rhs.sequencesCountBuffer )
-      , sequencesCountOffset( rhs.sequencesCountOffset )
-      , sequencesIndexBuffer( rhs.sequencesIndexBuffer )
-      , sequencesIndexOffset( rhs.sequencesIndexOffset )
-    {}
-
-    CmdProcessCommandsInfoNVX & operator=( CmdProcessCommandsInfoNVX const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( &pNext, &rhs.pNext, sizeof( CmdProcessCommandsInfoNVX ) - offsetof( CmdProcessCommandsInfoNVX, pNext ) );
-      return *this;
-    }
-
-    CmdProcessCommandsInfoNVX( VkCmdProcessCommandsInfoNVX const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      *this = rhs;
-    }
-
-    CmdProcessCommandsInfoNVX& operator=( VkCmdProcessCommandsInfoNVX const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::CmdProcessCommandsInfoNVX const *>(&rhs);
-      return *this;
-    }
-
-    CmdProcessCommandsInfoNVX & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
-    {
-      pNext = pNext_;
-      return *this;
-    }
-
-    CmdProcessCommandsInfoNVX & setObjectTable( VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable_ ) VULKAN_HPP_NOEXCEPT
-    {
-      objectTable = objectTable_;
-      return *this;
-    }
-
-    CmdProcessCommandsInfoNVX & setIndirectCommandsLayout( VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNVX indirectCommandsLayout_ ) VULKAN_HPP_NOEXCEPT
-    {
-      indirectCommandsLayout = indirectCommandsLayout_;
-      return *this;
-    }
-
-    CmdProcessCommandsInfoNVX & setIndirectCommandsTokenCount( uint32_t indirectCommandsTokenCount_ ) VULKAN_HPP_NOEXCEPT
-    {
-      indirectCommandsTokenCount = indirectCommandsTokenCount_;
-      return *this;
-    }
-
-    CmdProcessCommandsInfoNVX & setPIndirectCommandsTokens( const VULKAN_HPP_NAMESPACE::IndirectCommandsTokenNVX* pIndirectCommandsTokens_ ) VULKAN_HPP_NOEXCEPT
-    {
-      pIndirectCommandsTokens = pIndirectCommandsTokens_;
-      return *this;
-    }
-
-    CmdProcessCommandsInfoNVX & setMaxSequencesCount( uint32_t maxSequencesCount_ ) VULKAN_HPP_NOEXCEPT
-    {
-      maxSequencesCount = maxSequencesCount_;
-      return *this;
-    }
-
-    CmdProcessCommandsInfoNVX & setTargetCommandBuffer( VULKAN_HPP_NAMESPACE::CommandBuffer targetCommandBuffer_ ) VULKAN_HPP_NOEXCEPT
-    {
-      targetCommandBuffer = targetCommandBuffer_;
-      return *this;
-    }
-
-    CmdProcessCommandsInfoNVX & setSequencesCountBuffer( VULKAN_HPP_NAMESPACE::Buffer sequencesCountBuffer_ ) VULKAN_HPP_NOEXCEPT
-    {
-      sequencesCountBuffer = sequencesCountBuffer_;
-      return *this;
-    }
-
-    CmdProcessCommandsInfoNVX & setSequencesCountOffset( VULKAN_HPP_NAMESPACE::DeviceSize sequencesCountOffset_ ) VULKAN_HPP_NOEXCEPT
-    {
-      sequencesCountOffset = sequencesCountOffset_;
-      return *this;
-    }
-
-    CmdProcessCommandsInfoNVX & setSequencesIndexBuffer( VULKAN_HPP_NAMESPACE::Buffer sequencesIndexBuffer_ ) VULKAN_HPP_NOEXCEPT
-    {
-      sequencesIndexBuffer = sequencesIndexBuffer_;
-      return *this;
-    }
-
-    CmdProcessCommandsInfoNVX & setSequencesIndexOffset( VULKAN_HPP_NAMESPACE::DeviceSize sequencesIndexOffset_ ) VULKAN_HPP_NOEXCEPT
-    {
-      sequencesIndexOffset = sequencesIndexOffset_;
-      return *this;
-    }
-
-    operator VkCmdProcessCommandsInfoNVX const&() const VULKAN_HPP_NOEXCEPT
-    {
-      return *reinterpret_cast<const VkCmdProcessCommandsInfoNVX*>( this );
-    }
-
-    operator VkCmdProcessCommandsInfoNVX &() VULKAN_HPP_NOEXCEPT
-    {
-      return *reinterpret_cast<VkCmdProcessCommandsInfoNVX*>( this );
-    }
-
-#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
-    auto operator<=>( CmdProcessCommandsInfoNVX const& ) const = default;
-#else
-    bool operator==( CmdProcessCommandsInfoNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
-    {
-      return ( sType == rhs.sType )
-          && ( pNext == rhs.pNext )
-          && ( objectTable == rhs.objectTable )
-          && ( indirectCommandsLayout == rhs.indirectCommandsLayout )
-          && ( indirectCommandsTokenCount == rhs.indirectCommandsTokenCount )
-          && ( pIndirectCommandsTokens == rhs.pIndirectCommandsTokens )
-          && ( maxSequencesCount == rhs.maxSequencesCount )
-          && ( targetCommandBuffer == rhs.targetCommandBuffer )
-          && ( sequencesCountBuffer == rhs.sequencesCountBuffer )
-          && ( sequencesCountOffset == rhs.sequencesCountOffset )
-          && ( sequencesIndexBuffer == rhs.sequencesIndexBuffer )
-          && ( sequencesIndexOffset == rhs.sequencesIndexOffset );
-    }
-
-    bool operator!=( CmdProcessCommandsInfoNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
-    {
-      return !operator==( rhs );
-    }
-#endif
-
-  public:
-    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eCmdProcessCommandsInfoNVX;
-    const void* pNext = {};
-    VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable = {};
-    VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNVX indirectCommandsLayout = {};
-    uint32_t indirectCommandsTokenCount = {};
-    const VULKAN_HPP_NAMESPACE::IndirectCommandsTokenNVX* pIndirectCommandsTokens = {};
-    uint32_t maxSequencesCount = {};
-    VULKAN_HPP_NAMESPACE::CommandBuffer targetCommandBuffer = {};
-    VULKAN_HPP_NAMESPACE::Buffer sequencesCountBuffer = {};
-    VULKAN_HPP_NAMESPACE::DeviceSize sequencesCountOffset = {};
-    VULKAN_HPP_NAMESPACE::Buffer sequencesIndexBuffer = {};
-    VULKAN_HPP_NAMESPACE::DeviceSize sequencesIndexOffset = {};
-  };
-  static_assert( sizeof( CmdProcessCommandsInfoNVX ) == sizeof( VkCmdProcessCommandsInfoNVX ), "struct and wrapper have different size!" );
-  static_assert( std::is_standard_layout<CmdProcessCommandsInfoNVX>::value, "struct wrapper is not a standard layout!" );
-
-  struct CmdReserveSpaceForCommandsInfoNVX
-  {
-    VULKAN_HPP_CONSTEXPR CmdReserveSpaceForCommandsInfoNVX( VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable_ = {},
-                                                            VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNVX indirectCommandsLayout_ = {},
-                                                            uint32_t maxSequencesCount_ = {} ) VULKAN_HPP_NOEXCEPT
-      : objectTable( objectTable_ )
-      , indirectCommandsLayout( indirectCommandsLayout_ )
-      , maxSequencesCount( maxSequencesCount_ )
-    {}
-
-    VULKAN_HPP_CONSTEXPR CmdReserveSpaceForCommandsInfoNVX( CmdReserveSpaceForCommandsInfoNVX const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , objectTable( rhs.objectTable )
-      , indirectCommandsLayout( rhs.indirectCommandsLayout )
-      , maxSequencesCount( rhs.maxSequencesCount )
-    {}
-
-    CmdReserveSpaceForCommandsInfoNVX & operator=( CmdReserveSpaceForCommandsInfoNVX const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( &pNext, &rhs.pNext, sizeof( CmdReserveSpaceForCommandsInfoNVX ) - offsetof( CmdReserveSpaceForCommandsInfoNVX, pNext ) );
-      return *this;
-    }
-
-    CmdReserveSpaceForCommandsInfoNVX( VkCmdReserveSpaceForCommandsInfoNVX const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      *this = rhs;
-    }
-
-    CmdReserveSpaceForCommandsInfoNVX& operator=( VkCmdReserveSpaceForCommandsInfoNVX const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::CmdReserveSpaceForCommandsInfoNVX const *>(&rhs);
-      return *this;
-    }
-
-    CmdReserveSpaceForCommandsInfoNVX & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
-    {
-      pNext = pNext_;
-      return *this;
-    }
-
-    CmdReserveSpaceForCommandsInfoNVX & setObjectTable( VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable_ ) VULKAN_HPP_NOEXCEPT
-    {
-      objectTable = objectTable_;
-      return *this;
-    }
-
-    CmdReserveSpaceForCommandsInfoNVX & setIndirectCommandsLayout( VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNVX indirectCommandsLayout_ ) VULKAN_HPP_NOEXCEPT
-    {
-      indirectCommandsLayout = indirectCommandsLayout_;
-      return *this;
-    }
-
-    CmdReserveSpaceForCommandsInfoNVX & setMaxSequencesCount( uint32_t maxSequencesCount_ ) VULKAN_HPP_NOEXCEPT
-    {
-      maxSequencesCount = maxSequencesCount_;
-      return *this;
-    }
-
-    operator VkCmdReserveSpaceForCommandsInfoNVX const&() const VULKAN_HPP_NOEXCEPT
-    {
-      return *reinterpret_cast<const VkCmdReserveSpaceForCommandsInfoNVX*>( this );
-    }
-
-    operator VkCmdReserveSpaceForCommandsInfoNVX &() VULKAN_HPP_NOEXCEPT
-    {
-      return *reinterpret_cast<VkCmdReserveSpaceForCommandsInfoNVX*>( this );
-    }
-
-#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
-    auto operator<=>( CmdReserveSpaceForCommandsInfoNVX const& ) const = default;
-#else
-    bool operator==( CmdReserveSpaceForCommandsInfoNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
-    {
-      return ( sType == rhs.sType )
-          && ( pNext == rhs.pNext )
-          && ( objectTable == rhs.objectTable )
-          && ( indirectCommandsLayout == rhs.indirectCommandsLayout )
-          && ( maxSequencesCount == rhs.maxSequencesCount );
-    }
-
-    bool operator!=( CmdReserveSpaceForCommandsInfoNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
-    {
-      return !operator==( rhs );
-    }
-#endif
-
-  public:
-    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eCmdReserveSpaceForCommandsInfoNVX;
-    const void* pNext = {};
-    VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable = {};
-    VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNVX indirectCommandsLayout = {};
-    uint32_t maxSequencesCount = {};
-  };
-  static_assert( sizeof( CmdReserveSpaceForCommandsInfoNVX ) == sizeof( VkCmdReserveSpaceForCommandsInfoNVX ), "struct and wrapper have different size!" );
-  static_assert( std::is_standard_layout<CmdReserveSpaceForCommandsInfoNVX>::value, "struct wrapper is not a standard layout!" );
-
   struct CoarseSampleLocationNV
   {
     VULKAN_HPP_CONSTEXPR CoarseSampleLocationNV( uint32_t pixelX_ = {},
@@ -25950,18 +27446,6 @@
       , sample( sample_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR CoarseSampleLocationNV( CoarseSampleLocationNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pixelX( rhs.pixelX )
-      , pixelY( rhs.pixelY )
-      , sample( rhs.sample )
-    {}
-
-    CoarseSampleLocationNV & operator=( CoarseSampleLocationNV const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( CoarseSampleLocationNV ) );
-      return *this;
-    }
-
     CoarseSampleLocationNV( VkCoarseSampleLocationNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -26037,19 +27521,6 @@
       , pSampleLocations( pSampleLocations_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR CoarseSampleOrderCustomNV( CoarseSampleOrderCustomNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : shadingRate( rhs.shadingRate )
-      , sampleCount( rhs.sampleCount )
-      , sampleLocationCount( rhs.sampleLocationCount )
-      , pSampleLocations( rhs.pSampleLocations )
-    {}
-
-    CoarseSampleOrderCustomNV & operator=( CoarseSampleOrderCustomNV const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( CoarseSampleOrderCustomNV ) );
-      return *this;
-    }
-
     CoarseSampleOrderCustomNV( VkCoarseSampleOrderCustomNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -26131,13 +27602,6 @@
       , commandBufferCount( commandBufferCount_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR CommandBufferAllocateInfo( CommandBufferAllocateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , commandPool( rhs.commandPool )
-      , level( rhs.level )
-      , commandBufferCount( rhs.commandBufferCount )
-    {}
-
     CommandBufferAllocateInfo & operator=( CommandBufferAllocateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( CommandBufferAllocateInfo ) - offsetof( CommandBufferAllocateInfo, pNext ) );
@@ -26233,16 +27697,6 @@
       , pipelineStatistics( pipelineStatistics_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR CommandBufferInheritanceInfo( CommandBufferInheritanceInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , renderPass( rhs.renderPass )
-      , subpass( rhs.subpass )
-      , framebuffer( rhs.framebuffer )
-      , occlusionQueryEnable( rhs.occlusionQueryEnable )
-      , queryFlags( rhs.queryFlags )
-      , pipelineStatistics( rhs.pipelineStatistics )
-    {}
-
     CommandBufferInheritanceInfo & operator=( CommandBufferInheritanceInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( CommandBufferInheritanceInfo ) - offsetof( CommandBufferInheritanceInfo, pNext ) );
@@ -26354,12 +27808,6 @@
       , pInheritanceInfo( pInheritanceInfo_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR CommandBufferBeginInfo( CommandBufferBeginInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , pInheritanceInfo( rhs.pInheritanceInfo )
-    {}
-
     CommandBufferBeginInfo & operator=( CommandBufferBeginInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( CommandBufferBeginInfo ) - offsetof( CommandBufferBeginInfo, pNext ) );
@@ -26437,11 +27885,6 @@
       : conditionalRenderingEnable( conditionalRenderingEnable_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR CommandBufferInheritanceConditionalRenderingInfoEXT( CommandBufferInheritanceConditionalRenderingInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , conditionalRenderingEnable( rhs.conditionalRenderingEnable )
-    {}
-
     CommandBufferInheritanceConditionalRenderingInfoEXT & operator=( CommandBufferInheritanceConditionalRenderingInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( CommandBufferInheritanceConditionalRenderingInfoEXT ) - offsetof( CommandBufferInheritanceConditionalRenderingInfoEXT, pNext ) );
@@ -26513,12 +27956,6 @@
       , renderArea( renderArea_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR CommandBufferInheritanceRenderPassTransformInfoQCOM( CommandBufferInheritanceRenderPassTransformInfoQCOM const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , transform( rhs.transform )
-      , renderArea( rhs.renderArea )
-    {}
-
     CommandBufferInheritanceRenderPassTransformInfoQCOM & operator=( CommandBufferInheritanceRenderPassTransformInfoQCOM const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( CommandBufferInheritanceRenderPassTransformInfoQCOM ) - offsetof( CommandBufferInheritanceRenderPassTransformInfoQCOM, pNext ) );
@@ -26598,12 +28035,6 @@
       , queueFamilyIndex( queueFamilyIndex_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR CommandPoolCreateInfo( CommandPoolCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , queueFamilyIndex( rhs.queueFamilyIndex )
-    {}
-
     CommandPoolCreateInfo & operator=( CommandPoolCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( CommandPoolCreateInfo ) - offsetof( CommandPoolCreateInfo, pNext ) );
@@ -26685,18 +28116,6 @@
       , size( size_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SpecializationMapEntry( SpecializationMapEntry const& rhs ) VULKAN_HPP_NOEXCEPT
-      : constantID( rhs.constantID )
-      , offset( rhs.offset )
-      , size( rhs.size )
-    {}
-
-    SpecializationMapEntry & operator=( SpecializationMapEntry const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( SpecializationMapEntry ) );
-      return *this;
-    }
-
     SpecializationMapEntry( VkSpecializationMapEntry const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -26772,19 +28191,6 @@
       , pData( pData_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SpecializationInfo( SpecializationInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : mapEntryCount( rhs.mapEntryCount )
-      , pMapEntries( rhs.pMapEntries )
-      , dataSize( rhs.dataSize )
-      , pData( rhs.pData )
-    {}
-
-    SpecializationInfo & operator=( SpecializationInfo const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( SpecializationInfo ) );
-      return *this;
-    }
-
     SpecializationInfo( VkSpecializationInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -26870,15 +28276,6 @@
       , pSpecializationInfo( pSpecializationInfo_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PipelineShaderStageCreateInfo( PipelineShaderStageCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , stage( rhs.stage )
-      , module( rhs.module )
-      , pName( rhs.pName )
-      , pSpecializationInfo( rhs.pSpecializationInfo )
-    {}
-
     PipelineShaderStageCreateInfo & operator=( PipelineShaderStageCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PipelineShaderStageCreateInfo ) - offsetof( PipelineShaderStageCreateInfo, pNext ) );
@@ -26988,15 +28385,6 @@
       , basePipelineIndex( basePipelineIndex_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ComputePipelineCreateInfo( ComputePipelineCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , stage( rhs.stage )
-      , layout( rhs.layout )
-      , basePipelineHandle( rhs.basePipelineHandle )
-      , basePipelineIndex( rhs.basePipelineIndex )
-    {}
-
     ComputePipelineCreateInfo & operator=( ComputePipelineCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ComputePipelineCreateInfo ) - offsetof( ComputePipelineCreateInfo, pNext ) );
@@ -27102,13 +28490,6 @@
       , flags( flags_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ConditionalRenderingBeginInfoEXT( ConditionalRenderingBeginInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , buffer( rhs.buffer )
-      , offset( rhs.offset )
-      , flags( rhs.flags )
-    {}
-
     ConditionalRenderingBeginInfoEXT & operator=( ConditionalRenderingBeginInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ConditionalRenderingBeginInfoEXT ) - offsetof( ConditionalRenderingBeginInfoEXT, pNext ) );
@@ -27200,19 +28581,6 @@
       , patch( patch_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ConformanceVersion( ConformanceVersion const& rhs ) VULKAN_HPP_NOEXCEPT
-      : major( rhs.major )
-      , minor( rhs.minor )
-      , subminor( rhs.subminor )
-      , patch( rhs.patch )
-    {}
-
-    ConformanceVersion & operator=( ConformanceVersion const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( ConformanceVersion ) );
-      return *this;
-    }
-
     ConformanceVersion( VkConformanceVersion const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -27304,18 +28672,6 @@
       , scope( scope_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR CooperativeMatrixPropertiesNV( CooperativeMatrixPropertiesNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , MSize( rhs.MSize )
-      , NSize( rhs.NSize )
-      , KSize( rhs.KSize )
-      , AType( rhs.AType )
-      , BType( rhs.BType )
-      , CType( rhs.CType )
-      , DType( rhs.DType )
-      , scope( rhs.scope )
-    {}
-
     CooperativeMatrixPropertiesNV & operator=( CooperativeMatrixPropertiesNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( CooperativeMatrixPropertiesNV ) - offsetof( CooperativeMatrixPropertiesNV, pNext ) );
@@ -27435,6 +28791,170 @@
   static_assert( sizeof( CooperativeMatrixPropertiesNV ) == sizeof( VkCooperativeMatrixPropertiesNV ), "struct and wrapper have different size!" );
   static_assert( std::is_standard_layout<CooperativeMatrixPropertiesNV>::value, "struct wrapper is not a standard layout!" );
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct CopyAccelerationStructureInfoKHR
+  {
+    VULKAN_HPP_CONSTEXPR CopyAccelerationStructureInfoKHR( VULKAN_HPP_NAMESPACE::AccelerationStructureKHR src_ = {},
+                                                           VULKAN_HPP_NAMESPACE::AccelerationStructureKHR dst_ = {},
+                                                           VULKAN_HPP_NAMESPACE::CopyAccelerationStructureModeKHR mode_ = VULKAN_HPP_NAMESPACE::CopyAccelerationStructureModeKHR::eClone ) VULKAN_HPP_NOEXCEPT
+      : src( src_ )
+      , dst( dst_ )
+      , mode( mode_ )
+    {}
+
+    CopyAccelerationStructureInfoKHR & operator=( CopyAccelerationStructureInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      memcpy( &pNext, &rhs.pNext, sizeof( CopyAccelerationStructureInfoKHR ) - offsetof( CopyAccelerationStructureInfoKHR, pNext ) );
+      return *this;
+    }
+
+    CopyAccelerationStructureInfoKHR( VkCopyAccelerationStructureInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    CopyAccelerationStructureInfoKHR& operator=( VkCopyAccelerationStructureInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::CopyAccelerationStructureInfoKHR const *>(&rhs);
+      return *this;
+    }
+
+    CopyAccelerationStructureInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pNext = pNext_;
+      return *this;
+    }
+
+    CopyAccelerationStructureInfoKHR & setSrc( VULKAN_HPP_NAMESPACE::AccelerationStructureKHR src_ ) VULKAN_HPP_NOEXCEPT
+    {
+      src = src_;
+      return *this;
+    }
+
+    CopyAccelerationStructureInfoKHR & setDst( VULKAN_HPP_NAMESPACE::AccelerationStructureKHR dst_ ) VULKAN_HPP_NOEXCEPT
+    {
+      dst = dst_;
+      return *this;
+    }
+
+    CopyAccelerationStructureInfoKHR & setMode( VULKAN_HPP_NAMESPACE::CopyAccelerationStructureModeKHR mode_ ) VULKAN_HPP_NOEXCEPT
+    {
+      mode = mode_;
+      return *this;
+    }
+
+    operator VkCopyAccelerationStructureInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkCopyAccelerationStructureInfoKHR*>( this );
+    }
+
+    operator VkCopyAccelerationStructureInfoKHR &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkCopyAccelerationStructureInfoKHR*>( this );
+    }
+
+#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
+    auto operator<=>( CopyAccelerationStructureInfoKHR const& ) const = default;
+#else
+    bool operator==( CopyAccelerationStructureInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ( sType == rhs.sType )
+          && ( pNext == rhs.pNext )
+          && ( src == rhs.src )
+          && ( dst == rhs.dst )
+          && ( mode == rhs.mode );
+    }
+
+    bool operator!=( CopyAccelerationStructureInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return !operator==( rhs );
+    }
+#endif
+
+  public:
+    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eCopyAccelerationStructureInfoKHR;
+    const void* pNext = {};
+    VULKAN_HPP_NAMESPACE::AccelerationStructureKHR src = {};
+    VULKAN_HPP_NAMESPACE::AccelerationStructureKHR dst = {};
+    VULKAN_HPP_NAMESPACE::CopyAccelerationStructureModeKHR mode = VULKAN_HPP_NAMESPACE::CopyAccelerationStructureModeKHR::eClone;
+  };
+  static_assert( sizeof( CopyAccelerationStructureInfoKHR ) == sizeof( VkCopyAccelerationStructureInfoKHR ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<CopyAccelerationStructureInfoKHR>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct CopyAccelerationStructureToMemoryInfoKHR
+  {
+    CopyAccelerationStructureToMemoryInfoKHR( VULKAN_HPP_NAMESPACE::AccelerationStructureKHR src_ = {},
+                                              VULKAN_HPP_NAMESPACE::DeviceOrHostAddressKHR dst_ = {},
+                                              VULKAN_HPP_NAMESPACE::CopyAccelerationStructureModeKHR mode_ = VULKAN_HPP_NAMESPACE::CopyAccelerationStructureModeKHR::eClone ) VULKAN_HPP_NOEXCEPT
+      : src( src_ )
+      , dst( dst_ )
+      , mode( mode_ )
+    {}
+
+    CopyAccelerationStructureToMemoryInfoKHR & operator=( CopyAccelerationStructureToMemoryInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      memcpy( &pNext, &rhs.pNext, sizeof( CopyAccelerationStructureToMemoryInfoKHR ) - offsetof( CopyAccelerationStructureToMemoryInfoKHR, pNext ) );
+      return *this;
+    }
+
+    CopyAccelerationStructureToMemoryInfoKHR( VkCopyAccelerationStructureToMemoryInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    CopyAccelerationStructureToMemoryInfoKHR& operator=( VkCopyAccelerationStructureToMemoryInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::CopyAccelerationStructureToMemoryInfoKHR const *>(&rhs);
+      return *this;
+    }
+
+    CopyAccelerationStructureToMemoryInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pNext = pNext_;
+      return *this;
+    }
+
+    CopyAccelerationStructureToMemoryInfoKHR & setSrc( VULKAN_HPP_NAMESPACE::AccelerationStructureKHR src_ ) VULKAN_HPP_NOEXCEPT
+    {
+      src = src_;
+      return *this;
+    }
+
+    CopyAccelerationStructureToMemoryInfoKHR & setDst( VULKAN_HPP_NAMESPACE::DeviceOrHostAddressKHR dst_ ) VULKAN_HPP_NOEXCEPT
+    {
+      dst = dst_;
+      return *this;
+    }
+
+    CopyAccelerationStructureToMemoryInfoKHR & setMode( VULKAN_HPP_NAMESPACE::CopyAccelerationStructureModeKHR mode_ ) VULKAN_HPP_NOEXCEPT
+    {
+      mode = mode_;
+      return *this;
+    }
+
+    operator VkCopyAccelerationStructureToMemoryInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkCopyAccelerationStructureToMemoryInfoKHR*>( this );
+    }
+
+    operator VkCopyAccelerationStructureToMemoryInfoKHR &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkCopyAccelerationStructureToMemoryInfoKHR*>( this );
+    }
+
+  public:
+    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eCopyAccelerationStructureToMemoryInfoKHR;
+    const void* pNext = {};
+    VULKAN_HPP_NAMESPACE::AccelerationStructureKHR src = {};
+    VULKAN_HPP_NAMESPACE::DeviceOrHostAddressKHR dst = {};
+    VULKAN_HPP_NAMESPACE::CopyAccelerationStructureModeKHR mode = VULKAN_HPP_NAMESPACE::CopyAccelerationStructureModeKHR::eClone;
+  };
+  static_assert( sizeof( CopyAccelerationStructureToMemoryInfoKHR ) == sizeof( VkCopyAccelerationStructureToMemoryInfoKHR ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<CopyAccelerationStructureToMemoryInfoKHR>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
   struct CopyDescriptorSet
   {
     VULKAN_HPP_CONSTEXPR CopyDescriptorSet( VULKAN_HPP_NAMESPACE::DescriptorSet srcSet_ = {},
@@ -27453,17 +28973,6 @@
       , descriptorCount( descriptorCount_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR CopyDescriptorSet( CopyDescriptorSet const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , srcSet( rhs.srcSet )
-      , srcBinding( rhs.srcBinding )
-      , srcArrayElement( rhs.srcArrayElement )
-      , dstSet( rhs.dstSet )
-      , dstBinding( rhs.dstBinding )
-      , dstArrayElement( rhs.dstArrayElement )
-      , descriptorCount( rhs.descriptorCount )
-    {}
-
     CopyDescriptorSet & operator=( CopyDescriptorSet const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( CopyDescriptorSet ) - offsetof( CopyDescriptorSet, pNext ) );
@@ -27575,6 +29084,79 @@
   static_assert( sizeof( CopyDescriptorSet ) == sizeof( VkCopyDescriptorSet ), "struct and wrapper have different size!" );
   static_assert( std::is_standard_layout<CopyDescriptorSet>::value, "struct wrapper is not a standard layout!" );
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct CopyMemoryToAccelerationStructureInfoKHR
+  {
+    CopyMemoryToAccelerationStructureInfoKHR( VULKAN_HPP_NAMESPACE::DeviceOrHostAddressConstKHR src_ = {},
+                                              VULKAN_HPP_NAMESPACE::AccelerationStructureKHR dst_ = {},
+                                              VULKAN_HPP_NAMESPACE::CopyAccelerationStructureModeKHR mode_ = VULKAN_HPP_NAMESPACE::CopyAccelerationStructureModeKHR::eClone ) VULKAN_HPP_NOEXCEPT
+      : src( src_ )
+      , dst( dst_ )
+      , mode( mode_ )
+    {}
+
+    CopyMemoryToAccelerationStructureInfoKHR & operator=( CopyMemoryToAccelerationStructureInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      memcpy( &pNext, &rhs.pNext, sizeof( CopyMemoryToAccelerationStructureInfoKHR ) - offsetof( CopyMemoryToAccelerationStructureInfoKHR, pNext ) );
+      return *this;
+    }
+
+    CopyMemoryToAccelerationStructureInfoKHR( VkCopyMemoryToAccelerationStructureInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    CopyMemoryToAccelerationStructureInfoKHR& operator=( VkCopyMemoryToAccelerationStructureInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::CopyMemoryToAccelerationStructureInfoKHR const *>(&rhs);
+      return *this;
+    }
+
+    CopyMemoryToAccelerationStructureInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pNext = pNext_;
+      return *this;
+    }
+
+    CopyMemoryToAccelerationStructureInfoKHR & setSrc( VULKAN_HPP_NAMESPACE::DeviceOrHostAddressConstKHR src_ ) VULKAN_HPP_NOEXCEPT
+    {
+      src = src_;
+      return *this;
+    }
+
+    CopyMemoryToAccelerationStructureInfoKHR & setDst( VULKAN_HPP_NAMESPACE::AccelerationStructureKHR dst_ ) VULKAN_HPP_NOEXCEPT
+    {
+      dst = dst_;
+      return *this;
+    }
+
+    CopyMemoryToAccelerationStructureInfoKHR & setMode( VULKAN_HPP_NAMESPACE::CopyAccelerationStructureModeKHR mode_ ) VULKAN_HPP_NOEXCEPT
+    {
+      mode = mode_;
+      return *this;
+    }
+
+    operator VkCopyMemoryToAccelerationStructureInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkCopyMemoryToAccelerationStructureInfoKHR*>( this );
+    }
+
+    operator VkCopyMemoryToAccelerationStructureInfoKHR &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkCopyMemoryToAccelerationStructureInfoKHR*>( this );
+    }
+
+  public:
+    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eCopyMemoryToAccelerationStructureInfoKHR;
+    const void* pNext = {};
+    VULKAN_HPP_NAMESPACE::DeviceOrHostAddressConstKHR src = {};
+    VULKAN_HPP_NAMESPACE::AccelerationStructureKHR dst = {};
+    VULKAN_HPP_NAMESPACE::CopyAccelerationStructureModeKHR mode = VULKAN_HPP_NAMESPACE::CopyAccelerationStructureModeKHR::eClone;
+  };
+  static_assert( sizeof( CopyMemoryToAccelerationStructureInfoKHR ) == sizeof( VkCopyMemoryToAccelerationStructureInfoKHR ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<CopyMemoryToAccelerationStructureInfoKHR>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
 #ifdef VK_USE_PLATFORM_WIN32_KHR
   struct D3D12FenceSubmitInfoKHR
   {
@@ -27588,14 +29170,6 @@
       , pSignalSemaphoreValues( pSignalSemaphoreValues_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR D3D12FenceSubmitInfoKHR( D3D12FenceSubmitInfoKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , waitSemaphoreValuesCount( rhs.waitSemaphoreValuesCount )
-      , pWaitSemaphoreValues( rhs.pWaitSemaphoreValues )
-      , signalSemaphoreValuesCount( rhs.signalSemaphoreValuesCount )
-      , pSignalSemaphoreValues( rhs.pSignalSemaphoreValues )
-    {}
-
     D3D12FenceSubmitInfoKHR & operator=( D3D12FenceSubmitInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( D3D12FenceSubmitInfoKHR ) - offsetof( D3D12FenceSubmitInfoKHR, pNext ) );
@@ -27689,18 +29263,8 @@
     VULKAN_HPP_CONSTEXPR_14 DebugMarkerMarkerInfoEXT( const char* pMarkerName_ = {},
                                                       std::array<float,4> const& color_ = {} ) VULKAN_HPP_NOEXCEPT
       : pMarkerName( pMarkerName_ )
-      , color{}
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<float,4>::copy( color, color_ );
-    }
-
-    VULKAN_HPP_CONSTEXPR_14 DebugMarkerMarkerInfoEXT( DebugMarkerMarkerInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , pMarkerName( rhs.pMarkerName )
-      , color{}
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<float,4>::copy( color, rhs.color );
-    }
+      , color( color_ )
+    {}
 
     DebugMarkerMarkerInfoEXT & operator=( DebugMarkerMarkerInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
@@ -27733,7 +29297,7 @@
 
     DebugMarkerMarkerInfoEXT & setColor( std::array<float,4> color_ ) VULKAN_HPP_NOEXCEPT
     {
-      memcpy( color, color_.data(), 4 * sizeof( float ) );
+      color = color_;
       return *this;
     }
 
@@ -27755,7 +29319,7 @@
       return ( sType == rhs.sType )
           && ( pNext == rhs.pNext )
           && ( pMarkerName == rhs.pMarkerName )
-          && ( memcmp( color, rhs.color, 4 * sizeof( float ) ) == 0 );
+          && ( color == rhs.color );
     }
 
     bool operator!=( DebugMarkerMarkerInfoEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
@@ -27768,7 +29332,7 @@
     const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDebugMarkerMarkerInfoEXT;
     const void* pNext = {};
     const char* pMarkerName = {};
-    float color[4] = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<float, 4> color = {};
   };
   static_assert( sizeof( DebugMarkerMarkerInfoEXT ) == sizeof( VkDebugMarkerMarkerInfoEXT ), "struct and wrapper have different size!" );
   static_assert( std::is_standard_layout<DebugMarkerMarkerInfoEXT>::value, "struct wrapper is not a standard layout!" );
@@ -27783,13 +29347,6 @@
       , pObjectName( pObjectName_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DebugMarkerObjectNameInfoEXT( DebugMarkerObjectNameInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , objectType( rhs.objectType )
-      , object( rhs.object )
-      , pObjectName( rhs.pObjectName )
-    {}
-
     DebugMarkerObjectNameInfoEXT & operator=( DebugMarkerObjectNameInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DebugMarkerObjectNameInfoEXT ) - offsetof( DebugMarkerObjectNameInfoEXT, pNext ) );
@@ -27883,15 +29440,6 @@
       , pTag( pTag_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DebugMarkerObjectTagInfoEXT( DebugMarkerObjectTagInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , objectType( rhs.objectType )
-      , object( rhs.object )
-      , tagName( rhs.tagName )
-      , tagSize( rhs.tagSize )
-      , pTag( rhs.pTag )
-    {}
-
     DebugMarkerObjectTagInfoEXT & operator=( DebugMarkerObjectTagInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DebugMarkerObjectTagInfoEXT ) - offsetof( DebugMarkerObjectTagInfoEXT, pNext ) );
@@ -27997,13 +29545,6 @@
       , pUserData( pUserData_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DebugReportCallbackCreateInfoEXT( DebugReportCallbackCreateInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , pfnCallback( rhs.pfnCallback )
-      , pUserData( rhs.pUserData )
-    {}
-
     DebugReportCallbackCreateInfoEXT & operator=( DebugReportCallbackCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DebugReportCallbackCreateInfoEXT ) - offsetof( DebugReportCallbackCreateInfoEXT, pNext ) );
@@ -28088,18 +29629,8 @@
     VULKAN_HPP_CONSTEXPR_14 DebugUtilsLabelEXT( const char* pLabelName_ = {},
                                                 std::array<float,4> const& color_ = {} ) VULKAN_HPP_NOEXCEPT
       : pLabelName( pLabelName_ )
-      , color{}
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<float,4>::copy( color, color_ );
-    }
-
-    VULKAN_HPP_CONSTEXPR_14 DebugUtilsLabelEXT( DebugUtilsLabelEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , pLabelName( rhs.pLabelName )
-      , color{}
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<float,4>::copy( color, rhs.color );
-    }
+      , color( color_ )
+    {}
 
     DebugUtilsLabelEXT & operator=( DebugUtilsLabelEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
@@ -28132,7 +29663,7 @@
 
     DebugUtilsLabelEXT & setColor( std::array<float,4> color_ ) VULKAN_HPP_NOEXCEPT
     {
-      memcpy( color, color_.data(), 4 * sizeof( float ) );
+      color = color_;
       return *this;
     }
 
@@ -28154,7 +29685,7 @@
       return ( sType == rhs.sType )
           && ( pNext == rhs.pNext )
           && ( pLabelName == rhs.pLabelName )
-          && ( memcmp( color, rhs.color, 4 * sizeof( float ) ) == 0 );
+          && ( color == rhs.color );
     }
 
     bool operator!=( DebugUtilsLabelEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
@@ -28167,7 +29698,7 @@
     const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDebugUtilsLabelEXT;
     const void* pNext = {};
     const char* pLabelName = {};
-    float color[4] = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<float, 4> color = {};
   };
   static_assert( sizeof( DebugUtilsLabelEXT ) == sizeof( VkDebugUtilsLabelEXT ), "struct and wrapper have different size!" );
   static_assert( std::is_standard_layout<DebugUtilsLabelEXT>::value, "struct wrapper is not a standard layout!" );
@@ -28182,13 +29713,6 @@
       , pObjectName( pObjectName_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DebugUtilsObjectNameInfoEXT( DebugUtilsObjectNameInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , objectType( rhs.objectType )
-      , objectHandle( rhs.objectHandle )
-      , pObjectName( rhs.pObjectName )
-    {}
-
     DebugUtilsObjectNameInfoEXT & operator=( DebugUtilsObjectNameInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DebugUtilsObjectNameInfoEXT ) - offsetof( DebugUtilsObjectNameInfoEXT, pNext ) );
@@ -28292,20 +29816,6 @@
       , pObjects( pObjects_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR_14 DebugUtilsMessengerCallbackDataEXT( DebugUtilsMessengerCallbackDataEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , pMessageIdName( rhs.pMessageIdName )
-      , messageIdNumber( rhs.messageIdNumber )
-      , pMessage( rhs.pMessage )
-      , queueLabelCount( rhs.queueLabelCount )
-      , pQueueLabels( rhs.pQueueLabels )
-      , cmdBufLabelCount( rhs.cmdBufLabelCount )
-      , pCmdBufLabels( rhs.pCmdBufLabels )
-      , objectCount( rhs.objectCount )
-      , pObjects( rhs.pObjects )
-    {}
-
     DebugUtilsMessengerCallbackDataEXT & operator=( DebugUtilsMessengerCallbackDataEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DebugUtilsMessengerCallbackDataEXT ) - offsetof( DebugUtilsMessengerCallbackDataEXT, pNext ) );
@@ -28455,15 +29965,6 @@
       , pUserData( pUserData_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DebugUtilsMessengerCreateInfoEXT( DebugUtilsMessengerCreateInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , messageSeverity( rhs.messageSeverity )
-      , messageType( rhs.messageType )
-      , pfnUserCallback( rhs.pfnUserCallback )
-      , pUserData( rhs.pUserData )
-    {}
-
     DebugUtilsMessengerCreateInfoEXT & operator=( DebugUtilsMessengerCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DebugUtilsMessengerCreateInfoEXT ) - offsetof( DebugUtilsMessengerCreateInfoEXT, pNext ) );
@@ -28573,15 +30074,6 @@
       , pTag( pTag_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DebugUtilsObjectTagInfoEXT( DebugUtilsObjectTagInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , objectType( rhs.objectType )
-      , objectHandle( rhs.objectHandle )
-      , tagName( rhs.tagName )
-      , tagSize( rhs.tagSize )
-      , pTag( rhs.pTag )
-    {}
-
     DebugUtilsObjectTagInfoEXT & operator=( DebugUtilsObjectTagInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DebugUtilsObjectTagInfoEXT ) - offsetof( DebugUtilsObjectTagInfoEXT, pNext ) );
@@ -28683,11 +30175,6 @@
       : dedicatedAllocation( dedicatedAllocation_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DedicatedAllocationBufferCreateInfoNV( DedicatedAllocationBufferCreateInfoNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , dedicatedAllocation( rhs.dedicatedAllocation )
-    {}
-
     DedicatedAllocationBufferCreateInfoNV & operator=( DedicatedAllocationBufferCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DedicatedAllocationBufferCreateInfoNV ) - offsetof( DedicatedAllocationBufferCreateInfoNV, pNext ) );
@@ -28757,11 +30244,6 @@
       : dedicatedAllocation( dedicatedAllocation_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DedicatedAllocationImageCreateInfoNV( DedicatedAllocationImageCreateInfoNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , dedicatedAllocation( rhs.dedicatedAllocation )
-    {}
-
     DedicatedAllocationImageCreateInfoNV & operator=( DedicatedAllocationImageCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DedicatedAllocationImageCreateInfoNV ) - offsetof( DedicatedAllocationImageCreateInfoNV, pNext ) );
@@ -28833,12 +30315,6 @@
       , buffer( buffer_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DedicatedAllocationMemoryAllocateInfoNV( DedicatedAllocationMemoryAllocateInfoNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , image( rhs.image )
-      , buffer( rhs.buffer )
-    {}
-
     DedicatedAllocationMemoryAllocateInfoNV & operator=( DedicatedAllocationMemoryAllocateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DedicatedAllocationMemoryAllocateInfoNV ) - offsetof( DedicatedAllocationMemoryAllocateInfoNV, pNext ) );
@@ -28910,6 +30386,77 @@
   static_assert( sizeof( DedicatedAllocationMemoryAllocateInfoNV ) == sizeof( VkDedicatedAllocationMemoryAllocateInfoNV ), "struct and wrapper have different size!" );
   static_assert( std::is_standard_layout<DedicatedAllocationMemoryAllocateInfoNV>::value, "struct wrapper is not a standard layout!" );
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct DeferredOperationInfoKHR
+  {
+    VULKAN_HPP_CONSTEXPR DeferredOperationInfoKHR( VULKAN_HPP_NAMESPACE::DeferredOperationKHR operationHandle_ = {} ) VULKAN_HPP_NOEXCEPT
+      : operationHandle( operationHandle_ )
+    {}
+
+    DeferredOperationInfoKHR & operator=( DeferredOperationInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      memcpy( &pNext, &rhs.pNext, sizeof( DeferredOperationInfoKHR ) - offsetof( DeferredOperationInfoKHR, pNext ) );
+      return *this;
+    }
+
+    DeferredOperationInfoKHR( VkDeferredOperationInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    DeferredOperationInfoKHR& operator=( VkDeferredOperationInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DeferredOperationInfoKHR const *>(&rhs);
+      return *this;
+    }
+
+    DeferredOperationInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pNext = pNext_;
+      return *this;
+    }
+
+    DeferredOperationInfoKHR & setOperationHandle( VULKAN_HPP_NAMESPACE::DeferredOperationKHR operationHandle_ ) VULKAN_HPP_NOEXCEPT
+    {
+      operationHandle = operationHandle_;
+      return *this;
+    }
+
+    operator VkDeferredOperationInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkDeferredOperationInfoKHR*>( this );
+    }
+
+    operator VkDeferredOperationInfoKHR &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkDeferredOperationInfoKHR*>( this );
+    }
+
+#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
+    auto operator<=>( DeferredOperationInfoKHR const& ) const = default;
+#else
+    bool operator==( DeferredOperationInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ( sType == rhs.sType )
+          && ( pNext == rhs.pNext )
+          && ( operationHandle == rhs.operationHandle );
+    }
+
+    bool operator!=( DeferredOperationInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return !operator==( rhs );
+    }
+#endif
+
+  public:
+    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDeferredOperationInfoKHR;
+    const void* pNext = {};
+    VULKAN_HPP_NAMESPACE::DeferredOperationKHR operationHandle = {};
+  };
+  static_assert( sizeof( DeferredOperationInfoKHR ) == sizeof( VkDeferredOperationInfoKHR ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<DeferredOperationInfoKHR>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
   struct DescriptorBufferInfo
   {
     VULKAN_HPP_CONSTEXPR DescriptorBufferInfo( VULKAN_HPP_NAMESPACE::Buffer buffer_ = {},
@@ -28920,18 +30467,6 @@
       , range( range_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DescriptorBufferInfo( DescriptorBufferInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : buffer( rhs.buffer )
-      , offset( rhs.offset )
-      , range( rhs.range )
-    {}
-
-    DescriptorBufferInfo & operator=( DescriptorBufferInfo const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( DescriptorBufferInfo ) );
-      return *this;
-    }
-
     DescriptorBufferInfo( VkDescriptorBufferInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -29005,18 +30540,6 @@
       , imageLayout( imageLayout_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DescriptorImageInfo( DescriptorImageInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : sampler( rhs.sampler )
-      , imageView( rhs.imageView )
-      , imageLayout( rhs.imageLayout )
-    {}
-
-    DescriptorImageInfo & operator=( DescriptorImageInfo const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( DescriptorImageInfo ) );
-      return *this;
-    }
-
     DescriptorImageInfo( VkDescriptorImageInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -29088,17 +30611,6 @@
       , descriptorCount( descriptorCount_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DescriptorPoolSize( DescriptorPoolSize const& rhs ) VULKAN_HPP_NOEXCEPT
-      : type( rhs.type )
-      , descriptorCount( rhs.descriptorCount )
-    {}
-
-    DescriptorPoolSize & operator=( DescriptorPoolSize const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( DescriptorPoolSize ) );
-      return *this;
-    }
-
     DescriptorPoolSize( VkDescriptorPoolSize const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -29166,14 +30678,6 @@
       , pPoolSizes( pPoolSizes_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DescriptorPoolCreateInfo( DescriptorPoolCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , maxSets( rhs.maxSets )
-      , poolSizeCount( rhs.poolSizeCount )
-      , pPoolSizes( rhs.pPoolSizes )
-    {}
-
     DescriptorPoolCreateInfo & operator=( DescriptorPoolCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DescriptorPoolCreateInfo ) - offsetof( DescriptorPoolCreateInfo, pNext ) );
@@ -29267,11 +30771,6 @@
       : maxInlineUniformBlockBindings( maxInlineUniformBlockBindings_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DescriptorPoolInlineUniformBlockCreateInfoEXT( DescriptorPoolInlineUniformBlockCreateInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , maxInlineUniformBlockBindings( rhs.maxInlineUniformBlockBindings )
-    {}
-
     DescriptorPoolInlineUniformBlockCreateInfoEXT & operator=( DescriptorPoolInlineUniformBlockCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DescriptorPoolInlineUniformBlockCreateInfoEXT ) - offsetof( DescriptorPoolInlineUniformBlockCreateInfoEXT, pNext ) );
@@ -29345,13 +30844,6 @@
       , pSetLayouts( pSetLayouts_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DescriptorSetAllocateInfo( DescriptorSetAllocateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , descriptorPool( rhs.descriptorPool )
-      , descriptorSetCount( rhs.descriptorSetCount )
-      , pSetLayouts( rhs.pSetLayouts )
-    {}
-
     DescriptorSetAllocateInfo & operator=( DescriptorSetAllocateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DescriptorSetAllocateInfo ) - offsetof( DescriptorSetAllocateInfo, pNext ) );
@@ -29445,20 +30937,6 @@
       , pImmutableSamplers( pImmutableSamplers_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DescriptorSetLayoutBinding( DescriptorSetLayoutBinding const& rhs ) VULKAN_HPP_NOEXCEPT
-      : binding( rhs.binding )
-      , descriptorType( rhs.descriptorType )
-      , descriptorCount( rhs.descriptorCount )
-      , stageFlags( rhs.stageFlags )
-      , pImmutableSamplers( rhs.pImmutableSamplers )
-    {}
-
-    DescriptorSetLayoutBinding & operator=( DescriptorSetLayoutBinding const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( DescriptorSetLayoutBinding ) );
-      return *this;
-    }
-
     DescriptorSetLayoutBinding( VkDescriptorSetLayoutBinding const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -29546,12 +31024,6 @@
       , pBindingFlags( pBindingFlags_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DescriptorSetLayoutBindingFlagsCreateInfo( DescriptorSetLayoutBindingFlagsCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , bindingCount( rhs.bindingCount )
-      , pBindingFlags( rhs.pBindingFlags )
-    {}
-
     DescriptorSetLayoutBindingFlagsCreateInfo & operator=( DescriptorSetLayoutBindingFlagsCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DescriptorSetLayoutBindingFlagsCreateInfo ) - offsetof( DescriptorSetLayoutBindingFlagsCreateInfo, pNext ) );
@@ -29633,13 +31105,6 @@
       , pBindings( pBindings_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DescriptorSetLayoutCreateInfo( DescriptorSetLayoutCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , bindingCount( rhs.bindingCount )
-      , pBindings( rhs.pBindings )
-    {}
-
     DescriptorSetLayoutCreateInfo & operator=( DescriptorSetLayoutCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DescriptorSetLayoutCreateInfo ) - offsetof( DescriptorSetLayoutCreateInfo, pNext ) );
@@ -29725,11 +31190,6 @@
       : supported( supported_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DescriptorSetLayoutSupport( DescriptorSetLayoutSupport const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , supported( rhs.supported )
-    {}
-
     DescriptorSetLayoutSupport & operator=( DescriptorSetLayoutSupport const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DescriptorSetLayoutSupport ) - offsetof( DescriptorSetLayoutSupport, pNext ) );
@@ -29789,12 +31249,6 @@
       , pDescriptorCounts( pDescriptorCounts_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DescriptorSetVariableDescriptorCountAllocateInfo( DescriptorSetVariableDescriptorCountAllocateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , descriptorSetCount( rhs.descriptorSetCount )
-      , pDescriptorCounts( rhs.pDescriptorCounts )
-    {}
-
     DescriptorSetVariableDescriptorCountAllocateInfo & operator=( DescriptorSetVariableDescriptorCountAllocateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DescriptorSetVariableDescriptorCountAllocateInfo ) - offsetof( DescriptorSetVariableDescriptorCountAllocateInfo, pNext ) );
@@ -29872,11 +31326,6 @@
       : maxVariableDescriptorCount( maxVariableDescriptorCount_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DescriptorSetVariableDescriptorCountLayoutSupport( DescriptorSetVariableDescriptorCountLayoutSupport const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , maxVariableDescriptorCount( rhs.maxVariableDescriptorCount )
-    {}
-
     DescriptorSetVariableDescriptorCountLayoutSupport & operator=( DescriptorSetVariableDescriptorCountLayoutSupport const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DescriptorSetVariableDescriptorCountLayoutSupport ) - offsetof( DescriptorSetVariableDescriptorCountLayoutSupport, pNext ) );
@@ -29944,21 +31393,6 @@
       , stride( stride_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DescriptorUpdateTemplateEntry( DescriptorUpdateTemplateEntry const& rhs ) VULKAN_HPP_NOEXCEPT
-      : dstBinding( rhs.dstBinding )
-      , dstArrayElement( rhs.dstArrayElement )
-      , descriptorCount( rhs.descriptorCount )
-      , descriptorType( rhs.descriptorType )
-      , offset( rhs.offset )
-      , stride( rhs.stride )
-    {}
-
-    DescriptorUpdateTemplateEntry & operator=( DescriptorUpdateTemplateEntry const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( DescriptorUpdateTemplateEntry ) );
-      return *this;
-    }
-
     DescriptorUpdateTemplateEntry( VkDescriptorUpdateTemplateEntry const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -30066,18 +31500,6 @@
       , set( set_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DescriptorUpdateTemplateCreateInfo( DescriptorUpdateTemplateCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , descriptorUpdateEntryCount( rhs.descriptorUpdateEntryCount )
-      , pDescriptorUpdateEntries( rhs.pDescriptorUpdateEntries )
-      , templateType( rhs.templateType )
-      , descriptorSetLayout( rhs.descriptorSetLayout )
-      , pipelineBindPoint( rhs.pipelineBindPoint )
-      , pipelineLayout( rhs.pipelineLayout )
-      , set( rhs.set )
-    {}
-
     DescriptorUpdateTemplateCreateInfo & operator=( DescriptorUpdateTemplateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DescriptorUpdateTemplateCreateInfo ) - offsetof( DescriptorUpdateTemplateCreateInfo, pNext ) );
@@ -30209,14 +31631,6 @@
       , pQueuePriorities( pQueuePriorities_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DeviceQueueCreateInfo( DeviceQueueCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , queueFamilyIndex( rhs.queueFamilyIndex )
-      , queueCount( rhs.queueCount )
-      , pQueuePriorities( rhs.pQueuePriorities )
-    {}
-
     DeviceQueueCreateInfo & operator=( DeviceQueueCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DeviceQueueCreateInfo ) - offsetof( DeviceQueueCreateInfo, pNext ) );
@@ -30418,70 +31832,6 @@
       , inheritedQueries( inheritedQueries_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceFeatures( PhysicalDeviceFeatures const& rhs ) VULKAN_HPP_NOEXCEPT
-      : robustBufferAccess( rhs.robustBufferAccess )
-      , fullDrawIndexUint32( rhs.fullDrawIndexUint32 )
-      , imageCubeArray( rhs.imageCubeArray )
-      , independentBlend( rhs.independentBlend )
-      , geometryShader( rhs.geometryShader )
-      , tessellationShader( rhs.tessellationShader )
-      , sampleRateShading( rhs.sampleRateShading )
-      , dualSrcBlend( rhs.dualSrcBlend )
-      , logicOp( rhs.logicOp )
-      , multiDrawIndirect( rhs.multiDrawIndirect )
-      , drawIndirectFirstInstance( rhs.drawIndirectFirstInstance )
-      , depthClamp( rhs.depthClamp )
-      , depthBiasClamp( rhs.depthBiasClamp )
-      , fillModeNonSolid( rhs.fillModeNonSolid )
-      , depthBounds( rhs.depthBounds )
-      , wideLines( rhs.wideLines )
-      , largePoints( rhs.largePoints )
-      , alphaToOne( rhs.alphaToOne )
-      , multiViewport( rhs.multiViewport )
-      , samplerAnisotropy( rhs.samplerAnisotropy )
-      , textureCompressionETC2( rhs.textureCompressionETC2 )
-      , textureCompressionASTC_LDR( rhs.textureCompressionASTC_LDR )
-      , textureCompressionBC( rhs.textureCompressionBC )
-      , occlusionQueryPrecise( rhs.occlusionQueryPrecise )
-      , pipelineStatisticsQuery( rhs.pipelineStatisticsQuery )
-      , vertexPipelineStoresAndAtomics( rhs.vertexPipelineStoresAndAtomics )
-      , fragmentStoresAndAtomics( rhs.fragmentStoresAndAtomics )
-      , shaderTessellationAndGeometryPointSize( rhs.shaderTessellationAndGeometryPointSize )
-      , shaderImageGatherExtended( rhs.shaderImageGatherExtended )
-      , shaderStorageImageExtendedFormats( rhs.shaderStorageImageExtendedFormats )
-      , shaderStorageImageMultisample( rhs.shaderStorageImageMultisample )
-      , shaderStorageImageReadWithoutFormat( rhs.shaderStorageImageReadWithoutFormat )
-      , shaderStorageImageWriteWithoutFormat( rhs.shaderStorageImageWriteWithoutFormat )
-      , shaderUniformBufferArrayDynamicIndexing( rhs.shaderUniformBufferArrayDynamicIndexing )
-      , shaderSampledImageArrayDynamicIndexing( rhs.shaderSampledImageArrayDynamicIndexing )
-      , shaderStorageBufferArrayDynamicIndexing( rhs.shaderStorageBufferArrayDynamicIndexing )
-      , shaderStorageImageArrayDynamicIndexing( rhs.shaderStorageImageArrayDynamicIndexing )
-      , shaderClipDistance( rhs.shaderClipDistance )
-      , shaderCullDistance( rhs.shaderCullDistance )
-      , shaderFloat64( rhs.shaderFloat64 )
-      , shaderInt64( rhs.shaderInt64 )
-      , shaderInt16( rhs.shaderInt16 )
-      , shaderResourceResidency( rhs.shaderResourceResidency )
-      , shaderResourceMinLod( rhs.shaderResourceMinLod )
-      , sparseBinding( rhs.sparseBinding )
-      , sparseResidencyBuffer( rhs.sparseResidencyBuffer )
-      , sparseResidencyImage2D( rhs.sparseResidencyImage2D )
-      , sparseResidencyImage3D( rhs.sparseResidencyImage3D )
-      , sparseResidency2Samples( rhs.sparseResidency2Samples )
-      , sparseResidency4Samples( rhs.sparseResidency4Samples )
-      , sparseResidency8Samples( rhs.sparseResidency8Samples )
-      , sparseResidency16Samples( rhs.sparseResidency16Samples )
-      , sparseResidencyAliased( rhs.sparseResidencyAliased )
-      , variableMultisampleRate( rhs.variableMultisampleRate )
-      , inheritedQueries( rhs.inheritedQueries )
-    {}
-
-    PhysicalDeviceFeatures & operator=( PhysicalDeviceFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( PhysicalDeviceFeatures ) );
-      return *this;
-    }
-
     PhysicalDeviceFeatures( VkPhysicalDeviceFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -30981,18 +32331,6 @@
       , pEnabledFeatures( pEnabledFeatures_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DeviceCreateInfo( DeviceCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , queueCreateInfoCount( rhs.queueCreateInfoCount )
-      , pQueueCreateInfos( rhs.pQueueCreateInfos )
-      , enabledLayerCount( rhs.enabledLayerCount )
-      , ppEnabledLayerNames( rhs.ppEnabledLayerNames )
-      , enabledExtensionCount( rhs.enabledExtensionCount )
-      , ppEnabledExtensionNames( rhs.ppEnabledExtensionNames )
-      , pEnabledFeatures( rhs.pEnabledFeatures )
-    {}
-
     DeviceCreateInfo & operator=( DeviceCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DeviceCreateInfo ) - offsetof( DeviceCreateInfo, pNext ) );
@@ -31112,17 +32450,81 @@
   static_assert( sizeof( DeviceCreateInfo ) == sizeof( VkDeviceCreateInfo ), "struct and wrapper have different size!" );
   static_assert( std::is_standard_layout<DeviceCreateInfo>::value, "struct wrapper is not a standard layout!" );
 
+  struct DeviceDiagnosticsConfigCreateInfoNV
+  {
+    VULKAN_HPP_CONSTEXPR DeviceDiagnosticsConfigCreateInfoNV( VULKAN_HPP_NAMESPACE::DeviceDiagnosticsConfigFlagsNV flags_ = {} ) VULKAN_HPP_NOEXCEPT
+      : flags( flags_ )
+    {}
+
+    DeviceDiagnosticsConfigCreateInfoNV & operator=( DeviceDiagnosticsConfigCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      memcpy( &pNext, &rhs.pNext, sizeof( DeviceDiagnosticsConfigCreateInfoNV ) - offsetof( DeviceDiagnosticsConfigCreateInfoNV, pNext ) );
+      return *this;
+    }
+
+    DeviceDiagnosticsConfigCreateInfoNV( VkDeviceDiagnosticsConfigCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    DeviceDiagnosticsConfigCreateInfoNV& operator=( VkDeviceDiagnosticsConfigCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DeviceDiagnosticsConfigCreateInfoNV const *>(&rhs);
+      return *this;
+    }
+
+    DeviceDiagnosticsConfigCreateInfoNV & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pNext = pNext_;
+      return *this;
+    }
+
+    DeviceDiagnosticsConfigCreateInfoNV & setFlags( VULKAN_HPP_NAMESPACE::DeviceDiagnosticsConfigFlagsNV flags_ ) VULKAN_HPP_NOEXCEPT
+    {
+      flags = flags_;
+      return *this;
+    }
+
+    operator VkDeviceDiagnosticsConfigCreateInfoNV const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkDeviceDiagnosticsConfigCreateInfoNV*>( this );
+    }
+
+    operator VkDeviceDiagnosticsConfigCreateInfoNV &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkDeviceDiagnosticsConfigCreateInfoNV*>( this );
+    }
+
+#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
+    auto operator<=>( DeviceDiagnosticsConfigCreateInfoNV const& ) const = default;
+#else
+    bool operator==( DeviceDiagnosticsConfigCreateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ( sType == rhs.sType )
+          && ( pNext == rhs.pNext )
+          && ( flags == rhs.flags );
+    }
+
+    bool operator!=( DeviceDiagnosticsConfigCreateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return !operator==( rhs );
+    }
+#endif
+
+  public:
+    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDeviceDiagnosticsConfigCreateInfoNV;
+    const void* pNext = {};
+    VULKAN_HPP_NAMESPACE::DeviceDiagnosticsConfigFlagsNV flags = {};
+  };
+  static_assert( sizeof( DeviceDiagnosticsConfigCreateInfoNV ) == sizeof( VkDeviceDiagnosticsConfigCreateInfoNV ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<DeviceDiagnosticsConfigCreateInfoNV>::value, "struct wrapper is not a standard layout!" );
+
   struct DeviceEventInfoEXT
   {
     VULKAN_HPP_CONSTEXPR DeviceEventInfoEXT( VULKAN_HPP_NAMESPACE::DeviceEventTypeEXT deviceEvent_ = VULKAN_HPP_NAMESPACE::DeviceEventTypeEXT::eDisplayHotplug ) VULKAN_HPP_NOEXCEPT
       : deviceEvent( deviceEvent_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DeviceEventInfoEXT( DeviceEventInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , deviceEvent( rhs.deviceEvent )
-    {}
-
     DeviceEventInfoEXT & operator=( DeviceEventInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DeviceEventInfoEXT ) - offsetof( DeviceEventInfoEXT, pNext ) );
@@ -31186,198 +32588,6 @@
   static_assert( sizeof( DeviceEventInfoEXT ) == sizeof( VkDeviceEventInfoEXT ), "struct and wrapper have different size!" );
   static_assert( std::is_standard_layout<DeviceEventInfoEXT>::value, "struct wrapper is not a standard layout!" );
 
-  struct DeviceGeneratedCommandsFeaturesNVX
-  {
-    VULKAN_HPP_CONSTEXPR DeviceGeneratedCommandsFeaturesNVX( VULKAN_HPP_NAMESPACE::Bool32 computeBindingPointSupport_ = {} ) VULKAN_HPP_NOEXCEPT
-      : computeBindingPointSupport( computeBindingPointSupport_ )
-    {}
-
-    VULKAN_HPP_CONSTEXPR DeviceGeneratedCommandsFeaturesNVX( DeviceGeneratedCommandsFeaturesNVX const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , computeBindingPointSupport( rhs.computeBindingPointSupport )
-    {}
-
-    DeviceGeneratedCommandsFeaturesNVX & operator=( DeviceGeneratedCommandsFeaturesNVX const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( &pNext, &rhs.pNext, sizeof( DeviceGeneratedCommandsFeaturesNVX ) - offsetof( DeviceGeneratedCommandsFeaturesNVX, pNext ) );
-      return *this;
-    }
-
-    DeviceGeneratedCommandsFeaturesNVX( VkDeviceGeneratedCommandsFeaturesNVX const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      *this = rhs;
-    }
-
-    DeviceGeneratedCommandsFeaturesNVX& operator=( VkDeviceGeneratedCommandsFeaturesNVX const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DeviceGeneratedCommandsFeaturesNVX const *>(&rhs);
-      return *this;
-    }
-
-    DeviceGeneratedCommandsFeaturesNVX & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
-    {
-      pNext = pNext_;
-      return *this;
-    }
-
-    DeviceGeneratedCommandsFeaturesNVX & setComputeBindingPointSupport( VULKAN_HPP_NAMESPACE::Bool32 computeBindingPointSupport_ ) VULKAN_HPP_NOEXCEPT
-    {
-      computeBindingPointSupport = computeBindingPointSupport_;
-      return *this;
-    }
-
-    operator VkDeviceGeneratedCommandsFeaturesNVX const&() const VULKAN_HPP_NOEXCEPT
-    {
-      return *reinterpret_cast<const VkDeviceGeneratedCommandsFeaturesNVX*>( this );
-    }
-
-    operator VkDeviceGeneratedCommandsFeaturesNVX &() VULKAN_HPP_NOEXCEPT
-    {
-      return *reinterpret_cast<VkDeviceGeneratedCommandsFeaturesNVX*>( this );
-    }
-
-#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
-    auto operator<=>( DeviceGeneratedCommandsFeaturesNVX const& ) const = default;
-#else
-    bool operator==( DeviceGeneratedCommandsFeaturesNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
-    {
-      return ( sType == rhs.sType )
-          && ( pNext == rhs.pNext )
-          && ( computeBindingPointSupport == rhs.computeBindingPointSupport );
-    }
-
-    bool operator!=( DeviceGeneratedCommandsFeaturesNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
-    {
-      return !operator==( rhs );
-    }
-#endif
-
-  public:
-    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDeviceGeneratedCommandsFeaturesNVX;
-    const void* pNext = {};
-    VULKAN_HPP_NAMESPACE::Bool32 computeBindingPointSupport = {};
-  };
-  static_assert( sizeof( DeviceGeneratedCommandsFeaturesNVX ) == sizeof( VkDeviceGeneratedCommandsFeaturesNVX ), "struct and wrapper have different size!" );
-  static_assert( std::is_standard_layout<DeviceGeneratedCommandsFeaturesNVX>::value, "struct wrapper is not a standard layout!" );
-
-  struct DeviceGeneratedCommandsLimitsNVX
-  {
-    VULKAN_HPP_CONSTEXPR DeviceGeneratedCommandsLimitsNVX( uint32_t maxIndirectCommandsLayoutTokenCount_ = {},
-                                                           uint32_t maxObjectEntryCounts_ = {},
-                                                           uint32_t minSequenceCountBufferOffsetAlignment_ = {},
-                                                           uint32_t minSequenceIndexBufferOffsetAlignment_ = {},
-                                                           uint32_t minCommandsTokenBufferOffsetAlignment_ = {} ) VULKAN_HPP_NOEXCEPT
-      : maxIndirectCommandsLayoutTokenCount( maxIndirectCommandsLayoutTokenCount_ )
-      , maxObjectEntryCounts( maxObjectEntryCounts_ )
-      , minSequenceCountBufferOffsetAlignment( minSequenceCountBufferOffsetAlignment_ )
-      , minSequenceIndexBufferOffsetAlignment( minSequenceIndexBufferOffsetAlignment_ )
-      , minCommandsTokenBufferOffsetAlignment( minCommandsTokenBufferOffsetAlignment_ )
-    {}
-
-    VULKAN_HPP_CONSTEXPR DeviceGeneratedCommandsLimitsNVX( DeviceGeneratedCommandsLimitsNVX const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , maxIndirectCommandsLayoutTokenCount( rhs.maxIndirectCommandsLayoutTokenCount )
-      , maxObjectEntryCounts( rhs.maxObjectEntryCounts )
-      , minSequenceCountBufferOffsetAlignment( rhs.minSequenceCountBufferOffsetAlignment )
-      , minSequenceIndexBufferOffsetAlignment( rhs.minSequenceIndexBufferOffsetAlignment )
-      , minCommandsTokenBufferOffsetAlignment( rhs.minCommandsTokenBufferOffsetAlignment )
-    {}
-
-    DeviceGeneratedCommandsLimitsNVX & operator=( DeviceGeneratedCommandsLimitsNVX const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( &pNext, &rhs.pNext, sizeof( DeviceGeneratedCommandsLimitsNVX ) - offsetof( DeviceGeneratedCommandsLimitsNVX, pNext ) );
-      return *this;
-    }
-
-    DeviceGeneratedCommandsLimitsNVX( VkDeviceGeneratedCommandsLimitsNVX const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      *this = rhs;
-    }
-
-    DeviceGeneratedCommandsLimitsNVX& operator=( VkDeviceGeneratedCommandsLimitsNVX const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::DeviceGeneratedCommandsLimitsNVX const *>(&rhs);
-      return *this;
-    }
-
-    DeviceGeneratedCommandsLimitsNVX & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
-    {
-      pNext = pNext_;
-      return *this;
-    }
-
-    DeviceGeneratedCommandsLimitsNVX & setMaxIndirectCommandsLayoutTokenCount( uint32_t maxIndirectCommandsLayoutTokenCount_ ) VULKAN_HPP_NOEXCEPT
-    {
-      maxIndirectCommandsLayoutTokenCount = maxIndirectCommandsLayoutTokenCount_;
-      return *this;
-    }
-
-    DeviceGeneratedCommandsLimitsNVX & setMaxObjectEntryCounts( uint32_t maxObjectEntryCounts_ ) VULKAN_HPP_NOEXCEPT
-    {
-      maxObjectEntryCounts = maxObjectEntryCounts_;
-      return *this;
-    }
-
-    DeviceGeneratedCommandsLimitsNVX & setMinSequenceCountBufferOffsetAlignment( uint32_t minSequenceCountBufferOffsetAlignment_ ) VULKAN_HPP_NOEXCEPT
-    {
-      minSequenceCountBufferOffsetAlignment = minSequenceCountBufferOffsetAlignment_;
-      return *this;
-    }
-
-    DeviceGeneratedCommandsLimitsNVX & setMinSequenceIndexBufferOffsetAlignment( uint32_t minSequenceIndexBufferOffsetAlignment_ ) VULKAN_HPP_NOEXCEPT
-    {
-      minSequenceIndexBufferOffsetAlignment = minSequenceIndexBufferOffsetAlignment_;
-      return *this;
-    }
-
-    DeviceGeneratedCommandsLimitsNVX & setMinCommandsTokenBufferOffsetAlignment( uint32_t minCommandsTokenBufferOffsetAlignment_ ) VULKAN_HPP_NOEXCEPT
-    {
-      minCommandsTokenBufferOffsetAlignment = minCommandsTokenBufferOffsetAlignment_;
-      return *this;
-    }
-
-    operator VkDeviceGeneratedCommandsLimitsNVX const&() const VULKAN_HPP_NOEXCEPT
-    {
-      return *reinterpret_cast<const VkDeviceGeneratedCommandsLimitsNVX*>( this );
-    }
-
-    operator VkDeviceGeneratedCommandsLimitsNVX &() VULKAN_HPP_NOEXCEPT
-    {
-      return *reinterpret_cast<VkDeviceGeneratedCommandsLimitsNVX*>( this );
-    }
-
-#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
-    auto operator<=>( DeviceGeneratedCommandsLimitsNVX const& ) const = default;
-#else
-    bool operator==( DeviceGeneratedCommandsLimitsNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
-    {
-      return ( sType == rhs.sType )
-          && ( pNext == rhs.pNext )
-          && ( maxIndirectCommandsLayoutTokenCount == rhs.maxIndirectCommandsLayoutTokenCount )
-          && ( maxObjectEntryCounts == rhs.maxObjectEntryCounts )
-          && ( minSequenceCountBufferOffsetAlignment == rhs.minSequenceCountBufferOffsetAlignment )
-          && ( minSequenceIndexBufferOffsetAlignment == rhs.minSequenceIndexBufferOffsetAlignment )
-          && ( minCommandsTokenBufferOffsetAlignment == rhs.minCommandsTokenBufferOffsetAlignment );
-    }
-
-    bool operator!=( DeviceGeneratedCommandsLimitsNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
-    {
-      return !operator==( rhs );
-    }
-#endif
-
-  public:
-    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDeviceGeneratedCommandsLimitsNVX;
-    const void* pNext = {};
-    uint32_t maxIndirectCommandsLayoutTokenCount = {};
-    uint32_t maxObjectEntryCounts = {};
-    uint32_t minSequenceCountBufferOffsetAlignment = {};
-    uint32_t minSequenceIndexBufferOffsetAlignment = {};
-    uint32_t minCommandsTokenBufferOffsetAlignment = {};
-  };
-  static_assert( sizeof( DeviceGeneratedCommandsLimitsNVX ) == sizeof( VkDeviceGeneratedCommandsLimitsNVX ), "struct and wrapper have different size!" );
-  static_assert( std::is_standard_layout<DeviceGeneratedCommandsLimitsNVX>::value, "struct wrapper is not a standard layout!" );
-
   struct DeviceGroupBindSparseInfo
   {
     VULKAN_HPP_CONSTEXPR DeviceGroupBindSparseInfo( uint32_t resourceDeviceIndex_ = {},
@@ -31386,12 +32596,6 @@
       , memoryDeviceIndex( memoryDeviceIndex_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DeviceGroupBindSparseInfo( DeviceGroupBindSparseInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , resourceDeviceIndex( rhs.resourceDeviceIndex )
-      , memoryDeviceIndex( rhs.memoryDeviceIndex )
-    {}
-
     DeviceGroupBindSparseInfo & operator=( DeviceGroupBindSparseInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DeviceGroupBindSparseInfo ) - offsetof( DeviceGroupBindSparseInfo, pNext ) );
@@ -31469,11 +32673,6 @@
       : deviceMask( deviceMask_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DeviceGroupCommandBufferBeginInfo( DeviceGroupCommandBufferBeginInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , deviceMask( rhs.deviceMask )
-    {}
-
     DeviceGroupCommandBufferBeginInfo & operator=( DeviceGroupCommandBufferBeginInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DeviceGroupCommandBufferBeginInfo ) - offsetof( DeviceGroupCommandBufferBeginInfo, pNext ) );
@@ -31545,12 +32744,6 @@
       , pPhysicalDevices( pPhysicalDevices_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DeviceGroupDeviceCreateInfo( DeviceGroupDeviceCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , physicalDeviceCount( rhs.physicalDeviceCount )
-      , pPhysicalDevices( rhs.pPhysicalDevices )
-    {}
-
     DeviceGroupDeviceCreateInfo & operator=( DeviceGroupDeviceCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DeviceGroupDeviceCreateInfo ) - offsetof( DeviceGroupDeviceCreateInfo, pNext ) );
@@ -31626,19 +32819,9 @@
   {
     VULKAN_HPP_CONSTEXPR_14 DeviceGroupPresentCapabilitiesKHR( std::array<uint32_t,VK_MAX_DEVICE_GROUP_SIZE> const& presentMask_ = {},
                                                                VULKAN_HPP_NAMESPACE::DeviceGroupPresentModeFlagsKHR modes_ = {} ) VULKAN_HPP_NOEXCEPT
-      : presentMask{}
+      : presentMask( presentMask_ )
       , modes( modes_ )
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint32_t,VK_MAX_DEVICE_GROUP_SIZE>::copy( presentMask, presentMask_ );
-    }
-
-    VULKAN_HPP_CONSTEXPR_14 DeviceGroupPresentCapabilitiesKHR( DeviceGroupPresentCapabilitiesKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , presentMask{}
-      , modes( rhs.modes )
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint32_t,VK_MAX_DEVICE_GROUP_SIZE>::copy( presentMask, rhs.presentMask );
-    }
+    {}
 
     DeviceGroupPresentCapabilitiesKHR & operator=( DeviceGroupPresentCapabilitiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
@@ -31674,7 +32857,7 @@
     {
       return ( sType == rhs.sType )
           && ( pNext == rhs.pNext )
-          && ( memcmp( presentMask, rhs.presentMask, VK_MAX_DEVICE_GROUP_SIZE * sizeof( uint32_t ) ) == 0 )
+          && ( presentMask == rhs.presentMask )
           && ( modes == rhs.modes );
     }
 
@@ -31687,7 +32870,7 @@
   public:
     const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eDeviceGroupPresentCapabilitiesKHR;
     const void* pNext = {};
-    uint32_t presentMask[VK_MAX_DEVICE_GROUP_SIZE] = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<uint32_t, VK_MAX_DEVICE_GROUP_SIZE> presentMask = {};
     VULKAN_HPP_NAMESPACE::DeviceGroupPresentModeFlagsKHR modes = {};
   };
   static_assert( sizeof( DeviceGroupPresentCapabilitiesKHR ) == sizeof( VkDeviceGroupPresentCapabilitiesKHR ), "struct and wrapper have different size!" );
@@ -31703,13 +32886,6 @@
       , mode( mode_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DeviceGroupPresentInfoKHR( DeviceGroupPresentInfoKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , swapchainCount( rhs.swapchainCount )
-      , pDeviceMasks( rhs.pDeviceMasks )
-      , mode( rhs.mode )
-    {}
-
     DeviceGroupPresentInfoKHR & operator=( DeviceGroupPresentInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DeviceGroupPresentInfoKHR ) - offsetof( DeviceGroupPresentInfoKHR, pNext ) );
@@ -31799,13 +32975,6 @@
       , pDeviceRenderAreas( pDeviceRenderAreas_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DeviceGroupRenderPassBeginInfo( DeviceGroupRenderPassBeginInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , deviceMask( rhs.deviceMask )
-      , deviceRenderAreaCount( rhs.deviceRenderAreaCount )
-      , pDeviceRenderAreas( rhs.pDeviceRenderAreas )
-    {}
-
     DeviceGroupRenderPassBeginInfo & operator=( DeviceGroupRenderPassBeginInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DeviceGroupRenderPassBeginInfo ) - offsetof( DeviceGroupRenderPassBeginInfo, pNext ) );
@@ -31901,16 +33070,6 @@
       , pSignalSemaphoreDeviceIndices( pSignalSemaphoreDeviceIndices_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DeviceGroupSubmitInfo( DeviceGroupSubmitInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , waitSemaphoreCount( rhs.waitSemaphoreCount )
-      , pWaitSemaphoreDeviceIndices( rhs.pWaitSemaphoreDeviceIndices )
-      , commandBufferCount( rhs.commandBufferCount )
-      , pCommandBufferDeviceMasks( rhs.pCommandBufferDeviceMasks )
-      , signalSemaphoreCount( rhs.signalSemaphoreCount )
-      , pSignalSemaphoreDeviceIndices( rhs.pSignalSemaphoreDeviceIndices )
-    {}
-
     DeviceGroupSubmitInfo & operator=( DeviceGroupSubmitInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DeviceGroupSubmitInfo ) - offsetof( DeviceGroupSubmitInfo, pNext ) );
@@ -32020,11 +33179,6 @@
       : modes( modes_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DeviceGroupSwapchainCreateInfoKHR( DeviceGroupSwapchainCreateInfoKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , modes( rhs.modes )
-    {}
-
     DeviceGroupSwapchainCreateInfoKHR & operator=( DeviceGroupSwapchainCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DeviceGroupSwapchainCreateInfoKHR ) - offsetof( DeviceGroupSwapchainCreateInfoKHR, pNext ) );
@@ -32094,11 +33248,6 @@
       : memory( memory_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DeviceMemoryOpaqueCaptureAddressInfo( DeviceMemoryOpaqueCaptureAddressInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , memory( rhs.memory )
-    {}
-
     DeviceMemoryOpaqueCaptureAddressInfo & operator=( DeviceMemoryOpaqueCaptureAddressInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DeviceMemoryOpaqueCaptureAddressInfo ) - offsetof( DeviceMemoryOpaqueCaptureAddressInfo, pNext ) );
@@ -32168,11 +33317,6 @@
       : overallocationBehavior( overallocationBehavior_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DeviceMemoryOverallocationCreateInfoAMD( DeviceMemoryOverallocationCreateInfoAMD const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , overallocationBehavior( rhs.overallocationBehavior )
-    {}
-
     DeviceMemoryOverallocationCreateInfoAMD & operator=( DeviceMemoryOverallocationCreateInfoAMD const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DeviceMemoryOverallocationCreateInfoAMD ) - offsetof( DeviceMemoryOverallocationCreateInfoAMD, pNext ) );
@@ -32242,11 +33386,6 @@
       : globalPriority( globalPriority_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DeviceQueueGlobalPriorityCreateInfoEXT( DeviceQueueGlobalPriorityCreateInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , globalPriority( rhs.globalPriority )
-    {}
-
     DeviceQueueGlobalPriorityCreateInfoEXT & operator=( DeviceQueueGlobalPriorityCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DeviceQueueGlobalPriorityCreateInfoEXT ) - offsetof( DeviceQueueGlobalPriorityCreateInfoEXT, pNext ) );
@@ -32320,13 +33459,6 @@
       , queueIndex( queueIndex_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DeviceQueueInfo2( DeviceQueueInfo2 const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , queueFamilyIndex( rhs.queueFamilyIndex )
-      , queueIndex( rhs.queueIndex )
-    {}
-
     DeviceQueueInfo2 & operator=( DeviceQueueInfo2 const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DeviceQueueInfo2 ) - offsetof( DeviceQueueInfo2, pNext ) );
@@ -32416,18 +33548,6 @@
       , z( z_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DispatchIndirectCommand( DispatchIndirectCommand const& rhs ) VULKAN_HPP_NOEXCEPT
-      : x( rhs.x )
-      , y( rhs.y )
-      , z( rhs.z )
-    {}
-
-    DispatchIndirectCommand & operator=( DispatchIndirectCommand const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( DispatchIndirectCommand ) );
-      return *this;
-    }
-
     DispatchIndirectCommand( VkDispatchIndirectCommand const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -32497,11 +33617,6 @@
       : displayEvent( displayEvent_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DisplayEventInfoEXT( DisplayEventInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , displayEvent( rhs.displayEvent )
-    {}
-
     DisplayEventInfoEXT & operator=( DisplayEventInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DisplayEventInfoEXT ) - offsetof( DisplayEventInfoEXT, pNext ) );
@@ -32573,17 +33688,6 @@
       , refreshRate( refreshRate_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DisplayModeParametersKHR( DisplayModeParametersKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : visibleRegion( rhs.visibleRegion )
-      , refreshRate( rhs.refreshRate )
-    {}
-
-    DisplayModeParametersKHR & operator=( DisplayModeParametersKHR const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( DisplayModeParametersKHR ) );
-      return *this;
-    }
-
     DisplayModeParametersKHR( VkDisplayModeParametersKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -32647,12 +33751,6 @@
       , parameters( parameters_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DisplayModeCreateInfoKHR( DisplayModeCreateInfoKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , parameters( rhs.parameters )
-    {}
-
     DisplayModeCreateInfoKHR & operator=( DisplayModeCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DisplayModeCreateInfoKHR ) - offsetof( DisplayModeCreateInfoKHR, pNext ) );
@@ -32732,17 +33830,6 @@
       , parameters( parameters_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DisplayModePropertiesKHR( DisplayModePropertiesKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : displayMode( rhs.displayMode )
-      , parameters( rhs.parameters )
-    {}
-
-    DisplayModePropertiesKHR & operator=( DisplayModePropertiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( DisplayModePropertiesKHR ) );
-      return *this;
-    }
-
     DisplayModePropertiesKHR( VkDisplayModePropertiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -32792,11 +33879,6 @@
       : displayModeProperties( displayModeProperties_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DisplayModeProperties2KHR( DisplayModeProperties2KHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , displayModeProperties( rhs.displayModeProperties )
-    {}
-
     DisplayModeProperties2KHR & operator=( DisplayModeProperties2KHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DisplayModeProperties2KHR ) - offsetof( DisplayModeProperties2KHR, pNext ) );
@@ -32854,11 +33936,6 @@
       : localDimmingSupport( localDimmingSupport_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DisplayNativeHdrSurfaceCapabilitiesAMD( DisplayNativeHdrSurfaceCapabilitiesAMD const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , localDimmingSupport( rhs.localDimmingSupport )
-    {}
-
     DisplayNativeHdrSurfaceCapabilitiesAMD & operator=( DisplayNativeHdrSurfaceCapabilitiesAMD const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DisplayNativeHdrSurfaceCapabilitiesAMD ) - offsetof( DisplayNativeHdrSurfaceCapabilitiesAMD, pNext ) );
@@ -32932,24 +34009,6 @@
       , maxDstExtent( maxDstExtent_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DisplayPlaneCapabilitiesKHR( DisplayPlaneCapabilitiesKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : supportedAlpha( rhs.supportedAlpha )
-      , minSrcPosition( rhs.minSrcPosition )
-      , maxSrcPosition( rhs.maxSrcPosition )
-      , minSrcExtent( rhs.minSrcExtent )
-      , maxSrcExtent( rhs.maxSrcExtent )
-      , minDstPosition( rhs.minDstPosition )
-      , maxDstPosition( rhs.maxDstPosition )
-      , minDstExtent( rhs.minDstExtent )
-      , maxDstExtent( rhs.maxDstExtent )
-    {}
-
-    DisplayPlaneCapabilitiesKHR & operator=( DisplayPlaneCapabilitiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( DisplayPlaneCapabilitiesKHR ) );
-      return *this;
-    }
-
     DisplayPlaneCapabilitiesKHR( VkDisplayPlaneCapabilitiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -33013,11 +34072,6 @@
       : capabilities( capabilities_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DisplayPlaneCapabilities2KHR( DisplayPlaneCapabilities2KHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , capabilities( rhs.capabilities )
-    {}
-
     DisplayPlaneCapabilities2KHR & operator=( DisplayPlaneCapabilities2KHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DisplayPlaneCapabilities2KHR ) - offsetof( DisplayPlaneCapabilities2KHR, pNext ) );
@@ -33077,12 +34131,6 @@
       , planeIndex( planeIndex_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DisplayPlaneInfo2KHR( DisplayPlaneInfo2KHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , mode( rhs.mode )
-      , planeIndex( rhs.planeIndex )
-    {}
-
     DisplayPlaneInfo2KHR & operator=( DisplayPlaneInfo2KHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DisplayPlaneInfo2KHR ) - offsetof( DisplayPlaneInfo2KHR, pNext ) );
@@ -33162,17 +34210,6 @@
       , currentStackIndex( currentStackIndex_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DisplayPlanePropertiesKHR( DisplayPlanePropertiesKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : currentDisplay( rhs.currentDisplay )
-      , currentStackIndex( rhs.currentStackIndex )
-    {}
-
-    DisplayPlanePropertiesKHR & operator=( DisplayPlanePropertiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( DisplayPlanePropertiesKHR ) );
-      return *this;
-    }
-
     DisplayPlanePropertiesKHR( VkDisplayPlanePropertiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -33222,11 +34259,6 @@
       : displayPlaneProperties( displayPlaneProperties_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DisplayPlaneProperties2KHR( DisplayPlaneProperties2KHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , displayPlaneProperties( rhs.displayPlaneProperties )
-    {}
-
     DisplayPlaneProperties2KHR & operator=( DisplayPlaneProperties2KHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DisplayPlaneProperties2KHR ) - offsetof( DisplayPlaneProperties2KHR, pNext ) );
@@ -33284,11 +34316,6 @@
       : powerState( powerState_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DisplayPowerInfoEXT( DisplayPowerInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , powerState( rhs.powerState )
-    {}
-
     DisplayPowerInfoEXT & operator=( DisplayPowerInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DisplayPowerInfoEXT ) - offsetof( DisplayPowerInfoEXT, pNext ) );
@@ -33362,13 +34389,6 @@
       , persistent( persistent_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DisplayPresentInfoKHR( DisplayPresentInfoKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , srcRect( rhs.srcRect )
-      , dstRect( rhs.dstRect )
-      , persistent( rhs.persistent )
-    {}
-
     DisplayPresentInfoKHR & operator=( DisplayPresentInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DisplayPresentInfoKHR ) - offsetof( DisplayPresentInfoKHR, pNext ) );
@@ -33466,22 +34486,6 @@
       , persistentContent( persistentContent_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DisplayPropertiesKHR( DisplayPropertiesKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : display( rhs.display )
-      , displayName( rhs.displayName )
-      , physicalDimensions( rhs.physicalDimensions )
-      , physicalResolution( rhs.physicalResolution )
-      , supportedTransforms( rhs.supportedTransforms )
-      , planeReorderPossible( rhs.planeReorderPossible )
-      , persistentContent( rhs.persistentContent )
-    {}
-
-    DisplayPropertiesKHR & operator=( DisplayPropertiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( DisplayPropertiesKHR ) );
-      return *this;
-    }
-
     DisplayPropertiesKHR( VkDisplayPropertiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -33541,11 +34545,6 @@
       : displayProperties( displayProperties_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DisplayProperties2KHR( DisplayProperties2KHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , displayProperties( rhs.displayProperties )
-    {}
-
     DisplayProperties2KHR & operator=( DisplayProperties2KHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DisplayProperties2KHR ) - offsetof( DisplayProperties2KHR, pNext ) );
@@ -33617,18 +34616,6 @@
       , imageExtent( imageExtent_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DisplaySurfaceCreateInfoKHR( DisplaySurfaceCreateInfoKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , displayMode( rhs.displayMode )
-      , planeIndex( rhs.planeIndex )
-      , planeStackIndex( rhs.planeStackIndex )
-      , transform( rhs.transform )
-      , globalAlpha( rhs.globalAlpha )
-      , alphaMode( rhs.alphaMode )
-      , imageExtent( rhs.imageExtent )
-    {}
-
     DisplaySurfaceCreateInfoKHR & operator=( DisplaySurfaceCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DisplaySurfaceCreateInfoKHR ) - offsetof( DisplaySurfaceCreateInfoKHR, pNext ) );
@@ -33762,20 +34749,6 @@
       , firstInstance( firstInstance_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DrawIndexedIndirectCommand( DrawIndexedIndirectCommand const& rhs ) VULKAN_HPP_NOEXCEPT
-      : indexCount( rhs.indexCount )
-      , instanceCount( rhs.instanceCount )
-      , firstIndex( rhs.firstIndex )
-      , vertexOffset( rhs.vertexOffset )
-      , firstInstance( rhs.firstInstance )
-    {}
-
-    DrawIndexedIndirectCommand & operator=( DrawIndexedIndirectCommand const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( DrawIndexedIndirectCommand ) );
-      return *this;
-    }
-
     DrawIndexedIndirectCommand( VkDrawIndexedIndirectCommand const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -33867,19 +34840,6 @@
       , firstInstance( firstInstance_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DrawIndirectCommand( DrawIndirectCommand const& rhs ) VULKAN_HPP_NOEXCEPT
-      : vertexCount( rhs.vertexCount )
-      , instanceCount( rhs.instanceCount )
-      , firstVertex( rhs.firstVertex )
-      , firstInstance( rhs.firstInstance )
-    {}
-
-    DrawIndirectCommand & operator=( DrawIndirectCommand const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( DrawIndirectCommand ) );
-      return *this;
-    }
-
     DrawIndirectCommand( VkDrawIndirectCommand const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -33959,17 +34919,6 @@
       , firstTask( firstTask_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DrawMeshTasksIndirectCommandNV( DrawMeshTasksIndirectCommandNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : taskCount( rhs.taskCount )
-      , firstTask( rhs.firstTask )
-    {}
-
-    DrawMeshTasksIndirectCommandNV & operator=( DrawMeshTasksIndirectCommandNV const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( DrawMeshTasksIndirectCommandNV ) );
-      return *this;
-    }
-
     DrawMeshTasksIndirectCommandNV( VkDrawMeshTasksIndirectCommandNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -34035,18 +34984,6 @@
       , drmFormatModifierTilingFeatures( drmFormatModifierTilingFeatures_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DrmFormatModifierPropertiesEXT( DrmFormatModifierPropertiesEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : drmFormatModifier( rhs.drmFormatModifier )
-      , drmFormatModifierPlaneCount( rhs.drmFormatModifierPlaneCount )
-      , drmFormatModifierTilingFeatures( rhs.drmFormatModifierTilingFeatures )
-    {}
-
-    DrmFormatModifierPropertiesEXT & operator=( DrmFormatModifierPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( DrmFormatModifierPropertiesEXT ) );
-      return *this;
-    }
-
     DrmFormatModifierPropertiesEXT( VkDrmFormatModifierPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -34100,12 +35037,6 @@
       , pDrmFormatModifierProperties( pDrmFormatModifierProperties_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR DrmFormatModifierPropertiesListEXT( DrmFormatModifierPropertiesListEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , drmFormatModifierCount( rhs.drmFormatModifierCount )
-      , pDrmFormatModifierProperties( rhs.pDrmFormatModifierProperties )
-    {}
-
     DrmFormatModifierPropertiesListEXT & operator=( DrmFormatModifierPropertiesListEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( DrmFormatModifierPropertiesListEXT ) - offsetof( DrmFormatModifierPropertiesListEXT, pNext ) );
@@ -34165,11 +35096,6 @@
       : flags( flags_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR EventCreateInfo( EventCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-    {}
-
     EventCreateInfo & operator=( EventCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( EventCreateInfo ) - offsetof( EventCreateInfo, pNext ) );
@@ -34239,11 +35165,6 @@
       : handleTypes( handleTypes_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ExportFenceCreateInfo( ExportFenceCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , handleTypes( rhs.handleTypes )
-    {}
-
     ExportFenceCreateInfo & operator=( ExportFenceCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ExportFenceCreateInfo ) - offsetof( ExportFenceCreateInfo, pNext ) );
@@ -34318,13 +35239,6 @@
       , name( name_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ExportFenceWin32HandleInfoKHR( ExportFenceWin32HandleInfoKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , pAttributes( rhs.pAttributes )
-      , dwAccess( rhs.dwAccess )
-      , name( rhs.name )
-    {}
-
     ExportFenceWin32HandleInfoKHR & operator=( ExportFenceWin32HandleInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ExportFenceWin32HandleInfoKHR ) - offsetof( ExportFenceWin32HandleInfoKHR, pNext ) );
@@ -34411,11 +35325,6 @@
       : handleTypes( handleTypes_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ExportMemoryAllocateInfo( ExportMemoryAllocateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , handleTypes( rhs.handleTypes )
-    {}
-
     ExportMemoryAllocateInfo & operator=( ExportMemoryAllocateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ExportMemoryAllocateInfo ) - offsetof( ExportMemoryAllocateInfo, pNext ) );
@@ -34485,11 +35394,6 @@
       : handleTypes( handleTypes_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ExportMemoryAllocateInfoNV( ExportMemoryAllocateInfoNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , handleTypes( rhs.handleTypes )
-    {}
-
     ExportMemoryAllocateInfoNV & operator=( ExportMemoryAllocateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ExportMemoryAllocateInfoNV ) - offsetof( ExportMemoryAllocateInfoNV, pNext ) );
@@ -34564,13 +35468,6 @@
       , name( name_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ExportMemoryWin32HandleInfoKHR( ExportMemoryWin32HandleInfoKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , pAttributes( rhs.pAttributes )
-      , dwAccess( rhs.dwAccess )
-      , name( rhs.name )
-    {}
-
     ExportMemoryWin32HandleInfoKHR & operator=( ExportMemoryWin32HandleInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ExportMemoryWin32HandleInfoKHR ) - offsetof( ExportMemoryWin32HandleInfoKHR, pNext ) );
@@ -34660,12 +35557,6 @@
       , dwAccess( dwAccess_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ExportMemoryWin32HandleInfoNV( ExportMemoryWin32HandleInfoNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , pAttributes( rhs.pAttributes )
-      , dwAccess( rhs.dwAccess )
-    {}
-
     ExportMemoryWin32HandleInfoNV & operator=( ExportMemoryWin32HandleInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ExportMemoryWin32HandleInfoNV ) - offsetof( ExportMemoryWin32HandleInfoNV, pNext ) );
@@ -34744,11 +35635,6 @@
       : handleTypes( handleTypes_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ExportSemaphoreCreateInfo( ExportSemaphoreCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , handleTypes( rhs.handleTypes )
-    {}
-
     ExportSemaphoreCreateInfo & operator=( ExportSemaphoreCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ExportSemaphoreCreateInfo ) - offsetof( ExportSemaphoreCreateInfo, pNext ) );
@@ -34823,13 +35709,6 @@
       , name( name_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ExportSemaphoreWin32HandleInfoKHR( ExportSemaphoreWin32HandleInfoKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , pAttributes( rhs.pAttributes )
-      , dwAccess( rhs.dwAccess )
-      , name( rhs.name )
-    {}
-
     ExportSemaphoreWin32HandleInfoKHR & operator=( ExportSemaphoreWin32HandleInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ExportSemaphoreWin32HandleInfoKHR ) - offsetof( ExportSemaphoreWin32HandleInfoKHR, pNext ) );
@@ -34914,24 +35793,9 @@
   {
     VULKAN_HPP_CONSTEXPR_14 ExtensionProperties( std::array<char,VK_MAX_EXTENSION_NAME_SIZE> const& extensionName_ = {},
                                                  uint32_t specVersion_ = {} ) VULKAN_HPP_NOEXCEPT
-      : extensionName{}
+      : extensionName( extensionName_ )
       , specVersion( specVersion_ )
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_EXTENSION_NAME_SIZE>::copy( extensionName, extensionName_ );
-    }
-
-    VULKAN_HPP_CONSTEXPR_14 ExtensionProperties( ExtensionProperties const& rhs ) VULKAN_HPP_NOEXCEPT
-      : extensionName{}
-      , specVersion( rhs.specVersion )
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_EXTENSION_NAME_SIZE>::copy( extensionName, rhs.extensionName );
-    }
-
-    ExtensionProperties & operator=( ExtensionProperties const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( ExtensionProperties ) );
-      return *this;
-    }
+    {}
 
     ExtensionProperties( VkExtensionProperties const & rhs ) VULKAN_HPP_NOEXCEPT
     {
@@ -34959,7 +35823,7 @@
 #else
     bool operator==( ExtensionProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
     {
-      return ( memcmp( extensionName, rhs.extensionName, VK_MAX_EXTENSION_NAME_SIZE * sizeof( char ) ) == 0 )
+      return ( extensionName == rhs.extensionName )
           && ( specVersion == rhs.specVersion );
     }
 
@@ -34970,7 +35834,7 @@
 #endif
 
   public:
-    char extensionName[VK_MAX_EXTENSION_NAME_SIZE] = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<char, VK_MAX_EXTENSION_NAME_SIZE> extensionName = {};
     uint32_t specVersion = {};
   };
   static_assert( sizeof( ExtensionProperties ) == sizeof( VkExtensionProperties ), "struct and wrapper have different size!" );
@@ -34986,18 +35850,6 @@
       , compatibleHandleTypes( compatibleHandleTypes_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ExternalMemoryProperties( ExternalMemoryProperties const& rhs ) VULKAN_HPP_NOEXCEPT
-      : externalMemoryFeatures( rhs.externalMemoryFeatures )
-      , exportFromImportedHandleTypes( rhs.exportFromImportedHandleTypes )
-      , compatibleHandleTypes( rhs.compatibleHandleTypes )
-    {}
-
-    ExternalMemoryProperties & operator=( ExternalMemoryProperties const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( ExternalMemoryProperties ) );
-      return *this;
-    }
-
     ExternalMemoryProperties( VkExternalMemoryProperties const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -35049,11 +35901,6 @@
       : externalMemoryProperties( externalMemoryProperties_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ExternalBufferProperties( ExternalBufferProperties const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , externalMemoryProperties( rhs.externalMemoryProperties )
-    {}
-
     ExternalBufferProperties & operator=( ExternalBufferProperties const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ExternalBufferProperties ) - offsetof( ExternalBufferProperties, pNext ) );
@@ -35115,13 +35962,6 @@
       , externalFenceFeatures( externalFenceFeatures_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ExternalFenceProperties( ExternalFenceProperties const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , exportFromImportedHandleTypes( rhs.exportFromImportedHandleTypes )
-      , compatibleHandleTypes( rhs.compatibleHandleTypes )
-      , externalFenceFeatures( rhs.externalFenceFeatures )
-    {}
-
     ExternalFenceProperties & operator=( ExternalFenceProperties const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ExternalFenceProperties ) - offsetof( ExternalFenceProperties, pNext ) );
@@ -35184,11 +36024,6 @@
       : externalFormat( externalFormat_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ExternalFormatANDROID( ExternalFormatANDROID const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , externalFormat( rhs.externalFormat )
-    {}
-
     ExternalFormatANDROID & operator=( ExternalFormatANDROID const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ExternalFormatANDROID ) - offsetof( ExternalFormatANDROID, pNext ) );
@@ -35259,11 +36094,6 @@
       : externalMemoryProperties( externalMemoryProperties_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ExternalImageFormatProperties( ExternalImageFormatProperties const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , externalMemoryProperties( rhs.externalMemoryProperties )
-    {}
-
     ExternalImageFormatProperties & operator=( ExternalImageFormatProperties const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ExternalImageFormatProperties ) - offsetof( ExternalImageFormatProperties, pNext ) );
@@ -35329,20 +36159,6 @@
       , maxResourceSize( maxResourceSize_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ImageFormatProperties( ImageFormatProperties const& rhs ) VULKAN_HPP_NOEXCEPT
-      : maxExtent( rhs.maxExtent )
-      , maxMipLevels( rhs.maxMipLevels )
-      , maxArrayLayers( rhs.maxArrayLayers )
-      , sampleCounts( rhs.sampleCounts )
-      , maxResourceSize( rhs.maxResourceSize )
-    {}
-
-    ImageFormatProperties & operator=( ImageFormatProperties const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( ImageFormatProperties ) );
-      return *this;
-    }
-
     ImageFormatProperties( VkImageFormatProperties const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -35404,19 +36220,6 @@
       , compatibleHandleTypes( compatibleHandleTypes_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ExternalImageFormatPropertiesNV( ExternalImageFormatPropertiesNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : imageFormatProperties( rhs.imageFormatProperties )
-      , externalMemoryFeatures( rhs.externalMemoryFeatures )
-      , exportFromImportedHandleTypes( rhs.exportFromImportedHandleTypes )
-      , compatibleHandleTypes( rhs.compatibleHandleTypes )
-    {}
-
-    ExternalImageFormatPropertiesNV & operator=( ExternalImageFormatPropertiesNV const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( ExternalImageFormatPropertiesNV ) );
-      return *this;
-    }
-
     ExternalImageFormatPropertiesNV( VkExternalImageFormatPropertiesNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -35470,11 +36273,6 @@
       : handleTypes( handleTypes_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ExternalMemoryBufferCreateInfo( ExternalMemoryBufferCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , handleTypes( rhs.handleTypes )
-    {}
-
     ExternalMemoryBufferCreateInfo & operator=( ExternalMemoryBufferCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ExternalMemoryBufferCreateInfo ) - offsetof( ExternalMemoryBufferCreateInfo, pNext ) );
@@ -35544,11 +36342,6 @@
       : handleTypes( handleTypes_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ExternalMemoryImageCreateInfo( ExternalMemoryImageCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , handleTypes( rhs.handleTypes )
-    {}
-
     ExternalMemoryImageCreateInfo & operator=( ExternalMemoryImageCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ExternalMemoryImageCreateInfo ) - offsetof( ExternalMemoryImageCreateInfo, pNext ) );
@@ -35618,11 +36411,6 @@
       : handleTypes( handleTypes_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ExternalMemoryImageCreateInfoNV( ExternalMemoryImageCreateInfoNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , handleTypes( rhs.handleTypes )
-    {}
-
     ExternalMemoryImageCreateInfoNV & operator=( ExternalMemoryImageCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ExternalMemoryImageCreateInfoNV ) - offsetof( ExternalMemoryImageCreateInfoNV, pNext ) );
@@ -35696,13 +36484,6 @@
       , externalSemaphoreFeatures( externalSemaphoreFeatures_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ExternalSemaphoreProperties( ExternalSemaphoreProperties const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , exportFromImportedHandleTypes( rhs.exportFromImportedHandleTypes )
-      , compatibleHandleTypes( rhs.compatibleHandleTypes )
-      , externalSemaphoreFeatures( rhs.externalSemaphoreFeatures )
-    {}
-
     ExternalSemaphoreProperties & operator=( ExternalSemaphoreProperties const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ExternalSemaphoreProperties ) - offsetof( ExternalSemaphoreProperties, pNext ) );
@@ -35764,11 +36545,6 @@
       : flags( flags_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR FenceCreateInfo( FenceCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-    {}
-
     FenceCreateInfo & operator=( FenceCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( FenceCreateInfo ) - offsetof( FenceCreateInfo, pNext ) );
@@ -35840,12 +36616,6 @@
       , handleType( handleType_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR FenceGetFdInfoKHR( FenceGetFdInfoKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , fence( rhs.fence )
-      , handleType( rhs.handleType )
-    {}
-
     FenceGetFdInfoKHR & operator=( FenceGetFdInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( FenceGetFdInfoKHR ) - offsetof( FenceGetFdInfoKHR, pNext ) );
@@ -35926,12 +36696,6 @@
       , handleType( handleType_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR FenceGetWin32HandleInfoKHR( FenceGetWin32HandleInfoKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , fence( rhs.fence )
-      , handleType( rhs.handleType )
-    {}
-
     FenceGetWin32HandleInfoKHR & operator=( FenceGetWin32HandleInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( FenceGetWin32HandleInfoKHR ) - offsetof( FenceGetWin32HandleInfoKHR, pNext ) );
@@ -36012,12 +36776,6 @@
       , filterCubicMinmax( filterCubicMinmax_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR FilterCubicImageViewImageFormatPropertiesEXT( FilterCubicImageViewImageFormatPropertiesEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , filterCubic( rhs.filterCubic )
-      , filterCubicMinmax( rhs.filterCubicMinmax )
-    {}
-
     FilterCubicImageViewImageFormatPropertiesEXT & operator=( FilterCubicImageViewImageFormatPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( FilterCubicImageViewImageFormatPropertiesEXT ) - offsetof( FilterCubicImageViewImageFormatPropertiesEXT, pNext ) );
@@ -36081,18 +36839,6 @@
       , bufferFeatures( bufferFeatures_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR FormatProperties( FormatProperties const& rhs ) VULKAN_HPP_NOEXCEPT
-      : linearTilingFeatures( rhs.linearTilingFeatures )
-      , optimalTilingFeatures( rhs.optimalTilingFeatures )
-      , bufferFeatures( rhs.bufferFeatures )
-    {}
-
-    FormatProperties & operator=( FormatProperties const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( FormatProperties ) );
-      return *this;
-    }
-
     FormatProperties( VkFormatProperties const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -36144,11 +36890,6 @@
       : formatProperties( formatProperties_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR FormatProperties2( FormatProperties2 const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , formatProperties( rhs.formatProperties )
-    {}
-
     FormatProperties2 & operator=( FormatProperties2 const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( FormatProperties2 ) - offsetof( FormatProperties2, pNext ) );
@@ -36218,17 +36959,6 @@
       , pViewFormats( pViewFormats_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR FramebufferAttachmentImageInfo( FramebufferAttachmentImageInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , usage( rhs.usage )
-      , width( rhs.width )
-      , height( rhs.height )
-      , layerCount( rhs.layerCount )
-      , viewFormatCount( rhs.viewFormatCount )
-      , pViewFormats( rhs.pViewFormats )
-    {}
-
     FramebufferAttachmentImageInfo & operator=( FramebufferAttachmentImageInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( FramebufferAttachmentImageInfo ) - offsetof( FramebufferAttachmentImageInfo, pNext ) );
@@ -36348,12 +37078,6 @@
       , pAttachmentImageInfos( pAttachmentImageInfos_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR FramebufferAttachmentsCreateInfo( FramebufferAttachmentsCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , attachmentImageInfoCount( rhs.attachmentImageInfoCount )
-      , pAttachmentImageInfos( rhs.pAttachmentImageInfos )
-    {}
-
     FramebufferAttachmentsCreateInfo & operator=( FramebufferAttachmentsCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( FramebufferAttachmentsCreateInfo ) - offsetof( FramebufferAttachmentsCreateInfo, pNext ) );
@@ -36443,17 +37167,6 @@
       , layers( layers_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR FramebufferCreateInfo( FramebufferCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , renderPass( rhs.renderPass )
-      , attachmentCount( rhs.attachmentCount )
-      , pAttachments( rhs.pAttachments )
-      , width( rhs.width )
-      , height( rhs.height )
-      , layers( rhs.layers )
-    {}
-
     FramebufferCreateInfo & operator=( FramebufferCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( FramebufferCreateInfo ) - offsetof( FramebufferCreateInfo, pNext ) );
@@ -36577,14 +37290,6 @@
       , colorSamples( colorSamples_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR FramebufferMixedSamplesCombinationNV( FramebufferMixedSamplesCombinationNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , coverageReductionMode( rhs.coverageReductionMode )
-      , rasterizationSamples( rhs.rasterizationSamples )
-      , depthStencilSamples( rhs.depthStencilSamples )
-      , colorSamples( rhs.colorSamples )
-    {}
-
     FramebufferMixedSamplesCombinationNV & operator=( FramebufferMixedSamplesCombinationNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( FramebufferMixedSamplesCombinationNV ) - offsetof( FramebufferMixedSamplesCombinationNV, pNext ) );
@@ -36642,6 +37347,357 @@
   static_assert( sizeof( FramebufferMixedSamplesCombinationNV ) == sizeof( VkFramebufferMixedSamplesCombinationNV ), "struct and wrapper have different size!" );
   static_assert( std::is_standard_layout<FramebufferMixedSamplesCombinationNV>::value, "struct wrapper is not a standard layout!" );
 
+  struct IndirectCommandsStreamNV
+  {
+    VULKAN_HPP_CONSTEXPR IndirectCommandsStreamNV( VULKAN_HPP_NAMESPACE::Buffer buffer_ = {},
+                                                   VULKAN_HPP_NAMESPACE::DeviceSize offset_ = {} ) VULKAN_HPP_NOEXCEPT
+      : buffer( buffer_ )
+      , offset( offset_ )
+    {}
+
+    IndirectCommandsStreamNV( VkIndirectCommandsStreamNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    IndirectCommandsStreamNV& operator=( VkIndirectCommandsStreamNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::IndirectCommandsStreamNV const *>(&rhs);
+      return *this;
+    }
+
+    IndirectCommandsStreamNV & setBuffer( VULKAN_HPP_NAMESPACE::Buffer buffer_ ) VULKAN_HPP_NOEXCEPT
+    {
+      buffer = buffer_;
+      return *this;
+    }
+
+    IndirectCommandsStreamNV & setOffset( VULKAN_HPP_NAMESPACE::DeviceSize offset_ ) VULKAN_HPP_NOEXCEPT
+    {
+      offset = offset_;
+      return *this;
+    }
+
+    operator VkIndirectCommandsStreamNV const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkIndirectCommandsStreamNV*>( this );
+    }
+
+    operator VkIndirectCommandsStreamNV &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkIndirectCommandsStreamNV*>( this );
+    }
+
+#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
+    auto operator<=>( IndirectCommandsStreamNV const& ) const = default;
+#else
+    bool operator==( IndirectCommandsStreamNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ( buffer == rhs.buffer )
+          && ( offset == rhs.offset );
+    }
+
+    bool operator!=( IndirectCommandsStreamNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return !operator==( rhs );
+    }
+#endif
+
+  public:
+    VULKAN_HPP_NAMESPACE::Buffer buffer = {};
+    VULKAN_HPP_NAMESPACE::DeviceSize offset = {};
+  };
+  static_assert( sizeof( IndirectCommandsStreamNV ) == sizeof( VkIndirectCommandsStreamNV ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<IndirectCommandsStreamNV>::value, "struct wrapper is not a standard layout!" );
+
+  struct GeneratedCommandsInfoNV
+  {
+    VULKAN_HPP_CONSTEXPR GeneratedCommandsInfoNV( VULKAN_HPP_NAMESPACE::PipelineBindPoint pipelineBindPoint_ = VULKAN_HPP_NAMESPACE::PipelineBindPoint::eGraphics,
+                                                  VULKAN_HPP_NAMESPACE::Pipeline pipeline_ = {},
+                                                  VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNV indirectCommandsLayout_ = {},
+                                                  uint32_t streamCount_ = {},
+                                                  const VULKAN_HPP_NAMESPACE::IndirectCommandsStreamNV* pStreams_ = {},
+                                                  uint32_t sequencesCount_ = {},
+                                                  VULKAN_HPP_NAMESPACE::Buffer preprocessBuffer_ = {},
+                                                  VULKAN_HPP_NAMESPACE::DeviceSize preprocessOffset_ = {},
+                                                  VULKAN_HPP_NAMESPACE::DeviceSize preprocessSize_ = {},
+                                                  VULKAN_HPP_NAMESPACE::Buffer sequencesCountBuffer_ = {},
+                                                  VULKAN_HPP_NAMESPACE::DeviceSize sequencesCountOffset_ = {},
+                                                  VULKAN_HPP_NAMESPACE::Buffer sequencesIndexBuffer_ = {},
+                                                  VULKAN_HPP_NAMESPACE::DeviceSize sequencesIndexOffset_ = {} ) VULKAN_HPP_NOEXCEPT
+      : pipelineBindPoint( pipelineBindPoint_ )
+      , pipeline( pipeline_ )
+      , indirectCommandsLayout( indirectCommandsLayout_ )
+      , streamCount( streamCount_ )
+      , pStreams( pStreams_ )
+      , sequencesCount( sequencesCount_ )
+      , preprocessBuffer( preprocessBuffer_ )
+      , preprocessOffset( preprocessOffset_ )
+      , preprocessSize( preprocessSize_ )
+      , sequencesCountBuffer( sequencesCountBuffer_ )
+      , sequencesCountOffset( sequencesCountOffset_ )
+      , sequencesIndexBuffer( sequencesIndexBuffer_ )
+      , sequencesIndexOffset( sequencesIndexOffset_ )
+    {}
+
+    GeneratedCommandsInfoNV & operator=( GeneratedCommandsInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      memcpy( &pNext, &rhs.pNext, sizeof( GeneratedCommandsInfoNV ) - offsetof( GeneratedCommandsInfoNV, pNext ) );
+      return *this;
+    }
+
+    GeneratedCommandsInfoNV( VkGeneratedCommandsInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    GeneratedCommandsInfoNV& operator=( VkGeneratedCommandsInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::GeneratedCommandsInfoNV const *>(&rhs);
+      return *this;
+    }
+
+    GeneratedCommandsInfoNV & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pNext = pNext_;
+      return *this;
+    }
+
+    GeneratedCommandsInfoNV & setPipelineBindPoint( VULKAN_HPP_NAMESPACE::PipelineBindPoint pipelineBindPoint_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pipelineBindPoint = pipelineBindPoint_;
+      return *this;
+    }
+
+    GeneratedCommandsInfoNV & setPipeline( VULKAN_HPP_NAMESPACE::Pipeline pipeline_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pipeline = pipeline_;
+      return *this;
+    }
+
+    GeneratedCommandsInfoNV & setIndirectCommandsLayout( VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNV indirectCommandsLayout_ ) VULKAN_HPP_NOEXCEPT
+    {
+      indirectCommandsLayout = indirectCommandsLayout_;
+      return *this;
+    }
+
+    GeneratedCommandsInfoNV & setStreamCount( uint32_t streamCount_ ) VULKAN_HPP_NOEXCEPT
+    {
+      streamCount = streamCount_;
+      return *this;
+    }
+
+    GeneratedCommandsInfoNV & setPStreams( const VULKAN_HPP_NAMESPACE::IndirectCommandsStreamNV* pStreams_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pStreams = pStreams_;
+      return *this;
+    }
+
+    GeneratedCommandsInfoNV & setSequencesCount( uint32_t sequencesCount_ ) VULKAN_HPP_NOEXCEPT
+    {
+      sequencesCount = sequencesCount_;
+      return *this;
+    }
+
+    GeneratedCommandsInfoNV & setPreprocessBuffer( VULKAN_HPP_NAMESPACE::Buffer preprocessBuffer_ ) VULKAN_HPP_NOEXCEPT
+    {
+      preprocessBuffer = preprocessBuffer_;
+      return *this;
+    }
+
+    GeneratedCommandsInfoNV & setPreprocessOffset( VULKAN_HPP_NAMESPACE::DeviceSize preprocessOffset_ ) VULKAN_HPP_NOEXCEPT
+    {
+      preprocessOffset = preprocessOffset_;
+      return *this;
+    }
+
+    GeneratedCommandsInfoNV & setPreprocessSize( VULKAN_HPP_NAMESPACE::DeviceSize preprocessSize_ ) VULKAN_HPP_NOEXCEPT
+    {
+      preprocessSize = preprocessSize_;
+      return *this;
+    }
+
+    GeneratedCommandsInfoNV & setSequencesCountBuffer( VULKAN_HPP_NAMESPACE::Buffer sequencesCountBuffer_ ) VULKAN_HPP_NOEXCEPT
+    {
+      sequencesCountBuffer = sequencesCountBuffer_;
+      return *this;
+    }
+
+    GeneratedCommandsInfoNV & setSequencesCountOffset( VULKAN_HPP_NAMESPACE::DeviceSize sequencesCountOffset_ ) VULKAN_HPP_NOEXCEPT
+    {
+      sequencesCountOffset = sequencesCountOffset_;
+      return *this;
+    }
+
+    GeneratedCommandsInfoNV & setSequencesIndexBuffer( VULKAN_HPP_NAMESPACE::Buffer sequencesIndexBuffer_ ) VULKAN_HPP_NOEXCEPT
+    {
+      sequencesIndexBuffer = sequencesIndexBuffer_;
+      return *this;
+    }
+
+    GeneratedCommandsInfoNV & setSequencesIndexOffset( VULKAN_HPP_NAMESPACE::DeviceSize sequencesIndexOffset_ ) VULKAN_HPP_NOEXCEPT
+    {
+      sequencesIndexOffset = sequencesIndexOffset_;
+      return *this;
+    }
+
+    operator VkGeneratedCommandsInfoNV const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkGeneratedCommandsInfoNV*>( this );
+    }
+
+    operator VkGeneratedCommandsInfoNV &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkGeneratedCommandsInfoNV*>( this );
+    }
+
+#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
+    auto operator<=>( GeneratedCommandsInfoNV const& ) const = default;
+#else
+    bool operator==( GeneratedCommandsInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ( sType == rhs.sType )
+          && ( pNext == rhs.pNext )
+          && ( pipelineBindPoint == rhs.pipelineBindPoint )
+          && ( pipeline == rhs.pipeline )
+          && ( indirectCommandsLayout == rhs.indirectCommandsLayout )
+          && ( streamCount == rhs.streamCount )
+          && ( pStreams == rhs.pStreams )
+          && ( sequencesCount == rhs.sequencesCount )
+          && ( preprocessBuffer == rhs.preprocessBuffer )
+          && ( preprocessOffset == rhs.preprocessOffset )
+          && ( preprocessSize == rhs.preprocessSize )
+          && ( sequencesCountBuffer == rhs.sequencesCountBuffer )
+          && ( sequencesCountOffset == rhs.sequencesCountOffset )
+          && ( sequencesIndexBuffer == rhs.sequencesIndexBuffer )
+          && ( sequencesIndexOffset == rhs.sequencesIndexOffset );
+    }
+
+    bool operator!=( GeneratedCommandsInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return !operator==( rhs );
+    }
+#endif
+
+  public:
+    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eGeneratedCommandsInfoNV;
+    const void* pNext = {};
+    VULKAN_HPP_NAMESPACE::PipelineBindPoint pipelineBindPoint = VULKAN_HPP_NAMESPACE::PipelineBindPoint::eGraphics;
+    VULKAN_HPP_NAMESPACE::Pipeline pipeline = {};
+    VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNV indirectCommandsLayout = {};
+    uint32_t streamCount = {};
+    const VULKAN_HPP_NAMESPACE::IndirectCommandsStreamNV* pStreams = {};
+    uint32_t sequencesCount = {};
+    VULKAN_HPP_NAMESPACE::Buffer preprocessBuffer = {};
+    VULKAN_HPP_NAMESPACE::DeviceSize preprocessOffset = {};
+    VULKAN_HPP_NAMESPACE::DeviceSize preprocessSize = {};
+    VULKAN_HPP_NAMESPACE::Buffer sequencesCountBuffer = {};
+    VULKAN_HPP_NAMESPACE::DeviceSize sequencesCountOffset = {};
+    VULKAN_HPP_NAMESPACE::Buffer sequencesIndexBuffer = {};
+    VULKAN_HPP_NAMESPACE::DeviceSize sequencesIndexOffset = {};
+  };
+  static_assert( sizeof( GeneratedCommandsInfoNV ) == sizeof( VkGeneratedCommandsInfoNV ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<GeneratedCommandsInfoNV>::value, "struct wrapper is not a standard layout!" );
+
+  struct GeneratedCommandsMemoryRequirementsInfoNV
+  {
+    VULKAN_HPP_CONSTEXPR GeneratedCommandsMemoryRequirementsInfoNV( VULKAN_HPP_NAMESPACE::PipelineBindPoint pipelineBindPoint_ = VULKAN_HPP_NAMESPACE::PipelineBindPoint::eGraphics,
+                                                                    VULKAN_HPP_NAMESPACE::Pipeline pipeline_ = {},
+                                                                    VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNV indirectCommandsLayout_ = {},
+                                                                    uint32_t maxSequencesCount_ = {} ) VULKAN_HPP_NOEXCEPT
+      : pipelineBindPoint( pipelineBindPoint_ )
+      , pipeline( pipeline_ )
+      , indirectCommandsLayout( indirectCommandsLayout_ )
+      , maxSequencesCount( maxSequencesCount_ )
+    {}
+
+    GeneratedCommandsMemoryRequirementsInfoNV & operator=( GeneratedCommandsMemoryRequirementsInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      memcpy( &pNext, &rhs.pNext, sizeof( GeneratedCommandsMemoryRequirementsInfoNV ) - offsetof( GeneratedCommandsMemoryRequirementsInfoNV, pNext ) );
+      return *this;
+    }
+
+    GeneratedCommandsMemoryRequirementsInfoNV( VkGeneratedCommandsMemoryRequirementsInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    GeneratedCommandsMemoryRequirementsInfoNV& operator=( VkGeneratedCommandsMemoryRequirementsInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::GeneratedCommandsMemoryRequirementsInfoNV const *>(&rhs);
+      return *this;
+    }
+
+    GeneratedCommandsMemoryRequirementsInfoNV & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pNext = pNext_;
+      return *this;
+    }
+
+    GeneratedCommandsMemoryRequirementsInfoNV & setPipelineBindPoint( VULKAN_HPP_NAMESPACE::PipelineBindPoint pipelineBindPoint_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pipelineBindPoint = pipelineBindPoint_;
+      return *this;
+    }
+
+    GeneratedCommandsMemoryRequirementsInfoNV & setPipeline( VULKAN_HPP_NAMESPACE::Pipeline pipeline_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pipeline = pipeline_;
+      return *this;
+    }
+
+    GeneratedCommandsMemoryRequirementsInfoNV & setIndirectCommandsLayout( VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNV indirectCommandsLayout_ ) VULKAN_HPP_NOEXCEPT
+    {
+      indirectCommandsLayout = indirectCommandsLayout_;
+      return *this;
+    }
+
+    GeneratedCommandsMemoryRequirementsInfoNV & setMaxSequencesCount( uint32_t maxSequencesCount_ ) VULKAN_HPP_NOEXCEPT
+    {
+      maxSequencesCount = maxSequencesCount_;
+      return *this;
+    }
+
+    operator VkGeneratedCommandsMemoryRequirementsInfoNV const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkGeneratedCommandsMemoryRequirementsInfoNV*>( this );
+    }
+
+    operator VkGeneratedCommandsMemoryRequirementsInfoNV &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkGeneratedCommandsMemoryRequirementsInfoNV*>( this );
+    }
+
+#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
+    auto operator<=>( GeneratedCommandsMemoryRequirementsInfoNV const& ) const = default;
+#else
+    bool operator==( GeneratedCommandsMemoryRequirementsInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ( sType == rhs.sType )
+          && ( pNext == rhs.pNext )
+          && ( pipelineBindPoint == rhs.pipelineBindPoint )
+          && ( pipeline == rhs.pipeline )
+          && ( indirectCommandsLayout == rhs.indirectCommandsLayout )
+          && ( maxSequencesCount == rhs.maxSequencesCount );
+    }
+
+    bool operator!=( GeneratedCommandsMemoryRequirementsInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return !operator==( rhs );
+    }
+#endif
+
+  public:
+    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eGeneratedCommandsMemoryRequirementsInfoNV;
+    const void* pNext = {};
+    VULKAN_HPP_NAMESPACE::PipelineBindPoint pipelineBindPoint = VULKAN_HPP_NAMESPACE::PipelineBindPoint::eGraphics;
+    VULKAN_HPP_NAMESPACE::Pipeline pipeline = {};
+    VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNV indirectCommandsLayout = {};
+    uint32_t maxSequencesCount = {};
+  };
+  static_assert( sizeof( GeneratedCommandsMemoryRequirementsInfoNV ) == sizeof( VkGeneratedCommandsMemoryRequirementsInfoNV ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<GeneratedCommandsMemoryRequirementsInfoNV>::value, "struct wrapper is not a standard layout!" );
+
   struct VertexInputBindingDescription
   {
     VULKAN_HPP_CONSTEXPR VertexInputBindingDescription( uint32_t binding_ = {},
@@ -36652,18 +37708,6 @@
       , inputRate( inputRate_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR VertexInputBindingDescription( VertexInputBindingDescription const& rhs ) VULKAN_HPP_NOEXCEPT
-      : binding( rhs.binding )
-      , stride( rhs.stride )
-      , inputRate( rhs.inputRate )
-    {}
-
-    VertexInputBindingDescription & operator=( VertexInputBindingDescription const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( VertexInputBindingDescription ) );
-      return *this;
-    }
-
     VertexInputBindingDescription( VkVertexInputBindingDescription const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -36739,19 +37783,6 @@
       , offset( offset_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR VertexInputAttributeDescription( VertexInputAttributeDescription const& rhs ) VULKAN_HPP_NOEXCEPT
-      : location( rhs.location )
-      , binding( rhs.binding )
-      , format( rhs.format )
-      , offset( rhs.offset )
-    {}
-
-    VertexInputAttributeDescription & operator=( VertexInputAttributeDescription const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( VertexInputAttributeDescription ) );
-      return *this;
-    }
-
     VertexInputAttributeDescription( VkVertexInputAttributeDescription const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -36837,15 +37868,6 @@
       , pVertexAttributeDescriptions( pVertexAttributeDescriptions_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PipelineVertexInputStateCreateInfo( PipelineVertexInputStateCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , vertexBindingDescriptionCount( rhs.vertexBindingDescriptionCount )
-      , pVertexBindingDescriptions( rhs.pVertexBindingDescriptions )
-      , vertexAttributeDescriptionCount( rhs.vertexAttributeDescriptionCount )
-      , pVertexAttributeDescriptions( rhs.pVertexAttributeDescriptions )
-    {}
-
     PipelineVertexInputStateCreateInfo & operator=( PipelineVertexInputStateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PipelineVertexInputStateCreateInfo ) - offsetof( PipelineVertexInputStateCreateInfo, pNext ) );
@@ -36951,13 +37973,6 @@
       , primitiveRestartEnable( primitiveRestartEnable_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PipelineInputAssemblyStateCreateInfo( PipelineInputAssemblyStateCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , topology( rhs.topology )
-      , primitiveRestartEnable( rhs.primitiveRestartEnable )
-    {}
-
     PipelineInputAssemblyStateCreateInfo & operator=( PipelineInputAssemblyStateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PipelineInputAssemblyStateCreateInfo ) - offsetof( PipelineInputAssemblyStateCreateInfo, pNext ) );
@@ -37045,12 +38060,6 @@
       , patchControlPoints( patchControlPoints_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PipelineTessellationStateCreateInfo( PipelineTessellationStateCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , patchControlPoints( rhs.patchControlPoints )
-    {}
-
     PipelineTessellationStateCreateInfo & operator=( PipelineTessellationStateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PipelineTessellationStateCreateInfo ) - offsetof( PipelineTessellationStateCreateInfo, pNext ) );
@@ -37138,21 +38147,6 @@
       , maxDepth( maxDepth_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR Viewport( Viewport const& rhs ) VULKAN_HPP_NOEXCEPT
-      : x( rhs.x )
-      , y( rhs.y )
-      , width( rhs.width )
-      , height( rhs.height )
-      , minDepth( rhs.minDepth )
-      , maxDepth( rhs.maxDepth )
-    {}
-
-    Viewport & operator=( Viewport const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( Viewport ) );
-      return *this;
-    }
-
     Viewport( VkViewport const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -37254,15 +38248,6 @@
       , pScissors( pScissors_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PipelineViewportStateCreateInfo( PipelineViewportStateCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , viewportCount( rhs.viewportCount )
-      , pViewports( rhs.pViewports )
-      , scissorCount( rhs.scissorCount )
-      , pScissors( rhs.pScissors )
-    {}
-
     PipelineViewportStateCreateInfo & operator=( PipelineViewportStateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PipelineViewportStateCreateInfo ) - offsetof( PipelineViewportStateCreateInfo, pNext ) );
@@ -37384,21 +38369,6 @@
       , lineWidth( lineWidth_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PipelineRasterizationStateCreateInfo( PipelineRasterizationStateCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , depthClampEnable( rhs.depthClampEnable )
-      , rasterizerDiscardEnable( rhs.rasterizerDiscardEnable )
-      , polygonMode( rhs.polygonMode )
-      , cullMode( rhs.cullMode )
-      , frontFace( rhs.frontFace )
-      , depthBiasEnable( rhs.depthBiasEnable )
-      , depthBiasConstantFactor( rhs.depthBiasConstantFactor )
-      , depthBiasClamp( rhs.depthBiasClamp )
-      , depthBiasSlopeFactor( rhs.depthBiasSlopeFactor )
-      , lineWidth( rhs.lineWidth )
-    {}
-
     PipelineRasterizationStateCreateInfo & operator=( PipelineRasterizationStateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PipelineRasterizationStateCreateInfo ) - offsetof( PipelineRasterizationStateCreateInfo, pNext ) );
@@ -37560,17 +38530,6 @@
       , alphaToOneEnable( alphaToOneEnable_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PipelineMultisampleStateCreateInfo( PipelineMultisampleStateCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , rasterizationSamples( rhs.rasterizationSamples )
-      , sampleShadingEnable( rhs.sampleShadingEnable )
-      , minSampleShading( rhs.minSampleShading )
-      , pSampleMask( rhs.pSampleMask )
-      , alphaToCoverageEnable( rhs.alphaToCoverageEnable )
-      , alphaToOneEnable( rhs.alphaToOneEnable )
-    {}
-
     PipelineMultisampleStateCreateInfo & operator=( PipelineMultisampleStateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PipelineMultisampleStateCreateInfo ) - offsetof( PipelineMultisampleStateCreateInfo, pNext ) );
@@ -37700,22 +38659,6 @@
       , reference( reference_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR StencilOpState( StencilOpState const& rhs ) VULKAN_HPP_NOEXCEPT
-      : failOp( rhs.failOp )
-      , passOp( rhs.passOp )
-      , depthFailOp( rhs.depthFailOp )
-      , compareOp( rhs.compareOp )
-      , compareMask( rhs.compareMask )
-      , writeMask( rhs.writeMask )
-      , reference( rhs.reference )
-    {}
-
-    StencilOpState & operator=( StencilOpState const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( StencilOpState ) );
-      return *this;
-    }
-
     StencilOpState( VkStencilOpState const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -37835,20 +38778,6 @@
       , maxDepthBounds( maxDepthBounds_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PipelineDepthStencilStateCreateInfo( PipelineDepthStencilStateCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , depthTestEnable( rhs.depthTestEnable )
-      , depthWriteEnable( rhs.depthWriteEnable )
-      , depthCompareOp( rhs.depthCompareOp )
-      , depthBoundsTestEnable( rhs.depthBoundsTestEnable )
-      , stencilTestEnable( rhs.stencilTestEnable )
-      , front( rhs.front )
-      , back( rhs.back )
-      , minDepthBounds( rhs.minDepthBounds )
-      , maxDepthBounds( rhs.maxDepthBounds )
-    {}
-
     PipelineDepthStencilStateCreateInfo & operator=( PipelineDepthStencilStateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PipelineDepthStencilStateCreateInfo ) - offsetof( PipelineDepthStencilStateCreateInfo, pNext ) );
@@ -38004,23 +38933,6 @@
       , colorWriteMask( colorWriteMask_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PipelineColorBlendAttachmentState( PipelineColorBlendAttachmentState const& rhs ) VULKAN_HPP_NOEXCEPT
-      : blendEnable( rhs.blendEnable )
-      , srcColorBlendFactor( rhs.srcColorBlendFactor )
-      , dstColorBlendFactor( rhs.dstColorBlendFactor )
-      , colorBlendOp( rhs.colorBlendOp )
-      , srcAlphaBlendFactor( rhs.srcAlphaBlendFactor )
-      , dstAlphaBlendFactor( rhs.dstAlphaBlendFactor )
-      , alphaBlendOp( rhs.alphaBlendOp )
-      , colorWriteMask( rhs.colorWriteMask )
-    {}
-
-    PipelineColorBlendAttachmentState & operator=( PipelineColorBlendAttachmentState const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( PipelineColorBlendAttachmentState ) );
-      return *this;
-    }
-
     PipelineColorBlendAttachmentState( VkPipelineColorBlendAttachmentState const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -38137,22 +39049,8 @@
       , logicOp( logicOp_ )
       , attachmentCount( attachmentCount_ )
       , pAttachments( pAttachments_ )
-      , blendConstants{}
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<float,4>::copy( blendConstants, blendConstants_ );
-    }
-
-    VULKAN_HPP_CONSTEXPR_14 PipelineColorBlendStateCreateInfo( PipelineColorBlendStateCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , logicOpEnable( rhs.logicOpEnable )
-      , logicOp( rhs.logicOp )
-      , attachmentCount( rhs.attachmentCount )
-      , pAttachments( rhs.pAttachments )
-      , blendConstants{}
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<float,4>::copy( blendConstants, rhs.blendConstants );
-    }
+      , blendConstants( blendConstants_ )
+    {}
 
     PipelineColorBlendStateCreateInfo & operator=( PipelineColorBlendStateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
@@ -38209,7 +39107,7 @@
 
     PipelineColorBlendStateCreateInfo & setBlendConstants( std::array<float,4> blendConstants_ ) VULKAN_HPP_NOEXCEPT
     {
-      memcpy( blendConstants, blendConstants_.data(), 4 * sizeof( float ) );
+      blendConstants = blendConstants_;
       return *this;
     }
 
@@ -38235,7 +39133,7 @@
           && ( logicOp == rhs.logicOp )
           && ( attachmentCount == rhs.attachmentCount )
           && ( pAttachments == rhs.pAttachments )
-          && ( memcmp( blendConstants, rhs.blendConstants, 4 * sizeof( float ) ) == 0 );
+          && ( blendConstants == rhs.blendConstants );
     }
 
     bool operator!=( PipelineColorBlendStateCreateInfo const& rhs ) const VULKAN_HPP_NOEXCEPT
@@ -38252,7 +39150,7 @@
     VULKAN_HPP_NAMESPACE::LogicOp logicOp = VULKAN_HPP_NAMESPACE::LogicOp::eClear;
     uint32_t attachmentCount = {};
     const VULKAN_HPP_NAMESPACE::PipelineColorBlendAttachmentState* pAttachments = {};
-    float blendConstants[4] = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<float, 4> blendConstants = {};
   };
   static_assert( sizeof( PipelineColorBlendStateCreateInfo ) == sizeof( VkPipelineColorBlendStateCreateInfo ), "struct and wrapper have different size!" );
   static_assert( std::is_standard_layout<PipelineColorBlendStateCreateInfo>::value, "struct wrapper is not a standard layout!" );
@@ -38267,13 +39165,6 @@
       , pDynamicStates( pDynamicStates_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PipelineDynamicStateCreateInfo( PipelineDynamicStateCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , dynamicStateCount( rhs.dynamicStateCount )
-      , pDynamicStates( rhs.pDynamicStates )
-    {}
-
     PipelineDynamicStateCreateInfo & operator=( PipelineDynamicStateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PipelineDynamicStateCreateInfo ) - offsetof( PipelineDynamicStateCreateInfo, pNext ) );
@@ -38391,27 +39282,6 @@
       , basePipelineIndex( basePipelineIndex_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR_14 GraphicsPipelineCreateInfo( GraphicsPipelineCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , stageCount( rhs.stageCount )
-      , pStages( rhs.pStages )
-      , pVertexInputState( rhs.pVertexInputState )
-      , pInputAssemblyState( rhs.pInputAssemblyState )
-      , pTessellationState( rhs.pTessellationState )
-      , pViewportState( rhs.pViewportState )
-      , pRasterizationState( rhs.pRasterizationState )
-      , pMultisampleState( rhs.pMultisampleState )
-      , pDepthStencilState( rhs.pDepthStencilState )
-      , pColorBlendState( rhs.pColorBlendState )
-      , pDynamicState( rhs.pDynamicState )
-      , layout( rhs.layout )
-      , renderPass( rhs.renderPass )
-      , subpass( rhs.subpass )
-      , basePipelineHandle( rhs.basePipelineHandle )
-      , basePipelineIndex( rhs.basePipelineIndex )
-    {}
-
     GraphicsPipelineCreateInfo & operator=( GraphicsPipelineCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( GraphicsPipelineCreateInfo ) - offsetof( GraphicsPipelineCreateInfo, pNext ) );
@@ -38603,6 +39473,204 @@
   static_assert( sizeof( GraphicsPipelineCreateInfo ) == sizeof( VkGraphicsPipelineCreateInfo ), "struct and wrapper have different size!" );
   static_assert( std::is_standard_layout<GraphicsPipelineCreateInfo>::value, "struct wrapper is not a standard layout!" );
 
+  struct GraphicsShaderGroupCreateInfoNV
+  {
+    VULKAN_HPP_CONSTEXPR GraphicsShaderGroupCreateInfoNV( uint32_t stageCount_ = {},
+                                                          const VULKAN_HPP_NAMESPACE::PipelineShaderStageCreateInfo* pStages_ = {},
+                                                          const VULKAN_HPP_NAMESPACE::PipelineVertexInputStateCreateInfo* pVertexInputState_ = {},
+                                                          const VULKAN_HPP_NAMESPACE::PipelineTessellationStateCreateInfo* pTessellationState_ = {} ) VULKAN_HPP_NOEXCEPT
+      : stageCount( stageCount_ )
+      , pStages( pStages_ )
+      , pVertexInputState( pVertexInputState_ )
+      , pTessellationState( pTessellationState_ )
+    {}
+
+    GraphicsShaderGroupCreateInfoNV & operator=( GraphicsShaderGroupCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      memcpy( &pNext, &rhs.pNext, sizeof( GraphicsShaderGroupCreateInfoNV ) - offsetof( GraphicsShaderGroupCreateInfoNV, pNext ) );
+      return *this;
+    }
+
+    GraphicsShaderGroupCreateInfoNV( VkGraphicsShaderGroupCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    GraphicsShaderGroupCreateInfoNV& operator=( VkGraphicsShaderGroupCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::GraphicsShaderGroupCreateInfoNV const *>(&rhs);
+      return *this;
+    }
+
+    GraphicsShaderGroupCreateInfoNV & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pNext = pNext_;
+      return *this;
+    }
+
+    GraphicsShaderGroupCreateInfoNV & setStageCount( uint32_t stageCount_ ) VULKAN_HPP_NOEXCEPT
+    {
+      stageCount = stageCount_;
+      return *this;
+    }
+
+    GraphicsShaderGroupCreateInfoNV & setPStages( const VULKAN_HPP_NAMESPACE::PipelineShaderStageCreateInfo* pStages_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pStages = pStages_;
+      return *this;
+    }
+
+    GraphicsShaderGroupCreateInfoNV & setPVertexInputState( const VULKAN_HPP_NAMESPACE::PipelineVertexInputStateCreateInfo* pVertexInputState_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pVertexInputState = pVertexInputState_;
+      return *this;
+    }
+
+    GraphicsShaderGroupCreateInfoNV & setPTessellationState( const VULKAN_HPP_NAMESPACE::PipelineTessellationStateCreateInfo* pTessellationState_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pTessellationState = pTessellationState_;
+      return *this;
+    }
+
+    operator VkGraphicsShaderGroupCreateInfoNV const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkGraphicsShaderGroupCreateInfoNV*>( this );
+    }
+
+    operator VkGraphicsShaderGroupCreateInfoNV &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkGraphicsShaderGroupCreateInfoNV*>( this );
+    }
+
+#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
+    auto operator<=>( GraphicsShaderGroupCreateInfoNV const& ) const = default;
+#else
+    bool operator==( GraphicsShaderGroupCreateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ( sType == rhs.sType )
+          && ( pNext == rhs.pNext )
+          && ( stageCount == rhs.stageCount )
+          && ( pStages == rhs.pStages )
+          && ( pVertexInputState == rhs.pVertexInputState )
+          && ( pTessellationState == rhs.pTessellationState );
+    }
+
+    bool operator!=( GraphicsShaderGroupCreateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return !operator==( rhs );
+    }
+#endif
+
+  public:
+    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eGraphicsShaderGroupCreateInfoNV;
+    const void* pNext = {};
+    uint32_t stageCount = {};
+    const VULKAN_HPP_NAMESPACE::PipelineShaderStageCreateInfo* pStages = {};
+    const VULKAN_HPP_NAMESPACE::PipelineVertexInputStateCreateInfo* pVertexInputState = {};
+    const VULKAN_HPP_NAMESPACE::PipelineTessellationStateCreateInfo* pTessellationState = {};
+  };
+  static_assert( sizeof( GraphicsShaderGroupCreateInfoNV ) == sizeof( VkGraphicsShaderGroupCreateInfoNV ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<GraphicsShaderGroupCreateInfoNV>::value, "struct wrapper is not a standard layout!" );
+
+  struct GraphicsPipelineShaderGroupsCreateInfoNV
+  {
+    VULKAN_HPP_CONSTEXPR GraphicsPipelineShaderGroupsCreateInfoNV( uint32_t groupCount_ = {},
+                                                                   const VULKAN_HPP_NAMESPACE::GraphicsShaderGroupCreateInfoNV* pGroups_ = {},
+                                                                   uint32_t pipelineCount_ = {},
+                                                                   const VULKAN_HPP_NAMESPACE::Pipeline* pPipelines_ = {} ) VULKAN_HPP_NOEXCEPT
+      : groupCount( groupCount_ )
+      , pGroups( pGroups_ )
+      , pipelineCount( pipelineCount_ )
+      , pPipelines( pPipelines_ )
+    {}
+
+    GraphicsPipelineShaderGroupsCreateInfoNV & operator=( GraphicsPipelineShaderGroupsCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      memcpy( &pNext, &rhs.pNext, sizeof( GraphicsPipelineShaderGroupsCreateInfoNV ) - offsetof( GraphicsPipelineShaderGroupsCreateInfoNV, pNext ) );
+      return *this;
+    }
+
+    GraphicsPipelineShaderGroupsCreateInfoNV( VkGraphicsPipelineShaderGroupsCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    GraphicsPipelineShaderGroupsCreateInfoNV& operator=( VkGraphicsPipelineShaderGroupsCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::GraphicsPipelineShaderGroupsCreateInfoNV const *>(&rhs);
+      return *this;
+    }
+
+    GraphicsPipelineShaderGroupsCreateInfoNV & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pNext = pNext_;
+      return *this;
+    }
+
+    GraphicsPipelineShaderGroupsCreateInfoNV & setGroupCount( uint32_t groupCount_ ) VULKAN_HPP_NOEXCEPT
+    {
+      groupCount = groupCount_;
+      return *this;
+    }
+
+    GraphicsPipelineShaderGroupsCreateInfoNV & setPGroups( const VULKAN_HPP_NAMESPACE::GraphicsShaderGroupCreateInfoNV* pGroups_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pGroups = pGroups_;
+      return *this;
+    }
+
+    GraphicsPipelineShaderGroupsCreateInfoNV & setPipelineCount( uint32_t pipelineCount_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pipelineCount = pipelineCount_;
+      return *this;
+    }
+
+    GraphicsPipelineShaderGroupsCreateInfoNV & setPPipelines( const VULKAN_HPP_NAMESPACE::Pipeline* pPipelines_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pPipelines = pPipelines_;
+      return *this;
+    }
+
+    operator VkGraphicsPipelineShaderGroupsCreateInfoNV const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkGraphicsPipelineShaderGroupsCreateInfoNV*>( this );
+    }
+
+    operator VkGraphicsPipelineShaderGroupsCreateInfoNV &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkGraphicsPipelineShaderGroupsCreateInfoNV*>( this );
+    }
+
+#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
+    auto operator<=>( GraphicsPipelineShaderGroupsCreateInfoNV const& ) const = default;
+#else
+    bool operator==( GraphicsPipelineShaderGroupsCreateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ( sType == rhs.sType )
+          && ( pNext == rhs.pNext )
+          && ( groupCount == rhs.groupCount )
+          && ( pGroups == rhs.pGroups )
+          && ( pipelineCount == rhs.pipelineCount )
+          && ( pPipelines == rhs.pPipelines );
+    }
+
+    bool operator!=( GraphicsPipelineShaderGroupsCreateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return !operator==( rhs );
+    }
+#endif
+
+  public:
+    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eGraphicsPipelineShaderGroupsCreateInfoNV;
+    const void* pNext = {};
+    uint32_t groupCount = {};
+    const VULKAN_HPP_NAMESPACE::GraphicsShaderGroupCreateInfoNV* pGroups = {};
+    uint32_t pipelineCount = {};
+    const VULKAN_HPP_NAMESPACE::Pipeline* pPipelines = {};
+  };
+  static_assert( sizeof( GraphicsPipelineShaderGroupsCreateInfoNV ) == sizeof( VkGraphicsPipelineShaderGroupsCreateInfoNV ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<GraphicsPipelineShaderGroupsCreateInfoNV>::value, "struct wrapper is not a standard layout!" );
+
   struct XYColorEXT
   {
     VULKAN_HPP_CONSTEXPR XYColorEXT( float x_ = {},
@@ -38611,17 +39679,6 @@
       , y( y_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR XYColorEXT( XYColorEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : x( rhs.x )
-      , y( rhs.y )
-    {}
-
-    XYColorEXT & operator=( XYColorEXT const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( XYColorEXT ) );
-      return *this;
-    }
-
     XYColorEXT( VkXYColorEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -38697,18 +39754,6 @@
       , maxFrameAverageLightLevel( maxFrameAverageLightLevel_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR HdrMetadataEXT( HdrMetadataEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , displayPrimaryRed( rhs.displayPrimaryRed )
-      , displayPrimaryGreen( rhs.displayPrimaryGreen )
-      , displayPrimaryBlue( rhs.displayPrimaryBlue )
-      , whitePoint( rhs.whitePoint )
-      , maxLuminance( rhs.maxLuminance )
-      , minLuminance( rhs.minLuminance )
-      , maxContentLightLevel( rhs.maxContentLightLevel )
-      , maxFrameAverageLightLevel( rhs.maxFrameAverageLightLevel )
-    {}
-
     HdrMetadataEXT & operator=( HdrMetadataEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( HdrMetadataEXT ) - offsetof( HdrMetadataEXT, pNext ) );
@@ -38834,11 +39879,6 @@
       : flags( flags_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR HeadlessSurfaceCreateInfoEXT( HeadlessSurfaceCreateInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-    {}
-
     HeadlessSurfaceCreateInfoEXT & operator=( HeadlessSurfaceCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( HeadlessSurfaceCreateInfoEXT ) - offsetof( HeadlessSurfaceCreateInfoEXT, pNext ) );
@@ -38911,12 +39951,6 @@
       , pView( pView_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR IOSSurfaceCreateInfoMVK( IOSSurfaceCreateInfoMVK const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , pView( rhs.pView )
-    {}
-
     IOSSurfaceCreateInfoMVK & operator=( IOSSurfaceCreateInfoMVK const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( IOSSurfaceCreateInfoMVK ) - offsetof( IOSSurfaceCreateInfoMVK, pNext ) );
@@ -38996,29 +40030,10 @@
                                        VULKAN_HPP_NAMESPACE::ImageSubresourceLayers dstSubresource_ = {},
                                        std::array<VULKAN_HPP_NAMESPACE::Offset3D,2> const& dstOffsets_ = {} ) VULKAN_HPP_NOEXCEPT
       : srcSubresource( srcSubresource_ )
-      , srcOffsets{}
+      , srcOffsets( srcOffsets_ )
       , dstSubresource( dstSubresource_ )
-      , dstOffsets{}
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<VULKAN_HPP_NAMESPACE::Offset3D,2>::copy( srcOffsets, srcOffsets_ );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<VULKAN_HPP_NAMESPACE::Offset3D,2>::copy( dstOffsets, dstOffsets_ );
-    }
-
-    VULKAN_HPP_CONSTEXPR_14 ImageBlit( ImageBlit const& rhs ) VULKAN_HPP_NOEXCEPT
-      : srcSubresource( rhs.srcSubresource )
-      , srcOffsets{}
-      , dstSubresource( rhs.dstSubresource )
-      , dstOffsets{}
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<VULKAN_HPP_NAMESPACE::Offset3D,2>::copy( srcOffsets, rhs.srcOffsets );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<VULKAN_HPP_NAMESPACE::Offset3D,2>::copy( dstOffsets, rhs.dstOffsets );
-    }
-
-    ImageBlit & operator=( ImageBlit const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( ImageBlit ) );
-      return *this;
-    }
+      , dstOffsets( dstOffsets_ )
+    {}
 
     ImageBlit( VkImageBlit const & rhs ) VULKAN_HPP_NOEXCEPT
     {
@@ -39039,7 +40054,7 @@
 
     ImageBlit & setSrcOffsets( std::array<VULKAN_HPP_NAMESPACE::Offset3D,2> srcOffsets_ ) VULKAN_HPP_NOEXCEPT
     {
-      memcpy( srcOffsets, srcOffsets_.data(), 2 * sizeof( VULKAN_HPP_NAMESPACE::Offset3D ) );
+      srcOffsets = srcOffsets_;
       return *this;
     }
 
@@ -39051,7 +40066,7 @@
 
     ImageBlit & setDstOffsets( std::array<VULKAN_HPP_NAMESPACE::Offset3D,2> dstOffsets_ ) VULKAN_HPP_NOEXCEPT
     {
-      memcpy( dstOffsets, dstOffsets_.data(), 2 * sizeof( VULKAN_HPP_NAMESPACE::Offset3D ) );
+      dstOffsets = dstOffsets_;
       return *this;
     }
 
@@ -39071,9 +40086,9 @@
     bool operator==( ImageBlit const& rhs ) const VULKAN_HPP_NOEXCEPT
     {
       return ( srcSubresource == rhs.srcSubresource )
-          && ( memcmp( srcOffsets, rhs.srcOffsets, 2 * sizeof( VULKAN_HPP_NAMESPACE::Offset3D ) ) == 0 )
+          && ( srcOffsets == rhs.srcOffsets )
           && ( dstSubresource == rhs.dstSubresource )
-          && ( memcmp( dstOffsets, rhs.dstOffsets, 2 * sizeof( VULKAN_HPP_NAMESPACE::Offset3D ) ) == 0 );
+          && ( dstOffsets == rhs.dstOffsets );
     }
 
     bool operator!=( ImageBlit const& rhs ) const VULKAN_HPP_NOEXCEPT
@@ -39084,9 +40099,9 @@
 
   public:
     VULKAN_HPP_NAMESPACE::ImageSubresourceLayers srcSubresource = {};
-    VULKAN_HPP_NAMESPACE::Offset3D srcOffsets[2] = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<VULKAN_HPP_NAMESPACE::Offset3D, 2> srcOffsets = {};
     VULKAN_HPP_NAMESPACE::ImageSubresourceLayers dstSubresource = {};
-    VULKAN_HPP_NAMESPACE::Offset3D dstOffsets[2] = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<VULKAN_HPP_NAMESPACE::Offset3D, 2> dstOffsets = {};
   };
   static_assert( sizeof( ImageBlit ) == sizeof( VkImageBlit ), "struct and wrapper have different size!" );
   static_assert( std::is_standard_layout<ImageBlit>::value, "struct wrapper is not a standard layout!" );
@@ -39105,20 +40120,6 @@
       , extent( extent_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ImageCopy( ImageCopy const& rhs ) VULKAN_HPP_NOEXCEPT
-      : srcSubresource( rhs.srcSubresource )
-      , srcOffset( rhs.srcOffset )
-      , dstSubresource( rhs.dstSubresource )
-      , dstOffset( rhs.dstOffset )
-      , extent( rhs.extent )
-    {}
-
-    ImageCopy & operator=( ImageCopy const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( ImageCopy ) );
-      return *this;
-    }
-
     ImageCopy( VkImageCopy const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -39228,23 +40229,6 @@
       , initialLayout( initialLayout_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ImageCreateInfo( ImageCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , imageType( rhs.imageType )
-      , format( rhs.format )
-      , extent( rhs.extent )
-      , mipLevels( rhs.mipLevels )
-      , arrayLayers( rhs.arrayLayers )
-      , samples( rhs.samples )
-      , tiling( rhs.tiling )
-      , usage( rhs.usage )
-      , sharingMode( rhs.sharingMode )
-      , queueFamilyIndexCount( rhs.queueFamilyIndexCount )
-      , pQueueFamilyIndices( rhs.pQueueFamilyIndices )
-      , initialLayout( rhs.initialLayout )
-    {}
-
     ImageCreateInfo & operator=( ImageCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ImageCreateInfo ) - offsetof( ImageCreateInfo, pNext ) );
@@ -39418,20 +40402,6 @@
       , depthPitch( depthPitch_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SubresourceLayout( SubresourceLayout const& rhs ) VULKAN_HPP_NOEXCEPT
-      : offset( rhs.offset )
-      , size( rhs.size )
-      , rowPitch( rhs.rowPitch )
-      , arrayPitch( rhs.arrayPitch )
-      , depthPitch( rhs.depthPitch )
-    {}
-
-    SubresourceLayout & operator=( SubresourceLayout const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( SubresourceLayout ) );
-      return *this;
-    }
-
     SubresourceLayout( VkSubresourceLayout const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -39491,13 +40461,6 @@
       , pPlaneLayouts( pPlaneLayouts_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ImageDrmFormatModifierExplicitCreateInfoEXT( ImageDrmFormatModifierExplicitCreateInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , drmFormatModifier( rhs.drmFormatModifier )
-      , drmFormatModifierPlaneCount( rhs.drmFormatModifierPlaneCount )
-      , pPlaneLayouts( rhs.pPlaneLayouts )
-    {}
-
     ImageDrmFormatModifierExplicitCreateInfoEXT & operator=( ImageDrmFormatModifierExplicitCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ImageDrmFormatModifierExplicitCreateInfoEXT ) - offsetof( ImageDrmFormatModifierExplicitCreateInfoEXT, pNext ) );
@@ -39585,12 +40548,6 @@
       , pDrmFormatModifiers( pDrmFormatModifiers_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ImageDrmFormatModifierListCreateInfoEXT( ImageDrmFormatModifierListCreateInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , drmFormatModifierCount( rhs.drmFormatModifierCount )
-      , pDrmFormatModifiers( rhs.pDrmFormatModifiers )
-    {}
-
     ImageDrmFormatModifierListCreateInfoEXT & operator=( ImageDrmFormatModifierListCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ImageDrmFormatModifierListCreateInfoEXT ) - offsetof( ImageDrmFormatModifierListCreateInfoEXT, pNext ) );
@@ -39668,11 +40625,6 @@
       : drmFormatModifier( drmFormatModifier_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ImageDrmFormatModifierPropertiesEXT( ImageDrmFormatModifierPropertiesEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , drmFormatModifier( rhs.drmFormatModifier )
-    {}
-
     ImageDrmFormatModifierPropertiesEXT & operator=( ImageDrmFormatModifierPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ImageDrmFormatModifierPropertiesEXT ) - offsetof( ImageDrmFormatModifierPropertiesEXT, pNext ) );
@@ -39732,12 +40684,6 @@
       , pViewFormats( pViewFormats_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ImageFormatListCreateInfo( ImageFormatListCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , viewFormatCount( rhs.viewFormatCount )
-      , pViewFormats( rhs.pViewFormats )
-    {}
-
     ImageFormatListCreateInfo & operator=( ImageFormatListCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ImageFormatListCreateInfo ) - offsetof( ImageFormatListCreateInfo, pNext ) );
@@ -39815,11 +40761,6 @@
       : imageFormatProperties( imageFormatProperties_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ImageFormatProperties2( ImageFormatProperties2 const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , imageFormatProperties( rhs.imageFormatProperties )
-    {}
-
     ImageFormatProperties2 & operator=( ImageFormatProperties2 const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ImageFormatProperties2 ) - offsetof( ImageFormatProperties2, pNext ) );
@@ -39885,20 +40826,6 @@
       , layerCount( layerCount_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ImageSubresourceRange( ImageSubresourceRange const& rhs ) VULKAN_HPP_NOEXCEPT
-      : aspectMask( rhs.aspectMask )
-      , baseMipLevel( rhs.baseMipLevel )
-      , levelCount( rhs.levelCount )
-      , baseArrayLayer( rhs.baseArrayLayer )
-      , layerCount( rhs.layerCount )
-    {}
-
-    ImageSubresourceRange & operator=( ImageSubresourceRange const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( ImageSubresourceRange ) );
-      return *this;
-    }
-
     ImageSubresourceRange( VkImageSubresourceRange const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -39998,18 +40925,6 @@
       , subresourceRange( subresourceRange_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ImageMemoryBarrier( ImageMemoryBarrier const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , srcAccessMask( rhs.srcAccessMask )
-      , dstAccessMask( rhs.dstAccessMask )
-      , oldLayout( rhs.oldLayout )
-      , newLayout( rhs.newLayout )
-      , srcQueueFamilyIndex( rhs.srcQueueFamilyIndex )
-      , dstQueueFamilyIndex( rhs.dstQueueFamilyIndex )
-      , image( rhs.image )
-      , subresourceRange( rhs.subresourceRange )
-    {}
-
     ImageMemoryBarrier & operator=( ImageMemoryBarrier const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ImageMemoryBarrier ) - offsetof( ImageMemoryBarrier, pNext ) );
@@ -40135,11 +41050,6 @@
       : image( image_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ImageMemoryRequirementsInfo2( ImageMemoryRequirementsInfo2 const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , image( rhs.image )
-    {}
-
     ImageMemoryRequirementsInfo2 & operator=( ImageMemoryRequirementsInfo2 const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ImageMemoryRequirementsInfo2 ) - offsetof( ImageMemoryRequirementsInfo2, pNext ) );
@@ -40212,12 +41122,6 @@
       , imagePipeHandle( imagePipeHandle_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ImagePipeSurfaceCreateInfoFUCHSIA( ImagePipeSurfaceCreateInfoFUCHSIA const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , imagePipeHandle( rhs.imagePipeHandle )
-    {}
-
     ImagePipeSurfaceCreateInfoFUCHSIA & operator=( ImagePipeSurfaceCreateInfoFUCHSIA const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ImagePipeSurfaceCreateInfoFUCHSIA ) - offsetof( ImagePipeSurfaceCreateInfoFUCHSIA, pNext ) );
@@ -40296,11 +41200,6 @@
       : planeAspect( planeAspect_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ImagePlaneMemoryRequirementsInfo( ImagePlaneMemoryRequirementsInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , planeAspect( rhs.planeAspect )
-    {}
-
     ImagePlaneMemoryRequirementsInfo & operator=( ImagePlaneMemoryRequirementsInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ImagePlaneMemoryRequirementsInfo ) - offsetof( ImagePlaneMemoryRequirementsInfo, pNext ) );
@@ -40378,20 +41277,6 @@
       , extent( extent_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ImageResolve( ImageResolve const& rhs ) VULKAN_HPP_NOEXCEPT
-      : srcSubresource( rhs.srcSubresource )
-      , srcOffset( rhs.srcOffset )
-      , dstSubresource( rhs.dstSubresource )
-      , dstOffset( rhs.dstOffset )
-      , extent( rhs.extent )
-    {}
-
-    ImageResolve & operator=( ImageResolve const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( ImageResolve ) );
-      return *this;
-    }
-
     ImageResolve( VkImageResolve const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -40477,11 +41362,6 @@
       : image( image_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ImageSparseMemoryRequirementsInfo2( ImageSparseMemoryRequirementsInfo2 const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , image( rhs.image )
-    {}
-
     ImageSparseMemoryRequirementsInfo2 & operator=( ImageSparseMemoryRequirementsInfo2 const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ImageSparseMemoryRequirementsInfo2 ) - offsetof( ImageSparseMemoryRequirementsInfo2, pNext ) );
@@ -40551,11 +41431,6 @@
       : stencilUsage( stencilUsage_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ImageStencilUsageCreateInfo( ImageStencilUsageCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , stencilUsage( rhs.stencilUsage )
-    {}
-
     ImageStencilUsageCreateInfo & operator=( ImageStencilUsageCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ImageStencilUsageCreateInfo ) - offsetof( ImageStencilUsageCreateInfo, pNext ) );
@@ -40625,11 +41500,6 @@
       : swapchain( swapchain_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ImageSwapchainCreateInfoKHR( ImageSwapchainCreateInfoKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , swapchain( rhs.swapchain )
-    {}
-
     ImageSwapchainCreateInfoKHR & operator=( ImageSwapchainCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ImageSwapchainCreateInfoKHR ) - offsetof( ImageSwapchainCreateInfoKHR, pNext ) );
@@ -40699,11 +41569,6 @@
       : decodeMode( decodeMode_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ImageViewASTCDecodeModeEXT( ImageViewASTCDecodeModeEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , decodeMode( rhs.decodeMode )
-    {}
-
     ImageViewASTCDecodeModeEXT & operator=( ImageViewASTCDecodeModeEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ImageViewASTCDecodeModeEXT ) - offsetof( ImageViewASTCDecodeModeEXT, pNext ) );
@@ -40767,6 +41632,67 @@
   static_assert( sizeof( ImageViewASTCDecodeModeEXT ) == sizeof( VkImageViewASTCDecodeModeEXT ), "struct and wrapper have different size!" );
   static_assert( std::is_standard_layout<ImageViewASTCDecodeModeEXT>::value, "struct wrapper is not a standard layout!" );
 
+  struct ImageViewAddressPropertiesNVX
+  {
+    VULKAN_HPP_CONSTEXPR ImageViewAddressPropertiesNVX( VULKAN_HPP_NAMESPACE::DeviceAddress deviceAddress_ = {},
+                                                        VULKAN_HPP_NAMESPACE::DeviceSize size_ = {} ) VULKAN_HPP_NOEXCEPT
+      : deviceAddress( deviceAddress_ )
+      , size( size_ )
+    {}
+
+    ImageViewAddressPropertiesNVX & operator=( ImageViewAddressPropertiesNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      memcpy( &pNext, &rhs.pNext, sizeof( ImageViewAddressPropertiesNVX ) - offsetof( ImageViewAddressPropertiesNVX, pNext ) );
+      return *this;
+    }
+
+    ImageViewAddressPropertiesNVX( VkImageViewAddressPropertiesNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    ImageViewAddressPropertiesNVX& operator=( VkImageViewAddressPropertiesNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ImageViewAddressPropertiesNVX const *>(&rhs);
+      return *this;
+    }
+
+    operator VkImageViewAddressPropertiesNVX const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkImageViewAddressPropertiesNVX*>( this );
+    }
+
+    operator VkImageViewAddressPropertiesNVX &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkImageViewAddressPropertiesNVX*>( this );
+    }
+
+#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
+    auto operator<=>( ImageViewAddressPropertiesNVX const& ) const = default;
+#else
+    bool operator==( ImageViewAddressPropertiesNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ( sType == rhs.sType )
+          && ( pNext == rhs.pNext )
+          && ( deviceAddress == rhs.deviceAddress )
+          && ( size == rhs.size );
+    }
+
+    bool operator!=( ImageViewAddressPropertiesNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return !operator==( rhs );
+    }
+#endif
+
+  public:
+    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eImageViewAddressPropertiesNVX;
+    void* pNext = {};
+    VULKAN_HPP_NAMESPACE::DeviceAddress deviceAddress = {};
+    VULKAN_HPP_NAMESPACE::DeviceSize size = {};
+  };
+  static_assert( sizeof( ImageViewAddressPropertiesNVX ) == sizeof( VkImageViewAddressPropertiesNVX ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<ImageViewAddressPropertiesNVX>::value, "struct wrapper is not a standard layout!" );
+
   struct ImageViewCreateInfo
   {
     VULKAN_HPP_CONSTEXPR ImageViewCreateInfo( VULKAN_HPP_NAMESPACE::ImageViewCreateFlags flags_ = {},
@@ -40783,16 +41709,6 @@
       , subresourceRange( subresourceRange_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ImageViewCreateInfo( ImageViewCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , image( rhs.image )
-      , viewType( rhs.viewType )
-      , format( rhs.format )
-      , components( rhs.components )
-      , subresourceRange( rhs.subresourceRange )
-    {}
-
     ImageViewCreateInfo & operator=( ImageViewCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ImageViewCreateInfo ) - offsetof( ImageViewCreateInfo, pNext ) );
@@ -40906,13 +41822,6 @@
       , sampler( sampler_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ImageViewHandleInfoNVX( ImageViewHandleInfoNVX const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , imageView( rhs.imageView )
-      , descriptorType( rhs.descriptorType )
-      , sampler( rhs.sampler )
-    {}
-
     ImageViewHandleInfoNVX & operator=( ImageViewHandleInfoNVX const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ImageViewHandleInfoNVX ) - offsetof( ImageViewHandleInfoNVX, pNext ) );
@@ -40998,11 +41907,6 @@
       : usage( usage_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ImageViewUsageCreateInfo( ImageViewUsageCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , usage( rhs.usage )
-    {}
-
     ImageViewUsageCreateInfo & operator=( ImageViewUsageCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ImageViewUsageCreateInfo ) - offsetof( ImageViewUsageCreateInfo, pNext ) );
@@ -41073,11 +41977,6 @@
       : buffer( buffer_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ImportAndroidHardwareBufferInfoANDROID( ImportAndroidHardwareBufferInfoANDROID const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , buffer( rhs.buffer )
-    {}
-
     ImportAndroidHardwareBufferInfoANDROID & operator=( ImportAndroidHardwareBufferInfoANDROID const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ImportAndroidHardwareBufferInfoANDROID ) - offsetof( ImportAndroidHardwareBufferInfoANDROID, pNext ) );
@@ -41154,14 +42053,6 @@
       , fd( fd_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ImportFenceFdInfoKHR( ImportFenceFdInfoKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , fence( rhs.fence )
-      , flags( rhs.flags )
-      , handleType( rhs.handleType )
-      , fd( rhs.fd )
-    {}
-
     ImportFenceFdInfoKHR & operator=( ImportFenceFdInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ImportFenceFdInfoKHR ) - offsetof( ImportFenceFdInfoKHR, pNext ) );
@@ -41264,15 +42155,6 @@
       , name( name_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ImportFenceWin32HandleInfoKHR( ImportFenceWin32HandleInfoKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , fence( rhs.fence )
-      , flags( rhs.flags )
-      , handleType( rhs.handleType )
-      , handle( rhs.handle )
-      , name( rhs.name )
-    {}
-
     ImportFenceWin32HandleInfoKHR & operator=( ImportFenceWin32HandleInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ImportFenceWin32HandleInfoKHR ) - offsetof( ImportFenceWin32HandleInfoKHR, pNext ) );
@@ -41377,12 +42259,6 @@
       , fd( fd_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ImportMemoryFdInfoKHR( ImportMemoryFdInfoKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , handleType( rhs.handleType )
-      , fd( rhs.fd )
-    {}
-
     ImportMemoryFdInfoKHR & operator=( ImportMemoryFdInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ImportMemoryFdInfoKHR ) - offsetof( ImportMemoryFdInfoKHR, pNext ) );
@@ -41462,12 +42338,6 @@
       , pHostPointer( pHostPointer_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ImportMemoryHostPointerInfoEXT( ImportMemoryHostPointerInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , handleType( rhs.handleType )
-      , pHostPointer( rhs.pHostPointer )
-    {}
-
     ImportMemoryHostPointerInfoEXT & operator=( ImportMemoryHostPointerInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ImportMemoryHostPointerInfoEXT ) - offsetof( ImportMemoryHostPointerInfoEXT, pNext ) );
@@ -41550,13 +42420,6 @@
       , name( name_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ImportMemoryWin32HandleInfoKHR( ImportMemoryWin32HandleInfoKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , handleType( rhs.handleType )
-      , handle( rhs.handle )
-      , name( rhs.name )
-    {}
-
     ImportMemoryWin32HandleInfoKHR & operator=( ImportMemoryWin32HandleInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ImportMemoryWin32HandleInfoKHR ) - offsetof( ImportMemoryWin32HandleInfoKHR, pNext ) );
@@ -41646,12 +42509,6 @@
       , handle( handle_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ImportMemoryWin32HandleInfoNV( ImportMemoryWin32HandleInfoNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , handleType( rhs.handleType )
-      , handle( rhs.handle )
-    {}
-
     ImportMemoryWin32HandleInfoNV & operator=( ImportMemoryWin32HandleInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ImportMemoryWin32HandleInfoNV ) - offsetof( ImportMemoryWin32HandleInfoNV, pNext ) );
@@ -41736,14 +42593,6 @@
       , fd( fd_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ImportSemaphoreFdInfoKHR( ImportSemaphoreFdInfoKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , semaphore( rhs.semaphore )
-      , flags( rhs.flags )
-      , handleType( rhs.handleType )
-      , fd( rhs.fd )
-    {}
-
     ImportSemaphoreFdInfoKHR & operator=( ImportSemaphoreFdInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ImportSemaphoreFdInfoKHR ) - offsetof( ImportSemaphoreFdInfoKHR, pNext ) );
@@ -41846,15 +42695,6 @@
       , name( name_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ImportSemaphoreWin32HandleInfoKHR( ImportSemaphoreWin32HandleInfoKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , semaphore( rhs.semaphore )
-      , flags( rhs.flags )
-      , handleType( rhs.handleType )
-      , handle( rhs.handle )
-      , name( rhs.name )
-    {}
-
     ImportSemaphoreWin32HandleInfoKHR & operator=( ImportSemaphoreWin32HandleInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ImportSemaphoreWin32HandleInfoKHR ) - offsetof( ImportSemaphoreWin32HandleInfoKHR, pNext ) );
@@ -41951,208 +42791,313 @@
   static_assert( std::is_standard_layout<ImportSemaphoreWin32HandleInfoKHR>::value, "struct wrapper is not a standard layout!" );
 #endif /*VK_USE_PLATFORM_WIN32_KHR*/
 
-  struct IndirectCommandsLayoutTokenNVX
+  struct IndirectCommandsLayoutTokenNV
   {
-    VULKAN_HPP_CONSTEXPR IndirectCommandsLayoutTokenNVX( VULKAN_HPP_NAMESPACE::IndirectCommandsTokenTypeNVX tokenType_ = VULKAN_HPP_NAMESPACE::IndirectCommandsTokenTypeNVX::ePipeline,
-                                                         uint32_t bindingUnit_ = {},
-                                                         uint32_t dynamicCount_ = {},
-                                                         uint32_t divisor_ = {} ) VULKAN_HPP_NOEXCEPT
+    VULKAN_HPP_CONSTEXPR IndirectCommandsLayoutTokenNV( VULKAN_HPP_NAMESPACE::IndirectCommandsTokenTypeNV tokenType_ = VULKAN_HPP_NAMESPACE::IndirectCommandsTokenTypeNV::eShaderGroup,
+                                                        uint32_t stream_ = {},
+                                                        uint32_t offset_ = {},
+                                                        uint32_t vertexBindingUnit_ = {},
+                                                        VULKAN_HPP_NAMESPACE::Bool32 vertexDynamicStride_ = {},
+                                                        VULKAN_HPP_NAMESPACE::PipelineLayout pushconstantPipelineLayout_ = {},
+                                                        VULKAN_HPP_NAMESPACE::ShaderStageFlags pushconstantShaderStageFlags_ = {},
+                                                        uint32_t pushconstantOffset_ = {},
+                                                        uint32_t pushconstantSize_ = {},
+                                                        VULKAN_HPP_NAMESPACE::IndirectStateFlagsNV indirectStateFlags_ = {},
+                                                        uint32_t indexTypeCount_ = {},
+                                                        const VULKAN_HPP_NAMESPACE::IndexType* pIndexTypes_ = {},
+                                                        const uint32_t* pIndexTypeValues_ = {} ) VULKAN_HPP_NOEXCEPT
       : tokenType( tokenType_ )
-      , bindingUnit( bindingUnit_ )
-      , dynamicCount( dynamicCount_ )
-      , divisor( divisor_ )
+      , stream( stream_ )
+      , offset( offset_ )
+      , vertexBindingUnit( vertexBindingUnit_ )
+      , vertexDynamicStride( vertexDynamicStride_ )
+      , pushconstantPipelineLayout( pushconstantPipelineLayout_ )
+      , pushconstantShaderStageFlags( pushconstantShaderStageFlags_ )
+      , pushconstantOffset( pushconstantOffset_ )
+      , pushconstantSize( pushconstantSize_ )
+      , indirectStateFlags( indirectStateFlags_ )
+      , indexTypeCount( indexTypeCount_ )
+      , pIndexTypes( pIndexTypes_ )
+      , pIndexTypeValues( pIndexTypeValues_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR IndirectCommandsLayoutTokenNVX( IndirectCommandsLayoutTokenNVX const& rhs ) VULKAN_HPP_NOEXCEPT
-      : tokenType( rhs.tokenType )
-      , bindingUnit( rhs.bindingUnit )
-      , dynamicCount( rhs.dynamicCount )
-      , divisor( rhs.divisor )
-    {}
-
-    IndirectCommandsLayoutTokenNVX & operator=( IndirectCommandsLayoutTokenNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+    IndirectCommandsLayoutTokenNV & operator=( IndirectCommandsLayoutTokenNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( IndirectCommandsLayoutTokenNVX ) );
+      memcpy( &pNext, &rhs.pNext, sizeof( IndirectCommandsLayoutTokenNV ) - offsetof( IndirectCommandsLayoutTokenNV, pNext ) );
       return *this;
     }
 
-    IndirectCommandsLayoutTokenNVX( VkIndirectCommandsLayoutTokenNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+    IndirectCommandsLayoutTokenNV( VkIndirectCommandsLayoutTokenNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
     }
 
-    IndirectCommandsLayoutTokenNVX& operator=( VkIndirectCommandsLayoutTokenNVX const & rhs ) VULKAN_HPP_NOEXCEPT
+    IndirectCommandsLayoutTokenNV& operator=( VkIndirectCommandsLayoutTokenNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
-      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutTokenNVX const *>(&rhs);
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutTokenNV const *>(&rhs);
       return *this;
     }
 
-    IndirectCommandsLayoutTokenNVX & setTokenType( VULKAN_HPP_NAMESPACE::IndirectCommandsTokenTypeNVX tokenType_ ) VULKAN_HPP_NOEXCEPT
-    {
-      tokenType = tokenType_;
-      return *this;
-    }
-
-    IndirectCommandsLayoutTokenNVX & setBindingUnit( uint32_t bindingUnit_ ) VULKAN_HPP_NOEXCEPT
-    {
-      bindingUnit = bindingUnit_;
-      return *this;
-    }
-
-    IndirectCommandsLayoutTokenNVX & setDynamicCount( uint32_t dynamicCount_ ) VULKAN_HPP_NOEXCEPT
-    {
-      dynamicCount = dynamicCount_;
-      return *this;
-    }
-
-    IndirectCommandsLayoutTokenNVX & setDivisor( uint32_t divisor_ ) VULKAN_HPP_NOEXCEPT
-    {
-      divisor = divisor_;
-      return *this;
-    }
-
-    operator VkIndirectCommandsLayoutTokenNVX const&() const VULKAN_HPP_NOEXCEPT
-    {
-      return *reinterpret_cast<const VkIndirectCommandsLayoutTokenNVX*>( this );
-    }
-
-    operator VkIndirectCommandsLayoutTokenNVX &() VULKAN_HPP_NOEXCEPT
-    {
-      return *reinterpret_cast<VkIndirectCommandsLayoutTokenNVX*>( this );
-    }
-
-#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
-    auto operator<=>( IndirectCommandsLayoutTokenNVX const& ) const = default;
-#else
-    bool operator==( IndirectCommandsLayoutTokenNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
-    {
-      return ( tokenType == rhs.tokenType )
-          && ( bindingUnit == rhs.bindingUnit )
-          && ( dynamicCount == rhs.dynamicCount )
-          && ( divisor == rhs.divisor );
-    }
-
-    bool operator!=( IndirectCommandsLayoutTokenNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
-    {
-      return !operator==( rhs );
-    }
-#endif
-
-  public:
-    VULKAN_HPP_NAMESPACE::IndirectCommandsTokenTypeNVX tokenType = VULKAN_HPP_NAMESPACE::IndirectCommandsTokenTypeNVX::ePipeline;
-    uint32_t bindingUnit = {};
-    uint32_t dynamicCount = {};
-    uint32_t divisor = {};
-  };
-  static_assert( sizeof( IndirectCommandsLayoutTokenNVX ) == sizeof( VkIndirectCommandsLayoutTokenNVX ), "struct and wrapper have different size!" );
-  static_assert( std::is_standard_layout<IndirectCommandsLayoutTokenNVX>::value, "struct wrapper is not a standard layout!" );
-
-  struct IndirectCommandsLayoutCreateInfoNVX
-  {
-    VULKAN_HPP_CONSTEXPR IndirectCommandsLayoutCreateInfoNVX( VULKAN_HPP_NAMESPACE::PipelineBindPoint pipelineBindPoint_ = VULKAN_HPP_NAMESPACE::PipelineBindPoint::eGraphics,
-                                                              VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutUsageFlagsNVX flags_ = {},
-                                                              uint32_t tokenCount_ = {},
-                                                              const VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutTokenNVX* pTokens_ = {} ) VULKAN_HPP_NOEXCEPT
-      : pipelineBindPoint( pipelineBindPoint_ )
-      , flags( flags_ )
-      , tokenCount( tokenCount_ )
-      , pTokens( pTokens_ )
-    {}
-
-    VULKAN_HPP_CONSTEXPR IndirectCommandsLayoutCreateInfoNVX( IndirectCommandsLayoutCreateInfoNVX const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , pipelineBindPoint( rhs.pipelineBindPoint )
-      , flags( rhs.flags )
-      , tokenCount( rhs.tokenCount )
-      , pTokens( rhs.pTokens )
-    {}
-
-    IndirectCommandsLayoutCreateInfoNVX & operator=( IndirectCommandsLayoutCreateInfoNVX const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( &pNext, &rhs.pNext, sizeof( IndirectCommandsLayoutCreateInfoNVX ) - offsetof( IndirectCommandsLayoutCreateInfoNVX, pNext ) );
-      return *this;
-    }
-
-    IndirectCommandsLayoutCreateInfoNVX( VkIndirectCommandsLayoutCreateInfoNVX const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      *this = rhs;
-    }
-
-    IndirectCommandsLayoutCreateInfoNVX& operator=( VkIndirectCommandsLayoutCreateInfoNVX const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutCreateInfoNVX const *>(&rhs);
-      return *this;
-    }
-
-    IndirectCommandsLayoutCreateInfoNVX & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+    IndirectCommandsLayoutTokenNV & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
     {
       pNext = pNext_;
       return *this;
     }
 
-    IndirectCommandsLayoutCreateInfoNVX & setPipelineBindPoint( VULKAN_HPP_NAMESPACE::PipelineBindPoint pipelineBindPoint_ ) VULKAN_HPP_NOEXCEPT
+    IndirectCommandsLayoutTokenNV & setTokenType( VULKAN_HPP_NAMESPACE::IndirectCommandsTokenTypeNV tokenType_ ) VULKAN_HPP_NOEXCEPT
     {
-      pipelineBindPoint = pipelineBindPoint_;
+      tokenType = tokenType_;
       return *this;
     }
 
-    IndirectCommandsLayoutCreateInfoNVX & setFlags( VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutUsageFlagsNVX flags_ ) VULKAN_HPP_NOEXCEPT
+    IndirectCommandsLayoutTokenNV & setStream( uint32_t stream_ ) VULKAN_HPP_NOEXCEPT
     {
-      flags = flags_;
+      stream = stream_;
       return *this;
     }
 
-    IndirectCommandsLayoutCreateInfoNVX & setTokenCount( uint32_t tokenCount_ ) VULKAN_HPP_NOEXCEPT
+    IndirectCommandsLayoutTokenNV & setOffset( uint32_t offset_ ) VULKAN_HPP_NOEXCEPT
     {
-      tokenCount = tokenCount_;
+      offset = offset_;
       return *this;
     }
 
-    IndirectCommandsLayoutCreateInfoNVX & setPTokens( const VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutTokenNVX* pTokens_ ) VULKAN_HPP_NOEXCEPT
+    IndirectCommandsLayoutTokenNV & setVertexBindingUnit( uint32_t vertexBindingUnit_ ) VULKAN_HPP_NOEXCEPT
     {
-      pTokens = pTokens_;
+      vertexBindingUnit = vertexBindingUnit_;
       return *this;
     }
 
-    operator VkIndirectCommandsLayoutCreateInfoNVX const&() const VULKAN_HPP_NOEXCEPT
+    IndirectCommandsLayoutTokenNV & setVertexDynamicStride( VULKAN_HPP_NAMESPACE::Bool32 vertexDynamicStride_ ) VULKAN_HPP_NOEXCEPT
     {
-      return *reinterpret_cast<const VkIndirectCommandsLayoutCreateInfoNVX*>( this );
+      vertexDynamicStride = vertexDynamicStride_;
+      return *this;
     }
 
-    operator VkIndirectCommandsLayoutCreateInfoNVX &() VULKAN_HPP_NOEXCEPT
+    IndirectCommandsLayoutTokenNV & setPushconstantPipelineLayout( VULKAN_HPP_NAMESPACE::PipelineLayout pushconstantPipelineLayout_ ) VULKAN_HPP_NOEXCEPT
     {
-      return *reinterpret_cast<VkIndirectCommandsLayoutCreateInfoNVX*>( this );
+      pushconstantPipelineLayout = pushconstantPipelineLayout_;
+      return *this;
+    }
+
+    IndirectCommandsLayoutTokenNV & setPushconstantShaderStageFlags( VULKAN_HPP_NAMESPACE::ShaderStageFlags pushconstantShaderStageFlags_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pushconstantShaderStageFlags = pushconstantShaderStageFlags_;
+      return *this;
+    }
+
+    IndirectCommandsLayoutTokenNV & setPushconstantOffset( uint32_t pushconstantOffset_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pushconstantOffset = pushconstantOffset_;
+      return *this;
+    }
+
+    IndirectCommandsLayoutTokenNV & setPushconstantSize( uint32_t pushconstantSize_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pushconstantSize = pushconstantSize_;
+      return *this;
+    }
+
+    IndirectCommandsLayoutTokenNV & setIndirectStateFlags( VULKAN_HPP_NAMESPACE::IndirectStateFlagsNV indirectStateFlags_ ) VULKAN_HPP_NOEXCEPT
+    {
+      indirectStateFlags = indirectStateFlags_;
+      return *this;
+    }
+
+    IndirectCommandsLayoutTokenNV & setIndexTypeCount( uint32_t indexTypeCount_ ) VULKAN_HPP_NOEXCEPT
+    {
+      indexTypeCount = indexTypeCount_;
+      return *this;
+    }
+
+    IndirectCommandsLayoutTokenNV & setPIndexTypes( const VULKAN_HPP_NAMESPACE::IndexType* pIndexTypes_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pIndexTypes = pIndexTypes_;
+      return *this;
+    }
+
+    IndirectCommandsLayoutTokenNV & setPIndexTypeValues( const uint32_t* pIndexTypeValues_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pIndexTypeValues = pIndexTypeValues_;
+      return *this;
+    }
+
+    operator VkIndirectCommandsLayoutTokenNV const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkIndirectCommandsLayoutTokenNV*>( this );
+    }
+
+    operator VkIndirectCommandsLayoutTokenNV &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkIndirectCommandsLayoutTokenNV*>( this );
     }
 
 #if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
-    auto operator<=>( IndirectCommandsLayoutCreateInfoNVX const& ) const = default;
+    auto operator<=>( IndirectCommandsLayoutTokenNV const& ) const = default;
 #else
-    bool operator==( IndirectCommandsLayoutCreateInfoNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
+    bool operator==( IndirectCommandsLayoutTokenNV const& rhs ) const VULKAN_HPP_NOEXCEPT
     {
       return ( sType == rhs.sType )
           && ( pNext == rhs.pNext )
-          && ( pipelineBindPoint == rhs.pipelineBindPoint )
-          && ( flags == rhs.flags )
-          && ( tokenCount == rhs.tokenCount )
-          && ( pTokens == rhs.pTokens );
+          && ( tokenType == rhs.tokenType )
+          && ( stream == rhs.stream )
+          && ( offset == rhs.offset )
+          && ( vertexBindingUnit == rhs.vertexBindingUnit )
+          && ( vertexDynamicStride == rhs.vertexDynamicStride )
+          && ( pushconstantPipelineLayout == rhs.pushconstantPipelineLayout )
+          && ( pushconstantShaderStageFlags == rhs.pushconstantShaderStageFlags )
+          && ( pushconstantOffset == rhs.pushconstantOffset )
+          && ( pushconstantSize == rhs.pushconstantSize )
+          && ( indirectStateFlags == rhs.indirectStateFlags )
+          && ( indexTypeCount == rhs.indexTypeCount )
+          && ( pIndexTypes == rhs.pIndexTypes )
+          && ( pIndexTypeValues == rhs.pIndexTypeValues );
     }
 
-    bool operator!=( IndirectCommandsLayoutCreateInfoNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
+    bool operator!=( IndirectCommandsLayoutTokenNV const& rhs ) const VULKAN_HPP_NOEXCEPT
     {
       return !operator==( rhs );
     }
 #endif
 
   public:
-    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eIndirectCommandsLayoutCreateInfoNVX;
+    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eIndirectCommandsLayoutTokenNV;
     const void* pNext = {};
-    VULKAN_HPP_NAMESPACE::PipelineBindPoint pipelineBindPoint = VULKAN_HPP_NAMESPACE::PipelineBindPoint::eGraphics;
-    VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutUsageFlagsNVX flags = {};
-    uint32_t tokenCount = {};
-    const VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutTokenNVX* pTokens = {};
+    VULKAN_HPP_NAMESPACE::IndirectCommandsTokenTypeNV tokenType = VULKAN_HPP_NAMESPACE::IndirectCommandsTokenTypeNV::eShaderGroup;
+    uint32_t stream = {};
+    uint32_t offset = {};
+    uint32_t vertexBindingUnit = {};
+    VULKAN_HPP_NAMESPACE::Bool32 vertexDynamicStride = {};
+    VULKAN_HPP_NAMESPACE::PipelineLayout pushconstantPipelineLayout = {};
+    VULKAN_HPP_NAMESPACE::ShaderStageFlags pushconstantShaderStageFlags = {};
+    uint32_t pushconstantOffset = {};
+    uint32_t pushconstantSize = {};
+    VULKAN_HPP_NAMESPACE::IndirectStateFlagsNV indirectStateFlags = {};
+    uint32_t indexTypeCount = {};
+    const VULKAN_HPP_NAMESPACE::IndexType* pIndexTypes = {};
+    const uint32_t* pIndexTypeValues = {};
   };
-  static_assert( sizeof( IndirectCommandsLayoutCreateInfoNVX ) == sizeof( VkIndirectCommandsLayoutCreateInfoNVX ), "struct and wrapper have different size!" );
-  static_assert( std::is_standard_layout<IndirectCommandsLayoutCreateInfoNVX>::value, "struct wrapper is not a standard layout!" );
+  static_assert( sizeof( IndirectCommandsLayoutTokenNV ) == sizeof( VkIndirectCommandsLayoutTokenNV ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<IndirectCommandsLayoutTokenNV>::value, "struct wrapper is not a standard layout!" );
+
+  struct IndirectCommandsLayoutCreateInfoNV
+  {
+    VULKAN_HPP_CONSTEXPR IndirectCommandsLayoutCreateInfoNV( VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutUsageFlagsNV flags_ = {},
+                                                             VULKAN_HPP_NAMESPACE::PipelineBindPoint pipelineBindPoint_ = VULKAN_HPP_NAMESPACE::PipelineBindPoint::eGraphics,
+                                                             uint32_t tokenCount_ = {},
+                                                             const VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutTokenNV* pTokens_ = {},
+                                                             uint32_t streamCount_ = {},
+                                                             const uint32_t* pStreamStrides_ = {} ) VULKAN_HPP_NOEXCEPT
+      : flags( flags_ )
+      , pipelineBindPoint( pipelineBindPoint_ )
+      , tokenCount( tokenCount_ )
+      , pTokens( pTokens_ )
+      , streamCount( streamCount_ )
+      , pStreamStrides( pStreamStrides_ )
+    {}
+
+    IndirectCommandsLayoutCreateInfoNV & operator=( IndirectCommandsLayoutCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      memcpy( &pNext, &rhs.pNext, sizeof( IndirectCommandsLayoutCreateInfoNV ) - offsetof( IndirectCommandsLayoutCreateInfoNV, pNext ) );
+      return *this;
+    }
+
+    IndirectCommandsLayoutCreateInfoNV( VkIndirectCommandsLayoutCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    IndirectCommandsLayoutCreateInfoNV& operator=( VkIndirectCommandsLayoutCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutCreateInfoNV const *>(&rhs);
+      return *this;
+    }
+
+    IndirectCommandsLayoutCreateInfoNV & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pNext = pNext_;
+      return *this;
+    }
+
+    IndirectCommandsLayoutCreateInfoNV & setFlags( VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutUsageFlagsNV flags_ ) VULKAN_HPP_NOEXCEPT
+    {
+      flags = flags_;
+      return *this;
+    }
+
+    IndirectCommandsLayoutCreateInfoNV & setPipelineBindPoint( VULKAN_HPP_NAMESPACE::PipelineBindPoint pipelineBindPoint_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pipelineBindPoint = pipelineBindPoint_;
+      return *this;
+    }
+
+    IndirectCommandsLayoutCreateInfoNV & setTokenCount( uint32_t tokenCount_ ) VULKAN_HPP_NOEXCEPT
+    {
+      tokenCount = tokenCount_;
+      return *this;
+    }
+
+    IndirectCommandsLayoutCreateInfoNV & setPTokens( const VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutTokenNV* pTokens_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pTokens = pTokens_;
+      return *this;
+    }
+
+    IndirectCommandsLayoutCreateInfoNV & setStreamCount( uint32_t streamCount_ ) VULKAN_HPP_NOEXCEPT
+    {
+      streamCount = streamCount_;
+      return *this;
+    }
+
+    IndirectCommandsLayoutCreateInfoNV & setPStreamStrides( const uint32_t* pStreamStrides_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pStreamStrides = pStreamStrides_;
+      return *this;
+    }
+
+    operator VkIndirectCommandsLayoutCreateInfoNV const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkIndirectCommandsLayoutCreateInfoNV*>( this );
+    }
+
+    operator VkIndirectCommandsLayoutCreateInfoNV &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkIndirectCommandsLayoutCreateInfoNV*>( this );
+    }
+
+#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
+    auto operator<=>( IndirectCommandsLayoutCreateInfoNV const& ) const = default;
+#else
+    bool operator==( IndirectCommandsLayoutCreateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ( sType == rhs.sType )
+          && ( pNext == rhs.pNext )
+          && ( flags == rhs.flags )
+          && ( pipelineBindPoint == rhs.pipelineBindPoint )
+          && ( tokenCount == rhs.tokenCount )
+          && ( pTokens == rhs.pTokens )
+          && ( streamCount == rhs.streamCount )
+          && ( pStreamStrides == rhs.pStreamStrides );
+    }
+
+    bool operator!=( IndirectCommandsLayoutCreateInfoNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return !operator==( rhs );
+    }
+#endif
+
+  public:
+    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eIndirectCommandsLayoutCreateInfoNV;
+    const void* pNext = {};
+    VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutUsageFlagsNV flags = {};
+    VULKAN_HPP_NAMESPACE::PipelineBindPoint pipelineBindPoint = VULKAN_HPP_NAMESPACE::PipelineBindPoint::eGraphics;
+    uint32_t tokenCount = {};
+    const VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutTokenNV* pTokens = {};
+    uint32_t streamCount = {};
+    const uint32_t* pStreamStrides = {};
+  };
+  static_assert( sizeof( IndirectCommandsLayoutCreateInfoNV ) == sizeof( VkIndirectCommandsLayoutCreateInfoNV ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<IndirectCommandsLayoutCreateInfoNV>::value, "struct wrapper is not a standard layout!" );
 
   struct InitializePerformanceApiInfoINTEL
   {
@@ -42160,11 +43105,6 @@
       : pUserData( pUserData_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR InitializePerformanceApiInfoINTEL( InitializePerformanceApiInfoINTEL const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , pUserData( rhs.pUserData )
-    {}
-
     InitializePerformanceApiInfoINTEL & operator=( InitializePerformanceApiInfoINTEL const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( InitializePerformanceApiInfoINTEL ) - offsetof( InitializePerformanceApiInfoINTEL, pNext ) );
@@ -42238,18 +43178,6 @@
       , aspectMask( aspectMask_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR InputAttachmentAspectReference( InputAttachmentAspectReference const& rhs ) VULKAN_HPP_NOEXCEPT
-      : subpass( rhs.subpass )
-      , inputAttachmentIndex( rhs.inputAttachmentIndex )
-      , aspectMask( rhs.aspectMask )
-    {}
-
-    InputAttachmentAspectReference & operator=( InputAttachmentAspectReference const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( InputAttachmentAspectReference ) );
-      return *this;
-    }
-
     InputAttachmentAspectReference( VkInputAttachmentAspectReference const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -42329,16 +43257,6 @@
       , ppEnabledExtensionNames( ppEnabledExtensionNames_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR InstanceCreateInfo( InstanceCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , pApplicationInfo( rhs.pApplicationInfo )
-      , enabledLayerCount( rhs.enabledLayerCount )
-      , ppEnabledLayerNames( rhs.ppEnabledLayerNames )
-      , enabledExtensionCount( rhs.enabledExtensionCount )
-      , ppEnabledExtensionNames( rhs.ppEnabledExtensionNames )
-    {}
-
     InstanceCreateInfo & operator=( InstanceCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( InstanceCreateInfo ) - offsetof( InstanceCreateInfo, pNext ) );
@@ -42448,30 +43366,11 @@
                                              uint32_t specVersion_ = {},
                                              uint32_t implementationVersion_ = {},
                                              std::array<char,VK_MAX_DESCRIPTION_SIZE> const& description_ = {} ) VULKAN_HPP_NOEXCEPT
-      : layerName{}
+      : layerName( layerName_ )
       , specVersion( specVersion_ )
       , implementationVersion( implementationVersion_ )
-      , description{}
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_EXTENSION_NAME_SIZE>::copy( layerName, layerName_ );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DESCRIPTION_SIZE>::copy( description, description_ );
-    }
-
-    VULKAN_HPP_CONSTEXPR_14 LayerProperties( LayerProperties const& rhs ) VULKAN_HPP_NOEXCEPT
-      : layerName{}
-      , specVersion( rhs.specVersion )
-      , implementationVersion( rhs.implementationVersion )
-      , description{}
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_EXTENSION_NAME_SIZE>::copy( layerName, rhs.layerName );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DESCRIPTION_SIZE>::copy( description, rhs.description );
-    }
-
-    LayerProperties & operator=( LayerProperties const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( LayerProperties ) );
-      return *this;
-    }
+      , description( description_ )
+    {}
 
     LayerProperties( VkLayerProperties const & rhs ) VULKAN_HPP_NOEXCEPT
     {
@@ -42499,10 +43398,10 @@
 #else
     bool operator==( LayerProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
     {
-      return ( memcmp( layerName, rhs.layerName, VK_MAX_EXTENSION_NAME_SIZE * sizeof( char ) ) == 0 )
+      return ( layerName == rhs.layerName )
           && ( specVersion == rhs.specVersion )
           && ( implementationVersion == rhs.implementationVersion )
-          && ( memcmp( description, rhs.description, VK_MAX_DESCRIPTION_SIZE * sizeof( char ) ) == 0 );
+          && ( description == rhs.description );
     }
 
     bool operator!=( LayerProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
@@ -42512,10 +43411,10 @@
 #endif
 
   public:
-    char layerName[VK_MAX_EXTENSION_NAME_SIZE] = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<char, VK_MAX_EXTENSION_NAME_SIZE> layerName = {};
     uint32_t specVersion = {};
     uint32_t implementationVersion = {};
-    char description[VK_MAX_DESCRIPTION_SIZE] = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<char, VK_MAX_DESCRIPTION_SIZE> description = {};
   };
   static_assert( sizeof( LayerProperties ) == sizeof( VkLayerProperties ), "struct and wrapper have different size!" );
   static_assert( std::is_standard_layout<LayerProperties>::value, "struct wrapper is not a standard layout!" );
@@ -42529,12 +43428,6 @@
       , pView( pView_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR MacOSSurfaceCreateInfoMVK( MacOSSurfaceCreateInfoMVK const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , pView( rhs.pView )
-    {}
-
     MacOSSurfaceCreateInfoMVK & operator=( MacOSSurfaceCreateInfoMVK const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( MacOSSurfaceCreateInfoMVK ) - offsetof( MacOSSurfaceCreateInfoMVK, pNext ) );
@@ -42617,13 +43510,6 @@
       , size( size_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR MappedMemoryRange( MappedMemoryRange const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , memory( rhs.memory )
-      , offset( rhs.offset )
-      , size( rhs.size )
-    {}
-
     MappedMemoryRange & operator=( MappedMemoryRange const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( MappedMemoryRange ) - offsetof( MappedMemoryRange, pNext ) );
@@ -42711,12 +43597,6 @@
       , deviceMask( deviceMask_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR MemoryAllocateFlagsInfo( MemoryAllocateFlagsInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , deviceMask( rhs.deviceMask )
-    {}
-
     MemoryAllocateFlagsInfo & operator=( MemoryAllocateFlagsInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( MemoryAllocateFlagsInfo ) - offsetof( MemoryAllocateFlagsInfo, pNext ) );
@@ -42796,12 +43676,6 @@
       , memoryTypeIndex( memoryTypeIndex_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR MemoryAllocateInfo( MemoryAllocateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , allocationSize( rhs.allocationSize )
-      , memoryTypeIndex( rhs.memoryTypeIndex )
-    {}
-
     MemoryAllocateInfo & operator=( MemoryAllocateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( MemoryAllocateInfo ) - offsetof( MemoryAllocateInfo, pNext ) );
@@ -42881,12 +43755,6 @@
       , dstAccessMask( dstAccessMask_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR MemoryBarrier( MemoryBarrier const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , srcAccessMask( rhs.srcAccessMask )
-      , dstAccessMask( rhs.dstAccessMask )
-    {}
-
     MemoryBarrier & operator=( MemoryBarrier const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( MemoryBarrier ) - offsetof( MemoryBarrier, pNext ) );
@@ -42966,12 +43834,6 @@
       , buffer( buffer_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR MemoryDedicatedAllocateInfo( MemoryDedicatedAllocateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , image( rhs.image )
-      , buffer( rhs.buffer )
-    {}
-
     MemoryDedicatedAllocateInfo & operator=( MemoryDedicatedAllocateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( MemoryDedicatedAllocateInfo ) - offsetof( MemoryDedicatedAllocateInfo, pNext ) );
@@ -43051,12 +43913,6 @@
       , requiresDedicatedAllocation( requiresDedicatedAllocation_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR MemoryDedicatedRequirements( MemoryDedicatedRequirements const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , prefersDedicatedAllocation( rhs.prefersDedicatedAllocation )
-      , requiresDedicatedAllocation( rhs.requiresDedicatedAllocation )
-    {}
-
     MemoryDedicatedRequirements & operator=( MemoryDedicatedRequirements const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( MemoryDedicatedRequirements ) - offsetof( MemoryDedicatedRequirements, pNext ) );
@@ -43116,11 +43972,6 @@
       : memoryTypeBits( memoryTypeBits_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR MemoryFdPropertiesKHR( MemoryFdPropertiesKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , memoryTypeBits( rhs.memoryTypeBits )
-    {}
-
     MemoryFdPropertiesKHR & operator=( MemoryFdPropertiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( MemoryFdPropertiesKHR ) - offsetof( MemoryFdPropertiesKHR, pNext ) );
@@ -43179,11 +44030,6 @@
       : memory( memory_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR MemoryGetAndroidHardwareBufferInfoANDROID( MemoryGetAndroidHardwareBufferInfoANDROID const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , memory( rhs.memory )
-    {}
-
     MemoryGetAndroidHardwareBufferInfoANDROID & operator=( MemoryGetAndroidHardwareBufferInfoANDROID const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( MemoryGetAndroidHardwareBufferInfoANDROID ) - offsetof( MemoryGetAndroidHardwareBufferInfoANDROID, pNext ) );
@@ -43256,12 +44102,6 @@
       , handleType( handleType_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR MemoryGetFdInfoKHR( MemoryGetFdInfoKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , memory( rhs.memory )
-      , handleType( rhs.handleType )
-    {}
-
     MemoryGetFdInfoKHR & operator=( MemoryGetFdInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( MemoryGetFdInfoKHR ) - offsetof( MemoryGetFdInfoKHR, pNext ) );
@@ -43342,12 +44182,6 @@
       , handleType( handleType_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR MemoryGetWin32HandleInfoKHR( MemoryGetWin32HandleInfoKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , memory( rhs.memory )
-      , handleType( rhs.handleType )
-    {}
-
     MemoryGetWin32HandleInfoKHR & operator=( MemoryGetWin32HandleInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( MemoryGetWin32HandleInfoKHR ) - offsetof( MemoryGetWin32HandleInfoKHR, pNext ) );
@@ -43428,17 +44262,6 @@
       , flags( flags_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR MemoryHeap( MemoryHeap const& rhs ) VULKAN_HPP_NOEXCEPT
-      : size( rhs.size )
-      , flags( rhs.flags )
-    {}
-
-    MemoryHeap & operator=( MemoryHeap const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( MemoryHeap ) );
-      return *this;
-    }
-
     MemoryHeap( VkMemoryHeap const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -43488,11 +44311,6 @@
       : memoryTypeBits( memoryTypeBits_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR MemoryHostPointerPropertiesEXT( MemoryHostPointerPropertiesEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , memoryTypeBits( rhs.memoryTypeBits )
-    {}
-
     MemoryHostPointerPropertiesEXT & operator=( MemoryHostPointerPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( MemoryHostPointerPropertiesEXT ) - offsetof( MemoryHostPointerPropertiesEXT, pNext ) );
@@ -43550,11 +44368,6 @@
       : opaqueCaptureAddress( opaqueCaptureAddress_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR MemoryOpaqueCaptureAddressAllocateInfo( MemoryOpaqueCaptureAddressAllocateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , opaqueCaptureAddress( rhs.opaqueCaptureAddress )
-    {}
-
     MemoryOpaqueCaptureAddressAllocateInfo & operator=( MemoryOpaqueCaptureAddressAllocateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( MemoryOpaqueCaptureAddressAllocateInfo ) - offsetof( MemoryOpaqueCaptureAddressAllocateInfo, pNext ) );
@@ -43624,11 +44437,6 @@
       : priority( priority_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR MemoryPriorityAllocateInfoEXT( MemoryPriorityAllocateInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , priority( rhs.priority )
-    {}
-
     MemoryPriorityAllocateInfoEXT & operator=( MemoryPriorityAllocateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( MemoryPriorityAllocateInfoEXT ) - offsetof( MemoryPriorityAllocateInfoEXT, pNext ) );
@@ -43702,18 +44510,6 @@
       , memoryTypeBits( memoryTypeBits_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR MemoryRequirements( MemoryRequirements const& rhs ) VULKAN_HPP_NOEXCEPT
-      : size( rhs.size )
-      , alignment( rhs.alignment )
-      , memoryTypeBits( rhs.memoryTypeBits )
-    {}
-
-    MemoryRequirements & operator=( MemoryRequirements const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( MemoryRequirements ) );
-      return *this;
-    }
-
     MemoryRequirements( VkMemoryRequirements const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -43765,11 +44561,6 @@
       : memoryRequirements( memoryRequirements_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR MemoryRequirements2( MemoryRequirements2 const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , memoryRequirements( rhs.memoryRequirements )
-    {}
-
     MemoryRequirements2 & operator=( MemoryRequirements2 const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( MemoryRequirements2 ) - offsetof( MemoryRequirements2, pNext ) );
@@ -43829,17 +44620,6 @@
       , heapIndex( heapIndex_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR MemoryType( MemoryType const& rhs ) VULKAN_HPP_NOEXCEPT
-      : propertyFlags( rhs.propertyFlags )
-      , heapIndex( rhs.heapIndex )
-    {}
-
-    MemoryType & operator=( MemoryType const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( MemoryType ) );
-      return *this;
-    }
-
     MemoryType( VkMemoryType const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -43890,11 +44670,6 @@
       : memoryTypeBits( memoryTypeBits_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR MemoryWin32HandlePropertiesKHR( MemoryWin32HandlePropertiesKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , memoryTypeBits( rhs.memoryTypeBits )
-    {}
-
     MemoryWin32HandlePropertiesKHR & operator=( MemoryWin32HandlePropertiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( MemoryWin32HandlePropertiesKHR ) - offsetof( MemoryWin32HandlePropertiesKHR, pNext ) );
@@ -43956,12 +44731,6 @@
       , pLayer( pLayer_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR MetalSurfaceCreateInfoEXT( MetalSurfaceCreateInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , pLayer( rhs.pLayer )
-    {}
-
     MetalSurfaceCreateInfoEXT & operator=( MetalSurfaceCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( MetalSurfaceCreateInfoEXT ) - offsetof( MetalSurfaceCreateInfoEXT, pNext ) );
@@ -44040,11 +44809,6 @@
       : maxSampleLocationGridSize( maxSampleLocationGridSize_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR MultisamplePropertiesEXT( MultisamplePropertiesEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , maxSampleLocationGridSize( rhs.maxSampleLocationGridSize )
-    {}
-
     MultisamplePropertiesEXT & operator=( MultisamplePropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( MultisamplePropertiesEXT ) - offsetof( MultisamplePropertiesEXT, pNext ) );
@@ -44096,741 +44860,6 @@
   static_assert( sizeof( MultisamplePropertiesEXT ) == sizeof( VkMultisamplePropertiesEXT ), "struct and wrapper have different size!" );
   static_assert( std::is_standard_layout<MultisamplePropertiesEXT>::value, "struct wrapper is not a standard layout!" );
 
-  struct ObjectTableCreateInfoNVX
-  {
-    VULKAN_HPP_CONSTEXPR ObjectTableCreateInfoNVX( uint32_t objectCount_ = {},
-                                                   const VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX* pObjectEntryTypes_ = {},
-                                                   const uint32_t* pObjectEntryCounts_ = {},
-                                                   const VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX* pObjectEntryUsageFlags_ = {},
-                                                   uint32_t maxUniformBuffersPerDescriptor_ = {},
-                                                   uint32_t maxStorageBuffersPerDescriptor_ = {},
-                                                   uint32_t maxStorageImagesPerDescriptor_ = {},
-                                                   uint32_t maxSampledImagesPerDescriptor_ = {},
-                                                   uint32_t maxPipelineLayouts_ = {} ) VULKAN_HPP_NOEXCEPT
-      : objectCount( objectCount_ )
-      , pObjectEntryTypes( pObjectEntryTypes_ )
-      , pObjectEntryCounts( pObjectEntryCounts_ )
-      , pObjectEntryUsageFlags( pObjectEntryUsageFlags_ )
-      , maxUniformBuffersPerDescriptor( maxUniformBuffersPerDescriptor_ )
-      , maxStorageBuffersPerDescriptor( maxStorageBuffersPerDescriptor_ )
-      , maxStorageImagesPerDescriptor( maxStorageImagesPerDescriptor_ )
-      , maxSampledImagesPerDescriptor( maxSampledImagesPerDescriptor_ )
-      , maxPipelineLayouts( maxPipelineLayouts_ )
-    {}
-
-    VULKAN_HPP_CONSTEXPR ObjectTableCreateInfoNVX( ObjectTableCreateInfoNVX const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , objectCount( rhs.objectCount )
-      , pObjectEntryTypes( rhs.pObjectEntryTypes )
-      , pObjectEntryCounts( rhs.pObjectEntryCounts )
-      , pObjectEntryUsageFlags( rhs.pObjectEntryUsageFlags )
-      , maxUniformBuffersPerDescriptor( rhs.maxUniformBuffersPerDescriptor )
-      , maxStorageBuffersPerDescriptor( rhs.maxStorageBuffersPerDescriptor )
-      , maxStorageImagesPerDescriptor( rhs.maxStorageImagesPerDescriptor )
-      , maxSampledImagesPerDescriptor( rhs.maxSampledImagesPerDescriptor )
-      , maxPipelineLayouts( rhs.maxPipelineLayouts )
-    {}
-
-    ObjectTableCreateInfoNVX & operator=( ObjectTableCreateInfoNVX const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( &pNext, &rhs.pNext, sizeof( ObjectTableCreateInfoNVX ) - offsetof( ObjectTableCreateInfoNVX, pNext ) );
-      return *this;
-    }
-
-    ObjectTableCreateInfoNVX( VkObjectTableCreateInfoNVX const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      *this = rhs;
-    }
-
-    ObjectTableCreateInfoNVX& operator=( VkObjectTableCreateInfoNVX const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ObjectTableCreateInfoNVX const *>(&rhs);
-      return *this;
-    }
-
-    ObjectTableCreateInfoNVX & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
-    {
-      pNext = pNext_;
-      return *this;
-    }
-
-    ObjectTableCreateInfoNVX & setObjectCount( uint32_t objectCount_ ) VULKAN_HPP_NOEXCEPT
-    {
-      objectCount = objectCount_;
-      return *this;
-    }
-
-    ObjectTableCreateInfoNVX & setPObjectEntryTypes( const VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX* pObjectEntryTypes_ ) VULKAN_HPP_NOEXCEPT
-    {
-      pObjectEntryTypes = pObjectEntryTypes_;
-      return *this;
-    }
-
-    ObjectTableCreateInfoNVX & setPObjectEntryCounts( const uint32_t* pObjectEntryCounts_ ) VULKAN_HPP_NOEXCEPT
-    {
-      pObjectEntryCounts = pObjectEntryCounts_;
-      return *this;
-    }
-
-    ObjectTableCreateInfoNVX & setPObjectEntryUsageFlags( const VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX* pObjectEntryUsageFlags_ ) VULKAN_HPP_NOEXCEPT
-    {
-      pObjectEntryUsageFlags = pObjectEntryUsageFlags_;
-      return *this;
-    }
-
-    ObjectTableCreateInfoNVX & setMaxUniformBuffersPerDescriptor( uint32_t maxUniformBuffersPerDescriptor_ ) VULKAN_HPP_NOEXCEPT
-    {
-      maxUniformBuffersPerDescriptor = maxUniformBuffersPerDescriptor_;
-      return *this;
-    }
-
-    ObjectTableCreateInfoNVX & setMaxStorageBuffersPerDescriptor( uint32_t maxStorageBuffersPerDescriptor_ ) VULKAN_HPP_NOEXCEPT
-    {
-      maxStorageBuffersPerDescriptor = maxStorageBuffersPerDescriptor_;
-      return *this;
-    }
-
-    ObjectTableCreateInfoNVX & setMaxStorageImagesPerDescriptor( uint32_t maxStorageImagesPerDescriptor_ ) VULKAN_HPP_NOEXCEPT
-    {
-      maxStorageImagesPerDescriptor = maxStorageImagesPerDescriptor_;
-      return *this;
-    }
-
-    ObjectTableCreateInfoNVX & setMaxSampledImagesPerDescriptor( uint32_t maxSampledImagesPerDescriptor_ ) VULKAN_HPP_NOEXCEPT
-    {
-      maxSampledImagesPerDescriptor = maxSampledImagesPerDescriptor_;
-      return *this;
-    }
-
-    ObjectTableCreateInfoNVX & setMaxPipelineLayouts( uint32_t maxPipelineLayouts_ ) VULKAN_HPP_NOEXCEPT
-    {
-      maxPipelineLayouts = maxPipelineLayouts_;
-      return *this;
-    }
-
-    operator VkObjectTableCreateInfoNVX const&() const VULKAN_HPP_NOEXCEPT
-    {
-      return *reinterpret_cast<const VkObjectTableCreateInfoNVX*>( this );
-    }
-
-    operator VkObjectTableCreateInfoNVX &() VULKAN_HPP_NOEXCEPT
-    {
-      return *reinterpret_cast<VkObjectTableCreateInfoNVX*>( this );
-    }
-
-#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
-    auto operator<=>( ObjectTableCreateInfoNVX const& ) const = default;
-#else
-    bool operator==( ObjectTableCreateInfoNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
-    {
-      return ( sType == rhs.sType )
-          && ( pNext == rhs.pNext )
-          && ( objectCount == rhs.objectCount )
-          && ( pObjectEntryTypes == rhs.pObjectEntryTypes )
-          && ( pObjectEntryCounts == rhs.pObjectEntryCounts )
-          && ( pObjectEntryUsageFlags == rhs.pObjectEntryUsageFlags )
-          && ( maxUniformBuffersPerDescriptor == rhs.maxUniformBuffersPerDescriptor )
-          && ( maxStorageBuffersPerDescriptor == rhs.maxStorageBuffersPerDescriptor )
-          && ( maxStorageImagesPerDescriptor == rhs.maxStorageImagesPerDescriptor )
-          && ( maxSampledImagesPerDescriptor == rhs.maxSampledImagesPerDescriptor )
-          && ( maxPipelineLayouts == rhs.maxPipelineLayouts );
-    }
-
-    bool operator!=( ObjectTableCreateInfoNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
-    {
-      return !operator==( rhs );
-    }
-#endif
-
-  public:
-    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eObjectTableCreateInfoNVX;
-    const void* pNext = {};
-    uint32_t objectCount = {};
-    const VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX* pObjectEntryTypes = {};
-    const uint32_t* pObjectEntryCounts = {};
-    const VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX* pObjectEntryUsageFlags = {};
-    uint32_t maxUniformBuffersPerDescriptor = {};
-    uint32_t maxStorageBuffersPerDescriptor = {};
-    uint32_t maxStorageImagesPerDescriptor = {};
-    uint32_t maxSampledImagesPerDescriptor = {};
-    uint32_t maxPipelineLayouts = {};
-  };
-  static_assert( sizeof( ObjectTableCreateInfoNVX ) == sizeof( VkObjectTableCreateInfoNVX ), "struct and wrapper have different size!" );
-  static_assert( std::is_standard_layout<ObjectTableCreateInfoNVX>::value, "struct wrapper is not a standard layout!" );
-
-  struct ObjectTableEntryNVX
-  {
-    VULKAN_HPP_CONSTEXPR ObjectTableEntryNVX( VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX type_ = VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX::eDescriptorSet,
-                                              VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX flags_ = {} ) VULKAN_HPP_NOEXCEPT
-      : type( type_ )
-      , flags( flags_ )
-    {}
-
-    VULKAN_HPP_CONSTEXPR ObjectTableEntryNVX( ObjectTableEntryNVX const& rhs ) VULKAN_HPP_NOEXCEPT
-      : type( rhs.type )
-      , flags( rhs.flags )
-    {}
-
-    ObjectTableEntryNVX & operator=( ObjectTableEntryNVX const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( ObjectTableEntryNVX ) );
-      return *this;
-    }
-
-    ObjectTableEntryNVX( VkObjectTableEntryNVX const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      *this = rhs;
-    }
-
-    ObjectTableEntryNVX& operator=( VkObjectTableEntryNVX const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ObjectTableEntryNVX const *>(&rhs);
-      return *this;
-    }
-
-    ObjectTableEntryNVX & setType( VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX type_ ) VULKAN_HPP_NOEXCEPT
-    {
-      type = type_;
-      return *this;
-    }
-
-    ObjectTableEntryNVX & setFlags( VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX flags_ ) VULKAN_HPP_NOEXCEPT
-    {
-      flags = flags_;
-      return *this;
-    }
-
-    operator VkObjectTableEntryNVX const&() const VULKAN_HPP_NOEXCEPT
-    {
-      return *reinterpret_cast<const VkObjectTableEntryNVX*>( this );
-    }
-
-    operator VkObjectTableEntryNVX &() VULKAN_HPP_NOEXCEPT
-    {
-      return *reinterpret_cast<VkObjectTableEntryNVX*>( this );
-    }
-
-#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
-    auto operator<=>( ObjectTableEntryNVX const& ) const = default;
-#else
-    bool operator==( ObjectTableEntryNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
-    {
-      return ( type == rhs.type )
-          && ( flags == rhs.flags );
-    }
-
-    bool operator!=( ObjectTableEntryNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
-    {
-      return !operator==( rhs );
-    }
-#endif
-
-  public:
-    VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX type = VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX::eDescriptorSet;
-    VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX flags = {};
-  };
-  static_assert( sizeof( ObjectTableEntryNVX ) == sizeof( VkObjectTableEntryNVX ), "struct and wrapper have different size!" );
-  static_assert( std::is_standard_layout<ObjectTableEntryNVX>::value, "struct wrapper is not a standard layout!" );
-
-  struct ObjectTableDescriptorSetEntryNVX
-  {
-    VULKAN_HPP_CONSTEXPR ObjectTableDescriptorSetEntryNVX( VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX type_ = VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX::eDescriptorSet,
-                                                           VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX flags_ = {},
-                                                           VULKAN_HPP_NAMESPACE::PipelineLayout pipelineLayout_ = {},
-                                                           VULKAN_HPP_NAMESPACE::DescriptorSet descriptorSet_ = {} ) VULKAN_HPP_NOEXCEPT
-      : type( type_ )
-      , flags( flags_ )
-      , pipelineLayout( pipelineLayout_ )
-      , descriptorSet( descriptorSet_ )
-    {}
-
-    VULKAN_HPP_CONSTEXPR ObjectTableDescriptorSetEntryNVX( ObjectTableDescriptorSetEntryNVX const& rhs ) VULKAN_HPP_NOEXCEPT
-      : type( rhs.type )
-      , flags( rhs.flags )
-      , pipelineLayout( rhs.pipelineLayout )
-      , descriptorSet( rhs.descriptorSet )
-    {}
-
-    explicit ObjectTableDescriptorSetEntryNVX( ObjectTableEntryNVX const& objectTableEntryNVX,
-                                               VULKAN_HPP_NAMESPACE::PipelineLayout pipelineLayout_ = {},
-                                               VULKAN_HPP_NAMESPACE::DescriptorSet descriptorSet_ = {} )
-      : type( objectTableEntryNVX.type )
-      , flags( objectTableEntryNVX.flags )
-      , pipelineLayout( pipelineLayout_ )
-      , descriptorSet( descriptorSet_ )
-    {}
-
-    ObjectTableDescriptorSetEntryNVX & operator=( ObjectTableDescriptorSetEntryNVX const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( ObjectTableDescriptorSetEntryNVX ) );
-      return *this;
-    }
-
-    ObjectTableDescriptorSetEntryNVX( VkObjectTableDescriptorSetEntryNVX const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      *this = rhs;
-    }
-
-    ObjectTableDescriptorSetEntryNVX& operator=( VkObjectTableDescriptorSetEntryNVX const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ObjectTableDescriptorSetEntryNVX const *>(&rhs);
-      return *this;
-    }
-
-    ObjectTableDescriptorSetEntryNVX & setType( VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX type_ ) VULKAN_HPP_NOEXCEPT
-    {
-      type = type_;
-      return *this;
-    }
-
-    ObjectTableDescriptorSetEntryNVX & setFlags( VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX flags_ ) VULKAN_HPP_NOEXCEPT
-    {
-      flags = flags_;
-      return *this;
-    }
-
-    ObjectTableDescriptorSetEntryNVX & setPipelineLayout( VULKAN_HPP_NAMESPACE::PipelineLayout pipelineLayout_ ) VULKAN_HPP_NOEXCEPT
-    {
-      pipelineLayout = pipelineLayout_;
-      return *this;
-    }
-
-    ObjectTableDescriptorSetEntryNVX & setDescriptorSet( VULKAN_HPP_NAMESPACE::DescriptorSet descriptorSet_ ) VULKAN_HPP_NOEXCEPT
-    {
-      descriptorSet = descriptorSet_;
-      return *this;
-    }
-
-    operator VkObjectTableDescriptorSetEntryNVX const&() const VULKAN_HPP_NOEXCEPT
-    {
-      return *reinterpret_cast<const VkObjectTableDescriptorSetEntryNVX*>( this );
-    }
-
-    operator VkObjectTableDescriptorSetEntryNVX &() VULKAN_HPP_NOEXCEPT
-    {
-      return *reinterpret_cast<VkObjectTableDescriptorSetEntryNVX*>( this );
-    }
-
-#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
-    auto operator<=>( ObjectTableDescriptorSetEntryNVX const& ) const = default;
-#else
-    bool operator==( ObjectTableDescriptorSetEntryNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
-    {
-      return ( type == rhs.type )
-          && ( flags == rhs.flags )
-          && ( pipelineLayout == rhs.pipelineLayout )
-          && ( descriptorSet == rhs.descriptorSet );
-    }
-
-    bool operator!=( ObjectTableDescriptorSetEntryNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
-    {
-      return !operator==( rhs );
-    }
-#endif
-
-  public:
-    VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX type = VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX::eDescriptorSet;
-    VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX flags = {};
-    VULKAN_HPP_NAMESPACE::PipelineLayout pipelineLayout = {};
-    VULKAN_HPP_NAMESPACE::DescriptorSet descriptorSet = {};
-  };
-  static_assert( sizeof( ObjectTableDescriptorSetEntryNVX ) == sizeof( VkObjectTableDescriptorSetEntryNVX ), "struct and wrapper have different size!" );
-  static_assert( std::is_standard_layout<ObjectTableDescriptorSetEntryNVX>::value, "struct wrapper is not a standard layout!" );
-
-  struct ObjectTableIndexBufferEntryNVX
-  {
-    VULKAN_HPP_CONSTEXPR ObjectTableIndexBufferEntryNVX( VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX type_ = VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX::eDescriptorSet,
-                                                         VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX flags_ = {},
-                                                         VULKAN_HPP_NAMESPACE::Buffer buffer_ = {},
-                                                         VULKAN_HPP_NAMESPACE::IndexType indexType_ = VULKAN_HPP_NAMESPACE::IndexType::eUint16 ) VULKAN_HPP_NOEXCEPT
-      : type( type_ )
-      , flags( flags_ )
-      , buffer( buffer_ )
-      , indexType( indexType_ )
-    {}
-
-    VULKAN_HPP_CONSTEXPR ObjectTableIndexBufferEntryNVX( ObjectTableIndexBufferEntryNVX const& rhs ) VULKAN_HPP_NOEXCEPT
-      : type( rhs.type )
-      , flags( rhs.flags )
-      , buffer( rhs.buffer )
-      , indexType( rhs.indexType )
-    {}
-
-    explicit ObjectTableIndexBufferEntryNVX( ObjectTableEntryNVX const& objectTableEntryNVX,
-                                             VULKAN_HPP_NAMESPACE::Buffer buffer_ = {},
-                                             VULKAN_HPP_NAMESPACE::IndexType indexType_ = VULKAN_HPP_NAMESPACE::IndexType::eUint16 )
-      : type( objectTableEntryNVX.type )
-      , flags( objectTableEntryNVX.flags )
-      , buffer( buffer_ )
-      , indexType( indexType_ )
-    {}
-
-    ObjectTableIndexBufferEntryNVX & operator=( ObjectTableIndexBufferEntryNVX const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( ObjectTableIndexBufferEntryNVX ) );
-      return *this;
-    }
-
-    ObjectTableIndexBufferEntryNVX( VkObjectTableIndexBufferEntryNVX const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      *this = rhs;
-    }
-
-    ObjectTableIndexBufferEntryNVX& operator=( VkObjectTableIndexBufferEntryNVX const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ObjectTableIndexBufferEntryNVX const *>(&rhs);
-      return *this;
-    }
-
-    ObjectTableIndexBufferEntryNVX & setType( VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX type_ ) VULKAN_HPP_NOEXCEPT
-    {
-      type = type_;
-      return *this;
-    }
-
-    ObjectTableIndexBufferEntryNVX & setFlags( VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX flags_ ) VULKAN_HPP_NOEXCEPT
-    {
-      flags = flags_;
-      return *this;
-    }
-
-    ObjectTableIndexBufferEntryNVX & setBuffer( VULKAN_HPP_NAMESPACE::Buffer buffer_ ) VULKAN_HPP_NOEXCEPT
-    {
-      buffer = buffer_;
-      return *this;
-    }
-
-    ObjectTableIndexBufferEntryNVX & setIndexType( VULKAN_HPP_NAMESPACE::IndexType indexType_ ) VULKAN_HPP_NOEXCEPT
-    {
-      indexType = indexType_;
-      return *this;
-    }
-
-    operator VkObjectTableIndexBufferEntryNVX const&() const VULKAN_HPP_NOEXCEPT
-    {
-      return *reinterpret_cast<const VkObjectTableIndexBufferEntryNVX*>( this );
-    }
-
-    operator VkObjectTableIndexBufferEntryNVX &() VULKAN_HPP_NOEXCEPT
-    {
-      return *reinterpret_cast<VkObjectTableIndexBufferEntryNVX*>( this );
-    }
-
-#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
-    auto operator<=>( ObjectTableIndexBufferEntryNVX const& ) const = default;
-#else
-    bool operator==( ObjectTableIndexBufferEntryNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
-    {
-      return ( type == rhs.type )
-          && ( flags == rhs.flags )
-          && ( buffer == rhs.buffer )
-          && ( indexType == rhs.indexType );
-    }
-
-    bool operator!=( ObjectTableIndexBufferEntryNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
-    {
-      return !operator==( rhs );
-    }
-#endif
-
-  public:
-    VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX type = VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX::eDescriptorSet;
-    VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX flags = {};
-    VULKAN_HPP_NAMESPACE::Buffer buffer = {};
-    VULKAN_HPP_NAMESPACE::IndexType indexType = VULKAN_HPP_NAMESPACE::IndexType::eUint16;
-  };
-  static_assert( sizeof( ObjectTableIndexBufferEntryNVX ) == sizeof( VkObjectTableIndexBufferEntryNVX ), "struct and wrapper have different size!" );
-  static_assert( std::is_standard_layout<ObjectTableIndexBufferEntryNVX>::value, "struct wrapper is not a standard layout!" );
-
-  struct ObjectTablePipelineEntryNVX
-  {
-    VULKAN_HPP_CONSTEXPR ObjectTablePipelineEntryNVX( VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX type_ = VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX::eDescriptorSet,
-                                                      VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX flags_ = {},
-                                                      VULKAN_HPP_NAMESPACE::Pipeline pipeline_ = {} ) VULKAN_HPP_NOEXCEPT
-      : type( type_ )
-      , flags( flags_ )
-      , pipeline( pipeline_ )
-    {}
-
-    VULKAN_HPP_CONSTEXPR ObjectTablePipelineEntryNVX( ObjectTablePipelineEntryNVX const& rhs ) VULKAN_HPP_NOEXCEPT
-      : type( rhs.type )
-      , flags( rhs.flags )
-      , pipeline( rhs.pipeline )
-    {}
-
-    explicit ObjectTablePipelineEntryNVX( ObjectTableEntryNVX const& objectTableEntryNVX,
-                                          VULKAN_HPP_NAMESPACE::Pipeline pipeline_ = {} )
-      : type( objectTableEntryNVX.type )
-      , flags( objectTableEntryNVX.flags )
-      , pipeline( pipeline_ )
-    {}
-
-    ObjectTablePipelineEntryNVX & operator=( ObjectTablePipelineEntryNVX const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( ObjectTablePipelineEntryNVX ) );
-      return *this;
-    }
-
-    ObjectTablePipelineEntryNVX( VkObjectTablePipelineEntryNVX const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      *this = rhs;
-    }
-
-    ObjectTablePipelineEntryNVX& operator=( VkObjectTablePipelineEntryNVX const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ObjectTablePipelineEntryNVX const *>(&rhs);
-      return *this;
-    }
-
-    ObjectTablePipelineEntryNVX & setType( VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX type_ ) VULKAN_HPP_NOEXCEPT
-    {
-      type = type_;
-      return *this;
-    }
-
-    ObjectTablePipelineEntryNVX & setFlags( VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX flags_ ) VULKAN_HPP_NOEXCEPT
-    {
-      flags = flags_;
-      return *this;
-    }
-
-    ObjectTablePipelineEntryNVX & setPipeline( VULKAN_HPP_NAMESPACE::Pipeline pipeline_ ) VULKAN_HPP_NOEXCEPT
-    {
-      pipeline = pipeline_;
-      return *this;
-    }
-
-    operator VkObjectTablePipelineEntryNVX const&() const VULKAN_HPP_NOEXCEPT
-    {
-      return *reinterpret_cast<const VkObjectTablePipelineEntryNVX*>( this );
-    }
-
-    operator VkObjectTablePipelineEntryNVX &() VULKAN_HPP_NOEXCEPT
-    {
-      return *reinterpret_cast<VkObjectTablePipelineEntryNVX*>( this );
-    }
-
-#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
-    auto operator<=>( ObjectTablePipelineEntryNVX const& ) const = default;
-#else
-    bool operator==( ObjectTablePipelineEntryNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
-    {
-      return ( type == rhs.type )
-          && ( flags == rhs.flags )
-          && ( pipeline == rhs.pipeline );
-    }
-
-    bool operator!=( ObjectTablePipelineEntryNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
-    {
-      return !operator==( rhs );
-    }
-#endif
-
-  public:
-    VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX type = VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX::eDescriptorSet;
-    VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX flags = {};
-    VULKAN_HPP_NAMESPACE::Pipeline pipeline = {};
-  };
-  static_assert( sizeof( ObjectTablePipelineEntryNVX ) == sizeof( VkObjectTablePipelineEntryNVX ), "struct and wrapper have different size!" );
-  static_assert( std::is_standard_layout<ObjectTablePipelineEntryNVX>::value, "struct wrapper is not a standard layout!" );
-
-  struct ObjectTablePushConstantEntryNVX
-  {
-    VULKAN_HPP_CONSTEXPR ObjectTablePushConstantEntryNVX( VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX type_ = VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX::eDescriptorSet,
-                                                          VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX flags_ = {},
-                                                          VULKAN_HPP_NAMESPACE::PipelineLayout pipelineLayout_ = {},
-                                                          VULKAN_HPP_NAMESPACE::ShaderStageFlags stageFlags_ = {} ) VULKAN_HPP_NOEXCEPT
-      : type( type_ )
-      , flags( flags_ )
-      , pipelineLayout( pipelineLayout_ )
-      , stageFlags( stageFlags_ )
-    {}
-
-    VULKAN_HPP_CONSTEXPR ObjectTablePushConstantEntryNVX( ObjectTablePushConstantEntryNVX const& rhs ) VULKAN_HPP_NOEXCEPT
-      : type( rhs.type )
-      , flags( rhs.flags )
-      , pipelineLayout( rhs.pipelineLayout )
-      , stageFlags( rhs.stageFlags )
-    {}
-
-    explicit ObjectTablePushConstantEntryNVX( ObjectTableEntryNVX const& objectTableEntryNVX,
-                                              VULKAN_HPP_NAMESPACE::PipelineLayout pipelineLayout_ = {},
-                                              VULKAN_HPP_NAMESPACE::ShaderStageFlags stageFlags_ = {} )
-      : type( objectTableEntryNVX.type )
-      , flags( objectTableEntryNVX.flags )
-      , pipelineLayout( pipelineLayout_ )
-      , stageFlags( stageFlags_ )
-    {}
-
-    ObjectTablePushConstantEntryNVX & operator=( ObjectTablePushConstantEntryNVX const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( ObjectTablePushConstantEntryNVX ) );
-      return *this;
-    }
-
-    ObjectTablePushConstantEntryNVX( VkObjectTablePushConstantEntryNVX const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      *this = rhs;
-    }
-
-    ObjectTablePushConstantEntryNVX& operator=( VkObjectTablePushConstantEntryNVX const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ObjectTablePushConstantEntryNVX const *>(&rhs);
-      return *this;
-    }
-
-    ObjectTablePushConstantEntryNVX & setType( VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX type_ ) VULKAN_HPP_NOEXCEPT
-    {
-      type = type_;
-      return *this;
-    }
-
-    ObjectTablePushConstantEntryNVX & setFlags( VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX flags_ ) VULKAN_HPP_NOEXCEPT
-    {
-      flags = flags_;
-      return *this;
-    }
-
-    ObjectTablePushConstantEntryNVX & setPipelineLayout( VULKAN_HPP_NAMESPACE::PipelineLayout pipelineLayout_ ) VULKAN_HPP_NOEXCEPT
-    {
-      pipelineLayout = pipelineLayout_;
-      return *this;
-    }
-
-    ObjectTablePushConstantEntryNVX & setStageFlags( VULKAN_HPP_NAMESPACE::ShaderStageFlags stageFlags_ ) VULKAN_HPP_NOEXCEPT
-    {
-      stageFlags = stageFlags_;
-      return *this;
-    }
-
-    operator VkObjectTablePushConstantEntryNVX const&() const VULKAN_HPP_NOEXCEPT
-    {
-      return *reinterpret_cast<const VkObjectTablePushConstantEntryNVX*>( this );
-    }
-
-    operator VkObjectTablePushConstantEntryNVX &() VULKAN_HPP_NOEXCEPT
-    {
-      return *reinterpret_cast<VkObjectTablePushConstantEntryNVX*>( this );
-    }
-
-#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
-    auto operator<=>( ObjectTablePushConstantEntryNVX const& ) const = default;
-#else
-    bool operator==( ObjectTablePushConstantEntryNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
-    {
-      return ( type == rhs.type )
-          && ( flags == rhs.flags )
-          && ( pipelineLayout == rhs.pipelineLayout )
-          && ( stageFlags == rhs.stageFlags );
-    }
-
-    bool operator!=( ObjectTablePushConstantEntryNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
-    {
-      return !operator==( rhs );
-    }
-#endif
-
-  public:
-    VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX type = VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX::eDescriptorSet;
-    VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX flags = {};
-    VULKAN_HPP_NAMESPACE::PipelineLayout pipelineLayout = {};
-    VULKAN_HPP_NAMESPACE::ShaderStageFlags stageFlags = {};
-  };
-  static_assert( sizeof( ObjectTablePushConstantEntryNVX ) == sizeof( VkObjectTablePushConstantEntryNVX ), "struct and wrapper have different size!" );
-  static_assert( std::is_standard_layout<ObjectTablePushConstantEntryNVX>::value, "struct wrapper is not a standard layout!" );
-
-  struct ObjectTableVertexBufferEntryNVX
-  {
-    VULKAN_HPP_CONSTEXPR ObjectTableVertexBufferEntryNVX( VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX type_ = VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX::eDescriptorSet,
-                                                          VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX flags_ = {},
-                                                          VULKAN_HPP_NAMESPACE::Buffer buffer_ = {} ) VULKAN_HPP_NOEXCEPT
-      : type( type_ )
-      , flags( flags_ )
-      , buffer( buffer_ )
-    {}
-
-    VULKAN_HPP_CONSTEXPR ObjectTableVertexBufferEntryNVX( ObjectTableVertexBufferEntryNVX const& rhs ) VULKAN_HPP_NOEXCEPT
-      : type( rhs.type )
-      , flags( rhs.flags )
-      , buffer( rhs.buffer )
-    {}
-
-    explicit ObjectTableVertexBufferEntryNVX( ObjectTableEntryNVX const& objectTableEntryNVX,
-                                              VULKAN_HPP_NAMESPACE::Buffer buffer_ = {} )
-      : type( objectTableEntryNVX.type )
-      , flags( objectTableEntryNVX.flags )
-      , buffer( buffer_ )
-    {}
-
-    ObjectTableVertexBufferEntryNVX & operator=( ObjectTableVertexBufferEntryNVX const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( ObjectTableVertexBufferEntryNVX ) );
-      return *this;
-    }
-
-    ObjectTableVertexBufferEntryNVX( VkObjectTableVertexBufferEntryNVX const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      *this = rhs;
-    }
-
-    ObjectTableVertexBufferEntryNVX& operator=( VkObjectTableVertexBufferEntryNVX const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::ObjectTableVertexBufferEntryNVX const *>(&rhs);
-      return *this;
-    }
-
-    ObjectTableVertexBufferEntryNVX & setType( VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX type_ ) VULKAN_HPP_NOEXCEPT
-    {
-      type = type_;
-      return *this;
-    }
-
-    ObjectTableVertexBufferEntryNVX & setFlags( VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX flags_ ) VULKAN_HPP_NOEXCEPT
-    {
-      flags = flags_;
-      return *this;
-    }
-
-    ObjectTableVertexBufferEntryNVX & setBuffer( VULKAN_HPP_NAMESPACE::Buffer buffer_ ) VULKAN_HPP_NOEXCEPT
-    {
-      buffer = buffer_;
-      return *this;
-    }
-
-    operator VkObjectTableVertexBufferEntryNVX const&() const VULKAN_HPP_NOEXCEPT
-    {
-      return *reinterpret_cast<const VkObjectTableVertexBufferEntryNVX*>( this );
-    }
-
-    operator VkObjectTableVertexBufferEntryNVX &() VULKAN_HPP_NOEXCEPT
-    {
-      return *reinterpret_cast<VkObjectTableVertexBufferEntryNVX*>( this );
-    }
-
-#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
-    auto operator<=>( ObjectTableVertexBufferEntryNVX const& ) const = default;
-#else
-    bool operator==( ObjectTableVertexBufferEntryNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
-    {
-      return ( type == rhs.type )
-          && ( flags == rhs.flags )
-          && ( buffer == rhs.buffer );
-    }
-
-    bool operator!=( ObjectTableVertexBufferEntryNVX const& rhs ) const VULKAN_HPP_NOEXCEPT
-    {
-      return !operator==( rhs );
-    }
-#endif
-
-  public:
-    VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX type = VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX::eDescriptorSet;
-    VULKAN_HPP_NAMESPACE::ObjectEntryUsageFlagsNVX flags = {};
-    VULKAN_HPP_NAMESPACE::Buffer buffer = {};
-  };
-  static_assert( sizeof( ObjectTableVertexBufferEntryNVX ) == sizeof( VkObjectTableVertexBufferEntryNVX ), "struct and wrapper have different size!" );
-  static_assert( std::is_standard_layout<ObjectTableVertexBufferEntryNVX>::value, "struct wrapper is not a standard layout!" );
-
   struct PastPresentationTimingGOOGLE
   {
     VULKAN_HPP_CONSTEXPR PastPresentationTimingGOOGLE( uint32_t presentID_ = {},
@@ -44845,20 +44874,6 @@
       , presentMargin( presentMargin_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PastPresentationTimingGOOGLE( PastPresentationTimingGOOGLE const& rhs ) VULKAN_HPP_NOEXCEPT
-      : presentID( rhs.presentID )
-      , desiredPresentTime( rhs.desiredPresentTime )
-      , actualPresentTime( rhs.actualPresentTime )
-      , earliestPresentTime( rhs.earliestPresentTime )
-      , presentMargin( rhs.presentMargin )
-    {}
-
-    PastPresentationTimingGOOGLE & operator=( PastPresentationTimingGOOGLE const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( PastPresentationTimingGOOGLE ) );
-      return *this;
-    }
-
     PastPresentationTimingGOOGLE( VkPastPresentationTimingGOOGLE const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -44914,11 +44929,6 @@
       : type( type_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PerformanceConfigurationAcquireInfoINTEL( PerformanceConfigurationAcquireInfoINTEL const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , type( rhs.type )
-    {}
-
     PerformanceConfigurationAcquireInfoINTEL & operator=( PerformanceConfigurationAcquireInfoINTEL const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PerformanceConfigurationAcquireInfoINTEL ) - offsetof( PerformanceConfigurationAcquireInfoINTEL, pNext ) );
@@ -44989,26 +44999,10 @@
                                                               std::array<char,VK_MAX_DESCRIPTION_SIZE> const& category_ = {},
                                                               std::array<char,VK_MAX_DESCRIPTION_SIZE> const& description_ = {} ) VULKAN_HPP_NOEXCEPT
       : flags( flags_ )
-      , name{}
-      , category{}
-      , description{}
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DESCRIPTION_SIZE>::copy( name, name_ );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DESCRIPTION_SIZE>::copy( category, category_ );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DESCRIPTION_SIZE>::copy( description, description_ );
-    }
-
-    VULKAN_HPP_CONSTEXPR_14 PerformanceCounterDescriptionKHR( PerformanceCounterDescriptionKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , name{}
-      , category{}
-      , description{}
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DESCRIPTION_SIZE>::copy( name, rhs.name );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DESCRIPTION_SIZE>::copy( category, rhs.category );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DESCRIPTION_SIZE>::copy( description, rhs.description );
-    }
+      , name( name_ )
+      , category( category_ )
+      , description( description_ )
+    {}
 
     PerformanceCounterDescriptionKHR & operator=( PerformanceCounterDescriptionKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
@@ -45045,9 +45039,9 @@
       return ( sType == rhs.sType )
           && ( pNext == rhs.pNext )
           && ( flags == rhs.flags )
-          && ( memcmp( name, rhs.name, VK_MAX_DESCRIPTION_SIZE * sizeof( char ) ) == 0 )
-          && ( memcmp( category, rhs.category, VK_MAX_DESCRIPTION_SIZE * sizeof( char ) ) == 0 )
-          && ( memcmp( description, rhs.description, VK_MAX_DESCRIPTION_SIZE * sizeof( char ) ) == 0 );
+          && ( name == rhs.name )
+          && ( category == rhs.category )
+          && ( description == rhs.description );
     }
 
     bool operator!=( PerformanceCounterDescriptionKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
@@ -45060,9 +45054,9 @@
     const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePerformanceCounterDescriptionKHR;
     const void* pNext = {};
     VULKAN_HPP_NAMESPACE::PerformanceCounterDescriptionFlagsKHR flags = {};
-    char name[VK_MAX_DESCRIPTION_SIZE] = {};
-    char category[VK_MAX_DESCRIPTION_SIZE] = {};
-    char description[VK_MAX_DESCRIPTION_SIZE] = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<char, VK_MAX_DESCRIPTION_SIZE> name = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<char, VK_MAX_DESCRIPTION_SIZE> category = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<char, VK_MAX_DESCRIPTION_SIZE> description = {};
   };
   static_assert( sizeof( PerformanceCounterDescriptionKHR ) == sizeof( VkPerformanceCounterDescriptionKHR ), "struct and wrapper have different size!" );
   static_assert( std::is_standard_layout<PerformanceCounterDescriptionKHR>::value, "struct wrapper is not a standard layout!" );
@@ -45076,20 +45070,8 @@
       : unit( unit_ )
       , scope( scope_ )
       , storage( storage_ )
-      , uuid{}
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint8_t,VK_UUID_SIZE>::copy( uuid, uuid_ );
-    }
-
-    VULKAN_HPP_CONSTEXPR_14 PerformanceCounterKHR( PerformanceCounterKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , unit( rhs.unit )
-      , scope( rhs.scope )
-      , storage( rhs.storage )
-      , uuid{}
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint8_t,VK_UUID_SIZE>::copy( uuid, rhs.uuid );
-    }
+      , uuid( uuid_ )
+    {}
 
     PerformanceCounterKHR & operator=( PerformanceCounterKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
@@ -45128,7 +45110,7 @@
           && ( unit == rhs.unit )
           && ( scope == rhs.scope )
           && ( storage == rhs.storage )
-          && ( memcmp( uuid, rhs.uuid, VK_UUID_SIZE * sizeof( uint8_t ) ) == 0 );
+          && ( uuid == rhs.uuid );
     }
 
     bool operator!=( PerformanceCounterKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
@@ -45143,7 +45125,7 @@
     VULKAN_HPP_NAMESPACE::PerformanceCounterUnitKHR unit = VULKAN_HPP_NAMESPACE::PerformanceCounterUnitKHR::eGeneric;
     VULKAN_HPP_NAMESPACE::PerformanceCounterScopeKHR scope = VULKAN_HPP_NAMESPACE::PerformanceCounterScopeKHR::eCommandBuffer;
     VULKAN_HPP_NAMESPACE::PerformanceCounterStorageKHR storage = VULKAN_HPP_NAMESPACE::PerformanceCounterStorageKHR::eInt32;
-    uint8_t uuid[VK_UUID_SIZE] = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<uint8_t, VK_UUID_SIZE> uuid = {};
   };
   static_assert( sizeof( PerformanceCounterKHR ) == sizeof( VkPerformanceCounterKHR ), "struct and wrapper have different size!" );
   static_assert( std::is_standard_layout<PerformanceCounterKHR>::value, "struct wrapper is not a standard layout!" );
@@ -45251,11 +45233,6 @@
       : marker( marker_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PerformanceMarkerInfoINTEL( PerformanceMarkerInfoINTEL const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , marker( rhs.marker )
-    {}
-
     PerformanceMarkerInfoINTEL & operator=( PerformanceMarkerInfoINTEL const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PerformanceMarkerInfoINTEL ) - offsetof( PerformanceMarkerInfoINTEL, pNext ) );
@@ -45329,13 +45306,6 @@
       , parameter( parameter_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PerformanceOverrideInfoINTEL( PerformanceOverrideInfoINTEL const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , type( rhs.type )
-      , enable( rhs.enable )
-      , parameter( rhs.parameter )
-    {}
-
     PerformanceOverrideInfoINTEL & operator=( PerformanceOverrideInfoINTEL const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PerformanceOverrideInfoINTEL ) - offsetof( PerformanceOverrideInfoINTEL, pNext ) );
@@ -45421,11 +45391,6 @@
       : counterPassIndex( counterPassIndex_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PerformanceQuerySubmitInfoKHR( PerformanceQuerySubmitInfoKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , counterPassIndex( rhs.counterPassIndex )
-    {}
-
     PerformanceQuerySubmitInfoKHR & operator=( PerformanceQuerySubmitInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PerformanceQuerySubmitInfoKHR ) - offsetof( PerformanceQuerySubmitInfoKHR, pNext ) );
@@ -45495,11 +45460,6 @@
       : marker( marker_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PerformanceStreamMarkerInfoINTEL( PerformanceStreamMarkerInfoINTEL const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , marker( rhs.marker )
-    {}
-
     PerformanceStreamMarkerInfoINTEL & operator=( PerformanceStreamMarkerInfoINTEL const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PerformanceStreamMarkerInfoINTEL ) - offsetof( PerformanceStreamMarkerInfoINTEL, pNext ) );
@@ -45659,17 +45619,6 @@
       , data( data_ )
     {}
 
-    PerformanceValueINTEL( PerformanceValueINTEL const& rhs ) VULKAN_HPP_NOEXCEPT
-      : type( rhs.type )
-      , data( rhs.data )
-    {}
-
-    PerformanceValueINTEL & operator=( PerformanceValueINTEL const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( PerformanceValueINTEL ) );
-      return *this;
-    }
-
     PerformanceValueINTEL( VkPerformanceValueINTEL const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -45722,14 +45671,6 @@
       , storageInputOutput16( storageInputOutput16_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDevice16BitStorageFeatures( PhysicalDevice16BitStorageFeatures const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , storageBuffer16BitAccess( rhs.storageBuffer16BitAccess )
-      , uniformAndStorageBuffer16BitAccess( rhs.uniformAndStorageBuffer16BitAccess )
-      , storagePushConstant16( rhs.storagePushConstant16 )
-      , storageInputOutput16( rhs.storageInputOutput16 )
-    {}
-
     PhysicalDevice16BitStorageFeatures & operator=( PhysicalDevice16BitStorageFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDevice16BitStorageFeatures ) - offsetof( PhysicalDevice16BitStorageFeatures, pNext ) );
@@ -45827,13 +45768,6 @@
       , storagePushConstant8( storagePushConstant8_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDevice8BitStorageFeatures( PhysicalDevice8BitStorageFeatures const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , storageBuffer8BitAccess( rhs.storageBuffer8BitAccess )
-      , uniformAndStorageBuffer8BitAccess( rhs.uniformAndStorageBuffer8BitAccess )
-      , storagePushConstant8( rhs.storagePushConstant8 )
-    {}
-
     PhysicalDevice8BitStorageFeatures & operator=( PhysicalDevice8BitStorageFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDevice8BitStorageFeatures ) - offsetof( PhysicalDevice8BitStorageFeatures, pNext ) );
@@ -45919,11 +45853,6 @@
       : decodeModeSharedExponent( decodeModeSharedExponent_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceASTCDecodeFeaturesEXT( PhysicalDeviceASTCDecodeFeaturesEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , decodeModeSharedExponent( rhs.decodeModeSharedExponent )
-    {}
-
     PhysicalDeviceASTCDecodeFeaturesEXT & operator=( PhysicalDeviceASTCDecodeFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceASTCDecodeFeaturesEXT ) - offsetof( PhysicalDeviceASTCDecodeFeaturesEXT, pNext ) );
@@ -45993,11 +45922,6 @@
       : advancedBlendCoherentOperations( advancedBlendCoherentOperations_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceBlendOperationAdvancedFeaturesEXT( PhysicalDeviceBlendOperationAdvancedFeaturesEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , advancedBlendCoherentOperations( rhs.advancedBlendCoherentOperations )
-    {}
-
     PhysicalDeviceBlendOperationAdvancedFeaturesEXT & operator=( PhysicalDeviceBlendOperationAdvancedFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceBlendOperationAdvancedFeaturesEXT ) - offsetof( PhysicalDeviceBlendOperationAdvancedFeaturesEXT, pNext ) );
@@ -46077,16 +46001,6 @@
       , advancedBlendAllOperations( advancedBlendAllOperations_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceBlendOperationAdvancedPropertiesEXT( PhysicalDeviceBlendOperationAdvancedPropertiesEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , advancedBlendMaxColorAttachments( rhs.advancedBlendMaxColorAttachments )
-      , advancedBlendIndependentBlend( rhs.advancedBlendIndependentBlend )
-      , advancedBlendNonPremultipliedSrcColor( rhs.advancedBlendNonPremultipliedSrcColor )
-      , advancedBlendNonPremultipliedDstColor( rhs.advancedBlendNonPremultipliedDstColor )
-      , advancedBlendCorrelatedOverlap( rhs.advancedBlendCorrelatedOverlap )
-      , advancedBlendAllOperations( rhs.advancedBlendAllOperations )
-    {}
-
     PhysicalDeviceBlendOperationAdvancedPropertiesEXT & operator=( PhysicalDeviceBlendOperationAdvancedPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceBlendOperationAdvancedPropertiesEXT ) - offsetof( PhysicalDeviceBlendOperationAdvancedPropertiesEXT, pNext ) );
@@ -46158,13 +46072,6 @@
       , bufferDeviceAddressMultiDevice( bufferDeviceAddressMultiDevice_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceBufferDeviceAddressFeatures( PhysicalDeviceBufferDeviceAddressFeatures const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , bufferDeviceAddress( rhs.bufferDeviceAddress )
-      , bufferDeviceAddressCaptureReplay( rhs.bufferDeviceAddressCaptureReplay )
-      , bufferDeviceAddressMultiDevice( rhs.bufferDeviceAddressMultiDevice )
-    {}
-
     PhysicalDeviceBufferDeviceAddressFeatures & operator=( PhysicalDeviceBufferDeviceAddressFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceBufferDeviceAddressFeatures ) - offsetof( PhysicalDeviceBufferDeviceAddressFeatures, pNext ) );
@@ -46254,13 +46161,6 @@
       , bufferDeviceAddressMultiDevice( bufferDeviceAddressMultiDevice_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceBufferDeviceAddressFeaturesEXT( PhysicalDeviceBufferDeviceAddressFeaturesEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , bufferDeviceAddress( rhs.bufferDeviceAddress )
-      , bufferDeviceAddressCaptureReplay( rhs.bufferDeviceAddressCaptureReplay )
-      , bufferDeviceAddressMultiDevice( rhs.bufferDeviceAddressMultiDevice )
-    {}
-
     PhysicalDeviceBufferDeviceAddressFeaturesEXT & operator=( PhysicalDeviceBufferDeviceAddressFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceBufferDeviceAddressFeaturesEXT ) - offsetof( PhysicalDeviceBufferDeviceAddressFeaturesEXT, pNext ) );
@@ -46346,11 +46246,6 @@
       : deviceCoherentMemory( deviceCoherentMemory_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceCoherentMemoryFeaturesAMD( PhysicalDeviceCoherentMemoryFeaturesAMD const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , deviceCoherentMemory( rhs.deviceCoherentMemory )
-    {}
-
     PhysicalDeviceCoherentMemoryFeaturesAMD & operator=( PhysicalDeviceCoherentMemoryFeaturesAMD const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceCoherentMemoryFeaturesAMD ) - offsetof( PhysicalDeviceCoherentMemoryFeaturesAMD, pNext ) );
@@ -46422,12 +46317,6 @@
       , computeDerivativeGroupLinear( computeDerivativeGroupLinear_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceComputeShaderDerivativesFeaturesNV( PhysicalDeviceComputeShaderDerivativesFeaturesNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , computeDerivativeGroupQuads( rhs.computeDerivativeGroupQuads )
-      , computeDerivativeGroupLinear( rhs.computeDerivativeGroupLinear )
-    {}
-
     PhysicalDeviceComputeShaderDerivativesFeaturesNV & operator=( PhysicalDeviceComputeShaderDerivativesFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceComputeShaderDerivativesFeaturesNV ) - offsetof( PhysicalDeviceComputeShaderDerivativesFeaturesNV, pNext ) );
@@ -46507,12 +46396,6 @@
       , inheritedConditionalRendering( inheritedConditionalRendering_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceConditionalRenderingFeaturesEXT( PhysicalDeviceConditionalRenderingFeaturesEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , conditionalRendering( rhs.conditionalRendering )
-      , inheritedConditionalRendering( rhs.inheritedConditionalRendering )
-    {}
-
     PhysicalDeviceConditionalRenderingFeaturesEXT & operator=( PhysicalDeviceConditionalRenderingFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceConditionalRenderingFeaturesEXT ) - offsetof( PhysicalDeviceConditionalRenderingFeaturesEXT, pNext ) );
@@ -46606,19 +46489,6 @@
       , conservativeRasterizationPostDepthCoverage( conservativeRasterizationPostDepthCoverage_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceConservativeRasterizationPropertiesEXT( PhysicalDeviceConservativeRasterizationPropertiesEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , primitiveOverestimationSize( rhs.primitiveOverestimationSize )
-      , maxExtraPrimitiveOverestimationSize( rhs.maxExtraPrimitiveOverestimationSize )
-      , extraPrimitiveOverestimationSizeGranularity( rhs.extraPrimitiveOverestimationSizeGranularity )
-      , primitiveUnderestimation( rhs.primitiveUnderestimation )
-      , conservativePointAndLineRasterization( rhs.conservativePointAndLineRasterization )
-      , degenerateTrianglesRasterized( rhs.degenerateTrianglesRasterized )
-      , degenerateLinesRasterized( rhs.degenerateLinesRasterized )
-      , fullyCoveredFragmentShaderInputVariable( rhs.fullyCoveredFragmentShaderInputVariable )
-      , conservativeRasterizationPostDepthCoverage( rhs.conservativeRasterizationPostDepthCoverage )
-    {}
-
     PhysicalDeviceConservativeRasterizationPropertiesEXT & operator=( PhysicalDeviceConservativeRasterizationPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceConservativeRasterizationPropertiesEXT ) - offsetof( PhysicalDeviceConservativeRasterizationPropertiesEXT, pNext ) );
@@ -46694,12 +46564,6 @@
       , cooperativeMatrixRobustBufferAccess( cooperativeMatrixRobustBufferAccess_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceCooperativeMatrixFeaturesNV( PhysicalDeviceCooperativeMatrixFeaturesNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , cooperativeMatrix( rhs.cooperativeMatrix )
-      , cooperativeMatrixRobustBufferAccess( rhs.cooperativeMatrixRobustBufferAccess )
-    {}
-
     PhysicalDeviceCooperativeMatrixFeaturesNV & operator=( PhysicalDeviceCooperativeMatrixFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceCooperativeMatrixFeaturesNV ) - offsetof( PhysicalDeviceCooperativeMatrixFeaturesNV, pNext ) );
@@ -46777,11 +46641,6 @@
       : cooperativeMatrixSupportedStages( cooperativeMatrixSupportedStages_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceCooperativeMatrixPropertiesNV( PhysicalDeviceCooperativeMatrixPropertiesNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , cooperativeMatrixSupportedStages( rhs.cooperativeMatrixSupportedStages )
-    {}
-
     PhysicalDeviceCooperativeMatrixPropertiesNV & operator=( PhysicalDeviceCooperativeMatrixPropertiesNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceCooperativeMatrixPropertiesNV ) - offsetof( PhysicalDeviceCooperativeMatrixPropertiesNV, pNext ) );
@@ -46839,11 +46698,6 @@
       : cornerSampledImage( cornerSampledImage_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceCornerSampledImageFeaturesNV( PhysicalDeviceCornerSampledImageFeaturesNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , cornerSampledImage( rhs.cornerSampledImage )
-    {}
-
     PhysicalDeviceCornerSampledImageFeaturesNV & operator=( PhysicalDeviceCornerSampledImageFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceCornerSampledImageFeaturesNV ) - offsetof( PhysicalDeviceCornerSampledImageFeaturesNV, pNext ) );
@@ -46913,11 +46767,6 @@
       : coverageReductionMode( coverageReductionMode_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceCoverageReductionModeFeaturesNV( PhysicalDeviceCoverageReductionModeFeaturesNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , coverageReductionMode( rhs.coverageReductionMode )
-    {}
-
     PhysicalDeviceCoverageReductionModeFeaturesNV & operator=( PhysicalDeviceCoverageReductionModeFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceCoverageReductionModeFeaturesNV ) - offsetof( PhysicalDeviceCoverageReductionModeFeaturesNV, pNext ) );
@@ -46987,11 +46836,6 @@
       : dedicatedAllocationImageAliasing( dedicatedAllocationImageAliasing_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV( PhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , dedicatedAllocationImageAliasing( rhs.dedicatedAllocationImageAliasing )
-    {}
-
     PhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV & operator=( PhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV ) - offsetof( PhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV, pNext ) );
@@ -47061,11 +46905,6 @@
       : depthClipEnable( depthClipEnable_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceDepthClipEnableFeaturesEXT( PhysicalDeviceDepthClipEnableFeaturesEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , depthClipEnable( rhs.depthClipEnable )
-    {}
-
     PhysicalDeviceDepthClipEnableFeaturesEXT & operator=( PhysicalDeviceDepthClipEnableFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceDepthClipEnableFeaturesEXT ) - offsetof( PhysicalDeviceDepthClipEnableFeaturesEXT, pNext ) );
@@ -47141,14 +46980,6 @@
       , independentResolve( independentResolve_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceDepthStencilResolveProperties( PhysicalDeviceDepthStencilResolveProperties const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , supportedDepthResolveModes( rhs.supportedDepthResolveModes )
-      , supportedStencilResolveModes( rhs.supportedStencilResolveModes )
-      , independentResolveNone( rhs.independentResolveNone )
-      , independentResolve( rhs.independentResolve )
-    {}
-
     PhysicalDeviceDepthStencilResolveProperties & operator=( PhysicalDeviceDepthStencilResolveProperties const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceDepthStencilResolveProperties ) - offsetof( PhysicalDeviceDepthStencilResolveProperties, pNext ) );
@@ -47250,30 +47081,6 @@
       , runtimeDescriptorArray( runtimeDescriptorArray_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceDescriptorIndexingFeatures( PhysicalDeviceDescriptorIndexingFeatures const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , shaderInputAttachmentArrayDynamicIndexing( rhs.shaderInputAttachmentArrayDynamicIndexing )
-      , shaderUniformTexelBufferArrayDynamicIndexing( rhs.shaderUniformTexelBufferArrayDynamicIndexing )
-      , shaderStorageTexelBufferArrayDynamicIndexing( rhs.shaderStorageTexelBufferArrayDynamicIndexing )
-      , shaderUniformBufferArrayNonUniformIndexing( rhs.shaderUniformBufferArrayNonUniformIndexing )
-      , shaderSampledImageArrayNonUniformIndexing( rhs.shaderSampledImageArrayNonUniformIndexing )
-      , shaderStorageBufferArrayNonUniformIndexing( rhs.shaderStorageBufferArrayNonUniformIndexing )
-      , shaderStorageImageArrayNonUniformIndexing( rhs.shaderStorageImageArrayNonUniformIndexing )
-      , shaderInputAttachmentArrayNonUniformIndexing( rhs.shaderInputAttachmentArrayNonUniformIndexing )
-      , shaderUniformTexelBufferArrayNonUniformIndexing( rhs.shaderUniformTexelBufferArrayNonUniformIndexing )
-      , shaderStorageTexelBufferArrayNonUniformIndexing( rhs.shaderStorageTexelBufferArrayNonUniformIndexing )
-      , descriptorBindingUniformBufferUpdateAfterBind( rhs.descriptorBindingUniformBufferUpdateAfterBind )
-      , descriptorBindingSampledImageUpdateAfterBind( rhs.descriptorBindingSampledImageUpdateAfterBind )
-      , descriptorBindingStorageImageUpdateAfterBind( rhs.descriptorBindingStorageImageUpdateAfterBind )
-      , descriptorBindingStorageBufferUpdateAfterBind( rhs.descriptorBindingStorageBufferUpdateAfterBind )
-      , descriptorBindingUniformTexelBufferUpdateAfterBind( rhs.descriptorBindingUniformTexelBufferUpdateAfterBind )
-      , descriptorBindingStorageTexelBufferUpdateAfterBind( rhs.descriptorBindingStorageTexelBufferUpdateAfterBind )
-      , descriptorBindingUpdateUnusedWhilePending( rhs.descriptorBindingUpdateUnusedWhilePending )
-      , descriptorBindingPartiallyBound( rhs.descriptorBindingPartiallyBound )
-      , descriptorBindingVariableDescriptorCount( rhs.descriptorBindingVariableDescriptorCount )
-      , runtimeDescriptorArray( rhs.runtimeDescriptorArray )
-    {}
-
     PhysicalDeviceDescriptorIndexingFeatures & operator=( PhysicalDeviceDescriptorIndexingFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceDescriptorIndexingFeatures ) - offsetof( PhysicalDeviceDescriptorIndexingFeatures, pNext ) );
@@ -47539,33 +47346,6 @@
       , maxDescriptorSetUpdateAfterBindInputAttachments( maxDescriptorSetUpdateAfterBindInputAttachments_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceDescriptorIndexingProperties( PhysicalDeviceDescriptorIndexingProperties const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , maxUpdateAfterBindDescriptorsInAllPools( rhs.maxUpdateAfterBindDescriptorsInAllPools )
-      , shaderUniformBufferArrayNonUniformIndexingNative( rhs.shaderUniformBufferArrayNonUniformIndexingNative )
-      , shaderSampledImageArrayNonUniformIndexingNative( rhs.shaderSampledImageArrayNonUniformIndexingNative )
-      , shaderStorageBufferArrayNonUniformIndexingNative( rhs.shaderStorageBufferArrayNonUniformIndexingNative )
-      , shaderStorageImageArrayNonUniformIndexingNative( rhs.shaderStorageImageArrayNonUniformIndexingNative )
-      , shaderInputAttachmentArrayNonUniformIndexingNative( rhs.shaderInputAttachmentArrayNonUniformIndexingNative )
-      , robustBufferAccessUpdateAfterBind( rhs.robustBufferAccessUpdateAfterBind )
-      , quadDivergentImplicitLod( rhs.quadDivergentImplicitLod )
-      , maxPerStageDescriptorUpdateAfterBindSamplers( rhs.maxPerStageDescriptorUpdateAfterBindSamplers )
-      , maxPerStageDescriptorUpdateAfterBindUniformBuffers( rhs.maxPerStageDescriptorUpdateAfterBindUniformBuffers )
-      , maxPerStageDescriptorUpdateAfterBindStorageBuffers( rhs.maxPerStageDescriptorUpdateAfterBindStorageBuffers )
-      , maxPerStageDescriptorUpdateAfterBindSampledImages( rhs.maxPerStageDescriptorUpdateAfterBindSampledImages )
-      , maxPerStageDescriptorUpdateAfterBindStorageImages( rhs.maxPerStageDescriptorUpdateAfterBindStorageImages )
-      , maxPerStageDescriptorUpdateAfterBindInputAttachments( rhs.maxPerStageDescriptorUpdateAfterBindInputAttachments )
-      , maxPerStageUpdateAfterBindResources( rhs.maxPerStageUpdateAfterBindResources )
-      , maxDescriptorSetUpdateAfterBindSamplers( rhs.maxDescriptorSetUpdateAfterBindSamplers )
-      , maxDescriptorSetUpdateAfterBindUniformBuffers( rhs.maxDescriptorSetUpdateAfterBindUniformBuffers )
-      , maxDescriptorSetUpdateAfterBindUniformBuffersDynamic( rhs.maxDescriptorSetUpdateAfterBindUniformBuffersDynamic )
-      , maxDescriptorSetUpdateAfterBindStorageBuffers( rhs.maxDescriptorSetUpdateAfterBindStorageBuffers )
-      , maxDescriptorSetUpdateAfterBindStorageBuffersDynamic( rhs.maxDescriptorSetUpdateAfterBindStorageBuffersDynamic )
-      , maxDescriptorSetUpdateAfterBindSampledImages( rhs.maxDescriptorSetUpdateAfterBindSampledImages )
-      , maxDescriptorSetUpdateAfterBindStorageImages( rhs.maxDescriptorSetUpdateAfterBindStorageImages )
-      , maxDescriptorSetUpdateAfterBindInputAttachments( rhs.maxDescriptorSetUpdateAfterBindInputAttachments )
-    {}
-
     PhysicalDeviceDescriptorIndexingProperties & operator=( PhysicalDeviceDescriptorIndexingProperties const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceDescriptorIndexingProperties ) - offsetof( PhysicalDeviceDescriptorIndexingProperties, pNext ) );
@@ -47661,17 +47441,239 @@
   static_assert( sizeof( PhysicalDeviceDescriptorIndexingProperties ) == sizeof( VkPhysicalDeviceDescriptorIndexingProperties ), "struct and wrapper have different size!" );
   static_assert( std::is_standard_layout<PhysicalDeviceDescriptorIndexingProperties>::value, "struct wrapper is not a standard layout!" );
 
+  struct PhysicalDeviceDeviceGeneratedCommandsFeaturesNV
+  {
+    VULKAN_HPP_CONSTEXPR PhysicalDeviceDeviceGeneratedCommandsFeaturesNV( VULKAN_HPP_NAMESPACE::Bool32 deviceGeneratedCommands_ = {} ) VULKAN_HPP_NOEXCEPT
+      : deviceGeneratedCommands( deviceGeneratedCommands_ )
+    {}
+
+    PhysicalDeviceDeviceGeneratedCommandsFeaturesNV & operator=( PhysicalDeviceDeviceGeneratedCommandsFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceDeviceGeneratedCommandsFeaturesNV ) - offsetof( PhysicalDeviceDeviceGeneratedCommandsFeaturesNV, pNext ) );
+      return *this;
+    }
+
+    PhysicalDeviceDeviceGeneratedCommandsFeaturesNV( VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    PhysicalDeviceDeviceGeneratedCommandsFeaturesNV& operator=( VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceDeviceGeneratedCommandsFeaturesNV const *>(&rhs);
+      return *this;
+    }
+
+    PhysicalDeviceDeviceGeneratedCommandsFeaturesNV & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pNext = pNext_;
+      return *this;
+    }
+
+    PhysicalDeviceDeviceGeneratedCommandsFeaturesNV & setDeviceGeneratedCommands( VULKAN_HPP_NAMESPACE::Bool32 deviceGeneratedCommands_ ) VULKAN_HPP_NOEXCEPT
+    {
+      deviceGeneratedCommands = deviceGeneratedCommands_;
+      return *this;
+    }
+
+    operator VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV*>( this );
+    }
+
+    operator VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV*>( this );
+    }
+
+#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
+    auto operator<=>( PhysicalDeviceDeviceGeneratedCommandsFeaturesNV const& ) const = default;
+#else
+    bool operator==( PhysicalDeviceDeviceGeneratedCommandsFeaturesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ( sType == rhs.sType )
+          && ( pNext == rhs.pNext )
+          && ( deviceGeneratedCommands == rhs.deviceGeneratedCommands );
+    }
+
+    bool operator!=( PhysicalDeviceDeviceGeneratedCommandsFeaturesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return !operator==( rhs );
+    }
+#endif
+
+  public:
+    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceDeviceGeneratedCommandsFeaturesNV;
+    void* pNext = {};
+    VULKAN_HPP_NAMESPACE::Bool32 deviceGeneratedCommands = {};
+  };
+  static_assert( sizeof( PhysicalDeviceDeviceGeneratedCommandsFeaturesNV ) == sizeof( VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<PhysicalDeviceDeviceGeneratedCommandsFeaturesNV>::value, "struct wrapper is not a standard layout!" );
+
+  struct PhysicalDeviceDeviceGeneratedCommandsPropertiesNV
+  {
+    VULKAN_HPP_CONSTEXPR PhysicalDeviceDeviceGeneratedCommandsPropertiesNV( uint32_t maxGraphicsShaderGroupCount_ = {},
+                                                                            uint32_t maxIndirectSequenceCount_ = {},
+                                                                            uint32_t maxIndirectCommandsTokenCount_ = {},
+                                                                            uint32_t maxIndirectCommandsStreamCount_ = {},
+                                                                            uint32_t maxIndirectCommandsTokenOffset_ = {},
+                                                                            uint32_t maxIndirectCommandsStreamStride_ = {},
+                                                                            uint32_t minSequencesCountBufferOffsetAlignment_ = {},
+                                                                            uint32_t minSequencesIndexBufferOffsetAlignment_ = {},
+                                                                            uint32_t minIndirectCommandsBufferOffsetAlignment_ = {} ) VULKAN_HPP_NOEXCEPT
+      : maxGraphicsShaderGroupCount( maxGraphicsShaderGroupCount_ )
+      , maxIndirectSequenceCount( maxIndirectSequenceCount_ )
+      , maxIndirectCommandsTokenCount( maxIndirectCommandsTokenCount_ )
+      , maxIndirectCommandsStreamCount( maxIndirectCommandsStreamCount_ )
+      , maxIndirectCommandsTokenOffset( maxIndirectCommandsTokenOffset_ )
+      , maxIndirectCommandsStreamStride( maxIndirectCommandsStreamStride_ )
+      , minSequencesCountBufferOffsetAlignment( minSequencesCountBufferOffsetAlignment_ )
+      , minSequencesIndexBufferOffsetAlignment( minSequencesIndexBufferOffsetAlignment_ )
+      , minIndirectCommandsBufferOffsetAlignment( minIndirectCommandsBufferOffsetAlignment_ )
+    {}
+
+    PhysicalDeviceDeviceGeneratedCommandsPropertiesNV & operator=( PhysicalDeviceDeviceGeneratedCommandsPropertiesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceDeviceGeneratedCommandsPropertiesNV ) - offsetof( PhysicalDeviceDeviceGeneratedCommandsPropertiesNV, pNext ) );
+      return *this;
+    }
+
+    PhysicalDeviceDeviceGeneratedCommandsPropertiesNV( VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    PhysicalDeviceDeviceGeneratedCommandsPropertiesNV& operator=( VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceDeviceGeneratedCommandsPropertiesNV const *>(&rhs);
+      return *this;
+    }
+
+    operator VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV*>( this );
+    }
+
+    operator VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV*>( this );
+    }
+
+#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
+    auto operator<=>( PhysicalDeviceDeviceGeneratedCommandsPropertiesNV const& ) const = default;
+#else
+    bool operator==( PhysicalDeviceDeviceGeneratedCommandsPropertiesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ( sType == rhs.sType )
+          && ( pNext == rhs.pNext )
+          && ( maxGraphicsShaderGroupCount == rhs.maxGraphicsShaderGroupCount )
+          && ( maxIndirectSequenceCount == rhs.maxIndirectSequenceCount )
+          && ( maxIndirectCommandsTokenCount == rhs.maxIndirectCommandsTokenCount )
+          && ( maxIndirectCommandsStreamCount == rhs.maxIndirectCommandsStreamCount )
+          && ( maxIndirectCommandsTokenOffset == rhs.maxIndirectCommandsTokenOffset )
+          && ( maxIndirectCommandsStreamStride == rhs.maxIndirectCommandsStreamStride )
+          && ( minSequencesCountBufferOffsetAlignment == rhs.minSequencesCountBufferOffsetAlignment )
+          && ( minSequencesIndexBufferOffsetAlignment == rhs.minSequencesIndexBufferOffsetAlignment )
+          && ( minIndirectCommandsBufferOffsetAlignment == rhs.minIndirectCommandsBufferOffsetAlignment );
+    }
+
+    bool operator!=( PhysicalDeviceDeviceGeneratedCommandsPropertiesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return !operator==( rhs );
+    }
+#endif
+
+  public:
+    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceDeviceGeneratedCommandsPropertiesNV;
+    void* pNext = {};
+    uint32_t maxGraphicsShaderGroupCount = {};
+    uint32_t maxIndirectSequenceCount = {};
+    uint32_t maxIndirectCommandsTokenCount = {};
+    uint32_t maxIndirectCommandsStreamCount = {};
+    uint32_t maxIndirectCommandsTokenOffset = {};
+    uint32_t maxIndirectCommandsStreamStride = {};
+    uint32_t minSequencesCountBufferOffsetAlignment = {};
+    uint32_t minSequencesIndexBufferOffsetAlignment = {};
+    uint32_t minIndirectCommandsBufferOffsetAlignment = {};
+  };
+  static_assert( sizeof( PhysicalDeviceDeviceGeneratedCommandsPropertiesNV ) == sizeof( VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<PhysicalDeviceDeviceGeneratedCommandsPropertiesNV>::value, "struct wrapper is not a standard layout!" );
+
+  struct PhysicalDeviceDiagnosticsConfigFeaturesNV
+  {
+    VULKAN_HPP_CONSTEXPR PhysicalDeviceDiagnosticsConfigFeaturesNV( VULKAN_HPP_NAMESPACE::Bool32 diagnosticsConfig_ = {} ) VULKAN_HPP_NOEXCEPT
+      : diagnosticsConfig( diagnosticsConfig_ )
+    {}
+
+    PhysicalDeviceDiagnosticsConfigFeaturesNV & operator=( PhysicalDeviceDiagnosticsConfigFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceDiagnosticsConfigFeaturesNV ) - offsetof( PhysicalDeviceDiagnosticsConfigFeaturesNV, pNext ) );
+      return *this;
+    }
+
+    PhysicalDeviceDiagnosticsConfigFeaturesNV( VkPhysicalDeviceDiagnosticsConfigFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    PhysicalDeviceDiagnosticsConfigFeaturesNV& operator=( VkPhysicalDeviceDiagnosticsConfigFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceDiagnosticsConfigFeaturesNV const *>(&rhs);
+      return *this;
+    }
+
+    PhysicalDeviceDiagnosticsConfigFeaturesNV & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pNext = pNext_;
+      return *this;
+    }
+
+    PhysicalDeviceDiagnosticsConfigFeaturesNV & setDiagnosticsConfig( VULKAN_HPP_NAMESPACE::Bool32 diagnosticsConfig_ ) VULKAN_HPP_NOEXCEPT
+    {
+      diagnosticsConfig = diagnosticsConfig_;
+      return *this;
+    }
+
+    operator VkPhysicalDeviceDiagnosticsConfigFeaturesNV const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkPhysicalDeviceDiagnosticsConfigFeaturesNV*>( this );
+    }
+
+    operator VkPhysicalDeviceDiagnosticsConfigFeaturesNV &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkPhysicalDeviceDiagnosticsConfigFeaturesNV*>( this );
+    }
+
+#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
+    auto operator<=>( PhysicalDeviceDiagnosticsConfigFeaturesNV const& ) const = default;
+#else
+    bool operator==( PhysicalDeviceDiagnosticsConfigFeaturesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ( sType == rhs.sType )
+          && ( pNext == rhs.pNext )
+          && ( diagnosticsConfig == rhs.diagnosticsConfig );
+    }
+
+    bool operator!=( PhysicalDeviceDiagnosticsConfigFeaturesNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return !operator==( rhs );
+    }
+#endif
+
+  public:
+    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceDiagnosticsConfigFeaturesNV;
+    void* pNext = {};
+    VULKAN_HPP_NAMESPACE::Bool32 diagnosticsConfig = {};
+  };
+  static_assert( sizeof( PhysicalDeviceDiagnosticsConfigFeaturesNV ) == sizeof( VkPhysicalDeviceDiagnosticsConfigFeaturesNV ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<PhysicalDeviceDiagnosticsConfigFeaturesNV>::value, "struct wrapper is not a standard layout!" );
+
   struct PhysicalDeviceDiscardRectanglePropertiesEXT
   {
     VULKAN_HPP_CONSTEXPR PhysicalDeviceDiscardRectanglePropertiesEXT( uint32_t maxDiscardRectangles_ = {} ) VULKAN_HPP_NOEXCEPT
       : maxDiscardRectangles( maxDiscardRectangles_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceDiscardRectanglePropertiesEXT( PhysicalDeviceDiscardRectanglePropertiesEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , maxDiscardRectangles( rhs.maxDiscardRectangles )
-    {}
-
     PhysicalDeviceDiscardRectanglePropertiesEXT & operator=( PhysicalDeviceDiscardRectanglePropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceDiscardRectanglePropertiesEXT ) - offsetof( PhysicalDeviceDiscardRectanglePropertiesEXT, pNext ) );
@@ -47730,24 +47732,10 @@
                                                             std::array<char,VK_MAX_DRIVER_INFO_SIZE> const& driverInfo_ = {},
                                                             VULKAN_HPP_NAMESPACE::ConformanceVersion conformanceVersion_ = {} ) VULKAN_HPP_NOEXCEPT
       : driverID( driverID_ )
-      , driverName{}
-      , driverInfo{}
+      , driverName( driverName_ )
+      , driverInfo( driverInfo_ )
       , conformanceVersion( conformanceVersion_ )
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DRIVER_NAME_SIZE>::copy( driverName, driverName_ );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DRIVER_INFO_SIZE>::copy( driverInfo, driverInfo_ );
-    }
-
-    VULKAN_HPP_CONSTEXPR_14 PhysicalDeviceDriverProperties( PhysicalDeviceDriverProperties const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , driverID( rhs.driverID )
-      , driverName{}
-      , driverInfo{}
-      , conformanceVersion( rhs.conformanceVersion )
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DRIVER_NAME_SIZE>::copy( driverName, rhs.driverName );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DRIVER_INFO_SIZE>::copy( driverInfo, rhs.driverInfo );
-    }
+    {}
 
     PhysicalDeviceDriverProperties & operator=( PhysicalDeviceDriverProperties const & rhs ) VULKAN_HPP_NOEXCEPT
     {
@@ -47784,8 +47772,8 @@
       return ( sType == rhs.sType )
           && ( pNext == rhs.pNext )
           && ( driverID == rhs.driverID )
-          && ( memcmp( driverName, rhs.driverName, VK_MAX_DRIVER_NAME_SIZE * sizeof( char ) ) == 0 )
-          && ( memcmp( driverInfo, rhs.driverInfo, VK_MAX_DRIVER_INFO_SIZE * sizeof( char ) ) == 0 )
+          && ( driverName == rhs.driverName )
+          && ( driverInfo == rhs.driverInfo )
           && ( conformanceVersion == rhs.conformanceVersion );
     }
 
@@ -47799,8 +47787,8 @@
     const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceDriverProperties;
     void* pNext = {};
     VULKAN_HPP_NAMESPACE::DriverId driverID = VULKAN_HPP_NAMESPACE::DriverId::eAmdProprietary;
-    char driverName[VK_MAX_DRIVER_NAME_SIZE] = {};
-    char driverInfo[VK_MAX_DRIVER_INFO_SIZE] = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<char, VK_MAX_DRIVER_NAME_SIZE> driverName = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<char, VK_MAX_DRIVER_INFO_SIZE> driverInfo = {};
     VULKAN_HPP_NAMESPACE::ConformanceVersion conformanceVersion = {};
   };
   static_assert( sizeof( PhysicalDeviceDriverProperties ) == sizeof( VkPhysicalDeviceDriverProperties ), "struct and wrapper have different size!" );
@@ -47812,11 +47800,6 @@
       : exclusiveScissor( exclusiveScissor_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceExclusiveScissorFeaturesNV( PhysicalDeviceExclusiveScissorFeaturesNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , exclusiveScissor( rhs.exclusiveScissor )
-    {}
-
     PhysicalDeviceExclusiveScissorFeaturesNV & operator=( PhysicalDeviceExclusiveScissorFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceExclusiveScissorFeaturesNV ) - offsetof( PhysicalDeviceExclusiveScissorFeaturesNV, pNext ) );
@@ -47890,13 +47873,6 @@
       , handleType( handleType_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceExternalBufferInfo( PhysicalDeviceExternalBufferInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , usage( rhs.usage )
-      , handleType( rhs.handleType )
-    {}
-
     PhysicalDeviceExternalBufferInfo & operator=( PhysicalDeviceExternalBufferInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceExternalBufferInfo ) - offsetof( PhysicalDeviceExternalBufferInfo, pNext ) );
@@ -47982,11 +47958,6 @@
       : handleType( handleType_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceExternalFenceInfo( PhysicalDeviceExternalFenceInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , handleType( rhs.handleType )
-    {}
-
     PhysicalDeviceExternalFenceInfo & operator=( PhysicalDeviceExternalFenceInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceExternalFenceInfo ) - offsetof( PhysicalDeviceExternalFenceInfo, pNext ) );
@@ -48056,11 +48027,6 @@
       : handleType( handleType_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceExternalImageFormatInfo( PhysicalDeviceExternalImageFormatInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , handleType( rhs.handleType )
-    {}
-
     PhysicalDeviceExternalImageFormatInfo & operator=( PhysicalDeviceExternalImageFormatInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceExternalImageFormatInfo ) - offsetof( PhysicalDeviceExternalImageFormatInfo, pNext ) );
@@ -48130,11 +48096,6 @@
       : minImportedHostPointerAlignment( minImportedHostPointerAlignment_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceExternalMemoryHostPropertiesEXT( PhysicalDeviceExternalMemoryHostPropertiesEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , minImportedHostPointerAlignment( rhs.minImportedHostPointerAlignment )
-    {}
-
     PhysicalDeviceExternalMemoryHostPropertiesEXT & operator=( PhysicalDeviceExternalMemoryHostPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceExternalMemoryHostPropertiesEXT ) - offsetof( PhysicalDeviceExternalMemoryHostPropertiesEXT, pNext ) );
@@ -48192,11 +48153,6 @@
       : handleType( handleType_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceExternalSemaphoreInfo( PhysicalDeviceExternalSemaphoreInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , handleType( rhs.handleType )
-    {}
-
     PhysicalDeviceExternalSemaphoreInfo & operator=( PhysicalDeviceExternalSemaphoreInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceExternalSemaphoreInfo ) - offsetof( PhysicalDeviceExternalSemaphoreInfo, pNext ) );
@@ -48266,11 +48222,6 @@
       : features( features_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceFeatures2( PhysicalDeviceFeatures2 const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , features( rhs.features )
-    {}
-
     PhysicalDeviceFeatures2 & operator=( PhysicalDeviceFeatures2 const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceFeatures2 ) - offsetof( PhysicalDeviceFeatures2, pNext ) );
@@ -48372,27 +48323,6 @@
       , shaderRoundingModeRTZFloat64( shaderRoundingModeRTZFloat64_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceFloatControlsProperties( PhysicalDeviceFloatControlsProperties const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , denormBehaviorIndependence( rhs.denormBehaviorIndependence )
-      , roundingModeIndependence( rhs.roundingModeIndependence )
-      , shaderSignedZeroInfNanPreserveFloat16( rhs.shaderSignedZeroInfNanPreserveFloat16 )
-      , shaderSignedZeroInfNanPreserveFloat32( rhs.shaderSignedZeroInfNanPreserveFloat32 )
-      , shaderSignedZeroInfNanPreserveFloat64( rhs.shaderSignedZeroInfNanPreserveFloat64 )
-      , shaderDenormPreserveFloat16( rhs.shaderDenormPreserveFloat16 )
-      , shaderDenormPreserveFloat32( rhs.shaderDenormPreserveFloat32 )
-      , shaderDenormPreserveFloat64( rhs.shaderDenormPreserveFloat64 )
-      , shaderDenormFlushToZeroFloat16( rhs.shaderDenormFlushToZeroFloat16 )
-      , shaderDenormFlushToZeroFloat32( rhs.shaderDenormFlushToZeroFloat32 )
-      , shaderDenormFlushToZeroFloat64( rhs.shaderDenormFlushToZeroFloat64 )
-      , shaderRoundingModeRTEFloat16( rhs.shaderRoundingModeRTEFloat16 )
-      , shaderRoundingModeRTEFloat32( rhs.shaderRoundingModeRTEFloat32 )
-      , shaderRoundingModeRTEFloat64( rhs.shaderRoundingModeRTEFloat64 )
-      , shaderRoundingModeRTZFloat16( rhs.shaderRoundingModeRTZFloat16 )
-      , shaderRoundingModeRTZFloat32( rhs.shaderRoundingModeRTZFloat32 )
-      , shaderRoundingModeRTZFloat64( rhs.shaderRoundingModeRTZFloat64 )
-    {}
-
     PhysicalDeviceFloatControlsProperties & operator=( PhysicalDeviceFloatControlsProperties const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceFloatControlsProperties ) - offsetof( PhysicalDeviceFloatControlsProperties, pNext ) );
@@ -48486,13 +48416,6 @@
       , fragmentDensityMapNonSubsampledImages( fragmentDensityMapNonSubsampledImages_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceFragmentDensityMapFeaturesEXT( PhysicalDeviceFragmentDensityMapFeaturesEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , fragmentDensityMap( rhs.fragmentDensityMap )
-      , fragmentDensityMapDynamic( rhs.fragmentDensityMapDynamic )
-      , fragmentDensityMapNonSubsampledImages( rhs.fragmentDensityMapNonSubsampledImages )
-    {}
-
     PhysicalDeviceFragmentDensityMapFeaturesEXT & operator=( PhysicalDeviceFragmentDensityMapFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceFragmentDensityMapFeaturesEXT ) - offsetof( PhysicalDeviceFragmentDensityMapFeaturesEXT, pNext ) );
@@ -48558,13 +48481,6 @@
       , fragmentDensityInvocations( fragmentDensityInvocations_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceFragmentDensityMapPropertiesEXT( PhysicalDeviceFragmentDensityMapPropertiesEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , minFragmentDensityTexelSize( rhs.minFragmentDensityTexelSize )
-      , maxFragmentDensityTexelSize( rhs.maxFragmentDensityTexelSize )
-      , fragmentDensityInvocations( rhs.fragmentDensityInvocations )
-    {}
-
     PhysicalDeviceFragmentDensityMapPropertiesEXT & operator=( PhysicalDeviceFragmentDensityMapPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceFragmentDensityMapPropertiesEXT ) - offsetof( PhysicalDeviceFragmentDensityMapPropertiesEXT, pNext ) );
@@ -48626,11 +48542,6 @@
       : fragmentShaderBarycentric( fragmentShaderBarycentric_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceFragmentShaderBarycentricFeaturesNV( PhysicalDeviceFragmentShaderBarycentricFeaturesNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , fragmentShaderBarycentric( rhs.fragmentShaderBarycentric )
-    {}
-
     PhysicalDeviceFragmentShaderBarycentricFeaturesNV & operator=( PhysicalDeviceFragmentShaderBarycentricFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceFragmentShaderBarycentricFeaturesNV ) - offsetof( PhysicalDeviceFragmentShaderBarycentricFeaturesNV, pNext ) );
@@ -48704,13 +48615,6 @@
       , fragmentShaderShadingRateInterlock( fragmentShaderShadingRateInterlock_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceFragmentShaderInterlockFeaturesEXT( PhysicalDeviceFragmentShaderInterlockFeaturesEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , fragmentShaderSampleInterlock( rhs.fragmentShaderSampleInterlock )
-      , fragmentShaderPixelInterlock( rhs.fragmentShaderPixelInterlock )
-      , fragmentShaderShadingRateInterlock( rhs.fragmentShaderShadingRateInterlock )
-    {}
-
     PhysicalDeviceFragmentShaderInterlockFeaturesEXT & operator=( PhysicalDeviceFragmentShaderInterlockFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceFragmentShaderInterlockFeaturesEXT ) - offsetof( PhysicalDeviceFragmentShaderInterlockFeaturesEXT, pNext ) );
@@ -48796,20 +48700,9 @@
                                                            std::array<VULKAN_HPP_NAMESPACE::PhysicalDevice,VK_MAX_DEVICE_GROUP_SIZE> const& physicalDevices_ = {},
                                                            VULKAN_HPP_NAMESPACE::Bool32 subsetAllocation_ = {} ) VULKAN_HPP_NOEXCEPT
       : physicalDeviceCount( physicalDeviceCount_ )
-      , physicalDevices{}
+      , physicalDevices( physicalDevices_ )
       , subsetAllocation( subsetAllocation_ )
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<VULKAN_HPP_NAMESPACE::PhysicalDevice,VK_MAX_DEVICE_GROUP_SIZE>::copy( physicalDevices, physicalDevices_ );
-    }
-
-    VULKAN_HPP_CONSTEXPR_14 PhysicalDeviceGroupProperties( PhysicalDeviceGroupProperties const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , physicalDeviceCount( rhs.physicalDeviceCount )
-      , physicalDevices{}
-      , subsetAllocation( rhs.subsetAllocation )
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<VULKAN_HPP_NAMESPACE::PhysicalDevice,VK_MAX_DEVICE_GROUP_SIZE>::copy( physicalDevices, rhs.physicalDevices );
-    }
+    {}
 
     PhysicalDeviceGroupProperties & operator=( PhysicalDeviceGroupProperties const & rhs ) VULKAN_HPP_NOEXCEPT
     {
@@ -48846,7 +48739,7 @@
       return ( sType == rhs.sType )
           && ( pNext == rhs.pNext )
           && ( physicalDeviceCount == rhs.physicalDeviceCount )
-          && ( memcmp( physicalDevices, rhs.physicalDevices, std::min<uint32_t>( VK_MAX_DEVICE_GROUP_SIZE, physicalDeviceCount ) * sizeof( VULKAN_HPP_NAMESPACE::PhysicalDevice ) ) == 0 )
+          && ( physicalDevices == rhs.physicalDevices )
           && ( subsetAllocation == rhs.subsetAllocation );
     }
 
@@ -48860,7 +48753,7 @@
     const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceGroupProperties;
     void* pNext = {};
     uint32_t physicalDeviceCount = {};
-    VULKAN_HPP_NAMESPACE::PhysicalDevice physicalDevices[VK_MAX_DEVICE_GROUP_SIZE] = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<VULKAN_HPP_NAMESPACE::PhysicalDevice, VK_MAX_DEVICE_GROUP_SIZE> physicalDevices = {};
     VULKAN_HPP_NAMESPACE::Bool32 subsetAllocation = {};
   };
   static_assert( sizeof( PhysicalDeviceGroupProperties ) == sizeof( VkPhysicalDeviceGroupProperties ), "struct and wrapper have different size!" );
@@ -48872,11 +48765,6 @@
       : hostQueryReset( hostQueryReset_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceHostQueryResetFeatures( PhysicalDeviceHostQueryResetFeatures const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , hostQueryReset( rhs.hostQueryReset )
-    {}
-
     PhysicalDeviceHostQueryResetFeatures & operator=( PhysicalDeviceHostQueryResetFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceHostQueryResetFeatures ) - offsetof( PhysicalDeviceHostQueryResetFeatures, pNext ) );
@@ -48947,29 +48835,12 @@
                                                         std::array<uint8_t,VK_LUID_SIZE> const& deviceLUID_ = {},
                                                         uint32_t deviceNodeMask_ = {},
                                                         VULKAN_HPP_NAMESPACE::Bool32 deviceLUIDValid_ = {} ) VULKAN_HPP_NOEXCEPT
-      : deviceUUID{}
-      , driverUUID{}
-      , deviceLUID{}
+      : deviceUUID( deviceUUID_ )
+      , driverUUID( driverUUID_ )
+      , deviceLUID( deviceLUID_ )
       , deviceNodeMask( deviceNodeMask_ )
       , deviceLUIDValid( deviceLUIDValid_ )
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint8_t,VK_UUID_SIZE>::copy( deviceUUID, deviceUUID_ );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint8_t,VK_UUID_SIZE>::copy( driverUUID, driverUUID_ );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint8_t,VK_LUID_SIZE>::copy( deviceLUID, deviceLUID_ );
-    }
-
-    VULKAN_HPP_CONSTEXPR_14 PhysicalDeviceIDProperties( PhysicalDeviceIDProperties const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , deviceUUID{}
-      , driverUUID{}
-      , deviceLUID{}
-      , deviceNodeMask( rhs.deviceNodeMask )
-      , deviceLUIDValid( rhs.deviceLUIDValid )
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint8_t,VK_UUID_SIZE>::copy( deviceUUID, rhs.deviceUUID );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint8_t,VK_UUID_SIZE>::copy( driverUUID, rhs.driverUUID );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint8_t,VK_LUID_SIZE>::copy( deviceLUID, rhs.deviceLUID );
-    }
+    {}
 
     PhysicalDeviceIDProperties & operator=( PhysicalDeviceIDProperties const & rhs ) VULKAN_HPP_NOEXCEPT
     {
@@ -49005,9 +48876,9 @@
     {
       return ( sType == rhs.sType )
           && ( pNext == rhs.pNext )
-          && ( memcmp( deviceUUID, rhs.deviceUUID, VK_UUID_SIZE * sizeof( uint8_t ) ) == 0 )
-          && ( memcmp( driverUUID, rhs.driverUUID, VK_UUID_SIZE * sizeof( uint8_t ) ) == 0 )
-          && ( memcmp( deviceLUID, rhs.deviceLUID, VK_LUID_SIZE * sizeof( uint8_t ) ) == 0 )
+          && ( deviceUUID == rhs.deviceUUID )
+          && ( driverUUID == rhs.driverUUID )
+          && ( deviceLUID == rhs.deviceLUID )
           && ( deviceNodeMask == rhs.deviceNodeMask )
           && ( deviceLUIDValid == rhs.deviceLUIDValid );
     }
@@ -49021,9 +48892,9 @@
   public:
     const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceIdProperties;
     void* pNext = {};
-    uint8_t deviceUUID[VK_UUID_SIZE] = {};
-    uint8_t driverUUID[VK_UUID_SIZE] = {};
-    uint8_t deviceLUID[VK_LUID_SIZE] = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<uint8_t, VK_UUID_SIZE> deviceUUID = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<uint8_t, VK_UUID_SIZE> driverUUID = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<uint8_t, VK_LUID_SIZE> deviceLUID = {};
     uint32_t deviceNodeMask = {};
     VULKAN_HPP_NAMESPACE::Bool32 deviceLUIDValid = {};
   };
@@ -49042,14 +48913,6 @@
       , pQueueFamilyIndices( pQueueFamilyIndices_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceImageDrmFormatModifierInfoEXT( PhysicalDeviceImageDrmFormatModifierInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , drmFormatModifier( rhs.drmFormatModifier )
-      , sharingMode( rhs.sharingMode )
-      , queueFamilyIndexCount( rhs.queueFamilyIndexCount )
-      , pQueueFamilyIndices( rhs.pQueueFamilyIndices )
-    {}
-
     PhysicalDeviceImageDrmFormatModifierInfoEXT & operator=( PhysicalDeviceImageDrmFormatModifierInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceImageDrmFormatModifierInfoEXT ) - offsetof( PhysicalDeviceImageDrmFormatModifierInfoEXT, pNext ) );
@@ -49151,15 +49014,6 @@
       , flags( flags_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceImageFormatInfo2( PhysicalDeviceImageFormatInfo2 const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , format( rhs.format )
-      , type( rhs.type )
-      , tiling( rhs.tiling )
-      , usage( rhs.usage )
-      , flags( rhs.flags )
-    {}
-
     PhysicalDeviceImageFormatInfo2 & operator=( PhysicalDeviceImageFormatInfo2 const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceImageFormatInfo2 ) - offsetof( PhysicalDeviceImageFormatInfo2, pNext ) );
@@ -49261,11 +49115,6 @@
       : imageViewType( imageViewType_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceImageViewImageFormatInfoEXT( PhysicalDeviceImageViewImageFormatInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , imageViewType( rhs.imageViewType )
-    {}
-
     PhysicalDeviceImageViewImageFormatInfoEXT & operator=( PhysicalDeviceImageViewImageFormatInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceImageViewImageFormatInfoEXT ) - offsetof( PhysicalDeviceImageViewImageFormatInfoEXT, pNext ) );
@@ -49335,11 +49184,6 @@
       : imagelessFramebuffer( imagelessFramebuffer_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceImagelessFramebufferFeatures( PhysicalDeviceImagelessFramebufferFeatures const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , imagelessFramebuffer( rhs.imagelessFramebuffer )
-    {}
-
     PhysicalDeviceImagelessFramebufferFeatures & operator=( PhysicalDeviceImagelessFramebufferFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceImagelessFramebufferFeatures ) - offsetof( PhysicalDeviceImagelessFramebufferFeatures, pNext ) );
@@ -49409,11 +49253,6 @@
       : indexTypeUint8( indexTypeUint8_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceIndexTypeUint8FeaturesEXT( PhysicalDeviceIndexTypeUint8FeaturesEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , indexTypeUint8( rhs.indexTypeUint8 )
-    {}
-
     PhysicalDeviceIndexTypeUint8FeaturesEXT & operator=( PhysicalDeviceIndexTypeUint8FeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceIndexTypeUint8FeaturesEXT ) - offsetof( PhysicalDeviceIndexTypeUint8FeaturesEXT, pNext ) );
@@ -49485,12 +49324,6 @@
       , descriptorBindingInlineUniformBlockUpdateAfterBind( descriptorBindingInlineUniformBlockUpdateAfterBind_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceInlineUniformBlockFeaturesEXT( PhysicalDeviceInlineUniformBlockFeaturesEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , inlineUniformBlock( rhs.inlineUniformBlock )
-      , descriptorBindingInlineUniformBlockUpdateAfterBind( rhs.descriptorBindingInlineUniformBlockUpdateAfterBind )
-    {}
-
     PhysicalDeviceInlineUniformBlockFeaturesEXT & operator=( PhysicalDeviceInlineUniformBlockFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceInlineUniformBlockFeaturesEXT ) - offsetof( PhysicalDeviceInlineUniformBlockFeaturesEXT, pNext ) );
@@ -49576,15 +49409,6 @@
       , maxDescriptorSetUpdateAfterBindInlineUniformBlocks( maxDescriptorSetUpdateAfterBindInlineUniformBlocks_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceInlineUniformBlockPropertiesEXT( PhysicalDeviceInlineUniformBlockPropertiesEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , maxInlineUniformBlockSize( rhs.maxInlineUniformBlockSize )
-      , maxPerStageDescriptorInlineUniformBlocks( rhs.maxPerStageDescriptorInlineUniformBlocks )
-      , maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks( rhs.maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks )
-      , maxDescriptorSetInlineUniformBlocks( rhs.maxDescriptorSetInlineUniformBlocks )
-      , maxDescriptorSetUpdateAfterBindInlineUniformBlocks( rhs.maxDescriptorSetUpdateAfterBindInlineUniformBlocks )
-    {}
-
     PhysicalDeviceInlineUniformBlockPropertiesEXT & operator=( PhysicalDeviceInlineUniformBlockPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceInlineUniformBlockPropertiesEXT ) - offsetof( PhysicalDeviceInlineUniformBlockPropertiesEXT, pNext ) );
@@ -49804,9 +49628,9 @@
       , maxFragmentDualSrcAttachments( maxFragmentDualSrcAttachments_ )
       , maxFragmentCombinedOutputResources( maxFragmentCombinedOutputResources_ )
       , maxComputeSharedMemorySize( maxComputeSharedMemorySize_ )
-      , maxComputeWorkGroupCount{}
+      , maxComputeWorkGroupCount( maxComputeWorkGroupCount_ )
       , maxComputeWorkGroupInvocations( maxComputeWorkGroupInvocations_ )
-      , maxComputeWorkGroupSize{}
+      , maxComputeWorkGroupSize( maxComputeWorkGroupSize_ )
       , subPixelPrecisionBits( subPixelPrecisionBits_ )
       , subTexelPrecisionBits( subTexelPrecisionBits_ )
       , mipmapPrecisionBits( mipmapPrecisionBits_ )
@@ -49815,8 +49639,8 @@
       , maxSamplerLodBias( maxSamplerLodBias_ )
       , maxSamplerAnisotropy( maxSamplerAnisotropy_ )
       , maxViewports( maxViewports_ )
-      , maxViewportDimensions{}
-      , viewportBoundsRange{}
+      , maxViewportDimensions( maxViewportDimensions_ )
+      , viewportBoundsRange( viewportBoundsRange_ )
       , viewportSubPixelBits( viewportSubPixelBits_ )
       , minMemoryMapAlignment( minMemoryMapAlignment_ )
       , minTexelBufferOffsetAlignment( minTexelBufferOffsetAlignment_ )
@@ -49849,8 +49673,8 @@
       , maxCullDistances( maxCullDistances_ )
       , maxCombinedClipAndCullDistances( maxCombinedClipAndCullDistances_ )
       , discreteQueuePriorities( discreteQueuePriorities_ )
-      , pointSizeRange{}
-      , lineWidthRange{}
+      , pointSizeRange( pointSizeRange_ )
+      , lineWidthRange( lineWidthRange_ )
       , pointSizeGranularity( pointSizeGranularity_ )
       , lineWidthGranularity( lineWidthGranularity_ )
       , strictLines( strictLines_ )
@@ -49858,136 +49682,7 @@
       , optimalBufferCopyOffsetAlignment( optimalBufferCopyOffsetAlignment_ )
       , optimalBufferCopyRowPitchAlignment( optimalBufferCopyRowPitchAlignment_ )
       , nonCoherentAtomSize( nonCoherentAtomSize_ )
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint32_t,3>::copy( maxComputeWorkGroupCount, maxComputeWorkGroupCount_ );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint32_t,3>::copy( maxComputeWorkGroupSize, maxComputeWorkGroupSize_ );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint32_t,2>::copy( maxViewportDimensions, maxViewportDimensions_ );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<float,2>::copy( viewportBoundsRange, viewportBoundsRange_ );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<float,2>::copy( pointSizeRange, pointSizeRange_ );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<float,2>::copy( lineWidthRange, lineWidthRange_ );
-    }
-
-    VULKAN_HPP_CONSTEXPR_14 PhysicalDeviceLimits( PhysicalDeviceLimits const& rhs ) VULKAN_HPP_NOEXCEPT
-      : maxImageDimension1D( rhs.maxImageDimension1D )
-      , maxImageDimension2D( rhs.maxImageDimension2D )
-      , maxImageDimension3D( rhs.maxImageDimension3D )
-      , maxImageDimensionCube( rhs.maxImageDimensionCube )
-      , maxImageArrayLayers( rhs.maxImageArrayLayers )
-      , maxTexelBufferElements( rhs.maxTexelBufferElements )
-      , maxUniformBufferRange( rhs.maxUniformBufferRange )
-      , maxStorageBufferRange( rhs.maxStorageBufferRange )
-      , maxPushConstantsSize( rhs.maxPushConstantsSize )
-      , maxMemoryAllocationCount( rhs.maxMemoryAllocationCount )
-      , maxSamplerAllocationCount( rhs.maxSamplerAllocationCount )
-      , bufferImageGranularity( rhs.bufferImageGranularity )
-      , sparseAddressSpaceSize( rhs.sparseAddressSpaceSize )
-      , maxBoundDescriptorSets( rhs.maxBoundDescriptorSets )
-      , maxPerStageDescriptorSamplers( rhs.maxPerStageDescriptorSamplers )
-      , maxPerStageDescriptorUniformBuffers( rhs.maxPerStageDescriptorUniformBuffers )
-      , maxPerStageDescriptorStorageBuffers( rhs.maxPerStageDescriptorStorageBuffers )
-      , maxPerStageDescriptorSampledImages( rhs.maxPerStageDescriptorSampledImages )
-      , maxPerStageDescriptorStorageImages( rhs.maxPerStageDescriptorStorageImages )
-      , maxPerStageDescriptorInputAttachments( rhs.maxPerStageDescriptorInputAttachments )
-      , maxPerStageResources( rhs.maxPerStageResources )
-      , maxDescriptorSetSamplers( rhs.maxDescriptorSetSamplers )
-      , maxDescriptorSetUniformBuffers( rhs.maxDescriptorSetUniformBuffers )
-      , maxDescriptorSetUniformBuffersDynamic( rhs.maxDescriptorSetUniformBuffersDynamic )
-      , maxDescriptorSetStorageBuffers( rhs.maxDescriptorSetStorageBuffers )
-      , maxDescriptorSetStorageBuffersDynamic( rhs.maxDescriptorSetStorageBuffersDynamic )
-      , maxDescriptorSetSampledImages( rhs.maxDescriptorSetSampledImages )
-      , maxDescriptorSetStorageImages( rhs.maxDescriptorSetStorageImages )
-      , maxDescriptorSetInputAttachments( rhs.maxDescriptorSetInputAttachments )
-      , maxVertexInputAttributes( rhs.maxVertexInputAttributes )
-      , maxVertexInputBindings( rhs.maxVertexInputBindings )
-      , maxVertexInputAttributeOffset( rhs.maxVertexInputAttributeOffset )
-      , maxVertexInputBindingStride( rhs.maxVertexInputBindingStride )
-      , maxVertexOutputComponents( rhs.maxVertexOutputComponents )
-      , maxTessellationGenerationLevel( rhs.maxTessellationGenerationLevel )
-      , maxTessellationPatchSize( rhs.maxTessellationPatchSize )
-      , maxTessellationControlPerVertexInputComponents( rhs.maxTessellationControlPerVertexInputComponents )
-      , maxTessellationControlPerVertexOutputComponents( rhs.maxTessellationControlPerVertexOutputComponents )
-      , maxTessellationControlPerPatchOutputComponents( rhs.maxTessellationControlPerPatchOutputComponents )
-      , maxTessellationControlTotalOutputComponents( rhs.maxTessellationControlTotalOutputComponents )
-      , maxTessellationEvaluationInputComponents( rhs.maxTessellationEvaluationInputComponents )
-      , maxTessellationEvaluationOutputComponents( rhs.maxTessellationEvaluationOutputComponents )
-      , maxGeometryShaderInvocations( rhs.maxGeometryShaderInvocations )
-      , maxGeometryInputComponents( rhs.maxGeometryInputComponents )
-      , maxGeometryOutputComponents( rhs.maxGeometryOutputComponents )
-      , maxGeometryOutputVertices( rhs.maxGeometryOutputVertices )
-      , maxGeometryTotalOutputComponents( rhs.maxGeometryTotalOutputComponents )
-      , maxFragmentInputComponents( rhs.maxFragmentInputComponents )
-      , maxFragmentOutputAttachments( rhs.maxFragmentOutputAttachments )
-      , maxFragmentDualSrcAttachments( rhs.maxFragmentDualSrcAttachments )
-      , maxFragmentCombinedOutputResources( rhs.maxFragmentCombinedOutputResources )
-      , maxComputeSharedMemorySize( rhs.maxComputeSharedMemorySize )
-      , maxComputeWorkGroupCount{}
-      , maxComputeWorkGroupInvocations( rhs.maxComputeWorkGroupInvocations )
-      , maxComputeWorkGroupSize{}
-      , subPixelPrecisionBits( rhs.subPixelPrecisionBits )
-      , subTexelPrecisionBits( rhs.subTexelPrecisionBits )
-      , mipmapPrecisionBits( rhs.mipmapPrecisionBits )
-      , maxDrawIndexedIndexValue( rhs.maxDrawIndexedIndexValue )
-      , maxDrawIndirectCount( rhs.maxDrawIndirectCount )
-      , maxSamplerLodBias( rhs.maxSamplerLodBias )
-      , maxSamplerAnisotropy( rhs.maxSamplerAnisotropy )
-      , maxViewports( rhs.maxViewports )
-      , maxViewportDimensions{}
-      , viewportBoundsRange{}
-      , viewportSubPixelBits( rhs.viewportSubPixelBits )
-      , minMemoryMapAlignment( rhs.minMemoryMapAlignment )
-      , minTexelBufferOffsetAlignment( rhs.minTexelBufferOffsetAlignment )
-      , minUniformBufferOffsetAlignment( rhs.minUniformBufferOffsetAlignment )
-      , minStorageBufferOffsetAlignment( rhs.minStorageBufferOffsetAlignment )
-      , minTexelOffset( rhs.minTexelOffset )
-      , maxTexelOffset( rhs.maxTexelOffset )
-      , minTexelGatherOffset( rhs.minTexelGatherOffset )
-      , maxTexelGatherOffset( rhs.maxTexelGatherOffset )
-      , minInterpolationOffset( rhs.minInterpolationOffset )
-      , maxInterpolationOffset( rhs.maxInterpolationOffset )
-      , subPixelInterpolationOffsetBits( rhs.subPixelInterpolationOffsetBits )
-      , maxFramebufferWidth( rhs.maxFramebufferWidth )
-      , maxFramebufferHeight( rhs.maxFramebufferHeight )
-      , maxFramebufferLayers( rhs.maxFramebufferLayers )
-      , framebufferColorSampleCounts( rhs.framebufferColorSampleCounts )
-      , framebufferDepthSampleCounts( rhs.framebufferDepthSampleCounts )
-      , framebufferStencilSampleCounts( rhs.framebufferStencilSampleCounts )
-      , framebufferNoAttachmentsSampleCounts( rhs.framebufferNoAttachmentsSampleCounts )
-      , maxColorAttachments( rhs.maxColorAttachments )
-      , sampledImageColorSampleCounts( rhs.sampledImageColorSampleCounts )
-      , sampledImageIntegerSampleCounts( rhs.sampledImageIntegerSampleCounts )
-      , sampledImageDepthSampleCounts( rhs.sampledImageDepthSampleCounts )
-      , sampledImageStencilSampleCounts( rhs.sampledImageStencilSampleCounts )
-      , storageImageSampleCounts( rhs.storageImageSampleCounts )
-      , maxSampleMaskWords( rhs.maxSampleMaskWords )
-      , timestampComputeAndGraphics( rhs.timestampComputeAndGraphics )
-      , timestampPeriod( rhs.timestampPeriod )
-      , maxClipDistances( rhs.maxClipDistances )
-      , maxCullDistances( rhs.maxCullDistances )
-      , maxCombinedClipAndCullDistances( rhs.maxCombinedClipAndCullDistances )
-      , discreteQueuePriorities( rhs.discreteQueuePriorities )
-      , pointSizeRange{}
-      , lineWidthRange{}
-      , pointSizeGranularity( rhs.pointSizeGranularity )
-      , lineWidthGranularity( rhs.lineWidthGranularity )
-      , strictLines( rhs.strictLines )
-      , standardSampleLocations( rhs.standardSampleLocations )
-      , optimalBufferCopyOffsetAlignment( rhs.optimalBufferCopyOffsetAlignment )
-      , optimalBufferCopyRowPitchAlignment( rhs.optimalBufferCopyRowPitchAlignment )
-      , nonCoherentAtomSize( rhs.nonCoherentAtomSize )
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint32_t,3>::copy( maxComputeWorkGroupCount, rhs.maxComputeWorkGroupCount );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint32_t,3>::copy( maxComputeWorkGroupSize, rhs.maxComputeWorkGroupSize );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint32_t,2>::copy( maxViewportDimensions, rhs.maxViewportDimensions );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<float,2>::copy( viewportBoundsRange, rhs.viewportBoundsRange );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<float,2>::copy( pointSizeRange, rhs.pointSizeRange );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<float,2>::copy( lineWidthRange, rhs.lineWidthRange );
-    }
-
-    PhysicalDeviceLimits & operator=( PhysicalDeviceLimits const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( PhysicalDeviceLimits ) );
-      return *this;
-    }
+    {}
 
     PhysicalDeviceLimits( VkPhysicalDeviceLimits const & rhs ) VULKAN_HPP_NOEXCEPT
     {
@@ -50067,9 +49762,9 @@
           && ( maxFragmentDualSrcAttachments == rhs.maxFragmentDualSrcAttachments )
           && ( maxFragmentCombinedOutputResources == rhs.maxFragmentCombinedOutputResources )
           && ( maxComputeSharedMemorySize == rhs.maxComputeSharedMemorySize )
-          && ( memcmp( maxComputeWorkGroupCount, rhs.maxComputeWorkGroupCount, 3 * sizeof( uint32_t ) ) == 0 )
+          && ( maxComputeWorkGroupCount == rhs.maxComputeWorkGroupCount )
           && ( maxComputeWorkGroupInvocations == rhs.maxComputeWorkGroupInvocations )
-          && ( memcmp( maxComputeWorkGroupSize, rhs.maxComputeWorkGroupSize, 3 * sizeof( uint32_t ) ) == 0 )
+          && ( maxComputeWorkGroupSize == rhs.maxComputeWorkGroupSize )
           && ( subPixelPrecisionBits == rhs.subPixelPrecisionBits )
           && ( subTexelPrecisionBits == rhs.subTexelPrecisionBits )
           && ( mipmapPrecisionBits == rhs.mipmapPrecisionBits )
@@ -50078,8 +49773,8 @@
           && ( maxSamplerLodBias == rhs.maxSamplerLodBias )
           && ( maxSamplerAnisotropy == rhs.maxSamplerAnisotropy )
           && ( maxViewports == rhs.maxViewports )
-          && ( memcmp( maxViewportDimensions, rhs.maxViewportDimensions, 2 * sizeof( uint32_t ) ) == 0 )
-          && ( memcmp( viewportBoundsRange, rhs.viewportBoundsRange, 2 * sizeof( float ) ) == 0 )
+          && ( maxViewportDimensions == rhs.maxViewportDimensions )
+          && ( viewportBoundsRange == rhs.viewportBoundsRange )
           && ( viewportSubPixelBits == rhs.viewportSubPixelBits )
           && ( minMemoryMapAlignment == rhs.minMemoryMapAlignment )
           && ( minTexelBufferOffsetAlignment == rhs.minTexelBufferOffsetAlignment )
@@ -50112,8 +49807,8 @@
           && ( maxCullDistances == rhs.maxCullDistances )
           && ( maxCombinedClipAndCullDistances == rhs.maxCombinedClipAndCullDistances )
           && ( discreteQueuePriorities == rhs.discreteQueuePriorities )
-          && ( memcmp( pointSizeRange, rhs.pointSizeRange, 2 * sizeof( float ) ) == 0 )
-          && ( memcmp( lineWidthRange, rhs.lineWidthRange, 2 * sizeof( float ) ) == 0 )
+          && ( pointSizeRange == rhs.pointSizeRange )
+          && ( lineWidthRange == rhs.lineWidthRange )
           && ( pointSizeGranularity == rhs.pointSizeGranularity )
           && ( lineWidthGranularity == rhs.lineWidthGranularity )
           && ( strictLines == rhs.strictLines )
@@ -50182,9 +49877,9 @@
     uint32_t maxFragmentDualSrcAttachments = {};
     uint32_t maxFragmentCombinedOutputResources = {};
     uint32_t maxComputeSharedMemorySize = {};
-    uint32_t maxComputeWorkGroupCount[3] = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<uint32_t, 3> maxComputeWorkGroupCount = {};
     uint32_t maxComputeWorkGroupInvocations = {};
-    uint32_t maxComputeWorkGroupSize[3] = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<uint32_t, 3> maxComputeWorkGroupSize = {};
     uint32_t subPixelPrecisionBits = {};
     uint32_t subTexelPrecisionBits = {};
     uint32_t mipmapPrecisionBits = {};
@@ -50193,8 +49888,8 @@
     float maxSamplerLodBias = {};
     float maxSamplerAnisotropy = {};
     uint32_t maxViewports = {};
-    uint32_t maxViewportDimensions[2] = {};
-    float viewportBoundsRange[2] = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<uint32_t, 2> maxViewportDimensions = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<float, 2> viewportBoundsRange = {};
     uint32_t viewportSubPixelBits = {};
     size_t minMemoryMapAlignment = {};
     VULKAN_HPP_NAMESPACE::DeviceSize minTexelBufferOffsetAlignment = {};
@@ -50227,8 +49922,8 @@
     uint32_t maxCullDistances = {};
     uint32_t maxCombinedClipAndCullDistances = {};
     uint32_t discreteQueuePriorities = {};
-    float pointSizeRange[2] = {};
-    float lineWidthRange[2] = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<float, 2> pointSizeRange = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<float, 2> lineWidthRange = {};
     float pointSizeGranularity = {};
     float lineWidthGranularity = {};
     VULKAN_HPP_NAMESPACE::Bool32 strictLines = {};
@@ -50256,16 +49951,6 @@
       , stippledSmoothLines( stippledSmoothLines_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceLineRasterizationFeaturesEXT( PhysicalDeviceLineRasterizationFeaturesEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , rectangularLines( rhs.rectangularLines )
-      , bresenhamLines( rhs.bresenhamLines )
-      , smoothLines( rhs.smoothLines )
-      , stippledRectangularLines( rhs.stippledRectangularLines )
-      , stippledBresenhamLines( rhs.stippledBresenhamLines )
-      , stippledSmoothLines( rhs.stippledSmoothLines )
-    {}
-
     PhysicalDeviceLineRasterizationFeaturesEXT & operator=( PhysicalDeviceLineRasterizationFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceLineRasterizationFeaturesEXT ) - offsetof( PhysicalDeviceLineRasterizationFeaturesEXT, pNext ) );
@@ -50375,11 +50060,6 @@
       : lineSubPixelPrecisionBits( lineSubPixelPrecisionBits_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceLineRasterizationPropertiesEXT( PhysicalDeviceLineRasterizationPropertiesEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , lineSubPixelPrecisionBits( rhs.lineSubPixelPrecisionBits )
-    {}
-
     PhysicalDeviceLineRasterizationPropertiesEXT & operator=( PhysicalDeviceLineRasterizationPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceLineRasterizationPropertiesEXT ) - offsetof( PhysicalDeviceLineRasterizationPropertiesEXT, pNext ) );
@@ -50439,12 +50119,6 @@
       , maxMemoryAllocationSize( maxMemoryAllocationSize_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceMaintenance3Properties( PhysicalDeviceMaintenance3Properties const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , maxPerSetDescriptors( rhs.maxPerSetDescriptors )
-      , maxMemoryAllocationSize( rhs.maxMemoryAllocationSize )
-    {}
-
     PhysicalDeviceMaintenance3Properties & operator=( PhysicalDeviceMaintenance3Properties const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceMaintenance3Properties ) - offsetof( PhysicalDeviceMaintenance3Properties, pNext ) );
@@ -50502,21 +50176,9 @@
   {
     VULKAN_HPP_CONSTEXPR_14 PhysicalDeviceMemoryBudgetPropertiesEXT( std::array<VULKAN_HPP_NAMESPACE::DeviceSize,VK_MAX_MEMORY_HEAPS> const& heapBudget_ = {},
                                                                      std::array<VULKAN_HPP_NAMESPACE::DeviceSize,VK_MAX_MEMORY_HEAPS> const& heapUsage_ = {} ) VULKAN_HPP_NOEXCEPT
-      : heapBudget{}
-      , heapUsage{}
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<VULKAN_HPP_NAMESPACE::DeviceSize,VK_MAX_MEMORY_HEAPS>::copy( heapBudget, heapBudget_ );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<VULKAN_HPP_NAMESPACE::DeviceSize,VK_MAX_MEMORY_HEAPS>::copy( heapUsage, heapUsage_ );
-    }
-
-    VULKAN_HPP_CONSTEXPR_14 PhysicalDeviceMemoryBudgetPropertiesEXT( PhysicalDeviceMemoryBudgetPropertiesEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , heapBudget{}
-      , heapUsage{}
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<VULKAN_HPP_NAMESPACE::DeviceSize,VK_MAX_MEMORY_HEAPS>::copy( heapBudget, rhs.heapBudget );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<VULKAN_HPP_NAMESPACE::DeviceSize,VK_MAX_MEMORY_HEAPS>::copy( heapUsage, rhs.heapUsage );
-    }
+      : heapBudget( heapBudget_ )
+      , heapUsage( heapUsage_ )
+    {}
 
     PhysicalDeviceMemoryBudgetPropertiesEXT & operator=( PhysicalDeviceMemoryBudgetPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
@@ -50552,8 +50214,8 @@
     {
       return ( sType == rhs.sType )
           && ( pNext == rhs.pNext )
-          && ( memcmp( heapBudget, rhs.heapBudget, VK_MAX_MEMORY_HEAPS * sizeof( VULKAN_HPP_NAMESPACE::DeviceSize ) ) == 0 )
-          && ( memcmp( heapUsage, rhs.heapUsage, VK_MAX_MEMORY_HEAPS * sizeof( VULKAN_HPP_NAMESPACE::DeviceSize ) ) == 0 );
+          && ( heapBudget == rhs.heapBudget )
+          && ( heapUsage == rhs.heapUsage );
     }
 
     bool operator!=( PhysicalDeviceMemoryBudgetPropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
@@ -50565,8 +50227,8 @@
   public:
     const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceMemoryBudgetPropertiesEXT;
     void* pNext = {};
-    VULKAN_HPP_NAMESPACE::DeviceSize heapBudget[VK_MAX_MEMORY_HEAPS] = {};
-    VULKAN_HPP_NAMESPACE::DeviceSize heapUsage[VK_MAX_MEMORY_HEAPS] = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<VULKAN_HPP_NAMESPACE::DeviceSize, VK_MAX_MEMORY_HEAPS> heapBudget = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<VULKAN_HPP_NAMESPACE::DeviceSize, VK_MAX_MEMORY_HEAPS> heapUsage = {};
   };
   static_assert( sizeof( PhysicalDeviceMemoryBudgetPropertiesEXT ) == sizeof( VkPhysicalDeviceMemoryBudgetPropertiesEXT ), "struct and wrapper have different size!" );
   static_assert( std::is_standard_layout<PhysicalDeviceMemoryBudgetPropertiesEXT>::value, "struct wrapper is not a standard layout!" );
@@ -50577,11 +50239,6 @@
       : memoryPriority( memoryPriority_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceMemoryPriorityFeaturesEXT( PhysicalDeviceMemoryPriorityFeaturesEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , memoryPriority( rhs.memoryPriority )
-    {}
-
     PhysicalDeviceMemoryPriorityFeaturesEXT & operator=( PhysicalDeviceMemoryPriorityFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceMemoryPriorityFeaturesEXT ) - offsetof( PhysicalDeviceMemoryPriorityFeaturesEXT, pNext ) );
@@ -50652,29 +50309,10 @@
                                                             uint32_t memoryHeapCount_ = {},
                                                             std::array<VULKAN_HPP_NAMESPACE::MemoryHeap,VK_MAX_MEMORY_HEAPS> const& memoryHeaps_ = {} ) VULKAN_HPP_NOEXCEPT
       : memoryTypeCount( memoryTypeCount_ )
-      , memoryTypes{}
+      , memoryTypes( memoryTypes_ )
       , memoryHeapCount( memoryHeapCount_ )
-      , memoryHeaps{}
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<VULKAN_HPP_NAMESPACE::MemoryType,VK_MAX_MEMORY_TYPES>::copy( memoryTypes, memoryTypes_ );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<VULKAN_HPP_NAMESPACE::MemoryHeap,VK_MAX_MEMORY_HEAPS>::copy( memoryHeaps, memoryHeaps_ );
-    }
-
-    VULKAN_HPP_CONSTEXPR_14 PhysicalDeviceMemoryProperties( PhysicalDeviceMemoryProperties const& rhs ) VULKAN_HPP_NOEXCEPT
-      : memoryTypeCount( rhs.memoryTypeCount )
-      , memoryTypes{}
-      , memoryHeapCount( rhs.memoryHeapCount )
-      , memoryHeaps{}
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<VULKAN_HPP_NAMESPACE::MemoryType,VK_MAX_MEMORY_TYPES>::copy( memoryTypes, rhs.memoryTypes );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<VULKAN_HPP_NAMESPACE::MemoryHeap,VK_MAX_MEMORY_HEAPS>::copy( memoryHeaps, rhs.memoryHeaps );
-    }
-
-    PhysicalDeviceMemoryProperties & operator=( PhysicalDeviceMemoryProperties const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( PhysicalDeviceMemoryProperties ) );
-      return *this;
-    }
+      , memoryHeaps( memoryHeaps_ )
+    {}
 
     PhysicalDeviceMemoryProperties( VkPhysicalDeviceMemoryProperties const & rhs ) VULKAN_HPP_NOEXCEPT
     {
@@ -50703,9 +50341,9 @@
     bool operator==( PhysicalDeviceMemoryProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
     {
       return ( memoryTypeCount == rhs.memoryTypeCount )
-          && ( memcmp( memoryTypes, rhs.memoryTypes, std::min<uint32_t>( VK_MAX_MEMORY_TYPES, memoryTypeCount ) * sizeof( VULKAN_HPP_NAMESPACE::MemoryType ) ) == 0 )
+          && ( memoryTypes == rhs.memoryTypes )
           && ( memoryHeapCount == rhs.memoryHeapCount )
-          && ( memcmp( memoryHeaps, rhs.memoryHeaps, std::min<uint32_t>( VK_MAX_MEMORY_HEAPS, memoryHeapCount ) * sizeof( VULKAN_HPP_NAMESPACE::MemoryHeap ) ) == 0 );
+          && ( memoryHeaps == rhs.memoryHeaps );
     }
 
     bool operator!=( PhysicalDeviceMemoryProperties const& rhs ) const VULKAN_HPP_NOEXCEPT
@@ -50716,9 +50354,9 @@
 
   public:
     uint32_t memoryTypeCount = {};
-    VULKAN_HPP_NAMESPACE::MemoryType memoryTypes[VK_MAX_MEMORY_TYPES] = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<VULKAN_HPP_NAMESPACE::MemoryType, VK_MAX_MEMORY_TYPES> memoryTypes = {};
     uint32_t memoryHeapCount = {};
-    VULKAN_HPP_NAMESPACE::MemoryHeap memoryHeaps[VK_MAX_MEMORY_HEAPS] = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<VULKAN_HPP_NAMESPACE::MemoryHeap, VK_MAX_MEMORY_HEAPS> memoryHeaps = {};
   };
   static_assert( sizeof( PhysicalDeviceMemoryProperties ) == sizeof( VkPhysicalDeviceMemoryProperties ), "struct and wrapper have different size!" );
   static_assert( std::is_standard_layout<PhysicalDeviceMemoryProperties>::value, "struct wrapper is not a standard layout!" );
@@ -50729,11 +50367,6 @@
       : memoryProperties( memoryProperties_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR_14 PhysicalDeviceMemoryProperties2( PhysicalDeviceMemoryProperties2 const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , memoryProperties( rhs.memoryProperties )
-    {}
-
     PhysicalDeviceMemoryProperties2 & operator=( PhysicalDeviceMemoryProperties2 const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceMemoryProperties2 ) - offsetof( PhysicalDeviceMemoryProperties2, pNext ) );
@@ -50793,12 +50426,6 @@
       , meshShader( meshShader_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceMeshShaderFeaturesNV( PhysicalDeviceMeshShaderFeaturesNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , taskShader( rhs.taskShader )
-      , meshShader( rhs.meshShader )
-    {}
-
     PhysicalDeviceMeshShaderFeaturesNV & operator=( PhysicalDeviceMeshShaderFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceMeshShaderFeaturesNV ) - offsetof( PhysicalDeviceMeshShaderFeaturesNV, pNext ) );
@@ -50887,41 +50514,18 @@
                                                                   uint32_t meshOutputPerPrimitiveGranularity_ = {} ) VULKAN_HPP_NOEXCEPT
       : maxDrawMeshTasksCount( maxDrawMeshTasksCount_ )
       , maxTaskWorkGroupInvocations( maxTaskWorkGroupInvocations_ )
-      , maxTaskWorkGroupSize{}
+      , maxTaskWorkGroupSize( maxTaskWorkGroupSize_ )
       , maxTaskTotalMemorySize( maxTaskTotalMemorySize_ )
       , maxTaskOutputCount( maxTaskOutputCount_ )
       , maxMeshWorkGroupInvocations( maxMeshWorkGroupInvocations_ )
-      , maxMeshWorkGroupSize{}
+      , maxMeshWorkGroupSize( maxMeshWorkGroupSize_ )
       , maxMeshTotalMemorySize( maxMeshTotalMemorySize_ )
       , maxMeshOutputVertices( maxMeshOutputVertices_ )
       , maxMeshOutputPrimitives( maxMeshOutputPrimitives_ )
       , maxMeshMultiviewViewCount( maxMeshMultiviewViewCount_ )
       , meshOutputPerVertexGranularity( meshOutputPerVertexGranularity_ )
       , meshOutputPerPrimitiveGranularity( meshOutputPerPrimitiveGranularity_ )
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint32_t,3>::copy( maxTaskWorkGroupSize, maxTaskWorkGroupSize_ );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint32_t,3>::copy( maxMeshWorkGroupSize, maxMeshWorkGroupSize_ );
-    }
-
-    VULKAN_HPP_CONSTEXPR_14 PhysicalDeviceMeshShaderPropertiesNV( PhysicalDeviceMeshShaderPropertiesNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , maxDrawMeshTasksCount( rhs.maxDrawMeshTasksCount )
-      , maxTaskWorkGroupInvocations( rhs.maxTaskWorkGroupInvocations )
-      , maxTaskWorkGroupSize{}
-      , maxTaskTotalMemorySize( rhs.maxTaskTotalMemorySize )
-      , maxTaskOutputCount( rhs.maxTaskOutputCount )
-      , maxMeshWorkGroupInvocations( rhs.maxMeshWorkGroupInvocations )
-      , maxMeshWorkGroupSize{}
-      , maxMeshTotalMemorySize( rhs.maxMeshTotalMemorySize )
-      , maxMeshOutputVertices( rhs.maxMeshOutputVertices )
-      , maxMeshOutputPrimitives( rhs.maxMeshOutputPrimitives )
-      , maxMeshMultiviewViewCount( rhs.maxMeshMultiviewViewCount )
-      , meshOutputPerVertexGranularity( rhs.meshOutputPerVertexGranularity )
-      , meshOutputPerPrimitiveGranularity( rhs.meshOutputPerPrimitiveGranularity )
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint32_t,3>::copy( maxTaskWorkGroupSize, rhs.maxTaskWorkGroupSize );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint32_t,3>::copy( maxMeshWorkGroupSize, rhs.maxMeshWorkGroupSize );
-    }
+    {}
 
     PhysicalDeviceMeshShaderPropertiesNV & operator=( PhysicalDeviceMeshShaderPropertiesNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
@@ -50959,11 +50563,11 @@
           && ( pNext == rhs.pNext )
           && ( maxDrawMeshTasksCount == rhs.maxDrawMeshTasksCount )
           && ( maxTaskWorkGroupInvocations == rhs.maxTaskWorkGroupInvocations )
-          && ( memcmp( maxTaskWorkGroupSize, rhs.maxTaskWorkGroupSize, 3 * sizeof( uint32_t ) ) == 0 )
+          && ( maxTaskWorkGroupSize == rhs.maxTaskWorkGroupSize )
           && ( maxTaskTotalMemorySize == rhs.maxTaskTotalMemorySize )
           && ( maxTaskOutputCount == rhs.maxTaskOutputCount )
           && ( maxMeshWorkGroupInvocations == rhs.maxMeshWorkGroupInvocations )
-          && ( memcmp( maxMeshWorkGroupSize, rhs.maxMeshWorkGroupSize, 3 * sizeof( uint32_t ) ) == 0 )
+          && ( maxMeshWorkGroupSize == rhs.maxMeshWorkGroupSize )
           && ( maxMeshTotalMemorySize == rhs.maxMeshTotalMemorySize )
           && ( maxMeshOutputVertices == rhs.maxMeshOutputVertices )
           && ( maxMeshOutputPrimitives == rhs.maxMeshOutputPrimitives )
@@ -50983,11 +50587,11 @@
     void* pNext = {};
     uint32_t maxDrawMeshTasksCount = {};
     uint32_t maxTaskWorkGroupInvocations = {};
-    uint32_t maxTaskWorkGroupSize[3] = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<uint32_t, 3> maxTaskWorkGroupSize = {};
     uint32_t maxTaskTotalMemorySize = {};
     uint32_t maxTaskOutputCount = {};
     uint32_t maxMeshWorkGroupInvocations = {};
-    uint32_t maxMeshWorkGroupSize[3] = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<uint32_t, 3> maxMeshWorkGroupSize = {};
     uint32_t maxMeshTotalMemorySize = {};
     uint32_t maxMeshOutputVertices = {};
     uint32_t maxMeshOutputPrimitives = {};
@@ -51008,13 +50612,6 @@
       , multiviewTessellationShader( multiviewTessellationShader_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceMultiviewFeatures( PhysicalDeviceMultiviewFeatures const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , multiview( rhs.multiview )
-      , multiviewGeometryShader( rhs.multiviewGeometryShader )
-      , multiviewTessellationShader( rhs.multiviewTessellationShader )
-    {}
-
     PhysicalDeviceMultiviewFeatures & operator=( PhysicalDeviceMultiviewFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceMultiviewFeatures ) - offsetof( PhysicalDeviceMultiviewFeatures, pNext ) );
@@ -51100,11 +50697,6 @@
       : perViewPositionAllComponents( perViewPositionAllComponents_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceMultiviewPerViewAttributesPropertiesNVX( PhysicalDeviceMultiviewPerViewAttributesPropertiesNVX const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , perViewPositionAllComponents( rhs.perViewPositionAllComponents )
-    {}
-
     PhysicalDeviceMultiviewPerViewAttributesPropertiesNVX & operator=( PhysicalDeviceMultiviewPerViewAttributesPropertiesNVX const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceMultiviewPerViewAttributesPropertiesNVX ) - offsetof( PhysicalDeviceMultiviewPerViewAttributesPropertiesNVX, pNext ) );
@@ -51164,12 +50756,6 @@
       , maxMultiviewInstanceIndex( maxMultiviewInstanceIndex_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceMultiviewProperties( PhysicalDeviceMultiviewProperties const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , maxMultiviewViewCount( rhs.maxMultiviewViewCount )
-      , maxMultiviewInstanceIndex( rhs.maxMultiviewInstanceIndex )
-    {}
-
     PhysicalDeviceMultiviewProperties & operator=( PhysicalDeviceMultiviewProperties const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceMultiviewProperties ) - offsetof( PhysicalDeviceMultiviewProperties, pNext ) );
@@ -51235,14 +50821,6 @@
       , pciFunction( pciFunction_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDevicePCIBusInfoPropertiesEXT( PhysicalDevicePCIBusInfoPropertiesEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , pciDomain( rhs.pciDomain )
-      , pciBus( rhs.pciBus )
-      , pciDevice( rhs.pciDevice )
-      , pciFunction( rhs.pciFunction )
-    {}
-
     PhysicalDevicePCIBusInfoPropertiesEXT & operator=( PhysicalDevicePCIBusInfoPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDevicePCIBusInfoPropertiesEXT ) - offsetof( PhysicalDevicePCIBusInfoPropertiesEXT, pNext ) );
@@ -51308,12 +50886,6 @@
       , performanceCounterMultipleQueryPools( performanceCounterMultipleQueryPools_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDevicePerformanceQueryFeaturesKHR( PhysicalDevicePerformanceQueryFeaturesKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , performanceCounterQueryPools( rhs.performanceCounterQueryPools )
-      , performanceCounterMultipleQueryPools( rhs.performanceCounterMultipleQueryPools )
-    {}
-
     PhysicalDevicePerformanceQueryFeaturesKHR & operator=( PhysicalDevicePerformanceQueryFeaturesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDevicePerformanceQueryFeaturesKHR ) - offsetof( PhysicalDevicePerformanceQueryFeaturesKHR, pNext ) );
@@ -51391,11 +50963,6 @@
       : allowCommandBufferQueryCopies( allowCommandBufferQueryCopies_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDevicePerformanceQueryPropertiesKHR( PhysicalDevicePerformanceQueryPropertiesKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , allowCommandBufferQueryCopies( rhs.allowCommandBufferQueryCopies )
-    {}
-
     PhysicalDevicePerformanceQueryPropertiesKHR & operator=( PhysicalDevicePerformanceQueryPropertiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDevicePerformanceQueryPropertiesKHR ) - offsetof( PhysicalDevicePerformanceQueryPropertiesKHR, pNext ) );
@@ -51447,17 +51014,81 @@
   static_assert( sizeof( PhysicalDevicePerformanceQueryPropertiesKHR ) == sizeof( VkPhysicalDevicePerformanceQueryPropertiesKHR ), "struct and wrapper have different size!" );
   static_assert( std::is_standard_layout<PhysicalDevicePerformanceQueryPropertiesKHR>::value, "struct wrapper is not a standard layout!" );
 
+  struct PhysicalDevicePipelineCreationCacheControlFeaturesEXT
+  {
+    VULKAN_HPP_CONSTEXPR PhysicalDevicePipelineCreationCacheControlFeaturesEXT( VULKAN_HPP_NAMESPACE::Bool32 pipelineCreationCacheControl_ = {} ) VULKAN_HPP_NOEXCEPT
+      : pipelineCreationCacheControl( pipelineCreationCacheControl_ )
+    {}
+
+    PhysicalDevicePipelineCreationCacheControlFeaturesEXT & operator=( PhysicalDevicePipelineCreationCacheControlFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDevicePipelineCreationCacheControlFeaturesEXT ) - offsetof( PhysicalDevicePipelineCreationCacheControlFeaturesEXT, pNext ) );
+      return *this;
+    }
+
+    PhysicalDevicePipelineCreationCacheControlFeaturesEXT( VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    PhysicalDevicePipelineCreationCacheControlFeaturesEXT& operator=( VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDevicePipelineCreationCacheControlFeaturesEXT const *>(&rhs);
+      return *this;
+    }
+
+    PhysicalDevicePipelineCreationCacheControlFeaturesEXT & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pNext = pNext_;
+      return *this;
+    }
+
+    PhysicalDevicePipelineCreationCacheControlFeaturesEXT & setPipelineCreationCacheControl( VULKAN_HPP_NAMESPACE::Bool32 pipelineCreationCacheControl_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pipelineCreationCacheControl = pipelineCreationCacheControl_;
+      return *this;
+    }
+
+    operator VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT*>( this );
+    }
+
+    operator VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT*>( this );
+    }
+
+#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
+    auto operator<=>( PhysicalDevicePipelineCreationCacheControlFeaturesEXT const& ) const = default;
+#else
+    bool operator==( PhysicalDevicePipelineCreationCacheControlFeaturesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ( sType == rhs.sType )
+          && ( pNext == rhs.pNext )
+          && ( pipelineCreationCacheControl == rhs.pipelineCreationCacheControl );
+    }
+
+    bool operator!=( PhysicalDevicePipelineCreationCacheControlFeaturesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return !operator==( rhs );
+    }
+#endif
+
+  public:
+    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDevicePipelineCreationCacheControlFeaturesEXT;
+    void* pNext = {};
+    VULKAN_HPP_NAMESPACE::Bool32 pipelineCreationCacheControl = {};
+  };
+  static_assert( sizeof( PhysicalDevicePipelineCreationCacheControlFeaturesEXT ) == sizeof( VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<PhysicalDevicePipelineCreationCacheControlFeaturesEXT>::value, "struct wrapper is not a standard layout!" );
+
   struct PhysicalDevicePipelineExecutablePropertiesFeaturesKHR
   {
     VULKAN_HPP_CONSTEXPR PhysicalDevicePipelineExecutablePropertiesFeaturesKHR( VULKAN_HPP_NAMESPACE::Bool32 pipelineExecutableInfo_ = {} ) VULKAN_HPP_NOEXCEPT
       : pipelineExecutableInfo( pipelineExecutableInfo_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDevicePipelineExecutablePropertiesFeaturesKHR( PhysicalDevicePipelineExecutablePropertiesFeaturesKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , pipelineExecutableInfo( rhs.pipelineExecutableInfo )
-    {}
-
     PhysicalDevicePipelineExecutablePropertiesFeaturesKHR & operator=( PhysicalDevicePipelineExecutablePropertiesFeaturesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDevicePipelineExecutablePropertiesFeaturesKHR ) - offsetof( PhysicalDevicePipelineExecutablePropertiesFeaturesKHR, pNext ) );
@@ -51527,11 +51158,6 @@
       : pointClippingBehavior( pointClippingBehavior_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDevicePointClippingProperties( PhysicalDevicePointClippingProperties const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , pointClippingBehavior( rhs.pointClippingBehavior )
-    {}
-
     PhysicalDevicePointClippingProperties & operator=( PhysicalDevicePointClippingProperties const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDevicePointClippingProperties ) - offsetof( PhysicalDevicePointClippingProperties, pNext ) );
@@ -51597,20 +51223,6 @@
       , residencyNonResidentStrict( residencyNonResidentStrict_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceSparseProperties( PhysicalDeviceSparseProperties const& rhs ) VULKAN_HPP_NOEXCEPT
-      : residencyStandard2DBlockShape( rhs.residencyStandard2DBlockShape )
-      , residencyStandard2DMultisampleBlockShape( rhs.residencyStandard2DMultisampleBlockShape )
-      , residencyStandard3DBlockShape( rhs.residencyStandard3DBlockShape )
-      , residencyAlignedMipSize( rhs.residencyAlignedMipSize )
-      , residencyNonResidentStrict( rhs.residencyNonResidentStrict )
-    {}
-
-    PhysicalDeviceSparseProperties & operator=( PhysicalDeviceSparseProperties const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( PhysicalDeviceSparseProperties ) );
-      return *this;
-    }
-
     PhysicalDeviceSparseProperties( VkPhysicalDeviceSparseProperties const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -51676,35 +51288,11 @@
       , vendorID( vendorID_ )
       , deviceID( deviceID_ )
       , deviceType( deviceType_ )
-      , deviceName{}
-      , pipelineCacheUUID{}
+      , deviceName( deviceName_ )
+      , pipelineCacheUUID( pipelineCacheUUID_ )
       , limits( limits_ )
       , sparseProperties( sparseProperties_ )
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_PHYSICAL_DEVICE_NAME_SIZE>::copy( deviceName, deviceName_ );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint8_t,VK_UUID_SIZE>::copy( pipelineCacheUUID, pipelineCacheUUID_ );
-    }
-
-    VULKAN_HPP_CONSTEXPR_14 PhysicalDeviceProperties( PhysicalDeviceProperties const& rhs ) VULKAN_HPP_NOEXCEPT
-      : apiVersion( rhs.apiVersion )
-      , driverVersion( rhs.driverVersion )
-      , vendorID( rhs.vendorID )
-      , deviceID( rhs.deviceID )
-      , deviceType( rhs.deviceType )
-      , deviceName{}
-      , pipelineCacheUUID{}
-      , limits( rhs.limits )
-      , sparseProperties( rhs.sparseProperties )
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_PHYSICAL_DEVICE_NAME_SIZE>::copy( deviceName, rhs.deviceName );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint8_t,VK_UUID_SIZE>::copy( pipelineCacheUUID, rhs.pipelineCacheUUID );
-    }
-
-    PhysicalDeviceProperties & operator=( PhysicalDeviceProperties const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( PhysicalDeviceProperties ) );
-      return *this;
-    }
+    {}
 
     PhysicalDeviceProperties( VkPhysicalDeviceProperties const & rhs ) VULKAN_HPP_NOEXCEPT
     {
@@ -51737,8 +51325,8 @@
           && ( vendorID == rhs.vendorID )
           && ( deviceID == rhs.deviceID )
           && ( deviceType == rhs.deviceType )
-          && ( memcmp( deviceName, rhs.deviceName, VK_MAX_PHYSICAL_DEVICE_NAME_SIZE * sizeof( char ) ) == 0 )
-          && ( memcmp( pipelineCacheUUID, rhs.pipelineCacheUUID, VK_UUID_SIZE * sizeof( uint8_t ) ) == 0 )
+          && ( deviceName == rhs.deviceName )
+          && ( pipelineCacheUUID == rhs.pipelineCacheUUID )
           && ( limits == rhs.limits )
           && ( sparseProperties == rhs.sparseProperties );
     }
@@ -51755,8 +51343,8 @@
     uint32_t vendorID = {};
     uint32_t deviceID = {};
     VULKAN_HPP_NAMESPACE::PhysicalDeviceType deviceType = VULKAN_HPP_NAMESPACE::PhysicalDeviceType::eOther;
-    char deviceName[VK_MAX_PHYSICAL_DEVICE_NAME_SIZE] = {};
-    uint8_t pipelineCacheUUID[VK_UUID_SIZE] = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<char, VK_MAX_PHYSICAL_DEVICE_NAME_SIZE> deviceName = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<uint8_t, VK_UUID_SIZE> pipelineCacheUUID = {};
     VULKAN_HPP_NAMESPACE::PhysicalDeviceLimits limits = {};
     VULKAN_HPP_NAMESPACE::PhysicalDeviceSparseProperties sparseProperties = {};
   };
@@ -51769,11 +51357,6 @@
       : properties( properties_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR_14 PhysicalDeviceProperties2( PhysicalDeviceProperties2 const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , properties( rhs.properties )
-    {}
-
     PhysicalDeviceProperties2 & operator=( PhysicalDeviceProperties2 const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceProperties2 ) - offsetof( PhysicalDeviceProperties2, pNext ) );
@@ -51831,11 +51414,6 @@
       : protectedMemory( protectedMemory_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceProtectedMemoryFeatures( PhysicalDeviceProtectedMemoryFeatures const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , protectedMemory( rhs.protectedMemory )
-    {}
-
     PhysicalDeviceProtectedMemoryFeatures & operator=( PhysicalDeviceProtectedMemoryFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceProtectedMemoryFeatures ) - offsetof( PhysicalDeviceProtectedMemoryFeatures, pNext ) );
@@ -51905,11 +51483,6 @@
       : protectedNoFault( protectedNoFault_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceProtectedMemoryProperties( PhysicalDeviceProtectedMemoryProperties const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , protectedNoFault( rhs.protectedNoFault )
-    {}
-
     PhysicalDeviceProtectedMemoryProperties & operator=( PhysicalDeviceProtectedMemoryProperties const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceProtectedMemoryProperties ) - offsetof( PhysicalDeviceProtectedMemoryProperties, pNext ) );
@@ -51967,11 +51540,6 @@
       : maxPushDescriptors( maxPushDescriptors_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDevicePushDescriptorPropertiesKHR( PhysicalDevicePushDescriptorPropertiesKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , maxPushDescriptors( rhs.maxPushDescriptors )
-    {}
-
     PhysicalDevicePushDescriptorPropertiesKHR & operator=( PhysicalDevicePushDescriptorPropertiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDevicePushDescriptorPropertiesKHR ) - offsetof( PhysicalDevicePushDescriptorPropertiesKHR, pNext ) );
@@ -52023,6 +51591,248 @@
   static_assert( sizeof( PhysicalDevicePushDescriptorPropertiesKHR ) == sizeof( VkPhysicalDevicePushDescriptorPropertiesKHR ), "struct and wrapper have different size!" );
   static_assert( std::is_standard_layout<PhysicalDevicePushDescriptorPropertiesKHR>::value, "struct wrapper is not a standard layout!" );
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct PhysicalDeviceRayTracingFeaturesKHR
+  {
+    VULKAN_HPP_CONSTEXPR PhysicalDeviceRayTracingFeaturesKHR( VULKAN_HPP_NAMESPACE::Bool32 rayTracing_ = {},
+                                                              VULKAN_HPP_NAMESPACE::Bool32 rayTracingShaderGroupHandleCaptureReplay_ = {},
+                                                              VULKAN_HPP_NAMESPACE::Bool32 rayTracingShaderGroupHandleCaptureReplayMixed_ = {},
+                                                              VULKAN_HPP_NAMESPACE::Bool32 rayTracingAccelerationStructureCaptureReplay_ = {},
+                                                              VULKAN_HPP_NAMESPACE::Bool32 rayTracingIndirectTraceRays_ = {},
+                                                              VULKAN_HPP_NAMESPACE::Bool32 rayTracingIndirectAccelerationStructureBuild_ = {},
+                                                              VULKAN_HPP_NAMESPACE::Bool32 rayTracingHostAccelerationStructureCommands_ = {},
+                                                              VULKAN_HPP_NAMESPACE::Bool32 rayQuery_ = {},
+                                                              VULKAN_HPP_NAMESPACE::Bool32 rayTracingPrimitiveCulling_ = {} ) VULKAN_HPP_NOEXCEPT
+      : rayTracing( rayTracing_ )
+      , rayTracingShaderGroupHandleCaptureReplay( rayTracingShaderGroupHandleCaptureReplay_ )
+      , rayTracingShaderGroupHandleCaptureReplayMixed( rayTracingShaderGroupHandleCaptureReplayMixed_ )
+      , rayTracingAccelerationStructureCaptureReplay( rayTracingAccelerationStructureCaptureReplay_ )
+      , rayTracingIndirectTraceRays( rayTracingIndirectTraceRays_ )
+      , rayTracingIndirectAccelerationStructureBuild( rayTracingIndirectAccelerationStructureBuild_ )
+      , rayTracingHostAccelerationStructureCommands( rayTracingHostAccelerationStructureCommands_ )
+      , rayQuery( rayQuery_ )
+      , rayTracingPrimitiveCulling( rayTracingPrimitiveCulling_ )
+    {}
+
+    PhysicalDeviceRayTracingFeaturesKHR & operator=( PhysicalDeviceRayTracingFeaturesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceRayTracingFeaturesKHR ) - offsetof( PhysicalDeviceRayTracingFeaturesKHR, pNext ) );
+      return *this;
+    }
+
+    PhysicalDeviceRayTracingFeaturesKHR( VkPhysicalDeviceRayTracingFeaturesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    PhysicalDeviceRayTracingFeaturesKHR& operator=( VkPhysicalDeviceRayTracingFeaturesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceRayTracingFeaturesKHR const *>(&rhs);
+      return *this;
+    }
+
+    PhysicalDeviceRayTracingFeaturesKHR & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pNext = pNext_;
+      return *this;
+    }
+
+    PhysicalDeviceRayTracingFeaturesKHR & setRayTracing( VULKAN_HPP_NAMESPACE::Bool32 rayTracing_ ) VULKAN_HPP_NOEXCEPT
+    {
+      rayTracing = rayTracing_;
+      return *this;
+    }
+
+    PhysicalDeviceRayTracingFeaturesKHR & setRayTracingShaderGroupHandleCaptureReplay( VULKAN_HPP_NAMESPACE::Bool32 rayTracingShaderGroupHandleCaptureReplay_ ) VULKAN_HPP_NOEXCEPT
+    {
+      rayTracingShaderGroupHandleCaptureReplay = rayTracingShaderGroupHandleCaptureReplay_;
+      return *this;
+    }
+
+    PhysicalDeviceRayTracingFeaturesKHR & setRayTracingShaderGroupHandleCaptureReplayMixed( VULKAN_HPP_NAMESPACE::Bool32 rayTracingShaderGroupHandleCaptureReplayMixed_ ) VULKAN_HPP_NOEXCEPT
+    {
+      rayTracingShaderGroupHandleCaptureReplayMixed = rayTracingShaderGroupHandleCaptureReplayMixed_;
+      return *this;
+    }
+
+    PhysicalDeviceRayTracingFeaturesKHR & setRayTracingAccelerationStructureCaptureReplay( VULKAN_HPP_NAMESPACE::Bool32 rayTracingAccelerationStructureCaptureReplay_ ) VULKAN_HPP_NOEXCEPT
+    {
+      rayTracingAccelerationStructureCaptureReplay = rayTracingAccelerationStructureCaptureReplay_;
+      return *this;
+    }
+
+    PhysicalDeviceRayTracingFeaturesKHR & setRayTracingIndirectTraceRays( VULKAN_HPP_NAMESPACE::Bool32 rayTracingIndirectTraceRays_ ) VULKAN_HPP_NOEXCEPT
+    {
+      rayTracingIndirectTraceRays = rayTracingIndirectTraceRays_;
+      return *this;
+    }
+
+    PhysicalDeviceRayTracingFeaturesKHR & setRayTracingIndirectAccelerationStructureBuild( VULKAN_HPP_NAMESPACE::Bool32 rayTracingIndirectAccelerationStructureBuild_ ) VULKAN_HPP_NOEXCEPT
+    {
+      rayTracingIndirectAccelerationStructureBuild = rayTracingIndirectAccelerationStructureBuild_;
+      return *this;
+    }
+
+    PhysicalDeviceRayTracingFeaturesKHR & setRayTracingHostAccelerationStructureCommands( VULKAN_HPP_NAMESPACE::Bool32 rayTracingHostAccelerationStructureCommands_ ) VULKAN_HPP_NOEXCEPT
+    {
+      rayTracingHostAccelerationStructureCommands = rayTracingHostAccelerationStructureCommands_;
+      return *this;
+    }
+
+    PhysicalDeviceRayTracingFeaturesKHR & setRayQuery( VULKAN_HPP_NAMESPACE::Bool32 rayQuery_ ) VULKAN_HPP_NOEXCEPT
+    {
+      rayQuery = rayQuery_;
+      return *this;
+    }
+
+    PhysicalDeviceRayTracingFeaturesKHR & setRayTracingPrimitiveCulling( VULKAN_HPP_NAMESPACE::Bool32 rayTracingPrimitiveCulling_ ) VULKAN_HPP_NOEXCEPT
+    {
+      rayTracingPrimitiveCulling = rayTracingPrimitiveCulling_;
+      return *this;
+    }
+
+    operator VkPhysicalDeviceRayTracingFeaturesKHR const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkPhysicalDeviceRayTracingFeaturesKHR*>( this );
+    }
+
+    operator VkPhysicalDeviceRayTracingFeaturesKHR &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkPhysicalDeviceRayTracingFeaturesKHR*>( this );
+    }
+
+#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
+    auto operator<=>( PhysicalDeviceRayTracingFeaturesKHR const& ) const = default;
+#else
+    bool operator==( PhysicalDeviceRayTracingFeaturesKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ( sType == rhs.sType )
+          && ( pNext == rhs.pNext )
+          && ( rayTracing == rhs.rayTracing )
+          && ( rayTracingShaderGroupHandleCaptureReplay == rhs.rayTracingShaderGroupHandleCaptureReplay )
+          && ( rayTracingShaderGroupHandleCaptureReplayMixed == rhs.rayTracingShaderGroupHandleCaptureReplayMixed )
+          && ( rayTracingAccelerationStructureCaptureReplay == rhs.rayTracingAccelerationStructureCaptureReplay )
+          && ( rayTracingIndirectTraceRays == rhs.rayTracingIndirectTraceRays )
+          && ( rayTracingIndirectAccelerationStructureBuild == rhs.rayTracingIndirectAccelerationStructureBuild )
+          && ( rayTracingHostAccelerationStructureCommands == rhs.rayTracingHostAccelerationStructureCommands )
+          && ( rayQuery == rhs.rayQuery )
+          && ( rayTracingPrimitiveCulling == rhs.rayTracingPrimitiveCulling );
+    }
+
+    bool operator!=( PhysicalDeviceRayTracingFeaturesKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return !operator==( rhs );
+    }
+#endif
+
+  public:
+    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceRayTracingFeaturesKHR;
+    void* pNext = {};
+    VULKAN_HPP_NAMESPACE::Bool32 rayTracing = {};
+    VULKAN_HPP_NAMESPACE::Bool32 rayTracingShaderGroupHandleCaptureReplay = {};
+    VULKAN_HPP_NAMESPACE::Bool32 rayTracingShaderGroupHandleCaptureReplayMixed = {};
+    VULKAN_HPP_NAMESPACE::Bool32 rayTracingAccelerationStructureCaptureReplay = {};
+    VULKAN_HPP_NAMESPACE::Bool32 rayTracingIndirectTraceRays = {};
+    VULKAN_HPP_NAMESPACE::Bool32 rayTracingIndirectAccelerationStructureBuild = {};
+    VULKAN_HPP_NAMESPACE::Bool32 rayTracingHostAccelerationStructureCommands = {};
+    VULKAN_HPP_NAMESPACE::Bool32 rayQuery = {};
+    VULKAN_HPP_NAMESPACE::Bool32 rayTracingPrimitiveCulling = {};
+  };
+  static_assert( sizeof( PhysicalDeviceRayTracingFeaturesKHR ) == sizeof( VkPhysicalDeviceRayTracingFeaturesKHR ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<PhysicalDeviceRayTracingFeaturesKHR>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct PhysicalDeviceRayTracingPropertiesKHR
+  {
+    VULKAN_HPP_CONSTEXPR PhysicalDeviceRayTracingPropertiesKHR( uint32_t shaderGroupHandleSize_ = {},
+                                                                uint32_t maxRecursionDepth_ = {},
+                                                                uint32_t maxShaderGroupStride_ = {},
+                                                                uint32_t shaderGroupBaseAlignment_ = {},
+                                                                uint64_t maxGeometryCount_ = {},
+                                                                uint64_t maxInstanceCount_ = {},
+                                                                uint64_t maxPrimitiveCount_ = {},
+                                                                uint32_t maxDescriptorSetAccelerationStructures_ = {},
+                                                                uint32_t shaderGroupHandleCaptureReplaySize_ = {} ) VULKAN_HPP_NOEXCEPT
+      : shaderGroupHandleSize( shaderGroupHandleSize_ )
+      , maxRecursionDepth( maxRecursionDepth_ )
+      , maxShaderGroupStride( maxShaderGroupStride_ )
+      , shaderGroupBaseAlignment( shaderGroupBaseAlignment_ )
+      , maxGeometryCount( maxGeometryCount_ )
+      , maxInstanceCount( maxInstanceCount_ )
+      , maxPrimitiveCount( maxPrimitiveCount_ )
+      , maxDescriptorSetAccelerationStructures( maxDescriptorSetAccelerationStructures_ )
+      , shaderGroupHandleCaptureReplaySize( shaderGroupHandleCaptureReplaySize_ )
+    {}
+
+    PhysicalDeviceRayTracingPropertiesKHR & operator=( PhysicalDeviceRayTracingPropertiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceRayTracingPropertiesKHR ) - offsetof( PhysicalDeviceRayTracingPropertiesKHR, pNext ) );
+      return *this;
+    }
+
+    PhysicalDeviceRayTracingPropertiesKHR( VkPhysicalDeviceRayTracingPropertiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    PhysicalDeviceRayTracingPropertiesKHR& operator=( VkPhysicalDeviceRayTracingPropertiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PhysicalDeviceRayTracingPropertiesKHR const *>(&rhs);
+      return *this;
+    }
+
+    operator VkPhysicalDeviceRayTracingPropertiesKHR const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkPhysicalDeviceRayTracingPropertiesKHR*>( this );
+    }
+
+    operator VkPhysicalDeviceRayTracingPropertiesKHR &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkPhysicalDeviceRayTracingPropertiesKHR*>( this );
+    }
+
+#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
+    auto operator<=>( PhysicalDeviceRayTracingPropertiesKHR const& ) const = default;
+#else
+    bool operator==( PhysicalDeviceRayTracingPropertiesKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ( sType == rhs.sType )
+          && ( pNext == rhs.pNext )
+          && ( shaderGroupHandleSize == rhs.shaderGroupHandleSize )
+          && ( maxRecursionDepth == rhs.maxRecursionDepth )
+          && ( maxShaderGroupStride == rhs.maxShaderGroupStride )
+          && ( shaderGroupBaseAlignment == rhs.shaderGroupBaseAlignment )
+          && ( maxGeometryCount == rhs.maxGeometryCount )
+          && ( maxInstanceCount == rhs.maxInstanceCount )
+          && ( maxPrimitiveCount == rhs.maxPrimitiveCount )
+          && ( maxDescriptorSetAccelerationStructures == rhs.maxDescriptorSetAccelerationStructures )
+          && ( shaderGroupHandleCaptureReplaySize == rhs.shaderGroupHandleCaptureReplaySize );
+    }
+
+    bool operator!=( PhysicalDeviceRayTracingPropertiesKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return !operator==( rhs );
+    }
+#endif
+
+  public:
+    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceRayTracingPropertiesKHR;
+    void* pNext = {};
+    uint32_t shaderGroupHandleSize = {};
+    uint32_t maxRecursionDepth = {};
+    uint32_t maxShaderGroupStride = {};
+    uint32_t shaderGroupBaseAlignment = {};
+    uint64_t maxGeometryCount = {};
+    uint64_t maxInstanceCount = {};
+    uint64_t maxPrimitiveCount = {};
+    uint32_t maxDescriptorSetAccelerationStructures = {};
+    uint32_t shaderGroupHandleCaptureReplaySize = {};
+  };
+  static_assert( sizeof( PhysicalDeviceRayTracingPropertiesKHR ) == sizeof( VkPhysicalDeviceRayTracingPropertiesKHR ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<PhysicalDeviceRayTracingPropertiesKHR>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
   struct PhysicalDeviceRayTracingPropertiesNV
   {
     VULKAN_HPP_CONSTEXPR PhysicalDeviceRayTracingPropertiesNV( uint32_t shaderGroupHandleSize_ = {},
@@ -52043,18 +51853,6 @@
       , maxDescriptorSetAccelerationStructures( maxDescriptorSetAccelerationStructures_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceRayTracingPropertiesNV( PhysicalDeviceRayTracingPropertiesNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , shaderGroupHandleSize( rhs.shaderGroupHandleSize )
-      , maxRecursionDepth( rhs.maxRecursionDepth )
-      , maxShaderGroupStride( rhs.maxShaderGroupStride )
-      , shaderGroupBaseAlignment( rhs.shaderGroupBaseAlignment )
-      , maxGeometryCount( rhs.maxGeometryCount )
-      , maxInstanceCount( rhs.maxInstanceCount )
-      , maxTriangleCount( rhs.maxTriangleCount )
-      , maxDescriptorSetAccelerationStructures( rhs.maxDescriptorSetAccelerationStructures )
-    {}
-
     PhysicalDeviceRayTracingPropertiesNV & operator=( PhysicalDeviceRayTracingPropertiesNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceRayTracingPropertiesNV ) - offsetof( PhysicalDeviceRayTracingPropertiesNV, pNext ) );
@@ -52126,11 +51924,6 @@
       : representativeFragmentTest( representativeFragmentTest_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceRepresentativeFragmentTestFeaturesNV( PhysicalDeviceRepresentativeFragmentTestFeaturesNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , representativeFragmentTest( rhs.representativeFragmentTest )
-    {}
-
     PhysicalDeviceRepresentativeFragmentTestFeaturesNV & operator=( PhysicalDeviceRepresentativeFragmentTestFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceRepresentativeFragmentTestFeaturesNV ) - offsetof( PhysicalDeviceRepresentativeFragmentTestFeaturesNV, pNext ) );
@@ -52203,23 +51996,10 @@
                                                                         VULKAN_HPP_NAMESPACE::Bool32 variableSampleLocations_ = {} ) VULKAN_HPP_NOEXCEPT
       : sampleLocationSampleCounts( sampleLocationSampleCounts_ )
       , maxSampleLocationGridSize( maxSampleLocationGridSize_ )
-      , sampleLocationCoordinateRange{}
+      , sampleLocationCoordinateRange( sampleLocationCoordinateRange_ )
       , sampleLocationSubPixelBits( sampleLocationSubPixelBits_ )
       , variableSampleLocations( variableSampleLocations_ )
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<float,2>::copy( sampleLocationCoordinateRange, sampleLocationCoordinateRange_ );
-    }
-
-    VULKAN_HPP_CONSTEXPR_14 PhysicalDeviceSampleLocationsPropertiesEXT( PhysicalDeviceSampleLocationsPropertiesEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , sampleLocationSampleCounts( rhs.sampleLocationSampleCounts )
-      , maxSampleLocationGridSize( rhs.maxSampleLocationGridSize )
-      , sampleLocationCoordinateRange{}
-      , sampleLocationSubPixelBits( rhs.sampleLocationSubPixelBits )
-      , variableSampleLocations( rhs.variableSampleLocations )
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<float,2>::copy( sampleLocationCoordinateRange, rhs.sampleLocationCoordinateRange );
-    }
+    {}
 
     PhysicalDeviceSampleLocationsPropertiesEXT & operator=( PhysicalDeviceSampleLocationsPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
@@ -52257,7 +52037,7 @@
           && ( pNext == rhs.pNext )
           && ( sampleLocationSampleCounts == rhs.sampleLocationSampleCounts )
           && ( maxSampleLocationGridSize == rhs.maxSampleLocationGridSize )
-          && ( memcmp( sampleLocationCoordinateRange, rhs.sampleLocationCoordinateRange, 2 * sizeof( float ) ) == 0 )
+          && ( sampleLocationCoordinateRange == rhs.sampleLocationCoordinateRange )
           && ( sampleLocationSubPixelBits == rhs.sampleLocationSubPixelBits )
           && ( variableSampleLocations == rhs.variableSampleLocations );
     }
@@ -52273,7 +52053,7 @@
     void* pNext = {};
     VULKAN_HPP_NAMESPACE::SampleCountFlags sampleLocationSampleCounts = {};
     VULKAN_HPP_NAMESPACE::Extent2D maxSampleLocationGridSize = {};
-    float sampleLocationCoordinateRange[2] = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<float, 2> sampleLocationCoordinateRange = {};
     uint32_t sampleLocationSubPixelBits = {};
     VULKAN_HPP_NAMESPACE::Bool32 variableSampleLocations = {};
   };
@@ -52288,12 +52068,6 @@
       , filterMinmaxImageComponentMapping( filterMinmaxImageComponentMapping_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceSamplerFilterMinmaxProperties( PhysicalDeviceSamplerFilterMinmaxProperties const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , filterMinmaxSingleComponentFormats( rhs.filterMinmaxSingleComponentFormats )
-      , filterMinmaxImageComponentMapping( rhs.filterMinmaxImageComponentMapping )
-    {}
-
     PhysicalDeviceSamplerFilterMinmaxProperties & operator=( PhysicalDeviceSamplerFilterMinmaxProperties const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceSamplerFilterMinmaxProperties ) - offsetof( PhysicalDeviceSamplerFilterMinmaxProperties, pNext ) );
@@ -52353,11 +52127,6 @@
       : samplerYcbcrConversion( samplerYcbcrConversion_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceSamplerYcbcrConversionFeatures( PhysicalDeviceSamplerYcbcrConversionFeatures const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , samplerYcbcrConversion( rhs.samplerYcbcrConversion )
-    {}
-
     PhysicalDeviceSamplerYcbcrConversionFeatures & operator=( PhysicalDeviceSamplerYcbcrConversionFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceSamplerYcbcrConversionFeatures ) - offsetof( PhysicalDeviceSamplerYcbcrConversionFeatures, pNext ) );
@@ -52427,11 +52196,6 @@
       : scalarBlockLayout( scalarBlockLayout_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceScalarBlockLayoutFeatures( PhysicalDeviceScalarBlockLayoutFeatures const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , scalarBlockLayout( rhs.scalarBlockLayout )
-    {}
-
     PhysicalDeviceScalarBlockLayoutFeatures & operator=( PhysicalDeviceScalarBlockLayoutFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceScalarBlockLayoutFeatures ) - offsetof( PhysicalDeviceScalarBlockLayoutFeatures, pNext ) );
@@ -52501,11 +52265,6 @@
       : separateDepthStencilLayouts( separateDepthStencilLayouts_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceSeparateDepthStencilLayoutsFeatures( PhysicalDeviceSeparateDepthStencilLayoutsFeatures const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , separateDepthStencilLayouts( rhs.separateDepthStencilLayouts )
-    {}
-
     PhysicalDeviceSeparateDepthStencilLayoutsFeatures & operator=( PhysicalDeviceSeparateDepthStencilLayoutsFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceSeparateDepthStencilLayoutsFeatures ) - offsetof( PhysicalDeviceSeparateDepthStencilLayoutsFeatures, pNext ) );
@@ -52577,12 +52336,6 @@
       , shaderSharedInt64Atomics( shaderSharedInt64Atomics_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceShaderAtomicInt64Features( PhysicalDeviceShaderAtomicInt64Features const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , shaderBufferInt64Atomics( rhs.shaderBufferInt64Atomics )
-      , shaderSharedInt64Atomics( rhs.shaderSharedInt64Atomics )
-    {}
-
     PhysicalDeviceShaderAtomicInt64Features & operator=( PhysicalDeviceShaderAtomicInt64Features const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceShaderAtomicInt64Features ) - offsetof( PhysicalDeviceShaderAtomicInt64Features, pNext ) );
@@ -52662,12 +52415,6 @@
       , shaderDeviceClock( shaderDeviceClock_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceShaderClockFeaturesKHR( PhysicalDeviceShaderClockFeaturesKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , shaderSubgroupClock( rhs.shaderSubgroupClock )
-      , shaderDeviceClock( rhs.shaderDeviceClock )
-    {}
-
     PhysicalDeviceShaderClockFeaturesKHR & operator=( PhysicalDeviceShaderClockFeaturesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceShaderClockFeaturesKHR ) - offsetof( PhysicalDeviceShaderClockFeaturesKHR, pNext ) );
@@ -52747,12 +52494,6 @@
       , activeComputeUnitCount( activeComputeUnitCount_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceShaderCoreProperties2AMD( PhysicalDeviceShaderCoreProperties2AMD const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , shaderCoreFeatures( rhs.shaderCoreFeatures )
-      , activeComputeUnitCount( rhs.activeComputeUnitCount )
-    {}
-
     PhysicalDeviceShaderCoreProperties2AMD & operator=( PhysicalDeviceShaderCoreProperties2AMD const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceShaderCoreProperties2AMD ) - offsetof( PhysicalDeviceShaderCoreProperties2AMD, pNext ) );
@@ -52838,24 +52579,6 @@
       , vgprAllocationGranularity( vgprAllocationGranularity_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceShaderCorePropertiesAMD( PhysicalDeviceShaderCorePropertiesAMD const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , shaderEngineCount( rhs.shaderEngineCount )
-      , shaderArraysPerEngineCount( rhs.shaderArraysPerEngineCount )
-      , computeUnitsPerShaderArray( rhs.computeUnitsPerShaderArray )
-      , simdPerComputeUnit( rhs.simdPerComputeUnit )
-      , wavefrontsPerSimd( rhs.wavefrontsPerSimd )
-      , wavefrontSize( rhs.wavefrontSize )
-      , sgprsPerSimd( rhs.sgprsPerSimd )
-      , minSgprAllocation( rhs.minSgprAllocation )
-      , maxSgprAllocation( rhs.maxSgprAllocation )
-      , sgprAllocationGranularity( rhs.sgprAllocationGranularity )
-      , vgprsPerSimd( rhs.vgprsPerSimd )
-      , minVgprAllocation( rhs.minVgprAllocation )
-      , maxVgprAllocation( rhs.maxVgprAllocation )
-      , vgprAllocationGranularity( rhs.vgprAllocationGranularity )
-    {}
-
     PhysicalDeviceShaderCorePropertiesAMD & operator=( PhysicalDeviceShaderCorePropertiesAMD const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceShaderCorePropertiesAMD ) - offsetof( PhysicalDeviceShaderCorePropertiesAMD, pNext ) );
@@ -52939,11 +52662,6 @@
       : shaderDemoteToHelperInvocation( shaderDemoteToHelperInvocation_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT( PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , shaderDemoteToHelperInvocation( rhs.shaderDemoteToHelperInvocation )
-    {}
-
     PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT & operator=( PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT ) - offsetof( PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT, pNext ) );
@@ -53013,11 +52731,6 @@
       : shaderDrawParameters( shaderDrawParameters_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceShaderDrawParametersFeatures( PhysicalDeviceShaderDrawParametersFeatures const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , shaderDrawParameters( rhs.shaderDrawParameters )
-    {}
-
     PhysicalDeviceShaderDrawParametersFeatures & operator=( PhysicalDeviceShaderDrawParametersFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceShaderDrawParametersFeatures ) - offsetof( PhysicalDeviceShaderDrawParametersFeatures, pNext ) );
@@ -53089,12 +52802,6 @@
       , shaderInt8( shaderInt8_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceShaderFloat16Int8Features( PhysicalDeviceShaderFloat16Int8Features const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , shaderFloat16( rhs.shaderFloat16 )
-      , shaderInt8( rhs.shaderInt8 )
-    {}
-
     PhysicalDeviceShaderFloat16Int8Features & operator=( PhysicalDeviceShaderFloat16Int8Features const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceShaderFloat16Int8Features ) - offsetof( PhysicalDeviceShaderFloat16Int8Features, pNext ) );
@@ -53172,11 +52879,6 @@
       : imageFootprint( imageFootprint_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceShaderImageFootprintFeaturesNV( PhysicalDeviceShaderImageFootprintFeaturesNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , imageFootprint( rhs.imageFootprint )
-    {}
-
     PhysicalDeviceShaderImageFootprintFeaturesNV & operator=( PhysicalDeviceShaderImageFootprintFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceShaderImageFootprintFeaturesNV ) - offsetof( PhysicalDeviceShaderImageFootprintFeaturesNV, pNext ) );
@@ -53246,11 +52948,6 @@
       : shaderIntegerFunctions2( shaderIntegerFunctions2_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceShaderIntegerFunctions2FeaturesINTEL( PhysicalDeviceShaderIntegerFunctions2FeaturesINTEL const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , shaderIntegerFunctions2( rhs.shaderIntegerFunctions2 )
-    {}
-
     PhysicalDeviceShaderIntegerFunctions2FeaturesINTEL & operator=( PhysicalDeviceShaderIntegerFunctions2FeaturesINTEL const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceShaderIntegerFunctions2FeaturesINTEL ) - offsetof( PhysicalDeviceShaderIntegerFunctions2FeaturesINTEL, pNext ) );
@@ -53320,11 +53017,6 @@
       : shaderSMBuiltins( shaderSMBuiltins_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceShaderSMBuiltinsFeaturesNV( PhysicalDeviceShaderSMBuiltinsFeaturesNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , shaderSMBuiltins( rhs.shaderSMBuiltins )
-    {}
-
     PhysicalDeviceShaderSMBuiltinsFeaturesNV & operator=( PhysicalDeviceShaderSMBuiltinsFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceShaderSMBuiltinsFeaturesNV ) - offsetof( PhysicalDeviceShaderSMBuiltinsFeaturesNV, pNext ) );
@@ -53396,12 +53088,6 @@
       , shaderWarpsPerSM( shaderWarpsPerSM_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceShaderSMBuiltinsPropertiesNV( PhysicalDeviceShaderSMBuiltinsPropertiesNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , shaderSMCount( rhs.shaderSMCount )
-      , shaderWarpsPerSM( rhs.shaderWarpsPerSM )
-    {}
-
     PhysicalDeviceShaderSMBuiltinsPropertiesNV & operator=( PhysicalDeviceShaderSMBuiltinsPropertiesNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceShaderSMBuiltinsPropertiesNV ) - offsetof( PhysicalDeviceShaderSMBuiltinsPropertiesNV, pNext ) );
@@ -53461,11 +53147,6 @@
       : shaderSubgroupExtendedTypes( shaderSubgroupExtendedTypes_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceShaderSubgroupExtendedTypesFeatures( PhysicalDeviceShaderSubgroupExtendedTypesFeatures const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , shaderSubgroupExtendedTypes( rhs.shaderSubgroupExtendedTypes )
-    {}
-
     PhysicalDeviceShaderSubgroupExtendedTypesFeatures & operator=( PhysicalDeviceShaderSubgroupExtendedTypesFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceShaderSubgroupExtendedTypesFeatures ) - offsetof( PhysicalDeviceShaderSubgroupExtendedTypesFeatures, pNext ) );
@@ -53537,12 +53218,6 @@
       , shadingRateCoarseSampleOrder( shadingRateCoarseSampleOrder_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceShadingRateImageFeaturesNV( PhysicalDeviceShadingRateImageFeaturesNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , shadingRateImage( rhs.shadingRateImage )
-      , shadingRateCoarseSampleOrder( rhs.shadingRateCoarseSampleOrder )
-    {}
-
     PhysicalDeviceShadingRateImageFeaturesNV & operator=( PhysicalDeviceShadingRateImageFeaturesNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceShadingRateImageFeaturesNV ) - offsetof( PhysicalDeviceShadingRateImageFeaturesNV, pNext ) );
@@ -53624,13 +53299,6 @@
       , shadingRateMaxCoarseSamples( shadingRateMaxCoarseSamples_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceShadingRateImagePropertiesNV( PhysicalDeviceShadingRateImagePropertiesNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , shadingRateTexelSize( rhs.shadingRateTexelSize )
-      , shadingRatePaletteSize( rhs.shadingRatePaletteSize )
-      , shadingRateMaxCoarseSamples( rhs.shadingRateMaxCoarseSamples )
-    {}
-
     PhysicalDeviceShadingRateImagePropertiesNV & operator=( PhysicalDeviceShadingRateImagePropertiesNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceShadingRateImagePropertiesNV ) - offsetof( PhysicalDeviceShadingRateImagePropertiesNV, pNext ) );
@@ -53700,15 +53368,6 @@
       , tiling( tiling_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceSparseImageFormatInfo2( PhysicalDeviceSparseImageFormatInfo2 const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , format( rhs.format )
-      , type( rhs.type )
-      , samples( rhs.samples )
-      , usage( rhs.usage )
-      , tiling( rhs.tiling )
-    {}
-
     PhysicalDeviceSparseImageFormatInfo2 & operator=( PhysicalDeviceSparseImageFormatInfo2 const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceSparseImageFormatInfo2 ) - offsetof( PhysicalDeviceSparseImageFormatInfo2, pNext ) );
@@ -53816,14 +53475,6 @@
       , quadOperationsInAllStages( quadOperationsInAllStages_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceSubgroupProperties( PhysicalDeviceSubgroupProperties const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , subgroupSize( rhs.subgroupSize )
-      , supportedStages( rhs.supportedStages )
-      , supportedOperations( rhs.supportedOperations )
-      , quadOperationsInAllStages( rhs.quadOperationsInAllStages )
-    {}
-
     PhysicalDeviceSubgroupProperties & operator=( PhysicalDeviceSubgroupProperties const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceSubgroupProperties ) - offsetof( PhysicalDeviceSubgroupProperties, pNext ) );
@@ -53889,12 +53540,6 @@
       , computeFullSubgroups( computeFullSubgroups_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceSubgroupSizeControlFeaturesEXT( PhysicalDeviceSubgroupSizeControlFeaturesEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , subgroupSizeControl( rhs.subgroupSizeControl )
-      , computeFullSubgroups( rhs.computeFullSubgroups )
-    {}
-
     PhysicalDeviceSubgroupSizeControlFeaturesEXT & operator=( PhysicalDeviceSubgroupSizeControlFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceSubgroupSizeControlFeaturesEXT ) - offsetof( PhysicalDeviceSubgroupSizeControlFeaturesEXT, pNext ) );
@@ -53978,14 +53623,6 @@
       , requiredSubgroupSizeStages( requiredSubgroupSizeStages_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceSubgroupSizeControlPropertiesEXT( PhysicalDeviceSubgroupSizeControlPropertiesEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , minSubgroupSize( rhs.minSubgroupSize )
-      , maxSubgroupSize( rhs.maxSubgroupSize )
-      , maxComputeWorkgroupSubgroups( rhs.maxComputeWorkgroupSubgroups )
-      , requiredSubgroupSizeStages( rhs.requiredSubgroupSizeStages )
-    {}
-
     PhysicalDeviceSubgroupSizeControlPropertiesEXT & operator=( PhysicalDeviceSubgroupSizeControlPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceSubgroupSizeControlPropertiesEXT ) - offsetof( PhysicalDeviceSubgroupSizeControlPropertiesEXT, pNext ) );
@@ -54049,11 +53686,6 @@
       : surface( surface_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceSurfaceInfo2KHR( PhysicalDeviceSurfaceInfo2KHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , surface( rhs.surface )
-    {}
-
     PhysicalDeviceSurfaceInfo2KHR & operator=( PhysicalDeviceSurfaceInfo2KHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceSurfaceInfo2KHR ) - offsetof( PhysicalDeviceSurfaceInfo2KHR, pNext ) );
@@ -54123,11 +53755,6 @@
       : texelBufferAlignment( texelBufferAlignment_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceTexelBufferAlignmentFeaturesEXT( PhysicalDeviceTexelBufferAlignmentFeaturesEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , texelBufferAlignment( rhs.texelBufferAlignment )
-    {}
-
     PhysicalDeviceTexelBufferAlignmentFeaturesEXT & operator=( PhysicalDeviceTexelBufferAlignmentFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceTexelBufferAlignmentFeaturesEXT ) - offsetof( PhysicalDeviceTexelBufferAlignmentFeaturesEXT, pNext ) );
@@ -54203,14 +53830,6 @@
       , uniformTexelBufferOffsetSingleTexelAlignment( uniformTexelBufferOffsetSingleTexelAlignment_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceTexelBufferAlignmentPropertiesEXT( PhysicalDeviceTexelBufferAlignmentPropertiesEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , storageTexelBufferOffsetAlignmentBytes( rhs.storageTexelBufferOffsetAlignmentBytes )
-      , storageTexelBufferOffsetSingleTexelAlignment( rhs.storageTexelBufferOffsetSingleTexelAlignment )
-      , uniformTexelBufferOffsetAlignmentBytes( rhs.uniformTexelBufferOffsetAlignmentBytes )
-      , uniformTexelBufferOffsetSingleTexelAlignment( rhs.uniformTexelBufferOffsetSingleTexelAlignment )
-    {}
-
     PhysicalDeviceTexelBufferAlignmentPropertiesEXT & operator=( PhysicalDeviceTexelBufferAlignmentPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceTexelBufferAlignmentPropertiesEXT ) - offsetof( PhysicalDeviceTexelBufferAlignmentPropertiesEXT, pNext ) );
@@ -54274,11 +53893,6 @@
       : textureCompressionASTC_HDR( textureCompressionASTC_HDR_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceTextureCompressionASTCHDRFeaturesEXT( PhysicalDeviceTextureCompressionASTCHDRFeaturesEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , textureCompressionASTC_HDR( rhs.textureCompressionASTC_HDR )
-    {}
-
     PhysicalDeviceTextureCompressionASTCHDRFeaturesEXT & operator=( PhysicalDeviceTextureCompressionASTCHDRFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceTextureCompressionASTCHDRFeaturesEXT ) - offsetof( PhysicalDeviceTextureCompressionASTCHDRFeaturesEXT, pNext ) );
@@ -54348,11 +53962,6 @@
       : timelineSemaphore( timelineSemaphore_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceTimelineSemaphoreFeatures( PhysicalDeviceTimelineSemaphoreFeatures const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , timelineSemaphore( rhs.timelineSemaphore )
-    {}
-
     PhysicalDeviceTimelineSemaphoreFeatures & operator=( PhysicalDeviceTimelineSemaphoreFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceTimelineSemaphoreFeatures ) - offsetof( PhysicalDeviceTimelineSemaphoreFeatures, pNext ) );
@@ -54422,11 +54031,6 @@
       : maxTimelineSemaphoreValueDifference( maxTimelineSemaphoreValueDifference_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceTimelineSemaphoreProperties( PhysicalDeviceTimelineSemaphoreProperties const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , maxTimelineSemaphoreValueDifference( rhs.maxTimelineSemaphoreValueDifference )
-    {}
-
     PhysicalDeviceTimelineSemaphoreProperties & operator=( PhysicalDeviceTimelineSemaphoreProperties const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceTimelineSemaphoreProperties ) - offsetof( PhysicalDeviceTimelineSemaphoreProperties, pNext ) );
@@ -54485,31 +54089,12 @@
                                                              VULKAN_HPP_NAMESPACE::ToolPurposeFlagsEXT purposes_ = {},
                                                              std::array<char,VK_MAX_DESCRIPTION_SIZE> const& description_ = {},
                                                              std::array<char,VK_MAX_EXTENSION_NAME_SIZE> const& layer_ = {} ) VULKAN_HPP_NOEXCEPT
-      : name{}
-      , version{}
+      : name( name_ )
+      , version( version_ )
       , purposes( purposes_ )
-      , description{}
-      , layer{}
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_EXTENSION_NAME_SIZE>::copy( name, name_ );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_EXTENSION_NAME_SIZE>::copy( version, version_ );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DESCRIPTION_SIZE>::copy( description, description_ );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_EXTENSION_NAME_SIZE>::copy( layer, layer_ );
-    }
-
-    VULKAN_HPP_CONSTEXPR_14 PhysicalDeviceToolPropertiesEXT( PhysicalDeviceToolPropertiesEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , name{}
-      , version{}
-      , purposes( rhs.purposes )
-      , description{}
-      , layer{}
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_EXTENSION_NAME_SIZE>::copy( name, rhs.name );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_EXTENSION_NAME_SIZE>::copy( version, rhs.version );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DESCRIPTION_SIZE>::copy( description, rhs.description );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_EXTENSION_NAME_SIZE>::copy( layer, rhs.layer );
-    }
+      , description( description_ )
+      , layer( layer_ )
+    {}
 
     PhysicalDeviceToolPropertiesEXT & operator=( PhysicalDeviceToolPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
@@ -54545,11 +54130,11 @@
     {
       return ( sType == rhs.sType )
           && ( pNext == rhs.pNext )
-          && ( memcmp( name, rhs.name, VK_MAX_EXTENSION_NAME_SIZE * sizeof( char ) ) == 0 )
-          && ( memcmp( version, rhs.version, VK_MAX_EXTENSION_NAME_SIZE * sizeof( char ) ) == 0 )
+          && ( name == rhs.name )
+          && ( version == rhs.version )
           && ( purposes == rhs.purposes )
-          && ( memcmp( description, rhs.description, VK_MAX_DESCRIPTION_SIZE * sizeof( char ) ) == 0 )
-          && ( memcmp( layer, rhs.layer, VK_MAX_EXTENSION_NAME_SIZE * sizeof( char ) ) == 0 );
+          && ( description == rhs.description )
+          && ( layer == rhs.layer );
     }
 
     bool operator!=( PhysicalDeviceToolPropertiesEXT const& rhs ) const VULKAN_HPP_NOEXCEPT
@@ -54561,11 +54146,11 @@
   public:
     const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceToolPropertiesEXT;
     void* pNext = {};
-    char name[VK_MAX_EXTENSION_NAME_SIZE] = {};
-    char version[VK_MAX_EXTENSION_NAME_SIZE] = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<char, VK_MAX_EXTENSION_NAME_SIZE> name = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<char, VK_MAX_EXTENSION_NAME_SIZE> version = {};
     VULKAN_HPP_NAMESPACE::ToolPurposeFlagsEXT purposes = {};
-    char description[VK_MAX_DESCRIPTION_SIZE] = {};
-    char layer[VK_MAX_EXTENSION_NAME_SIZE] = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<char, VK_MAX_DESCRIPTION_SIZE> description = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<char, VK_MAX_EXTENSION_NAME_SIZE> layer = {};
   };
   static_assert( sizeof( PhysicalDeviceToolPropertiesEXT ) == sizeof( VkPhysicalDeviceToolPropertiesEXT ), "struct and wrapper have different size!" );
   static_assert( std::is_standard_layout<PhysicalDeviceToolPropertiesEXT>::value, "struct wrapper is not a standard layout!" );
@@ -54578,12 +54163,6 @@
       , geometryStreams( geometryStreams_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceTransformFeedbackFeaturesEXT( PhysicalDeviceTransformFeedbackFeaturesEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , transformFeedback( rhs.transformFeedback )
-      , geometryStreams( rhs.geometryStreams )
-    {}
-
     PhysicalDeviceTransformFeedbackFeaturesEXT & operator=( PhysicalDeviceTransformFeedbackFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceTransformFeedbackFeaturesEXT ) - offsetof( PhysicalDeviceTransformFeedbackFeaturesEXT, pNext ) );
@@ -54679,20 +54258,6 @@
       , transformFeedbackDraw( transformFeedbackDraw_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceTransformFeedbackPropertiesEXT( PhysicalDeviceTransformFeedbackPropertiesEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , maxTransformFeedbackStreams( rhs.maxTransformFeedbackStreams )
-      , maxTransformFeedbackBuffers( rhs.maxTransformFeedbackBuffers )
-      , maxTransformFeedbackBufferSize( rhs.maxTransformFeedbackBufferSize )
-      , maxTransformFeedbackStreamDataSize( rhs.maxTransformFeedbackStreamDataSize )
-      , maxTransformFeedbackBufferDataSize( rhs.maxTransformFeedbackBufferDataSize )
-      , maxTransformFeedbackBufferDataStride( rhs.maxTransformFeedbackBufferDataStride )
-      , transformFeedbackQueries( rhs.transformFeedbackQueries )
-      , transformFeedbackStreamsLinesTriangles( rhs.transformFeedbackStreamsLinesTriangles )
-      , transformFeedbackRasterizationStreamSelect( rhs.transformFeedbackRasterizationStreamSelect )
-      , transformFeedbackDraw( rhs.transformFeedbackDraw )
-    {}
-
     PhysicalDeviceTransformFeedbackPropertiesEXT & operator=( PhysicalDeviceTransformFeedbackPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceTransformFeedbackPropertiesEXT ) - offsetof( PhysicalDeviceTransformFeedbackPropertiesEXT, pNext ) );
@@ -54768,11 +54333,6 @@
       : uniformBufferStandardLayout( uniformBufferStandardLayout_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceUniformBufferStandardLayoutFeatures( PhysicalDeviceUniformBufferStandardLayoutFeatures const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , uniformBufferStandardLayout( rhs.uniformBufferStandardLayout )
-    {}
-
     PhysicalDeviceUniformBufferStandardLayoutFeatures & operator=( PhysicalDeviceUniformBufferStandardLayoutFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceUniformBufferStandardLayoutFeatures ) - offsetof( PhysicalDeviceUniformBufferStandardLayoutFeatures, pNext ) );
@@ -54844,12 +54404,6 @@
       , variablePointers( variablePointers_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceVariablePointersFeatures( PhysicalDeviceVariablePointersFeatures const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , variablePointersStorageBuffer( rhs.variablePointersStorageBuffer )
-      , variablePointers( rhs.variablePointers )
-    {}
-
     PhysicalDeviceVariablePointersFeatures & operator=( PhysicalDeviceVariablePointersFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceVariablePointersFeatures ) - offsetof( PhysicalDeviceVariablePointersFeatures, pNext ) );
@@ -54929,12 +54483,6 @@
       , vertexAttributeInstanceRateZeroDivisor( vertexAttributeInstanceRateZeroDivisor_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceVertexAttributeDivisorFeaturesEXT( PhysicalDeviceVertexAttributeDivisorFeaturesEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , vertexAttributeInstanceRateDivisor( rhs.vertexAttributeInstanceRateDivisor )
-      , vertexAttributeInstanceRateZeroDivisor( rhs.vertexAttributeInstanceRateZeroDivisor )
-    {}
-
     PhysicalDeviceVertexAttributeDivisorFeaturesEXT & operator=( PhysicalDeviceVertexAttributeDivisorFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceVertexAttributeDivisorFeaturesEXT ) - offsetof( PhysicalDeviceVertexAttributeDivisorFeaturesEXT, pNext ) );
@@ -55012,11 +54560,6 @@
       : maxVertexAttribDivisor( maxVertexAttribDivisor_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceVertexAttributeDivisorPropertiesEXT( PhysicalDeviceVertexAttributeDivisorPropertiesEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , maxVertexAttribDivisor( rhs.maxVertexAttribDivisor )
-    {}
-
     PhysicalDeviceVertexAttributeDivisorPropertiesEXT & operator=( PhysicalDeviceVertexAttributeDivisorPropertiesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceVertexAttributeDivisorPropertiesEXT ) - offsetof( PhysicalDeviceVertexAttributeDivisorPropertiesEXT, pNext ) );
@@ -55096,22 +54639,6 @@
       , shaderDrawParameters( shaderDrawParameters_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceVulkan11Features( PhysicalDeviceVulkan11Features const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , storageBuffer16BitAccess( rhs.storageBuffer16BitAccess )
-      , uniformAndStorageBuffer16BitAccess( rhs.uniformAndStorageBuffer16BitAccess )
-      , storagePushConstant16( rhs.storagePushConstant16 )
-      , storageInputOutput16( rhs.storageInputOutput16 )
-      , multiview( rhs.multiview )
-      , multiviewGeometryShader( rhs.multiviewGeometryShader )
-      , multiviewTessellationShader( rhs.multiviewTessellationShader )
-      , variablePointersStorageBuffer( rhs.variablePointersStorageBuffer )
-      , variablePointers( rhs.variablePointers )
-      , protectedMemory( rhs.protectedMemory )
-      , samplerYcbcrConversion( rhs.samplerYcbcrConversion )
-      , shaderDrawParameters( rhs.shaderDrawParameters )
-    {}
-
     PhysicalDeviceVulkan11Features & operator=( PhysicalDeviceVulkan11Features const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceVulkan11Features ) - offsetof( PhysicalDeviceVulkan11Features, pNext ) );
@@ -55280,9 +54807,9 @@
                                                               VULKAN_HPP_NAMESPACE::Bool32 protectedNoFault_ = {},
                                                               uint32_t maxPerSetDescriptors_ = {},
                                                               VULKAN_HPP_NAMESPACE::DeviceSize maxMemoryAllocationSize_ = {} ) VULKAN_HPP_NOEXCEPT
-      : deviceUUID{}
-      , driverUUID{}
-      , deviceLUID{}
+      : deviceUUID( deviceUUID_ )
+      , driverUUID( driverUUID_ )
+      , deviceLUID( deviceLUID_ )
       , deviceNodeMask( deviceNodeMask_ )
       , deviceLUIDValid( deviceLUIDValid_ )
       , subgroupSize( subgroupSize_ )
@@ -55295,34 +54822,7 @@
       , protectedNoFault( protectedNoFault_ )
       , maxPerSetDescriptors( maxPerSetDescriptors_ )
       , maxMemoryAllocationSize( maxMemoryAllocationSize_ )
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint8_t,VK_UUID_SIZE>::copy( deviceUUID, deviceUUID_ );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint8_t,VK_UUID_SIZE>::copy( driverUUID, driverUUID_ );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint8_t,VK_LUID_SIZE>::copy( deviceLUID, deviceLUID_ );
-    }
-
-    VULKAN_HPP_CONSTEXPR_14 PhysicalDeviceVulkan11Properties( PhysicalDeviceVulkan11Properties const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , deviceUUID{}
-      , driverUUID{}
-      , deviceLUID{}
-      , deviceNodeMask( rhs.deviceNodeMask )
-      , deviceLUIDValid( rhs.deviceLUIDValid )
-      , subgroupSize( rhs.subgroupSize )
-      , subgroupSupportedStages( rhs.subgroupSupportedStages )
-      , subgroupSupportedOperations( rhs.subgroupSupportedOperations )
-      , subgroupQuadOperationsInAllStages( rhs.subgroupQuadOperationsInAllStages )
-      , pointClippingBehavior( rhs.pointClippingBehavior )
-      , maxMultiviewViewCount( rhs.maxMultiviewViewCount )
-      , maxMultiviewInstanceIndex( rhs.maxMultiviewInstanceIndex )
-      , protectedNoFault( rhs.protectedNoFault )
-      , maxPerSetDescriptors( rhs.maxPerSetDescriptors )
-      , maxMemoryAllocationSize( rhs.maxMemoryAllocationSize )
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint8_t,VK_UUID_SIZE>::copy( deviceUUID, rhs.deviceUUID );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint8_t,VK_UUID_SIZE>::copy( driverUUID, rhs.driverUUID );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint8_t,VK_LUID_SIZE>::copy( deviceLUID, rhs.deviceLUID );
-    }
+    {}
 
     PhysicalDeviceVulkan11Properties & operator=( PhysicalDeviceVulkan11Properties const & rhs ) VULKAN_HPP_NOEXCEPT
     {
@@ -55341,102 +54841,6 @@
       return *this;
     }
 
-    PhysicalDeviceVulkan11Properties & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
-    {
-      pNext = pNext_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan11Properties & setDeviceUUID( std::array<uint8_t,VK_UUID_SIZE> deviceUUID_ ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( deviceUUID, deviceUUID_.data(), VK_UUID_SIZE * sizeof( uint8_t ) );
-      return *this;
-    }
-
-    PhysicalDeviceVulkan11Properties & setDriverUUID( std::array<uint8_t,VK_UUID_SIZE> driverUUID_ ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( driverUUID, driverUUID_.data(), VK_UUID_SIZE * sizeof( uint8_t ) );
-      return *this;
-    }
-
-    PhysicalDeviceVulkan11Properties & setDeviceLUID( std::array<uint8_t,VK_LUID_SIZE> deviceLUID_ ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( deviceLUID, deviceLUID_.data(), VK_LUID_SIZE * sizeof( uint8_t ) );
-      return *this;
-    }
-
-    PhysicalDeviceVulkan11Properties & setDeviceNodeMask( uint32_t deviceNodeMask_ ) VULKAN_HPP_NOEXCEPT
-    {
-      deviceNodeMask = deviceNodeMask_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan11Properties & setDeviceLUIDValid( VULKAN_HPP_NAMESPACE::Bool32 deviceLUIDValid_ ) VULKAN_HPP_NOEXCEPT
-    {
-      deviceLUIDValid = deviceLUIDValid_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan11Properties & setSubgroupSize( uint32_t subgroupSize_ ) VULKAN_HPP_NOEXCEPT
-    {
-      subgroupSize = subgroupSize_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan11Properties & setSubgroupSupportedStages( VULKAN_HPP_NAMESPACE::ShaderStageFlags subgroupSupportedStages_ ) VULKAN_HPP_NOEXCEPT
-    {
-      subgroupSupportedStages = subgroupSupportedStages_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan11Properties & setSubgroupSupportedOperations( VULKAN_HPP_NAMESPACE::SubgroupFeatureFlags subgroupSupportedOperations_ ) VULKAN_HPP_NOEXCEPT
-    {
-      subgroupSupportedOperations = subgroupSupportedOperations_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan11Properties & setSubgroupQuadOperationsInAllStages( VULKAN_HPP_NAMESPACE::Bool32 subgroupQuadOperationsInAllStages_ ) VULKAN_HPP_NOEXCEPT
-    {
-      subgroupQuadOperationsInAllStages = subgroupQuadOperationsInAllStages_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan11Properties & setPointClippingBehavior( VULKAN_HPP_NAMESPACE::PointClippingBehavior pointClippingBehavior_ ) VULKAN_HPP_NOEXCEPT
-    {
-      pointClippingBehavior = pointClippingBehavior_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan11Properties & setMaxMultiviewViewCount( uint32_t maxMultiviewViewCount_ ) VULKAN_HPP_NOEXCEPT
-    {
-      maxMultiviewViewCount = maxMultiviewViewCount_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan11Properties & setMaxMultiviewInstanceIndex( uint32_t maxMultiviewInstanceIndex_ ) VULKAN_HPP_NOEXCEPT
-    {
-      maxMultiviewInstanceIndex = maxMultiviewInstanceIndex_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan11Properties & setProtectedNoFault( VULKAN_HPP_NAMESPACE::Bool32 protectedNoFault_ ) VULKAN_HPP_NOEXCEPT
-    {
-      protectedNoFault = protectedNoFault_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan11Properties & setMaxPerSetDescriptors( uint32_t maxPerSetDescriptors_ ) VULKAN_HPP_NOEXCEPT
-    {
-      maxPerSetDescriptors = maxPerSetDescriptors_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan11Properties & setMaxMemoryAllocationSize( VULKAN_HPP_NAMESPACE::DeviceSize maxMemoryAllocationSize_ ) VULKAN_HPP_NOEXCEPT
-    {
-      maxMemoryAllocationSize = maxMemoryAllocationSize_;
-      return *this;
-    }
-
     operator VkPhysicalDeviceVulkan11Properties const&() const VULKAN_HPP_NOEXCEPT
     {
       return *reinterpret_cast<const VkPhysicalDeviceVulkan11Properties*>( this );
@@ -55454,9 +54858,9 @@
     {
       return ( sType == rhs.sType )
           && ( pNext == rhs.pNext )
-          && ( memcmp( deviceUUID, rhs.deviceUUID, VK_UUID_SIZE * sizeof( uint8_t ) ) == 0 )
-          && ( memcmp( driverUUID, rhs.driverUUID, VK_UUID_SIZE * sizeof( uint8_t ) ) == 0 )
-          && ( memcmp( deviceLUID, rhs.deviceLUID, VK_LUID_SIZE * sizeof( uint8_t ) ) == 0 )
+          && ( deviceUUID == rhs.deviceUUID )
+          && ( driverUUID == rhs.driverUUID )
+          && ( deviceLUID == rhs.deviceLUID )
           && ( deviceNodeMask == rhs.deviceNodeMask )
           && ( deviceLUIDValid == rhs.deviceLUIDValid )
           && ( subgroupSize == rhs.subgroupSize )
@@ -55480,9 +54884,9 @@
   public:
     const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceVulkan11Properties;
     void* pNext = {};
-    uint8_t deviceUUID[VK_UUID_SIZE] = {};
-    uint8_t driverUUID[VK_UUID_SIZE] = {};
-    uint8_t deviceLUID[VK_LUID_SIZE] = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<uint8_t, VK_UUID_SIZE> deviceUUID = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<uint8_t, VK_UUID_SIZE> driverUUID = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<uint8_t, VK_LUID_SIZE> deviceLUID = {};
     uint32_t deviceNodeMask = {};
     VULKAN_HPP_NAMESPACE::Bool32 deviceLUIDValid = {};
     uint32_t subgroupSize = {};
@@ -55597,57 +55001,6 @@
       , subgroupBroadcastDynamicId( subgroupBroadcastDynamicId_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceVulkan12Features( PhysicalDeviceVulkan12Features const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , samplerMirrorClampToEdge( rhs.samplerMirrorClampToEdge )
-      , drawIndirectCount( rhs.drawIndirectCount )
-      , storageBuffer8BitAccess( rhs.storageBuffer8BitAccess )
-      , uniformAndStorageBuffer8BitAccess( rhs.uniformAndStorageBuffer8BitAccess )
-      , storagePushConstant8( rhs.storagePushConstant8 )
-      , shaderBufferInt64Atomics( rhs.shaderBufferInt64Atomics )
-      , shaderSharedInt64Atomics( rhs.shaderSharedInt64Atomics )
-      , shaderFloat16( rhs.shaderFloat16 )
-      , shaderInt8( rhs.shaderInt8 )
-      , descriptorIndexing( rhs.descriptorIndexing )
-      , shaderInputAttachmentArrayDynamicIndexing( rhs.shaderInputAttachmentArrayDynamicIndexing )
-      , shaderUniformTexelBufferArrayDynamicIndexing( rhs.shaderUniformTexelBufferArrayDynamicIndexing )
-      , shaderStorageTexelBufferArrayDynamicIndexing( rhs.shaderStorageTexelBufferArrayDynamicIndexing )
-      , shaderUniformBufferArrayNonUniformIndexing( rhs.shaderUniformBufferArrayNonUniformIndexing )
-      , shaderSampledImageArrayNonUniformIndexing( rhs.shaderSampledImageArrayNonUniformIndexing )
-      , shaderStorageBufferArrayNonUniformIndexing( rhs.shaderStorageBufferArrayNonUniformIndexing )
-      , shaderStorageImageArrayNonUniformIndexing( rhs.shaderStorageImageArrayNonUniformIndexing )
-      , shaderInputAttachmentArrayNonUniformIndexing( rhs.shaderInputAttachmentArrayNonUniformIndexing )
-      , shaderUniformTexelBufferArrayNonUniformIndexing( rhs.shaderUniformTexelBufferArrayNonUniformIndexing )
-      , shaderStorageTexelBufferArrayNonUniformIndexing( rhs.shaderStorageTexelBufferArrayNonUniformIndexing )
-      , descriptorBindingUniformBufferUpdateAfterBind( rhs.descriptorBindingUniformBufferUpdateAfterBind )
-      , descriptorBindingSampledImageUpdateAfterBind( rhs.descriptorBindingSampledImageUpdateAfterBind )
-      , descriptorBindingStorageImageUpdateAfterBind( rhs.descriptorBindingStorageImageUpdateAfterBind )
-      , descriptorBindingStorageBufferUpdateAfterBind( rhs.descriptorBindingStorageBufferUpdateAfterBind )
-      , descriptorBindingUniformTexelBufferUpdateAfterBind( rhs.descriptorBindingUniformTexelBufferUpdateAfterBind )
-      , descriptorBindingStorageTexelBufferUpdateAfterBind( rhs.descriptorBindingStorageTexelBufferUpdateAfterBind )
-      , descriptorBindingUpdateUnusedWhilePending( rhs.descriptorBindingUpdateUnusedWhilePending )
-      , descriptorBindingPartiallyBound( rhs.descriptorBindingPartiallyBound )
-      , descriptorBindingVariableDescriptorCount( rhs.descriptorBindingVariableDescriptorCount )
-      , runtimeDescriptorArray( rhs.runtimeDescriptorArray )
-      , samplerFilterMinmax( rhs.samplerFilterMinmax )
-      , scalarBlockLayout( rhs.scalarBlockLayout )
-      , imagelessFramebuffer( rhs.imagelessFramebuffer )
-      , uniformBufferStandardLayout( rhs.uniformBufferStandardLayout )
-      , shaderSubgroupExtendedTypes( rhs.shaderSubgroupExtendedTypes )
-      , separateDepthStencilLayouts( rhs.separateDepthStencilLayouts )
-      , hostQueryReset( rhs.hostQueryReset )
-      , timelineSemaphore( rhs.timelineSemaphore )
-      , bufferDeviceAddress( rhs.bufferDeviceAddress )
-      , bufferDeviceAddressCaptureReplay( rhs.bufferDeviceAddressCaptureReplay )
-      , bufferDeviceAddressMultiDevice( rhs.bufferDeviceAddressMultiDevice )
-      , vulkanMemoryModel( rhs.vulkanMemoryModel )
-      , vulkanMemoryModelDeviceScope( rhs.vulkanMemoryModelDeviceScope )
-      , vulkanMemoryModelAvailabilityVisibilityChains( rhs.vulkanMemoryModelAvailabilityVisibilityChains )
-      , shaderOutputViewportIndex( rhs.shaderOutputViewportIndex )
-      , shaderOutputLayer( rhs.shaderOutputLayer )
-      , subgroupBroadcastDynamicId( rhs.subgroupBroadcastDynamicId )
-    {}
-
     PhysicalDeviceVulkan12Features & operator=( PhysicalDeviceVulkan12Features const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceVulkan12Features ) - offsetof( PhysicalDeviceVulkan12Features, pNext ) );
@@ -56134,8 +55487,8 @@
                                                               uint64_t maxTimelineSemaphoreValueDifference_ = {},
                                                               VULKAN_HPP_NAMESPACE::SampleCountFlags framebufferIntegerColorSampleCounts_ = {} ) VULKAN_HPP_NOEXCEPT
       : driverID( driverID_ )
-      , driverName{}
-      , driverInfo{}
+      , driverName( driverName_ )
+      , driverInfo( driverInfo_ )
       , conformanceVersion( conformanceVersion_ )
       , denormBehaviorIndependence( denormBehaviorIndependence_ )
       , roundingModeIndependence( roundingModeIndependence_ )
@@ -56185,69 +55538,7 @@
       , filterMinmaxImageComponentMapping( filterMinmaxImageComponentMapping_ )
       , maxTimelineSemaphoreValueDifference( maxTimelineSemaphoreValueDifference_ )
       , framebufferIntegerColorSampleCounts( framebufferIntegerColorSampleCounts_ )
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DRIVER_NAME_SIZE>::copy( driverName, driverName_ );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DRIVER_INFO_SIZE>::copy( driverInfo, driverInfo_ );
-    }
-
-    VULKAN_HPP_CONSTEXPR_14 PhysicalDeviceVulkan12Properties( PhysicalDeviceVulkan12Properties const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , driverID( rhs.driverID )
-      , driverName{}
-      , driverInfo{}
-      , conformanceVersion( rhs.conformanceVersion )
-      , denormBehaviorIndependence( rhs.denormBehaviorIndependence )
-      , roundingModeIndependence( rhs.roundingModeIndependence )
-      , shaderSignedZeroInfNanPreserveFloat16( rhs.shaderSignedZeroInfNanPreserveFloat16 )
-      , shaderSignedZeroInfNanPreserveFloat32( rhs.shaderSignedZeroInfNanPreserveFloat32 )
-      , shaderSignedZeroInfNanPreserveFloat64( rhs.shaderSignedZeroInfNanPreserveFloat64 )
-      , shaderDenormPreserveFloat16( rhs.shaderDenormPreserveFloat16 )
-      , shaderDenormPreserveFloat32( rhs.shaderDenormPreserveFloat32 )
-      , shaderDenormPreserveFloat64( rhs.shaderDenormPreserveFloat64 )
-      , shaderDenormFlushToZeroFloat16( rhs.shaderDenormFlushToZeroFloat16 )
-      , shaderDenormFlushToZeroFloat32( rhs.shaderDenormFlushToZeroFloat32 )
-      , shaderDenormFlushToZeroFloat64( rhs.shaderDenormFlushToZeroFloat64 )
-      , shaderRoundingModeRTEFloat16( rhs.shaderRoundingModeRTEFloat16 )
-      , shaderRoundingModeRTEFloat32( rhs.shaderRoundingModeRTEFloat32 )
-      , shaderRoundingModeRTEFloat64( rhs.shaderRoundingModeRTEFloat64 )
-      , shaderRoundingModeRTZFloat16( rhs.shaderRoundingModeRTZFloat16 )
-      , shaderRoundingModeRTZFloat32( rhs.shaderRoundingModeRTZFloat32 )
-      , shaderRoundingModeRTZFloat64( rhs.shaderRoundingModeRTZFloat64 )
-      , maxUpdateAfterBindDescriptorsInAllPools( rhs.maxUpdateAfterBindDescriptorsInAllPools )
-      , shaderUniformBufferArrayNonUniformIndexingNative( rhs.shaderUniformBufferArrayNonUniformIndexingNative )
-      , shaderSampledImageArrayNonUniformIndexingNative( rhs.shaderSampledImageArrayNonUniformIndexingNative )
-      , shaderStorageBufferArrayNonUniformIndexingNative( rhs.shaderStorageBufferArrayNonUniformIndexingNative )
-      , shaderStorageImageArrayNonUniformIndexingNative( rhs.shaderStorageImageArrayNonUniformIndexingNative )
-      , shaderInputAttachmentArrayNonUniformIndexingNative( rhs.shaderInputAttachmentArrayNonUniformIndexingNative )
-      , robustBufferAccessUpdateAfterBind( rhs.robustBufferAccessUpdateAfterBind )
-      , quadDivergentImplicitLod( rhs.quadDivergentImplicitLod )
-      , maxPerStageDescriptorUpdateAfterBindSamplers( rhs.maxPerStageDescriptorUpdateAfterBindSamplers )
-      , maxPerStageDescriptorUpdateAfterBindUniformBuffers( rhs.maxPerStageDescriptorUpdateAfterBindUniformBuffers )
-      , maxPerStageDescriptorUpdateAfterBindStorageBuffers( rhs.maxPerStageDescriptorUpdateAfterBindStorageBuffers )
-      , maxPerStageDescriptorUpdateAfterBindSampledImages( rhs.maxPerStageDescriptorUpdateAfterBindSampledImages )
-      , maxPerStageDescriptorUpdateAfterBindStorageImages( rhs.maxPerStageDescriptorUpdateAfterBindStorageImages )
-      , maxPerStageDescriptorUpdateAfterBindInputAttachments( rhs.maxPerStageDescriptorUpdateAfterBindInputAttachments )
-      , maxPerStageUpdateAfterBindResources( rhs.maxPerStageUpdateAfterBindResources )
-      , maxDescriptorSetUpdateAfterBindSamplers( rhs.maxDescriptorSetUpdateAfterBindSamplers )
-      , maxDescriptorSetUpdateAfterBindUniformBuffers( rhs.maxDescriptorSetUpdateAfterBindUniformBuffers )
-      , maxDescriptorSetUpdateAfterBindUniformBuffersDynamic( rhs.maxDescriptorSetUpdateAfterBindUniformBuffersDynamic )
-      , maxDescriptorSetUpdateAfterBindStorageBuffers( rhs.maxDescriptorSetUpdateAfterBindStorageBuffers )
-      , maxDescriptorSetUpdateAfterBindStorageBuffersDynamic( rhs.maxDescriptorSetUpdateAfterBindStorageBuffersDynamic )
-      , maxDescriptorSetUpdateAfterBindSampledImages( rhs.maxDescriptorSetUpdateAfterBindSampledImages )
-      , maxDescriptorSetUpdateAfterBindStorageImages( rhs.maxDescriptorSetUpdateAfterBindStorageImages )
-      , maxDescriptorSetUpdateAfterBindInputAttachments( rhs.maxDescriptorSetUpdateAfterBindInputAttachments )
-      , supportedDepthResolveModes( rhs.supportedDepthResolveModes )
-      , supportedStencilResolveModes( rhs.supportedStencilResolveModes )
-      , independentResolveNone( rhs.independentResolveNone )
-      , independentResolve( rhs.independentResolve )
-      , filterMinmaxSingleComponentFormats( rhs.filterMinmaxSingleComponentFormats )
-      , filterMinmaxImageComponentMapping( rhs.filterMinmaxImageComponentMapping )
-      , maxTimelineSemaphoreValueDifference( rhs.maxTimelineSemaphoreValueDifference )
-      , framebufferIntegerColorSampleCounts( rhs.framebufferIntegerColorSampleCounts )
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DRIVER_NAME_SIZE>::copy( driverName, rhs.driverName );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DRIVER_INFO_SIZE>::copy( driverInfo, rhs.driverInfo );
-    }
+    {}
 
     PhysicalDeviceVulkan12Properties & operator=( PhysicalDeviceVulkan12Properties const & rhs ) VULKAN_HPP_NOEXCEPT
     {
@@ -56266,324 +55557,6 @@
       return *this;
     }
 
-    PhysicalDeviceVulkan12Properties & setPNext( void* pNext_ ) VULKAN_HPP_NOEXCEPT
-    {
-      pNext = pNext_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setDriverID( VULKAN_HPP_NAMESPACE::DriverId driverID_ ) VULKAN_HPP_NOEXCEPT
-    {
-      driverID = driverID_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setDriverName( std::array<char,VK_MAX_DRIVER_NAME_SIZE> driverName_ ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( driverName, driverName_.data(), VK_MAX_DRIVER_NAME_SIZE * sizeof( char ) );
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setDriverInfo( std::array<char,VK_MAX_DRIVER_INFO_SIZE> driverInfo_ ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( driverInfo, driverInfo_.data(), VK_MAX_DRIVER_INFO_SIZE * sizeof( char ) );
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setConformanceVersion( VULKAN_HPP_NAMESPACE::ConformanceVersion conformanceVersion_ ) VULKAN_HPP_NOEXCEPT
-    {
-      conformanceVersion = conformanceVersion_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setDenormBehaviorIndependence( VULKAN_HPP_NAMESPACE::ShaderFloatControlsIndependence denormBehaviorIndependence_ ) VULKAN_HPP_NOEXCEPT
-    {
-      denormBehaviorIndependence = denormBehaviorIndependence_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setRoundingModeIndependence( VULKAN_HPP_NAMESPACE::ShaderFloatControlsIndependence roundingModeIndependence_ ) VULKAN_HPP_NOEXCEPT
-    {
-      roundingModeIndependence = roundingModeIndependence_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setShaderSignedZeroInfNanPreserveFloat16( VULKAN_HPP_NAMESPACE::Bool32 shaderSignedZeroInfNanPreserveFloat16_ ) VULKAN_HPP_NOEXCEPT
-    {
-      shaderSignedZeroInfNanPreserveFloat16 = shaderSignedZeroInfNanPreserveFloat16_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setShaderSignedZeroInfNanPreserveFloat32( VULKAN_HPP_NAMESPACE::Bool32 shaderSignedZeroInfNanPreserveFloat32_ ) VULKAN_HPP_NOEXCEPT
-    {
-      shaderSignedZeroInfNanPreserveFloat32 = shaderSignedZeroInfNanPreserveFloat32_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setShaderSignedZeroInfNanPreserveFloat64( VULKAN_HPP_NAMESPACE::Bool32 shaderSignedZeroInfNanPreserveFloat64_ ) VULKAN_HPP_NOEXCEPT
-    {
-      shaderSignedZeroInfNanPreserveFloat64 = shaderSignedZeroInfNanPreserveFloat64_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setShaderDenormPreserveFloat16( VULKAN_HPP_NAMESPACE::Bool32 shaderDenormPreserveFloat16_ ) VULKAN_HPP_NOEXCEPT
-    {
-      shaderDenormPreserveFloat16 = shaderDenormPreserveFloat16_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setShaderDenormPreserveFloat32( VULKAN_HPP_NAMESPACE::Bool32 shaderDenormPreserveFloat32_ ) VULKAN_HPP_NOEXCEPT
-    {
-      shaderDenormPreserveFloat32 = shaderDenormPreserveFloat32_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setShaderDenormPreserveFloat64( VULKAN_HPP_NAMESPACE::Bool32 shaderDenormPreserveFloat64_ ) VULKAN_HPP_NOEXCEPT
-    {
-      shaderDenormPreserveFloat64 = shaderDenormPreserveFloat64_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setShaderDenormFlushToZeroFloat16( VULKAN_HPP_NAMESPACE::Bool32 shaderDenormFlushToZeroFloat16_ ) VULKAN_HPP_NOEXCEPT
-    {
-      shaderDenormFlushToZeroFloat16 = shaderDenormFlushToZeroFloat16_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setShaderDenormFlushToZeroFloat32( VULKAN_HPP_NAMESPACE::Bool32 shaderDenormFlushToZeroFloat32_ ) VULKAN_HPP_NOEXCEPT
-    {
-      shaderDenormFlushToZeroFloat32 = shaderDenormFlushToZeroFloat32_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setShaderDenormFlushToZeroFloat64( VULKAN_HPP_NAMESPACE::Bool32 shaderDenormFlushToZeroFloat64_ ) VULKAN_HPP_NOEXCEPT
-    {
-      shaderDenormFlushToZeroFloat64 = shaderDenormFlushToZeroFloat64_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setShaderRoundingModeRTEFloat16( VULKAN_HPP_NAMESPACE::Bool32 shaderRoundingModeRTEFloat16_ ) VULKAN_HPP_NOEXCEPT
-    {
-      shaderRoundingModeRTEFloat16 = shaderRoundingModeRTEFloat16_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setShaderRoundingModeRTEFloat32( VULKAN_HPP_NAMESPACE::Bool32 shaderRoundingModeRTEFloat32_ ) VULKAN_HPP_NOEXCEPT
-    {
-      shaderRoundingModeRTEFloat32 = shaderRoundingModeRTEFloat32_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setShaderRoundingModeRTEFloat64( VULKAN_HPP_NAMESPACE::Bool32 shaderRoundingModeRTEFloat64_ ) VULKAN_HPP_NOEXCEPT
-    {
-      shaderRoundingModeRTEFloat64 = shaderRoundingModeRTEFloat64_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setShaderRoundingModeRTZFloat16( VULKAN_HPP_NAMESPACE::Bool32 shaderRoundingModeRTZFloat16_ ) VULKAN_HPP_NOEXCEPT
-    {
-      shaderRoundingModeRTZFloat16 = shaderRoundingModeRTZFloat16_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setShaderRoundingModeRTZFloat32( VULKAN_HPP_NAMESPACE::Bool32 shaderRoundingModeRTZFloat32_ ) VULKAN_HPP_NOEXCEPT
-    {
-      shaderRoundingModeRTZFloat32 = shaderRoundingModeRTZFloat32_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setShaderRoundingModeRTZFloat64( VULKAN_HPP_NAMESPACE::Bool32 shaderRoundingModeRTZFloat64_ ) VULKAN_HPP_NOEXCEPT
-    {
-      shaderRoundingModeRTZFloat64 = shaderRoundingModeRTZFloat64_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setMaxUpdateAfterBindDescriptorsInAllPools( uint32_t maxUpdateAfterBindDescriptorsInAllPools_ ) VULKAN_HPP_NOEXCEPT
-    {
-      maxUpdateAfterBindDescriptorsInAllPools = maxUpdateAfterBindDescriptorsInAllPools_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setShaderUniformBufferArrayNonUniformIndexingNative( VULKAN_HPP_NAMESPACE::Bool32 shaderUniformBufferArrayNonUniformIndexingNative_ ) VULKAN_HPP_NOEXCEPT
-    {
-      shaderUniformBufferArrayNonUniformIndexingNative = shaderUniformBufferArrayNonUniformIndexingNative_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setShaderSampledImageArrayNonUniformIndexingNative( VULKAN_HPP_NAMESPACE::Bool32 shaderSampledImageArrayNonUniformIndexingNative_ ) VULKAN_HPP_NOEXCEPT
-    {
-      shaderSampledImageArrayNonUniformIndexingNative = shaderSampledImageArrayNonUniformIndexingNative_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setShaderStorageBufferArrayNonUniformIndexingNative( VULKAN_HPP_NAMESPACE::Bool32 shaderStorageBufferArrayNonUniformIndexingNative_ ) VULKAN_HPP_NOEXCEPT
-    {
-      shaderStorageBufferArrayNonUniformIndexingNative = shaderStorageBufferArrayNonUniformIndexingNative_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setShaderStorageImageArrayNonUniformIndexingNative( VULKAN_HPP_NAMESPACE::Bool32 shaderStorageImageArrayNonUniformIndexingNative_ ) VULKAN_HPP_NOEXCEPT
-    {
-      shaderStorageImageArrayNonUniformIndexingNative = shaderStorageImageArrayNonUniformIndexingNative_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setShaderInputAttachmentArrayNonUniformIndexingNative( VULKAN_HPP_NAMESPACE::Bool32 shaderInputAttachmentArrayNonUniformIndexingNative_ ) VULKAN_HPP_NOEXCEPT
-    {
-      shaderInputAttachmentArrayNonUniformIndexingNative = shaderInputAttachmentArrayNonUniformIndexingNative_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setRobustBufferAccessUpdateAfterBind( VULKAN_HPP_NAMESPACE::Bool32 robustBufferAccessUpdateAfterBind_ ) VULKAN_HPP_NOEXCEPT
-    {
-      robustBufferAccessUpdateAfterBind = robustBufferAccessUpdateAfterBind_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setQuadDivergentImplicitLod( VULKAN_HPP_NAMESPACE::Bool32 quadDivergentImplicitLod_ ) VULKAN_HPP_NOEXCEPT
-    {
-      quadDivergentImplicitLod = quadDivergentImplicitLod_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setMaxPerStageDescriptorUpdateAfterBindSamplers( uint32_t maxPerStageDescriptorUpdateAfterBindSamplers_ ) VULKAN_HPP_NOEXCEPT
-    {
-      maxPerStageDescriptorUpdateAfterBindSamplers = maxPerStageDescriptorUpdateAfterBindSamplers_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setMaxPerStageDescriptorUpdateAfterBindUniformBuffers( uint32_t maxPerStageDescriptorUpdateAfterBindUniformBuffers_ ) VULKAN_HPP_NOEXCEPT
-    {
-      maxPerStageDescriptorUpdateAfterBindUniformBuffers = maxPerStageDescriptorUpdateAfterBindUniformBuffers_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setMaxPerStageDescriptorUpdateAfterBindStorageBuffers( uint32_t maxPerStageDescriptorUpdateAfterBindStorageBuffers_ ) VULKAN_HPP_NOEXCEPT
-    {
-      maxPerStageDescriptorUpdateAfterBindStorageBuffers = maxPerStageDescriptorUpdateAfterBindStorageBuffers_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setMaxPerStageDescriptorUpdateAfterBindSampledImages( uint32_t maxPerStageDescriptorUpdateAfterBindSampledImages_ ) VULKAN_HPP_NOEXCEPT
-    {
-      maxPerStageDescriptorUpdateAfterBindSampledImages = maxPerStageDescriptorUpdateAfterBindSampledImages_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setMaxPerStageDescriptorUpdateAfterBindStorageImages( uint32_t maxPerStageDescriptorUpdateAfterBindStorageImages_ ) VULKAN_HPP_NOEXCEPT
-    {
-      maxPerStageDescriptorUpdateAfterBindStorageImages = maxPerStageDescriptorUpdateAfterBindStorageImages_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setMaxPerStageDescriptorUpdateAfterBindInputAttachments( uint32_t maxPerStageDescriptorUpdateAfterBindInputAttachments_ ) VULKAN_HPP_NOEXCEPT
-    {
-      maxPerStageDescriptorUpdateAfterBindInputAttachments = maxPerStageDescriptorUpdateAfterBindInputAttachments_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setMaxPerStageUpdateAfterBindResources( uint32_t maxPerStageUpdateAfterBindResources_ ) VULKAN_HPP_NOEXCEPT
-    {
-      maxPerStageUpdateAfterBindResources = maxPerStageUpdateAfterBindResources_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setMaxDescriptorSetUpdateAfterBindSamplers( uint32_t maxDescriptorSetUpdateAfterBindSamplers_ ) VULKAN_HPP_NOEXCEPT
-    {
-      maxDescriptorSetUpdateAfterBindSamplers = maxDescriptorSetUpdateAfterBindSamplers_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setMaxDescriptorSetUpdateAfterBindUniformBuffers( uint32_t maxDescriptorSetUpdateAfterBindUniformBuffers_ ) VULKAN_HPP_NOEXCEPT
-    {
-      maxDescriptorSetUpdateAfterBindUniformBuffers = maxDescriptorSetUpdateAfterBindUniformBuffers_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setMaxDescriptorSetUpdateAfterBindUniformBuffersDynamic( uint32_t maxDescriptorSetUpdateAfterBindUniformBuffersDynamic_ ) VULKAN_HPP_NOEXCEPT
-    {
-      maxDescriptorSetUpdateAfterBindUniformBuffersDynamic = maxDescriptorSetUpdateAfterBindUniformBuffersDynamic_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setMaxDescriptorSetUpdateAfterBindStorageBuffers( uint32_t maxDescriptorSetUpdateAfterBindStorageBuffers_ ) VULKAN_HPP_NOEXCEPT
-    {
-      maxDescriptorSetUpdateAfterBindStorageBuffers = maxDescriptorSetUpdateAfterBindStorageBuffers_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setMaxDescriptorSetUpdateAfterBindStorageBuffersDynamic( uint32_t maxDescriptorSetUpdateAfterBindStorageBuffersDynamic_ ) VULKAN_HPP_NOEXCEPT
-    {
-      maxDescriptorSetUpdateAfterBindStorageBuffersDynamic = maxDescriptorSetUpdateAfterBindStorageBuffersDynamic_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setMaxDescriptorSetUpdateAfterBindSampledImages( uint32_t maxDescriptorSetUpdateAfterBindSampledImages_ ) VULKAN_HPP_NOEXCEPT
-    {
-      maxDescriptorSetUpdateAfterBindSampledImages = maxDescriptorSetUpdateAfterBindSampledImages_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setMaxDescriptorSetUpdateAfterBindStorageImages( uint32_t maxDescriptorSetUpdateAfterBindStorageImages_ ) VULKAN_HPP_NOEXCEPT
-    {
-      maxDescriptorSetUpdateAfterBindStorageImages = maxDescriptorSetUpdateAfterBindStorageImages_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setMaxDescriptorSetUpdateAfterBindInputAttachments( uint32_t maxDescriptorSetUpdateAfterBindInputAttachments_ ) VULKAN_HPP_NOEXCEPT
-    {
-      maxDescriptorSetUpdateAfterBindInputAttachments = maxDescriptorSetUpdateAfterBindInputAttachments_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setSupportedDepthResolveModes( VULKAN_HPP_NAMESPACE::ResolveModeFlags supportedDepthResolveModes_ ) VULKAN_HPP_NOEXCEPT
-    {
-      supportedDepthResolveModes = supportedDepthResolveModes_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setSupportedStencilResolveModes( VULKAN_HPP_NAMESPACE::ResolveModeFlags supportedStencilResolveModes_ ) VULKAN_HPP_NOEXCEPT
-    {
-      supportedStencilResolveModes = supportedStencilResolveModes_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setIndependentResolveNone( VULKAN_HPP_NAMESPACE::Bool32 independentResolveNone_ ) VULKAN_HPP_NOEXCEPT
-    {
-      independentResolveNone = independentResolveNone_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setIndependentResolve( VULKAN_HPP_NAMESPACE::Bool32 independentResolve_ ) VULKAN_HPP_NOEXCEPT
-    {
-      independentResolve = independentResolve_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setFilterMinmaxSingleComponentFormats( VULKAN_HPP_NAMESPACE::Bool32 filterMinmaxSingleComponentFormats_ ) VULKAN_HPP_NOEXCEPT
-    {
-      filterMinmaxSingleComponentFormats = filterMinmaxSingleComponentFormats_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setFilterMinmaxImageComponentMapping( VULKAN_HPP_NAMESPACE::Bool32 filterMinmaxImageComponentMapping_ ) VULKAN_HPP_NOEXCEPT
-    {
-      filterMinmaxImageComponentMapping = filterMinmaxImageComponentMapping_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setMaxTimelineSemaphoreValueDifference( uint64_t maxTimelineSemaphoreValueDifference_ ) VULKAN_HPP_NOEXCEPT
-    {
-      maxTimelineSemaphoreValueDifference = maxTimelineSemaphoreValueDifference_;
-      return *this;
-    }
-
-    PhysicalDeviceVulkan12Properties & setFramebufferIntegerColorSampleCounts( VULKAN_HPP_NAMESPACE::SampleCountFlags framebufferIntegerColorSampleCounts_ ) VULKAN_HPP_NOEXCEPT
-    {
-      framebufferIntegerColorSampleCounts = framebufferIntegerColorSampleCounts_;
-      return *this;
-    }
-
     operator VkPhysicalDeviceVulkan12Properties const&() const VULKAN_HPP_NOEXCEPT
     {
       return *reinterpret_cast<const VkPhysicalDeviceVulkan12Properties*>( this );
@@ -56602,8 +55575,8 @@
       return ( sType == rhs.sType )
           && ( pNext == rhs.pNext )
           && ( driverID == rhs.driverID )
-          && ( memcmp( driverName, rhs.driverName, VK_MAX_DRIVER_NAME_SIZE * sizeof( char ) ) == 0 )
-          && ( memcmp( driverInfo, rhs.driverInfo, VK_MAX_DRIVER_INFO_SIZE * sizeof( char ) ) == 0 )
+          && ( driverName == rhs.driverName )
+          && ( driverInfo == rhs.driverInfo )
           && ( conformanceVersion == rhs.conformanceVersion )
           && ( denormBehaviorIndependence == rhs.denormBehaviorIndependence )
           && ( roundingModeIndependence == rhs.roundingModeIndependence )
@@ -56665,8 +55638,8 @@
     const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePhysicalDeviceVulkan12Properties;
     void* pNext = {};
     VULKAN_HPP_NAMESPACE::DriverId driverID = VULKAN_HPP_NAMESPACE::DriverId::eAmdProprietary;
-    char driverName[VK_MAX_DRIVER_NAME_SIZE] = {};
-    char driverInfo[VK_MAX_DRIVER_INFO_SIZE] = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<char, VK_MAX_DRIVER_NAME_SIZE> driverName = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<char, VK_MAX_DRIVER_INFO_SIZE> driverInfo = {};
     VULKAN_HPP_NAMESPACE::ConformanceVersion conformanceVersion = {};
     VULKAN_HPP_NAMESPACE::ShaderFloatControlsIndependence denormBehaviorIndependence = VULKAN_HPP_NAMESPACE::ShaderFloatControlsIndependence::e32BitOnly;
     VULKAN_HPP_NAMESPACE::ShaderFloatControlsIndependence roundingModeIndependence = VULKAN_HPP_NAMESPACE::ShaderFloatControlsIndependence::e32BitOnly;
@@ -56730,13 +55703,6 @@
       , vulkanMemoryModelAvailabilityVisibilityChains( vulkanMemoryModelAvailabilityVisibilityChains_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceVulkanMemoryModelFeatures( PhysicalDeviceVulkanMemoryModelFeatures const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , vulkanMemoryModel( rhs.vulkanMemoryModel )
-      , vulkanMemoryModelDeviceScope( rhs.vulkanMemoryModelDeviceScope )
-      , vulkanMemoryModelAvailabilityVisibilityChains( rhs.vulkanMemoryModelAvailabilityVisibilityChains )
-    {}
-
     PhysicalDeviceVulkanMemoryModelFeatures & operator=( PhysicalDeviceVulkanMemoryModelFeatures const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceVulkanMemoryModelFeatures ) - offsetof( PhysicalDeviceVulkanMemoryModelFeatures, pNext ) );
@@ -56822,11 +55788,6 @@
       : ycbcrImageArrays( ycbcrImageArrays_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PhysicalDeviceYcbcrImageArraysFeaturesEXT( PhysicalDeviceYcbcrImageArraysFeaturesEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , ycbcrImageArrays( rhs.ycbcrImageArrays )
-    {}
-
     PhysicalDeviceYcbcrImageArraysFeaturesEXT & operator=( PhysicalDeviceYcbcrImageArraysFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PhysicalDeviceYcbcrImageArraysFeaturesEXT ) - offsetof( PhysicalDeviceYcbcrImageArraysFeaturesEXT, pNext ) );
@@ -56900,13 +55861,6 @@
       , pInitialData( pInitialData_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PipelineCacheCreateInfo( PipelineCacheCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , initialDataSize( rhs.initialDataSize )
-      , pInitialData( rhs.pInitialData )
-    {}
-
     PipelineCacheCreateInfo & operator=( PipelineCacheCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PipelineCacheCreateInfo ) - offsetof( PipelineCacheCreateInfo, pNext ) );
@@ -56996,13 +55950,6 @@
       , blendOverlap( blendOverlap_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PipelineColorBlendAdvancedStateCreateInfoEXT( PipelineColorBlendAdvancedStateCreateInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , srcPremultiplied( rhs.srcPremultiplied )
-      , dstPremultiplied( rhs.dstPremultiplied )
-      , blendOverlap( rhs.blendOverlap )
-    {}
-
     PipelineColorBlendAdvancedStateCreateInfoEXT & operator=( PipelineColorBlendAdvancedStateCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PipelineColorBlendAdvancedStateCreateInfoEXT ) - offsetof( PipelineColorBlendAdvancedStateCreateInfoEXT, pNext ) );
@@ -57088,11 +56035,6 @@
       : compilerControlFlags( compilerControlFlags_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PipelineCompilerControlCreateInfoAMD( PipelineCompilerControlCreateInfoAMD const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , compilerControlFlags( rhs.compilerControlFlags )
-    {}
-
     PipelineCompilerControlCreateInfoAMD & operator=( PipelineCompilerControlCreateInfoAMD const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PipelineCompilerControlCreateInfoAMD ) - offsetof( PipelineCompilerControlCreateInfoAMD, pNext ) );
@@ -57170,15 +56112,6 @@
       , pCoverageModulationTable( pCoverageModulationTable_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PipelineCoverageModulationStateCreateInfoNV( PipelineCoverageModulationStateCreateInfoNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , coverageModulationMode( rhs.coverageModulationMode )
-      , coverageModulationTableEnable( rhs.coverageModulationTableEnable )
-      , coverageModulationTableCount( rhs.coverageModulationTableCount )
-      , pCoverageModulationTable( rhs.pCoverageModulationTable )
-    {}
-
     PipelineCoverageModulationStateCreateInfoNV & operator=( PipelineCoverageModulationStateCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PipelineCoverageModulationStateCreateInfoNV ) - offsetof( PipelineCoverageModulationStateCreateInfoNV, pNext ) );
@@ -57282,12 +56215,6 @@
       , coverageReductionMode( coverageReductionMode_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PipelineCoverageReductionStateCreateInfoNV( PipelineCoverageReductionStateCreateInfoNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , coverageReductionMode( rhs.coverageReductionMode )
-    {}
-
     PipelineCoverageReductionStateCreateInfoNV & operator=( PipelineCoverageReductionStateCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PipelineCoverageReductionStateCreateInfoNV ) - offsetof( PipelineCoverageReductionStateCreateInfoNV, pNext ) );
@@ -57369,13 +56296,6 @@
       , coverageToColorLocation( coverageToColorLocation_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PipelineCoverageToColorStateCreateInfoNV( PipelineCoverageToColorStateCreateInfoNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , coverageToColorEnable( rhs.coverageToColorEnable )
-      , coverageToColorLocation( rhs.coverageToColorLocation )
-    {}
-
     PipelineCoverageToColorStateCreateInfoNV & operator=( PipelineCoverageToColorStateCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PipelineCoverageToColorStateCreateInfoNV ) - offsetof( PipelineCoverageToColorStateCreateInfoNV, pNext ) );
@@ -57463,17 +56383,6 @@
       , duration( duration_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PipelineCreationFeedbackEXT( PipelineCreationFeedbackEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : flags( rhs.flags )
-      , duration( rhs.duration )
-    {}
-
-    PipelineCreationFeedbackEXT & operator=( PipelineCreationFeedbackEXT const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( PipelineCreationFeedbackEXT ) );
-      return *this;
-    }
-
     PipelineCreationFeedbackEXT( VkPipelineCreationFeedbackEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -57527,13 +56436,6 @@
       , pPipelineStageCreationFeedbacks( pPipelineStageCreationFeedbacks_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PipelineCreationFeedbackCreateInfoEXT( PipelineCreationFeedbackCreateInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , pPipelineCreationFeedback( rhs.pPipelineCreationFeedback )
-      , pipelineStageCreationFeedbackCount( rhs.pipelineStageCreationFeedbackCount )
-      , pPipelineStageCreationFeedbacks( rhs.pPipelineStageCreationFeedbacks )
-    {}
-
     PipelineCreationFeedbackCreateInfoEXT & operator=( PipelineCreationFeedbackCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PipelineCreationFeedbackCreateInfoEXT ) - offsetof( PipelineCreationFeedbackCreateInfoEXT, pNext ) );
@@ -57625,14 +56527,6 @@
       , pDiscardRectangles( pDiscardRectangles_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PipelineDiscardRectangleStateCreateInfoEXT( PipelineDiscardRectangleStateCreateInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , discardRectangleMode( rhs.discardRectangleMode )
-      , discardRectangleCount( rhs.discardRectangleCount )
-      , pDiscardRectangles( rhs.pDiscardRectangles )
-    {}
-
     PipelineDiscardRectangleStateCreateInfoEXT & operator=( PipelineDiscardRectangleStateCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PipelineDiscardRectangleStateCreateInfoEXT ) - offsetof( PipelineDiscardRectangleStateCreateInfoEXT, pNext ) );
@@ -57728,12 +56622,6 @@
       , executableIndex( executableIndex_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PipelineExecutableInfoKHR( PipelineExecutableInfoKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , pipeline( rhs.pipeline )
-      , executableIndex( rhs.executableIndex )
-    {}
-
     PipelineExecutableInfoKHR & operator=( PipelineExecutableInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PipelineExecutableInfoKHR ) - offsetof( PipelineExecutableInfoKHR, pNext ) );
@@ -57812,27 +56700,12 @@
                                                                          VULKAN_HPP_NAMESPACE::Bool32 isText_ = {},
                                                                          size_t dataSize_ = {},
                                                                          void* pData_ = {} ) VULKAN_HPP_NOEXCEPT
-      : name{}
-      , description{}
+      : name( name_ )
+      , description( description_ )
       , isText( isText_ )
       , dataSize( dataSize_ )
       , pData( pData_ )
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DESCRIPTION_SIZE>::copy( name, name_ );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DESCRIPTION_SIZE>::copy( description, description_ );
-    }
-
-    VULKAN_HPP_CONSTEXPR_14 PipelineExecutableInternalRepresentationKHR( PipelineExecutableInternalRepresentationKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , name{}
-      , description{}
-      , isText( rhs.isText )
-      , dataSize( rhs.dataSize )
-      , pData( rhs.pData )
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DESCRIPTION_SIZE>::copy( name, rhs.name );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DESCRIPTION_SIZE>::copy( description, rhs.description );
-    }
+    {}
 
     PipelineExecutableInternalRepresentationKHR & operator=( PipelineExecutableInternalRepresentationKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
@@ -57868,8 +56741,8 @@
     {
       return ( sType == rhs.sType )
           && ( pNext == rhs.pNext )
-          && ( memcmp( name, rhs.name, VK_MAX_DESCRIPTION_SIZE * sizeof( char ) ) == 0 )
-          && ( memcmp( description, rhs.description, VK_MAX_DESCRIPTION_SIZE * sizeof( char ) ) == 0 )
+          && ( name == rhs.name )
+          && ( description == rhs.description )
           && ( isText == rhs.isText )
           && ( dataSize == rhs.dataSize )
           && ( pData == rhs.pData );
@@ -57884,8 +56757,8 @@
   public:
     const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineExecutableInternalRepresentationKHR;
     void* pNext = {};
-    char name[VK_MAX_DESCRIPTION_SIZE] = {};
-    char description[VK_MAX_DESCRIPTION_SIZE] = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<char, VK_MAX_DESCRIPTION_SIZE> name = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<char, VK_MAX_DESCRIPTION_SIZE> description = {};
     VULKAN_HPP_NAMESPACE::Bool32 isText = {};
     size_t dataSize = {};
     void* pData = {};
@@ -57900,24 +56773,10 @@
                                                              std::array<char,VK_MAX_DESCRIPTION_SIZE> const& description_ = {},
                                                              uint32_t subgroupSize_ = {} ) VULKAN_HPP_NOEXCEPT
       : stages( stages_ )
-      , name{}
-      , description{}
+      , name( name_ )
+      , description( description_ )
       , subgroupSize( subgroupSize_ )
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DESCRIPTION_SIZE>::copy( name, name_ );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DESCRIPTION_SIZE>::copy( description, description_ );
-    }
-
-    VULKAN_HPP_CONSTEXPR_14 PipelineExecutablePropertiesKHR( PipelineExecutablePropertiesKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , stages( rhs.stages )
-      , name{}
-      , description{}
-      , subgroupSize( rhs.subgroupSize )
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DESCRIPTION_SIZE>::copy( name, rhs.name );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DESCRIPTION_SIZE>::copy( description, rhs.description );
-    }
+    {}
 
     PipelineExecutablePropertiesKHR & operator=( PipelineExecutablePropertiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
@@ -57954,8 +56813,8 @@
       return ( sType == rhs.sType )
           && ( pNext == rhs.pNext )
           && ( stages == rhs.stages )
-          && ( memcmp( name, rhs.name, VK_MAX_DESCRIPTION_SIZE * sizeof( char ) ) == 0 )
-          && ( memcmp( description, rhs.description, VK_MAX_DESCRIPTION_SIZE * sizeof( char ) ) == 0 )
+          && ( name == rhs.name )
+          && ( description == rhs.description )
           && ( subgroupSize == rhs.subgroupSize );
     }
 
@@ -57969,8 +56828,8 @@
     const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineExecutablePropertiesKHR;
     void* pNext = {};
     VULKAN_HPP_NAMESPACE::ShaderStageFlags stages = {};
-    char name[VK_MAX_DESCRIPTION_SIZE] = {};
-    char description[VK_MAX_DESCRIPTION_SIZE] = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<char, VK_MAX_DESCRIPTION_SIZE> name = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<char, VK_MAX_DESCRIPTION_SIZE> description = {};
     uint32_t subgroupSize = {};
   };
   static_assert( sizeof( PipelineExecutablePropertiesKHR ) == sizeof( VkPipelineExecutablePropertiesKHR ), "struct and wrapper have different size!" );
@@ -58062,25 +56921,11 @@
                                     std::array<char,VK_MAX_DESCRIPTION_SIZE> const& description_ = {},
                                     VULKAN_HPP_NAMESPACE::PipelineExecutableStatisticFormatKHR format_ = VULKAN_HPP_NAMESPACE::PipelineExecutableStatisticFormatKHR::eBool32,
                                     VULKAN_HPP_NAMESPACE::PipelineExecutableStatisticValueKHR value_ = {} ) VULKAN_HPP_NOEXCEPT
-      : name{}
-      , description{}
+      : name( name_ )
+      , description( description_ )
       , format( format_ )
       , value( value_ )
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DESCRIPTION_SIZE>::copy( name, name_ );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DESCRIPTION_SIZE>::copy( description, description_ );
-    }
-
-    PipelineExecutableStatisticKHR( PipelineExecutableStatisticKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , name{}
-      , description{}
-      , format( rhs.format )
-      , value( rhs.value )
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DESCRIPTION_SIZE>::copy( name, rhs.name );
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<char,VK_MAX_DESCRIPTION_SIZE>::copy( description, rhs.description );
-    }
+    {}
 
     PipelineExecutableStatisticKHR & operator=( PipelineExecutableStatisticKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
@@ -58112,8 +56957,8 @@
   public:
     const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineExecutableStatisticKHR;
     void* pNext = {};
-    char name[VK_MAX_DESCRIPTION_SIZE] = {};
-    char description[VK_MAX_DESCRIPTION_SIZE] = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<char, VK_MAX_DESCRIPTION_SIZE> name = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<char, VK_MAX_DESCRIPTION_SIZE> description = {};
     VULKAN_HPP_NAMESPACE::PipelineExecutableStatisticFormatKHR format = VULKAN_HPP_NAMESPACE::PipelineExecutableStatisticFormatKHR::eBool32;
     VULKAN_HPP_NAMESPACE::PipelineExecutableStatisticValueKHR value = {};
   };
@@ -58126,11 +56971,6 @@
       : pipeline( pipeline_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PipelineInfoKHR( PipelineInfoKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , pipeline( rhs.pipeline )
-    {}
-
     PipelineInfoKHR & operator=( PipelineInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PipelineInfoKHR ) - offsetof( PipelineInfoKHR, pNext ) );
@@ -58204,18 +57044,6 @@
       , size( size_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PushConstantRange( PushConstantRange const& rhs ) VULKAN_HPP_NOEXCEPT
-      : stageFlags( rhs.stageFlags )
-      , offset( rhs.offset )
-      , size( rhs.size )
-    {}
-
-    PushConstantRange & operator=( PushConstantRange const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( PushConstantRange ) );
-      return *this;
-    }
-
     PushConstantRange( VkPushConstantRange const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -58293,15 +57121,6 @@
       , pPushConstantRanges( pPushConstantRanges_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PipelineLayoutCreateInfo( PipelineLayoutCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , setLayoutCount( rhs.setLayoutCount )
-      , pSetLayouts( rhs.pSetLayouts )
-      , pushConstantRangeCount( rhs.pushConstantRangeCount )
-      , pPushConstantRanges( rhs.pPushConstantRanges )
-    {}
-
     PipelineLayoutCreateInfo & operator=( PipelineLayoutCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PipelineLayoutCreateInfo ) - offsetof( PipelineLayoutCreateInfo, pNext ) );
@@ -58397,6 +57216,87 @@
   static_assert( sizeof( PipelineLayoutCreateInfo ) == sizeof( VkPipelineLayoutCreateInfo ), "struct and wrapper have different size!" );
   static_assert( std::is_standard_layout<PipelineLayoutCreateInfo>::value, "struct wrapper is not a standard layout!" );
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct PipelineLibraryCreateInfoKHR
+  {
+    VULKAN_HPP_CONSTEXPR PipelineLibraryCreateInfoKHR( uint32_t libraryCount_ = {},
+                                                       const VULKAN_HPP_NAMESPACE::Pipeline* pLibraries_ = {} ) VULKAN_HPP_NOEXCEPT
+      : libraryCount( libraryCount_ )
+      , pLibraries( pLibraries_ )
+    {}
+
+    PipelineLibraryCreateInfoKHR & operator=( PipelineLibraryCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      memcpy( &pNext, &rhs.pNext, sizeof( PipelineLibraryCreateInfoKHR ) - offsetof( PipelineLibraryCreateInfoKHR, pNext ) );
+      return *this;
+    }
+
+    PipelineLibraryCreateInfoKHR( VkPipelineLibraryCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    PipelineLibraryCreateInfoKHR& operator=( VkPipelineLibraryCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::PipelineLibraryCreateInfoKHR const *>(&rhs);
+      return *this;
+    }
+
+    PipelineLibraryCreateInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pNext = pNext_;
+      return *this;
+    }
+
+    PipelineLibraryCreateInfoKHR & setLibraryCount( uint32_t libraryCount_ ) VULKAN_HPP_NOEXCEPT
+    {
+      libraryCount = libraryCount_;
+      return *this;
+    }
+
+    PipelineLibraryCreateInfoKHR & setPLibraries( const VULKAN_HPP_NAMESPACE::Pipeline* pLibraries_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pLibraries = pLibraries_;
+      return *this;
+    }
+
+    operator VkPipelineLibraryCreateInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkPipelineLibraryCreateInfoKHR*>( this );
+    }
+
+    operator VkPipelineLibraryCreateInfoKHR &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkPipelineLibraryCreateInfoKHR*>( this );
+    }
+
+#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
+    auto operator<=>( PipelineLibraryCreateInfoKHR const& ) const = default;
+#else
+    bool operator==( PipelineLibraryCreateInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ( sType == rhs.sType )
+          && ( pNext == rhs.pNext )
+          && ( libraryCount == rhs.libraryCount )
+          && ( pLibraries == rhs.pLibraries );
+    }
+
+    bool operator!=( PipelineLibraryCreateInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return !operator==( rhs );
+    }
+#endif
+
+  public:
+    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::ePipelineLibraryCreateInfoKHR;
+    const void* pNext = {};
+    uint32_t libraryCount = {};
+    const VULKAN_HPP_NAMESPACE::Pipeline* pLibraries = {};
+  };
+  static_assert( sizeof( PipelineLibraryCreateInfoKHR ) == sizeof( VkPipelineLibraryCreateInfoKHR ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<PipelineLibraryCreateInfoKHR>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
   struct PipelineRasterizationConservativeStateCreateInfoEXT
   {
     VULKAN_HPP_CONSTEXPR PipelineRasterizationConservativeStateCreateInfoEXT( VULKAN_HPP_NAMESPACE::PipelineRasterizationConservativeStateCreateFlagsEXT flags_ = {},
@@ -58407,13 +57307,6 @@
       , extraPrimitiveOverestimationSize( extraPrimitiveOverestimationSize_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PipelineRasterizationConservativeStateCreateInfoEXT( PipelineRasterizationConservativeStateCreateInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , conservativeRasterizationMode( rhs.conservativeRasterizationMode )
-      , extraPrimitiveOverestimationSize( rhs.extraPrimitiveOverestimationSize )
-    {}
-
     PipelineRasterizationConservativeStateCreateInfoEXT & operator=( PipelineRasterizationConservativeStateCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PipelineRasterizationConservativeStateCreateInfoEXT ) - offsetof( PipelineRasterizationConservativeStateCreateInfoEXT, pNext ) );
@@ -58501,12 +57394,6 @@
       , depthClipEnable( depthClipEnable_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PipelineRasterizationDepthClipStateCreateInfoEXT( PipelineRasterizationDepthClipStateCreateInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , depthClipEnable( rhs.depthClipEnable )
-    {}
-
     PipelineRasterizationDepthClipStateCreateInfoEXT & operator=( PipelineRasterizationDepthClipStateCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PipelineRasterizationDepthClipStateCreateInfoEXT ) - offsetof( PipelineRasterizationDepthClipStateCreateInfoEXT, pNext ) );
@@ -58590,14 +57477,6 @@
       , lineStipplePattern( lineStipplePattern_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PipelineRasterizationLineStateCreateInfoEXT( PipelineRasterizationLineStateCreateInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , lineRasterizationMode( rhs.lineRasterizationMode )
-      , stippledLineEnable( rhs.stippledLineEnable )
-      , lineStippleFactor( rhs.lineStippleFactor )
-      , lineStipplePattern( rhs.lineStipplePattern )
-    {}
-
     PipelineRasterizationLineStateCreateInfoEXT & operator=( PipelineRasterizationLineStateCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PipelineRasterizationLineStateCreateInfoEXT ) - offsetof( PipelineRasterizationLineStateCreateInfoEXT, pNext ) );
@@ -58691,11 +57570,6 @@
       : rasterizationOrder( rasterizationOrder_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PipelineRasterizationStateRasterizationOrderAMD( PipelineRasterizationStateRasterizationOrderAMD const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , rasterizationOrder( rhs.rasterizationOrder )
-    {}
-
     PipelineRasterizationStateRasterizationOrderAMD & operator=( PipelineRasterizationStateRasterizationOrderAMD const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PipelineRasterizationStateRasterizationOrderAMD ) - offsetof( PipelineRasterizationStateRasterizationOrderAMD, pNext ) );
@@ -58767,12 +57641,6 @@
       , rasterizationStream( rasterizationStream_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PipelineRasterizationStateStreamCreateInfoEXT( PipelineRasterizationStateStreamCreateInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , rasterizationStream( rhs.rasterizationStream )
-    {}
-
     PipelineRasterizationStateStreamCreateInfoEXT & operator=( PipelineRasterizationStateStreamCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PipelineRasterizationStateStreamCreateInfoEXT ) - offsetof( PipelineRasterizationStateStreamCreateInfoEXT, pNext ) );
@@ -58850,11 +57718,6 @@
       : representativeFragmentTestEnable( representativeFragmentTestEnable_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PipelineRepresentativeFragmentTestStateCreateInfoNV( PipelineRepresentativeFragmentTestStateCreateInfoNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , representativeFragmentTestEnable( rhs.representativeFragmentTestEnable )
-    {}
-
     PipelineRepresentativeFragmentTestStateCreateInfoNV & operator=( PipelineRepresentativeFragmentTestStateCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PipelineRepresentativeFragmentTestStateCreateInfoNV ) - offsetof( PipelineRepresentativeFragmentTestStateCreateInfoNV, pNext ) );
@@ -58926,12 +57789,6 @@
       , sampleLocationsInfo( sampleLocationsInfo_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PipelineSampleLocationsStateCreateInfoEXT( PipelineSampleLocationsStateCreateInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , sampleLocationsEnable( rhs.sampleLocationsEnable )
-      , sampleLocationsInfo( rhs.sampleLocationsInfo )
-    {}
-
     PipelineSampleLocationsStateCreateInfoEXT & operator=( PipelineSampleLocationsStateCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PipelineSampleLocationsStateCreateInfoEXT ) - offsetof( PipelineSampleLocationsStateCreateInfoEXT, pNext ) );
@@ -59009,11 +57866,6 @@
       : requiredSubgroupSize( requiredSubgroupSize_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PipelineShaderStageRequiredSubgroupSizeCreateInfoEXT( PipelineShaderStageRequiredSubgroupSizeCreateInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , requiredSubgroupSize( rhs.requiredSubgroupSize )
-    {}
-
     PipelineShaderStageRequiredSubgroupSizeCreateInfoEXT & operator=( PipelineShaderStageRequiredSubgroupSizeCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PipelineShaderStageRequiredSubgroupSizeCreateInfoEXT ) - offsetof( PipelineShaderStageRequiredSubgroupSizeCreateInfoEXT, pNext ) );
@@ -59071,11 +57923,6 @@
       : domainOrigin( domainOrigin_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PipelineTessellationDomainOriginStateCreateInfo( PipelineTessellationDomainOriginStateCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , domainOrigin( rhs.domainOrigin )
-    {}
-
     PipelineTessellationDomainOriginStateCreateInfo & operator=( PipelineTessellationDomainOriginStateCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PipelineTessellationDomainOriginStateCreateInfo ) - offsetof( PipelineTessellationDomainOriginStateCreateInfo, pNext ) );
@@ -59147,17 +57994,6 @@
       , divisor( divisor_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR VertexInputBindingDivisorDescriptionEXT( VertexInputBindingDivisorDescriptionEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : binding( rhs.binding )
-      , divisor( rhs.divisor )
-    {}
-
-    VertexInputBindingDivisorDescriptionEXT & operator=( VertexInputBindingDivisorDescriptionEXT const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( VertexInputBindingDivisorDescriptionEXT ) );
-      return *this;
-    }
-
     VertexInputBindingDivisorDescriptionEXT( VkVertexInputBindingDivisorDescriptionEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -59221,12 +58057,6 @@
       , pVertexBindingDivisors( pVertexBindingDivisors_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PipelineVertexInputDivisorStateCreateInfoEXT( PipelineVertexInputDivisorStateCreateInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , vertexBindingDivisorCount( rhs.vertexBindingDivisorCount )
-      , pVertexBindingDivisors( rhs.pVertexBindingDivisors )
-    {}
-
     PipelineVertexInputDivisorStateCreateInfoEXT & operator=( PipelineVertexInputDivisorStateCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PipelineVertexInputDivisorStateCreateInfoEXT ) - offsetof( PipelineVertexInputDivisorStateCreateInfoEXT, pNext ) );
@@ -59308,13 +58138,6 @@
       , pCustomSampleOrders( pCustomSampleOrders_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PipelineViewportCoarseSampleOrderStateCreateInfoNV( PipelineViewportCoarseSampleOrderStateCreateInfoNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , sampleOrderType( rhs.sampleOrderType )
-      , customSampleOrderCount( rhs.customSampleOrderCount )
-      , pCustomSampleOrders( rhs.pCustomSampleOrders )
-    {}
-
     PipelineViewportCoarseSampleOrderStateCreateInfoNV & operator=( PipelineViewportCoarseSampleOrderStateCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PipelineViewportCoarseSampleOrderStateCreateInfoNV ) - offsetof( PipelineViewportCoarseSampleOrderStateCreateInfoNV, pNext ) );
@@ -59402,12 +58225,6 @@
       , pExclusiveScissors( pExclusiveScissors_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PipelineViewportExclusiveScissorStateCreateInfoNV( PipelineViewportExclusiveScissorStateCreateInfoNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , exclusiveScissorCount( rhs.exclusiveScissorCount )
-      , pExclusiveScissors( rhs.pExclusiveScissors )
-    {}
-
     PipelineViewportExclusiveScissorStateCreateInfoNV & operator=( PipelineViewportExclusiveScissorStateCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PipelineViewportExclusiveScissorStateCreateInfoNV ) - offsetof( PipelineViewportExclusiveScissorStateCreateInfoNV, pNext ) );
@@ -59487,17 +58304,6 @@
       , pShadingRatePaletteEntries( pShadingRatePaletteEntries_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ShadingRatePaletteNV( ShadingRatePaletteNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : shadingRatePaletteEntryCount( rhs.shadingRatePaletteEntryCount )
-      , pShadingRatePaletteEntries( rhs.pShadingRatePaletteEntries )
-    {}
-
-    ShadingRatePaletteNV & operator=( ShadingRatePaletteNV const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( ShadingRatePaletteNV ) );
-      return *this;
-    }
-
     ShadingRatePaletteNV( VkShadingRatePaletteNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -59563,13 +58369,6 @@
       , pShadingRatePalettes( pShadingRatePalettes_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PipelineViewportShadingRateImageStateCreateInfoNV( PipelineViewportShadingRateImageStateCreateInfoNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , shadingRateImageEnable( rhs.shadingRateImageEnable )
-      , viewportCount( rhs.viewportCount )
-      , pShadingRatePalettes( rhs.pShadingRatePalettes )
-    {}
-
     PipelineViewportShadingRateImageStateCreateInfoNV & operator=( PipelineViewportShadingRateImageStateCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PipelineViewportShadingRateImageStateCreateInfoNV ) - offsetof( PipelineViewportShadingRateImageStateCreateInfoNV, pNext ) );
@@ -59661,19 +58460,6 @@
       , w( w_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ViewportSwizzleNV( ViewportSwizzleNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : x( rhs.x )
-      , y( rhs.y )
-      , z( rhs.z )
-      , w( rhs.w )
-    {}
-
-    ViewportSwizzleNV & operator=( ViewportSwizzleNV const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( ViewportSwizzleNV ) );
-      return *this;
-    }
-
     ViewportSwizzleNV( VkViewportSwizzleNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -59755,13 +58541,6 @@
       , pViewportSwizzles( pViewportSwizzles_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PipelineViewportSwizzleStateCreateInfoNV( PipelineViewportSwizzleStateCreateInfoNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , viewportCount( rhs.viewportCount )
-      , pViewportSwizzles( rhs.pViewportSwizzles )
-    {}
-
     PipelineViewportSwizzleStateCreateInfoNV & operator=( PipelineViewportSwizzleStateCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PipelineViewportSwizzleStateCreateInfoNV ) - offsetof( PipelineViewportSwizzleStateCreateInfoNV, pNext ) );
@@ -59849,17 +58628,6 @@
       , ycoeff( ycoeff_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ViewportWScalingNV( ViewportWScalingNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : xcoeff( rhs.xcoeff )
-      , ycoeff( rhs.ycoeff )
-    {}
-
-    ViewportWScalingNV & operator=( ViewportWScalingNV const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( ViewportWScalingNV ) );
-      return *this;
-    }
-
     ViewportWScalingNV( VkViewportWScalingNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -59925,13 +58693,6 @@
       , pViewportWScalings( pViewportWScalings_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PipelineViewportWScalingStateCreateInfoNV( PipelineViewportWScalingStateCreateInfoNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , viewportWScalingEnable( rhs.viewportWScalingEnable )
-      , viewportCount( rhs.viewportCount )
-      , pViewportWScalings( rhs.pViewportWScalings )
-    {}
-
     PipelineViewportWScalingStateCreateInfoNV & operator=( PipelineViewportWScalingStateCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PipelineViewportWScalingStateCreateInfoNV ) - offsetof( PipelineViewportWScalingStateCreateInfoNV, pNext ) );
@@ -60018,11 +58779,6 @@
       : frameToken( frameToken_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PresentFrameTokenGGP( PresentFrameTokenGGP const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , frameToken( rhs.frameToken )
-    {}
-
     PresentFrameTokenGGP & operator=( PresentFrameTokenGGP const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PresentFrameTokenGGP ) - offsetof( PresentFrameTokenGGP, pNext ) );
@@ -60103,16 +58859,6 @@
       , pResults( pResults_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PresentInfoKHR( PresentInfoKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , waitSemaphoreCount( rhs.waitSemaphoreCount )
-      , pWaitSemaphores( rhs.pWaitSemaphores )
-      , swapchainCount( rhs.swapchainCount )
-      , pSwapchains( rhs.pSwapchains )
-      , pImageIndices( rhs.pImageIndices )
-      , pResults( rhs.pResults )
-    {}
-
     PresentInfoKHR & operator=( PresentInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PresentInfoKHR ) - offsetof( PresentInfoKHR, pNext ) );
@@ -60226,12 +58972,6 @@
       , layer( layer_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR RectLayerKHR( RectLayerKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : offset( rhs.offset )
-      , extent( rhs.extent )
-      , layer( rhs.layer )
-    {}
-
     explicit RectLayerKHR( Rect2D const& rect2D,
                            uint32_t layer_ = {} )
       : offset( rect2D.offset )
@@ -60239,12 +58979,6 @@
       , layer( layer_ )
     {}
 
-    RectLayerKHR & operator=( RectLayerKHR const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( RectLayerKHR ) );
-      return *this;
-    }
-
     RectLayerKHR( VkRectLayerKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -60316,17 +59050,6 @@
       , pRectangles( pRectangles_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PresentRegionKHR( PresentRegionKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : rectangleCount( rhs.rectangleCount )
-      , pRectangles( rhs.pRectangles )
-    {}
-
-    PresentRegionKHR & operator=( PresentRegionKHR const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( PresentRegionKHR ) );
-      return *this;
-    }
-
     PresentRegionKHR( VkPresentRegionKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -60390,12 +59113,6 @@
       , pRegions( pRegions_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PresentRegionsKHR( PresentRegionsKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , swapchainCount( rhs.swapchainCount )
-      , pRegions( rhs.pRegions )
-    {}
-
     PresentRegionsKHR & operator=( PresentRegionsKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PresentRegionsKHR ) - offsetof( PresentRegionsKHR, pNext ) );
@@ -60475,17 +59192,6 @@
       , desiredPresentTime( desiredPresentTime_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PresentTimeGOOGLE( PresentTimeGOOGLE const& rhs ) VULKAN_HPP_NOEXCEPT
-      : presentID( rhs.presentID )
-      , desiredPresentTime( rhs.desiredPresentTime )
-    {}
-
-    PresentTimeGOOGLE & operator=( PresentTimeGOOGLE const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( PresentTimeGOOGLE ) );
-      return *this;
-    }
-
     PresentTimeGOOGLE( VkPresentTimeGOOGLE const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -60549,12 +59255,6 @@
       , pTimes( pTimes_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR PresentTimesInfoGOOGLE( PresentTimesInfoGOOGLE const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , swapchainCount( rhs.swapchainCount )
-      , pTimes( rhs.pTimes )
-    {}
-
     PresentTimesInfoGOOGLE & operator=( PresentTimesInfoGOOGLE const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( PresentTimesInfoGOOGLE ) - offsetof( PresentTimesInfoGOOGLE, pNext ) );
@@ -60632,11 +59332,6 @@
       : protectedSubmit( protectedSubmit_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ProtectedSubmitInfo( ProtectedSubmitInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , protectedSubmit( rhs.protectedSubmit )
-    {}
-
     ProtectedSubmitInfo & operator=( ProtectedSubmitInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ProtectedSubmitInfo ) - offsetof( ProtectedSubmitInfo, pNext ) );
@@ -60712,14 +59407,6 @@
       , pipelineStatistics( pipelineStatistics_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR QueryPoolCreateInfo( QueryPoolCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , queryType( rhs.queryType )
-      , queryCount( rhs.queryCount )
-      , pipelineStatistics( rhs.pipelineStatistics )
-    {}
-
     QueryPoolCreateInfo & operator=( QueryPoolCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( QueryPoolCreateInfo ) - offsetof( QueryPoolCreateInfo, pNext ) );
@@ -60807,80 +59494,6 @@
   static_assert( sizeof( QueryPoolCreateInfo ) == sizeof( VkQueryPoolCreateInfo ), "struct and wrapper have different size!" );
   static_assert( std::is_standard_layout<QueryPoolCreateInfo>::value, "struct wrapper is not a standard layout!" );
 
-  struct QueryPoolCreateInfoINTEL
-  {
-    VULKAN_HPP_CONSTEXPR QueryPoolCreateInfoINTEL( VULKAN_HPP_NAMESPACE::QueryPoolSamplingModeINTEL performanceCountersSampling_ = VULKAN_HPP_NAMESPACE::QueryPoolSamplingModeINTEL::eManual ) VULKAN_HPP_NOEXCEPT
-      : performanceCountersSampling( performanceCountersSampling_ )
-    {}
-
-    VULKAN_HPP_CONSTEXPR QueryPoolCreateInfoINTEL( QueryPoolCreateInfoINTEL const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , performanceCountersSampling( rhs.performanceCountersSampling )
-    {}
-
-    QueryPoolCreateInfoINTEL & operator=( QueryPoolCreateInfoINTEL const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( &pNext, &rhs.pNext, sizeof( QueryPoolCreateInfoINTEL ) - offsetof( QueryPoolCreateInfoINTEL, pNext ) );
-      return *this;
-    }
-
-    QueryPoolCreateInfoINTEL( VkQueryPoolCreateInfoINTEL const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      *this = rhs;
-    }
-
-    QueryPoolCreateInfoINTEL& operator=( VkQueryPoolCreateInfoINTEL const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::QueryPoolCreateInfoINTEL const *>(&rhs);
-      return *this;
-    }
-
-    QueryPoolCreateInfoINTEL & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
-    {
-      pNext = pNext_;
-      return *this;
-    }
-
-    QueryPoolCreateInfoINTEL & setPerformanceCountersSampling( VULKAN_HPP_NAMESPACE::QueryPoolSamplingModeINTEL performanceCountersSampling_ ) VULKAN_HPP_NOEXCEPT
-    {
-      performanceCountersSampling = performanceCountersSampling_;
-      return *this;
-    }
-
-    operator VkQueryPoolCreateInfoINTEL const&() const VULKAN_HPP_NOEXCEPT
-    {
-      return *reinterpret_cast<const VkQueryPoolCreateInfoINTEL*>( this );
-    }
-
-    operator VkQueryPoolCreateInfoINTEL &() VULKAN_HPP_NOEXCEPT
-    {
-      return *reinterpret_cast<VkQueryPoolCreateInfoINTEL*>( this );
-    }
-
-#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
-    auto operator<=>( QueryPoolCreateInfoINTEL const& ) const = default;
-#else
-    bool operator==( QueryPoolCreateInfoINTEL const& rhs ) const VULKAN_HPP_NOEXCEPT
-    {
-      return ( sType == rhs.sType )
-          && ( pNext == rhs.pNext )
-          && ( performanceCountersSampling == rhs.performanceCountersSampling );
-    }
-
-    bool operator!=( QueryPoolCreateInfoINTEL const& rhs ) const VULKAN_HPP_NOEXCEPT
-    {
-      return !operator==( rhs );
-    }
-#endif
-
-  public:
-    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eQueryPoolCreateInfoINTEL;
-    const void* pNext = {};
-    VULKAN_HPP_NAMESPACE::QueryPoolSamplingModeINTEL performanceCountersSampling = VULKAN_HPP_NAMESPACE::QueryPoolSamplingModeINTEL::eManual;
-  };
-  static_assert( sizeof( QueryPoolCreateInfoINTEL ) == sizeof( VkQueryPoolCreateInfoINTEL ), "struct and wrapper have different size!" );
-  static_assert( std::is_standard_layout<QueryPoolCreateInfoINTEL>::value, "struct wrapper is not a standard layout!" );
-
   struct QueryPoolPerformanceCreateInfoKHR
   {
     VULKAN_HPP_CONSTEXPR QueryPoolPerformanceCreateInfoKHR( uint32_t queueFamilyIndex_ = {},
@@ -60891,13 +59504,6 @@
       , pCounterIndices( pCounterIndices_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR QueryPoolPerformanceCreateInfoKHR( QueryPoolPerformanceCreateInfoKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , queueFamilyIndex( rhs.queueFamilyIndex )
-      , counterIndexCount( rhs.counterIndexCount )
-      , pCounterIndices( rhs.pCounterIndices )
-    {}
-
     QueryPoolPerformanceCreateInfoKHR & operator=( QueryPoolPerformanceCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( QueryPoolPerformanceCreateInfoKHR ) - offsetof( QueryPoolPerformanceCreateInfoKHR, pNext ) );
@@ -60977,17 +59583,81 @@
   static_assert( sizeof( QueryPoolPerformanceCreateInfoKHR ) == sizeof( VkQueryPoolPerformanceCreateInfoKHR ), "struct and wrapper have different size!" );
   static_assert( std::is_standard_layout<QueryPoolPerformanceCreateInfoKHR>::value, "struct wrapper is not a standard layout!" );
 
+  struct QueryPoolPerformanceQueryCreateInfoINTEL
+  {
+    VULKAN_HPP_CONSTEXPR QueryPoolPerformanceQueryCreateInfoINTEL( VULKAN_HPP_NAMESPACE::QueryPoolSamplingModeINTEL performanceCountersSampling_ = VULKAN_HPP_NAMESPACE::QueryPoolSamplingModeINTEL::eManual ) VULKAN_HPP_NOEXCEPT
+      : performanceCountersSampling( performanceCountersSampling_ )
+    {}
+
+    QueryPoolPerformanceQueryCreateInfoINTEL & operator=( QueryPoolPerformanceQueryCreateInfoINTEL const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      memcpy( &pNext, &rhs.pNext, sizeof( QueryPoolPerformanceQueryCreateInfoINTEL ) - offsetof( QueryPoolPerformanceQueryCreateInfoINTEL, pNext ) );
+      return *this;
+    }
+
+    QueryPoolPerformanceQueryCreateInfoINTEL( VkQueryPoolPerformanceQueryCreateInfoINTEL const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    QueryPoolPerformanceQueryCreateInfoINTEL& operator=( VkQueryPoolPerformanceQueryCreateInfoINTEL const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::QueryPoolPerformanceQueryCreateInfoINTEL const *>(&rhs);
+      return *this;
+    }
+
+    QueryPoolPerformanceQueryCreateInfoINTEL & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pNext = pNext_;
+      return *this;
+    }
+
+    QueryPoolPerformanceQueryCreateInfoINTEL & setPerformanceCountersSampling( VULKAN_HPP_NAMESPACE::QueryPoolSamplingModeINTEL performanceCountersSampling_ ) VULKAN_HPP_NOEXCEPT
+    {
+      performanceCountersSampling = performanceCountersSampling_;
+      return *this;
+    }
+
+    operator VkQueryPoolPerformanceQueryCreateInfoINTEL const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkQueryPoolPerformanceQueryCreateInfoINTEL*>( this );
+    }
+
+    operator VkQueryPoolPerformanceQueryCreateInfoINTEL &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkQueryPoolPerformanceQueryCreateInfoINTEL*>( this );
+    }
+
+#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
+    auto operator<=>( QueryPoolPerformanceQueryCreateInfoINTEL const& ) const = default;
+#else
+    bool operator==( QueryPoolPerformanceQueryCreateInfoINTEL const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ( sType == rhs.sType )
+          && ( pNext == rhs.pNext )
+          && ( performanceCountersSampling == rhs.performanceCountersSampling );
+    }
+
+    bool operator!=( QueryPoolPerformanceQueryCreateInfoINTEL const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return !operator==( rhs );
+    }
+#endif
+
+  public:
+    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eQueryPoolPerformanceQueryCreateInfoINTEL;
+    const void* pNext = {};
+    VULKAN_HPP_NAMESPACE::QueryPoolSamplingModeINTEL performanceCountersSampling = VULKAN_HPP_NAMESPACE::QueryPoolSamplingModeINTEL::eManual;
+  };
+  static_assert( sizeof( QueryPoolPerformanceQueryCreateInfoINTEL ) == sizeof( VkQueryPoolPerformanceQueryCreateInfoINTEL ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<QueryPoolPerformanceQueryCreateInfoINTEL>::value, "struct wrapper is not a standard layout!" );
+
   struct QueueFamilyCheckpointPropertiesNV
   {
     VULKAN_HPP_CONSTEXPR QueueFamilyCheckpointPropertiesNV( VULKAN_HPP_NAMESPACE::PipelineStageFlags checkpointExecutionStageMask_ = {} ) VULKAN_HPP_NOEXCEPT
       : checkpointExecutionStageMask( checkpointExecutionStageMask_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR QueueFamilyCheckpointPropertiesNV( QueueFamilyCheckpointPropertiesNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , checkpointExecutionStageMask( rhs.checkpointExecutionStageMask )
-    {}
-
     QueueFamilyCheckpointPropertiesNV & operator=( QueueFamilyCheckpointPropertiesNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( QueueFamilyCheckpointPropertiesNV ) - offsetof( QueueFamilyCheckpointPropertiesNV, pNext ) );
@@ -61051,19 +59721,6 @@
       , minImageTransferGranularity( minImageTransferGranularity_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR QueueFamilyProperties( QueueFamilyProperties const& rhs ) VULKAN_HPP_NOEXCEPT
-      : queueFlags( rhs.queueFlags )
-      , queueCount( rhs.queueCount )
-      , timestampValidBits( rhs.timestampValidBits )
-      , minImageTransferGranularity( rhs.minImageTransferGranularity )
-    {}
-
-    QueueFamilyProperties & operator=( QueueFamilyProperties const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( QueueFamilyProperties ) );
-      return *this;
-    }
-
     QueueFamilyProperties( VkQueueFamilyProperties const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -61117,11 +59774,6 @@
       : queueFamilyProperties( queueFamilyProperties_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR QueueFamilyProperties2( QueueFamilyProperties2 const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , queueFamilyProperties( rhs.queueFamilyProperties )
-    {}
-
     QueueFamilyProperties2 & operator=( QueueFamilyProperties2 const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( QueueFamilyProperties2 ) - offsetof( QueueFamilyProperties2, pNext ) );
@@ -61173,9 +59825,392 @@
   static_assert( sizeof( QueueFamilyProperties2 ) == sizeof( VkQueueFamilyProperties2 ), "struct and wrapper have different size!" );
   static_assert( std::is_standard_layout<QueueFamilyProperties2>::value, "struct wrapper is not a standard layout!" );
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct RayTracingShaderGroupCreateInfoKHR
+  {
+    VULKAN_HPP_CONSTEXPR RayTracingShaderGroupCreateInfoKHR( VULKAN_HPP_NAMESPACE::RayTracingShaderGroupTypeKHR type_ = VULKAN_HPP_NAMESPACE::RayTracingShaderGroupTypeKHR::eGeneral,
+                                                             uint32_t generalShader_ = {},
+                                                             uint32_t closestHitShader_ = {},
+                                                             uint32_t anyHitShader_ = {},
+                                                             uint32_t intersectionShader_ = {},
+                                                             const void* pShaderGroupCaptureReplayHandle_ = {} ) VULKAN_HPP_NOEXCEPT
+      : type( type_ )
+      , generalShader( generalShader_ )
+      , closestHitShader( closestHitShader_ )
+      , anyHitShader( anyHitShader_ )
+      , intersectionShader( intersectionShader_ )
+      , pShaderGroupCaptureReplayHandle( pShaderGroupCaptureReplayHandle_ )
+    {}
+
+    RayTracingShaderGroupCreateInfoKHR & operator=( RayTracingShaderGroupCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      memcpy( &pNext, &rhs.pNext, sizeof( RayTracingShaderGroupCreateInfoKHR ) - offsetof( RayTracingShaderGroupCreateInfoKHR, pNext ) );
+      return *this;
+    }
+
+    RayTracingShaderGroupCreateInfoKHR( VkRayTracingShaderGroupCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    RayTracingShaderGroupCreateInfoKHR& operator=( VkRayTracingShaderGroupCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::RayTracingShaderGroupCreateInfoKHR const *>(&rhs);
+      return *this;
+    }
+
+    RayTracingShaderGroupCreateInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pNext = pNext_;
+      return *this;
+    }
+
+    RayTracingShaderGroupCreateInfoKHR & setType( VULKAN_HPP_NAMESPACE::RayTracingShaderGroupTypeKHR type_ ) VULKAN_HPP_NOEXCEPT
+    {
+      type = type_;
+      return *this;
+    }
+
+    RayTracingShaderGroupCreateInfoKHR & setGeneralShader( uint32_t generalShader_ ) VULKAN_HPP_NOEXCEPT
+    {
+      generalShader = generalShader_;
+      return *this;
+    }
+
+    RayTracingShaderGroupCreateInfoKHR & setClosestHitShader( uint32_t closestHitShader_ ) VULKAN_HPP_NOEXCEPT
+    {
+      closestHitShader = closestHitShader_;
+      return *this;
+    }
+
+    RayTracingShaderGroupCreateInfoKHR & setAnyHitShader( uint32_t anyHitShader_ ) VULKAN_HPP_NOEXCEPT
+    {
+      anyHitShader = anyHitShader_;
+      return *this;
+    }
+
+    RayTracingShaderGroupCreateInfoKHR & setIntersectionShader( uint32_t intersectionShader_ ) VULKAN_HPP_NOEXCEPT
+    {
+      intersectionShader = intersectionShader_;
+      return *this;
+    }
+
+    RayTracingShaderGroupCreateInfoKHR & setPShaderGroupCaptureReplayHandle( const void* pShaderGroupCaptureReplayHandle_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pShaderGroupCaptureReplayHandle = pShaderGroupCaptureReplayHandle_;
+      return *this;
+    }
+
+    operator VkRayTracingShaderGroupCreateInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkRayTracingShaderGroupCreateInfoKHR*>( this );
+    }
+
+    operator VkRayTracingShaderGroupCreateInfoKHR &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkRayTracingShaderGroupCreateInfoKHR*>( this );
+    }
+
+#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
+    auto operator<=>( RayTracingShaderGroupCreateInfoKHR const& ) const = default;
+#else
+    bool operator==( RayTracingShaderGroupCreateInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ( sType == rhs.sType )
+          && ( pNext == rhs.pNext )
+          && ( type == rhs.type )
+          && ( generalShader == rhs.generalShader )
+          && ( closestHitShader == rhs.closestHitShader )
+          && ( anyHitShader == rhs.anyHitShader )
+          && ( intersectionShader == rhs.intersectionShader )
+          && ( pShaderGroupCaptureReplayHandle == rhs.pShaderGroupCaptureReplayHandle );
+    }
+
+    bool operator!=( RayTracingShaderGroupCreateInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return !operator==( rhs );
+    }
+#endif
+
+  public:
+    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eRayTracingShaderGroupCreateInfoKHR;
+    const void* pNext = {};
+    VULKAN_HPP_NAMESPACE::RayTracingShaderGroupTypeKHR type = VULKAN_HPP_NAMESPACE::RayTracingShaderGroupTypeKHR::eGeneral;
+    uint32_t generalShader = {};
+    uint32_t closestHitShader = {};
+    uint32_t anyHitShader = {};
+    uint32_t intersectionShader = {};
+    const void* pShaderGroupCaptureReplayHandle = {};
+  };
+  static_assert( sizeof( RayTracingShaderGroupCreateInfoKHR ) == sizeof( VkRayTracingShaderGroupCreateInfoKHR ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<RayTracingShaderGroupCreateInfoKHR>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct RayTracingPipelineInterfaceCreateInfoKHR
+  {
+    VULKAN_HPP_CONSTEXPR RayTracingPipelineInterfaceCreateInfoKHR( uint32_t maxPayloadSize_ = {},
+                                                                   uint32_t maxAttributeSize_ = {},
+                                                                   uint32_t maxCallableSize_ = {} ) VULKAN_HPP_NOEXCEPT
+      : maxPayloadSize( maxPayloadSize_ )
+      , maxAttributeSize( maxAttributeSize_ )
+      , maxCallableSize( maxCallableSize_ )
+    {}
+
+    RayTracingPipelineInterfaceCreateInfoKHR & operator=( RayTracingPipelineInterfaceCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      memcpy( &pNext, &rhs.pNext, sizeof( RayTracingPipelineInterfaceCreateInfoKHR ) - offsetof( RayTracingPipelineInterfaceCreateInfoKHR, pNext ) );
+      return *this;
+    }
+
+    RayTracingPipelineInterfaceCreateInfoKHR( VkRayTracingPipelineInterfaceCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    RayTracingPipelineInterfaceCreateInfoKHR& operator=( VkRayTracingPipelineInterfaceCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::RayTracingPipelineInterfaceCreateInfoKHR const *>(&rhs);
+      return *this;
+    }
+
+    RayTracingPipelineInterfaceCreateInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pNext = pNext_;
+      return *this;
+    }
+
+    RayTracingPipelineInterfaceCreateInfoKHR & setMaxPayloadSize( uint32_t maxPayloadSize_ ) VULKAN_HPP_NOEXCEPT
+    {
+      maxPayloadSize = maxPayloadSize_;
+      return *this;
+    }
+
+    RayTracingPipelineInterfaceCreateInfoKHR & setMaxAttributeSize( uint32_t maxAttributeSize_ ) VULKAN_HPP_NOEXCEPT
+    {
+      maxAttributeSize = maxAttributeSize_;
+      return *this;
+    }
+
+    RayTracingPipelineInterfaceCreateInfoKHR & setMaxCallableSize( uint32_t maxCallableSize_ ) VULKAN_HPP_NOEXCEPT
+    {
+      maxCallableSize = maxCallableSize_;
+      return *this;
+    }
+
+    operator VkRayTracingPipelineInterfaceCreateInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkRayTracingPipelineInterfaceCreateInfoKHR*>( this );
+    }
+
+    operator VkRayTracingPipelineInterfaceCreateInfoKHR &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkRayTracingPipelineInterfaceCreateInfoKHR*>( this );
+    }
+
+#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
+    auto operator<=>( RayTracingPipelineInterfaceCreateInfoKHR const& ) const = default;
+#else
+    bool operator==( RayTracingPipelineInterfaceCreateInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ( sType == rhs.sType )
+          && ( pNext == rhs.pNext )
+          && ( maxPayloadSize == rhs.maxPayloadSize )
+          && ( maxAttributeSize == rhs.maxAttributeSize )
+          && ( maxCallableSize == rhs.maxCallableSize );
+    }
+
+    bool operator!=( RayTracingPipelineInterfaceCreateInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return !operator==( rhs );
+    }
+#endif
+
+  public:
+    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eRayTracingPipelineInterfaceCreateInfoKHR;
+    const void* pNext = {};
+    uint32_t maxPayloadSize = {};
+    uint32_t maxAttributeSize = {};
+    uint32_t maxCallableSize = {};
+  };
+  static_assert( sizeof( RayTracingPipelineInterfaceCreateInfoKHR ) == sizeof( VkRayTracingPipelineInterfaceCreateInfoKHR ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<RayTracingPipelineInterfaceCreateInfoKHR>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct RayTracingPipelineCreateInfoKHR
+  {
+    VULKAN_HPP_CONSTEXPR RayTracingPipelineCreateInfoKHR( VULKAN_HPP_NAMESPACE::PipelineCreateFlags flags_ = {},
+                                                          uint32_t stageCount_ = {},
+                                                          const VULKAN_HPP_NAMESPACE::PipelineShaderStageCreateInfo* pStages_ = {},
+                                                          uint32_t groupCount_ = {},
+                                                          const VULKAN_HPP_NAMESPACE::RayTracingShaderGroupCreateInfoKHR* pGroups_ = {},
+                                                          uint32_t maxRecursionDepth_ = {},
+                                                          VULKAN_HPP_NAMESPACE::PipelineLibraryCreateInfoKHR libraries_ = {},
+                                                          const VULKAN_HPP_NAMESPACE::RayTracingPipelineInterfaceCreateInfoKHR* pLibraryInterface_ = {},
+                                                          VULKAN_HPP_NAMESPACE::PipelineLayout layout_ = {},
+                                                          VULKAN_HPP_NAMESPACE::Pipeline basePipelineHandle_ = {},
+                                                          int32_t basePipelineIndex_ = {} ) VULKAN_HPP_NOEXCEPT
+      : flags( flags_ )
+      , stageCount( stageCount_ )
+      , pStages( pStages_ )
+      , groupCount( groupCount_ )
+      , pGroups( pGroups_ )
+      , maxRecursionDepth( maxRecursionDepth_ )
+      , libraries( libraries_ )
+      , pLibraryInterface( pLibraryInterface_ )
+      , layout( layout_ )
+      , basePipelineHandle( basePipelineHandle_ )
+      , basePipelineIndex( basePipelineIndex_ )
+    {}
+
+    RayTracingPipelineCreateInfoKHR & operator=( RayTracingPipelineCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      memcpy( &pNext, &rhs.pNext, sizeof( RayTracingPipelineCreateInfoKHR ) - offsetof( RayTracingPipelineCreateInfoKHR, pNext ) );
+      return *this;
+    }
+
+    RayTracingPipelineCreateInfoKHR( VkRayTracingPipelineCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    RayTracingPipelineCreateInfoKHR& operator=( VkRayTracingPipelineCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoKHR const *>(&rhs);
+      return *this;
+    }
+
+    RayTracingPipelineCreateInfoKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pNext = pNext_;
+      return *this;
+    }
+
+    RayTracingPipelineCreateInfoKHR & setFlags( VULKAN_HPP_NAMESPACE::PipelineCreateFlags flags_ ) VULKAN_HPP_NOEXCEPT
+    {
+      flags = flags_;
+      return *this;
+    }
+
+    RayTracingPipelineCreateInfoKHR & setStageCount( uint32_t stageCount_ ) VULKAN_HPP_NOEXCEPT
+    {
+      stageCount = stageCount_;
+      return *this;
+    }
+
+    RayTracingPipelineCreateInfoKHR & setPStages( const VULKAN_HPP_NAMESPACE::PipelineShaderStageCreateInfo* pStages_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pStages = pStages_;
+      return *this;
+    }
+
+    RayTracingPipelineCreateInfoKHR & setGroupCount( uint32_t groupCount_ ) VULKAN_HPP_NOEXCEPT
+    {
+      groupCount = groupCount_;
+      return *this;
+    }
+
+    RayTracingPipelineCreateInfoKHR & setPGroups( const VULKAN_HPP_NAMESPACE::RayTracingShaderGroupCreateInfoKHR* pGroups_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pGroups = pGroups_;
+      return *this;
+    }
+
+    RayTracingPipelineCreateInfoKHR & setMaxRecursionDepth( uint32_t maxRecursionDepth_ ) VULKAN_HPP_NOEXCEPT
+    {
+      maxRecursionDepth = maxRecursionDepth_;
+      return *this;
+    }
+
+    RayTracingPipelineCreateInfoKHR & setLibraries( VULKAN_HPP_NAMESPACE::PipelineLibraryCreateInfoKHR libraries_ ) VULKAN_HPP_NOEXCEPT
+    {
+      libraries = libraries_;
+      return *this;
+    }
+
+    RayTracingPipelineCreateInfoKHR & setPLibraryInterface( const VULKAN_HPP_NAMESPACE::RayTracingPipelineInterfaceCreateInfoKHR* pLibraryInterface_ ) VULKAN_HPP_NOEXCEPT
+    {
+      pLibraryInterface = pLibraryInterface_;
+      return *this;
+    }
+
+    RayTracingPipelineCreateInfoKHR & setLayout( VULKAN_HPP_NAMESPACE::PipelineLayout layout_ ) VULKAN_HPP_NOEXCEPT
+    {
+      layout = layout_;
+      return *this;
+    }
+
+    RayTracingPipelineCreateInfoKHR & setBasePipelineHandle( VULKAN_HPP_NAMESPACE::Pipeline basePipelineHandle_ ) VULKAN_HPP_NOEXCEPT
+    {
+      basePipelineHandle = basePipelineHandle_;
+      return *this;
+    }
+
+    RayTracingPipelineCreateInfoKHR & setBasePipelineIndex( int32_t basePipelineIndex_ ) VULKAN_HPP_NOEXCEPT
+    {
+      basePipelineIndex = basePipelineIndex_;
+      return *this;
+    }
+
+    operator VkRayTracingPipelineCreateInfoKHR const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkRayTracingPipelineCreateInfoKHR*>( this );
+    }
+
+    operator VkRayTracingPipelineCreateInfoKHR &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkRayTracingPipelineCreateInfoKHR*>( this );
+    }
+
+#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
+    auto operator<=>( RayTracingPipelineCreateInfoKHR const& ) const = default;
+#else
+    bool operator==( RayTracingPipelineCreateInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ( sType == rhs.sType )
+          && ( pNext == rhs.pNext )
+          && ( flags == rhs.flags )
+          && ( stageCount == rhs.stageCount )
+          && ( pStages == rhs.pStages )
+          && ( groupCount == rhs.groupCount )
+          && ( pGroups == rhs.pGroups )
+          && ( maxRecursionDepth == rhs.maxRecursionDepth )
+          && ( libraries == rhs.libraries )
+          && ( pLibraryInterface == rhs.pLibraryInterface )
+          && ( layout == rhs.layout )
+          && ( basePipelineHandle == rhs.basePipelineHandle )
+          && ( basePipelineIndex == rhs.basePipelineIndex );
+    }
+
+    bool operator!=( RayTracingPipelineCreateInfoKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return !operator==( rhs );
+    }
+#endif
+
+  public:
+    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eRayTracingPipelineCreateInfoKHR;
+    const void* pNext = {};
+    VULKAN_HPP_NAMESPACE::PipelineCreateFlags flags = {};
+    uint32_t stageCount = {};
+    const VULKAN_HPP_NAMESPACE::PipelineShaderStageCreateInfo* pStages = {};
+    uint32_t groupCount = {};
+    const VULKAN_HPP_NAMESPACE::RayTracingShaderGroupCreateInfoKHR* pGroups = {};
+    uint32_t maxRecursionDepth = {};
+    VULKAN_HPP_NAMESPACE::PipelineLibraryCreateInfoKHR libraries = {};
+    const VULKAN_HPP_NAMESPACE::RayTracingPipelineInterfaceCreateInfoKHR* pLibraryInterface = {};
+    VULKAN_HPP_NAMESPACE::PipelineLayout layout = {};
+    VULKAN_HPP_NAMESPACE::Pipeline basePipelineHandle = {};
+    int32_t basePipelineIndex = {};
+  };
+  static_assert( sizeof( RayTracingPipelineCreateInfoKHR ) == sizeof( VkRayTracingPipelineCreateInfoKHR ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<RayTracingPipelineCreateInfoKHR>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
   struct RayTracingShaderGroupCreateInfoNV
   {
-    VULKAN_HPP_CONSTEXPR RayTracingShaderGroupCreateInfoNV( VULKAN_HPP_NAMESPACE::RayTracingShaderGroupTypeNV type_ = VULKAN_HPP_NAMESPACE::RayTracingShaderGroupTypeNV::eGeneral,
+    VULKAN_HPP_CONSTEXPR RayTracingShaderGroupCreateInfoNV( VULKAN_HPP_NAMESPACE::RayTracingShaderGroupTypeKHR type_ = VULKAN_HPP_NAMESPACE::RayTracingShaderGroupTypeKHR::eGeneral,
                                                             uint32_t generalShader_ = {},
                                                             uint32_t closestHitShader_ = {},
                                                             uint32_t anyHitShader_ = {},
@@ -61187,15 +60222,6 @@
       , intersectionShader( intersectionShader_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR RayTracingShaderGroupCreateInfoNV( RayTracingShaderGroupCreateInfoNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , type( rhs.type )
-      , generalShader( rhs.generalShader )
-      , closestHitShader( rhs.closestHitShader )
-      , anyHitShader( rhs.anyHitShader )
-      , intersectionShader( rhs.intersectionShader )
-    {}
-
     RayTracingShaderGroupCreateInfoNV & operator=( RayTracingShaderGroupCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( RayTracingShaderGroupCreateInfoNV ) - offsetof( RayTracingShaderGroupCreateInfoNV, pNext ) );
@@ -61219,7 +60245,7 @@
       return *this;
     }
 
-    RayTracingShaderGroupCreateInfoNV & setType( VULKAN_HPP_NAMESPACE::RayTracingShaderGroupTypeNV type_ ) VULKAN_HPP_NOEXCEPT
+    RayTracingShaderGroupCreateInfoNV & setType( VULKAN_HPP_NAMESPACE::RayTracingShaderGroupTypeKHR type_ ) VULKAN_HPP_NOEXCEPT
     {
       type = type_;
       return *this;
@@ -61282,7 +60308,7 @@
   public:
     const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eRayTracingShaderGroupCreateInfoNV;
     const void* pNext = {};
-    VULKAN_HPP_NAMESPACE::RayTracingShaderGroupTypeNV type = VULKAN_HPP_NAMESPACE::RayTracingShaderGroupTypeNV::eGeneral;
+    VULKAN_HPP_NAMESPACE::RayTracingShaderGroupTypeKHR type = VULKAN_HPP_NAMESPACE::RayTracingShaderGroupTypeKHR::eGeneral;
     uint32_t generalShader = {};
     uint32_t closestHitShader = {};
     uint32_t anyHitShader = {};
@@ -61313,19 +60339,6 @@
       , basePipelineIndex( basePipelineIndex_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR RayTracingPipelineCreateInfoNV( RayTracingPipelineCreateInfoNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , stageCount( rhs.stageCount )
-      , pStages( rhs.pStages )
-      , groupCount( rhs.groupCount )
-      , pGroups( rhs.pGroups )
-      , maxRecursionDepth( rhs.maxRecursionDepth )
-      , layout( rhs.layout )
-      , basePipelineHandle( rhs.basePipelineHandle )
-      , basePipelineIndex( rhs.basePipelineIndex )
-    {}
-
     RayTracingPipelineCreateInfoNV & operator=( RayTracingPipelineCreateInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( RayTracingPipelineCreateInfoNV ) - offsetof( RayTracingPipelineCreateInfoNV, pNext ) );
@@ -61459,16 +60472,6 @@
       : refreshDuration( refreshDuration_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR RefreshCycleDurationGOOGLE( RefreshCycleDurationGOOGLE const& rhs ) VULKAN_HPP_NOEXCEPT
-      : refreshDuration( rhs.refreshDuration )
-    {}
-
-    RefreshCycleDurationGOOGLE & operator=( RefreshCycleDurationGOOGLE const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( RefreshCycleDurationGOOGLE ) );
-      return *this;
-    }
-
     RefreshCycleDurationGOOGLE( VkRefreshCycleDurationGOOGLE const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -61518,12 +60521,6 @@
       , pAttachments( pAttachments_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR RenderPassAttachmentBeginInfo( RenderPassAttachmentBeginInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , attachmentCount( rhs.attachmentCount )
-      , pAttachments( rhs.pAttachments )
-    {}
-
     RenderPassAttachmentBeginInfo & operator=( RenderPassAttachmentBeginInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( RenderPassAttachmentBeginInfo ) - offsetof( RenderPassAttachmentBeginInfo, pNext ) );
@@ -61609,15 +60606,6 @@
       , pClearValues( pClearValues_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR_14 RenderPassBeginInfo( RenderPassBeginInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , renderPass( rhs.renderPass )
-      , framebuffer( rhs.framebuffer )
-      , renderArea( rhs.renderArea )
-      , clearValueCount( rhs.clearValueCount )
-      , pClearValues( rhs.pClearValues )
-    {}
-
     RenderPassBeginInfo & operator=( RenderPassBeginInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( RenderPassBeginInfo ) - offsetof( RenderPassBeginInfo, pNext ) );
@@ -61737,25 +60725,6 @@
       , pPreserveAttachments( pPreserveAttachments_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SubpassDescription( SubpassDescription const& rhs ) VULKAN_HPP_NOEXCEPT
-      : flags( rhs.flags )
-      , pipelineBindPoint( rhs.pipelineBindPoint )
-      , inputAttachmentCount( rhs.inputAttachmentCount )
-      , pInputAttachments( rhs.pInputAttachments )
-      , colorAttachmentCount( rhs.colorAttachmentCount )
-      , pColorAttachments( rhs.pColorAttachments )
-      , pResolveAttachments( rhs.pResolveAttachments )
-      , pDepthStencilAttachment( rhs.pDepthStencilAttachment )
-      , preserveAttachmentCount( rhs.preserveAttachmentCount )
-      , pPreserveAttachments( rhs.pPreserveAttachments )
-    {}
-
-    SubpassDescription & operator=( SubpassDescription const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( SubpassDescription ) );
-      return *this;
-    }
-
     SubpassDescription( VkSubpassDescription const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -61893,22 +60862,6 @@
       , dependencyFlags( dependencyFlags_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SubpassDependency( SubpassDependency const& rhs ) VULKAN_HPP_NOEXCEPT
-      : srcSubpass( rhs.srcSubpass )
-      , dstSubpass( rhs.dstSubpass )
-      , srcStageMask( rhs.srcStageMask )
-      , dstStageMask( rhs.dstStageMask )
-      , srcAccessMask( rhs.srcAccessMask )
-      , dstAccessMask( rhs.dstAccessMask )
-      , dependencyFlags( rhs.dependencyFlags )
-    {}
-
-    SubpassDependency & operator=( SubpassDependency const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( SubpassDependency ) );
-      return *this;
-    }
-
     SubpassDependency( VkSubpassDependency const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -62022,17 +60975,6 @@
       , pDependencies( pDependencies_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR RenderPassCreateInfo( RenderPassCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , attachmentCount( rhs.attachmentCount )
-      , pAttachments( rhs.pAttachments )
-      , subpassCount( rhs.subpassCount )
-      , pSubpasses( rhs.pSubpasses )
-      , dependencyCount( rhs.dependencyCount )
-      , pDependencies( rhs.pDependencies )
-    {}
-
     RenderPassCreateInfo & operator=( RenderPassCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( RenderPassCreateInfo ) - offsetof( RenderPassCreateInfo, pNext ) );
@@ -62170,21 +61112,6 @@
       , pPreserveAttachments( pPreserveAttachments_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SubpassDescription2( SubpassDescription2 const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , pipelineBindPoint( rhs.pipelineBindPoint )
-      , viewMask( rhs.viewMask )
-      , inputAttachmentCount( rhs.inputAttachmentCount )
-      , pInputAttachments( rhs.pInputAttachments )
-      , colorAttachmentCount( rhs.colorAttachmentCount )
-      , pColorAttachments( rhs.pColorAttachments )
-      , pResolveAttachments( rhs.pResolveAttachments )
-      , pDepthStencilAttachment( rhs.pDepthStencilAttachment )
-      , preserveAttachmentCount( rhs.preserveAttachmentCount )
-      , pPreserveAttachments( rhs.pPreserveAttachments )
-    {}
-
     SubpassDescription2 & operator=( SubpassDescription2 const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( SubpassDescription2 ) - offsetof( SubpassDescription2, pNext ) );
@@ -62348,18 +61275,6 @@
       , viewOffset( viewOffset_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SubpassDependency2( SubpassDependency2 const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , srcSubpass( rhs.srcSubpass )
-      , dstSubpass( rhs.dstSubpass )
-      , srcStageMask( rhs.srcStageMask )
-      , dstStageMask( rhs.dstStageMask )
-      , srcAccessMask( rhs.srcAccessMask )
-      , dstAccessMask( rhs.dstAccessMask )
-      , dependencyFlags( rhs.dependencyFlags )
-      , viewOffset( rhs.viewOffset )
-    {}
-
     SubpassDependency2 & operator=( SubpassDependency2 const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( SubpassDependency2 ) - offsetof( SubpassDependency2, pNext ) );
@@ -62501,19 +61416,6 @@
       , pCorrelatedViewMasks( pCorrelatedViewMasks_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR RenderPassCreateInfo2( RenderPassCreateInfo2 const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , attachmentCount( rhs.attachmentCount )
-      , pAttachments( rhs.pAttachments )
-      , subpassCount( rhs.subpassCount )
-      , pSubpasses( rhs.pSubpasses )
-      , dependencyCount( rhs.dependencyCount )
-      , pDependencies( rhs.pDependencies )
-      , correlatedViewMaskCount( rhs.correlatedViewMaskCount )
-      , pCorrelatedViewMasks( rhs.pCorrelatedViewMasks )
-    {}
-
     RenderPassCreateInfo2 & operator=( RenderPassCreateInfo2 const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( RenderPassCreateInfo2 ) - offsetof( RenderPassCreateInfo2, pNext ) );
@@ -62647,11 +61549,6 @@
       : fragmentDensityMapAttachment( fragmentDensityMapAttachment_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR RenderPassFragmentDensityMapCreateInfoEXT( RenderPassFragmentDensityMapCreateInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , fragmentDensityMapAttachment( rhs.fragmentDensityMapAttachment )
-    {}
-
     RenderPassFragmentDensityMapCreateInfoEXT & operator=( RenderPassFragmentDensityMapCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( RenderPassFragmentDensityMapCreateInfoEXT ) - offsetof( RenderPassFragmentDensityMapCreateInfoEXT, pNext ) );
@@ -62723,12 +61620,6 @@
       , pAspectReferences( pAspectReferences_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR RenderPassInputAttachmentAspectCreateInfo( RenderPassInputAttachmentAspectCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , aspectReferenceCount( rhs.aspectReferenceCount )
-      , pAspectReferences( rhs.pAspectReferences )
-    {}
-
     RenderPassInputAttachmentAspectCreateInfo & operator=( RenderPassInputAttachmentAspectCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( RenderPassInputAttachmentAspectCreateInfo ) - offsetof( RenderPassInputAttachmentAspectCreateInfo, pNext ) );
@@ -62816,16 +61707,6 @@
       , pCorrelationMasks( pCorrelationMasks_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR RenderPassMultiviewCreateInfo( RenderPassMultiviewCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , subpassCount( rhs.subpassCount )
-      , pViewMasks( rhs.pViewMasks )
-      , dependencyCount( rhs.dependencyCount )
-      , pViewOffsets( rhs.pViewOffsets )
-      , correlationMaskCount( rhs.correlationMaskCount )
-      , pCorrelationMasks( rhs.pCorrelationMasks )
-    {}
-
     RenderPassMultiviewCreateInfo & operator=( RenderPassMultiviewCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( RenderPassMultiviewCreateInfo ) - offsetof( RenderPassMultiviewCreateInfo, pNext ) );
@@ -62937,17 +61818,6 @@
       , sampleLocationsInfo( sampleLocationsInfo_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SubpassSampleLocationsEXT( SubpassSampleLocationsEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : subpassIndex( rhs.subpassIndex )
-      , sampleLocationsInfo( rhs.sampleLocationsInfo )
-    {}
-
-    SubpassSampleLocationsEXT & operator=( SubpassSampleLocationsEXT const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( SubpassSampleLocationsEXT ) );
-      return *this;
-    }
-
     SubpassSampleLocationsEXT( VkSubpassSampleLocationsEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -63015,14 +61885,6 @@
       , pPostSubpassSampleLocations( pPostSubpassSampleLocations_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR RenderPassSampleLocationsBeginInfoEXT( RenderPassSampleLocationsBeginInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , attachmentInitialSampleLocationsCount( rhs.attachmentInitialSampleLocationsCount )
-      , pAttachmentInitialSampleLocations( rhs.pAttachmentInitialSampleLocations )
-      , postSubpassSampleLocationsCount( rhs.postSubpassSampleLocationsCount )
-      , pPostSubpassSampleLocations( rhs.pPostSubpassSampleLocations )
-    {}
-
     RenderPassSampleLocationsBeginInfoEXT & operator=( RenderPassSampleLocationsBeginInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( RenderPassSampleLocationsBeginInfoEXT ) - offsetof( RenderPassSampleLocationsBeginInfoEXT, pNext ) );
@@ -63116,11 +61978,6 @@
       : transform( transform_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR RenderPassTransformBeginInfoQCOM( RenderPassTransformBeginInfoQCOM const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , transform( rhs.transform )
-    {}
-
     RenderPassTransformBeginInfoQCOM & operator=( RenderPassTransformBeginInfoQCOM const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( RenderPassTransformBeginInfoQCOM ) - offsetof( RenderPassTransformBeginInfoQCOM, pNext ) );
@@ -63220,26 +62077,6 @@
       , unnormalizedCoordinates( unnormalizedCoordinates_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SamplerCreateInfo( SamplerCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , magFilter( rhs.magFilter )
-      , minFilter( rhs.minFilter )
-      , mipmapMode( rhs.mipmapMode )
-      , addressModeU( rhs.addressModeU )
-      , addressModeV( rhs.addressModeV )
-      , addressModeW( rhs.addressModeW )
-      , mipLodBias( rhs.mipLodBias )
-      , anisotropyEnable( rhs.anisotropyEnable )
-      , maxAnisotropy( rhs.maxAnisotropy )
-      , compareEnable( rhs.compareEnable )
-      , compareOp( rhs.compareOp )
-      , minLod( rhs.minLod )
-      , maxLod( rhs.maxLod )
-      , borderColor( rhs.borderColor )
-      , unnormalizedCoordinates( rhs.unnormalizedCoordinates )
-    {}
-
     SamplerCreateInfo & operator=( SamplerCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( SamplerCreateInfo ) - offsetof( SamplerCreateInfo, pNext ) );
@@ -63429,11 +62266,6 @@
       : reductionMode( reductionMode_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SamplerReductionModeCreateInfo( SamplerReductionModeCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , reductionMode( rhs.reductionMode )
-    {}
-
     SamplerReductionModeCreateInfo & operator=( SamplerReductionModeCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( SamplerReductionModeCreateInfo ) - offsetof( SamplerReductionModeCreateInfo, pNext ) );
@@ -63517,18 +62349,6 @@
       , forceExplicitReconstruction( forceExplicitReconstruction_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SamplerYcbcrConversionCreateInfo( SamplerYcbcrConversionCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , format( rhs.format )
-      , ycbcrModel( rhs.ycbcrModel )
-      , ycbcrRange( rhs.ycbcrRange )
-      , components( rhs.components )
-      , xChromaOffset( rhs.xChromaOffset )
-      , yChromaOffset( rhs.yChromaOffset )
-      , chromaFilter( rhs.chromaFilter )
-      , forceExplicitReconstruction( rhs.forceExplicitReconstruction )
-    {}
-
     SamplerYcbcrConversionCreateInfo & operator=( SamplerYcbcrConversionCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( SamplerYcbcrConversionCreateInfo ) - offsetof( SamplerYcbcrConversionCreateInfo, pNext ) );
@@ -63654,11 +62474,6 @@
       : combinedImageSamplerDescriptorCount( combinedImageSamplerDescriptorCount_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SamplerYcbcrConversionImageFormatProperties( SamplerYcbcrConversionImageFormatProperties const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , combinedImageSamplerDescriptorCount( rhs.combinedImageSamplerDescriptorCount )
-    {}
-
     SamplerYcbcrConversionImageFormatProperties & operator=( SamplerYcbcrConversionImageFormatProperties const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( SamplerYcbcrConversionImageFormatProperties ) - offsetof( SamplerYcbcrConversionImageFormatProperties, pNext ) );
@@ -63716,11 +62531,6 @@
       : conversion( conversion_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SamplerYcbcrConversionInfo( SamplerYcbcrConversionInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , conversion( rhs.conversion )
-    {}
-
     SamplerYcbcrConversionInfo & operator=( SamplerYcbcrConversionInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( SamplerYcbcrConversionInfo ) - offsetof( SamplerYcbcrConversionInfo, pNext ) );
@@ -63790,11 +62600,6 @@
       : flags( flags_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SemaphoreCreateInfo( SemaphoreCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-    {}
-
     SemaphoreCreateInfo & operator=( SemaphoreCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( SemaphoreCreateInfo ) - offsetof( SemaphoreCreateInfo, pNext ) );
@@ -63866,12 +62671,6 @@
       , handleType( handleType_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SemaphoreGetFdInfoKHR( SemaphoreGetFdInfoKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , semaphore( rhs.semaphore )
-      , handleType( rhs.handleType )
-    {}
-
     SemaphoreGetFdInfoKHR & operator=( SemaphoreGetFdInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( SemaphoreGetFdInfoKHR ) - offsetof( SemaphoreGetFdInfoKHR, pNext ) );
@@ -63952,12 +62751,6 @@
       , handleType( handleType_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SemaphoreGetWin32HandleInfoKHR( SemaphoreGetWin32HandleInfoKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , semaphore( rhs.semaphore )
-      , handleType( rhs.handleType )
-    {}
-
     SemaphoreGetWin32HandleInfoKHR & operator=( SemaphoreGetWin32HandleInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( SemaphoreGetWin32HandleInfoKHR ) - offsetof( SemaphoreGetWin32HandleInfoKHR, pNext ) );
@@ -64038,12 +62831,6 @@
       , value( value_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SemaphoreSignalInfo( SemaphoreSignalInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , semaphore( rhs.semaphore )
-      , value( rhs.value )
-    {}
-
     SemaphoreSignalInfo & operator=( SemaphoreSignalInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( SemaphoreSignalInfo ) - offsetof( SemaphoreSignalInfo, pNext ) );
@@ -64123,12 +62910,6 @@
       , initialValue( initialValue_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SemaphoreTypeCreateInfo( SemaphoreTypeCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , semaphoreType( rhs.semaphoreType )
-      , initialValue( rhs.initialValue )
-    {}
-
     SemaphoreTypeCreateInfo & operator=( SemaphoreTypeCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( SemaphoreTypeCreateInfo ) - offsetof( SemaphoreTypeCreateInfo, pNext ) );
@@ -64212,14 +62993,6 @@
       , pValues( pValues_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SemaphoreWaitInfo( SemaphoreWaitInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , semaphoreCount( rhs.semaphoreCount )
-      , pSemaphores( rhs.pSemaphores )
-      , pValues( rhs.pValues )
-    {}
-
     SemaphoreWaitInfo & operator=( SemaphoreWaitInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( SemaphoreWaitInfo ) - offsetof( SemaphoreWaitInfo, pNext ) );
@@ -64307,6 +63080,59 @@
   static_assert( sizeof( SemaphoreWaitInfo ) == sizeof( VkSemaphoreWaitInfo ), "struct and wrapper have different size!" );
   static_assert( std::is_standard_layout<SemaphoreWaitInfo>::value, "struct wrapper is not a standard layout!" );
 
+  struct SetStateFlagsIndirectCommandNV
+  {
+    VULKAN_HPP_CONSTEXPR SetStateFlagsIndirectCommandNV( uint32_t data_ = {} ) VULKAN_HPP_NOEXCEPT
+      : data( data_ )
+    {}
+
+    SetStateFlagsIndirectCommandNV( VkSetStateFlagsIndirectCommandNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    SetStateFlagsIndirectCommandNV& operator=( VkSetStateFlagsIndirectCommandNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::SetStateFlagsIndirectCommandNV const *>(&rhs);
+      return *this;
+    }
+
+    SetStateFlagsIndirectCommandNV & setData( uint32_t data_ ) VULKAN_HPP_NOEXCEPT
+    {
+      data = data_;
+      return *this;
+    }
+
+    operator VkSetStateFlagsIndirectCommandNV const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkSetStateFlagsIndirectCommandNV*>( this );
+    }
+
+    operator VkSetStateFlagsIndirectCommandNV &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkSetStateFlagsIndirectCommandNV*>( this );
+    }
+
+#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
+    auto operator<=>( SetStateFlagsIndirectCommandNV const& ) const = default;
+#else
+    bool operator==( SetStateFlagsIndirectCommandNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ( data == rhs.data );
+    }
+
+    bool operator!=( SetStateFlagsIndirectCommandNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return !operator==( rhs );
+    }
+#endif
+
+  public:
+    uint32_t data = {};
+  };
+  static_assert( sizeof( SetStateFlagsIndirectCommandNV ) == sizeof( VkSetStateFlagsIndirectCommandNV ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<SetStateFlagsIndirectCommandNV>::value, "struct wrapper is not a standard layout!" );
+
   struct ShaderModuleCreateInfo
   {
     VULKAN_HPP_CONSTEXPR ShaderModuleCreateInfo( VULKAN_HPP_NAMESPACE::ShaderModuleCreateFlags flags_ = {},
@@ -64317,13 +63143,6 @@
       , pCode( pCode_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ShaderModuleCreateInfo( ShaderModuleCreateInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , codeSize( rhs.codeSize )
-      , pCode( rhs.pCode )
-    {}
-
     ShaderModuleCreateInfo & operator=( ShaderModuleCreateInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ShaderModuleCreateInfo ) - offsetof( ShaderModuleCreateInfo, pNext ) );
@@ -64409,11 +63228,6 @@
       : validationCache( validationCache_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ShaderModuleValidationCacheCreateInfoEXT( ShaderModuleValidationCacheCreateInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , validationCache( rhs.validationCache )
-    {}
-
     ShaderModuleValidationCacheCreateInfoEXT & operator=( ShaderModuleValidationCacheCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ShaderModuleValidationCacheCreateInfoEXT ) - offsetof( ShaderModuleValidationCacheCreateInfoEXT, pNext ) );
@@ -64491,20 +63305,6 @@
       , scratchMemUsageInBytes( scratchMemUsageInBytes_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ShaderResourceUsageAMD( ShaderResourceUsageAMD const& rhs ) VULKAN_HPP_NOEXCEPT
-      : numUsedVgprs( rhs.numUsedVgprs )
-      , numUsedSgprs( rhs.numUsedSgprs )
-      , ldsSizePerLocalWorkGroup( rhs.ldsSizePerLocalWorkGroup )
-      , ldsUsageSizeInBytes( rhs.ldsUsageSizeInBytes )
-      , scratchMemUsageInBytes( rhs.scratchMemUsageInBytes )
-    {}
-
-    ShaderResourceUsageAMD & operator=( ShaderResourceUsageAMD const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( ShaderResourceUsageAMD ) );
-      return *this;
-    }
-
     ShaderResourceUsageAMD( VkShaderResourceUsageAMD const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -64569,28 +63369,8 @@
       , numPhysicalSgprs( numPhysicalSgprs_ )
       , numAvailableVgprs( numAvailableVgprs_ )
       , numAvailableSgprs( numAvailableSgprs_ )
-      , computeWorkGroupSize{}
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint32_t,3>::copy( computeWorkGroupSize, computeWorkGroupSize_ );
-    }
-
-    VULKAN_HPP_CONSTEXPR_14 ShaderStatisticsInfoAMD( ShaderStatisticsInfoAMD const& rhs ) VULKAN_HPP_NOEXCEPT
-      : shaderStageMask( rhs.shaderStageMask )
-      , resourceUsage( rhs.resourceUsage )
-      , numPhysicalVgprs( rhs.numPhysicalVgprs )
-      , numPhysicalSgprs( rhs.numPhysicalSgprs )
-      , numAvailableVgprs( rhs.numAvailableVgprs )
-      , numAvailableSgprs( rhs.numAvailableSgprs )
-      , computeWorkGroupSize{}
-    {
-      VULKAN_HPP_NAMESPACE::ConstExpression1DArrayCopy<uint32_t,3>::copy( computeWorkGroupSize, rhs.computeWorkGroupSize );
-    }
-
-    ShaderStatisticsInfoAMD & operator=( ShaderStatisticsInfoAMD const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( ShaderStatisticsInfoAMD ) );
-      return *this;
-    }
+      , computeWorkGroupSize( computeWorkGroupSize_ )
+    {}
 
     ShaderStatisticsInfoAMD( VkShaderStatisticsInfoAMD const & rhs ) VULKAN_HPP_NOEXCEPT
     {
@@ -64624,7 +63404,7 @@
           && ( numPhysicalSgprs == rhs.numPhysicalSgprs )
           && ( numAvailableVgprs == rhs.numAvailableVgprs )
           && ( numAvailableSgprs == rhs.numAvailableSgprs )
-          && ( memcmp( computeWorkGroupSize, rhs.computeWorkGroupSize, 3 * sizeof( uint32_t ) ) == 0 );
+          && ( computeWorkGroupSize == rhs.computeWorkGroupSize );
     }
 
     bool operator!=( ShaderStatisticsInfoAMD const& rhs ) const VULKAN_HPP_NOEXCEPT
@@ -64640,7 +63420,7 @@
     uint32_t numPhysicalSgprs = {};
     uint32_t numAvailableVgprs = {};
     uint32_t numAvailableSgprs = {};
-    uint32_t computeWorkGroupSize[3] = {};
+    VULKAN_HPP_NAMESPACE::ArrayWrapper1D<uint32_t, 3> computeWorkGroupSize = {};
   };
   static_assert( sizeof( ShaderStatisticsInfoAMD ) == sizeof( VkShaderStatisticsInfoAMD ), "struct and wrapper have different size!" );
   static_assert( std::is_standard_layout<ShaderStatisticsInfoAMD>::value, "struct wrapper is not a standard layout!" );
@@ -64651,11 +63431,6 @@
       : sharedPresentSupportedUsageFlags( sharedPresentSupportedUsageFlags_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SharedPresentSurfaceCapabilitiesKHR( SharedPresentSurfaceCapabilitiesKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , sharedPresentSupportedUsageFlags( rhs.sharedPresentSupportedUsageFlags )
-    {}
-
     SharedPresentSurfaceCapabilitiesKHR & operator=( SharedPresentSurfaceCapabilitiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( SharedPresentSurfaceCapabilitiesKHR ) - offsetof( SharedPresentSurfaceCapabilitiesKHR, pNext ) );
@@ -64717,18 +63492,6 @@
       , flags( flags_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SparseImageFormatProperties( SparseImageFormatProperties const& rhs ) VULKAN_HPP_NOEXCEPT
-      : aspectMask( rhs.aspectMask )
-      , imageGranularity( rhs.imageGranularity )
-      , flags( rhs.flags )
-    {}
-
-    SparseImageFormatProperties & operator=( SparseImageFormatProperties const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( SparseImageFormatProperties ) );
-      return *this;
-    }
-
     SparseImageFormatProperties( VkSparseImageFormatProperties const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -64780,11 +63543,6 @@
       : properties( properties_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SparseImageFormatProperties2( SparseImageFormatProperties2 const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , properties( rhs.properties )
-    {}
-
     SparseImageFormatProperties2 & operator=( SparseImageFormatProperties2 const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( SparseImageFormatProperties2 ) - offsetof( SparseImageFormatProperties2, pNext ) );
@@ -64850,20 +63608,6 @@
       , imageMipTailStride( imageMipTailStride_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SparseImageMemoryRequirements( SparseImageMemoryRequirements const& rhs ) VULKAN_HPP_NOEXCEPT
-      : formatProperties( rhs.formatProperties )
-      , imageMipTailFirstLod( rhs.imageMipTailFirstLod )
-      , imageMipTailSize( rhs.imageMipTailSize )
-      , imageMipTailOffset( rhs.imageMipTailOffset )
-      , imageMipTailStride( rhs.imageMipTailStride )
-    {}
-
-    SparseImageMemoryRequirements & operator=( SparseImageMemoryRequirements const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( SparseImageMemoryRequirements ) );
-      return *this;
-    }
-
     SparseImageMemoryRequirements( VkSparseImageMemoryRequirements const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -64919,11 +63663,6 @@
       : memoryRequirements( memoryRequirements_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SparseImageMemoryRequirements2( SparseImageMemoryRequirements2 const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , memoryRequirements( rhs.memoryRequirements )
-    {}
-
     SparseImageMemoryRequirements2 & operator=( SparseImageMemoryRequirements2 const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( SparseImageMemoryRequirements2 ) - offsetof( SparseImageMemoryRequirements2, pNext ) );
@@ -64984,12 +63723,6 @@
       , streamDescriptor( streamDescriptor_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR StreamDescriptorSurfaceCreateInfoGGP( StreamDescriptorSurfaceCreateInfoGGP const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , streamDescriptor( rhs.streamDescriptor )
-    {}
-
     StreamDescriptorSurfaceCreateInfoGGP & operator=( StreamDescriptorSurfaceCreateInfoGGP const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( StreamDescriptorSurfaceCreateInfoGGP ) - offsetof( StreamDescriptorSurfaceCreateInfoGGP, pNext ) );
@@ -65062,6 +63795,100 @@
   static_assert( std::is_standard_layout<StreamDescriptorSurfaceCreateInfoGGP>::value, "struct wrapper is not a standard layout!" );
 #endif /*VK_USE_PLATFORM_GGP*/
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct StridedBufferRegionKHR
+  {
+    VULKAN_HPP_CONSTEXPR StridedBufferRegionKHR( VULKAN_HPP_NAMESPACE::Buffer buffer_ = {},
+                                                 VULKAN_HPP_NAMESPACE::DeviceSize offset_ = {},
+                                                 VULKAN_HPP_NAMESPACE::DeviceSize stride_ = {},
+                                                 VULKAN_HPP_NAMESPACE::DeviceSize size_ = {} ) VULKAN_HPP_NOEXCEPT
+      : buffer( buffer_ )
+      , offset( offset_ )
+      , stride( stride_ )
+      , size( size_ )
+    {}
+
+    explicit StridedBufferRegionKHR( IndirectCommandsStreamNV const& indirectCommandsStreamNV,
+                                     VULKAN_HPP_NAMESPACE::DeviceSize stride_ = {},
+                                     VULKAN_HPP_NAMESPACE::DeviceSize size_ = {} )
+      : buffer( indirectCommandsStreamNV.buffer )
+      , offset( indirectCommandsStreamNV.offset )
+      , stride( stride_ )
+      , size( size_ )
+    {}
+
+    StridedBufferRegionKHR( VkStridedBufferRegionKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    StridedBufferRegionKHR& operator=( VkStridedBufferRegionKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::StridedBufferRegionKHR const *>(&rhs);
+      return *this;
+    }
+
+    StridedBufferRegionKHR & setBuffer( VULKAN_HPP_NAMESPACE::Buffer buffer_ ) VULKAN_HPP_NOEXCEPT
+    {
+      buffer = buffer_;
+      return *this;
+    }
+
+    StridedBufferRegionKHR & setOffset( VULKAN_HPP_NAMESPACE::DeviceSize offset_ ) VULKAN_HPP_NOEXCEPT
+    {
+      offset = offset_;
+      return *this;
+    }
+
+    StridedBufferRegionKHR & setStride( VULKAN_HPP_NAMESPACE::DeviceSize stride_ ) VULKAN_HPP_NOEXCEPT
+    {
+      stride = stride_;
+      return *this;
+    }
+
+    StridedBufferRegionKHR & setSize( VULKAN_HPP_NAMESPACE::DeviceSize size_ ) VULKAN_HPP_NOEXCEPT
+    {
+      size = size_;
+      return *this;
+    }
+
+    operator VkStridedBufferRegionKHR const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkStridedBufferRegionKHR*>( this );
+    }
+
+    operator VkStridedBufferRegionKHR &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkStridedBufferRegionKHR*>( this );
+    }
+
+#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
+    auto operator<=>( StridedBufferRegionKHR const& ) const = default;
+#else
+    bool operator==( StridedBufferRegionKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ( buffer == rhs.buffer )
+          && ( offset == rhs.offset )
+          && ( stride == rhs.stride )
+          && ( size == rhs.size );
+    }
+
+    bool operator!=( StridedBufferRegionKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return !operator==( rhs );
+    }
+#endif
+
+  public:
+    VULKAN_HPP_NAMESPACE::Buffer buffer = {};
+    VULKAN_HPP_NAMESPACE::DeviceSize offset = {};
+    VULKAN_HPP_NAMESPACE::DeviceSize stride = {};
+    VULKAN_HPP_NAMESPACE::DeviceSize size = {};
+  };
+  static_assert( sizeof( StridedBufferRegionKHR ) == sizeof( VkStridedBufferRegionKHR ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<StridedBufferRegionKHR>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
   struct SubmitInfo
   {
     VULKAN_HPP_CONSTEXPR SubmitInfo( uint32_t waitSemaphoreCount_ = {},
@@ -65080,17 +63907,6 @@
       , pSignalSemaphores( pSignalSemaphores_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SubmitInfo( SubmitInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , waitSemaphoreCount( rhs.waitSemaphoreCount )
-      , pWaitSemaphores( rhs.pWaitSemaphores )
-      , pWaitDstStageMask( rhs.pWaitDstStageMask )
-      , commandBufferCount( rhs.commandBufferCount )
-      , pCommandBuffers( rhs.pCommandBuffers )
-      , signalSemaphoreCount( rhs.signalSemaphoreCount )
-      , pSignalSemaphores( rhs.pSignalSemaphores )
-    {}
-
     SubmitInfo & operator=( SubmitInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( SubmitInfo ) - offsetof( SubmitInfo, pNext ) );
@@ -65208,11 +64024,6 @@
       : contents( contents_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SubpassBeginInfo( SubpassBeginInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , contents( rhs.contents )
-    {}
-
     SubpassBeginInfo & operator=( SubpassBeginInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( SubpassBeginInfo ) - offsetof( SubpassBeginInfo, pNext ) );
@@ -65286,13 +64097,6 @@
       , pDepthStencilResolveAttachment( pDepthStencilResolveAttachment_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SubpassDescriptionDepthStencilResolve( SubpassDescriptionDepthStencilResolve const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , depthResolveMode( rhs.depthResolveMode )
-      , stencilResolveMode( rhs.stencilResolveMode )
-      , pDepthStencilResolveAttachment( rhs.pDepthStencilResolveAttachment )
-    {}
-
     SubpassDescriptionDepthStencilResolve & operator=( SubpassDescriptionDepthStencilResolve const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( SubpassDescriptionDepthStencilResolve ) - offsetof( SubpassDescriptionDepthStencilResolve, pNext ) );
@@ -65377,10 +64181,6 @@
     VULKAN_HPP_CONSTEXPR SubpassEndInfo() VULKAN_HPP_NOEXCEPT
     {}
 
-    VULKAN_HPP_CONSTEXPR SubpassEndInfo( SubpassEndInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-    {}
-
     SubpassEndInfo & operator=( SubpassEndInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( SubpassEndInfo ) - offsetof( SubpassEndInfo, pNext ) );
@@ -65462,21 +64262,6 @@
       , supportedSurfaceCounters( supportedSurfaceCounters_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SurfaceCapabilities2EXT( SurfaceCapabilities2EXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , minImageCount( rhs.minImageCount )
-      , maxImageCount( rhs.maxImageCount )
-      , currentExtent( rhs.currentExtent )
-      , minImageExtent( rhs.minImageExtent )
-      , maxImageExtent( rhs.maxImageExtent )
-      , maxImageArrayLayers( rhs.maxImageArrayLayers )
-      , supportedTransforms( rhs.supportedTransforms )
-      , currentTransform( rhs.currentTransform )
-      , supportedCompositeAlpha( rhs.supportedCompositeAlpha )
-      , supportedUsageFlags( rhs.supportedUsageFlags )
-      , supportedSurfaceCounters( rhs.supportedSurfaceCounters )
-    {}
-
     SurfaceCapabilities2EXT & operator=( SurfaceCapabilities2EXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( SurfaceCapabilities2EXT ) - offsetof( SurfaceCapabilities2EXT, pNext ) );
@@ -65572,25 +64357,6 @@
       , supportedUsageFlags( supportedUsageFlags_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SurfaceCapabilitiesKHR( SurfaceCapabilitiesKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : minImageCount( rhs.minImageCount )
-      , maxImageCount( rhs.maxImageCount )
-      , currentExtent( rhs.currentExtent )
-      , minImageExtent( rhs.minImageExtent )
-      , maxImageExtent( rhs.maxImageExtent )
-      , maxImageArrayLayers( rhs.maxImageArrayLayers )
-      , supportedTransforms( rhs.supportedTransforms )
-      , currentTransform( rhs.currentTransform )
-      , supportedCompositeAlpha( rhs.supportedCompositeAlpha )
-      , supportedUsageFlags( rhs.supportedUsageFlags )
-    {}
-
-    SurfaceCapabilitiesKHR & operator=( SurfaceCapabilitiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( SurfaceCapabilitiesKHR ) );
-      return *this;
-    }
-
     SurfaceCapabilitiesKHR( VkSurfaceCapabilitiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -65656,11 +64422,6 @@
       : surfaceCapabilities( surfaceCapabilities_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SurfaceCapabilities2KHR( SurfaceCapabilities2KHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , surfaceCapabilities( rhs.surfaceCapabilities )
-    {}
-
     SurfaceCapabilities2KHR & operator=( SurfaceCapabilities2KHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( SurfaceCapabilities2KHR ) - offsetof( SurfaceCapabilities2KHR, pNext ) );
@@ -65719,11 +64480,6 @@
       : fullScreenExclusiveSupported( fullScreenExclusiveSupported_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SurfaceCapabilitiesFullScreenExclusiveEXT( SurfaceCapabilitiesFullScreenExclusiveEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , fullScreenExclusiveSupported( rhs.fullScreenExclusiveSupported )
-    {}
-
     SurfaceCapabilitiesFullScreenExclusiveEXT & operator=( SurfaceCapabilitiesFullScreenExclusiveEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( SurfaceCapabilitiesFullScreenExclusiveEXT ) - offsetof( SurfaceCapabilitiesFullScreenExclusiveEXT, pNext ) );
@@ -65796,17 +64552,6 @@
       , colorSpace( colorSpace_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SurfaceFormatKHR( SurfaceFormatKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : format( rhs.format )
-      , colorSpace( rhs.colorSpace )
-    {}
-
-    SurfaceFormatKHR & operator=( SurfaceFormatKHR const & rhs ) VULKAN_HPP_NOEXCEPT
-    {
-      memcpy( static_cast<void*>(this), &rhs, sizeof( SurfaceFormatKHR ) );
-      return *this;
-    }
-
     SurfaceFormatKHR( VkSurfaceFormatKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
@@ -65856,11 +64601,6 @@
       : surfaceFormat( surfaceFormat_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SurfaceFormat2KHR( SurfaceFormat2KHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , surfaceFormat( rhs.surfaceFormat )
-    {}
-
     SurfaceFormat2KHR & operator=( SurfaceFormat2KHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( SurfaceFormat2KHR ) - offsetof( SurfaceFormat2KHR, pNext ) );
@@ -65919,11 +64659,6 @@
       : fullScreenExclusive( fullScreenExclusive_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SurfaceFullScreenExclusiveInfoEXT( SurfaceFullScreenExclusiveInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , fullScreenExclusive( rhs.fullScreenExclusive )
-    {}
-
     SurfaceFullScreenExclusiveInfoEXT & operator=( SurfaceFullScreenExclusiveInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( SurfaceFullScreenExclusiveInfoEXT ) - offsetof( SurfaceFullScreenExclusiveInfoEXT, pNext ) );
@@ -65995,11 +64730,6 @@
       : hmonitor( hmonitor_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SurfaceFullScreenExclusiveWin32InfoEXT( SurfaceFullScreenExclusiveWin32InfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , hmonitor( rhs.hmonitor )
-    {}
-
     SurfaceFullScreenExclusiveWin32InfoEXT & operator=( SurfaceFullScreenExclusiveWin32InfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( SurfaceFullScreenExclusiveWin32InfoEXT ) - offsetof( SurfaceFullScreenExclusiveWin32InfoEXT, pNext ) );
@@ -66070,11 +64800,6 @@
       : supportsProtected( supportsProtected_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SurfaceProtectedCapabilitiesKHR( SurfaceProtectedCapabilitiesKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , supportsProtected( rhs.supportsProtected )
-    {}
-
     SurfaceProtectedCapabilitiesKHR & operator=( SurfaceProtectedCapabilitiesKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( SurfaceProtectedCapabilitiesKHR ) - offsetof( SurfaceProtectedCapabilitiesKHR, pNext ) );
@@ -66144,11 +64869,6 @@
       : surfaceCounters( surfaceCounters_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SwapchainCounterCreateInfoEXT( SwapchainCounterCreateInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , surfaceCounters( rhs.surfaceCounters )
-    {}
-
     SwapchainCounterCreateInfoEXT & operator=( SwapchainCounterCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( SwapchainCounterCreateInfoEXT ) - offsetof( SwapchainCounterCreateInfoEXT, pNext ) );
@@ -66248,26 +64968,6 @@
       , oldSwapchain( oldSwapchain_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SwapchainCreateInfoKHR( SwapchainCreateInfoKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , surface( rhs.surface )
-      , minImageCount( rhs.minImageCount )
-      , imageFormat( rhs.imageFormat )
-      , imageColorSpace( rhs.imageColorSpace )
-      , imageExtent( rhs.imageExtent )
-      , imageArrayLayers( rhs.imageArrayLayers )
-      , imageUsage( rhs.imageUsage )
-      , imageSharingMode( rhs.imageSharingMode )
-      , queueFamilyIndexCount( rhs.queueFamilyIndexCount )
-      , pQueueFamilyIndices( rhs.pQueueFamilyIndices )
-      , preTransform( rhs.preTransform )
-      , compositeAlpha( rhs.compositeAlpha )
-      , presentMode( rhs.presentMode )
-      , clipped( rhs.clipped )
-      , oldSwapchain( rhs.oldSwapchain )
-    {}
-
     SwapchainCreateInfoKHR & operator=( SwapchainCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( SwapchainCreateInfoKHR ) - offsetof( SwapchainCreateInfoKHR, pNext ) );
@@ -66457,11 +65157,6 @@
       : localDimmingEnable( localDimmingEnable_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR SwapchainDisplayNativeHdrCreateInfoAMD( SwapchainDisplayNativeHdrCreateInfoAMD const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , localDimmingEnable( rhs.localDimmingEnable )
-    {}
-
     SwapchainDisplayNativeHdrCreateInfoAMD & operator=( SwapchainDisplayNativeHdrCreateInfoAMD const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( SwapchainDisplayNativeHdrCreateInfoAMD ) - offsetof( SwapchainDisplayNativeHdrCreateInfoAMD, pNext ) );
@@ -66531,11 +65226,6 @@
       : supportsTextureGatherLODBiasAMD( supportsTextureGatherLODBiasAMD_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR TextureLODGatherFormatPropertiesAMD( TextureLODGatherFormatPropertiesAMD const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , supportsTextureGatherLODBiasAMD( rhs.supportsTextureGatherLODBiasAMD )
-    {}
-
     TextureLODGatherFormatPropertiesAMD & operator=( TextureLODGatherFormatPropertiesAMD const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( TextureLODGatherFormatPropertiesAMD ) - offsetof( TextureLODGatherFormatPropertiesAMD, pNext ) );
@@ -66599,14 +65289,6 @@
       , pSignalSemaphoreValues( pSignalSemaphoreValues_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR TimelineSemaphoreSubmitInfo( TimelineSemaphoreSubmitInfo const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , waitSemaphoreValueCount( rhs.waitSemaphoreValueCount )
-      , pWaitSemaphoreValues( rhs.pWaitSemaphoreValues )
-      , signalSemaphoreValueCount( rhs.signalSemaphoreValueCount )
-      , pSignalSemaphoreValues( rhs.pSignalSemaphoreValues )
-    {}
-
     TimelineSemaphoreSubmitInfo & operator=( TimelineSemaphoreSubmitInfo const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( TimelineSemaphoreSubmitInfo ) - offsetof( TimelineSemaphoreSubmitInfo, pNext ) );
@@ -66694,6 +65376,88 @@
   static_assert( sizeof( TimelineSemaphoreSubmitInfo ) == sizeof( VkTimelineSemaphoreSubmitInfo ), "struct and wrapper have different size!" );
   static_assert( std::is_standard_layout<TimelineSemaphoreSubmitInfo>::value, "struct wrapper is not a standard layout!" );
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  struct TraceRaysIndirectCommandKHR
+  {
+    VULKAN_HPP_CONSTEXPR TraceRaysIndirectCommandKHR( uint32_t width_ = {},
+                                                      uint32_t height_ = {},
+                                                      uint32_t depth_ = {} ) VULKAN_HPP_NOEXCEPT
+      : width( width_ )
+      , height( height_ )
+      , depth( depth_ )
+    {}
+
+    explicit TraceRaysIndirectCommandKHR( Extent2D const& extent2D,
+                                          uint32_t depth_ = {} )
+      : width( extent2D.width )
+      , height( extent2D.height )
+      , depth( depth_ )
+    {}
+
+    TraceRaysIndirectCommandKHR( VkTraceRaysIndirectCommandKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = rhs;
+    }
+
+    TraceRaysIndirectCommandKHR& operator=( VkTraceRaysIndirectCommandKHR const & rhs ) VULKAN_HPP_NOEXCEPT
+    {
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::TraceRaysIndirectCommandKHR const *>(&rhs);
+      return *this;
+    }
+
+    TraceRaysIndirectCommandKHR & setWidth( uint32_t width_ ) VULKAN_HPP_NOEXCEPT
+    {
+      width = width_;
+      return *this;
+    }
+
+    TraceRaysIndirectCommandKHR & setHeight( uint32_t height_ ) VULKAN_HPP_NOEXCEPT
+    {
+      height = height_;
+      return *this;
+    }
+
+    TraceRaysIndirectCommandKHR & setDepth( uint32_t depth_ ) VULKAN_HPP_NOEXCEPT
+    {
+      depth = depth_;
+      return *this;
+    }
+
+    operator VkTraceRaysIndirectCommandKHR const&() const VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<const VkTraceRaysIndirectCommandKHR*>( this );
+    }
+
+    operator VkTraceRaysIndirectCommandKHR &() VULKAN_HPP_NOEXCEPT
+    {
+      return *reinterpret_cast<VkTraceRaysIndirectCommandKHR*>( this );
+    }
+
+#if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
+    auto operator<=>( TraceRaysIndirectCommandKHR const& ) const = default;
+#else
+    bool operator==( TraceRaysIndirectCommandKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return ( width == rhs.width )
+          && ( height == rhs.height )
+          && ( depth == rhs.depth );
+    }
+
+    bool operator!=( TraceRaysIndirectCommandKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
+    {
+      return !operator==( rhs );
+    }
+#endif
+
+  public:
+    uint32_t width = {};
+    uint32_t height = {};
+    uint32_t depth = {};
+  };
+  static_assert( sizeof( TraceRaysIndirectCommandKHR ) == sizeof( VkTraceRaysIndirectCommandKHR ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<TraceRaysIndirectCommandKHR>::value, "struct wrapper is not a standard layout!" );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
   struct ValidationCacheCreateInfoEXT
   {
     VULKAN_HPP_CONSTEXPR ValidationCacheCreateInfoEXT( VULKAN_HPP_NAMESPACE::ValidationCacheCreateFlagsEXT flags_ = {},
@@ -66704,13 +65468,6 @@
       , pInitialData( pInitialData_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ValidationCacheCreateInfoEXT( ValidationCacheCreateInfoEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , initialDataSize( rhs.initialDataSize )
-      , pInitialData( rhs.pInitialData )
-    {}
-
     ValidationCacheCreateInfoEXT & operator=( ValidationCacheCreateInfoEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ValidationCacheCreateInfoEXT ) - offsetof( ValidationCacheCreateInfoEXT, pNext ) );
@@ -66802,14 +65559,6 @@
       , pDisabledValidationFeatures( pDisabledValidationFeatures_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ValidationFeaturesEXT( ValidationFeaturesEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , enabledValidationFeatureCount( rhs.enabledValidationFeatureCount )
-      , pEnabledValidationFeatures( rhs.pEnabledValidationFeatures )
-      , disabledValidationFeatureCount( rhs.disabledValidationFeatureCount )
-      , pDisabledValidationFeatures( rhs.pDisabledValidationFeatures )
-    {}
-
     ValidationFeaturesEXT & operator=( ValidationFeaturesEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ValidationFeaturesEXT ) - offsetof( ValidationFeaturesEXT, pNext ) );
@@ -66905,12 +65654,6 @@
       , pDisabledValidationChecks( pDisabledValidationChecks_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ValidationFlagsEXT( ValidationFlagsEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , disabledValidationCheckCount( rhs.disabledValidationCheckCount )
-      , pDisabledValidationChecks( rhs.pDisabledValidationChecks )
-    {}
-
     ValidationFlagsEXT & operator=( ValidationFlagsEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ValidationFlagsEXT ) - offsetof( ValidationFlagsEXT, pNext ) );
@@ -66991,12 +65734,6 @@
       , window( window_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR ViSurfaceCreateInfoNN( ViSurfaceCreateInfoNN const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , window( rhs.window )
-    {}
-
     ViSurfaceCreateInfoNN & operator=( ViSurfaceCreateInfoNN const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( ViSurfaceCreateInfoNN ) - offsetof( ViSurfaceCreateInfoNN, pNext ) );
@@ -67080,13 +65817,6 @@
       , surface( surface_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR WaylandSurfaceCreateInfoKHR( WaylandSurfaceCreateInfoKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , display( rhs.display )
-      , surface( rhs.surface )
-    {}
-
     WaylandSurfaceCreateInfoKHR & operator=( WaylandSurfaceCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( WaylandSurfaceCreateInfoKHR ) - offsetof( WaylandSurfaceCreateInfoKHR, pNext ) );
@@ -67186,17 +65916,6 @@
       , pReleaseKeys( pReleaseKeys_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR Win32KeyedMutexAcquireReleaseInfoKHR( Win32KeyedMutexAcquireReleaseInfoKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , acquireCount( rhs.acquireCount )
-      , pAcquireSyncs( rhs.pAcquireSyncs )
-      , pAcquireKeys( rhs.pAcquireKeys )
-      , pAcquireTimeouts( rhs.pAcquireTimeouts )
-      , releaseCount( rhs.releaseCount )
-      , pReleaseSyncs( rhs.pReleaseSyncs )
-      , pReleaseKeys( rhs.pReleaseKeys )
-    {}
-
     Win32KeyedMutexAcquireReleaseInfoKHR & operator=( Win32KeyedMutexAcquireReleaseInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( Win32KeyedMutexAcquireReleaseInfoKHR ) - offsetof( Win32KeyedMutexAcquireReleaseInfoKHR, pNext ) );
@@ -67328,17 +66047,6 @@
       , pReleaseKeys( pReleaseKeys_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR Win32KeyedMutexAcquireReleaseInfoNV( Win32KeyedMutexAcquireReleaseInfoNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , acquireCount( rhs.acquireCount )
-      , pAcquireSyncs( rhs.pAcquireSyncs )
-      , pAcquireKeys( rhs.pAcquireKeys )
-      , pAcquireTimeoutMilliseconds( rhs.pAcquireTimeoutMilliseconds )
-      , releaseCount( rhs.releaseCount )
-      , pReleaseSyncs( rhs.pReleaseSyncs )
-      , pReleaseKeys( rhs.pReleaseKeys )
-    {}
-
     Win32KeyedMutexAcquireReleaseInfoNV & operator=( Win32KeyedMutexAcquireReleaseInfoNV const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( Win32KeyedMutexAcquireReleaseInfoNV ) - offsetof( Win32KeyedMutexAcquireReleaseInfoNV, pNext ) );
@@ -67462,13 +66170,6 @@
       , hwnd( hwnd_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR Win32SurfaceCreateInfoKHR( Win32SurfaceCreateInfoKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , hinstance( rhs.hinstance )
-      , hwnd( rhs.hwnd )
-    {}
-
     Win32SurfaceCreateInfoKHR & operator=( Win32SurfaceCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( Win32SurfaceCreateInfoKHR ) - offsetof( Win32SurfaceCreateInfoKHR, pNext ) );
@@ -67569,18 +66270,6 @@
       , pTexelBufferView( pTexelBufferView_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR WriteDescriptorSet( WriteDescriptorSet const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , dstSet( rhs.dstSet )
-      , dstBinding( rhs.dstBinding )
-      , dstArrayElement( rhs.dstArrayElement )
-      , descriptorCount( rhs.descriptorCount )
-      , descriptorType( rhs.descriptorType )
-      , pImageInfo( rhs.pImageInfo )
-      , pBufferInfo( rhs.pBufferInfo )
-      , pTexelBufferView( rhs.pTexelBufferView )
-    {}
-
     WriteDescriptorSet & operator=( WriteDescriptorSet const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( WriteDescriptorSet ) - offsetof( WriteDescriptorSet, pNext ) );
@@ -67700,69 +66389,63 @@
   static_assert( sizeof( WriteDescriptorSet ) == sizeof( VkWriteDescriptorSet ), "struct and wrapper have different size!" );
   static_assert( std::is_standard_layout<WriteDescriptorSet>::value, "struct wrapper is not a standard layout!" );
 
-  struct WriteDescriptorSetAccelerationStructureNV
+  struct WriteDescriptorSetAccelerationStructureKHR
   {
-    VULKAN_HPP_CONSTEXPR WriteDescriptorSetAccelerationStructureNV( uint32_t accelerationStructureCount_ = {},
-                                                                    const VULKAN_HPP_NAMESPACE::AccelerationStructureNV* pAccelerationStructures_ = {} ) VULKAN_HPP_NOEXCEPT
+    VULKAN_HPP_CONSTEXPR WriteDescriptorSetAccelerationStructureKHR( uint32_t accelerationStructureCount_ = {},
+                                                                     const VULKAN_HPP_NAMESPACE::AccelerationStructureKHR* pAccelerationStructures_ = {} ) VULKAN_HPP_NOEXCEPT
       : accelerationStructureCount( accelerationStructureCount_ )
       , pAccelerationStructures( pAccelerationStructures_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR WriteDescriptorSetAccelerationStructureNV( WriteDescriptorSetAccelerationStructureNV const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , accelerationStructureCount( rhs.accelerationStructureCount )
-      , pAccelerationStructures( rhs.pAccelerationStructures )
-    {}
-
-    WriteDescriptorSetAccelerationStructureNV & operator=( WriteDescriptorSetAccelerationStructureNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    WriteDescriptorSetAccelerationStructureKHR & operator=( WriteDescriptorSetAccelerationStructureKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
-      memcpy( &pNext, &rhs.pNext, sizeof( WriteDescriptorSetAccelerationStructureNV ) - offsetof( WriteDescriptorSetAccelerationStructureNV, pNext ) );
+      memcpy( &pNext, &rhs.pNext, sizeof( WriteDescriptorSetAccelerationStructureKHR ) - offsetof( WriteDescriptorSetAccelerationStructureKHR, pNext ) );
       return *this;
     }
 
-    WriteDescriptorSetAccelerationStructureNV( VkWriteDescriptorSetAccelerationStructureNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    WriteDescriptorSetAccelerationStructureKHR( VkWriteDescriptorSetAccelerationStructureKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       *this = rhs;
     }
 
-    WriteDescriptorSetAccelerationStructureNV& operator=( VkWriteDescriptorSetAccelerationStructureNV const & rhs ) VULKAN_HPP_NOEXCEPT
+    WriteDescriptorSetAccelerationStructureKHR& operator=( VkWriteDescriptorSetAccelerationStructureKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
-      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::WriteDescriptorSetAccelerationStructureNV const *>(&rhs);
+      *this = *reinterpret_cast<VULKAN_HPP_NAMESPACE::WriteDescriptorSetAccelerationStructureKHR const *>(&rhs);
       return *this;
     }
 
-    WriteDescriptorSetAccelerationStructureNV & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
+    WriteDescriptorSetAccelerationStructureKHR & setPNext( const void* pNext_ ) VULKAN_HPP_NOEXCEPT
     {
       pNext = pNext_;
       return *this;
     }
 
-    WriteDescriptorSetAccelerationStructureNV & setAccelerationStructureCount( uint32_t accelerationStructureCount_ ) VULKAN_HPP_NOEXCEPT
+    WriteDescriptorSetAccelerationStructureKHR & setAccelerationStructureCount( uint32_t accelerationStructureCount_ ) VULKAN_HPP_NOEXCEPT
     {
       accelerationStructureCount = accelerationStructureCount_;
       return *this;
     }
 
-    WriteDescriptorSetAccelerationStructureNV & setPAccelerationStructures( const VULKAN_HPP_NAMESPACE::AccelerationStructureNV* pAccelerationStructures_ ) VULKAN_HPP_NOEXCEPT
+    WriteDescriptorSetAccelerationStructureKHR & setPAccelerationStructures( const VULKAN_HPP_NAMESPACE::AccelerationStructureKHR* pAccelerationStructures_ ) VULKAN_HPP_NOEXCEPT
     {
       pAccelerationStructures = pAccelerationStructures_;
       return *this;
     }
 
-    operator VkWriteDescriptorSetAccelerationStructureNV const&() const VULKAN_HPP_NOEXCEPT
+    operator VkWriteDescriptorSetAccelerationStructureKHR const&() const VULKAN_HPP_NOEXCEPT
     {
-      return *reinterpret_cast<const VkWriteDescriptorSetAccelerationStructureNV*>( this );
+      return *reinterpret_cast<const VkWriteDescriptorSetAccelerationStructureKHR*>( this );
     }
 
-    operator VkWriteDescriptorSetAccelerationStructureNV &() VULKAN_HPP_NOEXCEPT
+    operator VkWriteDescriptorSetAccelerationStructureKHR &() VULKAN_HPP_NOEXCEPT
     {
-      return *reinterpret_cast<VkWriteDescriptorSetAccelerationStructureNV*>( this );
+      return *reinterpret_cast<VkWriteDescriptorSetAccelerationStructureKHR*>( this );
     }
 
 #if defined(VULKAN_HPP_HAS_SPACESHIP_OPERATOR)
-    auto operator<=>( WriteDescriptorSetAccelerationStructureNV const& ) const = default;
+    auto operator<=>( WriteDescriptorSetAccelerationStructureKHR const& ) const = default;
 #else
-    bool operator==( WriteDescriptorSetAccelerationStructureNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+    bool operator==( WriteDescriptorSetAccelerationStructureKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
     {
       return ( sType == rhs.sType )
           && ( pNext == rhs.pNext )
@@ -67770,20 +66453,20 @@
           && ( pAccelerationStructures == rhs.pAccelerationStructures );
     }
 
-    bool operator!=( WriteDescriptorSetAccelerationStructureNV const& rhs ) const VULKAN_HPP_NOEXCEPT
+    bool operator!=( WriteDescriptorSetAccelerationStructureKHR const& rhs ) const VULKAN_HPP_NOEXCEPT
     {
       return !operator==( rhs );
     }
 #endif
 
   public:
-    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eWriteDescriptorSetAccelerationStructureNV;
+    const VULKAN_HPP_NAMESPACE::StructureType sType = StructureType::eWriteDescriptorSetAccelerationStructureKHR;
     const void* pNext = {};
     uint32_t accelerationStructureCount = {};
-    const VULKAN_HPP_NAMESPACE::AccelerationStructureNV* pAccelerationStructures = {};
+    const VULKAN_HPP_NAMESPACE::AccelerationStructureKHR* pAccelerationStructures = {};
   };
-  static_assert( sizeof( WriteDescriptorSetAccelerationStructureNV ) == sizeof( VkWriteDescriptorSetAccelerationStructureNV ), "struct and wrapper have different size!" );
-  static_assert( std::is_standard_layout<WriteDescriptorSetAccelerationStructureNV>::value, "struct wrapper is not a standard layout!" );
+  static_assert( sizeof( WriteDescriptorSetAccelerationStructureKHR ) == sizeof( VkWriteDescriptorSetAccelerationStructureKHR ), "struct and wrapper have different size!" );
+  static_assert( std::is_standard_layout<WriteDescriptorSetAccelerationStructureKHR>::value, "struct wrapper is not a standard layout!" );
 
   struct WriteDescriptorSetInlineUniformBlockEXT
   {
@@ -67793,12 +66476,6 @@
       , pData( pData_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR WriteDescriptorSetInlineUniformBlockEXT( WriteDescriptorSetInlineUniformBlockEXT const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , dataSize( rhs.dataSize )
-      , pData( rhs.pData )
-    {}
-
     WriteDescriptorSetInlineUniformBlockEXT & operator=( WriteDescriptorSetInlineUniformBlockEXT const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( WriteDescriptorSetInlineUniformBlockEXT ) - offsetof( WriteDescriptorSetInlineUniformBlockEXT, pNext ) );
@@ -67881,13 +66558,6 @@
       , window( window_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR XcbSurfaceCreateInfoKHR( XcbSurfaceCreateInfoKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , connection( rhs.connection )
-      , window( rhs.window )
-    {}
-
     XcbSurfaceCreateInfoKHR & operator=( XcbSurfaceCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( XcbSurfaceCreateInfoKHR ) - offsetof( XcbSurfaceCreateInfoKHR, pNext ) );
@@ -67979,13 +66649,6 @@
       , window( window_ )
     {}
 
-    VULKAN_HPP_CONSTEXPR XlibSurfaceCreateInfoKHR( XlibSurfaceCreateInfoKHR const& rhs ) VULKAN_HPP_NOEXCEPT
-      : pNext( rhs.pNext )
-      , flags( rhs.flags )
-      , dpy( rhs.dpy )
-      , window( rhs.window )
-    {}
-
     XlibSurfaceCreateInfoKHR & operator=( XlibSurfaceCreateInfoKHR const & rhs ) VULKAN_HPP_NOEXCEPT
     {
       memcpy( &pNext, &rhs.pNext, sizeof( XlibSurfaceCreateInfoKHR ) - offsetof( XlibSurfaceCreateInfoKHR, pNext ) );
@@ -68308,13 +66971,13 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE void CommandBuffer::beginRenderPass2KHR( const VULKAN_HPP_NAMESPACE::RenderPassBeginInfo* pRenderPassBegin, const VULKAN_HPP_NAMESPACE::SubpassBeginInfo* pSubpassBeginInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkCmdBeginRenderPass2( m_commandBuffer, reinterpret_cast<const VkRenderPassBeginInfo*>( pRenderPassBegin ), reinterpret_cast<const VkSubpassBeginInfo*>( pSubpassBeginInfo ) );
+    d.vkCmdBeginRenderPass2KHR( m_commandBuffer, reinterpret_cast<const VkRenderPassBeginInfo*>( pRenderPassBegin ), reinterpret_cast<const VkSubpassBeginInfo*>( pSubpassBeginInfo ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
   VULKAN_HPP_INLINE void CommandBuffer::beginRenderPass2KHR( const RenderPassBeginInfo & renderPassBegin, const SubpassBeginInfo & subpassBeginInfo, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkCmdBeginRenderPass2( m_commandBuffer, reinterpret_cast<const VkRenderPassBeginInfo*>( &renderPassBegin ), reinterpret_cast<const VkSubpassBeginInfo*>( &subpassBeginInfo ) );
+    d.vkCmdBeginRenderPass2KHR( m_commandBuffer, reinterpret_cast<const VkRenderPassBeginInfo*>( &renderPassBegin ), reinterpret_cast<const VkSubpassBeginInfo*>( &subpassBeginInfo ) );
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
@@ -68382,6 +67045,20 @@
 
 #ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
+  VULKAN_HPP_INLINE void CommandBuffer::bindPipelineShaderGroupNV( VULKAN_HPP_NAMESPACE::PipelineBindPoint pipelineBindPoint, VULKAN_HPP_NAMESPACE::Pipeline pipeline, uint32_t groupIndex, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  {
+    d.vkCmdBindPipelineShaderGroupNV( m_commandBuffer, static_cast<VkPipelineBindPoint>( pipelineBindPoint ), static_cast<VkPipeline>( pipeline ), groupIndex );
+  }
+#else
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE void CommandBuffer::bindPipelineShaderGroupNV( VULKAN_HPP_NAMESPACE::PipelineBindPoint pipelineBindPoint, VULKAN_HPP_NAMESPACE::Pipeline pipeline, uint32_t groupIndex, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+  {
+    d.vkCmdBindPipelineShaderGroupNV( m_commandBuffer, static_cast<VkPipelineBindPoint>( pipelineBindPoint ), static_cast<VkPipeline>( pipeline ), groupIndex );
+  }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+  template<typename Dispatch>
   VULKAN_HPP_INLINE void CommandBuffer::bindShadingRateImageNV( VULKAN_HPP_NAMESPACE::ImageView imageView, VULKAN_HPP_NAMESPACE::ImageLayout imageLayout, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
     d.vkCmdBindShadingRateImageNV( m_commandBuffer, static_cast<VkImageView>( imageView ), static_cast<VkImageLayout>( imageLayout ) );
@@ -68465,16 +67142,54 @@
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
   template<typename Dispatch>
-  VULKAN_HPP_INLINE void CommandBuffer::buildAccelerationStructureNV( const VULKAN_HPP_NAMESPACE::AccelerationStructureInfoNV* pInfo, VULKAN_HPP_NAMESPACE::Buffer instanceData, VULKAN_HPP_NAMESPACE::DeviceSize instanceOffset, VULKAN_HPP_NAMESPACE::Bool32 update, VULKAN_HPP_NAMESPACE::AccelerationStructureNV dst, VULKAN_HPP_NAMESPACE::AccelerationStructureNV src, VULKAN_HPP_NAMESPACE::Buffer scratch, VULKAN_HPP_NAMESPACE::DeviceSize scratchOffset, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  VULKAN_HPP_INLINE void CommandBuffer::buildAccelerationStructureIndirectKHR( const VULKAN_HPP_NAMESPACE::AccelerationStructureBuildGeometryInfoKHR* pInfo, VULKAN_HPP_NAMESPACE::Buffer indirectBuffer, VULKAN_HPP_NAMESPACE::DeviceSize indirectOffset, uint32_t indirectStride, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkCmdBuildAccelerationStructureNV( m_commandBuffer, reinterpret_cast<const VkAccelerationStructureInfoNV*>( pInfo ), static_cast<VkBuffer>( instanceData ), static_cast<VkDeviceSize>( instanceOffset ), static_cast<VkBool32>( update ), static_cast<VkAccelerationStructureNV>( dst ), static_cast<VkAccelerationStructureNV>( src ), static_cast<VkBuffer>( scratch ), static_cast<VkDeviceSize>( scratchOffset ) );
+    d.vkCmdBuildAccelerationStructureIndirectKHR( m_commandBuffer, reinterpret_cast<const VkAccelerationStructureBuildGeometryInfoKHR*>( pInfo ), static_cast<VkBuffer>( indirectBuffer ), static_cast<VkDeviceSize>( indirectOffset ), indirectStride );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
-  VULKAN_HPP_INLINE void CommandBuffer::buildAccelerationStructureNV( const AccelerationStructureInfoNV & info, VULKAN_HPP_NAMESPACE::Buffer instanceData, VULKAN_HPP_NAMESPACE::DeviceSize instanceOffset, VULKAN_HPP_NAMESPACE::Bool32 update, VULKAN_HPP_NAMESPACE::AccelerationStructureNV dst, VULKAN_HPP_NAMESPACE::AccelerationStructureNV src, VULKAN_HPP_NAMESPACE::Buffer scratch, VULKAN_HPP_NAMESPACE::DeviceSize scratchOffset, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+  VULKAN_HPP_INLINE void CommandBuffer::buildAccelerationStructureIndirectKHR( const AccelerationStructureBuildGeometryInfoKHR & info, VULKAN_HPP_NAMESPACE::Buffer indirectBuffer, VULKAN_HPP_NAMESPACE::DeviceSize indirectOffset, uint32_t indirectStride, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkCmdBuildAccelerationStructureNV( m_commandBuffer, reinterpret_cast<const VkAccelerationStructureInfoNV*>( &info ), static_cast<VkBuffer>( instanceData ), static_cast<VkDeviceSize>( instanceOffset ), static_cast<VkBool32>( update ), static_cast<VkAccelerationStructureNV>( dst ), static_cast<VkAccelerationStructureNV>( src ), static_cast<VkBuffer>( scratch ), static_cast<VkDeviceSize>( scratchOffset ) );
+    d.vkCmdBuildAccelerationStructureIndirectKHR( m_commandBuffer, reinterpret_cast<const VkAccelerationStructureBuildGeometryInfoKHR*>( &info ), static_cast<VkBuffer>( indirectBuffer ), static_cast<VkDeviceSize>( indirectOffset ), indirectStride );
+  }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE void CommandBuffer::buildAccelerationStructureKHR( uint32_t infoCount, const VULKAN_HPP_NAMESPACE::AccelerationStructureBuildGeometryInfoKHR* pInfos, const VULKAN_HPP_NAMESPACE::AccelerationStructureBuildOffsetInfoKHR* const* ppOffsetInfos, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  {
+    d.vkCmdBuildAccelerationStructureKHR( m_commandBuffer, infoCount, reinterpret_cast<const VkAccelerationStructureBuildGeometryInfoKHR*>( pInfos ), reinterpret_cast<const VkAccelerationStructureBuildOffsetInfoKHR* const*>( ppOffsetInfos ) );
+  }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE void CommandBuffer::buildAccelerationStructureKHR( ArrayProxy<const VULKAN_HPP_NAMESPACE::AccelerationStructureBuildGeometryInfoKHR> infos, ArrayProxy<const VULKAN_HPP_NAMESPACE::AccelerationStructureBuildOffsetInfoKHR* const> pOffsetInfos, Dispatch const &d ) const
+  {
+#ifdef VULKAN_HPP_NO_EXCEPTIONS
+    VULKAN_HPP_ASSERT( infos.size() == pOffsetInfos.size() );
+#else
+    if ( infos.size() != pOffsetInfos.size() )
+    {
+      throw LogicError( VULKAN_HPP_NAMESPACE_STRING "::VkCommandBuffer::buildAccelerationStructureKHR: infos.size() != pOffsetInfos.size()" );
+    }
+#endif  /*VULKAN_HPP_NO_EXCEPTIONS*/
+    d.vkCmdBuildAccelerationStructureKHR( m_commandBuffer, infos.size() , reinterpret_cast<const VkAccelerationStructureBuildGeometryInfoKHR*>( infos.data() ), reinterpret_cast<const VkAccelerationStructureBuildOffsetInfoKHR* const*>( pOffsetInfos.data() ) );
+  }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE void CommandBuffer::buildAccelerationStructureNV( const VULKAN_HPP_NAMESPACE::AccelerationStructureInfoNV* pInfo, VULKAN_HPP_NAMESPACE::Buffer instanceData, VULKAN_HPP_NAMESPACE::DeviceSize instanceOffset, VULKAN_HPP_NAMESPACE::Bool32 update, VULKAN_HPP_NAMESPACE::AccelerationStructureKHR dst, VULKAN_HPP_NAMESPACE::AccelerationStructureKHR src, VULKAN_HPP_NAMESPACE::Buffer scratch, VULKAN_HPP_NAMESPACE::DeviceSize scratchOffset, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  {
+    d.vkCmdBuildAccelerationStructureNV( m_commandBuffer, reinterpret_cast<const VkAccelerationStructureInfoNV*>( pInfo ), static_cast<VkBuffer>( instanceData ), static_cast<VkDeviceSize>( instanceOffset ), static_cast<VkBool32>( update ), static_cast<VkAccelerationStructureKHR>( dst ), static_cast<VkAccelerationStructureKHR>( src ), static_cast<VkBuffer>( scratch ), static_cast<VkDeviceSize>( scratchOffset ) );
+  }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE void CommandBuffer::buildAccelerationStructureNV( const AccelerationStructureInfoNV & info, VULKAN_HPP_NAMESPACE::Buffer instanceData, VULKAN_HPP_NAMESPACE::DeviceSize instanceOffset, VULKAN_HPP_NAMESPACE::Bool32 update, VULKAN_HPP_NAMESPACE::AccelerationStructureKHR dst, VULKAN_HPP_NAMESPACE::AccelerationStructureKHR src, VULKAN_HPP_NAMESPACE::Buffer scratch, VULKAN_HPP_NAMESPACE::DeviceSize scratchOffset, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+  {
+    d.vkCmdBuildAccelerationStructureNV( m_commandBuffer, reinterpret_cast<const VkAccelerationStructureInfoNV*>( &info ), static_cast<VkBuffer>( instanceData ), static_cast<VkDeviceSize>( instanceOffset ), static_cast<VkBool32>( update ), static_cast<VkAccelerationStructureKHR>( dst ), static_cast<VkAccelerationStructureKHR>( src ), static_cast<VkBuffer>( scratch ), static_cast<VkDeviceSize>( scratchOffset ) );
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
@@ -68517,20 +67232,50 @@
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE void CommandBuffer::copyAccelerationStructureKHR( const VULKAN_HPP_NAMESPACE::CopyAccelerationStructureInfoKHR* pInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  {
+    d.vkCmdCopyAccelerationStructureKHR( m_commandBuffer, reinterpret_cast<const VkCopyAccelerationStructureInfoKHR*>( pInfo ) );
+  }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE void CommandBuffer::copyAccelerationStructureKHR( const CopyAccelerationStructureInfoKHR & info, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+  {
+    d.vkCmdCopyAccelerationStructureKHR( m_commandBuffer, reinterpret_cast<const VkCopyAccelerationStructureInfoKHR*>( &info ) );
+  }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
 #ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
-  VULKAN_HPP_INLINE void CommandBuffer::copyAccelerationStructureNV( VULKAN_HPP_NAMESPACE::AccelerationStructureNV dst, VULKAN_HPP_NAMESPACE::AccelerationStructureNV src, VULKAN_HPP_NAMESPACE::CopyAccelerationStructureModeNV mode, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  VULKAN_HPP_INLINE void CommandBuffer::copyAccelerationStructureNV( VULKAN_HPP_NAMESPACE::AccelerationStructureKHR dst, VULKAN_HPP_NAMESPACE::AccelerationStructureKHR src, VULKAN_HPP_NAMESPACE::CopyAccelerationStructureModeKHR mode, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkCmdCopyAccelerationStructureNV( m_commandBuffer, static_cast<VkAccelerationStructureNV>( dst ), static_cast<VkAccelerationStructureNV>( src ), static_cast<VkCopyAccelerationStructureModeNV>( mode ) );
+    d.vkCmdCopyAccelerationStructureNV( m_commandBuffer, static_cast<VkAccelerationStructureKHR>( dst ), static_cast<VkAccelerationStructureKHR>( src ), static_cast<VkCopyAccelerationStructureModeKHR>( mode ) );
   }
 #else
   template<typename Dispatch>
-  VULKAN_HPP_INLINE void CommandBuffer::copyAccelerationStructureNV( VULKAN_HPP_NAMESPACE::AccelerationStructureNV dst, VULKAN_HPP_NAMESPACE::AccelerationStructureNV src, VULKAN_HPP_NAMESPACE::CopyAccelerationStructureModeNV mode, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+  VULKAN_HPP_INLINE void CommandBuffer::copyAccelerationStructureNV( VULKAN_HPP_NAMESPACE::AccelerationStructureKHR dst, VULKAN_HPP_NAMESPACE::AccelerationStructureKHR src, VULKAN_HPP_NAMESPACE::CopyAccelerationStructureModeKHR mode, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkCmdCopyAccelerationStructureNV( m_commandBuffer, static_cast<VkAccelerationStructureNV>( dst ), static_cast<VkAccelerationStructureNV>( src ), static_cast<VkCopyAccelerationStructureModeNV>( mode ) );
+    d.vkCmdCopyAccelerationStructureNV( m_commandBuffer, static_cast<VkAccelerationStructureKHR>( dst ), static_cast<VkAccelerationStructureKHR>( src ), static_cast<VkCopyAccelerationStructureModeKHR>( mode ) );
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE void CommandBuffer::copyAccelerationStructureToMemoryKHR( const VULKAN_HPP_NAMESPACE::CopyAccelerationStructureToMemoryInfoKHR* pInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  {
+    d.vkCmdCopyAccelerationStructureToMemoryKHR( m_commandBuffer, reinterpret_cast<const VkCopyAccelerationStructureToMemoryInfoKHR*>( pInfo ) );
+  }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE void CommandBuffer::copyAccelerationStructureToMemoryKHR( const CopyAccelerationStructureToMemoryInfoKHR & info, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+  {
+    d.vkCmdCopyAccelerationStructureToMemoryKHR( m_commandBuffer, reinterpret_cast<const VkCopyAccelerationStructureToMemoryInfoKHR*>( &info ) );
+  }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
   template<typename Dispatch>
   VULKAN_HPP_INLINE void CommandBuffer::copyBuffer( VULKAN_HPP_NAMESPACE::Buffer srcBuffer, VULKAN_HPP_NAMESPACE::Buffer dstBuffer, uint32_t regionCount, const VULKAN_HPP_NAMESPACE::BufferCopy* pRegions, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
@@ -68583,6 +67328,21 @@
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE void CommandBuffer::copyMemoryToAccelerationStructureKHR( const VULKAN_HPP_NAMESPACE::CopyMemoryToAccelerationStructureInfoKHR* pInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  {
+    d.vkCmdCopyMemoryToAccelerationStructureKHR( m_commandBuffer, reinterpret_cast<const VkCopyMemoryToAccelerationStructureInfoKHR*>( pInfo ) );
+  }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE void CommandBuffer::copyMemoryToAccelerationStructureKHR( const CopyMemoryToAccelerationStructureInfoKHR & info, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+  {
+    d.vkCmdCopyMemoryToAccelerationStructureKHR( m_commandBuffer, reinterpret_cast<const VkCopyMemoryToAccelerationStructureInfoKHR*>( &info ) );
+  }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
 #ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
   VULKAN_HPP_INLINE void CommandBuffer::copyQueryPoolResults( VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, VULKAN_HPP_NAMESPACE::Buffer dstBuffer, VULKAN_HPP_NAMESPACE::DeviceSize dstOffset, VULKAN_HPP_NAMESPACE::DeviceSize stride, VULKAN_HPP_NAMESPACE::QueryResultFlags flags, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
@@ -68669,13 +67429,13 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE void CommandBuffer::dispatchBaseKHR( uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkCmdDispatchBase( m_commandBuffer, baseGroupX, baseGroupY, baseGroupZ, groupCountX, groupCountY, groupCountZ );
+    d.vkCmdDispatchBaseKHR( m_commandBuffer, baseGroupX, baseGroupY, baseGroupZ, groupCountX, groupCountY, groupCountZ );
   }
 #else
   template<typename Dispatch>
   VULKAN_HPP_INLINE void CommandBuffer::dispatchBaseKHR( uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkCmdDispatchBase( m_commandBuffer, baseGroupX, baseGroupY, baseGroupZ, groupCountX, groupCountY, groupCountZ );
+    d.vkCmdDispatchBaseKHR( m_commandBuffer, baseGroupX, baseGroupY, baseGroupZ, groupCountX, groupCountY, groupCountZ );
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
@@ -68753,13 +67513,13 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE void CommandBuffer::drawIndexedIndirectCountAMD( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, VULKAN_HPP_NAMESPACE::Buffer countBuffer, VULKAN_HPP_NAMESPACE::DeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkCmdDrawIndexedIndirectCount( m_commandBuffer, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ), static_cast<VkBuffer>( countBuffer ), static_cast<VkDeviceSize>( countBufferOffset ), maxDrawCount, stride );
+    d.vkCmdDrawIndexedIndirectCountAMD( m_commandBuffer, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ), static_cast<VkBuffer>( countBuffer ), static_cast<VkDeviceSize>( countBufferOffset ), maxDrawCount, stride );
   }
 #else
   template<typename Dispatch>
   VULKAN_HPP_INLINE void CommandBuffer::drawIndexedIndirectCountAMD( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, VULKAN_HPP_NAMESPACE::Buffer countBuffer, VULKAN_HPP_NAMESPACE::DeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkCmdDrawIndexedIndirectCount( m_commandBuffer, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ), static_cast<VkBuffer>( countBuffer ), static_cast<VkDeviceSize>( countBufferOffset ), maxDrawCount, stride );
+    d.vkCmdDrawIndexedIndirectCountAMD( m_commandBuffer, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ), static_cast<VkBuffer>( countBuffer ), static_cast<VkDeviceSize>( countBufferOffset ), maxDrawCount, stride );
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
@@ -68767,13 +67527,13 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE void CommandBuffer::drawIndexedIndirectCountKHR( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, VULKAN_HPP_NAMESPACE::Buffer countBuffer, VULKAN_HPP_NAMESPACE::DeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkCmdDrawIndexedIndirectCount( m_commandBuffer, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ), static_cast<VkBuffer>( countBuffer ), static_cast<VkDeviceSize>( countBufferOffset ), maxDrawCount, stride );
+    d.vkCmdDrawIndexedIndirectCountKHR( m_commandBuffer, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ), static_cast<VkBuffer>( countBuffer ), static_cast<VkDeviceSize>( countBufferOffset ), maxDrawCount, stride );
   }
 #else
   template<typename Dispatch>
   VULKAN_HPP_INLINE void CommandBuffer::drawIndexedIndirectCountKHR( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, VULKAN_HPP_NAMESPACE::Buffer countBuffer, VULKAN_HPP_NAMESPACE::DeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkCmdDrawIndexedIndirectCount( m_commandBuffer, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ), static_cast<VkBuffer>( countBuffer ), static_cast<VkDeviceSize>( countBufferOffset ), maxDrawCount, stride );
+    d.vkCmdDrawIndexedIndirectCountKHR( m_commandBuffer, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ), static_cast<VkBuffer>( countBuffer ), static_cast<VkDeviceSize>( countBufferOffset ), maxDrawCount, stride );
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
@@ -68823,13 +67583,13 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE void CommandBuffer::drawIndirectCountAMD( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, VULKAN_HPP_NAMESPACE::Buffer countBuffer, VULKAN_HPP_NAMESPACE::DeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkCmdDrawIndirectCount( m_commandBuffer, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ), static_cast<VkBuffer>( countBuffer ), static_cast<VkDeviceSize>( countBufferOffset ), maxDrawCount, stride );
+    d.vkCmdDrawIndirectCountAMD( m_commandBuffer, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ), static_cast<VkBuffer>( countBuffer ), static_cast<VkDeviceSize>( countBufferOffset ), maxDrawCount, stride );
   }
 #else
   template<typename Dispatch>
   VULKAN_HPP_INLINE void CommandBuffer::drawIndirectCountAMD( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, VULKAN_HPP_NAMESPACE::Buffer countBuffer, VULKAN_HPP_NAMESPACE::DeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkCmdDrawIndirectCount( m_commandBuffer, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ), static_cast<VkBuffer>( countBuffer ), static_cast<VkDeviceSize>( countBufferOffset ), maxDrawCount, stride );
+    d.vkCmdDrawIndirectCountAMD( m_commandBuffer, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ), static_cast<VkBuffer>( countBuffer ), static_cast<VkDeviceSize>( countBufferOffset ), maxDrawCount, stride );
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
@@ -68837,13 +67597,13 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE void CommandBuffer::drawIndirectCountKHR( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, VULKAN_HPP_NAMESPACE::Buffer countBuffer, VULKAN_HPP_NAMESPACE::DeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkCmdDrawIndirectCount( m_commandBuffer, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ), static_cast<VkBuffer>( countBuffer ), static_cast<VkDeviceSize>( countBufferOffset ), maxDrawCount, stride );
+    d.vkCmdDrawIndirectCountKHR( m_commandBuffer, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ), static_cast<VkBuffer>( countBuffer ), static_cast<VkDeviceSize>( countBufferOffset ), maxDrawCount, stride );
   }
 #else
   template<typename Dispatch>
   VULKAN_HPP_INLINE void CommandBuffer::drawIndirectCountKHR( VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, VULKAN_HPP_NAMESPACE::Buffer countBuffer, VULKAN_HPP_NAMESPACE::DeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkCmdDrawIndirectCount( m_commandBuffer, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ), static_cast<VkBuffer>( countBuffer ), static_cast<VkDeviceSize>( countBufferOffset ), maxDrawCount, stride );
+    d.vkCmdDrawIndirectCountKHR( m_commandBuffer, static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ), static_cast<VkBuffer>( countBuffer ), static_cast<VkDeviceSize>( countBufferOffset ), maxDrawCount, stride );
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
@@ -68975,13 +67735,13 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE void CommandBuffer::endRenderPass2KHR( const VULKAN_HPP_NAMESPACE::SubpassEndInfo* pSubpassEndInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkCmdEndRenderPass2( m_commandBuffer, reinterpret_cast<const VkSubpassEndInfo*>( pSubpassEndInfo ) );
+    d.vkCmdEndRenderPass2KHR( m_commandBuffer, reinterpret_cast<const VkSubpassEndInfo*>( pSubpassEndInfo ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
   VULKAN_HPP_INLINE void CommandBuffer::endRenderPass2KHR( const SubpassEndInfo & subpassEndInfo, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkCmdEndRenderPass2( m_commandBuffer, reinterpret_cast<const VkSubpassEndInfo*>( &subpassEndInfo ) );
+    d.vkCmdEndRenderPass2KHR( m_commandBuffer, reinterpret_cast<const VkSubpassEndInfo*>( &subpassEndInfo ) );
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
@@ -69019,6 +67779,19 @@
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE void CommandBuffer::executeGeneratedCommandsNV( VULKAN_HPP_NAMESPACE::Bool32 isPreprocessed, const VULKAN_HPP_NAMESPACE::GeneratedCommandsInfoNV* pGeneratedCommandsInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  {
+    d.vkCmdExecuteGeneratedCommandsNV( m_commandBuffer, static_cast<VkBool32>( isPreprocessed ), reinterpret_cast<const VkGeneratedCommandsInfoNV*>( pGeneratedCommandsInfo ) );
+  }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE void CommandBuffer::executeGeneratedCommandsNV( VULKAN_HPP_NAMESPACE::Bool32 isPreprocessed, const GeneratedCommandsInfoNV & generatedCommandsInfo, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+  {
+    d.vkCmdExecuteGeneratedCommandsNV( m_commandBuffer, static_cast<VkBool32>( isPreprocessed ), reinterpret_cast<const VkGeneratedCommandsInfoNV*>( &generatedCommandsInfo ) );
+  }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
 #ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
   VULKAN_HPP_INLINE void CommandBuffer::fillBuffer( VULKAN_HPP_NAMESPACE::Buffer dstBuffer, VULKAN_HPP_NAMESPACE::DeviceSize dstOffset, VULKAN_HPP_NAMESPACE::DeviceSize size, uint32_t data, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
@@ -69076,13 +67849,13 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE void CommandBuffer::nextSubpass2KHR( const VULKAN_HPP_NAMESPACE::SubpassBeginInfo* pSubpassBeginInfo, const VULKAN_HPP_NAMESPACE::SubpassEndInfo* pSubpassEndInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkCmdNextSubpass2( m_commandBuffer, reinterpret_cast<const VkSubpassBeginInfo*>( pSubpassBeginInfo ), reinterpret_cast<const VkSubpassEndInfo*>( pSubpassEndInfo ) );
+    d.vkCmdNextSubpass2KHR( m_commandBuffer, reinterpret_cast<const VkSubpassBeginInfo*>( pSubpassBeginInfo ), reinterpret_cast<const VkSubpassEndInfo*>( pSubpassEndInfo ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
   VULKAN_HPP_INLINE void CommandBuffer::nextSubpass2KHR( const SubpassBeginInfo & subpassBeginInfo, const SubpassEndInfo & subpassEndInfo, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkCmdNextSubpass2( m_commandBuffer, reinterpret_cast<const VkSubpassBeginInfo*>( &subpassBeginInfo ), reinterpret_cast<const VkSubpassEndInfo*>( &subpassEndInfo ) );
+    d.vkCmdNextSubpass2KHR( m_commandBuffer, reinterpret_cast<const VkSubpassBeginInfo*>( &subpassBeginInfo ), reinterpret_cast<const VkSubpassEndInfo*>( &subpassEndInfo ) );
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
@@ -69100,15 +67873,15 @@
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
   template<typename Dispatch>
-  VULKAN_HPP_INLINE void CommandBuffer::processCommandsNVX( const VULKAN_HPP_NAMESPACE::CmdProcessCommandsInfoNVX* pProcessCommandsInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  VULKAN_HPP_INLINE void CommandBuffer::preprocessGeneratedCommandsNV( const VULKAN_HPP_NAMESPACE::GeneratedCommandsInfoNV* pGeneratedCommandsInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkCmdProcessCommandsNVX( m_commandBuffer, reinterpret_cast<const VkCmdProcessCommandsInfoNVX*>( pProcessCommandsInfo ) );
+    d.vkCmdPreprocessGeneratedCommandsNV( m_commandBuffer, reinterpret_cast<const VkGeneratedCommandsInfoNV*>( pGeneratedCommandsInfo ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
-  VULKAN_HPP_INLINE void CommandBuffer::processCommandsNVX( const CmdProcessCommandsInfoNVX & processCommandsInfo, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+  VULKAN_HPP_INLINE void CommandBuffer::preprocessGeneratedCommandsNV( const GeneratedCommandsInfoNV & generatedCommandsInfo, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkCmdProcessCommandsNVX( m_commandBuffer, reinterpret_cast<const VkCmdProcessCommandsInfoNVX*>( &processCommandsInfo ) );
+    d.vkCmdPreprocessGeneratedCommandsNV( m_commandBuffer, reinterpret_cast<const VkGeneratedCommandsInfoNV*>( &generatedCommandsInfo ) );
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
@@ -69152,19 +67925,6 @@
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
-  template<typename Dispatch>
-  VULKAN_HPP_INLINE void CommandBuffer::reserveSpaceForCommandsNVX( const VULKAN_HPP_NAMESPACE::CmdReserveSpaceForCommandsInfoNVX* pReserveSpaceInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
-  {
-    d.vkCmdReserveSpaceForCommandsNVX( m_commandBuffer, reinterpret_cast<const VkCmdReserveSpaceForCommandsInfoNVX*>( pReserveSpaceInfo ) );
-  }
-#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
-  template<typename Dispatch>
-  VULKAN_HPP_INLINE void CommandBuffer::reserveSpaceForCommandsNVX( const CmdReserveSpaceForCommandsInfoNVX & reserveSpaceInfo, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
-  {
-    d.vkCmdReserveSpaceForCommandsNVX( m_commandBuffer, reinterpret_cast<const VkCmdReserveSpaceForCommandsInfoNVX*>( &reserveSpaceInfo ) );
-  }
-#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
-
 #ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
   VULKAN_HPP_INLINE void CommandBuffer::resetEvent( VULKAN_HPP_NAMESPACE::Event event, VULKAN_HPP_NAMESPACE::PipelineStageFlags stageMask, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
@@ -69293,13 +68053,13 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE void CommandBuffer::setDeviceMaskKHR( uint32_t deviceMask, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkCmdSetDeviceMask( m_commandBuffer, deviceMask );
+    d.vkCmdSetDeviceMaskKHR( m_commandBuffer, deviceMask );
   }
 #else
   template<typename Dispatch>
   VULKAN_HPP_INLINE void CommandBuffer::setDeviceMaskKHR( uint32_t deviceMask, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkCmdSetDeviceMask( m_commandBuffer, deviceMask );
+    d.vkCmdSetDeviceMaskKHR( m_commandBuffer, deviceMask );
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
@@ -69520,6 +68280,36 @@
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE void CommandBuffer::traceRaysIndirectKHR( const VULKAN_HPP_NAMESPACE::StridedBufferRegionKHR* pRaygenShaderBindingTable, const VULKAN_HPP_NAMESPACE::StridedBufferRegionKHR* pMissShaderBindingTable, const VULKAN_HPP_NAMESPACE::StridedBufferRegionKHR* pHitShaderBindingTable, const VULKAN_HPP_NAMESPACE::StridedBufferRegionKHR* pCallableShaderBindingTable, VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  {
+    d.vkCmdTraceRaysIndirectKHR( m_commandBuffer, reinterpret_cast<const VkStridedBufferRegionKHR*>( pRaygenShaderBindingTable ), reinterpret_cast<const VkStridedBufferRegionKHR*>( pMissShaderBindingTable ), reinterpret_cast<const VkStridedBufferRegionKHR*>( pHitShaderBindingTable ), reinterpret_cast<const VkStridedBufferRegionKHR*>( pCallableShaderBindingTable ), static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ) );
+  }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE void CommandBuffer::traceRaysIndirectKHR( const StridedBufferRegionKHR & raygenShaderBindingTable, const StridedBufferRegionKHR & missShaderBindingTable, const StridedBufferRegionKHR & hitShaderBindingTable, const StridedBufferRegionKHR & callableShaderBindingTable, VULKAN_HPP_NAMESPACE::Buffer buffer, VULKAN_HPP_NAMESPACE::DeviceSize offset, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+  {
+    d.vkCmdTraceRaysIndirectKHR( m_commandBuffer, reinterpret_cast<const VkStridedBufferRegionKHR*>( &raygenShaderBindingTable ), reinterpret_cast<const VkStridedBufferRegionKHR*>( &missShaderBindingTable ), reinterpret_cast<const VkStridedBufferRegionKHR*>( &hitShaderBindingTable ), reinterpret_cast<const VkStridedBufferRegionKHR*>( &callableShaderBindingTable ), static_cast<VkBuffer>( buffer ), static_cast<VkDeviceSize>( offset ) );
+  }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE void CommandBuffer::traceRaysKHR( const VULKAN_HPP_NAMESPACE::StridedBufferRegionKHR* pRaygenShaderBindingTable, const VULKAN_HPP_NAMESPACE::StridedBufferRegionKHR* pMissShaderBindingTable, const VULKAN_HPP_NAMESPACE::StridedBufferRegionKHR* pHitShaderBindingTable, const VULKAN_HPP_NAMESPACE::StridedBufferRegionKHR* pCallableShaderBindingTable, uint32_t width, uint32_t height, uint32_t depth, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  {
+    d.vkCmdTraceRaysKHR( m_commandBuffer, reinterpret_cast<const VkStridedBufferRegionKHR*>( pRaygenShaderBindingTable ), reinterpret_cast<const VkStridedBufferRegionKHR*>( pMissShaderBindingTable ), reinterpret_cast<const VkStridedBufferRegionKHR*>( pHitShaderBindingTable ), reinterpret_cast<const VkStridedBufferRegionKHR*>( pCallableShaderBindingTable ), width, height, depth );
+  }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE void CommandBuffer::traceRaysKHR( const StridedBufferRegionKHR & raygenShaderBindingTable, const StridedBufferRegionKHR & missShaderBindingTable, const StridedBufferRegionKHR & hitShaderBindingTable, const StridedBufferRegionKHR & callableShaderBindingTable, uint32_t width, uint32_t height, uint32_t depth, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+  {
+    d.vkCmdTraceRaysKHR( m_commandBuffer, reinterpret_cast<const VkStridedBufferRegionKHR*>( &raygenShaderBindingTable ), reinterpret_cast<const VkStridedBufferRegionKHR*>( &missShaderBindingTable ), reinterpret_cast<const VkStridedBufferRegionKHR*>( &hitShaderBindingTable ), reinterpret_cast<const VkStridedBufferRegionKHR*>( &callableShaderBindingTable ), width, height, depth );
+  }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
 #ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
   VULKAN_HPP_INLINE void CommandBuffer::traceRaysNV( VULKAN_HPP_NAMESPACE::Buffer raygenShaderBindingTableBuffer, VULKAN_HPP_NAMESPACE::DeviceSize raygenShaderBindingOffset, VULKAN_HPP_NAMESPACE::Buffer missShaderBindingTableBuffer, VULKAN_HPP_NAMESPACE::DeviceSize missShaderBindingOffset, VULKAN_HPP_NAMESPACE::DeviceSize missShaderBindingStride, VULKAN_HPP_NAMESPACE::Buffer hitShaderBindingTableBuffer, VULKAN_HPP_NAMESPACE::DeviceSize hitShaderBindingOffset, VULKAN_HPP_NAMESPACE::DeviceSize hitShaderBindingStride, VULKAN_HPP_NAMESPACE::Buffer callableShaderBindingTableBuffer, VULKAN_HPP_NAMESPACE::DeviceSize callableShaderBindingOffset, VULKAN_HPP_NAMESPACE::DeviceSize callableShaderBindingStride, uint32_t width, uint32_t height, uint32_t depth, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
@@ -69561,15 +68351,28 @@
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
   template<typename Dispatch>
-  VULKAN_HPP_INLINE void CommandBuffer::writeAccelerationStructuresPropertiesNV( uint32_t accelerationStructureCount, const VULKAN_HPP_NAMESPACE::AccelerationStructureNV* pAccelerationStructures, VULKAN_HPP_NAMESPACE::QueryType queryType, VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t firstQuery, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  VULKAN_HPP_INLINE void CommandBuffer::writeAccelerationStructuresPropertiesKHR( uint32_t accelerationStructureCount, const VULKAN_HPP_NAMESPACE::AccelerationStructureKHR* pAccelerationStructures, VULKAN_HPP_NAMESPACE::QueryType queryType, VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t firstQuery, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkCmdWriteAccelerationStructuresPropertiesNV( m_commandBuffer, accelerationStructureCount, reinterpret_cast<const VkAccelerationStructureNV*>( pAccelerationStructures ), static_cast<VkQueryType>( queryType ), static_cast<VkQueryPool>( queryPool ), firstQuery );
+    d.vkCmdWriteAccelerationStructuresPropertiesKHR( m_commandBuffer, accelerationStructureCount, reinterpret_cast<const VkAccelerationStructureKHR*>( pAccelerationStructures ), static_cast<VkQueryType>( queryType ), static_cast<VkQueryPool>( queryPool ), firstQuery );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
-  VULKAN_HPP_INLINE void CommandBuffer::writeAccelerationStructuresPropertiesNV( ArrayProxy<const VULKAN_HPP_NAMESPACE::AccelerationStructureNV> accelerationStructures, VULKAN_HPP_NAMESPACE::QueryType queryType, VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t firstQuery, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+  VULKAN_HPP_INLINE void CommandBuffer::writeAccelerationStructuresPropertiesKHR( ArrayProxy<const VULKAN_HPP_NAMESPACE::AccelerationStructureKHR> accelerationStructures, VULKAN_HPP_NAMESPACE::QueryType queryType, VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t firstQuery, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkCmdWriteAccelerationStructuresPropertiesNV( m_commandBuffer, accelerationStructures.size() , reinterpret_cast<const VkAccelerationStructureNV*>( accelerationStructures.data() ), static_cast<VkQueryType>( queryType ), static_cast<VkQueryPool>( queryPool ), firstQuery );
+    d.vkCmdWriteAccelerationStructuresPropertiesKHR( m_commandBuffer, accelerationStructures.size() , reinterpret_cast<const VkAccelerationStructureKHR*>( accelerationStructures.data() ), static_cast<VkQueryType>( queryType ), static_cast<VkQueryPool>( queryPool ), firstQuery );
+  }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE void CommandBuffer::writeAccelerationStructuresPropertiesNV( uint32_t accelerationStructureCount, const VULKAN_HPP_NAMESPACE::AccelerationStructureKHR* pAccelerationStructures, VULKAN_HPP_NAMESPACE::QueryType queryType, VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t firstQuery, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  {
+    d.vkCmdWriteAccelerationStructuresPropertiesNV( m_commandBuffer, accelerationStructureCount, reinterpret_cast<const VkAccelerationStructureKHR*>( pAccelerationStructures ), static_cast<VkQueryType>( queryType ), static_cast<VkQueryPool>( queryPool ), firstQuery );
+  }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE void CommandBuffer::writeAccelerationStructuresPropertiesNV( ArrayProxy<const VULKAN_HPP_NAMESPACE::AccelerationStructureKHR> accelerationStructures, VULKAN_HPP_NAMESPACE::QueryType queryType, VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t firstQuery, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+  {
+    d.vkCmdWriteAccelerationStructuresPropertiesNV( m_commandBuffer, accelerationStructures.size() , reinterpret_cast<const VkAccelerationStructureKHR*>( accelerationStructures.data() ), static_cast<VkQueryType>( queryType ), static_cast<VkQueryPool>( queryPool ), firstQuery );
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
@@ -69731,40 +68534,38 @@
   template<typename Allocator, typename Dispatch>
   VULKAN_HPP_INLINE typename ResultValueType<std::vector<UniqueHandle<CommandBuffer,Dispatch>,Allocator>>::type Device::allocateCommandBuffersUnique( const CommandBufferAllocateInfo & allocateInfo, Dispatch const &d ) const
   {
-    static_assert( sizeof( CommandBuffer ) <= sizeof( UniqueHandle<CommandBuffer, Dispatch> ), "CommandBuffer is greater than UniqueHandle<CommandBuffer, Dispatch>!" );
-    std::vector<UniqueHandle<CommandBuffer, Dispatch>, Allocator> commandBuffers;
-    commandBuffers.reserve( allocateInfo.commandBufferCount );
-    CommandBuffer* buffer = reinterpret_cast<CommandBuffer*>( reinterpret_cast<char*>( commandBuffers.data() ) + allocateInfo.commandBufferCount * ( sizeof( UniqueHandle<CommandBuffer, Dispatch> ) - sizeof( CommandBuffer ) ) );
-    Result result = static_cast<Result>(d.vkAllocateCommandBuffers( m_device, reinterpret_cast<const VkCommandBufferAllocateInfo*>( &allocateInfo ), reinterpret_cast<VkCommandBuffer*>( buffer ) ) );
+    std::vector<UniqueHandle<CommandBuffer, Dispatch>, Allocator> uniqueCommandBuffers;
+    std::vector<CommandBuffer> commandBuffers( allocateInfo.commandBufferCount );
+    Result result = static_cast<Result>( d.vkAllocateCommandBuffers( m_device, reinterpret_cast<const VkCommandBufferAllocateInfo*>( &allocateInfo ), reinterpret_cast<VkCommandBuffer*>(commandBuffers.data()) ) );
     if ( result == VULKAN_HPP_NAMESPACE::Result::eSuccess )
     {
+      uniqueCommandBuffers.reserve( allocateInfo.commandBufferCount );
       PoolFree<Device,CommandPool,Dispatch> deleter( *this, allocateInfo.commandPool, d );
       for ( size_t i=0 ; i<allocateInfo.commandBufferCount ; i++ )
       {
-        commandBuffers.push_back( UniqueHandle<CommandBuffer, Dispatch>( buffer[i], deleter ) );
+        uniqueCommandBuffers.push_back( UniqueHandle<CommandBuffer, Dispatch>( commandBuffers[i], deleter ) );
       }
     }
 
-    return createResultValue( result, commandBuffers, VULKAN_HPP_NAMESPACE_STRING "::Device::allocateCommandBuffersUnique" );
+    return createResultValue( result, uniqueCommandBuffers, VULKAN_HPP_NAMESPACE_STRING "::Device::allocateCommandBuffersUnique" );
   }
   template<typename Allocator, typename Dispatch>
   VULKAN_HPP_INLINE typename ResultValueType<std::vector<UniqueHandle<CommandBuffer,Dispatch>,Allocator>>::type Device::allocateCommandBuffersUnique( const CommandBufferAllocateInfo & allocateInfo, Allocator const& vectorAllocator, Dispatch const &d ) const
   {
-    static_assert( sizeof( CommandBuffer ) <= sizeof( UniqueHandle<CommandBuffer, Dispatch> ), "CommandBuffer is greater than UniqueHandle<CommandBuffer, Dispatch>!" );
-    std::vector<UniqueHandle<CommandBuffer, Dispatch>, Allocator> commandBuffers( vectorAllocator );
-    commandBuffers.reserve( allocateInfo.commandBufferCount );
-    CommandBuffer* buffer = reinterpret_cast<CommandBuffer*>( reinterpret_cast<char*>( commandBuffers.data() ) + allocateInfo.commandBufferCount * ( sizeof( UniqueHandle<CommandBuffer, Dispatch> ) - sizeof( CommandBuffer ) ) );
-    Result result = static_cast<Result>(d.vkAllocateCommandBuffers( m_device, reinterpret_cast<const VkCommandBufferAllocateInfo*>( &allocateInfo ), reinterpret_cast<VkCommandBuffer*>( buffer ) ) );
+    std::vector<UniqueHandle<CommandBuffer, Dispatch>, Allocator> uniqueCommandBuffers( vectorAllocator );
+    std::vector<CommandBuffer> commandBuffers( allocateInfo.commandBufferCount );
+    Result result = static_cast<Result>( d.vkAllocateCommandBuffers( m_device, reinterpret_cast<const VkCommandBufferAllocateInfo*>( &allocateInfo ), reinterpret_cast<VkCommandBuffer*>(commandBuffers.data()) ) );
     if ( result == VULKAN_HPP_NAMESPACE::Result::eSuccess )
     {
+      uniqueCommandBuffers.reserve( allocateInfo.commandBufferCount );
       PoolFree<Device,CommandPool,Dispatch> deleter( *this, allocateInfo.commandPool, d );
       for ( size_t i=0 ; i<allocateInfo.commandBufferCount ; i++ )
       {
-        commandBuffers.push_back( UniqueHandle<CommandBuffer, Dispatch>( buffer[i], deleter ) );
+        uniqueCommandBuffers.push_back( UniqueHandle<CommandBuffer, Dispatch>( commandBuffers[i], deleter ) );
       }
     }
 
-    return createResultValue( result, commandBuffers, VULKAN_HPP_NAMESPACE_STRING "::Device::allocateCommandBuffersUnique" );
+    return createResultValue( result, uniqueCommandBuffers, VULKAN_HPP_NAMESPACE_STRING "::Device::allocateCommandBuffersUnique" );
   }
 #endif /*VULKAN_HPP_NO_SMART_HANDLE*/
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
@@ -69793,40 +68594,38 @@
   template<typename Allocator, typename Dispatch>
   VULKAN_HPP_INLINE typename ResultValueType<std::vector<UniqueHandle<DescriptorSet,Dispatch>,Allocator>>::type Device::allocateDescriptorSetsUnique( const DescriptorSetAllocateInfo & allocateInfo, Dispatch const &d ) const
   {
-    static_assert( sizeof( DescriptorSet ) <= sizeof( UniqueHandle<DescriptorSet, Dispatch> ), "DescriptorSet is greater than UniqueHandle<DescriptorSet, Dispatch>!" );
-    std::vector<UniqueHandle<DescriptorSet, Dispatch>, Allocator> descriptorSets;
-    descriptorSets.reserve( allocateInfo.descriptorSetCount );
-    DescriptorSet* buffer = reinterpret_cast<DescriptorSet*>( reinterpret_cast<char*>( descriptorSets.data() ) + allocateInfo.descriptorSetCount * ( sizeof( UniqueHandle<DescriptorSet, Dispatch> ) - sizeof( DescriptorSet ) ) );
-    Result result = static_cast<Result>(d.vkAllocateDescriptorSets( m_device, reinterpret_cast<const VkDescriptorSetAllocateInfo*>( &allocateInfo ), reinterpret_cast<VkDescriptorSet*>( buffer ) ) );
+    std::vector<UniqueHandle<DescriptorSet, Dispatch>, Allocator> uniqueDescriptorSets;
+    std::vector<DescriptorSet> descriptorSets( allocateInfo.descriptorSetCount );
+    Result result = static_cast<Result>( d.vkAllocateDescriptorSets( m_device, reinterpret_cast<const VkDescriptorSetAllocateInfo*>( &allocateInfo ), reinterpret_cast<VkDescriptorSet*>(descriptorSets.data()) ) );
     if ( result == VULKAN_HPP_NAMESPACE::Result::eSuccess )
     {
+      uniqueDescriptorSets.reserve( allocateInfo.descriptorSetCount );
       PoolFree<Device,DescriptorPool,Dispatch> deleter( *this, allocateInfo.descriptorPool, d );
       for ( size_t i=0 ; i<allocateInfo.descriptorSetCount ; i++ )
       {
-        descriptorSets.push_back( UniqueHandle<DescriptorSet, Dispatch>( buffer[i], deleter ) );
+        uniqueDescriptorSets.push_back( UniqueHandle<DescriptorSet, Dispatch>( descriptorSets[i], deleter ) );
       }
     }
 
-    return createResultValue( result, descriptorSets, VULKAN_HPP_NAMESPACE_STRING "::Device::allocateDescriptorSetsUnique" );
+    return createResultValue( result, uniqueDescriptorSets, VULKAN_HPP_NAMESPACE_STRING "::Device::allocateDescriptorSetsUnique" );
   }
   template<typename Allocator, typename Dispatch>
   VULKAN_HPP_INLINE typename ResultValueType<std::vector<UniqueHandle<DescriptorSet,Dispatch>,Allocator>>::type Device::allocateDescriptorSetsUnique( const DescriptorSetAllocateInfo & allocateInfo, Allocator const& vectorAllocator, Dispatch const &d ) const
   {
-    static_assert( sizeof( DescriptorSet ) <= sizeof( UniqueHandle<DescriptorSet, Dispatch> ), "DescriptorSet is greater than UniqueHandle<DescriptorSet, Dispatch>!" );
-    std::vector<UniqueHandle<DescriptorSet, Dispatch>, Allocator> descriptorSets( vectorAllocator );
-    descriptorSets.reserve( allocateInfo.descriptorSetCount );
-    DescriptorSet* buffer = reinterpret_cast<DescriptorSet*>( reinterpret_cast<char*>( descriptorSets.data() ) + allocateInfo.descriptorSetCount * ( sizeof( UniqueHandle<DescriptorSet, Dispatch> ) - sizeof( DescriptorSet ) ) );
-    Result result = static_cast<Result>(d.vkAllocateDescriptorSets( m_device, reinterpret_cast<const VkDescriptorSetAllocateInfo*>( &allocateInfo ), reinterpret_cast<VkDescriptorSet*>( buffer ) ) );
+    std::vector<UniqueHandle<DescriptorSet, Dispatch>, Allocator> uniqueDescriptorSets( vectorAllocator );
+    std::vector<DescriptorSet> descriptorSets( allocateInfo.descriptorSetCount );
+    Result result = static_cast<Result>( d.vkAllocateDescriptorSets( m_device, reinterpret_cast<const VkDescriptorSetAllocateInfo*>( &allocateInfo ), reinterpret_cast<VkDescriptorSet*>(descriptorSets.data()) ) );
     if ( result == VULKAN_HPP_NAMESPACE::Result::eSuccess )
     {
+      uniqueDescriptorSets.reserve( allocateInfo.descriptorSetCount );
       PoolFree<Device,DescriptorPool,Dispatch> deleter( *this, allocateInfo.descriptorPool, d );
       for ( size_t i=0 ; i<allocateInfo.descriptorSetCount ; i++ )
       {
-        descriptorSets.push_back( UniqueHandle<DescriptorSet, Dispatch>( buffer[i], deleter ) );
+        uniqueDescriptorSets.push_back( UniqueHandle<DescriptorSet, Dispatch>( descriptorSets[i], deleter ) );
       }
     }
 
-    return createResultValue( result, descriptorSets, VULKAN_HPP_NAMESPACE_STRING "::Device::allocateDescriptorSetsUnique" );
+    return createResultValue( result, uniqueDescriptorSets, VULKAN_HPP_NAMESPACE_STRING "::Device::allocateDescriptorSetsUnique" );
   }
 #endif /*VULKAN_HPP_NO_SMART_HANDLE*/
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
@@ -69858,15 +68657,29 @@
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
   template<typename Dispatch>
-  VULKAN_HPP_INLINE Result Device::bindAccelerationStructureMemoryNV( uint32_t bindInfoCount, const VULKAN_HPP_NAMESPACE::BindAccelerationStructureMemoryInfoNV* pBindInfos, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  VULKAN_HPP_INLINE Result Device::bindAccelerationStructureMemoryKHR( uint32_t bindInfoCount, const VULKAN_HPP_NAMESPACE::BindAccelerationStructureMemoryInfoKHR* pBindInfos, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    return static_cast<Result>( d.vkBindAccelerationStructureMemoryNV( m_device, bindInfoCount, reinterpret_cast<const VkBindAccelerationStructureMemoryInfoNV*>( pBindInfos ) ) );
+    return static_cast<Result>( d.vkBindAccelerationStructureMemoryKHR( m_device, bindInfoCount, reinterpret_cast<const VkBindAccelerationStructureMemoryInfoKHR*>( pBindInfos ) ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
-  VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::bindAccelerationStructureMemoryNV( ArrayProxy<const VULKAN_HPP_NAMESPACE::BindAccelerationStructureMemoryInfoNV> bindInfos, Dispatch const &d ) const
+  VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::bindAccelerationStructureMemoryKHR( ArrayProxy<const VULKAN_HPP_NAMESPACE::BindAccelerationStructureMemoryInfoKHR> bindInfos, Dispatch const &d ) const
   {
-    Result result = static_cast<Result>( d.vkBindAccelerationStructureMemoryNV( m_device, bindInfos.size() , reinterpret_cast<const VkBindAccelerationStructureMemoryInfoNV*>( bindInfos.data() ) ) );
+    Result result = static_cast<Result>( d.vkBindAccelerationStructureMemoryKHR( m_device, bindInfos.size() , reinterpret_cast<const VkBindAccelerationStructureMemoryInfoKHR*>( bindInfos.data() ) ) );
+    return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::bindAccelerationStructureMemoryKHR" );
+  }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE Result Device::bindAccelerationStructureMemoryNV( uint32_t bindInfoCount, const VULKAN_HPP_NAMESPACE::BindAccelerationStructureMemoryInfoKHR* pBindInfos, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  {
+    return static_cast<Result>( d.vkBindAccelerationStructureMemoryNV( m_device, bindInfoCount, reinterpret_cast<const VkBindAccelerationStructureMemoryInfoKHR*>( pBindInfos ) ) );
+  }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::bindAccelerationStructureMemoryNV( ArrayProxy<const VULKAN_HPP_NAMESPACE::BindAccelerationStructureMemoryInfoKHR> bindInfos, Dispatch const &d ) const
+  {
+    Result result = static_cast<Result>( d.vkBindAccelerationStructureMemoryNV( m_device, bindInfos.size() , reinterpret_cast<const VkBindAccelerationStructureMemoryInfoKHR*>( bindInfos.data() ) ) );
     return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::bindAccelerationStructureMemoryNV" );
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
@@ -69903,13 +68716,13 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE Result Device::bindBufferMemory2KHR( uint32_t bindInfoCount, const VULKAN_HPP_NAMESPACE::BindBufferMemoryInfo* pBindInfos, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    return static_cast<Result>( d.vkBindBufferMemory2( m_device, bindInfoCount, reinterpret_cast<const VkBindBufferMemoryInfo*>( pBindInfos ) ) );
+    return static_cast<Result>( d.vkBindBufferMemory2KHR( m_device, bindInfoCount, reinterpret_cast<const VkBindBufferMemoryInfo*>( pBindInfos ) ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
   VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::bindBufferMemory2KHR( ArrayProxy<const VULKAN_HPP_NAMESPACE::BindBufferMemoryInfo> bindInfos, Dispatch const &d ) const
   {
-    Result result = static_cast<Result>( d.vkBindBufferMemory2( m_device, bindInfos.size() , reinterpret_cast<const VkBindBufferMemoryInfo*>( bindInfos.data() ) ) );
+    Result result = static_cast<Result>( d.vkBindBufferMemory2KHR( m_device, bindInfos.size() , reinterpret_cast<const VkBindBufferMemoryInfo*>( bindInfos.data() ) ) );
     return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::bindBufferMemory2KHR" );
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
@@ -69946,17 +68759,41 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE Result Device::bindImageMemory2KHR( uint32_t bindInfoCount, const VULKAN_HPP_NAMESPACE::BindImageMemoryInfo* pBindInfos, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    return static_cast<Result>( d.vkBindImageMemory2( m_device, bindInfoCount, reinterpret_cast<const VkBindImageMemoryInfo*>( pBindInfos ) ) );
+    return static_cast<Result>( d.vkBindImageMemory2KHR( m_device, bindInfoCount, reinterpret_cast<const VkBindImageMemoryInfo*>( pBindInfos ) ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
   VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::bindImageMemory2KHR( ArrayProxy<const VULKAN_HPP_NAMESPACE::BindImageMemoryInfo> bindInfos, Dispatch const &d ) const
   {
-    Result result = static_cast<Result>( d.vkBindImageMemory2( m_device, bindInfos.size() , reinterpret_cast<const VkBindImageMemoryInfo*>( bindInfos.data() ) ) );
+    Result result = static_cast<Result>( d.vkBindImageMemory2KHR( m_device, bindInfos.size() , reinterpret_cast<const VkBindImageMemoryInfo*>( bindInfos.data() ) ) );
     return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::bindImageMemory2KHR" );
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE Result Device::buildAccelerationStructureKHR( uint32_t infoCount, const VULKAN_HPP_NAMESPACE::AccelerationStructureBuildGeometryInfoKHR* pInfos, const VULKAN_HPP_NAMESPACE::AccelerationStructureBuildOffsetInfoKHR* const* ppOffsetInfos, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  {
+    return static_cast<Result>( d.vkBuildAccelerationStructureKHR( m_device, infoCount, reinterpret_cast<const VkAccelerationStructureBuildGeometryInfoKHR*>( pInfos ), reinterpret_cast<const VkAccelerationStructureBuildOffsetInfoKHR* const*>( ppOffsetInfos ) ) );
+  }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE Result Device::buildAccelerationStructureKHR( ArrayProxy<const VULKAN_HPP_NAMESPACE::AccelerationStructureBuildGeometryInfoKHR> infos, ArrayProxy<const VULKAN_HPP_NAMESPACE::AccelerationStructureBuildOffsetInfoKHR* const> pOffsetInfos, Dispatch const &d ) const
+  {
+#ifdef VULKAN_HPP_NO_EXCEPTIONS
+    VULKAN_HPP_ASSERT( infos.size() == pOffsetInfos.size() );
+#else
+    if ( infos.size() != pOffsetInfos.size() )
+    {
+      throw LogicError( VULKAN_HPP_NAMESPACE_STRING "::VkDevice::buildAccelerationStructureKHR: infos.size() != pOffsetInfos.size()" );
+    }
+#endif  /*VULKAN_HPP_NO_EXCEPTIONS*/
+    Result result = static_cast<Result>( d.vkBuildAccelerationStructureKHR( m_device, infos.size() , reinterpret_cast<const VkAccelerationStructureBuildGeometryInfoKHR*>( infos.data() ), reinterpret_cast<const VkAccelerationStructureBuildOffsetInfoKHR* const*>( pOffsetInfos.data() ) ) );
+    return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::buildAccelerationStructureKHR", { Result::eSuccess, Result::eOperationDeferredKHR, Result::eOperationNotDeferredKHR } );
+  }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
 #ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
   VULKAN_HPP_INLINE Result Device::compileDeferredNV( VULKAN_HPP_NAMESPACE::Pipeline pipeline, uint32_t shader, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
@@ -69972,6 +68809,82 @@
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE Result Device::copyAccelerationStructureKHR( const VULKAN_HPP_NAMESPACE::CopyAccelerationStructureInfoKHR* pInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  {
+    return static_cast<Result>( d.vkCopyAccelerationStructureKHR( m_device, reinterpret_cast<const VkCopyAccelerationStructureInfoKHR*>( pInfo ) ) );
+  }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE Result Device::copyAccelerationStructureKHR( const CopyAccelerationStructureInfoKHR & info, Dispatch const &d ) const
+  {
+    Result result = static_cast<Result>( d.vkCopyAccelerationStructureKHR( m_device, reinterpret_cast<const VkCopyAccelerationStructureInfoKHR*>( &info ) ) );
+    return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::copyAccelerationStructureKHR", { Result::eSuccess, Result::eOperationDeferredKHR, Result::eOperationNotDeferredKHR } );
+  }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE Result Device::copyAccelerationStructureToMemoryKHR( const VULKAN_HPP_NAMESPACE::CopyAccelerationStructureToMemoryInfoKHR* pInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  {
+    return static_cast<Result>( d.vkCopyAccelerationStructureToMemoryKHR( m_device, reinterpret_cast<const VkCopyAccelerationStructureToMemoryInfoKHR*>( pInfo ) ) );
+  }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE Result Device::copyAccelerationStructureToMemoryKHR( const CopyAccelerationStructureToMemoryInfoKHR & info, Dispatch const &d ) const
+  {
+    Result result = static_cast<Result>( d.vkCopyAccelerationStructureToMemoryKHR( m_device, reinterpret_cast<const VkCopyAccelerationStructureToMemoryInfoKHR*>( &info ) ) );
+    return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::copyAccelerationStructureToMemoryKHR", { Result::eSuccess, Result::eOperationDeferredKHR, Result::eOperationNotDeferredKHR } );
+  }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE Result Device::copyMemoryToAccelerationStructureKHR( const VULKAN_HPP_NAMESPACE::CopyMemoryToAccelerationStructureInfoKHR* pInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  {
+    return static_cast<Result>( d.vkCopyMemoryToAccelerationStructureKHR( m_device, reinterpret_cast<const VkCopyMemoryToAccelerationStructureInfoKHR*>( pInfo ) ) );
+  }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE Result Device::copyMemoryToAccelerationStructureKHR( const CopyMemoryToAccelerationStructureInfoKHR & info, Dispatch const &d ) const
+  {
+    Result result = static_cast<Result>( d.vkCopyMemoryToAccelerationStructureKHR( m_device, reinterpret_cast<const VkCopyMemoryToAccelerationStructureInfoKHR*>( &info ) ) );
+    return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::copyMemoryToAccelerationStructureKHR", { Result::eSuccess, Result::eOperationDeferredKHR, Result::eOperationNotDeferredKHR } );
+  }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE Result Device::createAccelerationStructureKHR( const VULKAN_HPP_NAMESPACE::AccelerationStructureCreateInfoKHR* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::AccelerationStructureKHR* pAccelerationStructure, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  {
+    return static_cast<Result>( d.vkCreateAccelerationStructureKHR( m_device, reinterpret_cast<const VkAccelerationStructureCreateInfoKHR*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkAccelerationStructureKHR*>( pAccelerationStructure ) ) );
+  }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::AccelerationStructureKHR>::type Device::createAccelerationStructureKHR( const AccelerationStructureCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+  {
+    VULKAN_HPP_NAMESPACE::AccelerationStructureKHR accelerationStructure;
+    Result result = static_cast<Result>( d.vkCreateAccelerationStructureKHR( m_device, reinterpret_cast<const VkAccelerationStructureCreateInfoKHR*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkAccelerationStructureKHR*>( &accelerationStructure ) ) );
+    return createResultValue( result, accelerationStructure, VULKAN_HPP_NAMESPACE_STRING"::Device::createAccelerationStructureKHR" );
+  }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<AccelerationStructureKHR,Dispatch>>::type Device::createAccelerationStructureKHRUnique( const AccelerationStructureCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+  {
+    VULKAN_HPP_NAMESPACE::AccelerationStructureKHR accelerationStructure;
+    Result result = static_cast<Result>( d.vkCreateAccelerationStructureKHR( m_device, reinterpret_cast<const VkAccelerationStructureCreateInfoKHR*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkAccelerationStructureKHR*>( &accelerationStructure ) ) );
+
+    ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+    return createResultValue<AccelerationStructureKHR,Dispatch>( result, accelerationStructure, VULKAN_HPP_NAMESPACE_STRING"::Device::createAccelerationStructureKHRUnique", deleter );
+  }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
   template<typename Dispatch>
   VULKAN_HPP_INLINE Result Device::createAccelerationStructureNV( const VULKAN_HPP_NAMESPACE::AccelerationStructureCreateInfoNV* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::AccelerationStructureNV* pAccelerationStructure, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
@@ -70083,77 +68996,103 @@
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Allocator, typename Dispatch>
-  VULKAN_HPP_INLINE typename ResultValueType<std::vector<Pipeline,Allocator>>::type Device::createComputePipelines( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::ComputePipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+  VULKAN_HPP_INLINE ResultValue<std::vector<Pipeline,Allocator>> Device::createComputePipelines( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::ComputePipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
   {
     std::vector<Pipeline,Allocator> pipelines( createInfos.size() );
     Result result = static_cast<Result>( d.vkCreateComputePipelines( m_device, static_cast<VkPipelineCache>( pipelineCache ), createInfos.size() , reinterpret_cast<const VkComputePipelineCreateInfo*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( pipelines.data() ) ) );
-    return createResultValue( result, pipelines, VULKAN_HPP_NAMESPACE_STRING"::Device::createComputePipelines" );
+    return createResultValue( result, pipelines, VULKAN_HPP_NAMESPACE_STRING"::Device::createComputePipelines", { Result::eSuccess, Result::ePipelineCompileRequiredEXT } );
   }
   template<typename Allocator, typename Dispatch>
-  VULKAN_HPP_INLINE typename ResultValueType<std::vector<Pipeline,Allocator>>::type Device::createComputePipelines( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::ComputePipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const
+  VULKAN_HPP_INLINE ResultValue<std::vector<Pipeline,Allocator>> Device::createComputePipelines( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::ComputePipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const
   {
     std::vector<Pipeline,Allocator> pipelines( createInfos.size(), vectorAllocator );
     Result result = static_cast<Result>( d.vkCreateComputePipelines( m_device, static_cast<VkPipelineCache>( pipelineCache ), createInfos.size() , reinterpret_cast<const VkComputePipelineCreateInfo*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( pipelines.data() ) ) );
-    return createResultValue( result, pipelines, VULKAN_HPP_NAMESPACE_STRING"::Device::createComputePipelines" );
+    return createResultValue( result, pipelines, VULKAN_HPP_NAMESPACE_STRING"::Device::createComputePipelines", { Result::eSuccess, Result::ePipelineCompileRequiredEXT } );
   }
   template<typename Dispatch>
-  VULKAN_HPP_INLINE typename ResultValueType<Pipeline>::type Device::createComputePipeline( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const ComputePipelineCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+  VULKAN_HPP_INLINE ResultValue<Pipeline> Device::createComputePipeline( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const ComputePipelineCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
   {
     Pipeline pipeline;
     Result result = static_cast<Result>( d.vkCreateComputePipelines( m_device, static_cast<VkPipelineCache>( pipelineCache ), 1 , reinterpret_cast<const VkComputePipelineCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( &pipeline ) ) );
-    return createResultValue( result, pipeline, VULKAN_HPP_NAMESPACE_STRING"::Device::createComputePipeline" );
+    return createResultValue( result, pipeline, VULKAN_HPP_NAMESPACE_STRING"::Device::createComputePipeline", { Result::eSuccess, Result::ePipelineCompileRequiredEXT } );
   }
 #ifndef VULKAN_HPP_NO_SMART_HANDLE
   template<typename Allocator, typename Dispatch>
-  VULKAN_HPP_INLINE typename ResultValueType<std::vector<UniqueHandle<Pipeline,Dispatch>,Allocator>>::type Device::createComputePipelinesUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::ComputePipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+  VULKAN_HPP_INLINE ResultValue<std::vector<UniqueHandle<Pipeline,Dispatch>,Allocator>> Device::createComputePipelinesUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::ComputePipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
   {
-    static_assert( sizeof( Pipeline ) <= sizeof( UniqueHandle<Pipeline, Dispatch> ), "Pipeline is greater than UniqueHandle<Pipeline, Dispatch>!" );
-    std::vector<UniqueHandle<Pipeline, Dispatch>, Allocator> pipelines;
-    pipelines.reserve( createInfos.size() );
-    Pipeline* buffer = reinterpret_cast<Pipeline*>( reinterpret_cast<char*>( pipelines.data() ) + createInfos.size() * ( sizeof( UniqueHandle<Pipeline, Dispatch> ) - sizeof( Pipeline ) ) );
-    Result result = static_cast<Result>(d.vkCreateComputePipelines( m_device, static_cast<VkPipelineCache>( pipelineCache ), createInfos.size() , reinterpret_cast<const VkComputePipelineCreateInfo*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( buffer ) ) );
-    if ( result == VULKAN_HPP_NAMESPACE::Result::eSuccess )
+    std::vector<UniqueHandle<Pipeline, Dispatch>, Allocator> uniquePipelines;
+    std::vector<Pipeline> pipelines( createInfos.size() );
+    Result result = static_cast<Result>( d.vkCreateComputePipelines( m_device, static_cast<VkPipelineCache>( pipelineCache ), createInfos.size() , reinterpret_cast<const VkComputePipelineCreateInfo*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>(pipelines.data()) ) );
+    if ( ( result == VULKAN_HPP_NAMESPACE::Result::eSuccess ) || ( result == VULKAN_HPP_NAMESPACE::Result::ePipelineCompileRequiredEXT ) )
     {
+      uniquePipelines.reserve( createInfos.size() );
       ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
       for ( size_t i=0 ; i<createInfos.size() ; i++ )
       {
-        pipelines.push_back( UniqueHandle<Pipeline, Dispatch>( buffer[i], deleter ) );
+        uniquePipelines.push_back( UniqueHandle<Pipeline, Dispatch>( pipelines[i], deleter ) );
       }
     }
 
-    return createResultValue( result, pipelines, VULKAN_HPP_NAMESPACE_STRING "::Device::createComputePipelinesUnique" );
+    return createResultValue( result, uniquePipelines, VULKAN_HPP_NAMESPACE_STRING "::Device::createComputePipelinesUnique", { VULKAN_HPP_NAMESPACE::Result::eSuccess, VULKAN_HPP_NAMESPACE::Result::ePipelineCompileRequiredEXT } );
   }
   template<typename Allocator, typename Dispatch>
-  VULKAN_HPP_INLINE typename ResultValueType<std::vector<UniqueHandle<Pipeline,Dispatch>,Allocator>>::type Device::createComputePipelinesUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::ComputePipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const
+  VULKAN_HPP_INLINE ResultValue<std::vector<UniqueHandle<Pipeline,Dispatch>,Allocator>> Device::createComputePipelinesUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::ComputePipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const
   {
-    static_assert( sizeof( Pipeline ) <= sizeof( UniqueHandle<Pipeline, Dispatch> ), "Pipeline is greater than UniqueHandle<Pipeline, Dispatch>!" );
-    std::vector<UniqueHandle<Pipeline, Dispatch>, Allocator> pipelines( vectorAllocator );
-    pipelines.reserve( createInfos.size() );
-    Pipeline* buffer = reinterpret_cast<Pipeline*>( reinterpret_cast<char*>( pipelines.data() ) + createInfos.size() * ( sizeof( UniqueHandle<Pipeline, Dispatch> ) - sizeof( Pipeline ) ) );
-    Result result = static_cast<Result>(d.vkCreateComputePipelines( m_device, static_cast<VkPipelineCache>( pipelineCache ), createInfos.size() , reinterpret_cast<const VkComputePipelineCreateInfo*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( buffer ) ) );
-    if ( result == VULKAN_HPP_NAMESPACE::Result::eSuccess )
+    std::vector<UniqueHandle<Pipeline, Dispatch>, Allocator> uniquePipelines( vectorAllocator );
+    std::vector<Pipeline> pipelines( createInfos.size() );
+    Result result = static_cast<Result>( d.vkCreateComputePipelines( m_device, static_cast<VkPipelineCache>( pipelineCache ), createInfos.size() , reinterpret_cast<const VkComputePipelineCreateInfo*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>(pipelines.data()) ) );
+    if ( ( result == VULKAN_HPP_NAMESPACE::Result::eSuccess ) || ( result == VULKAN_HPP_NAMESPACE::Result::ePipelineCompileRequiredEXT ) )
     {
+      uniquePipelines.reserve( createInfos.size() );
       ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
       for ( size_t i=0 ; i<createInfos.size() ; i++ )
       {
-        pipelines.push_back( UniqueHandle<Pipeline, Dispatch>( buffer[i], deleter ) );
+        uniquePipelines.push_back( UniqueHandle<Pipeline, Dispatch>( pipelines[i], deleter ) );
       }
     }
 
-    return createResultValue( result, pipelines, VULKAN_HPP_NAMESPACE_STRING "::Device::createComputePipelinesUnique" );
+    return createResultValue( result, uniquePipelines, VULKAN_HPP_NAMESPACE_STRING "::Device::createComputePipelinesUnique", { VULKAN_HPP_NAMESPACE::Result::eSuccess, VULKAN_HPP_NAMESPACE::Result::ePipelineCompileRequiredEXT } );
   }
   template<typename Dispatch>
-  VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<Pipeline,Dispatch>>::type Device::createComputePipelineUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const ComputePipelineCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+  VULKAN_HPP_INLINE ResultValue<UniqueHandle<Pipeline,Dispatch>> Device::createComputePipelineUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const ComputePipelineCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
   {
     Pipeline pipeline;
     Result result = static_cast<Result>( d.vkCreateComputePipelines( m_device, static_cast<VkPipelineCache>( pipelineCache ), 1 , reinterpret_cast<const VkComputePipelineCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( &pipeline ) ) );
 
     ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
-    return createResultValue<Pipeline,Dispatch>( result, pipeline, VULKAN_HPP_NAMESPACE_STRING"::Device::createComputePipelineUnique", deleter );
+    return createResultValue<Pipeline,Dispatch>( result, pipeline, VULKAN_HPP_NAMESPACE_STRING"::Device::createComputePipelineUnique", { Result::eSuccess, Result::ePipelineCompileRequiredEXT }, deleter );
   }
 #endif /*VULKAN_HPP_NO_SMART_HANDLE*/
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE Result Device::createDeferredOperationKHR( const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::DeferredOperationKHR* pDeferredOperation, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  {
+    return static_cast<Result>( d.vkCreateDeferredOperationKHR( m_device, reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkDeferredOperationKHR*>( pDeferredOperation ) ) );
+  }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::DeferredOperationKHR>::type Device::createDeferredOperationKHR( Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+  {
+    VULKAN_HPP_NAMESPACE::DeferredOperationKHR deferredOperation;
+    Result result = static_cast<Result>( d.vkCreateDeferredOperationKHR( m_device, reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkDeferredOperationKHR*>( &deferredOperation ) ) );
+    return createResultValue( result, deferredOperation, VULKAN_HPP_NAMESPACE_STRING"::Device::createDeferredOperationKHR" );
+  }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<DeferredOperationKHR,Dispatch>>::type Device::createDeferredOperationKHRUnique( Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+  {
+    VULKAN_HPP_NAMESPACE::DeferredOperationKHR deferredOperation;
+    Result result = static_cast<Result>( d.vkCreateDeferredOperationKHR( m_device, reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkDeferredOperationKHR*>( &deferredOperation ) ) );
+
+    ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+    return createResultValue<DeferredOperationKHR,Dispatch>( result, deferredOperation, VULKAN_HPP_NAMESPACE_STRING"::Device::createDeferredOperationKHRUnique", deleter );
+  }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
   template<typename Dispatch>
   VULKAN_HPP_INLINE Result Device::createDescriptorPool( const VULKAN_HPP_NAMESPACE::DescriptorPoolCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::DescriptorPool* pDescriptorPool, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
@@ -70235,14 +69174,14 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE Result Device::createDescriptorUpdateTemplateKHR( const VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplateCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate* pDescriptorUpdateTemplate, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    return static_cast<Result>( d.vkCreateDescriptorUpdateTemplate( m_device, reinterpret_cast<const VkDescriptorUpdateTemplateCreateInfo*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkDescriptorUpdateTemplate*>( pDescriptorUpdateTemplate ) ) );
+    return static_cast<Result>( d.vkCreateDescriptorUpdateTemplateKHR( m_device, reinterpret_cast<const VkDescriptorUpdateTemplateCreateInfo*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkDescriptorUpdateTemplate*>( pDescriptorUpdateTemplate ) ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
   VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate>::type Device::createDescriptorUpdateTemplateKHR( const DescriptorUpdateTemplateCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
   {
     VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate descriptorUpdateTemplate;
-    Result result = static_cast<Result>( d.vkCreateDescriptorUpdateTemplate( m_device, reinterpret_cast<const VkDescriptorUpdateTemplateCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkDescriptorUpdateTemplate*>( &descriptorUpdateTemplate ) ) );
+    Result result = static_cast<Result>( d.vkCreateDescriptorUpdateTemplateKHR( m_device, reinterpret_cast<const VkDescriptorUpdateTemplateCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkDescriptorUpdateTemplate*>( &descriptorUpdateTemplate ) ) );
     return createResultValue( result, descriptorUpdateTemplate, VULKAN_HPP_NAMESPACE_STRING"::Device::createDescriptorUpdateTemplateKHR" );
   }
 #ifndef VULKAN_HPP_NO_SMART_HANDLE
@@ -70250,7 +69189,7 @@
   VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<DescriptorUpdateTemplate,Dispatch>>::type Device::createDescriptorUpdateTemplateKHRUnique( const DescriptorUpdateTemplateCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
   {
     VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate descriptorUpdateTemplate;
-    Result result = static_cast<Result>( d.vkCreateDescriptorUpdateTemplate( m_device, reinterpret_cast<const VkDescriptorUpdateTemplateCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkDescriptorUpdateTemplate*>( &descriptorUpdateTemplate ) ) );
+    Result result = static_cast<Result>( d.vkCreateDescriptorUpdateTemplateKHR( m_device, reinterpret_cast<const VkDescriptorUpdateTemplateCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkDescriptorUpdateTemplate*>( &descriptorUpdateTemplate ) ) );
 
     ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
     return createResultValue<DescriptorUpdateTemplate,Dispatch>( result, descriptorUpdateTemplate, VULKAN_HPP_NAMESPACE_STRING"::Device::createDescriptorUpdateTemplateKHRUnique", deleter );
@@ -70343,73 +69282,71 @@
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Allocator, typename Dispatch>
-  VULKAN_HPP_INLINE typename ResultValueType<std::vector<Pipeline,Allocator>>::type Device::createGraphicsPipelines( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::GraphicsPipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+  VULKAN_HPP_INLINE ResultValue<std::vector<Pipeline,Allocator>> Device::createGraphicsPipelines( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::GraphicsPipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
   {
     std::vector<Pipeline,Allocator> pipelines( createInfos.size() );
     Result result = static_cast<Result>( d.vkCreateGraphicsPipelines( m_device, static_cast<VkPipelineCache>( pipelineCache ), createInfos.size() , reinterpret_cast<const VkGraphicsPipelineCreateInfo*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( pipelines.data() ) ) );
-    return createResultValue( result, pipelines, VULKAN_HPP_NAMESPACE_STRING"::Device::createGraphicsPipelines" );
+    return createResultValue( result, pipelines, VULKAN_HPP_NAMESPACE_STRING"::Device::createGraphicsPipelines", { Result::eSuccess, Result::ePipelineCompileRequiredEXT } );
   }
   template<typename Allocator, typename Dispatch>
-  VULKAN_HPP_INLINE typename ResultValueType<std::vector<Pipeline,Allocator>>::type Device::createGraphicsPipelines( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::GraphicsPipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const
+  VULKAN_HPP_INLINE ResultValue<std::vector<Pipeline,Allocator>> Device::createGraphicsPipelines( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::GraphicsPipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const
   {
     std::vector<Pipeline,Allocator> pipelines( createInfos.size(), vectorAllocator );
     Result result = static_cast<Result>( d.vkCreateGraphicsPipelines( m_device, static_cast<VkPipelineCache>( pipelineCache ), createInfos.size() , reinterpret_cast<const VkGraphicsPipelineCreateInfo*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( pipelines.data() ) ) );
-    return createResultValue( result, pipelines, VULKAN_HPP_NAMESPACE_STRING"::Device::createGraphicsPipelines" );
+    return createResultValue( result, pipelines, VULKAN_HPP_NAMESPACE_STRING"::Device::createGraphicsPipelines", { Result::eSuccess, Result::ePipelineCompileRequiredEXT } );
   }
   template<typename Dispatch>
-  VULKAN_HPP_INLINE typename ResultValueType<Pipeline>::type Device::createGraphicsPipeline( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const GraphicsPipelineCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+  VULKAN_HPP_INLINE ResultValue<Pipeline> Device::createGraphicsPipeline( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const GraphicsPipelineCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
   {
     Pipeline pipeline;
     Result result = static_cast<Result>( d.vkCreateGraphicsPipelines( m_device, static_cast<VkPipelineCache>( pipelineCache ), 1 , reinterpret_cast<const VkGraphicsPipelineCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( &pipeline ) ) );
-    return createResultValue( result, pipeline, VULKAN_HPP_NAMESPACE_STRING"::Device::createGraphicsPipeline" );
+    return createResultValue( result, pipeline, VULKAN_HPP_NAMESPACE_STRING"::Device::createGraphicsPipeline", { Result::eSuccess, Result::ePipelineCompileRequiredEXT } );
   }
 #ifndef VULKAN_HPP_NO_SMART_HANDLE
   template<typename Allocator, typename Dispatch>
-  VULKAN_HPP_INLINE typename ResultValueType<std::vector<UniqueHandle<Pipeline,Dispatch>,Allocator>>::type Device::createGraphicsPipelinesUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::GraphicsPipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+  VULKAN_HPP_INLINE ResultValue<std::vector<UniqueHandle<Pipeline,Dispatch>,Allocator>> Device::createGraphicsPipelinesUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::GraphicsPipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
   {
-    static_assert( sizeof( Pipeline ) <= sizeof( UniqueHandle<Pipeline, Dispatch> ), "Pipeline is greater than UniqueHandle<Pipeline, Dispatch>!" );
-    std::vector<UniqueHandle<Pipeline, Dispatch>, Allocator> pipelines;
-    pipelines.reserve( createInfos.size() );
-    Pipeline* buffer = reinterpret_cast<Pipeline*>( reinterpret_cast<char*>( pipelines.data() ) + createInfos.size() * ( sizeof( UniqueHandle<Pipeline, Dispatch> ) - sizeof( Pipeline ) ) );
-    Result result = static_cast<Result>(d.vkCreateGraphicsPipelines( m_device, static_cast<VkPipelineCache>( pipelineCache ), createInfos.size() , reinterpret_cast<const VkGraphicsPipelineCreateInfo*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( buffer ) ) );
-    if ( result == VULKAN_HPP_NAMESPACE::Result::eSuccess )
+    std::vector<UniqueHandle<Pipeline, Dispatch>, Allocator> uniquePipelines;
+    std::vector<Pipeline> pipelines( createInfos.size() );
+    Result result = static_cast<Result>( d.vkCreateGraphicsPipelines( m_device, static_cast<VkPipelineCache>( pipelineCache ), createInfos.size() , reinterpret_cast<const VkGraphicsPipelineCreateInfo*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>(pipelines.data()) ) );
+    if ( ( result == VULKAN_HPP_NAMESPACE::Result::eSuccess ) || ( result == VULKAN_HPP_NAMESPACE::Result::ePipelineCompileRequiredEXT ) )
     {
+      uniquePipelines.reserve( createInfos.size() );
       ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
       for ( size_t i=0 ; i<createInfos.size() ; i++ )
       {
-        pipelines.push_back( UniqueHandle<Pipeline, Dispatch>( buffer[i], deleter ) );
+        uniquePipelines.push_back( UniqueHandle<Pipeline, Dispatch>( pipelines[i], deleter ) );
       }
     }
 
-    return createResultValue( result, pipelines, VULKAN_HPP_NAMESPACE_STRING "::Device::createGraphicsPipelinesUnique" );
+    return createResultValue( result, uniquePipelines, VULKAN_HPP_NAMESPACE_STRING "::Device::createGraphicsPipelinesUnique", { VULKAN_HPP_NAMESPACE::Result::eSuccess, VULKAN_HPP_NAMESPACE::Result::ePipelineCompileRequiredEXT } );
   }
   template<typename Allocator, typename Dispatch>
-  VULKAN_HPP_INLINE typename ResultValueType<std::vector<UniqueHandle<Pipeline,Dispatch>,Allocator>>::type Device::createGraphicsPipelinesUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::GraphicsPipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const
+  VULKAN_HPP_INLINE ResultValue<std::vector<UniqueHandle<Pipeline,Dispatch>,Allocator>> Device::createGraphicsPipelinesUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::GraphicsPipelineCreateInfo> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const
   {
-    static_assert( sizeof( Pipeline ) <= sizeof( UniqueHandle<Pipeline, Dispatch> ), "Pipeline is greater than UniqueHandle<Pipeline, Dispatch>!" );
-    std::vector<UniqueHandle<Pipeline, Dispatch>, Allocator> pipelines( vectorAllocator );
-    pipelines.reserve( createInfos.size() );
-    Pipeline* buffer = reinterpret_cast<Pipeline*>( reinterpret_cast<char*>( pipelines.data() ) + createInfos.size() * ( sizeof( UniqueHandle<Pipeline, Dispatch> ) - sizeof( Pipeline ) ) );
-    Result result = static_cast<Result>(d.vkCreateGraphicsPipelines( m_device, static_cast<VkPipelineCache>( pipelineCache ), createInfos.size() , reinterpret_cast<const VkGraphicsPipelineCreateInfo*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( buffer ) ) );
-    if ( result == VULKAN_HPP_NAMESPACE::Result::eSuccess )
+    std::vector<UniqueHandle<Pipeline, Dispatch>, Allocator> uniquePipelines( vectorAllocator );
+    std::vector<Pipeline> pipelines( createInfos.size() );
+    Result result = static_cast<Result>( d.vkCreateGraphicsPipelines( m_device, static_cast<VkPipelineCache>( pipelineCache ), createInfos.size() , reinterpret_cast<const VkGraphicsPipelineCreateInfo*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>(pipelines.data()) ) );
+    if ( ( result == VULKAN_HPP_NAMESPACE::Result::eSuccess ) || ( result == VULKAN_HPP_NAMESPACE::Result::ePipelineCompileRequiredEXT ) )
     {
+      uniquePipelines.reserve( createInfos.size() );
       ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
       for ( size_t i=0 ; i<createInfos.size() ; i++ )
       {
-        pipelines.push_back( UniqueHandle<Pipeline, Dispatch>( buffer[i], deleter ) );
+        uniquePipelines.push_back( UniqueHandle<Pipeline, Dispatch>( pipelines[i], deleter ) );
       }
     }
 
-    return createResultValue( result, pipelines, VULKAN_HPP_NAMESPACE_STRING "::Device::createGraphicsPipelinesUnique" );
+    return createResultValue( result, uniquePipelines, VULKAN_HPP_NAMESPACE_STRING "::Device::createGraphicsPipelinesUnique", { VULKAN_HPP_NAMESPACE::Result::eSuccess, VULKAN_HPP_NAMESPACE::Result::ePipelineCompileRequiredEXT } );
   }
   template<typename Dispatch>
-  VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<Pipeline,Dispatch>>::type Device::createGraphicsPipelineUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const GraphicsPipelineCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+  VULKAN_HPP_INLINE ResultValue<UniqueHandle<Pipeline,Dispatch>> Device::createGraphicsPipelineUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const GraphicsPipelineCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
   {
     Pipeline pipeline;
     Result result = static_cast<Result>( d.vkCreateGraphicsPipelines( m_device, static_cast<VkPipelineCache>( pipelineCache ), 1 , reinterpret_cast<const VkGraphicsPipelineCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( &pipeline ) ) );
 
     ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
-    return createResultValue<Pipeline,Dispatch>( result, pipeline, VULKAN_HPP_NAMESPACE_STRING"::Device::createGraphicsPipelineUnique", deleter );
+    return createResultValue<Pipeline,Dispatch>( result, pipeline, VULKAN_HPP_NAMESPACE_STRING"::Device::createGraphicsPipelineUnique", { Result::eSuccess, Result::ePipelineCompileRequiredEXT }, deleter );
   }
 #endif /*VULKAN_HPP_NO_SMART_HANDLE*/
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
@@ -70467,53 +69404,27 @@
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
   template<typename Dispatch>
-  VULKAN_HPP_INLINE Result Device::createIndirectCommandsLayoutNVX( const VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutCreateInfoNVX* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNVX* pIndirectCommandsLayout, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  VULKAN_HPP_INLINE Result Device::createIndirectCommandsLayoutNV( const VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutCreateInfoNV* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNV* pIndirectCommandsLayout, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    return static_cast<Result>( d.vkCreateIndirectCommandsLayoutNVX( m_device, reinterpret_cast<const VkIndirectCommandsLayoutCreateInfoNVX*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkIndirectCommandsLayoutNVX*>( pIndirectCommandsLayout ) ) );
+    return static_cast<Result>( d.vkCreateIndirectCommandsLayoutNV( m_device, reinterpret_cast<const VkIndirectCommandsLayoutCreateInfoNV*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkIndirectCommandsLayoutNV*>( pIndirectCommandsLayout ) ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
-  VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNVX>::type Device::createIndirectCommandsLayoutNVX( const IndirectCommandsLayoutCreateInfoNVX & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+  VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNV>::type Device::createIndirectCommandsLayoutNV( const IndirectCommandsLayoutCreateInfoNV & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
   {
-    VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNVX indirectCommandsLayout;
-    Result result = static_cast<Result>( d.vkCreateIndirectCommandsLayoutNVX( m_device, reinterpret_cast<const VkIndirectCommandsLayoutCreateInfoNVX*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkIndirectCommandsLayoutNVX*>( &indirectCommandsLayout ) ) );
-    return createResultValue( result, indirectCommandsLayout, VULKAN_HPP_NAMESPACE_STRING"::Device::createIndirectCommandsLayoutNVX" );
+    VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNV indirectCommandsLayout;
+    Result result = static_cast<Result>( d.vkCreateIndirectCommandsLayoutNV( m_device, reinterpret_cast<const VkIndirectCommandsLayoutCreateInfoNV*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkIndirectCommandsLayoutNV*>( &indirectCommandsLayout ) ) );
+    return createResultValue( result, indirectCommandsLayout, VULKAN_HPP_NAMESPACE_STRING"::Device::createIndirectCommandsLayoutNV" );
   }
 #ifndef VULKAN_HPP_NO_SMART_HANDLE
   template<typename Dispatch>
-  VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<IndirectCommandsLayoutNVX,Dispatch>>::type Device::createIndirectCommandsLayoutNVXUnique( const IndirectCommandsLayoutCreateInfoNVX & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+  VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<IndirectCommandsLayoutNV,Dispatch>>::type Device::createIndirectCommandsLayoutNVUnique( const IndirectCommandsLayoutCreateInfoNV & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
   {
-    VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNVX indirectCommandsLayout;
-    Result result = static_cast<Result>( d.vkCreateIndirectCommandsLayoutNVX( m_device, reinterpret_cast<const VkIndirectCommandsLayoutCreateInfoNVX*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkIndirectCommandsLayoutNVX*>( &indirectCommandsLayout ) ) );
+    VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNV indirectCommandsLayout;
+    Result result = static_cast<Result>( d.vkCreateIndirectCommandsLayoutNV( m_device, reinterpret_cast<const VkIndirectCommandsLayoutCreateInfoNV*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkIndirectCommandsLayoutNV*>( &indirectCommandsLayout ) ) );
 
     ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
-    return createResultValue<IndirectCommandsLayoutNVX,Dispatch>( result, indirectCommandsLayout, VULKAN_HPP_NAMESPACE_STRING"::Device::createIndirectCommandsLayoutNVXUnique", deleter );
-  }
-#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
-#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
-
-  template<typename Dispatch>
-  VULKAN_HPP_INLINE Result Device::createObjectTableNVX( const VULKAN_HPP_NAMESPACE::ObjectTableCreateInfoNVX* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::ObjectTableNVX* pObjectTable, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
-  {
-    return static_cast<Result>( d.vkCreateObjectTableNVX( m_device, reinterpret_cast<const VkObjectTableCreateInfoNVX*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkObjectTableNVX*>( pObjectTable ) ) );
-  }
-#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
-  template<typename Dispatch>
-  VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::ObjectTableNVX>::type Device::createObjectTableNVX( const ObjectTableCreateInfoNVX & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
-  {
-    VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable;
-    Result result = static_cast<Result>( d.vkCreateObjectTableNVX( m_device, reinterpret_cast<const VkObjectTableCreateInfoNVX*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkObjectTableNVX*>( &objectTable ) ) );
-    return createResultValue( result, objectTable, VULKAN_HPP_NAMESPACE_STRING"::Device::createObjectTableNVX" );
-  }
-#ifndef VULKAN_HPP_NO_SMART_HANDLE
-  template<typename Dispatch>
-  VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<ObjectTableNVX,Dispatch>>::type Device::createObjectTableNVXUnique( const ObjectTableCreateInfoNVX & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
-  {
-    VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable;
-    Result result = static_cast<Result>( d.vkCreateObjectTableNVX( m_device, reinterpret_cast<const VkObjectTableCreateInfoNVX*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkObjectTableNVX*>( &objectTable ) ) );
-
-    ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
-    return createResultValue<ObjectTableNVX,Dispatch>( result, objectTable, VULKAN_HPP_NAMESPACE_STRING"::Device::createObjectTableNVXUnique", deleter );
+    return createResultValue<IndirectCommandsLayoutNV,Dispatch>( result, indirectCommandsLayout, VULKAN_HPP_NAMESPACE_STRING"::Device::createIndirectCommandsLayoutNVUnique", deleter );
   }
 #endif /*VULKAN_HPP_NO_SMART_HANDLE*/
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
@@ -70596,6 +69507,84 @@
 #endif /*VULKAN_HPP_NO_SMART_HANDLE*/
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE Result Device::createRayTracingPipelinesKHR( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, uint32_t createInfoCount, const VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoKHR* pCreateInfos, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::Pipeline* pPipelines, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  {
+    return static_cast<Result>( d.vkCreateRayTracingPipelinesKHR( m_device, static_cast<VkPipelineCache>( pipelineCache ), createInfoCount, reinterpret_cast<const VkRayTracingPipelineCreateInfoKHR*>( pCreateInfos ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkPipeline*>( pPipelines ) ) );
+  }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+  template<typename Allocator, typename Dispatch>
+  VULKAN_HPP_INLINE ResultValue<std::vector<Pipeline,Allocator>> Device::createRayTracingPipelinesKHR( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoKHR> createInfos, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+  {
+    std::vector<Pipeline,Allocator> pipelines( createInfos.size() );
+    Result result = static_cast<Result>( d.vkCreateRayTracingPipelinesKHR( m_device, static_cast<VkPipelineCache>( pipelineCache ), createInfos.size() , reinterpret_cast<const VkRayTracingPipelineCreateInfoKHR*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( pipelines.data() ) ) );
+    return createResultValue( result, pipelines, VULKAN_HPP_NAMESPACE_STRING"::Device::createRayTracingPipelinesKHR", { Result::eSuccess, Result::eOperationDeferredKHR, Result::eOperationNotDeferredKHR, Result::ePipelineCompileRequiredEXT } );
+  }
+  template<typename Allocator, typename Dispatch>
+  VULKAN_HPP_INLINE ResultValue<std::vector<Pipeline,Allocator>> Device::createRayTracingPipelinesKHR( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoKHR> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const
+  {
+    std::vector<Pipeline,Allocator> pipelines( createInfos.size(), vectorAllocator );
+    Result result = static_cast<Result>( d.vkCreateRayTracingPipelinesKHR( m_device, static_cast<VkPipelineCache>( pipelineCache ), createInfos.size() , reinterpret_cast<const VkRayTracingPipelineCreateInfoKHR*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( pipelines.data() ) ) );
+    return createResultValue( result, pipelines, VULKAN_HPP_NAMESPACE_STRING"::Device::createRayTracingPipelinesKHR", { Result::eSuccess, Result::eOperationDeferredKHR, Result::eOperationNotDeferredKHR, Result::ePipelineCompileRequiredEXT } );
+  }
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE ResultValue<Pipeline> Device::createRayTracingPipelineKHR( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const RayTracingPipelineCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+  {
+    Pipeline pipeline;
+    Result result = static_cast<Result>( d.vkCreateRayTracingPipelinesKHR( m_device, static_cast<VkPipelineCache>( pipelineCache ), 1 , reinterpret_cast<const VkRayTracingPipelineCreateInfoKHR*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( &pipeline ) ) );
+    return createResultValue( result, pipeline, VULKAN_HPP_NAMESPACE_STRING"::Device::createRayTracingPipelineKHR", { Result::eSuccess, Result::eOperationDeferredKHR, Result::eOperationNotDeferredKHR, Result::ePipelineCompileRequiredEXT } );
+  }
+#ifndef VULKAN_HPP_NO_SMART_HANDLE
+  template<typename Allocator, typename Dispatch>
+  VULKAN_HPP_INLINE ResultValue<std::vector<UniqueHandle<Pipeline,Dispatch>,Allocator>> Device::createRayTracingPipelinesKHRUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoKHR> createInfos, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+  {
+    std::vector<UniqueHandle<Pipeline, Dispatch>, Allocator> uniquePipelines;
+    std::vector<Pipeline> pipelines( createInfos.size() );
+    Result result = static_cast<Result>( d.vkCreateRayTracingPipelinesKHR( m_device, static_cast<VkPipelineCache>( pipelineCache ), createInfos.size() , reinterpret_cast<const VkRayTracingPipelineCreateInfoKHR*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>(pipelines.data()) ) );
+    if ( ( result == VULKAN_HPP_NAMESPACE::Result::eSuccess ) || ( result == VULKAN_HPP_NAMESPACE::Result::eOperationDeferredKHR ) || ( result == VULKAN_HPP_NAMESPACE::Result::eOperationNotDeferredKHR ) || ( result == VULKAN_HPP_NAMESPACE::Result::ePipelineCompileRequiredEXT ) )
+    {
+      uniquePipelines.reserve( createInfos.size() );
+      ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+      for ( size_t i=0 ; i<createInfos.size() ; i++ )
+      {
+        uniquePipelines.push_back( UniqueHandle<Pipeline, Dispatch>( pipelines[i], deleter ) );
+      }
+    }
+
+    return createResultValue( result, uniquePipelines, VULKAN_HPP_NAMESPACE_STRING "::Device::createRayTracingPipelinesKHRUnique", { VULKAN_HPP_NAMESPACE::Result::eSuccess, VULKAN_HPP_NAMESPACE::Result::eOperationDeferredKHR, VULKAN_HPP_NAMESPACE::Result::eOperationNotDeferredKHR, VULKAN_HPP_NAMESPACE::Result::ePipelineCompileRequiredEXT } );
+  }
+  template<typename Allocator, typename Dispatch>
+  VULKAN_HPP_INLINE ResultValue<std::vector<UniqueHandle<Pipeline,Dispatch>,Allocator>> Device::createRayTracingPipelinesKHRUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoKHR> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const
+  {
+    std::vector<UniqueHandle<Pipeline, Dispatch>, Allocator> uniquePipelines( vectorAllocator );
+    std::vector<Pipeline> pipelines( createInfos.size() );
+    Result result = static_cast<Result>( d.vkCreateRayTracingPipelinesKHR( m_device, static_cast<VkPipelineCache>( pipelineCache ), createInfos.size() , reinterpret_cast<const VkRayTracingPipelineCreateInfoKHR*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>(pipelines.data()) ) );
+    if ( ( result == VULKAN_HPP_NAMESPACE::Result::eSuccess ) || ( result == VULKAN_HPP_NAMESPACE::Result::eOperationDeferredKHR ) || ( result == VULKAN_HPP_NAMESPACE::Result::eOperationNotDeferredKHR ) || ( result == VULKAN_HPP_NAMESPACE::Result::ePipelineCompileRequiredEXT ) )
+    {
+      uniquePipelines.reserve( createInfos.size() );
+      ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+      for ( size_t i=0 ; i<createInfos.size() ; i++ )
+      {
+        uniquePipelines.push_back( UniqueHandle<Pipeline, Dispatch>( pipelines[i], deleter ) );
+      }
+    }
+
+    return createResultValue( result, uniquePipelines, VULKAN_HPP_NAMESPACE_STRING "::Device::createRayTracingPipelinesKHRUnique", { VULKAN_HPP_NAMESPACE::Result::eSuccess, VULKAN_HPP_NAMESPACE::Result::eOperationDeferredKHR, VULKAN_HPP_NAMESPACE::Result::eOperationNotDeferredKHR, VULKAN_HPP_NAMESPACE::Result::ePipelineCompileRequiredEXT } );
+  }
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE ResultValue<UniqueHandle<Pipeline,Dispatch>> Device::createRayTracingPipelineKHRUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const RayTracingPipelineCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+  {
+    Pipeline pipeline;
+    Result result = static_cast<Result>( d.vkCreateRayTracingPipelinesKHR( m_device, static_cast<VkPipelineCache>( pipelineCache ), 1 , reinterpret_cast<const VkRayTracingPipelineCreateInfoKHR*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( &pipeline ) ) );
+
+    ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
+    return createResultValue<Pipeline,Dispatch>( result, pipeline, VULKAN_HPP_NAMESPACE_STRING"::Device::createRayTracingPipelineKHRUnique", { Result::eSuccess, Result::eOperationDeferredKHR, Result::eOperationNotDeferredKHR, Result::ePipelineCompileRequiredEXT }, deleter );
+  }
+#endif /*VULKAN_HPP_NO_SMART_HANDLE*/
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
   template<typename Dispatch>
   VULKAN_HPP_INLINE Result Device::createRayTracingPipelinesNV( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, uint32_t createInfoCount, const VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoNV* pCreateInfos, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::Pipeline* pPipelines, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
@@ -70603,73 +69592,71 @@
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Allocator, typename Dispatch>
-  VULKAN_HPP_INLINE typename ResultValueType<std::vector<Pipeline,Allocator>>::type Device::createRayTracingPipelinesNV( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoNV> createInfos, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+  VULKAN_HPP_INLINE ResultValue<std::vector<Pipeline,Allocator>> Device::createRayTracingPipelinesNV( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoNV> createInfos, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
   {
     std::vector<Pipeline,Allocator> pipelines( createInfos.size() );
     Result result = static_cast<Result>( d.vkCreateRayTracingPipelinesNV( m_device, static_cast<VkPipelineCache>( pipelineCache ), createInfos.size() , reinterpret_cast<const VkRayTracingPipelineCreateInfoNV*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( pipelines.data() ) ) );
-    return createResultValue( result, pipelines, VULKAN_HPP_NAMESPACE_STRING"::Device::createRayTracingPipelinesNV" );
+    return createResultValue( result, pipelines, VULKAN_HPP_NAMESPACE_STRING"::Device::createRayTracingPipelinesNV", { Result::eSuccess, Result::ePipelineCompileRequiredEXT } );
   }
   template<typename Allocator, typename Dispatch>
-  VULKAN_HPP_INLINE typename ResultValueType<std::vector<Pipeline,Allocator>>::type Device::createRayTracingPipelinesNV( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoNV> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const
+  VULKAN_HPP_INLINE ResultValue<std::vector<Pipeline,Allocator>> Device::createRayTracingPipelinesNV( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoNV> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const
   {
     std::vector<Pipeline,Allocator> pipelines( createInfos.size(), vectorAllocator );
     Result result = static_cast<Result>( d.vkCreateRayTracingPipelinesNV( m_device, static_cast<VkPipelineCache>( pipelineCache ), createInfos.size() , reinterpret_cast<const VkRayTracingPipelineCreateInfoNV*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( pipelines.data() ) ) );
-    return createResultValue( result, pipelines, VULKAN_HPP_NAMESPACE_STRING"::Device::createRayTracingPipelinesNV" );
+    return createResultValue( result, pipelines, VULKAN_HPP_NAMESPACE_STRING"::Device::createRayTracingPipelinesNV", { Result::eSuccess, Result::ePipelineCompileRequiredEXT } );
   }
   template<typename Dispatch>
-  VULKAN_HPP_INLINE typename ResultValueType<Pipeline>::type Device::createRayTracingPipelineNV( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const RayTracingPipelineCreateInfoNV & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+  VULKAN_HPP_INLINE ResultValue<Pipeline> Device::createRayTracingPipelineNV( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const RayTracingPipelineCreateInfoNV & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
   {
     Pipeline pipeline;
     Result result = static_cast<Result>( d.vkCreateRayTracingPipelinesNV( m_device, static_cast<VkPipelineCache>( pipelineCache ), 1 , reinterpret_cast<const VkRayTracingPipelineCreateInfoNV*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( &pipeline ) ) );
-    return createResultValue( result, pipeline, VULKAN_HPP_NAMESPACE_STRING"::Device::createRayTracingPipelineNV" );
+    return createResultValue( result, pipeline, VULKAN_HPP_NAMESPACE_STRING"::Device::createRayTracingPipelineNV", { Result::eSuccess, Result::ePipelineCompileRequiredEXT } );
   }
 #ifndef VULKAN_HPP_NO_SMART_HANDLE
   template<typename Allocator, typename Dispatch>
-  VULKAN_HPP_INLINE typename ResultValueType<std::vector<UniqueHandle<Pipeline,Dispatch>,Allocator>>::type Device::createRayTracingPipelinesNVUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoNV> createInfos, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+  VULKAN_HPP_INLINE ResultValue<std::vector<UniqueHandle<Pipeline,Dispatch>,Allocator>> Device::createRayTracingPipelinesNVUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoNV> createInfos, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
   {
-    static_assert( sizeof( Pipeline ) <= sizeof( UniqueHandle<Pipeline, Dispatch> ), "Pipeline is greater than UniqueHandle<Pipeline, Dispatch>!" );
-    std::vector<UniqueHandle<Pipeline, Dispatch>, Allocator> pipelines;
-    pipelines.reserve( createInfos.size() );
-    Pipeline* buffer = reinterpret_cast<Pipeline*>( reinterpret_cast<char*>( pipelines.data() ) + createInfos.size() * ( sizeof( UniqueHandle<Pipeline, Dispatch> ) - sizeof( Pipeline ) ) );
-    Result result = static_cast<Result>(d.vkCreateRayTracingPipelinesNV( m_device, static_cast<VkPipelineCache>( pipelineCache ), createInfos.size() , reinterpret_cast<const VkRayTracingPipelineCreateInfoNV*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( buffer ) ) );
-    if ( result == VULKAN_HPP_NAMESPACE::Result::eSuccess )
+    std::vector<UniqueHandle<Pipeline, Dispatch>, Allocator> uniquePipelines;
+    std::vector<Pipeline> pipelines( createInfos.size() );
+    Result result = static_cast<Result>( d.vkCreateRayTracingPipelinesNV( m_device, static_cast<VkPipelineCache>( pipelineCache ), createInfos.size() , reinterpret_cast<const VkRayTracingPipelineCreateInfoNV*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>(pipelines.data()) ) );
+    if ( ( result == VULKAN_HPP_NAMESPACE::Result::eSuccess ) || ( result == VULKAN_HPP_NAMESPACE::Result::ePipelineCompileRequiredEXT ) )
     {
+      uniquePipelines.reserve( createInfos.size() );
       ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
       for ( size_t i=0 ; i<createInfos.size() ; i++ )
       {
-        pipelines.push_back( UniqueHandle<Pipeline, Dispatch>( buffer[i], deleter ) );
+        uniquePipelines.push_back( UniqueHandle<Pipeline, Dispatch>( pipelines[i], deleter ) );
       }
     }
 
-    return createResultValue( result, pipelines, VULKAN_HPP_NAMESPACE_STRING "::Device::createRayTracingPipelinesNVUnique" );
+    return createResultValue( result, uniquePipelines, VULKAN_HPP_NAMESPACE_STRING "::Device::createRayTracingPipelinesNVUnique", { VULKAN_HPP_NAMESPACE::Result::eSuccess, VULKAN_HPP_NAMESPACE::Result::ePipelineCompileRequiredEXT } );
   }
   template<typename Allocator, typename Dispatch>
-  VULKAN_HPP_INLINE typename ResultValueType<std::vector<UniqueHandle<Pipeline,Dispatch>,Allocator>>::type Device::createRayTracingPipelinesNVUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoNV> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const
+  VULKAN_HPP_INLINE ResultValue<std::vector<UniqueHandle<Pipeline,Dispatch>,Allocator>> Device::createRayTracingPipelinesNVUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, ArrayProxy<const VULKAN_HPP_NAMESPACE::RayTracingPipelineCreateInfoNV> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const
   {
-    static_assert( sizeof( Pipeline ) <= sizeof( UniqueHandle<Pipeline, Dispatch> ), "Pipeline is greater than UniqueHandle<Pipeline, Dispatch>!" );
-    std::vector<UniqueHandle<Pipeline, Dispatch>, Allocator> pipelines( vectorAllocator );
-    pipelines.reserve( createInfos.size() );
-    Pipeline* buffer = reinterpret_cast<Pipeline*>( reinterpret_cast<char*>( pipelines.data() ) + createInfos.size() * ( sizeof( UniqueHandle<Pipeline, Dispatch> ) - sizeof( Pipeline ) ) );
-    Result result = static_cast<Result>(d.vkCreateRayTracingPipelinesNV( m_device, static_cast<VkPipelineCache>( pipelineCache ), createInfos.size() , reinterpret_cast<const VkRayTracingPipelineCreateInfoNV*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( buffer ) ) );
-    if ( result == VULKAN_HPP_NAMESPACE::Result::eSuccess )
+    std::vector<UniqueHandle<Pipeline, Dispatch>, Allocator> uniquePipelines( vectorAllocator );
+    std::vector<Pipeline> pipelines( createInfos.size() );
+    Result result = static_cast<Result>( d.vkCreateRayTracingPipelinesNV( m_device, static_cast<VkPipelineCache>( pipelineCache ), createInfos.size() , reinterpret_cast<const VkRayTracingPipelineCreateInfoNV*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>(pipelines.data()) ) );
+    if ( ( result == VULKAN_HPP_NAMESPACE::Result::eSuccess ) || ( result == VULKAN_HPP_NAMESPACE::Result::ePipelineCompileRequiredEXT ) )
     {
+      uniquePipelines.reserve( createInfos.size() );
       ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
       for ( size_t i=0 ; i<createInfos.size() ; i++ )
       {
-        pipelines.push_back( UniqueHandle<Pipeline, Dispatch>( buffer[i], deleter ) );
+        uniquePipelines.push_back( UniqueHandle<Pipeline, Dispatch>( pipelines[i], deleter ) );
       }
     }
 
-    return createResultValue( result, pipelines, VULKAN_HPP_NAMESPACE_STRING "::Device::createRayTracingPipelinesNVUnique" );
+    return createResultValue( result, uniquePipelines, VULKAN_HPP_NAMESPACE_STRING "::Device::createRayTracingPipelinesNVUnique", { VULKAN_HPP_NAMESPACE::Result::eSuccess, VULKAN_HPP_NAMESPACE::Result::ePipelineCompileRequiredEXT } );
   }
   template<typename Dispatch>
-  VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<Pipeline,Dispatch>>::type Device::createRayTracingPipelineNVUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const RayTracingPipelineCreateInfoNV & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
+  VULKAN_HPP_INLINE ResultValue<UniqueHandle<Pipeline,Dispatch>> Device::createRayTracingPipelineNVUnique( VULKAN_HPP_NAMESPACE::PipelineCache pipelineCache, const RayTracingPipelineCreateInfoNV & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
   {
     Pipeline pipeline;
     Result result = static_cast<Result>( d.vkCreateRayTracingPipelinesNV( m_device, static_cast<VkPipelineCache>( pipelineCache ), 1 , reinterpret_cast<const VkRayTracingPipelineCreateInfoNV*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkPipeline*>( &pipeline ) ) );
 
     ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
-    return createResultValue<Pipeline,Dispatch>( result, pipeline, VULKAN_HPP_NAMESPACE_STRING"::Device::createRayTracingPipelineNVUnique", deleter );
+    return createResultValue<Pipeline,Dispatch>( result, pipeline, VULKAN_HPP_NAMESPACE_STRING"::Device::createRayTracingPipelineNVUnique", { Result::eSuccess, Result::ePipelineCompileRequiredEXT }, deleter );
   }
 #endif /*VULKAN_HPP_NO_SMART_HANDLE*/
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
@@ -70729,14 +69716,14 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE Result Device::createRenderPass2KHR( const VULKAN_HPP_NAMESPACE::RenderPassCreateInfo2* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::RenderPass* pRenderPass, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    return static_cast<Result>( d.vkCreateRenderPass2( m_device, reinterpret_cast<const VkRenderPassCreateInfo2*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkRenderPass*>( pRenderPass ) ) );
+    return static_cast<Result>( d.vkCreateRenderPass2KHR( m_device, reinterpret_cast<const VkRenderPassCreateInfo2*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkRenderPass*>( pRenderPass ) ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
   VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::RenderPass>::type Device::createRenderPass2KHR( const RenderPassCreateInfo2 & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
   {
     VULKAN_HPP_NAMESPACE::RenderPass renderPass;
-    Result result = static_cast<Result>( d.vkCreateRenderPass2( m_device, reinterpret_cast<const VkRenderPassCreateInfo2*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkRenderPass*>( &renderPass ) ) );
+    Result result = static_cast<Result>( d.vkCreateRenderPass2KHR( m_device, reinterpret_cast<const VkRenderPassCreateInfo2*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkRenderPass*>( &renderPass ) ) );
     return createResultValue( result, renderPass, VULKAN_HPP_NAMESPACE_STRING"::Device::createRenderPass2KHR" );
   }
 #ifndef VULKAN_HPP_NO_SMART_HANDLE
@@ -70744,7 +69731,7 @@
   VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<RenderPass,Dispatch>>::type Device::createRenderPass2KHRUnique( const RenderPassCreateInfo2 & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
   {
     VULKAN_HPP_NAMESPACE::RenderPass renderPass;
-    Result result = static_cast<Result>( d.vkCreateRenderPass2( m_device, reinterpret_cast<const VkRenderPassCreateInfo2*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkRenderPass*>( &renderPass ) ) );
+    Result result = static_cast<Result>( d.vkCreateRenderPass2KHR( m_device, reinterpret_cast<const VkRenderPassCreateInfo2*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkRenderPass*>( &renderPass ) ) );
 
     ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
     return createResultValue<RenderPass,Dispatch>( result, renderPass, VULKAN_HPP_NAMESPACE_STRING"::Device::createRenderPass2KHRUnique", deleter );
@@ -70807,14 +69794,14 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE Result Device::createSamplerYcbcrConversionKHR( const VULKAN_HPP_NAMESPACE::SamplerYcbcrConversionCreateInfo* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::SamplerYcbcrConversion* pYcbcrConversion, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    return static_cast<Result>( d.vkCreateSamplerYcbcrConversion( m_device, reinterpret_cast<const VkSamplerYcbcrConversionCreateInfo*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkSamplerYcbcrConversion*>( pYcbcrConversion ) ) );
+    return static_cast<Result>( d.vkCreateSamplerYcbcrConversionKHR( m_device, reinterpret_cast<const VkSamplerYcbcrConversionCreateInfo*>( pCreateInfo ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ), reinterpret_cast<VkSamplerYcbcrConversion*>( pYcbcrConversion ) ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
   VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::SamplerYcbcrConversion>::type Device::createSamplerYcbcrConversionKHR( const SamplerYcbcrConversionCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
   {
     VULKAN_HPP_NAMESPACE::SamplerYcbcrConversion ycbcrConversion;
-    Result result = static_cast<Result>( d.vkCreateSamplerYcbcrConversion( m_device, reinterpret_cast<const VkSamplerYcbcrConversionCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSamplerYcbcrConversion*>( &ycbcrConversion ) ) );
+    Result result = static_cast<Result>( d.vkCreateSamplerYcbcrConversionKHR( m_device, reinterpret_cast<const VkSamplerYcbcrConversionCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSamplerYcbcrConversion*>( &ycbcrConversion ) ) );
     return createResultValue( result, ycbcrConversion, VULKAN_HPP_NAMESPACE_STRING"::Device::createSamplerYcbcrConversionKHR" );
   }
 #ifndef VULKAN_HPP_NO_SMART_HANDLE
@@ -70822,7 +69809,7 @@
   VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<SamplerYcbcrConversion,Dispatch>>::type Device::createSamplerYcbcrConversionKHRUnique( const SamplerYcbcrConversionCreateInfo & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
   {
     VULKAN_HPP_NAMESPACE::SamplerYcbcrConversion ycbcrConversion;
-    Result result = static_cast<Result>( d.vkCreateSamplerYcbcrConversion( m_device, reinterpret_cast<const VkSamplerYcbcrConversionCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSamplerYcbcrConversion*>( &ycbcrConversion ) ) );
+    Result result = static_cast<Result>( d.vkCreateSamplerYcbcrConversionKHR( m_device, reinterpret_cast<const VkSamplerYcbcrConversionCreateInfo*>( &createInfo ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSamplerYcbcrConversion*>( &ycbcrConversion ) ) );
 
     ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
     return createResultValue<SamplerYcbcrConversion,Dispatch>( result, ycbcrConversion, VULKAN_HPP_NAMESPACE_STRING"::Device::createSamplerYcbcrConversionKHRUnique", deleter );
@@ -70913,40 +69900,38 @@
   template<typename Allocator, typename Dispatch>
   VULKAN_HPP_INLINE typename ResultValueType<std::vector<UniqueHandle<SwapchainKHR,Dispatch>,Allocator>>::type Device::createSharedSwapchainsKHRUnique( ArrayProxy<const VULKAN_HPP_NAMESPACE::SwapchainCreateInfoKHR> createInfos, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
   {
-    static_assert( sizeof( SwapchainKHR ) <= sizeof( UniqueHandle<SwapchainKHR, Dispatch> ), "SwapchainKHR is greater than UniqueHandle<SwapchainKHR, Dispatch>!" );
-    std::vector<UniqueHandle<SwapchainKHR, Dispatch>, Allocator> swapchainKHRs;
-    swapchainKHRs.reserve( createInfos.size() );
-    SwapchainKHR* buffer = reinterpret_cast<SwapchainKHR*>( reinterpret_cast<char*>( swapchainKHRs.data() ) + createInfos.size() * ( sizeof( UniqueHandle<SwapchainKHR, Dispatch> ) - sizeof( SwapchainKHR ) ) );
-    Result result = static_cast<Result>(d.vkCreateSharedSwapchainsKHR( m_device, createInfos.size() , reinterpret_cast<const VkSwapchainCreateInfoKHR*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSwapchainKHR*>( buffer ) ) );
+    std::vector<UniqueHandle<SwapchainKHR, Dispatch>, Allocator> uniqueSwapchainKHRs;
+    std::vector<SwapchainKHR> swapchainKHRs( createInfos.size() );
+    Result result = static_cast<Result>( d.vkCreateSharedSwapchainsKHR( m_device, createInfos.size() , reinterpret_cast<const VkSwapchainCreateInfoKHR*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSwapchainKHR*>(swapchainKHRs.data()) ) );
     if ( result == VULKAN_HPP_NAMESPACE::Result::eSuccess )
     {
+      uniqueSwapchainKHRs.reserve( createInfos.size() );
       ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
       for ( size_t i=0 ; i<createInfos.size() ; i++ )
       {
-        swapchainKHRs.push_back( UniqueHandle<SwapchainKHR, Dispatch>( buffer[i], deleter ) );
+        uniqueSwapchainKHRs.push_back( UniqueHandle<SwapchainKHR, Dispatch>( swapchainKHRs[i], deleter ) );
       }
     }
 
-    return createResultValue( result, swapchainKHRs, VULKAN_HPP_NAMESPACE_STRING "::Device::createSharedSwapchainsKHRUnique" );
+    return createResultValue( result, uniqueSwapchainKHRs, VULKAN_HPP_NAMESPACE_STRING "::Device::createSharedSwapchainsKHRUnique" );
   }
   template<typename Allocator, typename Dispatch>
   VULKAN_HPP_INLINE typename ResultValueType<std::vector<UniqueHandle<SwapchainKHR,Dispatch>,Allocator>>::type Device::createSharedSwapchainsKHRUnique( ArrayProxy<const VULKAN_HPP_NAMESPACE::SwapchainCreateInfoKHR> createInfos, Optional<const AllocationCallbacks> allocator, Allocator const& vectorAllocator, Dispatch const &d ) const
   {
-    static_assert( sizeof( SwapchainKHR ) <= sizeof( UniqueHandle<SwapchainKHR, Dispatch> ), "SwapchainKHR is greater than UniqueHandle<SwapchainKHR, Dispatch>!" );
-    std::vector<UniqueHandle<SwapchainKHR, Dispatch>, Allocator> swapchainKHRs( vectorAllocator );
-    swapchainKHRs.reserve( createInfos.size() );
-    SwapchainKHR* buffer = reinterpret_cast<SwapchainKHR*>( reinterpret_cast<char*>( swapchainKHRs.data() ) + createInfos.size() * ( sizeof( UniqueHandle<SwapchainKHR, Dispatch> ) - sizeof( SwapchainKHR ) ) );
-    Result result = static_cast<Result>(d.vkCreateSharedSwapchainsKHR( m_device, createInfos.size() , reinterpret_cast<const VkSwapchainCreateInfoKHR*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSwapchainKHR*>( buffer ) ) );
+    std::vector<UniqueHandle<SwapchainKHR, Dispatch>, Allocator> uniqueSwapchainKHRs( vectorAllocator );
+    std::vector<SwapchainKHR> swapchainKHRs( createInfos.size() );
+    Result result = static_cast<Result>( d.vkCreateSharedSwapchainsKHR( m_device, createInfos.size() , reinterpret_cast<const VkSwapchainCreateInfoKHR*>( createInfos.data() ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ), reinterpret_cast<VkSwapchainKHR*>(swapchainKHRs.data()) ) );
     if ( result == VULKAN_HPP_NAMESPACE::Result::eSuccess )
     {
+      uniqueSwapchainKHRs.reserve( createInfos.size() );
       ObjectDestroy<Device,Dispatch> deleter( *this, allocator, d );
       for ( size_t i=0 ; i<createInfos.size() ; i++ )
       {
-        swapchainKHRs.push_back( UniqueHandle<SwapchainKHR, Dispatch>( buffer[i], deleter ) );
+        uniqueSwapchainKHRs.push_back( UniqueHandle<SwapchainKHR, Dispatch>( swapchainKHRs[i], deleter ) );
       }
     }
 
-    return createResultValue( result, swapchainKHRs, VULKAN_HPP_NAMESPACE_STRING "::Device::createSharedSwapchainsKHRUnique" );
+    return createResultValue( result, uniqueSwapchainKHRs, VULKAN_HPP_NAMESPACE_STRING "::Device::createSharedSwapchainsKHRUnique" );
   }
   template<typename Dispatch>
   VULKAN_HPP_INLINE typename ResultValueType<UniqueHandle<SwapchainKHR,Dispatch>>::type Device::createSharedSwapchainKHRUnique( const SwapchainCreateInfoKHR & createInfo, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const
@@ -71040,29 +70025,59 @@
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
-  VULKAN_HPP_INLINE void Device::destroyAccelerationStructureNV( VULKAN_HPP_NAMESPACE::AccelerationStructureNV accelerationStructure, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  VULKAN_HPP_INLINE Result Device::deferredOperationJoinKHR( VULKAN_HPP_NAMESPACE::DeferredOperationKHR operation, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkDestroyAccelerationStructureNV( m_device, static_cast<VkAccelerationStructureNV>( accelerationStructure ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+    return static_cast<Result>( d.vkDeferredOperationJoinKHR( m_device, static_cast<VkDeferredOperationKHR>( operation ) ) );
+  }
+#else
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE Result Device::deferredOperationJoinKHR( VULKAN_HPP_NAMESPACE::DeferredOperationKHR operation, Dispatch const &d ) const
+  {
+    Result result = static_cast<Result>( d.vkDeferredOperationJoinKHR( m_device, static_cast<VkDeferredOperationKHR>( operation ) ) );
+    return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::deferredOperationJoinKHR", { Result::eSuccess, Result::eThreadDoneKHR, Result::eThreadIdleKHR } );
+  }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE void Device::destroyAccelerationStructureKHR( VULKAN_HPP_NAMESPACE::AccelerationStructureKHR accelerationStructure, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  {
+    d.vkDestroyAccelerationStructureKHR( m_device, static_cast<VkAccelerationStructureKHR>( accelerationStructure ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
-  VULKAN_HPP_INLINE void Device::destroyAccelerationStructureNV( VULKAN_HPP_NAMESPACE::AccelerationStructureNV accelerationStructure, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+  VULKAN_HPP_INLINE void Device::destroyAccelerationStructureKHR( VULKAN_HPP_NAMESPACE::AccelerationStructureKHR accelerationStructure, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkDestroyAccelerationStructureNV( m_device, static_cast<VkAccelerationStructureNV>( accelerationStructure ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+    d.vkDestroyAccelerationStructureKHR( m_device, static_cast<VkAccelerationStructureKHR>( accelerationStructure ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
   template<typename Dispatch>
-  VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::AccelerationStructureNV accelerationStructure, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  VULKAN_HPP_INLINE void Device::destroyAccelerationStructureNV( VULKAN_HPP_NAMESPACE::AccelerationStructureKHR accelerationStructure, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkDestroyAccelerationStructureNV( m_device, static_cast<VkAccelerationStructureNV>( accelerationStructure ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+    d.vkDestroyAccelerationStructureNV( m_device, static_cast<VkAccelerationStructureKHR>( accelerationStructure ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
-  VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::AccelerationStructureNV accelerationStructure, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+  VULKAN_HPP_INLINE void Device::destroyAccelerationStructureNV( VULKAN_HPP_NAMESPACE::AccelerationStructureKHR accelerationStructure, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkDestroyAccelerationStructureNV( m_device, static_cast<VkAccelerationStructureNV>( accelerationStructure ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+    d.vkDestroyAccelerationStructureNV( m_device, static_cast<VkAccelerationStructureKHR>( accelerationStructure ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+  }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::AccelerationStructureKHR accelerationStructure, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  {
+    d.vkDestroyAccelerationStructureKHR( m_device, static_cast<VkAccelerationStructureKHR>( accelerationStructure ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+  }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::AccelerationStructureKHR accelerationStructure, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+  {
+    d.vkDestroyAccelerationStructureKHR( m_device, static_cast<VkAccelerationStructureKHR>( accelerationStructure ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
@@ -71144,6 +70159,34 @@
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE void Device::destroyDeferredOperationKHR( VULKAN_HPP_NAMESPACE::DeferredOperationKHR operation, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  {
+    d.vkDestroyDeferredOperationKHR( m_device, static_cast<VkDeferredOperationKHR>( operation ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+  }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE void Device::destroyDeferredOperationKHR( VULKAN_HPP_NAMESPACE::DeferredOperationKHR operation, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+  {
+    d.vkDestroyDeferredOperationKHR( m_device, static_cast<VkDeferredOperationKHR>( operation ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+  }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::DeferredOperationKHR operation, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  {
+    d.vkDestroyDeferredOperationKHR( m_device, static_cast<VkDeferredOperationKHR>( operation ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+  }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::DeferredOperationKHR operation, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+  {
+    d.vkDestroyDeferredOperationKHR( m_device, static_cast<VkDeferredOperationKHR>( operation ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+  }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
   template<typename Dispatch>
   VULKAN_HPP_INLINE void Device::destroyDescriptorPool( VULKAN_HPP_NAMESPACE::DescriptorPool descriptorPool, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
@@ -71212,13 +70255,13 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE void Device::destroyDescriptorUpdateTemplateKHR( VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate descriptorUpdateTemplate, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkDestroyDescriptorUpdateTemplate( m_device, static_cast<VkDescriptorUpdateTemplate>( descriptorUpdateTemplate ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+    d.vkDestroyDescriptorUpdateTemplateKHR( m_device, static_cast<VkDescriptorUpdateTemplate>( descriptorUpdateTemplate ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
   VULKAN_HPP_INLINE void Device::destroyDescriptorUpdateTemplateKHR( VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate descriptorUpdateTemplate, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkDestroyDescriptorUpdateTemplate( m_device, static_cast<VkDescriptorUpdateTemplate>( descriptorUpdateTemplate ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+    d.vkDestroyDescriptorUpdateTemplateKHR( m_device, static_cast<VkDescriptorUpdateTemplate>( descriptorUpdateTemplate ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
@@ -71379,54 +70422,28 @@
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
   template<typename Dispatch>
-  VULKAN_HPP_INLINE void Device::destroyIndirectCommandsLayoutNVX( VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNVX indirectCommandsLayout, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  VULKAN_HPP_INLINE void Device::destroyIndirectCommandsLayoutNV( VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNV indirectCommandsLayout, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkDestroyIndirectCommandsLayoutNVX( m_device, static_cast<VkIndirectCommandsLayoutNVX>( indirectCommandsLayout ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+    d.vkDestroyIndirectCommandsLayoutNV( m_device, static_cast<VkIndirectCommandsLayoutNV>( indirectCommandsLayout ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
-  VULKAN_HPP_INLINE void Device::destroyIndirectCommandsLayoutNVX( VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNVX indirectCommandsLayout, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+  VULKAN_HPP_INLINE void Device::destroyIndirectCommandsLayoutNV( VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNV indirectCommandsLayout, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkDestroyIndirectCommandsLayoutNVX( m_device, static_cast<VkIndirectCommandsLayoutNVX>( indirectCommandsLayout ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+    d.vkDestroyIndirectCommandsLayoutNV( m_device, static_cast<VkIndirectCommandsLayoutNV>( indirectCommandsLayout ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
   template<typename Dispatch>
-  VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNVX indirectCommandsLayout, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNV indirectCommandsLayout, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkDestroyIndirectCommandsLayoutNVX( m_device, static_cast<VkIndirectCommandsLayoutNVX>( indirectCommandsLayout ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+    d.vkDestroyIndirectCommandsLayoutNV( m_device, static_cast<VkIndirectCommandsLayoutNV>( indirectCommandsLayout ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
-  VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNVX indirectCommandsLayout, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+  VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::IndirectCommandsLayoutNV indirectCommandsLayout, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkDestroyIndirectCommandsLayoutNVX( m_device, static_cast<VkIndirectCommandsLayoutNVX>( indirectCommandsLayout ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
-  }
-#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
-
-  template<typename Dispatch>
-  VULKAN_HPP_INLINE void Device::destroyObjectTableNVX( VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
-  {
-    d.vkDestroyObjectTableNVX( m_device, static_cast<VkObjectTableNVX>( objectTable ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
-  }
-#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
-  template<typename Dispatch>
-  VULKAN_HPP_INLINE void Device::destroyObjectTableNVX( VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
-  {
-    d.vkDestroyObjectTableNVX( m_device, static_cast<VkObjectTableNVX>( objectTable ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
-  }
-#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
-
-  template<typename Dispatch>
-  VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
-  {
-    d.vkDestroyObjectTableNVX( m_device, static_cast<VkObjectTableNVX>( objectTable ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
-  }
-#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
-  template<typename Dispatch>
-  VULKAN_HPP_INLINE void Device::destroy( VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
-  {
-    d.vkDestroyObjectTableNVX( m_device, static_cast<VkObjectTableNVX>( objectTable ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+    d.vkDestroyIndirectCommandsLayoutNV( m_device, static_cast<VkIndirectCommandsLayoutNV>( indirectCommandsLayout ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
@@ -71602,13 +70619,13 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE void Device::destroySamplerYcbcrConversionKHR( VULKAN_HPP_NAMESPACE::SamplerYcbcrConversion ycbcrConversion, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkDestroySamplerYcbcrConversion( m_device, static_cast<VkSamplerYcbcrConversion>( ycbcrConversion ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
+    d.vkDestroySamplerYcbcrConversionKHR( m_device, static_cast<VkSamplerYcbcrConversion>( ycbcrConversion ), reinterpret_cast<const VkAllocationCallbacks*>( pAllocator ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
   VULKAN_HPP_INLINE void Device::destroySamplerYcbcrConversionKHR( VULKAN_HPP_NAMESPACE::SamplerYcbcrConversion ycbcrConversion, Optional<const AllocationCallbacks> allocator, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkDestroySamplerYcbcrConversion( m_device, static_cast<VkSamplerYcbcrConversion>( ycbcrConversion ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
+    d.vkDestroySamplerYcbcrConversionKHR( m_device, static_cast<VkSamplerYcbcrConversion>( ycbcrConversion ), reinterpret_cast<const VkAllocationCallbacks*>( static_cast<const AllocationCallbacks*>( allocator ) ) );
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
@@ -71852,20 +70869,60 @@
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
   template<typename Dispatch>
-  VULKAN_HPP_INLINE Result Device::getAccelerationStructureHandleNV( VULKAN_HPP_NAMESPACE::AccelerationStructureNV accelerationStructure, size_t dataSize, void* pData, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  VULKAN_HPP_INLINE DeviceAddress Device::getAccelerationStructureAddressKHR( const VULKAN_HPP_NAMESPACE::AccelerationStructureDeviceAddressInfoKHR* pInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    return static_cast<Result>( d.vkGetAccelerationStructureHandleNV( m_device, static_cast<VkAccelerationStructureNV>( accelerationStructure ), dataSize, pData ) );
+    return static_cast<DeviceAddress>( d.vkGetAccelerationStructureDeviceAddressKHR( m_device, reinterpret_cast<const VkAccelerationStructureDeviceAddressInfoKHR*>( pInfo ) ) );
+  }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE DeviceAddress Device::getAccelerationStructureAddressKHR( const AccelerationStructureDeviceAddressInfoKHR & info, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+  {
+    return d.vkGetAccelerationStructureDeviceAddressKHR( m_device, reinterpret_cast<const VkAccelerationStructureDeviceAddressInfoKHR*>( &info ) );
+  }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE Result Device::getAccelerationStructureHandleNV( VULKAN_HPP_NAMESPACE::AccelerationStructureKHR accelerationStructure, size_t dataSize, void* pData, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  {
+    return static_cast<Result>( d.vkGetAccelerationStructureHandleNV( m_device, static_cast<VkAccelerationStructureKHR>( accelerationStructure ), dataSize, pData ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename T, typename Dispatch>
-  VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::getAccelerationStructureHandleNV( VULKAN_HPP_NAMESPACE::AccelerationStructureNV accelerationStructure, ArrayProxy<T> data, Dispatch const &d ) const
+  VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::getAccelerationStructureHandleNV( VULKAN_HPP_NAMESPACE::AccelerationStructureKHR accelerationStructure, ArrayProxy<T> data, Dispatch const &d ) const
   {
-    Result result = static_cast<Result>( d.vkGetAccelerationStructureHandleNV( m_device, static_cast<VkAccelerationStructureNV>( accelerationStructure ), data.size() * sizeof( T ) , reinterpret_cast<void*>( data.data() ) ) );
+    Result result = static_cast<Result>( d.vkGetAccelerationStructureHandleNV( m_device, static_cast<VkAccelerationStructureKHR>( accelerationStructure ), data.size() * sizeof( T ) , reinterpret_cast<void*>( data.data() ) ) );
     return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::getAccelerationStructureHandleNV" );
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE void Device::getAccelerationStructureMemoryRequirementsKHR( const VULKAN_HPP_NAMESPACE::AccelerationStructureMemoryRequirementsInfoKHR* pInfo, VULKAN_HPP_NAMESPACE::MemoryRequirements2* pMemoryRequirements, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  {
+    d.vkGetAccelerationStructureMemoryRequirementsKHR( m_device, reinterpret_cast<const VkAccelerationStructureMemoryRequirementsInfoKHR*>( pInfo ), reinterpret_cast<VkMemoryRequirements2*>( pMemoryRequirements ) );
+  }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::MemoryRequirements2 Device::getAccelerationStructureMemoryRequirementsKHR( const AccelerationStructureMemoryRequirementsInfoKHR & info, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+  {
+    VULKAN_HPP_NAMESPACE::MemoryRequirements2 memoryRequirements;
+    d.vkGetAccelerationStructureMemoryRequirementsKHR( m_device, reinterpret_cast<const VkAccelerationStructureMemoryRequirementsInfoKHR*>( &info ), reinterpret_cast<VkMemoryRequirements2*>( &memoryRequirements ) );
+    return memoryRequirements;
+  }
+  template<typename X, typename Y, typename ...Z, typename Dispatch>
+  VULKAN_HPP_INLINE StructureChain<X, Y, Z...> Device::getAccelerationStructureMemoryRequirementsKHR( const AccelerationStructureMemoryRequirementsInfoKHR & info, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+  {
+    StructureChain<X, Y, Z...> structureChain;
+    VULKAN_HPP_NAMESPACE::MemoryRequirements2& memoryRequirements = structureChain.template get<VULKAN_HPP_NAMESPACE::MemoryRequirements2>();
+    d.vkGetAccelerationStructureMemoryRequirementsKHR( m_device, reinterpret_cast<const VkAccelerationStructureMemoryRequirementsInfoKHR*>( &info ), reinterpret_cast<VkMemoryRequirements2*>( &memoryRequirements ) );
+    return structureChain;
+  }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
   template<typename Dispatch>
   VULKAN_HPP_INLINE void Device::getAccelerationStructureMemoryRequirementsNV( const VULKAN_HPP_NAMESPACE::AccelerationStructureMemoryRequirementsInfoNV* pInfo, VULKAN_HPP_NAMESPACE::MemoryRequirements2KHR* pMemoryRequirements, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
@@ -71930,26 +70987,26 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE DeviceAddress Device::getBufferAddressEXT( const VULKAN_HPP_NAMESPACE::BufferDeviceAddressInfo* pInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    return static_cast<DeviceAddress>( d.vkGetBufferDeviceAddress( m_device, reinterpret_cast<const VkBufferDeviceAddressInfo*>( pInfo ) ) );
+    return static_cast<DeviceAddress>( d.vkGetBufferDeviceAddressEXT( m_device, reinterpret_cast<const VkBufferDeviceAddressInfo*>( pInfo ) ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
   VULKAN_HPP_INLINE DeviceAddress Device::getBufferAddressEXT( const BufferDeviceAddressInfo & info, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
   {
-    return d.vkGetBufferDeviceAddress( m_device, reinterpret_cast<const VkBufferDeviceAddressInfo*>( &info ) );
+    return d.vkGetBufferDeviceAddressEXT( m_device, reinterpret_cast<const VkBufferDeviceAddressInfo*>( &info ) );
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
   template<typename Dispatch>
   VULKAN_HPP_INLINE DeviceAddress Device::getBufferAddressKHR( const VULKAN_HPP_NAMESPACE::BufferDeviceAddressInfo* pInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    return static_cast<DeviceAddress>( d.vkGetBufferDeviceAddress( m_device, reinterpret_cast<const VkBufferDeviceAddressInfo*>( pInfo ) ) );
+    return static_cast<DeviceAddress>( d.vkGetBufferDeviceAddressKHR( m_device, reinterpret_cast<const VkBufferDeviceAddressInfo*>( pInfo ) ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
   VULKAN_HPP_INLINE DeviceAddress Device::getBufferAddressKHR( const BufferDeviceAddressInfo & info, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
   {
-    return d.vkGetBufferDeviceAddress( m_device, reinterpret_cast<const VkBufferDeviceAddressInfo*>( &info ) );
+    return d.vkGetBufferDeviceAddressKHR( m_device, reinterpret_cast<const VkBufferDeviceAddressInfo*>( &info ) );
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
@@ -71994,14 +71051,14 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE void Device::getBufferMemoryRequirements2KHR( const VULKAN_HPP_NAMESPACE::BufferMemoryRequirementsInfo2* pInfo, VULKAN_HPP_NAMESPACE::MemoryRequirements2* pMemoryRequirements, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkGetBufferMemoryRequirements2( m_device, reinterpret_cast<const VkBufferMemoryRequirementsInfo2*>( pInfo ), reinterpret_cast<VkMemoryRequirements2*>( pMemoryRequirements ) );
+    d.vkGetBufferMemoryRequirements2KHR( m_device, reinterpret_cast<const VkBufferMemoryRequirementsInfo2*>( pInfo ), reinterpret_cast<VkMemoryRequirements2*>( pMemoryRequirements ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
   VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::MemoryRequirements2 Device::getBufferMemoryRequirements2KHR( const BufferMemoryRequirementsInfo2 & info, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
   {
     VULKAN_HPP_NAMESPACE::MemoryRequirements2 memoryRequirements;
-    d.vkGetBufferMemoryRequirements2( m_device, reinterpret_cast<const VkBufferMemoryRequirementsInfo2*>( &info ), reinterpret_cast<VkMemoryRequirements2*>( &memoryRequirements ) );
+    d.vkGetBufferMemoryRequirements2KHR( m_device, reinterpret_cast<const VkBufferMemoryRequirementsInfo2*>( &info ), reinterpret_cast<VkMemoryRequirements2*>( &memoryRequirements ) );
     return memoryRequirements;
   }
   template<typename X, typename Y, typename ...Z, typename Dispatch>
@@ -72009,7 +71066,7 @@
   {
     StructureChain<X, Y, Z...> structureChain;
     VULKAN_HPP_NAMESPACE::MemoryRequirements2& memoryRequirements = structureChain.template get<VULKAN_HPP_NAMESPACE::MemoryRequirements2>();
-    d.vkGetBufferMemoryRequirements2( m_device, reinterpret_cast<const VkBufferMemoryRequirementsInfo2*>( &info ), reinterpret_cast<VkMemoryRequirements2*>( &memoryRequirements ) );
+    d.vkGetBufferMemoryRequirements2KHR( m_device, reinterpret_cast<const VkBufferMemoryRequirementsInfo2*>( &info ), reinterpret_cast<VkMemoryRequirements2*>( &memoryRequirements ) );
     return structureChain;
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
@@ -72030,13 +71087,13 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE uint64_t Device::getBufferOpaqueCaptureAddressKHR( const VULKAN_HPP_NAMESPACE::BufferDeviceAddressInfo* pInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    return d.vkGetBufferOpaqueCaptureAddress( m_device, reinterpret_cast<const VkBufferDeviceAddressInfo*>( pInfo ) );
+    return d.vkGetBufferOpaqueCaptureAddressKHR( m_device, reinterpret_cast<const VkBufferDeviceAddressInfo*>( pInfo ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
   VULKAN_HPP_INLINE uint64_t Device::getBufferOpaqueCaptureAddressKHR( const BufferDeviceAddressInfo & info, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
   {
-    return d.vkGetBufferOpaqueCaptureAddress( m_device, reinterpret_cast<const VkBufferDeviceAddressInfo*>( &info ) );
+    return d.vkGetBufferOpaqueCaptureAddressKHR( m_device, reinterpret_cast<const VkBufferDeviceAddressInfo*>( &info ) );
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
@@ -72063,6 +71120,39 @@
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE uint32_t Device::getDeferredOperationMaxConcurrencyKHR( VULKAN_HPP_NAMESPACE::DeferredOperationKHR operation, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  {
+    return d.vkGetDeferredOperationMaxConcurrencyKHR( m_device, static_cast<VkDeferredOperationKHR>( operation ) );
+  }
+#else
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE uint32_t Device::getDeferredOperationMaxConcurrencyKHR( VULKAN_HPP_NAMESPACE::DeferredOperationKHR operation, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+  {
+    return d.vkGetDeferredOperationMaxConcurrencyKHR( m_device, static_cast<VkDeferredOperationKHR>( operation ) );
+  }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+#ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE Result Device::getDeferredOperationResultKHR( VULKAN_HPP_NAMESPACE::DeferredOperationKHR operation, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  {
+    return static_cast<Result>( d.vkGetDeferredOperationResultKHR( m_device, static_cast<VkDeferredOperationKHR>( operation ) ) );
+  }
+#else
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE Result Device::getDeferredOperationResultKHR( VULKAN_HPP_NAMESPACE::DeferredOperationKHR operation, Dispatch const &d ) const
+  {
+    Result result = static_cast<Result>( d.vkGetDeferredOperationResultKHR( m_device, static_cast<VkDeferredOperationKHR>( operation ) ) );
+    return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::getDeferredOperationResultKHR", { Result::eSuccess, Result::eNotReady } );
+  }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
   template<typename Dispatch>
   VULKAN_HPP_INLINE void Device::getDescriptorSetLayoutSupport( const VULKAN_HPP_NAMESPACE::DescriptorSetLayoutCreateInfo* pCreateInfo, VULKAN_HPP_NAMESPACE::DescriptorSetLayoutSupport* pSupport, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
@@ -72089,14 +71179,14 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE void Device::getDescriptorSetLayoutSupportKHR( const VULKAN_HPP_NAMESPACE::DescriptorSetLayoutCreateInfo* pCreateInfo, VULKAN_HPP_NAMESPACE::DescriptorSetLayoutSupport* pSupport, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkGetDescriptorSetLayoutSupport( m_device, reinterpret_cast<const VkDescriptorSetLayoutCreateInfo*>( pCreateInfo ), reinterpret_cast<VkDescriptorSetLayoutSupport*>( pSupport ) );
+    d.vkGetDescriptorSetLayoutSupportKHR( m_device, reinterpret_cast<const VkDescriptorSetLayoutCreateInfo*>( pCreateInfo ), reinterpret_cast<VkDescriptorSetLayoutSupport*>( pSupport ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
   VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::DescriptorSetLayoutSupport Device::getDescriptorSetLayoutSupportKHR( const DescriptorSetLayoutCreateInfo & createInfo, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
   {
     VULKAN_HPP_NAMESPACE::DescriptorSetLayoutSupport support;
-    d.vkGetDescriptorSetLayoutSupport( m_device, reinterpret_cast<const VkDescriptorSetLayoutCreateInfo*>( &createInfo ), reinterpret_cast<VkDescriptorSetLayoutSupport*>( &support ) );
+    d.vkGetDescriptorSetLayoutSupportKHR( m_device, reinterpret_cast<const VkDescriptorSetLayoutCreateInfo*>( &createInfo ), reinterpret_cast<VkDescriptorSetLayoutSupport*>( &support ) );
     return support;
   }
   template<typename X, typename Y, typename ...Z, typename Dispatch>
@@ -72104,11 +71194,27 @@
   {
     StructureChain<X, Y, Z...> structureChain;
     VULKAN_HPP_NAMESPACE::DescriptorSetLayoutSupport& support = structureChain.template get<VULKAN_HPP_NAMESPACE::DescriptorSetLayoutSupport>();
-    d.vkGetDescriptorSetLayoutSupport( m_device, reinterpret_cast<const VkDescriptorSetLayoutCreateInfo*>( &createInfo ), reinterpret_cast<VkDescriptorSetLayoutSupport*>( &support ) );
+    d.vkGetDescriptorSetLayoutSupportKHR( m_device, reinterpret_cast<const VkDescriptorSetLayoutCreateInfo*>( &createInfo ), reinterpret_cast<VkDescriptorSetLayoutSupport*>( &support ) );
     return structureChain;
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE Result Device::getAccelerationStructureCompatibilityKHR( const VULKAN_HPP_NAMESPACE::AccelerationStructureVersionKHR* version, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  {
+    return static_cast<Result>( d.vkGetDeviceAccelerationStructureCompatibilityKHR( m_device, reinterpret_cast<const VkAccelerationStructureVersionKHR*>( version ) ) );
+  }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::getAccelerationStructureCompatibilityKHR( const AccelerationStructureVersionKHR & version, Dispatch const &d ) const
+  {
+    Result result = static_cast<Result>( d.vkGetDeviceAccelerationStructureCompatibilityKHR( m_device, reinterpret_cast<const VkAccelerationStructureVersionKHR*>( &version ) ) );
+    return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::getAccelerationStructureCompatibilityKHR" );
+  }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
   template<typename Dispatch>
   VULKAN_HPP_INLINE void Device::getGroupPeerMemoryFeatures( uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VULKAN_HPP_NAMESPACE::PeerMemoryFeatureFlags* pPeerMemoryFeatures, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
@@ -72127,14 +71233,14 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE void Device::getGroupPeerMemoryFeaturesKHR( uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VULKAN_HPP_NAMESPACE::PeerMemoryFeatureFlags* pPeerMemoryFeatures, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkGetDeviceGroupPeerMemoryFeatures( m_device, heapIndex, localDeviceIndex, remoteDeviceIndex, reinterpret_cast<VkPeerMemoryFeatureFlags*>( pPeerMemoryFeatures ) );
+    d.vkGetDeviceGroupPeerMemoryFeaturesKHR( m_device, heapIndex, localDeviceIndex, remoteDeviceIndex, reinterpret_cast<VkPeerMemoryFeatureFlags*>( pPeerMemoryFeatures ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
   VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::PeerMemoryFeatureFlags Device::getGroupPeerMemoryFeaturesKHR( uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
   {
     VULKAN_HPP_NAMESPACE::PeerMemoryFeatureFlags peerMemoryFeatures;
-    d.vkGetDeviceGroupPeerMemoryFeatures( m_device, heapIndex, localDeviceIndex, remoteDeviceIndex, reinterpret_cast<VkPeerMemoryFeatureFlags*>( &peerMemoryFeatures ) );
+    d.vkGetDeviceGroupPeerMemoryFeaturesKHR( m_device, heapIndex, localDeviceIndex, remoteDeviceIndex, reinterpret_cast<VkPeerMemoryFeatureFlags*>( &peerMemoryFeatures ) );
     return peerMemoryFeatures;
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
@@ -72217,13 +71323,13 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE uint64_t Device::getMemoryOpaqueCaptureAddressKHR( const VULKAN_HPP_NAMESPACE::DeviceMemoryOpaqueCaptureAddressInfo* pInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    return d.vkGetDeviceMemoryOpaqueCaptureAddress( m_device, reinterpret_cast<const VkDeviceMemoryOpaqueCaptureAddressInfo*>( pInfo ) );
+    return d.vkGetDeviceMemoryOpaqueCaptureAddressKHR( m_device, reinterpret_cast<const VkDeviceMemoryOpaqueCaptureAddressInfo*>( pInfo ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
   VULKAN_HPP_INLINE uint64_t Device::getMemoryOpaqueCaptureAddressKHR( const DeviceMemoryOpaqueCaptureAddressInfo & info, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
   {
-    return d.vkGetDeviceMemoryOpaqueCaptureAddress( m_device, reinterpret_cast<const VkDeviceMemoryOpaqueCaptureAddressInfo*>( &info ) );
+    return d.vkGetDeviceMemoryOpaqueCaptureAddressKHR( m_device, reinterpret_cast<const VkDeviceMemoryOpaqueCaptureAddressInfo*>( &info ) );
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
@@ -72333,6 +71439,29 @@
 #endif /*VK_USE_PLATFORM_WIN32_KHR*/
 
   template<typename Dispatch>
+  VULKAN_HPP_INLINE void Device::getGeneratedCommandsMemoryRequirementsNV( const VULKAN_HPP_NAMESPACE::GeneratedCommandsMemoryRequirementsInfoNV* pInfo, VULKAN_HPP_NAMESPACE::MemoryRequirements2* pMemoryRequirements, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  {
+    d.vkGetGeneratedCommandsMemoryRequirementsNV( m_device, reinterpret_cast<const VkGeneratedCommandsMemoryRequirementsInfoNV*>( pInfo ), reinterpret_cast<VkMemoryRequirements2*>( pMemoryRequirements ) );
+  }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::MemoryRequirements2 Device::getGeneratedCommandsMemoryRequirementsNV( const GeneratedCommandsMemoryRequirementsInfoNV & info, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+  {
+    VULKAN_HPP_NAMESPACE::MemoryRequirements2 memoryRequirements;
+    d.vkGetGeneratedCommandsMemoryRequirementsNV( m_device, reinterpret_cast<const VkGeneratedCommandsMemoryRequirementsInfoNV*>( &info ), reinterpret_cast<VkMemoryRequirements2*>( &memoryRequirements ) );
+    return memoryRequirements;
+  }
+  template<typename X, typename Y, typename ...Z, typename Dispatch>
+  VULKAN_HPP_INLINE StructureChain<X, Y, Z...> Device::getGeneratedCommandsMemoryRequirementsNV( const GeneratedCommandsMemoryRequirementsInfoNV & info, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
+  {
+    StructureChain<X, Y, Z...> structureChain;
+    VULKAN_HPP_NAMESPACE::MemoryRequirements2& memoryRequirements = structureChain.template get<VULKAN_HPP_NAMESPACE::MemoryRequirements2>();
+    d.vkGetGeneratedCommandsMemoryRequirementsNV( m_device, reinterpret_cast<const VkGeneratedCommandsMemoryRequirementsInfoNV*>( &info ), reinterpret_cast<VkMemoryRequirements2*>( &memoryRequirements ) );
+    return structureChain;
+  }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+  template<typename Dispatch>
   VULKAN_HPP_INLINE Result Device::getImageDrmFormatModifierPropertiesEXT( VULKAN_HPP_NAMESPACE::Image image, VULKAN_HPP_NAMESPACE::ImageDrmFormatModifierPropertiesEXT* pProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
     return static_cast<Result>( d.vkGetImageDrmFormatModifierPropertiesEXT( m_device, static_cast<VkImage>( image ), reinterpret_cast<VkImageDrmFormatModifierPropertiesEXT*>( pProperties ) ) );
@@ -72388,14 +71517,14 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE void Device::getImageMemoryRequirements2KHR( const VULKAN_HPP_NAMESPACE::ImageMemoryRequirementsInfo2* pInfo, VULKAN_HPP_NAMESPACE::MemoryRequirements2* pMemoryRequirements, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkGetImageMemoryRequirements2( m_device, reinterpret_cast<const VkImageMemoryRequirementsInfo2*>( pInfo ), reinterpret_cast<VkMemoryRequirements2*>( pMemoryRequirements ) );
+    d.vkGetImageMemoryRequirements2KHR( m_device, reinterpret_cast<const VkImageMemoryRequirementsInfo2*>( pInfo ), reinterpret_cast<VkMemoryRequirements2*>( pMemoryRequirements ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
   VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::MemoryRequirements2 Device::getImageMemoryRequirements2KHR( const ImageMemoryRequirementsInfo2 & info, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
   {
     VULKAN_HPP_NAMESPACE::MemoryRequirements2 memoryRequirements;
-    d.vkGetImageMemoryRequirements2( m_device, reinterpret_cast<const VkImageMemoryRequirementsInfo2*>( &info ), reinterpret_cast<VkMemoryRequirements2*>( &memoryRequirements ) );
+    d.vkGetImageMemoryRequirements2KHR( m_device, reinterpret_cast<const VkImageMemoryRequirementsInfo2*>( &info ), reinterpret_cast<VkMemoryRequirements2*>( &memoryRequirements ) );
     return memoryRequirements;
   }
   template<typename X, typename Y, typename ...Z, typename Dispatch>
@@ -72403,7 +71532,7 @@
   {
     StructureChain<X, Y, Z...> structureChain;
     VULKAN_HPP_NAMESPACE::MemoryRequirements2& memoryRequirements = structureChain.template get<VULKAN_HPP_NAMESPACE::MemoryRequirements2>();
-    d.vkGetImageMemoryRequirements2( m_device, reinterpret_cast<const VkImageMemoryRequirementsInfo2*>( &info ), reinterpret_cast<VkMemoryRequirements2*>( &memoryRequirements ) );
+    d.vkGetImageMemoryRequirements2KHR( m_device, reinterpret_cast<const VkImageMemoryRequirementsInfo2*>( &info ), reinterpret_cast<VkMemoryRequirements2*>( &memoryRequirements ) );
     return structureChain;
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
@@ -72467,7 +71596,7 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE void Device::getImageSparseMemoryRequirements2KHR( const VULKAN_HPP_NAMESPACE::ImageSparseMemoryRequirementsInfo2* pInfo, uint32_t* pSparseMemoryRequirementCount, VULKAN_HPP_NAMESPACE::SparseImageMemoryRequirements2* pSparseMemoryRequirements, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkGetImageSparseMemoryRequirements2( m_device, reinterpret_cast<const VkImageSparseMemoryRequirementsInfo2*>( pInfo ), pSparseMemoryRequirementCount, reinterpret_cast<VkSparseImageMemoryRequirements2*>( pSparseMemoryRequirements ) );
+    d.vkGetImageSparseMemoryRequirements2KHR( m_device, reinterpret_cast<const VkImageSparseMemoryRequirementsInfo2*>( pInfo ), pSparseMemoryRequirementCount, reinterpret_cast<VkSparseImageMemoryRequirements2*>( pSparseMemoryRequirements ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Allocator, typename Dispatch>
@@ -72475,9 +71604,9 @@
   {
     std::vector<SparseImageMemoryRequirements2,Allocator> sparseMemoryRequirements;
     uint32_t sparseMemoryRequirementCount;
-    d.vkGetImageSparseMemoryRequirements2( m_device, reinterpret_cast<const VkImageSparseMemoryRequirementsInfo2*>( &info ), &sparseMemoryRequirementCount, nullptr );
+    d.vkGetImageSparseMemoryRequirements2KHR( m_device, reinterpret_cast<const VkImageSparseMemoryRequirementsInfo2*>( &info ), &sparseMemoryRequirementCount, nullptr );
     sparseMemoryRequirements.resize( sparseMemoryRequirementCount );
-    d.vkGetImageSparseMemoryRequirements2( m_device, reinterpret_cast<const VkImageSparseMemoryRequirementsInfo2*>( &info ), &sparseMemoryRequirementCount, reinterpret_cast<VkSparseImageMemoryRequirements2*>( sparseMemoryRequirements.data() ) );
+    d.vkGetImageSparseMemoryRequirements2KHR( m_device, reinterpret_cast<const VkImageSparseMemoryRequirementsInfo2*>( &info ), &sparseMemoryRequirementCount, reinterpret_cast<VkSparseImageMemoryRequirements2*>( sparseMemoryRequirements.data() ) );
     return sparseMemoryRequirements;
   }
   template<typename Allocator, typename Dispatch>
@@ -72485,9 +71614,9 @@
   {
     std::vector<SparseImageMemoryRequirements2,Allocator> sparseMemoryRequirements( vectorAllocator );
     uint32_t sparseMemoryRequirementCount;
-    d.vkGetImageSparseMemoryRequirements2( m_device, reinterpret_cast<const VkImageSparseMemoryRequirementsInfo2*>( &info ), &sparseMemoryRequirementCount, nullptr );
+    d.vkGetImageSparseMemoryRequirements2KHR( m_device, reinterpret_cast<const VkImageSparseMemoryRequirementsInfo2*>( &info ), &sparseMemoryRequirementCount, nullptr );
     sparseMemoryRequirements.resize( sparseMemoryRequirementCount );
-    d.vkGetImageSparseMemoryRequirements2( m_device, reinterpret_cast<const VkImageSparseMemoryRequirementsInfo2*>( &info ), &sparseMemoryRequirementCount, reinterpret_cast<VkSparseImageMemoryRequirements2*>( sparseMemoryRequirements.data() ) );
+    d.vkGetImageSparseMemoryRequirements2KHR( m_device, reinterpret_cast<const VkImageSparseMemoryRequirementsInfo2*>( &info ), &sparseMemoryRequirementCount, reinterpret_cast<VkSparseImageMemoryRequirements2*>( sparseMemoryRequirements.data() ) );
     return sparseMemoryRequirements;
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
@@ -72508,6 +71637,21 @@
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
   template<typename Dispatch>
+  VULKAN_HPP_INLINE Result Device::getImageViewAddressNVX( VULKAN_HPP_NAMESPACE::ImageView imageView, VULKAN_HPP_NAMESPACE::ImageViewAddressPropertiesNVX* pProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  {
+    return static_cast<Result>( d.vkGetImageViewAddressNVX( m_device, static_cast<VkImageView>( imageView ), reinterpret_cast<VkImageViewAddressPropertiesNVX*>( pProperties ) ) );
+  }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::ImageViewAddressPropertiesNVX>::type Device::getImageViewAddressNVX( VULKAN_HPP_NAMESPACE::ImageView imageView, Dispatch const &d ) const
+  {
+    VULKAN_HPP_NAMESPACE::ImageViewAddressPropertiesNVX properties;
+    Result result = static_cast<Result>( d.vkGetImageViewAddressNVX( m_device, static_cast<VkImageView>( imageView ), reinterpret_cast<VkImageViewAddressPropertiesNVX*>( &properties ) ) );
+    return createResultValue( result, properties, VULKAN_HPP_NAMESPACE_STRING"::Device::getImageViewAddressNVX" );
+  }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
+  template<typename Dispatch>
   VULKAN_HPP_INLINE uint32_t Device::getImageViewHandleNVX( const VULKAN_HPP_NAMESPACE::ImageViewHandleInfoNVX* pInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
     return d.vkGetImageViewHandleNVX( m_device, reinterpret_cast<const VkImageViewHandleInfoNVX*>( pInfo ) );
@@ -72922,6 +72066,36 @@
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE Result Device::getRayTracingCaptureReplayShaderGroupHandlesKHR( VULKAN_HPP_NAMESPACE::Pipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  {
+    return static_cast<Result>( d.vkGetRayTracingCaptureReplayShaderGroupHandlesKHR( m_device, static_cast<VkPipeline>( pipeline ), firstGroup, groupCount, dataSize, pData ) );
+  }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+  template<typename T, typename Dispatch>
+  VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::getRayTracingCaptureReplayShaderGroupHandlesKHR( VULKAN_HPP_NAMESPACE::Pipeline pipeline, uint32_t firstGroup, uint32_t groupCount, ArrayProxy<T> data, Dispatch const &d ) const
+  {
+    Result result = static_cast<Result>( d.vkGetRayTracingCaptureReplayShaderGroupHandlesKHR( m_device, static_cast<VkPipeline>( pipeline ), firstGroup, groupCount, data.size() * sizeof( T ) , reinterpret_cast<void*>( data.data() ) ) );
+    return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::getRayTracingCaptureReplayShaderGroupHandlesKHR" );
+  }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE Result Device::getRayTracingShaderGroupHandlesKHR( VULKAN_HPP_NAMESPACE::Pipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  {
+    return static_cast<Result>( d.vkGetRayTracingShaderGroupHandlesKHR( m_device, static_cast<VkPipeline>( pipeline ), firstGroup, groupCount, dataSize, pData ) );
+  }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+  template<typename T, typename Dispatch>
+  VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::getRayTracingShaderGroupHandlesKHR( VULKAN_HPP_NAMESPACE::Pipeline pipeline, uint32_t firstGroup, uint32_t groupCount, ArrayProxy<T> data, Dispatch const &d ) const
+  {
+    Result result = static_cast<Result>( d.vkGetRayTracingShaderGroupHandlesKHR( m_device, static_cast<VkPipeline>( pipeline ), firstGroup, groupCount, data.size() * sizeof( T ) , reinterpret_cast<void*>( data.data() ) ) );
+    return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::getRayTracingShaderGroupHandlesKHR" );
+  }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+
   template<typename Dispatch>
   VULKAN_HPP_INLINE Result Device::getRayTracingShaderGroupHandlesNV( VULKAN_HPP_NAMESPACE::Pipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
@@ -72984,14 +72158,14 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE Result Device::getSemaphoreCounterValueKHR( VULKAN_HPP_NAMESPACE::Semaphore semaphore, uint64_t* pValue, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    return static_cast<Result>( d.vkGetSemaphoreCounterValue( m_device, static_cast<VkSemaphore>( semaphore ), pValue ) );
+    return static_cast<Result>( d.vkGetSemaphoreCounterValueKHR( m_device, static_cast<VkSemaphore>( semaphore ), pValue ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
   VULKAN_HPP_INLINE typename ResultValueType<uint64_t>::type Device::getSemaphoreCounterValueKHR( VULKAN_HPP_NAMESPACE::Semaphore semaphore, Dispatch const &d ) const
   {
     uint64_t value;
-    Result result = static_cast<Result>( d.vkGetSemaphoreCounterValue( m_device, static_cast<VkSemaphore>( semaphore ), &value ) );
+    Result result = static_cast<Result>( d.vkGetSemaphoreCounterValueKHR( m_device, static_cast<VkSemaphore>( semaphore ), &value ) );
     return createResultValue( result, value, VULKAN_HPP_NAMESPACE_STRING"::Device::getSemaphoreCounterValueKHR" );
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
@@ -73397,28 +72571,6 @@
 #endif /*VULKAN_HPP_NO_SMART_HANDLE*/
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
-  template<typename Dispatch>
-  VULKAN_HPP_INLINE Result Device::registerObjectsNVX( VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable, uint32_t objectCount, const VULKAN_HPP_NAMESPACE::ObjectTableEntryNVX* const* ppObjectTableEntries, const uint32_t* pObjectIndices, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
-  {
-    return static_cast<Result>( d.vkRegisterObjectsNVX( m_device, static_cast<VkObjectTableNVX>( objectTable ), objectCount, reinterpret_cast<const VkObjectTableEntryNVX* const*>( ppObjectTableEntries ), pObjectIndices ) );
-  }
-#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
-  template<typename Dispatch>
-  VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::registerObjectsNVX( VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable, ArrayProxy<const VULKAN_HPP_NAMESPACE::ObjectTableEntryNVX* const> pObjectTableEntries, ArrayProxy<const uint32_t> objectIndices, Dispatch const &d ) const
-  {
-#ifdef VULKAN_HPP_NO_EXCEPTIONS
-    VULKAN_HPP_ASSERT( pObjectTableEntries.size() == objectIndices.size() );
-#else
-    if ( pObjectTableEntries.size() != objectIndices.size() )
-    {
-      throw LogicError( VULKAN_HPP_NAMESPACE_STRING "::VkDevice::registerObjectsNVX: pObjectTableEntries.size() != objectIndices.size()" );
-    }
-#endif  /*VULKAN_HPP_NO_EXCEPTIONS*/
-    Result result = static_cast<Result>( d.vkRegisterObjectsNVX( m_device, static_cast<VkObjectTableNVX>( objectTable ), pObjectTableEntries.size() , reinterpret_cast<const VkObjectTableEntryNVX* const*>( pObjectTableEntries.data() ), objectIndices.data() ) );
-    return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::registerObjectsNVX" );
-  }
-#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
-
 #ifdef VK_USE_PLATFORM_WIN32_KHR
 #ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
@@ -73542,13 +72694,13 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE void Device::resetQueryPoolEXT( VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkResetQueryPool( m_device, static_cast<VkQueryPool>( queryPool ), firstQuery, queryCount );
+    d.vkResetQueryPoolEXT( m_device, static_cast<VkQueryPool>( queryPool ), firstQuery, queryCount );
   }
 #else
   template<typename Dispatch>
   VULKAN_HPP_INLINE void Device::resetQueryPoolEXT( VULKAN_HPP_NAMESPACE::QueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkResetQueryPool( m_device, static_cast<VkQueryPool>( queryPool ), firstQuery, queryCount );
+    d.vkResetQueryPoolEXT( m_device, static_cast<VkQueryPool>( queryPool ), firstQuery, queryCount );
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
@@ -73647,13 +72799,13 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE Result Device::signalSemaphoreKHR( const VULKAN_HPP_NAMESPACE::SemaphoreSignalInfo* pSignalInfo, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    return static_cast<Result>( d.vkSignalSemaphore( m_device, reinterpret_cast<const VkSemaphoreSignalInfo*>( pSignalInfo ) ) );
+    return static_cast<Result>( d.vkSignalSemaphoreKHR( m_device, reinterpret_cast<const VkSemaphoreSignalInfo*>( pSignalInfo ) ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
   VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::signalSemaphoreKHR( const SemaphoreSignalInfo & signalInfo, Dispatch const &d ) const
   {
-    Result result = static_cast<Result>( d.vkSignalSemaphore( m_device, reinterpret_cast<const VkSemaphoreSignalInfo*>( &signalInfo ) ) );
+    Result result = static_cast<Result>( d.vkSignalSemaphoreKHR( m_device, reinterpret_cast<const VkSemaphoreSignalInfo*>( &signalInfo ) ) );
     return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::signalSemaphoreKHR" );
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
@@ -73676,13 +72828,13 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE void Device::trimCommandPoolKHR( VULKAN_HPP_NAMESPACE::CommandPool commandPool, VULKAN_HPP_NAMESPACE::CommandPoolTrimFlags flags, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkTrimCommandPool( m_device, static_cast<VkCommandPool>( commandPool ), static_cast<VkCommandPoolTrimFlags>( flags ) );
+    d.vkTrimCommandPoolKHR( m_device, static_cast<VkCommandPool>( commandPool ), static_cast<VkCommandPoolTrimFlags>( flags ) );
   }
 #else
   template<typename Dispatch>
   VULKAN_HPP_INLINE void Device::trimCommandPoolKHR( VULKAN_HPP_NAMESPACE::CommandPool commandPool, VULKAN_HPP_NAMESPACE::CommandPoolTrimFlags flags, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkTrimCommandPool( m_device, static_cast<VkCommandPool>( commandPool ), static_cast<VkCommandPoolTrimFlags>( flags ) );
+    d.vkTrimCommandPoolKHR( m_device, static_cast<VkCommandPool>( commandPool ), static_cast<VkCommandPoolTrimFlags>( flags ) );
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
@@ -73714,28 +72866,6 @@
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
-  template<typename Dispatch>
-  VULKAN_HPP_INLINE Result Device::unregisterObjectsNVX( VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable, uint32_t objectCount, const VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX* pObjectEntryTypes, const uint32_t* pObjectIndices, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
-  {
-    return static_cast<Result>( d.vkUnregisterObjectsNVX( m_device, static_cast<VkObjectTableNVX>( objectTable ), objectCount, reinterpret_cast<const VkObjectEntryTypeNVX*>( pObjectEntryTypes ), pObjectIndices ) );
-  }
-#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
-  template<typename Dispatch>
-  VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::unregisterObjectsNVX( VULKAN_HPP_NAMESPACE::ObjectTableNVX objectTable, ArrayProxy<const VULKAN_HPP_NAMESPACE::ObjectEntryTypeNVX> objectEntryTypes, ArrayProxy<const uint32_t> objectIndices, Dispatch const &d ) const
-  {
-#ifdef VULKAN_HPP_NO_EXCEPTIONS
-    VULKAN_HPP_ASSERT( objectEntryTypes.size() == objectIndices.size() );
-#else
-    if ( objectEntryTypes.size() != objectIndices.size() )
-    {
-      throw LogicError( VULKAN_HPP_NAMESPACE_STRING "::VkDevice::unregisterObjectsNVX: objectEntryTypes.size() != objectIndices.size()" );
-    }
-#endif  /*VULKAN_HPP_NO_EXCEPTIONS*/
-    Result result = static_cast<Result>( d.vkUnregisterObjectsNVX( m_device, static_cast<VkObjectTableNVX>( objectTable ), objectEntryTypes.size() , reinterpret_cast<const VkObjectEntryTypeNVX*>( objectEntryTypes.data() ), objectIndices.data() ) );
-    return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::unregisterObjectsNVX" );
-  }
-#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
-
 #ifdef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
   VULKAN_HPP_INLINE void Device::updateDescriptorSetWithTemplate( VULKAN_HPP_NAMESPACE::DescriptorSet descriptorSet, VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
@@ -73754,13 +72884,13 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE void Device::updateDescriptorSetWithTemplateKHR( VULKAN_HPP_NAMESPACE::DescriptorSet descriptorSet, VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkUpdateDescriptorSetWithTemplate( m_device, static_cast<VkDescriptorSet>( descriptorSet ), static_cast<VkDescriptorUpdateTemplate>( descriptorUpdateTemplate ), pData );
+    d.vkUpdateDescriptorSetWithTemplateKHR( m_device, static_cast<VkDescriptorSet>( descriptorSet ), static_cast<VkDescriptorUpdateTemplate>( descriptorUpdateTemplate ), pData );
   }
 #else
   template<typename Dispatch>
   VULKAN_HPP_INLINE void Device::updateDescriptorSetWithTemplateKHR( VULKAN_HPP_NAMESPACE::DescriptorSet descriptorSet, VULKAN_HPP_NAMESPACE::DescriptorUpdateTemplate descriptorUpdateTemplate, const void* pData, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkUpdateDescriptorSetWithTemplate( m_device, static_cast<VkDescriptorSet>( descriptorSet ), static_cast<VkDescriptorUpdateTemplate>( descriptorUpdateTemplate ), pData );
+    d.vkUpdateDescriptorSetWithTemplateKHR( m_device, static_cast<VkDescriptorSet>( descriptorSet ), static_cast<VkDescriptorUpdateTemplate>( descriptorUpdateTemplate ), pData );
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
@@ -73808,17 +72938,33 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE Result Device::waitSemaphoresKHR( const VULKAN_HPP_NAMESPACE::SemaphoreWaitInfo* pWaitInfo, uint64_t timeout, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    return static_cast<Result>( d.vkWaitSemaphores( m_device, reinterpret_cast<const VkSemaphoreWaitInfo*>( pWaitInfo ), timeout ) );
+    return static_cast<Result>( d.vkWaitSemaphoresKHR( m_device, reinterpret_cast<const VkSemaphoreWaitInfo*>( pWaitInfo ), timeout ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
   VULKAN_HPP_INLINE Result Device::waitSemaphoresKHR( const SemaphoreWaitInfo & waitInfo, uint64_t timeout, Dispatch const &d ) const
   {
-    Result result = static_cast<Result>( d.vkWaitSemaphores( m_device, reinterpret_cast<const VkSemaphoreWaitInfo*>( &waitInfo ), timeout ) );
+    Result result = static_cast<Result>( d.vkWaitSemaphoresKHR( m_device, reinterpret_cast<const VkSemaphoreWaitInfo*>( &waitInfo ), timeout ) );
     return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::waitSemaphoresKHR", { Result::eSuccess, Result::eTimeout } );
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  template<typename Dispatch>
+  VULKAN_HPP_INLINE Result Device::writeAccelerationStructuresPropertiesKHR( uint32_t accelerationStructureCount, const VULKAN_HPP_NAMESPACE::AccelerationStructureKHR* pAccelerationStructures, VULKAN_HPP_NAMESPACE::QueryType queryType, size_t dataSize, void* pData, size_t stride, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
+  {
+    return static_cast<Result>( d.vkWriteAccelerationStructuresPropertiesKHR( m_device, accelerationStructureCount, reinterpret_cast<const VkAccelerationStructureKHR*>( pAccelerationStructures ), static_cast<VkQueryType>( queryType ), dataSize, pData, stride ) );
+  }
+#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
+  template<typename T, typename Dispatch>
+  VULKAN_HPP_INLINE typename ResultValueType<void>::type Device::writeAccelerationStructuresPropertiesKHR( ArrayProxy<const VULKAN_HPP_NAMESPACE::AccelerationStructureKHR> accelerationStructures, VULKAN_HPP_NAMESPACE::QueryType queryType, ArrayProxy<T> data, size_t stride, Dispatch const &d ) const
+  {
+    Result result = static_cast<Result>( d.vkWriteAccelerationStructuresPropertiesKHR( m_device, accelerationStructures.size() , reinterpret_cast<const VkAccelerationStructureKHR*>( accelerationStructures.data() ), static_cast<VkQueryType>( queryType ), data.size() * sizeof( T ) , reinterpret_cast<void*>( data.data() ), stride ) );
+    return createResultValue( result, VULKAN_HPP_NAMESPACE_STRING"::Device::writeAccelerationStructuresPropertiesKHR" );
+  }
+#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
 #ifdef VK_USE_PLATFORM_ANDROID_KHR
   template<typename Dispatch>
   VULKAN_HPP_INLINE Result Instance::createAndroidSurfaceKHR( const VULKAN_HPP_NAMESPACE::AndroidSurfaceCreateInfoKHR* pCreateInfo, const VULKAN_HPP_NAMESPACE::AllocationCallbacks* pAllocator, VULKAN_HPP_NAMESPACE::SurfaceKHR* pSurface, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
@@ -74398,7 +73544,7 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE Result Instance::enumeratePhysicalDeviceGroupsKHR( uint32_t* pPhysicalDeviceGroupCount, VULKAN_HPP_NAMESPACE::PhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    return static_cast<Result>( d.vkEnumeratePhysicalDeviceGroups( m_instance, pPhysicalDeviceGroupCount, reinterpret_cast<VkPhysicalDeviceGroupProperties*>( pPhysicalDeviceGroupProperties ) ) );
+    return static_cast<Result>( d.vkEnumeratePhysicalDeviceGroupsKHR( m_instance, pPhysicalDeviceGroupCount, reinterpret_cast<VkPhysicalDeviceGroupProperties*>( pPhysicalDeviceGroupProperties ) ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Allocator, typename Dispatch>
@@ -74409,11 +73555,11 @@
     Result result;
     do
     {
-      result = static_cast<Result>( d.vkEnumeratePhysicalDeviceGroups( m_instance, &physicalDeviceGroupCount, nullptr ) );
+      result = static_cast<Result>( d.vkEnumeratePhysicalDeviceGroupsKHR( m_instance, &physicalDeviceGroupCount, nullptr ) );
       if ( ( result == Result::eSuccess ) && physicalDeviceGroupCount )
       {
         physicalDeviceGroupProperties.resize( physicalDeviceGroupCount );
-        result = static_cast<Result>( d.vkEnumeratePhysicalDeviceGroups( m_instance, &physicalDeviceGroupCount, reinterpret_cast<VkPhysicalDeviceGroupProperties*>( physicalDeviceGroupProperties.data() ) ) );
+        result = static_cast<Result>( d.vkEnumeratePhysicalDeviceGroupsKHR( m_instance, &physicalDeviceGroupCount, reinterpret_cast<VkPhysicalDeviceGroupProperties*>( physicalDeviceGroupProperties.data() ) ) );
       }
     } while ( result == Result::eIncomplete );
     if ( result == Result::eSuccess )
@@ -74431,11 +73577,11 @@
     Result result;
     do
     {
-      result = static_cast<Result>( d.vkEnumeratePhysicalDeviceGroups( m_instance, &physicalDeviceGroupCount, nullptr ) );
+      result = static_cast<Result>( d.vkEnumeratePhysicalDeviceGroupsKHR( m_instance, &physicalDeviceGroupCount, nullptr ) );
       if ( ( result == Result::eSuccess ) && physicalDeviceGroupCount )
       {
         physicalDeviceGroupProperties.resize( physicalDeviceGroupCount );
-        result = static_cast<Result>( d.vkEnumeratePhysicalDeviceGroups( m_instance, &physicalDeviceGroupCount, reinterpret_cast<VkPhysicalDeviceGroupProperties*>( physicalDeviceGroupProperties.data() ) ) );
+        result = static_cast<Result>( d.vkEnumeratePhysicalDeviceGroupsKHR( m_instance, &physicalDeviceGroupCount, reinterpret_cast<VkPhysicalDeviceGroupProperties*>( physicalDeviceGroupProperties.data() ) ) );
       }
     } while ( result == Result::eIncomplete );
     if ( result == Result::eSuccess )
@@ -75255,14 +74401,14 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE void PhysicalDevice::getExternalBufferPropertiesKHR( const VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VULKAN_HPP_NAMESPACE::ExternalBufferProperties* pExternalBufferProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkGetPhysicalDeviceExternalBufferProperties( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceExternalBufferInfo*>( pExternalBufferInfo ), reinterpret_cast<VkExternalBufferProperties*>( pExternalBufferProperties ) );
+    d.vkGetPhysicalDeviceExternalBufferPropertiesKHR( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceExternalBufferInfo*>( pExternalBufferInfo ), reinterpret_cast<VkExternalBufferProperties*>( pExternalBufferProperties ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
   VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::ExternalBufferProperties PhysicalDevice::getExternalBufferPropertiesKHR( const PhysicalDeviceExternalBufferInfo & externalBufferInfo, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
   {
     VULKAN_HPP_NAMESPACE::ExternalBufferProperties externalBufferProperties;
-    d.vkGetPhysicalDeviceExternalBufferProperties( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceExternalBufferInfo*>( &externalBufferInfo ), reinterpret_cast<VkExternalBufferProperties*>( &externalBufferProperties ) );
+    d.vkGetPhysicalDeviceExternalBufferPropertiesKHR( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceExternalBufferInfo*>( &externalBufferInfo ), reinterpret_cast<VkExternalBufferProperties*>( &externalBufferProperties ) );
     return externalBufferProperties;
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
@@ -75285,14 +74431,14 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE void PhysicalDevice::getExternalFencePropertiesKHR( const VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalFenceInfo* pExternalFenceInfo, VULKAN_HPP_NAMESPACE::ExternalFenceProperties* pExternalFenceProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkGetPhysicalDeviceExternalFenceProperties( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceExternalFenceInfo*>( pExternalFenceInfo ), reinterpret_cast<VkExternalFenceProperties*>( pExternalFenceProperties ) );
+    d.vkGetPhysicalDeviceExternalFencePropertiesKHR( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceExternalFenceInfo*>( pExternalFenceInfo ), reinterpret_cast<VkExternalFenceProperties*>( pExternalFenceProperties ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
   VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::ExternalFenceProperties PhysicalDevice::getExternalFencePropertiesKHR( const PhysicalDeviceExternalFenceInfo & externalFenceInfo, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
   {
     VULKAN_HPP_NAMESPACE::ExternalFenceProperties externalFenceProperties;
-    d.vkGetPhysicalDeviceExternalFenceProperties( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceExternalFenceInfo*>( &externalFenceInfo ), reinterpret_cast<VkExternalFenceProperties*>( &externalFenceProperties ) );
+    d.vkGetPhysicalDeviceExternalFencePropertiesKHR( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceExternalFenceInfo*>( &externalFenceInfo ), reinterpret_cast<VkExternalFenceProperties*>( &externalFenceProperties ) );
     return externalFenceProperties;
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
@@ -75330,14 +74476,14 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE void PhysicalDevice::getExternalSemaphorePropertiesKHR( const VULKAN_HPP_NAMESPACE::PhysicalDeviceExternalSemaphoreInfo* pExternalSemaphoreInfo, VULKAN_HPP_NAMESPACE::ExternalSemaphoreProperties* pExternalSemaphoreProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkGetPhysicalDeviceExternalSemaphoreProperties( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceExternalSemaphoreInfo*>( pExternalSemaphoreInfo ), reinterpret_cast<VkExternalSemaphoreProperties*>( pExternalSemaphoreProperties ) );
+    d.vkGetPhysicalDeviceExternalSemaphorePropertiesKHR( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceExternalSemaphoreInfo*>( pExternalSemaphoreInfo ), reinterpret_cast<VkExternalSemaphoreProperties*>( pExternalSemaphoreProperties ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
   VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::ExternalSemaphoreProperties PhysicalDevice::getExternalSemaphorePropertiesKHR( const PhysicalDeviceExternalSemaphoreInfo & externalSemaphoreInfo, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
   {
     VULKAN_HPP_NAMESPACE::ExternalSemaphoreProperties externalSemaphoreProperties;
-    d.vkGetPhysicalDeviceExternalSemaphoreProperties( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceExternalSemaphoreInfo*>( &externalSemaphoreInfo ), reinterpret_cast<VkExternalSemaphoreProperties*>( &externalSemaphoreProperties ) );
+    d.vkGetPhysicalDeviceExternalSemaphorePropertiesKHR( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceExternalSemaphoreInfo*>( &externalSemaphoreInfo ), reinterpret_cast<VkExternalSemaphoreProperties*>( &externalSemaphoreProperties ) );
     return externalSemaphoreProperties;
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
@@ -75383,14 +74529,14 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE void PhysicalDevice::getFeatures2KHR( VULKAN_HPP_NAMESPACE::PhysicalDeviceFeatures2* pFeatures, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkGetPhysicalDeviceFeatures2( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceFeatures2*>( pFeatures ) );
+    d.vkGetPhysicalDeviceFeatures2KHR( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceFeatures2*>( pFeatures ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
   VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::PhysicalDeviceFeatures2 PhysicalDevice::getFeatures2KHR(Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
   {
     VULKAN_HPP_NAMESPACE::PhysicalDeviceFeatures2 features;
-    d.vkGetPhysicalDeviceFeatures2( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceFeatures2*>( &features ) );
+    d.vkGetPhysicalDeviceFeatures2KHR( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceFeatures2*>( &features ) );
     return features;
   }
   template<typename X, typename Y, typename ...Z, typename Dispatch>
@@ -75398,7 +74544,7 @@
   {
     StructureChain<X, Y, Z...> structureChain;
     VULKAN_HPP_NAMESPACE::PhysicalDeviceFeatures2& features = structureChain.template get<VULKAN_HPP_NAMESPACE::PhysicalDeviceFeatures2>();
-    d.vkGetPhysicalDeviceFeatures2( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceFeatures2*>( &features ) );
+    d.vkGetPhysicalDeviceFeatures2KHR( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceFeatures2*>( &features ) );
     return structureChain;
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
@@ -75444,14 +74590,14 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE void PhysicalDevice::getFormatProperties2KHR( VULKAN_HPP_NAMESPACE::Format format, VULKAN_HPP_NAMESPACE::FormatProperties2* pFormatProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkGetPhysicalDeviceFormatProperties2( m_physicalDevice, static_cast<VkFormat>( format ), reinterpret_cast<VkFormatProperties2*>( pFormatProperties ) );
+    d.vkGetPhysicalDeviceFormatProperties2KHR( m_physicalDevice, static_cast<VkFormat>( format ), reinterpret_cast<VkFormatProperties2*>( pFormatProperties ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
   VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::FormatProperties2 PhysicalDevice::getFormatProperties2KHR( VULKAN_HPP_NAMESPACE::Format format, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
   {
     VULKAN_HPP_NAMESPACE::FormatProperties2 formatProperties;
-    d.vkGetPhysicalDeviceFormatProperties2( m_physicalDevice, static_cast<VkFormat>( format ), reinterpret_cast<VkFormatProperties2*>( &formatProperties ) );
+    d.vkGetPhysicalDeviceFormatProperties2KHR( m_physicalDevice, static_cast<VkFormat>( format ), reinterpret_cast<VkFormatProperties2*>( &formatProperties ) );
     return formatProperties;
   }
   template<typename X, typename Y, typename ...Z, typename Dispatch>
@@ -75459,27 +74605,12 @@
   {
     StructureChain<X, Y, Z...> structureChain;
     VULKAN_HPP_NAMESPACE::FormatProperties2& formatProperties = structureChain.template get<VULKAN_HPP_NAMESPACE::FormatProperties2>();
-    d.vkGetPhysicalDeviceFormatProperties2( m_physicalDevice, static_cast<VkFormat>( format ), reinterpret_cast<VkFormatProperties2*>( &formatProperties ) );
+    d.vkGetPhysicalDeviceFormatProperties2KHR( m_physicalDevice, static_cast<VkFormat>( format ), reinterpret_cast<VkFormatProperties2*>( &formatProperties ) );
     return structureChain;
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
 
   template<typename Dispatch>
-  VULKAN_HPP_INLINE void PhysicalDevice::getGeneratedCommandsPropertiesNVX( VULKAN_HPP_NAMESPACE::DeviceGeneratedCommandsFeaturesNVX* pFeatures, VULKAN_HPP_NAMESPACE::DeviceGeneratedCommandsLimitsNVX* pLimits, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
-  {
-    d.vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX( m_physicalDevice, reinterpret_cast<VkDeviceGeneratedCommandsFeaturesNVX*>( pFeatures ), reinterpret_cast<VkDeviceGeneratedCommandsLimitsNVX*>( pLimits ) );
-  }
-#ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
-  template<typename Dispatch>
-  VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::DeviceGeneratedCommandsLimitsNVX PhysicalDevice::getGeneratedCommandsPropertiesNVX( DeviceGeneratedCommandsFeaturesNVX & features, Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
-  {
-    VULKAN_HPP_NAMESPACE::DeviceGeneratedCommandsLimitsNVX limits;
-    d.vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX( m_physicalDevice, reinterpret_cast<VkDeviceGeneratedCommandsFeaturesNVX*>( &features ), reinterpret_cast<VkDeviceGeneratedCommandsLimitsNVX*>( &limits ) );
-    return limits;
-  }
-#endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
-
-  template<typename Dispatch>
   VULKAN_HPP_INLINE Result PhysicalDevice::getImageFormatProperties( VULKAN_HPP_NAMESPACE::Format format, VULKAN_HPP_NAMESPACE::ImageType type, VULKAN_HPP_NAMESPACE::ImageTiling tiling, VULKAN_HPP_NAMESPACE::ImageUsageFlags usage, VULKAN_HPP_NAMESPACE::ImageCreateFlags flags, VULKAN_HPP_NAMESPACE::ImageFormatProperties* pImageFormatProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
     return static_cast<Result>( d.vkGetPhysicalDeviceImageFormatProperties( m_physicalDevice, static_cast<VkFormat>( format ), static_cast<VkImageType>( type ), static_cast<VkImageTiling>( tiling ), static_cast<VkImageUsageFlags>( usage ), static_cast<VkImageCreateFlags>( flags ), reinterpret_cast<VkImageFormatProperties*>( pImageFormatProperties ) ) );
@@ -75520,14 +74651,14 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE Result PhysicalDevice::getImageFormatProperties2KHR( const VULKAN_HPP_NAMESPACE::PhysicalDeviceImageFormatInfo2* pImageFormatInfo, VULKAN_HPP_NAMESPACE::ImageFormatProperties2* pImageFormatProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    return static_cast<Result>( d.vkGetPhysicalDeviceImageFormatProperties2( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceImageFormatInfo2*>( pImageFormatInfo ), reinterpret_cast<VkImageFormatProperties2*>( pImageFormatProperties ) ) );
+    return static_cast<Result>( d.vkGetPhysicalDeviceImageFormatProperties2KHR( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceImageFormatInfo2*>( pImageFormatInfo ), reinterpret_cast<VkImageFormatProperties2*>( pImageFormatProperties ) ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
   VULKAN_HPP_INLINE typename ResultValueType<VULKAN_HPP_NAMESPACE::ImageFormatProperties2>::type PhysicalDevice::getImageFormatProperties2KHR( const PhysicalDeviceImageFormatInfo2 & imageFormatInfo, Dispatch const &d ) const
   {
     VULKAN_HPP_NAMESPACE::ImageFormatProperties2 imageFormatProperties;
-    Result result = static_cast<Result>( d.vkGetPhysicalDeviceImageFormatProperties2( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceImageFormatInfo2*>( &imageFormatInfo ), reinterpret_cast<VkImageFormatProperties2*>( &imageFormatProperties ) ) );
+    Result result = static_cast<Result>( d.vkGetPhysicalDeviceImageFormatProperties2KHR( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceImageFormatInfo2*>( &imageFormatInfo ), reinterpret_cast<VkImageFormatProperties2*>( &imageFormatProperties ) ) );
     return createResultValue( result, imageFormatProperties, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getImageFormatProperties2KHR" );
   }
   template<typename X, typename Y, typename ...Z, typename Dispatch>
@@ -75535,7 +74666,7 @@
   {
     StructureChain<X, Y, Z...> structureChain;
     VULKAN_HPP_NAMESPACE::ImageFormatProperties2& imageFormatProperties = structureChain.template get<VULKAN_HPP_NAMESPACE::ImageFormatProperties2>();
-    Result result = static_cast<Result>( d.vkGetPhysicalDeviceImageFormatProperties2( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceImageFormatInfo2*>( &imageFormatInfo ), reinterpret_cast<VkImageFormatProperties2*>( &imageFormatProperties ) ) );
+    Result result = static_cast<Result>( d.vkGetPhysicalDeviceImageFormatProperties2KHR( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceImageFormatInfo2*>( &imageFormatInfo ), reinterpret_cast<VkImageFormatProperties2*>( &imageFormatProperties ) ) );
     return createResultValue( result, structureChain, VULKAN_HPP_NAMESPACE_STRING"::PhysicalDevice::getImageFormatProperties2KHR" );
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
@@ -75581,14 +74712,14 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE void PhysicalDevice::getMemoryProperties2KHR( VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryProperties2* pMemoryProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkGetPhysicalDeviceMemoryProperties2( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceMemoryProperties2*>( pMemoryProperties ) );
+    d.vkGetPhysicalDeviceMemoryProperties2KHR( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceMemoryProperties2*>( pMemoryProperties ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
   VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryProperties2 PhysicalDevice::getMemoryProperties2KHR(Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
   {
     VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryProperties2 memoryProperties;
-    d.vkGetPhysicalDeviceMemoryProperties2( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceMemoryProperties2*>( &memoryProperties ) );
+    d.vkGetPhysicalDeviceMemoryProperties2KHR( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceMemoryProperties2*>( &memoryProperties ) );
     return memoryProperties;
   }
   template<typename X, typename Y, typename ...Z, typename Dispatch>
@@ -75596,7 +74727,7 @@
   {
     StructureChain<X, Y, Z...> structureChain;
     VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryProperties2& memoryProperties = structureChain.template get<VULKAN_HPP_NAMESPACE::PhysicalDeviceMemoryProperties2>();
-    d.vkGetPhysicalDeviceMemoryProperties2( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceMemoryProperties2*>( &memoryProperties ) );
+    d.vkGetPhysicalDeviceMemoryProperties2KHR( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceMemoryProperties2*>( &memoryProperties ) );
     return structureChain;
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
@@ -75709,14 +74840,14 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE void PhysicalDevice::getProperties2KHR( VULKAN_HPP_NAMESPACE::PhysicalDeviceProperties2* pProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkGetPhysicalDeviceProperties2( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceProperties2*>( pProperties ) );
+    d.vkGetPhysicalDeviceProperties2KHR( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceProperties2*>( pProperties ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Dispatch>
   VULKAN_HPP_INLINE VULKAN_HPP_NAMESPACE::PhysicalDeviceProperties2 PhysicalDevice::getProperties2KHR(Dispatch const &d ) const VULKAN_HPP_NOEXCEPT
   {
     VULKAN_HPP_NAMESPACE::PhysicalDeviceProperties2 properties;
-    d.vkGetPhysicalDeviceProperties2( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceProperties2*>( &properties ) );
+    d.vkGetPhysicalDeviceProperties2KHR( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceProperties2*>( &properties ) );
     return properties;
   }
   template<typename X, typename Y, typename ...Z, typename Dispatch>
@@ -75724,7 +74855,7 @@
   {
     StructureChain<X, Y, Z...> structureChain;
     VULKAN_HPP_NAMESPACE::PhysicalDeviceProperties2& properties = structureChain.template get<VULKAN_HPP_NAMESPACE::PhysicalDeviceProperties2>();
-    d.vkGetPhysicalDeviceProperties2( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceProperties2*>( &properties ) );
+    d.vkGetPhysicalDeviceProperties2KHR( m_physicalDevice, reinterpret_cast<VkPhysicalDeviceProperties2*>( &properties ) );
     return structureChain;
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
@@ -75841,7 +74972,7 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE void PhysicalDevice::getQueueFamilyProperties2KHR( uint32_t* pQueueFamilyPropertyCount, VULKAN_HPP_NAMESPACE::QueueFamilyProperties2* pQueueFamilyProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkGetPhysicalDeviceQueueFamilyProperties2( m_physicalDevice, pQueueFamilyPropertyCount, reinterpret_cast<VkQueueFamilyProperties2*>( pQueueFamilyProperties ) );
+    d.vkGetPhysicalDeviceQueueFamilyProperties2KHR( m_physicalDevice, pQueueFamilyPropertyCount, reinterpret_cast<VkQueueFamilyProperties2*>( pQueueFamilyProperties ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Allocator, typename Dispatch>
@@ -75849,9 +74980,9 @@
   {
     std::vector<QueueFamilyProperties2,Allocator> queueFamilyProperties;
     uint32_t queueFamilyPropertyCount;
-    d.vkGetPhysicalDeviceQueueFamilyProperties2( m_physicalDevice, &queueFamilyPropertyCount, nullptr );
+    d.vkGetPhysicalDeviceQueueFamilyProperties2KHR( m_physicalDevice, &queueFamilyPropertyCount, nullptr );
     queueFamilyProperties.resize( queueFamilyPropertyCount );
-    d.vkGetPhysicalDeviceQueueFamilyProperties2( m_physicalDevice, &queueFamilyPropertyCount, reinterpret_cast<VkQueueFamilyProperties2*>( queueFamilyProperties.data() ) );
+    d.vkGetPhysicalDeviceQueueFamilyProperties2KHR( m_physicalDevice, &queueFamilyPropertyCount, reinterpret_cast<VkQueueFamilyProperties2*>( queueFamilyProperties.data() ) );
     return queueFamilyProperties;
   }
   template<typename Allocator, typename Dispatch>
@@ -75859,9 +74990,9 @@
   {
     std::vector<QueueFamilyProperties2,Allocator> queueFamilyProperties( vectorAllocator );
     uint32_t queueFamilyPropertyCount;
-    d.vkGetPhysicalDeviceQueueFamilyProperties2( m_physicalDevice, &queueFamilyPropertyCount, nullptr );
+    d.vkGetPhysicalDeviceQueueFamilyProperties2KHR( m_physicalDevice, &queueFamilyPropertyCount, nullptr );
     queueFamilyProperties.resize( queueFamilyPropertyCount );
-    d.vkGetPhysicalDeviceQueueFamilyProperties2( m_physicalDevice, &queueFamilyPropertyCount, reinterpret_cast<VkQueueFamilyProperties2*>( queueFamilyProperties.data() ) );
+    d.vkGetPhysicalDeviceQueueFamilyProperties2KHR( m_physicalDevice, &queueFamilyPropertyCount, reinterpret_cast<VkQueueFamilyProperties2*>( queueFamilyProperties.data() ) );
     return queueFamilyProperties;
   }
   template<typename StructureChain, typename Allocator, typename Dispatch>
@@ -75869,14 +75000,14 @@
   {
     std::vector<StructureChain,Allocator> queueFamilyProperties;
     uint32_t queueFamilyPropertyCount;
-    d.vkGetPhysicalDeviceQueueFamilyProperties2( m_physicalDevice, &queueFamilyPropertyCount, nullptr );
+    d.vkGetPhysicalDeviceQueueFamilyProperties2KHR( m_physicalDevice, &queueFamilyPropertyCount, nullptr );
     queueFamilyProperties.resize( queueFamilyPropertyCount );
     std::vector<VULKAN_HPP_NAMESPACE::QueueFamilyProperties2> localVector( queueFamilyPropertyCount );
     for ( uint32_t i = 0; i < queueFamilyPropertyCount ; i++ )
     {
       localVector[i].pNext = queueFamilyProperties[i].template get<VULKAN_HPP_NAMESPACE::QueueFamilyProperties2>().pNext;
     }
-    d.vkGetPhysicalDeviceQueueFamilyProperties2( m_physicalDevice, &queueFamilyPropertyCount, reinterpret_cast<VkQueueFamilyProperties2*>( localVector.data() ) );
+    d.vkGetPhysicalDeviceQueueFamilyProperties2KHR( m_physicalDevice, &queueFamilyPropertyCount, reinterpret_cast<VkQueueFamilyProperties2*>( localVector.data() ) );
     for ( uint32_t i = 0; i < queueFamilyPropertyCount ; i++ )
     {
       queueFamilyProperties[i].template get<VULKAN_HPP_NAMESPACE::QueueFamilyProperties2>() = localVector[i];
@@ -75888,14 +75019,14 @@
   {
     std::vector<StructureChain,Allocator> queueFamilyProperties( vectorAllocator );
     uint32_t queueFamilyPropertyCount;
-    d.vkGetPhysicalDeviceQueueFamilyProperties2( m_physicalDevice, &queueFamilyPropertyCount, nullptr );
+    d.vkGetPhysicalDeviceQueueFamilyProperties2KHR( m_physicalDevice, &queueFamilyPropertyCount, nullptr );
     queueFamilyProperties.resize( queueFamilyPropertyCount );
     std::vector<VULKAN_HPP_NAMESPACE::QueueFamilyProperties2> localVector( queueFamilyPropertyCount );
     for ( uint32_t i = 0; i < queueFamilyPropertyCount ; i++ )
     {
       localVector[i].pNext = queueFamilyProperties[i].template get<VULKAN_HPP_NAMESPACE::QueueFamilyProperties2>().pNext;
     }
-    d.vkGetPhysicalDeviceQueueFamilyProperties2( m_physicalDevice, &queueFamilyPropertyCount, reinterpret_cast<VkQueueFamilyProperties2*>( localVector.data() ) );
+    d.vkGetPhysicalDeviceQueueFamilyProperties2KHR( m_physicalDevice, &queueFamilyPropertyCount, reinterpret_cast<VkQueueFamilyProperties2*>( localVector.data() ) );
     for ( uint32_t i = 0; i < queueFamilyPropertyCount ; i++ )
     {
       queueFamilyProperties[i].template get<VULKAN_HPP_NAMESPACE::QueueFamilyProperties2>() = localVector[i];
@@ -75963,7 +75094,7 @@
   template<typename Dispatch>
   VULKAN_HPP_INLINE void PhysicalDevice::getSparseImageFormatProperties2KHR( const VULKAN_HPP_NAMESPACE::PhysicalDeviceSparseImageFormatInfo2* pFormatInfo, uint32_t* pPropertyCount, VULKAN_HPP_NAMESPACE::SparseImageFormatProperties2* pProperties, Dispatch const &d) const VULKAN_HPP_NOEXCEPT
   {
-    d.vkGetPhysicalDeviceSparseImageFormatProperties2( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceSparseImageFormatInfo2*>( pFormatInfo ), pPropertyCount, reinterpret_cast<VkSparseImageFormatProperties2*>( pProperties ) );
+    d.vkGetPhysicalDeviceSparseImageFormatProperties2KHR( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceSparseImageFormatInfo2*>( pFormatInfo ), pPropertyCount, reinterpret_cast<VkSparseImageFormatProperties2*>( pProperties ) );
   }
 #ifndef VULKAN_HPP_DISABLE_ENHANCED_MODE
   template<typename Allocator, typename Dispatch>
@@ -75971,9 +75102,9 @@
   {
     std::vector<SparseImageFormatProperties2,Allocator> properties;
     uint32_t propertyCount;
-    d.vkGetPhysicalDeviceSparseImageFormatProperties2( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceSparseImageFormatInfo2*>( &formatInfo ), &propertyCount, nullptr );
+    d.vkGetPhysicalDeviceSparseImageFormatProperties2KHR( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceSparseImageFormatInfo2*>( &formatInfo ), &propertyCount, nullptr );
     properties.resize( propertyCount );
-    d.vkGetPhysicalDeviceSparseImageFormatProperties2( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceSparseImageFormatInfo2*>( &formatInfo ), &propertyCount, reinterpret_cast<VkSparseImageFormatProperties2*>( properties.data() ) );
+    d.vkGetPhysicalDeviceSparseImageFormatProperties2KHR( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceSparseImageFormatInfo2*>( &formatInfo ), &propertyCount, reinterpret_cast<VkSparseImageFormatProperties2*>( properties.data() ) );
     return properties;
   }
   template<typename Allocator, typename Dispatch>
@@ -75981,9 +75112,9 @@
   {
     std::vector<SparseImageFormatProperties2,Allocator> properties( vectorAllocator );
     uint32_t propertyCount;
-    d.vkGetPhysicalDeviceSparseImageFormatProperties2( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceSparseImageFormatInfo2*>( &formatInfo ), &propertyCount, nullptr );
+    d.vkGetPhysicalDeviceSparseImageFormatProperties2KHR( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceSparseImageFormatInfo2*>( &formatInfo ), &propertyCount, nullptr );
     properties.resize( propertyCount );
-    d.vkGetPhysicalDeviceSparseImageFormatProperties2( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceSparseImageFormatInfo2*>( &formatInfo ), &propertyCount, reinterpret_cast<VkSparseImageFormatProperties2*>( properties.data() ) );
+    d.vkGetPhysicalDeviceSparseImageFormatProperties2KHR( m_physicalDevice, reinterpret_cast<const VkPhysicalDeviceSparseImageFormatInfo2*>( &formatInfo ), &propertyCount, reinterpret_cast<VkSparseImageFormatProperties2*>( properties.data() ) );
     return properties;
   }
 #endif /*VULKAN_HPP_DISABLE_ENHANCED_MODE*/
@@ -76627,10 +75758,18 @@
   template <> struct isStructureChainValid<BufferCreateInfo, DedicatedAllocationBufferCreateInfoNV>{ enum { value = true }; };
   template <> struct isStructureChainValid<ImageCreateInfo, DedicatedAllocationImageCreateInfoNV>{ enum { value = true }; };
   template <> struct isStructureChainValid<MemoryAllocateInfo, DedicatedAllocationMemoryAllocateInfoNV>{ enum { value = true }; };
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  template <> struct isStructureChainValid<RayTracingPipelineCreateInfoKHR, DeferredOperationInfoKHR>{ enum { value = true }; };
+  template <> struct isStructureChainValid<AccelerationStructureBuildGeometryInfoKHR, DeferredOperationInfoKHR>{ enum { value = true }; };
+  template <> struct isStructureChainValid<CopyAccelerationStructureInfoKHR, DeferredOperationInfoKHR>{ enum { value = true }; };
+  template <> struct isStructureChainValid<CopyMemoryToAccelerationStructureInfoKHR, DeferredOperationInfoKHR>{ enum { value = true }; };
+  template <> struct isStructureChainValid<CopyAccelerationStructureToMemoryInfoKHR, DeferredOperationInfoKHR>{ enum { value = true }; };
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
   template <> struct isStructureChainValid<DescriptorPoolCreateInfo, DescriptorPoolInlineUniformBlockCreateInfoEXT>{ enum { value = true }; };
   template <> struct isStructureChainValid<DescriptorSetLayoutCreateInfo, DescriptorSetLayoutBindingFlagsCreateInfo>{ enum { value = true }; };
   template <> struct isStructureChainValid<DescriptorSetAllocateInfo, DescriptorSetVariableDescriptorCountAllocateInfo>{ enum { value = true }; };
   template <> struct isStructureChainValid<DescriptorSetLayoutSupport, DescriptorSetVariableDescriptorCountLayoutSupport>{ enum { value = true }; };
+  template <> struct isStructureChainValid<DeviceCreateInfo, DeviceDiagnosticsConfigCreateInfoNV>{ enum { value = true }; };
   template <> struct isStructureChainValid<BindSparseInfo, DeviceGroupBindSparseInfo>{ enum { value = true }; };
   template <> struct isStructureChainValid<CommandBufferBeginInfo, DeviceGroupCommandBufferBeginInfo>{ enum { value = true }; };
   template <> struct isStructureChainValid<DeviceCreateInfo, DeviceGroupDeviceCreateInfo>{ enum { value = true }; };
@@ -76669,6 +75808,7 @@
   template <> struct isStructureChainValid<ImageCreateInfo, ExternalMemoryImageCreateInfoNV>{ enum { value = true }; };
   template <> struct isStructureChainValid<ImageFormatProperties2, FilterCubicImageViewImageFormatPropertiesEXT>{ enum { value = true }; };
   template <> struct isStructureChainValid<FramebufferCreateInfo, FramebufferAttachmentsCreateInfo>{ enum { value = true }; };
+  template <> struct isStructureChainValid<GraphicsPipelineCreateInfo, GraphicsPipelineShaderGroupsCreateInfoNV>{ enum { value = true }; };
   template <> struct isStructureChainValid<ImageCreateInfo, ImageDrmFormatModifierExplicitCreateInfoEXT>{ enum { value = true }; };
   template <> struct isStructureChainValid<ImageCreateInfo, ImageDrmFormatModifierListCreateInfoEXT>{ enum { value = true }; };
   template <> struct isStructureChainValid<ImageCreateInfo, ImageFormatListCreateInfo>{ enum { value = true }; };
@@ -76732,6 +75872,11 @@
   template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceDescriptorIndexingFeatures>{ enum { value = true }; };
   template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceDescriptorIndexingFeatures>{ enum { value = true }; };
   template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDeviceDescriptorIndexingProperties>{ enum { value = true }; };
+  template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceDeviceGeneratedCommandsFeaturesNV>{ enum { value = true }; };
+  template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceDeviceGeneratedCommandsFeaturesNV>{ enum { value = true }; };
+  template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDeviceDeviceGeneratedCommandsPropertiesNV>{ enum { value = true }; };
+  template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceDiagnosticsConfigFeaturesNV>{ enum { value = true }; };
+  template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceDiagnosticsConfigFeaturesNV>{ enum { value = true }; };
   template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDeviceDiscardRectanglePropertiesEXT>{ enum { value = true }; };
   template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDeviceDriverProperties>{ enum { value = true }; };
   template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceExclusiveScissorFeaturesNV>{ enum { value = true }; };
@@ -76777,6 +75922,8 @@
   template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDevicePerformanceQueryFeaturesKHR>{ enum { value = true }; };
   template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDevicePerformanceQueryFeaturesKHR>{ enum { value = true }; };
   template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDevicePerformanceQueryPropertiesKHR>{ enum { value = true }; };
+  template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDevicePipelineCreationCacheControlFeaturesEXT>{ enum { value = true }; };
+  template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDevicePipelineCreationCacheControlFeaturesEXT>{ enum { value = true }; };
   template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDevicePipelineExecutablePropertiesFeaturesKHR>{ enum { value = true }; };
   template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDevicePipelineExecutablePropertiesFeaturesKHR>{ enum { value = true }; };
   template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDevicePointClippingProperties>{ enum { value = true }; };
@@ -76784,6 +75931,13 @@
   template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceProtectedMemoryFeatures>{ enum { value = true }; };
   template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDeviceProtectedMemoryProperties>{ enum { value = true }; };
   template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDevicePushDescriptorPropertiesKHR>{ enum { value = true }; };
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceRayTracingFeaturesKHR>{ enum { value = true }; };
+  template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceRayTracingFeaturesKHR>{ enum { value = true }; };
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDeviceRayTracingPropertiesKHR>{ enum { value = true }; };
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
   template <> struct isStructureChainValid<PhysicalDeviceProperties2, PhysicalDeviceRayTracingPropertiesNV>{ enum { value = true }; };
   template <> struct isStructureChainValid<PhysicalDeviceFeatures2, PhysicalDeviceRepresentativeFragmentTestFeaturesNV>{ enum { value = true }; };
   template <> struct isStructureChainValid<DeviceCreateInfo, PhysicalDeviceRepresentativeFragmentTestFeaturesNV>{ enum { value = true }; };
@@ -76860,6 +76014,9 @@
   template <> struct isStructureChainValid<GraphicsPipelineCreateInfo, PipelineCreationFeedbackCreateInfoEXT>{ enum { value = true }; };
   template <> struct isStructureChainValid<ComputePipelineCreateInfo, PipelineCreationFeedbackCreateInfoEXT>{ enum { value = true }; };
   template <> struct isStructureChainValid<RayTracingPipelineCreateInfoNV, PipelineCreationFeedbackCreateInfoEXT>{ enum { value = true }; };
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  template <> struct isStructureChainValid<RayTracingPipelineCreateInfoKHR, PipelineCreationFeedbackCreateInfoEXT>{ enum { value = true }; };
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
   template <> struct isStructureChainValid<GraphicsPipelineCreateInfo, PipelineDiscardRectangleStateCreateInfoEXT>{ enum { value = true }; };
   template <> struct isStructureChainValid<PipelineRasterizationStateCreateInfo, PipelineRasterizationConservativeStateCreateInfoEXT>{ enum { value = true }; };
   template <> struct isStructureChainValid<PipelineRasterizationStateCreateInfo, PipelineRasterizationDepthClipStateCreateInfoEXT>{ enum { value = true }; };
@@ -76882,8 +76039,8 @@
   template <> struct isStructureChainValid<PresentInfoKHR, PresentRegionsKHR>{ enum { value = true }; };
   template <> struct isStructureChainValid<PresentInfoKHR, PresentTimesInfoGOOGLE>{ enum { value = true }; };
   template <> struct isStructureChainValid<SubmitInfo, ProtectedSubmitInfo>{ enum { value = true }; };
-  template <> struct isStructureChainValid<QueryPoolCreateInfo, QueryPoolCreateInfoINTEL>{ enum { value = true }; };
   template <> struct isStructureChainValid<QueryPoolCreateInfo, QueryPoolPerformanceCreateInfoKHR>{ enum { value = true }; };
+  template <> struct isStructureChainValid<QueryPoolCreateInfo, QueryPoolPerformanceQueryCreateInfoINTEL>{ enum { value = true }; };
   template <> struct isStructureChainValid<QueueFamilyProperties2, QueueFamilyCheckpointPropertiesNV>{ enum { value = true }; };
   template <> struct isStructureChainValid<RenderPassBeginInfo, RenderPassAttachmentBeginInfo>{ enum { value = true }; };
   template <> struct isStructureChainValid<RenderPassCreateInfo, RenderPassFragmentDensityMapCreateInfoEXT>{ enum { value = true }; };
@@ -76927,7 +76084,7 @@
 #ifdef VK_USE_PLATFORM_WIN32_KHR
   template <> struct isStructureChainValid<SubmitInfo, Win32KeyedMutexAcquireReleaseInfoNV>{ enum { value = true }; };
 #endif /*VK_USE_PLATFORM_WIN32_KHR*/
-  template <> struct isStructureChainValid<WriteDescriptorSet, WriteDescriptorSetAccelerationStructureNV>{ enum { value = true }; };
+  template <> struct isStructureChainValid<WriteDescriptorSet, WriteDescriptorSetAccelerationStructureKHR>{ enum { value = true }; };
   template <> struct isStructureChainValid<WriteDescriptorSet, WriteDescriptorSetInlineUniformBlockEXT>{ enum { value = true }; };
 
 #if VULKAN_HPP_ENABLE_DYNAMIC_LOADER_TOOL
@@ -77033,19 +76190,35 @@
     PFN_vkCmdBindDescriptorSets vkCmdBindDescriptorSets = 0;
     PFN_vkCmdBindIndexBuffer vkCmdBindIndexBuffer = 0;
     PFN_vkCmdBindPipeline vkCmdBindPipeline = 0;
+    PFN_vkCmdBindPipelineShaderGroupNV vkCmdBindPipelineShaderGroupNV = 0;
     PFN_vkCmdBindShadingRateImageNV vkCmdBindShadingRateImageNV = 0;
     PFN_vkCmdBindTransformFeedbackBuffersEXT vkCmdBindTransformFeedbackBuffersEXT = 0;
     PFN_vkCmdBindVertexBuffers vkCmdBindVertexBuffers = 0;
     PFN_vkCmdBlitImage vkCmdBlitImage = 0;
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    PFN_vkCmdBuildAccelerationStructureIndirectKHR vkCmdBuildAccelerationStructureIndirectKHR = 0;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    PFN_vkCmdBuildAccelerationStructureKHR vkCmdBuildAccelerationStructureKHR = 0;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
     PFN_vkCmdBuildAccelerationStructureNV vkCmdBuildAccelerationStructureNV = 0;
     PFN_vkCmdClearAttachments vkCmdClearAttachments = 0;
     PFN_vkCmdClearColorImage vkCmdClearColorImage = 0;
     PFN_vkCmdClearDepthStencilImage vkCmdClearDepthStencilImage = 0;
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    PFN_vkCmdCopyAccelerationStructureKHR vkCmdCopyAccelerationStructureKHR = 0;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
     PFN_vkCmdCopyAccelerationStructureNV vkCmdCopyAccelerationStructureNV = 0;
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    PFN_vkCmdCopyAccelerationStructureToMemoryKHR vkCmdCopyAccelerationStructureToMemoryKHR = 0;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
     PFN_vkCmdCopyBuffer vkCmdCopyBuffer = 0;
     PFN_vkCmdCopyBufferToImage vkCmdCopyBufferToImage = 0;
     PFN_vkCmdCopyImage vkCmdCopyImage = 0;
     PFN_vkCmdCopyImageToBuffer vkCmdCopyImageToBuffer = 0;
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    PFN_vkCmdCopyMemoryToAccelerationStructureKHR vkCmdCopyMemoryToAccelerationStructureKHR = 0;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
     PFN_vkCmdCopyQueryPoolResults vkCmdCopyQueryPoolResults = 0;
     PFN_vkCmdDebugMarkerBeginEXT vkCmdDebugMarkerBeginEXT = 0;
     PFN_vkCmdDebugMarkerEndEXT vkCmdDebugMarkerEndEXT = 0;
@@ -77077,17 +76250,17 @@
     PFN_vkCmdEndRenderPass2KHR vkCmdEndRenderPass2KHR = 0;
     PFN_vkCmdEndTransformFeedbackEXT vkCmdEndTransformFeedbackEXT = 0;
     PFN_vkCmdExecuteCommands vkCmdExecuteCommands = 0;
+    PFN_vkCmdExecuteGeneratedCommandsNV vkCmdExecuteGeneratedCommandsNV = 0;
     PFN_vkCmdFillBuffer vkCmdFillBuffer = 0;
     PFN_vkCmdInsertDebugUtilsLabelEXT vkCmdInsertDebugUtilsLabelEXT = 0;
     PFN_vkCmdNextSubpass vkCmdNextSubpass = 0;
     PFN_vkCmdNextSubpass2 vkCmdNextSubpass2 = 0;
     PFN_vkCmdNextSubpass2KHR vkCmdNextSubpass2KHR = 0;
     PFN_vkCmdPipelineBarrier vkCmdPipelineBarrier = 0;
-    PFN_vkCmdProcessCommandsNVX vkCmdProcessCommandsNVX = 0;
+    PFN_vkCmdPreprocessGeneratedCommandsNV vkCmdPreprocessGeneratedCommandsNV = 0;
     PFN_vkCmdPushConstants vkCmdPushConstants = 0;
     PFN_vkCmdPushDescriptorSetKHR vkCmdPushDescriptorSetKHR = 0;
     PFN_vkCmdPushDescriptorSetWithTemplateKHR vkCmdPushDescriptorSetWithTemplateKHR = 0;
-    PFN_vkCmdReserveSpaceForCommandsNVX vkCmdReserveSpaceForCommandsNVX = 0;
     PFN_vkCmdResetEvent vkCmdResetEvent = 0;
     PFN_vkCmdResetQueryPool vkCmdResetQueryPool = 0;
     PFN_vkCmdResolveImage vkCmdResolveImage = 0;
@@ -77114,9 +76287,16 @@
     PFN_vkCmdSetViewport vkCmdSetViewport = 0;
     PFN_vkCmdSetViewportShadingRatePaletteNV vkCmdSetViewportShadingRatePaletteNV = 0;
     PFN_vkCmdSetViewportWScalingNV vkCmdSetViewportWScalingNV = 0;
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    PFN_vkCmdTraceRaysIndirectKHR vkCmdTraceRaysIndirectKHR = 0;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    PFN_vkCmdTraceRaysKHR vkCmdTraceRaysKHR = 0;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
     PFN_vkCmdTraceRaysNV vkCmdTraceRaysNV = 0;
     PFN_vkCmdUpdateBuffer vkCmdUpdateBuffer = 0;
     PFN_vkCmdWaitEvents vkCmdWaitEvents = 0;
+    PFN_vkCmdWriteAccelerationStructuresPropertiesKHR vkCmdWriteAccelerationStructuresPropertiesKHR = 0;
     PFN_vkCmdWriteAccelerationStructuresPropertiesNV vkCmdWriteAccelerationStructuresPropertiesNV = 0;
     PFN_vkCmdWriteBufferMarkerAMD vkCmdWriteBufferMarkerAMD = 0;
     PFN_vkCmdWriteTimestamp vkCmdWriteTimestamp = 0;
@@ -77132,6 +76312,7 @@
     PFN_vkAllocateCommandBuffers vkAllocateCommandBuffers = 0;
     PFN_vkAllocateDescriptorSets vkAllocateDescriptorSets = 0;
     PFN_vkAllocateMemory vkAllocateMemory = 0;
+    PFN_vkBindAccelerationStructureMemoryKHR vkBindAccelerationStructureMemoryKHR = 0;
     PFN_vkBindAccelerationStructureMemoryNV vkBindAccelerationStructureMemoryNV = 0;
     PFN_vkBindBufferMemory vkBindBufferMemory = 0;
     PFN_vkBindBufferMemory2 vkBindBufferMemory2 = 0;
@@ -77139,12 +76320,30 @@
     PFN_vkBindImageMemory vkBindImageMemory = 0;
     PFN_vkBindImageMemory2 vkBindImageMemory2 = 0;
     PFN_vkBindImageMemory2KHR vkBindImageMemory2KHR = 0;
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    PFN_vkBuildAccelerationStructureKHR vkBuildAccelerationStructureKHR = 0;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
     PFN_vkCompileDeferredNV vkCompileDeferredNV = 0;
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    PFN_vkCopyAccelerationStructureKHR vkCopyAccelerationStructureKHR = 0;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    PFN_vkCopyAccelerationStructureToMemoryKHR vkCopyAccelerationStructureToMemoryKHR = 0;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    PFN_vkCopyMemoryToAccelerationStructureKHR vkCopyMemoryToAccelerationStructureKHR = 0;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    PFN_vkCreateAccelerationStructureKHR vkCreateAccelerationStructureKHR = 0;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
     PFN_vkCreateAccelerationStructureNV vkCreateAccelerationStructureNV = 0;
     PFN_vkCreateBuffer vkCreateBuffer = 0;
     PFN_vkCreateBufferView vkCreateBufferView = 0;
     PFN_vkCreateCommandPool vkCreateCommandPool = 0;
     PFN_vkCreateComputePipelines vkCreateComputePipelines = 0;
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    PFN_vkCreateDeferredOperationKHR vkCreateDeferredOperationKHR = 0;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
     PFN_vkCreateDescriptorPool vkCreateDescriptorPool = 0;
     PFN_vkCreateDescriptorSetLayout vkCreateDescriptorSetLayout = 0;
     PFN_vkCreateDescriptorUpdateTemplate vkCreateDescriptorUpdateTemplate = 0;
@@ -77155,11 +76354,13 @@
     PFN_vkCreateGraphicsPipelines vkCreateGraphicsPipelines = 0;
     PFN_vkCreateImage vkCreateImage = 0;
     PFN_vkCreateImageView vkCreateImageView = 0;
-    PFN_vkCreateIndirectCommandsLayoutNVX vkCreateIndirectCommandsLayoutNVX = 0;
-    PFN_vkCreateObjectTableNVX vkCreateObjectTableNVX = 0;
+    PFN_vkCreateIndirectCommandsLayoutNV vkCreateIndirectCommandsLayoutNV = 0;
     PFN_vkCreatePipelineCache vkCreatePipelineCache = 0;
     PFN_vkCreatePipelineLayout vkCreatePipelineLayout = 0;
     PFN_vkCreateQueryPool vkCreateQueryPool = 0;
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    PFN_vkCreateRayTracingPipelinesKHR vkCreateRayTracingPipelinesKHR = 0;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
     PFN_vkCreateRayTracingPipelinesNV vkCreateRayTracingPipelinesNV = 0;
     PFN_vkCreateRenderPass vkCreateRenderPass = 0;
     PFN_vkCreateRenderPass2 vkCreateRenderPass2 = 0;
@@ -77174,10 +76375,17 @@
     PFN_vkCreateValidationCacheEXT vkCreateValidationCacheEXT = 0;
     PFN_vkDebugMarkerSetObjectNameEXT vkDebugMarkerSetObjectNameEXT = 0;
     PFN_vkDebugMarkerSetObjectTagEXT vkDebugMarkerSetObjectTagEXT = 0;
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    PFN_vkDeferredOperationJoinKHR vkDeferredOperationJoinKHR = 0;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+    PFN_vkDestroyAccelerationStructureKHR vkDestroyAccelerationStructureKHR = 0;
     PFN_vkDestroyAccelerationStructureNV vkDestroyAccelerationStructureNV = 0;
     PFN_vkDestroyBuffer vkDestroyBuffer = 0;
     PFN_vkDestroyBufferView vkDestroyBufferView = 0;
     PFN_vkDestroyCommandPool vkDestroyCommandPool = 0;
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    PFN_vkDestroyDeferredOperationKHR vkDestroyDeferredOperationKHR = 0;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
     PFN_vkDestroyDescriptorPool vkDestroyDescriptorPool = 0;
     PFN_vkDestroyDescriptorSetLayout vkDestroyDescriptorSetLayout = 0;
     PFN_vkDestroyDescriptorUpdateTemplate vkDestroyDescriptorUpdateTemplate = 0;
@@ -77188,8 +76396,7 @@
     PFN_vkDestroyFramebuffer vkDestroyFramebuffer = 0;
     PFN_vkDestroyImage vkDestroyImage = 0;
     PFN_vkDestroyImageView vkDestroyImageView = 0;
-    PFN_vkDestroyIndirectCommandsLayoutNVX vkDestroyIndirectCommandsLayoutNVX = 0;
-    PFN_vkDestroyObjectTableNVX vkDestroyObjectTableNVX = 0;
+    PFN_vkDestroyIndirectCommandsLayoutNV vkDestroyIndirectCommandsLayoutNV = 0;
     PFN_vkDestroyPipeline vkDestroyPipeline = 0;
     PFN_vkDestroyPipelineCache vkDestroyPipelineCache = 0;
     PFN_vkDestroyPipelineLayout vkDestroyPipelineLayout = 0;
@@ -77208,7 +76415,13 @@
     PFN_vkFreeCommandBuffers vkFreeCommandBuffers = 0;
     PFN_vkFreeDescriptorSets vkFreeDescriptorSets = 0;
     PFN_vkFreeMemory vkFreeMemory = 0;
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    PFN_vkGetAccelerationStructureDeviceAddressKHR vkGetAccelerationStructureDeviceAddressKHR = 0;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
     PFN_vkGetAccelerationStructureHandleNV vkGetAccelerationStructureHandleNV = 0;
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    PFN_vkGetAccelerationStructureMemoryRequirementsKHR vkGetAccelerationStructureMemoryRequirementsKHR = 0;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
     PFN_vkGetAccelerationStructureMemoryRequirementsNV vkGetAccelerationStructureMemoryRequirementsNV = 0;
 #ifdef VK_USE_PLATFORM_ANDROID_KHR
     PFN_vkGetAndroidHardwareBufferPropertiesANDROID vkGetAndroidHardwareBufferPropertiesANDROID = 0;
@@ -77222,8 +76435,17 @@
     PFN_vkGetBufferOpaqueCaptureAddress vkGetBufferOpaqueCaptureAddress = 0;
     PFN_vkGetBufferOpaqueCaptureAddressKHR vkGetBufferOpaqueCaptureAddressKHR = 0;
     PFN_vkGetCalibratedTimestampsEXT vkGetCalibratedTimestampsEXT = 0;
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    PFN_vkGetDeferredOperationMaxConcurrencyKHR vkGetDeferredOperationMaxConcurrencyKHR = 0;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    PFN_vkGetDeferredOperationResultKHR vkGetDeferredOperationResultKHR = 0;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
     PFN_vkGetDescriptorSetLayoutSupport vkGetDescriptorSetLayoutSupport = 0;
     PFN_vkGetDescriptorSetLayoutSupportKHR vkGetDescriptorSetLayoutSupportKHR = 0;
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    PFN_vkGetDeviceAccelerationStructureCompatibilityKHR vkGetDeviceAccelerationStructureCompatibilityKHR = 0;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
     PFN_vkGetDeviceGroupPeerMemoryFeatures vkGetDeviceGroupPeerMemoryFeatures = 0;
     PFN_vkGetDeviceGroupPeerMemoryFeaturesKHR vkGetDeviceGroupPeerMemoryFeaturesKHR = 0;
     PFN_vkGetDeviceGroupPresentCapabilitiesKHR vkGetDeviceGroupPresentCapabilitiesKHR = 0;
@@ -77243,6 +76465,7 @@
 #ifdef VK_USE_PLATFORM_WIN32_KHR
     PFN_vkGetFenceWin32HandleKHR vkGetFenceWin32HandleKHR = 0;
 #endif /*VK_USE_PLATFORM_WIN32_KHR*/
+    PFN_vkGetGeneratedCommandsMemoryRequirementsNV vkGetGeneratedCommandsMemoryRequirementsNV = 0;
     PFN_vkGetImageDrmFormatModifierPropertiesEXT vkGetImageDrmFormatModifierPropertiesEXT = 0;
     PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements = 0;
     PFN_vkGetImageMemoryRequirements2 vkGetImageMemoryRequirements2 = 0;
@@ -77251,6 +76474,7 @@
     PFN_vkGetImageSparseMemoryRequirements2 vkGetImageSparseMemoryRequirements2 = 0;
     PFN_vkGetImageSparseMemoryRequirements2KHR vkGetImageSparseMemoryRequirements2KHR = 0;
     PFN_vkGetImageSubresourceLayout vkGetImageSubresourceLayout = 0;
+    PFN_vkGetImageViewAddressNVX vkGetImageViewAddressNVX = 0;
     PFN_vkGetImageViewHandleNVX vkGetImageViewHandleNVX = 0;
 #ifdef VK_USE_PLATFORM_ANDROID_KHR
     PFN_vkGetMemoryAndroidHardwareBufferANDROID vkGetMemoryAndroidHardwareBufferANDROID = 0;
@@ -77274,6 +76498,10 @@
     PFN_vkGetPipelineExecutablePropertiesKHR vkGetPipelineExecutablePropertiesKHR = 0;
     PFN_vkGetPipelineExecutableStatisticsKHR vkGetPipelineExecutableStatisticsKHR = 0;
     PFN_vkGetQueryPoolResults vkGetQueryPoolResults = 0;
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    PFN_vkGetRayTracingCaptureReplayShaderGroupHandlesKHR vkGetRayTracingCaptureReplayShaderGroupHandlesKHR = 0;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+    PFN_vkGetRayTracingShaderGroupHandlesKHR vkGetRayTracingShaderGroupHandlesKHR = 0;
     PFN_vkGetRayTracingShaderGroupHandlesNV vkGetRayTracingShaderGroupHandlesNV = 0;
     PFN_vkGetRefreshCycleDurationGOOGLE vkGetRefreshCycleDurationGOOGLE = 0;
     PFN_vkGetRenderAreaGranularity vkGetRenderAreaGranularity = 0;
@@ -77303,7 +76531,6 @@
     PFN_vkMergeValidationCachesEXT vkMergeValidationCachesEXT = 0;
     PFN_vkRegisterDeviceEventEXT vkRegisterDeviceEventEXT = 0;
     PFN_vkRegisterDisplayEventEXT vkRegisterDisplayEventEXT = 0;
-    PFN_vkRegisterObjectsNVX vkRegisterObjectsNVX = 0;
 #ifdef VK_USE_PLATFORM_WIN32_KHR
     PFN_vkReleaseFullScreenExclusiveModeEXT vkReleaseFullScreenExclusiveModeEXT = 0;
 #endif /*VK_USE_PLATFORM_WIN32_KHR*/
@@ -77326,13 +76553,15 @@
     PFN_vkTrimCommandPoolKHR vkTrimCommandPoolKHR = 0;
     PFN_vkUninitializePerformanceApiINTEL vkUninitializePerformanceApiINTEL = 0;
     PFN_vkUnmapMemory vkUnmapMemory = 0;
-    PFN_vkUnregisterObjectsNVX vkUnregisterObjectsNVX = 0;
     PFN_vkUpdateDescriptorSetWithTemplate vkUpdateDescriptorSetWithTemplate = 0;
     PFN_vkUpdateDescriptorSetWithTemplateKHR vkUpdateDescriptorSetWithTemplateKHR = 0;
     PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets = 0;
     PFN_vkWaitForFences vkWaitForFences = 0;
     PFN_vkWaitSemaphores vkWaitSemaphores = 0;
     PFN_vkWaitSemaphoresKHR vkWaitSemaphoresKHR = 0;
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+    PFN_vkWriteAccelerationStructuresPropertiesKHR vkWriteAccelerationStructuresPropertiesKHR = 0;
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
 #ifdef VK_USE_PLATFORM_ANDROID_KHR
     PFN_vkCreateAndroidSurfaceKHR vkCreateAndroidSurfaceKHR = 0;
 #endif /*VK_USE_PLATFORM_ANDROID_KHR*/
@@ -77412,7 +76641,6 @@
     PFN_vkGetPhysicalDeviceFormatProperties vkGetPhysicalDeviceFormatProperties = 0;
     PFN_vkGetPhysicalDeviceFormatProperties2 vkGetPhysicalDeviceFormatProperties2 = 0;
     PFN_vkGetPhysicalDeviceFormatProperties2KHR vkGetPhysicalDeviceFormatProperties2KHR = 0;
-    PFN_vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX = 0;
     PFN_vkGetPhysicalDeviceImageFormatProperties vkGetPhysicalDeviceImageFormatProperties = 0;
     PFN_vkGetPhysicalDeviceImageFormatProperties2 vkGetPhysicalDeviceImageFormatProperties2 = 0;
     PFN_vkGetPhysicalDeviceImageFormatProperties2KHR vkGetPhysicalDeviceImageFormatProperties2KHR = 0;
@@ -77609,7 +76837,6 @@
       vkGetPhysicalDeviceFormatProperties = PFN_vkGetPhysicalDeviceFormatProperties( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceFormatProperties" ) );
       vkGetPhysicalDeviceFormatProperties2 = PFN_vkGetPhysicalDeviceFormatProperties2( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceFormatProperties2" ) );
       vkGetPhysicalDeviceFormatProperties2KHR = PFN_vkGetPhysicalDeviceFormatProperties2KHR( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceFormatProperties2KHR" ) );
-      vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX = PFN_vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX" ) );
       vkGetPhysicalDeviceImageFormatProperties = PFN_vkGetPhysicalDeviceImageFormatProperties( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceImageFormatProperties" ) );
       vkGetPhysicalDeviceImageFormatProperties2 = PFN_vkGetPhysicalDeviceImageFormatProperties2( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceImageFormatProperties2" ) );
       vkGetPhysicalDeviceImageFormatProperties2KHR = PFN_vkGetPhysicalDeviceImageFormatProperties2KHR( vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceImageFormatProperties2KHR" ) );
@@ -77668,19 +76895,35 @@
       vkCmdBindDescriptorSets = PFN_vkCmdBindDescriptorSets( vkGetInstanceProcAddr( instance, "vkCmdBindDescriptorSets" ) );
       vkCmdBindIndexBuffer = PFN_vkCmdBindIndexBuffer( vkGetInstanceProcAddr( instance, "vkCmdBindIndexBuffer" ) );
       vkCmdBindPipeline = PFN_vkCmdBindPipeline( vkGetInstanceProcAddr( instance, "vkCmdBindPipeline" ) );
+      vkCmdBindPipelineShaderGroupNV = PFN_vkCmdBindPipelineShaderGroupNV( vkGetInstanceProcAddr( instance, "vkCmdBindPipelineShaderGroupNV" ) );
       vkCmdBindShadingRateImageNV = PFN_vkCmdBindShadingRateImageNV( vkGetInstanceProcAddr( instance, "vkCmdBindShadingRateImageNV" ) );
       vkCmdBindTransformFeedbackBuffersEXT = PFN_vkCmdBindTransformFeedbackBuffersEXT( vkGetInstanceProcAddr( instance, "vkCmdBindTransformFeedbackBuffersEXT" ) );
       vkCmdBindVertexBuffers = PFN_vkCmdBindVertexBuffers( vkGetInstanceProcAddr( instance, "vkCmdBindVertexBuffers" ) );
       vkCmdBlitImage = PFN_vkCmdBlitImage( vkGetInstanceProcAddr( instance, "vkCmdBlitImage" ) );
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkCmdBuildAccelerationStructureIndirectKHR = PFN_vkCmdBuildAccelerationStructureIndirectKHR( vkGetInstanceProcAddr( instance, "vkCmdBuildAccelerationStructureIndirectKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkCmdBuildAccelerationStructureKHR = PFN_vkCmdBuildAccelerationStructureKHR( vkGetInstanceProcAddr( instance, "vkCmdBuildAccelerationStructureKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
       vkCmdBuildAccelerationStructureNV = PFN_vkCmdBuildAccelerationStructureNV( vkGetInstanceProcAddr( instance, "vkCmdBuildAccelerationStructureNV" ) );
       vkCmdClearAttachments = PFN_vkCmdClearAttachments( vkGetInstanceProcAddr( instance, "vkCmdClearAttachments" ) );
       vkCmdClearColorImage = PFN_vkCmdClearColorImage( vkGetInstanceProcAddr( instance, "vkCmdClearColorImage" ) );
       vkCmdClearDepthStencilImage = PFN_vkCmdClearDepthStencilImage( vkGetInstanceProcAddr( instance, "vkCmdClearDepthStencilImage" ) );
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkCmdCopyAccelerationStructureKHR = PFN_vkCmdCopyAccelerationStructureKHR( vkGetInstanceProcAddr( instance, "vkCmdCopyAccelerationStructureKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
       vkCmdCopyAccelerationStructureNV = PFN_vkCmdCopyAccelerationStructureNV( vkGetInstanceProcAddr( instance, "vkCmdCopyAccelerationStructureNV" ) );
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkCmdCopyAccelerationStructureToMemoryKHR = PFN_vkCmdCopyAccelerationStructureToMemoryKHR( vkGetInstanceProcAddr( instance, "vkCmdCopyAccelerationStructureToMemoryKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
       vkCmdCopyBuffer = PFN_vkCmdCopyBuffer( vkGetInstanceProcAddr( instance, "vkCmdCopyBuffer" ) );
       vkCmdCopyBufferToImage = PFN_vkCmdCopyBufferToImage( vkGetInstanceProcAddr( instance, "vkCmdCopyBufferToImage" ) );
       vkCmdCopyImage = PFN_vkCmdCopyImage( vkGetInstanceProcAddr( instance, "vkCmdCopyImage" ) );
       vkCmdCopyImageToBuffer = PFN_vkCmdCopyImageToBuffer( vkGetInstanceProcAddr( instance, "vkCmdCopyImageToBuffer" ) );
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkCmdCopyMemoryToAccelerationStructureKHR = PFN_vkCmdCopyMemoryToAccelerationStructureKHR( vkGetInstanceProcAddr( instance, "vkCmdCopyMemoryToAccelerationStructureKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
       vkCmdCopyQueryPoolResults = PFN_vkCmdCopyQueryPoolResults( vkGetInstanceProcAddr( instance, "vkCmdCopyQueryPoolResults" ) );
       vkCmdDebugMarkerBeginEXT = PFN_vkCmdDebugMarkerBeginEXT( vkGetInstanceProcAddr( instance, "vkCmdDebugMarkerBeginEXT" ) );
       vkCmdDebugMarkerEndEXT = PFN_vkCmdDebugMarkerEndEXT( vkGetInstanceProcAddr( instance, "vkCmdDebugMarkerEndEXT" ) );
@@ -77712,17 +76955,17 @@
       vkCmdEndRenderPass2KHR = PFN_vkCmdEndRenderPass2KHR( vkGetInstanceProcAddr( instance, "vkCmdEndRenderPass2KHR" ) );
       vkCmdEndTransformFeedbackEXT = PFN_vkCmdEndTransformFeedbackEXT( vkGetInstanceProcAddr( instance, "vkCmdEndTransformFeedbackEXT" ) );
       vkCmdExecuteCommands = PFN_vkCmdExecuteCommands( vkGetInstanceProcAddr( instance, "vkCmdExecuteCommands" ) );
+      vkCmdExecuteGeneratedCommandsNV = PFN_vkCmdExecuteGeneratedCommandsNV( vkGetInstanceProcAddr( instance, "vkCmdExecuteGeneratedCommandsNV" ) );
       vkCmdFillBuffer = PFN_vkCmdFillBuffer( vkGetInstanceProcAddr( instance, "vkCmdFillBuffer" ) );
       vkCmdInsertDebugUtilsLabelEXT = PFN_vkCmdInsertDebugUtilsLabelEXT( vkGetInstanceProcAddr( instance, "vkCmdInsertDebugUtilsLabelEXT" ) );
       vkCmdNextSubpass = PFN_vkCmdNextSubpass( vkGetInstanceProcAddr( instance, "vkCmdNextSubpass" ) );
       vkCmdNextSubpass2 = PFN_vkCmdNextSubpass2( vkGetInstanceProcAddr( instance, "vkCmdNextSubpass2" ) );
       vkCmdNextSubpass2KHR = PFN_vkCmdNextSubpass2KHR( vkGetInstanceProcAddr( instance, "vkCmdNextSubpass2KHR" ) );
       vkCmdPipelineBarrier = PFN_vkCmdPipelineBarrier( vkGetInstanceProcAddr( instance, "vkCmdPipelineBarrier" ) );
-      vkCmdProcessCommandsNVX = PFN_vkCmdProcessCommandsNVX( vkGetInstanceProcAddr( instance, "vkCmdProcessCommandsNVX" ) );
+      vkCmdPreprocessGeneratedCommandsNV = PFN_vkCmdPreprocessGeneratedCommandsNV( vkGetInstanceProcAddr( instance, "vkCmdPreprocessGeneratedCommandsNV" ) );
       vkCmdPushConstants = PFN_vkCmdPushConstants( vkGetInstanceProcAddr( instance, "vkCmdPushConstants" ) );
       vkCmdPushDescriptorSetKHR = PFN_vkCmdPushDescriptorSetKHR( vkGetInstanceProcAddr( instance, "vkCmdPushDescriptorSetKHR" ) );
       vkCmdPushDescriptorSetWithTemplateKHR = PFN_vkCmdPushDescriptorSetWithTemplateKHR( vkGetInstanceProcAddr( instance, "vkCmdPushDescriptorSetWithTemplateKHR" ) );
-      vkCmdReserveSpaceForCommandsNVX = PFN_vkCmdReserveSpaceForCommandsNVX( vkGetInstanceProcAddr( instance, "vkCmdReserveSpaceForCommandsNVX" ) );
       vkCmdResetEvent = PFN_vkCmdResetEvent( vkGetInstanceProcAddr( instance, "vkCmdResetEvent" ) );
       vkCmdResetQueryPool = PFN_vkCmdResetQueryPool( vkGetInstanceProcAddr( instance, "vkCmdResetQueryPool" ) );
       vkCmdResolveImage = PFN_vkCmdResolveImage( vkGetInstanceProcAddr( instance, "vkCmdResolveImage" ) );
@@ -77749,9 +76992,16 @@
       vkCmdSetViewport = PFN_vkCmdSetViewport( vkGetInstanceProcAddr( instance, "vkCmdSetViewport" ) );
       vkCmdSetViewportShadingRatePaletteNV = PFN_vkCmdSetViewportShadingRatePaletteNV( vkGetInstanceProcAddr( instance, "vkCmdSetViewportShadingRatePaletteNV" ) );
       vkCmdSetViewportWScalingNV = PFN_vkCmdSetViewportWScalingNV( vkGetInstanceProcAddr( instance, "vkCmdSetViewportWScalingNV" ) );
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkCmdTraceRaysIndirectKHR = PFN_vkCmdTraceRaysIndirectKHR( vkGetInstanceProcAddr( instance, "vkCmdTraceRaysIndirectKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkCmdTraceRaysKHR = PFN_vkCmdTraceRaysKHR( vkGetInstanceProcAddr( instance, "vkCmdTraceRaysKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
       vkCmdTraceRaysNV = PFN_vkCmdTraceRaysNV( vkGetInstanceProcAddr( instance, "vkCmdTraceRaysNV" ) );
       vkCmdUpdateBuffer = PFN_vkCmdUpdateBuffer( vkGetInstanceProcAddr( instance, "vkCmdUpdateBuffer" ) );
       vkCmdWaitEvents = PFN_vkCmdWaitEvents( vkGetInstanceProcAddr( instance, "vkCmdWaitEvents" ) );
+      vkCmdWriteAccelerationStructuresPropertiesKHR = PFN_vkCmdWriteAccelerationStructuresPropertiesKHR( vkGetInstanceProcAddr( instance, "vkCmdWriteAccelerationStructuresPropertiesKHR" ) );
       vkCmdWriteAccelerationStructuresPropertiesNV = PFN_vkCmdWriteAccelerationStructuresPropertiesNV( vkGetInstanceProcAddr( instance, "vkCmdWriteAccelerationStructuresPropertiesNV" ) );
       vkCmdWriteBufferMarkerAMD = PFN_vkCmdWriteBufferMarkerAMD( vkGetInstanceProcAddr( instance, "vkCmdWriteBufferMarkerAMD" ) );
       vkCmdWriteTimestamp = PFN_vkCmdWriteTimestamp( vkGetInstanceProcAddr( instance, "vkCmdWriteTimestamp" ) );
@@ -77767,6 +77017,7 @@
       vkAllocateCommandBuffers = PFN_vkAllocateCommandBuffers( vkGetInstanceProcAddr( instance, "vkAllocateCommandBuffers" ) );
       vkAllocateDescriptorSets = PFN_vkAllocateDescriptorSets( vkGetInstanceProcAddr( instance, "vkAllocateDescriptorSets" ) );
       vkAllocateMemory = PFN_vkAllocateMemory( vkGetInstanceProcAddr( instance, "vkAllocateMemory" ) );
+      vkBindAccelerationStructureMemoryKHR = PFN_vkBindAccelerationStructureMemoryKHR( vkGetInstanceProcAddr( instance, "vkBindAccelerationStructureMemoryKHR" ) );
       vkBindAccelerationStructureMemoryNV = PFN_vkBindAccelerationStructureMemoryNV( vkGetInstanceProcAddr( instance, "vkBindAccelerationStructureMemoryNV" ) );
       vkBindBufferMemory = PFN_vkBindBufferMemory( vkGetInstanceProcAddr( instance, "vkBindBufferMemory" ) );
       vkBindBufferMemory2 = PFN_vkBindBufferMemory2( vkGetInstanceProcAddr( instance, "vkBindBufferMemory2" ) );
@@ -77774,12 +77025,30 @@
       vkBindImageMemory = PFN_vkBindImageMemory( vkGetInstanceProcAddr( instance, "vkBindImageMemory" ) );
       vkBindImageMemory2 = PFN_vkBindImageMemory2( vkGetInstanceProcAddr( instance, "vkBindImageMemory2" ) );
       vkBindImageMemory2KHR = PFN_vkBindImageMemory2KHR( vkGetInstanceProcAddr( instance, "vkBindImageMemory2KHR" ) );
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkBuildAccelerationStructureKHR = PFN_vkBuildAccelerationStructureKHR( vkGetInstanceProcAddr( instance, "vkBuildAccelerationStructureKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
       vkCompileDeferredNV = PFN_vkCompileDeferredNV( vkGetInstanceProcAddr( instance, "vkCompileDeferredNV" ) );
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkCopyAccelerationStructureKHR = PFN_vkCopyAccelerationStructureKHR( vkGetInstanceProcAddr( instance, "vkCopyAccelerationStructureKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkCopyAccelerationStructureToMemoryKHR = PFN_vkCopyAccelerationStructureToMemoryKHR( vkGetInstanceProcAddr( instance, "vkCopyAccelerationStructureToMemoryKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkCopyMemoryToAccelerationStructureKHR = PFN_vkCopyMemoryToAccelerationStructureKHR( vkGetInstanceProcAddr( instance, "vkCopyMemoryToAccelerationStructureKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkCreateAccelerationStructureKHR = PFN_vkCreateAccelerationStructureKHR( vkGetInstanceProcAddr( instance, "vkCreateAccelerationStructureKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
       vkCreateAccelerationStructureNV = PFN_vkCreateAccelerationStructureNV( vkGetInstanceProcAddr( instance, "vkCreateAccelerationStructureNV" ) );
       vkCreateBuffer = PFN_vkCreateBuffer( vkGetInstanceProcAddr( instance, "vkCreateBuffer" ) );
       vkCreateBufferView = PFN_vkCreateBufferView( vkGetInstanceProcAddr( instance, "vkCreateBufferView" ) );
       vkCreateCommandPool = PFN_vkCreateCommandPool( vkGetInstanceProcAddr( instance, "vkCreateCommandPool" ) );
       vkCreateComputePipelines = PFN_vkCreateComputePipelines( vkGetInstanceProcAddr( instance, "vkCreateComputePipelines" ) );
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkCreateDeferredOperationKHR = PFN_vkCreateDeferredOperationKHR( vkGetInstanceProcAddr( instance, "vkCreateDeferredOperationKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
       vkCreateDescriptorPool = PFN_vkCreateDescriptorPool( vkGetInstanceProcAddr( instance, "vkCreateDescriptorPool" ) );
       vkCreateDescriptorSetLayout = PFN_vkCreateDescriptorSetLayout( vkGetInstanceProcAddr( instance, "vkCreateDescriptorSetLayout" ) );
       vkCreateDescriptorUpdateTemplate = PFN_vkCreateDescriptorUpdateTemplate( vkGetInstanceProcAddr( instance, "vkCreateDescriptorUpdateTemplate" ) );
@@ -77790,11 +77059,13 @@
       vkCreateGraphicsPipelines = PFN_vkCreateGraphicsPipelines( vkGetInstanceProcAddr( instance, "vkCreateGraphicsPipelines" ) );
       vkCreateImage = PFN_vkCreateImage( vkGetInstanceProcAddr( instance, "vkCreateImage" ) );
       vkCreateImageView = PFN_vkCreateImageView( vkGetInstanceProcAddr( instance, "vkCreateImageView" ) );
-      vkCreateIndirectCommandsLayoutNVX = PFN_vkCreateIndirectCommandsLayoutNVX( vkGetInstanceProcAddr( instance, "vkCreateIndirectCommandsLayoutNVX" ) );
-      vkCreateObjectTableNVX = PFN_vkCreateObjectTableNVX( vkGetInstanceProcAddr( instance, "vkCreateObjectTableNVX" ) );
+      vkCreateIndirectCommandsLayoutNV = PFN_vkCreateIndirectCommandsLayoutNV( vkGetInstanceProcAddr( instance, "vkCreateIndirectCommandsLayoutNV" ) );
       vkCreatePipelineCache = PFN_vkCreatePipelineCache( vkGetInstanceProcAddr( instance, "vkCreatePipelineCache" ) );
       vkCreatePipelineLayout = PFN_vkCreatePipelineLayout( vkGetInstanceProcAddr( instance, "vkCreatePipelineLayout" ) );
       vkCreateQueryPool = PFN_vkCreateQueryPool( vkGetInstanceProcAddr( instance, "vkCreateQueryPool" ) );
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkCreateRayTracingPipelinesKHR = PFN_vkCreateRayTracingPipelinesKHR( vkGetInstanceProcAddr( instance, "vkCreateRayTracingPipelinesKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
       vkCreateRayTracingPipelinesNV = PFN_vkCreateRayTracingPipelinesNV( vkGetInstanceProcAddr( instance, "vkCreateRayTracingPipelinesNV" ) );
       vkCreateRenderPass = PFN_vkCreateRenderPass( vkGetInstanceProcAddr( instance, "vkCreateRenderPass" ) );
       vkCreateRenderPass2 = PFN_vkCreateRenderPass2( vkGetInstanceProcAddr( instance, "vkCreateRenderPass2" ) );
@@ -77809,10 +77080,17 @@
       vkCreateValidationCacheEXT = PFN_vkCreateValidationCacheEXT( vkGetInstanceProcAddr( instance, "vkCreateValidationCacheEXT" ) );
       vkDebugMarkerSetObjectNameEXT = PFN_vkDebugMarkerSetObjectNameEXT( vkGetInstanceProcAddr( instance, "vkDebugMarkerSetObjectNameEXT" ) );
       vkDebugMarkerSetObjectTagEXT = PFN_vkDebugMarkerSetObjectTagEXT( vkGetInstanceProcAddr( instance, "vkDebugMarkerSetObjectTagEXT" ) );
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkDeferredOperationJoinKHR = PFN_vkDeferredOperationJoinKHR( vkGetInstanceProcAddr( instance, "vkDeferredOperationJoinKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+      vkDestroyAccelerationStructureKHR = PFN_vkDestroyAccelerationStructureKHR( vkGetInstanceProcAddr( instance, "vkDestroyAccelerationStructureKHR" ) );
       vkDestroyAccelerationStructureNV = PFN_vkDestroyAccelerationStructureNV( vkGetInstanceProcAddr( instance, "vkDestroyAccelerationStructureNV" ) );
       vkDestroyBuffer = PFN_vkDestroyBuffer( vkGetInstanceProcAddr( instance, "vkDestroyBuffer" ) );
       vkDestroyBufferView = PFN_vkDestroyBufferView( vkGetInstanceProcAddr( instance, "vkDestroyBufferView" ) );
       vkDestroyCommandPool = PFN_vkDestroyCommandPool( vkGetInstanceProcAddr( instance, "vkDestroyCommandPool" ) );
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkDestroyDeferredOperationKHR = PFN_vkDestroyDeferredOperationKHR( vkGetInstanceProcAddr( instance, "vkDestroyDeferredOperationKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
       vkDestroyDescriptorPool = PFN_vkDestroyDescriptorPool( vkGetInstanceProcAddr( instance, "vkDestroyDescriptorPool" ) );
       vkDestroyDescriptorSetLayout = PFN_vkDestroyDescriptorSetLayout( vkGetInstanceProcAddr( instance, "vkDestroyDescriptorSetLayout" ) );
       vkDestroyDescriptorUpdateTemplate = PFN_vkDestroyDescriptorUpdateTemplate( vkGetInstanceProcAddr( instance, "vkDestroyDescriptorUpdateTemplate" ) );
@@ -77823,8 +77101,7 @@
       vkDestroyFramebuffer = PFN_vkDestroyFramebuffer( vkGetInstanceProcAddr( instance, "vkDestroyFramebuffer" ) );
       vkDestroyImage = PFN_vkDestroyImage( vkGetInstanceProcAddr( instance, "vkDestroyImage" ) );
       vkDestroyImageView = PFN_vkDestroyImageView( vkGetInstanceProcAddr( instance, "vkDestroyImageView" ) );
-      vkDestroyIndirectCommandsLayoutNVX = PFN_vkDestroyIndirectCommandsLayoutNVX( vkGetInstanceProcAddr( instance, "vkDestroyIndirectCommandsLayoutNVX" ) );
-      vkDestroyObjectTableNVX = PFN_vkDestroyObjectTableNVX( vkGetInstanceProcAddr( instance, "vkDestroyObjectTableNVX" ) );
+      vkDestroyIndirectCommandsLayoutNV = PFN_vkDestroyIndirectCommandsLayoutNV( vkGetInstanceProcAddr( instance, "vkDestroyIndirectCommandsLayoutNV" ) );
       vkDestroyPipeline = PFN_vkDestroyPipeline( vkGetInstanceProcAddr( instance, "vkDestroyPipeline" ) );
       vkDestroyPipelineCache = PFN_vkDestroyPipelineCache( vkGetInstanceProcAddr( instance, "vkDestroyPipelineCache" ) );
       vkDestroyPipelineLayout = PFN_vkDestroyPipelineLayout( vkGetInstanceProcAddr( instance, "vkDestroyPipelineLayout" ) );
@@ -77843,7 +77120,13 @@
       vkFreeCommandBuffers = PFN_vkFreeCommandBuffers( vkGetInstanceProcAddr( instance, "vkFreeCommandBuffers" ) );
       vkFreeDescriptorSets = PFN_vkFreeDescriptorSets( vkGetInstanceProcAddr( instance, "vkFreeDescriptorSets" ) );
       vkFreeMemory = PFN_vkFreeMemory( vkGetInstanceProcAddr( instance, "vkFreeMemory" ) );
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkGetAccelerationStructureDeviceAddressKHR = PFN_vkGetAccelerationStructureDeviceAddressKHR( vkGetInstanceProcAddr( instance, "vkGetAccelerationStructureDeviceAddressKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
       vkGetAccelerationStructureHandleNV = PFN_vkGetAccelerationStructureHandleNV( vkGetInstanceProcAddr( instance, "vkGetAccelerationStructureHandleNV" ) );
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkGetAccelerationStructureMemoryRequirementsKHR = PFN_vkGetAccelerationStructureMemoryRequirementsKHR( vkGetInstanceProcAddr( instance, "vkGetAccelerationStructureMemoryRequirementsKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
       vkGetAccelerationStructureMemoryRequirementsNV = PFN_vkGetAccelerationStructureMemoryRequirementsNV( vkGetInstanceProcAddr( instance, "vkGetAccelerationStructureMemoryRequirementsNV" ) );
 #ifdef VK_USE_PLATFORM_ANDROID_KHR
       vkGetAndroidHardwareBufferPropertiesANDROID = PFN_vkGetAndroidHardwareBufferPropertiesANDROID( vkGetInstanceProcAddr( instance, "vkGetAndroidHardwareBufferPropertiesANDROID" ) );
@@ -77857,8 +77140,17 @@
       vkGetBufferOpaqueCaptureAddress = PFN_vkGetBufferOpaqueCaptureAddress( vkGetInstanceProcAddr( instance, "vkGetBufferOpaqueCaptureAddress" ) );
       vkGetBufferOpaqueCaptureAddressKHR = PFN_vkGetBufferOpaqueCaptureAddressKHR( vkGetInstanceProcAddr( instance, "vkGetBufferOpaqueCaptureAddressKHR" ) );
       vkGetCalibratedTimestampsEXT = PFN_vkGetCalibratedTimestampsEXT( vkGetInstanceProcAddr( instance, "vkGetCalibratedTimestampsEXT" ) );
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkGetDeferredOperationMaxConcurrencyKHR = PFN_vkGetDeferredOperationMaxConcurrencyKHR( vkGetInstanceProcAddr( instance, "vkGetDeferredOperationMaxConcurrencyKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkGetDeferredOperationResultKHR = PFN_vkGetDeferredOperationResultKHR( vkGetInstanceProcAddr( instance, "vkGetDeferredOperationResultKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
       vkGetDescriptorSetLayoutSupport = PFN_vkGetDescriptorSetLayoutSupport( vkGetInstanceProcAddr( instance, "vkGetDescriptorSetLayoutSupport" ) );
       vkGetDescriptorSetLayoutSupportKHR = PFN_vkGetDescriptorSetLayoutSupportKHR( vkGetInstanceProcAddr( instance, "vkGetDescriptorSetLayoutSupportKHR" ) );
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkGetDeviceAccelerationStructureCompatibilityKHR = PFN_vkGetDeviceAccelerationStructureCompatibilityKHR( vkGetInstanceProcAddr( instance, "vkGetDeviceAccelerationStructureCompatibilityKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
       vkGetDeviceGroupPeerMemoryFeatures = PFN_vkGetDeviceGroupPeerMemoryFeatures( vkGetInstanceProcAddr( instance, "vkGetDeviceGroupPeerMemoryFeatures" ) );
       vkGetDeviceGroupPeerMemoryFeaturesKHR = PFN_vkGetDeviceGroupPeerMemoryFeaturesKHR( vkGetInstanceProcAddr( instance, "vkGetDeviceGroupPeerMemoryFeaturesKHR" ) );
       vkGetDeviceGroupPresentCapabilitiesKHR = PFN_vkGetDeviceGroupPresentCapabilitiesKHR( vkGetInstanceProcAddr( instance, "vkGetDeviceGroupPresentCapabilitiesKHR" ) );
@@ -77878,6 +77170,7 @@
 #ifdef VK_USE_PLATFORM_WIN32_KHR
       vkGetFenceWin32HandleKHR = PFN_vkGetFenceWin32HandleKHR( vkGetInstanceProcAddr( instance, "vkGetFenceWin32HandleKHR" ) );
 #endif /*VK_USE_PLATFORM_WIN32_KHR*/
+      vkGetGeneratedCommandsMemoryRequirementsNV = PFN_vkGetGeneratedCommandsMemoryRequirementsNV( vkGetInstanceProcAddr( instance, "vkGetGeneratedCommandsMemoryRequirementsNV" ) );
       vkGetImageDrmFormatModifierPropertiesEXT = PFN_vkGetImageDrmFormatModifierPropertiesEXT( vkGetInstanceProcAddr( instance, "vkGetImageDrmFormatModifierPropertiesEXT" ) );
       vkGetImageMemoryRequirements = PFN_vkGetImageMemoryRequirements( vkGetInstanceProcAddr( instance, "vkGetImageMemoryRequirements" ) );
       vkGetImageMemoryRequirements2 = PFN_vkGetImageMemoryRequirements2( vkGetInstanceProcAddr( instance, "vkGetImageMemoryRequirements2" ) );
@@ -77886,6 +77179,7 @@
       vkGetImageSparseMemoryRequirements2 = PFN_vkGetImageSparseMemoryRequirements2( vkGetInstanceProcAddr( instance, "vkGetImageSparseMemoryRequirements2" ) );
       vkGetImageSparseMemoryRequirements2KHR = PFN_vkGetImageSparseMemoryRequirements2KHR( vkGetInstanceProcAddr( instance, "vkGetImageSparseMemoryRequirements2KHR" ) );
       vkGetImageSubresourceLayout = PFN_vkGetImageSubresourceLayout( vkGetInstanceProcAddr( instance, "vkGetImageSubresourceLayout" ) );
+      vkGetImageViewAddressNVX = PFN_vkGetImageViewAddressNVX( vkGetInstanceProcAddr( instance, "vkGetImageViewAddressNVX" ) );
       vkGetImageViewHandleNVX = PFN_vkGetImageViewHandleNVX( vkGetInstanceProcAddr( instance, "vkGetImageViewHandleNVX" ) );
 #ifdef VK_USE_PLATFORM_ANDROID_KHR
       vkGetMemoryAndroidHardwareBufferANDROID = PFN_vkGetMemoryAndroidHardwareBufferANDROID( vkGetInstanceProcAddr( instance, "vkGetMemoryAndroidHardwareBufferANDROID" ) );
@@ -77909,6 +77203,10 @@
       vkGetPipelineExecutablePropertiesKHR = PFN_vkGetPipelineExecutablePropertiesKHR( vkGetInstanceProcAddr( instance, "vkGetPipelineExecutablePropertiesKHR" ) );
       vkGetPipelineExecutableStatisticsKHR = PFN_vkGetPipelineExecutableStatisticsKHR( vkGetInstanceProcAddr( instance, "vkGetPipelineExecutableStatisticsKHR" ) );
       vkGetQueryPoolResults = PFN_vkGetQueryPoolResults( vkGetInstanceProcAddr( instance, "vkGetQueryPoolResults" ) );
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkGetRayTracingCaptureReplayShaderGroupHandlesKHR = PFN_vkGetRayTracingCaptureReplayShaderGroupHandlesKHR( vkGetInstanceProcAddr( instance, "vkGetRayTracingCaptureReplayShaderGroupHandlesKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+      vkGetRayTracingShaderGroupHandlesKHR = PFN_vkGetRayTracingShaderGroupHandlesKHR( vkGetInstanceProcAddr( instance, "vkGetRayTracingShaderGroupHandlesKHR" ) );
       vkGetRayTracingShaderGroupHandlesNV = PFN_vkGetRayTracingShaderGroupHandlesNV( vkGetInstanceProcAddr( instance, "vkGetRayTracingShaderGroupHandlesNV" ) );
       vkGetRefreshCycleDurationGOOGLE = PFN_vkGetRefreshCycleDurationGOOGLE( vkGetInstanceProcAddr( instance, "vkGetRefreshCycleDurationGOOGLE" ) );
       vkGetRenderAreaGranularity = PFN_vkGetRenderAreaGranularity( vkGetInstanceProcAddr( instance, "vkGetRenderAreaGranularity" ) );
@@ -77938,7 +77236,6 @@
       vkMergeValidationCachesEXT = PFN_vkMergeValidationCachesEXT( vkGetInstanceProcAddr( instance, "vkMergeValidationCachesEXT" ) );
       vkRegisterDeviceEventEXT = PFN_vkRegisterDeviceEventEXT( vkGetInstanceProcAddr( instance, "vkRegisterDeviceEventEXT" ) );
       vkRegisterDisplayEventEXT = PFN_vkRegisterDisplayEventEXT( vkGetInstanceProcAddr( instance, "vkRegisterDisplayEventEXT" ) );
-      vkRegisterObjectsNVX = PFN_vkRegisterObjectsNVX( vkGetInstanceProcAddr( instance, "vkRegisterObjectsNVX" ) );
 #ifdef VK_USE_PLATFORM_WIN32_KHR
       vkReleaseFullScreenExclusiveModeEXT = PFN_vkReleaseFullScreenExclusiveModeEXT( vkGetInstanceProcAddr( instance, "vkReleaseFullScreenExclusiveModeEXT" ) );
 #endif /*VK_USE_PLATFORM_WIN32_KHR*/
@@ -77961,13 +77258,15 @@
       vkTrimCommandPoolKHR = PFN_vkTrimCommandPoolKHR( vkGetInstanceProcAddr( instance, "vkTrimCommandPoolKHR" ) );
       vkUninitializePerformanceApiINTEL = PFN_vkUninitializePerformanceApiINTEL( vkGetInstanceProcAddr( instance, "vkUninitializePerformanceApiINTEL" ) );
       vkUnmapMemory = PFN_vkUnmapMemory( vkGetInstanceProcAddr( instance, "vkUnmapMemory" ) );
-      vkUnregisterObjectsNVX = PFN_vkUnregisterObjectsNVX( vkGetInstanceProcAddr( instance, "vkUnregisterObjectsNVX" ) );
       vkUpdateDescriptorSetWithTemplate = PFN_vkUpdateDescriptorSetWithTemplate( vkGetInstanceProcAddr( instance, "vkUpdateDescriptorSetWithTemplate" ) );
       vkUpdateDescriptorSetWithTemplateKHR = PFN_vkUpdateDescriptorSetWithTemplateKHR( vkGetInstanceProcAddr( instance, "vkUpdateDescriptorSetWithTemplateKHR" ) );
       vkUpdateDescriptorSets = PFN_vkUpdateDescriptorSets( vkGetInstanceProcAddr( instance, "vkUpdateDescriptorSets" ) );
       vkWaitForFences = PFN_vkWaitForFences( vkGetInstanceProcAddr( instance, "vkWaitForFences" ) );
       vkWaitSemaphores = PFN_vkWaitSemaphores( vkGetInstanceProcAddr( instance, "vkWaitSemaphores" ) );
       vkWaitSemaphoresKHR = PFN_vkWaitSemaphoresKHR( vkGetInstanceProcAddr( instance, "vkWaitSemaphoresKHR" ) );
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkWriteAccelerationStructuresPropertiesKHR = PFN_vkWriteAccelerationStructuresPropertiesKHR( vkGetInstanceProcAddr( instance, "vkWriteAccelerationStructuresPropertiesKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
       vkGetQueueCheckpointDataNV = PFN_vkGetQueueCheckpointDataNV( vkGetInstanceProcAddr( instance, "vkGetQueueCheckpointDataNV" ) );
       vkQueueBeginDebugUtilsLabelEXT = PFN_vkQueueBeginDebugUtilsLabelEXT( vkGetInstanceProcAddr( instance, "vkQueueBeginDebugUtilsLabelEXT" ) );
       vkQueueBindSparse = PFN_vkQueueBindSparse( vkGetInstanceProcAddr( instance, "vkQueueBindSparse" ) );
@@ -77994,19 +77293,35 @@
       vkCmdBindDescriptorSets = PFN_vkCmdBindDescriptorSets( vkGetDeviceProcAddr( device, "vkCmdBindDescriptorSets" ) );
       vkCmdBindIndexBuffer = PFN_vkCmdBindIndexBuffer( vkGetDeviceProcAddr( device, "vkCmdBindIndexBuffer" ) );
       vkCmdBindPipeline = PFN_vkCmdBindPipeline( vkGetDeviceProcAddr( device, "vkCmdBindPipeline" ) );
+      vkCmdBindPipelineShaderGroupNV = PFN_vkCmdBindPipelineShaderGroupNV( vkGetDeviceProcAddr( device, "vkCmdBindPipelineShaderGroupNV" ) );
       vkCmdBindShadingRateImageNV = PFN_vkCmdBindShadingRateImageNV( vkGetDeviceProcAddr( device, "vkCmdBindShadingRateImageNV" ) );
       vkCmdBindTransformFeedbackBuffersEXT = PFN_vkCmdBindTransformFeedbackBuffersEXT( vkGetDeviceProcAddr( device, "vkCmdBindTransformFeedbackBuffersEXT" ) );
       vkCmdBindVertexBuffers = PFN_vkCmdBindVertexBuffers( vkGetDeviceProcAddr( device, "vkCmdBindVertexBuffers" ) );
       vkCmdBlitImage = PFN_vkCmdBlitImage( vkGetDeviceProcAddr( device, "vkCmdBlitImage" ) );
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkCmdBuildAccelerationStructureIndirectKHR = PFN_vkCmdBuildAccelerationStructureIndirectKHR( vkGetDeviceProcAddr( device, "vkCmdBuildAccelerationStructureIndirectKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkCmdBuildAccelerationStructureKHR = PFN_vkCmdBuildAccelerationStructureKHR( vkGetDeviceProcAddr( device, "vkCmdBuildAccelerationStructureKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
       vkCmdBuildAccelerationStructureNV = PFN_vkCmdBuildAccelerationStructureNV( vkGetDeviceProcAddr( device, "vkCmdBuildAccelerationStructureNV" ) );
       vkCmdClearAttachments = PFN_vkCmdClearAttachments( vkGetDeviceProcAddr( device, "vkCmdClearAttachments" ) );
       vkCmdClearColorImage = PFN_vkCmdClearColorImage( vkGetDeviceProcAddr( device, "vkCmdClearColorImage" ) );
       vkCmdClearDepthStencilImage = PFN_vkCmdClearDepthStencilImage( vkGetDeviceProcAddr( device, "vkCmdClearDepthStencilImage" ) );
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkCmdCopyAccelerationStructureKHR = PFN_vkCmdCopyAccelerationStructureKHR( vkGetDeviceProcAddr( device, "vkCmdCopyAccelerationStructureKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
       vkCmdCopyAccelerationStructureNV = PFN_vkCmdCopyAccelerationStructureNV( vkGetDeviceProcAddr( device, "vkCmdCopyAccelerationStructureNV" ) );
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkCmdCopyAccelerationStructureToMemoryKHR = PFN_vkCmdCopyAccelerationStructureToMemoryKHR( vkGetDeviceProcAddr( device, "vkCmdCopyAccelerationStructureToMemoryKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
       vkCmdCopyBuffer = PFN_vkCmdCopyBuffer( vkGetDeviceProcAddr( device, "vkCmdCopyBuffer" ) );
       vkCmdCopyBufferToImage = PFN_vkCmdCopyBufferToImage( vkGetDeviceProcAddr( device, "vkCmdCopyBufferToImage" ) );
       vkCmdCopyImage = PFN_vkCmdCopyImage( vkGetDeviceProcAddr( device, "vkCmdCopyImage" ) );
       vkCmdCopyImageToBuffer = PFN_vkCmdCopyImageToBuffer( vkGetDeviceProcAddr( device, "vkCmdCopyImageToBuffer" ) );
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkCmdCopyMemoryToAccelerationStructureKHR = PFN_vkCmdCopyMemoryToAccelerationStructureKHR( vkGetDeviceProcAddr( device, "vkCmdCopyMemoryToAccelerationStructureKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
       vkCmdCopyQueryPoolResults = PFN_vkCmdCopyQueryPoolResults( vkGetDeviceProcAddr( device, "vkCmdCopyQueryPoolResults" ) );
       vkCmdDebugMarkerBeginEXT = PFN_vkCmdDebugMarkerBeginEXT( vkGetDeviceProcAddr( device, "vkCmdDebugMarkerBeginEXT" ) );
       vkCmdDebugMarkerEndEXT = PFN_vkCmdDebugMarkerEndEXT( vkGetDeviceProcAddr( device, "vkCmdDebugMarkerEndEXT" ) );
@@ -78038,17 +77353,17 @@
       vkCmdEndRenderPass2KHR = PFN_vkCmdEndRenderPass2KHR( vkGetDeviceProcAddr( device, "vkCmdEndRenderPass2KHR" ) );
       vkCmdEndTransformFeedbackEXT = PFN_vkCmdEndTransformFeedbackEXT( vkGetDeviceProcAddr( device, "vkCmdEndTransformFeedbackEXT" ) );
       vkCmdExecuteCommands = PFN_vkCmdExecuteCommands( vkGetDeviceProcAddr( device, "vkCmdExecuteCommands" ) );
+      vkCmdExecuteGeneratedCommandsNV = PFN_vkCmdExecuteGeneratedCommandsNV( vkGetDeviceProcAddr( device, "vkCmdExecuteGeneratedCommandsNV" ) );
       vkCmdFillBuffer = PFN_vkCmdFillBuffer( vkGetDeviceProcAddr( device, "vkCmdFillBuffer" ) );
       vkCmdInsertDebugUtilsLabelEXT = PFN_vkCmdInsertDebugUtilsLabelEXT( vkGetDeviceProcAddr( device, "vkCmdInsertDebugUtilsLabelEXT" ) );
       vkCmdNextSubpass = PFN_vkCmdNextSubpass( vkGetDeviceProcAddr( device, "vkCmdNextSubpass" ) );
       vkCmdNextSubpass2 = PFN_vkCmdNextSubpass2( vkGetDeviceProcAddr( device, "vkCmdNextSubpass2" ) );
       vkCmdNextSubpass2KHR = PFN_vkCmdNextSubpass2KHR( vkGetDeviceProcAddr( device, "vkCmdNextSubpass2KHR" ) );
       vkCmdPipelineBarrier = PFN_vkCmdPipelineBarrier( vkGetDeviceProcAddr( device, "vkCmdPipelineBarrier" ) );
-      vkCmdProcessCommandsNVX = PFN_vkCmdProcessCommandsNVX( vkGetDeviceProcAddr( device, "vkCmdProcessCommandsNVX" ) );
+      vkCmdPreprocessGeneratedCommandsNV = PFN_vkCmdPreprocessGeneratedCommandsNV( vkGetDeviceProcAddr( device, "vkCmdPreprocessGeneratedCommandsNV" ) );
       vkCmdPushConstants = PFN_vkCmdPushConstants( vkGetDeviceProcAddr( device, "vkCmdPushConstants" ) );
       vkCmdPushDescriptorSetKHR = PFN_vkCmdPushDescriptorSetKHR( vkGetDeviceProcAddr( device, "vkCmdPushDescriptorSetKHR" ) );
       vkCmdPushDescriptorSetWithTemplateKHR = PFN_vkCmdPushDescriptorSetWithTemplateKHR( vkGetDeviceProcAddr( device, "vkCmdPushDescriptorSetWithTemplateKHR" ) );
-      vkCmdReserveSpaceForCommandsNVX = PFN_vkCmdReserveSpaceForCommandsNVX( vkGetDeviceProcAddr( device, "vkCmdReserveSpaceForCommandsNVX" ) );
       vkCmdResetEvent = PFN_vkCmdResetEvent( vkGetDeviceProcAddr( device, "vkCmdResetEvent" ) );
       vkCmdResetQueryPool = PFN_vkCmdResetQueryPool( vkGetDeviceProcAddr( device, "vkCmdResetQueryPool" ) );
       vkCmdResolveImage = PFN_vkCmdResolveImage( vkGetDeviceProcAddr( device, "vkCmdResolveImage" ) );
@@ -78075,9 +77390,16 @@
       vkCmdSetViewport = PFN_vkCmdSetViewport( vkGetDeviceProcAddr( device, "vkCmdSetViewport" ) );
       vkCmdSetViewportShadingRatePaletteNV = PFN_vkCmdSetViewportShadingRatePaletteNV( vkGetDeviceProcAddr( device, "vkCmdSetViewportShadingRatePaletteNV" ) );
       vkCmdSetViewportWScalingNV = PFN_vkCmdSetViewportWScalingNV( vkGetDeviceProcAddr( device, "vkCmdSetViewportWScalingNV" ) );
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkCmdTraceRaysIndirectKHR = PFN_vkCmdTraceRaysIndirectKHR( vkGetDeviceProcAddr( device, "vkCmdTraceRaysIndirectKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkCmdTraceRaysKHR = PFN_vkCmdTraceRaysKHR( vkGetDeviceProcAddr( device, "vkCmdTraceRaysKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
       vkCmdTraceRaysNV = PFN_vkCmdTraceRaysNV( vkGetDeviceProcAddr( device, "vkCmdTraceRaysNV" ) );
       vkCmdUpdateBuffer = PFN_vkCmdUpdateBuffer( vkGetDeviceProcAddr( device, "vkCmdUpdateBuffer" ) );
       vkCmdWaitEvents = PFN_vkCmdWaitEvents( vkGetDeviceProcAddr( device, "vkCmdWaitEvents" ) );
+      vkCmdWriteAccelerationStructuresPropertiesKHR = PFN_vkCmdWriteAccelerationStructuresPropertiesKHR( vkGetDeviceProcAddr( device, "vkCmdWriteAccelerationStructuresPropertiesKHR" ) );
       vkCmdWriteAccelerationStructuresPropertiesNV = PFN_vkCmdWriteAccelerationStructuresPropertiesNV( vkGetDeviceProcAddr( device, "vkCmdWriteAccelerationStructuresPropertiesNV" ) );
       vkCmdWriteBufferMarkerAMD = PFN_vkCmdWriteBufferMarkerAMD( vkGetDeviceProcAddr( device, "vkCmdWriteBufferMarkerAMD" ) );
       vkCmdWriteTimestamp = PFN_vkCmdWriteTimestamp( vkGetDeviceProcAddr( device, "vkCmdWriteTimestamp" ) );
@@ -78093,6 +77415,7 @@
       vkAllocateCommandBuffers = PFN_vkAllocateCommandBuffers( vkGetDeviceProcAddr( device, "vkAllocateCommandBuffers" ) );
       vkAllocateDescriptorSets = PFN_vkAllocateDescriptorSets( vkGetDeviceProcAddr( device, "vkAllocateDescriptorSets" ) );
       vkAllocateMemory = PFN_vkAllocateMemory( vkGetDeviceProcAddr( device, "vkAllocateMemory" ) );
+      vkBindAccelerationStructureMemoryKHR = PFN_vkBindAccelerationStructureMemoryKHR( vkGetDeviceProcAddr( device, "vkBindAccelerationStructureMemoryKHR" ) );
       vkBindAccelerationStructureMemoryNV = PFN_vkBindAccelerationStructureMemoryNV( vkGetDeviceProcAddr( device, "vkBindAccelerationStructureMemoryNV" ) );
       vkBindBufferMemory = PFN_vkBindBufferMemory( vkGetDeviceProcAddr( device, "vkBindBufferMemory" ) );
       vkBindBufferMemory2 = PFN_vkBindBufferMemory2( vkGetDeviceProcAddr( device, "vkBindBufferMemory2" ) );
@@ -78100,12 +77423,30 @@
       vkBindImageMemory = PFN_vkBindImageMemory( vkGetDeviceProcAddr( device, "vkBindImageMemory" ) );
       vkBindImageMemory2 = PFN_vkBindImageMemory2( vkGetDeviceProcAddr( device, "vkBindImageMemory2" ) );
       vkBindImageMemory2KHR = PFN_vkBindImageMemory2KHR( vkGetDeviceProcAddr( device, "vkBindImageMemory2KHR" ) );
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkBuildAccelerationStructureKHR = PFN_vkBuildAccelerationStructureKHR( vkGetDeviceProcAddr( device, "vkBuildAccelerationStructureKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
       vkCompileDeferredNV = PFN_vkCompileDeferredNV( vkGetDeviceProcAddr( device, "vkCompileDeferredNV" ) );
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkCopyAccelerationStructureKHR = PFN_vkCopyAccelerationStructureKHR( vkGetDeviceProcAddr( device, "vkCopyAccelerationStructureKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkCopyAccelerationStructureToMemoryKHR = PFN_vkCopyAccelerationStructureToMemoryKHR( vkGetDeviceProcAddr( device, "vkCopyAccelerationStructureToMemoryKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkCopyMemoryToAccelerationStructureKHR = PFN_vkCopyMemoryToAccelerationStructureKHR( vkGetDeviceProcAddr( device, "vkCopyMemoryToAccelerationStructureKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkCreateAccelerationStructureKHR = PFN_vkCreateAccelerationStructureKHR( vkGetDeviceProcAddr( device, "vkCreateAccelerationStructureKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
       vkCreateAccelerationStructureNV = PFN_vkCreateAccelerationStructureNV( vkGetDeviceProcAddr( device, "vkCreateAccelerationStructureNV" ) );
       vkCreateBuffer = PFN_vkCreateBuffer( vkGetDeviceProcAddr( device, "vkCreateBuffer" ) );
       vkCreateBufferView = PFN_vkCreateBufferView( vkGetDeviceProcAddr( device, "vkCreateBufferView" ) );
       vkCreateCommandPool = PFN_vkCreateCommandPool( vkGetDeviceProcAddr( device, "vkCreateCommandPool" ) );
       vkCreateComputePipelines = PFN_vkCreateComputePipelines( vkGetDeviceProcAddr( device, "vkCreateComputePipelines" ) );
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkCreateDeferredOperationKHR = PFN_vkCreateDeferredOperationKHR( vkGetDeviceProcAddr( device, "vkCreateDeferredOperationKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
       vkCreateDescriptorPool = PFN_vkCreateDescriptorPool( vkGetDeviceProcAddr( device, "vkCreateDescriptorPool" ) );
       vkCreateDescriptorSetLayout = PFN_vkCreateDescriptorSetLayout( vkGetDeviceProcAddr( device, "vkCreateDescriptorSetLayout" ) );
       vkCreateDescriptorUpdateTemplate = PFN_vkCreateDescriptorUpdateTemplate( vkGetDeviceProcAddr( device, "vkCreateDescriptorUpdateTemplate" ) );
@@ -78116,11 +77457,13 @@
       vkCreateGraphicsPipelines = PFN_vkCreateGraphicsPipelines( vkGetDeviceProcAddr( device, "vkCreateGraphicsPipelines" ) );
       vkCreateImage = PFN_vkCreateImage( vkGetDeviceProcAddr( device, "vkCreateImage" ) );
       vkCreateImageView = PFN_vkCreateImageView( vkGetDeviceProcAddr( device, "vkCreateImageView" ) );
-      vkCreateIndirectCommandsLayoutNVX = PFN_vkCreateIndirectCommandsLayoutNVX( vkGetDeviceProcAddr( device, "vkCreateIndirectCommandsLayoutNVX" ) );
-      vkCreateObjectTableNVX = PFN_vkCreateObjectTableNVX( vkGetDeviceProcAddr( device, "vkCreateObjectTableNVX" ) );
+      vkCreateIndirectCommandsLayoutNV = PFN_vkCreateIndirectCommandsLayoutNV( vkGetDeviceProcAddr( device, "vkCreateIndirectCommandsLayoutNV" ) );
       vkCreatePipelineCache = PFN_vkCreatePipelineCache( vkGetDeviceProcAddr( device, "vkCreatePipelineCache" ) );
       vkCreatePipelineLayout = PFN_vkCreatePipelineLayout( vkGetDeviceProcAddr( device, "vkCreatePipelineLayout" ) );
       vkCreateQueryPool = PFN_vkCreateQueryPool( vkGetDeviceProcAddr( device, "vkCreateQueryPool" ) );
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkCreateRayTracingPipelinesKHR = PFN_vkCreateRayTracingPipelinesKHR( vkGetDeviceProcAddr( device, "vkCreateRayTracingPipelinesKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
       vkCreateRayTracingPipelinesNV = PFN_vkCreateRayTracingPipelinesNV( vkGetDeviceProcAddr( device, "vkCreateRayTracingPipelinesNV" ) );
       vkCreateRenderPass = PFN_vkCreateRenderPass( vkGetDeviceProcAddr( device, "vkCreateRenderPass" ) );
       vkCreateRenderPass2 = PFN_vkCreateRenderPass2( vkGetDeviceProcAddr( device, "vkCreateRenderPass2" ) );
@@ -78135,10 +77478,17 @@
       vkCreateValidationCacheEXT = PFN_vkCreateValidationCacheEXT( vkGetDeviceProcAddr( device, "vkCreateValidationCacheEXT" ) );
       vkDebugMarkerSetObjectNameEXT = PFN_vkDebugMarkerSetObjectNameEXT( vkGetDeviceProcAddr( device, "vkDebugMarkerSetObjectNameEXT" ) );
       vkDebugMarkerSetObjectTagEXT = PFN_vkDebugMarkerSetObjectTagEXT( vkGetDeviceProcAddr( device, "vkDebugMarkerSetObjectTagEXT" ) );
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkDeferredOperationJoinKHR = PFN_vkDeferredOperationJoinKHR( vkGetDeviceProcAddr( device, "vkDeferredOperationJoinKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+      vkDestroyAccelerationStructureKHR = PFN_vkDestroyAccelerationStructureKHR( vkGetDeviceProcAddr( device, "vkDestroyAccelerationStructureKHR" ) );
       vkDestroyAccelerationStructureNV = PFN_vkDestroyAccelerationStructureNV( vkGetDeviceProcAddr( device, "vkDestroyAccelerationStructureNV" ) );
       vkDestroyBuffer = PFN_vkDestroyBuffer( vkGetDeviceProcAddr( device, "vkDestroyBuffer" ) );
       vkDestroyBufferView = PFN_vkDestroyBufferView( vkGetDeviceProcAddr( device, "vkDestroyBufferView" ) );
       vkDestroyCommandPool = PFN_vkDestroyCommandPool( vkGetDeviceProcAddr( device, "vkDestroyCommandPool" ) );
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkDestroyDeferredOperationKHR = PFN_vkDestroyDeferredOperationKHR( vkGetDeviceProcAddr( device, "vkDestroyDeferredOperationKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
       vkDestroyDescriptorPool = PFN_vkDestroyDescriptorPool( vkGetDeviceProcAddr( device, "vkDestroyDescriptorPool" ) );
       vkDestroyDescriptorSetLayout = PFN_vkDestroyDescriptorSetLayout( vkGetDeviceProcAddr( device, "vkDestroyDescriptorSetLayout" ) );
       vkDestroyDescriptorUpdateTemplate = PFN_vkDestroyDescriptorUpdateTemplate( vkGetDeviceProcAddr( device, "vkDestroyDescriptorUpdateTemplate" ) );
@@ -78149,8 +77499,7 @@
       vkDestroyFramebuffer = PFN_vkDestroyFramebuffer( vkGetDeviceProcAddr( device, "vkDestroyFramebuffer" ) );
       vkDestroyImage = PFN_vkDestroyImage( vkGetDeviceProcAddr( device, "vkDestroyImage" ) );
       vkDestroyImageView = PFN_vkDestroyImageView( vkGetDeviceProcAddr( device, "vkDestroyImageView" ) );
-      vkDestroyIndirectCommandsLayoutNVX = PFN_vkDestroyIndirectCommandsLayoutNVX( vkGetDeviceProcAddr( device, "vkDestroyIndirectCommandsLayoutNVX" ) );
-      vkDestroyObjectTableNVX = PFN_vkDestroyObjectTableNVX( vkGetDeviceProcAddr( device, "vkDestroyObjectTableNVX" ) );
+      vkDestroyIndirectCommandsLayoutNV = PFN_vkDestroyIndirectCommandsLayoutNV( vkGetDeviceProcAddr( device, "vkDestroyIndirectCommandsLayoutNV" ) );
       vkDestroyPipeline = PFN_vkDestroyPipeline( vkGetDeviceProcAddr( device, "vkDestroyPipeline" ) );
       vkDestroyPipelineCache = PFN_vkDestroyPipelineCache( vkGetDeviceProcAddr( device, "vkDestroyPipelineCache" ) );
       vkDestroyPipelineLayout = PFN_vkDestroyPipelineLayout( vkGetDeviceProcAddr( device, "vkDestroyPipelineLayout" ) );
@@ -78169,7 +77518,13 @@
       vkFreeCommandBuffers = PFN_vkFreeCommandBuffers( vkGetDeviceProcAddr( device, "vkFreeCommandBuffers" ) );
       vkFreeDescriptorSets = PFN_vkFreeDescriptorSets( vkGetDeviceProcAddr( device, "vkFreeDescriptorSets" ) );
       vkFreeMemory = PFN_vkFreeMemory( vkGetDeviceProcAddr( device, "vkFreeMemory" ) );
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkGetAccelerationStructureDeviceAddressKHR = PFN_vkGetAccelerationStructureDeviceAddressKHR( vkGetDeviceProcAddr( device, "vkGetAccelerationStructureDeviceAddressKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
       vkGetAccelerationStructureHandleNV = PFN_vkGetAccelerationStructureHandleNV( vkGetDeviceProcAddr( device, "vkGetAccelerationStructureHandleNV" ) );
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkGetAccelerationStructureMemoryRequirementsKHR = PFN_vkGetAccelerationStructureMemoryRequirementsKHR( vkGetDeviceProcAddr( device, "vkGetAccelerationStructureMemoryRequirementsKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
       vkGetAccelerationStructureMemoryRequirementsNV = PFN_vkGetAccelerationStructureMemoryRequirementsNV( vkGetDeviceProcAddr( device, "vkGetAccelerationStructureMemoryRequirementsNV" ) );
 #ifdef VK_USE_PLATFORM_ANDROID_KHR
       vkGetAndroidHardwareBufferPropertiesANDROID = PFN_vkGetAndroidHardwareBufferPropertiesANDROID( vkGetDeviceProcAddr( device, "vkGetAndroidHardwareBufferPropertiesANDROID" ) );
@@ -78183,8 +77538,17 @@
       vkGetBufferOpaqueCaptureAddress = PFN_vkGetBufferOpaqueCaptureAddress( vkGetDeviceProcAddr( device, "vkGetBufferOpaqueCaptureAddress" ) );
       vkGetBufferOpaqueCaptureAddressKHR = PFN_vkGetBufferOpaqueCaptureAddressKHR( vkGetDeviceProcAddr( device, "vkGetBufferOpaqueCaptureAddressKHR" ) );
       vkGetCalibratedTimestampsEXT = PFN_vkGetCalibratedTimestampsEXT( vkGetDeviceProcAddr( device, "vkGetCalibratedTimestampsEXT" ) );
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkGetDeferredOperationMaxConcurrencyKHR = PFN_vkGetDeferredOperationMaxConcurrencyKHR( vkGetDeviceProcAddr( device, "vkGetDeferredOperationMaxConcurrencyKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkGetDeferredOperationResultKHR = PFN_vkGetDeferredOperationResultKHR( vkGetDeviceProcAddr( device, "vkGetDeferredOperationResultKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
       vkGetDescriptorSetLayoutSupport = PFN_vkGetDescriptorSetLayoutSupport( vkGetDeviceProcAddr( device, "vkGetDescriptorSetLayoutSupport" ) );
       vkGetDescriptorSetLayoutSupportKHR = PFN_vkGetDescriptorSetLayoutSupportKHR( vkGetDeviceProcAddr( device, "vkGetDescriptorSetLayoutSupportKHR" ) );
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkGetDeviceAccelerationStructureCompatibilityKHR = PFN_vkGetDeviceAccelerationStructureCompatibilityKHR( vkGetDeviceProcAddr( device, "vkGetDeviceAccelerationStructureCompatibilityKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
       vkGetDeviceGroupPeerMemoryFeatures = PFN_vkGetDeviceGroupPeerMemoryFeatures( vkGetDeviceProcAddr( device, "vkGetDeviceGroupPeerMemoryFeatures" ) );
       vkGetDeviceGroupPeerMemoryFeaturesKHR = PFN_vkGetDeviceGroupPeerMemoryFeaturesKHR( vkGetDeviceProcAddr( device, "vkGetDeviceGroupPeerMemoryFeaturesKHR" ) );
       vkGetDeviceGroupPresentCapabilitiesKHR = PFN_vkGetDeviceGroupPresentCapabilitiesKHR( vkGetDeviceProcAddr( device, "vkGetDeviceGroupPresentCapabilitiesKHR" ) );
@@ -78204,6 +77568,7 @@
 #ifdef VK_USE_PLATFORM_WIN32_KHR
       vkGetFenceWin32HandleKHR = PFN_vkGetFenceWin32HandleKHR( vkGetDeviceProcAddr( device, "vkGetFenceWin32HandleKHR" ) );
 #endif /*VK_USE_PLATFORM_WIN32_KHR*/
+      vkGetGeneratedCommandsMemoryRequirementsNV = PFN_vkGetGeneratedCommandsMemoryRequirementsNV( vkGetDeviceProcAddr( device, "vkGetGeneratedCommandsMemoryRequirementsNV" ) );
       vkGetImageDrmFormatModifierPropertiesEXT = PFN_vkGetImageDrmFormatModifierPropertiesEXT( vkGetDeviceProcAddr( device, "vkGetImageDrmFormatModifierPropertiesEXT" ) );
       vkGetImageMemoryRequirements = PFN_vkGetImageMemoryRequirements( vkGetDeviceProcAddr( device, "vkGetImageMemoryRequirements" ) );
       vkGetImageMemoryRequirements2 = PFN_vkGetImageMemoryRequirements2( vkGetDeviceProcAddr( device, "vkGetImageMemoryRequirements2" ) );
@@ -78212,6 +77577,7 @@
       vkGetImageSparseMemoryRequirements2 = PFN_vkGetImageSparseMemoryRequirements2( vkGetDeviceProcAddr( device, "vkGetImageSparseMemoryRequirements2" ) );
       vkGetImageSparseMemoryRequirements2KHR = PFN_vkGetImageSparseMemoryRequirements2KHR( vkGetDeviceProcAddr( device, "vkGetImageSparseMemoryRequirements2KHR" ) );
       vkGetImageSubresourceLayout = PFN_vkGetImageSubresourceLayout( vkGetDeviceProcAddr( device, "vkGetImageSubresourceLayout" ) );
+      vkGetImageViewAddressNVX = PFN_vkGetImageViewAddressNVX( vkGetDeviceProcAddr( device, "vkGetImageViewAddressNVX" ) );
       vkGetImageViewHandleNVX = PFN_vkGetImageViewHandleNVX( vkGetDeviceProcAddr( device, "vkGetImageViewHandleNVX" ) );
 #ifdef VK_USE_PLATFORM_ANDROID_KHR
       vkGetMemoryAndroidHardwareBufferANDROID = PFN_vkGetMemoryAndroidHardwareBufferANDROID( vkGetDeviceProcAddr( device, "vkGetMemoryAndroidHardwareBufferANDROID" ) );
@@ -78235,6 +77601,10 @@
       vkGetPipelineExecutablePropertiesKHR = PFN_vkGetPipelineExecutablePropertiesKHR( vkGetDeviceProcAddr( device, "vkGetPipelineExecutablePropertiesKHR" ) );
       vkGetPipelineExecutableStatisticsKHR = PFN_vkGetPipelineExecutableStatisticsKHR( vkGetDeviceProcAddr( device, "vkGetPipelineExecutableStatisticsKHR" ) );
       vkGetQueryPoolResults = PFN_vkGetQueryPoolResults( vkGetDeviceProcAddr( device, "vkGetQueryPoolResults" ) );
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkGetRayTracingCaptureReplayShaderGroupHandlesKHR = PFN_vkGetRayTracingCaptureReplayShaderGroupHandlesKHR( vkGetDeviceProcAddr( device, "vkGetRayTracingCaptureReplayShaderGroupHandlesKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+      vkGetRayTracingShaderGroupHandlesKHR = PFN_vkGetRayTracingShaderGroupHandlesKHR( vkGetDeviceProcAddr( device, "vkGetRayTracingShaderGroupHandlesKHR" ) );
       vkGetRayTracingShaderGroupHandlesNV = PFN_vkGetRayTracingShaderGroupHandlesNV( vkGetDeviceProcAddr( device, "vkGetRayTracingShaderGroupHandlesNV" ) );
       vkGetRefreshCycleDurationGOOGLE = PFN_vkGetRefreshCycleDurationGOOGLE( vkGetDeviceProcAddr( device, "vkGetRefreshCycleDurationGOOGLE" ) );
       vkGetRenderAreaGranularity = PFN_vkGetRenderAreaGranularity( vkGetDeviceProcAddr( device, "vkGetRenderAreaGranularity" ) );
@@ -78264,7 +77634,6 @@
       vkMergeValidationCachesEXT = PFN_vkMergeValidationCachesEXT( vkGetDeviceProcAddr( device, "vkMergeValidationCachesEXT" ) );
       vkRegisterDeviceEventEXT = PFN_vkRegisterDeviceEventEXT( vkGetDeviceProcAddr( device, "vkRegisterDeviceEventEXT" ) );
       vkRegisterDisplayEventEXT = PFN_vkRegisterDisplayEventEXT( vkGetDeviceProcAddr( device, "vkRegisterDisplayEventEXT" ) );
-      vkRegisterObjectsNVX = PFN_vkRegisterObjectsNVX( vkGetDeviceProcAddr( device, "vkRegisterObjectsNVX" ) );
 #ifdef VK_USE_PLATFORM_WIN32_KHR
       vkReleaseFullScreenExclusiveModeEXT = PFN_vkReleaseFullScreenExclusiveModeEXT( vkGetDeviceProcAddr( device, "vkReleaseFullScreenExclusiveModeEXT" ) );
 #endif /*VK_USE_PLATFORM_WIN32_KHR*/
@@ -78287,13 +77656,15 @@
       vkTrimCommandPoolKHR = PFN_vkTrimCommandPoolKHR( vkGetDeviceProcAddr( device, "vkTrimCommandPoolKHR" ) );
       vkUninitializePerformanceApiINTEL = PFN_vkUninitializePerformanceApiINTEL( vkGetDeviceProcAddr( device, "vkUninitializePerformanceApiINTEL" ) );
       vkUnmapMemory = PFN_vkUnmapMemory( vkGetDeviceProcAddr( device, "vkUnmapMemory" ) );
-      vkUnregisterObjectsNVX = PFN_vkUnregisterObjectsNVX( vkGetDeviceProcAddr( device, "vkUnregisterObjectsNVX" ) );
       vkUpdateDescriptorSetWithTemplate = PFN_vkUpdateDescriptorSetWithTemplate( vkGetDeviceProcAddr( device, "vkUpdateDescriptorSetWithTemplate" ) );
       vkUpdateDescriptorSetWithTemplateKHR = PFN_vkUpdateDescriptorSetWithTemplateKHR( vkGetDeviceProcAddr( device, "vkUpdateDescriptorSetWithTemplateKHR" ) );
       vkUpdateDescriptorSets = PFN_vkUpdateDescriptorSets( vkGetDeviceProcAddr( device, "vkUpdateDescriptorSets" ) );
       vkWaitForFences = PFN_vkWaitForFences( vkGetDeviceProcAddr( device, "vkWaitForFences" ) );
       vkWaitSemaphores = PFN_vkWaitSemaphores( vkGetDeviceProcAddr( device, "vkWaitSemaphores" ) );
       vkWaitSemaphoresKHR = PFN_vkWaitSemaphoresKHR( vkGetDeviceProcAddr( device, "vkWaitSemaphoresKHR" ) );
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+      vkWriteAccelerationStructuresPropertiesKHR = PFN_vkWriteAccelerationStructuresPropertiesKHR( vkGetDeviceProcAddr( device, "vkWriteAccelerationStructuresPropertiesKHR" ) );
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
       vkGetQueueCheckpointDataNV = PFN_vkGetQueueCheckpointDataNV( vkGetDeviceProcAddr( device, "vkGetQueueCheckpointDataNV" ) );
       vkQueueBeginDebugUtilsLabelEXT = PFN_vkQueueBeginDebugUtilsLabelEXT( vkGetDeviceProcAddr( device, "vkQueueBeginDebugUtilsLabelEXT" ) );
       vkQueueBindSparse = PFN_vkQueueBindSparse( vkGetDeviceProcAddr( device, "vkQueueBindSparse" ) );
@@ -78307,4 +77678,313 @@
   };
 
 } // namespace VULKAN_HPP_NAMESPACE
+
+namespace std
+{
+  template <> struct hash<vk::AccelerationStructureKHR>
+  {
+    std::size_t operator()(vk::AccelerationStructureKHR const& accelerationStructureKHR) const VULKAN_HPP_NOEXCEPT
+    {
+      return std::hash<VkAccelerationStructureKHR>{}(static_cast<VkAccelerationStructureKHR>(accelerationStructureKHR));
+    }
+  };
+
+  template <> struct hash<vk::Buffer>
+  {
+    std::size_t operator()(vk::Buffer const& buffer) const VULKAN_HPP_NOEXCEPT
+    {
+      return std::hash<VkBuffer>{}(static_cast<VkBuffer>(buffer));
+    }
+  };
+
+  template <> struct hash<vk::BufferView>
+  {
+    std::size_t operator()(vk::BufferView const& bufferView) const VULKAN_HPP_NOEXCEPT
+    {
+      return std::hash<VkBufferView>{}(static_cast<VkBufferView>(bufferView));
+    }
+  };
+
+  template <> struct hash<vk::CommandBuffer>
+  {
+    std::size_t operator()(vk::CommandBuffer const& commandBuffer) const VULKAN_HPP_NOEXCEPT
+    {
+      return std::hash<VkCommandBuffer>{}(static_cast<VkCommandBuffer>(commandBuffer));
+    }
+  };
+
+  template <> struct hash<vk::CommandPool>
+  {
+    std::size_t operator()(vk::CommandPool const& commandPool) const VULKAN_HPP_NOEXCEPT
+    {
+      return std::hash<VkCommandPool>{}(static_cast<VkCommandPool>(commandPool));
+    }
+  };
+
+  template <> struct hash<vk::DebugReportCallbackEXT>
+  {
+    std::size_t operator()(vk::DebugReportCallbackEXT const& debugReportCallbackEXT) const VULKAN_HPP_NOEXCEPT
+    {
+      return std::hash<VkDebugReportCallbackEXT>{}(static_cast<VkDebugReportCallbackEXT>(debugReportCallbackEXT));
+    }
+  };
+
+  template <> struct hash<vk::DebugUtilsMessengerEXT>
+  {
+    std::size_t operator()(vk::DebugUtilsMessengerEXT const& debugUtilsMessengerEXT) const VULKAN_HPP_NOEXCEPT
+    {
+      return std::hash<VkDebugUtilsMessengerEXT>{}(static_cast<VkDebugUtilsMessengerEXT>(debugUtilsMessengerEXT));
+    }
+  };
+
+#ifdef VK_ENABLE_BETA_EXTENSIONS
+  template <> struct hash<vk::DeferredOperationKHR>
+  {
+    std::size_t operator()(vk::DeferredOperationKHR const& deferredOperationKHR) const VULKAN_HPP_NOEXCEPT
+    {
+      return std::hash<VkDeferredOperationKHR>{}(static_cast<VkDeferredOperationKHR>(deferredOperationKHR));
+    }
+  };
+#endif /*VK_ENABLE_BETA_EXTENSIONS*/
+
+  template <> struct hash<vk::DescriptorPool>
+  {
+    std::size_t operator()(vk::DescriptorPool const& descriptorPool) const VULKAN_HPP_NOEXCEPT
+    {
+      return std::hash<VkDescriptorPool>{}(static_cast<VkDescriptorPool>(descriptorPool));
+    }
+  };
+
+  template <> struct hash<vk::DescriptorSet>
+  {
+    std::size_t operator()(vk::DescriptorSet const& descriptorSet) const VULKAN_HPP_NOEXCEPT
+    {
+      return std::hash<VkDescriptorSet>{}(static_cast<VkDescriptorSet>(descriptorSet));
+    }
+  };
+
+  template <> struct hash<vk::DescriptorSetLayout>
+  {
+    std::size_t operator()(vk::DescriptorSetLayout const& descriptorSetLayout) const VULKAN_HPP_NOEXCEPT
+    {
+      return std::hash<VkDescriptorSetLayout>{}(static_cast<VkDescriptorSetLayout>(descriptorSetLayout));
+    }
+  };
+
+  template <> struct hash<vk::DescriptorUpdateTemplate>
+  {
+    std::size_t operator()(vk::DescriptorUpdateTemplate const& descriptorUpdateTemplate) const VULKAN_HPP_NOEXCEPT
+    {
+      return std::hash<VkDescriptorUpdateTemplate>{}(static_cast<VkDescriptorUpdateTemplate>(descriptorUpdateTemplate));
+    }
+  };
+
+  template <> struct hash<vk::Device>
+  {
+    std::size_t operator()(vk::Device const& device) const VULKAN_HPP_NOEXCEPT
+    {
+      return std::hash<VkDevice>{}(static_cast<VkDevice>(device));
+    }
+  };
+
+  template <> struct hash<vk::DeviceMemory>
+  {
+    std::size_t operator()(vk::DeviceMemory const& deviceMemory) const VULKAN_HPP_NOEXCEPT
+    {
+      return std::hash<VkDeviceMemory>{}(static_cast<VkDeviceMemory>(deviceMemory));
+    }
+  };
+
+  template <> struct hash<vk::DisplayKHR>
+  {
+    std::size_t operator()(vk::DisplayKHR const& displayKHR) const VULKAN_HPP_NOEXCEPT
+    {
+      return std::hash<VkDisplayKHR>{}(static_cast<VkDisplayKHR>(displayKHR));
+    }
+  };
+
+  template <> struct hash<vk::DisplayModeKHR>
+  {
+    std::size_t operator()(vk::DisplayModeKHR const& displayModeKHR) const VULKAN_HPP_NOEXCEPT
+    {
+      return std::hash<VkDisplayModeKHR>{}(static_cast<VkDisplayModeKHR>(displayModeKHR));
+    }
+  };
+
+  template <> struct hash<vk::Event>
+  {
+    std::size_t operator()(vk::Event const& event) const VULKAN_HPP_NOEXCEPT
+    {
+      return std::hash<VkEvent>{}(static_cast<VkEvent>(event));
+    }
+  };
+
+  template <> struct hash<vk::Fence>
+  {
+    std::size_t operator()(vk::Fence const& fence) const VULKAN_HPP_NOEXCEPT
+    {
+      return std::hash<VkFence>{}(static_cast<VkFence>(fence));
+    }
+  };
+
+  template <> struct hash<vk::Framebuffer>
+  {
+    std::size_t operator()(vk::Framebuffer const& framebuffer) const VULKAN_HPP_NOEXCEPT
+    {
+      return std::hash<VkFramebuffer>{}(static_cast<VkFramebuffer>(framebuffer));
+    }
+  };
+
+  template <> struct hash<vk::Image>
+  {
+    std::size_t operator()(vk::Image const& image) const VULKAN_HPP_NOEXCEPT
+    {
+      return std::hash<VkImage>{}(static_cast<VkImage>(image));
+    }
+  };
+
+  template <> struct hash<vk::ImageView>
+  {
+    std::size_t operator()(vk::ImageView const& imageView) const VULKAN_HPP_NOEXCEPT
+    {
+      return std::hash<VkImageView>{}(static_cast<VkImageView>(imageView));
+    }
+  };
+
+  template <> struct hash<vk::IndirectCommandsLayoutNV>
+  {
+    std::size_t operator()(vk::IndirectCommandsLayoutNV const& indirectCommandsLayoutNV) const VULKAN_HPP_NOEXCEPT
+    {
+      return std::hash<VkIndirectCommandsLayoutNV>{}(static_cast<VkIndirectCommandsLayoutNV>(indirectCommandsLayoutNV));
+    }
+  };
+
+  template <> struct hash<vk::Instance>
+  {
+    std::size_t operator()(vk::Instance const& instance) const VULKAN_HPP_NOEXCEPT
+    {
+      return std::hash<VkInstance>{}(static_cast<VkInstance>(instance));
+    }
+  };
+
+  template <> struct hash<vk::PerformanceConfigurationINTEL>
+  {
+    std::size_t operator()(vk::PerformanceConfigurationINTEL const& performanceConfigurationINTEL) const VULKAN_HPP_NOEXCEPT
+    {
+      return std::hash<VkPerformanceConfigurationINTEL>{}(static_cast<VkPerformanceConfigurationINTEL>(performanceConfigurationINTEL));
+    }
+  };
+
+  template <> struct hash<vk::PhysicalDevice>
+  {
+    std::size_t operator()(vk::PhysicalDevice const& physicalDevice) const VULKAN_HPP_NOEXCEPT
+    {
+      return std::hash<VkPhysicalDevice>{}(static_cast<VkPhysicalDevice>(physicalDevice));
+    }
+  };
+
+  template <> struct hash<vk::Pipeline>
+  {
+    std::size_t operator()(vk::Pipeline const& pipeline) const VULKAN_HPP_NOEXCEPT
+    {
+      return std::hash<VkPipeline>{}(static_cast<VkPipeline>(pipeline));
+    }
+  };
+
+  template <> struct hash<vk::PipelineCache>
+  {
+    std::size_t operator()(vk::PipelineCache const& pipelineCache) const VULKAN_HPP_NOEXCEPT
+    {
+      return std::hash<VkPipelineCache>{}(static_cast<VkPipelineCache>(pipelineCache));
+    }
+  };
+
+  template <> struct hash<vk::PipelineLayout>
+  {
+    std::size_t operator()(vk::PipelineLayout const& pipelineLayout) const VULKAN_HPP_NOEXCEPT
+    {
+      return std::hash<VkPipelineLayout>{}(static_cast<VkPipelineLayout>(pipelineLayout));
+    }
+  };
+
+  template <> struct hash<vk::QueryPool>
+  {
+    std::size_t operator()(vk::QueryPool const& queryPool) const VULKAN_HPP_NOEXCEPT
+    {
+      return std::hash<VkQueryPool>{}(static_cast<VkQueryPool>(queryPool));
+    }
+  };
+
+  template <> struct hash<vk::Queue>
+  {
+    std::size_t operator()(vk::Queue const& queue) const VULKAN_HPP_NOEXCEPT
+    {
+      return std::hash<VkQueue>{}(static_cast<VkQueue>(queue));
+    }
+  };
+
+  template <> struct hash<vk::RenderPass>
+  {
+    std::size_t operator()(vk::RenderPass const& renderPass) const VULKAN_HPP_NOEXCEPT
+    {
+      return std::hash<VkRenderPass>{}(static_cast<VkRenderPass>(renderPass));
+    }
+  };
+
+  template <> struct hash<vk::Sampler>
+  {
+    std::size_t operator()(vk::Sampler const& sampler) const VULKAN_HPP_NOEXCEPT
+    {
+      return std::hash<VkSampler>{}(static_cast<VkSampler>(sampler));
+    }
+  };
+
+  template <> struct hash<vk::SamplerYcbcrConversion>
+  {
+    std::size_t operator()(vk::SamplerYcbcrConversion const& samplerYcbcrConversion) const VULKAN_HPP_NOEXCEPT
+    {
+      return std::hash<VkSamplerYcbcrConversion>{}(static_cast<VkSamplerYcbcrConversion>(samplerYcbcrConversion));
+    }
+  };
+
+  template <> struct hash<vk::Semaphore>
+  {
+    std::size_t operator()(vk::Semaphore const& semaphore) const VULKAN_HPP_NOEXCEPT
+    {
+      return std::hash<VkSemaphore>{}(static_cast<VkSemaphore>(semaphore));
+    }
+  };
+
+  template <> struct hash<vk::ShaderModule>
+  {
+    std::size_t operator()(vk::ShaderModule const& shaderModule) const VULKAN_HPP_NOEXCEPT
+    {
+      return std::hash<VkShaderModule>{}(static_cast<VkShaderModule>(shaderModule));
+    }
+  };
+
+  template <> struct hash<vk::SurfaceKHR>
+  {
+    std::size_t operator()(vk::SurfaceKHR const& surfaceKHR) const VULKAN_HPP_NOEXCEPT
+    {
+      return std::hash<VkSurfaceKHR>{}(static_cast<VkSurfaceKHR>(surfaceKHR));
+    }
+  };
+
+  template <> struct hash<vk::SwapchainKHR>
+  {
+    std::size_t operator()(vk::SwapchainKHR const& swapchainKHR) const VULKAN_HPP_NOEXCEPT
+    {
+      return std::hash<VkSwapchainKHR>{}(static_cast<VkSwapchainKHR>(swapchainKHR));
+    }
+  };
+
+  template <> struct hash<vk::ValidationCacheEXT>
+  {
+    std::size_t operator()(vk::ValidationCacheEXT const& validationCacheEXT) const VULKAN_HPP_NOEXCEPT
+    {
+      return std::hash<VkValidationCacheEXT>{}(static_cast<VkValidationCacheEXT>(validationCacheEXT));
+    }
+  };
+}
 #endif
diff --git a/third_party/vulkan-headers/src/include/vulkan/vulkan_beta.h b/third_party/vulkan-headers/src/include/vulkan/vulkan_beta.h
new file mode 100644
index 0000000..6d0eec6
--- /dev/null
+++ b/third_party/vulkan-headers/src/include/vulkan/vulkan_beta.h
@@ -0,0 +1,441 @@
+#ifndef VULKAN_BETA_H_
+#define VULKAN_BETA_H_ 1
+
+/*
+** Copyright (c) 2015-2020 The Khronos Group 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
+**
+**     http://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.
+*/
+
+/*
+** This header is generated from the Khronos Vulkan XML API Registry.
+**
+*/
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+#define VK_KHR_deferred_host_operations 1
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDeferredOperationKHR)
+#define VK_KHR_DEFERRED_HOST_OPERATIONS_SPEC_VERSION 2
+#define VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME "VK_KHR_deferred_host_operations"
+typedef struct VkDeferredOperationInfoKHR {
+    VkStructureType           sType;
+    const void*               pNext;
+    VkDeferredOperationKHR    operationHandle;
+} VkDeferredOperationInfoKHR;
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateDeferredOperationKHR)(VkDevice device, const VkAllocationCallbacks* pAllocator, VkDeferredOperationKHR* pDeferredOperation);
+typedef void (VKAPI_PTR *PFN_vkDestroyDeferredOperationKHR)(VkDevice device, VkDeferredOperationKHR operation, const VkAllocationCallbacks* pAllocator);
+typedef uint32_t (VKAPI_PTR *PFN_vkGetDeferredOperationMaxConcurrencyKHR)(VkDevice device, VkDeferredOperationKHR operation);
+typedef VkResult (VKAPI_PTR *PFN_vkGetDeferredOperationResultKHR)(VkDevice device, VkDeferredOperationKHR operation);
+typedef VkResult (VKAPI_PTR *PFN_vkDeferredOperationJoinKHR)(VkDevice device, VkDeferredOperationKHR operation);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateDeferredOperationKHR(
+    VkDevice                                    device,
+    const VkAllocationCallbacks*                pAllocator,
+    VkDeferredOperationKHR*                     pDeferredOperation);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyDeferredOperationKHR(
+    VkDevice                                    device,
+    VkDeferredOperationKHR                      operation,
+    const VkAllocationCallbacks*                pAllocator);
+
+VKAPI_ATTR uint32_t VKAPI_CALL vkGetDeferredOperationMaxConcurrencyKHR(
+    VkDevice                                    device,
+    VkDeferredOperationKHR                      operation);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetDeferredOperationResultKHR(
+    VkDevice                                    device,
+    VkDeferredOperationKHR                      operation);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkDeferredOperationJoinKHR(
+    VkDevice                                    device,
+    VkDeferredOperationKHR                      operation);
+#endif
+
+
+#define VK_KHR_pipeline_library 1
+#define VK_KHR_PIPELINE_LIBRARY_SPEC_VERSION 1
+#define VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME "VK_KHR_pipeline_library"
+typedef struct VkPipelineLibraryCreateInfoKHR {
+    VkStructureType      sType;
+    const void*          pNext;
+    uint32_t             libraryCount;
+    const VkPipeline*    pLibraries;
+} VkPipelineLibraryCreateInfoKHR;
+
+
+
+#define VK_KHR_ray_tracing 1
+#define VK_KHR_RAY_TRACING_SPEC_VERSION   8
+#define VK_KHR_RAY_TRACING_EXTENSION_NAME "VK_KHR_ray_tracing"
+
+typedef enum VkAccelerationStructureBuildTypeKHR {
+    VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR = 0,
+    VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR = 1,
+    VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_OR_DEVICE_KHR = 2,
+    VK_ACCELERATION_STRUCTURE_BUILD_TYPE_BEGIN_RANGE_KHR = VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR,
+    VK_ACCELERATION_STRUCTURE_BUILD_TYPE_END_RANGE_KHR = VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_OR_DEVICE_KHR,
+    VK_ACCELERATION_STRUCTURE_BUILD_TYPE_RANGE_SIZE_KHR = (VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_OR_DEVICE_KHR - VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR + 1),
+    VK_ACCELERATION_STRUCTURE_BUILD_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF
+} VkAccelerationStructureBuildTypeKHR;
+typedef union VkDeviceOrHostAddressKHR {
+    VkDeviceAddress    deviceAddress;
+    void*              hostAddress;
+} VkDeviceOrHostAddressKHR;
+
+typedef union VkDeviceOrHostAddressConstKHR {
+    VkDeviceAddress    deviceAddress;
+    const void*        hostAddress;
+} VkDeviceOrHostAddressConstKHR;
+
+typedef struct VkAccelerationStructureBuildOffsetInfoKHR {
+    uint32_t    primitiveCount;
+    uint32_t    primitiveOffset;
+    uint32_t    firstVertex;
+    uint32_t    transformOffset;
+} VkAccelerationStructureBuildOffsetInfoKHR;
+
+typedef struct VkRayTracingShaderGroupCreateInfoKHR {
+    VkStructureType                   sType;
+    const void*                       pNext;
+    VkRayTracingShaderGroupTypeKHR    type;
+    uint32_t                          generalShader;
+    uint32_t                          closestHitShader;
+    uint32_t                          anyHitShader;
+    uint32_t                          intersectionShader;
+    const void*                       pShaderGroupCaptureReplayHandle;
+} VkRayTracingShaderGroupCreateInfoKHR;
+
+typedef struct VkRayTracingPipelineInterfaceCreateInfoKHR {
+    VkStructureType    sType;
+    const void*        pNext;
+    uint32_t           maxPayloadSize;
+    uint32_t           maxAttributeSize;
+    uint32_t           maxCallableSize;
+} VkRayTracingPipelineInterfaceCreateInfoKHR;
+
+typedef struct VkRayTracingPipelineCreateInfoKHR {
+    VkStructureType                                      sType;
+    const void*                                          pNext;
+    VkPipelineCreateFlags                                flags;
+    uint32_t                                             stageCount;
+    const VkPipelineShaderStageCreateInfo*               pStages;
+    uint32_t                                             groupCount;
+    const VkRayTracingShaderGroupCreateInfoKHR*          pGroups;
+    uint32_t                                             maxRecursionDepth;
+    VkPipelineLibraryCreateInfoKHR                       libraries;
+    const VkRayTracingPipelineInterfaceCreateInfoKHR*    pLibraryInterface;
+    VkPipelineLayout                                     layout;
+    VkPipeline                                           basePipelineHandle;
+    int32_t                                              basePipelineIndex;
+} VkRayTracingPipelineCreateInfoKHR;
+
+typedef struct VkAccelerationStructureGeometryTrianglesDataKHR {
+    VkStructureType                  sType;
+    const void*                      pNext;
+    VkFormat                         vertexFormat;
+    VkDeviceOrHostAddressConstKHR    vertexData;
+    VkDeviceSize                     vertexStride;
+    VkIndexType                      indexType;
+    VkDeviceOrHostAddressConstKHR    indexData;
+    VkDeviceOrHostAddressConstKHR    transformData;
+} VkAccelerationStructureGeometryTrianglesDataKHR;
+
+typedef struct VkAccelerationStructureGeometryAabbsDataKHR {
+    VkStructureType                  sType;
+    const void*                      pNext;
+    VkDeviceOrHostAddressConstKHR    data;
+    VkDeviceSize                     stride;
+} VkAccelerationStructureGeometryAabbsDataKHR;
+
+typedef struct VkAccelerationStructureGeometryInstancesDataKHR {
+    VkStructureType                  sType;
+    const void*                      pNext;
+    VkBool32                         arrayOfPointers;
+    VkDeviceOrHostAddressConstKHR    data;
+} VkAccelerationStructureGeometryInstancesDataKHR;
+
+typedef union VkAccelerationStructureGeometryDataKHR {
+    VkAccelerationStructureGeometryTrianglesDataKHR    triangles;
+    VkAccelerationStructureGeometryAabbsDataKHR        aabbs;
+    VkAccelerationStructureGeometryInstancesDataKHR    instances;
+} VkAccelerationStructureGeometryDataKHR;
+
+typedef struct VkAccelerationStructureGeometryKHR {
+    VkStructureType                           sType;
+    const void*                               pNext;
+    VkGeometryTypeKHR                         geometryType;
+    VkAccelerationStructureGeometryDataKHR    geometry;
+    VkGeometryFlagsKHR                        flags;
+} VkAccelerationStructureGeometryKHR;
+
+typedef struct VkAccelerationStructureBuildGeometryInfoKHR {
+    VkStructureType                                     sType;
+    const void*                                         pNext;
+    VkAccelerationStructureTypeKHR                      type;
+    VkBuildAccelerationStructureFlagsKHR                flags;
+    VkBool32                                            update;
+    VkAccelerationStructureKHR                          srcAccelerationStructure;
+    VkAccelerationStructureKHR                          dstAccelerationStructure;
+    VkBool32                                            geometryArrayOfPointers;
+    uint32_t                                            geometryCount;
+    const VkAccelerationStructureGeometryKHR* const*    ppGeometries;
+    VkDeviceOrHostAddressKHR                            scratchData;
+} VkAccelerationStructureBuildGeometryInfoKHR;
+
+typedef struct VkAccelerationStructureCreateGeometryTypeInfoKHR {
+    VkStructureType      sType;
+    const void*          pNext;
+    VkGeometryTypeKHR    geometryType;
+    uint32_t             maxPrimitiveCount;
+    VkIndexType          indexType;
+    uint32_t             maxVertexCount;
+    VkFormat             vertexFormat;
+    VkBool32             allowsTransforms;
+} VkAccelerationStructureCreateGeometryTypeInfoKHR;
+
+typedef struct VkAccelerationStructureCreateInfoKHR {
+    VkStructureType                                            sType;
+    const void*                                                pNext;
+    VkDeviceSize                                               compactedSize;
+    VkAccelerationStructureTypeKHR                             type;
+    VkBuildAccelerationStructureFlagsKHR                       flags;
+    uint32_t                                                   maxGeometryCount;
+    const VkAccelerationStructureCreateGeometryTypeInfoKHR*    pGeometryInfos;
+    VkDeviceAddress                                            deviceAddress;
+} VkAccelerationStructureCreateInfoKHR;
+
+typedef struct VkAccelerationStructureMemoryRequirementsInfoKHR {
+    VkStructureType                                     sType;
+    const void*                                         pNext;
+    VkAccelerationStructureMemoryRequirementsTypeKHR    type;
+    VkAccelerationStructureBuildTypeKHR                 buildType;
+    VkAccelerationStructureKHR                          accelerationStructure;
+} VkAccelerationStructureMemoryRequirementsInfoKHR;
+
+typedef struct VkPhysicalDeviceRayTracingFeaturesKHR {
+    VkStructureType    sType;
+    void*              pNext;
+    VkBool32           rayTracing;
+    VkBool32           rayTracingShaderGroupHandleCaptureReplay;
+    VkBool32           rayTracingShaderGroupHandleCaptureReplayMixed;
+    VkBool32           rayTracingAccelerationStructureCaptureReplay;
+    VkBool32           rayTracingIndirectTraceRays;
+    VkBool32           rayTracingIndirectAccelerationStructureBuild;
+    VkBool32           rayTracingHostAccelerationStructureCommands;
+    VkBool32           rayQuery;
+    VkBool32           rayTracingPrimitiveCulling;
+} VkPhysicalDeviceRayTracingFeaturesKHR;
+
+typedef struct VkPhysicalDeviceRayTracingPropertiesKHR {
+    VkStructureType    sType;
+    void*              pNext;
+    uint32_t           shaderGroupHandleSize;
+    uint32_t           maxRecursionDepth;
+    uint32_t           maxShaderGroupStride;
+    uint32_t           shaderGroupBaseAlignment;
+    uint64_t           maxGeometryCount;
+    uint64_t           maxInstanceCount;
+    uint64_t           maxPrimitiveCount;
+    uint32_t           maxDescriptorSetAccelerationStructures;
+    uint32_t           shaderGroupHandleCaptureReplaySize;
+} VkPhysicalDeviceRayTracingPropertiesKHR;
+
+typedef struct VkAccelerationStructureDeviceAddressInfoKHR {
+    VkStructureType               sType;
+    const void*                   pNext;
+    VkAccelerationStructureKHR    accelerationStructure;
+} VkAccelerationStructureDeviceAddressInfoKHR;
+
+typedef struct VkAccelerationStructureVersionKHR {
+    VkStructureType    sType;
+    const void*        pNext;
+    const uint8_t*     versionData;
+} VkAccelerationStructureVersionKHR;
+
+typedef struct VkStridedBufferRegionKHR {
+    VkBuffer        buffer;
+    VkDeviceSize    offset;
+    VkDeviceSize    stride;
+    VkDeviceSize    size;
+} VkStridedBufferRegionKHR;
+
+typedef struct VkTraceRaysIndirectCommandKHR {
+    uint32_t    width;
+    uint32_t    height;
+    uint32_t    depth;
+} VkTraceRaysIndirectCommandKHR;
+
+typedef struct VkCopyAccelerationStructureToMemoryInfoKHR {
+    VkStructureType                       sType;
+    const void*                           pNext;
+    VkAccelerationStructureKHR            src;
+    VkDeviceOrHostAddressKHR              dst;
+    VkCopyAccelerationStructureModeKHR    mode;
+} VkCopyAccelerationStructureToMemoryInfoKHR;
+
+typedef struct VkCopyMemoryToAccelerationStructureInfoKHR {
+    VkStructureType                       sType;
+    const void*                           pNext;
+    VkDeviceOrHostAddressConstKHR         src;
+    VkAccelerationStructureKHR            dst;
+    VkCopyAccelerationStructureModeKHR    mode;
+} VkCopyMemoryToAccelerationStructureInfoKHR;
+
+typedef struct VkCopyAccelerationStructureInfoKHR {
+    VkStructureType                       sType;
+    const void*                           pNext;
+    VkAccelerationStructureKHR            src;
+    VkAccelerationStructureKHR            dst;
+    VkCopyAccelerationStructureModeKHR    mode;
+} VkCopyAccelerationStructureInfoKHR;
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateAccelerationStructureKHR)(VkDevice                                           device, const VkAccelerationStructureCreateInfoKHR*        pCreateInfo, const VkAllocationCallbacks*       pAllocator, VkAccelerationStructureKHR*                        pAccelerationStructure);
+typedef void (VKAPI_PTR *PFN_vkGetAccelerationStructureMemoryRequirementsKHR)(VkDevice device, const VkAccelerationStructureMemoryRequirementsInfoKHR* pInfo, VkMemoryRequirements2* pMemoryRequirements);
+typedef void (VKAPI_PTR *PFN_vkCmdBuildAccelerationStructureKHR)(VkCommandBuffer                                    commandBuffer, uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, const VkAccelerationStructureBuildOffsetInfoKHR* const* ppOffsetInfos);
+typedef void (VKAPI_PTR *PFN_vkCmdBuildAccelerationStructureIndirectKHR)(VkCommandBuffer                                    commandBuffer, const VkAccelerationStructureBuildGeometryInfoKHR* pInfo, VkBuffer                                           indirectBuffer, VkDeviceSize                                       indirectOffset, uint32_t                                           indirectStride);
+typedef VkResult (VKAPI_PTR *PFN_vkBuildAccelerationStructureKHR)(VkDevice                                           device, uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, const VkAccelerationStructureBuildOffsetInfoKHR* const* ppOffsetInfos);
+typedef VkResult (VKAPI_PTR *PFN_vkCopyAccelerationStructureKHR)(VkDevice device, const VkCopyAccelerationStructureInfoKHR* pInfo);
+typedef VkResult (VKAPI_PTR *PFN_vkCopyAccelerationStructureToMemoryKHR)(VkDevice device, const VkCopyAccelerationStructureToMemoryInfoKHR* pInfo);
+typedef VkResult (VKAPI_PTR *PFN_vkCopyMemoryToAccelerationStructureKHR)(VkDevice device, const VkCopyMemoryToAccelerationStructureInfoKHR* pInfo);
+typedef VkResult (VKAPI_PTR *PFN_vkWriteAccelerationStructuresPropertiesKHR)(VkDevice device, uint32_t accelerationStructureCount, const VkAccelerationStructureKHR* pAccelerationStructures, VkQueryType  queryType, size_t       dataSize, void* pData, size_t stride);
+typedef void (VKAPI_PTR *PFN_vkCmdCopyAccelerationStructureKHR)(VkCommandBuffer commandBuffer, const VkCopyAccelerationStructureInfoKHR* pInfo);
+typedef void (VKAPI_PTR *PFN_vkCmdCopyAccelerationStructureToMemoryKHR)(VkCommandBuffer commandBuffer, const VkCopyAccelerationStructureToMemoryInfoKHR* pInfo);
+typedef void (VKAPI_PTR *PFN_vkCmdCopyMemoryToAccelerationStructureKHR)(VkCommandBuffer commandBuffer, const VkCopyMemoryToAccelerationStructureInfoKHR* pInfo);
+typedef void (VKAPI_PTR *PFN_vkCmdTraceRaysKHR)(VkCommandBuffer commandBuffer, const VkStridedBufferRegionKHR* pRaygenShaderBindingTable, const VkStridedBufferRegionKHR* pMissShaderBindingTable, const VkStridedBufferRegionKHR* pHitShaderBindingTable, const VkStridedBufferRegionKHR* pCallableShaderBindingTable, uint32_t width, uint32_t height, uint32_t depth);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateRayTracingPipelinesKHR)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoKHR* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines);
+typedef VkDeviceAddress (VKAPI_PTR *PFN_vkGetAccelerationStructureDeviceAddressKHR)(VkDevice device, const VkAccelerationStructureDeviceAddressInfoKHR* pInfo);
+typedef VkResult (VKAPI_PTR *PFN_vkGetRayTracingCaptureReplayShaderGroupHandlesKHR)(VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData);
+typedef void (VKAPI_PTR *PFN_vkCmdTraceRaysIndirectKHR)(VkCommandBuffer commandBuffer, const VkStridedBufferRegionKHR* pRaygenShaderBindingTable, const VkStridedBufferRegionKHR* pMissShaderBindingTable, const VkStridedBufferRegionKHR* pHitShaderBindingTable, const VkStridedBufferRegionKHR* pCallableShaderBindingTable, VkBuffer buffer, VkDeviceSize offset);
+typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceAccelerationStructureCompatibilityKHR)(VkDevice device, const VkAccelerationStructureVersionKHR* version);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateAccelerationStructureKHR(
+    VkDevice                                    device,
+    const VkAccelerationStructureCreateInfoKHR* pCreateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkAccelerationStructureKHR*                 pAccelerationStructure);
+
+VKAPI_ATTR void VKAPI_CALL vkGetAccelerationStructureMemoryRequirementsKHR(
+    VkDevice                                    device,
+    const VkAccelerationStructureMemoryRequirementsInfoKHR* pInfo,
+    VkMemoryRequirements2*                      pMemoryRequirements);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdBuildAccelerationStructureKHR(
+    VkCommandBuffer                             commandBuffer,
+    uint32_t                                    infoCount,
+    const VkAccelerationStructureBuildGeometryInfoKHR* pInfos,
+    const VkAccelerationStructureBuildOffsetInfoKHR* const* ppOffsetInfos);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdBuildAccelerationStructureIndirectKHR(
+    VkCommandBuffer                             commandBuffer,
+    const VkAccelerationStructureBuildGeometryInfoKHR* pInfo,
+    VkBuffer                                    indirectBuffer,
+    VkDeviceSize                                indirectOffset,
+    uint32_t                                    indirectStride);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkBuildAccelerationStructureKHR(
+    VkDevice                                    device,
+    uint32_t                                    infoCount,
+    const VkAccelerationStructureBuildGeometryInfoKHR* pInfos,
+    const VkAccelerationStructureBuildOffsetInfoKHR* const* ppOffsetInfos);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCopyAccelerationStructureKHR(
+    VkDevice                                    device,
+    const VkCopyAccelerationStructureInfoKHR*   pInfo);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCopyAccelerationStructureToMemoryKHR(
+    VkDevice                                    device,
+    const VkCopyAccelerationStructureToMemoryInfoKHR* pInfo);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCopyMemoryToAccelerationStructureKHR(
+    VkDevice                                    device,
+    const VkCopyMemoryToAccelerationStructureInfoKHR* pInfo);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkWriteAccelerationStructuresPropertiesKHR(
+    VkDevice                                    device,
+    uint32_t                                    accelerationStructureCount,
+    const VkAccelerationStructureKHR*           pAccelerationStructures,
+    VkQueryType                                 queryType,
+    size_t                                      dataSize,
+    void*                                       pData,
+    size_t                                      stride);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdCopyAccelerationStructureKHR(
+    VkCommandBuffer                             commandBuffer,
+    const VkCopyAccelerationStructureInfoKHR*   pInfo);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdCopyAccelerationStructureToMemoryKHR(
+    VkCommandBuffer                             commandBuffer,
+    const VkCopyAccelerationStructureToMemoryInfoKHR* pInfo);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdCopyMemoryToAccelerationStructureKHR(
+    VkCommandBuffer                             commandBuffer,
+    const VkCopyMemoryToAccelerationStructureInfoKHR* pInfo);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysKHR(
+    VkCommandBuffer                             commandBuffer,
+    const VkStridedBufferRegionKHR*             pRaygenShaderBindingTable,
+    const VkStridedBufferRegionKHR*             pMissShaderBindingTable,
+    const VkStridedBufferRegionKHR*             pHitShaderBindingTable,
+    const VkStridedBufferRegionKHR*             pCallableShaderBindingTable,
+    uint32_t                                    width,
+    uint32_t                                    height,
+    uint32_t                                    depth);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateRayTracingPipelinesKHR(
+    VkDevice                                    device,
+    VkPipelineCache                             pipelineCache,
+    uint32_t                                    createInfoCount,
+    const VkRayTracingPipelineCreateInfoKHR*    pCreateInfos,
+    const VkAllocationCallbacks*                pAllocator,
+    VkPipeline*                                 pPipelines);
+
+VKAPI_ATTR VkDeviceAddress VKAPI_CALL vkGetAccelerationStructureDeviceAddressKHR(
+    VkDevice                                    device,
+    const VkAccelerationStructureDeviceAddressInfoKHR* pInfo);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetRayTracingCaptureReplayShaderGroupHandlesKHR(
+    VkDevice                                    device,
+    VkPipeline                                  pipeline,
+    uint32_t                                    firstGroup,
+    uint32_t                                    groupCount,
+    size_t                                      dataSize,
+    void*                                       pData);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysIndirectKHR(
+    VkCommandBuffer                             commandBuffer,
+    const VkStridedBufferRegionKHR*             pRaygenShaderBindingTable,
+    const VkStridedBufferRegionKHR*             pMissShaderBindingTable,
+    const VkStridedBufferRegionKHR*             pHitShaderBindingTable,
+    const VkStridedBufferRegionKHR*             pCallableShaderBindingTable,
+    VkBuffer                                    buffer,
+    VkDeviceSize                                offset);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceAccelerationStructureCompatibilityKHR(
+    VkDevice                                    device,
+    const VkAccelerationStructureVersionKHR*    version);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/third_party/vulkan-headers/src/include/vulkan/vulkan_core.h b/third_party/vulkan-headers/src/include/vulkan/vulkan_core.h
index 2fdffa6..51c9376 100644
--- a/third_party/vulkan-headers/src/include/vulkan/vulkan_core.h
+++ b/third_party/vulkan-headers/src/include/vulkan/vulkan_core.h
@@ -44,7 +44,7 @@
 #define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff)
 #define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff)
 // Version of this file
-#define VK_HEADER_VERSION 134
+#define VK_HEADER_VERSION 137
 
 // Complete version of this file
 #define VK_HEADER_VERSION_COMPLETE VK_MAKE_VERSION(1, 2, VK_HEADER_VERSION)
@@ -148,14 +148,21 @@
     VK_ERROR_INCOMPATIBLE_DISPLAY_KHR = -1000003001,
     VK_ERROR_VALIDATION_FAILED_EXT = -1000011001,
     VK_ERROR_INVALID_SHADER_NV = -1000012000,
+    VK_ERROR_INCOMPATIBLE_VERSION_KHR = -1000150000,
     VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT = -1000158000,
     VK_ERROR_NOT_PERMITTED_EXT = -1000174001,
     VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT = -1000255000,
+    VK_THREAD_IDLE_KHR = 1000268000,
+    VK_THREAD_DONE_KHR = 1000268001,
+    VK_OPERATION_DEFERRED_KHR = 1000268002,
+    VK_OPERATION_NOT_DEFERRED_KHR = 1000268003,
+    VK_PIPELINE_COMPILE_REQUIRED_EXT = 1000297000,
     VK_ERROR_OUT_OF_POOL_MEMORY_KHR = VK_ERROR_OUT_OF_POOL_MEMORY,
     VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR = VK_ERROR_INVALID_EXTERNAL_HANDLE,
     VK_ERROR_FRAGMENTATION_EXT = VK_ERROR_FRAGMENTATION,
     VK_ERROR_INVALID_DEVICE_ADDRESS_EXT = VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS,
     VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS_KHR = VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS,
+    VK_ERROR_PIPELINE_COMPILE_REQUIRED_EXT = VK_PIPELINE_COMPILE_REQUIRED_EXT,
     VK_RESULT_BEGIN_RANGE = VK_ERROR_UNKNOWN,
     VK_RESULT_END_RANGE = VK_INCOMPLETE,
     VK_RESULT_RANGE_SIZE = (VK_INCOMPLETE - VK_ERROR_UNKNOWN + 1),
@@ -355,6 +362,7 @@
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT = 1000028001,
     VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT = 1000028002,
     VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX = 1000030000,
+    VK_STRUCTURE_TYPE_IMAGE_VIEW_ADDRESS_PROPERTIES_NVX = 1000030001,
     VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD = 1000041000,
     VK_STRUCTURE_TYPE_STREAM_DESCRIPTOR_SURFACE_CREATE_INFO_GGP = 1000049000,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CORNER_SAMPLED_IMAGE_FEATURES_NV = 1000050000,
@@ -387,12 +395,6 @@
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT = 1000081001,
     VK_STRUCTURE_TYPE_CONDITIONAL_RENDERING_BEGIN_INFO_EXT = 1000081002,
     VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR = 1000084000,
-    VK_STRUCTURE_TYPE_OBJECT_TABLE_CREATE_INFO_NVX = 1000086000,
-    VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NVX = 1000086001,
-    VK_STRUCTURE_TYPE_CMD_PROCESS_COMMANDS_INFO_NVX = 1000086002,
-    VK_STRUCTURE_TYPE_CMD_RESERVE_SPACE_FOR_COMMANDS_INFO_NVX = 1000086003,
-    VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_LIMITS_NVX = 1000086004,
-    VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_FEATURES_NVX = 1000086005,
     VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_W_SCALING_STATE_CREATE_INFO_NV = 1000087000,
     VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT = 1000090000,
     VK_STRUCTURE_TYPE_DISPLAY_POWER_INFO_EXT = 1000091000,
@@ -456,6 +458,26 @@
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT = 1000148001,
     VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT = 1000148002,
     VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_TO_COLOR_STATE_CREATE_INFO_NV = 1000149000,
+    VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_KHR = 1000165006,
+    VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR = 1000165007,
+    VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR = 1000150000,
+    VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR = 1000150001,
+    VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR = 1000150002,
+    VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR = 1000150003,
+    VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR = 1000150004,
+    VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR = 1000150005,
+    VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR = 1000150006,
+    VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR = 1000150008,
+    VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_VERSION_KHR = 1000150009,
+    VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR = 1000150010,
+    VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_TO_MEMORY_INFO_KHR = 1000150011,
+    VK_STRUCTURE_TYPE_COPY_MEMORY_TO_ACCELERATION_STRUCTURE_INFO_KHR = 1000150012,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_FEATURES_KHR = 1000150013,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_KHR = 1000150014,
+    VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR = 1000150015,
+    VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR = 1000150016,
+    VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR = 1000150017,
+    VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_INTERFACE_CREATE_INFO_KHR = 1000150018,
     VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_MODULATION_STATE_CREATE_INFO_NV = 1000152000,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_FEATURES_NV = 1000154000,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_PROPERTIES_NV = 1000154001,
@@ -476,8 +498,6 @@
     VK_STRUCTURE_TYPE_GEOMETRY_NV = 1000165003,
     VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV = 1000165004,
     VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV = 1000165005,
-    VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV = 1000165006,
-    VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_NV = 1000165007,
     VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV = 1000165008,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_NV = 1000165009,
     VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV = 1000165011,
@@ -510,7 +530,7 @@
     VK_STRUCTURE_TYPE_CHECKPOINT_DATA_NV = 1000206000,
     VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_NV = 1000206001,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_FUNCTIONS_2_FEATURES_INTEL = 1000209000,
-    VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO_INTEL = 1000210000,
+    VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_QUERY_CREATE_INFO_INTEL = 1000210000,
     VK_STRUCTURE_TYPE_INITIALIZE_PERFORMANCE_API_INFO_INTEL = 1000210001,
     VK_STRUCTURE_TYPE_PERFORMANCE_MARKER_INFO_INTEL = 1000210002,
     VK_STRUCTURE_TYPE_PERFORMANCE_STREAM_MARKER_INFO_INTEL = 1000210003,
@@ -554,6 +574,7 @@
     VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT = 1000259001,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES_EXT = 1000259002,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT = 1000265000,
+    VK_STRUCTURE_TYPE_DEFERRED_OPERATION_INFO_KHR = 1000268000,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR = 1000269000,
     VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR = 1000269001,
     VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_PROPERTIES_KHR = 1000269002,
@@ -561,10 +582,22 @@
     VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_STATISTIC_KHR = 1000269004,
     VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INTERNAL_REPRESENTATION_KHR = 1000269005,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT = 1000276000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_PROPERTIES_NV = 1000277000,
+    VK_STRUCTURE_TYPE_GRAPHICS_SHADER_GROUP_CREATE_INFO_NV = 1000277001,
+    VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_SHADER_GROUPS_CREATE_INFO_NV = 1000277002,
+    VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_TOKEN_NV = 1000277003,
+    VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NV = 1000277004,
+    VK_STRUCTURE_TYPE_GENERATED_COMMANDS_INFO_NV = 1000277005,
+    VK_STRUCTURE_TYPE_GENERATED_COMMANDS_MEMORY_REQUIREMENTS_INFO_NV = 1000277006,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_FEATURES_NV = 1000277007,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_FEATURES_EXT = 1000281000,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT = 1000281001,
     VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDER_PASS_TRANSFORM_INFO_QCOM = 1000282000,
     VK_STRUCTURE_TYPE_RENDER_PASS_TRANSFORM_BEGIN_INFO_QCOM = 1000282001,
+    VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR = 1000290000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES_EXT = 1000297000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DIAGNOSTICS_CONFIG_FEATURES_NV = 1000300000,
+    VK_STRUCTURE_TYPE_DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV = 1000300001,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES,
     VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT,
@@ -648,6 +681,8 @@
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES,
     VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO_EXT = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO,
     VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT_EXT = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT,
+    VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV = VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_KHR,
+    VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_NV = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES,
     VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT_KHR = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES,
@@ -663,6 +698,7 @@
     VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO_KHR = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO,
     VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO_KHR = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
     VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO_KHR = VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO,
+    VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO_INTEL = VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_QUERY_CREATE_INFO_INTEL,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES,
@@ -1024,8 +1060,10 @@
     VK_QUERY_TYPE_TIMESTAMP = 2,
     VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT = 1000028004,
     VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR = 1000116000,
-    VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV = 1000165000,
+    VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR = 1000165000,
+    VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR = 1000150000,
     VK_QUERY_TYPE_PERFORMANCE_QUERY_INTEL = 1000210000,
+    VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV = VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR,
     VK_QUERY_TYPE_BEGIN_RANGE = VK_QUERY_TYPE_OCCLUSION,
     VK_QUERY_TYPE_END_RANGE = VK_QUERY_TYPE_TIMESTAMP,
     VK_QUERY_TYPE_RANGE_SIZE = (VK_QUERY_TYPE_TIMESTAMP - VK_QUERY_TYPE_OCCLUSION + 1),
@@ -1367,7 +1405,8 @@
     VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC = 9,
     VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT = 10,
     VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT = 1000138000,
-    VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV = 1000165000,
+    VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR = 1000165000,
+    VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR,
     VK_DESCRIPTOR_TYPE_BEGIN_RANGE = VK_DESCRIPTOR_TYPE_SAMPLER,
     VK_DESCRIPTOR_TYPE_END_RANGE = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
     VK_DESCRIPTOR_TYPE_RANGE_SIZE = (VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT - VK_DESCRIPTOR_TYPE_SAMPLER + 1),
@@ -1387,6 +1426,7 @@
 typedef enum VkAttachmentStoreOp {
     VK_ATTACHMENT_STORE_OP_STORE = 0,
     VK_ATTACHMENT_STORE_OP_DONT_CARE = 1,
+    VK_ATTACHMENT_STORE_OP_NONE_QCOM = 1000301000,
     VK_ATTACHMENT_STORE_OP_BEGIN_RANGE = VK_ATTACHMENT_STORE_OP_STORE,
     VK_ATTACHMENT_STORE_OP_END_RANGE = VK_ATTACHMENT_STORE_OP_DONT_CARE,
     VK_ATTACHMENT_STORE_OP_RANGE_SIZE = (VK_ATTACHMENT_STORE_OP_DONT_CARE - VK_ATTACHMENT_STORE_OP_STORE + 1),
@@ -1396,7 +1436,8 @@
 typedef enum VkPipelineBindPoint {
     VK_PIPELINE_BIND_POINT_GRAPHICS = 0,
     VK_PIPELINE_BIND_POINT_COMPUTE = 1,
-    VK_PIPELINE_BIND_POINT_RAY_TRACING_NV = 1000165000,
+    VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR = 1000165000,
+    VK_PIPELINE_BIND_POINT_RAY_TRACING_NV = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR,
     VK_PIPELINE_BIND_POINT_BEGIN_RANGE = VK_PIPELINE_BIND_POINT_GRAPHICS,
     VK_PIPELINE_BIND_POINT_END_RANGE = VK_PIPELINE_BIND_POINT_COMPUTE,
     VK_PIPELINE_BIND_POINT_RANGE_SIZE = (VK_PIPELINE_BIND_POINT_COMPUTE - VK_PIPELINE_BIND_POINT_GRAPHICS + 1),
@@ -1415,8 +1456,9 @@
 typedef enum VkIndexType {
     VK_INDEX_TYPE_UINT16 = 0,
     VK_INDEX_TYPE_UINT32 = 1,
-    VK_INDEX_TYPE_NONE_NV = 1000165000,
+    VK_INDEX_TYPE_NONE_KHR = 1000165000,
     VK_INDEX_TYPE_UINT8_EXT = 1000265000,
+    VK_INDEX_TYPE_NONE_NV = VK_INDEX_TYPE_NONE_KHR,
     VK_INDEX_TYPE_BEGIN_RANGE = VK_INDEX_TYPE_UINT16,
     VK_INDEX_TYPE_END_RANGE = VK_INDEX_TYPE_UINT32,
     VK_INDEX_TYPE_RANGE_SIZE = (VK_INDEX_TYPE_UINT32 - VK_INDEX_TYPE_UINT16 + 1),
@@ -1466,14 +1508,15 @@
     VK_OBJECT_TYPE_DISPLAY_KHR = 1000002000,
     VK_OBJECT_TYPE_DISPLAY_MODE_KHR = 1000002001,
     VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT = 1000011000,
-    VK_OBJECT_TYPE_OBJECT_TABLE_NVX = 1000086000,
-    VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX = 1000086001,
     VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT = 1000128000,
+    VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR = 1000165000,
     VK_OBJECT_TYPE_VALIDATION_CACHE_EXT = 1000160000,
-    VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV = 1000165000,
     VK_OBJECT_TYPE_PERFORMANCE_CONFIGURATION_INTEL = 1000210000,
+    VK_OBJECT_TYPE_DEFERRED_OPERATION_KHR = 1000268000,
+    VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NV = 1000277000,
     VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR = VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE,
     VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR = VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION,
+    VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV = VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR,
     VK_OBJECT_TYPE_BEGIN_RANGE = VK_OBJECT_TYPE_UNKNOWN,
     VK_OBJECT_TYPE_END_RANGE = VK_OBJECT_TYPE_COMMAND_POOL,
     VK_OBJECT_TYPE_RANGE_SIZE = (VK_OBJECT_TYPE_COMMAND_POOL - VK_OBJECT_TYPE_UNKNOWN + 1),
@@ -1517,6 +1560,7 @@
     VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT = 0x00800000,
     VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT = 0x00010000,
     VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG = 0x00002000,
+    VK_FORMAT_FEATURE_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR = 0x20000000,
     VK_FORMAT_FEATURE_FRAGMENT_DENSITY_MAP_BIT_EXT = 0x01000000,
     VK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR = VK_FORMAT_FEATURE_TRANSFER_SRC_BIT,
     VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR = VK_FORMAT_FEATURE_TRANSFER_DST_BIT,
@@ -1644,13 +1688,15 @@
     VK_PIPELINE_STAGE_ALL_COMMANDS_BIT = 0x00010000,
     VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT = 0x01000000,
     VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT = 0x00040000,
-    VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX = 0x00020000,
+    VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR = 0x00200000,
+    VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR = 0x02000000,
     VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV = 0x00400000,
-    VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_NV = 0x00200000,
-    VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV = 0x02000000,
     VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV = 0x00080000,
     VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV = 0x00100000,
     VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT = 0x00800000,
+    VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_NV = 0x00020000,
+    VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_NV = VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR,
+    VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV = VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR,
     VK_PIPELINE_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkPipelineStageFlagBits;
 typedef VkFlags VkPipelineStageFlags;
@@ -1749,7 +1795,8 @@
     VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT = 0x00000800,
     VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT = 0x00001000,
     VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT = 0x00000200,
-    VK_BUFFER_USAGE_RAY_TRACING_BIT_NV = 0x00000400,
+    VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR = 0x00000400,
+    VK_BUFFER_USAGE_RAY_TRACING_BIT_NV = VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR,
     VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_EXT = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
     VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
     VK_BUFFER_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
@@ -1767,6 +1814,11 @@
     VK_SHADER_MODULE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkShaderModuleCreateFlagBits;
 typedef VkFlags VkShaderModuleCreateFlags;
+
+typedef enum VkPipelineCacheCreateFlagBits {
+    VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT_EXT = 0x00000001,
+    VK_PIPELINE_CACHE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkPipelineCacheCreateFlagBits;
 typedef VkFlags VkPipelineCacheCreateFlags;
 
 typedef enum VkPipelineCreateFlagBits {
@@ -1775,9 +1827,19 @@
     VK_PIPELINE_CREATE_DERIVATIVE_BIT = 0x00000004,
     VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT = 0x00000008,
     VK_PIPELINE_CREATE_DISPATCH_BASE_BIT = 0x00000010,
+    VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_ANY_HIT_SHADERS_BIT_KHR = 0x00004000,
+    VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_CLOSEST_HIT_SHADERS_BIT_KHR = 0x00008000,
+    VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_MISS_SHADERS_BIT_KHR = 0x00010000,
+    VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_INTERSECTION_SHADERS_BIT_KHR = 0x00020000,
+    VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR = 0x00001000,
+    VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR = 0x00002000,
     VK_PIPELINE_CREATE_DEFER_COMPILE_BIT_NV = 0x00000020,
     VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR = 0x00000040,
     VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR = 0x00000080,
+    VK_PIPELINE_CREATE_INDIRECT_BINDABLE_BIT_NV = 0x00040000,
+    VK_PIPELINE_CREATE_LIBRARY_BIT_KHR = 0x00000800,
+    VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_EXT = 0x00000100,
+    VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT_EXT = 0x00000200,
     VK_PIPELINE_CREATE_DISPATCH_BASE = VK_PIPELINE_CREATE_DISPATCH_BASE_BIT,
     VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT_KHR = VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT,
     VK_PIPELINE_CREATE_DISPATCH_BASE_KHR = VK_PIPELINE_CREATE_DISPATCH_BASE,
@@ -1801,14 +1863,20 @@
     VK_SHADER_STAGE_COMPUTE_BIT = 0x00000020,
     VK_SHADER_STAGE_ALL_GRAPHICS = 0x0000001F,
     VK_SHADER_STAGE_ALL = 0x7FFFFFFF,
-    VK_SHADER_STAGE_RAYGEN_BIT_NV = 0x00000100,
-    VK_SHADER_STAGE_ANY_HIT_BIT_NV = 0x00000200,
-    VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV = 0x00000400,
-    VK_SHADER_STAGE_MISS_BIT_NV = 0x00000800,
-    VK_SHADER_STAGE_INTERSECTION_BIT_NV = 0x00001000,
-    VK_SHADER_STAGE_CALLABLE_BIT_NV = 0x00002000,
+    VK_SHADER_STAGE_RAYGEN_BIT_KHR = 0x00000100,
+    VK_SHADER_STAGE_ANY_HIT_BIT_KHR = 0x00000200,
+    VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR = 0x00000400,
+    VK_SHADER_STAGE_MISS_BIT_KHR = 0x00000800,
+    VK_SHADER_STAGE_INTERSECTION_BIT_KHR = 0x00001000,
+    VK_SHADER_STAGE_CALLABLE_BIT_KHR = 0x00002000,
     VK_SHADER_STAGE_TASK_BIT_NV = 0x00000040,
     VK_SHADER_STAGE_MESH_BIT_NV = 0x00000080,
+    VK_SHADER_STAGE_RAYGEN_BIT_NV = VK_SHADER_STAGE_RAYGEN_BIT_KHR,
+    VK_SHADER_STAGE_ANY_HIT_BIT_NV = VK_SHADER_STAGE_ANY_HIT_BIT_KHR,
+    VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,
+    VK_SHADER_STAGE_MISS_BIT_NV = VK_SHADER_STAGE_MISS_BIT_KHR,
+    VK_SHADER_STAGE_INTERSECTION_BIT_NV = VK_SHADER_STAGE_INTERSECTION_BIT_KHR,
+    VK_SHADER_STAGE_CALLABLE_BIT_NV = VK_SHADER_STAGE_CALLABLE_BIT_KHR,
     VK_SHADER_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkShaderStageFlagBits;
 typedef VkFlags VkPipelineVertexInputStateCreateFlags;
@@ -1913,13 +1981,15 @@
     VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT = 0x04000000,
     VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT = 0x08000000,
     VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT = 0x00100000,
-    VK_ACCESS_COMMAND_PROCESS_READ_BIT_NVX = 0x00020000,
-    VK_ACCESS_COMMAND_PROCESS_WRITE_BIT_NVX = 0x00040000,
     VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT = 0x00080000,
+    VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR = 0x00200000,
+    VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR = 0x00400000,
     VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV = 0x00800000,
-    VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV = 0x00200000,
-    VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NV = 0x00400000,
     VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT = 0x01000000,
+    VK_ACCESS_COMMAND_PREPROCESS_READ_BIT_NV = 0x00020000,
+    VK_ACCESS_COMMAND_PREPROCESS_WRITE_BIT_NV = 0x00040000,
+    VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR,
+    VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NV = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR,
     VK_ACCESS_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkAccessFlagBits;
 typedef VkFlags VkAccessFlags;
@@ -7436,16 +7506,15 @@
     VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT = 28,
     VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT = 29,
     VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT = 30,
-    VK_DEBUG_REPORT_OBJECT_TYPE_OBJECT_TABLE_NVX_EXT = 31,
-    VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT = 32,
     VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT = 33,
     VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT = 1000156000,
     VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT = 1000085000,
-    VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT = 1000165000,
+    VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR_EXT = 1000165000,
     VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT,
     VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT,
     VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT,
     VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT,
+    VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR_EXT,
     VK_DEBUG_REPORT_OBJECT_TYPE_BEGIN_RANGE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
     VK_DEBUG_REPORT_OBJECT_TYPE_END_RANGE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT,
     VK_DEBUG_REPORT_OBJECT_TYPE_RANGE_SIZE_EXT = (VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT - VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT + 1),
@@ -7725,7 +7794,7 @@
 
 
 #define VK_NVX_image_view_handle 1
-#define VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION 1
+#define VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION 2
 #define VK_NVX_IMAGE_VIEW_HANDLE_EXTENSION_NAME "VK_NVX_image_view_handle"
 typedef struct VkImageViewHandleInfoNVX {
     VkStructureType     sType;
@@ -7735,12 +7804,25 @@
     VkSampler           sampler;
 } VkImageViewHandleInfoNVX;
 
+typedef struct VkImageViewAddressPropertiesNVX {
+    VkStructureType    sType;
+    void*              pNext;
+    VkDeviceAddress    deviceAddress;
+    VkDeviceSize       size;
+} VkImageViewAddressPropertiesNVX;
+
 typedef uint32_t (VKAPI_PTR *PFN_vkGetImageViewHandleNVX)(VkDevice device, const VkImageViewHandleInfoNVX* pInfo);
+typedef VkResult (VKAPI_PTR *PFN_vkGetImageViewAddressNVX)(VkDevice device, VkImageView imageView, VkImageViewAddressPropertiesNVX* pProperties);
 
 #ifndef VK_NO_PROTOTYPES
 VKAPI_ATTR uint32_t VKAPI_CALL vkGetImageViewHandleNVX(
     VkDevice                                    device,
     const VkImageViewHandleInfoNVX*             pInfo);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetImageViewAddressNVX(
+    VkDevice                                    device,
+    VkImageView                                 imageView,
+    VkImageViewAddressPropertiesNVX*            pProperties);
 #endif
 
 
@@ -8023,229 +8105,6 @@
 #endif
 
 
-#define VK_NVX_device_generated_commands 1
-VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkObjectTableNVX)
-VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkIndirectCommandsLayoutNVX)
-#define VK_NVX_DEVICE_GENERATED_COMMANDS_SPEC_VERSION 3
-#define VK_NVX_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME "VK_NVX_device_generated_commands"
-
-typedef enum VkIndirectCommandsTokenTypeNVX {
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NVX = 0,
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_DESCRIPTOR_SET_NVX = 1,
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_NVX = 2,
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_NVX = 3,
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NVX = 4,
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NVX = 5,
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NVX = 6,
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NVX = 7,
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_BEGIN_RANGE_NVX = VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NVX,
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_END_RANGE_NVX = VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NVX,
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_RANGE_SIZE_NVX = (VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NVX - VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NVX + 1),
-    VK_INDIRECT_COMMANDS_TOKEN_TYPE_MAX_ENUM_NVX = 0x7FFFFFFF
-} VkIndirectCommandsTokenTypeNVX;
-
-typedef enum VkObjectEntryTypeNVX {
-    VK_OBJECT_ENTRY_TYPE_DESCRIPTOR_SET_NVX = 0,
-    VK_OBJECT_ENTRY_TYPE_PIPELINE_NVX = 1,
-    VK_OBJECT_ENTRY_TYPE_INDEX_BUFFER_NVX = 2,
-    VK_OBJECT_ENTRY_TYPE_VERTEX_BUFFER_NVX = 3,
-    VK_OBJECT_ENTRY_TYPE_PUSH_CONSTANT_NVX = 4,
-    VK_OBJECT_ENTRY_TYPE_BEGIN_RANGE_NVX = VK_OBJECT_ENTRY_TYPE_DESCRIPTOR_SET_NVX,
-    VK_OBJECT_ENTRY_TYPE_END_RANGE_NVX = VK_OBJECT_ENTRY_TYPE_PUSH_CONSTANT_NVX,
-    VK_OBJECT_ENTRY_TYPE_RANGE_SIZE_NVX = (VK_OBJECT_ENTRY_TYPE_PUSH_CONSTANT_NVX - VK_OBJECT_ENTRY_TYPE_DESCRIPTOR_SET_NVX + 1),
-    VK_OBJECT_ENTRY_TYPE_MAX_ENUM_NVX = 0x7FFFFFFF
-} VkObjectEntryTypeNVX;
-
-typedef enum VkIndirectCommandsLayoutUsageFlagBitsNVX {
-    VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NVX = 0x00000001,
-    VK_INDIRECT_COMMANDS_LAYOUT_USAGE_SPARSE_SEQUENCES_BIT_NVX = 0x00000002,
-    VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EMPTY_EXECUTIONS_BIT_NVX = 0x00000004,
-    VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NVX = 0x00000008,
-    VK_INDIRECT_COMMANDS_LAYOUT_USAGE_FLAG_BITS_MAX_ENUM_NVX = 0x7FFFFFFF
-} VkIndirectCommandsLayoutUsageFlagBitsNVX;
-typedef VkFlags VkIndirectCommandsLayoutUsageFlagsNVX;
-
-typedef enum VkObjectEntryUsageFlagBitsNVX {
-    VK_OBJECT_ENTRY_USAGE_GRAPHICS_BIT_NVX = 0x00000001,
-    VK_OBJECT_ENTRY_USAGE_COMPUTE_BIT_NVX = 0x00000002,
-    VK_OBJECT_ENTRY_USAGE_FLAG_BITS_MAX_ENUM_NVX = 0x7FFFFFFF
-} VkObjectEntryUsageFlagBitsNVX;
-typedef VkFlags VkObjectEntryUsageFlagsNVX;
-typedef struct VkDeviceGeneratedCommandsFeaturesNVX {
-    VkStructureType    sType;
-    const void*        pNext;
-    VkBool32           computeBindingPointSupport;
-} VkDeviceGeneratedCommandsFeaturesNVX;
-
-typedef struct VkDeviceGeneratedCommandsLimitsNVX {
-    VkStructureType    sType;
-    const void*        pNext;
-    uint32_t           maxIndirectCommandsLayoutTokenCount;
-    uint32_t           maxObjectEntryCounts;
-    uint32_t           minSequenceCountBufferOffsetAlignment;
-    uint32_t           minSequenceIndexBufferOffsetAlignment;
-    uint32_t           minCommandsTokenBufferOffsetAlignment;
-} VkDeviceGeneratedCommandsLimitsNVX;
-
-typedef struct VkIndirectCommandsTokenNVX {
-    VkIndirectCommandsTokenTypeNVX    tokenType;
-    VkBuffer                          buffer;
-    VkDeviceSize                      offset;
-} VkIndirectCommandsTokenNVX;
-
-typedef struct VkIndirectCommandsLayoutTokenNVX {
-    VkIndirectCommandsTokenTypeNVX    tokenType;
-    uint32_t                          bindingUnit;
-    uint32_t                          dynamicCount;
-    uint32_t                          divisor;
-} VkIndirectCommandsLayoutTokenNVX;
-
-typedef struct VkIndirectCommandsLayoutCreateInfoNVX {
-    VkStructureType                            sType;
-    const void*                                pNext;
-    VkPipelineBindPoint                        pipelineBindPoint;
-    VkIndirectCommandsLayoutUsageFlagsNVX      flags;
-    uint32_t                                   tokenCount;
-    const VkIndirectCommandsLayoutTokenNVX*    pTokens;
-} VkIndirectCommandsLayoutCreateInfoNVX;
-
-typedef struct VkCmdProcessCommandsInfoNVX {
-    VkStructureType                      sType;
-    const void*                          pNext;
-    VkObjectTableNVX                     objectTable;
-    VkIndirectCommandsLayoutNVX          indirectCommandsLayout;
-    uint32_t                             indirectCommandsTokenCount;
-    const VkIndirectCommandsTokenNVX*    pIndirectCommandsTokens;
-    uint32_t                             maxSequencesCount;
-    VkCommandBuffer                      targetCommandBuffer;
-    VkBuffer                             sequencesCountBuffer;
-    VkDeviceSize                         sequencesCountOffset;
-    VkBuffer                             sequencesIndexBuffer;
-    VkDeviceSize                         sequencesIndexOffset;
-} VkCmdProcessCommandsInfoNVX;
-
-typedef struct VkCmdReserveSpaceForCommandsInfoNVX {
-    VkStructureType                sType;
-    const void*                    pNext;
-    VkObjectTableNVX               objectTable;
-    VkIndirectCommandsLayoutNVX    indirectCommandsLayout;
-    uint32_t                       maxSequencesCount;
-} VkCmdReserveSpaceForCommandsInfoNVX;
-
-typedef struct VkObjectTableCreateInfoNVX {
-    VkStructureType                      sType;
-    const void*                          pNext;
-    uint32_t                             objectCount;
-    const VkObjectEntryTypeNVX*          pObjectEntryTypes;
-    const uint32_t*                      pObjectEntryCounts;
-    const VkObjectEntryUsageFlagsNVX*    pObjectEntryUsageFlags;
-    uint32_t                             maxUniformBuffersPerDescriptor;
-    uint32_t                             maxStorageBuffersPerDescriptor;
-    uint32_t                             maxStorageImagesPerDescriptor;
-    uint32_t                             maxSampledImagesPerDescriptor;
-    uint32_t                             maxPipelineLayouts;
-} VkObjectTableCreateInfoNVX;
-
-typedef struct VkObjectTableEntryNVX {
-    VkObjectEntryTypeNVX          type;
-    VkObjectEntryUsageFlagsNVX    flags;
-} VkObjectTableEntryNVX;
-
-typedef struct VkObjectTablePipelineEntryNVX {
-    VkObjectEntryTypeNVX          type;
-    VkObjectEntryUsageFlagsNVX    flags;
-    VkPipeline                    pipeline;
-} VkObjectTablePipelineEntryNVX;
-
-typedef struct VkObjectTableDescriptorSetEntryNVX {
-    VkObjectEntryTypeNVX          type;
-    VkObjectEntryUsageFlagsNVX    flags;
-    VkPipelineLayout              pipelineLayout;
-    VkDescriptorSet               descriptorSet;
-} VkObjectTableDescriptorSetEntryNVX;
-
-typedef struct VkObjectTableVertexBufferEntryNVX {
-    VkObjectEntryTypeNVX          type;
-    VkObjectEntryUsageFlagsNVX    flags;
-    VkBuffer                      buffer;
-} VkObjectTableVertexBufferEntryNVX;
-
-typedef struct VkObjectTableIndexBufferEntryNVX {
-    VkObjectEntryTypeNVX          type;
-    VkObjectEntryUsageFlagsNVX    flags;
-    VkBuffer                      buffer;
-    VkIndexType                   indexType;
-} VkObjectTableIndexBufferEntryNVX;
-
-typedef struct VkObjectTablePushConstantEntryNVX {
-    VkObjectEntryTypeNVX          type;
-    VkObjectEntryUsageFlagsNVX    flags;
-    VkPipelineLayout              pipelineLayout;
-    VkShaderStageFlags            stageFlags;
-} VkObjectTablePushConstantEntryNVX;
-
-typedef void (VKAPI_PTR *PFN_vkCmdProcessCommandsNVX)(VkCommandBuffer commandBuffer, const VkCmdProcessCommandsInfoNVX* pProcessCommandsInfo);
-typedef void (VKAPI_PTR *PFN_vkCmdReserveSpaceForCommandsNVX)(VkCommandBuffer commandBuffer, const VkCmdReserveSpaceForCommandsInfoNVX* pReserveSpaceInfo);
-typedef VkResult (VKAPI_PTR *PFN_vkCreateIndirectCommandsLayoutNVX)(VkDevice device, const VkIndirectCommandsLayoutCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkIndirectCommandsLayoutNVX* pIndirectCommandsLayout);
-typedef void (VKAPI_PTR *PFN_vkDestroyIndirectCommandsLayoutNVX)(VkDevice device, VkIndirectCommandsLayoutNVX indirectCommandsLayout, const VkAllocationCallbacks* pAllocator);
-typedef VkResult (VKAPI_PTR *PFN_vkCreateObjectTableNVX)(VkDevice device, const VkObjectTableCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkObjectTableNVX* pObjectTable);
-typedef void (VKAPI_PTR *PFN_vkDestroyObjectTableNVX)(VkDevice device, VkObjectTableNVX objectTable, const VkAllocationCallbacks* pAllocator);
-typedef VkResult (VKAPI_PTR *PFN_vkRegisterObjectsNVX)(VkDevice device, VkObjectTableNVX objectTable, uint32_t objectCount, const VkObjectTableEntryNVX* const*    ppObjectTableEntries, const uint32_t* pObjectIndices);
-typedef VkResult (VKAPI_PTR *PFN_vkUnregisterObjectsNVX)(VkDevice device, VkObjectTableNVX objectTable, uint32_t objectCount, const VkObjectEntryTypeNVX* pObjectEntryTypes, const uint32_t* pObjectIndices);
-typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX)(VkPhysicalDevice physicalDevice, VkDeviceGeneratedCommandsFeaturesNVX* pFeatures, VkDeviceGeneratedCommandsLimitsNVX* pLimits);
-
-#ifndef VK_NO_PROTOTYPES
-VKAPI_ATTR void VKAPI_CALL vkCmdProcessCommandsNVX(
-    VkCommandBuffer                             commandBuffer,
-    const VkCmdProcessCommandsInfoNVX*          pProcessCommandsInfo);
-
-VKAPI_ATTR void VKAPI_CALL vkCmdReserveSpaceForCommandsNVX(
-    VkCommandBuffer                             commandBuffer,
-    const VkCmdReserveSpaceForCommandsInfoNVX*  pReserveSpaceInfo);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkCreateIndirectCommandsLayoutNVX(
-    VkDevice                                    device,
-    const VkIndirectCommandsLayoutCreateInfoNVX* pCreateInfo,
-    const VkAllocationCallbacks*                pAllocator,
-    VkIndirectCommandsLayoutNVX*                pIndirectCommandsLayout);
-
-VKAPI_ATTR void VKAPI_CALL vkDestroyIndirectCommandsLayoutNVX(
-    VkDevice                                    device,
-    VkIndirectCommandsLayoutNVX                 indirectCommandsLayout,
-    const VkAllocationCallbacks*                pAllocator);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkCreateObjectTableNVX(
-    VkDevice                                    device,
-    const VkObjectTableCreateInfoNVX*           pCreateInfo,
-    const VkAllocationCallbacks*                pAllocator,
-    VkObjectTableNVX*                           pObjectTable);
-
-VKAPI_ATTR void VKAPI_CALL vkDestroyObjectTableNVX(
-    VkDevice                                    device,
-    VkObjectTableNVX                            objectTable,
-    const VkAllocationCallbacks*                pAllocator);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkRegisterObjectsNVX(
-    VkDevice                                    device,
-    VkObjectTableNVX                            objectTable,
-    uint32_t                                    objectCount,
-    const VkObjectTableEntryNVX* const*         ppObjectTableEntries,
-    const uint32_t*                             pObjectIndices);
-
-VKAPI_ATTR VkResult VKAPI_CALL vkUnregisterObjectsNVX(
-    VkDevice                                    device,
-    VkObjectTableNVX                            objectTable,
-    uint32_t                                    objectCount,
-    const VkObjectEntryTypeNVX*                 pObjectEntryTypes,
-    const uint32_t*                             pObjectIndices);
-
-VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX(
-    VkPhysicalDevice                            physicalDevice,
-    VkDeviceGeneratedCommandsFeaturesNVX*       pFeatures,
-    VkDeviceGeneratedCommandsLimitsNVX*         pLimits);
-#endif
-
-
 #define VK_NV_clip_space_w_scaling 1
 #define VK_NV_CLIP_SPACE_W_SCALING_SPEC_VERSION 1
 #define VK_NV_CLIP_SPACE_W_SCALING_EXTENSION_NAME "VK_NV_clip_space_w_scaling"
@@ -8657,7 +8516,7 @@
 
 #define VK_EXT_debug_utils 1
 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugUtilsMessengerEXT)
-#define VK_EXT_DEBUG_UTILS_SPEC_VERSION   1
+#define VK_EXT_DEBUG_UTILS_SPEC_VERSION   2
 #define VK_EXT_DEBUG_UTILS_EXTENSION_NAME "VK_EXT_debug_utils"
 typedef VkFlags VkDebugUtilsMessengerCallbackDataFlagsEXT;
 typedef VkFlags VkDebugUtilsMessengerCreateFlagsEXT;
@@ -9290,91 +9149,142 @@
 
 
 #define VK_NV_ray_tracing 1
-VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkAccelerationStructureNV)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkAccelerationStructureKHR)
+typedef VkAccelerationStructureKHR VkAccelerationStructureNV;
+
 #define VK_NV_RAY_TRACING_SPEC_VERSION    3
 #define VK_NV_RAY_TRACING_EXTENSION_NAME  "VK_NV_ray_tracing"
-#define VK_SHADER_UNUSED_NV               (~0U)
+#define VK_SHADER_UNUSED_KHR              (~0U)
+#define VK_SHADER_UNUSED_NV               VK_SHADER_UNUSED_KHR
 
-typedef enum VkAccelerationStructureTypeNV {
-    VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV = 0,
-    VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV = 1,
-    VK_ACCELERATION_STRUCTURE_TYPE_BEGIN_RANGE_NV = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV,
-    VK_ACCELERATION_STRUCTURE_TYPE_END_RANGE_NV = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV,
-    VK_ACCELERATION_STRUCTURE_TYPE_RANGE_SIZE_NV = (VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV - VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV + 1),
-    VK_ACCELERATION_STRUCTURE_TYPE_MAX_ENUM_NV = 0x7FFFFFFF
-} VkAccelerationStructureTypeNV;
+typedef enum VkRayTracingShaderGroupTypeKHR {
+    VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR = 0,
+    VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR = 1,
+    VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR = 2,
+    VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR,
+    VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_NV = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR,
+    VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV = VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR,
+    VK_RAY_TRACING_SHADER_GROUP_TYPE_BEGIN_RANGE_KHR = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR,
+    VK_RAY_TRACING_SHADER_GROUP_TYPE_END_RANGE_KHR = VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR,
+    VK_RAY_TRACING_SHADER_GROUP_TYPE_RANGE_SIZE_KHR = (VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR - VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR + 1),
+    VK_RAY_TRACING_SHADER_GROUP_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF
+} VkRayTracingShaderGroupTypeKHR;
+typedef VkRayTracingShaderGroupTypeKHR VkRayTracingShaderGroupTypeNV;
 
-typedef enum VkRayTracingShaderGroupTypeNV {
-    VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV = 0,
-    VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_NV = 1,
-    VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV = 2,
-    VK_RAY_TRACING_SHADER_GROUP_TYPE_BEGIN_RANGE_NV = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV,
-    VK_RAY_TRACING_SHADER_GROUP_TYPE_END_RANGE_NV = VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV,
-    VK_RAY_TRACING_SHADER_GROUP_TYPE_RANGE_SIZE_NV = (VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV - VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV + 1),
-    VK_RAY_TRACING_SHADER_GROUP_TYPE_MAX_ENUM_NV = 0x7FFFFFFF
-} VkRayTracingShaderGroupTypeNV;
 
-typedef enum VkGeometryTypeNV {
-    VK_GEOMETRY_TYPE_TRIANGLES_NV = 0,
-    VK_GEOMETRY_TYPE_AABBS_NV = 1,
-    VK_GEOMETRY_TYPE_BEGIN_RANGE_NV = VK_GEOMETRY_TYPE_TRIANGLES_NV,
-    VK_GEOMETRY_TYPE_END_RANGE_NV = VK_GEOMETRY_TYPE_AABBS_NV,
-    VK_GEOMETRY_TYPE_RANGE_SIZE_NV = (VK_GEOMETRY_TYPE_AABBS_NV - VK_GEOMETRY_TYPE_TRIANGLES_NV + 1),
-    VK_GEOMETRY_TYPE_MAX_ENUM_NV = 0x7FFFFFFF
-} VkGeometryTypeNV;
+typedef enum VkGeometryTypeKHR {
+    VK_GEOMETRY_TYPE_TRIANGLES_KHR = 0,
+    VK_GEOMETRY_TYPE_AABBS_KHR = 1,
+    VK_GEOMETRY_TYPE_INSTANCES_KHR = 1000150000,
+    VK_GEOMETRY_TYPE_TRIANGLES_NV = VK_GEOMETRY_TYPE_TRIANGLES_KHR,
+    VK_GEOMETRY_TYPE_AABBS_NV = VK_GEOMETRY_TYPE_AABBS_KHR,
+    VK_GEOMETRY_TYPE_BEGIN_RANGE_KHR = VK_GEOMETRY_TYPE_TRIANGLES_KHR,
+    VK_GEOMETRY_TYPE_END_RANGE_KHR = VK_GEOMETRY_TYPE_AABBS_KHR,
+    VK_GEOMETRY_TYPE_RANGE_SIZE_KHR = (VK_GEOMETRY_TYPE_AABBS_KHR - VK_GEOMETRY_TYPE_TRIANGLES_KHR + 1),
+    VK_GEOMETRY_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF
+} VkGeometryTypeKHR;
+typedef VkGeometryTypeKHR VkGeometryTypeNV;
 
-typedef enum VkCopyAccelerationStructureModeNV {
-    VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV = 0,
-    VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV = 1,
-    VK_COPY_ACCELERATION_STRUCTURE_MODE_BEGIN_RANGE_NV = VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV,
-    VK_COPY_ACCELERATION_STRUCTURE_MODE_END_RANGE_NV = VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV,
-    VK_COPY_ACCELERATION_STRUCTURE_MODE_RANGE_SIZE_NV = (VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV - VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV + 1),
-    VK_COPY_ACCELERATION_STRUCTURE_MODE_MAX_ENUM_NV = 0x7FFFFFFF
-} VkCopyAccelerationStructureModeNV;
 
-typedef enum VkAccelerationStructureMemoryRequirementsTypeNV {
-    VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV = 0,
-    VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV = 1,
-    VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV = 2,
-    VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BEGIN_RANGE_NV = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV,
-    VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_END_RANGE_NV = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV,
-    VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_RANGE_SIZE_NV = (VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV - VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV + 1),
-    VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_MAX_ENUM_NV = 0x7FFFFFFF
-} VkAccelerationStructureMemoryRequirementsTypeNV;
+typedef enum VkAccelerationStructureTypeKHR {
+    VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR = 0,
+    VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR = 1,
+    VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR,
+    VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR,
+    VK_ACCELERATION_STRUCTURE_TYPE_BEGIN_RANGE_KHR = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR,
+    VK_ACCELERATION_STRUCTURE_TYPE_END_RANGE_KHR = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR,
+    VK_ACCELERATION_STRUCTURE_TYPE_RANGE_SIZE_KHR = (VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR - VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR + 1),
+    VK_ACCELERATION_STRUCTURE_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF
+} VkAccelerationStructureTypeKHR;
+typedef VkAccelerationStructureTypeKHR VkAccelerationStructureTypeNV;
 
-typedef enum VkGeometryFlagBitsNV {
-    VK_GEOMETRY_OPAQUE_BIT_NV = 0x00000001,
-    VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_NV = 0x00000002,
-    VK_GEOMETRY_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF
-} VkGeometryFlagBitsNV;
-typedef VkFlags VkGeometryFlagsNV;
 
-typedef enum VkGeometryInstanceFlagBitsNV {
-    VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NV = 0x00000001,
-    VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_NV = 0x00000002,
-    VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_NV = 0x00000004,
-    VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_NV = 0x00000008,
-    VK_GEOMETRY_INSTANCE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF
-} VkGeometryInstanceFlagBitsNV;
-typedef VkFlags VkGeometryInstanceFlagsNV;
+typedef enum VkCopyAccelerationStructureModeKHR {
+    VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR = 0,
+    VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR = 1,
+    VK_COPY_ACCELERATION_STRUCTURE_MODE_SERIALIZE_KHR = 2,
+    VK_COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR = 3,
+    VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV = VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR,
+    VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV = VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR,
+    VK_COPY_ACCELERATION_STRUCTURE_MODE_BEGIN_RANGE_KHR = VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR,
+    VK_COPY_ACCELERATION_STRUCTURE_MODE_END_RANGE_KHR = VK_COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR,
+    VK_COPY_ACCELERATION_STRUCTURE_MODE_RANGE_SIZE_KHR = (VK_COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR - VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR + 1),
+    VK_COPY_ACCELERATION_STRUCTURE_MODE_MAX_ENUM_KHR = 0x7FFFFFFF
+} VkCopyAccelerationStructureModeKHR;
+typedef VkCopyAccelerationStructureModeKHR VkCopyAccelerationStructureModeNV;
 
-typedef enum VkBuildAccelerationStructureFlagBitsNV {
-    VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_NV = 0x00000001,
-    VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_NV = 0x00000002,
-    VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_NV = 0x00000004,
-    VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_NV = 0x00000008,
-    VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_NV = 0x00000010,
-    VK_BUILD_ACCELERATION_STRUCTURE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF
-} VkBuildAccelerationStructureFlagBitsNV;
-typedef VkFlags VkBuildAccelerationStructureFlagsNV;
+
+typedef enum VkAccelerationStructureMemoryRequirementsTypeKHR {
+    VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR = 0,
+    VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR = 1,
+    VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_KHR = 2,
+    VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR,
+    VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR,
+    VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_KHR,
+    VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BEGIN_RANGE_KHR = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR,
+    VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_END_RANGE_KHR = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_KHR,
+    VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_RANGE_SIZE_KHR = (VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_KHR - VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR + 1),
+    VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF
+} VkAccelerationStructureMemoryRequirementsTypeKHR;
+typedef VkAccelerationStructureMemoryRequirementsTypeKHR VkAccelerationStructureMemoryRequirementsTypeNV;
+
+
+typedef enum VkGeometryFlagBitsKHR {
+    VK_GEOMETRY_OPAQUE_BIT_KHR = 0x00000001,
+    VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR = 0x00000002,
+    VK_GEOMETRY_OPAQUE_BIT_NV = VK_GEOMETRY_OPAQUE_BIT_KHR,
+    VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_NV = VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR,
+    VK_GEOMETRY_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
+} VkGeometryFlagBitsKHR;
+typedef VkFlags VkGeometryFlagsKHR;
+typedef VkGeometryFlagsKHR VkGeometryFlagsNV;
+
+typedef VkGeometryFlagBitsKHR VkGeometryFlagBitsNV;
+
+
+typedef enum VkGeometryInstanceFlagBitsKHR {
+    VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR = 0x00000001,
+    VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_KHR = 0x00000002,
+    VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR = 0x00000004,
+    VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR = 0x00000008,
+    VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NV = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR,
+    VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_NV = VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_KHR,
+    VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_NV = VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR,
+    VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_NV = VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR,
+    VK_GEOMETRY_INSTANCE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
+} VkGeometryInstanceFlagBitsKHR;
+typedef VkFlags VkGeometryInstanceFlagsKHR;
+typedef VkGeometryInstanceFlagsKHR VkGeometryInstanceFlagsNV;
+
+typedef VkGeometryInstanceFlagBitsKHR VkGeometryInstanceFlagBitsNV;
+
+
+typedef enum VkBuildAccelerationStructureFlagBitsKHR {
+    VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR = 0x00000001,
+    VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR = 0x00000002,
+    VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR = 0x00000004,
+    VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR = 0x00000008,
+    VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR = 0x00000010,
+    VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR,
+    VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR,
+    VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR,
+    VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR,
+    VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_NV = VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR,
+    VK_BUILD_ACCELERATION_STRUCTURE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
+} VkBuildAccelerationStructureFlagBitsKHR;
+typedef VkFlags VkBuildAccelerationStructureFlagsKHR;
+typedef VkBuildAccelerationStructureFlagsKHR VkBuildAccelerationStructureFlagsNV;
+
+typedef VkBuildAccelerationStructureFlagBitsKHR VkBuildAccelerationStructureFlagBitsNV;
+
 typedef struct VkRayTracingShaderGroupCreateInfoNV {
-    VkStructureType                  sType;
-    const void*                      pNext;
-    VkRayTracingShaderGroupTypeNV    type;
-    uint32_t                         generalShader;
-    uint32_t                         closestHitShader;
-    uint32_t                         anyHitShader;
-    uint32_t                         intersectionShader;
+    VkStructureType                   sType;
+    const void*                       pNext;
+    VkRayTracingShaderGroupTypeKHR    type;
+    uint32_t                          generalShader;
+    uint32_t                          closestHitShader;
+    uint32_t                          anyHitShader;
+    uint32_t                          intersectionShader;
 } VkRayTracingShaderGroupCreateInfoNV;
 
 typedef struct VkRayTracingPipelineCreateInfoNV {
@@ -9422,11 +9332,11 @@
 } VkGeometryDataNV;
 
 typedef struct VkGeometryNV {
-    VkStructureType      sType;
-    const void*          pNext;
-    VkGeometryTypeNV     geometryType;
-    VkGeometryDataNV     geometry;
-    VkGeometryFlagsNV    flags;
+    VkStructureType       sType;
+    const void*           pNext;
+    VkGeometryTypeKHR     geometryType;
+    VkGeometryDataNV      geometry;
+    VkGeometryFlagsKHR    flags;
 } VkGeometryNV;
 
 typedef struct VkAccelerationStructureInfoNV {
@@ -9446,22 +9356,26 @@
     VkAccelerationStructureInfoNV    info;
 } VkAccelerationStructureCreateInfoNV;
 
-typedef struct VkBindAccelerationStructureMemoryInfoNV {
-    VkStructureType              sType;
-    const void*                  pNext;
-    VkAccelerationStructureNV    accelerationStructure;
-    VkDeviceMemory               memory;
-    VkDeviceSize                 memoryOffset;
-    uint32_t                     deviceIndexCount;
-    const uint32_t*              pDeviceIndices;
-} VkBindAccelerationStructureMemoryInfoNV;
+typedef struct VkBindAccelerationStructureMemoryInfoKHR {
+    VkStructureType               sType;
+    const void*                   pNext;
+    VkAccelerationStructureKHR    accelerationStructure;
+    VkDeviceMemory                memory;
+    VkDeviceSize                  memoryOffset;
+    uint32_t                      deviceIndexCount;
+    const uint32_t*               pDeviceIndices;
+} VkBindAccelerationStructureMemoryInfoKHR;
 
-typedef struct VkWriteDescriptorSetAccelerationStructureNV {
-    VkStructureType                     sType;
-    const void*                         pNext;
-    uint32_t                            accelerationStructureCount;
-    const VkAccelerationStructureNV*    pAccelerationStructures;
-} VkWriteDescriptorSetAccelerationStructureNV;
+typedef VkBindAccelerationStructureMemoryInfoKHR VkBindAccelerationStructureMemoryInfoNV;
+
+typedef struct VkWriteDescriptorSetAccelerationStructureKHR {
+    VkStructureType                      sType;
+    const void*                          pNext;
+    uint32_t                             accelerationStructureCount;
+    const VkAccelerationStructureKHR*    pAccelerationStructures;
+} VkWriteDescriptorSetAccelerationStructureKHR;
+
+typedef VkWriteDescriptorSetAccelerationStructureKHR VkWriteDescriptorSetAccelerationStructureNV;
 
 typedef struct VkAccelerationStructureMemoryRequirementsInfoNV {
     VkStructureType                                    sType;
@@ -9483,17 +9397,49 @@
     uint32_t           maxDescriptorSetAccelerationStructures;
 } VkPhysicalDeviceRayTracingPropertiesNV;
 
+typedef struct VkTransformMatrixKHR {
+    float    matrix[3][4];
+} VkTransformMatrixKHR;
+
+typedef VkTransformMatrixKHR VkTransformMatrixNV;
+
+typedef struct VkAabbPositionsKHR {
+    float    minX;
+    float    minY;
+    float    minZ;
+    float    maxX;
+    float    maxY;
+    float    maxZ;
+} VkAabbPositionsKHR;
+
+typedef VkAabbPositionsKHR VkAabbPositionsNV;
+
+typedef struct VkAccelerationStructureInstanceKHR {
+    VkTransformMatrixKHR          transform;
+    uint32_t                      instanceCustomIndex:24;
+    uint32_t                      mask:8;
+    uint32_t                      instanceShaderBindingTableRecordOffset:24;
+    VkGeometryInstanceFlagsKHR    flags:8;
+    uint64_t                      accelerationStructureReference;
+} VkAccelerationStructureInstanceKHR;
+
+typedef VkAccelerationStructureInstanceKHR VkAccelerationStructureInstanceNV;
+
 typedef VkResult (VKAPI_PTR *PFN_vkCreateAccelerationStructureNV)(VkDevice device, const VkAccelerationStructureCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkAccelerationStructureNV* pAccelerationStructure);
-typedef void (VKAPI_PTR *PFN_vkDestroyAccelerationStructureNV)(VkDevice device, VkAccelerationStructureNV accelerationStructure, const VkAllocationCallbacks* pAllocator);
+typedef void (VKAPI_PTR *PFN_vkDestroyAccelerationStructureKHR)(VkDevice device, VkAccelerationStructureKHR accelerationStructure, const VkAllocationCallbacks* pAllocator);
+typedef void (VKAPI_PTR *PFN_vkDestroyAccelerationStructureNV)(VkDevice device, VkAccelerationStructureKHR accelerationStructure, const VkAllocationCallbacks* pAllocator);
 typedef void (VKAPI_PTR *PFN_vkGetAccelerationStructureMemoryRequirementsNV)(VkDevice device, const VkAccelerationStructureMemoryRequirementsInfoNV* pInfo, VkMemoryRequirements2KHR* pMemoryRequirements);
-typedef VkResult (VKAPI_PTR *PFN_vkBindAccelerationStructureMemoryNV)(VkDevice device, uint32_t bindInfoCount, const VkBindAccelerationStructureMemoryInfoNV* pBindInfos);
-typedef void (VKAPI_PTR *PFN_vkCmdBuildAccelerationStructureNV)(VkCommandBuffer commandBuffer, const VkAccelerationStructureInfoNV* pInfo, VkBuffer instanceData, VkDeviceSize instanceOffset, VkBool32 update, VkAccelerationStructureNV dst, VkAccelerationStructureNV src, VkBuffer scratch, VkDeviceSize scratchOffset);
-typedef void (VKAPI_PTR *PFN_vkCmdCopyAccelerationStructureNV)(VkCommandBuffer commandBuffer, VkAccelerationStructureNV dst, VkAccelerationStructureNV src, VkCopyAccelerationStructureModeNV mode);
+typedef VkResult (VKAPI_PTR *PFN_vkBindAccelerationStructureMemoryKHR)(VkDevice device, uint32_t bindInfoCount, const VkBindAccelerationStructureMemoryInfoKHR* pBindInfos);
+typedef VkResult (VKAPI_PTR *PFN_vkBindAccelerationStructureMemoryNV)(VkDevice device, uint32_t bindInfoCount, const VkBindAccelerationStructureMemoryInfoKHR* pBindInfos);
+typedef void (VKAPI_PTR *PFN_vkCmdBuildAccelerationStructureNV)(VkCommandBuffer commandBuffer, const VkAccelerationStructureInfoNV* pInfo, VkBuffer instanceData, VkDeviceSize instanceOffset, VkBool32 update, VkAccelerationStructureKHR dst, VkAccelerationStructureKHR src, VkBuffer scratch, VkDeviceSize scratchOffset);
+typedef void (VKAPI_PTR *PFN_vkCmdCopyAccelerationStructureNV)(VkCommandBuffer commandBuffer, VkAccelerationStructureKHR dst, VkAccelerationStructureKHR src, VkCopyAccelerationStructureModeKHR mode);
 typedef void (VKAPI_PTR *PFN_vkCmdTraceRaysNV)(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer, VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer, VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride, VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset, VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer, VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride, uint32_t width, uint32_t height, uint32_t depth);
 typedef VkResult (VKAPI_PTR *PFN_vkCreateRayTracingPipelinesNV)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkRayTracingPipelineCreateInfoNV* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines);
+typedef VkResult (VKAPI_PTR *PFN_vkGetRayTracingShaderGroupHandlesKHR)(VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData);
 typedef VkResult (VKAPI_PTR *PFN_vkGetRayTracingShaderGroupHandlesNV)(VkDevice device, VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData);
-typedef VkResult (VKAPI_PTR *PFN_vkGetAccelerationStructureHandleNV)(VkDevice device, VkAccelerationStructureNV accelerationStructure, size_t dataSize, void* pData);
-typedef void (VKAPI_PTR *PFN_vkCmdWriteAccelerationStructuresPropertiesNV)(VkCommandBuffer commandBuffer, uint32_t accelerationStructureCount, const VkAccelerationStructureNV* pAccelerationStructures, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery);
+typedef VkResult (VKAPI_PTR *PFN_vkGetAccelerationStructureHandleNV)(VkDevice device, VkAccelerationStructureKHR accelerationStructure, size_t dataSize, void* pData);
+typedef void (VKAPI_PTR *PFN_vkCmdWriteAccelerationStructuresPropertiesKHR)(VkCommandBuffer commandBuffer, uint32_t accelerationStructureCount, const VkAccelerationStructureKHR* pAccelerationStructures, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery);
+typedef void (VKAPI_PTR *PFN_vkCmdWriteAccelerationStructuresPropertiesNV)(VkCommandBuffer commandBuffer, uint32_t accelerationStructureCount, const VkAccelerationStructureKHR* pAccelerationStructures, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery);
 typedef VkResult (VKAPI_PTR *PFN_vkCompileDeferredNV)(VkDevice device, VkPipeline pipeline, uint32_t shader);
 
 #ifndef VK_NO_PROTOTYPES
@@ -9503,9 +9449,14 @@
     const VkAllocationCallbacks*                pAllocator,
     VkAccelerationStructureNV*                  pAccelerationStructure);
 
+VKAPI_ATTR void VKAPI_CALL vkDestroyAccelerationStructureKHR(
+    VkDevice                                    device,
+    VkAccelerationStructureKHR                  accelerationStructure,
+    const VkAllocationCallbacks*                pAllocator);
+
 VKAPI_ATTR void VKAPI_CALL vkDestroyAccelerationStructureNV(
     VkDevice                                    device,
-    VkAccelerationStructureNV                   accelerationStructure,
+    VkAccelerationStructureKHR                  accelerationStructure,
     const VkAllocationCallbacks*                pAllocator);
 
 VKAPI_ATTR void VKAPI_CALL vkGetAccelerationStructureMemoryRequirementsNV(
@@ -9513,10 +9464,15 @@
     const VkAccelerationStructureMemoryRequirementsInfoNV* pInfo,
     VkMemoryRequirements2KHR*                   pMemoryRequirements);
 
+VKAPI_ATTR VkResult VKAPI_CALL vkBindAccelerationStructureMemoryKHR(
+    VkDevice                                    device,
+    uint32_t                                    bindInfoCount,
+    const VkBindAccelerationStructureMemoryInfoKHR* pBindInfos);
+
 VKAPI_ATTR VkResult VKAPI_CALL vkBindAccelerationStructureMemoryNV(
     VkDevice                                    device,
     uint32_t                                    bindInfoCount,
-    const VkBindAccelerationStructureMemoryInfoNV* pBindInfos);
+    const VkBindAccelerationStructureMemoryInfoKHR* pBindInfos);
 
 VKAPI_ATTR void VKAPI_CALL vkCmdBuildAccelerationStructureNV(
     VkCommandBuffer                             commandBuffer,
@@ -9524,16 +9480,16 @@
     VkBuffer                                    instanceData,
     VkDeviceSize                                instanceOffset,
     VkBool32                                    update,
-    VkAccelerationStructureNV                   dst,
-    VkAccelerationStructureNV                   src,
+    VkAccelerationStructureKHR                  dst,
+    VkAccelerationStructureKHR                  src,
     VkBuffer                                    scratch,
     VkDeviceSize                                scratchOffset);
 
 VKAPI_ATTR void VKAPI_CALL vkCmdCopyAccelerationStructureNV(
     VkCommandBuffer                             commandBuffer,
-    VkAccelerationStructureNV                   dst,
-    VkAccelerationStructureNV                   src,
-    VkCopyAccelerationStructureModeNV           mode);
+    VkAccelerationStructureKHR                  dst,
+    VkAccelerationStructureKHR                  src,
+    VkCopyAccelerationStructureModeKHR          mode);
 
 VKAPI_ATTR void VKAPI_CALL vkCmdTraceRaysNV(
     VkCommandBuffer                             commandBuffer,
@@ -9560,6 +9516,14 @@
     const VkAllocationCallbacks*                pAllocator,
     VkPipeline*                                 pPipelines);
 
+VKAPI_ATTR VkResult VKAPI_CALL vkGetRayTracingShaderGroupHandlesKHR(
+    VkDevice                                    device,
+    VkPipeline                                  pipeline,
+    uint32_t                                    firstGroup,
+    uint32_t                                    groupCount,
+    size_t                                      dataSize,
+    void*                                       pData);
+
 VKAPI_ATTR VkResult VKAPI_CALL vkGetRayTracingShaderGroupHandlesNV(
     VkDevice                                    device,
     VkPipeline                                  pipeline,
@@ -9570,14 +9534,22 @@
 
 VKAPI_ATTR VkResult VKAPI_CALL vkGetAccelerationStructureHandleNV(
     VkDevice                                    device,
-    VkAccelerationStructureNV                   accelerationStructure,
+    VkAccelerationStructureKHR                  accelerationStructure,
     size_t                                      dataSize,
     void*                                       pData);
 
+VKAPI_ATTR void VKAPI_CALL vkCmdWriteAccelerationStructuresPropertiesKHR(
+    VkCommandBuffer                             commandBuffer,
+    uint32_t                                    accelerationStructureCount,
+    const VkAccelerationStructureKHR*           pAccelerationStructures,
+    VkQueryType                                 queryType,
+    VkQueryPool                                 queryPool,
+    uint32_t                                    firstQuery);
+
 VKAPI_ATTR void VKAPI_CALL vkCmdWriteAccelerationStructuresPropertiesNV(
     VkCommandBuffer                             commandBuffer,
     uint32_t                                    accelerationStructureCount,
-    const VkAccelerationStructureNV*            pAccelerationStructures,
+    const VkAccelerationStructureKHR*           pAccelerationStructures,
     VkQueryType                                 queryType,
     VkQueryPool                                 queryPool,
     uint32_t                                    firstQuery);
@@ -10020,7 +9992,7 @@
 
 #define VK_INTEL_performance_query 1
 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPerformanceConfigurationINTEL)
-#define VK_INTEL_PERFORMANCE_QUERY_SPEC_VERSION 1
+#define VK_INTEL_PERFORMANCE_QUERY_SPEC_VERSION 2
 #define VK_INTEL_PERFORMANCE_QUERY_EXTENSION_NAME "VK_INTEL_performance_query"
 
 typedef enum VkPerformanceConfigurationTypeINTEL {
@@ -10087,11 +10059,13 @@
     void*              pUserData;
 } VkInitializePerformanceApiInfoINTEL;
 
-typedef struct VkQueryPoolCreateInfoINTEL {
+typedef struct VkQueryPoolPerformanceQueryCreateInfoINTEL {
     VkStructureType                 sType;
     const void*                     pNext;
     VkQueryPoolSamplingModeINTEL    performanceCountersSampling;
-} VkQueryPoolCreateInfoINTEL;
+} VkQueryPoolPerformanceQueryCreateInfoINTEL;
+
+typedef VkQueryPoolPerformanceQueryCreateInfoINTEL VkQueryPoolCreateInfoINTEL;
 
 typedef struct VkPerformanceMarkerInfoINTEL {
     VkStructureType    sType;
@@ -10420,16 +10394,17 @@
 
 
 #define VK_EXT_validation_features 1
-#define VK_EXT_VALIDATION_FEATURES_SPEC_VERSION 2
+#define VK_EXT_VALIDATION_FEATURES_SPEC_VERSION 3
 #define VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME "VK_EXT_validation_features"
 
 typedef enum VkValidationFeatureEnableEXT {
     VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT = 0,
     VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT = 1,
     VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT = 2,
+    VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT = 3,
     VK_VALIDATION_FEATURE_ENABLE_BEGIN_RANGE_EXT = VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT,
-    VK_VALIDATION_FEATURE_ENABLE_END_RANGE_EXT = VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT,
-    VK_VALIDATION_FEATURE_ENABLE_RANGE_SIZE_EXT = (VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT - VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT + 1),
+    VK_VALIDATION_FEATURE_ENABLE_END_RANGE_EXT = VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT,
+    VK_VALIDATION_FEATURE_ENABLE_RANGE_SIZE_EXT = (VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT - VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT + 1),
     VK_VALIDATION_FEATURE_ENABLE_MAX_ENUM_EXT = 0x7FFFFFFF
 } VkValidationFeatureEnableEXT;
 
@@ -10703,6 +10678,199 @@
 
 
 
+#define VK_NV_device_generated_commands 1
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkIndirectCommandsLayoutNV)
+#define VK_NV_DEVICE_GENERATED_COMMANDS_SPEC_VERSION 3
+#define VK_NV_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME "VK_NV_device_generated_commands"
+
+typedef enum VkIndirectCommandsTokenTypeNV {
+    VK_INDIRECT_COMMANDS_TOKEN_TYPE_SHADER_GROUP_NV = 0,
+    VK_INDIRECT_COMMANDS_TOKEN_TYPE_STATE_FLAGS_NV = 1,
+    VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_NV = 2,
+    VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_NV = 3,
+    VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NV = 4,
+    VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NV = 5,
+    VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NV = 6,
+    VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_TASKS_NV = 7,
+    VK_INDIRECT_COMMANDS_TOKEN_TYPE_BEGIN_RANGE_NV = VK_INDIRECT_COMMANDS_TOKEN_TYPE_SHADER_GROUP_NV,
+    VK_INDIRECT_COMMANDS_TOKEN_TYPE_END_RANGE_NV = VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_TASKS_NV,
+    VK_INDIRECT_COMMANDS_TOKEN_TYPE_RANGE_SIZE_NV = (VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_TASKS_NV - VK_INDIRECT_COMMANDS_TOKEN_TYPE_SHADER_GROUP_NV + 1),
+    VK_INDIRECT_COMMANDS_TOKEN_TYPE_MAX_ENUM_NV = 0x7FFFFFFF
+} VkIndirectCommandsTokenTypeNV;
+
+typedef enum VkIndirectStateFlagBitsNV {
+    VK_INDIRECT_STATE_FLAG_FRONTFACE_BIT_NV = 0x00000001,
+    VK_INDIRECT_STATE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF
+} VkIndirectStateFlagBitsNV;
+typedef VkFlags VkIndirectStateFlagsNV;
+
+typedef enum VkIndirectCommandsLayoutUsageFlagBitsNV {
+    VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EXPLICIT_PREPROCESS_BIT_NV = 0x00000001,
+    VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NV = 0x00000002,
+    VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NV = 0x00000004,
+    VK_INDIRECT_COMMANDS_LAYOUT_USAGE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF
+} VkIndirectCommandsLayoutUsageFlagBitsNV;
+typedef VkFlags VkIndirectCommandsLayoutUsageFlagsNV;
+typedef struct VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV {
+    VkStructureType    sType;
+    void*              pNext;
+    uint32_t           maxGraphicsShaderGroupCount;
+    uint32_t           maxIndirectSequenceCount;
+    uint32_t           maxIndirectCommandsTokenCount;
+    uint32_t           maxIndirectCommandsStreamCount;
+    uint32_t           maxIndirectCommandsTokenOffset;
+    uint32_t           maxIndirectCommandsStreamStride;
+    uint32_t           minSequencesCountBufferOffsetAlignment;
+    uint32_t           minSequencesIndexBufferOffsetAlignment;
+    uint32_t           minIndirectCommandsBufferOffsetAlignment;
+} VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV;
+
+typedef struct VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV {
+    VkStructureType    sType;
+    void*              pNext;
+    VkBool32           deviceGeneratedCommands;
+} VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV;
+
+typedef struct VkGraphicsShaderGroupCreateInfoNV {
+    VkStructureType                                 sType;
+    const void*                                     pNext;
+    uint32_t                                        stageCount;
+    const VkPipelineShaderStageCreateInfo*          pStages;
+    const VkPipelineVertexInputStateCreateInfo*     pVertexInputState;
+    const VkPipelineTessellationStateCreateInfo*    pTessellationState;
+} VkGraphicsShaderGroupCreateInfoNV;
+
+typedef struct VkGraphicsPipelineShaderGroupsCreateInfoNV {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    uint32_t                                    groupCount;
+    const VkGraphicsShaderGroupCreateInfoNV*    pGroups;
+    uint32_t                                    pipelineCount;
+    const VkPipeline*                           pPipelines;
+} VkGraphicsPipelineShaderGroupsCreateInfoNV;
+
+typedef struct VkBindShaderGroupIndirectCommandNV {
+    uint32_t    groupIndex;
+} VkBindShaderGroupIndirectCommandNV;
+
+typedef struct VkBindIndexBufferIndirectCommandNV {
+    VkDeviceAddress    bufferAddress;
+    uint32_t           size;
+    VkIndexType        indexType;
+} VkBindIndexBufferIndirectCommandNV;
+
+typedef struct VkBindVertexBufferIndirectCommandNV {
+    VkDeviceAddress    bufferAddress;
+    uint32_t           size;
+    uint32_t           stride;
+} VkBindVertexBufferIndirectCommandNV;
+
+typedef struct VkSetStateFlagsIndirectCommandNV {
+    uint32_t    data;
+} VkSetStateFlagsIndirectCommandNV;
+
+typedef struct VkIndirectCommandsStreamNV {
+    VkBuffer        buffer;
+    VkDeviceSize    offset;
+} VkIndirectCommandsStreamNV;
+
+typedef struct VkIndirectCommandsLayoutTokenNV {
+    VkStructureType                  sType;
+    const void*                      pNext;
+    VkIndirectCommandsTokenTypeNV    tokenType;
+    uint32_t                         stream;
+    uint32_t                         offset;
+    uint32_t                         vertexBindingUnit;
+    VkBool32                         vertexDynamicStride;
+    VkPipelineLayout                 pushconstantPipelineLayout;
+    VkShaderStageFlags               pushconstantShaderStageFlags;
+    uint32_t                         pushconstantOffset;
+    uint32_t                         pushconstantSize;
+    VkIndirectStateFlagsNV           indirectStateFlags;
+    uint32_t                         indexTypeCount;
+    const VkIndexType*               pIndexTypes;
+    const uint32_t*                  pIndexTypeValues;
+} VkIndirectCommandsLayoutTokenNV;
+
+typedef struct VkIndirectCommandsLayoutCreateInfoNV {
+    VkStructureType                           sType;
+    const void*                               pNext;
+    VkIndirectCommandsLayoutUsageFlagsNV      flags;
+    VkPipelineBindPoint                       pipelineBindPoint;
+    uint32_t                                  tokenCount;
+    const VkIndirectCommandsLayoutTokenNV*    pTokens;
+    uint32_t                                  streamCount;
+    const uint32_t*                           pStreamStrides;
+} VkIndirectCommandsLayoutCreateInfoNV;
+
+typedef struct VkGeneratedCommandsInfoNV {
+    VkStructureType                      sType;
+    const void*                          pNext;
+    VkPipelineBindPoint                  pipelineBindPoint;
+    VkPipeline                           pipeline;
+    VkIndirectCommandsLayoutNV           indirectCommandsLayout;
+    uint32_t                             streamCount;
+    const VkIndirectCommandsStreamNV*    pStreams;
+    uint32_t                             sequencesCount;
+    VkBuffer                             preprocessBuffer;
+    VkDeviceSize                         preprocessOffset;
+    VkDeviceSize                         preprocessSize;
+    VkBuffer                             sequencesCountBuffer;
+    VkDeviceSize                         sequencesCountOffset;
+    VkBuffer                             sequencesIndexBuffer;
+    VkDeviceSize                         sequencesIndexOffset;
+} VkGeneratedCommandsInfoNV;
+
+typedef struct VkGeneratedCommandsMemoryRequirementsInfoNV {
+    VkStructureType               sType;
+    const void*                   pNext;
+    VkPipelineBindPoint           pipelineBindPoint;
+    VkPipeline                    pipeline;
+    VkIndirectCommandsLayoutNV    indirectCommandsLayout;
+    uint32_t                      maxSequencesCount;
+} VkGeneratedCommandsMemoryRequirementsInfoNV;
+
+typedef void (VKAPI_PTR *PFN_vkGetGeneratedCommandsMemoryRequirementsNV)(VkDevice device, const VkGeneratedCommandsMemoryRequirementsInfoNV* pInfo, VkMemoryRequirements2* pMemoryRequirements);
+typedef void (VKAPI_PTR *PFN_vkCmdPreprocessGeneratedCommandsNV)(VkCommandBuffer commandBuffer, const VkGeneratedCommandsInfoNV* pGeneratedCommandsInfo);
+typedef void (VKAPI_PTR *PFN_vkCmdExecuteGeneratedCommandsNV)(VkCommandBuffer commandBuffer, VkBool32 isPreprocessed, const VkGeneratedCommandsInfoNV* pGeneratedCommandsInfo);
+typedef void (VKAPI_PTR *PFN_vkCmdBindPipelineShaderGroupNV)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline, uint32_t groupIndex);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateIndirectCommandsLayoutNV)(VkDevice device, const VkIndirectCommandsLayoutCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkIndirectCommandsLayoutNV* pIndirectCommandsLayout);
+typedef void (VKAPI_PTR *PFN_vkDestroyIndirectCommandsLayoutNV)(VkDevice device, VkIndirectCommandsLayoutNV indirectCommandsLayout, const VkAllocationCallbacks* pAllocator);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkGetGeneratedCommandsMemoryRequirementsNV(
+    VkDevice                                    device,
+    const VkGeneratedCommandsMemoryRequirementsInfoNV* pInfo,
+    VkMemoryRequirements2*                      pMemoryRequirements);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdPreprocessGeneratedCommandsNV(
+    VkCommandBuffer                             commandBuffer,
+    const VkGeneratedCommandsInfoNV*            pGeneratedCommandsInfo);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdExecuteGeneratedCommandsNV(
+    VkCommandBuffer                             commandBuffer,
+    VkBool32                                    isPreprocessed,
+    const VkGeneratedCommandsInfoNV*            pGeneratedCommandsInfo);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdBindPipelineShaderGroupNV(
+    VkCommandBuffer                             commandBuffer,
+    VkPipelineBindPoint                         pipelineBindPoint,
+    VkPipeline                                  pipeline,
+    uint32_t                                    groupIndex);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateIndirectCommandsLayoutNV(
+    VkDevice                                    device,
+    const VkIndirectCommandsLayoutCreateInfoNV* pCreateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkIndirectCommandsLayoutNV*                 pIndirectCommandsLayout);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyIndirectCommandsLayoutNV(
+    VkDevice                                    device,
+    VkIndirectCommandsLayoutNV                  indirectCommandsLayout,
+    const VkAllocationCallbacks*                pAllocator);
+#endif
+
+
 #define VK_EXT_texel_buffer_alignment 1
 #define VK_EXT_TEXEL_BUFFER_ALIGNMENT_SPEC_VERSION 1
 #define VK_EXT_TEXEL_BUFFER_ALIGNMENT_EXTENSION_NAME "VK_EXT_texel_buffer_alignment"
@@ -10745,6 +10913,47 @@
 #define VK_GOOGLE_USER_TYPE_SPEC_VERSION  1
 #define VK_GOOGLE_USER_TYPE_EXTENSION_NAME "VK_GOOGLE_user_type"
 
+
+#define VK_EXT_pipeline_creation_cache_control 1
+#define VK_EXT_PIPELINE_CREATION_CACHE_CONTROL_SPEC_VERSION 3
+#define VK_EXT_PIPELINE_CREATION_CACHE_CONTROL_EXTENSION_NAME "VK_EXT_pipeline_creation_cache_control"
+typedef struct VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT {
+    VkStructureType    sType;
+    void*              pNext;
+    VkBool32           pipelineCreationCacheControl;
+} VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT;
+
+
+
+#define VK_NV_device_diagnostics_config 1
+#define VK_NV_DEVICE_DIAGNOSTICS_CONFIG_SPEC_VERSION 1
+#define VK_NV_DEVICE_DIAGNOSTICS_CONFIG_EXTENSION_NAME "VK_NV_device_diagnostics_config"
+
+typedef enum VkDeviceDiagnosticsConfigFlagBitsNV {
+    VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_SHADER_DEBUG_INFO_BIT_NV = 0x00000001,
+    VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_RESOURCE_TRACKING_BIT_NV = 0x00000002,
+    VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_AUTOMATIC_CHECKPOINTS_BIT_NV = 0x00000004,
+    VK_DEVICE_DIAGNOSTICS_CONFIG_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF
+} VkDeviceDiagnosticsConfigFlagBitsNV;
+typedef VkFlags VkDeviceDiagnosticsConfigFlagsNV;
+typedef struct VkPhysicalDeviceDiagnosticsConfigFeaturesNV {
+    VkStructureType    sType;
+    void*              pNext;
+    VkBool32           diagnosticsConfig;
+} VkPhysicalDeviceDiagnosticsConfigFeaturesNV;
+
+typedef struct VkDeviceDiagnosticsConfigCreateInfoNV {
+    VkStructureType                     sType;
+    const void*                         pNext;
+    VkDeviceDiagnosticsConfigFlagsNV    flags;
+} VkDeviceDiagnosticsConfigCreateInfoNV;
+
+
+
+#define VK_QCOM_render_pass_store_ops 1
+#define VK_QCOM_render_pass_store_ops_SPEC_VERSION 2
+#define VK_QCOM_render_pass_store_ops_EXTENSION_NAME "VK_QCOM_render_pass_store_ops"
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/third_party/vulkan-headers/src/registry/conventions.py b/third_party/vulkan-headers/src/registry/conventions.py
index 2df9304..79971ea 100644
--- a/third_party/vulkan-headers/src/registry/conventions.py
+++ b/third_party/vulkan-headers/src/registry/conventions.py
@@ -81,8 +81,8 @@
         self._type_prefix = None
 
     def formatExtension(self, name):
-        """Mark up a name as an extension for the spec."""
-        return '`<<{}>>`'.format(name)
+        """Mark up an extension name as a link the spec."""
+        return '`apiext:{}`'.format(name)
 
     @property
     def null(self):
diff --git a/third_party/vulkan-headers/src/registry/generator.py b/third_party/vulkan-headers/src/registry/generator.py
index 47dfb70..95fda21 100644
--- a/third_party/vulkan-headers/src/registry/generator.py
+++ b/third_party/vulkan-headers/src/registry/generator.py
@@ -78,6 +78,7 @@
 def regSortOrderKey(feature):
     """Sort key for regSortFeatures - key is the sortorder attribute."""
 
+    # print("regSortOrderKey {} -> {}".format(feature.name, feature.sortorder))
     return feature.sortorder
 
 
@@ -98,14 +99,14 @@
 def regSortFeatures(featureList):
     """Default sort procedure for features.
 
-    - Sorts by primary key of feature category ('feature' or 'extension'),
-    - then by sort order within the category
+    - Sorts by explicit sort order (default 0) relative to other features
+    - then by feature category ('feature' or 'extension'),
     - then by version number (for features)
     - then by extension number (for extensions)"""
     featureList.sort(key=regSortExtensionNumberKey)
     featureList.sort(key=regSortFeatureVersionKey)
-    featureList.sort(key=regSortOrderKey)
     featureList.sort(key=regSortCategoryKey)
+    featureList.sort(key=regSortOrderKey)
 
 
 class GeneratorOptions:
diff --git a/third_party/vulkan-headers/src/registry/genvk.py b/third_party/vulkan-headers/src/registry/genvk.py
index 37d050e..668be79 100755
--- a/third_party/vulkan-headers/src/registry/genvk.py
+++ b/third_party/vulkan-headers/src/registry/genvk.py
@@ -245,10 +245,16 @@
     # Track all platform extensions, for exclusion from vulkan_core.h
     allPlatformExtensions = []
 
-    # Extensions suppressed for all platforms.
-    # Covers common WSI extension types.
+    # Extensions suppressed for all WSI platforms (WSI extensions required
+    # by all platforms)
     commonSuppressExtensions = [ 'VK_KHR_display', 'VK_KHR_swapchain' ]
 
+    # Extensions required and suppressed for beta "platform". This can
+    # probably eventually be derived from the requires= attributes of
+    # the extension blocks.
+    betaRequireExtensions = [ 'VK_KHR_ray_tracing', 'VK_KHR_deferred_host_operations', 'VK_KHR_pipeline_library' ]
+    betaSuppressExtensions = [ 'VK_NV_ray_tracing' ]
+
     platforms = [
         [ 'vulkan_android.h',     [ 'VK_KHR_android_surface',
                                     'VK_ANDROID_external_memory_android_hardware_buffer'
@@ -273,6 +279,7 @@
         [ 'vulkan_xlib.h',        [ 'VK_KHR_xlib_surface'         ], commonSuppressExtensions ],
         [ 'vulkan_xlib_xrandr.h', [ 'VK_EXT_acquire_xlib_display' ], commonSuppressExtensions ],
         [ 'vulkan_metal.h',       [ 'VK_EXT_metal_surface'        ], commonSuppressExtensions ],
+        [ 'vulkan_beta.h',        betaRequireExtensions,             betaSuppressExtensions ],
     ]
 
     for platform in platforms:
diff --git a/third_party/vulkan-headers/src/registry/reg.py b/third_party/vulkan-headers/src/registry/reg.py
index da769ab..24012de 100755
--- a/third_party/vulkan-headers/src/registry/reg.py
+++ b/third_party/vulkan-headers/src/registry/reg.py
@@ -1120,6 +1120,7 @@
         # Sort the features list, if a sort procedure is defined
         if self.genOpts.sortProcedure:
             self.genOpts.sortProcedure(features)
+            # print('sortProcedure ->', [f.name for f in features])
 
         # Pass 1: loop over requested API versions and extensions tagging
         #   types/commands/features as required (in an <require> block) or no
diff --git a/third_party/vulkan-headers/src/registry/validusage.json b/third_party/vulkan-headers/src/registry/validusage.json
index b0750a3..b2c58c7 100644
--- a/third_party/vulkan-headers/src/registry/validusage.json
+++ b/third_party/vulkan-headers/src/registry/validusage.json
@@ -1,9 +1,9 @@
 {
   "version info": {
     "schema version": 2,
-    "api version": "1.2.134",
-    "comment": "from git branch: github-master commit: b27536168823d5e8b025fc5622eab7df54008589",
-    "date": "2020-03-06 14:02:32Z"
+    "api version": "1.2.137",
+    "comment": "from git branch: github-master commit: 019f62b11de9358d3383ead2e1a8c5bc2fda23ad",
+    "date": "2020-04-07 05:14:56Z"
   },
   "validation": {
     "vkGetInstanceProcAddr": {
@@ -42,7 +42,7 @@
       "core": [
         {
           "vuid": "VUID-vkCreateInstance-ppEnabledExtensionNames-01388",
-          "text": " All <a href=\"#extendingvulkan-extensions-extensiondependencies\">required extensions</a> for each extension in the <a href=\"#VkInstanceCreateInfo\">VkInstanceCreateInfo</a>::<code>ppEnabledExtensionNames</code> list <strong class=\"purple\">must</strong> also be present in that list."
+          "text": " All <a href=\"#extendingvulkan-extensions-extensiondependencies\">required extensions</a> for each extension in the <a href=\"#VkInstanceCreateInfo\">VkInstanceCreateInfo</a>::<code>ppEnabledExtensionNames</code> list <strong class=\"purple\">must</strong> also be present in that list"
         },
         {
           "vuid": "VUID-vkCreateInstance-pCreateInfo-parameter",
@@ -109,6 +109,14 @@
     "VkValidationFeaturesEXT": {
       "(VK_EXT_validation_features)": [
         {
+          "vuid": "VUID-VkValidationFeaturesEXT-pEnabledValidationFeatures-02967",
+          "text": " If the <code>pEnabledValidationFeatures</code> array contains <code>VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT</code>, then it <strong class=\"purple\">must</strong> also contain <code>VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT</code>"
+        },
+        {
+          "vuid": "VUID-VkValidationFeaturesEXT-pEnabledValidationFeatures-02968",
+          "text": " If the <code>pEnabledValidationFeatures</code> array contains <code>VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT</code>, then it <strong class=\"purple\">must</strong> not contain <code>VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT</code>"
+        },
+        {
           "vuid": "VUID-VkValidationFeaturesEXT-sType-sType",
           "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT</code>"
         },
@@ -214,7 +222,7 @@
         },
         {
           "vuid": "VUID-VkPhysicalDeviceProperties2-pNext-pNext",
-          "text": " Each <code>pNext</code> member of any structure (including this one) in the <code>pNext</code> chain <strong class=\"purple\">must</strong> be either <code>NULL</code> or a pointer to a valid instance of <a href=\"#VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT\">VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT</a>, <a href=\"#VkPhysicalDeviceConservativeRasterizationPropertiesEXT\">VkPhysicalDeviceConservativeRasterizationPropertiesEXT</a>, <a href=\"#VkPhysicalDeviceCooperativeMatrixPropertiesNV\">VkPhysicalDeviceCooperativeMatrixPropertiesNV</a>, <a href=\"#VkPhysicalDeviceDepthStencilResolveProperties\">VkPhysicalDeviceDepthStencilResolveProperties</a>, <a href=\"#VkPhysicalDeviceDescriptorIndexingProperties\">VkPhysicalDeviceDescriptorIndexingProperties</a>, <a href=\"#VkPhysicalDeviceDiscardRectanglePropertiesEXT\">VkPhysicalDeviceDiscardRectanglePropertiesEXT</a>, <a href=\"#VkPhysicalDeviceDriverProperties\">VkPhysicalDeviceDriverProperties</a>, <a href=\"#VkPhysicalDeviceExternalMemoryHostPropertiesEXT\">VkPhysicalDeviceExternalMemoryHostPropertiesEXT</a>, <a href=\"#VkPhysicalDeviceFloatControlsProperties\">VkPhysicalDeviceFloatControlsProperties</a>, <a href=\"#VkPhysicalDeviceFragmentDensityMapPropertiesEXT\">VkPhysicalDeviceFragmentDensityMapPropertiesEXT</a>, <a href=\"#VkPhysicalDeviceIDProperties\">VkPhysicalDeviceIDProperties</a>, <a href=\"#VkPhysicalDeviceInlineUniformBlockPropertiesEXT\">VkPhysicalDeviceInlineUniformBlockPropertiesEXT</a>, <a href=\"#VkPhysicalDeviceLineRasterizationPropertiesEXT\">VkPhysicalDeviceLineRasterizationPropertiesEXT</a>, <a href=\"#VkPhysicalDeviceMaintenance3Properties\">VkPhysicalDeviceMaintenance3Properties</a>, <a href=\"#VkPhysicalDeviceMeshShaderPropertiesNV\">VkPhysicalDeviceMeshShaderPropertiesNV</a>, <a href=\"#VkPhysicalDeviceMultiviewPerViewAttributesPropertiesNVX\">VkPhysicalDeviceMultiviewPerViewAttributesPropertiesNVX</a>, <a href=\"#VkPhysicalDeviceMultiviewProperties\">VkPhysicalDeviceMultiviewProperties</a>, <a href=\"#VkPhysicalDevicePCIBusInfoPropertiesEXT\">VkPhysicalDevicePCIBusInfoPropertiesEXT</a>, <a href=\"#VkPhysicalDevicePerformanceQueryPropertiesKHR\">VkPhysicalDevicePerformanceQueryPropertiesKHR</a>, <a href=\"#VkPhysicalDevicePointClippingProperties\">VkPhysicalDevicePointClippingProperties</a>, <a href=\"#VkPhysicalDeviceProtectedMemoryProperties\">VkPhysicalDeviceProtectedMemoryProperties</a>, <a href=\"#VkPhysicalDevicePushDescriptorPropertiesKHR\">VkPhysicalDevicePushDescriptorPropertiesKHR</a>, <a href=\"#VkPhysicalDeviceRayTracingPropertiesNV\">VkPhysicalDeviceRayTracingPropertiesNV</a>, <a href=\"#VkPhysicalDeviceSampleLocationsPropertiesEXT\">VkPhysicalDeviceSampleLocationsPropertiesEXT</a>, <a href=\"#VkPhysicalDeviceSamplerFilterMinmaxProperties\">VkPhysicalDeviceSamplerFilterMinmaxProperties</a>, <a href=\"#VkPhysicalDeviceShaderCoreProperties2AMD\">VkPhysicalDeviceShaderCoreProperties2AMD</a>, <a href=\"#VkPhysicalDeviceShaderCorePropertiesAMD\">VkPhysicalDeviceShaderCorePropertiesAMD</a>, <a href=\"#VkPhysicalDeviceShaderSMBuiltinsPropertiesNV\">VkPhysicalDeviceShaderSMBuiltinsPropertiesNV</a>, <a href=\"#VkPhysicalDeviceShadingRateImagePropertiesNV\">VkPhysicalDeviceShadingRateImagePropertiesNV</a>, <a href=\"#VkPhysicalDeviceSubgroupProperties\">VkPhysicalDeviceSubgroupProperties</a>, <a href=\"#VkPhysicalDeviceSubgroupSizeControlPropertiesEXT\">VkPhysicalDeviceSubgroupSizeControlPropertiesEXT</a>, <a href=\"#VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT\">VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT</a>, <a href=\"#VkPhysicalDeviceTimelineSemaphoreProperties\">VkPhysicalDeviceTimelineSemaphoreProperties</a>, <a href=\"#VkPhysicalDeviceTransformFeedbackPropertiesEXT\">VkPhysicalDeviceTransformFeedbackPropertiesEXT</a>, <a href=\"#VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT\">VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT</a>, <a href=\"#VkPhysicalDeviceVulkan11Properties\">VkPhysicalDeviceVulkan11Properties</a>, or <a href=\"#VkPhysicalDeviceVulkan12Properties\">VkPhysicalDeviceVulkan12Properties</a>"
+          "text": " Each <code>pNext</code> member of any structure (including this one) in the <code>pNext</code> chain <strong class=\"purple\">must</strong> be either <code>NULL</code> or a pointer to a valid instance of <a href=\"#VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT\">VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT</a>, <a href=\"#VkPhysicalDeviceConservativeRasterizationPropertiesEXT\">VkPhysicalDeviceConservativeRasterizationPropertiesEXT</a>, <a href=\"#VkPhysicalDeviceCooperativeMatrixPropertiesNV\">VkPhysicalDeviceCooperativeMatrixPropertiesNV</a>, <a href=\"#VkPhysicalDeviceDepthStencilResolveProperties\">VkPhysicalDeviceDepthStencilResolveProperties</a>, <a href=\"#VkPhysicalDeviceDescriptorIndexingProperties\">VkPhysicalDeviceDescriptorIndexingProperties</a>, <a href=\"#VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV\">VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV</a>, <a href=\"#VkPhysicalDeviceDiscardRectanglePropertiesEXT\">VkPhysicalDeviceDiscardRectanglePropertiesEXT</a>, <a href=\"#VkPhysicalDeviceDriverProperties\">VkPhysicalDeviceDriverProperties</a>, <a href=\"#VkPhysicalDeviceExternalMemoryHostPropertiesEXT\">VkPhysicalDeviceExternalMemoryHostPropertiesEXT</a>, <a href=\"#VkPhysicalDeviceFloatControlsProperties\">VkPhysicalDeviceFloatControlsProperties</a>, <a href=\"#VkPhysicalDeviceFragmentDensityMapPropertiesEXT\">VkPhysicalDeviceFragmentDensityMapPropertiesEXT</a>, <a href=\"#VkPhysicalDeviceIDProperties\">VkPhysicalDeviceIDProperties</a>, <a href=\"#VkPhysicalDeviceInlineUniformBlockPropertiesEXT\">VkPhysicalDeviceInlineUniformBlockPropertiesEXT</a>, <a href=\"#VkPhysicalDeviceLineRasterizationPropertiesEXT\">VkPhysicalDeviceLineRasterizationPropertiesEXT</a>, <a href=\"#VkPhysicalDeviceMaintenance3Properties\">VkPhysicalDeviceMaintenance3Properties</a>, <a href=\"#VkPhysicalDeviceMeshShaderPropertiesNV\">VkPhysicalDeviceMeshShaderPropertiesNV</a>, <a href=\"#VkPhysicalDeviceMultiviewPerViewAttributesPropertiesNVX\">VkPhysicalDeviceMultiviewPerViewAttributesPropertiesNVX</a>, <a href=\"#VkPhysicalDeviceMultiviewProperties\">VkPhysicalDeviceMultiviewProperties</a>, <a href=\"#VkPhysicalDevicePCIBusInfoPropertiesEXT\">VkPhysicalDevicePCIBusInfoPropertiesEXT</a>, <a href=\"#VkPhysicalDevicePerformanceQueryPropertiesKHR\">VkPhysicalDevicePerformanceQueryPropertiesKHR</a>, <a href=\"#VkPhysicalDevicePointClippingProperties\">VkPhysicalDevicePointClippingProperties</a>, <a href=\"#VkPhysicalDeviceProtectedMemoryProperties\">VkPhysicalDeviceProtectedMemoryProperties</a>, <a href=\"#VkPhysicalDevicePushDescriptorPropertiesKHR\">VkPhysicalDevicePushDescriptorPropertiesKHR</a>, <a href=\"#VkPhysicalDeviceRayTracingPropertiesKHR\">VkPhysicalDeviceRayTracingPropertiesKHR</a>, <a href=\"#VkPhysicalDeviceRayTracingPropertiesNV\">VkPhysicalDeviceRayTracingPropertiesNV</a>, <a href=\"#VkPhysicalDeviceSampleLocationsPropertiesEXT\">VkPhysicalDeviceSampleLocationsPropertiesEXT</a>, <a href=\"#VkPhysicalDeviceSamplerFilterMinmaxProperties\">VkPhysicalDeviceSamplerFilterMinmaxProperties</a>, <a href=\"#VkPhysicalDeviceShaderCoreProperties2AMD\">VkPhysicalDeviceShaderCoreProperties2AMD</a>, <a href=\"#VkPhysicalDeviceShaderCorePropertiesAMD\">VkPhysicalDeviceShaderCorePropertiesAMD</a>, <a href=\"#VkPhysicalDeviceShaderSMBuiltinsPropertiesNV\">VkPhysicalDeviceShaderSMBuiltinsPropertiesNV</a>, <a href=\"#VkPhysicalDeviceShadingRateImagePropertiesNV\">VkPhysicalDeviceShadingRateImagePropertiesNV</a>, <a href=\"#VkPhysicalDeviceSubgroupProperties\">VkPhysicalDeviceSubgroupProperties</a>, <a href=\"#VkPhysicalDeviceSubgroupSizeControlPropertiesEXT\">VkPhysicalDeviceSubgroupSizeControlPropertiesEXT</a>, <a href=\"#VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT\">VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT</a>, <a href=\"#VkPhysicalDeviceTimelineSemaphoreProperties\">VkPhysicalDeviceTimelineSemaphoreProperties</a>, <a href=\"#VkPhysicalDeviceTransformFeedbackPropertiesEXT\">VkPhysicalDeviceTransformFeedbackPropertiesEXT</a>, <a href=\"#VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT\">VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT</a>, <a href=\"#VkPhysicalDeviceVulkan11Properties\">VkPhysicalDeviceVulkan11Properties</a>, or <a href=\"#VkPhysicalDeviceVulkan12Properties\">VkPhysicalDeviceVulkan12Properties</a>"
         },
         {
           "vuid": "VUID-VkPhysicalDeviceProperties2-sType-unique",
@@ -227,10 +235,6 @@
         {
           "vuid": "VUID-VkPhysicalDeviceVulkan11Properties-sType-sType",
           "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES</code>"
-        },
-        {
-          "vuid": "VUID-VkPhysicalDeviceVulkan11Properties-pointClippingBehavior-parameter",
-          "text": " <code>pointClippingBehavior</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkPointClippingBehavior\">VkPointClippingBehavior</a> value"
         }
       ]
     },
@@ -239,46 +243,6 @@
         {
           "vuid": "VUID-VkPhysicalDeviceVulkan12Properties-sType-sType",
           "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES</code>"
-        },
-        {
-          "vuid": "VUID-VkPhysicalDeviceVulkan12Properties-driverID-parameter",
-          "text": " <code>driverID</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDriverId\">VkDriverId</a> value"
-        },
-        {
-          "vuid": "VUID-VkPhysicalDeviceVulkan12Properties-driverName-parameter",
-          "text": " <code>driverName</code> <strong class=\"purple\">must</strong> be a null-terminated UTF-8 string whose length is less than or equal to VK_MAX_DRIVER_NAME_SIZE"
-        },
-        {
-          "vuid": "VUID-VkPhysicalDeviceVulkan12Properties-driverInfo-parameter",
-          "text": " <code>driverInfo</code> <strong class=\"purple\">must</strong> be a null-terminated UTF-8 string whose length is less than or equal to VK_MAX_DRIVER_INFO_SIZE"
-        },
-        {
-          "vuid": "VUID-VkPhysicalDeviceVulkan12Properties-denormBehaviorIndependence-parameter",
-          "text": " <code>denormBehaviorIndependence</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkShaderFloatControlsIndependence\">VkShaderFloatControlsIndependence</a> value"
-        },
-        {
-          "vuid": "VUID-VkPhysicalDeviceVulkan12Properties-roundingModeIndependence-parameter",
-          "text": " <code>roundingModeIndependence</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkShaderFloatControlsIndependence\">VkShaderFloatControlsIndependence</a> value"
-        },
-        {
-          "vuid": "VUID-VkPhysicalDeviceVulkan12Properties-supportedDepthResolveModes-parameter",
-          "text": " <code>supportedDepthResolveModes</code> <strong class=\"purple\">must</strong> be a valid combination of <a href=\"#VkResolveModeFlagBits\">VkResolveModeFlagBits</a> values"
-        },
-        {
-          "vuid": "VUID-VkPhysicalDeviceVulkan12Properties-supportedDepthResolveModes-requiredbitmask",
-          "text": " <code>supportedDepthResolveModes</code> <strong class=\"purple\">must</strong> not be <code>0</code>"
-        },
-        {
-          "vuid": "VUID-VkPhysicalDeviceVulkan12Properties-supportedStencilResolveModes-parameter",
-          "text": " <code>supportedStencilResolveModes</code> <strong class=\"purple\">must</strong> be a valid combination of <a href=\"#VkResolveModeFlagBits\">VkResolveModeFlagBits</a> values"
-        },
-        {
-          "vuid": "VUID-VkPhysicalDeviceVulkan12Properties-supportedStencilResolveModes-requiredbitmask",
-          "text": " <code>supportedStencilResolveModes</code> <strong class=\"purple\">must</strong> not be <code>0</code>"
-        },
-        {
-          "vuid": "VUID-VkPhysicalDeviceVulkan12Properties-framebufferIntegerColorSampleCounts-parameter",
-          "text": " <code>framebufferIntegerColorSampleCounts</code> <strong class=\"purple\">must</strong> be a valid combination of <a href=\"#VkSampleCountFlagBits\">VkSampleCountFlagBits</a> values"
         }
       ]
     },
@@ -438,7 +402,7 @@
       "core": [
         {
           "vuid": "VUID-vkCreateDevice-ppEnabledExtensionNames-01387",
-          "text": " All <a href=\"#extendingvulkan-extensions-extensiondependencies\">required extensions</a> for each extension in the <a href=\"#VkDeviceCreateInfo\">VkDeviceCreateInfo</a>::<code>ppEnabledExtensionNames</code> list <strong class=\"purple\">must</strong> also be present in that list."
+          "text": " All <a href=\"#extendingvulkan-extensions-extensiondependencies\">required extensions</a> for each extension in the <a href=\"#VkDeviceCreateInfo\">VkDeviceCreateInfo</a>::<code>ppEnabledExtensionNames</code> list <strong class=\"purple\">must</strong> also be present in that list"
         },
         {
           "vuid": "VUID-vkCreateDevice-physicalDevice-parameter",
@@ -542,7 +506,7 @@
         },
         {
           "vuid": "VUID-VkDeviceCreateInfo-pNext-pNext",
-          "text": " Each <code>pNext</code> member of any structure (including this one) in the <code>pNext</code> chain <strong class=\"purple\">must</strong> be either <code>NULL</code> or a pointer to a valid instance of <a href=\"#VkDeviceGroupDeviceCreateInfo\">VkDeviceGroupDeviceCreateInfo</a>, <a href=\"#VkDeviceMemoryOverallocationCreateInfoAMD\">VkDeviceMemoryOverallocationCreateInfoAMD</a>, <a href=\"#VkPhysicalDevice16BitStorageFeatures\">VkPhysicalDevice16BitStorageFeatures</a>, <a href=\"#VkPhysicalDevice8BitStorageFeatures\">VkPhysicalDevice8BitStorageFeatures</a>, <a href=\"#VkPhysicalDeviceASTCDecodeFeaturesEXT\">VkPhysicalDeviceASTCDecodeFeaturesEXT</a>, <a href=\"#VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT\">VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT</a>, <a href=\"#VkPhysicalDeviceBufferDeviceAddressFeatures\">VkPhysicalDeviceBufferDeviceAddressFeatures</a>, <a href=\"#VkPhysicalDeviceBufferDeviceAddressFeaturesEXT\">VkPhysicalDeviceBufferDeviceAddressFeaturesEXT</a>, <a href=\"#VkPhysicalDeviceCoherentMemoryFeaturesAMD\">VkPhysicalDeviceCoherentMemoryFeaturesAMD</a>, <a href=\"#VkPhysicalDeviceComputeShaderDerivativesFeaturesNV\">VkPhysicalDeviceComputeShaderDerivativesFeaturesNV</a>, <a href=\"#VkPhysicalDeviceConditionalRenderingFeaturesEXT\">VkPhysicalDeviceConditionalRenderingFeaturesEXT</a>, <a href=\"#VkPhysicalDeviceCooperativeMatrixFeaturesNV\">VkPhysicalDeviceCooperativeMatrixFeaturesNV</a>, <a href=\"#VkPhysicalDeviceCornerSampledImageFeaturesNV\">VkPhysicalDeviceCornerSampledImageFeaturesNV</a>, <a href=\"#VkPhysicalDeviceCoverageReductionModeFeaturesNV\">VkPhysicalDeviceCoverageReductionModeFeaturesNV</a>, <a href=\"#VkPhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV\">VkPhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV</a>, <a href=\"#VkPhysicalDeviceDepthClipEnableFeaturesEXT\">VkPhysicalDeviceDepthClipEnableFeaturesEXT</a>, <a href=\"#VkPhysicalDeviceDescriptorIndexingFeatures\">VkPhysicalDeviceDescriptorIndexingFeatures</a>, <a href=\"#VkPhysicalDeviceExclusiveScissorFeaturesNV\">VkPhysicalDeviceExclusiveScissorFeaturesNV</a>, <a href=\"#VkPhysicalDeviceFeatures2\">VkPhysicalDeviceFeatures2</a>, <a href=\"#VkPhysicalDeviceFragmentDensityMapFeaturesEXT\">VkPhysicalDeviceFragmentDensityMapFeaturesEXT</a>, <a href=\"#VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV\">VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV</a>, <a href=\"#VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT\">VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT</a>, <a href=\"#VkPhysicalDeviceHostQueryResetFeatures\">VkPhysicalDeviceHostQueryResetFeatures</a>, <a href=\"#VkPhysicalDeviceImagelessFramebufferFeatures\">VkPhysicalDeviceImagelessFramebufferFeatures</a>, <a href=\"#VkPhysicalDeviceIndexTypeUint8FeaturesEXT\">VkPhysicalDeviceIndexTypeUint8FeaturesEXT</a>, <a href=\"#VkPhysicalDeviceInlineUniformBlockFeaturesEXT\">VkPhysicalDeviceInlineUniformBlockFeaturesEXT</a>, <a href=\"#VkPhysicalDeviceLineRasterizationFeaturesEXT\">VkPhysicalDeviceLineRasterizationFeaturesEXT</a>, <a href=\"#VkPhysicalDeviceMemoryPriorityFeaturesEXT\">VkPhysicalDeviceMemoryPriorityFeaturesEXT</a>, <a href=\"#VkPhysicalDeviceMeshShaderFeaturesNV\">VkPhysicalDeviceMeshShaderFeaturesNV</a>, <a href=\"#VkPhysicalDeviceMultiviewFeatures\">VkPhysicalDeviceMultiviewFeatures</a>, <a href=\"#VkPhysicalDevicePerformanceQueryFeaturesKHR\">VkPhysicalDevicePerformanceQueryFeaturesKHR</a>, <a href=\"#VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR\">VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR</a>, <a href=\"#VkPhysicalDeviceProtectedMemoryFeatures\">VkPhysicalDeviceProtectedMemoryFeatures</a>, <a href=\"#VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV\">VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV</a>, <a href=\"#VkPhysicalDeviceSamplerYcbcrConversionFeatures\">VkPhysicalDeviceSamplerYcbcrConversionFeatures</a>, <a href=\"#VkPhysicalDeviceScalarBlockLayoutFeatures\">VkPhysicalDeviceScalarBlockLayoutFeatures</a>, <a href=\"#VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures\">VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures</a>, <a href=\"#VkPhysicalDeviceShaderAtomicInt64Features\">VkPhysicalDeviceShaderAtomicInt64Features</a>, <a href=\"#VkPhysicalDeviceShaderClockFeaturesKHR\">VkPhysicalDeviceShaderClockFeaturesKHR</a>, <a href=\"#VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT\">VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT</a>, <a href=\"#VkPhysicalDeviceShaderDrawParametersFeatures\">VkPhysicalDeviceShaderDrawParametersFeatures</a>, <a href=\"#VkPhysicalDeviceShaderFloat16Int8Features\">VkPhysicalDeviceShaderFloat16Int8Features</a>, <a href=\"#VkPhysicalDeviceShaderImageFootprintFeaturesNV\">VkPhysicalDeviceShaderImageFootprintFeaturesNV</a>, <a href=\"#VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL\">VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL</a>, <a href=\"#VkPhysicalDeviceShaderSMBuiltinsFeaturesNV\">VkPhysicalDeviceShaderSMBuiltinsFeaturesNV</a>, <a href=\"#VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures\">VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures</a>, <a href=\"#VkPhysicalDeviceShadingRateImageFeaturesNV\">VkPhysicalDeviceShadingRateImageFeaturesNV</a>, <a href=\"#VkPhysicalDeviceSubgroupSizeControlFeaturesEXT\">VkPhysicalDeviceSubgroupSizeControlFeaturesEXT</a>, <a href=\"#VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT\">VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT</a>, <a href=\"#VkPhysicalDeviceTextureCompressionASTCHDRFeaturesEXT\">VkPhysicalDeviceTextureCompressionASTCHDRFeaturesEXT</a>, <a href=\"#VkPhysicalDeviceTimelineSemaphoreFeatures\">VkPhysicalDeviceTimelineSemaphoreFeatures</a>, <a href=\"#VkPhysicalDeviceTransformFeedbackFeaturesEXT\">VkPhysicalDeviceTransformFeedbackFeaturesEXT</a>, <a href=\"#VkPhysicalDeviceUniformBufferStandardLayoutFeatures\">VkPhysicalDeviceUniformBufferStandardLayoutFeatures</a>, <a href=\"#VkPhysicalDeviceVariablePointersFeatures\">VkPhysicalDeviceVariablePointersFeatures</a>, <a href=\"#VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT\">VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT</a>, <a href=\"#VkPhysicalDeviceVulkan11Features\">VkPhysicalDeviceVulkan11Features</a>, <a href=\"#VkPhysicalDeviceVulkan12Features\">VkPhysicalDeviceVulkan12Features</a>, <a href=\"#VkPhysicalDeviceVulkanMemoryModelFeatures\">VkPhysicalDeviceVulkanMemoryModelFeatures</a>, or <a href=\"#VkPhysicalDeviceYcbcrImageArraysFeaturesEXT\">VkPhysicalDeviceYcbcrImageArraysFeaturesEXT</a>"
+          "text": " Each <code>pNext</code> member of any structure (including this one) in the <code>pNext</code> chain <strong class=\"purple\">must</strong> be either <code>NULL</code> or a pointer to a valid instance of <a href=\"#VkDeviceDiagnosticsConfigCreateInfoNV\">VkDeviceDiagnosticsConfigCreateInfoNV</a>, <a href=\"#VkDeviceGroupDeviceCreateInfo\">VkDeviceGroupDeviceCreateInfo</a>, <a href=\"#VkDeviceMemoryOverallocationCreateInfoAMD\">VkDeviceMemoryOverallocationCreateInfoAMD</a>, <a href=\"#VkPhysicalDevice16BitStorageFeatures\">VkPhysicalDevice16BitStorageFeatures</a>, <a href=\"#VkPhysicalDevice8BitStorageFeatures\">VkPhysicalDevice8BitStorageFeatures</a>, <a href=\"#VkPhysicalDeviceASTCDecodeFeaturesEXT\">VkPhysicalDeviceASTCDecodeFeaturesEXT</a>, <a href=\"#VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT\">VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT</a>, <a href=\"#VkPhysicalDeviceBufferDeviceAddressFeatures\">VkPhysicalDeviceBufferDeviceAddressFeatures</a>, <a href=\"#VkPhysicalDeviceBufferDeviceAddressFeaturesEXT\">VkPhysicalDeviceBufferDeviceAddressFeaturesEXT</a>, <a href=\"#VkPhysicalDeviceCoherentMemoryFeaturesAMD\">VkPhysicalDeviceCoherentMemoryFeaturesAMD</a>, <a href=\"#VkPhysicalDeviceComputeShaderDerivativesFeaturesNV\">VkPhysicalDeviceComputeShaderDerivativesFeaturesNV</a>, <a href=\"#VkPhysicalDeviceConditionalRenderingFeaturesEXT\">VkPhysicalDeviceConditionalRenderingFeaturesEXT</a>, <a href=\"#VkPhysicalDeviceCooperativeMatrixFeaturesNV\">VkPhysicalDeviceCooperativeMatrixFeaturesNV</a>, <a href=\"#VkPhysicalDeviceCornerSampledImageFeaturesNV\">VkPhysicalDeviceCornerSampledImageFeaturesNV</a>, <a href=\"#VkPhysicalDeviceCoverageReductionModeFeaturesNV\">VkPhysicalDeviceCoverageReductionModeFeaturesNV</a>, <a href=\"#VkPhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV\">VkPhysicalDeviceDedicatedAllocationImageAliasingFeaturesNV</a>, <a href=\"#VkPhysicalDeviceDepthClipEnableFeaturesEXT\">VkPhysicalDeviceDepthClipEnableFeaturesEXT</a>, <a href=\"#VkPhysicalDeviceDescriptorIndexingFeatures\">VkPhysicalDeviceDescriptorIndexingFeatures</a>, <a href=\"#VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV\">VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV</a>, <a href=\"#VkPhysicalDeviceDiagnosticsConfigFeaturesNV\">VkPhysicalDeviceDiagnosticsConfigFeaturesNV</a>, <a href=\"#VkPhysicalDeviceExclusiveScissorFeaturesNV\">VkPhysicalDeviceExclusiveScissorFeaturesNV</a>, <a href=\"#VkPhysicalDeviceFeatures2\">VkPhysicalDeviceFeatures2</a>, <a href=\"#VkPhysicalDeviceFragmentDensityMapFeaturesEXT\">VkPhysicalDeviceFragmentDensityMapFeaturesEXT</a>, <a href=\"#VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV\">VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV</a>, <a href=\"#VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT\">VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT</a>, <a href=\"#VkPhysicalDeviceHostQueryResetFeatures\">VkPhysicalDeviceHostQueryResetFeatures</a>, <a href=\"#VkPhysicalDeviceImagelessFramebufferFeatures\">VkPhysicalDeviceImagelessFramebufferFeatures</a>, <a href=\"#VkPhysicalDeviceIndexTypeUint8FeaturesEXT\">VkPhysicalDeviceIndexTypeUint8FeaturesEXT</a>, <a href=\"#VkPhysicalDeviceInlineUniformBlockFeaturesEXT\">VkPhysicalDeviceInlineUniformBlockFeaturesEXT</a>, <a href=\"#VkPhysicalDeviceLineRasterizationFeaturesEXT\">VkPhysicalDeviceLineRasterizationFeaturesEXT</a>, <a href=\"#VkPhysicalDeviceMemoryPriorityFeaturesEXT\">VkPhysicalDeviceMemoryPriorityFeaturesEXT</a>, <a href=\"#VkPhysicalDeviceMeshShaderFeaturesNV\">VkPhysicalDeviceMeshShaderFeaturesNV</a>, <a href=\"#VkPhysicalDeviceMultiviewFeatures\">VkPhysicalDeviceMultiviewFeatures</a>, <a href=\"#VkPhysicalDevicePerformanceQueryFeaturesKHR\">VkPhysicalDevicePerformanceQueryFeaturesKHR</a>, <a href=\"#VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT\">VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT</a>, <a href=\"#VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR\">VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR</a>, <a href=\"#VkPhysicalDeviceProtectedMemoryFeatures\">VkPhysicalDeviceProtectedMemoryFeatures</a>, <a href=\"#VkPhysicalDeviceRayTracingFeaturesKHR\">VkPhysicalDeviceRayTracingFeaturesKHR</a>, <a href=\"#VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV\">VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV</a>, <a href=\"#VkPhysicalDeviceSamplerYcbcrConversionFeatures\">VkPhysicalDeviceSamplerYcbcrConversionFeatures</a>, <a href=\"#VkPhysicalDeviceScalarBlockLayoutFeatures\">VkPhysicalDeviceScalarBlockLayoutFeatures</a>, <a href=\"#VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures\">VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures</a>, <a href=\"#VkPhysicalDeviceShaderAtomicInt64Features\">VkPhysicalDeviceShaderAtomicInt64Features</a>, <a href=\"#VkPhysicalDeviceShaderClockFeaturesKHR\">VkPhysicalDeviceShaderClockFeaturesKHR</a>, <a href=\"#VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT\">VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT</a>, <a href=\"#VkPhysicalDeviceShaderDrawParametersFeatures\">VkPhysicalDeviceShaderDrawParametersFeatures</a>, <a href=\"#VkPhysicalDeviceShaderFloat16Int8Features\">VkPhysicalDeviceShaderFloat16Int8Features</a>, <a href=\"#VkPhysicalDeviceShaderImageFootprintFeaturesNV\">VkPhysicalDeviceShaderImageFootprintFeaturesNV</a>, <a href=\"#VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL\">VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL</a>, <a href=\"#VkPhysicalDeviceShaderSMBuiltinsFeaturesNV\">VkPhysicalDeviceShaderSMBuiltinsFeaturesNV</a>, <a href=\"#VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures\">VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures</a>, <a href=\"#VkPhysicalDeviceShadingRateImageFeaturesNV\">VkPhysicalDeviceShadingRateImageFeaturesNV</a>, <a href=\"#VkPhysicalDeviceSubgroupSizeControlFeaturesEXT\">VkPhysicalDeviceSubgroupSizeControlFeaturesEXT</a>, <a href=\"#VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT\">VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT</a>, <a href=\"#VkPhysicalDeviceTextureCompressionASTCHDRFeaturesEXT\">VkPhysicalDeviceTextureCompressionASTCHDRFeaturesEXT</a>, <a href=\"#VkPhysicalDeviceTimelineSemaphoreFeatures\">VkPhysicalDeviceTimelineSemaphoreFeatures</a>, <a href=\"#VkPhysicalDeviceTransformFeedbackFeaturesEXT\">VkPhysicalDeviceTransformFeedbackFeaturesEXT</a>, <a href=\"#VkPhysicalDeviceUniformBufferStandardLayoutFeatures\">VkPhysicalDeviceUniformBufferStandardLayoutFeatures</a>, <a href=\"#VkPhysicalDeviceVariablePointersFeatures\">VkPhysicalDeviceVariablePointersFeatures</a>, <a href=\"#VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT\">VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT</a>, <a href=\"#VkPhysicalDeviceVulkan11Features\">VkPhysicalDeviceVulkan11Features</a>, <a href=\"#VkPhysicalDeviceVulkan12Features\">VkPhysicalDeviceVulkan12Features</a>, <a href=\"#VkPhysicalDeviceVulkanMemoryModelFeatures\">VkPhysicalDeviceVulkanMemoryModelFeatures</a>, or <a href=\"#VkPhysicalDeviceYcbcrImageArraysFeaturesEXT\">VkPhysicalDeviceYcbcrImageArraysFeaturesEXT</a>"
         },
         {
           "vuid": "VUID-VkDeviceCreateInfo-sType-unique",
@@ -586,7 +550,7 @@
         },
         {
           "vuid": "VUID-VkDeviceGroupDeviceCreateInfo-physicalDeviceCount-00377",
-          "text": " If <code>physicalDeviceCount</code> is not <code>0</code>, the <code>physicalDevice</code> parameter of <a href=\"#vkCreateDevice\">vkCreateDevice</a> <strong class=\"purple\">must</strong> be an element of <code>pPhysicalDevices</code>."
+          "text": " If <code>physicalDeviceCount</code> is not <code>0</code>, the <code>physicalDevice</code> parameter of <a href=\"#vkCreateDevice\">vkCreateDevice</a> <strong class=\"purple\">must</strong> be an element of <code>pPhysicalDevices</code>"
         },
         {
           "vuid": "VUID-VkDeviceGroupDeviceCreateInfo-sType-sType",
@@ -610,6 +574,18 @@
         }
       ]
     },
+    "VkDeviceDiagnosticsConfigCreateInfoNV": {
+      "(VK_NV_device_diagnostics_config)": [
+        {
+          "vuid": "VUID-VkDeviceDiagnosticsConfigCreateInfoNV-sType-sType",
+          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV</code>"
+        },
+        {
+          "vuid": "VUID-VkDeviceDiagnosticsConfigCreateInfoNV-flags-parameter",
+          "text": " <code>flags</code> <strong class=\"purple\">must</strong> be a valid combination of <a href=\"#VkDeviceDiagnosticsConfigFlagBitsNV\">VkDeviceDiagnosticsConfigFlagBitsNV</a> values"
+        }
+      ]
+    },
     "vkDestroyDevice": {
       "core": [
         {
@@ -676,7 +652,7 @@
       "(VK_VERSION_1_1)": [
         {
           "vuid": "VUID-VkDeviceQueueCreateInfo-flags-02861",
-          "text": " If the <a href=\"#features-protectedMemory\">protected memory</a> feature is not enabled, the <code>VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT</code> bit of <code>flags</code> <strong class=\"purple\">must</strong> not be set."
+          "text": " If the <a href=\"#features-protectedMemory\">protected memory</a> feature is not enabled, the <code>VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT</code> bit of <code>flags</code> <strong class=\"purple\">must</strong> not be set"
         }
       ]
     },
@@ -696,11 +672,11 @@
       "core": [
         {
           "vuid": "VUID-vkGetDeviceQueue-queueFamilyIndex-00384",
-          "text": " <code>queueFamilyIndex</code> <strong class=\"purple\">must</strong> be one of the queue family indices specified when <code>device</code> was created, via the <code>VkDeviceQueueCreateInfo</code> structure"
+          "text": " <code>queueFamilyIndex</code> <strong class=\"purple\">must</strong> be one of the queue family indices specified when <code>device</code> was created, via the <a href=\"#VkDeviceQueueCreateInfo\">VkDeviceQueueCreateInfo</a> structure"
         },
         {
           "vuid": "VUID-vkGetDeviceQueue-queueIndex-00385",
-          "text": " <code>queueIndex</code> <strong class=\"purple\">must</strong> be less than the number of queues created for the specified queue family index when <code>device</code> was created, via the <code>queueCount</code> member of the <code>VkDeviceQueueCreateInfo</code> structure"
+          "text": " <code>queueIndex</code> <strong class=\"purple\">must</strong> be less than the number of queues created for the specified queue family index when <code>device</code> was created, via the <code>queueCount</code> member of the <a href=\"#VkDeviceQueueCreateInfo\">VkDeviceQueueCreateInfo</a> structure"
         },
         {
           "vuid": "VUID-vkGetDeviceQueue-flags-01841",
@@ -736,11 +712,11 @@
       "(VK_VERSION_1_1)": [
         {
           "vuid": "VUID-VkDeviceQueueInfo2-queueFamilyIndex-01842",
-          "text": " <code>queueFamilyIndex</code> <strong class=\"purple\">must</strong> be one of the queue family indices specified when <code>device</code> was created, via the <code>VkDeviceQueueCreateInfo</code> structure"
+          "text": " <code>queueFamilyIndex</code> <strong class=\"purple\">must</strong> be one of the queue family indices specified when <code>device</code> was created, via the <a href=\"#VkDeviceQueueCreateInfo\">VkDeviceQueueCreateInfo</a> structure"
         },
         {
           "vuid": "VUID-VkDeviceQueueInfo2-queueIndex-01843",
-          "text": " <code>queueIndex</code> <strong class=\"purple\">must</strong> be less than the number of queues created for the specified queue family index and <a href=\"#VkDeviceQueueCreateFlags\">VkDeviceQueueCreateFlags</a> member <code>flags</code> equal to this <code>flags</code> value when <code>device</code> was created, via the <code>queueCount</code> member of the <code>VkDeviceQueueCreateInfo</code> structure"
+          "text": " <code>queueIndex</code> <strong class=\"purple\">must</strong> be less than the number of queues created for the specified queue family index and <a href=\"#VkDeviceQueueCreateFlags\">VkDeviceQueueCreateFlags</a> member <code>flags</code> equal to this <code>flags</code> value when <code>device</code> was created, via the <code>queueCount</code> member of the <a href=\"#VkDeviceQueueCreateInfo\">VkDeviceQueueCreateInfo</a> structure"
         },
         {
           "vuid": "VUID-VkDeviceQueueInfo2-sType-sType",
@@ -760,7 +736,7 @@
       "core": [
         {
           "vuid": "VUID-vkCreateCommandPool-queueFamilyIndex-01937",
-          "text": " <code>pCreateInfo-&gt;queueFamilyIndex</code> <strong class=\"purple\">must</strong> be the index of a queue family available in the logical device <code>device</code>."
+          "text": " <code>pCreateInfo-&gt;queueFamilyIndex</code> <strong class=\"purple\">must</strong> be the index of a queue family available in the logical device <code>device</code>"
         },
         {
           "vuid": "VUID-vkCreateCommandPool-device-parameter",
@@ -784,7 +760,7 @@
       "(VK_VERSION_1_1)": [
         {
           "vuid": "VUID-VkCommandPoolCreateInfo-flags-02860",
-          "text": " If the protected memory feature is not enabled, the <code>VK_COMMAND_POOL_CREATE_PROTECTED_BIT</code> bit of <code>flags</code> <strong class=\"purple\">must</strong> not be set."
+          "text": " If the protected memory feature is not enabled, the <code>VK_COMMAND_POOL_CREATE_PROTECTED_BIT</code> bit of <code>flags</code> <strong class=\"purple\">must</strong> not be set"
         }
       ],
       "core": [
@@ -850,7 +826,7 @@
       "core": [
         {
           "vuid": "VUID-vkDestroyCommandPool-commandPool-00041",
-          "text": " All <code>VkCommandBuffer</code> objects allocated from <code>commandPool</code> <strong class=\"purple\">must</strong> not be in the <a href=\"#commandbuffers-lifecycle\">pending state</a>."
+          "text": " All <code>VkCommandBuffer</code> objects allocated from <code>commandPool</code> <strong class=\"purple\">must</strong> not be in the <a href=\"#commandbuffers-lifecycle\">pending state</a>"
         },
         {
           "vuid": "VUID-vkDestroyCommandPool-commandPool-00042",
@@ -1094,7 +1070,7 @@
       "(VK_QCOM_render_pass_transform)": [
         {
           "vuid": "VUID-VkCommandBufferInheritanceRenderPassTransformInfoQCOM-transform-02864",
-          "text": " <code>transform</code> <strong class=\"purple\">must</strong> be VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR, VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR, VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR, or VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR."
+          "text": " <code>transform</code> <strong class=\"purple\">must</strong> be <code>VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR</code>, <code>VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR</code>, <code>VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR</code>, or <code>VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR</code>"
         },
         {
           "vuid": "VUID-VkCommandBufferInheritanceRenderPassTransformInfoQCOM-sType-sType",
@@ -1106,7 +1082,7 @@
       "core": [
         {
           "vuid": "VUID-vkEndCommandBuffer-commandBuffer-00059",
-          "text": " <code>commandBuffer</code> <strong class=\"purple\">must</strong> be in the <a href=\"#commandbuffers-lifecycle\">recording state</a>."
+          "text": " <code>commandBuffer</code> <strong class=\"purple\">must</strong> be in the <a href=\"#commandbuffers-lifecycle\">recording state</a>"
         },
         {
           "vuid": "VUID-vkEndCommandBuffer-commandBuffer-00060",
@@ -1130,13 +1106,13 @@
       "(VK_EXT_debug_utils)": [
         {
           "vuid": "VUID-vkEndCommandBuffer-commandBuffer-01815",
-          "text": " If <code>commandBuffer</code> is a secondary command buffer, there <strong class=\"purple\">must</strong> not be an outstanding <a href=\"#vkCmdBeginDebugUtilsLabelEXT\">vkCmdBeginDebugUtilsLabelEXT</a> command recorded to <code>commandBuffer</code> that has not previously been ended by a call to <a href=\"#vkCmdEndDebugUtilsLabelEXT\">vkCmdEndDebugUtilsLabelEXT</a>."
+          "text": " If <code>commandBuffer</code> is a secondary command buffer, there <strong class=\"purple\">must</strong> not be an outstanding <a href=\"#vkCmdBeginDebugUtilsLabelEXT\">vkCmdBeginDebugUtilsLabelEXT</a> command recorded to <code>commandBuffer</code> that has not previously been ended by a call to <a href=\"#vkCmdEndDebugUtilsLabelEXT\">vkCmdEndDebugUtilsLabelEXT</a>"
         }
       ],
       "(VK_EXT_debug_marker)": [
         {
           "vuid": "VUID-vkEndCommandBuffer-commandBuffer-00062",
-          "text": " If <code>commandBuffer</code> is a secondary command buffer, there <strong class=\"purple\">must</strong> not be an outstanding <a href=\"#vkCmdDebugMarkerBeginEXT\">vkCmdDebugMarkerBeginEXT</a> command recorded to <code>commandBuffer</code> that has not previously been ended by a call to <a href=\"#vkCmdDebugMarkerEndEXT\">vkCmdDebugMarkerEndEXT</a>."
+          "text": " If <code>commandBuffer</code> is a secondary command buffer, there <strong class=\"purple\">must</strong> not be an outstanding <a href=\"#vkCmdDebugMarkerBeginEXT\">vkCmdDebugMarkerBeginEXT</a> command recorded to <code>commandBuffer</code> that has not previously been ended by a call to <a href=\"#vkCmdDebugMarkerEndEXT\">vkCmdDebugMarkerEndEXT</a>"
         }
       ]
     },
@@ -1304,11 +1280,11 @@
         },
         {
           "vuid": "VUID-VkSubmitInfo-pWaitSemaphores-03243",
-          "text": " For each element of <code>pWaitSemaphores</code> created with a <a href=\"#VkSemaphoreType\">VkSemaphoreType</a> of <code>VK_SEMAPHORE_TYPE_TIMELINE</code> the corresponding element of <a href=\"#VkTimelineSemaphoreSubmitInfo\">VkTimelineSemaphoreSubmitInfo</a>::pWaitSemaphoreValues <strong class=\"purple\">must</strong> have a value which does not differ from the current value of the semaphore or the value of any outstanding semaphore wait or signal operation on that semaphore by more than <a href=\"#limits-maxTimelineSemaphoreValueDifference\"><code>maxTimelineSemaphoreValueDifference</code></a>."
+          "text": " For each element of <code>pWaitSemaphores</code> created with a <a href=\"#VkSemaphoreType\">VkSemaphoreType</a> of <code>VK_SEMAPHORE_TYPE_TIMELINE</code> the corresponding element of <a href=\"#VkTimelineSemaphoreSubmitInfo\">VkTimelineSemaphoreSubmitInfo</a>::pWaitSemaphoreValues <strong class=\"purple\">must</strong> have a value which does not differ from the current value of the semaphore or the value of any outstanding semaphore wait or signal operation on that semaphore by more than <a href=\"#limits-maxTimelineSemaphoreValueDifference\"><code>maxTimelineSemaphoreValueDifference</code></a>"
         },
         {
           "vuid": "VUID-VkSubmitInfo-pSignalSemaphores-03244",
-          "text": " For each element of <code>pSignalSemaphores</code> created with a <a href=\"#VkSemaphoreType\">VkSemaphoreType</a> of <code>VK_SEMAPHORE_TYPE_TIMELINE</code> the corresponding element of <a href=\"#VkTimelineSemaphoreSubmitInfo\">VkTimelineSemaphoreSubmitInfo</a>::pSignalSemaphoreValues <strong class=\"purple\">must</strong> have a value which does not differ from the current value of the semaphore or the value of any outstanding semaphore wait or signal operation on that semaphore by more than <a href=\"#limits-maxTimelineSemaphoreValueDifference\"><code>maxTimelineSemaphoreValueDifference</code></a>."
+          "text": " For each element of <code>pSignalSemaphores</code> created with a <a href=\"#VkSemaphoreType\">VkSemaphoreType</a> of <code>VK_SEMAPHORE_TYPE_TIMELINE</code> the corresponding element of <a href=\"#VkTimelineSemaphoreSubmitInfo\">VkTimelineSemaphoreSubmitInfo</a>::pSignalSemaphoreValues <strong class=\"purple\">must</strong> have a value which does not differ from the current value of the semaphore or the value of any outstanding semaphore wait or signal operation on that semaphore by more than <a href=\"#limits-maxTimelineSemaphoreValueDifference\"><code>maxTimelineSemaphoreValueDifference</code></a>"
         }
       ],
       "(VK_NV_mesh_shader)": [
@@ -1342,11 +1318,11 @@
       "(VK_KHR_external_semaphore_win32)": [
         {
           "vuid": "VUID-VkD3D12FenceSubmitInfoKHR-waitSemaphoreValuesCount-00079",
-          "text": " <code>waitSemaphoreValuesCount</code> <strong class=\"purple\">must</strong> be the same value as <code>VkSubmitInfo</code>::<code>waitSemaphoreCount</code>, where <code>VkSubmitInfo</code> is in the <code>pNext</code> chain of this <code>VkD3D12FenceSubmitInfoKHR</code> structure."
+          "text": " <code>waitSemaphoreValuesCount</code> <strong class=\"purple\">must</strong> be the same value as <code>VkSubmitInfo</code>::<code>waitSemaphoreCount</code>, where <code>VkSubmitInfo</code> is in the <code>pNext</code> chain of this <code>VkD3D12FenceSubmitInfoKHR</code> structure"
         },
         {
           "vuid": "VUID-VkD3D12FenceSubmitInfoKHR-signalSemaphoreValuesCount-00080",
-          "text": " <code>signalSemaphoreValuesCount</code> <strong class=\"purple\">must</strong> be the same value as <code>VkSubmitInfo</code>::<code>signalSemaphoreCount</code>, where <code>VkSubmitInfo</code> is in the <code>pNext</code> chain of this <code>VkD3D12FenceSubmitInfoKHR</code> structure."
+          "text": " <code>signalSemaphoreValuesCount</code> <strong class=\"purple\">must</strong> be the same value as <code>VkSubmitInfo</code>::<code>signalSemaphoreCount</code>, where <code>VkSubmitInfo</code> is in the <code>pNext</code> chain of this <code>VkD3D12FenceSubmitInfoKHR</code> structure"
         },
         {
           "vuid": "VUID-VkD3D12FenceSubmitInfoKHR-sType-sType",
@@ -1366,7 +1342,7 @@
       "(VK_KHR_win32_keyed_mutex)": [
         {
           "vuid": "VUID-VkWin32KeyedMutexAcquireReleaseInfoKHR-pAcquireSyncs-00081",
-          "text": " Each member of <code>pAcquireSyncs</code> and <code>pReleaseSyncs</code> <strong class=\"purple\">must</strong> be a device memory object imported by setting <a href=\"#VkImportMemoryWin32HandleInfoKHR\">VkImportMemoryWin32HandleInfoKHR</a>::<code>handleType</code> to <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT</code> or <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT</code>."
+          "text": " Each member of <code>pAcquireSyncs</code> and <code>pReleaseSyncs</code> <strong class=\"purple\">must</strong> be a device memory object imported by setting <a href=\"#VkImportMemoryWin32HandleInfoKHR\">VkImportMemoryWin32HandleInfoKHR</a>::<code>handleType</code> to <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT</code> or <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT</code>"
         },
         {
           "vuid": "VUID-VkWin32KeyedMutexAcquireReleaseInfoKHR-sType-sType",
@@ -1434,19 +1410,19 @@
       "(VK_VERSION_1_1)": [
         {
           "vuid": "VUID-VkProtectedSubmitInfo-protectedSubmit-01816",
-          "text": " If the protected memory feature is not enabled, <code>protectedSubmit</code> <strong class=\"purple\">must</strong> not be <code>VK_TRUE</code>."
+          "text": " If the protected memory feature is not enabled, <code>protectedSubmit</code> <strong class=\"purple\">must</strong> not be <code>VK_TRUE</code>"
         },
         {
           "vuid": "VUID-VkProtectedSubmitInfo-protectedSubmit-01817",
-          "text": " If <code>protectedSubmit</code> is <code>VK_TRUE</code>, then each element of the <code>pCommandBuffers</code> array <strong class=\"purple\">must</strong> be a protected command buffer."
+          "text": " If <code>protectedSubmit</code> is <code>VK_TRUE</code>, then each element of the <code>pCommandBuffers</code> array <strong class=\"purple\">must</strong> be a protected command buffer"
         },
         {
           "vuid": "VUID-VkProtectedSubmitInfo-protectedSubmit-01818",
-          "text": " If <code>protectedSubmit</code> is <code>VK_FALSE</code>, then each element of the <code>pCommandBuffers</code> array <strong class=\"purple\">must</strong> be an unprotected command buffer."
+          "text": " If <code>protectedSubmit</code> is <code>VK_FALSE</code>, then each element of the <code>pCommandBuffers</code> array <strong class=\"purple\">must</strong> be an unprotected command buffer"
         },
         {
           "vuid": "VUID-VkProtectedSubmitInfo-pNext-01819",
-          "text": " If the <code>VkSubmitInfo</code>::<code>pNext</code> chain does not include a <code>VkProtectedSubmitInfo</code> structure, then each element of the command buffer of the <code>pCommandBuffers</code> array <strong class=\"purple\">must</strong> be an unprotected command buffer."
+          "text": " If the <code>VkSubmitInfo</code>::<code>pNext</code> chain does not include a <code>VkProtectedSubmitInfo</code> structure, then each element of the command buffer of the <code>pCommandBuffers</code> array <strong class=\"purple\">must</strong> be an unprotected command buffer"
         },
         {
           "vuid": "VUID-VkProtectedSubmitInfo-sType-sType",
@@ -1608,7 +1584,7 @@
       "(VK_QCOM_render_pass_transform)": [
         {
           "vuid": "VUID-vkCmdExecuteCommands-pNext-02865",
-          "text": " If <code>vkCmdExecuteCommands</code> is being called within a render pass instance that included <a href=\"#VkRenderPassTransformBeginInfoQCOM\">VkRenderPassTransformBeginInfoQCOM</a> in the <code>pNext</code> chain of <a href=\"#VkRenderPassBeginInfo\">VkRenderPassBeginInfo</a>, then each element of <code>pCommandBuffers</code> <strong class=\"purple\">must</strong> have been recorded with <a href=\"#VkCommandBufferInheritanceRenderPassTransformInfoQCOM\">VkCommandBufferInheritanceRenderPassTransformInfoQCOM</a> in the <code>pNext</code> chain of VkCommandBufferBeginInfo"
+          "text": " If <code>vkCmdExecuteCommands</code> is being called within a render pass instance that included <a href=\"#VkRenderPassTransformBeginInfoQCOM\">VkRenderPassTransformBeginInfoQCOM</a> in the <code>pNext</code> chain of <a href=\"#VkRenderPassBeginInfo\">VkRenderPassBeginInfo</a>, then each element of <code>pCommandBuffers</code> <strong class=\"purple\">must</strong> have been recorded with <a href=\"#VkCommandBufferInheritanceRenderPassTransformInfoQCOM\">VkCommandBufferInheritanceRenderPassTransformInfoQCOM</a> in the <code>pNext</code> chain of <a href=\"#VkCommandBufferBeginInfo\">VkCommandBufferBeginInfo</a>"
         },
         {
           "vuid": "VUID-vkCmdExecuteCommands-pNext-02866",
@@ -1664,11 +1640,11 @@
         },
         {
           "vuid": "VUID-vkCmdSetDeviceMask-deviceMask-00110",
-          "text": " <code>deviceMask</code> <strong class=\"purple\">must</strong> not include any set bits that were not in the <a href=\"#VkDeviceGroupCommandBufferBeginInfo\">VkDeviceGroupCommandBufferBeginInfo</a>::<code>deviceMask</code> value when the command buffer began recording."
+          "text": " <code>deviceMask</code> <strong class=\"purple\">must</strong> not include any set bits that were not in the <a href=\"#VkDeviceGroupCommandBufferBeginInfo\">VkDeviceGroupCommandBufferBeginInfo</a>::<code>deviceMask</code> value when the command buffer began recording"
         },
         {
           "vuid": "VUID-vkCmdSetDeviceMask-deviceMask-00111",
-          "text": " If <code>vkCmdSetDeviceMask</code> is called inside a render pass instance, <code>deviceMask</code> <strong class=\"purple\">must</strong> not include any set bits that were not in the <a href=\"#VkDeviceGroupRenderPassBeginInfo\">VkDeviceGroupRenderPassBeginInfo</a>::<code>deviceMask</code> value when the render pass instance began recording."
+          "text": " If <code>vkCmdSetDeviceMask</code> is called inside a render pass instance, <code>deviceMask</code> <strong class=\"purple\">must</strong> not include any set bits that were not in the <a href=\"#VkDeviceGroupRenderPassBeginInfo\">VkDeviceGroupRenderPassBeginInfo</a>::<code>deviceMask</code> value when the render pass instance began recording"
         },
         {
           "vuid": "VUID-vkCmdSetDeviceMask-commandBuffer-parameter",
@@ -1728,7 +1704,7 @@
       "(VK_VERSION_1_1,VK_KHR_external_fence)": [
         {
           "vuid": "VUID-VkExportFenceCreateInfo-handleTypes-01446",
-          "text": " The bits in <code>handleTypes</code> must be supported and compatible, as reported by <a href=\"#VkExternalFenceProperties\">VkExternalFenceProperties</a>."
+          "text": " The bits in <code>handleTypes</code> must be supported and compatible, as reported by <a href=\"#VkExternalFenceProperties\">VkExternalFenceProperties</a>"
         },
         {
           "vuid": "VUID-VkExportFenceCreateInfo-sType-sType",
@@ -1744,7 +1720,7 @@
       "(VK_KHR_external_fence_win32)": [
         {
           "vuid": "VUID-VkExportFenceWin32HandleInfoKHR-handleTypes-01447",
-          "text": " If <a href=\"#VkExportFenceCreateInfo\">VkExportFenceCreateInfo</a>::<code>handleTypes</code> does not include <code>VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT</code>, a <code>VkExportFenceWin32HandleInfoKHR</code> structure <strong class=\"purple\">must</strong> not be included in the <code>pNext</code> chain of <a href=\"#VkFenceCreateInfo\">VkFenceCreateInfo</a>."
+          "text": " If <a href=\"#VkExportFenceCreateInfo\">VkExportFenceCreateInfo</a>::<code>handleTypes</code> does not include <code>VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT</code>, a <code>VkExportFenceWin32HandleInfoKHR</code> structure <strong class=\"purple\">must</strong> not be included in the <code>pNext</code> chain of <a href=\"#VkFenceCreateInfo\">VkFenceCreateInfo</a>"
         },
         {
           "vuid": "VUID-VkExportFenceWin32HandleInfoKHR-sType-sType",
@@ -1776,23 +1752,23 @@
       "(VK_KHR_external_fence_win32)": [
         {
           "vuid": "VUID-VkFenceGetWin32HandleInfoKHR-handleType-01448",
-          "text": " <code>handleType</code> <strong class=\"purple\">must</strong> have been included in <a href=\"#VkExportFenceCreateInfo\">VkExportFenceCreateInfo</a>::<code>handleTypes</code> when the <code>fence</code>&#8217;s current payload was created."
+          "text": " <code>handleType</code> <strong class=\"purple\">must</strong> have been included in <a href=\"#VkExportFenceCreateInfo\">VkExportFenceCreateInfo</a>::<code>handleTypes</code> when the <code>fence</code>&#8217;s current payload was created"
         },
         {
           "vuid": "VUID-VkFenceGetWin32HandleInfoKHR-handleType-01449",
-          "text": " If <code>handleType</code> is defined as an NT handle, <a href=\"#vkGetFenceWin32HandleKHR\">vkGetFenceWin32HandleKHR</a> <strong class=\"purple\">must</strong> be called no more than once for each valid unique combination of <code>fence</code> and <code>handleType</code>."
+          "text": " If <code>handleType</code> is defined as an NT handle, <a href=\"#vkGetFenceWin32HandleKHR\">vkGetFenceWin32HandleKHR</a> <strong class=\"purple\">must</strong> be called no more than once for each valid unique combination of <code>fence</code> and <code>handleType</code>"
         },
         {
           "vuid": "VUID-VkFenceGetWin32HandleInfoKHR-fence-01450",
-          "text": " <code>fence</code> <strong class=\"purple\">must</strong> not currently have its payload replaced by an imported payload as described below in <a href=\"#synchronization-fences-importing\">Importing Fence Payloads</a> unless that imported payload&#8217;s handle type was included in <a href=\"#VkExternalFenceProperties\">VkExternalFenceProperties</a>::<code>exportFromImportedHandleTypes</code> for <code>handleType</code>."
+          "text": " <code>fence</code> <strong class=\"purple\">must</strong> not currently have its payload replaced by an imported payload as described below in <a href=\"#synchronization-fences-importing\">Importing Fence Payloads</a> unless that imported payload&#8217;s handle type was included in <a href=\"#VkExternalFenceProperties\">VkExternalFenceProperties</a>::<code>exportFromImportedHandleTypes</code> for <code>handleType</code>"
         },
         {
           "vuid": "VUID-VkFenceGetWin32HandleInfoKHR-handleType-01451",
-          "text": " If <code>handleType</code> refers to a handle type with copy payload transference semantics, <code>fence</code> <strong class=\"purple\">must</strong> be signaled, or have an associated <a href=\"#synchronization-fences-signaling\">fence signal operation</a> pending execution."
+          "text": " If <code>handleType</code> refers to a handle type with copy payload transference semantics, <code>fence</code> <strong class=\"purple\">must</strong> be signaled, or have an associated <a href=\"#synchronization-fences-signaling\">fence signal operation</a> pending execution"
         },
         {
           "vuid": "VUID-VkFenceGetWin32HandleInfoKHR-handleType-01452",
-          "text": " <code>handleType</code> <strong class=\"purple\">must</strong> be defined as an NT handle or a global share handle."
+          "text": " <code>handleType</code> <strong class=\"purple\">must</strong> be defined as an NT handle or a global share handle"
         },
         {
           "vuid": "VUID-VkFenceGetWin32HandleInfoKHR-sType-sType",
@@ -1832,19 +1808,19 @@
       "(VK_KHR_external_fence_fd)": [
         {
           "vuid": "VUID-VkFenceGetFdInfoKHR-handleType-01453",
-          "text": " <code>handleType</code> <strong class=\"purple\">must</strong> have been included in <a href=\"#VkExportFenceCreateInfo\">VkExportFenceCreateInfo</a>::<code>handleTypes</code> when <code>fence</code>&#8217;s current payload was created."
+          "text": " <code>handleType</code> <strong class=\"purple\">must</strong> have been included in <a href=\"#VkExportFenceCreateInfo\">VkExportFenceCreateInfo</a>::<code>handleTypes</code> when <code>fence</code>&#8217;s current payload was created"
         },
         {
           "vuid": "VUID-VkFenceGetFdInfoKHR-handleType-01454",
-          "text": " If <code>handleType</code> refers to a handle type with copy payload transference semantics, <code>fence</code> <strong class=\"purple\">must</strong> be signaled, or have an associated <a href=\"#synchronization-fences-signaling\">fence signal operation</a> pending execution."
+          "text": " If <code>handleType</code> refers to a handle type with copy payload transference semantics, <code>fence</code> <strong class=\"purple\">must</strong> be signaled, or have an associated <a href=\"#synchronization-fences-signaling\">fence signal operation</a> pending execution"
         },
         {
           "vuid": "VUID-VkFenceGetFdInfoKHR-fence-01455",
-          "text": " <code>fence</code> <strong class=\"purple\">must</strong> not currently have its payload replaced by an imported payload as described below in <a href=\"#synchronization-fences-importing\">Importing Fence Payloads</a> unless that imported payload&#8217;s handle type was included in <a href=\"#VkExternalFenceProperties\">VkExternalFenceProperties</a>::<code>exportFromImportedHandleTypes</code> for <code>handleType</code>."
+          "text": " <code>fence</code> <strong class=\"purple\">must</strong> not currently have its payload replaced by an imported payload as described below in <a href=\"#synchronization-fences-importing\">Importing Fence Payloads</a> unless that imported payload&#8217;s handle type was included in <a href=\"#VkExternalFenceProperties\">VkExternalFenceProperties</a>::<code>exportFromImportedHandleTypes</code> for <code>handleType</code>"
         },
         {
           "vuid": "VUID-VkFenceGetFdInfoKHR-handleType-01456",
-          "text": " <code>handleType</code> <strong class=\"purple\">must</strong> be defined as a POSIX file descriptor handle."
+          "text": " <code>handleType</code> <strong class=\"purple\">must</strong> be defined as a POSIX file descriptor handle"
         },
         {
           "vuid": "VUID-VkFenceGetFdInfoKHR-sType-sType",
@@ -2052,31 +2028,31 @@
       "(VK_KHR_external_fence_win32)": [
         {
           "vuid": "VUID-VkImportFenceWin32HandleInfoKHR-handleType-01457",
-          "text": " <code>handleType</code> <strong class=\"purple\">must</strong> be a value included in the <a href=\"#synchronization-fence-handletypes-win32\">Handle Types Supported by VkImportFenceWin32HandleInfoKHR</a> table."
+          "text": " <code>handleType</code> <strong class=\"purple\">must</strong> be a value included in the <a href=\"#synchronization-fence-handletypes-win32\">Handle Types Supported by <code>VkImportFenceWin32HandleInfoKHR</code></a> table"
         },
         {
           "vuid": "VUID-VkImportFenceWin32HandleInfoKHR-handleType-01459",
-          "text": " If <code>handleType</code> is not <code>VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT</code>, <code>name</code> <strong class=\"purple\">must</strong> be <code>NULL</code>."
+          "text": " If <code>handleType</code> is not <code>VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT</code>, <code>name</code> <strong class=\"purple\">must</strong> be <code>NULL</code>"
         },
         {
           "vuid": "VUID-VkImportFenceWin32HandleInfoKHR-handleType-01460",
-          "text": " If <code>handleType</code> is not <code>0</code> and <code>handle</code> is <code>NULL</code>, <code>name</code> <strong class=\"purple\">must</strong> name a valid synchronization primitive of the type specified by <code>handleType</code>."
+          "text": " If <code>handleType</code> is not <code>0</code> and <code>handle</code> is <code>NULL</code>, <code>name</code> <strong class=\"purple\">must</strong> name a valid synchronization primitive of the type specified by <code>handleType</code>"
         },
         {
           "vuid": "VUID-VkImportFenceWin32HandleInfoKHR-handleType-01461",
-          "text": " If <code>handleType</code> is not <code>0</code> and <code>name</code> is <code>NULL</code>, <code>handle</code> <strong class=\"purple\">must</strong> be a valid handle of the type specified by <code>handleType</code>."
+          "text": " If <code>handleType</code> is not <code>0</code> and <code>name</code> is <code>NULL</code>, <code>handle</code> <strong class=\"purple\">must</strong> be a valid handle of the type specified by <code>handleType</code>"
         },
         {
           "vuid": "VUID-VkImportFenceWin32HandleInfoKHR-handle-01462",
-          "text": " If <code>handle</code> is not <code>NULL</code>, <code>name</code> must be <code>NULL</code>."
+          "text": " If <code>handle</code> is not <code>NULL</code>, <code>name</code> must be <code>NULL</code>"
         },
         {
           "vuid": "VUID-VkImportFenceWin32HandleInfoKHR-handle-01539",
-          "text": " If <code>handle</code> is not <code>NULL</code>, it <strong class=\"purple\">must</strong> obey any requirements listed for <code>handleType</code> in <a href=\"#external-fence-handle-types-compatibility\">external fence handle types compatibility</a>."
+          "text": " If <code>handle</code> is not <code>NULL</code>, it <strong class=\"purple\">must</strong> obey any requirements listed for <code>handleType</code> in <a href=\"#external-fence-handle-types-compatibility\">external fence handle types compatibility</a>"
         },
         {
           "vuid": "VUID-VkImportFenceWin32HandleInfoKHR-name-01540",
-          "text": " If <code>name</code> is not <code>NULL</code>, it <strong class=\"purple\">must</strong> obey any requirements listed for <code>handleType</code> in <a href=\"#external-fence-handle-types-compatibility\">external fence handle types compatibility</a>."
+          "text": " If <code>name</code> is not <code>NULL</code>, it <strong class=\"purple\">must</strong> obey any requirements listed for <code>handleType</code> in <a href=\"#external-fence-handle-types-compatibility\">external fence handle types compatibility</a>"
         },
         {
           "vuid": "VUID-VkImportFenceWin32HandleInfoKHR-sType-sType",
@@ -2120,11 +2096,11 @@
       "(VK_KHR_external_fence_fd)": [
         {
           "vuid": "VUID-VkImportFenceFdInfoKHR-handleType-01464",
-          "text": " <code>handleType</code> <strong class=\"purple\">must</strong> be a value included in the <a href=\"#synchronization-fence-handletypes-fd\">Handle Types Supported by VkImportFenceFdInfoKHR</a> table."
+          "text": " <code>handleType</code> <strong class=\"purple\">must</strong> be a value included in the <a href=\"#synchronization-fence-handletypes-fd\">Handle Types Supported by <code>VkImportFenceFdInfoKHR</code></a> table"
         },
         {
           "vuid": "VUID-VkImportFenceFdInfoKHR-fd-01541",
-          "text": " <code>fd</code> <strong class=\"purple\">must</strong> obey any requirements listed for <code>handleType</code> in <a href=\"#external-fence-handle-types-compatibility\">external fence handle types compatibility</a>."
+          "text": " <code>fd</code> <strong class=\"purple\">must</strong> obey any requirements listed for <code>handleType</code> in <a href=\"#external-fence-handle-types-compatibility\">external fence handle types compatibility</a>"
         },
         {
           "vuid": "VUID-VkImportFenceFdInfoKHR-sType-sType",
@@ -2204,7 +2180,7 @@
         },
         {
           "vuid": "VUID-VkSemaphoreTypeCreateInfo-semaphoreType-03279",
-          "text": " If <code>semaphoreType</code> is <code>VK_SEMAPHORE_TYPE_BINARY</code>, <code>initialValue</code> <strong class=\"purple\">must</strong> be zero."
+          "text": " If <code>semaphoreType</code> is <code>VK_SEMAPHORE_TYPE_BINARY</code>, <code>initialValue</code> <strong class=\"purple\">must</strong> be zero"
         }
       ]
     },
@@ -2212,7 +2188,7 @@
       "(VK_VERSION_1_1,VK_KHR_external_semaphore)": [
         {
           "vuid": "VUID-VkExportSemaphoreCreateInfo-handleTypes-01124",
-          "text": " The bits in <code>handleTypes</code> <strong class=\"purple\">must</strong> be supported and compatible, as reported by <a href=\"#VkExternalSemaphoreProperties\">VkExternalSemaphoreProperties</a>."
+          "text": " The bits in <code>handleTypes</code> <strong class=\"purple\">must</strong> be supported and compatible, as reported by <a href=\"#VkExternalSemaphoreProperties\">VkExternalSemaphoreProperties</a>"
         },
         {
           "vuid": "VUID-VkExportSemaphoreCreateInfo-sType-sType",
@@ -2228,7 +2204,7 @@
       "(VK_KHR_external_semaphore_win32)": [
         {
           "vuid": "VUID-VkExportSemaphoreWin32HandleInfoKHR-handleTypes-01125",
-          "text": " If <a href=\"#VkExportSemaphoreCreateInfo\">VkExportSemaphoreCreateInfo</a>::<code>handleTypes</code> does not include <code>VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT</code> or <code>VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT</code>, <code>VkExportSemaphoreWin32HandleInfoKHR</code> <strong class=\"purple\">must</strong> not be included in the <code>pNext</code> chain of <a href=\"#VkSemaphoreCreateInfo\">VkSemaphoreCreateInfo</a>."
+          "text": " If <a href=\"#VkExportSemaphoreCreateInfo\">VkExportSemaphoreCreateInfo</a>::<code>handleTypes</code> does not include <code>VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT</code> or <code>VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT</code>, <code>VkExportSemaphoreWin32HandleInfoKHR</code> <strong class=\"purple\">must</strong> not be included in the <code>pNext</code> chain of <a href=\"#VkSemaphoreCreateInfo\">VkSemaphoreCreateInfo</a>"
         },
         {
           "vuid": "VUID-VkExportSemaphoreWin32HandleInfoKHR-sType-sType",
@@ -2260,27 +2236,27 @@
       "(VK_KHR_external_semaphore_win32)": [
         {
           "vuid": "VUID-VkSemaphoreGetWin32HandleInfoKHR-handleType-01126",
-          "text": " <code>handleType</code> <strong class=\"purple\">must</strong> have been included in <a href=\"#VkExportSemaphoreCreateInfo\">VkExportSemaphoreCreateInfo</a>::<code>handleTypes</code> when the <code>semaphore</code>&#8217;s current payload was created."
+          "text": " <code>handleType</code> <strong class=\"purple\">must</strong> have been included in <a href=\"#VkExportSemaphoreCreateInfo\">VkExportSemaphoreCreateInfo</a>::<code>handleTypes</code> when the <code>semaphore</code>&#8217;s current payload was created"
         },
         {
           "vuid": "VUID-VkSemaphoreGetWin32HandleInfoKHR-handleType-01127",
-          "text": " If <code>handleType</code> is defined as an NT handle, <a href=\"#vkGetSemaphoreWin32HandleKHR\">vkGetSemaphoreWin32HandleKHR</a> <strong class=\"purple\">must</strong> be called no more than once for each valid unique combination of <code>semaphore</code> and <code>handleType</code>."
+          "text": " If <code>handleType</code> is defined as an NT handle, <a href=\"#vkGetSemaphoreWin32HandleKHR\">vkGetSemaphoreWin32HandleKHR</a> <strong class=\"purple\">must</strong> be called no more than once for each valid unique combination of <code>semaphore</code> and <code>handleType</code>"
         },
         {
           "vuid": "VUID-VkSemaphoreGetWin32HandleInfoKHR-semaphore-01128",
-          "text": " <code>semaphore</code> <strong class=\"purple\">must</strong> not currently have its payload replaced by an imported payload as described below in <a href=\"#synchronization-semaphores-importing\">Importing Semaphore Payloads</a> unless that imported payload&#8217;s handle type was included in <a href=\"#VkExternalSemaphoreProperties\">VkExternalSemaphoreProperties</a>::<code>exportFromImportedHandleTypes</code> for <code>handleType</code>."
+          "text": " <code>semaphore</code> <strong class=\"purple\">must</strong> not currently have its payload replaced by an imported payload as described below in <a href=\"#synchronization-semaphores-importing\">Importing Semaphore Payloads</a> unless that imported payload&#8217;s handle type was included in <a href=\"#VkExternalSemaphoreProperties\">VkExternalSemaphoreProperties</a>::<code>exportFromImportedHandleTypes</code> for <code>handleType</code>"
         },
         {
           "vuid": "VUID-VkSemaphoreGetWin32HandleInfoKHR-handleType-01129",
-          "text": " If <code>handleType</code> refers to a handle type with copy payload transference semantics, as defined below in <a href=\"#synchronization-semaphores-importing\">Importing Semaphore Payloads</a>, there <strong class=\"purple\">must</strong> be no queue waiting on <code>semaphore</code>."
+          "text": " If <code>handleType</code> refers to a handle type with copy payload transference semantics, as defined below in <a href=\"#synchronization-semaphores-importing\">Importing Semaphore Payloads</a>, there <strong class=\"purple\">must</strong> be no queue waiting on <code>semaphore</code>"
         },
         {
           "vuid": "VUID-VkSemaphoreGetWin32HandleInfoKHR-handleType-01130",
-          "text": " If <code>handleType</code> refers to a handle type with copy payload transference semantics, <code>semaphore</code> <strong class=\"purple\">must</strong> be signaled, or have an associated <a href=\"#synchronization-semaphores-signaling\">semaphore signal operation</a> pending execution."
+          "text": " If <code>handleType</code> refers to a handle type with copy payload transference semantics, <code>semaphore</code> <strong class=\"purple\">must</strong> be signaled, or have an associated <a href=\"#synchronization-semaphores-signaling\">semaphore signal operation</a> pending execution"
         },
         {
           "vuid": "VUID-VkSemaphoreGetWin32HandleInfoKHR-handleType-01131",
-          "text": " <code>handleType</code> <strong class=\"purple\">must</strong> be defined as an NT handle or a global share handle."
+          "text": " <code>handleType</code> <strong class=\"purple\">must</strong> be defined as an NT handle or a global share handle"
         },
         {
           "vuid": "VUID-VkSemaphoreGetWin32HandleInfoKHR-sType-sType",
@@ -2320,19 +2296,19 @@
       "(VK_KHR_external_semaphore_fd)": [
         {
           "vuid": "VUID-VkSemaphoreGetFdInfoKHR-handleType-01132",
-          "text": " <code>handleType</code> <strong class=\"purple\">must</strong> have been included in <a href=\"#VkExportSemaphoreCreateInfo\">VkExportSemaphoreCreateInfo</a>::<code>handleTypes</code> when <code>semaphore</code>&#8217;s current payload was created."
+          "text": " <code>handleType</code> <strong class=\"purple\">must</strong> have been included in <a href=\"#VkExportSemaphoreCreateInfo\">VkExportSemaphoreCreateInfo</a>::<code>handleTypes</code> when <code>semaphore</code>&#8217;s current payload was created"
         },
         {
           "vuid": "VUID-VkSemaphoreGetFdInfoKHR-semaphore-01133",
-          "text": " <code>semaphore</code> <strong class=\"purple\">must</strong> not currently have its payload replaced by an imported payload as described below in <a href=\"#synchronization-semaphores-importing\">Importing Semaphore Payloads</a> unless that imported payload&#8217;s handle type was included in <a href=\"#VkExternalSemaphoreProperties\">VkExternalSemaphoreProperties</a>::<code>exportFromImportedHandleTypes</code> for <code>handleType</code>."
+          "text": " <code>semaphore</code> <strong class=\"purple\">must</strong> not currently have its payload replaced by an imported payload as described below in <a href=\"#synchronization-semaphores-importing\">Importing Semaphore Payloads</a> unless that imported payload&#8217;s handle type was included in <a href=\"#VkExternalSemaphoreProperties\">VkExternalSemaphoreProperties</a>::<code>exportFromImportedHandleTypes</code> for <code>handleType</code>"
         },
         {
           "vuid": "VUID-VkSemaphoreGetFdInfoKHR-handleType-01134",
-          "text": " If <code>handleType</code> refers to a handle type with copy payload transference semantics, as defined below in <a href=\"#synchronization-semaphores-importing\">Importing Semaphore Payloads</a>, there <strong class=\"purple\">must</strong> be no queue waiting on <code>semaphore</code>."
+          "text": " If <code>handleType</code> refers to a handle type with copy payload transference semantics, as defined below in <a href=\"#synchronization-semaphores-importing\">Importing Semaphore Payloads</a>, there <strong class=\"purple\">must</strong> be no queue waiting on <code>semaphore</code>"
         },
         {
           "vuid": "VUID-VkSemaphoreGetFdInfoKHR-handleType-01135",
-          "text": " If <code>handleType</code> refers to a handle type with copy payload transference semantics, <code>semaphore</code> <strong class=\"purple\">must</strong> be signaled, or have an associated <a href=\"#synchronization-semaphores-signaling\">semaphore signal operation</a> pending execution."
+          "text": " If <code>handleType</code> refers to a handle type with copy payload transference semantics, <code>semaphore</code> <strong class=\"purple\">must</strong> be signaled, or have an associated <a href=\"#synchronization-semaphores-signaling\">semaphore signal operation</a> pending execution"
         },
         {
           "vuid": "VUID-VkSemaphoreGetFdInfoKHR-handleType-01136",
@@ -2358,11 +2334,11 @@
       "(VK_KHR_external_semaphore_fd)+(VK_VERSION_1_2,VK_KHR_timeline_semaphore)": [
         {
           "vuid": "VUID-VkSemaphoreGetFdInfoKHR-handleType-03253",
-          "text": " If <code>handleType</code> refers to a handle type with copy payload transference semantics, <code>semaphore</code> <strong class=\"purple\">must</strong> have been created with a <a href=\"#VkSemaphoreType\">VkSemaphoreType</a> of <code>VK_SEMAPHORE_TYPE_BINARY</code>."
+          "text": " If <code>handleType</code> refers to a handle type with copy payload transference semantics, <code>semaphore</code> <strong class=\"purple\">must</strong> have been created with a <a href=\"#VkSemaphoreType\">VkSemaphoreType</a> of <code>VK_SEMAPHORE_TYPE_BINARY</code>"
         },
         {
           "vuid": "VUID-VkSemaphoreGetFdInfoKHR-handleType-03254",
-          "text": " If <code>handleType</code> refers to a handle type with copy payload transference semantics, <code>semaphore</code> <strong class=\"purple\">must</strong> have an associated semaphore signal operation that has been submitted for execution and any semaphore signal operations on which it depends (if any) <strong class=\"purple\">must</strong> have also been submitted for execution."
+          "text": " If <code>handleType</code> refers to a handle type with copy payload transference semantics, <code>semaphore</code> <strong class=\"purple\">must</strong> have an associated semaphore signal operation that has been submitted for execution and any semaphore signal operations on which it depends (if any) <strong class=\"purple\">must</strong> have also been submitted for execution"
         }
       ]
     },
@@ -2494,7 +2470,7 @@
         },
         {
           "vuid": "VUID-VkSemaphoreSignalInfo-value-03260",
-          "text": " <code>value</code> <strong class=\"purple\">must</strong> have a value which does not differ from the current value of the semaphore or the value of any outstanding semaphore wait or signal operation on <code>semaphore</code> by more than <a href=\"#limits-maxTimelineSemaphoreValueDifference\"><code>maxTimelineSemaphoreValueDifference</code></a>."
+          "text": " <code>value</code> <strong class=\"purple\">must</strong> have a value which does not differ from the current value of the semaphore or the value of any outstanding semaphore wait or signal operation on <code>semaphore</code> by more than <a href=\"#limits-maxTimelineSemaphoreValueDifference\"><code>maxTimelineSemaphoreValueDifference</code></a>"
         },
         {
           "vuid": "VUID-VkSemaphoreSignalInfo-sType-sType",
@@ -2526,31 +2502,31 @@
       "(VK_KHR_external_semaphore_win32)": [
         {
           "vuid": "VUID-VkImportSemaphoreWin32HandleInfoKHR-handleType-01140",
-          "text": " <code>handleType</code> <strong class=\"purple\">must</strong> be a value included in the <a href=\"#synchronization-semaphore-handletypes-win32\">Handle Types Supported by VkImportSemaphoreWin32HandleInfoKHR</a> table."
+          "text": " <code>handleType</code> <strong class=\"purple\">must</strong> be a value included in the <a href=\"#synchronization-semaphore-handletypes-win32\">Handle Types Supported by <code>VkImportSemaphoreWin32HandleInfoKHR</code></a> table"
         },
         {
           "vuid": "VUID-VkImportSemaphoreWin32HandleInfoKHR-handleType-01466",
-          "text": " If <code>handleType</code> is not <code>VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT</code> or <code>VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT</code>, <code>name</code> <strong class=\"purple\">must</strong> be <code>NULL</code>."
+          "text": " If <code>handleType</code> is not <code>VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT</code> or <code>VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT</code>, <code>name</code> <strong class=\"purple\">must</strong> be <code>NULL</code>"
         },
         {
           "vuid": "VUID-VkImportSemaphoreWin32HandleInfoKHR-handleType-01467",
-          "text": " If <code>handleType</code> is not <code>0</code> and <code>handle</code> is <code>NULL</code>, <code>name</code> <strong class=\"purple\">must</strong> name a valid synchronization primitive of the type specified by <code>handleType</code>."
+          "text": " If <code>handleType</code> is not <code>0</code> and <code>handle</code> is <code>NULL</code>, <code>name</code> <strong class=\"purple\">must</strong> name a valid synchronization primitive of the type specified by <code>handleType</code>"
         },
         {
           "vuid": "VUID-VkImportSemaphoreWin32HandleInfoKHR-handleType-01468",
-          "text": " If <code>handleType</code> is not <code>0</code> and <code>name</code> is <code>NULL</code>, <code>handle</code> <strong class=\"purple\">must</strong> be a valid handle of the type specified by <code>handleType</code>."
+          "text": " If <code>handleType</code> is not <code>0</code> and <code>name</code> is <code>NULL</code>, <code>handle</code> <strong class=\"purple\">must</strong> be a valid handle of the type specified by <code>handleType</code>"
         },
         {
           "vuid": "VUID-VkImportSemaphoreWin32HandleInfoKHR-handle-01469",
-          "text": " If <code>handle</code> is not <code>NULL</code>, <code>name</code> must be <code>NULL</code>."
+          "text": " If <code>handle</code> is not <code>NULL</code>, <code>name</code> must be <code>NULL</code>"
         },
         {
           "vuid": "VUID-VkImportSemaphoreWin32HandleInfoKHR-handle-01542",
-          "text": " If <code>handle</code> is not <code>NULL</code>, it <strong class=\"purple\">must</strong> obey any requirements listed for <code>handleType</code> in <a href=\"#external-semaphore-handle-types-compatibility\">external semaphore handle types compatibility</a>."
+          "text": " If <code>handle</code> is not <code>NULL</code>, it <strong class=\"purple\">must</strong> obey any requirements listed for <code>handleType</code> in <a href=\"#external-semaphore-handle-types-compatibility\">external semaphore handle types compatibility</a>"
         },
         {
           "vuid": "VUID-VkImportSemaphoreWin32HandleInfoKHR-name-01543",
-          "text": " If <code>name</code> is not <code>NULL</code>, it <strong class=\"purple\">must</strong> obey any requirements listed for <code>handleType</code> in <a href=\"#external-semaphore-handle-types-compatibility\">external semaphore handle types compatibility</a>."
+          "text": " If <code>name</code> is not <code>NULL</code>, it <strong class=\"purple\">must</strong> obey any requirements listed for <code>handleType</code> in <a href=\"#external-semaphore-handle-types-compatibility\">external semaphore handle types compatibility</a>"
         },
         {
           "vuid": "VUID-VkImportSemaphoreWin32HandleInfoKHR-handleType-03261",
@@ -2580,11 +2556,11 @@
       "(VK_KHR_external_semaphore_win32)+(VK_VERSION_1_2,VK_KHR_timeline_semaphore)": [
         {
           "vuid": "VUID-VkImportSemaphoreWin32HandleInfoKHR-handleType-03262",
-          "text": " If <code>handleType</code> is <code>VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT</code> or <code>VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT</code>, the <a href=\"#VkSemaphoreTypeCreateInfo\">VkSemaphoreTypeCreateInfo</a>::<code>semaphoreType</code> field <strong class=\"purple\">must</strong> match that of the semaphore from which <code>handle</code> or <code>name</code> was exported."
+          "text": " If <code>handleType</code> is <code>VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT</code> or <code>VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT</code>, the <a href=\"#VkSemaphoreTypeCreateInfo\">VkSemaphoreTypeCreateInfo</a>::<code>semaphoreType</code> field <strong class=\"purple\">must</strong> match that of the semaphore from which <code>handle</code> or <code>name</code> was exported"
         },
         {
           "vuid": "VUID-VkImportSemaphoreWin32HandleInfoKHR-flags-03322",
-          "text": " If <code>flags</code> contains <code>VK_SEMAPHORE_IMPORT_TEMPORARY_BIT</code>, the <a href=\"#VkSemaphoreTypeCreateInfo\">VkSemaphoreTypeCreateInfo</a>::<code>semaphoreType</code> field of the semaphore from which <code>handle</code> or <code>name</code> was exported <strong class=\"purple\">must</strong> not be <code>VK_SEMAPHORE_TYPE_TIMELINE</code>."
+          "text": " If <code>flags</code> contains <code>VK_SEMAPHORE_IMPORT_TEMPORARY_BIT</code>, the <a href=\"#VkSemaphoreTypeCreateInfo\">VkSemaphoreTypeCreateInfo</a>::<code>semaphoreType</code> field of the semaphore from which <code>handle</code> or <code>name</code> was exported <strong class=\"purple\">must</strong> not be <code>VK_SEMAPHORE_TYPE_TIMELINE</code>"
         }
       ]
     },
@@ -2608,11 +2584,11 @@
       "(VK_KHR_external_semaphore_fd)": [
         {
           "vuid": "VUID-VkImportSemaphoreFdInfoKHR-handleType-01143",
-          "text": " <code>handleType</code> <strong class=\"purple\">must</strong> be a value included in the <a href=\"#synchronization-semaphore-handletypes-fd\">Handle Types Supported by VkImportSemaphoreFdInfoKHR</a> table."
+          "text": " <code>handleType</code> <strong class=\"purple\">must</strong> be a value included in the <a href=\"#synchronization-semaphore-handletypes-fd\">Handle Types Supported by <code>VkImportSemaphoreFdInfoKHR</code></a> table"
         },
         {
           "vuid": "VUID-VkImportSemaphoreFdInfoKHR-fd-01544",
-          "text": " <code>fd</code> <strong class=\"purple\">must</strong> obey any requirements listed for <code>handleType</code> in <a href=\"#external-semaphore-handle-types-compatibility\">external semaphore handle types compatibility</a>."
+          "text": " <code>fd</code> <strong class=\"purple\">must</strong> obey any requirements listed for <code>handleType</code> in <a href=\"#external-semaphore-handle-types-compatibility\">external semaphore handle types compatibility</a>"
         },
         {
           "vuid": "VUID-VkImportSemaphoreFdInfoKHR-handleType-03263",
@@ -2642,11 +2618,11 @@
       "(VK_KHR_external_semaphore_fd)+(VK_VERSION_1_2,VK_KHR_timeline_semaphore)": [
         {
           "vuid": "VUID-VkImportSemaphoreFdInfoKHR-handleType-03264",
-          "text": " If <code>handleType</code> is <code>VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT</code>, the <a href=\"#VkSemaphoreTypeCreateInfo\">VkSemaphoreTypeCreateInfo</a>::<code>semaphoreType</code> field <strong class=\"purple\">must</strong> match that of the semaphore from which <code>fd</code> was exported."
+          "text": " If <code>handleType</code> is <code>VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT</code>, the <a href=\"#VkSemaphoreTypeCreateInfo\">VkSemaphoreTypeCreateInfo</a>::<code>semaphoreType</code> field <strong class=\"purple\">must</strong> match that of the semaphore from which <code>fd</code> was exported"
         },
         {
           "vuid": "VUID-VkImportSemaphoreFdInfoKHR-flags-03323",
-          "text": " If <code>flags</code> contains <code>VK_SEMAPHORE_IMPORT_TEMPORARY_BIT</code>, the <a href=\"#VkSemaphoreTypeCreateInfo\">VkSemaphoreTypeCreateInfo</a>::<code>semaphoreType</code> field of the semaphore from which <code>fd</code> was exported <strong class=\"purple\">must</strong> not be <code>VK_SEMAPHORE_TYPE_TIMELINE</code>."
+          "text": " If <code>flags</code> contains <code>VK_SEMAPHORE_IMPORT_TEMPORARY_BIT</code>, the <a href=\"#VkSemaphoreTypeCreateInfo\">VkSemaphoreTypeCreateInfo</a>::<code>semaphoreType</code> field of the semaphore from which <code>fd</code> was exported <strong class=\"purple\">must</strong> not be <code>VK_SEMAPHORE_TYPE_TIMELINE</code>"
         }
       ]
     },
@@ -2820,7 +2796,7 @@
       "(VK_VERSION_1_1,VK_KHR_device_group)": [
         {
           "vuid": "VUID-vkCmdSetEvent-commandBuffer-01152",
-          "text": " <code>commandBuffer</code>&#8217;s current device mask <strong class=\"purple\">must</strong> include exactly one physical device."
+          "text": " <code>commandBuffer</code>&#8217;s current device mask <strong class=\"purple\">must</strong> include exactly one physical device"
         }
       ],
       "(VK_NV_mesh_shader)": [
@@ -2888,7 +2864,7 @@
       "(VK_VERSION_1_1,VK_KHR_device_group)": [
         {
           "vuid": "VUID-vkCmdResetEvent-commandBuffer-01157",
-          "text": " <code>commandBuffer</code>&#8217;s current device mask <strong class=\"purple\">must</strong> include exactly one physical device."
+          "text": " <code>commandBuffer</code>&#8217;s current device mask <strong class=\"purple\">must</strong> include exactly one physical device"
         }
       ],
       "(VK_NV_mesh_shader)": [
@@ -2930,15 +2906,15 @@
         },
         {
           "vuid": "VUID-vkCmdWaitEvents-srcStageMask-01164",
-          "text": " Any pipeline stage included in <code>srcStageMask</code> or <code>dstStageMask</code> <strong class=\"purple\">must</strong> be supported by the capabilities of the queue family specified by the <code>queueFamilyIndex</code> member of the <a href=\"#VkCommandPoolCreateInfo\">VkCommandPoolCreateInfo</a> structure that was used to create the <code>VkCommandPool</code> that <code>commandBuffer</code> was allocated from, as specified in the <a href=\"#synchronization-pipeline-stages-supported\">table of supported pipeline stages</a>."
+          "text": " Any pipeline stage included in <code>srcStageMask</code> or <code>dstStageMask</code> <strong class=\"purple\">must</strong> be supported by the capabilities of the queue family specified by the <code>queueFamilyIndex</code> member of the <a href=\"#VkCommandPoolCreateInfo\">VkCommandPoolCreateInfo</a> structure that was used to create the <code>VkCommandPool</code> that <code>commandBuffer</code> was allocated from, as specified in the <a href=\"#synchronization-pipeline-stages-supported\">table of supported pipeline stages</a>"
         },
         {
           "vuid": "VUID-vkCmdWaitEvents-pMemoryBarriers-01165",
-          "text": " Each element of <code>pMemoryBarriers</code>, <code>pBufferMemoryBarriers</code> or <code>pImageMemoryBarriers</code> <strong class=\"purple\">must</strong> not have any access flag included in its <code>srcAccessMask</code> member if that bit is not supported by any of the pipeline stages in <code>srcStageMask</code>, as specified in the <a href=\"#synchronization-access-types-supported\">table of supported access types</a>."
+          "text": " Each element of <code>pMemoryBarriers</code>, <code>pBufferMemoryBarriers</code> or <code>pImageMemoryBarriers</code> <strong class=\"purple\">must</strong> not have any access flag included in its <code>srcAccessMask</code> member if that bit is not supported by any of the pipeline stages in <code>srcStageMask</code>, as specified in the <a href=\"#synchronization-access-types-supported\">table of supported access types</a>"
         },
         {
           "vuid": "VUID-vkCmdWaitEvents-pMemoryBarriers-01166",
-          "text": " Each element of <code>pMemoryBarriers</code>, <code>pBufferMemoryBarriers</code> or <code>pImageMemoryBarriers</code> <strong class=\"purple\">must</strong> not have any access flag included in its <code>dstAccessMask</code> member if that bit is not supported by any of the pipeline stages in <code>dstStageMask</code>, as specified in the <a href=\"#synchronization-access-types-supported\">table of supported access types</a>."
+          "text": " Each element of <code>pMemoryBarriers</code>, <code>pBufferMemoryBarriers</code> or <code>pImageMemoryBarriers</code> <strong class=\"purple\">must</strong> not have any access flag included in its <code>dstAccessMask</code> member if that bit is not supported by any of the pipeline stages in <code>dstStageMask</code>, as specified in the <a href=\"#synchronization-access-types-supported\">table of supported access types</a>"
         },
         {
           "vuid": "VUID-vkCmdWaitEvents-srcQueueFamilyIndex-02803",
@@ -3024,7 +3000,7 @@
       "(VK_VERSION_1_1,VK_KHR_device_group)": [
         {
           "vuid": "VUID-vkCmdWaitEvents-commandBuffer-01167",
-          "text": " <code>commandBuffer</code>&#8217;s current device mask <strong class=\"purple\">must</strong> include exactly one physical device."
+          "text": " <code>commandBuffer</code>&#8217;s current device mask <strong class=\"purple\">must</strong> include exactly one physical device"
         }
       ],
       "(VK_NV_mesh_shader)": [
@@ -3066,7 +3042,7 @@
         },
         {
           "vuid": "VUID-vkCmdPipelineBarrier-pDependencies-02285",
-          "text": " If <code>vkCmdPipelineBarrier</code> is called within a render pass instance, the render pass <strong class=\"purple\">must</strong> have been created with at least one <code>VkSubpassDependency</code> instance in <code>VkRenderPassCreateInfo</code>::<code>pDependencies</code> that expresses a dependency from the current subpass to itself, and for which <code>srcStageMask</code> contains a subset of the bit values in <code>VkSubpassDependency</code>::<code>srcStageMask</code>, <code>dstStageMask</code> contains a subset of the bit values in <code>VkSubpassDependency</code>::<code>dstStageMask</code>, <code>dependencyFlags</code> is equal to <code>VkSubpassDependency</code>::<code>dependencyFlags</code>, <code>srcAccessMask</code> member of each element of <code>pMemoryBarriers</code> and <code>pImageMemoryBarriers</code> contains a subset of the bit values in <code>VkSubpassDependency</code>::<code>srcAccessMask</code>, and <code>dstAccessMask</code> member of each element of <code>pMemoryBarriers</code> and <code>pImageMemoryBarriers</code> contains a subset of the bit values in <code>VkSubpassDependency</code>::<code>dstAccessMask</code>"
+          "text": " If <code>vkCmdPipelineBarrier</code> is called within a render pass instance, the render pass <strong class=\"purple\">must</strong> have been created with at least one <code>VkSubpassDependency</code> instance in <a href=\"#VkRenderPassCreateInfo\">VkRenderPassCreateInfo</a>::<code>pDependencies</code> that expresses a dependency from the current subpass to itself, and for which <code>srcStageMask</code> contains a subset of the bit values in <code>VkSubpassDependency</code>::<code>srcStageMask</code>, <code>dstStageMask</code> contains a subset of the bit values in <code>VkSubpassDependency</code>::<code>dstStageMask</code>, <code>dependencyFlags</code> is equal to <code>VkSubpassDependency</code>::<code>dependencyFlags</code>, <code>srcAccessMask</code> member of each element of <code>pMemoryBarriers</code> and <code>pImageMemoryBarriers</code> contains a subset of the bit values in <code>VkSubpassDependency</code>::<code>srcAccessMask</code>, and <code>dstAccessMask</code> member of each element of <code>pMemoryBarriers</code> and <code>pImageMemoryBarriers</code> contains a subset of the bit values in <code>VkSubpassDependency</code>::<code>dstAccessMask</code>"
         },
         {
           "vuid": "VUID-vkCmdPipelineBarrier-bufferMemoryBarrierCount-01178",
@@ -3270,7 +3246,7 @@
         },
         {
           "vuid": "VUID-VkBufferMemoryBarrier-buffer-01763",
-          "text": " If <code>buffer</code> was created with a sharing mode of <code>VK_SHARING_MODE_CONCURRENT</code>, and one of <code>srcQueueFamilyIndex</code> and <code>dstQueueFamilyIndex</code> is <code>VK_QUEUE_FAMILY_IGNORED</code>, the other <strong class=\"purple\">must</strong> be <code>VK_QUEUE_FAMILY_IGNORED</code> or a special queue family reserved for external memory ownership transfers, as described in <a href=\"#synchronization-queue-transfers\">Queue Family Ownership Transfer</a>."
+          "text": " If <code>buffer</code> was created with a sharing mode of <code>VK_SHARING_MODE_CONCURRENT</code>, and one of <code>srcQueueFamilyIndex</code> and <code>dstQueueFamilyIndex</code> is <code>VK_QUEUE_FAMILY_IGNORED</code>, the other <strong class=\"purple\">must</strong> be <code>VK_QUEUE_FAMILY_IGNORED</code> or a special queue family reserved for external memory ownership transfers, as described in <a href=\"#synchronization-queue-transfers\">Queue Family Ownership Transfer</a>"
         },
         {
           "vuid": "VUID-VkBufferMemoryBarrier-buffer-01193",
@@ -3278,11 +3254,11 @@
         },
         {
           "vuid": "VUID-VkBufferMemoryBarrier-buffer-01764",
-          "text": " If <code>buffer</code> was created with a sharing mode of <code>VK_SHARING_MODE_EXCLUSIVE</code> and <code>srcQueueFamilyIndex</code> is not <code>VK_QUEUE_FAMILY_IGNORED</code>, it <strong class=\"purple\">must</strong> be a valid queue family or a special queue family reserved for external memory transfers, as described in <a href=\"#synchronization-queue-transfers\">Queue Family Ownership Transfer</a>."
+          "text": " If <code>buffer</code> was created with a sharing mode of <code>VK_SHARING_MODE_EXCLUSIVE</code> and <code>srcQueueFamilyIndex</code> is not <code>VK_QUEUE_FAMILY_IGNORED</code>, it <strong class=\"purple\">must</strong> be a valid queue family or a special queue family reserved for external memory transfers, as described in <a href=\"#synchronization-queue-transfers\">Queue Family Ownership Transfer</a>"
         },
         {
           "vuid": "VUID-VkBufferMemoryBarrier-buffer-01765",
-          "text": " If <code>buffer</code> was created with a sharing mode of <code>VK_SHARING_MODE_EXCLUSIVE</code> and <code>dstQueueFamilyIndex</code> is not <code>VK_QUEUE_FAMILY_IGNORED</code>, it <strong class=\"purple\">must</strong> be a valid queue family or a special queue family reserved for external memory transfers, as described in <a href=\"#synchronization-queue-transfers\">Queue Family Ownership Transfer</a>."
+          "text": " If <code>buffer</code> was created with a sharing mode of <code>VK_SHARING_MODE_EXCLUSIVE</code> and <code>dstQueueFamilyIndex</code> is not <code>VK_QUEUE_FAMILY_IGNORED</code>, it <strong class=\"purple\">must</strong> be a valid queue family or a special queue family reserved for external memory transfers, as described in <a href=\"#synchronization-queue-transfers\">Queue Family Ownership Transfer</a>"
         }
       ]
     },
@@ -3380,7 +3356,7 @@
         },
         {
           "vuid": "VUID-VkImageMemoryBarrier-image-01200",
-          "text": " If <code>image</code> was created with a sharing mode of <code>VK_SHARING_MODE_EXCLUSIVE</code>, <code>srcQueueFamilyIndex</code> and <code>dstQueueFamilyIndex</code> <strong class=\"purple\">must</strong> either both be <code>VK_QUEUE_FAMILY_IGNORED</code>, or both be a valid queue family (see <a href=\"#devsandqueues-queueprops\">Queue Family Properties</a>)."
+          "text": " If <code>image</code> was created with a sharing mode of <code>VK_SHARING_MODE_EXCLUSIVE</code>, <code>srcQueueFamilyIndex</code> and <code>dstQueueFamilyIndex</code> <strong class=\"purple\">must</strong> either both be <code>VK_QUEUE_FAMILY_IGNORED</code>, or both be a valid queue family (see <a href=\"#devsandqueues-queueprops\">Queue Family Properties</a>)"
         }
       ],
       "(VK_VERSION_1_1,VK_KHR_external_memory)": [
@@ -3390,19 +3366,19 @@
         },
         {
           "vuid": "VUID-VkImageMemoryBarrier-image-01766",
-          "text": " If <code>image</code> was created with a sharing mode of <code>VK_SHARING_MODE_CONCURRENT</code>, and one of <code>srcQueueFamilyIndex</code> and <code>dstQueueFamilyIndex</code> is <code>VK_QUEUE_FAMILY_IGNORED</code>, the other <strong class=\"purple\">must</strong> be <code>VK_QUEUE_FAMILY_IGNORED</code> or a special queue family reserved for external memory transfers, as described in <a href=\"#synchronization-queue-transfers\">Queue Family Ownership Transfer</a>."
+          "text": " If <code>image</code> was created with a sharing mode of <code>VK_SHARING_MODE_CONCURRENT</code>, and one of <code>srcQueueFamilyIndex</code> and <code>dstQueueFamilyIndex</code> is <code>VK_QUEUE_FAMILY_IGNORED</code>, the other <strong class=\"purple\">must</strong> be <code>VK_QUEUE_FAMILY_IGNORED</code> or a special queue family reserved for external memory transfers, as described in <a href=\"#synchronization-queue-transfers\">Queue Family Ownership Transfer</a>"
         },
         {
           "vuid": "VUID-VkImageMemoryBarrier-image-01201",
-          "text": " If <code>image</code> was created with a sharing mode of <code>VK_SHARING_MODE_EXCLUSIVE</code> and <code>srcQueueFamilyIndex</code> is <code>VK_QUEUE_FAMILY_IGNORED</code>, <code>dstQueueFamilyIndex</code> <strong class=\"purple\">must</strong> also be <code>VK_QUEUE_FAMILY_IGNORED</code>."
+          "text": " If <code>image</code> was created with a sharing mode of <code>VK_SHARING_MODE_EXCLUSIVE</code> and <code>srcQueueFamilyIndex</code> is <code>VK_QUEUE_FAMILY_IGNORED</code>, <code>dstQueueFamilyIndex</code> <strong class=\"purple\">must</strong> also be <code>VK_QUEUE_FAMILY_IGNORED</code>"
         },
         {
           "vuid": "VUID-VkImageMemoryBarrier-image-01767",
-          "text": " If <code>image</code> was created with a sharing mode of <code>VK_SHARING_MODE_EXCLUSIVE</code> and <code>srcQueueFamilyIndex</code> is not <code>VK_QUEUE_FAMILY_IGNORED</code>, it <strong class=\"purple\">must</strong> be a valid queue family or a special queue family reserved for external memory transfers, as described in <a href=\"#synchronization-queue-transfers\">Queue Family Ownership Transfer</a>."
+          "text": " If <code>image</code> was created with a sharing mode of <code>VK_SHARING_MODE_EXCLUSIVE</code> and <code>srcQueueFamilyIndex</code> is not <code>VK_QUEUE_FAMILY_IGNORED</code>, it <strong class=\"purple\">must</strong> be a valid queue family or a special queue family reserved for external memory transfers, as described in <a href=\"#synchronization-queue-transfers\">Queue Family Ownership Transfer</a>"
         },
         {
           "vuid": "VUID-VkImageMemoryBarrier-image-01768",
-          "text": " If <code>image</code> was created with a sharing mode of <code>VK_SHARING_MODE_EXCLUSIVE</code> and <code>dstQueueFamilyIndex</code> is not <code>VK_QUEUE_FAMILY_IGNORED</code>, it <strong class=\"purple\">must</strong> be a valid queue family or a special queue family reserved for external memory transfers, as described in <a href=\"#synchronization-queue-transfers\">Queue Family Ownership Transfer</a>."
+          "text": " If <code>image</code> was created with a sharing mode of <code>VK_SHARING_MODE_EXCLUSIVE</code> and <code>dstQueueFamilyIndex</code> is not <code>VK_QUEUE_FAMILY_IGNORED</code>, it <strong class=\"purple\">must</strong> be a valid queue family or a special queue family reserved for external memory transfers, as described in <a href=\"#synchronization-queue-transfers\">Queue Family Ownership Transfer</a>"
         }
       ],
       "(VK_VERSION_1_2,VK_KHR_separate_depth_stencil_layouts)": [
@@ -3421,10 +3397,16 @@
           "text": " If <code>image</code> has a depth/stencil format with both depth and stencil components, then the <code>aspectMask</code> member of <code>subresourceRange</code> <strong class=\"purple\">must</strong> include both <code>VK_IMAGE_ASPECT_DEPTH_BIT</code> and <code>VK_IMAGE_ASPECT_STENCIL_BIT</code>"
         }
       ],
+      "!(VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion)": [
+        {
+          "vuid": "VUID-VkImageMemoryBarrier-image-02902",
+          "text": " If <code>image</code> has a color format, then the <code>aspectMask</code> member of <code>subresourceRange</code> <strong class=\"purple\">must</strong> only include <code>VK_IMAGE_ASPECT_COLOR_BIT</code>"
+        }
+      ],
       "(VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion)": [
         {
           "vuid": "VUID-VkImageMemoryBarrier-image-01671",
-          "text": " If <code>image</code> has a single-plane color format or is not <em>disjoint</em>, then the <code>aspectMask</code> member of <code>subresourceRange</code> <strong class=\"purple\">must</strong> be <code>VK_IMAGE_ASPECT_COLOR_BIT</code>"
+          "text": " If <code>image</code> has a color format and either the format is single-plane or the image is not disjoint then the <code>aspectMask</code> member of <code>subresourceRange</code> <strong class=\"purple\">must</strong> only include <code>VK_IMAGE_ASPECT_COLOR_BIT</code>"
         },
         {
           "vuid": "VUID-VkImageMemoryBarrier-image-01672",
@@ -3540,7 +3522,7 @@
         },
         {
           "vuid": "VUID-VkRenderPassCreateInfo-pAttachments-00836",
-          "text": " For any member of <code>pAttachments</code> with a <code>loadOp</code> equal to <code>VK_ATTACHMENT_LOAD_OP_CLEAR</code>, the first use of that attachment <strong class=\"purple\">must</strong> not specify a <code>layout</code> equal to <code>VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL</code> or <code>VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL</code>."
+          "text": " For any member of <code>pAttachments</code> with a <code>loadOp</code> equal to <code>VK_ATTACHMENT_LOAD_OP_CLEAR</code>, the first use of that attachment <strong class=\"purple\">must</strong> not specify a <code>layout</code> equal to <code>VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL</code> or <code>VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL</code>"
         },
         {
           "vuid": "VUID-VkRenderPassCreateInfo-pAttachments-02511",
@@ -3598,11 +3580,11 @@
       "(VK_VERSION_1_1,VK_KHR_maintenance2)": [
         {
           "vuid": "VUID-VkRenderPassCreateInfo-pAttachments-01566",
-          "text": " For any member of <code>pAttachments</code> with a <code>loadOp</code> equal to <code>VK_ATTACHMENT_LOAD_OP_CLEAR</code>, the first use of that attachment <strong class=\"purple\">must</strong> not specify a <code>layout</code> equal to <code>VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL</code>."
+          "text": " For any member of <code>pAttachments</code> with a <code>loadOp</code> equal to <code>VK_ATTACHMENT_LOAD_OP_CLEAR</code>, the first use of that attachment <strong class=\"purple\">must</strong> not specify a <code>layout</code> equal to <code>VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL</code>"
         },
         {
           "vuid": "VUID-VkRenderPassCreateInfo-pAttachments-01567",
-          "text": " For any member of <code>pAttachments</code> with a <code>stencilLoadOp</code> equal to <code>VK_ATTACHMENT_LOAD_OP_CLEAR</code>, the first use of that attachment <strong class=\"purple\">must</strong> not specify a <code>layout</code> equal to <code>VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL</code>."
+          "text": " For any member of <code>pAttachments</code> with a <code>stencilLoadOp</code> equal to <code>VK_ATTACHMENT_LOAD_OP_CLEAR</code>, the first use of that attachment <strong class=\"purple\">must</strong> not specify a <code>layout</code> equal to <code>VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL</code>"
         },
         {
           "vuid": "VUID-VkRenderPassCreateInfo-pNext-01926",
@@ -3692,11 +3674,11 @@
         },
         {
           "vuid": "VUID-VkRenderPassFragmentDensityMapCreateInfoEXT-fragmentDensityMapAttachment-02550",
-          "text": " If <code>fragmentDensityMapAttachment</code> is not <code>VK_ATTACHMENT_UNUSED</code>, <code>fragmentDensityMapAttachment</code> <strong class=\"purple\">must</strong> reference an attachment with a <code>loadOp</code> equal to <code>VK_ATTACHMENT_LOAD_OP_LOAD</code> or <code>VK_ATTACHMENT_LOAD_OP_DONT_CARE</code>."
+          "text": " If <code>fragmentDensityMapAttachment</code> is not <code>VK_ATTACHMENT_UNUSED</code>, <code>fragmentDensityMapAttachment</code> <strong class=\"purple\">must</strong> reference an attachment with a <code>loadOp</code> equal to <code>VK_ATTACHMENT_LOAD_OP_LOAD</code> or <code>VK_ATTACHMENT_LOAD_OP_DONT_CARE</code>"
         },
         {
           "vuid": "VUID-VkRenderPassFragmentDensityMapCreateInfoEXT-fragmentDensityMapAttachment-02551",
-          "text": " If <code>fragmentDensityMapAttachment</code> is not <code>VK_ATTACHMENT_UNUSED</code>, <code>fragmentDensityMapAttachment</code> <strong class=\"purple\">must</strong> reference an attachment with a <code>storeOp</code> equal to <code>VK_ATTACHMENT_STORE_OP_DONT_CARE</code>."
+          "text": " If <code>fragmentDensityMapAttachment</code> is not <code>VK_ATTACHMENT_UNUSED</code>, <code>fragmentDensityMapAttachment</code> <strong class=\"purple\">must</strong> reference an attachment with a <code>storeOp</code> equal to <code>VK_ATTACHMENT_STORE_OP_DONT_CARE</code>"
         },
         {
           "vuid": "VUID-VkRenderPassFragmentDensityMapCreateInfoEXT-sType-sType",
@@ -3844,7 +3826,7 @@
       "(VK_VERSION_1_1,VK_KHR_maintenance2)+(VK_EXT_image_drm_format_modifier)": [
         {
           "vuid": "VUID-VkInputAttachmentAspectReference-aspectMask-02250",
-          "text": " <code>aspectMask</code> <strong class=\"purple\">must</strong> not include <code>VK_IMAGE_ASPECT_MEMORY_PLANE_i_BIT_EXT</code> for any index <code>i</code>."
+          "text": " <code>aspectMask</code> <strong class=\"purple\">must</strong> not include <code>VK_IMAGE_ASPECT_MEMORY_PLANE_i_BIT_EXT</code> for any index <code>i</code>"
         }
       ]
     },
@@ -3884,7 +3866,7 @@
         },
         {
           "vuid": "VUID-VkSubpassDescription-pInputAttachments-02647",
-          "text": " All attachments in <code>pInputAttachments</code> that are not <code>VK_ATTACHMENT_UNUSED</code> <strong class=\"purple\">must</strong> have formats whose features contain at least one of <code>VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT</code> or <code>VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT</code>."
+          "text": " All attachments in <code>pInputAttachments</code> that are not <code>VK_ATTACHMENT_UNUSED</code> <strong class=\"purple\">must</strong> have formats whose features contain at least one of <code>VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT</code> or <code>VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT</code>"
         },
         {
           "vuid": "VUID-VkSubpassDescription-pColorAttachments-02648",
@@ -3952,13 +3934,13 @@
       "(VK_NVX_multiview_per_view_attributes)": [
         {
           "vuid": "VUID-VkSubpassDescription-flags-00856",
-          "text": " If <code>flags</code> includes <code>VK_SUBPASS_DESCRIPTION_PER_VIEW_POSITION_X_ONLY_BIT_NVX</code>, it <strong class=\"purple\">must</strong> also include <code>VK_SUBPASS_DESCRIPTION_PER_VIEW_ATTRIBUTES_BIT_NVX</code>."
+          "text": " If <code>flags</code> includes <code>VK_SUBPASS_DESCRIPTION_PER_VIEW_POSITION_X_ONLY_BIT_NVX</code>, it <strong class=\"purple\">must</strong> also include <code>VK_SUBPASS_DESCRIPTION_PER_VIEW_ATTRIBUTES_BIT_NVX</code>"
         }
       ],
       "(VK_QCOM_render_pass_transform)": [
         {
           "vuid": "VUID-VkSubpassDescription-pInputAttachments-02868",
-          "text": " If the render pass is created with <code>VK_RENDER_PASS_CREATE_TRANSFORM_BIT_QCOM</code> each of the elements of <code>pInputAttachments</code> <strong class=\"purple\">must</strong> be <code>VK_ATTACHMENT_UNUSED</code>."
+          "text": " If the render pass is created with <code>VK_RENDER_PASS_CREATE_TRANSFORM_BIT_QCOM</code> each of the elements of <code>pInputAttachments</code> <strong class=\"purple\">must</strong> be <code>VK_ATTACHMENT_UNUSED</code>"
         }
       ]
     },
@@ -4118,7 +4100,7 @@
         },
         {
           "vuid": "VUID-VkRenderPassCreateInfo2-pAttachments-02523",
-          "text": " For any member of <code>pAttachments</code> with a <code>stencilLoadOp</code> equal to <code>VK_ATTACHMENT_LOAD_OP_CLEAR</code>, the first use of that attachment <strong class=\"purple\">must</strong> not specify a <code>layout</code> equal to <code>VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL</code>, <code>VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL</code>, or <code>VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL</code>."
+          "text": " For any member of <code>pAttachments</code> with a <code>stencilLoadOp</code> equal to <code>VK_ATTACHMENT_LOAD_OP_CLEAR</code>, the first use of that attachment <strong class=\"purple\">must</strong> not specify a <code>layout</code> equal to <code>VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL</code>, <code>VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL</code>, or <code>VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL</code>"
         },
         {
           "vuid": "VUID-VkRenderPassCreateInfo2-pDependencies-03054",
@@ -4371,6 +4353,22 @@
           "text": " All attachments in <code>pColorAttachments</code> that are not <code>VK_ATTACHMENT_UNUSED</code> <strong class=\"purple\">must</strong> have the same sample count"
         },
         {
+          "vuid": "VUID-VkSubpassDescription2-pInputAttachments-02897",
+          "text": " All attachments in <code>pInputAttachments</code> that are not <code>VK_ATTACHMENT_UNUSED</code> <strong class=\"purple\">must</strong> have formats whose features contain at least one of <code>VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT</code> or <code>VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT</code>"
+        },
+        {
+          "vuid": "VUID-VkSubpassDescription2-pColorAttachments-02898",
+          "text": " All attachments in <code>pColorAttachments</code> that are not <code>VK_ATTACHMENT_UNUSED</code> <strong class=\"purple\">must</strong> have formats whose features contain <code>VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT</code>"
+        },
+        {
+          "vuid": "VUID-VkSubpassDescription2-pResolveAttachments-02899",
+          "text": " All attachments in <code>pResolveAttachments</code> that are not <code>VK_ATTACHMENT_UNUSED</code> <strong class=\"purple\">must</strong> have formats whose features contain <code>VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT</code>"
+        },
+        {
+          "vuid": "VUID-VkSubpassDescription2-pDepthStencilAttachment-02900",
+          "text": " If <code>pDepthStencilAttachment</code> is not <code>NULL</code> and the attachment is not <code>VK_ATTACHMENT_UNUSED</code> then it <strong class=\"purple\">must</strong> have a format whose features contain <code>VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT</code>"
+        },
+        {
           "vuid": "VUID-VkSubpassDescription2-pDepthStencilAttachment-03071",
           "text": " If neither the <code>VK_AMD_mixed_attachment_samples</code> nor the <code>VK_NV_framebuffer_mixed_samples</code> extensions are enabled, and if <code>pDepthStencilAttachment</code> is not <code>VK_ATTACHMENT_UNUSED</code> and any attachments in <code>pColorAttachments</code> are not <code>VK_ATTACHMENT_UNUSED</code>, they <strong class=\"purple\">must</strong> have the same sample count"
         },
@@ -4440,7 +4438,7 @@
       "(VK_VERSION_1_2,VK_KHR_create_renderpass2)+(VK_NVX_multiview_per_view_attributes)": [
         {
           "vuid": "VUID-VkSubpassDescription2-flags-03076",
-          "text": " If <code>flags</code> includes <code>VK_SUBPASS_DESCRIPTION_PER_VIEW_POSITION_X_ONLY_BIT_NVX</code>, it <strong class=\"purple\">must</strong> also include <code>VK_SUBPASS_DESCRIPTION_PER_VIEW_ATTRIBUTES_BIT_NVX</code>."
+          "text": " If <code>flags</code> includes <code>VK_SUBPASS_DESCRIPTION_PER_VIEW_POSITION_X_ONLY_BIT_NVX</code>, it <strong class=\"purple\">must</strong> also include <code>VK_SUBPASS_DESCRIPTION_PER_VIEW_ATTRIBUTES_BIT_NVX</code>"
         }
       ]
     },
@@ -4780,7 +4778,7 @@
         },
         {
           "vuid": "VUID-VkFramebufferCreateInfo-width-00885",
-          "text": " <code>width</code> <strong class=\"purple\">must</strong> be greater than <code>0</code>."
+          "text": " <code>width</code> <strong class=\"purple\">must</strong> be greater than <code>0</code>"
         },
         {
           "vuid": "VUID-VkFramebufferCreateInfo-width-00886",
@@ -4788,7 +4786,7 @@
         },
         {
           "vuid": "VUID-VkFramebufferCreateInfo-height-00887",
-          "text": " <code>height</code> <strong class=\"purple\">must</strong> be greater than <code>0</code>."
+          "text": " <code>height</code> <strong class=\"purple\">must</strong> be greater than <code>0</code>"
         },
         {
           "vuid": "VUID-VkFramebufferCreateInfo-height-00888",
@@ -4796,7 +4794,7 @@
         },
         {
           "vuid": "VUID-VkFramebufferCreateInfo-layers-00889",
-          "text": " <code>layers</code> <strong class=\"purple\">must</strong> be greater than <code>0</code>."
+          "text": " <code>layers</code> <strong class=\"purple\">must</strong> be greater than <code>0</code>"
         },
         {
           "vuid": "VUID-VkFramebufferCreateInfo-layers-00890",
@@ -4840,11 +4838,11 @@
       "(VK_EXT_fragment_density_map)": [
         {
           "vuid": "VUID-VkFramebufferCreateInfo-pAttachments-02552",
-          "text": " Each element of <code>pAttachments</code> that is used as a fragment density map attachment by <code>renderPass</code> <strong class=\"purple\">must</strong> not have been created with a <code>flags</code> value including <code>VK_IMAGE_CREATE_SUBSAMPLED_BIT_EXT</code>."
+          "text": " Each element of <code>pAttachments</code> that is used as a fragment density map attachment by <code>renderPass</code> <strong class=\"purple\">must</strong> not have been created with a <code>flags</code> value including <code>VK_IMAGE_CREATE_SUBSAMPLED_BIT_EXT</code>"
         },
         {
           "vuid": "VUID-VkFramebufferCreateInfo-renderPass-02553",
-          "text": " If <code>renderPass</code> has a fragment density map attachment and <a href=\"#features-nonsubsampledimages\">non-subsample image feature</a> is not enabled, each element of <code>pAttachments</code> <strong class=\"purple\">must</strong> have been created with a <code>flags</code> value including <code>VK_IMAGE_CREATE_SUBSAMPLED_BIT_EXT</code> unless that element is the fragment density map attachment."
+          "text": " If <code>renderPass</code> has a fragment density map attachment and <a href=\"#features-nonsubsampledimages\">non-subsample image feature</a> is not enabled, each element of <code>pAttachments</code> <strong class=\"purple\">must</strong> have been created with a <code>flags</code> value including <code>VK_IMAGE_CREATE_SUBSAMPLED_BIT_EXT</code> unless that element is the fragment density map attachment"
         },
         {
           "vuid": "VUID-VkFramebufferCreateInfo-pAttachments-02554",
@@ -5224,7 +5222,7 @@
         },
         {
           "vuid": "VUID-VkRenderPassBeginInfo-renderPass-00904",
-          "text": " <code>renderPass</code> <strong class=\"purple\">must</strong> be <a href=\"#renderpass-compatibility\">compatible</a> with the <code>renderPass</code> member of the <code>VkFramebufferCreateInfo</code> structure specified when creating <code>framebuffer</code>"
+          "text": " <code>renderPass</code> <strong class=\"purple\">must</strong> be <a href=\"#renderpass-compatibility\">compatible</a> with the <code>renderPass</code> member of the <a href=\"#VkFramebufferCreateInfo\">VkFramebufferCreateInfo</a> structure specified when creating <code>framebuffer</code>"
         },
         {
           "vuid": "VUID-VkRenderPassBeginInfo-sType-sType",
@@ -5360,11 +5358,11 @@
       "(VK_QCOM_render_pass_transform)": [
         {
           "vuid": "VUID-VkRenderPassBeginInfo-pNext-02869",
-          "text": " If the <code>pNext</code> chain includes <a href=\"#VkRenderPassTransformBeginInfoQCOM\">VkRenderPassTransformBeginInfoQCOM</a>, <code>renderArea</code>::<code>offset</code> <strong class=\"purple\">must</strong> equal (0,0)."
+          "text": " If the <code>pNext</code> chain includes <a href=\"#VkRenderPassTransformBeginInfoQCOM\">VkRenderPassTransformBeginInfoQCOM</a>, <code>renderArea</code>::<code>offset</code> <strong class=\"purple\">must</strong> equal (0,0)"
         },
         {
           "vuid": "VUID-VkRenderPassBeginInfo-pNext-02870",
-          "text": " If the <code>pNext</code> chain includes <a href=\"#VkRenderPassTransformBeginInfoQCOM\">VkRenderPassTransformBeginInfoQCOM</a>, <code>renderArea</code>::<code>extent</code> transformed by <a href=\"#VkRenderPassTransformBeginInfoQCOM\">VkRenderPassTransformBeginInfoQCOM</a>::<code>transform</code> <strong class=\"purple\">must</strong> equal the <code>framebuffer</code> dimensions."
+          "text": " If the <code>pNext</code> chain includes <a href=\"#VkRenderPassTransformBeginInfoQCOM\">VkRenderPassTransformBeginInfoQCOM</a>, <code>renderArea</code>::<code>extent</code> transformed by <a href=\"#VkRenderPassTransformBeginInfoQCOM\">VkRenderPassTransformBeginInfoQCOM</a>::<code>transform</code> <strong class=\"purple\">must</strong> equal the <code>framebuffer</code> dimensions"
         }
       ]
     },
@@ -5412,11 +5410,11 @@
       "(VK_QCOM_render_pass_transform)": [
         {
           "vuid": "VUID-VkRenderPassTransformBeginInfoQCOM-transform-02871",
-          "text": " <code>transform</code> <strong class=\"purple\">must</strong> be VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR, VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR, VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR, or VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR."
+          "text": " <code>transform</code> <strong class=\"purple\">must</strong> be <code>VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR</code>, <code>VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR</code>, <code>VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR</code>, or <code>VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR</code>"
         },
         {
           "vuid": "VUID-VkRenderPassTransformBeginInfoQCOM-flags-02872",
-          "text": " The renderpass must have been created with <a href=\"#VkRenderPassCreateInfo\">VkRenderPassCreateInfo</a>::<code>flags</code> containing VK_RENDER_PASS_CREATE_TRANSFORM_BIT_QCOM."
+          "text": " The <code>renderpass</code> must have been created with <a href=\"#VkRenderPassCreateInfo\">VkRenderPassCreateInfo</a>::<code>flags</code> containing <code>VK_RENDER_PASS_CREATE_TRANSFORM_BIT_QCOM</code>"
         },
         {
           "vuid": "VUID-VkRenderPassTransformBeginInfoQCOM-sType-sType",
@@ -5456,7 +5454,7 @@
         },
         {
           "vuid": "VUID-VkDeviceGroupRenderPassBeginInfo-deviceRenderAreaCount-00908",
-          "text": " <code>deviceRenderAreaCount</code> <strong class=\"purple\">must</strong> either be zero or equal to the number of physical devices in the logical device."
+          "text": " <code>deviceRenderAreaCount</code> <strong class=\"purple\">must</strong> either be zero or equal to the number of physical devices in the logical device"
         },
         {
           "vuid": "VUID-VkDeviceGroupRenderPassBeginInfo-sType-sType",
@@ -5708,7 +5706,7 @@
         },
         {
           "vuid": "VUID-VkShaderModuleCreateInfo-pCode-01091",
-          "text": " If <code>pCode</code> declares any of the capabilities listed as <strong class=\"purple\">optional</strong> in the <a href=\"#spirvenv-capabilities-table\">SPIR-V Environment</a> appendix, the corresponding feature(s) <strong class=\"purple\">must</strong> be enabled."
+          "text": " If <code>pCode</code> declares any of the capabilities listed as <strong class=\"purple\">optional</strong> in the <a href=\"#spirvenv-capabilities-table\">SPIR-V Environment</a> appendix, the corresponding feature(s) <strong class=\"purple\">must</strong> be enabled"
         },
         {
           "vuid": "VUID-VkShaderModuleCreateInfo-sType-sType",
@@ -6022,6 +6020,12 @@
           "vuid": "VUID-vkCreateComputePipelines-pipelineCache-parent",
           "text": " If <code>pipelineCache</code> is a valid handle, it <strong class=\"purple\">must</strong> have been created, allocated, or retrieved from <code>device</code>"
         }
+      ],
+      "(VK_EXT_pipeline_creation_cache_control)": [
+        {
+          "vuid": "VUID-vkCreateComputePipelines-pipelineCache-02873",
+          "text": " If <code>pipelineCache</code> was created with <code>VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT_EXT</code>, host access to <code>pipelineCache</code> <strong class=\"purple\">must</strong> be <a href=\"#fundamentals-threadingbehavior\">externally synchronized</a>"
+        }
       ]
     },
     "VkComputePipelineCreateInfo": {
@@ -6086,6 +6090,50 @@
           "vuid": "VUID-VkComputePipelineCreateInfo-commonparent",
           "text": " Both of <code>basePipelineHandle</code>, and <code>layout</code> that are valid handles of non-ignored parameters <strong class=\"purple\">must</strong> have been created, allocated, or retrieved from the same <a href=\"#VkDevice\">VkDevice</a>"
         }
+      ],
+      "(VK_KHR_pipeline_library)": [
+        {
+          "vuid": "VUID-VkComputePipelineCreateInfo-flags-03364",
+          "text": " <code>flags</code> <strong class=\"purple\">must</strong> not include <code>VK_PIPELINE_CREATE_LIBRARY_BIT_KHR</code>"
+        }
+      ],
+      "(VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-VkComputePipelineCreateInfo-flags-03365",
+          "text": " <code>flags</code> <strong class=\"purple\">must</strong> not include <code>VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_ANY_HIT_SHADERS_BIT_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkComputePipelineCreateInfo-flags-03366",
+          "text": " <code>flags</code> <strong class=\"purple\">must</strong> not include <code>VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_CLOSEST_HIT_SHADERS_BIT_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkComputePipelineCreateInfo-flags-03367",
+          "text": " <code>flags</code> <strong class=\"purple\">must</strong> not include <code>VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_MISS_SHADERS_BIT_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkComputePipelineCreateInfo-flags-03368",
+          "text": " <code>flags</code> <strong class=\"purple\">must</strong> not include <code>VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_INTERSECTION_SHADERS_BIT_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkComputePipelineCreateInfo-flags-03369",
+          "text": " <code>flags</code> <strong class=\"purple\">must</strong> not include <code>VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkComputePipelineCreateInfo-flags-03370",
+          "text": " <code>flags</code> <strong class=\"purple\">must</strong> not include <code>VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR</code>"
+        }
+      ],
+      "(VK_NV_device_generated_commands)": [
+        {
+          "vuid": "VUID-VkComputePipelineCreateInfo-flags-02874",
+          "text": " <code>flags</code> <strong class=\"purple\">must</strong> not include <code>VK_PIPELINE_CREATE_INDIRECT_BINDABLE_BIT_NV</code>"
+        }
+      ],
+      "(VK_EXT_pipeline_creation_cache_control)": [
+        {
+          "vuid": "VUID-VkComputePipelineCreateInfo-pipelineCreationCacheControl-02875",
+          "text": " If the <a href=\"#features-pipelineCreationCacheControl\"><code>pipelineCreationCacheControl</code></a> feature is not enabled, <code>flags</code> <strong class=\"purple\">must</strong> not include <code>VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_EXT</code> or <code>VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT_EXT</code>"
+        }
       ]
     },
     "VkPipelineShaderStageCreateInfo": {
@@ -6198,11 +6246,11 @@
         },
         {
           "vuid": "VUID-VkPipelineShaderStageCreateInfo-stage-02093",
-          "text": " If <code>stage</code> is <code>VK_SHADER_STAGE_MESH_BIT_NV</code>, the identified entry point <strong class=\"purple\">must</strong> have an <code>OpExecutionMode</code> instruction that specifies a maximum output vertex count, <code>OutputVertices</code>, that is greater than <code>0</code> and less than or equal to <code>VkPhysicalDeviceMeshShaderPropertiesNV</code>::<code>maxMeshOutputVertices</code>."
+          "text": " If <code>stage</code> is <code>VK_SHADER_STAGE_MESH_BIT_NV</code>, the identified entry point <strong class=\"purple\">must</strong> have an <code>OpExecutionMode</code> instruction that specifies a maximum output vertex count, <code>OutputVertices</code>, that is greater than <code>0</code> and less than or equal to <code>VkPhysicalDeviceMeshShaderPropertiesNV</code>::<code>maxMeshOutputVertices</code>"
         },
         {
           "vuid": "VUID-VkPipelineShaderStageCreateInfo-stage-02094",
-          "text": " If <code>stage</code> is <code>VK_SHADER_STAGE_MESH_BIT_NV</code>, the identified entry point <strong class=\"purple\">must</strong> have an <code>OpExecutionMode</code> instruction that specifies a maximum output primitive count, <code>OutputPrimitivesNV</code>, that is greater than <code>0</code> and less than or equal to <code>VkPhysicalDeviceMeshShaderPropertiesNV</code>::<code>maxMeshOutputPrimitives</code>."
+          "text": " If <code>stage</code> is <code>VK_SHADER_STAGE_MESH_BIT_NV</code>, the identified entry point <strong class=\"purple\">must</strong> have an <code>OpExecutionMode</code> instruction that specifies a maximum output primitive count, <code>OutputPrimitivesNV</code>, that is greater than <code>0</code> and less than or equal to <code>VkPhysicalDeviceMeshShaderPropertiesNV</code>::<code>maxMeshOutputPrimitives</code>"
         }
       ],
       "(VK_EXT_shader_stencil_export)": [
@@ -6214,35 +6262,35 @@
       "(VK_EXT_subgroup_size_control)": [
         {
           "vuid": "VUID-VkPipelineShaderStageCreateInfo-flags-02784",
-          "text": " If <code>flags</code> has the <code>VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT</code> flag set, the <a href=\"#features-subgroupSizeControl\"><code>subgroupSizeControl</code></a> feature <strong class=\"purple\">must</strong> be enabled."
+          "text": " If <code>flags</code> has the <code>VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT</code> flag set, the <a href=\"#features-subgroupSizeControl\"><code>subgroupSizeControl</code></a> feature <strong class=\"purple\">must</strong> be enabled"
         },
         {
           "vuid": "VUID-VkPipelineShaderStageCreateInfo-flags-02785",
-          "text": " If <code>flags</code> has the <code>VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT</code> flag set, the <a href=\"#features-computeFullSubgroups\"><code>computeFullSubgroups</code></a> feature <strong class=\"purple\">must</strong> be enabled."
+          "text": " If <code>flags</code> has the <code>VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT</code> flag set, the <a href=\"#features-computeFullSubgroups\"><code>computeFullSubgroups</code></a> feature <strong class=\"purple\">must</strong> be enabled"
         },
         {
           "vuid": "VUID-VkPipelineShaderStageCreateInfo-pNext-02754",
-          "text": " If a <a href=\"#VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT\">VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT</a> structure is included in the <code>pNext</code> chain, <code>flags</code> <strong class=\"purple\">must</strong> not have the <code>VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT</code> flag set."
+          "text": " If a <a href=\"#VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT\">VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT</a> structure is included in the <code>pNext</code> chain, <code>flags</code> <strong class=\"purple\">must</strong> not have the <code>VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT</code> flag set"
         },
         {
           "vuid": "VUID-VkPipelineShaderStageCreateInfo-pNext-02755",
-          "text": " If a <a href=\"#VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT\">VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT</a> structure is included in the <code>pNext</code> chain, the <a href=\"#features-subgroupSizeControl\"><code>subgroupSizeControl</code></a> feature <strong class=\"purple\">must</strong> be enabled, and <code>stage</code> <strong class=\"purple\">must</strong> be a valid bit specified in <a href=\"#limits-required-subgroup-size-stages\"><code>requiredSubgroupSizeStages</code></a>."
+          "text": " If a <a href=\"#VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT\">VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT</a> structure is included in the <code>pNext</code> chain, the <a href=\"#features-subgroupSizeControl\"><code>subgroupSizeControl</code></a> feature <strong class=\"purple\">must</strong> be enabled, and <code>stage</code> <strong class=\"purple\">must</strong> be a valid bit specified in <a href=\"#limits-required-subgroup-size-stages\"><code>requiredSubgroupSizeStages</code></a>"
         },
         {
           "vuid": "VUID-VkPipelineShaderStageCreateInfo-pNext-02756",
-          "text": " If a <a href=\"#VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT\">VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT</a> structure is included in the <code>pNext</code> chain and <code>stage</code> is <code>VK_SHADER_STAGE_COMPUTE_BIT</code>, the local workgroup size of the shader <strong class=\"purple\">must</strong> be less than or equal to the product of <a href=\"#VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT\">VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT</a>::<code>requiredSubgroupSize</code> and <a href=\"#limits-max-subgroups-per-workgroup\"><code>maxComputeWorkgroupSubgroups</code></a>."
+          "text": " If a <a href=\"#VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT\">VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT</a> structure is included in the <code>pNext</code> chain and <code>stage</code> is <code>VK_SHADER_STAGE_COMPUTE_BIT</code>, the local workgroup size of the shader <strong class=\"purple\">must</strong> be less than or equal to the product of <a href=\"#VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT\">VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT</a>::<code>requiredSubgroupSize</code> and <a href=\"#limits-max-subgroups-per-workgroup\"><code>maxComputeWorkgroupSubgroups</code></a>"
         },
         {
           "vuid": "VUID-VkPipelineShaderStageCreateInfo-pNext-02757",
-          "text": " If a <a href=\"#VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT\">VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT</a> structure is included in the <code>pNext</code> chain, and <code>flags</code> has the <code>VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT</code> flag set, the local workgroup size in the X dimension of the pipeline <strong class=\"purple\">must</strong> be a multiple of <a href=\"#VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT\">VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT</a>::<code>requiredSubgroupSize</code>."
+          "text": " If a <a href=\"#VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT\">VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT</a> structure is included in the <code>pNext</code> chain, and <code>flags</code> has the <code>VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT</code> flag set, the local workgroup size in the X dimension of the pipeline <strong class=\"purple\">must</strong> be a multiple of <a href=\"#VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT\">VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT</a>::<code>requiredSubgroupSize</code>"
         },
         {
           "vuid": "VUID-VkPipelineShaderStageCreateInfo-flags-02758",
-          "text": " If <code>flags</code> has both the <code>VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT</code> and <code>VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT</code> flags set, the local workgroup size in the X dimension of the pipeline <strong class=\"purple\">must</strong> be a multiple of <a href=\"#limits-max-subgroup-size\"><code>maxSubgroupSize</code></a>."
+          "text": " If <code>flags</code> has both the <code>VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT</code> and <code>VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT</code> flags set, the local workgroup size in the X dimension of the pipeline <strong class=\"purple\">must</strong> be a multiple of <a href=\"#limits-max-subgroup-size\"><code>maxSubgroupSize</code></a>"
         },
         {
           "vuid": "VUID-VkPipelineShaderStageCreateInfo-flags-02759",
-          "text": " If <code>flags</code> has the <code>VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT</code> flag set and <code>flags</code> does not have the <code>VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT</code> flag set and no <a href=\"#VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT\">VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT</a> structure is included in the <code>pNext</code> chain, the local workgroup size in the X dimension of the pipeline <strong class=\"purple\">must</strong> be a multiple of <a href=\"#limits-subgroup-size\"><code>subgroupSize</code></a>."
+          "text": " If <code>flags</code> has the <code>VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT</code> flag set and <code>flags</code> does not have the <code>VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT</code> flag set and no <a href=\"#VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT\">VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT</a> structure is included in the <code>pNext</code> chain, the local workgroup size in the X dimension of the pipeline <strong class=\"purple\">must</strong> be a multiple of <a href=\"#limits-subgroup-size\"><code>subgroupSize</code></a>"
         }
       ]
     },
@@ -6250,15 +6298,15 @@
       "(VK_EXT_subgroup_size_control)": [
         {
           "vuid": "VUID-VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT-requiredSubgroupSize-02760",
-          "text": " <code>requiredSubgroupSize</code> <strong class=\"purple\">must</strong> be a power-of-two integer."
+          "text": " <code>requiredSubgroupSize</code> <strong class=\"purple\">must</strong> be a power-of-two integer"
         },
         {
           "vuid": "VUID-VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT-requiredSubgroupSize-02761",
-          "text": " <code>requiredSubgroupSize</code> <strong class=\"purple\">must</strong> be greater or equal to <a href=\"#limits-min-subgroup-size\">minSubgroupSize</a>."
+          "text": " <code>requiredSubgroupSize</code> <strong class=\"purple\">must</strong> be greater or equal to <a href=\"#limits-min-subgroup-size\">minSubgroupSize</a>"
         },
         {
           "vuid": "VUID-VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT-requiredSubgroupSize-02762",
-          "text": " <code>requiredSubgroupSize</code> <strong class=\"purple\">must</strong> be less than or equal to <a href=\"#limits-max-subgroup-size\">maxSubgroupSize</a>."
+          "text": " <code>requiredSubgroupSize</code> <strong class=\"purple\">must</strong> be less than or equal to <a href=\"#limits-max-subgroup-size\">maxSubgroupSize</a>"
         },
         {
           "vuid": "VUID-VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT-sType-sType",
@@ -6304,6 +6352,12 @@
           "vuid": "VUID-vkCreateGraphicsPipelines-pipelineCache-parent",
           "text": " If <code>pipelineCache</code> is a valid handle, it <strong class=\"purple\">must</strong> have been created, allocated, or retrieved from <code>device</code>"
         }
+      ],
+      "(VK_EXT_pipeline_creation_cache_control)": [
+        {
+          "vuid": "VUID-vkCreateGraphicsPipelines-pipelineCache-02876",
+          "text": " If <code>pipelineCache</code> was created with <code>VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT_EXT</code>, host access to <code>pipelineCache</code> <strong class=\"purple\">must</strong> be <a href=\"#fundamentals-threadingbehavior\">externally synchronized</a>"
+        }
       ]
     },
     "VkGraphicsPipelineCreateInfo": {
@@ -6342,7 +6396,7 @@
         },
         {
           "vuid": "VUID-VkGraphicsPipelineCreateInfo-pStages-00731",
-          "text": " If <code>pStages</code> includes a tessellation control shader stage and a tessellation evaluation shader stage, <code>pTessellationState</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <code>VkPipelineTessellationStateCreateInfo</code> structure"
+          "text": " If <code>pStages</code> includes a tessellation control shader stage and a tessellation evaluation shader stage, <code>pTessellationState</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkPipelineTessellationStateCreateInfo\">VkPipelineTessellationStateCreateInfo</a> structure"
         },
         {
           "vuid": "VUID-VkGraphicsPipelineCreateInfo-pStages-00732",
@@ -6390,7 +6444,7 @@
         },
         {
           "vuid": "VUID-VkGraphicsPipelineCreateInfo-blendEnable-02023",
-          "text": " If rasterization is not disabled and the subpass uses color attachments, then for each color attachment in the subpass the <code>blendEnable</code> member of the corresponding element of the <code>pAttachment</code> member of <code>pColorBlendState</code> <strong class=\"purple\">must</strong> be <code>VK_FALSE</code> if the attached image&#8217;s <a href=\"#resources-image-format-features\">format features</a> does not contain <code>VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT</code>."
+          "text": " If rasterization is not disabled and the subpass uses color attachments, then for each color attachment in the subpass the <code>blendEnable</code> member of the corresponding element of the <code>pAttachment</code> member of <code>pColorBlendState</code> <strong class=\"purple\">must</strong> be <code>VK_FALSE</code> if the attached image&#8217;s <a href=\"#resources-image-format-features\">format features</a> does not contain <code>VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT</code>"
         },
         {
           "vuid": "VUID-VkGraphicsPipelineCreateInfo-attachmentCount-00746",
@@ -6410,19 +6464,19 @@
         },
         {
           "vuid": "VUID-VkGraphicsPipelineCreateInfo-rasterizerDiscardEnable-00750",
-          "text": " If the <code>rasterizerDiscardEnable</code> member of <code>pRasterizationState</code> is <code>VK_FALSE</code>, <code>pViewportState</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <code>VkPipelineViewportStateCreateInfo</code> structure"
+          "text": " If the <code>rasterizerDiscardEnable</code> member of <code>pRasterizationState</code> is <code>VK_FALSE</code>, <code>pViewportState</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkPipelineViewportStateCreateInfo\">VkPipelineViewportStateCreateInfo</a> structure"
         },
         {
           "vuid": "VUID-VkGraphicsPipelineCreateInfo-rasterizerDiscardEnable-00751",
-          "text": " If the <code>rasterizerDiscardEnable</code> member of <code>pRasterizationState</code> is <code>VK_FALSE</code>, <code>pMultisampleState</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <code>VkPipelineMultisampleStateCreateInfo</code> structure"
+          "text": " If the <code>rasterizerDiscardEnable</code> member of <code>pRasterizationState</code> is <code>VK_FALSE</code>, <code>pMultisampleState</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkPipelineMultisampleStateCreateInfo\">VkPipelineMultisampleStateCreateInfo</a> structure"
         },
         {
           "vuid": "VUID-VkGraphicsPipelineCreateInfo-rasterizerDiscardEnable-00752",
-          "text": " If the <code>rasterizerDiscardEnable</code> member of <code>pRasterizationState</code> is <code>VK_FALSE</code>, and <code>subpass</code> uses a depth/stencil attachment, <code>pDepthStencilState</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <code>VkPipelineDepthStencilStateCreateInfo</code> structure"
+          "text": " If the <code>rasterizerDiscardEnable</code> member of <code>pRasterizationState</code> is <code>VK_FALSE</code>, and <code>subpass</code> uses a depth/stencil attachment, <code>pDepthStencilState</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkPipelineDepthStencilStateCreateInfo\">VkPipelineDepthStencilStateCreateInfo</a> structure"
         },
         {
           "vuid": "VUID-VkGraphicsPipelineCreateInfo-rasterizerDiscardEnable-00753",
-          "text": " If the <code>rasterizerDiscardEnable</code> member of <code>pRasterizationState</code> is <code>VK_FALSE</code>, and <code>subpass</code> uses color attachments, <code>pColorBlendState</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <code>VkPipelineColorBlendStateCreateInfo</code> structure"
+          "text": " If the <code>rasterizerDiscardEnable</code> member of <code>pRasterizationState</code> is <code>VK_FALSE</code>, and <code>subpass</code> uses color attachments, <code>pColorBlendState</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkPipelineColorBlendStateCreateInfo\">VkPipelineColorBlendStateCreateInfo</a> structure"
         },
         {
           "vuid": "VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00754",
@@ -6462,7 +6516,7 @@
         },
         {
           "vuid": "VUID-VkGraphicsPipelineCreateInfo-pNext-pNext",
-          "text": " Each <code>pNext</code> member of any structure (including this one) in the <code>pNext</code> chain <strong class=\"purple\">must</strong> be either <code>NULL</code> or a pointer to a valid instance of <a href=\"#VkPipelineCompilerControlCreateInfoAMD\">VkPipelineCompilerControlCreateInfoAMD</a>, <a href=\"#VkPipelineCreationFeedbackCreateInfoEXT\">VkPipelineCreationFeedbackCreateInfoEXT</a>, <a href=\"#VkPipelineDiscardRectangleStateCreateInfoEXT\">VkPipelineDiscardRectangleStateCreateInfoEXT</a>, or <a href=\"#VkPipelineRepresentativeFragmentTestStateCreateInfoNV\">VkPipelineRepresentativeFragmentTestStateCreateInfoNV</a>"
+          "text": " Each <code>pNext</code> member of any structure (including this one) in the <code>pNext</code> chain <strong class=\"purple\">must</strong> be either <code>NULL</code> or a pointer to a valid instance of <a href=\"#VkGraphicsPipelineShaderGroupsCreateInfoNV\">VkGraphicsPipelineShaderGroupsCreateInfoNV</a>, <a href=\"#VkPipelineCompilerControlCreateInfoAMD\">VkPipelineCompilerControlCreateInfoAMD</a>, <a href=\"#VkPipelineCreationFeedbackCreateInfoEXT\">VkPipelineCreationFeedbackCreateInfoEXT</a>, <a href=\"#VkPipelineDiscardRectangleStateCreateInfoEXT\">VkPipelineDiscardRectangleStateCreateInfoEXT</a>, or <a href=\"#VkPipelineRepresentativeFragmentTestStateCreateInfoNV\">VkPipelineRepresentativeFragmentTestStateCreateInfoNV</a>"
         },
         {
           "vuid": "VUID-VkGraphicsPipelineCreateInfo-sType-unique",
@@ -6510,11 +6564,11 @@
       "(VK_NV_mesh_shader)": [
         {
           "vuid": "VUID-VkGraphicsPipelineCreateInfo-pStages-02095",
-          "text": " The geometric shader stages provided in <code>pStages</code> <strong class=\"purple\">must</strong> be either from the mesh shading pipeline (<code>stage</code> is <code>VK_SHADER_STAGE_TASK_BIT_NV</code> or <code>VK_SHADER_STAGE_MESH_BIT_NV</code>) or from the primitive shading pipeline (<code>stage</code> is <code>VK_SHADER_STAGE_VERTEX_BIT</code>, <code>VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT</code>, <code>VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT</code>, or <code>VK_SHADER_STAGE_GEOMETRY_BIT</code>)."
+          "text": " The geometric shader stages provided in <code>pStages</code> <strong class=\"purple\">must</strong> be either from the mesh shading pipeline (<code>stage</code> is <code>VK_SHADER_STAGE_TASK_BIT_NV</code> or <code>VK_SHADER_STAGE_MESH_BIT_NV</code>) or from the primitive shading pipeline (<code>stage</code> is <code>VK_SHADER_STAGE_VERTEX_BIT</code>, <code>VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT</code>, <code>VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT</code>, or <code>VK_SHADER_STAGE_GEOMETRY_BIT</code>)"
         },
         {
           "vuid": "VUID-VkGraphicsPipelineCreateInfo-stage-02096",
-          "text": " The <code>stage</code> member of one element of <code>pStages</code> <strong class=\"purple\">must</strong> be either <code>VK_SHADER_STAGE_VERTEX_BIT</code> or <code>VK_SHADER_STAGE_MESH_BIT_NV</code>."
+          "text": " The <code>stage</code> member of one element of <code>pStages</code> <strong class=\"purple\">must</strong> be either <code>VK_SHADER_STAGE_VERTEX_BIT</code> or <code>VK_SHADER_STAGE_MESH_BIT_NV</code>"
         }
       ],
       "!(VK_VERSION_1_1,VK_KHR_maintenance2)": [
@@ -6535,10 +6589,6 @@
         {
           "vuid": "VUID-VkGraphicsPipelineCreateInfo-subpass-01757",
           "text": " If rasterization is not disabled and <code>subpass</code> uses a depth/stencil attachment in <code>renderPass</code> that has a layout of <code>VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL</code> or <code>VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL</code> in the <code>VkAttachmentReference</code> defined by <code>subpass</code>, the <code>failOp</code>, <code>passOp</code> and <code>depthFailOp</code> members of each of the <code>front</code> and <code>back</code> members of <code>pDepthStencilState</code> <strong class=\"purple\">must</strong> be <code>VK_STENCIL_OP_KEEP</code>"
-        },
-        {
-          "vuid": "VUID-VkGraphicsPipelineCreateInfo-pStages-01565",
-          "text": " If <code>pStages</code> includes a fragment shader stage and an input attachment was referenced by the <a href=\"#VkRenderPassInputAttachmentAspectCreateInfo\">VkRenderPassInputAttachmentAspectCreateInfo</a> at <code>renderPass</code> create time, its shader code <strong class=\"purple\">must</strong> not read from any aspect that was not specified in the <code>aspectMask</code> of the corresponding <a href=\"#VkInputAttachmentAspectReference\">VkInputAttachmentAspectReference</a> structure."
         }
       ],
       "!(VK_EXT_depth_range_unrestricted)": [
@@ -6596,11 +6646,11 @@
       "(VK_VERSION_1_1,VK_KHR_multiview)": [
         {
           "vuid": "VUID-VkGraphicsPipelineCreateInfo-renderPass-00760",
-          "text": " If the <code>renderPass</code> has multiview enabled and <code>subpass</code> has more than one bit set in the view mask and <code>multiviewTessellationShader</code> is not enabled, then <code>pStages</code> <strong class=\"purple\">must</strong> not include tessellation shaders."
+          "text": " If the <code>renderPass</code> has multiview enabled and <code>subpass</code> has more than one bit set in the view mask and <code>multiviewTessellationShader</code> is not enabled, then <code>pStages</code> <strong class=\"purple\">must</strong> not include tessellation shaders"
         },
         {
           "vuid": "VUID-VkGraphicsPipelineCreateInfo-renderPass-00761",
-          "text": " If the <code>renderPass</code> has multiview enabled and <code>subpass</code> has more than one bit set in the view mask and <code>multiviewGeometryShader</code> is not enabled, then <code>pStages</code> <strong class=\"purple\">must</strong> not include a geometry shader."
+          "text": " If the <code>renderPass</code> has multiview enabled and <code>subpass</code> has more than one bit set in the view mask and <code>multiviewGeometryShader</code> is not enabled, then <code>pStages</code> <strong class=\"purple\">must</strong> not include a geometry shader"
         },
         {
           "vuid": "VUID-VkGraphicsPipelineCreateInfo-renderPass-00762",
@@ -6608,13 +6658,19 @@
         },
         {
           "vuid": "VUID-VkGraphicsPipelineCreateInfo-renderPass-00763",
-          "text": " If the <code>renderPass</code> has multiview enabled, then all shaders <strong class=\"purple\">must</strong> not include variables decorated with the <code>Layer</code> built-in decoration in their interfaces."
+          "text": " If the <code>renderPass</code> has multiview enabled, then all shaders <strong class=\"purple\">must</strong> not include variables decorated with the <code>Layer</code> built-in decoration in their interfaces"
         }
       ],
       "(VK_VERSION_1_1,VK_KHR_device_group)": [
         {
           "vuid": "VUID-VkGraphicsPipelineCreateInfo-flags-00764",
-          "text": " <code>flags</code> <strong class=\"purple\">must</strong> not contain the <code>VK_PIPELINE_CREATE_DISPATCH_BASE</code> flag."
+          "text": " <code>flags</code> <strong class=\"purple\">must</strong> not contain the <code>VK_PIPELINE_CREATE_DISPATCH_BASE</code> flag"
+        }
+      ],
+      "(VK_VERSION_1_1,VK_KHR_maintenance2,VK_KHR_create_renderpass2)": [
+        {
+          "vuid": "VUID-VkGraphicsPipelineCreateInfo-pStages-01565",
+          "text": " If <code>pStages</code> includes a fragment shader stage and an input attachment was referenced by an <code>aspectMask</code> at <code>renderPass</code> creation time, its shader code <strong class=\"purple\">must</strong> only read from the aspects that were specified for that input attachment"
         }
       ],
       "(VK_NV_clip_space_w_scaling)": [
@@ -6634,11 +6690,11 @@
         },
         {
           "vuid": "VUID-VkGraphicsPipelineCreateInfo-rasterizationStream-02319",
-          "text": " If a <code>VkPipelineRasterizationStateStreamCreateInfoEXT</code>::<code>rasterizationStream</code> value other than zero is specified, all variables in the output interface of the entry point being compiled decorated with <code>Position</code>, <code>PointSize</code>, <code>ClipDistance</code>, or <code>CullDistance</code> <strong class=\"purple\">must</strong> all be decorated with identical <code>Stream</code> values that match the <code>rasterizationStream</code>"
+          "text": " If a <a href=\"#VkPipelineRasterizationStateStreamCreateInfoEXT\">VkPipelineRasterizationStateStreamCreateInfoEXT</a>::<code>rasterizationStream</code> value other than zero is specified, all variables in the output interface of the entry point being compiled decorated with <code>Position</code>, <code>PointSize</code>, <code>ClipDistance</code>, or <code>CullDistance</code> <strong class=\"purple\">must</strong> all be decorated with identical <code>Stream</code> values that match the <code>rasterizationStream</code>"
         },
         {
           "vuid": "VUID-VkGraphicsPipelineCreateInfo-rasterizationStream-02320",
-          "text": " If <code>VkPipelineRasterizationStateStreamCreateInfoEXT</code>::<code>rasterizationStream</code> is zero, or not specified, all variables in the output interface of the entry point being compiled decorated with <code>Position</code>, <code>PointSize</code>, <code>ClipDistance</code>, or <code>CullDistance</code> <strong class=\"purple\">must</strong> all be decorated with a <code>Stream</code> value of zero, or <strong class=\"purple\">must</strong> not specify the <code>Stream</code> decoration"
+          "text": " If <a href=\"#VkPipelineRasterizationStateStreamCreateInfoEXT\">VkPipelineRasterizationStateStreamCreateInfoEXT</a>::<code>rasterizationStream</code> is zero, or not specified, all variables in the output interface of the entry point being compiled decorated with <code>Position</code>, <code>PointSize</code>, <code>ClipDistance</code>, or <code>CullDistance</code> <strong class=\"purple\">must</strong> all be decorated with a <code>Stream</code> value of zero, or <strong class=\"purple\">must</strong> not specify the <code>Stream</code> decoration"
         },
         {
           "vuid": "VUID-VkGraphicsPipelineCreateInfo-geometryStreams-02321",
@@ -6648,7 +6704,7 @@
       "(VK_EXT_transform_feedback)+(VK_NV_mesh_shader)": [
         {
           "vuid": "VUID-VkGraphicsPipelineCreateInfo-None-02322",
-          "text": " If there are any mesh shader stages in the pipeline there <strong class=\"purple\">must</strong> not be any shader stage in the pipeline with a <code>Xfb</code> execution mode."
+          "text": " If there are any mesh shader stages in the pipeline there <strong class=\"purple\">must</strong> not be any shader stage in the pipeline with a <code>Xfb</code> execution mode"
         }
       ],
       "(VK_EXT_line_rasterization)": [
@@ -6660,6 +6716,56 @@
           "vuid": "VUID-VkGraphicsPipelineCreateInfo-stippledLineEnable-02767",
           "text": " If the <code>stippledLineEnable</code> member of <a href=\"#VkPipelineRasterizationLineStateCreateInfoEXT\">VkPipelineRasterizationLineStateCreateInfoEXT</a> is <code>VK_TRUE</code> and no element of the <code>pDynamicStates</code> member of <code>pDynamicState</code> is <code>VK_DYNAMIC_STATE_LINE_STIPPLE_EXT</code>, then the <code>lineStippleFactor</code> member of <a href=\"#VkPipelineRasterizationLineStateCreateInfoEXT\">VkPipelineRasterizationLineStateCreateInfoEXT</a> <strong class=\"purple\">must</strong> be in the range <span class=\"eq\">[1,256]</span>"
         }
+      ],
+      "(VK_KHR_pipeline_library)": [
+        {
+          "vuid": "VUID-VkGraphicsPipelineCreateInfo-flags-03371",
+          "text": " <code>flags</code> <strong class=\"purple\">must</strong> not include <code>VK_PIPELINE_CREATE_LIBRARY_BIT_KHR</code>"
+        }
+      ],
+      "(VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-VkGraphicsPipelineCreateInfo-flags-03372",
+          "text": " <code>flags</code> <strong class=\"purple\">must</strong> not include <code>VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_ANY_HIT_SHADERS_BIT_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkGraphicsPipelineCreateInfo-flags-03373",
+          "text": " <code>flags</code> <strong class=\"purple\">must</strong> not include <code>VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_CLOSEST_HIT_SHADERS_BIT_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkGraphicsPipelineCreateInfo-flags-03374",
+          "text": " <code>flags</code> <strong class=\"purple\">must</strong> not include <code>VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_MISS_SHADERS_BIT_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkGraphicsPipelineCreateInfo-flags-03375",
+          "text": " <code>flags</code> <strong class=\"purple\">must</strong> not include <code>VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_INTERSECTION_SHADERS_BIT_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkGraphicsPipelineCreateInfo-flags-03376",
+          "text": " <code>flags</code> <strong class=\"purple\">must</strong> not include <code>VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkGraphicsPipelineCreateInfo-flags-03377",
+          "text": " <code>flags</code> <strong class=\"purple\">must</strong> not include <code>VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR</code>"
+        }
+      ],
+      "(VK_NV_device_generated_commands)": [
+        {
+          "vuid": "VUID-VkGraphicsPipelineCreateInfo-flags-02877",
+          "text": " If <code>flags</code> includes <code>VK_PIPELINE_CREATE_INDIRECT_BINDABLE_BIT_NV</code>, then the <a href=\"#feature-device-generated-commands\"><code>VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV</code>::<code>deviceGeneratedCommands</code></a> feature <strong class=\"purple\">must</strong> be enabled"
+        }
+      ],
+      "(VK_NV_device_generated_commands)+(VK_EXT_transform_feedback)": [
+        {
+          "vuid": "VUID-VkGraphicsPipelineCreateInfo-flags-02966",
+          "text": " If <code>flags</code> includes <code>VK_PIPELINE_CREATE_INDIRECT_BINDABLE_BIT_NV</code>, then all stages <strong class=\"purple\">must</strong> not specify <code>Xfb</code> execution mode"
+        }
+      ],
+      "(VK_EXT_pipeline_creation_cache_control)": [
+        {
+          "vuid": "VUID-VkGraphicsPipelineCreateInfo-pipelineCreationCacheControl-02878",
+          "text": " If the <a href=\"#features-pipelineCreationCacheControl\"><code>pipelineCreationCacheControl</code></a> feature is not enabled, <code>flags</code> <strong class=\"purple\">must</strong> not include <code>VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_EXT</code> or <code>VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT_EXT</code>"
+        }
       ]
     },
     "VkPipelineDynamicStateCreateInfo": {
@@ -6686,6 +6792,102 @@
         }
       ]
     },
+    "VkGraphicsPipelineShaderGroupsCreateInfoNV": {
+      "(VK_NV_device_generated_commands)": [
+        {
+          "vuid": "VUID-VkGraphicsPipelineShaderGroupsCreateInfoNV-groupCount-02879",
+          "text": " <code>groupCount</code> <strong class=\"purple\">must</strong> be at least <code>1</code> and as maximum <code>VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV</code>::<code>maxGraphicsShaderGroupCount</code>"
+        },
+        {
+          "vuid": "VUID-VkGraphicsPipelineShaderGroupsCreateInfoNV-groupCount-02880",
+          "text": " The sum of <code>groupCount</code> including those groups added from referenced <code>pPipelines</code> <strong class=\"purple\">must</strong> also be as maximum <code>VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV</code>::<code>maxGraphicsShaderGroupCount</code>"
+        },
+        {
+          "vuid": "VUID-VkGraphicsPipelineShaderGroupsCreateInfoNV-pGroups-02881",
+          "text": " The state of the first element of <code>pGroups</code> must match its equivalent within the parent&#8217;s <a href=\"#VkGraphicsPipelineCreateInfo\">VkGraphicsPipelineCreateInfo</a>"
+        },
+        {
+          "vuid": "VUID-VkGraphicsPipelineShaderGroupsCreateInfoNV-pGroups-02882",
+          "text": " Each element of <code>pGroups</code> <strong class=\"purple\">must</strong> in combination with the rest of the pipeline state yield a valid state configuration"
+        },
+        {
+          "vuid": "VUID-VkGraphicsPipelineShaderGroupsCreateInfoNV-pPipelines-02886",
+          "text": " Each element of the <code>pPipelines</code> member of <code>libraries</code> <strong class=\"purple\">must</strong> have been created with identical state to the pipeline currently created except the state that can be overriden by <a href=\"#VkGraphicsShaderGroupCreateInfoNV\">VkGraphicsShaderGroupCreateInfoNV</a>"
+        },
+        {
+          "vuid": "VUID-VkGraphicsPipelineShaderGroupsCreateInfoNV-deviceGeneratedCommands-02887",
+          "text": " The <a href=\"#feature-device-generated-commands\"><code>VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV</code>::<code>deviceGeneratedCommands</code></a> feature <strong class=\"purple\">must</strong> be enabled"
+        },
+        {
+          "vuid": "VUID-VkGraphicsPipelineShaderGroupsCreateInfoNV-sType-sType",
+          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_SHADER_GROUPS_CREATE_INFO_NV</code>"
+        },
+        {
+          "vuid": "VUID-VkGraphicsPipelineShaderGroupsCreateInfoNV-pGroups-parameter",
+          "text": " <code>pGroups</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>groupCount</code> valid <a href=\"#VkGraphicsShaderGroupCreateInfoNV\">VkGraphicsShaderGroupCreateInfoNV</a> structures"
+        },
+        {
+          "vuid": "VUID-VkGraphicsPipelineShaderGroupsCreateInfoNV-pPipelines-parameter",
+          "text": " If <code>pipelineCount</code> is not <code>0</code>, <code>pPipelines</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>pipelineCount</code> valid <a href=\"#VkPipeline\">VkPipeline</a> handles"
+        },
+        {
+          "vuid": "VUID-VkGraphicsPipelineShaderGroupsCreateInfoNV-groupCount-arraylength",
+          "text": " <code>groupCount</code> <strong class=\"purple\">must</strong> be greater than <code>0</code>"
+        }
+      ],
+      "(VK_NV_device_generated_commands)+!(VK_NV_mesh_shader)": [
+        {
+          "vuid": "VUID-VkGraphicsPipelineShaderGroupsCreateInfoNV-pGroups-02883",
+          "text": " All elements of <code>pGroups</code> <strong class=\"purple\">must</strong> use the same shader stage combinations"
+        }
+      ],
+      "(VK_NV_device_generated_commands)+(VK_NV_mesh_shader)": [
+        {
+          "vuid": "VUID-VkGraphicsPipelineShaderGroupsCreateInfoNV-pGroups-02884",
+          "text": " All elements of <code>pGroups</code> <strong class=\"purple\">must</strong> use the same shader stage combinations unless any mesh shader stage is used, then either combination of task and mesh or just mesh shader is valid"
+        },
+        {
+          "vuid": "VUID-VkGraphicsPipelineShaderGroupsCreateInfoNV-pGroups-02885",
+          "text": " Mesh and regular primitive shading stages cannot be mixed across <code>pGroups</code>"
+        }
+      ]
+    },
+    "VkGraphicsShaderGroupCreateInfoNV": {
+      "(VK_NV_device_generated_commands)": [
+        {
+          "vuid": "VUID-VkGraphicsShaderGroupCreateInfoNV-stageCount-02888",
+          "text": " For <code>stageCount</code>, the same restrictions as in <a href=\"#VkGraphicsPipelineCreateInfo\">VkGraphicsPipelineCreateInfo</a>::<code>stageCount</code> apply"
+        },
+        {
+          "vuid": "VUID-VkGraphicsShaderGroupCreateInfoNV-pStages-02889",
+          "text": " For <code>pStages</code>, the same restrictions as in <a href=\"#VkGraphicsPipelineCreateInfo\">VkGraphicsPipelineCreateInfo</a>::<code>pStages</code> apply"
+        },
+        {
+          "vuid": "VUID-VkGraphicsShaderGroupCreateInfoNV-pVertexInputState-02890",
+          "text": " For <code>pVertexInputState</code>, the same restrictions as in <a href=\"#VkGraphicsPipelineCreateInfo\">VkGraphicsPipelineCreateInfo</a>::<code>pVertexInputState</code> apply"
+        },
+        {
+          "vuid": "VUID-VkGraphicsShaderGroupCreateInfoNV-pTessellationState-02891",
+          "text": " For <code>pTessellationState</code>, the same restrictions as in <a href=\"#VkGraphicsPipelineCreateInfo\">VkGraphicsPipelineCreateInfo</a>::<code>pTessellationState</code> apply"
+        },
+        {
+          "vuid": "VUID-VkGraphicsShaderGroupCreateInfoNV-sType-sType",
+          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_GRAPHICS_SHADER_GROUP_CREATE_INFO_NV</code>"
+        },
+        {
+          "vuid": "VUID-VkGraphicsShaderGroupCreateInfoNV-pNext-pNext",
+          "text": " <code>pNext</code> <strong class=\"purple\">must</strong> be <code>NULL</code>"
+        },
+        {
+          "vuid": "VUID-VkGraphicsShaderGroupCreateInfoNV-pStages-parameter",
+          "text": " <code>pStages</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>stageCount</code> valid <a href=\"#VkPipelineShaderStageCreateInfo\">VkPipelineShaderStageCreateInfo</a> structures"
+        },
+        {
+          "vuid": "VUID-VkGraphicsShaderGroupCreateInfoNV-stageCount-arraylength",
+          "text": " <code>stageCount</code> <strong class=\"purple\">must</strong> be greater than <code>0</code>"
+        }
+      ]
+    },
     "vkDestroyPipeline": {
       "core": [
         {
@@ -6757,13 +6959,19 @@
           "text": " <code>pNext</code> <strong class=\"purple\">must</strong> be <code>NULL</code>"
         },
         {
-          "vuid": "VUID-VkPipelineCacheCreateInfo-flags-zerobitmask",
-          "text": " <code>flags</code> <strong class=\"purple\">must</strong> be <code>0</code>"
+          "vuid": "VUID-VkPipelineCacheCreateInfo-flags-parameter",
+          "text": " <code>flags</code> <strong class=\"purple\">must</strong> be a valid combination of <a href=\"#VkPipelineCacheCreateFlagBits\">VkPipelineCacheCreateFlagBits</a> values"
         },
         {
           "vuid": "VUID-VkPipelineCacheCreateInfo-pInitialData-parameter",
           "text": " If <code>initialDataSize</code> is not <code>0</code>, <code>pInitialData</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>initialDataSize</code> bytes"
         }
+      ],
+      "(VK_EXT_pipeline_creation_cache_control)": [
+        {
+          "vuid": "VUID-VkPipelineCacheCreateInfo-pipelineCreationCacheControl-02892",
+          "text": " If the <a href=\"#features-pipelineCreationCacheControl\"><code>pipelineCreationCacheControl</code></a> feature is not enabled, <code>flags</code> <strong class=\"purple\">must</strong> not include <code>VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT_EXT</code>"
+        }
       ]
     },
     "vkMergePipelineCaches": {
@@ -6878,6 +7086,26 @@
         }
       ]
     },
+    "VkPipelineLibraryCreateInfoKHR": {
+      "(VK_KHR_pipeline_library)": [
+        {
+          "vuid": "VUID-VkPipelineLibraryCreateInfoKHR-pLibraries-03381",
+          "text": " Each element of <code>pLibraries</code> <strong class=\"purple\">must</strong> have been created with <code>VK_PIPELINE_CREATE_LIBRARY_BIT_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkPipelineLibraryCreateInfoKHR-sType-sType",
+          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkPipelineLibraryCreateInfoKHR-pNext-pNext",
+          "text": " <code>pNext</code> <strong class=\"purple\">must</strong> be <code>NULL</code>"
+        },
+        {
+          "vuid": "VUID-VkPipelineLibraryCreateInfoKHR-pLibraries-parameter",
+          "text": " If <code>libraryCount</code> is not <code>0</code>, <code>pLibraries</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>libraryCount</code> valid <a href=\"#VkPipeline\">VkPipeline</a> handles"
+        }
+      ]
+    },
     "vkCmdBindPipeline": {
       "core": [
         {
@@ -6898,7 +7126,7 @@
         },
         {
           "vuid": "VUID-vkCmdBindPipeline-pipeline-00781",
-          "text": " If the <a href=\"#features-variableMultisampleRate\">variable multisample rate</a> feature is not supported, <code>pipeline</code> is a graphics pipeline, the current subpass has no attachments, and this is not the first call to this function with a graphics pipeline after transitioning to the current subpass, then the sample count specified by this pipeline <strong class=\"purple\">must</strong> match that set in the previous pipeline"
+          "text": " If the <a href=\"#features-variableMultisampleRate\">variable multisample rate</a> feature is not supported, <code>pipeline</code> is a graphics pipeline, the current subpass <a href=\"#renderpass-noattachments\">uses no attachments</a>, and this is not the first call to this function with a graphics pipeline after transitioning to the current subpass, then the sample count specified by this pipeline <strong class=\"purple\">must</strong> match that set in the previous pipeline"
         },
         {
           "vuid": "VUID-vkCmdBindPipeline-commandBuffer-parameter",
@@ -6937,14 +7165,64 @@
           "text": " This command <strong class=\"purple\">must</strong> not be recorded when transform feedback is active"
         }
       ],
-      "(VK_NV_ray_tracing)": [
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)": [
         {
           "vuid": "VUID-vkCmdBindPipeline-pipelineBindPoint-02391",
-          "text": " If <code>pipelineBindPoint</code> is <code>VK_PIPELINE_BIND_POINT_RAY_TRACING_NV</code>, the <code>VkCommandPool</code> that <code>commandBuffer</code> was allocated from <strong class=\"purple\">must</strong> support compute operations"
+          "text": " If <code>pipelineBindPoint</code> is <code>VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR</code>, the <code>VkCommandPool</code> that <code>commandBuffer</code> was allocated from <strong class=\"purple\">must</strong> support compute operations"
         },
         {
           "vuid": "VUID-vkCmdBindPipeline-pipelineBindPoint-02392",
-          "text": " If <code>pipelineBindPoint</code> is <code>VK_PIPELINE_BIND_POINT_RAY_TRACING_NV</code>, the <code>pipeline</code> <strong class=\"purple\">must</strong> be a ray tracing pipeline"
+          "text": " If <code>pipelineBindPoint</code> is <code>VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR</code>, the <code>pipeline</code> <strong class=\"purple\">must</strong> be a ray tracing pipeline"
+        }
+      ],
+      "(VK_KHR_pipeline_library)": [
+        {
+          "vuid": "VUID-vkCmdBindPipeline-pipeline-03382",
+          "text": " The <code>pipeline</code> <strong class=\"purple\">must</strong> not have been created with <code>VK_PIPELINE_CREATE_LIBRARY_BIT_KHR</code> set"
+        }
+      ]
+    },
+    "vkCmdBindPipelineShaderGroupNV": {
+      "(VK_NV_device_generated_commands)": [
+        {
+          "vuid": "VUID-vkCmdBindPipelineShaderGroupNV-groupIndex-02893",
+          "text": " <code>groupIndex</code> must be <code>0</code> or less than the effective <a href=\"#VkGraphicsPipelineShaderGroupsCreateInfoNV\">VkGraphicsPipelineShaderGroupsCreateInfoNV</a>::<code>groupCount</code> including the referenced pipelines"
+        },
+        {
+          "vuid": "VUID-vkCmdBindPipelineShaderGroupNV-pipelineBindPoint-02894",
+          "text": " The <code>pipelineBindPoint</code> must be <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdBindPipelineShaderGroupNV-groupIndex-02895",
+          "text": " The same restrictions as <a href=\"#vkCmdBindPipeline\">vkCmdBindPipeline</a> apply as if the bound pipeline was created only with the Shader Group from the <code>groupIndex</code> information"
+        },
+        {
+          "vuid": "VUID-vkCmdBindPipelineShaderGroupNV-deviceGeneratedCommands-02896",
+          "text": " The <a href=\"#feature-device-generated-commands\"><code>VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV</code>::<code>deviceGeneratedCommands</code></a> feature <strong class=\"purple\">must</strong> be enabled"
+        },
+        {
+          "vuid": "VUID-vkCmdBindPipelineShaderGroupNV-commandBuffer-parameter",
+          "text": " <code>commandBuffer</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkCommandBuffer\">VkCommandBuffer</a> handle"
+        },
+        {
+          "vuid": "VUID-vkCmdBindPipelineShaderGroupNV-pipelineBindPoint-parameter",
+          "text": " <code>pipelineBindPoint</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkPipelineBindPoint\">VkPipelineBindPoint</a> value"
+        },
+        {
+          "vuid": "VUID-vkCmdBindPipelineShaderGroupNV-pipeline-parameter",
+          "text": " <code>pipeline</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkPipeline\">VkPipeline</a> handle"
+        },
+        {
+          "vuid": "VUID-vkCmdBindPipelineShaderGroupNV-commandBuffer-recording",
+          "text": " <code>commandBuffer</code> <strong class=\"purple\">must</strong> be in the <a href=\"#commandbuffers-lifecycle\">recording state</a>"
+        },
+        {
+          "vuid": "VUID-vkCmdBindPipelineShaderGroupNV-commandBuffer-cmdpool",
+          "text": " The <code>VkCommandPool</code> that <code>commandBuffer</code> was allocated from <strong class=\"purple\">must</strong> support graphics, or compute operations"
+        },
+        {
+          "vuid": "VUID-vkCmdBindPipelineShaderGroupNV-commonparent",
+          "text": " Both of <code>commandBuffer</code>, and <code>pipeline</code> <strong class=\"purple\">must</strong> have been created, allocated, or retrieved from the same <a href=\"#VkDevice\">VkDevice</a>"
         }
       ]
     },
@@ -6952,11 +7230,11 @@
       "(VK_KHR_pipeline_executable_properties)": [
         {
           "vuid": "VUID-vkGetPipelineExecutablePropertiesKHR-pipelineExecutableInfo-03270",
-          "text": " <a href=\"#features-pipelineExecutableInfo\"><code>pipelineExecutableInfo</code></a> <strong class=\"purple\">must</strong> be enabled."
+          "text": " <a href=\"#features-pipelineExecutableInfo\"><code>pipelineExecutableInfo</code></a> <strong class=\"purple\">must</strong> be enabled"
         },
         {
           "vuid": "VUID-vkGetPipelineExecutablePropertiesKHR-pipeline-03271",
-          "text": " <code>pipeline</code> member of <code>pPipelineInfo</code> <strong class=\"purple\">must</strong> have been created with <code>device</code>."
+          "text": " <code>pipeline</code> member of <code>pPipelineInfo</code> <strong class=\"purple\">must</strong> have been created with <code>device</code>"
         },
         {
           "vuid": "VUID-vkGetPipelineExecutablePropertiesKHR-device-parameter",
@@ -7008,15 +7286,15 @@
       "(VK_KHR_pipeline_executable_properties)": [
         {
           "vuid": "VUID-vkGetPipelineExecutableStatisticsKHR-pipelineExecutableInfo-03272",
-          "text": " <a href=\"#features-pipelineExecutableInfo\"><code>pipelineExecutableInfo</code></a> <strong class=\"purple\">must</strong> be enabled."
+          "text": " <a href=\"#features-pipelineExecutableInfo\"><code>pipelineExecutableInfo</code></a> <strong class=\"purple\">must</strong> be enabled"
         },
         {
           "vuid": "VUID-vkGetPipelineExecutableStatisticsKHR-pipeline-03273",
-          "text": " <code>pipeline</code> member of <code>pExecutableInfo</code> <strong class=\"purple\">must</strong> have been created with <code>device</code>."
+          "text": " <code>pipeline</code> member of <code>pExecutableInfo</code> <strong class=\"purple\">must</strong> have been created with <code>device</code>"
         },
         {
           "vuid": "VUID-vkGetPipelineExecutableStatisticsKHR-pipeline-03274",
-          "text": " <code>pipeline</code> member of <code>pExecutableInfo</code> <strong class=\"purple\">must</strong> have been created with <code>VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR</code> set in the <code>flags</code> field of <a href=\"#VkGraphicsPipelineCreateInfo\">VkGraphicsPipelineCreateInfo</a> or <a href=\"#VkComputePipelineCreateInfo\">VkComputePipelineCreateInfo</a>."
+          "text": " <code>pipeline</code> member of <code>pExecutableInfo</code> <strong class=\"purple\">must</strong> have been created with <code>VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR</code> set in the <code>flags</code> field of <a href=\"#VkGraphicsPipelineCreateInfo\">VkGraphicsPipelineCreateInfo</a> or <a href=\"#VkComputePipelineCreateInfo\">VkComputePipelineCreateInfo</a>"
         },
         {
           "vuid": "VUID-vkGetPipelineExecutableStatisticsKHR-device-parameter",
@@ -7040,7 +7318,7 @@
       "(VK_KHR_pipeline_executable_properties)": [
         {
           "vuid": "VUID-VkPipelineExecutableInfoKHR-executableIndex-03275",
-          "text": " <code>executableIndex</code> <strong class=\"purple\">must</strong> be less than the number of executables associated with <code>pipeline</code> as returned in the <code>pExecutableCount</code> parameter of <code>vkGetPipelineExecutablePropertiesKHR</code>."
+          "text": " <code>executableIndex</code> <strong class=\"purple\">must</strong> be less than the number of executables associated with <code>pipeline</code> as returned in the <code>pExecutableCount</code> parameter of <code>vkGetPipelineExecutablePropertiesKHR</code>"
         },
         {
           "vuid": "VUID-VkPipelineExecutableInfoKHR-sType-sType",
@@ -7072,15 +7350,15 @@
       "(VK_KHR_pipeline_executable_properties)": [
         {
           "vuid": "VUID-vkGetPipelineExecutableInternalRepresentationsKHR-pipelineExecutableInfo-03276",
-          "text": " <a href=\"#features-pipelineExecutableInfo\"><code>pipelineExecutableInfo</code></a> <strong class=\"purple\">must</strong> be enabled."
+          "text": " <a href=\"#features-pipelineExecutableInfo\"><code>pipelineExecutableInfo</code></a> <strong class=\"purple\">must</strong> be enabled"
         },
         {
           "vuid": "VUID-vkGetPipelineExecutableInternalRepresentationsKHR-pipeline-03277",
-          "text": " <code>pipeline</code> member of <code>pExecutableInfo</code> <strong class=\"purple\">must</strong> have been created with <code>device</code>."
+          "text": " <code>pipeline</code> member of <code>pExecutableInfo</code> <strong class=\"purple\">must</strong> have been created with <code>device</code>"
         },
         {
           "vuid": "VUID-vkGetPipelineExecutableInternalRepresentationsKHR-pipeline-03278",
-          "text": " <code>pipeline</code> member of <code>pExecutableInfo</code> <strong class=\"purple\">must</strong> have been created with <code>VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR</code> set in the <code>flags</code> field of <a href=\"#VkGraphicsPipelineCreateInfo\">VkGraphicsPipelineCreateInfo</a> or <a href=\"#VkComputePipelineCreateInfo\">VkComputePipelineCreateInfo</a>."
+          "text": " <code>pipeline</code> member of <code>pExecutableInfo</code> <strong class=\"purple\">must</strong> have been created with <code>VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR</code> set in the <code>flags</code> field of <a href=\"#VkGraphicsPipelineCreateInfo\">VkGraphicsPipelineCreateInfo</a> or <a href=\"#VkComputePipelineCreateInfo\">VkComputePipelineCreateInfo</a>"
         },
         {
           "vuid": "VUID-vkGetPipelineExecutableInternalRepresentationsKHR-device-parameter",
@@ -7157,13 +7435,13 @@
       ]
     },
     "vkCreateRayTracingPipelinesNV": {
-      "(VK_NV_ray_tracing)": [
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_NV_ray_tracing)": [
         {
-          "vuid": "VUID-vkCreateRayTracingPipelinesNV-flags-02402",
+          "vuid": "VUID-vkCreateRayTracingPipelinesNV-flags-03415",
           "text": " If the <code>flags</code> member of any element of <code>pCreateInfos</code> contains the <code>VK_PIPELINE_CREATE_DERIVATIVE_BIT</code> flag, and the <code>basePipelineIndex</code> member of that same element is not <code>-1</code>, <code>basePipelineIndex</code> <strong class=\"purple\">must</strong> be less than the index into <code>pCreateInfos</code> that corresponds to that element"
         },
         {
-          "vuid": "VUID-vkCreateRayTracingPipelinesNV-flags-02403",
+          "vuid": "VUID-vkCreateRayTracingPipelinesNV-flags-03416",
           "text": " If the <code>flags</code> member of any element of <code>pCreateInfos</code> contains the <code>VK_PIPELINE_CREATE_DERIVATIVE_BIT</code> flag, the base pipeline <strong class=\"purple\">must</strong> have been created with the <code>VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT</code> flag set"
         },
         {
@@ -7194,44 +7472,100 @@
           "vuid": "VUID-vkCreateRayTracingPipelinesNV-pipelineCache-parent",
           "text": " If <code>pipelineCache</code> is a valid handle, it <strong class=\"purple\">must</strong> have been created, allocated, or retrieved from <code>device</code>"
         }
+      ],
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_NV_ray_tracing)+(VK_EXT_pipeline_creation_cache_control)": [
+        {
+          "vuid": "VUID-vkCreateRayTracingPipelinesNV-pipelineCache-02903",
+          "text": " If <code>pipelineCache</code> was created with <code>VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT_EXT</code>, host access to <code>pipelineCache</code> <strong class=\"purple\">must</strong> be <a href=\"#fundamentals-threadingbehavior\">externally synchronized</a>"
+        }
+      ]
+    },
+    "vkCreateRayTracingPipelinesKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-vkCreateRayTracingPipelinesKHR-flags-03415",
+          "text": " If the <code>flags</code> member of any element of <code>pCreateInfos</code> contains the <code>VK_PIPELINE_CREATE_DERIVATIVE_BIT</code> flag, and the <code>basePipelineIndex</code> member of that same element is not <code>-1</code>, <code>basePipelineIndex</code> <strong class=\"purple\">must</strong> be less than the index into <code>pCreateInfos</code> that corresponds to that element"
+        },
+        {
+          "vuid": "VUID-vkCreateRayTracingPipelinesKHR-flags-03416",
+          "text": " If the <code>flags</code> member of any element of <code>pCreateInfos</code> contains the <code>VK_PIPELINE_CREATE_DERIVATIVE_BIT</code> flag, the base pipeline <strong class=\"purple\">must</strong> have been created with the <code>VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT</code> flag set"
+        },
+        {
+          "vuid": "VUID-vkCreateRayTracingPipelinesKHR-rayTracing-03455",
+          "text": " The <a href=\"#features-raytracing\"><code>rayTracing</code></a> feature <strong class=\"purple\">must</strong> be enabled"
+        },
+        {
+          "vuid": "VUID-vkCreateRayTracingPipelinesKHR-device-parameter",
+          "text": " <code>device</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDevice\">VkDevice</a> handle"
+        },
+        {
+          "vuid": "VUID-vkCreateRayTracingPipelinesKHR-pipelineCache-parameter",
+          "text": " If <code>pipelineCache</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, <code>pipelineCache</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkPipelineCache\">VkPipelineCache</a> handle"
+        },
+        {
+          "vuid": "VUID-vkCreateRayTracingPipelinesKHR-pCreateInfos-parameter",
+          "text": " <code>pCreateInfos</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>createInfoCount</code> valid <a href=\"#VkRayTracingPipelineCreateInfoKHR\">VkRayTracingPipelineCreateInfoKHR</a> structures"
+        },
+        {
+          "vuid": "VUID-vkCreateRayTracingPipelinesKHR-pAllocator-parameter",
+          "text": " If <code>pAllocator</code> is not <code>NULL</code>, <code>pAllocator</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkAllocationCallbacks\">VkAllocationCallbacks</a> structure"
+        },
+        {
+          "vuid": "VUID-vkCreateRayTracingPipelinesKHR-pPipelines-parameter",
+          "text": " <code>pPipelines</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>createInfoCount</code> <a href=\"#VkPipeline\">VkPipeline</a> handles"
+        },
+        {
+          "vuid": "VUID-vkCreateRayTracingPipelinesKHR-createInfoCount-arraylength",
+          "text": " <code>createInfoCount</code> <strong class=\"purple\">must</strong> be greater than <code>0</code>"
+        },
+        {
+          "vuid": "VUID-vkCreateRayTracingPipelinesKHR-pipelineCache-parent",
+          "text": " If <code>pipelineCache</code> is a valid handle, it <strong class=\"purple\">must</strong> have been created, allocated, or retrieved from <code>device</code>"
+        }
+      ],
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)+(VK_EXT_pipeline_creation_cache_control)": [
+        {
+          "vuid": "VUID-vkCreateRayTracingPipelinesKHR-pipelineCache-02903",
+          "text": " If <code>pipelineCache</code> was created with <code>VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT_EXT</code>, host access to <code>pipelineCache</code> <strong class=\"purple\">must</strong> be <a href=\"#fundamentals-threadingbehavior\">externally synchronized</a>"
+        }
       ]
     },
     "VkRayTracingPipelineCreateInfoNV": {
-      "(VK_NV_ray_tracing)": [
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_NV_ray_tracing)": [
         {
-          "vuid": "VUID-VkRayTracingPipelineCreateInfoNV-flags-02404",
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoNV-flags-03421",
           "text": " If <code>flags</code> contains the <code>VK_PIPELINE_CREATE_DERIVATIVE_BIT</code> flag, and <code>basePipelineIndex</code> is <code>-1</code>, <code>basePipelineHandle</code> <strong class=\"purple\">must</strong> be a valid handle to a ray tracing <code>VkPipeline</code>"
         },
         {
-          "vuid": "VUID-VkRayTracingPipelineCreateInfoNV-flags-02405",
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoNV-flags-03422",
           "text": " If <code>flags</code> contains the <code>VK_PIPELINE_CREATE_DERIVATIVE_BIT</code> flag, and <code>basePipelineHandle</code> is <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, <code>basePipelineIndex</code> <strong class=\"purple\">must</strong> be a valid index into the calling command&#8217;s <code>pCreateInfos</code> parameter"
         },
         {
-          "vuid": "VUID-VkRayTracingPipelineCreateInfoNV-flags-02406",
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoNV-flags-03423",
           "text": " If <code>flags</code> contains the <code>VK_PIPELINE_CREATE_DERIVATIVE_BIT</code> flag, and <code>basePipelineIndex</code> is not <code>-1</code>, <code>basePipelineHandle</code> <strong class=\"purple\">must</strong> be <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>"
         },
         {
-          "vuid": "VUID-VkRayTracingPipelineCreateInfoNV-flags-02407",
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoNV-flags-03424",
           "text": " If <code>flags</code> contains the <code>VK_PIPELINE_CREATE_DERIVATIVE_BIT</code> flag, and <code>basePipelineHandle</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, <code>basePipelineIndex</code> <strong class=\"purple\">must</strong> be <code>-1</code>"
         },
         {
-          "vuid": "VUID-VkRayTracingPipelineCreateInfoNV-stage-02408",
-          "text": " The <code>stage</code> member of one element of <code>pStages</code> <strong class=\"purple\">must</strong> be <code>VK_SHADER_STAGE_RAYGEN_BIT_NV</code>"
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoNV-stage-03425",
+          "text": " The <code>stage</code> member of at least one element of <code>pStages</code> <strong class=\"purple\">must</strong> be <code>VK_SHADER_STAGE_RAYGEN_BIT_KHR</code>"
         },
         {
-          "vuid": "VUID-VkRayTracingPipelineCreateInfoNV-pStages-02409",
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoNV-pStages-03426",
           "text": " The shader code for the entry points identified by <code>pStages</code>, and the rest of the state identified by this structure <strong class=\"purple\">must</strong> adhere to the pipeline linking rules described in the <a href=\"#interfaces\">Shader Interfaces</a> chapter"
         },
         {
-          "vuid": "VUID-VkRayTracingPipelineCreateInfoNV-layout-02410",
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoNV-layout-03427",
           "text": " <code>layout</code> <strong class=\"purple\">must</strong> be <a href=\"#descriptorsets-pipelinelayout-consistency\">consistent</a> with all shaders specified in <code>pStages</code>"
         },
         {
-          "vuid": "VUID-VkRayTracingPipelineCreateInfoNV-layout-02411",
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoNV-layout-03428",
           "text": " The number of resources in <code>layout</code> accessible to each shader stage that is used by the pipeline <strong class=\"purple\">must</strong> be less than or equal to <a href=\"#VkPhysicalDeviceLimits\">VkPhysicalDeviceLimits</a>::<code>maxPerStageResources</code>"
         },
         {
-          "vuid": "VUID-VkRayTracingPipelineCreateInfoNV-maxRecursionDepth-02412",
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoNV-maxRecursionDepth-03457",
           "text": " <code>maxRecursionDepth</code> <strong class=\"purple\">must</strong> be less than or equal to <a href=\"#VkPhysicalDeviceRayTracingPropertiesNV\">VkPhysicalDeviceRayTracingPropertiesNV</a>::<code>maxRecursionDepth</code>"
         },
         {
@@ -7274,13 +7608,199 @@
           "vuid": "VUID-VkRayTracingPipelineCreateInfoNV-commonparent",
           "text": " Both of <code>basePipelineHandle</code>, and <code>layout</code> that are valid handles of non-ignored parameters <strong class=\"purple\">must</strong> have been created, allocated, or retrieved from the same <a href=\"#VkDevice\">VkDevice</a>"
         }
+      ],
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_NV_ray_tracing)+(VK_NV_device_generated_commands)": [
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoNV-flags-02904",
+          "text": " <code>flags</code> <strong class=\"purple\">must</strong> not include <code>VK_PIPELINE_CREATE_INDIRECT_BINDABLE_BIT_NV</code>"
+        }
+      ],
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_NV_ray_tracing)+(VK_EXT_pipeline_creation_cache_control)": [
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoNV-pipelineCreationCacheControl-02905",
+          "text": " If the <a href=\"#features-pipelineCreationCacheControl\"><code>pipelineCreationCacheControl</code></a> feature is not enabled, <code>flags</code> <strong class=\"purple\">must</strong> not include <code>VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_EXT</code> or <code>VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT_EXT</code>"
+        },
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoNV-flags-02957",
+          "text": " <code>flags</code> <strong class=\"purple\">must</strong> not include both <code>VK_PIPELINE_CREATE_DEFER_COMPILE_BIT_NV</code> and <code>VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_EXT</code> at the same time"
+        }
+      ],
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_NV_ray_tracing)+(VK_KHR_pipeline_library)": [
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoNV-flags-03456",
+          "text": " <code>flags</code> <strong class=\"purple\">must</strong> not include <code>VK_PIPELINE_CREATE_LIBRARY_BIT_KHR</code>"
+        }
+      ],
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_NV_ray_tracing)+(VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoNV-flags-03458",
+          "text": " <code>flags</code> <strong class=\"purple\">must</strong> not include <code>VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_ANY_HIT_SHADERS_BIT_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoNV-flags-03459",
+          "text": " <code>flags</code> <strong class=\"purple\">must</strong> not include <code>VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_CLOSEST_HIT_SHADERS_BIT_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoNV-flags-03460",
+          "text": " <code>flags</code> <strong class=\"purple\">must</strong> not include <code>VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_MISS_SHADERS_BIT_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoNV-flags-03461",
+          "text": " <code>flags</code> <strong class=\"purple\">must</strong> not include <code>VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_INTERSECTION_SHADERS_BIT_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoNV-flags-03462",
+          "text": " <code>flags</code> <strong class=\"purple\">must</strong> not include <code>VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoNV-flags-03463",
+          "text": " <code>flags</code> <strong class=\"purple\">must</strong> not include <code>VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR</code>"
+        }
+      ]
+    },
+    "VkRayTracingPipelineCreateInfoKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoKHR-flags-03421",
+          "text": " If <code>flags</code> contains the <code>VK_PIPELINE_CREATE_DERIVATIVE_BIT</code> flag, and <code>basePipelineIndex</code> is <code>-1</code>, <code>basePipelineHandle</code> <strong class=\"purple\">must</strong> be a valid handle to a ray tracing <code>VkPipeline</code>"
+        },
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoKHR-flags-03422",
+          "text": " If <code>flags</code> contains the <code>VK_PIPELINE_CREATE_DERIVATIVE_BIT</code> flag, and <code>basePipelineHandle</code> is <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, <code>basePipelineIndex</code> <strong class=\"purple\">must</strong> be a valid index into the calling command&#8217;s <code>pCreateInfos</code> parameter"
+        },
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoKHR-flags-03423",
+          "text": " If <code>flags</code> contains the <code>VK_PIPELINE_CREATE_DERIVATIVE_BIT</code> flag, and <code>basePipelineIndex</code> is not <code>-1</code>, <code>basePipelineHandle</code> <strong class=\"purple\">must</strong> be <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>"
+        },
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoKHR-flags-03424",
+          "text": " If <code>flags</code> contains the <code>VK_PIPELINE_CREATE_DERIVATIVE_BIT</code> flag, and <code>basePipelineHandle</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, <code>basePipelineIndex</code> <strong class=\"purple\">must</strong> be <code>-1</code>"
+        },
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoKHR-stage-03425",
+          "text": " The <code>stage</code> member of at least one element of <code>pStages</code> <strong class=\"purple\">must</strong> be <code>VK_SHADER_STAGE_RAYGEN_BIT_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoKHR-pStages-03426",
+          "text": " The shader code for the entry points identified by <code>pStages</code>, and the rest of the state identified by this structure <strong class=\"purple\">must</strong> adhere to the pipeline linking rules described in the <a href=\"#interfaces\">Shader Interfaces</a> chapter"
+        },
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoKHR-layout-03427",
+          "text": " <code>layout</code> <strong class=\"purple\">must</strong> be <a href=\"#descriptorsets-pipelinelayout-consistency\">consistent</a> with all shaders specified in <code>pStages</code>"
+        },
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoKHR-layout-03428",
+          "text": " The number of resources in <code>layout</code> accessible to each shader stage that is used by the pipeline <strong class=\"purple\">must</strong> be less than or equal to <a href=\"#VkPhysicalDeviceLimits\">VkPhysicalDeviceLimits</a>::<code>maxPerStageResources</code>"
+        },
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoKHR-maxRecursionDepth-03464",
+          "text": " <code>maxRecursionDepth</code> <strong class=\"purple\">must</strong> be less than or equal to <a href=\"#VkPhysicalDeviceRayTracingPropertiesKHR\">VkPhysicalDeviceRayTracingPropertiesKHR</a>::<code>maxRecursionDepth</code>"
+        },
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoKHR-flags-03470",
+          "text": " If <code>flags</code> includes <code>VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_ANY_HIT_SHADERS_BIT_KHR</code>, for any element of <code>pGroups</code> with a <code>type</code> of <code>VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR</code> or <code>VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR</code>, the <code>anyHitShader</code> of that element <strong class=\"purple\">must</strong> not be <code>VK_SHADER_UNUSED_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoKHR-flags-03471",
+          "text": " If <code>flags</code> includes <code>VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_CLOSEST_HIT_SHADERS_BIT_KHR</code>, for any element of <code>pGroups</code> with a <code>type</code> of <code>VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR</code> or <code>VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR</code>, the <code>closestHitShader</code> of that element <strong class=\"purple\">must</strong> not be <code>VK_SHADER_UNUSED_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoKHR-rayTracingPrimitiveCulling-03472",
+          "text": " If the <a href=\"#features-rayTracingPrimitiveCulling\"><code>rayTracingPrimitiveCulling</code></a> feature is not enabled, <code>flags</code> <strong class=\"purple\">must</strong> not include <code>VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoKHR-rayTracingPrimitiveCulling-03473",
+          "text": " If the <a href=\"#features-rayTracingPrimitiveCulling\"><code>rayTracingPrimitiveCulling</code></a> feature is not enabled, <code>flags</code> <strong class=\"purple\">must</strong> not include <code>VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoKHR-libraries-02958",
+          "text": " If <code>libraries.libraryCount</code> is zero, then <code>stageCount</code> <strong class=\"purple\">must</strong> not be zero"
+        },
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoKHR-libraries-02959",
+          "text": " If <code>libraries.libraryCount</code> is zero, then <code>groupCount</code> <strong class=\"purple\">must</strong> not be zero"
+        },
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoKHR-sType-sType",
+          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoKHR-pNext-pNext",
+          "text": " Each <code>pNext</code> member of any structure (including this one) in the <code>pNext</code> chain <strong class=\"purple\">must</strong> be either <code>NULL</code> or a pointer to a valid instance of <a href=\"#VkDeferredOperationInfoKHR\">VkDeferredOperationInfoKHR</a> or <a href=\"#VkPipelineCreationFeedbackCreateInfoEXT\">VkPipelineCreationFeedbackCreateInfoEXT</a>"
+        },
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoKHR-sType-unique",
+          "text": " The <code>sType</code> value of each struct in the <code>pNext</code> chain <strong class=\"purple\">must</strong> be unique"
+        },
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoKHR-flags-parameter",
+          "text": " <code>flags</code> <strong class=\"purple\">must</strong> be a valid combination of <a href=\"#VkPipelineCreateFlagBits\">VkPipelineCreateFlagBits</a> values"
+        },
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoKHR-pStages-parameter",
+          "text": " If <code>stageCount</code> is not <code>0</code>, <code>pStages</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>stageCount</code> valid <a href=\"#VkPipelineShaderStageCreateInfo\">VkPipelineShaderStageCreateInfo</a> structures"
+        },
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoKHR-pGroups-parameter",
+          "text": " If <code>groupCount</code> is not <code>0</code>, <code>pGroups</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>groupCount</code> valid <a href=\"#VkRayTracingShaderGroupCreateInfoKHR\">VkRayTracingShaderGroupCreateInfoKHR</a> structures"
+        },
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoKHR-libraries-parameter",
+          "text": " <code>libraries</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkPipelineLibraryCreateInfoKHR\">VkPipelineLibraryCreateInfoKHR</a> structure"
+        },
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoKHR-pLibraryInterface-parameter",
+          "text": " If <code>pLibraryInterface</code> is not <code>NULL</code>, <code>pLibraryInterface</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkRayTracingPipelineInterfaceCreateInfoKHR\">VkRayTracingPipelineInterfaceCreateInfoKHR</a> structure"
+        },
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoKHR-layout-parameter",
+          "text": " <code>layout</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkPipelineLayout\">VkPipelineLayout</a> handle"
+        },
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoKHR-commonparent",
+          "text": " Both of <code>basePipelineHandle</code>, and <code>layout</code> that are valid handles of non-ignored parameters <strong class=\"purple\">must</strong> have been created, allocated, or retrieved from the same <a href=\"#VkDevice\">VkDevice</a>"
+        }
+      ],
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)+(VK_NV_device_generated_commands)": [
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoKHR-flags-02904",
+          "text": " <code>flags</code> <strong class=\"purple\">must</strong> not include <code>VK_PIPELINE_CREATE_INDIRECT_BINDABLE_BIT_NV</code>"
+        }
+      ],
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)+(VK_EXT_pipeline_creation_cache_control)": [
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoKHR-pipelineCreationCacheControl-02905",
+          "text": " If the <a href=\"#features-pipelineCreationCacheControl\"><code>pipelineCreationCacheControl</code></a> feature is not enabled, <code>flags</code> <strong class=\"purple\">must</strong> not include <code>VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_EXT</code> or <code>VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT_EXT</code>"
+        }
+      ],
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)+(VK_KHR_pipeline_library)": [
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoKHR-flags-03465",
+          "text": " If <code>flags</code> includes <code>VK_PIPELINE_CREATE_LIBRARY_BIT_KHR</code>, <code>pLibraryInterface</code> <strong class=\"purple\">must</strong> not be <code>NULL</code>"
+        },
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoKHR-libraryCount-03466",
+          "text": " If the <code>libraryCount</code> member of <code>libraries</code> is greater than <code>0</code>, <code>pLibraryInterface</code> <strong class=\"purple\">must</strong> not be <code>NULL</code>"
+        },
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoKHR-pLibraries-03467",
+          "text": " Each element of the <code>pLibraries</code> member of <code>libraries</code> <strong class=\"purple\">must</strong> have been created with the value of <code>maxRecursionDepth</code> equal to that in this pipeline"
+        },
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoKHR-pLibraries-03468",
+          "text": " Each element of the <code>pLibraries</code> member of <code>libraries</code> <strong class=\"purple\">must</strong> have been created with a <code>layout</code> that is compatible with the <code>layout</code> in this pipeline"
+        },
+        {
+          "vuid": "VUID-VkRayTracingPipelineCreateInfoKHR-pLibraries-03469",
+          "text": " Each element of the <code>pLibraries</code> member of <code>libraries</code> <strong class=\"purple\">must</strong> have been created with values of the <code>maxPayloadSize</code>, <code>maxAttributeSize</code>, and <code>maxCallableSize</code> members of <code>pLibraryInterface</code> equal to those in this pipeline"
+        }
       ]
     },
     "VkRayTracingShaderGroupCreateInfoNV": {
-      "(VK_NV_ray_tracing)": [
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_NV_ray_tracing)": [
         {
           "vuid": "VUID-VkRayTracingShaderGroupCreateInfoNV-type-02413",
-          "text": " If <code>type</code> is <code>VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV</code> then <code>generalShader</code> <strong class=\"purple\">must</strong> be a valid index into <code>pStages</code> referring to a shader of <code>VK_SHADER_STAGE_RAYGEN_BIT_NV</code>, <code>VK_SHADER_STAGE_MISS_BIT_NV</code>, or <code>VK_SHADER_STAGE_CALLABLE_BIT_NV</code>"
+          "text": " If <code>type</code> is <code>VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV</code> then <code>generalShader</code> <strong class=\"purple\">must</strong> be a valid index into <a href=\"#VkRayTracingPipelineCreateInfoNV\">VkRayTracingPipelineCreateInfoNV</a>::<code>pStages</code> referring to a shader of <code>VK_SHADER_STAGE_RAYGEN_BIT_NV</code>, <code>VK_SHADER_STAGE_MISS_BIT_NV</code>, or <code>VK_SHADER_STAGE_CALLABLE_BIT_NV</code>"
         },
         {
           "vuid": "VUID-VkRayTracingShaderGroupCreateInfoNV-type-02414",
@@ -7288,7 +7808,7 @@
         },
         {
           "vuid": "VUID-VkRayTracingShaderGroupCreateInfoNV-type-02415",
-          "text": " If <code>type</code> is <code>VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV</code> then <code>intersectionShader</code> <strong class=\"purple\">must</strong> be a valid index into <code>pStages</code> referring to a shader of <code>VK_SHADER_STAGE_INTERSECTION_BIT_NV</code>"
+          "text": " If <code>type</code> is <code>VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV</code> then <code>intersectionShader</code> <strong class=\"purple\">must</strong> be a valid index into <a href=\"#VkRayTracingPipelineCreateInfoNV\">VkRayTracingPipelineCreateInfoNV</a>::<code>pStages</code> referring to a shader of <code>VK_SHADER_STAGE_INTERSECTION_BIT_NV</code>"
         },
         {
           "vuid": "VUID-VkRayTracingShaderGroupCreateInfoNV-type-02416",
@@ -7296,11 +7816,11 @@
         },
         {
           "vuid": "VUID-VkRayTracingShaderGroupCreateInfoNV-closestHitShader-02417",
-          "text": " <code>closestHitShader</code> <strong class=\"purple\">must</strong> be either <code>VK_SHADER_UNUSED_NV</code> or a valid index into <code>pStages</code> referring to a shader of <code>VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV</code>"
+          "text": " <code>closestHitShader</code> <strong class=\"purple\">must</strong> be either <code>VK_SHADER_UNUSED_NV</code> or a valid index into <a href=\"#VkRayTracingPipelineCreateInfoNV\">VkRayTracingPipelineCreateInfoNV</a>::<code>pStages</code> referring to a shader of <code>VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV</code>"
         },
         {
           "vuid": "VUID-VkRayTracingShaderGroupCreateInfoNV-anyHitShader-02418",
-          "text": " <code>anyHitShader</code> <strong class=\"purple\">must</strong> be either <code>VK_SHADER_UNUSED_NV</code> or a valid index into <code>pStages</code> referring to a shader of <code>VK_SHADER_STAGE_ANY_HIT_BIT_NV</code>"
+          "text": " <code>anyHitShader</code> <strong class=\"purple\">must</strong> be either <code>VK_SHADER_UNUSED_NV</code> or a valid index into <a href=\"#VkRayTracingPipelineCreateInfoNV\">VkRayTracingPipelineCreateInfoNV</a>::<code>pStages</code> referring to a shader of <code>VK_SHADER_STAGE_ANY_HIT_BIT_NV</code>"
         },
         {
           "vuid": "VUID-VkRayTracingShaderGroupCreateInfoNV-sType-sType",
@@ -7312,44 +7832,146 @@
         },
         {
           "vuid": "VUID-VkRayTracingShaderGroupCreateInfoNV-type-parameter",
-          "text": " <code>type</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkRayTracingShaderGroupTypeNV\">VkRayTracingShaderGroupTypeNV</a> value"
+          "text": " <code>type</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkRayTracingShaderGroupTypeKHR\">VkRayTracingShaderGroupTypeKHR</a> value"
         }
       ]
     },
-    "vkGetRayTracingShaderGroupHandlesNV": {
-      "(VK_NV_ray_tracing)": [
+    "VkRayTracingShaderGroupCreateInfoKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)": [
         {
-          "vuid": "VUID-vkGetRayTracingShaderGroupHandlesNV-firstGroup-02419",
-          "text": " The sum of <code>firstGroup</code> and <code>groupCount</code> <strong class=\"purple\">must</strong> be less than the number of shader groups in <code>pipeline</code>."
+          "vuid": "VUID-VkRayTracingShaderGroupCreateInfoKHR-type-03474",
+          "text": " If <code>type</code> is <code>VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR</code> then <code>generalShader</code> <strong class=\"purple\">must</strong> be a valid index into <a href=\"#VkRayTracingPipelineCreateInfoKHR\">VkRayTracingPipelineCreateInfoKHR</a>::<code>pStages</code> referring to a shader of <code>VK_SHADER_STAGE_RAYGEN_BIT_KHR</code>, <code>VK_SHADER_STAGE_MISS_BIT_KHR</code>, or <code>VK_SHADER_STAGE_CALLABLE_BIT_KHR</code>"
         },
         {
-          "vuid": "VUID-vkGetRayTracingShaderGroupHandlesNV-dataSize-02420",
-          "text": " <code>dataSize</code> <strong class=\"purple\">must</strong> be at least <span class=\"eq\"><code>VkPhysicalDeviceRayTracingPropertiesNV</code>::<code>shaderGroupHandleSize</code> {times} <code>groupCount</code></span>"
+          "vuid": "VUID-VkRayTracingShaderGroupCreateInfoKHR-type-03475",
+          "text": " If <code>type</code> is <code>VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR</code> then <code>closestHitShader</code>, <code>anyHitShader</code>, and <code>intersectionShader</code> <strong class=\"purple\">must</strong> be <code>VK_SHADER_UNUSED_KHR</code>"
         },
         {
-          "vuid": "VUID-vkGetRayTracingShaderGroupHandlesNV-device-parameter",
+          "vuid": "VUID-VkRayTracingShaderGroupCreateInfoKHR-type-03476",
+          "text": " If <code>type</code> is <code>VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR</code> then <code>intersectionShader</code> <strong class=\"purple\">must</strong> be a valid index into <a href=\"#VkRayTracingPipelineCreateInfoKHR\">VkRayTracingPipelineCreateInfoKHR</a>::<code>pStages</code> referring to a shader of <code>VK_SHADER_STAGE_INTERSECTION_BIT_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkRayTracingShaderGroupCreateInfoKHR-type-03477",
+          "text": " If <code>type</code> is <code>VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR</code> then <code>intersectionShader</code> <strong class=\"purple\">must</strong> be <code>VK_SHADER_UNUSED_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkRayTracingShaderGroupCreateInfoKHR-closestHitShader-03478",
+          "text": " <code>closestHitShader</code> <strong class=\"purple\">must</strong> be either <code>VK_SHADER_UNUSED_KHR</code> or a valid index into <a href=\"#VkRayTracingPipelineCreateInfoKHR\">VkRayTracingPipelineCreateInfoKHR</a>::<code>pStages</code> referring to a shader of <code>VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkRayTracingShaderGroupCreateInfoKHR-anyHitShader-03479",
+          "text": " <code>anyHitShader</code> <strong class=\"purple\">must</strong> be either <code>VK_SHADER_UNUSED_KHR</code> or a valid index into <a href=\"#VkRayTracingPipelineCreateInfoKHR\">VkRayTracingPipelineCreateInfoKHR</a>::<code>pStages</code> referring to a shader of <code>VK_SHADER_STAGE_ANY_HIT_BIT_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkRayTracingShaderGroupCreateInfoKHR-rayTracingShaderGroupHandleCaptureReplayMixed-03480",
+          "text": " If <a href=\"#VkPhysicalDeviceRayTracingFeaturesKHR\">VkPhysicalDeviceRayTracingFeaturesKHR</a>::<code>rayTracingShaderGroupHandleCaptureReplayMixed</code> is <code>VK_FALSE</code> then <code>pShaderGroupCaptureReplayHandle</code> <strong class=\"purple\">must</strong> not be provided if it has not been provided on a previous call to ray tracing pipeline creation"
+        },
+        {
+          "vuid": "VUID-VkRayTracingShaderGroupCreateInfoKHR-rayTracingShaderGroupHandleCaptureReplayMixed-03481",
+          "text": " If <a href=\"#VkPhysicalDeviceRayTracingFeaturesKHR\">VkPhysicalDeviceRayTracingFeaturesKHR</a>::<code>rayTracingShaderGroupHandleCaptureReplayMixed</code> is <code>VK_FALSE</code> then the caller <strong class=\"purple\">must</strong> guarantee that no ray tracing pipeline creation commands with <code>pShaderGroupCaptureReplayHandle</code> provided execute simultaneously with ray tracing pipeline creation commands without <code>pShaderGroupCaptureReplayHandle</code> provided"
+        },
+        {
+          "vuid": "VUID-VkRayTracingShaderGroupCreateInfoKHR-sType-sType",
+          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkRayTracingShaderGroupCreateInfoKHR-pNext-pNext",
+          "text": " <code>pNext</code> <strong class=\"purple\">must</strong> be <code>NULL</code>"
+        },
+        {
+          "vuid": "VUID-VkRayTracingShaderGroupCreateInfoKHR-type-parameter",
+          "text": " <code>type</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkRayTracingShaderGroupTypeKHR\">VkRayTracingShaderGroupTypeKHR</a> value"
+        }
+      ]
+    },
+    "VkRayTracingPipelineInterfaceCreateInfoKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-VkRayTracingPipelineInterfaceCreateInfoKHR-sType-sType",
+          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_INTERFACE_CREATE_INFO_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkRayTracingPipelineInterfaceCreateInfoKHR-pNext-pNext",
+          "text": " <code>pNext</code> <strong class=\"purple\">must</strong> be <code>NULL</code>"
+        }
+      ]
+    },
+    "vkGetRayTracingShaderGroupHandlesKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-vkGetRayTracingShaderGroupHandlesKHR-firstGroup-02419",
+          "text": " The sum of <code>firstGroup</code> and <code>groupCount</code> <strong class=\"purple\">must</strong> be less than the number of shader groups in <code>pipeline</code>"
+        },
+        {
+          "vuid": "VUID-vkGetRayTracingShaderGroupHandlesKHR-dataSize-02420",
+          "text": " <code>dataSize</code> <strong class=\"purple\">must</strong> be at least <span class=\"eq\"><a href=\"#VkPhysicalDeviceRayTracingPropertiesKHR\">VkPhysicalDeviceRayTracingPropertiesKHR</a>::<code>shaderGroupHandleSize</code> {times} <code>groupCount</code></span>"
+        },
+        {
+          "vuid": "VUID-vkGetRayTracingShaderGroupHandlesKHR-device-parameter",
           "text": " <code>device</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDevice\">VkDevice</a> handle"
         },
         {
-          "vuid": "VUID-vkGetRayTracingShaderGroupHandlesNV-pipeline-parameter",
+          "vuid": "VUID-vkGetRayTracingShaderGroupHandlesKHR-pipeline-parameter",
           "text": " <code>pipeline</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkPipeline\">VkPipeline</a> handle"
         },
         {
-          "vuid": "VUID-vkGetRayTracingShaderGroupHandlesNV-pData-parameter",
+          "vuid": "VUID-vkGetRayTracingShaderGroupHandlesKHR-pData-parameter",
           "text": " <code>pData</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>dataSize</code> bytes"
         },
         {
-          "vuid": "VUID-vkGetRayTracingShaderGroupHandlesNV-dataSize-arraylength",
+          "vuid": "VUID-vkGetRayTracingShaderGroupHandlesKHR-dataSize-arraylength",
           "text": " <code>dataSize</code> <strong class=\"purple\">must</strong> be greater than <code>0</code>"
         },
         {
-          "vuid": "VUID-vkGetRayTracingShaderGroupHandlesNV-pipeline-parent",
+          "vuid": "VUID-vkGetRayTracingShaderGroupHandlesKHR-pipeline-parent",
+          "text": " <code>pipeline</code> <strong class=\"purple\">must</strong> have been created, allocated, or retrieved from <code>device</code>"
+        }
+      ],
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_pipeline_library)": [
+        {
+          "vuid": "VUID-vkGetRayTracingShaderGroupHandlesKHR-pipeline-03482",
+          "text": " <code>pipeline</code> <strong class=\"purple\">must</strong> have not been created with <code>VK_PIPELINE_CREATE_LIBRARY_BIT_KHR</code>"
+        }
+      ]
+    },
+    "vkGetRayTracingCaptureReplayShaderGroupHandlesKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-vkGetRayTracingCaptureReplayShaderGroupHandlesKHR-firstGroup-03483",
+          "text": " The sum of <code>firstGroup</code> and <code>groupCount</code> <strong class=\"purple\">must</strong> be less than the number of shader groups in <code>pipeline</code>"
+        },
+        {
+          "vuid": "VUID-vkGetRayTracingCaptureReplayShaderGroupHandlesKHR-dataSize-03484",
+          "text": " <code>dataSize</code> <strong class=\"purple\">must</strong> be at least <span class=\"eq\"><a href=\"#VkPhysicalDeviceRayTracingPropertiesKHR\">VkPhysicalDeviceRayTracingPropertiesKHR</a>::<code>shaderGroupHandleCaptureReplaySize</code> {times} <code>groupCount</code></span>"
+        },
+        {
+          "vuid": "VUID-vkGetRayTracingCaptureReplayShaderGroupHandlesKHR-rayTracingShaderGroupHandleCaptureReplay-03485",
+          "text": " <code>VkPhysicalDeviceRayTracingFeaturesKHR</code>::<code>rayTracingShaderGroupHandleCaptureReplay</code> <strong class=\"purple\">must</strong> be enabled to call this function"
+        },
+        {
+          "vuid": "VUID-vkGetRayTracingCaptureReplayShaderGroupHandlesKHR-device-parameter",
+          "text": " <code>device</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDevice\">VkDevice</a> handle"
+        },
+        {
+          "vuid": "VUID-vkGetRayTracingCaptureReplayShaderGroupHandlesKHR-pipeline-parameter",
+          "text": " <code>pipeline</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkPipeline\">VkPipeline</a> handle"
+        },
+        {
+          "vuid": "VUID-vkGetRayTracingCaptureReplayShaderGroupHandlesKHR-pData-parameter",
+          "text": " <code>pData</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>dataSize</code> bytes"
+        },
+        {
+          "vuid": "VUID-vkGetRayTracingCaptureReplayShaderGroupHandlesKHR-dataSize-arraylength",
+          "text": " <code>dataSize</code> <strong class=\"purple\">must</strong> be greater than <code>0</code>"
+        },
+        {
+          "vuid": "VUID-vkGetRayTracingCaptureReplayShaderGroupHandlesKHR-pipeline-parent",
           "text": " <code>pipeline</code> <strong class=\"purple\">must</strong> have been created, allocated, or retrieved from <code>device</code>"
         }
       ]
     },
     "vkCompileDeferredNV": {
-      "(VK_NV_ray_tracing)": [
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_NV_ray_tracing)": [
         {
           "vuid": "VUID-vkCompileDeferredNV-pipeline-02237",
           "text": " <code>pipeline</code> <strong class=\"purple\">must</strong> have been created with <code>VK_PIPELINE_CREATE_DEFER_COMPILE_BIT_NV</code>"
@@ -7399,9 +8021,15 @@
           "text": " <code>pipelineStageCreationFeedbackCount</code> <strong class=\"purple\">must</strong> be greater than <code>0</code>"
         }
       ],
-      "(VK_EXT_pipeline_creation_feedback)+(VK_NV_ray_tracing)": [
+      "(VK_EXT_pipeline_creation_feedback)+(VK_KHR_ray_tracing)": [
         {
           "vuid": "VUID-VkPipelineCreationFeedbackCreateInfoEXT-pipelineStageCreationFeedbackCount-02670",
+          "text": " When chained to <a href=\"#VkRayTracingPipelineCreateInfoKHR\">VkRayTracingPipelineCreateInfoKHR</a>, <a href=\"#VkPipelineCreationFeedbackEXT\">VkPipelineCreationFeedbackEXT</a>::<code>pipelineStageCreationFeedbackCount</code> <strong class=\"purple\">must</strong> equal <a href=\"#VkRayTracingPipelineCreateInfoKHR\">VkRayTracingPipelineCreateInfoKHR</a>::<code>stageCount</code>"
+        }
+      ],
+      "(VK_EXT_pipeline_creation_feedback)+(VK_NV_ray_tracing)": [
+        {
+          "vuid": "VUID-VkPipelineCreationFeedbackCreateInfoEXT-pipelineStageCreationFeedbackCount-02969",
           "text": " When chained to <a href=\"#VkRayTracingPipelineCreateInfoNV\">VkRayTracingPipelineCreateInfoNV</a>, <a href=\"#VkPipelineCreationFeedbackEXT\">VkPipelineCreationFeedbackEXT</a>::<code>pipelineStageCreationFeedbackCount</code> <strong class=\"purple\">must</strong> equal <a href=\"#VkRayTracingPipelineCreateInfoNV\">VkRayTracingPipelineCreateInfoNV</a>::<code>stageCount</code>"
         }
       ]
@@ -7478,7 +8106,7 @@
       "core": [
         {
           "vuid": "VUID-vkAllocateMemory-pAllocateInfo-01713",
-          "text": " <code>pAllocateInfo-&gt;allocationSize</code> <strong class=\"purple\">must</strong> be less than or equal to <a href=\"#VkPhysicalDeviceMemoryProperties\">VkPhysicalDeviceMemoryProperties</a>::<code>memoryHeaps</code>[memindex].size where <code>memindex</code> = <a href=\"#VkPhysicalDeviceMemoryProperties\">VkPhysicalDeviceMemoryProperties</a>::<code>memoryTypes</code>[pAllocateInfo-&gt;memoryTypeIndex].heapIndex as returned by <a href=\"#vkGetPhysicalDeviceMemoryProperties\">vkGetPhysicalDeviceMemoryProperties</a> for the <a href=\"#VkPhysicalDevice\">VkPhysicalDevice</a> that <code>device</code> was created from."
+          "text": " <code>pAllocateInfo-&gt;allocationSize</code> <strong class=\"purple\">must</strong> be less than or equal to <a href=\"#VkPhysicalDeviceMemoryProperties\">VkPhysicalDeviceMemoryProperties</a>::<code>memoryHeaps</code>[memindex].size where <code>memindex</code> = <a href=\"#VkPhysicalDeviceMemoryProperties\">VkPhysicalDeviceMemoryProperties</a>::<code>memoryTypes</code>[pAllocateInfo-&gt;memoryTypeIndex].heapIndex as returned by <a href=\"#vkGetPhysicalDeviceMemoryProperties\">vkGetPhysicalDeviceMemoryProperties</a> for the <a href=\"#VkPhysicalDevice\">VkPhysicalDevice</a> that <code>device</code> was created from"
         },
         {
           "vuid": "VUID-vkAllocateMemory-pAllocateInfo-01714",
@@ -7524,57 +8152,57 @@
       "(VK_KHR_external_memory)+(VK_NV_external_memory)": [
         {
           "vuid": "VUID-VkMemoryAllocateInfo-pNext-00640",
-          "text": " If the <code>pNext</code> chain includes a <a href=\"#VkExportMemoryAllocateInfo\">VkExportMemoryAllocateInfo</a> structure, it <strong class=\"purple\">must</strong> not include a <a href=\"#VkExportMemoryAllocateInfoNV\">VkExportMemoryAllocateInfoNV</a> or <a href=\"#VkExportMemoryWin32HandleInfoNV\">VkExportMemoryWin32HandleInfoNV</a> structure."
+          "text": " If the <code>pNext</code> chain includes a <a href=\"#VkExportMemoryAllocateInfo\">VkExportMemoryAllocateInfo</a> structure, it <strong class=\"purple\">must</strong> not include a <a href=\"#VkExportMemoryAllocateInfoNV\">VkExportMemoryAllocateInfoNV</a> or <a href=\"#VkExportMemoryWin32HandleInfoNV\">VkExportMemoryWin32HandleInfoNV</a> structure"
         }
       ],
       "(VK_KHR_external_memory_win32+VK_NV_external_memory_win32)": [
         {
           "vuid": "VUID-VkMemoryAllocateInfo-pNext-00641",
-          "text": " If the <code>pNext</code> chain includes a <a href=\"#VkImportMemoryWin32HandleInfoKHR\">VkImportMemoryWin32HandleInfoKHR</a> structure, it <strong class=\"purple\">must</strong> not include a <a href=\"#VkImportMemoryWin32HandleInfoNV\">VkImportMemoryWin32HandleInfoNV</a> structure."
+          "text": " If the <code>pNext</code> chain includes a <a href=\"#VkImportMemoryWin32HandleInfoKHR\">VkImportMemoryWin32HandleInfoKHR</a> structure, it <strong class=\"purple\">must</strong> not include a <a href=\"#VkImportMemoryWin32HandleInfoNV\">VkImportMemoryWin32HandleInfoNV</a> structure"
         }
       ],
       "(VK_KHR_external_memory_fd)": [
         {
           "vuid": "VUID-VkMemoryAllocateInfo-allocationSize-01742",
-          "text": " If the parameters define an import operation, the external handle specified was created by the Vulkan API, and the external handle type is <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR</code>, then the values of <code>allocationSize</code> and <code>memoryTypeIndex</code> <strong class=\"purple\">must</strong> match those specified when the memory object being imported was created."
+          "text": " If the parameters define an import operation, the external handle specified was created by the Vulkan API, and the external handle type is <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR</code>, then the values of <code>allocationSize</code> and <code>memoryTypeIndex</code> <strong class=\"purple\">must</strong> match those specified when the memory object being imported was created"
         },
         {
           "vuid": "VUID-VkMemoryAllocateInfo-memoryTypeIndex-00648",
-          "text": " If the parameters define an import operation and the external handle is a POSIX file descriptor created outside of the Vulkan API, the value of <code>memoryTypeIndex</code> <strong class=\"purple\">must</strong> be one of those returned by <a href=\"#vkGetMemoryFdPropertiesKHR\">vkGetMemoryFdPropertiesKHR</a>."
+          "text": " If the parameters define an import operation and the external handle is a POSIX file descriptor created outside of the Vulkan API, the value of <code>memoryTypeIndex</code> <strong class=\"purple\">must</strong> be one of those returned by <a href=\"#vkGetMemoryFdPropertiesKHR\">vkGetMemoryFdPropertiesKHR</a>"
         }
       ],
       "(VK_KHR_external_memory+VK_KHR_device_group)": [
         {
           "vuid": "VUID-VkMemoryAllocateInfo-None-00643",
-          "text": " If the parameters define an import operation and the external handle specified was created by the Vulkan API, the device mask specified by <a href=\"#VkMemoryAllocateFlagsInfo\">VkMemoryAllocateFlagsInfo</a> <strong class=\"purple\">must</strong> match that specified when the memory object being imported was allocated."
+          "text": " If the parameters define an import operation and the external handle specified was created by the Vulkan API, the device mask specified by <a href=\"#VkMemoryAllocateFlagsInfo\">VkMemoryAllocateFlagsInfo</a> <strong class=\"purple\">must</strong> match that specified when the memory object being imported was allocated"
         },
         {
           "vuid": "VUID-VkMemoryAllocateInfo-None-00644",
-          "text": " If the parameters define an import operation and the external handle specified was created by the Vulkan API, the list of physical devices that comprise the logical device passed to <a href=\"#vkAllocateMemory\">vkAllocateMemory</a> <strong class=\"purple\">must</strong> match the list of physical devices that comprise the logical device on which the memory was originally allocated."
+          "text": " If the parameters define an import operation and the external handle specified was created by the Vulkan API, the list of physical devices that comprise the logical device passed to <a href=\"#vkAllocateMemory\">vkAllocateMemory</a> <strong class=\"purple\">must</strong> match the list of physical devices that comprise the logical device on which the memory was originally allocated"
         }
       ],
       "(VK_KHR_external_memory_win32)": [
         {
           "vuid": "VUID-VkMemoryAllocateInfo-memoryTypeIndex-00645",
-          "text": " If the parameters define an import operation and the external handle is an NT handle or a global share handle created outside of the Vulkan API, the value of <code>memoryTypeIndex</code> <strong class=\"purple\">must</strong> be one of those returned by <a href=\"#vkGetMemoryWin32HandlePropertiesKHR\">vkGetMemoryWin32HandlePropertiesKHR</a>."
+          "text": " If the parameters define an import operation and the external handle is an NT handle or a global share handle created outside of the Vulkan API, the value of <code>memoryTypeIndex</code> <strong class=\"purple\">must</strong> be one of those returned by <a href=\"#vkGetMemoryWin32HandlePropertiesKHR\">vkGetMemoryWin32HandlePropertiesKHR</a>"
         },
         {
           "vuid": "VUID-VkMemoryAllocateInfo-allocationSize-01743",
-          "text": " If the parameters define an import operation, the external handle was created by the Vulkan API, and the external handle type is <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR</code> or <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR</code>, then the values of <code>allocationSize</code> and <code>memoryTypeIndex</code> <strong class=\"purple\">must</strong> match those specified when the memory object being imported was created."
+          "text": " If the parameters define an import operation, the external handle was created by the Vulkan API, and the external handle type is <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR</code> or <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR</code>, then the values of <code>allocationSize</code> and <code>memoryTypeIndex</code> <strong class=\"purple\">must</strong> match those specified when the memory object being imported was created"
         },
         {
           "vuid": "VUID-VkMemoryAllocateInfo-allocationSize-00646",
-          "text": " If the parameters define an import operation and the external handle type is <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT</code>, <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT</code>, or <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT</code>, <code>allocationSize</code> <strong class=\"purple\">must</strong> match the size reported in the memory requirements of the <code>image</code> or <code>buffer</code> member of the <code>VkDedicatedAllocationMemoryAllocateInfoNV</code> structure included in the <code>pNext</code> chain."
+          "text": " If the parameters define an import operation and the external handle type is <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT</code>, <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT</code>, or <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT</code>, <code>allocationSize</code> <strong class=\"purple\">must</strong> match the size reported in the memory requirements of the <code>image</code> or <code>buffer</code> member of the <code>VkDedicatedAllocationMemoryAllocateInfoNV</code> structure included in the <code>pNext</code> chain"
         },
         {
           "vuid": "VUID-VkMemoryAllocateInfo-allocationSize-00647",
-          "text": " If the parameters define an import operation and the external handle type is <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT</code>, <code>allocationSize</code> <strong class=\"purple\">must</strong> match the size specified when creating the Direct3D 12 heap from which the external handle was extracted."
+          "text": " If the parameters define an import operation and the external handle type is <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT</code>, <code>allocationSize</code> <strong class=\"purple\">must</strong> match the size specified when creating the Direct3D 12 heap from which the external handle was extracted"
         }
       ],
       "(VK_VERSION_1_1)": [
         {
           "vuid": "VUID-VkMemoryAllocateInfo-memoryTypeIndex-01872",
-          "text": " If the protected memory feature is not enabled, the <code>VkMemoryAllocateInfo</code>::<code>memoryTypeIndex</code> <strong class=\"purple\">must</strong> not indicate a memory type that reports <code>VK_MEMORY_PROPERTY_PROTECTED_BIT</code>."
+          "text": " If the protected memory feature is not enabled, the <code>VkMemoryAllocateInfo</code>::<code>memoryTypeIndex</code> <strong class=\"purple\">must</strong> not indicate a memory type that reports <code>VK_MEMORY_PROPERTY_PROTECTED_BIT</code>"
         }
       ],
       "(VK_EXT_external_memory_host)": [
@@ -7590,55 +8218,55 @@
       "(VK_EXT_external_memory_host)+(VK_NV_dedicated_allocation)": [
         {
           "vuid": "VUID-VkMemoryAllocateInfo-pNext-02805",
-          "text": " If the parameters define an import operation and the external handle is a host pointer, the <code>pNext</code> chain <strong class=\"purple\">must</strong> not include a <a href=\"#VkDedicatedAllocationMemoryAllocateInfoNV\">VkDedicatedAllocationMemoryAllocateInfoNV</a> structure with either its <code>image</code> or <code>buffer</code> field set to a value other than <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>."
+          "text": " If the parameters define an import operation and the external handle is a host pointer, the <code>pNext</code> chain <strong class=\"purple\">must</strong> not include a <a href=\"#VkDedicatedAllocationMemoryAllocateInfoNV\">VkDedicatedAllocationMemoryAllocateInfoNV</a> structure with either its <code>image</code> or <code>buffer</code> field set to a value other than <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>"
         }
       ],
       "(VK_EXT_external_memory_host)+(VK_KHR_dedicated_allocation)": [
         {
           "vuid": "VUID-VkMemoryAllocateInfo-pNext-02806",
-          "text": " If the parameters define an import operation and the external handle is a host pointer, the <code>pNext</code> chain <strong class=\"purple\">must</strong> not include a <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a> structure with either its <code>image</code> or <code>buffer</code> field set to a value other than <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>."
+          "text": " If the parameters define an import operation and the external handle is a host pointer, the <code>pNext</code> chain <strong class=\"purple\">must</strong> not include a <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a> structure with either its <code>image</code> or <code>buffer</code> field set to a value other than <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>"
         }
       ],
       "(VK_ANDROID_external_memory_android_hardware_buffer)": [
         {
           "vuid": "VUID-VkMemoryAllocateInfo-allocationSize-02383",
-          "text": " If the parameters define an import operation and the external handle type is <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID</code>, <code>allocationSize</code> <strong class=\"purple\">must</strong> be the size returned by <a href=\"#vkGetAndroidHardwareBufferPropertiesANDROID\">vkGetAndroidHardwareBufferPropertiesANDROID</a> for the Android hardware buffer."
+          "text": " If the parameters define an import operation and the external handle type is <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID</code>, <code>allocationSize</code> <strong class=\"purple\">must</strong> be the size returned by <a href=\"#vkGetAndroidHardwareBufferPropertiesANDROID\">vkGetAndroidHardwareBufferPropertiesANDROID</a> for the Android hardware buffer"
         },
         {
           "vuid": "VUID-VkMemoryAllocateInfo-pNext-02384",
-          "text": " If the parameters define an import operation and the external handle type is <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID</code>, and the <code>pNext</code> chain does not include a <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a> structure or <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a>::<code>image</code> is <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, the Android hardware buffer <strong class=\"purple\">must</strong> have a <code>AHardwareBuffer_Desc</code>::<code>format</code> of <code>AHARDWAREBUFFER_FORMAT_BLOB</code> and a <code>AHardwareBuffer_Desc</code>::<code>usage</code> that includes <code>AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER</code>."
+          "text": " If the parameters define an import operation and the external handle type is <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID</code>, and the <code>pNext</code> chain does not include a <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a> structure or <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a>::<code>image</code> is <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, the Android hardware buffer <strong class=\"purple\">must</strong> have a <code>AHardwareBuffer_Desc</code>::<code>format</code> of <code>AHARDWAREBUFFER_FORMAT_BLOB</code> and a <code>AHardwareBuffer_Desc</code>::<code>usage</code> that includes <code>AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER</code>"
         },
         {
           "vuid": "VUID-VkMemoryAllocateInfo-memoryTypeIndex-02385",
-          "text": " If the parameters define an import operation and the external handle type is <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID</code>, <code>memoryTypeIndex</code> <strong class=\"purple\">must</strong> be one of those returned by <a href=\"#vkGetAndroidHardwareBufferPropertiesANDROID\">vkGetAndroidHardwareBufferPropertiesANDROID</a> for the Android hardware buffer."
+          "text": " If the parameters define an import operation and the external handle type is <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID</code>, <code>memoryTypeIndex</code> <strong class=\"purple\">must</strong> be one of those returned by <a href=\"#vkGetAndroidHardwareBufferPropertiesANDROID\">vkGetAndroidHardwareBufferPropertiesANDROID</a> for the Android hardware buffer"
         },
         {
           "vuid": "VUID-VkMemoryAllocateInfo-pNext-01874",
-          "text": " If the parameters do not define an import operation, and the <code>pNext</code> chain includes a <code>VkExportMemoryAllocateInfo</code> structure with <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID</code> included in its <code>handleTypes</code> member, and the <code>pNext</code> chain includes a <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a> structure with <code>image</code> not equal to <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, then <code>allocationSize</code> <strong class=\"purple\">must</strong> be <code>0</code>, otherwise <code>allocationSize</code> <strong class=\"purple\">must</strong> be greater than <code>0</code>."
+          "text": " If the parameters do not define an import operation, and the <code>pNext</code> chain includes a <code>VkExportMemoryAllocateInfo</code> structure with <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID</code> included in its <code>handleTypes</code> member, and the <code>pNext</code> chain includes a <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a> structure with <code>image</code> not equal to <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, then <code>allocationSize</code> <strong class=\"purple\">must</strong> be <code>0</code>, otherwise <code>allocationSize</code> <strong class=\"purple\">must</strong> be greater than <code>0</code>"
         },
         {
           "vuid": "VUID-VkMemoryAllocateInfo-pNext-02386",
-          "text": " If the parameters define an import operation, the external handle is an Android hardware buffer, and the <code>pNext</code> chain includes a <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a> with <code>image</code> that is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, the Android hardware buffer&#8217;s <a href=\"#AHardwareBuffer\">AHardwareBuffer</a>::<code>usage</code> <strong class=\"purple\">must</strong> include at least one of <code>AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT</code> or <code>AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE</code>."
+          "text": " If the parameters define an import operation, the external handle is an Android hardware buffer, and the <code>pNext</code> chain includes a <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a> with <code>image</code> that is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, the Android hardware buffer&#8217;s <a href=\"#AHardwareBuffer\">AHardwareBuffer</a>::<code>usage</code> <strong class=\"purple\">must</strong> include at least one of <code>AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT</code> or <code>AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE</code>"
         },
         {
           "vuid": "VUID-VkMemoryAllocateInfo-pNext-02387",
-          "text": " If the parameters define an import operation, the external handle is an Android hardware buffer, and the <code>pNext</code> chain includes a <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a> with <code>image</code> that is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, the format of <code>image</code> <strong class=\"purple\">must</strong> be <code>VK_FORMAT_UNDEFINED</code> or the format returned by <a href=\"#vkGetAndroidHardwareBufferPropertiesANDROID\">vkGetAndroidHardwareBufferPropertiesANDROID</a> in <a href=\"#VkAndroidHardwareBufferFormatPropertiesANDROID\">VkAndroidHardwareBufferFormatPropertiesANDROID</a>::<code>format</code> for the Android hardware buffer."
+          "text": " If the parameters define an import operation, the external handle is an Android hardware buffer, and the <code>pNext</code> chain includes a <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a> with <code>image</code> that is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, the format of <code>image</code> <strong class=\"purple\">must</strong> be <code>VK_FORMAT_UNDEFINED</code> or the format returned by <a href=\"#vkGetAndroidHardwareBufferPropertiesANDROID\">vkGetAndroidHardwareBufferPropertiesANDROID</a> in <a href=\"#VkAndroidHardwareBufferFormatPropertiesANDROID\">VkAndroidHardwareBufferFormatPropertiesANDROID</a>::<code>format</code> for the Android hardware buffer"
         },
         {
           "vuid": "VUID-VkMemoryAllocateInfo-pNext-02388",
-          "text": " If the parameters define an import operation, the external handle is an Android hardware buffer, and the <code>pNext</code> chain includes a <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a> structure with <code>image</code> that is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, the width, height, and array layer dimensions of <code>image</code> and the Android hardware buffer&#8217;s <code>AHardwareBuffer_Desc</code> <strong class=\"purple\">must</strong> be identical."
+          "text": " If the parameters define an import operation, the external handle is an Android hardware buffer, and the <code>pNext</code> chain includes a <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a> structure with <code>image</code> that is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, the width, height, and array layer dimensions of <code>image</code> and the Android hardware buffer&#8217;s <code>AHardwareBuffer_Desc</code> <strong class=\"purple\">must</strong> be identical"
         },
         {
           "vuid": "VUID-VkMemoryAllocateInfo-pNext-02389",
-          "text": " If the parameters define an import operation, the external handle is an Android hardware buffer, and the <code>pNext</code> chain includes a <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a> structure with <code>image</code> that is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, and the Android hardware buffer&#8217;s <a href=\"#AHardwareBuffer\">AHardwareBuffer</a>::<code>usage</code> includes <code>AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE</code>, the <code>image</code> <strong class=\"purple\">must</strong> have a complete mipmap chain."
+          "text": " If the parameters define an import operation, the external handle is an Android hardware buffer, and the <code>pNext</code> chain includes a <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a> structure with <code>image</code> that is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, and the Android hardware buffer&#8217;s <a href=\"#AHardwareBuffer\">AHardwareBuffer</a>::<code>usage</code> includes <code>AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE</code>, the <code>image</code> <strong class=\"purple\">must</strong> have a complete mipmap chain"
         },
         {
           "vuid": "VUID-VkMemoryAllocateInfo-pNext-02586",
-          "text": " If the parameters define an import operation, the external handle is an Android hardware buffer, and the <code>pNext</code> chain includes a <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a> structure with <code>image</code> that is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, and the Android hardware buffer&#8217;s <a href=\"#AHardwareBuffer\">AHardwareBuffer</a>::<code>usage</code> does not include <code>AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE</code>, the <code>image</code> <strong class=\"purple\">must</strong> have exactly one mipmap level."
+          "text": " If the parameters define an import operation, the external handle is an Android hardware buffer, and the <code>pNext</code> chain includes a <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a> structure with <code>image</code> that is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, and the Android hardware buffer&#8217;s <a href=\"#AHardwareBuffer\">AHardwareBuffer</a>::<code>usage</code> does not include <code>AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE</code>, the <code>image</code> <strong class=\"purple\">must</strong> have exactly one mipmap level"
         },
         {
           "vuid": "VUID-VkMemoryAllocateInfo-pNext-02390",
-          "text": " If the parameters define an import operation, the external handle is an Android hardware buffer, and the <code>pNext</code> chain includes a <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a> structure with <code>image</code> that is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, each bit set in the usage of <code>image</code> <strong class=\"purple\">must</strong> be listed in <a href=\"#memory-external-android-hardware-buffer-usage\">AHardwareBuffer Usage Equivalence</a>, and if there is a corresponding <code>AHARDWAREBUFFER_USAGE</code> bit listed that bit <strong class=\"purple\">must</strong> be included in the Android hardware buffer&#8217;s <code>AHardwareBuffer_Desc</code>::<code>usage</code>."
+          "text": " If the parameters define an import operation, the external handle is an Android hardware buffer, and the <code>pNext</code> chain includes a <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a> structure with <code>image</code> that is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, each bit set in the usage of <code>image</code> <strong class=\"purple\">must</strong> be listed in <a href=\"#memory-external-android-hardware-buffer-usage\">AHardwareBuffer Usage Equivalence</a>, and if there is a corresponding <code>AHARDWAREBUFFER_USAGE</code> bit listed that bit <strong class=\"purple\">must</strong> be included in the Android hardware buffer&#8217;s <code>AHardwareBuffer_Desc</code>::<code>usage</code>"
         }
       ],
       "(VK_VERSION_1_2,VK_KHR_buffer_device_address)": [
@@ -7687,16 +8315,8 @@
           "text": " At least one of <code>image</code> and <code>buffer</code> <strong class=\"purple\">must</strong> be <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>"
         },
         {
-          "vuid": "VUID-VkMemoryDedicatedAllocateInfo-image-01433",
-          "text": " If <code>image</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, <code>VkMemoryAllocateInfo</code>::<code>allocationSize</code> <strong class=\"purple\">must</strong> equal the <code>VkMemoryRequirements</code>::<code>size</code> of the image"
-        },
-        {
           "vuid": "VUID-VkMemoryDedicatedAllocateInfo-image-01434",
-          "text": " If <code>image</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, <code>image</code> <strong class=\"purple\">must</strong> have been created without <code>VK_IMAGE_CREATE_SPARSE_BINDING_BIT</code> set in <code>VkImageCreateInfo</code>::<code>flags</code>"
-        },
-        {
-          "vuid": "VUID-VkMemoryDedicatedAllocateInfo-buffer-01435",
-          "text": " If <code>buffer</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, <code>VkMemoryAllocateInfo</code>::<code>allocationSize</code> <strong class=\"purple\">must</strong> equal the <code>VkMemoryRequirements</code>::<code>size</code> of the buffer"
+          "text": " If <code>image</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, <code>image</code> <strong class=\"purple\">must</strong> have been created without <code>VK_IMAGE_CREATE_SPARSE_BINDING_BIT</code> set in <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>flags</code>"
         },
         {
           "vuid": "VUID-VkMemoryDedicatedAllocateInfo-buffer-01436",
@@ -7719,24 +8339,44 @@
           "text": " Both of <code>buffer</code>, and <code>image</code> that are valid handles of non-ignored parameters <strong class=\"purple\">must</strong> have been created, allocated, or retrieved from the same <a href=\"#VkDevice\">VkDevice</a>"
         }
       ],
+      "(VK_VERSION_1_1,VK_KHR_dedicated_allocation)+!(VK_ANDROID_external_memory_android_hardware_buffer)": [
+        {
+          "vuid": "VUID-VkMemoryDedicatedAllocateInfo-image-01433",
+          "text": " If <code>image</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, <code>VkMemoryAllocateInfo</code>::<code>allocationSize</code> <strong class=\"purple\">must</strong> equal the <code>VkMemoryRequirements</code>::<code>size</code> of the image"
+        },
+        {
+          "vuid": "VUID-VkMemoryDedicatedAllocateInfo-buffer-01435",
+          "text": " If <code>buffer</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, <code>VkMemoryAllocateInfo</code>::<code>allocationSize</code> <strong class=\"purple\">must</strong> equal the <code>VkMemoryRequirements</code>::<code>size</code> of the buffer"
+        }
+      ],
+      "(VK_VERSION_1_1,VK_KHR_dedicated_allocation)+(VK_ANDROID_external_memory_android_hardware_buffer)": [
+        {
+          "vuid": "VUID-VkMemoryDedicatedAllocateInfo-image-02964",
+          "text": " If <code>image</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a> and the memory is not an imported Android Hardware Buffer, <code>VkMemoryAllocateInfo</code>::<code>allocationSize</code> <strong class=\"purple\">must</strong> equal the <code>VkMemoryRequirements</code>::<code>size</code> of the image"
+        },
+        {
+          "vuid": "VUID-VkMemoryDedicatedAllocateInfo-buffer-02965",
+          "text": " If <code>buffer</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a> and the memory is not an imported Android Hardware Buffer, <code>VkMemoryAllocateInfo</code>::<code>allocationSize</code> <strong class=\"purple\">must</strong> equal the <code>VkMemoryRequirements</code>::<code>size</code> of the buffer"
+        }
+      ],
       "(VK_VERSION_1_1,VK_KHR_dedicated_allocation)+(VK_KHR_external_memory_win32)": [
         {
           "vuid": "VUID-VkMemoryDedicatedAllocateInfo-image-01876",
-          "text": " If <code>image</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a> and <a href=\"#VkMemoryAllocateInfo\">VkMemoryAllocateInfo</a> defines a memory import operation with handle type <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT</code>, <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT</code>, <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT</code>, <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT</code>, <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT</code>, or <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT</code>, and the external handle was created by the Vulkan API, then the memory being imported <strong class=\"purple\">must</strong> also be a dedicated image allocation and <code>image</code> must be identical to the image associated with the imported memory."
+          "text": " If <code>image</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a> and <a href=\"#VkMemoryAllocateInfo\">VkMemoryAllocateInfo</a> defines a memory import operation with handle type <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT</code>, <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT</code>, <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT</code>, <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT</code>, <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT</code>, or <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT</code>, and the external handle was created by the Vulkan API, then the memory being imported <strong class=\"purple\">must</strong> also be a dedicated image allocation and <code>image</code> must be identical to the image associated with the imported memory"
         },
         {
           "vuid": "VUID-VkMemoryDedicatedAllocateInfo-buffer-01877",
-          "text": " If <code>buffer</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a> and <a href=\"#VkMemoryAllocateInfo\">VkMemoryAllocateInfo</a> defines a memory import operation with handle type <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT</code>, <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT</code>, <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT</code>, <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT</code>, <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT</code>, or <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT</code>, and the external handle was created by the Vulkan API, then the memory being imported <strong class=\"purple\">must</strong> also be a dedicated buffer allocation and <code>buffer</code> must be identical to the buffer associated with the imported memory."
+          "text": " If <code>buffer</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a> and <a href=\"#VkMemoryAllocateInfo\">VkMemoryAllocateInfo</a> defines a memory import operation with handle type <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT</code>, <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT</code>, <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT</code>, <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT</code>, <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT</code>, or <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT</code>, and the external handle was created by the Vulkan API, then the memory being imported <strong class=\"purple\">must</strong> also be a dedicated buffer allocation and <code>buffer</code> must be identical to the buffer associated with the imported memory"
         }
       ],
       "(VK_VERSION_1_1,VK_KHR_dedicated_allocation)+(VK_KHR_external_memory_fd)": [
         {
           "vuid": "VUID-VkMemoryDedicatedAllocateInfo-image-01878",
-          "text": " If <code>image</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a> and <a href=\"#VkMemoryAllocateInfo\">VkMemoryAllocateInfo</a> defines a memory import operation with handle type <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT</code>, the memory being imported <strong class=\"purple\">must</strong> also be a dedicated image allocation and <code>image</code> must be identical to the image associated with the imported memory."
+          "text": " If <code>image</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a> and <a href=\"#VkMemoryAllocateInfo\">VkMemoryAllocateInfo</a> defines a memory import operation with handle type <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT</code>, the memory being imported <strong class=\"purple\">must</strong> also be a dedicated image allocation and <code>image</code> must be identical to the image associated with the imported memory"
         },
         {
           "vuid": "VUID-VkMemoryDedicatedAllocateInfo-buffer-01879",
-          "text": " If <code>buffer</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a> and <a href=\"#VkMemoryAllocateInfo\">VkMemoryAllocateInfo</a> defines a memory import operation with handle type <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT</code>, the memory being imported <strong class=\"purple\">must</strong> also be a dedicated buffer allocation and <code>buffer</code> must be identical to the buffer associated with the imported memory."
+          "text": " If <code>buffer</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a> and <a href=\"#VkMemoryAllocateInfo\">VkMemoryAllocateInfo</a> defines a memory import operation with handle type <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT</code>, the memory being imported <strong class=\"purple\">must</strong> also be a dedicated buffer allocation and <code>buffer</code> must be identical to the buffer associated with the imported memory"
         }
       ],
       "(VK_VERSION_1_1,VK_KHR_dedicated_allocation)+(VK_KHR_sampler_ycbcr_conversion)": [
@@ -7754,11 +8394,11 @@
         },
         {
           "vuid": "VUID-VkDedicatedAllocationMemoryAllocateInfoNV-image-00650",
-          "text": " If <code>image</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, the image <strong class=\"purple\">must</strong> have been created with <code>VkDedicatedAllocationImageCreateInfoNV</code>::<code>dedicatedAllocation</code> equal to <code>VK_TRUE</code>"
+          "text": " If <code>image</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, the image <strong class=\"purple\">must</strong> have been created with <a href=\"#VkDedicatedAllocationImageCreateInfoNV\">VkDedicatedAllocationImageCreateInfoNV</a>::<code>dedicatedAllocation</code> equal to <code>VK_TRUE</code>"
         },
         {
           "vuid": "VUID-VkDedicatedAllocationMemoryAllocateInfoNV-buffer-00651",
-          "text": " If <code>buffer</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, the buffer <strong class=\"purple\">must</strong> have been created with <code>VkDedicatedAllocationBufferCreateInfoNV</code>::<code>dedicatedAllocation</code> equal to <code>VK_TRUE</code>"
+          "text": " If <code>buffer</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, the buffer <strong class=\"purple\">must</strong> have been created with <a href=\"#VkDedicatedAllocationBufferCreateInfoNV\">VkDedicatedAllocationBufferCreateInfoNV</a>::<code>dedicatedAllocation</code> equal to <code>VK_TRUE</code>"
         },
         {
           "vuid": "VUID-VkDedicatedAllocationMemoryAllocateInfoNV-image-00652",
@@ -7788,11 +8428,11 @@
       "(VK_NV_dedicated_allocation)+(VK_KHR_external_memory_win32,VK_KHR_external_memory_fd)": [
         {
           "vuid": "VUID-VkDedicatedAllocationMemoryAllocateInfoNV-image-00654",
-          "text": " If <code>image</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a> and <a href=\"#VkMemoryAllocateInfo\">VkMemoryAllocateInfo</a> defines a memory import operation, the memory being imported <strong class=\"purple\">must</strong> also be a dedicated image allocation and <code>image</code> <strong class=\"purple\">must</strong> be identical to the image associated with the imported memory."
+          "text": " If <code>image</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a> and <a href=\"#VkMemoryAllocateInfo\">VkMemoryAllocateInfo</a> defines a memory import operation, the memory being imported <strong class=\"purple\">must</strong> also be a dedicated image allocation and <code>image</code> <strong class=\"purple\">must</strong> be identical to the image associated with the imported memory"
         },
         {
           "vuid": "VUID-VkDedicatedAllocationMemoryAllocateInfoNV-buffer-00655",
-          "text": " If <code>buffer</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a> and <a href=\"#VkMemoryAllocateInfo\">VkMemoryAllocateInfo</a> defines a memory import operation, the memory being imported <strong class=\"purple\">must</strong> also be a dedicated buffer allocation and <code>buffer</code> <strong class=\"purple\">must</strong> be identical to the buffer associated with the imported memory."
+          "text": " If <code>buffer</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a> and <a href=\"#VkMemoryAllocateInfo\">VkMemoryAllocateInfo</a> defines a memory import operation, the memory being imported <strong class=\"purple\">must</strong> also be a dedicated buffer allocation and <code>buffer</code> <strong class=\"purple\">must</strong> be identical to the buffer associated with the imported memory"
         }
       ]
     },
@@ -7812,7 +8452,7 @@
       "(VK_VERSION_1_1,VK_KHR_external_memory)": [
         {
           "vuid": "VUID-VkExportMemoryAllocateInfo-handleTypes-00656",
-          "text": " The bits in <code>handleTypes</code> <strong class=\"purple\">must</strong> be supported and compatible, as reported by <a href=\"#VkExternalImageFormatProperties\">VkExternalImageFormatProperties</a> or <a href=\"#VkExternalBufferProperties\">VkExternalBufferProperties</a>."
+          "text": " The bits in <code>handleTypes</code> <strong class=\"purple\">must</strong> be supported and compatible, as reported by <a href=\"#VkExternalImageFormatProperties\">VkExternalImageFormatProperties</a> or <a href=\"#VkExternalBufferProperties\">VkExternalBufferProperties</a>"
         },
         {
           "vuid": "VUID-VkExportMemoryAllocateInfo-sType-sType",
@@ -7828,7 +8468,7 @@
       "(VK_KHR_external_memory_win32)": [
         {
           "vuid": "VUID-VkExportMemoryWin32HandleInfoKHR-handleTypes-00657",
-          "text": " If <a href=\"#VkExportMemoryAllocateInfo\">VkExportMemoryAllocateInfo</a>::<code>handleTypes</code> does not include <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT</code>, <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT</code>, <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT</code>, or <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT</code>, a <code>VkExportMemoryWin32HandleInfoKHR</code> structure <strong class=\"purple\">must</strong> not be included in the <code>pNext</code> chain of <a href=\"#VkMemoryAllocateInfo\">VkMemoryAllocateInfo</a>."
+          "text": " If <a href=\"#VkExportMemoryAllocateInfo\">VkExportMemoryAllocateInfo</a>::<code>handleTypes</code> does not include <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT</code>, <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT</code>, <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT</code>, or <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT</code>, a <code>VkExportMemoryWin32HandleInfoKHR</code> structure <strong class=\"purple\">must</strong> not be included in the <code>pNext</code> chain of <a href=\"#VkMemoryAllocateInfo\">VkMemoryAllocateInfo</a>"
         },
         {
           "vuid": "VUID-VkExportMemoryWin32HandleInfoKHR-sType-sType",
@@ -7844,39 +8484,39 @@
       "(VK_KHR_external_memory_win32)": [
         {
           "vuid": "VUID-VkImportMemoryWin32HandleInfoKHR-handleType-00658",
-          "text": " If <code>handleType</code> is not <code>0</code>, it <strong class=\"purple\">must</strong> be supported for import, as reported by <a href=\"#VkExternalImageFormatProperties\">VkExternalImageFormatProperties</a> or <a href=\"#VkExternalBufferProperties\">VkExternalBufferProperties</a>."
+          "text": " If <code>handleType</code> is not <code>0</code>, it <strong class=\"purple\">must</strong> be supported for import, as reported by <a href=\"#VkExternalImageFormatProperties\">VkExternalImageFormatProperties</a> or <a href=\"#VkExternalBufferProperties\">VkExternalBufferProperties</a>"
         },
         {
           "vuid": "VUID-VkImportMemoryWin32HandleInfoKHR-handle-00659",
-          "text": " The memory from which <code>handle</code> was exported, or the memory named by <code>name</code> <strong class=\"purple\">must</strong> have been created on the same underlying physical device as <code>device</code>."
+          "text": " The memory from which <code>handle</code> was exported, or the memory named by <code>name</code> <strong class=\"purple\">must</strong> have been created on the same underlying physical device as <code>device</code>"
         },
         {
           "vuid": "VUID-VkImportMemoryWin32HandleInfoKHR-handleType-00660",
-          "text": " If <code>handleType</code> is not <code>0</code>, it <strong class=\"purple\">must</strong> be defined as an NT handle or a global share handle."
+          "text": " If <code>handleType</code> is not <code>0</code>, it <strong class=\"purple\">must</strong> be defined as an NT handle or a global share handle"
         },
         {
           "vuid": "VUID-VkImportMemoryWin32HandleInfoKHR-handleType-01439",
-          "text": " If <code>handleType</code> is not <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT</code>, <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT</code>, <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT</code>, or <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT</code>, <code>name</code> <strong class=\"purple\">must</strong> be <code>NULL</code>."
+          "text": " If <code>handleType</code> is not <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT</code>, <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT</code>, <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT</code>, or <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT</code>, <code>name</code> <strong class=\"purple\">must</strong> be <code>NULL</code>"
         },
         {
           "vuid": "VUID-VkImportMemoryWin32HandleInfoKHR-handleType-01440",
-          "text": " If <code>handleType</code> is not <code>0</code> and <code>handle</code> is <code>NULL</code>, <code>name</code> <strong class=\"purple\">must</strong> name a valid memory resource of the type specified by <code>handleType</code>."
+          "text": " If <code>handleType</code> is not <code>0</code> and <code>handle</code> is <code>NULL</code>, <code>name</code> <strong class=\"purple\">must</strong> name a valid memory resource of the type specified by <code>handleType</code>"
         },
         {
           "vuid": "VUID-VkImportMemoryWin32HandleInfoKHR-handleType-00661",
-          "text": " If <code>handleType</code> is not <code>0</code> and <code>name</code> is <code>NULL</code>, <code>handle</code> <strong class=\"purple\">must</strong> be a valid handle of the type specified by <code>handleType</code>."
+          "text": " If <code>handleType</code> is not <code>0</code> and <code>name</code> is <code>NULL</code>, <code>handle</code> <strong class=\"purple\">must</strong> be a valid handle of the type specified by <code>handleType</code>"
         },
         {
           "vuid": "VUID-VkImportMemoryWin32HandleInfoKHR-handle-01441",
-          "text": " if <code>handle</code> is not <code>NULL</code>, <code>name</code> must be <code>NULL</code>."
+          "text": " if <code>handle</code> is not <code>NULL</code>, <code>name</code> must be <code>NULL</code>"
         },
         {
           "vuid": "VUID-VkImportMemoryWin32HandleInfoKHR-handle-01518",
-          "text": " If <code>handle</code> is not <code>NULL</code>, it <strong class=\"purple\">must</strong> obey any requirements listed for <code>handleType</code> in <a href=\"#external-memory-handle-types-compatibility\">external memory handle types compatibility</a>."
+          "text": " If <code>handle</code> is not <code>NULL</code>, it <strong class=\"purple\">must</strong> obey any requirements listed for <code>handleType</code> in <a href=\"#external-memory-handle-types-compatibility\">external memory handle types compatibility</a>"
         },
         {
           "vuid": "VUID-VkImportMemoryWin32HandleInfoKHR-name-01519",
-          "text": " If <code>name</code> is not <code>NULL</code>, it <strong class=\"purple\">must</strong> obey any requirements listed for <code>handleType</code> in <a href=\"#external-memory-handle-types-compatibility\">external memory handle types compatibility</a>."
+          "text": " If <code>name</code> is not <code>NULL</code>, it <strong class=\"purple\">must</strong> obey any requirements listed for <code>handleType</code> in <a href=\"#external-memory-handle-types-compatibility\">external memory handle types compatibility</a>"
         },
         {
           "vuid": "VUID-VkImportMemoryWin32HandleInfoKHR-sType-sType",
@@ -7908,15 +8548,15 @@
       "(VK_KHR_external_memory_win32)": [
         {
           "vuid": "VUID-VkMemoryGetWin32HandleInfoKHR-handleType-00662",
-          "text": " <code>handleType</code> <strong class=\"purple\">must</strong> have been included in <a href=\"#VkExportMemoryAllocateInfo\">VkExportMemoryAllocateInfo</a>::<code>handleTypes</code> when <code>memory</code> was created."
+          "text": " <code>handleType</code> <strong class=\"purple\">must</strong> have been included in <a href=\"#VkExportMemoryAllocateInfo\">VkExportMemoryAllocateInfo</a>::<code>handleTypes</code> when <code>memory</code> was created"
         },
         {
           "vuid": "VUID-VkMemoryGetWin32HandleInfoKHR-handleType-00663",
-          "text": " If <code>handleType</code> is defined as an NT handle, <a href=\"#vkGetMemoryWin32HandleKHR\">vkGetMemoryWin32HandleKHR</a> <strong class=\"purple\">must</strong> be called no more than once for each valid unique combination of <code>memory</code> and <code>handleType</code>."
+          "text": " If <code>handleType</code> is defined as an NT handle, <a href=\"#vkGetMemoryWin32HandleKHR\">vkGetMemoryWin32HandleKHR</a> <strong class=\"purple\">must</strong> be called no more than once for each valid unique combination of <code>memory</code> and <code>handleType</code>"
         },
         {
           "vuid": "VUID-VkMemoryGetWin32HandleInfoKHR-handleType-00664",
-          "text": " <code>handleType</code> <strong class=\"purple\">must</strong> be defined as an NT handle or a global share handle."
+          "text": " <code>handleType</code> <strong class=\"purple\">must</strong> be defined as an NT handle or a global share handle"
         },
         {
           "vuid": "VUID-VkMemoryGetWin32HandleInfoKHR-sType-sType",
@@ -7940,11 +8580,11 @@
       "(VK_KHR_external_memory_win32)": [
         {
           "vuid": "VUID-vkGetMemoryWin32HandlePropertiesKHR-handle-00665",
-          "text": " <code>handle</code> <strong class=\"purple\">must</strong> be an external memory handle created outside of the Vulkan API."
+          "text": " <code>handle</code> <strong class=\"purple\">must</strong> be an external memory handle created outside of the Vulkan API"
         },
         {
           "vuid": "VUID-vkGetMemoryWin32HandlePropertiesKHR-handleType-00666",
-          "text": " <code>handleType</code> <strong class=\"purple\">must</strong> not be one of the handle types defined as opaque."
+          "text": " <code>handleType</code> <strong class=\"purple\">must</strong> not be one of the handle types defined as opaque"
         },
         {
           "vuid": "VUID-vkGetMemoryWin32HandlePropertiesKHR-device-parameter",
@@ -7976,27 +8616,27 @@
       "(VK_KHR_external_memory_fd)": [
         {
           "vuid": "VUID-VkImportMemoryFdInfoKHR-handleType-00667",
-          "text": " If <code>handleType</code> is not <code>0</code>, it <strong class=\"purple\">must</strong> be supported for import, as reported by <a href=\"#VkExternalImageFormatProperties\">VkExternalImageFormatProperties</a> or <a href=\"#VkExternalBufferProperties\">VkExternalBufferProperties</a>."
+          "text": " If <code>handleType</code> is not <code>0</code>, it <strong class=\"purple\">must</strong> be supported for import, as reported by <a href=\"#VkExternalImageFormatProperties\">VkExternalImageFormatProperties</a> or <a href=\"#VkExternalBufferProperties\">VkExternalBufferProperties</a>"
         },
         {
           "vuid": "VUID-VkImportMemoryFdInfoKHR-fd-00668",
-          "text": " The memory from which <code>fd</code> was exported <strong class=\"purple\">must</strong> have been created on the same underlying physical device as <code>device</code>."
+          "text": " The memory from which <code>fd</code> was exported <strong class=\"purple\">must</strong> have been created on the same underlying physical device as <code>device</code>"
         },
         {
           "vuid": "VUID-VkImportMemoryFdInfoKHR-handleType-00669",
-          "text": " If <code>handleType</code> is not <code>0</code>, it <strong class=\"purple\">must</strong> be defined as a POSIX file descriptor handle."
+          "text": " If <code>handleType</code> is not <code>0</code>, it <strong class=\"purple\">must</strong> be defined as a POSIX file descriptor handle"
         },
         {
           "vuid": "VUID-VkImportMemoryFdInfoKHR-handleType-00670",
-          "text": " If <code>handleType</code> is not <code>0</code>, <code>fd</code> <strong class=\"purple\">must</strong> be a valid handle of the type specified by <code>handleType</code>."
+          "text": " If <code>handleType</code> is not <code>0</code>, <code>fd</code> <strong class=\"purple\">must</strong> be a valid handle of the type specified by <code>handleType</code>"
         },
         {
           "vuid": "VUID-VkImportMemoryFdInfoKHR-fd-01746",
-          "text": " The memory represented by <code>fd</code> <strong class=\"purple\">must</strong> have been created from a physical device and driver that is compatible with <code>device</code> and <code>handleType</code>, as described in <a href=\"#external-memory-handle-types-compatibility\">External memory handle types compatibility</a>."
+          "text": " The memory represented by <code>fd</code> <strong class=\"purple\">must</strong> have been created from a physical device and driver that is compatible with <code>device</code> and <code>handleType</code>, as described in <a href=\"#external-memory-handle-types-compatibility\">External memory handle types compatibility</a>"
         },
         {
           "vuid": "VUID-VkImportMemoryFdInfoKHR-fd-01520",
-          "text": " <code>fd</code> <strong class=\"purple\">must</strong> obey any requirements listed for <code>handleType</code> in <a href=\"#external-memory-handle-types-compatibility\">external memory handle types compatibility</a>."
+          "text": " <code>fd</code> <strong class=\"purple\">must</strong> obey any requirements listed for <code>handleType</code> in <a href=\"#external-memory-handle-types-compatibility\">external memory handle types compatibility</a>"
         },
         {
           "vuid": "VUID-VkImportMemoryFdInfoKHR-sType-sType",
@@ -8028,11 +8668,11 @@
       "(VK_KHR_external_memory_fd)": [
         {
           "vuid": "VUID-VkMemoryGetFdInfoKHR-handleType-00671",
-          "text": " <code>handleType</code> <strong class=\"purple\">must</strong> have been included in <a href=\"#VkExportMemoryAllocateInfo\">VkExportMemoryAllocateInfo</a>::<code>handleTypes</code> when <code>memory</code> was created."
+          "text": " <code>handleType</code> <strong class=\"purple\">must</strong> have been included in <a href=\"#VkExportMemoryAllocateInfo\">VkExportMemoryAllocateInfo</a>::<code>handleTypes</code> when <code>memory</code> was created"
         },
         {
           "vuid": "VUID-VkMemoryGetFdInfoKHR-handleType-00672",
-          "text": " <code>handleType</code> <strong class=\"purple\">must</strong> be defined as a POSIX file descriptor handle."
+          "text": " <code>handleType</code> <strong class=\"purple\">must</strong> be defined as a POSIX file descriptor handle"
         },
         {
           "vuid": "VUID-VkMemoryGetFdInfoKHR-sType-sType",
@@ -8056,11 +8696,11 @@
       "(VK_KHR_external_memory_fd)": [
         {
           "vuid": "VUID-vkGetMemoryFdPropertiesKHR-fd-00673",
-          "text": " <code>fd</code> <strong class=\"purple\">must</strong> be an external memory handle created outside of the Vulkan API."
+          "text": " <code>fd</code> <strong class=\"purple\">must</strong> be an external memory handle created outside of the Vulkan API"
         },
         {
           "vuid": "VUID-vkGetMemoryFdPropertiesKHR-handleType-00674",
-          "text": " <code>handleType</code> <strong class=\"purple\">must</strong> not be <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR</code>."
+          "text": " <code>handleType</code> <strong class=\"purple\">must</strong> not be <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR</code>"
         },
         {
           "vuid": "VUID-vkGetMemoryFdPropertiesKHR-device-parameter",
@@ -8168,11 +8808,11 @@
       "(VK_ANDROID_external_memory_android_hardware_buffer)": [
         {
           "vuid": "VUID-VkImportAndroidHardwareBufferInfoANDROID-buffer-01880",
-          "text": " If <code>buffer</code> is not <code>NULL</code>, Android hardware buffers <strong class=\"purple\">must</strong> be supported for import, as reported by <a href=\"#VkExternalImageFormatProperties\">VkExternalImageFormatProperties</a> or <a href=\"#VkExternalBufferProperties\">VkExternalBufferProperties</a>."
+          "text": " If <code>buffer</code> is not <code>NULL</code>, Android hardware buffers <strong class=\"purple\">must</strong> be supported for import, as reported by <a href=\"#VkExternalImageFormatProperties\">VkExternalImageFormatProperties</a> or <a href=\"#VkExternalBufferProperties\">VkExternalBufferProperties</a>"
         },
         {
           "vuid": "VUID-VkImportAndroidHardwareBufferInfoANDROID-buffer-01881",
-          "text": " If <code>buffer</code> is not <code>NULL</code>, it <strong class=\"purple\">must</strong> be a valid Android hardware buffer object with <code>AHardwareBuffer_Desc</code>::<code>format</code> and <code>AHardwareBuffer_Desc</code>::<code>usage</code> compatible with Vulkan as described in <a href=\"#memory-external-android-hardware-buffer\">Android Hardware Buffers</a>."
+          "text": " If <code>buffer</code> is not <code>NULL</code>, it <strong class=\"purple\">must</strong> be a valid Android hardware buffer object with <code>AHardwareBuffer_Desc</code>::<code>format</code> and <code>AHardwareBuffer_Desc</code>::<code>usage</code> compatible with Vulkan as described in <a href=\"#memory-external-android-hardware-buffer\">Android Hardware Buffers</a>"
         },
         {
           "vuid": "VUID-VkImportAndroidHardwareBufferInfoANDROID-sType-sType",
@@ -8204,11 +8844,11 @@
       "(VK_ANDROID_external_memory_android_hardware_buffer)": [
         {
           "vuid": "VUID-VkMemoryGetAndroidHardwareBufferInfoANDROID-handleTypes-01882",
-          "text": " <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID</code> <strong class=\"purple\">must</strong> have been included in <a href=\"#VkExportMemoryAllocateInfo\">VkExportMemoryAllocateInfo</a>::<code>handleTypes</code> when <code>memory</code> was created."
+          "text": " <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID</code> <strong class=\"purple\">must</strong> have been included in <a href=\"#VkExportMemoryAllocateInfo\">VkExportMemoryAllocateInfo</a>::<code>handleTypes</code> when <code>memory</code> was created"
         },
         {
           "vuid": "VUID-VkMemoryGetAndroidHardwareBufferInfoANDROID-pNext-01883",
-          "text": " If the <code>pNext</code> chain of the <a href=\"#VkMemoryAllocateInfo\">VkMemoryAllocateInfo</a> used to allocate <code>memory</code> included a <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a> with non-<code>NULL</code> <code>image</code> member, then that <code>image</code> <strong class=\"purple\">must</strong> already be bound to <code>memory</code>."
+          "text": " If the <code>pNext</code> chain of the <a href=\"#VkMemoryAllocateInfo\">VkMemoryAllocateInfo</a> used to allocate <code>memory</code> included a <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a> with non-<code>NULL</code> <code>image</code> member, then that <code>image</code> <strong class=\"purple\">must</strong> already be bound to <code>memory</code>"
         },
         {
           "vuid": "VUID-VkMemoryGetAndroidHardwareBufferInfoANDROID-sType-sType",
@@ -8296,11 +8936,11 @@
       "(VK_NV_external_memory_win32)": [
         {
           "vuid": "VUID-VkImportMemoryWin32HandleInfoNV-handleType-01327",
-          "text": " <code>handleType</code> <strong class=\"purple\">must</strong> not have more than one bit set."
+          "text": " <code>handleType</code> <strong class=\"purple\">must</strong> not have more than one bit set"
         },
         {
           "vuid": "VUID-VkImportMemoryWin32HandleInfoNV-handle-01328",
-          "text": " <code>handle</code> <strong class=\"purple\">must</strong> be a valid handle to memory, obtained as specified by <code>handleType</code>."
+          "text": " <code>handle</code> <strong class=\"purple\">must</strong> be a valid handle to memory, obtained as specified by <code>handleType</code>"
         },
         {
           "vuid": "VUID-VkImportMemoryWin32HandleInfoNV-sType-sType",
@@ -8348,7 +8988,7 @@
       "(VK_VERSION_1_1,VK_KHR_device_group)": [
         {
           "vuid": "VUID-VkMemoryAllocateFlagsInfo-deviceMask-00675",
-          "text": " If <code>VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT</code> is set, <code>deviceMask</code> <strong class=\"purple\">must</strong> be a valid device mask."
+          "text": " If <code>VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT</code> is set, <code>deviceMask</code> <strong class=\"purple\">must</strong> be a valid device mask"
         },
         {
           "vuid": "VUID-VkMemoryAllocateFlagsInfo-deviceMask-00676",
@@ -8442,7 +9082,7 @@
       "(VK_KHR_device_group)": [
         {
           "vuid": "VUID-vkMapMemory-memory-00683",
-          "text": " <code>memory</code> <strong class=\"purple\">must</strong> not have been allocated with multiple instances."
+          "text": " <code>memory</code> <strong class=\"purple\">must</strong> not have been allocated with multiple instances"
         }
       ]
     },
@@ -8494,7 +9134,7 @@
         },
         {
           "vuid": "VUID-VkMappedMemoryRange-size-01389",
-          "text": " If <code>size</code> is equal to <code>VK_WHOLE_SIZE</code>, the end of the current mapping of <code>memory</code> <strong class=\"purple\">must</strong> be a multiple of <a href=\"#VkPhysicalDeviceLimits\">VkPhysicalDeviceLimits</a>::<code>nonCoherentAtomSize</code> bytes from the beginning of the memory object."
+          "text": " If <code>size</code> is equal to <code>VK_WHOLE_SIZE</code>, the end of the current mapping of <code>memory</code> <strong class=\"purple\">must</strong> be a multiple of <a href=\"#VkPhysicalDeviceLimits\">VkPhysicalDeviceLimits</a>::<code>nonCoherentAtomSize</code> bytes from the beginning of the memory object"
         },
         {
           "vuid": "VUID-VkMappedMemoryRange-offset-00687",
@@ -8502,7 +9142,7 @@
         },
         {
           "vuid": "VUID-VkMappedMemoryRange-size-01390",
-          "text": " If <code>size</code> is not equal to <code>VK_WHOLE_SIZE</code>, <code>size</code> <strong class=\"purple\">must</strong> either be a multiple of <a href=\"#VkPhysicalDeviceLimits\">VkPhysicalDeviceLimits</a>::<code>nonCoherentAtomSize</code>, or <code>offset</code> plus <code>size</code> <strong class=\"purple\">must</strong> equal the size of <code>memory</code>."
+          "text": " If <code>size</code> is not equal to <code>VK_WHOLE_SIZE</code>, <code>size</code> <strong class=\"purple\">must</strong> either be a multiple of <a href=\"#VkPhysicalDeviceLimits\">VkPhysicalDeviceLimits</a>::<code>nonCoherentAtomSize</code>, or <code>offset</code> plus <code>size</code> <strong class=\"purple\">must</strong> equal the size of <code>memory</code>"
         },
         {
           "vuid": "VUID-VkMappedMemoryRange-sType-sType",
@@ -8994,7 +9634,7 @@
       "core": [
         {
           "vuid": "VUID-VkImageCreateInfo-imageCreateMaxMipLevels-02251",
-          "text": " Each of the following values (as described in <a href=\"#resources-image-creation-limits\">Image Creation Limits</a>) <strong class=\"purple\">must</strong> not be undefined <code>imageCreateMaxMipLevels</code>, <code>imageCreateMaxArrayLayers</code>, <code>imageCreateMaxExtent</code>, and <code>imageCreateSampleCounts</code>."
+          "text": " Each of the following values (as described in <a href=\"#resources-image-creation-limits\">Image Creation Limits</a>) <strong class=\"purple\">must</strong> not be undefined <code>imageCreateMaxMipLevels</code>, <code>imageCreateMaxArrayLayers</code>, <code>imageCreateMaxExtent</code>, and <code>imageCreateSampleCounts</code>"
         },
         {
           "vuid": "VUID-VkImageCreateInfo-sharingMode-00941",
@@ -9006,15 +9646,15 @@
         },
         {
           "vuid": "VUID-VkImageCreateInfo-extent-00944",
-          "text": " <code>extent.width</code> <strong class=\"purple\">must</strong> be greater than <code>0</code>."
+          "text": " <code>extent.width</code> <strong class=\"purple\">must</strong> be greater than <code>0</code>"
         },
         {
           "vuid": "VUID-VkImageCreateInfo-extent-00945",
-          "text": " <code>extent.height</code> <strong class=\"purple\">must</strong> be greater than <code>0</code>."
+          "text": " <code>extent.height</code> <strong class=\"purple\">must</strong> be greater than <code>0</code>"
         },
         {
           "vuid": "VUID-VkImageCreateInfo-extent-00946",
-          "text": " <code>extent.depth</code> <strong class=\"purple\">must</strong> be greater than <code>0</code>."
+          "text": " <code>extent.depth</code> <strong class=\"purple\">must</strong> be greater than <code>0</code>"
         },
         {
           "vuid": "VUID-VkImageCreateInfo-mipLevels-00947",
@@ -9030,15 +9670,15 @@
         },
         {
           "vuid": "VUID-VkImageCreateInfo-extent-02252",
-          "text": " <code>extent.width</code> <strong class=\"purple\">must</strong> be less than or equal to <code>imageCreateMaxExtent.width</code> (as defined in <a href=\"#resources-image-creation-limits\">Image Creation Limits</a>)."
+          "text": " <code>extent.width</code> <strong class=\"purple\">must</strong> be less than or equal to <code>imageCreateMaxExtent.width</code> (as defined in <a href=\"#resources-image-creation-limits\">Image Creation Limits</a>)"
         },
         {
           "vuid": "VUID-VkImageCreateInfo-extent-02253",
-          "text": " <code>extent.height</code> <strong class=\"purple\">must</strong> be less than or equal to <code>imageCreateMaxExtent.height</code> (as defined in <a href=\"#resources-image-creation-limits\">Image Creation Limits</a>)."
+          "text": " <code>extent.height</code> <strong class=\"purple\">must</strong> be less than or equal to <code>imageCreateMaxExtent.height</code> (as defined in <a href=\"#resources-image-creation-limits\">Image Creation Limits</a>)"
         },
         {
           "vuid": "VUID-VkImageCreateInfo-extent-02254",
-          "text": " <code>extent.depth</code> <strong class=\"purple\">must</strong> be less than or equal to <code>imageCreateMaxExtent.depth</code> (as defined in <a href=\"#resources-image-creation-limits\">Image Creation Limits</a>)."
+          "text": " <code>extent.depth</code> <strong class=\"purple\">must</strong> be less than or equal to <code>imageCreateMaxExtent.depth</code> (as defined in <a href=\"#resources-image-creation-limits\">Image Creation Limits</a>)"
         },
         {
           "vuid": "VUID-VkImageCreateInfo-imageType-00954",
@@ -9054,19 +9694,19 @@
         },
         {
           "vuid": "VUID-VkImageCreateInfo-mipLevels-00958",
-          "text": " <code>mipLevels</code> <strong class=\"purple\">must</strong> be less than or equal to the number of levels in the complete mipmap chain based on <span class=\"eq\"><code>extent.width</code></span>, <span class=\"eq\"><code>extent.height</code></span>, and <span class=\"eq\"><code>extent.depth</code></span>."
+          "text": " <code>mipLevels</code> <strong class=\"purple\">must</strong> be less than or equal to the number of levels in the complete mipmap chain based on <span class=\"eq\"><code>extent.width</code></span>, <span class=\"eq\"><code>extent.height</code></span>, and <span class=\"eq\"><code>extent.depth</code></span>"
         },
         {
           "vuid": "VUID-VkImageCreateInfo-mipLevels-02255",
-          "text": " <code>mipLevels</code> <strong class=\"purple\">must</strong> be less than or equal to <code>imageCreateMaxMipLevels</code> (as defined in <a href=\"#resources-image-creation-limits\">Image Creation Limits</a>)."
+          "text": " <code>mipLevels</code> <strong class=\"purple\">must</strong> be less than or equal to <code>imageCreateMaxMipLevels</code> (as defined in <a href=\"#resources-image-creation-limits\">Image Creation Limits</a>)"
         },
         {
           "vuid": "VUID-VkImageCreateInfo-arrayLayers-02256",
-          "text": " <code>arrayLayers</code> <strong class=\"purple\">must</strong> be less than or equal to <code>imageCreateMaxArrayLayers</code> (as defined in <a href=\"#resources-image-creation-limits\">Image Creation Limits</a>)."
+          "text": " <code>arrayLayers</code> <strong class=\"purple\">must</strong> be less than or equal to <code>imageCreateMaxArrayLayers</code> (as defined in <a href=\"#resources-image-creation-limits\">Image Creation Limits</a>)"
         },
         {
           "vuid": "VUID-VkImageCreateInfo-imageType-00961",
-          "text": " If <code>imageType</code> is <code>VK_IMAGE_TYPE_3D</code>, <code>arrayLayers</code> <strong class=\"purple\">must</strong> be <code>1</code>."
+          "text": " If <code>imageType</code> is <code>VK_IMAGE_TYPE_3D</code>, <code>arrayLayers</code> <strong class=\"purple\">must</strong> be <code>1</code>"
         },
         {
           "vuid": "VUID-VkImageCreateInfo-samples-02257",
@@ -9086,11 +9726,11 @@
         },
         {
           "vuid": "VUID-VkImageCreateInfo-usage-00966",
-          "text": " If <code>usage</code> includes <code>VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT</code>, <code>usage</code> <strong class=\"purple\">must</strong> also contain at least one of <code>VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT</code>, <code>VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT</code>, or <code>VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT</code>."
+          "text": " If <code>usage</code> includes <code>VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT</code>, <code>usage</code> <strong class=\"purple\">must</strong> also contain at least one of <code>VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT</code>, <code>VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT</code>, or <code>VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT</code>"
         },
         {
           "vuid": "VUID-VkImageCreateInfo-samples-02258",
-          "text": " <code>samples</code> <strong class=\"purple\">must</strong> be a bit value that is set in <code>imageCreateSampleCounts</code> (as defined in <a href=\"#resources-image-creation-limits\">Image Creation Limits</a>)."
+          "text": " <code>samples</code> <strong class=\"purple\">must</strong> be a bit value that is set in <code>imageCreateSampleCounts</code> (as defined in <a href=\"#resources-image-creation-limits\">Image Creation Limits</a>)"
         },
         {
           "vuid": "VUID-VkImageCreateInfo-usage-00968",
@@ -9214,31 +9854,31 @@
       "(VK_ANDROID_external_memory_android_hardware_buffer)": [
         {
           "vuid": "VUID-VkImageCreateInfo-pNext-01974",
-          "text": " If the <code>pNext</code> chain includes a <a href=\"#VkExternalFormatANDROID\">VkExternalFormatANDROID</a> structure, and its <code>externalFormat</code> member is non-zero the <code>format</code> <strong class=\"purple\">must</strong> be <code>VK_FORMAT_UNDEFINED</code>."
+          "text": " If the <code>pNext</code> chain includes a <a href=\"#VkExternalFormatANDROID\">VkExternalFormatANDROID</a> structure, and its <code>externalFormat</code> member is non-zero the <code>format</code> <strong class=\"purple\">must</strong> be <code>VK_FORMAT_UNDEFINED</code>"
         },
         {
           "vuid": "VUID-VkImageCreateInfo-pNext-01975",
-          "text": " If the <code>pNext</code> chain does not include a <a href=\"#VkExternalFormatANDROID\">VkExternalFormatANDROID</a> structure, or does and its <code>externalFormat</code> member is <code>0</code>, the <code>format</code> <strong class=\"purple\">must</strong> not be <code>VK_FORMAT_UNDEFINED</code>."
+          "text": " If the <code>pNext</code> chain does not include a <a href=\"#VkExternalFormatANDROID\">VkExternalFormatANDROID</a> structure, or does and its <code>externalFormat</code> member is <code>0</code>, the <code>format</code> <strong class=\"purple\">must</strong> not be <code>VK_FORMAT_UNDEFINED</code>"
         },
         {
           "vuid": "VUID-VkImageCreateInfo-pNext-02393",
-          "text": " If the <code>pNext</code> chain includes a <a href=\"#VkExternalMemoryImageCreateInfo\">VkExternalMemoryImageCreateInfo</a> structure whose <code>handleTypes</code> member includes <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID</code>, <code>imageType</code> <strong class=\"purple\">must</strong> be <code>VK_IMAGE_TYPE_2D</code>."
+          "text": " If the <code>pNext</code> chain includes a <a href=\"#VkExternalMemoryImageCreateInfo\">VkExternalMemoryImageCreateInfo</a> structure whose <code>handleTypes</code> member includes <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID</code>, <code>imageType</code> <strong class=\"purple\">must</strong> be <code>VK_IMAGE_TYPE_2D</code>"
         },
         {
           "vuid": "VUID-VkImageCreateInfo-pNext-02394",
-          "text": " If the <code>pNext</code> chain includes a <a href=\"#VkExternalMemoryImageCreateInfo\">VkExternalMemoryImageCreateInfo</a> structure whose <code>handleTypes</code> member includes <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID</code>, <code>mipLevels</code> <strong class=\"purple\">must</strong> either be <code>1</code> or equal to the number of levels in the complete mipmap chain based on <span class=\"eq\"><code>extent.width</code></span>, <span class=\"eq\"><code>extent.height</code></span>, and <span class=\"eq\"><code>extent.depth</code></span>."
+          "text": " If the <code>pNext</code> chain includes a <a href=\"#VkExternalMemoryImageCreateInfo\">VkExternalMemoryImageCreateInfo</a> structure whose <code>handleTypes</code> member includes <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID</code>, <code>mipLevels</code> <strong class=\"purple\">must</strong> either be <code>1</code> or equal to the number of levels in the complete mipmap chain based on <span class=\"eq\"><code>extent.width</code></span>, <span class=\"eq\"><code>extent.height</code></span>, and <span class=\"eq\"><code>extent.depth</code></span>"
         },
         {
           "vuid": "VUID-VkImageCreateInfo-pNext-02396",
-          "text": " If the <code>pNext</code> chain includes a <a href=\"#VkExternalFormatANDROID\">VkExternalFormatANDROID</a> structure whose <code>externalFormat</code> member is not <code>0</code>, <code>flags</code> <strong class=\"purple\">must</strong> not include <code>VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT</code>."
+          "text": " If the <code>pNext</code> chain includes a <a href=\"#VkExternalFormatANDROID\">VkExternalFormatANDROID</a> structure whose <code>externalFormat</code> member is not <code>0</code>, <code>flags</code> <strong class=\"purple\">must</strong> not include <code>VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT</code>"
         },
         {
           "vuid": "VUID-VkImageCreateInfo-pNext-02397",
-          "text": " If the <code>pNext</code> chain includes a <a href=\"#VkExternalFormatANDROID\">VkExternalFormatANDROID</a> structure whose <code>externalFormat</code> member is not <code>0</code>, <code>usage</code> <strong class=\"purple\">must</strong> not include any usages except <code>VK_IMAGE_USAGE_SAMPLED_BIT</code>."
+          "text": " If the <code>pNext</code> chain includes a <a href=\"#VkExternalFormatANDROID\">VkExternalFormatANDROID</a> structure whose <code>externalFormat</code> member is not <code>0</code>, <code>usage</code> <strong class=\"purple\">must</strong> not include any usages except <code>VK_IMAGE_USAGE_SAMPLED_BIT</code>"
         },
         {
           "vuid": "VUID-VkImageCreateInfo-pNext-02398",
-          "text": " If the <code>pNext</code> chain includes a <a href=\"#VkExternalFormatANDROID\">VkExternalFormatANDROID</a> structure whose <code>externalFormat</code> member is not <code>0</code>, <code>tiling</code> <strong class=\"purple\">must</strong> be <code>VK_IMAGE_TILING_OPTIMAL</code>."
+          "text": " If the <code>pNext</code> chain includes a <a href=\"#VkExternalFormatANDROID\">VkExternalFormatANDROID</a> structure whose <code>externalFormat</code> member is not <code>0</code>, <code>tiling</code> <strong class=\"purple\">must</strong> be <code>VK_IMAGE_TILING_OPTIMAL</code>"
         }
       ],
       "(VK_EXT_fragment_density_map)": [
@@ -9284,17 +9924,17 @@
       "(VK_VERSION_1_1)": [
         {
           "vuid": "VUID-VkImageCreateInfo-flags-01890",
-          "text": " If the protected memory feature is not enabled, <code>flags</code> <strong class=\"purple\">must</strong> not contain <code>VK_IMAGE_CREATE_PROTECTED_BIT</code>."
+          "text": " If the protected memory feature is not enabled, <code>flags</code> <strong class=\"purple\">must</strong> not contain <code>VK_IMAGE_CREATE_PROTECTED_BIT</code>"
         },
         {
           "vuid": "VUID-VkImageCreateInfo-None-01891",
-          "text": " If any of the bits <code>VK_IMAGE_CREATE_SPARSE_BINDING_BIT</code>, <code>VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT</code>, or <code>VK_IMAGE_CREATE_SPARSE_ALIASED_BIT</code> are set, <code>VK_IMAGE_CREATE_PROTECTED_BIT</code> <strong class=\"purple\">must</strong> not also be set."
+          "text": " If any of the bits <code>VK_IMAGE_CREATE_SPARSE_BINDING_BIT</code>, <code>VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT</code>, or <code>VK_IMAGE_CREATE_SPARSE_ALIASED_BIT</code> are set, <code>VK_IMAGE_CREATE_PROTECTED_BIT</code> <strong class=\"purple\">must</strong> not also be set"
         }
       ],
       "(VK_VERSION_1_1,VK_KHR_external_memory)+(VK_NV_external_memory)": [
         {
           "vuid": "VUID-VkImageCreateInfo-pNext-00988",
-          "text": " If the <code>pNext</code> chain includes a <a href=\"#VkExternalMemoryImageCreateInfoNV\">VkExternalMemoryImageCreateInfoNV</a> structure, it <strong class=\"purple\">must</strong> not contain a <a href=\"#VkExternalMemoryImageCreateInfo\">VkExternalMemoryImageCreateInfo</a> structure."
+          "text": " If the <code>pNext</code> chain includes a <a href=\"#VkExternalMemoryImageCreateInfoNV\">VkExternalMemoryImageCreateInfoNV</a> structure, it <strong class=\"purple\">must</strong> not contain a <a href=\"#VkExternalMemoryImageCreateInfo\">VkExternalMemoryImageCreateInfo</a> structure"
         }
       ],
       "(VK_VERSION_1_1,VK_KHR_external_memory)": [
@@ -9316,17 +9956,17 @@
         },
         {
           "vuid": "VUID-VkImageCreateInfo-flags-02259",
-          "text": " If <code>flags</code> contains <code>VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT</code>, then <code>mipLevels</code> <strong class=\"purple\">must</strong> be one, <code>arrayLayers</code> <strong class=\"purple\">must</strong> be one, <code>imageType</code> <strong class=\"purple\">must</strong> be <code>VK_IMAGE_TYPE_2D</code>. and <code>imageCreateMaybeLinear</code> (as defined in <a href=\"#resources-image-creation-limits\">Image Creation Limits</a>) <strong class=\"purple\">must</strong> be <code>false</code>."
+          "text": " If <code>flags</code> contains <code>VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT</code>, then <code>mipLevels</code> <strong class=\"purple\">must</strong> be one, <code>arrayLayers</code> <strong class=\"purple\">must</strong> be one, <code>imageType</code> <strong class=\"purple\">must</strong> be <code>VK_IMAGE_TYPE_2D</code>. and <code>imageCreateMaybeLinear</code> (as defined in <a href=\"#resources-image-creation-limits\">Image Creation Limits</a>) <strong class=\"purple\">must</strong> be <code>false</code>"
         }
       ],
       "(VK_VERSION_1_1,VK_KHR_maintenance2)": [
         {
           "vuid": "VUID-VkImageCreateInfo-flags-01572",
-          "text": " If <code>flags</code> contains <code>VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT</code>, then <code>format</code> <strong class=\"purple\">must</strong> be a <a href=\"#appendix-compressedtex-bc\">block-compressed image format</a>, an <a href=\"#appendix-compressedtex-etc2\">ETC compressed image format</a>, or an <a href=\"#appendix-compressedtex-astc\">ASTC compressed image format</a>."
+          "text": " If <code>flags</code> contains <code>VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT</code>, then <code>format</code> <strong class=\"purple\">must</strong> be a <a href=\"#appendix-compressedtex-bc\">block-compressed image format</a>, an <a href=\"#appendix-compressedtex-etc2\">ETC compressed image format</a>, or an <a href=\"#appendix-compressedtex-astc\">ASTC compressed image format</a>"
         },
         {
           "vuid": "VUID-VkImageCreateInfo-flags-01573",
-          "text": " If <code>flags</code> contains <code>VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT</code>, then <code>flags</code> <strong class=\"purple\">must</strong> also contain <code>VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT</code>."
+          "text": " If <code>flags</code> contains <code>VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT</code>, then <code>flags</code> <strong class=\"purple\">must</strong> also contain <code>VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT</code>"
         }
       ],
       "(VK_VERSION_1_1,VK_KHR_external_memory,VK_NV_external_memory)": [
@@ -9380,7 +10020,7 @@
         },
         {
           "vuid": "VUID-VkImageCreateInfo-tiling-02353",
-          "text": " If <code>tiling</code> is <code>VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT</code> and <code>flags</code> contains <code>VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT</code>, then the <code>pNext</code> chain <strong class=\"purple\">must</strong> include a <a href=\"#VkImageFormatListCreateInfo\">VkImageFormatListCreateInfo</a> structure with non-zero <code>viewFormatCount</code>."
+          "text": " If <code>tiling</code> is <code>VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT</code> and <code>flags</code> contains <code>VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT</code>, then the <code>pNext</code> chain <strong class=\"purple\">must</strong> include a <a href=\"#VkImageFormatListCreateInfo\">VkImageFormatListCreateInfo</a> structure with non-zero <code>viewFormatCount</code>"
         }
       ],
       "(VK_EXT_sample_locations)": [
@@ -9440,15 +10080,15 @@
       "(VK_NV_shading_rate_image)": [
         {
           "vuid": "VUID-VkImageCreateInfo-imageType-02082",
-          "text": " If <code>usage</code> includes <code>VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV</code>, <code>imageType</code> <strong class=\"purple\">must</strong> be <code>VK_IMAGE_TYPE_2D</code>."
+          "text": " If <code>usage</code> includes <code>VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV</code>, <code>imageType</code> <strong class=\"purple\">must</strong> be <code>VK_IMAGE_TYPE_2D</code>"
         },
         {
           "vuid": "VUID-VkImageCreateInfo-samples-02083",
-          "text": " If <code>usage</code> includes <code>VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV</code>, <code>samples</code> <strong class=\"purple\">must</strong> be <code>VK_SAMPLE_COUNT_1_BIT</code>."
+          "text": " If <code>usage</code> includes <code>VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV</code>, <code>samples</code> <strong class=\"purple\">must</strong> be <code>VK_SAMPLE_COUNT_1_BIT</code>"
         },
         {
           "vuid": "VUID-VkImageCreateInfo-tiling-02084",
-          "text": " If <code>usage</code> includes <code>VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV</code>, <code>tiling</code> <strong class=\"purple\">must</strong> be <code>VK_IMAGE_TILING_OPTIMAL</code>."
+          "text": " If <code>usage</code> includes <code>VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV</code>, <code>tiling</code> <strong class=\"purple\">must</strong> be <code>VK_IMAGE_TILING_OPTIMAL</code>"
         }
       ]
     },
@@ -9476,7 +10116,7 @@
       "(VK_NV_dedicated_allocation)": [
         {
           "vuid": "VUID-VkDedicatedAllocationImageCreateInfoNV-dedicatedAllocation-00994",
-          "text": " If <code>dedicatedAllocation</code> is <code>VK_TRUE</code>, <code>VkImageCreateInfo</code>::<code>flags</code> <strong class=\"purple\">must</strong> not include <code>VK_IMAGE_CREATE_SPARSE_BINDING_BIT</code>, <code>VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT</code>, or <code>VK_IMAGE_CREATE_SPARSE_ALIASED_BIT</code>"
+          "text": " If <code>dedicatedAllocation</code> is <code>VK_TRUE</code>, <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>flags</code> <strong class=\"purple\">must</strong> not include <code>VK_IMAGE_CREATE_SPARSE_BINDING_BIT</code>, <code>VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT</code>, or <code>VK_IMAGE_CREATE_SPARSE_ALIASED_BIT</code>"
         },
         {
           "vuid": "VUID-VkDedicatedAllocationImageCreateInfoNV-sType-sType",
@@ -9544,15 +10184,15 @@
       "(VK_VERSION_1_2,VK_KHR_image_format_list)": [
         {
           "vuid": "VUID-VkImageFormatListCreateInfo-viewFormatCount-01578",
-          "text": " If <code>viewFormatCount</code> is not <code>0</code>, all of the formats in the <code>pViewFormats</code> array <strong class=\"purple\">must</strong> be compatible with the format specified in the <code>format</code> field of <code>VkImageCreateInfo</code>, as described in the <a href=\"#formats-compatibility\">compatibility table</a>."
+          "text": " If <code>viewFormatCount</code> is not <code>0</code>, all of the formats in the <code>pViewFormats</code> array <strong class=\"purple\">must</strong> be compatible with the format specified in the <code>format</code> field of <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>, as described in the <a href=\"#formats-compatibility\">compatibility table</a>"
         },
         {
           "vuid": "VUID-VkImageFormatListCreateInfo-flags-01579",
-          "text": " If <code>VkImageCreateInfo</code>::<code>flags</code> does not contain <code>VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT</code>, <code>viewFormatCount</code> <strong class=\"purple\">must</strong> be <code>0</code> or <code>1</code>."
+          "text": " If <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>flags</code> does not contain <code>VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT</code>, <code>viewFormatCount</code> <strong class=\"purple\">must</strong> be <code>0</code> or <code>1</code>"
         },
         {
           "vuid": "VUID-VkImageFormatListCreateInfo-viewFormatCount-01580",
-          "text": " If <code>viewFormatCount</code> is not <code>0</code>, <code>VkImageCreateInfo</code>::<code>format</code> <strong class=\"purple\">must</strong> be in <code>pViewFormats</code>."
+          "text": " If <code>viewFormatCount</code> is not <code>0</code>, <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>format</code> <strong class=\"purple\">must</strong> be in <code>pViewFormats</code>"
         },
         {
           "vuid": "VUID-VkImageFormatListCreateInfo-sType-sType",
@@ -9568,7 +10208,7 @@
       "(VK_EXT_image_drm_format_modifier)": [
         {
           "vuid": "VUID-VkImageDrmFormatModifierListCreateInfoEXT-pDrmFormatModifiers-02263",
-          "text": " Each <em>modifier</em> in <code>pDrmFormatModifiers</code> must be compatible with the parameters in <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a> and its <code>pNext</code> chain, as determined by querying <a href=\"#VkPhysicalDeviceImageFormatInfo2\">VkPhysicalDeviceImageFormatInfo2</a> extended with <a href=\"#VkPhysicalDeviceImageDrmFormatModifierInfoEXT\">VkPhysicalDeviceImageDrmFormatModifierInfoEXT</a>."
+          "text": " Each <em>modifier</em> in <code>pDrmFormatModifiers</code> must be compatible with the parameters in <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a> and its <code>pNext</code> chain, as determined by querying <a href=\"#VkPhysicalDeviceImageFormatInfo2\">VkPhysicalDeviceImageFormatInfo2</a> extended with <a href=\"#VkPhysicalDeviceImageDrmFormatModifierInfoEXT\">VkPhysicalDeviceImageDrmFormatModifierInfoEXT</a>"
         },
         {
           "vuid": "VUID-VkImageDrmFormatModifierListCreateInfoEXT-sType-sType",
@@ -9588,11 +10228,11 @@
       "(VK_EXT_image_drm_format_modifier)": [
         {
           "vuid": "VUID-VkImageDrmFormatModifierExplicitCreateInfoEXT-drmFormatModifier-02264",
-          "text": " <code>drmFormatModifier</code> must be compatible with the parameters in <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a> and its <code>pNext</code> chain, as determined by querying <a href=\"#VkPhysicalDeviceImageFormatInfo2\">VkPhysicalDeviceImageFormatInfo2</a> extended with <a href=\"#VkPhysicalDeviceImageDrmFormatModifierInfoEXT\">VkPhysicalDeviceImageDrmFormatModifierInfoEXT</a>."
+          "text": " <code>drmFormatModifier</code> must be compatible with the parameters in <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a> and its <code>pNext</code> chain, as determined by querying <a href=\"#VkPhysicalDeviceImageFormatInfo2\">VkPhysicalDeviceImageFormatInfo2</a> extended with <a href=\"#VkPhysicalDeviceImageDrmFormatModifierInfoEXT\">VkPhysicalDeviceImageDrmFormatModifierInfoEXT</a>"
         },
         {
           "vuid": "VUID-VkImageDrmFormatModifierExplicitCreateInfoEXT-drmFormatModifierPlaneCount-02265",
-          "text": " <code>drmFormatModifierPlaneCount</code> <strong class=\"purple\">must</strong> be equal to the <a href=\"#VkDrmFormatModifierPropertiesEXT\">VkDrmFormatModifierPropertiesEXT</a>::<code>drmFormatModifierPlaneCount</code> associated with <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>format</code> and <code>drmFormatModifier</code>, as found by querying <a href=\"#VkDrmFormatModifierPropertiesListEXT\">VkDrmFormatModifierPropertiesListEXT</a>."
+          "text": " <code>drmFormatModifierPlaneCount</code> <strong class=\"purple\">must</strong> be equal to the <a href=\"#VkDrmFormatModifierPropertiesEXT\">VkDrmFormatModifierPropertiesEXT</a>::<code>drmFormatModifierPlaneCount</code> associated with <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>format</code> and <code>drmFormatModifier</code>, as found by querying <a href=\"#VkDrmFormatModifierPropertiesListEXT\">VkDrmFormatModifierPropertiesListEXT</a>"
         },
         {
           "vuid": "VUID-VkImageDrmFormatModifierExplicitCreateInfoEXT-size-02267",
@@ -9600,11 +10240,11 @@
         },
         {
           "vuid": "VUID-VkImageDrmFormatModifierExplicitCreateInfoEXT-arrayPitch-02268",
-          "text": " For each element of <code>pPlaneLayouts</code>, <code>arrayPitch</code> <strong class=\"purple\">must</strong> be 0 if <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>arrayLayers</code> is 1."
+          "text": " For each element of <code>pPlaneLayouts</code>, <code>arrayPitch</code> <strong class=\"purple\">must</strong> be 0 if <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>arrayLayers</code> is 1"
         },
         {
           "vuid": "VUID-VkImageDrmFormatModifierExplicitCreateInfoEXT-depthPitch-02269",
-          "text": " For each element of <code>pPlaneLayouts</code>, <code>depthPitch</code> <strong class=\"purple\">must</strong> be 0 if <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>extent.depth</code> is 1."
+          "text": " For each element of <code>pPlaneLayouts</code>, <code>depthPitch</code> <strong class=\"purple\">must</strong> be 0 if <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>extent.depth</code> is 1"
         },
         {
           "vuid": "VUID-VkImageDrmFormatModifierExplicitCreateInfoEXT-sType-sType",
@@ -9630,7 +10270,7 @@
         },
         {
           "vuid": "VUID-vkGetImageSubresourceLayout-tiling-02271",
-          "text": "  If the <code>tiling</code> of the <code>image</code> is  <code>VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT</code>, then the <code>aspectMask</code>  member of <code>pSubresource</code> <strong class=\"purple\">must</strong> be  <code>VK_IMAGE_ASPECT_MEMORY_PLANE_i_BIT_EXT</code> and the index <code>i</code> <strong class=\"purple\">must</strong>  be less than the  <a href=\"#VkDrmFormatModifierPropertiesEXT\"><code>drmFormatModifierPlaneCount</code></a>  associated with the image&#8217;s <a href=\"#VkImageCreateInfo\"><code>format</code></a> and <a href=\"#VkImageDrmFormatModifierPropertiesEXT\"><code>drmFormatModifier</code></a>."
+          "text": " If the <code>tiling</code> of the <code>image</code> is <code>VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT</code>, then the <code>aspectMask</code> member of <code>pSubresource</code> <strong class=\"purple\">must</strong> be <code>VK_IMAGE_ASPECT_MEMORY_PLANE_i_BIT_EXT</code> and the index <code>i</code> <strong class=\"purple\">must</strong> be less than the <a href=\"#VkDrmFormatModifierPropertiesEXT\">VkDrmFormatModifierPropertiesEXT</a>::<code>drmFormatModifierPlaneCount</code> associated with the image&#8217;s <code>format</code> and <a href=\"#VkImageDrmFormatModifierPropertiesEXT\">VkImageDrmFormatModifierPropertiesEXT</a>::<code>drmFormatModifier</code>"
         }
       ],
       "core": [
@@ -9680,7 +10320,7 @@
       "(VK_ANDROID_external_memory_android_hardware_buffer)": [
         {
           "vuid": "VUID-vkGetImageSubresourceLayout-image-01895",
-          "text": " If <code>image</code> was created with the <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID</code> external memory handle type, then <code>image</code> <strong class=\"purple\">must</strong> be bound to memory."
+          "text": " If <code>image</code> was created with the <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID</code> external memory handle type, then <code>image</code> <strong class=\"purple\">must</strong> be bound to memory"
         }
       ]
     },
@@ -9700,7 +10340,7 @@
       "(VK_EXT_image_drm_format_modifier)": [
         {
           "vuid": "VUID-vkGetImageDrmFormatModifierPropertiesEXT-image-02272",
-          "text": " <code>image</code> <strong class=\"purple\">must</strong> have been created with <a href=\"#VkImageCreateInfo\"><code>tiling</code></a> equal to <code>VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT</code>."
+          "text": " <code>image</code> <strong class=\"purple\">must</strong> have been created with <a href=\"#VkImageCreateInfo\"><code>tiling</code></a> equal to <code>VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT</code>"
         },
         {
           "vuid": "VUID-vkGetImageDrmFormatModifierPropertiesEXT-device-parameter",
@@ -9796,27 +10436,27 @@
         },
         {
           "vuid": "VUID-VkImageViewCreateInfo-None-02273",
-          "text": " The <a href=\"#resources-image-view-format-features\">format features</a> of the resultant image view <strong class=\"purple\">must</strong> contain at least one bit."
+          "text": " The <a href=\"#resources-image-view-format-features\">format features</a> of the resultant image view <strong class=\"purple\">must</strong> contain at least one bit"
         },
         {
           "vuid": "VUID-VkImageViewCreateInfo-usage-02274",
-          "text": " If <code>usage</code> contains <code>VK_IMAGE_USAGE_SAMPLED_BIT</code>, then the <a href=\"#resources-image-view-format-features\">format features</a> of the resultant image view <strong class=\"purple\">must</strong> contain <code>VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT</code>."
+          "text": " If <code>usage</code> contains <code>VK_IMAGE_USAGE_SAMPLED_BIT</code>, then the <a href=\"#resources-image-view-format-features\">format features</a> of the resultant image view <strong class=\"purple\">must</strong> contain <code>VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT</code>"
         },
         {
           "vuid": "VUID-VkImageViewCreateInfo-usage-02275",
-          "text": " If <code>usage</code> contains <code>VK_IMAGE_USAGE_STORAGE_BIT</code>, then the image view&#8217;s <a href=\"#resources-image-view-format-features\">format features</a> <strong class=\"purple\">must</strong> contain <code>VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT</code>."
+          "text": " If <code>usage</code> contains <code>VK_IMAGE_USAGE_STORAGE_BIT</code>, then the image view&#8217;s <a href=\"#resources-image-view-format-features\">format features</a> <strong class=\"purple\">must</strong> contain <code>VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT</code>"
         },
         {
           "vuid": "VUID-VkImageViewCreateInfo-usage-02276",
-          "text": " If <code>usage</code> contains <code>VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT</code>, then the image view&#8217;s <a href=\"#resources-image-view-format-features\">format features</a> <strong class=\"purple\">must</strong> contain <code>VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT</code>."
+          "text": " If <code>usage</code> contains <code>VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT</code>, then the image view&#8217;s <a href=\"#resources-image-view-format-features\">format features</a> <strong class=\"purple\">must</strong> contain <code>VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT</code>"
         },
         {
           "vuid": "VUID-VkImageViewCreateInfo-usage-02277",
-          "text": " If <code>usage</code> contains <code>VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT</code>, then the image view&#8217;s <a href=\"#resources-image-view-format-features\">format features</a> <strong class=\"purple\">must</strong> contain <code>VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT</code>."
+          "text": " If <code>usage</code> contains <code>VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT</code>, then the image view&#8217;s <a href=\"#resources-image-view-format-features\">format features</a> <strong class=\"purple\">must</strong> contain <code>VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT</code>"
         },
         {
           "vuid": "VUID-VkImageViewCreateInfo-usage-02652",
-          "text": " If <code>usage</code> contains <code>VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT</code>, then the image view&#8217;s <a href=\"#resources-image-view-format-features\">format features</a> <strong class=\"purple\">must</strong> contain at least one of <code>VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT</code> or <code>VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT</code>."
+          "text": " If <code>usage</code> contains <code>VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT</code>, then the image view&#8217;s <a href=\"#resources-image-view-format-features\">format features</a> <strong class=\"purple\">must</strong> contain at least one of <code>VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT</code> or <code>VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT</code>"
         },
         {
           "vuid": "VUID-VkImageViewCreateInfo-subresourceRange-01478",
@@ -9827,10 +10467,6 @@
           "text": " If <code>subresourceRange.levelCount</code> is not <code>VK_REMAINING_MIP_LEVELS</code>, <span class=\"eq\"><code>subresourceRange.baseMipLevel</code> &#43; <code>subresourceRange.levelCount</code></span> <strong class=\"purple\">must</strong> be less than or equal to the <code>mipLevels</code> specified in <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a> when <code>image</code> was created"
         },
         {
-          "vuid": "VUID-VkImageViewCreateInfo-image-01018",
-          "text": " If <code>image</code> was created with the <code>VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT</code> flag, <code>format</code> <strong class=\"purple\">must</strong> be compatible with the <code>format</code> used to create <code>image</code>, as defined in <a href=\"#formats-compatibility-classes\">Format Compatibility Classes</a>"
-        },
-        {
           "vuid": "VUID-VkImageViewCreateInfo-image-01020",
           "text": " If <code>image</code> is non-sparse then it <strong class=\"purple\">must</strong> be bound completely and contiguously to a single <code>VkDeviceMemory</code> object"
         },
@@ -9839,6 +10475,22 @@
           "text": " <code>subresourceRange</code> and <code>viewType</code> <strong class=\"purple\">must</strong> be compatible with the image, as described in the <a href=\"#resources-image-views-compatibility\">compatibility table</a>"
         },
         {
+          "vuid": "VUID-VkImageViewCreateInfo-viewType-02960",
+          "text": " If <code>viewType</code> is <code>VK_IMAGE_VIEW_TYPE_CUBE</code> and <code>subresourceRange.layerCount</code> is not <code>VK_REMAINING_ARRAY_LAYERS</code>, <code>subresourceRange.layerCount</code> <strong class=\"purple\">must</strong> be <code>6</code>"
+        },
+        {
+          "vuid": "VUID-VkImageViewCreateInfo-viewType-02961",
+          "text": " If <code>viewType</code> is <code>VK_IMAGE_VIEW_TYPE_CUBE_ARRAY</code> and <code>subresourceRange.layerCount</code> is not <code>VK_REMAINING_ARRAY_LAYERS</code>, <code>subresourceRange.layerCount</code> <strong class=\"purple\">must</strong> be a multiple of <code>6</code>"
+        },
+        {
+          "vuid": "VUID-VkImageViewCreateInfo-viewType-02962",
+          "text": " If <code>viewType</code> is <code>VK_IMAGE_VIEW_TYPE_CUBE</code> and <code>subresourceRange.layerCount</code> is <code>VK_REMAINING_ARRAY_LAYERS</code>, the remaining number of layers <strong class=\"purple\">must</strong> be <code>6</code>"
+        },
+        {
+          "vuid": "VUID-VkImageViewCreateInfo-viewType-02963",
+          "text": " If <code>viewType</code> is <code>VK_IMAGE_VIEW_TYPE_CUBE_ARRAY</code> and <code>subresourceRange.layerCount</code> is <code>VK_REMAINING_ARRAY_LAYERS</code>, the remaining number of layers <strong class=\"purple\">must</strong> be a multiple of <code>6</code>"
+        },
+        {
           "vuid": "VUID-VkImageViewCreateInfo-sType-sType",
           "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO</code>"
         },
@@ -9890,11 +10542,11 @@
         },
         {
           "vuid": "VUID-VkImageViewCreateInfo-image-02724",
-          "text": " If <code>image</code> is a 3D image created with <code>VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT</code> set, and <code>viewType</code> is <code>VK_IMAGE_VIEW_TYPE_2D</code> or <code>VK_IMAGE_VIEW_TYPE_2D_ARRAY</code>, <code>subresourceRange.baseArrayLayer</code> <strong class=\"purple\">must</strong> be less than the depth computed from <code>baseMipLevel</code> and <code>extent.depth</code> specified in <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a> when <code>image</code> was created, according to the formula defined in <a href=\"#resources-image-miplevel-sizing\">Image Miplevel Sizing</a>."
+          "text": " If <code>image</code> is a 3D image created with <code>VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT</code> set, and <code>viewType</code> is <code>VK_IMAGE_VIEW_TYPE_2D</code> or <code>VK_IMAGE_VIEW_TYPE_2D_ARRAY</code>, <code>subresourceRange.baseArrayLayer</code> <strong class=\"purple\">must</strong> be less than the depth computed from <code>baseMipLevel</code> and <code>extent.depth</code> specified in <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a> when <code>image</code> was created, according to the formula defined in <a href=\"#resources-image-miplevel-sizing\">Image Miplevel Sizing</a>"
         },
         {
           "vuid": "VUID-VkImageViewCreateInfo-subresourceRange-02725",
-          "text": " If <code>subresourceRange.layerCount</code> is not <code>VK_REMAINING_ARRAY_LAYERS</code>, <code>image</code> is a 3D image created with <code>VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT</code> set, and <code>viewType</code> is <code>VK_IMAGE_VIEW_TYPE_2D</code> or <code>VK_IMAGE_VIEW_TYPE_2D_ARRAY</code>, <code>subresourceRange.layerCount</code> <strong class=\"purple\">must</strong> be non-zero and <span class=\"eq\"><code>subresourceRange.baseArrayLayer</code> &#43; <code>subresourceRange.layerCount</code></span> <strong class=\"purple\">must</strong> be less than or equal to the depth computed from <code>baseMipLevel</code> and <code>extent.depth</code> specified in <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a> when <code>image</code> was created, according to the formula defined in <a href=\"#resources-image-miplevel-sizing\">Image Miplevel Sizing</a>."
+          "text": " If <code>subresourceRange.layerCount</code> is not <code>VK_REMAINING_ARRAY_LAYERS</code>, <code>image</code> is a 3D image created with <code>VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT</code> set, and <code>viewType</code> is <code>VK_IMAGE_VIEW_TYPE_2D</code> or <code>VK_IMAGE_VIEW_TYPE_2D_ARRAY</code>, <code>subresourceRange.layerCount</code> <strong class=\"purple\">must</strong> be non-zero and <span class=\"eq\"><code>subresourceRange.baseArrayLayer</code> &#43; <code>subresourceRange.layerCount</code></span> <strong class=\"purple\">must</strong> be less than or equal to the depth computed from <code>baseMipLevel</code> and <code>extent.depth</code> specified in <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a> when <code>image</code> was created, according to the formula defined in <a href=\"#resources-image-miplevel-sizing\">Image Miplevel Sizing</a>"
         }
       ],
       "!(VK_EXT_fragment_density_map)+!(VK_NV_shading_rate_image)": [
@@ -9945,6 +10597,12 @@
           "text": " If <code>subresourceRange.layerCount</code> is not <code>VK_REMAINING_ARRAY_LAYERS</code>, <span class=\"eq\"><code>subresourceRange.baseArrayLayer</code> &#43; <code>subresourceRange.layerCount</code></span> <strong class=\"purple\">must</strong> be less than or equal to the <code>arrayLayers</code> specified in <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a> when <code>image</code> was created"
         }
       ],
+      "!(VK_VERSION_1_1,VK_KHR_maintenance2)+!(VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion)": [
+        {
+          "vuid": "VUID-VkImageViewCreateInfo-image-01018",
+          "text": " If <code>image</code> was created with the <code>VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT</code> flag, <code>format</code> <strong class=\"purple\">must</strong> be compatible with the <code>format</code> used to create <code>image</code>, as defined in <a href=\"#formats-compatibility-classes\">Format Compatibility Classes</a>"
+        }
+      ],
       "(VK_VERSION_1_1,VK_KHR_maintenance2)+!(VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion)": [
         {
           "vuid": "VUID-VkImageViewCreateInfo-image-01759",
@@ -9966,17 +10624,17 @@
       "(VK_VERSION_1_1,VK_KHR_maintenance2)": [
         {
           "vuid": "VUID-VkImageViewCreateInfo-image-01583",
-          "text": " If <code>image</code> was created with the <code>VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT</code> flag, <code>format</code> <strong class=\"purple\">must</strong> be compatible with, or <strong class=\"purple\">must</strong> be an uncompressed format that is size-compatible with, the <code>format</code> used to create <code>image</code>."
+          "text": " If <code>image</code> was created with the <code>VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT</code> flag, <code>format</code> <strong class=\"purple\">must</strong> be compatible with, or <strong class=\"purple\">must</strong> be an uncompressed format that is size-compatible with, the <code>format</code> used to create <code>image</code>"
         },
         {
           "vuid": "VUID-VkImageViewCreateInfo-image-01584",
-          "text": " If <code>image</code> was created with the <code>VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT</code> flag, the <code>levelCount</code> and <code>layerCount</code> members of <code>subresourceRange</code> <strong class=\"purple\">must</strong> both be <code>1</code>."
+          "text": " If <code>image</code> was created with the <code>VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT</code> flag, the <code>levelCount</code> and <code>layerCount</code> members of <code>subresourceRange</code> <strong class=\"purple\">must</strong> both be <code>1</code>"
         }
       ],
       "(VK_VERSION_1_2,VK_KHR_image_format_list)": [
         {
           "vuid": "VUID-VkImageViewCreateInfo-pNext-01585",
-          "text": " If a <code>VkImageFormatListCreateInfo</code> structure was included in the <code>pNext</code> chain of the <code>VkImageCreateInfo</code> structure used when creating <code>image</code> and the <code>viewFormatCount</code> field of <code>VkImageFormatListCreateInfo</code> is not zero then <code>format</code> <strong class=\"purple\">must</strong> be one of the formats in <code>VkImageFormatListCreateInfo</code>::<code>pViewFormats</code>."
+          "text": " If a <a href=\"#VkImageFormatListCreateInfo\">VkImageFormatListCreateInfo</a> structure was included in the <code>pNext</code> chain of the <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a> structure used when creating <code>image</code> and the <code>viewFormatCount</code> field of <a href=\"#VkImageFormatListCreateInfo\">VkImageFormatListCreateInfo</a> is not zero then <code>format</code> <strong class=\"purple\">must</strong> be one of the formats in <a href=\"#VkImageFormatListCreateInfo\">VkImageFormatListCreateInfo</a>::<code>pViewFormats</code>"
         }
       ],
       "(VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion)": [
@@ -9990,7 +10648,7 @@
         },
         {
           "vuid": "VUID-VkImageViewCreateInfo-pNext-01970",
-          "text": " If the <code>pNext</code> chain includes a <a href=\"#VkSamplerYcbcrConversionInfo\">VkSamplerYcbcrConversionInfo</a> structure with a <code>conversion</code> value other than <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, all members of <code>components</code> <strong class=\"purple\">must</strong> have the value <code>VK_COMPONENT_SWIZZLE_IDENTITY</code>."
+          "text": " If the <code>pNext</code> chain includes a <a href=\"#VkSamplerYcbcrConversionInfo\">VkSamplerYcbcrConversionInfo</a> structure with a <code>conversion</code> value other than <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, all members of <code>components</code> <strong class=\"purple\">must</strong> have the value <code>VK_COMPONENT_SWIZZLE_IDENTITY</code>"
         }
       ],
       "!(VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion)": [
@@ -10002,15 +10660,15 @@
       "(VK_ANDROID_external_memory_android_hardware_buffer)": [
         {
           "vuid": "VUID-VkImageViewCreateInfo-image-02399",
-          "text": " If <code>image</code> has an <a href=\"#memory-external-android-hardware-buffer-external-formats\">external format</a>, <code>format</code> <strong class=\"purple\">must</strong> be <code>VK_FORMAT_UNDEFINED</code>."
+          "text": " If <code>image</code> has an <a href=\"#memory-external-android-hardware-buffer-external-formats\">external format</a>, <code>format</code> <strong class=\"purple\">must</strong> be <code>VK_FORMAT_UNDEFINED</code>"
         },
         {
           "vuid": "VUID-VkImageViewCreateInfo-image-02400",
-          "text": " If <code>image</code> has an <a href=\"#memory-external-android-hardware-buffer-external-formats\">external format</a>, the <code>pNext</code> chain <strong class=\"purple\">must</strong> include a <a href=\"#VkSamplerYcbcrConversionInfo\">VkSamplerYcbcrConversionInfo</a> structure with a <code>conversion</code> object created with the same external format as <code>image</code>."
+          "text": " If <code>image</code> has an <a href=\"#memory-external-android-hardware-buffer-external-formats\">external format</a>, the <code>pNext</code> chain <strong class=\"purple\">must</strong> include a <a href=\"#VkSamplerYcbcrConversionInfo\">VkSamplerYcbcrConversionInfo</a> structure with a <code>conversion</code> object created with the same external format as <code>image</code>"
         },
         {
           "vuid": "VUID-VkImageViewCreateInfo-image-02401",
-          "text": " If <code>image</code> has an <a href=\"#memory-external-android-hardware-buffer-external-formats\">external format</a>, all members of <code>components</code> <strong class=\"purple\">must</strong> be <code>VK_COMPONENT_SWIZZLE_IDENTITY</code>."
+          "text": " If <code>image</code> has an <a href=\"#memory-external-android-hardware-buffer-external-formats\">external format</a>, all members of <code>components</code> <strong class=\"purple\">must</strong> be <code>VK_COMPONENT_SWIZZLE_IDENTITY</code>"
         }
       ],
       "(VK_NV_shading_rate_image)": [
@@ -10026,7 +10684,7 @@
       "(VK_VERSION_1_1,VK_KHR_maintenance2)+!(VK_EXT_separate_stencil_usage)": [
         {
           "vuid": "VUID-VkImageViewCreateInfo-pNext-02661",
-          "text": " If the <code>pNext</code> chain includes a <a href=\"#VkImageViewUsageCreateInfo\">VkImageViewUsageCreateInfo</a> structure, its <code>usage</code> member <strong class=\"purple\">must</strong> not include any bits that were not set in the <code>usage</code> member of the <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a> structure used to create <code>image</code>."
+          "text": " If the <code>pNext</code> chain includes a <a href=\"#VkImageViewUsageCreateInfo\">VkImageViewUsageCreateInfo</a> structure, its <code>usage</code> member <strong class=\"purple\">must</strong> not include any bits that were not set in the <code>usage</code> member of the <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a> structure used to create <code>image</code>"
         }
       ],
       "(VK_VERSION_1_1,VK_KHR_maintenance2)+(VK_EXT_separate_stencil_usage)": [
@@ -10228,6 +10886,38 @@
         }
       ]
     },
+    "vkGetImageViewAddressNVX": {
+      "(VK_NVX_image_view_handle)": [
+        {
+          "vuid": "VUID-vkGetImageViewAddressNVX-device-parameter",
+          "text": " <code>device</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDevice\">VkDevice</a> handle"
+        },
+        {
+          "vuid": "VUID-vkGetImageViewAddressNVX-imageView-parameter",
+          "text": " <code>imageView</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkImageView\">VkImageView</a> handle"
+        },
+        {
+          "vuid": "VUID-vkGetImageViewAddressNVX-pProperties-parameter",
+          "text": " <code>pProperties</code> <strong class=\"purple\">must</strong> be a valid pointer to a <a href=\"#VkImageViewAddressPropertiesNVX\">VkImageViewAddressPropertiesNVX</a> structure"
+        },
+        {
+          "vuid": "VUID-vkGetImageViewAddressNVX-imageView-parent",
+          "text": " <code>imageView</code> <strong class=\"purple\">must</strong> have been created, allocated, or retrieved from <code>device</code>"
+        }
+      ]
+    },
+    "VkImageViewAddressPropertiesNVX": {
+      "(VK_NVX_image_view_handle)": [
+        {
+          "vuid": "VUID-VkImageViewAddressPropertiesNVX-sType-sType",
+          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_IMAGE_VIEW_ADDRESS_PROPERTIES_NVX</code>"
+        },
+        {
+          "vuid": "VUID-VkImageViewAddressPropertiesNVX-pNext-pNext",
+          "text": " <code>pNext</code> <strong class=\"purple\">must</strong> be <code>NULL</code>"
+        }
+      ]
+    },
     "vkGetBufferMemoryRequirements": {
       "core": [
         {
@@ -10352,7 +11042,7 @@
       "(VK_VERSION_1_1,VK_KHR_get_memory_requirements2)+(VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion)+(VK_ANDROID_external_memory_android_hardware_buffer)": [
         {
           "vuid": "VUID-VkImageMemoryRequirementsInfo2-image-01897",
-          "text": " If <code>image</code> was created with the <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID</code> external memory handle type, then <code>image</code> <strong class=\"purple\">must</strong> be bound to memory."
+          "text": " If <code>image</code> was created with the <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID</code> external memory handle type, then <code>image</code> <strong class=\"purple\">must</strong> be bound to memory"
         }
       ],
       "(VK_VERSION_1_1,VK_KHR_get_memory_requirements2)": [
@@ -10378,7 +11068,7 @@
       "(VK_VERSION_1_1,VK_KHR_get_memory_requirements2)+(VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion)": [
         {
           "vuid": "VUID-VkImagePlaneMemoryRequirementsInfo-planeAspect-02281",
-          "text": " If the image&#8217;s tiling is <code>VK_IMAGE_TILING_LINEAR</code> or <code>VK_IMAGE_TILING_OPTIMAL</code>, then <code>planeAspect</code> <strong class=\"purple\">must</strong> be a single valid <em>format plane</em> for the image. (That is, for a two-plane image <code>planeAspect</code> <strong class=\"purple\">must</strong> be <code>VK_IMAGE_ASPECT_PLANE_0_BIT</code> or <code>VK_IMAGE_ASPECT_PLANE_1_BIT</code>, and for a three-plane image <code>planeAspect</code> <strong class=\"purple\">must</strong> be <code>VK_IMAGE_ASPECT_PLANE_0_BIT</code>, <code>VK_IMAGE_ASPECT_PLANE_1_BIT</code> or <code>VK_IMAGE_ASPECT_PLANE_2_BIT</code>)."
+          "text": " If the image&#8217;s <code>tiling</code> is <code>VK_IMAGE_TILING_LINEAR</code> or <code>VK_IMAGE_TILING_OPTIMAL</code>, then <code>planeAspect</code> <strong class=\"purple\">must</strong> be a single valid <em>format plane</em> for the image (that is, for a two-plane image <code>planeAspect</code> <strong class=\"purple\">must</strong> be <code>VK_IMAGE_ASPECT_PLANE_0_BIT</code> or <code>VK_IMAGE_ASPECT_PLANE_1_BIT</code>, and for a three-plane image <code>planeAspect</code> <strong class=\"purple\">must</strong> be <code>VK_IMAGE_ASPECT_PLANE_0_BIT</code>, <code>VK_IMAGE_ASPECT_PLANE_1_BIT</code> or <code>VK_IMAGE_ASPECT_PLANE_2_BIT</code>)"
         },
         {
           "vuid": "VUID-VkImagePlaneMemoryRequirementsInfo-sType-sType",
@@ -10392,7 +11082,7 @@
       "(VK_VERSION_1_1,VK_KHR_get_memory_requirements2)+(VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion)+(VK_EXT_image_drm_format_modifier)": [
         {
           "vuid": "VUID-VkImagePlaneMemoryRequirementsInfo-planeAspect-02282",
-          "text": "  If the image&#8217;s tiling is <code>VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT</code>,  then <code>planeAspect</code> <strong class=\"purple\">must</strong> be a single valid <em>memory plane</em> for the  image.  (That is, <code>aspectMask</code> <strong class=\"purple\">must</strong> specify a plane index that is less than  the  <a href=\"#VkDrmFormatModifierPropertiesEXT\"><code>drmFormatModifierPlaneCount</code></a>  associated with the image&#8217;s <a href=\"#VkImageCreateInfo\"><code>format</code></a> and <a href=\"#VkImageDrmFormatModifierPropertiesEXT\"><code>drmFormatModifier</code></a>.)"
+          "text": " If the image&#8217;s <code>tiling</code> is <code>VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT</code>, then <code>planeAspect</code> <strong class=\"purple\">must</strong> be a single valid <em>memory plane</em> for the image (that is, <code>aspectMask</code> <strong class=\"purple\">must</strong> specify a plane index that is less than the <a href=\"#VkDrmFormatModifierPropertiesEXT\">VkDrmFormatModifierPropertiesEXT</a>::<code>drmFormatModifierPlaneCount</code> associated with the image&#8217;s <code>format</code> and <a href=\"#VkImageDrmFormatModifierPropertiesEXT\">VkImageDrmFormatModifierPropertiesEXT</a>::<code>drmFormatModifier</code>)"
         }
       ]
     },
@@ -10474,7 +11164,7 @@
         },
         {
           "vuid": "VUID-vkBindBufferMemory-memory-01508",
-          "text": " If the <code>VkMemoryAllocateInfo</code> provided when <code>memory</code> was allocated included a <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a> structure in its <code>pNext</code> chain, and <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a>::<code>buffer</code> was not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, then <code>buffer</code> <strong class=\"purple\">must</strong> equal <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a>::<code>buffer</code>, and <code>memoryOffset</code> <strong class=\"purple\">must</strong> be zero."
+          "text": " If the <code>VkMemoryAllocateInfo</code> provided when <code>memory</code> was allocated included a <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a> structure in its <code>pNext</code> chain, and <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a>::<code>buffer</code> was not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, then <code>buffer</code> <strong class=\"purple\">must</strong> equal <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a>::<code>buffer</code>, and <code>memoryOffset</code> <strong class=\"purple\">must</strong> be zero"
         }
       ],
       "(VK_VERSION_1_1)": [
@@ -10590,7 +11280,7 @@
         },
         {
           "vuid": "VUID-VkBindBufferMemoryInfo-memory-01900",
-          "text": " If the <code>VkMemoryAllocateInfo</code> provided when <code>memory</code> was allocated included a <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a> structure in its <code>pNext</code> chain, and <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a>::<code>buffer</code> was not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, then <code>buffer</code> <strong class=\"purple\">must</strong> equal <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a>::<code>buffer</code> and <code>memoryOffset</code> <strong class=\"purple\">must</strong> be zero."
+          "text": " If the <code>VkMemoryAllocateInfo</code> provided when <code>memory</code> was allocated included a <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a> structure in its <code>pNext</code> chain, and <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a>::<code>buffer</code> was not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, then <code>buffer</code> <strong class=\"purple\">must</strong> equal <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a>::<code>buffer</code> and <code>memoryOffset</code> <strong class=\"purple\">must</strong> be zero"
         }
       ],
       "(VK_VERSION_1_1,VK_KHR_bind_memory2)+(VK_NV_dedicated_allocation)": [
@@ -10652,7 +11342,7 @@
       "(VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion)": [
         {
           "vuid": "VUID-vkBindImageMemory-image-01608",
-          "text": " <code>image</code> <strong class=\"purple\">must</strong> not have been created with the <code>VK_IMAGE_CREATE_DISJOINT_BIT</code> set."
+          "text": " <code>image</code> <strong class=\"purple\">must</strong> not have been created with the <code>VK_IMAGE_CREATE_DISJOINT_BIT</code> set"
         }
       ],
       "core": [
@@ -10716,11 +11406,11 @@
       "(VK_VERSION_1_1,VK_KHR_dedicated_allocation)+(VK_NV_dedicated_allocation_image_aliasing)": [
         {
           "vuid": "VUID-vkBindImageMemory-memory-02628",
-          "text": " If the <a href=\"#features-dedicatedAllocationImageAliasing\">dedicated allocation image aliasing</a> feature is not enabled, and the <code>VkMemoryAllocateInfo</code> provided when <code>memory</code> was allocated included a <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a> structure in its <code>pNext</code> chain, and <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a>::<code>image</code> was not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, then <code>image</code> <strong class=\"purple\">must</strong> equal <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a>::<code>image</code> and <code>memoryOffset</code> <strong class=\"purple\">must</strong> be zero."
+          "text": " If the <a href=\"#features-dedicatedAllocationImageAliasing\">dedicated allocation image aliasing</a> feature is not enabled, and the <code>VkMemoryAllocateInfo</code> provided when <code>memory</code> was allocated included a <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a> structure in its <code>pNext</code> chain, and <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a>::<code>image</code> was not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, then <code>image</code> <strong class=\"purple\">must</strong> equal <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a>::<code>image</code> and <code>memoryOffset</code> <strong class=\"purple\">must</strong> be zero"
         },
         {
           "vuid": "VUID-vkBindImageMemory-memory-02629",
-          "text": " If the <a href=\"#features-dedicatedAllocationImageAliasing\">dedicated allocation image aliasing</a> feature is enabled, and the <code>VkMemoryAllocateInfo</code> provided when <code>memory</code> was allocated included a <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a> structure in its <code>pNext</code> chain, and <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a>::<code>image</code> was not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, then <code>memoryOffset</code> <strong class=\"purple\">must</strong> be zero, and <code>image</code> <strong class=\"purple\">must</strong> be either equal to <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a>::<code>image</code> or an image that was created using the same parameters in <code>VkImageCreateInfo</code>, with the exception that <code>extent</code> and <code>arrayLayers</code> <strong class=\"purple\">may</strong> differ subject to the following restrictions: every dimension in the <code>extent</code> parameter of the image being bound <strong class=\"purple\">must</strong> be equal to or smaller than the original image for which the allocation was created; and the <code>arrayLayers</code> parameter of the image being bound <strong class=\"purple\">must</strong> be equal to or smaller than the original image for which the allocation was created."
+          "text": " If the <a href=\"#features-dedicatedAllocationImageAliasing\">dedicated allocation image aliasing</a> feature is enabled, and the <code>VkMemoryAllocateInfo</code> provided when <code>memory</code> was allocated included a <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a> structure in its <code>pNext</code> chain, and <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a>::<code>image</code> was not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, then <code>memoryOffset</code> <strong class=\"purple\">must</strong> be zero, and <code>image</code> <strong class=\"purple\">must</strong> be either equal to <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a>::<code>image</code> or an image that was created using the same parameters in <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>, with the exception that <code>extent</code> and <code>arrayLayers</code> <strong class=\"purple\">may</strong> differ subject to the following restrictions: every dimension in the <code>extent</code> parameter of the image being bound <strong class=\"purple\">must</strong> be equal to or smaller than the original image for which the allocation was created; and the <code>arrayLayers</code> parameter of the image being bound <strong class=\"purple\">must</strong> be equal to or smaller than the original image for which the allocation was created"
         }
       ],
       "(VK_VERSION_1_1)": [
@@ -10842,7 +11532,7 @@
         },
         {
           "vuid": "VUID-VkBindImageMemoryInfo-pNext-01618",
-          "text": " If the <code>pNext</code> chain includes a <a href=\"#VkBindImagePlaneMemoryInfo\">VkBindImagePlaneMemoryInfo</a> structure, <code>image</code> <strong class=\"purple\">must</strong> have been created with the <code>VK_IMAGE_CREATE_DISJOINT_BIT</code> bit set."
+          "text": " If the <code>pNext</code> chain includes a <a href=\"#VkBindImagePlaneMemoryInfo\">VkBindImagePlaneMemoryInfo</a> structure, <code>image</code> <strong class=\"purple\">must</strong> have been created with the <code>VK_IMAGE_CREATE_DISJOINT_BIT</code> bit set"
         },
         {
           "vuid": "VUID-VkBindImageMemoryInfo-pNext-01619",
@@ -10866,17 +11556,17 @@
       "(VK_VERSION_1_1,VK_KHR_bind_memory2)+(VK_VERSION_1_1,VK_KHR_dedicated_allocation)+!(VK_NV_dedicated_allocation_image_aliasing)": [
         {
           "vuid": "VUID-VkBindImageMemoryInfo-memory-01903",
-          "text": " If the <code>VkMemoryAllocateInfo</code> provided when <code>memory</code> was allocated included a <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a> structure in its <code>pNext</code> chain, and <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a>::<code>image</code> was not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, then <code>image</code> <strong class=\"purple\">must</strong> equal <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a>::<code>image</code> and <code>memoryOffset</code> <strong class=\"purple\">must</strong> be zero."
+          "text": " If the <code>VkMemoryAllocateInfo</code> provided when <code>memory</code> was allocated included a <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a> structure in its <code>pNext</code> chain, and <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a>::<code>image</code> was not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, then <code>image</code> <strong class=\"purple\">must</strong> equal <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a>::<code>image</code> and <code>memoryOffset</code> <strong class=\"purple\">must</strong> be zero"
         }
       ],
       "(VK_VERSION_1_1,VK_KHR_bind_memory2)+(VK_VERSION_1_1,VK_KHR_dedicated_allocation)+(VK_NV_dedicated_allocation_image_aliasing)": [
         {
           "vuid": "VUID-VkBindImageMemoryInfo-memory-02630",
-          "text": " If the <a href=\"#features-dedicatedAllocationImageAliasing\">dedicated allocation image aliasing</a> feature is not enabled, and the <code>VkMemoryAllocateInfo</code> provided when <code>memory</code> was allocated included a <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a> structure in its <code>pNext</code> chain, and <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a>::<code>image</code> was not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, then <code>image</code> <strong class=\"purple\">must</strong> equal <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a>::<code>image</code> and <code>memoryOffset</code> <strong class=\"purple\">must</strong> be zero."
+          "text": " If the <a href=\"#features-dedicatedAllocationImageAliasing\">dedicated allocation image aliasing</a> feature is not enabled, and the <code>VkMemoryAllocateInfo</code> provided when <code>memory</code> was allocated included a <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a> structure in its <code>pNext</code> chain, and <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a>::<code>image</code> was not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, then <code>image</code> <strong class=\"purple\">must</strong> equal <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a>::<code>image</code> and <code>memoryOffset</code> <strong class=\"purple\">must</strong> be zero"
         },
         {
           "vuid": "VUID-VkBindImageMemoryInfo-memory-02631",
-          "text": " If the <a href=\"#features-dedicatedAllocationImageAliasing\">dedicated allocation image aliasing</a> feature is enabled, and the <code>VkMemoryAllocateInfo</code> provided when <code>memory</code> was allocated included a <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a> structure in its <code>pNext</code> chain, and <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a>::<code>image</code> was not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, then <code>memoryOffset</code> <strong class=\"purple\">must</strong> be zero, and <code>image</code> <strong class=\"purple\">must</strong> be either equal to <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a>::<code>image</code> or an image that was created using the same parameters in <code>VkImageCreateInfo</code>, with the exception that <code>extent</code> and <code>arrayLayers</code> <strong class=\"purple\">may</strong> differ subject to the following restrictions: every dimension in the <code>extent</code> parameter of the image being bound <strong class=\"purple\">must</strong> be equal to or smaller than the original image for which the allocation was created; and the <code>arrayLayers</code> parameter of the image being bound <strong class=\"purple\">must</strong> be equal to or smaller than the original image for which the allocation was created."
+          "text": " If the <a href=\"#features-dedicatedAllocationImageAliasing\">dedicated allocation image aliasing</a> feature is enabled, and the <code>VkMemoryAllocateInfo</code> provided when <code>memory</code> was allocated included a <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a> structure in its <code>pNext</code> chain, and <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a>::<code>image</code> was not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, then <code>memoryOffset</code> <strong class=\"purple\">must</strong> be zero, and <code>image</code> <strong class=\"purple\">must</strong> be either equal to <a href=\"#VkMemoryDedicatedAllocateInfo\">VkMemoryDedicatedAllocateInfo</a>::<code>image</code> or an image that was created using the same parameters in <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>, with the exception that <code>extent</code> and <code>arrayLayers</code> <strong class=\"purple\">may</strong> differ subject to the following restrictions: every dimension in the <code>extent</code> parameter of the image being bound <strong class=\"purple\">must</strong> be equal to or smaller than the original image for which the allocation was created; and the <code>arrayLayers</code> parameter of the image being bound <strong class=\"purple\">must</strong> be equal to or smaller than the original image for which the allocation was created"
         }
       ],
       "(VK_VERSION_1_1,VK_KHR_bind_memory2)+(VK_NV_dedicated_allocation)": [
@@ -10918,7 +11608,7 @@
       "(VK_VERSION_1_1,VK_KHR_bind_memory2)+(VK_VERSION_1_1,VK_KHR_device_group)+(VK_KHR_swapchain)": [
         {
           "vuid": "VUID-VkBindImageMemoryInfo-image-01630",
-          "text": " If <code>image</code> was created with a valid swapchain handle in <a href=\"#VkImageSwapchainCreateInfoKHR\">VkImageSwapchainCreateInfoKHR</a>::<code>swapchain</code>, then the <code>pNext</code> chain <strong class=\"purple\">must</strong> include a <a href=\"#VkBindImageMemorySwapchainInfoKHR\">VkBindImageMemorySwapchainInfoKHR</a> structure containing the same swapchain handle."
+          "text": " If <code>image</code> was created with a valid swapchain handle in <a href=\"#VkImageSwapchainCreateInfoKHR\">VkImageSwapchainCreateInfoKHR</a>::<code>swapchain</code>, then the <code>pNext</code> chain <strong class=\"purple\">must</strong> include a <a href=\"#VkBindImageMemorySwapchainInfoKHR\">VkBindImageMemorySwapchainInfoKHR</a> structure containing the same swapchain handle"
         },
         {
           "vuid": "VUID-VkBindImageMemoryInfo-pNext-01631",
@@ -10944,7 +11634,7 @@
       "(VK_VERSION_1_1,VK_KHR_bind_memory2)+(VK_VERSION_1_1,VK_KHR_device_group)": [
         {
           "vuid": "VUID-VkBindImageMemoryDeviceGroupInfo-deviceIndexCount-01633",
-          "text": " At least one of <code>deviceIndexCount</code> and <code>splitInstanceBindRegionCount</code> <strong class=\"purple\">must</strong> be zero."
+          "text": " At least one of <code>deviceIndexCount</code> and <code>splitInstanceBindRegionCount</code> <strong class=\"purple\">must</strong> be zero"
         },
         {
           "vuid": "VUID-VkBindImageMemoryDeviceGroupInfo-deviceIndexCount-01634",
@@ -10952,7 +11642,7 @@
         },
         {
           "vuid": "VUID-VkBindImageMemoryDeviceGroupInfo-pDeviceIndices-01635",
-          "text": " All elements of <code>pDeviceIndices</code> <strong class=\"purple\">must</strong> be valid device indices."
+          "text": " All elements of <code>pDeviceIndices</code> <strong class=\"purple\">must</strong> be valid device indices"
         },
         {
           "vuid": "VUID-VkBindImageMemoryDeviceGroupInfo-splitInstanceBindRegionCount-01636",
@@ -10960,7 +11650,7 @@
         },
         {
           "vuid": "VUID-VkBindImageMemoryDeviceGroupInfo-pSplitInstanceBindRegions-01637",
-          "text": " Elements of <code>pSplitInstanceBindRegions</code> that correspond to the same instance of an image <strong class=\"purple\">must</strong> not overlap."
+          "text": " Elements of <code>pSplitInstanceBindRegions</code> that correspond to the same instance of an image <strong class=\"purple\">must</strong> not overlap"
         },
         {
           "vuid": "VUID-VkBindImageMemoryDeviceGroupInfo-offset-01638",
@@ -11012,7 +11702,7 @@
       "(VK_VERSION_1_1,VK_KHR_bind_memory2)+(VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion)": [
         {
           "vuid": "VUID-VkBindImagePlaneMemoryInfo-planeAspect-02283",
-          "text": " If the image&#8217;s tiling is <code>VK_IMAGE_TILING_LINEAR</code> or <code>VK_IMAGE_TILING_OPTIMAL</code>, then <code>planeAspect</code> <strong class=\"purple\">must</strong> be a single valid <em>format plane</em> for the image. (That is, <code>planeAspect</code> <strong class=\"purple\">must</strong> be <code>VK_IMAGE_ASPECT_PLANE_0_BIT</code> or <code>VK_IMAGE_ASPECT_PLANE_1_BIT</code> for &#8220;<code>_2PLANE</code>&#8221; formats and <code>planeAspect</code> <strong class=\"purple\">must</strong> be <code>VK_IMAGE_ASPECT_PLANE_0_BIT</code>, <code>VK_IMAGE_ASPECT_PLANE_1_BIT</code>, or <code>VK_IMAGE_ASPECT_PLANE_2_BIT</code> for &#8220;<code>_3PLANE</code>&#8221; formats.)"
+          "text": " If the image&#8217;s <code>tiling</code> is <code>VK_IMAGE_TILING_LINEAR</code> or <code>VK_IMAGE_TILING_OPTIMAL</code>, then <code>planeAspect</code> <strong class=\"purple\">must</strong> be a single valid <em>format plane</em> for the image (that is, for a two-plane image <code>planeAspect</code> <strong class=\"purple\">must</strong> be <code>VK_IMAGE_ASPECT_PLANE_0_BIT</code> or <code>VK_IMAGE_ASPECT_PLANE_1_BIT</code>, and for a three-plane image <code>planeAspect</code> <strong class=\"purple\">must</strong> be <code>VK_IMAGE_ASPECT_PLANE_0_BIT</code>, <code>VK_IMAGE_ASPECT_PLANE_1_BIT</code> or <code>VK_IMAGE_ASPECT_PLANE_2_BIT</code>)"
         },
         {
           "vuid": "VUID-VkBindImagePlaneMemoryInfo-sType-sType",
@@ -11026,12 +11716,12 @@
       "(VK_VERSION_1_1,VK_KHR_bind_memory2)+(VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion)+(VK_EXT_image_drm_format_modifier)": [
         {
           "vuid": "VUID-VkBindImagePlaneMemoryInfo-planeAspect-02284",
-          "text": "  If the image&#8217;s tiling is <code>VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT</code>,  then <code>planeAspect</code> <strong class=\"purple\">must</strong> be a single valid <em>memory plane</em> for the  image.  (That is, <code>aspectMask</code> <strong class=\"purple\">must</strong> specify a plane index that is less than  the  <a href=\"#VkDrmFormatModifierPropertiesEXT\"><code>drmFormatModifierPlaneCount</code></a>  associated with the image&#8217;s <a href=\"#VkImageCreateInfo\"><code>format</code></a> and <a href=\"#VkImageDrmFormatModifierPropertiesEXT\"><code>drmFormatModifier</code></a>.)"
+          "text": " If the image&#8217;s <code>tiling</code> is <code>VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT</code>, then <code>planeAspect</code> <strong class=\"purple\">must</strong> be a single valid <em>memory plane</em> for the image (that is, <code>aspectMask</code> <strong class=\"purple\">must</strong> specify a plane index that is less than the <a href=\"#VkDrmFormatModifierPropertiesEXT\">VkDrmFormatModifierPropertiesEXT</a>::<code>drmFormatModifierPlaneCount</code> associated with the image&#8217;s <code>format</code> and <a href=\"#VkImageDrmFormatModifierPropertiesEXT\">VkImageDrmFormatModifierPropertiesEXT</a>::<code>drmFormatModifier</code>)"
         }
       ]
     },
     "vkCreateAccelerationStructureNV": {
-      "(VK_NV_ray_tracing)": [
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_NV_ray_tracing)": [
         {
           "vuid": "VUID-vkCreateAccelerationStructureNV-device-parameter",
           "text": " <code>device</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDevice\">VkDevice</a> handle"
@@ -11051,7 +11741,7 @@
       ]
     },
     "VkAccelerationStructureCreateInfoNV": {
-      "(VK_NV_ray_tracing)": [
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_NV_ray_tracing)": [
         {
           "vuid": "VUID-VkAccelerationStructureCreateInfoNV-compactedSize-02421",
           "text": " If <code>compactedSize</code> is not <code>0</code> then both <code>info.geometryCount</code> and <code>info.instanceCount</code> <strong class=\"purple\">must</strong> be <code>0</code>"
@@ -11071,7 +11761,7 @@
       ]
     },
     "VkAccelerationStructureInfoNV": {
-      "(VK_NV_ray_tracing)": [
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_NV_ray_tracing)": [
         {
           "vuid": "VUID-VkAccelerationStructureInfoNV-geometryCount-02422",
           "text": " <code>geometryCount</code> <strong class=\"purple\">must</strong> be less than or equal to <a href=\"#VkPhysicalDeviceRayTracingPropertiesNV\">VkPhysicalDeviceRayTracingPropertiesNV</a>::<code>maxGeometryCount</code>"
@@ -11097,6 +11787,10 @@
           "text": " If <code>type</code> is <code>VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV</code> then the <code>geometryType</code> member of each geometry in <code>pGeometries</code> <strong class=\"purple\">must</strong> be the same"
         },
         {
+          "vuid": "VUID-VkAccelerationStructureInfoNV-flags-03486",
+          "text": " <code>flags</code> <strong class=\"purple\">must</strong> be a valid combination of <a href=\"#VkBuildAccelerationStructureFlagBitsNV\">VkBuildAccelerationStructureFlagBitsNV</a> values"
+        },
+        {
           "vuid": "VUID-VkAccelerationStructureInfoNV-flags-02592",
           "text": " If <code>flags</code> has the <code>VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_NV</code> bit set, then it <strong class=\"purple\">must</strong> not have the <code>VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_NV</code> bit set"
         },
@@ -11121,8 +11815,8 @@
           "text": " <code>type</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkAccelerationStructureTypeNV\">VkAccelerationStructureTypeNV</a> value"
         },
         {
-          "vuid": "VUID-VkAccelerationStructureInfoNV-flags-parameter",
-          "text": " <code>flags</code> <strong class=\"purple\">must</strong> be a valid combination of <a href=\"#VkBuildAccelerationStructureFlagBitsNV\">VkBuildAccelerationStructureFlagBitsNV</a> values"
+          "vuid": "VUID-VkAccelerationStructureInfoNV-flags-zerobitmask",
+          "text": " <code>flags</code> <strong class=\"purple\">must</strong> be <code>0</code>"
         },
         {
           "vuid": "VUID-VkAccelerationStructureInfoNV-pGeometries-parameter",
@@ -11130,8 +11824,148 @@
         }
       ]
     },
+    "vkCreateAccelerationStructureKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-vkCreateAccelerationStructureKHR-rayTracing-03487",
+          "text": " The <a href=\"#features-raytracing\"><code>rayTracing</code></a> or <a href=\"#features-rayQuery\"><code>rayQuery</code></a> feature <strong class=\"purple\">must</strong> be enabled"
+        },
+        {
+          "vuid": "VUID-vkCreateAccelerationStructureKHR-deviceAddress-03488",
+          "text": " If <a href=\"#VkAccelerationStructureCreateInfoKHR\">VkAccelerationStructureCreateInfoKHR</a>::<code>deviceAddress</code> is not zero, the <a href=\"#features-raytracing-ascapturereplay\"><code>rayTracingAccelerationStructureCaptureReplay</code></a> feature <strong class=\"purple\">must</strong> be enabled"
+        },
+        {
+          "vuid": "VUID-vkCreateAccelerationStructureKHR-device-03489",
+          "text": " If <code>device</code> was created with multiple physical devices, then the <a href=\"#features-bufferDeviceAddressMultiDevice\">bufferDeviceAddressMultiDevice</a> feature <strong class=\"purple\">must</strong> be enabled"
+        },
+        {
+          "vuid": "VUID-vkCreateAccelerationStructureKHR-device-parameter",
+          "text": " <code>device</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDevice\">VkDevice</a> handle"
+        },
+        {
+          "vuid": "VUID-vkCreateAccelerationStructureKHR-pCreateInfo-parameter",
+          "text": " <code>pCreateInfo</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkAccelerationStructureCreateInfoKHR\">VkAccelerationStructureCreateInfoKHR</a> structure"
+        },
+        {
+          "vuid": "VUID-vkCreateAccelerationStructureKHR-pAllocator-parameter",
+          "text": " If <code>pAllocator</code> is not <code>NULL</code>, <code>pAllocator</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkAllocationCallbacks\">VkAllocationCallbacks</a> structure"
+        },
+        {
+          "vuid": "VUID-vkCreateAccelerationStructureKHR-pAccelerationStructure-parameter",
+          "text": " <code>pAccelerationStructure</code> <strong class=\"purple\">must</strong> be a valid pointer to a <a href=\"#VkAccelerationStructureKHR\">VkAccelerationStructureKHR</a> handle"
+        }
+      ]
+    },
+    "VkAccelerationStructureCreateInfoKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-VkAccelerationStructureCreateInfoKHR-compactedSize-03490",
+          "text": " If <code>compactedSize</code> is not <code>0</code> then <code>maxGeometryCount</code> <strong class=\"purple\">must</strong> be <code>0</code>"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureCreateInfoKHR-type-03491",
+          "text": " If <code>type</code> is <code>VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR</code> then <code>maxGeometryCount</code> <strong class=\"purple\">must</strong> be less than or equal to <a href=\"#VkPhysicalDeviceRayTracingPropertiesKHR\">VkPhysicalDeviceRayTracingPropertiesKHR</a>::<code>maxGeometryCount</code>"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureCreateInfoKHR-type-03492",
+          "text": " If <code>type</code> is <code>VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR</code> then <code>pGeometryInfos-&gt;maxPrimitiveCount</code> <strong class=\"purple\">must</strong> be less than or equal to <a href=\"#VkPhysicalDeviceRayTracingPropertiesKHR\">VkPhysicalDeviceRayTracingPropertiesKHR</a>::<code>maxInstanceCount</code>"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureCreateInfoKHR-maxPrimitiveCount-03493",
+          "text": " The total number of triangles in all geometries <strong class=\"purple\">must</strong> be less than or equal to <a href=\"#VkPhysicalDeviceRayTracingPropertiesKHR\">VkPhysicalDeviceRayTracingPropertiesKHR</a>::<code>maxPrimitiveCount</code>"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureCreateInfoKHR-maxPrimitiveCount-03494",
+          "text": " The total number of AABBs in all geometries <strong class=\"purple\">must</strong> be less than or equal to <a href=\"#VkPhysicalDeviceRayTracingPropertiesKHR\">VkPhysicalDeviceRayTracingPropertiesKHR</a>::<code>maxPrimitiveCount</code>"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureCreateInfoKHR-type-03495",
+          "text": " If <code>type</code> is <code>VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR</code> and <code>compactedSize</code> is <code>0</code>, <code>maxGeometryCount</code> <strong class=\"purple\">must</strong> be <code>1</code>"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureCreateInfoKHR-type-03496",
+          "text": " If <code>type</code> is <code>VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR</code> and <code>compactedSize</code> is <code>0</code>, the <code>geometryType</code> member of elements of <code>pGeometryInfos</code> <strong class=\"purple\">must</strong> be <code>VK_GEOMETRY_TYPE_INSTANCES_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureCreateInfoKHR-type-03497",
+          "text": " If <code>type</code> is <code>VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR</code> and <code>compactedSize</code> is <code>0</code>, the <code>geometryType</code> member of elements of <code>pGeometryInfos</code> <strong class=\"purple\">must</strong> not be <code>VK_GEOMETRY_TYPE_INSTANCES_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureCreateInfoKHR-type-03498",
+          "text": " If <code>type</code> is <code>VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR</code> then the <code>geometryType</code> member of each geometry in <code>pGeometryInfos</code> <strong class=\"purple\">must</strong> be the same"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureCreateInfoKHR-flags-03499",
+          "text": " If <code>flags</code> has the <code>VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR</code> bit set, then it <strong class=\"purple\">must</strong> not have the <code>VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR</code> bit set"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureCreateInfoKHR-deviceAddress-03500",
+          "text": " If <code>deviceAddress</code> is not <code>0</code>, <a href=\"#VkPhysicalDeviceRayTracingFeaturesKHR\">VkPhysicalDeviceRayTracingFeaturesKHR</a>::<code>rayTracingAccelerationStructureCaptureReplay</code> <strong class=\"purple\">must</strong> be <code>VK_TRUE</code>"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureCreateInfoKHR-sType-sType",
+          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureCreateInfoKHR-pNext-pNext",
+          "text": " <code>pNext</code> <strong class=\"purple\">must</strong> be <code>NULL</code>"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureCreateInfoKHR-type-parameter",
+          "text": " <code>type</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkAccelerationStructureTypeKHR\">VkAccelerationStructureTypeKHR</a> value"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureCreateInfoKHR-flags-parameter",
+          "text": " <code>flags</code> <strong class=\"purple\">must</strong> be a valid combination of <a href=\"#VkBuildAccelerationStructureFlagBitsKHR\">VkBuildAccelerationStructureFlagBitsKHR</a> values"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureCreateInfoKHR-pGeometryInfos-parameter",
+          "text": " <code>pGeometryInfos</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>maxGeometryCount</code> valid <a href=\"#VkAccelerationStructureCreateGeometryTypeInfoKHR\">VkAccelerationStructureCreateGeometryTypeInfoKHR</a> structures"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureCreateInfoKHR-maxGeometryCount-arraylength",
+          "text": " <code>maxGeometryCount</code> <strong class=\"purple\">must</strong> be greater than <code>0</code>"
+        }
+      ]
+    },
+    "VkAccelerationStructureCreateGeometryTypeInfoKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-VkAccelerationStructureCreateGeometryTypeInfoKHR-geometryType-03501",
+          "text": " If <code>geometryType</code> is <code>VK_GEOMETRY_TYPE_TRIANGLES_KHR</code>, <code>vertexFormat</code> <strong class=\"purple\">must</strong> support the <code>VK_FORMAT_FEATURE_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR</code> in <a href=\"#VkFormatProperties\">VkFormatProperties</a>::<code>bufferFeatures</code> as returned by <a href=\"#vkGetPhysicalDeviceFormatProperties2\">vkGetPhysicalDeviceFormatProperties2</a>"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureCreateGeometryTypeInfoKHR-geometryType-03502",
+          "text": " If <code>geometryType</code> is <code>VK_GEOMETRY_TYPE_TRIANGLES_KHR</code>, <code>indexType</code> <strong class=\"purple\">must</strong> be <code>VK_INDEX_TYPE_UINT16</code>, <code>VK_INDEX_TYPE_UINT32</code>, or <code>VK_INDEX_TYPE_NONE_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureCreateGeometryTypeInfoKHR-sType-sType",
+          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureCreateGeometryTypeInfoKHR-pNext-pNext",
+          "text": " <code>pNext</code> <strong class=\"purple\">must</strong> be <code>NULL</code>"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureCreateGeometryTypeInfoKHR-geometryType-parameter",
+          "text": " <code>geometryType</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkGeometryTypeKHR\">VkGeometryTypeKHR</a> value"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureCreateGeometryTypeInfoKHR-indexType-parameter",
+          "text": " <code>indexType</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkIndexType\">VkIndexType</a> value"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureCreateGeometryTypeInfoKHR-vertexFormat-parameter",
+          "text": " If <code>vertexFormat</code> is not <code>0</code>, <code>vertexFormat</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkFormat\">VkFormat</a> value"
+        }
+      ]
+    },
     "VkGeometryNV": {
-      "(VK_NV_ray_tracing)": [
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_NV_ray_tracing)": [
+        {
+          "vuid": "VUID-VkGeometryNV-geometryType-03503",
+          "text": " <code>geometryType</code> <strong class=\"purple\">must</strong> be <code>VK_GEOMETRY_TYPE_TRIANGLES_NV</code> or <code>VK_GEOMETRY_TYPE_AABBS_NV</code>"
+        },
         {
           "vuid": "VUID-VkGeometryNV-sType-sType",
           "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_GEOMETRY_NV</code>"
@@ -11142,7 +11976,7 @@
         },
         {
           "vuid": "VUID-VkGeometryNV-geometryType-parameter",
-          "text": " <code>geometryType</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkGeometryTypeNV\">VkGeometryTypeNV</a> value"
+          "text": " <code>geometryType</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkGeometryTypeKHR\">VkGeometryTypeKHR</a> value"
         },
         {
           "vuid": "VUID-VkGeometryNV-geometry-parameter",
@@ -11150,12 +11984,12 @@
         },
         {
           "vuid": "VUID-VkGeometryNV-flags-parameter",
-          "text": " <code>flags</code> <strong class=\"purple\">must</strong> be a valid combination of <a href=\"#VkGeometryFlagBitsNV\">VkGeometryFlagBitsNV</a> values"
+          "text": " <code>flags</code> <strong class=\"purple\">must</strong> be a valid combination of <a href=\"#VkGeometryFlagBitsKHR\">VkGeometryFlagBitsKHR</a> values"
         }
       ]
     },
     "VkGeometryDataNV": {
-      "(VK_NV_ray_tracing)": [
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_NV_ray_tracing)": [
         {
           "vuid": "VUID-VkGeometryDataNV-triangles-parameter",
           "text": " <code>triangles</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkGeometryTrianglesNV\">VkGeometryTrianglesNV</a> structure"
@@ -11167,7 +12001,7 @@
       ]
     },
     "VkGeometryTrianglesNV": {
-      "(VK_NV_ray_tracing)": [
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_NV_ray_tracing)": [
         {
           "vuid": "VUID-VkGeometryTrianglesNV-vertexOffset-02428",
           "text": " <code>vertexOffset</code> <strong class=\"purple\">must</strong> be less than the size of <code>vertexData</code>"
@@ -11247,7 +12081,7 @@
       ]
     },
     "VkGeometryAABBNV": {
-      "(VK_NV_ray_tracing)": [
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_NV_ray_tracing)": [
         {
           "vuid": "VUID-VkGeometryAABBNV-offset-02439",
           "text": " <code>offset</code> <strong class=\"purple\">must</strong> be less than the size of <code>aabbData</code>"
@@ -11274,40 +12108,40 @@
         }
       ]
     },
-    "vkDestroyAccelerationStructureNV": {
-      "(VK_NV_ray_tracing)": [
+    "vkDestroyAccelerationStructureKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)": [
         {
-          "vuid": "VUID-vkDestroyAccelerationStructureNV-accelerationStructure-02442",
+          "vuid": "VUID-vkDestroyAccelerationStructureKHR-accelerationStructure-02442",
           "text": " All submitted commands that refer to <code>accelerationStructure</code> <strong class=\"purple\">must</strong> have completed execution"
         },
         {
-          "vuid": "VUID-vkDestroyAccelerationStructureNV-accelerationStructure-02443",
+          "vuid": "VUID-vkDestroyAccelerationStructureKHR-accelerationStructure-02443",
           "text": " If <code>VkAllocationCallbacks</code> were provided when <code>accelerationStructure</code> was created, a compatible set of callbacks <strong class=\"purple\">must</strong> be provided here"
         },
         {
-          "vuid": "VUID-vkDestroyAccelerationStructureNV-accelerationStructure-02444",
+          "vuid": "VUID-vkDestroyAccelerationStructureKHR-accelerationStructure-02444",
           "text": " If no <code>VkAllocationCallbacks</code> were provided when <code>accelerationStructure</code> was created, <code>pAllocator</code> <strong class=\"purple\">must</strong> be <code>NULL</code>"
         },
         {
-          "vuid": "VUID-vkDestroyAccelerationStructureNV-device-parameter",
+          "vuid": "VUID-vkDestroyAccelerationStructureKHR-device-parameter",
           "text": " <code>device</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDevice\">VkDevice</a> handle"
         },
         {
-          "vuid": "VUID-vkDestroyAccelerationStructureNV-accelerationStructure-parameter",
-          "text": " <code>accelerationStructure</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkAccelerationStructureNV\">VkAccelerationStructureNV</a> handle"
+          "vuid": "VUID-vkDestroyAccelerationStructureKHR-accelerationStructure-parameter",
+          "text": " <code>accelerationStructure</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkAccelerationStructureKHR\">VkAccelerationStructureKHR</a> handle"
         },
         {
-          "vuid": "VUID-vkDestroyAccelerationStructureNV-pAllocator-parameter",
+          "vuid": "VUID-vkDestroyAccelerationStructureKHR-pAllocator-parameter",
           "text": " If <code>pAllocator</code> is not <code>NULL</code>, <code>pAllocator</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkAllocationCallbacks\">VkAllocationCallbacks</a> structure"
         },
         {
-          "vuid": "VUID-vkDestroyAccelerationStructureNV-accelerationStructure-parent",
+          "vuid": "VUID-vkDestroyAccelerationStructureKHR-accelerationStructure-parent",
           "text": " <code>accelerationStructure</code> <strong class=\"purple\">must</strong> have been created, allocated, or retrieved from <code>device</code>"
         }
       ]
     },
     "vkGetAccelerationStructureMemoryRequirementsNV": {
-      "(VK_NV_ray_tracing)": [
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_NV_ray_tracing)": [
         {
           "vuid": "VUID-vkGetAccelerationStructureMemoryRequirementsNV-device-parameter",
           "text": " <code>device</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDevice\">VkDevice</a> handle"
@@ -11323,7 +12157,7 @@
       ]
     },
     "VkAccelerationStructureMemoryRequirementsInfoNV": {
-      "(VK_NV_ray_tracing)": [
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_NV_ray_tracing)": [
         {
           "vuid": "VUID-VkAccelerationStructureMemoryRequirementsInfoNV-sType-sType",
           "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV</code>"
@@ -11342,79 +12176,119 @@
         }
       ]
     },
-    "vkBindAccelerationStructureMemoryNV": {
-      "(VK_NV_ray_tracing)": [
+    "vkGetAccelerationStructureMemoryRequirementsKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)": [
         {
-          "vuid": "VUID-vkBindAccelerationStructureMemoryNV-device-parameter",
+          "vuid": "VUID-vkGetAccelerationStructureMemoryRequirementsKHR-device-parameter",
           "text": " <code>device</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDevice\">VkDevice</a> handle"
         },
         {
-          "vuid": "VUID-vkBindAccelerationStructureMemoryNV-pBindInfos-parameter",
-          "text": " <code>pBindInfos</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>bindInfoCount</code> valid <a href=\"#VkBindAccelerationStructureMemoryInfoNV\">VkBindAccelerationStructureMemoryInfoNV</a> structures"
+          "vuid": "VUID-vkGetAccelerationStructureMemoryRequirementsKHR-pInfo-parameter",
+          "text": " <code>pInfo</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkAccelerationStructureMemoryRequirementsInfoKHR\">VkAccelerationStructureMemoryRequirementsInfoKHR</a> structure"
         },
         {
-          "vuid": "VUID-vkBindAccelerationStructureMemoryNV-bindInfoCount-arraylength",
+          "vuid": "VUID-vkGetAccelerationStructureMemoryRequirementsKHR-pMemoryRequirements-parameter",
+          "text": " <code>pMemoryRequirements</code> <strong class=\"purple\">must</strong> be a valid pointer to a <a href=\"#VkMemoryRequirements2\">VkMemoryRequirements2</a> structure"
+        }
+      ]
+    },
+    "VkAccelerationStructureMemoryRequirementsInfoKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-VkAccelerationStructureMemoryRequirementsInfoKHR-sType-sType",
+          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureMemoryRequirementsInfoKHR-pNext-pNext",
+          "text": " <code>pNext</code> <strong class=\"purple\">must</strong> be <code>NULL</code>"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureMemoryRequirementsInfoKHR-type-parameter",
+          "text": " <code>type</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkAccelerationStructureMemoryRequirementsTypeKHR\">VkAccelerationStructureMemoryRequirementsTypeKHR</a> value"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureMemoryRequirementsInfoKHR-buildType-parameter",
+          "text": " <code>buildType</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkAccelerationStructureBuildTypeKHR\">VkAccelerationStructureBuildTypeKHR</a> value"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureMemoryRequirementsInfoKHR-accelerationStructure-parameter",
+          "text": " <code>accelerationStructure</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkAccelerationStructureKHR\">VkAccelerationStructureKHR</a> handle"
+        }
+      ]
+    },
+    "vkBindAccelerationStructureMemoryKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-vkBindAccelerationStructureMemoryKHR-device-parameter",
+          "text": " <code>device</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDevice\">VkDevice</a> handle"
+        },
+        {
+          "vuid": "VUID-vkBindAccelerationStructureMemoryKHR-pBindInfos-parameter",
+          "text": " <code>pBindInfos</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>bindInfoCount</code> valid <a href=\"#VkBindAccelerationStructureMemoryInfoKHR\">VkBindAccelerationStructureMemoryInfoKHR</a> structures"
+        },
+        {
+          "vuid": "VUID-vkBindAccelerationStructureMemoryKHR-bindInfoCount-arraylength",
           "text": " <code>bindInfoCount</code> <strong class=\"purple\">must</strong> be greater than <code>0</code>"
         }
       ]
     },
-    "VkBindAccelerationStructureMemoryInfoNV": {
-      "(VK_NV_ray_tracing)": [
+    "VkBindAccelerationStructureMemoryInfoKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)": [
         {
-          "vuid": "VUID-VkBindAccelerationStructureMemoryInfoNV-accelerationStructure-02450",
+          "vuid": "VUID-VkBindAccelerationStructureMemoryInfoKHR-accelerationStructure-02450",
           "text": " <code>accelerationStructure</code> <strong class=\"purple\">must</strong> not already be backed by a memory object"
         },
         {
-          "vuid": "VUID-VkBindAccelerationStructureMemoryInfoNV-memoryOffset-02451",
+          "vuid": "VUID-VkBindAccelerationStructureMemoryInfoKHR-memoryOffset-02451",
           "text": " <code>memoryOffset</code> <strong class=\"purple\">must</strong> be less than the size of <code>memory</code>"
         },
         {
-          "vuid": "VUID-VkBindAccelerationStructureMemoryInfoNV-memory-02593",
-          "text": " <code>memory</code> <strong class=\"purple\">must</strong> have been allocated using one of the memory types allowed in the <code>memoryTypeBits</code> member of the <a href=\"#VkMemoryRequirements\">VkMemoryRequirements</a> structure returned from a call to <a href=\"#vkGetAccelerationStructureMemoryRequirementsNV\">vkGetAccelerationStructureMemoryRequirementsNV</a> with <code>accelerationStructure</code> and <code>type</code> of <code>VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV</code>"
+          "vuid": "VUID-VkBindAccelerationStructureMemoryInfoKHR-memory-02593",
+          "text": " <code>memory</code> <strong class=\"purple\">must</strong> have been allocated using one of the memory types allowed in the <code>memoryTypeBits</code> member of the <a href=\"#VkMemoryRequirements\">VkMemoryRequirements</a> structure returned from a call to <a href=\"#vkGetAccelerationStructureMemoryRequirementsKHR\">vkGetAccelerationStructureMemoryRequirementsKHR</a> with <code>accelerationStructure</code> and <code>type</code> of <code>VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR</code>"
         },
         {
-          "vuid": "VUID-VkBindAccelerationStructureMemoryInfoNV-memoryOffset-02594",
-          "text": " <code>memoryOffset</code> <strong class=\"purple\">must</strong> be an integer multiple of the <code>alignment</code> member of the <a href=\"#VkMemoryRequirements\">VkMemoryRequirements</a> structure returned from a call to <a href=\"#vkGetAccelerationStructureMemoryRequirementsNV\">vkGetAccelerationStructureMemoryRequirementsNV</a> with <code>accelerationStructure</code> and <code>type</code> of <code>VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV</code>"
+          "vuid": "VUID-VkBindAccelerationStructureMemoryInfoKHR-memoryOffset-02594",
+          "text": " <code>memoryOffset</code> <strong class=\"purple\">must</strong> be an integer multiple of the <code>alignment</code> member of the <a href=\"#VkMemoryRequirements\">VkMemoryRequirements</a> structure returned from a call to <a href=\"#vkGetAccelerationStructureMemoryRequirementsKHR\">vkGetAccelerationStructureMemoryRequirementsKHR</a> with <code>accelerationStructure</code> and <code>type</code> of <code>VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR</code>"
         },
         {
-          "vuid": "VUID-VkBindAccelerationStructureMemoryInfoNV-size-02595",
-          "text": " The <code>size</code> member of the <code>VkMemoryRequirements</code> structure returned from a call to <a href=\"#vkGetAccelerationStructureMemoryRequirementsNV\">vkGetAccelerationStructureMemoryRequirementsNV</a> with <code>accelerationStructure</code> and <code>type</code> of <code>VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV</code> <strong class=\"purple\">must</strong> be less than or equal to the size of <code>memory</code> minus <code>memoryOffset</code>"
+          "vuid": "VUID-VkBindAccelerationStructureMemoryInfoKHR-size-02595",
+          "text": " The <code>size</code> member of the <code>VkMemoryRequirements</code> structure returned from a call to <a href=\"#vkGetAccelerationStructureMemoryRequirementsKHR\">vkGetAccelerationStructureMemoryRequirementsKHR</a> with <code>accelerationStructure</code> and <code>type</code> of <code>VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR</code> <strong class=\"purple\">must</strong> be less than or equal to the size of <code>memory</code> minus <code>memoryOffset</code>"
         },
         {
-          "vuid": "VUID-VkBindAccelerationStructureMemoryInfoNV-sType-sType",
-          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV</code>"
+          "vuid": "VUID-VkBindAccelerationStructureMemoryInfoKHR-sType-sType",
+          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_KHR</code>"
         },
         {
-          "vuid": "VUID-VkBindAccelerationStructureMemoryInfoNV-pNext-pNext",
+          "vuid": "VUID-VkBindAccelerationStructureMemoryInfoKHR-pNext-pNext",
           "text": " <code>pNext</code> <strong class=\"purple\">must</strong> be <code>NULL</code>"
         },
         {
-          "vuid": "VUID-VkBindAccelerationStructureMemoryInfoNV-accelerationStructure-parameter",
-          "text": " <code>accelerationStructure</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkAccelerationStructureNV\">VkAccelerationStructureNV</a> handle"
+          "vuid": "VUID-VkBindAccelerationStructureMemoryInfoKHR-accelerationStructure-parameter",
+          "text": " <code>accelerationStructure</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkAccelerationStructureKHR\">VkAccelerationStructureKHR</a> handle"
         },
         {
-          "vuid": "VUID-VkBindAccelerationStructureMemoryInfoNV-memory-parameter",
+          "vuid": "VUID-VkBindAccelerationStructureMemoryInfoKHR-memory-parameter",
           "text": " <code>memory</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDeviceMemory\">VkDeviceMemory</a> handle"
         },
         {
-          "vuid": "VUID-VkBindAccelerationStructureMemoryInfoNV-pDeviceIndices-parameter",
+          "vuid": "VUID-VkBindAccelerationStructureMemoryInfoKHR-pDeviceIndices-parameter",
           "text": " If <code>deviceIndexCount</code> is not <code>0</code>, <code>pDeviceIndices</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>deviceIndexCount</code> <code>uint32_t</code> values"
         },
         {
-          "vuid": "VUID-VkBindAccelerationStructureMemoryInfoNV-commonparent",
+          "vuid": "VUID-VkBindAccelerationStructureMemoryInfoKHR-commonparent",
           "text": " Both of <code>accelerationStructure</code>, and <code>memory</code> <strong class=\"purple\">must</strong> have been created, allocated, or retrieved from the same <a href=\"#VkDevice\">VkDevice</a>"
         }
       ]
     },
     "vkGetAccelerationStructureHandleNV": {
-      "(VK_NV_ray_tracing)": [
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_NV_ray_tracing)": [
         {
           "vuid": "VUID-vkGetAccelerationStructureHandleNV-dataSize-02240",
           "text": " <code>dataSize</code> <strong class=\"purple\">must</strong> be large enough to contain the result of the query, as described above"
         },
         {
           "vuid": "VUID-vkGetAccelerationStructureHandleNV-accelerationStructure-02787",
-          "text": " <code>accelerationStructure</code> <strong class=\"purple\">must</strong> be bound completely and contiguously to a single <code>VkDeviceMemory</code> object via <a href=\"#vkBindAccelerationStructureMemoryNV\">vkBindAccelerationStructureMemoryNV</a>"
+          "text": " <code>accelerationStructure</code> <strong class=\"purple\">must</strong> be bound completely and contiguously to a single <code>VkDeviceMemory</code> object via <a href=\"#vkBindAccelerationStructureMemoryKHR\">vkBindAccelerationStructureMemoryKHR</a>"
         },
         {
           "vuid": "VUID-vkGetAccelerationStructureHandleNV-device-parameter",
@@ -11422,7 +12296,7 @@
         },
         {
           "vuid": "VUID-vkGetAccelerationStructureHandleNV-accelerationStructure-parameter",
-          "text": " <code>accelerationStructure</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkAccelerationStructureNV\">VkAccelerationStructureNV</a> handle"
+          "text": " <code>accelerationStructure</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkAccelerationStructureKHR\">VkAccelerationStructureKHR</a> handle"
         },
         {
           "vuid": "VUID-vkGetAccelerationStructureHandleNV-pData-parameter",
@@ -11438,6 +12312,38 @@
         }
       ]
     },
+    "vkGetAccelerationStructureDeviceAddressKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-vkGetAccelerationStructureDeviceAddressKHR-device-03504",
+          "text": " If <code>device</code> was created with multiple physical devices, then the <a href=\"#features-bufferDeviceAddressMultiDevice\">bufferDeviceAddressMultiDevice</a> feature <strong class=\"purple\">must</strong> be enabled"
+        },
+        {
+          "vuid": "VUID-vkGetAccelerationStructureDeviceAddressKHR-device-parameter",
+          "text": " <code>device</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDevice\">VkDevice</a> handle"
+        },
+        {
+          "vuid": "VUID-vkGetAccelerationStructureDeviceAddressKHR-pInfo-parameter",
+          "text": " <code>pInfo</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkAccelerationStructureDeviceAddressInfoKHR\">VkAccelerationStructureDeviceAddressInfoKHR</a> structure"
+        }
+      ]
+    },
+    "VkAccelerationStructureDeviceAddressInfoKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-VkAccelerationStructureDeviceAddressInfoKHR-sType-sType",
+          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureDeviceAddressInfoKHR-pNext-pNext",
+          "text": " <code>pNext</code> <strong class=\"purple\">must</strong> be <code>NULL</code>"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureDeviceAddressInfoKHR-accelerationStructure-parameter",
+          "text": " <code>accelerationStructure</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkAccelerationStructureKHR\">VkAccelerationStructureKHR</a> handle"
+        }
+      ]
+    },
     "vkCreateSampler": {
       "core": [
         {
@@ -11552,7 +12458,7 @@
       "(VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion)": [
         {
           "vuid": "VUID-VkSamplerCreateInfo-minFilter-01645",
-          "text": " If <a href=\"#samplers-YCbCr-conversion\">sampler {YCbCr} conversion</a> is enabled and <code>VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT</code> is not set for the format, <code>minFilter</code> and <code>magFilter</code> <strong class=\"purple\">must</strong> be equal to the sampler {YCbCr} conversion&#8217;s <code>chromaFilter</code>"
+          "text": " If <a href=\"#samplers-YCbCr-conversion\">sampler {YCbCr} conversion</a> is enabled and the <a href=\"#resources-sampler-ycbcr-conversion-format-features\">sampler {YCbCr} conversion&#8217;s features</a> do not support <code>VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT</code>, <code>minFilter</code> and <code>magFilter</code> <strong class=\"purple\">must</strong> be equal to the sampler {YCbCr} conversion&#8217;s <code>chromaFilter</code>"
         },
         {
           "vuid": "VUID-VkSamplerCreateInfo-addressModeU-01646",
@@ -11592,31 +12498,31 @@
       "(VK_EXT_fragment_density_map)": [
         {
           "vuid": "VUID-VkSamplerCreateInfo-flags-02574",
-          "text": " If <code>flags</code> includes <code>VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT</code>, then <code>minFilter</code> and <code>magFilter</code> <strong class=\"purple\">must</strong> be equal."
+          "text": " If <code>flags</code> includes <code>VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT</code>, then <code>minFilter</code> and <code>magFilter</code> <strong class=\"purple\">must</strong> be equal"
         },
         {
           "vuid": "VUID-VkSamplerCreateInfo-flags-02575",
-          "text": " If <code>flags</code> includes <code>VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT</code>, then <code>mipmapMode</code> <strong class=\"purple\">must</strong> be <code>VK_SAMPLER_MIPMAP_MODE_NEAREST</code>."
+          "text": " If <code>flags</code> includes <code>VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT</code>, then <code>mipmapMode</code> <strong class=\"purple\">must</strong> be <code>VK_SAMPLER_MIPMAP_MODE_NEAREST</code>"
         },
         {
           "vuid": "VUID-VkSamplerCreateInfo-flags-02576",
-          "text": " If <code>flags</code> includes <code>VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT</code>, then <code>minLod</code> and <code>maxLod</code> <strong class=\"purple\">must</strong> be zero."
+          "text": " If <code>flags</code> includes <code>VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT</code>, then <code>minLod</code> and <code>maxLod</code> <strong class=\"purple\">must</strong> be zero"
         },
         {
           "vuid": "VUID-VkSamplerCreateInfo-flags-02577",
-          "text": " If <code>flags</code> includes <code>VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT</code>, then <code>addressModeU</code> and <code>addressModeV</code> <strong class=\"purple\">must</strong> each be either <code>VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE</code> or <code>VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER</code>."
+          "text": " If <code>flags</code> includes <code>VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT</code>, then <code>addressModeU</code> and <code>addressModeV</code> <strong class=\"purple\">must</strong> each be either <code>VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE</code> or <code>VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER</code>"
         },
         {
           "vuid": "VUID-VkSamplerCreateInfo-flags-02578",
-          "text": " If <code>flags</code> includes <code>VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT</code>, then <code>anisotropyEnable</code> <strong class=\"purple\">must</strong> be <code>VK_FALSE</code>."
+          "text": " If <code>flags</code> includes <code>VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT</code>, then <code>anisotropyEnable</code> <strong class=\"purple\">must</strong> be <code>VK_FALSE</code>"
         },
         {
           "vuid": "VUID-VkSamplerCreateInfo-flags-02579",
-          "text": " If <code>flags</code> includes <code>VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT</code>, then <code>compareEnable</code> <strong class=\"purple\">must</strong> be <code>VK_FALSE</code>."
+          "text": " If <code>flags</code> includes <code>VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT</code>, then <code>compareEnable</code> <strong class=\"purple\">must</strong> be <code>VK_FALSE</code>"
         },
         {
           "vuid": "VUID-VkSamplerCreateInfo-flags-02580",
-          "text": " If <code>flags</code> includes <code>VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT</code>, then <code>unnormalizedCoordinates</code> <strong class=\"purple\">must</strong> be <code>VK_FALSE</code>."
+          "text": " If <code>flags</code> includes <code>VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT</code>, then <code>unnormalizedCoordinates</code> <strong class=\"purple\">must</strong> be <code>VK_FALSE</code>"
         }
       ]
     },
@@ -11705,30 +12611,30 @@
         {
           "vuid": "VUID-VkSamplerYcbcrConversionCreateInfo-format-01649",
           "text": " <code>format</code> <strong class=\"purple\">must</strong> not be <code>VK_FORMAT_UNDEFINED</code>"
+        },
+        {
+          "vuid": "VUID-VkSamplerYcbcrConversionCreateInfo-format-01653",
+          "text": " If an external format conversion is not being created, <code>format</code> <strong class=\"purple\">must</strong> represent unsigned normalized values (i.e. the format must be a <code>UNORM</code> format)"
         }
       ],
       "(VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion)+(VK_ANDROID_external_memory_android_hardware_buffer)": [
         {
           "vuid": "VUID-VkSamplerYcbcrConversionCreateInfo-format-01904",
-          "text": " If an external format conversion is being created, <code>format</code> <strong class=\"purple\">must</strong> be <code>VK_FORMAT_UNDEFINED</code>, otherwise it <strong class=\"purple\">must</strong> not be <code>VK_FORMAT_UNDEFINED</code>."
+          "text": " If an external format conversion is being created, <code>format</code> <strong class=\"purple\">must</strong> be <code>VK_FORMAT_UNDEFINED</code>, otherwise it <strong class=\"purple\">must</strong> not be <code>VK_FORMAT_UNDEFINED</code>"
         }
       ],
       "(VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion)": [
         {
           "vuid": "VUID-VkSamplerYcbcrConversionCreateInfo-format-01650",
-          "text": " <code>format</code> <strong class=\"purple\">must</strong> support <code>VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT</code> or <code>VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT</code>"
+          "text": " The <a href=\"#resources-sampler-ycbcr-conversion-format-features\">sampler {YCbCr} conversion&#8217;s features</a> <strong class=\"purple\">must</strong> support <code>VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT</code> or <code>VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT</code>"
         },
         {
           "vuid": "VUID-VkSamplerYcbcrConversionCreateInfo-xChromaOffset-01651",
-          "text": " If the format does not support <code>VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT</code>, <code>xChromaOffset</code> and <code>yChromaOffset</code> <strong class=\"purple\">must</strong> not be <code>VK_CHROMA_LOCATION_COSITED_EVEN</code>"
+          "text": " If the <a href=\"#resources-sampler-ycbcr-conversion-format-features\">sampler {YCbCr} conversion&#8217;s features</a> do not support <code>VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT</code>, <code>xChromaOffset</code> and <code>yChromaOffset</code> <strong class=\"purple\">must</strong> not be <code>VK_CHROMA_LOCATION_COSITED_EVEN</code>"
         },
         {
           "vuid": "VUID-VkSamplerYcbcrConversionCreateInfo-xChromaOffset-01652",
-          "text": " If the format does not support <code>VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT</code>, <code>xChromaOffset</code> and <code>yChromaOffset</code> <strong class=\"purple\">must</strong> not be <code>VK_CHROMA_LOCATION_MIDPOINT</code>"
-        },
-        {
-          "vuid": "VUID-VkSamplerYcbcrConversionCreateInfo-format-01653",
-          "text": " <code>format</code> <strong class=\"purple\">must</strong> represent unsigned normalized values (i.e. the format must be a <code>UNORM</code> format)"
+          "text": " If the <a href=\"#resources-sampler-ycbcr-conversion-format-features\">sampler {YCbCr} conversion&#8217;s features</a> do not support <code>VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT</code>, <code>xChromaOffset</code> and <code>yChromaOffset</code> <strong class=\"purple\">must</strong> not be <code>VK_CHROMA_LOCATION_MIDPOINT</code>"
         },
         {
           "vuid": "VUID-VkSamplerYcbcrConversionCreateInfo-components-02581",
@@ -11756,15 +12662,15 @@
         },
         {
           "vuid": "VUID-VkSamplerYcbcrConversionCreateInfo-ycbcrRange-02748",
-          "text": " If <code>ycbcrRange</code> is <code>VK_SAMPLER_YCBCR_RANGE_ITU_NARROW</code> then the R, G and B channels obtained by applying the <code>component</code> swizzle to <code>format</code> <strong class=\"purple\">must</strong> each have a bit-depth greater than or equal to 8."
+          "text": " If <code>ycbcrRange</code> is <code>VK_SAMPLER_YCBCR_RANGE_ITU_NARROW</code> then the R, G and B channels obtained by applying the <code>component</code> swizzle to <code>format</code> <strong class=\"purple\">must</strong> each have a bit-depth greater than or equal to 8"
         },
         {
           "vuid": "VUID-VkSamplerYcbcrConversionCreateInfo-forceExplicitReconstruction-01656",
-          "text": " If the format does not support <code>VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT</code> <code>forceExplicitReconstruction</code> <strong class=\"purple\">must</strong> be <code>VK_FALSE</code>"
+          "text": " If the <a href=\"#resources-sampler-ycbcr-conversion-format-features\">sampler {YCbCr} conversion&#8217;s features</a> do not support <code>VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT</code> <code>forceExplicitReconstruction</code> <strong class=\"purple\">must</strong> be <code>VK_FALSE</code>"
         },
         {
           "vuid": "VUID-VkSamplerYcbcrConversionCreateInfo-chromaFilter-01657",
-          "text": " If the format does not support <code>VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT</code>, <code>chromaFilter</code> <strong class=\"purple\">must</strong> not be <code>VK_FILTER_LINEAR</code>"
+          "text": " If the <a href=\"#resources-sampler-ycbcr-conversion-format-features\">sampler {YCbCr} conversion&#8217;s features</a> do not support <code>VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT</code>, <code>chromaFilter</code> <strong class=\"purple\">must</strong> not be <code>VK_FILTER_LINEAR</code>"
         },
         {
           "vuid": "VUID-VkSamplerYcbcrConversionCreateInfo-sType-sType",
@@ -12333,10 +13239,10 @@
           "text": " <code>pSetLayouts</code> <strong class=\"purple\">must</strong> not contain more than one descriptor set layout that was created with <code>VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR</code> set"
         }
       ],
-      "(VK_NV_ray_tracing)": [
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)": [
         {
           "vuid": "VUID-VkPipelineLayoutCreateInfo-descriptorType-02381",
-          "text": " The total number of bindings with a <code>descriptorType</code> of <code>VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV</code> accessible across all shader stages and across all elements of <code>pSetLayouts</code> <strong class=\"purple\">must</strong> be less than or equal to <code>VkPhysicalDeviceRayTracingPropertiesNV</code>::<code>maxDescriptorSetAccelerationStructures</code>"
+          "text": " The total number of bindings with a <code>descriptorType</code> of <code>VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR</code> accessible across all shader stages and across all elements of <code>pSetLayouts</code> <strong class=\"purple\">must</strong> be less than or equal to <code>VkPhysicalDeviceRayTracingPropertiesKHR</code>::<code>maxDescriptorSetAccelerationStructures</code>"
         }
       ]
     },
@@ -12596,7 +13502,7 @@
         },
         {
           "vuid": "VUID-VkDescriptorSetVariableDescriptorCountAllocateInfo-pSetLayouts-03046",
-          "text": " If <a href=\"#VkDescriptorSetAllocateInfo\">VkDescriptorSetAllocateInfo</a>::<code>pSetLayouts</code>[i] has a variable descriptor count binding, then <code>pDescriptorCounts</code>[i] <strong class=\"purple\">must</strong> be less than or equal to the descriptor count specified for that binding when the descriptor set layout was created."
+          "text": " If <a href=\"#VkDescriptorSetAllocateInfo\">VkDescriptorSetAllocateInfo</a>::<code>pSetLayouts</code>[i] has a variable descriptor count binding, then <code>pDescriptorCounts</code>[i] <strong class=\"purple\">must</strong> be less than or equal to the descriptor count specified for that binding when the descriptor set layout was created"
         },
         {
           "vuid": "VUID-VkDescriptorSetVariableDescriptorCountAllocateInfo-sType-sType",
@@ -12676,13 +13582,13 @@
       "!(VK_VERSION_1_2,VK_EXT_descriptor_indexing)": [
         {
           "vuid": "VUID-vkUpdateDescriptorSets-dstSet-00314",
-          "text": " The <code>dstSet</code> member of each element of <code>pDescriptorWrites</code> or <code>pDescriptorCopies</code> <strong class=\"purple\">must</strong> not be used by any command that was recorded to a command buffer which is in the <a href=\"#commandbuffers-lifecycle\">pending state</a>."
+          "text": " The <code>dstSet</code> member of each element of <code>pDescriptorWrites</code> or <code>pDescriptorCopies</code> <strong class=\"purple\">must</strong> not be used by any command that was recorded to a command buffer which is in the <a href=\"#commandbuffers-lifecycle\">pending state</a>"
         }
       ],
       "(VK_VERSION_1_2,VK_EXT_descriptor_indexing)": [
         {
           "vuid": "VUID-vkUpdateDescriptorSets-None-03047",
-          "text": " Descriptor bindings updated by this command which were created without the <code>VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT</code> or <code>VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT</code> bits set <strong class=\"purple\">must</strong> not be used by any command that was recorded to a command buffer which is in the <a href=\"#commandbuffers-lifecycle\">pending state</a>."
+          "text": " Descriptor bindings updated by this command which were created without the <code>VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT</code> or <code>VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT</code> bits set <strong class=\"purple\">must</strong> not be used by any command that was recorded to a command buffer which is in the <a href=\"#commandbuffers-lifecycle\">pending state</a>"
         }
       ],
       "core": [
@@ -12712,11 +13618,11 @@
         },
         {
           "vuid": "VUID-VkWriteDescriptorSet-descriptorCount-00317",
-          "text": " All consecutive bindings updated via a single <code>VkWriteDescriptorSet</code> structure, except those with a <code>descriptorCount</code> of zero, <strong class=\"purple\">must</strong> have identical <code>descriptorType</code> and <code>stageFlags</code>."
+          "text": " All consecutive bindings updated via a single <code>VkWriteDescriptorSet</code> structure, except those with a <code>descriptorCount</code> of zero, <strong class=\"purple\">must</strong> have identical <code>descriptorType</code> and <code>stageFlags</code>"
         },
         {
           "vuid": "VUID-VkWriteDescriptorSet-descriptorCount-00318",
-          "text": " All consecutive bindings updated via a single <code>VkWriteDescriptorSet</code> structure, except those with a <code>descriptorCount</code> of zero, <strong class=\"purple\">must</strong> all either use immutable samplers or <strong class=\"purple\">must</strong> all not use immutable samplers."
+          "text": " All consecutive bindings updated via a single <code>VkWriteDescriptorSet</code> structure, except those with a <code>descriptorCount</code> of zero, <strong class=\"purple\">must</strong> all either use immutable samplers or <strong class=\"purple\">must</strong> all not use immutable samplers"
         },
         {
           "vuid": "VUID-VkWriteDescriptorSet-descriptorType-00319",
@@ -12751,18 +13657,6 @@
           "text": " If <code>descriptorType</code> is <code>VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER</code>, <code>VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE</code>, <code>VK_DESCRIPTOR_TYPE_STORAGE_IMAGE</code>, or <code>VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT</code>, the <code>imageView</code> and <code>imageLayout</code> members of each element of <code>pImageInfo</code> <strong class=\"purple\">must</strong> be a valid <code>VkImageView</code> and <a href=\"#VkImageLayout\">VkImageLayout</a>, respectively"
         },
         {
-          "vuid": "VUID-VkWriteDescriptorSet-descriptorType-01946",
-          "text": " If <code>descriptorType</code> is <code>VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE</code>, then the <code>imageView</code> member of each <code>pImageInfo</code> element <strong class=\"purple\">must</strong> have been created without a <code>VkSamplerYcbcrConversionInfo</code> structure in its <code>pNext</code> chain"
-        },
-        {
-          "vuid": "VUID-VkWriteDescriptorSet-descriptorType-02738",
-          "text": " If <code>descriptorType</code> is <code>VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER</code>, and if any element of <code>pImageInfo</code> has a <code>imageView</code> member that was created with a <code>VkSamplerYcbcrConversionInfo</code> structure in its <code>pNext</code> chain, then <code>dstSet</code> <strong class=\"purple\">must</strong> have been allocated with a layout that included immutable samplers for <code>dstBinding</code>, and the corresponding immutable sampler <strong class=\"purple\">must</strong> have been created with an <em>identically defined</em> <code>VkSamplerYcbcrConversionInfo</code> object"
-        },
-        {
-          "vuid": "VUID-VkWriteDescriptorSet-descriptorType-01948",
-          "text": " If <code>descriptorType</code> is <code>VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER</code>, and <code>dstSet</code> was allocated with a layout that included immutable samplers for <code>dstBinding</code>, then the <code>imageView</code> member of each element of <code>pImageInfo</code> which corresponds to an immutable sampler that enables <a href=\"#samplers-YCbCr-conversion\">sampler {YCbCr} conversion</a> <strong class=\"purple\">must</strong> have been created with a <code>VkSamplerYcbcrConversionInfo</code> structure in its <code>pNext</code> chain with an <em>identically defined</em> <code>VkSamplerYcbcrConversionInfo</code> to the corresponding immutable sampler"
-        },
-        {
           "vuid": "VUID-VkWriteDescriptorSet-descriptorType-01402",
           "text": " If <code>descriptorType</code> is <code>VK_DESCRIPTOR_TYPE_STORAGE_IMAGE</code>, for each descriptor that will be accessed via load or store operations the <code>imageLayout</code> member for corresponding elements of <code>pImageInfo</code> <strong class=\"purple\">must</strong> be <code>VK_IMAGE_LAYOUT_GENERAL</code>"
         },
@@ -12832,7 +13726,7 @@
         },
         {
           "vuid": "VUID-VkWriteDescriptorSet-pNext-pNext",
-          "text": " Each <code>pNext</code> member of any structure (including this one) in the <code>pNext</code> chain <strong class=\"purple\">must</strong> be either <code>NULL</code> or a pointer to a valid instance of <a href=\"#VkWriteDescriptorSetAccelerationStructureNV\">VkWriteDescriptorSetAccelerationStructureNV</a> or <a href=\"#VkWriteDescriptorSetInlineUniformBlockEXT\">VkWriteDescriptorSetInlineUniformBlockEXT</a>"
+          "text": " Each <code>pNext</code> member of any structure (including this one) in the <code>pNext</code> chain <strong class=\"purple\">must</strong> be either <code>NULL</code> or a pointer to a valid instance of <a href=\"#VkWriteDescriptorSetAccelerationStructureKHR\">VkWriteDescriptorSetAccelerationStructureKHR</a> or <a href=\"#VkWriteDescriptorSetInlineUniformBlockEXT\">VkWriteDescriptorSetInlineUniformBlockEXT</a>"
         },
         {
           "vuid": "VUID-VkWriteDescriptorSet-sType-unique",
@@ -12865,16 +13759,30 @@
           "text": " If <code>descriptorType</code> is <code>VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT</code>, the <code>pNext</code> chain <strong class=\"purple\">must</strong> include a <a href=\"#VkWriteDescriptorSetInlineUniformBlockEXT\">VkWriteDescriptorSetInlineUniformBlockEXT</a> structure whose <code>dataSize</code> member equals <code>descriptorCount</code>"
         }
       ],
-      "(VK_NV_ray_tracing)": [
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)": [
         {
           "vuid": "VUID-VkWriteDescriptorSet-descriptorType-02382",
-          "text": " If <code>descriptorType</code> is <code>VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV</code>, the <code>pNext</code> chain <strong class=\"purple\">must</strong> include a <a href=\"#VkWriteDescriptorSetAccelerationStructureNV\">VkWriteDescriptorSetAccelerationStructureNV</a> structure whose <code>accelerationStructureCount</code> member equals <code>descriptorCount</code>"
+          "text": " If <code>descriptorType</code> is <code>VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR</code>, the <code>pNext</code> chain <strong class=\"purple\">must</strong> include a <a href=\"#VkWriteDescriptorSetAccelerationStructureKHR\">VkWriteDescriptorSetAccelerationStructureKHR</a> structure whose <code>accelerationStructureCount</code> member equals <code>descriptorCount</code>"
+        }
+      ],
+      "(VK_VULKAN_1_1,VK_KHR_sampler_ycbcr_conversion)": [
+        {
+          "vuid": "VUID-VkWriteDescriptorSet-descriptorType-01946",
+          "text": " If <code>descriptorType</code> is <code>VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE</code>, then the <code>imageView</code> member of each <code>pImageInfo</code> element <strong class=\"purple\">must</strong> have been created without a <code>VkSamplerYcbcrConversionInfo</code> structure in its <code>pNext</code> chain"
+        },
+        {
+          "vuid": "VUID-VkWriteDescriptorSet-descriptorType-02738",
+          "text": " If <code>descriptorType</code> is <code>VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER</code>, and if any element of <code>pImageInfo</code> has a <code>imageView</code> member that was created with a <code>VkSamplerYcbcrConversionInfo</code> structure in its <code>pNext</code> chain, then <code>dstSet</code> <strong class=\"purple\">must</strong> have been allocated with a layout that included immutable samplers for <code>dstBinding</code>, and the corresponding immutable sampler <strong class=\"purple\">must</strong> have been created with an <em>identically defined</em> <code>VkSamplerYcbcrConversionInfo</code> object"
+        },
+        {
+          "vuid": "VUID-VkWriteDescriptorSet-descriptorType-01948",
+          "text": " If <code>descriptorType</code> is <code>VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER</code>, and <code>dstSet</code> was allocated with a layout that included immutable samplers for <code>dstBinding</code>, then the <code>imageView</code> member of each element of <code>pImageInfo</code> which corresponds to an immutable sampler that enables <a href=\"#samplers-YCbCr-conversion\">sampler {YCbCr} conversion</a> <strong class=\"purple\">must</strong> have been created with a <code>VkSamplerYcbcrConversionInfo</code> structure in its <code>pNext</code> chain with an <em>identically defined</em> <code>VkSamplerYcbcrConversionInfo</code> to the corresponding immutable sampler"
         }
       ],
       "(VK_VERSION_1_2,VK_EXT_descriptor_indexing)": [
         {
           "vuid": "VUID-VkWriteDescriptorSet-descriptorCount-03048",
-          "text": " All consecutive bindings updated via a single <code>VkWriteDescriptorSet</code> structure, except those with a <code>descriptorCount</code> of zero, <strong class=\"purple\">must</strong> have identical <a href=\"#VkDescriptorBindingFlagBits\">VkDescriptorBindingFlagBits</a>."
+          "text": " All consecutive bindings updated via a single <code>VkWriteDescriptorSet</code> structure, except those with a <code>descriptorCount</code> of zero, <strong class=\"purple\">must</strong> have identical <a href=\"#VkDescriptorBindingFlagBits\">VkDescriptorBindingFlagBits</a>"
         }
       ]
     },
@@ -12908,7 +13816,7 @@
       "core": [
         {
           "vuid": "VUID-VkDescriptorImageInfo-imageView-01976",
-          "text": " If <code>imageView</code> is created from a depth/stencil image, the <code>aspectMask</code> used to create the <code>imageView</code> <strong class=\"purple\">must</strong> include either <code>VK_IMAGE_ASPECT_DEPTH_BIT</code> or <code>VK_IMAGE_ASPECT_STENCIL_BIT</code> but not both."
+          "text": " If <code>imageView</code> is created from a depth/stencil image, the <code>aspectMask</code> used to create the <code>imageView</code> <strong class=\"purple\">must</strong> include either <code>VK_IMAGE_ASPECT_DEPTH_BIT</code> or <code>VK_IMAGE_ASPECT_STENCIL_BIT</code> but not both"
         },
         {
           "vuid": "VUID-VkDescriptorImageInfo-imageLayout-00344",
@@ -12946,26 +13854,26 @@
         }
       ]
     },
-    "VkWriteDescriptorSetAccelerationStructureNV": {
-      "(VK_NV_ray_tracing)": [
+    "VkWriteDescriptorSetAccelerationStructureKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)": [
         {
-          "vuid": "VUID-VkWriteDescriptorSetAccelerationStructureNV-accelerationStructureCount-02236",
+          "vuid": "VUID-VkWriteDescriptorSetAccelerationStructureKHR-accelerationStructureCount-02236",
           "text": " <code>accelerationStructureCount</code> <strong class=\"purple\">must</strong> be equal to <code>descriptorCount</code> in the extended structure"
         },
         {
-          "vuid": "VUID-VkWriteDescriptorSetAccelerationStructureNV-pAccelerationStructures-02764",
-          "text": " Each acceleration structure in <code>pAccelerationStructures</code> must have been created with <code>VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV</code>"
+          "vuid": "VUID-VkWriteDescriptorSetAccelerationStructureKHR-pAccelerationStructures-02764",
+          "text": " Each acceleration structure in <code>pAccelerationStructures</code> <strong class=\"purple\">must</strong> have been created with <code>VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR</code>"
         },
         {
-          "vuid": "VUID-VkWriteDescriptorSetAccelerationStructureNV-sType-sType",
-          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_NV</code>"
+          "vuid": "VUID-VkWriteDescriptorSetAccelerationStructureKHR-sType-sType",
+          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR</code>"
         },
         {
-          "vuid": "VUID-VkWriteDescriptorSetAccelerationStructureNV-pAccelerationStructures-parameter",
-          "text": " <code>pAccelerationStructures</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>accelerationStructureCount</code> valid <a href=\"#VkAccelerationStructureNV\">VkAccelerationStructureNV</a> handles"
+          "vuid": "VUID-VkWriteDescriptorSetAccelerationStructureKHR-pAccelerationStructures-parameter",
+          "text": " <code>pAccelerationStructures</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>accelerationStructureCount</code> valid <a href=\"#VkAccelerationStructureKHR\">VkAccelerationStructureKHR</a> handles"
         },
         {
-          "vuid": "VUID-VkWriteDescriptorSetAccelerationStructureNV-accelerationStructureCount-arraylength",
+          "vuid": "VUID-VkWriteDescriptorSetAccelerationStructureKHR-accelerationStructureCount-arraylength",
           "text": " <code>accelerationStructureCount</code> <strong class=\"purple\">must</strong> be greater than <code>0</code>"
         }
       ]
@@ -13128,7 +14036,7 @@
       "(VK_VERSION_1_1,VK_KHR_descriptor_update_template)": [
         {
           "vuid": "VUID-VkDescriptorUpdateTemplateEntry-dstBinding-00354",
-          "text": " <code>dstBinding</code> <strong class=\"purple\">must</strong> be a valid binding in the descriptor set layout implicitly specified when using a descriptor update template to update descriptors."
+          "text": " <code>dstBinding</code> <strong class=\"purple\">must</strong> be a valid binding in the descriptor set layout implicitly specified when using a descriptor update template to update descriptors"
         },
         {
           "vuid": "VUID-VkDescriptorUpdateTemplateEntry-dstArrayElement-00355",
@@ -13214,7 +14122,7 @@
         },
         {
           "vuid": "VUID-vkCmdBindDescriptorSets-firstSet-00360",
-          "text": " The sum of <code>firstSet</code> and <code>descriptorSetCount</code> <strong class=\"purple\">must</strong> be less than or equal to <code>VkPipelineLayoutCreateInfo</code>::<code>setLayoutCount</code> provided when <code>layout</code> was created"
+          "text": " The sum of <code>firstSet</code> and <code>descriptorSetCount</code> <strong class=\"purple\">must</strong> be less than or equal to <a href=\"#VkPipelineLayoutCreateInfo\">VkPipelineLayoutCreateInfo</a>::<code>setLayoutCount</code> provided when <code>layout</code> was created"
         },
         {
           "vuid": "VUID-vkCmdBindDescriptorSets-pipelineBindPoint-00361",
@@ -13278,7 +14186,7 @@
         },
         {
           "vuid": "VUID-vkCmdPushDescriptorSetKHR-set-00364",
-          "text": " <code>set</code> <strong class=\"purple\">must</strong> be less than <code>VkPipelineLayoutCreateInfo</code>::<code>setLayoutCount</code> provided when <code>layout</code> was created"
+          "text": " <code>set</code> <strong class=\"purple\">must</strong> be less than <a href=\"#VkPipelineLayoutCreateInfo\">VkPipelineLayoutCreateInfo</a>::<code>setLayoutCount</code> provided when <code>layout</code> was created"
         },
         {
           "vuid": "VUID-vkCmdPushDescriptorSetKHR-set-00365",
@@ -13522,7 +14430,7 @@
         },
         {
           "vuid": "VUID-VkQueryPoolCreateInfo-pNext-pNext",
-          "text": " Each <code>pNext</code> member of any structure (including this one) in the <code>pNext</code> chain <strong class=\"purple\">must</strong> be either <code>NULL</code> or a pointer to a valid instance of <a href=\"#VkQueryPoolCreateInfoINTEL\">VkQueryPoolCreateInfoINTEL</a> or <a href=\"#VkQueryPoolPerformanceCreateInfoKHR\">VkQueryPoolPerformanceCreateInfoKHR</a>"
+          "text": " Each <code>pNext</code> member of any structure (including this one) in the <code>pNext</code> chain <strong class=\"purple\">must</strong> be either <code>NULL</code> or a pointer to a valid instance of <a href=\"#VkQueryPoolPerformanceCreateInfoKHR\">VkQueryPoolPerformanceCreateInfoKHR</a> or <a href=\"#VkQueryPoolPerformanceQueryCreateInfoINTEL\">VkQueryPoolPerformanceQueryCreateInfoINTEL</a>"
         },
         {
           "vuid": "VUID-VkQueryPoolCreateInfo-sType-unique",
@@ -13802,7 +14710,7 @@
         },
         {
           "vuid": "VUID-vkCmdBeginQuery-None-02863",
-          "text": " If <code>queryPool</code> was created with a <code>queryType</code> of <code>VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR</code>, this command <strong class=\"purple\">must</strong> not be recorded in a command buffer that, either directly or through secondary command buffers, also contains a <code>vkCmdResetQueryPool</code> command affecting the same query."
+          "text": " If <code>queryPool</code> was created with a <code>queryType</code> of <code>VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR</code>, this command <strong class=\"purple\">must</strong> not be recorded in a command buffer that, either directly or through secondary command buffers, also contains a <code>vkCmdResetQueryPool</code> command affecting the same query"
         }
       ]
     },
@@ -13912,7 +14820,7 @@
         },
         {
           "vuid": "VUID-vkCmdBeginQueryIndexedEXT-None-02863",
-          "text": " If <code>queryPool</code> was created with a <code>queryType</code> of <code>VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR</code>, this command <strong class=\"purple\">must</strong> not be recorded in a command buffer that, either directly or through secondary command buffers, also contains a <code>vkCmdResetQueryPool</code> command affecting the same query."
+          "text": " If <code>queryPool</code> was created with a <code>queryType</code> of <code>VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR</code>, this command <strong class=\"purple\">must</strong> not be recorded in a command buffer that, either directly or through secondary command buffers, also contains a <code>vkCmdResetQueryPool</code> command affecting the same query"
         }
       ]
     },
@@ -14342,18 +15250,18 @@
       "(VK_INTEL_performance_query)+(VK_INTEL_performance_query)": [
         {
           "vuid": "VUID-VkPerformanceValueDataINTEL-valueString-parameter",
-          "text": " <code>valueString</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid"
+          "text": " <code>valueString</code> <strong class=\"purple\">must</strong> be a null-terminated UTF-8 string"
         }
       ]
     },
-    "VkQueryPoolCreateInfoINTEL": {
+    "VkQueryPoolPerformanceQueryCreateInfoINTEL": {
       "(VK_INTEL_performance_query)+(VK_INTEL_performance_query)": [
         {
-          "vuid": "VUID-VkQueryPoolCreateInfoINTEL-sType-sType",
-          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO_INTEL</code>"
+          "vuid": "VUID-VkQueryPoolPerformanceQueryCreateInfoINTEL-sType-sType",
+          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_QUERY_CREATE_INFO_INTEL</code>"
         },
         {
-          "vuid": "VUID-VkQueryPoolCreateInfoINTEL-performanceCountersSampling-parameter",
+          "vuid": "VUID-VkQueryPoolPerformanceQueryCreateInfoINTEL-performanceCountersSampling-parameter",
           "text": " <code>performanceCountersSampling</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkQueryPoolSamplingModeINTEL\">VkQueryPoolSamplingModeINTEL</a> value"
         }
       ]
@@ -14414,7 +15322,7 @@
       "(VK_INTEL_performance_query)+(VK_INTEL_performance_query)": [
         {
           "vuid": "VUID-VkPerformanceStreamMarkerInfoINTEL-marker-02735",
-          "text": " The value written by the application into <code>marker</code> <strong class=\"purple\">must</strong> only used the valid bits as reported by <a href=\"#vkGetPerformanceParameterINTEL\">vkGetPerformanceParameterINTEL</a> with the <code>VK_PERFORMANCE_PARAMETER_TYPE_STREAM_MARKER_VALID_BITS_INTEL</code>."
+          "text": " The value written by the application into <code>marker</code> <strong class=\"purple\">must</strong> only used the valid bits as reported by <a href=\"#vkGetPerformanceParameterINTEL\">vkGetPerformanceParameterINTEL</a> with the <code>VK_PERFORMANCE_PARAMETER_TYPE_STREAM_MARKER_VALID_BITS_INTEL</code>"
         },
         {
           "vuid": "VUID-VkPerformanceStreamMarkerInfoINTEL-sType-sType",
@@ -14430,7 +15338,7 @@
       "(VK_INTEL_performance_query)+(VK_INTEL_performance_query)": [
         {
           "vuid": "VUID-vkCmdSetPerformanceOverrideINTEL-pOverrideInfo-02736",
-          "text": " <code>pOverrideInfo</code> <strong class=\"purple\">must</strong> not be used with a <a href=\"#VkPerformanceOverrideTypeINTEL\">VkPerformanceOverrideTypeINTEL</a> that is not reported available by <code>vkGetPerformanceParameterINTEL</code>."
+          "text": " <code>pOverrideInfo</code> <strong class=\"purple\">must</strong> not be used with a <a href=\"#VkPerformanceOverrideTypeINTEL\">VkPerformanceOverrideTypeINTEL</a> that is not reported available by <code>vkGetPerformanceParameterINTEL</code>"
         },
         {
           "vuid": "VUID-vkCmdSetPerformanceOverrideINTEL-commandBuffer-parameter",
@@ -14518,7 +15426,7 @@
       "(VK_INTEL_performance_query)+(VK_INTEL_performance_query)": [
         {
           "vuid": "VUID-vkReleasePerformanceConfigurationINTEL-configuration-02737",
-          "text": " <code>configuration</code> <strong class=\"purple\">must</strong> not be released before all command buffers submitted while the configuration was set are in <a href=\"#commandbuffers-lifecycle\">pending state</a>."
+          "text": " <code>configuration</code> <strong class=\"purple\">must</strong> not be released before all command buffers submitted while the configuration was set are in <a href=\"#commandbuffers-lifecycle\">pending state</a>"
         },
         {
           "vuid": "VUID-vkReleasePerformanceConfigurationINTEL-device-parameter",
@@ -14538,7 +15446,7 @@
       "(VK_VERSION_1_1,VK_KHR_maintenance1)": [
         {
           "vuid": "VUID-vkCmdClearColorImage-image-01993",
-          "text": " The <a href=\"#resources-image-format-features\">format features</a> of <code>image</code> <strong class=\"purple\">must</strong> contain <code>VK_FORMAT_FEATURE_TRANSFER_DST_BIT</code>."
+          "text": " The <a href=\"#resources-image-format-features\">format features</a> of <code>image</code> <strong class=\"purple\">must</strong> contain <code>VK_FORMAT_FEATURE_TRANSFER_DST_BIT</code>"
         }
       ],
       "core": [
@@ -14652,7 +15560,7 @@
       "(VK_VERSION_1_1,VK_KHR_maintenance1)": [
         {
           "vuid": "VUID-vkCmdClearDepthStencilImage-image-01994",
-          "text": " The <a href=\"#resources-image-format-features\">format features</a> of <code>image</code> <strong class=\"purple\">must</strong> contain <code>VK_FORMAT_FEATURE_TRANSFER_DST_BIT</code>."
+          "text": " The <a href=\"#resources-image-format-features\">format features</a> of <code>image</code> <strong class=\"purple\">must</strong> contain <code>VK_FORMAT_FEATURE_TRANSFER_DST_BIT</code>"
         }
       ],
       "!(VK_VERSION_1_2,VK_EXT_separate_stencil_usage)": [
@@ -14776,7 +15684,7 @@
       "core": [
         {
           "vuid": "VUID-vkCmdClearAttachments-aspectMask-02501",
-          "text": " If the <code>aspectMask</code> member of any element of <code>pAttachments</code> contains <code>VK_IMAGE_ASPECT_COLOR_BIT</code>, then the <code>colorAttachment</code> member of that element <strong class=\"purple\">must</strong> either refer to a color attachment which is <code>VK_ATTACHMENT_UNUSED</code>, or <strong class=\"purple\">must</strong> be a valid color attachment."
+          "text": " If the <code>aspectMask</code> member of any element of <code>pAttachments</code> contains <code>VK_IMAGE_ASPECT_COLOR_BIT</code>, then the <code>colorAttachment</code> member of that element <strong class=\"purple\">must</strong> either refer to a color attachment which is <code>VK_ATTACHMENT_UNUSED</code>, or <strong class=\"purple\">must</strong> be a valid color attachment"
         },
         {
           "vuid": "VUID-vkCmdClearAttachments-aspectMask-02502",
@@ -14842,17 +15750,17 @@
       "(VK_VERSION_1_1)": [
         {
           "vuid": "VUID-vkCmdClearAttachments-commandBuffer-02504",
-          "text": " If <code>commandBuffer</code> is an unprotected command buffer, then each attachment to be cleared <strong class=\"purple\">must</strong> not be a protected image."
+          "text": " If <code>commandBuffer</code> is an unprotected command buffer, then each attachment to be cleared <strong class=\"purple\">must</strong> not be a protected image"
         },
         {
           "vuid": "VUID-vkCmdClearAttachments-commandBuffer-02505",
-          "text": " If <code>commandBuffer</code> is a protected command buffer, then each attachment to be cleared <strong class=\"purple\">must</strong> not be an unprotected image."
+          "text": " If <code>commandBuffer</code> is a protected command buffer, then each attachment to be cleared <strong class=\"purple\">must</strong> not be an unprotected image"
         }
       ],
       "(VK_VERSION_1_1,VK_KHR_multiview)": [
         {
           "vuid": "VUID-vkCmdClearAttachments-baseArrayLayer-00018",
-          "text": " If the render pass instance this is recorded in uses multiview, then <code>baseArrayLayer</code> <strong class=\"purple\">must</strong> be zero and <code>layerCount</code> <strong class=\"purple\">must</strong> be one."
+          "text": " If the render pass instance this is recorded in uses multiview, then <code>baseArrayLayer</code> <strong class=\"purple\">must</strong> be zero and <code>layerCount</code> <strong class=\"purple\">must</strong> be one"
         }
       ]
     },
@@ -14882,7 +15790,7 @@
       "(VK_EXT_image_drm_format_modifier)": [
         {
           "vuid": "VUID-VkClearAttachment-aspectMask-02246",
-          "text": " <code>aspectMask</code> <strong class=\"purple\">must</strong> not include <code>VK_IMAGE_ASPECT_MEMORY_PLANE_i_BIT_EXT</code> for any index <code>i</code>."
+          "text": " <code>aspectMask</code> <strong class=\"purple\">must</strong> not include <code>VK_IMAGE_ASPECT_MEMORY_PLANE_i_BIT_EXT</code> for any index <code>i</code>"
         }
       ]
     },
@@ -15147,14 +16055,6 @@
     "vkCmdCopyImage": {
       "core": [
         {
-          "vuid": "VUID-vkCmdCopyImage-pRegions-00122",
-          "text": " The source region specified by each element of <code>pRegions</code> <strong class=\"purple\">must</strong> be a region that is contained within <code>srcImage</code>"
-        },
-        {
-          "vuid": "VUID-vkCmdCopyImage-pRegions-00123",
-          "text": " The destination region specified by each element of <code>pRegions</code> <strong class=\"purple\">must</strong> be a region that is contained within <code>dstImage</code>"
-        },
-        {
           "vuid": "VUID-vkCmdCopyImage-pRegions-00124",
           "text": " The union of all source regions, and the union of all destination regions, specified by the elements of <code>pRegions</code>, <strong class=\"purple\">must</strong> not overlap in memory"
         },
@@ -15250,11 +16150,11 @@
       "(VK_VERSION_1_1,VK_KHR_maintenance1)": [
         {
           "vuid": "VUID-vkCmdCopyImage-srcImage-01995",
-          "text": " The <a href=\"#resources-image-format-features\">format features</a> of <code>srcImage</code> <strong class=\"purple\">must</strong> contain <code>VK_FORMAT_FEATURE_TRANSFER_SRC_BIT</code>."
+          "text": " The <a href=\"#resources-image-format-features\">format features</a> of <code>srcImage</code> <strong class=\"purple\">must</strong> contain <code>VK_FORMAT_FEATURE_TRANSFER_SRC_BIT</code>"
         },
         {
           "vuid": "VUID-vkCmdCopyImage-dstImage-01996",
-          "text": " The <a href=\"#resources-image-format-features\">format features</a> of <code>dstImage</code> <strong class=\"purple\">must</strong> contain <code>VK_FORMAT_FEATURE_TRANSFER_DST_BIT</code>."
+          "text": " The <a href=\"#resources-image-format-features\">format features</a> of <code>dstImage</code> <strong class=\"purple\">must</strong> contain <code>VK_FORMAT_FEATURE_TRANSFER_DST_BIT</code>"
         }
       ],
       "!(VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion)": [
@@ -15287,10 +16187,6 @@
         {
           "vuid": "VUID-vkCmdCopyImage-None-01549",
           "text": " In a copy to or from a plane of a <a href=\"#formats-requiring-sampler-ycbcr-conversion\">multi-planar image</a>, the <a href=\"#VkFormat\">VkFormat</a> of the image and plane <strong class=\"purple\">must</strong> be compatible according to <a href=\"#formats-compatible-planes\">the description of compatible planes</a> for the plane being copied"
-        },
-        {
-          "vuid": "VUID-vkCmdCopyImage-aspectMask-01550",
-          "text": " When a copy is performed to or from an image with a <a href=\"#formats-requiring-sampler-ycbcr-conversion\">multi-planar format</a>, the <code>aspectMask</code> of the <code>srcSubresource</code> and/or <code>dstSubresource</code> that refers to the multi-planar image <strong class=\"purple\">must</strong> be <code>VK_IMAGE_ASPECT_PLANE_0_BIT</code>, <code>VK_IMAGE_ASPECT_PLANE_1_BIT</code>, or <code>VK_IMAGE_ASPECT_PLANE_2_BIT</code> (with <code>VK_IMAGE_ASPECT_PLANE_2_BIT</code> valid only for a <a href=\"#VkFormat\">VkFormat</a> with three planes)"
         }
       ],
       "!(VK_KHR_shared_presentable_image)": [
@@ -15446,7 +16342,7 @@
         },
         {
           "vuid": "VUID-VkImageCopy-srcImage-01789",
-          "text": " If the calling command&#8217;s <code>srcImage</code> or <code>dstImage</code> is of type <code>VK_IMAGE_TYPE_2D</code>, then <code>extent.depth</code> <strong class=\"purple\">must</strong> be <code>1</code>."
+          "text": " If the calling command&#8217;s <code>srcImage</code> or <code>dstImage</code> is of type <code>VK_IMAGE_TYPE_2D</code>, then <code>extent.depth</code> <strong class=\"purple\">must</strong> be <code>1</code>"
         }
       ],
       "(VK_VERSION_1_1,VK_KHR_maintenance1)": [
@@ -15460,15 +16356,15 @@
         },
         {
           "vuid": "VUID-VkImageCopy-srcImage-01790",
-          "text": " If both <code>srcImage</code> and <code>dstImage</code> are of type <code>VK_IMAGE_TYPE_2D</code> then <code>extent.depth</code> <strong class=\"purple\">must</strong> be <code>1</code>."
+          "text": " If both <code>srcImage</code> and <code>dstImage</code> are of type <code>VK_IMAGE_TYPE_2D</code> then <code>extent.depth</code> <strong class=\"purple\">must</strong> be <code>1</code>"
         },
         {
           "vuid": "VUID-VkImageCopy-srcImage-01791",
-          "text": " If the calling command&#8217;s <code>srcImage</code> is of type <code>VK_IMAGE_TYPE_2D</code>, and the <code>dstImage</code> is of type <code>VK_IMAGE_TYPE_3D</code>, then <code>extent.depth</code> <strong class=\"purple\">must</strong> equal to the <code>layerCount</code> member of <code>srcSubresource</code>."
+          "text": " If the calling command&#8217;s <code>srcImage</code> is of type <code>VK_IMAGE_TYPE_2D</code>, and the <code>dstImage</code> is of type <code>VK_IMAGE_TYPE_3D</code>, then <code>extent.depth</code> <strong class=\"purple\">must</strong> equal to the <code>layerCount</code> member of <code>srcSubresource</code>"
         },
         {
           "vuid": "VUID-VkImageCopy-dstImage-01792",
-          "text": " If the calling command&#8217;s <code>dstImage</code> is of type <code>VK_IMAGE_TYPE_2D</code>, and the <code>srcImage</code> is of type <code>VK_IMAGE_TYPE_3D</code>, then <code>extent.depth</code> <strong class=\"purple\">must</strong> equal to the <code>layerCount</code> member of <code>dstSubresource</code>."
+          "text": " If the calling command&#8217;s <code>dstImage</code> is of type <code>VK_IMAGE_TYPE_2D</code>, and the <code>srcImage</code> is of type <code>VK_IMAGE_TYPE_3D</code>, then <code>extent.depth</code> <strong class=\"purple\">must</strong> equal to the <code>layerCount</code> member of <code>dstSubresource</code>"
         }
       ],
       "core": [
@@ -15490,7 +16386,7 @@
         },
         {
           "vuid": "VUID-VkImageCopy-srcImage-00146",
-          "text": " If the calling command&#8217;s <code>srcImage</code> is of type <code>VK_IMAGE_TYPE_1D</code>, then <code>srcOffset.y</code> <strong class=\"purple\">must</strong> be <code>0</code> and <code>extent.height</code> <strong class=\"purple\">must</strong> be <code>1</code>."
+          "text": " If the calling command&#8217;s <code>srcImage</code> is of type <code>VK_IMAGE_TYPE_1D</code>, then <code>srcOffset.y</code> <strong class=\"purple\">must</strong> be <code>0</code> and <code>extent.height</code> <strong class=\"purple\">must</strong> be <code>1</code>"
         },
         {
           "vuid": "VUID-VkImageCopy-srcOffset-00147",
@@ -15498,15 +16394,15 @@
         },
         {
           "vuid": "VUID-VkImageCopy-srcImage-01785",
-          "text": " If the calling command&#8217;s <code>srcImage</code> is of type <code>VK_IMAGE_TYPE_1D</code>, then <code>srcOffset.z</code> <strong class=\"purple\">must</strong> be <code>0</code> and <code>extent.depth</code> <strong class=\"purple\">must</strong> be <code>1</code>."
+          "text": " If the calling command&#8217;s <code>srcImage</code> is of type <code>VK_IMAGE_TYPE_1D</code>, then <code>srcOffset.z</code> <strong class=\"purple\">must</strong> be <code>0</code> and <code>extent.depth</code> <strong class=\"purple\">must</strong> be <code>1</code>"
         },
         {
           "vuid": "VUID-VkImageCopy-dstImage-01786",
-          "text": " If the calling command&#8217;s <code>dstImage</code> is of type <code>VK_IMAGE_TYPE_1D</code>, then <code>dstOffset.z</code> <strong class=\"purple\">must</strong> be <code>0</code> and <code>extent.depth</code> <strong class=\"purple\">must</strong> be <code>1</code>."
+          "text": " If the calling command&#8217;s <code>dstImage</code> is of type <code>VK_IMAGE_TYPE_1D</code>, then <code>dstOffset.z</code> <strong class=\"purple\">must</strong> be <code>0</code> and <code>extent.depth</code> <strong class=\"purple\">must</strong> be <code>1</code>"
         },
         {
           "vuid": "VUID-VkImageCopy-srcImage-01787",
-          "text": " If the calling command&#8217;s <code>srcImage</code> is of type <code>VK_IMAGE_TYPE_2D</code>, then <code>srcOffset.z</code> <strong class=\"purple\">must</strong> be <code>0</code>."
+          "text": " If the calling command&#8217;s <code>srcImage</code> is of type <code>VK_IMAGE_TYPE_2D</code>, then <code>srcOffset.z</code> <strong class=\"purple\">must</strong> be <code>0</code>"
         },
         {
           "vuid": "VUID-VkImageCopy-dstImage-01788",
@@ -15522,7 +16418,7 @@
         },
         {
           "vuid": "VUID-VkImageCopy-dstImage-00152",
-          "text": " If the calling command&#8217;s <code>dstImage</code> is of type <code>VK_IMAGE_TYPE_1D</code>, then <code>dstOffset.y</code> <strong class=\"purple\">must</strong> be <code>0</code> and <code>extent.height</code> <strong class=\"purple\">must</strong> be <code>1</code>."
+          "text": " If the calling command&#8217;s <code>dstImage</code> is of type <code>VK_IMAGE_TYPE_1D</code>, then <code>dstOffset.y</code> <strong class=\"purple\">must</strong> be <code>0</code> and <code>extent.height</code> <strong class=\"purple\">must</strong> be <code>1</code>"
         },
         {
           "vuid": "VUID-VkImageCopy-dstOffset-00153",
@@ -15564,7 +16460,7 @@
       "(VK_EXT_image_drm_format_modifier)": [
         {
           "vuid": "VUID-VkImageSubresourceLayers-aspectMask-02247",
-          "text": " <code>aspectMask</code> <strong class=\"purple\">must</strong> not include <code>VK_IMAGE_ASPECT_MEMORY_PLANE_i_BIT_EXT</code> for any index <code>i</code>."
+          "text": " <code>aspectMask</code> <strong class=\"purple\">must</strong> not include <code>VK_IMAGE_ASPECT_MEMORY_PLANE_i_BIT_EXT</code> for any index <code>i</code>"
         }
       ]
     },
@@ -15662,7 +16558,7 @@
       "(VK_VERSION_1_1,VK_KHR_maintenance1)": [
         {
           "vuid": "VUID-vkCmdCopyBufferToImage-dstImage-01997",
-          "text": " The <a href=\"#resources-image-format-features\">format features</a> of <code>dstImage</code> <strong class=\"purple\">must</strong> contain <code>VK_FORMAT_FEATURE_TRANSFER_DST_BIT</code>."
+          "text": " The <a href=\"#resources-image-format-features\">format features</a> of <code>dstImage</code> <strong class=\"purple\">must</strong> contain <code>VK_FORMAT_FEATURE_TRANSFER_DST_BIT</code>"
         }
       ],
       "!(VK_KHR_shared_presentable_image)": [
@@ -15792,7 +16688,7 @@
       "(VK_VERSION_1_1,VK_KHR_maintenance1)": [
         {
           "vuid": "VUID-vkCmdCopyImageToBuffer-srcImage-01998",
-          "text": " The <a href=\"#resources-image-format-features\">format features</a> of <code>srcImage</code> <strong class=\"purple\">must</strong> contain <code>VK_FORMAT_FEATURE_TRANSFER_SRC_BIT</code>."
+          "text": " The <a href=\"#resources-image-format-features\">format features</a> of <code>srcImage</code> <strong class=\"purple\">must</strong> contain <code>VK_FORMAT_FEATURE_TRANSFER_SRC_BIT</code>"
         }
       ],
       "!(VK_KHR_shared_presentable_image)": [
@@ -15832,7 +16728,7 @@
       "!(VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion)": [
         {
           "vuid": "VUID-VkBufferImageCopy-bufferOffset-00193",
-          "text": " If the calling command&#8217;s <code>VkImage</code> parameter&#8217;s format is not a depth/stencil format, then <code>bufferOffset</code> <strong class=\"purple\">must</strong> be a multiple of the format&#8217;s texel block size."
+          "text": " If the calling command&#8217;s <code>VkImage</code> parameter&#8217;s format is not a depth/stencil format, then <code>bufferOffset</code> <strong class=\"purple\">must</strong> be a multiple of the format&#8217;s texel block size"
         },
         {
           "vuid": "VUID-VkBufferImageCopy-bufferRowLength-00203",
@@ -15866,7 +16762,7 @@
       "(VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion)": [
         {
           "vuid": "VUID-VkBufferImageCopy-bufferOffset-01558",
-          "text": " If the calling command&#8217;s <code>VkImage</code> parameter&#8217;s format is not a depth/stencil format or a <a href=\"#formats-requiring-sampler-ycbcr-conversion\">multi-planar format</a>, then <code>bufferOffset</code> <strong class=\"purple\">must</strong> be a multiple of the format&#8217;s texel block size."
+          "text": " If the calling command&#8217;s <code>VkImage</code> parameter&#8217;s format is not a depth/stencil format or a <a href=\"#formats-requiring-sampler-ycbcr-conversion\">multi-planar format</a>, then <code>bufferOffset</code> <strong class=\"purple\">must</strong> be a multiple of the format&#8217;s texel block size"
         },
         {
           "vuid": "VUID-VkBufferImageCopy-bufferOffset-01559",
@@ -15928,7 +16824,7 @@
         },
         {
           "vuid": "VUID-VkBufferImageCopy-srcImage-00199",
-          "text": " If the calling command&#8217;s <code>srcImage</code> (<a href=\"#vkCmdCopyImageToBuffer\">vkCmdCopyImageToBuffer</a>) or <code>dstImage</code> (<a href=\"#vkCmdCopyBufferToImage\">vkCmdCopyBufferToImage</a>) is of type <code>VK_IMAGE_TYPE_1D</code>, then <code>imageOffset.y</code> <strong class=\"purple\">must</strong> be <code>0</code> and <code>imageExtent.height</code> <strong class=\"purple\">must</strong> be <code>1</code>."
+          "text": " If the calling command&#8217;s <code>srcImage</code> (<a href=\"#vkCmdCopyImageToBuffer\">vkCmdCopyImageToBuffer</a>) or <code>dstImage</code> (<a href=\"#vkCmdCopyBufferToImage\">vkCmdCopyBufferToImage</a>) is of type <code>VK_IMAGE_TYPE_1D</code>, then <code>imageOffset.y</code> <strong class=\"purple\">must</strong> be <code>0</code> and <code>imageExtent.height</code> <strong class=\"purple\">must</strong> be <code>1</code>"
         },
         {
           "vuid": "VUID-VkBufferImageCopy-imageOffset-00200",
@@ -16009,10 +16905,6 @@
           "text": " <code>dstImageLayout</code> <strong class=\"purple\">must</strong> specify the layout of the image subresources of <code>dstImage</code> specified in <code>pRegions</code> at the time this command is executed on a <code>VkDevice</code>"
         },
         {
-          "vuid": "VUID-vkCmdBlitImage-srcImage-00228",
-          "text": " The sample count of <code>srcImage</code> and <code>dstImage</code> <strong class=\"purple\">must</strong> both be equal to <code>VK_SAMPLE_COUNT_1_BIT</code>"
-        },
-        {
           "vuid": "VUID-vkCmdBlitImage-srcImage-00229",
           "text": " If either of <code>srcImage</code> or <code>dstImage</code> was created with a signed integer <a href=\"#VkFormat\">VkFormat</a>, the other <strong class=\"purple\">must</strong> also have been created with a signed integer <a href=\"#VkFormat\">VkFormat</a>"
         },
@@ -16138,7 +17030,7 @@
       "(VK_IMG_filter_cubic,VK_EXT_filter_cubic)": [
         {
           "vuid": "VUID-vkCmdBlitImage-filter-02002",
-          "text": " If <code>filter</code> is <code>VK_FILTER_CUBIC_EXT</code>, then the <a href=\"#resources-image-format-features\">format features</a> of <code>srcImage</code> <strong class=\"purple\">must</strong> contain <code>VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT</code>."
+          "text": " If <code>filter</code> is <code>VK_FILTER_CUBIC_EXT</code>, then the <a href=\"#resources-image-format-features\">format features</a> of <code>srcImage</code> <strong class=\"purple\">must</strong> contain <code>VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT</code>"
         },
         {
           "vuid": "VUID-vkCmdBlitImage-filter-00237",
@@ -16198,7 +17090,7 @@
         },
         {
           "vuid": "VUID-VkImageBlit-srcImage-00245",
-          "text": " If the calling command&#8217;s <code>srcImage</code> is of type <code>VK_IMAGE_TYPE_1D</code>, then <code>srcOffset</code>[0].y <strong class=\"purple\">must</strong> be <code>0</code> and <code>srcOffset</code>[1].y <strong class=\"purple\">must</strong> be <code>1</code>."
+          "text": " If the calling command&#8217;s <code>srcImage</code> is of type <code>VK_IMAGE_TYPE_1D</code>, then <code>srcOffset</code>[0].y <strong class=\"purple\">must</strong> be <code>0</code> and <code>srcOffset</code>[1].y <strong class=\"purple\">must</strong> be <code>1</code>"
         },
         {
           "vuid": "VUID-VkImageBlit-srcOffset-00246",
@@ -16206,7 +17098,7 @@
         },
         {
           "vuid": "VUID-VkImageBlit-srcImage-00247",
-          "text": " If the calling command&#8217;s <code>srcImage</code> is of type <code>VK_IMAGE_TYPE_1D</code> or <code>VK_IMAGE_TYPE_2D</code>, then <code>srcOffset</code>[0].z <strong class=\"purple\">must</strong> be <code>0</code> and <code>srcOffset</code>[1].z <strong class=\"purple\">must</strong> be <code>1</code>."
+          "text": " If the calling command&#8217;s <code>srcImage</code> is of type <code>VK_IMAGE_TYPE_1D</code> or <code>VK_IMAGE_TYPE_2D</code>, then <code>srcOffset</code>[0].z <strong class=\"purple\">must</strong> be <code>0</code> and <code>srcOffset</code>[1].z <strong class=\"purple\">must</strong> be <code>1</code>"
         },
         {
           "vuid": "VUID-VkImageBlit-dstOffset-00248",
@@ -16218,7 +17110,7 @@
         },
         {
           "vuid": "VUID-VkImageBlit-dstImage-00250",
-          "text": " If the calling command&#8217;s <code>dstImage</code> is of type <code>VK_IMAGE_TYPE_1D</code>, then <code>dstOffset</code>[0].y <strong class=\"purple\">must</strong> be <code>0</code> and <code>dstOffset</code>[1].y <strong class=\"purple\">must</strong> be <code>1</code>."
+          "text": " If the calling command&#8217;s <code>dstImage</code> is of type <code>VK_IMAGE_TYPE_1D</code>, then <code>dstOffset</code>[0].y <strong class=\"purple\">must</strong> be <code>0</code> and <code>dstOffset</code>[1].y <strong class=\"purple\">must</strong> be <code>1</code>"
         },
         {
           "vuid": "VUID-VkImageBlit-dstOffset-00251",
@@ -16226,7 +17118,7 @@
         },
         {
           "vuid": "VUID-VkImageBlit-dstImage-00252",
-          "text": " If the calling command&#8217;s <code>dstImage</code> is of type <code>VK_IMAGE_TYPE_1D</code> or <code>VK_IMAGE_TYPE_2D</code>, then <code>dstOffset</code>[0].z <strong class=\"purple\">must</strong> be <code>0</code> and <code>dstOffset</code>[1].z <strong class=\"purple\">must</strong> be <code>1</code>."
+          "text": " If the calling command&#8217;s <code>dstImage</code> is of type <code>VK_IMAGE_TYPE_1D</code> or <code>VK_IMAGE_TYPE_2D</code>, then <code>dstOffset</code>[0].z <strong class=\"purple\">must</strong> be <code>0</code> and <code>dstOffset</code>[1].z <strong class=\"purple\">must</strong> be <code>1</code>"
         },
         {
           "vuid": "VUID-VkImageBlit-srcSubresource-parameter",
@@ -16278,7 +17170,7 @@
         },
         {
           "vuid": "VUID-vkCmdResolveImage-dstImage-02003",
-          "text": " The <a href=\"#resources-image-format-features\">format features</a> of <code>dstImage</code> <strong class=\"purple\">must</strong> contain <code>VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT</code>."
+          "text": " The <a href=\"#resources-image-format-features\">format features</a> of <code>dstImage</code> <strong class=\"purple\">must</strong> contain <code>VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT</code>"
         },
         {
           "vuid": "VUID-vkCmdResolveImage-srcImage-01386",
@@ -16410,7 +17302,7 @@
         },
         {
           "vuid": "VUID-VkImageResolve-srcImage-00271",
-          "text": " If the calling command&#8217;s <code>srcImage</code> is of type <code>VK_IMAGE_TYPE_1D</code>, then <code>srcOffset.y</code> <strong class=\"purple\">must</strong> be <code>0</code> and <code>extent.height</code> <strong class=\"purple\">must</strong> be <code>1</code>."
+          "text": " If the calling command&#8217;s <code>srcImage</code> is of type <code>VK_IMAGE_TYPE_1D</code>, then <code>srcOffset.y</code> <strong class=\"purple\">must</strong> be <code>0</code> and <code>extent.height</code> <strong class=\"purple\">must</strong> be <code>1</code>"
         },
         {
           "vuid": "VUID-VkImageResolve-srcOffset-00272",
@@ -16418,7 +17310,7 @@
         },
         {
           "vuid": "VUID-VkImageResolve-srcImage-00273",
-          "text": " If the calling command&#8217;s <code>srcImage</code> is of type <code>VK_IMAGE_TYPE_1D</code> or <code>VK_IMAGE_TYPE_2D</code>, then <code>srcOffset.z</code> <strong class=\"purple\">must</strong> be <code>0</code> and <code>extent.depth</code> <strong class=\"purple\">must</strong> be <code>1</code>."
+          "text": " If the calling command&#8217;s <code>srcImage</code> is of type <code>VK_IMAGE_TYPE_1D</code> or <code>VK_IMAGE_TYPE_2D</code>, then <code>srcOffset.z</code> <strong class=\"purple\">must</strong> be <code>0</code> and <code>extent.depth</code> <strong class=\"purple\">must</strong> be <code>1</code>"
         },
         {
           "vuid": "VUID-VkImageResolve-dstOffset-00274",
@@ -16430,7 +17322,7 @@
         },
         {
           "vuid": "VUID-VkImageResolve-dstImage-00276",
-          "text": " If the calling command&#8217;s <code>dstImage</code> is of type <code>VK_IMAGE_TYPE_1D</code>, then <code>dstOffset.y</code> <strong class=\"purple\">must</strong> be <code>0</code> and <code>extent.height</code> <strong class=\"purple\">must</strong> be <code>1</code>."
+          "text": " If the calling command&#8217;s <code>dstImage</code> is of type <code>VK_IMAGE_TYPE_1D</code>, then <code>dstOffset.y</code> <strong class=\"purple\">must</strong> be <code>0</code> and <code>extent.height</code> <strong class=\"purple\">must</strong> be <code>1</code>"
         },
         {
           "vuid": "VUID-VkImageResolve-dstOffset-00277",
@@ -16438,7 +17330,7 @@
         },
         {
           "vuid": "VUID-VkImageResolve-dstImage-00278",
-          "text": " If the calling command&#8217;s <code>dstImage</code> is of type <code>VK_IMAGE_TYPE_1D</code> or <code>VK_IMAGE_TYPE_2D</code>, then <code>dstOffset.z</code> <strong class=\"purple\">must</strong> be <code>0</code> and <code>extent.depth</code> <strong class=\"purple\">must</strong> be <code>1</code>."
+          "text": " If the calling command&#8217;s <code>dstImage</code> is of type <code>VK_IMAGE_TYPE_1D</code> or <code>VK_IMAGE_TYPE_2D</code>, then <code>dstOffset.z</code> <strong class=\"purple\">must</strong> be <code>0</code> and <code>extent.depth</code> <strong class=\"purple\">must</strong> be <code>1</code>"
         },
         {
           "vuid": "VUID-VkImageResolve-srcSubresource-parameter",
@@ -16454,7 +17346,7 @@
       "(VK_AMD_buffer_marker)": [
         {
           "vuid": "VUID-vkCmdWriteBufferMarkerAMD-dstOffset-01798",
-          "text": " <code>dstOffset</code> <strong class=\"purple\">must</strong> be less than or equal to the size of <code>dstBuffer</code> minus <code>4</code>."
+          "text": " <code>dstOffset</code> <strong class=\"purple\">must</strong> be less than or equal to the size of <code>dstBuffer</code> minus <code>4</code>"
         },
         {
           "vuid": "VUID-vkCmdWriteBufferMarkerAMD-dstBuffer-01799",
@@ -16569,10 +17461,10 @@
           "text": " Both of <code>buffer</code>, and <code>commandBuffer</code> <strong class=\"purple\">must</strong> have been created, allocated, or retrieved from the same <a href=\"#VkDevice\">VkDevice</a>"
         }
       ],
-      "(VK_NV_ray_tracing)": [
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)": [
         {
           "vuid": "VUID-vkCmdBindIndexBuffer-indexType-02507",
-          "text": " <code>indexType</code> <strong class=\"purple\">must</strong> not be <code>VK_INDEX_TYPE_NONE_NV</code>."
+          "text": " <code>indexType</code> <strong class=\"purple\">must</strong> not be <code>VK_INDEX_TYPE_NONE_KHR</code>"
         }
       ],
       "(VK_EXT_index_type_uint8)": [
@@ -16638,11 +17530,11 @@
         },
         {
           "vuid": "VUID-vkCmdDraw-renderPass-02684",
-          "text": " The current render pass <strong class=\"purple\">must</strong> be <a href=\"#renderpass-compatibility\">compatible</a> with the <code>renderPass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>."
+          "text": " The current render pass <strong class=\"purple\">must</strong> be <a href=\"#renderpass-compatibility\">compatible</a> with the <code>renderPass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>"
         },
         {
           "vuid": "VUID-vkCmdDraw-subpass-02685",
-          "text": " The subpass index of the current render pass <strong class=\"purple\">must</strong> be equal to the <code>subpass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>."
+          "text": " The subpass index of the current render pass <strong class=\"purple\">must</strong> be equal to the <code>subpass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>"
         },
         {
           "vuid": "VUID-vkCmdDraw-None-02686",
@@ -16702,7 +17594,7 @@
       "(VK_NV_corner_sampled_image)": [
         {
           "vuid": "VUID-vkCmdDraw-flags-02696",
-          "text": " Any <a href=\"#VkImage\">VkImage</a> created with a <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>flags</code> containing <code>VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV</code> sampled as a result of this command <strong class=\"purple\">must</strong> only be sampled using a <a href=\"#VkSamplerAddressMode\">VkSamplerAddressMode</a> of <code>VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE</code>."
+          "text": " Any <a href=\"#VkImage\">VkImage</a> created with a <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>flags</code> containing <code>VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV</code> sampled as a result of this command <strong class=\"purple\">must</strong> only be sampled using a <a href=\"#VkSamplerAddressMode\">VkSamplerAddressMode</a> of <code>VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE</code>"
         }
       ],
       "(VK_VERSION_1_1)": [
@@ -16722,7 +17614,7 @@
       "(VK_VERSION_1_1,VK_KHR_multiview)": [
         {
           "vuid": "VUID-vkCmdDraw-maxMultiviewInstanceIndex-02688",
-          "text": " If the draw is recorded in a render pass instance with multiview enabled, the maximum instance index <strong class=\"purple\">must</strong> be less than or equal to <a href=\"#VkPhysicalDeviceMultiviewProperties\">VkPhysicalDeviceMultiviewProperties</a>::<code>maxMultiviewInstanceIndex</code>."
+          "text": " If the draw is recorded in a render pass instance with multiview enabled, the maximum instance index <strong class=\"purple\">must</strong> be less than or equal to <a href=\"#VkPhysicalDeviceMultiviewProperties\">VkPhysicalDeviceMultiviewProperties</a>::<code>maxMultiviewInstanceIndex</code>"
         }
       ],
       "(VK_EXT_sample_locations)": [
@@ -16788,11 +17680,11 @@
         },
         {
           "vuid": "VUID-vkCmdDrawIndexed-renderPass-02684",
-          "text": " The current render pass <strong class=\"purple\">must</strong> be <a href=\"#renderpass-compatibility\">compatible</a> with the <code>renderPass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>."
+          "text": " The current render pass <strong class=\"purple\">must</strong> be <a href=\"#renderpass-compatibility\">compatible</a> with the <code>renderPass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>"
         },
         {
           "vuid": "VUID-vkCmdDrawIndexed-subpass-02685",
-          "text": " The subpass index of the current render pass <strong class=\"purple\">must</strong> be equal to the <code>subpass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>."
+          "text": " The subpass index of the current render pass <strong class=\"purple\">must</strong> be equal to the <code>subpass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>"
         },
         {
           "vuid": "VUID-vkCmdDrawIndexed-None-02686",
@@ -16856,7 +17748,7 @@
       "(VK_NV_corner_sampled_image)": [
         {
           "vuid": "VUID-vkCmdDrawIndexed-flags-02696",
-          "text": " Any <a href=\"#VkImage\">VkImage</a> created with a <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>flags</code> containing <code>VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV</code> sampled as a result of this command <strong class=\"purple\">must</strong> only be sampled using a <a href=\"#VkSamplerAddressMode\">VkSamplerAddressMode</a> of <code>VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE</code>."
+          "text": " Any <a href=\"#VkImage\">VkImage</a> created with a <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>flags</code> containing <code>VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV</code> sampled as a result of this command <strong class=\"purple\">must</strong> only be sampled using a <a href=\"#VkSamplerAddressMode\">VkSamplerAddressMode</a> of <code>VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE</code>"
         }
       ],
       "(VK_VERSION_1_1)": [
@@ -16876,7 +17768,7 @@
       "(VK_VERSION_1_1,VK_KHR_multiview)": [
         {
           "vuid": "VUID-vkCmdDrawIndexed-maxMultiviewInstanceIndex-02688",
-          "text": " If the draw is recorded in a render pass instance with multiview enabled, the maximum instance index <strong class=\"purple\">must</strong> be less than or equal to <a href=\"#VkPhysicalDeviceMultiviewProperties\">VkPhysicalDeviceMultiviewProperties</a>::<code>maxMultiviewInstanceIndex</code>."
+          "text": " If the draw is recorded in a render pass instance with multiview enabled, the maximum instance index <strong class=\"purple\">must</strong> be less than or equal to <a href=\"#VkPhysicalDeviceMultiviewProperties\">VkPhysicalDeviceMultiviewProperties</a>::<code>maxMultiviewInstanceIndex</code>"
         }
       ],
       "(VK_EXT_sample_locations)": [
@@ -16942,11 +17834,11 @@
         },
         {
           "vuid": "VUID-vkCmdDrawIndirect-renderPass-02684",
-          "text": " The current render pass <strong class=\"purple\">must</strong> be <a href=\"#renderpass-compatibility\">compatible</a> with the <code>renderPass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>."
+          "text": " The current render pass <strong class=\"purple\">must</strong> be <a href=\"#renderpass-compatibility\">compatible</a> with the <code>renderPass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>"
         },
         {
           "vuid": "VUID-vkCmdDrawIndirect-subpass-02685",
-          "text": " The subpass index of the current render pass <strong class=\"purple\">must</strong> be equal to the <code>subpass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>."
+          "text": " The subpass index of the current render pass <strong class=\"purple\">must</strong> be equal to the <code>subpass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>"
         },
         {
           "vuid": "VUID-vkCmdDrawIndirect-None-02686",
@@ -17050,7 +17942,7 @@
       "(VK_NV_corner_sampled_image)": [
         {
           "vuid": "VUID-vkCmdDrawIndirect-flags-02696",
-          "text": " Any <a href=\"#VkImage\">VkImage</a> created with a <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>flags</code> containing <code>VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV</code> sampled as a result of this command <strong class=\"purple\">must</strong> only be sampled using a <a href=\"#VkSamplerAddressMode\">VkSamplerAddressMode</a> of <code>VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE</code>."
+          "text": " Any <a href=\"#VkImage\">VkImage</a> created with a <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>flags</code> containing <code>VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV</code> sampled as a result of this command <strong class=\"purple\">must</strong> only be sampled using a <a href=\"#VkSamplerAddressMode\">VkSamplerAddressMode</a> of <code>VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE</code>"
         }
       ],
       "(VK_VERSION_1_1)": [
@@ -17066,7 +17958,7 @@
       "(VK_VERSION_1_1,VK_KHR_multiview)": [
         {
           "vuid": "VUID-vkCmdDrawIndirect-maxMultiviewInstanceIndex-02688",
-          "text": " If the draw is recorded in a render pass instance with multiview enabled, the maximum instance index <strong class=\"purple\">must</strong> be less than or equal to <a href=\"#VkPhysicalDeviceMultiviewProperties\">VkPhysicalDeviceMultiviewProperties</a>::<code>maxMultiviewInstanceIndex</code>."
+          "text": " If the draw is recorded in a render pass instance with multiview enabled, the maximum instance index <strong class=\"purple\">must</strong> be less than or equal to <a href=\"#VkPhysicalDeviceMultiviewProperties\">VkPhysicalDeviceMultiviewProperties</a>::<code>maxMultiviewInstanceIndex</code>"
         }
       ],
       "(VK_EXT_sample_locations)": [
@@ -17144,11 +18036,11 @@
         },
         {
           "vuid": "VUID-vkCmdDrawIndirectCount-renderPass-02684",
-          "text": " The current render pass <strong class=\"purple\">must</strong> be <a href=\"#renderpass-compatibility\">compatible</a> with the <code>renderPass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>."
+          "text": " The current render pass <strong class=\"purple\">must</strong> be <a href=\"#renderpass-compatibility\">compatible</a> with the <code>renderPass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>"
         },
         {
           "vuid": "VUID-vkCmdDrawIndirectCount-subpass-02685",
-          "text": " The subpass index of the current render pass <strong class=\"purple\">must</strong> be equal to the <code>subpass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>."
+          "text": " The subpass index of the current render pass <strong class=\"purple\">must</strong> be equal to the <code>subpass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>"
         },
         {
           "vuid": "VUID-vkCmdDrawIndirectCount-None-02686",
@@ -17264,7 +18156,7 @@
       "(VK_VERSION_1_2,VK_KHR_draw_indirect_count)+(VK_NV_corner_sampled_image)": [
         {
           "vuid": "VUID-vkCmdDrawIndirectCount-flags-02696",
-          "text": " Any <a href=\"#VkImage\">VkImage</a> created with a <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>flags</code> containing <code>VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV</code> sampled as a result of this command <strong class=\"purple\">must</strong> only be sampled using a <a href=\"#VkSamplerAddressMode\">VkSamplerAddressMode</a> of <code>VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE</code>."
+          "text": " Any <a href=\"#VkImage\">VkImage</a> created with a <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>flags</code> containing <code>VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV</code> sampled as a result of this command <strong class=\"purple\">must</strong> only be sampled using a <a href=\"#VkSamplerAddressMode\">VkSamplerAddressMode</a> of <code>VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE</code>"
         }
       ],
       "(VK_VERSION_1_2,VK_KHR_draw_indirect_count)+(VK_VERSION_1_1)": [
@@ -17280,7 +18172,7 @@
       "(VK_VERSION_1_2,VK_KHR_draw_indirect_count)+(VK_VERSION_1_1,VK_KHR_multiview)": [
         {
           "vuid": "VUID-vkCmdDrawIndirectCount-maxMultiviewInstanceIndex-02688",
-          "text": " If the draw is recorded in a render pass instance with multiview enabled, the maximum instance index <strong class=\"purple\">must</strong> be less than or equal to <a href=\"#VkPhysicalDeviceMultiviewProperties\">VkPhysicalDeviceMultiviewProperties</a>::<code>maxMultiviewInstanceIndex</code>."
+          "text": " If the draw is recorded in a render pass instance with multiview enabled, the maximum instance index <strong class=\"purple\">must</strong> be less than or equal to <a href=\"#VkPhysicalDeviceMultiviewProperties\">VkPhysicalDeviceMultiviewProperties</a>::<code>maxMultiviewInstanceIndex</code>"
         }
       ],
       "(VK_VERSION_1_2,VK_KHR_draw_indirect_count)+(VK_EXT_sample_locations)": [
@@ -17352,11 +18244,11 @@
         },
         {
           "vuid": "VUID-vkCmdDrawIndexedIndirect-renderPass-02684",
-          "text": " The current render pass <strong class=\"purple\">must</strong> be <a href=\"#renderpass-compatibility\">compatible</a> with the <code>renderPass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>."
+          "text": " The current render pass <strong class=\"purple\">must</strong> be <a href=\"#renderpass-compatibility\">compatible</a> with the <code>renderPass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>"
         },
         {
           "vuid": "VUID-vkCmdDrawIndexedIndirect-subpass-02685",
-          "text": " The subpass index of the current render pass <strong class=\"purple\">must</strong> be equal to the <code>subpass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>."
+          "text": " The subpass index of the current render pass <strong class=\"purple\">must</strong> be equal to the <code>subpass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>"
         },
         {
           "vuid": "VUID-vkCmdDrawIndexedIndirect-None-02686",
@@ -17460,7 +18352,7 @@
       "(VK_NV_corner_sampled_image)": [
         {
           "vuid": "VUID-vkCmdDrawIndexedIndirect-flags-02696",
-          "text": " Any <a href=\"#VkImage\">VkImage</a> created with a <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>flags</code> containing <code>VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV</code> sampled as a result of this command <strong class=\"purple\">must</strong> only be sampled using a <a href=\"#VkSamplerAddressMode\">VkSamplerAddressMode</a> of <code>VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE</code>."
+          "text": " Any <a href=\"#VkImage\">VkImage</a> created with a <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>flags</code> containing <code>VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV</code> sampled as a result of this command <strong class=\"purple\">must</strong> only be sampled using a <a href=\"#VkSamplerAddressMode\">VkSamplerAddressMode</a> of <code>VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE</code>"
         }
       ],
       "(VK_VERSION_1_1)": [
@@ -17476,7 +18368,7 @@
       "(VK_VERSION_1_1,VK_KHR_multiview)": [
         {
           "vuid": "VUID-vkCmdDrawIndexedIndirect-maxMultiviewInstanceIndex-02688",
-          "text": " If the draw is recorded in a render pass instance with multiview enabled, the maximum instance index <strong class=\"purple\">must</strong> be less than or equal to <a href=\"#VkPhysicalDeviceMultiviewProperties\">VkPhysicalDeviceMultiviewProperties</a>::<code>maxMultiviewInstanceIndex</code>."
+          "text": " If the draw is recorded in a render pass instance with multiview enabled, the maximum instance index <strong class=\"purple\">must</strong> be less than or equal to <a href=\"#VkPhysicalDeviceMultiviewProperties\">VkPhysicalDeviceMultiviewProperties</a>::<code>maxMultiviewInstanceIndex</code>"
         }
       ],
       "(VK_EXT_sample_locations)": [
@@ -17564,11 +18456,11 @@
         },
         {
           "vuid": "VUID-vkCmdDrawIndexedIndirectCount-renderPass-02684",
-          "text": " The current render pass <strong class=\"purple\">must</strong> be <a href=\"#renderpass-compatibility\">compatible</a> with the <code>renderPass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>."
+          "text": " The current render pass <strong class=\"purple\">must</strong> be <a href=\"#renderpass-compatibility\">compatible</a> with the <code>renderPass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>"
         },
         {
           "vuid": "VUID-vkCmdDrawIndexedIndirectCount-subpass-02685",
-          "text": " The subpass index of the current render pass <strong class=\"purple\">must</strong> be equal to the <code>subpass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>."
+          "text": " The subpass index of the current render pass <strong class=\"purple\">must</strong> be equal to the <code>subpass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>"
         },
         {
           "vuid": "VUID-vkCmdDrawIndexedIndirectCount-None-02686",
@@ -17684,7 +18576,7 @@
       "(VK_VERSION_1_2,VK_KHR_draw_indirect_count)+(VK_NV_corner_sampled_image)": [
         {
           "vuid": "VUID-vkCmdDrawIndexedIndirectCount-flags-02696",
-          "text": " Any <a href=\"#VkImage\">VkImage</a> created with a <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>flags</code> containing <code>VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV</code> sampled as a result of this command <strong class=\"purple\">must</strong> only be sampled using a <a href=\"#VkSamplerAddressMode\">VkSamplerAddressMode</a> of <code>VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE</code>."
+          "text": " Any <a href=\"#VkImage\">VkImage</a> created with a <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>flags</code> containing <code>VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV</code> sampled as a result of this command <strong class=\"purple\">must</strong> only be sampled using a <a href=\"#VkSamplerAddressMode\">VkSamplerAddressMode</a> of <code>VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE</code>"
         }
       ],
       "(VK_VERSION_1_2,VK_KHR_draw_indirect_count)+(VK_VERSION_1_1)": [
@@ -17700,7 +18592,7 @@
       "(VK_VERSION_1_2,VK_KHR_draw_indirect_count)+(VK_VERSION_1_1,VK_KHR_multiview)": [
         {
           "vuid": "VUID-vkCmdDrawIndexedIndirectCount-maxMultiviewInstanceIndex-02688",
-          "text": " If the draw is recorded in a render pass instance with multiview enabled, the maximum instance index <strong class=\"purple\">must</strong> be less than or equal to <a href=\"#VkPhysicalDeviceMultiviewProperties\">VkPhysicalDeviceMultiviewProperties</a>::<code>maxMultiviewInstanceIndex</code>."
+          "text": " If the draw is recorded in a render pass instance with multiview enabled, the maximum instance index <strong class=\"purple\">must</strong> be less than or equal to <a href=\"#VkPhysicalDeviceMultiviewProperties\">VkPhysicalDeviceMultiviewProperties</a>::<code>maxMultiviewInstanceIndex</code>"
         }
       ],
       "(VK_VERSION_1_2,VK_KHR_draw_indirect_count)+(VK_EXT_sample_locations)": [
@@ -17766,11 +18658,11 @@
         },
         {
           "vuid": "VUID-vkCmdDrawIndirectByteCountEXT-renderPass-02684",
-          "text": " The current render pass <strong class=\"purple\">must</strong> be <a href=\"#renderpass-compatibility\">compatible</a> with the <code>renderPass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>."
+          "text": " The current render pass <strong class=\"purple\">must</strong> be <a href=\"#renderpass-compatibility\">compatible</a> with the <code>renderPass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>"
         },
         {
           "vuid": "VUID-vkCmdDrawIndirectByteCountEXT-subpass-02685",
-          "text": " The subpass index of the current render pass <strong class=\"purple\">must</strong> be equal to the <code>subpass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>."
+          "text": " The subpass index of the current render pass <strong class=\"purple\">must</strong> be equal to the <code>subpass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>"
         },
         {
           "vuid": "VUID-vkCmdDrawIndirectByteCountEXT-None-02686",
@@ -17854,7 +18746,7 @@
       "(VK_EXT_transform_feedback)+(VK_NV_corner_sampled_image)": [
         {
           "vuid": "VUID-vkCmdDrawIndirectByteCountEXT-flags-02696",
-          "text": " Any <a href=\"#VkImage\">VkImage</a> created with a <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>flags</code> containing <code>VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV</code> sampled as a result of this command <strong class=\"purple\">must</strong> only be sampled using a <a href=\"#VkSamplerAddressMode\">VkSamplerAddressMode</a> of <code>VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE</code>."
+          "text": " Any <a href=\"#VkImage\">VkImage</a> created with a <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>flags</code> containing <code>VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV</code> sampled as a result of this command <strong class=\"purple\">must</strong> only be sampled using a <a href=\"#VkSamplerAddressMode\">VkSamplerAddressMode</a> of <code>VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE</code>"
         }
       ],
       "(VK_EXT_transform_feedback)+(VK_VERSION_1_1)": [
@@ -17870,7 +18762,7 @@
       "(VK_EXT_transform_feedback)+(VK_VERSION_1_1,VK_KHR_multiview)": [
         {
           "vuid": "VUID-vkCmdDrawIndirectByteCountEXT-maxMultiviewInstanceIndex-02688",
-          "text": " If the draw is recorded in a render pass instance with multiview enabled, the maximum instance index <strong class=\"purple\">must</strong> be less than or equal to <a href=\"#VkPhysicalDeviceMultiviewProperties\">VkPhysicalDeviceMultiviewProperties</a>::<code>maxMultiviewInstanceIndex</code>."
+          "text": " If the draw is recorded in a render pass instance with multiview enabled, the maximum instance index <strong class=\"purple\">must</strong> be less than or equal to <a href=\"#VkPhysicalDeviceMultiviewProperties\">VkPhysicalDeviceMultiviewProperties</a>::<code>maxMultiviewInstanceIndex</code>"
         }
       ],
       "(VK_EXT_transform_feedback)+(VK_EXT_sample_locations)": [
@@ -17916,7 +18808,7 @@
         },
         {
           "vuid": "VUID-VkConditionalRenderingBeginInfoEXT-offset-01983",
-          "text": " <code>offset</code> <strong class=\"purple\">must</strong> be less than the size of <code>buffer</code> by at least 32 bits."
+          "text": " <code>offset</code> <strong class=\"purple\">must</strong> be less than the size of <code>buffer</code> by at least 32 bits"
         },
         {
           "vuid": "VUID-VkConditionalRenderingBeginInfoEXT-offset-01984",
@@ -18024,11 +18916,11 @@
         },
         {
           "vuid": "VUID-vkCmdDrawMeshTasksNV-renderPass-02684",
-          "text": " The current render pass <strong class=\"purple\">must</strong> be <a href=\"#renderpass-compatibility\">compatible</a> with the <code>renderPass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>."
+          "text": " The current render pass <strong class=\"purple\">must</strong> be <a href=\"#renderpass-compatibility\">compatible</a> with the <code>renderPass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>"
         },
         {
           "vuid": "VUID-vkCmdDrawMeshTasksNV-subpass-02685",
-          "text": " The subpass index of the current render pass <strong class=\"purple\">must</strong> be equal to the <code>subpass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>."
+          "text": " The subpass index of the current render pass <strong class=\"purple\">must</strong> be equal to the <code>subpass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>"
         },
         {
           "vuid": "VUID-vkCmdDrawMeshTasksNV-None-02686",
@@ -18084,7 +18976,7 @@
       "(VK_NV_mesh_shader)+(VK_NV_corner_sampled_image)": [
         {
           "vuid": "VUID-vkCmdDrawMeshTasksNV-flags-02696",
-          "text": " Any <a href=\"#VkImage\">VkImage</a> created with a <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>flags</code> containing <code>VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV</code> sampled as a result of this command <strong class=\"purple\">must</strong> only be sampled using a <a href=\"#VkSamplerAddressMode\">VkSamplerAddressMode</a> of <code>VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE</code>."
+          "text": " Any <a href=\"#VkImage\">VkImage</a> created with a <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>flags</code> containing <code>VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV</code> sampled as a result of this command <strong class=\"purple\">must</strong> only be sampled using a <a href=\"#VkSamplerAddressMode\">VkSamplerAddressMode</a> of <code>VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE</code>"
         }
       ],
       "(VK_NV_mesh_shader)+(VK_VERSION_1_1)": [
@@ -18096,7 +18988,7 @@
       "(VK_NV_mesh_shader)+(VK_VERSION_1_1,VK_KHR_multiview)": [
         {
           "vuid": "VUID-vkCmdDrawMeshTasksNV-maxMultiviewInstanceIndex-02688",
-          "text": " If the draw is recorded in a render pass instance with multiview enabled, the maximum instance index <strong class=\"purple\">must</strong> be less than or equal to <a href=\"#VkPhysicalDeviceMultiviewProperties\">VkPhysicalDeviceMultiviewProperties</a>::<code>maxMultiviewInstanceIndex</code>."
+          "text": " If the draw is recorded in a render pass instance with multiview enabled, the maximum instance index <strong class=\"purple\">must</strong> be less than or equal to <a href=\"#VkPhysicalDeviceMultiviewProperties\">VkPhysicalDeviceMultiviewProperties</a>::<code>maxMultiviewInstanceIndex</code>"
         }
       ],
       "(VK_NV_mesh_shader)+(VK_EXT_sample_locations)": [
@@ -18162,11 +19054,11 @@
         },
         {
           "vuid": "VUID-vkCmdDrawMeshTasksIndirectNV-renderPass-02684",
-          "text": " The current render pass <strong class=\"purple\">must</strong> be <a href=\"#renderpass-compatibility\">compatible</a> with the <code>renderPass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>."
+          "text": " The current render pass <strong class=\"purple\">must</strong> be <a href=\"#renderpass-compatibility\">compatible</a> with the <code>renderPass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>"
         },
         {
           "vuid": "VUID-vkCmdDrawMeshTasksIndirectNV-subpass-02685",
-          "text": " The subpass index of the current render pass <strong class=\"purple\">must</strong> be equal to the <code>subpass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>."
+          "text": " The subpass index of the current render pass <strong class=\"purple\">must</strong> be equal to the <code>subpass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>"
         },
         {
           "vuid": "VUID-vkCmdDrawMeshTasksIndirectNV-None-02686",
@@ -18258,7 +19150,7 @@
       "(VK_NV_mesh_shader)+(VK_NV_corner_sampled_image)": [
         {
           "vuid": "VUID-vkCmdDrawMeshTasksIndirectNV-flags-02696",
-          "text": " Any <a href=\"#VkImage\">VkImage</a> created with a <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>flags</code> containing <code>VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV</code> sampled as a result of this command <strong class=\"purple\">must</strong> only be sampled using a <a href=\"#VkSamplerAddressMode\">VkSamplerAddressMode</a> of <code>VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE</code>."
+          "text": " Any <a href=\"#VkImage\">VkImage</a> created with a <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>flags</code> containing <code>VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV</code> sampled as a result of this command <strong class=\"purple\">must</strong> only be sampled using a <a href=\"#VkSamplerAddressMode\">VkSamplerAddressMode</a> of <code>VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE</code>"
         }
       ],
       "(VK_NV_mesh_shader)+(VK_VERSION_1_1)": [
@@ -18274,7 +19166,7 @@
       "(VK_NV_mesh_shader)+(VK_VERSION_1_1,VK_KHR_multiview)": [
         {
           "vuid": "VUID-vkCmdDrawMeshTasksIndirectNV-maxMultiviewInstanceIndex-02688",
-          "text": " If the draw is recorded in a render pass instance with multiview enabled, the maximum instance index <strong class=\"purple\">must</strong> be less than or equal to <a href=\"#VkPhysicalDeviceMultiviewProperties\">VkPhysicalDeviceMultiviewProperties</a>::<code>maxMultiviewInstanceIndex</code>."
+          "text": " If the draw is recorded in a render pass instance with multiview enabled, the maximum instance index <strong class=\"purple\">must</strong> be less than or equal to <a href=\"#VkPhysicalDeviceMultiviewProperties\">VkPhysicalDeviceMultiviewProperties</a>::<code>maxMultiviewInstanceIndex</code>"
         }
       ],
       "(VK_NV_mesh_shader)+(VK_EXT_sample_locations)": [
@@ -18348,11 +19240,11 @@
         },
         {
           "vuid": "VUID-vkCmdDrawMeshTasksIndirectCountNV-renderPass-02684",
-          "text": " The current render pass <strong class=\"purple\">must</strong> be <a href=\"#renderpass-compatibility\">compatible</a> with the <code>renderPass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>."
+          "text": " The current render pass <strong class=\"purple\">must</strong> be <a href=\"#renderpass-compatibility\">compatible</a> with the <code>renderPass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>"
         },
         {
           "vuid": "VUID-vkCmdDrawMeshTasksIndirectCountNV-subpass-02685",
-          "text": " The subpass index of the current render pass <strong class=\"purple\">must</strong> be equal to the <code>subpass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>."
+          "text": " The subpass index of the current render pass <strong class=\"purple\">must</strong> be equal to the <code>subpass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>"
         },
         {
           "vuid": "VUID-vkCmdDrawMeshTasksIndirectCountNV-None-02686",
@@ -18460,7 +19352,7 @@
       "(VK_NV_mesh_shader)+(VK_NV_corner_sampled_image)": [
         {
           "vuid": "VUID-vkCmdDrawMeshTasksIndirectCountNV-flags-02696",
-          "text": " Any <a href=\"#VkImage\">VkImage</a> created with a <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>flags</code> containing <code>VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV</code> sampled as a result of this command <strong class=\"purple\">must</strong> only be sampled using a <a href=\"#VkSamplerAddressMode\">VkSamplerAddressMode</a> of <code>VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE</code>."
+          "text": " Any <a href=\"#VkImage\">VkImage</a> created with a <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>flags</code> containing <code>VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV</code> sampled as a result of this command <strong class=\"purple\">must</strong> only be sampled using a <a href=\"#VkSamplerAddressMode\">VkSamplerAddressMode</a> of <code>VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE</code>"
         }
       ],
       "(VK_NV_mesh_shader)+(VK_VERSION_1_1)": [
@@ -18476,7 +19368,7 @@
       "(VK_NV_mesh_shader)+(VK_VERSION_1_1,VK_KHR_multiview)": [
         {
           "vuid": "VUID-vkCmdDrawMeshTasksIndirectCountNV-maxMultiviewInstanceIndex-02688",
-          "text": " If the draw is recorded in a render pass instance with multiview enabled, the maximum instance index <strong class=\"purple\">must</strong> be less than or equal to <a href=\"#VkPhysicalDeviceMultiviewProperties\">VkPhysicalDeviceMultiviewProperties</a>::<code>maxMultiviewInstanceIndex</code>."
+          "text": " If the draw is recorded in a render pass instance with multiview enabled, the maximum instance index <strong class=\"purple\">must</strong> be less than or equal to <a href=\"#VkPhysicalDeviceMultiviewProperties\">VkPhysicalDeviceMultiviewProperties</a>::<code>maxMultiviewInstanceIndex</code>"
         }
       ],
       "(VK_NV_mesh_shader)+(VK_EXT_sample_locations)": [
@@ -18658,11 +19550,11 @@
         },
         {
           "vuid": "VUID-VkVertexInputBindingDivisorDescriptionEXT-divisor-01870",
-          "text": " <code>divisor</code> <strong class=\"purple\">must</strong> be a value between <code>0</code> and <code>VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT</code>::<code>maxVertexAttribDivisor</code>, inclusive."
+          "text": " <code>divisor</code> <strong class=\"purple\">must</strong> be a value between <code>0</code> and <code>VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT</code>::<code>maxVertexAttribDivisor</code>, inclusive"
         },
         {
           "vuid": "VUID-VkVertexInputBindingDivisorDescriptionEXT-inputRate-01871",
-          "text": " <a href=\"#VkVertexInputBindingDescription\">VkVertexInputBindingDescription</a>::<code>inputRate</code> <strong class=\"purple\">must</strong> be of type <code>VK_VERTEX_INPUT_RATE_INSTANCE</code> for this <code>binding</code>."
+          "text": " <a href=\"#VkVertexInputBindingDescription\">VkVertexInputBindingDescription</a>::<code>inputRate</code> <strong class=\"purple\">must</strong> be of type <code>VK_VERTEX_INPUT_RATE_INSTANCE</code> for this <code>binding</code>"
         }
       ]
     },
@@ -19392,7 +20284,7 @@
         },
         {
           "vuid": "VUID-VkPipelineViewportShadingRateImageStateCreateInfoNV-shadingRateImageEnable-02056",
-          "text": " If <code>shadingRateImageEnable</code> is <code>VK_TRUE</code>, <code>viewportCount</code> <strong class=\"purple\">must</strong> be equal to the <code>viewportCount</code> member of <code>VkPipelineViewportStateCreateInfo</code>"
+          "text": " If <code>shadingRateImageEnable</code> is <code>VK_TRUE</code>, <code>viewportCount</code> <strong class=\"purple\">must</strong> be equal to the <code>viewportCount</code> member of <a href=\"#VkPipelineViewportStateCreateInfo\">VkPipelineViewportStateCreateInfo</a>"
         },
         {
           "vuid": "VUID-VkPipelineViewportShadingRateImageStateCreateInfoNV-pDynamicStates-02057",
@@ -19412,15 +20304,15 @@
       "(VK_NV_shading_rate_image)": [
         {
           "vuid": "VUID-vkCmdBindShadingRateImageNV-None-02058",
-          "text": " The <a href=\"#features-shadingRateImage\">shading rate image</a> feature <strong class=\"purple\">must</strong> be enabled."
+          "text": " The <a href=\"#features-shadingRateImage\">shading rate image</a> feature <strong class=\"purple\">must</strong> be enabled"
         },
         {
           "vuid": "VUID-vkCmdBindShadingRateImageNV-imageView-02059",
-          "text": " If <code>imageView</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, it <strong class=\"purple\">must</strong> be a valid <a href=\"#VkImageView\">VkImageView</a> handle of type <code>VK_IMAGE_VIEW_TYPE_2D</code> or <code>VK_IMAGE_VIEW_TYPE_2D_ARRAY</code>."
+          "text": " If <code>imageView</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, it <strong class=\"purple\">must</strong> be a valid <a href=\"#VkImageView\">VkImageView</a> handle of type <code>VK_IMAGE_VIEW_TYPE_2D</code> or <code>VK_IMAGE_VIEW_TYPE_2D_ARRAY</code>"
         },
         {
           "vuid": "VUID-vkCmdBindShadingRateImageNV-imageView-02060",
-          "text": " If <code>imageView</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, it <strong class=\"purple\">must</strong> have a format of <code>VK_FORMAT_R8_UINT</code>."
+          "text": " If <code>imageView</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, it <strong class=\"purple\">must</strong> have a format of <code>VK_FORMAT_R8_UINT</code>"
         },
         {
           "vuid": "VUID-vkCmdBindShadingRateImageNV-imageView-02061",
@@ -19428,11 +20320,11 @@
         },
         {
           "vuid": "VUID-vkCmdBindShadingRateImageNV-imageView-02062",
-          "text": " If <code>imageView</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, <code>imageLayout</code> <strong class=\"purple\">must</strong> match the actual <a href=\"#VkImageLayout\">VkImageLayout</a> of each subresource accessible from <code>imageView</code> at the time the subresource is accessed."
+          "text": " If <code>imageView</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, <code>imageLayout</code> <strong class=\"purple\">must</strong> match the actual <a href=\"#VkImageLayout\">VkImageLayout</a> of each subresource accessible from <code>imageView</code> at the time the subresource is accessed"
         },
         {
           "vuid": "VUID-vkCmdBindShadingRateImageNV-imageLayout-02063",
-          "text": " If <code>imageView</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, <code>imageLayout</code> <strong class=\"purple\">must</strong> be <code>VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV</code> or <code>VK_IMAGE_LAYOUT_GENERAL</code>."
+          "text": " If <code>imageView</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, <code>imageLayout</code> <strong class=\"purple\">must</strong> be <code>VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV</code> or <code>VK_IMAGE_LAYOUT_GENERAL</code>"
         },
         {
           "vuid": "VUID-vkCmdBindShadingRateImageNV-commandBuffer-parameter",
@@ -19464,7 +20356,7 @@
       "(VK_NV_shading_rate_image)": [
         {
           "vuid": "VUID-vkCmdSetViewportShadingRatePaletteNV-None-02064",
-          "text": " The <a href=\"#features-shadingRateImage\">shading rate image</a> feature <strong class=\"purple\">must</strong> be enabled."
+          "text": " The <a href=\"#features-shadingRateImage\">shading rate image</a> feature <strong class=\"purple\">must</strong> be enabled"
         },
         {
           "vuid": "VUID-vkCmdSetViewportShadingRatePaletteNV-firstViewport-02066",
@@ -19528,7 +20420,7 @@
         },
         {
           "vuid": "VUID-VkPipelineViewportCoarseSampleOrderStateCreateInfoNV-pCustomSampleOrders-02234",
-          "text": " The array <code>pCustomSampleOrders</code> <strong class=\"purple\">must</strong> not contain two structures with matching values for both the <code>shadingRate</code> and <code>sampleCount</code> members."
+          "text": " The array <code>pCustomSampleOrders</code> <strong class=\"purple\">must</strong> not contain two structures with matching values for both the <code>shadingRate</code> and <code>sampleCount</code> members"
         },
         {
           "vuid": "VUID-VkPipelineViewportCoarseSampleOrderStateCreateInfoNV-sType-sType",
@@ -19548,23 +20440,23 @@
       "(VK_NV_shading_rate_image)": [
         {
           "vuid": "VUID-VkCoarseSampleOrderCustomNV-shadingRate-02073",
-          "text": " <code>shadingRate</code> <strong class=\"purple\">must</strong> be a shading rate that generates fragments with more than one pixel."
+          "text": " <code>shadingRate</code> <strong class=\"purple\">must</strong> be a shading rate that generates fragments with more than one pixel"
         },
         {
           "vuid": "VUID-VkCoarseSampleOrderCustomNV-sampleCount-02074",
-          "text": " <code>sampleCount</code> <strong class=\"purple\">must</strong> correspond to a sample count enumerated in <a href=\"#VkSampleCountFlags\">VkSampleCountFlags</a> whose corresponding bit is set in <a href=\"#VkPhysicalDeviceLimits\">VkPhysicalDeviceLimits</a>::<code>framebufferNoAttachmentsSampleCounts</code>."
+          "text": " <code>sampleCount</code> <strong class=\"purple\">must</strong> correspond to a sample count enumerated in <a href=\"#VkSampleCountFlags\">VkSampleCountFlags</a> whose corresponding bit is set in <a href=\"#VkPhysicalDeviceLimits\">VkPhysicalDeviceLimits</a>::<code>framebufferNoAttachmentsSampleCounts</code>"
         },
         {
           "vuid": "VUID-VkCoarseSampleOrderCustomNV-sampleLocationCount-02075",
-          "text": " <code>sampleLocationCount</code> <strong class=\"purple\">must</strong> be equal to the product of <code>sampleCount</code>, the fragment width for <code>shadingRate</code>, and the fragment height for <code>shadingRate</code>."
+          "text": " <code>sampleLocationCount</code> <strong class=\"purple\">must</strong> be equal to the product of <code>sampleCount</code>, the fragment width for <code>shadingRate</code>, and the fragment height for <code>shadingRate</code>"
         },
         {
           "vuid": "VUID-VkCoarseSampleOrderCustomNV-sampleLocationCount-02076",
-          "text": " <code>sampleLocationCount</code> <strong class=\"purple\">must</strong> be less than or equal to the value of <code>VkPhysicalDeviceShadingRateImagePropertiesNV</code>::<code>shadingRateMaxCoarseSamples</code>."
+          "text": " <code>sampleLocationCount</code> <strong class=\"purple\">must</strong> be less than or equal to the value of <code>VkPhysicalDeviceShadingRateImagePropertiesNV</code>::<code>shadingRateMaxCoarseSamples</code>"
         },
         {
           "vuid": "VUID-VkCoarseSampleOrderCustomNV-pSampleLocations-02077",
-          "text": " The array <code>pSampleLocations</code> <strong class=\"purple\">must</strong> contain exactly one entry for every combination of valid values for <code>pixelX</code>, <code>pixelY</code>, and <code>sample</code> in the structure <a href=\"#VkCoarseSampleOrderCustomNV\">VkCoarseSampleOrderCustomNV</a>."
+          "text": " The array <code>pSampleLocations</code> <strong class=\"purple\">must</strong> contain exactly one entry for every combination of valid values for <code>pixelX</code>, <code>pixelY</code>, and <code>sample</code> in the structure <a href=\"#VkCoarseSampleOrderCustomNV\">VkCoarseSampleOrderCustomNV</a>"
         },
         {
           "vuid": "VUID-VkCoarseSampleOrderCustomNV-shadingRate-parameter",
@@ -19584,15 +20476,15 @@
       "(VK_NV_shading_rate_image)": [
         {
           "vuid": "VUID-VkCoarseSampleLocationNV-pixelX-02078",
-          "text": " <code>pixelX</code> <strong class=\"purple\">must</strong> be less than the width (in pixels) of the fragment."
+          "text": " <code>pixelX</code> <strong class=\"purple\">must</strong> be less than the width (in pixels) of the fragment"
         },
         {
           "vuid": "VUID-VkCoarseSampleLocationNV-pixelY-02079",
-          "text": " <code>pixelY</code> <strong class=\"purple\">must</strong> be less than the height (in pixels) of the fragment."
+          "text": " <code>pixelY</code> <strong class=\"purple\">must</strong> be less than the height (in pixels) of the fragment"
         },
         {
           "vuid": "VUID-VkCoarseSampleLocationNV-sample-02080",
-          "text": " <code>sample</code> <strong class=\"purple\">must</strong> be less than the number of coverage samples in each pixel belonging to the fragment."
+          "text": " <code>sample</code> <strong class=\"purple\">must</strong> be less than the number of coverage samples in each pixel belonging to the fragment"
         }
       ]
     },
@@ -19872,7 +20764,7 @@
         },
         {
           "vuid": "VUID-VkPipelineViewportExclusiveScissorStateCreateInfoNV-exclusiveScissorCount-02029",
-          "text": " <code>exclusiveScissorCount</code> <strong class=\"purple\">must</strong> be <code>0</code> or identical to the <code>viewportCount</code> member of <code>VkPipelineViewportStateCreateInfo</code>"
+          "text": " <code>exclusiveScissorCount</code> <strong class=\"purple\">must</strong> be <code>0</code> or identical to the <code>viewportCount</code> member of <a href=\"#VkPipelineViewportStateCreateInfo\">VkPipelineViewportStateCreateInfo</a>"
         },
         {
           "vuid": "VUID-VkPipelineViewportExclusiveScissorStateCreateInfoNV-pDynamicStates-02030",
@@ -19892,7 +20784,7 @@
       "(VK_NV_scissor_exclusive)": [
         {
           "vuid": "VUID-vkCmdSetExclusiveScissorNV-None-02031",
-          "text": " The <a href=\"#features-exclusiveScissor\">exclusive scissor</a> feature <strong class=\"purple\">must</strong> be enabled."
+          "text": " The <a href=\"#features-exclusiveScissor\">exclusive scissor</a> feature <strong class=\"purple\">must</strong> be enabled"
         },
         {
           "vuid": "VUID-vkCmdSetExclusiveScissorNV-firstExclusiveScissor-02033",
@@ -20282,11 +21174,11 @@
         },
         {
           "vuid": "VUID-VkPipelineColorBlendAttachmentState-advancedBlendIndependentBlend-01407",
-          "text": " If <a href=\"#VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT\">VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT</a>::<code>advancedBlendIndependentBlend</code> is <code>VK_FALSE</code> and <code>colorBlendOp</code> is an <a href=\"#framebuffer-blend-advanced\">advanced blend operation</a>, then <code>colorBlendOp</code> <strong class=\"purple\">must</strong> be the same for all attachments."
+          "text": " If <a href=\"#VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT\">VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT</a>::<code>advancedBlendIndependentBlend</code> is <code>VK_FALSE</code> and <code>colorBlendOp</code> is an <a href=\"#framebuffer-blend-advanced\">advanced blend operation</a>, then <code>colorBlendOp</code> <strong class=\"purple\">must</strong> be the same for all attachments"
         },
         {
           "vuid": "VUID-VkPipelineColorBlendAttachmentState-advancedBlendIndependentBlend-01408",
-          "text": " If <a href=\"#VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT\">VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT</a>::<code>advancedBlendIndependentBlend</code> is <code>VK_FALSE</code> and <code>alphaBlendOp</code> is an <a href=\"#framebuffer-blend-advanced\">advanced blend operation</a>, then <code>alphaBlendOp</code> <strong class=\"purple\">must</strong> be the same for all attachments."
+          "text": " If <a href=\"#VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT\">VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT</a>::<code>advancedBlendIndependentBlend</code> is <code>VK_FALSE</code> and <code>alphaBlendOp</code> is an <a href=\"#framebuffer-blend-advanced\">advanced blend operation</a>, then <code>alphaBlendOp</code> <strong class=\"purple\">must</strong> be the same for all attachments"
         },
         {
           "vuid": "VUID-VkPipelineColorBlendAttachmentState-advancedBlendAllOperations-01409",
@@ -20446,7 +21338,7 @@
       "(VK_NV_corner_sampled_image)": [
         {
           "vuid": "VUID-vkCmdDispatch-flags-02696",
-          "text": " Any <a href=\"#VkImage\">VkImage</a> created with a <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>flags</code> containing <code>VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV</code> sampled as a result of this command <strong class=\"purple\">must</strong> only be sampled using a <a href=\"#VkSamplerAddressMode\">VkSamplerAddressMode</a> of <code>VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE</code>."
+          "text": " Any <a href=\"#VkImage\">VkImage</a> created with a <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>flags</code> containing <code>VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV</code> sampled as a result of this command <strong class=\"purple\">must</strong> only be sampled using a <a href=\"#VkSamplerAddressMode\">VkSamplerAddressMode</a> of <code>VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE</code>"
         }
       ],
       "(VK_VERSION_1_1)": [
@@ -20584,7 +21476,7 @@
       "(VK_NV_corner_sampled_image)": [
         {
           "vuid": "VUID-vkCmdDispatchIndirect-flags-02696",
-          "text": " Any <a href=\"#VkImage\">VkImage</a> created with a <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>flags</code> containing <code>VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV</code> sampled as a result of this command <strong class=\"purple\">must</strong> only be sampled using a <a href=\"#VkSamplerAddressMode\">VkSamplerAddressMode</a> of <code>VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE</code>."
+          "text": " Any <a href=\"#VkImage\">VkImage</a> created with a <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>flags</code> containing <code>VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV</code> sampled as a result of this command <strong class=\"purple\">must</strong> only be sampled using a <a href=\"#VkSamplerAddressMode\">VkSamplerAddressMode</a> of <code>VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE</code>"
         }
       ],
       "(VK_VERSION_1_1)": [
@@ -20694,7 +21586,7 @@
         },
         {
           "vuid": "VUID-vkCmdDispatchBase-baseGroupX-00427",
-          "text": " If any of <code>baseGroupX</code>, <code>baseGroupY</code>, or <code>baseGroupZ</code> are not zero, then the bound compute pipeline <strong class=\"purple\">must</strong> have been created with the <code>VK_PIPELINE_CREATE_DISPATCH_BASE</code> flag."
+          "text": " If any of <code>baseGroupX</code>, <code>baseGroupY</code>, or <code>baseGroupZ</code> are not zero, then the bound compute pipeline <strong class=\"purple\">must</strong> have been created with the <code>VK_PIPELINE_CREATE_DISPATCH_BASE</code> flag"
         },
         {
           "vuid": "VUID-vkCmdDispatchBase-commandBuffer-parameter",
@@ -20738,7 +21630,7 @@
       "(VK_VERSION_1_1,VK_KHR_device_group)+(VK_NV_corner_sampled_image)": [
         {
           "vuid": "VUID-vkCmdDispatchBase-flags-02696",
-          "text": " Any <a href=\"#VkImage\">VkImage</a> created with a <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>flags</code> containing <code>VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV</code> sampled as a result of this command <strong class=\"purple\">must</strong> only be sampled using a <a href=\"#VkSamplerAddressMode\">VkSamplerAddressMode</a> of <code>VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE</code>."
+          "text": " Any <a href=\"#VkImage\">VkImage</a> created with a <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>flags</code> containing <code>VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV</code> sampled as a result of this command <strong class=\"purple\">must</strong> only be sampled using a <a href=\"#VkSamplerAddressMode\">VkSamplerAddressMode</a> of <code>VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE</code>"
         }
       ],
       "(VK_VERSION_1_1,VK_KHR_device_group)+(VK_VERSION_1_1)": [
@@ -20748,711 +21640,657 @@
         }
       ]
     },
-    "vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX": {
-      "(VK_NVX_device_generated_commands)": [
+    "vkCreateIndirectCommandsLayoutNV": {
+      "(VK_NV_device_generated_commands)": [
         {
-          "vuid": "VUID-vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX-physicalDevice-parameter",
-          "text": " <code>physicalDevice</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkPhysicalDevice\">VkPhysicalDevice</a> handle"
+          "vuid": "VUID-vkCreateIndirectCommandsLayoutNV-deviceGeneratedCommands-02929",
+          "text": " The <a href=\"#feature-device-generated-commands\"><code>VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV</code>::<code>deviceGeneratedCommands</code></a> feature <strong class=\"purple\">must</strong> be enabled"
         },
         {
-          "vuid": "VUID-vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX-pFeatures-parameter",
-          "text": " <code>pFeatures</code> <strong class=\"purple\">must</strong> be a valid pointer to a <a href=\"#VkDeviceGeneratedCommandsFeaturesNVX\">VkDeviceGeneratedCommandsFeaturesNVX</a> structure"
-        },
-        {
-          "vuid": "VUID-vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX-pLimits-parameter",
-          "text": " <code>pLimits</code> <strong class=\"purple\">must</strong> be a valid pointer to a <a href=\"#VkDeviceGeneratedCommandsLimitsNVX\">VkDeviceGeneratedCommandsLimitsNVX</a> structure"
-        }
-      ]
-    },
-    "VkDeviceGeneratedCommandsFeaturesNVX": {
-      "(VK_NVX_device_generated_commands)": [
-        {
-          "vuid": "VUID-VkDeviceGeneratedCommandsFeaturesNVX-sType-sType",
-          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_FEATURES_NVX</code>"
-        },
-        {
-          "vuid": "VUID-VkDeviceGeneratedCommandsFeaturesNVX-pNext-pNext",
-          "text": " <code>pNext</code> <strong class=\"purple\">must</strong> be <code>NULL</code>"
-        }
-      ]
-    },
-    "VkDeviceGeneratedCommandsLimitsNVX": {
-      "(VK_NVX_device_generated_commands)": [
-        {
-          "vuid": "VUID-VkDeviceGeneratedCommandsLimitsNVX-sType-sType",
-          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_LIMITS_NVX</code>"
-        },
-        {
-          "vuid": "VUID-VkDeviceGeneratedCommandsLimitsNVX-pNext-pNext",
-          "text": " <code>pNext</code> <strong class=\"purple\">must</strong> be <code>NULL</code>"
-        }
-      ]
-    },
-    "vkCreateObjectTableNVX": {
-      "(VK_NVX_device_generated_commands)": [
-        {
-          "vuid": "VUID-vkCreateObjectTableNVX-device-parameter",
+          "vuid": "VUID-vkCreateIndirectCommandsLayoutNV-device-parameter",
           "text": " <code>device</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDevice\">VkDevice</a> handle"
         },
         {
-          "vuid": "VUID-vkCreateObjectTableNVX-pCreateInfo-parameter",
-          "text": " <code>pCreateInfo</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkObjectTableCreateInfoNVX\">VkObjectTableCreateInfoNVX</a> structure"
+          "vuid": "VUID-vkCreateIndirectCommandsLayoutNV-pCreateInfo-parameter",
+          "text": " <code>pCreateInfo</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkIndirectCommandsLayoutCreateInfoNV\">VkIndirectCommandsLayoutCreateInfoNV</a> structure"
         },
         {
-          "vuid": "VUID-vkCreateObjectTableNVX-pAllocator-parameter",
+          "vuid": "VUID-vkCreateIndirectCommandsLayoutNV-pAllocator-parameter",
           "text": " If <code>pAllocator</code> is not <code>NULL</code>, <code>pAllocator</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkAllocationCallbacks\">VkAllocationCallbacks</a> structure"
         },
         {
-          "vuid": "VUID-vkCreateObjectTableNVX-pObjectTable-parameter",
-          "text": " <code>pObjectTable</code> <strong class=\"purple\">must</strong> be a valid pointer to a <a href=\"#VkObjectTableNVX\">VkObjectTableNVX</a> handle"
+          "vuid": "VUID-vkCreateIndirectCommandsLayoutNV-pIndirectCommandsLayout-parameter",
+          "text": " <code>pIndirectCommandsLayout</code> <strong class=\"purple\">must</strong> be a valid pointer to a <a href=\"#VkIndirectCommandsLayoutNV\">VkIndirectCommandsLayoutNV</a> handle"
         }
       ]
     },
-    "VkObjectTableCreateInfoNVX": {
-      "(VK_NVX_device_generated_commands)": [
+    "VkIndirectCommandsLayoutCreateInfoNV": {
+      "(VK_NV_device_generated_commands)": [
         {
-          "vuid": "VUID-VkObjectTableCreateInfoNVX-computeBindingPointSupport-01355",
-          "text": " If the <code>VkDeviceGeneratedCommandsFeaturesNVX</code>::<code>computeBindingPointSupport</code> feature is not enabled, <code>pObjectEntryUsageFlags</code> <strong class=\"purple\">must</strong> not contain <code>VK_OBJECT_ENTRY_USAGE_COMPUTE_BIT_NVX</code>"
+          "vuid": "VUID-VkIndirectCommandsLayoutCreateInfoNV-pipelineBindPoint-02930",
+          "text": " The <code>pipelineBindPoint</code> <strong class=\"purple\">must</strong> be <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>"
         },
         {
-          "vuid": "VUID-VkObjectTableCreateInfoNVX-pObjectEntryCounts-01356",
-          "text": " Any value within <code>pObjectEntryCounts</code> <strong class=\"purple\">must</strong> not exceed <code>VkDeviceGeneratedCommandsLimitsNVX</code>::<code>maxObjectEntryCounts</code>"
+          "vuid": "VUID-VkIndirectCommandsLayoutCreateInfoNV-tokenCount-02931",
+          "text": " <code>tokenCount</code> <strong class=\"purple\">must</strong> be greater than <code>0</code> and less than or equal to <code>VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV</code>::<code>maxIndirectCommandsTokenCount</code>"
         },
         {
-          "vuid": "VUID-VkObjectTableCreateInfoNVX-maxUniformBuffersPerDescriptor-01357",
-          "text": " <code>maxUniformBuffersPerDescriptor</code> <strong class=\"purple\">must</strong> be within the limits supported by the device."
+          "vuid": "VUID-VkIndirectCommandsLayoutCreateInfoNV-pTokens-02932",
+          "text": " If <code>pTokens</code> contains an entry of <code>VK_INDIRECT_COMMANDS_TOKEN_TYPE_SHADER_GROUP_NV</code> it <strong class=\"purple\">must</strong> be the first element of the array and there <strong class=\"purple\">must</strong> be only a single element of such token type"
         },
         {
-          "vuid": "VUID-VkObjectTableCreateInfoNVX-maxStorageBuffersPerDescriptor-01358",
-          "text": " <code>maxStorageBuffersPerDescriptor</code> <strong class=\"purple\">must</strong> be within the limits supported by the device."
+          "vuid": "VUID-VkIndirectCommandsLayoutCreateInfoNV-pTokens-02933",
+          "text": " If <code>pTokens</code> contains an entry of <code>VK_INDIRECT_COMMANDS_TOKEN_TYPE_STATE_FLAGS_NV</code> there <strong class=\"purple\">must</strong> be only a single element of such token type"
         },
         {
-          "vuid": "VUID-VkObjectTableCreateInfoNVX-maxStorageImagesPerDescriptor-01359",
-          "text": " <code>maxStorageImagesPerDescriptor</code> <strong class=\"purple\">must</strong> be within the limits supported by the device."
+          "vuid": "VUID-VkIndirectCommandsLayoutCreateInfoNV-pTokens-02934",
+          "text": " All state tokens in <code>pTokens</code> <strong class=\"purple\">must</strong> occur prior work provoking tokens (<code>VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NV</code>, <code>VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NV</code>, <code>VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_TASKS_NV</code>)"
         },
         {
-          "vuid": "VUID-VkObjectTableCreateInfoNVX-maxSampledImagesPerDescriptor-01360",
-          "text": " <code>maxSampledImagesPerDescriptor</code> <strong class=\"purple\">must</strong> be within the limits supported by the device."
+          "vuid": "VUID-VkIndirectCommandsLayoutCreateInfoNV-pTokens-02935",
+          "text": " The content of <code>pTokens</code> <strong class=\"purple\">must</strong> include one single work provoking token that is compatible with the <code>pipelineBindPoint</code>"
         },
         {
-          "vuid": "VUID-VkObjectTableCreateInfoNVX-sType-sType",
-          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_OBJECT_TABLE_CREATE_INFO_NVX</code>"
+          "vuid": "VUID-VkIndirectCommandsLayoutCreateInfoNV-streamCount-02936",
+          "text": " <code>streamCount</code> <strong class=\"purple\">must</strong> be greater than <code>0</code> and less or equal to <code>VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV</code>::<code>maxIndirectCommandsStreamCount</code>"
         },
         {
-          "vuid": "VUID-VkObjectTableCreateInfoNVX-pNext-pNext",
+          "vuid": "VUID-VkIndirectCommandsLayoutCreateInfoNV-pStreamStrides-02937",
+          "text": " each element of <code>pStreamStrides</code> <strong class=\"purple\">must</strong> be greater than `0`and less than or equal to <code>VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV</code>::<code>maxIndirectCommandsStreamStride</code>. Furthermore the alignment of each token input <strong class=\"purple\">must</strong> be ensured"
+        },
+        {
+          "vuid": "VUID-VkIndirectCommandsLayoutCreateInfoNV-sType-sType",
+          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NV</code>"
+        },
+        {
+          "vuid": "VUID-VkIndirectCommandsLayoutCreateInfoNV-pNext-pNext",
           "text": " <code>pNext</code> <strong class=\"purple\">must</strong> be <code>NULL</code>"
         },
         {
-          "vuid": "VUID-VkObjectTableCreateInfoNVX-pObjectEntryTypes-parameter",
-          "text": " <code>pObjectEntryTypes</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>objectCount</code> valid <a href=\"#VkObjectEntryTypeNVX\">VkObjectEntryTypeNVX</a> values"
+          "vuid": "VUID-VkIndirectCommandsLayoutCreateInfoNV-flags-parameter",
+          "text": " <code>flags</code> <strong class=\"purple\">must</strong> be a valid combination of <a href=\"#VkIndirectCommandsLayoutUsageFlagBitsNV\">VkIndirectCommandsLayoutUsageFlagBitsNV</a> values"
         },
         {
-          "vuid": "VUID-VkObjectTableCreateInfoNVX-pObjectEntryCounts-parameter",
-          "text": " <code>pObjectEntryCounts</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>objectCount</code> <code>uint32_t</code> values"
-        },
-        {
-          "vuid": "VUID-VkObjectTableCreateInfoNVX-pObjectEntryUsageFlags-parameter",
-          "text": " <code>pObjectEntryUsageFlags</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>objectCount</code> valid combinations of <a href=\"#VkObjectEntryUsageFlagBitsNVX\">VkObjectEntryUsageFlagBitsNVX</a> values"
-        },
-        {
-          "vuid": "VUID-VkObjectTableCreateInfoNVX-pObjectEntryUsageFlags-requiredbitmask",
-          "text": " Each element of <code>pObjectEntryUsageFlags</code> <strong class=\"purple\">must</strong> not be <code>0</code>"
-        },
-        {
-          "vuid": "VUID-VkObjectTableCreateInfoNVX-objectCount-arraylength",
-          "text": " <code>objectCount</code> <strong class=\"purple\">must</strong> be greater than <code>0</code>"
-        }
-      ]
-    },
-    "vkDestroyObjectTableNVX": {
-      "(VK_NVX_device_generated_commands)": [
-        {
-          "vuid": "VUID-vkDestroyObjectTableNVX-objectTable-01361",
-          "text": " All submitted commands that refer to <code>objectTable</code> <strong class=\"purple\">must</strong> have completed execution."
-        },
-        {
-          "vuid": "VUID-vkDestroyObjectTableNVX-objectTable-01362",
-          "text": " If <code>VkAllocationCallbacks</code> were provided when <code>objectTable</code> was created, a compatible set of callbacks <strong class=\"purple\">must</strong> be provided here."
-        },
-        {
-          "vuid": "VUID-vkDestroyObjectTableNVX-objectTable-01363",
-          "text": " If no <code>VkAllocationCallbacks</code> were provided when <code>objectTable</code> was created, <code>pAllocator</code> <strong class=\"purple\">must</strong> be <code>NULL</code>."
-        },
-        {
-          "vuid": "VUID-vkDestroyObjectTableNVX-device-parameter",
-          "text": " <code>device</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDevice\">VkDevice</a> handle"
-        },
-        {
-          "vuid": "VUID-vkDestroyObjectTableNVX-objectTable-parameter",
-          "text": " <code>objectTable</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkObjectTableNVX\">VkObjectTableNVX</a> handle"
-        },
-        {
-          "vuid": "VUID-vkDestroyObjectTableNVX-pAllocator-parameter",
-          "text": " If <code>pAllocator</code> is not <code>NULL</code>, <code>pAllocator</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkAllocationCallbacks\">VkAllocationCallbacks</a> structure"
-        },
-        {
-          "vuid": "VUID-vkDestroyObjectTableNVX-objectTable-parent",
-          "text": " <code>objectTable</code> <strong class=\"purple\">must</strong> have been created, allocated, or retrieved from <code>device</code>"
-        }
-      ]
-    },
-    "vkRegisterObjectsNVX": {
-      "(VK_NVX_device_generated_commands)": [
-        {
-          "vuid": "VUID-vkRegisterObjectsNVX-pObjectTableEntry-01364",
-          "text": " The contents of <code>pObjectTableEntry</code> <strong class=\"purple\">must</strong> yield plausible bindings supported by the device."
-        },
-        {
-          "vuid": "VUID-vkRegisterObjectsNVX-pObjectIndices-01365",
-          "text": " At any <code>pObjectIndices</code> there <strong class=\"purple\">must</strong> not be a registered resource already."
-        },
-        {
-          "vuid": "VUID-vkRegisterObjectsNVX-pObjectIndices-01366",
-          "text": " Any value inside <code>pObjectIndices</code> <strong class=\"purple\">must</strong> be below the appropriate <code>VkObjectTableCreateInfoNVX</code>::<code>pObjectEntryCounts</code> limits provided at <code>objectTable</code> creation time."
-        },
-        {
-          "vuid": "VUID-vkRegisterObjectsNVX-device-parameter",
-          "text": " <code>device</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDevice\">VkDevice</a> handle"
-        },
-        {
-          "vuid": "VUID-vkRegisterObjectsNVX-objectTable-parameter",
-          "text": " <code>objectTable</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkObjectTableNVX\">VkObjectTableNVX</a> handle"
-        },
-        {
-          "vuid": "VUID-vkRegisterObjectsNVX-ppObjectTableEntries-parameter",
-          "text": " <code>ppObjectTableEntries</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>objectCount</code> valid <a href=\"#VkObjectTableEntryNVX\">VkObjectTableEntryNVX</a> structures"
-        },
-        {
-          "vuid": "VUID-vkRegisterObjectsNVX-pObjectIndices-parameter",
-          "text": " <code>pObjectIndices</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>objectCount</code> <code>uint32_t</code> values"
-        },
-        {
-          "vuid": "VUID-vkRegisterObjectsNVX-objectCount-arraylength",
-          "text": " <code>objectCount</code> <strong class=\"purple\">must</strong> be greater than <code>0</code>"
-        },
-        {
-          "vuid": "VUID-vkRegisterObjectsNVX-objectTable-parent",
-          "text": " <code>objectTable</code> <strong class=\"purple\">must</strong> have been created, allocated, or retrieved from <code>device</code>"
-        }
-      ]
-    },
-    "VkObjectTableEntryNVX": {
-      "(VK_NVX_device_generated_commands)": [
-        {
-          "vuid": "VUID-VkObjectTableEntryNVX-computeBindingPointSupport-01367",
-          "text": " If the <code>VkDeviceGeneratedCommandsFeaturesNVX</code>::<code>computeBindingPointSupport</code> feature is not enabled, <code>flags</code> <strong class=\"purple\">must</strong> not contain <code>VK_OBJECT_ENTRY_USAGE_COMPUTE_BIT_NVX</code>"
-        },
-        {
-          "vuid": "VUID-VkObjectTableEntryNVX-type-parameter",
-          "text": " <code>type</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkObjectEntryTypeNVX\">VkObjectEntryTypeNVX</a> value"
-        },
-        {
-          "vuid": "VUID-VkObjectTableEntryNVX-flags-parameter",
-          "text": " <code>flags</code> <strong class=\"purple\">must</strong> be a valid combination of <a href=\"#VkObjectEntryUsageFlagBitsNVX\">VkObjectEntryUsageFlagBitsNVX</a> values"
-        },
-        {
-          "vuid": "VUID-VkObjectTableEntryNVX-flags-requiredbitmask",
-          "text": " <code>flags</code> <strong class=\"purple\">must</strong> not be <code>0</code>"
-        }
-      ]
-    },
-    "VkObjectTablePipelineEntryNVX": {
-      "(VK_NVX_device_generated_commands)": [
-        {
-          "vuid": "VUID-VkObjectTablePipelineEntryNVX-type-01368",
-          "text": " <code>type</code> <strong class=\"purple\">must</strong> be <code>VK_OBJECT_ENTRY_TYPE_PIPELINE_NVX</code>"
-        },
-        {
-          "vuid": "VUID-VkObjectTablePipelineEntryNVX-type-parameter",
-          "text": " <code>type</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkObjectEntryTypeNVX\">VkObjectEntryTypeNVX</a> value"
-        },
-        {
-          "vuid": "VUID-VkObjectTablePipelineEntryNVX-flags-parameter",
-          "text": " <code>flags</code> <strong class=\"purple\">must</strong> be a valid combination of <a href=\"#VkObjectEntryUsageFlagBitsNVX\">VkObjectEntryUsageFlagBitsNVX</a> values"
-        },
-        {
-          "vuid": "VUID-VkObjectTablePipelineEntryNVX-flags-requiredbitmask",
+          "vuid": "VUID-VkIndirectCommandsLayoutCreateInfoNV-flags-requiredbitmask",
           "text": " <code>flags</code> <strong class=\"purple\">must</strong> not be <code>0</code>"
         },
         {
-          "vuid": "VUID-VkObjectTablePipelineEntryNVX-pipeline-parameter",
-          "text": " <code>pipeline</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkPipeline\">VkPipeline</a> handle"
-        }
-      ]
-    },
-    "VkObjectTableDescriptorSetEntryNVX": {
-      "(VK_NVX_device_generated_commands)": [
-        {
-          "vuid": "VUID-VkObjectTableDescriptorSetEntryNVX-type-01369",
-          "text": " <code>type</code> <strong class=\"purple\">must</strong> be <code>VK_OBJECT_ENTRY_TYPE_DESCRIPTOR_SET_NVX</code>"
-        },
-        {
-          "vuid": "VUID-VkObjectTableDescriptorSetEntryNVX-type-parameter",
-          "text": " <code>type</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkObjectEntryTypeNVX\">VkObjectEntryTypeNVX</a> value"
-        },
-        {
-          "vuid": "VUID-VkObjectTableDescriptorSetEntryNVX-flags-parameter",
-          "text": " <code>flags</code> <strong class=\"purple\">must</strong> be a valid combination of <a href=\"#VkObjectEntryUsageFlagBitsNVX\">VkObjectEntryUsageFlagBitsNVX</a> values"
-        },
-        {
-          "vuid": "VUID-VkObjectTableDescriptorSetEntryNVX-flags-requiredbitmask",
-          "text": " <code>flags</code> <strong class=\"purple\">must</strong> not be <code>0</code>"
-        },
-        {
-          "vuid": "VUID-VkObjectTableDescriptorSetEntryNVX-pipelineLayout-parameter",
-          "text": " <code>pipelineLayout</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkPipelineLayout\">VkPipelineLayout</a> handle"
-        },
-        {
-          "vuid": "VUID-VkObjectTableDescriptorSetEntryNVX-descriptorSet-parameter",
-          "text": " <code>descriptorSet</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDescriptorSet\">VkDescriptorSet</a> handle"
-        },
-        {
-          "vuid": "VUID-VkObjectTableDescriptorSetEntryNVX-commonparent",
-          "text": " Both of <code>descriptorSet</code>, and <code>pipelineLayout</code> <strong class=\"purple\">must</strong> have been created, allocated, or retrieved from the same <a href=\"#VkDevice\">VkDevice</a>"
-        }
-      ]
-    },
-    "VkObjectTableVertexBufferEntryNVX": {
-      "(VK_NVX_device_generated_commands)": [
-        {
-          "vuid": "VUID-VkObjectTableVertexBufferEntryNVX-type-01370",
-          "text": " <code>type</code> <strong class=\"purple\">must</strong> be <code>VK_OBJECT_ENTRY_TYPE_VERTEX_BUFFER_NVX</code>"
-        },
-        {
-          "vuid": "VUID-VkObjectTableVertexBufferEntryNVX-type-parameter",
-          "text": " <code>type</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkObjectEntryTypeNVX\">VkObjectEntryTypeNVX</a> value"
-        },
-        {
-          "vuid": "VUID-VkObjectTableVertexBufferEntryNVX-flags-parameter",
-          "text": " <code>flags</code> <strong class=\"purple\">must</strong> be a valid combination of <a href=\"#VkObjectEntryUsageFlagBitsNVX\">VkObjectEntryUsageFlagBitsNVX</a> values"
-        },
-        {
-          "vuid": "VUID-VkObjectTableVertexBufferEntryNVX-flags-requiredbitmask",
-          "text": " <code>flags</code> <strong class=\"purple\">must</strong> not be <code>0</code>"
-        },
-        {
-          "vuid": "VUID-VkObjectTableVertexBufferEntryNVX-buffer-parameter",
-          "text": " <code>buffer</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkBuffer\">VkBuffer</a> handle"
-        }
-      ]
-    },
-    "VkObjectTableIndexBufferEntryNVX": {
-      "(VK_NVX_device_generated_commands)": [
-        {
-          "vuid": "VUID-VkObjectTableIndexBufferEntryNVX-type-01371",
-          "text": " <code>type</code> <strong class=\"purple\">must</strong> be <code>VK_OBJECT_ENTRY_TYPE_INDEX_BUFFER_NVX</code>"
-        },
-        {
-          "vuid": "VUID-VkObjectTableIndexBufferEntryNVX-indexType-02783",
-          "text": " <code>indexType</code> <strong class=\"purple\">must</strong> be <code>VK_INDEX_TYPE_UINT16</code>, or <code>VK_INDEX_TYPE_UINT32</code>"
-        },
-        {
-          "vuid": "VUID-VkObjectTableIndexBufferEntryNVX-type-parameter",
-          "text": " <code>type</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkObjectEntryTypeNVX\">VkObjectEntryTypeNVX</a> value"
-        },
-        {
-          "vuid": "VUID-VkObjectTableIndexBufferEntryNVX-flags-parameter",
-          "text": " <code>flags</code> <strong class=\"purple\">must</strong> be a valid combination of <a href=\"#VkObjectEntryUsageFlagBitsNVX\">VkObjectEntryUsageFlagBitsNVX</a> values"
-        },
-        {
-          "vuid": "VUID-VkObjectTableIndexBufferEntryNVX-flags-requiredbitmask",
-          "text": " <code>flags</code> <strong class=\"purple\">must</strong> not be <code>0</code>"
-        },
-        {
-          "vuid": "VUID-VkObjectTableIndexBufferEntryNVX-buffer-parameter",
-          "text": " <code>buffer</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkBuffer\">VkBuffer</a> handle"
-        },
-        {
-          "vuid": "VUID-VkObjectTableIndexBufferEntryNVX-indexType-parameter",
-          "text": " <code>indexType</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkIndexType\">VkIndexType</a> value"
-        }
-      ]
-    },
-    "VkObjectTablePushConstantEntryNVX": {
-      "(VK_NVX_device_generated_commands)": [
-        {
-          "vuid": "VUID-VkObjectTablePushConstantEntryNVX-type-01372",
-          "text": " <code>type</code> <strong class=\"purple\">must</strong> be <code>VK_OBJECT_ENTRY_TYPE_PUSH_CONSTANT_NVX</code>"
-        },
-        {
-          "vuid": "VUID-VkObjectTablePushConstantEntryNVX-type-parameter",
-          "text": " <code>type</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkObjectEntryTypeNVX\">VkObjectEntryTypeNVX</a> value"
-        },
-        {
-          "vuid": "VUID-VkObjectTablePushConstantEntryNVX-flags-parameter",
-          "text": " <code>flags</code> <strong class=\"purple\">must</strong> be a valid combination of <a href=\"#VkObjectEntryUsageFlagBitsNVX\">VkObjectEntryUsageFlagBitsNVX</a> values"
-        },
-        {
-          "vuid": "VUID-VkObjectTablePushConstantEntryNVX-flags-requiredbitmask",
-          "text": " <code>flags</code> <strong class=\"purple\">must</strong> not be <code>0</code>"
-        },
-        {
-          "vuid": "VUID-VkObjectTablePushConstantEntryNVX-pipelineLayout-parameter",
-          "text": " <code>pipelineLayout</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkPipelineLayout\">VkPipelineLayout</a> handle"
-        },
-        {
-          "vuid": "VUID-VkObjectTablePushConstantEntryNVX-stageFlags-parameter",
-          "text": " <code>stageFlags</code> <strong class=\"purple\">must</strong> be a valid combination of <a href=\"#VkShaderStageFlagBits\">VkShaderStageFlagBits</a> values"
-        },
-        {
-          "vuid": "VUID-VkObjectTablePushConstantEntryNVX-stageFlags-requiredbitmask",
-          "text": " <code>stageFlags</code> <strong class=\"purple\">must</strong> not be <code>0</code>"
-        }
-      ]
-    },
-    "vkUnregisterObjectsNVX": {
-      "(VK_NVX_device_generated_commands)": [
-        {
-          "vuid": "VUID-vkUnregisterObjectsNVX-pObjectIndices-01373",
-          "text": " At any <code>pObjectIndices</code> there <strong class=\"purple\">must</strong> be a registered resource already."
-        },
-        {
-          "vuid": "VUID-vkUnregisterObjectsNVX-pObjectEntryTypes-01374",
-          "text": " The <code>pObjectEntryTypes</code> of the resource at <code>pObjectIndices</code> <strong class=\"purple\">must</strong> match."
-        },
-        {
-          "vuid": "VUID-vkUnregisterObjectsNVX-None-01375",
-          "text": " All operations on the device using the registered resource <strong class=\"purple\">must</strong> have been completed."
-        },
-        {
-          "vuid": "VUID-vkUnregisterObjectsNVX-device-parameter",
-          "text": " <code>device</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDevice\">VkDevice</a> handle"
-        },
-        {
-          "vuid": "VUID-vkUnregisterObjectsNVX-objectTable-parameter",
-          "text": " <code>objectTable</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkObjectTableNVX\">VkObjectTableNVX</a> handle"
-        },
-        {
-          "vuid": "VUID-vkUnregisterObjectsNVX-pObjectEntryTypes-parameter",
-          "text": " <code>pObjectEntryTypes</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>objectCount</code> valid <a href=\"#VkObjectEntryTypeNVX\">VkObjectEntryTypeNVX</a> values"
-        },
-        {
-          "vuid": "VUID-vkUnregisterObjectsNVX-pObjectIndices-parameter",
-          "text": " <code>pObjectIndices</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>objectCount</code> <code>uint32_t</code> values"
-        },
-        {
-          "vuid": "VUID-vkUnregisterObjectsNVX-objectCount-arraylength",
-          "text": " <code>objectCount</code> <strong class=\"purple\">must</strong> be greater than <code>0</code>"
-        },
-        {
-          "vuid": "VUID-vkUnregisterObjectsNVX-objectTable-parent",
-          "text": " <code>objectTable</code> <strong class=\"purple\">must</strong> have been created, allocated, or retrieved from <code>device</code>"
-        }
-      ]
-    },
-    "VkIndirectCommandsLayoutTokenNVX": {
-      "(VK_NVX_device_generated_commands)": [
-        {
-          "vuid": "VUID-VkIndirectCommandsLayoutTokenNVX-bindingUnit-01342",
-          "text": " <code>bindingUnit</code> <strong class=\"purple\">must</strong> stay within device supported limits for the appropriate commands."
-        },
-        {
-          "vuid": "VUID-VkIndirectCommandsLayoutTokenNVX-dynamicCount-01343",
-          "text": " <code>dynamicCount</code> <strong class=\"purple\">must</strong> stay within device supported limits for the appropriate commands."
-        },
-        {
-          "vuid": "VUID-VkIndirectCommandsLayoutTokenNVX-divisor-01344",
-          "text": " <code>divisor</code> <strong class=\"purple\">must</strong> be greater than <code>0</code> and a power of two."
-        },
-        {
-          "vuid": "VUID-VkIndirectCommandsLayoutTokenNVX-tokenType-parameter",
-          "text": " <code>tokenType</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkIndirectCommandsTokenTypeNVX\">VkIndirectCommandsTokenTypeNVX</a> value"
-        }
-      ]
-    },
-    "VkIndirectCommandsTokenNVX": {
-      "(VK_NVX_device_generated_commands)": [
-        {
-          "vuid": "VUID-VkIndirectCommandsTokenNVX-buffer-01345",
-          "text": " The <code>buffer</code>&#8217;s usage flag <strong class=\"purple\">must</strong> have the <code>VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT</code> bit set."
-        },
-        {
-          "vuid": "VUID-VkIndirectCommandsTokenNVX-offset-01346",
-          "text": " The <code>offset</code> <strong class=\"purple\">must</strong> be aligned to <code>VkDeviceGeneratedCommandsLimitsNVX</code>::<code>minCommandsTokenBufferOffsetAlignment</code>."
-        },
-        {
-          "vuid": "VUID-VkIndirectCommandsTokenNVX-tokenType-parameter",
-          "text": " <code>tokenType</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkIndirectCommandsTokenTypeNVX\">VkIndirectCommandsTokenTypeNVX</a> value"
-        },
-        {
-          "vuid": "VUID-VkIndirectCommandsTokenNVX-buffer-parameter",
-          "text": " <code>buffer</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkBuffer\">VkBuffer</a> handle"
-        }
-      ]
-    },
-    "vkCreateIndirectCommandsLayoutNVX": {
-      "(VK_NVX_device_generated_commands)": [
-        {
-          "vuid": "VUID-vkCreateIndirectCommandsLayoutNVX-device-parameter",
-          "text": " <code>device</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDevice\">VkDevice</a> handle"
-        },
-        {
-          "vuid": "VUID-vkCreateIndirectCommandsLayoutNVX-pCreateInfo-parameter",
-          "text": " <code>pCreateInfo</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkIndirectCommandsLayoutCreateInfoNVX\">VkIndirectCommandsLayoutCreateInfoNVX</a> structure"
-        },
-        {
-          "vuid": "VUID-vkCreateIndirectCommandsLayoutNVX-pAllocator-parameter",
-          "text": " If <code>pAllocator</code> is not <code>NULL</code>, <code>pAllocator</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkAllocationCallbacks\">VkAllocationCallbacks</a> structure"
-        },
-        {
-          "vuid": "VUID-vkCreateIndirectCommandsLayoutNVX-pIndirectCommandsLayout-parameter",
-          "text": " <code>pIndirectCommandsLayout</code> <strong class=\"purple\">must</strong> be a valid pointer to a <a href=\"#VkIndirectCommandsLayoutNVX\">VkIndirectCommandsLayoutNVX</a> handle"
-        }
-      ]
-    },
-    "VkIndirectCommandsLayoutCreateInfoNVX": {
-      "(VK_NVX_device_generated_commands)": [
-        {
-          "vuid": "VUID-VkIndirectCommandsLayoutCreateInfoNVX-tokenCount-01347",
-          "text": " <code>tokenCount</code> <strong class=\"purple\">must</strong> be greater than <code>0</code> and below <code>VkDeviceGeneratedCommandsLimitsNVX</code>::<code>maxIndirectCommandsLayoutTokenCount</code>"
-        },
-        {
-          "vuid": "VUID-VkIndirectCommandsLayoutCreateInfoNVX-computeBindingPointSupport-01348",
-          "text": " If the <code>VkDeviceGeneratedCommandsFeaturesNVX</code>::<code>computeBindingPointSupport</code> feature is not enabled, then <code>pipelineBindPoint</code> <strong class=\"purple\">must</strong> not be <code>VK_PIPELINE_BIND_POINT_COMPUTE</code>"
-        },
-        {
-          "vuid": "VUID-VkIndirectCommandsLayoutCreateInfoNVX-pTokens-01349",
-          "text": " If <code>pTokens</code> contains an entry of <code>VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NVX</code> it <strong class=\"purple\">must</strong> be the first element of the array and there <strong class=\"purple\">must</strong> be only a single element of such token type."
-        },
-        {
-          "vuid": "VUID-VkIndirectCommandsLayoutCreateInfoNVX-pTokens-01350",
-          "text": " All state binding tokens in <code>pTokens</code> <strong class=\"purple\">must</strong> occur prior work provoking tokens (<code>VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NVX</code>, <code>VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NVX</code>, <code>VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NVX</code>)."
-        },
-        {
-          "vuid": "VUID-VkIndirectCommandsLayoutCreateInfoNVX-pTokens-01351",
-          "text": " The content of <code>pTokens</code> <strong class=\"purple\">must</strong> include one single work provoking token that is compatible with the <code>pipelineBindPoint</code>."
-        },
-        {
-          "vuid": "VUID-VkIndirectCommandsLayoutCreateInfoNVX-sType-sType",
-          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NVX</code>"
-        },
-        {
-          "vuid": "VUID-VkIndirectCommandsLayoutCreateInfoNVX-pNext-pNext",
-          "text": " <code>pNext</code> <strong class=\"purple\">must</strong> be <code>NULL</code>"
-        },
-        {
-          "vuid": "VUID-VkIndirectCommandsLayoutCreateInfoNVX-pipelineBindPoint-parameter",
+          "vuid": "VUID-VkIndirectCommandsLayoutCreateInfoNV-pipelineBindPoint-parameter",
           "text": " <code>pipelineBindPoint</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkPipelineBindPoint\">VkPipelineBindPoint</a> value"
         },
         {
-          "vuid": "VUID-VkIndirectCommandsLayoutCreateInfoNVX-flags-parameter",
-          "text": " <code>flags</code> <strong class=\"purple\">must</strong> be a valid combination of <a href=\"#VkIndirectCommandsLayoutUsageFlagBitsNVX\">VkIndirectCommandsLayoutUsageFlagBitsNVX</a> values"
+          "vuid": "VUID-VkIndirectCommandsLayoutCreateInfoNV-pTokens-parameter",
+          "text": " <code>pTokens</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>tokenCount</code> valid <a href=\"#VkIndirectCommandsLayoutTokenNV\">VkIndirectCommandsLayoutTokenNV</a> structures"
         },
         {
-          "vuid": "VUID-VkIndirectCommandsLayoutCreateInfoNVX-flags-requiredbitmask",
-          "text": " <code>flags</code> <strong class=\"purple\">must</strong> not be <code>0</code>"
+          "vuid": "VUID-VkIndirectCommandsLayoutCreateInfoNV-pStreamStrides-parameter",
+          "text": " <code>pStreamStrides</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>streamCount</code> <code>uint32_t</code> values"
         },
         {
-          "vuid": "VUID-VkIndirectCommandsLayoutCreateInfoNVX-pTokens-parameter",
-          "text": " <code>pTokens</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>tokenCount</code> valid <a href=\"#VkIndirectCommandsLayoutTokenNVX\">VkIndirectCommandsLayoutTokenNVX</a> structures"
-        },
-        {
-          "vuid": "VUID-VkIndirectCommandsLayoutCreateInfoNVX-tokenCount-arraylength",
+          "vuid": "VUID-VkIndirectCommandsLayoutCreateInfoNV-tokenCount-arraylength",
           "text": " <code>tokenCount</code> <strong class=\"purple\">must</strong> be greater than <code>0</code>"
+        },
+        {
+          "vuid": "VUID-VkIndirectCommandsLayoutCreateInfoNV-streamCount-arraylength",
+          "text": " <code>streamCount</code> <strong class=\"purple\">must</strong> be greater than <code>0</code>"
         }
       ]
     },
-    "vkDestroyIndirectCommandsLayoutNVX": {
-      "(VK_NVX_device_generated_commands)": [
+    "vkDestroyIndirectCommandsLayoutNV": {
+      "(VK_NV_device_generated_commands)": [
         {
-          "vuid": "VUID-vkDestroyIndirectCommandsLayoutNVX-indirectCommandsLayout-01352",
+          "vuid": "VUID-vkDestroyIndirectCommandsLayoutNV-indirectCommandsLayout-02938",
           "text": " All submitted commands that refer to <code>indirectCommandsLayout</code> <strong class=\"purple\">must</strong> have completed execution"
         },
         {
-          "vuid": "VUID-vkDestroyIndirectCommandsLayoutNVX-objectTable-01353",
-          "text": " If <code>VkAllocationCallbacks</code> were provided when <code>objectTable</code> was created, a compatible set of callbacks <strong class=\"purple\">must</strong> be provided here"
+          "vuid": "VUID-vkDestroyIndirectCommandsLayoutNV-indirectCommandsLayout-02939",
+          "text": " If <code>VkAllocationCallbacks</code> were provided when <code>indirectCommandsLayout</code> was created, a compatible set of callbacks <strong class=\"purple\">must</strong> be provided here"
         },
         {
-          "vuid": "VUID-vkDestroyIndirectCommandsLayoutNVX-objectTable-01354",
-          "text": " If no <code>VkAllocationCallbacks</code> were provided when <code>objectTable</code> was created, <code>pAllocator</code> <strong class=\"purple\">must</strong> be <code>NULL</code>"
+          "vuid": "VUID-vkDestroyIndirectCommandsLayoutNV-indirectCommandsLayout-02940",
+          "text": " If no <code>VkAllocationCallbacks</code> were provided when <code>indirectCommandsLayout</code> was created, <code>pAllocator</code> <strong class=\"purple\">must</strong> be <code>NULL</code>"
         },
         {
-          "vuid": "VUID-vkDestroyIndirectCommandsLayoutNVX-device-parameter",
+          "vuid": "VUID-vkDestroyIndirectCommandsLayoutNV-deviceGeneratedCommands-02941",
+          "text": " The <a href=\"#feature-device-generated-commands\"><code>VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV</code>::<code>deviceGeneratedCommands</code></a> feature <strong class=\"purple\">must</strong> be enabled"
+        },
+        {
+          "vuid": "VUID-vkDestroyIndirectCommandsLayoutNV-device-parameter",
           "text": " <code>device</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDevice\">VkDevice</a> handle"
         },
         {
-          "vuid": "VUID-vkDestroyIndirectCommandsLayoutNVX-indirectCommandsLayout-parameter",
-          "text": " <code>indirectCommandsLayout</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkIndirectCommandsLayoutNVX\">VkIndirectCommandsLayoutNVX</a> handle"
+          "vuid": "VUID-vkDestroyIndirectCommandsLayoutNV-indirectCommandsLayout-parameter",
+          "text": " <code>indirectCommandsLayout</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkIndirectCommandsLayoutNV\">VkIndirectCommandsLayoutNV</a> handle"
         },
         {
-          "vuid": "VUID-vkDestroyIndirectCommandsLayoutNVX-pAllocator-parameter",
+          "vuid": "VUID-vkDestroyIndirectCommandsLayoutNV-pAllocator-parameter",
           "text": " If <code>pAllocator</code> is not <code>NULL</code>, <code>pAllocator</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkAllocationCallbacks\">VkAllocationCallbacks</a> structure"
         },
         {
-          "vuid": "VUID-vkDestroyIndirectCommandsLayoutNVX-indirectCommandsLayout-parent",
+          "vuid": "VUID-vkDestroyIndirectCommandsLayoutNV-indirectCommandsLayout-parent",
           "text": " <code>indirectCommandsLayout</code> <strong class=\"purple\">must</strong> have been created, allocated, or retrieved from <code>device</code>"
         }
       ]
     },
-    "vkCmdReserveSpaceForCommandsNVX": {
-      "(VK_NVX_device_generated_commands)": [
+    "VkIndirectCommandsStreamNV": {
+      "(VK_NV_device_generated_commands)": [
         {
-          "vuid": "VUID-vkCmdReserveSpaceForCommandsNVX-commandBuffer-01329",
-          "text": " The provided <code>commandBuffer</code> <strong class=\"purple\">must</strong> not have had a prior space reservation since its creation or the last reset."
+          "vuid": "VUID-VkIndirectCommandsStreamNV-buffer-02942",
+          "text": " The <code>buffer</code>&#8217;s usage flag <strong class=\"purple\">must</strong> have the <code>VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT</code> bit set"
         },
         {
-          "vuid": "VUID-vkCmdReserveSpaceForCommandsNVX-commandBuffer-01330",
-          "text": " The state of the <code>commandBuffer</code> <strong class=\"purple\">must</strong> be legal to execute all commands within the sequence provided by the <code>indirectCommandsLayout</code> member of <code>pProcessCommandsInfo</code>."
+          "vuid": "VUID-VkIndirectCommandsStreamNV-offset-02943",
+          "text": " The <code>offset</code> <strong class=\"purple\">must</strong> be aligned to <code>VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV</code>::<code>minIndirectCommandsBufferOffsetAlignment</code>."
         },
         {
-          "vuid": "VUID-vkCmdReserveSpaceForCommandsNVX-commandBuffer-parameter",
-          "text": " <code>commandBuffer</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkCommandBuffer\">VkCommandBuffer</a> handle"
+          "vuid": "VUID-VkIndirectCommandsStreamNV-buffer-02975",
+          "text": " If <code>buffer</code> is non-sparse then it <strong class=\"purple\">must</strong> be bound completely and contiguously to a single <code>VkDeviceMemory</code> object"
         },
         {
-          "vuid": "VUID-vkCmdReserveSpaceForCommandsNVX-pReserveSpaceInfo-parameter",
-          "text": " <code>pReserveSpaceInfo</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkCmdReserveSpaceForCommandsInfoNVX\">VkCmdReserveSpaceForCommandsInfoNVX</a> structure"
-        },
-        {
-          "vuid": "VUID-vkCmdReserveSpaceForCommandsNVX-commandBuffer-recording",
-          "text": " <code>commandBuffer</code> <strong class=\"purple\">must</strong> be in the <a href=\"#commandbuffers-lifecycle\">recording state</a>"
-        },
-        {
-          "vuid": "VUID-vkCmdReserveSpaceForCommandsNVX-commandBuffer-cmdpool",
-          "text": " The <code>VkCommandPool</code> that <code>commandBuffer</code> was allocated from <strong class=\"purple\">must</strong> support graphics, or compute operations"
-        },
-        {
-          "vuid": "VUID-vkCmdReserveSpaceForCommandsNVX-renderpass",
-          "text": " This command <strong class=\"purple\">must</strong> only be called inside of a render pass instance"
-        },
-        {
-          "vuid": "VUID-vkCmdReserveSpaceForCommandsNVX-bufferlevel",
-          "text": " <code>commandBuffer</code> <strong class=\"purple\">must</strong> be a secondary <code>VkCommandBuffer</code>"
+          "vuid": "VUID-VkIndirectCommandsStreamNV-buffer-parameter",
+          "text": " <code>buffer</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkBuffer\">VkBuffer</a> handle"
         }
       ]
     },
-    "VkCmdReserveSpaceForCommandsInfoNVX": {
-      "(VK_NVX_device_generated_commands)": [
+    "VkBindShaderGroupIndirectCommandNV": {
+      "(VK_NV_device_generated_commands)": [
         {
-          "vuid": "VUID-VkCmdReserveSpaceForCommandsInfoNVX-sType-sType",
-          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_CMD_RESERVE_SPACE_FOR_COMMANDS_INFO_NVX</code>"
+          "vuid": "VUID-VkBindShaderGroupIndirectCommandNV-None-02944",
+          "text": " The current bound graphics pipeline, as well as the pipelines it may reference, <strong class=\"purple\">must</strong> have been created with <code>VK_PIPELINE_CREATE_INDIRECT_BINDABLE_BIT_NV</code>"
         },
         {
-          "vuid": "VUID-VkCmdReserveSpaceForCommandsInfoNVX-pNext-pNext",
+          "vuid": "VUID-VkBindShaderGroupIndirectCommandNV-index-02945",
+          "text": " The <code>index</code> <strong class=\"purple\">must</strong> be within range of the accessible shader groups of the current bound graphics pipeline. See <a href=\"#vkCmdBindPipelineShaderGroupNV\">vkCmdBindPipelineShaderGroupNV</a> for further details"
+        }
+      ]
+    },
+    "VkBindIndexBufferIndirectCommandNV": {
+      "(VK_NV_device_generated_commands)": [
+        {
+          "vuid": "VUID-VkBindIndexBufferIndirectCommandNV-None-02946",
+          "text": " The buffer&#8217;s usage flag from which the address was acquired <strong class=\"purple\">must</strong> have the <code>VK_BUFFER_USAGE_INDEX_BUFFER_BIT</code> bit set"
+        },
+        {
+          "vuid": "VUID-VkBindIndexBufferIndirectCommandNV-bufferAddress-02947",
+          "text": " The <code>bufferAddress</code> <strong class=\"purple\">must</strong> be aligned to the <code>indexType</code> used"
+        },
+        {
+          "vuid": "VUID-VkBindIndexBufferIndirectCommandNV-None-02948",
+          "text": " Each element of the buffer from which the address was acquired and that is non-sparse <strong class=\"purple\">must</strong> be bound completely and contiguously to a single <code>VkDeviceMemory</code> object"
+        },
+        {
+          "vuid": "VUID-VkBindIndexBufferIndirectCommandNV-indexType-parameter",
+          "text": " <code>indexType</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkIndexType\">VkIndexType</a> value"
+        }
+      ]
+    },
+    "VkBindVertexBufferIndirectCommandNV": {
+      "(VK_NV_device_generated_commands)": [
+        {
+          "vuid": "VUID-VkBindVertexBufferIndirectCommandNV-None-02949",
+          "text": " The buffer&#8217;s usage flag from which the address was acquired <strong class=\"purple\">must</strong> have the <code>VK_BUFFER_USAGE_VERTEX_BUFFER_BIT</code> bit set"
+        },
+        {
+          "vuid": "VUID-VkBindVertexBufferIndirectCommandNV-None-02950",
+          "text": " Each element of the buffer from which the address was acquired and that is non-sparse <strong class=\"purple\">must</strong> be bound completely and contiguously to a single <code>VkDeviceMemory</code> object"
+        }
+      ]
+    },
+    "VkIndirectCommandsLayoutTokenNV": {
+      "(VK_NV_device_generated_commands)": [
+        {
+          "vuid": "VUID-VkIndirectCommandsLayoutTokenNV-stream-02951",
+          "text": " <code>stream</code> <strong class=\"purple\">must</strong> be smaller than <code>VkIndirectCommandsLayoutCreateInfoNV</code>::<code>streamCount</code>"
+        },
+        {
+          "vuid": "VUID-VkIndirectCommandsLayoutTokenNV-offset-02952",
+          "text": " <code>offset</code> <strong class=\"purple\">must</strong> be less than or equal to <code>VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV</code>::<code>maxIndirectCommandsTokenOffset</code>."
+        },
+        {
+          "vuid": "VUID-VkIndirectCommandsLayoutTokenNV-tokenType-02976",
+          "text": " If <code>tokenType</code> is <code>VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_NV</code>, <code>vertexBindingUnit</code> <strong class=\"purple\">must</strong> stay within device supported limits for the appropriate commands"
+        },
+        {
+          "vuid": "VUID-VkIndirectCommandsLayoutTokenNV-tokenType-02977",
+          "text": " If <code>tokenType</code> is <code>VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NV</code>, <code>pushconstantPipelineLayout</code> <strong class=\"purple\">must</strong> be valid"
+        },
+        {
+          "vuid": "VUID-VkIndirectCommandsLayoutTokenNV-tokenType-02978",
+          "text": " If <code>tokenType</code> is <code>VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NV</code>, <code>pushconstantOffset</code> <strong class=\"purple\">must</strong> be a multiple of <code>4</code>"
+        },
+        {
+          "vuid": "VUID-VkIndirectCommandsLayoutTokenNV-tokenType-02979",
+          "text": " If <code>tokenType</code> is <code>VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NV</code>, <code>pushconstantSize</code> <strong class=\"purple\">must</strong> be a multiple of <code>4</code>"
+        },
+        {
+          "vuid": "VUID-VkIndirectCommandsLayoutTokenNV-tokenType-02980",
+          "text": " If <code>tokenType</code> is <code>VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NV</code>, <code>pushconstantOffset</code> <strong class=\"purple\">must</strong> be less than <code>VkPhysicalDeviceLimits</code>::<code>maxPushConstantsSize</code>"
+        },
+        {
+          "vuid": "VUID-VkIndirectCommandsLayoutTokenNV-tokenType-02981",
+          "text": " If <code>tokenType</code> is <code>VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NV</code>, <code>pushconstantSize</code> <strong class=\"purple\">must</strong> be less than or equal to <code>VkPhysicalDeviceLimits</code>::<code>maxPushConstantsSize</code> minus <code>pushconstantOffset</code>"
+        },
+        {
+          "vuid": "VUID-VkIndirectCommandsLayoutTokenNV-tokenType-02982",
+          "text": " If <code>tokenType</code> is <code>VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NV</code>, for each byte in the range specified by <code>pushconstantOffset</code> and <code>pushconstantSize</code> and for each shader stage in <code>pushconstantShaderStageFlags</code>, there <strong class=\"purple\">must</strong> be a push constant range in <code>pushconstantPipelineLayout</code> that includes that byte and that stage"
+        },
+        {
+          "vuid": "VUID-VkIndirectCommandsLayoutTokenNV-tokenType-02983",
+          "text": " If <code>tokenType</code> is <code>VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NV</code>, for each byte in the range specified by <code>pushconstantOffset</code> and <code>pushconstantSize</code> and for each push constant range that overlaps that byte, <code>pushconstantShaderStageFlags</code> <strong class=\"purple\">must</strong> include all stages in that push constant range&#8217;s <a href=\"#VkPushConstantRange\">VkPushConstantRange</a>::<code>pushconstantShaderStageFlags</code>"
+        },
+        {
+          "vuid": "VUID-VkIndirectCommandsLayoutTokenNV-tokenType-02984",
+          "text": " If <code>tokenType</code> is <code>VK_INDIRECT_COMMANDS_TOKEN_TYPE_STATE_FLAGS_NV</code>, <code>indirectStateFlags</code> <strong class=\"purple\">must</strong> not be ´0´"
+        },
+        {
+          "vuid": "VUID-VkIndirectCommandsLayoutTokenNV-sType-sType",
+          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_TOKEN_NV</code>"
+        },
+        {
+          "vuid": "VUID-VkIndirectCommandsLayoutTokenNV-pNext-pNext",
           "text": " <code>pNext</code> <strong class=\"purple\">must</strong> be <code>NULL</code>"
         },
         {
-          "vuid": "VUID-VkCmdReserveSpaceForCommandsInfoNVX-objectTable-parameter",
-          "text": " <code>objectTable</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkObjectTableNVX\">VkObjectTableNVX</a> handle"
+          "vuid": "VUID-VkIndirectCommandsLayoutTokenNV-tokenType-parameter",
+          "text": " <code>tokenType</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkIndirectCommandsTokenTypeNV\">VkIndirectCommandsTokenTypeNV</a> value"
         },
         {
-          "vuid": "VUID-VkCmdReserveSpaceForCommandsInfoNVX-indirectCommandsLayout-parameter",
-          "text": " <code>indirectCommandsLayout</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkIndirectCommandsLayoutNVX\">VkIndirectCommandsLayoutNVX</a> handle"
+          "vuid": "VUID-VkIndirectCommandsLayoutTokenNV-pushconstantPipelineLayout-parameter",
+          "text": " If <code>pushconstantPipelineLayout</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, <code>pushconstantPipelineLayout</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkPipelineLayout\">VkPipelineLayout</a> handle"
         },
         {
-          "vuid": "VUID-VkCmdReserveSpaceForCommandsInfoNVX-commonparent",
-          "text": " Both of <code>indirectCommandsLayout</code>, and <code>objectTable</code> <strong class=\"purple\">must</strong> have been created, allocated, or retrieved from the same <a href=\"#VkDevice\">VkDevice</a>"
+          "vuid": "VUID-VkIndirectCommandsLayoutTokenNV-pushconstantShaderStageFlags-parameter",
+          "text": " <code>pushconstantShaderStageFlags</code> <strong class=\"purple\">must</strong> be a valid combination of <a href=\"#VkShaderStageFlagBits\">VkShaderStageFlagBits</a> values"
+        },
+        {
+          "vuid": "VUID-VkIndirectCommandsLayoutTokenNV-indirectStateFlags-parameter",
+          "text": " <code>indirectStateFlags</code> <strong class=\"purple\">must</strong> be a valid combination of <a href=\"#VkIndirectStateFlagBitsNV\">VkIndirectStateFlagBitsNV</a> values"
+        },
+        {
+          "vuid": "VUID-VkIndirectCommandsLayoutTokenNV-pIndexTypes-parameter",
+          "text": " If <code>indexTypeCount</code> is not <code>0</code>, <code>pIndexTypes</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>indexTypeCount</code> valid <a href=\"#VkIndexType\">VkIndexType</a> values"
+        },
+        {
+          "vuid": "VUID-VkIndirectCommandsLayoutTokenNV-pIndexTypeValues-parameter",
+          "text": " If <code>indexTypeCount</code> is not <code>0</code>, <code>pIndexTypeValues</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>indexTypeCount</code> <code>uint32_t</code> values"
         }
       ]
     },
-    "vkCmdProcessCommandsNVX": {
-      "(VK_NVX_device_generated_commands)": [
+    "vkGetGeneratedCommandsMemoryRequirementsNV": {
+      "(VK_NV_device_generated_commands)": [
         {
-          "vuid": "VUID-vkCmdProcessCommandsNVX-commandBuffer-parameter",
-          "text": " <code>commandBuffer</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkCommandBuffer\">VkCommandBuffer</a> handle"
+          "vuid": "VUID-vkGetGeneratedCommandsMemoryRequirementsNV-deviceGeneratedCommands-02906",
+          "text": " The <a href=\"#feature-device-generated-commands\"><code>VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV</code>::<code>deviceGeneratedCommands</code></a> feature <strong class=\"purple\">must</strong> be enabled"
         },
         {
-          "vuid": "VUID-vkCmdProcessCommandsNVX-pProcessCommandsInfo-parameter",
-          "text": " <code>pProcessCommandsInfo</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkCmdProcessCommandsInfoNVX\">VkCmdProcessCommandsInfoNVX</a> structure"
+          "vuid": "VUID-vkGetGeneratedCommandsMemoryRequirementsNV-device-parameter",
+          "text": " <code>device</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDevice\">VkDevice</a> handle"
         },
         {
-          "vuid": "VUID-vkCmdProcessCommandsNVX-commandBuffer-recording",
-          "text": " <code>commandBuffer</code> <strong class=\"purple\">must</strong> be in the <a href=\"#commandbuffers-lifecycle\">recording state</a>"
+          "vuid": "VUID-vkGetGeneratedCommandsMemoryRequirementsNV-pInfo-parameter",
+          "text": " <code>pInfo</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkGeneratedCommandsMemoryRequirementsInfoNV\">VkGeneratedCommandsMemoryRequirementsInfoNV</a> structure"
         },
         {
-          "vuid": "VUID-vkCmdProcessCommandsNVX-commandBuffer-cmdpool",
-          "text": " The <code>VkCommandPool</code> that <code>commandBuffer</code> was allocated from <strong class=\"purple\">must</strong> support graphics, or compute operations"
-        },
-        {
-          "vuid": "VUID-vkCmdProcessCommandsNVX-renderpass",
-          "text": " This command <strong class=\"purple\">must</strong> only be called inside of a render pass instance"
+          "vuid": "VUID-vkGetGeneratedCommandsMemoryRequirementsNV-pMemoryRequirements-parameter",
+          "text": " <code>pMemoryRequirements</code> <strong class=\"purple\">must</strong> be a valid pointer to a <a href=\"#VkMemoryRequirements2\">VkMemoryRequirements2</a> structure"
         }
       ]
     },
-    "VkCmdProcessCommandsInfoNVX": {
-      "(VK_NVX_device_generated_commands)": [
+    "VkGeneratedCommandsMemoryRequirementsInfoNV": {
+      "(VK_NV_device_generated_commands)": [
         {
-          "vuid": "VUID-VkCmdProcessCommandsInfoNVX-objectTable-01331",
-          "text": " The provided <code>objectTable</code> <strong class=\"purple\">must</strong> include all objects referenced by the generation process"
+          "vuid": "VUID-VkGeneratedCommandsMemoryRequirementsInfoNV-maxSequencesCount-02907",
+          "text": " <code>maxSequencesCount</code> <strong class=\"purple\">must</strong> be less or equal to <a href=\"#VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV\">VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV</a>::<code>maxIndirectSequenceCount</code>"
         },
         {
-          "vuid": "VUID-VkCmdProcessCommandsInfoNVX-indirectCommandsTokenCount-01332",
-          "text": " <code>indirectCommandsTokenCount</code> <strong class=\"purple\">must</strong> match the <code>indirectCommandsLayout</code>&#8217;s <code>tokenCount</code>"
+          "vuid": "VUID-VkGeneratedCommandsMemoryRequirementsInfoNV-sType-sType",
+          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_GENERATED_COMMANDS_MEMORY_REQUIREMENTS_INFO_NV</code>"
         },
         {
-          "vuid": "VUID-VkCmdProcessCommandsInfoNVX-tokenType-01333",
-          "text": " The <code>tokenType</code> member of each entry in the <code>pIndirectCommandsTokens</code> array <strong class=\"purple\">must</strong> match the values used at creation time of <code>indirectCommandsLayout</code>"
-        },
-        {
-          "vuid": "VUID-VkCmdProcessCommandsInfoNVX-targetCommandBuffer-01334",
-          "text": " If <code>targetCommandBuffer</code> is provided, it <strong class=\"purple\">must</strong> have reserved command space"
-        },
-        {
-          "vuid": "VUID-VkCmdProcessCommandsInfoNVX-targetCommandBuffer-01335",
-          "text": " If <code>targetCommandBuffer</code> is provided, the <code>objectTable</code> <strong class=\"purple\">must</strong> match the reservation&#8217;s <code>objectTable</code> and <strong class=\"purple\">must</strong> have had all referenced objects registered at reservation time"
-        },
-        {
-          "vuid": "VUID-VkCmdProcessCommandsInfoNVX-targetCommandBuffer-01336",
-          "text": " If <code>targetCommandBuffer</code> is provided, the <code>indirectCommandsLayout</code> <strong class=\"purple\">must</strong> match the reservation&#8217;s <code>indirectCommandsLayout</code>"
-        },
-        {
-          "vuid": "VUID-VkCmdProcessCommandsInfoNVX-targetCommandBuffer-01337",
-          "text": " If <code>targetCommandBuffer</code> is provided, the <code>maxSequencesCount</code> <strong class=\"purple\">must</strong> not exceed the reservation&#8217;s <code>maxSequencesCount</code>"
-        },
-        {
-          "vuid": "VUID-VkCmdProcessCommandsInfoNVX-sequencesCountBuffer-01338",
-          "text": " If <code>sequencesCountBuffer</code> is used, its usage flag <strong class=\"purple\">must</strong> have the <code>VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT</code> bit set"
-        },
-        {
-          "vuid": "VUID-VkCmdProcessCommandsInfoNVX-sequencesCountBuffer-01339",
-          "text": " If <code>sequencesCountBuffer</code> is used, <code>sequencesCountOffset</code> <strong class=\"purple\">must</strong> be aligned to <code>VkDeviceGeneratedCommandsLimitsNVX</code>::<code>minSequenceCountBufferOffsetAlignment</code>"
-        },
-        {
-          "vuid": "VUID-VkCmdProcessCommandsInfoNVX-sequencesIndexBuffer-01340",
-          "text": " If <code>sequencesIndexBuffer</code> is used, its usage flag <strong class=\"purple\">must</strong> have the <code>VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT</code> bit set"
-        },
-        {
-          "vuid": "VUID-VkCmdProcessCommandsInfoNVX-sequencesIndexBuffer-01341",
-          "text": " If <code>sequencesIndexBuffer</code> is used, <code>sequencesIndexOffset</code> <strong class=\"purple\">must</strong> be aligned to <code>VkDeviceGeneratedCommandsLimitsNVX</code>::<code>minSequenceIndexBufferOffsetAlignment</code>"
-        },
-        {
-          "vuid": "VUID-VkCmdProcessCommandsInfoNVX-sType-sType",
-          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_CMD_PROCESS_COMMANDS_INFO_NVX</code>"
-        },
-        {
-          "vuid": "VUID-VkCmdProcessCommandsInfoNVX-pNext-pNext",
+          "vuid": "VUID-VkGeneratedCommandsMemoryRequirementsInfoNV-pNext-pNext",
           "text": " <code>pNext</code> <strong class=\"purple\">must</strong> be <code>NULL</code>"
         },
         {
-          "vuid": "VUID-VkCmdProcessCommandsInfoNVX-objectTable-parameter",
-          "text": " <code>objectTable</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkObjectTableNVX\">VkObjectTableNVX</a> handle"
+          "vuid": "VUID-VkGeneratedCommandsMemoryRequirementsInfoNV-pipelineBindPoint-parameter",
+          "text": " <code>pipelineBindPoint</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkPipelineBindPoint\">VkPipelineBindPoint</a> value"
         },
         {
-          "vuid": "VUID-VkCmdProcessCommandsInfoNVX-indirectCommandsLayout-parameter",
-          "text": " <code>indirectCommandsLayout</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkIndirectCommandsLayoutNVX\">VkIndirectCommandsLayoutNVX</a> handle"
+          "vuid": "VUID-VkGeneratedCommandsMemoryRequirementsInfoNV-pipeline-parameter",
+          "text": " <code>pipeline</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkPipeline\">VkPipeline</a> handle"
         },
         {
-          "vuid": "VUID-VkCmdProcessCommandsInfoNVX-pIndirectCommandsTokens-parameter",
-          "text": " <code>pIndirectCommandsTokens</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>indirectCommandsTokenCount</code> valid <a href=\"#VkIndirectCommandsTokenNVX\">VkIndirectCommandsTokenNVX</a> structures"
+          "vuid": "VUID-VkGeneratedCommandsMemoryRequirementsInfoNV-indirectCommandsLayout-parameter",
+          "text": " <code>indirectCommandsLayout</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkIndirectCommandsLayoutNV\">VkIndirectCommandsLayoutNV</a> handle"
         },
         {
-          "vuid": "VUID-VkCmdProcessCommandsInfoNVX-targetCommandBuffer-parameter",
-          "text": " If <code>targetCommandBuffer</code> is not <code>NULL</code>, <code>targetCommandBuffer</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkCommandBuffer\">VkCommandBuffer</a> handle"
+          "vuid": "VUID-VkGeneratedCommandsMemoryRequirementsInfoNV-commonparent",
+          "text": " Both of <code>indirectCommandsLayout</code>, and <code>pipeline</code> <strong class=\"purple\">must</strong> have been created, allocated, or retrieved from the same <a href=\"#VkDevice\">VkDevice</a>"
+        }
+      ]
+    },
+    "vkCmdExecuteGeneratedCommandsNV": {
+      "(VK_NV_device_generated_commands)": [
+        {
+          "vuid": "VUID-vkCmdExecuteGeneratedCommandsNV-None-02690",
+          "text": " If a <code>VkImageView</code> is sampled with <code>VK_FILTER_LINEAR</code> as a result of this command, then the image view&#8217;s <a href=\"#resources-image-view-format-features\">format features</a> <strong class=\"purple\">must</strong> contain <code>VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT</code>"
         },
         {
-          "vuid": "VUID-VkCmdProcessCommandsInfoNVX-sequencesCountBuffer-parameter",
+          "vuid": "VUID-vkCmdExecuteGeneratedCommandsNV-None-02691",
+          "text": " If a <code>VkImageView</code> is accessed using atomic operations as a result of this command, then the image view&#8217;s <a href=\"#resources-image-view-format-features\">format features</a> <strong class=\"purple\">must</strong> contain <code>VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdExecuteGeneratedCommandsNV-None-02697",
+          "text": " For each set <em>n</em> that is statically used by the <code>VkPipeline</code> bound to the pipeline bind point used by this command, a descriptor set <strong class=\"purple\">must</strong> have been bound to <em>n</em> at the same pipeline bind point, with a <code>VkPipelineLayout</code> that is compatible for set <em>n</em>, with the <code>VkPipelineLayout</code> used to create the current <code>VkPipeline</code>, as described in <a href=\"#descriptorsets-compatibility\">Pipeline Layout Compatibility</a>"
+        },
+        {
+          "vuid": "VUID-vkCmdExecuteGeneratedCommandsNV-None-02698",
+          "text": " For each push constant that is statically used by the <code>VkPipeline</code> bound to the pipeline bind point used by this command, a push constant value <strong class=\"purple\">must</strong> have been set for the same pipeline bind point, with a <code>VkPipelineLayout</code> that is compatible for push constants, with the <code>VkPipelineLayout</code> used to create the current <code>VkPipeline</code>, as described in <a href=\"#descriptorsets-compatibility\">Pipeline Layout Compatibility</a>"
+        },
+        {
+          "vuid": "VUID-vkCmdExecuteGeneratedCommandsNV-None-02699",
+          "text": " Descriptors in each bound descriptor set, specified via <code>vkCmdBindDescriptorSets</code>, <strong class=\"purple\">must</strong> be valid if they are statically used by the <code>VkPipeline</code> bound to the pipeline bind point used by this command"
+        },
+        {
+          "vuid": "VUID-vkCmdExecuteGeneratedCommandsNV-None-02700",
+          "text": " A valid pipeline <strong class=\"purple\">must</strong> be bound to the pipeline bind point used by this command"
+        },
+        {
+          "vuid": "VUID-vkCmdExecuteGeneratedCommandsNV-commandBuffer-02701",
+          "text": " If the <code>VkPipeline</code> object bound to the pipeline bind point used by this command requires any dynamic state, that state <strong class=\"purple\">must</strong> have been set for <code>commandBuffer</code>, and done so after any previously bound pipeline with the corresponding state not specified as dynamic"
+        },
+        {
+          "vuid": "VUID-vkCmdExecuteGeneratedCommandsNV-None-02859",
+          "text": " There <strong class=\"purple\">must</strong> not have been any calls to dynamic state setting commands for any state not specified as dynamic in the <code>VkPipeline</code> object bound to the pipeline bind point used by this command, since that pipeline was bound"
+        },
+        {
+          "vuid": "VUID-vkCmdExecuteGeneratedCommandsNV-None-02702",
+          "text": " If the <code>VkPipeline</code> object bound to the pipeline bind point used by this command accesses a <code>VkSampler</code> object that uses unnormalized coordinates, that sampler <strong class=\"purple\">must</strong> not be used to sample from any <code>VkImage</code> with a <code>VkImageView</code> of the type <code>VK_IMAGE_VIEW_TYPE_3D</code>, <code>VK_IMAGE_VIEW_TYPE_CUBE</code>, <code>VK_IMAGE_VIEW_TYPE_1D_ARRAY</code>, <code>VK_IMAGE_VIEW_TYPE_2D_ARRAY</code> or <code>VK_IMAGE_VIEW_TYPE_CUBE_ARRAY</code>, in any shader stage"
+        },
+        {
+          "vuid": "VUID-vkCmdExecuteGeneratedCommandsNV-None-02703",
+          "text": " If the <code>VkPipeline</code> object bound to the pipeline bind point used by this command accesses a <code>VkSampler</code> object that uses unnormalized coordinates, that sampler <strong class=\"purple\">must</strong> not be used with any of the SPIR-V <code>OpImageSample*</code> or <code>OpImageSparseSample*</code> instructions with <code>ImplicitLod</code>, <code>Dref</code> or <code>Proj</code> in their name, in any shader stage"
+        },
+        {
+          "vuid": "VUID-vkCmdExecuteGeneratedCommandsNV-None-02704",
+          "text": " If the <code>VkPipeline</code> object bound to the pipeline bind point used by this command accesses a <code>VkSampler</code> object that uses unnormalized coordinates, that sampler <strong class=\"purple\">must</strong> not be used with any of the SPIR-V <code>OpImageSample*</code> or <code>OpImageSparseSample*</code> instructions that includes a LOD bias or any offset values, in any shader stage"
+        },
+        {
+          "vuid": "VUID-vkCmdExecuteGeneratedCommandsNV-None-02705",
+          "text": " If the <a href=\"#features-robustBufferAccess\">robust buffer access</a> feature is not enabled, and if the <code>VkPipeline</code> object bound to the pipeline bind point used by this command accesses a uniform buffer, it <strong class=\"purple\">must</strong> not access values outside of the range of the buffer as specified in the descriptor set bound to the same pipeline bind point"
+        },
+        {
+          "vuid": "VUID-vkCmdExecuteGeneratedCommandsNV-None-02706",
+          "text": " If the <a href=\"#features-robustBufferAccess\">robust buffer access</a> feature is not enabled, and if the <code>VkPipeline</code> object bound to the pipeline bind point used by this command accesses a storage buffer, it <strong class=\"purple\">must</strong> not access values outside of the range of the buffer as specified in the descriptor set bound to the same pipeline bind point"
+        },
+        {
+          "vuid": "VUID-vkCmdExecuteGeneratedCommandsNV-renderPass-02684",
+          "text": " The current render pass <strong class=\"purple\">must</strong> be <a href=\"#renderpass-compatibility\">compatible</a> with the <code>renderPass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdExecuteGeneratedCommandsNV-subpass-02685",
+          "text": " The subpass index of the current render pass <strong class=\"purple\">must</strong> be equal to the <code>subpass</code> member of the <code>VkGraphicsPipelineCreateInfo</code> structure specified when creating the <code>VkPipeline</code> bound to <code>VK_PIPELINE_BIND_POINT_GRAPHICS</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdExecuteGeneratedCommandsNV-None-02686",
+          "text": " Every input attachment used by the current subpass <strong class=\"purple\">must</strong> be bound to the pipeline via a descriptor set"
+        },
+        {
+          "vuid": "VUID-vkCmdExecuteGeneratedCommandsNV-None-02687",
+          "text": " Image subresources used as attachments in the current render pass <strong class=\"purple\">must</strong> not be accessed in any way other than as an attachment by this command."
+        },
+        {
+          "vuid": "VUID-vkCmdExecuteGeneratedCommandsNV-None-02720",
+          "text": " All vertex input bindings accessed via vertex input variables declared in the vertex shader entry point&#8217;s interface <strong class=\"purple\">must</strong> have valid buffers bound"
+        },
+        {
+          "vuid": "VUID-vkCmdExecuteGeneratedCommandsNV-None-02721",
+          "text": " For a given vertex buffer binding, any attribute data fetched <strong class=\"purple\">must</strong> be entirely contained within the corresponding vertex buffer binding, as described in <a href=\"#fxvertex-input\">Vertex Input Description</a>"
+        },
+        {
+          "vuid": "VUID-vkCmdExecuteGeneratedCommandsNV-isPreprocessed-02908",
+          "text": " If <code>isPreprocessed</code> is <code>VK_TRUE</code> then <a href=\"#vkCmdPreprocessGeneratedCommandsNV\">vkCmdPreprocessGeneratedCommandsNV</a> <strong class=\"purple\">must</strong> have already been executed on the device, using the same <code>pGeneratedCommandsInfo</code> content as well as the content of the input buffers it references (all except <a href=\"#VkGeneratedCommandsInfoNV\">VkGeneratedCommandsInfoNV</a>::<code>preprocessBuffer</code>). Furthermore <code>pGeneratedCommandsInfo</code>`s <code>indirectCommandsLayout</code> <strong class=\"purple\">must</strong> have been created with the <code>VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EXPLICIT_PREPROCESS_BIT_NV</code> bit set"
+        },
+        {
+          "vuid": "VUID-vkCmdExecuteGeneratedCommandsNV-pipeline-02909",
+          "text": " <code>VkGeneratedCommandsInfoNV</code>::<code>pipeline</code> <strong class=\"purple\">must</strong> match the current bound pipeline at <code>VkGeneratedCommandsInfoNV</code>::<code>pipelineBindPoint</code>."
+        },
+        {
+          "vuid": "VUID-vkCmdExecuteGeneratedCommandsNV-deviceGeneratedCommands-02911",
+          "text": " The <a href=\"#feature-device-generated-commands\"><code>VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV</code>::<code>deviceGeneratedCommands</code></a> feature <strong class=\"purple\">must</strong> be enabled"
+        },
+        {
+          "vuid": "VUID-vkCmdExecuteGeneratedCommandsNV-commandBuffer-parameter",
+          "text": " <code>commandBuffer</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkCommandBuffer\">VkCommandBuffer</a> handle"
+        },
+        {
+          "vuid": "VUID-vkCmdExecuteGeneratedCommandsNV-pGeneratedCommandsInfo-parameter",
+          "text": " <code>pGeneratedCommandsInfo</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkGeneratedCommandsInfoNV\">VkGeneratedCommandsInfoNV</a> structure"
+        },
+        {
+          "vuid": "VUID-vkCmdExecuteGeneratedCommandsNV-commandBuffer-recording",
+          "text": " <code>commandBuffer</code> <strong class=\"purple\">must</strong> be in the <a href=\"#commandbuffers-lifecycle\">recording state</a>"
+        },
+        {
+          "vuid": "VUID-vkCmdExecuteGeneratedCommandsNV-commandBuffer-cmdpool",
+          "text": " The <code>VkCommandPool</code> that <code>commandBuffer</code> was allocated from <strong class=\"purple\">must</strong> support graphics, or compute operations"
+        },
+        {
+          "vuid": "VUID-vkCmdExecuteGeneratedCommandsNV-renderpass",
+          "text": " This command <strong class=\"purple\">must</strong> only be called inside of a render pass instance"
+        }
+      ],
+      "(VK_NV_device_generated_commands)+(VK_IMG_filter_cubic,VK_EXT_filter_cubic)": [
+        {
+          "vuid": "VUID-vkCmdExecuteGeneratedCommandsNV-None-02692",
+          "text": " If a <code>VkImageView</code> is sampled with <code>VK_FILTER_CUBIC_EXT</code> as a result of this command, then the image view&#8217;s <a href=\"#resources-image-view-format-features\">format features</a> <strong class=\"purple\">must</strong> contain <code>VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT</code>"
+        }
+      ],
+      "(VK_NV_device_generated_commands)+(VK_IMG_filter_cubic,VK_EXT_filter_cubic)+!(VK_EXT_filter_cubic)": [
+        {
+          "vuid": "VUID-vkCmdExecuteGeneratedCommandsNV-None-02693",
+          "text": " Any <a href=\"#VkImageView\">VkImageView</a> being sampled with <code>VK_FILTER_CUBIC_EXT</code> as a result of this command <strong class=\"purple\">must</strong> not have a <a href=\"#VkImageViewType\">VkImageViewType</a> of <code>VK_IMAGE_VIEW_TYPE_3D</code>, <code>VK_IMAGE_VIEW_TYPE_CUBE</code>, or <code>VK_IMAGE_VIEW_TYPE_CUBE_ARRAY</code>"
+        }
+      ],
+      "(VK_NV_device_generated_commands)+(VK_IMG_filter_cubic,VK_EXT_filter_cubic)+(VK_EXT_filter_cubic)": [
+        {
+          "vuid": "VUID-vkCmdExecuteGeneratedCommandsNV-filterCubic-02694",
+          "text": " Any <a href=\"#VkImageView\">VkImageView</a> being sampled with <code>VK_FILTER_CUBIC_EXT</code> as a result of this command <strong class=\"purple\">must</strong> have a <a href=\"#VkImageViewType\">VkImageViewType</a> and format that supports cubic filtering, as specified by <code>VkFilterCubicImageViewImageFormatPropertiesEXT</code>::<code>filterCubic</code> returned by <code>vkGetPhysicalDeviceImageFormatProperties2</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdExecuteGeneratedCommandsNV-filterCubicMinmax-02695",
+          "text": " Any <a href=\"#VkImageView\">VkImageView</a> being sampled with <code>VK_FILTER_CUBIC_EXT</code> with a reduction mode of either <code>VK_SAMPLER_REDUCTION_MODE_MIN</code> or <code>VK_SAMPLER_REDUCTION_MODE_MAX</code> as a result of this command <strong class=\"purple\">must</strong> have a <a href=\"#VkImageViewType\">VkImageViewType</a> and format that supports cubic filtering together with minmax filtering, as specified by <code>VkFilterCubicImageViewImageFormatPropertiesEXT</code>::<code>filterCubicMinmax</code> returned by <code>vkGetPhysicalDeviceImageFormatProperties2</code>"
+        }
+      ],
+      "(VK_NV_device_generated_commands)+(VK_NV_corner_sampled_image)": [
+        {
+          "vuid": "VUID-vkCmdExecuteGeneratedCommandsNV-flags-02696",
+          "text": " Any <a href=\"#VkImage\">VkImage</a> created with a <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>flags</code> containing <code>VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV</code> sampled as a result of this command <strong class=\"purple\">must</strong> only be sampled using a <a href=\"#VkSamplerAddressMode\">VkSamplerAddressMode</a> of <code>VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE</code>"
+        }
+      ],
+      "(VK_NV_device_generated_commands)+(VK_VERSION_1_1)": [
+        {
+          "vuid": "VUID-vkCmdExecuteGeneratedCommandsNV-commandBuffer-02707",
+          "text": " If <code>commandBuffer</code> is an unprotected command buffer, any resource accessed by the <code>VkPipeline</code> object bound to the pipeline bind point used by this command <strong class=\"purple\">must</strong> not be a protected resource"
+        },
+        {
+          "vuid": "VUID-vkCmdExecuteGeneratedCommandsNV-commandBuffer-02970",
+          "text": " <code>commandBuffer</code> <strong class=\"purple\">must</strong> not be a protected command buffer"
+        }
+      ],
+      "(VK_NV_device_generated_commands)+(VK_VERSION_1_1,VK_KHR_multiview)": [
+        {
+          "vuid": "VUID-vkCmdExecuteGeneratedCommandsNV-maxMultiviewInstanceIndex-02688",
+          "text": " If the draw is recorded in a render pass instance with multiview enabled, the maximum instance index <strong class=\"purple\">must</strong> be less than or equal to <a href=\"#VkPhysicalDeviceMultiviewProperties\">VkPhysicalDeviceMultiviewProperties</a>::<code>maxMultiviewInstanceIndex</code>"
+        }
+      ],
+      "(VK_NV_device_generated_commands)+(VK_EXT_sample_locations)": [
+        {
+          "vuid": "VUID-vkCmdExecuteGeneratedCommandsNV-sampleLocationsEnable-02689",
+          "text": " If the bound graphics pipeline was created with <a href=\"#VkPipelineSampleLocationsStateCreateInfoEXT\">VkPipelineSampleLocationsStateCreateInfoEXT</a>::<code>sampleLocationsEnable</code> set to <code>VK_TRUE</code> and the current subpass has a depth/stencil attachment, then that attachment <strong class=\"purple\">must</strong> have been created with the <code>VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT</code> bit set"
+        }
+      ],
+      "(VK_NV_device_generated_commands)+(VK_EXT_transform_feedback)": [
+        {
+          "vuid": "VUID-vkCmdExecuteGeneratedCommandsNV-None-02910",
+          "text": " Transform feedback <strong class=\"purple\">must</strong> not be active"
+        }
+      ]
+    },
+    "VkGeneratedCommandsInfoNV": {
+      "(VK_NV_device_generated_commands)": [
+        {
+          "vuid": "VUID-VkGeneratedCommandsInfoNV-pipeline-02912",
+          "text": " The provided <code>pipeline</code> <strong class=\"purple\">must</strong> match the pipeline bound at execution time"
+        },
+        {
+          "vuid": "VUID-VkGeneratedCommandsInfoNV-indirectCommandsLayout-02913",
+          "text": " If the <code>indirectCommandsLayout</code> uses a token of <code>VK_INDIRECT_COMMANDS_TOKEN_TYPE_SHADER_GROUP_NV</code>, then the <code>pipeline</code> <strong class=\"purple\">must</strong> have been created with multiple shader groups"
+        },
+        {
+          "vuid": "VUID-VkGeneratedCommandsInfoNV-indirectCommandsLayout-02914",
+          "text": " If the <code>indirectCommandsLayout</code> uses a token of <code>VK_INDIRECT_COMMANDS_TOKEN_TYPE_SHADER_GROUP_NV</code>, then the <code>pipeline</code> <strong class=\"purple\">must</strong> have been created with <code>VK_PIPELINE_CREATE_INDIRECT_BINDABLE_BIT_NV</code> set in <code>VkGraphicsPipelineCreateInfo</code>::<code>flags</code>"
+        },
+        {
+          "vuid": "VUID-VkGeneratedCommandsInfoNV-indirectCommandsLayout-02915",
+          "text": " If the <code>indirectCommandsLayout</code> uses a token of <code>VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NV</code>, then the <code>pipeline</code>`s <code>VkPipelineLayout</code> <strong class=\"purple\">must</strong> match the <a href=\"#VkIndirectCommandsLayoutTokenNV\">VkIndirectCommandsLayoutTokenNV</a>::<code>pushconstantPipelineLayout</code>"
+        },
+        {
+          "vuid": "VUID-VkGeneratedCommandsInfoNV-streamCount-02916",
+          "text": " <code>streamCount</code> <strong class=\"purple\">must</strong> match the <code>indirectCommandsLayout</code>&#8217;s <code>streamCount</code>"
+        },
+        {
+          "vuid": "VUID-VkGeneratedCommandsInfoNV-sequencesCount-02917",
+          "text": " <code>sequencesCount</code> <strong class=\"purple\">must</strong> be less or equal to <a href=\"#VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV\">VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV</a>::<code>maxIndirectSequenceCount</code> and <a href=\"#VkGeneratedCommandsMemoryRequirementsInfoNV\">VkGeneratedCommandsMemoryRequirementsInfoNV</a>::<code>maxSequencesCount</code> that was used to determine the <code>preprocessSize</code>"
+        },
+        {
+          "vuid": "VUID-VkGeneratedCommandsInfoNV-preprocessBuffer-02918",
+          "text": " <code>preprocessBuffer</code> <strong class=\"purple\">must</strong> have the <code>VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT</code> bit set in its usage flag"
+        },
+        {
+          "vuid": "VUID-VkGeneratedCommandsInfoNV-preprocessOffset-02919",
+          "text": " <code>preprocessOffset</code> <strong class=\"purple\">must</strong> be aligned to <a href=\"#VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV\">VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV</a>::<code>minIndirectCommandsBufferOffsetAlignment</code>"
+        },
+        {
+          "vuid": "VUID-VkGeneratedCommandsInfoNV-preprocessBuffer-02971",
+          "text": " If <code>preprocessBuffer</code> is non-sparse then it <strong class=\"purple\">must</strong> be bound completely and contiguously to a single <code>VkDeviceMemory</code> object"
+        },
+        {
+          "vuid": "VUID-VkGeneratedCommandsInfoNV-preprocessSize-02920",
+          "text": " <code>preprocessSize</code> <strong class=\"purple\">must</strong> be at least equal to the memory requirement`s size returned by <a href=\"#vkGetGeneratedCommandsMemoryRequirementsNV\">vkGetGeneratedCommandsMemoryRequirementsNV</a> using the matching inputs (<code>indirectCommandsLayout</code>, &#8230;&#8203;) as within this structure"
+        },
+        {
+          "vuid": "VUID-VkGeneratedCommandsInfoNV-sequencesCountBuffer-02921",
+          "text": " <code>sequencesCountBuffer</code> <strong class=\"purple\">can</strong> be set if the actual used count of sequences is sourced from the provided buffer. In that case the <code>sequencesCount</code> serves as upper bound"
+        },
+        {
+          "vuid": "VUID-VkGeneratedCommandsInfoNV-sequencesCountBuffer-02922",
+          "text": " If <code>sequencesCountBuffer</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, its usage flag <strong class=\"purple\">must</strong> have the <code>VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT</code> bit set"
+        },
+        {
+          "vuid": "VUID-VkGeneratedCommandsInfoNV-sequencesCountBuffer-02923",
+          "text": " If <code>sequencesCountBuffer</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, <code>sequencesCountOffset</code> <strong class=\"purple\">must</strong> be aligned to <code>VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV</code>::<code>minSequencesCountBufferOffsetAlignment</code>"
+        },
+        {
+          "vuid": "VUID-VkGeneratedCommandsInfoNV-sequencesCountBuffer-02972",
+          "text": " If <code>sequencesCountBuffer</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a> and is non-sparse then it <strong class=\"purple\">must</strong> be bound completely and contiguously to a single <code>VkDeviceMemory</code> object"
+        },
+        {
+          "vuid": "VUID-VkGeneratedCommandsInfoNV-sequencesIndexBuffer-02924",
+          "text": " If <code>indirectCommandsLayout</code>&#8217;s <code>VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NV</code> is set, <code>sequencesIndexBuffer</code> <strong class=\"purple\">must</strong> be set otherwise it <strong class=\"purple\">must</strong> be <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>"
+        },
+        {
+          "vuid": "VUID-VkGeneratedCommandsInfoNV-sequencesIndexBuffer-02925",
+          "text": " If <code>sequencesIndexBuffer</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, its usage flag <strong class=\"purple\">must</strong> have the <code>VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT</code> bit set"
+        },
+        {
+          "vuid": "VUID-VkGeneratedCommandsInfoNV-sequencesIndexBuffer-02926",
+          "text": " If <code>sequencesIndexBuffer</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, <code>sequencesIndexOffset</code> <strong class=\"purple\">must</strong> be aligned to <code>VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV</code>::<code>minSequencesIndexBufferOffsetAlignment</code>"
+        },
+        {
+          "vuid": "VUID-VkGeneratedCommandsInfoNV-sequencesIndexBuffer-02973",
+          "text": " If <code>sequencesIndexBuffer</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a> and is non-sparse then it <strong class=\"purple\">must</strong> be bound completely and contiguously to a single <code>VkDeviceMemory</code> object"
+        },
+        {
+          "vuid": "VUID-VkGeneratedCommandsInfoNV-sType-sType",
+          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_GENERATED_COMMANDS_INFO_NV</code>"
+        },
+        {
+          "vuid": "VUID-VkGeneratedCommandsInfoNV-pNext-pNext",
+          "text": " <code>pNext</code> <strong class=\"purple\">must</strong> be <code>NULL</code>"
+        },
+        {
+          "vuid": "VUID-VkGeneratedCommandsInfoNV-pipelineBindPoint-parameter",
+          "text": " <code>pipelineBindPoint</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkPipelineBindPoint\">VkPipelineBindPoint</a> value"
+        },
+        {
+          "vuid": "VUID-VkGeneratedCommandsInfoNV-pipeline-parameter",
+          "text": " <code>pipeline</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkPipeline\">VkPipeline</a> handle"
+        },
+        {
+          "vuid": "VUID-VkGeneratedCommandsInfoNV-indirectCommandsLayout-parameter",
+          "text": " <code>indirectCommandsLayout</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkIndirectCommandsLayoutNV\">VkIndirectCommandsLayoutNV</a> handle"
+        },
+        {
+          "vuid": "VUID-VkGeneratedCommandsInfoNV-pStreams-parameter",
+          "text": " <code>pStreams</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>streamCount</code> valid <a href=\"#VkIndirectCommandsStreamNV\">VkIndirectCommandsStreamNV</a> structures"
+        },
+        {
+          "vuid": "VUID-VkGeneratedCommandsInfoNV-preprocessBuffer-parameter",
+          "text": " <code>preprocessBuffer</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkBuffer\">VkBuffer</a> handle"
+        },
+        {
+          "vuid": "VUID-VkGeneratedCommandsInfoNV-sequencesCountBuffer-parameter",
           "text": " If <code>sequencesCountBuffer</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, <code>sequencesCountBuffer</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkBuffer\">VkBuffer</a> handle"
         },
         {
-          "vuid": "VUID-VkCmdProcessCommandsInfoNVX-sequencesIndexBuffer-parameter",
+          "vuid": "VUID-VkGeneratedCommandsInfoNV-sequencesIndexBuffer-parameter",
           "text": " If <code>sequencesIndexBuffer</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, <code>sequencesIndexBuffer</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkBuffer\">VkBuffer</a> handle"
         },
         {
-          "vuid": "VUID-VkCmdProcessCommandsInfoNVX-indirectCommandsTokenCount-arraylength",
-          "text": " <code>indirectCommandsTokenCount</code> <strong class=\"purple\">must</strong> be greater than <code>0</code>"
+          "vuid": "VUID-VkGeneratedCommandsInfoNV-streamCount-arraylength",
+          "text": " <code>streamCount</code> <strong class=\"purple\">must</strong> be greater than <code>0</code>"
         },
         {
-          "vuid": "VUID-VkCmdProcessCommandsInfoNVX-commonparent",
-          "text": " Each of <code>indirectCommandsLayout</code>, <code>objectTable</code>, <code>sequencesCountBuffer</code>, <code>sequencesIndexBuffer</code>, and <code>targetCommandBuffer</code> that are valid handles of non-ignored parameters <strong class=\"purple\">must</strong> have been created, allocated, or retrieved from the same <a href=\"#VkDevice\">VkDevice</a>"
+          "vuid": "VUID-VkGeneratedCommandsInfoNV-commonparent",
+          "text": " Each of <code>indirectCommandsLayout</code>, <code>pipeline</code>, <code>preprocessBuffer</code>, <code>sequencesCountBuffer</code>, and <code>sequencesIndexBuffer</code> that are valid handles of non-ignored parameters <strong class=\"purple\">must</strong> have been created, allocated, or retrieved from the same <a href=\"#VkDevice\">VkDevice</a>"
+        }
+      ]
+    },
+    "vkCmdPreprocessGeneratedCommandsNV": {
+      "(VK_NV_device_generated_commands)+(VK_VERSION_1_1)": [
+        {
+          "vuid": "VUID-vkCmdPreprocessGeneratedCommandsNV-commandBuffer-02974",
+          "text": " <code>commandBuffer</code> <strong class=\"purple\">must</strong> not be a protected command buffer"
+        }
+      ],
+      "(VK_NV_device_generated_commands)": [
+        {
+          "vuid": "VUID-vkCmdPreprocessGeneratedCommandsNV-pGeneratedCommandsInfo-02927",
+          "text": " <code>pGeneratedCommandsInfo</code>`s <code>indirectCommandsLayout</code> <strong class=\"purple\">must</strong> have been created with the <code>VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EXPLICIT_PREPROCESS_BIT_NV</code> bit set"
+        },
+        {
+          "vuid": "VUID-vkCmdPreprocessGeneratedCommandsNV-deviceGeneratedCommands-02928",
+          "text": " The <a href=\"#feature-device-generated-commands\"><code>VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV</code>::<code>deviceGeneratedCommands</code></a> feature <strong class=\"purple\">must</strong> be enabled"
+        },
+        {
+          "vuid": "VUID-vkCmdPreprocessGeneratedCommandsNV-commandBuffer-parameter",
+          "text": " <code>commandBuffer</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkCommandBuffer\">VkCommandBuffer</a> handle"
+        },
+        {
+          "vuid": "VUID-vkCmdPreprocessGeneratedCommandsNV-pGeneratedCommandsInfo-parameter",
+          "text": " <code>pGeneratedCommandsInfo</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkGeneratedCommandsInfoNV\">VkGeneratedCommandsInfoNV</a> structure"
+        },
+        {
+          "vuid": "VUID-vkCmdPreprocessGeneratedCommandsNV-commandBuffer-recording",
+          "text": " <code>commandBuffer</code> <strong class=\"purple\">must</strong> be in the <a href=\"#commandbuffers-lifecycle\">recording state</a>"
+        },
+        {
+          "vuid": "VUID-vkCmdPreprocessGeneratedCommandsNV-commandBuffer-cmdpool",
+          "text": " The <code>VkCommandPool</code> that <code>commandBuffer</code> was allocated from <strong class=\"purple\">must</strong> support graphics, or compute operations"
+        },
+        {
+          "vuid": "VUID-vkCmdPreprocessGeneratedCommandsNV-renderpass",
+          "text": " This command <strong class=\"purple\">must</strong> only be called outside of a render pass instance"
         }
       ]
     },
@@ -21460,7 +22298,7 @@
       "core": [
         {
           "vuid": "VUID-vkGetPhysicalDeviceSparseImageFormatProperties-samples-01094",
-          "text": " <code>samples</code> <strong class=\"purple\">must</strong> be a bit value that is set in <code>VkImageFormatProperties</code>::<code>sampleCounts</code> returned by <code>vkGetPhysicalDeviceImageFormatProperties</code> with <code>format</code>, <code>type</code>, <code>tiling</code>, and <code>usage</code> equal to those in this command and <code>flags</code> equal to the value that is set in <code>VkImageCreateInfo</code>::<code>flags</code> when the image is created"
+          "text": " <code>samples</code> <strong class=\"purple\">must</strong> be a bit value that is set in <code>VkImageFormatProperties</code>::<code>sampleCounts</code> returned by <code>vkGetPhysicalDeviceImageFormatProperties</code> with <code>format</code>, <code>type</code>, <code>tiling</code>, and <code>usage</code> equal to those in this command and <code>flags</code> equal to the value that is set in <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>flags</code> when the image is created"
         },
         {
           "vuid": "VUID-vkGetPhysicalDeviceSparseImageFormatProperties-physicalDevice-parameter",
@@ -21524,7 +22362,7 @@
       "(VK_VERSION_1_1,VK_KHR_get_physical_device_properties2)": [
         {
           "vuid": "VUID-VkPhysicalDeviceSparseImageFormatInfo2-samples-01095",
-          "text": " <code>samples</code> <strong class=\"purple\">must</strong> be a bit value that is set in <code>VkImageFormatProperties</code>::<code>sampleCounts</code> returned by <code>vkGetPhysicalDeviceImageFormatProperties</code> with <code>format</code>, <code>type</code>, <code>tiling</code>, and <code>usage</code> equal to those in this command and <code>flags</code> equal to the value that is set in <code>VkImageCreateInfo</code>::<code>flags</code> when the image is created"
+          "text": " <code>samples</code> <strong class=\"purple\">must</strong> be a bit value that is set in <code>VkImageFormatProperties</code>::<code>sampleCounts</code> returned by <code>vkGetPhysicalDeviceImageFormatProperties</code> with <code>format</code>, <code>type</code>, <code>tiling</code>, and <code>usage</code> equal to those in this command and <code>flags</code> equal to the value that is set in <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>flags</code> when the image is created"
         },
         {
           "vuid": "VUID-VkPhysicalDeviceSparseImageFormatInfo2-sType-sType",
@@ -21686,11 +22524,11 @@
       "(VK_VERSION_1_1,VK_KHR_external_memory)": [
         {
           "vuid": "VUID-VkSparseMemoryBind-memory-02730",
-          "text": " If <code>memory</code> was created with <a href=\"#VkExportMemoryAllocateInfo\">VkExportMemoryAllocateInfo</a>::<code>handleTypes</code> not equal to <code>0</code>, at least one handle type it contained <strong class=\"purple\">must</strong> also have been set in <a href=\"#VkExternalMemoryBufferCreateInfo\">VkExternalMemoryBufferCreateInfo</a>::<code>handleTypes</code> or <a href=\"#VkExternalMemoryImageCreateInfo\">VkExternalMemoryImageCreateInfo</a>::<code>handleTypes</code> when the resource was created."
+          "text": " If <code>memory</code> was created with <a href=\"#VkExportMemoryAllocateInfo\">VkExportMemoryAllocateInfo</a>::<code>handleTypes</code> not equal to <code>0</code>, at least one handle type it contained <strong class=\"purple\">must</strong> also have been set in <a href=\"#VkExternalMemoryBufferCreateInfo\">VkExternalMemoryBufferCreateInfo</a>::<code>handleTypes</code> or <a href=\"#VkExternalMemoryImageCreateInfo\">VkExternalMemoryImageCreateInfo</a>::<code>handleTypes</code> when the resource was created"
         },
         {
           "vuid": "VUID-VkSparseMemoryBind-memory-02731",
-          "text": " If <code>memory</code> was created by a memory import operation, the external handle type of the imported memory <strong class=\"purple\">must</strong> also have been set in <a href=\"#VkExternalMemoryBufferCreateInfo\">VkExternalMemoryBufferCreateInfo</a>::<code>handleTypes</code> or <a href=\"#VkExternalMemoryImageCreateInfo\">VkExternalMemoryImageCreateInfo</a>::<code>handleTypes</code> when the resource was created."
+          "text": " If <code>memory</code> was created by a memory import operation, the external handle type of the imported memory <strong class=\"purple\">must</strong> also have been set in <a href=\"#VkExternalMemoryBufferCreateInfo\">VkExternalMemoryBufferCreateInfo</a>::<code>handleTypes</code> or <a href=\"#VkExternalMemoryImageCreateInfo\">VkExternalMemoryImageCreateInfo</a>::<code>handleTypes</code> when the resource was created"
         }
       ]
     },
@@ -21741,6 +22579,10 @@
           "text": " The <code>subresource.arrayLayer</code> member of each element of <code>pBinds</code> <strong class=\"purple\">must</strong> be less than the <code>arrayLayers</code> specified in <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a> when <code>image</code> was created"
         },
         {
+          "vuid": "VUID-VkSparseImageMemoryBindInfo-image-02901",
+          "text": " <code>image</code> <strong class=\"purple\">must</strong> have been created with <code>VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT</code> set"
+        },
+        {
           "vuid": "VUID-VkSparseImageMemoryBindInfo-image-parameter",
           "text": " <code>image</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkImage\">VkImage</a> handle"
         },
@@ -21808,11 +22650,11 @@
       "(VK_VERSION_1_1,VK_KHR_external_memory)": [
         {
           "vuid": "VUID-VkSparseImageMemoryBind-memory-02732",
-          "text": " If <code>memory</code> was created with <a href=\"#VkExportMemoryAllocateInfo\">VkExportMemoryAllocateInfo</a>::<code>handleTypes</code> not equal to <code>0</code>, at least one handle type it contained <strong class=\"purple\">must</strong> also have been set in <a href=\"#VkExternalMemoryImageCreateInfo\">VkExternalMemoryImageCreateInfo</a>::<code>handleTypes</code> when the image was created."
+          "text": " If <code>memory</code> was created with <a href=\"#VkExportMemoryAllocateInfo\">VkExportMemoryAllocateInfo</a>::<code>handleTypes</code> not equal to <code>0</code>, at least one handle type it contained <strong class=\"purple\">must</strong> also have been set in <a href=\"#VkExternalMemoryImageCreateInfo\">VkExternalMemoryImageCreateInfo</a>::<code>handleTypes</code> when the image was created"
         },
         {
           "vuid": "VUID-VkSparseImageMemoryBind-memory-02733",
-          "text": " If <code>memory</code> was created by a memory import operation, the external handle type of the imported memory <strong class=\"purple\">must</strong> also have been set in <a href=\"#VkExternalMemoryImageCreateInfo\">VkExternalMemoryImageCreateInfo</a>::<code>handleTypes</code> when <code>image</code> was created."
+          "text": " If <code>memory</code> was created by a memory import operation, the external handle type of the imported memory <strong class=\"purple\">must</strong> also have been set in <a href=\"#VkExternalMemoryImageCreateInfo\">VkExternalMemoryImageCreateInfo</a>::<code>handleTypes</code> when <code>image</code> was created"
         }
       ]
     },
@@ -21832,7 +22674,7 @@
         },
         {
           "vuid": "VUID-vkQueueBindSparse-pWaitSemaphores-01116",
-          "text": " When a semaphore wait operation referring to a binary semaphore defined by any element of the <code>pWaitSemaphores</code> member of any element of <code>pBindInfo</code> executes on <code>queue</code>, there <strong class=\"purple\">must</strong> be no other queues waiting on the same semaphore."
+          "text": " When a semaphore wait operation referring to a binary semaphore defined by any element of the <code>pWaitSemaphores</code> member of any element of <code>pBindInfo</code> executes on <code>queue</code>, there <strong class=\"purple\">must</strong> be no other queues waiting on the same semaphore"
         },
         {
           "vuid": "VUID-vkQueueBindSparse-pWaitSemaphores-01117",
@@ -21862,7 +22704,7 @@
       "(VK_VERSION_1_2,VK_KHR_timeline_semaphore)": [
         {
           "vuid": "VUID-vkQueueBindSparse-pWaitSemaphores-03245",
-          "text": " All elements of the <code>pWaitSemaphores</code> member of all elements of <code>pBindInfo</code> created with a <a href=\"#VkSemaphoreType\">VkSemaphoreType</a> of <code>VK_SEMAPHORE_TYPE_BINARY</code> <strong class=\"purple\">must</strong> reference a semaphore signal operation that has been submitted for execution and any semaphore signal operations on which it depends (if any) <strong class=\"purple\">must</strong> have also been submitted for execution."
+          "text": " All elements of the <code>pWaitSemaphores</code> member of all elements of <code>pBindInfo</code> created with a <a href=\"#VkSemaphoreType\">VkSemaphoreType</a> of <code>VK_SEMAPHORE_TYPE_BINARY</code> <strong class=\"purple\">must</strong> reference a semaphore signal operation that has been submitted for execution and any semaphore signal operations on which it depends (if any) <strong class=\"purple\">must</strong> have also been submitted for execution"
         }
       ]
     },
@@ -21886,11 +22728,11 @@
         },
         {
           "vuid": "VUID-VkBindSparseInfo-pWaitSemaphores-03250",
-          "text": " For each element of <code>pWaitSemaphores</code> created with a <a href=\"#VkSemaphoreType\">VkSemaphoreType</a> of <code>VK_SEMAPHORE_TYPE_TIMELINE</code> the corresponding element of <a href=\"#VkTimelineSemaphoreSubmitInfo\">VkTimelineSemaphoreSubmitInfo</a>::pWaitSemaphoreValues <strong class=\"purple\">must</strong> have a value which does not differ from the current value of the semaphore or from the value of any outstanding semaphore wait or signal operation on that semaphore by more than <a href=\"#limits-maxTimelineSemaphoreValueDifference\"><code>maxTimelineSemaphoreValueDifference</code></a>."
+          "text": " For each element of <code>pWaitSemaphores</code> created with a <a href=\"#VkSemaphoreType\">VkSemaphoreType</a> of <code>VK_SEMAPHORE_TYPE_TIMELINE</code> the corresponding element of <a href=\"#VkTimelineSemaphoreSubmitInfo\">VkTimelineSemaphoreSubmitInfo</a>::pWaitSemaphoreValues <strong class=\"purple\">must</strong> have a value which does not differ from the current value of the semaphore or from the value of any outstanding semaphore wait or signal operation on that semaphore by more than <a href=\"#limits-maxTimelineSemaphoreValueDifference\"><code>maxTimelineSemaphoreValueDifference</code></a>"
         },
         {
           "vuid": "VUID-VkBindSparseInfo-pSignalSemaphores-03251",
-          "text": " For each element of <code>pSignalSemaphores</code> created with a <a href=\"#VkSemaphoreType\">VkSemaphoreType</a> of <code>VK_SEMAPHORE_TYPE_TIMELINE</code> the corresponding element of <a href=\"#VkTimelineSemaphoreSubmitInfo\">VkTimelineSemaphoreSubmitInfo</a>::pSignalSemaphoreValues <strong class=\"purple\">must</strong> have a value which does not differ from the current value of the semaphore or from the value of any outstanding semaphore wait or signal operation on that semaphore by more than <a href=\"#limits-maxTimelineSemaphoreValueDifference\"><code>maxTimelineSemaphoreValueDifference</code></a>."
+          "text": " For each element of <code>pSignalSemaphores</code> created with a <a href=\"#VkSemaphoreType\">VkSemaphoreType</a> of <code>VK_SEMAPHORE_TYPE_TIMELINE</code> the corresponding element of <a href=\"#VkTimelineSemaphoreSubmitInfo\">VkTimelineSemaphoreSubmitInfo</a>::pSignalSemaphoreValues <strong class=\"purple\">must</strong> have a value which does not differ from the current value of the semaphore or from the value of any outstanding semaphore wait or signal operation on that semaphore by more than <a href=\"#limits-maxTimelineSemaphoreValueDifference\"><code>maxTimelineSemaphoreValueDifference</code></a>"
         }
       ],
       "core": [
@@ -21936,11 +22778,11 @@
       "(VK_VERSION_1_1,VK_KHR_device_group)": [
         {
           "vuid": "VUID-VkDeviceGroupBindSparseInfo-resourceDeviceIndex-01118",
-          "text": " <code>resourceDeviceIndex</code> and <code>memoryDeviceIndex</code> <strong class=\"purple\">must</strong> both be valid device indices."
+          "text": " <code>resourceDeviceIndex</code> and <code>memoryDeviceIndex</code> <strong class=\"purple\">must</strong> both be valid device indices"
         },
         {
           "vuid": "VUID-VkDeviceGroupBindSparseInfo-memoryDeviceIndex-01119",
-          "text": " Each memory allocation bound in this batch <strong class=\"purple\">must</strong> have allocated an instance for <code>memoryDeviceIndex</code>."
+          "text": " Each memory allocation bound in this batch <strong class=\"purple\">must</strong> have allocated an instance for <code>memoryDeviceIndex</code>"
         },
         {
           "vuid": "VUID-VkDeviceGroupBindSparseInfo-sType-sType",
@@ -21972,7 +22814,7 @@
       "(VK_KHR_surface)+(VK_KHR_android_surface)": [
         {
           "vuid": "VUID-VkAndroidSurfaceCreateInfoKHR-window-01248",
-          "text": " <code>window</code> <strong class=\"purple\">must</strong> point to a valid Android <a href=\"#ANativeWindow\">ANativeWindow</a>."
+          "text": " <code>window</code> <strong class=\"purple\">must</strong> point to a valid Android <a href=\"#ANativeWindow\">ANativeWindow</a>"
         },
         {
           "vuid": "VUID-VkAndroidSurfaceCreateInfoKHR-sType-sType",
@@ -22012,11 +22854,11 @@
       "(VK_KHR_surface)+(VK_KHR_wayland_surface)": [
         {
           "vuid": "VUID-VkWaylandSurfaceCreateInfoKHR-display-01304",
-          "text": " <code>display</code> <strong class=\"purple\">must</strong> point to a valid Wayland <code>wl_display</code>."
+          "text": " <code>display</code> <strong class=\"purple\">must</strong> point to a valid Wayland <code>wl_display</code>"
         },
         {
           "vuid": "VUID-VkWaylandSurfaceCreateInfoKHR-surface-01305",
-          "text": " <code>surface</code> <strong class=\"purple\">must</strong> point to a valid Wayland <code>wl_surface</code>."
+          "text": " <code>surface</code> <strong class=\"purple\">must</strong> point to a valid Wayland <code>wl_surface</code>"
         },
         {
           "vuid": "VUID-VkWaylandSurfaceCreateInfoKHR-sType-sType",
@@ -22056,11 +22898,11 @@
       "(VK_KHR_surface)+(VK_KHR_win32_surface)": [
         {
           "vuid": "VUID-VkWin32SurfaceCreateInfoKHR-hinstance-01307",
-          "text": " <code>hinstance</code> <strong class=\"purple\">must</strong> be a valid Win32 <code>HINSTANCE</code>."
+          "text": " <code>hinstance</code> <strong class=\"purple\">must</strong> be a valid Win32 <code>HINSTANCE</code>"
         },
         {
           "vuid": "VUID-VkWin32SurfaceCreateInfoKHR-hwnd-01308",
-          "text": " <code>hwnd</code> <strong class=\"purple\">must</strong> be a valid Win32 <code>HWND</code>."
+          "text": " <code>hwnd</code> <strong class=\"purple\">must</strong> be a valid Win32 <code>HWND</code>"
         },
         {
           "vuid": "VUID-VkWin32SurfaceCreateInfoKHR-sType-sType",
@@ -22100,11 +22942,11 @@
       "(VK_KHR_surface)+(VK_KHR_xcb_surface)": [
         {
           "vuid": "VUID-VkXcbSurfaceCreateInfoKHR-connection-01310",
-          "text": " <code>connection</code> <strong class=\"purple\">must</strong> point to a valid X11 <code>xcb_connection_t</code>."
+          "text": " <code>connection</code> <strong class=\"purple\">must</strong> point to a valid X11 <code>xcb_connection_t</code>"
         },
         {
           "vuid": "VUID-VkXcbSurfaceCreateInfoKHR-window-01311",
-          "text": " <code>window</code> <strong class=\"purple\">must</strong> be a valid X11 <code>xcb_window_t</code>."
+          "text": " <code>window</code> <strong class=\"purple\">must</strong> be a valid X11 <code>xcb_window_t</code>"
         },
         {
           "vuid": "VUID-VkXcbSurfaceCreateInfoKHR-sType-sType",
@@ -22144,11 +22986,11 @@
       "(VK_KHR_surface)+(VK_KHR_xlib_surface)": [
         {
           "vuid": "VUID-VkXlibSurfaceCreateInfoKHR-dpy-01313",
-          "text": " <code>dpy</code> <strong class=\"purple\">must</strong> point to a valid Xlib <code>Display</code>."
+          "text": " <code>dpy</code> <strong class=\"purple\">must</strong> point to a valid Xlib <code>Display</code>"
         },
         {
           "vuid": "VUID-VkXlibSurfaceCreateInfoKHR-window-01314",
-          "text": " <code>window</code> <strong class=\"purple\">must</strong> be a valid Xlib <code>Window</code>."
+          "text": " <code>window</code> <strong class=\"purple\">must</strong> be a valid Xlib <code>Window</code>"
         },
         {
           "vuid": "VUID-VkXlibSurfaceCreateInfoKHR-sType-sType",
@@ -22268,7 +23110,7 @@
       "(VK_KHR_surface)+(VK_MVK_ios_surface)": [
         {
           "vuid": "VUID-VkIOSSurfaceCreateInfoMVK-pView-01316",
-          "text": " <code>pView</code> <strong class=\"purple\">must</strong> be a valid <code>UIView</code> and <strong class=\"purple\">must</strong> be backed by a <code>CALayer</code> instance of type <a href=\"#CAMetalLayer\">CAMetalLayer</a>."
+          "text": " <code>pView</code> <strong class=\"purple\">must</strong> be a valid <code>UIView</code> and <strong class=\"purple\">must</strong> be backed by a <code>CALayer</code> instance of type <a href=\"#CAMetalLayer\">CAMetalLayer</a>"
         },
         {
           "vuid": "VUID-VkIOSSurfaceCreateInfoMVK-sType-sType",
@@ -22308,7 +23150,7 @@
       "(VK_KHR_surface)+(VK_MVK_macos_surface)": [
         {
           "vuid": "VUID-VkMacOSSurfaceCreateInfoMVK-pView-01317",
-          "text": " <code>pView</code> <strong class=\"purple\">must</strong> be a valid <code>NSView</code> and <strong class=\"purple\">must</strong> be backed by a <code>CALayer</code> instance of type <a href=\"#CAMetalLayer\">CAMetalLayer</a>."
+          "text": " <code>pView</code> <strong class=\"purple\">must</strong> be a valid <code>NSView</code> and <strong class=\"purple\">must</strong> be backed by a <code>CALayer</code> instance of type <a href=\"#CAMetalLayer\">CAMetalLayer</a>"
         },
         {
           "vuid": "VUID-VkMacOSSurfaceCreateInfoMVK-sType-sType",
@@ -23024,7 +23866,7 @@
       "(VK_KHR_surface)+(VK_KHR_get_surface_capabilities2)+(VK_EXT_full_screen_exclusive+VK_KHR_win32_surface)": [
         {
           "vuid": "VUID-vkGetPhysicalDeviceSurfaceCapabilities2KHR-pNext-02671",
-          "text": " If a <a href=\"#VkSurfaceCapabilitiesFullScreenExclusiveEXT\">VkSurfaceCapabilitiesFullScreenExclusiveEXT</a> structure is included in the <code>pNext</code> chain of <code>pSurfaceCapabilities</code>, a <a href=\"#VkSurfaceFullScreenExclusiveWin32InfoEXT\">VkSurfaceFullScreenExclusiveWin32InfoEXT</a> structure <strong class=\"purple\">must</strong> be included in the <code>pNext</code> chain of <code>pSurfaceInfo</code>."
+          "text": " If a <a href=\"#VkSurfaceCapabilitiesFullScreenExclusiveEXT\">VkSurfaceCapabilitiesFullScreenExclusiveEXT</a> structure is included in the <code>pNext</code> chain of <code>pSurfaceCapabilities</code>, a <a href=\"#VkSurfaceFullScreenExclusiveWin32InfoEXT\">VkSurfaceFullScreenExclusiveWin32InfoEXT</a> structure <strong class=\"purple\">must</strong> be included in the <code>pNext</code> chain of <code>pSurfaceInfo</code>"
         }
       ],
       "(VK_KHR_surface)+(VK_KHR_get_surface_capabilities2)": [
@@ -23164,7 +24006,7 @@
       "(VK_KHR_surface)+(VK_EXT_display_surface_counter)": [
         {
           "vuid": "VUID-VkSurfaceCapabilities2EXT-supportedSurfaceCounters-01246",
-          "text": " <code>supportedSurfaceCounters</code> <strong class=\"purple\">must</strong> not include <code>VK_SURFACE_COUNTER_VBLANK_EXT</code> unless the surface queried is a <a href=\"#wsi-display-surfaces\">display surface</a>."
+          "text": " <code>supportedSurfaceCounters</code> <strong class=\"purple\">must</strong> not include <code>VK_SURFACE_COUNTER_VBLANK_EXT</code> unless the surface queried is a <a href=\"#wsi-display-surfaces\">display surface</a>"
         },
         {
           "vuid": "VUID-VkSurfaceCapabilities2EXT-sType-sType",
@@ -23180,7 +24022,7 @@
       "(VK_KHR_surface)": [
         {
           "vuid": "VUID-vkGetPhysicalDeviceSurfaceFormatsKHR-surface-02739",
-          "text": " <code>surface</code> must be supported by <code>physicalDevice</code>, as reported by <a href=\"#vkGetPhysicalDeviceSurfaceSupportKHR\">vkGetPhysicalDeviceSurfaceSupportKHR</a> or an equivalent platform-specific mechanism."
+          "text": " <code>surface</code> must be supported by <code>physicalDevice</code>, as reported by <a href=\"#vkGetPhysicalDeviceSurfaceSupportKHR\">vkGetPhysicalDeviceSurfaceSupportKHR</a> or an equivalent platform-specific mechanism"
         },
         {
           "vuid": "VUID-vkGetPhysicalDeviceSurfaceFormatsKHR-physicalDevice-parameter",
@@ -23208,7 +24050,7 @@
       "(VK_KHR_surface)+(VK_KHR_get_surface_capabilities2)": [
         {
           "vuid": "VUID-vkGetPhysicalDeviceSurfaceFormats2KHR-pSurfaceInfo-02740",
-          "text": " <code>pSurfaceInfo-&gt;surface</code> must be supported by <code>physicalDevice</code>, as reported by <a href=\"#vkGetPhysicalDeviceSurfaceSupportKHR\">vkGetPhysicalDeviceSurfaceSupportKHR</a> or an equivalent platform-specific mechanism."
+          "text": " <code>pSurfaceInfo-&gt;surface</code> must be supported by <code>physicalDevice</code>, as reported by <a href=\"#vkGetPhysicalDeviceSurfaceSupportKHR\">vkGetPhysicalDeviceSurfaceSupportKHR</a> or an equivalent platform-specific mechanism"
         },
         {
           "vuid": "VUID-vkGetPhysicalDeviceSurfaceFormats2KHR-physicalDevice-parameter",
@@ -23696,7 +24538,7 @@
         },
         {
           "vuid": "VUID-VkSwapchainDisplayNativeHdrCreateInfoAMD-localDimmingEnable-XXXXX",
-          "text": " It is only valid to set <code>localDimmingEnable</code> to <code>VK_TRUE</code> if <a href=\"#VkDisplayNativeHdrSurfaceCapabilitiesAMD\">VkDisplayNativeHdrSurfaceCapabilitiesAMD</a>::<code>localDimmingSupport</code> is supported."
+          "text": " It is only valid to set <code>localDimmingEnable</code> to <code>VK_TRUE</code> if <a href=\"#VkDisplayNativeHdrSurfaceCapabilitiesAMD\">VkDisplayNativeHdrSurfaceCapabilitiesAMD</a>::<code>localDimmingSupport</code> is supported"
         }
       ]
     },
@@ -23716,7 +24558,7 @@
         },
         {
           "vuid": "VUID-vkSetLocalDimmingAMD-XXXXX",
-          "text": " It is only valid to call <a href=\"#vkSetLocalDimmingAMD\">vkSetLocalDimmingAMD</a> if <a href=\"#VkDisplayNativeHdrSurfaceCapabilitiesAMD\">VkDisplayNativeHdrSurfaceCapabilitiesAMD</a>::<code>localDimmingSupport</code> is supported."
+          "text": " It is only valid to call <a href=\"#vkSetLocalDimmingAMD\">vkSetLocalDimmingAMD</a> if <a href=\"#VkDisplayNativeHdrSurfaceCapabilitiesAMD\">VkDisplayNativeHdrSurfaceCapabilitiesAMD</a>::<code>localDimmingSupport</code> is supported"
         }
       ]
     },
@@ -23724,7 +24566,7 @@
       "(VK_KHR_surface)+(VK_KHR_swapchain)+(VK_EXT_display_control)": [
         {
           "vuid": "VUID-VkSwapchainCounterCreateInfoEXT-surfaceCounters-01244",
-          "text": " The bits in <code>surfaceCounters</code> <strong class=\"purple\">must</strong> be supported by <a href=\"#VkSwapchainCreateInfoKHR\">VkSwapchainCreateInfoKHR</a>::<code>surface</code>, as reported by <a href=\"#vkGetPhysicalDeviceSurfaceCapabilities2EXT\">vkGetPhysicalDeviceSurfaceCapabilities2EXT</a>."
+          "text": " The bits in <code>surfaceCounters</code> <strong class=\"purple\">must</strong> be supported by <a href=\"#VkSwapchainCreateInfoKHR\">VkSwapchainCreateInfoKHR</a>::<code>surface</code>, as reported by <a href=\"#vkGetPhysicalDeviceSurfaceCapabilities2EXT\">vkGetPhysicalDeviceSurfaceCapabilities2EXT</a>"
         },
         {
           "vuid": "VUID-VkSwapchainCounterCreateInfoEXT-sType-sType",
@@ -23740,7 +24582,7 @@
       "(VK_KHR_surface)+(VK_KHR_swapchain)+(VK_EXT_display_control)": [
         {
           "vuid": "VUID-vkGetSwapchainCounterEXT-swapchain-01245",
-          "text": " One or more present commands on <code>swapchain</code> <strong class=\"purple\">must</strong> have been processed by the presentation engine."
+          "text": " One or more present commands on <code>swapchain</code> <strong class=\"purple\">must</strong> have been processed by the presentation engine"
         },
         {
           "vuid": "VUID-vkGetSwapchainCounterEXT-device-parameter",
@@ -24000,7 +24842,7 @@
         },
         {
           "vuid": "VUID-vkQueuePresentKHR-pWaitSemaphores-01294",
-          "text": " When a semaphore wait operation referring to a binary semaphore defined by the elements of the <code>pWaitSemaphores</code> member of <code>pPresentInfo</code> executes on <code>queue</code>, there <strong class=\"purple\">must</strong> be no other queues waiting on the same semaphore."
+          "text": " When a semaphore wait operation referring to a binary semaphore defined by the elements of the <code>pWaitSemaphores</code> member of <code>pPresentInfo</code> executes on <code>queue</code>, there <strong class=\"purple\">must</strong> be no other queues waiting on the same semaphore"
         },
         {
           "vuid": "VUID-vkQueuePresentKHR-pWaitSemaphores-01295",
@@ -24024,11 +24866,11 @@
       "(VK_KHR_surface)+(VK_KHR_swapchain)+(VK_VERSION_1_2,VK_KHR_timeline_semaphore)": [
         {
           "vuid": "VUID-vkQueuePresentKHR-pWaitSemaphores-03267",
-          "text": " All elements of the <code>pWaitSemaphores</code> member of <code>pPresentInfo</code> <strong class=\"purple\">must</strong> be created with a <a href=\"#VkSemaphoreType\">VkSemaphoreType</a> of <code>VK_SEMAPHORE_TYPE_BINARY</code>."
+          "text": " All elements of the <code>pWaitSemaphores</code> member of <code>pPresentInfo</code> <strong class=\"purple\">must</strong> be created with a <a href=\"#VkSemaphoreType\">VkSemaphoreType</a> of <code>VK_SEMAPHORE_TYPE_BINARY</code>"
         },
         {
           "vuid": "VUID-vkQueuePresentKHR-pWaitSemaphores-03268",
-          "text": " All elements of the <code>pWaitSemaphores</code> member of <code>pPresentInfo</code> <strong class=\"purple\">must</strong> reference a semaphore signal operation that has been submitted for execution and any semaphore signal operations on which it depends (if any) <strong class=\"purple\">must</strong> have also been submitted for execution."
+          "text": " All elements of the <code>pWaitSemaphores</code> member of <code>pPresentInfo</code> <strong class=\"purple\">must</strong> reference a semaphore signal operation that has been submitted for execution and any semaphore signal operations on which it depends (if any) <strong class=\"purple\">must</strong> have also been submitted for execution"
         }
       ]
     },
@@ -24122,11 +24964,11 @@
       "(VK_KHR_surface)+(VK_KHR_swapchain)+(VK_KHR_incremental_present)": [
         {
           "vuid": "VUID-VkRectLayerKHR-offset-01261",
-          "text": " The sum of <code>offset</code> and <code>extent</code> <strong class=\"purple\">must</strong> be no greater than the <code>imageExtent</code> member of the <code>VkSwapchainCreateInfoKHR</code> structure given to <a href=\"#vkCreateSwapchainKHR\">vkCreateSwapchainKHR</a>."
+          "text": " The sum of <code>offset</code> and <code>extent</code> <strong class=\"purple\">must</strong> be no greater than the <code>imageExtent</code> member of the <a href=\"#VkSwapchainCreateInfoKHR\">VkSwapchainCreateInfoKHR</a> structure passed to <a href=\"#vkCreateSwapchainKHR\">vkCreateSwapchainKHR</a>"
         },
         {
           "vuid": "VUID-VkRectLayerKHR-layer-01262",
-          "text": " <code>layer</code> <strong class=\"purple\">must</strong> be less than <code>imageArrayLayers</code> member of the <code>VkSwapchainCreateInfoKHR</code> structure given to <a href=\"#vkCreateSwapchainKHR\">vkCreateSwapchainKHR</a>."
+          "text": " <code>layer</code> <strong class=\"purple\">must</strong> be less than the <code>imageArrayLayers</code> member of the <a href=\"#VkSwapchainCreateInfoKHR\">VkSwapchainCreateInfoKHR</a> structure passed to <a href=\"#vkCreateSwapchainKHR\">vkCreateSwapchainKHR</a>"
         }
       ]
     },
@@ -24162,7 +25004,7 @@
         },
         {
           "vuid": "VUID-VkDeviceGroupPresentInfoKHR-mode-01299",
-          "text": " If <code>mode</code> is <code>VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR</code>, then each element of <code>pDeviceMasks</code> <strong class=\"purple\">must</strong> have exactly one bit set, and some physical device in the logical device <strong class=\"purple\">must</strong> include that bit in its <a href=\"#VkDeviceGroupPresentCapabilitiesKHR\">VkDeviceGroupPresentCapabilitiesKHR</a>::<code>presentMask</code>."
+          "text": " If <code>mode</code> is <code>VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR</code>, then each element of <code>pDeviceMasks</code> <strong class=\"purple\">must</strong> have exactly one bit set, and some physical device in the logical device <strong class=\"purple\">must</strong> include that bit in its <a href=\"#VkDeviceGroupPresentCapabilitiesKHR\">VkDeviceGroupPresentCapabilitiesKHR</a>::<code>presentMask</code>"
         },
         {
           "vuid": "VUID-VkDeviceGroupPresentInfoKHR-mode-01300",
@@ -24198,7 +25040,7 @@
       "(VK_KHR_surface)+(VK_KHR_swapchain)+(VK_GOOGLE_display_timing)": [
         {
           "vuid": "VUID-VkPresentTimesInfoGOOGLE-swapchainCount-01247",
-          "text": " <code>swapchainCount</code> <strong class=\"purple\">must</strong> be the same value as <code>VkPresentInfoKHR</code>::<code>swapchainCount</code>, where <code>VkPresentInfoKHR</code> is included in the <code>pNext</code> chain of this <code>VkPresentTimesInfoGOOGLE</code> structure."
+          "text": " <code>swapchainCount</code> <strong class=\"purple\">must</strong> be the same value as <code>VkPresentInfoKHR</code>::<code>swapchainCount</code>, where <code>VkPresentInfoKHR</code> is included in the <code>pNext</code> chain of this <code>VkPresentTimesInfoGOOGLE</code> structure"
         },
         {
           "vuid": "VUID-VkPresentTimesInfoGOOGLE-sType-sType",
@@ -24262,8 +25104,116 @@
         }
       ]
     },
+    "VkDeferredOperationInfoKHR": {
+      "(VK_KHR_deferred_host_operations)": [
+        {
+          "vuid": "VUID-VkDeferredOperationInfoKHR-operationHandle-03433",
+          "text": " Any previous deferred operation that was associated with <code>operationHandle</code> <strong class=\"purple\">must</strong> be complete"
+        },
+        {
+          "vuid": "VUID-VkDeferredOperationInfoKHR-sType-sType",
+          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_DEFERRED_OPERATION_INFO_KHR</code>"
+        }
+      ]
+    },
+    "vkCreateDeferredOperationKHR": {
+      "(VK_KHR_deferred_host_operations)": [
+        {
+          "vuid": "VUID-vkCreateDeferredOperationKHR-device-parameter",
+          "text": " <code>device</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDevice\">VkDevice</a> handle"
+        },
+        {
+          "vuid": "VUID-vkCreateDeferredOperationKHR-pAllocator-parameter",
+          "text": " If <code>pAllocator</code> is not <code>NULL</code>, <code>pAllocator</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkAllocationCallbacks\">VkAllocationCallbacks</a> structure"
+        },
+        {
+          "vuid": "VUID-vkCreateDeferredOperationKHR-pDeferredOperation-parameter",
+          "text": " <code>pDeferredOperation</code> <strong class=\"purple\">must</strong> be a valid pointer to a <a href=\"#VkDeferredOperationKHR\">VkDeferredOperationKHR</a> handle"
+        }
+      ]
+    },
+    "vkDeferredOperationJoinKHR": {
+      "(VK_KHR_deferred_host_operations)": [
+        {
+          "vuid": "VUID-vkDeferredOperationJoinKHR-device-parameter",
+          "text": " <code>device</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDevice\">VkDevice</a> handle"
+        },
+        {
+          "vuid": "VUID-vkDeferredOperationJoinKHR-operation-parameter",
+          "text": " <code>operation</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDeferredOperationKHR\">VkDeferredOperationKHR</a> handle"
+        },
+        {
+          "vuid": "VUID-vkDeferredOperationJoinKHR-operation-parent",
+          "text": " <code>operation</code> <strong class=\"purple\">must</strong> have been created, allocated, or retrieved from <code>device</code>"
+        }
+      ]
+    },
+    "vkDestroyDeferredOperationKHR": {
+      "(VK_KHR_deferred_host_operations)": [
+        {
+          "vuid": "VUID-vkDestroyDeferredOperationKHR-operation-03434",
+          "text": " If <code>VkAllocationCallbacks</code> were provided when <code>operation</code> was created, a compatible set of callbacks <strong class=\"purple\">must</strong> be provided here"
+        },
+        {
+          "vuid": "VUID-vkDestroyDeferredOperationKHR-operation-03435",
+          "text": " If no <code>VkAllocationCallbacks</code> were provided when <code>operation</code> was created, <code>pAllocator</code> <strong class=\"purple\">must</strong> be <code>NULL</code>"
+        },
+        {
+          "vuid": "VUID-vkDestroyDeferredOperationKHR-operation-03436",
+          "text": " <code>operation</code> <strong class=\"purple\">must</strong> be completed"
+        },
+        {
+          "vuid": "VUID-vkDestroyDeferredOperationKHR-device-parameter",
+          "text": " <code>device</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDevice\">VkDevice</a> handle"
+        },
+        {
+          "vuid": "VUID-vkDestroyDeferredOperationKHR-operation-parameter",
+          "text": " <code>operation</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDeferredOperationKHR\">VkDeferredOperationKHR</a> handle"
+        },
+        {
+          "vuid": "VUID-vkDestroyDeferredOperationKHR-pAllocator-parameter",
+          "text": " If <code>pAllocator</code> is not <code>NULL</code>, <code>pAllocator</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkAllocationCallbacks\">VkAllocationCallbacks</a> structure"
+        },
+        {
+          "vuid": "VUID-vkDestroyDeferredOperationKHR-operation-parent",
+          "text": " <code>operation</code> <strong class=\"purple\">must</strong> have been created, allocated, or retrieved from <code>device</code>"
+        }
+      ]
+    },
+    "vkGetDeferredOperationMaxConcurrencyKHR": {
+      "(VK_KHR_deferred_host_operations)": [
+        {
+          "vuid": "VUID-vkGetDeferredOperationMaxConcurrencyKHR-device-parameter",
+          "text": " <code>device</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDevice\">VkDevice</a> handle"
+        },
+        {
+          "vuid": "VUID-vkGetDeferredOperationMaxConcurrencyKHR-operation-parameter",
+          "text": " <code>operation</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDeferredOperationKHR\">VkDeferredOperationKHR</a> handle"
+        },
+        {
+          "vuid": "VUID-vkGetDeferredOperationMaxConcurrencyKHR-operation-parent",
+          "text": " <code>operation</code> <strong class=\"purple\">must</strong> have been created, allocated, or retrieved from <code>device</code>"
+        }
+      ]
+    },
+    "vkGetDeferredOperationResultKHR": {
+      "(VK_KHR_deferred_host_operations)": [
+        {
+          "vuid": "VUID-vkGetDeferredOperationResultKHR-device-parameter",
+          "text": " <code>device</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDevice\">VkDevice</a> handle"
+        },
+        {
+          "vuid": "VUID-vkGetDeferredOperationResultKHR-operation-parameter",
+          "text": " <code>operation</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDeferredOperationKHR\">VkDeferredOperationKHR</a> handle"
+        },
+        {
+          "vuid": "VUID-vkGetDeferredOperationResultKHR-operation-parent",
+          "text": " <code>operation</code> <strong class=\"purple\">must</strong> have been created, allocated, or retrieved from <code>device</code>"
+        }
+      ]
+    },
     "vkCmdTraceRaysNV": {
-      "(VK_NV_ray_tracing)": [
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_NV_ray_tracing)": [
         {
           "vuid": "VUID-vkCmdTraceRaysNV-None-02690",
           "text": " If a <code>VkImageView</code> is sampled with <code>VK_FILTER_LINEAR</code> as a result of this command, then the image view&#8217;s <a href=\"#resources-image-view-format-features\">format features</a> <strong class=\"purple\">must</strong> contain <code>VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT</code>"
@@ -24322,7 +25272,7 @@
         },
         {
           "vuid": "VUID-vkCmdTraceRaysNV-raygenShaderBindingOffset-02456",
-          "text": " <code>raygenShaderBindingOffset</code> <strong class=\"purple\">must</strong> be a multiple of <code>VkPhysicalDeviceRayTracingPropertiesNV</code>::<code>shaderGroupBaseAlignment</code>"
+          "text": " <code>raygenShaderBindingOffset</code> <strong class=\"purple\">must</strong> be a multiple of <code>VkPhysicalDeviceRayTracingPropertiesKHR</code>::<code>shaderGroupBaseAlignment</code>"
         },
         {
           "vuid": "VUID-vkCmdTraceRaysNV-missShaderBindingOffset-02457",
@@ -24330,7 +25280,7 @@
         },
         {
           "vuid": "VUID-vkCmdTraceRaysNV-missShaderBindingOffset-02458",
-          "text": " <code>missShaderBindingOffset</code> <strong class=\"purple\">must</strong> be a multiple of <code>VkPhysicalDeviceRayTracingPropertiesNV</code>::<code>shaderGroupBaseAlignment</code>"
+          "text": " <code>missShaderBindingOffset</code> <strong class=\"purple\">must</strong> be a multiple of <code>VkPhysicalDeviceRayTracingPropertiesKHR</code>::<code>shaderGroupBaseAlignment</code>"
         },
         {
           "vuid": "VUID-vkCmdTraceRaysNV-hitShaderBindingOffset-02459",
@@ -24338,7 +25288,7 @@
         },
         {
           "vuid": "VUID-vkCmdTraceRaysNV-hitShaderBindingOffset-02460",
-          "text": " <code>hitShaderBindingOffset</code> <strong class=\"purple\">must</strong> be a multiple of <code>VkPhysicalDeviceRayTracingPropertiesNV</code>::<code>shaderGroupBaseAlignment</code>"
+          "text": " <code>hitShaderBindingOffset</code> <strong class=\"purple\">must</strong> be a multiple of <code>VkPhysicalDeviceRayTracingPropertiesKHR</code>::<code>shaderGroupBaseAlignment</code>"
         },
         {
           "vuid": "VUID-vkCmdTraceRaysNV-callableShaderBindingOffset-02461",
@@ -24346,31 +25296,39 @@
         },
         {
           "vuid": "VUID-vkCmdTraceRaysNV-callableShaderBindingOffset-02462",
-          "text": " <code>callableShaderBindingOffset</code> <strong class=\"purple\">must</strong> be a multiple of <code>VkPhysicalDeviceRayTracingPropertiesNV</code>::<code>shaderGroupBaseAlignment</code>"
+          "text": " <code>callableShaderBindingOffset</code> <strong class=\"purple\">must</strong> be a multiple of <code>VkPhysicalDeviceRayTracingPropertiesKHR</code>::<code>shaderGroupBaseAlignment</code>"
         },
         {
           "vuid": "VUID-vkCmdTraceRaysNV-missShaderBindingStride-02463",
-          "text": " <code>missShaderBindingStride</code> <strong class=\"purple\">must</strong> be a multiple of <code>VkPhysicalDeviceRayTracingPropertiesNV</code>::<code>shaderGroupHandleSize</code>"
+          "text": " <code>missShaderBindingStride</code> <strong class=\"purple\">must</strong> be a multiple of <code>VkPhysicalDeviceRayTracingPropertiesKHR</code>::<code>shaderGroupHandleSize</code>"
         },
         {
           "vuid": "VUID-vkCmdTraceRaysNV-hitShaderBindingStride-02464",
-          "text": " <code>hitShaderBindingStride</code> <strong class=\"purple\">must</strong> be a multiple of <code>VkPhysicalDeviceRayTracingPropertiesNV</code>::<code>shaderGroupHandleSize</code>"
+          "text": " <code>hitShaderBindingStride</code> <strong class=\"purple\">must</strong> be a multiple of <code>VkPhysicalDeviceRayTracingPropertiesKHR</code>::<code>shaderGroupHandleSize</code>"
         },
         {
           "vuid": "VUID-vkCmdTraceRaysNV-callableShaderBindingStride-02465",
-          "text": " <code>callableShaderBindingStride</code> <strong class=\"purple\">must</strong> be a multiple of <code>VkPhysicalDeviceRayTracingPropertiesNV</code>::<code>shaderGroupHandleSize</code>"
+          "text": " <code>callableShaderBindingStride</code> <strong class=\"purple\">must</strong> be a multiple of <code>VkPhysicalDeviceRayTracingPropertiesKHR</code>::<code>shaderGroupHandleSize</code>"
         },
         {
           "vuid": "VUID-vkCmdTraceRaysNV-missShaderBindingStride-02466",
-          "text": " <code>missShaderBindingStride</code> <strong class=\"purple\">must</strong> be a less than or equal to <code>VkPhysicalDeviceRayTracingPropertiesNV</code>::<code>maxShaderGroupStride</code>"
+          "text": " <code>missShaderBindingStride</code> <strong class=\"purple\">must</strong> be less than or equal to <code>VkPhysicalDeviceRayTracingPropertiesKHR</code>::<code>maxShaderGroupStride</code>"
         },
         {
           "vuid": "VUID-vkCmdTraceRaysNV-hitShaderBindingStride-02467",
-          "text": " <code>hitShaderBindingStride</code> <strong class=\"purple\">must</strong> be a less than or equal to <code>VkPhysicalDeviceRayTracingPropertiesNV</code>::<code>maxShaderGroupStride</code>"
+          "text": " <code>hitShaderBindingStride</code> <strong class=\"purple\">must</strong> be less than or equal to <code>VkPhysicalDeviceRayTracingPropertiesKHR</code>::<code>maxShaderGroupStride</code>"
         },
         {
           "vuid": "VUID-vkCmdTraceRaysNV-callableShaderBindingStride-02468",
-          "text": " <code>callableShaderBindingStride</code> <strong class=\"purple\">must</strong> be a less than or equal to <code>VkPhysicalDeviceRayTracingPropertiesNV</code>::<code>maxShaderGroupStride</code>"
+          "text": " <code>callableShaderBindingStride</code> <strong class=\"purple\">must</strong> be less than or equal to <code>VkPhysicalDeviceRayTracingPropertiesKHR</code>::<code>maxShaderGroupStride</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysNV-None-03429",
+          "text": " Any shader group handle referenced by this call <strong class=\"purple\">must</strong> have been queried from the currently bound ray tracing shader pipeline"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysNV-maxRecursionDepth-03430",
+          "text": " This command <strong class=\"purple\">must</strong> not cause a shader call instruction to be executed from a shader invocation with a <a href=\"#ray-tracing-recursion-depth\">recursion depth</a> greater than the value of <code>maxRecursionDepth</code> used to create the bound ray tracing pipeline."
         },
         {
           "vuid": "VUID-vkCmdTraceRaysNV-width-02469",
@@ -24421,19 +25379,19 @@
           "text": " Each of <code>callableShaderBindingTableBuffer</code>, <code>commandBuffer</code>, <code>hitShaderBindingTableBuffer</code>, <code>missShaderBindingTableBuffer</code>, and <code>raygenShaderBindingTableBuffer</code> that are valid handles of non-ignored parameters <strong class=\"purple\">must</strong> have been created, allocated, or retrieved from the same <a href=\"#VkDevice\">VkDevice</a>"
         }
       ],
-      "(VK_NV_ray_tracing)+(VK_IMG_filter_cubic,VK_EXT_filter_cubic)": [
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_NV_ray_tracing)+(VK_IMG_filter_cubic,VK_EXT_filter_cubic)": [
         {
           "vuid": "VUID-vkCmdTraceRaysNV-None-02692",
           "text": " If a <code>VkImageView</code> is sampled with <code>VK_FILTER_CUBIC_EXT</code> as a result of this command, then the image view&#8217;s <a href=\"#resources-image-view-format-features\">format features</a> <strong class=\"purple\">must</strong> contain <code>VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT</code>"
         }
       ],
-      "(VK_NV_ray_tracing)+(VK_IMG_filter_cubic,VK_EXT_filter_cubic)+!(VK_EXT_filter_cubic)": [
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_NV_ray_tracing)+(VK_IMG_filter_cubic,VK_EXT_filter_cubic)+!(VK_EXT_filter_cubic)": [
         {
           "vuid": "VUID-vkCmdTraceRaysNV-None-02693",
           "text": " Any <a href=\"#VkImageView\">VkImageView</a> being sampled with <code>VK_FILTER_CUBIC_EXT</code> as a result of this command <strong class=\"purple\">must</strong> not have a <a href=\"#VkImageViewType\">VkImageViewType</a> of <code>VK_IMAGE_VIEW_TYPE_3D</code>, <code>VK_IMAGE_VIEW_TYPE_CUBE</code>, or <code>VK_IMAGE_VIEW_TYPE_CUBE_ARRAY</code>"
         }
       ],
-      "(VK_NV_ray_tracing)+(VK_IMG_filter_cubic,VK_EXT_filter_cubic)+(VK_EXT_filter_cubic)": [
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_NV_ray_tracing)+(VK_IMG_filter_cubic,VK_EXT_filter_cubic)+(VK_EXT_filter_cubic)": [
         {
           "vuid": "VUID-vkCmdTraceRaysNV-filterCubic-02694",
           "text": " Any <a href=\"#VkImageView\">VkImageView</a> being sampled with <code>VK_FILTER_CUBIC_EXT</code> as a result of this command <strong class=\"purple\">must</strong> have a <a href=\"#VkImageViewType\">VkImageViewType</a> and format that supports cubic filtering, as specified by <code>VkFilterCubicImageViewImageFormatPropertiesEXT</code>::<code>filterCubic</code> returned by <code>vkGetPhysicalDeviceImageFormatProperties2</code>"
@@ -24443,13 +25401,13 @@
           "text": " Any <a href=\"#VkImageView\">VkImageView</a> being sampled with <code>VK_FILTER_CUBIC_EXT</code> with a reduction mode of either <code>VK_SAMPLER_REDUCTION_MODE_MIN</code> or <code>VK_SAMPLER_REDUCTION_MODE_MAX</code> as a result of this command <strong class=\"purple\">must</strong> have a <a href=\"#VkImageViewType\">VkImageViewType</a> and format that supports cubic filtering together with minmax filtering, as specified by <code>VkFilterCubicImageViewImageFormatPropertiesEXT</code>::<code>filterCubicMinmax</code> returned by <code>vkGetPhysicalDeviceImageFormatProperties2</code>"
         }
       ],
-      "(VK_NV_ray_tracing)+(VK_NV_corner_sampled_image)": [
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_NV_ray_tracing)+(VK_NV_corner_sampled_image)": [
         {
           "vuid": "VUID-vkCmdTraceRaysNV-flags-02696",
-          "text": " Any <a href=\"#VkImage\">VkImage</a> created with a <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>flags</code> containing <code>VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV</code> sampled as a result of this command <strong class=\"purple\">must</strong> only be sampled using a <a href=\"#VkSamplerAddressMode\">VkSamplerAddressMode</a> of <code>VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE</code>."
+          "text": " Any <a href=\"#VkImage\">VkImage</a> created with a <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>flags</code> containing <code>VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV</code> sampled as a result of this command <strong class=\"purple\">must</strong> only be sampled using a <a href=\"#VkSamplerAddressMode\">VkSamplerAddressMode</a> of <code>VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE</code>"
         }
       ],
-      "(VK_NV_ray_tracing)+(VK_VERSION_1_1)": [
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_NV_ray_tracing)+(VK_VERSION_1_1)": [
         {
           "vuid": "VUID-vkCmdTraceRaysNV-commandBuffer-02707",
           "text": " If <code>commandBuffer</code> is an unprotected command buffer, any resource accessed by the <code>VkPipeline</code> object bound to the pipeline bind point used by this command <strong class=\"purple\">must</strong> not be a protected resource"
@@ -24464,15 +25422,499 @@
         }
       ]
     },
+    "vkCmdTraceRaysKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-None-02690",
+          "text": " If a <code>VkImageView</code> is sampled with <code>VK_FILTER_LINEAR</code> as a result of this command, then the image view&#8217;s <a href=\"#resources-image-view-format-features\">format features</a> <strong class=\"purple\">must</strong> contain <code>VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-None-02691",
+          "text": " If a <code>VkImageView</code> is accessed using atomic operations as a result of this command, then the image view&#8217;s <a href=\"#resources-image-view-format-features\">format features</a> <strong class=\"purple\">must</strong> contain <code>VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-None-02697",
+          "text": " For each set <em>n</em> that is statically used by the <code>VkPipeline</code> bound to the pipeline bind point used by this command, a descriptor set <strong class=\"purple\">must</strong> have been bound to <em>n</em> at the same pipeline bind point, with a <code>VkPipelineLayout</code> that is compatible for set <em>n</em>, with the <code>VkPipelineLayout</code> used to create the current <code>VkPipeline</code>, as described in <a href=\"#descriptorsets-compatibility\">Pipeline Layout Compatibility</a>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-None-02698",
+          "text": " For each push constant that is statically used by the <code>VkPipeline</code> bound to the pipeline bind point used by this command, a push constant value <strong class=\"purple\">must</strong> have been set for the same pipeline bind point, with a <code>VkPipelineLayout</code> that is compatible for push constants, with the <code>VkPipelineLayout</code> used to create the current <code>VkPipeline</code>, as described in <a href=\"#descriptorsets-compatibility\">Pipeline Layout Compatibility</a>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-None-02699",
+          "text": " Descriptors in each bound descriptor set, specified via <code>vkCmdBindDescriptorSets</code>, <strong class=\"purple\">must</strong> be valid if they are statically used by the <code>VkPipeline</code> bound to the pipeline bind point used by this command"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-None-02700",
+          "text": " A valid pipeline <strong class=\"purple\">must</strong> be bound to the pipeline bind point used by this command"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-commandBuffer-02701",
+          "text": " If the <code>VkPipeline</code> object bound to the pipeline bind point used by this command requires any dynamic state, that state <strong class=\"purple\">must</strong> have been set for <code>commandBuffer</code>, and done so after any previously bound pipeline with the corresponding state not specified as dynamic"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-None-02859",
+          "text": " There <strong class=\"purple\">must</strong> not have been any calls to dynamic state setting commands for any state not specified as dynamic in the <code>VkPipeline</code> object bound to the pipeline bind point used by this command, since that pipeline was bound"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-None-02702",
+          "text": " If the <code>VkPipeline</code> object bound to the pipeline bind point used by this command accesses a <code>VkSampler</code> object that uses unnormalized coordinates, that sampler <strong class=\"purple\">must</strong> not be used to sample from any <code>VkImage</code> with a <code>VkImageView</code> of the type <code>VK_IMAGE_VIEW_TYPE_3D</code>, <code>VK_IMAGE_VIEW_TYPE_CUBE</code>, <code>VK_IMAGE_VIEW_TYPE_1D_ARRAY</code>, <code>VK_IMAGE_VIEW_TYPE_2D_ARRAY</code> or <code>VK_IMAGE_VIEW_TYPE_CUBE_ARRAY</code>, in any shader stage"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-None-02703",
+          "text": " If the <code>VkPipeline</code> object bound to the pipeline bind point used by this command accesses a <code>VkSampler</code> object that uses unnormalized coordinates, that sampler <strong class=\"purple\">must</strong> not be used with any of the SPIR-V <code>OpImageSample*</code> or <code>OpImageSparseSample*</code> instructions with <code>ImplicitLod</code>, <code>Dref</code> or <code>Proj</code> in their name, in any shader stage"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-None-02704",
+          "text": " If the <code>VkPipeline</code> object bound to the pipeline bind point used by this command accesses a <code>VkSampler</code> object that uses unnormalized coordinates, that sampler <strong class=\"purple\">must</strong> not be used with any of the SPIR-V <code>OpImageSample*</code> or <code>OpImageSparseSample*</code> instructions that includes a LOD bias or any offset values, in any shader stage"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-None-02705",
+          "text": " If the <a href=\"#features-robustBufferAccess\">robust buffer access</a> feature is not enabled, and if the <code>VkPipeline</code> object bound to the pipeline bind point used by this command accesses a uniform buffer, it <strong class=\"purple\">must</strong> not access values outside of the range of the buffer as specified in the descriptor set bound to the same pipeline bind point"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-None-02706",
+          "text": " If the <a href=\"#features-robustBufferAccess\">robust buffer access</a> feature is not enabled, and if the <code>VkPipeline</code> object bound to the pipeline bind point used by this command accesses a storage buffer, it <strong class=\"purple\">must</strong> not access values outside of the range of the buffer as specified in the descriptor set bound to the same pipeline bind point"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-raygenShaderBindingOffset-02455",
+          "text": " <code>raygenShaderBindingOffset</code> <strong class=\"purple\">must</strong> be less than the size of <code>raygenShaderBindingTableBuffer</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-raygenShaderBindingOffset-02456",
+          "text": " <code>raygenShaderBindingOffset</code> <strong class=\"purple\">must</strong> be a multiple of <code>VkPhysicalDeviceRayTracingPropertiesKHR</code>::<code>shaderGroupBaseAlignment</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-missShaderBindingOffset-02457",
+          "text": " <code>missShaderBindingOffset</code> <strong class=\"purple\">must</strong> be less than the size of <code>missShaderBindingTableBuffer</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-missShaderBindingOffset-02458",
+          "text": " <code>missShaderBindingOffset</code> <strong class=\"purple\">must</strong> be a multiple of <code>VkPhysicalDeviceRayTracingPropertiesKHR</code>::<code>shaderGroupBaseAlignment</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-hitShaderBindingOffset-02459",
+          "text": " <code>hitShaderBindingOffset</code> <strong class=\"purple\">must</strong> be less than the size of <code>hitShaderBindingTableBuffer</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-hitShaderBindingOffset-02460",
+          "text": " <code>hitShaderBindingOffset</code> <strong class=\"purple\">must</strong> be a multiple of <code>VkPhysicalDeviceRayTracingPropertiesKHR</code>::<code>shaderGroupBaseAlignment</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-callableShaderBindingOffset-02461",
+          "text": " <code>callableShaderBindingOffset</code> <strong class=\"purple\">must</strong> be less than the size of <code>callableShaderBindingTableBuffer</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-callableShaderBindingOffset-02462",
+          "text": " <code>callableShaderBindingOffset</code> <strong class=\"purple\">must</strong> be a multiple of <code>VkPhysicalDeviceRayTracingPropertiesKHR</code>::<code>shaderGroupBaseAlignment</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-missShaderBindingStride-02463",
+          "text": " <code>missShaderBindingStride</code> <strong class=\"purple\">must</strong> be a multiple of <code>VkPhysicalDeviceRayTracingPropertiesKHR</code>::<code>shaderGroupHandleSize</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-hitShaderBindingStride-02464",
+          "text": " <code>hitShaderBindingStride</code> <strong class=\"purple\">must</strong> be a multiple of <code>VkPhysicalDeviceRayTracingPropertiesKHR</code>::<code>shaderGroupHandleSize</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-callableShaderBindingStride-02465",
+          "text": " <code>callableShaderBindingStride</code> <strong class=\"purple\">must</strong> be a multiple of <code>VkPhysicalDeviceRayTracingPropertiesKHR</code>::<code>shaderGroupHandleSize</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-missShaderBindingStride-02466",
+          "text": " <code>missShaderBindingStride</code> <strong class=\"purple\">must</strong> be less than or equal to <code>VkPhysicalDeviceRayTracingPropertiesKHR</code>::<code>maxShaderGroupStride</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-hitShaderBindingStride-02467",
+          "text": " <code>hitShaderBindingStride</code> <strong class=\"purple\">must</strong> be less than or equal to <code>VkPhysicalDeviceRayTracingPropertiesKHR</code>::<code>maxShaderGroupStride</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-callableShaderBindingStride-02468",
+          "text": " <code>callableShaderBindingStride</code> <strong class=\"purple\">must</strong> be less than or equal to <code>VkPhysicalDeviceRayTracingPropertiesKHR</code>::<code>maxShaderGroupStride</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-None-03429",
+          "text": " Any shader group handle referenced by this call <strong class=\"purple\">must</strong> have been queried from the currently bound ray tracing shader pipeline"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-maxRecursionDepth-03430",
+          "text": " This command <strong class=\"purple\">must</strong> not cause a shader call instruction to be executed from a shader invocation with a <a href=\"#ray-tracing-recursion-depth\">recursion depth</a> greater than the value of <code>maxRecursionDepth</code> used to create the bound ray tracing pipeline."
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-width-03505",
+          "text": " <code>width</code> <strong class=\"purple\">must</strong> be less than or equal to <code>VkPhysicalDeviceLimits</code>::<code>maxComputeWorkGroupCount</code>[0]"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-height-03506",
+          "text": " <code>height</code> <strong class=\"purple\">must</strong> be less than or equal to <code>VkPhysicalDeviceLimits</code>::<code>maxComputeWorkGroupCount</code>[1]"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-depth-03507",
+          "text": " <code>depth</code> <strong class=\"purple\">must</strong> be less than or equal to <code>VkPhysicalDeviceLimits</code>::<code>maxComputeWorkGroupCount</code>[2]"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-flags-03508",
+          "text": " If the currently bound ray tracing pipeline was created with <code>flags</code> that included <code>VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_ANY_HIT_SHADERS_BIT_KHR</code>, the <code>buffer</code> member of <code>hitShaderBindingTable</code> <strong class=\"purple\">must</strong> not be <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-flags-03509",
+          "text": " If the currently bound ray tracing pipeline was created with <code>flags</code> that included <code>VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_CLOSEST_HIT_SHADERS_BIT_KHR</code>, the <code>buffer</code> member of <code>hitShaderBindingTable</code> <strong class=\"purple\">must</strong> not be <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-flags-03510",
+          "text": " If the currently bound ray tracing pipeline was created with <code>flags</code> that included <code>VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_INTERSECTION_SHADERS_BIT_KHR</code>, the <code>buffer</code> member of <code>hitShaderBindingTable</code> <strong class=\"purple\">must</strong> not be <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-flags-03511",
+          "text": " If the currently bound ray tracing pipeline was created with <code>flags</code> that included <code>VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_MISS_SHADERS_BIT_KHR</code>, the shader group handle identified by <code>missShaderBindingTable</code> <strong class=\"purple\">must</strong> contain a valid miss shader"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-flags-03512",
+          "text": " If the currently bound ray tracing pipeline was created with <code>flags</code> that included <code>VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_ANY_HIT_SHADERS_BIT_KHR</code>, entries in <code>hitShaderBindingTable</code> accessed as a result of this command in order to execute an any hit shader <strong class=\"purple\">must</strong> not be set to zero"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-flags-03513",
+          "text": " If the currently bound ray tracing pipeline was created with <code>flags</code> that included <code>VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_CLOSEST_HIT_SHADERS_BIT_KHR</code>, entries in <code>hitShaderBindingTable</code> accessed as a result of this command in order to execute a closest hit shader <strong class=\"purple\">must</strong> not be set to zero"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-flags-03514",
+          "text": " If the currently bound ray tracing pipeline was created with <code>flags</code> that included <code>VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_INTERSECTION_SHADERS_BIT_KHR</code>, entries in <code>hitShaderBindingTable</code> accessed as a result of this command in order to execute an intersection shader <strong class=\"purple\">must</strong> not be set to zero"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-commandBuffer-parameter",
+          "text": " <code>commandBuffer</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkCommandBuffer\">VkCommandBuffer</a> handle"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-pRaygenShaderBindingTable-parameter",
+          "text": " <code>pRaygenShaderBindingTable</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkStridedBufferRegionKHR\">VkStridedBufferRegionKHR</a> structure"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-pMissShaderBindingTable-parameter",
+          "text": " <code>pMissShaderBindingTable</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkStridedBufferRegionKHR\">VkStridedBufferRegionKHR</a> structure"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-pHitShaderBindingTable-parameter",
+          "text": " <code>pHitShaderBindingTable</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkStridedBufferRegionKHR\">VkStridedBufferRegionKHR</a> structure"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-pCallableShaderBindingTable-parameter",
+          "text": " <code>pCallableShaderBindingTable</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkStridedBufferRegionKHR\">VkStridedBufferRegionKHR</a> structure"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-commandBuffer-recording",
+          "text": " <code>commandBuffer</code> <strong class=\"purple\">must</strong> be in the <a href=\"#commandbuffers-lifecycle\">recording state</a>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-commandBuffer-cmdpool",
+          "text": " The <code>VkCommandPool</code> that <code>commandBuffer</code> was allocated from <strong class=\"purple\">must</strong> support compute operations"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-renderpass",
+          "text": " This command <strong class=\"purple\">must</strong> only be called outside of a render pass instance"
+        }
+      ],
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)+(VK_IMG_filter_cubic,VK_EXT_filter_cubic)": [
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-None-02692",
+          "text": " If a <code>VkImageView</code> is sampled with <code>VK_FILTER_CUBIC_EXT</code> as a result of this command, then the image view&#8217;s <a href=\"#resources-image-view-format-features\">format features</a> <strong class=\"purple\">must</strong> contain <code>VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT</code>"
+        }
+      ],
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)+(VK_IMG_filter_cubic,VK_EXT_filter_cubic)+!(VK_EXT_filter_cubic)": [
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-None-02693",
+          "text": " Any <a href=\"#VkImageView\">VkImageView</a> being sampled with <code>VK_FILTER_CUBIC_EXT</code> as a result of this command <strong class=\"purple\">must</strong> not have a <a href=\"#VkImageViewType\">VkImageViewType</a> of <code>VK_IMAGE_VIEW_TYPE_3D</code>, <code>VK_IMAGE_VIEW_TYPE_CUBE</code>, or <code>VK_IMAGE_VIEW_TYPE_CUBE_ARRAY</code>"
+        }
+      ],
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)+(VK_IMG_filter_cubic,VK_EXT_filter_cubic)+(VK_EXT_filter_cubic)": [
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-filterCubic-02694",
+          "text": " Any <a href=\"#VkImageView\">VkImageView</a> being sampled with <code>VK_FILTER_CUBIC_EXT</code> as a result of this command <strong class=\"purple\">must</strong> have a <a href=\"#VkImageViewType\">VkImageViewType</a> and format that supports cubic filtering, as specified by <code>VkFilterCubicImageViewImageFormatPropertiesEXT</code>::<code>filterCubic</code> returned by <code>vkGetPhysicalDeviceImageFormatProperties2</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-filterCubicMinmax-02695",
+          "text": " Any <a href=\"#VkImageView\">VkImageView</a> being sampled with <code>VK_FILTER_CUBIC_EXT</code> with a reduction mode of either <code>VK_SAMPLER_REDUCTION_MODE_MIN</code> or <code>VK_SAMPLER_REDUCTION_MODE_MAX</code> as a result of this command <strong class=\"purple\">must</strong> have a <a href=\"#VkImageViewType\">VkImageViewType</a> and format that supports cubic filtering together with minmax filtering, as specified by <code>VkFilterCubicImageViewImageFormatPropertiesEXT</code>::<code>filterCubicMinmax</code> returned by <code>vkGetPhysicalDeviceImageFormatProperties2</code>"
+        }
+      ],
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)+(VK_NV_corner_sampled_image)": [
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-flags-02696",
+          "text": " Any <a href=\"#VkImage\">VkImage</a> created with a <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>flags</code> containing <code>VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV</code> sampled as a result of this command <strong class=\"purple\">must</strong> only be sampled using a <a href=\"#VkSamplerAddressMode\">VkSamplerAddressMode</a> of <code>VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE</code>"
+        }
+      ],
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)+(VK_VERSION_1_1)": [
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-commandBuffer-02707",
+          "text": " If <code>commandBuffer</code> is an unprotected command buffer, any resource accessed by the <code>VkPipeline</code> object bound to the pipeline bind point used by this command <strong class=\"purple\">must</strong> not be a protected resource"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-commandBuffer-02712",
+          "text": " If <code>commandBuffer</code> is a protected command buffer, any resource written to by the <code>VkPipeline</code> object bound to the pipeline bind point used by this command <strong class=\"purple\">must</strong> not be an unprotected resource"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysKHR-commandBuffer-02713",
+          "text": " If <code>commandBuffer</code> is a protected command buffer, pipeline stages other than the framebuffer-space and compute stages in the <code>VkPipeline</code> object bound to the pipeline bind point <strong class=\"purple\">must</strong> not write to any resource"
+        }
+      ]
+    },
+    "VkStridedBufferRegionKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-VkStridedBufferRegionKHR-buffer-03515",
+          "text": " If <code>buffer</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, <code>size</code> plus <code>offset</code> <strong class=\"purple\">must</strong> be less than or equal to the size of <code>buffer</code>"
+        },
+        {
+          "vuid": "VUID-VkStridedBufferRegionKHR-buffer-03516",
+          "text": " If <code>buffer</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, <code>stride</code> <strong class=\"purple\">must</strong> be less than the size of <code>buffer</code>"
+        },
+        {
+          "vuid": "VUID-VkStridedBufferRegionKHR-buffer-parameter",
+          "text": " If <code>buffer</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, <code>buffer</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkBuffer\">VkBuffer</a> handle"
+        }
+      ]
+    },
+    "vkCmdTraceRaysIndirectKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-None-02690",
+          "text": " If a <code>VkImageView</code> is sampled with <code>VK_FILTER_LINEAR</code> as a result of this command, then the image view&#8217;s <a href=\"#resources-image-view-format-features\">format features</a> <strong class=\"purple\">must</strong> contain <code>VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-None-02691",
+          "text": " If a <code>VkImageView</code> is accessed using atomic operations as a result of this command, then the image view&#8217;s <a href=\"#resources-image-view-format-features\">format features</a> <strong class=\"purple\">must</strong> contain <code>VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-None-02697",
+          "text": " For each set <em>n</em> that is statically used by the <code>VkPipeline</code> bound to the pipeline bind point used by this command, a descriptor set <strong class=\"purple\">must</strong> have been bound to <em>n</em> at the same pipeline bind point, with a <code>VkPipelineLayout</code> that is compatible for set <em>n</em>, with the <code>VkPipelineLayout</code> used to create the current <code>VkPipeline</code>, as described in <a href=\"#descriptorsets-compatibility\">Pipeline Layout Compatibility</a>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-None-02698",
+          "text": " For each push constant that is statically used by the <code>VkPipeline</code> bound to the pipeline bind point used by this command, a push constant value <strong class=\"purple\">must</strong> have been set for the same pipeline bind point, with a <code>VkPipelineLayout</code> that is compatible for push constants, with the <code>VkPipelineLayout</code> used to create the current <code>VkPipeline</code>, as described in <a href=\"#descriptorsets-compatibility\">Pipeline Layout Compatibility</a>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-None-02699",
+          "text": " Descriptors in each bound descriptor set, specified via <code>vkCmdBindDescriptorSets</code>, <strong class=\"purple\">must</strong> be valid if they are statically used by the <code>VkPipeline</code> bound to the pipeline bind point used by this command"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-None-02700",
+          "text": " A valid pipeline <strong class=\"purple\">must</strong> be bound to the pipeline bind point used by this command"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-commandBuffer-02701",
+          "text": " If the <code>VkPipeline</code> object bound to the pipeline bind point used by this command requires any dynamic state, that state <strong class=\"purple\">must</strong> have been set for <code>commandBuffer</code>, and done so after any previously bound pipeline with the corresponding state not specified as dynamic"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-None-02859",
+          "text": " There <strong class=\"purple\">must</strong> not have been any calls to dynamic state setting commands for any state not specified as dynamic in the <code>VkPipeline</code> object bound to the pipeline bind point used by this command, since that pipeline was bound"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-None-02702",
+          "text": " If the <code>VkPipeline</code> object bound to the pipeline bind point used by this command accesses a <code>VkSampler</code> object that uses unnormalized coordinates, that sampler <strong class=\"purple\">must</strong> not be used to sample from any <code>VkImage</code> with a <code>VkImageView</code> of the type <code>VK_IMAGE_VIEW_TYPE_3D</code>, <code>VK_IMAGE_VIEW_TYPE_CUBE</code>, <code>VK_IMAGE_VIEW_TYPE_1D_ARRAY</code>, <code>VK_IMAGE_VIEW_TYPE_2D_ARRAY</code> or <code>VK_IMAGE_VIEW_TYPE_CUBE_ARRAY</code>, in any shader stage"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-None-02703",
+          "text": " If the <code>VkPipeline</code> object bound to the pipeline bind point used by this command accesses a <code>VkSampler</code> object that uses unnormalized coordinates, that sampler <strong class=\"purple\">must</strong> not be used with any of the SPIR-V <code>OpImageSample*</code> or <code>OpImageSparseSample*</code> instructions with <code>ImplicitLod</code>, <code>Dref</code> or <code>Proj</code> in their name, in any shader stage"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-None-02704",
+          "text": " If the <code>VkPipeline</code> object bound to the pipeline bind point used by this command accesses a <code>VkSampler</code> object that uses unnormalized coordinates, that sampler <strong class=\"purple\">must</strong> not be used with any of the SPIR-V <code>OpImageSample*</code> or <code>OpImageSparseSample*</code> instructions that includes a LOD bias or any offset values, in any shader stage"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-None-02705",
+          "text": " If the <a href=\"#features-robustBufferAccess\">robust buffer access</a> feature is not enabled, and if the <code>VkPipeline</code> object bound to the pipeline bind point used by this command accesses a uniform buffer, it <strong class=\"purple\">must</strong> not access values outside of the range of the buffer as specified in the descriptor set bound to the same pipeline bind point"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-None-02706",
+          "text": " If the <a href=\"#features-robustBufferAccess\">robust buffer access</a> feature is not enabled, and if the <code>VkPipeline</code> object bound to the pipeline bind point used by this command accesses a storage buffer, it <strong class=\"purple\">must</strong> not access values outside of the range of the buffer as specified in the descriptor set bound to the same pipeline bind point"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-raygenShaderBindingOffset-02455",
+          "text": " <code>raygenShaderBindingOffset</code> <strong class=\"purple\">must</strong> be less than the size of <code>raygenShaderBindingTableBuffer</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-raygenShaderBindingOffset-02456",
+          "text": " <code>raygenShaderBindingOffset</code> <strong class=\"purple\">must</strong> be a multiple of <code>VkPhysicalDeviceRayTracingPropertiesKHR</code>::<code>shaderGroupBaseAlignment</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-missShaderBindingOffset-02457",
+          "text": " <code>missShaderBindingOffset</code> <strong class=\"purple\">must</strong> be less than the size of <code>missShaderBindingTableBuffer</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-missShaderBindingOffset-02458",
+          "text": " <code>missShaderBindingOffset</code> <strong class=\"purple\">must</strong> be a multiple of <code>VkPhysicalDeviceRayTracingPropertiesKHR</code>::<code>shaderGroupBaseAlignment</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-hitShaderBindingOffset-02459",
+          "text": " <code>hitShaderBindingOffset</code> <strong class=\"purple\">must</strong> be less than the size of <code>hitShaderBindingTableBuffer</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-hitShaderBindingOffset-02460",
+          "text": " <code>hitShaderBindingOffset</code> <strong class=\"purple\">must</strong> be a multiple of <code>VkPhysicalDeviceRayTracingPropertiesKHR</code>::<code>shaderGroupBaseAlignment</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-callableShaderBindingOffset-02461",
+          "text": " <code>callableShaderBindingOffset</code> <strong class=\"purple\">must</strong> be less than the size of <code>callableShaderBindingTableBuffer</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-callableShaderBindingOffset-02462",
+          "text": " <code>callableShaderBindingOffset</code> <strong class=\"purple\">must</strong> be a multiple of <code>VkPhysicalDeviceRayTracingPropertiesKHR</code>::<code>shaderGroupBaseAlignment</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-missShaderBindingStride-02463",
+          "text": " <code>missShaderBindingStride</code> <strong class=\"purple\">must</strong> be a multiple of <code>VkPhysicalDeviceRayTracingPropertiesKHR</code>::<code>shaderGroupHandleSize</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-hitShaderBindingStride-02464",
+          "text": " <code>hitShaderBindingStride</code> <strong class=\"purple\">must</strong> be a multiple of <code>VkPhysicalDeviceRayTracingPropertiesKHR</code>::<code>shaderGroupHandleSize</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-callableShaderBindingStride-02465",
+          "text": " <code>callableShaderBindingStride</code> <strong class=\"purple\">must</strong> be a multiple of <code>VkPhysicalDeviceRayTracingPropertiesKHR</code>::<code>shaderGroupHandleSize</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-missShaderBindingStride-02466",
+          "text": " <code>missShaderBindingStride</code> <strong class=\"purple\">must</strong> be less than or equal to <code>VkPhysicalDeviceRayTracingPropertiesKHR</code>::<code>maxShaderGroupStride</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-hitShaderBindingStride-02467",
+          "text": " <code>hitShaderBindingStride</code> <strong class=\"purple\">must</strong> be less than or equal to <code>VkPhysicalDeviceRayTracingPropertiesKHR</code>::<code>maxShaderGroupStride</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-callableShaderBindingStride-02468",
+          "text": " <code>callableShaderBindingStride</code> <strong class=\"purple\">must</strong> be less than or equal to <code>VkPhysicalDeviceRayTracingPropertiesKHR</code>::<code>maxShaderGroupStride</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-None-03429",
+          "text": " Any shader group handle referenced by this call <strong class=\"purple\">must</strong> have been queried from the currently bound ray tracing shader pipeline"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-maxRecursionDepth-03430",
+          "text": " This command <strong class=\"purple\">must</strong> not cause a shader call instruction to be executed from a shader invocation with a <a href=\"#ray-tracing-recursion-depth\">recursion depth</a> greater than the value of <code>maxRecursionDepth</code> used to create the bound ray tracing pipeline."
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-buffer-02708",
+          "text": " If <code>buffer</code> is non-sparse then it <strong class=\"purple\">must</strong> be bound completely and contiguously to a single <code>VkDeviceMemory</code> object"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-buffer-02709",
+          "text": " <code>buffer</code> <strong class=\"purple\">must</strong> have been created with the <code>VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT</code> bit set"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-offset-02710",
+          "text": " <code>offset</code> <strong class=\"purple\">must</strong> be a multiple of <code>4</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-offset-03517",
+          "text": " <span class=\"eq\">(<code>offset</code> &#43; <code>sizeof</code>(<code>VkTraceRaysIndirectCommandKHR</code>))</span> <strong class=\"purple\">must</strong> be less than or equal to the size of <code>buffer</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-rayTracingIndirectTraceRays-03518",
+          "text": " the <a href=\"#features-raytracing-indirecttraceray\"><code>VkPhysicalDeviceRayTracingFeaturesKHR</code>::<code>rayTracingIndirectTraceRays</code></a> feature <strong class=\"purple\">must</strong> be enabled"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-commandBuffer-parameter",
+          "text": " <code>commandBuffer</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkCommandBuffer\">VkCommandBuffer</a> handle"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-pRaygenShaderBindingTable-parameter",
+          "text": " <code>pRaygenShaderBindingTable</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkStridedBufferRegionKHR\">VkStridedBufferRegionKHR</a> structure"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-pMissShaderBindingTable-parameter",
+          "text": " <code>pMissShaderBindingTable</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkStridedBufferRegionKHR\">VkStridedBufferRegionKHR</a> structure"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-pHitShaderBindingTable-parameter",
+          "text": " <code>pHitShaderBindingTable</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkStridedBufferRegionKHR\">VkStridedBufferRegionKHR</a> structure"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-pCallableShaderBindingTable-parameter",
+          "text": " <code>pCallableShaderBindingTable</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkStridedBufferRegionKHR\">VkStridedBufferRegionKHR</a> structure"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-buffer-parameter",
+          "text": " <code>buffer</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkBuffer\">VkBuffer</a> handle"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-commandBuffer-recording",
+          "text": " <code>commandBuffer</code> <strong class=\"purple\">must</strong> be in the <a href=\"#commandbuffers-lifecycle\">recording state</a>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-commandBuffer-cmdpool",
+          "text": " The <code>VkCommandPool</code> that <code>commandBuffer</code> was allocated from <strong class=\"purple\">must</strong> support compute operations"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-renderpass",
+          "text": " This command <strong class=\"purple\">must</strong> only be called outside of a render pass instance"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-commonparent",
+          "text": " Both of <code>buffer</code>, and <code>commandBuffer</code> <strong class=\"purple\">must</strong> have been created, allocated, or retrieved from the same <a href=\"#VkDevice\">VkDevice</a>"
+        }
+      ],
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)+(VK_IMG_filter_cubic,VK_EXT_filter_cubic)": [
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-None-02692",
+          "text": " If a <code>VkImageView</code> is sampled with <code>VK_FILTER_CUBIC_EXT</code> as a result of this command, then the image view&#8217;s <a href=\"#resources-image-view-format-features\">format features</a> <strong class=\"purple\">must</strong> contain <code>VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT</code>"
+        }
+      ],
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)+(VK_IMG_filter_cubic,VK_EXT_filter_cubic)+!(VK_EXT_filter_cubic)": [
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-None-02693",
+          "text": " Any <a href=\"#VkImageView\">VkImageView</a> being sampled with <code>VK_FILTER_CUBIC_EXT</code> as a result of this command <strong class=\"purple\">must</strong> not have a <a href=\"#VkImageViewType\">VkImageViewType</a> of <code>VK_IMAGE_VIEW_TYPE_3D</code>, <code>VK_IMAGE_VIEW_TYPE_CUBE</code>, or <code>VK_IMAGE_VIEW_TYPE_CUBE_ARRAY</code>"
+        }
+      ],
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)+(VK_IMG_filter_cubic,VK_EXT_filter_cubic)+(VK_EXT_filter_cubic)": [
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-filterCubic-02694",
+          "text": " Any <a href=\"#VkImageView\">VkImageView</a> being sampled with <code>VK_FILTER_CUBIC_EXT</code> as a result of this command <strong class=\"purple\">must</strong> have a <a href=\"#VkImageViewType\">VkImageViewType</a> and format that supports cubic filtering, as specified by <code>VkFilterCubicImageViewImageFormatPropertiesEXT</code>::<code>filterCubic</code> returned by <code>vkGetPhysicalDeviceImageFormatProperties2</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-filterCubicMinmax-02695",
+          "text": " Any <a href=\"#VkImageView\">VkImageView</a> being sampled with <code>VK_FILTER_CUBIC_EXT</code> with a reduction mode of either <code>VK_SAMPLER_REDUCTION_MODE_MIN</code> or <code>VK_SAMPLER_REDUCTION_MODE_MAX</code> as a result of this command <strong class=\"purple\">must</strong> have a <a href=\"#VkImageViewType\">VkImageViewType</a> and format that supports cubic filtering together with minmax filtering, as specified by <code>VkFilterCubicImageViewImageFormatPropertiesEXT</code>::<code>filterCubicMinmax</code> returned by <code>vkGetPhysicalDeviceImageFormatProperties2</code>"
+        }
+      ],
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)+(VK_NV_corner_sampled_image)": [
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-flags-02696",
+          "text": " Any <a href=\"#VkImage\">VkImage</a> created with a <a href=\"#VkImageCreateInfo\">VkImageCreateInfo</a>::<code>flags</code> containing <code>VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV</code> sampled as a result of this command <strong class=\"purple\">must</strong> only be sampled using a <a href=\"#VkSamplerAddressMode\">VkSamplerAddressMode</a> of <code>VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE</code>"
+        }
+      ],
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)+(VK_VERSION_1_1)": [
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-commandBuffer-02707",
+          "text": " If <code>commandBuffer</code> is an unprotected command buffer, any resource accessed by the <code>VkPipeline</code> object bound to the pipeline bind point used by this command <strong class=\"purple\">must</strong> not be a protected resource"
+        },
+        {
+          "vuid": "VUID-vkCmdTraceRaysIndirectKHR-commandBuffer-02711",
+          "text": " <code>commandBuffer</code> <strong class=\"purple\">must</strong> not be a protected command buffer"
+        }
+      ]
+    },
+    "VkTraceRaysIndirectCommandKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-VkTraceRaysIndirectCommandKHR-width-03519",
+          "text": " <code>width</code> <strong class=\"purple\">must</strong> be less than or equal to <code>VkPhysicalDeviceLimits</code>::<code>maxComputeWorkGroupCount</code>[0]"
+        },
+        {
+          "vuid": "VUID-VkTraceRaysIndirectCommandKHR-height-03520",
+          "text": " <code>height</code> <strong class=\"purple\">must</strong> be less than or equal to <code>VkPhysicalDeviceLimits</code>::<code>maxComputeWorkGroupCount</code>[1]"
+        },
+        {
+          "vuid": "VUID-VkTraceRaysIndirectCommandKHR-depth-03521",
+          "text": " <code>depth</code> <strong class=\"purple\">must</strong> be less than or equal to <code>VkPhysicalDeviceLimits</code>::<code>maxComputeWorkGroupCount</code>[2]"
+        }
+      ]
+    },
     "vkCmdBuildAccelerationStructureNV": {
-      "(VK_NV_ray_tracing)": [
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_NV_ray_tracing)": [
         {
           "vuid": "VUID-vkCmdBuildAccelerationStructureNV-geometryCount-02241",
           "text": " <code>geometryCount</code> <strong class=\"purple\">must</strong> be less than or equal to <a href=\"#VkPhysicalDeviceRayTracingPropertiesNV\">VkPhysicalDeviceRayTracingPropertiesNV</a>::<code>maxGeometryCount</code>"
         },
         {
           "vuid": "VUID-vkCmdBuildAccelerationStructureNV-dst-02488",
-          "text": " <code>dst</code> <strong class=\"purple\">must</strong> have been created with compatible <a href=\"#VkAccelerationStructureInfoNV\">VkAccelerationStructureInfoNV</a> where <a href=\"#VkAccelerationStructureInfoNV\">VkAccelerationStructureInfoNV</a>::<code>type</code> and <a href=\"#VkAccelerationStructureInfoNV\">VkAccelerationStructureInfoNV</a>::<code>flags</code> are identical, <a href=\"#VkAccelerationStructureInfoNV\">VkAccelerationStructureInfoNV</a>::<code>instanceCount</code> and <a href=\"#VkAccelerationStructureInfoNV\">VkAccelerationStructureInfoNV</a>::<code>geometryCount</code> for <code>dst</code> are greater than or equal to the build size and each geometry in <a href=\"#VkAccelerationStructureInfoNV\">VkAccelerationStructureInfoNV</a>::<code>pGeometries</code> for <code>dst</code> has greater than or equal to the number of vertices, indices, and AABBs."
+          "text": " <code>dst</code> <strong class=\"purple\">must</strong> have been created with compatible <a href=\"#VkAccelerationStructureInfoNV\">VkAccelerationStructureInfoNV</a> where <a href=\"#VkAccelerationStructureInfoNV\">VkAccelerationStructureInfoNV</a>::<code>type</code> and <a href=\"#VkAccelerationStructureInfoNV\">VkAccelerationStructureInfoNV</a>::<code>flags</code> are identical, <a href=\"#VkAccelerationStructureInfoNV\">VkAccelerationStructureInfoNV</a>::<code>instanceCount</code> and <a href=\"#VkAccelerationStructureInfoNV\">VkAccelerationStructureInfoNV</a>::<code>geometryCount</code> for <code>dst</code> are greater than or equal to the build size and each geometry in <a href=\"#VkAccelerationStructureInfoNV\">VkAccelerationStructureInfoNV</a>::<code>pGeometries</code> for <code>dst</code> has greater than or equal to the number of vertices, indices, and AABBs"
         },
         {
           "vuid": "VUID-vkCmdBuildAccelerationStructureNV-update-02489",
@@ -24484,11 +25926,31 @@
         },
         {
           "vuid": "VUID-vkCmdBuildAccelerationStructureNV-update-02491",
-          "text": " If <code>update</code> is <code>VK_FALSE</code>, The <code>size</code> member of the <a href=\"#VkMemoryRequirements\">VkMemoryRequirements</a> structure returned from a call to <a href=\"#vkGetAccelerationStructureMemoryRequirementsNV\">vkGetAccelerationStructureMemoryRequirementsNV</a> with <a href=\"#VkAccelerationStructureMemoryRequirementsInfoNV\">VkAccelerationStructureMemoryRequirementsInfoNV</a>::<code>accelerationStructure</code> set to <code>dst</code> and <a href=\"#VkAccelerationStructureMemoryRequirementsInfoNV\">VkAccelerationStructureMemoryRequirementsInfoNV</a>::<code>type</code> set to <code>VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV</code> <strong class=\"purple\">must</strong> be less than or equal to the size of <code>scratch</code> minus <code>scratchOffset</code>"
+          "text": " If <code>update</code> is <code>VK_FALSE</code>, the <code>size</code> member of the <a href=\"#VkMemoryRequirements\">VkMemoryRequirements</a> structure returned from a call to <a href=\"#vkGetAccelerationStructureMemoryRequirementsNV\">vkGetAccelerationStructureMemoryRequirementsNV</a> with <a href=\"#VkAccelerationStructureMemoryRequirementsInfoNV\">VkAccelerationStructureMemoryRequirementsInfoNV</a>::<code>accelerationStructure</code> set to <code>dst</code> and <a href=\"#VkAccelerationStructureMemoryRequirementsInfoNV\">VkAccelerationStructureMemoryRequirementsInfoNV</a>::<code>type</code> set to <code>VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV</code> <strong class=\"purple\">must</strong> be less than or equal to the size of <code>scratch</code> minus <code>scratchOffset</code>"
         },
         {
           "vuid": "VUID-vkCmdBuildAccelerationStructureNV-update-02492",
-          "text": " If <code>update</code> is <code>VK_TRUE</code>, The <code>size</code> member of the <a href=\"#VkMemoryRequirements\">VkMemoryRequirements</a> structure returned from a call to <a href=\"#vkGetAccelerationStructureMemoryRequirementsNV\">vkGetAccelerationStructureMemoryRequirementsNV</a> with <a href=\"#VkAccelerationStructureMemoryRequirementsInfoNV\">VkAccelerationStructureMemoryRequirementsInfoNV</a>::<code>accelerationStructure</code> set to <code>dst</code> and <a href=\"#VkAccelerationStructureMemoryRequirementsInfoNV\">VkAccelerationStructureMemoryRequirementsInfoNV</a>::<code>type</code> set to <code>VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV</code> <strong class=\"purple\">must</strong> be less than or equal to the size of <code>scratch</code> minus <code>scratchOffset</code>"
+          "text": " If <code>update</code> is <code>VK_TRUE</code>, the <code>size</code> member of the <a href=\"#VkMemoryRequirements\">VkMemoryRequirements</a> structure returned from a call to <a href=\"#vkGetAccelerationStructureMemoryRequirementsNV\">vkGetAccelerationStructureMemoryRequirementsNV</a> with <a href=\"#VkAccelerationStructureMemoryRequirementsInfoNV\">VkAccelerationStructureMemoryRequirementsInfoNV</a>::<code>accelerationStructure</code> set to <code>dst</code> and <a href=\"#VkAccelerationStructureMemoryRequirementsInfoNV\">VkAccelerationStructureMemoryRequirementsInfoNV</a>::<code>type</code> set to <code>VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV</code> <strong class=\"purple\">must</strong> be less than or equal to the size of <code>scratch</code> minus <code>scratchOffset</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdBuildAccelerationStructureNV-scratch-03522",
+          "text": " <code>scratch</code> <strong class=\"purple\">must</strong> have been created with <code>VK_BUFFER_USAGE_RAY_TRACING_BIT_NV</code> usage flag"
+        },
+        {
+          "vuid": "VUID-vkCmdBuildAccelerationStructureNV-instanceData-03523",
+          "text": " If <code>instanceData</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, <code>instanceData</code> <strong class=\"purple\">must</strong> have been created with <code>VK_BUFFER_USAGE_RAY_TRACING_BIT_NV</code> usage flag"
+        },
+        {
+          "vuid": "VUID-vkCmdBuildAccelerationStructureNV-update-03524",
+          "text": " If <code>update</code> is <code>VK_TRUE</code>, then objects that were previously active <strong class=\"purple\">must</strong> not be made inactive as per <a href=\"#acceleration-structure-inactive-prims\">Inactive Primitives and Instances</a>"
+        },
+        {
+          "vuid": "VUID-vkCmdBuildAccelerationStructureNV-update-03525",
+          "text": " If <code>update</code> is <code>VK_TRUE</code>, then objects that were previously inactive <strong class=\"purple\">must</strong> not be made active as per <a href=\"#acceleration-structure-inactive-prims\">Inactive Primitives and Instances</a>"
+        },
+        {
+          "vuid": "VUID-vkCmdBuildAccelerationStructureNV-update-03526",
+          "text": " If <code>update</code> is <code>VK_TRUE</code>, the <code>src</code> and <code>dst</code> objects <strong class=\"purple\">must</strong> either be the same object or not have any <a href=\"#resources-memory-aliasing\">memory aliasing</a>"
         },
         {
           "vuid": "VUID-vkCmdBuildAccelerationStructureNV-commandBuffer-parameter",
@@ -24504,11 +25966,11 @@
         },
         {
           "vuid": "VUID-vkCmdBuildAccelerationStructureNV-dst-parameter",
-          "text": " <code>dst</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkAccelerationStructureNV\">VkAccelerationStructureNV</a> handle"
+          "text": " <code>dst</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkAccelerationStructureKHR\">VkAccelerationStructureKHR</a> handle"
         },
         {
           "vuid": "VUID-vkCmdBuildAccelerationStructureNV-src-parameter",
-          "text": " If <code>src</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, <code>src</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkAccelerationStructureNV\">VkAccelerationStructureNV</a> handle"
+          "text": " If <code>src</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, <code>src</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkAccelerationStructureKHR\">VkAccelerationStructureKHR</a> handle"
         },
         {
           "vuid": "VUID-vkCmdBuildAccelerationStructureNV-scratch-parameter",
@@ -24532,71 +25994,449 @@
         }
       ]
     },
-    "vkCmdWriteAccelerationStructuresPropertiesNV": {
-      "(VK_NV_ray_tracing)": [
+    "vkCmdBuildAccelerationStructureKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)": [
         {
-          "vuid": "VUID-vkCmdWriteAccelerationStructuresPropertiesNV-queryType-02242",
-          "text": " <code>queryType</code> <strong class=\"purple\">must</strong> be <code>VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV</code>"
+          "vuid": "VUID-vkCmdBuildAccelerationStructureKHR-pOffsetInfos-03402",
+          "text": " <code>pOffsetInfos</code>[i] <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>pInfos</code>[i].<code>geometryCount</code> <code>VkAccelerationStructureBuildOffsetInfoKHR</code> structures"
         },
         {
-          "vuid": "VUID-vkCmdWriteAccelerationStructuresPropertiesNV-queryPool-02493",
-          "text": " <code>queryPool</code> <strong class=\"purple\">must</strong> have been created with a <code>queryType</code> matching <code>queryType</code>"
+          "vuid": "VUID-vkCmdBuildAccelerationStructureKHR-pInfos-03403",
+          "text": " Each <code>pInfos</code>[i].<code>srcAccelerationStructure</code> <strong class=\"purple\">must</strong> not refer to the same acceleration structure as any <code>pInfos</code>[i].<code>dstAccelerationStructure</code> that is provided to the same build command unless it is identical for an update"
         },
         {
-          "vuid": "VUID-vkCmdWriteAccelerationStructuresPropertiesNV-queryPool-02494",
-          "text": " The queries identified by <code>queryPool</code> and <code>firstQuery</code> <strong class=\"purple\">must</strong> be <em>unavailable</em>"
+          "vuid": "VUID-vkCmdBuildAccelerationStructureKHR-pInfos-03404",
+          "text": " For each <code>pInfos</code>[i], <code>dstAccelerationStructure</code> <strong class=\"purple\">must</strong> have been created with compatible <a href=\"#VkAccelerationStructureCreateInfoKHR\">VkAccelerationStructureCreateInfoKHR</a> where <a href=\"#VkAccelerationStructureCreateInfoKHR\">VkAccelerationStructureCreateInfoKHR</a>::<code>type</code> and <a href=\"#VkAccelerationStructureCreateInfoKHR\">VkAccelerationStructureCreateInfoKHR</a>::<code>flags</code> are identical to <a href=\"#VkAccelerationStructureBuildGeometryInfoKHR\">VkAccelerationStructureBuildGeometryInfoKHR</a>::<code>type</code> and <a href=\"#VkAccelerationStructureBuildGeometryInfoKHR\">VkAccelerationStructureBuildGeometryInfoKHR</a>::<code>flags</code> respectively, <a href=\"#VkAccelerationStructureBuildGeometryInfoKHR\">VkAccelerationStructureBuildGeometryInfoKHR</a>::<code>geometryCount</code> for <code>dstAccelerationStructure</code> are greater than or equal to the build size, and each geometry in <a href=\"#VkAccelerationStructureBuildGeometryInfoKHR\">VkAccelerationStructureBuildGeometryInfoKHR</a>::<code>ppGeometries</code> for <code>dstAccelerationStructure</code> has greater than or equal to the number of vertices, indices, and AABBs, <a href=\"#VkAccelerationStructureGeometryTrianglesDataKHR\">VkAccelerationStructureGeometryTrianglesDataKHR</a>::<code>transformData</code> is both 0 or both non-zero, and all other parameters are the same"
         },
         {
-          "vuid": "VUID-vkCmdWriteAccelerationStructuresPropertiesNV-accelerationStructures-02495",
-          "text": " All acceleration structures in <code>accelerationStructures</code> <strong class=\"purple\">must</strong> have been built with <code>VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_NV</code> if <code>queryType</code> is <code>VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV</code>"
+          "vuid": "VUID-vkCmdBuildAccelerationStructureKHR-pInfos-03405",
+          "text": " For each <code>pInfos</code>[i], if <code>update</code> is <code>VK_TRUE</code>, then objects that were previously active for that acceleration structure <strong class=\"purple\">must</strong> not be made inactive as per <a href=\"#acceleration-structure-inactive-prims\">Inactive Primitives and Instances</a>"
         },
         {
-          "vuid": "VUID-vkCmdWriteAccelerationStructuresPropertiesNV-commandBuffer-parameter",
+          "vuid": "VUID-vkCmdBuildAccelerationStructureKHR-pInfos-03406",
+          "text": " For each <code>pInfos</code>[i], if <code>update</code> is <code>VK_TRUE</code>, then objects that were previously inactive for that acceleration structure <strong class=\"purple\">must</strong> not be made active as per <a href=\"#acceleration-structure-inactive-prims\">Inactive Primitives and Instances</a>"
+        },
+        {
+          "vuid": "VUID-vkCmdBuildAccelerationStructureKHR-None-03407",
+          "text": " Any acceleration structure instance in any top level build in this command <strong class=\"purple\">must</strong> not reference any bottom level acceleration structure built by this command"
+        },
+        {
+          "vuid": "VUID-vkCmdBuildAccelerationStructureKHR-pInfos-03408",
+          "text": " There <strong class=\"purple\">must</strong> not be any <a href=\"#resources-memory-aliasing\">memory aliasing</a> between the scratch memories that are provided in all the <code>pInfos</code>[i].<code>scratchData</code> memories for the acceleration structure builds"
+        },
+        {
+          "vuid": "VUID-vkCmdBuildAccelerationStructureKHR-None-03409",
+          "text": " There <strong class=\"purple\">must</strong> not be any <a href=\"#resources-memory-aliasing\">memory aliasing</a> between memory bound to any top level, bottom level, or instance acceleration structure accessed by this command"
+        },
+        {
+          "vuid": "VUID-vkCmdBuildAccelerationStructureKHR-commandBuffer-parameter",
           "text": " <code>commandBuffer</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkCommandBuffer\">VkCommandBuffer</a> handle"
         },
         {
-          "vuid": "VUID-vkCmdWriteAccelerationStructuresPropertiesNV-pAccelerationStructures-parameter",
-          "text": " <code>pAccelerationStructures</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>accelerationStructureCount</code> valid <a href=\"#VkAccelerationStructureNV\">VkAccelerationStructureNV</a> handles"
+          "vuid": "VUID-vkCmdBuildAccelerationStructureKHR-pInfos-parameter",
+          "text": " <code>pInfos</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>infoCount</code> valid <a href=\"#VkAccelerationStructureBuildGeometryInfoKHR\">VkAccelerationStructureBuildGeometryInfoKHR</a> structures"
         },
         {
-          "vuid": "VUID-vkCmdWriteAccelerationStructuresPropertiesNV-queryType-parameter",
-          "text": " <code>queryType</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkQueryType\">VkQueryType</a> value"
+          "vuid": "VUID-vkCmdBuildAccelerationStructureKHR-ppOffsetInfos-parameter",
+          "text": " <code>ppOffsetInfos</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>infoCount</code> <a href=\"#VkAccelerationStructureBuildOffsetInfoKHR\">VkAccelerationStructureBuildOffsetInfoKHR</a> structures"
         },
         {
-          "vuid": "VUID-vkCmdWriteAccelerationStructuresPropertiesNV-queryPool-parameter",
-          "text": " <code>queryPool</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkQueryPool\">VkQueryPool</a> handle"
-        },
-        {
-          "vuid": "VUID-vkCmdWriteAccelerationStructuresPropertiesNV-commandBuffer-recording",
+          "vuid": "VUID-vkCmdBuildAccelerationStructureKHR-commandBuffer-recording",
           "text": " <code>commandBuffer</code> <strong class=\"purple\">must</strong> be in the <a href=\"#commandbuffers-lifecycle\">recording state</a>"
         },
         {
-          "vuid": "VUID-vkCmdWriteAccelerationStructuresPropertiesNV-commandBuffer-cmdpool",
+          "vuid": "VUID-vkCmdBuildAccelerationStructureKHR-commandBuffer-cmdpool",
           "text": " The <code>VkCommandPool</code> that <code>commandBuffer</code> was allocated from <strong class=\"purple\">must</strong> support compute operations"
         },
         {
-          "vuid": "VUID-vkCmdWriteAccelerationStructuresPropertiesNV-renderpass",
+          "vuid": "VUID-vkCmdBuildAccelerationStructureKHR-renderpass",
           "text": " This command <strong class=\"purple\">must</strong> only be called outside of a render pass instance"
         },
         {
-          "vuid": "VUID-vkCmdWriteAccelerationStructuresPropertiesNV-accelerationStructureCount-arraylength",
+          "vuid": "VUID-vkCmdBuildAccelerationStructureKHR-infoCount-arraylength",
+          "text": " <code>infoCount</code> <strong class=\"purple\">must</strong> be greater than <code>0</code>"
+        }
+      ],
+      "core": [
+        {
+          "vuid": "VUID-vkCmdBuildAccelerationStructureKHR-update-03527",
+          "text": " If <code>update</code> is <code>VK_FALSE</code>, all addresses between <code>pInfos</code>[i].<code>scratchData</code> and <code>pInfos</code>[i].<code>scratchData</code> + N - 1 <strong class=\"purple\">must</strong> be in the buffer device address range of the same buffer, where N is given by the <code>size</code> member of the <a href=\"#VkMemoryRequirements\">VkMemoryRequirements</a> structure returned from a call to <a href=\"#vkGetAccelerationStructureMemoryRequirementsKHR\">vkGetAccelerationStructureMemoryRequirementsKHR</a> with <a href=\"#VkAccelerationStructureMemoryRequirementsInfoKHR\">VkAccelerationStructureMemoryRequirementsInfoKHR</a>::<code>accelerationStructure</code> set to <code>pInfos</code>[i].<code>dstAccelerationStructure</code> and <a href=\"#VkAccelerationStructureMemoryRequirementsInfoKHR\">VkAccelerationStructureMemoryRequirementsInfoKHR</a>::<code>type</code> set to <code>VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdBuildAccelerationStructureKHR-update-03528",
+          "text": " If <code>update</code> is <code>VK_TRUE</code>, all addresses between <code>pInfos</code>[i].<code>scratchData</code> and <code>pInfos</code>[i].<code>scratchData</code> + N - 1 <strong class=\"purple\">must</strong> be in the buffer device address range of the same buffer, where N is given by the <code>size</code> member of the <a href=\"#VkMemoryRequirements\">VkMemoryRequirements</a> structure returned from a call to <a href=\"#vkGetAccelerationStructureMemoryRequirementsKHR\">vkGetAccelerationStructureMemoryRequirementsKHR</a> with <a href=\"#VkAccelerationStructureMemoryRequirementsInfoKHR\">VkAccelerationStructureMemoryRequirementsInfoKHR</a>::<code>accelerationStructure</code> set to <code>pInfos</code>[i].<code>dstAccelerationStructure</code> and <a href=\"#VkAccelerationStructureMemoryRequirementsInfoKHR\">VkAccelerationStructureMemoryRequirementsInfoKHR</a>::<code>type</code> set to <code>VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_KHR</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdBuildAccelerationStructureKHR-pInfos-03529",
+          "text": " The buffer from which the buffer device address <code>pInfos</code>[i].<code>scratchData</code> is queried <strong class=\"purple\">must</strong> have been created with <code>VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR</code> usage flag"
+        },
+        {
+          "vuid": "VUID-vkCmdBuildAccelerationStructureKHR-None-03530",
+          "text": " All <a href=\"#VkDeviceOrHostAddressKHR\">VkDeviceOrHostAddressKHR</a> or <a href=\"#VkDeviceOrHostAddressConstKHR\">VkDeviceOrHostAddressConstKHR</a> referenced by this command <strong class=\"purple\">must</strong> contain valid device addresses"
+        },
+        {
+          "vuid": "VUID-vkCmdBuildAccelerationStructureKHR-None-03531",
+          "text": " All <code>VkAccelerationStructureKHR</code> objects referenced by this command <strong class=\"purple\">must</strong> be bound to device memory"
+        }
+      ],
+      "(VK_KHR_deferred_host_operations)": [
+        {
+          "vuid": "VUID-vkCmdBuildAccelerationStructureKHR-pNext-03532",
+          "text": " The <a href=\"#VkDeferredOperationInfoKHR\">VkDeferredOperationInfoKHR</a> structure <strong class=\"purple\">must</strong> not be included in the <code>pNext</code> chain of any of the provided <a href=\"#VkAccelerationStructureBuildGeometryInfoKHR\">VkAccelerationStructureBuildGeometryInfoKHR</a> structures"
+        }
+      ]
+    },
+    "vkCmdBuildAccelerationStructureIndirectKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-vkCmdBuildAccelerationStructureIndirectKHR-None-03533",
+          "text": " All <a href=\"#VkDeviceOrHostAddressKHR\">VkDeviceOrHostAddressKHR</a> or <a href=\"#VkDeviceOrHostAddressConstKHR\">VkDeviceOrHostAddressConstKHR</a> referenced by this command <strong class=\"purple\">must</strong> contain valid device addresses"
+        },
+        {
+          "vuid": "VUID-vkCmdBuildAccelerationStructureIndirectKHR-None-03534",
+          "text": " All <code>VkAccelerationStructureKHR</code> objects referenced by this command <strong class=\"purple\">must</strong> be bound to device memory"
+        },
+        {
+          "vuid": "VUID-vkCmdBuildAccelerationStructureIndirectKHR-rayTracingIndirectAccelerationStructureBuild-03535",
+          "text": " The <a href=\"#features-raytracing-indirectasbuild\"><code>VkPhysicalDeviceRayTracingFeaturesKHR</code>::<code>rayTracingIndirectAccelerationStructureBuild</code></a> feature <strong class=\"purple\">must</strong> be enabled"
+        },
+        {
+          "vuid": "VUID-vkCmdBuildAccelerationStructureIndirectKHR-commandBuffer-parameter",
+          "text": " <code>commandBuffer</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkCommandBuffer\">VkCommandBuffer</a> handle"
+        },
+        {
+          "vuid": "VUID-vkCmdBuildAccelerationStructureIndirectKHR-pInfo-parameter",
+          "text": " <code>pInfo</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkAccelerationStructureBuildGeometryInfoKHR\">VkAccelerationStructureBuildGeometryInfoKHR</a> structure"
+        },
+        {
+          "vuid": "VUID-vkCmdBuildAccelerationStructureIndirectKHR-indirectBuffer-parameter",
+          "text": " <code>indirectBuffer</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkBuffer\">VkBuffer</a> handle"
+        },
+        {
+          "vuid": "VUID-vkCmdBuildAccelerationStructureIndirectKHR-commandBuffer-recording",
+          "text": " <code>commandBuffer</code> <strong class=\"purple\">must</strong> be in the <a href=\"#commandbuffers-lifecycle\">recording state</a>"
+        },
+        {
+          "vuid": "VUID-vkCmdBuildAccelerationStructureIndirectKHR-commandBuffer-cmdpool",
+          "text": " The <code>VkCommandPool</code> that <code>commandBuffer</code> was allocated from <strong class=\"purple\">must</strong> support compute operations"
+        },
+        {
+          "vuid": "VUID-vkCmdBuildAccelerationStructureIndirectKHR-renderpass",
+          "text": " This command <strong class=\"purple\">must</strong> only be called outside of a render pass instance"
+        },
+        {
+          "vuid": "VUID-vkCmdBuildAccelerationStructureIndirectKHR-commonparent",
+          "text": " Both of <code>commandBuffer</code>, and <code>indirectBuffer</code> <strong class=\"purple\">must</strong> have been created, allocated, or retrieved from the same <a href=\"#VkDevice\">VkDevice</a>"
+        }
+      ],
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)+(VK_KHR_deferred_host_operations)": [
+        {
+          "vuid": "VUID-vkCmdBuildAccelerationStructureIndirectKHR-pNext-03536",
+          "text": " The <a href=\"#VkDeferredOperationInfoKHR\">VkDeferredOperationInfoKHR</a> structure <strong class=\"purple\">must</strong> not be included in the <code>pNext</code> chain of any of the provided <a href=\"#VkAccelerationStructureBuildGeometryInfoKHR\">VkAccelerationStructureBuildGeometryInfoKHR</a> structures"
+        }
+      ]
+    },
+    "VkAccelerationStructureBuildGeometryInfoKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-VkAccelerationStructureBuildGeometryInfoKHR-update-03537",
+          "text": " If <code>update</code> is <code>VK_TRUE</code>, <code>srcAccelerationStructure</code> <strong class=\"purple\">must</strong> not be <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureBuildGeometryInfoKHR-update-03538",
+          "text": " If <code>update</code> is <code>VK_TRUE</code>, <code>srcAccelerationStructure</code> <strong class=\"purple\">must</strong> have been built before with <code>VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR</code> set in <a href=\"#VkAccelerationStructureBuildGeometryInfoKHR\">VkAccelerationStructureBuildGeometryInfoKHR</a>::<code>flags</code>"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureBuildGeometryInfoKHR-scratchData-03539",
+          "text": " <code>scratchData</code> <strong class=\"purple\">must</strong> have been created with <code>VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR</code> usage flag"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureBuildGeometryInfoKHR-update-03540",
+          "text": " If <code>update</code> is <code>VK_TRUE</code>, the <code>srcAccelerationStructure</code> and <code>dstAccelerationStructure</code> objects <strong class=\"purple\">must</strong> either be the same object or not have any <a href=\"#resources-memory-aliasing\">memory aliasing</a>"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureBuildGeometryInfoKHR-sType-sType",
+          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureBuildGeometryInfoKHR-pNext-pNext",
+          "text": " <code>pNext</code> <strong class=\"purple\">must</strong> be <code>NULL</code> or a pointer to a valid instance of <a href=\"#VkDeferredOperationInfoKHR\">VkDeferredOperationInfoKHR</a>"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureBuildGeometryInfoKHR-sType-unique",
+          "text": " The <code>sType</code> value of each struct in the <code>pNext</code> chain <strong class=\"purple\">must</strong> be unique"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureBuildGeometryInfoKHR-type-parameter",
+          "text": " <code>type</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkAccelerationStructureTypeKHR\">VkAccelerationStructureTypeKHR</a> value"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureBuildGeometryInfoKHR-flags-parameter",
+          "text": " <code>flags</code> <strong class=\"purple\">must</strong> be a valid combination of <a href=\"#VkBuildAccelerationStructureFlagBitsKHR\">VkBuildAccelerationStructureFlagBitsKHR</a> values"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureBuildGeometryInfoKHR-srcAccelerationStructure-parameter",
+          "text": " If <code>srcAccelerationStructure</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, <code>srcAccelerationStructure</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkAccelerationStructureKHR\">VkAccelerationStructureKHR</a> handle"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureBuildGeometryInfoKHR-dstAccelerationStructure-parameter",
+          "text": " <code>dstAccelerationStructure</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkAccelerationStructureKHR\">VkAccelerationStructureKHR</a> handle"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureBuildGeometryInfoKHR-scratchData-parameter",
+          "text": " <code>scratchData</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDeviceOrHostAddressKHR\">VkDeviceOrHostAddressKHR</a> union"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureBuildGeometryInfoKHR-commonparent",
+          "text": " Both of <code>dstAccelerationStructure</code>, and <code>srcAccelerationStructure</code> that are valid handles of non-ignored parameters <strong class=\"purple\">must</strong> have been created, allocated, or retrieved from the same <a href=\"#VkDevice\">VkDevice</a>"
+        }
+      ]
+    },
+    "VkAccelerationStructureGeometryKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-VkAccelerationStructureGeometryKHR-geometryType-03541",
+          "text": " If <code>geometryType</code> is <code>VK_GEOMETRY_TYPE_AABBS_KHR</code>, the <code>aabbs</code> member of <code>geometry</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkAccelerationStructureGeometryAabbsDataKHR\">VkAccelerationStructureGeometryAabbsDataKHR</a> structure"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureGeometryKHR-geometryType-03542",
+          "text": " If <code>geometryType</code> is <code>VK_GEOMETRY_TYPE_TRIANGLES_KHR</code>, the <code>triangles</code> member of <code>geometry</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkAccelerationStructureGeometryTrianglesDataKHR\">VkAccelerationStructureGeometryTrianglesDataKHR</a> structure"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureGeometryKHR-geometryType-03543",
+          "text": " If <code>geometryType</code> is <code>VK_GEOMETRY_TYPE_INSTANCES_KHR</code>, the <code>instances</code> member of <code>geometry</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkAccelerationStructureGeometryInstancesDataKHR\">VkAccelerationStructureGeometryInstancesDataKHR</a> structure"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureGeometryKHR-sType-sType",
+          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureGeometryKHR-pNext-pNext",
+          "text": " <code>pNext</code> <strong class=\"purple\">must</strong> be <code>NULL</code>"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureGeometryKHR-geometryType-parameter",
+          "text": " <code>geometryType</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkGeometryTypeKHR\">VkGeometryTypeKHR</a> value"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureGeometryKHR-geometry-parameter",
+          "text": " <code>geometry</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkAccelerationStructureGeometryDataKHR\">VkAccelerationStructureGeometryDataKHR</a> union"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureGeometryKHR-flags-parameter",
+          "text": " <code>flags</code> <strong class=\"purple\">must</strong> be a valid combination of <a href=\"#VkGeometryFlagBitsKHR\">VkGeometryFlagBitsKHR</a> values"
+        }
+      ]
+    },
+    "VkAccelerationStructureGeometryDataKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-VkAccelerationStructureGeometryDataKHR-triangles-parameter",
+          "text": " <code>triangles</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkAccelerationStructureGeometryTrianglesDataKHR\">VkAccelerationStructureGeometryTrianglesDataKHR</a> structure"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureGeometryDataKHR-aabbs-parameter",
+          "text": " <code>aabbs</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkAccelerationStructureGeometryAabbsDataKHR\">VkAccelerationStructureGeometryAabbsDataKHR</a> structure"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureGeometryDataKHR-instances-parameter",
+          "text": " <code>instances</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkAccelerationStructureGeometryInstancesDataKHR\">VkAccelerationStructureGeometryInstancesDataKHR</a> structure"
+        }
+      ]
+    },
+    "VkAccelerationStructureGeometryTrianglesDataKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-VkAccelerationStructureGeometryTrianglesDataKHR-sType-sType",
+          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureGeometryTrianglesDataKHR-pNext-pNext",
+          "text": " <code>pNext</code> <strong class=\"purple\">must</strong> be <code>NULL</code>"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureGeometryTrianglesDataKHR-vertexFormat-parameter",
+          "text": " <code>vertexFormat</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkFormat\">VkFormat</a> value"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureGeometryTrianglesDataKHR-vertexData-parameter",
+          "text": " <code>vertexData</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDeviceOrHostAddressConstKHR\">VkDeviceOrHostAddressConstKHR</a> union"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureGeometryTrianglesDataKHR-indexType-parameter",
+          "text": " <code>indexType</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkIndexType\">VkIndexType</a> value"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureGeometryTrianglesDataKHR-indexData-parameter",
+          "text": " If <code>indexData</code> is not <code>0</code>, <code>indexData</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDeviceOrHostAddressConstKHR\">VkDeviceOrHostAddressConstKHR</a> union"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureGeometryTrianglesDataKHR-transformData-parameter",
+          "text": " If <code>transformData</code> is not <code>0</code>, <code>transformData</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDeviceOrHostAddressConstKHR\">VkDeviceOrHostAddressConstKHR</a> union"
+        }
+      ]
+    },
+    "VkAccelerationStructureGeometryAabbsDataKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-VkAccelerationStructureGeometryAabbsDataKHR-data-03544",
+          "text": " <code>data</code> <strong class=\"purple\">must</strong> be aligned to <code>8</code> bytes"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureGeometryAabbsDataKHR-stride-03545",
+          "text": " <code>stride</code> <strong class=\"purple\">must</strong> be a multiple of <code>8</code>"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureGeometryAabbsDataKHR-sType-sType",
+          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureGeometryAabbsDataKHR-pNext-pNext",
+          "text": " <code>pNext</code> <strong class=\"purple\">must</strong> be <code>NULL</code>"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureGeometryAabbsDataKHR-data-parameter",
+          "text": " <code>data</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDeviceOrHostAddressConstKHR\">VkDeviceOrHostAddressConstKHR</a> union"
+        }
+      ]
+    },
+    "VkAabbPositionsKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-VkAabbPositionsKHR-minX-03546",
+          "text": " <code>minX</code> <strong class=\"purple\">must</strong> be less than or equal to <code>maxX</code>"
+        },
+        {
+          "vuid": "VUID-VkAabbPositionsKHR-minY-03547",
+          "text": " <code>minY</code> <strong class=\"purple\">must</strong> be less than or equal to <code>maxY</code>"
+        },
+        {
+          "vuid": "VUID-VkAabbPositionsKHR-minZ-03548",
+          "text": " <code>minZ</code> <strong class=\"purple\">must</strong> be less than or equal to <code>maxZ</code>"
+        }
+      ]
+    },
+    "VkAccelerationStructureGeometryInstancesDataKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-VkAccelerationStructureGeometryInstancesDataKHR-data-03549",
+          "text": " <code>data</code> <strong class=\"purple\">must</strong> be aligned to <code>16</code> bytes"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureGeometryInstancesDataKHR-arrayOfPointers-03550",
+          "text": " If <code>arrayOfPointers</code> is true, each pointer <strong class=\"purple\">must</strong> be aligned to <code>16</code> bytes"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureGeometryInstancesDataKHR-sType-sType",
+          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureGeometryInstancesDataKHR-pNext-pNext",
+          "text": " <code>pNext</code> <strong class=\"purple\">must</strong> be <code>NULL</code>"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureGeometryInstancesDataKHR-data-parameter",
+          "text": " <code>data</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDeviceOrHostAddressConstKHR\">VkDeviceOrHostAddressConstKHR</a> union"
+        }
+      ]
+    },
+    "VkAccelerationStructureInstanceKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-VkAccelerationStructureInstanceKHR-flags-parameter",
+          "text": " <code>flags</code> <strong class=\"purple\">must</strong> be a valid combination of <a href=\"#VkGeometryInstanceFlagBitsKHR\">VkGeometryInstanceFlagBitsKHR</a> values"
+        }
+      ]
+    },
+    "VkAccelerationStructureBuildOffsetInfoKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-VkAccelerationStructureBuildOffsetInfoKHR-primitiveOffset-03551",
+          "text": " For geometries of type <code>VK_GEOMETRY_TYPE_TRIANGLES_KHR</code>, if the geometry uses indices, the offset <code>primitiveOffset</code> from <a href=\"#VkAccelerationStructureGeometryTrianglesDataKHR\">VkAccelerationStructureGeometryTrianglesDataKHR</a>::<code>indexData</code> <strong class=\"purple\">must</strong> be a multiple of the element size of <a href=\"#VkAccelerationStructureGeometryTrianglesDataKHR\">VkAccelerationStructureGeometryTrianglesDataKHR</a>::<code>indexType</code>"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureBuildOffsetInfoKHR-primitiveOffset-03552",
+          "text": " For geometries of type <code>VK_GEOMETRY_TYPE_TRIANGLES_KHR</code>, if the geometry doesn&#8217;t use indices, the offset <code>primitiveOffset</code> from <a href=\"#VkAccelerationStructureGeometryTrianglesDataKHR\">VkAccelerationStructureGeometryTrianglesDataKHR</a>::<code>vertexData</code> <strong class=\"purple\">must</strong> be a multiple of the component size of <a href=\"#VkAccelerationStructureGeometryTrianglesDataKHR\">VkAccelerationStructureGeometryTrianglesDataKHR</a>::<code>vertexType</code>"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureBuildOffsetInfoKHR-transformOffset-03553",
+          "text": " For geometries of type <code>VK_GEOMETRY_TYPE_TRIANGLES_KHR</code>, the offset <code>transformOffset</code> from <a href=\"#VkAccelerationStructureGeometryTrianglesDataKHR\">VkAccelerationStructureGeometryTrianglesDataKHR</a>::<code>transformData</code> <strong class=\"purple\">must</strong> be a multiple of 16"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureBuildOffsetInfoKHR-primitiveOffset-03554",
+          "text": " For geometries of type <code>VK_GEOMETRY_TYPE_AABBS_KHR</code>, the offset <code>primitiveOffset</code> from <a href=\"#VkAccelerationStructureGeometryAabbsDataKHR\">VkAccelerationStructureGeometryAabbsDataKHR</a>::<code>data</code> <strong class=\"purple\">must</strong> be a multiple of 8"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureBuildOffsetInfoKHR-primitiveOffset-03555",
+          "text": "   For geometries of type <code>VK_GEOMETRY_TYPE_INSTANCES_KHR</code>, the offset   <code>primitiveOffset</code> from   <a href=\"#VkAccelerationStructureGeometryInstancesDataKHR\">VkAccelerationStructureGeometryInstancesDataKHR</a>::<code>data</code> <strong class=\"purple\">must</strong>   be a multiple of 16 // TODO - Almost certainly should be more here"
+        }
+      ]
+    },
+    "vkCmdWriteAccelerationStructuresPropertiesKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-vkCmdWriteAccelerationStructuresPropertiesKHR-queryPool-02493",
+          "text": " <code>queryPool</code> <strong class=\"purple\">must</strong> have been created with a <code>queryType</code> matching <code>queryType</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdWriteAccelerationStructuresPropertiesKHR-queryPool-02494",
+          "text": " The queries identified by <code>queryPool</code> and <code>firstQuery</code> <strong class=\"purple\">must</strong> be <em>unavailable</em>"
+        },
+        {
+          "vuid": "VUID-vkCmdWriteAccelerationStructuresPropertiesKHR-accelerationStructures-03431",
+          "text": " All acceleration structures in <code>accelerationStructures</code> <strong class=\"purple\">must</strong> have been built with <code>VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR</code> if <code>queryType</code> is <code>VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdWriteAccelerationStructuresPropertiesKHR-queryType-03432",
+          "text": " <code>queryType</code> <strong class=\"purple\">must</strong> be <code>VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR</code> or <code>VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdWriteAccelerationStructuresPropertiesKHR-commandBuffer-parameter",
+          "text": " <code>commandBuffer</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkCommandBuffer\">VkCommandBuffer</a> handle"
+        },
+        {
+          "vuid": "VUID-vkCmdWriteAccelerationStructuresPropertiesKHR-pAccelerationStructures-parameter",
+          "text": " <code>pAccelerationStructures</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>accelerationStructureCount</code> valid <a href=\"#VkAccelerationStructureKHR\">VkAccelerationStructureKHR</a> handles"
+        },
+        {
+          "vuid": "VUID-vkCmdWriteAccelerationStructuresPropertiesKHR-queryType-parameter",
+          "text": " <code>queryType</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkQueryType\">VkQueryType</a> value"
+        },
+        {
+          "vuid": "VUID-vkCmdWriteAccelerationStructuresPropertiesKHR-queryPool-parameter",
+          "text": " <code>queryPool</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkQueryPool\">VkQueryPool</a> handle"
+        },
+        {
+          "vuid": "VUID-vkCmdWriteAccelerationStructuresPropertiesKHR-commandBuffer-recording",
+          "text": " <code>commandBuffer</code> <strong class=\"purple\">must</strong> be in the <a href=\"#commandbuffers-lifecycle\">recording state</a>"
+        },
+        {
+          "vuid": "VUID-vkCmdWriteAccelerationStructuresPropertiesKHR-commandBuffer-cmdpool",
+          "text": " The <code>VkCommandPool</code> that <code>commandBuffer</code> was allocated from <strong class=\"purple\">must</strong> support compute operations"
+        },
+        {
+          "vuid": "VUID-vkCmdWriteAccelerationStructuresPropertiesKHR-renderpass",
+          "text": " This command <strong class=\"purple\">must</strong> only be called outside of a render pass instance"
+        },
+        {
+          "vuid": "VUID-vkCmdWriteAccelerationStructuresPropertiesKHR-accelerationStructureCount-arraylength",
           "text": " <code>accelerationStructureCount</code> <strong class=\"purple\">must</strong> be greater than <code>0</code>"
         },
         {
-          "vuid": "VUID-vkCmdWriteAccelerationStructuresPropertiesNV-commonparent",
+          "vuid": "VUID-vkCmdWriteAccelerationStructuresPropertiesKHR-commonparent",
           "text": " Each of <code>commandBuffer</code>, <code>queryPool</code>, and the elements of <code>pAccelerationStructures</code> <strong class=\"purple\">must</strong> have been created, allocated, or retrieved from the same <a href=\"#VkDevice\">VkDevice</a>"
         }
       ]
     },
     "vkCmdCopyAccelerationStructureNV": {
-      "(VK_NV_ray_tracing)": [
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_NV_ray_tracing)": [
         {
-          "vuid": "VUID-vkCmdCopyAccelerationStructureNV-mode-02496",
-          "text": " <code>mode</code> <strong class=\"purple\">must</strong> be <code>VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV</code> or <code>VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV</code>"
+          "vuid": "VUID-vkCmdCopyAccelerationStructureNV-mode-03410",
+          "text": " <code>mode</code> <strong class=\"purple\">must</strong> be <code>VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR</code> or <code>VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR</code>"
         },
         {
-          "vuid": "VUID-vkCmdCopyAccelerationStructureNV-src-02497",
-          "text": " <code>src</code> <strong class=\"purple\">must</strong> have been built with <code>VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_NV</code> if <code>mode</code> is <code>VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV</code>"
+          "vuid": "VUID-vkCmdCopyAccelerationStructureNV-src-03411",
+          "text": " <code>src</code> <strong class=\"purple\">must</strong> have been built with <code>VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR</code> if <code>mode</code> is <code>VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR</code>"
         },
         {
           "vuid": "VUID-vkCmdCopyAccelerationStructureNV-commandBuffer-parameter",
@@ -24604,15 +26444,15 @@
         },
         {
           "vuid": "VUID-vkCmdCopyAccelerationStructureNV-dst-parameter",
-          "text": " <code>dst</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkAccelerationStructureNV\">VkAccelerationStructureNV</a> handle"
+          "text": " <code>dst</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkAccelerationStructureKHR\">VkAccelerationStructureKHR</a> handle"
         },
         {
           "vuid": "VUID-vkCmdCopyAccelerationStructureNV-src-parameter",
-          "text": " <code>src</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkAccelerationStructureNV\">VkAccelerationStructureNV</a> handle"
+          "text": " <code>src</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkAccelerationStructureKHR\">VkAccelerationStructureKHR</a> handle"
         },
         {
           "vuid": "VUID-vkCmdCopyAccelerationStructureNV-mode-parameter",
-          "text": " <code>mode</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkCopyAccelerationStructureModeNV\">VkCopyAccelerationStructureModeNV</a> value"
+          "text": " <code>mode</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkCopyAccelerationStructureModeKHR\">VkCopyAccelerationStructureModeKHR</a> value"
         },
         {
           "vuid": "VUID-vkCmdCopyAccelerationStructureNV-commandBuffer-recording",
@@ -24632,6 +26472,476 @@
         }
       ]
     },
+    "vkCmdCopyAccelerationStructureKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-vkCmdCopyAccelerationStructureKHR-None-03556",
+          "text": " All <code>VkAccelerationStructureKHR</code> objects referenced by this command <strong class=\"purple\">must</strong> be bound to device memory."
+        },
+        {
+          "vuid": "VUID-vkCmdCopyAccelerationStructureKHR-commandBuffer-parameter",
+          "text": " <code>commandBuffer</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkCommandBuffer\">VkCommandBuffer</a> handle"
+        },
+        {
+          "vuid": "VUID-vkCmdCopyAccelerationStructureKHR-pInfo-parameter",
+          "text": " <code>pInfo</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkCopyAccelerationStructureInfoKHR\">VkCopyAccelerationStructureInfoKHR</a> structure"
+        },
+        {
+          "vuid": "VUID-vkCmdCopyAccelerationStructureKHR-commandBuffer-recording",
+          "text": " <code>commandBuffer</code> <strong class=\"purple\">must</strong> be in the <a href=\"#commandbuffers-lifecycle\">recording state</a>"
+        },
+        {
+          "vuid": "VUID-vkCmdCopyAccelerationStructureKHR-commandBuffer-cmdpool",
+          "text": " The <code>VkCommandPool</code> that <code>commandBuffer</code> was allocated from <strong class=\"purple\">must</strong> support compute operations"
+        },
+        {
+          "vuid": "VUID-vkCmdCopyAccelerationStructureKHR-renderpass",
+          "text": " This command <strong class=\"purple\">must</strong> only be called outside of a render pass instance"
+        }
+      ],
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)+(VK_KHR_deferred_host_operations)": [
+        {
+          "vuid": "VUID-vkCmdCopyAccelerationStructureKHR-pNext-03557",
+          "text": " The <a href=\"#VkDeferredOperationInfoKHR\">VkDeferredOperationInfoKHR</a> structure <strong class=\"purple\">must</strong> not be included in the <code>pNext</code> chain of the <a href=\"#VkCopyAccelerationStructureInfoKHR\">VkCopyAccelerationStructureInfoKHR</a> structure"
+        }
+      ]
+    },
+    "VkCopyAccelerationStructureInfoKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-VkCopyAccelerationStructureInfoKHR-mode-03410",
+          "text": " <code>mode</code> <strong class=\"purple\">must</strong> be <code>VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR</code> or <code>VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkCopyAccelerationStructureInfoKHR-src-03411",
+          "text": " <code>src</code> <strong class=\"purple\">must</strong> have been built with <code>VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR</code> if <code>mode</code> is <code>VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkCopyAccelerationStructureInfoKHR-sType-sType",
+          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkCopyAccelerationStructureInfoKHR-pNext-pNext",
+          "text": " <code>pNext</code> <strong class=\"purple\">must</strong> be <code>NULL</code> or a pointer to a valid instance of <a href=\"#VkDeferredOperationInfoKHR\">VkDeferredOperationInfoKHR</a>"
+        },
+        {
+          "vuid": "VUID-VkCopyAccelerationStructureInfoKHR-sType-unique",
+          "text": " The <code>sType</code> value of each struct in the <code>pNext</code> chain <strong class=\"purple\">must</strong> be unique"
+        },
+        {
+          "vuid": "VUID-VkCopyAccelerationStructureInfoKHR-src-parameter",
+          "text": " <code>src</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkAccelerationStructureKHR\">VkAccelerationStructureKHR</a> handle"
+        },
+        {
+          "vuid": "VUID-VkCopyAccelerationStructureInfoKHR-dst-parameter",
+          "text": " <code>dst</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkAccelerationStructureKHR\">VkAccelerationStructureKHR</a> handle"
+        },
+        {
+          "vuid": "VUID-VkCopyAccelerationStructureInfoKHR-mode-parameter",
+          "text": " <code>mode</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkCopyAccelerationStructureModeKHR\">VkCopyAccelerationStructureModeKHR</a> value"
+        },
+        {
+          "vuid": "VUID-VkCopyAccelerationStructureInfoKHR-commonparent",
+          "text": " Both of <code>dst</code>, and <code>src</code> <strong class=\"purple\">must</strong> have been created, allocated, or retrieved from the same <a href=\"#VkDevice\">VkDevice</a>"
+        }
+      ]
+    },
+    "vkCmdCopyAccelerationStructureToMemoryKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-vkCmdCopyAccelerationStructureToMemoryKHR-None-03558",
+          "text": " All <code>VkDeviceOrHostAddressConstKHR</code> referenced by this command <strong class=\"purple\">must</strong> contain valid device addresses"
+        },
+        {
+          "vuid": "VUID-vkCmdCopyAccelerationStructureToMemoryKHR-None-03559",
+          "text": " All <code>VkAccelerationStructureKHR</code> objects referenced by this command <strong class=\"purple\">must</strong> be bound to device memory."
+        },
+        {
+          "vuid": "VUID-vkCmdCopyAccelerationStructureToMemoryKHR-mode-03412",
+          "text": " <code>mode</code> <strong class=\"purple\">must</strong> be <code>VK_COPY_ACCELERATION_STRUCTURE_MODE_SERIALIZE_KHR</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdCopyAccelerationStructureToMemoryKHR-commandBuffer-parameter",
+          "text": " <code>commandBuffer</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkCommandBuffer\">VkCommandBuffer</a> handle"
+        },
+        {
+          "vuid": "VUID-vkCmdCopyAccelerationStructureToMemoryKHR-pInfo-parameter",
+          "text": " <code>pInfo</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkCopyAccelerationStructureToMemoryInfoKHR\">VkCopyAccelerationStructureToMemoryInfoKHR</a> structure"
+        },
+        {
+          "vuid": "VUID-vkCmdCopyAccelerationStructureToMemoryKHR-commandBuffer-recording",
+          "text": " <code>commandBuffer</code> <strong class=\"purple\">must</strong> be in the <a href=\"#commandbuffers-lifecycle\">recording state</a>"
+        },
+        {
+          "vuid": "VUID-vkCmdCopyAccelerationStructureToMemoryKHR-commandBuffer-cmdpool",
+          "text": " The <code>VkCommandPool</code> that <code>commandBuffer</code> was allocated from <strong class=\"purple\">must</strong> support compute operations"
+        },
+        {
+          "vuid": "VUID-vkCmdCopyAccelerationStructureToMemoryKHR-renderpass",
+          "text": " This command <strong class=\"purple\">must</strong> only be called outside of a render pass instance"
+        }
+      ],
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_deferred_host_operations)": [
+        {
+          "vuid": "VUID-vkCmdCopyAccelerationStructureToMemoryKHR-pNext-03560",
+          "text": " The <a href=\"#VkDeferredOperationInfoKHR\">VkDeferredOperationInfoKHR</a> structure <strong class=\"purple\">must</strong> not be included in the <code>pNext</code> chain of the <a href=\"#VkCopyAccelerationStructureToMemoryInfoKHR\">VkCopyAccelerationStructureToMemoryInfoKHR</a> structure"
+        }
+      ]
+    },
+    "VkCopyAccelerationStructureToMemoryInfoKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-VkCopyAccelerationStructureToMemoryInfoKHR-dst-03561",
+          "text": " The memory pointed to by <code>dst</code> <strong class=\"purple\">must</strong> be at least as large as the serialization size of <code>src</code>, as reported by <code>VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR</code>."
+        },
+        {
+          "vuid": "VUID-VkCopyAccelerationStructureToMemoryInfoKHR-mode-03412",
+          "text": " <code>mode</code> <strong class=\"purple\">must</strong> be <code>VK_COPY_ACCELERATION_STRUCTURE_MODE_SERIALIZE_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkCopyAccelerationStructureToMemoryInfoKHR-sType-sType",
+          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_TO_MEMORY_INFO_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkCopyAccelerationStructureToMemoryInfoKHR-pNext-pNext",
+          "text": " <code>pNext</code> <strong class=\"purple\">must</strong> be <code>NULL</code> or a pointer to a valid instance of <a href=\"#VkDeferredOperationInfoKHR\">VkDeferredOperationInfoKHR</a>"
+        },
+        {
+          "vuid": "VUID-VkCopyAccelerationStructureToMemoryInfoKHR-sType-unique",
+          "text": " The <code>sType</code> value of each struct in the <code>pNext</code> chain <strong class=\"purple\">must</strong> be unique"
+        },
+        {
+          "vuid": "VUID-VkCopyAccelerationStructureToMemoryInfoKHR-src-parameter",
+          "text": " <code>src</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkAccelerationStructureKHR\">VkAccelerationStructureKHR</a> handle"
+        },
+        {
+          "vuid": "VUID-VkCopyAccelerationStructureToMemoryInfoKHR-dst-parameter",
+          "text": " <code>dst</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDeviceOrHostAddressKHR\">VkDeviceOrHostAddressKHR</a> union"
+        },
+        {
+          "vuid": "VUID-VkCopyAccelerationStructureToMemoryInfoKHR-mode-parameter",
+          "text": " <code>mode</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkCopyAccelerationStructureModeKHR\">VkCopyAccelerationStructureModeKHR</a> value"
+        }
+      ]
+    },
+    "vkCmdCopyMemoryToAccelerationStructureKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-vkCmdCopyMemoryToAccelerationStructureKHR-None-03562",
+          "text": " All <code>VkDeviceOrHostAddressKHR</code> referenced by this command <strong class=\"purple\">must</strong> contain valid device addresses"
+        },
+        {
+          "vuid": "VUID-vkCmdCopyMemoryToAccelerationStructureKHR-None-03563",
+          "text": " All <code>VkAccelerationStructureKHR</code> objects referenced by this command <strong class=\"purple\">must</strong> be bound to device memory."
+        },
+        {
+          "vuid": "VUID-vkCmdCopyMemoryToAccelerationStructureKHR-mode-03413",
+          "text": " <code>mode</code> <strong class=\"purple\">must</strong> be <code>VK_COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR</code>"
+        },
+        {
+          "vuid": "VUID-vkCmdCopyMemoryToAccelerationStructureKHR-pInfo-03414",
+          "text": " The data in <code>pInfo-&gt;src</code> <strong class=\"purple\">must</strong> have a format compatible with the destination physical device as returned by <a href=\"#vkGetDeviceAccelerationStructureCompatibilityKHR\">vkGetDeviceAccelerationStructureCompatibilityKHR</a>"
+        },
+        {
+          "vuid": "VUID-vkCmdCopyMemoryToAccelerationStructureKHR-commandBuffer-parameter",
+          "text": " <code>commandBuffer</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkCommandBuffer\">VkCommandBuffer</a> handle"
+        },
+        {
+          "vuid": "VUID-vkCmdCopyMemoryToAccelerationStructureKHR-pInfo-parameter",
+          "text": " <code>pInfo</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkCopyMemoryToAccelerationStructureInfoKHR\">VkCopyMemoryToAccelerationStructureInfoKHR</a> structure"
+        },
+        {
+          "vuid": "VUID-vkCmdCopyMemoryToAccelerationStructureKHR-commandBuffer-recording",
+          "text": " <code>commandBuffer</code> <strong class=\"purple\">must</strong> be in the <a href=\"#commandbuffers-lifecycle\">recording state</a>"
+        },
+        {
+          "vuid": "VUID-vkCmdCopyMemoryToAccelerationStructureKHR-commandBuffer-cmdpool",
+          "text": " The <code>VkCommandPool</code> that <code>commandBuffer</code> was allocated from <strong class=\"purple\">must</strong> support compute operations"
+        },
+        {
+          "vuid": "VUID-vkCmdCopyMemoryToAccelerationStructureKHR-renderpass",
+          "text": " This command <strong class=\"purple\">must</strong> only be called outside of a render pass instance"
+        }
+      ],
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)+(VK_KHR_deferred_host_operations)": [
+        {
+          "vuid": "VUID-vkCmdCopyMemoryToAccelerationStructureKHR-pNext-03564",
+          "text": " The <a href=\"#VkDeferredOperationInfoKHR\">VkDeferredOperationInfoKHR</a> structure <strong class=\"purple\">must</strong> not be included in the <code>pNext</code> chain of the <a href=\"#VkCopyMemoryToAccelerationStructureInfoKHR\">VkCopyMemoryToAccelerationStructureInfoKHR</a> structure"
+        }
+      ]
+    },
+    "VkCopyMemoryToAccelerationStructureInfoKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-VkCopyMemoryToAccelerationStructureInfoKHR-mode-03413",
+          "text": " <code>mode</code> <strong class=\"purple\">must</strong> be <code>VK_COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkCopyMemoryToAccelerationStructureInfoKHR-pInfo-03414",
+          "text": " The data in <code>pInfo-&gt;src</code> <strong class=\"purple\">must</strong> have a format compatible with the destination physical device as returned by <a href=\"#vkGetDeviceAccelerationStructureCompatibilityKHR\">vkGetDeviceAccelerationStructureCompatibilityKHR</a>"
+        },
+        {
+          "vuid": "VUID-VkCopyMemoryToAccelerationStructureInfoKHR-sType-sType",
+          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_COPY_MEMORY_TO_ACCELERATION_STRUCTURE_INFO_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkCopyMemoryToAccelerationStructureInfoKHR-pNext-pNext",
+          "text": " <code>pNext</code> <strong class=\"purple\">must</strong> be <code>NULL</code> or a pointer to a valid instance of <a href=\"#VkDeferredOperationInfoKHR\">VkDeferredOperationInfoKHR</a>"
+        },
+        {
+          "vuid": "VUID-VkCopyMemoryToAccelerationStructureInfoKHR-sType-unique",
+          "text": " The <code>sType</code> value of each struct in the <code>pNext</code> chain <strong class=\"purple\">must</strong> be unique"
+        },
+        {
+          "vuid": "VUID-VkCopyMemoryToAccelerationStructureInfoKHR-src-parameter",
+          "text": " <code>src</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDeviceOrHostAddressConstKHR\">VkDeviceOrHostAddressConstKHR</a> union"
+        },
+        {
+          "vuid": "VUID-VkCopyMemoryToAccelerationStructureInfoKHR-dst-parameter",
+          "text": " <code>dst</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkAccelerationStructureKHR\">VkAccelerationStructureKHR</a> handle"
+        },
+        {
+          "vuid": "VUID-VkCopyMemoryToAccelerationStructureInfoKHR-mode-parameter",
+          "text": " <code>mode</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkCopyAccelerationStructureModeKHR\">VkCopyAccelerationStructureModeKHR</a> value"
+        }
+      ]
+    },
+    "vkGetDeviceAccelerationStructureCompatibilityKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-vkGetDeviceAccelerationStructureCompatibilityKHR-rayTracing-03565",
+          "text": " The <a href=\"#features-raytracing\"><code>rayTracing</code></a> or <a href=\"#features-rayQuery\"><code>rayQuery</code></a> feature <strong class=\"purple\">must</strong> be enabled"
+        },
+        {
+          "vuid": "VUID-vkGetDeviceAccelerationStructureCompatibilityKHR-device-parameter",
+          "text": " <code>device</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDevice\">VkDevice</a> handle"
+        },
+        {
+          "vuid": "VUID-vkGetDeviceAccelerationStructureCompatibilityKHR-version-parameter",
+          "text": " <code>version</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkAccelerationStructureVersionKHR\">VkAccelerationStructureVersionKHR</a> structure"
+        }
+      ]
+    },
+    "VkAccelerationStructureVersionKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-VkAccelerationStructureVersionKHR-sType-sType",
+          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_VERSION_KHR</code>"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureVersionKHR-pNext-pNext",
+          "text": " <code>pNext</code> <strong class=\"purple\">must</strong> be <code>NULL</code>"
+        },
+        {
+          "vuid": "VUID-VkAccelerationStructureVersionKHR-versionData-parameter",
+          "text": " <code>versionData</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>2</code>*VK_UUID_SIZE <code>uint8_t</code> values"
+        }
+      ]
+    },
+    "vkBuildAccelerationStructureKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-vkBuildAccelerationStructureKHR-pOffsetInfos-03402",
+          "text": " <code>pOffsetInfos</code>[i] <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>pInfos</code>[i].<code>geometryCount</code> <code>VkAccelerationStructureBuildOffsetInfoKHR</code> structures"
+        },
+        {
+          "vuid": "VUID-vkBuildAccelerationStructureKHR-pInfos-03403",
+          "text": " Each <code>pInfos</code>[i].<code>srcAccelerationStructure</code> <strong class=\"purple\">must</strong> not refer to the same acceleration structure as any <code>pInfos</code>[i].<code>dstAccelerationStructure</code> that is provided to the same build command unless it is identical for an update"
+        },
+        {
+          "vuid": "VUID-vkBuildAccelerationStructureKHR-pInfos-03404",
+          "text": " For each <code>pInfos</code>[i], <code>dstAccelerationStructure</code> <strong class=\"purple\">must</strong> have been created with compatible <a href=\"#VkAccelerationStructureCreateInfoKHR\">VkAccelerationStructureCreateInfoKHR</a> where <a href=\"#VkAccelerationStructureCreateInfoKHR\">VkAccelerationStructureCreateInfoKHR</a>::<code>type</code> and <a href=\"#VkAccelerationStructureCreateInfoKHR\">VkAccelerationStructureCreateInfoKHR</a>::<code>flags</code> are identical to <a href=\"#VkAccelerationStructureBuildGeometryInfoKHR\">VkAccelerationStructureBuildGeometryInfoKHR</a>::<code>type</code> and <a href=\"#VkAccelerationStructureBuildGeometryInfoKHR\">VkAccelerationStructureBuildGeometryInfoKHR</a>::<code>flags</code> respectively, <a href=\"#VkAccelerationStructureBuildGeometryInfoKHR\">VkAccelerationStructureBuildGeometryInfoKHR</a>::<code>geometryCount</code> for <code>dstAccelerationStructure</code> are greater than or equal to the build size, and each geometry in <a href=\"#VkAccelerationStructureBuildGeometryInfoKHR\">VkAccelerationStructureBuildGeometryInfoKHR</a>::<code>ppGeometries</code> for <code>dstAccelerationStructure</code> has greater than or equal to the number of vertices, indices, and AABBs, <a href=\"#VkAccelerationStructureGeometryTrianglesDataKHR\">VkAccelerationStructureGeometryTrianglesDataKHR</a>::<code>transformData</code> is both 0 or both non-zero, and all other parameters are the same"
+        },
+        {
+          "vuid": "VUID-vkBuildAccelerationStructureKHR-pInfos-03405",
+          "text": " For each <code>pInfos</code>[i], if <code>update</code> is <code>VK_TRUE</code>, then objects that were previously active for that acceleration structure <strong class=\"purple\">must</strong> not be made inactive as per <a href=\"#acceleration-structure-inactive-prims\">Inactive Primitives and Instances</a>"
+        },
+        {
+          "vuid": "VUID-vkBuildAccelerationStructureKHR-pInfos-03406",
+          "text": " For each <code>pInfos</code>[i], if <code>update</code> is <code>VK_TRUE</code>, then objects that were previously inactive for that acceleration structure <strong class=\"purple\">must</strong> not be made active as per <a href=\"#acceleration-structure-inactive-prims\">Inactive Primitives and Instances</a>"
+        },
+        {
+          "vuid": "VUID-vkBuildAccelerationStructureKHR-None-03407",
+          "text": " Any acceleration structure instance in any top level build in this command <strong class=\"purple\">must</strong> not reference any bottom level acceleration structure built by this command"
+        },
+        {
+          "vuid": "VUID-vkBuildAccelerationStructureKHR-pInfos-03408",
+          "text": " There <strong class=\"purple\">must</strong> not be any <a href=\"#resources-memory-aliasing\">memory aliasing</a> between the scratch memories that are provided in all the <code>pInfos</code>[i].<code>scratchData</code> memories for the acceleration structure builds"
+        },
+        {
+          "vuid": "VUID-vkBuildAccelerationStructureKHR-None-03409",
+          "text": " There <strong class=\"purple\">must</strong> not be any <a href=\"#resources-memory-aliasing\">memory aliasing</a> between memory bound to any top level, bottom level, or instance acceleration structure accessed by this command"
+        },
+        {
+          "vuid": "VUID-vkBuildAccelerationStructureKHR-device-parameter",
+          "text": " <code>device</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDevice\">VkDevice</a> handle"
+        },
+        {
+          "vuid": "VUID-vkBuildAccelerationStructureKHR-pInfos-parameter",
+          "text": " <code>pInfos</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>infoCount</code> valid <a href=\"#VkAccelerationStructureBuildGeometryInfoKHR\">VkAccelerationStructureBuildGeometryInfoKHR</a> structures"
+        },
+        {
+          "vuid": "VUID-vkBuildAccelerationStructureKHR-ppOffsetInfos-parameter",
+          "text": " <code>ppOffsetInfos</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>infoCount</code> <a href=\"#VkAccelerationStructureBuildOffsetInfoKHR\">VkAccelerationStructureBuildOffsetInfoKHR</a> structures"
+        },
+        {
+          "vuid": "VUID-vkBuildAccelerationStructureKHR-infoCount-arraylength",
+          "text": " <code>infoCount</code> <strong class=\"purple\">must</strong> be greater than <code>0</code>"
+        }
+      ],
+      "core": [
+        {
+          "vuid": "VUID-vkBuildAccelerationStructureKHR-None-03437",
+          "text": " All <a href=\"#VkDeviceOrHostAddressKHR\">VkDeviceOrHostAddressKHR</a> or <a href=\"#VkDeviceOrHostAddressConstKHR\">VkDeviceOrHostAddressConstKHR</a> referenced by this command <strong class=\"purple\">must</strong> contain valid host addresses"
+        },
+        {
+          "vuid": "VUID-vkBuildAccelerationStructureKHR-None-03438",
+          "text": " All <code>VkAccelerationStructureKHR</code> objects referenced by this command <strong class=\"purple\">must</strong> be bound to host-visible memory"
+        },
+        {
+          "vuid": "VUID-vkBuildAccelerationStructureKHR-rayTracingHostAccelerationStructureCommands-03439",
+          "text": " The <a href=\"#feature-raytracing-hostascmds\"><code>VkPhysicalDeviceRayTracingFeaturesKHR</code>::<code>rayTracingHostAccelerationStructureCommands</code></a> feature <strong class=\"purple\">must</strong> be enabled"
+        }
+      ]
+    },
+    "vkCopyAccelerationStructureKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-vkCopyAccelerationStructureKHR-None-03440",
+          "text": " All <code>VkAccelerationStructureKHR</code> objects referenced by this command <strong class=\"purple\">must</strong> be bound to host-visible memory"
+        },
+        {
+          "vuid": "VUID-vkCopyAccelerationStructureKHR-rayTracingHostAccelerationStructureCommands-03441",
+          "text": " the <a href=\"#feature-raytracing-hostascmds\"><code>VkPhysicalDeviceRayTracingFeaturesKHR</code>::<code>rayTracingHostAccelerationStructureCommands</code></a> feature <strong class=\"purple\">must</strong> be enabled"
+        },
+        {
+          "vuid": "VUID-vkCopyAccelerationStructureKHR-device-parameter",
+          "text": " <code>device</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDevice\">VkDevice</a> handle"
+        },
+        {
+          "vuid": "VUID-vkCopyAccelerationStructureKHR-pInfo-parameter",
+          "text": " <code>pInfo</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkCopyAccelerationStructureInfoKHR\">VkCopyAccelerationStructureInfoKHR</a> structure"
+        }
+      ]
+    },
+    "vkCopyMemoryToAccelerationStructureKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-vkCopyMemoryToAccelerationStructureKHR-None-03442",
+          "text": " All <code>VkAccelerationStructureKHR</code> objects referenced by this command <strong class=\"purple\">must</strong> be bound to host-visible memory"
+        },
+        {
+          "vuid": "VUID-vkCopyMemoryToAccelerationStructureKHR-None-03443",
+          "text": " All <code>VkDeviceOrHostAddressConstKHR</code> referenced by this command <strong class=\"purple\">must</strong> contain valid host pointers"
+        },
+        {
+          "vuid": "VUID-vkCopyMemoryToAccelerationStructureKHR-rayTracingHostAccelerationStructureCommands-03444",
+          "text": " the <a href=\"#feature-raytracing-hostascmds\"><code>VkPhysicalDeviceRayTracingFeaturesKHR</code>::<code>rayTracingHostAccelerationStructureCommands</code></a> feature <strong class=\"purple\">must</strong> be enabled"
+        },
+        {
+          "vuid": "VUID-vkCopyMemoryToAccelerationStructureKHR-device-parameter",
+          "text": " <code>device</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDevice\">VkDevice</a> handle"
+        },
+        {
+          "vuid": "VUID-vkCopyMemoryToAccelerationStructureKHR-pInfo-parameter",
+          "text": " <code>pInfo</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkCopyMemoryToAccelerationStructureInfoKHR\">VkCopyMemoryToAccelerationStructureInfoKHR</a> structure"
+        }
+      ]
+    },
+    "vkCopyAccelerationStructureToMemoryKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-vkCopyAccelerationStructureToMemoryKHR-None-03445",
+          "text": " All <code>VkAccelerationStructureKHR</code> objects referenced by this command <strong class=\"purple\">must</strong> be bound to host-visible memory"
+        },
+        {
+          "vuid": "VUID-vkCopyAccelerationStructureToMemoryKHR-None-03446",
+          "text": " All <code>VkDeviceOrHostAddressKHR</code> referenced by this command <strong class=\"purple\">must</strong> contain valid host pointers"
+        },
+        {
+          "vuid": "VUID-vkCopyAccelerationStructureToMemoryKHR-rayTracingHostAccelerationStructureCommands-03447",
+          "text": " the <a href=\"#feature-raytracing-hostascmds\"><code>VkPhysicalDeviceRayTracingFeaturesKHR</code>::<code>rayTracingHostAccelerationStructureCommands</code></a> feature <strong class=\"purple\">must</strong> be enabled"
+        },
+        {
+          "vuid": "VUID-vkCopyAccelerationStructureToMemoryKHR-device-parameter",
+          "text": " <code>device</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDevice\">VkDevice</a> handle"
+        },
+        {
+          "vuid": "VUID-vkCopyAccelerationStructureToMemoryKHR-pInfo-parameter",
+          "text": " <code>pInfo</code> <strong class=\"purple\">must</strong> be a valid pointer to a valid <a href=\"#VkCopyAccelerationStructureToMemoryInfoKHR\">VkCopyAccelerationStructureToMemoryInfoKHR</a> structure"
+        }
+      ]
+    },
+    "vkWriteAccelerationStructuresPropertiesKHR": {
+      "(VK_NV_ray_tracing,VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-vkWriteAccelerationStructuresPropertiesKHR-queryType-03448",
+          "text": " If <code>queryType</code> is <code>VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR</code>, then <code>stride</code> <strong class=\"purple\">must</strong> be a multiple of the size of <code>VkDeviceSize</code>"
+        },
+        {
+          "vuid": "VUID-vkWriteAccelerationStructuresPropertiesKHR-queryType-03449",
+          "text": " If <code>queryType</code> is <code>VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR</code>, then <code>data</code> <strong class=\"purple\">must</strong> point to a <code>VkDeviceSize</code>"
+        },
+        {
+          "vuid": "VUID-vkWriteAccelerationStructuresPropertiesKHR-queryType-03450",
+          "text": " If <code>queryType</code> is <code>VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR</code>, then <code>stride</code> <strong class=\"purple\">must</strong> be a multiple of the size of <code>VkDeviceSize</code>"
+        },
+        {
+          "vuid": "VUID-vkWriteAccelerationStructuresPropertiesKHR-queryType-03451",
+          "text": " If <code>queryType</code> is <code>VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR</code>, then <code>data</code> <strong class=\"purple\">must</strong> point to a <code>VkDeviceSize</code>"
+        },
+        {
+          "vuid": "VUID-vkWriteAccelerationStructuresPropertiesKHR-dataSize-03452",
+          "text": " <code>dataSize</code> <strong class=\"purple\">must</strong> be greater than or equal to <span class=\"eq\"><code>accelerationStructureCount</code>*<code>stride</code></span>"
+        },
+        {
+          "vuid": "VUID-vkWriteAccelerationStructuresPropertiesKHR-pAccelerationStructures-03453",
+          "text": " The acceleration structures referenced by <code>pAccelerationStructures</code> <strong class=\"purple\">must</strong> be bound to host-visible memory"
+        },
+        {
+          "vuid": "VUID-vkWriteAccelerationStructuresPropertiesKHR-accelerationStructures-03431",
+          "text": " All acceleration structures in <code>accelerationStructures</code> <strong class=\"purple\">must</strong> have been built with <code>VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR</code> if <code>queryType</code> is <code>VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR</code>"
+        },
+        {
+          "vuid": "VUID-vkWriteAccelerationStructuresPropertiesKHR-queryType-03432",
+          "text": " <code>queryType</code> <strong class=\"purple\">must</strong> be <code>VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR</code> or <code>VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR</code>"
+        },
+        {
+          "vuid": "VUID-vkWriteAccelerationStructuresPropertiesKHR-device-parameter",
+          "text": " <code>device</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkDevice\">VkDevice</a> handle"
+        },
+        {
+          "vuid": "VUID-vkWriteAccelerationStructuresPropertiesKHR-pAccelerationStructures-parameter",
+          "text": " <code>pAccelerationStructures</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>accelerationStructureCount</code> valid <a href=\"#VkAccelerationStructureKHR\">VkAccelerationStructureKHR</a> handles"
+        },
+        {
+          "vuid": "VUID-vkWriteAccelerationStructuresPropertiesKHR-queryType-parameter",
+          "text": " <code>queryType</code> <strong class=\"purple\">must</strong> be a valid <a href=\"#VkQueryType\">VkQueryType</a> value"
+        },
+        {
+          "vuid": "VUID-vkWriteAccelerationStructuresPropertiesKHR-pData-parameter",
+          "text": " <code>pData</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>dataSize</code> bytes"
+        },
+        {
+          "vuid": "VUID-vkWriteAccelerationStructuresPropertiesKHR-accelerationStructureCount-arraylength",
+          "text": " <code>accelerationStructureCount</code> <strong class=\"purple\">must</strong> be greater than <code>0</code>"
+        },
+        {
+          "vuid": "VUID-vkWriteAccelerationStructuresPropertiesKHR-dataSize-arraylength",
+          "text": " <code>dataSize</code> <strong class=\"purple\">must</strong> be greater than <code>0</code>"
+        },
+        {
+          "vuid": "VUID-vkWriteAccelerationStructuresPropertiesKHR-pAccelerationStructures-parent",
+          "text": " Each element of <code>pAccelerationStructures</code> <strong class=\"purple\">must</strong> have been created, allocated, or retrieved from <code>device</code>"
+        }
+      ],
+      "core": [
+        {
+          "vuid": "VUID-vkWriteAccelerationStructuresPropertiesKHR-rayTracingHostAccelerationStructureCommands-03454",
+          "text": " the <a href=\"#feature-raytracing-hostascmds\"><code>VkPhysicalDeviceRayTracingFeaturesKHR</code>::<code>rayTracingHostAccelerationStructureCommands</code></a> feature <strong class=\"purple\">must</strong> be enabled"
+        }
+      ]
+    },
     "vkEnumerateInstanceLayerProperties": {
       "core": [
         {
@@ -24748,7 +27058,7 @@
       "(VK_VERSION_1_1,VK_KHR_variable_pointers)": [
         {
           "vuid": "VUID-VkPhysicalDeviceVariablePointersFeatures-variablePointers-01431",
-          "text": " If <code>variablePointers</code> is enabled then <code>variablePointersStorageBuffer</code> <strong class=\"purple\">must</strong> also be enabled."
+          "text": " If <code>variablePointers</code> is enabled then <code>variablePointersStorageBuffer</code> <strong class=\"purple\">must</strong> also be enabled"
         },
         {
           "vuid": "VUID-VkPhysicalDeviceVariablePointersFeatures-sType-sType",
@@ -24760,11 +27070,11 @@
       "(VK_VERSION_1_1,VK_KHR_multiview)": [
         {
           "vuid": "VUID-VkPhysicalDeviceMultiviewFeatures-multiviewGeometryShader-00580",
-          "text": " If <code>multiviewGeometryShader</code> is enabled then <code>multiview</code> <strong class=\"purple\">must</strong> also be enabled."
+          "text": " If <code>multiviewGeometryShader</code> is enabled then <code>multiview</code> <strong class=\"purple\">must</strong> also be enabled"
         },
         {
           "vuid": "VUID-VkPhysicalDeviceMultiviewFeatures-multiviewTessellationShader-00581",
-          "text": " If <code>multiviewTessellationShader</code> is enabled then <code>multiview</code> <strong class=\"purple\">must</strong> also be enabled."
+          "text": " If <code>multiviewTessellationShader</code> is enabled then <code>multiview</code> <strong class=\"purple\">must</strong> also be enabled"
         },
         {
           "vuid": "VUID-VkPhysicalDeviceMultiviewFeatures-sType-sType",
@@ -25180,6 +27490,42 @@
         }
       ]
     },
+    "VkPhysicalDeviceRayTracingFeaturesKHR": {
+      "(VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-VkPhysicalDeviceRayTracingFeaturesKHR-rayTracingShaderGroupHandleCaptureReplayMixed-03348",
+          "text": " If <code>rayTracingShaderGroupHandleCaptureReplayMixed</code> is <code>VK_TRUE</code>, <code>rayTracingShaderGroupHandleCaptureReplay</code> must also be <code>VK_TRUE</code>"
+        },
+        {
+          "vuid": "VUID-VkPhysicalDeviceRayTracingFeaturesKHR-sType-sType",
+          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_FEATURES_KHR</code>"
+        }
+      ]
+    },
+    "VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV": {
+      "(VK_NV_device_generated_commands)": [
+        {
+          "vuid": "VUID-VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV-sType-sType",
+          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_FEATURES_NV</code>"
+        }
+      ]
+    },
+    "VkPhysicalDeviceDiagnosticsConfigFeaturesNV": {
+      "(VK_NV_device_diagnostics_config)": [
+        {
+          "vuid": "VUID-VkPhysicalDeviceDiagnosticsConfigFeaturesNV-sType-sType",
+          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DIAGNOSTICS_CONFIG_FEATURES_NV</code>"
+        }
+      ]
+    },
+    "VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT": {
+      "(VK_EXT_pipeline_creation_cache_control)": [
+        {
+          "vuid": "VUID-VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT-sType-sType",
+          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES_EXT</code>"
+        }
+      ]
+    },
     "VkPhysicalDevicePushDescriptorPropertiesKHR": {
       "(VK_KHR_push_descriptor)": [
         {
@@ -25404,6 +27750,14 @@
         }
       ]
     },
+    "VkPhysicalDeviceRayTracingPropertiesKHR": {
+      "(VK_KHR_ray_tracing)": [
+        {
+          "vuid": "VUID-VkPhysicalDeviceRayTracingPropertiesKHR-sType-sType",
+          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_KHR</code>"
+        }
+      ]
+    },
     "VkPhysicalDeviceCooperativeMatrixPropertiesNV": {
       "(VK_NV_cooperative_matrix)": [
         {
@@ -25444,6 +27798,14 @@
         }
       ]
     },
+    "VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV": {
+      "(VK_NV_device_generated_commands)": [
+        {
+          "vuid": "VUID-VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV-sType-sType",
+          "text": " <code>sType</code> <strong class=\"purple\">must</strong> be <code>VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_PROPERTIES_NV</code>"
+        }
+      ]
+    },
     "vkGetPhysicalDeviceMultisamplePropertiesEXT": {
       "(VK_EXT_sample_locations)": [
         {
@@ -25532,7 +27894,7 @@
       "(VK_EXT_image_drm_format_modifier)": [
         {
           "vuid": "VUID-vkGetPhysicalDeviceImageFormatProperties-tiling-02248",
-          "text": " <code>tiling</code> <strong class=\"purple\">must</strong> not be <code>VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT</code>. (Use <a href=\"#vkGetPhysicalDeviceImageFormatProperties2\">vkGetPhysicalDeviceImageFormatProperties2</a> instead)."
+          "text": " <code>tiling</code> <strong class=\"purple\">must</strong> not be <code>VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT</code>. (Use <a href=\"#vkGetPhysicalDeviceImageFormatProperties2\">vkGetPhysicalDeviceImageFormatProperties2</a> instead)"
         }
       ],
       "core": [
@@ -25614,7 +27976,7 @@
       "(VK_VERSION_1_1,VK_KHR_get_physical_device_properties2)+(VK_ANDROID_external_memory_android_hardware_buffer)": [
         {
           "vuid": "VUID-vkGetPhysicalDeviceImageFormatProperties2-pNext-01868",
-          "text": " If the <code>pNext</code> chain of <code>pImageFormatProperties</code> includes a <a href=\"#VkAndroidHardwareBufferUsageANDROID\">VkAndroidHardwareBufferUsageANDROID</a> structure, the <code>pNext</code> chain of <code>pImageFormatInfo</code> <strong class=\"purple\">must</strong> include a <a href=\"#VkPhysicalDeviceExternalImageFormatInfo\">VkPhysicalDeviceExternalImageFormatInfo</a> structure with <code>handleType</code> set to <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID</code>."
+          "text": " If the <code>pNext</code> chain of <code>pImageFormatProperties</code> includes a <a href=\"#VkAndroidHardwareBufferUsageANDROID\">VkAndroidHardwareBufferUsageANDROID</a> structure, the <code>pNext</code> chain of <code>pImageFormatInfo</code> <strong class=\"purple\">must</strong> include a <a href=\"#VkPhysicalDeviceExternalImageFormatInfo\">VkPhysicalDeviceExternalImageFormatInfo</a> structure with <code>handleType</code> set to <code>VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID</code>"
         }
       ],
       "(VK_VERSION_1_1,VK_KHR_get_physical_device_properties2)": [
@@ -25636,11 +27998,11 @@
       "(VK_VERSION_1_1,VK_KHR_get_physical_device_properties2)+(VK_EXT_image_drm_format_modifier)": [
         {
           "vuid": "VUID-VkPhysicalDeviceImageFormatInfo2-tiling-02249",
-          "text": " <code>tiling</code> <strong class=\"purple\">must</strong> be <code>VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT</code> if and only if the <code>pNext</code> chain includes <a href=\"#VkPhysicalDeviceImageDrmFormatModifierInfoEXT\">VkPhysicalDeviceImageDrmFormatModifierInfoEXT</a>."
+          "text": " <code>tiling</code> <strong class=\"purple\">must</strong> be <code>VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT</code> if and only if the <code>pNext</code> chain includes <a href=\"#VkPhysicalDeviceImageDrmFormatModifierInfoEXT\">VkPhysicalDeviceImageDrmFormatModifierInfoEXT</a>"
         },
         {
           "vuid": "VUID-VkPhysicalDeviceImageFormatInfo2-tiling-02313",
-          "text": " If <code>tiling</code> is <code>VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT</code> and <code>flags</code> contains <code>VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT</code>, then the <code>pNext</code> chain <strong class=\"purple\">must</strong> include a <a href=\"#VkImageFormatListCreateInfo\">VkImageFormatListCreateInfo</a> structure with non-zero <code>viewFormatCount</code>."
+          "text": " If <code>tiling</code> is <code>VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT</code> and <code>flags</code> contains <code>VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT</code>, then the <code>pNext</code> chain <strong class=\"purple\">must</strong> include a <a href=\"#VkImageFormatListCreateInfo\">VkImageFormatListCreateInfo</a> structure with non-zero <code>viewFormatCount</code>"
         }
       ],
       "(VK_VERSION_1_1,VK_KHR_get_physical_device_properties2)": [
@@ -25730,15 +28092,15 @@
       "(VK_VERSION_1_1,VK_KHR_get_physical_device_properties2)+(VK_EXT_image_drm_format_modifier)": [
         {
           "vuid": "VUID-VkPhysicalDeviceImageDrmFormatModifierInfoEXT-sharingMode-02314",
-          "text": " If <code>sharingMode</code> is <code>VK_SHARING_MODE_CONCURRENT</code>, then <code>pQueueFamilyIndices</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>queueFamilyIndexCount</code> <code>uint32_t</code> values."
+          "text": " If <code>sharingMode</code> is <code>VK_SHARING_MODE_CONCURRENT</code>, then <code>pQueueFamilyIndices</code> <strong class=\"purple\">must</strong> be a valid pointer to an array of <code>queueFamilyIndexCount</code> <code>uint32_t</code> values"
         },
         {
           "vuid": "VUID-VkPhysicalDeviceImageDrmFormatModifierInfoEXT-sharingMode-02315",
-          "text": " If <code>sharingMode</code> is <code>VK_SHARING_MODE_CONCURRENT</code>, then <code>queueFamilyIndexCount</code> <strong class=\"purple\">must</strong> be greater than <code>1</code>."
+          "text": " If <code>sharingMode</code> is <code>VK_SHARING_MODE_CONCURRENT</code>, then <code>queueFamilyIndexCount</code> <strong class=\"purple\">must</strong> be greater than <code>1</code>"
         },
         {
           "vuid": "VUID-VkPhysicalDeviceImageDrmFormatModifierInfoEXT-sharingMode-02316",
-          "text": " If <code>sharingMode</code> is <code>VK_SHARING_MODE_CONCURRENT</code>, each element of <code>pQueueFamilyIndices</code> <strong class=\"purple\">must</strong> be unique and <strong class=\"purple\">must</strong> be less than the <code>pQueueFamilyPropertyCount</code> returned by <a href=\"#vkGetPhysicalDeviceQueueFamilyProperties2\">vkGetPhysicalDeviceQueueFamilyProperties2</a> for the <code>physicalDevice</code> that was used to create <code>device</code>."
+          "text": " If <code>sharingMode</code> is <code>VK_SHARING_MODE_CONCURRENT</code>, each element of <code>pQueueFamilyIndices</code> <strong class=\"purple\">must</strong> be unique and <strong class=\"purple\">must</strong> be less than the <code>pQueueFamilyPropertyCount</code> returned by <a href=\"#vkGetPhysicalDeviceQueueFamilyProperties2\">vkGetPhysicalDeviceQueueFamilyProperties2</a> for the <code>physicalDevice</code> that was used to create <code>device</code>"
         },
         {
           "vuid": "VUID-VkPhysicalDeviceImageDrmFormatModifierInfoEXT-sType-sType",
@@ -25786,7 +28148,7 @@
         },
         {
           "vuid": "VUID-VkFilterCubicImageViewImageFormatPropertiesEXT-pNext-02627",
-          "text": " If the <code>pNext</code> chain of the <a href=\"#VkImageFormatProperties2\">VkImageFormatProperties2</a> structure includes a <a href=\"#VkFilterCubicImageViewImageFormatPropertiesEXT\">VkFilterCubicImageViewImageFormatPropertiesEXT</a> structure, the <code>pNext</code> chain of the <a href=\"#VkPhysicalDeviceImageFormatInfo2\">VkPhysicalDeviceImageFormatInfo2</a> structure <strong class=\"purple\">must</strong> include a <a href=\"#VkPhysicalDeviceImageViewImageFormatInfoEXT\">VkPhysicalDeviceImageViewImageFormatInfoEXT</a> structure with an <code>imageViewType</code> that is compatible with <code>imageType</code>."
+          "text": " If the <code>pNext</code> chain of the <a href=\"#VkImageFormatProperties2\">VkImageFormatProperties2</a> structure includes a <a href=\"#VkFilterCubicImageViewImageFormatPropertiesEXT\">VkFilterCubicImageViewImageFormatPropertiesEXT</a> structure, the <code>pNext</code> chain of the <a href=\"#VkPhysicalDeviceImageFormatInfo2\">VkPhysicalDeviceImageFormatInfo2</a> structure <strong class=\"purple\">must</strong> include a <a href=\"#VkPhysicalDeviceImageViewImageFormatInfoEXT\">VkPhysicalDeviceImageViewImageFormatInfoEXT</a> structure with an <code>imageViewType</code> that is compatible with <code>imageType</code>"
         }
       ]
     },
@@ -25998,7 +28360,7 @@
         },
         {
           "vuid": "VUID-VkDebugUtilsObjectNameInfoEXT-pObjectName-parameter",
-          "text": " <code>pObjectName</code> <strong class=\"purple\">must</strong> be a null-terminated UTF-8 string"
+          "text": " If <code>pObjectName</code> is not <code>NULL</code>, <code>pObjectName</code> <strong class=\"purple\">must</strong> be a null-terminated UTF-8 string"
         }
       ]
     },
@@ -26126,7 +28488,7 @@
         },
         {
           "vuid": "VUID-vkCmdEndDebugUtilsLabelEXT-commandBuffer-01913",
-          "text": " If <code>commandBuffer</code> is a secondary command buffer, there <strong class=\"purple\">must</strong> be an outstanding <code>vkCmdBeginDebugUtilsLabelEXT</code> command recorded to <code>commandBuffer</code> that has not previously been ended by a call to <code>vkCmdEndDebugUtilsLabelEXT</code>."
+          "text": " If <code>commandBuffer</code> is a secondary command buffer, there <strong class=\"purple\">must</strong> be an outstanding <code>vkCmdBeginDebugUtilsLabelEXT</code> command recorded to <code>commandBuffer</code> that has not previously been ended by a call to <code>vkCmdEndDebugUtilsLabelEXT</code>"
         },
         {
           "vuid": "VUID-vkCmdEndDebugUtilsLabelEXT-commandBuffer-parameter",
@@ -26334,7 +28696,7 @@
         },
         {
           "vuid": "VUID-VkDebugMarkerObjectNameInfoEXT-object-01492",
-          "text": " <code>object</code> <strong class=\"purple\">must</strong> be a Vulkan object of the type associated with <code>objectType</code> as defined in <a href=\"#debug-report-object-types\">VkDebugReportObjectTypeEXT and Vulkan Handle Relationship</a>."
+          "text": " <code>object</code> <strong class=\"purple\">must</strong> be a Vulkan object of the type associated with <code>objectType</code> as defined in <a href=\"#debug-report-object-types\"><a href=\"#VkDebugReportObjectTypeEXT\">VkDebugReportObjectTypeEXT</a> and Vulkan Handle Relationship</a>"
         },
         {
           "vuid": "VUID-VkDebugMarkerObjectNameInfoEXT-sType-sType",
@@ -26378,7 +28740,7 @@
         },
         {
           "vuid": "VUID-VkDebugMarkerObjectTagInfoEXT-object-01495",
-          "text": " <code>object</code> <strong class=\"purple\">must</strong> be a Vulkan object of the type associated with <code>objectType</code> as defined in <a href=\"#debug-report-object-types\">VkDebugReportObjectTypeEXT and Vulkan Handle Relationship</a>."
+          "text": " <code>object</code> <strong class=\"purple\">must</strong> be a Vulkan object of the type associated with <code>objectType</code> as defined in <a href=\"#debug-report-object-types\"><a href=\"#VkDebugReportObjectTypeEXT\">VkDebugReportObjectTypeEXT</a> and Vulkan Handle Relationship</a>"
         },
         {
           "vuid": "VUID-VkDebugMarkerObjectTagInfoEXT-sType-sType",
@@ -26446,7 +28808,7 @@
         },
         {
           "vuid": "VUID-vkCmdDebugMarkerEndEXT-commandBuffer-01240",
-          "text": " If <code>commandBuffer</code> is a secondary command buffer, there <strong class=\"purple\">must</strong> be an outstanding <a href=\"#vkCmdDebugMarkerBeginEXT\">vkCmdDebugMarkerBeginEXT</a> command recorded to <code>commandBuffer</code> that has not previously been ended by a call to <a href=\"#vkCmdDebugMarkerEndEXT\">vkCmdDebugMarkerEndEXT</a>."
+          "text": " If <code>commandBuffer</code> is a secondary command buffer, there <strong class=\"purple\">must</strong> be an outstanding <a href=\"#vkCmdDebugMarkerBeginEXT\">vkCmdDebugMarkerBeginEXT</a> command recorded to <code>commandBuffer</code> that has not previously been ended by a call to <a href=\"#vkCmdDebugMarkerEndEXT\">vkCmdDebugMarkerEndEXT</a>"
         },
         {
           "vuid": "VUID-vkCmdDebugMarkerEndEXT-commandBuffer-parameter",
@@ -26526,7 +28888,7 @@
         },
         {
           "vuid": "VUID-vkDebugReportMessageEXT-objectType-01498",
-          "text": " If <code>objectType</code> is not <code>VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT</code> and <code>object</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, <code>object</code> <strong class=\"purple\">must</strong> be a Vulkan object of the corresponding type associated with <code>objectType</code> as defined in <a href=\"#debug-report-object-types\">VkDebugReportObjectTypeEXT and Vulkan Handle Relationship</a>."
+          "text": " If <code>objectType</code> is not <code>VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT</code> and <code>object</code> is not <a href=\"#VK_NULL_HANDLE\">VK_NULL_HANDLE</a>, <code>object</code> <strong class=\"purple\">must</strong> be a Vulkan object of the corresponding type associated with <code>objectType</code> as defined in <a href=\"#debug-report-object-types\"><a href=\"#VkDebugReportObjectTypeEXT\">VkDebugReportObjectTypeEXT</a> and Vulkan Handle Relationship</a>"
         },
         {
           "vuid": "VUID-vkDebugReportMessageEXT-instance-parameter",
diff --git a/third_party/vulkan-headers/src/registry/vk.xml b/third_party/vulkan-headers/src/registry/vk.xml
index b7f8e45..7a04c93 100644
--- a/third_party/vulkan-headers/src/registry/vk.xml
+++ b/third_party/vulkan-headers/src/registry/vk.xml
@@ -57,6 +57,7 @@
         <platform name="metal" protect="VK_USE_PLATFORM_METAL_EXT" comment="Metal on CoreAnimation on Apple platforms"/>
         <platform name="fuchsia" protect="VK_USE_PLATFORM_FUCHSIA" comment="Fuchsia"/>
         <platform name="ggp" protect="VK_USE_PLATFORM_GGP" comment="Google Games Platform"/>
+        <platform name="provisional" protect="VK_ENABLE_BETA_EXTENSIONS" comment="Enable declarations for beta/provisional extensions"/>
     </platforms>
 
     <tags comment="Vulkan vendor/author tags for extensions and layers">
@@ -156,7 +157,7 @@
         <type category="define">// Vulkan 1.2 version number
 #define <name>VK_API_VERSION_1_2</name> <type>VK_MAKE_VERSION</type>(1, 2, 0)// Patch version should always be set to 0</type>
         <type category="define">// Version of this file
-#define <name>VK_HEADER_VERSION</name> 134</type>
+#define <name>VK_HEADER_VERSION</name> 137</type>
         <type category="define" requires="VK_HEADER_VERSION">// Complete version of this file
 #define <name>VK_HEADER_VERSION_COMPLETE</name> <type>VK_MAKE_VERSION</type>(1, 2, VK_HEADER_VERSION)</type>
 
@@ -210,7 +211,7 @@
         <type requires="VkRenderPassCreateFlagBits"       category="bitmask">typedef <type>VkFlags</type> <name>VkRenderPassCreateFlags</name>;</type>
         <type requires="VkSamplerCreateFlagBits"          category="bitmask">typedef <type>VkFlags</type> <name>VkSamplerCreateFlags</name>;</type>
         <type                                             category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineLayoutCreateFlags</name>;</type>
-        <type                                             category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineCacheCreateFlags</name>;</type>
+        <type requires="VkPipelineCacheCreateFlagBits"    category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineCacheCreateFlags</name>;</type>
         <type                                             category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineDepthStencilStateCreateFlags</name>;</type>
         <type                                             category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineDynamicStateCreateFlags</name>;</type>
         <type                                             category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineColorBlendStateCreateFlags</name>;</type>
@@ -264,12 +265,14 @@
         <type                                             category="bitmask">typedef <type>VkFlags</type> <name>VkDescriptorPoolResetFlags</name>;</type>
         <type requires="VkDependencyFlagBits"             category="bitmask">typedef <type>VkFlags</type> <name>VkDependencyFlags</name>;</type>
         <type requires="VkSubgroupFeatureFlagBits"        category="bitmask">typedef <type>VkFlags</type> <name>VkSubgroupFeatureFlags</name>;</type>
-        <type requires="VkIndirectCommandsLayoutUsageFlagBitsNVX"  category="bitmask">typedef <type>VkFlags</type> <name>VkIndirectCommandsLayoutUsageFlagsNVX</name>;</type>
-        <type requires="VkObjectEntryUsageFlagBitsNVX"             category="bitmask">typedef <type>VkFlags</type> <name>VkObjectEntryUsageFlagsNVX</name>;</type>
-        <type requires="VkGeometryFlagBitsNV"            category="bitmask">typedef <type>VkFlags</type> <name>VkGeometryFlagsNV</name>;</type>
-        <type requires="VkGeometryInstanceFlagBitsNV"    category="bitmask">typedef <type>VkFlags</type> <name>VkGeometryInstanceFlagsNV</name>;</type>
-        <type requires="VkBuildAccelerationStructureFlagBitsNV" category="bitmask">typedef <type>VkFlags</type> <name>VkBuildAccelerationStructureFlagsNV</name>;</type>
-
+        <type requires="VkIndirectCommandsLayoutUsageFlagBitsNV"   category="bitmask">typedef <type>VkFlags</type> <name>VkIndirectCommandsLayoutUsageFlagsNV</name>;</type>
+        <type requires="VkIndirectStateFlagBitsNV"                 category="bitmask">typedef <type>VkFlags</type> <name>VkIndirectStateFlagsNV</name>;</type>
+        <type requires="VkGeometryFlagBitsKHR"           category="bitmask">typedef <type>VkFlags</type> <name>VkGeometryFlagsKHR</name>;</type>
+        <type                                            category="bitmask" name="VkGeometryFlagsNV" alias="VkGeometryFlagsKHR"/>
+        <type requires="VkGeometryInstanceFlagBitsKHR"   category="bitmask">typedef <type>VkFlags</type> <name>VkGeometryInstanceFlagsKHR</name>;</type>
+        <type                                            category="bitmask" name="VkGeometryInstanceFlagsNV" alias="VkGeometryInstanceFlagsKHR"/>
+        <type requires="VkBuildAccelerationStructureFlagBitsKHR" category="bitmask">typedef <type>VkFlags</type> <name>VkBuildAccelerationStructureFlagsKHR</name>;</type>
+        <type                                            category="bitmask" name="VkBuildAccelerationStructureFlagsNV" alias="VkBuildAccelerationStructureFlagsKHR"/>
         <type                                             category="bitmask">typedef <type>VkFlags</type> <name>VkDescriptorUpdateTemplateCreateFlags</name>;</type>
         <type                                             category="bitmask" name="VkDescriptorUpdateTemplateCreateFlagsKHR" alias="VkDescriptorUpdateTemplateCreateFlags"/>
         <type requires="VkPipelineCreationFeedbackFlagBitsEXT" category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineCreationFeedbackFlagsEXT</name>;</type>
@@ -279,6 +282,7 @@
         <type                                             category="bitmask" name="VkSemaphoreWaitFlagsKHR" alias="VkSemaphoreWaitFlags"/>
         <type requires="VkPipelineCompilerControlFlagBitsAMD" category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineCompilerControlFlagsAMD</name>;</type>
         <type requires="VkShaderCorePropertiesFlagBitsAMD" category="bitmask">typedef <type>VkFlags</type> <name>VkShaderCorePropertiesFlagsAMD</name>;</type>
+        <type requires="VkDeviceDiagnosticsConfigFlagBitsNV" category="bitmask">typedef <type>VkFlags</type> <name>VkDeviceDiagnosticsConfigFlagsNV</name>;</type>
 
             <comment>WSI extensions</comment>
         <type requires="VkCompositeAlphaFlagBitsKHR"      category="bitmask">typedef <type>VkFlags</type> <name>VkCompositeAlphaFlagsKHR</name>;</type>
@@ -374,15 +378,16 @@
         <type category="handle" parent="VkDevice"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkFramebuffer</name>)</type>
         <type category="handle" parent="VkDevice"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkRenderPass</name>)</type>
         <type category="handle" parent="VkDevice"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkPipelineCache</name>)</type>
-        <type category="handle" parent="VkDevice"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkObjectTableNVX</name>)</type>
-        <type category="handle" parent="VkDevice"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkIndirectCommandsLayoutNVX</name>)</type>
+        <type category="handle" parent="VkDevice"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkIndirectCommandsLayoutNV</name>)</type>
         <type category="handle" parent="VkDevice"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkDescriptorUpdateTemplate</name>)</type>
         <type category="handle" name="VkDescriptorUpdateTemplateKHR" alias="VkDescriptorUpdateTemplate"/>
         <type category="handle" parent="VkDevice"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkSamplerYcbcrConversion</name>)</type>
         <type category="handle" name="VkSamplerYcbcrConversionKHR"   alias="VkSamplerYcbcrConversion"/>
         <type category="handle" parent="VkDevice"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkValidationCacheEXT</name>)</type>
-        <type category="handle" parent="VkDevice"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkAccelerationStructureNV</name>)</type>
+        <type category="handle" parent="VkDevice"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkAccelerationStructureKHR</name>)</type>
+        <type category="handle" name="VkAccelerationStructureNV"     alias="VkAccelerationStructureKHR"/>
         <type category="handle" parent="VkDevice"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkPerformanceConfigurationINTEL</name>)</type>
+        <type category="handle" parent="VkDevice"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkDeferredOperationKHR</name>)</type>
 
             <comment>WSI extensions</comment>
         <type category="handle" parent="VkPhysicalDevice"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkDisplayKHR</name>)</type>
@@ -483,10 +488,9 @@
         <type name="VkObjectType" category="enum"/>
 
         <comment>Extensions</comment>
-        <type name="VkIndirectCommandsLayoutUsageFlagBitsNVX" category="enum"/>
-        <type name="VkIndirectCommandsTokenTypeNVX" category="enum"/>
-        <type name="VkObjectEntryUsageFlagBitsNVX" category="enum"/>
-        <type name="VkObjectEntryTypeNVX" category="enum"/>
+        <type name="VkIndirectCommandsLayoutUsageFlagBitsNV" category="enum"/>
+        <type name="VkIndirectCommandsTokenTypeNV" category="enum"/>
+        <type name="VkIndirectStateFlagBitsNV" category="enum"/>
         <type name="VkDescriptorUpdateTemplateType" category="enum"/>
         <type category="enum" name="VkDescriptorUpdateTemplateTypeKHR"             alias="VkDescriptorUpdateTemplateType"/>
         <type name="VkViewportCoordinateSwizzleNV" category="enum"/>
@@ -508,17 +512,27 @@
         <type name="VkConditionalRenderingFlagBitsEXT" category="enum"/>
         <type name="VkSemaphoreType" category="enum"/>
         <type category="enum" name="VkSemaphoreTypeKHR"                            alias="VkSemaphoreType"/>
-        <type name="VkGeometryFlagBitsNV" category="enum"/>
-        <type name="VkGeometryInstanceFlagBitsNV" category="enum"/>
-        <type name="VkBuildAccelerationStructureFlagBitsNV" category="enum"/>
-        <type name="VkCopyAccelerationStructureModeNV" category="enum"/>
-        <type name="VkAccelerationStructureTypeNV" category="enum"/>
-        <type name="VkGeometryTypeNV" category="enum"/>
-        <type name="VkRayTracingShaderGroupTypeNV" category="enum"/>
-        <type name="VkAccelerationStructureMemoryRequirementsTypeNV" category="enum"/>
+        <type name="VkGeometryFlagBitsKHR" category="enum"/>
+        <type category="enum" name="VkGeometryFlagBitsNV"                           alias="VkGeometryFlagBitsKHR"/>
+        <type name="VkGeometryInstanceFlagBitsKHR" category="enum"/>
+        <type category="enum" name="VkGeometryInstanceFlagBitsNV"                   alias="VkGeometryInstanceFlagBitsKHR"/>
+        <type name="VkBuildAccelerationStructureFlagBitsKHR" category="enum"/>
+        <type category="enum" name="VkBuildAccelerationStructureFlagBitsNV"         alias="VkBuildAccelerationStructureFlagBitsKHR"/>
+        <type name="VkCopyAccelerationStructureModeKHR" category="enum"/>
+        <type category="enum" name="VkCopyAccelerationStructureModeNV" alias="VkCopyAccelerationStructureModeKHR"/>
+        <type name="VkAccelerationStructureTypeKHR" category="enum"/>
+        <type category="enum" name="VkAccelerationStructureTypeNV"                  alias="VkAccelerationStructureTypeKHR"/>
+        <type name="VkGeometryTypeKHR" category="enum"/>
+        <type category="enum" name="VkGeometryTypeNV"                               alias="VkGeometryTypeKHR"/>
+        <type name="VkRayTracingShaderGroupTypeKHR" category="enum"/>
+        <type category="enum" name="VkRayTracingShaderGroupTypeNV"                  alias="VkRayTracingShaderGroupTypeKHR"/>
+        <type name="VkAccelerationStructureMemoryRequirementsTypeKHR" category="enum"/>
+        <type category="enum" name="VkAccelerationStructureMemoryRequirementsTypeNV" alias="VkAccelerationStructureMemoryRequirementsTypeKHR"/>
+        <type name="VkAccelerationStructureBuildTypeKHR" category="enum"/>
         <type name="VkMemoryOverallocationBehaviorAMD" category="enum"/>
         <type name="VkScopeNV" category="enum"/>
         <type name="VkComponentTypeNV" category="enum"/>
+        <type name="VkDeviceDiagnosticsConfigFlagBitsNV" category="enum"/>
         <type name="VkPipelineCreationFeedbackFlagBitsEXT" category="enum"/>
         <type name="VkPerformanceCounterScopeKHR" category="enum"/>
         <type name="VkPerformanceCounterUnitKHR" category="enum"/>
@@ -1561,7 +1575,7 @@
             <member optional="true"><type>VkSampleCountFlags</type>     <name>framebufferColorSampleCounts</name><comment>supported color sample counts for a framebuffer</comment></member>
             <member optional="true"><type>VkSampleCountFlags</type>     <name>framebufferDepthSampleCounts</name><comment>supported depth sample counts for a framebuffer</comment></member>
             <member optional="true"><type>VkSampleCountFlags</type>     <name>framebufferStencilSampleCounts</name><comment>supported stencil sample counts for a framebuffer</comment></member>
-            <member optional="true"><type>VkSampleCountFlags</type>     <name>framebufferNoAttachmentsSampleCounts</name><comment>supported sample counts for a framebuffer with no attachments</comment></member>
+            <member optional="true"><type>VkSampleCountFlags</type>     <name>framebufferNoAttachmentsSampleCounts</name><comment>supported sample counts for a subpass which uses no attachments</comment></member>
             <member><type>uint32_t</type>               <name>maxColorAttachments</name><comment>max number of color attachments per subpass</comment></member>
             <member optional="true"><type>VkSampleCountFlags</type>     <name>sampledImageColorSampleCounts</name><comment>supported color sample counts for a non-integer sampled image</comment></member>
             <member optional="true"><type>VkSampleCountFlags</type>     <name>sampledImageIntegerSampleCounts</name><comment>supported sample counts for an integer image</comment></member>
@@ -1897,105 +1911,111 @@
             <member len="releaseCount">const <type>VkDeviceMemory</type>*            <name>pReleaseSyncs</name></member>
             <member len="releaseCount">const <type>uint64_t</type>*                  <name>pReleaseKeys</name></member>
         </type>
-        <type category="struct" name="VkDeviceGeneratedCommandsFeaturesNVX">
-            <member values="VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_FEATURES_NVX"><type>VkStructureType</type> <name>sType</name></member>
-            <member>const <type>void</type>*                      <name>pNext</name></member>
-            <member><type>VkBool32</type>                         <name>computeBindingPointSupport</name></member>
+        <type category="struct" name="VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+            <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_FEATURES_NV"><type>VkStructureType</type><name>sType</name></member>
+            <member noautovalidity="true"><type>void</type>*    <name>pNext</name></member>
+            <member><type>VkBool32</type>                       <name>deviceGeneratedCommands</name></member>
         </type>
-        <type category="struct" name="VkDeviceGeneratedCommandsLimitsNVX">
-            <member values="VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_LIMITS_NVX"><type>VkStructureType</type> <name>sType</name></member>
-            <member>const <type>void</type>*                      <name>pNext</name></member>
-            <member><type>uint32_t</type>                         <name>maxIndirectCommandsLayoutTokenCount</name></member>
-            <member><type>uint32_t</type>                         <name>maxObjectEntryCounts</name></member>
-            <member><type>uint32_t</type>                         <name>minSequenceCountBufferOffsetAlignment</name></member>
-            <member><type>uint32_t</type>                         <name>minSequenceIndexBufferOffsetAlignment</name></member>
-            <member><type>uint32_t</type>                         <name>minCommandsTokenBufferOffsetAlignment</name></member>
+        <type category="struct" name="VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV" structextends="VkPhysicalDeviceProperties2" returnedonly="true">
+            <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_PROPERTIES_NV"><type>VkStructureType</type> <name>sType</name></member>
+            <member noautovalidity="true"><type>void</type>*    <name>pNext</name></member>
+            <member><type>uint32_t</type>         <name>maxGraphicsShaderGroupCount</name></member>
+            <member><type>uint32_t</type>         <name>maxIndirectSequenceCount</name></member>
+            <member><type>uint32_t</type>         <name>maxIndirectCommandsTokenCount</name></member>
+            <member><type>uint32_t</type>         <name>maxIndirectCommandsStreamCount</name></member>
+            <member><type>uint32_t</type>         <name>maxIndirectCommandsTokenOffset</name></member>
+            <member><type>uint32_t</type>         <name>maxIndirectCommandsStreamStride</name></member>
+            <member><type>uint32_t</type>         <name>minSequencesCountBufferOffsetAlignment</name></member>
+            <member><type>uint32_t</type>         <name>minSequencesIndexBufferOffsetAlignment</name></member>
+            <member><type>uint32_t</type>         <name>minIndirectCommandsBufferOffsetAlignment</name></member>
         </type>
-        <type category="struct" name="VkIndirectCommandsTokenNVX">
-            <member><type>VkIndirectCommandsTokenTypeNVX</type>      <name>tokenType</name></member>
-            <member><type>VkBuffer</type>                         <name>buffer</name><comment>buffer containing tableEntries and additional data for indirectCommands</comment></member>
-            <member><type>VkDeviceSize</type>                     <name>offset</name><comment>offset from the base address of the buffer</comment></member>
+        <type category="struct" name="VkGraphicsShaderGroupCreateInfoNV">
+            <member values="VK_STRUCTURE_TYPE_GRAPHICS_SHADER_GROUP_CREATE_INFO_NV"><type>VkStructureType</type> <name>sType</name></member>
+            <member>const <type>void</type>*                                                <name>pNext</name></member>
+            <member><type>uint32_t</type>                                                   <name>stageCount</name></member>
+            <member len="stageCount">const <type>VkPipelineShaderStageCreateInfo</type>*    <name>pStages</name></member>
+            <member noautovalidity="true" optional="true">const <type>VkPipelineVertexInputStateCreateInfo</type>*                <name>pVertexInputState</name></member>
+            <member noautovalidity="true" optional="true">const <type>VkPipelineTessellationStateCreateInfo</type>*               <name>pTessellationState</name></member>
         </type>
-        <type category="struct" name="VkIndirectCommandsLayoutTokenNVX">
-            <member><type>VkIndirectCommandsTokenTypeNVX</type>      <name>tokenType</name></member>
-            <member><type>uint32_t</type>                         <name>bindingUnit</name><comment>Binding unit for vertex attribute / descriptor set, offset for pushconstants</comment></member>
-            <member><type>uint32_t</type>                         <name>dynamicCount</name><comment>Number of variable dynamic values for descriptor set / push constants</comment></member>
-            <member><type>uint32_t</type>                         <name>divisor</name><comment>Rate the which the array is advanced per element (must be power of 2, minimum 1)</comment></member>
+        <type category="struct" name="VkGraphicsPipelineShaderGroupsCreateInfoNV" structextends="VkGraphicsPipelineCreateInfo">
+            <member values="VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_SHADER_GROUPS_CREATE_INFO_NV"><type>VkStructureType</type> <name>sType</name></member>
+            <member>const <type>void</type>*                                                <name>pNext</name></member>
+            <member><type>uint32_t</type>                                                   <name>groupCount</name></member>
+            <member len="groupCount">const <type>VkGraphicsShaderGroupCreateInfoNV</type>*  <name>pGroups</name></member>
+            <member optional="true"><type>uint32_t</type>                                   <name>pipelineCount</name></member>
+            <member len="pipelineCount">const <type>VkPipeline</type>*                      <name>pPipelines</name></member>
         </type>
-        <type category="struct" name="VkIndirectCommandsLayoutCreateInfoNVX">
-            <member values="VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NVX"><type>VkStructureType</type> <name>sType</name></member>
-            <member>const <type>void</type>*                      <name>pNext</name></member>
-            <member><type>VkPipelineBindPoint</type>                      <name>pipelineBindPoint</name></member>
-            <member><type>VkIndirectCommandsLayoutUsageFlagsNVX</type>    <name>flags</name></member>
-            <member><type>uint32_t</type>                                 <name>tokenCount</name></member>
-            <member len="tokenCount">const <type>VkIndirectCommandsLayoutTokenNVX</type>*  <name>pTokens</name></member>
+        <type category="struct" name="VkBindShaderGroupIndirectCommandNV">
+            <member><type>uint32_t</type>         <name>groupIndex</name></member>
         </type>
-        <type category="struct" name="VkCmdProcessCommandsInfoNVX">
-            <member values="VK_STRUCTURE_TYPE_CMD_PROCESS_COMMANDS_INFO_NVX"><type>VkStructureType</type> <name>sType</name></member>
-            <member>const <type>void</type>*                      <name>pNext</name></member>
-            <member externsync="true"><type>VkObjectTableNVX</type>                                         <name>objectTable</name></member>
-            <member><type>VkIndirectCommandsLayoutNVX</type>                              <name>indirectCommandsLayout</name></member>
-            <member><type>uint32_t</type>                                                 <name>indirectCommandsTokenCount</name></member>
-            <member len="indirectCommandsTokenCount">const <type>VkIndirectCommandsTokenNVX</type>*       <name>pIndirectCommandsTokens</name></member>
-            <member><type>uint32_t</type>                                                 <name>maxSequencesCount</name></member>
-            <member optional="true" externsync="true"><type>VkCommandBuffer</type>                          <name>targetCommandBuffer</name></member>
-            <member optional="true"><type>VkBuffer</type>                                 <name>sequencesCountBuffer</name></member>
-            <member optional="true"><type>VkDeviceSize</type>                             <name>sequencesCountOffset</name></member>
-            <member optional="true"><type>VkBuffer</type>                                 <name>sequencesIndexBuffer</name></member>
-            <member optional="true"><type>VkDeviceSize</type>                             <name>sequencesIndexOffset</name></member>
+        <type category="struct" name="VkBindIndexBufferIndirectCommandNV">
+            <member><type>VkDeviceAddress</type>  <name>bufferAddress</name></member>
+            <member><type>uint32_t</type>         <name>size</name></member>
+            <member><type>VkIndexType</type>      <name>indexType</name></member>
         </type>
-        <type category="struct" name="VkCmdReserveSpaceForCommandsInfoNVX">
-            <member values="VK_STRUCTURE_TYPE_CMD_RESERVE_SPACE_FOR_COMMANDS_INFO_NVX"><type>VkStructureType</type> <name>sType</name></member>
-            <member>const <type>void</type>*                      <name>pNext</name></member>
-            <member externsync="true"><type>VkObjectTableNVX</type>                                         <name>objectTable</name></member>
-            <member><type>VkIndirectCommandsLayoutNVX</type>                              <name>indirectCommandsLayout</name></member>
-            <member><type>uint32_t</type>                                                 <name>maxSequencesCount</name></member>
+        <type category="struct" name="VkBindVertexBufferIndirectCommandNV">
+            <member><type>VkDeviceAddress</type>  <name>bufferAddress</name></member>
+            <member><type>uint32_t</type>         <name>size</name></member>
+            <member><type>uint32_t</type>         <name>stride</name></member>
         </type>
-        <type category="struct" name="VkObjectTableCreateInfoNVX">
-            <member values="VK_STRUCTURE_TYPE_OBJECT_TABLE_CREATE_INFO_NVX"><type>VkStructureType</type> <name>sType</name></member>
-            <member>const <type>void</type>*                      <name>pNext</name></member>
-            <member><type>uint32_t</type>                                          <name>objectCount</name></member>
-            <member len="objectCount">const <type>VkObjectEntryTypeNVX</type>*       <name>pObjectEntryTypes</name></member>
-            <member len="objectCount">const <type>uint32_t</type>*                   <name>pObjectEntryCounts</name></member>
-            <member len="objectCount">const <type>VkObjectEntryUsageFlagsNVX</type>* <name>pObjectEntryUsageFlags</name></member>
-
-            <member><type>uint32_t</type> <name>maxUniformBuffersPerDescriptor</name></member>
-            <member><type>uint32_t</type> <name>maxStorageBuffersPerDescriptor</name></member>
-            <member><type>uint32_t</type> <name>maxStorageImagesPerDescriptor</name></member>
-            <member><type>uint32_t</type> <name>maxSampledImagesPerDescriptor</name></member>
-            <member><type>uint32_t</type> <name>maxPipelineLayouts</name></member>
+        <type category="struct" name="VkSetStateFlagsIndirectCommandNV">
+            <member><type>uint32_t</type>          <name>data</name></member>
         </type>
-        <type category="struct" name="VkObjectTableEntryNVX">
-            <member><type>VkObjectEntryTypeNVX</type>         <name>type</name></member>
-            <member><type>VkObjectEntryUsageFlagsNVX</type>   <name>flags</name></member>
+        <type category="struct" name="VkIndirectCommandsStreamNV">
+            <member><type>VkBuffer</type>      <name>buffer</name></member>
+            <member><type>VkDeviceSize</type>  <name>offset</name></member>
         </type>
-        <type category="struct" name="VkObjectTablePipelineEntryNVX">
-            <member><type>VkObjectEntryTypeNVX</type>         <name>type</name></member>
-            <member><type>VkObjectEntryUsageFlagsNVX</type>   <name>flags</name></member>
-            <member><type>VkPipeline</type>                   <name>pipeline</name></member>
+        <type category="struct" name="VkIndirectCommandsLayoutTokenNV">
+            <member values="VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_TOKEN_NV"><type>VkStructureType</type> <name>sType</name></member>
+            <member>const <type>void</type>*                    <name>pNext</name></member>
+            <member><type>VkIndirectCommandsTokenTypeNV</type>  <name>tokenType</name></member>
+            <member><type>uint32_t</type>                       <name>stream</name></member>
+            <member><type>uint32_t</type>                       <name>offset</name></member>
+            <member><type>uint32_t</type>                                <name>vertexBindingUnit</name></member>
+            <member><type>VkBool32</type>                                <name>vertexDynamicStride</name></member>
+            <member optional="true"><type>VkPipelineLayout</type>        <name>pushconstantPipelineLayout</name></member>
+            <member optional="true"><type>VkShaderStageFlags</type>      <name>pushconstantShaderStageFlags</name></member>
+            <member><type>uint32_t</type>                                <name>pushconstantOffset</name></member>
+            <member><type>uint32_t</type>                                <name>pushconstantSize</name></member>
+            <member optional="true"><type>VkIndirectStateFlagsNV</type>  <name>indirectStateFlags</name></member>
+            <member optional="true"><type>uint32_t</type>                <name>indexTypeCount</name></member>
+            <member len="indexTypeCount">const <type>VkIndexType</type>* <name>pIndexTypes</name></member>
+            <member len="indexTypeCount">const <type>uint32_t</type>*    <name>pIndexTypeValues</name></member>
         </type>
-        <type category="struct" name="VkObjectTableDescriptorSetEntryNVX">
-            <member><type>VkObjectEntryTypeNVX</type>         <name>type</name></member>
-            <member><type>VkObjectEntryUsageFlagsNVX</type>   <name>flags</name></member>
-            <member><type>VkPipelineLayout</type>             <name>pipelineLayout</name></member>
-            <member><type>VkDescriptorSet</type>              <name>descriptorSet</name></member>
+        <type category="struct" name="VkIndirectCommandsLayoutCreateInfoNV">
+            <member values="VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NV"><type>VkStructureType</type> <name>sType</name></member>
+            <member>const <type>void</type>*                             <name>pNext</name></member>
+            <member><type>VkIndirectCommandsLayoutUsageFlagsNV</type>    <name>flags</name></member>
+            <member><type>VkPipelineBindPoint</type>                     <name>pipelineBindPoint</name></member>
+            <member><type>uint32_t</type>                                <name>tokenCount</name></member>
+            <member len="tokenCount">const <type>VkIndirectCommandsLayoutTokenNV</type>*  <name>pTokens</name></member>
+            <member><type>uint32_t</type>                                <name>streamCount</name></member>
+            <member len="streamCount">const <type>uint32_t</type>*       <name>pStreamStrides</name></member>
         </type>
-        <type category="struct" name="VkObjectTableVertexBufferEntryNVX">
-            <member><type>VkObjectEntryTypeNVX</type>         <name>type</name></member>
-            <member><type>VkObjectEntryUsageFlagsNVX</type>   <name>flags</name></member>
-            <member><type>VkBuffer</type>                     <name>buffer</name></member>
+        <type category="struct" name="VkGeneratedCommandsInfoNV">
+            <member values="VK_STRUCTURE_TYPE_GENERATED_COMMANDS_INFO_NV"><type>VkStructureType</type> <name>sType</name></member>
+            <member>const <type>void</type>*                        <name>pNext</name></member>
+            <member><type>VkPipelineBindPoint</type>                <name>pipelineBindPoint</name></member>
+            <member><type>VkPipeline</type>                         <name>pipeline</name></member>
+            <member><type>VkIndirectCommandsLayoutNV</type>         <name>indirectCommandsLayout</name></member>
+            <member><type>uint32_t</type>                           <name>streamCount</name></member>
+            <member len="streamCount">const <type>VkIndirectCommandsStreamNV</type>*  <name>pStreams</name></member>
+            <member><type>uint32_t</type>                           <name>sequencesCount</name></member>
+            <member><type>VkBuffer</type>                           <name>preprocessBuffer</name></member>
+            <member><type>VkDeviceSize</type>                       <name>preprocessOffset</name></member>
+            <member><type>VkDeviceSize</type>                       <name>preprocessSize</name></member>
+            <member optional="true"><type>VkBuffer</type>           <name>sequencesCountBuffer</name></member>
+            <member optional="true"><type>VkDeviceSize</type>       <name>sequencesCountOffset</name></member>
+            <member optional="true"><type>VkBuffer</type>           <name>sequencesIndexBuffer</name></member>
+            <member optional="true"><type>VkDeviceSize</type>       <name>sequencesIndexOffset</name></member>
         </type>
-        <type category="struct" name="VkObjectTableIndexBufferEntryNVX">
-            <member><type>VkObjectEntryTypeNVX</type>         <name>type</name></member>
-            <member><type>VkObjectEntryUsageFlagsNVX</type>   <name>flags</name></member>
-            <member><type>VkBuffer</type>                     <name>buffer</name></member>
-            <member><type>VkIndexType</type>                  <name>indexType</name></member>
-        </type>
-        <type category="struct" name="VkObjectTablePushConstantEntryNVX">
-            <member><type>VkObjectEntryTypeNVX</type>         <name>type</name></member>
-            <member><type>VkObjectEntryUsageFlagsNVX</type>   <name>flags</name></member>
-            <member><type>VkPipelineLayout</type>             <name>pipelineLayout</name></member>
-            <member><type>VkShaderStageFlags</type>           <name>stageFlags</name></member>
+        <type category="struct" name="VkGeneratedCommandsMemoryRequirementsInfoNV">
+            <member values="VK_STRUCTURE_TYPE_GENERATED_COMMANDS_MEMORY_REQUIREMENTS_INFO_NV"><type>VkStructureType</type> <name>sType</name></member>
+            <member>const <type>void</type>*                 <name>pNext</name></member>
+            <member><type>VkPipelineBindPoint</type>         <name>pipelineBindPoint</name></member>
+            <member><type>VkPipeline</type>                  <name>pipeline</name></member>
+            <member><type>VkIndirectCommandsLayoutNV</type>  <name>indirectCommandsLayout</name></member>
+            <member><type>uint32_t</type>                    <name>maxSequencesCount</name></member>
         </type>
         <type category="struct" name="VkPhysicalDeviceFeatures2" structextends="VkDeviceCreateInfo">
             <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2"><type>VkStructureType</type> <name>sType</name></member>
@@ -3122,7 +3142,7 @@
             <member>const <type>void</type>*                                            <name>pNext</name></member>
             <member><type>VkObjectType</type>                                           <name>objectType</name></member>
             <member><type>uint64_t</type>                                               <name>objectHandle</name></member>
-            <member len="null-terminated">const <type>char</type>*                      <name>pObjectName</name></member>
+            <member optional="true" len="null-terminated">const <type>char</type>*      <name>pObjectName</name></member>
         </type>
         <type category="struct" name="VkDebugUtilsObjectTagInfoEXT">
             <member values="VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_TAG_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
@@ -3704,12 +3724,22 @@
         <type category="struct" name="VkRayTracingShaderGroupCreateInfoNV">
             <member values="VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV"><type>VkStructureType</type> <name>sType</name></member>
             <member>const <type>void</type>*            <name>pNext</name></member>
-            <member><type>VkRayTracingShaderGroupTypeNV</type> <name>type</name></member>
+            <member><type>VkRayTracingShaderGroupTypeKHR</type> <name>type</name></member>
             <member><type>uint32_t</type>               <name>generalShader</name></member>
             <member><type>uint32_t</type>               <name>closestHitShader</name></member>
             <member><type>uint32_t</type>               <name>anyHitShader</name></member>
             <member><type>uint32_t</type>               <name>intersectionShader</name></member>
         </type>
+        <type category="struct" name="VkRayTracingShaderGroupCreateInfoKHR">
+            <member values="VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
+            <member>const <type>void</type>*            <name>pNext</name></member>
+            <member><type>VkRayTracingShaderGroupTypeKHR</type> <name>type</name></member>
+            <member><type>uint32_t</type>               <name>generalShader</name></member>
+            <member><type>uint32_t</type>               <name>closestHitShader</name></member>
+            <member><type>uint32_t</type>               <name>anyHitShader</name></member>
+            <member><type>uint32_t</type>               <name>intersectionShader</name></member>
+            <member optional="true">const <type>void</type>* <name>pShaderGroupCaptureReplayHandle</name></member>
+        </type>
         <type category="struct" name="VkRayTracingPipelineCreateInfoNV">
             <member values="VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_NV"><type>VkStructureType</type> <name>sType</name></member>
             <member>const <type>void</type>*            <name>pNext</name></member>
@@ -3723,6 +3753,21 @@
             <member noautovalidity="true" optional="true"><type>VkPipeline</type>      <name>basePipelineHandle</name><comment>If VK_PIPELINE_CREATE_DERIVATIVE_BIT is set and this value is nonzero, it specifies the handle of the base pipeline this is a derivative of</comment></member>
             <member><type>int32_t</type>                <name>basePipelineIndex</name><comment>If VK_PIPELINE_CREATE_DERIVATIVE_BIT is set and this value is not -1, it specifies an index into pCreateInfos of the base pipeline this is a derivative of</comment></member>
         </type>
+        <type category="struct" name="VkRayTracingPipelineCreateInfoKHR">
+            <member values="VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
+            <member>const <type>void</type>*            <name>pNext</name></member>
+            <member optional="true"><type>VkPipelineCreateFlags</type>  <name>flags</name><comment>Pipeline creation flags</comment></member>
+            <member optional="true"><type>uint32_t</type> <name>stageCount</name></member>
+            <member len="stageCount">const <type>VkPipelineShaderStageCreateInfo</type>* <name>pStages</name><comment>One entry for each active shader stage</comment></member>
+            <member optional="true"><type>uint32_t</type> <name>groupCount</name></member>
+            <member len="groupCount">const <type>VkRayTracingShaderGroupCreateInfoKHR</type>* <name>pGroups</name></member>
+            <member><type>uint32_t</type>               <name>maxRecursionDepth</name></member>
+            <member><type>VkPipelineLibraryCreateInfoKHR</type> <name>libraries</name></member>
+            <member optional="true">const <type>VkRayTracingPipelineInterfaceCreateInfoKHR</type>* <name>pLibraryInterface</name></member>
+            <member><type>VkPipelineLayout</type>       <name>layout</name><comment>Interface layout of the pipeline</comment></member>
+            <member noautovalidity="true" optional="true"><type>VkPipeline</type>      <name>basePipelineHandle</name><comment>If VK_PIPELINE_CREATE_DERIVATIVE_BIT is set and this value is nonzero, it specifies the handle of the base pipeline this is a derivative of</comment></member>
+            <member><type>int32_t</type>                <name>basePipelineIndex</name><comment>If VK_PIPELINE_CREATE_DERIVATIVE_BIT is set and this value is not -1, it specifies an index into pCreateInfos of the base pipeline this is a derivative of</comment></member>
+        </type>
         <type category="struct" name="VkGeometryTrianglesNV">
             <member values="VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV"><type>VkStructureType</type> <name>sType</name></member>
             <member>const <type>void</type>*                <name>pNext</name></member>
@@ -3752,16 +3797,16 @@
         </type>
         <type category="struct" name="VkGeometryNV">
             <member values="VK_STRUCTURE_TYPE_GEOMETRY_NV"><type>VkStructureType</type> <name>sType</name></member>
-            <member>const <type>void</type>*                        <name>pNext</name></member>
-            <member><type>VkGeometryTypeNV</type>                  <name>geometryType</name></member>
-            <member><type>VkGeometryDataNV</type>                  <name>geometry</name></member>
-            <member optional="true"><type>VkGeometryFlagsNV</type> <name>flags</name></member>
+            <member>const <type>void</type>*                                   <name>pNext</name></member>
+            <member><type>VkGeometryTypeKHR</type>                  <name>geometryType</name></member>
+            <member><type>VkGeometryDataNV</type>                              <name>geometry</name></member>
+            <member optional="true"><type>VkGeometryFlagsKHR</type> <name>flags</name></member>
         </type>
         <type category="struct" name="VkAccelerationStructureInfoNV">
             <member values="VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV"><type>VkStructureType</type> <name>sType</name></member>
             <member>const <type>void</type>*                            <name>pNext</name></member>
             <member><type>VkAccelerationStructureTypeNV</type>         <name>type</name></member>
-            <member optional="true"><type>VkBuildAccelerationStructureFlagsNV</type><name>flags</name></member>
+            <member noautovalidity="true" optional="true"><type>VkBuildAccelerationStructureFlagsNV</type><name>flags</name></member>
             <member optional="true"><type>uint32_t</type>               <name>instanceCount</name></member>
             <member optional="true"><type>uint32_t</type>               <name>geometryCount</name></member>
             <member len="geometryCount">const <type>VkGeometryNV</type>* <name>pGeometries</name></member>
@@ -3772,26 +3817,61 @@
             <member><type>VkDeviceSize</type>                           <name>compactedSize</name></member>
             <member><type>VkAccelerationStructureInfoNV</type>          <name>info</name></member>
         </type>
-        <type category="struct" name="VkBindAccelerationStructureMemoryInfoNV">
-            <member values="VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV"><type>VkStructureType</type> <name>sType</name></member>
+        <type category="struct" name="VkBindAccelerationStructureMemoryInfoKHR">
+            <member values="VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
             <member>const <type>void</type>*                      <name>pNext</name></member>
-            <member><type>VkAccelerationStructureNV</type>        <name>accelerationStructure</name></member>
+            <member><type>VkAccelerationStructureKHR</type>       <name>accelerationStructure</name></member>
             <member><type>VkDeviceMemory</type>                   <name>memory</name></member>
             <member><type>VkDeviceSize</type>                     <name>memoryOffset</name></member>
             <member optional="true"><type>uint32_t</type>         <name>deviceIndexCount</name></member>
             <member len="deviceIndexCount">const <type>uint32_t</type>*  <name>pDeviceIndices</name></member>
         </type>
-        <type category="struct" name="VkWriteDescriptorSetAccelerationStructureNV" structextends="VkWriteDescriptorSet">
-            <member values="VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_NV"><type>VkStructureType</type> <name>sType</name></member>
+        <type category="struct" name="VkBindAccelerationStructureMemoryInfoNV"            alias="VkBindAccelerationStructureMemoryInfoKHR"/>
+        <type category="struct" name="VkWriteDescriptorSetAccelerationStructureKHR" structextends="VkWriteDescriptorSet">
+            <member values="VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR"><type>VkStructureType</type> <name>sType</name></member>
             <member>const <type>void</type>*                      <name>pNext</name></member>
             <member><type>uint32_t</type>                         <name>accelerationStructureCount</name></member>
-            <member len="accelerationStructureCount">const <type>VkAccelerationStructureNV</type>* <name>pAccelerationStructures</name></member>
+            <member len="accelerationStructureCount">const <type>VkAccelerationStructureKHR</type>* <name>pAccelerationStructures</name></member>
+        </type>
+        <type category="struct" name="VkWriteDescriptorSetAccelerationStructureNV"        alias="VkWriteDescriptorSetAccelerationStructureKHR"/>
+        <type category="struct" name="VkAccelerationStructureMemoryRequirementsInfoKHR">
+            <member values="VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
+            <member>const <type>void</type>*                                                          <name>pNext</name></member>
+            <member><type>VkAccelerationStructureMemoryRequirementsTypeKHR</type>                     <name>type</name></member>
+            <member><type>VkAccelerationStructureBuildTypeKHR</type>                                  <name>buildType</name></member>
+            <member><type>VkAccelerationStructureKHR</type>                                           <name>accelerationStructure</name></member>
         </type>
         <type category="struct" name="VkAccelerationStructureMemoryRequirementsInfoNV">
             <member values="VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV"><type>VkStructureType</type> <name>sType</name></member>
             <member>const <type>void</type>*                                                          <name>pNext</name></member>
-            <member><type>VkAccelerationStructureMemoryRequirementsTypeNV</type>                      <name>type</name></member>
-            <member><type>VkAccelerationStructureNV</type>                                            <name>accelerationStructure</name></member>
+            <member><type>VkAccelerationStructureMemoryRequirementsTypeNV</type>                     <name>type</name></member>
+            <member><type>VkAccelerationStructureNV</type>                                           <name>accelerationStructure</name></member>
+        </type>
+        <type category="struct" name="VkPhysicalDeviceRayTracingFeaturesKHR" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+            <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_FEATURES_KHR"><type>VkStructureType</type> <name>sType</name></member>
+            <member><type>void</type>*                            <name>pNext</name></member>
+            <member><type>VkBool32</type>                         <name>rayTracing</name></member>
+            <member><type>VkBool32</type>                         <name>rayTracingShaderGroupHandleCaptureReplay</name></member>
+            <member><type>VkBool32</type>                         <name>rayTracingShaderGroupHandleCaptureReplayMixed</name></member>
+            <member><type>VkBool32</type>                         <name>rayTracingAccelerationStructureCaptureReplay</name></member>
+            <member><type>VkBool32</type>                         <name>rayTracingIndirectTraceRays</name></member>
+            <member><type>VkBool32</type>                         <name>rayTracingIndirectAccelerationStructureBuild</name></member>
+            <member><type>VkBool32</type>                         <name>rayTracingHostAccelerationStructureCommands</name></member>
+            <member><type>VkBool32</type>                         <name>rayQuery</name></member>
+            <member><type>VkBool32</type>                         <name>rayTracingPrimitiveCulling</name></member>
+        </type>
+        <type category="struct" name="VkPhysicalDeviceRayTracingPropertiesKHR" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
+            <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_KHR"><type>VkStructureType</type> <name>sType</name></member>
+            <member><type>void</type>*                            <name>pNext</name></member>
+            <member><type>uint32_t</type>                         <name>shaderGroupHandleSize</name></member>
+            <member><type>uint32_t</type>                         <name>maxRecursionDepth</name></member>
+            <member><type>uint32_t</type>                         <name>maxShaderGroupStride</name></member>
+            <member><type>uint32_t</type>                         <name>shaderGroupBaseAlignment</name></member>
+            <member><type>uint64_t</type>                         <name>maxGeometryCount</name></member>
+            <member><type>uint64_t</type>                         <name>maxInstanceCount</name></member>
+            <member><type>uint64_t</type>                         <name>maxPrimitiveCount</name></member>
+            <member><type>uint32_t</type>                         <name>maxDescriptorSetAccelerationStructures</name></member>
+            <member><type>uint32_t</type>                         <name>shaderGroupHandleCaptureReplaySize</name></member>
         </type>
         <type category="struct" name="VkPhysicalDeviceRayTracingPropertiesNV" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
             <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_NV"><type>VkStructureType</type> <name>sType</name></member>
@@ -3805,6 +3885,17 @@
             <member><type>uint64_t</type>                         <name>maxTriangleCount</name></member>
             <member><type>uint32_t</type>                         <name>maxDescriptorSetAccelerationStructures</name></member>
         </type>
+        <type category="struct" name="VkStridedBufferRegionKHR">
+            <member optional="true"><type>VkBuffer</type>         <name>buffer</name></member>
+            <member><type>VkDeviceSize</type>                     <name>offset</name></member>
+            <member><type>VkDeviceSize</type>                     <name>stride</name></member>
+            <member><type>VkDeviceSize</type>                     <name>size</name></member>
+        </type>
+        <type category="struct" name="VkTraceRaysIndirectCommandKHR">
+            <member><type>uint32_t</type>               <name>width</name></member>
+            <member><type>uint32_t</type>               <name>height</name></member>
+            <member><type>uint32_t</type>               <name>depth</name></member>
+        </type>
         <type category="struct" name="VkDrmFormatModifierPropertiesListEXT" returnedonly="true" structextends="VkFormatProperties2">
             <member values="VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT"><type>VkStructureType</type> <name>sType</name></member>
             <member><type>void</type>* <name>pNext</name></member>
@@ -4033,6 +4124,12 @@
             <member><type>VkDescriptorType</type>                    <name>descriptorType</name></member>
             <member optional="true"><type>VkSampler</type>           <name>sampler</name></member>
         </type>
+        <type category="struct" name="VkImageViewAddressPropertiesNVX" returnedonly="true">
+            <member values="VK_STRUCTURE_TYPE_IMAGE_VIEW_ADDRESS_PROPERTIES_NVX"><type>VkStructureType</type> <name>sType</name></member>
+            <member><type>void</type>*              <name>pNext</name></member>
+            <member><type>VkDeviceAddress</type>    <name>deviceAddress</name></member>
+            <member><type>VkDeviceSize</type>       <name>size</name></member>
+        </type>
         <type category="struct" name="VkPresentFrameTokenGGP" structextends="VkPresentInfoKHR">
             <member values="VK_STRUCTURE_TYPE_PRESENT_FRAME_TOKEN_GGP"><type>VkStructureType</type> <name>sType</name></member>
             <member>const <type>void</type>*                      <name>pNext</name></member>
@@ -4042,7 +4139,7 @@
             <member><type>VkPipelineCreationFeedbackFlagsEXT</type>  <name>flags</name></member>
             <member><type>uint64_t</type>                            <name>duration</name></member>
         </type>
-        <type category="struct" name="VkPipelineCreationFeedbackCreateInfoEXT" structextends="VkGraphicsPipelineCreateInfo,VkComputePipelineCreateInfo,VkRayTracingPipelineCreateInfoNV">
+        <type category="struct" name="VkPipelineCreationFeedbackCreateInfoEXT" structextends="VkGraphicsPipelineCreateInfo,VkComputePipelineCreateInfo,VkRayTracingPipelineCreateInfoNV,VkRayTracingPipelineCreateInfoKHR">
             <member values="VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
             <member>const <type>void</type>*                         <name>pNext</name></member>
             <member><type>VkPipelineCreationFeedbackEXT</type>*      <name>pPipelineCreationFeedback</name><comment>Output pipeline creation feedback.</comment></member>
@@ -4150,7 +4247,7 @@
             <member><type>uint64_t</type>                           <name>value64</name></member>
             <member><type>float</type>                              <name>valueFloat</name></member>
             <member><type>VkBool32</type>                           <name>valueBool</name></member>
-            <member>const <type>char</type>*                        <name>valueString</name></member>
+            <member len="null-terminated">const <type>char</type>*  <name>valueString</name></member>
         </type>
         <type category="struct" name="VkPerformanceValueINTEL">
             <member><type>VkPerformanceValueTypeINTEL</type>        <name>type</name></member>
@@ -4161,11 +4258,12 @@
             <member>const <type>void</type>*                         <name>pNext</name></member>
             <member optional="false"><type>void</type>*             <name>pUserData</name></member>
         </type>
-        <type category="struct" name="VkQueryPoolCreateInfoINTEL" structextends="VkQueryPoolCreateInfo">
-            <member values="VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO_INTEL"><type>VkStructureType</type> <name>sType</name></member>
+        <type category="struct" name="VkQueryPoolPerformanceQueryCreateInfoINTEL" structextends="VkQueryPoolCreateInfo">
+            <member values="VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_QUERY_CREATE_INFO_INTEL"><type>VkStructureType</type> <name>sType</name></member>
             <member>const <type>void</type>*                         <name>pNext</name></member>
             <member><type>VkQueryPoolSamplingModeINTEL</type>        <name>performanceCountersSampling</name></member>
         </type>
+        <type category="struct" name="VkQueryPoolCreateInfoINTEL" alias="VkQueryPoolPerformanceQueryCreateInfoINTEL"/>
         <type category="struct" name="VkPerformanceMarkerInfoINTEL">
             <member values="VK_STRUCTURE_TYPE_PERFORMANCE_MARKER_INFO_INTEL"><type>VkStructureType</type> <name>sType</name></member>
             <member>const <type>void</type>*                         <name>pNext</name></member>
@@ -4355,6 +4453,11 @@
             <member optional="true"><type>uint32_t</type>                                         <name>lineStippleFactor</name></member>
             <member optional="true"><type>uint16_t</type>                                         <name>lineStipplePattern</name></member>
         </type>
+        <type category="struct" name="VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+            <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+            <member noautovalidity="true"><type>void</type>* <name>pNext</name></member>
+            <member><type>VkBool32</type>                                                         <name>pipelineCreationCacheControl</name></member>
+        </type>
         <type category="struct" name="VkPhysicalDeviceVulkan11Features" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
             <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES"><type>VkStructureType</type><name>sType</name></member>
             <member noautovalidity="true"><type>void</type>*    <name>pNext</name></member>
@@ -4371,7 +4474,7 @@
             <member><type>VkBool32</type>                         <name>samplerYcbcrConversion</name><comment>Sampler color conversion supported</comment></member>
             <member><type>VkBool32</type>                         <name>shaderDrawParameters</name></member>
         </type>
-        <type category="struct" name="VkPhysicalDeviceVulkan11Properties" structextends="VkPhysicalDeviceProperties2">
+        <type category="struct" name="VkPhysicalDeviceVulkan11Properties" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
             <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES"><type>VkStructureType</type><name>sType</name></member>
             <member noautovalidity="true"><type>void</type>*      <name>pNext</name></member>
             <member><type>uint8_t</type>                          <name>deviceUUID</name>[<enum>VK_UUID_SIZE</enum>]</member>
@@ -4441,7 +4544,7 @@
             <member><type>VkBool32</type>                         <name>shaderOutputLayer</name></member>
             <member><type>VkBool32</type>                         <name>subgroupBroadcastDynamicId</name></member>
         </type>
-        <type category="struct" name="VkPhysicalDeviceVulkan12Properties" structextends="VkPhysicalDeviceProperties2">
+        <type category="struct" name="VkPhysicalDeviceVulkan12Properties" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
             <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES"><type>VkStructureType</type><name>sType</name></member>
             <member noautovalidity="true"><type>void</type>*    <name>pNext</name></member>
             <member><type>VkDriverId</type>                       <name>driverID</name></member>
@@ -4516,6 +4619,158 @@
             <member><type>char</type>            <name>description</name>[<enum>VK_MAX_DESCRIPTION_SIZE</enum>]</member>
             <member><type>char</type>            <name>layer</name>[<enum>VK_MAX_EXTENSION_NAME_SIZE</enum>]</member>
         </type>
+        <type category="union" name="VkDeviceOrHostAddressKHR">
+            <member noautovalidity="true"><type>VkDeviceAddress</type>            <name>deviceAddress</name></member>
+            <member noautovalidity="true"><type>void</type>*                      <name>hostAddress</name></member>
+        </type>
+        <type category="union" name="VkDeviceOrHostAddressConstKHR">
+            <member noautovalidity="true"><type>VkDeviceAddress</type>            <name>deviceAddress</name></member>
+            <member noautovalidity="true">const <type>void</type>*                <name>hostAddress</name></member>
+        </type>
+        <type category="struct" name="VkAccelerationStructureGeometryTrianglesDataKHR">
+            <member values="VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR"><type>VkStructureType</type> <name>sType</name></member>
+            <member>const <type>void</type>*                                   <name>pNext</name></member>
+            <member><type>VkFormat</type>                                      <name>vertexFormat</name></member>
+            <member><type>VkDeviceOrHostAddressConstKHR</type>                 <name>vertexData</name></member>
+            <member><type>VkDeviceSize</type>                                  <name>vertexStride</name></member>
+            <member><type>VkIndexType</type>                                   <name>indexType</name></member>
+            <member optional="true"><type>VkDeviceOrHostAddressConstKHR</type> <name>indexData</name></member>
+            <member optional="true"><type>VkDeviceOrHostAddressConstKHR</type> <name>transformData</name></member>
+        </type>
+        <type category="struct" name="VkAccelerationStructureGeometryAabbsDataKHR">
+            <member values="VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR"><type>VkStructureType</type> <name>sType</name></member>
+            <member>const <type>void</type>*                           <name>pNext</name></member>
+            <member><type>VkDeviceOrHostAddressConstKHR</type>         <name>data</name></member>
+            <member><type>VkDeviceSize</type>                          <name>stride</name></member>
+        </type>
+        <type category="struct" name="VkAccelerationStructureGeometryInstancesDataKHR">
+            <member values="VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR"><type>VkStructureType</type> <name>sType</name></member>
+            <member>const <type>void</type>*                           <name>pNext</name></member>
+            <member><type>VkBool32</type>                              <name>arrayOfPointers</name></member>
+            <member><type>VkDeviceOrHostAddressConstKHR</type>         <name>data</name></member>
+        </type>
+        <type category="union" name="VkAccelerationStructureGeometryDataKHR">
+            <member><type>VkAccelerationStructureGeometryTrianglesDataKHR</type>            <name>triangles</name></member>
+            <member><type>VkAccelerationStructureGeometryAabbsDataKHR</type>                <name>aabbs</name></member>
+            <member><type>VkAccelerationStructureGeometryInstancesDataKHR</type>            <name>instances</name></member>
+        </type>
+        <type category="struct" name="VkAccelerationStructureGeometryKHR">
+            <member values="VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR"><type>VkStructureType</type> <name>sType</name></member>
+            <member>const <type>void</type>*                            <name>pNext</name></member>
+            <member><type>VkGeometryTypeKHR</type>                      <name>geometryType</name></member>
+            <member><type>VkAccelerationStructureGeometryDataKHR</type> <name>geometry</name></member>
+            <member optional="true"><type>VkGeometryFlagsKHR</type>     <name>flags</name></member>
+        </type>
+        <type category="struct" name="VkAccelerationStructureBuildGeometryInfoKHR">
+            <member values="VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
+            <member>const <type>void</type>*                                                        <name>pNext</name></member>
+            <member><type>VkAccelerationStructureTypeKHR</type>                                     <name>type</name></member>
+            <member optional="true"><type>VkBuildAccelerationStructureFlagsKHR</type>               <name>flags</name></member>
+            <member><type>VkBool32</type>                                                           <name>update</name></member>
+            <member optional="true"><type>VkAccelerationStructureKHR</type>                         <name>srcAccelerationStructure</name></member>
+            <member><type>VkAccelerationStructureKHR</type>                                         <name>dstAccelerationStructure</name></member>
+            <member><type>VkBool32</type>                                                           <name>geometryArrayOfPointers</name></member>
+            <member optional="true"><type>uint32_t</type>                                           <name>geometryCount</name></member>
+            <member noautovalidity="true">const <type>VkAccelerationStructureGeometryKHR</type>* const*   <name>ppGeometries</name></member>
+            <member><type>VkDeviceOrHostAddressKHR</type>                                           <name>scratchData</name></member>
+        </type>
+        <type category="struct" name="VkAccelerationStructureBuildOffsetInfoKHR">
+            <member><type>uint32_t</type>                                                <name>primitiveCount</name></member>
+            <member><type>uint32_t</type>                                                <name>primitiveOffset</name></member>
+            <member optional="true"><type>uint32_t</type>                                <name>firstVertex</name></member>
+            <member optional="true"><type>uint32_t</type>                                <name>transformOffset</name></member>
+        </type>
+        <type category="struct" name="VkAccelerationStructureCreateGeometryTypeInfoKHR">
+            <member values="VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
+            <member>const <type>void</type>*                                             <name>pNext</name></member>
+            <member><type>VkGeometryTypeKHR</type>                                       <name>geometryType</name></member>
+            <member><type>uint32_t</type>                                                <name>maxPrimitiveCount</name></member>
+            <member><type>VkIndexType</type>                                              <name>indexType</name></member>
+            <member optional="true"><type>uint32_t</type>                                <name>maxVertexCount</name></member>
+            <member optional="true"><type>VkFormat</type>                                <name>vertexFormat</name></member>
+            <member optional="true"><type>VkBool32</type>                                <name>allowsTransforms</name></member>
+        </type>
+        <type category="struct" name="VkAccelerationStructureCreateInfoKHR">
+            <member values="VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
+            <member>const <type>void</type>*                                             <name>pNext</name></member>
+            <member><type>VkDeviceSize</type>                                            <name>compactedSize</name></member>
+            <member><type>VkAccelerationStructureTypeKHR</type>                          <name>type</name></member>
+            <member optional="true"><type>VkBuildAccelerationStructureFlagsKHR</type>    <name>flags</name></member>
+            <member><type>uint32_t</type>                                                <name>maxGeometryCount</name></member>
+            <member len="maxGeometryCount">const <type>VkAccelerationStructureCreateGeometryTypeInfoKHR</type>* <name>pGeometryInfos</name></member>
+            <member optional="true"><type>VkDeviceAddress</type>                         <name>deviceAddress</name></member>
+        </type>
+        <type category="struct" name="VkAabbPositionsKHR">
+            <member><type>float</type>                                                   <name>minX</name></member>
+            <member><type>float</type>                                                   <name>minY</name></member>
+            <member><type>float</type>                                                   <name>minZ</name></member>
+            <member><type>float</type>                                                   <name>maxX</name></member>
+            <member><type>float</type>                                                   <name>maxY</name></member>
+            <member><type>float</type>                                                   <name>maxZ</name></member>
+        </type>
+        <type category="struct" name="VkAabbPositionsNV" alias="VkAabbPositionsKHR"/>
+        <type category="struct" name="VkTransformMatrixKHR">
+            <member><type>float</type>                                                   <name>matrix</name>[3][4]</member>
+        </type>
+        <type category="struct" name="VkTransformMatrixNV" alias="VkTransformMatrixKHR"/>
+        <type category="struct" name="VkAccelerationStructureInstanceKHR">
+            <member><type>VkTransformMatrixKHR</type>                                    <name>transform</name></member>
+            <member><type>uint32_t</type>                                                <name>instanceCustomIndex</name>:24</member>
+            <member><type>uint32_t</type>                                                <name>mask</name>:8</member>
+            <member><type>uint32_t</type>                                                <name>instanceShaderBindingTableRecordOffset</name>:24</member>
+            <member optional="true"><type>VkGeometryInstanceFlagsKHR</type>              <name>flags</name>:8</member>
+            <member><type>uint64_t</type>                                                <name>accelerationStructureReference</name></member>
+        </type>
+        <type category="struct" name="VkAccelerationStructureInstanceNV" alias="VkAccelerationStructureInstanceKHR"/>
+        <type category="struct" name="VkAccelerationStructureDeviceAddressInfoKHR">
+            <member values="VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
+            <member>const <type>void</type>*                                            <name>pNext</name></member>
+            <member><type>VkAccelerationStructureKHR</type>                             <name>accelerationStructure</name></member>
+        </type>
+        <type category="struct" name="VkAccelerationStructureVersionKHR">
+            <member values="VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_VERSION_KHR"><type>VkStructureType</type> <name>sType</name></member>
+            <member>const <type>void</type>*                                            <name>pNext</name></member>
+            <member len="2*VK_UUID_SIZE">const <type>uint8_t</type>*                    <name>versionData</name></member>
+        </type>
+        <type category="struct" name="VkCopyAccelerationStructureInfoKHR">
+            <member values="VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
+            <member>const <type>void</type>*                                            <name>pNext</name></member>
+            <member><type>VkAccelerationStructureKHR</type>                             <name>src</name></member>
+            <member><type>VkAccelerationStructureKHR</type>                             <name>dst</name></member>
+            <member><type>VkCopyAccelerationStructureModeKHR</type>                     <name>mode</name></member>
+        </type>
+        <type category="struct" name="VkCopyAccelerationStructureToMemoryInfoKHR">
+            <member values="VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_TO_MEMORY_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
+            <member>const <type>void</type>*                                            <name>pNext</name></member>
+            <member><type>VkAccelerationStructureKHR</type>                             <name>src</name></member>
+            <member><type>VkDeviceOrHostAddressKHR</type>                               <name>dst</name></member>
+            <member><type>VkCopyAccelerationStructureModeKHR</type>                     <name>mode</name></member>
+        </type>
+        <type category="struct" name="VkCopyMemoryToAccelerationStructureInfoKHR">
+            <member values="VK_STRUCTURE_TYPE_COPY_MEMORY_TO_ACCELERATION_STRUCTURE_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
+            <member>const <type>void</type>*                                            <name>pNext</name></member>
+            <member><type>VkDeviceOrHostAddressConstKHR</type>                          <name>src</name></member>
+            <member><type>VkAccelerationStructureKHR</type>                             <name>dst</name></member>
+            <member><type>VkCopyAccelerationStructureModeKHR</type>                     <name>mode</name></member>
+        </type>
+        <type category="struct" name="VkRayTracingPipelineInterfaceCreateInfoKHR">
+            <member values="VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_INTERFACE_CREATE_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
+            <member>const <type>void</type>*                                            <name>pNext</name></member>
+            <member><type>uint32_t</type>                                               <name>maxPayloadSize</name></member>
+            <member><type>uint32_t</type>                                               <name>maxAttributeSize</name></member>
+            <member><type>uint32_t</type>                                               <name>maxCallableSize</name></member>
+        </type>
+        <type category="struct" name="VkDeferredOperationInfoKHR" structextends="VkRayTracingPipelineCreateInfoKHR,VkAccelerationStructureBuildGeometryInfoKHR,VkCopyAccelerationStructureInfoKHR,VkCopyMemoryToAccelerationStructureInfoKHR,VkCopyAccelerationStructureToMemoryInfoKHR">
+            <member values="VK_STRUCTURE_TYPE_DEFERRED_OPERATION_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
+            <member>const <type>void</type>*                   <name>pNext</name></member>
+            <member noautovalidity="true"><type>VkDeferredOperationKHR</type>        <name>operationHandle</name></member>
+        </type>
+        <type category="struct" name="VkPipelineLibraryCreateInfoKHR">
+            <member values="VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
+            <member>const <type>void</type>*                                            <name>pNext</name></member>
+            <member optional="true"><type>uint32_t</type>                               <name>libraryCount</name></member>
+            <member len="libraryCount">const <type>VkPipeline</type>*                   <name>pLibraries</name></member>
+        </type>
         <type category="struct" name="VkRenderPassTransformBeginInfoQCOM" structextends="VkRenderPassBeginInfo">
             <member values="VK_STRUCTURE_TYPE_RENDER_PASS_TRANSFORM_BEGIN_INFO_QCOM"><type>VkStructureType</type> <name>sType</name></member>
             <member><type>void</type>*                           <name>pNext</name><comment>Pointer to next structure</comment></member>
@@ -4527,6 +4782,16 @@
             <member noautovalidity="true"><type>VkSurfaceTransformFlagBitsKHR</type>   <name>transform</name></member>
             <member><type>VkRect2D</type>                        <name>renderArea</name></member>
         </type>
+        <type category="struct" name="VkPhysicalDeviceDiagnosticsConfigFeaturesNV" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+            <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DIAGNOSTICS_CONFIG_FEATURES_NV"><type>VkStructureType</type><name>sType</name></member>
+            <member noautovalidity="true"><type>void</type>*    <name>pNext</name></member>
+            <member><type>VkBool32</type>                       <name>diagnosticsConfig</name></member>
+        </type>
+        <type category="struct" name="VkDeviceDiagnosticsConfigCreateInfoNV" structextends="VkDeviceCreateInfo">
+            <member values="VK_STRUCTURE_TYPE_DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV"><type>VkStructureType</type> <name>sType</name></member>
+            <member>const <type>void</type>*                                         <name>pNext</name></member>
+            <member optional="true"><type>VkDeviceDiagnosticsConfigFlagsNV</type>    <name>flags</name></member>
+        </type>
  </types>
 
     <comment>Vulkan enumerant (token) definitions</comment>
@@ -4558,7 +4823,8 @@
         <enum               name="VK_MAX_DRIVER_NAME_SIZE_KHR" alias="VK_MAX_DRIVER_NAME_SIZE"/>
         <enum value="256"   name="VK_MAX_DRIVER_INFO_SIZE"/>
         <enum               name="VK_MAX_DRIVER_INFO_SIZE_KHR" alias="VK_MAX_DRIVER_INFO_SIZE"/>
-        <enum value="(~0U)" name="VK_SHADER_UNUSED_NV"/>
+        <enum value="(~0U)" name="VK_SHADER_UNUSED_KHR"/>
+        <enum               name="VK_SHADER_UNUSED_NV" alias="VK_SHADER_UNUSED_KHR"/>
     </enums>
 
     <comment>
@@ -4654,6 +4920,7 @@
     <enums name="VkPipelineCacheHeaderVersion" type="enum">
         <enum value="1"     name="VK_PIPELINE_CACHE_HEADER_VERSION_ONE"/>
     </enums>
+    <enums name="VkPipelineCacheCreateFlagBits" type="bitmask"></enums>
     <enums name="VkPrimitiveTopology" type="enum">
         <enum value="0"     name="VK_PRIMITIVE_TOPOLOGY_POINT_LIST"/>
         <enum value="1"     name="VK_PRIMITIVE_TOPOLOGY_LINE_LIST"/>
@@ -5408,8 +5675,8 @@
         <enum               name="VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT" alias="VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT" comment="Backwards-compatible alias containing a typo"/>
         <enum value="29"    name="VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT"/>
         <enum value="30"    name="VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT"/>
-        <enum value="31"    name="VK_DEBUG_REPORT_OBJECT_TYPE_OBJECT_TABLE_NVX_EXT"/>
-        <enum value="32"    name="VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT"/>
+        <!--<enum value="31"    name="VK_DEBUG_REPORT_OBJECT_TYPE_OBJECT_TABLE_NVX_EXT" comment="Removed NVX_device_generated_commands"/>-->
+        <!--<enum value="32"    name="VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT" comment="Removed NVX_device_generated_commands"/>-->
         <enum value="33"    name="VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT"/>
         <enum               name="VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT" alias="VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT" comment="Backwards-compatible alias containing a typo"/>
     </enums>
@@ -5436,6 +5703,7 @@
         <enum value="0"     name="VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT"/>
         <enum value="1"     name="VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT"/>
         <enum value="2"     name="VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT"/>
+        <enum value="3"     name="VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT"/>
     </enums>
     <enums name="VkValidationFeatureDisableEXT" type="enum">
         <enum value="0"     name="VK_VALIDATION_FEATURE_DISABLE_ALL_EXT"/>
@@ -5456,32 +5724,23 @@
         <enum bitpos="6"    name="VK_SUBGROUP_FEATURE_CLUSTERED_BIT"          comment="Clustered subgroup operations"/>
         <enum bitpos="7"    name="VK_SUBGROUP_FEATURE_QUAD_BIT"               comment="Quad subgroup operations"/>
     </enums>
-    <enums name="VkIndirectCommandsLayoutUsageFlagBitsNVX" type="bitmask">
-        <enum bitpos="0"    name="VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NVX"/>
-        <enum bitpos="1"    name="VK_INDIRECT_COMMANDS_LAYOUT_USAGE_SPARSE_SEQUENCES_BIT_NVX"/>
-        <enum bitpos="2"    name="VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EMPTY_EXECUTIONS_BIT_NVX"/>
-        <enum bitpos="3"    name="VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NVX"/>
+    <enums name="VkIndirectCommandsLayoutUsageFlagBitsNV" type="bitmask">
+        <enum bitpos="0"    name="VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EXPLICIT_PREPROCESS_BIT_NV"/>
+        <enum bitpos="1"    name="VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NV"/>
+        <enum bitpos="2"    name="VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NV"/>
     </enums>
-    <enums name="VkObjectEntryUsageFlagBitsNVX" type="bitmask">
-        <enum bitpos="0"    name="VK_OBJECT_ENTRY_USAGE_GRAPHICS_BIT_NVX"/>
-        <enum bitpos="1"    name="VK_OBJECT_ENTRY_USAGE_COMPUTE_BIT_NVX"/>
+    <enums name="VkIndirectStateFlagBitsNV" type="bitmask">
+        <enum bitpos="0"    name="VK_INDIRECT_STATE_FLAG_FRONTFACE_BIT_NV"/>
     </enums>
-    <enums name="VkIndirectCommandsTokenTypeNVX" type="enum">
-        <enum value="0"     name="VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NVX"/>
-        <enum value="1"     name="VK_INDIRECT_COMMANDS_TOKEN_TYPE_DESCRIPTOR_SET_NVX"/>
-        <enum value="2"     name="VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_NVX"/>
-        <enum value="3"     name="VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_NVX"/>
-        <enum value="4"     name="VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NVX"/>
-        <enum value="5"     name="VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NVX"/>
-        <enum value="6"     name="VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NVX"/>
-        <enum value="7"     name="VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NVX"/>
-    </enums>
-    <enums name="VkObjectEntryTypeNVX" type="enum">
-        <enum value="0"     name="VK_OBJECT_ENTRY_TYPE_DESCRIPTOR_SET_NVX"/>
-        <enum value="1"     name="VK_OBJECT_ENTRY_TYPE_PIPELINE_NVX"/>
-        <enum value="2"     name="VK_OBJECT_ENTRY_TYPE_INDEX_BUFFER_NVX"/>
-        <enum value="3"     name="VK_OBJECT_ENTRY_TYPE_VERTEX_BUFFER_NVX"/>
-        <enum value="4"     name="VK_OBJECT_ENTRY_TYPE_PUSH_CONSTANT_NVX"/>
+    <enums name="VkIndirectCommandsTokenTypeNV" type="enum">
+        <enum value="0"     name="VK_INDIRECT_COMMANDS_TOKEN_TYPE_SHADER_GROUP_NV"/>
+        <enum value="1"     name="VK_INDIRECT_COMMANDS_TOKEN_TYPE_STATE_FLAGS_NV"/>
+        <enum value="2"     name="VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_NV"/>
+        <enum value="3"     name="VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_NV"/>
+        <enum value="4"     name="VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NV"/>
+        <enum value="5"     name="VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NV"/>
+        <enum value="6"     name="VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NV"/>
+        <enum value="7"     name="VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_TASKS_NV"/>
     </enums>
     <enums name="VkDescriptorSetLayoutCreateFlagBits" type="bitmask">
     </enums>
@@ -5709,44 +5968,51 @@
         <enum value="2" name="VK_COARSE_SAMPLE_ORDER_TYPE_PIXEL_MAJOR_NV"/>
         <enum value="3" name="VK_COARSE_SAMPLE_ORDER_TYPE_SAMPLE_MAJOR_NV"/>
     </enums>
-    <enums name="VkGeometryInstanceFlagBitsNV" type="bitmask">
-        <enum bitpos="0" name="VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NV"/>
-        <enum bitpos="1" name="VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_NV"/>
-        <enum bitpos="2" name="VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_NV"/>
-        <enum bitpos="3" name="VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_NV"/>
+    <enums name="VkGeometryInstanceFlagBitsKHR" type="bitmask">
+        <enum bitpos="0" name="VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR"/>
+        <enum bitpos="1" name="VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_KHR"/>
+        <enum bitpos="2" name="VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR"/>
+        <enum bitpos="3" name="VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR"/>
     </enums>
-    <enums name="VkGeometryFlagBitsNV" type="bitmask">
-        <enum bitpos="0" name="VK_GEOMETRY_OPAQUE_BIT_NV"/>
-        <enum bitpos="1" name="VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_NV"/>
+    <enums name="VkGeometryFlagBitsKHR" type="bitmask">
+        <enum bitpos="0" name="VK_GEOMETRY_OPAQUE_BIT_KHR"/>
+        <enum bitpos="1" name="VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR"/>
     </enums>
-    <enums name="VkBuildAccelerationStructureFlagBitsNV" type="bitmask">
-        <enum bitpos="0" name="VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_NV"/>
-        <enum bitpos="1" name="VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_NV"/>
-        <enum bitpos="2" name="VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_NV"/>
-        <enum bitpos="3" name="VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_NV"/>
-        <enum bitpos="4" name="VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_NV"/>
+    <enums name="VkBuildAccelerationStructureFlagBitsKHR" type="bitmask">
+        <enum bitpos="0" name="VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR"/>
+        <enum bitpos="1" name="VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR"/>
+        <enum bitpos="2" name="VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR"/>
+        <enum bitpos="3" name="VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR"/>
+        <enum bitpos="4" name="VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR"/>
     </enums>
-    <enums name="VkCopyAccelerationStructureModeNV" type="enum">
-        <enum value="0" name="VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV"/>
-        <enum value="1" name="VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV"/>
+    <enums name="VkCopyAccelerationStructureModeKHR" type="enum">
+        <enum value="0" name="VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR"/>
+        <enum value="1" name="VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR"/>
+        <enum value="2" name="VK_COPY_ACCELERATION_STRUCTURE_MODE_SERIALIZE_KHR"/>
+        <enum value="3" name="VK_COPY_ACCELERATION_STRUCTURE_MODE_DESERIALIZE_KHR"/>
     </enums>
-    <enums name="VkAccelerationStructureTypeNV" type="enum">
-        <enum value="0" name="VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV"/>
-        <enum value="1" name="VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV"/>
+    <enums name="VkAccelerationStructureTypeKHR" type="enum">
+        <enum value="0" name="VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR"/>
+        <enum value="1" name="VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR"/>
     </enums>
-    <enums name="VkGeometryTypeNV" type="enum">
-        <enum value="0" name="VK_GEOMETRY_TYPE_TRIANGLES_NV"/>
-        <enum value="1" name="VK_GEOMETRY_TYPE_AABBS_NV"/>
+    <enums name="VkGeometryTypeKHR" type="enum">
+        <enum value="0" name="VK_GEOMETRY_TYPE_TRIANGLES_KHR"/>
+        <enum value="1" name="VK_GEOMETRY_TYPE_AABBS_KHR"/>
     </enums>
-    <enums name="VkAccelerationStructureMemoryRequirementsTypeNV" type="enum">
-        <enum value="0" name="VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV"/>
-        <enum value="1" name="VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV"/>
-        <enum value="2" name="VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV"/>
+    <enums name="VkAccelerationStructureMemoryRequirementsTypeKHR" type="enum">
+        <enum value="0" name="VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR"/>
+        <enum value="1" name="VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR"/>
+        <enum value="2" name="VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_KHR"/>
     </enums>
-    <enums name="VkRayTracingShaderGroupTypeNV" type="enum">
-        <enum value="0" name="VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV"/>
-        <enum value="1" name="VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_NV"/>
-        <enum value="2" name="VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV"/>
+    <enums name="VkAccelerationStructureBuildTypeKHR" type="enum">
+        <enum value="0" name="VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR"/>
+        <enum value="1" name="VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR"/>
+        <enum value="2" name="VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_OR_DEVICE_KHR"/>
+    </enums>
+    <enums name="VkRayTracingShaderGroupTypeKHR" type="enum">
+        <enum value="0" name="VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR"/>
+        <enum value="1" name="VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR"/>
+        <enum value="2" name="VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR"/>
     </enums>
     <enums name="VkMemoryOverallocationBehaviorAMD" type="enum">
         <enum value="0"     name="VK_MEMORY_OVERALLOCATION_BEHAVIOR_DEFAULT_AMD"/>
@@ -5774,6 +6040,11 @@
         <enum value="9"     name="VK_COMPONENT_TYPE_UINT32_NV"/>
         <enum value="10"    name="VK_COMPONENT_TYPE_UINT64_NV"/>
     </enums>
+    <enums name="VkDeviceDiagnosticsConfigFlagBitsNV" type="bitmask">
+        <enum bitpos="0" name="VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_SHADER_DEBUG_INFO_BIT_NV"/>
+        <enum bitpos="1" name="VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_RESOURCE_TRACKING_BIT_NV"/>
+        <enum bitpos="2" name="VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_AUTOMATIC_CHECKPOINTS_BIT_NV"/>
+    </enums>
     <enums name="VkPipelineCreationFeedbackFlagBitsEXT" type="bitmask">
         <enum bitpos="0"    name="VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT"/>
         <enum bitpos="1"    name="VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT"/>
@@ -5949,7 +6220,7 @@
             <param optional="true" externsync="true"><type>VkDevice</type> <name>device</name></param>
             <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
         </command>
-        <command successcodes="VK_SUCCESS">
+        <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY">
             <proto><type>VkResult</type> <name>vkEnumerateInstanceVersion</name></proto>
             <param><type>uint32_t</type>* <name>pApiVersion</name></param>
         </command>
@@ -6302,7 +6573,7 @@
             <param><type>uint32_t</type> <name>srcCacheCount</name></param>
             <param len="srcCacheCount">const <type>VkPipelineCache</type>* <name>pSrcCaches</name></param>
         </command>
-        <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_INVALID_SHADER_NV">
+        <command successcodes="VK_SUCCESS,VK_PIPELINE_COMPILE_REQUIRED_EXT" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_INVALID_SHADER_NV">
             <proto><type>VkResult</type> <name>vkCreateGraphicsPipelines</name></proto>
             <param><type>VkDevice</type> <name>device</name></param>
             <param optional="true"><type>VkPipelineCache</type> <name>pipelineCache</name></param>
@@ -6311,7 +6582,7 @@
             <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
             <param len="createInfoCount"><type>VkPipeline</type>* <name>pPipelines</name></param>
         </command>
-        <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_INVALID_SHADER_NV">
+        <command successcodes="VK_SUCCESS,VK_PIPELINE_COMPILE_REQUIRED_EXT" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_INVALID_SHADER_NV">
             <proto><type>VkResult</type> <name>vkCreateComputePipelines</name></proto>
             <param><type>VkDevice</type> <name>device</name></param>
             <param optional="true"><type>VkPipelineCache</type> <name>pipelineCache</name></param>
@@ -7111,63 +7382,42 @@
             <param><type>HANDLE</type>* <name>pHandle</name></param>
         </command>
         <command queues="graphics,compute" renderpass="inside" cmdbufferlevel="primary,secondary">
-            <proto><type>void</type> <name>vkCmdProcessCommandsNVX</name></proto>
+            <proto><type>void</type> <name>vkCmdExecuteGeneratedCommandsNV</name></proto>
             <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
-            <param>const <type>VkCmdProcessCommandsInfoNVX</type>* <name>pProcessCommandsInfo</name></param>
+            <param><type>VkBool32</type> <name>isPreprocessed</name></param>
+            <param>const <type>VkGeneratedCommandsInfoNV</type>* <name>pGeneratedCommandsInfo</name></param>
         </command>
-        <command queues="graphics,compute" renderpass="inside" cmdbufferlevel="secondary">
-            <proto><type>void</type> <name>vkCmdReserveSpaceForCommandsNVX</name></proto>
+        <command queues="graphics,compute" renderpass="outside" cmdbufferlevel="primary,secondary">
+            <proto><type>void</type> <name>vkCmdPreprocessGeneratedCommandsNV</name></proto>
             <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
-            <param>const <type>VkCmdReserveSpaceForCommandsInfoNVX</type>* <name>pReserveSpaceInfo</name></param>
+            <param>const <type>VkGeneratedCommandsInfoNV</type>* <name>pGeneratedCommandsInfo</name></param>
         </command>
-        <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
-            <proto><type>VkResult</type> <name>vkCreateIndirectCommandsLayoutNVX</name></proto>
-            <param><type>VkDevice</type> <name>device</name></param>
-            <param>const <type>VkIndirectCommandsLayoutCreateInfoNVX</type>* <name>pCreateInfo</name></param>
-            <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
-            <param><type>VkIndirectCommandsLayoutNVX</type>* <name>pIndirectCommandsLayout</name></param>
+        <command queues="graphics,compute" renderpass="both" cmdbufferlevel="primary,secondary">
+            <proto><type>void</type> <name>vkCmdBindPipelineShaderGroupNV</name></proto>
+            <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+            <param><type>VkPipelineBindPoint</type> <name>pipelineBindPoint</name></param>
+            <param><type>VkPipeline</type> <name>pipeline</name></param>
+            <param><type>uint32_t</type> <name>groupIndex</name></param>
         </command>
         <command>
-            <proto><type>void</type> <name>vkDestroyIndirectCommandsLayoutNVX</name></proto>
+            <proto><type>void</type> <name>vkGetGeneratedCommandsMemoryRequirementsNV</name></proto>
             <param><type>VkDevice</type> <name>device</name></param>
-            <param><type>VkIndirectCommandsLayoutNVX</type> <name>indirectCommandsLayout</name></param>
-            <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+            <param>const <type>VkGeneratedCommandsMemoryRequirementsInfoNV</type>* <name>pInfo</name></param>
+            <param><type>VkMemoryRequirements2</type>* <name>pMemoryRequirements</name></param>
         </command>
         <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
-            <proto><type>VkResult</type> <name>vkCreateObjectTableNVX</name></proto>
+            <proto><type>VkResult</type> <name>vkCreateIndirectCommandsLayoutNV</name></proto>
             <param><type>VkDevice</type> <name>device</name></param>
-            <param>const <type>VkObjectTableCreateInfoNVX</type>* <name>pCreateInfo</name></param>
+            <param>const <type>VkIndirectCommandsLayoutCreateInfoNV</type>* <name>pCreateInfo</name></param>
             <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
-            <param><type>VkObjectTableNVX</type>* <name>pObjectTable</name></param>
+            <param><type>VkIndirectCommandsLayoutNV</type>* <name>pIndirectCommandsLayout</name></param>
         </command>
         <command>
-            <proto><type>void</type> <name>vkDestroyObjectTableNVX</name></proto>
+            <proto><type>void</type> <name>vkDestroyIndirectCommandsLayoutNV</name></proto>
             <param><type>VkDevice</type> <name>device</name></param>
-            <param externsync="true"><type>VkObjectTableNVX</type> <name>objectTable</name></param>
+            <param><type>VkIndirectCommandsLayoutNV</type> <name>indirectCommandsLayout</name></param>
             <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
         </command>
-        <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
-            <proto><type>VkResult</type> <name>vkRegisterObjectsNVX</name></proto>
-            <param><type>VkDevice</type> <name>device</name></param>
-            <param externsync="true"><type>VkObjectTableNVX</type> <name>objectTable</name></param>
-            <param><type>uint32_t</type> <name>objectCount</name></param>
-            <param len="objectCount">const <type>VkObjectTableEntryNVX</type>* const*    <name>ppObjectTableEntries</name></param>
-            <param len="objectCount">const <type>uint32_t</type>* <name>pObjectIndices</name></param>
-        </command>
-        <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
-            <proto><type>VkResult</type> <name>vkUnregisterObjectsNVX</name></proto>
-            <param><type>VkDevice</type> <name>device</name></param>
-            <param externsync="true"><type>VkObjectTableNVX</type> <name>objectTable</name></param>
-            <param><type>uint32_t</type> <name>objectCount</name></param>
-            <param len="objectCount">const <type>VkObjectEntryTypeNVX</type>* <name>pObjectEntryTypes</name></param>
-            <param len="objectCount">const <type>uint32_t</type>* <name>pObjectIndices</name></param>
-        </command>
-        <command>
-            <proto><type>void</type> <name>vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX</name></proto>
-            <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
-            <param><type>VkDeviceGeneratedCommandsFeaturesNVX</type>* <name>pFeatures</name></param>
-            <param><type>VkDeviceGeneratedCommandsLimitsNVX</type>* <name>pLimits</name></param>
-        </command>
         <command>
             <proto><type>void</type> <name>vkGetPhysicalDeviceFeatures2</name></proto>
             <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
@@ -8006,11 +8256,18 @@
             <param><type>VkAccelerationStructureNV</type>* <name>pAccelerationStructure</name></param>
         </command>
         <command>
-            <proto><type>void</type> <name>vkDestroyAccelerationStructureNV</name></proto>
+            <proto><type>void</type> <name>vkDestroyAccelerationStructureKHR</name></proto>
             <param><type>VkDevice</type> <name>device</name></param>
-            <param><type>VkAccelerationStructureNV</type> <name>accelerationStructure</name></param>
+            <param><type>VkAccelerationStructureKHR</type> <name>accelerationStructure</name></param>
             <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
         </command>
+        <command name="vkDestroyAccelerationStructureNV"                    alias="vkDestroyAccelerationStructureKHR"/>
+        <command>
+            <proto><type>void</type> <name>vkGetAccelerationStructureMemoryRequirementsKHR</name></proto>
+            <param><type>VkDevice</type> <name>device</name></param>
+            <param>const <type>VkAccelerationStructureMemoryRequirementsInfoKHR</type>* <name>pInfo</name></param>
+            <param><type>VkMemoryRequirements2</type>* <name>pMemoryRequirements</name></param>
+        </command>
         <command>
             <proto><type>void</type> <name>vkGetAccelerationStructureMemoryRequirementsNV</name></proto>
             <param><type>VkDevice</type> <name>device</name></param>
@@ -8018,27 +8275,59 @@
             <param><type>VkMemoryRequirements2KHR</type>* <name>pMemoryRequirements</name></param>
         </command>
         <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
-            <proto><type>VkResult</type> <name>vkBindAccelerationStructureMemoryNV</name></proto>
+            <proto><type>VkResult</type> <name>vkBindAccelerationStructureMemoryKHR</name></proto>
             <param><type>VkDevice</type> <name>device</name></param>
             <param><type>uint32_t</type> <name>bindInfoCount</name></param>
-            <param len="bindInfoCount">const <type>VkBindAccelerationStructureMemoryInfoNV</type>* <name>pBindInfos</name></param>
+            <param len="bindInfoCount">const <type>VkBindAccelerationStructureMemoryInfoKHR</type>* <name>pBindInfos</name></param>
         </command>
+        <command name="vkBindAccelerationStructureMemoryNV"                 alias="vkBindAccelerationStructureMemoryKHR"/>
         <command queues="compute" renderpass="outside" cmdbufferlevel="primary,secondary">
             <proto><type>void</type> <name>vkCmdCopyAccelerationStructureNV</name></proto>
             <param><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
-            <param><type>VkAccelerationStructureNV</type> <name>dst</name></param>
-            <param><type>VkAccelerationStructureNV</type> <name>src</name></param>
-            <param><type>VkCopyAccelerationStructureModeNV</type> <name>mode</name></param>
+            <param><type>VkAccelerationStructureKHR</type> <name>dst</name></param>
+            <param><type>VkAccelerationStructureKHR</type> <name>src</name></param>
+            <param><type>VkCopyAccelerationStructureModeKHR</type> <name>mode</name></param>
         </command>
         <command queues="compute" renderpass="outside" cmdbufferlevel="primary,secondary">
-            <proto><type>void</type> <name>vkCmdWriteAccelerationStructuresPropertiesNV</name></proto>
+            <proto><type>void</type> <name>vkCmdCopyAccelerationStructureKHR</name></proto>
+            <param><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+            <param>const <type>VkCopyAccelerationStructureInfoKHR</type>* <name>pInfo</name></param>
+        </command>
+        <command successcodes="VK_SUCCESS,VK_OPERATION_DEFERRED_KHR,VK_OPERATION_NOT_DEFERRED_KHR" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+            <proto><type>VkResult</type> <name>vkCopyAccelerationStructureKHR</name></proto>
+            <param><type>VkDevice</type> <name>device</name></param>
+            <param>const <type>VkCopyAccelerationStructureInfoKHR</type>* <name>pInfo</name></param>
+        </command>
+        <command queues="compute" renderpass="outside" cmdbufferlevel="primary,secondary">
+            <proto><type>void</type> <name>vkCmdCopyAccelerationStructureToMemoryKHR</name></proto>
+            <param><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+            <param>const <type>VkCopyAccelerationStructureToMemoryInfoKHR</type>* <name>pInfo</name></param>
+        </command>
+        <command successcodes="VK_SUCCESS,VK_OPERATION_DEFERRED_KHR,VK_OPERATION_NOT_DEFERRED_KHR" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+            <proto><type>VkResult</type> <name>vkCopyAccelerationStructureToMemoryKHR</name></proto>
+            <param><type>VkDevice</type> <name>device</name></param>
+            <param>const <type>VkCopyAccelerationStructureToMemoryInfoKHR</type>* <name>pInfo</name></param>
+        </command>
+        <command queues="compute" renderpass="outside" cmdbufferlevel="primary,secondary">
+            <proto><type>void</type> <name>vkCmdCopyMemoryToAccelerationStructureKHR</name></proto>
+            <param><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+            <param>const <type>VkCopyMemoryToAccelerationStructureInfoKHR</type>* <name>pInfo</name></param>
+        </command>
+        <command successcodes="VK_SUCCESS,VK_OPERATION_DEFERRED_KHR,VK_OPERATION_NOT_DEFERRED_KHR" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+            <proto><type>VkResult</type> <name>vkCopyMemoryToAccelerationStructureKHR</name></proto>
+            <param><type>VkDevice</type> <name>device</name></param>
+            <param>const <type>VkCopyMemoryToAccelerationStructureInfoKHR</type>* <name>pInfo</name></param>
+        </command>
+        <command queues="compute" renderpass="outside" cmdbufferlevel="primary,secondary">
+            <proto><type>void</type> <name>vkCmdWriteAccelerationStructuresPropertiesKHR</name></proto>
             <param><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
             <param><type>uint32_t</type> <name>accelerationStructureCount</name></param>
-            <param len="accelerationStructureCount">const <type>VkAccelerationStructureNV</type>* <name>pAccelerationStructures</name></param>
+            <param len="accelerationStructureCount">const <type>VkAccelerationStructureKHR</type>* <name>pAccelerationStructures</name></param>
             <param><type>VkQueryType</type> <name>queryType</name></param>
             <param><type>VkQueryPool</type> <name>queryPool</name></param>
             <param><type>uint32_t</type> <name>firstQuery</name></param>
         </command>
+        <command name="vkCmdWriteAccelerationStructuresPropertiesNV"        alias="vkCmdWriteAccelerationStructuresPropertiesKHR"/>
         <command queues="compute" renderpass="outside" cmdbufferlevel="primary,secondary">
             <proto><type>void</type> <name>vkCmdBuildAccelerationStructureNV</name></proto>
             <param><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
@@ -8046,11 +8335,32 @@
             <param optional="true"><type>VkBuffer</type> <name>instanceData</name></param>
             <param><type>VkDeviceSize</type> <name>instanceOffset</name></param>
             <param><type>VkBool32</type> <name>update</name></param>
-            <param><type>VkAccelerationStructureNV</type> <name>dst</name></param>
-            <param optional="true"><type>VkAccelerationStructureNV</type> <name>src</name></param>
+            <param><type>VkAccelerationStructureKHR</type> <name>dst</name></param>
+            <param optional="true"><type>VkAccelerationStructureKHR</type> <name>src</name></param>
             <param><type>VkBuffer</type> <name>scratch</name></param>
             <param><type>VkDeviceSize</type> <name>scratchOffset</name></param>
         </command>
+        <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+            <proto><type>VkResult</type> <name>vkWriteAccelerationStructuresPropertiesKHR</name></proto>
+            <param><type>VkDevice</type> <name>device</name></param>
+            <param><type>uint32_t</type> <name>accelerationStructureCount</name></param>
+            <param len="accelerationStructureCount">const <type>VkAccelerationStructureKHR</type>* <name>pAccelerationStructures</name></param>
+            <param><type>VkQueryType</type>  <name>queryType</name></param>
+            <param><type>size_t</type>       <name>dataSize</name></param>
+            <param len="dataSize"><type>void</type>* <name>pData</name></param>
+            <param><type>size_t</type> <name>stride</name></param>
+        </command>
+        <command queues="compute" renderpass="outside" cmdbufferlevel="primary,secondary">
+            <proto><type>void</type> <name>vkCmdTraceRaysKHR</name></proto>
+            <param><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+            <param>const <type>VkStridedBufferRegionKHR</type>* <name>pRaygenShaderBindingTable</name></param>
+            <param>const <type>VkStridedBufferRegionKHR</type>* <name>pMissShaderBindingTable</name></param>
+            <param>const <type>VkStridedBufferRegionKHR</type>* <name>pHitShaderBindingTable</name></param>
+            <param>const <type>VkStridedBufferRegionKHR</type>* <name>pCallableShaderBindingTable</name></param>
+            <param><type>uint32_t</type> <name>width</name></param>
+            <param><type>uint32_t</type> <name>height</name></param>
+            <param><type>uint32_t</type> <name>depth</name></param>
+        </command>
         <command queues="compute" renderpass="outside" cmdbufferlevel="primary,secondary">
             <proto><type>void</type> <name>vkCmdTraceRaysNV</name></proto>
             <param><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
@@ -8070,7 +8380,17 @@
             <param><type>uint32_t</type> <name>depth</name></param>
         </command>
         <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
-            <proto><type>VkResult</type> <name>vkGetRayTracingShaderGroupHandlesNV</name></proto>
+            <proto><type>VkResult</type> <name>vkGetRayTracingShaderGroupHandlesKHR</name></proto>
+            <param><type>VkDevice</type> <name>device</name></param>
+            <param><type>VkPipeline</type> <name>pipeline</name></param>
+            <param><type>uint32_t</type> <name>firstGroup</name></param>
+            <param><type>uint32_t</type> <name>groupCount</name></param>
+            <param><type>size_t</type> <name>dataSize</name></param>
+            <param len="dataSize"><type>void</type>* <name>pData</name></param>
+        </command>
+        <command name="vkGetRayTracingShaderGroupHandlesNV"                 alias="vkGetRayTracingShaderGroupHandlesKHR"/>
+        <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+            <proto><type>VkResult</type> <name>vkGetRayTracingCaptureReplayShaderGroupHandlesKHR</name></proto>
             <param><type>VkDevice</type> <name>device</name></param>
             <param><type>VkPipeline</type> <name>pipeline</name></param>
             <param><type>uint32_t</type> <name>firstGroup</name></param>
@@ -8081,11 +8401,11 @@
         <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
             <proto><type>VkResult</type> <name>vkGetAccelerationStructureHandleNV</name></proto>
             <param><type>VkDevice</type> <name>device</name></param>
-            <param><type>VkAccelerationStructureNV</type> <name>accelerationStructure</name></param>
+            <param><type>VkAccelerationStructureKHR</type> <name>accelerationStructure</name></param>
             <param><type>size_t</type> <name>dataSize</name></param>
             <param len="dataSize"><type>void</type>* <name>pData</name></param>
         </command>
-        <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_INVALID_SHADER_NV">
+        <command successcodes="VK_SUCCESS,VK_PIPELINE_COMPILE_REQUIRED_EXT" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_INVALID_SHADER_NV">
             <proto><type>VkResult</type> <name>vkCreateRayTracingPipelinesNV</name></proto>
             <param><type>VkDevice</type> <name>device</name></param>
             <param optional="true"><type>VkPipelineCache</type> <name>pipelineCache</name></param>
@@ -8094,17 +8414,47 @@
             <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
             <param len="createInfoCount"><type>VkPipeline</type>* <name>pPipelines</name></param>
         </command>
+        <command successcodes="VK_SUCCESS,VK_OPERATION_DEFERRED_KHR,VK_OPERATION_NOT_DEFERRED_KHR,VK_PIPELINE_COMPILE_REQUIRED_EXT" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS">
+            <proto><type>VkResult</type> <name>vkCreateRayTracingPipelinesKHR</name></proto>
+            <param><type>VkDevice</type> <name>device</name></param>
+            <param optional="true"><type>VkPipelineCache</type> <name>pipelineCache</name></param>
+            <param><type>uint32_t</type> <name>createInfoCount</name></param>
+            <param len="createInfoCount">const <type>VkRayTracingPipelineCreateInfoKHR</type>* <name>pCreateInfos</name></param>
+            <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+            <param len="createInfoCount"><type>VkPipeline</type>* <name>pPipelines</name></param>
+        </command>
         <command successcodes="VK_SUCCESS,VK_INCOMPLETE" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
             <proto><type>VkResult</type> <name>vkGetPhysicalDeviceCooperativeMatrixPropertiesNV</name></proto>
             <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
             <param optional="false,true"><type>uint32_t</type>* <name>pPropertyCount</name></param>
             <param optional="true" len="pPropertyCount"><type>VkCooperativeMatrixPropertiesNV</type>* <name>pProperties</name></param>
         </command>
+        <command queues="compute" renderpass="outside" cmdbufferlevel="primary,secondary">
+            <proto><type>void</type> <name>vkCmdTraceRaysIndirectKHR</name></proto>
+            <param><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+            <param>const <type>VkStridedBufferRegionKHR</type>* <name>pRaygenShaderBindingTable</name></param>
+            <param>const <type>VkStridedBufferRegionKHR</type>* <name>pMissShaderBindingTable</name></param>
+            <param>const <type>VkStridedBufferRegionKHR</type>* <name>pHitShaderBindingTable</name></param>
+            <param>const <type>VkStridedBufferRegionKHR</type>* <name>pCallableShaderBindingTable</name></param>
+            <param><type>VkBuffer</type> <name>buffer</name></param>
+            <param><type>VkDeviceSize</type> <name>offset</name></param>
+        </command>
+        <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_INCOMPATIBLE_VERSION_KHR">
+            <proto><type>VkResult</type> <name>vkGetDeviceAccelerationStructureCompatibilityKHR</name></proto>
+            <param><type>VkDevice</type> <name>device</name></param>
+            <param>const <type>VkAccelerationStructureVersionKHR</type>* <name>version</name></param>
+        </command>
         <command>
             <proto><type>uint32_t</type> <name>vkGetImageViewHandleNVX</name></proto>
             <param><type>VkDevice</type> <name>device</name></param>
             <param>const <type>VkImageViewHandleInfoNVX</type>* <name>pInfo</name></param>
         </command>
+        <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_UNKNOWN">
+            <proto><type>VkResult</type> <name>vkGetImageViewAddressNVX</name></proto>
+            <param><type>VkDevice</type> <name>device</name></param>
+            <param><type>VkImageView</type> <name>imageView</name></param>
+            <param><type>VkImageViewAddressPropertiesNVX</type>* <name>pProperties</name></param>
+        </command>
         <command successcodes="VK_SUCCESS,VK_INCOMPLETE" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_SURFACE_LOST_KHR">
             <proto><type>VkResult</type> <name>vkGetPhysicalDeviceSurfacePresentModes2EXT</name></proto>
             <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
@@ -8268,6 +8618,67 @@
             <param optional="false,true"><type>uint32_t</type>* <name>pToolCount</name></param>
             <param optional="true" len="pToolCount"><type>VkPhysicalDeviceToolPropertiesEXT</type>* <name>pToolProperties</name></param>
         </command>
+        <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS_KHR">
+            <proto><type>VkResult</type> <name>vkCreateAccelerationStructureKHR</name></proto>
+            <param><type>VkDevice</type>                                           <name>device</name></param>
+            <param>const <type>VkAccelerationStructureCreateInfoKHR</type>*        <name>pCreateInfo</name></param>
+            <param optional="true">const <type>VkAllocationCallbacks</type>*       <name>pAllocator</name></param>
+            <param><type>VkAccelerationStructureKHR</type>*                        <name>pAccelerationStructure</name></param>
+        </command>
+        <command queues="compute" renderpass="outside" cmdbufferlevel="primary,secondary">
+            <proto><type>void</type> <name>vkCmdBuildAccelerationStructureKHR</name></proto>
+            <param><type>VkCommandBuffer</type>                                    <name>commandBuffer</name></param>
+            <param><type>uint32_t</type> <name>infoCount</name></param>
+            <param len="infoCount">const <type>VkAccelerationStructureBuildGeometryInfoKHR</type>* <name>pInfos</name></param>
+            <param len="infoCount">const <type>VkAccelerationStructureBuildOffsetInfoKHR</type>* const* <name>ppOffsetInfos</name></param>
+        </command>
+        <command queues="compute" renderpass="outside" cmdbufferlevel="primary,secondary">
+            <proto><type>void</type> <name>vkCmdBuildAccelerationStructureIndirectKHR</name></proto>
+            <param><type>VkCommandBuffer</type>                                    <name>commandBuffer</name></param>
+            <param>const <type>VkAccelerationStructureBuildGeometryInfoKHR</type>* <name>pInfo</name></param>
+            <param><type>VkBuffer</type>                                           <name>indirectBuffer</name></param>
+            <param><type>VkDeviceSize</type>                                       <name>indirectOffset</name></param>
+            <param><type>uint32_t</type>                                           <name>indirectStride</name></param>
+        </command>
+        <command successcodes="VK_SUCCESS,VK_OPERATION_DEFERRED_KHR,VK_OPERATION_NOT_DEFERRED_KHR" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+            <proto><type>VkResult</type> <name>vkBuildAccelerationStructureKHR</name></proto>
+            <param><type>VkDevice</type>                                           <name>device</name></param>
+            <param><type>uint32_t</type> <name>infoCount</name></param>
+            <param len="infoCount">const <type>VkAccelerationStructureBuildGeometryInfoKHR</type>* <name>pInfos</name></param>
+            <param len="infoCount">const <type>VkAccelerationStructureBuildOffsetInfoKHR</type>* const* <name>ppOffsetInfos</name></param>
+        </command>
+        <command>
+            <proto><type>VkDeviceAddress</type> <name>vkGetAccelerationStructureDeviceAddressKHR</name></proto>
+            <param><type>VkDevice</type> <name>device</name></param>
+            <param>const <type>VkAccelerationStructureDeviceAddressInfoKHR</type>* <name>pInfo</name></param>
+        </command>
+        <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY">
+            <proto><type>VkResult</type> <name>vkCreateDeferredOperationKHR</name></proto>
+            <param><type>VkDevice</type> <name>device</name></param>
+            <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+            <param><type>VkDeferredOperationKHR</type>* <name>pDeferredOperation</name></param>
+        </command>
+        <command>
+            <proto><type>void</type> <name>vkDestroyDeferredOperationKHR</name></proto>
+            <param><type>VkDevice</type> <name>device</name></param>
+            <param><type>VkDeferredOperationKHR</type> <name>operation</name></param>
+            <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+        </command>
+        <command>
+           <proto><type>uint32_t</type> <name>vkGetDeferredOperationMaxConcurrencyKHR</name></proto>
+           <param><type>VkDevice</type> <name>device</name></param>
+           <param><type>VkDeferredOperationKHR</type> <name>operation</name></param>
+        </command>
+        <command successcodes="VK_SUCCESS,VK_NOT_READY">
+           <proto><type>VkResult</type> <name>vkGetDeferredOperationResultKHR</name></proto>
+           <param><type>VkDevice</type> <name>device</name></param>
+           <param><type>VkDeferredOperationKHR</type> <name>operation</name></param>
+        </command>
+        <command successcodes="VK_SUCCESS,VK_THREAD_DONE_KHR,VK_THREAD_IDLE_KHR" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+           <proto><type>VkResult</type> <name>vkDeferredOperationJoinKHR</name></proto>
+           <param><type>VkDevice</type> <name>device</name></param>
+           <param><type>VkDeferredOperationKHR</type> <name>operation</name></param>
+        </command>
     </commands>
 
     <feature api="vulkan" name="VK_VERSION_1_0" number="1.0" comment="Vulkan core API interface definitions">
@@ -9183,6 +9594,7 @@
                 <enum value="8"                                                 name="VK_ANDROID_NATIVE_BUFFER_SPEC_VERSION"/>
                 <enum value="11"                                                name="VK_ANDROID_NATIVE_BUFFER_NUMBER"/>
                 <enum value="&quot;VK_ANDROID_native_buffer&quot;"              name="VK_ANDROID_NATIVE_BUFFER_NAME"/>
+                <enum                                                           name="VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME" alias="VK_ANDROID_NATIVE_BUFFER_NAME"/>
                 <enum offset="0" extends="VkStructureType"                      name="VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID"/>
                 <enum offset="1" extends="VkStructureType"                      name="VK_STRUCTURE_TYPE_SWAPCHAIN_IMAGE_CREATE_INFO_ANDROID"/>
                 <enum offset="2" extends="VkStructureType"                      name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENTATION_PROPERTIES_ANDROID"/>
@@ -9311,7 +9723,10 @@
                 <enum bitpos="6" extends="VkQueueFlagBits"              name="VK_QUEUE_RESERVED_6_BIT_KHR"/>
                 <enum bitpos="27" extends="VkPipelineStageFlagBits"     name="VK_PIPELINE_STAGE_RESERVED_27_BIT_KHR"/>
                 <enum bitpos="30" extends="VkAccessFlagBits"            name="VK_ACCESS_RESERVED_30_BIT_KHR"/>
+                    <!-- Comment this out for now to avoid warning messages.
+                         The extension will probably change to avoid it.
                 <enum bitpos="31" extends="VkAccessFlagBits"            name="VK_ACCESS_RESERVED_31_BIT_KHR"/>
+                    -->
                 <enum bitpos="15" extends="VkBufferUsageFlagBits"       name="VK_BUFFER_USAGE_RESERVED_15_BIT_KHR"/>
                 <enum bitpos="16" extends="VkBufferUsageFlagBits"       name="VK_BUFFER_USAGE_RESERVED_16_BIT_KHR"/>
                 <enum bitpos="13" extends="VkImageUsageFlagBits"        name="VK_IMAGE_USAGE_RESERVED_13_BIT_KHR"/>
@@ -9405,11 +9820,14 @@
         </extension>
         <extension name="VK_NVX_image_view_handle" number="31" type="device" author="NVX" contact="Eric Werness @ewerness" supported="vulkan">
             <require>
-                <enum value="1"                                                 name="VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION"/>
+                <enum value="2"                                                 name="VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION"/>
                 <enum value="&quot;VK_NVX_image_view_handle&quot;"              name="VK_NVX_IMAGE_VIEW_HANDLE_EXTENSION_NAME"/>
                 <enum offset="0" extends="VkStructureType"                      name="VK_STRUCTURE_TYPE_IMAGE_VIEW_HANDLE_INFO_NVX"/>
+                <enum offset="1" extends="VkStructureType"                      name="VK_STRUCTURE_TYPE_IMAGE_VIEW_ADDRESS_PROPERTIES_NVX"/>
                 <type name="VkImageViewHandleInfoNVX"/>
+                <type name="VkImageViewAddressPropertiesNVX"/>
                 <command name="vkGetImageViewHandleNVX"/>
+                <command name="vkGetImageViewAddressNVX"/>
             </require>
         </extension>
         <extension name="VK_AMD_extension_32" number="32" author="AMD" contact="Daniel Rakos @drakos-amd" supported="disabled">
@@ -10053,52 +10471,10 @@
                 <enum extends="VkDebugReportObjectTypeEXT"                  name="VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR_EXT" alias="VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT"/>
             </require>
         </extension>
-        <extension name="VK_NVX_device_generated_commands" number="87" type="device" author="NVX" contact="Christoph Kubisch @pixeljetstream" supported="vulkan">
+        <extension name="VK_NVX_device_generated_commands" number="87" type="device" author="NVX" contact="Christoph Kubisch @pixeljetstream" supported="disabled">
             <require>
                 <enum value="3"                                             name="VK_NVX_DEVICE_GENERATED_COMMANDS_SPEC_VERSION"/>
                 <enum value="&quot;VK_NVX_device_generated_commands&quot;"  name="VK_NVX_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME"/>
-                <enum offset="0" extends="VkStructureType"                  name="VK_STRUCTURE_TYPE_OBJECT_TABLE_CREATE_INFO_NVX"/>
-                <enum offset="1" extends="VkStructureType"                  name="VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NVX"/>
-                <enum offset="2" extends="VkStructureType"                  name="VK_STRUCTURE_TYPE_CMD_PROCESS_COMMANDS_INFO_NVX"/>
-                <enum offset="3" extends="VkStructureType"                  name="VK_STRUCTURE_TYPE_CMD_RESERVE_SPACE_FOR_COMMANDS_INFO_NVX"/>
-                <enum offset="4" extends="VkStructureType"                  name="VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_LIMITS_NVX"/>
-                <enum offset="5" extends="VkStructureType"                  name="VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_FEATURES_NVX"/>
-                <enum bitpos="17" extends="VkPipelineStageFlagBits"         name="VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX"/>
-                <enum bitpos="17" extends="VkAccessFlagBits"                name="VK_ACCESS_COMMAND_PROCESS_READ_BIT_NVX"/>
-                <enum bitpos="18" extends="VkAccessFlagBits"                name="VK_ACCESS_COMMAND_PROCESS_WRITE_BIT_NVX"/>
-                <enum offset="0" extends="VkObjectType"                     name="VK_OBJECT_TYPE_OBJECT_TABLE_NVX"               comment="VkobjectTableNVX"/>
-                <enum offset="1" extends="VkObjectType"                     name="VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX"   comment="VkIndirectCommandsLayoutNVX"/>
-                <type name="VkObjectTableNVX"/>
-                <type name="VkIndirectCommandsLayoutNVX"/>
-                <type name="VkIndirectCommandsLayoutUsageFlagsNVX"/>
-                <type name="VkObjectEntryUsageFlagsNVX"/>
-                <type name="VkIndirectCommandsLayoutUsageFlagBitsNVX"/>
-                <type name="VkIndirectCommandsTokenTypeNVX"/>
-                <type name="VkObjectEntryUsageFlagBitsNVX"/>
-                <type name="VkObjectEntryTypeNVX"/>
-                <type name="VkDeviceGeneratedCommandsFeaturesNVX"/>
-                <type name="VkDeviceGeneratedCommandsLimitsNVX"/>
-                <type name="VkIndirectCommandsTokenNVX"/>
-                <type name="VkIndirectCommandsLayoutTokenNVX"/>
-                <type name="VkIndirectCommandsLayoutCreateInfoNVX"/>
-                <type name="VkCmdProcessCommandsInfoNVX"/>
-                <type name="VkCmdReserveSpaceForCommandsInfoNVX"/>
-                <type name="VkObjectTableCreateInfoNVX"/>
-                <type name="VkObjectTableEntryNVX"/>
-                <type name="VkObjectTablePipelineEntryNVX"/>
-                <type name="VkObjectTableDescriptorSetEntryNVX"/>
-                <type name="VkObjectTableVertexBufferEntryNVX"/>
-                <type name="VkObjectTableIndexBufferEntryNVX"/>
-                <type name="VkObjectTablePushConstantEntryNVX"/>
-                <command name="vkCmdProcessCommandsNVX"/>
-                <command name="vkCmdReserveSpaceForCommandsNVX"/>
-                <command name="vkCreateIndirectCommandsLayoutNVX"/>
-                <command name="vkDestroyIndirectCommandsLayoutNVX"/>
-                <command name="vkCreateObjectTableNVX"/>
-                <command name="vkDestroyObjectTableNVX"/>
-                <command name="vkRegisterObjectsNVX"/>
-                <command name="vkUnregisterObjectsNVX"/>
-                <command name="vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX"/>
             </require>
         </extension>
         <extension name="VK_NV_clip_space_w_scaling" number="88" type="device" author="NV" contact="Eric Werness @ewerness-nv" supported="vulkan">
@@ -10588,7 +10964,7 @@
         </extension>
         <extension name="VK_EXT_debug_utils" number="129" type="instance" author="EXT" contact="Mark Young @marky-lunarg" specialuse="debugging" supported="vulkan">
             <require>
-                <enum value="1"                                             name="VK_EXT_DEBUG_UTILS_SPEC_VERSION"/>
+                <enum value="2"                                             name="VK_EXT_DEBUG_UTILS_SPEC_VERSION"/>
                 <enum value="&quot;VK_EXT_debug_utils&quot;"                name="VK_EXT_DEBUG_UTILS_EXTENSION_NAME"/>
                 <enum offset="0" extends="VkStructureType"                  name="VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT"/>
                 <enum offset="1" extends="VkStructureType"                  name="VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_TAG_INFO_EXT"/>
@@ -10858,16 +11234,122 @@
                 <type name="VkPipelineCoverageToColorStateCreateInfoNV"/>
             </require>
         </extension>
-        <extension name="VK_NV_extension_151" number="151" author="NV" contact="Jeff Bolz @jeffbolznv" supported="disabled">
+        <extension name="VK_KHR_ray_tracing" number="151" type="device" requires="VK_KHR_get_physical_device_properties2,VK_KHR_get_memory_requirements2,VK_EXT_descriptor_indexing,VK_KHR_buffer_device_address,VK_KHR_deferred_host_operations,VK_KHR_pipeline_library" author="KHR" contact="Daniel Koch @dgkoch" platform="provisional" supported="vulkan" provisional="true" sortorder="1" comment="Explicit sort order to require processing after VK_NV_ray_tracing">
             <require>
-                <enum value="0"                                             name="VK_NV_EXTENSION_151_SPEC_VERSION"/>
-                <enum value="&quot;VK_NV_extension_151&quot;"               name="VK_NV_EXTENSION_151_EXTENSION_NAME"/>
-                <enum bitpos="11" extends="VkPipelineCreateFlagBits"        name="VK_PIPELINE_CREATE_EXTENSION_151_BIT0_NV"/>
-                <enum bitpos="29" extends="VkFormatFeatureFlagBits"         name="VK_FORMAT_FEATURE_RESERVED_29_BIT_NV"/>
-                <enum bitpos="14" extends="VkPipelineCreateFlagBits"        name="VK_PIPELINE_CREATE_EXTENSION_151_BIT1_NV"/>
-                <enum bitpos="15" extends="VkPipelineCreateFlagBits"        name="VK_PIPELINE_CREATE_EXTENSION_151_BIT2_NV"/>
-                <enum bitpos="16" extends="VkPipelineCreateFlagBits"        name="VK_PIPELINE_CREATE_EXTENSION_151_BIT3_NV"/>
-                <enum bitpos="17" extends="VkPipelineCreateFlagBits"        name="VK_PIPELINE_CREATE_EXTENSION_151_BIT4_NV"/>
+                <enum value="8"                                             name="VK_KHR_RAY_TRACING_SPEC_VERSION"/>
+                <enum value="&quot;VK_KHR_ray_tracing&quot;"                name="VK_KHR_RAY_TRACING_EXTENSION_NAME"/>
+                <enum                                                       name="VK_SHADER_UNUSED_KHR"/>
+                <enum offset="6"  extends="VkStructureType" extnumber="166" name="VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_KHR"/>
+                <enum offset="7"  extends="VkStructureType" extnumber="166" name="VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR"/>
+                <enum offset="0"  extends="VkStructureType"                 name="VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR"/>
+                <enum offset="1"  extends="VkStructureType"                 name="VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR"/>
+                <enum offset="2"  extends="VkStructureType"                 name="VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR"/>
+                <enum offset="3"  extends="VkStructureType"                 name="VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR"/>
+                <enum offset="4"  extends="VkStructureType"                 name="VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR"/>
+                <enum offset="5"  extends="VkStructureType"                 name="VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR"/>
+                <enum offset="6"  extends="VkStructureType"                 name="VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR"/>
+                <enum offset="8"  extends="VkStructureType"                 name="VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR"/>
+                <enum offset="9"  extends="VkStructureType"                 name="VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_VERSION_KHR"/>
+                <enum offset="10" extends="VkStructureType"                 name="VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR"/>
+                <enum offset="11" extends="VkStructureType"                 name="VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_TO_MEMORY_INFO_KHR"/>
+                <enum offset="12" extends="VkStructureType"                 name="VK_STRUCTURE_TYPE_COPY_MEMORY_TO_ACCELERATION_STRUCTURE_INFO_KHR"/>
+                <enum offset="13" extends="VkStructureType"                 name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_FEATURES_KHR"/>
+                <enum offset="14" extends="VkStructureType"                 name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_KHR"/>
+                <enum offset="15" extends="VkStructureType"                 name="VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR"/>
+                <enum offset="16" extends="VkStructureType"                 name="VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR"/>
+                <enum offset="17" extends="VkStructureType"                 name="VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR"/>
+                <enum offset="18" extends="VkStructureType"                 name="VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_INTERFACE_CREATE_INFO_KHR"/>
+                <enum bitpos="8"  extends="VkShaderStageFlagBits"           name="VK_SHADER_STAGE_RAYGEN_BIT_KHR"/>
+                <enum bitpos="9"  extends="VkShaderStageFlagBits"           name="VK_SHADER_STAGE_ANY_HIT_BIT_KHR"/>
+                <enum bitpos="10" extends="VkShaderStageFlagBits"           name="VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR"/>
+                <enum bitpos="11" extends="VkShaderStageFlagBits"           name="VK_SHADER_STAGE_MISS_BIT_KHR"/>
+                <enum bitpos="12" extends="VkShaderStageFlagBits"           name="VK_SHADER_STAGE_INTERSECTION_BIT_KHR"/>
+                <enum bitpos="13" extends="VkShaderStageFlagBits"           name="VK_SHADER_STAGE_CALLABLE_BIT_KHR"/>
+                <enum bitpos="21" extends="VkPipelineStageFlagBits"         name="VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR"/>
+                <enum bitpos="25" extends="VkPipelineStageFlagBits"         name="VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR"/>
+                <enum bitpos="10" extends="VkBufferUsageFlagBits"           name="VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR"/>
+                <enum offset="0"  extends="VkPipelineBindPoint" extnumber="166" name="VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR"/>
+                <enum offset="0"  extends="VkDescriptorType" extnumber="166" name="VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR"/>
+                <enum bitpos="21" extends="VkAccessFlagBits"                name="VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR"/>
+                <enum bitpos="22" extends="VkAccessFlagBits"                name="VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR"/>
+                <enum offset="0"  extends="VkQueryType" extnumber="166"     name="VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR"/>
+                <enum offset="0"  extends="VkQueryType"                     name="VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR"/>
+                <enum offset="0"  extends="VkObjectType" extnumber="166"    name="VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR"/>
+                <enum offset="0"  extends="VkDebugReportObjectTypeEXT" extnumber="166" name="VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR_EXT"/>
+                <enum offset="0"  extends="VkIndexType" extnumber="166"     name="VK_INDEX_TYPE_NONE_KHR"/>
+                <enum offset="0"  extends="VkGeometryTypeKHR"               name="VK_GEOMETRY_TYPE_INSTANCES_KHR"/>
+                <enum offset="0"  extends="VkResult" dir="-"                name="VK_ERROR_INCOMPATIBLE_VERSION_KHR"/>
+                <enum bitpos="29" extends="VkFormatFeatureFlagBits"         name="VK_FORMAT_FEATURE_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR"/>
+                <enum bitpos="14" extends="VkPipelineCreateFlagBits"        name="VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_ANY_HIT_SHADERS_BIT_KHR"/>
+                <enum bitpos="15" extends="VkPipelineCreateFlagBits"        name="VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_CLOSEST_HIT_SHADERS_BIT_KHR"/>
+                <enum bitpos="16" extends="VkPipelineCreateFlagBits"        name="VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_MISS_SHADERS_BIT_KHR"/>
+                <enum bitpos="17" extends="VkPipelineCreateFlagBits"        name="VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_INTERSECTION_SHADERS_BIT_KHR"/>
+                <enum bitpos="12" extends="VkPipelineCreateFlagBits"        name="VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR"/>
+                <enum bitpos="13" extends="VkPipelineCreateFlagBits"        name="VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR"/>
+                <type name="VkAccelerationStructureTypeKHR"/>
+                <type name="VkDeviceOrHostAddressKHR"/>
+                <type name="VkDeviceOrHostAddressConstKHR"/>
+                <type name="VkAccelerationStructureBuildOffsetInfoKHR"/>
+                <type name="VkRayTracingShaderGroupCreateInfoKHR"/>
+                <type name="VkRayTracingShaderGroupTypeKHR"/>
+                <type name="VkRayTracingPipelineCreateInfoKHR"/>
+                <type name="VkAabbPositionsKHR"/>
+                <type name="VkAccelerationStructureGeometryTrianglesDataKHR"/>
+                <type name="VkTransformMatrixKHR"/>
+                <type name="VkAccelerationStructureBuildGeometryInfoKHR"/>
+                <type name="VkAccelerationStructureBuildTypeKHR"/>
+                <type name="VkAccelerationStructureGeometryAabbsDataKHR"/>
+                <type name="VkAccelerationStructureInstanceKHR"/>
+                <type name="VkAccelerationStructureGeometryInstancesDataKHR"/>
+                <type name="VkAccelerationStructureGeometryDataKHR"/>
+                <type name="VkAccelerationStructureGeometryKHR"/>
+                <type name="VkGeometryFlagsKHR"/>
+                <type name="VkGeometryInstanceFlagsKHR"/>
+                <type name="VkGeometryFlagBitsKHR"/>
+                <type name="VkGeometryInstanceFlagBitsKHR"/>
+                <type name="VkAccelerationStructureCreateGeometryTypeInfoKHR"/>
+                <type name="VkAccelerationStructureCreateInfoKHR"/>
+                <type name="VkAccelerationStructureKHR"/>
+                <type name="VkBuildAccelerationStructureFlagBitsKHR"/>
+                <type name="VkBuildAccelerationStructureFlagsKHR"/>
+                <type name="VkCopyAccelerationStructureModeKHR"/>
+                <type name="VkGeometryTypeKHR"/>
+                <type name="VkBindAccelerationStructureMemoryInfoKHR"/>
+                <type name="VkWriteDescriptorSetAccelerationStructureKHR"/>
+                <type name="VkAccelerationStructureMemoryRequirementsInfoKHR"/>
+                <type name="VkPhysicalDeviceRayTracingFeaturesKHR"/>
+                <type name="VkPhysicalDeviceRayTracingPropertiesKHR"/>
+                <type name="VkAccelerationStructureMemoryRequirementsTypeKHR"/>
+                <type name="VkAccelerationStructureDeviceAddressInfoKHR"/>
+                <type name="VkAccelerationStructureVersionKHR"/>
+                <type name="VkStridedBufferRegionKHR"/>
+                <type name="VkTraceRaysIndirectCommandKHR"/>
+                <type name="VkCopyAccelerationStructureToMemoryInfoKHR"/>
+                <type name="VkCopyMemoryToAccelerationStructureInfoKHR"/>
+                <type name="VkCopyAccelerationStructureInfoKHR"/>
+                <type name="VkRayTracingPipelineInterfaceCreateInfoKHR"/>
+                <command name="vkCreateAccelerationStructureKHR"/>
+                <command name="vkDestroyAccelerationStructureKHR"/>
+                <command name="vkGetAccelerationStructureMemoryRequirementsKHR"/>
+                <command name="vkBindAccelerationStructureMemoryKHR"/>
+                <command name="vkCmdBuildAccelerationStructureKHR"/>
+                <command name="vkCmdBuildAccelerationStructureIndirectKHR"/>
+                <command name="vkBuildAccelerationStructureKHR"/>
+                <command name="vkCopyAccelerationStructureKHR"/>
+                <command name="vkCopyAccelerationStructureToMemoryKHR"/>
+                <command name="vkCopyMemoryToAccelerationStructureKHR"/>
+                <command name="vkWriteAccelerationStructuresPropertiesKHR"/>
+                <command name="vkCmdCopyAccelerationStructureKHR"/>
+                <command name="vkCmdCopyAccelerationStructureToMemoryKHR"/>
+                <command name="vkCmdCopyMemoryToAccelerationStructureKHR"/>
+                <command name="vkCmdTraceRaysKHR"/>
+                <command name="vkCreateRayTracingPipelinesKHR"/>
+                <command name="vkGetRayTracingShaderGroupHandlesKHR"/>
+                <command name="vkGetAccelerationStructureDeviceAddressKHR"/>
+                <command name="vkGetRayTracingCaptureReplayShaderGroupHandlesKHR"/>
+                <command name="vkCmdWriteAccelerationStructuresPropertiesKHR"/>
+                <command name="vkCmdTraceRaysIndirectKHR"/>
+                <command name="vkGetDeviceAccelerationStructureCompatibilityKHR"/>
             </require>
         </extension>
         <extension name="VK_NV_extension_152" number="152" author="NV" contact="Jeff Bolz @jeffbolznv" supported="disabled">
@@ -11127,63 +11609,89 @@
         </extension>
         <extension name="VK_NV_ray_tracing" number="166" type="device" requires="VK_KHR_get_physical_device_properties2,VK_KHR_get_memory_requirements2" author="NV" contact="Eric Werness @ewerness" supported="vulkan">
             <require>
-                <enum value="3"                                          name="VK_NV_RAY_TRACING_SPEC_VERSION"/>
-                <enum value="&quot;VK_NV_ray_tracing&quot;"              name="VK_NV_RAY_TRACING_EXTENSION_NAME"/>
-                <enum                                                    name="VK_SHADER_UNUSED_NV"/>
-                <enum offset="0" extends="VkStructureType"               name="VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_NV"/>
-                <enum offset="1" extends="VkStructureType"               name="VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV"/>
-                <enum offset="3" extends="VkStructureType"               name="VK_STRUCTURE_TYPE_GEOMETRY_NV"/>
-                <enum offset="4" extends="VkStructureType"               name="VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV"/>
-                <enum offset="5" extends="VkStructureType"               name="VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV"/>
-                <enum offset="6" extends="VkStructureType"               name="VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV"/>
-                <enum offset="7" extends="VkStructureType"               name="VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_NV"/>
-                <enum offset="8" extends="VkStructureType"               name="VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV"/>
-                <enum offset="9" extends="VkStructureType"               name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_NV"/>
-                <enum offset="11" extends="VkStructureType"              name="VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV"/>
-                <enum offset="12" extends="VkStructureType"              name="VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV"/>
-                <enum bitpos="8" extends="VkShaderStageFlagBits"         name="VK_SHADER_STAGE_RAYGEN_BIT_NV"/>
-                <enum bitpos="9" extends="VkShaderStageFlagBits"         name="VK_SHADER_STAGE_ANY_HIT_BIT_NV"/>
-                <enum bitpos="10" extends="VkShaderStageFlagBits"        name="VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV"/>
-                <enum bitpos="11" extends="VkShaderStageFlagBits"        name="VK_SHADER_STAGE_MISS_BIT_NV"/>
-                <enum bitpos="12" extends="VkShaderStageFlagBits"        name="VK_SHADER_STAGE_INTERSECTION_BIT_NV"/>
-                <enum bitpos="13" extends="VkShaderStageFlagBits"        name="VK_SHADER_STAGE_CALLABLE_BIT_NV"/>
-                <enum bitpos="21" extends="VkPipelineStageFlagBits"      name="VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_NV"/>
-                <enum bitpos="25" extends="VkPipelineStageFlagBits"      name="VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV"/>
-                <enum bitpos="10" extends="VkBufferUsageFlagBits"        name="VK_BUFFER_USAGE_RAY_TRACING_BIT_NV"/>
-                <enum offset="0" extends="VkPipelineBindPoint"           name="VK_PIPELINE_BIND_POINT_RAY_TRACING_NV"/>
-                <enum offset="0" extends="VkDescriptorType"              name="VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV"/>
-                <enum bitpos="21" extends="VkAccessFlagBits"             name="VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV"/>
-                <enum bitpos="22" extends="VkAccessFlagBits"             name="VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NV"/>
-                <enum offset="0" extends="VkQueryType"                   name="VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV"/>
+                <enum value="3"                               name="VK_NV_RAY_TRACING_SPEC_VERSION"/>
+                <enum value="&quot;VK_NV_ray_tracing&quot;"   name="VK_NV_RAY_TRACING_EXTENSION_NAME"/>
+                <enum                                         name="VK_SHADER_UNUSED_NV"/>
+                <enum offset="0"  extends="VkStructureType"   name="VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_NV"/>
+                <enum offset="1"  extends="VkStructureType"   name="VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV"/>
+                <enum offset="3"  extends="VkStructureType"   name="VK_STRUCTURE_TYPE_GEOMETRY_NV"/>
+                <enum offset="4"  extends="VkStructureType"   name="VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV"/>
+                <enum offset="5"  extends="VkStructureType"   name="VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV"/>
+                <enum extends="VkStructureType"               name="VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV" alias="VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_KHR"/>
+                <enum extends="VkStructureType"               name="VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_NV" alias="VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR"/>
+                <enum offset="8"  extends="VkStructureType"   name="VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV"/>
+                <enum offset="9"  extends="VkStructureType"   name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_NV"/>
+                <enum offset="11" extends="VkStructureType"   name="VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV"/>
+                <enum offset="12" extends="VkStructureType"   name="VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV"/>
+                <enum extends="VkShaderStageFlagBits"         name="VK_SHADER_STAGE_RAYGEN_BIT_NV" alias="VK_SHADER_STAGE_RAYGEN_BIT_KHR"/>
+                <enum extends="VkShaderStageFlagBits"         name="VK_SHADER_STAGE_ANY_HIT_BIT_NV" alias="VK_SHADER_STAGE_ANY_HIT_BIT_KHR"/>
+                <enum extends="VkShaderStageFlagBits"         name="VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV" alias="VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR"/>
+                <enum extends="VkShaderStageFlagBits"         name="VK_SHADER_STAGE_MISS_BIT_NV" alias="VK_SHADER_STAGE_MISS_BIT_KHR"/>
+                <enum extends="VkShaderStageFlagBits"         name="VK_SHADER_STAGE_INTERSECTION_BIT_NV" alias="VK_SHADER_STAGE_INTERSECTION_BIT_KHR"/>
+                <enum extends="VkShaderStageFlagBits"         name="VK_SHADER_STAGE_CALLABLE_BIT_NV" alias="VK_SHADER_STAGE_CALLABLE_BIT_KHR"/>
+                <enum extends="VkPipelineStageFlagBits"       name="VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_NV" alias="VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR"/>
+                <enum extends="VkPipelineStageFlagBits"       name="VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV" alias="VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR"/>
+                <enum extends="VkBufferUsageFlagBits"         name="VK_BUFFER_USAGE_RAY_TRACING_BIT_NV" alias="VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR"/>
+                <enum extends="VkPipelineBindPoint"           name="VK_PIPELINE_BIND_POINT_RAY_TRACING_NV" alias="VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR"/>
+                <enum extends="VkDescriptorType"              name="VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV" alias="VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR"/>
+                <enum extends="VkAccessFlagBits"              name="VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV" alias="VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR"/>
+                <enum extends="VkAccessFlagBits"              name="VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NV" alias="VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR"/>
+                <enum extends="VkQueryType"                   name="VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV" alias="VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR"/>
                 <enum bitpos="5" extends="VkPipelineCreateFlagBits"      name="VK_PIPELINE_CREATE_DEFER_COMPILE_BIT_NV"/>
-                <enum offset="0" extends="VkObjectType"                  name="VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV"/>
-                <enum offset="0" extends="VkDebugReportObjectTypeEXT"    name="VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT"/>
-                <enum offset="0" extends="VkIndexType"                   name="VK_INDEX_TYPE_NONE_NV"/>
-                <type name="VkAccelerationStructureTypeNV"/>
+                <enum extends="VkObjectType"                  name="VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV" alias="VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR"/>
+                <enum extends="VkDebugReportObjectTypeEXT"    name="VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT" alias="VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR_EXT"/>
+                <enum extends="VkIndexType"                   name="VK_INDEX_TYPE_NONE_NV" alias="VK_INDEX_TYPE_NONE_KHR"/>
                 <type name="VkRayTracingShaderGroupCreateInfoNV"/>
                 <type name="VkRayTracingShaderGroupTypeNV"/>
+                <enum extends="VkRayTracingShaderGroupTypeKHR" name="VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV" alias="VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR"/>
+                <enum extends="VkRayTracingShaderGroupTypeKHR" name="VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_NV" alias="VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR"/>
+                <enum extends="VkRayTracingShaderGroupTypeKHR" name="VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV" alias="VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR"/>
                 <type name="VkRayTracingPipelineCreateInfoNV"/>
+                <type name="VkGeometryTypeNV"/>
+                <enum extends="VkGeometryTypeKHR" name="VK_GEOMETRY_TYPE_TRIANGLES_NV" alias="VK_GEOMETRY_TYPE_TRIANGLES_KHR"/>
+                <enum extends="VkGeometryTypeKHR" name="VK_GEOMETRY_TYPE_AABBS_NV" alias="VK_GEOMETRY_TYPE_AABBS_KHR"/>
+                <type name="VkAccelerationStructureTypeNV"/>
+                <enum extends="VkAccelerationStructureTypeKHR" name="VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV" alias="VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR"/>
+                <enum extends="VkAccelerationStructureTypeKHR" name="VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV" alias="VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR"/>
                 <type name="VkGeometryTrianglesNV"/>
                 <type name="VkGeometryAABBNV"/>
                 <type name="VkGeometryDataNV"/>
                 <type name="VkGeometryNV"/>
                 <type name="VkGeometryFlagsNV"/>
-                <type name="VkGeometryInstanceFlagsNV"/>
                 <type name="VkGeometryFlagBitsNV"/>
+                <enum extends="VkGeometryFlagBitsKHR" name="VK_GEOMETRY_OPAQUE_BIT_NV" alias="VK_GEOMETRY_OPAQUE_BIT_KHR"/>
+                <enum extends="VkGeometryFlagBitsKHR" name="VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_NV" alias="VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR"/>
+                <type name="VkGeometryInstanceFlagsNV"/>
                 <type name="VkGeometryInstanceFlagBitsNV"/>
+                <enum extends="VkGeometryInstanceFlagBitsKHR" name="VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NV" alias="VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR"/>
+                <enum extends="VkGeometryInstanceFlagBitsKHR" name="VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_NV" alias="VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_KHR"/>
+                <enum extends="VkGeometryInstanceFlagBitsKHR" name="VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_NV" alias="VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR"/>
+                <enum extends="VkGeometryInstanceFlagBitsKHR" name="VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_NV" alias="VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR"/>
                 <type name="VkAccelerationStructureInfoNV"/>
                 <type name="VkAccelerationStructureCreateInfoNV"/>
                 <type name="VkAccelerationStructureNV"/>
                 <type name="VkBuildAccelerationStructureFlagBitsNV"/>
+                <enum extends="VkBuildAccelerationStructureFlagBitsKHR" name="VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_NV" alias="VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR"/>
+                <enum extends="VkBuildAccelerationStructureFlagBitsKHR" name="VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_NV" alias="VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR"/>
+                <enum extends="VkBuildAccelerationStructureFlagBitsKHR" name="VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_NV" alias="VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR"/>
+                <enum extends="VkBuildAccelerationStructureFlagBitsKHR" name="VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_NV" alias="VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR"/>
+                <enum extends="VkBuildAccelerationStructureFlagBitsKHR" name="VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_NV" alias="VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR"/>
                 <type name="VkBuildAccelerationStructureFlagsNV"/>
                 <type name="VkCopyAccelerationStructureModeNV"/>
-                <type name="VkGeometryTypeNV"/>
+                <enum extends="VkCopyAccelerationStructureModeKHR" name="VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_NV" alias="VK_COPY_ACCELERATION_STRUCTURE_MODE_CLONE_KHR"/>
+                <enum extends="VkCopyAccelerationStructureModeKHR" name="VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_NV" alias="VK_COPY_ACCELERATION_STRUCTURE_MODE_COMPACT_KHR"/>
                 <type name="VkBindAccelerationStructureMemoryInfoNV"/>
                 <type name="VkWriteDescriptorSetAccelerationStructureNV"/>
                 <type name="VkAccelerationStructureMemoryRequirementsInfoNV"/>
                 <type name="VkPhysicalDeviceRayTracingPropertiesNV"/>
                 <type name="VkMemoryRequirements2KHR"/>
                 <type name="VkAccelerationStructureMemoryRequirementsTypeNV"/>
+                <type name="VkTransformMatrixNV"/>
+                <type name="VkAabbPositionsNV"/>
+                <type name="VkAccelerationStructureInstanceNV"/>
+                <enum extends="VkAccelerationStructureMemoryRequirementsTypeKHR" name="VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV" alias="VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR"/>
+                <enum extends="VkAccelerationStructureMemoryRequirementsTypeKHR" name="VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV" alias="VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR"/>
+                <enum extends="VkAccelerationStructureMemoryRequirementsTypeKHR" name="VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV" alias="VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_KHR"/>
                 <command name="vkCreateAccelerationStructureNV"/>
                 <command name="vkDestroyAccelerationStructureNV"/>
                 <command name="vkGetAccelerationStructureMemoryRequirementsNV"/>
@@ -11628,9 +12136,10 @@
         </extension>
         <extension name="VK_INTEL_performance_query" number="211" type="device" author="INTEL" contact="Lionel Landwerlin @llandwerlin" specialuse="devtools" supported="vulkan">
             <require>
-                <enum value="1"                                         name="VK_INTEL_PERFORMANCE_QUERY_SPEC_VERSION"/>
+                <enum value="2"                                         name="VK_INTEL_PERFORMANCE_QUERY_SPEC_VERSION"/>
                 <enum value="&quot;VK_INTEL_performance_query&quot;"    name="VK_INTEL_PERFORMANCE_QUERY_EXTENSION_NAME"/>
-                <enum offset="0" extends="VkStructureType"              name="VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO_INTEL"/>
+                <enum offset="0" extends="VkStructureType"              name="VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_QUERY_CREATE_INFO_INTEL"/>
+                <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO_INTEL" alias="VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_QUERY_CREATE_INFO_INTEL" comment="Backwards-compatible alias"/>
                 <enum offset="1" extends="VkStructureType"              name="VK_STRUCTURE_TYPE_INITIALIZE_PERFORMANCE_API_INFO_INTEL"/>
                 <enum offset="2" extends="VkStructureType"              name="VK_STRUCTURE_TYPE_PERFORMANCE_MARKER_INFO_INTEL"/>
                 <enum offset="3" extends="VkStructureType"              name="VK_STRUCTURE_TYPE_PERFORMANCE_STREAM_MARKER_INFO_INTEL"/>
@@ -11647,6 +12156,7 @@
                 <type name="VkPerformanceValueINTEL"/>
                 <type name="VkInitializePerformanceApiInfoINTEL"/>
                 <type name="VkQueryPoolCreateInfoINTEL"/>
+                <type name="VkQueryPoolPerformanceQueryCreateInfoINTEL"/>
                 <type name="VkPerformanceMarkerInfoINTEL"/>
                 <type name="VkPerformanceStreamMarkerInfoINTEL"/>
                 <type name="VkPerformanceOverrideInfoINTEL"/>
@@ -11982,7 +12492,7 @@
         </extension>
         <extension name="VK_EXT_validation_features" number="248" type="instance" author="LUNARG" contact="Karl Schultz @karl-lunarg" specialuse="debugging" supported="vulkan">
             <require>
-                <enum value="2"                                             name="VK_EXT_VALIDATION_FEATURES_SPEC_VERSION"/>
+                <enum value="3"                                             name="VK_EXT_VALIDATION_FEATURES_SPEC_VERSION"/>
                 <enum value="&quot;VK_EXT_validation_features&quot;"        name="VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME"/>
                 <enum offset="0" extends="VkStructureType"                  name="VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT"/>
                 <type name="VkValidationFeaturesEXT"/>
@@ -12188,10 +12698,23 @@
                 <enum value="&quot;VK_KHR_extension_268&quot;"              name="VK_EXT_extension_268"/>
             </require>
         </extension>
-        <extension name="VK_KHR_extension_269" number="269" type="device" author="KHR" contact="Josh Barczak @jbarczak" supported="disabled">
+        <extension name="VK_KHR_deferred_host_operations" number="269" type="device" author="KHR" contact="Josh Barczak @jbarczak" platform="provisional" supported="vulkan" provisional="true">
             <require>
-                <enum value="0"                                             name="VK_KHR_EXTENSION_269_SPEC_VERSION"/>
-                <enum value="&quot;VK_KHR_extension_269&quot;"              name="VK_KHR_extension_269"/>
+                <enum value="2"                                             name="VK_KHR_DEFERRED_HOST_OPERATIONS_SPEC_VERSION"/>
+                <enum value="&quot;VK_KHR_deferred_host_operations&quot;"   name="VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME"/>
+                <enum offset="0" extends="VkStructureType"                  name="VK_STRUCTURE_TYPE_DEFERRED_OPERATION_INFO_KHR"/>
+                <enum offset="0" extends="VkObjectType"                     name="VK_OBJECT_TYPE_DEFERRED_OPERATION_KHR"/>
+                <type name="VkDeferredOperationKHR"/>
+                <type name="VkDeferredOperationInfoKHR"/>
+                <command name="vkCreateDeferredOperationKHR"/>
+                <command name="vkDestroyDeferredOperationKHR"/>
+                <command name="vkGetDeferredOperationMaxConcurrencyKHR"/>
+                <command name="vkGetDeferredOperationResultKHR"/>
+                <command name="vkDeferredOperationJoinKHR" />
+                <enum extends="VkResult"       offset="0"       name="VK_THREAD_IDLE_KHR" />
+                <enum extends="VkResult"       offset="1"       name="VK_THREAD_DONE_KHR" />
+                <enum extends="VkResult"       offset="2"       name="VK_OPERATION_DEFERRED_KHR" />
+                <enum extends="VkResult"       offset="3"       name="VK_OPERATION_NOT_DEFERRED_KHR" />
             </require>
         </extension>
         <extension name="VK_KHR_pipeline_executable_properties" number="270" type="device" author="KHR" contact="Jason Ekstrand @jekstrand" specialuse="devtools" supported="vulkan">
@@ -12263,11 +12786,48 @@
                 <type name="VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT"/>
             </require>
         </extension>
-        <extension name="VK_NV_extension_278" number="278" type="device" author="NV" contact="Christoph Kubisch @pixeljetstream" supported="disabled">
+        <extension name="VK_NV_device_generated_commands" number="278" type="device" requiresCore="1.1" author="NV" contact="Christoph Kubisch @pixeljetstream" supported="vulkan">
             <require>
-                <enum value="0"                                             name="VK_NV_EXTENSION_278_SPEC_VERSION"/>
-                <enum value="&quot;VK_NV_extension_278&quot;"               name="VK_NV_extension_278"/>
-                <enum bitpos="18" extends="VkPipelineCreateFlagBits"        name="VK_PIPELINE_CREATE_EXTENSION_278_BIT18_NV"/>
+                <enum value="3"                                             name="VK_NV_DEVICE_GENERATED_COMMANDS_SPEC_VERSION"/>
+                <enum value="&quot;VK_NV_device_generated_commands&quot;"   name="VK_NV_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME"/>
+                <enum offset="0" extends="VkStructureType"                  name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_PROPERTIES_NV"/>
+                <enum offset="1" extends="VkStructureType"                  name="VK_STRUCTURE_TYPE_GRAPHICS_SHADER_GROUP_CREATE_INFO_NV"/>
+                <enum offset="2" extends="VkStructureType"                  name="VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_SHADER_GROUPS_CREATE_INFO_NV"/>
+                <enum offset="3" extends="VkStructureType"                  name="VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_TOKEN_NV"/>
+                <enum offset="4" extends="VkStructureType"                  name="VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NV"/>
+                <enum offset="5" extends="VkStructureType"                  name="VK_STRUCTURE_TYPE_GENERATED_COMMANDS_INFO_NV"/>
+                <enum offset="6" extends="VkStructureType"                  name="VK_STRUCTURE_TYPE_GENERATED_COMMANDS_MEMORY_REQUIREMENTS_INFO_NV"/>
+                <enum offset="7" extends="VkStructureType"                  name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_FEATURES_NV"/>
+                <enum bitpos="18" extends="VkPipelineCreateFlagBits"        name="VK_PIPELINE_CREATE_INDIRECT_BINDABLE_BIT_NV"/>
+                <enum bitpos="17" extends="VkPipelineStageFlagBits"         name="VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_NV"/>
+                <enum bitpos="17" extends="VkAccessFlagBits"                name="VK_ACCESS_COMMAND_PREPROCESS_READ_BIT_NV"/>
+                <enum bitpos="18" extends="VkAccessFlagBits"                name="VK_ACCESS_COMMAND_PREPROCESS_WRITE_BIT_NV"/>
+                <enum offset="0" extends="VkObjectType"                     name="VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NV" comment="VkIndirectCommandsLayoutNV"/>
+                <type name="VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV"/>
+                <type name="VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV"/>
+                <type name="VkGraphicsShaderGroupCreateInfoNV"/>
+                <type name="VkGraphicsPipelineShaderGroupsCreateInfoNV"/>
+                <type name="VkBindShaderGroupIndirectCommandNV"/>
+                <type name="VkBindIndexBufferIndirectCommandNV"/>
+                <type name="VkBindVertexBufferIndirectCommandNV"/>
+                <type name="VkSetStateFlagsIndirectCommandNV"/>
+                <type name="VkIndirectStateFlagBitsNV"/>
+                <type name="VkIndirectStateFlagsNV"/>
+                <type name="VkIndirectCommandsLayoutNV"/>
+                <type name="VkIndirectCommandsTokenTypeNV"/>
+                <type name="VkIndirectCommandsLayoutUsageFlagBitsNV"/>
+                <type name="VkIndirectCommandsLayoutUsageFlagsNV"/>
+                <type name="VkIndirectCommandsStreamNV"/>
+                <type name="VkIndirectCommandsLayoutTokenNV"/>
+                <type name="VkIndirectCommandsLayoutCreateInfoNV"/>
+                <type name="VkGeneratedCommandsInfoNV"/>
+                <type name="VkGeneratedCommandsMemoryRequirementsInfoNV"/>
+                <command name="vkGetGeneratedCommandsMemoryRequirementsNV"/>
+                <command name="vkCmdPreprocessGeneratedCommandsNV"/>
+                <command name="vkCmdExecuteGeneratedCommandsNV"/>
+                <command name="vkCmdBindPipelineShaderGroupNV"/>
+                <command name="vkCreateIndirectCommandsLayoutNV"/>
+                <command name="vkDestroyIndirectCommandsLayoutNV"/>
             </require>
         </extension>
         <extension name="VK_NV_extension_279" number="279" type="device" author="NV" contact="Christoph Kubisch @pixeljetstream" supported="disabled">
@@ -12352,12 +12912,13 @@
                 <enum value="&quot;VK_GOOGLE_user_type&quot;"               name="VK_GOOGLE_USER_TYPE_EXTENSION_NAME"/>
             </require>
         </extension>
-        <extension name="VK_NV_extension_291" number="291" author="NV" contact="Daniel Koch @dgkoch" supported="disabled">
+        <extension name="VK_KHR_pipeline_library" number="291" type="device" author="KHR" contact="Christoph Kubisch @pixeljetstream" platform="provisional" supported="vulkan" provisional="true">
             <require>
-                <enum value="0"                                             name="VK_NV_EXTENSION_291_SPEC_VERSION"/>
-                <enum value="&quot;VK_NV_extension_291&quot;"               name="VK_NV_EXTENSION_291_EXTENSION_NAME"/>
-                <enum bitpos="12"  extends="VkPipelineCreateFlagBits"       name="VK_PIPELINE_CREATE_EXTENSION_291_BIT0_NV"/>
-                <enum bitpos="13"  extends="VkPipelineCreateFlagBits"       name="VK_PIPELINE_CREATE_EXTENSION_291_BIT1_NV"/>
+                <enum value="1"                                             name="VK_KHR_PIPELINE_LIBRARY_SPEC_VERSION"/>
+                <enum value="&quot;VK_KHR_pipeline_library&quot;"           name="VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME"/>
+                <enum bitpos="11" extends="VkPipelineCreateFlagBits"        name="VK_PIPELINE_CREATE_LIBRARY_BIT_KHR"/>
+                <enum offset="0" extends="VkStructureType"                  name="VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR"/>
+                <type name="VkPipelineLibraryCreateInfoKHR"/>
             </require>
         </extension>
         <extension name="VK_NV_extension_292" number="292" author="NV" contact="Daniel Koch @dgkoch" supported="disabled">
@@ -12397,14 +12958,22 @@
                 <enum bitpos="3" extends="VkPipelineShaderStageCreateFlagBits"  name="VK_PIPELINE_SHADER_STAGE_CREATE_RESERVED_3_BIT_KHR"/>
             </require>
         </extension>
-        <extension name="VK_EXT_extension_298" number="298" author="AMD" contact="Gregory Grebe @grgrebe-amd" supported="disabled">
+        <extension name="VK_EXT_pipeline_creation_cache_control" number="298" type="device" author="AMD" contact="Gregory Grebe @grgrebe_amd" supported="vulkan">
             <require>
-                <enum value="0"                                             name="VK_EXT_EXTENSION_298_SPEC_VERSION"/>
-                <enum value="&quot;VK_EXT_extension_298&quot;"              name="VK_EXT_EXTENSION_298_EXTENSION_NAME"/>
-                <enum bitpos="8"  extends="VkPipelineCreateFlagBits"    name="VK_PIPELINE_CREATE_RESERVED_8_BIT_EXT"/>
-                <enum bitpos="9"  extends="VkPipelineCreateFlagBits"    name="VK_PIPELINE_CREATE_RESERVED_9_BIT_EXT"/>
-                <enum bitpos="10" extends="VkPipelineCreateFlagBits"    name="VK_PIPELINE_CREATE_RESERVED_10_BIT_EXT"/>
-                <enum extends="VkResult" offset="0"                     name="VK_RESULT_EXT_298_RESERVED_VALUE_0_EXT"/>
+                <enum value="3" name="VK_EXT_PIPELINE_CREATION_CACHE_CONTROL_SPEC_VERSION"/>
+                <enum value="&quot;VK_EXT_pipeline_creation_cache_control&quot;"
+                    name="VK_EXT_PIPELINE_CREATION_CACHE_CONTROL_EXTENSION_NAME"/>
+                <enum offset="0" extends="VkStructureType"
+                    name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES_EXT"/>
+                <type name="VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT"/>
+                <enum bitpos="8"  extends="VkPipelineCreateFlagBits"
+                    name="VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_EXT"/>
+                <enum bitpos="9" extends="VkPipelineCreateFlagBits"
+                    name="VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT_EXT"/>
+                <enum extends="VkResult" offset="0" name="VK_PIPELINE_COMPILE_REQUIRED_EXT"/>
+                <enum extends="VkResult"            name="VK_ERROR_PIPELINE_COMPILE_REQUIRED_EXT" alias="VK_PIPELINE_COMPILE_REQUIRED_EXT"/>
+                <enum bitpos="0"  extends="VkPipelineCacheCreateFlagBits"
+                    name="VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT_EXT"/>
             </require>
         </extension>
         <extension name="VK_KHR_extension_299" number="299" author="KHR" contact="Mark Bellamy @mark.bellamy_arm" supported="disabled">
@@ -12419,16 +12988,23 @@
                 <enum value="&quot;VK_KHR_extension_300&quot;"              name="VK_KHR_EXTENSION_300_EXTENSION_NAME"/>
             </require>
         </extension>
-        <extension name="VK_NV_extension_301" number="301" author="NV" contact="Kedarnath Thangudu @kthangudu" supported="disabled">
+        <extension name="VK_NV_device_diagnostics_config" number="301" type="device" requires="VK_KHR_get_physical_device_properties2" author="NV" contact="Kedarnath Thangudu @kthangudu" supported="vulkan">
             <require>
-                <enum value="0"                                             name="VK_NV_EXTENSION_301_SPEC_VERSION"/>
-                <enum value="&quot;VK_NV_extension_301&quot;"               name="VK_NV_EXTENSION_301_EXTENSION_NAME"/>
+                <enum value="1"                                             name="VK_NV_DEVICE_DIAGNOSTICS_CONFIG_SPEC_VERSION"/>
+                <enum value="&quot;VK_NV_device_diagnostics_config&quot;"     name="VK_NV_DEVICE_DIAGNOSTICS_CONFIG_EXTENSION_NAME"/>
+                <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DIAGNOSTICS_CONFIG_FEATURES_NV"/>
+                <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV"/>
+                <type name="VkPhysicalDeviceDiagnosticsConfigFeaturesNV"/>
+                <type name="VkDeviceDiagnosticsConfigCreateInfoNV"/>
+                <type name="VkDeviceDiagnosticsConfigFlagsNV"/>
+                <type name="VkDeviceDiagnosticsConfigFlagBitsNV"/>
             </require>
         </extension>
-        <extension name="VK_QCOM_extension_302" number="302" author="QCOM" contact="Bill Licea-Kane @wwlk" supported="disabled">
+        <extension name="VK_QCOM_render_pass_store_ops" number="302" type="device" author="QCOM" contact="Bill Licea-Kane @wwlk" supported="vulkan">
             <require>
-                <enum value="0"                                             name="VK_QCOM_extension_302_SPEC_VERSION"/>
-                <enum value="&quot;VK_QCOM_extension_302&quot;"             name="VK_QCOM_extension_302_EXTENSION_NAME"/>
+                <enum value="2"                                             name="VK_QCOM_render_pass_store_ops_SPEC_VERSION"/>
+                <enum value="&quot;VK_QCOM_render_pass_store_ops&quot;"     name="VK_QCOM_render_pass_store_ops_EXTENSION_NAME"/>
+                <enum offset="0" extends="VkAttachmentStoreOp"              name="VK_ATTACHMENT_STORE_OP_NONE_QCOM"/>
             </require>
         </extension>
         <extension name="VK_QCOM_extension_303" number="303" author="QCOM" contact="Bill Licea-Kane @wwlk" supported="disabled">
@@ -12463,8 +13039,8 @@
         </extension>
         <extension name="VK_NV_extension_308" number="308" type="device" author="NV" contact="Tristan Lorach @tlorach" supported="disabled">
             <require>
-                <enum value="0"                       name="VK_NV_EXTENSION_308_SPEC_VERSION"/>
-                <enum value="&quot;VK_NV_extension_308&quot;"        name="VK_NV_EXTENSION_308_EXTENSION_NAME"/>
+                <enum value="0"                                             name="VK_NV_EXTENSION_308_SPEC_VERSION"/>
+                <enum value="&quot;VK_NV_extension_308&quot;"               name="VK_NV_EXTENSION_308_EXTENSION_NAME"/>
             </require>
         </extension>
         <extension name="VK_KHR_extension_309" number="309" author="KHR" contact="Aidan Fabius @afabius" supported="disabled">
@@ -12484,20 +13060,134 @@
         <extension name="VK_NV_extension_311" number="311" author="NV" contact="Charles Hansen @cshansen" supported="disabled">
             <require>
                 <enum value="0"                                             name="VK_NV_EXTENSION_311_SPEC_VERSION"/>
-                <enum value="&quot;VK_NV_extension_311&quot;"             name="VK_NV_EXTENSION_311_EXTENSION_NAME"/>
+                <enum value="&quot;VK_NV_extension_311&quot;"               name="VK_NV_EXTENSION_311_EXTENSION_NAME"/>
             </require>
         </extension>
-		<extension name="VK_EXT_extension_312" number="312" author="MVK" contact="Bill Hollings @billhollings" supported="disabled">
-			<require>
-				<enum value="0"                                             name="VK_EXT_EXTENSION_312_SPEC_VERSION"/>
-				<enum value="&quot;VK_EXT_extension_312&quot;"             name="VK_EXT_EXTENSION_312_EXTENSION_NAME"/>
-			</require>
-		</extension>
-		<extension name="VK_EXT_extension_313" number="313" author="MVK" contact="Bill Hollings @billhollings" supported="disabled">
-			<require>
-				<enum value="0"                                             name="VK_EXT_EXTENSION_313_SPEC_VERSION"/>
-				<enum value="&quot;VK_EXT_extension_313&quot;"             name="VK_EXT_EXTENSION_313_EXTENSION_NAME"/>
-			</require>
-		</extension>
+        <extension name="VK_EXT_extension_312" number="312" author="MVK" contact="Bill Hollings @billhollings" supported="disabled">
+            <require>
+                <enum value="0"                                             name="VK_EXT_EXTENSION_312_SPEC_VERSION"/>
+                <enum value="&quot;VK_EXT_extension_312&quot;"              name="VK_EXT_EXTENSION_312_EXTENSION_NAME"/>
+            </require>
+        </extension>
+        <extension name="VK_EXT_extension_313" number="313" author="MVK" contact="Bill Hollings @billhollings" supported="disabled">
+            <require>
+                <enum value="0"                                             name="VK_EXT_EXTENSION_313_SPEC_VERSION"/>
+                <enum value="&quot;VK_EXT_extension_313&quot;"              name="VK_EXT_EXTENSION_313_EXTENSION_NAME"/>
+            </require>
+        </extension>
+        <extension name="VK_AMD_extension_314" number="314" author="AMD" contact="Martin Dinkov @mdinkov" supported="disabled">
+            <require>
+                <enum value="0"                                             name="VK_AMD_EXTENSION_314_SPEC_VERSION"/>
+                <enum value="&quot;VK_AMD_extension_314&quot;"              name="VK_AMD_EXTENSION_314_EXTENSION_NAME"/>
+            </require>
+        </extension>
+        <extension name="VK_AMD_extension_315" number="315" author="AMD" contact="Martin Dinkov @mdinkov" supported="disabled">
+            <require>
+                <enum value="0"                                             name="VK_AMD_EXTENSION_315_SPEC_VERSION"/>
+                <enum value="&quot;VK_AMD_extension_315&quot;"              name="VK_AMD_EXTENSION_315_EXTENSION_NAME"/>
+            </require>
+        </extension>
+        <extension name="VK_AMD_extension_316" number="316" author="AMD" contact="Martin Dinkov @mdinkov" supported="disabled">
+            <require>
+                <enum value="0"                                             name="VK_AMD_EXTENSION_316_SPEC_VERSION"/>
+                <enum value="&quot;VK_AMD_extension_316&quot;"              name="VK_AMD_EXTENSION_316_EXTENSION_NAME"/>
+            </require>
+        </extension>
+        <extension name="VK_AMD_extension_317" number="317" author="AMD" contact="Martin Dinkov @mdinkov" supported="disabled">
+            <require>
+                <enum value="0"                                             name="VK_AMD_EXTENSION_317_SPEC_VERSION"/>
+                <enum value="&quot;VK_AMD_extension_317&quot;"              name="VK_AMD_EXTENSION_317_EXTENSION_NAME"/>
+            </require>
+        </extension>
+        <extension name="VK_AMD_extension_318" number="318" author="AMD" contact="Martin Dinkov @mdinkov" supported="disabled">
+            <require>
+                <enum value="0"                                             name="VK_AMD_EXTENSION_318_SPEC_VERSION"/>
+                <enum value="&quot;VK_AMD_extension_318&quot;"              name="VK_AMD_EXTENSION_318_EXTENSION_NAME"/>
+            </require>
+        </extension>
+        <extension name="VK_AMD_extension_319" number="319" author="AMD" contact="Martin Dinkov @mdinkov" supported="disabled">
+            <require>
+                <enum value="0"                                             name="VK_AMD_EXTENSION_319_SPEC_VERSION"/>
+                <enum value="&quot;VK_AMD_extension_319&quot;"              name="VK_AMD_EXTENSION_319_EXTENSION_NAME"/>
+            </require>
+        </extension>
+        <extension name="VK_AMD_extension_320" number="320" author="AMD" contact="Martin Dinkov @mdinkov" supported="disabled">
+            <require>
+                <enum value="0"                                             name="VK_AMD_EXTENSION_320_SPEC_VERSION"/>
+                <enum value="&quot;VK_AMD_extension_320&quot;"              name="VK_AMD_EXTENSION_320_EXTENSION_NAME"/>
+            </require>
+        </extension>
+        <extension name="VK_AMD_extension_321" number="321" author="AMD" contact="Martin Dinkov @mdinkov" supported="disabled">
+            <require>
+                <enum value="0"                                             name="VK_AMD_EXTENSION_321_SPEC_VERSION"/>
+                <enum value="&quot;VK_AMD_extension_321&quot;"              name="VK_AMD_EXTENSION_321_EXTENSION_NAME"/>
+            </require>
+        </extension>
+        <extension name="VK_AMD_extension_322" number="322" author="AMD" contact="Martin Dinkov @mdinkov" supported="disabled">
+            <require>
+                <enum value="0"                                             name="VK_AMD_EXTENSION_322_SPEC_VERSION"/>
+                <enum value="&quot;VK_AMD_extension_322&quot;"              name="VK_AMD_EXTENSION_322_EXTENSION_NAME"/>
+            </require>
+        </extension>
+        <extension name="VK_AMD_extension_323" number="323" author="AMD" contact="Martin Dinkov @mdinkov" supported="disabled">
+            <require>
+                <enum value="0"                                             name="VK_AMD_EXTENSION_323_SPEC_VERSION"/>
+                <enum value="&quot;VK_AMD_extension_323&quot;"              name="VK_AMD_EXTENSION_323_EXTENSION_NAME"/>
+            </require>
+        </extension>
+        <extension name="VK_KHR_extension_324" number="324" author="KHR" contact="Alan Baker @alan-baker" supported="disabled">
+            <require>
+                <enum value="0"                                             name="VK_KHR_EXTENSION_324_SPEC_VERSION"/>
+                <enum value="&quot;VK_KHR_extension_324&quot;"              name="VK_KHR_EXTENSION_324_EXTENSION_NAME"/>
+            </require>
+        </extension>
+        <extension name="VK_KHR_extension_325" number="325" author="KHR" contact="Ralph Potter gitlab:@r_potter" supported="disabled">
+            <require>
+                <enum value="0"                                             name="VK_KHR_EXTENSION_325_SPEC_VERSION"/>
+                <enum value="&quot;VK_KHR_extension_325&quot;"              name="VK_KHR_EXTENSION_325_EXTENSION_NAME"/>
+            </require>
+        </extension>
+        <extension name="VK_KHR_extension_326" number="326" author="KHR" contact="Alan Baker @alan-baker" supported="disabled">
+            <require>
+                <enum value="0"                                             name="VK_KHR_EXTENSION_326_SPEC_VERSION"/>
+                <enum value="&quot;VK_KHR_extension_326&quot;"              name="VK_KHR_EXTENSION_326_EXTENSION_NAME"/>
+            </require>
+        </extension>
+        <extension name="VK_NV_extension_327" number="327" author="NV" contact="Pat Brown @pbrown" supported="disabled">
+            <require>
+                <enum value="0"                                             name="VK_NV_EXTENSION_327_SPEC_VERSION"/>
+                <enum value="&quot;VK_NV_extension_327&quot;"               name="VK_NV_EXTENSION_327_EXTENSION_NAME"/>
+            </require>
+        </extension>
+        <extension name="VK_NV_extension_328" number="328" author="NV" contact="Pat Brown @pbrown" supported="disabled">
+            <require>
+                <enum value="0"                                             name="VK_NV_EXTENSION_328_SPEC_VERSION"/>
+                <enum value="&quot;VK_NV_extension_328&quot;"               name="VK_NV_EXTENSION_328_EXTENSION_NAME"/>
+            </require>
+        </extension>
+        <extension name="VK_NV_extension_329" number="329" author="NV" contact="Pat Brown @pbrown" supported="disabled">
+            <require>
+                <enum value="0"                                             name="VK_NV_EXTENSION_329_SPEC_VERSION"/>
+                <enum value="&quot;VK_NV_extension_329&quot;"               name="VK_NV_EXTENSION_329_EXTENSION_NAME"/>
+            </require>
+        </extension>
+        <extension name="VK_NV_extension_330" number="330" author="NV" contact="Liam Middlebrook @liam-middlebrook" supported="disabled">
+            <require>
+                <enum value="0"                                             name="VK_NV_EXTENSION_330_SPEC_VERSION"/>
+                <enum value="&quot;VK_NV_extension_330&quot;"               name="VK_NV_EXTENSION_330_EXTENSION_NAME"/>
+            </require>
+        </extension>
+        <extension name="VK_NV_extension_331" number="331" author="NV" contact="Tony Zlatinski @tzlatinski" supported="disabled">
+            <require>
+                <enum value="0"                                             name="VK_NV_EXTENSION_331_SPEC_VERSION"/>
+                <enum value="&quot;VK_NV_extension_331&quot;"               name="VK_NV_EXTENSION_331_EXTENSION_NAME"/>
+            </require>
+        </extension>
+        <extension name="VK_NV_extension_332" number="332" author="NV" contact="Tony Zlatinski @tzlatinski" supported="disabled">
+            <require>
+                <enum value="0"                                             name="VK_NV_EXTENSION_332_SPEC_VERSION"/>
+                <enum value="&quot;VK_NV_extension_332&quot;"               name="VK_NV_EXTENSION_332_EXTENSION_NAME"/>
+            </require>
+        </extension>
     </extensions>
-</registry>
\ No newline at end of file
+</registry>
diff --git a/util/BUILD.gn b/util/BUILD.gn
index a967b00..acb1b44 100644
--- a/util/BUILD.gn
+++ b/util/BUILD.gn
@@ -15,6 +15,7 @@
   "OSWindow.cpp",
   "OSWindow.h",
   "com_utils.h",
+  "frame_capture_utils.h",
   "geometry_utils.cpp",
   "geometry_utils.h",
   "keyboard.h",
diff --git a/util/egl_loader_autogen.cpp b/util/egl_loader_autogen.cpp
index f3fef00..32e8366 100644
--- a/util/egl_loader_autogen.cpp
+++ b/util/egl_loader_autogen.cpp
@@ -77,7 +77,7 @@
     eglCreateStreamProducerD3DTextureANGLE;
 ANGLE_UTIL_EXPORT PFNEGLSTREAMPOSTD3DTEXTUREANGLEPROC eglStreamPostD3DTextureANGLE;
 ANGLE_UTIL_EXPORT PFNEGLSWAPBUFFERSWITHFRAMETOKENANGLEPROC eglSwapBuffersWithFrameTokenANGLE;
-ANGLE_UTIL_EXPORT PFNEGLGETMSCRATECHROMIUMPROC eglGetMscRateCHROMIUM;
+ANGLE_UTIL_EXPORT PFNEGLGETMSCRATEANGLEPROC eglGetMscRateANGLE;
 ANGLE_UTIL_EXPORT PFNEGLGETSYNCVALUESCHROMIUMPROC eglGetSyncValuesCHROMIUM;
 ANGLE_UTIL_EXPORT PFNEGLQUERYDEVICEATTRIBEXTPROC eglQueryDeviceAttribEXT;
 ANGLE_UTIL_EXPORT PFNEGLQUERYDEVICESTRINGEXTPROC eglQueryDeviceStringEXT;
@@ -214,8 +214,8 @@
         loadProc("eglStreamPostD3DTextureANGLE"));
     eglSwapBuffersWithFrameTokenANGLE = reinterpret_cast<PFNEGLSWAPBUFFERSWITHFRAMETOKENANGLEPROC>(
         loadProc("eglSwapBuffersWithFrameTokenANGLE"));
-    eglGetMscRateCHROMIUM =
-        reinterpret_cast<PFNEGLGETMSCRATECHROMIUMPROC>(loadProc("eglGetMscRateCHROMIUM"));
+    eglGetMscRateANGLE =
+        reinterpret_cast<PFNEGLGETMSCRATEANGLEPROC>(loadProc("eglGetMscRateANGLE"));
     eglGetSyncValuesCHROMIUM =
         reinterpret_cast<PFNEGLGETSYNCVALUESCHROMIUMPROC>(loadProc("eglGetSyncValuesCHROMIUM"));
     eglQueryDeviceAttribEXT =
diff --git a/util/egl_loader_autogen.h b/util/egl_loader_autogen.h
index a5c09e7..4f46511 100644
--- a/util/egl_loader_autogen.h
+++ b/util/egl_loader_autogen.h
@@ -84,7 +84,7 @@
     eglCreateStreamProducerD3DTextureANGLE;
 ANGLE_UTIL_EXPORT extern PFNEGLSTREAMPOSTD3DTEXTUREANGLEPROC eglStreamPostD3DTextureANGLE;
 ANGLE_UTIL_EXPORT extern PFNEGLSWAPBUFFERSWITHFRAMETOKENANGLEPROC eglSwapBuffersWithFrameTokenANGLE;
-ANGLE_UTIL_EXPORT extern PFNEGLGETMSCRATECHROMIUMPROC eglGetMscRateCHROMIUM;
+ANGLE_UTIL_EXPORT extern PFNEGLGETMSCRATEANGLEPROC eglGetMscRateANGLE;
 ANGLE_UTIL_EXPORT extern PFNEGLGETSYNCVALUESCHROMIUMPROC eglGetSyncValuesCHROMIUM;
 ANGLE_UTIL_EXPORT extern PFNEGLQUERYDEVICEATTRIBEXTPROC eglQueryDeviceAttribEXT;
 ANGLE_UTIL_EXPORT extern PFNEGLQUERYDEVICESTRINGEXTPROC eglQueryDeviceStringEXT;
diff --git a/util/frame_capture_utils.h b/util/frame_capture_utils.h
new file mode 100644
index 0000000..11ae256
--- /dev/null
+++ b/util/frame_capture_utils.h
@@ -0,0 +1,47 @@
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// frame_capture_utils:
+//   Helper functions for capture and replay of traces.
+//
+
+#ifndef UTIL_FRAME_CAPTURE_UTILS_H_
+#define UTIL_FRAME_CAPTURE_UTILS_H_
+
+#include <iostream>
+#include <memory>
+#include <vector>
+
+#include "common/angleutils.h"
+
+#define USE_SYSTEM_ZLIB
+#include "compression_utils_portable.h"
+
+namespace angle
+{
+
+inline uint8_t *DecompressBinaryData(const std::vector<uint8_t> &compressedData)
+{
+    uint32_t uncompressedSize =
+        zlib_internal::GetGzipUncompressedSize(compressedData.data(), compressedData.size());
+
+    std::unique_ptr<uint8_t[]> uncompressedData(new uint8_t[uncompressedSize]);
+    uLong destLen = uncompressedSize;
+    int zResult =
+        zlib_internal::GzipUncompressHelper(uncompressedData.get(), &destLen, compressedData.data(),
+                                            static_cast<uLong>(compressedData.size()));
+
+    if (zResult != Z_OK)
+    {
+        std::cerr << "Failure to decompressed binary data: " << zResult << "\n";
+        return nullptr;
+    }
+
+    return uncompressedData.release();
+}
+
+}  // namespace angle
+
+#endif  // UTIL_FRAME_CAPTURE_UTILS_H_
diff --git a/util/gles_loader_autogen.cpp b/util/gles_loader_autogen.cpp
index a16b4b6..8836834 100644
--- a/util/gles_loader_autogen.cpp
+++ b/util/gles_loader_autogen.cpp
@@ -518,35 +518,7 @@
 ANGLE_UTIL_EXPORT PFNGLCOPYSUBTEXTURECHROMIUMPROC glCopySubTextureCHROMIUM;
 ANGLE_UTIL_EXPORT PFNGLCOPYTEXTURECHROMIUMPROC glCopyTextureCHROMIUM;
 ANGLE_UTIL_EXPORT PFNGLCOVERAGEMODULATIONCHROMIUMPROC glCoverageModulationCHROMIUM;
-ANGLE_UTIL_EXPORT PFNGLMATRIXLOADIDENTITYCHROMIUMPROC glMatrixLoadIdentityCHROMIUM;
-ANGLE_UTIL_EXPORT PFNGLMATRIXLOADFCHROMIUMPROC glMatrixLoadfCHROMIUM;
 ANGLE_UTIL_EXPORT PFNGLLOSECONTEXTCHROMIUMPROC glLoseContextCHROMIUM;
-ANGLE_UTIL_EXPORT PFNGLBINDFRAGMENTINPUTLOCATIONCHROMIUMPROC glBindFragmentInputLocationCHROMIUM;
-ANGLE_UTIL_EXPORT PFNGLCOVERFILLPATHCHROMIUMPROC glCoverFillPathCHROMIUM;
-ANGLE_UTIL_EXPORT PFNGLCOVERFILLPATHINSTANCEDCHROMIUMPROC glCoverFillPathInstancedCHROMIUM;
-ANGLE_UTIL_EXPORT PFNGLCOVERSTROKEPATHCHROMIUMPROC glCoverStrokePathCHROMIUM;
-ANGLE_UTIL_EXPORT PFNGLCOVERSTROKEPATHINSTANCEDCHROMIUMPROC glCoverStrokePathInstancedCHROMIUM;
-ANGLE_UTIL_EXPORT PFNGLDELETEPATHSCHROMIUMPROC glDeletePathsCHROMIUM;
-ANGLE_UTIL_EXPORT PFNGLGENPATHSCHROMIUMPROC glGenPathsCHROMIUM;
-ANGLE_UTIL_EXPORT PFNGLGETPATHPARAMETERFVCHROMIUMPROC glGetPathParameterfvCHROMIUM;
-ANGLE_UTIL_EXPORT PFNGLGETPATHPARAMETERIVCHROMIUMPROC glGetPathParameterivCHROMIUM;
-ANGLE_UTIL_EXPORT PFNGLISPATHCHROMIUMPROC glIsPathCHROMIUM;
-ANGLE_UTIL_EXPORT PFNGLPATHCOMMANDSCHROMIUMPROC glPathCommandsCHROMIUM;
-ANGLE_UTIL_EXPORT PFNGLPATHPARAMETERFCHROMIUMPROC glPathParameterfCHROMIUM;
-ANGLE_UTIL_EXPORT PFNGLPATHPARAMETERICHROMIUMPROC glPathParameteriCHROMIUM;
-ANGLE_UTIL_EXPORT PFNGLPATHSTENCILFUNCCHROMIUMPROC glPathStencilFuncCHROMIUM;
-ANGLE_UTIL_EXPORT PFNGLPROGRAMPATHFRAGMENTINPUTGENCHROMIUMPROC
-    glProgramPathFragmentInputGenCHROMIUM;
-ANGLE_UTIL_EXPORT PFNGLSTENCILFILLPATHCHROMIUMPROC glStencilFillPathCHROMIUM;
-ANGLE_UTIL_EXPORT PFNGLSTENCILFILLPATHINSTANCEDCHROMIUMPROC glStencilFillPathInstancedCHROMIUM;
-ANGLE_UTIL_EXPORT PFNGLSTENCILSTROKEPATHCHROMIUMPROC glStencilStrokePathCHROMIUM;
-ANGLE_UTIL_EXPORT PFNGLSTENCILSTROKEPATHINSTANCEDCHROMIUMPROC glStencilStrokePathInstancedCHROMIUM;
-ANGLE_UTIL_EXPORT PFNGLSTENCILTHENCOVERFILLPATHCHROMIUMPROC glStencilThenCoverFillPathCHROMIUM;
-ANGLE_UTIL_EXPORT PFNGLSTENCILTHENCOVERFILLPATHINSTANCEDCHROMIUMPROC
-    glStencilThenCoverFillPathInstancedCHROMIUM;
-ANGLE_UTIL_EXPORT PFNGLSTENCILTHENCOVERSTROKEPATHCHROMIUMPROC glStencilThenCoverStrokePathCHROMIUM;
-ANGLE_UTIL_EXPORT PFNGLSTENCILTHENCOVERSTROKEPATHINSTANCEDCHROMIUMPROC
-    glStencilThenCoverStrokePathInstancedCHROMIUM;
 ANGLE_UTIL_EXPORT PFNGLBINDFRAGDATALOCATIONEXTPROC glBindFragDataLocationEXT;
 ANGLE_UTIL_EXPORT PFNGLBINDFRAGDATALOCATIONINDEXEDEXTPROC glBindFragDataLocationIndexedEXT;
 ANGLE_UTIL_EXPORT PFNGLGETFRAGDATAINDEXEXTPROC glGetFragDataIndexEXT;
@@ -1322,49 +1294,7 @@
 ANGLE_UTIL_EXPORT PFNGLCOPYTEXTURECHROMIUMCONTEXTANGLEPROC glCopyTextureCHROMIUMContextANGLE;
 ANGLE_UTIL_EXPORT PFNGLCOVERAGEMODULATIONCHROMIUMCONTEXTANGLEPROC
     glCoverageModulationCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT PFNGLMATRIXLOADIDENTITYCHROMIUMCONTEXTANGLEPROC
-    glMatrixLoadIdentityCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT PFNGLMATRIXLOADFCHROMIUMCONTEXTANGLEPROC glMatrixLoadfCHROMIUMContextANGLE;
 ANGLE_UTIL_EXPORT PFNGLLOSECONTEXTCHROMIUMCONTEXTANGLEPROC glLoseContextCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT PFNGLBINDFRAGMENTINPUTLOCATIONCHROMIUMCONTEXTANGLEPROC
-    glBindFragmentInputLocationCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT PFNGLCOVERFILLPATHCHROMIUMCONTEXTANGLEPROC glCoverFillPathCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT PFNGLCOVERFILLPATHINSTANCEDCHROMIUMCONTEXTANGLEPROC
-    glCoverFillPathInstancedCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT PFNGLCOVERSTROKEPATHCHROMIUMCONTEXTANGLEPROC
-    glCoverStrokePathCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT PFNGLCOVERSTROKEPATHINSTANCEDCHROMIUMCONTEXTANGLEPROC
-    glCoverStrokePathInstancedCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT PFNGLDELETEPATHSCHROMIUMCONTEXTANGLEPROC glDeletePathsCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT PFNGLGENPATHSCHROMIUMCONTEXTANGLEPROC glGenPathsCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT PFNGLGETPATHPARAMETERFVCHROMIUMCONTEXTANGLEPROC
-    glGetPathParameterfvCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT PFNGLGETPATHPARAMETERIVCHROMIUMCONTEXTANGLEPROC
-    glGetPathParameterivCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT PFNGLISPATHCHROMIUMCONTEXTANGLEPROC glIsPathCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT PFNGLPATHCOMMANDSCHROMIUMCONTEXTANGLEPROC glPathCommandsCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT PFNGLPATHPARAMETERFCHROMIUMCONTEXTANGLEPROC glPathParameterfCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT PFNGLPATHPARAMETERICHROMIUMCONTEXTANGLEPROC glPathParameteriCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT PFNGLPATHSTENCILFUNCCHROMIUMCONTEXTANGLEPROC
-    glPathStencilFuncCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT PFNGLPROGRAMPATHFRAGMENTINPUTGENCHROMIUMCONTEXTANGLEPROC
-    glProgramPathFragmentInputGenCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT PFNGLSTENCILFILLPATHCHROMIUMCONTEXTANGLEPROC
-    glStencilFillPathCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT PFNGLSTENCILFILLPATHINSTANCEDCHROMIUMCONTEXTANGLEPROC
-    glStencilFillPathInstancedCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT PFNGLSTENCILSTROKEPATHCHROMIUMCONTEXTANGLEPROC
-    glStencilStrokePathCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT PFNGLSTENCILSTROKEPATHINSTANCEDCHROMIUMCONTEXTANGLEPROC
-    glStencilStrokePathInstancedCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT PFNGLSTENCILTHENCOVERFILLPATHCHROMIUMCONTEXTANGLEPROC
-    glStencilThenCoverFillPathCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT PFNGLSTENCILTHENCOVERFILLPATHINSTANCEDCHROMIUMCONTEXTANGLEPROC
-    glStencilThenCoverFillPathInstancedCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT PFNGLSTENCILTHENCOVERSTROKEPATHCHROMIUMCONTEXTANGLEPROC
-    glStencilThenCoverStrokePathCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT PFNGLSTENCILTHENCOVERSTROKEPATHINSTANCEDCHROMIUMCONTEXTANGLEPROC
-    glStencilThenCoverStrokePathInstancedCHROMIUMContextANGLE;
 ANGLE_UTIL_EXPORT PFNGLBINDFRAGDATALOCATIONEXTCONTEXTANGLEPROC
     glBindFragDataLocationEXTContextANGLE;
 ANGLE_UTIL_EXPORT PFNGLBINDFRAGDATALOCATIONINDEXEDEXTCONTEXTANGLEPROC
@@ -2361,66 +2291,8 @@
         reinterpret_cast<PFNGLCOPYTEXTURECHROMIUMPROC>(loadProc("glCopyTextureCHROMIUM"));
     glCoverageModulationCHROMIUM = reinterpret_cast<PFNGLCOVERAGEMODULATIONCHROMIUMPROC>(
         loadProc("glCoverageModulationCHROMIUM"));
-    glMatrixLoadIdentityCHROMIUM = reinterpret_cast<PFNGLMATRIXLOADIDENTITYCHROMIUMPROC>(
-        loadProc("glMatrixLoadIdentityCHROMIUM"));
-    glMatrixLoadfCHROMIUM =
-        reinterpret_cast<PFNGLMATRIXLOADFCHROMIUMPROC>(loadProc("glMatrixLoadfCHROMIUM"));
     glLoseContextCHROMIUM =
         reinterpret_cast<PFNGLLOSECONTEXTCHROMIUMPROC>(loadProc("glLoseContextCHROMIUM"));
-    glBindFragmentInputLocationCHROMIUM =
-        reinterpret_cast<PFNGLBINDFRAGMENTINPUTLOCATIONCHROMIUMPROC>(
-            loadProc("glBindFragmentInputLocationCHROMIUM"));
-    glCoverFillPathCHROMIUM =
-        reinterpret_cast<PFNGLCOVERFILLPATHCHROMIUMPROC>(loadProc("glCoverFillPathCHROMIUM"));
-    glCoverFillPathInstancedCHROMIUM = reinterpret_cast<PFNGLCOVERFILLPATHINSTANCEDCHROMIUMPROC>(
-        loadProc("glCoverFillPathInstancedCHROMIUM"));
-    glCoverStrokePathCHROMIUM =
-        reinterpret_cast<PFNGLCOVERSTROKEPATHCHROMIUMPROC>(loadProc("glCoverStrokePathCHROMIUM"));
-    glCoverStrokePathInstancedCHROMIUM =
-        reinterpret_cast<PFNGLCOVERSTROKEPATHINSTANCEDCHROMIUMPROC>(
-            loadProc("glCoverStrokePathInstancedCHROMIUM"));
-    glDeletePathsCHROMIUM =
-        reinterpret_cast<PFNGLDELETEPATHSCHROMIUMPROC>(loadProc("glDeletePathsCHROMIUM"));
-    glGenPathsCHROMIUM =
-        reinterpret_cast<PFNGLGENPATHSCHROMIUMPROC>(loadProc("glGenPathsCHROMIUM"));
-    glGetPathParameterfvCHROMIUM = reinterpret_cast<PFNGLGETPATHPARAMETERFVCHROMIUMPROC>(
-        loadProc("glGetPathParameterfvCHROMIUM"));
-    glGetPathParameterivCHROMIUM = reinterpret_cast<PFNGLGETPATHPARAMETERIVCHROMIUMPROC>(
-        loadProc("glGetPathParameterivCHROMIUM"));
-    glIsPathCHROMIUM = reinterpret_cast<PFNGLISPATHCHROMIUMPROC>(loadProc("glIsPathCHROMIUM"));
-    glPathCommandsCHROMIUM =
-        reinterpret_cast<PFNGLPATHCOMMANDSCHROMIUMPROC>(loadProc("glPathCommandsCHROMIUM"));
-    glPathParameterfCHROMIUM =
-        reinterpret_cast<PFNGLPATHPARAMETERFCHROMIUMPROC>(loadProc("glPathParameterfCHROMIUM"));
-    glPathParameteriCHROMIUM =
-        reinterpret_cast<PFNGLPATHPARAMETERICHROMIUMPROC>(loadProc("glPathParameteriCHROMIUM"));
-    glPathStencilFuncCHROMIUM =
-        reinterpret_cast<PFNGLPATHSTENCILFUNCCHROMIUMPROC>(loadProc("glPathStencilFuncCHROMIUM"));
-    glProgramPathFragmentInputGenCHROMIUM =
-        reinterpret_cast<PFNGLPROGRAMPATHFRAGMENTINPUTGENCHROMIUMPROC>(
-            loadProc("glProgramPathFragmentInputGenCHROMIUM"));
-    glStencilFillPathCHROMIUM =
-        reinterpret_cast<PFNGLSTENCILFILLPATHCHROMIUMPROC>(loadProc("glStencilFillPathCHROMIUM"));
-    glStencilFillPathInstancedCHROMIUM =
-        reinterpret_cast<PFNGLSTENCILFILLPATHINSTANCEDCHROMIUMPROC>(
-            loadProc("glStencilFillPathInstancedCHROMIUM"));
-    glStencilStrokePathCHROMIUM = reinterpret_cast<PFNGLSTENCILSTROKEPATHCHROMIUMPROC>(
-        loadProc("glStencilStrokePathCHROMIUM"));
-    glStencilStrokePathInstancedCHROMIUM =
-        reinterpret_cast<PFNGLSTENCILSTROKEPATHINSTANCEDCHROMIUMPROC>(
-            loadProc("glStencilStrokePathInstancedCHROMIUM"));
-    glStencilThenCoverFillPathCHROMIUM =
-        reinterpret_cast<PFNGLSTENCILTHENCOVERFILLPATHCHROMIUMPROC>(
-            loadProc("glStencilThenCoverFillPathCHROMIUM"));
-    glStencilThenCoverFillPathInstancedCHROMIUM =
-        reinterpret_cast<PFNGLSTENCILTHENCOVERFILLPATHINSTANCEDCHROMIUMPROC>(
-            loadProc("glStencilThenCoverFillPathInstancedCHROMIUM"));
-    glStencilThenCoverStrokePathCHROMIUM =
-        reinterpret_cast<PFNGLSTENCILTHENCOVERSTROKEPATHCHROMIUMPROC>(
-            loadProc("glStencilThenCoverStrokePathCHROMIUM"));
-    glStencilThenCoverStrokePathInstancedCHROMIUM =
-        reinterpret_cast<PFNGLSTENCILTHENCOVERSTROKEPATHINSTANCEDCHROMIUMPROC>(
-            loadProc("glStencilThenCoverStrokePathInstancedCHROMIUM"));
     glBindFragDataLocationEXT =
         reinterpret_cast<PFNGLBINDFRAGDATALOCATIONEXTPROC>(loadProc("glBindFragDataLocationEXT"));
     glBindFragDataLocationIndexedEXT = reinterpret_cast<PFNGLBINDFRAGDATALOCATIONINDEXEDEXTPROC>(
@@ -3864,79 +3736,8 @@
     glCoverageModulationCHROMIUMContextANGLE =
         reinterpret_cast<PFNGLCOVERAGEMODULATIONCHROMIUMCONTEXTANGLEPROC>(
             loadProc("glCoverageModulationCHROMIUMContextANGLE"));
-    glMatrixLoadIdentityCHROMIUMContextANGLE =
-        reinterpret_cast<PFNGLMATRIXLOADIDENTITYCHROMIUMCONTEXTANGLEPROC>(
-            loadProc("glMatrixLoadIdentityCHROMIUMContextANGLE"));
-    glMatrixLoadfCHROMIUMContextANGLE = reinterpret_cast<PFNGLMATRIXLOADFCHROMIUMCONTEXTANGLEPROC>(
-        loadProc("glMatrixLoadfCHROMIUMContextANGLE"));
     glLoseContextCHROMIUMContextANGLE = reinterpret_cast<PFNGLLOSECONTEXTCHROMIUMCONTEXTANGLEPROC>(
         loadProc("glLoseContextCHROMIUMContextANGLE"));
-    glBindFragmentInputLocationCHROMIUMContextANGLE =
-        reinterpret_cast<PFNGLBINDFRAGMENTINPUTLOCATIONCHROMIUMCONTEXTANGLEPROC>(
-            loadProc("glBindFragmentInputLocationCHROMIUMContextANGLE"));
-    glCoverFillPathCHROMIUMContextANGLE =
-        reinterpret_cast<PFNGLCOVERFILLPATHCHROMIUMCONTEXTANGLEPROC>(
-            loadProc("glCoverFillPathCHROMIUMContextANGLE"));
-    glCoverFillPathInstancedCHROMIUMContextANGLE =
-        reinterpret_cast<PFNGLCOVERFILLPATHINSTANCEDCHROMIUMCONTEXTANGLEPROC>(
-            loadProc("glCoverFillPathInstancedCHROMIUMContextANGLE"));
-    glCoverStrokePathCHROMIUMContextANGLE =
-        reinterpret_cast<PFNGLCOVERSTROKEPATHCHROMIUMCONTEXTANGLEPROC>(
-            loadProc("glCoverStrokePathCHROMIUMContextANGLE"));
-    glCoverStrokePathInstancedCHROMIUMContextANGLE =
-        reinterpret_cast<PFNGLCOVERSTROKEPATHINSTANCEDCHROMIUMCONTEXTANGLEPROC>(
-            loadProc("glCoverStrokePathInstancedCHROMIUMContextANGLE"));
-    glDeletePathsCHROMIUMContextANGLE = reinterpret_cast<PFNGLDELETEPATHSCHROMIUMCONTEXTANGLEPROC>(
-        loadProc("glDeletePathsCHROMIUMContextANGLE"));
-    glGenPathsCHROMIUMContextANGLE = reinterpret_cast<PFNGLGENPATHSCHROMIUMCONTEXTANGLEPROC>(
-        loadProc("glGenPathsCHROMIUMContextANGLE"));
-    glGetPathParameterfvCHROMIUMContextANGLE =
-        reinterpret_cast<PFNGLGETPATHPARAMETERFVCHROMIUMCONTEXTANGLEPROC>(
-            loadProc("glGetPathParameterfvCHROMIUMContextANGLE"));
-    glGetPathParameterivCHROMIUMContextANGLE =
-        reinterpret_cast<PFNGLGETPATHPARAMETERIVCHROMIUMCONTEXTANGLEPROC>(
-            loadProc("glGetPathParameterivCHROMIUMContextANGLE"));
-    glIsPathCHROMIUMContextANGLE = reinterpret_cast<PFNGLISPATHCHROMIUMCONTEXTANGLEPROC>(
-        loadProc("glIsPathCHROMIUMContextANGLE"));
-    glPathCommandsCHROMIUMContextANGLE =
-        reinterpret_cast<PFNGLPATHCOMMANDSCHROMIUMCONTEXTANGLEPROC>(
-            loadProc("glPathCommandsCHROMIUMContextANGLE"));
-    glPathParameterfCHROMIUMContextANGLE =
-        reinterpret_cast<PFNGLPATHPARAMETERFCHROMIUMCONTEXTANGLEPROC>(
-            loadProc("glPathParameterfCHROMIUMContextANGLE"));
-    glPathParameteriCHROMIUMContextANGLE =
-        reinterpret_cast<PFNGLPATHPARAMETERICHROMIUMCONTEXTANGLEPROC>(
-            loadProc("glPathParameteriCHROMIUMContextANGLE"));
-    glPathStencilFuncCHROMIUMContextANGLE =
-        reinterpret_cast<PFNGLPATHSTENCILFUNCCHROMIUMCONTEXTANGLEPROC>(
-            loadProc("glPathStencilFuncCHROMIUMContextANGLE"));
-    glProgramPathFragmentInputGenCHROMIUMContextANGLE =
-        reinterpret_cast<PFNGLPROGRAMPATHFRAGMENTINPUTGENCHROMIUMCONTEXTANGLEPROC>(
-            loadProc("glProgramPathFragmentInputGenCHROMIUMContextANGLE"));
-    glStencilFillPathCHROMIUMContextANGLE =
-        reinterpret_cast<PFNGLSTENCILFILLPATHCHROMIUMCONTEXTANGLEPROC>(
-            loadProc("glStencilFillPathCHROMIUMContextANGLE"));
-    glStencilFillPathInstancedCHROMIUMContextANGLE =
-        reinterpret_cast<PFNGLSTENCILFILLPATHINSTANCEDCHROMIUMCONTEXTANGLEPROC>(
-            loadProc("glStencilFillPathInstancedCHROMIUMContextANGLE"));
-    glStencilStrokePathCHROMIUMContextANGLE =
-        reinterpret_cast<PFNGLSTENCILSTROKEPATHCHROMIUMCONTEXTANGLEPROC>(
-            loadProc("glStencilStrokePathCHROMIUMContextANGLE"));
-    glStencilStrokePathInstancedCHROMIUMContextANGLE =
-        reinterpret_cast<PFNGLSTENCILSTROKEPATHINSTANCEDCHROMIUMCONTEXTANGLEPROC>(
-            loadProc("glStencilStrokePathInstancedCHROMIUMContextANGLE"));
-    glStencilThenCoverFillPathCHROMIUMContextANGLE =
-        reinterpret_cast<PFNGLSTENCILTHENCOVERFILLPATHCHROMIUMCONTEXTANGLEPROC>(
-            loadProc("glStencilThenCoverFillPathCHROMIUMContextANGLE"));
-    glStencilThenCoverFillPathInstancedCHROMIUMContextANGLE =
-        reinterpret_cast<PFNGLSTENCILTHENCOVERFILLPATHINSTANCEDCHROMIUMCONTEXTANGLEPROC>(
-            loadProc("glStencilThenCoverFillPathInstancedCHROMIUMContextANGLE"));
-    glStencilThenCoverStrokePathCHROMIUMContextANGLE =
-        reinterpret_cast<PFNGLSTENCILTHENCOVERSTROKEPATHCHROMIUMCONTEXTANGLEPROC>(
-            loadProc("glStencilThenCoverStrokePathCHROMIUMContextANGLE"));
-    glStencilThenCoverStrokePathInstancedCHROMIUMContextANGLE =
-        reinterpret_cast<PFNGLSTENCILTHENCOVERSTROKEPATHINSTANCEDCHROMIUMCONTEXTANGLEPROC>(
-            loadProc("glStencilThenCoverStrokePathInstancedCHROMIUMContextANGLE"));
     glBindFragDataLocationEXTContextANGLE =
         reinterpret_cast<PFNGLBINDFRAGDATALOCATIONEXTCONTEXTANGLEPROC>(
             loadProc("glBindFragDataLocationEXTContextANGLE"));
diff --git a/util/gles_loader_autogen.h b/util/gles_loader_autogen.h
index 7f8a539..672a468 100644
--- a/util/gles_loader_autogen.h
+++ b/util/gles_loader_autogen.h
@@ -540,41 +540,7 @@
 ANGLE_UTIL_EXPORT extern PFNGLCOPYSUBTEXTURECHROMIUMPROC glCopySubTextureCHROMIUM;
 ANGLE_UTIL_EXPORT extern PFNGLCOPYTEXTURECHROMIUMPROC glCopyTextureCHROMIUM;
 ANGLE_UTIL_EXPORT extern PFNGLCOVERAGEMODULATIONCHROMIUMPROC glCoverageModulationCHROMIUM;
-ANGLE_UTIL_EXPORT extern PFNGLMATRIXLOADIDENTITYCHROMIUMPROC glMatrixLoadIdentityCHROMIUM;
-ANGLE_UTIL_EXPORT extern PFNGLMATRIXLOADFCHROMIUMPROC glMatrixLoadfCHROMIUM;
 ANGLE_UTIL_EXPORT extern PFNGLLOSECONTEXTCHROMIUMPROC glLoseContextCHROMIUM;
-ANGLE_UTIL_EXPORT extern PFNGLBINDFRAGMENTINPUTLOCATIONCHROMIUMPROC
-    glBindFragmentInputLocationCHROMIUM;
-ANGLE_UTIL_EXPORT extern PFNGLCOVERFILLPATHCHROMIUMPROC glCoverFillPathCHROMIUM;
-ANGLE_UTIL_EXPORT extern PFNGLCOVERFILLPATHINSTANCEDCHROMIUMPROC glCoverFillPathInstancedCHROMIUM;
-ANGLE_UTIL_EXPORT extern PFNGLCOVERSTROKEPATHCHROMIUMPROC glCoverStrokePathCHROMIUM;
-ANGLE_UTIL_EXPORT extern PFNGLCOVERSTROKEPATHINSTANCEDCHROMIUMPROC
-    glCoverStrokePathInstancedCHROMIUM;
-ANGLE_UTIL_EXPORT extern PFNGLDELETEPATHSCHROMIUMPROC glDeletePathsCHROMIUM;
-ANGLE_UTIL_EXPORT extern PFNGLGENPATHSCHROMIUMPROC glGenPathsCHROMIUM;
-ANGLE_UTIL_EXPORT extern PFNGLGETPATHPARAMETERFVCHROMIUMPROC glGetPathParameterfvCHROMIUM;
-ANGLE_UTIL_EXPORT extern PFNGLGETPATHPARAMETERIVCHROMIUMPROC glGetPathParameterivCHROMIUM;
-ANGLE_UTIL_EXPORT extern PFNGLISPATHCHROMIUMPROC glIsPathCHROMIUM;
-ANGLE_UTIL_EXPORT extern PFNGLPATHCOMMANDSCHROMIUMPROC glPathCommandsCHROMIUM;
-ANGLE_UTIL_EXPORT extern PFNGLPATHPARAMETERFCHROMIUMPROC glPathParameterfCHROMIUM;
-ANGLE_UTIL_EXPORT extern PFNGLPATHPARAMETERICHROMIUMPROC glPathParameteriCHROMIUM;
-ANGLE_UTIL_EXPORT extern PFNGLPATHSTENCILFUNCCHROMIUMPROC glPathStencilFuncCHROMIUM;
-ANGLE_UTIL_EXPORT extern PFNGLPROGRAMPATHFRAGMENTINPUTGENCHROMIUMPROC
-    glProgramPathFragmentInputGenCHROMIUM;
-ANGLE_UTIL_EXPORT extern PFNGLSTENCILFILLPATHCHROMIUMPROC glStencilFillPathCHROMIUM;
-ANGLE_UTIL_EXPORT extern PFNGLSTENCILFILLPATHINSTANCEDCHROMIUMPROC
-    glStencilFillPathInstancedCHROMIUM;
-ANGLE_UTIL_EXPORT extern PFNGLSTENCILSTROKEPATHCHROMIUMPROC glStencilStrokePathCHROMIUM;
-ANGLE_UTIL_EXPORT extern PFNGLSTENCILSTROKEPATHINSTANCEDCHROMIUMPROC
-    glStencilStrokePathInstancedCHROMIUM;
-ANGLE_UTIL_EXPORT extern PFNGLSTENCILTHENCOVERFILLPATHCHROMIUMPROC
-    glStencilThenCoverFillPathCHROMIUM;
-ANGLE_UTIL_EXPORT extern PFNGLSTENCILTHENCOVERFILLPATHINSTANCEDCHROMIUMPROC
-    glStencilThenCoverFillPathInstancedCHROMIUM;
-ANGLE_UTIL_EXPORT extern PFNGLSTENCILTHENCOVERSTROKEPATHCHROMIUMPROC
-    glStencilThenCoverStrokePathCHROMIUM;
-ANGLE_UTIL_EXPORT extern PFNGLSTENCILTHENCOVERSTROKEPATHINSTANCEDCHROMIUMPROC
-    glStencilThenCoverStrokePathInstancedCHROMIUM;
 ANGLE_UTIL_EXPORT extern PFNGLBINDFRAGDATALOCATIONEXTPROC glBindFragDataLocationEXT;
 ANGLE_UTIL_EXPORT extern PFNGLBINDFRAGDATALOCATIONINDEXEDEXTPROC glBindFragDataLocationIndexedEXT;
 ANGLE_UTIL_EXPORT extern PFNGLGETFRAGDATAINDEXEXTPROC glGetFragDataIndexEXT;
@@ -1407,53 +1373,7 @@
 ANGLE_UTIL_EXPORT extern PFNGLCOPYTEXTURECHROMIUMCONTEXTANGLEPROC glCopyTextureCHROMIUMContextANGLE;
 ANGLE_UTIL_EXPORT extern PFNGLCOVERAGEMODULATIONCHROMIUMCONTEXTANGLEPROC
     glCoverageModulationCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT extern PFNGLMATRIXLOADIDENTITYCHROMIUMCONTEXTANGLEPROC
-    glMatrixLoadIdentityCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT extern PFNGLMATRIXLOADFCHROMIUMCONTEXTANGLEPROC glMatrixLoadfCHROMIUMContextANGLE;
 ANGLE_UTIL_EXPORT extern PFNGLLOSECONTEXTCHROMIUMCONTEXTANGLEPROC glLoseContextCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT extern PFNGLBINDFRAGMENTINPUTLOCATIONCHROMIUMCONTEXTANGLEPROC
-    glBindFragmentInputLocationCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT extern PFNGLCOVERFILLPATHCHROMIUMCONTEXTANGLEPROC
-    glCoverFillPathCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT extern PFNGLCOVERFILLPATHINSTANCEDCHROMIUMCONTEXTANGLEPROC
-    glCoverFillPathInstancedCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT extern PFNGLCOVERSTROKEPATHCHROMIUMCONTEXTANGLEPROC
-    glCoverStrokePathCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT extern PFNGLCOVERSTROKEPATHINSTANCEDCHROMIUMCONTEXTANGLEPROC
-    glCoverStrokePathInstancedCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT extern PFNGLDELETEPATHSCHROMIUMCONTEXTANGLEPROC glDeletePathsCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT extern PFNGLGENPATHSCHROMIUMCONTEXTANGLEPROC glGenPathsCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT extern PFNGLGETPATHPARAMETERFVCHROMIUMCONTEXTANGLEPROC
-    glGetPathParameterfvCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT extern PFNGLGETPATHPARAMETERIVCHROMIUMCONTEXTANGLEPROC
-    glGetPathParameterivCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT extern PFNGLISPATHCHROMIUMCONTEXTANGLEPROC glIsPathCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT extern PFNGLPATHCOMMANDSCHROMIUMCONTEXTANGLEPROC
-    glPathCommandsCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT extern PFNGLPATHPARAMETERFCHROMIUMCONTEXTANGLEPROC
-    glPathParameterfCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT extern PFNGLPATHPARAMETERICHROMIUMCONTEXTANGLEPROC
-    glPathParameteriCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT extern PFNGLPATHSTENCILFUNCCHROMIUMCONTEXTANGLEPROC
-    glPathStencilFuncCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT extern PFNGLPROGRAMPATHFRAGMENTINPUTGENCHROMIUMCONTEXTANGLEPROC
-    glProgramPathFragmentInputGenCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT extern PFNGLSTENCILFILLPATHCHROMIUMCONTEXTANGLEPROC
-    glStencilFillPathCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT extern PFNGLSTENCILFILLPATHINSTANCEDCHROMIUMCONTEXTANGLEPROC
-    glStencilFillPathInstancedCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT extern PFNGLSTENCILSTROKEPATHCHROMIUMCONTEXTANGLEPROC
-    glStencilStrokePathCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT extern PFNGLSTENCILSTROKEPATHINSTANCEDCHROMIUMCONTEXTANGLEPROC
-    glStencilStrokePathInstancedCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT extern PFNGLSTENCILTHENCOVERFILLPATHCHROMIUMCONTEXTANGLEPROC
-    glStencilThenCoverFillPathCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT extern PFNGLSTENCILTHENCOVERFILLPATHINSTANCEDCHROMIUMCONTEXTANGLEPROC
-    glStencilThenCoverFillPathInstancedCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT extern PFNGLSTENCILTHENCOVERSTROKEPATHCHROMIUMCONTEXTANGLEPROC
-    glStencilThenCoverStrokePathCHROMIUMContextANGLE;
-ANGLE_UTIL_EXPORT extern PFNGLSTENCILTHENCOVERSTROKEPATHINSTANCEDCHROMIUMCONTEXTANGLEPROC
-    glStencilThenCoverStrokePathInstancedCHROMIUMContextANGLE;
 ANGLE_UTIL_EXPORT extern PFNGLBINDFRAGDATALOCATIONEXTCONTEXTANGLEPROC
     glBindFragDataLocationEXTContextANGLE;
 ANGLE_UTIL_EXPORT extern PFNGLBINDFRAGDATALOCATIONINDEXEDEXTCONTEXTANGLEPROC